summaryrefslogtreecommitdiffstats
path: root/flasher/usb-libusb.c
diff options
context:
space:
mode:
Diffstat (limited to 'flasher/usb-libusb.c')
-rw-r--r--flasher/usb-libusb.c203
1 files changed, 203 insertions, 0 deletions
diff --git a/flasher/usb-libusb.c b/flasher/usb-libusb.c
new file mode 100644
index 0000000..c0bd2a1
--- /dev/null
+++ b/flasher/usb-libusb.c
@@ -0,0 +1,203 @@
+/* Name: usb-libusb.c
+ * Project: usbcalls library
+ * Author: Christian Starkjohann
+ * Creation Date: 2006-02-02
+ * Tabsize: 4
+ * Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: Proprietary, free under certain conditions. See Documentation.
+ * This Revision: $Id$
+ */
+
+/*
+General Description:
+This module implements USB HID report receiving/sending based on libusb. It
+does not read and parse the report descriptor. You must therefore be careful
+to pass correctly formatted data blocks of correct size. In order to be
+compatible with the Windows implementation, we add a zero report ID for all
+reports which don't have an ID. Since we don't parse the descriptor, the caller
+must tell us whether report IDs are used or not in usbOpenDevice().
+
+The implementation of dummy report IDs is a hack. Whether they are used is
+stored in a global variable, not in the device structure (just laziness, don't
+want to allocate memory for that). If you open more than one device and the
+devices differ in report ID usage, you must change the code.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <usb.h>
+
+#define usbDevice usb_dev_handle /* use libusb's device structure */
+#include "usbcalls.h"
+
+/* ------------------------------------------------------------------------- */
+
+#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;
+}
+
+int usbOpenDevice(usbDevice_t **device, int vendor, char *vendorName, int product, char *productName, int _usesReportIDs)
+{
+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;
+ fprintf(stderr, "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;
+ fprintf(stderr, "Warning: cannot query manufacturer for device: %s\n", usb_strerror());
+ }else{
+ errorCode = USB_ERROR_NOTFOUND;
+ /* fprintf(stderr, "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;
+ fprintf(stderr, "Warning: cannot query product for device: %s\n", usb_strerror());
+ }else{
+ errorCode = USB_ERROR_NOTFOUND;
+ /* fprintf(stderr, "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)){
+ fprintf(stderr, "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){
+ fprintf(stderr, "Warning: could not detach kernel HID driver: %s\n", usb_strerror());
+ }
+#endif
+ }
+#ifndef __APPLE__
+ if(rval != 0)
+ fprintf(stderr, "Warning: could not claim interface\n");
+#endif
+/* Continue anyway, even if we could not claim the interface. Control transfers
+ * should still work.
+ */
+ errorCode = 0;
+ *device = handle;
+ usesReportIDs = _usesReportIDs;
+ }
+ return errorCode;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void usbCloseDevice(usbDevice_t *device)
+{
+ if(device != NULL)
+ usb_close(device);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int usbSetReport(usbDevice_t *device, int reportType, char *buffer, int len)
+{
+int bytesSent;
+
+ if(!usesReportIDs){
+ buffer++; /* skip dummy report ID */
+ len--;
+ }
+ bytesSent = usb_control_msg(device, 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)
+ fprintf(stderr, "Error sending message: %s\n", usb_strerror());
+ return USB_ERROR_IO;
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int usbGetReport(usbDevice_t *device, 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(device, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_ENDPOINT_IN, USBRQ_HID_GET_REPORT, reportType << 8 | reportNumber, 0, buffer, maxLen, 5000);
+ if(bytesReceived < 0){
+ fprintf(stderr, "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;
+}
+
+/* ------------------------------------------------------------------------- */
+
+