IOHIDFamily
是一个内核扩展,提供了一个用户界面设备(human interface device
, HID)的抽象接口,比如:触摸屏,按钮,加速计等等。在用户层,一共有2中与IOHIDFamily
有关的API:
(1) 公开API,用于HID驱动的编写
(2) 私有API,用来事件处理。
本文只介绍私有API,公开API的说明可以在Mac开发文档上查看。
内容:
- 类结构
- 例子
- iOS >= 6.1(或更早)上的问题
- 服务
- 键盘事件
- 引用文献
类结构
IOHID的用户总是先创建一个IOHIDEventSystem
的对象,用来和整个HID系统进行交互。一个事件系统包含多个IOHIDService
和IOHIDDisplay
。
各种服务对于内核插件IOHIDLibPlugin
(位于/System/Library/Extensions/IOHIDFamily.kext/PlugIns/IOHIDLib.plugin/IOHIDLib
)都是不同的界面接口。它们接受直接的人类输入,并且是所有IOHIDEvent
的源。
Display很明显的就是LCD屏幕了。IOHIDDisplay
类智能控制亮度,而不是一个像素点的颜色(绘制是由VRAM控制的)。你只能通过改变事件系统的属性来间接控制display。
IOHID定义了20种类型的事件,这其中只有4种是SpringBoard能够处理的:键盘(按钮),屏幕,加速计和邻近事件(温度事件直接被IOKit处理)。每一个事件可能包含多个子事件。
例子
#include <IOKit/hid/IOHIDEventSystem.h>
#include <stdio.h>
void handle_event (void* target, void* refcon, IOHIDServiceRef service, IOHIDEventRef event) {
// handle the events here.
printf("Received event of type %2d from service %p.\n", IOHIDEventGetType(event), service);
}
int main () {
// Create and open an event system.
IOHIDEventSystemRef system = IOHIDEventSystemCreate(NULL);
IOHIDEventSystemOpen(system, handle_event, NULL, NULL, NULL);
printf("HID Event system should now be running. Hit enter to quit any time.\n");
getchar();
IOHIDEventSystemClose(system, NULL);
CFRelease(system);
return 0;
}
iOS >= 6.1(或更早)上的问题
至少从iOS 6.1开始,在函数IOHIDEventSystemCreate
中会有一个检查,比较bundleID是否等于com.apple.springboard
。如果这个检查失败,函数就会返回NULL。因为没有任何方法能够在我们的app中使用HID系统,除非我们绕过了这个检查。
__text:0001561A loc_1561A ; CODE XREF: _IOHIDEventSystemCreate+7E�j
__text:0001561A MOV R0, R4
__text:0001561C MOVS R2, #0xC4 ; ''
__text:0001561E MOVS R3, #0
__text:00015620 MOVS R5, #0
__text:00015622 BLX __CFRuntimeCreateInstance
__text:00015626 MOV R4, R0
__text:00015628 CMP R4, #0
__text:0001562A BEQ.W loc_1584A
__text:0001562E ADD.W R5, R4, #8
__text:00015632 MOVS R1, #0 ; int
__text:00015634 MOV R0, R5 ; void *
__text:00015636 MOVS R2, #0xC4 ; '' ; size_t
__text:00015638 BLX _memset ; Initialize the struct's variables to zero.
__text:0001563C BLX _CFBundleGetMainBundle ; Get the main bundle
__text:00015640 CBZ R0, loc_15660 ; Go to loc_15660 if it returned NULL.
__text:00015642 BLX _CFBundleGetIdentifier ; Get the bundle's identifier.
__text:00015646 CBZ R0, loc_15660 ; Go to loc_15660 if the identifier is NULL.
__text:00015648 MOV R1, #(cfstr_Com_apple_spri - 0x15654) ; "com.apple.springboard"
__text:00015650 ADD R1, PC ; "com.apple.springboard"
__text:00015652 BLX _CFEqual ; Check if the main bundle's identifier is equal to com.apple.springboard.
__text:00015656 CMP R0, #0 ; If the check returned false, return.
__text:00015658 ITT NE
__text:0001565A MOVNE R0, #1
__text:0001565C STRNEB.W R0, [R4,#0xB8]
__text:00015660
__text:00015660 loc_15660 ; CODE XREF: _IOHIDEventSystemCreate+C0�j
__text:00015660 ; _IOHIDEventSystemCreate+C6�j
__text:00015660 ADD.W R8, R4, #0x38
__text:00015664 MOVS R1, #0 ; attr
__text:00015666 MOV R0, R8 ; rwlock
__text:00015668 BLX _pthread_rwlock_init
__text:0001566C CMP R0, #0
__text:0001566E BNE.W loc_15792
服务
要访问这些服务,你必须首先用IOHIDEventSystemCopyMatchingServices
来匹配他们。这些判断规则可以从ioreg -l
获得。
键盘事件
iPhonsOS上的事件实际上被当成了键盘事件。下面说明了如何识别他们: