From 0b7c7f032a6e5fdb8d29d29c9aa6efc5ba558832 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sat, 29 Jun 2013 17:52:18 +0200 Subject: [PATCH 1/2] linux: add HID Sony upstream patches to support Sony Buzz and PS3 remote repeating Signed-off-by: Stephan Raue --- ...nux-058.01-HID-Sony-upstream_patches.patch | 860 ++++++++++++++++++ ..._sony-add_autorepeat_for_PS3_remotes.patch | 61 ++ 2 files changed, 921 insertions(+) create mode 100644 packages/linux/patches/3.9.8/linux-058.01-HID-Sony-upstream_patches.patch create mode 100644 packages/linux/patches/3.9.8/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch diff --git a/packages/linux/patches/3.9.8/linux-058.01-HID-Sony-upstream_patches.patch b/packages/linux/patches/3.9.8/linux-058.01-HID-Sony-upstream_patches.patch new file mode 100644 index 0000000000..60cdb00b31 --- /dev/null +++ b/packages/linux/patches/3.9.8/linux-058.01-HID-Sony-upstream_patches.patch @@ -0,0 +1,860 @@ +diff -Naur linux-3.9.8/drivers/hid/hid-core.c linux-3.9.8.patch/drivers/hid/hid-core.c +--- linux-3.9.8/drivers/hid/hid-core.c 2013-06-27 19:41:32.000000000 +0200 ++++ linux-3.9.8.patch/drivers/hid/hid-core.c 2013-06-29 14:25:21.160976576 +0200 +@@ -1697,6 +1697,8 @@ + { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, +diff -Naur linux-3.9.8/drivers/hid/hid-ids.h linux-3.9.8.patch/drivers/hid/hid-ids.h +--- linux-3.9.8/drivers/hid/hid-ids.h 2013-06-27 19:41:32.000000000 +0200 ++++ linux-3.9.8.patch/drivers/hid/hid-ids.h 2013-06-29 14:25:21.161976575 +0200 +@@ -727,6 +727,8 @@ + #define USB_DEVICE_ID_SONY_PS3_BDREMOTE 0x0306 + #define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 + #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f ++#define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002 ++#define USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER 0x1000 + + #define USB_VENDOR_ID_SOUNDGRAPH 0x15c2 + #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034 +diff -Naur linux-3.9.8/drivers/hid/hid-ps3remote.c linux-3.9.8.patch/drivers/hid/hid-ps3remote.c +--- linux-3.9.8/drivers/hid/hid-ps3remote.c 2013-06-27 19:41:32.000000000 +0200 ++++ linux-3.9.8.patch/drivers/hid/hid-ps3remote.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,204 +0,0 @@ +-/* +- * HID driver for Sony PS3 BD Remote Control +- * +- * Copyright (c) 2012 David Dillow +- * Based on a blend of the bluez fakehid user-space code by Marcel Holtmann +- * and other kernel HID drivers. +- */ +- +-/* +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the Free +- * Software Foundation; either version 2 of the License, or (at your option) +- * any later version. +- */ +- +-/* NOTE: in order for the Sony PS3 BD Remote Control to be found by +- * a Bluetooth host, the key combination Start+Enter has to be kept pressed +- * for about 7 seconds with the Bluetooth Host Controller in discovering mode. +- * +- * There will be no PIN request from the device. +- */ +- +-#include +-#include +-#include +- +-#include "hid-ids.h" +- +-static __u8 ps3remote_rdesc[] = { +- 0x05, 0x01, /* GUsagePage Generic Desktop */ +- 0x09, 0x05, /* LUsage 0x05 [Game Pad] */ +- 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */ +- +- /* Use collection 1 for joypad buttons */ +- 0xA1, 0x02, /* MCollection Logical (interrelated data) */ +- +- /* Ignore the 1st byte, maybe it is used for a controller +- * number but it's not needed for correct operation */ +- 0x75, 0x08, /* GReportSize 0x08 [8] */ +- 0x95, 0x01, /* GReportCount 0x01 [1] */ +- 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ +- +- /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these +- * buttons multiple keypresses are allowed */ +- 0x05, 0x09, /* GUsagePage Button */ +- 0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */ +- 0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */ +- 0x14, /* GLogicalMinimum [0] */ +- 0x25, 0x01, /* GLogicalMaximum 0x01 [1] */ +- 0x75, 0x01, /* GReportSize 0x01 [1] */ +- 0x95, 0x18, /* GReportCount 0x18 [24] */ +- 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ +- +- 0xC0, /* MEndCollection */ +- +- /* Use collection 2 for remote control buttons */ +- 0xA1, 0x02, /* MCollection Logical (interrelated data) */ +- +- /* 5th byte is used for remote control buttons */ +- 0x05, 0x09, /* GUsagePage Button */ +- 0x18, /* LUsageMinimum [No button pressed] */ +- 0x29, 0xFE, /* LUsageMaximum 0xFE [Button 254] */ +- 0x14, /* GLogicalMinimum [0] */ +- 0x26, 0xFE, 0x00, /* GLogicalMaximum 0x00FE [254] */ +- 0x75, 0x08, /* GReportSize 0x08 [8] */ +- 0x95, 0x01, /* GReportCount 0x01 [1] */ +- 0x80, /* MInput */ +- +- /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at +- * 0xff and 11th is for press indication */ +- 0x75, 0x08, /* GReportSize 0x08 [8] */ +- 0x95, 0x06, /* GReportCount 0x06 [6] */ +- 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ +- +- /* 12th byte is for battery strength */ +- 0x05, 0x06, /* GUsagePage Generic Device Controls */ +- 0x09, 0x20, /* LUsage 0x20 [Battery Strength] */ +- 0x14, /* GLogicalMinimum [0] */ +- 0x25, 0x05, /* GLogicalMaximum 0x05 [5] */ +- 0x75, 0x08, /* GReportSize 0x08 [8] */ +- 0x95, 0x01, /* GReportCount 0x01 [1] */ +- 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ +- +- 0xC0, /* MEndCollection */ +- +- 0xC0 /* MEndCollection [Game Pad] */ +-}; +- +-static const unsigned int ps3remote_keymap_joypad_buttons[] = { +- [0x01] = KEY_SELECT, +- [0x02] = BTN_THUMBL, /* L3 */ +- [0x03] = BTN_THUMBR, /* R3 */ +- [0x04] = BTN_START, +- [0x05] = KEY_UP, +- [0x06] = KEY_RIGHT, +- [0x07] = KEY_DOWN, +- [0x08] = KEY_LEFT, +- [0x09] = BTN_TL2, /* L2 */ +- [0x0a] = BTN_TR2, /* R2 */ +- [0x0b] = BTN_TL, /* L1 */ +- [0x0c] = BTN_TR, /* R1 */ +- [0x0d] = KEY_OPTION, /* options/triangle */ +- [0x0e] = KEY_BACK, /* back/circle */ +- [0x0f] = BTN_0, /* cross */ +- [0x10] = KEY_SCREEN, /* view/square */ +- [0x11] = KEY_HOMEPAGE, /* PS button */ +- [0x14] = KEY_ENTER, +-}; +-static const unsigned int ps3remote_keymap_remote_buttons[] = { +- [0x00] = KEY_1, +- [0x01] = KEY_2, +- [0x02] = KEY_3, +- [0x03] = KEY_4, +- [0x04] = KEY_5, +- [0x05] = KEY_6, +- [0x06] = KEY_7, +- [0x07] = KEY_8, +- [0x08] = KEY_9, +- [0x09] = KEY_0, +- [0x0e] = KEY_ESC, /* return */ +- [0x0f] = KEY_CLEAR, +- [0x16] = KEY_EJECTCD, +- [0x1a] = KEY_MENU, /* top menu */ +- [0x28] = KEY_TIME, +- [0x30] = KEY_PREVIOUS, +- [0x31] = KEY_NEXT, +- [0x32] = KEY_PLAY, +- [0x33] = KEY_REWIND, /* scan back */ +- [0x34] = KEY_FORWARD, /* scan forward */ +- [0x38] = KEY_STOP, +- [0x39] = KEY_PAUSE, +- [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */ +- [0x60] = KEY_FRAMEBACK, /* slow/step back */ +- [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */ +- [0x63] = KEY_SUBTITLE, +- [0x64] = KEY_AUDIO, +- [0x65] = KEY_ANGLE, +- [0x70] = KEY_INFO, /* display */ +- [0x80] = KEY_BLUE, +- [0x81] = KEY_RED, +- [0x82] = KEY_GREEN, +- [0x83] = KEY_YELLOW, +-}; +- +-static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, +- unsigned int *rsize) +-{ +- *rsize = sizeof(ps3remote_rdesc); +- return ps3remote_rdesc; +-} +- +-static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, +- struct hid_field *field, struct hid_usage *usage, +- unsigned long **bit, int *max) +-{ +- unsigned int key = usage->hid & HID_USAGE; +- +- if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) +- return -1; +- +- switch (usage->collection_index) { +- case 1: +- if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons)) +- return -1; +- +- key = ps3remote_keymap_joypad_buttons[key]; +- if (!key) +- return -1; +- break; +- case 2: +- if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons)) +- return -1; +- +- key = ps3remote_keymap_remote_buttons[key]; +- if (!key) +- return -1; +- break; +- default: +- return -1; +- } +- +- hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); +- return 1; +-} +- +-static const struct hid_device_id ps3remote_devices[] = { +- /* PS3 BD Remote Control */ +- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, +- /* Logitech Harmony Adapter for PS3 */ +- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) }, +- { } +-}; +-MODULE_DEVICE_TABLE(hid, ps3remote_devices); +- +-static struct hid_driver ps3remote_driver = { +- .name = "ps3_remote", +- .id_table = ps3remote_devices, +- .report_fixup = ps3remote_fixup, +- .input_mapping = ps3remote_mapping, +-}; +-module_hid_driver(ps3remote_driver); +- +-MODULE_LICENSE("GPL"); +-MODULE_AUTHOR("David Dillow , Antonio Ospite "); +diff -Naur linux-3.9.8/drivers/hid/hid-sony.c linux-3.9.8.patch/drivers/hid/hid-sony.c +--- linux-3.9.8/drivers/hid/hid-sony.c 2013-06-27 19:41:32.000000000 +0200 ++++ linux-3.9.8.patch/drivers/hid/hid-sony.c 2013-06-29 14:26:02.738933634 +0200 +@@ -1,11 +1,13 @@ + /* +- * HID driver for some sony "special" devices ++ * HID driver for Sony / PS2 / PS3 BD devices. + * + * Copyright (c) 1999 Andreas Gal + * Copyright (c) 2000-2005 Vojtech Pavlik + * Copyright (c) 2005 Michael Haboustak for Concept2, Inc + * Copyright (c) 2008 Jiri Slaby +- * Copyright (c) 2006-2008 Jiri Kosina ++ * Copyright (c) 2012 David Dillow ++ * Copyright (c) 2006-2013 Jiri Kosina ++ * Copyright (c) 2013 Colin Leitner + */ + + /* +@@ -15,17 +17,28 @@ + * any later version. + */ + ++/* NOTE: in order for the Sony PS3 BD Remote Control to be found by ++ * a Bluetooth host, the key combination Start+Enter has to be kept pressed ++ * for about 7 seconds with the Bluetooth Host Controller in discovering mode. ++ * ++ * There will be no PIN request from the device. ++ */ ++ + #include + #include + #include + #include + #include ++#include "usbhid/usbhid.h" ++#include + + #include "hid-ids.h" + + #define VAIO_RDESC_CONSTANT (1 << 0) + #define SIXAXIS_CONTROLLER_USB (1 << 1) + #define SIXAXIS_CONTROLLER_BT (1 << 2) ++#define BUZZ_CONTROLLER (1 << 3) ++#define PS3REMOTE (1 << 4) + + static const u8 sixaxis_rdesc_fixup[] = { + 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C, +@@ -55,10 +68,214 @@ + 0xb1, 0x02, 0xc0, 0xc0, + }; + ++static __u8 ps3remote_rdesc[] = { ++ 0x05, 0x01, /* GUsagePage Generic Desktop */ ++ 0x09, 0x05, /* LUsage 0x05 [Game Pad] */ ++ 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */ ++ ++ /* Use collection 1 for joypad buttons */ ++ 0xA1, 0x02, /* MCollection Logical (interrelated data) */ ++ ++ /* Ignore the 1st byte, maybe it is used for a controller ++ * number but it's not needed for correct operation */ ++ 0x75, 0x08, /* GReportSize 0x08 [8] */ ++ 0x95, 0x01, /* GReportCount 0x01 [1] */ ++ 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ ++ ++ /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these ++ * buttons multiple keypresses are allowed */ ++ 0x05, 0x09, /* GUsagePage Button */ ++ 0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */ ++ 0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */ ++ 0x14, /* GLogicalMinimum [0] */ ++ 0x25, 0x01, /* GLogicalMaximum 0x01 [1] */ ++ 0x75, 0x01, /* GReportSize 0x01 [1] */ ++ 0x95, 0x18, /* GReportCount 0x18 [24] */ ++ 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ ++ ++ 0xC0, /* MEndCollection */ ++ ++ /* Use collection 2 for remote control buttons */ ++ 0xA1, 0x02, /* MCollection Logical (interrelated data) */ ++ ++ /* 5th byte is used for remote control buttons */ ++ 0x05, 0x09, /* GUsagePage Button */ ++ 0x18, /* LUsageMinimum [No button pressed] */ ++ 0x29, 0xFE, /* LUsageMaximum 0xFE [Button 254] */ ++ 0x14, /* GLogicalMinimum [0] */ ++ 0x26, 0xFE, 0x00, /* GLogicalMaximum 0x00FE [254] */ ++ 0x75, 0x08, /* GReportSize 0x08 [8] */ ++ 0x95, 0x01, /* GReportCount 0x01 [1] */ ++ 0x80, /* MInput */ ++ ++ /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at ++ * 0xff and 11th is for press indication */ ++ 0x75, 0x08, /* GReportSize 0x08 [8] */ ++ 0x95, 0x06, /* GReportCount 0x06 [6] */ ++ 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ ++ ++ /* 12th byte is for battery strength */ ++ 0x05, 0x06, /* GUsagePage Generic Device Controls */ ++ 0x09, 0x20, /* LUsage 0x20 [Battery Strength] */ ++ 0x14, /* GLogicalMinimum [0] */ ++ 0x25, 0x05, /* GLogicalMaximum 0x05 [5] */ ++ 0x75, 0x08, /* GReportSize 0x08 [8] */ ++ 0x95, 0x01, /* GReportCount 0x01 [1] */ ++ 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ ++ ++ 0xC0, /* MEndCollection */ ++ ++ 0xC0 /* MEndCollection [Game Pad] */ ++}; ++ ++static const unsigned int ps3remote_keymap_joypad_buttons[] = { ++ [0x01] = KEY_SELECT, ++ [0x02] = BTN_THUMBL, /* L3 */ ++ [0x03] = BTN_THUMBR, /* R3 */ ++ [0x04] = BTN_START, ++ [0x05] = KEY_UP, ++ [0x06] = KEY_RIGHT, ++ [0x07] = KEY_DOWN, ++ [0x08] = KEY_LEFT, ++ [0x09] = BTN_TL2, /* L2 */ ++ [0x0a] = BTN_TR2, /* R2 */ ++ [0x0b] = BTN_TL, /* L1 */ ++ [0x0c] = BTN_TR, /* R1 */ ++ [0x0d] = KEY_OPTION, /* options/triangle */ ++ [0x0e] = KEY_BACK, /* back/circle */ ++ [0x0f] = BTN_0, /* cross */ ++ [0x10] = KEY_SCREEN, /* view/square */ ++ [0x11] = KEY_HOMEPAGE, /* PS button */ ++ [0x14] = KEY_ENTER, ++}; ++static const unsigned int ps3remote_keymap_remote_buttons[] = { ++ [0x00] = KEY_1, ++ [0x01] = KEY_2, ++ [0x02] = KEY_3, ++ [0x03] = KEY_4, ++ [0x04] = KEY_5, ++ [0x05] = KEY_6, ++ [0x06] = KEY_7, ++ [0x07] = KEY_8, ++ [0x08] = KEY_9, ++ [0x09] = KEY_0, ++ [0x0e] = KEY_ESC, /* return */ ++ [0x0f] = KEY_CLEAR, ++ [0x16] = KEY_EJECTCD, ++ [0x1a] = KEY_MENU, /* top menu */ ++ [0x28] = KEY_TIME, ++ [0x30] = KEY_PREVIOUS, ++ [0x31] = KEY_NEXT, ++ [0x32] = KEY_PLAY, ++ [0x33] = KEY_REWIND, /* scan back */ ++ [0x34] = KEY_FORWARD, /* scan forward */ ++ [0x38] = KEY_STOP, ++ [0x39] = KEY_PAUSE, ++ [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */ ++ [0x60] = KEY_FRAMEBACK, /* slow/step back */ ++ [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */ ++ [0x63] = KEY_SUBTITLE, ++ [0x64] = KEY_AUDIO, ++ [0x65] = KEY_ANGLE, ++ [0x70] = KEY_INFO, /* display */ ++ [0x80] = KEY_BLUE, ++ [0x81] = KEY_RED, ++ [0x82] = KEY_GREEN, ++ [0x83] = KEY_YELLOW, ++}; ++ ++static const unsigned int buzz_keymap[] = { ++ /* The controller has 4 remote buzzers, each with one LED and 5 ++ * buttons. ++ * ++ * We use the mapping chosen by the controller, which is: ++ * ++ * Key Offset ++ * ------------------- ++ * Buzz 1 ++ * Blue 5 ++ * Orange 4 ++ * Green 3 ++ * Yellow 2 ++ * ++ * So, for example, the orange button on the third buzzer is mapped to ++ * BTN_TRIGGER_HAPPY14 ++ */ ++ [ 1] = BTN_TRIGGER_HAPPY1, ++ [ 2] = BTN_TRIGGER_HAPPY2, ++ [ 3] = BTN_TRIGGER_HAPPY3, ++ [ 4] = BTN_TRIGGER_HAPPY4, ++ [ 5] = BTN_TRIGGER_HAPPY5, ++ [ 6] = BTN_TRIGGER_HAPPY6, ++ [ 7] = BTN_TRIGGER_HAPPY7, ++ [ 8] = BTN_TRIGGER_HAPPY8, ++ [ 9] = BTN_TRIGGER_HAPPY9, ++ [10] = BTN_TRIGGER_HAPPY10, ++ [11] = BTN_TRIGGER_HAPPY11, ++ [12] = BTN_TRIGGER_HAPPY12, ++ [13] = BTN_TRIGGER_HAPPY13, ++ [14] = BTN_TRIGGER_HAPPY14, ++ [15] = BTN_TRIGGER_HAPPY15, ++ [16] = BTN_TRIGGER_HAPPY16, ++ [17] = BTN_TRIGGER_HAPPY17, ++ [18] = BTN_TRIGGER_HAPPY18, ++ [19] = BTN_TRIGGER_HAPPY19, ++ [20] = BTN_TRIGGER_HAPPY20, ++}; ++ + struct sony_sc { + unsigned long quirks; ++ ++ void *extra; ++}; ++ ++struct buzz_extra { ++ int led_state; ++ struct led_classdev *leds[4]; + }; + ++static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, ++ unsigned int *rsize) ++{ ++ *rsize = sizeof(ps3remote_rdesc); ++ return ps3remote_rdesc; ++} ++ ++static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, ++ struct hid_field *field, struct hid_usage *usage, ++ unsigned long **bit, int *max) ++{ ++ unsigned int key = usage->hid & HID_USAGE; ++ ++ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) ++ return -1; ++ ++ switch (usage->collection_index) { ++ case 1: ++ if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons)) ++ return -1; ++ ++ key = ps3remote_keymap_joypad_buttons[key]; ++ if (!key) ++ return -1; ++ break; ++ case 2: ++ if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons)) ++ return -1; ++ ++ key = ps3remote_keymap_remote_buttons[key]; ++ if (!key) ++ return -1; ++ break; ++ default: ++ return -1; ++ } ++ ++ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); ++ return 1; ++} ++ ++ + /* Sony Vaio VGX has wrongly mouse pointer declared as constant */ + static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) +@@ -95,6 +312,10 @@ + *rsize = sizeof(sixaxis_rdesc_fixup2); + memcpy(rdesc, &sixaxis_rdesc_fixup2, *rsize); + } ++ ++ if (sc->quirks & PS3REMOTE) ++ return ps3remote_fixup(hdev, rdesc, rsize); ++ + return rdesc; + } + +@@ -117,6 +338,41 @@ + return 0; + } + ++static int sony_mapping(struct hid_device *hdev, struct hid_input *hi, ++ struct hid_field *field, struct hid_usage *usage, ++ unsigned long **bit, int *max) ++{ ++ struct sony_sc *sc = hid_get_drvdata(hdev); ++ ++ if (sc->quirks & BUZZ_CONTROLLER) { ++ unsigned int key = usage->hid & HID_USAGE; ++ ++ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) ++ return -1; ++ ++ switch (usage->collection_index) { ++ case 1: ++ if (key >= ARRAY_SIZE(buzz_keymap)) ++ return -1; ++ ++ key = buzz_keymap[key]; ++ if (!key) ++ return -1; ++ break; ++ default: ++ return -1; ++ } ++ ++ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); ++ return 1; ++ } ++ ++ if (sc->quirks & PS3REMOTE) ++ return ps3remote_mapping(hdev, hi, field, usage, bit, max); ++ ++ return -1; ++} ++ + /* + * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP + * like it should according to usbhid/hid-core.c::usbhid_output_raw_report() +@@ -192,11 +448,181 @@ + return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); + } + ++static void buzz_set_leds(struct hid_device *hdev, int leds) ++{ ++ struct list_head *report_list = ++ &hdev->report_enum[HID_OUTPUT_REPORT].report_list; ++ struct hid_report *report = list_entry(report_list->next, ++ struct hid_report, list); ++ __s32 *value = report->field[0]->value; ++ ++ value[0] = 0x00; ++ value[1] = (leds & 1) ? 0xff : 0x00; ++ value[2] = (leds & 2) ? 0xff : 0x00; ++ value[3] = (leds & 4) ? 0xff : 0x00; ++ value[4] = (leds & 8) ? 0xff : 0x00; ++ value[5] = 0x00; ++ value[6] = 0x00; ++ usbhid_submit_report(hdev, report, USB_DIR_OUT); ++} ++ ++static void buzz_led_set_brightness(struct led_classdev *led, ++ enum led_brightness value) ++{ ++ struct device *dev = led->dev->parent; ++ struct hid_device *hdev = container_of(dev, struct hid_device, dev); ++ struct sony_sc *drv_data; ++ struct buzz_extra *buzz; ++ ++ int n; ++ ++ drv_data = hid_get_drvdata(hdev); ++ if (!drv_data || !drv_data->extra) { ++ hid_err(hdev, "No device data\n"); ++ return; ++ } ++ buzz = drv_data->extra; ++ ++ for (n = 0; n < 4; n++) { ++ if (led == buzz->leds[n]) { ++ int on = !! (buzz->led_state & (1 << n)); ++ if (value == LED_OFF && on) { ++ buzz->led_state &= ~(1 << n); ++ buzz_set_leds(hdev, buzz->led_state); ++ } else if (value != LED_OFF && !on) { ++ buzz->led_state |= (1 << n); ++ buzz_set_leds(hdev, buzz->led_state); ++ } ++ break; ++ } ++ } ++} ++ ++static enum led_brightness buzz_led_get_brightness(struct led_classdev *led) ++{ ++ struct device *dev = led->dev->parent; ++ struct hid_device *hdev = container_of(dev, struct hid_device, dev); ++ struct sony_sc *drv_data; ++ struct buzz_extra *buzz; ++ ++ int n; ++ int on = 0; ++ ++ drv_data = hid_get_drvdata(hdev); ++ if (!drv_data || !drv_data->extra) { ++ hid_err(hdev, "No device data\n"); ++ return LED_OFF; ++ } ++ buzz = drv_data->extra; ++ ++ for (n = 0; n < 4; n++) { ++ if (led == buzz->leds[n]) { ++ on = !! (buzz->led_state & (1 << n)); ++ break; ++ } ++ } ++ ++ return on ? LED_FULL : LED_OFF; ++} ++ ++static int buzz_init(struct hid_device *hdev) ++{ ++ struct sony_sc *drv_data; ++ struct buzz_extra *buzz; ++ int n, ret = 0; ++ struct led_classdev *led; ++ size_t name_sz; ++ char *name; ++ ++ drv_data = hid_get_drvdata(hdev); ++ BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER)); ++ ++ buzz = kzalloc(sizeof(*buzz), GFP_KERNEL); ++ if (!buzz) { ++ hid_err(hdev, "Insufficient memory, cannot allocate driver data\n"); ++ return -ENOMEM; ++ } ++ drv_data->extra = buzz; ++ ++ /* Clear LEDs as we have no way of reading their initial state. This is ++ * only relevant if the driver is loaded after somebody actively set the ++ * LEDs to on */ ++ buzz_set_leds(hdev, 0x00); ++ ++ name_sz = strlen(dev_name(&hdev->dev)) + strlen("::buzz#") + 1; ++ ++ for (n = 0; n < 4; n++) { ++ led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL); ++ if (!led) { ++ hid_err(hdev, "Couldn't allocate memory for LED %d\n", n); ++ goto error_leds; ++ } ++ ++ name = (void *)(&led[1]); ++ snprintf(name, name_sz, "%s::buzz%d", dev_name(&hdev->dev), n + 1); ++ led->name = name; ++ led->brightness = 0; ++ led->max_brightness = 1; ++ led->brightness_get = buzz_led_get_brightness; ++ led->brightness_set = buzz_led_set_brightness; ++ ++ if (led_classdev_register(&hdev->dev, led)) { ++ hid_err(hdev, "Failed to register LED %d\n", n); ++ kfree(led); ++ goto error_leds; ++ } ++ ++ buzz->leds[n] = led; ++ } ++ ++ return ret; ++ ++error_leds: ++ for (n = 0; n < 4; n++) { ++ led = buzz->leds[n]; ++ buzz->leds[n] = NULL; ++ if (!led) ++ continue; ++ led_classdev_unregister(led); ++ kfree(led); ++ } ++ ++ kfree(drv_data->extra); ++ drv_data->extra = NULL; ++ return ret; ++} ++ ++static void buzz_remove(struct hid_device *hdev) ++{ ++ struct sony_sc *drv_data; ++ struct buzz_extra *buzz; ++ struct led_classdev *led; ++ int n; ++ ++ drv_data = hid_get_drvdata(hdev); ++ BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER)); ++ ++ buzz = drv_data->extra; ++ ++ for (n = 0; n < 4; n++) { ++ led = buzz->leds[n]; ++ buzz->leds[n] = NULL; ++ if (!led) ++ continue; ++ led_classdev_unregister(led); ++ kfree(led); ++ } ++ ++ kfree(drv_data->extra); ++ drv_data->extra = NULL; ++} ++ + 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; ++ unsigned int connect_mask = HID_CONNECT_DEFAULT; + + sc = kzalloc(sizeof(*sc), GFP_KERNEL); + if (sc == NULL) { +@@ -213,8 +639,14 @@ + goto err_free; + } + +- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | +- HID_CONNECT_HIDDEV_FORCE); ++ if (sc->quirks & VAIO_RDESC_CONSTANT) ++ connect_mask |= HID_CONNECT_HIDDEV_FORCE; ++ else if (sc->quirks & SIXAXIS_CONTROLLER_USB) ++ connect_mask |= HID_CONNECT_HIDDEV_FORCE; ++ else if (sc->quirks & SIXAXIS_CONTROLLER_BT) ++ connect_mask |= HID_CONNECT_HIDDEV_FORCE; ++ ++ ret = hid_hw_start(hdev, connect_mask); + if (ret) { + hid_err(hdev, "hw start failed\n"); + goto err_free; +@@ -226,6 +658,8 @@ + } + else if (sc->quirks & SIXAXIS_CONTROLLER_BT) + ret = sixaxis_set_operational_bt(hdev); ++ else if (sc->quirks & BUZZ_CONTROLLER) ++ ret = buzz_init(hdev); + else + ret = 0; + +@@ -242,8 +676,13 @@ + + static void sony_remove(struct hid_device *hdev) + { ++ struct sony_sc *sc = hid_get_drvdata(hdev); ++ ++ if (sc->quirks & BUZZ_CONTROLLER) ++ buzz_remove(hdev); ++ + hid_hw_stop(hdev); +- kfree(hid_get_drvdata(hdev)); ++ kfree(sc); + } + + static const struct hid_device_id sony_devices[] = { +@@ -257,17 +696,30 @@ + .driver_data = VAIO_RDESC_CONSTANT }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE), + .driver_data = VAIO_RDESC_CONSTANT }, ++ /* Wired Buzz Controller. Reported as Sony Hub from its USB ID and as ++ * Logitech joystick from the device descriptor. */ ++ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER), ++ .driver_data = BUZZ_CONTROLLER }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER), ++ .driver_data = BUZZ_CONTROLLER }, ++ /* PS3 BD Remote Control */ ++ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE), ++ .driver_data = PS3REMOTE }, ++ /* Logitech Harmony Adapter for PS3 */ ++ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3), ++ .driver_data = PS3REMOTE }, + { } + }; + MODULE_DEVICE_TABLE(hid, sony_devices); + + static struct hid_driver sony_driver = { +- .name = "sony", +- .id_table = sony_devices, +- .probe = sony_probe, +- .remove = sony_remove, +- .report_fixup = sony_report_fixup, +- .raw_event = sony_raw_event ++ .name = "sony", ++ .id_table = sony_devices, ++ .input_mapping = sony_mapping, ++ .probe = sony_probe, ++ .remove = sony_remove, ++ .report_fixup = sony_report_fixup, ++ .raw_event = sony_raw_event + }; + module_hid_driver(sony_driver); + +diff -Naur linux-3.9.8/drivers/hid/Kconfig linux-3.9.8.patch/drivers/hid/Kconfig +--- linux-3.9.8/drivers/hid/Kconfig 2013-06-27 19:41:32.000000000 +0200 ++++ linux-3.9.8.patch/drivers/hid/Kconfig 2013-06-29 14:25:21.173976563 +0200 +@@ -550,15 +550,6 @@ + Support for Primax devices that are not fully compliant with the + HID standard. + +-config HID_PS3REMOTE +- tristate "Sony PS3 BD Remote Control" +- depends on BT_HIDP +- ---help--- +- Support for the Sony PS3 Blue-ray Disk Remote Control and Logitech +- Harmony Adapter for PS3, which connect over Bluetooth. +- +- Support for the 6-axis controllers is provided by HID_SONY. +- + config HID_ROCCAT + tristate "Roccat device support" + depends on USB_HID +@@ -583,12 +574,17 @@ + Support for Samsung InfraRed remote control or keyboards. + + config HID_SONY +- tristate "Sony PS3 controller" ++ tristate "Sony PS2/3 accessories" + depends on USB_HID ++ depends on NEW_LEDS ++ depends on LEDS_CLASS + ---help--- +- Support for Sony PS3 6-axis controllers. +- +- Support for the Sony PS3 BD Remote is provided by HID_PS3REMOTE. ++ Support for ++ ++ * Sony PS3 6-axis controllers ++ * Buzz controllers ++ * Sony PS3 Blue-ray Disk Remote Control (Bluetooth) ++ * Logitech Harmony adapter for Sony Playstation 3 (Bluetooth) + + config HID_SPEEDLINK + tristate "Speedlink VAD Cezanne mouse support" +diff -Naur linux-3.9.8/drivers/hid/Makefile linux-3.9.8.patch/drivers/hid/Makefile +--- linux-3.9.8/drivers/hid/Makefile 2013-06-27 19:41:32.000000000 +0200 ++++ linux-3.9.8.patch/drivers/hid/Makefile 2013-06-29 14:25:21.174976562 +0200 +@@ -91,7 +91,6 @@ + endif + + obj-$(CONFIG_HID_PRIMAX) += hid-primax.o +-obj-$(CONFIG_HID_PS3REMOTE) += hid-ps3remote.o + obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ + hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ + hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-lua.o \ diff --git a/packages/linux/patches/3.9.8/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch b/packages/linux/patches/3.9.8/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch new file mode 100644 index 0000000000..abdc74f673 --- /dev/null +++ b/packages/linux/patches/3.9.8/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch @@ -0,0 +1,61 @@ +Betreff: [RFC] hid/sony: add autorepeat for PS3 remotes +Von: David Dillow +Datum: 28.06.2013 04:28 +An: linux-input@vger.kernel.org +Kopie (CC): Stephan Raue + +Some applications using the PS3 remote would like to have autorepeat +from the device. Use the input subsystem's software emulation to provide +this capability, and enable those that don't need it to turn it off. +--- +I'm not sure this is the correct approach, or if it is even appropriate +for a remote to do autorepeat. However, the media/rc subsystem does do +it by default, and it's been requested by users, so there is at least +some demand. + +This compiled against the hid-sony driver with the PS3 remote changes +merged, but I have done no testing of it. If the approach seems +reasonable, I'll try to test it when the MythTV is idle. + + drivers/hid/hid-sony.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) +diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c +index ecbc749..0bbcd07 100644 +--- a/drivers/hid/hid-sony.c ++++ b/drivers/hid/hid-sony.c +@@ -274,6 +274,24 @@ static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, + return 1; + } + ++static int ps3remote_setup_repeat(struct hid_device *hdev) ++{ ++ struct hid_input *hidinput = list_first_entry(&hdev->inputs, ++ struct hid_input, list); ++ struct input_dev *input = hidinput->input; ++ ++ /* ++ * Set up autorepeat defaults per the remote control subsystem; ++ * this must be done after hid_hw_start(), as having these non-zero ++ * at the time of input_register_device() tells the input system that ++ * the hardware does the autorepeat, and the PS3 remote does not. ++ */ ++ set_bit(EV_REP, input->evbit); ++ input->rep[REP_DELAY] = 500; ++ input->rep[REP_PERIOD] = 125; ++ ++ return 0; ++} + + /* Sony Vaio VGX has wrongly mouse pointer declared as constant */ + static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, +@@ -659,6 +677,8 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) + ret = sixaxis_set_operational_bt(hdev); + else if (sc->quirks & BUZZ_CONTROLLER) + ret = buzz_init(hdev); ++ else if (sc->quirks & PS3REMOTE) ++ ret = ps3remote_setup_repeat(hdev); + else + ret = 0; + + + From 326a1605e7f857c0218aebfe4e08c0170b12a124 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sat, 29 Jun 2013 17:53:07 +0200 Subject: [PATCH 2/2] eventlircd: add Sony PS3 remote support and map buttons Signed-off-by: Stephan Raue --- .../remote/eventlircd/evmap/ps3remote.evmap | 63 +++++++++++++++++++ .../eventlircd/udev.d/98-eventlircd.rules | 4 ++ 2 files changed, 67 insertions(+) create mode 100644 packages/sysutils/remote/eventlircd/evmap/ps3remote.evmap diff --git a/packages/sysutils/remote/eventlircd/evmap/ps3remote.evmap b/packages/sysutils/remote/eventlircd/evmap/ps3remote.evmap new file mode 100644 index 0000000000..b928276a29 --- /dev/null +++ b/packages/sysutils/remote/eventlircd/evmap/ps3remote.evmap @@ -0,0 +1,63 @@ +# PS3 Bluetooth remote + +KEY_EJECTCD = KEY_EJECT # Eject + +KEY_NUMERIC_1 = KEY_NUMERIC_1 # 1 +KEY_NUMERIC_2 = KEY_NUMERIC_2 # 2 +KEY_NUMERIC_3 = KEY_NUMERIC_3 # 3 +KEY_NUMERIC_4 = KEY_NUMERIC_4 # 4 +KEY_NUMERIC_5 = KEY_NUMERIC_5 # 5 +KEY_NUMERIC_6 = KEY_NUMERIC_6 # 6 +KEY_NUMERIC_7 = KEY_NUMERIC_7 # 7 +KEY_NUMERIC_8 = KEY_NUMERIC_8 # 8 +KEY_NUMERIC_9 = KEY_NUMERIC_9 # 9 +KEY_NUMERIC_0 = KEY_NUMERIC_0 # 0 + +KEY_AUDIO = KEY_LANGUAGE # Audio +KEY_SUBTITLE = KEY_SUBTITLE # Subtitle +KEY_ZOOM = KEY_ZOOM # Angle +KEY_CLEAR = KEY_DELETE # Clear +KEY_TIME = KEY_TIME # Time + +KEY_RED = KEY_RED # Red +KEY_GREEN = KEY_GREEN # Green +KEY_YELLOW = KEY_YELLOW # Yellow +KEY_BLUE = KEY_BLUE # Blue + +KEY_INFO = KEY_INFO # Display +KEY_MENU = KEY_MENU # Top Menu +KEY_CONTEXT_MENU = KEY_EPG # Pop UP/MENU +KEY_ESC = KEY_EXIT # Return + +KEY_BACK = KEY_EXIT # Back +KEY_OPTION = KEY_OPTION # Options +KEY_SCREEN = KEY_SCREEN # View +BTN_0 = KEY_EXIT # X + +KEY_UP = KEY_UP # Direction Up +KEY_DOWN = KEY_DOWN # Direction Down +KEY_LEFT = KEY_LEFT # Direction Left +KEY_RIGHT = KEY_RIGHT # Direction Right +KEY_ENTER = KEY_OK # Enter + +BTN_TL = KEY_VOLUMEUP # L1 -> Volume Upn +BTN_TL2 = KEY_VOLUMEDOWN # L2 -> Volume down +BTN_THUMBL = KEY_MUTE # L3 -> Mute + +KEY_HOMEPAGE = KEY_PROG1 # PS3 Menu +KEY_SELECT = KEY_RECORD # Select +KEY_START = KEY_OK # Start + +BTN_TR = KEY_CHANNELUP # R1 -> Channel Up +BTN_TR2 = KEY_CHANNELDOWN # R2 -> Channel down +BTN_THUMBR = KEY_PREVIOUS # R3 -> Previous Channel + +KEY_PLAY = KEY_PLAY # Play +KEY_STOP = KEY_STOP # Stop +KEY_PAUSE = KEY_PAUSE # Pause +KEY_REWIND = KEY_REWIND # Reverse +KEY_FORWARD = KEY_FASTFORWARD # Forward +KEY_PREVIOUS = KEY_PREVIOUS # Pre-track +KEY_NEXT = KEY_NEXT # Next track +KEY_FRAMEBACK = KEY_FRAMEBACK # Step back +KEY_FRAMEFORWARD = KEY_FRAMEFORWARD # Step forward diff --git a/packages/sysutils/remote/eventlircd/udev.d/98-eventlircd.rules b/packages/sysutils/remote/eventlircd/udev.d/98-eventlircd.rules index 04a232d878..6966d50745 100644 --- a/packages/sysutils/remote/eventlircd/udev.d/98-eventlircd.rules +++ b/packages/sysutils/remote/eventlircd/udev.d/98-eventlircd.rules @@ -179,6 +179,10 @@ ATTRS{name}=="Nintendo Wii Remote", \ ENV{eventlircd_enable}="true", \ ENV{eventlircd_evmap}="wiimote.evmap" +ATTRS{name}=="BD Remote Control", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="ps3remote.evmap" + LABEL="end-bluetooth" LABEL="end"