Skip to contentSkip to conversation

sh: maple: add support for Maple controller as a joystick

PATCH In review Adrian McMenamin 7 participants 12 messages Dec 19, 2008 – Dec 26, 2008

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 sh: maple: add support for Maple controller as a joystick

Not sure what happened with earlier submissions, so here is an up-to-date patch for the Dreamcast Maple controlled.

Add support for the SEGA Dreamcast Maple controller as a joystick

---

drivers/input/joystick/Kconfig +13 -0
index be5c14a..ca7ce42 100644
@@ -294,4 +294,17 @@ config JOYSTICK_XPAD_LEDS
 	  This option enables support for the LED which surrounds the Big X on
 	  XBox 360 controller.
 
+config JOYSTICK_MAPLE
+	tristate "Dreamcast control pad"
+	depends on SH_DREAMCAST
+	select MAPLE
+	help
+	  Say Y here if you have a SEGA Dreamcast and want to use your
+	  controller as a joystick.
+
+	  Most Dreamcast users will say Y.
+
+	  To compile this as a module choose M here: the module will be called
+	  maplecontrol.
+
 endif
drivers/input/joystick/Makefile +1 -0
index fdbf8c4..bfd848d 100644
@@ -10,6 +10,7 @@ obj-$(CONFIG_JOYSTICK_AMIGA)		+= amijoy.o
 obj-$(CONFIG_JOYSTICK_ANALOG)		+= analog.o
 obj-$(CONFIG_JOYSTICK_COBRA)		+= cobra.o
 obj-$(CONFIG_JOYSTICK_DB9)		+= db9.o
+obj-$(CONFIG_JOYSTICK_MAPLE)		+= maplecontrol.o
 obj-$(CONFIG_JOYSTICK_GAMECON)		+= gamecon.o
 obj-$(CONFIG_JOYSTICK_GF2K)		+= gf2k.o
 obj-$(CONFIG_JOYSTICK_GRIP)		+= grip.o
drivers/input/joystick/maplecontrol.c new file +193 -0

193 lines not on this page · raw message

#1 lore raw
Quoted 3 lines · Adrian McMenamin

Add support for the SEGA Dreamcast Maple controller as a joystick

[snip]

drivers/input/joystick/maplecontrol.c line 35

Quoted 6 lines
drivers/input/joystick/maplecontrol.c new file +6 -0
+	struct dc_pad *pad = maple_get_drvdata(mapledev);
+	struct input_dev *dev = pad->dev;
+	unsigned char *res = mq->recvbuf;
+
+	buttons = ~cpu_to_le16(*(unsigned short *)(res + 8));
+

I may be wrong but shouldn't this use the I/O accessor functions?

Quoted 7 lines
drivers/input/joystick/maplecontrol.c new file +7 -0
+
+	pad = kzalloc(sizeof(struct dc_pad), GFP_KERNEL);
+	idev = input_allocate_device();
+	if (!pad || !idev){
+		error = ENOMEM;
+		goto fail;
+	}

[snip]

drivers/input/joystick/maplecontrol.c line 155

Quoted 2 lines
drivers/input/joystick/maplecontrol.c new file +2 -0
+fail:
+	input_free_device(pad->dev);

Possible NULL pointer dereference?

#2 lore raw
Quoted 7 lines · Matt Fleming
Quoted 3 lines · Adrian McMenamin

Add support for the SEGA Dreamcast Maple controller as a joystick

[snip]

Quoted 9 lines

drivers/input/joystick/maplecontrol.c line 35

Quoted 6 lines
drivers/input/joystick/maplecontrol.c new file +6 -0
+	struct dc_pad *pad = maple_get_drvdata(mapledev);
+	struct input_dev *dev = pad->dev;
+	unsigned char *res = mq->recvbuf;
+
+	buttons = ~cpu_to_le16(*(unsigned short *)(res + 8));
+

I may be wrong but shouldn't this use the I/O accessor functions?

It's not iomemory, so I don't think so. The maple bus writes to a buffer in the physical RAM.

