Merge branch 'master' into local/stm32l_flash
authorFabien Le Mentec <texane@gmail.com>
Fri, 21 Oct 2011 09:23:50 +0000 (04:23 -0500)
committerFabien Le Mentec <texane@gmail.com>
Fri, 21 Oct 2011 09:23:50 +0000 (04:23 -0500)
16 files changed:
AUTHORS
Makefile
doc/tutorial/tutorial.pdf
doc/tutorial/tutorial.tex
example/blink/Makefile
example/blink/main.c
example/blink_flash/Makefile
flash/Makefile
flash/main.c
gdbserver/Makefile
gdbserver/gdb-server.c
src/stlink-sg.c
src/stlink-usb.c
src/stlink-usb.h
src/test_sg.c
src/test_usb.c

diff --git a/AUTHORS b/AUTHORS
index ca1df75a08ed463e1101ed747f50b3156b586eb2..0abaac62097ea0a5840eededb94a6a8ffb2acb4b 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -7,3 +7,5 @@ karlp@tweak.net.au
 h0rr0rrdrag@gmail.com
 mstempin@com1.fr
 bon@elektron.ikp.physik.tu-darmstadt.de
+nelsonjm@macpod.neta
+ned@bike-nomad.com
\ No newline at end of file
index 4c3b44b8321bf12f1972b0a94895e0e980be4775..c5bb1d9a1f082db033aea7d5da793578475537c2 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,21 +1,36 @@
-
+# make ... for both libusb and libsg
+#
+# make CONFIG_USE_LIBSG=0 ...
+# for just libusb
+#
 VPATH=src
 
-SOURCES_LIB=stlink-common.c stlink-usb.c stlink-sg.c
+SOURCES_LIB=stlink-common.c stlink-usb.c
 OBJS_LIB=$(SOURCES_LIB:.c=.o)
+TEST_PROGRAMS=test_usb
+LDFLAGS=-lusb-1.0 -L. -lstlink
+
+ifeq ($(CONFIG_USE_LIBSG),)
+CONFIG_USE_LIBSG=1
+endif
+
+ifneq ($(CONFIG_USE_LIBSG),0)
+SOURCES_LIB+=stlink-sg.c
+CFLAGS+=-DCONFIG_USE_LIBSG=1
+LDFLAGS+=-lsgutils2
+TEST_PROGRAMS+=test_sg
+endif
 
 CFLAGS+=-g
-CFLAGS+=-DCONFIG_USE_LIBUSB
-CFLAGS+=-DCONFIG_USE_LIBSG
-CFLAGS+=-DDEBUG
+CFLAGS+=-DCONFIG_USE_LIBUSB=1
+CFLAGS+=-DDEBUG=1
 CFLAGS+=-std=gnu99
 CFLAGS+=-Wall -Wextra
 
-LDFLAGS=-lstlink -lusb-1.0 -lsgutils2 -L.
 
 LIBRARY=libstlink.a
 
-all:  $(LIBRARY) test_usb test_sg 
+all:  $(LIBRARY) flash gdbserver $(TEST_PROGRAMS)
 
 $(LIBRARY): $(OBJS_LIB)
        @echo "objs are $(OBJS_LIB)"
@@ -42,5 +57,15 @@ clean:
        rm -rf $(LIBRARY)
        rm -rf test_usb*
        rm -rf test_sg*
+
+distclean: clean
+       $(MAKE) -C flash clean
+       $(MAKE) -C gdbserver clean
        
-.PHONY: clean all
+flash:
+       $(MAKE) -C flash CONFIG_USE_LIBSG="$(CONFIG_USE_LIBSG)" 
+
+gdbserver:
+       $(MAKE) -C gdbserver
+
+.PHONY: clean all flash gdbserver
index 2b4618ff5b52877f2147399ca583b6204f8e9959..a237871313bd7c76ac47a532b0c53cae24ced02d 100644 (file)
Binary files a/doc/tutorial/tutorial.pdf and b/doc/tutorial/tutorial.pdf differ
index e0e8d2d73a1fe8a4caba5ca80b0dc140ffc87cde..c0d90b3ba3f2b6713b92b723676ce4b6b889d955 100644 (file)
@@ -56,12 +56,15 @@ point of view, those versions differ only in the transport layer used to communi
 (v1 uses SCSI passthru commands, while v2 uses raw USB).
 
 \paragraph{}
-Before continuing, the following dependencies are required:
+Before continuing, the following dependencies must be met:
 \begin{itemize}
 \item libusb-1.0
-\item libsg2
+\item libsgutils2 (optionnal)
 \end{itemize}
 
+\paragraph{}
+STLINK should run on any system meeting the above constraints.
+
 \paragraph{}
 The STLINK software source code is retrieved using:\\
 \begin{small}
@@ -71,15 +74,19 @@ git clone https://github.com/texane/stlink stlink.git
 \end{small}
 
 \paragraph{}
-The GDB server is called st-util and is built using:\\
+Everything can be built from the top directory:\\
 \begin{small}
 \begin{lstlisting}[frame=tb]
-$> cd stlink.git;
-$> make ;
-$> cd gdbserver ;
+$> cd stlink.git ;
 $> make ;
 \end{lstlisting}
 \end{small}
+It includes:
+\begin{itemize}
+\item a communication library (stlink.git/libstlink.a),
+\item a GDB server (stlink.git/gdbserver/st-util),
+\item a flash manipulation tool (stlink.git/flash/flash).
+\end{itemize}
 
 
 \newpage
@@ -88,8 +95,9 @@ $> make ;
 A simple LED blinking example is provided in the example directory. It is built using:\\
 \begin{small}
 \begin{lstlisting}[frame=tb]
+# update the make option accordingly to your architecture
 cd stlink.git/example/blink ;
-PATH=$TOOLCHAIN_PATH/bin:$PATH make ;
+PATH=$TOOLCHAIN_PATH/bin:$PATH make CONFIG_STM32L_DISCOVERY=1;
 \end{lstlisting}
 \end{small}
 
@@ -102,7 +110,8 @@ are using, you must run one of the 2 commands:\\
 $> sudo ./st-util /dev/sg2
 
 # STM32L discovery kit
-$> sudo ./st-util
+# 2 dummy command line arguments needed, will be fixed soon
+$> sudo ./st-util fu bar
 \end{lstlisting}
 \end{small}
 
@@ -151,8 +160,8 @@ Flash memory reading and writing is done by a separate tool. A binary running in
 be linked against address 0x8000000. The flash tool is then used as shown below:\\
 \begin{small}
 \begin{lstlisting}[frame=tb]
-# build the flash tool
-$> cd stlink.git/flash ; make ;
+# change to the flash tool directory
+$> cd stlink.git/flash ;
 
 # stlinkv1 command to read 4096 from flash into out.bin
 $> ./flash read /dev/sg2 out.bin 0x8000000 4096
@@ -212,6 +221,17 @@ $> make
 \end{lstlisting}
 \end{small}
 
