6 #include "../../SDL_internal.h" 8 #ifdef SDL_JOYSTICK_HIDAPI 10 #include <CoreBluetooth/CoreBluetooth.h> 11 #include <QuartzCore/QuartzCore.h> 12 #import <UIKit/UIKit.h> 13 #import <mach/mach_time.h> 17 #include "../hidapi/hidapi.h" 19 #define VALVE_USB_VID 0x28DE 20 #define D0G_BLE2_PID 0x1106 26 #define FEATURE_REPORT_LOGGING 0 28 #define REPORT_SEGMENT_DATA_FLAG 0x80 29 #define REPORT_SEGMENT_LAST_FLAG 0x40 31 #define VALVE_SERVICE @"100F6C32-1735-4313-B402-38567131E5F3" 34 #define VALVE_INPUT_CHAR @"100F6C33-1735-4313-B402-38567131E5F3" 37 #define VALVE_REPORT_CHAR @"100F6C34-1735-4313-B402-38567131E5F3" 60 bluetoothSegment segment;
78 size_t GetBluetoothSegmentSize(bluetoothSegment *segment)
80 return segment->length + 3;
83 #define RingBuffer_cbElem 19 84 #define RingBuffer_nElem 4096 88 uint8_t _data[ ( RingBuffer_nElem * RingBuffer_cbElem ) ];
89 pthread_mutex_t accessLock;
92 static void RingBuffer_init( RingBuffer *
this )
96 pthread_mutex_init( &this->accessLock, 0 );
99 static bool RingBuffer_write( RingBuffer *
this,
const uint8_t *
src )
101 pthread_mutex_lock( &this->accessLock );
102 memcpy( &this->_data[ this->_last ], src, RingBuffer_cbElem );
103 if ( this->_first == -1 )
105 this->_first = this->_last;
107 this->_last = ( this->_last + RingBuffer_cbElem ) % (RingBuffer_nElem * RingBuffer_cbElem);
108 if ( this->_last == this->_first )
110 this->_first = ( this->_first + RingBuffer_cbElem ) % (RingBuffer_nElem * RingBuffer_cbElem);
111 pthread_mutex_unlock( &this->accessLock );
114 pthread_mutex_unlock( &this->accessLock );
118 static bool RingBuffer_read( RingBuffer *
this,
uint8_t *
dst )
120 pthread_mutex_lock( &this->accessLock );
121 if ( this->_first == -1 )
123 pthread_mutex_unlock( &this->accessLock );
126 memcpy( dst, &this->_data[ this->_first ], RingBuffer_cbElem );
127 this->_first = ( this->_first + RingBuffer_cbElem ) % (RingBuffer_nElem * RingBuffer_cbElem);
128 if ( this->_first == this->_last )
132 pthread_mutex_unlock( &this->accessLock );
137 #pragma mark HIDBLEDevice Definition 141 BLEDeviceWaitState_None,
142 BLEDeviceWaitState_Waiting,
143 BLEDeviceWaitState_Complete,
144 BLEDeviceWaitState_Error
145 } BLEDeviceWaitState;
147 @interface HIDBLEDevice : NSObject <CBPeripheralDelegate>
149 RingBuffer _inputReports;
151 BLEDeviceWaitState _waitStateForReadFeatureReport;
152 BLEDeviceWaitState _waitStateForWriteFeatureReport;
155 @property (nonatomic, readwrite)
bool connected;
156 @property (nonatomic, readwrite)
bool ready;
158 @property (nonatomic, strong) CBPeripheral *bleSteamController;
159 @property (nonatomic, strong) CBCharacteristic *bleCharacteristicInput;
160 @property (nonatomic, strong) CBCharacteristic *bleCharacteristicReport;
162 - (
id)initWithPeripheral:(CBPeripheral *)peripheral;
167 @interface HIDBLEManager : NSObject <CBCentralManagerDelegate>
169 @property (nonatomic)
int nPendingScans;
170 @property (nonatomic)
int nPendingPairs;
171 @property (nonatomic, strong) CBCentralManager *centralManager;
172 @property (nonatomic, strong) NSMapTable<CBPeripheral *, HIDBLEDevice *> *deviceMap;
173 @property (nonatomic, retain) dispatch_queue_t bleSerialQueue;
175 + (instancetype)sharedInstance;
176 - (
void)startScan:(
int)duration;
178 - (int)updateConnectedSteamControllers:(BOOL) bForce;
179 - (
void)appWillResignActiveNotification:(NSNotification *)note;
180 - (
void)appDidBecomeActiveNotification:(NSNotification *)note;
186 @implementation HIDBLEManager
188 + (instancetype)sharedInstance
190 static HIDBLEManager *sharedInstance = nil;
191 static dispatch_once_t onceToken;
192 dispatch_once(&onceToken, ^{
193 sharedInstance = [HIDBLEManager new];
194 sharedInstance.nPendingScans = 0;
195 sharedInstance.nPendingPairs = 0;
197 [[NSNotificationCenter defaultCenter] addObserver:sharedInstance selector:@selector(appWillResignActiveNotification:) name: UIApplicationWillResignActiveNotification object:nil];
198 [[NSNotificationCenter defaultCenter] addObserver:sharedInstance selector:@selector(appDidBecomeActiveNotification:) name:UIApplicationDidBecomeActiveNotification object:nil];
207 sharedInstance.bleSerialQueue = dispatch_queue_create(
"com.valvesoftware.steamcontroller.ble", DISPATCH_QUEUE_SERIAL );
208 dispatch_set_target_queue( sharedInstance.bleSerialQueue, dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0 ) );
213 sharedInstance.centralManager = [[CBCentralManager alloc] initWithDelegate:sharedInstance queue:sharedInstance.bleSerialQueue];
214 sharedInstance.deviceMap = [[NSMapTable alloc] initWithKeyOptions:NSMapTableWeakMemory valueOptions:NSMapTableStrongMemory capacity:4];
216 return sharedInstance;
220 - (
void)appWillResignActiveNotification:(NSNotification *)note
223 if (
self.nPendingPairs > 0 )
226 for ( CBPeripheral *peripheral
in self.deviceMap )
228 HIDBLEDevice *steamController = [
self.deviceMap objectForKey:peripheral];
229 if ( steamController )
231 steamController.connected = NO;
232 steamController.ready = NO;
233 [
self.centralManager cancelPeripheralConnection:peripheral];
236 [
self.deviceMap removeAllObjects];
242 - (
void)appDidBecomeActiveNotification:(NSNotification *)note
244 [
self updateConnectedSteamControllers:true];
248 - (int)updateConnectedSteamControllers:(BOOL) bForce
250 static uint64_t s_unLastUpdateTick = 0;
251 static mach_timebase_info_data_t s_timebase_info;
253 if (s_timebase_info.denom == 0)
255 mach_timebase_info( &s_timebase_info );
258 uint64_t ticksNow = mach_approximate_time();
259 if ( !bForce && ( ( (ticksNow - s_unLastUpdateTick) * s_timebase_info.numer ) / s_timebase_info.denom ) < (5ull * NSEC_PER_SEC) )
260 return (
int)
self.deviceMap.count;
264 if (
self.centralManager.state != CBManagerStatePoweredOn )
265 return (
int)
self.deviceMap.count;
268 s_unLastUpdateTick = mach_approximate_time();
272 if (
self.nPendingPairs > 0 )
273 return (
int)
self.deviceMap.count;
275 NSArray<CBPeripheral *> *peripherals = [
self.centralManager retrieveConnectedPeripheralsWithServices: @[ [CBUUID UUIDWithString:@"180A"]]];
276 for ( CBPeripheral *peripheral
in peripherals )
279 if ( [
self.deviceMap objectForKey: peripheral] != nil )
282 NSLog(
@"connected peripheral: %@", peripheral );
283 if ( [peripheral.name isEqualToString:
@"SteamController"] )
285 HIDBLEDevice *steamController = [[HIDBLEDevice alloc] initWithPeripheral:peripheral];
286 [
self.deviceMap setObject:steamController forKey:peripheral];
287 [
self.centralManager connectPeripheral:peripheral options:nil];
291 return (
int)
self.deviceMap.count;
295 - (
void)startScan:(
int)duration
297 NSLog(
@"BLE: requesting scan for %d seconds", duration );
300 if ( _nPendingScans++ == 0 )
302 [
self.centralManager scanForPeripheralsWithServices:nil options:nil];
308 dispatch_after( dispatch_time( DISPATCH_TIME_NOW, (
int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
316 NSLog(
@"BLE: stopping scan" );
319 if ( --_nPendingScans <= 0 )
322 [
self.centralManager stopScan];
328 #pragma mark CBCentralManagerDelegate Implementation 331 - (
void)centralManagerDidUpdateState:(CBCentralManager *)central
333 switch ( central.state )
335 case CBCentralManagerStatePoweredOn:
337 NSLog(
@"CoreBluetooth BLE hardware is powered on and ready" );
344 if ( [
self updateConnectedSteamControllers:
false] == 0 )
355 case CBCentralManagerStatePoweredOff:
356 NSLog(
@"CoreBluetooth BLE hardware is powered off" );
359 case CBCentralManagerStateUnauthorized:
360 NSLog(
@"CoreBluetooth BLE state is unauthorized" );
363 case CBCentralManagerStateUnknown:
364 NSLog(
@"CoreBluetooth BLE state is unknown" );
367 case CBCentralManagerStateUnsupported:
368 NSLog(
@"CoreBluetooth BLE hardware is unsupported on this platform" );
371 case CBCentralManagerStateResetting:
372 NSLog(
@"CoreBluetooth BLE manager is resetting" );
377 - (
void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
379 HIDBLEDevice *steamController = [_deviceMap objectForKey:peripheral];
380 steamController.connected = YES;
381 self.nPendingPairs -= 1;
384 - (
void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
386 NSLog(
@"Failed to connect: %@", error );
387 [_deviceMap removeObjectForKey:peripheral];
388 self.nPendingPairs -= 1;
391 - (
void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
393 NSString *localName = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey];
394 NSString *log = [NSString stringWithFormat:@"Found '%@'", localName];
396 if ( [localName isEqualToString:
@"SteamController"] )
398 NSLog(
@"%@ : %@ - %@", log, peripheral, advertisementData );
399 self.nPendingPairs += 1;
400 HIDBLEDevice *steamController = [[HIDBLEDevice alloc] initWithPeripheral:peripheral];
401 [
self.deviceMap setObject:steamController forKey:peripheral];
402 [
self.centralManager connectPeripheral:peripheral options:nil];
406 - (
void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
408 HIDBLEDevice *steamController = [
self.deviceMap objectForKey:peripheral];
409 if ( steamController )
411 steamController.connected = NO;
412 steamController.ready = NO;
413 [
self.deviceMap removeObjectForKey:peripheral];
421 static void process_pending_events()
423 CFRunLoopRunResult
res;
426 res = CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0.001,
FALSE );
428 while( res != kCFRunLoopRunFinished && res != kCFRunLoopRunTimedOut );
431 @implementation HIDBLEDevice
435 if (
self = [super init] )
437 RingBuffer_init( &_inputReports );
438 self.bleSteamController = nil;
439 self.bleCharacteristicInput = nil;
440 self.bleCharacteristicReport = nil;
447 - (
id)initWithPeripheral:(CBPeripheral *)peripheral
449 if (
self = [super init] )
451 RingBuffer_init( &_inputReports );
454 self.bleSteamController = peripheral;
457 peripheral.delegate =
self;
459 self.bleCharacteristicInput = nil;
460 self.bleCharacteristicReport = nil;
465 - (
void)setConnected:(
bool)connected
467 _connected = connected;
470 [_bleSteamController discoverServices:nil];
474 NSLog(
@"Disconnected" );
480 if ( RingBuffer_read( &_inputReports, dst+1 ) )
488 - (int)send_report:(const
uint8_t *)data length:(
size_t)length
490 [_bleSteamController writeValue:[NSData dataWithBytes:data length:length] forCharacteristic:_bleCharacteristicReport type:CBCharacteristicWriteWithResponse];
494 - (int)send_feature_report:(hidFeatureReport *)report
496 #if FEATURE_REPORT_LOGGING 499 NSLog(
@"HIDBLE:send_feature_report (%02zu/19) [%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]", GetBluetoothSegmentSize( report->segment ),
500 reportBytes[1], reportBytes[2], reportBytes[3], reportBytes[4], reportBytes[5], reportBytes[6],
501 reportBytes[7], reportBytes[8], reportBytes[9], reportBytes[10], reportBytes[11], reportBytes[12],
502 reportBytes[13], reportBytes[14], reportBytes[15], reportBytes[16], reportBytes[17], reportBytes[18],
506 int sendSize = (int)GetBluetoothSegmentSize( &report->segment );
513 [_bleSteamController writeValue:[NSData dataWithBytes:&report->segment length:sendSize] forCharacteristic:_bleCharacteristicReport type:CBCharacteristicWriteWithResponse];
521 _waitStateForWriteFeatureReport = BLEDeviceWaitState_Waiting;
522 [_bleSteamController writeValue:[NSData dataWithBytes:&report->segment length:sendSize
523 ] forCharacteristic:_bleCharacteristicReport type:CBCharacteristicWriteWithResponse];
525 while ( _waitStateForWriteFeatureReport == BLEDeviceWaitState_Waiting )
527 process_pending_events();
530 if ( _waitStateForWriteFeatureReport == BLEDeviceWaitState_Error )
532 _waitStateForWriteFeatureReport = BLEDeviceWaitState_None;
536 _waitStateForWriteFeatureReport = BLEDeviceWaitState_None;
543 _waitStateForReadFeatureReport = BLEDeviceWaitState_Waiting;
544 [_bleSteamController readValueForCharacteristic:_bleCharacteristicReport];
546 while ( _waitStateForReadFeatureReport == BLEDeviceWaitState_Waiting )
547 process_pending_events();
549 if ( _waitStateForReadFeatureReport == BLEDeviceWaitState_Error )
551 _waitStateForReadFeatureReport = BLEDeviceWaitState_None;
555 memcpy( buffer, _featureReport,
sizeof(_featureReport) );
557 _waitStateForReadFeatureReport = BLEDeviceWaitState_None;
559 #if FEATURE_REPORT_LOGGING 560 NSLog(
@"HIDBLE:get_feature_report (19) [%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]",
561 buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6],
562 buffer[7], buffer[8], buffer[9], buffer[10], buffer[11], buffer[12],
563 buffer[13], buffer[14], buffer[15], buffer[16], buffer[17], buffer[18],
570 #pragma mark CBPeripheralDelegate Implementation 572 - (
void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
574 for (CBService *service
in peripheral.services)
576 NSLog(
@"Found Service: %@", service );
577 if ( [service.UUID isEqual:[CBUUID UUIDWithString:VALVE_SERVICE]] )
579 [peripheral discoverCharacteristics:nil forService:service];
584 - (
void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
589 for ( CBDescriptor *descriptor in characteristic.descriptors )
591 NSLog(
@" - Descriptor '%@'", descriptor );
596 - (
void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
598 if ([service.UUID isEqual:[CBUUID UUIDWithString:VALVE_SERVICE]])
600 for (CBCharacteristic *aChar in service.characteristics)
602 NSLog(
@"Found Characteristic %@", aChar );
604 if ( [aChar.UUID isEqual:[CBUUID UUIDWithString:VALVE_INPUT_CHAR]] )
606 self.bleCharacteristicInput = aChar;
608 else if ( [aChar.UUID isEqual:[CBUUID UUIDWithString:VALVE_REPORT_CHAR]] )
610 self.bleCharacteristicReport = aChar;
611 [
self.bleSteamController discoverDescriptorsForCharacteristic: aChar];
617 - (
void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
619 static uint64_t s_ticksLastOverflowReport = 0;
624 if (
self.ready == NO )
627 HIDBLEManager.sharedInstance.nPendingPairs -= 1;
630 if ( [characteristic.UUID isEqual:_bleCharacteristicInput.UUID] )
632 NSData *data = [characteristic value];
633 if ( data.length != 19 )
635 NSLog(
@"HIDBLE: incoming data is %lu bytes should be exactly 19", (
unsigned long)data.length );
637 if ( !RingBuffer_write( &_inputReports, (
const uint8_t *)data.bytes ) )
639 uint64_t ticksNow = mach_approximate_time();
640 if ( ticksNow - s_ticksLastOverflowReport > (5ull * NSEC_PER_SEC / 10) )
642 NSLog(
@"HIDBLE: input report buffer overflow" );
643 s_ticksLastOverflowReport = ticksNow;
647 else if ( [characteristic.UUID isEqual:_bleCharacteristicReport.UUID] )
649 memset( _featureReport, 0,
sizeof(_featureReport) );
653 NSLog(
@"HIDBLE: get_feature_report error: %@", error );
654 _waitStateForReadFeatureReport = BLEDeviceWaitState_Error;
658 NSData *data = [characteristic value];
659 if ( data.length != 20 )
661 NSLog(
@"HIDBLE: incoming data is %lu bytes should be exactly 20", (
unsigned long)data.length );
663 memcpy( _featureReport, data.bytes,
MIN( data.length,
sizeof(_featureReport) ) );
664 _waitStateForReadFeatureReport = BLEDeviceWaitState_Complete;
669 - (
void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
671 if ( [characteristic.UUID isEqual:[CBUUID UUIDWithString:VALVE_REPORT_CHAR]] )
675 NSLog(
@"HIDBLE: write_feature_report error: %@", error );
676 _waitStateForWriteFeatureReport = BLEDeviceWaitState_Error;
680 _waitStateForWriteFeatureReport = BLEDeviceWaitState_Complete;
685 - (
void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
687 NSLog(
@"didUpdateNotifcationStateForCharacteristic %@ (%@)", characteristic, error );
693 #pragma mark hid_api implementation 703 return ( HIDBLEManager.sharedInstance == nil ) ? -1 : 0;
713 HIDBLEManager *bleManager = HIDBLEManager.sharedInstance;
716 [bleManager startScan:0];
720 [bleManager stopScan];
727 NSString *nssPath = [NSString stringWithUTF8String:path];
728 HIDBLEManager *bleManager = HIDBLEManager.sharedInstance;
729 NSEnumerator<HIDBLEDevice *> *
devices = [bleManager.deviceMap objectEnumerator];
731 for ( HIDBLEDevice *
device in devices )
737 if ( [
device.bleSteamController.identifier.UUIDString isEqualToString:nssPath] )
739 result = (hid_device *)
malloc(
sizeof( hid_device ) );
740 memset( result, 0,
sizeof( hid_device ) );
741 result->device_handle = (
void*)CFBridgingRetain(
device );
742 result->blocking = NO;
744 [device.bleSteamController setNotifyValue:YES forCharacteristic:device.bleCharacteristicInput];
769 dev->blocking = !nonblock;
778 if ( ( vendor_id == 0 && product_id == 0 ) ||
779 ( vendor_id == VALVE_USB_VID && product_id == D0G_BLE2_PID ) )
781 HIDBLEManager *bleManager = HIDBLEManager.sharedInstance;
782 [bleManager updateConnectedSteamControllers:false];
783 NSEnumerator<HIDBLEDevice *> *devices = [bleManager.deviceMap objectEnumerator];
784 for ( HIDBLEDevice *
device in devices )
792 if (
device.bleSteamController.state != CBPeripheralStateConnected ||
795 if (
device.ready == NO &&
device.bleCharacteristicInput != nil )
799 [device.bleSteamController setNotifyValue:YES forCharacteristic:device.bleCharacteristicInput];
805 device_info->
next = root;
807 device_info->
path = strdup(
device.bleSteamController.identifier.UUIDString.UTF8String );
819 static wchar_t s_wszManufacturer[] = L
"Valve Corporation";
820 wcsncpy(
string, s_wszManufacturer,
sizeof(s_wszManufacturer)/
sizeof(s_wszManufacturer[0]) );
826 static wchar_t s_wszProduct[] = L
"Steam Controller";
827 wcsncpy(
string, s_wszProduct,
sizeof(s_wszProduct)/
sizeof(s_wszProduct[0]) );
833 static wchar_t s_wszSerial[] = L
"12345";
834 wcsncpy(
string, s_wszSerial,
sizeof(s_wszSerial)/
sizeof(s_wszSerial[0]) );
840 HIDBLEDevice *device_handle = (__bridge HIDBLEDevice *)dev->device_handle;
842 if ( !device_handle.connected )
845 return [device_handle send_report:data length:length];
850 HIDBLEDevice *device_handle = CFBridgingRelease( dev->device_handle );
853 if ( device_handle.connected ) {
854 [device_handle.bleSteamController setNotifyValue:NO forCharacteristic:device_handle.bleCharacteristicInput];
862 HIDBLEDevice *device_handle = (__bridge HIDBLEDevice *)dev->device_handle;
864 if ( !device_handle.connected )
867 return [device_handle send_feature_report:(hidFeatureReport *)(void *)data];
872 HIDBLEDevice *device_handle = (__bridge HIDBLEDevice *)dev->device_handle;
874 if ( !device_handle.connected )
877 size_t written = [device_handle get_feature_report:data[0] into:data];
879 return written == length-1 ? (int)length : (
int)written;
884 HIDBLEDevice *device_handle = (__bridge HIDBLEDevice *)dev->device_handle;
886 if ( !device_handle.connected )
894 HIDBLEDevice *device_handle = (__bridge HIDBLEDevice *)dev->device_handle;
896 if ( !device_handle.connected )
899 if ( milliseconds != 0 )
901 NSLog(
@"hid_read_timeout with non-zero wait" );
903 int result = (int)[device_handle read_input_report:data];
904 #if FEATURE_REPORT_LOGGING 905 NSLog(
@"HIDBLE:hid_read_timeout (%d) [%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]", result,
906 data[1], data[2], data[3], data[4], data[5], data[6],
907 data[7], data[8], data[9], data[10], data[11], data[12],
908 data[13], data[14], data[15], data[16], data[17], data[18],
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
Free an enumeration Linked List.
unsigned long long uint64_t
wchar_t * manufacturer_string
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.
static SDL_AudioDeviceID device
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.
struct hid_device_info * next
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock)
Set the device handle to be non-blocking.
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device)
Close a HID device.
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.
unsigned short product_id
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 ** d
int hid_exit(void)
Finalize the HIDAPI library.
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.
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.
#define HID_API_EXPORT_CALL
int hid_init(void)
Initialize the HIDAPI library.
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 void
HID_API_EXPORT hid_device *HID_API_CALL hid_open_path(const char *path, int bExclusive)
Open a HID device by its path name.
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.
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.
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.
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.