Quoted 10 lines
Quoted 7 lines
drivers/input/joystick/maplecontrol.c new file +7 -0
+
+	pad = kzalloc(sizeof(struct dc_pad), GFP_KERNEL);
+	idev = input_allocate_device();
+	if (!pad || !idev){
+		error = ENOMEM;
+		goto fail;
+	}

[snip]

Quoted 4 lines

drivers/input/joystick/maplecontrol.c line 155

Quoted 2 lines
drivers/input/joystick/maplecontrol.c new file +2 -0
+fail:
+	input_free_device(pad->dev);

Possible NULL pointer dereference?

No, because input_free_device is:

void input_free_device(struct input_dev *dev)

{
        if (dev)
               input_put_device(dev);
}

EXPORT_SYMBOL(input_free_device);

maintainer
#3 lore raw
Quoted 15 lines · On Saturday 20 December 2008 08:07:27 Adrian McMenamin wrote:
Quoted 5 lines · Matt Fleming
Quoted 1 line · Adrian McMenamin

Add support for the SEGA Dreamcast Maple controller as a joystick

[snip]

Quoted 8 lines

drivers/input/joystick/maplecontrol.c line 35

Quoted 6 lines
drivers/input/joystick/maplecontrol.c new file +6 -0
+	struct dc_pad *pad = maple_get_drvdata(mapledev);
+	struct input_dev *dev = pad->dev;
+	unsigned char *res = mq->recvbuf;
+
+	buttons = ~cpu_to_le16(*(unsigned short *)(res + 8));
+

I may be wrong but shouldn't this use the I/O accessor functions?

Quoted 3 lines

It's not iomemory, so I don't think so. The maple bus writes to a buffer in the physical RAM.

Hmm, but why we are going _from_ cpu order to le16??? I'd expect we wanted to do conversion the other way around. I pulled it out of 'next' for now.

Quoted 15 lines
Quoted 10 lines
Quoted 7 lines
drivers/input/joystick/maplecontrol.c new file +7 -0
+
+	pad = kzalloc(sizeof(struct dc_pad), GFP_KERNEL);
+	idev = input_allocate_device();
+	if (!pad || !idev){
+		error = ENOMEM;
+		goto fail;
+	}

[snip]

Quoted 4 lines

drivers/input/joystick/maplecontrol.c line 155

Quoted 2 lines
drivers/input/joystick/maplecontrol.c new file +2 -0
+fail:
+	input_free_device(pad->dev);

Possible NULL pointer dereference?

Quoted 8 lines

No, because input_free_device is:

void input_free_device(struct input_dev *dev)

{
        if (dev)
               input_put_device(dev);
}

EXPORT_SYMBOL(input_free_device);

But we need to be freeing idev, not pad->dev because pad might be NULL.

Signature · 1 line
Dmitry
#4 lore raw
Quoted 16 lines · Dmitry Torokhov
Quoted 15 lines · On Saturday 20 December 2008 08:07:27 Adrian McMenamin wrote:
Quoted 13 lines · Matt Fleming
Quoted 1 line · Adrian McMenamin

Add support for the SEGA Dreamcast Maple controller as a joystick

[snip]

drivers/input/joystick/maplecontrol.c line 35

Quoted 6 lines
drivers/input/joystick/maplecontrol.c new file +6 -0
+	struct dc_pad *pad = maple_get_drvdata(mapledev);
+	struct input_dev *dev = pad->dev;
+	unsigned char *res = mq->recvbuf;
+
+	buttons = ~cpu_to_le16(*(unsigned short *)(res + 8));
+

I may be wrong but shouldn't this use the I/O accessor functions?

Quoted 8 lines
Quoted 3 lines

It's not iomemory, so I don't think so. The maple bus writes to a buffer in the physical RAM.

Hmm, but why we are going _from_ cpu order to le16??? I'd expect we wanted to do conversion the other way around. I pulled it out of 'next' for now.

