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;
}