Message ID | 20110418104547.GB4876@atlantis.wh2.tu-dresden.de.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hello, can please give me some reply if my patch is ok or not. It was a lot of work for me and I wont that it was for nothing. Thanks, Jan Losinski
Hi Jan, On Mon, Apr 18, 2011 at 12:45:47PM +0200, Jan Losinski wrote: > This extends the ati_remote to support multiple keytables. The table > will be selected with the productId of the device. > > It also provides a table for the medion rf remote control that enables > all buttons on it. > I am not a big fan of static keymaps in kernel drivers and would much more prefer driver supporting adjusting keymaps via EVIOCSKEYCODE ioctls. Unfortunately ati_remote key handling code is kind of involved and I am not sure what is the best way of wiring it up. I believe Anssi Hannula (CCed) mentioned that he has a version of ati_remove ported to rc-core infrastructure that supports such remapping. Anssi, could you tell me what is the status of that driver? Is it usable with rc-core? Thanks. > Signed-off-by: Jan Losinski <losinski@wh2.tu-dresden.de> > --- > drivers/input/misc/ati_remote.c | 155 ++++++++++++++++++++++++++++++++------- > 1 files changed, 128 insertions(+), 27 deletions(-) > > diff --git a/drivers/input/misc/ati_remote.c b/drivers/input/misc/ati_remote.c > index bce5712..74a3d5c 100644 > --- a/drivers/input/misc/ati_remote.c > +++ b/drivers/input/misc/ati_remote.c > @@ -165,6 +165,14 @@ MODULE_DEVICE_TABLE(usb, ati_remote_table); > static char init1[] = { 0x01, 0x00, 0x20, 0x14 }; > static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; > > +struct ati_event_table { > + short kind; > + unsigned char data1, data2; > + int type; > + unsigned int code; > + int value; > +}; > + > struct ati_remote { > struct input_dev *idev; > struct usb_device *udev; > @@ -191,6 +199,8 @@ struct ati_remote { > > wait_queue_head_t wait; > int send_flags; > + > + const struct ati_event_table *event_table; > }; > > /* "Kinds" of messages sent from the hardware to the driver. */ > @@ -204,13 +214,7 @@ struct ati_remote { > #define KIND_ACCEL 7 /* Directional keypad - left, right, up, down.*/ > > /* Translation table from hardware messages to input events. */ > -static const struct { > - short kind; > - unsigned char data1, data2; > - int type; > - unsigned int code; > - int value; > -} ati_remote_tbl[] = { > +static const struct ati_event_table ati_dflt_event_tbl[] = { > /* Directional control pad axes */ > {KIND_ACCEL, 0x35, 0x70, EV_REL, REL_X, -1}, /* left */ > {KIND_ACCEL, 0x36, 0x71, EV_REL, REL_X, 1}, /* right */ > @@ -288,6 +292,88 @@ static const struct { > {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} > }; > > +/* Translation table from hardware messages to input events. > + * Special version for the Medion Remote */ > +static const struct ati_event_table ati_medion_event_tbl[] = { > + > + {KIND_FILTERED, 0xf1, 0x2c, EV_KEY, KEY_TV, 1}, /* TV */ > + {KIND_FILTERED, 0xf2, 0x2d, EV_KEY, KEY_VCR, 1}, /* VCR */ > + {KIND_FILTERED, 0xc9, 0x04, EV_KEY, KEY_DVD, 1}, /* DVD */ > + {KIND_FILTERED, 0xcb, 0x06, EV_KEY, KEY_AUDIO, 1}, /* MUSIC */ > + > + {KIND_FILTERED, 0xf3, 0x2e, EV_KEY, KEY_RADIO, 1}, /* RADIO */ > + {KIND_FILTERED, 0xca, 0x05, EV_KEY, KEY_DIRECTORY, 1}, /* PHOTO */ > + {KIND_FILTERED, 0xf4, 0x2f, EV_KEY, KEY_INFO, 1}, /* TV-PREVIEW */ > + {KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_LIST, 1}, /* CHANNEL-LST */ > + > + {KIND_FILTERED, 0xe0, 0x1b, EV_KEY, KEY_SETUP, 1}, /* SETUP */ > + {KIND_FILTERED, 0xf6, 0x31, EV_KEY, KEY_VIDEO, 1}, /* VIDEO DESKTOP */ > + > + {KIND_FILTERED, 0xcd, 0x08, EV_KEY, KEY_VOLUMEDOWN, 1}, /* VOL - */ > + {KIND_FILTERED, 0xce, 0x09, EV_KEY, KEY_VOLUMEUP, 1}, /* VOL + */ > + {KIND_FILTERED, 0xd0, 0x0b, EV_KEY, KEY_CHANNELUP, 1}, /* CHAN + */ > + {KIND_FILTERED, 0xd1, 0x0c, EV_KEY, KEY_CHANNELDOWN, 1}, /* CHAN - */ > + {KIND_FILTERED, 0xc5, 0x00, EV_KEY, KEY_MUTE, 1}, /* MUTE */ > + > + {KIND_FILTERED, 0xf7, 0x32, EV_KEY, KEY_RED, 1}, /* red */ > + {KIND_FILTERED, 0xf8, 0x33, EV_KEY, KEY_GREEN, 1}, /* green */ > + {KIND_FILTERED, 0xf9, 0x34, EV_KEY, KEY_YELLOW, 1}, /* yellow */ > + {KIND_FILTERED, 0xfa, 0x35, EV_KEY, KEY_BLUE, 1}, /* blue */ > + {KIND_FILTERED, 0xdb, 0x16, EV_KEY, KEY_TEXT, 1}, /* TXT */ > + > + /* keyboard. */ > + {KIND_FILTERED, 0xd2, 0x0d, EV_KEY, KEY_1, 1}, > + {KIND_FILTERED, 0xd3, 0x0e, EV_KEY, KEY_2, 1}, > + {KIND_FILTERED, 0xd4, 0x0f, EV_KEY, KEY_3, 1}, > + {KIND_FILTERED, 0xd5, 0x10, EV_KEY, KEY_4, 1}, > + {KIND_FILTERED, 0xd6, 0x11, EV_KEY, KEY_5, 1}, > + {KIND_FILTERED, 0xd7, 0x12, EV_KEY, KEY_6, 1}, > + {KIND_FILTERED, 0xd8, 0x13, EV_KEY, KEY_7, 1}, > + {KIND_FILTERED, 0xd9, 0x14, EV_KEY, KEY_8, 1}, > + {KIND_FILTERED, 0xda, 0x15, EV_KEY, KEY_9, 1}, > + {KIND_FILTERED, 0xdc, 0x17, EV_KEY, KEY_0, 1}, > + {KIND_FILTERED, 0xe1, 0x1c, EV_KEY, KEY_SEARCH, 1}, /* TV/RAD, CH SRC */ > + {KIND_FILTERED, 0xe5, 0x20, EV_KEY, KEY_DELETE, 1}, /* DELETE */ > + > + {KIND_FILTERED, 0xfb, 0x36, EV_KEY, KEY_KEYBOARD, 1}, /* RENAME */ > + {KIND_FILTERED, 0xdd, 0x18, EV_KEY, KEY_SCREEN, 1}, /* SNAPSHOT */ > + > + {KIND_FILTERED, 0xdf, 0x1a, EV_KEY, KEY_UP, 1}, /* up */ > + {KIND_FILTERED, 0xe7, 0x22, EV_KEY, KEY_DOWN, 1}, /* down */ > + {KIND_FILTERED, 0xe2, 0x1d, EV_KEY, KEY_LEFT, 1}, /* left */ > + {KIND_FILTERED, 0xe4, 0x1f, EV_KEY, KEY_RIGHT, 1}, /* right */ > + {KIND_FILTERED, 0xe3, 0x1e, EV_KEY, KEY_OK, 1}, /* OK */ > + > + {KIND_FILTERED, 0xfc, 0x37, EV_KEY, KEY_SELECT, 1}, /* AQUIRE IMAGE */ > + {KIND_FILTERED, 0xfd, 0x38, EV_KEY, KEY_EDIT, 1}, /* EDIT IMAGE */ > + > + {KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1}, /* rewind (<<) */ > + {KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAY, 1}, /* play ( >) */ > + {KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1}, /* forward (>>) */ > + {KIND_FILTERED, 0xec, 0x27, EV_KEY, KEY_RECORD, 1}, /* record ( o) */ > + {KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1}, /* stop ([]) */ > + {KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PLAYPAUSE, 1},/* pause ('') */ > + > + {KIND_FILTERED, 0xe6, 0x21, EV_KEY, KEY_PREVIOUS, 1}, /* prev */ > + {KIND_FILTERED, 0xfe, 0x39, EV_KEY, KEY_SWITCHVIDEOMODE, 1}, /* F SCR */ > + {KIND_FILTERED, 0xe8, 0x23, EV_KEY, KEY_NEXT, 1}, /* next */ > + {KIND_FILTERED, 0xde, 0x19, EV_KEY, KEY_MENU, 1}, /* MENU */ > + {KIND_FILTERED, 0xff, 0x3a, EV_KEY, KEY_LANGUAGE, 1}, /* AUDIO */ > + > + {KIND_FILTERED, 0xc7, 0x02, EV_KEY, KEY_POWER, 1}, /* POWER */ > + > + {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} > +}; > + > +/* key translation assignment table */ > +static const struct { > + __u16 product_id; > + const struct ati_event_table * const table; > +} ati_remotes_table[] = { > + {MEDION_REMOTE_PRODUCT_ID, ati_medion_event_tbl}, > + {} /* Terminating entry */ > +}; > + > /* Local function prototypes */ > static int ati_remote_open (struct input_dev *inputdev); > static void ati_remote_close (struct input_dev *inputdev); > @@ -405,7 +491,8 @@ static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigne > /* > * ati_remote_event_lookup > */ > -static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) > +static int ati_remote_event_lookup(const struct ati_event_table *ati_remote_tbl, > + int rem, unsigned char d1, unsigned char d2) > { > int i; > > @@ -489,7 +576,8 @@ static void ati_remote_input_report(struct urb *urb) > } > > /* Look up event code index in translation table */ > - index = ati_remote_event_lookup(remote_num, data[1], data[2]); > + index = ati_remote_event_lookup(ati_remote->event_table, > + remote_num, data[1], data[2]); > if (index < 0) { > dev_warn(&ati_remote->interface->dev, > "Unknown input from channel 0x%02x: data %02x,%02x\n", > @@ -498,19 +586,20 @@ static void ati_remote_input_report(struct urb *urb) > } > dbginfo(&ati_remote->interface->dev, > "channel 0x%02x; data %02x,%02x; index %d; keycode %d\n", > - remote_num, data[1], data[2], index, ati_remote_tbl[index].code); > + remote_num, data[1], data[2], index, > + ati_remote->event_table[index].code); > > - if (ati_remote_tbl[index].kind == KIND_LITERAL) { > - input_event(dev, ati_remote_tbl[index].type, > - ati_remote_tbl[index].code, > - ati_remote_tbl[index].value); > + if (ati_remote->event_table[index].kind == KIND_LITERAL) { > + input_event(dev, ati_remote->event_table[index].type, > + ati_remote->event_table[index].code, > + ati_remote->event_table[index].value); > input_sync(dev); > > ati_remote->old_jiffies = jiffies; > return; > } > > - if (ati_remote_tbl[index].kind == KIND_FILTERED) { > + if (ati_remote->event_table[index].kind == KIND_FILTERED) { > unsigned long now = jiffies; > > /* Filter duplicate events which happen "too close" together. */ > @@ -539,11 +628,11 @@ static void ati_remote_input_report(struct urb *urb) > return; > > > - input_event(dev, ati_remote_tbl[index].type, > - ati_remote_tbl[index].code, 1); > + input_event(dev, ati_remote->event_table[index].type, > + ati_remote->event_table[index].code, 1); > input_sync(dev); > - input_event(dev, ati_remote_tbl[index].type, > - ati_remote_tbl[index].code, 0); > + input_event(dev, ati_remote->event_table[index].type, > + ati_remote->event_table[index].code, 0); > input_sync(dev); > > } else { > @@ -555,11 +644,11 @@ static void ati_remote_input_report(struct urb *urb) > */ > acc = ati_remote_compute_accel(ati_remote); > > - switch (ati_remote_tbl[index].kind) { > + switch (ati_remote->event_table[index].kind) { > case KIND_ACCEL: > - input_event(dev, ati_remote_tbl[index].type, > - ati_remote_tbl[index].code, > - ati_remote_tbl[index].value * acc); > + input_event(dev, ati_remote->event_table[index].type, > + ati_remote->event_table[index].code, > + ati_remote->event_table[index].value * acc); > break; > case KIND_LU: > input_report_rel(dev, REL_X, -acc); > @@ -579,7 +668,7 @@ static void ati_remote_input_report(struct urb *urb) > break; > default: > dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", > - ati_remote_tbl[index].kind); > + ati_remote->event_table[index].kind); > } > input_sync(dev); > > @@ -669,9 +758,9 @@ static void ati_remote_input_init(struct ati_remote *ati_remote) > idev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | > BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA); > idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); > - for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) > - if (ati_remote_tbl[i].type == EV_KEY) > - set_bit(ati_remote_tbl[i].code, idev->keybit); > + for (i = 0; ati_remote->event_table[i].kind != KIND_END; i++) > + if (ati_remote->event_table[i].type == EV_KEY) > + set_bit(ati_remote->event_table[i].code, idev->keybit); > > input_set_drvdata(idev, ati_remote); > > @@ -736,6 +825,7 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de > struct ati_remote *ati_remote; > struct input_dev *input_dev; > int err = -ENOMEM; > + int i; > > if (iface_host->desc.bNumEndpoints != 2) { > err("%s: Unexpected desc.bNumEndpoints\n", __func__); > @@ -785,6 +875,17 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de > le16_to_cpu(ati_remote->udev->descriptor.idVendor), > le16_to_cpu(ati_remote->udev->descriptor.idProduct)); > > + /* choose the right translation table */ > + ati_remote->event_table = ati_dflt_event_tbl; > + for (i = 0; ati_remotes_table[i].product_id || > + ati_remotes_table[i].table; i++) { > + if (le16_to_cpu(ati_remote->udev->descriptor.idProduct) == > + ati_remotes_table[i].product_id) { > + ati_remote->event_table = ati_remotes_table[i].table; > + break; > + } > + } > + > ati_remote_input_init(ati_remote); > > /* Device Hardware Initialization - fills in ati_remote->idev from udev. */ > -- > 1.7.4.1 >
2011/5/25 Dmitry Torokhov <dmitry.torokhov@gmail.com>: > Hi Jan, > > On Mon, Apr 18, 2011 at 12:45:47PM +0200, Jan Losinski wrote: >> This extends the ati_remote to support multiple keytables. The table >> will be selected with the productId of the device. >> >> It also provides a table for the medion rf remote control that enables >> all buttons on it. >> > > I am not a big fan of static keymaps in kernel drivers and would much > more prefer driver supporting adjusting keymaps via EVIOCSKEYCODE > ioctls. Unfortunately ati_remote key handling code is kind of involved > and I am not sure what is the best way of wiring it up. > > I believe Anssi Hannula (CCed) mentioned that he has a version of > ati_remove ported to rc-core infrastructure that supports such > remapping. Anssi, could you tell me what is the status of that driver? > Is it usable with rc-core? > That would be cool - being a remote it might be the right framework. Until then this patch might improve the situation. -- 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
On Wed, 25 May 2011 09:32:04 -0700 Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote: > Hi Jan, > > On Mon, Apr 18, 2011 at 12:45:47PM +0200, Jan Losinski wrote: > > This extends the ati_remote to support multiple keytables. The table > > will be selected with the productId of the device. > > > > It also provides a table for the medion rf remote control that > > enables all buttons on it. > > > > I am not a big fan of static keymaps in kernel drivers and would much > more prefer driver supporting adjusting keymaps via EVIOCSKEYCODE > ioctls. Unfortunately ati_remote key handling code is kind of involved > and I am not sure what is the best way of wiring it up. > > I believe Anssi Hannula (CCed) mentioned that he has a version of > ati_remove ported to rc-core infrastructure that supports such > remapping. Anssi, could you tell me what is the status of that driver? > Is it usable with rc-core? Jarod also had some interest in moving this to rc-core (but as he stated no time soon) Could this be added in the meantime ? Anyone ? Whats missing ? :) Thanks -- 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
On 25.05.2011 19:32, Dmitry Torokhov wrote: > Hi Jan, > > On Mon, Apr 18, 2011 at 12:45:47PM +0200, Jan Losinski wrote: >> This extends the ati_remote to support multiple keytables. The table >> will be selected with the productId of the device. >> >> It also provides a table for the medion rf remote control that enables >> all buttons on it. >> > > I am not a big fan of static keymaps in kernel drivers and would much > more prefer driver supporting adjusting keymaps via EVIOCSKEYCODE > ioctls. Unfortunately ati_remote key handling code is kind of involved > and I am not sure what is the best way of wiring it up. > > I believe Anssi Hannula (CCed) mentioned that he has a version of > ati_remove ported to rc-core infrastructure that supports such > remapping. Anssi, could you tell me what is the status of that driver? > Is it usable with rc-core? Sorry, it seems for some reason I didn't receive your message via CC and only now saw it while looking at linux-input@ messages. Indeed I have a patchset that makes it work with rc-core which I didn't get around to posting yet (sorry about that). I'll try to look over it now and do some more testing, and then post the set. Some notes about the patchset: - The mouse handling is left as-is, and it now appears as a separate input device (that part of the keymap is the same for all remotes with mouse). The mouse device is created regardless of receiver, in case another type of remote is used with the receiver. - The driver sends rc_keyup immediately after every rc_keydown, as that is what the driver has always done for input events as well. Doing otherwise would cause a regression as ghost repeats would appear with this driver while they didn't before.
Anssi Hannula wrote: > On 25.05.2011 19:32, Dmitry Torokhov wrote: >> I believe Anssi Hannula (CCed) mentioned that he has a version of >> ati_remove ported to rc-core infrastructure that supports such >> remapping. Anssi, could you tell me what is the status of that driver? >> Is it usable with rc-core? > > Sorry, it seems for some reason I didn't receive your message via CC and > only now saw it while looking at linux-input@ messages. > > Indeed I have a patchset that makes it work with rc-core which I didn't > get around to posting yet (sorry about that). > > I'll try to look over it now and do some more testing, and then post the > set. > > Some notes about the patchset: > - The mouse handling is left as-is, and it now appears as a separate > input device (that part of the keymap is the same for all remotes > with mouse). The mouse device is created regardless of receiver, > in case another type of remote is used with the receiver. > - The driver sends rc_keyup immediately after every rc_keydown, as that > is what the driver has always done for input events as well. Doing > otherwise would cause a regression as ghost repeats would appear > with this driver while they didn't before. Here goes the patchset, comments welcome. Anssi Hannula (7): [media] move ati_remote driver from input/misc to media/rc [media] ati_remote: migrate to the rc subsystem [media] ati_remote: parent input devices to usb interface [media] ati_remote: fix check for a weird byte [media] ati_remote: add keymap for Medion X10 RF remote [media] ati_remote: add support for SnapStream Firefly remote [media] ati_remote: update Kconfig description --- drivers/input/misc/Kconfig | 16 - drivers/input/misc/Makefile | 1 - drivers/input/misc/ati_remote.c | 867 -------------------- drivers/media/rc/Kconfig | 23 +- drivers/media/rc/Makefile | 1 + drivers/media/rc/ati_remote.c | 946 ++++++++++++++++++++++ drivers/media/rc/keymaps/Makefile | 3 + drivers/media/rc/keymaps/rc-ati-x10.c | 103 +++ drivers/media/rc/keymaps/rc-medion-x10.c | 116 +++ drivers/media/rc/keymaps/rc-snapstream-firefly.c | 106 +++ include/media/rc-map.h | 3 + 11 files changed, 1299 insertions(+), 886 deletions(-)
diff --git a/drivers/input/misc/ati_remote.c b/drivers/input/misc/ati_remote.c index bce5712..74a3d5c 100644 --- a/drivers/input/misc/ati_remote.c +++ b/drivers/input/misc/ati_remote.c @@ -165,6 +165,14 @@ MODULE_DEVICE_TABLE(usb, ati_remote_table); static char init1[] = { 0x01, 0x00, 0x20, 0x14 }; static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; +struct ati_event_table { + short kind; + unsigned char data1, data2; + int type; + unsigned int code; + int value; +}; + struct ati_remote { struct input_dev *idev; struct usb_device *udev; @@ -191,6 +199,8 @@ struct ati_remote { wait_queue_head_t wait; int send_flags; + + const struct ati_event_table *event_table; }; /* "Kinds" of messages sent from the hardware to the driver. */ @@ -204,13 +214,7 @@ struct ati_remote { #define KIND_ACCEL 7 /* Directional keypad - left, right, up, down.*/ /* Translation table from hardware messages to input events. */ -static const struct { - short kind; - unsigned char data1, data2; - int type; - unsigned int code; - int value; -} ati_remote_tbl[] = { +static const struct ati_event_table ati_dflt_event_tbl[] = { /* Directional control pad axes */ {KIND_ACCEL, 0x35, 0x70, EV_REL, REL_X, -1}, /* left */ {KIND_ACCEL, 0x36, 0x71, EV_REL, REL_X, 1}, /* right */ @@ -288,6 +292,88 @@ static const struct { {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} }; +/* Translation table from hardware messages to input events. + * Special version for the Medion Remote */ +static const struct ati_event_table ati_medion_event_tbl[] = { + + {KIND_FILTERED, 0xf1, 0x2c, EV_KEY, KEY_TV, 1}, /* TV */ + {KIND_FILTERED, 0xf2, 0x2d, EV_KEY, KEY_VCR, 1}, /* VCR */ + {KIND_FILTERED, 0xc9, 0x04, EV_KEY, KEY_DVD, 1}, /* DVD */ + {KIND_FILTERED, 0xcb, 0x06, EV_KEY, KEY_AUDIO, 1}, /* MUSIC */ + + {KIND_FILTERED, 0xf3, 0x2e, EV_KEY, KEY_RADIO, 1}, /* RADIO */ + {KIND_FILTERED, 0xca, 0x05, EV_KEY, KEY_DIRECTORY, 1}, /* PHOTO */ + {KIND_FILTERED, 0xf4, 0x2f, EV_KEY, KEY_INFO, 1}, /* TV-PREVIEW */ + {KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_LIST, 1}, /* CHANNEL-LST */ + + {KIND_FILTERED, 0xe0, 0x1b, EV_KEY, KEY_SETUP, 1}, /* SETUP */ + {KIND_FILTERED, 0xf6, 0x31, EV_KEY, KEY_VIDEO, 1}, /* VIDEO DESKTOP */ + + {KIND_FILTERED, 0xcd, 0x08, EV_KEY, KEY_VOLUMEDOWN, 1}, /* VOL - */ + {KIND_FILTERED, 0xce, 0x09, EV_KEY, KEY_VOLUMEUP, 1}, /* VOL + */ + {KIND_FILTERED, 0xd0, 0x0b, EV_KEY, KEY_CHANNELUP, 1}, /* CHAN + */ + {KIND_FILTERED, 0xd1, 0x0c, EV_KEY, KEY_CHANNELDOWN, 1}, /* CHAN - */ + {KIND_FILTERED, 0xc5, 0x00, EV_KEY, KEY_MUTE, 1}, /* MUTE */ + + {KIND_FILTERED, 0xf7, 0x32, EV_KEY, KEY_RED, 1}, /* red */ + {KIND_FILTERED, 0xf8, 0x33, EV_KEY, KEY_GREEN, 1}, /* green */ + {KIND_FILTERED, 0xf9, 0x34, EV_KEY, KEY_YELLOW, 1}, /* yellow */ + {KIND_FILTERED, 0xfa, 0x35, EV_KEY, KEY_BLUE, 1}, /* blue */ + {KIND_FILTERED, 0xdb, 0x16, EV_KEY, KEY_TEXT, 1}, /* TXT */ + + /* keyboard. */ + {KIND_FILTERED, 0xd2, 0x0d, EV_KEY, KEY_1, 1}, + {KIND_FILTERED, 0xd3, 0x0e, EV_KEY, KEY_2, 1}, + {KIND_FILTERED, 0xd4, 0x0f, EV_KEY, KEY_3, 1}, + {KIND_FILTERED, 0xd5, 0x10, EV_KEY, KEY_4, 1}, + {KIND_FILTERED, 0xd6, 0x11, EV_KEY, KEY_5, 1}, + {KIND_FILTERED, 0xd7, 0x12, EV_KEY, KEY_6, 1}, + {KIND_FILTERED, 0xd8, 0x13, EV_KEY, KEY_7, 1}, + {KIND_FILTERED, 0xd9, 0x14, EV_KEY, KEY_8, 1}, + {KIND_FILTERED, 0xda, 0x15, EV_KEY, KEY_9, 1}, + {KIND_FILTERED, 0xdc, 0x17, EV_KEY, KEY_0, 1}, + {KIND_FILTERED, 0xe1, 0x1c, EV_KEY, KEY_SEARCH, 1}, /* TV/RAD, CH SRC */ + {KIND_FILTERED, 0xe5, 0x20, EV_KEY, KEY_DELETE, 1}, /* DELETE */ + + {KIND_FILTERED, 0xfb, 0x36, EV_KEY, KEY_KEYBOARD, 1}, /* RENAME */ + {KIND_FILTERED, 0xdd, 0x18, EV_KEY, KEY_SCREEN, 1}, /* SNAPSHOT */ + + {KIND_FILTERED, 0xdf, 0x1a, EV_KEY, KEY_UP, 1}, /* up */ + {KIND_FILTERED, 0xe7, 0x22, EV_KEY, KEY_DOWN, 1}, /* down */ + {KIND_FILTERED, 0xe2, 0x1d, EV_KEY, KEY_LEFT, 1}, /* left */ + {KIND_FILTERED, 0xe4, 0x1f, EV_KEY, KEY_RIGHT, 1}, /* right */ + {KIND_FILTERED, 0xe3, 0x1e, EV_KEY, KEY_OK, 1}, /* OK */ + + {KIND_FILTERED, 0xfc, 0x37, EV_KEY, KEY_SELECT, 1}, /* AQUIRE IMAGE */ + {KIND_FILTERED, 0xfd, 0x38, EV_KEY, KEY_EDIT, 1}, /* EDIT IMAGE */ + + {KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1}, /* rewind (<<) */ + {KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAY, 1}, /* play ( >) */ + {KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1}, /* forward (>>) */ + {KIND_FILTERED, 0xec, 0x27, EV_KEY, KEY_RECORD, 1}, /* record ( o) */ + {KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1}, /* stop ([]) */ + {KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PLAYPAUSE, 1},/* pause ('') */ + + {KIND_FILTERED, 0xe6, 0x21, EV_KEY, KEY_PREVIOUS, 1}, /* prev */ + {KIND_FILTERED, 0xfe, 0x39, EV_KEY, KEY_SWITCHVIDEOMODE, 1}, /* F SCR */ + {KIND_FILTERED, 0xe8, 0x23, EV_KEY, KEY_NEXT, 1}, /* next */ + {KIND_FILTERED, 0xde, 0x19, EV_KEY, KEY_MENU, 1}, /* MENU */ + {KIND_FILTERED, 0xff, 0x3a, EV_KEY, KEY_LANGUAGE, 1}, /* AUDIO */ + + {KIND_FILTERED, 0xc7, 0x02, EV_KEY, KEY_POWER, 1}, /* POWER */ + + {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} +}; + +/* key translation assignment table */ +static const struct { + __u16 product_id; + const struct ati_event_table * const table; +} ati_remotes_table[] = { + {MEDION_REMOTE_PRODUCT_ID, ati_medion_event_tbl}, + {} /* Terminating entry */ +}; + /* Local function prototypes */ static int ati_remote_open (struct input_dev *inputdev); static void ati_remote_close (struct input_dev *inputdev); @@ -405,7 +491,8 @@ static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigne /* * ati_remote_event_lookup */ -static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) +static int ati_remote_event_lookup(const struct ati_event_table *ati_remote_tbl, + int rem, unsigned char d1, unsigned char d2) { int i; @@ -489,7 +576,8 @@ static void ati_remote_input_report(struct urb *urb) } /* Look up event code index in translation table */ - index = ati_remote_event_lookup(remote_num, data[1], data[2]); + index = ati_remote_event_lookup(ati_remote->event_table, + remote_num, data[1], data[2]); if (index < 0) { dev_warn(&ati_remote->interface->dev, "Unknown input from channel 0x%02x: data %02x,%02x\n", @@ -498,19 +586,20 @@ static void ati_remote_input_report(struct urb *urb) } dbginfo(&ati_remote->interface->dev, "channel 0x%02x; data %02x,%02x; index %d; keycode %d\n", - remote_num, data[1], data[2], index, ati_remote_tbl[index].code); + remote_num, data[1], data[2], index, + ati_remote->event_table[index].code); - if (ati_remote_tbl[index].kind == KIND_LITERAL) { - input_event(dev, ati_remote_tbl[index].type, - ati_remote_tbl[index].code, - ati_remote_tbl[index].value); + if (ati_remote->event_table[index].kind == KIND_LITERAL) { + input_event(dev, ati_remote->event_table[index].type, + ati_remote->event_table[index].code, + ati_remote->event_table[index].value); input_sync(dev); ati_remote->old_jiffies = jiffies; return; } - if (ati_remote_tbl[index].kind == KIND_FILTERED) { + if (ati_remote->event_table[index].kind == KIND_FILTERED) { unsigned long now = jiffies; /* Filter duplicate events which happen "too close" together. */ @@ -539,11 +628,11 @@ static void ati_remote_input_report(struct urb *urb) return; - input_event(dev, ati_remote_tbl[index].type, - ati_remote_tbl[index].code, 1); + input_event(dev, ati_remote->event_table[index].type, + ati_remote->event_table[index].code, 1); input_sync(dev); - input_event(dev, ati_remote_tbl[index].type, - ati_remote_tbl[index].code, 0); + input_event(dev, ati_remote->event_table[index].type, + ati_remote->event_table[index].code, 0); input_sync(dev); } else { @@ -555,11 +644,11 @@ static void ati_remote_input_report(struct urb *urb) */ acc = ati_remote_compute_accel(ati_remote); - switch (ati_remote_tbl[index].kind) { + switch (ati_remote->event_table[index].kind) { case KIND_ACCEL: - input_event(dev, ati_remote_tbl[index].type, - ati_remote_tbl[index].code, - ati_remote_tbl[index].value * acc); + input_event(dev, ati_remote->event_table[index].type, + ati_remote->event_table[index].code, + ati_remote->event_table[index].value * acc); break; case KIND_LU: input_report_rel(dev, REL_X, -acc); @@ -579,7 +668,7 @@ static void ati_remote_input_report(struct urb *urb) break; default: dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", - ati_remote_tbl[index].kind); + ati_remote->event_table[index].kind); } input_sync(dev); @@ -669,9 +758,9 @@ static void ati_remote_input_init(struct ati_remote *ati_remote) idev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA); idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); - for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) - if (ati_remote_tbl[i].type == EV_KEY) - set_bit(ati_remote_tbl[i].code, idev->keybit); + for (i = 0; ati_remote->event_table[i].kind != KIND_END; i++) + if (ati_remote->event_table[i].type == EV_KEY) + set_bit(ati_remote->event_table[i].code, idev->keybit); input_set_drvdata(idev, ati_remote); @@ -736,6 +825,7 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de struct ati_remote *ati_remote; struct input_dev *input_dev; int err = -ENOMEM; + int i; if (iface_host->desc.bNumEndpoints != 2) { err("%s: Unexpected desc.bNumEndpoints\n", __func__); @@ -785,6 +875,17 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de le16_to_cpu(ati_remote->udev->descriptor.idVendor), le16_to_cpu(ati_remote->udev->descriptor.idProduct)); + /* choose the right translation table */ + ati_remote->event_table = ati_dflt_event_tbl; + for (i = 0; ati_remotes_table[i].product_id || + ati_remotes_table[i].table; i++) { + if (le16_to_cpu(ati_remote->udev->descriptor.idProduct) == + ati_remotes_table[i].product_id) { + ati_remote->event_table = ati_remotes_table[i].table; + break; + } + } + ati_remote_input_init(ati_remote); /* Device Hardware Initialization - fills in ati_remote->idev from udev. */
This extends the ati_remote to support multiple keytables. The table will be selected with the productId of the device. It also provides a table for the medion rf remote control that enables all buttons on it. Signed-off-by: Jan Losinski <losinski@wh2.tu-dresden.de> --- drivers/input/misc/ati_remote.c | 155 ++++++++++++++++++++++++++++++++------- 1 files changed, 128 insertions(+), 27 deletions(-)