Re: [PATCH 1/1] Input: ati_remote - extend keytable for medion remotes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxxxxx>
> ---
>  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
> 



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


[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux