ftdi_stream: fix timeout setting: tv_usec field of timeval is in microseconds, not ms
[libftdi] / src / ftdi.c
index 1e3b445..573080a 100644 (file)
@@ -1470,9 +1470,15 @@ static void LIBUSB_CALL ftdi_read_data_cb(struct libusb_transfer *transfer)
             }
         }
     }
-    ret = libusb_submit_transfer (transfer);
-    if (ret < 0)
-        tc->completed = 1;
+
+    if (transfer->status == LIBUSB_TRANSFER_CANCELLED)
+        tc->completed = LIBUSB_TRANSFER_CANCELLED;
+    else
+    {
+        ret = libusb_submit_transfer (transfer);
+        if (ret < 0)
+            tc->completed = 1;
+    }
 }
 
 
@@ -1497,9 +1503,15 @@ static void LIBUSB_CALL ftdi_write_data_cb(struct libusb_transfer *transfer)
 
         transfer->length = write_size;
         transfer->buffer = tc->buf + tc->offset;
-        ret = libusb_submit_transfer (transfer);
-        if (ret < 0)
-            tc->completed = 1;
+
+        if (transfer->status == LIBUSB_TRANSFER_CANCELLED)
+            tc->completed = LIBUSB_TRANSFER_CANCELLED;
+        else
+        {
+            ret = libusb_submit_transfer (transfer);
+            if (ret < 0)
+                tc->completed = 1;
+        }
     }
 }
 
