diff options
author | Dmitry Torokhov <dtor@insightbb.com> | 2007-05-07 23:31:32 +0200 |
---|---|---|
committer | Dmitry Torokhov <dtor@insightbb.com> | 2007-05-08 07:41:29 +0200 |
commit | ba0acb5ee318901646f82c134cca2e4de0c43934 (patch) | |
tree | 862d0d2b5d06332dce642571f625431c313d04ea /drivers/usb | |
parent | Input: move USB mice under drivers/input/mouse (diff) | |
download | linux-ba0acb5ee318901646f82c134cca2e4de0c43934.tar.xz linux-ba0acb5ee318901646f82c134cca2e4de0c43934.zip |
Input: move USB miscellaneous devices under drivers/input/misc
This will allow concentrating all input devices in one place
in {menu|x|q}config.
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/Makefile | 3 | ||||
-rw-r--r-- | drivers/usb/input/Kconfig | 77 | ||||
-rw-r--r-- | drivers/usb/input/Makefile | 13 | ||||
-rw-r--r-- | drivers/usb/input/ati_remote.c | 862 | ||||
-rw-r--r-- | drivers/usb/input/ati_remote2.c | 543 | ||||
-rw-r--r-- | drivers/usb/input/keyspan_remote.c | 592 | ||||
-rw-r--r-- | drivers/usb/input/map_to_7segment.h | 189 | ||||
-rw-r--r-- | drivers/usb/input/powermate.c | 463 | ||||
-rw-r--r-- | drivers/usb/input/yealink.c | 1004 | ||||
-rw-r--r-- | drivers/usb/input/yealink.h | 220 |
11 files changed, 0 insertions, 3968 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 9980a4ddfed9..b847bbc8b0e1 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -85,8 +85,6 @@ source "drivers/usb/class/Kconfig" source "drivers/usb/storage/Kconfig" -source "drivers/usb/input/Kconfig" - source "drivers/usb/image/Kconfig" source "drivers/usb/net/Kconfig" diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 7059a64637a8..0ef090b1b37c 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -23,9 +23,6 @@ obj-$(CONFIG_USB_PRINTER) += class/ obj-$(CONFIG_USB_STORAGE) += storage/ obj-$(CONFIG_USB) += storage/ -obj-$(CONFIG_USB_ATI_REMOTE) += input/ -obj-$(CONFIG_USB_POWERMATE) += input/ - obj-$(CONFIG_USB_CATC) += net/ obj-$(CONFIG_USB_KAWETH) += net/ obj-$(CONFIG_USB_PEGASUS) += net/ diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig deleted file mode 100644 index 4959dcf3cb4d..000000000000 --- a/drivers/usb/input/Kconfig +++ /dev/null @@ -1,77 +0,0 @@ -# -# USB Input driver configuration -# -comment "USB Input Devices" - depends on USB - -config USB_POWERMATE - tristate "Griffin PowerMate and Contour Jog support" - depends on USB && INPUT - ---help--- - Say Y here if you want to use Griffin PowerMate or Contour Jog devices. - These are aluminum dials which can measure clockwise and anticlockwise - rotation. The dial also acts as a pushbutton. The base contains an LED - which can be instructed to pulse or to switch to a particular intensity. - - You can download userspace tools from - <http://sowerbutts.com/powermate/>. - - To compile this driver as a module, choose M here: the - module will be called powermate. - -config USB_YEALINK - tristate "Yealink usb-p1k voip phone" - depends on USB && INPUT && EXPERIMENTAL - ---help--- - Say Y here if you want to enable keyboard and LCD functions of the - Yealink usb-p1k usb phones. The audio part is enabled by the generic - usb sound driver, so you might want to enable that as well. - - For information about how to use these additional functions, see - <file:Documentation/input/yealink.txt>. - - To compile this driver as a module, choose M here: the module will be - called yealink. - -config USB_ATI_REMOTE - tristate "ATI / X10 USB RF remote control" - depends on USB && INPUT - ---help--- - Say Y here if you want to use an ATI or X10 "Lola" USB remote control. - These are RF remotes with USB receivers. - The ATI remote comes with many of ATI's All-In-Wonder video cards. - The X10 "Lola" remote is available at: - <http://www.x10.com/products/lola_sg1.htm> - This driver provides mouse pointer, left and right mouse buttons, - and maps all the other remote buttons to keypress events. - - To compile this driver as a module, choose M here: the module will be - called ati_remote. - -config USB_ATI_REMOTE2 - tristate "ATI / Philips USB RF remote control" - depends on USB && INPUT - ---help--- - Say Y here if you want to use an ATI or Philips USB RF remote control. - These are RF remotes with USB receivers. - ATI Remote Wonder II comes with some ATI's All-In-Wonder video cards - and is also available as a separate product. - This driver provides mouse pointer, left and right mouse buttons, - and maps all the other remote buttons to keypress events. - - To compile this driver as a module, choose M here: the module will be - called ati_remote2. - -config USB_KEYSPAN_REMOTE - tristate "Keyspan DMR USB remote control (EXPERIMENTAL)" - depends on USB && INPUT && EXPERIMENTAL - ---help--- - Say Y here if you want to use a Keyspan DMR USB remote control. - Currently only the UIA-11 type of receiver has been tested. The tag - on the receiver that connects to the USB port should have a P/N that - will tell you what type of DMR you have. The UIA-10 type is not - supported at this time. This driver maps all buttons to keypress - events. - - To compile this driver as a module, choose M here: the module will - be called keyspan_remote. diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile deleted file mode 100644 index 91df130909e6..000000000000 --- a/drivers/usb/input/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# -# Makefile for the USB input drivers -# - -obj-$(CONFIG_USB_ATI_REMOTE) += ati_remote.o -obj-$(CONFIG_USB_ATI_REMOTE2) += ati_remote2.o -obj-$(CONFIG_USB_KEYSPAN_REMOTE) += keyspan_remote.o -obj-$(CONFIG_USB_POWERMATE) += powermate.o -obj-$(CONFIG_USB_YEALINK) += yealink.o - -ifeq ($(CONFIG_USB_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c deleted file mode 100644 index 471aab206443..000000000000 --- a/drivers/usb/input/ati_remote.c +++ /dev/null @@ -1,862 +0,0 @@ -/* - * USB ATI Remote support - * - * Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net> - * 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 <thoffman@arnor.net> - * Version 2.2.0 - * Jun 2004: Torrey Hoffman <thoffman@arnor.net> - * Version 2.2.1 - * Added key repeat support contributed by: - * Vincent Vanackere <vanackere@lif.univ-mrs.fr> - * Added support for the "Lola" remote contributed by: - * Seth Cohn <sethcohn@yahoo.com> - * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * - * 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 - * - * 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/moduleparam.h> -#include <linux/usb/input.h> -#include <linux/wait.h> -#include <linux/jiffies.h> - -/* - * Module and Version Information, Module Parameters - */ - -#define ATI_REMOTE_VENDOR_ID 0x0bc7 -#define ATI_REMOTE_PRODUCT_ID 0x004 -#define LOLA_REMOTE_PRODUCT_ID 0x002 -#define MEDION_REMOTE_PRODUCT_ID 0x006 - -#define DRIVER_VERSION "2.2.1" -#define DRIVER_AUTHOR "Torrey Hoffman <thoffman@arnor.net>" -#define DRIVER_DESC "ATI/X10 RF USB Remote Control" - -#define NAME_BUFSIZE 80 /* size of product name, path buffers */ -#define DATA_BUFSIZE 63 /* size of URB data buffers */ - -/* - * 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 60 /* msec */ -#define REPEAT_DELAY 500 /* msec */ - -static unsigned long channel_mask; -module_param(channel_mask, ulong, 0644); -MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); - -static int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); - -static int repeat_filter = FILTER_TIME; -module_param(repeat_filter, int, 0644); -MODULE_PARM_DESC(repeat_filter, "Repeat filter time, default = 60 msec"); - -static int repeat_delay = REPEAT_DELAY; -module_param(repeat_delay, int, 0644); -MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec"); - -#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) - -static struct usb_device_id ati_remote_table[] = { - { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, - { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, - { USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID) }, - {} /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, ati_remote_table); - -/* Get hi and low bytes of a 16-bits int */ -#define HI(a) ((unsigned char)((a) >> 8)) -#define LO(a) ((unsigned char)((a) & 0xff)) - -#define SEND_FLAG_IN_PROGRESS 1 -#define SEND_FLAG_COMPLETE 2 - -/* Device initialization strings */ -static char init1[] = { 0x01, 0x00, 0x20, 0x14 }; -static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; - -struct ati_remote { - struct input_dev *idev; - struct usb_device *udev; - struct usb_interface *interface; - - struct urb *irq_urb; - struct urb *out_urb; - struct usb_endpoint_descriptor *endpoint_in; - struct usb_endpoint_descriptor *endpoint_out; - unsigned char *inbuf; - unsigned char *outbuf; - dma_addr_t inbuf_dma; - dma_addr_t outbuf_dma; - - unsigned char old_data[2]; /* Detect duplicate events */ - unsigned long old_jiffies; - unsigned long acc_jiffies; /* handle acceleration */ - unsigned long first_jiffies; - - unsigned int repeat_count; - - char name[NAME_BUFSIZE]; - char phys[NAME_BUFSIZE]; - - wait_queue_head_t wait; - int send_flags; -}; - -/* "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_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.*/ - -/* 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[] = { - /* Directional control pad axes */ - {KIND_ACCEL, 0x35, 0x70, EV_REL, REL_X, -1}, /* left */ - {KIND_ACCEL, 0x36, 0x71, EV_REL, REL_X, 1}, /* right */ - {KIND_ACCEL, 0x37, 0x72, EV_REL, REL_Y, -1}, /* up */ - {KIND_ACCEL, 0x38, 0x73, EV_REL, REL_Y, 1}, /* down */ - /* Directional control pad diagonals */ - {KIND_LU, 0x39, 0x74, EV_REL, 0, 0}, /* left up */ - {KIND_RU, 0x3a, 0x75, EV_REL, 0, 0}, /* right up */ - {KIND_LD, 0x3c, 0x77, EV_REL, 0, 0}, /* left down */ - {KIND_RD, 0x3b, 0x76, EV_REL, 0, 0}, /* right down */ - - /* "Mouse button" buttons */ - {KIND_LITERAL, 0x3d, 0x78, EV_KEY, BTN_LEFT, 1}, /* left btn down */ - {KIND_LITERAL, 0x3e, 0x79, EV_KEY, BTN_LEFT, 0}, /* left btn up */ - {KIND_LITERAL, 0x41, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */ - {KIND_LITERAL, 0x42, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */ - - /* Artificial "doubleclick" events are generated by the hardware. - * They are mapped to the "side" and "extra" mouse buttons here. */ - {KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */ - {KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */ - - /* 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, 0xc5, 0x00, EV_KEY, KEY_A, 1}, - {KIND_FILTERED, 0xc6, 0x01, EV_KEY, KEY_B, 1}, - {KIND_FILTERED, 0xde, 0x19, EV_KEY, KEY_C, 1}, - {KIND_FILTERED, 0xe0, 0x1b, EV_KEY, KEY_D, 1}, - {KIND_FILTERED, 0xe6, 0x21, EV_KEY, KEY_E, 1}, - {KIND_FILTERED, 0xe8, 0x23, EV_KEY, KEY_F, 1}, - - /* "special" keys */ - {KIND_FILTERED, 0xdd, 0x18, EV_KEY, KEY_KPENTER, 1}, /* "check" */ - {KIND_FILTERED, 0xdb, 0x16, EV_KEY, KEY_MENU, 1}, /* "menu" */ - {KIND_FILTERED, 0xc7, 0x02, EV_KEY, KEY_POWER, 1}, /* Power */ - {KIND_FILTERED, 0xc8, 0x03, EV_KEY, KEY_TV, 1}, /* TV */ - {KIND_FILTERED, 0xc9, 0x04, EV_KEY, KEY_DVD, 1}, /* DVD */ - {KIND_FILTERED, 0xca, 0x05, EV_KEY, KEY_WWW, 1}, /* WEB */ - {KIND_FILTERED, 0xcb, 0x06, EV_KEY, KEY_BOOKMARKS, 1}, /* "book" */ - {KIND_FILTERED, 0xcc, 0x07, EV_KEY, KEY_EDIT, 1}, /* "hand" */ - {KIND_FILTERED, 0xe1, 0x1c, EV_KEY, KEY_COFFEE, 1}, /* "timer" */ - {KIND_FILTERED, 0xe5, 0x20, EV_KEY, KEY_FRONT, 1}, /* "max" */ - {KIND_FILTERED, 0xe2, 0x1d, EV_KEY, KEY_LEFT, 1}, /* left */ - {KIND_FILTERED, 0xe4, 0x1f, EV_KEY, KEY_RIGHT, 1}, /* right */ - {KIND_FILTERED, 0xe7, 0x22, EV_KEY, KEY_DOWN, 1}, /* down */ - {KIND_FILTERED, 0xdf, 0x1a, EV_KEY, KEY_UP, 1}, /* up */ - {KIND_FILTERED, 0xe3, 0x1e, EV_KEY, KEY_OK, 1}, /* "OK" */ - {KIND_FILTERED, 0xce, 0x09, EV_KEY, KEY_VOLUMEDOWN, 1}, /* VOL + */ - {KIND_FILTERED, 0xcd, 0x08, EV_KEY, KEY_VOLUMEUP, 1}, /* VOL - */ - {KIND_FILTERED, 0xcf, 0x0a, EV_KEY, KEY_MUTE, 1}, /* MUTE */ - {KIND_FILTERED, 0xd0, 0x0b, EV_KEY, KEY_CHANNELUP, 1}, /* CH + */ - {KIND_FILTERED, 0xd1, 0x0c, EV_KEY, KEY_CHANNELDOWN, 1},/* CH - */ - {KIND_FILTERED, 0xec, 0x27, EV_KEY, KEY_RECORD, 1}, /* ( o) red */ - {KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAY, 1}, /* ( >) */ - {KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1}, /* (<<) */ - {KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1}, /* (>>) */ - {KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1}, /* ([]) */ - {KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PAUSE, 1}, /* ('') */ - {KIND_FILTERED, 0xf0, 0x2b, EV_KEY, KEY_PREVIOUS, 1}, /* (<-) */ - {KIND_FILTERED, 0xef, 0x2a, EV_KEY, KEY_NEXT, 1}, /* (>+) */ - {KIND_FILTERED, 0xf2, 0x2D, EV_KEY, KEY_INFO, 1}, /* PLAYING */ - {KIND_FILTERED, 0xf3, 0x2E, EV_KEY, KEY_HOME, 1}, /* TOP */ - {KIND_FILTERED, 0xf4, 0x2F, EV_KEY, KEY_END, 1}, /* END */ - {KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_SELECT, 1}, /* SELECT */ - - {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} -}; - -/* Local function prototypes */ -static void ati_remote_dump (unsigned char *data, unsigned int actual_length); -static int ati_remote_open (struct input_dev *inputdev); -static void ati_remote_close (struct input_dev *inputdev); -static int ati_remote_sendpacket (struct ati_remote *ati_remote, u16 cmd, unsigned char *data); -static void ati_remote_irq_out (struct urb *urb); -static void ati_remote_irq_in (struct urb *urb); -static void ati_remote_input_report (struct urb *urb); -static int ati_remote_initialize (struct ati_remote *ati_remote); -static int ati_remote_probe (struct usb_interface *interface, const struct usb_device_id *id); -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 = { - .name = "ati_remote", - .probe = ati_remote_probe, - .disconnect = ati_remote_disconnect, - .id_table = ati_remote_table, -}; - -/* - * ati_remote_dump_input - */ -static void ati_remote_dump(unsigned char *data, unsigned int len) -{ - if ((len == 1) && (data[0] != (unsigned char)0xff) && (data[0] != 0x00)) - warn("Weird byte 0x%02x", data[0]); - else if (len == 4) - warn("Weird key %02x %02x %02x %02x", - data[0], data[1], data[2], data[3]); - else - warn("Weird data, len=%d %02x %02x %02x %02x %02x %02x ...", - len, data[0], data[1], data[2], data[3], data[4], data[5]); -} - -/* - * ati_remote_open - */ -static int ati_remote_open(struct input_dev *inputdev) -{ - struct ati_remote *ati_remote = input_get_drvdata(inputdev); - - /* On first open, submit the read urb which was set up previously. */ - ati_remote->irq_urb->dev = ati_remote->udev; - if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) { - dev_err(&ati_remote->interface->dev, - "%s: usb_submit_urb failed!\n", __FUNCTION__); - return -EIO; - } - - return 0; -} - -/* - * ati_remote_close - */ -static void ati_remote_close(struct input_dev *inputdev) -{ - struct ati_remote *ati_remote = input_get_drvdata(inputdev); - - usb_kill_urb(ati_remote->irq_urb); -} - -/* - * ati_remote_irq_out - */ -static void ati_remote_irq_out(struct urb *urb) -{ - struct ati_remote *ati_remote = urb->context; - - if (urb->status) { - dev_dbg(&ati_remote->interface->dev, "%s: status %d\n", - __FUNCTION__, urb->status); - return; - } - - ati_remote->send_flags |= SEND_FLAG_COMPLETE; - wmb(); - wake_up(&ati_remote->wait); -} - -/* - * ati_remote_sendpacket - * - * Used to send device initialization strings - */ -static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data) -{ - int retval = 0; - - /* Set up out_urb */ - memcpy(ati_remote->out_urb->transfer_buffer + 1, data, LO(cmd)); - ((char *) ati_remote->out_urb->transfer_buffer)[0] = HI(cmd); - - ati_remote->out_urb->transfer_buffer_length = LO(cmd) + 1; - ati_remote->out_urb->dev = ati_remote->udev; - ati_remote->send_flags = SEND_FLAG_IN_PROGRESS; - - retval = usb_submit_urb(ati_remote->out_urb, GFP_ATOMIC); - if (retval) { - dev_dbg(&ati_remote->interface->dev, - "sendpacket: usb_submit_urb failed: %d\n", retval); - return retval; - } - - wait_event_timeout(ati_remote->wait, - ((ati_remote->out_urb->status != -EINPROGRESS) || - (ati_remote->send_flags & SEND_FLAG_COMPLETE)), - HZ); - usb_kill_urb(ati_remote->out_urb); - - return retval; -} - -/* - * ati_remote_event_lookup - */ -static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) -{ - int i; - - for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) { - /* - * Decide if the table entry matches the remote input. - */ - if ((((ati_remote_tbl[i].data1 & 0x0f) == (d1 & 0x0f))) && - ((((ati_remote_tbl[i].data1 >> 4) - - (d1 >> 4) + rem) & 0x0f) == 0x0f) && - (ati_remote_tbl[i].data2 == d2)) - return i; - - } - return -1; -} - -/* - * 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) -{ - static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; - unsigned long now = jiffies; - int acc; - - if (time_after(now, ati_remote->old_jiffies + msecs_to_jiffies(250))) { - acc = 1; - ati_remote->acc_jiffies = now; - } - 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]; - - return acc; -} - -/* - * ati_remote_report_input - */ -static void ati_remote_input_report(struct urb *urb) -{ - struct ati_remote *ati_remote = urb->context; - unsigned char *data= ati_remote->inbuf; - struct input_dev *dev = ati_remote->idev; - int index, acc; - int remote_num; - - /* Deal with strange looking inputs */ - if ( (urb->actual_length != 4) || (data[0] != 0x14) || - ((data[3] & 0x0f) != 0x00) ) { - ati_remote_dump(data, urb->actual_length); - return; - } - - /* Mask unwanted remote channels. */ - /* note: remote_num is 0-based, channel 1 on remote == 0 here */ - 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); - return; - } - - /* Look up event code index in translation table */ - index = ati_remote_event_lookup(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", - remote_num, data[1], data[2]); - return; - } - 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); - - 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); - input_sync(dev); - - ati_remote->old_jiffies = jiffies; - return; - } - - if (ati_remote_tbl[index].kind == KIND_FILTERED) { - unsigned long now = jiffies; - - /* Filter duplicate events which happen "too close" together. */ - if (ati_remote->old_data[0] == data[1] && - ati_remote->old_data[1] == data[2] && - time_before(now, ati_remote->old_jiffies + - msecs_to_jiffies(repeat_filter))) { - ati_remote->repeat_count++; - } else { - ati_remote->repeat_count = 0; - ati_remote->first_jiffies = now; - } - - ati_remote->old_data[0] = data[1]; - ati_remote->old_data[1] = 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 - */ - if (ati_remote->repeat_count > 0 && - (ati_remote->repeat_count < 5 || - time_before(now, ati_remote->first_jiffies + - msecs_to_jiffies(repeat_delay)))) - return; - - - 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 { - - /* - * 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); - - ati_remote->old_jiffies = jiffies; - ati_remote->old_data[0] = data[1]; - ati_remote->old_data[1] = data[2]; - } -} - -/* - * ati_remote_irq_in - */ -static void ati_remote_irq_in(struct urb *urb) -{ - struct ati_remote *ati_remote = urb->context; - int retval; - - switch (urb->status) { - case 0: /* success */ - ati_remote_input_report(urb); - break; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: - dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n", - __FUNCTION__); - return; - default: /* error */ - dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n", - __FUNCTION__, urb->status); - } - - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n", - __FUNCTION__, retval); -} - -/* - * ati_remote_alloc_buffers - */ -static int ati_remote_alloc_buffers(struct usb_device *udev, - struct ati_remote *ati_remote) -{ - ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC, - &ati_remote->inbuf_dma); - if (!ati_remote->inbuf) - return -1; - - ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC, - &ati_remote->outbuf_dma); - if (!ati_remote->outbuf) - return -1; - - ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!ati_remote->irq_urb) - return -1; - - ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!ati_remote->out_urb) - return -1; - - return 0; -} - -/* - * ati_remote_free_buffers - */ -static void ati_remote_free_buffers(struct ati_remote *ati_remote) -{ - usb_free_urb(ati_remote->irq_urb); - usb_free_urb(ati_remote->out_urb); - - usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, - ati_remote->inbuf, ati_remote->inbuf_dma); - - usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, - ati_remote->outbuf, ati_remote->outbuf_dma); -} - -static void ati_remote_input_init(struct ati_remote *ati_remote) -{ - struct input_dev *idev = ati_remote->idev; - int i; - - idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); - idev->keybit[LONG(BTN_MOUSE)] = ( BIT(BTN_LEFT) | BIT(BTN_RIGHT) | - BIT(BTN_SIDE) | BIT(BTN_EXTRA) ); - idev->relbit[0] = BIT(REL_X) | BIT(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); - - input_set_drvdata(idev, ati_remote); - - idev->open = ati_remote_open; - idev->close = ati_remote_close; - - idev->name = ati_remote->name; - idev->phys = ati_remote->phys; - - usb_to_input_id(ati_remote->udev, &idev->id); - idev->dev.parent = &ati_remote->udev->dev; -} - -static int ati_remote_initialize(struct ati_remote *ati_remote) -{ - struct usb_device *udev = ati_remote->udev; - int pipe, maxp; - - init_waitqueue_head(&ati_remote->wait); - - /* Set up irq_urb */ - pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress); - maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); - maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; - - usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf, - maxp, ati_remote_irq_in, ati_remote, - ati_remote->endpoint_in->bInterval); - ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma; - ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - /* Set up out_urb */ - pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress); - maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); - maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; - - usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf, - maxp, ati_remote_irq_out, ati_remote, - ati_remote->endpoint_out->bInterval); - ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma; - ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - /* send initialization strings */ - if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) || - (ati_remote_sendpacket(ati_remote, 0x8007, init2))) { - dev_err(&ati_remote->interface->dev, - "Initializing ati_remote hardware failed.\n"); - return -EIO; - } - - return 0; -} - -/* - * ati_remote_probe - */ -static int ati_remote_probe(struct usb_interface *interface, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct usb_host_interface *iface_host = interface->cur_altsetting; - struct usb_endpoint_descriptor *endpoint_in, *endpoint_out; - struct ati_remote *ati_remote; - struct input_dev *input_dev; - int err = -ENOMEM; - - if (iface_host->desc.bNumEndpoints != 2) { - err("%s: Unexpected desc.bNumEndpoints\n", __FUNCTION__); - return -ENODEV; - } - - endpoint_in = &iface_host->endpoint[0].desc; - endpoint_out = &iface_host->endpoint[1].desc; - - if (!usb_endpoint_is_int_in(endpoint_in)) { - err("%s: Unexpected endpoint_in\n", __FUNCTION__); - return -ENODEV; - } - if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) { - err("%s: endpoint_in message size==0? \n", __FUNCTION__); - return -ENODEV; - } - - ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ati_remote || !input_dev) - goto fail1; - - /* Allocate URB buffers, URBs */ - if (ati_remote_alloc_buffers(udev, ati_remote)) - goto fail2; - - ati_remote->endpoint_in = endpoint_in; - ati_remote->endpoint_out = endpoint_out; - ati_remote->udev = udev; - ati_remote->idev = input_dev; - ati_remote->interface = interface; - - usb_make_path(udev, ati_remote->phys, sizeof(ati_remote->phys)); - strlcpy(ati_remote->phys, "/input0", sizeof(ati_remote->phys)); - - if (udev->manufacturer) - strlcpy(ati_remote->name, udev->manufacturer, sizeof(ati_remote->name)); - - if (udev->product) - snprintf(ati_remote->name, sizeof(ati_remote->name), - "%s %s", ati_remote->name, udev->product); - - if (!strlen(ati_remote->name)) - snprintf(ati_remote->name, sizeof(ati_remote->name), - DRIVER_DESC "(%04x,%04x)", - le16_to_cpu(ati_remote->udev->descriptor.idVendor), - le16_to_cpu(ati_remote->udev->descriptor.idProduct)); - - ati_remote_input_init(ati_remote); - - /* Device Hardware Initialization - fills in ati_remote->idev from udev. */ - err = ati_remote_initialize(ati_remote); - if (err) - goto fail3; - - /* Set up and register input device */ - err = input_register_device(ati_remote->idev); - if (err) - goto fail3; - - usb_set_intfdata(interface, ati_remote); - return 0; - - fail3: usb_kill_urb(ati_remote->irq_urb); - usb_kill_urb(ati_remote->out_urb); - fail2: ati_remote_free_buffers(ati_remote); - fail1: input_free_device(input_dev); - kfree(ati_remote); - return err; -} - -/* - * ati_remote_disconnect - */ -static void ati_remote_disconnect(struct usb_interface *interface) -{ - struct ati_remote *ati_remote; - - ati_remote = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - if (!ati_remote) { - warn("%s - null device?\n", __FUNCTION__); - return; - } - - usb_kill_urb(ati_remote->irq_urb); - usb_kill_urb(ati_remote->out_urb); - input_unregister_device(ati_remote->idev); - ati_remote_free_buffers(ati_remote); - kfree(ati_remote); -} - -/* - * ati_remote_init - */ -static int __init ati_remote_init(void) -{ - int result; - - result = usb_register(&ati_remote_driver); - if (result) - err("usb_register error #%d\n", result); - else - info("Registered USB driver " DRIVER_DESC " v. " DRIVER_VERSION); - - return result; -} - -/* - * ati_remote_exit - */ -static void __exit ati_remote_exit(void) -{ - usb_deregister(&ati_remote_driver); -} - -/* - * module specification - */ - -module_init(ati_remote_init); -module_exit(ati_remote_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/input/ati_remote2.c b/drivers/usb/input/ati_remote2.c deleted file mode 100644 index 1031543e5c3f..000000000000 --- a/drivers/usb/input/ati_remote2.c +++ /dev/null @@ -1,543 +0,0 @@ -/* - * ati_remote2 - ATI/Philips USB RF remote driver - * - * Copyright (C) 2005 Ville Syrjala <syrjala@sci.fi> - * Copyright (C) 2007 Peter Stokes <linux@dadeos.freeserve.co.uk> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#include <linux/usb/input.h> - -#define DRIVER_DESC "ATI/Philips USB RF remote driver" -#define DRIVER_VERSION "0.2" - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); -MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>"); -MODULE_LICENSE("GPL"); - -/* - * ATI Remote Wonder II Channel Configuration - * - * The remote control can by assigned one of sixteen "channels" in order to facilitate - * the use of multiple remote controls within range of each other. - * A remote's "channel" may be altered by pressing and holding the "PC" button for - * approximately 3 seconds, after which the button will slowly flash the count of the - * currently configured "channel", using the numeric keypad enter a number between 1 and - * 16 and then the "PC" button again, the button will slowly flash the count of the - * newly configured "channel". - */ - -static unsigned int channel_mask = 0xFFFF; -module_param(channel_mask, uint, 0644); -MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>"); - -static unsigned int mode_mask = 0x1F; -module_param(mode_mask, uint, 0644); -MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>"); - -static struct usb_device_id ati_remote2_id_table[] = { - { USB_DEVICE(0x0471, 0x0602) }, /* ATI Remote Wonder II */ - { } -}; -MODULE_DEVICE_TABLE(usb, ati_remote2_id_table); - -static struct { - int hw_code; - int key_code; -} ati_remote2_key_table[] = { - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - { 0x0c, KEY_POWER }, - { 0x0d, KEY_MUTE }, - { 0x10, KEY_VOLUMEUP }, - { 0x11, KEY_VOLUMEDOWN }, - { 0x20, KEY_CHANNELUP }, - { 0x21, KEY_CHANNELDOWN }, - { 0x28, KEY_FORWARD }, - { 0x29, KEY_REWIND }, - { 0x2c, KEY_PLAY }, - { 0x30, KEY_PAUSE }, - { 0x31, KEY_STOP }, - { 0x37, KEY_RECORD }, - { 0x38, KEY_DVD }, - { 0x39, KEY_TV }, - { 0x54, KEY_MENU }, - { 0x58, KEY_UP }, - { 0x59, KEY_DOWN }, - { 0x5a, KEY_LEFT }, - { 0x5b, KEY_RIGHT }, - { 0x5c, KEY_OK }, - { 0x78, KEY_A }, - { 0x79, KEY_B }, - { 0x7a, KEY_C }, - { 0x7b, KEY_D }, - { 0x7c, KEY_E }, - { 0x7d, KEY_F }, - { 0x82, KEY_ENTER }, - { 0x8e, KEY_VENDOR }, - { 0x96, KEY_COFFEE }, - { 0xa9, BTN_LEFT }, - { 0xaa, BTN_RIGHT }, - { 0xbe, KEY_QUESTION }, - { 0xd5, KEY_FRONT }, - { 0xd0, KEY_EDIT }, - { 0xf9, KEY_INFO }, - { (0x00 << 8) | 0x3f, KEY_PROG1 }, - { (0x01 << 8) | 0x3f, KEY_PROG2 }, - { (0x02 << 8) | 0x3f, KEY_PROG3 }, - { (0x03 << 8) | 0x3f, KEY_PROG4 }, - { (0x04 << 8) | 0x3f, KEY_PC }, - { 0, KEY_RESERVED } -}; - -struct ati_remote2 { - struct input_dev *idev; - struct usb_device *udev; - - struct usb_interface *intf[2]; - struct usb_endpoint_descriptor *ep[2]; - struct urb *urb[2]; - void *buf[2]; - dma_addr_t buf_dma[2]; - - unsigned long jiffies; - int mode; - - char name[64]; - char phys[64]; -}; - -static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id); -static void ati_remote2_disconnect(struct usb_interface *interface); - -static struct usb_driver ati_remote2_driver = { - .name = "ati_remote2", - .probe = ati_remote2_probe, - .disconnect = ati_remote2_disconnect, - .id_table = ati_remote2_id_table, -}; - -static int ati_remote2_open(struct input_dev *idev) -{ - struct ati_remote2 *ar2 = input_get_drvdata(idev); - int r; - - r = usb_submit_urb(ar2->urb[0], GFP_KERNEL); - if (r) { - dev_err(&ar2->intf[0]->dev, - "%s: usb_submit_urb() = %d\n", __FUNCTION__, r); - return r; - } - r = usb_submit_urb(ar2->urb[1], GFP_KERNEL); - if (r) { - usb_kill_urb(ar2->urb[0]); - dev_err(&ar2->intf[1]->dev, - "%s: usb_submit_urb() = %d\n", __FUNCTION__, r); - return r; - } - - return 0; -} - -static void ati_remote2_close(struct input_dev *idev) -{ - struct ati_remote2 *ar2 = input_get_drvdata(idev); - - usb_kill_urb(ar2->urb[0]); - usb_kill_urb(ar2->urb[1]); -} - -static void ati_remote2_input_mouse(struct ati_remote2 *ar2) -{ - struct input_dev *idev = ar2->idev; - u8 *data = ar2->buf[0]; - int channel, mode; - - channel = data[0] >> 4; - - if (!((1 << channel) & channel_mask)) - return; - - mode = data[0] & 0x0F; - - if (mode > 4) { - dev_err(&ar2->intf[0]->dev, - "Unknown mode byte (%02x %02x %02x %02x)\n", - data[3], data[2], data[1], data[0]); - return; - } - - if (!((1 << mode) & mode_mask)) - return; - - input_event(idev, EV_REL, REL_X, (s8) data[1]); - input_event(idev, EV_REL, REL_Y, (s8) data[2]); - input_sync(idev); -} - -static int ati_remote2_lookup(unsigned int hw_code) -{ - int i; - - for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++) - if (ati_remote2_key_table[i].hw_code == hw_code) - return i; - - return -1; -} - -static void ati_remote2_input_key(struct ati_remote2 *ar2) -{ - struct input_dev *idev = ar2->idev; - u8 *data = ar2->buf[1]; - int channel, mode, hw_code, index; - - channel = data[0] >> 4; - - if (!((1 << channel) & channel_mask)) - return; - - mode = data[0] & 0x0F; - - if (mode > 4) { - dev_err(&ar2->intf[1]->dev, - "Unknown mode byte (%02x %02x %02x %02x)\n", - data[3], data[2], data[1], data[0]); - return; - } - - hw_code = data[2]; - /* - * Mode keys (AUX1-AUX4, PC) all generate the same code byte. - * Use the mode byte to figure out which one was pressed. - */ - if (hw_code == 0x3f) { - /* - * For some incomprehensible reason the mouse pad generates - * events which look identical to the events from the last - * pressed mode key. Naturally we don't want to generate key - * events for the mouse pad so we filter out any subsequent - * events from the same mode key. - */ - if (ar2->mode == mode) - return; - - if (data[1] == 0) - ar2->mode = mode; - - hw_code |= mode << 8; - } - - if (!((1 << mode) & mode_mask)) - return; - - index = ati_remote2_lookup(hw_code); - if (index < 0) { - dev_err(&ar2->intf[1]->dev, - "Unknown code byte (%02x %02x %02x %02x)\n", - data[3], data[2], data[1], data[0]); - return; - } - - switch (data[1]) { - case 0: /* release */ - break; - case 1: /* press */ - ar2->jiffies = jiffies + msecs_to_jiffies(idev->rep[REP_DELAY]); - break; - case 2: /* repeat */ - - /* No repeat for mouse buttons. */ - if (ati_remote2_key_table[index].key_code == BTN_LEFT || - ati_remote2_key_table[index].key_code == BTN_RIGHT) - return; - - if (!time_after_eq(jiffies, ar2->jiffies)) - return; - - ar2->jiffies = jiffies + msecs_to_jiffies(idev->rep[REP_PERIOD]); - break; - default: - dev_err(&ar2->intf[1]->dev, - "Unknown state byte (%02x %02x %02x %02x)\n", - data[3], data[2], data[1], data[0]); - return; - } - - input_event(idev, EV_KEY, ati_remote2_key_table[index].key_code, data[1]); - input_sync(idev); -} - -static void ati_remote2_complete_mouse(struct urb *urb) -{ - struct ati_remote2 *ar2 = urb->context; - int r; - - switch (urb->status) { - case 0: - ati_remote2_input_mouse(ar2); - break; - case -ENOENT: - case -EILSEQ: - case -ECONNRESET: - case -ESHUTDOWN: - dev_dbg(&ar2->intf[0]->dev, - "%s(): urb status = %d\n", __FUNCTION__, urb->status); - return; - default: - dev_err(&ar2->intf[0]->dev, - "%s(): urb status = %d\n", __FUNCTION__, urb->status); - } - - r = usb_submit_urb(urb, GFP_ATOMIC); - if (r) - dev_err(&ar2->intf[0]->dev, - "%s(): usb_submit_urb() = %d\n", __FUNCTION__, r); -} - -static void ati_remote2_complete_key(struct urb *urb) -{ - struct ati_remote2 *ar2 = urb->context; - int r; - - switch (urb->status) { - case 0: - ati_remote2_input_key(ar2); - break; - case -ENOENT: - case -EILSEQ: - case -ECONNRESET: - case -ESHUTDOWN: - dev_dbg(&ar2->intf[1]->dev, - "%s(): urb status = %d\n", __FUNCTION__, urb->status); - return; - default: - dev_err(&ar2->intf[1]->dev, - "%s(): urb status = %d\n", __FUNCTION__, urb->status); - } - - r = usb_submit_urb(urb, GFP_ATOMIC); - if (r) - dev_err(&ar2->intf[1]->dev, - "%s(): usb_submit_urb() = %d\n", __FUNCTION__, r); -} - -static int ati_remote2_input_init(struct ati_remote2 *ar2) -{ - struct input_dev *idev; - int i, retval; - - idev = input_allocate_device(); - if (!idev) - return -ENOMEM; - - ar2->idev = idev; - input_set_drvdata(idev, ar2); - - idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL); - idev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT); - idev->relbit[0] = BIT(REL_X) | BIT(REL_Y); - for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++) - set_bit(ati_remote2_key_table[i].key_code, idev->keybit); - - idev->rep[REP_DELAY] = 250; - idev->rep[REP_PERIOD] = 33; - - idev->open = ati_remote2_open; - idev->close = ati_remote2_close; - - idev->name = ar2->name; - idev->phys = ar2->phys; - - usb_to_input_id(ar2->udev, &idev->id); - idev->dev.parent = &ar2->udev->dev; - - retval = input_register_device(idev); - if (retval) - input_free_device(idev); - - return retval; -} - -static int ati_remote2_urb_init(struct ati_remote2 *ar2) -{ - struct usb_device *udev = ar2->udev; - int i, pipe, maxp; - - for (i = 0; i < 2; i++) { - ar2->buf[i] = usb_buffer_alloc(udev, 4, GFP_KERNEL, &ar2->buf_dma[i]); - if (!ar2->buf[i]) - return -ENOMEM; - - ar2->urb[i] = usb_alloc_urb(0, GFP_KERNEL); - if (!ar2->urb[i]) - return -ENOMEM; - - pipe = usb_rcvintpipe(udev, ar2->ep[i]->bEndpointAddress); - maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); - maxp = maxp > 4 ? 4 : maxp; - - usb_fill_int_urb(ar2->urb[i], udev, pipe, ar2->buf[i], maxp, - i ? ati_remote2_complete_key : ati_remote2_complete_mouse, - ar2, ar2->ep[i]->bInterval); - ar2->urb[i]->transfer_dma = ar2->buf_dma[i]; - ar2->urb[i]->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - } - - return 0; -} - -static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2) -{ - int i; - - for (i = 0; i < 2; i++) { - usb_free_urb(ar2->urb[i]); - usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]); - } -} - -static int ati_remote2_setup(struct ati_remote2 *ar2) -{ - int r, i, channel; - - /* - * Configure receiver to only accept input from remote "channel" - * channel == 0 -> Accept input from any remote channel - * channel == 1 -> Only accept input from remote channel 1 - * channel == 2 -> Only accept input from remote channel 2 - * ... - * channel == 16 -> Only accept input from remote channel 16 - */ - - channel = 0; - for (i = 0; i < 16; i++) { - if ((1 << i) & channel_mask) { - if (!(~(1 << i) & 0xFFFF & channel_mask)) - channel = i + 1; - break; - } - } - - r = usb_control_msg(ar2->udev, usb_sndctrlpipe(ar2->udev, 0), - 0x20, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - channel, 0x0, NULL, 0, USB_CTRL_SET_TIMEOUT); - if (r) { - dev_err(&ar2->udev->dev, "%s - failed to set channel due to error: %d\n", - __FUNCTION__, r); - return r; - } - - return 0; -} - -static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct usb_host_interface *alt = interface->cur_altsetting; - struct ati_remote2 *ar2; - int r; - - if (alt->desc.bInterfaceNumber) - return -ENODEV; - - ar2 = kzalloc(sizeof (struct ati_remote2), GFP_KERNEL); - if (!ar2) - return -ENOMEM; - - ar2->udev = udev; - - ar2->intf[0] = interface; - ar2->ep[0] = &alt->endpoint[0].desc; - - ar2->intf[1] = usb_ifnum_to_if(udev, 1); - r = usb_driver_claim_interface(&ati_remote2_driver, ar2->intf[1], ar2); - if (r) - goto fail1; - alt = ar2->intf[1]->cur_altsetting; - ar2->ep[1] = &alt->endpoint[0].desc; - - r = ati_remote2_urb_init(ar2); - if (r) - goto fail2; - - r = ati_remote2_setup(ar2); - if (r) - goto fail2; - - usb_make_path(udev, ar2->phys, sizeof(ar2->phys)); - strlcat(ar2->phys, "/input0", sizeof(ar2->phys)); - - strlcat(ar2->name, "ATI Remote Wonder II", sizeof(ar2->name)); - - r = ati_remote2_input_init(ar2); - if (r) - goto fail2; - - usb_set_intfdata(interface, ar2); - - return 0; - - fail2: - ati_remote2_urb_cleanup(ar2); - - usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); - fail1: - kfree(ar2); - - return r; -} - -static void ati_remote2_disconnect(struct usb_interface *interface) -{ - struct ati_remote2 *ar2; - struct usb_host_interface *alt = interface->cur_altsetting; - - if (alt->desc.bInterfaceNumber) - return; - - ar2 = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - - input_unregister_device(ar2->idev); - - ati_remote2_urb_cleanup(ar2); - - usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); - - kfree(ar2); -} - -static int __init ati_remote2_init(void) -{ - int r; - - r = usb_register(&ati_remote2_driver); - if (r) - printk(KERN_ERR "ati_remote2: usb_register() = %d\n", r); - else - printk(KERN_INFO "ati_remote2: " DRIVER_DESC " " DRIVER_VERSION "\n"); - - return r; -} - -static void __exit ati_remote2_exit(void) -{ - usb_deregister(&ati_remote2_driver); -} - -module_init(ati_remote2_init); -module_exit(ati_remote2_exit); diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c deleted file mode 100644 index 1bffc9fa98c2..000000000000 --- a/drivers/usb/input/keyspan_remote.c +++ /dev/null @@ -1,592 +0,0 @@ -/* - * keyspan_remote: USB driver for the Keyspan DMR - * - * Copyright (C) 2005 Zymeta Corporation - Michael Downey (downey@zymeta.com) - * - * 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, version 2. - * - * This driver has been put together with the support of Innosys, Inc. - * and Keyspan, Inc the manufacturers of the Keyspan USB DMR product. - */ - -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/usb/input.h> - -#define DRIVER_VERSION "v0.1" -#define DRIVER_AUTHOR "Michael Downey <downey@zymeta.com>" -#define DRIVER_DESC "Driver for the USB Keyspan remote control." -#define DRIVER_LICENSE "GPL" - -/* Parameters that can be passed to the driver. */ -static int debug; -module_param(debug, int, 0444); -MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); - -/* Vendor and product ids */ -#define USB_KEYSPAN_VENDOR_ID 0x06CD -#define USB_KEYSPAN_PRODUCT_UIA11 0x0202 - -/* Defines for converting the data from the remote. */ -#define ZERO 0x18 -#define ZERO_MASK 0x1F /* 5 bits for a 0 */ -#define ONE 0x3C -#define ONE_MASK 0x3F /* 6 bits for a 1 */ -#define SYNC 0x3F80 -#define SYNC_MASK 0x3FFF /* 14 bits for a SYNC sequence */ -#define STOP 0x00 -#define STOP_MASK 0x1F /* 5 bits for the STOP sequence */ -#define GAP 0xFF - -#define RECV_SIZE 8 /* The UIA-11 type have a 8 byte limit. */ - -/* table of devices that work with this driver */ -static struct usb_device_id keyspan_table[] = { - { USB_DEVICE(USB_KEYSPAN_VENDOR_ID, USB_KEYSPAN_PRODUCT_UIA11) }, - { } /* Terminating entry */ -}; - -/* Structure to store all the real stuff that a remote sends to us. */ -struct keyspan_message { - u16 system; - u8 button; - u8 toggle; -}; - -/* Structure used for all the bit testing magic needed to be done. */ -struct bit_tester { - u32 tester; - int len; - int pos; - int bits_left; - u8 buffer[32]; -}; - -/* Structure to hold all of our driver specific stuff */ -struct usb_keyspan { - char name[128]; - char phys[64]; - struct usb_device* udev; - struct input_dev *input; - struct usb_interface* interface; - struct usb_endpoint_descriptor* in_endpoint; - struct urb* irq_urb; - int open; - dma_addr_t in_dma; - unsigned char* in_buffer; - - /* variables used to parse messages from remote. */ - struct bit_tester data; - int stage; - int toggle; -}; - -/* - * Table that maps the 31 possible keycodes to input keys. - * Currently there are 15 and 17 button models so RESERVED codes - * are blank areas in the mapping. - */ -static const int keyspan_key_table[] = { - KEY_RESERVED, /* 0 is just a place holder. */ - KEY_RESERVED, - KEY_STOP, - KEY_PLAYCD, - KEY_RESERVED, - KEY_PREVIOUSSONG, - KEY_REWIND, - KEY_FORWARD, - KEY_NEXTSONG, - KEY_RESERVED, - KEY_RESERVED, - KEY_RESERVED, - KEY_PAUSE, - KEY_VOLUMEUP, - KEY_RESERVED, - KEY_RESERVED, - KEY_RESERVED, - KEY_VOLUMEDOWN, - KEY_RESERVED, - KEY_UP, - KEY_RESERVED, - KEY_MUTE, - KEY_LEFT, - KEY_ENTER, - KEY_RIGHT, - KEY_RESERVED, - KEY_RESERVED, - KEY_DOWN, - KEY_RESERVED, - KEY_KPASTERISK, - KEY_RESERVED, - KEY_MENU -}; - -static struct usb_driver keyspan_driver; - -/* - * Debug routine that prints out what we've received from the remote. - */ -static void keyspan_print(struct usb_keyspan* dev) /*unsigned char* data)*/ -{ - char codes[4 * RECV_SIZE]; - int i; - - for (i = 0; i < RECV_SIZE; i++) - snprintf(codes + i * 3, 4, "%02x ", dev->in_buffer[i]); - - dev_info(&dev->udev->dev, "%s\n", codes); -} - -/* - * Routine that manages the bit_tester structure. It makes sure that there are - * at least bits_needed bits loaded into the tester. - */ -static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed) -{ - if (dev->data.bits_left >= bits_needed) - return 0; - - /* - * Somehow we've missed the last message. The message will be repeated - * though so it's not too big a deal - */ - if (dev->data.pos >= dev->data.len) { - dev_dbg(&dev->udev->dev, - "%s - Error ran out of data. pos: %d, len: %d\n", - __FUNCTION__, dev->data.pos, dev->data.len); - return -1; - } - - /* Load as much as we can into the tester. */ - while ((dev->data.bits_left + 7 < (sizeof(dev->data.tester) * 8)) && - (dev->data.pos < dev->data.len)) { - dev->data.tester += (dev->data.buffer[dev->data.pos++] << dev->data.bits_left); - dev->data.bits_left += 8; - } - - return 0; -} - -/* - * Routine that handles all the logic needed to parse out the message from the remote. - */ -static void keyspan_check_data(struct usb_keyspan *remote) -{ - int i; - int found = 0; - struct keyspan_message message; - - switch(remote->stage) { - case 0: - /* - * In stage 0 we want to find the start of a message. The remote sends a 0xFF as filler. - * So the first byte that isn't a FF should be the start of a new message. - */ - for (i = 0; i < RECV_SIZE && remote->in_buffer[i] == GAP; ++i); - - if (i < RECV_SIZE) { - memcpy(remote->data.buffer, remote->in_buffer, RECV_SIZE); - remote->data.len = RECV_SIZE; - remote->data.pos = 0; - remote->data.tester = 0; - remote->data.bits_left = 0; - remote->stage = 1; - } - break; - - case 1: - /* - * Stage 1 we should have 16 bytes and should be able to detect a - * SYNC. The SYNC is 14 bits, 7 0's and then 7 1's. - */ - memcpy(remote->data.buffer + remote->data.len, remote->in_buffer, RECV_SIZE); - remote->data.len += RECV_SIZE; - - found = 0; - while ((remote->data.bits_left >= 14 || remote->data.pos < remote->data.len) && !found) { - for (i = 0; i < 8; ++i) { - if (keyspan_load_tester(remote, 14) != 0) { - remote->stage = 0; - return; - } - - if ((remote->data.tester & SYNC_MASK) == SYNC) { - remote->data.tester = remote->data.tester >> 14; - remote->data.bits_left -= 14; - found = 1; - break; - } else { - remote->data.tester = remote->data.tester >> 1; - --remote->data.bits_left; - } - } - } - - if (!found) { - remote->stage = 0; - remote->data.len = 0; - } else { - remote->stage = 2; - } - break; - - case 2: - /* - * Stage 2 we should have 24 bytes which will be enough for a full - * message. We need to parse out the system code, button code, - * toggle code, and stop. - */ - memcpy(remote->data.buffer + remote->data.len, remote->in_buffer, RECV_SIZE); - remote->data.len += RECV_SIZE; - - message.system = 0; - for (i = 0; i < 9; i++) { - keyspan_load_tester(remote, 6); - - if ((remote->data.tester & ZERO_MASK) == ZERO) { - message.system = message.system << 1; - remote->data.tester = remote->data.tester >> 5; - remote->data.bits_left -= 5; - } else if ((remote->data.tester & ONE_MASK) == ONE) { - message.system = (message.system << 1) + 1; - remote->data.tester = remote->data.tester >> 6; - remote->data.bits_left -= 6; - } else { - err("%s - Unknown sequence found in system data.\n", __FUNCTION__); - remote->stage = 0; - return; - } - } - - message.button = 0; - for (i = 0; i < 5; i++) { - keyspan_load_tester(remote, 6); - - if ((remote->data.tester & ZERO_MASK) == ZERO) { - message.button = message.button << 1; - remote->data.tester = remote->data.tester >> 5; - remote->data.bits_left -= 5; - } else if ((remote->data.tester & ONE_MASK) == ONE) { - message.button = (message.button << 1) + 1; - remote->data.tester = remote->data.tester >> 6; - remote->data.bits_left -= 6; - } else { - err("%s - Unknown sequence found in button data.\n", __FUNCTION__); - remote->stage = 0; - return; - } - } - - keyspan_load_tester(remote, 6); - if ((remote->data.tester & ZERO_MASK) == ZERO) { - message.toggle = 0; - remote->data.tester = remote->data.tester >> 5; - remote->data.bits_left -= 5; - } else if ((remote->data.tester & ONE_MASK) == ONE) { - message.toggle = 1; - remote->data.tester = remote->data.tester >> 6; - remote->data.bits_left -= 6; - } else { - err("%s - Error in message, invalid toggle.\n", __FUNCTION__); - remote->stage = 0; - return; - } - - keyspan_load_tester(remote, 5); - if ((remote->data.tester & STOP_MASK) == STOP) { - remote->data.tester = remote->data.tester >> 5; - remote->data.bits_left -= 5; - } else { - err("Bad message recieved, no stop bit found.\n"); - } - - dev_dbg(&remote->udev->dev, - "%s found valid message: system: %d, button: %d, toggle: %d\n", - __FUNCTION__, message.system, message.button, message.toggle); - - if (message.toggle != remote->toggle) { - input_report_key(remote->input, keyspan_key_table[message.button], 1); - input_report_key(remote->input, keyspan_key_table[message.button], 0); - input_sync(remote->input); - remote->toggle = message.toggle; - } - - remote->stage = 0; - break; - } -} - -/* - * Routine for sending all the initialization messages to the remote. - */ -static int keyspan_setup(struct usb_device* dev) -{ - int retval = 0; - - retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0x11, 0x40, 0x5601, 0x0, NULL, 0, 0); - if (retval) { - dev_dbg(&dev->dev, "%s - failed to set bit rate due to error: %d\n", - __FUNCTION__, retval); - return(retval); - } - - retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0x44, 0x40, 0x0, 0x0, NULL, 0, 0); - if (retval) { - dev_dbg(&dev->dev, "%s - failed to set resume sensitivity due to error: %d\n", - __FUNCTION__, retval); - return(retval); - } - - retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0x22, 0x40, 0x0, 0x0, NULL, 0, 0); - if (retval) { - dev_dbg(&dev->dev, "%s - failed to turn receive on due to error: %d\n", - __FUNCTION__, retval); - return(retval); - } - - dev_dbg(&dev->dev, "%s - Setup complete.\n", __FUNCTION__); - return(retval); -} - -/* - * Routine used to handle a new message that has come in. - */ -static void keyspan_irq_recv(struct urb *urb) -{ - struct usb_keyspan *dev = urb->context; - int retval; - - /* Check our status in case we need to bail out early. */ - switch (urb->status) { - case 0: - break; - - /* Device went away so don't keep trying to read from it. */ - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - return; - - default: - goto resubmit; - break; - } - - if (debug) - keyspan_print(dev); - - keyspan_check_data(dev); - -resubmit: - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - err ("%s - usb_submit_urb failed with result: %d", __FUNCTION__, retval); -} - -static int keyspan_open(struct input_dev *dev) -{ - struct usb_keyspan *remote = input_get_drvdata(dev); - - remote->irq_urb->dev = remote->udev; - if (usb_submit_urb(remote->irq_urb, GFP_KERNEL)) - return -EIO; - - return 0; -} - -static void keyspan_close(struct input_dev *dev) -{ - struct usb_keyspan *remote = input_get_drvdata(dev); - - usb_kill_urb(remote->irq_urb); -} - -static struct usb_endpoint_descriptor *keyspan_get_in_endpoint(struct usb_host_interface *iface) -{ - - struct usb_endpoint_descriptor *endpoint; - int i; - - for (i = 0; i < iface->desc.bNumEndpoints; ++i) { - endpoint = &iface->endpoint[i].desc; - - if (usb_endpoint_is_int_in(endpoint)) { - /* we found our interrupt in endpoint */ - return endpoint; - } - } - - return NULL; -} - -/* - * Routine that sets up the driver to handle a specific USB device detected on the bus. - */ -static int keyspan_probe(struct usb_interface *interface, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct usb_endpoint_descriptor *endpoint; - struct usb_keyspan *remote; - struct input_dev *input_dev; - int i, error; - - endpoint = keyspan_get_in_endpoint(interface->cur_altsetting); - if (!endpoint) - return -ENODEV; - - remote = kzalloc(sizeof(*remote), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!remote || !input_dev) { - error = -ENOMEM; - goto fail1; - } - - remote->udev = udev; - remote->input = input_dev; - remote->interface = interface; - remote->in_endpoint = endpoint; - remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */ - - remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma); - if (!remote->in_buffer) { - error = -ENOMEM; - goto fail1; - } - - remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!remote->irq_urb) { - error = -ENOMEM; - goto fail2; - } - - error = keyspan_setup(udev); - if (error) { - error = -ENODEV; - goto fail3; - } - - if (udev->manufacturer) - strlcpy(remote->name, udev->manufacturer, sizeof(remote->name)); - - if (udev->product) { - if (udev->manufacturer) - strlcat(remote->name, " ", sizeof(remote->name)); - strlcat(remote->name, udev->product, sizeof(remote->name)); - } - - if (!strlen(remote->name)) - snprintf(remote->name, sizeof(remote->name), - "USB Keyspan Remote %04x:%04x", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); - - usb_make_path(udev, remote->phys, sizeof(remote->phys)); - strlcat(remote->phys, "/input0", sizeof(remote->phys)); - - input_dev->name = remote->name; - input_dev->phys = remote->phys; - usb_to_input_id(udev, &input_dev->id); - input_dev->dev.parent = &interface->dev; - - input_dev->evbit[0] = BIT(EV_KEY); /* We will only report KEY events. */ - for (i = 0; i < ARRAY_SIZE(keyspan_key_table); i++) - if (keyspan_key_table[i] != KEY_RESERVED) - set_bit(keyspan_key_table[i], input_dev->keybit); - - input_set_drvdata(input_dev, remote); - - input_dev->open = keyspan_open; - input_dev->close = keyspan_close; - - /* - * Initialize the URB to access the device. The urb gets sent to the device in keyspan_open() - */ - usb_fill_int_urb(remote->irq_urb, - remote->udev, usb_rcvintpipe(remote->udev, remote->in_endpoint->bEndpointAddress), - remote->in_buffer, RECV_SIZE, keyspan_irq_recv, remote, - remote->in_endpoint->bInterval); - remote->irq_urb->transfer_dma = remote->in_dma; - remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - /* we can register the device now, as it is ready */ - error = input_register_device(remote->input); - if (error) - goto fail3; - - /* save our data pointer in this interface device */ - usb_set_intfdata(interface, remote); - - return 0; - - fail3: usb_free_urb(remote->irq_urb); - fail2: usb_buffer_free(udev, RECV_SIZE, remote->in_buffer, remote->in_dma); - fail1: kfree(remote); - input_free_device(input_dev); - - return error; -} - -/* - * Routine called when a device is disconnected from the USB. - */ -static void keyspan_disconnect(struct usb_interface *interface) -{ - struct usb_keyspan *remote; - - remote = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - - if (remote) { /* We have a valid driver structure so clean up everything we allocated. */ - input_unregister_device(remote->input); - usb_kill_urb(remote->irq_urb); - usb_free_urb(remote->irq_urb); - usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma); - kfree(remote); - } -} - -/* - * Standard driver set up sections - */ -static struct usb_driver keyspan_driver = -{ - .name = "keyspan_remote", - .probe = keyspan_probe, - .disconnect = keyspan_disconnect, - .id_table = keyspan_table -}; - -static int __init usb_keyspan_init(void) -{ - int result; - - /* register this driver with the USB subsystem */ - result = usb_register(&keyspan_driver); - if (result) - err("usb_register failed. Error number %d\n", result); - - return result; -} - -static void __exit usb_keyspan_exit(void) -{ - /* deregister this driver with the USB subsystem */ - usb_deregister(&keyspan_driver); -} - -module_init(usb_keyspan_init); -module_exit(usb_keyspan_exit); - -MODULE_DEVICE_TABLE(usb, keyspan_table); -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENSE); diff --git a/drivers/usb/input/map_to_7segment.h b/drivers/usb/input/map_to_7segment.h deleted file mode 100644 index a424094d9fe2..000000000000 --- a/drivers/usb/input/map_to_7segment.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * drivers/usb/input/map_to_7segment.h - * - * Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com> - * - * 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 - */ - -#ifndef MAP_TO_7SEGMENT_H -#define MAP_TO_7SEGMENT_H - -/* This file provides translation primitives and tables for the conversion - * of (ASCII) characters to a 7-segments notation. - * - * The 7 segment's wikipedia notation below is used as standard. - * See: http://en.wikipedia.org/wiki/Seven_segment_display - * - * Notation: +-a-+ - * f b - * +-g-+ - * e c - * +-d-+ - * - * Usage: - * - * Register a map variable, and fill it with a character set: - * static SEG7_DEFAULT_MAP(map_seg7); - * - * - * Then use for conversion: - * seg7 = map_to_seg7(&map_seg7, some_char); - * ... - * - * In device drivers it is recommended, if required, to make the char map - * accessible via the sysfs interface using the following scheme: - * - * static ssize_t show_map(struct device *dev, char *buf) { - * memcpy(buf, &map_seg7, sizeof(map_seg7)); - * return sizeof(map_seg7); - * } - * static ssize_t store_map(struct device *dev, const char *buf, size_t cnt) { - * if(cnt != sizeof(map_seg7)) - * return -EINVAL; - * memcpy(&map_seg7, buf, cnt); - * return cnt; - * } - * static DEVICE_ATTR(map_seg7, PERMS_RW, show_map, store_map); - * - * History: - * 2005-05-31 RFC linux-kernel@vger.kernel.org - */ -#include <linux/errno.h> - - -#define BIT_SEG7_A 0 -#define BIT_SEG7_B 1 -#define BIT_SEG7_C 2 -#define BIT_SEG7_D 3 -#define BIT_SEG7_E 4 -#define BIT_SEG7_F 5 -#define BIT_SEG7_G 6 -#define BIT_SEG7_RESERVED 7 - -struct seg7_conversion_map { - unsigned char table[128]; -}; - -static inline int map_to_seg7(struct seg7_conversion_map *map, int c) -{ - return c >= 0 && c < sizeof(map->table) ? map->table[c] : -EINVAL; -} - -#define SEG7_CONVERSION_MAP(_name, _map) \ - struct seg7_conversion_map _name = { .table = { _map } } - -/* - * It is recommended to use a facility that allows user space to redefine - * custom character sets for LCD devices. Please use a sysfs interface - * as described above. - */ -#define MAP_TO_SEG7_SYSFS_FILE "map_seg7" - -/******************************************************************************* - * ASCII conversion table - ******************************************************************************/ - -#define _SEG7(l,a,b,c,d,e,f,g) \ - ( a<<BIT_SEG7_A | b<<BIT_SEG7_B | c<<BIT_SEG7_C | d<<BIT_SEG7_D | \ - e<<BIT_SEG7_E | f<<BIT_SEG7_F | g<<BIT_SEG7_G ) - -#define _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - -#define _MAP_33_47_ASCII_SEG7_SYMBOL \ - _SEG7('!',0,0,0,0,1,1,0), _SEG7('"',0,1,0,0,0,1,0), _SEG7('#',0,1,1,0,1,1,0),\ - _SEG7('$',1,0,1,1,0,1,1), _SEG7('%',0,0,1,0,0,1,0), _SEG7('&',1,0,1,1,1,1,1),\ - _SEG7('\'',0,0,0,0,0,1,0),_SEG7('(',1,0,0,1,1,1,0), _SEG7(')',1,1,1,1,0,0,0),\ - _SEG7('*',0,1,1,0,1,1,1), _SEG7('+',0,1,1,0,0,0,1), _SEG7(',',0,0,0,0,1,0,0),\ - _SEG7('-',0,0,0,0,0,0,1), _SEG7('.',0,0,0,0,1,0,0), _SEG7('/',0,1,0,0,1,0,1), - -#define _MAP_48_57_ASCII_SEG7_NUMERIC \ - _SEG7('0',1,1,1,1,1,1,0), _SEG7('1',0,1,1,0,0,0,0), _SEG7('2',1,1,0,1,1,0,1),\ - _SEG7('3',1,1,1,1,0,0,1), _SEG7('4',0,1,1,0,0,1,1), _SEG7('5',1,0,1,1,0,1,1),\ - _SEG7('6',1,0,1,1,1,1,1), _SEG7('7',1,1,1,0,0,0,0), _SEG7('8',1,1,1,1,1,1,1),\ - _SEG7('9',1,1,1,1,0,1,1), - -#define _MAP_58_64_ASCII_SEG7_SYMBOL \ - _SEG7(':',0,0,0,1,0,0,1), _SEG7(';',0,0,0,1,0,0,1), _SEG7('<',1,0,0,0,0,1,1),\ - _SEG7('=',0,0,0,1,0,0,1), _SEG7('>',1,1,0,0,0,0,1), _SEG7('?',1,1,1,0,0,1,0),\ - _SEG7('@',1,1,0,1,1,1,1), - -#define _MAP_65_90_ASCII_SEG7_ALPHA_UPPR \ - _SEG7('A',1,1,1,0,1,1,1), _SEG7('B',1,1,1,1,1,1,1), _SEG7('C',1,0,0,1,1,1,0),\ - _SEG7('D',1,1,1,1,1,1,0), _SEG7('E',1,0,0,1,1,1,1), _SEG7('F',1,0,0,0,1,1,1),\ - _SEG7('G',1,1,1,1,0,1,1), _SEG7('H',0,1,1,0,1,1,1), _SEG7('I',0,1,1,0,0,0,0),\ - _SEG7('J',0,1,1,1,0,0,0), _SEG7('K',0,1,1,0,1,1,1), _SEG7('L',0,0,0,1,1,1,0),\ - _SEG7('M',1,1,1,0,1,1,0), _SEG7('N',1,1,1,0,1,1,0), _SEG7('O',1,1,1,1,1,1,0),\ - _SEG7('P',1,1,0,0,1,1,1), _SEG7('Q',1,1,1,1,1,1,0), _SEG7('R',1,1,1,0,1,1,1),\ - _SEG7('S',1,0,1,1,0,1,1), _SEG7('T',0,0,0,1,1,1,1), _SEG7('U',0,1,1,1,1,1,0),\ - _SEG7('V',0,1,1,1,1,1,0), _SEG7('W',0,1,1,1,1,1,1), _SEG7('X',0,1,1,0,1,1,1),\ - _SEG7('Y',0,1,1,0,0,1,1), _SEG7('Z',1,1,0,1,1,0,1), - -#define _MAP_91_96_ASCII_SEG7_SYMBOL \ - _SEG7('[',1,0,0,1,1,1,0), _SEG7('\\',0,0,1,0,0,1,1),_SEG7(']',1,1,1,1,0,0,0),\ - _SEG7('^',1,1,0,0,0,1,0), _SEG7('_',0,0,0,1,0,0,0), _SEG7('`',0,1,0,0,0,0,0), - -#define _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ - _SEG7('A',1,1,1,0,1,1,1), _SEG7('b',0,0,1,1,1,1,1), _SEG7('c',0,0,0,1,1,0,1),\ - _SEG7('d',0,1,1,1,1,0,1), _SEG7('E',1,0,0,1,1,1,1), _SEG7('F',1,0,0,0,1,1,1),\ - _SEG7('G',1,1,1,1,0,1,1), _SEG7('h',0,0,1,0,1,1,1), _SEG7('i',0,0,1,0,0,0,0),\ - _SEG7('j',0,0,1,1,0,0,0), _SEG7('k',0,0,1,0,1,1,1), _SEG7('L',0,0,0,1,1,1,0),\ - _SEG7('M',1,1,1,0,1,1,0), _SEG7('n',0,0,1,0,1,0,1), _SEG7('o',0,0,1,1,1,0,1),\ - _SEG7('P',1,1,0,0,1,1,1), _SEG7('q',1,1,1,0,0,1,1), _SEG7('r',0,0,0,0,1,0,1),\ - _SEG7('S',1,0,1,1,0,1,1), _SEG7('T',0,0,0,1,1,1,1), _SEG7('u',0,0,1,1,1,0,0),\ - _SEG7('v',0,0,1,1,1,0,0), _SEG7('W',0,1,1,1,1,1,1), _SEG7('X',0,1,1,0,1,1,1),\ - _SEG7('y',0,1,1,1,0,1,1), _SEG7('Z',1,1,0,1,1,0,1), - -#define _MAP_123_126_ASCII_SEG7_SYMBOL \ - _SEG7('{',1,0,0,1,1,1,0), _SEG7('|',0,0,0,0,1,1,0), _SEG7('}',1,1,1,1,0,0,0),\ - _SEG7('~',1,0,0,0,0,0,0), - -/* Maps */ - -/* This set tries to map as close as possible to the visible characteristics - * of the ASCII symbol, lowercase and uppercase letters may differ in - * presentation on the display. - */ -#define MAP_ASCII7SEG_ALPHANUM \ - _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \ - _MAP_33_47_ASCII_SEG7_SYMBOL \ - _MAP_48_57_ASCII_SEG7_NUMERIC \ - _MAP_58_64_ASCII_SEG7_SYMBOL \ - _MAP_65_90_ASCII_SEG7_ALPHA_UPPR \ - _MAP_91_96_ASCII_SEG7_SYMBOL \ - _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ - _MAP_123_126_ASCII_SEG7_SYMBOL - -/* This set tries to map as close as possible to the symbolic characteristics - * of the ASCII character for maximum discrimination. - * For now this means all alpha chars are in lower case representations. - * (This for example facilitates the use of hex numbers with uppercase input.) - */ -#define MAP_ASCII7SEG_ALPHANUM_LC \ - _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \ - _MAP_33_47_ASCII_SEG7_SYMBOL \ - _MAP_48_57_ASCII_SEG7_NUMERIC \ - _MAP_58_64_ASCII_SEG7_SYMBOL \ - _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ - _MAP_91_96_ASCII_SEG7_SYMBOL \ - _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ - _MAP_123_126_ASCII_SEG7_SYMBOL - -#define SEG7_DEFAULT_MAP(_name) \ - SEG7_CONVERSION_MAP(_name,MAP_ASCII7SEG_ALPHANUM) - -#endif /* MAP_TO_7SEGMENT_H */ - diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c deleted file mode 100644 index 448a470d28f2..000000000000 --- a/drivers/usb/input/powermate.c +++ /dev/null @@ -1,463 +0,0 @@ -/* - * A driver for the Griffin Technology, Inc. "PowerMate" USB controller dial. - * - * v1.1, (c)2002 William R Sowerbutts <will@sowerbutts.com> - * - * This device is a anodised aluminium knob which connects over USB. It can measure - * clockwise and anticlockwise rotation. The dial also acts as a pushbutton with - * a spring for automatic release. The base contains a pair of LEDs which illuminate - * the translucent base. It rotates without limit and reports its relative rotation - * back to the host when polled by the USB controller. - * - * Testing with the knob I have has shown that it measures approximately 94 "clicks" - * for one full rotation. Testing with my High Speed Rotation Actuator (ok, it was - * a variable speed cordless electric drill) has shown that the device can measure - * speeds of up to 7 clicks either clockwise or anticlockwise between pollings from - * the host. If it counts more than 7 clicks before it is polled, it will wrap back - * to zero and start counting again. This was at quite high speed, however, almost - * certainly faster than the human hand could turn it. Griffin say that it loses a - * pulse or two on a direction change; the granularity is so fine that I never - * noticed this in practice. - * - * The device's microcontroller can be programmed to set the LED to either a constant - * intensity, or to a rhythmic pulsing. Several patterns and speeds are available. - * - * Griffin were very happy to provide documentation and free hardware for development. - * - * Some userspace tools are available on the web: http://sowerbutts.com/powermate/ - * - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/usb/input.h> - -#define POWERMATE_VENDOR 0x077d /* Griffin Technology, Inc. */ -#define POWERMATE_PRODUCT_NEW 0x0410 /* Griffin PowerMate */ -#define POWERMATE_PRODUCT_OLD 0x04AA /* Griffin soundKnob */ - -#define CONTOUR_VENDOR 0x05f3 /* Contour Design, Inc. */ -#define CONTOUR_JOG 0x0240 /* Jog and Shuttle */ - -/* these are the command codes we send to the device */ -#define SET_STATIC_BRIGHTNESS 0x01 -#define SET_PULSE_ASLEEP 0x02 -#define SET_PULSE_AWAKE 0x03 -#define SET_PULSE_MODE 0x04 - -/* these refer to bits in the powermate_device's requires_update field. */ -#define UPDATE_STATIC_BRIGHTNESS (1<<0) -#define UPDATE_PULSE_ASLEEP (1<<1) -#define UPDATE_PULSE_AWAKE (1<<2) -#define UPDATE_PULSE_MODE (1<<3) - -/* at least two versions of the hardware exist, with differing payload - sizes. the first three bytes always contain the "interesting" data in - the relevant format. */ -#define POWERMATE_PAYLOAD_SIZE_MAX 6 -#define POWERMATE_PAYLOAD_SIZE_MIN 3 -struct powermate_device { - signed char *data; - dma_addr_t data_dma; - struct urb *irq, *config; - struct usb_ctrlrequest *configcr; - dma_addr_t configcr_dma; - struct usb_device *udev; - struct input_dev *input; - spinlock_t lock; - int static_brightness; - int pulse_speed; - int pulse_table; - int pulse_asleep; - int pulse_awake; - int requires_update; // physical settings which are out of sync - char phys[64]; -}; - -static char pm_name_powermate[] = "Griffin PowerMate"; -static char pm_name_soundknob[] = "Griffin SoundKnob"; - -static void powermate_config_complete(struct urb *urb); - -/* Callback for data arriving from the PowerMate over the USB interrupt pipe */ -static void powermate_irq(struct urb *urb) -{ - struct powermate_device *pm = urb->context; - int retval; - - switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); - return; - default: - dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); - goto exit; - } - - /* handle updates to device state */ - input_report_key(pm->input, BTN_0, pm->data[0] & 0x01); - input_report_rel(pm->input, REL_DIAL, pm->data[1]); - input_sync(pm->input); - -exit: - retval = usb_submit_urb (urb, GFP_ATOMIC); - if (retval) - err ("%s - usb_submit_urb failed with result %d", - __FUNCTION__, retval); -} - -/* Decide if we need to issue a control message and do so. Must be called with pm->lock taken */ -static void powermate_sync_state(struct powermate_device *pm) -{ - if (pm->requires_update == 0) - return; /* no updates are required */ - if (pm->config->status == -EINPROGRESS) - return; /* an update is already in progress; it'll issue this update when it completes */ - - if (pm->requires_update & UPDATE_PULSE_ASLEEP){ - pm->configcr->wValue = cpu_to_le16( SET_PULSE_ASLEEP ); - pm->configcr->wIndex = cpu_to_le16( pm->pulse_asleep ? 1 : 0 ); - pm->requires_update &= ~UPDATE_PULSE_ASLEEP; - }else if (pm->requires_update & UPDATE_PULSE_AWAKE){ - pm->configcr->wValue = cpu_to_le16( SET_PULSE_AWAKE ); - pm->configcr->wIndex = cpu_to_le16( pm->pulse_awake ? 1 : 0 ); - pm->requires_update &= ~UPDATE_PULSE_AWAKE; - }else if (pm->requires_update & UPDATE_PULSE_MODE){ - int op, arg; - /* the powermate takes an operation and an argument for its pulse algorithm. - the operation can be: - 0: divide the speed - 1: pulse at normal speed - 2: multiply the speed - the argument only has an effect for operations 0 and 2, and ranges between - 1 (least effect) to 255 (maximum effect). - - thus, several states are equivalent and are coalesced into one state. - - we map this onto a range from 0 to 510, with: - 0 -- 254 -- use divide (0 = slowest) - 255 -- use normal speed - 256 -- 510 -- use multiple (510 = fastest). - - Only values of 'arg' quite close to 255 are particularly useful/spectacular. - */ - if (pm->pulse_speed < 255) { - op = 0; // divide - arg = 255 - pm->pulse_speed; - } else if (pm->pulse_speed > 255) { - op = 2; // multiply - arg = pm->pulse_speed - 255; - } else { - op = 1; // normal speed - arg = 0; // can be any value - } - pm->configcr->wValue = cpu_to_le16( (pm->pulse_table << 8) | SET_PULSE_MODE ); - pm->configcr->wIndex = cpu_to_le16( (arg << 8) | op ); - pm->requires_update &= ~UPDATE_PULSE_MODE; - } else if (pm->requires_update & UPDATE_STATIC_BRIGHTNESS) { - pm->configcr->wValue = cpu_to_le16( SET_STATIC_BRIGHTNESS ); - pm->configcr->wIndex = cpu_to_le16( pm->static_brightness ); - pm->requires_update &= ~UPDATE_STATIC_BRIGHTNESS; - } else { - printk(KERN_ERR "powermate: unknown update required"); - pm->requires_update = 0; /* fudge the bug */ - return; - } - -/* printk("powermate: %04x %04x\n", pm->configcr->wValue, pm->configcr->wIndex); */ - - pm->configcr->bRequestType = 0x41; /* vendor request */ - pm->configcr->bRequest = 0x01; - pm->configcr->wLength = 0; - - usb_fill_control_urb(pm->config, pm->udev, usb_sndctrlpipe(pm->udev, 0), - (void *) pm->configcr, NULL, 0, - powermate_config_complete, pm); - pm->config->setup_dma = pm->configcr_dma; - pm->config->transfer_flags |= URB_NO_SETUP_DMA_MAP; - - if (usb_submit_urb(pm->config, GFP_ATOMIC)) - printk(KERN_ERR "powermate: usb_submit_urb(config) failed"); -} - -/* Called when our asynchronous control message completes. We may need to issue another immediately */ -static void powermate_config_complete(struct urb *urb) -{ - struct powermate_device *pm = urb->context; - unsigned long flags; - - if (urb->status) - printk(KERN_ERR "powermate: config urb returned %d\n", urb->status); - - spin_lock_irqsave(&pm->lock, flags); - powermate_sync_state(pm); - spin_unlock_irqrestore(&pm->lock, flags); -} - -/* Set the LED up as described and begin the sync with the hardware if required */ -static void powermate_pulse_led(struct powermate_device *pm, int static_brightness, int pulse_speed, - int pulse_table, int pulse_asleep, int pulse_awake) -{ - unsigned long flags; - - if (pulse_speed < 0) - pulse_speed = 0; - if (pulse_table < 0) - pulse_table = 0; - if (pulse_speed > 510) - pulse_speed = 510; - if (pulse_table > 2) - pulse_table = 2; - - pulse_asleep = !!pulse_asleep; - pulse_awake = !!pulse_awake; - - - spin_lock_irqsave(&pm->lock, flags); - - /* mark state updates which are required */ - if (static_brightness != pm->static_brightness) { - pm->static_brightness = static_brightness; - pm->requires_update |= UPDATE_STATIC_BRIGHTNESS; - } - if (pulse_asleep != pm->pulse_asleep) { - pm->pulse_asleep = pulse_asleep; - pm->requires_update |= (UPDATE_PULSE_ASLEEP | UPDATE_STATIC_BRIGHTNESS); - } - if (pulse_awake != pm->pulse_awake) { - pm->pulse_awake = pulse_awake; - pm->requires_update |= (UPDATE_PULSE_AWAKE | UPDATE_STATIC_BRIGHTNESS); - } - if (pulse_speed != pm->pulse_speed || pulse_table != pm->pulse_table) { - pm->pulse_speed = pulse_speed; - pm->pulse_table = pulse_table; - pm->requires_update |= UPDATE_PULSE_MODE; - } - - powermate_sync_state(pm); - - spin_unlock_irqrestore(&pm->lock, flags); -} - -/* Callback from the Input layer when an event arrives from userspace to configure the LED */ -static int powermate_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int _value) -{ - unsigned int command = (unsigned int)_value; - struct powermate_device *pm = input_get_drvdata(dev); - - if (type == EV_MSC && code == MSC_PULSELED){ - /* - bits 0- 7: 8 bits: LED brightness - bits 8-16: 9 bits: pulsing speed modifier (0 ... 510); 0-254 = slower, 255 = standard, 256-510 = faster. - bits 17-18: 2 bits: pulse table (0, 1, 2 valid) - bit 19: 1 bit : pulse whilst asleep? - bit 20: 1 bit : pulse constantly? - */ - int static_brightness = command & 0xFF; // bits 0-7 - int pulse_speed = (command >> 8) & 0x1FF; // bits 8-16 - int pulse_table = (command >> 17) & 0x3; // bits 17-18 - int pulse_asleep = (command >> 19) & 0x1; // bit 19 - int pulse_awake = (command >> 20) & 0x1; // bit 20 - - powermate_pulse_led(pm, static_brightness, pulse_speed, pulse_table, pulse_asleep, pulse_awake); - } - - return 0; -} - -static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_device *pm) -{ - pm->data = usb_buffer_alloc(udev, POWERMATE_PAYLOAD_SIZE_MAX, - GFP_ATOMIC, &pm->data_dma); - if (!pm->data) - return -1; - - pm->configcr = usb_buffer_alloc(udev, sizeof(*(pm->configcr)), - GFP_ATOMIC, &pm->configcr_dma); - if (!pm->configcr) - return -1; - - return 0; -} - -static void powermate_free_buffers(struct usb_device *udev, struct powermate_device *pm) -{ - usb_buffer_free(udev, POWERMATE_PAYLOAD_SIZE_MAX, - pm->data, pm->data_dma); - usb_buffer_free(udev, sizeof(*(pm->configcr)), - pm->configcr, pm->configcr_dma); -} - -/* Called whenever a USB device matching one in our supported devices table is connected */ -static int powermate_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev (intf); - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct powermate_device *pm; - struct input_dev *input_dev; - int pipe, maxp; - int error = -ENOMEM; - - interface = intf->cur_altsetting; - endpoint = &interface->endpoint[0].desc; - if (!usb_endpoint_is_int_in(endpoint)) - return -EIO; - - usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0x0a, USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, interface->desc.bInterfaceNumber, NULL, 0, - USB_CTRL_SET_TIMEOUT); - - pm = kzalloc(sizeof(struct powermate_device), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!pm || !input_dev) - goto fail1; - - if (powermate_alloc_buffers(udev, pm)) - goto fail2; - - pm->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!pm->irq) - goto fail2; - - pm->config = usb_alloc_urb(0, GFP_KERNEL); - if (!pm->config) - goto fail3; - - pm->udev = udev; - pm->input = input_dev; - - usb_make_path(udev, pm->phys, sizeof(pm->phys)); - strlcpy(pm->phys, "/input0", sizeof(pm->phys)); - - spin_lock_init(&pm->lock); - - switch (le16_to_cpu(udev->descriptor.idProduct)) { - case POWERMATE_PRODUCT_NEW: - input_dev->name = pm_name_powermate; - break; - case POWERMATE_PRODUCT_OLD: - input_dev->name = pm_name_soundknob; - break; - default: - input_dev->name = pm_name_soundknob; - printk(KERN_WARNING "powermate: unknown product id %04x\n", - le16_to_cpu(udev->descriptor.idProduct)); - } - - input_dev->phys = pm->phys; - usb_to_input_id(udev, &input_dev->id); - input_dev->dev.parent = &intf->dev; - - input_set_drvdata(input_dev, pm); - - input_dev->event = powermate_input_event; - - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_MSC); - input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0); - input_dev->relbit[LONG(REL_DIAL)] = BIT(REL_DIAL); - input_dev->mscbit[LONG(MSC_PULSELED)] = BIT(MSC_PULSELED); - - /* get a handle to the interrupt data pipe */ - pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); - - if (maxp < POWERMATE_PAYLOAD_SIZE_MIN || maxp > POWERMATE_PAYLOAD_SIZE_MAX) { - printk(KERN_WARNING "powermate: Expected payload of %d--%d bytes, found %d bytes!\n", - POWERMATE_PAYLOAD_SIZE_MIN, POWERMATE_PAYLOAD_SIZE_MAX, maxp); - maxp = POWERMATE_PAYLOAD_SIZE_MAX; - } - - usb_fill_int_urb(pm->irq, udev, pipe, pm->data, - maxp, powermate_irq, - pm, endpoint->bInterval); - pm->irq->transfer_dma = pm->data_dma; - pm->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - /* register our interrupt URB with the USB system */ - if (usb_submit_urb(pm->irq, GFP_KERNEL)) { - error = -EIO; - goto fail4; - } - - error = input_register_device(pm->input); - if (error) - goto fail5; - - - /* force an update of everything */ - pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS; - powermate_pulse_led(pm, 0x80, 255, 0, 1, 0); // set default pulse parameters - - usb_set_intfdata(intf, pm); - return 0; - - fail5: usb_kill_urb(pm->irq); - fail4: usb_free_urb(pm->config); - fail3: usb_free_urb(pm->irq); - fail2: powermate_free_buffers(udev, pm); - fail1: input_free_device(input_dev); - kfree(pm); - return error; -} - -/* Called when a USB device we've accepted ownership of is removed */ -static void powermate_disconnect(struct usb_interface *intf) -{ - struct powermate_device *pm = usb_get_intfdata (intf); - - usb_set_intfdata(intf, NULL); - if (pm) { - pm->requires_update = 0; - usb_kill_urb(pm->irq); - input_unregister_device(pm->input); - usb_free_urb(pm->irq); - usb_free_urb(pm->config); - powermate_free_buffers(interface_to_usbdev(intf), pm); - - kfree(pm); - } -} - -static struct usb_device_id powermate_devices [] = { - { USB_DEVICE(POWERMATE_VENDOR, POWERMATE_PRODUCT_NEW) }, - { USB_DEVICE(POWERMATE_VENDOR, POWERMATE_PRODUCT_OLD) }, - { USB_DEVICE(CONTOUR_VENDOR, CONTOUR_JOG) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, powermate_devices); - -static struct usb_driver powermate_driver = { - .name = "powermate", - .probe = powermate_probe, - .disconnect = powermate_disconnect, - .id_table = powermate_devices, -}; - -static int __init powermate_init(void) -{ - return usb_register(&powermate_driver); -} - -static void __exit powermate_cleanup(void) -{ - usb_deregister(&powermate_driver); -} - -module_init(powermate_init); -module_exit(powermate_cleanup); - -MODULE_AUTHOR( "William R Sowerbutts" ); -MODULE_DESCRIPTION( "Griffin Technology, Inc PowerMate driver" ); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c deleted file mode 100644 index fc645b299189..000000000000 --- a/drivers/usb/input/yealink.c +++ /dev/null @@ -1,1004 +0,0 @@ -/* - * drivers/usb/input/yealink.c - * - * Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com> - * - * 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 - */ -/* - * Description: - * Driver for the USB-P1K voip usb phone. - * This device is produced by Yealink Network Technology Co Ltd - * but may be branded under several names: - * - Yealink usb-p1k - * - Tiptel 115 - * - ... - * - * This driver is based on: - * - the usbb2k-api http://savannah.nongnu.org/projects/usbb2k-api/ - * - information from http://memeteau.free.fr/usbb2k - * - the xpad-driver drivers/usb/input/xpad.c - * - * Thanks to: - * - Olivier Vandorpe, for providing the usbb2k-api. - * - Martin Diehl, for spotting my memory allocation bug. - * - * History: - * 20050527 henk First version, functional keyboard. Keyboard events - * will pop-up on the ../input/eventX bus. - * 20050531 henk Added led, LCD, dialtone and sysfs interface. - * 20050610 henk Cleanups, make it ready for public consumption. - * 20050630 henk Cleanups, fixes in response to comments. - * 20050701 henk sysfs write serialisation, fix potential unload races - * 20050801 henk Added ringtone, restructure USB - * 20050816 henk Merge 2.6.13-rc6 - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/rwsem.h> -#include <linux/usb/input.h> - -#include "map_to_7segment.h" -#include "yealink.h" - -#define DRIVER_VERSION "yld-20051230" -#define DRIVER_AUTHOR "Henk Vergonet" -#define DRIVER_DESC "Yealink phone driver" - -#define YEALINK_POLLING_FREQUENCY 10 /* in [Hz] */ - -struct yld_status { - u8 lcd[24]; - u8 led; - u8 dialtone; - u8 ringtone; - u8 keynum; -} __attribute__ ((packed)); - -/* - * Register the LCD segment and icon map - */ -#define _LOC(k,l) { .a = (k), .m = (l) } -#define _SEG(t, a, am, b, bm, c, cm, d, dm, e, em, f, fm, g, gm) \ - { .type = (t), \ - .u = { .s = { _LOC(a, am), _LOC(b, bm), _LOC(c, cm), \ - _LOC(d, dm), _LOC(e, em), _LOC(g, gm), \ - _LOC(f, fm) } } } -#define _PIC(t, h, hm, n) \ - { .type = (t), \ - .u = { .p = { .name = (n), .a = (h), .m = (hm) } } } - -static const struct lcd_segment_map { - char type; - union { - struct pictogram_map { - u8 a,m; - char name[10]; - } p; - struct segment_map { - u8 a,m; - } s[7]; - } u; -} lcdMap[] = { -#include "yealink.h" -}; - -struct yealink_dev { - struct input_dev *idev; /* input device */ - struct usb_device *udev; /* usb device */ - - /* irq input channel */ - struct yld_ctl_packet *irq_data; - dma_addr_t irq_dma; - struct urb *urb_irq; - - /* control output channel */ - struct yld_ctl_packet *ctl_data; - dma_addr_t ctl_dma; - struct usb_ctrlrequest *ctl_req; - dma_addr_t ctl_req_dma; - struct urb *urb_ctl; - - char phys[64]; /* physical device path */ - - u8 lcdMap[ARRAY_SIZE(lcdMap)]; /* state of LCD, LED ... */ - int key_code; /* last reported key */ - - int stat_ix; - union { - struct yld_status s; - u8 b[sizeof(struct yld_status)]; - } master, copy; -}; - - -/******************************************************************************* - * Yealink lcd interface - ******************************************************************************/ - -/* - * Register a default 7 segment character set - */ -static SEG7_DEFAULT_MAP(map_seg7); - - /* Display a char, - * char '\9' and '\n' are placeholders and do not overwrite the original text. - * A space will always hide an icon. - */ -static int setChar(struct yealink_dev *yld, int el, int chr) -{ - int i, a, m, val; - - if (el >= ARRAY_SIZE(lcdMap)) - return -EINVAL; - - if (chr == '\t' || chr == '\n') - return 0; - - yld->lcdMap[el] = chr; - - if (lcdMap[el].type == '.') { - a = lcdMap[el].u.p.a; - m = lcdMap[el].u.p.m; - if (chr != ' ') - yld->master.b[a] |= m; - else - yld->master.b[a] &= ~m; - return 0; - } - - val = map_to_seg7(&map_seg7, chr); - for (i = 0; i < ARRAY_SIZE(lcdMap[0].u.s); i++) { - m = lcdMap[el].u.s[i].m; - - if (m == 0) - continue; - - a = lcdMap[el].u.s[i].a; - if (val & 1) - yld->master.b[a] |= m; - else - yld->master.b[a] &= ~m; - val = val >> 1; - } - return 0; -}; - -/******************************************************************************* - * Yealink key interface - ******************************************************************************/ - -/* Map device buttons to internal key events. - * - * USB-P1K button layout: - * - * up - * IN OUT - * down - * - * pickup C hangup - * 1 2 3 - * 4 5 6 - * 7 8 9 - * * 0 # - * - * The "up" and "down" keys, are symbolised by arrows on the button. - * The "pickup" and "hangup" keys are symbolised by a green and red phone - * on the button. - */ -static int map_p1k_to_key(int scancode) -{ - switch(scancode) { /* phone key: */ - case 0x23: return KEY_LEFT; /* IN */ - case 0x33: return KEY_UP; /* up */ - case 0x04: return KEY_RIGHT; /* OUT */ - case 0x24: return KEY_DOWN; /* down */ - case 0x03: return KEY_ENTER; /* pickup */ - case 0x14: return KEY_BACKSPACE; /* C */ - case 0x13: return KEY_ESC; /* hangup */ - case 0x00: return KEY_1; /* 1 */ - case 0x01: return KEY_2; /* 2 */ - case 0x02: return KEY_3; /* 3 */ - case 0x10: return KEY_4; /* 4 */ - case 0x11: return KEY_5; /* 5 */ - case 0x12: return KEY_6; /* 6 */ - case 0x20: return KEY_7; /* 7 */ - case 0x21: return KEY_8; /* 8 */ - case 0x22: return KEY_9; /* 9 */ - case 0x30: return KEY_KPASTERISK; /* * */ - case 0x31: return KEY_0; /* 0 */ - case 0x32: return KEY_LEFTSHIFT | - KEY_3 << 8; /* # */ - } - return -EINVAL; -} - -/* Completes a request by converting the data into events for the - * input subsystem. - * - * The key parameter can be cascaded: key2 << 8 | key1 - */ -static void report_key(struct yealink_dev *yld, int key) -{ - struct input_dev *idev = yld->idev; - - if (yld->key_code >= 0) { - /* old key up */ - input_report_key(idev, yld->key_code & 0xff, 0); - if (yld->key_code >> 8) - input_report_key(idev, yld->key_code >> 8, 0); - } - - yld->key_code = key; - if (key >= 0) { - /* new valid key */ - input_report_key(idev, key & 0xff, 1); - if (key >> 8) - input_report_key(idev, key >> 8, 1); - } - input_sync(idev); -} - -/******************************************************************************* - * Yealink usb communication interface - ******************************************************************************/ - -static int yealink_cmd(struct yealink_dev *yld, struct yld_ctl_packet *p) -{ - u8 *buf = (u8 *)p; - int i; - u8 sum = 0; - - for(i=0; i<USB_PKT_LEN-1; i++) - sum -= buf[i]; - p->sum = sum; - return usb_control_msg(yld->udev, - usb_sndctrlpipe(yld->udev, 0), - USB_REQ_SET_CONFIGURATION, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, - 0x200, 3, - p, sizeof(*p), - USB_CTRL_SET_TIMEOUT); -} - -static u8 default_ringtone[] = { - 0xEF, /* volume [0-255] */ - 0xFB, 0x1E, 0x00, 0x0C, /* 1250 [hz], 12/100 [s] */ - 0xFC, 0x18, 0x00, 0x0C, /* 1000 [hz], 12/100 [s] */ - 0xFB, 0x1E, 0x00, 0x0C, - 0xFC, 0x18, 0x00, 0x0C, - 0xFB, 0x1E, 0x00, 0x0C, - 0xFC, 0x18, 0x00, 0x0C, - 0xFB, 0x1E, 0x00, 0x0C, - 0xFC, 0x18, 0x00, 0x0C, - 0xFF, 0xFF, 0x01, 0x90, /* silent, 400/100 [s] */ - 0x00, 0x00 /* end of sequence */ -}; - -static int yealink_set_ringtone(struct yealink_dev *yld, u8 *buf, size_t size) -{ - struct yld_ctl_packet *p = yld->ctl_data; - int ix, len; - - if (size <= 0) - return -EINVAL; - - /* Set the ringtone volume */ - memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data))); - yld->ctl_data->cmd = CMD_RING_VOLUME; - yld->ctl_data->size = 1; - yld->ctl_data->data[0] = buf[0]; - yealink_cmd(yld, p); - - buf++; - size--; - - p->cmd = CMD_RING_NOTE; - ix = 0; - while (size != ix) { - len = size - ix; - if (len > sizeof(p->data)) - len = sizeof(p->data); - p->size = len; - p->offset = cpu_to_be16(ix); - memcpy(p->data, &buf[ix], len); - yealink_cmd(yld, p); - ix += len; - } - return 0; -} - -/* keep stat_master & stat_copy in sync. - */ -static int yealink_do_idle_tasks(struct yealink_dev *yld) -{ - u8 val; - int i, ix, len; - - ix = yld->stat_ix; - - memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data))); - yld->ctl_data->cmd = CMD_KEYPRESS; - yld->ctl_data->size = 1; - yld->ctl_data->sum = 0xff - CMD_KEYPRESS; - - /* If state update pointer wraps do a KEYPRESS first. */ - if (ix >= sizeof(yld->master)) { - yld->stat_ix = 0; - return 0; - } - - /* find update candidates: copy != master */ - do { - val = yld->master.b[ix]; - if (val != yld->copy.b[ix]) - goto send_update; - } while (++ix < sizeof(yld->master)); - - /* nothing todo, wait a bit and poll for a KEYPRESS */ - yld->stat_ix = 0; - /* TODO how can we wait abit. ?? - * msleep_interruptible(1000 / YEALINK_POLLING_FREQUENCY); - */ - return 0; - -send_update: - - /* Setup an appropriate update request */ - yld->copy.b[ix] = val; - yld->ctl_data->data[0] = val; - - switch(ix) { - case offsetof(struct yld_status, led): - yld->ctl_data->cmd = CMD_LED; - yld->ctl_data->sum = -1 - CMD_LED - val; - break; - case offsetof(struct yld_status, dialtone): - yld->ctl_data->cmd = CMD_DIALTONE; - yld->ctl_data->sum = -1 - CMD_DIALTONE - val; - break; - case offsetof(struct yld_status, ringtone): - yld->ctl_data->cmd = CMD_RINGTONE; - yld->ctl_data->sum = -1 - CMD_RINGTONE - val; - break; - case offsetof(struct yld_status, keynum): - val--; - val &= 0x1f; - yld->ctl_data->cmd = CMD_SCANCODE; - yld->ctl_data->offset = cpu_to_be16(val); - yld->ctl_data->data[0] = 0; - yld->ctl_data->sum = -1 - CMD_SCANCODE - val; - break; - default: - len = sizeof(yld->master.s.lcd) - ix; - if (len > sizeof(yld->ctl_data->data)) - len = sizeof(yld->ctl_data->data); - - /* Combine up to <len> consecutive LCD bytes in a singe request - */ - yld->ctl_data->cmd = CMD_LCD; - yld->ctl_data->offset = cpu_to_be16(ix); - yld->ctl_data->size = len; - yld->ctl_data->sum = -CMD_LCD - ix - val - len; - for(i=1; i<len; i++) { - ix++; - val = yld->master.b[ix]; - yld->copy.b[ix] = val; - yld->ctl_data->data[i] = val; - yld->ctl_data->sum -= val; - } - } - yld->stat_ix = ix + 1; - return 1; -} - -/* Decide on how to handle responses - * - * The state transition diagram is somethhing like: - * - * syncState<--+ - * | | - * | idle - * \|/ | - * init --ok--> waitForKey --ok--> getKey - * ^ ^ | - * | +-------ok-------+ - * error,start - * - */ -static void urb_irq_callback(struct urb *urb) -{ - struct yealink_dev *yld = urb->context; - int ret; - - if (urb->status) - err("%s - urb status %d", __FUNCTION__, urb->status); - - switch (yld->irq_data->cmd) { - case CMD_KEYPRESS: - - yld->master.s.keynum = yld->irq_data->data[0]; - break; - - case CMD_SCANCODE: - dbg("get scancode %x", yld->irq_data->data[0]); - - report_key(yld, map_p1k_to_key(yld->irq_data->data[0])); - break; - - default: - err("unexpected response %x", yld->irq_data->cmd); - } - - yealink_do_idle_tasks(yld); - - ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC); - if (ret) - err("%s - usb_submit_urb failed %d", __FUNCTION__, ret); -} - -static void urb_ctl_callback(struct urb *urb) -{ - struct yealink_dev *yld = urb->context; - int ret; - - if (urb->status) - err("%s - urb status %d", __FUNCTION__, urb->status); - - switch (yld->ctl_data->cmd) { - case CMD_KEYPRESS: - case CMD_SCANCODE: - /* ask for a response */ - ret = usb_submit_urb(yld->urb_irq, GFP_ATOMIC); - break; - default: - /* send new command */ - yealink_do_idle_tasks(yld); - ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC); - } - - if (ret) - err("%s - usb_submit_urb failed %d", __FUNCTION__, ret); -} - -/******************************************************************************* - * input event interface - ******************************************************************************/ - -/* TODO should we issue a ringtone on a SND_BELL event? -static int input_ev(struct input_dev *dev, unsigned int type, - unsigned int code, int value) -{ - - if (type != EV_SND) - return -EINVAL; - - switch (code) { - case SND_BELL: - case SND_TONE: - break; - default: - return -EINVAL; - } - - return 0; -} -*/ - -static int input_open(struct input_dev *dev) -{ - struct yealink_dev *yld = input_get_drvdata(dev); - int i, ret; - - dbg("%s", __FUNCTION__); - - /* force updates to device */ - for (i = 0; i<sizeof(yld->master); i++) - yld->copy.b[i] = ~yld->master.b[i]; - yld->key_code = -1; /* no keys pressed */ - - yealink_set_ringtone(yld, default_ringtone, sizeof(default_ringtone)); - - /* issue INIT */ - memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data))); - yld->ctl_data->cmd = CMD_INIT; - yld->ctl_data->size = 10; - yld->ctl_data->sum = 0x100-CMD_INIT-10; - if ((ret = usb_submit_urb(yld->urb_ctl, GFP_KERNEL)) != 0) { - dbg("%s - usb_submit_urb failed with result %d", - __FUNCTION__, ret); - return ret; - } - return 0; -} - -static void input_close(struct input_dev *dev) -{ - struct yealink_dev *yld = input_get_drvdata(dev); - - usb_kill_urb(yld->urb_ctl); - usb_kill_urb(yld->urb_irq); -} - -/******************************************************************************* - * sysfs interface - ******************************************************************************/ - -static DECLARE_RWSEM(sysfs_rwsema); - -/* Interface to the 7-segments translation table aka. char set. - */ -static ssize_t show_map(struct device *dev, struct device_attribute *attr, - char *buf) -{ - memcpy(buf, &map_seg7, sizeof(map_seg7)); - return sizeof(map_seg7); -} - -static ssize_t store_map(struct device *dev, struct device_attribute *attr, - const char *buf, size_t cnt) -{ - if (cnt != sizeof(map_seg7)) - return -EINVAL; - memcpy(&map_seg7, buf, sizeof(map_seg7)); - return sizeof(map_seg7); -} - -/* Interface to the LCD. - */ - -/* Reading /sys/../lineX will return the format string with its settings: - * - * Example: - * cat ./line3 - * 888888888888 - * Linux Rocks! - */ -static ssize_t show_line(struct device *dev, char *buf, int a, int b) -{ - struct yealink_dev *yld; - int i; - - down_read(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_read(&sysfs_rwsema); - return -ENODEV; - } - - for (i = a; i < b; i++) - *buf++ = lcdMap[i].type; - *buf++ = '\n'; - for (i = a; i < b; i++) - *buf++ = yld->lcdMap[i]; - *buf++ = '\n'; - *buf = 0; - - up_read(&sysfs_rwsema); - return 3 + ((b - a) << 1); -} - -static ssize_t show_line1(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return show_line(dev, buf, LCD_LINE1_OFFSET, LCD_LINE2_OFFSET); -} - -static ssize_t show_line2(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return show_line(dev, buf, LCD_LINE2_OFFSET, LCD_LINE3_OFFSET); -} - -static ssize_t show_line3(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return show_line(dev, buf, LCD_LINE3_OFFSET, LCD_LINE4_OFFSET); -} - -/* Writing to /sys/../lineX will set the coresponding LCD line. - * - Excess characters are ignored. - * - If less characters are written than allowed, the remaining digits are - * unchanged. - * - The '\n' or '\t' char is a placeholder, it does not overwrite the - * original content. - */ -static ssize_t store_line(struct device *dev, const char *buf, size_t count, - int el, size_t len) -{ - struct yealink_dev *yld; - int i; - - down_write(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_write(&sysfs_rwsema); - return -ENODEV; - } - - if (len > count) - len = count; - for (i = 0; i < len; i++) - setChar(yld, el++, buf[i]); - - up_write(&sysfs_rwsema); - return count; -} - -static ssize_t store_line1(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - return store_line(dev, buf, count, LCD_LINE1_OFFSET, LCD_LINE1_SIZE); -} - -static ssize_t store_line2(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - return store_line(dev, buf, count, LCD_LINE2_OFFSET, LCD_LINE2_SIZE); -} - -static ssize_t store_line3(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - return store_line(dev, buf, count, LCD_LINE3_OFFSET, LCD_LINE3_SIZE); -} - -/* Interface to visible and audible "icons", these include: - * pictures on the LCD, the LED, and the dialtone signal. - */ - -/* Get a list of "switchable elements" with their current state. */ -static ssize_t get_icons(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct yealink_dev *yld; - int i, ret = 1; - - down_read(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_read(&sysfs_rwsema); - return -ENODEV; - } - - for (i = 0; i < ARRAY_SIZE(lcdMap); i++) { - if (lcdMap[i].type != '.') - continue; - ret += sprintf(&buf[ret], "%s %s\n", - yld->lcdMap[i] == ' ' ? " " : "on", - lcdMap[i].u.p.name); - } - up_read(&sysfs_rwsema); - return ret; -} - -/* Change the visibility of a particular element. */ -static ssize_t set_icon(struct device *dev, const char *buf, size_t count, - int chr) -{ - struct yealink_dev *yld; - int i; - - down_write(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_write(&sysfs_rwsema); - return -ENODEV; - } - - for (i = 0; i < ARRAY_SIZE(lcdMap); i++) { - if (lcdMap[i].type != '.') - continue; - if (strncmp(buf, lcdMap[i].u.p.name, count) == 0) { - setChar(yld, i, chr); - break; - } - } - - up_write(&sysfs_rwsema); - return count; -} - -static ssize_t show_icon(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - return set_icon(dev, buf, count, buf[0]); -} - -static ssize_t hide_icon(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - return set_icon(dev, buf, count, ' '); -} - -/* Upload a ringtone to the device. - */ - -/* Stores raw ringtone data in the phone */ -static ssize_t store_ringtone(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct yealink_dev *yld; - - down_write(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_write(&sysfs_rwsema); - return -ENODEV; - } - - /* TODO locking with async usb control interface??? */ - yealink_set_ringtone(yld, (char *)buf, count); - up_write(&sysfs_rwsema); - return count; -} - -#define _M444 S_IRUGO -#define _M664 S_IRUGO|S_IWUSR|S_IWGRP -#define _M220 S_IWUSR|S_IWGRP - -static DEVICE_ATTR(map_seg7 , _M664, show_map , store_map ); -static DEVICE_ATTR(line1 , _M664, show_line1 , store_line1 ); -static DEVICE_ATTR(line2 , _M664, show_line2 , store_line2 ); -static DEVICE_ATTR(line3 , _M664, show_line3 , store_line3 ); -static DEVICE_ATTR(get_icons , _M444, get_icons , NULL ); -static DEVICE_ATTR(show_icon , _M220, NULL , show_icon ); -static DEVICE_ATTR(hide_icon , _M220, NULL , hide_icon ); -static DEVICE_ATTR(ringtone , _M220, NULL , store_ringtone); - -static struct attribute *yld_attributes[] = { - &dev_attr_line1.attr, - &dev_attr_line2.attr, - &dev_attr_line3.attr, - &dev_attr_get_icons.attr, - &dev_attr_show_icon.attr, - &dev_attr_hide_icon.attr, - &dev_attr_map_seg7.attr, - &dev_attr_ringtone.attr, - NULL -}; - -static struct attribute_group yld_attr_group = { - .attrs = yld_attributes -}; - -/******************************************************************************* - * Linux interface and usb initialisation - ******************************************************************************/ - -struct driver_info { - char *name; -}; - -static const struct driver_info info_P1K = { - .name = "Yealink usb-p1k", -}; - -static const struct usb_device_id usb_table [] = { - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | - USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x6993, - .idProduct = 0xb001, - .bInterfaceClass = USB_CLASS_HID, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .driver_info = (kernel_ulong_t)&info_P1K - }, - { } -}; - -static int usb_cleanup(struct yealink_dev *yld, int err) -{ - if (yld == NULL) - return err; - - usb_kill_urb(yld->urb_irq); /* parameter validation in core/urb */ - usb_kill_urb(yld->urb_ctl); /* parameter validation in core/urb */ - - if (yld->idev) { - if (err) - input_free_device(yld->idev); - else - input_unregister_device(yld->idev); - } - - usb_free_urb(yld->urb_irq); - usb_free_urb(yld->urb_ctl); - - usb_buffer_free(yld->udev, sizeof(*(yld->ctl_req)), - yld->ctl_req, yld->ctl_req_dma); - usb_buffer_free(yld->udev, USB_PKT_LEN, - yld->ctl_data, yld->ctl_dma); - usb_buffer_free(yld->udev, USB_PKT_LEN, - yld->irq_data, yld->irq_dma); - - kfree(yld); - return err; -} - -static void usb_disconnect(struct usb_interface *intf) -{ - struct yealink_dev *yld; - - down_write(&sysfs_rwsema); - yld = usb_get_intfdata(intf); - sysfs_remove_group(&intf->dev.kobj, &yld_attr_group); - usb_set_intfdata(intf, NULL); - up_write(&sysfs_rwsema); - - usb_cleanup(yld, 0); -} - -static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev (intf); - struct driver_info *nfo = (struct driver_info *)id->driver_info; - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct yealink_dev *yld; - struct input_dev *input_dev; - int ret, pipe, i; - - interface = intf->cur_altsetting; - endpoint = &interface->endpoint[0].desc; - if (!usb_endpoint_is_int_in(endpoint)) - return -ENODEV; - - yld = kzalloc(sizeof(struct yealink_dev), GFP_KERNEL); - if (!yld) - return -ENOMEM; - - yld->udev = udev; - - yld->idev = input_dev = input_allocate_device(); - if (!input_dev) - return usb_cleanup(yld, -ENOMEM); - - /* allocate usb buffers */ - yld->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN, - GFP_ATOMIC, &yld->irq_dma); - if (yld->irq_data == NULL) - return usb_cleanup(yld, -ENOMEM); - - yld->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN, - GFP_ATOMIC, &yld->ctl_dma); - if (!yld->ctl_data) - return usb_cleanup(yld, -ENOMEM); - - yld->ctl_req = usb_buffer_alloc(udev, sizeof(*(yld->ctl_req)), - GFP_ATOMIC, &yld->ctl_req_dma); - if (yld->ctl_req == NULL) - return usb_cleanup(yld, -ENOMEM); - - /* allocate urb structures */ - yld->urb_irq = usb_alloc_urb(0, GFP_KERNEL); - if (yld->urb_irq == NULL) - return usb_cleanup(yld, -ENOMEM); - - yld->urb_ctl = usb_alloc_urb(0, GFP_KERNEL); - if (yld->urb_ctl == NULL) - return usb_cleanup(yld, -ENOMEM); - - /* get a handle to the interrupt data pipe */ - pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); - ret = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); - if (ret != USB_PKT_LEN) - err("invalid payload size %d, expected %zd", ret, USB_PKT_LEN); - - /* initialise irq urb */ - usb_fill_int_urb(yld->urb_irq, udev, pipe, yld->irq_data, - USB_PKT_LEN, - urb_irq_callback, - yld, endpoint->bInterval); - yld->urb_irq->transfer_dma = yld->irq_dma; - yld->urb_irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - yld->urb_irq->dev = udev; - - /* initialise ctl urb */ - yld->ctl_req->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | - USB_DIR_OUT; - yld->ctl_req->bRequest = USB_REQ_SET_CONFIGURATION; - yld->ctl_req->wValue = cpu_to_le16(0x200); - yld->ctl_req->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber); - yld->ctl_req->wLength = cpu_to_le16(USB_PKT_LEN); - - usb_fill_control_urb(yld->urb_ctl, udev, usb_sndctrlpipe(udev, 0), - (void *)yld->ctl_req, yld->ctl_data, USB_PKT_LEN, - urb_ctl_callback, yld); - yld->urb_ctl->setup_dma = yld->ctl_req_dma; - yld->urb_ctl->transfer_dma = yld->ctl_dma; - yld->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP | - URB_NO_TRANSFER_DMA_MAP; - yld->urb_ctl->dev = udev; - - /* find out the physical bus location */ - usb_make_path(udev, yld->phys, sizeof(yld->phys)); - strlcat(yld->phys, "/input0", sizeof(yld->phys)); - - /* register settings for the input device */ - input_dev->name = nfo->name; - input_dev->phys = yld->phys; - usb_to_input_id(udev, &input_dev->id); - input_dev->dev.parent = &intf->dev; - - input_set_drvdata(input_dev, yld); - - input_dev->open = input_open; - input_dev->close = input_close; - /* input_dev->event = input_ev; TODO */ - - /* register available key events */ - input_dev->evbit[0] = BIT(EV_KEY); - for (i = 0; i < 256; i++) { - int k = map_p1k_to_key(i); - if (k >= 0) { - set_bit(k & 0xff, input_dev->keybit); - if (k >> 8) - set_bit(k >> 8, input_dev->keybit); - } - } - - ret = input_register_device(yld->idev); - if (ret) - return usb_cleanup(yld, ret); - - usb_set_intfdata(intf, yld); - - /* clear visible elements */ - for (i = 0; i < ARRAY_SIZE(lcdMap); i++) - setChar(yld, i, ' '); - - /* display driver version on LCD line 3 */ - store_line3(&intf->dev, NULL, - DRIVER_VERSION, sizeof(DRIVER_VERSION)); - - /* Register sysfs hooks (don't care about failure) */ - ret = sysfs_create_group(&intf->dev.kobj, &yld_attr_group); - return 0; -} - -static struct usb_driver yealink_driver = { - .name = "yealink", - .probe = usb_probe, - .disconnect = usb_disconnect, - .id_table = usb_table, -}; - -static int __init yealink_dev_init(void) -{ - int ret = usb_register(&yealink_driver); - if (ret == 0) - info(DRIVER_DESC ":" DRIVER_VERSION); - return ret; -} - -static void __exit yealink_dev_exit(void) -{ - usb_deregister(&yealink_driver); -} - -module_init(yealink_dev_init); -module_exit(yealink_dev_exit); - -MODULE_DEVICE_TABLE (usb, usb_table); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/input/yealink.h b/drivers/usb/input/yealink.h deleted file mode 100644 index 48af0be9cbdf..000000000000 --- a/drivers/usb/input/yealink.h +++ /dev/null @@ -1,220 +0,0 @@ -/* - * drivers/usb/input/yealink.h - * - * Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com> - * - * - * 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 - */ -#ifndef INPUT_YEALINK_H -#define INPUT_YEALINK_H - -/* Using the control channel on interface 3 various aspects of the phone - * can be controlled like LCD, LED, dialtone and the ringtone. - */ - -struct yld_ctl_packet { - u8 cmd; /* command code, see below */ - u8 size; /* 1-11, size of used data bytes. */ - u16 offset; /* internal packet offset */ - u8 data[11]; - s8 sum; /* negative sum of 15 preceding bytes */ -} __attribute__ ((packed)); - -#define USB_PKT_LEN sizeof(struct yld_ctl_packet) - -/* The following yld_ctl_packet's are available: */ - -/* Init registers - * - * cmd 0x8e - * size 10 - * offset 0 - * data 0,0,0,0.... - */ -#define CMD_INIT 0x8e - -/* Request key scan - * - * cmd 0x80 - * size 1 - * offset 0 - * data[0] on return returns the key number, if it changes there's a new - * key pressed. - */ -#define CMD_KEYPRESS 0x80 - -/* Request scancode - * - * cmd 0x81 - * size 1 - * offset key number [0-1f] - * data[0] on return returns the scancode - */ -#define CMD_SCANCODE 0x81 - -/* Set LCD - * - * cmd 0x04 - * size 1-11 - * offset 0-23 - * data segment bits - */ -#define CMD_LCD 0x04 - -/* Set led - * - * cmd 0x05 - * size 1 - * offset 0 - * data[0] 0 OFF / 1 ON - */ -#define CMD_LED 0x05 - -/* Set ringtone volume - * - * cmd 0x11 - * size 1 - * offset 0 - * data[0] 0-0xff volume - */ -#define CMD_RING_VOLUME 0x11 - -/* Set ringtone notes - * - * cmd 0x02 - * size 1-11 - * offset 0-> - * data binary representation LE16(-freq), LE16(duration) .... - */ -#define CMD_RING_NOTE 0x02 - -/* Sound ringtone via the speaker on the back - * - * cmd 0x03 - * size 1 - * offset 0 - * data[0] 0 OFF / 0x24 ON - */ -#define CMD_RINGTONE 0x03 - -/* Sound dial tone via the ear speaker - * - * cmd 0x09 - * size 1 - * offset 0 - * data[0] 0 OFF / 1 ON - */ -#define CMD_DIALTONE 0x09 - -#endif /* INPUT_YEALINK_H */ - - -#if defined(_SEG) && defined(_PIC) -/* This table maps the LCD segments onto individual bit positions in the - * yld_status struct. - */ - -/* LCD, each segment must be driven seperately. - * - * Layout: - * - * |[] [][] [][] [][] in |[][] - * |[] M [][] D [][] : [][] out |[][] - * store - * - * NEW REP SU MO TU WE TH FR SA - * - * [] [] [] [] [] [] [] [] [] [] [] [] - * [] [] [] [] [] [] [] [] [] [] [] [] - */ - -/* Line 1 - * Format : 18.e8.M8.88...188 - * Icon names : M D : IN OUT STORE - */ -#define LCD_LINE1_OFFSET 0 -#define LCD_LINE1_SIZE 17 - -/* Note: first g then f => ! ! */ -/* _SEG( type a b c d e g f ) */ - _SEG('1', 0,0 , 22,2 , 22,2 , 0,0 , 0,0 , 0,0 , 0,0 ), - _SEG('8', 20,1 , 20,2 , 20,4 , 20,8 , 21,4 , 21,2 , 21,1 ), - _PIC('.', 22,1 , "M" ), - _SEG('e', 18,1 , 18,2 , 18,4 , 18,1 , 19,2 , 18,1 , 19,1 ), - _SEG('8', 16,1 , 16,2 , 16,4 , 16,8 , 17,4 , 17,2 , 17,1 ), - _PIC('.', 15,8 , "D" ), - _SEG('M', 14,1 , 14,2 , 14,4 , 14,1 , 15,4 , 15,2 , 15,1 ), - _SEG('8', 12,1 , 12,2 , 12,4 , 12,8 , 13,4 , 13,2 , 13,1 ), - _PIC('.', 11,8 , ":" ), - _SEG('8', 10,1 , 10,2 , 10,4 , 10,8 , 11,4 , 11,2 , 11,1 ), - _SEG('8', 8,1 , 8,2 , 8,4 , 8,8 , 9,4 , 9,2 , 9,1 ), - _PIC('.', 7,1 , "IN" ), - _PIC('.', 7,2 , "OUT" ), - _PIC('.', 7,4 , "STORE" ), - _SEG('1', 0,0 , 5,1 , 5,1 , 0,0 , 0,0 , 0,0 , 0,0 ), - _SEG('8', 4,1 , 4,2 , 4,4 , 4,8 , 5,8 , 5,4 , 5,2 ), - _SEG('8', 2,1 , 2,2 , 2,4 , 2,8 , 3,4 , 3,2 , 3,1 ), - -/* Line 2 - * Format : ......... - * Pict. name : NEW REP SU MO TU WE TH FR SA - */ -#define LCD_LINE2_OFFSET LCD_LINE1_OFFSET + LCD_LINE1_SIZE -#define LCD_LINE2_SIZE 9 - - _PIC('.', 23,2 , "NEW" ), - _PIC('.', 23,4 , "REP" ), - _PIC('.', 1,8 , "SU" ), - _PIC('.', 1,4 , "MO" ), - _PIC('.', 1,2 , "TU" ), - _PIC('.', 1,1 , "WE" ), - _PIC('.', 0,1 , "TH" ), - _PIC('.', 0,2 , "FR" ), - _PIC('.', 0,4 , "SA" ), - -/* Line 3 - * Format : 888888888888 - */ -#define LCD_LINE3_OFFSET LCD_LINE2_OFFSET + LCD_LINE2_SIZE -#define LCD_LINE3_SIZE 12 - - _SEG('8', 22,16, 22,32, 22,64, 22,128, 23,128, 23,64, 23,32 ), - _SEG('8', 20,16, 20,32, 20,64, 20,128, 21,128, 21,64, 21,32 ), - _SEG('8', 18,16, 18,32, 18,64, 18,128, 19,128, 19,64, 19,32 ), - _SEG('8', 16,16, 16,32, 16,64, 16,128, 17,128, 17,64, 17,32 ), - _SEG('8', 14,16, 14,32, 14,64, 14,128, 15,128, 15,64, 15,32 ), - _SEG('8', 12,16, 12,32, 12,64, 12,128, 13,128, 13,64, 13,32 ), - _SEG('8', 10,16, 10,32, 10,64, 10,128, 11,128, 11,64, 11,32 ), - _SEG('8', 8,16, 8,32, 8,64, 8,128, 9,128, 9,64, 9,32 ), - _SEG('8', 6,16, 6,32, 6,64, 6,128, 7,128, 7,64, 7,32 ), - _SEG('8', 4,16, 4,32, 4,64, 4,128, 5,128, 5,64, 5,32 ), - _SEG('8', 2,16, 2,32, 2,64, 2,128, 3,128, 3,64, 3,32 ), - _SEG('8', 0,16, 0,32, 0,64, 0,128, 1,128, 1,64, 1,32 ), - -/* Line 4 - * - * The LED, DIALTONE and RINGTONE are implemented as icons and use the same - * sysfs interface. - */ -#define LCD_LINE4_OFFSET LCD_LINE3_OFFSET + LCD_LINE3_SIZE - - _PIC('.', offsetof(struct yld_status, led) , 0x01, "LED" ), - _PIC('.', offsetof(struct yld_status, dialtone) , 0x01, "DIALTONE" ), - _PIC('.', offsetof(struct yld_status, ringtone) , 0x24, "RINGTONE" ), - -#undef _SEG -#undef _PIC -#endif /* _SEG && _PIC */ |