From 845abf1d08101d1a297a4c44a3ad629eaed66e31 Mon Sep 17 00:00:00 2001 From: Joerg Wunsch Date: Sun, 14 Jan 2018 23:12:06 +0000 Subject: [PATCH] Submitted by Axel Simon: patch #9033: avrdoper backend uses libhidapi instead of libusb * ser_avrdoper: Add libhidapi implementation * stk500v2.c: Adapt #ifdefs for LIBHIDAPI * avrdude.1: Document change * doc/avrdude.texi: (Dito) git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1414 81a1dc3b-b13d-400b-aceb-764788c761c2 --- ChangeLog | 9 ++ NEWS | 2 + avrdude.1 | 2 +- doc/avrdude.texi | 4 +- ser_avrdoper.c | 299 ++++++++++++++++------------------------------- stk500v2.c | 4 +- 6 files changed, 114 insertions(+), 206 deletions(-) diff --git a/ChangeLog b/ChangeLog index c52cd134..6a2a3b39 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2018-01-15 Joerg Wunsch + + Submitted by Axel Simon: + patch #9033: avrdoper backend uses libhidapi instead of libusb + * ser_avrdoper: Add libhidapi implementation + * stk500v2.c: Adapt #ifdefs for LIBHIDAPI + * avrdude.1: Document change + * doc/avrdude.texi: (Dito) + 2018-01-13 Joerg Wunsch Submitted by David Mosberger-Tang diff --git a/NEWS b/NEWS index 2f1800d5..9aa33d37 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,7 @@ Current: debuggers (JTAGICE3 with firmware 3+, AtmelICE, EDBG, mEDBG) - UPDI support added (AVR8X family) - TPI support for USBtinyISP + - AVR Doper uses libhidapi rather than raw libusb (patch #9033) * New devices supported: @@ -53,6 +54,7 @@ Current: patch #9317: Support atmega64m1 as part patch #9222: Enable silent build patch #8924: Enable TPI for usbtiny + patch #9033: avrdoper backend uses libhidapi instead of libusb * Internals: - New avrdude.conf keyword "family_id", used to verify SIB attributes diff --git a/avrdude.1 b/avrdude.1 index 65fc7b1d..ce1f041f 100644 --- a/avrdude.1 +++ b/avrdude.1 @@ -485,7 +485,7 @@ same method of specifying the port is required there. For the USB programmer "AVR-Doper" running in HID mode, the port must be specified as .Ar avrdoper. -Libusb support is required on Unix but not on Windows. For more +Libhidapi support is required on Unix and Mac OS but not on Windows. For more information about AVR-Doper see http://www.obdev.at/avrusb/avrdoper.html. .Pp For the USBtinyISP, which is a simplicistic device not implementing diff --git a/doc/avrdude.texi b/doc/avrdude.texi index 227399fa..5da36c9c 100644 --- a/doc/avrdude.texi +++ b/doc/avrdude.texi @@ -542,8 +542,8 @@ As the AVRISP mkII device can only be talked to over USB, the very same method of specifying the port is required there. For the USB programmer "AVR-Doper" running in HID mode, the port must -be specified as @var{avrdoper}. Libusb support is required on Unix -but not on Windows. For more information about AVR-Doper see +be specified as @var{avrdoper}. Libhidapi support is required on Unix +and Mac OS but not on Windows. For more information about AVR-Doper see @url{http://www.obdev.at/avrusb/avrdoper.html}. For the USBtinyISP, which is a simplistic device not implementing diff --git a/ser_avrdoper.c b/ser_avrdoper.c index 71080b7c..8eae2c3f 100644 --- a/ser_avrdoper.c +++ b/ser_avrdoper.c @@ -26,7 +26,7 @@ #include "ac_cfg.h" -#if defined(HAVE_LIBUSB) || (defined(WIN32NATIVE) && defined(HAVE_LIBHID)) +#if defined(HAVE_LIBHIDAPI) || (defined(WIN32NATIVE) && defined(HAVE_LIBHID)) #include #include @@ -64,7 +64,102 @@ static int avrdoperRxPosition = 0; /* amount of bytes already consu /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ -#if defined(WIN32NATIVE) && defined(HAVE_LIBHID) +#if defined(HAVE_LIBHIDAPI) + +#include + +/* ------------------------------------------------------------------------- */ + +static int usbOpenDevice(union filedescriptor *fdp, int vendor, char *vendorName, + int product, char *productName, int doReportIDs) +{ + hid_device *dev; + + dev = hid_open(vendor, product, NULL); + if (dev == NULL) + { + avrdude_message(MSG_INFO, "%s: usbOpenDevice(): No device found\n", + progname); + return USB_ERROR_NOTFOUND; + } + fdp->usb.handle = dev; + return USB_ERROR_NONE; +} + +/* ------------------------------------------------------------------------- */ + +static void usbCloseDevice(union filedescriptor *fdp) +{ + hid_device *udev = (hid_device *)fdp->usb.handle; + fdp->usb.handle = NULL; + + if (udev == NULL) + return; + + hid_close(udev); +} + +/* ------------------------------------------------------------------------- */ + +static int usbSetReport(union filedescriptor *fdp, int reportType, char *buffer, int len) +{ + hid_device *udev = (hid_device *)fdp->usb.handle; + int bytesSent = -1; + + switch(reportType){ + case USB_HID_REPORT_TYPE_INPUT: + break; + case USB_HID_REPORT_TYPE_OUTPUT: + bytesSent = hid_write(udev, (unsigned char*) buffer, len); + break; + case USB_HID_REPORT_TYPE_FEATURE: + bytesSent = hid_send_feature_report(udev, (unsigned char*) buffer, len); + break; + } + + if(bytesSent != len){ + if(bytesSent < 0) + avrdude_message(MSG_INFO, "Error sending message: %s\n", hid_error(udev)); + return USB_ERROR_IO; + } + return USB_ERROR_NONE; +} + +/* ------------------------------------------------------------------------- */ + +static int usbGetReport(union filedescriptor *fdp, int reportType, int reportNumber, + char *buffer, int *len) +{ + hid_device *udev = (hid_device *)fdp->usb.handle; + int bytesReceived = -1; + + switch(reportType){ + case USB_HID_REPORT_TYPE_INPUT: + bytesReceived = hid_read_timeout(udev, (unsigned char*) buffer, *len, 300); + break; + case USB_HID_REPORT_TYPE_OUTPUT: + break; + case USB_HID_REPORT_TYPE_FEATURE: + bytesReceived = hid_get_feature_report(udev, (unsigned char*) buffer, *len); + break; + } + if(bytesReceived < 0){ + avrdude_message(MSG_INFO, "Error sending message: %s\n", hid_error(udev)); + return USB_ERROR_IO; + } + *len = bytesReceived; + return USB_ERROR_NONE; +} +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +#else /* !defined(HAVE_LIBHIDAPI) */ + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + #include #include @@ -237,204 +332,6 @@ static int usbGetReport(union filedescriptor *fdp, int reportType, int reportNum return rval == 0 ? USB_ERROR_IO : 0; } -/* ------------------------------------------------------------------------ */ -/* ------------------------------------------------------------------------ */ -/* ------------------------------------------------------------------------ */ - -#else /* !(WIN32NATIVE && HAVE_LIBHID) */ - -/* ------------------------------------------------------------------------ */ -/* ------------------------------------------------------------------------ */ -/* ------------------------------------------------------------------------ */ - -#if defined(HAVE_USB_H) -# include -#elif defined(HAVE_LUSB0_USB_H) -# include -#else -# error "libusb needs either or " -#endif - -/* ------------------------------------------------------------------------- */ - -#define USBRQ_HID_GET_REPORT 0x01 -#define USBRQ_HID_SET_REPORT 0x09 - -static int usesReportIDs; - -/* ------------------------------------------------------------------------- */ - -static int usbGetStringAscii(usb_dev_handle *dev, int index, int langid, char *buf, int buflen) -{ - char buffer[256]; - int rval, i; - - if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, - (USB_DT_STRING << 8) + index, langid, buffer, - sizeof(buffer), 1000)) < 0) - return rval; - if(buffer[1] != USB_DT_STRING) - return 0; - if((unsigned char)buffer[0] < rval) - rval = (unsigned char)buffer[0]; - rval /= 2; - /* lossy conversion to ISO Latin1 */ - for(i=1;i buflen) /* destination buffer overflow */ - break; - buf[i-1] = buffer[2 * i]; - if(buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */ - buf[i-1] = '?'; - } - buf[i-1] = 0; - return i-1; -} - -static int usbOpenDevice(union filedescriptor *fdp, int vendor, char *vendorName, - int product, char *productName, int doReportIDs) -{ - struct usb_bus *bus; - struct usb_device *dev; - usb_dev_handle *handle = NULL; - int errorCode = USB_ERROR_NOTFOUND; - static int didUsbInit = 0; - - if(!didUsbInit){ - usb_init(); - didUsbInit = 1; - } - usb_find_busses(); - usb_find_devices(); - for(bus=usb_get_busses(); bus; bus=bus->next){ - for(dev=bus->devices; dev; dev=dev->next){ - if(dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product){ - char string[256]; - int len; - handle = usb_open(dev); /* we need to open the device in order to query strings */ - if(!handle){ - errorCode = USB_ERROR_ACCESS; - avrdude_message(MSG_INFO, "Warning: cannot open USB device: %s\n", - usb_strerror()); - continue; - } - if(vendorName == NULL && productName == NULL){ /* name does not matter */ - break; - } - /* now check whether the names match: */ - len = usbGetStringAscii(handle, dev->descriptor.iManufacturer, - 0x0409, string, sizeof(string)); - if(len < 0){ - errorCode = USB_ERROR_IO; - avrdude_message(MSG_INFO, "Warning: cannot query manufacturer for device: %s\n", - usb_strerror()); - }else{ - errorCode = USB_ERROR_NOTFOUND; - /* avrdude_message(MSG_INFO, "seen device from vendor ->%s<-\n", string); */ - if(strcmp(string, vendorName) == 0){ - len = usbGetStringAscii(handle, dev->descriptor.iProduct, - 0x0409, string, sizeof(string)); - if(len < 0){ - errorCode = USB_ERROR_IO; - avrdude_message(MSG_INFO, "Warning: cannot query product for device: %s\n", - usb_strerror()); - }else{ - errorCode = USB_ERROR_NOTFOUND; - /* avrdude_message(MSG_INFO, "seen product ->%s<-\n", string); */ - if(strcmp(string, productName) == 0) - break; - } - } - } - usb_close(handle); - handle = NULL; - } - } - if(handle) - break; - } - if(handle != NULL){ - int rval, retries = 3; - if(usb_set_configuration(handle, 1)){ - avrdude_message(MSG_INFO, "Warning: could not set configuration: %s\n", - usb_strerror()); - } - /* now try to claim the interface and detach the kernel HID driver on - * linux and other operating systems which support the call. - */ - while((rval = usb_claim_interface(handle, 0)) != 0 && retries-- > 0){ -#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP - if(usb_detach_kernel_driver_np(handle, 0) < 0){ - avrdude_message(MSG_INFO, "Warning: could not detach kernel HID driver: %s\n", - usb_strerror()); - } -#endif - } - if(rval != 0) - avrdude_message(MSG_INFO, "Warning: could not claim interface\n"); -/* Continue anyway, even if we could not claim the interface. Control transfers - * should still work. - */ - errorCode = 0; - fdp->pfd = (void *)handle; - usesReportIDs = doReportIDs; - } - return errorCode; -} - -/* ------------------------------------------------------------------------- */ - -static void usbCloseDevice(union filedescriptor *fdp) -{ - usb_close((usb_dev_handle *)fdp->pfd); -} - -/* ------------------------------------------------------------------------- */ - -static int usbSetReport(union filedescriptor *fdp, int reportType, char *buffer, int len) -{ - int bytesSent; - - if(!usesReportIDs){ - buffer++; /* skip dummy report ID */ - len--; - } - bytesSent = usb_control_msg((usb_dev_handle *)fdp->pfd, USB_TYPE_CLASS | - USB_RECIP_INTERFACE | USB_ENDPOINT_OUT, USBRQ_HID_SET_REPORT, - reportType << 8 | buffer[0], 0, buffer, len, 5000); - if(bytesSent != len){ - if(bytesSent < 0) - avrdude_message(MSG_INFO, "Error sending message: %s\n", usb_strerror()); - return USB_ERROR_IO; - } - return 0; -} - -/* ------------------------------------------------------------------------- */ - -static int usbGetReport(union filedescriptor *fdp, int reportType, int reportNumber, - char *buffer, int *len) -{ - int bytesReceived, maxLen = *len; - - if(!usesReportIDs){ - buffer++; /* make room for dummy report ID */ - maxLen--; - } - bytesReceived = usb_control_msg((usb_dev_handle *)fdp->pfd, USB_TYPE_CLASS | - USB_RECIP_INTERFACE | USB_ENDPOINT_IN, USBRQ_HID_GET_REPORT, - reportType << 8 | reportNumber, 0, buffer, maxLen, 5000); - if(bytesReceived < 0){ - avrdude_message(MSG_INFO, "Error sending message: %s\n", usb_strerror()); - return USB_ERROR_IO; - } - *len = bytesReceived; - if(!usesReportIDs){ - buffer[-1] = reportNumber; /* add dummy report ID */ - len++; - } - return 0; -} - #endif /* WIN32NATIVE */ /* ------------------------------------------------------------------------ */ @@ -658,4 +555,4 @@ struct serial_device avrdoper_serdev = .flags = SERDEV_FL_NONE, }; -#endif /* defined(HAVE_LIBUSB) || (defined(WIN32NATIVE) && defined(HAVE_LIBHID)) */ +#endif /* defined(HAVE_LIBHIDAPI) || (defined(WIN32NATIVE) && defined(HAVE_LIBHID)) */ diff --git a/stk500v2.c b/stk500v2.c index 0e5ff620..82050d36 100644 --- a/stk500v2.c +++ b/stk500v2.c @@ -1609,11 +1609,11 @@ static int stk500v2_open(PROGRAMMER * pgm, char * port) PDATA(pgm)->pgmtype = PGMTYPE_UNKNOWN; if(strcasecmp(port, "avrdoper") == 0){ -#if defined(HAVE_LIBUSB) || (defined(WIN32NATIVE) && defined(HAVE_LIBHID)) +#if defined(HAVE_LIBHIDAPI) || (defined(WIN32NATIVE) && defined(HAVE_LIBHID)) serdev = &avrdoper_serdev; PDATA(pgm)->pgmtype = PGMTYPE_STK500; #else - avrdude_message(MSG_INFO, "avrdude was compiled without usb support.\n"); + avrdude_message(MSG_INFO, "avrdoper requires avrdude with hid support.\n"); return -1; #endif }