diff options
Diffstat (limited to 'drivers/media/rc/ati_remote.c')
| -rw-r--r-- | drivers/media/rc/ati_remote.c | 276 |
1 files changed, 120 insertions, 156 deletions
diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c index 4d6a63fe6c5e..a733914a2574 100644 --- a/drivers/media/rc/ati_remote.c +++ b/drivers/media/rc/ati_remote.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * USB ATI Remote support * @@ -26,20 +27,6 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Hardware & software notes @@ -83,7 +70,6 @@ * * The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this * parameter are unused. - * */ #include <linux/kernel.h> @@ -149,8 +135,6 @@ MODULE_PARM_DESC(mouse, "Enable mouse device, default = yes"); #define dbginfo(dev, format, arg...) \ do { if (debug) dev_info(dev , format , ## arg); } while (0) -#undef err -#define err(format, arg...) printk(KERN_ERR format , ## arg) struct ati_receiver_type { /* either default_keymap or get_default_keymap should be set */ @@ -202,7 +186,7 @@ static const struct ati_receiver_type type_firefly = { .default_keymap = RC_MAP_SNAPSTREAM_FIREFLY }; -static struct usb_device_id ati_remote_table[] = { +static const struct usb_device_id ati_remote_table[] = { { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)&type_ati @@ -267,7 +251,7 @@ struct ati_remote { char rc_name[NAME_BUFSIZE]; char rc_phys[NAME_BUFSIZE]; - char mouse_name[NAME_BUFSIZE]; + char mouse_name[NAME_BUFSIZE + 6]; char mouse_phys[NAME_BUFSIZE]; wait_queue_head_t wait; @@ -279,46 +263,42 @@ struct ati_remote { /* "Kinds" of messages sent from the hardware to the driver. */ #define KIND_END 0 -#define KIND_LITERAL 1 /* Simply pass to input system */ +#define KIND_LITERAL 1 /* Simply pass to input system as EV_KEY */ #define KIND_FILTERED 2 /* Add artificial key-up events, drop keyrepeats */ -#define KIND_LU 3 /* Directional keypad diagonals - left up, */ -#define KIND_RU 4 /* right up, */ -#define KIND_LD 5 /* left down, */ -#define KIND_RD 6 /* right down */ -#define KIND_ACCEL 7 /* Directional keypad - left, right, up, down.*/ +#define KIND_ACCEL 3 /* Translate to EV_REL mouse-move events */ /* Translation table from hardware messages to input events. */ static const struct { - short kind; - unsigned char data; - int type; - unsigned int code; - int value; + unsigned char kind; + unsigned char data; /* Raw key code from remote */ + unsigned short code; /* Input layer translation */ } ati_remote_tbl[] = { - /* Directional control pad axes */ - {KIND_ACCEL, 0x70, EV_REL, REL_X, -1}, /* left */ - {KIND_ACCEL, 0x71, EV_REL, REL_X, 1}, /* right */ - {KIND_ACCEL, 0x72, EV_REL, REL_Y, -1}, /* up */ - {KIND_ACCEL, 0x73, EV_REL, REL_Y, 1}, /* down */ + /* Directional control pad axes. Code is xxyy */ + {KIND_ACCEL, 0x70, 0xff00}, /* left */ + {KIND_ACCEL, 0x71, 0x0100}, /* right */ + {KIND_ACCEL, 0x72, 0x00ff}, /* up */ + {KIND_ACCEL, 0x73, 0x0001}, /* down */ + /* Directional control pad diagonals */ - {KIND_LU, 0x74, EV_REL, 0, 0}, /* left up */ - {KIND_RU, 0x75, EV_REL, 0, 0}, /* right up */ - {KIND_LD, 0x77, EV_REL, 0, 0}, /* left down */ - {KIND_RD, 0x76, EV_REL, 0, 0}, /* right down */ - - /* "Mouse button" buttons */ - {KIND_LITERAL, 0x78, EV_KEY, BTN_LEFT, 1}, /* left btn down */ - {KIND_LITERAL, 0x79, EV_KEY, BTN_LEFT, 0}, /* left btn up */ - {KIND_LITERAL, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */ - {KIND_LITERAL, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */ - - /* Artificial "doubleclick" events are generated by the hardware. + {KIND_ACCEL, 0x74, 0xffff}, /* left up */ + {KIND_ACCEL, 0x75, 0x01ff}, /* right up */ + {KIND_ACCEL, 0x77, 0xff01}, /* left down */ + {KIND_ACCEL, 0x76, 0x0101}, /* right down */ + + /* "Mouse button" buttons. The code below uses the fact that the + * lsbit of the raw code is a down/up indicator. */ + {KIND_LITERAL, 0x78, BTN_LEFT}, /* left btn down */ + {KIND_LITERAL, 0x79, BTN_LEFT}, /* left btn up */ + {KIND_LITERAL, 0x7c, BTN_RIGHT},/* right btn down */ + {KIND_LITERAL, 0x7d, BTN_RIGHT},/* right btn up */ + + /* Artificial "double-click" events are generated by the hardware. * They are mapped to the "side" and "extra" mouse buttons here. */ - {KIND_FILTERED, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */ - {KIND_FILTERED, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */ + {KIND_FILTERED, 0x7a, BTN_SIDE}, /* left dblclick */ + {KIND_FILTERED, 0x7e, BTN_EXTRA},/* right dblclick */ /* Non-mouse events are handled by rc-core */ - {KIND_END, 0x00, EV_MAX + 1, 0, 0} + {KIND_END, 0x00, 0} }; /* @@ -331,9 +311,9 @@ static void ati_remote_dump(struct device *dev, unsigned char *data, if (data[0] != (unsigned char)0xff && data[0] != 0x00) dev_warn(dev, "Weird byte 0x%02x\n", data[0]); } else if (len == 4) - dev_warn(dev, "Weird key %*ph\n", 4, data); + dev_warn(dev, "Weird key %4ph\n", data); else - dev_warn(dev, "Weird data, len=%d %*ph ...\n", len, 6, data); + dev_warn(dev, "Weird data, len=%d %6ph ...\n", len, data); } /* @@ -447,6 +427,21 @@ static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, return retval; } +struct accel_times { + const char value; + unsigned int msecs; +}; + +static const struct accel_times accel[] = { + { 1, 125 }, + { 2, 250 }, + { 4, 500 }, + { 6, 1000 }, + { 9, 1500 }, + { 13, 2000 }, + { 20, 0 }, +}; + /* * ati_remote_compute_accel * @@ -458,30 +453,22 @@ static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, */ static int ati_remote_compute_accel(struct ati_remote *ati_remote) { - static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; - unsigned long now = jiffies; - int acc; + unsigned long now = jiffies, reset_time; + int i; - if (time_after(now, ati_remote->old_jiffies + msecs_to_jiffies(250))) { - acc = 1; + reset_time = msecs_to_jiffies(250); + + if (time_after(now, ati_remote->old_jiffies + reset_time)) { ati_remote->acc_jiffies = now; + return 1; } - else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(125))) - acc = accel[0]; - else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(250))) - acc = accel[1]; - else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(500))) - acc = accel[2]; - else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1000))) - acc = accel[3]; - else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1500))) - acc = accel[4]; - else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(2000))) - acc = accel[5]; - else - acc = accel[6]; + for (i = 0; i < ARRAY_SIZE(accel) - 1; i++) { + unsigned long timeout = msecs_to_jiffies(accel[i].msecs); - return acc; + if (time_before(now, ati_remote->acc_jiffies + timeout)) + return accel[i].value; + } + return accel[i].value; } /* @@ -493,7 +480,6 @@ static void ati_remote_input_report(struct urb *urb) unsigned char *data= ati_remote->inbuf; struct input_dev *dev = ati_remote->idev; int index = -1; - int acc; int remote_num; unsigned char scancode; u32 wheel_keycode = KEY_RESERVED; @@ -507,15 +493,16 @@ static void ati_remote_input_report(struct urb *urb) */ /* Deal with strange looking inputs */ - if ( (urb->actual_length != 4) || (data[0] != 0x14) || - ((data[3] & 0x0f) != 0x00) ) { + if ( urb->actual_length != 4 || data[0] != 0x14 || + data[1] != (unsigned char)(data[2] + data[3] + 0xD5) || + (data[3] & 0x0f) != 0x00) { ati_remote_dump(&urb->dev->dev, data, urb->actual_length); return; } if (data[1] != ((data[2] + data[3] + 0xd5) & 0xff)) { dbginfo(&ati_remote->interface->dev, - "wrong checksum in input: %*ph\n", 4, data); + "wrong checksum in input: %4ph\n", data); return; } @@ -524,9 +511,8 @@ static void ati_remote_input_report(struct urb *urb) remote_num = (data[3] >> 4) & 0x0f; if (channel_mask & (1 << (remote_num + 1))) { dbginfo(&ati_remote->interface->dev, - "Masked input from channel 0x%02x: data %02x,%02x, " - "mask= 0x%02lx\n", - remote_num, data[1], data[2], channel_mask); + "Masked input from channel 0x%02x: data %02x, mask= 0x%02lx\n", + remote_num, data[2], channel_mask); return; } @@ -566,16 +552,16 @@ static void ati_remote_input_report(struct urb *urb) } if (index >= 0 && 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); - input_sync(dev); + /* + * The lsbit of the raw key code is a down/up flag. + * Invert it to match the input layer's conventions. + */ + input_event(dev, EV_KEY, ati_remote_tbl[index].code, + !(data[2] & 1)); ati_remote->old_jiffies = jiffies; - return; - } - if (index < 0 || ati_remote_tbl[index].kind == KIND_FILTERED) { + } else if (index < 0 || ati_remote_tbl[index].kind == KIND_FILTERED) { unsigned long now = jiffies; /* Filter duplicate events which happen "too close" together. */ @@ -588,12 +574,11 @@ static void ati_remote_input_report(struct urb *urb) ati_remote->first_jiffies = now; } - ati_remote->old_data = data[2]; ati_remote->old_jiffies = now; - /* Ensure we skip at least the 4 first duplicate events (generated - * by a single keypress), and continue skipping until repeat_delay - * msecs have passed + /* Ensure we skip at least the 4 first duplicate events + * (generated by a single keypress), and continue skipping + * until repeat_delay msecs have passed. */ if (ati_remote->repeat_count > 0 && (ati_remote->repeat_count < 5 || @@ -601,7 +586,10 @@ static void ati_remote_input_report(struct urb *urb) msecs_to_jiffies(repeat_delay)))) return; - if (index < 0) { + if (index >= 0) { + input_event(dev, EV_KEY, ati_remote_tbl[index].code, 1); + input_event(dev, EV_KEY, ati_remote_tbl[index].code, 0); + } else { /* Not a mouse event, hand it to rc-core. */ int count = 1; @@ -622,61 +610,38 @@ static void ati_remote_input_report(struct urb *urb) * it would cause ghost repeats which would be a * regression for this driver. */ - rc_keydown_notimeout(ati_remote->rdev, scancode, - data[2]); + rc_keydown_notimeout(ati_remote->rdev, + RC_PROTO_OTHER, + scancode, data[2]); rc_keyup(ati_remote->rdev); } - return; + goto nosync; } - input_event(dev, ati_remote_tbl[index].type, - ati_remote_tbl[index].code, 1); - input_sync(dev); - input_event(dev, ati_remote_tbl[index].type, - ati_remote_tbl[index].code, 0); - input_sync(dev); - - } else { + } else if (ati_remote_tbl[index].kind == KIND_ACCEL) { + signed char dx = ati_remote_tbl[index].code >> 8; + signed char dy = ati_remote_tbl[index].code & 255; /* * Other event kinds are from the directional control pad, and * have an acceleration factor applied to them. Without this * acceleration, the control pad is mostly unusable. */ - acc = ati_remote_compute_accel(ati_remote); - - switch (ati_remote_tbl[index].kind) { - case KIND_ACCEL: - input_event(dev, ati_remote_tbl[index].type, - ati_remote_tbl[index].code, - ati_remote_tbl[index].value * acc); - break; - case KIND_LU: - input_report_rel(dev, REL_X, -acc); - input_report_rel(dev, REL_Y, -acc); - break; - case KIND_RU: - input_report_rel(dev, REL_X, acc); - input_report_rel(dev, REL_Y, -acc); - break; - case KIND_LD: - input_report_rel(dev, REL_X, -acc); - input_report_rel(dev, REL_Y, acc); - break; - case KIND_RD: - input_report_rel(dev, REL_X, acc); - input_report_rel(dev, REL_Y, acc); - break; - default: - dev_dbg(&ati_remote->interface->dev, - "ati_remote kind=%d\n", - ati_remote_tbl[index].kind); - } - input_sync(dev); - + int acc = ati_remote_compute_accel(ati_remote); + if (dx) + input_report_rel(dev, REL_X, dx * acc); + if (dy) + input_report_rel(dev, REL_Y, dy * acc); ati_remote->old_jiffies = jiffies; - ati_remote->old_data = data[2]; + + } else { + dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", + ati_remote_tbl[index].kind); + return; } + input_sync(dev); +nosync: + ati_remote->old_data = data[2]; } /* @@ -763,8 +728,9 @@ static void ati_remote_input_init(struct ati_remote *ati_remote) 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); + if (ati_remote_tbl[i].kind == KIND_LITERAL || + ati_remote_tbl[i].kind == KIND_FILTERED) + __set_bit(ati_remote_tbl[i].code, idev->keybit); input_set_drvdata(idev, ati_remote); @@ -783,14 +749,13 @@ static void ati_remote_rc_init(struct ati_remote *ati_remote) struct rc_dev *rdev = ati_remote->rdev; rdev->priv = ati_remote; - rdev->driver_type = RC_DRIVER_SCANCODE; - rdev->allowed_protos = RC_BIT_OTHER; + rdev->allowed_protocols = RC_PROTO_BIT_OTHER; rdev->driver_name = "ati_remote"; rdev->open = ati_remote_rc_open; rdev->close = ati_remote_rc_close; - rdev->input_name = ati_remote->rc_name; + rdev->device_name = ati_remote->rc_name; rdev->input_phys = ati_remote->rc_phys; usb_to_input_id(ati_remote->udev, &rdev->input_id); @@ -806,7 +771,7 @@ static int ati_remote_initialize(struct ati_remote *ati_remote) /* Set up irq_urb */ pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress); - maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); + maxp = usb_maxpacket(udev, pipe); maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf, @@ -817,7 +782,7 @@ static int ati_remote_initialize(struct ati_remote *ati_remote) /* Set up out_urb */ pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress); - maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); + maxp = usb_maxpacket(udev, pipe); maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf, @@ -849,11 +814,12 @@ static int ati_remote_probe(struct usb_interface *interface, struct ati_receiver_type *type = (struct ati_receiver_type *)id->driver_info; struct ati_remote *ati_remote; struct input_dev *input_dev; + struct device *device = &interface->dev; struct rc_dev *rc_dev; int err = -ENOMEM; if (iface_host->desc.bNumEndpoints != 2) { - err("%s: Unexpected desc.bNumEndpoints\n", __func__); + dev_err(device, "%s: Unexpected desc.bNumEndpoints\n", __func__); return -ENODEV; } @@ -861,16 +827,20 @@ static int ati_remote_probe(struct usb_interface *interface, endpoint_out = &iface_host->endpoint[1].desc; if (!usb_endpoint_is_int_in(endpoint_in)) { - err("%s: Unexpected endpoint_in\n", __func__); + dev_err(device, "%s: Unexpected endpoint_in\n", __func__); return -ENODEV; } if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) { - err("%s: endpoint_in message size==0? \n", __func__); + dev_err(device, "%s: endpoint_in message size==0?\n", __func__); + return -ENODEV; + } + if (!usb_endpoint_is_int_out(endpoint_out)) { + dev_err(device, "%s: Unexpected endpoint_out\n", __func__); return -ENODEV; } ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL); - rc_dev = rc_allocate_device(); + rc_dev = rc_allocate_device(RC_DRIVER_SCANCODE); if (!ati_remote || !rc_dev) goto exit_free_dev_rdev; @@ -885,19 +855,16 @@ static int ati_remote_probe(struct usb_interface *interface, ati_remote->interface = interface; usb_make_path(udev, ati_remote->rc_phys, sizeof(ati_remote->rc_phys)); - strlcpy(ati_remote->mouse_phys, ati_remote->rc_phys, + strscpy(ati_remote->mouse_phys, ati_remote->rc_phys, sizeof(ati_remote->mouse_phys)); strlcat(ati_remote->rc_phys, "/input0", sizeof(ati_remote->rc_phys)); strlcat(ati_remote->mouse_phys, "/input1", sizeof(ati_remote->mouse_phys)); - if (udev->manufacturer) - strlcpy(ati_remote->rc_name, udev->manufacturer, - sizeof(ati_remote->rc_name)); - - if (udev->product) - snprintf(ati_remote->rc_name, sizeof(ati_remote->rc_name), - "%s %s", ati_remote->rc_name, udev->product); + snprintf(ati_remote->rc_name, sizeof(ati_remote->rc_name), "%s%s%s", + udev->manufacturer ?: "", + udev->manufacturer && udev->product ? " " : "", + udev->product ?: ""); if (!strlen(ati_remote->rc_name)) snprintf(ati_remote->rc_name, sizeof(ati_remote->rc_name), @@ -931,9 +898,6 @@ static int ati_remote_probe(struct usb_interface *interface, if (err) goto exit_kill_urbs; - /* use our delay for rc_dev */ - ati_remote->rdev->input_dev->rep[REP_DELAY] = repeat_delay; - /* Set up and register mouse input device */ if (mouse) { input_dev = input_allocate_device(); |
