summaryrefslogtreecommitdiff
path: root/Source/external/SDL2/src/hidapi/linux/hid.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/external/SDL2/src/hidapi/linux/hid.cpp')
-rw-r--r--Source/external/SDL2/src/hidapi/linux/hid.cpp333
1 files changed, 333 insertions, 0 deletions
diff --git a/Source/external/SDL2/src/hidapi/linux/hid.cpp b/Source/external/SDL2/src/hidapi/linux/hid.cpp
new file mode 100644
index 0000000..841f34f
--- /dev/null
+++ b/Source/external/SDL2/src/hidapi/linux/hid.cpp
@@ -0,0 +1,333 @@
+//=================== Copyright Valve Corporation, All rights reserved. =======
+//
+// Purpose: A wrapper around both the libusb and hidraw versions of HIDAPI
+//
+// The libusb version doesn't support Bluetooth, but not all Linux
+// distributions allow access to /dev/hidraw*
+//
+// This merges the two, at a small performance cost, until distributions
+// have granted access to /dev/hidraw*
+//
+//=============================================================================
+
+#define NAMESPACE HIDRAW
+#include "../hidapi/hidapi.h"
+#undef NAMESPACE
+#undef HIDAPI_H__
+
+#define NAMESPACE HIDUSB
+#include "../hidapi/hidapi.h"
+#undef NAMESPACE
+#undef HIDAPI_H__
+
+#include "../hidapi/hidapi.h"
+
+#include "../../../public/tier1/utlvector.h"
+#include "../../../public/tier1/utlhashmap.h"
+
+
+template <class T>
+void CopyHIDDeviceInfo( T *pSrc, struct hid_device_info *pDst )
+{
+ pDst->path = pSrc->path ? strdup( pSrc->path ) : NULL;
+ pDst->vendor_id = pSrc->vendor_id;
+ pDst->product_id = pSrc->product_id;
+ pDst->serial_number = pSrc->serial_number ? wcsdup( pSrc->serial_number ) : NULL;
+ pDst->release_number = pSrc->release_number;
+ pDst->manufacturer_string = pSrc->manufacturer_string ? wcsdup( pSrc->manufacturer_string ) : NULL;
+ pDst->product_string = pSrc->product_string ? wcsdup( pSrc->product_string ) : NULL;
+ pDst->usage_page = pSrc->usage_page;
+ pDst->usage = pSrc->usage;
+ pDst->interface_number = pSrc->interface_number;
+ pDst->next = NULL;
+}
+
+extern "C"
+{
+
+enum EHIDAPIType
+{
+ k_EHIDAPIUnknown,
+ k_EHIDAPIRAW,
+ k_EHIDAPIUSB
+};
+
+static CUtlHashMap<uintptr_t, EHIDAPIType> s_hashDeviceToAPI;
+
+static EHIDAPIType GetAPIForDevice( hid_device *pDevice )
+{
+ int iIndex = s_hashDeviceToAPI.Find( (uintptr_t)pDevice );
+ if ( iIndex != -1 )
+ {
+ return s_hashDeviceToAPI[ iIndex ];
+ }
+ return k_EHIDAPIUnknown;
+}
+
+struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
+{
+ struct HIDUSB::hid_device_info *usb_devs = HIDUSB::hid_enumerate( vendor_id, product_id );
+ struct HIDUSB::hid_device_info *usb_dev;
+ struct HIDRAW::hid_device_info *raw_devs = HIDRAW::hid_enumerate( vendor_id, product_id );
+ struct HIDRAW::hid_device_info *raw_dev;
+ struct hid_device_info *devs = NULL, *last = NULL, *new_dev;
+
+ for ( usb_dev = usb_devs; usb_dev; usb_dev = usb_dev->next )
+ {
+ bool bFound = false;
+ for ( raw_dev = raw_devs; raw_dev; raw_dev = raw_dev->next )
+ {
+ if ( usb_dev->vendor_id == raw_dev->vendor_id && usb_dev->product_id == raw_dev->product_id )
+ {
+ bFound = true;
+ break;
+ }
+ }
+
+//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 );
+
+ if ( !bFound )
+ {
+ new_dev = new struct hid_device_info;
+ CopyHIDDeviceInfo( usb_dev, new_dev );
+
+ if ( last )
+ {
+ last->next = new_dev;
+ }
+ else
+ {
+ devs = new_dev;
+ }
+ last = new_dev;
+ }
+ }
+ HIDUSB::hid_free_enumeration( usb_devs );
+
+ for ( raw_dev = raw_devs; raw_dev; raw_dev = raw_dev->next )
+ {
+ new_dev = new struct hid_device_info;
+ CopyHIDDeviceInfo( raw_dev, new_dev );
+ new_dev->next = NULL;
+
+ if ( last )
+ {
+ last->next = new_dev;
+ }
+ else
+ {
+ devs = new_dev;
+ }
+ last = new_dev;
+ }
+ HIDRAW::hid_free_enumeration( raw_devs );
+
+ return devs;
+}
+
+void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
+{
+ while ( devs )
+ {
+ struct hid_device_info *next = devs->next;
+ free( devs->path );
+ free( devs->serial_number );
+ free( devs->manufacturer_string );
+ free( devs->product_string );
+ delete devs;
+ devs = next;
+ }
+}
+
+HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
+{
+ hid_device *pDevice = NULL;
+ if ( ( pDevice = (hid_device *)HIDRAW::hid_open( vendor_id, product_id, serial_number ) ) != NULL )
+ {
+ s_hashDeviceToAPI.Insert( (uintptr_t)pDevice, k_EHIDAPIRAW );
+ return pDevice;
+ }
+ if ( ( pDevice = (hid_device *)HIDUSB::hid_open( vendor_id, product_id, serial_number ) ) != NULL )
+ {
+ s_hashDeviceToAPI.Insert( (uintptr_t)pDevice, k_EHIDAPIUSB );
+ return pDevice;
+ }
+ return NULL;
+}
+
+HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path, int bExclusive)
+{
+ hid_device *pDevice = NULL;
+ if ( ( pDevice = (hid_device *)HIDRAW::hid_open_path( path, bExclusive ) ) != NULL )
+ {
+ s_hashDeviceToAPI.Insert( (uintptr_t)pDevice, k_EHIDAPIRAW );
+ return pDevice;
+ }
+ if ( ( pDevice = (hid_device *)HIDUSB::hid_open_path( path, bExclusive ) ) != NULL )
+ {
+ s_hashDeviceToAPI.Insert( (uintptr_t)pDevice, k_EHIDAPIUSB );
+ return pDevice;
+ }
+ return NULL;
+}
+
+int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length)
+{
+ switch ( GetAPIForDevice( device ) )
+ {
+ case k_EHIDAPIRAW:
+ return HIDRAW::hid_write( (HIDRAW::hid_device*)device, data, length );
+ case k_EHIDAPIUSB:
+ return HIDUSB::hid_write( (HIDUSB::hid_device*)device, data, length );
+ default:
+ return -1;
+ }
+}
+
+int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds)
+{
+ switch ( GetAPIForDevice( device ) )
+ {
+ case k_EHIDAPIRAW:
+ return HIDRAW::hid_read_timeout( (HIDRAW::hid_device*)device, data, length, milliseconds );
+ case k_EHIDAPIUSB:
+ return HIDUSB::hid_read_timeout( (HIDUSB::hid_device*)device, data, length, milliseconds );
+ default:
+ return -1;
+ }
+}
+
+int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length)
+{
+ switch ( GetAPIForDevice( device ) )
+ {
+ case k_EHIDAPIRAW:
+ return HIDRAW::hid_read( (HIDRAW::hid_device*)device, data, length );
+ case k_EHIDAPIUSB:
+ return HIDUSB::hid_read( (HIDUSB::hid_device*)device, data, length );
+ default:
+ return -1;
+ }
+}
+
+int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock)
+{
+ switch ( GetAPIForDevice( device ) )
+ {
+ case k_EHIDAPIRAW:
+ return HIDRAW::hid_set_nonblocking( (HIDRAW::hid_device*)device, nonblock );
+ case k_EHIDAPIUSB:
+ return HIDUSB::hid_set_nonblocking( (HIDUSB::hid_device*)device, nonblock );
+ default:
+ return -1;
+ }
+}
+
+int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length)
+{
+ switch ( GetAPIForDevice( device ) )
+ {
+ case k_EHIDAPIRAW:
+ return HIDRAW::hid_send_feature_report( (HIDRAW::hid_device*)device, data, length );
+ case k_EHIDAPIUSB:
+ return HIDUSB::hid_send_feature_report( (HIDUSB::hid_device*)device, data, length );
+ default:
+ return -1;
+ }
+}
+
+int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length)
+{
+ switch ( GetAPIForDevice( device ) )
+ {
+ case k_EHIDAPIRAW:
+ return HIDRAW::hid_get_feature_report( (HIDRAW::hid_device*)device, data, length );
+ case k_EHIDAPIUSB:
+ return HIDUSB::hid_get_feature_report( (HIDUSB::hid_device*)device, data, length );
+ default:
+ return -1;
+ }
+}
+
+void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device)
+{
+ switch ( GetAPIForDevice( device ) )
+ {
+ case k_EHIDAPIRAW:
+ HIDRAW::hid_close( (HIDRAW::hid_device*)device );
+ break;
+ case k_EHIDAPIUSB:
+ HIDUSB::hid_close( (HIDUSB::hid_device*)device );
+ break;
+ default:
+ break;
+ }
+ s_hashDeviceToAPI.Remove( (uintptr_t)device );
+}
+
+int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen)
+{
+ switch ( GetAPIForDevice( device ) )
+ {
+ case k_EHIDAPIRAW:
+ return HIDRAW::hid_get_manufacturer_string( (HIDRAW::hid_device*)device, string, maxlen );
+ case k_EHIDAPIUSB:
+ return HIDUSB::hid_get_manufacturer_string( (HIDUSB::hid_device*)device, string, maxlen );
+ default:
+ return -1;
+ }
+}
+
+int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen)
+{
+ switch ( GetAPIForDevice( device ) )
+ {
+ case k_EHIDAPIRAW:
+ return HIDRAW::hid_get_product_string( (HIDRAW::hid_device*)device, string, maxlen );
+ case k_EHIDAPIUSB:
+ return HIDUSB::hid_get_product_string( (HIDUSB::hid_device*)device, string, maxlen );
+ default:
+ return -1;
+ }
+}
+
+int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen)
+{
+ switch ( GetAPIForDevice( device ) )
+ {
+ case k_EHIDAPIRAW:
+ return HIDRAW::hid_get_serial_number_string( (HIDRAW::hid_device*)device, string, maxlen );
+ case k_EHIDAPIUSB:
+ return HIDUSB::hid_get_serial_number_string( (HIDUSB::hid_device*)device, string, maxlen );
+ default:
+ return -1;
+ }
+}
+
+int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen)
+{
+ switch ( GetAPIForDevice( device ) )
+ {
+ case k_EHIDAPIRAW:
+ return HIDRAW::hid_get_indexed_string( (HIDRAW::hid_device*)device, string_index, string, maxlen );
+ case k_EHIDAPIUSB:
+ return HIDUSB::hid_get_indexed_string( (HIDUSB::hid_device*)device, string_index, string, maxlen );
+ default:
+ return -1;
+ }
+}
+
+HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device)
+{
+ switch ( GetAPIForDevice( device ) )
+ {
+ case k_EHIDAPIRAW:
+ return HIDRAW::hid_error( (HIDRAW::hid_device*)device );
+ case k_EHIDAPIUSB:
+ return HIDUSB::hid_error( (HIDUSB::hid_device*)device );
+ default:
+ return NULL;
+ }
+}
+
+}