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
This commit is contained in:
Joerg Wunsch 2018-01-14 23:12:06 +00:00
parent b46c10e661
commit 845abf1d08
6 changed files with 114 additions and 206 deletions

View File

@ -1,3 +1,12 @@
2018-01-15 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
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 <j.gnu@uriah.heep.sax.de>
Submitted by David Mosberger-Tang

2
NEWS
View File

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

View File

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

View File

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

View File

@ -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 <stdio.h>
#include <string.h>
@ -64,7 +64,102 @@ static int avrdoperRxPosition = 0; /* amount of bytes already consu
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
#if defined(WIN32NATIVE) && defined(HAVE_LIBHID)
#if defined(HAVE_LIBHIDAPI)
#include <hidapi/hidapi.h>
/* ------------------------------------------------------------------------- */
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 <windows.h>
#include <setupapi.h>
@ -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 <usb.h>
#elif defined(HAVE_LUSB0_USB_H)
# include <lusb0_usb.h>
#else
# error "libusb needs either <usb.h> or <lusb0_usb.h>"
#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<rval;i++){
if(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)) */

View File

@ -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
}