📄 osx.c
字号:
/*Copyright (c) 2003-2007 Ryan C. Gordon and others.http://icculus.org/manymouse/This software is provided 'as-is', without any express or implied warranty.In no event will the authors be held liable for any damages arising fromthe use of this software.Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute itfreely, subject to the following restrictions:1. The origin of this software must not be misrepresented; you must notclaim that you wrote the original software. If you use this software in aproduct, an acknowledgment in the product documentation would beappreciated but is not required.2. Altered source versions must be plainly marked as such, and must not bemisrepresented as being the original software.3. This notice may not be removed or altered from any source distribution. Ryan C. Gordon <icculus@icculus.org>*///Support for MacOS X via the HID Manager APIs.#include "mm.h"#if ( (defined(__MACH__)) && (defined(__APPLE__)) )/* * This source is almost entirely lifted from Apple's HID Utilities * example source code, written by George Warner: * * http://developer.apple.com/samplecode/HID_Utilities_Source/HID_Utilities_Source.html * * The source license to HID Utilities allows this sort of blatant stealing. * * Patches to HID Utilities have comments like "ryan added this", otherwise, * I just tried to cut down that package to the smallest set of functions * I needed. * * Scroll down for "-- END HID UTILITIES --" to see the ManyMouse glue code. */#include <Carbon/Carbon.h>#include <IOKit/IOTypes.h>// 10.0.x//#include <IOKit/IOUSBHIDParser.h>// 10.1.x#include <IOKit/hid/IOHIDUsageTables.h>#include <IOKit/hid/IOHIDLib.h>#include <IOKit/IOCFPlugIn.h>#include <IOKit/IOKitLib.h>#include <IOKit/IOMessage.h>#define USE_NOTIFICATIONS 1#define HIDREPORTERRORNUM(s,n) do {} while (false)#define HIDREPORTERROR(s) do {} while (false)typedef enum HIDElementTypeMask{ kHIDElementTypeInput = 1 << 1, kHIDElementTypeOutput = 1 << 2, kHIDElementTypeFeature = 1 << 3, kHIDElementTypeCollection = 1 << 4, kHIDElementTypeIO = kHIDElementTypeInput | kHIDElementTypeOutput | kHIDElementTypeFeature, kHIDElementTypeAll = kHIDElementTypeIO | kHIDElementTypeCollection}HIDElementTypeMask;enum{ kDefaultUserMin = 0, // default user min and max used for scaling kDefaultUserMax = 255};enum{ kDeviceQueueSize = 50 // this is 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 of // if states change quickly (updates are only posted on state changes)};struct recElement{ unsigned long type; // the type defined by IOHIDElementType in IOHIDKeys.h long usagePage; // usage page from IOUSBHIDParser.h which defines general usage long usage; // usage within above page from IOUSBHIDParser.h which defines specific usage void * cookie; // unique value (within device of specific vendorID and productID) which identifies element, will NOT change long min; // reported min value possible long max; // reported max value possible long scaledMin; // reported scaled min value possible long scaledMax; // reported scaled max value possible long size; // size in bits of data return from element unsigned char relative; // are reports relative to last report (deltas) unsigned char wrapping; // does element wrap around (one value higher than max is min) unsigned char nonLinear; // are the values reported non-linear relative to element movement unsigned char preferredState; // does element have a preferred state (such as a button) unsigned char nullState; // does element have null state long units; // units value is reported in (not used very often) long unitExp; // exponent for units (also not used very often) char name[256]; // name of element (c string)// runtime variables long calMin; // min returned value long calMax; // max returned value (calibrate call) long userMin; // user set value to scale to (scale call) long userMax; struct recElement * pPrevious; // previous element (NULL at list head) struct recElement * pChild; // next child (only of collections) struct recElement * pSibling; // next sibling (for elements and collections) long depth;};typedef struct recElement recElement;typedef recElement* pRecElement;// ryan added this.typedef enum{ DISCONNECT_CONNECTED, DISCONNECT_TELLUSER, DISCONNECT_COMPLETE} DisconnectState;struct recDevice{ void * interface; // interface to device, NULL = no interface void * queue; // device queue, NULL = no queue void * queueRunLoopSource; // device queue run loop source, NULL == no source void * transaction; // output transaction interface, NULL == no interface void * notification; // notifications char transport[256]; // device transport (c string) long vendorID; // id for device vendor, unique across all devices long productID; // id for particular product, unique across all of a vendors devices long version; // version of product char manufacturer[256]; // name of manufacturer char product[256]; // name of product char serial[256]; // serial number of specific product, can be assumed unique across specific product or specific vendor (not used often) long locID; // long representing location in USB (or other I/O) chain which device is pluged into, can identify specific device on machine long usage; // usage page from IOUSBHID Parser.h which defines general usage long usagePage; // usage within above page from IOUSBHID Parser.h which defines specific usage long totalElements; // number of total elements (should be total of all elements on device including collections) (calculated, not reported by device) long features; // number of elements of type kIOHIDElementTypeFeature long inputs; // number of elements of type kIOHIDElementTypeInput_Misc or kIOHIDElementTypeInput_Button or kIOHIDElementTypeInput_Axis or kIOHIDElementTypeInput_ScanCodes long outputs; // number of elements of type kIOHIDElementTypeOutput long collections; // number of elements of type kIOHIDElementTypeCollection long axis; // number of axis (calculated, not reported by device) long buttons; // number of buttons (calculated, not reported by device) long hats; // number of hat switches (calculated, not reported by device) long sliders; // number of sliders (calculated, not reported by device) long dials; // number of dials (calculated, not reported by device) long wheels; // number of wheels (calculated, not reported by device) recElement* pListElements; // head of linked list of elements DisconnectState disconnect; // (ryan added this.) AbsoluteTime lastScrollTime; // (ryan added this.) struct recDevice* pNext; // next device};typedef struct recDevice recDevice;typedef recDevice* pRecDevice;#if USE_NOTIFICATIONSstatic IONotificationPortRef gNotifyPort;static io_iterator_t gAddedIter;static CFRunLoopRef gRunLoop;#endif USE_NOTIFICATIONS// for element retrievalstatic pRecDevice gCurrentGetDevice = NULL;static Boolean gAddAsChild = false;static int gDepth = false;static pRecDevice gpDeviceList = NULL;static UInt32 gNumDevices = 0;static Boolean HIDIsValidDevice(const pRecDevice pSearchDevice);static pRecElement HIDGetFirstDeviceElement (pRecDevice pDevice, HIDElementTypeMask typeMask);static pRecElement HIDGetNextDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask);static pRecDevice HIDGetFirstDevice (void);static pRecDevice HIDGetNextDevice (pRecDevice pDevice);static void HIDReleaseDeviceList (void);static unsigned long HIDDequeueDevice (pRecDevice pDevice);static void hid_GetElements (CFTypeRef refElementCurrent, pRecElement *ppCurrentElement);static void HIDReportError(const char *err) {}static void HIDReportErrorNum(const char *err, int num) {}static void hid_GetCollectionElements (CFMutableDictionaryRef deviceProperties, pRecElement *ppCurrentCollection){ CFTypeRef refElementTop = CFDictionaryGetValue (deviceProperties, CFSTR(kIOHIDElementKey)); if (refElementTop) hid_GetElements (refElementTop, ppCurrentCollection); else HIDReportError ("hid_GetCollectionElements: CFDictionaryGetValue error when creating CFTypeRef for kIOHIDElementKey.");}// extracts actual specific element information from each element CF dictionary entrystatic void hid_GetElementInfo (CFTypeRef refElement, pRecElement pElement){ long number; CFTypeRef refType; // type, usagePage, usage already stored refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementCookieKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->cookie = (IOHIDElementCookie) number; else pElement->cookie = (IOHIDElementCookie) 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementMinKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->min = number; else pElement->min = 0; pElement->calMax = pElement->min; pElement->userMin = kDefaultUserMin; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementMaxKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->max = number; else pElement->max = 0; pElement->calMin = pElement->max; pElement->userMax = kDefaultUserMax; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementScaledMinKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->scaledMin = number; else pElement->scaledMin = 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementScaledMaxKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->scaledMax = number; else pElement->scaledMax = 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementSizeKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->size = number; else pElement->size = 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsRelativeKey)); if (refType) pElement->relative = CFBooleanGetValue (refType); else pElement->relative = 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsWrappingKey)); if (refType) pElement->wrapping = CFBooleanGetValue (refType); else pElement->wrapping = false; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsNonLinearKey)); if (refType) pElement->nonLinear = CFBooleanGetValue (refType); else pElement->wrapping = false;#ifdef kIOHIDElementHasPreferredStateKey refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasPreferredStateKey));#else // Mac OS X 10.0 has spelling error refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasPreferedStateKey));#endif if (refType) pElement->preferredState = CFBooleanGetValue (refType); else pElement->preferredState = false; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasNullStateKey)); if (refType) pElement->nullState = CFBooleanGetValue (refType); else pElement->nullState = false; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUnitKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->units = number; else pElement->units = 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUnitExponentKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->unitExp = number; else pElement->unitExp = 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementNameKey)); if (refType) if (!CFStringGetCString (refType, pElement->name, 256, CFStringGetSystemEncoding ())) HIDReportError ("CFStringGetCString error retrieving pElement->name."); #if 0 if (!*pElement->name) { // set name from vendor id, product id & usage info look up if (!HIDGetElementNameFromVendorProductUsage (gCurrentGetDevice->vendorID, gCurrentGetDevice->productID, pElement->usagePage, pElement->usage, pElement->name)) { // set name from vendor id/product id look up HIDGetElementNameFromVendorProductCookie (gCurrentGetDevice->vendorID, gCurrentGetDevice->productID, (long) pElement->cookie, pElement->name); if (!*pElement->name) { // if no name HIDGetUsageName (pElement->usagePage, pElement->usage, pElement->name); if (!*pElement->name) // if not usage sprintf (pElement->name, "Element"); } } } #endif}static void hid_AddElement (CFTypeRef refElement, pRecElement * ppElementCurrent){ pRecDevice pDevice = gCurrentGetDevice; pRecElement pElement = NULL; long elementType, usagePage, usage; CFTypeRef refElementType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementTypeKey)); CFTypeRef refUsagePage = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUsagePageKey)); CFTypeRef refUsage = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUsageKey)); if (refElementType) CFNumberGetValue (refElementType, kCFNumberLongType, &elementType); if (refUsagePage) CFNumberGetValue (refUsagePage, kCFNumberLongType, &usagePage); if (refUsage) CFNumberGetValue (refUsage, kCFNumberLongType, &usage);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -