/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.stanford.edu/ http://chuck.cs.princeton.edu/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A.-----------------------------------------------------------------------------*/ //-----------------------------------------------------------------------------// file: util_hid.cpp// desc: refactored HID joystick, keyboard, mouse support//// author: Spencer Salazar (spencer@ccrma.stanford.edu)// date: summer 2006//----------------------------------------------------------------------------- #include "chuck_def.h"#include "chuck_errmsg.h"#include "util_hid.h"#include "hidio_sdl.h" #include <limits.h>#include <vector>#include <map> using namespace std; /* device types */const t_CKUINT CK_HID_DEV_NONE = 0;const t_CKUINT CK_HID_DEV_JOYSTICK = 1;const t_CKUINT CK_HID_DEV_MOUSE = 2;const t_CKUINT CK_HID_DEV_KEYBOARD = 3;const t_CKUINT CK_HID_DEV_WIIREMOTE = 4;const t_CKUINT CK_HID_DEV_TILTSENSOR = 5;const t_CKUINT CK_HID_DEV_TABLET = 6;const t_CKUINT CK_HID_DEV_MULTITOUCH = 7;const t_CKUINT CK_HID_DEV_COUNT = 8; /* message types */const t_CKUINT CK_HID_JOYSTICK_AXIS = 0;const t_CKUINT CK_HID_BUTTON_DOWN = 1;const t_CKUINT CK_HID_BUTTON_UP = 2;const t_CKUINT CK_HID_JOYSTICK_HAT = 3;const t_CKUINT CK_HID_JOYSTICK_BALL = 4;const t_CKUINT CK_HID_MOUSE_MOTION = 5;const t_CKUINT CK_HID_MOUSE_WHEEL = 6;const t_CKUINT CK_HID_DEVICE_CONNECTED = 7;const t_CKUINT CK_HID_DEVICE_DISCONNECTED = 8;const t_CKUINT CK_HID_ACCELEROMETER = 9;const t_CKUINT CK_HID_WIIREMOTE_IR = 10;const t_CKUINT CK_HID_LED = 11;const t_CKUINT CK_HID_FORCE_FEEDBACK = 12;const t_CKUINT CK_HID_SPEAKER = 13;const t_CKUINT CK_HID_TABLET_PRESSURE = 14;const t_CKUINT CK_HID_TABLET_MOTION = 15;const t_CKUINT CK_HID_TABLET_ROTATION = 16;const t_CKUINT CK_HID_MULTITOUCH_TOUCH = 17;const t_CKUINT CK_HID_MSG_COUNT = 18; #if defined(__PLATFORM_MACOSX__) && !defined(__CHIP_MODE__)#pragma mark OS X General HID support /* TODO: *********************************************************************** Make Joystick/Mouse/Keyboard_open/_close thread safe (i.e., do all ->configure and ->startQueue calls on the Hid thread). *** DONE Make ->disconnect delete the element list *** worked around Make Keyboard, Mouse dis/reattachment work *** DONE Hid Probe *******************************************************************************/ #include <mach/mach.h>#include <mach/mach_error.h>#include <IOKit/IOKitLib.h>#include <IOKit/IOCFPlugIn.h>#include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h>#include <IOKit/hid/IOHIDLib.h>#include <IOKit/hid/IOHIDKeys.h>#include <IOKit/IOMessage.h>#include <CoreFoundation/CoreFoundation.h>#include <Carbon/Carbon.h> // check for OS X 10.4/CGEvent#include <AvailabilityMacros.h>#undef MAC_OS_X_VERSION_MIN_REQUIRED#undef MAC_OS_X_VERSION_MAX_ALLOWED#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_3#define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_10_4#include <ApplicationServices/ApplicationServices.h>#ifdef __CGEVENT_H__#define __CK_HID_CURSOR_TRACK__#endif #ifndef __DAN__#undef __CK_HID_CURSOR_TRACK__#endif #ifdef __CK_HID_WIIREMOTE__#include <IOBluetooth/IOBluetoothUserLib.h>#include "util_buffers.h"#endif // __CK_HID_WIIREMOTE__ class lockable{public: void lock() { m_mutex.acquire(); } void unlock() { m_mutex.release(); } private: XMutex m_mutex;}; template< typename _Tp, typename _Alloc = allocator< _Tp > >class xvector : public vector< _Tp, _Alloc >, public lockable{}; template <typename _Key, typename _Tp, typename _Compare = less<_Key>,typename _Alloc = allocator<pair<const _Key, _Tp> > >class xmultimap : public multimap< _Key, _Tp, _Compare, _Alloc >, public lockable{}; class OSX_Device : public lockable{public: OSX_Device() { refcount = 0; } virtual ~OSX_Device() {} virtual void open() {}; virtual void close() {}; t_CKUINT refcount; // incremented on open, decremented on close}; class OSX_Hid_Device_Element{public: OSX_Hid_Device_Element() { cookie = 0; num = 0; value = 0; usage = usage_page = 0; min = 0; max = 0; } IOHIDElementCookie cookie; t_CKINT type; t_CKINT num; t_CKINT value; t_CKINT usage_page; t_CKINT usage; t_CKINT min; t_CKINT max;}; class OSX_Hid_Device : public OSX_Device{public: OSX_Hid_Device() { configed = preconfiged = FALSE; plugInInterface = NULL; interface = NULL; queue = NULL; strncpy( name, "Device", 256 ); elements = NULL; outputs = NULL; usage = usage_page = 0; type = num = -1; buttons = -1; axes = -1; hats = -1; wheels = -1; refcount = 0; hidProperties = NULL; removal_notification = 0; // NULL; vendorID = productID = locationID = NULL; manufacturer = product = NULL; } ~OSX_Hid_Device() { cleanup(); } t_CKINT preconfigure( io_object_t ioHIDDeviceObject ); t_CKINT configure(); void enumerate_elements( CFArrayRef cfElements ); t_CKINT start(); t_CKINT stop(); t_CKBOOL is_connected() const; t_CKBOOL is_same_as( io_object_t ioHIDDeviceObject ) const; void disconnect(); void cleanup(); IOCFPlugInInterface ** plugInInterface; IOHIDDeviceInterface ** interface; // device interface IOHIDQueueInterface ** queue; // device event queue char name[256]; // uniquely identifying information /* For ChucK's purposes, HID devices are uniquely identified by the tuple of (USB device location, vendor ID, product ID, manufacturer name, product name ) */ CFNumberRef locationID; CFNumberRef vendorID; CFNumberRef productID; CFStringRef manufacturer; CFStringRef product; t_CKBOOL preconfiged, configed; t_CKINT type; t_CKINT num; t_CKINT usage_page; t_CKINT usage; map< IOHIDElementCookie, OSX_Hid_Device_Element * > * elements; /* Note: setting any of these to -1 informs the element enumerating method that we are not interested in that particular element type */ t_CKINT buttons; t_CKINT axes; t_CKINT hats; t_CKINT wheels; /* outputs are stored in a map of vectors of OSX_Hid_Device_Elements Thus if ( *outputs )[CK_HID_OUTPUT_TYPE] != NULL && ( *outputs )[CK_HID_OUTPUT_TYPE]->size() > n, ( *outputs )[CK_HID_OUTPUT_TYPE]->at( n ) is the nth output of type CK_HID_OUTPUT_TYPE. */ map< unsigned int, vector< OSX_Hid_Device_Element * > * > * outputs; CFRunLoopSourceRef eventSource; CFMutableDictionaryRef hidProperties; io_object_t removal_notification; const static t_CKINT event_queue_size = 50; // queues use wired kernel memory so should be set to as small as possible // but should account for the maximum possible events in the queue // USB updates will likely occur at 100 Hz so one must account for this rate // if states change quickly (updates are only posted on state changes)}; struct OSX_Hid_op{ enum { open, close } type; xvector< OSX_Hid_Device * > * v; xvector< OSX_Hid_Device * >::size_type index;}; #pragma mark global variables // hid run loop (event dispatcher)static CFRunLoopRef rlHid = NULL;// special hid run loop mode (limits events to hid device events only)//static const CFStringRef kCFRunLoopChuckHidMode = CFSTR( "ChucKHid" );static const CFStringRef kCFRunLoopChuckHidMode = kCFRunLoopDefaultMode; // general hid callback for device eventsstatic void Hid_callback( void * target, IOReturn result, void * refcon, void * sender ); // CFRunLoop source for open/close device operationsstatic CFRunLoopSourceRef hidOpSource = NULL;// cbuffer for open/close device operationsstatic CBufferSimple * hid_operation_buffer = NULL;// callback for open/close device operationsstatic void Hid_do_operation( void * info ); // IO iterator for new hid devices// we only keep track of this so we can release it laterio_iterator_t hid_iterator = 0; // NULL; // notification port for device add/remove eventsstatic IONotificationPortRef newDeviceNotificationPort = NULL;// callback for new devicesstatic void Hid_new_devices( void * refcon, io_iterator_t iterator );// callback for device removalstatic void Hid_device_removed( void * refcon, io_service_t service, natural_t messageType, void * messageArgument ); /* the mutexes should be acquired whenever making changes to the correspondingvectors or accessing them from a non-hid thread after the hid thread has been started */static xvector< OSX_Hid_Device * > * joysticks = NULL;static xvector< OSX_Hid_Device * > * mice = NULL;static xvector< OSX_Hid_Device * > * keyboards = NULL; static xmultimap< string, OSX_Hid_Device * > * joystick_names = NULL;static xmultimap< string, OSX_Hid_Device * > * mouse_names = NULL;static xmultimap< string, OSX_Hid_Device * > * keyboard_names = NULL; // has hid been initialized?static t_CKBOOL g_hid_init = FALSE;// table to translate keys to ASCIIstatic t_CKBYTE g_hid_key_table[256]; // cursor track stuff#ifdef __CK_HID_CURSOR_TRACK__static t_CKINT cursorX = 0;static t_CKINT cursorY = 0;static t_CKFLOAT scaledCursorX = 0;static t_CKFLOAT scaledCursorY = 0;static CFRunLoopRef rlCursorTrack = NULL;static t_CKBOOL g_ct_go = FALSE;#endif // __CK_HID_CURSOR_TRACK__ #ifdef __CK_HID_WIIREMOTE__// wii remote stuffstatic CFRunLoopSourceRef cfrlWiiRemoteSource = NULL;static void WiiRemote_cfrl_callback( void * info );#endif t_CKINT OSX_Hid_Device::preconfigure( io_object_t ioHIDDeviceObject ){ // can only be called in Hid thread, or if the hid thread hasnt started assert( rlHid == CFRunLoopGetCurrent() || rlHid == NULL ); if( preconfiged ) return 0; switch( type ) { case CK_HID_DEV_NONE: strncpy( name, "Human Interface Device", 256 ); buttons = 0; axes = 0; wheels = 0; hats = 0; break; case CK_HID_DEV_JOYSTICK: strncpy( name, "Joystick", 256 ); buttons = 0; axes = 0; wheels = 0; hats = 0; break; case CK_HID_DEV_MOUSE: strncpy( name, "Mouse", 256 ); buttons = 0; axes = 0; wheels = 0; hats = -1; break; case CK_HID_DEV_KEYBOARD: strncpy( name, "Keyboard", 256 ); buttons = 0; axes = -1; wheels = -1; hats = -1; break; } // retrieve a dictionary of device properties kern_return_t kern_result = IORegistryEntryCreateCFProperties( ioHIDDeviceObject, &hidProperties, kCFAllocatorDefault, kNilOptions); if( kern_result != KERN_SUCCESS || hidProperties == NULL ) { hidProperties = NULL; return -1; } // get the device name, and copy it into the device record CFTypeRef refCF = CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDProductKey ) ); if( refCF ) CFStringGetCString( ( CFStringRef )refCF, name, 256, kCFStringEncodingASCII ); // retrieve uniquely identifying information if( !locationID ) { locationID = ( CFNumberRef ) CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDLocationIDKey ) ); if( locationID ) CFRetain( locationID ); } if( !vendorID ) { vendorID = ( CFNumberRef ) CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDVendorIDKey ) ); if( vendorID ) CFRetain( vendorID ); } if( !productID ) { productID = ( CFNumberRef ) CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDProductIDKey ) ); if( productID ) CFRetain( productID ); } if( !manufacturer ) { manufacturer = ( CFStringRef ) CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDManufacturerKey ) ); if( manufacturer ) CFRetain( manufacturer ); } if( !product ) { product = ( CFStringRef ) CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDProductKey ) ); if( product ) CFRetain( product ); } // create plugin interface IOReturn result; SInt32 score = 0; result = IOCreatePlugInInterfaceForService( ioHIDDeviceObject, kIOHIDDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); if( result != kIOReturnSuccess ) { CFRelease( hidProperties ); hidProperties = NULL; return -1; } #ifdef __LITTLE_ENDIAN__ /* MacBooks and MacBook Pros have some sort of "phantom" trackpad, which shows up in the HID registry and claims to have no wheels. The device name is usually Trackpad with the manufacturer being Apple. This may disable legitimate Trackpads, but hopefully not... */ if( type == CK_HID_DEV_MOUSE && strncmp( "Trackpad", name, 256 ) == 0 ) { refCF = CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDManufacturerKey ) ); if( refCF != NULL && CFStringCompare( ( CFStringRef ) refCF, CFSTR( "Apple" ), 0 ) == 0 ) { preconfiged = TRUE; configure(); if( wheels == 0 ) // this is the "phantom" trackpad { // iterate through the element map, delete device element records map< IOHIDElementCookie, OSX_Hid_Device_Element * >::iterator iter, end; Lines 1–500 of 8068. Load more
/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.stanford.edu/ http://chuck.cs.princeton.edu/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: util_hid.cpp // desc: refactored HID joystick, keyboard, mouse support // // author: Spencer Salazar (spencer@ccrma.stanford.edu) // date: summer 2006 //----------------------------------------------------------------------------- #include "chuck_def.h" #include "chuck_errmsg.h" #include "util_hid.h" #include "hidio_sdl.h" #include <limits.h> #include <vector> #include <map> using namespace std; /* device types */ const t_CKUINT CK_HID_DEV_NONE = 0; const t_CKUINT CK_HID_DEV_JOYSTICK = 1; const t_CKUINT CK_HID_DEV_MOUSE = 2; const t_CKUINT CK_HID_DEV_KEYBOARD = 3; const t_CKUINT CK_HID_DEV_WIIREMOTE = 4; const t_CKUINT CK_HID_DEV_TILTSENSOR = 5; const t_CKUINT CK_HID_DEV_TABLET = 6; const t_CKUINT CK_HID_DEV_MULTITOUCH = 7; const t_CKUINT CK_HID_DEV_COUNT = 8; /* message types */ const t_CKUINT CK_HID_JOYSTICK_AXIS = 0; const t_CKUINT CK_HID_BUTTON_DOWN = 1; const t_CKUINT CK_HID_BUTTON_UP = 2; const t_CKUINT CK_HID_JOYSTICK_HAT = 3; const t_CKUINT CK_HID_JOYSTICK_BALL = 4; const t_CKUINT CK_HID_MOUSE_MOTION = 5; const t_CKUINT CK_HID_MOUSE_WHEEL = 6; const t_CKUINT CK_HID_DEVICE_CONNECTED = 7; const t_CKUINT CK_HID_DEVICE_DISCONNECTED = 8; const t_CKUINT CK_HID_ACCELEROMETER = 9; const t_CKUINT CK_HID_WIIREMOTE_IR = 10; const t_CKUINT CK_HID_LED = 11; const t_CKUINT CK_HID_FORCE_FEEDBACK = 12; const t_CKUINT CK_HID_SPEAKER = 13; const t_CKUINT CK_HID_TABLET_PRESSURE = 14; const t_CKUINT CK_HID_TABLET_MOTION = 15; const t_CKUINT CK_HID_TABLET_ROTATION = 16; const t_CKUINT CK_HID_MULTITOUCH_TOUCH = 17; const t_CKUINT CK_HID_MSG_COUNT = 18; #if defined(__PLATFORM_MACOSX__) && !defined(__CHIP_MODE__) #pragma mark OS X General HID support /* TODO: *********************************************************************** Make Joystick/Mouse/Keyboard_open/_close thread safe (i.e., do all ->configure and ->startQueue calls on the Hid thread). *** DONE Make ->disconnect delete the element list *** worked around Make Keyboard, Mouse dis/reattachment work *** DONE Hid Probe *******************************************************************************/ #include <mach/mach.h> #include <mach/mach_error.h> #include <IOKit/IOKitLib.h> #include <IOKit/IOCFPlugIn.h> #include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h> #include <IOKit/hid/IOHIDLib.h> #include <IOKit/hid/IOHIDKeys.h> #include <IOKit/IOMessage.h> #include <CoreFoundation/CoreFoundation.h> #include <Carbon/Carbon.h> // check for OS X 10.4/CGEvent #include <AvailabilityMacros.h> #undef MAC_OS_X_VERSION_MIN_REQUIRED #undef MAC_OS_X_VERSION_MAX_ALLOWED #define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_3 #define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_10_4 #include <ApplicationServices/ApplicationServices.h> #ifdef __CGEVENT_H__ #define __CK_HID_CURSOR_TRACK__ #endif #ifndef __DAN__ #undef __CK_HID_CURSOR_TRACK__ #endif #ifdef __CK_HID_WIIREMOTE__ #include <IOBluetooth/IOBluetoothUserLib.h> #include "util_buffers.h" #endif // __CK_HID_WIIREMOTE__ class lockable { public: void lock() { m_mutex.acquire(); } void unlock() { m_mutex.release(); } private: XMutex m_mutex; }; template< typename _Tp, typename _Alloc = allocator< _Tp > > class xvector : public vector< _Tp, _Alloc >, public lockable { }; template <typename _Key, typename _Tp, typename _Compare = less<_Key>, typename _Alloc = allocator<pair<const _Key, _Tp> > > class xmultimap : public multimap< _Key, _Tp, _Compare, _Alloc >, public lockable { }; class OSX_Device : public lockable { public: OSX_Device() { refcount = 0; } virtual ~OSX_Device() {} virtual void open() {}; virtual void close() {}; t_CKUINT refcount; // incremented on open, decremented on close }; class OSX_Hid_Device_Element { public: OSX_Hid_Device_Element() { cookie = 0; num = 0; value = 0; usage = usage_page = 0; min = 0; max = 0; } IOHIDElementCookie cookie; t_CKINT type; t_CKINT num; t_CKINT value; t_CKINT usage_page; t_CKINT usage; t_CKINT min; t_CKINT max; }; class OSX_Hid_Device : public OSX_Device { public: OSX_Hid_Device() { configed = preconfiged = FALSE; plugInInterface = NULL; interface = NULL; queue = NULL; strncpy( name, "Device", 256 ); elements = NULL; outputs = NULL; usage = usage_page = 0; type = num = -1; buttons = -1; axes = -1; hats = -1; wheels = -1; refcount = 0; hidProperties = NULL; removal_notification = 0; // NULL; vendorID = productID = locationID = NULL; manufacturer = product = NULL; } ~OSX_Hid_Device() { cleanup(); } t_CKINT preconfigure( io_object_t ioHIDDeviceObject ); t_CKINT configure(); void enumerate_elements( CFArrayRef cfElements ); t_CKINT start(); t_CKINT stop(); t_CKBOOL is_connected() const; t_CKBOOL is_same_as( io_object_t ioHIDDeviceObject ) const; void disconnect(); void cleanup(); IOCFPlugInInterface ** plugInInterface; IOHIDDeviceInterface ** interface; // device interface IOHIDQueueInterface ** queue; // device event queue char name[256]; // uniquely identifying information /* For ChucK's purposes, HID devices are uniquely identified by the tuple of (USB device location, vendor ID, product ID, manufacturer name, product name ) */ CFNumberRef locationID; CFNumberRef vendorID; CFNumberRef productID; CFStringRef manufacturer; CFStringRef product; t_CKBOOL preconfiged, configed; t_CKINT type; t_CKINT num; t_CKINT usage_page; t_CKINT usage; map< IOHIDElementCookie, OSX_Hid_Device_Element * > * elements; /* Note: setting any of these to -1 informs the element enumerating method that we are not interested in that particular element type */ t_CKINT buttons; t_CKINT axes; t_CKINT hats; t_CKINT wheels; /* outputs are stored in a map of vectors of OSX_Hid_Device_Elements Thus if ( *outputs )[CK_HID_OUTPUT_TYPE] != NULL && ( *outputs )[CK_HID_OUTPUT_TYPE]->size() > n, ( *outputs )[CK_HID_OUTPUT_TYPE]->at( n ) is the nth output of type CK_HID_OUTPUT_TYPE. */ map< unsigned int, vector< OSX_Hid_Device_Element * > * > * outputs; CFRunLoopSourceRef eventSource; CFMutableDictionaryRef hidProperties; io_object_t removal_notification; const static t_CKINT event_queue_size = 50; // queues use wired kernel memory so should be set to as small as possible // but should account for the maximum possible events in the queue // USB updates will likely occur at 100 Hz so one must account for this rate // if states change quickly (updates are only posted on state changes) }; struct OSX_Hid_op { enum { open, close } type; xvector< OSX_Hid_Device * > * v; xvector< OSX_Hid_Device * >::size_type index; }; #pragma mark global variables // hid run loop (event dispatcher) static CFRunLoopRef rlHid = NULL; // special hid run loop mode (limits events to hid device events only) //static const CFStringRef kCFRunLoopChuckHidMode = CFSTR( "ChucKHid" ); static const CFStringRef kCFRunLoopChuckHidMode = kCFRunLoopDefaultMode; // general hid callback for device events static void Hid_callback( void * target, IOReturn result, void * refcon, void * sender ); // CFRunLoop source for open/close device operations static CFRunLoopSourceRef hidOpSource = NULL; // cbuffer for open/close device operations static CBufferSimple * hid_operation_buffer = NULL; // callback for open/close device operations static void Hid_do_operation( void * info ); // IO iterator for new hid devices // we only keep track of this so we can release it later io_iterator_t hid_iterator = 0; // NULL; // notification port for device add/remove events static IONotificationPortRef newDeviceNotificationPort = NULL; // callback for new devices static void Hid_new_devices( void * refcon, io_iterator_t iterator ); // callback for device removal static void Hid_device_removed( void * refcon, io_service_t service, natural_t messageType, void * messageArgument ); /* the mutexes should be acquired whenever making changes to the corresponding vectors or accessing them from a non-hid thread after the hid thread has been started */ static xvector< OSX_Hid_Device * > * joysticks = NULL; static xvector< OSX_Hid_Device * > * mice = NULL; static xvector< OSX_Hid_Device * > * keyboards = NULL; static xmultimap< string, OSX_Hid_Device * > * joystick_names = NULL; static xmultimap< string, OSX_Hid_Device * > * mouse_names = NULL; static xmultimap< string, OSX_Hid_Device * > * keyboard_names = NULL; // has hid been initialized? static t_CKBOOL g_hid_init = FALSE; // table to translate keys to ASCII static t_CKBYTE g_hid_key_table[256]; // cursor track stuff #ifdef __CK_HID_CURSOR_TRACK__ static t_CKINT cursorX = 0; static t_CKINT cursorY = 0; static t_CKFLOAT scaledCursorX = 0; static t_CKFLOAT scaledCursorY = 0; static CFRunLoopRef rlCursorTrack = NULL; static t_CKBOOL g_ct_go = FALSE; #endif // __CK_HID_CURSOR_TRACK__ #ifdef __CK_HID_WIIREMOTE__ // wii remote stuff static CFRunLoopSourceRef cfrlWiiRemoteSource = NULL; static void WiiRemote_cfrl_callback( void * info ); #endif t_CKINT OSX_Hid_Device::preconfigure( io_object_t ioHIDDeviceObject ) { // can only be called in Hid thread, or if the hid thread hasnt started assert( rlHid == CFRunLoopGetCurrent() || rlHid == NULL ); if( preconfiged ) return 0; switch( type ) { case CK_HID_DEV_NONE: strncpy( name, "Human Interface Device", 256 ); buttons = 0; axes = 0; wheels = 0; hats = 0; break; case CK_HID_DEV_JOYSTICK: strncpy( name, "Joystick", 256 ); buttons = 0; axes = 0; wheels = 0; hats = 0; break; case CK_HID_DEV_MOUSE: strncpy( name, "Mouse", 256 ); buttons = 0; axes = 0; wheels = 0; hats = -1; break; case CK_HID_DEV_KEYBOARD: strncpy( name, "Keyboard", 256 ); buttons = 0; axes = -1; wheels = -1; hats = -1; break; } // retrieve a dictionary of device properties kern_return_t kern_result = IORegistryEntryCreateCFProperties( ioHIDDeviceObject, &hidProperties, kCFAllocatorDefault, kNilOptions); if( kern_result != KERN_SUCCESS || hidProperties == NULL ) { hidProperties = NULL; return -1; } // get the device name, and copy it into the device record CFTypeRef refCF = CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDProductKey ) ); if( refCF ) CFStringGetCString( ( CFStringRef )refCF, name, 256, kCFStringEncodingASCII ); // retrieve uniquely identifying information if( !locationID ) { locationID = ( CFNumberRef ) CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDLocationIDKey ) ); if( locationID ) CFRetain( locationID ); } if( !vendorID ) { vendorID = ( CFNumberRef ) CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDVendorIDKey ) ); if( vendorID ) CFRetain( vendorID ); } if( !productID ) { productID = ( CFNumberRef ) CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDProductIDKey ) ); if( productID ) CFRetain( productID ); } if( !manufacturer ) { manufacturer = ( CFStringRef ) CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDManufacturerKey ) ); if( manufacturer ) CFRetain( manufacturer ); } if( !product ) { product = ( CFStringRef ) CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDProductKey ) ); if( product ) CFRetain( product ); } // create plugin interface IOReturn result; SInt32 score = 0; result = IOCreatePlugInInterfaceForService( ioHIDDeviceObject, kIOHIDDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); if( result != kIOReturnSuccess ) { CFRelease( hidProperties ); hidProperties = NULL; return -1; } #ifdef __LITTLE_ENDIAN__ /* MacBooks and MacBook Pros have some sort of "phantom" trackpad, which shows up in the HID registry and claims to have no wheels. The device name is usually Trackpad with the manufacturer being Apple. This may disable legitimate Trackpads, but hopefully not... */ if( type == CK_HID_DEV_MOUSE && strncmp( "Trackpad", name, 256 ) == 0 ) { refCF = CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDManufacturerKey ) ); if( refCF != NULL && CFStringCompare( ( CFStringRef ) refCF, CFSTR( "Apple" ), 0 ) == 0 ) { preconfiged = TRUE; configure(); if( wheels == 0 ) // this is the "phantom" trackpad { // iterate through the element map, delete device element records map< IOHIDElementCookie, OSX_Hid_Device_Element * >::iterator iter, end;