libftdi Archives

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

From: "David Challis" <dchallis@xxxxxxxxxxxxx>
To: <libftdi@xxxxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 23 Mar 2009 08:55:47 -0700
> Good work! Maybe the attached patch will help you.
> 
> Cheers,
> Thomas

Thomas,

The line in the patch:

        else if (dev->descriptor.bcdDevice == 0x800)
                ftdi->type = TYPE_2232H;

for the FT2232H should be:

        else if (dev->descriptor.bcdDevice == 0x700)
                ftdi->type = TYPE_2232H;


With your patch applied, my proposed new ftdi_read_data() is:

/**
    Reads data in chunks (see ftdi_read_data_set_chunksize()) from the chip.

    Automatically strips the two modem status bytes transfered during every
read.

    \param ftdi pointer to ftdi_context
    \param buf Buffer to store data in
    \param size Size of the buffer

    \retval <0: error code from usb_bulk_read()
    \retval  0: no data was available
    \retval >0: number of bytes read

    \remark This function is not useful in bitbang mode.
            Use ftdi_read_pins() to get the current state of the pins.
*/
int ftdi_read_data(struct ftdi_context *ftdi, unsigned char *buf, int size)
{
    int offset = 0, ret = 1, i, num_of_chunks, chunk_remains;
        int packet_size;

        switch (ftdi->type)
        {
                case TYPE_2232H:
                        packet_size = 512;
                        break;
                default:
                        packet_size = 64;
        }

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

        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\n");

        if (ret > 2) {
            // skip FTDI status bytes.
            // Maybe stored in the future to enable modem use
            num_of_chunks = ret / packet_size;
            chunk_remains = ret % packet_size;
            ftdi->readbuffer_offset += 2;
            ret -= 2;

            if (ret > packet_size - 2) {
                for (i = 1; i < num_of_chunks; i++)
                    memmove
(ftdi->readbuffer+ftdi->readbuffer_offset+(packet_size - 2)*i,
 
ftdi->readbuffer+ftdi->readbuffer_offset+packet_size*i, packet_size - 2);
                if (chunk_remains > 2) {
                    memmove
(ftdi->readbuffer+ftdi->readbuffer_offset+(packet_size - 2)*i,
 
ftdi->readbuffer+ftdi->readbuffer_offset+packet_size*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);
                offset += ret;

                /* Did we read exactly the right amount of bytes? */
                if (offset == size) {
                    //printf("read_data exact readdata->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;

                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