The data is transmitted here by the bus in 32 bit little endian blocks but makes sense in le16 bit lumps. Off is 1 and on is 0 - hence the ~

The first 16 bits are the button data the next 16 bits are the (start of) the axis data. Both cpu and bus data (in this case - it can vary) are little endian.

maintainer
#5 lore raw

On Dec 20, 2008, at 12:47 PM, Adrian McMenamin <[email protected]

Quoted 29 lines

wrote:

Quoted 21 lines · Dmitry Torokhov
Quoted 15 lines · On Saturday 20 December 2008 08:07:27 Adrian McMenamin wrote:
Quoted 5 lines · Matt Fleming
Quoted 1 line · Adrian McMenamin

Add support for the SEGA Dreamcast Maple controller as a joystick

[snip]

Quoted 8 lines

drivers/input/joystick/maplecontrol.c line 35

Quoted 6 lines
drivers/input/joystick/maplecontrol.c new file +6 -0
+    struct dc_pad *pad = maple_get_drvdata(mapledev);
+    struct input_dev *dev = pad->dev;
+    unsigned char *res = mq->recvbuf;
+
+    buttons = ~cpu_to_le16(*(unsigned short *)(res + 8));
+

I may be wrong but shouldn't this use the I/O accessor functions?

Quoted 4 lines

It's not iomemory, so I don't think so. The maple bus writes to a buffer
in the physical RAM.

Quoted 5 lines

Hmm, but why we are going _from_ cpu order to le16??? I'd expect we wanted to do conversion the other way around. I pulled it out of 'next'
for now.

Quoted 6 lines

The data is transmitted here by the bus in 32 bit little endian blocks but makes sense in le16 bit lumps. Off is 1 and on is 0 - hence the ~

The first 16 bits are the button data the next 16 bits are the (start of) the axis data. Both cpu and bus data (in this case - it can vary) are little endian.

Right, so I think we need le16_to_cpu here, you want the data in native CPU order to manipulate it.

Signature · 1 line
Dmitry
#6 lore raw
In reply to Adrian McMenamin
Quoted 14 lines · Adrian McMenamin

Not sure what happened with earlier submissions, so here is an up-to-date patch for the Dreamcast Maple controlled.

Add support for the SEGA Dreamcast Maple controller as a joystick

---

drivers/input/joystick/Kconfig +0 -0
index be5c14a..ca7ce42 100644

drivers/input/joystick/Kconfig config JOYSTICK_XPAD_LEDS · line 301

Quoted 8 lines
drivers/input/joystick/Kconfig +5 -0
@@ -294,4 +294,17 @@ config JOYSTICK_XPAD_LEDS
 	  This option enables support for the LED which surrounds the Big X on
 	  XBox 360 controller.
 
+config JOYSTICK_MAPLE
+	tristate "Dreamcast control pad"
+	depends on SH_DREAMCAST
+	select MAPLE
+	help

Please don't do this kind of dependency garbage. The only dependency this device has is on the maple bus, there is nothing inherently dreamcast specific about it.

CONFIG_MAPLE already has the dreamcast dependency in this case, and I would speculate the only reason that you added the dreamcast dependency was to work around the fact that select would complain on plaforms where the MAPLE symbol is not visible.

This is an indicator that select is not the thing you should be using here in the first place. So, just change this to depends on MAPLE and be done with it. As soon as you have to start mixing and matching depends/selects that already have a dependency on each other, you have already lost.

#7 lore raw
In reply to Adrian McMenamin
Quoted 1 line · Adrian McMenamin

Add support for the SEGA Dreamcast Maple controller as a joystick

[snip]

Quoted 8 lines
drivers/input/joystick/maplecontrol.c new file +8 -0
+
+	pad = kzalloc(sizeof(struct dc_pad), GFP_KERNEL);
+	idev = input_allocate_device();
+	if (!pad || !idev){
+		error = ENOMEM;
+		goto fail;
+	}
+

[snip]

Quoted 6 lines
drivers/input/joystick/maplecontrol.c new file +6 -0
+
+	error = input_register_device(idev);
+	if (error)
+		goto fail;
+
+	mdev->driver = mdrv;

