diff mbox

[v2] HID: Add support for Sony PS3 BD Remote Control

Message ID 1347932038.29391.17.camel@obelisk.thedillows.org (mailing list archive)
State New, archived
Delegated to: Jiri Kosina
Headers show

Commit Message

David Dillow Sept. 18, 2012, 1:33 a.m. UTC
The Sony PS3 Blue-ray Disc Remote Control used to be supported by the
BlueZ project's user space, but the code that handled it was recently
removed as its functionality conflicted with a real HSP implementation
and the mapping was thought to be better handled in the kernel. This is
a port of the mapping logic from the fakehid driver by Marcel Holtmann
to the in-kernel HID layer.

We also add support for the Logitech Harmony Adapter for PS3, which
emulates the BD Remote.

Signed-off-by: David Dillow <dave@thedillows.org>
---
 drivers/hid/Kconfig         |   11 ++-
 drivers/hid/Makefile        |    1 +
 drivers/hid/hid-core.c      |    2 +
 drivers/hid/hid-ids.h       |    2 +
 drivers/hid/hid-ps3remote.c |  199 +++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 214 insertions(+), 1 deletions(-)

Here's an updated version of the HID driver for the PS3 BD Remote. I've
gone ahead and signed off on it as it works for my Harmony adapter, but
it needs testing with a real BD remote before going upstream. Antonio
also asked for some text about the pairing process -- I've left it out
since I don't know what it should be.





--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Antonio Ospite Sept. 19, 2012, 4:48 p.m. UTC | #1
On Mon, 17 Sep 2012 21:33:58 -0400
David Dillow <dave@thedillows.org> wrote:

> The Sony PS3 Blue-ray Disc Remote Control used to be supported by the
> BlueZ project's user space, but the code that handled it was recently
> removed as its functionality conflicted with a real HSP implementation
> and the mapping was thought to be better handled in the kernel. This is
> a port of the mapping logic from the fakehid driver by Marcel Holtmann
> to the in-kernel HID layer.
> 
> We also add support for the Logitech Harmony Adapter for PS3, which
> emulates the BD Remote.
> 
> Signed-off-by: David Dillow <dave@thedillows.org>
> ---
>  drivers/hid/Kconfig         |   11 ++-
>  drivers/hid/Makefile        |    1 +
>  drivers/hid/hid-core.c      |    2 +
>  drivers/hid/hid-ids.h       |    2 +
>  drivers/hid/hid-ps3remote.c |  199 +++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 214 insertions(+), 1 deletions(-)
> 
> Here's an updated version of the HID driver for the PS3 BD Remote. I've
> gone ahead and signed off on it as it works for my Harmony adapter, but
> it needs testing with a real BD remote before going upstream. Antonio
> also asked for some text about the pairing process -- I've left it out
> since I don't know what it should be.
>

Tested with the original PS3 BD remote and this version works fine too,
thanks.

Tested-by: Antonio Ospite <ospite@studenti.unina.it>

About the multiple keys press handling I see that my keyboard does this:

I press 'a' and keep it pressed:
Event: time 1348069423.217974, type 1 (EV_KEY), code 30 (KEY_A), value 1
Event: time 1348069423.249871, type 1 (EV_KEY), code 30 (KEY_A), value 2
Event: time 1348069423.282410, type 1 (EV_KEY), code 30 (KEY_A), value 2
aaa
...

I press 's' and release it:
Event: time 1348069423.290792, type 1 (EV_KEY), code 31 (KEY_S), value 1
Event: time 1348069423.374516, type 1 (EV_KEY), code 31 (KEY_S), value 0
s

I release 'a':
Event: time 1348069427.351315, type 1 (EV_KEY), code 30 (KEY_A), value 0


While on the remote I see:

I press '1' and keep it pressed:
Event: time 1348069656.505528, type 1 (EV_KEY), code 2 (KEY_1), value 1
1111111111...

I press '2' and release it ('1' is sent):
Event: time 1348069666.025543, type 1 (EV_KEY), code 2 (KEY_1), value 0
Event: time 1348069668.395531, type 1 (EV_KEY), code 2 (KEY_1), value 1
1111111111...

