// SPDX-License-Identifier: GPL-2.0-or-later /* * USB ATI Remote support * * Copyright (c) 2011, 2012 Anssi Hannula <[email protected]> * Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <[email protected]> * Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev * * This 2.2.0 version is a rewrite / cleanup of the 2.1.1 driver, including * porting to the 2.6 kernel interfaces, along with other modification * to better match the style of the existing usb/input drivers. However, the * protocol and hardware handling is essentially unchanged from 2.1.1. * * The 2.1.1 driver was derived from the usbati_remote and usbkbd drivers by * Vojtech Pavlik. * * Changes: * * Feb 2004: Torrey Hoffman <[email protected]> * Version 2.2.0 * Jun 2004: Torrey Hoffman <[email protected]> * Version 2.2.1 * Added key repeat support contributed by: * Vincent Vanackere <[email protected]> * Added support for the "Lola" remote contributed by: * Seth Cohn <[email protected]> * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Hardware & software notes * * These remote controls are distributed by ATI as part of their * "All-In-Wonder" video card packages. The receiver self-identifies as a * "USB Receiver" with manufacturer "X10 Wireless Technology Inc". * * The "Lola" remote is available from X10. See: * http://www.x10.com/products/lola_sg1.htm * The Lola is similar to the ATI remote but has no mouse support, and slightly * different keys. * * It is possible to use multiple receivers and remotes on multiple computers * simultaneously by configuring them to use specific channels. * * The RF protocol used by the remote supports 16 distinct channels, 1 to 16. * Actually, it may even support more, at least in some revisions of the * hardware. * * Each remote can be configured to transmit on one channel as follows: * - Press and hold the "hand icon" button. * - When the red LED starts to blink, let go of the "hand icon" button. * - When it stops blinking, input the channel code as two digits, from 01 * to 16, and press the hand icon again. * * The timing can be a little tricky. Try loading the module with debug=1 * to have the kernel print out messages about the remote control number * and mask. Note: debugging prints remote numbers as zero-based hexadecimal. * * The driver has a "channel_mask" parameter. This bitmask specifies which * channels will be ignored by the module. To mask out channels, just add * all the 2^channel_number values together. * * For instance, set channel_mask = 2^4 = 16 (binary 10000) to make ati_remote * ignore signals coming from remote controls transmitting on channel 4, but * accept all other channels. * * Or, set channel_mask = 65533, (0xFFFD), and all channels except 1 will be * ignored. * * The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this * parameter are unused. */ #include <linux/kernel.h> #include <linux/errno.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/usb/input.h> #include <linux/wait.h> #include <linux/jiffies.h> #include <media/rc-core.h> /* * Module and Version Information, Module Parameters */ #define ATI_REMOTE_VENDOR_ID … #define LOLA_REMOTE_PRODUCT_ID … #define LOLA2_REMOTE_PRODUCT_ID … #define ATI_REMOTE_PRODUCT_ID … #define NVIDIA_REMOTE_PRODUCT_ID … #define MEDION_REMOTE_PRODUCT_ID … #define FIREFLY_REMOTE_PRODUCT_ID … #define DRIVER_VERSION … #define DRIVER_AUTHOR … #define DRIVER_DESC … #define NAME_BUFSIZE … #define DATA_BUFSIZE … /* * Duplicate event filtering time. * Sequential, identical KIND_FILTERED inputs with less than * FILTER_TIME milliseconds between them are considered as repeat * events. The hardware generates 5 events for the first keypress * and we have to take this into account for an accurate repeat * behaviour. */ #define FILTER_TIME … #define REPEAT_DELAY … static unsigned long channel_mask; module_param(channel_mask, ulong, 0644); MODULE_PARM_DESC(…) …; static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(…) …; static int repeat_filter = …; module_param(repeat_filter, int, 0644); MODULE_PARM_DESC(…) …; static int repeat_delay = …; module_param(repeat_delay, int, 0644); MODULE_PARM_DESC(…) …; static bool mouse = …; module_param(mouse, bool, 0444); MODULE_PARM_DESC(…) …; #define dbginfo(dev, format, arg...) … struct ati_receiver_type { … }; static const char *get_medion_keymap(struct usb_interface *interface) { … } static const struct ati_receiver_type type_ati = …; static const struct ati_receiver_type type_medion = …; static const struct ati_receiver_type type_firefly = …; static const struct usb_device_id ati_remote_table[] = …; MODULE_DEVICE_TABLE(usb, ati_remote_table); /* Get hi and low bytes of a 16-bits int */ #define HI(a) … #define LO(a) … #define SEND_FLAG_IN_PROGRESS … #define SEND_FLAG_COMPLETE … /* Device initialization strings */ static char init1[] = …; static char init2[] = …; struct ati_remote { … }; /* "Kinds" of messages sent from the hardware to the driver. */ #define KIND_END … #define KIND_LITERAL … #define KIND_FILTERED … #define KIND_ACCEL … /* Translation table from hardware messages to input events. */ static const struct { … } ati_remote_tbl[] = …; /* * ati_remote_dump_input */ static void ati_remote_dump(struct device *dev, unsigned char *data, unsigned int len) { … } /* * ati_remote_open */ static int ati_remote_open(struct ati_remote *ati_remote) { … } /* * ati_remote_close */ static void ati_remote_close(struct ati_remote *ati_remote) { … } static int ati_remote_input_open(struct input_dev *inputdev) { … } static void ati_remote_input_close(struct input_dev *inputdev) { … } static int ati_remote_rc_open(struct rc_dev *rdev) { … } static void ati_remote_rc_close(struct rc_dev *rdev) { … } /* * ati_remote_irq_out */ static void ati_remote_irq_out(struct urb *urb) { … } /* * ati_remote_sendpacket * * Used to send device initialization strings */ static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data) { … } struct accel_times { … }; static const struct accel_times accel[] = …; /* * ati_remote_compute_accel * * Implements acceleration curve for directional control pad * If elapsed time since last event is > 1/4 second, user "stopped", * so reset acceleration. Otherwise, user is probably holding the control * pad down, so we increase acceleration, ramping up over two seconds to * a maximum speed. */ static int ati_remote_compute_accel(struct ati_remote *ati_remote) { … } /* * ati_remote_report_input */ static void ati_remote_input_report(struct urb *urb) { … } /* * ati_remote_irq_in */ static void ati_remote_irq_in(struct urb *urb) { … } /* * ati_remote_alloc_buffers */ static int ati_remote_alloc_buffers(struct usb_device *udev, struct ati_remote *ati_remote) { … } /* * ati_remote_free_buffers */ static void ati_remote_free_buffers(struct ati_remote *ati_remote) { … } static void ati_remote_input_init(struct ati_remote *ati_remote) { … } static void ati_remote_rc_init(struct ati_remote *ati_remote) { … } static int ati_remote_initialize(struct ati_remote *ati_remote) { … } /* * ati_remote_probe */ static int ati_remote_probe(struct usb_interface *interface, const struct usb_device_id *id) { … } /* * ati_remote_disconnect */ static void ati_remote_disconnect(struct usb_interface *interface) { … } /* usb specific object to register with the usb subsystem */ static struct usb_driver ati_remote_driver = …; module_usb_driver(…) …; MODULE_AUTHOR(…); MODULE_DESCRIPTION(…); MODULE_LICENSE(…) …;