- convert all files to unix line-ending
[fw/openocd] / src / jtag / usbprog.c
index 2ff785ab9a26784f752a6051b82c6e80fba0fed6..d0011f0ddfe51b5ec9bf22967b743620bc779374 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2007 by Benedikt Sauter sauter@ixbat.de                 *\r
- *   based on Dominic Rath's amt_jtagaccel.c                               *\r
- *                                                                         *\r
- *   usbprog is a free programming adapter. You can easily install         *\r
- *   different firmware versions from an "online pool" over USB.           *\r
- *   The adapter can be used for programming and debugging AVR and ARM     *\r
- *   processors, as USB to RS232 converter, as JTAG interface or as        *\r
- *   simple I/O interface (5 lines).                                       *\r
- *                                                                         *\r
- *   http://www.embedded-projects.net/usbprog                              *\r
- *                                                                         *\r
- *   This program is free software; you can redistribute it and/or modify  *\r
- *   it under the terms of the GNU General Public License as published by  *\r
- *   the Free Software Foundation; either version 2 of the License, or     *\r
- *   (at your option) any later version.                                   *\r
- *                                                                         *\r
- *   This program is distributed in the hope that it will be useful,       *\r
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
- *   GNU General Public License for more details.                          *\r
- *                                                                         *\r
- *   You should have received a copy of the GNU General Public License     *\r
- *   along with this program; if not, write to the                         *\r
- *   Free Software Foundation, Inc.,                                       *\r
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
- ***************************************************************************/\r
-#ifdef HAVE_CONFIG_H\r
-#include "config.h"\r
-#endif\r
-\r
-#include "replacements.h"\r
-\r
-#include "jtag.h"\r
-#include <usb.h>\r
-\r
-/* system includes */\r
-\r
-#include "log.h"\r
-\r
-#define VID 0x1781\r
-#define PID 0x0c63\r
-\r
-/* Pins at usbprog */\r
-#define TDO_BIT         0\r
-#define TDI_BIT         3\r
-#define TCK_BIT         2\r
-#define TMS_BIT         1\r
-\r
-int usbprog_execute_queue(void);\r
-int usbprog_speed(int speed);\r
-int usbprog_register_commands(struct command_context_s *cmd_ctx);\r
-int usbprog_init(void);\r
-int usbprog_quit(void);\r
-\r
-void usbprog_end_state(enum tap_state state);\r
-void usbprog_state_move(void);\r
-void usbprog_path_move(pathmove_command_t *cmd);\r
-void usbprog_runtest(int num_cycles);\r
-void usbprog_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size);\r
-\r
-jtag_interface_t usbprog_interface =\r
-{\r
-       .name = "usbprog",\r
-       .execute_queue = usbprog_execute_queue,\r
-       .speed = usbprog_speed,\r
-       .register_commands = usbprog_register_commands,\r
-       .init = usbprog_init,\r
-       .quit = usbprog_quit\r
-};\r
-\r
-#define UNKOWN_COMMAND  0x00\r
-#define PORT_DIRECTION  0x01\r
-#define PORT_SET        0x02\r
-#define PORT_GET        0x03\r
-#define PORT_SETBIT     0x04\r
-#define PORT_GETBIT     0x05\r
-#define WRITE_TDI      0x06\r
-#define READ_TDO       0x07\r
-#define WRITE_AND_READ         0x08\r
-#define WRITE_TMS      0x09\r
-#define WRITE_TMS_CHAIN 0x0A\r
-\r
-struct usbprog_jtag\r
-{\r
-       struct usb_dev_handle* usb_handle;\r
-};\r
-\r
-struct usbprog_jtag * usbprog_jtag_handle;\r
-\r
-struct usbprog_jtag* usbprog_jtag_open();\r
-void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag);\r
-void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag);\r
-unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen);\r
-\r
-void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);\r
-void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);\r
-void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);\r
-void usbprog_jtag_write_tms(struct usbprog_jtag *usbprog_jtag, char tms_scan);\r
-\r
-char tms_chain[64];\r
-int tms_chain_index;\r
-void usbprog_jtag_tms_collect(char tms_scan);\r
-void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag);\r
-\r
-void usbprog_write(int tck, int tms, int tdi);\r
-void usbprog_reset(int trst, int srst);\r
-\r
-void usbprog_jtag_set_direction(struct usbprog_jtag *usbprog_jtag, unsigned char direction);\r
-void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag,unsigned char value);\r
-unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag);\r
-void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag,int bit, int value);\r
-int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit);\r
-\r
-int usbprog_speed(int speed)\r
-{\r
-       return ERROR_OK;\r
-}\r
-\r
-int usbprog_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       return ERROR_OK;\r
-}\r
-\r
-int usbprog_execute_queue(void)\r
-{\r
-       jtag_command_t *cmd = jtag_command_queue; /* currently processed command */\r
-       int scan_size;\r
-       enum scan_type type;\r
-       u8 *buffer;\r
-\r
-       while (cmd)\r
-       {\r
-               switch (cmd->type)\r
-               {\r
-                       case JTAG_END_STATE:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("end_state: %i", cmd->cmd.end_state->end_state);\r
-#endif\r
-                               if (cmd->cmd.end_state->end_state != -1)\r
-                                       usbprog_end_state(cmd->cmd.end_state->end_state);\r
-                               break;\r
-                       case JTAG_RESET:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);\r
-#endif\r
-                               if (cmd->cmd.reset->trst == 1)\r
-                               {\r
-                                       cur_state = TAP_TLR;\r
-                               }\r
-                               usbprog_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);\r
-                               break;\r
-                       case JTAG_RUNTEST:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);\r
-#endif\r
-                               if (cmd->cmd.runtest->end_state != -1)\r
-                                       usbprog_end_state(cmd->cmd.runtest->end_state);\r
-                               usbprog_runtest(cmd->cmd.runtest->num_cycles);\r
-                               break;\r
-                       case JTAG_STATEMOVE:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);\r
-#endif\r
-                               if (cmd->cmd.statemove->end_state != -1)\r
-                                       usbprog_end_state(cmd->cmd.statemove->end_state);\r
-                               usbprog_state_move();\r
-                               break;\r
-                       case JTAG_PATHMOVE:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states,\r
-                                       cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);\r
-#endif\r
-                               usbprog_path_move(cmd->cmd.pathmove);\r
-                               break;\r
-                       case JTAG_SCAN:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("scan end in %i", cmd->cmd.scan->end_state);\r
-#endif\r
-                               if (cmd->cmd.scan->end_state != -1)\r
-                                       usbprog_end_state(cmd->cmd.scan->end_state);\r
-                               scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);\r
-                               type = jtag_scan_type(cmd->cmd.scan);\r
-                               usbprog_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);\r
-                               if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)\r
-                                       return ERROR_JTAG_QUEUE_FAILED;\r
-                               if (buffer)\r
-                                       free(buffer);\r
-                               break;\r
-                       case JTAG_SLEEP:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("sleep %i", cmd->cmd.sleep->us);\r
-#endif\r
-                               jtag_sleep(cmd->cmd.sleep->us);\r
-                                       break;\r
-                       default:\r
-                               ERROR("BUG: unknown JTAG command type encountered");\r
-                               exit(-1);\r
-               }\r
-\r
-               cmd = cmd->next;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int usbprog_init(void)\r
-{\r
-       usbprog_jtag_handle = usbprog_jtag_open();\r
-\r
-       tms_chain_index = 0;\r
-       if (usbprog_jtag_handle == 0)\r
-       {\r
-               ERROR("Can't find USB JTAG Interface! Please check connection and permissions.");\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-\r
-       INFO("USB JTAG Interface ready!");\r
-\r
-       usbprog_jtag_init(usbprog_jtag_handle);\r
-       usbprog_reset(0, 0);\r
-       usbprog_write(0, 0, 0);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int usbprog_quit(void)\r
-{\r
-       return ERROR_OK;\r
-}\r
-\r
-/*************** jtag execute commands **********************/\r
-void usbprog_end_state(enum tap_state state)\r
-{\r
-       if (tap_move_map[state] != -1)\r
-               end_state = state;\r
-       else\r
-       {\r
-               ERROR("BUG: %i is not a valid end state", state);\r
-               exit(-1);\r
-       }\r
-}\r
-\r
-void usbprog_state_move(void)\r
-{\r
-       int i = 0, tms = 0;\r
-       u8 tms_scan = TAP_MOVE(cur_state, end_state);\r
-\r
-       usbprog_jtag_write_tms(usbprog_jtag_handle, (char)tms_scan);\r
-       for (i = 0; i < 7; i++)\r
-       {\r
-               tms = (tms_scan >> i) & 1;\r
-       }\r
-\r
-       cur_state = end_state;\r
-}\r
-\r
-void usbprog_path_move(pathmove_command_t *cmd)\r
-{\r
-       int num_states = cmd->num_states;\r
-       int state_count;\r
-\r
-       state_count = 0;\r
-       while (num_states)\r
-       {\r
-               if (tap_transitions[cur_state].low == cmd->path[state_count])\r
-               {\r
-                       //INFO("1");\r
-                       usbprog_write(0, 0, 0);\r
-                       usbprog_write(1, 0, 0);\r
-               }\r
-               else if (tap_transitions[cur_state].high == cmd->path[state_count])\r
-               {\r
-                       //INFO("2");\r
-                       usbprog_write(0, 1, 0);\r
-                       usbprog_write(1, 1, 0);\r
-               }\r
-               else\r
-               {\r
-                       ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[state_count]]);\r
-                       exit(-1);\r
-               }\r
-\r
-               cur_state = cmd->path[state_count];\r
-               state_count++;\r
-               num_states--;\r
-       }\r
-\r
-       end_state = cur_state;\r
-}\r
-\r
-void usbprog_runtest(int num_cycles)\r
-{\r
-       int i;\r
-\r
-       /* only do a state_move when we're not already in RTI */\r
-       if (cur_state != TAP_RTI)\r
-       {\r
-               usbprog_end_state(TAP_RTI);\r
-               usbprog_state_move();\r
-       }\r
-\r
-       /* execute num_cycles */\r
-       if (num_cycles > 0)\r
-       {\r
-               usbprog_jtag_tms_send(usbprog_jtag_handle);\r
-               usbprog_write(0, 0, 0);\r
-       }\r
-       else\r
-       {\r
-               usbprog_jtag_tms_send(usbprog_jtag_handle);\r
-               //INFO("NUM CYCLES %i",num_cycles);\r
-       }\r
-\r
-       for (i = 0; i < num_cycles; i++)\r
-       {\r
-               usbprog_write(1, 0, 0);\r
-               usbprog_write(0, 0, 0);\r
-       }\r
-\r
-       /* finish in end_state */\r
-       /*\r
-       usbprog_end_state(saved_end_state);\r
-       if (cur_state != end_state)\r
-               usbprog_state_move();\r
-       */\r
-}\r
-\r
-void usbprog_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)\r
-{\r
-       enum tap_state saved_end_state = end_state;\r
-\r
-       if (ir_scan)\r
-               usbprog_end_state(TAP_SI);\r
-       else\r
-               usbprog_end_state(TAP_SD);\r
-\r
-       //usbprog_jtag_tms_send(usbprog_jtag_handle);\r
-\r
-       usbprog_state_move();\r
-       usbprog_end_state(saved_end_state);\r
-\r
-       usbprog_jtag_tms_send(usbprog_jtag_handle);\r
-\r
-       if (type == SCAN_OUT)\r
-       {\r
-               usbprog_jtag_write_tdi(usbprog_jtag_handle,buffer, scan_size);\r
-       }\r
-       if (type == SCAN_IN)\r
-       {\r
-               usbprog_jtag_read_tdo(usbprog_jtag_handle,buffer, scan_size);\r
-       }\r
-       if (type == SCAN_IO)\r
-       {\r
-               usbprog_jtag_write_and_read(usbprog_jtag_handle,buffer, scan_size);\r
-       }\r
-\r
-       if (ir_scan)\r
-               cur_state = TAP_PI;\r
-       else\r
-               cur_state = TAP_PD;\r
-\r
-       if (cur_state != end_state)\r
-               usbprog_state_move();\r
-}\r
-\r
-/*************** jtag wrapper functions *********************/\r
-\r
-void usbprog_write(int tck, int tms, int tdi)\r
-{\r
-       unsigned char output_value=0x00;\r
-\r
-       if (tms)\r
-               output_value |= (1<<TMS_BIT);\r
-       if (tdi)\r
-               output_value |= (1<<TDI_BIT);\r
-       if (tck)\r
-               output_value |= (1<<TCK_BIT);\r
-\r
-       usbprog_jtag_write_slice(usbprog_jtag_handle,output_value);\r
-}\r
-\r
-/* (1) assert or (0) deassert reset lines */\r
-void usbprog_reset(int trst, int srst)\r
-{\r
-       DEBUG("trst: %i, srst: %i", trst, srst);\r
-\r
-       if (trst)\r
-               usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 0);\r
-       else\r
-               usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 1);\r
-\r
-       if (srst)\r
-               usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 0);\r
-       else\r
-               usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 1);\r
-}\r
-\r
-/*************** jtag lowlevel functions ********************/\r
-\r
-struct usb_bus *busses;\r
-\r
-struct usbprog_jtag* usbprog_jtag_open()\r
-{\r
-       struct usb_bus *bus;\r
-       struct usb_device *dev;\r
-\r
-       struct usbprog_jtag *tmp;\r
-\r
-       tmp = (struct usbprog_jtag*)malloc(sizeof(struct usbprog_jtag));\r
-\r
-       usb_set_debug(10);\r
-       usb_init();\r
-       usb_find_busses();\r
-       usb_find_devices();\r
-\r
-       busses = usb_get_busses();\r
-\r
-       /* find usbprog_jtag device in usb bus */\r
-\r
-       for (bus = busses; bus; bus = bus->next)\r
-       {\r
-               for (dev = bus->devices; dev; dev = dev->next)\r
-               {\r
-                       /* condition for sucessfully hit (too bad, I only check the vendor id)*/\r
-                       if (dev->descriptor.idVendor == VID && dev->descriptor.idProduct == PID)\r
-                       {\r
-                               tmp->usb_handle = usb_open(dev);\r
-                               usb_set_configuration(tmp->usb_handle, 1);\r
-                               usb_claim_interface(tmp->usb_handle, 0);\r
-                               usb_set_altinterface(tmp->usb_handle, 0);\r
-                               return tmp;\r
-                       }\r
-               }\r
-       }\r
-       return 0;\r
-}\r
-\r
-void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag)\r
-{\r
-       usb_close(usbprog_jtag->usb_handle);\r
-       free(usbprog_jtag);\r
-}\r
-\r
-unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen)\r
-{\r
-       int res = usb_bulk_write(usbprog_jtag->usb_handle, 3, msg,msglen, 100);\r
-       if ((msg[0] == 2) || (msg[0] == 1) || (msg[0] == 4) || (msg[0] == 0) || \\r
-                       (msg[0] == 6) || (msg[0] == 0x0A) || (msg[0] == 9))\r
-               return 1;\r
-       if (res == msglen)\r
-       {\r
-               //INFO("HALLLLOOO %i",(int)msg[0]);\r
-               res =  usb_bulk_read(usbprog_jtag->usb_handle, 0x82, msg, 2, 100);\r
-               if (res > 0)\r
-                       return (unsigned char)msg[1];\r
-               else\r
-                       return -1;\r
-       }\r
-       else\r
-               return -1;\r
-       return 0;\r
-}\r
-\r
-void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag)\r
-{\r
-       usbprog_jtag_set_direction(usbprog_jtag, 0xFE);\r
-}\r
-\r
-void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)\r
-{\r
-       char tmp[64];   /* fastes packet size for usb controller */\r
-       int send_bits, bufindex = 0, fillindex = 0, i, loops;\r
-\r
-       char swap;\r
-       /* 61 byte can be transfered (488 bit) */\r
-\r
-       while (size > 0)\r
-       {\r
-               if (size > 488)\r
-               {\r
-                       send_bits = 488;\r
-                       size = size - 488;\r
-                       loops = 61;\r
-               }\r
-               else\r
-               {\r
-                       send_bits = size;\r
-                       loops = size / 8;\r
-                       loops++;\r
-                       size = 0;\r
-               }\r
-               tmp[0] = WRITE_AND_READ;\r
-               tmp[1] = (char)(send_bits >> 8);        /* high */\r
-               tmp[2] = (char)(send_bits);                     /* low */\r
-               i = 0;\r
-\r
-               for (i = 0; i < loops; i++)\r
-               {\r
-                       tmp[3 + i] = buffer[bufindex];\r
-                       bufindex++;\r
-               }\r
-\r
-               if (usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000) == 64)\r
-               {\r
-                       //INFO("HALLLLOOO2 %i",(int)tmp[0]);\r
-                       usleep(1);\r
-                       int timeout = 0;\r
-                       while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 1000) < 1)\r
-                       {\r
-                               timeout++;\r
-                               if (timeout > 10)\r
-                                       break;\r
-                       }\r
-\r
-                       for (i = 0; i < loops; i++)\r
-                       {\r
-                               swap =  tmp[3 + i];\r
-                               buffer[fillindex++] = swap;\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)\r
-{\r
-       char tmp[64];   /* fastes packet size for usb controller */\r
-       int send_bits, fillindex = 0, i, loops;\r
-\r
-       char swap;\r
-       /* 61 byte can be transfered (488 bit) */\r
-\r
-       while (size > 0)\r
-       {\r
-               if (size > 488)\r
-               {\r
-                       send_bits = 488;\r
-                       size = size - 488;\r
-                       loops = 61;\r
-               }\r
-               else\r
-               {\r
-                       send_bits = size;\r
-                       loops = size / 8;\r
-                       loops++;\r
-                       size = 0;\r
-               }\r
-               tmp[0] = WRITE_AND_READ;\r
-               tmp[1] = (char)(send_bits >> 8);        /* high */\r
-               tmp[2] = (char)(send_bits);                     /* low */\r
-\r
-               usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 3, 1000);\r
-\r
-               //INFO("HALLLLOOO3 %i",(int)tmp[0]);\r
-               int timeout = 0;\r
-               usleep(1);\r
-               while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 10) < 1)\r
-               {\r
-                       timeout++;\r
-                       if (timeout > 10)\r
-                               break;\r
-               }\r
-\r
-               for (i = 0; i < loops; i++)\r
-               {\r
-                       swap = tmp[3 + i];\r
-                       buffer[fillindex++] = swap;\r
-               }\r
-       }\r
-}\r
-\r
-void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)\r
-{\r
-       char tmp[64];   /* fastes packet size for usb controller */\r
-       int send_bits, bufindex = 0, i, loops;\r
-\r
-       /* 61 byte can be transfered (488 bit) */\r
-       while (size > 0)\r
-       {\r
-               if (size > 488)\r
-               {\r
-                       send_bits = 488;\r
-                       size = size - 488;\r
-                       loops = 61;\r
-               }\r
-               else\r
-               {\r
-                       send_bits = size;\r
-                       loops = size/8;\r
-                       //if(loops==0)\r
-                       loops++;\r
-                       size = 0;\r
-               }\r
-               tmp[0] = WRITE_TDI;\r
-               tmp[1] = (char)(send_bits >> 8);        /* high */\r
-               tmp[2] = (char)(send_bits);                     /* low */\r
-               i = 0;\r
-\r
-               for (i = 0; i < loops; i++)\r
-               {\r
-                       tmp[3 + i] = buffer[bufindex];\r
-                       bufindex++;\r
-               }\r
-               usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000);\r
-       }\r
-}\r
-\r
-void usbprog_jtag_write_tms(struct usbprog_jtag *usbprog_jtag, char tms_scan)\r
-{\r
-       usbprog_jtag_tms_collect(tms_scan);\r
-}\r
-\r
-void usbprog_jtag_set_direction(struct usbprog_jtag *usbprog_jtag, unsigned char direction)\r
-{\r
-       char tmp[2];\r
-       tmp[0] = PORT_DIRECTION;\r
-       tmp[1] = (char)direction;\r
-       usbprog_jtag_message(usbprog_jtag, tmp, 2);\r
-}\r
-\r
-void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag,unsigned char value)\r
-{\r
-       char tmp[2];\r
-       tmp[0] = PORT_SET;\r
-       tmp[1] = (char)value;\r
-       usbprog_jtag_message(usbprog_jtag, tmp, 2);\r
-}\r
-\r
-unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag)\r
-{\r
-       char tmp[2];\r
-       tmp[0] = PORT_GET;\r
-       tmp[1] = 0x00;\r
-       return usbprog_jtag_message(usbprog_jtag, tmp, 2);\r
-}\r
-\r
-void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag,int bit, int value)\r
-{\r
-       char tmp[3];\r
-       tmp[0] = PORT_SETBIT;\r
-       tmp[1] = (char)bit;\r
-       if (value == 1)\r
-               tmp[2] = 0x01;\r
-       else\r
-               tmp[2] = 0x00;\r
-       usbprog_jtag_message(usbprog_jtag, tmp, 3);\r
-}\r
-\r
-int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit)\r
-{\r
-       char tmp[2];\r
-       tmp[0] = PORT_GETBIT;\r
-       tmp[1] = (char)bit;\r
-\r
-       if (usbprog_jtag_message(usbprog_jtag, tmp, 2) > 0)\r
-               return 1;\r
-       else\r
-               return 0;\r
-}\r
-\r
-void usbprog_jtag_tms_collect(char tms_scan)\r
-{\r
-       tms_chain[tms_chain_index] = tms_scan;\r
-       tms_chain_index++;\r
-}\r
-\r
-void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag)\r
-{\r
-       int i;\r
-       //INFO("TMS SEND");\r
-       if (tms_chain_index > 0)\r
-       {\r
-               char tmp[tms_chain_index + 2];\r
-               tmp[0] = WRITE_TMS_CHAIN;\r
-               tmp[1] = (char)(tms_chain_index);\r
-               for (i = 0; i < tms_chain_index + 1; i++)\r
-                       tmp[2 + i] = tms_chain[i];\r
-               usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, tms_chain_index + 2, 1000);\r
-               tms_chain_index = 0;\r
-       }\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2007 by Benedikt Sauter sauter@ixbat.de                 *
+ *   based on Dominic Rath's amt_jtagaccel.c                               *
+ *                                                                         *
+ *   usbprog is a free programming adapter. You can easily install         *
+ *   different firmware versions from an "online pool" over USB.           *
+ *   The adapter can be used for programming and debugging AVR and ARM     *
+ *   processors, as USB to RS232 converter, as JTAG interface or as        *
+ *   simple I/O interface (5 lines).                                       *
+ *                                                                         *
+ *   http://www.embedded-projects.net/usbprog                              *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "replacements.h"
+
+#include "jtag.h"
+#include <usb.h>
+
+/* system includes */
+
+#include "log.h"
+
+#define VID 0x1781
+#define PID 0x0c63
+
+/* Pins at usbprog */
+#define TDO_BIT         0
+#define TDI_BIT         3
+#define TCK_BIT         2
+#define TMS_BIT         1
+
+int usbprog_execute_queue(void);
+int usbprog_speed(int speed);
+int usbprog_register_commands(struct command_context_s *cmd_ctx);
+int usbprog_init(void);
+int usbprog_quit(void);
+
+void usbprog_end_state(enum tap_state state);
+void usbprog_state_move(void);
+void usbprog_path_move(pathmove_command_t *cmd);
+void usbprog_runtest(int num_cycles);
+void usbprog_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size);
+
+jtag_interface_t usbprog_interface =
+{
+       .name = "usbprog",
+       .execute_queue = usbprog_execute_queue,
+       .speed = usbprog_speed,
+       .register_commands = usbprog_register_commands,
+       .init = usbprog_init,
+       .quit = usbprog_quit
+};
+
+#define UNKOWN_COMMAND  0x00
+#define PORT_DIRECTION  0x01
+#define PORT_SET        0x02
+#define PORT_GET        0x03
+#define PORT_SETBIT     0x04
+#define PORT_GETBIT     0x05
+#define WRITE_TDI      0x06
+#define READ_TDO       0x07
+#define WRITE_AND_READ         0x08
+#define WRITE_TMS      0x09
+#define WRITE_TMS_CHAIN 0x0A
+
+struct usbprog_jtag
+{
+       struct usb_dev_handle* usb_handle;
+};
+
+struct usbprog_jtag * usbprog_jtag_handle;
+
+struct usbprog_jtag* usbprog_jtag_open();
+void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag);
+void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag);
+unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen);
+
+void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);
+void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);
+void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);
+void usbprog_jtag_write_tms(struct usbprog_jtag *usbprog_jtag, char tms_scan);
+
+char tms_chain[64];
+int tms_chain_index;
+void usbprog_jtag_tms_collect(char tms_scan);
+void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag);
+
+void usbprog_write(int tck, int tms, int tdi);
+void usbprog_reset(int trst, int srst);
+
+void usbprog_jtag_set_direction(struct usbprog_jtag *usbprog_jtag, unsigned char direction);
+void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag,unsigned char value);
+unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag);
+void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag,int bit, int value);
+int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit);
+
+int usbprog_speed(int speed)
+{
+       return ERROR_OK;
+}
+
+int usbprog_register_commands(struct command_context_s *cmd_ctx)
+{
+       return ERROR_OK;
+}
+
+int usbprog_execute_queue(void)
+{
+       jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
+       int scan_size;
+       enum scan_type type;
+       u8 *buffer;
+
+       while (cmd)
+       {
+               switch (cmd->type)
+               {
+                       case JTAG_END_STATE:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
+#endif
+                               if (cmd->cmd.end_state->end_state != -1)
+                                       usbprog_end_state(cmd->cmd.end_state->end_state);
+                               break;
+                       case JTAG_RESET:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+#endif
+                               if (cmd->cmd.reset->trst == 1)
+                               {
+                                       cur_state = TAP_TLR;
+                               }
+                               usbprog_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+                               break;
+                       case JTAG_RUNTEST:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
+#endif
+                               if (cmd->cmd.runtest->end_state != -1)
+                                       usbprog_end_state(cmd->cmd.runtest->end_state);
+                               usbprog_runtest(cmd->cmd.runtest->num_cycles);
+                               break;
+                       case JTAG_STATEMOVE:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
+#endif
+                               if (cmd->cmd.statemove->end_state != -1)
+                                       usbprog_end_state(cmd->cmd.statemove->end_state);
+                               usbprog_state_move();
+                               break;
+                       case JTAG_PATHMOVE:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states,
+                                       cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
+#endif
+                               usbprog_path_move(cmd->cmd.pathmove);
+                               break;
+                       case JTAG_SCAN:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("scan end in %i", cmd->cmd.scan->end_state);
+#endif
+                               if (cmd->cmd.scan->end_state != -1)
+                                       usbprog_end_state(cmd->cmd.scan->end_state);
+                               scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
+                               type = jtag_scan_type(cmd->cmd.scan);
+                               usbprog_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
+                               if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
+                                       return ERROR_JTAG_QUEUE_FAILED;
+                               if (buffer)
+                                       free(buffer);
+                               break;
+                       case JTAG_SLEEP:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("sleep %i", cmd->cmd.sleep->us);
+#endif
+                               jtag_sleep(cmd->cmd.sleep->us);
+                                       break;
+                       default:
+                               ERROR("BUG: unknown JTAG command type encountered");
+                               exit(-1);
+               }
+
+               cmd = cmd->next;
+       }
+
+       return ERROR_OK;
+}
+
+int usbprog_init(void)
+{
+       usbprog_jtag_handle = usbprog_jtag_open();
+
+       tms_chain_index = 0;
+       if (usbprog_jtag_handle == 0)
+       {
+               ERROR("Can't find USB JTAG Interface! Please check connection and permissions.");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       INFO("USB JTAG Interface ready!");
+
+       usbprog_jtag_init(usbprog_jtag_handle);
+       usbprog_reset(0, 0);
+       usbprog_write(0, 0, 0);
+
+       return ERROR_OK;
+}
+
+int usbprog_quit(void)
+{
+       return ERROR_OK;
+}
+
+/*************** jtag execute commands **********************/
+void usbprog_end_state(enum tap_state state)
+{
+       if (tap_move_map[state] != -1)
+               end_state = state;
+       else
+       {
+               ERROR("BUG: %i is not a valid end state", state);
+               exit(-1);
+       }
+}
+
+void usbprog_state_move(void)
+{
+       int i = 0, tms = 0;
+       u8 tms_scan = TAP_MOVE(cur_state, end_state);
+
+       usbprog_jtag_write_tms(usbprog_jtag_handle, (char)tms_scan);
+       for (i = 0; i < 7; i++)
+       {
+               tms = (tms_scan >> i) & 1;
+       }
+
+       cur_state = end_state;
+}
+
+void usbprog_path_move(pathmove_command_t *cmd)
+{
+       int num_states = cmd->num_states;
+       int state_count;
+
+       state_count = 0;
+       while (num_states)
+       {
+               if (tap_transitions[cur_state].low == cmd->path[state_count])
+               {
+                       //INFO("1");
+                       usbprog_write(0, 0, 0);
+                       usbprog_write(1, 0, 0);
+               }
+               else if (tap_transitions[cur_state].high == cmd->path[state_count])
+               {
+                       //INFO("2");
+                       usbprog_write(0, 1, 0);
+                       usbprog_write(1, 1, 0);
+               }
+               else
+               {
+                       ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[state_count]]);
+                       exit(-1);
+               }
+
+               cur_state = cmd->path[state_count];
+               state_count++;
+               num_states--;
+       }
+
+       end_state = cur_state;
+}
+
+void usbprog_runtest(int num_cycles)
+{
+       int i;
+
+       /* only do a state_move when we're not already in RTI */
+       if (cur_state != TAP_RTI)
+       {
+               usbprog_end_state(TAP_RTI);
+               usbprog_state_move();
+       }
+
+       /* execute num_cycles */
+       if (num_cycles > 0)
+       {
+               usbprog_jtag_tms_send(usbprog_jtag_handle);
+               usbprog_write(0, 0, 0);
+       }
+       else
+       {
+               usbprog_jtag_tms_send(usbprog_jtag_handle);
+               //INFO("NUM CYCLES %i",num_cycles);
+       }
+
+       for (i = 0; i < num_cycles; i++)
+       {
+               usbprog_write(1, 0, 0);
+               usbprog_write(0, 0, 0);
+       }
+
+       /* finish in end_state */
+       /*
+       usbprog_end_state(saved_end_state);
+       if (cur_state != end_state)
+               usbprog_state_move();
+       */
+}
+
+void usbprog_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)
+{
+       enum tap_state saved_end_state = end_state;
+
+       if (ir_scan)
+               usbprog_end_state(TAP_SI);
+       else
+               usbprog_end_state(TAP_SD);
+
+       //usbprog_jtag_tms_send(usbprog_jtag_handle);
+
+       usbprog_state_move();
+       usbprog_end_state(saved_end_state);
+
+       usbprog_jtag_tms_send(usbprog_jtag_handle);
+
+       if (type == SCAN_OUT)
+       {
+               usbprog_jtag_write_tdi(usbprog_jtag_handle,buffer, scan_size);
+       }
+       if (type == SCAN_IN)
+       {
+               usbprog_jtag_read_tdo(usbprog_jtag_handle,buffer, scan_size);
+       }
+       if (type == SCAN_IO)
+       {
+               usbprog_jtag_write_and_read(usbprog_jtag_handle,buffer, scan_size);
+       }
+
+       if (ir_scan)
+               cur_state = TAP_PI;
+       else
+               cur_state = TAP_PD;
+
+       if (cur_state != end_state)
+               usbprog_state_move();
+}
+
+/*************** jtag wrapper functions *********************/
+
+void usbprog_write(int tck, int tms, int tdi)
+{
+       unsigned char output_value=0x00;
+
+       if (tms)
+               output_value |= (1<<TMS_BIT);
+       if (tdi)
+               output_value |= (1<<TDI_BIT);
+       if (tck)
+               output_value |= (1<<TCK_BIT);
+
+       usbprog_jtag_write_slice(usbprog_jtag_handle,output_value);
+}
+
+/* (1) assert or (0) deassert reset lines */
+void usbprog_reset(int trst, int srst)
+{
+       DEBUG("trst: %i, srst: %i", trst, srst);
+
+       if (trst)
+               usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 0);
+       else
+               usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 1);
+
+       if (srst)
+               usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 0);
+       else
+               usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 1);
+}
+
+/*************** jtag lowlevel functions ********************/
+
+struct usb_bus *busses;
+
+struct usbprog_jtag* usbprog_jtag_open()
+{
+       struct usb_bus *bus;
+       struct usb_device *dev;
+
+       struct usbprog_jtag *tmp;
+
+       tmp = (struct usbprog_jtag*)malloc(sizeof(struct usbprog_jtag));
+
+       usb_set_debug(10);
+       usb_init();
+       usb_find_busses();
+       usb_find_devices();
+
+       busses = usb_get_busses();
+
+       /* find usbprog_jtag device in usb bus */
+
+       for (bus = busses; bus; bus = bus->next)
+       {
+               for (dev = bus->devices; dev; dev = dev->next)
+               {
+                       /* condition for sucessfully hit (too bad, I only check the vendor id)*/
+                       if (dev->descriptor.idVendor == VID && dev->descriptor.idProduct == PID)
+                       {
+                               tmp->usb_handle = usb_open(dev);
+                               usb_set_configuration(tmp->usb_handle, 1);
+                               usb_claim_interface(tmp->usb_handle, 0);
+                               usb_set_altinterface(tmp->usb_handle, 0);
+                               return tmp;
+                       }
+               }
+       }
+       return 0;
+}
+
+void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag)
+{
+       usb_close(usbprog_jtag->usb_handle);
+       free(usbprog_jtag);
+}
+
+unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen)
+{
+       int res = usb_bulk_write(usbprog_jtag->usb_handle, 3, msg,msglen, 100);
+       if ((msg[0] == 2) || (msg[0] == 1) || (msg[0] == 4) || (msg[0] == 0) || \
+                       (msg[0] == 6) || (msg[0] == 0x0A) || (msg[0] == 9))
+               return 1;
+       if (res == msglen)
+       {
+               //INFO("HALLLLOOO %i",(int)msg[0]);
+               res =  usb_bulk_read(usbprog_jtag->usb_handle, 0x82, msg, 2, 100);
+               if (res > 0)
+                       return (unsigned char)msg[1];
+               else
+                       return -1;
+       }
+       else
+               return -1;
+       return 0;
+}
+
+void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag)
+{
+       usbprog_jtag_set_direction(usbprog_jtag, 0xFE);
+}
+
+void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)
+{
+       char tmp[64];   /* fastes packet size for usb controller */
+       int send_bits, bufindex = 0, fillindex = 0, i, loops;
+
+       char swap;
+       /* 61 byte can be transfered (488 bit) */
+
+       while (size > 0)
+       {
+               if (size > 488)
+               {
+                       send_bits = 488;
+                       size = size - 488;
+                       loops = 61;
+               }
+               else
+               {
+                       send_bits = size;
+                       loops = size / 8;
+                       loops++;
+                       size = 0;
+               }
+               tmp[0] = WRITE_AND_READ;
+               tmp[1] = (char)(send_bits >> 8);        /* high */
+               tmp[2] = (char)(send_bits);                     /* low */
+               i = 0;
+
+               for (i = 0; i < loops; i++)
+               {
+                       tmp[3 + i] = buffer[bufindex];
+                       bufindex++;
+               }
+
+               if (usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000) == 64)
+               {
+                       //INFO("HALLLLOOO2 %i",(int)tmp[0]);
+                       usleep(1);
+                       int timeout = 0;
+                       while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 1000) < 1)
+                       {
+                               timeout++;
+                               if (timeout > 10)
+                                       break;
+                       }
+
+                       for (i = 0; i < loops; i++)
+                       {
+                               swap =  tmp[3 + i];
+                               buffer[fillindex++] = swap;
+                       }
+               }
+       }
+}
+
+void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)
+{
+       char tmp[64];   /* fastes packet size for usb controller */
+       int send_bits, fillindex = 0, i, loops;
+
+       char swap;
+       /* 61 byte can be transfered (488 bit) */
+
+       while (size > 0)
+       {
+               if (size > 488)
+               {
+                       send_bits = 488;
+                       size = size - 488;
+                       loops = 61;
+               }
+               else
+               {
+                       send_bits = size;
+                       loops = size / 8;
+                       loops++;
+                       size = 0;
+               }
+               tmp[0] = WRITE_AND_READ;
+               tmp[1] = (char)(send_bits >> 8);        /* high */
+               tmp[2] = (char)(send_bits);                     /* low */
+
+               usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 3, 1000);
+
+               //INFO("HALLLLOOO3 %i",(int)tmp[0]);
+               int timeout = 0;
+               usleep(1);
+               while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 10) < 1)
+               {
+                       timeout++;
+                       if (timeout > 10)
+                               break;
+               }
+
+               for (i = 0; i < loops; i++)
+               {
+                       swap = tmp[3 + i];
+                       buffer[fillindex++] = swap;
+               }
+       }
+}
+
+void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)
+{
+       char tmp[64];   /* fastes packet size for usb controller */
+       int send_bits, bufindex = 0, i, loops;
+
+       /* 61 byte can be transfered (488 bit) */
+       while (size > 0)
+       {
+               if (size > 488)
+               {
+                       send_bits = 488;
+                       size = size - 488;
+                       loops = 61;
+               }
+               else
+               {
+                       send_bits = size;
+                       loops = size/8;
+                       //if(loops==0)
+                       loops++;
+                       size = 0;
+               }
+               tmp[0] = WRITE_TDI;
+               tmp[1] = (char)(send_bits >> 8);        /* high */
+               tmp[2] = (char)(send_bits);                     /* low */
+               i = 0;
+
+               for (i = 0; i < loops; i++)
+               {
+                       tmp[3 + i] = buffer[bufindex];
+                       bufindex++;
+               }
+               usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000);
+       }
+}
+
+void usbprog_jtag_write_tms(struct usbprog_jtag *usbprog_jtag, char tms_scan)
+{
+       usbprog_jtag_tms_collect(tms_scan);
+}
+
+void usbprog_jtag_set_direction(struct usbprog_jtag *usbprog_jtag, unsigned char direction)
+{
+       char tmp[2];
+       tmp[0] = PORT_DIRECTION;
+       tmp[1] = (char)direction;
+       usbprog_jtag_message(usbprog_jtag, tmp, 2);
+}
+
+void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag,unsigned char value)
+{
+       char tmp[2];
+       tmp[0] = PORT_SET;
+       tmp[1] = (char)value;
+       usbprog_jtag_message(usbprog_jtag, tmp, 2);
+}
+
+unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag)
+{
+       char tmp[2];
+       tmp[0] = PORT_GET;
+       tmp[1] = 0x00;
+       return usbprog_jtag_message(usbprog_jtag, tmp, 2);
+}
+
+void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag,int bit, int value)
+{
+       char tmp[3];
+       tmp[0] = PORT_SETBIT;
+       tmp[1] = (char)bit;
+       if (value == 1)
+               tmp[2] = 0x01;
+       else
+               tmp[2] = 0x00;
+       usbprog_jtag_message(usbprog_jtag, tmp, 3);
+}
+
+int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit)
+{
+       char tmp[2];
+       tmp[0] = PORT_GETBIT;
+       tmp[1] = (char)bit;
+
+       if (usbprog_jtag_message(usbprog_jtag, tmp, 2) > 0)
+               return 1;
+       else
+               return 0;
+}
+
+void usbprog_jtag_tms_collect(char tms_scan)
+{
+       tms_chain[tms_chain_index] = tms_scan;
+       tms_chain_index++;
+}
+
+void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag)
+{
+       int i;
+       //INFO("TMS SEND");
+       if (tms_chain_index > 0)
+       {
+               char tmp[tms_chain_index + 2];
+               tmp[0] = WRITE_TMS_CHAIN;
+               tmp[1] = (char)(tms_chain_index);
+               for (i = 0; i < tms_chain_index + 1; i++)
+                       tmp[2 + i] = tms_chain[i];
+               usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, tms_chain_index + 2, 1000);
+               tms_chain_index = 0;
+       }
+}