-/*****************************************************************************/
-/* JLink USB low-level functions */
-
-static struct jlink *jlink_usb_open()
-{
- struct jtag_libusb_device_handle *devh;
- if (jtag_libusb_open(vids, pids, NULL, &devh) != ERROR_OK)
- return NULL;
-
- /* 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
-
- jtag_libusb_reset_device(devh);
-
-#if IS_DARWIN == 0
-
- 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_libusb_open(vids, pids, NULL, &devh)) != ERROR_OK) {
- usleep(1000);
- timeout--;
- if (!timeout)
- break;
- }
- if (ERROR_OK != retval)
- return NULL;
-#endif
-
-#endif
-
- /* usb_set_configuration required under win32 */
- struct jtag_libusb_device *udev = jtag_libusb_get_device(devh);
- jtag_libusb_set_configuration(devh, 0);
- jtag_libusb_claim_interface(devh, 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);
-#endif
-
- /* Use the OB endpoints if the JLink we matched is a Jlink-OB adapter */
- uint16_t matched_pid;
- if (jtag_libusb_get_pid(udev, &matched_pid) == ERROR_OK) {
- if (matched_pid == JLINK_OB_PID) {
- jlink_read_ep = JLINK_OB_WRITE_ENDPOINT;
- jlink_write_ep = JLINK_OB_READ_ENDPOINT;
- }
- }
-
- jtag_libusb_get_endpoints(udev, &jlink_read_ep, &jlink_write_ep);
-
- struct jlink *result = malloc(sizeof(struct jlink));
- result->usb_handle = devh;
- return result;
-}
-
-static void jlink_usb_close(struct jlink *jlink)
-{
- jtag_libusb_close(jlink->usb_handle);
- free(jlink);
-}
-
-/* Send a message and receive the reply. */
-static int jlink_usb_message(struct jlink *jlink, int out_length, int in_length)
-{
- int result;
-
- result = jlink_usb_write(jlink, out_length);
- if (result != out_length) {
- LOG_ERROR("usb_bulk_write failed (requested=%d, result=%d)",
- out_length, result);
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- result = jlink_usb_read(jlink, in_length);
- if (result != in_length) {
- LOG_ERROR("usb_bulk_read failed (requested=%d, result=%d)",
- in_length, result);
- return ERROR_JTAG_DEVICE_ERROR;
- }
- return ERROR_OK;
-}
-
-/* calls the given usb_bulk_* function, allowing for the data to
- * trickle in with some timeouts */
-static int usb_bulk_with_retries(
- int (*f)(jtag_libusb_device_handle *, int, char *, int, int),
- jtag_libusb_device_handle *dev, int ep,
- char *bytes, int size, int timeout)
-{
- int tries = 3, count = 0;
-
- while (tries && (count < size)) {
- int result = f(dev, ep, bytes + count, size - count, timeout);
- if (result > 0)
- count += result;
- else if ((-ETIMEDOUT != result) || !--tries)
- return result;
- }
- return count;
-}
-
-static int wrap_usb_bulk_write(jtag_libusb_device_handle *dev, int ep,
- char *buff, int size, int timeout)
-{
- /* usb_bulk_write() takes const char *buff */
- return jtag_libusb_bulk_write(dev, ep, buff, size, timeout);
-}
-
-static inline int usb_bulk_write_ex(jtag_libusb_device_handle *dev, int ep,
- char *bytes, int size, int timeout)
-{
- return usb_bulk_with_retries(&wrap_usb_bulk_write,
- dev, ep, bytes, size, timeout);
-}
-
-static inline int usb_bulk_read_ex(jtag_libusb_device_handle *dev, int ep,
- char *bytes, int size, int timeout)
-{
- return usb_bulk_with_retries(&jtag_libusb_bulk_read,
- dev, ep, bytes, size, timeout);
-}
-
-/* Write data from out_buffer to USB. */
-static int jlink_usb_write(struct jlink *jlink, int out_length)
-{
- int result;
-
- if (out_length > JLINK_OUT_BUFFER_SIZE) {
- LOG_ERROR("jlink_write illegal out_length=%d (max=%d)",
- out_length, JLINK_OUT_BUFFER_SIZE);
- return -1;
- }
-
- result = usb_bulk_write_ex(jlink->usb_handle, jlink_write_ep,
- (char *)usb_out_buffer, out_length, JLINK_USB_TIMEOUT);
-
- DEBUG_JTAG_IO("jlink_usb_write, out_length = %d, result = %d",
- out_length, result);
-
- jlink_debug_buffer(usb_out_buffer, out_length);
- return result;
-}
-
-/* Read data from USB into in_buffer. */
-static int jlink_usb_read(struct jlink *jlink, int expected_size)
-{
- int result = usb_bulk_read_ex(jlink->usb_handle, jlink_read_ep,
- (char *)usb_in_buffer, expected_size, JLINK_USB_TIMEOUT);
-
- DEBUG_JTAG_IO("jlink_usb_read, result = %d", result);
-
- jlink_debug_buffer(usb_in_buffer, result);
- return result;
-}
-
-/*
- * Send a message and receive the reply - simple messages.
- *
- * @param jlink pointer to driver data
- * @param out_length data length in @c usb_out_buffer
- * @param in_length data length to be read to @c usb_in_buffer
- */
-static int jlink_usb_io(struct jlink *jlink, int out_length, int in_length)
-{
- int result;
-
- result = jlink_usb_write(jlink, out_length);
- if (result != out_length) {
- LOG_ERROR("usb_bulk_write failed (requested=%d, result=%d)",
- out_length, result);
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- result = jlink_usb_read(jlink, in_length);
- if (result != in_length) {
- LOG_ERROR("usb_bulk_read failed (requested=%d, result=%d)",
- in_length, result);
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- /*
- * Section 4.2.4 IN-transaction:
- * read dummy 0-byte packet if transaction size is
- * multiple of 64 bytes but not max. size of 0x8000
- */
- if ((in_length % 64) == 0 && in_length != 0x8000) {
- char dummy_buffer;
- result = usb_bulk_read_ex(jlink->usb_handle, jlink_read_ep,
- &dummy_buffer, 1, JLINK_USB_TIMEOUT);
- if (result != 0) {
- LOG_ERROR("dummy byte read failed");
- return ERROR_JTAG_DEVICE_ERROR;
- }
- }
- return ERROR_OK;
-}
-
-#ifdef _DEBUG_USB_COMMS_
-#define BYTES_PER_LINE 16