X-Git-Url: https://git.gag.com/?p=fw%2Fstlink;a=blobdiff_plain;f=src%2Fstlink-usb.c;h=979ba9731bbeb1eee93213a0a8f1d81a756be5fa;hp=5099bfd4f2cd03cdb6a3ef266cd25f3e4cb047a1;hb=c2d09105f5bc00c5d9896ebf3f2a5595005e6d64;hpb=4aa64b2daa46f5a36d8fa10a932833fcf66ee6f6 diff --git a/src/stlink-usb.c b/src/stlink-usb.c index 5099bfd..979ba97 100644 --- a/src/stlink-usb.c +++ b/src/stlink-usb.c @@ -1,13 +1,23 @@ -#include #include #include #include #include #include #include -#include +#include + #include "stlink-common.h" #include "stlink-usb.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) + + +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; @@ -19,8 +29,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 +99,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 +112,161 @@ 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; + if (rxsize != 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; + /* 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) { + fprintf(stderr, "This is never used....\n"); + exit(EXIT_FAILURE); + /* 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) { - struct libusb_device_descriptor desc; - - 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) - return 0; - - 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) { + fprintf(stderr, "This is never used....\n"); + 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, 6); + size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); if (size == -1) { printf("[!] send_recv\n"); return; } +} + +uint32_t _stlink_usb_read_debug32(stlink_t *sl, uint32_t addr) { + struct stlink_libusb * const slu = sl->backend_data; + unsigned char* const rdata = sl->q_buf; + unsigned char* const cmd = sl->c_buf; + ssize_t size; + const int rep_len = 8; + + int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); + cmd[i++] = STLINK_DEBUG_COMMAND; + cmd[i++] = STLINK_JTAG_READDEBUG_32BIT; + write_uint32(&cmd[i], addr); + size = send_recv(slu, 1, cmd, slu->cmd_len, rdata, rep_len); + if (size == -1) { + printf("[!] send_recv\n"); + return 0; + } + return read_uint32(rdata, 4); +} -#if 1 /* DEBUG */ - { - ssize_t i; - for (i = 0; i < size; ++i) printf("%02x", buf[i]); - printf("\n"); +void _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; + ssize_t size; + const int rep_len = 2; + + int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); + cmd[i++] = STLINK_DEBUG_COMMAND; + cmd[i++] = STLINK_JTAG_WRITEDEBUG_32BIT; + write_uint32(&cmd[i], addr); + write_uint32(&cmd[i + 4], data); + size = send_recv(slu, 1, cmd, slu->cmd_len, rdata, rep_len); + if (size == -1) { + printf("[!] send_recv\n"); + return; } -#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; - - 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); + unsigned char* const data = sl->q_buf; + unsigned char* const cmd = sl->c_buf; - 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, 2); + 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 +276,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, 4); + 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, 2); + 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, 2); + 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, 2); + size = send_only(slu, 1, cmd, slu->cmd_len); if (size == -1) { printf("[!] send_recv\n"); return; @@ -299,14 +349,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 +369,36 @@ 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); + + cmd[i++] = STLINK_DEBUG_COMMAND; + cmd[i++] = STLINK_DEBUG_RESETSYS; + + size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); + if (size == -1) { + printf("[!] send_recv\n"); + return; + } +} + + +void _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; 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_JTAG_DRIVE_NRST; + cmd[i++] = (value)?0:1; - 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 +408,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, 2); + size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); if (size == -1) { printf("[!] send_recv\n"); return; @@ -356,31 +430,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, 2); + 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 +464,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) */ - assert(len < sizeof(sl->q_buf)); // makes a compiler warning? always true? - - memset(buf, 0, sizeof (sl->q_buf)); - buf[0] = STLINK_DEBUG_COMMAND; - buf[1] = STLINK_DEBUG_READMEM_32BIT; - write_uint32(buf + 2, addr); - /* windows usb logs show only one byte is used for length ... */ - // Presumably, this is because usb transfers can't be 16 bits worth of bytes long... - assert (len < 256); - buf[6] = (uint8_t) len; + cmd[i++] = STLINK_DEBUG_COMMAND; + cmd[i++] = STLINK_DEBUG_READMEM_32BIT; + write_uint32(&cmd[i], addr); + write_uint16(&cmd[i + 4], len); - size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, len); + size = send_recv(slu, 1, cmd, slu->cmd_len, data, len); if (size == -1) { printf("[!] send_recv\n"); return; @@ -417,15 +487,15 @@ void _stlink_usb_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { 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; @@ -442,25 +512,26 @@ void _stlink_usb_read_all_regs(stlink_t *sl, reg *regp) { if (sl->verbose < 2) return; - DD(sl, "xpsr = 0x%08x\n", read_uint32(sl->q_buf, 64)); - DD(sl, "main_sp = 0x%08x\n", read_uint32(sl->q_buf, 68)); - DD(sl, "process_sp = 0x%08x\n", read_uint32(sl->q_buf, 72)); - DD(sl, "rw = 0x%08x\n", read_uint32(sl->q_buf, 76)); - DD(sl, "rw2 = 0x%08x\n", read_uint32(sl->q_buf, 80)); + 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)); } 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; @@ -468,7 +539,7 @@ void _stlink_usb_read_reg(stlink_t *sl, int r_idx, reg *regp) { sl->q_len = (size_t) size; stlink_print_data(sl); 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: @@ -481,10 +552,10 @@ 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; @@ -493,16 +564,17 @@ void _stlink_usb_read_reg(stlink_t *sl, int r_idx, reg *regp) { 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; @@ -519,10 +591,13 @@ stlink_backend_t _stlink_usb_backend = { _stlink_usb_exit_dfu_mode, _stlink_usb_core_id, _stlink_usb_reset, + _stlink_usb_jtag_reset, _stlink_usb_run, _stlink_usb_status, _stlink_usb_version, + _stlink_usb_read_debug32, _stlink_usb_read_mem32, + _stlink_usb_write_debug32, _stlink_usb_write_mem32, _stlink_usb_write_mem8, _stlink_usb_read_all_regs, @@ -534,55 +609,50 @@ 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; + int error = -1; + libusb_device** devs = NULL; + int config; 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; + ugly_init(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; - - libusb_device** devs = NULL; - libusb_device* dev; - ssize_t i; - ssize_t count; - int config; - - count = libusb_get_device_list(slu->libusb_ctx, &devs); - if (count < 0) { - printf("libusb_get_device_list\n"); - goto on_libusb_error; + if (libusb_init(&(slu->libusb_ctx))) { + WLOG("failed to init libusb context, wrong version of libraries?\n"); + goto on_error; } - - for (i = 0; i < count; ++i) { - dev = devs[i]; - if (is_stlink_device(dev)) break; + + slu->usb_handle = libusb_open_device_with_vid_pid(slu->libusb_ctx, USB_ST_VID, USB_STLINK_32L_PID); + if (slu->usb_handle == NULL) { + WLOG("Couldn't find any ST-Link/V2 devices"); + goto on_error; } - if (i == count) return NULL; - - if (libusb_open(dev, &(slu->usb_handle))) { - printf("libusb_open()\n"); - 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) { + WLOG("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 */ - printf("libusb_get_configuration()\n"); + WLOG("libusb_get_configuration()\n"); goto on_libusb_error; } @@ -590,40 +660,55 @@ stlink_t* stlink_open_usb(const char *dev_name, const int verbose) { printf("setting new configuration (%d -> 1)\n", config); if (libusb_set_configuration(slu->usb_handle, 1)) { /* this may fail for a previous configured device */ - printf("libusb_set_configuration()\n"); + WLOG("libusb_set_configuration() failed\n"); goto on_libusb_error; } } if (libusb_claim_interface(slu->usb_handle, 0)) { - printf("libusb_claim_interface()\n"); + WLOG("libusb_claim_interface() failed\n"); goto on_libusb_error; } slu->req_trans = libusb_alloc_transfer(0); if (slu->req_trans == NULL) { - printf("libusb_alloc_transfer\n"); + WLOG("libusb_alloc_transfer failed\n"); goto on_libusb_error; } slu->rep_trans = libusb_alloc_transfer(0); if (slu->rep_trans == NULL) { - printf("libusb_alloc_transfer\n"); + WLOG("libusb_alloc_transfer failed\n"); goto on_libusb_error; } - + // TODO - could use the scanning techniq from stm8 code here... 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; + // 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); + } + + if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) { + stlink_enter_swd_mode(sl); + } + + stlink_reset(sl); + stlink_load_device_params(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) { @@ -631,12 +716,12 @@ on_libusb_error: return NULL; } - sl->backend = &_stlink_usb_backend; - sl->backend_data = slu; /* success */ return sl; on_error: + if( slu->libusb_ctx) + libusb_exit(slu->libusb_ctx); if (sl != NULL) free(sl); if (slu != NULL) free(slu); return 0;