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:
parent
b46c10e661
commit
845abf1d08
|
@ -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
2
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
299
ser_avrdoper.c
299
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 <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)) */
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue