hiddata.cpp
Go to the documentation of this file.
00001 /* Name: hiddata.c
00002  * Author: Christian Starkjohann
00003  * Creation Date: 2008-04-11
00004  * Tabsize: 4
00005  * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
00006  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
00007  */
00008 
00009 #include <stdio.h>
00010 #include "blink1/hiddata.h"
00011 
00012 /* ######################################################################## */
00013 #if defined(WIN32) /* ##################################################### */
00014 /* ######################################################################## */
00015 
00016 #include <windows.h>
00017 #include <setupapi.h>
00018 #include "hidsdi.h"
00019 #include <ddk/hidpi.h>
00020 
00021 #ifdef DEBUG
00022 #define DEBUG_PRINT(arg)    printf arg
00023 #else
00024 #define DEBUG_PRINT(arg)
00025 #endif
00026 
00027 /* ------------------------------------------------------------------------ */
00028 
00029 static void convertUniToAscii(char *buffer)
00030 {
00031 unsigned short  *uni = (void *)buffer;
00032 char            *ascii = buffer;
00033 
00034     while(*uni != 0){
00035         if(*uni >= 256){
00036             *ascii++ = '?';
00037         }else{
00038             *ascii++ = *uni++;
00039         }
00040     }
00041     *ascii++ = 0;
00042 }
00043 
00044 int usbhidOpenDevice(usbDevice_t **device, int vendor, char *vendorName, int product, char *productName, int usesReportIDs)
00045 {
00046 GUID                                hidGuid;        /* GUID for HID driver */
00047 HDEVINFO                            deviceInfoList;
00048 SP_DEVICE_INTERFACE_DATA            deviceInfo;
00049 SP_DEVICE_INTERFACE_DETAIL_DATA     *deviceDetails = NULL;
00050 DWORD                               size;
00051 int                                 i, openFlag = 0;  /* may be FILE_FLAG_OVERLAPPED */
00052 int                                 errorCode = USBOPEN_ERR_NOTFOUND;
00053 HANDLE                              handle = INVALID_HANDLE_VALUE;
00054 HIDD_ATTRIBUTES                     deviceAttributes;
00055                                 
00056     HidD_GetHidGuid(&hidGuid);
00057     deviceInfoList = SetupDiGetClassDevs(&hidGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
00058     deviceInfo.cbSize = sizeof(deviceInfo);
00059     for(i=0;;i++){
00060         if(handle != INVALID_HANDLE_VALUE){
00061             CloseHandle(handle);
00062             handle = INVALID_HANDLE_VALUE;
00063         }
00064         if(!SetupDiEnumDeviceInterfaces(deviceInfoList, 0, &hidGuid, i, &deviceInfo))
00065             break;  /* no more entries */
00066         /* first do a dummy call just to determine the actual size required */
00067         SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, NULL, 0, &size, NULL);
00068         if(deviceDetails != NULL)
00069             free(deviceDetails);
00070         deviceDetails = malloc(size);
00071         deviceDetails->cbSize = sizeof(*deviceDetails);
00072         /* this call is for real: */
00073         SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, deviceDetails, size, &size, NULL);
00074         DEBUG_PRINT(("checking HID path \"%s\"\n", deviceDetails->DevicePath));
00075 #if 0
00076         /* If we want to access a mouse our keyboard, we can only use feature
00077          * requests as the device is locked by Windows. It must be opened
00078          * with ACCESS_TYPE_NONE.
00079          */
00080         handle = CreateFile(deviceDetails->DevicePath, ACCESS_TYPE_NONE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, openFlag, NULL);
00081 #endif
00082         /* attempt opening for R/W -- we don't care about devices which can't be accessed */
00083         handle = CreateFile(deviceDetails->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, openFlag, NULL);
00084         if(handle == INVALID_HANDLE_VALUE){
00085             DEBUG_PRINT(("opening failed: %d\n", (int)GetLastError()));
00086             /* errorCode = USBOPEN_ERR_ACCESS; opening will always fail for mouse -- ignore */
00087             continue;
00088         }
00089         deviceAttributes.Size = sizeof(deviceAttributes);
00090         HidD_GetAttributes(handle, &deviceAttributes);
00091         DEBUG_PRINT(("device attributes: vid=%d pid=%d\n", deviceAttributes.VendorID, deviceAttributes.ProductID));
00092         if(deviceAttributes.VendorID != vendor || deviceAttributes.ProductID != product)
00093             continue;   /* ignore this device */
00094         errorCode = USBOPEN_ERR_NOTFOUND;
00095         if(vendorName != NULL && productName != NULL){
00096             char    buffer[512];
00097             if(!HidD_GetManufacturerString(handle, buffer, sizeof(buffer))){
00098                 DEBUG_PRINT(("error obtaining vendor name\n"));
00099                 errorCode = USBOPEN_ERR_IO;
00100                 continue;
00101             }
00102             convertUniToAscii(buffer);
00103             DEBUG_PRINT(("vendorName = \"%s\"\n", buffer));
00104             if(strcmp(vendorName, buffer) != 0)
00105                 continue;
00106             if(!HidD_GetProductString(handle, buffer, sizeof(buffer))){
00107                 DEBUG_PRINT(("error obtaining product name\n"));
00108                 errorCode = USBOPEN_ERR_IO;
00109                 continue;
00110             }
00111             convertUniToAscii(buffer);
00112             DEBUG_PRINT(("productName = \"%s\"\n", buffer));
00113             if(strcmp(productName, buffer) != 0)
00114                 continue;
00115         }
00116         break;  /* we have found the device we are looking for! */
00117     }
00118     SetupDiDestroyDeviceInfoList(deviceInfoList);
00119     if(deviceDetails != NULL)
00120         free(deviceDetails);
00121     if(handle != INVALID_HANDLE_VALUE){
00122         *device = (usbDevice_t *)handle;
00123         errorCode = 0;
00124     }
00125     return errorCode;
00126 }
00127 
00128 /* ------------------------------------------------------------------------ */
00129 
00130 void    usbhidCloseDevice(usbDevice_t *device)
00131 {
00132     CloseHandle((HANDLE)device);
00133 }
00134 
00135 /* ------------------------------------------------------------------------ */
00136 
00137 int usbhidSetReport(usbDevice_t *device, char *buffer, int len)
00138 {
00139 BOOLEAN rval;
00140 
00141     rval = HidD_SetFeature((HANDLE)device, buffer, len);
00142     return rval == 0 ? USBOPEN_ERR_IO : 0;
00143 }
00144 
00145 /* ------------------------------------------------------------------------ */
00146 
00147 int usbhidGetReport(usbDevice_t *device, int reportNumber, char *buffer, int *len)
00148 {
00149 BOOLEAN rval = 0;
00150 
00151     buffer[0] = reportNumber;
00152     rval = HidD_GetFeature((HANDLE)device, buffer, *len);
00153     return rval == 0 ? USBOPEN_ERR_IO : 0;
00154 }
00155 
00156 /* ------------------------------------------------------------------------ */
00157 
00158 /* ######################################################################## */
00159 #else /* defined WIN32 #################################################### */
00160 /* ######################################################################## */
00161 
00162 #include <string.h>
00163 #include <usb.h>
00164 
00165 #define usbDevice   usb_dev_handle  /* use libusb's device structure */
00166 
00167 /* ------------------------------------------------------------------------- */
00168 
00169 #define USBRQ_HID_GET_REPORT    0x01
00170 #define USBRQ_HID_SET_REPORT    0x09
00171 
00172 #define USB_HID_REPORT_TYPE_FEATURE 3
00173 
00174 
00175 static int  usesReportIDs;
00176 
00177 /* ------------------------------------------------------------------------- */
00178 
00179 static int usbhidGetStringAscii(usb_dev_handle *dev, int index, char *buf, int buflen)
00180 {
00181 char    buffer[256];
00182 int     rval, i;
00183 
00184     if((rval = usb_get_string_simple(dev, index, buf, buflen)) >= 0) /* use libusb version if it works */
00185         return rval;
00186     if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + index, 0x0409, buffer, sizeof(buffer), 5000)) < 0)
00187         return rval;
00188     if(buffer[1] != USB_DT_STRING){
00189         *buf = 0;
00190         return 0;
00191     }
00192     if((unsigned char)buffer[0] < rval)
00193         rval = (unsigned char)buffer[0];
00194     rval /= 2;
00195     /* lossy conversion to ISO Latin1: */
00196     for(i=1;i<rval;i++){
00197         if(i > buflen)              /* destination buffer overflow */
00198             break;
00199         buf[i-1] = buffer[2 * i];
00200         if(buffer[2 * i + 1] != 0)  /* outside of ISO Latin1 range */
00201             buf[i-1] = '?';
00202     }
00203     buf[i-1] = 0;
00204     return i-1;
00205 }
00206 
00207 int usbhidOpenDevice(usbDevice_t **device, int vendor, char *vendorName, int product, char *productName, int _usesReportIDs)
00208 {
00209 char drivername[2];
00210 int detachrc;
00211 struct usb_bus      *bus;
00212 struct usb_device   *dev;
00213 usb_dev_handle      *handle = NULL;
00214 int                 errorCode = USBOPEN_ERR_NOTFOUND;
00215 static int          didUsbInit = 0;
00216 
00217     if(!didUsbInit){
00218         usb_init();
00219         didUsbInit = 1;
00220     }
00221     usb_find_busses();
00222     usb_find_devices();
00223     for(bus=usb_get_busses(); bus; bus=bus->next){
00224         for(dev=bus->devices; dev; dev=dev->next){
00225             if(dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product){
00226                 char    string[256];
00227                 int     len;
00228                 handle = usb_open(dev); /* we need to open the device in order to query strings */
00229                 if(!handle){
00230                     errorCode = USBOPEN_ERR_ACCESS;
00231                     fprintf(stderr, "Warning: cannot open USB device: %s\n", usb_strerror());
00232                     continue;
00233                 }
00234 
00235 
00236                 // Likely no need to capture the return code. It will return an error if no driver is
00237                 // attached, which is A-OK. Nothing will be detached in that case.
00238                 usb_get_driver_np(handle, 0, drivername, sizeof(drivername));
00239                 // If we have an empty then nothing is attached, otherwise will be something like "dummy".
00240                 if(strlen(drivername) > 0){
00241                     // Not doing this causes several issues writing control messages to the interface.
00242                     detachrc = usb_detach_kernel_driver_np(handle, 0);
00243                     if (detachrc != 0) {
00244                         errorCode = USBOPEN_ERR_IO;
00245                         fprintf(stderr, "Warning: cannot detach kernel driver from interface 0: %s\n", usb_strerror());
00246                         continue;
00247                     }
00248                 }
00249 
00250                 if(vendorName == NULL && productName == NULL){  /* name does not matter */
00251                     break;
00252                 }
00253                 /* now check whether the names match: */
00254                 len = usbhidGetStringAscii(handle, dev->descriptor.iManufacturer, string, sizeof(string));
00255                 if(len < 0){
00256                     errorCode = USBOPEN_ERR_IO;
00257                     fprintf(stderr, "Warning: cannot query manufacturer for device: %s\n", usb_strerror());
00258                 }else{
00259                     errorCode = USBOPEN_ERR_NOTFOUND;
00260                     /* fprintf(stderr, "seen device from vendor ->%s<-\n", string); */
00261                     if(strcmp(string, vendorName) == 0){
00262                         len = usbhidGetStringAscii(handle, dev->descriptor.iProduct, string, sizeof(string));
00263                         if(len < 0){
00264                             errorCode = USBOPEN_ERR_IO;
00265                             fprintf(stderr, "Warning: cannot query product for device: %s\n", usb_strerror());
00266                         }else{
00267                             errorCode = USBOPEN_ERR_NOTFOUND;
00268                             /* fprintf(stderr, "seen product ->%s<-\n", string); */
00269                             if(strcmp(string, productName) == 0)
00270                                 break;
00271                         }
00272                     }
00273                 }
00274                 usb_close(handle);
00275                 handle = NULL;
00276             }
00277         }
00278         if(handle)
00279             break;
00280     }
00281     if(handle != NULL){
00282         errorCode = 0;
00283         *device = (void *)handle;
00284         usesReportIDs = _usesReportIDs;
00285     }
00286     return errorCode;
00287 }
00288 
00289 /* ------------------------------------------------------------------------- */
00290 
00291 void    usbhidCloseDevice(usbDevice_t *device)
00292 {
00293     if(device != NULL)
00294         usb_close((void *)device);
00295 }
00296 
00297 /* ------------------------------------------------------------------------- */
00298 
00299 int usbhidSetReport(usbDevice_t *device, char *buffer, int len)
00300 {
00301 int bytesSent, reportId = buffer[0];
00302 int claimrc, releaserc;
00303 
00304     if(!usesReportIDs){
00305         buffer++;   /* skip dummy report ID */
00306         len--;
00307     }
00308 
00309     claimrc = usb_claim_interface((void *)device, 0);
00310     if(claimrc != 0){
00311         fprintf(stderr, "Error claiming interface 0 before sending a control message: %s\n", usb_strerror());
00312         return USBOPEN_ERR_IO;
00313     }
00314 
00315     // original hiddata.h
00316     //    bytesSent = usb_control_msg((void *)device, USB_TYPE_CLASS | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, USBRQ_HID_SET_REPORT, USB_HID_REPORT_TYPE_FEATURE << 8 | (reportId & 0xff), 0, buffer, len, 5000);
00317     // modification by todbot, matches roughly what hiddata does
00318     // change by tod to use USB_RECIP_INTERFACE instead of USB_RECIP_DEVICE
00319     bytesSent = usb_control_msg((void *)device, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_ENDPOINT_OUT, USBRQ_HID_SET_REPORT, USB_HID_REPORT_TYPE_FEATURE << 8 | (reportId & 0xff), 0, buffer, len, 5000);
00320     if(bytesSent != len){
00321         if(bytesSent < 0)
00322         {
00323             fprintf(stderr, "Error sending message: %s\n", usb_strerror());
00324         }
00325 
00326         usb_release_interface((void *)device, 0);
00327         return USBOPEN_ERR_IO;
00328     }
00329 
00330     releaserc = usb_release_interface((void *)device, 0);
00331     if(releaserc != 0){
00332         fprintf(stderr, "Error releasing interface 0 after sending a control message: %s\n", usb_strerror());
00333         return USBOPEN_ERR_IO;
00334     }
00335 
00336     return 0;
00337 }
00338 
00339 /* ------------------------------------------------------------------------- */
00340 
00341 int usbhidGetReport(usbDevice_t *device, int reportNumber, char *buffer, int *len)
00342 {
00343 int bytesReceived, maxLen = *len;
00344 int claimrc, releaserc;
00345 
00346     if(!usesReportIDs){
00347         buffer++;   /* make room for dummy report ID */
00348         maxLen--;
00349     }
00350 
00351     claimrc = usb_claim_interface((void *)device, 0);
00352     if(claimrc != 0){
00353         fprintf(stderr, "Error claiming interface 0 before sending a control message: %s\n", usb_strerror());
00354         return USBOPEN_ERR_IO;
00355     }
00356 
00357     // original hiddata.h
00358     //bytesReceived = usb_control_msg((void *)device, USB_TYPE_CLASS | USB_RECIP_DEVICE | USB_ENDPOINT_IN, USBRQ_HID_GET_REPORT, USB_HID_REPORT_TYPE_FEATURE << 8 | reportNumber, 0, buffer, maxLen, 5000);
00359     // change by tod to use USB_RECIP_INTERFACE instead of USB_RECIP_DEVICE
00360     bytesReceived = usb_control_msg((void *)device, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_ENDPOINT_IN, USBRQ_HID_GET_REPORT, USB_HID_REPORT_TYPE_FEATURE << 8 | reportNumber, 0, buffer, maxLen, 5000);
00361     if(bytesReceived < 0){
00362         fprintf(stderr, "Error sending message: %s\n", usb_strerror());
00363         usb_release_interface((void *)device, 0);
00364         return USBOPEN_ERR_IO;
00365     }
00366     *len = bytesReceived;
00367     if(!usesReportIDs){
00368         buffer[-1] = reportNumber;  /* add dummy report ID */
00369         (*len)++;
00370     }
00371 
00372     releaserc = usb_release_interface((void *)device, 0);
00373     if(releaserc != 0){
00374         fprintf(stderr, "Error releasing interface 0 after sending a control message: %s\n", usb_strerror());
00375         return USBOPEN_ERR_IO;
00376     }
00377 
00378     return 0;
00379 }
00380 
00381 /* ######################################################################## */
00382 #endif /* defined WIN32 ################################################### */
00383 /* ######################################################################## */


blink1
Author(s): Guilherme Pereira (The AIR lab, Carnegie Mellon University)
autogenerated on Sat Jun 8 2019 20:13:43