Removed dependency on C++ runtime on iOS

This commit is contained in:
Sam Lantinga 2018-08-21 19:42:19 -07:00
parent c6647bf9c9
commit e9f6805fc6
2 changed files with 122 additions and 94 deletions

View File

@ -203,7 +203,8 @@
F30D9CA5212CD0BF0047DF2E /* SDL_coremotionsensor.m in Sources */ = {isa = PBXBuildFile; fileRef = F30D9CA3212CD0BF0047DF2E /* SDL_coremotionsensor.m */; }; F30D9CA5212CD0BF0047DF2E /* SDL_coremotionsensor.m in Sources */ = {isa = PBXBuildFile; fileRef = F30D9CA3212CD0BF0047DF2E /* SDL_coremotionsensor.m */; };
F30D9CA6212CD0BF0047DF2E /* SDL_coremotionsensor.m in Sources */ = {isa = PBXBuildFile; fileRef = F30D9CA3212CD0BF0047DF2E /* SDL_coremotionsensor.m */; }; F30D9CA6212CD0BF0047DF2E /* SDL_coremotionsensor.m in Sources */ = {isa = PBXBuildFile; fileRef = F30D9CA3212CD0BF0047DF2E /* SDL_coremotionsensor.m */; };
F30D9CA7212CD0BF0047DF2E /* SDL_coremotionsensor.h in Headers */ = {isa = PBXBuildFile; fileRef = F30D9CA4212CD0BF0047DF2E /* SDL_coremotionsensor.h */; }; F30D9CA7212CD0BF0047DF2E /* SDL_coremotionsensor.h in Headers */ = {isa = PBXBuildFile; fileRef = F30D9CA4212CD0BF0047DF2E /* SDL_coremotionsensor.h */; };
F3BDD77620F51C3C004ECBF3 /* hid.mm in Sources */ = {isa = PBXBuildFile; fileRef = F3BDD77520F51C3C004ECBF3 /* hid.mm */; }; F30D9CC6212CE92C0047DF2E /* hid.m in Sources */ = {isa = PBXBuildFile; fileRef = F30D9CC5212CE92C0047DF2E /* hid.m */; };
F30D9CC7212CE92C0047DF2E /* hid.m in Sources */ = {isa = PBXBuildFile; fileRef = F30D9CC5212CE92C0047DF2E /* hid.m */; };
F3BDD79220F51CB8004ECBF3 /* SDL_hidapi_xbox360.c in Sources */ = {isa = PBXBuildFile; fileRef = F3BDD78B20F51CB8004ECBF3 /* SDL_hidapi_xbox360.c */; }; F3BDD79220F51CB8004ECBF3 /* SDL_hidapi_xbox360.c in Sources */ = {isa = PBXBuildFile; fileRef = F3BDD78B20F51CB8004ECBF3 /* SDL_hidapi_xbox360.c */; };
F3BDD79320F51CB8004ECBF3 /* SDL_hidapi_xbox360.c in Sources */ = {isa = PBXBuildFile; fileRef = F3BDD78B20F51CB8004ECBF3 /* SDL_hidapi_xbox360.c */; }; F3BDD79320F51CB8004ECBF3 /* SDL_hidapi_xbox360.c in Sources */ = {isa = PBXBuildFile; fileRef = F3BDD78B20F51CB8004ECBF3 /* SDL_hidapi_xbox360.c */; };
F3BDD79420F51CB8004ECBF3 /* SDL_hidapi_switch.c in Sources */ = {isa = PBXBuildFile; fileRef = F3BDD78C20F51CB8004ECBF3 /* SDL_hidapi_switch.c */; }; F3BDD79420F51CB8004ECBF3 /* SDL_hidapi_switch.c in Sources */ = {isa = PBXBuildFile; fileRef = F3BDD78C20F51CB8004ECBF3 /* SDL_hidapi_switch.c */; };
@ -535,7 +536,7 @@
F30D9C9D212CD0990047DF2E /* SDL_sensor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_sensor.c; sourceTree = "<group>"; }; F30D9C9D212CD0990047DF2E /* SDL_sensor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_sensor.c; sourceTree = "<group>"; };
F30D9CA3212CD0BF0047DF2E /* SDL_coremotionsensor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_coremotionsensor.m; sourceTree = "<group>"; }; F30D9CA3212CD0BF0047DF2E /* SDL_coremotionsensor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_coremotionsensor.m; sourceTree = "<group>"; };
F30D9CA4212CD0BF0047DF2E /* SDL_coremotionsensor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_coremotionsensor.h; sourceTree = "<group>"; }; F30D9CA4212CD0BF0047DF2E /* SDL_coremotionsensor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_coremotionsensor.h; sourceTree = "<group>"; };
F3BDD77520F51C3C004ECBF3 /* hid.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = hid.mm; sourceTree = "<group>"; }; F30D9CC5212CE92C0047DF2E /* hid.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = hid.m; sourceTree = "<group>"; };
F3BDD78B20F51CB8004ECBF3 /* SDL_hidapi_xbox360.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_xbox360.c; sourceTree = "<group>"; }; F3BDD78B20F51CB8004ECBF3 /* SDL_hidapi_xbox360.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_xbox360.c; sourceTree = "<group>"; };
F3BDD78C20F51CB8004ECBF3 /* SDL_hidapi_switch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_switch.c; sourceTree = "<group>"; }; F3BDD78C20F51CB8004ECBF3 /* SDL_hidapi_switch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_switch.c; sourceTree = "<group>"; };
F3BDD78D20F51CB8004ECBF3 /* SDL_hidapi_xboxone.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_xboxone.c; sourceTree = "<group>"; }; F3BDD78D20F51CB8004ECBF3 /* SDL_hidapi_xboxone.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_xboxone.c; sourceTree = "<group>"; };
@ -859,7 +860,7 @@
F3BDD77420F51C18004ECBF3 /* ios */ = { F3BDD77420F51C18004ECBF3 /* ios */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
F3BDD77520F51C3C004ECBF3 /* hid.mm */, F30D9CC5212CE92C0047DF2E /* hid.m */,
); );
path = ios; path = ios;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1520,6 +1521,7 @@
FAB598421BB5C31500BE72C5 /* SDL_quit.c in Sources */, FAB598421BB5C31500BE72C5 /* SDL_quit.c in Sources */,
FAB598441BB5C31500BE72C5 /* SDL_touch.c in Sources */, FAB598441BB5C31500BE72C5 /* SDL_touch.c in Sources */,
FAB598461BB5C31500BE72C5 /* SDL_windowevents.c in Sources */, FAB598461BB5C31500BE72C5 /* SDL_windowevents.c in Sources */,
F30D9CC7212CE92C0047DF2E /* hid.m in Sources */,
FAB598491BB5C31600BE72C5 /* SDL_rwopsbundlesupport.m in Sources */, FAB598491BB5C31600BE72C5 /* SDL_rwopsbundlesupport.m in Sources */,
FAB5984A1BB5C31600BE72C5 /* SDL_rwops.c in Sources */, FAB5984A1BB5C31600BE72C5 /* SDL_rwops.c in Sources */,
FAB5984B1BB5C31600BE72C5 /* SDL_sysfilesystem.m in Sources */, FAB5984B1BB5C31600BE72C5 /* SDL_sysfilesystem.m in Sources */,
@ -1631,6 +1633,7 @@
FD6526750DE8FCDD002AD96B /* SDL_windowevents.c in Sources */, FD6526750DE8FCDD002AD96B /* SDL_windowevents.c in Sources */,
4D7516FB1EE1C28A00820EEA /* SDL_uikitmetalview.m in Sources */, 4D7516FB1EE1C28A00820EEA /* SDL_uikitmetalview.m in Sources */,
FD6526760DE8FCDD002AD96B /* SDL_rwops.c in Sources */, FD6526760DE8FCDD002AD96B /* SDL_rwops.c in Sources */,
F30D9CC6212CE92C0047DF2E /* hid.m in Sources */,
4D7517201EE1D98200820EEA /* SDL_vulkan_utils.c in Sources */, 4D7517201EE1D98200820EEA /* SDL_vulkan_utils.c in Sources */,
FD6526780DE8FCDD002AD96B /* SDL_error.c in Sources */, FD6526780DE8FCDD002AD96B /* SDL_error.c in Sources */,
FD65267A0DE8FCDD002AD96B /* SDL.c in Sources */, FD65267A0DE8FCDD002AD96B /* SDL.c in Sources */,
@ -1716,7 +1719,6 @@
AA628ADB159369E3005138DD /* SDL_rotate.c in Sources */, AA628ADB159369E3005138DD /* SDL_rotate.c in Sources */,
AA126AD51617C5E7005ABC8F /* SDL_uikitmodes.m in Sources */, AA126AD51617C5E7005ABC8F /* SDL_uikitmodes.m in Sources */,
AA704DD7162AA90A0076D1C1 /* SDL_dropevents.c in Sources */, AA704DD7162AA90A0076D1C1 /* SDL_dropevents.c in Sources */,
F3BDD77620F51C3C004ECBF3 /* hid.mm in Sources */,
AABCC3951640643D00AB8930 /* SDL_uikitmessagebox.m in Sources */, AABCC3951640643D00AB8930 /* SDL_uikitmessagebox.m in Sources */,
AA0AD06216647BBB00CE5896 /* SDL_gamecontroller.c in Sources */, AA0AD06216647BBB00CE5896 /* SDL_gamecontroller.c in Sources */,
AA0F8495178D5F1A00823F9D /* SDL_systls.c in Sources */, AA0F8495178D5F1A00823F9D /* SDL_systls.c in Sources */,

View File

@ -36,7 +36,9 @@ typedef uint64_t uint64;
// TODO: create CBUUID's in __attribute__((constructor)) rather than doing [CBUUID UUIDWithString:...] everywhere // TODO: create CBUUID's in __attribute__((constructor)) rather than doing [CBUUID UUIDWithString:...] everywhere
#pragma pack(push,1) #pragma pack(push,1)
struct bluetoothSegment {
typedef struct
{
uint8_t segmentHeader; uint8_t segmentHeader;
uint8_t featureReportMessageID; uint8_t featureReportMessageID;
uint8_t length; uint8_t length;
@ -47,11 +49,9 @@ struct bluetoothSegment {
uint64_t ulPayload; uint64_t ulPayload;
uint8_t ucPayload[15]; uint8_t ucPayload[15];
}; };
} bluetoothSegment;
size_t size() { return length + 3; } typedef struct {
};
struct hidFeatureReport {
uint8_t id; uint8_t id;
union { union {
bluetoothSegment segment; bluetoothSegment segment;
@ -68,71 +68,83 @@ struct hidFeatureReport {
}; };
}; };
}; };
}; } hidFeatureReport;
#pragma pack(pop) #pragma pack(pop)
template <typename T, size_t cbElem, size_t nElem> size_t GetBluetoothSegmentSize(bluetoothSegment *segment)
struct RingBuffer { {
return segment->length + 3;
}
#define RingBuffer_cbElem 19
#define RingBuffer_nElem 4096
typedef struct {
int _first, _last; int _first, _last;
uint8_t _data[ ( nElem * cbElem ) ]; uint8_t _data[ ( RingBuffer_nElem * RingBuffer_cbElem ) ];
pthread_mutex_t accessLock; pthread_mutex_t accessLock;
} RingBuffer;
RingBuffer() { _first = -1; _last = 0; pthread_mutex_init( &accessLock, 0 ); } static void RingBuffer_init( RingBuffer *this )
{
this->_first = -1;
this->_last = 0;
pthread_mutex_init( &this->accessLock, 0 );
}
bool write( const T *src ) static bool RingBuffer_write( RingBuffer *this, const uint8_t *src )
{ {
pthread_mutex_lock( &accessLock ); pthread_mutex_lock( &this->accessLock );
memcpy( &_data[ _last ], src, cbElem ); memcpy( &this->_data[ this->_last ], src, RingBuffer_cbElem );
if ( _first == -1 ) if ( this->_first == -1 )
{ {
_first = _last; this->_first = this->_last;
} }
_last = ( _last + cbElem ) % (nElem * cbElem); this->_last = ( this->_last + RingBuffer_cbElem ) % (RingBuffer_nElem * RingBuffer_cbElem);
if ( _last == _first ) if ( this->_last == this->_first )
{ {
_first = ( _first + cbElem ) % (nElem * cbElem); this->_first = ( this->_first + RingBuffer_cbElem ) % (RingBuffer_nElem * RingBuffer_cbElem);
pthread_mutex_unlock( &accessLock ); pthread_mutex_unlock( &this->accessLock );
return false; return false;
} }
pthread_mutex_unlock( &accessLock ); pthread_mutex_unlock( &this->accessLock );
return true; return true;
} }
bool read( T *dst ) static bool RingBuffer_read( RingBuffer *this, uint8_t *dst )
{ {
pthread_mutex_lock( &accessLock ); pthread_mutex_lock( &this->accessLock );
if ( _first == -1 ) if ( this->_first == -1 )
{ {
pthread_mutex_unlock( &accessLock ); pthread_mutex_unlock( &this->accessLock );
return false; return false;
} }
memcpy( dst, &_data[ _first ], cbElem ); memcpy( dst, &this->_data[ this->_first ], RingBuffer_cbElem );
_first = ( _first + cbElem ) % (nElem * cbElem); this->_first = ( this->_first + RingBuffer_cbElem ) % (RingBuffer_nElem * RingBuffer_cbElem);
if ( _first == _last ) if ( this->_first == this->_last )
{ {
_first = -1; this->_first = -1;
} }
pthread_mutex_unlock( &accessLock ); pthread_mutex_unlock( &this->accessLock );
return true; return true;
} }
};
#pragma mark HIDBLEDevice Definition #pragma mark HIDBLEDevice Definition
enum BLEDeviceWaitState typedef enum
{ {
None, BLEDeviceWaitState_None,
Waiting, BLEDeviceWaitState_Waiting,
Complete, BLEDeviceWaitState_Complete,
Error BLEDeviceWaitState_Error
}; } BLEDeviceWaitState;
@interface HIDBLEDevice : NSObject <CBPeripheralDelegate> @interface HIDBLEDevice : NSObject <CBPeripheralDelegate>
{ {
RingBuffer<uint8_t, 19, 4096> _inputReports; RingBuffer _inputReports;
uint8_t _featureReport[20]; uint8_t _featureReport[20];
BLEDeviceWaitState _waitStateForReadFeatureReport; BLEDeviceWaitState _waitStateForReadFeatureReport;
BLEDeviceWaitState _waitStateForWriteFeatureReport; BLEDeviceWaitState _waitStateForWriteFeatureReport;
} }
@ -419,6 +431,7 @@ static void process_pending_events()
{ {
if ( self = [super init] ) if ( self = [super init] )
{ {
RingBuffer_init( &_inputReports );
self.bleSteamController = nil; self.bleSteamController = nil;
self.bleCharacteristicInput = nil; self.bleCharacteristicInput = nil;
self.bleCharacteristicReport = nil; self.bleCharacteristicReport = nil;
@ -432,6 +445,7 @@ static void process_pending_events()
{ {
if ( self = [super init] ) if ( self = [super init] )
{ {
RingBuffer_init( &_inputReports );
_connected = NO; _connected = NO;
_ready = NO; _ready = NO;
self.bleSteamController = peripheral; self.bleSteamController = peripheral;
@ -460,7 +474,7 @@ static void process_pending_events()
- (size_t)read_input_report:(uint8_t *)dst - (size_t)read_input_report:(uint8_t *)dst
{ {
if ( _inputReports.read( dst+1 ) ) if ( RingBuffer_read( &_inputReports, dst+1 ) )
{ {
*dst = 0x03; *dst = 0x03;
return 20; return 20;
@ -479,14 +493,14 @@ static void process_pending_events()
#if FEATURE_REPORT_LOGGING #if FEATURE_REPORT_LOGGING
uint8_t *reportBytes = (uint8_t *)report; uint8_t *reportBytes = (uint8_t *)report;
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]", report->segment.size(), 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 ),
reportBytes[1], reportBytes[2], reportBytes[3], reportBytes[4], reportBytes[5], reportBytes[6], reportBytes[1], reportBytes[2], reportBytes[3], reportBytes[4], reportBytes[5], reportBytes[6],
reportBytes[7], reportBytes[8], reportBytes[9], reportBytes[10], reportBytes[11], reportBytes[12], reportBytes[7], reportBytes[8], reportBytes[9], reportBytes[10], reportBytes[11], reportBytes[12],
reportBytes[13], reportBytes[14], reportBytes[15], reportBytes[16], reportBytes[17], reportBytes[18], reportBytes[13], reportBytes[14], reportBytes[15], reportBytes[16], reportBytes[17], reportBytes[18],
reportBytes[19] ); reportBytes[19] );
#endif #endif
int sendSize = (int)report->segment.size(); int sendSize = (int)GetBluetoothSegmentSize( &report->segment );
if ( sendSize > 20 ) if ( sendSize > 20 )
sendSize = 20; sendSize = 20;
@ -501,43 +515,43 @@ static void process_pending_events()
#else #else
// this is technically the correct send_feature_report logic if you want to make sure it gets through and is // this is technically the correct send_feature_report logic if you want to make sure it gets through and is
// acknowledged or errors out // acknowledged or errors out
_waitStateForWriteFeatureReport = BLEDeviceWaitState::Waiting; _waitStateForWriteFeatureReport = BLEDeviceWaitState_Waiting;
[_bleSteamController writeValue:[NSData dataWithBytes:&report->segment length:sendSize [_bleSteamController writeValue:[NSData dataWithBytes:&report->segment length:sendSize
] forCharacteristic:_bleCharacteristicReport type:CBCharacteristicWriteWithResponse]; ] forCharacteristic:_bleCharacteristicReport type:CBCharacteristicWriteWithResponse];
while ( _waitStateForWriteFeatureReport == BLEDeviceWaitState::Waiting ) while ( _waitStateForWriteFeatureReport == BLEDeviceWaitState_Waiting )
{ {
process_pending_events(); process_pending_events();
} }
if ( _waitStateForWriteFeatureReport == BLEDeviceWaitState::Error ) if ( _waitStateForWriteFeatureReport == BLEDeviceWaitState_Error )
{ {
_waitStateForWriteFeatureReport = BLEDeviceWaitState::None; _waitStateForWriteFeatureReport = BLEDeviceWaitState_None;
return -1; return -1;
} }
_waitStateForWriteFeatureReport = BLEDeviceWaitState::None; _waitStateForWriteFeatureReport = BLEDeviceWaitState_None;
return 19; return 19;
#endif #endif
} }
- (int)get_feature_report:(uint8_t)feature into:(uint8_t *)buffer - (int)get_feature_report:(uint8_t)feature into:(uint8_t *)buffer
{ {
_waitStateForReadFeatureReport = BLEDeviceWaitState::Waiting; _waitStateForReadFeatureReport = BLEDeviceWaitState_Waiting;
[_bleSteamController readValueForCharacteristic:_bleCharacteristicReport]; [_bleSteamController readValueForCharacteristic:_bleCharacteristicReport];
while ( _waitStateForReadFeatureReport == BLEDeviceWaitState::Waiting ) while ( _waitStateForReadFeatureReport == BLEDeviceWaitState_Waiting )
process_pending_events(); process_pending_events();
if ( _waitStateForReadFeatureReport == BLEDeviceWaitState::Error ) if ( _waitStateForReadFeatureReport == BLEDeviceWaitState_Error )
{ {
_waitStateForReadFeatureReport = BLEDeviceWaitState::None; _waitStateForReadFeatureReport = BLEDeviceWaitState_None;
return -1; return -1;
} }
memcpy( buffer, _featureReport, sizeof(_featureReport) ); memcpy( buffer, _featureReport, sizeof(_featureReport) );
_waitStateForReadFeatureReport = BLEDeviceWaitState::None; _waitStateForReadFeatureReport = BLEDeviceWaitState_None;
#if FEATURE_REPORT_LOGGING #if FEATURE_REPORT_LOGGING
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]", 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]",
@ -617,7 +631,7 @@ static void process_pending_events()
{ {
NSLog( @"HIDBLE: incoming data is %lu bytes should be exactly 19", (unsigned long)data.length ); NSLog( @"HIDBLE: incoming data is %lu bytes should be exactly 19", (unsigned long)data.length );
} }
if ( !_inputReports.write( (const uint8_t *)data.bytes ) ) if ( !RingBuffer_write( &_inputReports, (const uint8_t *)data.bytes ) )
{ {
uint64_t ticksNow = mach_approximate_time(); uint64_t ticksNow = mach_approximate_time();
if ( ticksNow - s_ticksLastOverflowReport > (5ull * NSEC_PER_SEC / 10) ) if ( ticksNow - s_ticksLastOverflowReport > (5ull * NSEC_PER_SEC / 10) )
@ -634,7 +648,7 @@ static void process_pending_events()
if ( error != nil ) if ( error != nil )
{ {
NSLog( @"HIDBLE: get_feature_report error: %@", error ); NSLog( @"HIDBLE: get_feature_report error: %@", error );
_waitStateForReadFeatureReport = BLEDeviceWaitState::Error; _waitStateForReadFeatureReport = BLEDeviceWaitState_Error;
} }
else else
{ {
@ -644,7 +658,7 @@ static void process_pending_events()
NSLog( @"HIDBLE: incoming data is %lu bytes should be exactly 20", (unsigned long)data.length ); NSLog( @"HIDBLE: incoming data is %lu bytes should be exactly 20", (unsigned long)data.length );
} }
memcpy( _featureReport, data.bytes, MIN( data.length, sizeof(_featureReport) ) ); memcpy( _featureReport, data.bytes, MIN( data.length, sizeof(_featureReport) ) );
_waitStateForReadFeatureReport = BLEDeviceWaitState::Complete; _waitStateForReadFeatureReport = BLEDeviceWaitState_Complete;
} }
} }
} }
@ -656,11 +670,11 @@ static void process_pending_events()
if ( error != nil ) if ( error != nil )
{ {
NSLog( @"HIDBLE: write_feature_report error: %@", error ); NSLog( @"HIDBLE: write_feature_report error: %@", error );
_waitStateForWriteFeatureReport = BLEDeviceWaitState::Error; _waitStateForWriteFeatureReport = BLEDeviceWaitState_Error;
} }
else else
{ {
_waitStateForWriteFeatureReport = BLEDeviceWaitState::Complete; _waitStateForWriteFeatureReport = BLEDeviceWaitState_Complete;
} }
} }
} }
@ -676,7 +690,7 @@ static void process_pending_events()
#pragma mark hid_api implementation #pragma mark hid_api implementation
struct hid_device_ { struct hid_device_ {
HIDBLEDevice *device_handle; void *device_handle;
int blocking; int blocking;
hid_device *next; hid_device *next;
}; };
@ -721,7 +735,7 @@ hid_device * HID_API_EXPORT hid_open_path( const char *path, int bExclusive /* =
{ {
result = (hid_device *)malloc( sizeof( hid_device ) ); result = (hid_device *)malloc( sizeof( hid_device ) );
memset( result, 0, sizeof( hid_device ) ); memset( result, 0, sizeof( hid_device ) );
result->device_handle = device; result->device_handle = (void*)CFBridgingRetain( device );
result->blocking = NO; result->blocking = NO;
// enable reporting input events on the characteristic // enable reporting input events on the characteristic
[device.bleSteamController setNotifyValue:YES forCharacteristic:device.bleCharacteristicInput]; [device.bleSteamController setNotifyValue:YES forCharacteristic:device.bleCharacteristicInput];
@ -783,8 +797,8 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
} }
continue; continue;
} }
hid_device_info *device_info = (hid_device_info *)malloc( sizeof(hid_device_info) ); struct hid_device_info *device_info = (struct hid_device_info *)malloc( sizeof(struct hid_device_info) );
memset( device_info, 0, sizeof(hid_device_info) ); memset( device_info, 0, sizeof(struct hid_device_info) );
device_info->next = root; device_info->next = root;
root = device_info; root = device_info;
device_info->path = strdup( device.bleSteamController.identifier.UUIDString.UTF8String ); device_info->path = strdup( device.bleSteamController.identifier.UUIDString.UTF8String );
@ -820,17 +834,21 @@ int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *s
int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
{ {
if ( !dev->device_handle.connected ) HIDBLEDevice *device_handle = (__bridge HIDBLEDevice *)dev->device_handle;
if ( !device_handle.connected )
return -1; return -1;
return [dev->device_handle send_report:data length:length]; return [device_handle send_report:data length:length];
} }
void HID_API_EXPORT hid_close(hid_device *dev) void HID_API_EXPORT hid_close(hid_device *dev)
{ {
HIDBLEDevice *device_handle = CFBridgingRelease( dev->device_handle );
// disable reporting input events on the characteristic // disable reporting input events on the characteristic
if ( dev->device_handle.connected ) { if ( device_handle.connected ) {
[dev->device_handle.bleSteamController setNotifyValue:NO forCharacteristic:dev->device_handle.bleCharacteristicInput]; [device_handle.bleSteamController setNotifyValue:NO forCharacteristic:device_handle.bleCharacteristicInput];
} }
free( dev ); free( dev );
@ -838,25 +856,31 @@ void HID_API_EXPORT hid_close(hid_device *dev)
int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
{ {
if ( !dev->device_handle.connected ) HIDBLEDevice *device_handle = (__bridge HIDBLEDevice *)dev->device_handle;
if ( !device_handle.connected )
return -1; return -1;
return [dev->device_handle send_feature_report:(hidFeatureReport *)(void *)data]; return [device_handle send_feature_report:(hidFeatureReport *)(void *)data];
} }
int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
{ {
if ( !dev->device_handle.connected ) HIDBLEDevice *device_handle = (__bridge HIDBLEDevice *)dev->device_handle;
if ( !device_handle.connected )
return -1; return -1;
size_t written = [dev->device_handle get_feature_report:data[0] into:data]; size_t written = [device_handle get_feature_report:data[0] into:data];
return written == length-1 ? (int)length : (int)written; return written == length-1 ? (int)length : (int)written;
} }
int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
{ {
if ( !dev->device_handle.connected ) HIDBLEDevice *device_handle = (__bridge HIDBLEDevice *)dev->device_handle;
if ( !device_handle.connected )
return -1; return -1;
return hid_read_timeout(dev, data, length, 0); return hid_read_timeout(dev, data, length, 0);
@ -864,14 +888,16 @@ int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
{ {
if ( !dev->device_handle.connected ) HIDBLEDevice *device_handle = (__bridge HIDBLEDevice *)dev->device_handle;
if ( !device_handle.connected )
return -1; return -1;
if ( milliseconds != 0 ) if ( milliseconds != 0 )
{ {
NSLog( @"hid_read_timeout with non-zero wait" ); NSLog( @"hid_read_timeout with non-zero wait" );
} }
int result = (int)[dev->device_handle read_input_report:data]; int result = (int)[device_handle read_input_report:data];
#if FEATURE_REPORT_LOGGING #if FEATURE_REPORT_LOGGING
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, 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,
data[1], data[2], data[3], data[4], data[5], data[6], data[1], data[2], data[3], data[4], data[5], data[6],