Align loader to 32-bit boundary
[fw/stlink] / src / stlink-usb.c
index ab555785c27ac4b1cf68afacfae9fabe3e6073b3..98654129eccdca57b5a20ebaca2b5d525f48d873 100644 (file)
 
 #include "stlink-common.h"
 #include "stlink-usb.h"
-#include "uglylogging.h"
 
 enum SCSI_Generic_Direction {SG_DXFER_TO_DEV=0, SG_DXFER_FROM_DEV=0x80};
 
 void _stlink_usb_close(stlink_t* sl) {
+    if (!sl)
+        return;
+
     struct stlink_libusb * const handle = sl->backend_data;
     // maybe we couldn't even get the usb device?
     if (handle != NULL) {
@@ -711,17 +713,19 @@ stlink_backend_t _stlink_usb_backend = {
     _stlink_usb_target_voltage
 };
 
-
-stlink_t* stlink_open_usb(const int verbose, int reset, char *p_usb_iserial) {
+stlink_t *stlink_open_usb(enum ugly_loglevel verbose, bool reset, char serial[16])
+{
     stlink_t* sl = NULL;
     struct stlink_libusb* slu = NULL;
-    int error = -1;
+    int ret = -1;
     int config;
 
     sl = calloc(1, sizeof (stlink_t));
     slu = calloc(1, sizeof (struct stlink_libusb));
-    if (sl == NULL) goto on_malloc_error;
-    if (slu == NULL) goto on_malloc_error;
+    if (sl == NULL)
+        goto on_malloc_error;
+    if (slu == NULL)
+        goto on_malloc_error;
 
     ugly_init(verbose);
     sl->backend = &_stlink_usb_backend;
@@ -739,6 +743,10 @@ stlink_t* stlink_open_usb(const int verbose, int reset, char *p_usb_iserial) {
     int devBus =0;
     int devAddr=0;
 
+    /* @TODO: Reading a environment variable in a usb open function is not very nice, this
+      should be refactored and moved into the CLI tools, and instead of giving USB_BUS:USB_ADDR a real stlink
+      serial string should be passed to this function. Probably people are using this but this is very odd because
+      as programmer can change to multiple busses and it is better to detect them based on serial.  */
     char *device = getenv("STLINK_DEVICE");
     if (device) {
         char *c = strchr(device,':');
@@ -751,26 +759,39 @@ stlink_t* stlink_open_usb(const int verbose, int reset, char *p_usb_iserial) {
         devAddr=atoi(c);
         ILOG("bus %03d dev %03d\n",devBus, devAddr);
     }
-    while (cnt--){
+
+    while (cnt--) {
         libusb_get_device_descriptor( list[cnt], &desc );
-        if (desc.idVendor!=USB_ST_VID) continue;
-        if (devBus && devAddr)
-            if ((libusb_get_bus_number(list[cnt])!=devBus) || (libusb_get_device_address(list[cnt])!=devAddr)) continue;
-        if ( (desc.idProduct == USB_STLINK_32L_PID) || (desc.idProduct == USB_STLINK_NUCLEO_PID) ){
-            if ((p_usb_iserial != NULL)){
-                struct libusb_device_handle* handle;
-                libusb_open(list[cnt], &handle);
-                libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, (unsigned char *)sl->serial, sizeof(sl->serial));
-                libusb_close(handle);
-                if (memcmp(p_usb_iserial,&sl->serial, sizeof(sl->serial) - 1) == 0){
-                    break;
-                }else{
-                    continue;
-                }
-            }else{
-                break;
+        if (desc.idVendor != USB_ST_VID)
+            continue;
+
+        if (devBus && devAddr) {
+            if ((libusb_get_bus_number(list[cnt]) != devBus)
+                || (libusb_get_device_address(list[cnt]) != devAddr)) {
+                continue;
             }
         }
+
+        if ((desc.idProduct == USB_STLINK_32L_PID) || (desc.idProduct == USB_STLINK_NUCLEO_PID)) {
+            struct libusb_device_handle *handle;
+
+            libusb_open(list[cnt], &handle);
+            sl->serial_size = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber,
+                                                                 (unsigned char *)sl->serial, sizeof(sl->serial));
+            libusb_close(handle);
+
+            if ((serial == NULL) || (*serial == 0))
+                 break;
+
+            if (sl->serial_size < 0)
+                continue;
+
+            if (memcmp(serial, &sl->serial, sl->serial_size) == 0)
+                 break;
+
+            continue;
+        }
+
         if (desc.idProduct == USB_STLINK_PID) {
             slu->protocoll = 1;
             break;
@@ -781,23 +802,20 @@ stlink_t* stlink_open_usb(const int verbose, int reset, char *p_usb_iserial) {
         WLOG ("Couldn't find %s ST-Link/V2 devices\n",(devBus && devAddr)?"matched":"any");
         goto on_error;
     } else {
-        int error = libusb_open(list[cnt], &slu->usb_handle);
-        if( error !=0 ) {
-            WLOG("Error %d (%s) opening ST-Link/V2 device %03d:%03d\n", 
-        error, strerror (errno), libusb_get_bus_number(list[cnt]), libusb_get_device_address(list[cnt]));
+        ret = libusb_open(list[cnt], &slu->usb_handle);
+        if (ret != 0) {
+            WLOG("Error %d (%s) opening ST-Link/V2 device %03d:%03d\n",
+                 ret, strerror (errno), libusb_get_bus_number(list[cnt]), libusb_get_device_address(list[cnt]));
             goto on_error;
         }
     }
 
     libusb_free_device_list(list, 1);
 
-
     if (libusb_kernel_driver_active(slu->usb_handle, 0) == 1) {
-        int r;
-
-        r = libusb_detach_kernel_driver(slu->usb_handle, 0);
-        if (r<0) {
-            WLOG("libusb_detach_kernel_driver(() error %s\n", strerror(-r));
+        ret = libusb_detach_kernel_driver(slu->usb_handle, 0);
+        if (ret < 0) {
+            WLOG("libusb_detach_kernel_driver(() error %s\n", strerror(-ret));
             goto on_libusb_error;
         }
     }
@@ -818,7 +836,7 @@ stlink_t* stlink_open_usb(const int verbose, int reset, char *p_usb_iserial) {
     }
 
     if (libusb_claim_interface(slu->usb_handle, 0)) {
-        WLOG("libusb_claim_interface() failed\n");
+        WLOG("Stlink usb device found, but unable to claim (probably already in use?)\n");
         goto on_libusb_error;
     }
 
@@ -834,8 +852,6 @@ stlink_t* stlink_open_usb(const int verbose, int reset, char *p_usb_iserial) {
     // TODO - never used at the moment, always CMD_SIZE
     slu->cmd_len = (slu->protocoll == 1)? STLINK_SG_SIZE: STLINK_CMD_SIZE;
 
-    /* success */
-
     if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) {
         ILOG("-- exit_dfu_mode\n");
         stlink_exit_dfu_mode(sl);
@@ -849,24 +865,28 @@ stlink_t* stlink_open_usb(const int verbose, int reset, char *p_usb_iserial) {
         stlink_reset(sl);
         usleep(10000);
     }
+
     stlink_version(sl);
-    error = stlink_load_device_params(sl);
+    ret = stlink_load_device_params(sl);
 
 on_libusb_error:
-    if (error == -1) {
+    if (ret == -1) {
         stlink_close(sl);
         return NULL;
     }
 
-    /* success */
     return sl;
 
 on_error:
-    ifslu->libusb_ctx)
+    if (slu->libusb_ctx)
         libusb_exit(slu->libusb_ctx);
+
 on_malloc_error:
-    if (sl != NULL) free(sl);
-    if (slu != NULL) free(slu);
+    if (sl != NULL)
+        free(sl);
+    if (slu != NULL)
+        free(slu);
+
     return NULL;
 }
 
@@ -874,6 +894,7 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) {
     stlink_t **_sldevs;
     libusb_device *dev;
     int i = 0;
+    int ret = 0;
     size_t slcnt = 0;
     size_t slcur = 0;
 
@@ -882,7 +903,7 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) {
         struct libusb_device_descriptor desc;
         int r = libusb_get_device_descriptor(dev, &desc);
         if (r < 0) {
-            fprintf(stderr, "failed to get device descriptor");
+            WLOG("failed to get libusb device descriptor\n");
             break;
         }
 
@@ -904,9 +925,9 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) {
     i = 0;
     while ((dev = devs[i++]) != NULL) {
         struct libusb_device_descriptor desc;
-        int r = libusb_get_device_descriptor(dev, &desc);
-        if (r < 0) {
-            fprintf(stderr, "failed to get device descriptor");
+        ret = libusb_get_device_descriptor(dev, &desc);
+        if (ret < 0) {
+            WLOG("failed to get libusb device descriptor\n");
             break;
         }
 
@@ -918,8 +939,16 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) {
         char serial[13];
         memset(serial, 0, sizeof(serial));
 
-        libusb_open(dev, &handle);
-        libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, (unsigned char *)&serial, sizeof(serial));
+        ret = libusb_open(dev, &handle);
+        if (ret < 0) {
+            WLOG("failed to get libusb device descriptor\n");
+            break;
+        }
+
+        ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, (unsigned char *)&serial, sizeof(serial));
+        if (ret < 0)
+          *serial = NULL;
+
         libusb_close(handle);
 
         stlink_t *sl = NULL;
@@ -931,6 +960,13 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) {
         slcur++;
     }
 
+    /* Something went wrong */
+    if (ret < 0) {
+        free(_sldevs);
+        *sldevs = NULL;
+        return 0;
+    }
+
     *sldevs = _sldevs;
     return slcnt;
 }