SDL  2.0
hid.cpp
Go to the documentation of this file.
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 
49 {
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 
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 
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 
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 
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 }
HID_API_EXPORT const wchar_t *HID_API_CALL hid_error(hid_device *device)
Get a string describing the last error which occurred.
Definition: hid.cpp:1149
int interface_number
Definition: hidapi.h:79
EHIDAPIType
Definition: hid.cpp:48
#define HID_API_EXPORT
Definition: hidapi.h:36
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
Free an enumeration Linked List.
Definition: hid.cpp:979
SDL_EventEntry * free
Definition: SDL_events.c:84
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
wchar_t * manufacturer_string
Definition: hidapi.h:66
char * path
Definition: hidapi.h:55
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length)
Write an Output report to a HID device.
Definition: hid.cpp:1028
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen)
Get a string from a HID device, based on its string index.
Definition: hid.cpp:1144
static const double T[]
Definition: k_tan.c:53
static SDL_AudioDeviceID device
Definition: loopwave.c:37
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds)
Read an Input report from a HID device with timeout.
Definition: hid.cpp:1040
struct hid_device_info * next
Definition: hidapi.h:82
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock)
Set the device handle to be non-blocking.
Definition: hid.cpp:1060
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device)
Close a HID device.
Definition: hid.cpp:1090
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen)
Get The Product String from a HID device.
Definition: hid.cpp:1122
unsigned short product_id
Definition: hidapi.h:59
wchar_t * serial_number
Definition: hidapi.h:61
unsigned short vendor_id
Definition: hidapi.h:57
HID_API_EXPORT hid_device *HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
Open a HID device using a Vendor ID (VID), Product ID (PID) and optionally a serial number...
Definition: hid.cpp:989
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length)
Get a feature report from a HID device.
Definition: hid.cpp:1078
unsigned int uintptr_t
wchar_t * product_string
Definition: hidapi.h:68
unsigned short usage
Definition: hidapi.h:74
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen)
Get The Serial Number String from a HID device.
Definition: hid.cpp:1133
#define HID_API_EXPORT_CALL
Definition: hidapi.h:40
#define NULL
Definition: begin_code.h:164
static EHIDAPIType GetAPIForDevice(hid_device *pDevice)
Definition: hid.cpp:57
unsigned short usage_page
Definition: hidapi.h:71
HID_API_EXPORT hid_device *HID_API_CALL hid_open_path(const char *path, int bExclusive)
Open a HID device by its path name.
Definition: hid.cpp:995
void CopyHIDDeviceInfo(T *pSrc, struct hid_device_info *pDst)
Definition: hid.cpp:30
GLsizei const GLchar *const * path
int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length)
Send a Feature report to the device.
Definition: hid.cpp:1065
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen)
Get The Manufacturer String from a HID device.
Definition: hid.cpp:1111
GLuint GLsizei GLsizei * length
struct hid_device_info HID_API_EXPORT *HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
Enumerate the HID Devices.
Definition: hid.cpp:961
#define HID_API_CALL
Definition: hidapi.h:37
unsigned short release_number
Definition: hidapi.h:64
static CUtlHashMap< uintptr_t, EHIDAPIType > s_hashDeviceToAPI
Definition: hid.cpp:55
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length)
Read an Input report from a HID device.
Definition: hid.cpp:1053