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:
joerg_wunsch
2014-02-26 17:54:32 +00:00
parent 9b9af4bc68
commit b1c64fbe92
9 changed files with 537 additions and 54 deletions

View File

@@ -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);