Apple Infrared Remote Daemon

© Amit Singh. All Rights Reserved. Written in January 2006

Introduction

Certain Apple computers, such as the x86-based iMac and the MacBook Pro, ship with an infrared remote control that is used to control the Front Row media application. iremoted is a command-line program that listens for button-press events and prints the identifier (the HID element cookie, to be precise) of the button in question.

$ ./iremoted 0x16 pressed 0x16 released 0x17 pressed 0x17 released ...

Note that only the plus and minus (volume) buttons have press and release events that are reported independently. For the other buttons, iremoted will report a press/release pair only after the button is released.

Details

iremoted was originally tested on an x86-based 17-inch iMac. The built-in IR controller in this machine is a USB-based human interface device (HID). The usage table information for this device includes usages in the Generic Desktop Page (page ID 0x0), the Generic Device Controls Page (page ID 0x06), the Consumer Page (page ID 0x0C), and a vendor-defined page (page ID 0xff01).

If you are not familiar with HID usage tables and the associated terminology, please refer to the documentation available on USB.org. In particular, refer to the document "HID Usage Tables". This discussions also assumes familiarity with HID programming on Mac OS X.

There are multiple ways in which to programmatically obtain remote control button-press information from the IR controller. At the lowest level, one could write a device driver. At a much higher level, one could depend on another program (such as iremoted) to obtain that information. iremoted itself uses a middle-ground approach: it communicates with Apple's in-kernel IR driver, which is implemented by the AppleIRController.kext kernel extension. Given the I/O Kit's power and flexibility, especially in allowing user-level access to hardware, this is a very reasonable approach.

iremoted first looks up the registered IOService object that corresponds to the IR controller. It then gets a plug-in interface for for the HID family's user client (kIOHIDDeviceUserClientTypeID). Once it has the interface, it calls its QueryInterface() method, which yields an IOHIDDeviceInterface on success. The returned pointer can be cast to an instance of the IOHIDDeviceInterface122 class, which represents a specific version (1.2.2) of the primary interface to HID devices.

Armed with the HID device interface, iremoted calls its copyMatchingElements() method to examine and record the values of the "cookies" that represent HID elements, for example:

$ ioreg -l -w 0 # output artificially wrapped ... | +-o AppleIRController <class AppleIRController, registered, matched, active, busy 0, retain count 10> ... { # this is "System App Menu" "Size"=1,"UnitExponent"=0,"ReportSize"=1,"ScaledMin"=0, "ScaledMax"=1,"ElementCookie"=7,"Max"=1,"Unit"=0, "IsArray"=Yes,"HasNullState"=Yes,"IsRelative"=Yes, "Report ID"=0,"ValueLocation"=316,"Min"=0,"IsWrapping"=No, "UsagePage"=1,"HasPreferredState"=Yes,"ReportCount"=1, "IsNonLinear"=No,"Usage"=134,"Type"=2 } ...

iremoted then opens the HID interface and performs the following key operations:

Thereafter, pressing a button on the Apple Remote Control will cause the callback function to be invoked. The callback uses the queue's getNextEvent() method to read the next event from the queue. Each event is an IOHIDEventStruct, whose elementCookie field is the element of interest — that is, the button that was pressed. The value field, depending on whether it is zero or not, determines if the button was pressed or released.

For a better understanding of how IOHIDQueueInterface functions work, please refer to <IOHIDLib/IOHIDLib.h> in the source for the I/O Kit's HID family (the IOHIDFamily Darwin package).

Controlling Keynote Presentations

To illustrate the remote's utility, iremoted supports translating forward and backward button presses to "next slide" and "previous slide" events in a running instance of Apple's Keynote application.

To use this functionality of iremoted, run it with the -k option. Thereafter, with a Keynote presentation playing, the remote can be used to control slide transition.

$ ./iremoted -k # now play a Keynote presentation # use the remote's |<< and >>| buttons

Source


iremoted.c