@@ -1662,17 +1674,19 @@ struct ftdi_transfer_control *ftdi_read_data_submit(struct ftdi_context *ftdi, u
 int ftdi_transfer_data_done(struct ftdi_transfer_control *tc)
 {
     int ret;
-
+    struct timeval to = { 0, 0 };
     while (!tc->completed)
     {
-        ret = libusb_handle_events(tc->ftdi->usb_ctx);
+        ret = libusb_handle_events_timeout_completed(tc->ftdi->usb_ctx,
+                &to, &tc->completed);
         if (ret < 0)
         {
             if (ret == LIBUSB_ERROR_INTERRUPTED)
                 continue;
             libusb_cancel_transfer(tc->transfer);
             while (!tc->completed)
-                if (libusb_handle_events(tc->ftdi->usb_ctx) < 0)
+                if (libusb_handle_events_timeout_completed(tc->ftdi->usb_ctx,
+                        &to, &tc->completed) < 0)
                     break;
             libusb_free_transfer(tc->transfer);
             free (tc);
@@ -1696,6 +1710,39 @@ int ftdi_transfer_data_done(struct ftdi_transfer_control *tc)
 }
 
 /**
+    Cancel transfer and wait for completion.
+
+    Use libusb 1.0 asynchronous API.
+
+    \param tc pointer to ftdi_transfer_control
+    \param to pointer to timeout value or NULL for infinite
+*/
+
+void ftdi_transfer_data_cancel(struct ftdi_transfer_control *tc,
+                               struct timeval * to)
+{
+    struct timeval tv = { 0, 0 };
+
+    if (!tc->completed && tc->transfer != NULL)
+    {
+        if (to == NULL)
+            to = &tv;
+
+        libusb_cancel_transfer(tc->transfer);
+        while (!tc->completed)
+        {
+            if (libusb_handle_events_timeout_completed(tc->ftdi->usb_ctx, to, &tc->completed) < 0)
+                break;
+        }
+    }
+
+    if (tc->transfer)
+        libusb_free_transfer(tc->transfer);
+
+    free (tc);
+}
+
+/**
     Configure write buffer chunk size.
     Default is 4096.
 
@@ -2563,7 +2610,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
     unsigned char i, j, eeprom_size_mask;
     unsigned short checksum, value;
     unsigned char manufacturer_size = 0, product_size = 0, serial_size = 0;
-    int user_area_size;
+    int user_area_size, free_start, free_end;
     struct ftdi_eeprom *eeprom;
     unsigned char * output;
 
@@ -2598,14 +2645,12 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
     {
         case TYPE_AM:
         case TYPE_BM:
+        case TYPE_R:
             user_area_size = 96;    // base size for strings (total of 48 characters)
             break;
         case TYPE_2232C:
             user_area_size = 90;     // two extra config bytes and 4 bytes PnP stuff
             break;
-        case TYPE_R:
-            user_area_size = 96;
-            break;
         case TYPE_230X:
             user_area_size = 88;     // four extra config bytes + 4 bytes PnP stuff
             break;
@@ -2712,6 +2757,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
     }
     /* Wrap around 0x80 for 128 byte EEPROMS (Internale and 93x46) */
     eeprom_size_mask = eeprom->size -1;
+    free_end = i & eeprom_size_mask;
 
     // Addr 0E: Offset of the manufacturer string + 0x80, calculated later
     // Addr 0F: Length of manufacturer string
@@ -2779,7 +2825,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
         case TYPE_BM:
             output[0x0C] = eeprom->usb_version & 0xff;
             output[0x0D] = (eeprom->usb_version>>8) & 0xff;
-            if (eeprom->use_usb_version == USE_USB_VERSION_BIT)
+            if (eeprom->use_usb_version)
                 output[0x0A] |= USE_USB_VERSION_BIT;
             else
                 output[0x0A] &= ~USE_USB_VERSION_BIT;
@@ -2821,7 +2867,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
                 output[0x0A] |= 0x4;
             else
                 output[0x0A] &= ~0x4;
-            if (eeprom->use_usb_version == USE_USB_VERSION_BIT)
+            if (eeprom->use_usb_version)
                 output[0x0A] |= USE_USB_VERSION_BIT;
             else
                 output[0x0A] &= ~USE_USB_VERSION_BIT;
@@ -2833,6 +2879,8 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
         case TYPE_R:
             if (eeprom->high_current == HIGH_CURRENT_DRIVE_R)
                 output[0x00] |= HIGH_CURRENT_DRIVE_R;
+            if (eeprom->external_oscillator)
+                output[0x00] |= 0x02;
             output[0x01] = 0x40; /* Hard coded Endpoint Size*/
 
             if (eeprom->suspend_pull_downs)
@@ -3072,6 +3120,38 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
             break;
     }
 
+    /* First address without use */
+    free_start = 0;
+    switch (ftdi->type)
+    {
+        case TYPE_230X:
+            free_start += 2;
+        case TYPE_232H:
+            free_start += 6;
+        case TYPE_2232H:
+        case TYPE_4232H:
+            free_start += 2;
+        case TYPE_R:
+            free_start += 2;
+        case TYPE_2232C:
+            free_start++;
+        case TYPE_AM:
+        case TYPE_BM:
+            free_start += 0x14;
+    }
+
+    /* Arbitrary user data */
+    if (eeprom->user_data && eeprom->user_data_size >= 0)
+    {
+        if (eeprom->user_data_addr < free_start)
+            fprintf(stderr,"Warning, user data starts inside the generated data!\n");
+        if (eeprom->user_data_addr + eeprom->user_data_size >= free_end)
+            fprintf(stderr,"Warning, user data overlaps the strings area!\n");
+        if (eeprom->user_data_addr + eeprom->user_data_size > eeprom->size)
+            ftdi_error_return(-1,"eeprom size exceeded");
+        memcpy(output + eeprom->user_data_addr, eeprom->user_data, eeprom->user_data_size);
+    }
+
     // calculate checksum
     checksum = 0xAAAA;
 
@@ -3203,8 +3283,8 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose)
     eeprom->in_is_isochronous  = buf[0x0A]&0x01;
     eeprom->out_is_isochronous = buf[0x0A]&0x02;
     eeprom->suspend_pull_downs = buf[0x0A]&0x04;
-    eeprom->use_serial         = (buf[0x0A] & USE_SERIAL_NUM)?1:0;
-    eeprom->use_usb_version    = buf[0x0A] & USE_USB_VERSION_BIT;
+    eeprom->use_serial         = !!(buf[0x0A] & USE_SERIAL_NUM);
+    eeprom->use_usb_version    = !!(buf[0x0A] & USE_USB_VERSION_BIT);
 
     // Addr 0C: USB version low byte when 0x0A
     // Addr 0D: USB version high byte when 0x0A
@@ -3318,6 +3398,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose)
         /* TYPE_R flags D2XX, not VCP as all others*/
         eeprom->channel_a_driver = ~buf[0x00] & DRIVER_VCP;
         eeprom->high_current     = buf[0x00] & HIGH_CURRENT_DRIVE_R;
