[PATCH] bcm5974-0.57 plus hack

Henrik Rydberg rydberg at euromail.se
Mon Jul 21 20:41:32 UTC 2008


From: Henrik Rydberg <rydberg at euromail.se>

The usbhid_modify_dquirk function is not exported in hardy,
and trying to load the bcm5974 from the hardy-proposed LBM 2.6.24-20 simply
fails with an undefined-symbol error. This patch upgrades hardy-lbm to bcm5974-0.57,
and comments out the dynamic quirk addition, awaiting a possible addition of
EXPORT_SYMBOL(usbhid_modify_dquirk) in usbhid/hid-quirks.c.

Signed-off-by: Henrik Rydberg <rydberg at euromail.se>
---
 updates/input/mouse/bcm5974.c |  117 ++++++++++++++---------------------------
 1 files changed, 40 insertions(+), 77 deletions(-)

diff --git a/updates/input/mouse/bcm5974.c b/updates/input/mouse/bcm5974.c
index c43fc0c..6bd21fb 100644
--- a/updates/input/mouse/bcm5974.c
+++ b/updates/input/mouse/bcm5974.c
@@ -157,7 +157,6 @@ struct atp {
 	struct bt_data *bt_data;	/* button transferred data */
 	struct urb *tp_urb;		/* trackpad usb request block */
 	struct tp_data *tp_data;	/* trackpad transferred data */
-	unsigned tp_valid;		/* trackpad sensors valid */
 };
 
 /* logical dimensions */
@@ -283,10 +282,9 @@ static int report_tp_state(struct atp *dev, int size)
 #define ATP_WELLSPRING_MODE_WRITE_REQUEST_ID	9
 #define ATP_WELLSPRING_MODE_REQUEST_VALUE	0x300
 #define ATP_WELLSPRING_MODE_REQUEST_INDEX	0
-#define ATP_WELLSPRING_MODE_VENDOR_VALUE_1	0x01
-#define ATP_WELLSPRING_MODE_VENDOR_VALUE_2	0x05
+#define ATP_WELLSPRING_MODE_VENDOR_VALUE	0x01
 
-static int atp_wellspring_init(struct atp *dev)
+static int atp_wellspring_mode(struct atp *dev)
 {
 	char *data = kmalloc(8, GFP_KERNEL);
 	int error = 0, size;
@@ -297,24 +295,6 @@ static int atp_wellspring_init(struct atp *dev)
 		goto error;
 	}
 
-	/* reset button endpoint */
-	if (usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
-			USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
-			0, dev->cfg.bt_ep, NULL, 0, 5000)) {
-		err("bcm5974: could not reset button endpoint");
-		error = -EIO;
-		goto error;
-	}
-
-	/* reset trackpad endpoint */
-	if (usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
-			USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
-			0, dev->cfg.tp_ep, NULL, 0, 5000)) {
-		err("bcm5974: could not reset trackpad endpoint");
-		error = -EIO;
-		goto error;
-	}
-
 	/* read configuration */
 	size = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
 		ATP_WELLSPRING_MODE_READ_REQUEST_ID,
@@ -329,8 +309,7 @@ static int atp_wellspring_init(struct atp *dev)
 	}
 
 	/* apply the mode switch */
-	data[0] = ATP_WELLSPRING_MODE_VENDOR_VALUE_1;
-	data[1] = ATP_WELLSPRING_MODE_VENDOR_VALUE_2;
+	data[0] = ATP_WELLSPRING_MODE_VENDOR_VALUE;
 
 	/* write configuration */
 	size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
@@ -345,9 +324,7 @@ static int atp_wellspring_init(struct atp *dev)
 		goto error;
 	}
 
-	dev->tp_valid = 0;
-
-	printk(KERN_INFO "bcm5974: Wellspring mode initialized.\n");
+	dprintk(2, "bcm5974: switched to wellspring mode.\n");
 
 	kfree(data);
 	return 0;
@@ -409,11 +386,9 @@ static void irq_trackpad(struct urb *urb)
 		goto exit;
 	}
 
