split jim_jtag_command into multiple handlers
[openocd.git] / src / jtag / jlink.c
index 9677f0e80d54ade44c075a45188a78e7c5081895..9b2326bdb0918a9f3c7614b136bdcf0ea6ccef0c 100644 (file)
@@ -27,8 +27,7 @@
 
 #include "interface.h"
 #include "commands.h"
-
-#include <usb.h>
+#include "usb_common.h"
 
 
 #define VID 0x1366
@@ -82,19 +81,6 @@ static uint8_t usb_emu_result_buffer[JLINK_EMU_RESULT_BUFFER_SIZE];
 /* max speed 12MHz v5.0 jlink */
 #define JLINK_MAX_SPEED 12000
 
-/* External interface functions */
-static int jlink_execute_queue(void);
-static int jlink_speed(int speed);
-static int jlink_speed_div(int speed, int* khz);
-static int jlink_khz(int khz, int *jtag_speed);
-static int jlink_register_commands(struct command_context_s *cmd_ctx);
-static int jlink_init(void);
-static int jlink_quit(void);
-
-/* CLI command handler functions */
-static int jlink_handle_jlink_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-static int jlink_handle_jlink_hw_jtag_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
 /* Queue command functions */
 static void jlink_end_state(tap_state_t state);
 static void jlink_state_move(void);
@@ -138,18 +124,6 @@ static struct jlink* jlink_handle;
 /***************************************************************************/
 /* External interface implementation */
 