I release '1':
Event: time 1348069671.625541, type 1 (EV_KEY), code 2 (KEY_1), value 0

I don't know at what level this behavior is enforced.

I will test later with the old raw_event callback and the fix to the
descriptor you suggested in the other mail.

David D. what is the behavior of the Harmony adapter?

Few more comments inlined below.

> 
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index fbf4950..7bf3b1a 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -534,6 +534,14 @@ config HID_PRIMAX
>  	Support for Primax devices that are not fully compliant with the
>  	HID standard.
>  
> +config HID_PS3REMOTE
> +	tristate "Sony PS3 BD Remote"

If you are going for a v3, consider using "Sony PS3 BD Remote Control"
here too, not a big deal but that's the name on the user manual.

> +	depends on BT_HIDP
> +	---help---
> +	Support for the Sony PS3 BD Remote 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
> @@ -561,7 +569,8 @@ config HID_SONY
>  	tristate "Sony PS3 controller"
>  	depends on USB_HID
>  	---help---
> -	Support for Sony PS3 controller.
> +	Support for Sony PS3 6-axis controllers. Support for the Sony PS3
> +	BD Remote is provided by HID_PS3REMOTE.
>  
>  config HID_SPEEDLINK
>  	tristate "Speedlink VAD Cezanne mouse support"
> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> index f975485..333ed6c 100644
> --- a/drivers/hid/Makefile
> +++ b/drivers/hid/Makefile
> @@ -70,6 +70,7 @@ obj-$(CONFIG_HID_PANTHERLORD)	+= hid-pl.o
>  obj-$(CONFIG_HID_PETALYNX)	+= hid-petalynx.o
>  obj-$(CONFIG_HID_PICOLCD)	+= hid-picolcd.o
>  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-pyra.o \
> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
> index 60ea284..a9f0439 100644
> --- a/drivers/hid/hid-core.c
> +++ b/drivers/hid/hid-core.c
> @@ -1591,6 +1591,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) },
> +	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) },

Jiri, what is supposed to be the ordering of entries here? Alphabetical
on the product field, or by product numerical value like in hid-ids.h?

