jtag_libusb_bulk_read|write: return error code instead of size
[fw/openocd] / src / jtag / drivers / kitprog.c
index 584da8c9482c96a9663988dd04e758faec3673b8..7b339aa0baef715f6b88e7396d47d2f691352370 100644 (file)
@@ -681,7 +681,7 @@ static int kitprog_swd_run_queue(void)
        uint8_t *buffer = kitprog_handle->packet_buffer;
 
        do {
-               LOG_DEBUG("Executing %d queued transactions", pending_transfer_count);
+               LOG_DEBUG_IO("Executing %d queued transactions", pending_transfer_count);
 
                if (queued_retval != ERROR_OK) {
                        LOG_DEBUG("Skipping due to previous errors: %d", queued_retval);
@@ -714,12 +714,10 @@ static int kitprog_swd_run_queue(void)
                                data &= ~CORUNDETECT;
                        }
 
-#if 0
-                       LOG_DEBUG("%s %s reg %x %"PRIx32,
+                       LOG_DEBUG_IO("%s %s reg %x %"PRIx32,
                                        cmd & SWD_CMD_APnDP ? "AP" : "DP",
                                        cmd & SWD_CMD_RnW ? "read" : "write",
                                  (cmd & SWD_CMD_A32) >> 1, data);
-#endif
 
                        buffer[write_count++] = (cmd | SWD_CMD_START | SWD_CMD_PARK) & ~SWD_CMD_STOP;
                        read_count++;
@@ -733,40 +731,47 @@ static int kitprog_swd_run_queue(void)
                        }
                }
 
