libftdi Archives

Subject: Callbacks not closing properly

From: Mike Gilorma <mike.gilorma@xxxxxxxxxxxxxx>
To: "libftdi@xxxxxxxxxxxxxxxxxxxxxxx" <libftdi@xxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed, 30 Nov 2016 22:52:01 +0000

I am trying to create a simple test program where in a main while loop I initialize and startup a callback, run for a short while, close the device and repeat.  Although it looks like everything shuts down cleanly, the second time through the loop the callback only reads data for a short burst then everything shuts down again.  I have been trying to debug the ftdi and libusb libraries but have gotten nowhere.


The interesting thing is that if I use ftdi_read_data instead of the callback the while loop works as expected. 


I am using version 1.3 of libftdi.


Thanks in advance.


********************** TEST CODE ***************************

#include <iostream>
#include <csignal>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <getopt.h>
#include <signal.h>
#include <libftdi1/ftdi.h>

static int exitRequested = 0;
bool showDebug = false;
int countDown = 2500;
    
void sighandler(int sig) {
    std::cout << "Caught a signal: " << sig << ", exiting." << std::endl;
    exitRequested = 1;
}

void usage() {
    std::cout << "Usage: test_tx -d device" << std::endl;
}

static int readCallback(uint8_t *buffer, int length, FTDIProgressInfo *progress, void *userdata) {
   if (length) {
        if (showDebug)
        printf("USB Read: %i bytes\n", length);  
   }
   else {
//         std::cout << "nope" << std::endl;
   }
   
//    std::cout << "in readback: " << countDown << std::endl;
   if (countDown-- <= 0) {
       exitRequested = 1;
   }

   if (progress) {
       fprintf(stderr, "%10.02fs total time %9.3f MiB captured %7.1f kB/s curr rate - %7.3f Mbps\n",
               progress->totalTime,
               progress->current.totalBytes / (1024.0 * 1024.0),
               progress->currentRate / 1024.0,
               progress->currentRate * 8 / 1000000
              );
   }
   return exitRequested ? 1 : 0;
}

