libftdi Archives

Subject: RE: Release 0.15 and the ft2232 data loss.

From: "David Challis" <dchallis@xxxxxxxxxxxxx>
To: <libftdi@xxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 20 Mar 2009 18:17:56 -0700

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 libftdi+unsubscribe@xxxxxxxxxxxxxxxxxxxxxxx


Current Thread