From fca7f164708033819b48b765d9b80e1b47a3ed2a Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Thu, 23 Oct 2008 10:12:43 +0200 Subject: bcm5974-0.66-rc11: Add support for Macbook5 (Unibody) This version is not final, but good enough to base tests on. Signed-off-by: Henrik Rydberg --- CHANGES | 6 +++ bcm5974-dkms-mkdeb/debian/changelog | 2 +- bcm5974.c | 96 +++++++++++++++++++++++++++---------- dkms.conf | 2 +- etc/modprobe.d/bcm5974 | 29 +++++++++-- scripts/bcm5974-post-install | 41 ++++++++++------ 6 files changed, 130 insertions(+), 46 deletions(-) diff --git a/CHANGES b/CHANGES index 2850cef..e1df040 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,9 @@ +bcm5974 (0.66) unstable; urgency=low + + * Add support for MacBook 5,1 (unibody) + + -- Henrik Rydberg Sun, 19 Oct 2008 17:23:26 +0200 + bcm5974 (0.65) unstable; urgency=low * Switch back to normal mode when closing diff --git a/bcm5974-dkms-mkdeb/debian/changelog b/bcm5974-dkms-mkdeb/debian/changelog index 3ea1523..2f74f29 100644 --- a/bcm5974-dkms-mkdeb/debian/changelog +++ b/bcm5974-dkms-mkdeb/debian/changelog @@ -1,5 +1,5 @@ MODULE_NAME-dkms (MODULE_VERSION) unstable; urgency=low - * Switch back to normal mode when closing + * Add support for MacBook 5,1 (unibody) -- Henrik Rydberg DATE_STAMP diff --git a/bcm5974.c b/bcm5974.c index bf6c59f..9965e8f 100644 --- a/bcm5974.c +++ b/bcm5974.c @@ -42,6 +42,8 @@ #include #define USB_VENDOR_ID_APPLE 0x05ac +#define BTN_TOOL_PRESS 0x148 +#define BTN_TOOL_QUADTAP 0x14f /* MacbookAir, aka wellspring */ #define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI 0x0223 @@ -51,6 +53,10 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230 #define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231 #define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232 +/* Macbook5,1 (unibody), aka wellspring3 */ +#define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 +#define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 +#define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 #define BCM5974_DEVICE(prod) { \ .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ @@ -72,6 +78,10 @@ static const struct usb_device_id bcm5974_table[] = { BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ISO), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_JIS), + /* Macbook5,1 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ISO), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), /* Terminating entry */ {} }; @@ -96,13 +106,22 @@ struct bt_data { u8 rel_y; /* relative y coordinate */ }; -/* trackpad header structure */ -struct tp_header { - u8 unknown1[16]; /* constants, timers, etc */ - u8 fingers; /* number of fingers on trackpad */ - u8 unknown2[9]; /* constants, timers, etc */ +/* trackpad header types */ +enum tp_type { + TYPE1, /* plain trackpad */ + TYPE2 /* button integrated in trackpad */ }; +/* trackpad finger data offsets */ +#define FINGER_TYPE1 26 +#define FINGER_TYPE2 30 + +/* trackpad button data offsets */ +#define BUTTON_TYPE2 15 + +/* integrated button capability by configuration */ +#define HAS_INTEGRATED_BUTTON(c) (c->tp_type == TYPE2) + /* trackpad finger structure */ struct tp_finger { __le16 origin; /* zero when switching track finger */ @@ -119,11 +138,9 @@ struct tp_finger { __le16 multi; /* one finger: varies, more fingers: constant */ }; -/* trackpad data structure, empirically at least ten fingers */ -struct tp_data { - struct tp_header header; - struct tp_finger finger[16]; -}; +/* trackpad finger data size, empirically at least ten fingers */ +#define SIZEOF_FINGER sizeof(struct tp_finger) +#define SIZEOF_ALL_FINGERS (16 * SIZEOF_FINGER) /* device-specific parameters */ struct bcm5974_param { @@ -139,6 +156,8 @@ struct bcm5974_config { int bt_ep; /* the endpoint of the button interface */ int bt_datalen; /* data length of the button interface */ int tp_ep; /* the endpoint of the trackpad interface */ + enum tp_type tp_type; /* type of trackpad interface */ + int tp_offset; /* offset to trackpad finger data */ int tp_datalen; /* data length of the trackpad interface */ struct bcm5974_param p; /* finger pressure limits */ struct bcm5974_param w; /* finger width limits */ @@ -158,7 +177,7 @@ struct bcm5974 { struct urb *bt_urb; /* button usb request block */ struct bt_data *bt_data; /* button transferred data */ struct urb *tp_urb; /* trackpad usb request block */ - struct tp_data *tp_data; /* trackpad transferred data */ + u8 *tp_data; /* trackpad transferred data */ int fingers; /* number of fingers on trackpad */ }; @@ -184,7 +203,7 @@ static const struct bcm5974_config bcm5974_config_table[] = { USB_DEVICE_ID_APPLE_WELLSPRING_ISO, USB_DEVICE_ID_APPLE_WELLSPRING_JIS, 0x84, sizeof(struct bt_data), - 0x81, sizeof(struct tp_data), + 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS, { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, { DIM_X, DIM_X / SN_COORD, -4824, 5342 }, @@ -195,12 +214,23 @@ static const struct bcm5974_config bcm5974_config_table[] = { USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, 0x84, sizeof(struct bt_data), - 0x81, sizeof(struct tp_data), + 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS, { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, { DIM_X, DIM_X / SN_COORD, -4824, 4824 }, { DIM_Y, DIM_Y / SN_COORD, -172, 4290 } }, + { + USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI, + USB_DEVICE_ID_APPLE_WELLSPRING3_ISO, + USB_DEVICE_ID_APPLE_WELLSPRING3_JIS, + 0x84, sizeof(struct bt_data), + 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, + { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 768 }, + { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, + { DIM_X, DIM_X / SN_COORD, -4460, 5166 }, + { DIM_Y, DIM_Y / SN_COORD, -75, 6700 } + }, {} }; @@ -258,6 +288,9 @@ static void setup_events_to_report(struct input_dev *input_dev, __set_bit(BTN_TOOL_FINGER, input_dev->keybit); __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); + __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); + if (HAS_INTEGRATED_BUTTON(cfg)) + __set_bit(BTN_TOOL_PRESS, input_dev->keybit); __set_bit(BTN_LEFT, input_dev->keybit); } @@ -267,6 +300,11 @@ static int report_bt_state(struct bcm5974 *dev, int size) if (size != sizeof(struct bt_data)) return -EIO; + dprintk(7, + "bcm5974: button data: %x %x %x %x\n", + dev->bt_data->unknown1, dev->bt_data->button, + dev->bt_data->rel_x, dev->bt_data->rel_y); + input_report_key(dev->input, BTN_LEFT, dev->bt_data->button); input_sync(dev->input); @@ -277,29 +315,35 @@ static int report_bt_state(struct bcm5974 *dev, int size) static int report_tp_state(struct bcm5974 *dev, int size) { const struct bcm5974_config *c = &dev->cfg; - const struct tp_finger *f = dev->tp_data->finger; + const struct tp_finger *f; struct input_dev *input = dev->input; - const int fingers = (size - 26) / 28; - int raw_p, raw_w, raw_x, raw_y; - int ptest = 0, origin = 0, nmin = 0, nmax = 0; + int raw_p, raw_w, raw_x, raw_y, raw_n; + int ptest = 0, origin = 0, ibt = 0, nmin = 0, nmax = 0; int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; - if (size < 26 || (size - 26) % 28 != 0) + if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0) return -EIO; + f = (const struct tp_finger *)(dev->tp_data + c->tp_offset); + raw_n = (size - c->tp_offset) / SIZEOF_FINGER; + /* always track the first finger; when detached, start over */ - if (fingers) { + if (raw_n) { raw_p = raw2int(f->force_major); raw_w = raw2int(f->size_major); raw_x = raw2int(f->abs_x); raw_y = raw2int(f->abs_y); dprintk(9, - "bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d\n", - raw_p, raw_w, raw_x, raw_y); + "bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d " + "n: %d\n", raw_p, raw_w, raw_x, raw_y, raw_n); ptest = int2bound(&c->p, raw_p); origin = raw2int(f->origin); + + /* set the integrated button if applicable */ + if (c->tp_type == TYPE2) + ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); } /* while tracking finger still valid, count all fingers */ @@ -308,12 +352,13 @@ static int report_tp_state(struct bcm5974 *dev, int size) abs_w = int2bound(&c->w, raw_w); abs_x = int2bound(&c->x, raw_x - c->x.devmin); abs_y = int2bound(&c->y, c->y.devmax - raw_y); - for (; f != dev->tp_data->finger + fingers; f++) { + while (raw_n--) { ptest = int2bound(&c->p, raw2int(f->force_major)); if (ptest > PRESSURE_LOW) nmax++; if (ptest > PRESSURE_HIGH) nmin++; + f++; } } @@ -325,7 +370,8 @@ static int report_tp_state(struct bcm5974 *dev, int size) input_report_key(input, BTN_TOUCH, dev->fingers > 0); input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1); input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2); - input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers > 2); + input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers == 3); + input_report_key(input, BTN_TOOL_QUADTAP, dev->fingers > 3); input_report_abs(input, ABS_PRESSURE, abs_p); input_report_abs(input, ABS_TOOL_WIDTH, abs_w); @@ -336,8 +382,8 @@ static int report_tp_state(struct bcm5974 *dev, int size) dprintk(8, "bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d " - "nmin: %d nmax: %d n: %d\n", - abs_p, abs_w, abs_x, abs_y, nmin, nmax, dev->fingers); + "nmin: %d nmax: %d n: %d ibt: %d\n", abs_p, abs_w, + abs_x, abs_y, nmin, nmax, dev->fingers, ibt); } diff --git a/dkms.conf b/dkms.conf index aec50fa..4be76c4 100644 --- a/dkms.conf +++ b/dkms.conf @@ -1,5 +1,5 @@ PACKAGE_NAME="bcm5974" -PACKAGE_VERSION="0.65" +PACKAGE_VERSION="0.66" MAKE[0]="make -C ${kernel_source_dir} SUBDIRS=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build modules" BUILT_MODULE_NAME[0]="bcm5974" diff --git a/etc/modprobe.d/bcm5974 b/etc/modprobe.d/bcm5974 index 81cd5ce..1aabdd8 100644 --- a/etc/modprobe.d/bcm5974 +++ b/etc/modprobe.d/bcm5974 @@ -1,10 +1,31 @@ ### Options for the bcm5974 driver -## quirks for the Macbook Air -#options usbhid quirks=0x05ac:0x0223:0x00020800,0x05ac:0x0224:0x00024800,0x05ac:0x0225:0x00020800 +## quirks for the Macbook Air (ANSI keyboard) +#options usbhid quirks=0x05ac:0x0223:0x00020800 -## quirks for the Macbook Pro Penryn -#options usbhid quirks=0x05ac:0x0230:0x00020800,0x05ac:0x0231:0x00024800,0x05ac:0x0232:0x00020800 +## quirks for the Macbook Air (ISO keyboard) +#options usbhid quirks=0x05ac:0x0224:0x00024800 + +## quirks for the Macbook Air (JIS keyboard) +#options usbhid quirks=0x05ac:0x0225:0x00020800 + +## quirks for the Macbook Pro Penryn (ANSI keyboard) +#options usbhid quirks=0x05ac:0x0230:0x00020800 + +## quirks for the Macbook Pro Penryn (ISO keyboard) +#options usbhid quirks=0x05ac:0x0231:0x00024800 + +## quirks for the Macbook Pro Penryn (JIS keyboard) +#options usbhid quirks=0x05ac:0x0232:0x00020800 + +## quirks for the Macbook 5,1 Unibody (ANSI keyboard) +#options usbhid quirks=0x05ac:0x0236:0x00020800 + +## quirks for the Macbook 5,1 Unibody (ISO keyboard) +#options usbhid quirks=0x05ac:0x0237:0x00024800 + +## quirks for the Macbook 5,1 Unibody (JIS keyboard) +#options usbhid quirks=0x05ac:0x0238:0x00020800 ## Debug level - uncomment this to get raw packets in /var/log/debug #options bcm5974 debug=99 diff --git a/scripts/bcm5974-post-install b/scripts/bcm5974-post-install index 5674d40..de5094c 100755 --- a/scripts/bcm5974-post-install +++ b/scripts/bcm5974-post-install @@ -28,25 +28,36 @@ DIR=`dirname $0` LSUSB=/usr/sbin/lsusb PAT_HEAD="options usbhid quirks=" -PAT[0]="05ac:022" -PAT[1]="05ac:023" -MATCH[0]=${PAT_HEAD}0x05ac:0x022 -MATCH[1]=${PAT_HEAD}0x05ac:0x023 + +DEV[0]="0223" +DEV[1]="0224" +DEV[2]="0225" +DEV[3]="0230" +DEV[4]="0231" +DEV[5]="0232" +DEV[6]="0236" +DEV[7]="0237" +DEV[8]="0238" if [ -x $LSUSB ]; then - if [ "`$LSUSB|grep ${PAT[0]}`" != "" ]; then - SED="s/#${MATCH[0]}/${MATCH[0]}/" - elif [ "`$LSUSB|grep ${PAT[1]}`" != "" ]; then - SED="s/#${MATCH[1]}/${MATCH[1]}/" - else - echo No suitable device found - exit 1 - fi + typeset -i i=0 + while [ $i -lt 9 ]; do + PAT=05ac:${DEV[$i]} + MATCH=${PAT_HEAD}0x05ac:0x${DEV[$i]} + if [ "`$LSUSB|grep $PAT`" != "" ]; then + SED="s/#$MATCH/$MATCH/" + fi + i=$i+1 + done else echo \* USB device: UNKNOWN - lsusb not found exit 1 fi -cat $DIR/..$ETCPATH | sed "$SED" > $ETCPATH - -exit 0 +if [ "$SED" != "" ]; then + cat $DIR/..$ETCPATH | sed "$SED" > $ETCPATH + exit 0 +else + echo No suitable device found + exit 1 +fi -- cgit v1.2.3