More interesting data. The read that fails (requesting 102 bytes), always
comes up 2 bytes short.
The sequence is this: Two bytes are send to the camera to initial a request.
The camera returns 104 bytes. The host first reads 2 bytes in a read call,
then the remaining 102 bytes in a second read call.
When running the test case, I put a break point in ftdi_read_data,
"num_of_chunks = ret / 64; See below. The break point is hit on the first
read call of two bytes requested.
When stopped at the break point, the value of "ret" is 104! Just like there
are no modem status bytes in the data stream! I would expect 2 + 104 or 106
bytes at that point in the code-two bytes of modem status, then the 104
bytes of camera data.
Has the ft2232H ever been tested with libftdi in async FIFO mode? Does the
ft2232H not send modem status bytes in that configuration?
Any other ideas?
Thanks,
Dave Challis
int ftdi_read_data(struct ftdi_context *ftdi, unsigned char *buf, int size)
{
int offset = 0, ret = 1, i, num_of_chunks, chunk_remains;
// everything we want is still in the readbuffer?
if (size <= ftdi->readbuffer_remaining) {
memcpy (buf, ftdi->readbuffer+ftdi->readbuffer_offset, size);
// Fix offsets
ftdi->readbuffer_remaining -= size;
ftdi->readbuffer_offset += size;
/* printf("Returning bytes from buffer: %d - remaining: %d\n", size,
ftdi->readbuffer_remaining); */
return size;
}
// something still in the readbuffer, but not enough to satisfy 'size'?
if (ftdi->readbuffer_remaining != 0) {
memcpy (buf, ftdi->readbuffer+ftdi->readbuffer_offset,
ftdi->readbuffer_remaining);
// Fix offset
offset += ftdi->readbuffer_remaining;
}
// do the actual USB read
while (offset < size && ret > 0) {
ftdi->readbuffer_remaining = 0;
ftdi->readbuffer_offset = 0;
/* returns how much received */
ret = usb_bulk_read (ftdi->usb_dev, ftdi->out_ep, ftdi->readbuffer,
ftdi->readbuffer_chunksize, ftdi->usb_read_timeout);
if (ret < 0)
ftdi_error_return(ret, "usb bulk read failed");
if (ret > 2) {
// skip FTDI status bytes.
// Maybe stored in the future to enable modem use
num_of_chunks = ret / 64;
chunk_remains = ret % 64;
//printf("ret = %X, num_of_chunks = %X, chunk_remains = %X,
readbuffer_offset = %X\n", ret, num_of_chunks, chunk_remains,
ftdi->readbuffer_offset);
ftdi->readbuffer_offset += 2;
ret -= 2;
if (ret > 62) {
for (i = 1; i < num_of_chunks; i++)
memmove (ftdi->readbuffer+ftdi->readbuffer_offset+62*i,
ftdi->readbuffer+ftdi->readbuffer_offset+64*i,
62);
if (chunk_remains > 2) {
memmove (ftdi->readbuffer+ftdi->readbuffer_offset+62*i,
ftdi->readbuffer+ftdi->readbuffer_offset+64*i,
chunk_remains-2);
ret -= 2*num_of_chunks;
} else
ret -= 2*(num_of_chunks-1)+chunk_remains;
}
} else if (ret <= 2) {
// no more data to read?
return offset;
}
if (ret > 0) {
// data still fits in buf?
if (offset+ret <= size) {
memcpy (buf+offset,
ftdi->readbuffer+ftdi->readbuffer_offset, ret);
//printf("buf[0] = %X, buf[1] = %X\n", buf[0], buf[1]);
offset += ret;
/* Did we read exactly the right amount of bytes? */
if (offset == size)
//printf("read_data exact rem %d offset %d\n",
//ftdi->readbuffer_remaining, offset);
return offset;
} else {
// only copy part of the data or size <=
readbuffer_chunksize
int part_size = size-offset;
memcpy (buf+offset,
ftdi->readbuffer+ftdi->readbuffer_offset, part_size);
ftdi->readbuffer_offset += part_size;
ftdi->readbuffer_remaining = ret-part_size;
offset += part_size;
/* printf("Returning part: %d - size: %d - offset: %d - ret:
%d - remaining: %d\n",
part_size, size, offset, ret, ftdi->readbuffer_remaining);
*/
return offset;
}
}
}
// never reached
return -127;
}
--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to [email protected]