>  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) },
> @@ -1641,6 +1642,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) },
>  	{ HID_BLUETOOTH_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_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index 1dcb76f..0f5c2bb 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -492,6 +492,7 @@
>  #define USB_DEVICE_ID_LG_MULTITOUCH	0x0064
>  
>  #define USB_VENDOR_ID_LOGITECH		0x046d
> +#define USB_DEVICE_ID_LOGITECH_HARMONY_PS3 0x0306
>  #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
>  #define USB_DEVICE_ID_LOGITECH_RECEIVER	0xc101
>  #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST  0xc110
> @@ -684,6 +685,7 @@
>  #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_DEVICE_ID_SONY_PS3_BDREMOTE		0x0306
>  #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER	0x042f
>  
>  #define USB_VENDOR_ID_SOUNDGRAPH	0x15c2
> diff --git a/drivers/hid/hid-ps3remote.c b/drivers/hid/hid-ps3remote.c
> new file mode 100644
> index 0000000..e8caef0
> --- /dev/null
> +++ b/drivers/hid/hid-ps3remote.c
> @@ -0,0 +1,199 @@
> +/*
> + * HID driver for Sony PS3 BD Remote
> + *
> + * Copyright (c) 2012 David Dillow <dave@thedillows.org>
> + * 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.
> + */
> +

For the note about the association procedure I had in mind something
like this:

/* NOTE: in order to associate the Sony PS3 BD Remote with a Bluetooth host
 * the key combination Start+Enter has to be kept pressed for about 7 seconds,
 * with the host BT Controller in discovering mode.
 *
 * Also the pin request should be ignored by the BT Controller (NULL pin).
 */

Could someone more into BT please check the terminology here? Thanks.

>
> +#include <linux/device.h>
> +#include <linux/hid.h>
> +#include <linux/module.h>
> +
> +#include "hid-ids.h"
> +
> +/*
> + * The first byte of the raw event report seems to contain a fixed number,
> + * possibly a controller number. The next three bytes contain a bitmask,
> + * in big-endian order, of a portion of the buttons available.
> + *
> + * Button	Bit	Scan	Mapped Key
> + * PS		0	0x43	KEY_HOMEPAGE
> + * Unknown	1-2
> + * Enter	3	0x0b	KEY_ENTER
> + * Unknown	4-7
> + * L2		8	0x58	BTN_TL2
> + * R2		9	0x59	BTN_TR2
> + * L1		10	0x5a	BTN_TL
> + * R1		11	0x5b	BTN_TR
> + * Triangle	12	0x5c	KEY_OPTION
> + * Circle	13	0x5d	KEY_BACK
> + * Cross	14	0x5e	BTN_0
> + * Square	15	0x5f	KEY_SCREEN
> + * Select	16	0x50	KEY_SELECT
> + * L3		17	0x51	BTN_THUMBL
> + * R3		18	0x52	BTN_THUMBR
> + * Start	19	0x53	BTN_START
> + * Up		20	0x54	KEY_UP
> + * Right	21	0x55	KEY_RIGHT
> + * Down		22	0x56	KEY_DOWN
> + * Left		23	0x57	KEY_LEFT
> + *
> + * The keymap is generally ordered by the physical location of the buttons,
> + * as this makes it easier to verify a correct mapping during testing.
> + */
> +static const unsigned int ps3remote_keymap[] = {
> +	[0x16] = KEY_EJECTCD,
> +	[0x64] = KEY_AUDIO,
> +	[0x65] = KEY_ANGLE,
> +	[0x63] = KEY_SUBTITLE,
> +	[0x0f] = KEY_CLEAR,
> +	[0x28] = KEY_TIME,
> +	[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,
> +	[0x81] = KEY_RED,
> +	[0x82] = KEY_GREEN,
> +	[0x80] = KEY_BLUE,
> +	[0x83] = KEY_YELLOW,
> +	[0x70] = KEY_INFO,		/* display */
> +	[0x1a] = KEY_MENU,		/* top menu */
> +	[0x40] = KEY_CONTEXT_MENU,	/* pop up/menu */
> +	[0x0e] = KEY_ESC,		/* return */
> +	[0x5c] = KEY_OPTION,		/* options/triangle */
> +	[0x5d] = KEY_BACK,		/* back/circle */
> +	[0x5f] = KEY_SCREEN,		/* view/square */
> +	[0x5e] = BTN_0,			/* cross */
> +	[0x54] = KEY_UP,
> +	[0x56] = KEY_DOWN,
> +	[0x57] = KEY_LEFT,
> +	[0x55] = KEY_RIGHT,
> +	[0x0b] = KEY_ENTER,
> +	[0x5a] = BTN_TL,		/* L1 */
> +	[0x58] = BTN_TL2,		/* L2 */
> +	[0x51] = BTN_THUMBL,		/* L3 */
> +	[0x5b] = BTN_TR,		/* R1 */
> +	[0x59] = BTN_TR2,		/* R2 */
> +	[0x52] = BTN_THUMBR,		/* R3 */
> +	[0x43] = KEY_HOMEPAGE,		/* PS button */
> +	[0x50] = KEY_SELECT,
> +	[0x53] = BTN_START,
> +	[0x33] = KEY_REWIND,		/* scan back */
> +	[0x32] = KEY_PLAY,
> +	[0x34] = KEY_FORWARD,		/* scan forward */
> +	[0x30] = KEY_PREVIOUS,
> +	[0x38] = KEY_STOP,
> +	[0x31] = KEY_NEXT,
> +	[0x60] = KEY_FRAMEBACK,		/* slow/step back */
> +	[0x39] = KEY_PAUSE,
> +	[0x61] = KEY_FRAMEFORWARD,	/* slow/step forward */
> +};
> +
> +static __u8 ps3remote_rdesc[] = {
> +	0x05, 0x01,	/* USAGE PAGE (Generic Desktop) */
> +	0x09, 0x05,	/* USAGE (Game Pad) */
> +	0xa1, 0x01,	/* COLLECTION (Application) */
> +
> +	/* First four bytes contain a bitmask for some of the buttons, and
> +	 * possibly a controller number. We don't need this information,
> +	 * as the keys will be reported in the next field as well.
> +	 */
> +	0x75, 0x20,	/*   REPORT SIZE (32) */
> +	0x95, 0x01,	/*   REPORT COUNT (1) */
> +	0x81, 0x01,	/*   INPUT (Constant) */
> +
> +	/* All key presses are reported in this field  */
> +	0x05, 0x09,	/*   USAGE PAGE (Button) */
> +	0x19, 0x00,	/*   USAGE MINIMUM (0) */
> +	0x29, 0xfe,	/*   USAGE MAXIMUM (254) */
> +	0x15, 0x00,	/*   LOGICAL MINIMUM (0) */
> +	0x25, 0xfe,	/*   LOGICAL MAXIMUM (254) */
> +	0x75, 0x08,	/*   REPORT SIZE (8) */
> +	0x95, 0x06,	/*   REPORT COUNT (6) */
> +	0x81, 0x00,	/*   INPUT (Array, Absolute) */
> +
> +	/* Ignore press indication */
> +	0x75, 0x08,	/*   REPORT SIZE (8) */
> +	0x95, 0x01,	/*   REPORT COUNT (1) */
> +	0x81, 0x01,	/*   INPUT (Constant) */
> +
> +	/* Report the battery level */
> +	0x05, 0x06,	/*   USAGE PAGE (Generic Device) */
> +	0x09, 0x20,	/*   USAGE (Battery Strength) */
> +	0x15, 0x00,	/*   LOGICAL MINIMUM (0) */
> +	0x25, 0x05,	/*   LOGICAL MAXIMUM (5) */
> +	0x75, 0x08,	/*   REPORT SIZE (8) */
> +	0x95, 0x01,	/*   REPORT COUNT (1) */
> +	0x81, 0x02,	/*   INPUT (Variable, Absolute) */
> +	0xc0,		/* END_COLLECTION */
> +};
> +
> +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 ||
> +	    key >= ARRAY_SIZE(ps3remote_keymap))
> +		return -1;
> +
> +	key = ps3remote_keymap[key];
> +	if (!key)
> +		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 */
> +	{ 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,
> +};
> +
> +static int __init ps3remote_init(void)
> +{
> +	return hid_register_driver(&ps3remote_driver);
> +}
> +
> +static void __exit ps3remote_exit(void)
> +{
> +	hid_unregister_driver(&ps3remote_driver);
> +}
> +
> +module_init(ps3remote_init);
> +module_exit(ps3remote_exit);
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("David Dillow <dave@thedillows.org>");
> 

Thanks,
   Antonio
David Dillow Sept. 19, 2012, 4:59 p.m. UTC | #2
On Wed, 2012-09-19 at 18:48 +0200, Antonio Ospite wrote:
> On Mon, 17 Sep 2012 21:33:58 -0400
> David Dillow <dave@thedillows.org> wrote:

> While on the remote I see:
> 
> I press '1' and keep it pressed:
> Event: time 1348069656.505528, type 1 (EV_KEY), code 2 (KEY_1), value 1
> 1111111111...
> 
> I press '2' and release it ('1' is sent):
> Event: time 1348069666.025543, type 1 (EV_KEY), code 2 (KEY_1), value 0
> Event: time 1348069668.395531, type 1 (EV_KEY), code 2 (KEY_1), value 1
> 1111111111...
> 
> I release '1':
> Event: time 1348069671.625541, type 1 (EV_KEY), code 2 (KEY_1), value 0
> 
> I don't know at what level this behavior is enforced.
> 
> I will test later with the old raw_event callback and the fix to the
> descriptor you suggested in the other mail.

Please capture the raw reports
from /sys/kernel/debug/hid/0005:*:0306:*/events when pressing multiple
keys -- and tell me which ones they were. You may need to mount debugfs
to get to this path.

It looks like this simple approach isn't going to work when you press
multiple keys, so I'll need more information to see if I can do
something else -- my Harmony can only do one key press at a time, as it
is converting IR to an emulated BD remote.

> > +config HID_PS3REMOTE
> > +	tristate "Sony PS3 BD Remote"
> 
> If you are going for a v3, consider using "Sony PS3 BD Remote Control"
> here too, not a big deal but that's the name on the user manual.

Will do, thanks.

> For the note about the association procedure I had in mind something
> like this:
> 
> /* NOTE: in order to associate the Sony PS3 BD Remote with a Bluetooth host
>  * the key combination Start+Enter has to be kept pressed for about 7 seconds,
>  * with the host BT Controller in discovering mode.
>  *
>  * Also the pin request should be ignored by the BT Controller (NULL pin).
>  */
> 
> Could someone more into BT please check the terminology here? Thanks.

Will add something along these lines, though I think you mean there is
no authentication step rather than a NULL pin, which implies we still
need to do auth. Or maybe that's just how the Harmony needed it...

Thanks,
Dave
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Bastien Nocera Sept. 19, 2012, 5:05 p.m. UTC | #3
Em Wed, 2012-09-19 às 18:48 +0200, Antonio Ospite escreveu:
> For the note about the association procedure I had in mind something
> like this:
> 
> /* NOTE: in order to associate the Sony PS3 BD Remote with a Bluetooth
> host
>  * the key combination Start+Enter has to be kept pressed for about 7
> seconds,
>  * with the host BT Controller in discovering mode.
>  *
>  * Also the pin request should be ignored by the BT Controller (NULL
> pin).
>  */
> 
> Could someone more into BT please check the terminology here? Thanks.

Pairing means that the communication between the 2 Bluetooth devices
will be encrypted. In this case (and as is usually the case for mice),
the communication isn't encrypted, they will just agree to communicate
and the computer will just agree not to ask whether the connection is
allowed at every attempt (favourite/trusted settings depending on the OS
or terminology). There will be no PIN request.

Cheers

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Antonio Ospite Sept. 21, 2012, 8:06 p.m. UTC | #4
On Wed, 19 Sep 2012 12:59:46 -0400
David Dillow <dave@thedillows.org> wrote:

> On Wed, 2012-09-19 at 18:48 +0200, Antonio Ospite wrote:
> > On Mon, 17 Sep 2012 21:33:58 -0400
> > David Dillow <dave@thedillows.org> wrote:
> 
> > While on the remote I see:
> > 
> > I press '1' and keep it pressed:
> > Event: time 1348069656.505528, type 1 (EV_KEY), code 2 (KEY_1), value 1
> > 1111111111...
> > 
> > I press '2' and release it ('1' is sent):
> > Event: time 1348069666.025543, type 1 (EV_KEY), code 2 (KEY_1), value 0
> > Event: time 1348069668.395531, type 1 (EV_KEY), code 2 (KEY_1), value 1
> > 1111111111...
> > 
> > I release '1':
> > Event: time 1348069671.625541, type 1 (EV_KEY), code 2 (KEY_1), value 0
> > 
> > I don't know at what level this behavior is enforced.
> > 
> > I will test later with the old raw_event callback and the fix to the
> > descriptor you suggested in the other mail.
> 
> Please capture the raw reports
> from /sys/kernel/debug/hid/0005:*:0306:*/events when pressing multiple
> keys -- and tell me which ones they were. You may need to mount debugfs
> to get to this path.
>

I used hidraw which is equivalent in this case.

$ sudo cat /dev/hidraw1 | hexdump -e '12/1 "%02X " "\n"'

I press and release 'Play'
01 00 00 00 32 FF FF FF FF FF 01 05
01 00 00 00 FF FF FF FF FF FF 00 05

I press and release 'Stop'
01 00 00 00 32 FF FF FF FF FF 01 05
01 00 00 00 FF FF FF FF FF FF 00 05

I press 'Play', keep it pressed and press 'Stop'
01 00 00 00 32 FF FF FF FF FF 01 05
01 00 00 00 FF FF FF FF FF FF 01 05
I release 'Stop' and then release 'Play'
01 00 00 00 32 FF FF FF FF FF 01 05
01 00 00 00 FF FF FF FF FF FF 00 05

So this combination cannot be detected at all, but:

I press and release 'Triangle'
01 00 10 00 5C FF FF FF FF FF 01 05
01 00 00 00 FF FF FF FF FF FF 00 05

I press and release 'Circle'
01 00 20 00 5D FF FF FF FF FF 01 05
01 00 00 00 FF FF FF FF FF FF 00 05

I press 'Triangle', keep it pressed and press 'Circle'
01 00 10 00 5C FF FF FF FF FF 01 05
01 00 30 00 FF FF FF FF FF FF 01 05
I release 'Circle' and then release 'Triangle'
01 00 10 00 5C FF FF FF FF FF 01 05
01 00 00 00 FF FF FF FF FF FF 00 05

So using the third byte (actually second, third and fourth right?) this
combination of multiple key presses can be detected, that happens to be
true for the "joypad buttons" which makes sense.

We can express the decoding of a bitfield in terms of HID descriptor,
right? Maybe copying from the Sixaxis report descriptor as the raw
report data for the first four bytes looks the same as the Sixaxis.
I'll try modifying the descriptor later.

David D. if you want you could send the version with the raw_event
callback first and get that merged and we can improve the descriptor
later, that would be fine to me.

BTW Some three keys combinations also produce a 03 in the one to last
byte: 01 00 00 00 FF FF FF FF FF FF 03 05
combinations like "Play+Stop+Next" do but some other do not and I could
not find a rule about that, so I don't know what the 03 really means.

> It looks like this simple approach isn't going to work when you press
> multiple keys, so I'll need more information to see if I can do
> something else -- my Harmony can only do one key press at a time, as it
> is converting IR to an emulated BD remote.
> 
> > > +config HID_PS3REMOTE
> > > +	tristate "Sony PS3 BD Remote"
> > 
> > If you are going for a v3, consider using "Sony PS3 BD Remote Control"
> > here too, not a big deal but that's the name on the user manual.
> 
> Will do, thanks.
> 
> > For the note about the association procedure I had in mind something
> > like this:
> > 
> > /* NOTE: in order to associate the Sony PS3 BD Remote with a Bluetooth host
> >  * the key combination Start+Enter has to be kept pressed for about 7 seconds,
> >  * with the host BT Controller in discovering mode.
> >  *
> >  * Also the pin request should be ignored by the BT Controller (NULL pin).
> >  */
> > 
> > Could someone more into BT please check the terminology here? Thanks.
> 
> Will add something along these lines, though I think you mean there is
> no authentication step rather than a NULL pin, which implies we still
> need to do auth. Or maybe that's just how the Harmony needed it...
>

From a user point of view there is still some "set up" happening,
the gnome bluetooth-applet tells "Successfully set up new device '%
s'", so maybe we can just call this "set up" in the comment above too, I
mentioned the PIN because Gnome bluetooth does something about that[1],
Bastien in gnome-bt case pin="NULL" means that there will be no
pin request at all by the device, right?

Thanks,
   Antonio

[1]
http://git.gnome.org/browse/gnome-bluetooth/tree/wizard/pin-code-database.xml#n59
Bastien Nocera Sept. 21, 2012, 8:45 p.m. UTC | #5
Em Fri, 2012-09-21 às 22:06 +0200, Antonio Ospite escreveu:
> From a user point of view there is still some "set up" happening,
> the gnome bluetooth-applet tells "Successfully set up new device '%
> s'", so maybe we can just call this "set up" in the comment above too,
> I
> mentioned the PIN because Gnome bluetooth does something about
> that[1],
> Bastien in gnome-bt case pin="NULL" means that there will be no
> pin request at all by the device, right?

Yep. That means we don't try to pair, we just connect to it. No
security, first come first serve.

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index fbf4950..7bf3b1a 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -534,6 +534,14 @@  config HID_PRIMAX
 	Support for Primax devices that are not fully compliant with the
 	HID standard.
 
+config HID_PS3REMOTE
+	tristate "Sony PS3 BD Remote"
+	depends on BT_HIDP
+	---help---
+	Support for the Sony PS3 BD Remote 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
@@ -561,7 +569,8 @@  config HID_SONY
 	tristate "Sony PS3 controller"
 	depends on USB_HID
 	---help---
-	Support for Sony PS3 controller.
+	Support for Sony PS3 6-axis controllers. Support for the Sony PS3
+	BD Remote is provided by HID_PS3REMOTE.
 
 config HID_SPEEDLINK
 	tristate "Speedlink VAD Cezanne mouse support"
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index f975485..333ed6c 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -70,6 +70,7 @@  obj-$(CONFIG_HID_PANTHERLORD)	+= hid-pl.o
 obj-$(CONFIG_HID_PETALYNX)	+= hid-petalynx.o
 obj-$(CONFIG_HID_PICOLCD)	+= hid-picolcd.o
 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-pyra.o \
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 60ea284..a9f0439 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1591,6 +1591,7 @@  static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) },
@@ -1641,6 +1642,7 @@  static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) },
 	{ HID_BLUETOOTH_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_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 1dcb76f..0f5c2bb 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -492,6 +492,7 @@ 
 #define USB_DEVICE_ID_LG_MULTITOUCH	0x0064
 
 #define USB_VENDOR_ID_LOGITECH		0x046d
+#define USB_DEVICE_ID_LOGITECH_HARMONY_PS3 0x0306
 #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
 #define USB_DEVICE_ID_LOGITECH_RECEIVER	0xc101
 #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST  0xc110
@@ -684,6 +685,7 @@ 
 #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_DEVICE_ID_SONY_PS3_BDREMOTE		0x0306
 #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER	0x042f
 
 #define USB_VENDOR_ID_SOUNDGRAPH	0x15c2
diff --git a/drivers/hid/hid-ps3remote.c b/drivers/hid/hid-ps3remote.c
new file mode 100644
index 0000000..e8caef0
--- /dev/null
+++ b/drivers/hid/hid-ps3remote.c
@@ -0,0 +1,199 @@ 
+/*
+ * HID driver for Sony PS3 BD Remote
+ *
+ * Copyright (c) 2012 David Dillow <dave@thedillows.org>
+ * 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.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+/*
+ * The first byte of the raw event report seems to contain a fixed number,
+ * possibly a controller number. The next three bytes contain a bitmask,
+ * in big-endian order, of a portion of the buttons available.
+ *
+ * Button	Bit	Scan	Mapped Key
+ * PS		0	0x43	KEY_HOMEPAGE
+ * Unknown	1-2
+ * Enter	3	0x0b	KEY_ENTER
+ * Unknown	4-7
+ * L2		8	0x58	BTN_TL2
+ * R2		9	0x59	BTN_TR2
+ * L1		10	0x5a	BTN_TL
+ * R1		11	0x5b	BTN_TR
+ * Triangle	12	0x5c	KEY_OPTION
+ * Circle	13	0x5d	KEY_BACK
+ * Cross	14	0x5e	BTN_0
+ * Square	15	0x5f	KEY_SCREEN
+ * Select	16	0x50	KEY_SELECT
+ * L3		17	0x51	BTN_THUMBL
+ * R3		18	0x52	BTN_THUMBR
+ * Start	19	0x53	BTN_START
+ * Up		20	0x54	KEY_UP
+ * Right	21	0x55	KEY_RIGHT
+ * Down		22	0x56	KEY_DOWN
+ * Left		23	0x57	KEY_LEFT
+ *
+ * The keymap is generally ordered by the physical location of the buttons,
+ * as this makes it easier to verify a correct mapping during testing.
+ */
+static const unsigned int ps3remote_keymap[] = {
+	[0x16] = KEY_EJECTCD,
+	[0x64] = KEY_AUDIO,
+	[0x65] = KEY_ANGLE,
+	[0x63] = KEY_SUBTITLE,
+	[0x0f] = KEY_CLEAR,
+	[0x28] = KEY_TIME,
+	[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,
+	[0x81] = KEY_RED,
+	[0x82] = KEY_GREEN,
+	[0x80] = KEY_BLUE,
+	[0x83] = KEY_YELLOW,
+	[0x70] = KEY_INFO,		/* display */
+	[0x1a] = KEY_MENU,		/* top menu */
+	[0x40] = KEY_CONTEXT_MENU,	/* pop up/menu */
+	[0x0e] = KEY_ESC,		/* return */
+	[0x5c] = KEY_OPTION,		/* options/triangle */
+	[0x5d] = KEY_BACK,		/* back/circle */
+	[0x5f] = KEY_SCREEN,		/* view/square */
+	[0x5e] = BTN_0,			/* cross */
+	[0x54] = KEY_UP,
+	[0x56] = KEY_DOWN,
+	[0x57] = KEY_LEFT,
+	[0x55] = KEY_RIGHT,
+	[0x0b] = KEY_ENTER,
+	[0x5a] = BTN_TL,		/* L1 */
+	[0x58] = BTN_TL2,		/* L2 */
+	[0x51] = BTN_THUMBL,		/* L3 */
+	[0x5b] = BTN_TR,		/* R1 */
+	[0x59] = BTN_TR2,		/* R2 */
+	[0x52] = BTN_THUMBR,		/* R3 */
+	[0x43] = KEY_HOMEPAGE,		/* PS button */
+	[0x50] = KEY_SELECT,
+	[0x53] = BTN_START,
+	[0x33] = KEY_REWIND,		/* scan back */
+	[0x32] = KEY_PLAY,
+	[0x34] = KEY_FORWARD,		/* scan forward */
+	[0x30] = KEY_PREVIOUS,
+	[0x38] = KEY_STOP,
+	[0x31] = KEY_NEXT,
+	[0x60] = KEY_FRAMEBACK,		/* slow/step back */
+	[0x39] = KEY_PAUSE,
+	[0x61] = KEY_FRAMEFORWARD,	/* slow/step forward */
+};
+
+static __u8 ps3remote_rdesc[] = {
+	0x05, 0x01,	/* USAGE PAGE (Generic Desktop) */
+	0x09, 0x05,	/* USAGE (Game Pad) */
+	0xa1, 0x01,	/* COLLECTION (Application) */
+
+	/* First four bytes contain a bitmask for some of the buttons, and
+	 * possibly a controller number. We don't need this information,
+	 * as the keys will be reported in the next field as well.
+	 */
+	0x75, 0x20,	/*   REPORT SIZE (32) */
+	0x95, 0x01,	/*   REPORT COUNT (1) */
+	0x81, 0x01,	/*   INPUT (Constant) */
+
+	/* All key presses are reported in this field  */
+	0x05, 0x09,	/*   USAGE PAGE (Button) */
+	0x19, 0x00,	/*   USAGE MINIMUM (0) */
+	0x29, 0xfe,	/*   USAGE MAXIMUM (254) */
+	0x15, 0x00,	/*   LOGICAL MINIMUM (0) */
+	0x25, 0xfe,	/*   LOGICAL MAXIMUM (254) */
+	0x75, 0x08,	/*   REPORT SIZE (8) */
+	0x95, 0x06,	/*   REPORT COUNT (6) */
+	0x81, 0x00,	/*   INPUT (Array, Absolute) */
+
+	/* Ignore press indication */
+	0x75, 0x08,	/*   REPORT SIZE (8) */
+	0x95, 0x01,	/*   REPORT COUNT (1) */
+	0x81, 0x01,	/*   INPUT (Constant) */
+
+	/* Report the battery level */
+	0x05, 0x06,	/*   USAGE PAGE (Generic Device) */
+	0x09, 0x20,	/*   USAGE (Battery Strength) */
+	0x15, 0x00,	/*   LOGICAL MINIMUM (0) */
+	0x25, 0x05,	/*   LOGICAL MAXIMUM (5) */
+	0x75, 0x08,	/*   REPORT SIZE (8) */
+	0x95, 0x01,	/*   REPORT COUNT (1) */
+	0x81, 0x02,	/*   INPUT (Variable, Absolute) */
+	0xc0,		/* END_COLLECTION */
+};
+
+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 ||
+	    key >= ARRAY_SIZE(ps3remote_keymap))
+		return -1;
+
+	key = ps3remote_keymap[key];
+	if (!key)
+		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 */
+	{ 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,
+};
+
+static int __init ps3remote_init(void)
+{
+	return hid_register_driver(&ps3remote_driver);
+}
+
+static void __exit ps3remote_exit(void)
+{
+	hid_unregister_driver(&ps3remote_driver);
+}
+
+module_init(ps3remote_init);
+module_exit(ps3remote_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Dillow <dave@thedillows.org>");