Make the backends propagate errors
authorMaxime Coquelin <mcoquelin.stm32@gmail.com>
Fri, 11 Mar 2016 10:16:41 +0000 (11:16 +0100)
committerMaxime Coquelin <mcoquelin.stm32@gmail.com>
Mon, 14 Mar 2016 14:12:44 +0000 (15:12 +0100)
As the libusb returns errors, make the backends propagates them so that
callers can decide to continue or stop task execution.

Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
src/stlink-common.h
src/stlink-sg.c
src/stlink-usb.c

index fbbb2b42ee196eaf9fced25891ff9c47266277c2..467b9b90ac39575bd7a03feeefe5449df84618be 100644 (file)
@@ -556,30 +556,30 @@ extern "C" {
 
     typedef struct _stlink_backend {
         void (*close) (stlink_t * sl);
-        void (*exit_debug_mode) (stlink_t * sl);
-        void (*enter_swd_mode) (stlink_t * sl);
-        void (*enter_jtag_mode) (stlink_t * stl);
-        void (*exit_dfu_mode) (stlink_t * stl);
-        void (*core_id) (stlink_t * stl);
-        void (*reset) (stlink_t * stl);
-        void (*jtag_reset) (stlink_t * stl, int value);
-        void (*run) (stlink_t * stl);
-        void (*status) (stlink_t * stl);
-        void (*version) (stlink_t *sl);
-        void (*read_debug32) (stlink_t *sl, uint32_t addr, uint32_t *data);
-        void (*read_mem32) (stlink_t *sl, uint32_t addr, uint16_t len);
-        void (*write_debug32) (stlink_t *sl, uint32_t addr, uint32_t data);
-        void (*write_mem32) (stlink_t *sl, uint32_t addr, uint16_t len);
-        void (*write_mem8) (stlink_t *sl, uint32_t addr, uint16_t len);
-        void (*read_all_regs) (stlink_t *sl, reg * regp);
-        void (*read_reg) (stlink_t *sl, int r_idx, reg * regp);
-        void (*read_all_unsupported_regs) (stlink_t *sl, reg *regp);
-        void (*read_unsupported_reg) (stlink_t *sl, int r_idx, reg *regp);
-        void (*write_unsupported_reg) (stlink_t *sl, uint32_t value, int idx, reg *regp);
-        void (*write_reg) (stlink_t *sl, uint32_t reg, int idx);
-        void (*step) (stlink_t * stl);
+        int (*exit_debug_mode) (stlink_t * sl);
+        int (*enter_swd_mode) (stlink_t * sl);
+        int (*enter_jtag_mode) (stlink_t * stl);
+        int (*exit_dfu_mode) (stlink_t * stl);
+        int (*core_id) (stlink_t * stl);
+        int (*reset) (stlink_t * stl);
+        int (*jtag_reset) (stlink_t * stl, int value);
+        int (*run) (stlink_t * stl);
+        int (*status) (stlink_t * stl);
+        int (*version) (stlink_t *sl);
+        int (*read_debug32) (stlink_t *sl, uint32_t addr, uint32_t *data);
+        int (*read_mem32) (stlink_t *sl, uint32_t addr, uint16_t len);
+        int (*write_debug32) (stlink_t *sl, uint32_t addr, uint32_t data);
+        int (*write_mem32) (stlink_t *sl, uint32_t addr, uint16_t len);
+        int (*write_mem8) (stlink_t *sl, uint32_t addr, uint16_t len);
+        int (*read_all_regs) (stlink_t *sl, reg * regp);
+        int (*read_reg) (stlink_t *sl, int r_idx, reg * regp);
+        int (*read_all_unsupported_regs) (stlink_t *sl, reg *regp);
+        int (*read_unsupported_reg) (stlink_t *sl, int r_idx, reg *regp);
+        int (*write_unsupported_reg) (stlink_t *sl, uint32_t value, int idx, reg *regp);
+        int (*write_reg) (stlink_t *sl, uint32_t reg, int idx);
+        int (*step) (stlink_t * stl);
         int (*current_mode) (stlink_t * stl);
-        void (*force_debug) (stlink_t *sl);
+        int (*force_debug) (stlink_t *sl);
         int32_t (*target_voltage) (stlink_t *sl);
     } stlink_backend_t;
 
index 3fdc0bde5b85b23949c8ed0b57f5e83b295bcdde..03df7d85468f09b0356222d84beb21031d013191 100644 (file)
@@ -403,13 +403,13 @@ void stlink_stat(stlink_t *stl, char *txt) {
 }
 
 
-void _stlink_sg_version(stlink_t *stl) {
+int _stlink_sg_version(stlink_t *stl) {
     struct stlink_libsg *sl = stl->backend_data;
     clear_cdb(sl);
     sl->cdb_cmd_blk[0] = STLINK_GET_VERSION;
     stl->q_len = 6;
     sl->q_addr = 0;
-    stlink_q(stl);
+    return stlink_q(stl);
 }
 
 // Get stlink mode:
@@ -422,44 +422,46 @@ int _stlink_sg_current_mode(stlink_t *stl) {
     sl->cdb_cmd_blk[0] = STLINK_GET_CURRENT_MODE;
     stl->q_len = 2;
     sl->q_addr = 0;
-    stlink_q(stl);
+    if (stlink_q(stl))
+        return -1;
+
     return stl->q_buf[0];
 }
 
 // Exit the mass mode and enter the swd debug mode.
 
-void _stlink_sg_enter_swd_mode(stlink_t *sl) {
+int _stlink_sg_enter_swd_mode(stlink_t *sl) {
     struct stlink_libsg *sg = sl->backend_data;
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_ENTER;
     sg->cdb_cmd_blk[2] = STLINK_DEBUG_ENTER_SWD;
     sl->q_len = 0; // >0 -> aboard
-    stlink_q(sl);
+    return stlink_q(sl);
 }
 
 // Exit the mass mode and enter the jtag debug mode.
 // (jtag is disabled in the discovery's stlink firmware)
 
-void _stlink_sg_enter_jtag_mode(stlink_t *sl) {
+int _stlink_sg_enter_jtag_mode(stlink_t *sl) {
     struct stlink_libsg *sg = sl->backend_data;
     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;
     sl->q_len = 0;
-    stlink_q(sl);
+    return stlink_q(sl);
 }
 
 // XXX kernel driver performs reset, the device temporally disappears
 // Suspect this is no longer the case when we have ignore on? RECHECK
-void _stlink_sg_exit_dfu_mode(stlink_t *sl) {
+int _stlink_sg_exit_dfu_mode(stlink_t *sl) {
     struct stlink_libsg *sg = sl->backend_data;
     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;
     sl->q_len = 0; // ??
-    stlink_q(sl);
+    return stlink_q(sl);
     /*
        [135121.844564] sd 19:0:0:0: [sdb] Unhandled error code
        [135121.844569] sd 19:0:0:0: [sdb] Result: hostbyte=DID_ERROR driverbyte=DRIVER_OK
@@ -505,74 +507,91 @@ void _stlink_sg_exit_dfu_mode(stlink_t *sl) {
        */
 }
 
-void _stlink_sg_core_id(stlink_t *sl) {
+int _stlink_sg_core_id(stlink_t *sl) {
     struct stlink_libsg *sg = sl->backend_data;
+    int ret;
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_READCOREID;
     sl->q_len = 4;
     sg->q_addr = 0;
-    stlink_q(sl);
+    ret = stlink_q(sl);
+    if (ret)
+        return ret;
+
     sl->core_id = read_uint32(sl->q_buf, 0);
+    return 0;
 }
 
 // Arm-core reset -> halted state.
 
-void _stlink_sg_reset(stlink_t *sl) {
+int _stlink_sg_reset(stlink_t *sl) {
     struct stlink_libsg *sg = sl->backend_data;
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_RESETSYS;
     sl->q_len = 2;
     sg->q_addr = 0;
-    stlink_q(sl);
+    if (stlink_q(sl))
+        return -1;
+
     stlink_stat(sl, "core reset");
+    return 0;
 }
 
 // Arm-core reset -> halted state.
 
-void _stlink_sg_jtag_reset(stlink_t *sl, int value) {
+int _stlink_sg_jtag_reset(stlink_t *sl, int value) {
     struct stlink_libsg *sg = sl->backend_data;
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_JTAG_DRIVE_NRST;
     sg->cdb_cmd_blk[2] = (value)?0:1;
     sl->q_len = 3;
     sg->q_addr = 2;
-    stlink_q(sl);
+    if (stlink_q(sl))
+        return -1;
+
     stlink_stat(sl, "core reset");
+
+    return 0;
 }
 
 // Arm-core status: halted or running.
 
-void _stlink_sg_status(stlink_t *sl) {
+int _stlink_sg_status(stlink_t *sl) {
     struct stlink_libsg *sg = sl->backend_data;
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_GETSTATUS;
     sl->q_len = 2;
     sg->q_addr = 0;
-    stlink_q(sl);
+    return stlink_q(sl);
 }
 
 // Force the core into the debug mode -> halted state.
 
-void _stlink_sg_force_debug(stlink_t *sl) {
+int _stlink_sg_force_debug(stlink_t *sl) {
     struct stlink_libsg *sg = sl->backend_data;
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_FORCEDEBUG;
     sl->q_len = 2;
     sg->q_addr = 0;
-    stlink_q(sl);
+    if (stlink_q(sl))
+        return -1;
+
     stlink_stat(sl, "force debug");
+    return 0;
 }
 
 // Read all arm-core registers.
 
-void _stlink_sg_read_all_regs(stlink_t *sl, reg *regp) {
+int _stlink_sg_read_all_regs(stlink_t *sl, reg *regp) {
     struct stlink_libsg *sg = sl->backend_data;
 
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_READALLREGS;
     sl->q_len = 84;
     sg->q_addr = 0;
-    stlink_q(sl);
+    if (stlink_q(sl))
+        return -1;
+
     stlink_print_data(sl);
 
     // TODO - most of this should be re-extracted up....
@@ -590,27 +609,31 @@ void _stlink_sg_read_all_regs(stlink_t *sl, reg *regp) {
     regp->rw = read_uint32(sl->q_buf, 76);
     regp->rw2 = read_uint32(sl->q_buf, 80);
     if (sl->verbose < 2)
-        return;
+        return 0;
 
     DLOG("xpsr       = 0x%08x\n", regp->xpsr);
     DLOG("main_sp    = 0x%08x\n", regp->main_sp);
     DLOG("process_sp = 0x%08x\n", regp->process_sp);
     DLOG("rw         = 0x%08x\n", regp->rw);
     DLOG("rw2        = 0x%08x\n", regp->rw2);
+
+    return 0;
 }
 
 // Read an arm-core register, the index must be in the range 0..20.
 //  0  |  1  | ... |  15   |  16   |   17    |   18       |  19   |  20
 // r0  | r1  | ... | r15   | xpsr  | main_sp | process_sp | rw    | rw2
 
-void _stlink_sg_read_reg(stlink_t *sl, int r_idx, reg *regp) {
+int _stlink_sg_read_reg(stlink_t *sl, int r_idx, reg *regp) {
     struct stlink_libsg *sg = sl->backend_data;
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_READREG;
     sg->cdb_cmd_blk[2] = r_idx;
     sl->q_len = 4;
     sg->q_addr = 0;
-    stlink_q(sl);
+    if (stlink_q(sl))
+        return -1;
+
     //  0  |  1  | ... |  15   |  16   |   17    |   18       |  19   |  20
     // 0-3 | 4-7 | ... | 60-63 | 64-67 | 68-71   | 72-75      | 76-79 | 80-83
     // r0  | r1  | ... | r15   | xpsr  | main_sp | process_sp | rw    | rw2
@@ -638,13 +661,15 @@ void _stlink_sg_read_reg(stlink_t *sl, int r_idx, reg *regp) {
     default:
         regp->r[r_idx] = r;
     }
+
+    return 0;
 }
 
 // Write an arm-core register. Index:
 //  0  |  1  | ... |  15   |  16   |   17    |   18       |  19   |  20
 // r0  | r1  | ... | r15   | xpsr  | main_sp | process_sp | rw    | rw2
 
-void _stlink_sg_write_reg(stlink_t *sl, uint32_t reg, int idx) {
+int _stlink_sg_write_reg(stlink_t *sl, uint32_t reg, int idx) {
     struct stlink_libsg *sg = sl->backend_data;
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEREG;
@@ -654,8 +679,11 @@ void _stlink_sg_write_reg(stlink_t *sl, uint32_t reg, int idx) {
     write_uint32(sg->cdb_cmd_blk + 3, reg);
     sl->q_len = 2;
     sg->q_addr = 0;
-    stlink_q(sl);
+    if (stlink_q(sl))
+        return -1;
+
     stlink_stat(sl, "write reg");
+    return 0;
 }
 
 // Write a register of the debug module of the core.
@@ -679,26 +707,33 @@ void stlink_write_dreg(stlink_t *sl, uint32_t reg, uint32_t addr) {
 
 // Force the core exit the debug mode.
 
-void _stlink_sg_run(stlink_t *sl) {
+int _stlink_sg_run(stlink_t *sl) {
     struct stlink_libsg *sg = sl->backend_data;
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_RUNCORE;
     sl->q_len = 2;
     sg->q_addr = 0;
-    stlink_q(sl);
+    if (stlink_q(sl))
+        return -1;
+
     stlink_stat(sl, "run core");
+
+    return 0;
 }
 
 // Step the arm-core.
 
-void _stlink_sg_step(stlink_t *sl) {
+int _stlink_sg_step(stlink_t *sl) {
     struct stlink_libsg *sg = sl->backend_data;
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_STEPCORE;
     sl->q_len = 2;
     sg->q_addr = 0;
-    stlink_q(sl);
+    if (stlink_q(sl))
+        return -1;
+
     stlink_stat(sl, "step core");
+    return 0;
 }
 
 // TODO test
@@ -738,7 +773,7 @@ void stlink_clr_hw_bp(stlink_t *sl, int fp_nr) {
 
 // Read a "len" bytes to the sl->q_buf from the memory, max 6kB (6144 bytes)
 
-void _stlink_sg_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
+int _stlink_sg_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
     struct stlink_libsg *sg = sl->backend_data;
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_READMEM_32BIT;
@@ -754,14 +789,19 @@ void _stlink_sg_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
     //     (broken residue issue)
     sl->q_len = len;
     sg->q_addr = addr;
-    stlink_q(sl);
+    if (stlink_q(sl))
+        return -1;
+
     stlink_print_data(sl);
+    return 0;
 }
 
 // Write a "len" bytes from the sl->q_buf to the memory, max 64 Bytes.
 
-void _stlink_sg_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) {
+int _stlink_sg_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) {
     struct stlink_libsg *sg = sl->backend_data;
+    int ret;
+
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEMEM_8BIT;
     // 2-5: addr
@@ -770,16 +810,27 @@ void _stlink_sg_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) {
     write_uint16(sg->cdb_cmd_blk + 6, len);
 
     // this sends the command...
-    send_usb_mass_storage_command(sg->usb_handle, sg->ep_req, sg->cdb_cmd_blk, CDB_SL, 0, 0, 0);
+    ret = send_usb_mass_storage_command(sg->usb_handle,
+            sg->ep_req, sg->cdb_cmd_blk, CDB_SL, 0, 0, 0);
+    if (ret == -1)
+        return ret;
+
     // This sends the data...
-    send_usb_data_only(sg->usb_handle, sg->ep_req, sg->ep_rep, sl->q_buf, len);
+    ret = send_usb_data_only(sg->usb_handle,
+            sg->ep_req, sg->ep_rep, sl->q_buf, len);
+    if (ret == -1)
+        return ret;
+
     stlink_print_data(sl);
+    return 0;
 }
 
 // Write a "len" bytes from the sl->q_buf to the memory, max Q_BUF_LEN bytes.
 
-void _stlink_sg_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
+int _stlink_sg_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
     struct stlink_libsg *sg = sl->backend_data;
+    int ret;
+
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEMEM_32BIT;
     // 2-5: addr
@@ -788,16 +839,24 @@ void _stlink_sg_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
     write_uint16(sg->cdb_cmd_blk + 6, len);
 
     // this sends the command...
-    send_usb_mass_storage_command(sg->usb_handle, sg->ep_req, sg->cdb_cmd_blk, CDB_SL, 0, 0, 0);
+    ret = send_usb_mass_storage_command(sg->usb_handle,
+            sg->ep_req, sg->cdb_cmd_blk, CDB_SL, 0, 0, 0);
+    if (ret == -1)
+        return ret;
+
     // This sends the data...
-    send_usb_data_only(sg->usb_handle, sg->ep_req, sg->ep_rep, sl->q_buf, len);
+    ret = send_usb_data_only(sg->usb_handle,
+            sg->ep_req, sg->ep_rep, sl->q_buf, len);
+    if (ret == -1)
+        return ret;
 
     stlink_print_data(sl);
+    return 0;
 }
 
 // Write one DWORD data to memory
 
-void _stlink_sg_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) {
+int _stlink_sg_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) {
     struct stlink_libsg *sg = sl->backend_data;
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_JTAG_WRITEDEBUG_32BIT;
@@ -805,36 +864,38 @@ void _stlink_sg_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) {
     write_uint32(sg->cdb_cmd_blk + 2, addr);
     write_uint32(sg->cdb_cmd_blk + 6, data);
     sl->q_len = 2;
-    stlink_q(sl);
-
+    return stlink_q(sl);
 }
 
 // Read one DWORD data from memory
 
-void _stlink_sg_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data) {
+int _stlink_sg_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data) {
     struct stlink_libsg *sg = sl->backend_data;
     clear_cdb(sg);
     sg->cdb_cmd_blk[1] = STLINK_JTAG_READDEBUG_32BIT;
     // 2-5: addr
     write_uint32(sg->cdb_cmd_blk + 2, addr);
     sl->q_len = 8;
-    stlink_q(sl);
+    if (stlink_q(sl))
+        return -1;
 
     *data = read_uint32(sl->q_buf, 4);
-    return;
+    return 0;
 }
 
 // Exit the jtag or swd mode and enter the mass mode.
 
-void _stlink_sg_exit_debug_mode(stlink_t *stl) {
-
+int _stlink_sg_exit_debug_mode(stlink_t *stl)
+{
     if (stl) {
         struct stlink_libsg* sl = stl->backend_data;
         clear_cdb(sl);
         sl->cdb_cmd_blk[1] = STLINK_DEBUG_EXIT;
         stl->q_len = 0; // >0 -> aboard
-        stlink_q(stl);
+        return stlink_q(stl);
     }
+
+    return 0;
 }
 
 
index 927e44e9681649372c505fb580a330b0544bbde1..8e52c6801488459001a69e434a7e1c88831ef486 100644 (file)
@@ -93,7 +93,7 @@ static int fill_command
     return i;
 }
 
-void _stlink_usb_version(stlink_t *sl) {
+int _stlink_usb_version(stlink_t *sl) {
     struct stlink_libusb * const slu = sl->backend_data;
     unsigned char* const data = sl->q_buf;
     unsigned char* const cmd  = sl->c_buf;
@@ -106,8 +106,10 @@ void _stlink_usb_version(stlink_t *sl) {
     size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
-        return;
+        return size;
     }
+
+    return 0;
 }
 
 int32_t _stlink_usb_target_voltage(stlink_t *sl) {
@@ -138,7 +140,7 @@ int32_t _stlink_usb_target_voltage(stlink_t *sl) {
     return voltage;
 }
 
-void _stlink_usb_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data) {
+int _stlink_usb_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data) {
     struct stlink_libusb * const slu = sl->backend_data;
     unsigned char* const rdata = sl->q_buf;
     unsigned char* const cmd  = sl->c_buf;
@@ -152,13 +154,13 @@ void _stlink_usb_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data) {
     size = send_recv(slu, 1, cmd, slu->cmd_len, rdata, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
-        return;
+        return size;
     }
     *data = read_uint32(rdata, 4);
-    return;
+    return 0;
 }
 
-void _stlink_usb_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) {
+int _stlink_usb_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) {
     struct stlink_libusb * const slu = sl->backend_data;
     unsigned char* const rdata = sl->q_buf;
     unsigned char* const cmd  = sl->c_buf;
@@ -173,37 +175,54 @@ void _stlink_usb_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) {
     size = send_recv(slu, 1, cmd, slu->cmd_len, rdata, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
-        return;
+        return size;
     }
+
+    return 0;
 }
 
-void _stlink_usb_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
+int _stlink_usb_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
     struct stlink_libusb * const slu = sl->backend_data;
     unsigned char* const data = sl->q_buf;
     unsigned char* const cmd  = sl->c_buf;
+    int i, ret;
 
-    int i = fill_command(sl, SG_DXFER_TO_DEV, len);
+    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);
+    ret = send_only(slu, 0, cmd, slu->cmd_len);
+    if (ret == -1)
+        return ret;
+
+    ret = send_only(slu, 1, data, len);
+    if (ret == -1)
+        return ret;
 
-    send_only(slu, 1, data, len);
+    return 0;
 }
 
-void _stlink_usb_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) {
+int _stlink_usb_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) {
     struct stlink_libusb * const slu = sl->backend_data;
     unsigned char* const data = sl->q_buf;
     unsigned char* const cmd  = sl->c_buf;
+    int i, ret;
 
-    int i = fill_command(sl, SG_DXFER_TO_DEV, 0);
+    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);
+    ret = send_only(slu, 0, cmd, slu->cmd_len);
+    if (ret == -1)
+        return ret;
+
+    ret = send_only(slu, 1, data, len);
+    if (ret == -1)
+        return ret;
+
+    return 0;
 }
 
 
@@ -224,7 +243,7 @@ int _stlink_usb_current_mode(stlink_t * sl) {
     return sl->q_buf[0];
 }
 
-void _stlink_usb_core_id(stlink_t * sl) {
+int _stlink_usb_core_id(stlink_t * sl) {
     struct stlink_libusb * const slu = sl->backend_data;
     unsigned char* const cmd  = sl->c_buf;
     unsigned char* const data = sl->q_buf;
@@ -238,13 +257,14 @@ void _stlink_usb_core_id(stlink_t * sl) {
     size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
-        return;
+        return -1;
     }
 
     sl->core_id = read_uint32(data, 0);
+    return 0;
 }
 
-void _stlink_usb_status(stlink_t * sl) {
+int _stlink_usb_status(stlink_t * sl) {
     struct stlink_libusb * const slu = sl->backend_data;
     unsigned char* const data = sl->q_buf;
     unsigned char* const cmd  = sl->c_buf;
@@ -258,12 +278,14 @@ void _stlink_usb_status(stlink_t * sl) {
     size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
-        return;
+        return size;
     }
     sl->q_len = (size_t) size;
+
+    return 0;
 }
 
-void _stlink_usb_force_debug(stlink_t *sl) {
+int _stlink_usb_force_debug(stlink_t *sl) {
     struct stlink_libusb *slu = sl->backend_data;
     unsigned char* const data = sl->q_buf;
     unsigned char* const cmd  = sl->c_buf;
@@ -276,11 +298,13 @@ void _stlink_usb_force_debug(stlink_t *sl) {
     size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
-        return;
+        return size;
     }
+
+    return 0;
 }
 
-void _stlink_usb_enter_swd_mode(stlink_t * sl) {
+int _stlink_usb_enter_swd_mode(stlink_t * sl) {
     struct stlink_libusb * const slu = sl->backend_data;
     unsigned char* const cmd  = sl->c_buf;
     ssize_t size;
@@ -294,11 +318,13 @@ void _stlink_usb_enter_swd_mode(stlink_t * sl) {
     size = send_only(slu, 1, cmd, slu->cmd_len);
     if (size == -1) {
         printf("[!] send_recv\n");
-        return;
+        return size;
     }
+
+    return 0;
 }
 
-void _stlink_usb_exit_dfu_mode(stlink_t* sl) {
+int _stlink_usb_exit_dfu_mode(stlink_t* sl) {
     struct stlink_libusb * const slu = sl->backend_data;
     unsigned char* const cmd = sl->c_buf;
     ssize_t size;
@@ -310,15 +336,17 @@ void _stlink_usb_exit_dfu_mode(stlink_t* sl) {
     size = send_only(slu, 1, cmd, slu->cmd_len);
     if (size == -1) {
         printf("[!] send_recv\n");
-        return;
+        return size;
     }
+
+    return 0;
 }
 
 /**
  * TODO - not convinced this does anything...
  * @param sl
  */
-void _stlink_usb_reset(stlink_t * sl) {
+int _stlink_usb_reset(stlink_t * sl) {
     struct stlink_libusb * const slu = sl->backend_data;
     unsigned char* const data = sl->q_buf;
     unsigned char* const cmd = sl->c_buf;
@@ -332,12 +360,14 @@ void _stlink_usb_reset(stlink_t * sl) {
     size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
-        return;
+        return size;
     }
+
+       return 0;
 }
 
 
-void _stlink_usb_jtag_reset(stlink_t * sl, int value) {
+int _stlink_usb_jtag_reset(stlink_t * sl, int value) {
     struct stlink_libusb * const slu = sl->backend_data;
     unsigned char* const data = sl->q_buf;
     unsigned char* const cmd = sl->c_buf;
@@ -352,12 +382,14 @@ void _stlink_usb_jtag_reset(stlink_t * sl, int value) {
     size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
-        return;
+        return size;
     }
+
+    return 0;
 }
 
 
-void _stlink_usb_step(stlink_t* sl) {
+int _stlink_usb_step(stlink_t* sl) {
     struct stlink_libusb * const slu = sl->backend_data;
     unsigned char* const data = sl->q_buf;
     unsigned char* const cmd = sl->c_buf;
@@ -371,15 +403,17 @@ void _stlink_usb_step(stlink_t* sl) {
     size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
-        return;
+        return size;
     }
+
+    return 0;
 }
 
 /**
  * This seems to do a good job of restarting things from the beginning?
  * @param sl
  */
-void _stlink_usb_run(stlink_t* sl) {
+int _stlink_usb_run(stlink_t* sl) {
     struct stlink_libusb * const slu = sl->backend_data;
     unsigned char* const data = sl->q_buf;
     unsigned char* const cmd = sl->c_buf;
@@ -393,11 +427,13 @@ void _stlink_usb_run(stlink_t* sl) {
     size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
-        return;
+        return size;
     }
+
+    return 0;
 }
 
-void _stlink_usb_exit_debug_mode(stlink_t *sl) {
+int _stlink_usb_exit_debug_mode(stlink_t *sl) {
     struct stlink_libusb * const slu = sl->backend_data;
     unsigned char* const cmd = sl->c_buf;
     ssize_t size;
@@ -409,11 +445,13 @@ void _stlink_usb_exit_debug_mode(stlink_t *sl) {
     size = send_only(slu, 1, cmd, slu->cmd_len);
     if (size == -1) {
         printf("[!] send_only\n");
-        return;
+        return size;
     }
+
+    return 0;
 }
 
-void _stlink_usb_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
+int _stlink_usb_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
     struct stlink_libusb * const slu = sl->backend_data;
     unsigned char* const data = sl->q_buf;
     unsigned char* const cmd = sl->c_buf;
@@ -428,15 +466,16 @@ void _stlink_usb_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
     size = send_recv(slu, 1, cmd, slu->cmd_len, data, len);
     if (size == -1) {
         printf("[!] send_recv\n");
-        return;
+        return size;
     }
 
     sl->q_len = (size_t) size;
 
     stlink_print_data(sl);
+    return 0;
 }
 
-void _stlink_usb_read_all_regs(stlink_t *sl, reg *regp) {
+int _stlink_usb_read_all_regs(stlink_t *sl, reg *regp) {
     struct stlink_libusb * const slu = sl->backend_data;
     unsigned char* const cmd = sl->c_buf;
     unsigned char* const data = sl->q_buf;
@@ -449,7 +488,7 @@ void _stlink_usb_read_all_regs(stlink_t *sl, reg *regp) {
     size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
-        return;
+        return size;
     }
     sl->q_len = (size_t) size;
     stlink_print_data(sl);
@@ -461,16 +500,18 @@ void _stlink_usb_read_all_regs(stlink_t *sl, reg *regp) {
     regp->rw         = read_uint32(sl->q_buf, 76);
     regp->rw2        = read_uint32(sl->q_buf, 80);
     if (sl->verbose < 2)
-        return;
+        return 0;
 
     DLOG("xpsr       = 0x%08x\n", read_uint32(sl->q_buf, 64));
     DLOG("main_sp    = 0x%08x\n", read_uint32(sl->q_buf, 68));
     DLOG("process_sp = 0x%08x\n", read_uint32(sl->q_buf, 72));
     DLOG("rw         = 0x%08x\n", read_uint32(sl->q_buf, 76));
     DLOG("rw2        = 0x%08x\n", read_uint32(sl->q_buf, 80));
+
+    return 0;
 }
 
-void _stlink_usb_read_reg(stlink_t *sl, int r_idx, reg *regp) {
+int _stlink_usb_read_reg(stlink_t *sl, int r_idx, reg *regp) {
     struct stlink_libusb * const slu = sl->backend_data;
     unsigned char* const data = sl->q_buf;
     unsigned char* const cmd  = sl->c_buf;
@@ -485,7 +526,7 @@ void _stlink_usb_read_reg(stlink_t *sl, int r_idx, reg *regp) {
     size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
-        return;
+        return size;
     }
     sl->q_len = (size_t) size;
     stlink_print_data(sl);
@@ -511,19 +552,27 @@ void _stlink_usb_read_reg(stlink_t *sl, int r_idx, reg *regp) {
     default:
         regp->r[r_idx] = r;
     }
+
+    return 0;
 }
 
 /* See section C1.6 of the ARMv7-M Architecture Reference Manual */
-void _stlink_usb_read_unsupported_reg(stlink_t *sl, int r_idx, reg *regp) {
+int _stlink_usb_read_unsupported_reg(stlink_t *sl, int r_idx, reg *regp) {
     uint32_t r;
+    int ret;
 
     sl->q_buf[0] = (unsigned char) r_idx;
     for (int i = 1; i < 4; i++) {
         sl->q_buf[i] = 0;
     }
 
-    _stlink_usb_write_mem32(sl, DCRSR, 4);
+    ret = _stlink_usb_write_mem32(sl, DCRSR, 4);
+    if (ret == -1)
+        return ret;
+
     _stlink_usb_read_mem32(sl, DCRDR, 4);
+    if (ret == -1)
+        return ret;
 
     r = read_uint32(sl->q_buf, 0);
     DLOG("r_idx (%2d) = 0x%08x\n", r_idx, r);
@@ -542,22 +591,39 @@ void _stlink_usb_read_unsupported_reg(stlink_t *sl, int r_idx, reg *regp) {
         regp->s[r_idx - 0x40] = r;
         break;
     }
+
+    return 0;
 }
 
-void _stlink_usb_read_all_unsupported_regs(stlink_t *sl, reg *regp) {
-    _stlink_usb_read_unsupported_reg(sl, 0x14, regp);
-    _stlink_usb_read_unsupported_reg(sl, 0x21, regp);
+int _stlink_usb_read_all_unsupported_regs(stlink_t *sl, reg *regp) {
+    int ret;
+
+    ret = _stlink_usb_read_unsupported_reg(sl, 0x14, regp);
+    if (ret == -1)
+        return ret;
+
+    ret = _stlink_usb_read_unsupported_reg(sl, 0x21, regp);
+    if (ret == -1)
+        return ret;
 
     for (int i = 0; i < 32; i++) {
-        _stlink_usb_read_unsupported_reg(sl, 0x40+i, regp);
+        ret = _stlink_usb_read_unsupported_reg(sl, 0x40+i, regp);
+        if (ret == -1)
+            return ret;
     }
+
+    return 0;
 }
 
 /* See section C1.6 of the ARMv7-M Architecture Reference Manual */
-void _stlink_usb_write_unsupported_reg(stlink_t *sl, uint32_t val, int r_idx, reg *regp) {
+int _stlink_usb_write_unsupported_reg(stlink_t *sl, uint32_t val, int r_idx, reg *regp) {
+    int ret;
+
     if (r_idx >= 0x1C && r_idx <= 0x1F) { /* primask, basepri, faultmask, or control */
         /* These are held in the same register */
-        _stlink_usb_read_unsupported_reg(sl, 0x14, regp);
+        ret = _stlink_usb_read_unsupported_reg(sl, 0x14, regp);
+        if (ret == -1)
+            return ret;
 
         val = (uint8_t) (val>>24);
 
@@ -581,17 +647,19 @@ void _stlink_usb_write_unsupported_reg(stlink_t *sl, uint32_t val, int r_idx, re
 
     write_uint32(sl->q_buf, val);
 
-    _stlink_usb_write_mem32(sl, DCRDR, 4);
+    ret = _stlink_usb_write_mem32(sl, DCRDR, 4);
+    if (ret == -1)
+        return ret;
 
     sl->q_buf[0] = (unsigned char) r_idx;
     sl->q_buf[1] = 0;
     sl->q_buf[2] = 0x01;
     sl->q_buf[3] = 0;
 
-    _stlink_usb_write_mem32(sl, DCRSR, 4);
+    return _stlink_usb_write_mem32(sl, DCRSR, 4);
 }
 
-void _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int idx) {
+int _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int idx) {
     struct stlink_libusb * const slu = sl->backend_data;
     unsigned char* const data = sl->q_buf;
     unsigned char* const cmd  = sl->c_buf;
@@ -606,10 +674,12 @@ void _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int idx) {
     size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
     if (size == -1) {
         printf("[!] send_recv\n");
-        return;
+        return size;
     }
     sl->q_len = (size_t) size;
     stlink_print_data(sl);
+
+    return 0;
 }
 
 stlink_backend_t _stlink_usb_backend = {