Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 15 May 2009 21:55:08 +0200
From:      Christoph Langguth <christoph@rosenkeller.org>
To:        freebsd-usb@freebsd.org
Subject:   How to add support for Macbook Pro (USB) keyboard?
Message-ID:  <4A0DC89C.6010708@rosenkeller.org>

next in thread | raw e-mail | index | archive | help
Hi all,

first off, I have just subscribed to this list, as it seemed the most 
logical place -- but in case this is the wrong place to ask, please 
accept my apologies and point me to the right place.

Second, I'm sorry for the long mail, but I'm only getting started with 
this -- not much experience in hacking the kernel yet, and in how it 
really is organized internally. So I'd really appreciate any help here 
-- I'd also be willing to contribute, if I can.

The problem is the following: I'm trying to get FreeBSD to run on a 
Macbook Pro (MBP), purchased some time last year. As soon as the FreeBSD 
kernel is loaded, the keyboard is malfunctioning. (What I mean by this 
is: at the loader prompt, it still works ok; when it's handled by ukbd, 
it acts as if the Ctrl key was constantly stuck).

So far, I have found one reference to this problem: 
http://unix.derkeiler.com/Mailing-Lists/FreeBSD/stable/2009-02/msg00031.html


The keyboard in question identifies itself like this:

marvin# usbconfig -u 5 -a 3 dump_device_desc
ugen5.3: <Apple Internal Keyboard / Trackpad Apple, Inc.> at usbus5, 
cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON

   bLength = 0x0012
   bDescriptorType = 0x0001
   bcdUSB = 0x0200
   bDeviceClass = 0x0000
   bDeviceSubClass = 0x0000
   bDeviceProtocol = 0x0000
   bMaxPacketSize0 = 0x0008
   idVendor = 0x05ac
   idProduct = 0x0231
   bcdDevice = 0x0070
   iManufacturer = 0x0001  <Apple, Inc.>
   iProduct = 0x0002  <Apple Internal Keyboard / Trackpad>
   iSerialNumber = 0x0000  <no string>
   bNumConfigurations = 0x0001


I had first tried to pinpoint the problem with the sources that came 
with the 7.2-RELEASE sources, by turning some USB debugging on, but got 
stuck when I ended up getting BABBLE reports from uhci, and couldn't 
figure out how to get any further. I then decided to try to switch to 
CURRENT and see whether the problem may have been fixed there. Turns out 
it hasn't been fixed, but since there have obviously been major code 
rewrites there, I was able to figure out the problem.

It's happening in ukbd_intr_callback(): This function is expecting 8 
bytes of data (of which the first is the keyboard modifiers). Turns out 
that the MBP sends 10 bytes instead, with
- the first always being 01 (which explains why the Ctrl key seems to be 
stuck)
- indexes 1 to 8 containing the actually "expected" data
- the last being 00 or 02, depending on whether the Fn key was pressed.

I'm inlining a diff of my changes here:

--- ukbd.c.org  2009-05-15 17:38:59.000000000 +0000
+++ ukbd.c      2009-05-15 18:48:01.000000000 +0000
@@ -470,17 +470,24 @@
         struct ukbd_softc *sc = xfer->priv_sc;
         uint16_t len = xfer->actlen;
         uint8_t i;
+       uint8_t mydebug[256];
+       uint8_t offset = 0;

         switch (USB_GET_STATE(xfer)) {
         case USB_ST_TRANSFERRED:
                 DPRINTF("actlen=%d bytes\n", len);
+               usb2_copy_out(xfer->frbuffers, 0, &mydebug[0], len);
+               for (i=0; i < len; ++i) {
+                       DPRINTF("dump %02d = %02x\n",i,mydebug[i]);
+               }

                 if (len > sizeof(sc->sc_ndata)) {
                         len = sizeof(sc->sc_ndata);
+                       offset = 1;
                 }
                 if (len) {
                         bzero(&sc->sc_ndata, sizeof(sc->sc_ndata));
-                       usb2_copy_out(xfer->frbuffers, 0, &sc->sc_ndata, 
len);
+                       usb2_copy_out(xfer->frbuffers, offset, 
&sc->sc_ndata, len);
  #if USB_DEBUG
                         if (sc->sc_ndata.modifiers) {
                                 DPRINTF("mod: 0x%04x\n", 
sc->sc_ndata.modifiers);

(I know that's a hack, it was just for testing and works for me).

After having figured this out (and ignoring the Fn "bit" for now), I 
looked into the existing USB quirks, and there seems to be one named 
UQ_MS_LEADING_BYTE. I tried (with the original ukbd) to see if applying 
that quirk resulted in anything -- both by modifying the quirks.c, and 
by running

usbconfig -u 5 -a 3 add_dev_quirk_vplh 0x5ac 0x231 0 0xffff 
UQ_MS_LEADING_BYTE

but the result was exactly the same as before (i.e., the first spurious 
byte didn't vanish). I might have done something wrong with the quirks, 
but I guess it's actually just a different case than UQ_MS_LEADING_BYTE.

So my question now is: what is the correct approach to add support for 
this keyboard? The thing I did above is clearly a hack, but I'm just not 
sure where these things should be handled correctly (Especially in light 
of the additional "Fn" key being present, and probably requiring some 
translation table, e.g. to map "fn+backspace" to "del", etc.)

What is the correct approach here? Some modified ukbd as an additional 
module? Modifying the ukbd itself (but how)?

I'm also feeling kind of better when running on a -STABLE system for 
production use, which would require some "backporting" (but as said, I 
got stuck in the "old" sources because I didn't really understand how 
things worked there).

As I said, I would be willing to invest effort into this, but would need 
some guidance, so any help is very much appreciated :-)

OK, I guess that's it for now,
thanks in advance for the replies!

-- Chris




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4A0DC89C.6010708>