Successfully locate and open stlinkv1 by usb
[fw/stlink] / src / stlink-sg.c
index f8865e1e4e6b9e061836db44d59e6541be122303..3b9958d73a02751f2fd20aad1781110c27698334 100644 (file)
 #include <sys/stat.h>
 #include <sys/mman.h>
 
-// sgutils2 (apt-get install libsgutils2-dev)
-#include <scsi/sg_lib.h>
-#include <scsi/sg_pt.h>
-
 #include "stlink-common.h"
 #include "stlink-sg.h"
+#include "uglylogging.h"
 
+#define LOG_TAG __FILE__
+#define DLOG(format, args...)         ugly_log(UDEBUG, LOG_TAG, format, ## args)
+#define ILOG(format, args...)         ugly_log(UINFO, LOG_TAG, format, ## args)
+#define WLOG(format, args...)         ugly_log(UWARN, LOG_TAG, format, ## args)
+#define fatal(format, args...)        ugly_log(UFATAL, LOG_TAG, format, ## args)
 
 // Suspends execution of the calling process for
 // (at least) ms milliseconds.
@@ -107,7 +109,7 @@ static void clear_cdb(struct stlink_libsg *sl) {
 // E.g. make the valgrind happy.
 
 static void clear_buf(stlink_t *sl) {
-    DD(sl, "*** clear_buf ***\n");
+    DLOG("*** clear_buf ***\n");
     for (size_t i = 0; i < sizeof (sl->q_buf); i++)
         sl->q_buf[i] = 0;
 
@@ -117,15 +119,18 @@ static void clear_buf(stlink_t *sl) {
 
 void _stlink_sg_close(stlink_t *sl) {
     if (sl) {
+#if FINISHED_WITH_SG
         struct stlink_libsg *slsg = sl->backend_data;
         scsi_pt_close_device(slsg->sg_fd);
         free(slsg);
+#endif
     }
 }
 
 
 //TODO rewrite/cleanup, save the error in sl
 
+#if FINISHED_WITH_SG
 static void stlink_confirm_inq(stlink_t *stl, struct sg_pt_base *ptvp) {
     struct stlink_libsg *sl = stl->backend_data;
     const int e = sl->do_scsi_pt_err;
@@ -142,7 +147,7 @@ static void stlink_confirm_inq(stlink_t *stl, struct sg_pt_base *ptvp) {
     }
     const int duration = get_scsi_pt_duration_ms(ptvp);
     if ((stl->verbose > 1) && (duration >= 0))
-        DD(stl, "      duration=%d ms\n", duration);
+        DLOG("      duration=%d ms\n", duration);
 
     // XXX stlink fw sends broken residue, so ignore it and use the known q_len
     // "usb-storage quirks=483:3744:r"
@@ -159,7 +164,7 @@ static void stlink_confirm_inq(stlink_t *stl, struct sg_pt_base *ptvp) {
     switch (cat) {
         case SCSI_PT_RESULT_GOOD:
             if (stl->verbose && (resid > 0))
-                DD(stl, "      notice: requested %d bytes but "
+                DLOG("      notice: requested %d bytes but "
                     "got %d bytes, ignore [broken] residue = %d\n",
                     stl->q_len, dsize, resid);
             break;
@@ -168,7 +173,7 @@ static void stlink_confirm_inq(stlink_t *stl, struct sg_pt_base *ptvp) {
                 sg_get_scsi_status_str(
                         get_scsi_pt_status_response(ptvp), sizeof (buf),
                         buf);
-                DD(stl, "  scsi status: %s\n", buf);
+                DLOG("  scsi status: %s\n", buf);
             }
             return;
         case SCSI_PT_RESULT_SENSE:
@@ -176,11 +181,11 @@ static void stlink_confirm_inq(stlink_t *stl, struct sg_pt_base *ptvp) {
             if (stl->verbose) {
                 sg_get_sense_str("", sl->sense_buf, slen, (stl->verbose
                         > 1), sizeof (buf), buf);
-                DD(stl, "%s", buf);
+                DLOG("%s", buf);
             }
             if (stl->verbose && (resid > 0)) {
                 if ((stl->verbose) || (stl->q_len > 0))
-                    DD(stl, "    requested %d bytes but "
+                    DLOG("    requested %d bytes but "
                         "got %d bytes\n", stl->q_len, dsize);
             }
             return;
@@ -193,13 +198,13 @@ static void stlink_confirm_inq(stlink_t *stl, struct sg_pt_base *ptvp) {
                 // The 'host_status' field has the following values:
                 //     [0x07] Internal error detected in the host adapter.
                 // This may not be fatal (and the command may have succeeded).
-                DD(stl, "  transport: %s", buf);
+                DLOG("  transport: %s", buf);
             }
             return;
         case SCSI_PT_RESULT_OS_ERR:
             if (stl->verbose) {
                 get_scsi_pt_os_err_str(ptvp, sizeof (buf), buf);
-                DD(stl, "  os: %s", buf);
+                DLOG("  os: %s", buf);
             }
             return;
         default:
@@ -207,13 +212,15 @@ static void stlink_confirm_inq(stlink_t *stl, struct sg_pt_base *ptvp) {
                     "category (%d)\n", cat);
     }
 }
+#endif
 
 void stlink_q(stlink_t *sl) {
+#if FINISHED_WITH_SG
     struct stlink_libsg* sg = sl->backend_data;
-    DD(sl, "CDB[");
+    DLOG("CDB[");
     for (int i = 0; i < CDB_SL; i++)
-        DD(sl, " 0x%02x", (unsigned int) sg->cdb_cmd_blk[i]);
-    DD(sl, "]\n");
+        DLOG(" 0x%02x", (unsigned int) sg->cdb_cmd_blk[i]);
+    DLOG("]\n");
 
     // Get control command descriptor of scsi structure,
     // (one object per command!!)
@@ -243,6 +250,7 @@ void stlink_q(stlink_t *sl) {
     stlink_confirm_inq(sl, ptvp);
     // TODO recycle: clear_scsi_pt_obj(struct sg_pt_base * objp);
     destruct_scsi_pt_obj(ptvp);
+#endif
 }
 
 // TODO thinking, cleanup
@@ -255,55 +263,25 @@ void stlink_stat(stlink_t *stl, char *txt) {
 
     switch (stl->q_buf[0]) {
         case STLINK_OK:
-            DD(stl, "  %s: ok\n", txt);
+            DLOG("  %s: ok\n", txt);
             return;
         case STLINK_FALSE:
-            DD(stl, "  %s: false\n", txt);
+            DLOG("  %s: false\n", txt);
             return;
         default:
-            DD(stl, "  %s: unknown\n", txt);
+            DLOG("  %s: unknown\n", txt);
     }
 }
 
 
-static void parse_version(stlink_t *stl) {
-  struct stlink_libsg *sl = stl->backend_data;
-
-  sl->st_vid = 0;
-  sl->stlink_pid = 0;
-
-  if (stl->q_len <= 0) {
-    fprintf(stderr, "Error: could not parse the stlink version");
-    return;
-  }
-
-  uint32_t b0 = stl->q_buf[0]; //lsb
-  uint32_t b1 = stl->q_buf[1];
-  uint32_t b2 = stl->q_buf[2];
-  uint32_t b3 = stl->q_buf[3];
-  uint32_t b4 = stl->q_buf[4];
-  uint32_t b5 = stl->q_buf[5]; //msb
-
-  // b0 b1 || b2 b3 | b4 b5
-  // 4b | 6b | 6b || 2B | 2B
-  // stlink_v | jtag_v | swim_v || st_vid | stlink_pid
-
-  sl->stlink_v = (b0 & 0xf0) >> 4;
-  sl->jtag_v = ((b0 & 0x0f) << 2) | ((b1 & 0xc0) >> 6);
-  sl->swim_v = b1 & 0x3f;
-  sl->st_vid = (b3 << 8) | b2;
-  sl->stlink_pid = (b5 << 8) | b4;
-}
-
 void _stlink_sg_version(stlink_t *stl) {
     struct stlink_libsg *sl = stl->backend_data;
-    D(stl, "\n*** stlink_version ***\n");
+    DLOG("\n*** stlink_version ***\n");
     clear_cdb(sl);
     sl->cdb_cmd_blk[0] = STLINK_GET_VERSION;
     stl->q_len = 6;
     sl->q_addr = 0;
     stlink_q(stl);
-    parse_version(stl);
 }
 
 // Get stlink mode:
@@ -336,7 +314,7 @@ void _stlink_sg_enter_swd_mode(stlink_t *sl) {
 
 void _stlink_sg_enter_jtag_mode(stlink_t *sl) {
     struct stlink_libsg *sg = sl->backend_data;
-    D(sl, "\n*** stlink_enter_jtag_mode ***\n");
+    DLOG("\n*** stlink_enter_jtag_mode ***\n");
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_ENTER;
     sg->cdb_cmd_blk[2] = STLINK_DEBUG_ENTER_JTAG;
@@ -348,7 +326,7 @@ void _stlink_sg_enter_jtag_mode(stlink_t *sl) {
 
 void _stlink_sg_exit_dfu_mode(stlink_t *sl) {
     struct stlink_libsg *sg = sl->backend_data;
-    D(sl, "\n*** stlink_exit_dfu_mode ***\n");
+    DLOG("\n*** stlink_exit_dfu_mode ***\n");
     clear_cdb(sg);
     sg->cdb_cmd_blk[0] = STLINK_DFU_COMMAND;
     sg->cdb_cmd_blk[1] = STLINK_DFU_EXIT;
@@ -425,7 +403,7 @@ void _stlink_sg_reset(stlink_t *sl) {
 
 void _stlink_sg_status(stlink_t *sl) {
     struct stlink_libsg *sg = sl->backend_data;
-    D(sl, "\n*** stlink_status ***\n");
+    DLOG("\n*** stlink_status ***\n");
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_GETSTATUS;
     sl->q_len = 2;
@@ -437,7 +415,7 @@ void _stlink_sg_status(stlink_t *sl) {
 
 void _stlink_sg_force_debug(stlink_t *sl) {
     struct stlink_libsg *sg = sl->backend_data;
-    D(sl, "\n*** stlink_force_debug ***\n");
+    DLOG("\n*** stlink_force_debug ***\n");
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_FORCEDEBUG;
     sl->q_len = 2;
@@ -468,7 +446,7 @@ void _stlink_sg_read_all_regs(stlink_t *sl, reg *regp) {
     for (int i = 0; i < 16; i++) {
         sg->reg.r[i] = read_uint32(sl->q_buf, 4 * i);
         if (sl->verbose > 1)
-            DD(sl, "r%2d = 0x%08x\n", i, sg->reg.r[i]);
+            DLOG("r%2d = 0x%08x\n", i, sg->reg.r[i]);
     }
     sg->reg.xpsr = read_uint32(sl->q_buf, 64);
     sg->reg.main_sp = read_uint32(sl->q_buf, 68);
@@ -478,11 +456,11 @@ void _stlink_sg_read_all_regs(stlink_t *sl, reg *regp) {
     if (sl->verbose < 2)
         return;
 
-    DD(sl, "xpsr       = 0x%08x\n", sg->reg.xpsr);
-    DD(sl, "main_sp    = 0x%08x\n", sg->reg.main_sp);
-    DD(sl, "process_sp = 0x%08x\n", sg->reg.process_sp);
-    DD(sl, "rw         = 0x%08x\n", sg->reg.rw);
-    DD(sl, "rw2        = 0x%08x\n", sg->reg.rw2);
+    DLOG("xpsr       = 0x%08x\n", sg->reg.xpsr);
+    DLOG("main_sp    = 0x%08x\n", sg->reg.main_sp);
+    DLOG("process_sp = 0x%08x\n", sg->reg.process_sp);
+    DLOG("rw         = 0x%08x\n", sg->reg.rw);
+    DLOG("rw2        = 0x%08x\n", sg->reg.rw2);
 }
 
 // Read an arm-core register, the index must be in the range 0..20.
@@ -503,7 +481,7 @@ void _stlink_sg_read_reg(stlink_t *sl, int r_idx, reg *regp) {
     stlink_print_data(sl);
 
     uint32_t r = read_uint32(sl->q_buf, 0);
-    DD(sl, "r_idx (%2d) = 0x%08x\n", r_idx, r);
+    DLOG("r_idx (%2d) = 0x%08x\n", r_idx, r);
 
     switch (r_idx) {
         case 16:
@@ -550,7 +528,7 @@ void _stlink_sg_write_reg(stlink_t *sl, uint32_t reg, int idx) {
 
 void stlink_write_dreg(stlink_t *sl, uint32_t reg, uint32_t addr) {
     struct stlink_libsg *sg = sl->backend_data;
-    D(sl, "\n*** stlink_write_dreg ***\n");
+    DLOG("\n*** stlink_write_dreg ***\n");
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEDEBUGREG;
     // 2-5: address of reg of the debug module
@@ -567,7 +545,7 @@ void stlink_write_dreg(stlink_t *sl, uint32_t reg, uint32_t addr) {
 
 void _stlink_sg_run(stlink_t *sl) {
     struct stlink_libsg *sg = sl->backend_data;
-    D(sl, "\n*** stlink_run ***\n");
+    DLOG("\n*** stlink_run ***\n");
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_RUNCORE;
     sl->q_len = 2;
@@ -592,7 +570,7 @@ void _stlink_sg_step(stlink_t *sl) {
 // see Cortex-M3 Technical Reference Manual
 // TODO make delegate!
 void stlink_set_hw_bp(stlink_t *sl, int fp_nr, uint32_t addr, int fp) {
-    D(sl, "\n*** stlink_set_hw_bp ***\n");
+    DLOG("\n*** stlink_set_hw_bp ***\n");
     struct stlink_libsg *sg = sl->backend_data;
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_SETFP;
@@ -613,7 +591,7 @@ void stlink_set_hw_bp(stlink_t *sl, int fp_nr, uint32_t addr, int fp) {
 // TODO make delegate!
 void stlink_clr_hw_bp(stlink_t *sl, int fp_nr) {
     struct stlink_libsg *sg = sl->backend_data;
-    D(sl, "\n*** stlink_clr_hw_bp ***\n");
+    DLOG("\n*** stlink_clr_hw_bp ***\n");
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_CLEARFP;
     sg->cdb_cmd_blk[2] = fp_nr;
@@ -758,28 +736,95 @@ stlink_backend_t _stlink_sg_backend = {
     _stlink_sg_force_debug
 };
 
-stlink_t* stlink_open(const char *dev_name, const int verbose) {
-    fprintf(stderr, "\n*** stlink_open [%s] ***\n", dev_name);
-    int sg_fd = scsi_pt_open_device(dev_name, RDWR, verbose);
-    if (sg_fd < 0) {
-        fprintf(stderr, "error opening device: %s: %s\n", dev_name,
-                safe_strerror(-sg_fd));
+#if using_stm8_stuff_XXXX
+stlink *stlink_open(libusb_context *usb_context)
+{
+    stlink *stl = malloc(sizeof(stlink));
+    stl->handle = libusb_open_device_with_vid_pid(usb_context, USB_VID_ST, USB_PID_STLINK);
+    if (stl->handle == NULL) {
+        free(stl);
         return NULL;
     }
 
+    libusb_device *dev = libusb_get_device(stl->handle);
+    struct libusb_config_descriptor *conf_desc;
+    int ret = libusb_get_config_descriptor(dev, 0, &conf_desc);
+    if (ret != LIBUSB_SUCCESS) {
+        libusb_close(stl->handle);
+        free(stl);
+        return NULL;
+    }
+    for (int i = 0; i < conf_desc->bNumInterfaces; i++) {
+        printf("interface %d\n", i);
+        for (int j = 0; j < conf_desc->interface[i].num_altsetting; j++) {
+            for (int k = 0; k < conf_desc->interface[i].altsetting[j].bNumEndpoints; k++) {
+                const struct libusb_endpoint_descriptor *endpoint;
+                endpoint = &conf_desc->interface[i].altsetting[j].endpoint[k];
+                if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) {
+                    stl->endpoint_in = endpoint->bEndpointAddress;
+                    printf("Found IN endpoint\n");
+                } else {
+                    stl->endpoint_out = endpoint->bEndpointAddress;
+                    printf("Found OUT endpoint\n");
+                }
+            }
+        }
+    }
+    libusb_free_config_descriptor(conf_desc);
+
+    ret = libusb_kernel_driver_active(stl->handle, 0);
+    if (ret == 1) {
+        printf("kernel driver active\n");
+    } else if (ret == 0) {
+        //printf("kernel driver not active\n");
+    } else {
+        fprintf(stderr, "libusb_kernel_driver_active = %d\n", ret);
+    }
+    ret = libusb_claim_interface(stl->handle, 0);
+    if (ret != LIBUSB_SUCCESS) {
+        fprintf(stderr, "claiming interface failed: %d\n", ret);
+        libusb_close(stl->handle);
+        free(stl);
+        return NULL;
+    }
+
+    return stl;
+}
+#endif
+
+
+static stlink_t* stlink_open(const char *dev_name, const int verbose) {
+    fprintf(stderr, "\n*** stlink_open [%s] ***\n", dev_name);
+    
     stlink_t *sl = malloc(sizeof (stlink_t));
     struct stlink_libsg *slsg = malloc(sizeof (struct stlink_libsg));
     if (sl == NULL || slsg == NULL) {
-        fprintf(stderr, "Couldn't malloc stlink and stlink_sg structures out of memory!\n");
+        WLOG("Couldn't malloc stlink and stlink_sg structures out of memory!\n");
         return NULL;
     }
+    
+    if (libusb_init(&(slsg->libusb_ctx))) {
+        WLOG("failed to init libusb context, wrong version of libraries?\n");
+        free(sl);
+        free(slsg);
+        return NULL;
+    }
+    
+    slsg->handle = libusb_open_device_with_vid_pid(slsg->libusb_ctx, USB_ST_VID, USB_STLINK_PID);
+    if (slsg->handle == NULL) {
+        WLOG("Failed to find an stlink v1 by VID:PID\n");
+        free(sl);
+        free(slsg);
+        return NULL;
+    }
+    
+    DLOG("Successfully opened stlinkv1 by libusb :)\n");
+    
     sl->verbose = verbose;
     sl->backend_data = slsg;
     sl->backend = &_stlink_sg_backend;
 
-    slsg->sg_fd = sg_fd;
     sl->core_stat = STLINK_CORE_STAT_UNKNOWN;
-    slsg->core_id = 0;
     slsg->q_addr = 0;
     clear_buf(sl);
 
@@ -801,8 +846,8 @@ stlink_t* stlink_open(const char *dev_name, const int verbose) {
 
 
 
-stlink_t* stlink_quirk_open(const char *dev_name, const int verbose) {
-
+stlink_t* stlink_v1_open(const char *dev_name, const int verbose) {
+    ugly_init(verbose);
     stlink_t *sl = stlink_open(dev_name, verbose);
     if (sl == NULL) {
         fputs("Error: could not open stlink device\n", stderr);
@@ -812,17 +857,17 @@ stlink_t* stlink_quirk_open(const char *dev_name, const int verbose) {
     stlink_version(sl);
     struct stlink_libsg *sg = sl->backend_data;
 
-    if ((sg->st_vid != USB_ST_VID) || (sg->stlink_pid != USB_STLINK_PID)) {
+    if ((sl->version.st_vid != USB_ST_VID) || (sl->version.stlink_pid != USB_STLINK_PID)) {
         fprintf(stderr, "Error: the device %s is not a stlink\n",
                 dev_name);
         fprintf(stderr, "       VID: got %04x expect %04x \n",
-                sg->st_vid, USB_ST_VID);
+                sl->version.st_vid, USB_ST_VID);
         fprintf(stderr, "       PID: got %04x expect %04x \n",
-                sg->stlink_pid, USB_STLINK_PID);
+                sl->version.stlink_pid, USB_STLINK_PID);
         return NULL;
     }
 
-    D(sl, "\n*** stlink_force_open ***\n");
+    DLOG("\n*** stlink_force_open ***\n");
     switch (stlink_current_mode(sl)) {
         case STLINK_DEV_MASS_MODE:
             return sl;
@@ -830,10 +875,10 @@ stlink_t* stlink_quirk_open(const char *dev_name, const int verbose) {
             // TODO go to mass?
             return sl;
     }
-    DD(sl, "\n*** switch the stlink to mass mode ***\n");
+    DLOG("\n*** switch the stlink to mass mode ***\n");
     _stlink_sg_exit_dfu_mode(sl);
     // exit the dfu mode -> the device is gone
-    DD(sl, "\n*** reopen the stlink device ***\n");
+    DLOG("\n*** reopen the stlink device ***\n");
     delay(1000);
     stlink_close(sl);
     delay(5000);