+\subsection{STM32VL support}
+\paragraph{}
+It seems support for STM32VL is quite broken. If it does not work, try build STLINK using libsg:
+\begin{small}
+\begin{lstlisting}[frame=tb]
+$> cd stlink.git
+$> make CONFIG_USE_LIBSG=1
+\end{lstlisting}
+\end{small}
+
+
 \newpage
 \section{References}
 \begin{itemize}
index 1b310b1765e8984d1c92b8ef4a7239789934695d..e5f704525a8da8eccb63c0d1857764deb96949ea 100644 (file)
@@ -4,8 +4,15 @@ BIN_IMAGE=blink.bin
 CC=arm-none-eabi-gcc
 OBJCOPY=arm-none-eabi-objcopy
 
-CFLAGS=-O2 -mlittle-endian -mthumb
-CFLAGS+=-mcpu=cortex-m3 -ffreestanding -nostdlib -nostdinc
+CFLAGS=-g -O2 -mlittle-endian -mthumb
+ifeq ($(CONFIG_STM32L_DISCOVERY), 1)
+       CFLAGS+=-mcpu=cortex-m3 -DCONFIG_STM32L_DISCOVERY
+else ifeq ($(CONFIG_STM32VL_DISCOVERY), 1)
+       CFLAGS+=-mcpu=cortex-m3 -DCONFIG_STM32VL_DISCOVERY=1
+else ifeq ($(CONFIG_STM32F4_DISCOVERY), 1)
+       CFLAGS+=-mcpu=cortex-m4 -DCONFIG_STM32F4_DISCOVERY=1    
+endif
+       CFLAGS+=-ffreestanding -nostdlib -nostdinc
 
 # to run from SRAM
 CFLAGS+=-Wl,-Ttext,0x20000000 -Wl,-e,0x20000000
index 929e3b9c1279762da8bbdd5e703c2ac1a2f0d825..0889b81619a4850b2514db5e3d27ec46af051594 100644 (file)
@@ -5,10 +5,6 @@ typedef unsigned int uint32_t;
 
 /* hardware configuration */
 
-#define CONFIG_STM32L_DISCOVERY 1
-#define CONFIG_STM32VL_DISCOVERY 0
-
-
 #if CONFIG_STM32VL_DISCOVERY
 
 # define GPIOC 0x40011000 /* port C */
@@ -58,6 +54,36 @@ static inline void switch_leds_off(void)
   *(volatile uint32_t*)GPIOB_ODR = 0;
 }
 
+#elif CONFIG_STM32F4_DISCOVERY
+
+#define GPIOD 0x40020C00 /* port D */
+# define GPIOD_MODER (GPIOD + 0x00) /* port mode register */
+# define GPIOD_ODR (GPIOD + 0x14) /* port output data register */
+
+# define LED_GREEN (1 << 12) /* port B, pin 12 */
+# define LED_ORANGE (1 << 13) /* port B, pin 13 */
+# define LED_RED (1 << 14) /* port B, pin 14 */
+# define LED_BLUE (1 << 15) /* port B, pin 15 */
+
+static inline void setup_leds(void)
+{
+  *(volatile uint32_t*)GPIOD_MODER |= (1 << (12 * 2)) | (1 << (13 * 2)) |
+       (1 << (13 * 2)) | (1 << (14 * 2)) | (1 << (15 * 2));
+}
+
+
+static inline void switch_leds_on(void)
+{
+  *(volatile uint32_t*)GPIOD_ODR = LED_GREEN | LED_ORANGE | LED_RED | LED_BLUE;
+}
+
+static inline void switch_leds_off(void)
+{
+  *(volatile uint32_t*)GPIOD_ODR = 0;
+}
+
+#else
+#error "Architecture must be defined!"
 #endif /* otherwise, error */
 
 
index d0583902969d5baeeb75bf45055cd94a921970ca..77764715d9f42de214acc8895786329624ff49cb 100644 (file)
@@ -5,7 +5,18 @@ CC=arm-none-eabi-gcc
 OBJCOPY=arm-none-eabi-objcopy
 
 CFLAGS=-O2 -mlittle-endian -mthumb
-CFLAGS+=-mcpu=cortex-m3 -ffreestanding -nostdlib -nostdinc
+
+CFLAGS=-g -O2 -mlittle-endian -mthumb
+ifeq ($(CONFIG_STM32L_DISCOVERY), 1)
+       CFLAGS+=-mcpu=cortex-m3 -DCONFIG_STM32L_DISCOVERY
+else ifeq ($(CONFIG_STM32VL_DISCOVERY), 1)
+       CFLAGS+=-mcpu=cortex-m3 -DCONFIG_STM32VL_DISCOVERY=1
+else ifeq ($(CONFIG_STM32F4_DISCOVERY), 1)
+       CFLAGS+=-mcpu=cortex-m4 -DCONFIG_STM32F4_DISCOVERY=1    
+else
+$(error "must specify CONFIG_ for board!")
+endif
+       CFLAGS+=-ffreestanding -nostdlib -nostdinc
 
 # to run from FLASH
 CFLAGS+=-Wl,-T,stm32_flash.ld
index aee2f3726d6ed83c58b45de5595ef02efac8947a..8a30b4113a6bcebf88951810e7d83129e45f4f7d 100644 (file)
@@ -1,14 +1,27 @@
+# make ... for both libusb and libsg
+#
+# make CONFIG_USE_LIBSG=0 ...
+# for just libusb
+#
 CC=gcc
 
 CFLAGS+=-g
-CFLAGS+=-DCONFIG_USE_LIBUSB
-CFLAGS+=-DCONFIG_USE_LIBSG
+CFLAGS+=-DCONFIG_USE_LIBUSB=1
 CFLAGS+=-DDEBUG
 CFLAGS+=-std=gnu99
 CFLAGS+=-Wall -Wextra
 CFLAGS+=-I../src
 
-LDFLAGS=-L.. -lstlink -lusb-1.0 -lsgutils2
+LDFLAGS=-lusb-1.0 -L.. -lstlink 
+
+ifeq ($(CONFIG_USE_LIBSG),)
+CONFIG_USE_LIBSG=1
+endif
+
+ifneq ($(CONFIG_USE_LIBSG),0)
+CFLAGS+=-DCONFIG_USE_LIBSG=1
+LDFLAGS+=-lsgutils2
+endif
 
 SRCS=main.c
 OBJS=$(SRCS:.c=.o)
index 3b9416dff1b885f2d8714dacb7f60bf01b407bbd..e474174377b1ac154d17cfaf96e46823f087e551 100644 (file)
@@ -17,6 +17,11 @@ struct opts
   size_t size;
 };
 
