Apple Magic Mouse

Dirk Engling erdgeist at erdgeist.org
Sat Sep 12 14:26:57 UTC 2015


On 09.08.15 21:47, plunky at ogmig.net (Iain Hibbert) wrote:

> I'd say that using the NetBSD driver (I am the author) is not really 
> possible on FreeBSD, since FreeBSD does things related to Bluetooth HIDs 
> differently. It should be simple enough to add the Magic Mouse handling to 
> the bthidd(8) daemon though, but I don't know how easy that would be, or a 
> separate daemon could be written instead.

I've taken a look and there's several obstacles in the way. But first
the good news, once I add

        if (fd == srv->ctrl) {
                static uint8_t rep[] = { 0x53, 0xd7, 0x01 };
                write(new_fd, rep, 3 );
        }

to usr.sbin/bluetooth/bthidd/server.c:272, the hid_interrupt function in
usr.sbin/bluetooth/bthidd/hid.c gets trackpad-events and mouse lift/drop
from the magic mouse.

My problem is now, that this feature report is hard coded and obviously
not every device should be served this. But,

> The way I worked the identification in NetBSD, was that when configuring a 
> HID device, I checked the descriptor as normal and also the 
> Manufacturer/Product ID via the PNP profile. When the latter matched the 
> Apple Magic Mouse, then it just attaches a different driver.

it looks like the Manufacturer/Product ID is ignored on the hci level
and thus not available at higher layers. Maybe I'm missing something here?

> The Magic Mouse then needs an initialization command to be sent via the 
> standard HID protocol "SET_REPORT(FEATURE, 0xd7) = 0x01" once connected to 
> enable the special extra functionality that it provides.

Also I noticed that the reports sent by the magic mouse are not reported
in their hid descriptor. I get the following reports there (see attachment)

09 02    (LOCAL)  USAGE              Mouse (CA=Application Collection)
85 10      (GLOBAL) REPORT_ID          0x10 (16)

09 20      (LOCAL)  USAGE              Battery Strength
85 47      (GLOBAL) REPORT_ID          0x47 (71) 'G'

09 55      (LOCAL)  USAGE              0xFF020055
85 55      (GLOBAL) REPORT_ID          0x55 (85) 'U'

But when enabling the magic mouse modes as seen above, I see reports:

HID Interrupt: A1 60 01
HID Interrupt: A1 61 01

Which is 0x60 and 0x61, corresponding with mouse surface lift and drop.
When touching the trackpad area on the mouse, I get

HID Interrupt: A1 29 00 00 80 D0 6B 9F E3 11 4D 16 83 80 32

which is report 0x29 and corresponds to the magic trackpad messages
handled in the NetBSD [1] and Linux driver [2].

Problem is, that the bthidd code does not handle reports not announced
in hid descriptors at all. So I would need to either manually inject the
report id in hid_device->desc and add handler code, handle magic mouse
in a completely different code path, or write my own driver.

Maybe Maksim has some ideas, the daemon is his code, after all.

Regards,

  erdgeist




[1]
http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/dev/bluetooth/btmagic.c?rev=1.14&content-type=text/x-cvsweb-markup
[2] http://lxr.free-electrons.com/source/drivers/hid/hid-magicmouse.c

-------------- next part --------------
//--------------------------------------------------------------------------------
// Decoded Application Collection
//--------------------------------------------------------------------------------

