sl->q_data_dir = Q_DATA_IN;
}
-// E.g. make the valgrind happy.
-
-static void clear_buf(stlink_t *sl) {
- DLOG("*** clear_buf ***\n");
- for (size_t i = 0; i < sizeof (sl->q_buf); i++)
- sl->q_buf[i] = 0;
-
-}
-
// close the device, free the allocated memory
void _stlink_sg_close(stlink_t *sl) {
}
}
-
-//TODO rewrite/cleanup, save the error in sl
-
-#if FINISHED_WITH_SG
-static void stlink_confirm_inq(stlink_t *stl, struct sg_pt_base *ptvp) {
- struct stlink_libsg *sl = stl->backend_data;
- const int e = sl->do_scsi_pt_err;
- if (e < 0) {
- fprintf(stderr, "scsi_pt error: pass through os error: %s\n",
- safe_strerror(-e));
- return;
- } else if (e == SCSI_PT_DO_BAD_PARAMS) {
- fprintf(stderr, "scsi_pt error: bad pass through setup\n");
- return;
- } else if (e == SCSI_PT_DO_TIMEOUT) {
- fprintf(stderr, " pass through timeout\n");
- return;
+static int get_usb_mass_storage_status(libusb_device_handle *handle, uint8_t endpoint, uint32_t *tag)
+{
+ unsigned char csw[13];
+ memset(csw, 0, sizeof(csw));
+ int transferred;
+ int ret;
+ int try = 0;
+ do {
+ ret = libusb_bulk_transfer(handle, endpoint, (unsigned char *)&csw, sizeof(csw),
+ &transferred, SG_TIMEOUT_MSEC);
+ if (ret == LIBUSB_ERROR_PIPE) {
+ libusb_clear_halt(handle, endpoint);
+ }
+ try++;
+ } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3));
+ if (ret != LIBUSB_SUCCESS) {
+ fprintf(stderr, "%s: receiving failed: %d\n", __func__, ret);
+ return -1;
+ }
+ if (transferred != sizeof(csw)) {
+ fprintf(stderr, "%s: received unexpected amount: %d\n", __func__, transferred);
+ return -1;
}
- const int duration = get_scsi_pt_duration_ms(ptvp);
- if ((stl->verbose > 1) && (duration >= 0))
- DLOG(" duration=%d ms\n", duration);
-
- // XXX stlink fw sends broken residue, so ignore it and use the known q_len
- // "usb-storage quirks=483:3744:r"
- // forces residue to be ignored and calculated, but this causes aboard if
- // data_len = 0 and by some other data_len values.
-
- const int resid = get_scsi_pt_resid(ptvp);
- const int dsize = stl->q_len - resid;
-
- const int cat = get_scsi_pt_result_category(ptvp);
- char buf[512];
- unsigned int slen;
- switch (cat) {
- case SCSI_PT_RESULT_GOOD:
- if (stl->verbose && (resid > 0))
- DLOG(" notice: requested %d bytes but "
- "got %d bytes, ignore [broken] residue = %d\n",
- stl->q_len, dsize, resid);
- break;
- case SCSI_PT_RESULT_STATUS:
- if (stl->verbose) {
- sg_get_scsi_status_str(
- get_scsi_pt_status_response(ptvp), sizeof (buf),
- buf);
- DLOG(" scsi status: %s\n", buf);
- }
- return;
- case SCSI_PT_RESULT_SENSE:
- slen = get_scsi_pt_sense_len(ptvp);
- if (stl->verbose) {
- sg_get_sense_str("", sl->sense_buf, slen, (stl->verbose
- > 1), sizeof (buf), buf);
- DLOG("%s", buf);
- }
- if (stl->verbose && (resid > 0)) {
- if ((stl->verbose) || (stl->q_len > 0))
- DLOG(" requested %d bytes but "
- "got %d bytes\n", stl->q_len, dsize);
- }
- return;
- case SCSI_PT_RESULT_TRANSPORT_ERR:
- if (stl->verbose) {
- get_scsi_pt_transport_err_str(ptvp, sizeof (buf), buf);
- // http://tldp.org/HOWTO/SCSI-Generic-HOWTO/x291.html
- // These codes potentially come from the firmware on a host adapter
- // or from one of several hosts that an adapter driver controls.
- // The 'host_status' field has the following values:
- // [0x07] Internal error detected in the host adapter.
- // This may not be fatal (and the command may have succeeded).
- DLOG(" transport: %s", buf);
- }
- return;
- case SCSI_PT_RESULT_OS_ERR:
- if (stl->verbose) {
- get_scsi_pt_os_err_str(ptvp, sizeof (buf), buf);
- DLOG(" os: %s", buf);
- }
- return;
- default:
- fprintf(stderr, " unknown pass through result "
- "category (%d)\n", cat);
+ uint32_t rsig = read_uint32(csw, 0);
+ uint32_t rtag = read_uint32(csw, 4);
+ uint32_t residue = read_uint32(csw, 8);
+#define USB_CSW_SIGNATURE 0x53425355 // 'U' 'S' 'B' 'S' (reversed)
+ if (rsig != USB_CSW_SIGNATURE) {
+ WLOG("status signature was invalid: %#x\n", rsig);
+ return -1;
}
+ DLOG("residue was= %#x\n", residue);
+ *tag = rtag;
+ uint8_t rstatus = csw[12];
+ DLOG("rstatus = %x\n", rstatus);
+ return rstatus;
}
-#endif
static int dump_CDB_command(uint8_t *cdb, uint8_t cdb_len) {
char dbugblah[100];
}
-static int get_usb_mass_storage_status(libusb_device_handle *handle, uint8_t endpoint, uint32_t *tag)
-{
- unsigned char csw[13];
- memset(csw, 0, sizeof(csw));
- int transferred;
- int ret;
- int try = 0;
- do {
- ret = libusb_bulk_transfer(handle, endpoint, (unsigned char *)&csw, sizeof(csw),
- &transferred, SG_TIMEOUT_MSEC);
- if (ret == LIBUSB_ERROR_PIPE) {
- libusb_clear_halt(handle, endpoint);
- }
- try++;
- } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3));
- if (ret != LIBUSB_SUCCESS) {
- fprintf(stderr, "%s: receiving failed: %d\n", __func__, ret);
- return -1;
- }
- if (transferred != sizeof(csw)) {
- fprintf(stderr, "%s: received unexpected amount: %d\n", __func__, transferred);
- return -1;
- }
-
- uint32_t rsig = read_uint32(csw, 0);
- uint32_t rtag = read_uint32(csw, 4);
- uint32_t residue = read_uint32(csw, 8);
-#define USB_CSW_SIGNATURE 0x53425355 // 'U' 'S' 'B' 'S' (reversed)
- if (rsig != USB_CSW_SIGNATURE) {
- WLOG("status signature was invalid: %#x\n", rsig);
- return -1;
- }
- DLOG("residue was= %#x\n", residue);
- *tag = rtag;
- uint8_t rstatus = csw[12];
- DLOG("rstatus = %x\n", rstatus);
- return rstatus;
-}
-
/**
* Straight from stm8 stlink code...
* @param handle
}
}
+
+//TODO rewrite/cleanup, save the error in sl
+
+#if FINISHED_WITH_SG
+static void stlink_confirm_inq(stlink_t *stl, struct sg_pt_base *ptvp) {
+ struct stlink_libsg *sl = stl->backend_data;
+ const int e = sl->do_scsi_pt_err;
+ if (e < 0) {
+ fprintf(stderr, "scsi_pt error: pass through os error: %s\n",
+ safe_strerror(-e));
+ return;
+ } else if (e == SCSI_PT_DO_BAD_PARAMS) {
+ fprintf(stderr, "scsi_pt error: bad pass through setup\n");
+ return;
+ } else if (e == SCSI_PT_DO_TIMEOUT) {
+ fprintf(stderr, " pass through timeout\n");
+ return;
+ }
+ const int duration = get_scsi_pt_duration_ms(ptvp);
+ if ((stl->verbose > 1) && (duration >= 0))
+ DLOG(" duration=%d ms\n", duration);
+
+ // XXX stlink fw sends broken residue, so ignore it and use the known q_len
+ // "usb-storage quirks=483:3744:r"
+ // forces residue to be ignored and calculated, but this causes aboard if
+ // data_len = 0 and by some other data_len values.
+
+ const int resid = get_scsi_pt_resid(ptvp);
+ const int dsize = stl->q_len - resid;
+
+ const int cat = get_scsi_pt_result_category(ptvp);
+ char buf[512];
+ unsigned int slen;
+
+ switch (cat) {
+ case SCSI_PT_RESULT_GOOD:
+ if (stl->verbose && (resid > 0))
+ DLOG(" notice: requested %d bytes but "
+ "got %d bytes, ignore [broken] residue = %d\n",
+ stl->q_len, dsize, resid);
+ break;
+ case SCSI_PT_RESULT_STATUS:
+ if (stl->verbose) {
+ sg_get_scsi_status_str(
+ get_scsi_pt_status_response(ptvp), sizeof (buf),
+ buf);
+ DLOG(" scsi status: %s\n", buf);
+ }
+ return;
+ case SCSI_PT_RESULT_SENSE:
+ slen = get_scsi_pt_sense_len(ptvp);
+ if (stl->verbose) {
+ sg_get_sense_str("", sl->sense_buf, slen, (stl->verbose
+ > 1), sizeof (buf), buf);
+ DLOG("%s", buf);
+ }
+ if (stl->verbose && (resid > 0)) {
+ if ((stl->verbose) || (stl->q_len > 0))
+ DLOG(" requested %d bytes but "
+ "got %d bytes\n", stl->q_len, dsize);
+ }
+ return;
+ case SCSI_PT_RESULT_TRANSPORT_ERR:
+ if (stl->verbose) {
+ get_scsi_pt_transport_err_str(ptvp, sizeof (buf), buf);
+ // http://tldp.org/HOWTO/SCSI-Generic-HOWTO/x291.html
+ // These codes potentially come from the firmware on a host adapter
+ // or from one of several hosts that an adapter driver controls.
+ // The 'host_status' field has the following values:
+ // [0x07] Internal error detected in the host adapter.
+ // This may not be fatal (and the command may have succeeded).
+ DLOG(" transport: %s", buf);
+ }
+ return;
+ case SCSI_PT_RESULT_OS_ERR:
+ if (stl->verbose) {
+ get_scsi_pt_os_err_str(ptvp, sizeof (buf), buf);
+ DLOG(" os: %s", buf);
+ }
+ return;
+ default:
+ fprintf(stderr, " unknown pass through result "
+ "category (%d)\n", cat);
+ }
+}
+#endif
+
+/**
+ * Just send a buffer on an endpoint, no questions asked.
+ * Handles repeats, and time outs. Also handles reading status reports and sense
+ * @param handle libusb device *
+ * @param endpoint_out sends
+ * @param endpoint_in used to read status reports back in
+ * @param cbuf what to send
+ * @param length how much to send
+ * @return number of bytes actually sent, or -1 for failures.
+ */
+int send_usb_data_only(libusb_device_handle *handle, unsigned char endpoint_out,
+ unsigned char endpoint_in, unsigned char *cbuf, unsigned int length) {
+ int ret;
+ int real_transferred;
+ int try;
+ do {
+ DLOG("attempting tx...\n");
+ ret = libusb_bulk_transfer(handle, endpoint_out, cbuf, length,
+ &real_transferred, SG_TIMEOUT_MSEC);
+ if (ret == LIBUSB_ERROR_PIPE) {
+ libusb_clear_halt(handle, endpoint_out);
+ }
+ try++;
+ } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3));
+ if (ret != LIBUSB_SUCCESS) {
+ WLOG("sending failed: %d\n", ret);
+ return -1;
+ }
+ DLOG("Actually sent: %d\n", real_transferred);
+
+ // now, swallow up the status, so that things behave nicely...
+ uint32_t received_tag;
+ // -ve is for my errors, 0 is good, +ve is libusb sense status bytes
+ int status = get_usb_mass_storage_status(handle, endpoint_in, &received_tag);
+ if (status < 0) {
+ WLOG("receiving status failed: %d\n", status);
+ return -1;
+ }
+ if (status != 0) {
+ WLOG("receiving status not passed :(: %02x\n", status);
+ }
+ if (status == 1) {
+ get_sense(handle, endpoint_in, endpoint_out);
+ return -1;
+ }
+
+ return real_transferred;
+}
+
+
int stlink_q(stlink_t *sl) {
struct stlink_libsg* sg = sl->backend_data;
//uint8_t cdb_len = 6; // FIXME varies!!!
write_uint32(sg->cdb_cmd_blk + 2, addr);
write_uint16(sg->cdb_cmd_blk + 6, len);
- // data_out 0-len
- sl->q_len = len;
- sg->q_addr = addr;
- sg->q_data_dir = Q_DATA_OUT;
- stlink_q(sl);
+ // this sends the command...
+ send_usb_mass_storage_command(sg->usb_handle, sg->ep_req, sg->cdb_cmd_blk, CDB_SL, 0, 0, 0);
+ // This sends the data...
+ send_usb_data_only(sg->usb_handle, sg->ep_req, sg->ep_rep, sl->q_buf, len);
stlink_print_data(sl);
}
write_uint32(sg->cdb_cmd_blk + 2, addr);
write_uint16(sg->cdb_cmd_blk + 6, len);
- // data_out 0-0x40-...-len
- sl->q_len = len;
- sg->q_addr = addr;
- sg->q_data_dir = Q_DATA_OUT;
- stlink_q(sl);
+ // this sends the command...
+ send_usb_mass_storage_command(sg->usb_handle, sg->ep_req, sg->cdb_cmd_blk, CDB_SL, 0, 0, 0);
+ // This sends the data...
+ send_usb_data_only(sg->usb_handle, sg->ep_req, sg->ep_rep, sl->q_buf, len);
+
stlink_print_data(sl);
}
static stlink_t* stlink_open(const int verbose) {
stlink_t *sl = malloc(sizeof (stlink_t));
+ memset(sl, 0, sizeof(stlink_t));
struct stlink_libsg *slsg = malloc(sizeof (struct stlink_libsg));
if (sl == NULL || slsg == NULL) {
WLOG("Couldn't malloc stlink and stlink_sg structures out of memory!\n");
sl->core_stat = STLINK_CORE_STAT_UNKNOWN;
slsg->q_addr = 0;
- clear_buf(sl);
/* flash memory settings */
sl->flash_base = STM32_FLASH_BASE;
stlink_version(sl);
return sl;
}
-
-static void __attribute__((unused)) mark_buf(stlink_t *sl) {
- clear_buf(sl);
- sl->q_buf[0] = 0x12;
- sl->q_buf[1] = 0x34;
- sl->q_buf[2] = 0x56;
- sl->q_buf[3] = 0x78;
- sl->q_buf[4] = 0x90;
- sl->q_buf[15] = 0x42;
- sl->q_buf[16] = 0x43;
- sl->q_buf[63] = 0x42;
- sl->q_buf[64] = 0x43;
- sl->q_buf[1024 * 6 - 1] = 0x42; //6kB
- sl->q_buf[1024 * 8 - 1] = 0x42; //8kB
-}
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "stlink-common.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)
+
+static void __attribute__((unused)) mark_buf(stlink_t *sl) {
+ memset(sl->q_buf, 0, sizeof(sl->q_buf));
+ sl->q_buf[0] = 0xaa;
+ sl->q_buf[1] = 0xbb;
+ sl->q_buf[2] = 0xcc;
+ sl->q_buf[3] = 0xdd;
+ sl->q_buf[4] = 0x11;
+ sl->q_buf[15] = 0x22;
+ sl->q_buf[16] = 0x33;
+ sl->q_buf[63] = 0x44;
+ sl->q_buf[64] = 0x69;
+ sl->q_buf[1024 * 6 - 1] = 0x42; //6kB
+ sl->q_buf[1024 * 8 - 1] = 0x42; //8kB
+}
+
int main(int argc, char *argv[]) {
// set scpi lib debug level: 0 for no debug info, 10 for lots
//stlink_force_debug(sl);
stlink_reset(sl);
stlink_status(sl);
-#if 0
// core system control block
stlink_read_mem32(sl, 0xe000ed00, 4);
- DD(sl, "cpu id base register: SCB_CPUID = got 0x%08x expect 0x411fc231", read_uint32(sl->q_buf, 0));
+ DLOG("cpu id base register: SCB_CPUID = got 0x%08x expect 0x411fc231\n", read_uint32(sl->q_buf, 0));
// no MPU
stlink_read_mem32(sl, 0xe000ed90, 4);
- DD(sl, "mpu type register: MPU_TYPER = got 0x%08x expect 0x0", read_uint32(sl->q_buf, 0));
+ DLOG("mpu type register: MPU_TYPER = got 0x%08x expect 0x0\n", read_uint32(sl->q_buf, 0));
+#if 0
stlink_read_mem32(sl, 0xe000edf0, 4);
DD(sl, "DHCSR = 0x%08x", read_uint32(sl->q_buf, 0));
#if 0
// sram 0x20000000 8kB
fputs("\n++++++++++ read/write 8bit, sram at 0x2000 0000 ++++++++++++++++\n\n", stderr);
- clear_buf(sl);
+ memset(sl->q_buf, 0, sizeof(sl->q_buf));
+ mark_buf(sl);
stlink_write_mem8(sl, 0x20000000, 16);
- mark_buf(sl);
stlink_write_mem8(sl, 0x20000000, 1);
stlink_write_mem8(sl, 0x20000001, 1);
stlink_write_mem8(sl, 0x2000000b, 3);
#if 0
// a not aligned mem32 access doesn't work indeed
fputs("\n++++++++++ read/write 32bit, sram at 0x2000 0000 ++++++++++++++++\n\n", stderr);
- clear_buf(sl);
- stlink_write_mem8(sl, 0x20000000, 32);
-
+ memset(sl->q_buf, 0, sizeof(sl->q_buf));
mark_buf(sl);
stlink_write_mem32(sl, 0x20000000, 1);
stlink_read_mem32(sl, 0x20000000, 16);
stlink_write_mem32(sl, 0x20000000, 17);
stlink_read_mem32(sl, 0x20000000, 32);
#endif
-#if 0
+#if 1
// sram 0x20000000 8kB
fputs("++++++++++ read/write 32bit, sram at 0x2000 0000 ++++++++++++\n", stderr);
+ memset(sl->q_buf, 0, sizeof(sl->q_buf));
mark_buf(sl);
stlink_write_mem8(sl, 0x20000000, 64);
stlink_read_mem32(sl, 0x20000000, 64);