* [PATCH] sh: maple: add support for Maple controller as a joystick
@ 2008-12-19 23:15 Adrian McMenamin
2008-12-20 15:16 ` [PATCH] sh: maple: add support for Maple controller as a Matt Fleming
` (3 more replies)
0 siblings, 4 replies; 12+ messages in thread
From: Adrian McMenamin @ 2008-12-19 23:15 UTC (permalink / raw)
To: LKML, Dmitry Torokhov, linux-sh; +Cc: Andrew Morton, Paul Mundt
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
Signed-off-by: Adrian McMenamin <adrian@mcmen.demon.co.uk>
---
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
index be5c14a..ca7ce42 100644
--- a/drivers/input/joystick/Kconfig
+++ b/drivers/input/joystick/Kconfig
@@ -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
diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile
index fdbf8c4..bfd848d 100644
--- a/drivers/input/joystick/Makefile
+++ b/drivers/input/joystick/Makefile
@@ -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
diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c
new file mode 100644
index 0000000..e4308d8
--- /dev/null
+++ b/drivers/input/joystick/maplecontrol.c
@@ -0,0 +1,194 @@
+/*
+ * SEGA Dreamcast controller driver
+ * Based on drivers/usb/iforce.c
+ *
+ * Copyright Yaegashi Takeshi, 2001
+ * Adrian McMenamin, 2008
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/maple.h>
+
+MODULE_AUTHOR("Adrian McMenamin <adrian@mcmen.demon.co.uk>");
+MODULE_DESCRIPTION("SEGA Dreamcast controller driver");
+MODULE_LICENSE("GPL");
+
+struct dc_pad {
+ struct input_dev *dev;
+ struct maple_device *mdev;
+};
+
+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));
+
+ 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,
+ -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,
+ };
+
+ pad = kzalloc(sizeof(struct dc_pad), GFP_KERNEL);
+ idev = input_allocate_device();
+ if (!pad || !idev){
+ error = ENOMEM;
+ goto fail;
+ }
+
+ pad->dev = idev;
+ pad->mdev = mdev;
+
+ idev->open = dc_pad_open;
+ idev->close = dc_pad_close;
+
+ for (i = 0; i < 32; i++)
+ if (data & (1<<i) && btn_bit[i] >= 0)
+ idev->keybit[BIT_WORD(BTN_JOYSTICK)] |= BIT_MASK(btn_bit[i]);
+
+ if (idev->keybit[BTN_JOYSTICK/32])
+ idev->evbit[0] |= BIT_MASK(EV_KEY);
+
+ for (i = 0; i < 32; i++)
+ if (data & (1<<i) && abs_bit[i] >= 0)
+ idev->absbit[0] |= BIT_MASK(abs_bit[i]);
+
+ if (idev->absbit[0])
+ idev->evbit[0] |= BIT_MASK(EV_ABS);
+
+ for (i = ABS_X; i <= ABS_BRAKE; i++)
+ input_set_abs_params(idev, i, 0, 255, 0, 0);
+
+ for (i = ABS_HAT0X; i <= ABS_HAT3Y; i++)
+ input_set_abs_params(idev, i, 1, -1, 0, 0);
+
+ idev->dev.platform_data = pad;
+ idev->event = NULL;
+ idev->dev.parent = &mdev->dev;
+ idev->name = mdev->product_name;
+ idev->id.bustype = BUS_HOST;
+ input_set_drvdata(idev, pad);
+
+ error = input_register_device(idev);
+ if (error)
+ goto fail;
+
+ mdev->driver = mdrv;
+ maple_set_drvdata(mdev, pad);
+
+ return error;
+
+fail:
+ input_free_device(pad->dev);
+ kfree(pad);
+ maple_set_drvdata(mdev, NULL);
+ return -error;
+}
+
+static int remove_maple_controller(struct device *dev)
+{
+ struct maple_device *mdev = to_maple_dev(dev);
+ struct dc_pad *pad = maple_get_drvdata(mdev);
+
+ mdev->callback = NULL;
+ input_unregister_device(pad->dev);
+ maple_set_drvdata(mdev, NULL);
+ kfree(pad);
+ return 0;
+}
+
+static struct maple_driver dc_pad_driver = {
+ .function = MAPLE_FUNC_CONTROLLER,
+ .drv = {
+ .name = "Dreamcast_controller",
+ .probe = probe_maple_controller,
+ .remove = remove_maple_controller,
+ },
+};
+
+static int __init dc_pad_init(void)
+{
+ return maple_driver_register(&dc_pad_driver);
+}
+
+static void __exit dc_pad_exit(void)
+{
+ maple_driver_unregister(&dc_pad_driver);
+}
+
+module_init(dc_pad_init);
+module_exit(dc_pad_exit);
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH] sh: maple: add support for Maple controller as a 2008-12-19 23:15 [PATCH] sh: maple: add support for Maple controller as a joystick Adrian McMenamin @ 2008-12-20 15:16 ` Matt Fleming 2008-12-20 16:07 ` Adrian McMenamin 2008-12-21 6:47 ` Paul Mundt ` (2 subsequent siblings) 3 siblings, 1 reply; 12+ messages in thread From: Matt Fleming @ 2008-12-20 15:16 UTC (permalink / raw) To: Adrian McMenamin Cc: LKML, Dmitry Torokhov, linux-sh, Andrew Morton, Paul Mundt On Fri, Dec 19, 2008 at 11:15:42PM +0000, Adrian McMenamin wrote: > > Add support for the SEGA Dreamcast Maple controller as a joystick > [snip] > + 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? > + > + pad = kzalloc(sizeof(struct dc_pad), GFP_KERNEL); > + idev = input_allocate_device(); > + if (!pad || !idev){ > + error = ENOMEM; > + goto fail; > + } [snip] > +fail: > + input_free_device(pad->dev); Possible NULL pointer dereference? ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] sh: maple: add support for Maple controller as a 2008-12-20 15:16 ` [PATCH] sh: maple: add support for Maple controller as a Matt Fleming @ 2008-12-20 16:07 ` Adrian McMenamin 2008-12-20 20:19 ` [PATCH] sh: maple: add support for Maple controller as a joystick Dmitry Torokhov 0 siblings, 1 reply; 12+ messages in thread From: Adrian McMenamin @ 2008-12-20 16:07 UTC (permalink / raw) To: Matt Fleming; +Cc: LKML, Dmitry Torokhov, linux-sh, Andrew Morton, Paul Mundt On Sat, 2008-12-20 at 15:16 +0000, Matt Fleming wrote: > On Fri, Dec 19, 2008 at 11:15:42PM +0000, Adrian McMenamin wrote: > > > > Add support for the SEGA Dreamcast Maple controller as a joystick > > > > [snip] > > > + 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. > > + > > + pad = kzalloc(sizeof(struct dc_pad), GFP_KERNEL); > > + idev = input_allocate_device(); > > + if (!pad || !idev){ > > + error = ENOMEM; > > + goto fail; > > + } > > [snip] > > > +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); ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] sh: maple: add support for Maple controller as a joystick 2008-12-20 16:07 ` Adrian McMenamin @ 2008-12-20 20:19 ` Dmitry Torokhov 2008-12-20 20:47 ` [PATCH] sh: maple: add support for Maple controller as a Adrian McMenamin 0 siblings, 1 reply; 12+ messages in thread From: Dmitry Torokhov @ 2008-12-20 20:19 UTC (permalink / raw) To: Adrian McMenamin; +Cc: Matt Fleming, LKML, linux-sh, Andrew Morton, Paul Mundt On Saturday 20 December 2008 08:07:27 Adrian McMenamin wrote: > On Sat, 2008-12-20 at 15:16 +0000, Matt Fleming wrote: > > On Fri, Dec 19, 2008 at 11:15:42PM +0000, Adrian McMenamin wrote: > > > Add support for the SEGA Dreamcast Maple controller as a joystick > > > > [snip] > > > > > + 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. > 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. > > > + > > > + pad = kzalloc(sizeof(struct dc_pad), GFP_KERNEL); > > > + idev = input_allocate_device(); > > > + if (!pad || !idev){ > > > + error = ENOMEM; > > > + goto fail; > > > + } > > > > [snip] > > > > > +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); But we need to be freeing idev, not pad->dev because pad might be NULL. -- Dmitry ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] sh: maple: add support for Maple controller as a 2008-12-20 20:19 ` [PATCH] sh: maple: add support for Maple controller as a joystick Dmitry Torokhov @ 2008-12-20 20:47 ` Adrian McMenamin 2008-12-20 22:17 ` [PATCH] sh: maple: add support for Maple controller as a joystick Dmitry Torokhov 0 siblings, 1 reply; 12+ messages in thread From: Adrian McMenamin @ 2008-12-20 20:47 UTC (permalink / raw) To: Dmitry Torokhov; +Cc: Matt Fleming, LKML, linux-sh, Andrew Morton, Paul Mundt On Sat, 2008-12-20 at 12:19 -0800, Dmitry Torokhov wrote: > On Saturday 20 December 2008 08:07:27 Adrian McMenamin wrote: > > On Sat, 2008-12-20 at 15:16 +0000, Matt Fleming wrote: > > > On Fri, Dec 19, 2008 at 11:15:42PM +0000, Adrian McMenamin wrote: > > > > Add support for the SEGA Dreamcast Maple controller as a joystick > > > > > > [snip] > > > > > > > + 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. > > > > 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. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] sh: maple: add support for Maple controller as a joystick 2008-12-20 20:47 ` [PATCH] sh: maple: add support for Maple controller as a Adrian McMenamin @ 2008-12-20 22:17 ` Dmitry Torokhov 0 siblings, 0 replies; 12+ messages in thread From: Dmitry Torokhov @ 2008-12-20 22:17 UTC (permalink / raw) To: Adrian McMenamin; +Cc: Matt Fleming, LKML, linux-sh, Andrew Morton, Paul Mundt On Dec 20, 2008, at 12:47 PM, Adrian McMenamin <adrian@newgolddream.dyndns.info > wrote: > On Sat, 2008-12-20 at 12:19 -0800, Dmitry Torokhov wrote: >> On Saturday 20 December 2008 08:07:27 Adrian McMenamin wrote: >>> On Sat, 2008-12-20 at 15:16 +0000, Matt Fleming wrote: >>>> On Fri, Dec 19, 2008 at 11:15:42PM +0000, Adrian McMenamin wrote: >>>>> Add support for the SEGA Dreamcast Maple controller as a joystick >>>> >>>> [snip] >>>> >>>>> + 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. >>> >> >> 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. Right, so I think we need le16_to_cpu here, you want the data in native CPU order to manipulate it. -- Dmitry ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] sh: maple: add support for Maple controller as a joystick 2008-12-19 23:15 [PATCH] sh: maple: add support for Maple controller as a joystick Adrian McMenamin 2008-12-20 15:16 ` [PATCH] sh: maple: add support for Maple controller as a Matt Fleming @ 2008-12-21 6:47 ` Paul Mundt 2008-12-21 9:28 ` [PATCH] sh: maple: add support for Maple controller as a Rabin Vincent 2008-12-22 23:06 ` Andrew Morton 3 siblings, 0 replies; 12+ messages in thread From: Paul Mundt @ 2008-12-21 6:47 UTC (permalink / raw) To: Adrian McMenamin; +Cc: LKML, Dmitry Torokhov, linux-sh, Andrew Morton On Fri, Dec 19, 2008 at 11:15:42PM +0000, Adrian McMenamin wrote: > 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 > > Signed-off-by: Adrian McMenamin <adrian@mcmen.demon.co.uk> > --- > > diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig > index be5c14a..ca7ce42 100644 > --- a/drivers/input/joystick/Kconfig > +++ b/drivers/input/joystick/Kconfig > @@ -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. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] sh: maple: add support for Maple controller as a 2008-12-19 23:15 [PATCH] sh: maple: add support for Maple controller as a joystick Adrian McMenamin 2008-12-20 15:16 ` [PATCH] sh: maple: add support for Maple controller as a Matt Fleming 2008-12-21 6:47 ` Paul Mundt @ 2008-12-21 9:28 ` Rabin Vincent 2008-12-22 23:06 ` Andrew Morton 3 siblings, 0 replies; 12+ messages in thread From: Rabin Vincent @ 2008-12-21 9:28 UTC (permalink / raw) To: Adrian McMenamin Cc: LKML, Dmitry Torokhov, linux-sh, Andrew Morton, Paul Mundt On Fri, Dec 19, 2008 at 11:15:42PM +0000, Adrian McMenamin wrote: > Add support for the SEGA Dreamcast Maple controller as a joystick [snip] > + > + pad = kzalloc(sizeof(struct dc_pad), GFP_KERNEL); > + idev = input_allocate_device(); > + if (!pad || !idev){ > + error = ENOMEM; > + goto fail; > + } > + [snip] > + > + error = input_register_device(idev); > + if (error) > + goto fail; > + > + mdev->driver = mdrv; > + 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 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] sh: maple: add support for Maple controller as a 2008-12-19 23:15 [PATCH] sh: maple: add support for Maple controller as a joystick Adrian McMenamin ` (2 preceding siblings ...) 2008-12-21 9:28 ` [PATCH] sh: maple: add support for Maple controller as a Rabin Vincent @ 2008-12-22 23:06 ` Andrew Morton 2008-12-23 1:07 ` Harvey Harrison 3 siblings, 1 reply; 12+ messages in thread From: Andrew Morton @ 2008-12-22 23:06 UTC (permalink / raw) To: Adrian McMenamin; +Cc: linux-kernel, dmitry.torokhov, linux-sh, lethal On Fri, 19 Dec 2008 23:15:42 +0000 Adrian McMenamin <adrian@newgolddream.dyndns.info> wrote: > 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 > > ... > > +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? > + 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, > + -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. > + 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. > > ... > ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] sh: maple: add support for Maple controller as a 2008-12-22 23:06 ` Andrew Morton @ 2008-12-23 1:07 ` Harvey Harrison 2008-12-23 8:59 ` Dmitry Torokhov 0 siblings, 1 reply; 12+ messages in thread From: Harvey Harrison @ 2008-12-23 1:07 UTC (permalink / raw) To: Andrew Morton Cc: Adrian McMenamin, linux-kernel, dmitry.torokhov, linux-sh, lethal On Mon, 2008-12-22 at 15:06 -0800, Andrew Morton wrote: > On Fri, 19 Dec 2008 23:15:42 +0000 > Adrian McMenamin <adrian@newgolddream.dyndns.info> wrote: > > > 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 > > > > ... > > > > +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 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] sh: maple: add support for Maple controller as a 2008-12-23 1:07 ` Harvey Harrison @ 2008-12-23 8:59 ` Dmitry Torokhov 2008-12-26 19:08 ` Adrian McMenamin 0 siblings, 1 reply; 12+ messages in thread From: Dmitry Torokhov @ 2008-12-23 8:59 UTC (permalink / raw) To: Harvey Harrison Cc: Andrew Morton, Adrian McMenamin, linux-kernel, linux-sh, lethal On Mon, Dec 22, 2008 at 05:07:35PM -0800, Harvey Harrison wrote: > On Mon, 2008-12-22 at 15:06 -0800, Andrew Morton wrote: > > On Fri, 19 Dec 2008 23:15:42 +0000 > > Adrian McMenamin <adrian@newgolddream.dyndns.info> wrote: > > > > > 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 > > > > > > ... > > > > > > +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)); > 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! -- Dmitry Input: add support for Maple controller as a joystick From: Adrian McMenamin <adrian@newgolddream.dyndns.info> Add support for the SEGA Dreamcast Maple controller as a joystick Signed-off-by: Adrian McMenamin <adrian@mcmen.demon.co.uk> Signed-off-by: Dmitry Torokhov <dtor@mail.ru> --- 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 diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig index 268dd3f..b114195 100644 --- a/drivers/input/joystick/Kconfig +++ b/drivers/input/joystick/Kconfig @@ -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 diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile index 7230362..f397ec0 100644 --- a/drivers/input/joystick/Makefile +++ b/drivers/input/joystick/Makefile @@ -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 diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c new file mode 100644 index 0000000..c2e8160 --- /dev/null +++ b/drivers/input/joystick/maplecontrol.c @@ -0,0 +1,193 @@ +/* + * SEGA Dreamcast controller driver + * Based on drivers/usb/iforce.c + * + * Copyright Yaegashi Takeshi, 2001 + * Adrian McMenamin, 2008 + */ + +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/input.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/timer.h> +#include <linux/maple.h> + +MODULE_AUTHOR("Adrian McMenamin <adrian@mcmen.demon.co.uk>"); +MODULE_DESCRIPTION("SEGA Dreamcast controller driver"); +MODULE_LICENSE("GPL"); + +struct dc_pad { + struct input_dev *dev; + struct maple_device *mdev; +}; + +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 = ~le16_to_cpup((__le16 *)(res + 8)); + + 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 = 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 = 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) +{ + static 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, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + }; + + static 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, + }; + + 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]); + + pad = kzalloc(sizeof(struct dc_pad), GFP_KERNEL); + idev = input_allocate_device(); + if (!pad || !idev) { + error = -ENOMEM; + goto fail; + } + + pad->dev = idev; + pad->mdev = mdev; + + idev->open = dc_pad_open; + idev->close = dc_pad_close; + + for (i = 0; i < 32; i++) { + if (data & (1 << i)) { + if (btn_bit[i] >= 0) + __set_bit(btn_bit[i], idev->keybit); + else if (abs_bit[i] >= 0) + __set_bit(abs_bit[i], idev->absbit); + } + } + + if (idev->keybit[BIT_WORD(BTN_JOYSTICK)]) + idev->evbit[0] |= BIT_MASK(EV_KEY); + + if (idev->absbit[0]) + idev->evbit[0] |= BIT_MASK(EV_ABS); + + for (i = ABS_X; i <= ABS_BRAKE; i++) + input_set_abs_params(idev, i, 0, 255, 0, 0); + + for (i = ABS_HAT0X; i <= ABS_HAT3Y; i++) + input_set_abs_params(idev, i, 1, -1, 0, 0); + + idev->dev.platform_data = pad; + idev->dev.parent = &mdev->dev; + idev->name = mdev->product_name; + idev->id.bustype = BUS_HOST; + input_set_drvdata(idev, pad); + + error = input_register_device(idev); + if (error) + goto fail; + + mdev->driver = mdrv; + maple_set_drvdata(mdev, pad); + + return 0; + +fail: + input_free_device(idev); + kfree(pad); + maple_set_drvdata(mdev, NULL); + return error; +} + +static int remove_maple_controller(struct device *dev) +{ + struct maple_device *mdev = to_maple_dev(dev); + struct dc_pad *pad = maple_get_drvdata(mdev); + + mdev->callback = NULL; + input_unregister_device(pad->dev); + maple_set_drvdata(mdev, NULL); + kfree(pad); + + return 0; +} + +static struct maple_driver dc_pad_driver = { + .function = MAPLE_FUNC_CONTROLLER, + .drv = { + .name = "Dreamcast_controller", + .probe = probe_maple_controller, + .remove = remove_maple_controller, + }, +}; + +static int __init dc_pad_init(void) +{ + return maple_driver_register(&dc_pad_driver); +} + +static void __exit dc_pad_exit(void) +{ + maple_driver_unregister(&dc_pad_driver); +} + +module_init(dc_pad_init); +module_exit(dc_pad_exit); ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH] sh: maple: add support for Maple controller as a 2008-12-23 8:59 ` Dmitry Torokhov @ 2008-12-26 19:08 ` Adrian McMenamin 0 siblings, 0 replies; 12+ messages in thread From: Adrian McMenamin @ 2008-12-26 19:08 UTC (permalink / raw) To: Dmitry Torokhov Cc: Harvey Harrison, Andrew Morton, linux-kernel, linux-sh, lethal On Tue, 2008-12-23 at 03:59 -0500, Dmitry Torokhov wrote: > On Mon, Dec 22, 2008 at 05:07:35PM -0800, Harvey Harrison wrote: > > On Mon, 2008-12-22 at 15:06 -0800, Andrew Morton wrote: > > > On Fri, 19 Dec 2008 23:15:42 +0000 > > > Adrian McMenamin <adrian@newgolddream.dyndns.info> wrote: > > > > > > > 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 > > > > > > > > ... > > > > > > > > +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)); > > > > 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 :-) ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2008-12-26 19:08 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-12-19 23:15 [PATCH] sh: maple: add support for Maple controller as a joystick Adrian McMenamin 2008-12-20 15:16 ` [PATCH] sh: maple: add support for Maple controller as a Matt Fleming 2008-12-20 16:07 ` Adrian McMenamin 2008-12-20 20:19 ` [PATCH] sh: maple: add support for Maple controller as a joystick Dmitry Torokhov 2008-12-20 20:47 ` [PATCH] sh: maple: add support for Maple controller as a Adrian McMenamin 2008-12-20 22:17 ` [PATCH] sh: maple: add support for Maple controller as a joystick Dmitry Torokhov 2008-12-21 6:47 ` Paul Mundt 2008-12-21 9:28 ` [PATCH] sh: maple: add support for Maple controller as a Rabin Vincent 2008-12-22 23:06 ` Andrew Morton 2008-12-23 1:07 ` Harvey Harrison 2008-12-23 8:59 ` Dmitry Torokhov 2008-12-26 19:08 ` Adrian McMenamin
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).