-               ret = jtag_libusb_bulk_write(kitprog_handle->usb_handle,
-                               BULK_EP_OUT, (char *)buffer, write_count, 0);
-               if (ret > 0) {
-                       queued_retval = ERROR_OK;
-               } else {
+               if (jtag_libusb_bulk_write(kitprog_handle->usb_handle,
+                                          BULK_EP_OUT, (char *)buffer,
+                                          write_count, 0, &ret)) {
                        LOG_ERROR("Bulk write failed");
                        queued_retval = ERROR_FAIL;
                        break;
+               } else {
+                       queued_retval = ERROR_OK;
                }
 
-               /* We use the maximum buffer size here because the KitProg sometimes
-                * doesn't like bulk reads of fewer than 62 bytes. (?!?!)
+               /* KitProg firmware does not send a zero length packet
+                * after the bulk-in transmission of a length divisible by bulk packet
+                * size (64 bytes) as required by the USB specification.
+                * Therefore libusb would wait for continuation of transmission.
+                * Workaround: Limit bulk read size to expected number of bytes
+                * for problematic tranfer sizes. Otherwise use the maximum buffer
+                * size here because the KitProg sometimes doesn't like bulk reads
+                * of fewer than 62 bytes. (?!?!)
                 */
-               ret = jtag_libusb_bulk_read(kitprog_handle->usb_handle,
+               size_t read_count_workaround = SWD_MAX_BUFFER_LENGTH;
+               if (read_count % 64 == 0)
+                       read_count_workaround = read_count;
+
+               if (jtag_libusb_bulk_read(kitprog_handle->usb_handle,
                                BULK_EP_IN | LIBUSB_ENDPOINT_IN, (char *)buffer,
-                               SWD_MAX_BUFFER_LENGTH, 0);
-               if (ret > 0) {
+                               read_count_workaround, 1000, &ret)) {
+                       LOG_ERROR("Bulk read failed");
+                       queued_retval = ERROR_FAIL;
+                       break;
+               } else {
                        /* Handle garbage data by offsetting the initial read index */
                        if ((unsigned int)ret > read_count)
                                read_index = ret - read_count;
                        queued_retval = ERROR_OK;
-               } else {
-                       LOG_ERROR("Bulk read failed");
-                       queued_retval = ERROR_FAIL;
-                       break;
                }
 
                for (int i = 0; i < pending_transfer_count; i++) {
                        if (pending_transfers[i].cmd & SWD_CMD_RnW) {
                                uint32_t data = le_to_h_u32(&buffer[read_index]);
 
-#if 0
-                               LOG_DEBUG("Read result: %"PRIx32, data);
-#endif
+                               LOG_DEBUG_IO("Read result: %"PRIx32, data);
 
                                if (pending_transfers[i].buffer)
                                        *(uint32_t *)pending_transfers[i].buffer = data;
@@ -813,11 +818,16 @@ static void kitprog_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
 
 /*************** jtag lowlevel functions ********************/
 
-static void kitprog_execute_reset(struct jtag_command *cmd)
+static int kitprog_reset(int trst, int srst)
 {
        int retval = ERROR_OK;
 
-       if (cmd->cmd.reset->srst == 1) {
+       if (trst == 1) {
+               LOG_ERROR("KitProg: Interface has no TRST");
+               return ERROR_FAIL;
+       }
+
+       if (srst == 1) {
                retval = kitprog_reset_target();
                /* Since the previous command also disables SWCLK output, we need to send an
                 * SWD bus reset command to re-enable it. For some reason, running
@@ -830,38 +840,7 @@ static void kitprog_execute_reset(struct jtag_command *cmd)
 
        if (retval != ERROR_OK)
                LOG_ERROR("KitProg: Interface reset failed");
-}
-
-static void kitprog_execute_sleep(struct jtag_command *cmd)
-{
-       jtag_sleep(cmd->cmd.sleep->us);
-}
-
-static void kitprog_execute_command(struct jtag_command *cmd)
-{
-       switch (cmd->type) {
-               case JTAG_RESET:
-                       kitprog_execute_reset(cmd);
-                       break;
-               case JTAG_SLEEP:
-                       kitprog_execute_sleep(cmd);
-                       break;
-               default:
-                       LOG_ERROR("BUG: unknown JTAG command type encountered");
-                       exit(-1);
-       }
-}
-
-static int kitprog_execute_queue(void)
-{
-       struct jtag_command *cmd = jtag_command_queue;
-
-       while (cmd != NULL) {
-               kitprog_execute_command(cmd);
-               cmd = cmd->next;
-       }
-
-       return ERROR_OK;
+       return retval;
 }
 
 COMMAND_HANDLER(kitprog_handle_info_command)
@@ -882,13 +861,11 @@ COMMAND_HANDLER(kitprog_handle_acquire_psoc_command)
 COMMAND_HANDLER(kitprog_handle_serial_command)
 {
        if (CMD_ARGC == 1) {
-               size_t len = strlen(CMD_ARGV[0]);
-               kitprog_serial = calloc(len + 1, sizeof(char));
+               kitprog_serial = strdup(CMD_ARGV[0]);
                if (kitprog_serial == NULL) {
                        LOG_ERROR("Failed to allocate memory for the serial number");
                        return ERROR_FAIL;
                }
-               strncpy(kitprog_serial, CMD_ARGV[0], len + 1);
        } else {
                LOG_ERROR("expected exactly one argument to kitprog_serial <serial-number>");
                return ERROR_FAIL;
@@ -957,12 +934,14 @@ static const struct swd_driver kitprog_swd = {
 
 static const char * const kitprog_transports[] = { "swd", NULL };
 
-struct jtag_interface kitprog_interface = {
+struct adapter_driver kitprog_adapter_driver = {
        .name = "kitprog",
-       .commands = kitprog_command_handlers,
        .transports = kitprog_transports,
-       .swd = &kitprog_swd,
-       .execute_queue = kitprog_execute_queue,
+       .commands = kitprog_command_handlers,
+
        .init = kitprog_init,
-       .quit = kitprog_quit
+       .quit = kitprog_quit,
+       .reset = kitprog_reset,
+
+       .swd_ops = &kitprog_swd,
 };