hid.cpp (9327B)
1 //=================== Copyright Valve Corporation, All rights reserved. ======= 2 // 3 // Purpose: A wrapper around both the libusb and hidraw versions of HIDAPI 4 // 5 // The libusb version doesn't support Bluetooth, but not all Linux 6 // distributions allow access to /dev/hidraw* 7 // 8 // This merges the two, at a small performance cost, until distributions 9 // have granted access to /dev/hidraw* 10 // 11 //============================================================================= 12 13 #define NAMESPACE HIDRAW 14 #include "../hidapi/hidapi.h" 15 #undef NAMESPACE 16 #undef HIDAPI_H__ 17 18 #define NAMESPACE HIDUSB 19 #include "../hidapi/hidapi.h" 20 #undef NAMESPACE 21 #undef HIDAPI_H__ 22 23 #include "../hidapi/hidapi.h" 24 25 #include "../../../public/tier1/utlvector.h" 26 #include "../../../public/tier1/utlhashmap.h" 27 28 29 template <class T> 30 void CopyHIDDeviceInfo( T *pSrc, struct hid_device_info *pDst ) 31 { 32 pDst->path = pSrc->path ? strdup( pSrc->path ) : NULL; 33 pDst->vendor_id = pSrc->vendor_id; 34 pDst->product_id = pSrc->product_id; 35 pDst->serial_number = pSrc->serial_number ? wcsdup( pSrc->serial_number ) : NULL; 36 pDst->release_number = pSrc->release_number; 37 pDst->manufacturer_string = pSrc->manufacturer_string ? wcsdup( pSrc->manufacturer_string ) : NULL; 38 pDst->product_string = pSrc->product_string ? wcsdup( pSrc->product_string ) : NULL; 39 pDst->usage_page = pSrc->usage_page; 40 pDst->usage = pSrc->usage; 41 pDst->interface_number = pSrc->interface_number; 42 pDst->next = NULL; 43 } 44 45 extern "C" 46 { 47 48 enum EHIDAPIType 49 { 50 k_EHIDAPIUnknown, 51 k_EHIDAPIRAW, 52 k_EHIDAPIUSB 53 }; 54 55 static CUtlHashMap<uintptr_t, EHIDAPIType> s_hashDeviceToAPI; 56 57 static EHIDAPIType GetAPIForDevice( hid_device *pDevice ) 58 { 59 int iIndex = s_hashDeviceToAPI.Find( (uintptr_t)pDevice ); 60 if ( iIndex != -1 ) 61 { 62 return s_hashDeviceToAPI[ iIndex ]; 63 } 64 return k_EHIDAPIUnknown; 65 } 66 67 struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id) 68 { 69 struct HIDUSB::hid_device_info *usb_devs = HIDUSB::hid_enumerate( vendor_id, product_id ); 70 struct HIDUSB::hid_device_info *usb_dev; 71 struct HIDRAW::hid_device_info *raw_devs = HIDRAW::hid_enumerate( vendor_id, product_id ); 72 struct HIDRAW::hid_device_info *raw_dev; 73 struct hid_device_info *devs = NULL, *last = NULL, *new_dev; 74 75 for ( usb_dev = usb_devs; usb_dev; usb_dev = usb_dev->next ) 76 { 77 bool bFound = false; 78 for ( raw_dev = raw_devs; raw_dev; raw_dev = raw_dev->next ) 79 { 80 if ( usb_dev->vendor_id == raw_dev->vendor_id && usb_dev->product_id == raw_dev->product_id ) 81 { 82 bFound = true; 83 break; 84 } 85 } 86 87 //printf("%s USB device VID/PID 0x%.4x/0x%.4x, %ls %ls\n", bFound ? "Found matching" : "Added new", usb_dev->vendor_id, usb_dev->product_id, usb_dev->manufacturer_string, usb_dev->product_string ); 88 89 if ( !bFound ) 90 { 91 new_dev = new struct hid_device_info; 92 CopyHIDDeviceInfo( usb_dev, new_dev ); 93 94 if ( last ) 95 { 96 last->next = new_dev; 97 } 98 else 99 { 100 devs = new_dev; 101 } 102 last = new_dev; 103 } 104 } 105 HIDUSB::hid_free_enumeration( usb_devs ); 106 107 for ( raw_dev = raw_devs; raw_dev; raw_dev = raw_dev->next ) 108 { 109 new_dev = new struct hid_device_info; 110 CopyHIDDeviceInfo( raw_dev, new_dev ); 111 new_dev->next = NULL; 112 113 if ( last ) 114 { 115 last->next = new_dev; 116 } 117 else 118 { 119 devs = new_dev; 120 } 121 last = new_dev; 122 } 123 HIDRAW::hid_free_enumeration( raw_devs ); 124 125 return devs; 126 } 127 128 void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs) 129 { 130 while ( devs ) 131 { 132 struct hid_device_info *next = devs->next; 133 free( devs->path ); 134 free( devs->serial_number ); 135 free( devs->manufacturer_string ); 136 free( devs->product_string ); 137 delete devs; 138 devs = next; 139 } 140 } 141 142 HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) 143 { 144 hid_device *pDevice = NULL; 145 if ( ( pDevice = (hid_device *)HIDRAW::hid_open( vendor_id, product_id, serial_number ) ) != NULL ) 146 { 147 s_hashDeviceToAPI.Insert( (uintptr_t)pDevice, k_EHIDAPIRAW ); 148 return pDevice; 149 } 150 if ( ( pDevice = (hid_device *)HIDUSB::hid_open( vendor_id, product_id, serial_number ) ) != NULL ) 151 { 152 s_hashDeviceToAPI.Insert( (uintptr_t)pDevice, k_EHIDAPIUSB ); 153 return pDevice; 154 } 155 return NULL; 156 } 157 158 HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path, int bExclusive) 159 { 160 hid_device *pDevice = NULL; 161 if ( ( pDevice = (hid_device *)HIDRAW::hid_open_path( path, bExclusive ) ) != NULL ) 162 { 163 s_hashDeviceToAPI.Insert( (uintptr_t)pDevice, k_EHIDAPIRAW ); 164 return pDevice; 165 } 166 if ( ( pDevice = (hid_device *)HIDUSB::hid_open_path( path, bExclusive ) ) != NULL ) 167 { 168 s_hashDeviceToAPI.Insert( (uintptr_t)pDevice, k_EHIDAPIUSB ); 169 return pDevice; 170 } 171 return NULL; 172 } 173 174 int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length) 175 { 176 switch ( GetAPIForDevice( device ) ) 177 { 178 case k_EHIDAPIRAW: 179 return HIDRAW::hid_write( (HIDRAW::hid_device*)device, data, length ); 180 case k_EHIDAPIUSB: 181 return HIDUSB::hid_write( (HIDUSB::hid_device*)device, data, length ); 182 default: 183 return -1; 184 } 185 } 186 187 int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds) 188 { 189 switch ( GetAPIForDevice( device ) ) 190 { 191 case k_EHIDAPIRAW: 192 return HIDRAW::hid_read_timeout( (HIDRAW::hid_device*)device, data, length, milliseconds ); 193 case k_EHIDAPIUSB: 194 return HIDUSB::hid_read_timeout( (HIDUSB::hid_device*)device, data, length, milliseconds ); 195 default: 196 return -1; 197 } 198 } 199 200 int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length) 201 { 202 switch ( GetAPIForDevice( device ) ) 203 { 204 case k_EHIDAPIRAW: 205 return HIDRAW::hid_read( (HIDRAW::hid_device*)device, data, length ); 206 case k_EHIDAPIUSB: 207 return HIDUSB::hid_read( (HIDUSB::hid_device*)device, data, length ); 208 default: 209 return -1; 210 } 211 } 212 213 int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock) 214 { 215 switch ( GetAPIForDevice( device ) ) 216 { 217 case k_EHIDAPIRAW: 218 return HIDRAW::hid_set_nonblocking( (HIDRAW::hid_device*)device, nonblock ); 219 case k_EHIDAPIUSB: 220 return HIDUSB::hid_set_nonblocking( (HIDUSB::hid_device*)device, nonblock ); 221 default: 222 return -1; 223 } 224 } 225 226 int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length) 227 { 228 switch ( GetAPIForDevice( device ) ) 229 { 230 case k_EHIDAPIRAW: 231 return HIDRAW::hid_send_feature_report( (HIDRAW::hid_device*)device, data, length ); 232 case k_EHIDAPIUSB: 233 return HIDUSB::hid_send_feature_report( (HIDUSB::hid_device*)device, data, length ); 234 default: 235 return -1; 236 } 237 } 238 239 int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length) 240 { 241 switch ( GetAPIForDevice( device ) ) 242 { 243 case k_EHIDAPIRAW: 244 return HIDRAW::hid_get_feature_report( (HIDRAW::hid_device*)device, data, length ); 245 case k_EHIDAPIUSB: 246 return HIDUSB::hid_get_feature_report( (HIDUSB::hid_device*)device, data, length ); 247 default: 248 return -1; 249 } 250 } 251 252 void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device) 253 { 254 switch ( GetAPIForDevice( device ) ) 255 { 256 case k_EHIDAPIRAW: 257 HIDRAW::hid_close( (HIDRAW::hid_device*)device ); 258 break; 259 case k_EHIDAPIUSB: 260 HIDUSB::hid_close( (HIDUSB::hid_device*)device ); 261 break; 262 default: 263 break; 264 } 265 s_hashDeviceToAPI.Remove( (uintptr_t)device ); 266 } 267 268 int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen) 269 { 270 switch ( GetAPIForDevice( device ) ) 271 { 272 case k_EHIDAPIRAW: 273 return HIDRAW::hid_get_manufacturer_string( (HIDRAW::hid_device*)device, string, maxlen ); 274 case k_EHIDAPIUSB: 275 return HIDUSB::hid_get_manufacturer_string( (HIDUSB::hid_device*)device, string, maxlen ); 276 default: 277 return -1; 278 } 279 } 280 281 int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen) 282 { 283 switch ( GetAPIForDevice( device ) ) 284 { 285 case k_EHIDAPIRAW: 286 return HIDRAW::hid_get_product_string( (HIDRAW::hid_device*)device, string, maxlen ); 287 case k_EHIDAPIUSB: 288 return HIDUSB::hid_get_product_string( (HIDUSB::hid_device*)device, string, maxlen ); 289 default: 290 return -1; 291 } 292 } 293 294 int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen) 295 { 296 switch ( GetAPIForDevice( device ) ) 297 { 298 case k_EHIDAPIRAW: 299 return HIDRAW::hid_get_serial_number_string( (HIDRAW::hid_device*)device, string, maxlen ); 300 case k_EHIDAPIUSB: 301 return HIDUSB::hid_get_serial_number_string( (HIDUSB::hid_device*)device, string, maxlen ); 302 default: 303 return -1; 304 } 305 } 306 307 int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen) 308 { 309 switch ( GetAPIForDevice( device ) ) 310 { 311 case k_EHIDAPIRAW: 312 return HIDRAW::hid_get_indexed_string( (HIDRAW::hid_device*)device, string_index, string, maxlen ); 313 case k_EHIDAPIUSB: 314 return HIDUSB::hid_get_indexed_string( (HIDUSB::hid_device*)device, string_index, string, maxlen ); 315 default: 316 return -1; 317 } 318 } 319 320 HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device) 321 { 322 switch ( GetAPIForDevice( device ) ) 323 { 324 case k_EHIDAPIRAW: 325 return HIDRAW::hid_error( (HIDRAW::hid_device*)device ); 326 case k_EHIDAPIUSB: 327 return HIDUSB::hid_error( (HIDUSB::hid_device*)device ); 328 default: 329 return NULL; 330 } 331 } 332 333 }