mirror of
https://github.com/mariusgreuel/avrdude.git
synced 2025-09-27 14:35:27 +00:00
Implement the Atmel EDBG/CMSIS-DAP driver protocol for JTAGICE3
(running firmware 3.x) and XplainedPro boards. git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1278 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
157
usb_libusb.c
157
usb_libusb.c
@@ -70,6 +70,7 @@ static int usbdev_open(char * port, union pinfo pinfo, union filedescriptor *fd)
|
||||
usb_dev_handle *udev;
|
||||
char *serno, *cp2;
|
||||
int i;
|
||||
int iface;
|
||||
size_t x;
|
||||
|
||||
/*
|
||||
@@ -151,6 +152,21 @@ static int usbdev_open(char * port, union pinfo pinfo, union filedescriptor *fd)
|
||||
progname, usb_strerror());
|
||||
strcpy(product, "[unnamed product]");
|
||||
}
|
||||
/*
|
||||
* The CMSIS-DAP specification mandates the string
|
||||
* "CMSIS-DAP" must be present somewhere in the
|
||||
* product name string for a device compliant to
|
||||
* that protocol. Use this for the decisision
|
||||
* whether we have to search for a HID interface
|
||||
* below.
|
||||
*/
|
||||
if(strstr(product, "CMSIS-DAP") != NULL)
|
||||
{
|
||||
pinfo.usbinfo.flags |= PINFO_FL_USEHID;
|
||||
/* The JTAGICE3 running the CMSIS-DAP firmware doesn't
|
||||
* use a separate endpoint for event reception. */
|
||||
fd->usb.eep = 0;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr,
|
||||
@@ -186,66 +202,102 @@ static int usbdev_open(char * port, union pinfo pinfo, union filedescriptor *fd)
|
||||
if (usb_set_configuration(udev, dev->config[0].bConfigurationValue))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: usbdev_open(): error setting configuration %d: %s\n",
|
||||
"%s: usbdev_open(): WARNING: failed to set configuration %d: %s\n",
|
||||
progname, dev->config[0].bConfigurationValue,
|
||||
usb_strerror());
|
||||
goto trynext;
|
||||
/* let's hope it has already been configured */
|
||||
// goto trynext;
|
||||
}
|
||||
|
||||
usb_interface = dev->config[0].interface[0].altsetting[0].bInterfaceNumber;
|
||||
if (usb_claim_interface(udev, usb_interface))
|
||||
for (iface = 0; iface < dev->config[0].bNumInterfaces; iface++)
|
||||
{
|
||||
usb_interface = dev->config[0].interface[iface].altsetting[0].bInterfaceNumber;
|
||||
#ifdef LIBUSB_HAS_GET_DRIVER_NP
|
||||
/*
|
||||
* Many Linux systems attach the usbhid driver
|
||||
* by default to any HID-class device. On
|
||||
* those, the driver needs to be detached before
|
||||
* we can claim the interface.
|
||||
*/
|
||||
(void)usb_detach_kernel_driver_np(udev, usb_interface);
|
||||
#endif
|
||||
if (usb_claim_interface(udev, usb_interface))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: usbdev_open(): error claiming interface %d: %s\n",
|
||||
progname, usb_interface, usb_strerror());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pinfo.usbinfo.flags & PINFO_FL_USEHID)
|
||||
{
|
||||
/* only consider an interface that is of class HID */
|
||||
if (dev->config[0].interface[iface].altsetting[0].bInterfaceClass !=
|
||||
USB_CLASS_HID)
|
||||
continue;
|
||||
fd->usb.use_interrupt_xfer = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (iface == dev->config[0].bNumInterfaces)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: usbdev_open(): error claiming interface %d: %s\n",
|
||||
progname, usb_interface, usb_strerror());
|
||||
"%s: usbdev_open(): no usable interface found\n",
|
||||
progname);
|
||||
goto trynext;
|
||||
}
|
||||
|
||||
fd->usb.handle = udev;
|
||||
if (fd->usb.rep == 0)
|
||||
{
|
||||
/* Try finding out what our read endpoint is. */
|
||||
for (i = 0; i < dev->config[0].interface[0].altsetting[0].bNumEndpoints; i++)
|
||||
{
|
||||
int possible_ep = dev->config[0].interface[0].altsetting[0].
|
||||
endpoint[i].bEndpointAddress;
|
||||
/* Try finding out what our read endpoint is. */
|
||||
for (i = 0; i < dev->config[0].interface[iface].altsetting[0].bNumEndpoints; i++)
|
||||
{
|
||||
int possible_ep = dev->config[0].interface[iface].altsetting[0].
|
||||
endpoint[i].bEndpointAddress;
|
||||
|
||||
if ((possible_ep & USB_ENDPOINT_DIR_MASK) != 0)
|
||||
{
|
||||
if (verbose > 1)
|
||||
if ((possible_ep & USB_ENDPOINT_DIR_MASK) != 0)
|
||||
{
|
||||
if (verbose > 1)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: usbdev_open(): using read endpoint 0x%02x\n",
|
||||
progname, possible_ep);
|
||||
}
|
||||
fd->usb.rep = possible_ep;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fd->usb.rep == 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: usbdev_open(): using read endpoint 0x%02x\n",
|
||||
progname, possible_ep);
|
||||
"%s: usbdev_open(): cannot find a read endpoint, using 0x%02x\n",
|
||||
progname, USBDEV_BULK_EP_READ_MKII);
|
||||
fd->usb.rep = USBDEV_BULK_EP_READ_MKII;
|
||||
}
|
||||
fd->usb.rep = possible_ep;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fd->usb.rep == 0)
|
||||
for (i = 0; i < dev->config[0].interface[iface].altsetting[0].bNumEndpoints; i++)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: usbdev_open(): cannot find a read endpoint, using 0x%02x\n",
|
||||
progname, USBDEV_BULK_EP_READ_MKII);
|
||||
fd->usb.rep = USBDEV_BULK_EP_READ_MKII;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < dev->config[0].interface[0].altsetting[0].bNumEndpoints; i++)
|
||||
{
|
||||
if ((dev->config[0].interface[0].altsetting[0].endpoint[i].bEndpointAddress == fd->usb.rep ||
|
||||
dev->config[0].interface[0].altsetting[0].endpoint[i].bEndpointAddress == fd->usb.wep) &&
|
||||
dev->config[0].interface[0].altsetting[0].endpoint[i].wMaxPacketSize < fd->usb.max_xfer)
|
||||
if ((dev->config[0].interface[iface].altsetting[0].endpoint[i].bEndpointAddress == fd->usb.rep ||
|
||||
dev->config[0].interface[iface].altsetting[0].endpoint[i].bEndpointAddress == fd->usb.wep) &&
|
||||
dev->config[0].interface[iface].altsetting[0].endpoint[i].wMaxPacketSize < fd->usb.max_xfer)
|
||||
{
|
||||
if (verbose != 0)
|
||||
fprintf(stderr,
|
||||
"%s: max packet size expected %d, but found %d due to EP 0x%02x's wMaxPacketSize\n",
|
||||
progname,
|
||||
fd->usb.max_xfer,
|
||||
dev->config[0].interface[0].altsetting[0].endpoint[i].wMaxPacketSize,
|
||||
dev->config[0].interface[0].altsetting[0].endpoint[i].bEndpointAddress);
|
||||
fd->usb.max_xfer = dev->config[0].interface[0].altsetting[0].endpoint[i].wMaxPacketSize;
|
||||
dev->config[0].interface[iface].altsetting[0].endpoint[i].wMaxPacketSize,
|
||||
dev->config[0].interface[iface].altsetting[0].endpoint[i].bEndpointAddress);
|
||||
fd->usb.max_xfer = dev->config[0].interface[iface].altsetting[0].endpoint[i].wMaxPacketSize;
|
||||
}
|
||||
}
|
||||
if (pinfo.usbinfo.flags & PINFO_FL_USEHID)
|
||||
{
|
||||
if (usb_control_msg(udev, 0x21, 0x0a /* SET_IDLE */, 0, 0, NULL, 0, 100) < 0)
|
||||
fprintf(stderr, "%s: usbdev_open(): SET_IDLE failed\n", progname);
|
||||
}
|
||||
return 0;
|
||||
trynext:
|
||||
usb_close(udev);
|
||||
@@ -299,7 +351,10 @@ static int usbdev_send(union filedescriptor *fd, unsigned char *bp, size_t mlen)
|
||||
*/
|
||||
do {
|
||||
tx_size = (mlen < fd->usb.max_xfer)? mlen: fd->usb.max_xfer;
|
||||
rv = usb_bulk_write(udev, fd->usb.wep, (char *)bp, tx_size, 10000);
|
||||
if (fd->usb.use_interrupt_xfer)
|
||||
rv = usb_interrupt_write(udev, fd->usb.wep, (char *)bp, tx_size, 10000);
|
||||
else
|
||||
rv = usb_bulk_write(udev, fd->usb.wep, (char *)bp, tx_size, 10000);
|
||||
if (rv != tx_size)
|
||||
{
|
||||
fprintf(stderr, "%s: usbdev_send(): wrote %d out of %d bytes, err = %s\n",
|
||||
@@ -341,16 +396,20 @@ static int usbdev_send(union filedescriptor *fd, unsigned char *bp, size_t mlen)
|
||||
* empty and more data are requested.
|
||||
*/
|
||||
static int
|
||||
usb_fill_buf(usb_dev_handle *udev, int maxsize, int ep)
|
||||
usb_fill_buf(usb_dev_handle *udev, int maxsize, int ep, int use_interrupt_xfer)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = usb_bulk_read(udev, ep, usbbuf, maxsize, 10000);
|
||||
if (use_interrupt_xfer)
|
||||
rv = usb_interrupt_read(udev, ep, usbbuf, maxsize, 10000);
|
||||
else
|
||||
rv = usb_bulk_read(udev, ep, usbbuf, maxsize, 10000);
|
||||
if (rv < 0)
|
||||
{
|
||||
if (verbose > 1)
|
||||
fprintf(stderr, "%s: usb_fill_buf(): usb_bulk_read() error %s\n",
|
||||
progname, usb_strerror());
|
||||
fprintf(stderr, "%s: usb_fill_buf(): usb_%s_read() error %s\n",
|
||||
progname, (use_interrupt_xfer? "interrupt": "bulk"),
|
||||
usb_strerror());
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -370,7 +429,7 @@ static int usbdev_recv(union filedescriptor *fd, unsigned char *buf, size_t nbyt
|
||||
{
|
||||
if (buflen <= bufptr)
|
||||
{
|
||||
if (usb_fill_buf(udev, fd->usb.max_xfer, fd->usb.rep) < 0)
|
||||
if (usb_fill_buf(udev, fd->usb.max_xfer, fd->usb.rep, fd->usb.use_interrupt_xfer) < 0)
|
||||
return -1;
|
||||
}
|
||||
amnt = buflen - bufptr > nbytes? nbytes: buflen - bufptr;
|
||||
@@ -441,13 +500,18 @@ static int usbdev_recv_frame(union filedescriptor *fd, unsigned char *buf, size_
|
||||
n = 0;
|
||||
do
|
||||
{
|
||||
rv = usb_bulk_read(udev, fd->usb.rep, usbbuf,
|
||||
fd->usb.max_xfer, 10000);
|
||||
if (fd->usb.use_interrupt_xfer)
|
||||
rv = usb_interrupt_read(udev, fd->usb.rep, usbbuf,
|
||||
fd->usb.max_xfer, 10000);
|
||||
else
|
||||
rv = usb_bulk_read(udev, fd->usb.rep, usbbuf,
|
||||
fd->usb.max_xfer, 10000);
|
||||
if (rv < 0)
|
||||
{
|
||||
if (verbose > 1)
|
||||
fprintf(stderr, "%s: usbdev_recv_frame(): usb_bulk_read(): %s\n",
|
||||
progname, usb_strerror());
|
||||
fprintf(stderr, "%s: usbdev_recv_frame(): usb_%s_read(): %s\n",
|
||||
progname, (fd->usb.use_interrupt_xfer? "interrupt": "bulk"),
|
||||
usb_strerror());
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -495,7 +559,10 @@ static int usbdev_drain(union filedescriptor *fd, int display)
|
||||
int rv;
|
||||
|
||||
do {
|
||||
rv = usb_bulk_read(udev, fd->usb.rep, usbbuf, fd->usb.max_xfer, 100);
|
||||
if (fd->usb.use_interrupt_xfer)
|
||||
rv = usb_interrupt_read(udev, fd->usb.rep, usbbuf, fd->usb.max_xfer, 100);
|
||||
else
|
||||
rv = usb_bulk_read(udev, fd->usb.rep, usbbuf, fd->usb.max_xfer, 100);
|
||||
if (rv > 0 && verbose >= 4)
|
||||
fprintf(stderr, "%s: usbdev_drain(): flushed %d characters\n",
|
||||
progname, rv);
|
||||
|
Reference in New Issue
Block a user