-struct jtag_interface jlink_interface =
-{
-       .name = "jlink",
-       .execute_queue = jlink_execute_queue,
-       .speed = jlink_speed,
-       .speed_div = jlink_speed_div,
-       .khz = jlink_khz,
-       .register_commands = jlink_register_commands,
-       .init = jlink_init,
-       .quit = jlink_quit
-};
-
 static void jlink_execute_runtest(struct jtag_command *cmd)
 {
        DEBUG_JTAG_IO("runtest %i cycles, end in %i",
@@ -290,18 +264,6 @@ static int jlink_khz(int khz, int *jtag_speed)
        return ERROR_OK;
 }
 
-static int jlink_register_commands(struct command_context_s *cmd_ctx)
-{
-
-       register_command(cmd_ctx, NULL, "jlink_info",
-               &jlink_handle_jlink_info_command, COMMAND_EXEC,
-               "query jlink info");
-       register_command(cmd_ctx, NULL, "jlink_hw_jtag",
-               &jlink_handle_jlink_hw_jtag_command, COMMAND_EXEC,
-               "set/get jlink hw jtag command version [2 | 3]");
-       return ERROR_OK;
-}
-
 static int jlink_init(void)
 {
        int i;
@@ -630,7 +592,7 @@ static int jlink_get_version_info(void)
        return ERROR_OK;
 }
 
-static int jlink_handle_jlink_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(jlink_handle_jlink_info_command)
 {
        if (jlink_get_version_info() == ERROR_OK)
        {
@@ -641,14 +603,14 @@ static int jlink_handle_jlink_info_command(struct command_context_s *cmd_ctx, ch
        return ERROR_OK;
 }
 
-static int jlink_handle_jlink_hw_jtag_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(jlink_handle_jlink_hw_jtag_command)
 {
-       switch (argc) {
+       switch (CMD_ARGC) {
        case 0:
-               command_print(cmd_ctx, "jlink hw jtag  %i", jlink_hw_jtag_version);
+               command_print(CMD_CTX, "jlink hw jtag  %i", jlink_hw_jtag_version);
                break;
        case 1: {
-               int request_version = atoi(args[0]);
+               int request_version = atoi(CMD_ARGV[0]);
                switch (request_version) {
                case 2: case 3:
                        jlink_hw_jtag_version = request_version;
@@ -665,6 +627,37 @@ static int jlink_handle_jlink_hw_jtag_command(struct command_context_s *cmd_ctx,
        return ERROR_OK;
 }
 
+static const struct command_registration jlink_command_handlers[] = {
+       {
+               .name = "jlink_info",
+               .handler = &jlink_handle_jlink_info_command,
+               .mode = COMMAND_EXEC,
+               .help = "show jlink info",
+       },
+       {
+               .name = "jlink_hw_jtag",
+               .handler = &jlink_handle_jlink_hw_jtag_command,
+               .mode = COMMAND_EXEC,
+               .help = "access J-Link HW JTAG command version",
+               .usage = "[2|3]",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+struct jtag_interface jlink_interface = {
+               .name = "jlink",
+
+               .commands = jlink_command_handlers,
+
+               .execute_queue = &jlink_execute_queue,
+               .speed = &jlink_speed,
+               .speed_div = &jlink_speed_div,
+               .khz = &jlink_khz,
+
+               .init = &jlink_init,
+               .quit = &jlink_quit,
+       };
+
 /***************************************************************************/
 /* J-Link tap functions */
 
@@ -767,15 +760,16 @@ static int jlink_tap_execute(void)
        if (!tap_length)
                return ERROR_OK;
 
-       /* JLink returns an extra NULL in packet when size of in message is a multiple of 64, creates problems with usb comms */
-       /* WARNING This will interfere with tap state counting */
-       while ((TAP_SCAN_BYTES(tap_length)%64) == 0)
+       /* JLink returns an extra NULL in packet when size of incoming
+        * message is a multiple of 64, creates problems with USB comms.
+        * WARNING: This will interfere with tap state counting. */
+       while ((DIV_ROUND_UP(tap_length, 8) % 64) == 0)
        {
                jlink_tap_append_step((tap_get_state() == TAP_RESET)?1:0, 0);
        }
 
        // number of full bytes (plus one if some would be left over)
-       byte_length = TAP_SCAN_BYTES(tap_length);
+       byte_length = DIV_ROUND_UP(tap_length, 8);
 
        bool use_jtag3 = jlink_hw_jtag_version >= 3;
        usb_out_buffer[0] = use_jtag3 ? EMU_CMD_HW_JTAG3 : EMU_CMD_HW_JTAG2;
@@ -812,7 +806,7 @@ static int jlink_tap_execute(void)
                DEBUG_JTAG_IO("pending scan result, length = %d", length);
 
 #ifdef _DEBUG_USB_COMMS_
-               jlink_debug_buffer(buffer, TAP_SCAN_BYTES(length));
+               jlink_debug_buffer(buffer, DIV_ROUND_UP(length, 8));
 #endif
 
                if (jtag_read_buffer(buffer, command) != ERROR_OK)
@@ -831,124 +825,82 @@ static int jlink_tap_execute(void)
        return ERROR_OK;
 }
 
-static struct usb_device* find_jlink_device(void)
-{
-       struct usb_bus *busses;
-       struct usb_bus *bus;
-       struct usb_device *dev;
-
-       usb_find_busses();
-       usb_find_devices();
-
-       busses = usb_get_busses();
-
-       /* find jlink device in usb bus */
-
-       for (bus = busses; bus; bus = bus->next)
-       {
-               for (dev = bus->devices; dev; dev = dev->next)
-               {
-                       if ((dev->descriptor.idVendor == VID) && (dev->descriptor.idProduct == PID)) {
-                               return dev;
-                       }
-               }
-       }
-
-       return NULL;
-}
-
 /*****************************************************************************/
 /* JLink USB low-level functions */
 
 static struct jlink* jlink_usb_open()
 {
-       struct usb_device *dev;
-
-       struct jlink *result;
-
-       result = (struct jlink*) malloc(sizeof(struct jlink));
-
        usb_init();
 
-       if ((dev = find_jlink_device()) == NULL) {
-               free(result);
+       const uint16_t vids[] = { VID, 0 };
+       const uint16_t pids[] = { PID, 0 };
+       struct usb_dev_handle *dev;
+       if (jtag_usb_open(vids, pids, &dev) != ERROR_OK)
                return NULL;
-       }
-
-       result->usb_handle = usb_open(dev);
-
-       if (result->usb_handle)
-       {
 
-               /* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS AREA!!!!!!!!!!!
-                * The behavior of libusb is not completely consistent across Windows, Linux, and Mac OS X platforms.  The actions taken
-                * in the following compiler conditionals may not agree with published documentation for libusb, but were found
-                * to be necessary through trials and tribulations.  Even little tweaks can break one or more platforms, so if you do make changes
-                * test them carefully on all platforms before committing them!
-                */
+       /* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS
+        * AREA!!!!!!!!!!!  The behavior of libusb is not completely
+        * consistent across Windows, Linux, and Mac OS X platforms.
+        * The actions taken in the following compiler conditionals may
+        * not agree with published documentation for libusb, but were
+        * found to be necessary through trials and tribulations.  Even
+        * little tweaks can break one or more platforms, so if you do
+        * make changes test them carefully on all platforms before
+        * committing them!
+        */
 
 #if IS_WIN32 == 0
 
-               usb_reset(result->usb_handle);
+       usb_reset(dev);
 
 #if IS_DARWIN == 0
 
-               int timeout = 5;
-
-               /* reopen jlink after usb_reset
-                * on win32 this may take a second or two to re-enumerate */
-               while ((dev = find_jlink_device()) == NULL)
-               {
-                       usleep(1000);
-                       timeout--;
-                       if (!timeout) {
-                               break;
-                       }
-               }
-
-               if (dev == NULL)
-               {
-                       free(result);
-                       return NULL;
+       int timeout = 5;
+       /* reopen jlink after usb_reset
+        * on win32 this may take a second or two to re-enumerate */
+       int retval;
+       while ((retval = jtag_usb_open(vids, pids, &dev)) != ERROR_OK)
+       {
+               usleep(1000);
+               timeout--;
+               if (!timeout) {
+                       break;
                }
-
-               result->usb_handle = usb_open(dev);
+       }
+       if (ERROR_OK != retval)
+               return NULL;
 #endif
 
 #endif
 
-               if (result->usb_handle)
-               {
-                       /* usb_set_configuration required under win32 */
-                       usb_set_configuration(result->usb_handle, dev->config[0].bConfigurationValue);
-                       usb_claim_interface(result->usb_handle, 0);
+       /* usb_set_configuration required under win32 */
+       struct usb_device *udev = usb_device(dev);
+       usb_set_configuration(dev, udev->config[0].bConfigurationValue);
+       usb_claim_interface(dev, 0);
 
 #if 0
-                       /*
-                        * This makes problems under Mac OS X. And is not needed
-                        * under Windows. Hopefully this will not break a linux build
-                        */
-                       usb_set_altinterface(result->usb_handle, 0);
+       /*
+        * This makes problems under Mac OS X. And is not needed
+        * under Windows. Hopefully this will not break a linux build
+        */
+       usb_set_altinterface(result->usb_handle, 0);
 #endif
-                       struct usb_interface *iface = dev->config->interface;
-                       struct usb_interface_descriptor *desc = iface->altsetting;
-                       for (int i = 0; i < desc->bNumEndpoints; i++)
-                       {
-                               uint8_t epnum = desc->endpoint[i].bEndpointAddress;
-                               bool is_input = epnum & 0x80;
-                               LOG_DEBUG("usb ep %s %02x", is_input ? "in" : "out", epnum);
-                               if (is_input)
-                                       jlink_read_ep = epnum;
-                               else
-                                       jlink_write_ep = epnum;
-                       }
-
-                       return result;
-               }
+       struct usb_interface *iface = udev->config->interface;
+       struct usb_interface_descriptor *desc = iface->altsetting;
+       for (int i = 0; i < desc->bNumEndpoints; i++)
+       {
+               uint8_t epnum = desc->endpoint[i].bEndpointAddress;
+               bool is_input = epnum & 0x80;
+               LOG_DEBUG("usb ep %s %02x", is_input ? "in" : "out", epnum);
+               if (is_input)
+                       jlink_read_ep = epnum;
+               else
+                       jlink_write_ep = epnum;
        }
 
-       free(result);
-       return NULL;
+       struct jlink *result = malloc(sizeof(struct jlink));
+       result->usb_handle = dev;
+       return result;
 }
 
 static void jlink_usb_close(struct jlink *jlink)

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)