-	/* first sample data ignored */
-	if (!dev->tp_valid) {
-		dev->tp_valid = 1;
+	/* control response ignored */
+	if (dev->tp_urb->actual_length == 2)
 		goto exit;
-	}
 
 	if (report_tp_state(dev, dev->tp_urb->actual_length)) {
 		dprintk(1, "bcm5974: bad trackpad package, length: %d\n",
@@ -429,23 +404,45 @@ exit:
 		err("bcm5974: trackpad urb failed: %d", error);
 }
 
+/*
+ * The Wellspring trackpad, like many recent Apple trackpads, share
+ * the usb device with the keyboard. Since keyboards are usually
+ * handled by the HID system, the device ends up being handled by two
+ * modules. Setting up the device therefore becomes slightly
+ * complicated. To enable multitouch features, a mode switch is
+ * required, which is usually applied via the control interface of the
+ * device.  It can be argued where this switch should take place. In
+ * some drivers, like appletouch, the switch is made during
+ * probe. However, the hid module may also alter the state of the
+ * device, resulting in trackpad malfunction under certain
+ * circumstances. To get around this problem, there is at least one
+ * example that utilizes the USB_QUIRK_RESET_RESUME quirk in order to
+ * recieve a reset_resume request rather than the normal resume. Since
+ * the implementation of reset_resume is equal to mode switch plus
+ * open, it seems easier to always do the switch while opening the
+ * device.
+ */
 static int atp_open(struct input_dev *input)
 {
 	struct atp *dev = input_get_drvdata(input);
 
 	if (!dev->open) {
+		if (atp_wellspring_mode(dev)) {
+			dprintk(1, "bcm5974: mode switch failed\n");
+			goto error;
+		}
 		if (usb_submit_urb(dev->bt_urb, GFP_KERNEL))
 			goto error;
 		if (usb_submit_urb(dev->tp_urb, GFP_KERNEL))
-			goto err_free_bt_urb;
+			goto err_kill_bt;
 	}
 
 	dev->open = 1;
 	dev->suspended = 0;
 	return 0;
 
-err_free_bt_urb:
-	usb_free_urb(dev->bt_urb);
+err_kill_bt:
+	usb_kill_urb(dev->bt_urb);
 error:
 	return -EIO;
 }
@@ -486,12 +483,6 @@ static int atp_probe(struct usb_interface *iface,
 	dev->input = input_dev;
 	dev->cfg = *cfg;
 
-	/* switch to raw sensor mode */
-	if (atp_wellspring_init(dev)) {
-		error = -EIO;
-		goto err_free_devs;
-	}
-
 	dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!dev->bt_urb) {
 		error = -ENOMEM;
@@ -631,57 +622,27 @@ static int atp_resume(struct usb_interface *iface)
 	return error;
 }
 
-static int atp_reset_resume(struct usb_interface *iface)
-{
-	struct atp *dev = usb_get_intfdata(iface);
-
-	if (dev && atp_wellspring_init(dev))
-		printk(KERN_INFO "bcm5974: warning: reset failed\n");
-
-	return atp_resume(iface);
-}
-
-static int atp_pre_reset(struct usb_interface *iface)
-{
-	return atp_suspend(iface, PMSG_ON);
-}
-
-static int atp_post_reset(struct usb_interface *iface)
-{
-	return atp_reset_resume(iface);
-}
-
 static struct usb_driver atp_driver = {
 	.name = "bcm5974",
 	.probe = atp_probe,
 	.disconnect = atp_disconnect,
 	.suspend = atp_suspend,
 	.resume = atp_resume,
-	.reset_resume = atp_reset_resume,
-	.pre_reset = atp_pre_reset,
-	.post_reset = atp_post_reset,
+	.reset_resume = atp_resume,
 	.id_table = atp_table,
 };
 
-#define USB_VENDOR_ID_APPLE		0x05ac
-#define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI   0x0223
-#define USB_DEVICE_ID_APPLE_WELLSPRING_ISO    0x0224
-#define USB_DEVICE_ID_APPLE_WELLSPRING_JIS    0x0225
-#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI   0x0230
-#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO    0x0231
-#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS    0x0232
-
 static const struct hid_blacklist {
 	__u16 idVendor;
 	__u16 idProduct;
 	__u32 quirks;
 } hid_blacklist[] = {
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD | HID_QUIRK_IGNORE_MOUSE},
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE},
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE},
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, HID_QUIRK_APPLE_HAS_FN  | HID_QUIRK_IGNORE_MOUSE },
+	{ APPLE_VENDOR_ID, ATP_WELLSPRING_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+	{ APPLE_VENDOR_ID, ATP_WELLSPRING_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD | HID_QUIRK_IGNORE_MOUSE},
+	{ APPLE_VENDOR_ID, ATP_WELLSPRING_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE},
+	{ APPLE_VENDOR_ID, ATP_WELLSPRING2_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE},
+	{ APPLE_VENDOR_ID, ATP_WELLSPRING2_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD | HID_QUIRK_IGNORE_MOUSE },
+	{ APPLE_VENDOR_ID, ATP_WELLSPRING2_JIS, HID_QUIRK_APPLE_HAS_FN  | HID_QUIRK_IGNORE_MOUSE },
 	{0,0,0}
 };
 
@@ -689,6 +650,7 @@ static int __init atp_update_quirks(void)
 {
 	struct hid_blacklist *bp;
 	int result=0;
+#if 0
 	for (bp=hid_blacklist; bp->quirks; bp++)
 	{
 		result = usbhid_modify_dquirk(bp->idVendor,bp->idProduct,bp->quirks);
@@ -698,6 +660,7 @@ static int __init atp_update_quirks(void)
 			break;
 		}
 	}
+#endif
 	return result;
 }
 
-- 
1.5.4.3





More information about the kernel-team mailing list