/*
05 01        (GLOBAL) USAGE_PAGE         0x0001 Generic Desktop Page
09 02        (LOCAL)  USAGE              0x00010002 Mouse (CA=Application Collection)
A1 01        (MAIN)   COLLECTION         0x01 Application (Usage=0x00010002: Page=Generic Desktop Page, Usage=Mouse, Type=CA)
85 10          (GLOBAL) REPORT_ID          0x10 (16)
05 09          (GLOBAL) USAGE_PAGE         0x0009 Button Page
19 01          (LOCAL)  USAGE_MINIMUM      0x00090001 Button 1 Primary/trigger (MULTI=Selector, On/Off, Momentary, or One Shot)
29 02          (LOCAL)  USAGE_MAXIMUM      0x00090002 Button 2 Secondary (MULTI=Selector, On/Off, Momentary, or One Shot)
15 00          (GLOBAL) LOGICAL_MINIMUM    0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0
25 01          (GLOBAL) LOGICAL_MAXIMUM    0x01 (1)
95 02          (GLOBAL) REPORT_COUNT       0x02 (2) Number of fields
75 01          (GLOBAL) REPORT_SIZE        0x01 (1) Number of bits per field
81 02          (MAIN)   INPUT              0x00000002 (2 fields x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
95 01          (GLOBAL) REPORT_COUNT       0x01 (1) Number of fields
75 06          (GLOBAL) REPORT_SIZE        0x06 (6) Number of bits per field
81 03          (MAIN)   INPUT              0x00000003 (1 field x 6 bits) 1=Constant 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
05 01          (GLOBAL) USAGE_PAGE         0x0001 Generic Desktop Page
09 01          (LOCAL)  USAGE              0x00010001 Pointer (CP=Physical Collection)
A1 00          (MAIN)   COLLECTION         0x00 Physical (Usage=0x00010001: Page=Generic Desktop Page, Usage=Pointer, Type=CP)
16 01FE          (GLOBAL) LOGICAL_MINIMUM    0xFE01 (-511)
26 FF01          (GLOBAL) LOGICAL_MAXIMUM    0x01FF (511)
36 C0FE          (GLOBAL) PHYSICAL_MINIMUM   0xFEC0 (-320)
46 4001          (GLOBAL) PHYSICAL_MAXIMUM   0x0140 (320)
65 13            (GLOBAL) UNIT               0x00000013 Distance in inches [1 inch units] (3=System=English Linear, 1=Length=Inch)
55 0D            (GLOBAL) UNIT_EXPONENT      0x0D (Unit Value x 10⁻³)
09 30            (LOCAL)  USAGE              0x00010030 X (DV=Dynamic Value)
09 31            (LOCAL)  USAGE              0x00010031 Y (DV=Dynamic Value)
75 10            (GLOBAL) REPORT_SIZE        0x10 (16) Number of bits per field
95 02            (GLOBAL) REPORT_COUNT       0x02 (2) Number of fields
81 06            (MAIN)   INPUT              0x00000006 (2 fields x 16 bits) 0=Data 1=Variable 1=Relative 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
C0             (MAIN)   END_COLLECTION     Physical
05 06          (GLOBAL) USAGE_PAGE         0x0006 Generic Device Controls Page
09 20          (LOCAL)  USAGE              0x00060020 Battery Strength (DV=Dynamic Value)
85 47          (GLOBAL) REPORT_ID          0x47 (71) 'G'
15 00          (GLOBAL) LOGICAL_MINIMUM    0x00 (0)
25 64          (GLOBAL) LOGICAL_MAXIMUM    0x64 (100)
75 08          (GLOBAL) REPORT_SIZE        0x08 (8) Number of bits per field
95 01          (GLOBAL) REPORT_COUNT       0x01 (1) Number of fields
B1 A2          (MAIN)   FEATURE            0x000000A2 (1 field x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 1=NoPrefState 0=NoNull 1=Volatile 0=Bitmap
06 02FF        (GLOBAL) USAGE_PAGE         0xFF02 Vendor-defined
09 55          (LOCAL)  USAGE              0xFF020055
85 55          (GLOBAL) REPORT_ID          0x55 (85) 'U'
15 00          (GLOBAL) LOGICAL_MINIMUM    0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0
26 FF00        (GLOBAL) LOGICAL_MAXIMUM    0x00FF (255)
75 08          (GLOBAL) REPORT_SIZE        0x08 (8) Number of bits per field <-- Redundant: REPORT_SIZE is already 8
95 40          (GLOBAL) REPORT_COUNT       0x40 (64) Number of fields
B1 A2          (MAIN)   FEATURE            0x000000A2 (64 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 1=NoPrefState 0=NoNull 1=Volatile 0=Bitmap
C0           (MAIN)   END_COLLECTION     Application
*/




More information about the freebsd-bluetooth mailing list