+static void usage(void)
+{
+    puts("stlinkv1 command line: ./flash {read|write} /dev/sgX path addr <size>");
+    puts("stlinkv2 command line: ./flash {read|write} path addr <size>");
+}
 
 static int get_opts(struct opts* o, int ac, char** av)
 {
@@ -75,18 +80,24 @@ int main(int ac, char** av)
   if (get_opts(&o, ac - 1, av + 1) == -1)
   {
     printf("invalid command line\n");
+    usage();
     goto on_error;
   }
 
   if (o.devname != NULL) /* stlinkv1 */
   {
+#if CONFIG_USE_LIBSG
     static const int scsi_verbose = 2;
     sl = stlink_quirk_open(o.devname, scsi_verbose);
     if (sl == NULL) goto on_error;
+#else
+    printf("not compiled for use with STLink/V1");
+    goto on_error;
+#endif
   }
   else /* stlinkv2 */
   {
-    sl = stlink_open_usb(NULL, 10);
+    sl = stlink_open_usb(10);
     if (sl == NULL) goto on_error;
   }
 
index e9d2774f35b7f6826f0fd4e4c5be35113820ee8f..a8d1b90aa3b35dda5ba88637e1b65ddb51a9c798 100644 (file)
@@ -1,13 +1,24 @@
+# make ... for both libusb and libsg
+#
+# make CONFIG_USE_LIBSG=0 ...
+# for just libusb
+#
 
 PRG := st-util
 OBJS = gdb-remote.o gdb-server.o
 
 CFLAGS+=-g -Wall -Werror -std=gnu99 -I../src
-CFLAGS+=-DCONFIG_USE_LIBUSB
-CFLAGS+=-DCONFIG_USE_LIBSG
-LIBS := -lstlink -lusb-1.0 -lsgutils2
-LDFLAGS+=$(LIBS) -L..
+CFLAGS+=-DCONFIG_USE_LIBUSB=1
+LDFLAGS=-lusb-1.0 -L.. -lstlink 
 
+ifeq ($(CONFIG_USE_LIBSG),)
+CONFIG_USE_LIBSG=1
+endif
+
+ifneq ($(CONFIG_USE_LIBSG),0)
+CFLAGS+=-DCONFIG_USE_LIBSG=1
+LDFLAGS+=-lsgutils2
+endif
 
 all: $(PRG)
 
index 72f433ffe907ead83a0ee7ee0c7ec29af4defadb..67f0be0e61d4edd42992b72865b393c0ff3c186a 100644 (file)
@@ -14,6 +14,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <signal.h>
 
 #include <stlink-common.h>
 
 #define FLASH_PAGE_MASK (~((1 << 10) - 1))
 #define FLASH_SIZE (FLASH_PAGE * 128)
 
+volatile int do_exit = 0;
+void ctrl_c(int sig)
+{
+  do_exit = 1;
+}
+
 static const char hex[] = "0123456789abcdef";
 
 static const char* current_memory_map = NULL;
@@ -32,6 +39,11 @@ static const char* current_memory_map = NULL;
  * Chip IDs are explained in the appropriate programming manual for the
  * DBGMCU_IDCODE register (0xE0042000)
  */
+
+#define CORE_M3_R1 0x1BA00477
+#define CORE_M3_R2 0x4BA00477
+#define CORE_M4_R0 0x2BA01477
+
 struct chip_params {
        uint32_t chip_id;
        char* description;
@@ -43,11 +55,11 @@ struct chip_params {
        { 0x410, "F1 Medium-density device", 0x1ffff7e0,
          0x20000,  0x400, 0x5000,  0x1ffff000, 0x800  }, // table 2, pm0063
        { 0x411, "F2 device", 0, /* No flash size register found in the docs*/
-         0x100000,   0x20000, 0x20000, 0x1ff00000, 0x7800  }, // table 1, pm0059
+         0x100000,   0x20000, 0x20000, 0x1fff0000, 0x7800  }, // table 1, pm0059
        { 0x412, "F1 Low-density device", 0x1ffff7e0,
          0x8000,   0x400, 0x2800,  0x1ffff000, 0x800  }, // table 1, pm0063
        { 0x413, "F4 device", 0x1FFF7A10,
-         0x100000,   0x20000, 0x20000,  0x1ff00000, 0x7800  }, // table 1, pm0081
+         0x100000,   0x20000, 0x30000,  0x1fff0000, 0x7800  }, // table 1, pm0081
        { 0x414, "F1 High-density device", 0x1ffff7e0,
          0x80000,  0x800, 0x10000, 0x1ffff000, 0x800  },  // table 3 pm0063 
           // This ignores the EEPROM! (and uses the page erase size,
@@ -79,15 +91,10 @@ int main(int argc, char** argv) {
 
        switch(argc) {
 
-               default: {
-                       fprintf(stderr, HelpStr, NULL);
-                       return 1;
-               }
-
                case 3 : {
                        //sl = stlink_quirk_open(argv[2], 0);
-                        // FIXME - hardcoded to usb....
-                        sl = stlink_open_usb(argv[2], 10);
+                       // FIXME - hardcoded to usb....
+                       sl = stlink_open_usb(10);
                        if(sl == NULL) return 1;
                        break;
                }
@@ -99,6 +106,7 @@ int main(int argc, char** argv) {
                        }
                }
 
+#if CONFIG_USE_LIBSG
                case 1 : { // Search ST-LINK (from /dev/sg0 to /dev/sg99)
                        const int DevNumMax = 99;
                        int ExistDevCount = 0;
@@ -136,18 +144,32 @@ int main(int argc, char** argv) {
                        }
                        break;
                }
+#endif
+
+               default: {
+                       fprintf(stderr, HelpStr, NULL);
+                       return 1;
+               }
        }
 
-        if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) {
-            stlink_exit_dfu_mode(sl);
-        }
+       if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) {
+               stlink_exit_dfu_mode(sl);
+       }
 
        if(stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) {
          stlink_enter_swd_mode(sl);
        }
 
        uint32_t chip_id = stlink_chip_id(sl);
-       printf("Chip ID is %08x.\n", chip_id);
+       uint32_t core_id = stlink_core_id(sl);
+
+       /* Fix chip_id for F4 */
+       if (((chip_id & 0xFFF) == 0x411) && (core_id == CORE_M4_R0)) {
+         printf("Fixing wrong chip_id for STM32F4 Rev A errata\n");
+         chip_id = 0x413;
+       }
+
+       printf("Chip ID is %08x, Core ID is  %08x.\n", chip_id, core_id);
 
        const struct chip_params* params = NULL;
 
@@ -182,6 +204,9 @@ int main(int argc, char** argv) {
 
        while(serve(sl, port) == 0);
 
+       /* Switch back to mass storage mode before closing. */
+       stlink_run(sl);
+       stlink_exit_debug_mode(sl);
        stlink_close(sl);
 
        return 0;
@@ -578,7 +603,9 @@ int serve(stlink_t *sl, int port) {
 
        printf("Listening at *:%d...\n", port);
 
+       (void) signal (SIGINT, ctrl_c);
        int client = accept(sock, NULL, NULL);
+       signal (SIGINT, SIG_DFL);
        if(client < 0) {
                perror("accept");
                return 1;
index f8865e1e4e6b9e061836db44d59e6541be122303..b8220de133bf2c26a5f6b92338c87b288bb8e09c 100644 (file)
 #include <sys/stat.h>
 #include <sys/mman.h>
 
+#include "stlink-common.h"
+
+#if CONFIG_USE_LIBSG
 // sgutils2 (apt-get install libsgutils2-dev)
 #include <scsi/sg_lib.h>
 #include <scsi/sg_pt.h>
-
-#include "stlink-common.h"
 #include "stlink-sg.h"
+#endif
 
 
 // Suspends execution of the calling process for
index 9c28e9f3bceff283d7f8bff54bcf16e2c3c5d2b5..ff9ef71de7a4e6afc0b632342b473cc97826ff0b 100644 (file)
@@ -1,4 +1,3 @@
-#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -9,6 +8,8 @@
 #include "stlink-common.h"
 #include "stlink-usb.h"
 
+enum SCSI_Generic_Direction {SG_DXFER_TO_DEV=0, SG_DXFER_FROM_DEV=0x80};
+
 void _stlink_usb_close(stlink_t* sl) {
     struct stlink_libusb * const handle = sl->backend_data;
     // maybe we couldn't even get the usb device?
@@ -19,8 +20,9 @@ void _stlink_usb_close(stlink_t* sl) {
         if (handle->rep_trans != NULL)
             libusb_free_transfer(handle->rep_trans);
 
-        if (handle->usb_handle != NULL)
+        if (handle->usb_handle != NULL) {
             libusb_close(handle->usb_handle);
+        }
 
         libusb_exit(handle->libusb_ctx);
         free(handle);
@@ -88,10 +90,11 @@ int submit_wait(struct stlink_libusb *slu, struct libusb_transfer * trans) {
     return 0;
 }
 
-ssize_t send_recv(struct stlink_libusb* handle,
+ssize_t send_recv(struct stlink_libusb* handle, int terminate,
         unsigned char* txbuf, size_t txsize,
         unsigned char* rxbuf, size_t rxsize) {
     /* note: txbuf and rxbuf can point to the same area */
+    int res = 0;
 
     libusb_fill_bulk_transfer(handle->req_trans, handle->usb_handle,
             handle->ep_req,
@@ -100,118 +103,146 @@ ssize_t send_recv(struct stlink_libusb* handle,
             0
             );
 
-    printf("submit_wait(req)\n");
-
     if (submit_wait(handle, handle->req_trans)) return -1;
 
     /* send_only */
-    if (rxsize == 0) return 0;
-
-    /* read the response */
-
-    libusb_fill_bulk_transfer(handle->rep_trans, handle->usb_handle,
-            handle->ep_rep, rxbuf, rxsize, NULL, NULL, 0);
-
-    printf("submit_wait(rep)\n");
-
-    if (submit_wait(handle, handle->rep_trans)) return -1;
+    if (rxsize != 0) {
+
+        /* read the response */
+        
+        libusb_fill_bulk_transfer(handle->rep_trans, handle->usb_handle,
+                                  handle->ep_rep, rxbuf, rxsize, NULL, NULL, 0);
+        
+        if (submit_wait(handle, handle->rep_trans)) return -1;
+        res = handle->rep_trans->actual_length;
+    }
+    if ((handle->protocoll == 1) && terminate) {
+        /* Read the SG reply */
+        unsigned char sg_buf[13];
+        libusb_fill_bulk_transfer
+            (handle->rep_trans, handle->usb_handle,
+             handle->ep_rep, sg_buf, 13, NULL, NULL, 0);
+        res = submit_wait(handle, handle->rep_trans);
+       /* The STLink doesn't seem to evaluate the sequence number */
+        handle->sg_transfer_idx++;
+        if (res ) return -1;
+    }
 
     return handle->rep_trans->actual_length;
 }
 
 static inline int send_only
-(struct stlink_libusb* handle, unsigned char* txbuf, size_t txsize) {
-    return send_recv(handle, txbuf, txsize, NULL, 0);
+(struct stlink_libusb* handle, int terminate,
+ unsigned char* txbuf, size_t txsize) {
+    return send_recv(handle, terminate, txbuf, txsize, NULL, 0);
 }
 
 
-// KARL - fixme, common code! (or, one per backend)
-// candidate for common code...
-
-
-static int is_stlink_device(libusb_device * dev) {
+/* Search for a STLINK device, either any or teh one with the given PID
+ * Return the protocoll version
+ */
+static int is_stlink_device(libusb_device * dev, uint16_t pid) {
     struct libusb_device_descriptor desc;
+    int version;
 
     if (libusb_get_device_descriptor(dev, &desc))
         return 0;
 
-    printf("device: 0x%04x, 0x%04x\n", desc.idVendor, desc.idProduct);
-
     if (desc.idVendor != USB_ST_VID)
         return 0;
 
-    if (desc.idProduct != USB_STLINK_32L_PID)
+    if ((desc.idProduct != USB_STLINK_32L_PID) && 
+        (desc.idProduct != USB_STLINK_PID ))
+        return 0;
+
+    if(pid && (pid != desc.idProduct))
         return 0;
+    if (desc.idProduct == USB_STLINK_PID )
+        version = 1;
+    else
+        version = 2;
+
+    return version;
+}
 
-    return 1;
+static int fill_command
+(stlink_t * sl, enum SCSI_Generic_Direction dir, uint32_t len) {
+    struct stlink_libusb * const slu = sl->backend_data;
+    unsigned char* const cmd = sl->c_buf;
+    int i = 0;
+    memset(cmd, 0, sizeof (sl->c_buf));
+    if(slu->protocoll == 1) {
+        cmd[i++] = 'U';
+        cmd[i++] = 'S';
+        cmd[i++] = 'B';
+        cmd[i++] = 'C';
+        write_uint32(&cmd[i], slu->sg_transfer_idx);
+        write_uint32(&cmd[i + 4], len);
+        i += 8;
+        cmd[i++] = (dir == SG_DXFER_FROM_DEV)?0x80:0;
+        cmd[i++] = 0; /* Logical unit */
+        cmd[i++] = 0xa; /* Command length */
+    }
+    return i;
 }
 
 void _stlink_usb_version(stlink_t *sl) {
     struct stlink_libusb * const slu = sl->backend_data;
-    unsigned char* const buf = sl->q_buf;
+    unsigned char* const data = sl->q_buf;
+    unsigned char* const cmd  = sl->c_buf;
     ssize_t size;
+    uint32_t rep_len = 6;
+    int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
 
-    memset(buf, 0, sizeof (sl->q_buf));
-    buf[0] = STLINK_GET_VERSION;
-    buf[1] = 0x80;
+    cmd[i++] = STLINK_GET_VERSION;
 
-    size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
+    size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
         return;
     }
-
-#if 1 /* DEBUG */
-    {
-        ssize_t i;
-        for (i = 0; i < size; ++i) printf("%02x", buf[i]);
-        printf("\n");
-    }
-#endif /* DEBUG */
 }
 
 void _stlink_usb_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
     struct stlink_libusb * const slu = sl->backend_data;
-    unsigned char* const buf = sl->q_buf;
-    unsigned char *cmd_buf = sl->c_buf;
+    unsigned char* const data = sl->q_buf;
+    unsigned char* const cmd  = sl->c_buf;
 
-    memset(cmd_buf, 0, STLINK_CMD_SIZE);
-    cmd_buf[0] = STLINK_DEBUG_COMMAND;
-    cmd_buf[1] =  STLINK_DEBUG_WRITEMEM_32BIT;
-    write_uint32(cmd_buf + 2, addr);
-    write_uint16(cmd_buf + 6, len);
-    send_only(slu, cmd_buf, STLINK_CMD_SIZE);
-
-    assert((len & 3) == 0); 
-    stlink_print_data(sl);
-    send_only(slu, buf, len);
+    int i = fill_command(sl, SG_DXFER_TO_DEV, len);
+    cmd[i++] = STLINK_DEBUG_COMMAND;
+    cmd[i++] = STLINK_DEBUG_WRITEMEM_32BIT;
+    write_uint32(&cmd[i], addr);
+    write_uint16(&cmd[i + 4], len);
+    send_only(slu, 0, cmd, slu->cmd_len);
 
+    send_only(slu, 1, data, len);
 }
 
 void _stlink_usb_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) {
     struct stlink_libusb * const slu = sl->backend_data;
-    unsigned char* const buf = sl->q_buf;
-    unsigned char *cmd_buf = sl->c_buf;
-
-    memset(cmd_buf, 0, STLINK_CMD_SIZE);
-    cmd_buf[0] = STLINK_DEBUG_COMMAND;
-    cmd_buf[1] =  STLINK_DEBUG_WRITEMEM_8BIT;
-    write_uint32(cmd_buf + 2, addr);
-    write_uint16(cmd_buf + 6, len);
-    send_only(slu, cmd_buf, STLINK_CMD_SIZE);
-
-    stlink_print_data(sl);
-    send_only(slu, buf, len);
+    unsigned char* const data = sl->q_buf;
+    unsigned char* const cmd  = sl->c_buf;
+
+    int i = fill_command(sl, SG_DXFER_TO_DEV, 0);
+    cmd[i++] = STLINK_DEBUG_COMMAND;
+    cmd[i++] = STLINK_DEBUG_WRITEMEM_8BIT;
+    write_uint32(&cmd[i], addr);
+    write_uint16(&cmd[i + 4], len);
+    send_only(slu, 0, cmd, slu->cmd_len);
+    send_only(slu, 1, data, len);
 }
 
 
 int _stlink_usb_current_mode(stlink_t * sl) {
     struct stlink_libusb * const slu = sl->backend_data;
-    unsigned char* const buf = sl->q_buf;
+    unsigned char* const cmd  = sl->c_buf;
+    unsigned char* const data = sl->q_buf;
     ssize_t size;
-    memset(buf, 0, sizeof (sl->q_buf));
-    buf[0] = STLINK_GET_CURRENT_MODE;
-    size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
+    int rep_len = 2;
+    int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+    
+    cmd[i++] = STLINK_GET_CURRENT_MODE;
+    size = send_recv(slu, 1, cmd,  slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
         return -1;
@@ -221,76 +252,71 @@ int _stlink_usb_current_mode(stlink_t * sl) {
 
 void _stlink_usb_core_id(stlink_t * sl) {
     struct stlink_libusb * const slu = sl->backend_data;
-    unsigned char* const buf = sl->q_buf;
+    unsigned char* const cmd  = sl->c_buf;
+    unsigned char* const data = sl->q_buf;
     ssize_t size;
+    int rep_len = 4;
+    int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
 
-    memset(buf, 0, sizeof (sl->q_buf));
-    buf[0] = STLINK_DEBUG_COMMAND;
-    buf[1] = STLINK_DEBUG_READCOREID;
+    cmd[i++] = STLINK_DEBUG_COMMAND;
+    cmd[i++] = STLINK_DEBUG_READCOREID;
 
-    size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
+    size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
         return;
     }
 
-    sl->core_id = read_uint32(buf, 0);
+    sl->core_id = read_uint32(data, 0);
 }
 
 void _stlink_usb_status(stlink_t * sl) {
     struct stlink_libusb * const slu = sl->backend_data;
-    unsigned char* const buf = sl->q_buf;
+    unsigned char* const data = sl->q_buf;
+    unsigned char* const cmd  = sl->c_buf;
     ssize_t size;
+    int rep_len = 2;
+    int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
 
-    memset(buf, 0, sizeof (sl->q_buf));
-
-    buf[0] = STLINK_DEBUG_COMMAND;
-    buf[1] = STLINK_DEBUG_GETSTATUS;
+    cmd[i++] = STLINK_DEBUG_COMMAND;
+    cmd[i++] = STLINK_DEBUG_GETSTATUS;
 
-    size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
+    size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
         return;
     }
-
-    /* todo: stlink_core_stat */
-
-    // FIXME - decode into sl->core_stat
-#if 1 /* DEBUG */
-    printf("status == 0x%x\n", buf[0]);
-#endif /* DEBUG */
-
 }
 
 void _stlink_usb_force_debug(stlink_t *sl) {
     struct stlink_libusb *slu = sl->backend_data;
-    unsigned char* const buf = sl->q_buf;
+    unsigned char* const data = sl->q_buf;
+    unsigned char* const cmd  = sl->c_buf;
     ssize_t size;
+    int rep_len = 2;
+    int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
 
-    memset(buf, 0, sizeof (sl->q_buf));
-
-    buf[0] = STLINK_DEBUG_COMMAND;
-    buf[1] = STLINK_DEBUG_FORCEDEBUG;
-    size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
+    cmd[i++] = STLINK_DEBUG_COMMAND;
+    cmd[i++] = STLINK_DEBUG_FORCEDEBUG;
+    size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
         return;
     }
 }
 
-
 void _stlink_usb_enter_swd_mode(stlink_t * sl) {
     struct stlink_libusb * const slu = sl->backend_data;
-    unsigned char* const buf = sl->q_buf;
+    unsigned char* const cmd  = sl->c_buf;
     ssize_t size;
+    const int rep_len = 0;
+    int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
 
-    memset(buf, 0, sizeof (sl->q_buf));
-
-    buf[0] = STLINK_DEBUG_COMMAND;
-    buf[1] = STLINK_SWD_ENTER;
-    buf[2] = STLINK_DEBUG_ENTER_SWD;
+    cmd[i++] = STLINK_DEBUG_COMMAND;
+    cmd[i++] = STLINK_DEBUG_ENTER;
+    cmd[i++] = STLINK_DEBUG_ENTER_SWD;
 
-    size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
+    size = send_only(slu, 1, cmd, slu->cmd_len);
     if (size == -1) {
         printf("[!] send_recv\n");
         return;
@@ -299,14 +325,14 @@ void _stlink_usb_enter_swd_mode(stlink_t * sl) {
 
 void _stlink_usb_exit_dfu_mode(stlink_t* sl) {
     struct stlink_libusb * const slu = sl->backend_data;
-    unsigned char* const buf = sl->q_buf;
+    unsigned char* const cmd = sl->c_buf;
     ssize_t size;
+    int i = fill_command(sl, SG_DXFER_FROM_DEV, 0);
 
-    memset(buf, 0, sizeof (sl->q_buf));
-    buf[0] = STLINK_DFU_COMMAND;
-    buf[1] = STLINK_DFU_EXIT;
+    cmd[i++] = STLINK_DFU_COMMAND;
+    cmd[i++] = STLINK_DFU_EXIT;
 
-    size = send_only(slu, buf, 16);
+    size = send_only(slu, 1, cmd, slu->cmd_len);
     if (size == -1) {
         printf("[!] send_recv\n");
         return;
@@ -319,14 +345,16 @@ void _stlink_usb_exit_dfu_mode(stlink_t* sl) {
  */
 void _stlink_usb_reset(stlink_t * sl) {
     struct stlink_libusb * const slu = sl->backend_data;
-    unsigned char* const buf = sl->q_buf;
+    unsigned char* const data = sl->q_buf;
+    unsigned char* const cmd = sl->c_buf;
     ssize_t size;
+    int rep_len = 2;
+    int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
 
-    memset(buf, 0, sizeof (sl->q_buf));
-    buf[0] = STLINK_DEBUG_COMMAND;
-    buf[1] = STLINK_DEBUG_RESETSYS;
+    cmd[i++] = STLINK_DEBUG_COMMAND;
+    cmd[i++] = STLINK_DEBUG_RESETSYS;
 
-    size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
+    size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
         return;
@@ -336,14 +364,16 @@ void _stlink_usb_reset(stlink_t * sl) {
 
 void _stlink_usb_step(stlink_t* sl) {
     struct stlink_libusb * const slu = sl->backend_data;
-    unsigned char* const buf = sl->q_buf;
+    unsigned char* const data = sl->q_buf;
+    unsigned char* const cmd = sl->c_buf;
     ssize_t size;
+    int rep_len = 2;
+    int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
 
-    memset(buf, 0, sizeof (sl->q_buf));
-    buf[0] = STLINK_DEBUG_COMMAND;
-    buf[1] = STLINK_DEBUG_STEPCORE;
+    cmd[i++] = STLINK_DEBUG_COMMAND;
+    cmd[i++] = STLINK_DEBUG_STEPCORE;
 
-    size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
+    size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
         return;
@@ -356,31 +386,32 @@ void _stlink_usb_step(stlink_t* sl) {
  */
 void _stlink_usb_run(stlink_t* sl) {
     struct stlink_libusb * const slu = sl->backend_data;
-    unsigned char* const buf = sl->q_buf;
+    unsigned char* const data = sl->q_buf;
+    unsigned char* const cmd = sl->c_buf;
     ssize_t size;
+    int rep_len = 2;
+    int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
 
-    memset(buf, 0, sizeof (sl->q_buf));
-    buf[0] = STLINK_DEBUG_COMMAND;
-    buf[1] = STLINK_DEBUG_RUNCORE;
+    cmd[i++] = STLINK_DEBUG_COMMAND;
+    cmd[i++] = STLINK_DEBUG_RUNCORE;
 
-    size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
+    size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
         return;
     }
-
 }
 
 void _stlink_usb_exit_debug_mode(stlink_t *sl) {
     struct stlink_libusb * const slu = sl->backend_data;
-    unsigned char* const buf = sl->q_buf;
+    unsigned char* const cmd = sl->c_buf;
     ssize_t size;
+    int i = fill_command(sl, SG_DXFER_FROM_DEV, 0);
 
-    memset(buf, 0, sizeof (sl->q_buf));
-    buf[0] = STLINK_DEBUG_COMMAND;
-    buf[1] = STLINK_DEBUG_EXIT;
+    cmd[i++] = STLINK_DEBUG_COMMAND;
+    cmd[i++] = STLINK_DEBUG_EXIT;
 
-    size = send_only(slu, buf, 16);
+    size = send_only(slu, 1, cmd, slu->cmd_len);
     if (size == -1) {
         printf("[!] send_only\n");
         return;
@@ -389,22 +420,17 @@ void _stlink_usb_exit_debug_mode(stlink_t *sl) {
 
 void _stlink_usb_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
     struct stlink_libusb * const slu = sl->backend_data;
-    unsigned char* const buf = sl->q_buf;
+    unsigned char* const data = sl->q_buf;
+    unsigned char* const cmd = sl->c_buf;
     ssize_t size;
+    int i = fill_command(sl, SG_DXFER_FROM_DEV, len);
 
-    /* assume len < sizeof(sl->q_buf) */
-
-    memset(buf, 0, sizeof (sl->q_buf));
-    buf[0] = STLINK_DEBUG_COMMAND;
-    buf[1] = STLINK_DEBUG_READMEM_32BIT;
-    write_uint32(buf + 2, addr);
+    cmd[i++] = STLINK_DEBUG_COMMAND;
+    cmd[i++] = STLINK_DEBUG_READMEM_32BIT;
+    write_uint32(&cmd[i], addr);
+    write_uint16(&cmd[i + 4], len);
 
-    /* need to add +1 to len, otherwise get residue errors */
-    len += 1;
-    buf[6] = (uint8_t) len;
-    buf[7] = (uint8_t) (len >> 8);
-
-    size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
+    size = send_recv(slu, 1, cmd, slu->cmd_len, data, len);
     if (size == -1) {
         printf("[!] send_recv\n");
         return;
@@ -415,20 +441,17 @@ void _stlink_usb_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
     stlink_print_data(sl);
 }
 
-
-#if 1 /* stlinkv1 */
-
 void _stlink_usb_read_all_regs(stlink_t *sl, reg *regp) {
     struct stlink_libusb * const slu = sl->backend_data;
-    unsigned char* const buf = sl->q_buf;
-    unsigned char* const cmd_buf = sl->c_buf;
+    unsigned char* const cmd = sl->c_buf;
+    unsigned char* const data = sl->q_buf;
     ssize_t size;
-    int i;
+    uint32_t rep_len = 84;
+    int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
 
-    memset(cmd_buf, 0, STLINK_CMD_SIZE);
-    cmd_buf[0] = STLINK_DEBUG_COMMAND;
-    cmd_buf[1] = STLINK_DEBUG_READALLREGS;
-    size = send_recv(slu, cmd_buf, STLINK_CMD_SIZE, buf, 84);
+    cmd[i++] = STLINK_DEBUG_COMMAND;
+    cmd[i++] = STLINK_DEBUG_READALLREGS;
+    size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
         return;
@@ -452,53 +475,19 @@ void _stlink_usb_read_all_regs(stlink_t *sl, reg *regp) {
     DD(sl, "rw2        = 0x%08x\n", read_uint32(sl->q_buf, 80));
 }
 
-#else /* stlinkv2 */
-
-static void _stlink_usb_read_all_regs(stlink_t *sl, reg *regp) {
-    struct stlink_libusb * const slu = sl->backend_data;
-    unsigned char* const buf = sl->q_buf;
-    unsigned char* const cmd_buf = sl->c_buf;
-    ssize_t size;
-    int i;
-
-#define STLINK_JTAG_COMMAND 0xf2
-#define STLINK_JTAG_READALLREGS2 0x3a
-    memset(cmd_buf, 0, STLINK_CMD_SIZE);
-    cmd_buf[0] = STLINK_JTAG_COMMAND;
-    cmd_buf[1] = STLINK_JTAG_READALLREGS2;
-    size = send_recv(slu, cmd_buf, STLINK_CMD_SIZE, buf, 84);
-
-    if (size == -1) {
-        printf("[!] send_recv\n");
-        return;
-    }
-
-    sl->q_len = (size_t) size;
-
-    for(i=0; i<16; i++)
-      regp->r[i]= read_uint32(sl->q_buf, i*4);
-
-    regp->xpsr       = read_uint32(sl->q_buf, 64);
-    regp->main_sp    = read_uint32(sl->q_buf, 68);
-    regp->process_sp = read_uint32(sl->q_buf, 72);
-    regp->rw         = read_uint32(sl->q_buf, 76);
-    regp->rw2        = read_uint32(sl->q_buf, 80);
-}
-
-#endif /* stlinkv1 */
-
 void _stlink_usb_read_reg(stlink_t *sl, int r_idx, reg *regp) {
     struct stlink_libusb * const slu = sl->backend_data;
-    unsigned char* const buf = sl->q_buf;
-    unsigned char* const cmd_buf = sl->c_buf;
+    unsigned char* const data = sl->q_buf;
+    unsigned char* const cmd  = sl->c_buf;
     ssize_t size;
     uint32_t r;
+    uint32_t rep_len = 4;
+    int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
 
-    memset(cmd_buf, 0, STLINK_CMD_SIZE);
-    cmd_buf[0] = STLINK_DEBUG_COMMAND;
-    cmd_buf[1] = STLINK_DEBUG_READREG;
-    cmd_buf[2] = (uint8_t) r_idx;
-    size = send_recv(slu, cmd_buf, STLINK_CMD_SIZE, buf, 4);
+    cmd[i++] = STLINK_DEBUG_COMMAND;
+    cmd[i++] = STLINK_DEBUG_READREG;
+    cmd[i++] = (uint8_t) r_idx;
+    size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
         return;
@@ -519,31 +508,29 @@ void _stlink_usb_read_reg(stlink_t *sl, int r_idx, reg *regp) {
         regp->process_sp = r;
         break;
     case 19:
-        regp->rw = r; //XXX ?(primask, basemask etc.)
+        regp->rw = r; /* XXX ?(primask, basemask etc.) */
         break;
     case 20:
-        regp->rw2 = r; //XXX ?(primask, basemask etc.)
+        regp->rw2 = r; /* XXX ?(primask, basemask etc.) */
         break;
     default:
         regp->r[r_idx] = r;
     }
 }
 
-
-#if 1 /* stlinkv1 */
-
 void _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int idx) {
     struct stlink_libusb * const slu = sl->backend_data;
-    unsigned char* const buf = sl->q_buf;
-    unsigned char *cmd_buf = sl->c_buf;
+    unsigned char* const data = sl->q_buf;
+    unsigned char* const cmd  = sl->c_buf;
     ssize_t size;
-
-    memset(cmd_buf, 0, STLINK_CMD_SIZE);
-    cmd_buf[0] = STLINK_DEBUG_COMMAND;
-    cmd_buf[1] = STLINK_DEBUG_WRITEREG;
-    cmd_buf[2] = idx;
-    write_uint32(cmd_buf + 3, reg);
-    size = send_recv(slu, cmd_buf, STLINK_CMD_SIZE, buf, 2);
+    uint32_t rep_len = 2;
+    int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+
+    cmd[i++] = STLINK_DEBUG_COMMAND;
+    cmd[i++] = STLINK_DEBUG_WRITEREG;
+    cmd[i++] = idx;
+    write_uint32(&cmd[i], reg);
+    size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
         return;
@@ -552,32 +539,6 @@ void _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int idx) {
     stlink_print_data(sl);
 }
 
-#else /* stlinkv2 */
-
-void _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int idx) {
-    struct stlink_libusb * const slu = sl->backend_data;
-    unsigned char* const buf = sl->q_buf;
-    unsigned char *cmd_buf = sl->c_buf;
-    ssize_t size;
-
-#define STLINK_JTAG_WRITEREG2 0x34
-    memset(cmd_buf, 0, STLINK_CMD_SIZE);
-    cmd_buf[0] = STLINK_JTAG_COMMAND;
-    cmd_buf[1] = STLINK_JTAG_WRITEREG2;
-    cmd_buf[2] = idx;
-    write_uint32(cmd_buf + 3, reg);
-    size = send_recv(slu, cmd_buf, STLINK_CMD_SIZE, buf, 2);
-    if (size == -1) {
-        printf("[!] send_recv\n");
-        return;
-    }
-    sl->q_len = (size_t) size;
-    stlink_print_data(sl);
-}
-
-#endif /* stlinkv1 */
-
-
 stlink_backend_t _stlink_usb_backend = {
     _stlink_usb_close,
     _stlink_usb_exit_debug_mode,
@@ -601,38 +562,48 @@ stlink_backend_t _stlink_usb_backend = {
 };
 
 
-stlink_t* stlink_open_usb(const char *dev_name, const int verbose) {
+stlink_t* stlink_open_usb(const int verbose) {
     stlink_t* sl = NULL;
     struct stlink_libusb* slu = NULL;
-
-    /* unused */
-    dev_name = dev_name;
+    int error = -1;
+    libusb_device** devs = NULL;
+    libusb_device* dev;
+    ssize_t i;
+    ssize_t count;
+    int config;
+    char *iSerial = NULL;
 
     sl = malloc(sizeof (stlink_t));
     slu = malloc(sizeof (struct stlink_libusb));
     if (sl == NULL) goto on_error;
     if (slu == NULL) goto on_error;
+    memset(sl, 0, sizeof (stlink_t));
+    memset(slu, 0, sizeof (struct stlink_libusb));
 
     sl->verbose = verbose;
+    sl->backend = &_stlink_usb_backend;
+    sl->backend_data = slu;
     
-    if (slu->libusb_ctx != NULL) {
-        fprintf(stderr, "reopening with an existing context? undefined behaviour!\n");
-        goto on_error;
-    } else {
-        if (libusb_init(&(slu->libusb_ctx))) {
-            fprintf(stderr, "failed to init libusb context, wrong version of libraries?\n");
-            goto on_error;
-        }
-    }
+    sl->core_stat = STLINK_CORE_STAT_UNKNOWN;
 
-    int error = -1;
+    /* flash memory settings */
+    sl->flash_base = STM32_FLASH_BASE;
+    sl->flash_size = STM32_FLASH_SIZE;
+    sl->flash_pgsz = STM32_FLASH_PGSZ;
 
-    libusb_device** devs = NULL;
-    libusb_device* dev;
-    ssize_t i;
-    ssize_t count;
-    int config;
+    /* system memory */
+    sl->sys_base = STM32_SYSTEM_BASE;
+    sl->sys_size = STM32_SYSTEM_SIZE;
 
+    /* sram memory settings */
+    sl->sram_base = STM32_SRAM_BASE;
+    sl->sram_size = STM32L_SRAM_SIZE;
+
+    if (libusb_init(&(slu->libusb_ctx))) {
+       fprintf(stderr, "failed to init libusb context, wrong version of libraries?\n");
+       goto on_error;
+    }
+    
     count = libusb_get_device_list(slu->libusb_ctx, &devs);
     if (count < 0) {
         printf("libusb_get_device_list\n");
@@ -641,14 +612,47 @@ stlink_t* stlink_open_usb(const char *dev_name, const int verbose) {
 
     for (i = 0; i < count; ++i) {
         dev = devs[i];
-        if (is_stlink_device(dev)) break;
+        slu->protocoll = is_stlink_device(dev, 0);
+        if (slu->protocoll > 0) break;
     }
-    if (i == count) return NULL;
+    if (i == count) goto on_libusb_error;
 
     if (libusb_open(dev, &(slu->usb_handle))) {
         printf("libusb_open()\n");
         goto on_libusb_error;
     }
+    
+    if (iSerial) {
+        unsigned char serial[256];
+        struct libusb_device_descriptor desc;
+        int r;
+
+        r = libusb_get_device_descriptor(dev, &desc);
+        if (r<0) {
+            printf("Can't get descriptor to match Iserial\n");
+            goto on_libusb_error;
+        }
+        r = libusb_get_string_descriptor_ascii
+            (slu->usb_handle, desc.iSerialNumber, serial, 256);
+        if (r<0) {
+            printf("Can't get Serialnumber to match Iserial\n");
+            goto on_libusb_error;
+        }
+        if (strcmp((char*)serial, iSerial)) {
+            printf("Mismatch in serial numbers, dev %s vs given %s\n",
+                   serial, iSerial);
+            goto on_libusb_error;
+        }
+    }
+
+    if (libusb_kernel_driver_active(slu->usb_handle, 0) == 1) {
+        int r;
+        
+        r = libusb_detach_kernel_driver(slu->usb_handle, 0);
+        if (r<0)
+            printf("libusb_detach_kernel_driver(() error %s\n", strerror(-r));
+        goto on_libusb_error;
+    }
 
     if (libusb_get_configuration(slu->usb_handle, &config)) {
         /* this may fail for a previous configured device */
@@ -685,15 +689,20 @@ stlink_t* stlink_open_usb(const char *dev_name, const int verbose) {
     slu->ep_rep = 1 /* ep rep */ | LIBUSB_ENDPOINT_IN;
     slu->ep_req = 2 /* ep req */ | LIBUSB_ENDPOINT_OUT;
 
-    /* libusb_reset_device(slu->usb_handle); */
+    slu->sg_transfer_idx = 0;
+    slu->cmd_len = (slu->protocoll == 1)? STLINK_SG_SIZE: STLINK_CMD_SIZE;
 
     /* success */
+    if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) {
+      printf("-- exit_dfu_mode\n");
+      stlink_exit_dfu_mode(sl);
+    }
+    stlink_version(sl);
     error = 0;
 
 on_libusb_error:
     if (devs != NULL) {
         libusb_free_device_list(devs, 1);
-        fprintf(stderr, "freed libusb device list\n");
     }
 
     if (error == -1) {
@@ -701,22 +710,6 @@ on_libusb_error:
         return NULL;
     }
 
-    sl->backend = &_stlink_usb_backend;
-    sl->backend_data = slu;
-
-    /* flash memory settings */
-    sl->flash_base = STM32_FLASH_BASE;
-    sl->flash_size = STM32_FLASH_SIZE;
-    sl->flash_pgsz = STM32_FLASH_PGSZ;
-
-    /* system memory */
-    sl->sys_base = STM32_SYSTEM_BASE;
-    sl->sys_size = STM32_SYSTEM_SIZE;
-
-    /* sram memory settings */
-    sl->sram_base = STM32_SRAM_BASE;
-    sl->sram_size = STM32L_SRAM_SIZE;
-
     /* success */
     return sl;
 
index 4ed655b7e29c1b9e6a634f1f74b0e78bbd774b37..c632a8c4163da3257a61014cf1b614b30e7cc884 100644 (file)
@@ -15,6 +15,7 @@ extern "C" {
 #include <libusb-1.0/libusb.h>
 #include "stlink-common.h"
     
+#define STLINK_SG_SIZE 31
 #define STLINK_CMD_SIZE 16
 
 #if defined(CONFIG_USE_LIBUSB)
@@ -25,6 +26,9 @@ extern "C" {
         struct libusb_transfer* rep_trans;
         unsigned int ep_req;
         unsigned int ep_rep;
+        int protocoll;
+        unsigned int sg_transfer_idx;
+        unsigned int cmd_len;
     };
 #else
 #error "it's all bad!"
@@ -32,7 +36,7 @@ extern "C" {
 #endif
 
     
-    stlink_t* stlink_open_usb(const char *dev_name, const int verbose);
+    stlink_t* stlink_open_usb(const int verbose);
 
 
 #ifdef __cplusplus
index 137eca4cf1a34e894ba60be8a75b32340c3ec7e2..34fbe540caa000c2665a87582b7578487b2f1816 100644 (file)
@@ -6,8 +6,10 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#if CONFIG_USE_LIBSG
 #include <scsi/sg_lib.h>
 #include <scsi/sg_pt.h>
+#endif
 #include "stlink-common.h"
 
 int main(int argc, char *argv[]) {
@@ -210,4 +212,4 @@ int main(int argc, char *argv[]) {
 
        //fflush(stderr); fflush(stdout);
        return EXIT_SUCCESS;
-}
\ No newline at end of file
+}
index bd81ec1d5998e62950d579b4777fa23097055516..343e355a358f96ed327006074f760cd0ff78fe2b 100644 (file)
@@ -10,7 +10,7 @@ int main(int ac, char** av) {
     ac = ac;
     av = av;
 
-    sl = stlink_open_usb(NULL, 10);
+    sl = stlink_open_usb(10);
     if (sl != NULL) {
         printf("-- version\n");
         stlink_version(sl);