diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 339b90135d37..743e6f8cb202 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1294,6 +1294,7 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 1635ccd877d7..a0d6a6cb1842 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -350,6 +350,7 @@ #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001 #define USB_VENDOR_ID_SONY 0x054c +#define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b #define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 #define USB_VENDOR_ID_SOUNDGRAPH 0x15c2 diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 3af8095a7de1..86e563b8d644 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -4,9 +4,9 @@ * Copyright (c) 1999 Andreas Gal * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina * Copyright (c) 2007 Paul Walmsley * Copyright (c) 2008 Jiri Slaby + * Copyright (c) 2006-2008 Jiri Kosina */ /* @@ -23,6 +23,26 @@ #include "hid-ids.h" +#define VAIO_RDESC_CONSTANT 0x0001 + +struct sony_sc { + unsigned long quirks; +}; + +/* Sony Vaio VGX has wrongly mouse pointer declared as constant */ +static void sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int rsize) +{ + struct sony_sc *sc = hid_get_drvdata(hdev); + + if ((sc->quirks & VAIO_RDESC_CONSTANT) && + rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) { + dev_info(&hdev->dev, "Fixing up Sony Vaio VGX report " + "descriptor\n"); + rdesc[55] = 0x06; + } +} + /* * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller * to "operational". Without this, the ps3 controller will not report any @@ -56,6 +76,17 @@ static int sony_set_operational(struct hid_device *hdev) static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) { int ret; + unsigned long quirks = id->driver_data; + struct sony_sc *sc; + + sc = kzalloc(sizeof(*sc), GFP_KERNEL); + if (sc == NULL) { + dev_err(&hdev->dev, "can't alloc apple descriptor\n"); + return -ENOMEM; + } + + sc->quirks = quirks; + hid_set_drvdata(hdev, sc); ret = hid_parse(hdev); if (ret) { @@ -78,11 +109,20 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) err_stop: hid_hw_stop(hdev); err_free: + kfree(sc); return ret; } +static void sony_remove(struct hid_device *hdev) +{ + hid_hw_stop(hdev); + kfree(hid_get_drvdata(hdev)); +} + static const struct hid_device_id sony_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), + .driver_data = VAIO_RDESC_CONSTANT }, { } }; MODULE_DEVICE_TABLE(hid, sony_devices); @@ -91,6 +131,8 @@ static struct hid_driver sony_driver = { .name = "sony", .id_table = sony_devices, .probe = sony_probe, + .remove = sony_remove, + .report_fixup = sony_report_fixup, }; static int sony_init(void)