int main(int argc, char **argv) {

//     struct ftdi_context *ftdi;
//     struct ftdi_version_info version;

    unsigned int device = 3;
    int usbTransferSize = 65536;
    unsigned char latency = 2;
    int err;
    int packetsPerTransfer = 32;
    int numTransfers = 32;
    unsigned char readBuffer[102400];
    int res = -1;
    
    
    for (int i = 1; i < argc; ++i) {
        if (argv[i][0] == '-') {
            switch(argv[i][1]) {
                case 'd':
                    if (argc >= i + 1) {
                        device = atoi(argv[i+1]);
                        ++i;
                    }
                    break;
                default:
                    usage();
                    return -1;
                    break;
            }
        }
    }
    
    signal(SIGINT, sighandler);
    signal(SIGQUIT, sighandler);
    
    while (1) {    
        struct ftdi_context *ftdi;
        struct ftdi_version_info version;
        
        if ((ftdi = ftdi_new()) == 0) {
            printf("error creating data structures\n");
            return EXIT_FAILURE;
        }
        
        version = ftdi_get_library_version();
        printf("Initialized libftdi %s (major: %d, minor: %d, micro: %d, snapshot ver: %s)\n",
                version.version_str, version.major, version.minor, version.micro,
                version.snapshot_str);
        fflush(stdout);
        
        if (ftdi_set_interface(ftdi, INTERFACE_A) < 0) {
            printf("error setting interface\n");
            ftdi_free(ftdi);
            return EXIT_FAILURE;
        }
        
        std::cout << "--------  GOING TO OPEN USB DEVICE: " <<  device << " --------" << std::endl;
        if (ftdi_usb_open_desc_index(ftdi, 0x0403, 0x6014, NULL, NULL, device) < 0) {    
    //     if (ftdi_usb_open_desc_index(ftdi, 0x0403, 0x6001, NULL, NULL, device) < 0) {
            printf("error opening usb device %i\n", device);
            ftdi_free(ftdi);
            return EXIT_FAILURE;
        }
        
        /* A timeout value of 1 results in may skipped blocks */
        if(ftdi_set_latency_timer(ftdi, latency)) {
            fprintf(stderr,"Can't set latency, Error %s\n",ftdi_get_error_string(ftdi));
            ftdi_usb_close(ftdi);
            ftdi_free(ftdi);
            return EXIT_FAILURE;
        }
        
        // set chunk sizes???
        if (ftdi_write_data_set_chunksize(ftdi, usbTransferSize)) {
            printf("couldn't set write chunksize\n");
            ftdi_usb_close(ftdi);
            ftdi_free(ftdi);
            return EXIT_FAILURE;
        }

        if (ftdi_read_data_set_chunksize(ftdi, usbTransferSize)) {
            printf("couldn't set read chunksize\n");
            ftdi_usb_close(ftdi);
            ftdi_free(ftdi);
            return EXIT_FAILURE;
        }
        
        if (ftdi_setflowctrl(ftdi, SIO_RTS_CTS_HS)) {
            printf("couldn't set flow control\n");
            ftdi_usb_close(ftdi);
            ftdi_free(ftdi);
            return EXIT_FAILURE;
        }

        /* We don't know in what state we are, switch to reset*/
        if (ftdi_set_bitmode(ftdi,  0xff, BITMODE_RESET) < 0) {
            fprintf(stderr,"Can't reset mode\n");
            ftdi_usb_close(ftdi);
            ftdi_free(ftdi);
            return EXIT_FAILURE;
        }

        /* Purge anything remaining in the buffers*/
        if (ftdi_usb_purge_buffers(ftdi) < 0) {
            fprintf(stderr,"Can't Purge\n");
            ftdi_usb_close(ftdi);
            ftdi_free(ftdi);
            return EXIT_FAILURE;
        }

        /* Start the transfers only when everything has been set up.
        * Otherwise the transfers start stuttering and the PC not
        * fetching data for several to several ten milliseconds
        * and we skip blocks
        */
        if (ftdi_set_bitmode(ftdi,  0xff, BITMODE_SYNCFF) < 0)
        {
            fprintf(stderr,"Can't set synchronous fifo mode: %s\n", ftdi_get_error_string(ftdi));
            ftdi_usb_close(ftdi);
            ftdi_free(ftdi);
            return EXIT_FAILURE;
        }

        
        // testing callback
        err = ftdi_readstream(ftdi, readCallback, NULL, packetsPerTransfer, numTransfers);
        printf("done with readstream....\n");
        printf("checking ret from readstream: %i\n", err);
        
//         testing regular read...
//         for (countDown = 2500; countDown > 0; countDown--) {
//             printf("checking countDown: %i\n", countDown);
//             res = ftdi_read_data(ftdi, readBuffer, 1024);
//             if (res > 0) {
//     //             printf("just read %i bytes\n", res);
//             }
//             else {
//                 printf("uhh what... %i\n", res);
//             }
//         }
//         std::cout << "Done regular read...." << std::endl;

        // reset bit mode?
        
        if (ftdi_set_bitmode(ftdi,  0xff, BITMODE_RESET) < 0) {
            fprintf(stderr,"Can't set reset bitmode: %s\n", ftdi_get_error_string(ftdi));
            ftdi_usb_close(ftdi);
            ftdi_free(ftdi);
            return EXIT_FAILURE;
        }
        
        err = ftdi_usb_purge_buffers(ftdi);
        printf("checking ret from purge buffers: %i\n", err);
        
        err = ftdi_usb_reset(ftdi);
        printf("checking ret from usb reset: %i\n", err);
//         
        err = ftdi_usb_close(ftdi);
        printf("checking ret from usb close: %i\n", err);
        
        ftdi_deinit(ftdi);
        
        ftdi_free(ftdi);    

        signal(SIGINT, SIG_DFL);
            
        std::cout << "going to try again?" << std::endl;
        sleep(5);
        ftdi = NULL;
        countDown = 2500;
    }
    

    return 0;
}



libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to libftdi+unsubscribe@xxxxxxxxxxxxxxxxxxxxxxx


Current Thread