示例#1
0
static void
ReadStreamCallback(struct libusb_transfer *transfer)
{
   FTDIStreamState *state = transfer->user_data;
   int err;

   if (state->result == 0) {
      if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {

         int i;
         uint8_t *ptr = transfer->buffer;
         int length = transfer->actual_length;
         int numPackets = (length + FTDI_PACKET_SIZE - 1) >> FTDI_LOG_PACKET_SIZE;

         for (i = 0; i < numPackets; i++) {
            int payloadLen;
            int packetLen = length;

            if (packetLen > FTDI_PACKET_SIZE)
               packetLen = FTDI_PACKET_SIZE;

            payloadLen = packetLen - FTDI_HEADER_SIZE;
            state->progress.current.totalBytes += payloadLen;

            state->result = state->callback(ptr + FTDI_HEADER_SIZE, payloadLen,
                                            NULL, state->userdata);
            if (state->result)
               break;

            ptr += packetLen;
            length -= packetLen;
         }

      } else {
示例#2
0
/* Handle callbacks
 * 
 * With Exit request, free memory and release the transfer
 *
 * state->result is only set when some error happens 
 */
static void
ftdi_readstream_cb(struct libusb_transfer *transfer)
{
   FTDIStreamState *state = transfer->user_data;
   int packet_size = state->packetsize;

   state->activity++;
   if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
   {
       int i;
       uint8_t *ptr = transfer->buffer;
       int length = transfer->actual_length;
       int numPackets = (length + packet_size - 1) / packet_size;
       int res = 0;

       for (i = 0; i < numPackets; i++)
       {
           int payloadLen;
           int packetLen = length;
           
           if (packetLen > packet_size)
               packetLen = packet_size;
           
           payloadLen = packetLen - 2;
           state->progress.current.totalBytes += payloadLen;
           
           res = state->callback(ptr + 2, payloadLen,
                                 NULL, state->userdata);

           ptr += packetLen;
           length -= packetLen;
       }
       if (res)
       {
           free(transfer->buffer);
           libusb_free_transfer(transfer);           
       }
       else
       {
           transfer->status = -1;
           state->result = libusb_submit_transfer(transfer);
       }
   }
   else
   {
       fprintf(stderr, "unknown status %d\n",transfer->status); 
       state->result = LIBUSB_ERROR_IO;
   }
}
示例#3
0
int
ftdi_readstream(struct ftdi_context *ftdi,
                      FTDIStreamCallback *callback, void *userdata,
                      int packetsPerTransfer, int numTransfers)
{
    struct libusb_transfer **transfers;
    FTDIStreamState state = { callback, userdata, ftdi->max_packet_size, 1 };
    int bufferSize = packetsPerTransfer * ftdi->max_packet_size;
    int xferIndex;
    int err = 0;

    /* Only FT2232H and FT232H know about the synchronous FIFO Mode*/
    if ((ftdi->type != TYPE_2232H) && (ftdi->type != TYPE_232H))
    {
        fprintf(stderr,"Device doesn't support synchronous FIFO mode\n");
        return 1;
    }
    
    /* 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");
        return 1;
    }
    
    /* Purge anything remaining in the buffers*/
    if (ftdi_usb_purge_buffers(ftdi) < 0)
    {
        fprintf(stderr,"Can't Purge\n");
        return 1;
    }

    /*
     * Set up all transfers
     */
    
    transfers = calloc(numTransfers, sizeof *transfers);
    if (!transfers) {
        err = LIBUSB_ERROR_NO_MEM;
        goto cleanup;
    }
    
    for (xferIndex = 0; xferIndex < numTransfers; xferIndex++)
    {
        struct libusb_transfer *transfer;
        
        transfer = libusb_alloc_transfer(0);
        transfers[xferIndex] = transfer;
        if (!transfer) {
            err = LIBUSB_ERROR_NO_MEM;
            goto cleanup;
        }
        
        libusb_fill_bulk_transfer(transfer, ftdi->usb_dev, ftdi->out_ep,
                                  malloc(bufferSize), bufferSize, 
				  ftdi_readstream_cb,
                                  &state, 0);
        
        if (!transfer->buffer) {
            err = LIBUSB_ERROR_NO_MEM;
            goto cleanup;
        }
        
        transfer->status = -1;
        err = libusb_submit_transfer(transfer);
        if (err)
            goto cleanup;
    }

    /* 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));
        goto cleanup;
    }

    /*
     * Run the transfers, and periodically assess progress.
     */
    
    gettimeofday(&state.progress.first.time, NULL);
    
    do
    {
        FTDIProgressInfo  *progress = &state.progress;
        const double progressInterval = 1.0;
        struct timeval timeout = { 0, ftdi->usb_read_timeout };
        struct timeval now;
        
        int err = libusb_handle_events_timeout(ftdi->usb_ctx, &timeout);
        if (err ==  LIBUSB_ERROR_INTERRUPTED)
            /* restart interrupted events */
            err = libusb_handle_events_timeout(ftdi->usb_ctx, &timeout);  
        if (!state.result)
        {
            state.result = err;
        }
        if (state.activity == 0)
            state.result = 1;
        else
            state.activity = 0;
        
        // If enough time has elapsed, update the progress
        gettimeofday(&now, NULL);
        if (TimevalDiff(&now, &progress->current.time) >= progressInterval)
        {
            progress->current.time = now;
            progress->totalTime = TimevalDiff(&progress->current.time,
                                              &progress->first.time);
            
            if (progress->prev.totalBytes)
            {
                // We have enough information to calculate rates
                
                double currentTime;
                
                currentTime = TimevalDiff(&progress->current.time,
                                          &progress->prev.time);
                
                progress->totalRate = 
		    progress->current.totalBytes /progress->totalTime;
                progress->currentRate = 
		    (progress->current.totalBytes -
		     progress->prev.totalBytes) / currentTime;
            }
            
            state.callback(NULL, 0, progress, state.userdata);
            progress->prev = progress->current;
            
        }
    } while (!state.result);
    
    /*
     * Cancel any outstanding transfers, and free memory.
     */
    
 cleanup:
    fprintf(stderr, "cleanup\n");
    if (transfers)
       free(transfers);
    if (err)
        return err;
    else
        return state.result;
}