drivers/input/joystick/maplecontrol.c line 159

Quoted 10 lines
drivers/input/joystick/maplecontrol.c new file +10 -0
+	maple_set_drvdata(mdev, pad);
+
+	return error;
+
+fail:
+	input_free_device(pad->dev);
+	kfree(pad);
+	maple_set_drvdata(mdev, NULL);
+	return -error;
+}

This will incorrectly negate the already negative error code from input_register_device.

Rabin

#8 lore raw
In reply to Adrian McMenamin
Quoted 8 lines · On Fri, 19 Dec 2008 23:15:42 +0000 Adrian McMenamin…

Not sure what happened with earlier submissions, so here is an up-to-date patch for the Dreamcast Maple controlled.

Add support for the SEGA Dreamcast Maple controller as a joystick

...

drivers/input/joystick/maplecontrol.c line 34

Quoted 9 lines
drivers/input/joystick/maplecontrol.c new file +9 -0
+static void dc_pad_callback(struct mapleq *mq)
+{
+	unsigned short buttons;
+	struct maple_device *mapledev = mq->dev;
+	struct dc_pad *pad = maple_get_drvdata(mapledev);
+	struct input_dev *dev = pad->dev;
+	unsigned char *res = mq->recvbuf;
+
+	buttons = ~cpu_to_le16(*(unsigned short *)(res + 8));

hm, could that be simplified?

Quoted 58 lines
drivers/input/joystick/maplecontrol.c new file +58 -0
+	input_report_abs(dev, ABS_HAT0Y,
+			 (buttons & 0x0010 ? -1:0) + (buttons & 0x0020 ? 1:0));
+	input_report_abs(dev, ABS_HAT0X,
+			 (buttons & 0x0040 ? -1:0) + (buttons & 0x0080 ? 1:0));
+	input_report_abs(dev, ABS_HAT1Y,
+			 (buttons & 0x1000 ? -1:0) + (buttons & 0x2000 ? 1:0));
+	input_report_abs(dev, ABS_HAT1X,
+			 (buttons & 0x4000 ? -1:0) + (buttons & 0x8000 ? 1:0));
+
+	input_report_key(dev, BTN_C,      buttons & 0x0001);
+	input_report_key(dev, BTN_B,      buttons & 0x0002);
+	input_report_key(dev, BTN_A,      buttons & 0x0004);
+	input_report_key(dev, BTN_START,  buttons & 0x0008);
+	input_report_key(dev, BTN_Z,      buttons & 0x0100);
+	input_report_key(dev, BTN_Y,      buttons & 0x0200);
+	input_report_key(dev, BTN_X,      buttons & 0x0400);
+	input_report_key(dev, BTN_SELECT, buttons & 0x0800);
+
+	input_report_abs(dev, ABS_GAS,   res[10]);
+	input_report_abs(dev, ABS_BRAKE, res[11]);
+	input_report_abs(dev, ABS_X,     res[12]);
+	input_report_abs(dev, ABS_Y,     res[13]);
+	input_report_abs(dev, ABS_RX,    res[14]);
+	input_report_abs(dev, ABS_RY,    res[15]);
+}
+
+static int dc_pad_open(struct input_dev *dev)
+{
+	struct dc_pad *pad;
+
+	pad = dev->dev.platform_data;
+	maple_getcond_callback(pad->mdev, dc_pad_callback, HZ/20,
+		MAPLE_FUNC_CONTROLLER);
+	return 0;
+}
+
+static void dc_pad_close(struct input_dev *dev)
+{
+	struct dc_pad *pad;
+	
+	pad = dev->dev.platform_data;
+	maple_getcond_callback(pad->mdev, dc_pad_callback, 0,
+		MAPLE_FUNC_CONTROLLER);
+}
+
+/* allow the controller to be used */
+static int probe_maple_controller(struct device *dev)
+{
+	struct maple_device *mdev = to_maple_dev(dev);
+	struct maple_driver *mdrv = to_maple_driver(dev->driver);
+	int i, error;
+	struct dc_pad *pad;
+	struct input_dev *idev;
+	unsigned long data = be32_to_cpu(mdev->devinfo.function_data[0]);
+
+	const short btn_bit[32] = {
+		BTN_C, BTN_B, BTN_A, BTN_START, -1, -1, -1, -1,
+		BTN_Z, BTN_Y, BTN_X, BTN_SELECT, -1, -1, -1, -1,

drivers/input/joystick/maplecontrol.c line 103

Quoted 10 lines
drivers/input/joystick/maplecontrol.c new file +10 -0
+		-1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1,
+	};
+
+	const short abs_bit[32] = {
+		-1, -1, -1, -1, ABS_HAT0Y, ABS_HAT0Y, ABS_HAT0X, ABS_HAT0X,
+		-1, -1, -1, -1, ABS_HAT1Y, ABS_HAT1Y, ABS_HAT1X, ABS_HAT1X,
+		ABS_GAS, ABS_BRAKE, ABS_X, ABS_Y, ABS_RX, ABS_RY, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1,
+	};

These could be made static.

There's a risk that the compiler will go and assemble these arrays on the stack each time this function is called. gcc (some versions, at least) will actually internally turn these into static arrays (assembled at compile time) but it's best to do this explicitly.

drivers/input/joystick/maplecontrol.c line 158

Quoted 8 lines
drivers/input/joystick/maplecontrol.c new file +5 -0
+	pad = kzalloc(sizeof(struct dc_pad), GFP_KERNEL);
+	idev = input_allocate_device();
+	if (!pad || !idev){
+		error = ENOMEM;
 
...
 
+	return -error;

Please don't do this. People occasionally grep the tree for instances of 'EFOO' which are missing the "-" sign, which is a useful service. The above trick just makes things harder for them.

Quoted 3 lines

...

#9 lore raw
Quoted 11 lines · Andrew Morton
Quoted 8 lines · On Fri, 19 Dec 2008 23:15:42 +0000 Adrian McMenamin…

Not sure what happened with earlier submissions, so here is an up-to-date patch for the Dreamcast Maple controlled.

Add support for the SEGA Dreamcast Maple controller as a joystick

...

Quoted 11 lines

drivers/input/joystick/maplecontrol.c line 34

Quoted 9 lines
drivers/input/joystick/maplecontrol.c new file +9 -0
+static void dc_pad_callback(struct mapleq *mq)
+{
+	unsigned short buttons;
+	struct maple_device *mapledev = mq->dev;
+	struct dc_pad *pad = maple_get_drvdata(mapledev);
+	struct input_dev *dev = pad->dev;
+	unsigned char *res = mq->recvbuf;
+
+	buttons = ~cpu_to_le16(*(unsigned short *)(res + 8));

hm, could that be simplified?

And as a bonus fix the obvious sparse warning:

	buttons = ~le16_to_cpup((__le16 *)(res + 8));

Cheers,

Harvey

maintainer
#10 lore raw
Quoted 24 lines · Harvey Harrison
Quoted 11 lines · Andrew Morton
Quoted 8 lines · On Fri, 19 Dec 2008 23:15:42 +0000 Adrian McMenamin…

Not sure what happened with earlier submissions, so here is an up-to-date patch for the Dreamcast Maple controlled.

Add support for the SEGA Dreamcast Maple controller as a joystick

...

Quoted 11 lines

Review

Quoted 9 lines
(quoted diff) +9 -0
+static void dc_pad_callback(struct mapleq *mq)
+{
+	unsigned short buttons;
+	struct maple_device *mapledev = mq->dev;
+	struct dc_pad *pad = maple_get_drvdata(mapledev);
+	struct input_dev *dev = pad->dev;
+	unsigned char *res = mq->recvbuf;
+
+	buttons = ~cpu_to_le16(*(unsigned short *)(res + 8));

hm, could that be simplified?

Quoted 4 lines

And as a bonus fix the obvious sparse warning:

	buttons = ~le16_to_cpup((__le16 *)(res + 8));

Below is what I woudl like to apply unless you see more issues with the patch. Andrew, if you could test it on your hardware to make sure it still works that woudl be great.

Thanks!

Signature · 16 lines
Dmitry

Input: add support for Maple controller as a joystick

From: Adrian McMenamin <[email protected]>

Add support for the SEGA Dreamcast Maple controller as a joystick

Signed-off-by: Adrian McMenamin <[email protected]>
Signed-off-by: Dmitry Torokhov <[email protected]>
---
 drivers/input/joystick/Kconfig        |   12 ++
 drivers/input/joystick/Makefile       |    1 
 drivers/input/joystick/maplecontrol.c |  193 +++++++++++++++++++++++++++++++++
 3 files changed, 206 insertions(+), 0 deletions(-)
 create mode 100644 drivers/input/joystick/maplecontrol.c
drivers/input/joystick/Kconfig +12 -0
index 268dd3f..b114195 100644
@@ -306,4 +306,16 @@ config JOYSTICK_WALKERA0701
 	  To compile this driver as a module, choose M here: the
 	  module will be called walkera0701.
 
+config JOYSTICK_MAPLE
+	tristate "Dreamcast control pad"
+	depends on MAPLE
+	help
+	  Say Y here if you have a SEGA Dreamcast and want to use your
+	  controller as a joystick.
+
+	  Most Dreamcast users will say Y.
+
+	  To compile this as a module choose M here: the module will be called
+	  maplecontrol.
+
 endif
drivers/input/joystick/Makefile +1 -0
index 7230362..f397ec0 100644
@@ -10,6 +10,7 @@ obj-$(CONFIG_JOYSTICK_AMIGA)		+= amijoy.o
 obj-$(CONFIG_JOYSTICK_ANALOG)		+= analog.o
 obj-$(CONFIG_JOYSTICK_COBRA)		+= cobra.o
 obj-$(CONFIG_JOYSTICK_DB9)		+= db9.o
+obj-$(CONFIG_JOYSTICK_MAPLE)		+= maplecontrol.o
 obj-$(CONFIG_JOYSTICK_GAMECON)		+= gamecon.o
 obj-$(CONFIG_JOYSTICK_GF2K)		+= gf2k.o
 obj-$(CONFIG_JOYSTICK_GRIP)		+= grip.o
drivers/input/joystick/maplecontrol.c new file +193 -0

193 lines not on this page · raw message

#11 lore raw
Quoted 27 lines · Dmitry Torokhov
Quoted 26 lines · Harvey Harrison
Quoted 11 lines · Andrew Morton
Quoted 8 lines · On Fri, 19 Dec 2008 23:15:42 +0000 Adrian McMenamin…

Not sure what happened with earlier submissions, so here is an up-to-date patch for the Dreamcast Maple controlled.

Add support for the SEGA Dreamcast Maple controller as a joystick

...

Quoted 11 lines

drivers/input/joystick/maplecontrol.c

Quoted 9 lines
drivers/input/joystick/maplecontrol.c new file +9 -0
+static void dc_pad_callback(struct mapleq *mq)
+{
+	unsigned short buttons;
+	struct maple_device *mapledev = mq->dev;
+	struct dc_pad *pad = maple_get_drvdata(mapledev);
+	struct input_dev *dev = pad->dev;
+	unsigned char *res = mq->recvbuf;
+
+	buttons = ~cpu_to_le16(*(unsigned short *)(res + 8));

hm, could that be simplified?

And as a bonus fix the obvious sparse warning:

Quoted 9 lines
Quoted 2 lines
	buttons = ~le16_to_cpup((__le16 *)(res + 8));

Below is what I woudl like to apply unless you see more issues with the patch. Andrew, if you could test it on your hardware to make sure it still works that woudl be great.

Thanks!

Just to say I've tested this with jstest now and it seems to be in good working order. There is a calibration issue on one axis, but I think that's my hardware :-)