diff options
Diffstat (limited to 'commandline/usb-libusb.c')
| -rw-r--r-- | commandline/usb-libusb.c | 203 | 
1 files changed, 203 insertions, 0 deletions
diff --git a/commandline/usb-libusb.c b/commandline/usb-libusb.c new file mode 100644 index 0000000..886da3b --- /dev/null +++ b/commandline/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: usb-libusb.c 323 2007-03-29 17:25:03Z cs $ + */ + +/* +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; +} + +/* ------------------------------------------------------------------------- */ + +  | 