+        eeprom->external_oscillator = buf[0x00] & 0x02;
         if ( (buf[0x01]&0x40) != 0x40)
             fprintf(stderr,
                     "TYPE_R EEPROM byte[0x01] Bit 6 unexpected Endpoint size."
@@ -3431,8 +3512,10 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose)
         if (eeprom->serial)
             fprintf(stdout, "Serial:       %s\n",eeprom->serial);
         fprintf(stdout,     "Checksum      : %04x\n", checksum);
-        if (ftdi->type == TYPE_R)
+        if (ftdi->type == TYPE_R) {
             fprintf(stdout,     "Internal EEPROM\n");
+            fprintf(stdout,"Oscillator: %s\n", eeprom->external_oscillator?"External":"Internal");
+        }
         else if (eeprom->chip >= 0x46)
             fprintf(stdout,     "Attached EEPROM: 93x%02x\n", eeprom->chip);
         if (eeprom->suspend_dbus7)
@@ -3465,7 +3548,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose)
                     (eeprom->channel_b_driver)?" VCP":"",
                     (eeprom->high_current_b)?" High Current IO":"");
         if (((ftdi->type == TYPE_BM) || (ftdi->type == TYPE_2232C)) &&
-                eeprom->use_usb_version == USE_USB_VERSION_BIT)
+                eeprom->use_usb_version)
             fprintf(stdout,"Use explicit USB Version %04x\n",eeprom->usb_version);
 
         if ((ftdi->type == TYPE_2232H) || (ftdi->type == TYPE_4232H))
@@ -3684,7 +3767,7 @@ int ftdi_get_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu
             *value = ftdi->eeprom->cbus_function[8];
             break;
         case CBUS_FUNCTION_9:
-            *value = ftdi->eeprom->cbus_function[8];
+            *value = ftdi->eeprom->cbus_function[9];
             break;
         case HIGH_CURRENT:
             *value = ftdi->eeprom->high_current;
@@ -3752,6 +3835,9 @@ int ftdi_get_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu
         case CHIP_SIZE:
             *value = ftdi->eeprom->size;
             break;
+        case EXTERNAL_OSCILLATOR:
+            *value = ftdi->eeprom->external_oscillator;
+            break;
         default:
             ftdi_error_return(-1, "Request for unknown EEPROM value");
     }
@@ -3942,6 +4028,12 @@ int ftdi_set_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu
         case CHIP_SIZE:
             ftdi_error_return(-2, "EEPROM Value can't be changed");
             break;
+        case EXTERNAL_OSCILLATOR:
+            ftdi->eeprom->external_oscillator = value;
+            break;
+        case USER_DATA_ADDR:
+            ftdi->eeprom->user_data_addr = value;
+            break;
 
         default :
             ftdi_error_return(-1, "Request to unknown EEPROM value");
@@ -3984,7 +4076,7 @@ int ftdi_get_eeprom_buf(struct ftdi_context *ftdi, unsigned char * buf, int size
     \param size Size of buffer
 
     \retval 0: All fine
-    \retval -1: struct ftdi_contxt or ftdi_eeprom of buf missing
+    \retval -1: struct ftdi_context or ftdi_eeprom or buf missing
 */
 int ftdi_set_eeprom_buf(struct ftdi_context *ftdi, const unsigned char * buf, int size)
 {
@@ -4000,6 +4092,25 @@ int ftdi_set_eeprom_buf(struct ftdi_context *ftdi, const unsigned char * buf, in
     return 0;
 }
 
+/** Set the EEPROM user data content from the user-supplied prefilled buffer
+
+    \param ftdi pointer to ftdi_context
+    \param buf buffer to read EEPROM user data content
+    \param size Size of buffer
+
+    \retval 0: All fine
+    \retval -1: struct ftdi_context or ftdi_eeprom or buf missing
+*/
+int ftdi_set_eeprom_user_data(struct ftdi_context *ftdi, const char * buf, int size)
+{
+    if (!ftdi || !(ftdi->eeprom) || !buf)
+        ftdi_error_return(-1, "No appropriate structure");
+
+    ftdi->eeprom->user_data_size = size;
+    ftdi->eeprom->user_data = buf;
+    return 0;
+}
+
 /**
     Read eeprom location