@@ -190,6 +190,12 @@ struct jtag_proto_caps_speed_apb {
190190 *to be read, we have multiple buffers to store those before the bitq interface reads them out. */
191191#define IN_BUF_CT 8
192192
193+ /*
194+ * comment from libusb:
195+ * As per the USB 3.0 specs, the current maximum limit for the depth is 7.
196+ */
197+ #define MAX_USB_PORTS 7
198+
193199/*Private data */
194200struct esp_usb_jtag {
195201 struct jtag_libusb_device_handle * usb_device ;
@@ -234,6 +240,9 @@ static struct esp_usb_jtag *priv= &esp_usb_jtag_priv;
234240const char * cmds_string []= {"000" , "001" , "010" , "011" , "100" , "101" , "110" , "111" ,
235241 "srst0" , "srst1" , "flush" , "rsv" , "rep0" , "rep1" , "rep2" , "rep3" };
236242
243+ static int esp_usb_jtag_init (void );
244+ static int esp_usb_jtag_quit (void );
245+
237246static void log_cmds (uint8_t * buf , int ct , int wr )
238247{
239248 fprintf (priv -> logfile , "Wrote %d of %d bytes:%s\n" , wr , ct , wr != ct ? "***ERROR***" : "" );
@@ -269,6 +278,90 @@ static void log_resp(uint8_t *buf, int ct, int recvd)
269278 fflush (priv -> logfile );
270279}
271280
281+ static bool esp_usb_jtag_libusb_location_equal (libusb_device * dev1 , libusb_device * dev2 )
282+ {
283+ if (libusb_get_bus_number (dev1 ) != libusb_get_bus_number (dev2 ))
284+ return false;
285+
286+ #ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
287+ uint8_t port_path1 [MAX_USB_PORTS ], port_path2 [MAX_USB_PORTS ];
288+
289+ int path_len1 = libusb_get_port_numbers (dev1 , port_path1 , MAX_USB_PORTS );
290+ if (path_len1 == LIBUSB_ERROR_OVERFLOW ) {
291+ LOG_WARNING ("cannot determine path to usb device! (more than %i ports in path)\n" ,
292+ MAX_USB_PORTS );
293+ return false;
294+ }
295+
296+ int path_len2 = libusb_get_port_numbers (dev2 , port_path2 , MAX_USB_PORTS );
297+ if (path_len2 == LIBUSB_ERROR_OVERFLOW ) {
298+ LOG_WARNING ("cannot determine path to usb device! (more than %i ports in path)\n" ,
299+ MAX_USB_PORTS );
300+ return false;
301+ }
302+
303+ if (path_len1 != path_len2 )
304+ return false;
305+
306+ for (int i = 0 ; i < path_len1 ; i ++ ) {
307+ if (port_path1 [i ] != port_path2 [i ])
308+ return false;
309+ }
310+ #endif /* HAVE_LIBUSB_GET_PORT_NUMBERS */
311+ if (libusb_get_device_address (dev1 ) != libusb_get_device_address (dev2 ))
312+ return false;
313+ return true;
314+ }
315+
316+ static int esp_usb_jtag_revive_device (struct jtag_libusb_device_handle * usb_device )
317+ {
318+ const uint16_t vids []= {USB_VID , 0 }; /* must be null terminated */
319+ const uint16_t pids []= {USB_PID , 0 }; /* must be null terminated */
320+ libusb_device * cur_dev = libusb_get_device (usb_device );
321+ libusb_device * new_dev = NULL ;
322+ int ret , tries = 5 ;
323+
324+ while (tries -- >= 0 ) {
325+ new_dev = jtag_libusb_find_device (vids , pids , esp_usb_jtag_serial );
326+ if (new_dev ) {
327+ if (esp_usb_jtag_libusb_location_equal (cur_dev , new_dev )) {
328+ /* device is still at the same location on bus and with the same address,
329+ try to reset it */
330+ int rc = jtag_libusb_reset_device (usb_device );
331+ if (rc == LIBUSB_ERROR_NOT_FOUND || rc == LIBUSB_ERROR_NO_DEVICE ) {
332+ /* re-enumeration is necessary */
333+ break ;
334+ }
335+ libusb_unref_device (new_dev );
336+ return rc == 0 ? ERROR_OK : ERROR_WAIT ;
337+ }
338+ break ;
339+ }
340+ jtag_sleep (100000 );
341+ }
342+ if (new_dev == NULL ) {
343+ LOG_ERROR ("esp_usb_jtag: device not found!" );
344+ return ERROR_FAIL ;
345+ }
346+ libusb_unref_device (new_dev );
347+ ret = esp_usb_jtag_quit ();
348+ if (ret != ERROR_OK ) {
349+ LOG_ERROR ("esp_usb_jtag: failed to deinit (%d)" , ret );
350+ return ret ;
351+ }
352+ tries = 5 ;
353+ while (tries -- >= 0 ) {
354+ ret = esp_usb_jtag_init ();
355+ if (ret == ERROR_OK )
356+ break ;
357+ jtag_sleep (100000 );
358+ }
359+ if (ret != ERROR_OK ) {
360+ LOG_ERROR ("esp_usb_jtag: failed to init (%d)" , ret );
361+ return ret ;
362+ }
363+ return ERROR_OK ;
364+ }
272365
273366/*Try to receive from USB endpoint into the current priv->in_buf */
274367static int esp_usb_jtag_recv_buf (void )
@@ -328,6 +421,7 @@ static int esp_usb_jtag_send_buf(void)
328421{
329422 size_t ct = priv -> out_buf_pos_nibbles /2 ;
330423 size_t n = 0 ;
424+
331425 n = jtag_libusb_bulk_write (priv -> usb_device ,
332426 priv -> write_ep ,
333427 ((char * )priv -> out_buf ),
@@ -337,7 +431,12 @@ static int esp_usb_jtag_send_buf(void)
337431 if (priv -> logfile )
338432 log_cmds (priv -> out_buf , ct , n );
339433 if (n != ct ) {
340- LOG_ERROR ("esp_usb_jtag: usb sent only %d out of %d bytes." , (int )n , (int )ct );
434+ LOG_WARNING ("esp_usb_jtag: usb sent only %d out of %d bytes." , (int )n , (int )ct );
435+ int ret = esp_usb_jtag_reenum_device (priv -> usb_device );
436+ if (ret != ERROR_OK ) {
437+ LOG_ERROR ("esp_usb_jtag: failed to re-enum USB device!" );
438+ return ret ;
439+ }
341440 return ERROR_FAIL ;
342441 }
343442 priv -> out_buf_pos_nibbles = 0 ;
@@ -354,59 +453,80 @@ static int esp_usb_jtag_send_buf(void)
354453
355454/*Simply adds a command to the buffer. Is called by the RLE encoding mechanism.
356455 *Also sends the intermediate buffer if there's enough to go into one USB packet. */
357- static void esp_usb_jtag_command_add_raw (int cmd )
456+ static int esp_usb_jtag_command_add_raw (int cmd )
358457{
458+ int ret ;
459+
359460 if ((priv -> out_buf_pos_nibbles & 1 ) == 0 )
360461 priv -> out_buf [priv -> out_buf_pos_nibbles /2 ] = (cmd <<4 );
361462 else
362463 priv -> out_buf [priv -> out_buf_pos_nibbles /2 ] |= cmd ;
363464 priv -> out_buf_pos_nibbles ++ ;
364465
365- if (priv -> out_buf_pos_nibbles == OUT_BUF_SZ * 2 )
366- esp_usb_jtag_send_buf ();
466+ if (priv -> out_buf_pos_nibbles == OUT_BUF_SZ * 2 ) {
467+ ret = esp_usb_jtag_send_buf ();
468+ if (ret != ERROR_OK )
469+ return ret ;
470+ }
367471 if (priv -> out_buf_pos_nibbles %(OUT_EP_SZ * 2 ) == 0 ) {
368- if (priv -> pending_in_bits > (IN_BUF_SZ + priv -> hw_in_fifo_len - 1 ) * 8 )
369- esp_usb_jtag_send_buf ();
472+ if (priv -> pending_in_bits > (IN_BUF_SZ + priv -> hw_in_fifo_len - 1 ) * 8 ) {
473+ ret = esp_usb_jtag_send_buf ();
474+ if (ret != ERROR_OK )
475+ return ret ;
476+ }
370477 }
478+ return ERROR_OK ;
371479}
372480
373481/*Writes a command stream equivalent to writing `cmd` `ct` times. */
374- static void esp_usb_jtag_write_rlestream (int cmd , int ct )
482+ static int esp_usb_jtag_write_rlestream (int cmd , int ct )
375483{
484+ int ret ;
376485 /*Special case: stacking flush commands does not make sense (and may not make the hardware
377486 * very happy) */
378487 if (cmd == CMD_FLUSH )
379488 ct = 1 ;
380489 /*Output previous command and repeat commands */
381- esp_usb_jtag_command_add_raw (cmd );
490+ ret = esp_usb_jtag_command_add_raw (cmd );
491+ if (ret != ERROR_OK )
492+ return ret ;
382493 ct -- ; /*as the previous line already executes the command one time */
383494 while (ct > 0 ) {
384- esp_usb_jtag_command_add_raw (CMD_REP (ct & 3 ));
495+ ret = esp_usb_jtag_command_add_raw (CMD_REP (ct & 3 ));
496+ if (ret != ERROR_OK )
497+ return ret ;
385498 ct >>= 2 ;
386499 }
500+ return ERROR_OK ;
387501}
388502
389503
390504/*Adds a command to the buffer of things to be sent. Transparently handles RLE compression using
391505 *the CMD_REP_x commands */
392- static void esp_usb_jtag_command_add (int cmd )
506+ static int esp_usb_jtag_command_add (int cmd )
393507{
394508 if (cmd == priv -> prev_cmd && priv -> prev_cmd_repct < CMD_REP_MAX_REPS )
395509 priv -> prev_cmd_repct ++ ;
396510 else {
397511 /*We can now write out the previous command plus repeat count. */
398- if (priv -> prev_cmd_repct )
399- esp_usb_jtag_write_rlestream (priv -> prev_cmd , priv -> prev_cmd_repct );
512+ if (priv -> prev_cmd_repct ) {
513+ int ret = esp_usb_jtag_write_rlestream (priv -> prev_cmd , priv -> prev_cmd_repct );
514+ if (ret != ERROR_OK )
515+ return ret ;
516+ }
400517 /*Ready for new command. */
401518 priv -> prev_cmd = cmd ;
402519 priv -> prev_cmd_repct = 1 ;
403520 }
521+ return ERROR_OK ;
404522}
405523
406524/*Called by bitq interface to output a bit on tdi and perhaps read a bit from tdo */
407525static int esp_usb_jtag_out (int tms , int tdi , int tdo_req )
408526{
409- esp_usb_jtag_command_add (CMD_CLK (tdo_req , tdi , tms ));
527+ int ret = esp_usb_jtag_command_add (CMD_CLK (tdo_req , tdi , tms ));
528+ if (ret != ERROR_OK )
529+ return ret ;
410530 if (tdo_req )
411531 priv -> pending_in_bits ++ ;
412532 return ERROR_OK ;
@@ -415,22 +535,30 @@ static int esp_usb_jtag_out(int tms, int tdi, int tdo_req)
415535/*Called by bitq interface to flush all output commands and get returned data ready to read */
416536static int esp_usb_jtag_flush (void )
417537{
538+ int ret ;
418539 /*Make sure last command is written */
419- if (priv -> prev_cmd_repct )
420- esp_usb_jtag_write_rlestream (priv -> prev_cmd , priv -> prev_cmd_repct );
540+ if (priv -> prev_cmd_repct ) {
541+ ret = esp_usb_jtag_write_rlestream (priv -> prev_cmd , priv -> prev_cmd_repct );
542+ if (ret != ERROR_OK )
543+ return ret ;
544+ }
421545 priv -> prev_cmd_repct = 0 ;
422546 /*Flush in buffer */
423- esp_usb_jtag_command_add_raw (CMD_FLUSH );
547+ ret = esp_usb_jtag_command_add_raw (CMD_FLUSH );
548+ if (ret != ERROR_OK )
549+ return ret ;
424550 /*Make sure we have an even amount of commands, as we can't write a nibble by itself. */
425551 if (priv -> out_buf_pos_nibbles & 1 ) {
426552 /*If not, pad with an extra FLUSH */
427- esp_usb_jtag_command_add_raw (CMD_FLUSH );
553+ ret = esp_usb_jtag_command_add_raw (CMD_FLUSH );
554+ if (ret != ERROR_OK )
555+ return ret ;
428556 }
429557 LOG_DEBUG_IO ("esp_usb_jtag: Flush!" );
430558 /*Send off the buffer. */
431- int r = esp_usb_jtag_send_buf ();
432- if (r != ERROR_OK )
433- return r ;
559+ ret = esp_usb_jtag_send_buf ();
560+ if (ret != ERROR_OK )
561+ return ret ;
434562
435563 /*Immediately fetch the response bits. */
436564 while (priv -> pending_in_bits > 0 ) {
@@ -456,8 +584,7 @@ static int esp_usb_jtag_reset(int trst, int srst)
456584 /*ToDo: handle trst using setup commands. Kind-of superfluous, however, as we can also do */
457585 /*a tap reser using tms, and it's also not implemented on other ESP32 chips with external
458586 * JTAG. */
459- esp_usb_jtag_command_add (CMD_RST (srst ));
460- return ERROR_OK ;
587+ return esp_usb_jtag_command_add (CMD_RST (srst ));
461588}
462589
463590/*Called by bitq to see if the IN data already is returned to the host. */
0 commit comments