diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-05 01:13:17 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-05 01:16:12 (GMT) |
commit | a3d52136ee8f7399859f9a0824470fd49b1d1a00 (patch) | |
tree | ac0fd3d1efc356029cbbc5e413f778f7231cd909 | |
parent | 5b339915762d30b21995aa7263e74081f2f1110a (diff) | |
parent | 84767d00a8fd54dd97866561f6e2ee246c8e1cdc (diff) | |
download | linux-a3d52136ee8f7399859f9a0824470fd49b1d1a00.tar.xz |
Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/dtor/input: (65 commits)
Input: gpio_keys - add support for switches (EV_SW)
Input: cobalt_btns - convert to use polldev library
Input: add skeleton for simple polled devices
Input: update some documentation
Input: wistron - fix typo in keymap for Acer TM610
Input: add input_set_capability() helper
Input: i8042 - add Fujitsu touchscreen/touchpad PNP IDs
Input: i8042 - add Panasonic CF-29 to nomux list
Input: lifebook - split into 2 devices
Input: lifebook - add signature of Panasonic CF-29
Input: lifebook - activate 6-byte protocol on select models
Input: lifebook - work properly on Panasonic CF-18
Input: cobalt buttons - separate device and driver registration
Input: ati_remote - make button repeat sensitivity configurable
Input: pxa27x - do not use deprecated SA_INTERRUPT flag
Input: ucb1400 - make delays configurable
Input: misc devices - switch to using input_dev->dev.parent
Input: joysticks - switch to using input_dev->dev.parent
Input: touchscreens - switch to using input_dev->dev.parent
Input: mice - switch to using input_dev->dev.parent
...
Fixed up conflicts with core device model removal of "struct subsystem" manually.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
120 files changed, 4334 insertions, 3250 deletions
diff --git a/Documentation/input/input-programming.txt b/Documentation/input/input-programming.txt index 180e0689..d9d5230 100644 --- a/Documentation/input/input-programming.txt +++ b/Documentation/input/input-programming.txt @@ -1,5 +1,3 @@ -$Id: input-programming.txt,v 1.4 2001/05/04 09:47:14 vojtech Exp $ - Programming input drivers ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -20,28 +18,51 @@ pressed or released a BUTTON_IRQ happens. The driver could look like: #include <asm/irq.h> #include <asm/io.h> +static struct input_dev *button_dev; + static void button_interrupt(int irq, void *dummy, struct pt_regs *fp) { - input_report_key(&button_dev, BTN_1, inb(BUTTON_PORT) & 1); - input_sync(&button_dev); + input_report_key(button_dev, BTN_1, inb(BUTTON_PORT) & 1); + input_sync(button_dev); } static int __init button_init(void) { + int error; + if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) { printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq); return -EBUSY; } - - button_dev.evbit[0] = BIT(EV_KEY); - button_dev.keybit[LONG(BTN_0)] = BIT(BTN_0); - - input_register_device(&button_dev); + + button_dev = input_allocate_device(); + if (!button_dev) { + printk(KERN_ERR "button.c: Not enough memory\n"); + error = -ENOMEM; + goto err_free_irq; + } + + button_dev->evbit[0] = BIT(EV_KEY); + button_dev->keybit[LONG(BTN_0)] = BIT(BTN_0); + + error = input_register_device(button_dev); + if (error) { + printk(KERN_ERR "button.c: Failed to register device\n"); + goto err_free_dev; + } + + return 0; + + err_free_dev: + input_free_device(button_dev); + err_free_irq: + free_irq(BUTTON_IRQ, button_interrupt); + return error; } static void __exit button_exit(void) { - input_unregister_device(&button_dev); + input_unregister_device(button_dev); free_irq(BUTTON_IRQ, button_interrupt); } @@ -58,17 +79,18 @@ In the _init function, which is called either upon module load or when booting the kernel, it grabs the required resources (it should also check for the presence of the device). -Then it sets the input bitfields. This way the device driver tells the other +Then it allocates a new input device structure with input_aloocate_device() +and sets up input bitfields. This way the device driver tells the other parts of the input systems what it is - what events can be generated or -accepted by this input device. Our example device can only generate EV_KEY type -events, and from those only BTN_0 event code. Thus we only set these two -bits. We could have used +accepted by this input device. Our example device can only generate EV_KEY +type events, and from those only BTN_0 event code. Thus we only set these +two bits. We could have used set_bit(EV_KEY, button_dev.evbit); set_bit(BTN_0, button_dev.keybit); as well, but with more than single bits the first approach tends to be -shorter. +shorter. Then the example driver registers the input device structure by calling @@ -76,16 +98,15 @@ Then the example driver registers the input device structure by calling This adds the button_dev structure to linked lists of the input driver and calls device handler modules _connect functions to tell them a new input -device has appeared. Because the _connect functions may call kmalloc(, -GFP_KERNEL), which can sleep, input_register_device() must not be called -from an interrupt or with a spinlock held. +device has appeared. input_register_device() may sleep and therefore must +not be called from an interrupt or with a spinlock held. While in use, the only used function of the driver is button_interrupt() which upon every interrupt from the button checks its state and reports it -via the +via the input_report_key() @@ -113,16 +134,10 @@ can use the open and close callback to know when it can stop polling or release the interrupt and when it must resume polling or grab the interrupt again. To do that, we would add this to our example driver: -int button_used = 0; - static int button_open(struct input_dev *dev) { - if (button_used++) - return 0; - if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) { printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq); - button_used--; return -EBUSY; } @@ -131,20 +146,21 @@ static int button_open(struct input_dev *dev) static void button_close(struct input_dev *dev) { - if (!--button_used) - free_irq(IRQ_AMIGA_VERTB, button_interrupt); + free_irq(IRQ_AMIGA_VERTB, button_interrupt); } static int __init button_init(void) { ... - button_dev.open = button_open; - button_dev.close = button_close; + button_dev->open = button_open; + button_dev->close = button_close; ... } -Note the button_used variable - we have to track how many times the open -function was called to know when exactly our device stops being used. +Note that input core keeps track of number of users for the device and +makes sure that dev->open() is called only when the first user connects +to the device and that dev->close() is called when the very last user +disconnects. Calls to both callbacks are serialized. The open() callback should return a 0 in case of success or any nonzero value in case of failure. The close() callback (which is void) must always succeed. @@ -175,7 +191,7 @@ set the corresponding bits and call the input_report_rel(struct input_dev *dev, int code, int value) -function. Events are generated only for nonzero value. +function. Events are generated only for nonzero value. However EV_ABS requires a little special care. Before calling input_register_device, you have to fill additional fields in the input_dev @@ -187,6 +203,10 @@ the ABS_X axis: button_dev.absfuzz[ABS_X] = 4; button_dev.absflat[ABS_X] = 8; +Or, you can just say: + + input_set_abs_params(button_dev, ABS_X, 0, 255, 4, 8); + This setting would be appropriate for a joystick X axis, with the minimum of 0, maximum of 255 (which the joystick *must* be able to reach, no problem if it sometimes reports more, but it must be able to always reach the min and @@ -197,14 +217,7 @@ If you don't need absfuzz and absflat, you can set them to zero, which mean that the thing is precise and always returns to exactly the center position (if it has any). -1.4 The void *private field -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This field in the input structure can be used to point to any private data -structures in the input device driver, in case the driver handles more than -one device. You'll need it in the open and close callbacks. - -1.5 NBITS(), LONG(), BIT() +1.4 NBITS(), LONG(), BIT() ~~~~~~~~~~~~~~~~~~~~~~~~~~ These three macros from input.h help some bitfield computations: @@ -213,13 +226,9 @@ These three macros from input.h help some bitfield computations: LONG(x) - returns the index in the array in longs for bit x BIT(x) - returns the index in a long for bit x -1.6 The number, id* and name fields +1.5 The id* and name fields ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The dev->number is assigned by the input system to the input device when it -is registered. It has no use except for identifying the device to the user -in system messages. - The dev->name should be set before registering the input device by the input device driver. It's a string like 'Generic button device' containing a user friendly name of the device. @@ -234,15 +243,25 @@ driver. The id and name fields can be passed to userland via the evdev interface. -1.7 The keycode, keycodemax, keycodesize fields +1.6 The keycode, keycodemax, keycodesize fields ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -These two fields will be used for any input devices that report their data -as scancodes. If not all scancodes can be known by autodetection, they may -need to be set by userland utilities. The keycode array then is an array -used to map from scancodes to input system keycodes. The keycode max will -contain the size of the array and keycodesize the size of each entry in it -(in bytes). +These three fields should be used by input devices that have dense keymaps. +The keycode is an array used to map from scancodes to input system keycodes. +The keycode max should contain the size of the array and keycodesize the +size of each entry in it (in bytes). + +Userspace can query and alter current scancode to keycode mappings using +EVIOCGKEYCODE and EVIOCSKEYCODE ioctls on corresponding evdev interface. +When a device has all 3 aforementioned fields filled in, the driver may +rely on kernel's default implementation of setting and querying keycode +mappings. + +1.7 dev->getkeycode() and dev->setkeycode() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +getkeycode() and setkeycode() callbacks allow drivers to override default +keycode/keycodesize/keycodemax mapping mechanism provided by input core +and implement sparse keycode maps. 1.8 Key autorepeat ~~~~~~~~~~~~~~~~~~ @@ -266,7 +285,7 @@ direction - from the system to the input device driver. If your input device driver can handle these events, it has to set the respective bits in evbit, *and* also the callback routine: - button_dev.event = button_event; + button_dev->event = button_event; int button_event(struct input_dev *dev, unsigned int type, unsigned int code, int value); { diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile index de017c1..9565b21 100644 --- a/arch/mips/cobalt/Makefile +++ b/arch/mips/cobalt/Makefile @@ -2,7 +2,7 @@ # Makefile for the Cobalt micro systems family specific parts of the kernel # -obj-y := irq.o reset.o setup.o +obj-y := irq.o reset.o setup.o buttons.o obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_EARLY_PRINTK) += console.o diff --git a/arch/mips/cobalt/buttons.c b/arch/mips/cobalt/buttons.c new file mode 100644 index 0000000..9e14398 --- /dev/null +++ b/arch/mips/cobalt/buttons.c @@ -0,0 +1,54 @@ +/* + * Cobalt buttons platform device. + * + * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <linux/platform_device.h> +#include <linux/errno.h> +#include <linux/init.h> + +static struct resource cobalt_buttons_resource __initdata = { + .start = 0x1d000000, + .end = 0x1d000003, + .flags = IORESOURCE_MEM, +}; + +static __init int cobalt_add_buttons(void) +{ + struct platform_device *pd; + int error; + + pd = platform_device_alloc("Cobalt buttons", -1); + if (!pd) + return -ENOMEM; + + error = platform_device_add_resources(pd, &cobalt_buttons_resource, 1); + if (error) + goto err_free_device; + + error = platform_device_add(pd); + if (error) + goto err_free_device; + + return 0; + + err_free_device: + platform_device_put(pd); + return error; +} +device_initcall(cobalt_add_buttons); diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index cb8d691..c06e86a 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -41,7 +41,6 @@ #include <linux/input.h> #include <linux/reboot.h> -static void kbd_disconnect(struct input_handle *handle); extern void ctrl_alt_del(void); /* @@ -159,65 +158,41 @@ static int sysrq_alt_use; static int sysrq_alt; /* - * Translation of scancodes to keycodes. We set them on only the first attached - * keyboard - for per-keyboard setting, /dev/input/event is more useful. + * Translation of scancodes to keycodes. We set them on only the first + * keyboard in the list that accepts the scancode and keycode. + * Explanation for not choosing the first attached keyboard anymore: + * USB keyboards for example have two event devices: one for all "normal" + * keys and one for extra function keys (like "volume up", "make coffee", + * etc.). So this means that scancodes for the extra function keys won't + * be valid for the first event device, but will be for the second. */ int getkeycode(unsigned int scancode) { - struct list_head *node; - struct input_dev *dev = NULL; + struct input_handle *handle; + int keycode; + int error = -ENODEV; - list_for_each(node, &kbd_handler.h_list) { - struct input_handle *handle = to_handle_h(node); - if (handle->dev->keycodesize) { - dev = handle->dev; - break; - } + list_for_each_entry(handle, &kbd_handler.h_list, h_node) { + error = handle->dev->getkeycode(handle->dev, scancode, &keycode); + if (!error) + return keycode; } - if (!dev) - return -ENODEV; - - if (scancode >= dev->keycodemax) - return -EINVAL; - - return INPUT_KEYCODE(dev, scancode); + return error; } int setkeycode(unsigned int scancode, unsigned int keycode) { - struct list_head *node; - struct input_dev *dev = NULL; - unsigned int i, oldkey; + struct input_handle *handle; + int error = -ENODEV; - list_for_each(node, &kbd_handler.h_list) { - struct input_handle *handle = to_handle_h(node); - if (handle->dev->keycodesize) { - dev = handle->dev; + list_for_each_entry(handle, &kbd_handler.h_list, h_node) { + error = handle->dev->setkeycode(handle->dev, scancode, keycode); + if (!error) break; - } } - if (!dev) - return -ENODEV; - - if (scancode >= dev->keycodemax) - return -EINVAL; - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8))) - return -EINVAL; - - oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode); - - clear_bit(oldkey, dev->keybit); - set_bit(keycode, dev->keybit); - - for (i = 0; i < dev->keycodemax; i++) - if (INPUT_KEYCODE(dev,i) == oldkey) - set_bit(oldkey, dev->keybit); - - return 0; + return error; } /* @@ -225,10 +200,9 @@ int setkeycode(unsigned int scancode, unsigned int keycode) */ static void kd_nosound(unsigned long ignored) { - struct list_head *node; + struct input_handle *handle; - list_for_each(node, &kbd_handler.h_list) { - struct input_handle *handle = to_handle_h(node); + list_for_each_entry(handle, &kbd_handler.h_list, h_node) { if (test_bit(EV_SND, handle->dev->evbit)) { if (test_bit(SND_TONE, handle->dev->sndbit)) input_inject_event(handle, EV_SND, SND_TONE, 0); @@ -1161,7 +1135,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw) if (emulate_raw(vc, keycode, !down << 7)) - if (keycode < BTN_MISC) + if (keycode < BTN_MISC && printk_ratelimit()) printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode); #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ @@ -1285,11 +1259,11 @@ static void kbd_event(struct input_handle *handle, unsigned int event_type, * likes it, it can open it and get events from it. In this (kbd_connect) * function, we should decide which VT to bind that keyboard to initially. */ -static struct input_handle *kbd_connect(struct input_handler *handler, - struct input_dev *dev, - const struct input_device_id *id) +static int kbd_connect(struct input_handler *handler, struct input_dev *dev, + const struct input_device_id *id) { struct input_handle *handle; + int error; int i; for (i = KEY_RESERVED; i < BTN_MISC; i++) @@ -1297,24 +1271,37 @@ static struct input_handle *kbd_connect(struct input_handler *handler, break; if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit)) - return NULL; + return -ENODEV; handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); if (!handle) - return NULL; + return -ENOMEM; handle->dev = dev; handle->handler = handler; handle->name = "kbd"; - input_open_device(handle); + error = input_register_handle(handle); + if (error) + goto err_free_handle; + + error = input_open_device(handle); + if (error) + goto err_unregister_handle; + + return 0; - return handle; + err_unregister_handle: + input_unregister_handle(handle); + err_free_handle: + kfree(handle); + return error; } static void kbd_disconnect(struct input_handle *handle) { input_close_device(handle); + input_unregister_handle(handle); kfree(handle); } diff --git a/drivers/input/Makefile b/drivers/input/Makefile index da575de..b4cd106 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile @@ -13,7 +13,6 @@ obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o obj-$(CONFIG_INPUT_JOYDEV) += joydev.o obj-$(CONFIG_INPUT_EVDEV) += evdev.o obj-$(CONFIG_INPUT_TSDEV) += tsdev.o -obj-$(CONFIG_INPUT_POWER) += power.o obj-$(CONFIG_INPUT_EVBUG) += evbug.o obj-$(CONFIG_INPUT_KEYBOARD) += keyboard/ diff --git a/drivers/input/evbug.c b/drivers/input/evbug.c index 5a9653c..c21f2f1 100644 --- a/drivers/input/evbug.c +++ b/drivers/input/evbug.c @@ -38,31 +38,43 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_DESCRIPTION("Input driver event debug module"); MODULE_LICENSE("GPL"); -static char evbug_name[] = "evbug"; - static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) { printk(KERN_DEBUG "evbug.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n", handle->dev->phys, type, code, value); } -static struct input_handle *evbug_connect(struct input_handler *handler, struct input_dev *dev, - const struct input_device_id *id) +static int evbug_connect(struct input_handler *handler, struct input_dev *dev, + const struct input_device_id *id) { struct input_handle *handle; + int error; - if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL))) - return NULL; + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; handle->dev = dev; handle->handler = handler; - handle->name = evbug_name; + handle->name = "evbug"; + + error = input_register_handle(handle); + if (error) + goto err_free_handle; - input_open_device(handle); + error = input_open_device(handle); + if (error) + goto err_unregister_handle; printk(KERN_DEBUG "evbug.c: Connected device: \"%s\", %s\n", dev->name, dev->phys); - return handle; + return 0; + + err_unregister_handle: + input_unregister_handle(handle); + err_free_handle: + kfree(handle); + return error; } static void evbug_disconnect(struct input_handle *handle) @@ -70,7 +82,7 @@ static void evbug_disconnect(struct input_handle *handle) printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n", handle->dev->phys); input_close_device(handle); - + input_unregister_handle(handle); kfree(handle); } diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 6e55b2c..1f6fcec 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -29,11 +29,11 @@ struct evdev { char name[16]; struct input_handle handle; wait_queue_head_t wait; - struct evdev_list *grab; - struct list_head list; + struct evdev_client *grab; + struct list_head client_list; }; -struct evdev_list { +struct evdev_client { struct input_event buffer[EVDEV_BUFFER_SIZE]; int head; int tail; @@ -47,28 +47,28 @@ static struct evdev *evdev_table[EVDEV_MINORS]; static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) { struct evdev *evdev = handle->private; - struct evdev_list *list; + struct evdev_client *client; if (evdev->grab) { - list = evdev->grab; + client = evdev->grab; - do_gettimeofday(&list->buffer[list->head].time); - list->buffer[list->head].type = type; - list->buffer[list->head].code = code; - list->buffer[list->head].value = value; - list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1); + do_gettimeofday(&client->buffer[client->head].time); + client->buffer[client->head].type = type; + client->buffer[client->head].code = code; + client->buffer[client->head].value = value; + client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1); - kill_fasync(&list->fasync, SIGIO, POLL_IN); + kill_fasync(&client->fasync, SIGIO, POLL_IN); } else - list_for_each_entry(list, &evdev->list, node) { + list_for_each_entry(client, &evdev->client_list, node) { - do_gettimeofday(&list->buffer[list->head].time); - list->buffer[list->head].type = type; - list->buffer[list->head].code = code; - list->buffer[list->head].value = value; - list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1); + do_gettimeofday(&client->buffer[client->head].time); + client->buffer[client->head].type = type; + client->buffer[client->head].code = code; + client->buffer[client->head].value = value; + client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1); - kill_fasync(&list->fasync, SIGIO, POLL_IN); + kill_fasync(&client->fasync, SIGIO, POLL_IN); } wake_up_interruptible(&evdev->wait); @@ -76,22 +76,23 @@ static void evdev_event(struct input_handle *handle, unsigned int type, unsigned static int evdev_fasync(int fd, struct file *file, int on) { + struct evdev_client *client = file->private_data; int retval; - struct evdev_list *list = file->private_data; - retval = fasync_helper(fd, file, on, &list->fasync); + retval = fasync_helper(fd, file, on, &client->fasync); return retval < 0 ? retval : 0; } static int evdev_flush(struct file *file, fl_owner_t id) { - struct evdev_list *list = file->private_data; + struct evdev_client *client = file->private_data; + struct evdev *evdev = client->evdev; - if (!list->evdev->exist) + if (!evdev->exist) return -ENODEV; - return input_flush_device(&list->evdev->handle, file); + return input_flush_device(&evdev->handle, file); } static void evdev_free(struct evdev *evdev) @@ -100,48 +101,62 @@ static void evdev_free(struct evdev *evdev) kfree(evdev); } -static int evdev_release(struct inode * inode, struct file * file) +static int evdev_release(struct inode *inode, struct file *file) { - struct evdev_list *list = file->private_data; + struct evdev_client *client = file->private_data; + struct evdev *evdev = client->evdev; - if (list->evdev->grab == list) { - input_release_device(&list->evdev->handle); - list->evdev->grab = NULL; + if (evdev->grab == client) { + input_release_device(&evdev->handle); + evdev->grab = NULL; } evdev_fasync(-1, file, 0); - list_del(&list->node); + list_del(&client->node); + kfree(client); - if (!--list->evdev->open) { - if (list->evdev->exist) - input_close_device(&list->evdev->handle); + if (!--evdev->open) { + if (evdev->exist) + input_close_device(&evdev->handle); else - evdev_free(list->evdev); + evdev_free(evdev); } - kfree(list); return 0; } -static int evdev_open(struct inode * inode, struct file * file) +static int evdev_open(struct inode *inode, struct file *file) { - struct evdev_list *list; + struct evdev_client *client; + struct evdev *evdev; int i = iminor(inode) - EVDEV_MINOR_BASE; + int error; - if (i >= EVDEV_MINORS || !evdev_table[i] || !evdev_table[i]->exist) + if (i >= EVDEV_MINORS) return -ENODEV; - if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL))) + evdev = evdev_table[i]; + + if (!evdev || !evdev->exist) + return -ENODEV; + + client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL); + if (!client) return -ENOMEM; - list->evdev = evdev_table[i]; - list_add_tail(&list->node, &evdev_table[i]->list); - file->private_data = list; + client->evdev = evdev; + list_add_tail(&client->node, &evdev->client_list); - if (!list->evdev->open++) - if (list->evdev->exist) - input_open_device(&list->evdev->handle); + if (!evdev->open++ && evdev->exist) { + error = input_open_device(&evdev->handle); + if (error) { + list_del(&client->node); + kfree(client); + return error; + } + } + file->private_data = client; return 0; } @@ -243,54 +258,55 @@ static int evdev_event_to_user(char __user *buffer, const struct input_event *ev #endif /* CONFIG_COMPAT */ -static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) +static ssize_t evdev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { - struct evdev_list *list = file->private_data; + struct evdev_client *client = file->private_data; + struct evdev *evdev = client->evdev; struct input_event event; int retval = 0; - if (!list->evdev->exist) + if (!evdev->exist) return -ENODEV; while (retval < count) { if (evdev_event_from_user(buffer + retval, &event)) return -EFAULT; - input_inject_event(&list->evdev->handle, event.type, event.code, event.value); + input_inject_event(&evdev->handle, event.type, event.code, event.value); retval += evdev_event_size(); } return retval; } -static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) +static ssize_t evdev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { - struct evdev_list *list = file->private_data; + struct evdev_client *client = file->private_data; + struct evdev *evdev = client->evdev; int retval; if (count < evdev_event_size()) return -EINVAL; - if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK)) + if (client->head == client->tail && evdev->exist && (file->f_flags & O_NONBLOCK)) return -EAGAIN; - retval = wait_event_interruptible(list->evdev->wait, - list->head != list->tail || (!list->evdev->exist)); - + retval = wait_event_interruptible(evdev->wait, + client->head != client->tail || !evdev->exist); if (retval) return retval; - if (!list->evdev->exist) + if (!evdev->exist) return -ENODEV; - while (list->head != list->tail && retval + evdev_event_size() <= count) { + while (client->head != client->tail && retval + evdev_event_size() <= count) { - struct input_event *event = (struct input_event *) list->buffer + list->tail; + struct input_event *event = (struct input_event *) client->buffer + client->tail; if (evdev_event_to_user(buffer + retval, event)) return -EFAULT; - list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); + client->tail = (client->tail + 1) & (EVDEV_BUFFER_SIZE - 1); retval += evdev_event_size(); } @@ -300,11 +316,12 @@ static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count /* No kernel lock - fine */ static unsigned int evdev_poll(struct file *file, poll_table *wait) { - struct evdev_list *list = file->private_data; + struct evdev_client *client = file->private_data; + struct evdev *evdev = client->evdev; - poll_wait(file, &list->evdev->wait, wait); - return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) | - (list->evdev->exist ? 0 : (POLLHUP | POLLERR)); + poll_wait(file, &evdev->wait, wait); + return ((client->head == client->tail) ? 0 : (POLLIN | POLLRDNORM)) | + (evdev->exist ? 0 : (POLLHUP | POLLERR)); } #ifdef CONFIG_COMPAT @@ -387,8 +404,8 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p) static long evdev_ioctl_handler(struct file *file, unsigned int cmd, void __user *p, int compat_mode) { - struct evdev_list *list = file->private_data; - struct evdev *evdev = list->evdev; + struct evdev_client *client = file->private_data; + struct evdev *evdev = client->evdev; struct input_dev *dev = evdev->handle.dev; struct input_absinfo abs; struct ff_effect effect; @@ -434,32 +451,21 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd, case EVIOCGKEYCODE: if (get_user(t, ip)) return -EFAULT; - if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) - return -EINVAL; - if (put_user(INPUT_KEYCODE(dev, t), ip + 1)) + + error = dev->getkeycode(dev, t, &v); + if (error) + return error; + + if (put_user(v, ip + 1)) return -EFAULT; + return 0; case EVIOCSKEYCODE: - if (get_user(t, ip)) + if (get_user(t, ip) || get_user(v, ip + 1)) return -EFAULT; - if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) - return -EINVAL; - if (get_user(v, ip + 1)) - return -EFAULT; - if (v < 0 || v > KEY_MAX) - return -EINVAL; - if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8))) - return -EINVAL; - u = SET_INPUT_KEYCODE(dev, t, v); - clear_bit(u, dev->keybit); - set_bit(v, dev->keybit); - for (i = 0; i < dev->keycodemax; i++) - if (INPUT_KEYCODE(dev, i) == u) - set_bit(u, dev->keybit); - - return 0; + return dev->setkeycode(dev, t, v); case EVIOCSFF: if (copy_from_user(&effect, p, sizeof(effect))) @@ -487,10 +493,10 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd, return -EBUSY; if (input_grab_device(&evdev->handle)) return -EBUSY; - evdev->grab = list; + evdev->grab = client; return 0; } else { - if (evdev->grab != list) + if (evdev->grab != client) return -EINVAL; input_release_device(&evdev->handle); evdev->grab = NULL; @@ -616,23 +622,26 @@ static const struct file_operations evdev_fops = { .flush = evdev_flush }; -static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, - const struct input_device_id *id) +static int evdev_connect(struct input_handler *handler, struct input_dev *dev, + const struct input_device_id *id) { struct evdev *evdev; struct class_device *cdev; + dev_t devt; int minor; + int error; for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++); if (minor == EVDEV_MINORS) { printk(KERN_ERR "evdev: no more free evdev devices\n"); - return NULL; + return -ENFILE; } - if (!(evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL))) - return NULL; + evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL); + if (!evdev) + return -ENOMEM; - INIT_LIST_HEAD(&evdev->list); + INIT_LIST_HEAD(&evdev->client_list); init_waitqueue_head(&evdev->wait); evdev->exist = 1; @@ -645,21 +654,43 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct evdev_table[minor] = evdev; - cdev = class_device_create(&input_class, &dev->cdev, - MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor), - dev->cdev.dev, evdev->name); + devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor), + + cdev = class_device_create(&input_class, &dev->cdev, devt, + dev->cdev.dev, evdev->name); + if (IS_ERR(cdev)) { + error = PTR_ERR(cdev); + goto err_free_evdev; + } /* temporary symlink to keep userspace happy */ - sysfs_create_link(&input_class.subsys.kobj, &cdev->kobj, - evdev->name); + error = sysfs_create_link(&input_class.subsys.kobj, + &cdev->kobj, evdev->name); + if (error) + goto err_cdev_destroy; + + error = input_register_handle(&evdev->handle); + if (error) + goto err_remove_link; + + return 0; - return &evdev->handle; + err_remove_link: + sysfs_remove_link(&input_class.subsys.kobj, evdev->name); + err_cdev_destroy: + class_device_destroy(&input_class, devt); + err_free_evdev: + kfree(evdev); + evdev_table[minor] = NULL; + return error; } static void evdev_disconnect(struct input_handle *handle) { struct evdev *evdev = handle->private; - struct evdev_list *list; + struct evdev_client *client; + + input_unregister_handle(handle); sysfs_remove_link(&input_class.subsys.kobj, evdev->name); class_device_destroy(&input_class, @@ -670,8 +701,8 @@ static void evdev_disconnect(struct input_handle *handle) input_flush_device(handle, NULL); input_close_device(handle); wake_up_interruptible(&evdev->wait); - list_for_each_entry(list, &evdev->list, node) - kill_fasync(&list->fasync, SIGIO, POLL_HUP); + list_for_each_entry(client, &evdev->client_list, node) + kill_fasync(&client->fasync, SIGIO, POLL_HUP); } else evdev_free(evdev); } diff --git a/drivers/input/input.c b/drivers/input/input.c index a9a706f..915e9ab 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -299,12 +299,87 @@ void input_close_device(struct input_handle *handle) } EXPORT_SYMBOL(input_close_device); -static void input_link_handle(struct input_handle *handle) +static int input_fetch_keycode(struct input_dev *dev, int scancode) { - list_add_tail(&handle->d_node, &handle->dev->h_list); - list_add_tail(&handle->h_node, &handle->handler->h_list); + switch (dev->keycodesize) { + case 1: + return ((u8 *)dev->keycode)[scancode]; + + case 2: + return ((u16 *)dev->keycode)[scancode]; + + default: + return ((u32 *)dev->keycode)[scancode]; + } +} + +static int input_default_getkeycode(struct input_dev *dev, + int scancode, int *keycode) +{ + if (!dev->keycodesize) + return -EINVAL; + + if (scancode < 0 || scancode >= dev->keycodemax) + return -EINVAL; + + *keycode = input_fetch_keycode(dev, scancode); + + return 0; +} + +static int input_default_setkeycode(struct input_dev *dev, + int scancode, int keycode) +{ + int old_keycode; + int i; + + if (scancode < 0 || scancode >= dev->keycodemax) + return -EINVAL; + + if (keycode < 0 || keycode > KEY_MAX) + return -EINVAL; + + if (!dev->keycodesize) + return -EINVAL; + + if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8))) + return -EINVAL; + + switch (dev->keycodesize) { + case 1: { + u8 *k = (u8 *)dev->keycode; + old_keycode = k[scancode]; + k[scancode] = keycode; + break; + } + case 2: { + u16 *k = (u16 *)dev->keycode; + old_keycode = k[scancode]; + k[scancode] = keycode; + break; + } + default: { + u32 *k = (u32 *)dev->keycode; + old_keycode = k[scancode]; + k[scancode] = keycode; + break; + } + } + + clear_bit(old_keycode, dev->keybit); + set_bit(keycode, dev->keybit); + + for (i = 0; i < dev->keycodemax; i++) { + if (input_fetch_keycode(dev, i) == old_keycode) { + set_bit(old_keycode, dev->keybit); + break; /* Setting the bit twice is useless, so break */ + } + } + + return 0; } + #define MATCH_BIT(bit, max) \ for (i = 0; i < NBITS(max); i++) \ if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \ @@ -351,6 +426,29 @@ static const struct input_device_id *input_match_device(const struct input_devic return NULL; } +static int input_attach_handler(struct input_dev *dev, struct input_handler *handler) +{ + const struct input_device_id *id; + int error; + + if (handler->blacklist && input_match_device(handler->blacklist, dev)) + return -ENODEV; + + id = input_match_device(handler->id_table, dev); + if (!id) + return -ENODEV; + + error = handler->connect(handler, dev, id); + if (error && error != -ENODEV) + printk(KERN_ERR + "input: failed to attach handler %s to device %s, " + "error: %d\n", + handler->name, kobject_name(&dev->cdev.kobj), error); + + return error; +} + + #ifdef CONFIG_PROC_FS static struct proc_dir_entry *proc_bus_input_dir; @@ -439,6 +537,7 @@ static int input_devices_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "N: Name=\"%s\"\n", dev->name ? dev->name : ""); seq_printf(seq, "P: Phys=%s\n", dev->phys ? dev->phys : ""); seq_printf(seq, "S: Sysfs=%s\n", path ? path : ""); + seq_printf(seq, "U: Uniq=%s\n", dev->uniq ? dev->uniq : ""); seq_printf(seq, "H: Handlers="); list_for_each_entry(handle, &dev->h_list, d_node) @@ -753,6 +852,13 @@ static struct attribute_group input_dev_caps_attr_group = { .attrs = input_dev_caps_attrs, }; +static struct attribute_group *input_dev_attr_groups[] = { + &input_dev_attr_group, + &input_dev_id_attr_group, + &input_dev_caps_attr_group, + NULL +}; + static void input_dev_release(struct class_device *class_dev) { struct input_dev *dev = to_input_dev(class_dev); @@ -906,6 +1012,7 @@ struct input_dev *input_allocate_device(void) dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL); if (dev) { dev->cdev.class = &input_class; + dev->cdev.groups = input_dev_attr_groups; class_device_initialize(&dev->cdev); mutex_init(&dev->mutex); INIT_LIST_HEAD(&dev->h_list); @@ -934,23 +1041,71 @@ EXPORT_SYMBOL(input_allocate_device); */ void input_free_device(struct input_dev *dev) { - if (dev) { - - mutex_lock(&dev->mutex); - dev->name = dev->phys = dev->uniq = NULL; - mutex_unlock(&dev->mutex); - + if (dev) input_put_device(dev); - } } EXPORT_SYMBOL(input_free_device); +/** + * input_set_capability - mark device as capable of a certain event + * @dev: device that is capable of emitting or accepting event + * @type: type of the event (EV_KEY, EV_REL, etc...) + * @code: event code + * + * In addition to setting up corresponding bit in appropriate capability + * bitmap the function also adjusts dev->evbit. + */ +void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code) +{ + switch (type) { + case EV_KEY: + __set_bit(code, dev->keybit); + break; + + case EV_REL: + __set_bit(code, dev->relbit); + break; + + case EV_ABS: + __set_bit(code, dev->absbit); + break; + + case EV_MSC: + __set_bit(code, dev->mscbit); + break; + + case EV_SW: + __set_bit(code, dev->swbit); + break; + + case EV_LED: + __set_bit(code, dev->ledbit); + break; + + case EV_SND: + __set_bit(code, dev->sndbit); + break; + + case EV_FF: + __set_bit(code, dev->ffbit); + break; + + default: + printk(KERN_ERR + "input_set_capability: unknown type %u (code %u)\n", + type, code); + dump_stack(); + return; + } + + __set_bit(type, dev->evbit); +} +EXPORT_SYMBOL(input_set_capability); + int input_register_device(struct input_dev *dev) { static atomic_t input_no = ATOMIC_INIT(0); - struct input_handle *handle; struct input_handler *handler; - const struct input_device_id *id; const char *path; int error; @@ -969,55 +1124,41 @@ int input_register_device(struct input_dev *dev) dev->rep[REP_PERIOD] = 33; } + if (!dev->getkeycode) + dev->getkeycode = input_default_getkeycode; + + if (!dev->setkeycode) + dev->setkeycode = input_default_setkeycode; + list_add_tail(&dev->node, &input_dev_list); snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id), "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); + if (!dev->cdev.dev) + dev->cdev.dev = dev->dev.parent; + error = class_device_add(&dev->cdev); if (error) return error; - error = sysfs_create_group(&dev->cdev.kobj, &input_dev_attr_group); - if (error) - goto fail1; - - error = sysfs_create_group(&dev->cdev.kobj, &input_dev_id_attr_group); - if (error) - goto fail2; - - error = sysfs_create_group(&dev->cdev.kobj, &input_dev_caps_attr_group); - if (error) - goto fail3; - path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL); printk(KERN_INFO "input: %s as %s\n", dev->name ? dev->name : "Unspecified device", path ? path : "N/A"); kfree(path); list_for_each_entry(handler, &input_handler_list, node) - if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) - if ((id = input_match_device(handler->id_table, dev))) - if ((handle = handler->connect(handler, dev, id))) { - input_link_handle(handle); - if (handler->start) - handler->start(handle); - } + input_attach_handler(dev, handler); input_wakeup_procfs_readers(); return 0; - - fail3: sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group); - fail2: sysfs_remove_group(&dev->cdev.kobj, &input_dev_attr_group); - fail1: class_device_del(&dev->cdev); - return error; } EXPORT_SYMBOL(input_register_device); void input_unregister_device(struct input_dev *dev) { - struct list_head *node, *next; + struct input_handle *handle, *next; int code; for (code = 0; code <= KEY_MAX; code++) @@ -1027,19 +1168,12 @@ void input_unregister_device(struct input_dev *dev) del_timer_sync(&dev->timer); - list_for_each_safe(node, next, &dev->h_list) { - struct input_handle * handle = to_handle(node); - list_del_init(&handle->d_node); - list_del_init(&handle->h_node); + list_for_each_entry_safe(handle, next, &dev->h_list, d_node) handle->handler->disconnect(handle); - } + WARN_ON(!list_empty(&dev->h_list)); list_del_init(&dev->node); - sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group); - sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group); - sysfs_remove_group(&dev->cdev.kobj, &input_dev_attr_group); - class_device_unregister(&dev->cdev); input_wakeup_procfs_readers(); @@ -1049,8 +1183,6 @@ EXPORT_SYMBOL(input_unregister_device); int input_register_handler(struct input_handler *handler) { struct input_dev *dev; - struct input_handle *handle; - const struct input_device_id *id; INIT_LIST_HEAD(&handler->h_list); @@ -1064,13 +1196,7 @@ int input_register_handler(struct input_handler *handler) list_add_tail(&handler->node, &input_handler_list); list_for_each_entry(dev, &input_dev_list, node) - if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) - if ((id = input_match_device(handler->id_table, dev))) - if ((handle = handler->connect(handler, dev, id))) { - input_link_handle(handle); - if (handler->start) - handler->start(handle); - } + input_attach_handler(dev, handler); input_wakeup_procfs_readers(); return 0; @@ -1079,14 +1205,11 @@ EXPORT_SYMBOL(input_register_handler); void input_unregister_handler(struct input_handler *handler) { - struct list_head *node, *next; + struct input_handle *handle, *next; - list_for_each_safe(node, next, &handler->h_list) { - struct input_handle * handle = to_handle_h(node); - list_del_init(&handle->h_node); - list_del_init(&handle->d_node); + list_for_each_entry_safe(handle, next, &handler->h_list, h_node) handler->disconnect(handle); - } + WARN_ON(!list_empty(&handler->h_list)); list_del_init(&handler->node); @@ -1097,6 +1220,27 @@ void input_unregister_handler(struct input_handler *handler) } EXPORT_SYMBOL(input_unregister_handler); +int input_register_handle(struct input_handle *handle) +{ + struct input_handler *handler = handle->handler; + + list_add_tail(&handle->d_node, &handle->dev->h_list); + list_add_tail(&handle->h_node, &handler->h_list); + + if (handler->start) + handler->start(handle); + + return 0; +} +EXPORT_SYMBOL(input_register_handle); + +void input_unregister_handle(struct input_handle *handle) +{ + list_del_init(&handle->h_node); + list_del_init(&handle->d_node); +} +EXPORT_SYMBOL(input_unregister_handle); + static int input_open_file(struct inode *inode, struct file *file) { struct input_handler *handler = input_table[iminor(inode) >> 5]; diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index d2482e4..9bcc542 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -43,7 +43,7 @@ struct joydev { char name[16]; struct input_handle handle; wait_queue_head_t wait; - struct list_head list; + struct list_head client_list; struct js_corr corr[ABS_MAX + 1]; struct JS_DATA_SAVE_TYPE glue; int nabs; @@ -55,7 +55,7 @@ struct joydev { __s16 abs[ABS_MAX + 1]; }; -struct joydev_list { +struct joydev_client { struct js_event buffer[JOYDEV_BUFFER_SIZE]; int head; int tail; @@ -87,7 +87,7 @@ static int joydev_correct(int value, struct js_corr *corr) static void joydev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) { struct joydev *joydev = handle->private; - struct joydev_list *list; + struct joydev_client *client; struct js_event event; switch (type) { @@ -115,15 +115,15 @@ static void joydev_event(struct input_handle *handle, unsigned int type, unsigne event.time = jiffies_to_msecs(jiffies); - list_for_each_entry(list, &joydev->list, node) { + list_for_each_entry(client, &joydev->client_list, node) { - memcpy(list->buffer + list->head, &event, sizeof(struct js_event)); + memcpy(client->buffer + client->head, &event, sizeof(struct js_event)); - if (list->startup == joydev->nabs + joydev->nkey) - if (list->tail == (list->head = (list->head + 1) & (JOYDEV_BUFFER_SIZE - 1))) - list->startup = 0; + if (client->startup == joydev->nabs + joydev->nkey) + if (client->tail == (client->head = (client->head + 1) & (JOYDEV_BUFFER_SIZE - 1))) + client->startup = 0; - kill_fasync(&list->fasync, SIGIO, POLL_IN); + kill_fasync(&client->fasync, SIGIO, POLL_IN); } wake_up_interruptible(&joydev->wait); @@ -132,9 +132,9 @@ static void joydev_event(struct input_handle *handle, unsigned int type, unsigne static int joydev_fasync(int fd, struct file *file, int on) { int retval; - struct joydev_list *list = file->private_data; + struct joydev_client *client = file->private_data; - retval = fasync_helper(fd, file, on, &list->fasync); + retval = fasync_helper(fd, file, on, &client->fasync); return retval < 0 ? retval : 0; } @@ -145,60 +145,73 @@ static void joydev_free(struct joydev *joydev) kfree(joydev); } -static int joydev_release(struct inode * inode, struct file * file) +static int joydev_release(struct inode *inode, struct file *file) { - struct joydev_list *list = file->private_data; + struct joydev_client *client = file->private_data; + struct joydev *joydev = client->joydev; joydev_fasync(-1, file, 0); - list_del(&list->node); + list_del(&client->node); + kfree(client); - if (!--list->joydev->open) { - if (list->joydev->exist) - input_close_device(&list->joydev->handle); + if (!--joydev->open) { + if (joydev->exist) + input_close_device(&joydev->handle); else - joydev_free(list->joydev); + joydev_free(joydev); } - kfree(list); return 0; } static int joydev_open(struct inode *inode, struct file *file) { - struct joydev_list *list; + struct joydev_client *client; + struct joydev *joydev; int i = iminor(inode) - JOYDEV_MINOR_BASE; + int error; + + if (i >= JOYDEV_MINORS) + return -ENODEV; - if (i >= JOYDEV_MINORS || !joydev_table[i]) + joydev = joydev_table[i]; + if (!joydev || !joydev->exist) return -ENODEV; - if (!(list = kzalloc(sizeof(struct joydev_list), GFP_KERNEL))) + client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL); + if (!client) return -ENOMEM; - list->joydev = joydev_table[i]; - list_add_tail(&list->node, &joydev_table[i]->list); - file->private_data = list; + client->joydev = joydev; + list_add_tail(&client->node, &joydev->client_list); - if (!list->joydev->open++) - if (list->joydev->exist) - input_open_device(&list->joydev->handle); + if (!joydev->open++ && joydev->exist) { + error = input_open_device(&joydev->handle); + if (error) { + list_del(&client->node); + kfree(client); + return error; + } + } + file->private_data = client; return 0; } -static ssize_t joydev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) +static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { return -EINVAL; } static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct joydev_list *list = file->private_data; - struct joydev *joydev = list->joydev; + struct joydev_client *client = file->private_data; + struct joydev *joydev = client->joydev; struct input_dev *input = joydev->handle.dev; int retval = 0; - if (!list->joydev->exist) + if (!joydev->exist) return -ENODEV; if (count < sizeof(struct js_event)) @@ -217,56 +230,55 @@ static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, lo if (copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE))) return -EFAULT; - list->startup = 0; - list->tail = list->head; + client->startup = 0; + client->tail = client->head; return sizeof(struct JS_DATA_TYPE); } - if (list->startup == joydev->nabs + joydev->nkey && - list->head == list->tail && (file->f_flags & O_NONBLOCK)) + if (client->startup == joydev->nabs + joydev->nkey && + client->head == client->tail && (file->f_flags & O_NONBLOCK)) return -EAGAIN; - retval = wait_event_interruptible(list->joydev->wait, - !list->joydev->exist || - list->startup < joydev->nabs + joydev->nkey || - list->head != list->tail); - + retval = wait_event_interruptible(joydev->wait, + !joydev->exist || + client->startup < joydev->nabs + joydev->nkey || + client->head != client->tail); if (retval) return retval; - if (!list->joydev->exist) + if (!joydev->exist) return -ENODEV; - while (list->startup < joydev->nabs + joydev->nkey && retval + sizeof(struct js_event) <= count) { + while (client->startup < joydev->nabs + joydev->nkey && retval + sizeof(struct js_event) <= count) { struct js_event event; event.time = jiffies_to_msecs(jiffies); - if (list->startup < joydev->nkey) { + if (client->startup < joydev->nkey) { event.type = JS_EVENT_BUTTON | JS_EVENT_INIT; - event.number = list->startup; + event.number = client->startup; event.value = !!test_bit(joydev->keypam[event.number], input->key); } else { event.type = JS_EVENT_AXIS | JS_EVENT_INIT; - event.number = list->startup - joydev->nkey; + event.number = client->startup - joydev->nkey; event.value = joydev->abs[event.number]; } if (copy_to_user(buf + retval, &event, sizeof(struct js_event))) return -EFAULT; - list->startup++; + client->startup++; retval += sizeof(struct js_event); } - while (list->head != list->tail && retval + sizeof(struct js_event) <= count) { + while (client->head != client->tail && retval + sizeof(struct js_event) <= count) { - if (copy_to_user(buf + retval, list->buffer + list->tail, sizeof(struct js_event))) + if (copy_to_user(buf + retval, client->buffer + client->tail, sizeof(struct js_event))) return -EFAULT; - list->tail = (list->tail + 1) & (JOYDEV_BUFFER_SIZE - 1); + client->tail = (client->tail + 1) & (JOYDEV_BUFFER_SIZE - 1); retval += sizeof(struct js_event); } @@ -276,11 +288,12 @@ static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, lo /* No kernel lock - fine */ static unsigned int joydev_poll(struct file *file, poll_table *wait) { - struct joydev_list *list = file->private_data; + struct joydev_client *client = file->private_data; + struct joydev *joydev = client->joydev; - poll_wait(file, &list->joydev->wait, wait); - return ((list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey) ? - (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR)); + poll_wait(file, &joydev->wait, wait); + return ((client->head != client->tail || client->startup < joydev->nabs + joydev->nkey) ? + (POLLIN | POLLRDNORM) : 0) | (joydev->exist ? 0 : (POLLHUP | POLLERR)); } static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp) @@ -374,8 +387,8 @@ static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __u #ifdef CONFIG_COMPAT static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct joydev_list *list = file->private_data; - struct joydev *joydev = list->joydev; + struct joydev_client *client = file->private_data; + struct joydev *joydev = client->joydev; void __user *argp = (void __user *)arg; s32 tmp32; struct JS_DATA_SAVE_TYPE_32 ds32; @@ -428,8 +441,8 @@ static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned lo static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - struct joydev_list *list = file->private_data; - struct joydev *joydev = list->joydev; + struct joydev_client *client = file->private_data; + struct joydev *joydev = client->joydev; void __user *argp = (void __user *)arg; if (!joydev->exist) @@ -465,23 +478,26 @@ static const struct file_operations joydev_fops = { .fasync = joydev_fasync, }; -static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev, - const struct input_device_id *id) +static int joydev_connect(struct input_handler *handler, struct input_dev *dev, + const struct input_device_id *id) { struct joydev *joydev; struct class_device *cdev; + dev_t devt; int i, j, t, minor; + int error; for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++); if (minor == JOYDEV_MINORS) { printk(KERN_ERR "joydev: no more free joydev devices\n"); - return NULL; + return -ENFILE; } - if (!(joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL))) - return NULL; + joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL); + if (!joydev) + return -ENOMEM; - INIT_LIST_HEAD(&joydev->list); + INIT_LIST_HEAD(&joydev->client_list); init_waitqueue_head(&joydev->wait); joydev->minor = minor; @@ -534,21 +550,44 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct joydev_table[minor] = joydev; - cdev = class_device_create(&input_class, &dev->cdev, - MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor), - dev->cdev.dev, joydev->name); + devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor), + + cdev = class_device_create(&input_class, &dev->cdev, devt, + dev->cdev.dev, joydev->name); + if (IS_ERR(cdev)) { + error = PTR_ERR(cdev); + goto err_free_joydev; + } /* temporary symlink to keep userspace happy */ - sysfs_create_link(&input_class.subsys.kobj, &cdev->kobj, - joydev->name); + error = sysfs_create_link(&input_class.subsys.kobj, + &cdev->kobj, joydev->name); + if (error) + goto err_cdev_destroy; + + error = input_register_handle(&joydev->handle); + if (error) + goto err_remove_link; + + return 0; - return &joydev->handle; + err_remove_link: + sysfs_remove_link(&input_class.subsys.kobj, joydev->name); + err_cdev_destroy: + class_device_destroy(&input_class, devt); + err_free_joydev: + joydev_table[minor] = NULL; + kfree(joydev); + return error; } + static void joydev_disconnect(struct input_handle *handle) { struct joydev *joydev = handle->private; - struct joydev_list *list; + struct joydev_client *client; + + input_unregister_handle(handle); sysfs_remove_link(&input_class.subsys.kobj, joydev->name); class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor)); @@ -557,8 +596,8 @@ static void joydev_disconnect(struct input_handle *handle) if (joydev->open) { input_close_device(handle); wake_up_interruptible(&joydev->wait); - list_for_each_entry(list, &joydev->list, node) - kill_fasync(&list->fasync, SIGIO, POLL_HUP); + list_for_each_entry(client, &joydev->client_list, node) + kill_fasync(&client->fasync, SIGIO, POLL_HUP); } else joydev_free(joydev); } diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c index b11a4bb..ff701ab 100644 --- a/drivers/input/joystick/a3d.c +++ b/drivers/input/joystick/a3d.c @@ -241,7 +241,7 @@ static void a3d_adc_close(struct gameport *gameport) static int a3d_open(struct input_dev *dev) { - struct a3d *a3d = dev->private; + struct a3d *a3d = input_get_drvdata(dev); gameport_start_polling(a3d->gameport); return 0; @@ -253,7 +253,7 @@ static int a3d_open(struct input_dev *dev) static void a3d_close(struct input_dev *dev) { - struct a3d *a3d = dev->private; + struct a3d *a3d = input_get_drvdata(dev); gameport_stop_polling(a3d->gameport); } @@ -314,11 +314,12 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv) input_dev->id.vendor = GAMEPORT_ID_VENDOR_MADCATZ; input_dev->id.product = a3d->mode; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &gameport->dev; - input_dev->private = a3d; + input_dev->dev.parent = &gameport->dev; input_dev->open = a3d_open; input_dev->close = a3d_close; + input_set_drvdata(input_dev, a3d); + if (a3d->mode == A3D_MODE_PXL) { int axes[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER }; diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c index 6279ced..28140c4 100644 --- a/drivers/input/joystick/adi.c +++ b/drivers/input/joystick/adi.c @@ -290,7 +290,7 @@ static void adi_poll(struct gameport *gameport) static int adi_open(struct input_dev *dev) { - struct adi_port *port = dev->private; + struct adi_port *port = input_get_drvdata(dev); gameport_start_polling(port->gameport); return 0; @@ -302,7 +302,7 @@ static int adi_open(struct input_dev *dev) static void adi_close(struct input_dev *dev) { - struct adi_port *port = dev->private; + struct adi_port *port = input_get_drvdata(dev); gameport_stop_polling(port->gameport); } @@ -424,8 +424,9 @@ static int adi_init_input(struct adi *adi, struct adi_port *port, int half) input_dev->id.vendor = GAMEPORT_ID_VENDOR_LOGITECH; input_dev->id.product = adi->id; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &port->gameport->dev; - input_dev->private = port; + input_dev->dev.parent = &port->gameport->dev; + + input_set_drvdata(input_dev, port); input_dev->open = adi_open; input_dev->close = adi_close; diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 51f1e4b..1c1afb5 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -343,7 +343,7 @@ static void analog_poll(struct gameport *gameport) static int analog_open(struct input_dev *dev) { - struct analog_port *port = dev->private; + struct analog_port *port = input_get_drvdata(dev); gameport_start_polling(port->gameport); return 0; @@ -355,7 +355,7 @@ static int analog_open(struct input_dev *dev) static void analog_close(struct input_dev *dev) { - struct analog_port *port = dev->private; + struct analog_port *port = input_get_drvdata(dev); gameport_stop_polling(port->gameport); } @@ -449,10 +449,13 @@ static int analog_init_device(struct analog_port *port, struct analog *analog, i input_dev->id.vendor = GAMEPORT_ID_VENDOR_ANALOG; input_dev->id.product = analog->mask >> 4; input_dev->id.version = 0x0100; + input_dev->dev.parent = &port->gameport->dev; + + input_set_drvdata(input_dev, port); input_dev->open = analog_open; input_dev->close = analog_close; - input_dev->private = port; + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); for (i = j = 0; i < 4; i++) diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c index 034ec39..d3352a8 100644 --- a/drivers/input/joystick/cobra.c +++ b/drivers/input/joystick/cobra.c @@ -142,7 +142,7 @@ static void cobra_poll(struct gameport *gameport) static int cobra_open(struct input_dev *dev) { - struct cobra *cobra = dev->private; + struct cobra *cobra = input_get_drvdata(dev); gameport_start_polling(cobra->gameport); return 0; @@ -150,7 +150,7 @@ static int cobra_open(struct input_dev *dev) static void cobra_close(struct input_dev *dev) { - struct cobra *cobra = dev->private; + struct cobra *cobra = input_get_drvdata(dev); gameport_stop_polling(cobra->gameport); } @@ -211,8 +211,9 @@ static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv) input_dev->id.vendor = GAMEPORT_ID_VENDOR_CREATIVE; input_dev->id.product = 0x0008; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &gameport->dev; - input_dev->private = cobra; + input_dev->dev.parent = &gameport->dev; + + input_set_drvdata(input_dev, cobra); input_dev->open = cobra_open; input_dev->close = cobra_close; diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index b41bd2e..c27593b 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c @@ -518,7 +518,7 @@ static void db9_timer(unsigned long private) static int db9_open(struct input_dev *dev) { - struct db9 *db9 = dev->private; + struct db9 *db9 = input_get_drvdata(dev); struct parport *port = db9->pd->port; int err; @@ -542,7 +542,7 @@ static int db9_open(struct input_dev *dev) static void db9_close(struct input_dev *dev) { - struct db9 *db9 = dev->private; + struct db9 *db9 = input_get_drvdata(dev); struct parport *port = db9->pd->port; mutex_lock(&db9->mutex); @@ -625,7 +625,8 @@ static struct db9 __init *db9_probe(int parport, int mode) input_dev->id.vendor = 0x0002; input_dev->id.product = mode; input_dev->id.version = 0x0100; - input_dev->private = db9; + + input_set_drvdata(input_dev, db9); input_dev->open = db9_open; input_dev->close = db9_close; diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 711e4b3..c71b58f 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -591,7 +591,7 @@ static void gc_timer(unsigned long private) static int gc_open(struct input_dev *dev) { - struct gc *gc = dev->private; + struct gc *gc = input_get_drvdata(dev); int err; err = mutex_lock_interruptible(&gc->mutex); @@ -610,7 +610,7 @@ static int gc_open(struct input_dev *dev) static void gc_close(struct input_dev *dev) { - struct gc *gc = dev->private; + struct gc *gc = input_get_drvdata(dev); mutex_lock(&gc->mutex); if (!--gc->used) { @@ -646,7 +646,8 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) input_dev->id.vendor = 0x0001; input_dev->id.product = pad_type; input_dev->id.version = 0x0100; - input_dev->private = gc; + + input_set_drvdata(input_dev, gc); input_dev->open = gc_open; input_dev->close = gc_close; diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index bacbab5..d514aeb 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c @@ -220,7 +220,7 @@ static void gf2k_poll(struct gameport *gameport) static int gf2k_open(struct input_dev *dev) { - struct gf2k *gf2k = dev->private; + struct gf2k *gf2k = input_get_drvdata(dev); gameport_start_polling(gf2k->gameport); return 0; @@ -228,7 +228,7 @@ static int gf2k_open(struct input_dev *dev) static void gf2k_close(struct input_dev *dev) { - struct gf2k *gf2k = dev->private; + struct gf2k *gf2k = input_get_drvdata(dev); gameport_stop_polling(gf2k->gameport); } @@ -308,11 +308,13 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) input_dev->id.vendor = GAMEPORT_ID_VENDOR_GENIUS; input_dev->id.product = gf2k->id; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &gameport->dev; - input_dev->private = gf2k; + input_dev->dev.parent = &gameport->dev; + + input_set_drvdata(input_dev, gf2k); input_dev->open = gf2k_open; input_dev->close = gf2k_close; + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); for (i = 0; i < gf2k_axes[gf2k->id]; i++) diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c index 17a90c4..73eb5ab 100644 --- a/drivers/input/joystick/grip.c +++ b/drivers/input/joystick/grip.c @@ -285,7 +285,7 @@ static void grip_poll(struct gameport *gameport) static int grip_open(struct input_dev *dev) { - struct grip *grip = dev->private; + struct grip *grip = input_get_drvdata(dev); gameport_start_polling(grip->gameport); return 0; @@ -293,7 +293,7 @@ static int grip_open(struct input_dev *dev) static void grip_close(struct input_dev *dev) { - struct grip *grip = dev->private; + struct grip *grip = input_get_drvdata(dev); gameport_stop_polling(grip->gameport); } @@ -363,8 +363,9 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv) input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS; input_dev->id.product = grip->mode[i]; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &gameport->dev; - input_dev->private = grip; + input_dev->dev.parent = &gameport->dev; + + input_set_drvdata(input_dev, grip); input_dev->open = grip_open; input_dev->close = grip_close; diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c index 8120a9c..555319e 100644 --- a/drivers/input/joystick/grip_mp.c +++ b/drivers/input/joystick/grip_mp.c @@ -562,7 +562,7 @@ static void grip_poll(struct gameport *gameport) static int grip_open(struct input_dev *dev) { - struct grip_mp *grip = dev->private; + struct grip_mp *grip = input_get_drvdata(dev); gameport_start_polling(grip->gameport); return 0; @@ -574,9 +574,9 @@ static int grip_open(struct input_dev *dev) static void grip_close(struct input_dev *dev) { - struct grip_mp *grip = dev->private; + struct grip_mp *grip = input_get_drvdata(dev); - gameport_start_polling(grip->gameport); + gameport_stop_polling(grip->gameport); } /* @@ -599,8 +599,9 @@ static int register_slot(int slot, struct grip_mp *grip) input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS; input_dev->id.product = 0x0100 + port->mode; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &grip->gameport->dev; - input_dev->private = grip; + input_dev->dev.parent = &grip->gameport->dev; + + input_set_drvdata(input_dev, grip); input_dev->open = grip_open; input_dev->close = grip_close; diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c index dbc5d92..d4e8073 100644 --- a/drivers/input/joystick/guillemot.c +++ b/drivers/input/joystick/guillemot.c @@ -156,7 +156,7 @@ static void guillemot_poll(struct gameport *gameport) static int guillemot_open(struct input_dev *dev) { - struct guillemot *guillemot = dev->private; + struct guillemot *guillemot = input_get_drvdata(dev); gameport_start_polling(guillemot->gameport); return 0; @@ -168,7 +168,7 @@ static int guillemot_open(struct input_dev *dev) static void guillemot_close(struct input_dev *dev) { - struct guillemot *guillemot = dev->private; + struct guillemot *guillemot = input_get_drvdata(dev); gameport_stop_polling(guillemot->gameport); } @@ -231,8 +231,9 @@ static int guillemot_connect(struct gameport *gameport, struct gameport_driver * input_dev->id.vendor = GAMEPORT_ID_VENDOR_GUILLEMOT; input_dev->id.product = guillemot_type[i].id; input_dev->id.version = (int)data[14] << 8 | data[15]; - input_dev->cdev.dev = &gameport->dev; - input_dev->private = guillemot; + input_dev->dev.parent = &gameport->dev; + + input_set_drvdata(input_dev, guillemot); input_dev->open = guillemot_open; input_dev->close = guillemot_close; diff --git a/drivers/input/joystick/iforce/iforce-ff.c b/drivers/input/joystick/iforce/iforce-ff.c index 8fb0c19..f2a4381 100644 --- a/drivers/input/joystick/iforce/iforce-ff.c +++ b/drivers/input/joystick/iforce/iforce-ff.c @@ -2,7 +2,7 @@ * $Id: iforce-ff.c,v 1.9 2002/02/02 19:28:35 jdeneux Exp $ * * Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz> - * Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com> + * Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com> * * USB/RS232 I-Force joysticks and wheels. */ @@ -205,7 +205,7 @@ static int need_condition_modifier(struct ff_effect *old, struct ff_effect *new) int i; if (new->type != FF_SPRING && new->type != FF_FRICTION) { - printk(KERN_WARNING "iforce.c: bad effect type in need_condition_modifier\n"); + warn("bad effect type in need_condition_modifier"); return 0; } @@ -227,7 +227,7 @@ static int need_condition_modifier(struct ff_effect *old, struct ff_effect *new) static int need_magnitude_modifier(struct ff_effect *old, struct ff_effect *effect) { if (effect->type != FF_CONSTANT) { - printk(KERN_WARNING "iforce.c: bad effect type in need_envelope_modifier\n"); + warn("bad effect type in need_envelope_modifier"); return 0; } @@ -258,7 +258,7 @@ static int need_envelope_modifier(struct ff_effect *old, struct ff_effect *effec break; default: - printk(KERN_WARNING "iforce.c: bad effect type in need_envelope_modifier\n"); + warn("bad effect type in need_envelope_modifier"); } return 0; @@ -271,7 +271,7 @@ static int need_envelope_modifier(struct ff_effect *old, struct ff_effect *effec static int need_period_modifier(struct ff_effect *old, struct ff_effect *new) { if (new->type != FF_PERIODIC) { - printk(KERN_WARNING "iforce.c: bad effect type in need_period_modifier\n"); + warn("bad effect type in need_period_modifier"); return 0; } return (old->u.periodic.period != new->u.periodic.period diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index 3393a37..fb129c4 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -2,7 +2,7 @@ * $Id: iforce-main.c,v 1.19 2002/07/07 10:22:50 jdeneux Exp $ * * Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz> - * Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com> + * Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com> * * USB/RS232 I-Force joysticks and wheels. */ @@ -29,7 +29,7 @@ #include "iforce.h" -MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <deneux@ifrance.com>"); +MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <johann.deneux@gmail.com>"); MODULE_DESCRIPTION("USB/RS232 I-Force joysticks and wheels driver"); MODULE_LICENSE("GPL"); @@ -220,7 +220,7 @@ static void iforce_release(struct input_dev *dev) /* Check: no effects should be present in memory */ for (i = 0; i < dev->ff->max_effects; i++) { if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags)) { - printk(KERN_WARNING "iforce_release: Device still owns effects\n"); + warn("iforce_release: Device still owns effects"); break; } } @@ -232,7 +232,7 @@ static void iforce_release(struct input_dev *dev) switch (iforce->bus) { #ifdef CONFIG_JOYSTICK_IFORCE_USB case IFORCE_USB: - usb_unlink_urb(iforce->irq); + usb_kill_urb(iforce->irq); /* The device was unplugged before the file * was released */ @@ -287,13 +287,13 @@ int iforce_init_device(struct iforce *iforce) #ifdef CONFIG_JOYSTICK_IFORCE_USB case IFORCE_USB: input_dev->id.bustype = BUS_USB; - input_dev->cdev.dev = &iforce->usbdev->dev; + input_dev->dev.parent = &iforce->usbdev->dev; break; #endif #ifdef CONFIG_JOYSTICK_IFORCE_232 case IFORCE_232: input_dev->id.bustype = BUS_RS232; - input_dev->cdev.dev = &iforce->serio->dev; + input_dev->dev.parent = &iforce->serio->dev; break; #endif } @@ -324,7 +324,7 @@ int iforce_init_device(struct iforce *iforce) break; if (i == 20) { /* 5 seconds */ - printk(KERN_ERR "iforce-main.c: Timeout waiting for response from device.\n"); + err("Timeout waiting for response from device."); error = -ENODEV; goto fail; } @@ -336,26 +336,26 @@ int iforce_init_device(struct iforce *iforce) if (!iforce_get_id_packet(iforce, "M")) input_dev->id.vendor = (iforce->edata[2] << 8) | iforce->edata[1]; else - printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet M\n"); + warn("Device does not respond to id packet M"); if (!iforce_get_id_packet(iforce, "P")) input_dev->id.product = (iforce->edata[2] << 8) | iforce->edata[1]; else - printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet P\n"); + warn("Device does not respond to id packet P"); if (!iforce_get_id_packet(iforce, "B")) iforce->device_memory.end = (iforce->edata[2] << 8) | iforce->edata[1]; else - printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet B\n"); + warn("Device does not respond to id packet B"); if (!iforce_get_id_packet(iforce, "N")) ff_effects = iforce->edata[1]; else - printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet N\n"); + warn("Device does not respond to id packet N"); /* Check if the device can store more effects than the driver can really handle */ if (ff_effects > IFORCE_EFFECTS_MAX) { - printk(KERN_WARNING "iforce: Limiting number of effects to %d (device reports %d)\n", + warn("Limiting number of effects to %d (device reports %d)", IFORCE_EFFECTS_MAX, ff_effects); ff_effects = IFORCE_EFFECTS_MAX; } @@ -457,8 +457,6 @@ int iforce_init_device(struct iforce *iforce) if (error) goto fail; - printk(KERN_DEBUG "iforce->dev->open = %p\n", iforce->dev->open); - return 0; fail: input_free_device(input_dev); diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c index 808f059..21c4e13 100644 --- a/drivers/input/joystick/iforce/iforce-packets.c +++ b/drivers/input/joystick/iforce/iforce-packets.c @@ -2,7 +2,7 @@ * $Id: iforce-packets.c,v 1.16 2002/07/07 10:22:50 jdeneux Exp $ * * Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz> - * Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com> + * Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com> * * USB/RS232 I-Force joysticks and wheels. */ @@ -39,10 +39,10 @@ void iforce_dump_packet(char *msg, u16 cmd, unsigned char *data) { int i; - printk(KERN_DEBUG "iforce.c: %s ( cmd = %04x, data = ", msg, cmd); + printk(KERN_DEBUG __FILE__ ": %s cmd = %04x, data = ", msg, cmd); for (i = 0; i < LO(cmd); i++) printk("%02x ", data[i]); - printk(")\n"); + printk("\n"); } /* @@ -65,8 +65,9 @@ int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data) head = iforce->xmit.head; tail = iforce->xmit.tail; + if (CIRC_SPACE(head, tail, XMIT_SIZE) < n+2) { - printk(KERN_WARNING "iforce.c: not enough space in xmit buffer to send new packet\n"); + warn("not enough space in xmit buffer to send new packet"); spin_unlock_irqrestore(&iforce->xmit_lock, flags); return -1; } @@ -126,8 +127,6 @@ int iforce_control_playback(struct iforce* iforce, u16 id, unsigned int value) { unsigned char data[3]; -printk(KERN_DEBUG "iforce-packets.c: control_playback %d %d\n", id, value); - data[0] = LO(id); data[1] = (value > 0) ? ((value > 1) ? 0x41 : 0x01) : 0; data[2] = LO(value); @@ -151,7 +150,7 @@ static int mark_core_as_ready(struct iforce *iforce, unsigned short addr) return 0; } } - printk(KERN_WARNING "iforce-packets.c: unused effect %04x updated !!!\n", addr); + warn("unused effect %04x updated !!!", addr); return -1; } @@ -162,7 +161,7 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data) static int being_used = 0; if (being_used) - printk(KERN_WARNING "iforce-packets.c: re-entrant call to iforce_process %d\n", being_used); + warn("re-entrant call to iforce_process %d", being_used); being_used++; #ifdef CONFIG_JOYSTICK_IFORCE_232 @@ -266,7 +265,7 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet) return -1; } #else - printk(KERN_ERR "iforce_get_id_packet: iforce->bus = USB!\n"); + err("iforce_get_id_packet: iforce->bus = USB!"); #endif break; @@ -284,13 +283,12 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet) return -1; } #else - printk(KERN_ERR "iforce_get_id_packet: iforce->bus = SERIO!\n"); + err("iforce_get_id_packet: iforce->bus = SERIO!"); #endif break; default: - printk(KERN_ERR "iforce_get_id_packet: iforce->bus = %d\n", - iforce->bus); + err("iforce_get_id_packet: iforce->bus = %d", iforce->bus); break; } diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c index ec4be53..7b4bc19 100644 --- a/drivers/input/joystick/iforce/iforce-serio.c +++ b/drivers/input/joystick/iforce/iforce-serio.c @@ -2,7 +2,7 @@ * $Id: iforce-serio.c,v 1.4 2002/01/28 22:45:00 jdeneux Exp $ * * Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz> - * Copyright (c) 2001 Johann Deneux <deneux@ifrance.com> + * Copyright (c) 2001, 2007 Johann Deneux <johann.deneux@gmail.com> * * USB/RS232 I-Force joysticks and wheels. */ diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index 80cdebc..750099d 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -2,7 +2,7 @@ * $Id: iforce-usb.c,v 1.16 2002/06/09 11:08:04 jdeneux Exp $ * * Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz> - * Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com> + * Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com> * * USB/RS232 I-Force joysticks and wheels. */ @@ -65,7 +65,7 @@ void iforce_usb_xmit(struct iforce *iforce) XMIT_INC(iforce->xmit.tail, n); if ( (n=usb_submit_urb(iforce->out, GFP_ATOMIC)) ) { - printk(KERN_WARNING "iforce-usb.c: iforce_usb_xmit: usb_submit_urb failed %d\n", n); + warn("usb_submit_urb failed %d\n", n); } /* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended. @@ -110,7 +110,7 @@ static void iforce_usb_out(struct urb *urb) struct iforce *iforce = urb->context; if (urb->status) { - printk(KERN_DEBUG "iforce_usb_out: urb->status %d, exiting", urb->status); + dbg("urb->status %d, exiting", urb->status); return; } @@ -190,10 +190,9 @@ fail: /* Called by iforce_delete() */ void iforce_usb_delete(struct iforce* iforce) { - usb_unlink_urb(iforce->irq); -/* Is it ok to unlink those ? */ - usb_unlink_urb(iforce->out); - usb_unlink_urb(iforce->ctrl); + usb_kill_urb(iforce->irq); + usb_kill_urb(iforce->out); + usb_kill_urb(iforce->ctrl); usb_free_urb(iforce->irq); usb_free_urb(iforce->out); diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index ffaeaef..dadcf4f 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h @@ -2,7 +2,7 @@ * $Id: iforce.h,v 1.13 2002/07/07 10:22:50 jdeneux Exp $ * * Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz> - * Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com> + * Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com> * * USB/RS232 I-Force joysticks and wheels. */ diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c index fec8b3d..1aec1e9 100644 --- a/drivers/input/joystick/interact.c +++ b/drivers/input/joystick/interact.c @@ -185,7 +185,7 @@ static void interact_poll(struct gameport *gameport) static int interact_open(struct input_dev *dev) { - struct interact *interact = dev->private; + struct interact *interact = input_get_drvdata(dev); gameport_start_polling(interact->gameport); return 0; @@ -197,7 +197,7 @@ static int interact_open(struct input_dev *dev) static void interact_close(struct input_dev *dev) { - struct interact *interact = dev->private; + struct interact *interact = input_get_drvdata(dev); gameport_stop_polling(interact->gameport); } @@ -262,7 +262,9 @@ static int interact_connect(struct gameport *gameport, struct gameport_driver *d input_dev->id.vendor = GAMEPORT_ID_VENDOR_INTERACT; input_dev->id.product = interact_type[i].id; input_dev->id.version = 0x0100; - input_dev->private = interact; + input_dev->dev.parent = &gameport->dev; + + input_set_drvdata(input_dev, interact); input_dev->open = interact_open; input_dev->close = interact_close; diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c index 4112789..b35604e 100644 --- a/drivers/input/joystick/magellan.c +++ b/drivers/input/joystick/magellan.c @@ -168,8 +168,7 @@ static int magellan_connect(struct serio *serio, struct serio_driver *drv) input_dev->id.vendor = SERIO_MAGELLAN; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &serio->dev; - input_dev->private = magellan; + input_dev->dev.parent = &serio->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c index e58b22c..2adf73f 100644 --- a/drivers/input/joystick/sidewinder.c +++ b/drivers/input/joystick/sidewinder.c @@ -509,7 +509,7 @@ static void sw_poll(struct gameport *gameport) static int sw_open(struct input_dev *dev) { - struct sw *sw = dev->private; + struct sw *sw = input_get_drvdata(dev); gameport_start_polling(sw->gameport); return 0; @@ -517,7 +517,7 @@ static int sw_open(struct input_dev *dev) static void sw_close(struct input_dev *dev) { - struct sw *sw = dev->private; + struct sw *sw = input_get_drvdata(dev); gameport_stop_polling(sw->gameport); } @@ -751,8 +751,9 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) input_dev->id.vendor = GAMEPORT_ID_VENDOR_MICROSOFT; input_dev->id.product = sw->type; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &gameport->dev; - input_dev->private = sw; + input_dev->dev.parent = &gameport->dev; + + input_set_drvdata(input_dev, sw); input_dev->open = sw_open; input_dev->close = sw_close; diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c index 08bf113..abb7c4c 100644 --- a/drivers/input/joystick/spaceball.c +++ b/drivers/input/joystick/spaceball.c @@ -226,8 +226,7 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv) input_dev->id.vendor = SERIO_SPACEBALL; input_dev->id.product = id; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &serio->dev; - input_dev->private = spaceball; + input_dev->dev.parent = &serio->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c index c9c7921..c4937f1 100644 --- a/drivers/input/joystick/spaceorb.c +++ b/drivers/input/joystick/spaceorb.c @@ -183,8 +183,7 @@ static int spaceorb_connect(struct serio *serio, struct serio_driver *drv) input_dev->id.vendor = SERIO_SPACEORB; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &serio->dev; - input_dev->private = spaceorb; + input_dev->dev.parent = &serio->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c index ecb0916..8581ee9 100644 --- a/drivers/input/joystick/stinger.c +++ b/drivers/input/joystick/stinger.c @@ -154,8 +154,7 @@ static int stinger_connect(struct serio *serio, struct serio_driver *drv) input_dev->id.vendor = SERIO_STINGER; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &serio->dev; - input_dev->private = stinger; + input_dev->dev.parent = &serio->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); input_dev->keybit[LONG(BTN_A)] = BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_X) | diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c index bb23ed2..3b36ee0 100644 --- a/drivers/input/joystick/tmdc.c +++ b/drivers/input/joystick/tmdc.c @@ -265,7 +265,7 @@ static void tmdc_poll(struct gameport *gameport) static int tmdc_open(struct input_dev *dev) { - struct tmdc *tmdc = dev->private; + struct tmdc *tmdc = input_get_drvdata(dev); gameport_start_polling(tmdc->gameport); return 0; @@ -273,7 +273,7 @@ static int tmdc_open(struct input_dev *dev) static void tmdc_close(struct input_dev *dev) { - struct tmdc *tmdc = dev->private; + struct tmdc *tmdc = input_get_drvdata(dev); gameport_stop_polling(tmdc->gameport); } @@ -326,8 +326,9 @@ static int tmdc_setup_port(struct tmdc *tmdc, int idx, unsigned char *data) input_dev->id.vendor = GAMEPORT_ID_VENDOR_THRUSTMASTER; input_dev->id.product = model->id; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &tmdc->gameport->dev; - input_dev->private = tmdc; + input_dev->dev.parent = &tmdc->gameport->dev; + + input_set_drvdata(input_dev, tmdc); input_dev->open = tmdc_open; input_dev->close = tmdc_close; diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index 037d348..0f2c608 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c @@ -122,7 +122,7 @@ static void tgfx_timer(unsigned long private) static int tgfx_open(struct input_dev *dev) { - struct tgfx *tgfx = dev->private; + struct tgfx *tgfx = input_get_drvdata(dev); int err; err = mutex_lock_interruptible(&tgfx->sem); @@ -141,7 +141,7 @@ static int tgfx_open(struct input_dev *dev) static void tgfx_close(struct input_dev *dev) { - struct tgfx *tgfx = dev->private; + struct tgfx *tgfx = input_get_drvdata(dev); mutex_lock(&tgfx->sem); if (!--tgfx->used) { @@ -224,7 +224,8 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) input_dev->id.product = n_buttons[i]; input_dev->id.version = 0x0100; - input_dev->private = tgfx; + input_set_drvdata(input_dev, tgfx); + input_dev->open = tgfx_open; input_dev->close = tgfx_close; diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c index 9cf17d6..c91504e 100644 --- a/drivers/input/joystick/twidjoy.c +++ b/drivers/input/joystick/twidjoy.c @@ -205,11 +205,9 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv) input_dev->id.vendor = SERIO_TWIDJOY; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &serio->dev; - input_dev->private = twidjoy; + input_dev->dev.parent = &serio->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y); input_set_abs_params(input_dev, ABS_X, -50, 50, 4, 4); input_set_abs_params(input_dev, ABS_Y, -50, 50, 4, 4); diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c index 29d339a..4e85f72 100644 --- a/drivers/input/joystick/warrior.c +++ b/drivers/input/joystick/warrior.c @@ -160,8 +160,7 @@ static int warrior_connect(struct serio *serio, struct serio_driver *drv) input_dev->id.vendor = SERIO_WARRIOR; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &serio->dev; - input_dev->private = warrior; + input_dev->dev.parent = &serio->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS); input_dev->keybit[LONG(BTN_TRIGGER)] = BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_TOP2); diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index c845d5c..9f42e4d 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -214,6 +214,15 @@ config KEYBOARD_OMAP To compile this driver as a module, choose M here: the module will be called omap-keypad. +config KEYBOARD_PXA27x + tristate "PXA27x keyboard support" + depends on PXA27x + help + Enable support for PXA27x matrix keyboard controller + + To compile this driver as a module, choose M here: the + module will be called pxa27x_keyboard. + config KEYBOARD_AAED2000 tristate "AAED-2000 keyboard" depends on MACH_AAED2000 diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 7aa59ee..28d211b 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o +obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keyboard.o obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o diff --git a/drivers/input/keyboard/aaed2000_kbd.c b/drivers/input/keyboard/aaed2000_kbd.c index 65fcb6a..3a37505 100644 --- a/drivers/input/keyboard/aaed2000_kbd.c +++ b/drivers/input/keyboard/aaed2000_kbd.c @@ -97,7 +97,7 @@ static void aaedkbd_work(void *data) static int aaedkbd_open(struct input_dev *indev) { - struct aaedkbd *aaedkbd = indev->private; + struct aaedkbd *aaedkbd = input_get_drvdata(indev); schedule_delayed_work(&aaedkbd->workq, msecs_to_jiffies(SCAN_INTERVAL)); @@ -106,7 +106,7 @@ static int aaedkbd_open(struct input_dev *indev) static void aaedkbd_close(struct input_dev *indev) { - struct aaedkbd *aaedkbd = indev->private; + struct aaedkbd *aaedkbd = input_get_drvdata(indev); cancel_delayed_work(&aaedkbd->workq); flush_scheduled_work(); @@ -141,8 +141,9 @@ static int __devinit aaedkbd_probe(struct platform_device *pdev) input_dev->id.vendor = 0x0001; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &pdev->dev; - input_dev->private = aaedkbd; + input_dev->dev.parent = &pdev->dev; + + input_set_drvdata(input_dev, aaedkbd); input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); input_dev->keycode = aaedkbd->keycode; diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 6638770..be1fe46 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -586,7 +586,7 @@ static void atkbd_event_work(struct work_struct *work) static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - struct atkbd *atkbd = dev->private; + struct atkbd *atkbd = input_get_drvdata(dev); if (!atkbd->write) return -1; @@ -883,8 +883,9 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd) input_dev->id.product = atkbd->translated ? 1 : atkbd->set; input_dev->id.version = atkbd->id; input_dev->event = atkbd_event; - input_dev->private = atkbd; - input_dev->cdev.dev = &atkbd->ps2dev.serio->dev; + input_dev->dev.parent = &atkbd->ps2dev.serio->dev; + + input_set_drvdata(input_dev, atkbd); input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC); diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c index 1016c94..6578bff 100644 --- a/drivers/input/keyboard/corgikbd.c +++ b/drivers/input/keyboard/corgikbd.c @@ -323,8 +323,7 @@ static int __init corgikbd_probe(struct platform_device *pdev) input_dev->id.vendor = 0x0001; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &pdev->dev; - input_dev->private = corgikbd; + input_dev->dev.parent = &pdev->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW); input_dev->keycode = corgikbd->keycode; diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index ccf6df3..7392122 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -35,11 +35,14 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id) struct input_dev *input = platform_get_drvdata(pdev); for (i = 0; i < pdata->nbuttons; i++) { - int gpio = pdata->buttons[i].gpio; + struct gpio_keys_button *button = &pdata->buttons[i]; + int gpio = button->gpio; + if (irq == gpio_to_irq(gpio)) { - int state = (gpio_get_value(gpio) ? 1 : 0) ^ (pdata->buttons[i].active_low); + unsigned int type = button->type ?: EV_KEY; + int state = (gpio_get_value(gpio) ? 1 : 0) ^ button->active_low; - input_report_key(input, pdata->buttons[i].keycode, state); + input_event(input, type, button->code, !!state); input_sync(input); } } @@ -63,8 +66,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) input->name = pdev->name; input->phys = "gpio-keys/input0"; - input->cdev.dev = &pdev->dev; - input->private = pdata; + input->dev.parent = &pdev->dev; input->id.bustype = BUS_HOST; input->id.vendor = 0x0001; @@ -72,19 +74,21 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) input->id.version = 0x0100; for (i = 0; i < pdata->nbuttons; i++) { - int code = pdata->buttons[i].keycode; - int irq = gpio_to_irq(pdata->buttons[i].gpio); + struct gpio_keys_button *button = &pdata->buttons[i]; + int irq = gpio_to_irq(button->gpio); + unsigned int type = button->type ?: EV_KEY; set_irq_type(irq, IRQ_TYPE_EDGE_BOTH); error = request_irq(irq, gpio_keys_isr, IRQF_SAMPLE_RANDOM, - pdata->buttons[i].desc ? pdata->buttons[i].desc : "gpio_keys", + button->desc ? button->desc : "gpio_keys", pdev); if (error) { printk(KERN_ERR "gpio-keys: unable to claim irq %d; error %d\n", irq, error); goto fail; } - set_bit(code, input->keybit); + + input_set_capability(input, type, button->code); } error = input_register_device(input); diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index 7cc9728..cdd254f 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c @@ -51,7 +51,7 @@ MODULE_LICENSE("Dual BSD/GPL"); #define HIL_KBD_SET1_UPBIT 0x01 #define HIL_KBD_SET1_SHIFT 1 -static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] = +static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] __read_mostly = { HIL_KEYCODES_SET1 }; #define HIL_KBD_SET2_UPBIT 0x01 @@ -60,10 +60,10 @@ static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] = #define HIL_KBD_SET3_UPBIT 0x80 #define HIL_KBD_SET3_SHIFT 0 -static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] = +static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] __read_mostly = { HIL_KEYCODES_SET3 }; -static char hil_language[][16] = { HIL_LOCALE_MAP }; +static const char hil_language[][16] = { HIL_LOCALE_MAP }; struct hil_kbd { struct input_dev *dev; @@ -94,10 +94,12 @@ static void hil_kbd_process_record(struct hil_kbd *kbd) idx = kbd->idx4/4; p = data[idx - 1]; - if ((p & ~HIL_CMDCT_POL) == - (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report; - if ((p & ~HIL_CMDCT_RPL) == - (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report; + if ((p & ~HIL_CMDCT_POL) == + (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) + goto report; + if ((p & ~HIL_CMDCT_RPL) == + (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) + goto report; /* Not a poll response. See if we are loading config records. */ switch (p & HIL_PKT_DATA_MASK) { @@ -107,27 +109,32 @@ static void hil_kbd_process_record(struct hil_kbd *kbd) for (; i < HIL_KBD_MAX_LENGTH; i++) kbd->idd[i] = 0; break; + case HIL_CMD_RSC: for (i = 0; i < idx; i++) kbd->rsc[i] = kbd->data[i] & HIL_PKT_DATA_MASK; for (; i < HIL_KBD_MAX_LENGTH; i++) kbd->rsc[i] = 0; break; + case HIL_CMD_EXD: for (i = 0; i < idx; i++) kbd->exd[i] = kbd->data[i] & HIL_PKT_DATA_MASK; for (; i < HIL_KBD_MAX_LENGTH; i++) kbd->exd[i] = 0; break; + case HIL_CMD_RNM: for (i = 0; i < idx; i++) kbd->rnm[i] = kbd->data[i] & HIL_PKT_DATA_MASK; for (; i < HIL_KBD_MAX_LENGTH + 1; i++) kbd->rnm[i] = '\0'; break; + default: /* These occur when device isn't present */ - if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break; + if (p == (HIL_ERR_INT | HIL_PKT_CMD)) + break; /* Anything else we'd like to know about. */ printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); break; @@ -139,16 +146,19 @@ static void hil_kbd_process_record(struct hil_kbd *kbd) switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) { case HIL_POL_CHARTYPE_NONE: break; + case HIL_POL_CHARTYPE_ASCII: while (cnt < idx - 1) input_report_key(dev, kbd->data[cnt++] & 0x7f, 1); break; + case HIL_POL_CHARTYPE_RSVD1: case HIL_POL_CHARTYPE_RSVD2: case HIL_POL_CHARTYPE_BINARY: while (cnt < idx - 1) input_report_key(dev, kbd->data[cnt++], 1); break; + case HIL_POL_CHARTYPE_SET1: while (cnt < idx - 1) { unsigned int key; @@ -161,6 +171,7 @@ static void hil_kbd_process_record(struct hil_kbd *kbd) input_report_key(dev, key, !up); } break; + case HIL_POL_CHARTYPE_SET2: while (cnt < idx - 1) { unsigned int key; @@ -173,6 +184,7 @@ static void hil_kbd_process_record(struct hil_kbd *kbd) input_report_key(dev, key, !up); } break; + case HIL_POL_CHARTYPE_SET3: while (cnt < idx - 1) { unsigned int key; @@ -191,42 +203,43 @@ static void hil_kbd_process_record(struct hil_kbd *kbd) up(&kbd->sem); } -static void hil_kbd_process_err(struct hil_kbd *kbd) { +static void hil_kbd_process_err(struct hil_kbd *kbd) +{ printk(KERN_WARNING PREFIX "errored HIL packet\n"); kbd->idx4 = 0; up(&kbd->sem); } -static irqreturn_t hil_kbd_interrupt(struct serio *serio, - unsigned char data, unsigned int flags) +static irqreturn_t hil_kbd_interrupt(struct serio *serio, + unsigned char data, unsigned int flags) { struct hil_kbd *kbd; hil_packet packet; int idx; kbd = serio_get_drvdata(serio); - if (kbd == NULL) { - BUG(); - return IRQ_HANDLED; - } + BUG_ON(kbd == NULL); if (kbd->idx4 >= (HIL_KBD_MAX_LENGTH * sizeof(hil_packet))) { hil_kbd_process_err(kbd); return IRQ_HANDLED; } idx = kbd->idx4/4; - if (!(kbd->idx4 % 4)) kbd->data[idx] = 0; + if (!(kbd->idx4 % 4)) + kbd->data[idx] = 0; packet = kbd->data[idx]; packet |= ((hil_packet)data) << ((3 - (kbd->idx4 % 4)) * 8); kbd->data[idx] = packet; /* Records of N 4-byte hil_packets must terminate with a command. */ - if ((++(kbd->idx4)) % 4) return IRQ_HANDLED; + if ((++(kbd->idx4)) % 4) + return IRQ_HANDLED; if ((packet & 0xffff0000) != HIL_ERR_INT) { hil_kbd_process_err(kbd); return IRQ_HANDLED; } - if (packet & HIL_PKT_CMD) hil_kbd_process_record(kbd); + if (packet & HIL_PKT_CMD) + hil_kbd_process_record(kbd); return IRQ_HANDLED; } @@ -235,10 +248,7 @@ static void hil_kbd_disconnect(struct serio *serio) struct hil_kbd *kbd; kbd = serio_get_drvdata(serio); - if (kbd == NULL) { - BUG(); - return; - } + BUG_ON(kbd == NULL); serio_close(serio); input_unregister_device(kbd->dev); @@ -259,42 +269,40 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv) if (!kbd->dev) goto bail0; - kbd->dev->private = kbd; - if (serio_open(serio, drv)) goto bail1; serio_set_drvdata(serio, kbd); kbd->serio = serio; - init_MUTEX_LOCKED(&(kbd->sem)); + init_MUTEX_LOCKED(&kbd->sem); /* Get device info. MLC driver supplies devid/status/etc. */ serio->write(serio, 0); serio->write(serio, 0); serio->write(serio, HIL_PKT_CMD >> 8); serio->write(serio, HIL_CMD_IDD); - down(&(kbd->sem)); + down(&kbd->sem); serio->write(serio, 0); serio->write(serio, 0); serio->write(serio, HIL_PKT_CMD >> 8); serio->write(serio, HIL_CMD_RSC); - down(&(kbd->sem)); + down(&kbd->sem); serio->write(serio, 0); serio->write(serio, 0); serio->write(serio, HIL_PKT_CMD >> 8); serio->write(serio, HIL_CMD_RNM); - down(&(kbd->sem)); + down(&kbd->sem); serio->write(serio, 0); serio->write(serio, 0); serio->write(serio, HIL_PKT_CMD >> 8); serio->write(serio, HIL_CMD_EXD); - down(&(kbd->sem)); + down(&kbd->sem); - up(&(kbd->sem)); + up(&kbd->sem); did = kbd->idd[0]; idd = kbd->idd + 1; @@ -310,12 +318,11 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv) goto bail2; } - if(HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) { + if (HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) { printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n"); goto bail2; } - kbd->dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); kbd->dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); kbd->dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE; @@ -328,7 +335,7 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv) kbd->dev->id.vendor = PCI_VENDOR_ID_HP; kbd->dev->id.product = 0x0001; /* TODO: get from kbd->rsc */ kbd->dev->id.version = 0x0100; /* TODO: get from kbd->rsc */ - kbd->dev->cdev.dev = &serio->dev; + kbd->dev->dev.parent = &serio->dev; for (i = 0; i < 128; i++) { set_bit(hil_kbd_set1[i], kbd->dev->keybit); @@ -344,8 +351,8 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv) serio->write(serio, 0); serio->write(serio, HIL_PKT_CMD >> 8); serio->write(serio, HIL_CMD_EK1); /* Enable Keyswitch Autorepeat 1 */ - down(&(kbd->sem)); - up(&(kbd->sem)); + down(&kbd->sem); + up(&kbd->sem); return 0; bail2: @@ -368,26 +375,26 @@ static struct serio_device_id hil_kbd_ids[] = { { 0 } }; -struct serio_driver hil_kbd_serio_drv = { +static struct serio_driver hil_kbd_serio_drv = { .driver = { .name = "hil_kbd", }, .description = "HP HIL keyboard driver", .id_table = hil_kbd_ids, - .connect = hil_kbd_connect, - .disconnect = hil_kbd_disconnect, - .interrupt = hil_kbd_interrupt + .connect = hil_kbd_connect, + .disconnect = hil_kbd_disconnect, + .interrupt = hil_kbd_interrupt }; static int __init hil_kbd_init(void) { return serio_register_driver(&hil_kbd_serio_drv); } - + static void __exit hil_kbd_exit(void) { serio_unregister_driver(&hil_kbd_serio_drv); } - + module_init(hil_kbd_init); module_exit(hil_kbd_exit); diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c index 56277fb..499b697 100644 --- a/drivers/input/keyboard/hilkbd.c +++ b/drivers/input/keyboard/hilkbd.c @@ -3,7 +3,7 @@ * * Copyright (C) 1998 Philip Blundell <philb@gnu.org> * Copyright (C) 1999 Matthew Wilcox <willy@bofh.ai> - * Copyright (C) 1999-2006 Helge Deller <deller@gmx.de> + * Copyright (C) 1999-2007 Helge Deller <deller@gmx.de> * * Very basic HP Human Interface Loop (HIL) driver. * This driver handles the keyboard on HP300 (m68k) and on some @@ -89,7 +89,7 @@ MODULE_LICENSE("GPL v2"); #define HIL_READKBDSADR 0xF9 #define HIL_WRITEKBDSADR 0xE9 -static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] = +static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] __read_mostly = { HIL_KEYCODES_SET1 }; /* HIL structure */ @@ -211,10 +211,10 @@ hil_keyb_init(void) return -ENODEV; /* already initialized */ } + spin_lock_init(&hil_dev.lock); hil_dev.dev = input_allocate_device(); if (!hil_dev.dev) return -ENOMEM; - hil_dev.dev->private = &hil_dev; #if defined(CONFIG_HP300) if (!hwreg_present((void *)(HILBASE + HIL_DATA))) { diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 3d4d0a0..1b08f4e 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c @@ -515,7 +515,7 @@ static int lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code, int value) { - struct lkkbd *lk = dev->private; + struct lkkbd *lk = input_get_drvdata (dev); unsigned char leds_on = 0; unsigned char leds_off = 0; @@ -666,9 +666,10 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv) input_dev->id.vendor = SERIO_LKKBD; input_dev->id.product = 0; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &serio->dev; + input_dev->dev.parent = &serio->dev; input_dev->event = lkkbd_event; - input_dev->private = lk; + + input_set_drvdata (input_dev, lk); set_bit (EV_KEY, input_dev->evbit); set_bit (EV_LED, input_dev->evbit); diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c index 2ade518..7a41b27 100644 --- a/drivers/input/keyboard/locomokbd.c +++ b/drivers/input/keyboard/locomokbd.c @@ -231,7 +231,7 @@ static int locomokbd_probe(struct locomo_dev *dev) input_dev->id.vendor = 0x0001; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; - input_dev->private = locomokbd; + input_dev->dev.parent = &dev->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); input_dev->keycode = locomokbd->keycode; diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c index aa29b50..b97a41e 100644 --- a/drivers/input/keyboard/newtonkbd.c +++ b/drivers/input/keyboard/newtonkbd.c @@ -104,8 +104,7 @@ static int nkbd_connect(struct serio *serio, struct serio_driver *drv) input_dev->id.vendor = SERIO_NEWTON; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &serio->dev; - input_dev->private = nkbd; + input_dev->dev.parent = &serio->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); input_dev->keycode = nkbd->keycode; diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 5680a6d..3a22863 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -370,8 +370,7 @@ static int __init omap_kp_probe(struct platform_device *pdev) set_bit(keymap[i] & KEY_MAX, input_dev->keybit); input_dev->name = "omap-keypad"; input_dev->phys = "omap-keypad/input0"; - input_dev->cdev.dev = &pdev->dev; - input_dev->private = omap_kp; + input_dev->dev.parent = &pdev->dev; input_dev->id.bustype = BUS_HOST; input_dev->id.vendor = 0x0001; diff --git a/drivers/input/keyboard/pxa27x_keyboard.c b/drivers/input/keyboard/pxa27x_keyboard.c new file mode 100644 index 0000000..06eaf76 --- /dev/null +++ b/drivers/input/keyboard/pxa27x_keyboard.c @@ -0,0 +1,258 @@ +/* + * linux/drivers/input/keyboard/pxa27x_keyboard.c + * + * Driver for the pxa27x matrix keyboard controller. + * + * Created: Feb 22, 2007 + * Author: Rodolfo Giometti <giometti@linux.it> + * + * Based on a previous implementations by Kevin O'Connor + * <kevin_at_koconnor.net> and Alex Osborne <bobofdoom@gmail.com> and + * on some suggestions by Nicolas Pitre <nico@cam.org>. + * + * 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/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/input.h> +#include <linux/device.h> +#include <linux/platform_device.h> + +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <asm/arch/hardware.h> +#include <asm/arch/pxa-regs.h> +#include <asm/arch/irqs.h> +#include <asm/arch/pxa27x_keyboard.h> + +#define DRIVER_NAME "pxa27x-keyboard" + +#define KPASMKP(col) (col/2 == 0 ? KPASMKP0 : \ + col/2 == 1 ? KPASMKP1 : \ + col/2 == 2 ? KPASMKP2 : KPASMKP3) +#define KPASMKPx_MKC(row, col) (1 << (row + 16 * (col % 2))) + +static irqreturn_t pxakbd_irq_handler(int irq, void *dev_id) +{ + struct platform_device *pdev = dev_id; + struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data; + struct input_dev *input_dev = platform_get_drvdata(pdev); + unsigned long kpc = KPC; + int p, row, col, rel; + + if (kpc & KPC_DI) { + unsigned long kpdk = KPDK; + + if (!(kpdk & KPDK_DKP)) { + /* better luck next time */ + } else if (kpc & KPC_REE0) { + unsigned long kprec = KPREC; + KPREC = 0x7f; + + if (kprec & KPREC_OF0) + rel = (kprec & 0xff) + 0x7f; + else if (kprec & KPREC_UF0) + rel = (kprec & 0xff) - 0x7f - 0xff; + else + rel = (kprec & 0xff) - 0x7f; + + if (rel) { + input_report_rel(input_dev, REL_WHEEL, rel); + input_sync(input_dev); + } + } + } + + if (kpc & KPC_MI) { + /* report the status of every button */ + for (row = 0; row < pdata->nr_rows; row++) { + for (col = 0; col < pdata->nr_cols; col++) { + p = KPASMKP(col) & KPASMKPx_MKC(row, col) ? + 1 : 0; + pr_debug("keycode %x - pressed %x\n", + pdata->keycodes[row][col], p); + input_report_key(input_dev, + pdata->keycodes[row][col], p); + } + } + input_sync(input_dev); + } + + return IRQ_HANDLED; +} + +static int pxakbd_open(struct input_dev *dev) +{ + /* Set keypad control register */ + KPC |= (KPC_ASACT | + KPC_MS_ALL | + (2 << 6) | KPC_REE0 | KPC_DK_DEB_SEL | + KPC_ME | KPC_MIE | KPC_DE | KPC_DIE); + + KPC &= ~KPC_AS; /* disable automatic scan */ + KPC &= ~KPC_IMKP; /* do not ignore multiple keypresses */ + + /* Set rotary count to mid-point value */ + KPREC = 0x7F; + + /* Enable unit clock */ + pxa_set_cken(CKEN19_KEYPAD, 1); + + return 0; +} + +static void pxakbd_close(struct input_dev *dev) +{ + /* Disable clock unit */ + pxa_set_cken(CKEN19_KEYPAD, 0); +} + +#ifdef CONFIG_PM +static int pxakbd_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data; + + /* Save controller status */ + pdata->reg_kpc = KPC; + pdata->reg_kprec = KPREC; + + return 0; +} + +static int pxakbd_resume(struct platform_device *pdev) +{ + struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data; + struct input_dev *input_dev = platform_get_drvdata(pdev); + + mutex_lock(&input_dev->mutex); + + if (input_dev->users) { + /* Restore controller status */ + KPC = pdata->reg_kpc; + KPREC = pdata->reg_kprec; + + /* Enable unit clock */ + pxa_set_cken(CKEN19_KEYPAD, 1); + } + + mutex_unlock(&input_dev->mutex); + + return 0; +} +#else +#define pxakbd_suspend NULL +#define pxakbd_resume NULL +#endif + +static int __devinit pxakbd_probe(struct platform_device *pdev) +{ + struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data; + struct input_dev *input_dev; + int i, row, col, error; + + /* Create and register the input driver. */ + input_dev = input_allocate_device(); + if (!input_dev) { + printk(KERN_ERR "Cannot request keypad device\n"); + return -ENOMEM; + } + + input_dev->name = DRIVER_NAME; + input_dev->id.bustype = BUS_HOST; + input_dev->open = pxakbd_open; + input_dev->close = pxakbd_close; + input_dev->dev.parent = &pdev->dev; + + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL); + input_dev->relbit[LONG(REL_WHEEL)] = BIT(REL_WHEEL); + for (row = 0; row < pdata->nr_rows; row++) { + for (col = 0; col < pdata->nr_cols; col++) { + int code = pdata->keycodes[row][col]; + if (code > 0) + set_bit(code, input_dev->keybit); + } + } + + error = request_irq(IRQ_KEYPAD, pxakbd_irq_handler, IRQF_DISABLED, + DRIVER_NAME, pdev); + if (error) { + printk(KERN_ERR "Cannot request keypad IRQ\n"); + pxa_set_cken(CKEN19_KEYPAD, 0); + goto err_free_dev; + } + + platform_set_drvdata(pdev, input_dev); + + /* Register the input device */ + error = input_register_device(input_dev); + if (error) + goto err_free_irq; + + /* Setup GPIOs. */ + for (i = 0; i < pdata->nr_rows + pdata->nr_cols; i++) + pxa_gpio_mode(pdata->gpio_modes[i]); + + /* + * Store rows/cols info into keyboard registers. + */ + + KPC |= (pdata->nr_rows - 1) << 26; + KPC |= (pdata->nr_cols - 1) << 23; + + for (col = 0; col < pdata->nr_cols; col++) + KPC |= KPC_MS0 << col; + + return 0; + + err_free_irq: + platform_set_drvdata(pdev, NULL); + free_irq(IRQ_KEYPAD, pdev); + err_free_dev: + input_free_device(input_dev); + return error; +} + +static int __devexit pxakbd_remove(struct platform_device *pdev) +{ + struct input_dev *input_dev = platform_get_drvdata(pdev); + + input_unregister_device(input_dev); + free_irq(IRQ_KEYPAD, pdev); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver pxakbd_driver = { + .probe = pxakbd_probe, + .remove = __devexit_p(pxakbd_remove), + .suspend = pxakbd_suspend, + .resume = pxakbd_resume, + .driver = { + .name = DRIVER_NAME, + }, +}; + +static int __init pxakbd_init(void) +{ + return platform_driver_register(&pxakbd_driver); +} + +static void __exit pxakbd_exit(void) +{ + platform_driver_unregister(&pxakbd_driver); +} + +module_init(pxakbd_init); +module_exit(pxakbd_exit); + +MODULE_DESCRIPTION("PXA27x Matrix Keyboard Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c index 8a2166c..41b8038 100644 --- a/drivers/input/keyboard/spitzkbd.c +++ b/drivers/input/keyboard/spitzkbd.c @@ -372,10 +372,9 @@ static int __init spitzkbd_probe(struct platform_device *dev) spitzkbd->input = input_dev; - input_dev->private = spitzkbd; input_dev->name = "Spitz Keyboard"; input_dev->phys = spitzkbd->phys; - input_dev->cdev.dev = &dev->dev; + input_dev->dev.parent = &dev->dev; input_dev->id.bustype = BUS_HOST; input_dev->id.vendor = 0x0001; diff --git a/drivers/input/keyboard/stowaway.c b/drivers/input/keyboard/stowaway.c index f7b5c5b..b44b068 100644 --- a/drivers/input/keyboard/stowaway.c +++ b/drivers/input/keyboard/stowaway.c @@ -108,8 +108,7 @@ static int skbd_connect(struct serio *serio, struct serio_driver *drv) input_dev->id.vendor = SERIO_STOWAWAY; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &serio->dev; - input_dev->private = skbd; + input_dev->dev.parent = &serio->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); input_dev->keycode = skbd->keycode; diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index cc02383..1d4e396 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c @@ -146,7 +146,7 @@ out: static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - struct sunkbd *sunkbd = dev->private; + struct sunkbd *sunkbd = input_get_drvdata(dev); switch (type) { @@ -271,8 +271,10 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) input_dev->id.vendor = SERIO_SUNKBD; input_dev->id.product = sunkbd->type; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &serio->dev; - input_dev->private = sunkbd; + input_dev->dev.parent = &serio->dev; + + input_set_drvdata(input_dev, sunkbd); + input_dev->event = sunkbd_event; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP); diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c index a820934..f3a56eb 100644 --- a/drivers/input/keyboard/xtkbd.c +++ b/drivers/input/keyboard/xtkbd.c @@ -108,8 +108,7 @@ static int xtkbd_connect(struct serio *serio, struct serio_driver *drv) input_dev->id.vendor = 0x0001; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &serio->dev; - input_dev->private = xtkbd; + input_dev->dev.parent = &serio->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); input_dev->keycode = xtkbd->keycode; diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 41b4258..1d0d3e7 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -40,6 +40,16 @@ config INPUT_M68K_BEEP tristate "M68k Beeper support" depends on M68K +config INPUT_COBALT_BTNS + tristate "Cobalt button interface" + depends on MIPS_COBALT + select INPUT_POLLDEV + help + Say Y here if you want to support MIPS Cobalt button interface. + + To compile this driver as a module, choose M here: the + module will be called cobalt_btns. + config INPUT_WISTRON_BTNS tristate "x86 Wistron laptop button interface" depends on X86 && !X86_64 @@ -81,8 +91,19 @@ config INPUT_UINPUT To compile this driver as a module, choose M here: the module will be called uinput. +config INPUT_POLLDEV + tristate "Polled input device skeleton" + help + Say Y here if you are using a driver for an input + device that periodically polls hardware state. This + option is only useful for out-of-tree drivers since + in-tree drivers select it automatically. + + To compile this driver as a module, choose M here: the + module will be called input-polldev. + config HP_SDC_RTC - tristate "HP SDC Real Time Clock" + tristate "HP SDC Real Time Clock" depends on GSC || HP300 select HP_SDC help diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index e0a8d58..21e3cca 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -4,10 +4,12 @@ # Each configuration option enables a list of files. +obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o obj-$(CONFIG_INPUT_UINPUT) += uinput.o +obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c new file mode 100644 index 0000000..064b079 --- /dev/null +++ b/drivers/input/misc/cobalt_btns.c @@ -0,0 +1,172 @@ +/* + * Cobalt button interface driver. + * + * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <linux/init.h> +#include <linux/input-polldev.h> +#include <linux/ioport.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#define BUTTONS_POLL_INTERVAL 30 /* msec */ +#define BUTTONS_COUNT_THRESHOLD 3 +#define BUTTONS_STATUS_MASK 0xfe000000 + +struct buttons_dev { + struct input_polled_dev *poll_dev; + void __iomem *reg; +}; + +struct buttons_map { + uint32_t mask; + int keycode; + int count; +}; + +static struct buttons_map buttons_map[] = { + { 0x02000000, KEY_RESTART, }, + { 0x04000000, KEY_LEFT, }, + { 0x08000000, KEY_UP, }, + { 0x10000000, KEY_DOWN, }, + { 0x20000000, KEY_RIGHT, }, + { 0x40000000, KEY_ENTER, }, + { 0x80000000, KEY_SELECT, }, +}; + +static void handle_buttons(struct input_polled_dev *dev) +{ + struct buttons_map *button = buttons_map; + struct buttons_dev *bdev = dev->private; + struct input_dev *input = dev->input; + uint32_t status; + int i; + + status = readl(bdev->reg); + status = ~status & BUTTONS_STATUS_MASK; + + for (i = 0; i < ARRAY_SIZE(buttons_map); i++) { + if (status & button->mask) { + button->count++; + } else { + if (button->count >= BUTTONS_COUNT_THRESHOLD) { + input_report_key(input, button->keycode, 0); + input_sync(input); + } + button->count = 0; + } + + if (button->count == BUTTONS_COUNT_THRESHOLD) { + input_report_key(input, button->keycode, 1); + input_sync(input); + } + + button++; + } +} + +static int __devinit cobalt_buttons_probe(struct platform_device *pdev) +{ + struct buttons_dev *bdev; + struct input_polled_dev *poll_dev; + struct input_dev *input; + struct resource *res; + int error, i; + + bdev = kzalloc(sizeof(struct buttons_dev), GFP_KERNEL); + poll_dev = input_allocate_polled_device(); + if (!bdev || !poll_dev) { + error = -ENOMEM; + goto err_free_mem; + } + + poll_dev->private = bdev; + poll_dev->poll = handle_buttons; + poll_dev->poll_interval = BUTTONS_POLL_INTERVAL; + + input = poll_dev->input; + input->name = "Cobalt buttons"; + input->phys = "cobalt/input0"; + input->id.bustype = BUS_HOST; + input->cdev.dev = &pdev->dev; + + input->evbit[0] = BIT(EV_KEY); + for (i = 0; i < ARRAY_SIZE(buttons_map); i++) { + set_bit(buttons_map[i].keycode, input->keybit); + buttons_map[i].count = 0; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + error = -EBUSY; + goto err_free_mem; + } + + bdev->poll_dev = poll_dev; + bdev->reg = ioremap(res->start, res->end - res->start + 1); + dev_set_drvdata(&pdev->dev, bdev); + + error = input_register_polled_device(poll_dev); + if (error) + goto err_iounmap; + + return 0; + + err_iounmap: + iounmap(bdev->reg); + err_free_mem: + input_free_polled_device(poll_dev); + kfree(bdev); + dev_set_drvdata(&pdev->dev, NULL); + return error; +} + +static int __devexit cobalt_buttons_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct buttons_dev *bdev = dev_get_drvdata(dev); + + input_unregister_polled_device(bdev->poll_dev); + input_free_polled_device(bdev->poll_dev); + iounmap(bdev->reg); + kfree(bdev); + dev_set_drvdata(dev, NULL); + + return 0; +} + +static struct platform_driver cobalt_buttons_driver = { + .probe = cobalt_buttons_probe, + .remove = __devexit_p(cobalt_buttons_remove), + .driver = { + .name = "Cobalt buttons", + .owner = THIS_MODULE, + }, +}; + +static int __init cobalt_buttons_init(void) +{ + return platform_driver_register(&cobalt_buttons_driver); +} + +static void __exit cobalt_buttons_exit(void) +{ + platform_driver_unregister(&cobalt_buttons_driver); +} + +module_init(cobalt_buttons_init); +module_exit(cobalt_buttons_exit); diff --git a/drivers/input/misc/input-polldev.c b/drivers/input/misc/input-polldev.c new file mode 100644 index 0000000..1b2b9c9 --- /dev/null +++ b/drivers/input/misc/input-polldev.c @@ -0,0 +1,171 @@ +/* + * Generic implementation of a polled input device + + * Copyright (c) 2007 Dmitry Torokhov + * + * 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/jiffies.h> +#include <linux/mutex.h> +#include <linux/input-polldev.h> + +static DEFINE_MUTEX(polldev_mutex); +static int polldev_users; +static struct workqueue_struct *polldev_wq; + +static int input_polldev_start_workqueue(void) +{ + int retval; + + retval = mutex_lock_interruptible(&polldev_mutex); + if (retval) + return retval; + + if (!polldev_users) { + polldev_wq = create_singlethread_workqueue("ipolldevd"); + if (!polldev_wq) { + printk(KERN_ERR "input-polldev: failed to create " + "ipolldevd workqueue\n"); + retval = -ENOMEM; + goto out; + } + } + + polldev_users++; + + out: + mutex_unlock(&polldev_mutex); + return retval; +} + +static void input_polldev_stop_workqueue(void) +{ + mutex_lock(&polldev_mutex); + + if (!--polldev_users) + destroy_workqueue(polldev_wq); + + mutex_unlock(&polldev_mutex); +} + +static void input_polled_device_work(struct work_struct *work) +{ + struct input_polled_dev *dev = + container_of(work, struct input_polled_dev, work.work); + + dev->poll(dev); + queue_delayed_work(polldev_wq, &dev->work, + msecs_to_jiffies(dev->poll_interval)); +} + +static int input_open_polled_device(struct input_dev *input) +{ + struct input_polled_dev *dev = input->private; + int error; + + error = input_polldev_start_workqueue(); + if (error) + return error; + + if (dev->flush) + dev->flush(dev); + + queue_delayed_work(polldev_wq, &dev->work, + msecs_to_jiffies(dev->poll_interval)); + + return 0; +} + +static void input_close_polled_device(struct input_dev *input) +{ + struct input_polled_dev *dev = input->private; + + cancel_rearming_delayed_workqueue(polldev_wq, &dev->work); + input_polldev_stop_workqueue(); +} + +/** + * input_allocate_polled_device - allocated memory polled device + * + * The function allocates memory for a polled device and also + * for an input device associated with this polled device. + */ +struct input_polled_dev *input_allocate_polled_device(void) +{ + struct input_polled_dev *dev; + + dev = kzalloc(sizeof(struct input_polled_dev), GFP_KERNEL); + if (!dev) + return NULL; + + dev->input = input_allocate_device(); + if (!dev->input) { + kfree(dev); + return NULL; + } + + return dev; +} +EXPORT_SYMBOL(input_allocate_polled_device); + +/** + * input_free_polled_device - free memory allocated for polled device + * @dev: device to free + * + * The function frees memory allocated for polling device and drops + * reference to the associated input device (if present). + */ +void input_free_polled_device(struct input_polled_dev *dev) +{ + if (dev) { + input_free_device(dev->input); + kfree(dev); + } +} +EXPORT_SYMBOL(input_free_polled_device); + +/** + * input_register_polled_device - register polled device + * @dev: device to register + * + * The function registers previously initialized polled input device + * with input layer. The device should be allocated with call to + * input_allocate_polled_device(). Callers should also set up poll() + * method and set up capabilities (id, name, phys, bits) of the + * corresponing input_dev structure. + */ +int input_register_polled_device(struct input_polled_dev *dev) +{ + struct input_dev *input = dev->input; + + INIT_DELAYED_WORK(&dev->work, input_polled_device_work); + if (!dev->poll_interval) + dev->poll_interval = 500; + input->private = dev; + input->open = input_open_polled_device; + input->close = input_close_polled_device; + + return input_register_device(input); +} +EXPORT_SYMBOL(input_register_polled_device); + +/** + * input_unregister_polled_device - unregister polled device + * @dev: device to unregister + * + * The function unregisters previously registered polled input + * device from input layer. Polling is stopped and device is + * ready to be freed with call to input_free_polled_device(). + * Callers should not attempt to access dev->input pointer + * after calling this function. + */ +void input_unregister_polled_device(struct input_polled_dev *dev) +{ + input_unregister_device(dev->input); + dev->input = NULL; +} +EXPORT_SYMBOL(input_unregister_polled_device); + diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c index 105c6fc..3d4b619 100644 --- a/drivers/input/misc/ixp4xx-beeper.c +++ b/drivers/input/misc/ixp4xx-beeper.c @@ -51,7 +51,7 @@ static void ixp4xx_spkr_control(unsigned int pin, unsigned int count) static int ixp4xx_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - unsigned int pin = (unsigned int) dev->private; + unsigned int pin = (unsigned int) input_get_drvdata(input_dev); unsigned int count = 0; if (type != EV_SND) @@ -99,14 +99,15 @@ static int __devinit ixp4xx_spkr_probe(struct platform_device *dev) if (!input_dev) return -ENOMEM; - input_dev->private = (void *) dev->id; + input_set_drvdata(input_dev, (void *) dev->id); + input_dev->name = "ixp4xx beeper", input_dev->phys = "ixp4xx/gpio"; input_dev->id.bustype = BUS_HOST; input_dev->id.vendor = 0x001f; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &dev->dev; + input_dev->dev.parent = &dev->dev; input_dev->evbit[0] = BIT(EV_SND); input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); @@ -136,7 +137,7 @@ static int __devinit ixp4xx_spkr_probe(struct platform_device *dev) static int __devexit ixp4xx_spkr_remove(struct platform_device *dev) { struct input_dev *input_dev = platform_get_drvdata(dev); - unsigned int pin = (unsigned int) input_dev->private; + unsigned int pin = (unsigned int) input_get_drvdata(input_dev); input_unregister_device(input_dev); platform_set_drvdata(dev, NULL); @@ -153,7 +154,7 @@ static int __devexit ixp4xx_spkr_remove(struct platform_device *dev) static void ixp4xx_spkr_shutdown(struct platform_device *dev) { struct input_dev *input_dev = platform_get_drvdata(dev); - unsigned int pin = (unsigned int) input_dev->private; + unsigned int pin = (unsigned int) input_get_drvdata(input_dev); /* turn off the speaker */ disable_irq(IRQ_IXP4XX_TIMER2); diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c index 8d6c383..e9f26e7 100644 --- a/drivers/input/misc/m68kspkr.c +++ b/drivers/input/misc/m68kspkr.c @@ -63,7 +63,7 @@ static int __devinit m68kspkr_probe(struct platform_device *dev) input_dev->id.vendor = 0x001f; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &dev->dev; + input_dev->dev.parent = &dev->dev; input_dev->evbit[0] = BIT(EV_SND); input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index afd3221..31989dc 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c @@ -78,7 +78,7 @@ static int __devinit pcspkr_probe(struct platform_device *dev) pcspkr_dev->id.vendor = 0x001f; pcspkr_dev->id.product = 0x0001; pcspkr_dev->id.version = 0x0100; - pcspkr_dev->cdev.dev = &dev->dev; + pcspkr_dev->dev.parent = &dev->dev; pcspkr_dev->evbit[0] = BIT(EV_SND); pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index 106c94f..e36ec1d 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c @@ -28,7 +28,7 @@ struct sparcspkr_state { static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev); + struct sparcspkr_state *state = dev_get_drvdata(dev->dev.parent); unsigned int count = 0; unsigned long flags; @@ -61,7 +61,7 @@ static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned in static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev); + struct sparcspkr_state *state = dev_get_drvdata(dev->dev.parent); unsigned int count = 0; unsigned long flags; @@ -113,7 +113,7 @@ static int __devinit sparcspkr_probe(struct device *dev) input_dev->id.vendor = 0x001f; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; - input_dev->cdev.dev = dev; + input_dev->dev.parent = dev; input_dev->evbit[0] = BIT(EV_SND); input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 4255623..031467e 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -41,9 +41,7 @@ static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - struct uinput_device *udev; - - udev = dev->private; + struct uinput_device *udev = input_get_drvdata(dev); udev->buff[udev->head].type = type; udev->buff[udev->head].code = code; @@ -136,7 +134,7 @@ static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *eff request.u.upload.effect = effect; request.u.upload.old = old; - retval = uinput_request_reserve_slot(dev->private, &request); + retval = uinput_request_reserve_slot(input_get_drvdata(dev), &request); if (!retval) retval = uinput_request_submit(dev, &request); @@ -156,7 +154,7 @@ static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id) request.code = UI_FF_ERASE; request.u.effect_id = effect_id; - retval = uinput_request_reserve_slot(dev->private, &request); + retval = uinput_request_reserve_slot(input_get_drvdata(dev), &request); if (!retval) retval = uinput_request_submit(dev, &request); @@ -274,7 +272,7 @@ static int uinput_allocate_device(struct uinput_device *udev) return -ENOMEM; udev->dev->event = uinput_dev_event; - udev->dev->private = udev; + input_set_drvdata(udev->dev, udev); return 0; } diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index e1183ae..961aad7 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c @@ -50,7 +50,7 @@ MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>"); MODULE_DESCRIPTION("Wistron laptop button driver"); MODULE_LICENSE("GPL v2"); -MODULE_VERSION("0.1"); +MODULE_VERSION("0.2"); static int force; /* = 0; */ module_param(force, bool, 0); @@ -58,7 +58,7 @@ MODULE_PARM_DESC(force, "Load even if computer is not in database"); static char *keymap_name; /* = NULL; */ module_param_named(keymap, keymap_name, charp, 0); -MODULE_PARM_DESC(keymap, "Keymap name, if it can't be autodetected"); +MODULE_PARM_DESC(keymap, "Keymap name, if it can't be autodetected [generic, 1557/MS2141]"); static struct platform_device *wistron_device; @@ -233,10 +233,20 @@ static void bios_set_state(u8 subsys, int enable) struct key_entry { char type; /* See KE_* below */ u8 code; - unsigned keycode; /* For KE_KEY */ + union { + u16 keycode; /* For KE_KEY */ + struct { /* For KE_SW */ + u8 code; + u8 value; + } sw; + }; }; -enum { KE_END, KE_KEY, KE_WIFI, KE_BLUETOOTH }; +enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH }; + +#define FE_MAIL_LED 0x01 +#define FE_WIFI_LED 0x02 +#define FE_UNTESTED 0x80 static const struct key_entry *keymap; /* = NULL; Current key map */ static int have_wifi; @@ -256,93 +266,341 @@ static int __init dmi_matched(struct dmi_system_id *dmi) return 1; } -static struct key_entry keymap_empty[] = { +static struct key_entry keymap_empty[] __initdata = { { KE_END, 0 } }; -static struct key_entry keymap_fs_amilo_pro_v2000[] = { - { KE_KEY, 0x01, KEY_HELP }, - { KE_KEY, 0x11, KEY_PROG1 }, - { KE_KEY, 0x12, KEY_PROG2 }, - { KE_WIFI, 0x30, 0 }, - { KE_KEY, 0x31, KEY_MAIL }, - { KE_KEY, 0x36, KEY_WWW }, +static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_WIFI, 0x30 }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x36, {KEY_WWW} }, { KE_END, 0 } }; -static struct key_entry keymap_fujitsu_n3510[] = { - { KE_KEY, 0x11, KEY_PROG1 }, - { KE_KEY, 0x12, KEY_PROG2 }, - { KE_KEY, 0x36, KEY_WWW }, - { KE_KEY, 0x31, KEY_MAIL }, - { KE_KEY, 0x71, KEY_STOPCD }, - { KE_KEY, 0x72, KEY_PLAYPAUSE }, - { KE_KEY, 0x74, KEY_REWIND }, - { KE_KEY, 0x78, KEY_FORWARD }, +static struct key_entry keymap_fujitsu_n3510[] __initdata = { + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_KEY, 0x36, {KEY_WWW} }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x71, {KEY_STOPCD} }, + { KE_KEY, 0x72, {KEY_PLAYPAUSE} }, + { KE_KEY, 0x74, {KEY_REWIND} }, + { KE_KEY, 0x78, {KEY_FORWARD} }, { KE_END, 0 } }; -static struct key_entry keymap_wistron_ms2111[] = { - { KE_KEY, 0x11, KEY_PROG1 }, - { KE_KEY, 0x12, KEY_PROG2 }, - { KE_KEY, 0x13, KEY_PROG3 }, - { KE_KEY, 0x31, KEY_MAIL }, - { KE_KEY, 0x36, KEY_WWW }, - { KE_END, 0 } +static struct key_entry keymap_wistron_ms2111[] __initdata = { + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_KEY, 0x13, {KEY_PROG3} }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x36, {KEY_WWW} }, + { KE_END, FE_MAIL_LED } +}; + +static struct key_entry keymap_wistron_md40100[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x02, {KEY_CONFIG} }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x36, {KEY_WWW} }, + { KE_KEY, 0x37, {KEY_DISPLAYTOGGLE} }, /* Display on/off */ + { KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED } }; -static struct key_entry keymap_wistron_ms2141[] = { - { KE_KEY, 0x11, KEY_PROG1 }, - { KE_KEY, 0x12, KEY_PROG2 }, - { KE_WIFI, 0x30, 0 }, - { KE_KEY, 0x22, KEY_REWIND }, - { KE_KEY, 0x23, KEY_FORWARD }, - { KE_KEY, 0x24, KEY_PLAYPAUSE }, - { KE_KEY, 0x25, KEY_STOPCD }, - { KE_KEY, 0x31, KEY_MAIL }, - { KE_KEY, 0x36, KEY_WWW }, +static struct key_entry keymap_wistron_ms2141[] __initdata = { + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_WIFI, 0x30 }, + { KE_KEY, 0x22, {KEY_REWIND} }, + { KE_KEY, 0x23, {KEY_FORWARD} }, + { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, + { KE_KEY, 0x25, {KEY_STOPCD} }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x36, {KEY_WWW} }, { KE_END, 0 } }; -static struct key_entry keymap_acer_aspire_1500[] = { - { KE_KEY, 0x11, KEY_PROG1 }, - { KE_KEY, 0x12, KEY_PROG2 }, - { KE_WIFI, 0x30, 0 }, - { KE_KEY, 0x31, KEY_MAIL }, - { KE_KEY, 0x36, KEY_WWW }, - { KE_BLUETOOTH, 0x44, 0 }, - { KE_END, 0 } +static struct key_entry keymap_acer_aspire_1500[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x03, {KEY_POWER} }, + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_WIFI, 0x30 }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x36, {KEY_WWW} }, + { KE_KEY, 0x49, {KEY_CONFIG} }, + { KE_BLUETOOTH, 0x44 }, + { KE_END, FE_UNTESTED } }; -static struct key_entry keymap_acer_travelmate_240[] = { - { KE_KEY, 0x31, KEY_MAIL }, - { KE_KEY, 0x36, KEY_WWW }, - { KE_KEY, 0x11, KEY_PROG1 }, - { KE_KEY, 0x12, KEY_PROG2 }, - { KE_BLUETOOTH, 0x44, 0 }, - { KE_WIFI, 0x30, 0 }, - { KE_END, 0 } +static struct key_entry keymap_acer_aspire_1600[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x03, {KEY_POWER} }, + { KE_KEY, 0x08, {KEY_MUTE} }, + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_KEY, 0x13, {KEY_PROG3} }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x36, {KEY_WWW} }, + { KE_KEY, 0x49, {KEY_CONFIG} }, + { KE_WIFI, 0x30 }, + { KE_BLUETOOTH, 0x44 }, + { KE_END, FE_MAIL_LED | FE_UNTESTED } +}; + +/* 3020 has been tested */ +static struct key_entry keymap_acer_aspire_5020[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x03, {KEY_POWER} }, + { KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */ + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x36, {KEY_WWW} }, + { KE_KEY, 0x6a, {KEY_CONFIG} }, + { KE_WIFI, 0x30 }, + { KE_BLUETOOTH, 0x44 }, + { KE_END, FE_MAIL_LED | FE_UNTESTED } +}; + +static struct key_entry keymap_acer_travelmate_2410[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x6d, {KEY_POWER} }, + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x36, {KEY_WWW} }, + { KE_KEY, 0x6a, {KEY_CONFIG} }, + { KE_WIFI, 0x30 }, + { KE_BLUETOOTH, 0x44 }, + { KE_END, FE_MAIL_LED | FE_UNTESTED } +}; + +static struct key_entry keymap_acer_travelmate_110[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x02, {KEY_CONFIG} }, + { KE_KEY, 0x03, {KEY_POWER} }, + { KE_KEY, 0x08, {KEY_MUTE} }, + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_KEY, 0x20, {KEY_VOLUMEUP} }, + { KE_KEY, 0x21, {KEY_VOLUMEDOWN} }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x36, {KEY_WWW} }, + { KE_SW, 0x4a, {.sw = {SW_LID, 1}} }, /* lid close */ + { KE_SW, 0x4b, {.sw = {SW_LID, 0}} }, /* lid open */ + { KE_WIFI, 0x30 }, + { KE_END, FE_MAIL_LED | FE_UNTESTED } +}; + +static struct key_entry keymap_acer_travelmate_300[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x02, {KEY_CONFIG} }, + { KE_KEY, 0x03, {KEY_POWER} }, + { KE_KEY, 0x08, {KEY_MUTE} }, + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_KEY, 0x20, {KEY_VOLUMEUP} }, + { KE_KEY, 0x21, {KEY_VOLUMEDOWN} }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x36, {KEY_WWW} }, + { KE_WIFI, 0x30 }, + { KE_BLUETOOTH, 0x44 }, + { KE_END, FE_MAIL_LED | FE_UNTESTED } }; -static struct key_entry keymap_aopen_1559as[] = { - { KE_KEY, 0x01, KEY_HELP }, - { KE_KEY, 0x06, KEY_PROG3 }, - { KE_KEY, 0x11, KEY_PROG1 }, - { KE_KEY, 0x12, KEY_PROG2 }, - { KE_WIFI, 0x30, 0 }, - { KE_KEY, 0x31, KEY_MAIL }, - { KE_KEY, 0x36, KEY_WWW }, +static struct key_entry keymap_acer_travelmate_380[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x02, {KEY_CONFIG} }, + { KE_KEY, 0x03, {KEY_POWER} }, /* not 370 */ + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_KEY, 0x13, {KEY_PROG3} }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x36, {KEY_WWW} }, + { KE_WIFI, 0x30 }, + { KE_END, FE_MAIL_LED | FE_UNTESTED } +}; + +/* unusual map */ +static struct key_entry keymap_acer_travelmate_220[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x02, {KEY_CONFIG} }, + { KE_KEY, 0x11, {KEY_MAIL} }, + { KE_KEY, 0x12, {KEY_WWW} }, + { KE_KEY, 0x13, {KEY_PROG2} }, + { KE_KEY, 0x31, {KEY_PROG1} }, + { KE_END, FE_WIFI_LED | FE_UNTESTED } +}; + +static struct key_entry keymap_acer_travelmate_230[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x02, {KEY_CONFIG} }, + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x36, {KEY_WWW} }, + { KE_END, FE_WIFI_LED | FE_UNTESTED } +}; + +static struct key_entry keymap_acer_travelmate_240[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x02, {KEY_CONFIG} }, + { KE_KEY, 0x03, {KEY_POWER} }, + { KE_KEY, 0x08, {KEY_MUTE} }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x36, {KEY_WWW} }, + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_BLUETOOTH, 0x44 }, + { KE_WIFI, 0x30 }, + { KE_END, FE_UNTESTED } +}; + +static struct key_entry keymap_acer_travelmate_350[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x02, {KEY_CONFIG} }, + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_KEY, 0x13, {KEY_MAIL} }, + { KE_KEY, 0x14, {KEY_PROG3} }, + { KE_KEY, 0x15, {KEY_WWW} }, + { KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED } +}; + +static struct key_entry keymap_acer_travelmate_360[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x02, {KEY_CONFIG} }, + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_KEY, 0x13, {KEY_MAIL} }, + { KE_KEY, 0x14, {KEY_PROG3} }, + { KE_KEY, 0x15, {KEY_WWW} }, + { KE_KEY, 0x40, {KEY_WLAN} }, + { KE_END, FE_WIFI_LED | FE_UNTESTED } /* no mail led */ +}; + +/* Wifi subsystem only activates the led. Therefore we need to pass + * wifi event as a normal key, then userspace can really change the wifi state. + * TODO we need to export led state to userspace (wifi and mail) */ +static struct key_entry keymap_acer_travelmate_610[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x02, {KEY_CONFIG} }, + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_KEY, 0x13, {KEY_PROG3} }, + { KE_KEY, 0x14, {KEY_MAIL} }, + { KE_KEY, 0x15, {KEY_WWW} }, + { KE_KEY, 0x40, {KEY_WLAN} }, + { KE_END, FE_MAIL_LED | FE_WIFI_LED } +}; + +static struct key_entry keymap_acer_travelmate_630[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x02, {KEY_CONFIG} }, + { KE_KEY, 0x03, {KEY_POWER} }, + { KE_KEY, 0x08, {KEY_MUTE} }, /* not 620 */ + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_KEY, 0x13, {KEY_PROG3} }, + { KE_KEY, 0x20, {KEY_VOLUMEUP} }, + { KE_KEY, 0x21, {KEY_VOLUMEDOWN} }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x36, {KEY_WWW} }, + { KE_WIFI, 0x30 }, + { KE_END, FE_MAIL_LED | FE_UNTESTED } +}; + +static struct key_entry keymap_aopen_1559as[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x06, {KEY_PROG3} }, + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_WIFI, 0x30 }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x36, {KEY_WWW} }, { KE_END, 0 }, }; -static struct key_entry keymap_fs_amilo_d88x0[] = { - { KE_KEY, 0x01, KEY_HELP }, - { KE_KEY, 0x08, KEY_MUTE }, - { KE_KEY, 0x31, KEY_MAIL }, - { KE_KEY, 0x36, KEY_WWW }, - { KE_KEY, 0x11, KEY_PROG1 }, - { KE_KEY, 0x12, KEY_PROG2 }, - { KE_KEY, 0x13, KEY_PROG3 }, +static struct key_entry keymap_fs_amilo_d88x0[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x08, {KEY_MUTE} }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x36, {KEY_WWW} }, + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_KEY, 0x13, {KEY_PROG3} }, + { KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED } +}; + +static struct key_entry keymap_wistron_md2900[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x02, {KEY_CONFIG} }, + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x36, {KEY_WWW} }, + { KE_WIFI, 0x30 }, + { KE_END, FE_MAIL_LED | FE_UNTESTED } +}; + +static struct key_entry keymap_wistron_md96500[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x02, {KEY_CONFIG} }, + { KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */ + { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Display on/off */ + { KE_KEY, 0x08, {KEY_MUTE} }, + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_KEY, 0x20, {KEY_VOLUMEUP} }, + { KE_KEY, 0x21, {KEY_VOLUMEDOWN} }, + { KE_KEY, 0x22, {KEY_REWIND} }, + { KE_KEY, 0x23, {KEY_FORWARD} }, + { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, + { KE_KEY, 0x25, {KEY_STOPCD} }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x36, {KEY_WWW} }, + { KE_WIFI, 0x30 }, + { KE_BLUETOOTH, 0x44 }, + { KE_END, FE_UNTESTED } +}; + +static struct key_entry keymap_wistron_generic[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, + { KE_KEY, 0x02, {KEY_CONFIG} }, + { KE_KEY, 0x03, {KEY_POWER} }, + { KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */ + { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Display on/off */ + { KE_KEY, 0x08, {KEY_MUTE} }, + { KE_KEY, 0x11, {KEY_PROG1} }, + { KE_KEY, 0x12, {KEY_PROG2} }, + { KE_KEY, 0x13, {KEY_PROG3} }, + { KE_KEY, 0x14, {KEY_MAIL} }, + { KE_KEY, 0x15, {KEY_WWW} }, + { KE_KEY, 0x20, {KEY_VOLUMEUP} }, + { KE_KEY, 0x21, {KEY_VOLUMEDOWN} }, + { KE_KEY, 0x22, {KEY_REWIND} }, + { KE_KEY, 0x23, {KEY_FORWARD} }, + { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, + { KE_KEY, 0x25, {KEY_STOPCD} }, + { KE_KEY, 0x31, {KEY_MAIL} }, + { KE_KEY, 0x36, {KEY_WWW} }, + { KE_KEY, 0x37, {KEY_DISPLAYTOGGLE} }, /* Display on/off */ + { KE_KEY, 0x40, {KEY_WLAN} }, + { KE_KEY, 0x49, {KEY_CONFIG} }, + { KE_SW, 0x4a, {.sw = {SW_LID, 1}} }, /* lid close */ + { KE_SW, 0x4b, {.sw = {SW_LID, 0}} }, /* lid open */ + { KE_KEY, 0x6a, {KEY_CONFIG} }, + { KE_KEY, 0x6d, {KEY_POWER} }, + { KE_KEY, 0x71, {KEY_STOPCD} }, + { KE_KEY, 0x72, {KEY_PLAYPAUSE} }, + { KE_KEY, 0x74, {KEY_REWIND} }, + { KE_KEY, 0x78, {KEY_FORWARD} }, + { KE_WIFI, 0x30 }, + { KE_BLUETOOTH, 0x44 }, { KE_END, 0 } }; @@ -390,6 +648,133 @@ static struct dmi_system_id dmi_ids[] __initdata = { }, { .callback = dmi_matched, + .ident = "Acer Aspire 1600", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1600"), + }, + .driver_data = keymap_acer_aspire_1600 + }, + { + .callback = dmi_matched, + .ident = "Acer Aspire 3020", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3020"), + }, + .driver_data = keymap_acer_aspire_5020 + }, + { + .callback = dmi_matched, + .ident = "Acer Aspire 5020", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5020"), + }, + .driver_data = keymap_acer_aspire_5020 + }, + { + .callback = dmi_matched, + .ident = "Acer TravelMate 2100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2100"), + }, + .driver_data = keymap_acer_aspire_5020 + }, + { + .callback = dmi_matched, + .ident = "Acer TravelMate 2410", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2410"), + }, + .driver_data = keymap_acer_travelmate_2410 + }, + { + .callback = dmi_matched, + .ident = "Acer TravelMate C300", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C300"), + }, + .driver_data = keymap_acer_travelmate_300 + }, + { + .callback = dmi_matched, + .ident = "Acer TravelMate C100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C100"), + }, + .driver_data = keymap_acer_travelmate_300 + }, + { + .callback = dmi_matched, + .ident = "Acer TravelMate C110", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C110"), + }, + .driver_data = keymap_acer_travelmate_110 + }, + { + .callback = dmi_matched, + .ident = "Acer TravelMate 380", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 380"), + }, + .driver_data = keymap_acer_travelmate_380 + }, + { + .callback = dmi_matched, + .ident = "Acer TravelMate 370", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 370"), + }, + .driver_data = keymap_acer_travelmate_380 /* keyboard minus 1 key */ + }, + { + .callback = dmi_matched, + .ident = "Acer TravelMate 220", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 220"), + }, + .driver_data = keymap_acer_travelmate_220 + }, + { + .callback = dmi_matched, + .ident = "Acer TravelMate 260", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 260"), + }, + .driver_data = keymap_acer_travelmate_220 + }, + { + .callback = dmi_matched, + .ident = "Acer TravelMate 230", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 230"), + /* acerhk looks for "TravelMate F4..." ?! */ + }, + .driver_data = keymap_acer_travelmate_230 + }, + { + .callback = dmi_matched, + .ident = "Acer TravelMate 280", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 280"), + }, + .driver_data = keymap_acer_travelmate_230 + }, + { + .callback = dmi_matched, .ident = "Acer TravelMate 240", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), @@ -399,6 +784,15 @@ static struct dmi_system_id dmi_ids[] __initdata = { }, { .callback = dmi_matched, + .ident = "Acer TravelMate 250", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 250"), + }, + .driver_data = keymap_acer_travelmate_240 + }, + { + .callback = dmi_matched, .ident = "Acer TravelMate 2424NWXCi", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), @@ -408,6 +802,51 @@ static struct dmi_system_id dmi_ids[] __initdata = { }, { .callback = dmi_matched, + .ident = "Acer TravelMate 350", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 350"), + }, + .driver_data = keymap_acer_travelmate_350 + }, + { + .callback = dmi_matched, + .ident = "Acer TravelMate 360", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), + }, + .driver_data = keymap_acer_travelmate_360 + }, + { + .callback = dmi_matched, + .ident = "Acer TravelMate 610", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ACER"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 610"), + }, + .driver_data = keymap_acer_travelmate_610 + }, + { + .callback = dmi_matched, + .ident = "Acer TravelMate 620", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 620"), + }, + .driver_data = keymap_acer_travelmate_630 + }, + { + .callback = dmi_matched, + .ident = "Acer TravelMate 630", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 630"), + }, + .driver_data = keymap_acer_travelmate_630 + }, + { + .callback = dmi_matched, .ident = "AOpen 1559AS", .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "E2U"), @@ -426,6 +865,51 @@ static struct dmi_system_id dmi_ids[] __initdata = { }, { .callback = dmi_matched, + .ident = "Medion MD 40100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), + DMI_MATCH(DMI_PRODUCT_NAME, "WID2000"), + }, + .driver_data = keymap_wistron_md40100 + }, + { + .callback = dmi_matched, + .ident = "Medion MD 2900", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), + DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2000"), + }, + .driver_data = keymap_wistron_md2900 + }, + { + .callback = dmi_matched, + .ident = "Medion MD 96500", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"), + DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2040"), + }, + .driver_data = keymap_wistron_md96500 + }, + { + .callback = dmi_matched, + .ident = "Medion MD 95400", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"), + DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2050"), + }, + .driver_data = keymap_wistron_md96500 + }, + { + .callback = dmi_matched, + .ident = "Fujitsu Siemens Amilo D7820", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), /* not sure */ + DMI_MATCH(DMI_PRODUCT_NAME, "Amilo D"), + }, + .driver_data = keymap_fs_amilo_d88x0 + }, + { + .callback = dmi_matched, .ident = "Fujitsu Siemens Amilo D88x0", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), @@ -436,17 +920,39 @@ static struct dmi_system_id dmi_ids[] __initdata = { { NULL, } }; +/* Copy the good keymap, as the original ones are free'd */ +static int __init copy_keymap(void) +{ + const struct key_entry *key; + struct key_entry *new_keymap; + unsigned int length = 1; + + for (key = keymap; key->type != KE_END; key++) + length++; + + new_keymap = kmalloc(length * sizeof(struct key_entry), GFP_KERNEL); + if (!new_keymap) + return -ENOMEM; + + memcpy(new_keymap, keymap, length * sizeof(struct key_entry)); + keymap = new_keymap; + + return 0; +} + static int __init select_keymap(void) { + dmi_check_system(dmi_ids); if (keymap_name != NULL) { if (strcmp (keymap_name, "1557/MS2141") == 0) keymap = keymap_wistron_ms2141; + else if (strcmp (keymap_name, "generic") == 0) + keymap = keymap_wistron_generic; else { printk(KERN_ERR "wistron_btns: Keymap unknown\n"); return -EINVAL; } } - dmi_check_system(dmi_ids); if (keymap == NULL) { if (!force) { printk(KERN_ERR "wistron_btns: System unknown\n"); @@ -454,7 +960,8 @@ static int __init select_keymap(void) } keymap = keymap_empty; } - return 0; + + return copy_keymap(); } /* Input layer interface */ @@ -476,12 +983,28 @@ static int __devinit setup_input_dev(void) input_dev->cdev.dev = &wistron_device->dev; for (key = keymap; key->type != KE_END; key++) { - if (key->type == KE_KEY) { - input_dev->evbit[LONG(EV_KEY)] = BIT(EV_KEY); - set_bit(key->keycode, input_dev->keybit); + switch (key->type) { + case KE_KEY: + set_bit(EV_KEY, input_dev->evbit); + set_bit(key->keycode, input_dev->keybit); + break; + + case KE_SW: + set_bit(EV_SW, input_dev->evbit); + set_bit(key->sw.code, input_dev->swbit); + break; + + default: + ; } } + /* reads information flags on KE_END */ + if (key->code & FE_UNTESTED) + printk(KERN_WARNING "Untested laptop multimedia keys, " + "please report success or failure to eric.piel" + "@tremplin-utc.net\n"); + error = input_register_device(input_dev); if (error) { input_free_device(input_dev); @@ -499,6 +1022,12 @@ static void report_key(unsigned keycode) input_sync(input_dev); } +static void report_switch(unsigned code, int value) +{ + input_report_switch(input_dev, code, value); + input_sync(input_dev); +} + /* Driver core */ static int wifi_enabled; @@ -519,6 +1048,10 @@ static void handle_key(u8 code) report_key(key->keycode); break; + case KE_SW: + report_switch(key->sw.code, key->sw.value); + break; + case KE_WIFI: if (have_wifi) { wifi_enabled = !wifi_enabled; @@ -534,6 +1067,7 @@ static void handle_key(u8 code) break; case KE_END: + break; default: BUG(); } @@ -690,6 +1224,7 @@ static void __exit wb_module_exit(void) platform_device_unregister(wistron_device); platform_driver_unregister(&wistron_driver); unmap_bios(); + kfree(keymap); } module_init(wb_module_init); diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index b40784a..81dd8c7 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -37,6 +37,65 @@ config MOUSE_PS2 To compile this driver as a module, choose M here: the module will be called psmouse. +config MOUSE_PS2_ALPS + bool "ALPS PS/2 mouse protocol extension" if EMBEDDED + default y + depends on MOUSE_PS2 + ---help--- + Say Y here if you have an ALPS PS/2 touchpad connected to + your system. + + If unsure, say Y. + +config MOUSE_PS2_LOGIPS2PP + bool "Logictech PS/2++ mouse protocol extension" if EMBEDDED + default y + depends on MOUSE_PS2 + ---help--- + Say Y here if you have a Logictech PS/2++ mouse connected to + your system. + + If unsure, say Y. + +config MOUSE_PS2_SYNAPTICS + bool "Synaptics PS/2 mouse protocol extension" if EMBEDDED + default y + depends on MOUSE_PS2 + ---help--- + Say Y here if you have a Synaptics PS/2 TouchPad connected to + your system. + + If unsure, say Y. + +config MOUSE_PS2_LIFEBOOK + bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED + default y + depends on MOUSE_PS2 + ---help--- + Say Y here if you have a Fujitsu B-series Lifebook PS/2 + TouchScreen connected to your system. + + If unsure, say Y. + +config MOUSE_PS2_TRACKPOINT + bool "IBM Trackpoint PS/2 mouse protocol extension" if EMBEDDED + default y + depends on MOUSE_PS2 + ---help--- + Say Y here if you have an IBM Trackpoint PS/2 mouse connected + to your system. + + If unsure, say Y. + +config MOUSE_PS2_TOUCHKIT + bool "eGalax TouchKit PS/2 protocol extension" + depends on MOUSE_PS2 + ---help--- + Say Y here if you have an eGalax TouchKit PS/2 touchscreen + connected to your system. + + If unsure, say N. + config MOUSE_SERIAL tristate "Serial mouse" select SERIO @@ -129,7 +188,7 @@ config MOUSE_VSXXXAA digitizer (VSXXX-AB) DEC produced. config MOUSE_HIL - tristate "HIL pointers (mice etc)." + tristate "HIL pointers (mice etc)." depends on GSC || HP300 select HP_SDC select HIL_MLC diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 700f612..6a8f622 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -15,4 +15,10 @@ obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o -psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o trackpoint.o +psmouse-objs := psmouse-base.o synaptics.o + +psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o +psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o +psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o +psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o +psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 4e71a66..cf3e466 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -424,14 +424,15 @@ int alps_init(struct psmouse *psmouse) struct input_dev *dev1 = psmouse->dev, *dev2; int version; - psmouse->private = priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL); + priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL); dev2 = input_allocate_device(); if (!priv || !dev2) goto init_fail; priv->dev2 = dev2; - if (!(priv->i = alps_get_model(psmouse, &version))) + priv->i = alps_get_model(psmouse, &version); + if (!priv->i) goto init_fail; if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 1)) @@ -480,7 +481,8 @@ int alps_init(struct psmouse *psmouse) dev2->relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y); dev2->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); - input_register_device(priv->dev2); + if (input_register_device(priv->dev2)) + goto init_fail; psmouse->protocol_handler = alps_process_byte; psmouse->poll = alps_poll; @@ -491,9 +493,11 @@ int alps_init(struct psmouse *psmouse) /* We are having trouble resyncing ALPS touchpads so disable it for now */ psmouse->resync_time = 0; + psmouse->private = priv; return 0; init_fail: + psmouse_reset(psmouse); input_free_device(dev2); kfree(priv); return -1; @@ -504,7 +508,8 @@ int alps_detect(struct psmouse *psmouse, int set_properties) int version; const struct alps_model_info *model; - if (!(model = alps_get_model(psmouse, &version))) + model = alps_get_model(psmouse, &version); + if (!model) return -1; if (set_properties) { diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index 69db732..4bbddc9 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h @@ -12,9 +12,6 @@ #ifndef _ALPS_H #define _ALPS_H -int alps_detect(struct psmouse *psmouse, int set_properties); -int alps_init(struct psmouse *psmouse); - struct alps_model_info { unsigned char signature[3]; unsigned char byte0, mask0; @@ -23,10 +20,23 @@ struct alps_model_info { struct alps_data { struct input_dev *dev2; /* Relative device */ - char name[32]; /* Name */ char phys[32]; /* Phys */ const struct alps_model_info *i;/* Info */ int prev_fin; /* Finger bit from previous packet */ }; +#ifdef CONFIG_MOUSE_PS2_ALPS +int alps_detect(struct psmouse *psmouse, int set_properties); +int alps_init(struct psmouse *psmouse); +#else +inline int alps_detect(struct psmouse *psmouse, int set_properties) +{ + return -ENOSYS; +} +inline int alps_init(struct psmouse *psmouse) +{ + return -ENOSYS; +} +#endif /* CONFIG_MOUSE_PS2_ALPS */ + #endif diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c index bfb174f..449bf4d 100644 --- a/drivers/input/mouse/hil_ptr.c +++ b/drivers/input/mouse/hil_ptr.c @@ -88,10 +88,12 @@ static void hil_ptr_process_record(struct hil_ptr *ptr) idx = ptr->idx4/4; p = data[idx - 1]; - if ((p & ~HIL_CMDCT_POL) == - (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report; - if ((p & ~HIL_CMDCT_RPL) == - (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report; + if ((p & ~HIL_CMDCT_POL) == + (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) + goto report; + if ((p & ~HIL_CMDCT_RPL) == + (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) + goto report; /* Not a poll response. See if we are loading config records. */ switch (p & HIL_PKT_DATA_MASK) { @@ -101,27 +103,32 @@ static void hil_ptr_process_record(struct hil_ptr *ptr) for (; i < HIL_PTR_MAX_LENGTH; i++) ptr->idd[i] = 0; break; + case HIL_CMD_RSC: for (i = 0; i < idx; i++) ptr->rsc[i] = ptr->data[i] & HIL_PKT_DATA_MASK; for (; i < HIL_PTR_MAX_LENGTH; i++) ptr->rsc[i] = 0; break; + case HIL_CMD_EXD: for (i = 0; i < idx; i++) ptr->exd[i] = ptr->data[i] & HIL_PKT_DATA_MASK; for (; i < HIL_PTR_MAX_LENGTH; i++) ptr->exd[i] = 0; break; + case HIL_CMD_RNM: for (i = 0; i < idx; i++) ptr->rnm[i] = ptr->data[i] & HIL_PKT_DATA_MASK; for (; i < HIL_PTR_MAX_LENGTH + 1; i++) - ptr->rnm[i] = '\0'; + ptr->rnm[i] = 0; break; + default: /* These occur when device isn't present */ - if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break; + if (p == (HIL_ERR_INT | HIL_PKT_CMD)) + break; /* Anything else we'd like to know about. */ printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); break; @@ -130,7 +137,8 @@ static void hil_ptr_process_record(struct hil_ptr *ptr) report: if ((p & HIL_CMDCT_POL) != idx - 1) { - printk(KERN_WARNING PREFIX "Malformed poll packet %x (idx = %i)\n", p, idx); + printk(KERN_WARNING PREFIX + "Malformed poll packet %x (idx = %i)\n", p, idx); goto out; } @@ -139,7 +147,7 @@ static void hil_ptr_process_record(struct hil_ptr *ptr) laxis += i; ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */ - absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; + absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; for (cnt = 1; i < laxis; i++) { unsigned int lo,hi,val; @@ -157,7 +165,8 @@ static void hil_ptr_process_record(struct hil_ptr *ptr) input_report_abs(dev, ABS_X + i, val); } else { val = (int) (((int8_t)lo) | ((int8_t)hi<<8)); - if (i%3) val *= -1; + if (i%3) + val *= -1; input_report_rel(dev, REL_X + i, val); } } @@ -168,10 +177,11 @@ static void hil_ptr_process_record(struct hil_ptr *ptr) btn = ptr->data[cnt++]; up = btn & 1; btn &= 0xfe; - if (btn == 0x8e) { + if (btn == 0x8e) continue; /* TODO: proximity == touch? */ - } - else if ((btn > 0x8c) || (btn < 0x80)) continue; + else + if ((btn > 0x8c) || (btn < 0x80)) + continue; btn = (btn - 0x80) >> 1; btn = ptr->btnmap[btn]; input_report_key(dev, btn, !up); @@ -182,14 +192,14 @@ static void hil_ptr_process_record(struct hil_ptr *ptr) up(&ptr->sem); } -static void hil_ptr_process_err(struct hil_ptr *ptr) { +static void hil_ptr_process_err(struct hil_ptr *ptr) +{ printk(KERN_WARNING PREFIX "errored HIL packet\n"); ptr->idx4 = 0; up(&ptr->sem); - return; } -static irqreturn_t hil_ptr_interrupt(struct serio *serio, +static irqreturn_t hil_ptr_interrupt(struct serio *serio, unsigned char data, unsigned int flags) { struct hil_ptr *ptr; @@ -197,29 +207,29 @@ static irqreturn_t hil_ptr_interrupt(struct serio *serio, int idx; ptr = serio_get_drvdata(serio); - if (ptr == NULL) { - BUG(); - return IRQ_HANDLED; - } + BUG_ON(ptr == NULL); if (ptr->idx4 >= (HIL_PTR_MAX_LENGTH * sizeof(hil_packet))) { hil_ptr_process_err(ptr); return IRQ_HANDLED; } idx = ptr->idx4/4; - if (!(ptr->idx4 % 4)) ptr->data[idx] = 0; + if (!(ptr->idx4 % 4)) + ptr->data[idx] = 0; packet = ptr->data[idx]; packet |= ((hil_packet)data) << ((3 - (ptr->idx4 % 4)) * 8); ptr->data[idx] = packet; /* Records of N 4-byte hil_packets must terminate with a command. */ - if ((++(ptr->idx4)) % 4) return IRQ_HANDLED; + if ((++(ptr->idx4)) % 4) + return IRQ_HANDLED; if ((packet & 0xffff0000) != HIL_ERR_INT) { hil_ptr_process_err(ptr); return IRQ_HANDLED; } - if (packet & HIL_PKT_CMD) + if (packet & HIL_PKT_CMD) hil_ptr_process_record(ptr); + return IRQ_HANDLED; } @@ -228,10 +238,7 @@ static void hil_ptr_disconnect(struct serio *serio) struct hil_ptr *ptr; ptr = serio_get_drvdata(serio); - if (ptr == NULL) { - BUG(); - return; - } + BUG_ON(ptr == NULL); serio_close(serio); input_unregister_device(ptr->dev); @@ -241,7 +248,7 @@ static void hil_ptr_disconnect(struct serio *serio) static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) { struct hil_ptr *ptr; - char *txt; + const char *txt; unsigned int i, naxsets, btntype; uint8_t did, *idd; @@ -252,42 +259,40 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) if (!ptr->dev) goto bail0; - ptr->dev->private = ptr; - if (serio_open(serio, driver)) goto bail1; serio_set_drvdata(serio, ptr); ptr->serio = serio; - init_MUTEX_LOCKED(&(ptr->sem)); + init_MUTEX_LOCKED(&ptr->sem); /* Get device info. MLC driver supplies devid/status/etc. */ serio->write(serio, 0); serio->write(serio, 0); serio->write(serio, HIL_PKT_CMD >> 8); serio->write(serio, HIL_CMD_IDD); - down(&(ptr->sem)); + down(&ptr->sem); serio->write(serio, 0); serio->write(serio, 0); serio->write(serio, HIL_PKT_CMD >> 8); serio->write(serio, HIL_CMD_RSC); - down(&(ptr->sem)); + down(&ptr->sem); serio->write(serio, 0); serio->write(serio, 0); serio->write(serio, HIL_PKT_CMD >> 8); serio->write(serio, HIL_CMD_RNM); - down(&(ptr->sem)); + down(&ptr->sem); serio->write(serio, 0); serio->write(serio, 0); serio->write(serio, HIL_PKT_CMD >> 8); serio->write(serio, HIL_CMD_EXD); - down(&(ptr->sem)); + down(&ptr->sem); - up(&(ptr->sem)); + up(&ptr->sem); did = ptr->idd[0]; idd = ptr->idd + 1; @@ -301,12 +306,12 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) ptr->dev->evbit[0] = BIT(EV_ABS); txt = "absolute"; } - if (!ptr->dev->evbit[0]) { + if (!ptr->dev->evbit[0]) goto bail2; - } ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd); - if (ptr->nbtn) ptr->dev->evbit[0] |= BIT(EV_KEY); + if (ptr->nbtn) + ptr->dev->evbit[0] |= BIT(EV_KEY); naxsets = HIL_IDD_NUM_AXSETS(*idd); ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd); @@ -315,7 +320,7 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) did, txt); printk(KERN_INFO PREFIX "HIL pointer has %i buttons and %i sets of %i axes\n", ptr->nbtn, naxsets, ptr->naxes); - + btntype = BTN_MISC; if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET) #ifdef TABLET_SIMULATES_MOUSE @@ -325,7 +330,7 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) #endif if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN) btntype = BTN_TOUCH; - + if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE) btntype = BTN_MOUSE; @@ -341,12 +346,10 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) } if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) { - for (i = 0; i < ptr->naxes; i++) { + for (i = 0; i < ptr->naxes; i++) set_bit(REL_X + i, ptr->dev->relbit); - } - for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) { + for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) set_bit(REL_X + i, ptr->dev->relbit); - } } else { for (i = 0; i < ptr->naxes; i++) { set_bit(ABS_X + i, ptr->dev->absbit); @@ -375,7 +378,7 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) ptr->dev->id.vendor = PCI_VENDOR_ID_HP; ptr->dev->id.product = 0x0001; /* TODO: get from ptr->rsc */ ptr->dev->id.version = 0x0100; /* TODO: get from ptr->rsc */ - ptr->dev->cdev.dev = &serio->dev; + ptr->dev->dev.parent = &serio->dev; input_register_device(ptr->dev); printk(KERN_INFO "input: %s (%s), ID: %d\n", @@ -419,11 +422,11 @@ static int __init hil_ptr_init(void) { return serio_register_driver(&hil_ptr_serio_driver); } - + static void __exit hil_ptr_exit(void) { serio_unregister_driver(&hil_ptr_serio_driver); } - + module_init(hil_ptr_init); module_exit(hil_ptr_exit); diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index 29542f0..1740cad 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c @@ -20,6 +20,27 @@ #include "psmouse.h" #include "lifebook.h" +struct lifebook_data { + struct input_dev *dev2; /* Relative device */ + char phys[32]; +}; + +static const char *desired_serio_phys; + +static int lifebook_set_serio_phys(struct dmi_system_id *d) +{ + desired_serio_phys = d->driver_data; + return 0; +} + +static unsigned char lifebook_use_6byte_proto; + +static int lifebook_set_6byte_proto(struct dmi_system_id *d) +{ + lifebook_use_6byte_proto = 1; + return 0; +} + static struct dmi_system_id lifebook_dmi_table[] = { { .ident = "FLORA-ie 55mi", @@ -56,6 +77,24 @@ static struct dmi_system_id lifebook_dmi_table[] = { .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"), }, + .callback = lifebook_set_serio_phys, + .driver_data = "isa0060/serio3", + }, + { + .ident = "Panasonic CF-28", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"), + DMI_MATCH(DMI_PRODUCT_NAME, "CF-28"), + }, + .callback = lifebook_set_6byte_proto, + }, + { + .ident = "Panasonic CF-29", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"), + DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"), + }, + .callback = lifebook_set_6byte_proto, }, { .ident = "Lifebook B142", @@ -68,30 +107,70 @@ static struct dmi_system_id lifebook_dmi_table[] = { static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) { + struct lifebook_data *priv = psmouse->private; + struct input_dev *dev1 = psmouse->dev; + struct input_dev *dev2 = priv->dev2; unsigned char *packet = psmouse->packet; - struct input_dev *dev = psmouse->dev; + int relative_packet = packet[0] & 0x08; - if (psmouse->pktcnt != 3) - return PSMOUSE_GOOD_DATA; + if (relative_packet || !lifebook_use_6byte_proto) { + if (psmouse->pktcnt != 3) + return PSMOUSE_GOOD_DATA; + } else { + switch (psmouse->pktcnt) { + case 1: + return (packet[0] & 0xf8) == 0x00 ? + PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; + case 2: + return PSMOUSE_GOOD_DATA; + case 3: + return ((packet[2] & 0x30) << 2) == (packet[2] & 0xc0) ? + PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; + case 4: + return (packet[3] & 0xf8) == 0xc0 ? + PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; + case 5: + return (packet[4] & 0xc0) == (packet[2] & 0xc0) ? + PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; + case 6: + if (((packet[5] & 0x30) << 2) != (packet[5] & 0xc0)) + return PSMOUSE_BAD_DATA; + if ((packet[5] & 0xc0) != (packet[1] & 0xc0)) + return PSMOUSE_BAD_DATA; + break; /* report data */ + } + } - /* calculate X and Y */ - if ((packet[0] & 0x08) == 0x00) { - input_report_abs(dev, ABS_X, + if (relative_packet) { + if (!dev2) + printk(KERN_WARNING "lifebook.c: got relative packet " + "but no relative device set up\n"); + } else if (lifebook_use_6byte_proto) { + input_report_abs(dev1, ABS_X, + ((packet[1] & 0x3f) << 6) | (packet[2] & 0x3f)); + input_report_abs(dev1, ABS_Y, + 4096 - (((packet[4] & 0x3f) << 6) | (packet[5] & 0x3f))); + } else { + input_report_abs(dev1, ABS_X, (packet[1] | ((packet[0] & 0x30) << 4))); - input_report_abs(dev, ABS_Y, + input_report_abs(dev1, ABS_Y, 1024 - (packet[2] | ((packet[0] & 0xC0) << 2))); - } else { - input_report_rel(dev, REL_X, - ((packet[0] & 0x10) ? packet[1] - 256 : packet[1])); - input_report_rel(dev, REL_Y, - -(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2])); } - input_report_key(dev, BTN_LEFT, packet[0] & 0x01); - input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); - input_report_key(dev, BTN_TOUCH, packet[0] & 0x04); + input_report_key(dev1, BTN_TOUCH, packet[0] & 0x04); + input_sync(dev1); - input_sync(dev); + if (dev2) { + if (relative_packet) { + input_report_rel(dev2, REL_X, + ((packet[0] & 0x10) ? packet[1] - 256 : packet[1])); + input_report_rel(dev2, REL_Y, + -(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2])); + } + input_report_key(dev2, BTN_LEFT, packet[0] & 0x01); + input_report_key(dev2, BTN_RIGHT, packet[0] & 0x02); + input_sync(dev2); + } return PSMOUSE_FULL_PACKET; } @@ -109,12 +188,20 @@ static int lifebook_absolute_mode(struct psmouse *psmouse) you leave this call out the touchsreen will never send absolute coordinates */ - param = 0x07; + param = lifebook_use_6byte_proto ? 0x08 : 0x07; ps2_command(ps2dev, ¶m, PSMOUSE_CMD_SETRES); return 0; } +static void lifebook_relative_mode(struct psmouse *psmouse) +{ + struct ps2dev *ps2dev = &psmouse->ps2dev; + unsigned char param = 0x06; + + ps2_command(ps2dev, ¶m, PSMOUSE_CMD_SETRES); +} + static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolution) { static const unsigned char params[] = { 0, 1, 2, 2, 3 }; @@ -131,6 +218,8 @@ static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolu static void lifebook_disconnect(struct psmouse *psmouse) { psmouse_reset(psmouse); + kfree(psmouse->private); + psmouse->private = NULL; } int lifebook_detect(struct psmouse *psmouse, int set_properties) @@ -138,6 +227,10 @@ int lifebook_detect(struct psmouse *psmouse, int set_properties) if (!dmi_check_system(lifebook_dmi_table)) return -1; + if (desired_serio_phys && + strcmp(psmouse->ps2dev.serio->phys, desired_serio_phys)) + return -1; + if (set_properties) { psmouse->vendor = "Fujitsu"; psmouse->name = "Lifebook TouchScreen"; @@ -146,24 +239,78 @@ int lifebook_detect(struct psmouse *psmouse, int set_properties) return 0; } +static int lifebook_create_relative_device(struct psmouse *psmouse) +{ + struct input_dev *dev2; + struct lifebook_data *priv; + int error = -ENOMEM; + + priv = kzalloc(sizeof(struct lifebook_data), GFP_KERNEL); + dev2 = input_allocate_device(); + if (!priv || !dev2) + goto err_out; + + priv->dev2 = dev2; + snprintf(priv->phys, sizeof(priv->phys), + "%s/input1", psmouse->ps2dev.serio->phys); + + dev2->phys = priv->phys; + dev2->name = "PS/2 Touchpad"; + dev2->id.bustype = BUS_I8042; + dev2->id.vendor = 0x0002; + dev2->id.product = PSMOUSE_LIFEBOOK; + dev2->id.version = 0x0000; + dev2->dev.parent = &psmouse->ps2dev.serio->dev; + + dev2->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); + dev2->relbit[LONG(REL_X)] = BIT(REL_X) | BIT(REL_Y); + dev2->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT); + + error = input_register_device(priv->dev2); + if (error) + goto err_out; + + psmouse->private = priv; + return 0; + + err_out: + input_free_device(dev2); + kfree(priv); + return error; +} + int lifebook_init(struct psmouse *psmouse) { - struct input_dev *input_dev = psmouse->dev; + struct input_dev *dev1 = psmouse->dev; + int max_coord = lifebook_use_6byte_proto ? 1024 : 4096; if (lifebook_absolute_mode(psmouse)) return -1; - input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL); - input_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); - input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); - input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y); - input_set_abs_params(input_dev, ABS_X, 0, 1024, 0, 0); - input_set_abs_params(input_dev, ABS_Y, 0, 1024, 0, 0); + dev1->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY); + dev1->relbit[0] = 0; + dev1->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); + input_set_abs_params(dev1, ABS_X, 0, max_coord, 0, 0); + input_set_abs_params(dev1, ABS_Y, 0, max_coord, 0, 0); + + if (!desired_serio_phys) { + if (lifebook_create_relative_device(psmouse)) { + lifebook_relative_mode(psmouse); + return -1; + } + } psmouse->protocol_handler = lifebook_process_byte; psmouse->set_resolution = lifebook_set_resolution; psmouse->disconnect = lifebook_disconnect; psmouse->reconnect = lifebook_absolute_mode; + + psmouse->model = lifebook_use_6byte_proto ? 6 : 3; + + /* + * Use packet size = 3 even when using 6-byte protocol because + * that's what POLL will return on Lifebooks (according to spec). + */ psmouse->pktsize = 3; return 0; diff --git a/drivers/input/mouse/lifebook.h b/drivers/input/mouse/lifebook.h index be1c094..c1647cf 100644 --- a/drivers/input/mouse/lifebook.h +++ b/drivers/input/mouse/lifebook.h @@ -11,7 +11,18 @@ #ifndef _LIFEBOOK_H #define _LIFEBOOK_H +#ifdef CONFIG_MOUSE_PS2_LIFEBOOK int lifebook_detect(struct psmouse *psmouse, int set_properties); int lifebook_init(struct psmouse *psmouse); +#else +inline int lifebook_detect(struct psmouse *psmouse, int set_properties) +{ + return -ENOSYS; +} +inline int lifebook_init(struct psmouse *psmouse) +{ + return -ENOSYS; +} +#endif #endif diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index d3ddea2..9df74b7 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c @@ -200,6 +200,7 @@ static void ps2pp_disconnect(struct psmouse *psmouse) static const struct ps2pp_info *get_model_info(unsigned char model) { static const struct ps2pp_info ps2pp_list[] = { + { 1, 0, 0 }, /* Simple 2-button mouse */ { 12, 0, PS2PP_SIDE_BTN}, { 13, 0, 0 }, { 15, PS2PP_KIND_MX, /* MX1000 */ @@ -338,12 +339,12 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) param[1] = 0; ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO); - if (!param[1]) - return -1; - model = ((param[0] >> 4) & 0x07) | ((param[0] << 3) & 0x78); buttons = param[1]; + if (!model || !buttons) + return -1; + if ((model_info = get_model_info(model)) != NULL) { /* diff --git a/drivers/input/mouse/logips2pp.h b/drivers/input/mouse/logips2pp.h index 64a8ec5..6e57125 100644 --- a/drivers/input/mouse/logips2pp.h +++ b/drivers/input/mouse/logips2pp.h @@ -11,6 +11,13 @@ #ifndef _LOGIPS2PP_H #define _LOGIPS2PP_H +#ifdef CONFIG_MOUSE_PS2_LOGIPS2PP int ps2pp_init(struct psmouse *psmouse, int set_properties); +#else +inline int ps2pp_init(struct psmouse *psmouse, int set_properties) +{ + return -ENOSYS; +} +#endif /* CONFIG_MOUSE_PS2_LOGIPS2PP */ #endif diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 0fe5869..f15f695 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -28,6 +28,7 @@ #include "alps.h" #include "lifebook.h" #include "trackpoint.h" +#include "touchkit_ps2.h" #define DRIVER_DESC "PS/2 mouse driver" @@ -569,7 +570,9 @@ static int psmouse_extensions(struct psmouse *psmouse, return PSMOUSE_THINKPS; /* - * Try Synaptics TouchPad + * Try Synaptics TouchPad. Note that probing is done even if Synaptics protocol + * support is disabled in config - we need to know if it is synaptics so we + * can reset it properly after probing for intellimouse. */ if (max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse, set_properties) == 0) { synaptics_hardware = 1; @@ -605,14 +608,20 @@ static int psmouse_extensions(struct psmouse *psmouse, } } - if (max_proto > PSMOUSE_IMEX && genius_detect(psmouse, set_properties) == 0) - return PSMOUSE_GENPS; + if (max_proto > PSMOUSE_IMEX) { + + if (genius_detect(psmouse, set_properties) == 0) + return PSMOUSE_GENPS; - if (max_proto > PSMOUSE_IMEX && ps2pp_init(psmouse, set_properties) == 0) - return PSMOUSE_PS2PP; + if (ps2pp_init(psmouse, set_properties) == 0) + return PSMOUSE_PS2PP; - if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0) - return PSMOUSE_TRACKPOINT; + if (trackpoint_detect(psmouse, set_properties) == 0) + return PSMOUSE_TRACKPOINT; + + if (touchkit_ps2_detect(psmouse, set_properties) == 0) + return PSMOUSE_TOUCHKIT_PS2; + } /* * Reset to defaults in case the device got confused by extended @@ -654,12 +663,14 @@ static const struct psmouse_protocol psmouse_protocols[] = { .maxproto = 1, .detect = ps2bare_detect, }, +#ifdef CONFIG_MOUSE_PS2_LOGIPS2PP { .type = PSMOUSE_PS2PP, .name = "PS2++", .alias = "logitech", .detect = ps2pp_init, }, +#endif { .type = PSMOUSE_THINKPS, .name = "ThinkPS/2", @@ -686,6 +697,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { .maxproto = 1, .detect = im_explorer_detect, }, +#ifdef CONFIG_MOUSE_PS2_SYNAPTICS { .type = PSMOUSE_SYNAPTICS, .name = "SynPS/2", @@ -693,6 +705,8 @@ static const struct psmouse_protocol psmouse_protocols[] = { .detect = synaptics_detect, .init = synaptics_init, }, +#endif +#ifdef CONFIG_MOUSE_PS2_ALPS { .type = PSMOUSE_ALPS, .name = "AlpsPS/2", @@ -700,18 +714,31 @@ static const struct psmouse_protocol psmouse_protocols[] = { .detect = alps_detect, .init = alps_init, }, +#endif +#ifdef CONFIG_MOUSE_PS2_LIFEBOOK { .type = PSMOUSE_LIFEBOOK, .name = "LBPS/2", .alias = "lifebook", .init = lifebook_init, }, +#endif +#ifdef CONFIG_MOUSE_PS2_TRACKPOINT { .type = PSMOUSE_TRACKPOINT, .name = "TPPS/2", .alias = "trackpoint", .detect = trackpoint_detect, }, +#endif +#ifdef CONFIG_MOUSE_PS2_TOUCHKIT + { + .type = PSMOUSE_TOUCHKIT_PS2, + .name = "touchkitPS/2", + .alias = "touchkit", + .detect = touchkit_ps2_detect, + }, +#endif { .type = PSMOUSE_AUTO, .name = "auto", @@ -823,12 +850,6 @@ static void psmouse_set_rate(struct psmouse *psmouse, unsigned int rate) static void psmouse_initialize(struct psmouse *psmouse) { /* - * We set the mouse into streaming mode. - */ - - ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM); - -/* * We set the mouse report rate, resolution and scaling. */ @@ -1062,8 +1083,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, const struct psmouse { struct input_dev *input_dev = psmouse->dev; - input_dev->private = psmouse; - input_dev->cdev.dev = &psmouse->ps2dev.serio->dev; + input_dev->dev.parent = &psmouse->ps2dev.serio->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index cf1de95..3964e8a 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -87,6 +87,7 @@ enum psmouse_type { PSMOUSE_ALPS, PSMOUSE_LIFEBOOK, PSMOUSE_TRACKPOINT, + PSMOUSE_TOUCHKIT_PS2, PSMOUSE_AUTO /* This one should always be last */ }; diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c index a85d747..77b8ee2 100644 --- a/drivers/input/mouse/sermouse.c +++ b/drivers/input/mouse/sermouse.c @@ -69,7 +69,8 @@ static void sermouse_process_msc(struct sermouse *sermouse, signed char data) switch (sermouse->count) { case 0: - if ((data & 0xf8) != 0x80) return; + if ((data & 0xf8) != 0x80) + return; input_report_key(dev, BTN_LEFT, !(data & 4)); input_report_key(dev, BTN_RIGHT, !(data & 1)); input_report_key(dev, BTN_MIDDLE, !(data & 2)); @@ -107,7 +108,10 @@ static void sermouse_process_ms(struct sermouse *sermouse, signed char data) struct input_dev *dev = sermouse->dev; signed char *buf = sermouse->buf; - if (data & 0x40) sermouse->count = 0; + if (data & 0x40) + sermouse->count = 0; + else if (sermouse->count == 0) + return; switch (sermouse->count) { @@ -169,7 +173,8 @@ static void sermouse_process_ms(struct sermouse *sermouse, signed char data) case 5: case 7: /* Ignore anything besides MZ++ */ - if (sermouse->type != SERIO_MZPP) break; + if (sermouse->type != SERIO_MZPP) + break; switch (buf[1]) { @@ -206,13 +211,16 @@ static irqreturn_t sermouse_interrupt(struct serio *serio, { struct sermouse *sermouse = serio_get_drvdata(serio); - if (time_after(jiffies, sermouse->last + HZ/10)) sermouse->count = 0; + if (time_after(jiffies, sermouse->last + HZ/10)) + sermouse->count = 0; + sermouse->last = jiffies; if (sermouse->type > SERIO_SUN) sermouse_process_ms(sermouse, data); else sermouse_process_msc(sermouse, data); + return IRQ_HANDLED; } @@ -258,12 +266,11 @@ static int sermouse_connect(struct serio *serio, struct serio_driver *drv) input_dev->id.vendor = sermouse->type; input_dev->id.product = c; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &serio->dev; + input_dev->dev.parent = &serio->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT); input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y); - input_dev->private = sermouse; if (c & 0x01) set_bit(BTN_MIDDLE, input_dev->keybit); if (c & 0x02) set_bit(BTN_SIDE, input_dev->keybit); diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index f0f9413..c77788b 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -40,33 +40,70 @@ #define YMIN_NOMINAL 1408 #define YMAX_NOMINAL 4448 + /***************************************************************************** - * Synaptics communications functions + * Stuff we need even when we do not want native Synaptics support ****************************************************************************/ /* - * Send a command to the synpatics touchpad by special commands + * Set the synaptics touchpad mode byte by special commands */ -static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param) +static int synaptics_mode_cmd(struct psmouse *psmouse, unsigned char mode) { - if (psmouse_sliced_command(psmouse, c)) + unsigned char param[1]; + + if (psmouse_sliced_command(psmouse, mode)) return -1; - if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) + param[0] = SYN_PS_SET_MODE2; + if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_SETRATE)) return -1; return 0; } +int synaptics_detect(struct psmouse *psmouse, int set_properties) +{ + struct ps2dev *ps2dev = &psmouse->ps2dev; + unsigned char param[4]; + + param[0] = 0; + + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); + ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO); + + if (param[1] != 0x47) + return -ENODEV; + + if (set_properties) { + psmouse->vendor = "Synaptics"; + psmouse->name = "TouchPad"; + } + + return 0; +} + +void synaptics_reset(struct psmouse *psmouse) +{ + /* reset touchpad back to relative mode, gestures enabled */ + synaptics_mode_cmd(psmouse, 0); +} + +#ifdef CONFIG_MOUSE_PS2_SYNAPTICS + +/***************************************************************************** + * Synaptics communications functions + ****************************************************************************/ + /* - * Set the synaptics touchpad mode byte by special commands + * Send a command to the synpatics touchpad by special commands */ -static int synaptics_mode_cmd(struct psmouse *psmouse, unsigned char mode) +static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param) { - unsigned char param[1]; - - if (psmouse_sliced_command(psmouse, mode)) + if (psmouse_sliced_command(psmouse, c)) return -1; - param[0] = SYN_PS_SET_MODE2; - if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_SETRATE)) + if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) return -1; return 0; } @@ -529,12 +566,6 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) clear_bit(REL_Y, dev->relbit); } -void synaptics_reset(struct psmouse *psmouse) -{ - /* reset touchpad back to relative mode, gestures enabled */ - synaptics_mode_cmd(psmouse, 0); -} - static void synaptics_disconnect(struct psmouse *psmouse) { synaptics_reset(psmouse); @@ -569,30 +600,6 @@ static int synaptics_reconnect(struct psmouse *psmouse) return 0; } -int synaptics_detect(struct psmouse *psmouse, int set_properties) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[4]; - - param[0] = 0; - - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); - ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO); - - if (param[1] != 0x47) - return -1; - - if (set_properties) { - psmouse->vendor = "Synaptics"; - psmouse->name = "TouchPad"; - } - - return 0; -} - #if defined(__i386__) #include <linux/dmi.h> static struct dmi_system_id toshiba_dmi_table[] = { @@ -648,6 +655,16 @@ int synaptics_init(struct psmouse *psmouse) set_input_params(psmouse->dev, priv); + /* + * Encode touchpad model so that it can be used to set + * input device->id.version and be visible to userspace. + * Because version is __u16 we have to drop something. + * Hardware info bits seem to be good candidates as they + * are documented to be for Synaptics corp. internal use. + */ + psmouse->model = ((priv->model_id & 0x00ff0000) >> 8) | + (priv->model_id & 0x000000ff); + psmouse->protocol_handler = synaptics_process_byte; psmouse->set_rate = synaptics_set_rate; psmouse->disconnect = synaptics_disconnect; @@ -680,4 +697,12 @@ int synaptics_init(struct psmouse *psmouse) return -1; } +#else /* CONFIG_MOUSE_PS2_SYNAPTICS */ + +int synaptics_init(struct psmouse *psmouse) +{ + return -ENOSYS; +} + +#endif /* CONFIG_MOUSE_PS2_SYNAPTICS */ diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index 68fff1d..02aa4cf 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h @@ -9,10 +9,6 @@ #ifndef _SYNAPTICS_H #define _SYNAPTICS_H -extern int synaptics_detect(struct psmouse *psmouse, int set_properties); -extern int synaptics_init(struct psmouse *psmouse); -extern void synaptics_reset(struct psmouse *psmouse); - /* synaptics queries */ #define SYN_QUE_IDENTIFY 0x00 #define SYN_QUE_MODES 0x01 @@ -62,9 +58,9 @@ extern void synaptics_reset(struct psmouse *psmouse); #define SYN_MODE_WMODE(m) ((m) & (1 << 0)) /* synaptics identify query bits */ -#define SYN_ID_MODEL(i) (((i) >> 4) & 0x0f) -#define SYN_ID_MAJOR(i) ((i) & 0x0f) -#define SYN_ID_MINOR(i) (((i) >> 16) & 0xff) +#define SYN_ID_MODEL(i) (((i) >> 4) & 0x0f) +#define SYN_ID_MAJOR(i) ((i) & 0x0f) +#define SYN_ID_MINOR(i) (((i) >> 16) & 0xff) #define SYN_ID_IS_SYNAPTICS(i) ((((i) >> 8) & 0xff) == 0x47) /* synaptics special commands */ @@ -98,8 +94,8 @@ struct synaptics_hw_state { struct synaptics_data { /* Data read from the touchpad */ unsigned long int model_id; /* Model-ID */ - unsigned long int capabilities; /* Capabilities */ - unsigned long int ext_cap; /* Extended Capabilities */ + unsigned long int capabilities; /* Capabilities */ + unsigned long int ext_cap; /* Extended Capabilities */ unsigned long int identity; /* Identification */ unsigned char pkt_type; /* packet type - old, new, etc */ @@ -107,4 +103,8 @@ struct synaptics_data { int scroll; }; +int synaptics_detect(struct psmouse *psmouse, int set_properties); +int synaptics_init(struct psmouse *psmouse); +void synaptics_reset(struct psmouse *psmouse); + #endif /* _SYNAPTICS_H */ diff --git a/drivers/input/mouse/touchkit_ps2.c b/drivers/input/mouse/touchkit_ps2.c new file mode 100644 index 0000000..7b977fd --- /dev/null +++ b/drivers/input/mouse/touchkit_ps2.c @@ -0,0 +1,100 @@ +/* ---------------------------------------------------------------------------- + * touchkit_ps2.c -- Driver for eGalax TouchKit PS/2 Touchscreens + * + * Copyright (C) 2005 by Stefan Lucke + * Copyright (C) 2004 by Daniel Ritz + * Copyright (C) by Todd E. Johnson (mtouchusb.c) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Based upon touchkitusb.c + * + * Vendor documentation is available in support section of: + * http://www.egalax.com.tw/ + */ + +#include <linux/kernel.h> +#include <linux/slab.h> + +#include <linux/input.h> +#include <linux/serio.h> +#include <linux/libps2.h> + +#include "psmouse.h" +#include "touchkit_ps2.h" + +#define TOUCHKIT_MAX_XC 0x07ff +#define TOUCHKIT_MAX_YC 0x07ff + +#define TOUCHKIT_CMD 0x0a +#define TOUCHKIT_CMD_LENGTH 1 + +#define TOUCHKIT_CMD_ACTIVE 'A' +#define TOUCHKIT_CMD_FIRMWARE_VERSION 'D' +#define TOUCHKIT_CMD_CONTROLLER_TYPE 'E' + +#define TOUCHKIT_SEND_PARMS(s, r, c) ((s) << 12 | (r) << 8 | (c)) + +#define TOUCHKIT_GET_TOUCHED(packet) (((packet)[0]) & 0x01) +#define TOUCHKIT_GET_X(packet) (((packet)[1] << 7) | (packet)[2]) +#define TOUCHKIT_GET_Y(packet) (((packet)[3] << 7) | (packet)[4]) + +static psmouse_ret_t touchkit_ps2_process_byte(struct psmouse *psmouse) +{ + unsigned char *packet = psmouse->packet; + struct input_dev *dev = psmouse->dev; + + if (psmouse->pktcnt != 5) + return PSMOUSE_GOOD_DATA; + + input_report_abs(dev, ABS_X, TOUCHKIT_GET_X(packet)); + input_report_abs(dev, ABS_Y, TOUCHKIT_GET_Y(packet)); + input_report_key(dev, BTN_TOUCH, TOUCHKIT_GET_TOUCHED(packet)); + input_sync(dev); + + return PSMOUSE_FULL_PACKET; +} + +int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties) +{ + struct input_dev *dev = psmouse->dev; + unsigned char param[3]; + int command; + + param[0] = TOUCHKIT_CMD_LENGTH; + param[1] = TOUCHKIT_CMD_ACTIVE; + command = TOUCHKIT_SEND_PARMS(2, 3, TOUCHKIT_CMD); + + if (ps2_command(&psmouse->ps2dev, param, command)) + return -ENODEV; + + if (param[0] != TOUCHKIT_CMD || param[1] != 0x01 || + param[2] != TOUCHKIT_CMD_ACTIVE) + return -ENODEV; + + if (set_properties) { + dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + set_bit(BTN_TOUCH, dev->keybit); + input_set_abs_params(dev, ABS_X, 0, TOUCHKIT_MAX_XC, 0, 0); + input_set_abs_params(dev, ABS_Y, 0, TOUCHKIT_MAX_YC, 0, 0); + + psmouse->vendor = "eGalax"; + psmouse->name = "Touchscreen"; + psmouse->protocol_handler = touchkit_ps2_process_byte; + psmouse->pktsize = 5; + } + + return 0; +} diff --git a/drivers/input/mouse/touchkit_ps2.h b/drivers/input/mouse/touchkit_ps2.h new file mode 100644 index 0000000..61e9dfd --- /dev/null +++ b/drivers/input/mouse/touchkit_ps2.h @@ -0,0 +1,24 @@ +/* ---------------------------------------------------------------------------- + * touchkit_ps2.h -- Driver for eGalax TouchKit PS/2 Touchscreens + * + * Copyright (C) 2005 by Stefan Lucke + * Copyright (c) 2005 Vojtech Pavlik + * + * 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. + */ + +#ifndef _TOUCHKIT_PS2_H +#define _TOUCHKIT_PS2_H + +#ifdef CONFIG_MOUSE_PS2_TOUCHKIT +int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties); +#else +inline int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties) +{ + return -ENOSYS; +} +#endif /* CONFIG_MOUSE_PS2_TOUCHKIT */ + +#endif diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h index 050298b..c10a6e7 100644 --- a/drivers/input/mouse/trackpoint.h +++ b/drivers/input/mouse/trackpoint.h @@ -142,6 +142,13 @@ struct trackpoint_data unsigned char ext_dev; }; -extern int trackpoint_detect(struct psmouse *psmouse, int set_properties); +#ifdef CONFIG_MOUSE_PS2_TRACKPOINT +int trackpoint_detect(struct psmouse *psmouse, int set_properties); +#else +inline int trackpoint_detect(struct psmouse *psmouse, int set_properties) +{ + return -ENOSYS; +} +#endif /* CONFIG_MOUSE_PS2_TRACKPOINT */ #endif /* _TRACKPOINT_H */ diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index c3d64fc..4a32157 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c @@ -508,8 +508,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv) input_dev->name = mouse->name; input_dev->phys = mouse->phys; input_dev->id.bustype = BUS_RS232; - input_dev->cdev.dev = &serio->dev; - input_dev->private = mouse; + input_dev->dev.parent = &serio->dev; set_bit (EV_KEY, input_dev->evbit); /* We have buttons */ set_bit (EV_REL, input_dev->evbit); diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 074fee4..7678e98 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -63,9 +63,12 @@ struct mousedev { int minor; char name[16]; wait_queue_head_t wait; - struct list_head list; + struct list_head client_list; struct input_handle handle; + struct list_head mixdev_node; + int mixdev_open; + struct mousedev_hw_data packet; unsigned int pkt_count; int old_x[4], old_y[4]; @@ -85,7 +88,7 @@ struct mousedev_motion { }; #define PACKET_QUEUE_LEN 16 -struct mousedev_list { +struct mousedev_client { struct fasync_struct *fasync; struct mousedev *mousedev; struct list_head node; @@ -111,6 +114,7 @@ static struct input_handler mousedev_handler; static struct mousedev *mousedev_table[MOUSEDEV_MINORS]; static struct mousedev mousedev_mix; +static LIST_HEAD(mousedev_mix_list); #define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03]) #define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03]) @@ -120,32 +124,33 @@ static void mousedev_touchpad_event(struct input_dev *dev, struct mousedev *mous int size, tmp; enum { FRACTION_DENOM = 128 }; - if (mousedev->touch) { - size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; - if (size == 0) - size = 256 * 2; - - switch (code) { - case ABS_X: - fx(0) = value; - if (mousedev->pkt_count >= 2) { - tmp = ((value - fx(2)) * (256 * FRACTION_DENOM)) / size; - tmp += mousedev->frac_dx; - mousedev->packet.dx = tmp / FRACTION_DENOM; - mousedev->frac_dx = tmp - mousedev->packet.dx * FRACTION_DENOM; - } - break; + switch (code) { + case ABS_X: + fx(0) = value; + if (mousedev->touch && mousedev->pkt_count >= 2) { + size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; + if (size == 0) + size = 256 * 2; + tmp = ((value - fx(2)) * (256 * FRACTION_DENOM)) / size; + tmp += mousedev->frac_dx; + mousedev->packet.dx = tmp / FRACTION_DENOM; + mousedev->frac_dx = tmp - mousedev->packet.dx * FRACTION_DENOM; + } + break; - case ABS_Y: - fy(0) = value; - if (mousedev->pkt_count >= 2) { - tmp = -((value - fy(2)) * (256 * FRACTION_DENOM)) / size; - tmp += mousedev->frac_dy; - mousedev->packet.dy = tmp / FRACTION_DENOM; - mousedev->frac_dy = tmp - mousedev->packet.dy * FRACTION_DENOM; - } - break; - } + case ABS_Y: + fy(0) = value; + if (mousedev->touch && mousedev->pkt_count >= 2) { + /* use X size to keep the same scale */ + size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; + if (size == 0) + size = 256 * 2; + tmp = -((value - fy(2)) * (256 * FRACTION_DENOM)) / size; + tmp += mousedev->frac_dy; + mousedev->packet.dy = tmp / FRACTION_DENOM; + mousedev->frac_dy = tmp - mousedev->packet.dy * FRACTION_DENOM; + } + break; } } @@ -223,47 +228,47 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_hw_data *packet) { - struct mousedev_list *list; + struct mousedev_client *client; struct mousedev_motion *p; unsigned long flags; int wake_readers = 0; - list_for_each_entry(list, &mousedev->list, node) { - spin_lock_irqsave(&list->packet_lock, flags); + list_for_each_entry(client, &mousedev->client_list, node) { + spin_lock_irqsave(&client->packet_lock, flags); - p = &list->packets[list->head]; - if (list->ready && p->buttons != mousedev->packet.buttons) { - unsigned int new_head = (list->head + 1) % PACKET_QUEUE_LEN; - if (new_head != list->tail) { - p = &list->packets[list->head = new_head]; + p = &client->packets[client->head]; + if (client->ready && p->buttons != mousedev->packet.buttons) { + unsigned int new_head = (client->head + 1) % PACKET_QUEUE_LEN; + if (new_head != client->tail) { + p = &client->packets[client->head = new_head]; memset(p, 0, sizeof(struct mousedev_motion)); } } if (packet->abs_event) { - p->dx += packet->x - list->pos_x; - p->dy += packet->y - list->pos_y; - list->pos_x = packet->x; - list->pos_y = packet->y; + p->dx += packet->x - client->pos_x; + p->dy += packet->y - client->pos_y; + client->pos_x = packet->x; + client->pos_y = packet->y; } - list->pos_x += packet->dx; - list->pos_x = list->pos_x < 0 ? 0 : (list->pos_x >= xres ? xres : list->pos_x); - list->pos_y += packet->dy; - list->pos_y = list->pos_y < 0 ? 0 : (list->pos_y >= yres ? yres : list->pos_y); + client->pos_x += packet->dx; + client->pos_x = client->pos_x < 0 ? 0 : (client->pos_x >= xres ? xres : client->pos_x); + client->pos_y += packet->dy; + client->pos_y = client->pos_y < 0 ? 0 : (client->pos_y >= yres ? yres : client->pos_y); p->dx += packet->dx; p->dy += packet->dy; p->dz += packet->dz; p->buttons = mousedev->packet.buttons; - if (p->dx || p->dy || p->dz || p->buttons != list->last_buttons) - list->ready = 1; + if (p->dx || p->dy || p->dz || p->buttons != client->last_buttons) + client->ready = 1; - spin_unlock_irqrestore(&list->packet_lock, flags); + spin_unlock_irqrestore(&client->packet_lock, flags); - if (list->ready) { - kill_fasync(&list->fasync, SIGIO, POLL_IN); + if (client->ready) { + kill_fasync(&client->fasync, SIGIO, POLL_IN); wake_readers = 1; } } @@ -351,9 +356,9 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig static int mousedev_fasync(int fd, struct file *file, int on) { int retval; - struct mousedev_list *list = file->private_data; + struct mousedev_client *client = file->private_data; - retval = fasync_helper(fd, file, on, &list->fasync); + retval = fasync_helper(fd, file, on, &client->fasync); return retval < 0 ? retval : 0; } @@ -364,50 +369,95 @@ static void mousedev_free(struct mousedev *mousedev) kfree(mousedev); } -static void mixdev_release(void) +static int mixdev_add_device(struct mousedev *mousedev) { - struct input_handle *handle; + int error; - list_for_each_entry(handle, &mousedev_handler.h_list, h_node) { - struct mousedev *mousedev = handle->private; + if (mousedev_mix.open) { + error = input_open_device(&mousedev->handle); + if (error) + return error; - if (!mousedev->open) { - if (mousedev->exist) - input_close_device(&mousedev->handle); - else - mousedev_free(mousedev); + mousedev->open++; + mousedev->mixdev_open++; + } + + list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list); + + return 0; +} + +static void mixdev_remove_device(struct mousedev *mousedev) +{ + if (mousedev->mixdev_open) { + mousedev->mixdev_open = 0; + if (!--mousedev->open && mousedev->exist) + input_close_device(&mousedev->handle); + } + + list_del_init(&mousedev->mixdev_node); +} + +static void mixdev_open_devices(void) +{ + struct mousedev *mousedev; + + list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { + if (mousedev->exist && !mousedev->open) { + if (input_open_device(&mousedev->handle)) + continue; + + mousedev->open++; + mousedev->mixdev_open++; } } } -static int mousedev_release(struct inode * inode, struct file * file) +static void mixdev_close_devices(void) { - struct mousedev_list *list = file->private_data; + struct mousedev *mousedev, *next; + + list_for_each_entry_safe(mousedev, next, &mousedev_mix_list, mixdev_node) { + if (mousedev->mixdev_open) { + mousedev->mixdev_open = 0; + if (!--mousedev->open) { + if (mousedev->exist) + input_close_device(&mousedev->handle); + else + mousedev_free(mousedev); + } + } + } +} + +static int mousedev_release(struct inode *inode, struct file *file) +{ + struct mousedev_client *client = file->private_data; + struct mousedev *mousedev = client->mousedev; mousedev_fasync(-1, file, 0); - list_del(&list->node); + list_del(&client->node); + kfree(client); - if (!--list->mousedev->open) { - if (list->mousedev->minor == MOUSEDEV_MIX) - mixdev_release(); - else if (!mousedev_mix.open) { - if (list->mousedev->exist) - input_close_device(&list->mousedev->handle); - else - mousedev_free(list->mousedev); - } + if (!--mousedev->open) { + if (mousedev->minor == MOUSEDEV_MIX) + mixdev_close_devices(); + else if (mousedev->exist) + input_close_device(&mousedev->handle); + else + mousedev_free(mousedev); } - kfree(list); return 0; } -static int mousedev_open(struct inode * inode, struct file * file) + +static int mousedev_open(struct inode *inode, struct file *file) { - struct mousedev_list *list; - struct input_handle *handle; + struct mousedev_client *client; struct mousedev *mousedev; + int error; int i; #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX @@ -417,31 +467,37 @@ static int mousedev_open(struct inode * inode, struct file * file) #endif i = iminor(inode) - MOUSEDEV_MINOR_BASE; - if (i >= MOUSEDEV_MINORS || !mousedev_table[i]) + if (i >= MOUSEDEV_MINORS) return -ENODEV; - if (!(list = kzalloc(sizeof(struct mousedev_list), GFP_KERNEL))) + mousedev = mousedev_table[i]; + if (!mousedev) + return -ENODEV; + + client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL); + if (!client) return -ENOMEM; - spin_lock_init(&list->packet_lock); - list->pos_x = xres / 2; - list->pos_y = yres / 2; - list->mousedev = mousedev_table[i]; - list_add_tail(&list->node, &mousedev_table[i]->list); - file->private_data = list; - - if (!list->mousedev->open++) { - if (list->mousedev->minor == MOUSEDEV_MIX) { - list_for_each_entry(handle, &mousedev_handler.h_list, h_node) { - mousedev = handle->private; - if (!mousedev->open && mousedev->exist) - input_open_device(handle); + spin_lock_init(&client->packet_lock); + client->pos_x = xres / 2; + client->pos_y = yres / 2; + client->mousedev = mousedev; + list_add_tail(&client->node, &mousedev->client_list); + + if (!mousedev->open++) { + if (mousedev->minor == MOUSEDEV_MIX) + mixdev_open_devices(); + else if (mousedev->exist) { + error = input_open_device(&mousedev->handle); + if (error) { + list_del(&client->node); + kfree(client); + return error; } - } else - if (!mousedev_mix.open && list->mousedev->exist) - input_open_device(&list->mousedev->handle); + } } + file->private_data = client; return 0; } @@ -450,13 +506,13 @@ static inline int mousedev_limit_delta(int delta, int limit) return delta > limit ? limit : (delta < -limit ? -limit : delta); } -static void mousedev_packet(struct mousedev_list *list, signed char *ps2_data) +static void mousedev_packet(struct mousedev_client *client, signed char *ps2_data) { struct mousedev_motion *p; unsigned long flags; - spin_lock_irqsave(&list->packet_lock, flags); - p = &list->packets[list->tail]; + spin_lock_irqsave(&client->packet_lock, flags); + p = &client->packets[client->tail]; ps2_data[0] = 0x08 | ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07); ps2_data[1] = mousedev_limit_delta(p->dx, 127); @@ -464,44 +520,44 @@ static void mousedev_packet(struct mousedev_list *list, signed char *ps2_data) p->dx -= ps2_data[1]; p->dy -= ps2_data[2]; - switch (list->mode) { + switch (client->mode) { case MOUSEDEV_EMUL_EXPS: ps2_data[3] = mousedev_limit_delta(p->dz, 7); p->dz -= ps2_data[3]; ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1); - list->bufsiz = 4; + client->bufsiz = 4; break; case MOUSEDEV_EMUL_IMPS: ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); ps2_data[3] = mousedev_limit_delta(p->dz, 127); p->dz -= ps2_data[3]; - list->bufsiz = 4; + client->bufsiz = 4; break; case MOUSEDEV_EMUL_PS2: default: ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); p->dz = 0; - list->bufsiz = 3; + client->bufsiz = 3; break; } if (!p->dx && !p->dy && !p->dz) { - if (list->tail == list->head) { - list->ready = 0; - list->last_buttons = p->buttons; + if (client->tail == client->head) { + client->ready = 0; + client->last_buttons = p->buttons; } else - list->tail = (list->tail + 1) % PACKET_QUEUE_LEN; + client->tail = (client->tail + 1) % PACKET_QUEUE_LEN; } - spin_unlock_irqrestore(&list->packet_lock, flags); + spin_unlock_irqrestore(&client->packet_lock, flags); } -static ssize_t mousedev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) +static ssize_t mousedev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { - struct mousedev_list *list = file->private_data; + struct mousedev_client *client = file->private_data; unsigned char c; unsigned int i; @@ -510,95 +566,95 @@ static ssize_t mousedev_write(struct file * file, const char __user * buffer, si if (get_user(c, buffer + i)) return -EFAULT; - if (c == mousedev_imex_seq[list->imexseq]) { - if (++list->imexseq == MOUSEDEV_SEQ_LEN) { - list->imexseq = 0; - list->mode = MOUSEDEV_EMUL_EXPS; + if (c == mousedev_imex_seq[client->imexseq]) { + if (++client->imexseq == MOUSEDEV_SEQ_LEN) { + client->imexseq = 0; + client->mode = MOUSEDEV_EMUL_EXPS; } } else - list->imexseq = 0; + client->imexseq = 0; - if (c == mousedev_imps_seq[list->impsseq]) { - if (++list->impsseq == MOUSEDEV_SEQ_LEN) { - list->impsseq = 0; - list->mode = MOUSEDEV_EMUL_IMPS; + if (c == mousedev_imps_seq[client->impsseq]) { + if (++client->impsseq == MOUSEDEV_SEQ_LEN) { + client->impsseq = 0; + client->mode = MOUSEDEV_EMUL_IMPS; } } else - list->impsseq = 0; + client->impsseq = 0; - list->ps2[0] = 0xfa; + client->ps2[0] = 0xfa; switch (c) { case 0xeb: /* Poll */ - mousedev_packet(list, &list->ps2[1]); - list->bufsiz++; /* account for leading ACK */ + mousedev_packet(client, &client->ps2[1]); + client->bufsiz++; /* account for leading ACK */ break; case 0xf2: /* Get ID */ - switch (list->mode) { - case MOUSEDEV_EMUL_PS2: list->ps2[1] = 0; break; - case MOUSEDEV_EMUL_IMPS: list->ps2[1] = 3; break; - case MOUSEDEV_EMUL_EXPS: list->ps2[1] = 4; break; + switch (client->mode) { + case MOUSEDEV_EMUL_PS2: client->ps2[1] = 0; break; + case MOUSEDEV_EMUL_IMPS: client->ps2[1] = 3; break; + case MOUSEDEV_EMUL_EXPS: client->ps2[1] = 4; break; } - list->bufsiz = 2; + client->bufsiz = 2; break; case 0xe9: /* Get info */ - list->ps2[1] = 0x60; list->ps2[2] = 3; list->ps2[3] = 200; - list->bufsiz = 4; + client->ps2[1] = 0x60; client->ps2[2] = 3; client->ps2[3] = 200; + client->bufsiz = 4; break; case 0xff: /* Reset */ - list->impsseq = list->imexseq = 0; - list->mode = MOUSEDEV_EMUL_PS2; - list->ps2[1] = 0xaa; list->ps2[2] = 0x00; - list->bufsiz = 3; + client->impsseq = client->imexseq = 0; + client->mode = MOUSEDEV_EMUL_PS2; + client->ps2[1] = 0xaa; client->ps2[2] = 0x00; + client->bufsiz = 3; break; default: - list->bufsiz = 1; + client->bufsiz = 1; break; } - list->buffer = list->bufsiz; + client->buffer = client->bufsiz; } - kill_fasync(&list->fasync, SIGIO, POLL_IN); + kill_fasync(&client->fasync, SIGIO, POLL_IN); - wake_up_interruptible(&list->mousedev->wait); + wake_up_interruptible(&client->mousedev->wait); return count; } -static ssize_t mousedev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) +static ssize_t mousedev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { - struct mousedev_list *list = file->private_data; + struct mousedev_client *client = file->private_data; int retval = 0; - if (!list->ready && !list->buffer && (file->f_flags & O_NONBLOCK)) + if (!client->ready && !client->buffer && (file->f_flags & O_NONBLOCK)) return -EAGAIN; - retval = wait_event_interruptible(list->mousedev->wait, - !list->mousedev->exist || list->ready || list->buffer); + retval = wait_event_interruptible(client->mousedev->wait, + !client->mousedev->exist || client->ready || client->buffer); if (retval) return retval; - if (!list->mousedev->exist) + if (!client->mousedev->exist) return -ENODEV; - if (!list->buffer && list->ready) { - mousedev_packet(list, list->ps2); - list->buffer = list->bufsiz; + if (!client->buffer && client->ready) { + mousedev_packet(client, client->ps2); + client->buffer = client->bufsiz; } - if (count > list->buffer) - count = list->buffer; + if (count > client->buffer) + count = client->buffer; - list->buffer -= count; + client->buffer -= count; - if (copy_to_user(buffer, list->ps2 + list->bufsiz - list->buffer - count, count)) + if (copy_to_user(buffer, client->ps2 + client->bufsiz - client->buffer - count, count)) return -EFAULT; return count; @@ -607,11 +663,12 @@ static ssize_t mousedev_read(struct file * file, char __user * buffer, size_t co /* No kernel lock - fine */ static unsigned int mousedev_poll(struct file *file, poll_table *wait) { - struct mousedev_list *list = file->private_data; + struct mousedev_client *client = file->private_data; + struct mousedev *mousedev = client->mousedev; - poll_wait(file, &list->mousedev->wait, wait); - return ((list->ready || list->buffer) ? (POLLIN | POLLRDNORM) : 0) | - (list->mousedev->exist ? 0 : (POLLHUP | POLLERR)); + poll_wait(file, &mousedev->wait, wait); + return ((client->ready || client->buffer) ? (POLLIN | POLLRDNORM) : 0) | + (mousedev->exist ? 0 : (POLLHUP | POLLERR)); } static const struct file_operations mousedev_fops = { @@ -624,23 +681,27 @@ static const struct file_operations mousedev_fops = { .fasync = mousedev_fasync, }; -static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev, - const struct input_device_id *id) +static int mousedev_connect(struct input_handler *handler, struct input_dev *dev, + const struct input_device_id *id) { struct mousedev *mousedev; struct class_device *cdev; - int minor = 0; + dev_t devt; + int minor; + int error; for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++); if (minor == MOUSEDEV_MINORS) { printk(KERN_ERR "mousedev: no more free mousedev devices\n"); - return NULL; + return -ENFILE; } - if (!(mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL))) - return NULL; + mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL); + if (!mousedev) + return -ENOMEM; - INIT_LIST_HEAD(&mousedev->list); + INIT_LIST_HEAD(&mousedev->client_list); + INIT_LIST_HEAD(&mousedev->mixdev_node); init_waitqueue_head(&mousedev->wait); mousedev->minor = minor; @@ -651,42 +712,66 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru mousedev->handle.private = mousedev; sprintf(mousedev->name, "mouse%d", minor); - if (mousedev_mix.open) - input_open_device(&mousedev->handle); - mousedev_table[minor] = mousedev; - cdev = class_device_create(&input_class, &dev->cdev, - MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor), - dev->cdev.dev, mousedev->name); + devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor), + + cdev = class_device_create(&input_class, &dev->cdev, devt, + dev->cdev.dev, mousedev->name); + if (IS_ERR(cdev)) { + error = PTR_ERR(cdev); + goto err_free_mousedev; + } /* temporary symlink to keep userspace happy */ - sysfs_create_link(&input_class.subsys.kobj, &cdev->kobj, - mousedev->name); + error = sysfs_create_link(&input_class.subsys.kobj, + &cdev->kobj, mousedev->name); + if (error) + goto err_cdev_destroy; + + error = input_register_handle(&mousedev->handle); + if (error) + goto err_remove_link; + + error = mixdev_add_device(mousedev); + if (error) + goto err_unregister_handle; - return &mousedev->handle; + return 0; + + err_unregister_handle: + input_unregister_handle(&mousedev->handle); + err_remove_link: + sysfs_remove_link(&input_class.subsys.kobj, mousedev->name); + err_cdev_destroy: + class_device_destroy(&input_class, devt); + err_free_mousedev: + mousedev_table[minor] = NULL; + kfree(mousedev); + return error; } static void mousedev_disconnect(struct input_handle *handle) { struct mousedev *mousedev = handle->private; - struct mousedev_list *list; + struct mousedev_client *client; + + input_unregister_handle(handle); sysfs_remove_link(&input_class.subsys.kobj, mousedev->name); class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor)); mousedev->exist = 0; + mixdev_remove_device(mousedev); + if (mousedev->open) { input_close_device(handle); wake_up_interruptible(&mousedev->wait); - list_for_each_entry(list, &mousedev->list, node) - kill_fasync(&list->fasync, SIGIO, POLL_HUP); - } else { - if (mousedev_mix.open) - input_close_device(handle); + list_for_each_entry(client, &mousedev->client_list, node) + kill_fasync(&client->fasync, SIGIO, POLL_HUP); + } else mousedev_free(mousedev); - } } static const struct input_device_id mousedev_ids[] = { @@ -714,7 +799,7 @@ static const struct input_device_id mousedev_ids[] = { .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_TOOL_WIDTH) }, }, /* A touchpad */ - { }, /* Terminating entry */ + { }, /* Terminating entry */ }; MODULE_DEVICE_TABLE(input, mousedev_ids); @@ -746,7 +831,7 @@ static int __init mousedev_init(void) return error; memset(&mousedev_mix, 0, sizeof(struct mousedev)); - INIT_LIST_HEAD(&mousedev_mix.list); + INIT_LIST_HEAD(&mousedev_mix.client_list); init_waitqueue_head(&mousedev_mix.wait); mousedev_table[MOUSEDEV_MIX] = &mousedev_mix; mousedev_mix.exist = 1; diff --git a/drivers/input/power.c b/drivers/input/power.c deleted file mode 100644 index ee82464..0000000 --- a/drivers/input/power.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * $Id: power.c,v 1.10 2001/09/25 09:17:15 vojtech Exp $ - * - * Copyright (c) 2001 "Crazy" James Simmons - * - * Input driver Power Management. - * - * Sponsored by Transvirtual Technology. - */ - -/* - * 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 - * - * Should you need to contact me, the author, you can do so by - * e-mail - mail your message to <jsimmons@transvirtual.com>. - */ - -#include <linux/module.h> -#include <linux/input.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/tty.h> -#include <linux/delay.h> -#include <linux/pm.h> - -static struct input_handler power_handler; - -/* - * Power management can't be done in a interrupt context. So we have to - * use keventd. - */ -static int suspend_button_pushed = 0; -static void suspend_button_task_handler(void *data) -{ - udelay(200); /* debounce */ - suspend_button_pushed = 0; -} - -static DECLARE_WORK(suspend_button_task, suspend_button_task_handler, NULL); - -static void power_event(struct input_handle *handle, unsigned int type, - unsigned int code, int down) -{ - struct input_dev *dev = handle->dev; - - printk("Entering power_event\n"); - - if (type == EV_PWR) { - switch (code) { - case KEY_SUSPEND: - printk("Powering down entire device\n"); - - if (!suspend_button_pushed) { - suspend_button_pushed = 1; - schedule_work(&suspend_button_task); - } - break; - case KEY_POWER: - /* Hum power down the machine. */ - break; - default: - return; - } - } - - if (type == EV_KEY) { - switch (code) { - case KEY_SUSPEND: - printk("Powering down input device\n"); - /* This is risky. See pm.h for details. */ - if (dev->state != PM_RESUME) - dev->state = PM_RESUME; - else - dev->state = PM_SUSPEND; - pm_send(dev->pm_dev, dev->state, dev); - break; - case KEY_POWER: - /* Turn the input device off completely ? */ - break; - default: - return; - } - } - return; -} - -static struct input_handle *power_connect(struct input_handler *handler, - struct input_dev *dev, - const struct input_device_id *id) -{ - struct input_handle *handle; - - if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL))) - return NULL; - - handle->dev = dev; - handle->handler = handler; - - input_open_device(handle); - - printk(KERN_INFO "power.c: Adding power management to input layer\n"); - return handle; -} - -static void power_disconnect(struct input_handle *handle) -{ - input_close_device(handle); - kfree(handle); -} - -static const struct input_device_id power_ids[] = { - { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, - .evbit = { BIT(EV_KEY) }, - .keybit = { [LONG(KEY_SUSPEND)] = BIT(KEY_SUSPEND) } - }, - { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, - .evbit = { BIT(EV_KEY) }, - .keybit = { [LONG(KEY_POWER)] = BIT(KEY_POWER) } - }, - { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT, - .evbit = { BIT(EV_PWR) }, - }, - { }, /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(input, power_ids); - -static struct input_handler power_handler = { - .event = power_event, - .connect = power_connect, - .disconnect = power_disconnect, - .name = "power", - .id_table = power_ids, -}; - -static int __init power_init(void) -{ - return input_register_handler(&power_handler); -} - -static void __exit power_exit(void) -{ - input_unregister_handler(&power_handler); -} - -module_init(power_init); -module_exit(power_exit); - -MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>"); -MODULE_DESCRIPTION("Input Power Management driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c index 4fa93ff..93a1a6b 100644 --- a/drivers/input/serio/hil_mlc.c +++ b/drivers/input/serio/hil_mlc.c @@ -32,11 +32,11 @@ * * Driver theory of operation: * - * Some access methods and an ISR is defined by the sub-driver - * (e.g. hp_sdc_mlc.c). These methods are expected to provide a - * few bits of logic in addition to raw access to the HIL MLC, - * specifically, the ISR, which is entirely registered by the - * sub-driver and invoked directly, must check for record + * Some access methods and an ISR is defined by the sub-driver + * (e.g. hp_sdc_mlc.c). These methods are expected to provide a + * few bits of logic in addition to raw access to the HIL MLC, + * specifically, the ISR, which is entirely registered by the + * sub-driver and invoked directly, must check for record * termination or packet match, at which point a semaphore must * be cleared and then the hil_mlcs_tasklet must be scheduled. * @@ -47,7 +47,7 @@ * itself if output is pending. (This rescheduling should be replaced * at some point with a sub-driver-specific mechanism.) * - * A timer task prods the tasklet once per second to prevent + * A timer task prods the tasklet once per second to prevent * hangups when attached devices do not return expected data * and to initiate probes of the loop for new devices. */ @@ -83,69 +83,85 @@ DECLARE_TASKLET_DISABLED(hil_mlcs_tasklet, hil_mlcs_process, 0); /********************** Device info/instance management **********************/ -static void hil_mlc_clear_di_map (hil_mlc *mlc, int val) { +static void hil_mlc_clear_di_map(hil_mlc *mlc, int val) +{ int j; - for (j = val; j < 7 ; j++) { + + for (j = val; j < 7 ; j++) mlc->di_map[j] = -1; - } } -static void hil_mlc_clear_di_scratch (hil_mlc *mlc) { - memset(&(mlc->di_scratch), 0, sizeof(mlc->di_scratch)); +static void hil_mlc_clear_di_scratch(hil_mlc *mlc) +{ + memset(&mlc->di_scratch, 0, sizeof(mlc->di_scratch)); } -static void hil_mlc_copy_di_scratch (hil_mlc *mlc, int idx) { - memcpy(&(mlc->di[idx]), &(mlc->di_scratch), sizeof(mlc->di_scratch)); +static void hil_mlc_copy_di_scratch(hil_mlc *mlc, int idx) +{ + memcpy(&mlc->di[idx], &mlc->di_scratch, sizeof(mlc->di_scratch)); } -static int hil_mlc_match_di_scratch (hil_mlc *mlc) { +static int hil_mlc_match_di_scratch(hil_mlc *mlc) +{ int idx; for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) { - int j, found; + int j, found = 0; /* In-use slots are not eligible. */ - found = 0; - for (j = 0; j < 7 ; j++) { - if (mlc->di_map[j] == idx) found++; - } - if (found) continue; - if (!memcmp(mlc->di + idx, - &(mlc->di_scratch), - sizeof(mlc->di_scratch))) break; + for (j = 0; j < 7 ; j++) + if (mlc->di_map[j] == idx) + found++; + + if (found) + continue; + + if (!memcmp(mlc->di + idx, &mlc->di_scratch, + sizeof(mlc->di_scratch))) + break; } - return((idx >= HIL_MLC_DEVMEM) ? -1 : idx); + return idx >= HIL_MLC_DEVMEM ? -1 : idx; } -static int hil_mlc_find_free_di(hil_mlc *mlc) { +static int hil_mlc_find_free_di(hil_mlc *mlc) +{ int idx; - /* TODO: Pick all-zero slots first, failing that, - * randomize the slot picked among those eligible. + + /* TODO: Pick all-zero slots first, failing that, + * randomize the slot picked among those eligible. */ for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) { - int j, found; - found = 0; - for (j = 0; j < 7 ; j++) { - if (mlc->di_map[j] == idx) found++; - } - if (!found) break; + int j, found = 0; + + for (j = 0; j < 7 ; j++) + if (mlc->di_map[j] == idx) + found++; + + if (!found) + break; } - return(idx); /* Note: It is guaranteed at least one above will match */ + + return idx; /* Note: It is guaranteed at least one above will match */ } -static inline void hil_mlc_clean_serio_map(hil_mlc *mlc) { +static inline void hil_mlc_clean_serio_map(hil_mlc *mlc) +{ int idx; + for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) { - int j, found; - found = 0; - for (j = 0; j < 7 ; j++) { - if (mlc->di_map[j] == idx) found++; - } - if (!found) mlc->serio_map[idx].di_revmap = -1; + int j, found = 0; + + for (j = 0; j < 7 ; j++) + if (mlc->di_map[j] == idx) + found++; + + if (!found) + mlc->serio_map[idx].di_revmap = -1; } } -static void hil_mlc_send_polls(hil_mlc *mlc) { +static void hil_mlc_send_polls(hil_mlc *mlc) +{ int did, i, cnt; struct serio *serio; struct serio_driver *drv; @@ -157,26 +173,31 @@ static void hil_mlc_send_polls(hil_mlc *mlc) { while (mlc->icount < 15 - i) { hil_packet p; + p = mlc->ipacket[i]; if (did != (p & HIL_PKT_ADDR_MASK) >> 8) { - if (drv == NULL || drv->interrupt == NULL) goto skip; + if (drv && drv->interrupt) { + drv->interrupt(serio, 0, 0); + drv->interrupt(serio, HIL_ERR_INT >> 16, 0); + drv->interrupt(serio, HIL_PKT_CMD >> 8, 0); + drv->interrupt(serio, HIL_CMD_POL + cnt, 0); + } - drv->interrupt(serio, 0, 0); - drv->interrupt(serio, HIL_ERR_INT >> 16, 0); - drv->interrupt(serio, HIL_PKT_CMD >> 8, 0); - drv->interrupt(serio, HIL_CMD_POL + cnt, 0); - skip: did = (p & HIL_PKT_ADDR_MASK) >> 8; serio = did ? mlc->serio[mlc->di_map[did-1]] : NULL; drv = (serio != NULL) ? serio->drv : NULL; cnt = 0; } - cnt++; i++; - if (drv == NULL || drv->interrupt == NULL) continue; - drv->interrupt(serio, (p >> 24), 0); - drv->interrupt(serio, (p >> 16) & 0xff, 0); - drv->interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0); - drv->interrupt(serio, p & 0xff, 0); + + cnt++; + i++; + + if (drv && drv->interrupt) { + drv->interrupt(serio, (p >> 24), 0); + drv->interrupt(serio, (p >> 16) & 0xff, 0); + drv->interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0); + drv->interrupt(serio, p & 0xff, 0); + } } } @@ -215,12 +236,16 @@ static void hil_mlc_send_polls(hil_mlc *mlc) { #define HILSEN_DOZE (HILSEN_SAME | HILSEN_SCHED | HILSEN_BREAK) #define HILSEN_SLEEP (HILSEN_SAME | HILSEN_BREAK) -static int hilse_match(hil_mlc *mlc, int unused) { +static int hilse_match(hil_mlc *mlc, int unused) +{ int rc; + rc = hil_mlc_match_di_scratch(mlc); if (rc == -1) { rc = hil_mlc_find_free_di(mlc); - if (rc == -1) goto err; + if (rc == -1) + goto err; + #ifdef HIL_MLC_DEBUG printk(KERN_DEBUG PREFIX "new in slot %i\n", rc); #endif @@ -231,6 +256,7 @@ static int hilse_match(hil_mlc *mlc, int unused) { serio_rescan(mlc->serio[rc]); return -1; } + mlc->di_map[mlc->ddi] = rc; #ifdef HIL_MLC_DEBUG printk(KERN_DEBUG PREFIX "same in slot %i\n", rc); @@ -238,152 +264,177 @@ static int hilse_match(hil_mlc *mlc, int unused) { mlc->serio_map[rc].di_revmap = mlc->ddi; hil_mlc_clean_serio_map(mlc); return 0; + err: printk(KERN_ERR PREFIX "Residual device slots exhausted, close some serios!\n"); return 1; } /* An LCV used to prevent runaway loops, forces 5 second sleep when reset. */ -static int hilse_init_lcv(hil_mlc *mlc, int unused) { +static int hilse_init_lcv(hil_mlc *mlc, int unused) +{ struct timeval tv; do_gettimeofday(&tv); - if(mlc->lcv == 0) goto restart; /* First init, no need to dally */ - if(tv.tv_sec - mlc->lcv_tv.tv_sec < 5) return -1; - restart: + if (mlc->lcv && (tv.tv_sec - mlc->lcv_tv.tv_sec) < 5) + return -1; + mlc->lcv_tv = tv; mlc->lcv = 0; + return 0; } -static int hilse_inc_lcv(hil_mlc *mlc, int lim) { - if (mlc->lcv++ >= lim) return -1; - return 0; +static int hilse_inc_lcv(hil_mlc *mlc, int lim) +{ + return mlc->lcv++ >= lim ? -1 : 0; } #if 0 -static int hilse_set_lcv(hil_mlc *mlc, int val) { +static int hilse_set_lcv(hil_mlc *mlc, int val) +{ mlc->lcv = val; + return 0; } #endif /* Management of the discovered device index (zero based, -1 means no devs) */ -static int hilse_set_ddi(hil_mlc *mlc, int val) { +static int hilse_set_ddi(hil_mlc *mlc, int val) +{ mlc->ddi = val; hil_mlc_clear_di_map(mlc, val + 1); + return 0; } -static int hilse_dec_ddi(hil_mlc *mlc, int unused) { +static int hilse_dec_ddi(hil_mlc *mlc, int unused) +{ mlc->ddi--; - if (mlc->ddi <= -1) { + if (mlc->ddi <= -1) { mlc->ddi = -1; hil_mlc_clear_di_map(mlc, 0); return -1; } hil_mlc_clear_di_map(mlc, mlc->ddi + 1); + return 0; } -static int hilse_inc_ddi(hil_mlc *mlc, int unused) { - if (mlc->ddi >= 6) { - BUG(); - return -1; - } +static int hilse_inc_ddi(hil_mlc *mlc, int unused) +{ + BUG_ON(mlc->ddi >= 6); mlc->ddi++; + return 0; } -static int hilse_take_idd(hil_mlc *mlc, int unused) { +static int hilse_take_idd(hil_mlc *mlc, int unused) +{ int i; - /* Help the state engine: - * Is this a real IDD response or just an echo? + /* Help the state engine: + * Is this a real IDD response or just an echo? * - * Real IDD response does not start with a command. + * Real IDD response does not start with a command. */ - if (mlc->ipacket[0] & HIL_PKT_CMD) goto bail; + if (mlc->ipacket[0] & HIL_PKT_CMD) + goto bail; + /* Should have the command echoed further down. */ for (i = 1; i < 16; i++) { - if (((mlc->ipacket[i] & HIL_PKT_ADDR_MASK) == + if (((mlc->ipacket[i] & HIL_PKT_ADDR_MASK) == (mlc->ipacket[0] & HIL_PKT_ADDR_MASK)) && - (mlc->ipacket[i] & HIL_PKT_CMD) && + (mlc->ipacket[i] & HIL_PKT_CMD) && ((mlc->ipacket[i] & HIL_PKT_DATA_MASK) == HIL_CMD_IDD)) break; } - if (i > 15) goto bail; + if (i > 15) + goto bail; + /* And the rest of the packets should still be clear. */ - while (++i < 16) { - if (mlc->ipacket[i]) break; - } - if (i < 16) goto bail; - for (i = 0; i < 16; i++) { - mlc->di_scratch.idd[i] = + while (++i < 16) + if (mlc->ipacket[i]) + break; + + if (i < 16) + goto bail; + + for (i = 0; i < 16; i++) + mlc->di_scratch.idd[i] = mlc->ipacket[i] & HIL_PKT_DATA_MASK; - } + /* Next step is to see if RSC supported */ - if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_RSC) + if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_RSC) return HILSEN_NEXT; - if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) + + if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) return HILSEN_DOWN | 4; + return 0; + bail: mlc->ddi--; + return -1; /* This should send us off to ACF */ } -static int hilse_take_rsc(hil_mlc *mlc, int unused) { +static int hilse_take_rsc(hil_mlc *mlc, int unused) +{ int i; - for (i = 0; i < 16; i++) { - mlc->di_scratch.rsc[i] = + for (i = 0; i < 16; i++) + mlc->di_scratch.rsc[i] = mlc->ipacket[i] & HIL_PKT_DATA_MASK; - } + /* Next step is to see if EXD supported (IDD has already been read) */ - if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) + if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) return HILSEN_NEXT; + return 0; } -static int hilse_take_exd(hil_mlc *mlc, int unused) { +static int hilse_take_exd(hil_mlc *mlc, int unused) +{ int i; - for (i = 0; i < 16; i++) { - mlc->di_scratch.exd[i] = + for (i = 0; i < 16; i++) + mlc->di_scratch.exd[i] = mlc->ipacket[i] & HIL_PKT_DATA_MASK; - } + /* Next step is to see if RNM supported. */ - if (mlc->di_scratch.exd[0] & HIL_EXD_HEADER_RNM) + if (mlc->di_scratch.exd[0] & HIL_EXD_HEADER_RNM) return HILSEN_NEXT; + return 0; } -static int hilse_take_rnm(hil_mlc *mlc, int unused) { +static int hilse_take_rnm(hil_mlc *mlc, int unused) +{ int i; - for (i = 0; i < 16; i++) { - mlc->di_scratch.rnm[i] = + for (i = 0; i < 16; i++) + mlc->di_scratch.rnm[i] = mlc->ipacket[i] & HIL_PKT_DATA_MASK; - } - do { - char nam[17]; - snprintf(nam, 16, "%s", mlc->di_scratch.rnm); - nam[16] = '\0'; - printk(KERN_INFO PREFIX "Device name gotten: %s\n", nam); - } while (0); + + printk(KERN_INFO PREFIX "Device name gotten: %16s\n", + mlc->di_scratch.rnm); + return 0; } -static int hilse_operate(hil_mlc *mlc, int repoll) { +static int hilse_operate(hil_mlc *mlc, int repoll) +{ - if (mlc->opercnt == 0) hil_mlcs_probe = 0; + if (mlc->opercnt == 0) + hil_mlcs_probe = 0; mlc->opercnt = 1; hil_mlc_send_polls(mlc); - if (!hil_mlcs_probe) return 0; + if (!hil_mlcs_probe) + return 0; hil_mlcs_probe = 0; mlc->opercnt = 0; return 1; @@ -408,7 +459,7 @@ static int hilse_operate(hil_mlc *mlc, int repoll) { #define OUT_LAST(pack) \ { HILSE_OUT_LAST, { .packet = pack }, 0, 0, 0, 0 }, -struct hilse_node hil_mlc_se[HILSEN_END] = { +const struct hilse_node hil_mlc_se[HILSEN_END] = { /* 0 HILSEN_START */ FUNC(hilse_init_lcv, 0, HILSEN_NEXT, HILSEN_SLEEP, 0) @@ -428,7 +479,7 @@ struct hilse_node hil_mlc_se[HILSEN_END] = { EXPECT(HIL_ERR_INT | TEST_PACKET(0xa), 2000, HILSEN_NEXT, HILSEN_RESTART, HILSEN_RESTART) OUT(HIL_CTRL_ONLY | 0) /* Disable test mode */ - + /* 9 HILSEN_DHR */ FUNC(hilse_init_lcv, 0, HILSEN_NEXT, HILSEN_SLEEP, 0) @@ -439,7 +490,7 @@ struct hilse_node hil_mlc_se[HILSEN_END] = { IN(300000, HILSEN_DHR2, HILSEN_DHR2, HILSEN_NEXT) /* 14 HILSEN_IFC */ - OUT(HIL_PKT_CMD | HIL_CMD_IFC) + OUT(HIL_PKT_CMD | HIL_CMD_IFC) EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT, 20000, HILSEN_DISC, HILSEN_DHR2, HILSEN_NEXT ) @@ -455,7 +506,7 @@ struct hilse_node hil_mlc_se[HILSEN_END] = { /* 18 HILSEN_HEAL */ OUT_LAST(HIL_CMD_ELB) - EXPECT_LAST(HIL_CMD_ELB | HIL_ERR_INT, + EXPECT_LAST(HIL_CMD_ELB | HIL_ERR_INT, 20000, HILSEN_REPOLL, HILSEN_DSR, HILSEN_NEXT) FUNC(hilse_dec_ddi, 0, HILSEN_HEAL, HILSEN_NEXT, 0) @@ -503,7 +554,7 @@ struct hilse_node hil_mlc_se[HILSEN_END] = { /* 44 HILSEN_PROBE */ OUT_LAST(HIL_PKT_CMD | HIL_CMD_EPT) - IN(10000, HILSEN_DISC, HILSEN_DSR, HILSEN_NEXT) + IN(10000, HILSEN_DISC, HILSEN_DSR, HILSEN_NEXT) OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB) IN(10000, HILSEN_DISC, HILSEN_DSR, HILSEN_NEXT) OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1) @@ -514,7 +565,7 @@ struct hilse_node hil_mlc_se[HILSEN_END] = { /* 52 HILSEN_DSR */ FUNC(hilse_set_ddi, -1, HILSEN_NEXT, 0, 0) OUT(HIL_PKT_CMD | HIL_CMD_DSR) - IN(20000, HILSEN_DHR, HILSEN_DHR, HILSEN_IFC) + IN(20000, HILSEN_DHR, HILSEN_DHR, HILSEN_IFC) /* 55 HILSEN_REPOLL */ OUT(HIL_PKT_CMD | HIL_CMD_RPL) @@ -523,14 +574,15 @@ struct hilse_node hil_mlc_se[HILSEN_END] = { FUNC(hilse_operate, 1, HILSEN_OPERATE, HILSEN_IFC, HILSEN_PROBE) /* 58 HILSEN_IFCACF */ - OUT(HIL_PKT_CMD | HIL_CMD_IFC) + OUT(HIL_PKT_CMD | HIL_CMD_IFC) EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT, 20000, HILSEN_ACF2, HILSEN_DHR2, HILSEN_HEAL) /* 60 HILSEN_END */ }; -static inline void hilse_setup_input(hil_mlc *mlc, struct hilse_node *node) { +static inline void hilse_setup_input(hil_mlc *mlc, const struct hilse_node *node) +{ switch (node->act) { case HILSE_EXPECT_DISC: @@ -555,29 +607,27 @@ static inline void hilse_setup_input(hil_mlc *mlc, struct hilse_node *node) { do_gettimeofday(&(mlc->instart)); mlc->icount = 15; memset(mlc->ipacket, 0, 16 * sizeof(hil_packet)); - BUG_ON(down_trylock(&(mlc->isem))); - - return; + BUG_ON(down_trylock(&mlc->isem)); } #ifdef HIL_MLC_DEBUG -static int doze = 0; +static int doze; static int seidx; /* For debug */ -static int kick = 1; #endif -static int hilse_donode (hil_mlc *mlc) { - struct hilse_node *node; +static int hilse_donode(hil_mlc *mlc) +{ + const struct hilse_node *node; int nextidx = 0; int sched_long = 0; unsigned long flags; #ifdef HIL_MLC_DEBUG - if (mlc->seidx && (mlc->seidx != seidx) && mlc->seidx != 41 && mlc->seidx != 42 && mlc->seidx != 43) { - printk(KERN_DEBUG PREFIX "z%i \n%s {%i}", doze, kick ? "K" : "", mlc->seidx); + if (mlc->seidx && mlc->seidx != seidx && + mlc->seidx != 41 && mlc->seidx != 42 && mlc->seidx != 43) { + printk(KERN_DEBUG PREFIX "z%i \n {%i}", doze, mlc->seidx); doze = 0; } - kick = 0; seidx = mlc->seidx; #endif @@ -588,52 +638,61 @@ static int hilse_donode (hil_mlc *mlc) { hil_packet pack; case HILSE_FUNC: - if (node->object.func == NULL) break; + BUG_ON(node->object.func == NULL); rc = node->object.func(mlc, node->arg); - nextidx = (rc > 0) ? node->ugly : + nextidx = (rc > 0) ? node->ugly : ((rc < 0) ? node->bad : node->good); - if (nextidx == HILSEN_FOLLOW) nextidx = rc; + if (nextidx == HILSEN_FOLLOW) + nextidx = rc; break; + case HILSE_EXPECT_LAST: case HILSE_EXPECT_DISC: case HILSE_EXPECT: case HILSE_IN: /* Already set up from previous HILSE_OUT_* */ - write_lock_irqsave(&(mlc->lock), flags); + write_lock_irqsave(&mlc->lock, flags); rc = mlc->in(mlc, node->arg); if (rc == 2) { nextidx = HILSEN_DOZE; sched_long = 1; - write_unlock_irqrestore(&(mlc->lock), flags); + write_unlock_irqrestore(&mlc->lock, flags); break; } - if (rc == 1) nextidx = node->ugly; - else if (rc == 0) nextidx = node->good; - else nextidx = node->bad; + if (rc == 1) + nextidx = node->ugly; + else if (rc == 0) + nextidx = node->good; + else + nextidx = node->bad; mlc->istarted = 0; - write_unlock_irqrestore(&(mlc->lock), flags); + write_unlock_irqrestore(&mlc->lock, flags); break; + case HILSE_OUT_LAST: - write_lock_irqsave(&(mlc->lock), flags); + write_lock_irqsave(&mlc->lock, flags); pack = node->object.packet; pack |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT); goto out; + case HILSE_OUT_DISC: - write_lock_irqsave(&(mlc->lock), flags); + write_lock_irqsave(&mlc->lock, flags); pack = node->object.packet; pack |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT); goto out; + case HILSE_OUT: - write_lock_irqsave(&(mlc->lock), flags); + write_lock_irqsave(&mlc->lock, flags); pack = node->object.packet; out: - if (mlc->istarted) goto out2; + if (mlc->istarted) + goto out2; /* Prepare to receive input */ if ((node + 1)->act & HILSE_IN) hilse_setup_input(mlc, node + 1); out2: - write_unlock_irqrestore(&(mlc->lock), flags); + write_unlock_irqrestore(&mlc->lock, flags); if (down_trylock(&mlc->osem)) { nextidx = HILSEN_DOZE; @@ -641,60 +700,71 @@ static int hilse_donode (hil_mlc *mlc) { } up(&mlc->osem); - write_lock_irqsave(&(mlc->lock), flags); - if (!(mlc->ostarted)) { + write_lock_irqsave(&mlc->lock, flags); + if (!mlc->ostarted) { mlc->ostarted = 1; mlc->opacket = pack; mlc->out(mlc); nextidx = HILSEN_DOZE; - write_unlock_irqrestore(&(mlc->lock), flags); + write_unlock_irqrestore(&mlc->lock, flags); break; } mlc->ostarted = 0; do_gettimeofday(&(mlc->instart)); - write_unlock_irqrestore(&(mlc->lock), flags); + write_unlock_irqrestore(&mlc->lock, flags); nextidx = HILSEN_NEXT; break; + case HILSE_CTS: + write_lock_irqsave(&mlc->lock, flags); nextidx = mlc->cts(mlc) ? node->bad : node->good; + write_unlock_irqrestore(&mlc->lock, flags); break; + default: BUG(); - nextidx = 0; - break; } #ifdef HIL_MLC_DEBUG - if (nextidx == HILSEN_DOZE) doze++; + if (nextidx == HILSEN_DOZE) + doze++; #endif while (nextidx & HILSEN_SCHED) { struct timeval tv; - if (!sched_long) goto sched; + if (!sched_long) + goto sched; do_gettimeofday(&tv); - tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec); + tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec); tv.tv_usec -= mlc->instart.tv_usec; if (tv.tv_usec >= mlc->intimeout) goto sched; - tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / 1000000; + tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / USEC_PER_SEC; if (!tv.tv_usec) goto sched; mod_timer(&hil_mlcs_kicker, jiffies + tv.tv_usec); break; sched: tasklet_schedule(&hil_mlcs_tasklet); break; - } - if (nextidx & HILSEN_DOWN) mlc->seidx += nextidx & HILSEN_MASK; - else if (nextidx & HILSEN_UP) mlc->seidx -= nextidx & HILSEN_MASK; - else mlc->seidx = nextidx & HILSEN_MASK; + } + + if (nextidx & HILSEN_DOWN) + mlc->seidx += nextidx & HILSEN_MASK; + else if (nextidx & HILSEN_UP) + mlc->seidx -= nextidx & HILSEN_MASK; + else + mlc->seidx = nextidx & HILSEN_MASK; + + if (nextidx & HILSEN_BREAK) + return 1; - if (nextidx & HILSEN_BREAK) return 1; return 0; } /******************** tasklet context functions **************************/ -static void hil_mlcs_process(unsigned long unused) { +static void hil_mlcs_process(unsigned long unused) +{ struct list_head *tmp; read_lock(&hil_mlcs_lock); @@ -702,19 +772,20 @@ static void hil_mlcs_process(unsigned long unused) { struct hil_mlc *mlc = list_entry(tmp, hil_mlc, list); while (hilse_donode(mlc) == 0) { #ifdef HIL_MLC_DEBUG - if (mlc->seidx != 41 && - mlc->seidx != 42 && - mlc->seidx != 43) - printk(KERN_DEBUG PREFIX " + "); + if (mlc->seidx != 41 && + mlc->seidx != 42 && + mlc->seidx != 43) + printk(KERN_DEBUG PREFIX " + "); #endif - }; + } } read_unlock(&hil_mlcs_lock); } /************************* Keepalive timer task *********************/ -void hil_mlcs_timer (unsigned long data) { +void hil_mlcs_timer(unsigned long data) +{ hil_mlcs_probe = 1; tasklet_schedule(&hil_mlcs_tasklet); /* Re-insert the periodic task. */ @@ -724,28 +795,25 @@ void hil_mlcs_timer (unsigned long data) { /******************** user/kernel context functions **********************/ -static int hil_mlc_serio_write(struct serio *serio, unsigned char c) { +static int hil_mlc_serio_write(struct serio *serio, unsigned char c) +{ struct hil_mlc_serio_map *map; struct hil_mlc *mlc; struct serio_driver *drv; uint8_t *idx, *last; map = serio->port_data; - if (map == NULL) { - BUG(); - return -EIO; - } + BUG_ON(map == NULL); + mlc = map->mlc; - if (mlc == NULL) { - BUG(); - return -EIO; - } - mlc->serio_opacket[map->didx] |= + BUG_ON(mlc == NULL); + + mlc->serio_opacket[map->didx] |= ((hil_packet)c) << (8 * (3 - mlc->serio_oidx[map->didx])); if (mlc->serio_oidx[map->didx] >= 3) { /* for now only commands */ - if (!(mlc->serio_opacket[map->didx] & HIL_PKT_CMD)) + if (!(mlc->serio_opacket[map->didx] & HIL_PKT_CMD)) return -EIO; switch (mlc->serio_opacket[map->didx] & HIL_PKT_DATA_MASK) { case HIL_CMD_IDD: @@ -771,12 +839,11 @@ static int hil_mlc_serio_write(struct serio *serio, unsigned char c) { return -EIO; emu: drv = serio->drv; - if (drv == NULL) { - BUG(); - return -EIO; - } + BUG_ON(drv == NULL); + last = idx + 15; - while ((last != idx) && (*last == 0)) last--; + while ((last != idx) && (*last == 0)) + last--; while (idx != last) { drv->interrupt(serio, 0, 0); @@ -789,14 +856,15 @@ static int hil_mlc_serio_write(struct serio *serio, unsigned char c) { drv->interrupt(serio, HIL_ERR_INT >> 16, 0); drv->interrupt(serio, HIL_PKT_CMD >> 8, 0); drv->interrupt(serio, *idx, 0); - + mlc->serio_oidx[map->didx] = 0; mlc->serio_opacket[map->didx] = 0; return 0; } -static int hil_mlc_serio_open(struct serio *serio) { +static int hil_mlc_serio_open(struct serio *serio) +{ struct hil_mlc_serio_map *map; struct hil_mlc *mlc; @@ -804,67 +872,57 @@ static int hil_mlc_serio_open(struct serio *serio) { return -EBUSY; map = serio->port_data; - if (map == NULL) { - BUG(); - return -ENODEV; - } + BUG_ON(map == NULL); + mlc = map->mlc; - if (mlc == NULL) { - BUG(); - return -ENODEV; - } + BUG_ON(mlc == NULL); return 0; } -static void hil_mlc_serio_close(struct serio *serio) { +static void hil_mlc_serio_close(struct serio *serio) +{ struct hil_mlc_serio_map *map; struct hil_mlc *mlc; map = serio->port_data; - if (map == NULL) { - BUG(); - return; - } + BUG_ON(map == NULL); + mlc = map->mlc; - if (mlc == NULL) { - BUG(); - return; - } + BUG_ON(mlc == NULL); serio_set_drvdata(serio, NULL); serio->drv = NULL; /* TODO wake up interruptable */ } -static struct serio_device_id hil_mlc_serio_id = { +static const struct serio_device_id hil_mlc_serio_id = { .type = SERIO_HIL_MLC, .proto = SERIO_HIL, .extra = SERIO_ANY, .id = SERIO_ANY, }; -int hil_mlc_register(hil_mlc *mlc) { +int hil_mlc_register(hil_mlc *mlc) +{ int i; - unsigned long flags; + unsigned long flags; - if (mlc == NULL) { - return -EINVAL; - } + BUG_ON(mlc == NULL); mlc->istarted = 0; - mlc->ostarted = 0; + mlc->ostarted = 0; - rwlock_init(&mlc->lock); - init_MUTEX(&(mlc->osem)); + rwlock_init(&mlc->lock); + init_MUTEX(&mlc->osem); - init_MUTEX(&(mlc->isem)); - mlc->icount = -1; - mlc->imatch = 0; + init_MUTEX(&mlc->isem); + mlc->icount = -1; + mlc->imatch = 0; mlc->opercnt = 0; - init_MUTEX_LOCKED(&(mlc->csem)); + init_MUTEX_LOCKED(&(mlc->csem)); hil_mlc_clear_di_scratch(mlc); hil_mlc_clear_di_map(mlc, 0); @@ -873,6 +931,8 @@ int hil_mlc_register(hil_mlc *mlc) { hil_mlc_copy_di_scratch(mlc, i); mlc_serio = kzalloc(sizeof(*mlc_serio), GFP_KERNEL); mlc->serio[i] = mlc_serio; + snprintf(mlc_serio->name, sizeof(mlc_serio->name)-1, "HIL_SERIO%d", i); + snprintf(mlc_serio->phys, sizeof(mlc_serio->phys)-1, "HIL%d", i); mlc_serio->id = hil_mlc_serio_id; mlc_serio->write = hil_mlc_serio_write; mlc_serio->open = hil_mlc_serio_open; @@ -897,19 +957,18 @@ int hil_mlc_register(hil_mlc *mlc) { return 0; } -int hil_mlc_unregister(hil_mlc *mlc) { +int hil_mlc_unregister(hil_mlc *mlc) +{ struct list_head *tmp; - unsigned long flags; + unsigned long flags; int i; - if (mlc == NULL) - return -EINVAL; + BUG_ON(mlc == NULL); write_lock_irqsave(&hil_mlcs_lock, flags); - list_for_each(tmp, &hil_mlcs) { + list_for_each(tmp, &hil_mlcs) if (list_entry(tmp, hil_mlc, list) == mlc) goto found; - } /* not found in list */ write_unlock_irqrestore(&hil_mlcs_lock, flags); @@ -918,7 +977,7 @@ int hil_mlc_unregister(hil_mlc *mlc) { found: list_del(tmp); - write_unlock_irqrestore(&hil_mlcs_lock, flags); + write_unlock_irqrestore(&hil_mlcs_lock, flags); for (i = 0; i < HIL_MLC_DEVMEM; i++) { serio_unregister_port(mlc->serio[i]); @@ -942,7 +1001,7 @@ static int __init hil_mlc_init(void) return 0; } - + static void __exit hil_mlc_exit(void) { del_timer(&hil_mlcs_kicker); @@ -950,6 +1009,6 @@ static void __exit hil_mlc_exit(void) tasklet_disable(&hil_mlcs_tasklet); tasklet_kill(&hil_mlcs_tasklet); } - + module_init(hil_mlc_init); module_exit(hil_mlc_exit); diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index b57370d..6af1998 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c @@ -34,27 +34,27 @@ * * Driver theory of operation: * - * hp_sdc_put does all writing to the SDC. ISR can run on a different - * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time + * hp_sdc_put does all writing to the SDC. ISR can run on a different + * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time * (it cannot really benefit from SMP anyway.) A tasket fit this perfectly. * - * All data coming back from the SDC is sent via interrupt and can be read - * fully in the ISR, so there are no latency/throughput problems there. - * The problem is with output, due to the slow clock speed of the SDC - * compared to the CPU. This should not be too horrible most of the time, - * but if used with HIL devices that support the multibyte transfer command, - * keeping outbound throughput flowing at the 6500KBps that the HIL is + * All data coming back from the SDC is sent via interrupt and can be read + * fully in the ISR, so there are no latency/throughput problems there. + * The problem is with output, due to the slow clock speed of the SDC + * compared to the CPU. This should not be too horrible most of the time, + * but if used with HIL devices that support the multibyte transfer command, + * keeping outbound throughput flowing at the 6500KBps that the HIL is * capable of is more than can be done at HZ=100. * - * Busy polling for IBF clear wastes CPU cycles and bus cycles. hp_sdc.ibf - * is set to 0 when the IBF flag in the status register has cleared. ISR - * may do this, and may also access the parts of queued transactions related - * to reading data back from the SDC, but otherwise will not touch the + * Busy polling for IBF clear wastes CPU cycles and bus cycles. hp_sdc.ibf + * is set to 0 when the IBF flag in the status register has cleared. ISR + * may do this, and may also access the parts of queued transactions related + * to reading data back from the SDC, but otherwise will not touch the * hp_sdc state. Whenever a register is written hp_sdc.ibf is set to 1. * * The i8042 write index and the values in the 4-byte input buffer * starting at 0x70 are kept track of in hp_sdc.wi, and .r7[], respectively, - * to minimize the amount of IO needed to the SDC. However these values + * to minimize the amount of IO needed to the SDC. However these values * do not need to be locked since they are only ever accessed by hp_sdc_put. * * A timer task schedules the tasklet once per second just to make @@ -100,39 +100,46 @@ EXPORT_SYMBOL(hp_sdc_release_timer_irq); EXPORT_SYMBOL(hp_sdc_release_hil_irq); EXPORT_SYMBOL(hp_sdc_release_cooked_irq); +EXPORT_SYMBOL(__hp_sdc_enqueue_transaction); EXPORT_SYMBOL(hp_sdc_enqueue_transaction); EXPORT_SYMBOL(hp_sdc_dequeue_transaction); static hp_i8042_sdc hp_sdc; /* All driver state is kept in here. */ /*************** primitives for use in any context *********************/ -static inline uint8_t hp_sdc_status_in8 (void) { +static inline uint8_t hp_sdc_status_in8(void) +{ uint8_t status; unsigned long flags; write_lock_irqsave(&hp_sdc.ibf_lock, flags); status = sdc_readb(hp_sdc.status_io); - if (!(status & HP_SDC_STATUS_IBF)) hp_sdc.ibf = 0; + if (!(status & HP_SDC_STATUS_IBF)) + hp_sdc.ibf = 0; write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); return status; } -static inline uint8_t hp_sdc_data_in8 (void) { - return sdc_readb(hp_sdc.data_io); +static inline uint8_t hp_sdc_data_in8(void) +{ + return sdc_readb(hp_sdc.data_io); } -static inline void hp_sdc_status_out8 (uint8_t val) { +static inline void hp_sdc_status_out8(uint8_t val) +{ unsigned long flags; write_lock_irqsave(&hp_sdc.ibf_lock, flags); hp_sdc.ibf = 1; - if ((val & 0xf0) == 0xe0) hp_sdc.wi = 0xff; + if ((val & 0xf0) == 0xe0) + hp_sdc.wi = 0xff; sdc_writeb(val, hp_sdc.status_io); write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); } -static inline void hp_sdc_data_out8 (uint8_t val) { +static inline void hp_sdc_data_out8(uint8_t val) +{ unsigned long flags; write_lock_irqsave(&hp_sdc.ibf_lock, flags); @@ -141,11 +148,12 @@ static inline void hp_sdc_data_out8 (uint8_t val) { write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); } -/* Care must be taken to only invoke hp_sdc_spin_ibf when - * absolutely needed, or in rarely invoked subroutines. - * Not only does it waste CPU cycles, it also wastes bus cycles. +/* Care must be taken to only invoke hp_sdc_spin_ibf when + * absolutely needed, or in rarely invoked subroutines. + * Not only does it waste CPU cycles, it also wastes bus cycles. */ -static inline void hp_sdc_spin_ibf(void) { +static inline void hp_sdc_spin_ibf(void) +{ unsigned long flags; rwlock_t *lock; @@ -158,19 +166,21 @@ static inline void hp_sdc_spin_ibf(void) { } read_unlock(lock); write_lock(lock); - while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF) {}; + while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF) + { } hp_sdc.ibf = 0; write_unlock_irqrestore(lock, flags); } /************************ Interrupt context functions ************************/ -static void hp_sdc_take (int irq, void *dev_id, uint8_t status, uint8_t data) { +static void hp_sdc_take(int irq, void *dev_id, uint8_t status, uint8_t data) +{ hp_sdc_transaction *curr; read_lock(&hp_sdc.rtq_lock); if (hp_sdc.rcurr < 0) { - read_unlock(&hp_sdc.rtq_lock); + read_unlock(&hp_sdc.rtq_lock); return; } curr = hp_sdc.tq[hp_sdc.rcurr]; @@ -183,25 +193,27 @@ static void hp_sdc_take (int irq, void *dev_id, uint8_t status, uint8_t data) { if (hp_sdc.rqty <= 0) { /* All data has been gathered. */ - if(curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE) { - if (curr->act.semaphore) up(curr->act.semaphore); - } - if(curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK) { + if (curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE) + if (curr->act.semaphore) + up(curr->act.semaphore); + + if (curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK) if (curr->act.irqhook) curr->act.irqhook(irq, dev_id, status, data); - } + curr->actidx = curr->idx; curr->idx++; /* Return control of this transaction */ write_lock(&hp_sdc.rtq_lock); - hp_sdc.rcurr = -1; + hp_sdc.rcurr = -1; hp_sdc.rqty = 0; write_unlock(&hp_sdc.rtq_lock); tasklet_schedule(&hp_sdc.task); } } -static irqreturn_t hp_sdc_isr(int irq, void *dev_id) { +static irqreturn_t hp_sdc_isr(int irq, void *dev_id) +{ uint8_t status, data; status = hp_sdc_status_in8(); @@ -209,67 +221,74 @@ static irqreturn_t hp_sdc_isr(int irq, void *dev_id) { data = hp_sdc_data_in8(); /* For now we are ignoring these until we get the SDC to behave. */ - if (((status & 0xf1) == 0x51) && data == 0x82) { - return IRQ_HANDLED; - } + if (((status & 0xf1) == 0x51) && data == 0x82) + return IRQ_HANDLED; - switch(status & HP_SDC_STATUS_IRQMASK) { - case 0: /* This case is not documented. */ + switch (status & HP_SDC_STATUS_IRQMASK) { + case 0: /* This case is not documented. */ break; - case HP_SDC_STATUS_USERTIMER: - case HP_SDC_STATUS_PERIODIC: - case HP_SDC_STATUS_TIMER: + + case HP_SDC_STATUS_USERTIMER: + case HP_SDC_STATUS_PERIODIC: + case HP_SDC_STATUS_TIMER: read_lock(&hp_sdc.hook_lock); - if (hp_sdc.timer != NULL) + if (hp_sdc.timer != NULL) hp_sdc.timer(irq, dev_id, status, data); read_unlock(&hp_sdc.hook_lock); break; - case HP_SDC_STATUS_REG: + + case HP_SDC_STATUS_REG: hp_sdc_take(irq, dev_id, status, data); break; - case HP_SDC_STATUS_HILCMD: - case HP_SDC_STATUS_HILDATA: + + case HP_SDC_STATUS_HILCMD: + case HP_SDC_STATUS_HILDATA: read_lock(&hp_sdc.hook_lock); if (hp_sdc.hil != NULL) hp_sdc.hil(irq, dev_id, status, data); read_unlock(&hp_sdc.hook_lock); break; - case HP_SDC_STATUS_PUP: + + case HP_SDC_STATUS_PUP: read_lock(&hp_sdc.hook_lock); if (hp_sdc.pup != NULL) hp_sdc.pup(irq, dev_id, status, data); - else printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n"); + else + printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n"); read_unlock(&hp_sdc.hook_lock); break; - default: + + default: read_lock(&hp_sdc.hook_lock); if (hp_sdc.cooked != NULL) hp_sdc.cooked(irq, dev_id, status, data); read_unlock(&hp_sdc.hook_lock); break; } + return IRQ_HANDLED; } -static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id) { +static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id) +{ int status; - + status = hp_sdc_status_in8(); printk(KERN_WARNING PREFIX "NMI !\n"); -#if 0 +#if 0 if (status & HP_SDC_NMISTATUS_FHS) { read_lock(&hp_sdc.hook_lock); - if (hp_sdc.timer != NULL) + if (hp_sdc.timer != NULL) hp_sdc.timer(irq, dev_id, status, 0); read_unlock(&hp_sdc.hook_lock); - } - else { + } else { /* TODO: pass this on to the HIL handler, or do SAK here? */ printk(KERN_WARNING PREFIX "HIL NMI\n"); } #endif + return IRQ_HANDLED; } @@ -278,13 +297,17 @@ static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id) { unsigned long hp_sdc_put(void); -static void hp_sdc_tasklet(unsigned long foo) { - +static void hp_sdc_tasklet(unsigned long foo) +{ write_lock_irq(&hp_sdc.rtq_lock); + if (hp_sdc.rcurr >= 0) { struct timeval tv; + do_gettimeofday(&tv); - if (tv.tv_sec > hp_sdc.rtv.tv_sec) tv.tv_usec += 1000000; + if (tv.tv_sec > hp_sdc.rtv.tv_sec) + tv.tv_usec += USEC_PER_SEC; + if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) { hp_sdc_transaction *curr; uint8_t tmp; @@ -300,27 +323,29 @@ static void hp_sdc_tasklet(unsigned long foo) { hp_sdc.rqty = 0; tmp = curr->seq[curr->actidx]; curr->seq[curr->actidx] |= HP_SDC_ACT_DEAD; - if(tmp & HP_SDC_ACT_SEMAPHORE) { - if (curr->act.semaphore) + if (tmp & HP_SDC_ACT_SEMAPHORE) + if (curr->act.semaphore) up(curr->act.semaphore); - } - if(tmp & HP_SDC_ACT_CALLBACK) { + + if (tmp & HP_SDC_ACT_CALLBACK) { /* Note this means that irqhooks may be called * in tasklet/bh context. */ - if (curr->act.irqhook) + if (curr->act.irqhook) curr->act.irqhook(0, NULL, 0, 0); } + curr->actidx = curr->idx; curr->idx++; - hp_sdc.rcurr = -1; + hp_sdc.rcurr = -1; } } write_unlock_irq(&hp_sdc.rtq_lock); hp_sdc_put(); } -unsigned long hp_sdc_put(void) { +unsigned long hp_sdc_put(void) +{ hp_sdc_transaction *curr; uint8_t act; int idx, curridx; @@ -333,19 +358,24 @@ unsigned long hp_sdc_put(void) { requires output, so we skip to the administrativa. */ if (hp_sdc.ibf) { hp_sdc_status_in8(); - if (hp_sdc.ibf) goto finish; + if (hp_sdc.ibf) + goto finish; } anew: /* See if we are in the middle of a sequence. */ - if (hp_sdc.wcurr < 0) hp_sdc.wcurr = 0; + if (hp_sdc.wcurr < 0) + hp_sdc.wcurr = 0; read_lock_irq(&hp_sdc.rtq_lock); - if (hp_sdc.rcurr == hp_sdc.wcurr) hp_sdc.wcurr++; + if (hp_sdc.rcurr == hp_sdc.wcurr) + hp_sdc.wcurr++; read_unlock_irq(&hp_sdc.rtq_lock); - if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; + if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) + hp_sdc.wcurr = 0; curridx = hp_sdc.wcurr; - if (hp_sdc.tq[curridx] != NULL) goto start; + if (hp_sdc.tq[curridx] != NULL) + goto start; while (++curridx != hp_sdc.wcurr) { if (curridx >= HP_SDC_QUEUE_LEN) { @@ -358,7 +388,8 @@ unsigned long hp_sdc_put(void) { continue; } read_unlock_irq(&hp_sdc.rtq_lock); - if (hp_sdc.tq[curridx] != NULL) break; /* Found one. */ + if (hp_sdc.tq[curridx] != NULL) + break; /* Found one. */ } if (curridx == hp_sdc.wcurr) { /* There's nothing queued to do. */ curridx = -1; @@ -374,7 +405,8 @@ unsigned long hp_sdc_put(void) { goto finish; } - if (hp_sdc.wcurr == -1) goto done; + if (hp_sdc.wcurr == -1) + goto done; curr = hp_sdc.tq[curridx]; idx = curr->actidx; @@ -383,20 +415,23 @@ unsigned long hp_sdc_put(void) { hp_sdc.tq[curridx] = NULL; /* Interleave outbound data between the transactions. */ hp_sdc.wcurr++; - if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; - goto finish; + if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) + hp_sdc.wcurr = 0; + goto finish; } act = curr->seq[idx]; idx++; if (curr->idx >= curr->endidx) { - if (act & HP_SDC_ACT_DEALLOC) kfree(curr); + if (act & HP_SDC_ACT_DEALLOC) + kfree(curr); hp_sdc.tq[curridx] = NULL; /* Interleave outbound data between the transactions. */ hp_sdc.wcurr++; - if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; - goto finish; + if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) + hp_sdc.wcurr = 0; + goto finish; } while (act & HP_SDC_ACT_PRECMD) { @@ -409,9 +444,10 @@ unsigned long hp_sdc_put(void) { curr->idx++; /* act finished? */ if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_PRECMD) - goto actdone; + goto actdone; /* skip quantity field if data-out sequence follows. */ - if (act & HP_SDC_ACT_DATAOUT) curr->idx++; + if (act & HP_SDC_ACT_DATAOUT) + curr->idx++; goto finish; } if (act & HP_SDC_ACT_DATAOUT) { @@ -423,15 +459,15 @@ unsigned long hp_sdc_put(void) { hp_sdc_data_out8(curr->seq[curr->idx]); curr->idx++; /* act finished? */ - if ((curr->idx - idx >= qty) && - ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT)) + if (curr->idx - idx >= qty && + (act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT) goto actdone; goto finish; } idx += qty; act &= ~HP_SDC_ACT_DATAOUT; - } - else while (act & HP_SDC_ACT_DATAREG) { + } else + while (act & HP_SDC_ACT_DATAREG) { int mask; uint8_t w7[4]; @@ -445,26 +481,30 @@ unsigned long hp_sdc_put(void) { act &= ~HP_SDC_ACT_DATAREG; break; } - + w7[0] = (mask & 1) ? curr->seq[++idx] : hp_sdc.r7[0]; w7[1] = (mask & 2) ? curr->seq[++idx] : hp_sdc.r7[1]; w7[2] = (mask & 4) ? curr->seq[++idx] : hp_sdc.r7[2]; w7[3] = (mask & 8) ? curr->seq[++idx] : hp_sdc.r7[3]; - + if (hp_sdc.wi > 0x73 || hp_sdc.wi < 0x70 || - w7[hp_sdc.wi-0x70] == hp_sdc.r7[hp_sdc.wi-0x70]) { + w7[hp_sdc.wi - 0x70] == hp_sdc.r7[hp_sdc.wi - 0x70]) { int i = 0; - /* Need to point the write index register */ - while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++; + /* Need to point the write index register */ + while (i < 4 && w7[i] == hp_sdc.r7[i]) + i++; + if (i < 4) { hp_sdc_status_out8(HP_SDC_CMD_SET_D0 + i); hp_sdc.wi = 0x70 + i; goto finish; } + idx++; if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG) goto actdone; + curr->idx = idx; act &= ~HP_SDC_ACT_DATAREG; break; @@ -476,12 +516,13 @@ unsigned long hp_sdc_put(void) { { int i = 0; - while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++; + while ((i < 4) && w7[i] == hp_sdc.r7[i]) + i++; if (i >= 4) { curr->idx = idx + 1; - if ((act & HP_SDC_ACT_DURING) == + if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG) - goto actdone; + goto actdone; } } goto finish; @@ -497,7 +538,7 @@ unsigned long hp_sdc_put(void) { if (act & HP_SDC_ACT_POSTCMD) { - uint8_t postcmd; + uint8_t postcmd; /* curr->idx should == idx at this point. */ postcmd = curr->seq[idx]; @@ -505,12 +546,12 @@ unsigned long hp_sdc_put(void) { if (act & HP_SDC_ACT_DATAIN) { /* Start a new read */ - hp_sdc.rqty = curr->seq[curr->idx]; + hp_sdc.rqty = curr->seq[curr->idx]; do_gettimeofday(&hp_sdc.rtv); curr->idx++; /* Still need to lock here in case of spurious irq. */ write_lock_irq(&hp_sdc.rtq_lock); - hp_sdc.rcurr = curridx; + hp_sdc.rcurr = curridx; write_unlock_irq(&hp_sdc.rtq_lock); hp_sdc_status_out8(postcmd); goto finish; @@ -519,75 +560,86 @@ unsigned long hp_sdc_put(void) { goto actdone; } -actdone: - if (act & HP_SDC_ACT_SEMAPHORE) { + actdone: + if (act & HP_SDC_ACT_SEMAPHORE) up(curr->act.semaphore); - } - else if (act & HP_SDC_ACT_CALLBACK) { + else if (act & HP_SDC_ACT_CALLBACK) curr->act.irqhook(0,NULL,0,0); - } + if (curr->idx >= curr->endidx) { /* This transaction is over. */ - if (act & HP_SDC_ACT_DEALLOC) kfree(curr); + if (act & HP_SDC_ACT_DEALLOC) + kfree(curr); hp_sdc.tq[curridx] = NULL; - } - else { + } else { curr->actidx = idx + 1; curr->idx = idx + 2; } /* Interleave outbound data between the transactions. */ hp_sdc.wcurr++; - if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; + if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) + hp_sdc.wcurr = 0; finish: - /* If by some quirk IBF has cleared and our ISR has run to + /* If by some quirk IBF has cleared and our ISR has run to see that that has happened, do it all again. */ - if (!hp_sdc.ibf && limit++ < 20) goto anew; + if (!hp_sdc.ibf && limit++ < 20) + goto anew; done: - if (hp_sdc.wcurr >= 0) tasklet_schedule(&hp_sdc.task); + if (hp_sdc.wcurr >= 0) + tasklet_schedule(&hp_sdc.task); write_unlock(&hp_sdc.lock); + return 0; } /******* Functions called in either user or kernel context ****/ -int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) { - unsigned long flags; +int __hp_sdc_enqueue_transaction(hp_sdc_transaction *this) +{ int i; if (this == NULL) { - tasklet_schedule(&hp_sdc.task); + BUG(); return -EINVAL; - }; - - write_lock_irqsave(&hp_sdc.lock, flags); + } /* Can't have same transaction on queue twice */ - for (i=0; i < HP_SDC_QUEUE_LEN; i++) - if (hp_sdc.tq[i] == this) goto fail; + for (i = 0; i < HP_SDC_QUEUE_LEN; i++) + if (hp_sdc.tq[i] == this) + goto fail; this->actidx = 0; this->idx = 1; /* Search for empty slot */ - for (i=0; i < HP_SDC_QUEUE_LEN; i++) { + for (i = 0; i < HP_SDC_QUEUE_LEN; i++) if (hp_sdc.tq[i] == NULL) { hp_sdc.tq[i] = this; - write_unlock_irqrestore(&hp_sdc.lock, flags); tasklet_schedule(&hp_sdc.task); return 0; } - } - write_unlock_irqrestore(&hp_sdc.lock, flags); + printk(KERN_WARNING PREFIX "No free slot to add transaction.\n"); return -EBUSY; fail: - write_unlock_irqrestore(&hp_sdc.lock,flags); printk(KERN_WARNING PREFIX "Transaction add failed: transaction already queued?\n"); return -EINVAL; } -int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) { +int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) { + unsigned long flags; + int ret; + + write_lock_irqsave(&hp_sdc.lock, flags); + ret = __hp_sdc_enqueue_transaction(this); + write_unlock_irqrestore(&hp_sdc.lock,flags); + + return ret; +} + +int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) +{ unsigned long flags; int i; @@ -595,8 +647,9 @@ int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) { /* TODO: don't remove it if it's not done. */ - for (i=0; i < HP_SDC_QUEUE_LEN; i++) - if (hp_sdc.tq[i] == this) hp_sdc.tq[i] = NULL; + for (i = 0; i < HP_SDC_QUEUE_LEN; i++) + if (hp_sdc.tq[i] == this) + hp_sdc.tq[i] = NULL; write_unlock_irqrestore(&hp_sdc.lock, flags); return 0; @@ -605,11 +658,11 @@ int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) { /********************** User context functions **************************/ -int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) { - - if (callback == NULL || hp_sdc.dev == NULL) { +int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) +{ + if (callback == NULL || hp_sdc.dev == NULL) return -EINVAL; - } + write_lock_irq(&hp_sdc.hook_lock); if (hp_sdc.timer != NULL) { write_unlock_irq(&hp_sdc.hook_lock); @@ -629,11 +682,11 @@ int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) { return 0; } -int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) { - - if (callback == NULL || hp_sdc.dev == NULL) { +int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) +{ + if (callback == NULL || hp_sdc.dev == NULL) return -EINVAL; - } + write_lock_irq(&hp_sdc.hook_lock); if (hp_sdc.hil != NULL) { write_unlock_irq(&hp_sdc.hook_lock); @@ -650,11 +703,11 @@ int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) { return 0; } -int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) { - - if (callback == NULL || hp_sdc.dev == NULL) { +int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) +{ + if (callback == NULL || hp_sdc.dev == NULL) return -EINVAL; - } + write_lock_irq(&hp_sdc.hook_lock); if (hp_sdc.cooked != NULL) { write_unlock_irq(&hp_sdc.hook_lock); @@ -672,9 +725,8 @@ int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) { return 0; } -int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) { - - +int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) +{ write_lock_irq(&hp_sdc.hook_lock); if ((callback != hp_sdc.timer) || (hp_sdc.timer == NULL)) { @@ -694,8 +746,8 @@ int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) { return 0; } -int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) { - +int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) +{ write_lock_irq(&hp_sdc.hook_lock); if ((callback != hp_sdc.hil) || (hp_sdc.hil == NULL)) { @@ -715,8 +767,8 @@ int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) { return 0; } -int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) { - +int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) +{ write_lock_irq(&hp_sdc.hook_lock); if ((callback != hp_sdc.cooked) || (hp_sdc.cooked == NULL)) { @@ -738,7 +790,8 @@ int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) { /************************* Keepalive timer task *********************/ -void hp_sdc_kicker (unsigned long data) { +void hp_sdc_kicker (unsigned long data) +{ tasklet_schedule(&hp_sdc.task); /* Re-insert the periodic task. */ mod_timer(&hp_sdc.kicker, jiffies + HZ); @@ -748,12 +801,12 @@ void hp_sdc_kicker (unsigned long data) { #if defined(__hppa__) -static struct parisc_device_id hp_sdc_tbl[] = { +static const struct parisc_device_id hp_sdc_tbl[] = { { - .hw_type = HPHW_FIO, + .hw_type = HPHW_FIO, .hversion_rev = HVERSION_REV_ANY_ID, .hversion = HVERSION_ANY_ID, - .sversion = 0x73, + .sversion = 0x73, }, { 0, } }; @@ -772,16 +825,15 @@ static struct parisc_driver hp_sdc_driver = { static int __init hp_sdc_init(void) { - int i; char *errstr; hp_sdc_transaction t_sync; uint8_t ts_sync[6]; struct semaphore s_sync; - rwlock_init(&hp_sdc.lock); - rwlock_init(&hp_sdc.ibf_lock); - rwlock_init(&hp_sdc.rtq_lock); - rwlock_init(&hp_sdc.hook_lock); + rwlock_init(&hp_sdc.lock); + rwlock_init(&hp_sdc.ibf_lock); + rwlock_init(&hp_sdc.rtq_lock); + rwlock_init(&hp_sdc.hook_lock); hp_sdc.timer = NULL; hp_sdc.hil = NULL; @@ -796,7 +848,8 @@ static int __init hp_sdc_init(void) hp_sdc.r7[3] = 0xff; hp_sdc.ibf = 1; - for (i = 0; i < HP_SDC_QUEUE_LEN; i++) hp_sdc.tq[i] = NULL; + memset(&hp_sdc.tq, 0, sizeof(hp_sdc.tq)); + hp_sdc.wcurr = -1; hp_sdc.rcurr = -1; hp_sdc.rqty = 0; @@ -804,27 +857,32 @@ static int __init hp_sdc_init(void) hp_sdc.dev_err = -ENODEV; errstr = "IO not found for"; - if (!hp_sdc.base_io) goto err0; + if (!hp_sdc.base_io) + goto err0; errstr = "IRQ not found for"; - if (!hp_sdc.irq) goto err0; + if (!hp_sdc.irq) + goto err0; hp_sdc.dev_err = -EBUSY; #if defined(__hppa__) errstr = "IO not available for"; - if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name)) goto err0; -#endif + if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name)) + goto err0; +#endif errstr = "IRQ not available for"; - if(request_irq(hp_sdc.irq, &hp_sdc_isr, 0, "HP SDC", - (void *) hp_sdc.base_io)) goto err1; + if (request_irq(hp_sdc.irq, &hp_sdc_isr, IRQF_SHARED|IRQF_SAMPLE_RANDOM, + "HP SDC", &hp_sdc)) + goto err1; errstr = "NMI not available for"; - if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, 0, "HP SDC NMI", - (void *) hp_sdc.base_io)) goto err2; + if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, IRQF_SHARED, + "HP SDC NMI", &hp_sdc)) + goto err2; - printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n", + printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n", (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi); hp_sdc_status_in8(); @@ -854,13 +912,14 @@ static int __init hp_sdc_init(void) hp_sdc.dev_err = 0; return 0; err2: - free_irq(hp_sdc.irq, NULL); + free_irq(hp_sdc.irq, &hp_sdc); err1: release_region(hp_sdc.data_io, 2); err0: - printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n", + printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n", errstr, (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi); hp_sdc.dev = NULL; + return hp_sdc.dev_err; } @@ -868,8 +927,10 @@ static int __init hp_sdc_init(void) static int __init hp_sdc_init_hppa(struct parisc_device *d) { - if (!d) return 1; - if (hp_sdc.dev != NULL) return 1; /* We only expect one SDC */ + if (!d) + return 1; + if (hp_sdc.dev != NULL) + return 1; /* We only expect one SDC */ hp_sdc.dev = d; hp_sdc.irq = d->irq; @@ -898,18 +959,16 @@ static void hp_sdc_exit(void) /* Wait until we know this has been processed by the i8042 */ hp_sdc_spin_ibf(); - free_irq(hp_sdc.nmi, NULL); - free_irq(hp_sdc.irq, NULL); + free_irq(hp_sdc.nmi, &hp_sdc); + free_irq(hp_sdc.irq, &hp_sdc); write_unlock_irq(&hp_sdc.lock); del_timer(&hp_sdc.kicker); tasklet_kill(&hp_sdc.task); -/* release_region(hp_sdc.data_io, 2); */ - #if defined(__hppa__) - if (unregister_parisc_driver(&hp_sdc_driver)) + if (unregister_parisc_driver(&hp_sdc_driver)) printk(KERN_WARNING PREFIX "Error unregistering HP SDC"); #endif } @@ -923,7 +982,7 @@ static int __init hp_sdc_register(void) mm_segment_t fs; unsigned char i; #endif - + hp_sdc.dev = NULL; hp_sdc.dev_err = 0; #if defined(__hppa__) @@ -960,8 +1019,8 @@ static int __init hp_sdc_register(void) tq_init.seq = tq_init_seq; tq_init.act.semaphore = &tq_init_sem; - tq_init_seq[0] = - HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE; + tq_init_seq[0] = + HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE; tq_init_seq[1] = HP_SDC_CMD_READ_KCC; tq_init_seq[2] = 1; tq_init_seq[3] = 0; @@ -979,13 +1038,13 @@ static int __init hp_sdc_register(void) } hp_sdc.r11 = tq_init_seq[4]; if (hp_sdc.r11 & HP_SDC_CFG_NEW) { - char *str; + const char *str; printk(KERN_INFO PREFIX "New style SDC\n"); tq_init_seq[1] = HP_SDC_CMD_READ_XTD; tq_init.actidx = 0; tq_init.idx = 1; down(&tq_init_sem); - hp_sdc_enqueue_transaction(&tq_init); + hp_sdc_enqueue_transaction(&tq_init); down(&tq_init_sem); up(&tq_init_sem); if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) { @@ -995,15 +1054,13 @@ static int __init hp_sdc_register(void) hp_sdc.r7e = tq_init_seq[4]; HP_SDC_XTD_REV_STRINGS(hp_sdc.r7e & HP_SDC_XTD_REV, str) printk(KERN_INFO PREFIX "Revision: %s\n", str); - if (hp_sdc.r7e & HP_SDC_XTD_BEEPER) { + if (hp_sdc.r7e & HP_SDC_XTD_BEEPER) printk(KERN_INFO PREFIX "TI SN76494 beeper present\n"); - } - if (hp_sdc.r7e & HP_SDC_XTD_BBRTC) { + if (hp_sdc.r7e & HP_SDC_XTD_BBRTC) printk(KERN_INFO PREFIX "OKI MSM-58321 BBRTC present\n"); - } printk(KERN_INFO PREFIX "Spunking the self test register to force PUP " "on next firmware reset.\n"); - tq_init_seq[0] = HP_SDC_ACT_PRECMD | + tq_init_seq[0] = HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE; tq_init_seq[1] = HP_SDC_CMD_SET_STR; tq_init_seq[2] = 1; @@ -1012,14 +1069,12 @@ static int __init hp_sdc_register(void) tq_init.idx = 1; tq_init.endidx = 4; down(&tq_init_sem); - hp_sdc_enqueue_transaction(&tq_init); + hp_sdc_enqueue_transaction(&tq_init); down(&tq_init_sem); up(&tq_init_sem); - } - else { - printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n", + } else + printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n", (hp_sdc.r11 & HP_SDC_CFG_REV) ? "3300" : "2564/3087"); - } return 0; } @@ -1027,13 +1082,13 @@ static int __init hp_sdc_register(void) module_init(hp_sdc_register); module_exit(hp_sdc_exit); -/* Timing notes: These measurements taken on my 64MHz 7100-LC (715/64) +/* Timing notes: These measurements taken on my 64MHz 7100-LC (715/64) * cycles cycles-adj time * between two consecutive mfctl(16)'s: 4 n/a 63ns * hp_sdc_spin_ibf when idle: 119 115 1.7us * gsc_writeb status register: 83 79 1.2us * IBF to clear after sending SET_IM: 6204 6006 93us - * IBF to clear after sending LOAD_RT: 4467 4352 68us + * IBF to clear after sending LOAD_RT: 4467 4352 68us * IBF to clear after sending two LOAD_RTs: 18974 18859 295us * READ_T1, read status/data, IRQ, call handler: 35564 n/a 556us * cmd to ~IBF READ_T1 2nd time right after: 5158403 n/a 81ms diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c index aa4a8a4..c45ea74 100644 --- a/drivers/input/serio/hp_sdc_mlc.c +++ b/drivers/input/serio/hp_sdc_mlc.c @@ -58,12 +58,13 @@ struct hp_sdc_mlc_priv_s { } hp_sdc_mlc_priv; /************************* Interrupt context ******************************/ -static void hp_sdc_mlc_isr (int irq, void *dev_id, - uint8_t status, uint8_t data) { - int idx; +static void hp_sdc_mlc_isr (int irq, void *dev_id, + uint8_t status, uint8_t data) +{ + int idx; hil_mlc *mlc = &hp_sdc_mlc; - write_lock(&(mlc->lock)); + write_lock(&mlc->lock); if (mlc->icount < 0) { printk(KERN_WARNING PREFIX "HIL Overflow!\n"); up(&mlc->isem); @@ -73,239 +74,232 @@ static void hp_sdc_mlc_isr (int irq, void *dev_id, if ((status & HP_SDC_STATUS_IRQMASK) == HP_SDC_STATUS_HILDATA) { mlc->ipacket[idx] |= data | HIL_ERR_INT; mlc->icount--; - if (hp_sdc_mlc_priv.got5x) goto check; - if (!idx) goto check; - if ((mlc->ipacket[idx-1] & HIL_PKT_ADDR_MASK) != + if (hp_sdc_mlc_priv.got5x || !idx) + goto check; + if ((mlc->ipacket[idx - 1] & HIL_PKT_ADDR_MASK) != (mlc->ipacket[idx] & HIL_PKT_ADDR_MASK)) { mlc->ipacket[idx] &= ~HIL_PKT_ADDR_MASK; - mlc->ipacket[idx] |= (mlc->ipacket[idx-1] - & HIL_PKT_ADDR_MASK); + mlc->ipacket[idx] |= (mlc->ipacket[idx - 1] + & HIL_PKT_ADDR_MASK); } goto check; } /* We know status is 5X */ - if (data & HP_SDC_HIL_ISERR) goto err; - mlc->ipacket[idx] = + if (data & HP_SDC_HIL_ISERR) + goto err; + mlc->ipacket[idx] = (data & HP_SDC_HIL_R1MASK) << HIL_PKT_ADDR_SHIFT; hp_sdc_mlc_priv.got5x = 1; goto out; check: hp_sdc_mlc_priv.got5x = 0; - if (mlc->imatch == 0) goto done; - if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) - && (mlc->ipacket[idx] == (mlc->imatch | idx))) goto done; - if (mlc->ipacket[idx] == mlc->imatch) goto done; + if (mlc->imatch == 0) + goto done; + if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) + && (mlc->ipacket[idx] == (mlc->imatch | idx))) + goto done; + if (mlc->ipacket[idx] == mlc->imatch) + goto done; goto out; - err: + err: printk(KERN_DEBUG PREFIX "err code %x\n", data); + switch (data) { case HP_SDC_HIL_RC_DONE: printk(KERN_WARNING PREFIX "Bastard SDC reconfigured loop!\n"); break; + case HP_SDC_HIL_ERR: - mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR | - HIL_ERR_FERR | HIL_ERR_FOF; + mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR | + HIL_ERR_FERR | HIL_ERR_FOF; break; + case HP_SDC_HIL_TO: mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_LERR; break; + case HP_SDC_HIL_RC: printk(KERN_WARNING PREFIX "Bastard SDC decided to reconfigure loop!\n"); break; + default: printk(KERN_WARNING PREFIX "Unkown HIL Error status (%x)!\n", data); break; } + /* No more data will be coming due to an error. */ done: tasklet_schedule(mlc->tasklet); - up(&(mlc->isem)); + up(&mlc->isem); out: - write_unlock(&(mlc->lock)); + write_unlock(&mlc->lock); } /******************** Tasklet or userspace context functions ****************/ -static int hp_sdc_mlc_in (hil_mlc *mlc, suseconds_t timeout) { - unsigned long flags; +static int hp_sdc_mlc_in(hil_mlc *mlc, suseconds_t timeout) +{ struct hp_sdc_mlc_priv_s *priv; int rc = 2; priv = mlc->priv; - write_lock_irqsave(&(mlc->lock), flags); - /* Try to down the semaphore */ - if (down_trylock(&(mlc->isem))) { + if (down_trylock(&mlc->isem)) { struct timeval tv; if (priv->emtestmode) { - mlc->ipacket[0] = - HIL_ERR_INT | (mlc->opacket & - (HIL_PKT_CMD | - HIL_PKT_ADDR_MASK | + mlc->ipacket[0] = + HIL_ERR_INT | (mlc->opacket & + (HIL_PKT_CMD | + HIL_PKT_ADDR_MASK | HIL_PKT_DATA_MASK)); mlc->icount = 14; /* printk(KERN_DEBUG PREFIX ">[%x]\n", mlc->ipacket[0]); */ goto wasup; } do_gettimeofday(&tv); - tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec); + tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec); if (tv.tv_usec - mlc->instart.tv_usec > mlc->intimeout) { - /* printk("!%i %i", - tv.tv_usec - mlc->instart.tv_usec, - mlc->intimeout); - */ + /* printk("!%i %i", + tv.tv_usec - mlc->instart.tv_usec, + mlc->intimeout); + */ rc = 1; - up(&(mlc->isem)); + up(&mlc->isem); } goto done; } wasup: - up(&(mlc->isem)); + up(&mlc->isem); rc = 0; - goto done; done: - write_unlock_irqrestore(&(mlc->lock), flags); return rc; } -static int hp_sdc_mlc_cts (hil_mlc *mlc) { +static int hp_sdc_mlc_cts(hil_mlc *mlc) +{ struct hp_sdc_mlc_priv_s *priv; - unsigned long flags; - priv = mlc->priv; - - write_lock_irqsave(&(mlc->lock), flags); + priv = mlc->priv; /* Try to down the semaphores -- they should be up. */ - if (down_trylock(&(mlc->isem))) { - BUG(); - goto busy; - } - if (down_trylock(&(mlc->osem))) { - BUG(); - up(&(mlc->isem)); - goto busy; - } - up(&(mlc->isem)); - up(&(mlc->osem)); + BUG_ON(down_trylock(&mlc->isem)); + BUG_ON(down_trylock(&mlc->osem)); + + up(&mlc->isem); + up(&mlc->osem); - if (down_trylock(&(mlc->csem))) { - if (priv->trans.act.semaphore != &(mlc->csem)) goto poll; - goto busy; + if (down_trylock(&mlc->csem)) { + if (priv->trans.act.semaphore != &mlc->csem) + goto poll; + else + goto busy; } - if (!(priv->tseq[4] & HP_SDC_USE_LOOP)) goto done; + + if (!(priv->tseq[4] & HP_SDC_USE_LOOP)) + goto done; poll: - priv->trans.act.semaphore = &(mlc->csem); + priv->trans.act.semaphore = &mlc->csem; priv->trans.actidx = 0; priv->trans.idx = 1; priv->trans.endidx = 5; - priv->tseq[0] = + priv->tseq[0] = HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE; priv->tseq[1] = HP_SDC_CMD_READ_USE; priv->tseq[2] = 1; priv->tseq[3] = 0; priv->tseq[4] = 0; - hp_sdc_enqueue_transaction(&(priv->trans)); + __hp_sdc_enqueue_transaction(&priv->trans); busy: - write_unlock_irqrestore(&(mlc->lock), flags); return 1; done: - priv->trans.act.semaphore = &(mlc->osem); - up(&(mlc->csem)); - write_unlock_irqrestore(&(mlc->lock), flags); + priv->trans.act.semaphore = &mlc->osem; + up(&mlc->csem); return 0; } -static void hp_sdc_mlc_out (hil_mlc *mlc) { +static void hp_sdc_mlc_out(hil_mlc *mlc) +{ struct hp_sdc_mlc_priv_s *priv; - unsigned long flags; priv = mlc->priv; - write_lock_irqsave(&(mlc->lock), flags); - /* Try to down the semaphore -- it should be up. */ - if (down_trylock(&(mlc->osem))) { - BUG(); - goto done; - } + BUG_ON(down_trylock(&mlc->osem)); - if (mlc->opacket & HIL_DO_ALTER_CTRL) goto do_control; + if (mlc->opacket & HIL_DO_ALTER_CTRL) + goto do_control; do_data: if (priv->emtestmode) { - up(&(mlc->osem)); - goto done; + up(&mlc->osem); + return; } /* Shouldn't be sending commands when loop may be busy */ - if (down_trylock(&(mlc->csem))) { - BUG(); - goto done; - } - up(&(mlc->csem)); + BUG_ON(down_trylock(&mlc->csem)); + up(&mlc->csem); priv->trans.actidx = 0; priv->trans.idx = 1; - priv->trans.act.semaphore = &(mlc->osem); + priv->trans.act.semaphore = &mlc->osem; priv->trans.endidx = 6; - priv->tseq[0] = + priv->tseq[0] = HP_SDC_ACT_DATAREG | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_SEMAPHORE; priv->tseq[1] = 0x7; - priv->tseq[2] = - (mlc->opacket & + priv->tseq[2] = + (mlc->opacket & (HIL_PKT_ADDR_MASK | HIL_PKT_CMD)) >> HIL_PKT_ADDR_SHIFT; - priv->tseq[3] = - (mlc->opacket & HIL_PKT_DATA_MASK) + priv->tseq[3] = + (mlc->opacket & HIL_PKT_DATA_MASK) >> HIL_PKT_DATA_SHIFT; priv->tseq[4] = 0; /* No timeout */ - if (priv->tseq[3] == HIL_CMD_DHR) priv->tseq[4] = 1; + if (priv->tseq[3] == HIL_CMD_DHR) + priv->tseq[4] = 1; priv->tseq[5] = HP_SDC_CMD_DO_HIL; goto enqueue; do_control: priv->emtestmode = mlc->opacket & HIL_CTRL_TEST; - + /* we cannot emulate this, it should not be used. */ BUG_ON((mlc->opacket & (HIL_CTRL_APE | HIL_CTRL_IPF)) == HIL_CTRL_APE); - - if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY) goto control_only; - if (mlc->opacket & HIL_CTRL_APE) { - BUG(); /* Should not send command/data after engaging APE */ - goto done; - } - /* Disengaging APE this way would not be valid either since + + if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY) + goto control_only; + + /* Should not send command/data after engaging APE */ + BUG_ON(mlc->opacket & HIL_CTRL_APE); + + /* Disengaging APE this way would not be valid either since * the loop must be allowed to idle. * - * So, it works out that we really never actually send control - * and data when using SDC, we just send the data. + * So, it works out that we really never actually send control + * and data when using SDC, we just send the data. */ goto do_data; control_only: priv->trans.actidx = 0; priv->trans.idx = 1; - priv->trans.act.semaphore = &(mlc->osem); + priv->trans.act.semaphore = &mlc->osem; priv->trans.endidx = 4; - priv->tseq[0] = + priv->tseq[0] = HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE; priv->tseq[1] = HP_SDC_CMD_SET_LPC; priv->tseq[2] = 1; - // priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC; + /* priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC; */ priv->tseq[3] = 0; if (mlc->opacket & HIL_CTRL_APE) { priv->tseq[3] |= HP_SDC_LPC_APE_IPF; - down_trylock(&(mlc->csem)); - } + down_trylock(&mlc->csem); + } enqueue: - hp_sdc_enqueue_transaction(&(priv->trans)); - done: - write_unlock_irqrestore(&(mlc->lock), flags); + hp_sdc_enqueue_transaction(&priv->trans); } static int __init hp_sdc_mlc_init(void) @@ -316,18 +310,18 @@ static int __init hp_sdc_mlc_init(void) hp_sdc_mlc_priv.emtestmode = 0; hp_sdc_mlc_priv.trans.seq = hp_sdc_mlc_priv.tseq; - hp_sdc_mlc_priv.trans.act.semaphore = &(mlc->osem); + hp_sdc_mlc_priv.trans.act.semaphore = &mlc->osem; hp_sdc_mlc_priv.got5x = 0; - mlc->cts = &hp_sdc_mlc_cts; - mlc->in = &hp_sdc_mlc_in; - mlc->out = &hp_sdc_mlc_out; + mlc->cts = &hp_sdc_mlc_cts; + mlc->in = &hp_sdc_mlc_in; + mlc->out = &hp_sdc_mlc_out; + mlc->priv = &hp_sdc_mlc_priv; if (hil_mlc_register(mlc)) { printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n"); goto err0; } - mlc->priv = &hp_sdc_mlc_priv; if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) { printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n"); @@ -335,10 +329,9 @@ static int __init hp_sdc_mlc_init(void) } return 0; err1: - if (hil_mlc_unregister(mlc)) { + if (hil_mlc_unregister(mlc)) printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n" "This is bad. Could cause an oops.\n"); - } err0: return -EBUSY; } @@ -346,14 +339,14 @@ static int __init hp_sdc_mlc_init(void) static void __exit hp_sdc_mlc_exit(void) { hil_mlc *mlc = &hp_sdc_mlc; - if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr)) { + + if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr)) printk(KERN_ERR PREFIX "Failed to release the raw HIL ISR hook.\n" "This is bad. Could cause an oops.\n"); - } - if (hil_mlc_unregister(mlc)) { + + if (hil_mlc_unregister(mlc)) printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n" "This is bad. Could cause an oops.\n"); - } } module_init(hp_sdc_mlc_init); diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index d36bd54..6858bc5 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -160,6 +160,28 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { }, }, { + /* + * No data is coming from the touchscreen unless KBC + * is in legacy mode. + */ + .ident = "Panasonic CF-29", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"), + DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"), + }, + }, + { + /* + * Errors on MUX ports are reported without raising AUXDATA + * causing "spurious NAK" messages. + */ + .ident = "HP Pavilion DV4017EA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EA032EA#ABF)"), + }, + }, + { .ident = "Toshiba P10", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), @@ -280,6 +302,8 @@ static struct pnp_driver i8042_pnp_kbd_driver = { }; static struct pnp_device_id pnp_aux_devids[] = { + { .id = "FJC6000", .driver_data = 0 }, + { .id = "FJC6001", .driver_data = 0 }, { .id = "PNP0f03", .driver_data = 0 }, { .id = "PNP0f0b", .driver_data = 0 }, { .id = "PNP0f0e", .driver_data = 0 }, diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index db9cca3..7c17377 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -768,6 +768,13 @@ static void i8042_controller_reset(void) i8042_flush(); /* + * Disable both KBD and AUX interfaces so they don't get in the way + */ + + i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; + i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); + +/* * Disable MUX mode if present. */ diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 0a26e06..693e3b2 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -39,7 +39,8 @@ /* * This code has been heavily tested on a Nokia 770, and lightly * tested on other ads7846 devices (OSK/Mistral, Lubbock). - * Support for ads7843 and ads7845 has only been stubbed in. + * Support for ads7843 tested on Atmel at91sam926x-EK. + * Support for ads7845 has only been stubbed in. * * IRQ handling needs a workaround because of a shortcoming in handling * edge triggered IRQs on some platforms like the OMAP1/2. These @@ -246,18 +247,16 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) /* REVISIT: take a few more samples, and compare ... */ - /* maybe off internal vREF */ - if (use_internal) { - req->ref_off = REF_OFF; - req->xfer[4].tx_buf = &req->ref_off; - req->xfer[4].len = 1; - spi_message_add_tail(&req->xfer[4], &req->msg); - - req->xfer[5].rx_buf = &req->scratch; - req->xfer[5].len = 2; - CS_CHANGE(req->xfer[5]); - spi_message_add_tail(&req->xfer[5], &req->msg); - } + /* converter in low power mode & enable PENIRQ */ + req->ref_off = PWRDOWN; + req->xfer[4].tx_buf = &req->ref_off; + req->xfer[4].len = 1; + spi_message_add_tail(&req->xfer[4], &req->msg); + + req->xfer[5].rx_buf = &req->scratch; + req->xfer[5].len = 2; + CS_CHANGE(req->xfer[5]); + spi_message_add_tail(&req->xfer[5], &req->msg); ts->irq_disabled = 1; disable_irq(spi->irq); @@ -536,6 +535,9 @@ static void ads7846_rx(void *ads) } else Rt = 0; + if (ts->model == 7843) + Rt = ts->pressure_max / 2; + /* Sample found inconsistent by debouncing or pressure is beyond * the maximum. Don't report it to user space, repeat at least * once more the measurement @@ -897,7 +899,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) input_dev->name = "ADS784x Touchscreen"; input_dev->phys = ts->phys; - input_dev->cdev.dev = &spi->dev; + input_dev->dev.parent = &spi->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c index e294558..e6a31d1 100644 --- a/drivers/input/touchscreen/corgi_ts.c +++ b/drivers/input/touchscreen/corgi_ts.c @@ -300,8 +300,7 @@ static int __init corgits_probe(struct platform_device *pdev) input_dev->id.vendor = 0x0001; input_dev->id.product = 0x0002; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &pdev->dev; - input_dev->private = corgi_ts; + input_dev->dev.parent = &pdev->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index 9d61cd1..557d781 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c @@ -312,14 +312,13 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) init_completion(&elo->cmd_done); snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys); - input_dev->private = elo; input_dev->name = "Elo Serial TouchScreen"; input_dev->phys = elo->phys; input_dev->id.bustype = BUS_RS232; input_dev->id.vendor = SERIO_ELO; input_dev->id.product = elo->id; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &serio->dev; + input_dev->dev.parent = &serio->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c index 9157eb1..39d6026 100644 --- a/drivers/input/touchscreen/gunze.c +++ b/drivers/input/touchscreen/gunze.c @@ -130,13 +130,13 @@ static int gunze_connect(struct serio *serio, struct serio_driver *drv) gunze->dev = input_dev; snprintf(gunze->phys, sizeof(serio->phys), "%s/input0", serio->phys); - input_dev->private = gunze; input_dev->name = "Gunze AHL-51S TouchScreen"; input_dev->phys = gunze->phys; input_dev->id.bustype = BUS_RS232; input_dev->id.vendor = SERIO_GUNZE; input_dev->id.product = 0x0051; input_dev->id.version = 0x0100; + input_dev->dev.parent = &serio->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); input_set_abs_params(input_dev, ABS_X, 24, 1000, 0, 0); diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index c4116d4..09ed780 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c @@ -147,7 +147,7 @@ enum flite_pwr { unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr) { unsigned char brightness = (pwr == FLITE_PWR_OFF) ? 0 : flite_brightness; - struct h3600_dev *ts = dev->private; + struct h3600_dev *ts = input_get_drvdata(dev); /* Must be in this order */ ts->serio->write(ts->serio, 1); @@ -260,7 +260,7 @@ static int h3600ts_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { #if 0 - struct h3600_dev *ts = dev->private; + struct h3600_dev *ts = input_get_drvdata(dev); switch (type) { case EV_LED: { @@ -367,8 +367,9 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) input_dev->id.vendor = SERIO_H3600; input_dev->id.product = 0x0666; /* FIXME !!! We can ask the hardware */ input_dev->id.version = 0x0100; - input_dev->cdev.dev = &serio->dev; - input_dev->private = ts; + input_dev->dev.parent = &serio->dev; + + input_set_drvdata(input_dev, ts); input_dev->event = h3600ts_event; diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c index c3c2d73..4ec3b1f 100644 --- a/drivers/input/touchscreen/mtouch.c +++ b/drivers/input/touchscreen/mtouch.c @@ -144,13 +144,13 @@ static int mtouch_connect(struct serio *serio, struct serio_driver *drv) mtouch->dev = input_dev; snprintf(mtouch->phys, sizeof(mtouch->phys), "%s/input0", serio->phys); - input_dev->private = mtouch; input_dev->name = "MicroTouch Serial TouchScreen"; input_dev->phys = mtouch->phys; input_dev->id.bustype = BUS_RS232; input_dev->id.vendor = SERIO_MICROTOUCH; input_dev->id.product = 0; input_dev->id.version = 0x0100; + input_dev->dev.parent = &serio->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); input_set_abs_params(mtouch->dev, ABS_X, MTOUCH_MIN_XC, MTOUCH_MAX_XC, 0, 0); diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c index bd27679..f2c0d3c 100644 --- a/drivers/input/touchscreen/penmount.c +++ b/drivers/input/touchscreen/penmount.c @@ -105,14 +105,13 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv) pm->dev = input_dev; snprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys); - input_dev->private = pm; input_dev->name = "Penmount Serial TouchScreen"; input_dev->phys = pm->phys; input_dev->id.bustype = BUS_RS232; input_dev->id.vendor = SERIO_PENMOUNT; input_dev->id.product = 0; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &serio->dev; + input_dev->dev.parent = &serio->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); diff --git a/drivers/input/touchscreen/touchright.c b/drivers/input/touchscreen/touchright.c index 35ba46c..3def7bb 100644 --- a/drivers/input/touchscreen/touchright.c +++ b/drivers/input/touchscreen/touchright.c @@ -118,13 +118,13 @@ static int tr_connect(struct serio *serio, struct serio_driver *drv) tr->dev = input_dev; snprintf(tr->phys, sizeof(tr->phys), "%s/input0", serio->phys); - input_dev->private = tr; input_dev->name = "Touchright Serial TouchScreen"; input_dev->phys = tr->phys; input_dev->id.bustype = BUS_RS232; input_dev->id.vendor = SERIO_TOUCHRIGHT; input_dev->id.product = 0; input_dev->id.version = 0x0100; + input_dev->dev.parent = &serio->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); input_set_abs_params(tr->dev, ABS_X, TR_MIN_XC, TR_MAX_XC, 0, 0); diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c index 4dc073d..ac4bdcf 100644 --- a/drivers/input/touchscreen/touchwin.c +++ b/drivers/input/touchscreen/touchwin.c @@ -125,13 +125,13 @@ static int tw_connect(struct serio *serio, struct serio_driver *drv) tw->dev = input_dev; snprintf(tw->phys, sizeof(tw->phys), "%s/input0", serio->phys); - input_dev->private = tw; input_dev->name = "Touchwindow Serial TouchScreen"; input_dev->phys = tw->phys; input_dev->id.bustype = BUS_RS232; input_dev->id.vendor = SERIO_TOUCHWIN; input_dev->id.product = 0; input_dev->id.version = 0x0100; + input_dev->dev.parent = &serio->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); input_set_abs_params(tw->dev, ABS_X, TW_MIN_XC, TW_MAX_XC, 0, 0); diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index e8606c4..6582816 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c @@ -97,6 +97,8 @@ struct ucb1400 { }; static int adcsync; +static int ts_delay = 55; /* us */ +static int ts_delay_pressure; /* us */ static inline u16 ucb1400_reg_read(struct ucb1400 *ucb, u16 reg) { @@ -159,6 +161,7 @@ static inline unsigned int ucb1400_ts_read_pressure(struct ucb1400 *ucb) UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + udelay(ts_delay_pressure); return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY); } @@ -180,7 +183,7 @@ static inline unsigned int ucb1400_ts_read_xpos(struct ucb1400 *ucb) UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); - udelay(55); + udelay(ts_delay); return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY); } @@ -203,7 +206,7 @@ static inline unsigned int ucb1400_ts_read_ypos(struct ucb1400 *ucb) UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); - udelay(55); + udelay(ts_delay); return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPX); } @@ -369,7 +372,7 @@ static irqreturn_t ucb1400_hard_irq(int irqnr, void *devid) static int ucb1400_ts_open(struct input_dev *idev) { - struct ucb1400 *ucb = idev->private; + struct ucb1400 *ucb = input_get_drvdata(idev); int ret = 0; BUG_ON(ucb->ts_task); @@ -385,7 +388,7 @@ static int ucb1400_ts_open(struct input_dev *idev) static void ucb1400_ts_close(struct input_dev *idev) { - struct ucb1400 *ucb = idev->private; + struct ucb1400 *ucb = input_get_drvdata(idev); if (ucb->ts_task) kthread_stop(ucb->ts_task); @@ -507,8 +510,9 @@ static int ucb1400_ts_probe(struct device *dev) } printk(KERN_DEBUG "UCB1400: found IRQ %d\n", ucb->irq); - idev->private = ucb; - idev->cdev.dev = dev; + input_set_drvdata(idev, ucb); + + idev->dev.parent = dev; idev->name = "UCB1400 touchscreen interface"; idev->id.vendor = ucb1400_reg_read(ucb, AC97_VENDOR_ID1); idev->id.product = id; @@ -571,7 +575,15 @@ static void __exit ucb1400_ts_exit(void) driver_unregister(&ucb1400_ts_driver); } -module_param(adcsync, int, 0444); +module_param(adcsync, bool, 0444); +MODULE_PARM_DESC(adcsync, "Synchronize touch readings with ADCSYNC pin."); + +module_param(ts_delay, int, 0444); +MODULE_PARM_DESC(ts_delay, "Delay between panel setup and position read. Default = 55us."); + +module_param(ts_delay_pressure, int, 0444); +MODULE_PARM_DESC(ts_delay_pressure, + "delay between panel setup and pressure read. Default = 0us."); module_init(ucb1400_ts_init); module_exit(ucb1400_ts_exit); diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c index 05dfc10..5e5b5c9 100644 --- a/drivers/input/tsdev.c +++ b/drivers/input/tsdev.c @@ -111,13 +111,13 @@ struct tsdev { int minor; char name[8]; wait_queue_head_t wait; - struct list_head list; + struct list_head client_list; struct input_handle handle; int x, y, pressure; struct ts_calibration cal; }; -struct tsdev_list { +struct tsdev_client { struct fasync_struct *fasync; struct list_head node; struct tsdev *tsdev; @@ -139,38 +139,49 @@ static struct tsdev *tsdev_table[TSDEV_MINORS/2]; static int tsdev_fasync(int fd, struct file *file, int on) { - struct tsdev_list *list = file->private_data; + struct tsdev_client *client = file->private_data; int retval; - retval = fasync_helper(fd, file, on, &list->fasync); + retval = fasync_helper(fd, file, on, &client->fasync); return retval < 0 ? retval : 0; } static int tsdev_open(struct inode *inode, struct file *file) { int i = iminor(inode) - TSDEV_MINOR_BASE; - struct tsdev_list *list; + struct tsdev_client *client; + struct tsdev *tsdev; + int error; printk(KERN_WARNING "tsdev (compaq touchscreen emulation) is scheduled " "for removal.\nSee Documentation/feature-removal-schedule.txt " "for details.\n"); - if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK]) + if (i >= TSDEV_MINORS) + return -ENODEV; + + tsdev = tsdev_table[i & TSDEV_MINOR_MASK]; + if (!tsdev || !tsdev->exist) return -ENODEV; - if (!(list = kzalloc(sizeof(struct tsdev_list), GFP_KERNEL))) + client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL); + if (!client) return -ENOMEM; - list->raw = (i >= TSDEV_MINORS/2) ? 1 : 0; + client->tsdev = tsdev; + client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0; + list_add_tail(&client->node, &tsdev->client_list); - i &= TSDEV_MINOR_MASK; - list->tsdev = tsdev_table[i]; - list_add_tail(&list->node, &tsdev_table[i]->list); - file->private_data = list; + if (!tsdev->open++ && tsdev->exist) { + error = input_open_device(&tsdev->handle); + if (error) { + list_del(&client->node); + kfree(client); + return error; + } + } - if (!list->tsdev->open++) - if (list->tsdev->exist) - input_open_device(&list->tsdev->handle); + file->private_data = client; return 0; } @@ -182,45 +193,48 @@ static void tsdev_free(struct tsdev *tsdev) static int tsdev_release(struct inode *inode, struct file *file) { - struct tsdev_list *list = file->private_data; + struct tsdev_client *client = file->private_data; + struct tsdev *tsdev = client->tsdev; tsdev_fasync(-1, file, 0); - list_del(&list->node); - if (!--list->tsdev->open) { - if (list->tsdev->exist) - input_close_device(&list->tsdev->handle); + list_del(&client->node); + kfree(client); + + if (!--tsdev->open) { + if (tsdev->exist) + input_close_device(&tsdev->handle); else - tsdev_free(list->tsdev); + tsdev_free(tsdev); } - kfree(list); + return 0; } static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count, - loff_t * ppos) + loff_t *ppos) { - struct tsdev_list *list = file->private_data; + struct tsdev_client *client = file->private_data; + struct tsdev *tsdev = client->tsdev; int retval = 0; - if (list->head == list->tail && list->tsdev->exist && (file->f_flags & O_NONBLOCK)) + if (client->head == client->tail && tsdev->exist && (file->f_flags & O_NONBLOCK)) return -EAGAIN; - retval = wait_event_interruptible(list->tsdev->wait, - list->head != list->tail || !list->tsdev->exist); - + retval = wait_event_interruptible(tsdev->wait, + client->head != client->tail || !tsdev->exist); if (retval) return retval; - if (!list->tsdev->exist) + if (!tsdev->exist) return -ENODEV; - while (list->head != list->tail && + while (client->head != client->tail && retval + sizeof (struct ts_event) <= count) { - if (copy_to_user (buffer + retval, list->event + list->tail, + if (copy_to_user (buffer + retval, client->event + client->tail, sizeof (struct ts_event))) return -EFAULT; - list->tail = (list->tail + 1) & (TSDEV_BUFFER_SIZE - 1); + client->tail = (client->tail + 1) & (TSDEV_BUFFER_SIZE - 1); retval += sizeof (struct ts_event); } @@ -228,32 +242,33 @@ static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count, } /* No kernel lock - fine */ -static unsigned int tsdev_poll(struct file *file, poll_table * wait) +static unsigned int tsdev_poll(struct file *file, poll_table *wait) { - struct tsdev_list *list = file->private_data; + struct tsdev_client *client = file->private_data; + struct tsdev *tsdev = client->tsdev; - poll_wait(file, &list->tsdev->wait, wait); - return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) | - (list->tsdev->exist ? 0 : (POLLHUP | POLLERR)); + poll_wait(file, &tsdev->wait, wait); + return ((client->head == client->tail) ? 0 : (POLLIN | POLLRDNORM)) | + (tsdev->exist ? 0 : (POLLHUP | POLLERR)); } static int tsdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - struct tsdev_list *list = file->private_data; - struct tsdev *tsdev = list->tsdev; + struct tsdev_client *client = file->private_data; + struct tsdev *tsdev = client->tsdev; int retval = 0; switch (cmd) { case TS_GET_CAL: - if (copy_to_user ((void __user *)arg, &tsdev->cal, - sizeof (struct ts_calibration))) + if (copy_to_user((void __user *)arg, &tsdev->cal, + sizeof (struct ts_calibration))) retval = -EFAULT; break; case TS_SET_CAL: - if (copy_from_user (&tsdev->cal, (void __user *)arg, - sizeof (struct ts_calibration))) + if (copy_from_user(&tsdev->cal, (void __user *)arg, + sizeof (struct ts_calibration))) retval = -EFAULT; break; @@ -279,7 +294,7 @@ static void tsdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) { struct tsdev *tsdev = handle->private; - struct tsdev_list *list; + struct tsdev_client *client; struct timeval time; switch (type) { @@ -343,18 +358,18 @@ static void tsdev_event(struct input_handle *handle, unsigned int type, if (type != EV_SYN || code != SYN_REPORT) return; - list_for_each_entry(list, &tsdev->list, node) { + list_for_each_entry(client, &tsdev->client_list, node) { int x, y, tmp; do_gettimeofday(&time); - list->event[list->head].millisecs = time.tv_usec / 100; - list->event[list->head].pressure = tsdev->pressure; + client->event[client->head].millisecs = time.tv_usec / 100; + client->event[client->head].pressure = tsdev->pressure; x = tsdev->x; y = tsdev->y; /* Calibration */ - if (!list->raw) { + if (!client->raw) { x = ((x * tsdev->cal.xscale) >> 8) + tsdev->cal.xtrans; y = ((y * tsdev->cal.yscale) >> 8) + tsdev->cal.ytrans; if (tsdev->cal.xyswap) { @@ -362,33 +377,35 @@ static void tsdev_event(struct input_handle *handle, unsigned int type, } } - list->event[list->head].x = x; - list->event[list->head].y = y; - list->head = (list->head + 1) & (TSDEV_BUFFER_SIZE - 1); - kill_fasync(&list->fasync, SIGIO, POLL_IN); + client->event[client->head].x = x; + client->event[client->head].y = y; + client->head = (client->head + 1) & (TSDEV_BUFFER_SIZE - 1); + kill_fasync(&client->fasync, SIGIO, POLL_IN); } wake_up_interruptible(&tsdev->wait); } -static struct input_handle *tsdev_connect(struct input_handler *handler, - struct input_dev *dev, - const struct input_device_id *id) +static int tsdev_connect(struct input_handler *handler, struct input_dev *dev, + const struct input_device_id *id) { struct tsdev *tsdev; struct class_device *cdev; + dev_t devt; int minor, delta; + int error; for (minor = 0; minor < TSDEV_MINORS / 2 && tsdev_table[minor]; minor++); if (minor >= TSDEV_MINORS / 2) { printk(KERN_ERR "tsdev: You have way too many touchscreens\n"); - return NULL; + return -ENFILE; } - if (!(tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL))) - return NULL; + tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL); + if (!tsdev) + return -ENOMEM; - INIT_LIST_HEAD(&tsdev->list); + INIT_LIST_HEAD(&tsdev->client_list); init_waitqueue_head(&tsdev->wait); sprintf(tsdev->name, "ts%d", minor); @@ -415,21 +432,43 @@ static struct input_handle *tsdev_connect(struct input_handler *handler, tsdev_table[minor] = tsdev; - cdev = class_device_create(&input_class, &dev->cdev, - MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor), - dev->cdev.dev, tsdev->name); + devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor), + + cdev = class_device_create(&input_class, &dev->cdev, devt, + dev->cdev.dev, tsdev->name); + if (IS_ERR(cdev)) { + error = PTR_ERR(cdev); + goto err_free_tsdev; + } /* temporary symlink to keep userspace happy */ - sysfs_create_link(&input_class.subsys.kobj, &cdev->kobj, - tsdev->name); + error = sysfs_create_link(&input_class.subsys.kobj, + &cdev->kobj, tsdev->name); + if (error) + goto err_cdev_destroy; + + error = input_register_handle(&tsdev->handle); + if (error) + goto err_remove_link; + + return 0; - return &tsdev->handle; + err_remove_link: + sysfs_remove_link(&input_class.subsys.kobj, tsdev->name); + err_cdev_destroy: + class_device_destroy(&input_class, devt); + err_free_tsdev: + tsdev_table[minor] = NULL; + kfree(tsdev); + return error; } static void tsdev_disconnect(struct input_handle *handle) { struct tsdev *tsdev = handle->private; - struct tsdev_list *list; + struct tsdev_client *client; + + input_unregister_handle(handle); sysfs_remove_link(&input_class.subsys.kobj, tsdev->name); class_device_destroy(&input_class, @@ -439,8 +478,8 @@ static void tsdev_disconnect(struct input_handle *handle) if (tsdev->open) { input_close_device(handle); wake_up_interruptible(&tsdev->wait); - list_for_each_entry(list, &tsdev->list, node) - kill_fasync(&list->fasync, SIGIO, POLL_HUP); + list_for_each_entry(client, &tsdev->client_list, node) + kill_fasync(&client->fasync, SIGIO, POLL_HUP); } else tsdev_free(tsdev); } diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile index 9bf420e..284a073 100644 --- a/drivers/usb/input/Makefile +++ b/drivers/usb/input/Makefile @@ -10,9 +10,6 @@ obj-$(CONFIG_USB_ATI_REMOTE) += ati_remote.o obj-$(CONFIG_USB_ATI_REMOTE2) += ati_remote2.o obj-$(CONFIG_USB_KBTAB) += kbtab.o obj-$(CONFIG_USB_KEYSPAN_REMOTE) += keyspan_remote.o -obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o -obj-$(CONFIG_USB_ITMTOUCH) += itmtouch.o -obj-$(CONFIG_USB_EGALAX) += touchkitusb.o obj-$(CONFIG_USB_TOUCHSCREEN) += usbtouchscreen.o obj-$(CONFIG_USB_POWERMATE) += powermate.o obj-$(CONFIG_USB_WACOM) += wacom.o @@ -20,7 +17,7 @@ obj-$(CONFIG_USB_ACECAD) += acecad.o obj-$(CONFIG_USB_YEALINK) += yealink.o obj-$(CONFIG_USB_XPAD) += xpad.o obj-$(CONFIG_USB_APPLETOUCH) += appletouch.o -obj-$(CONFIG_USB_GTCO) += gtco.o +obj-$(CONFIG_USB_GTCO) += gtco.o ifeq ($(CONFIG_USB_DEBUG),y) EXTRA_CFLAGS += -DDEBUG diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c index 909138e..be8e924 100644 --- a/drivers/usb/input/acecad.c +++ b/drivers/usb/input/acecad.c @@ -111,7 +111,7 @@ resubmit: static int usb_acecad_open(struct input_dev *dev) { - struct usb_acecad *acecad = dev->private; + struct usb_acecad *acecad = input_get_drvdata(dev); acecad->irq->dev = acecad->usbdev; if (usb_submit_urb(acecad->irq, GFP_KERNEL)) @@ -122,7 +122,7 @@ static int usb_acecad_open(struct input_dev *dev) static void usb_acecad_close(struct input_dev *dev) { - struct usb_acecad *acecad = dev->private; + struct usb_acecad *acecad = input_get_drvdata(dev); usb_kill_urb(acecad->irq); } @@ -135,6 +135,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ struct usb_acecad *acecad; struct input_dev *input_dev; int pipe, maxp; + int err = -ENOMEM; if (interface->desc.bNumEndpoints != 1) return -ENODEV; @@ -149,16 +150,22 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL); input_dev = input_allocate_device(); - if (!acecad || !input_dev) + if (!acecad || !input_dev) { + err = -ENOMEM; goto fail1; + } acecad->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &acecad->data_dma); - if (!acecad->data) + if (!acecad->data) { + err= -ENOMEM; goto fail1; + } acecad->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!acecad->irq) + if (!acecad->irq) { + err = -ENOMEM; goto fail2; + } acecad->usbdev = dev; acecad->input = input_dev; @@ -178,8 +185,9 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ input_dev->name = acecad->name; input_dev->phys = acecad->phys; usb_to_input_id(dev, &input_dev->id); - input_dev->cdev.dev = &intf->dev; - input_dev->private = acecad; + input_dev->dev.parent = &intf->dev; + + input_set_drvdata(input_dev, acecad); input_dev->open = usb_acecad_open; input_dev->close = usb_acecad_close; @@ -221,7 +229,9 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ acecad->irq->transfer_dma = acecad->data_dma; acecad->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - input_register_device(acecad->input); + err = input_register_device(acecad->input); + if (err) + goto fail2; usb_set_intfdata(intf, acecad); @@ -230,7 +240,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ fail2: usb_buffer_free(dev, 8, acecad->data, acecad->data_dma); fail1: input_free_device(input_dev); kfree(acecad); - return -ENOMEM; + return err; } static void usb_acecad_disconnect(struct usb_interface *intf) diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c index f857935..cc0a498 100644 --- a/drivers/usb/input/aiptek.c +++ b/drivers/usb/input/aiptek.c @@ -798,7 +798,7 @@ MODULE_DEVICE_TABLE(usb, aiptek_ids); */ static int aiptek_open(struct input_dev *inputdev) { - struct aiptek *aiptek = inputdev->private; + struct aiptek *aiptek = input_get_drvdata(inputdev); aiptek->urb->dev = aiptek->usbdev; if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0) @@ -812,7 +812,7 @@ static int aiptek_open(struct input_dev *inputdev) */ static void aiptek_close(struct input_dev *inputdev) { - struct aiptek *aiptek = inputdev->private; + struct aiptek *aiptek = input_get_drvdata(inputdev); usb_kill_urb(aiptek->urb); } @@ -1972,6 +1972,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) AIPTEK_PROGRAMMABLE_DELAY_200, AIPTEK_PROGRAMMABLE_DELAY_300 }; + int err = -ENOMEM; /* programmableDelay is where the command-line specified * delay is kept. We make it the first element of speeds[], @@ -2043,8 +2044,10 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) inputdev->name = "Aiptek"; inputdev->phys = aiptek->features.usbPath; usb_to_input_id(usbdev, &inputdev->id); - inputdev->cdev.dev = &intf->dev; - inputdev->private = aiptek; + inputdev->dev.parent = &intf->dev; + + input_set_drvdata(inputdev, aiptek); + inputdev->open = aiptek_open; inputdev->close = aiptek_close; @@ -2133,7 +2136,9 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) /* Register the tablet as an Input Device */ - input_register_device(aiptek->inputdev); + err = input_register_device(aiptek->inputdev); + if (err) + goto fail2; /* We now will look for the evdev device which is mapped to * the tablet. The partial name is kept in the link list of @@ -2165,23 +2170,13 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) return 0; -fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data, + fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data, aiptek->data_dma); -fail1: input_free_device(inputdev); + fail1: input_free_device(inputdev); kfree(aiptek); - return -ENOMEM; + return err; } -/* Forward declaration */ -static void aiptek_disconnect(struct usb_interface *intf); - -static struct usb_driver aiptek_driver = { - .name = "aiptek", - .probe = aiptek_probe, - .disconnect = aiptek_disconnect, - .id_table = aiptek_ids, -}; - /*********************************************************************** * Deal with tablet disconnecting from the system. */ @@ -2206,6 +2201,13 @@ static void aiptek_disconnect(struct usb_interface *intf) } } +static struct usb_driver aiptek_driver = { + .name = "aiptek", + .probe = aiptek_probe, + .disconnect = aiptek_disconnect, + .id_table = aiptek_ids, +}; + static int __init aiptek_init(void) { int result = usb_register(&aiptek_driver); diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c index c77291d..e321526 100644 --- a/drivers/usb/input/appletouch.c +++ b/drivers/usb/input/appletouch.c @@ -466,7 +466,7 @@ exit: static int atp_open(struct input_dev *input) { - struct atp *dev = input->private; + struct atp *dev = input_get_drvdata(input); if (usb_submit_urb(dev->urb, GFP_ATOMIC)) return -EIO; @@ -477,7 +477,7 @@ static int atp_open(struct input_dev *input) static void atp_close(struct input_dev *input) { - struct atp *dev = input->private; + struct atp *dev = input_get_drvdata(input); usb_kill_urb(dev->urb); dev->open = 0; @@ -491,8 +491,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; int int_in_endpointAddr = 0; - int i, retval = -ENOMEM; - + int i, error = -ENOMEM; /* set up the endpoint information */ /* use only the first interrupt-in endpoint */ @@ -567,17 +566,13 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id } dev->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->urb) { - retval = -ENOMEM; + if (!dev->urb) goto err_free_devs; - } dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL, &dev->urb->transfer_dma); - if (!dev->data) { - retval = -ENOMEM; + if (!dev->data) goto err_free_urb; - } usb_fill_int_urb(dev->urb, udev, usb_rcvintpipe(udev, int_in_endpointAddr), @@ -589,9 +584,10 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id input_dev->name = "appletouch"; input_dev->phys = dev->phys; usb_to_input_id(dev->udev, &input_dev->id); - input_dev->cdev.dev = &iface->dev; + input_dev->dev.parent = &iface->dev; + + input_set_drvdata(input_dev, dev); - input_dev->private = dev; input_dev->open = atp_open; input_dev->close = atp_close; @@ -633,20 +629,25 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); set_bit(BTN_LEFT, input_dev->keybit); - input_register_device(dev->input); + error = input_register_device(dev->input); + if (error) + goto err_free_buffer; /* save our data pointer in this interface device */ usb_set_intfdata(iface, dev); return 0; + err_free_buffer: + usb_buffer_free(dev->udev, dev->datalen, + dev->data, dev->urb->transfer_dma); err_free_urb: usb_free_urb(dev->urb); err_free_devs: usb_set_intfdata(iface, NULL); kfree(dev); input_free_device(input_dev); - return retval; + return error; } static void atp_disconnect(struct usb_interface *iface) diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index b724e36..471aab2 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c @@ -120,6 +120,7 @@ * behaviour. */ #define FILTER_TIME 60 /* msec */ +#define REPEAT_DELAY 500 /* msec */ static unsigned long channel_mask; module_param(channel_mask, ulong, 0644); @@ -133,6 +134,10 @@ 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) @@ -174,6 +179,8 @@ struct ati_remote { 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]; @@ -318,7 +325,7 @@ static void ati_remote_dump(unsigned char *data, unsigned int len) */ static int ati_remote_open(struct input_dev *inputdev) { - struct ati_remote *ati_remote = inputdev->private; + 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; @@ -336,7 +343,7 @@ static int ati_remote_open(struct input_dev *inputdev) */ static void ati_remote_close(struct input_dev *inputdev) { - struct ati_remote *ati_remote = inputdev->private; + struct ati_remote *ati_remote = input_get_drvdata(inputdev); usb_kill_urb(ati_remote->irq_urb); } @@ -501,21 +508,31 @@ static void ati_remote_input_report(struct urb *urb) } 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(jiffies, ati_remote->old_jiffies + msecs_to_jiffies(repeat_filter))) { + 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 = jiffies; + 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) + (ati_remote->repeat_count < 5 || + time_before(now, ati_remote->first_jiffies + + msecs_to_jiffies(repeat_delay)))) return; @@ -653,7 +670,8 @@ static void ati_remote_input_init(struct ati_remote *ati_remote) if (ati_remote_tbl[i].type == EV_KEY) set_bit(ati_remote_tbl[i].code, idev->keybit); - idev->private = ati_remote; + input_set_drvdata(idev, ati_remote); + idev->open = ati_remote_open; idev->close = ati_remote_close; @@ -661,7 +679,7 @@ static void ati_remote_input_init(struct ati_remote *ati_remote) idev->phys = ati_remote->phys; usb_to_input_id(ati_remote->udev, &idev->id); - idev->cdev.dev = &ati_remote->udev->dev; + idev->dev.parent = &ati_remote->udev->dev; } static int ati_remote_initialize(struct ati_remote *ati_remote) @@ -772,15 +790,17 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de goto fail3; /* Set up and register input device */ - input_register_device(ati_remote->idev); + 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); + 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); + fail2: ati_remote_free_buffers(ati_remote); + fail1: input_free_device(input_dev); kfree(ati_remote); return err; } diff --git a/drivers/usb/input/ati_remote2.c b/drivers/usb/input/ati_remote2.c index 6459be9..a9032aa 100644 --- a/drivers/usb/input/ati_remote2.c +++ b/drivers/usb/input/ati_remote2.c @@ -131,7 +131,7 @@ static struct usb_driver ati_remote2_driver = { static int ati_remote2_open(struct input_dev *idev) { - struct ati_remote2 *ar2 = idev->private; + struct ati_remote2 *ar2 = input_get_drvdata(idev); int r; r = usb_submit_urb(ar2->urb[0], GFP_KERNEL); @@ -153,7 +153,7 @@ static int ati_remote2_open(struct input_dev *idev) static void ati_remote2_close(struct input_dev *idev) { - struct ati_remote2 *ar2 = idev->private; + struct ati_remote2 *ar2 = input_get_drvdata(idev); usb_kill_urb(ar2->urb[0]); usb_kill_urb(ar2->urb[1]); @@ -337,14 +337,14 @@ static void ati_remote2_complete_key(struct urb *urb) static int ati_remote2_input_init(struct ati_remote2 *ar2) { struct input_dev *idev; - int i; + int i, retval; idev = input_allocate_device(); if (!idev) return -ENOMEM; ar2->idev = idev; - idev->private = ar2; + 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); @@ -362,13 +362,13 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2) idev->phys = ar2->phys; usb_to_input_id(ar2->udev, &idev->id); - idev->cdev.dev = &ar2->udev->dev; + idev->dev.parent = &ar2->udev->dev; - i = input_register_device(idev); - if (i) + retval = input_register_device(idev); + if (retval) input_free_device(idev); - return i; + return retval; } static int ati_remote2_urb_init(struct ati_remote2 *ar2) diff --git a/drivers/usb/input/gtco.c b/drivers/usb/input/gtco.c index ae756e0..b2ca10f2f 100644 --- a/drivers/usb/input/gtco.c +++ b/drivers/usb/input/gtco.c @@ -187,7 +187,6 @@ struct hid_descriptor /* - * * This is an abbreviated parser for the HID Report Descriptor. We * know what devices we are talking to, so this is by no means meant * to be generic. We can make some safe assumptions: @@ -204,7 +203,7 @@ struct hid_descriptor static void parse_hid_report_descriptor(struct gtco *device, char * report, int length) { - int x,i=0; + int x, i = 0; /* Tag primitive vars */ __u8 prefix; @@ -215,7 +214,6 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report, __u16 data16 = 0; __u32 data32 = 0; - /* For parsing logic */ int inputnum = 0; __u32 usage = 0; @@ -225,46 +223,46 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report, __u32 oldval[TAG_GLOB_MAX]; /* Debug stuff */ - char maintype='x'; + char maintype = 'x'; char globtype[12]; - int indent=0; - char indentstr[10]=""; - + int indent = 0; + char indentstr[10] = ""; dbg("======>>>>>>PARSE<<<<<<======"); /* Walk this report and pull out the info we need */ - while (i<length){ - prefix=report[i]; + while (i < length) { + prefix = report[i]; /* Skip over prefix */ i++; /* Determine data size and save the data in the proper variable */ size = PREF_SIZE(prefix); - switch(size){ + switch (size) { case 1: data = report[i]; break; case 2: - data16 = le16_to_cpu(get_unaligned((__le16*)(&(report[i])))); + data16 = le16_to_cpu(get_unaligned((__le16 *)&report[i])); break; case 3: size = 4; - data32 = le32_to_cpu(get_unaligned((__le32*)(&(report[i])))); + data32 = le32_to_cpu(get_unaligned((__le32 *)&report[i])); + break; } /* Skip size of data */ - i+=size; + i += size; /* What we do depends on the tag type */ tag = PREF_TAG(prefix); type = PREF_TYPE(prefix); - switch(type){ + switch (type) { case TYPE_MAIN: - strcpy(globtype,""); - switch(tag){ + strcpy(globtype, ""); + switch (tag) { case TAG_MAIN_INPUT: /* @@ -274,19 +272,17 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report, * min/max values */ - maintype='I'; - if (data==2){ - strcpy(globtype,"Variable"); - } - if (data==3){ - strcpy(globtype,"Var|Const"); - } + maintype = 'I'; + if (data == 2) + strcpy(globtype, "Variable"); + else if (data == 3) + strcpy(globtype, "Var|Const"); dbg("::::: Saving Report: %d input #%d Max: 0x%X(%d) Min:0x%X(%d) of %d bits", - globalval[TAG_GLOB_REPORT_ID],inputnum, - globalval[TAG_GLOB_LOG_MAX],globalval[TAG_GLOB_LOG_MAX], - globalval[TAG_GLOB_LOG_MIN],globalval[TAG_GLOB_LOG_MIN], - (globalval[TAG_GLOB_REPORT_SZ] * globalval[TAG_GLOB_REPORT_CNT])); + globalval[TAG_GLOB_REPORT_ID], inputnum, + globalval[TAG_GLOB_LOG_MAX], globalval[TAG_GLOB_LOG_MAX], + globalval[TAG_GLOB_LOG_MIN], globalval[TAG_GLOB_LOG_MIN], + globalval[TAG_GLOB_REPORT_SZ] * globalval[TAG_GLOB_REPORT_CNT]); /* @@ -295,43 +291,43 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report, that, we look for everything else by local usage value */ - switch (inputnum){ + switch (inputnum) { case 0: /* X coord */ - dbg("GER: X Usage: 0x%x",usage); - if (device->max_X == 0){ + dbg("GER: X Usage: 0x%x", usage); + if (device->max_X == 0) { device->max_X = globalval[TAG_GLOB_LOG_MAX]; device->min_X = globalval[TAG_GLOB_LOG_MIN]; } - break; + case 1: /* Y coord */ - dbg("GER: Y Usage: 0x%x",usage); - if (device->max_Y == 0){ + dbg("GER: Y Usage: 0x%x", usage); + if (device->max_Y == 0) { device->max_Y = globalval[TAG_GLOB_LOG_MAX]; device->min_Y = globalval[TAG_GLOB_LOG_MIN]; } break; + default: /* Tilt X */ - if (usage == DIGITIZER_USAGE_TILT_X){ - if (device->maxtilt_X == 0){ + if (usage == DIGITIZER_USAGE_TILT_X) { + if (device->maxtilt_X == 0) { device->maxtilt_X = globalval[TAG_GLOB_LOG_MAX]; device->mintilt_X = globalval[TAG_GLOB_LOG_MIN]; } } /* Tilt Y */ - if (usage == DIGITIZER_USAGE_TILT_Y){ - if (device->maxtilt_Y == 0){ + if (usage == DIGITIZER_USAGE_TILT_Y) { + if (device->maxtilt_Y == 0) { device->maxtilt_Y = globalval[TAG_GLOB_LOG_MAX]; device->mintilt_Y = globalval[TAG_GLOB_LOG_MIN]; } } - /* Pressure */ - if (usage == DIGITIZER_USAGE_TIP_PRESSURE){ - if (device->maxpressure == 0){ + if (usage == DIGITIZER_USAGE_TIP_PRESSURE) { + if (device->maxpressure == 0) { device->maxpressure = globalval[TAG_GLOB_LOG_MAX]; device->minpressure = globalval[TAG_GLOB_LOG_MIN]; } @@ -341,214 +337,226 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report, } inputnum++; - - break; + case TAG_MAIN_OUTPUT: - maintype='O'; + maintype = 'O'; break; + case TAG_MAIN_FEATURE: - maintype='F'; + maintype = 'F'; break; + case TAG_MAIN_COL_START: - maintype='S'; + maintype = 'S'; - if (data==0){ + if (data == 0) { dbg("======>>>>>> Physical"); - strcpy(globtype,"Physical"); - }else{ + strcpy(globtype, "Physical"); + } else dbg("======>>>>>>"); - } /* Indent the debug output */ indent++; - for (x=0;x<indent;x++){ - indentstr[x]='-'; - } - indentstr[x]=0; + for (x = 0; x < indent; x++) + indentstr[x] = '-'; + indentstr[x] = 0; /* Save global tags */ - for (x=0;x<TAG_GLOB_MAX;x++){ + for (x = 0; x < TAG_GLOB_MAX; x++) oldval[x] = globalval[x]; - } break; + case TAG_MAIN_COL_END: dbg("<<<<<<======"); - maintype='E'; + maintype = 'E'; indent--; - for (x=0;x<indent;x++){ - indentstr[x]='-'; - } - indentstr[x]=0; + for (x = 0; x < indent; x++) + indentstr[x] = '-'; + indentstr[x] = 0; /* Copy global tags back */ - for (x=0;x<TAG_GLOB_MAX;x++){ + for (x = 0; x < TAG_GLOB_MAX; x++) globalval[x] = oldval[x]; - } break; } - switch (size){ + switch (size) { case 1: dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x", - indentstr,tag,maintype,size,globtype,data); + indentstr, tag, maintype, size, globtype, data); break; + case 2: dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x", - indentstr,tag,maintype,size,globtype, data16); + indentstr, tag, maintype, size, globtype, data16); break; + case 4: dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x", - indentstr,tag,maintype,size,globtype,data32); + indentstr, tag, maintype, size, globtype, data32); break; } break; + case TYPE_GLOBAL: - switch(tag){ + switch (tag) { case TAG_GLOB_USAGE: /* * First time we hit the global usage tag, * it should tell us the type of device */ - if (device->usage == 0){ + if (device->usage == 0) device->usage = data; - } - strcpy(globtype,"USAGE"); + + strcpy(globtype, "USAGE"); break; - case TAG_GLOB_LOG_MIN : - strcpy(globtype,"LOG_MIN"); + + case TAG_GLOB_LOG_MIN: + strcpy(globtype, "LOG_MIN"); break; - case TAG_GLOB_LOG_MAX : - strcpy(globtype,"LOG_MAX"); + + case TAG_GLOB_LOG_MAX: + strcpy(globtype, "LOG_MAX"); break; - case TAG_GLOB_PHYS_MIN : - strcpy(globtype,"PHYS_MIN"); + + case TAG_GLOB_PHYS_MIN: + strcpy(globtype, "PHYS_MIN"); break; - case TAG_GLOB_PHYS_MAX : - strcpy(globtype,"PHYS_MAX"); + + case TAG_GLOB_PHYS_MAX: + strcpy(globtype, "PHYS_MAX"); break; - case TAG_GLOB_UNIT_EXP : - strcpy(globtype,"EXP"); + + case TAG_GLOB_UNIT_EXP: + strcpy(globtype, "EXP"); break; - case TAG_GLOB_UNIT : - strcpy(globtype,"UNIT"); + + case TAG_GLOB_UNIT: + strcpy(globtype, "UNIT"); break; - case TAG_GLOB_REPORT_SZ : - strcpy(globtype,"REPORT_SZ"); + + case TAG_GLOB_REPORT_SZ: + strcpy(globtype, "REPORT_SZ"); break; - case TAG_GLOB_REPORT_ID : - strcpy(globtype,"REPORT_ID"); + + case TAG_GLOB_REPORT_ID: + strcpy(globtype, "REPORT_ID"); /* New report, restart numbering */ - inputnum=0; + inputnum = 0; break; + case TAG_GLOB_REPORT_CNT: - strcpy(globtype,"REPORT_CNT"); + strcpy(globtype, "REPORT_CNT"); break; - case TAG_GLOB_PUSH : - strcpy(globtype,"PUSH"); + + case TAG_GLOB_PUSH: + strcpy(globtype, "PUSH"); break; + case TAG_GLOB_POP: - strcpy(globtype,"POP"); + strcpy(globtype, "POP"); break; } - /* Check to make sure we have a good tag number so we don't overflow array */ - if (tag < TAG_GLOB_MAX){ - switch (size){ + if (tag < TAG_GLOB_MAX) { + switch (size) { case 1: - dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",indentstr,globtype,tag,size,data); - globalval[tag]=data; + dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x", + indentstr, globtype, tag, size, data); + globalval[tag] = data; break; + case 2: - dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",indentstr,globtype,tag,size,data16); - globalval[tag]=data16; + dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x", + indentstr, globtype, tag, size, data16); + globalval[tag] = data16; break; + case 4: - dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",indentstr,globtype,tag,size,data32); - globalval[tag]=data32; + dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x", + indentstr, globtype, tag, size, data32); + globalval[tag] = data32; break; } - }else{ + } else { dbg("%sGLOBALTAG: ILLEGAL TAG:%d SIZE: %d ", - indentstr,tag,size); + indentstr, tag, size); } - - break; case TYPE_LOCAL: - switch(tag){ + switch (tag) { case TAG_GLOB_USAGE: - strcpy(globtype,"USAGE"); + strcpy(globtype, "USAGE"); /* Always 1 byte */ usage = data; break; - case TAG_GLOB_LOG_MIN : - strcpy(globtype,"MIN"); + + case TAG_GLOB_LOG_MIN: + strcpy(globtype, "MIN"); break; - case TAG_GLOB_LOG_MAX : - strcpy(globtype,"MAX"); + + case TAG_GLOB_LOG_MAX: + strcpy(globtype, "MAX"); break; + default: - strcpy(globtype,"UNKNOWN"); + strcpy(globtype, "UNKNOWN"); + break; } - switch (size){ + switch (size) { case 1: dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", - indentstr,tag,globtype,size,data); + indentstr, tag, globtype, size, data); break; + case 2: dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", - indentstr,tag,globtype,size,data16); + indentstr, tag, globtype, size, data16); break; + case 4: dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", - indentstr,tag,globtype,size,data32); + indentstr, tag, globtype, size, data32); break; } break; } - } - } - - /* INPUT DRIVER Routines */ - /* - * Called when opening the input device. This will submit the URB to - * the usb system so we start getting reports + * Called when opening the input device. This will submit the URB to + * the usb system so we start getting reports */ static int gtco_input_open(struct input_dev *inputdev) { - struct gtco *device; - device = inputdev->private; + struct gtco *device = input_get_drvdata(inputdev); device->urbinfo->dev = device->usbdev; - if (usb_submit_urb(device->urbinfo, GFP_KERNEL)) { + if (usb_submit_urb(device->urbinfo, GFP_KERNEL)) return -EIO; - } + return 0; } -/** - Called when closing the input device. This will unlink the URB -*/ +/* + * Called when closing the input device. This will unlink the URB + */ static void gtco_input_close(struct input_dev *inputdev) { - struct gtco *device = inputdev->private; + struct gtco *device = input_get_drvdata(inputdev); usb_kill_urb(device->urbinfo); - } @@ -560,19 +568,16 @@ static void gtco_input_close(struct input_dev *inputdev) * placed in the struct gtco structure * */ -static void gtco_setup_caps(struct input_dev *inputdev) +static void gtco_setup_caps(struct input_dev *inputdev) { - struct gtco *device = inputdev->private; - + struct gtco *device = input_get_drvdata(inputdev); /* Which events */ inputdev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC); - /* Misc event menu block */ inputdev->mscbit[0] = BIT(MSC_SCAN)|BIT(MSC_SERIAL)|BIT(MSC_RAW) ; - /* Absolute values based on HID report info */ input_set_abs_params(inputdev, ABS_X, device->min_X, device->max_X, 0, 0); @@ -590,17 +595,12 @@ static void gtco_setup_caps(struct input_dev *inputdev) input_set_abs_params(inputdev, ABS_PRESSURE, device->minpressure, device->maxpressure, 0, 0); - /* Transducer */ - input_set_abs_params(inputdev, ABS_MISC, 0,0xFF, 0, 0); - + input_set_abs_params(inputdev, ABS_MISC, 0, 0xFF, 0, 0); } - - /* USB Routines */ - /* * URB callback routine. Called when we get IRQ reports from the * digitizer. @@ -610,9 +610,7 @@ static void gtco_setup_caps(struct input_dev *inputdev) */ static void gtco_urb_callback(struct urb *urbinfo) { - - - struct gtco *device = urbinfo->context; + struct gtco *device = urbinfo->context; struct input_dev *inputdev; int rc; u32 val = 0; @@ -621,19 +619,20 @@ static void gtco_urb_callback(struct urb *urbinfo) inputdev = device->inputdevice; - /* Was callback OK? */ - if ((urbinfo->status == -ECONNRESET ) || - (urbinfo->status == -ENOENT ) || - (urbinfo->status == -ESHUTDOWN )){ + if (urbinfo->status == -ECONNRESET || + urbinfo->status == -ENOENT || + urbinfo->status == -ESHUTDOWN) { /* Shutdown is occurring. Return and don't queue up any more */ return; } - if (urbinfo->status != 0 ) { - /* Some unknown error. Hopefully temporary. Just go and */ - /* requeue an URB */ + if (urbinfo->status != 0) { + /* + * Some unknown error. Hopefully temporary. Just go and + * requeue an URB + */ goto resubmit; } @@ -642,10 +641,9 @@ static void gtco_urb_callback(struct urb *urbinfo) */ /* PID dependent when we interpret the report */ - if ((inputdev->id.product == PID_1000 )|| - (inputdev->id.product == PID_1001 )|| - (inputdev->id.product == PID_1002 )) - { + if (inputdev->id.product == PID_1000 || + inputdev->id.product == PID_1001 || + inputdev->id.product == PID_1002) { /* * Switch on the report ID @@ -653,10 +651,10 @@ static void gtco_urb_callback(struct urb *urbinfo) * the report number. We can just fall through the case * statements if we start with the highest number report */ - switch(device->buffer[0]){ + switch (device->buffer[0]) { case 5: /* Pressure is 9 bits */ - val = ((u16)(device->buffer[8]) << 1); + val = ((u16)(device->buffer[8]) << 1); val |= (u16)(device->buffer[7] >> 7); input_report_abs(inputdev, ABS_PRESSURE, device->buffer[8]); @@ -664,7 +662,6 @@ static void gtco_urb_callback(struct urb *urbinfo) /* Mask out the Y tilt value used for pressure */ device->buffer[7] = (u8)((device->buffer[7]) & 0x7F); - /* Fall thru */ case 4: /* Tilt */ @@ -684,11 +681,10 @@ static void gtco_urb_callback(struct urb *urbinfo) input_report_abs(inputdev, ABS_TILT_Y, (s32)valsigned); /* Fall thru */ - case 2: case 3: /* Convert buttons, only 5 bits possible */ - val = (device->buffer[5])&MASK_BUTTON; + val = (device->buffer[5]) & MASK_BUTTON; /* We don't apply any meaning to the bitmask, just report */ @@ -696,132 +692,109 @@ static void gtco_urb_callback(struct urb *urbinfo) /* Fall thru */ case 1: - /* All reports have X and Y coords in the same place */ - val = le16_to_cpu(get_unaligned((__le16 *) &(device->buffer[1]))); + val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[1])); input_report_abs(inputdev, ABS_X, val); - val = le16_to_cpu(get_unaligned((__le16 *) &(device->buffer[3]))); + val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3])); input_report_abs(inputdev, ABS_Y, val); - /* Ditto for proximity bit */ - if (device->buffer[5]& MASK_INRANGE){ - val = 1; - }else{ - val=0; - } + val = device->buffer[5] & MASK_INRANGE ? 1 : 0; input_report_abs(inputdev, ABS_DISTANCE, val); - /* Report 1 is an exception to how we handle buttons */ /* Buttons are an index, not a bitmask */ - if (device->buffer[0] == 1){ + if (device->buffer[0] == 1) { - /* Convert buttons, 5 bit index */ - /* Report value of index set as one, - the rest as 0 */ - val = device->buffer[5]& MASK_BUTTON; + /* + * Convert buttons, 5 bit index + * Report value of index set as one, + * the rest as 0 + */ + val = device->buffer[5] & MASK_BUTTON; dbg("======>>>>>>REPORT 1: val 0x%X(%d)", - val,val); + val, val); /* * We don't apply any meaning to the button * index, just report it */ input_event(inputdev, EV_MSC, MSC_SERIAL, val); - - } - break; + case 7: /* Menu blocks */ input_event(inputdev, EV_MSC, MSC_SCAN, device->buffer[1]); - - break; - } - - } + /* Other pid class */ - if ((inputdev->id.product == PID_400 )|| - (inputdev->id.product == PID_401 )) - { + if (inputdev->id.product == PID_400 || + inputdev->id.product == PID_401) { /* Report 2 */ - if (device->buffer[0] == 2){ + if (device->buffer[0] == 2) { /* Menu blocks */ - input_event(inputdev, EV_MSC, MSC_SCAN, - device->buffer[1]); + input_event(inputdev, EV_MSC, MSC_SCAN, device->buffer[1]); } /* Report 1 */ - if (device->buffer[0] == 1){ + if (device->buffer[0] == 1) { char buttonbyte; - /* IF X max > 64K, we still a bit from the y report */ - if (device->max_X > 0x10000){ + if (device->max_X > 0x10000) { - val = (u16)(((u16)(device->buffer[2]<<8))|((u8)(device->buffer[1]))); - val |= (u32)(((u8)device->buffer[3]&0x1)<< 16); + val = (u16)(((u16)(device->buffer[2] << 8)) | (u8)device->buffer[1]); + val |= (u32)(((u8)device->buffer[3] & 0x1) << 16); input_report_abs(inputdev, ABS_X, val); - le_buffer[0] = (u8)((u8)(device->buffer[3])>>1); - le_buffer[0] |= (u8)((device->buffer[3]&0x1)<<7); - - le_buffer[1] = (u8)(device->buffer[4]>>1); - le_buffer[1] |= (u8)((device->buffer[5]&0x1)<<7); + le_buffer[0] = (u8)((u8)(device->buffer[3]) >> 1); + le_buffer[0] |= (u8)((device->buffer[3] & 0x1) << 7); - val = le16_to_cpu(get_unaligned((__le16 *)(le_buffer))); + le_buffer[1] = (u8)(device->buffer[4] >> 1); + le_buffer[1] |= (u8)((device->buffer[5] & 0x1) << 7); + val = le16_to_cpu(get_unaligned((__le16 *)le_buffer)); input_report_abs(inputdev, ABS_Y, val); - /* * Shift the button byte right by one to * make it look like the standard report */ - buttonbyte = (device->buffer[5])>>1; - }else{ + buttonbyte = device->buffer[5] >> 1; + } else { - val = le16_to_cpu(get_unaligned((__le16 *) (&(device->buffer[1])))); + val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[1])); input_report_abs(inputdev, ABS_X, val); - val = le16_to_cpu(get_unaligned((__le16 *) (&(device->buffer[3])))); + val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3])); input_report_abs(inputdev, ABS_Y, val); buttonbyte = device->buffer[5]; - } - /* BUTTONS and PROXIMITY */ - if (buttonbyte& MASK_INRANGE){ - val = 1; - }else{ - val=0; - } + val = buttonbyte & MASK_INRANGE ? 1 : 0; input_report_abs(inputdev, ABS_DISTANCE, val); /* Convert buttons, only 4 bits possible */ - val = buttonbyte&0x0F; + val = buttonbyte & 0x0F; #ifdef USE_BUTTONS - for ( i=0;i<5;i++){ - input_report_key(inputdev, BTN_DIGI+i,val&(1<<i)); - } + for (i = 0; i < 5; i++) + input_report_key(inputdev, BTN_DIGI + i, val & (1 << i)); #else /* We don't apply any meaning to the bitmask, just report */ input_event(inputdev, EV_MSC, MSC_SERIAL, val); #endif + /* TRANSDUCER */ input_report_abs(inputdev, ABS_MISC, device->buffer[6]); - } } @@ -833,10 +806,8 @@ static void gtco_urb_callback(struct urb *urbinfo) resubmit: rc = usb_submit_urb(urbinfo, GFP_ATOMIC); - if (rc != 0) { - err("usb_submit_urb failed rc=0x%x",rc); - } - + if (rc != 0) + err("usb_submit_urb failed rc=0x%x", rc); } /* @@ -854,58 +825,46 @@ static int gtco_probe(struct usb_interface *usbinterface, const struct usb_device_id *id) { - struct gtco *device = NULL; - char path[PATHLENGTH]; - struct input_dev *inputdev; + struct gtco *gtco; + struct input_dev *input_dev; struct hid_descriptor *hid_desc; - char *report; - int result=0, retry; + char *report = NULL; + int result = 0, retry; + int error; struct usb_endpoint_descriptor *endpoint; /* Allocate memory for device structure */ - device = kzalloc(sizeof(struct gtco), GFP_KERNEL); - if (device == NULL) { + gtco = kzalloc(sizeof(struct gtco), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!gtco || !input_dev) { err("No more memory"); - return -ENOMEM; + error = -ENOMEM; + goto err_free_devs; } - - device->inputdevice = input_allocate_device(); - if (!device->inputdevice){ - kfree(device); - err("No more memory"); - return -ENOMEM; - } - - /* Get pointer to the input device */ - inputdev = device->inputdevice; + /* Set pointer to the input device */ + gtco->inputdevice = input_dev; /* Save interface information */ - device->usbdev = usb_get_dev(interface_to_usbdev(usbinterface)); - + gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface)); /* Allocate some data for incoming reports */ - device->buffer = usb_buffer_alloc(device->usbdev, REPORT_MAX_SIZE, - GFP_KERNEL, &(device->buf_dma)); - if (!device->buffer){ - input_free_device(device->inputdevice); - kfree(device); - err("No more memory"); - return -ENOMEM; + gtco->buffer = usb_buffer_alloc(gtco->usbdev, REPORT_MAX_SIZE, + GFP_KERNEL, >co->buf_dma); + if (!gtco->buffer) { + err("No more memory for us buffers"); + error = -ENOMEM; + goto err_free_devs; } /* Allocate URB for reports */ - device->urbinfo = usb_alloc_urb(0, GFP_KERNEL); - if (!device->urbinfo) { - usb_buffer_free(device->usbdev, REPORT_MAX_SIZE, - device->buffer, device->buf_dma); - input_free_device(device->inputdevice); - kfree(device); - err("No more memory"); + gtco->urbinfo = usb_alloc_urb(0, GFP_KERNEL); + if (!gtco->urbinfo) { + err("Failed to allocate URB"); return -ENOMEM; + goto err_free_buf; } - /* * The endpoint is always altsetting 0, we know this since we know * this device only has one interrupt endpoint @@ -913,51 +872,43 @@ static int gtco_probe(struct usb_interface *usbinterface, endpoint = &usbinterface->altsetting[0].endpoint[0].desc; /* Some debug */ - dbg("gtco # interfaces: %d",usbinterface->num_altsetting); - dbg("num endpoints: %d",usbinterface->cur_altsetting->desc.bNumEndpoints); - dbg("interface class: %d",usbinterface->cur_altsetting->desc.bInterfaceClass); - dbg("endpoint: attribute:0x%x type:0x%x",endpoint->bmAttributes,endpoint->bDescriptorType); + dbg("gtco # interfaces: %d", usbinterface->num_altsetting); + dbg("num endpoints: %d", usbinterface->cur_altsetting->desc.bNumEndpoints); + dbg("interface class: %d", usbinterface->cur_altsetting->desc.bInterfaceClass); + dbg("endpoint: attribute:0x%x type:0x%x", endpoint->bmAttributes, endpoint->bDescriptorType); if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) dbg("endpoint: we have interrupt endpoint\n"); - dbg("endpoint extra len:%d ",usbinterface->altsetting[0].extralen); - - + dbg("endpoint extra len:%d ", usbinterface->altsetting[0].extralen); /* * Find the HID descriptor so we can find out the size of the * HID report descriptor */ if (usb_get_extra_descriptor(usbinterface->cur_altsetting, - HID_DEVICE_TYPE,&hid_desc) != 0){ + HID_DEVICE_TYPE, &hid_desc) != 0){ err("Can't retrieve exta USB descriptor to get hid report descriptor length"); - usb_buffer_free(device->usbdev, REPORT_MAX_SIZE, - device->buffer, device->buf_dma); - input_free_device(device->inputdevice); - kfree(device); - return -EIO; + error = -EIO; + goto err_free_urb; } dbg("Extra descriptor success: type:%d len:%d", hid_desc->bDescriptorType, hid_desc->wDescriptorLength); - if (!(report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL))) { - usb_buffer_free(device->usbdev, REPORT_MAX_SIZE, - device->buffer, device->buf_dma); - - input_free_device(device->inputdevice); - kfree(device); - err("No more memory"); - return -ENOMEM; + report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL); + if (!report) { + err("No more memory for report"); + error = -ENOMEM; + goto err_free_urb; } /* Couple of tries to get reply */ - for (retry=0;retry<3;retry++) { - result = usb_control_msg(device->usbdev, - usb_rcvctrlpipe(device->usbdev, 0), + for (retry = 0; retry < 3; retry++) { + result = usb_control_msg(gtco->usbdev, + usb_rcvctrlpipe(gtco->usbdev, 0), USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, - (REPORT_DEVICE_TYPE << 8), + REPORT_DEVICE_TYPE << 8, 0, /* interface */ report, hid_desc->wDescriptorLength, @@ -969,72 +920,76 @@ static int gtco_probe(struct usb_interface *usbinterface, /* If we didn't get the report, fail */ dbg("usb_control_msg result: :%d", result); - if (result != hid_desc->wDescriptorLength){ - kfree(report); - usb_buffer_free(device->usbdev, REPORT_MAX_SIZE, - device->buffer, device->buf_dma); - input_free_device(device->inputdevice); - kfree(device); + if (result != hid_desc->wDescriptorLength) { err("Failed to get HID Report Descriptor of size: %d", hid_desc->wDescriptorLength); - return -EIO; + error = -EIO; + goto err_free_urb; } - /* Now we parse the report */ - parse_hid_report_descriptor(device,report,result); + parse_hid_report_descriptor(gtco, report, result); /* Now we delete it */ kfree(report); /* Create a device file node */ - usb_make_path(device->usbdev, path, PATHLENGTH); - sprintf(device->usbpath, "%s/input0", path); - + usb_make_path(gtco->usbdev, gtco->usbpath, sizeof(gtco->usbpath)); + strlcat(gtco->usbpath, "/input0", sizeof(gtco->usbpath)); /* Set Input device functions */ - inputdev->open = gtco_input_open; - inputdev->close = gtco_input_close; + input_dev->open = gtco_input_open; + input_dev->close = gtco_input_close; /* Set input device information */ - inputdev->name = "GTCO_CalComp"; - inputdev->phys = device->usbpath; - inputdev->private = device; + input_dev->name = "GTCO_CalComp"; + input_dev->phys = gtco->usbpath; + input_set_drvdata(input_dev, gtco); /* Now set up all the input device capabilities */ - gtco_setup_caps(inputdev); + gtco_setup_caps(input_dev); /* Set input device required ID information */ - usb_to_input_id(device->usbdev, &device->inputdevice->id); - inputdev->cdev.dev = &usbinterface->dev; + usb_to_input_id(gtco->usbdev, &input_dev->id); + input_dev->dev.parent = &usbinterface->dev; /* Setup the URB, it will be posted later on open of input device */ endpoint = &usbinterface->altsetting[0].endpoint[0].desc; - usb_fill_int_urb(device->urbinfo, - device->usbdev, - usb_rcvintpipe(device->usbdev, + usb_fill_int_urb(gtco->urbinfo, + gtco->usbdev, + usb_rcvintpipe(gtco->usbdev, endpoint->bEndpointAddress), - device->buffer, + gtco->buffer, REPORT_MAX_SIZE, gtco_urb_callback, - device, + gtco, endpoint->bInterval); - device->urbinfo->transfer_dma = device->buf_dma; - device->urbinfo->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - + gtco->urbinfo->transfer_dma = gtco->buf_dma; + gtco->urbinfo->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - /* Save device pointer in USB interface device */ - usb_set_intfdata(usbinterface, device); + /* Save gtco pointer in USB interface gtco */ + usb_set_intfdata(usbinterface, gtco); /* All done, now register the input device */ - input_register_device(inputdev); + error = input_register_device(input_dev); + if (error) + goto err_free_urb; - info( "gtco driver created usb: %s\n", path); return 0; + err_free_urb: + usb_free_urb(gtco->urbinfo); + err_free_buf: + usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE, + gtco->buffer, gtco->buf_dma); + err_free_devs: + kfree(report); + input_free_device(input_dev); + kfree(gtco); + return error; } /* @@ -1044,47 +999,46 @@ static int gtco_probe(struct usb_interface *usbinterface, */ static void gtco_disconnect(struct usb_interface *interface) { - /* Grab private device ptr */ - struct gtco *device = usb_get_intfdata (interface); + struct gtco *gtco = usb_get_intfdata(interface); /* Now reverse all the registration stuff */ - if (device) { - input_unregister_device(device->inputdevice); - usb_kill_urb(device->urbinfo); - usb_free_urb(device->urbinfo); - usb_buffer_free(device->usbdev, REPORT_MAX_SIZE, - device->buffer, device->buf_dma); - kfree(device); + if (gtco) { + input_unregister_device(gtco->inputdevice); + usb_kill_urb(gtco->urbinfo); + usb_free_urb(gtco->urbinfo); + usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE, + gtco->buffer, gtco->buf_dma); + kfree(gtco); } info("gtco driver disconnected"); } - /* STANDARD MODULE LOAD ROUTINES */ static struct usb_driver gtco_driverinfo_table = { -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)) - .owner = THIS_MODULE, -#endif - .name = "gtco", - .id_table = gtco_usbid_table, - .probe = gtco_probe, - .disconnect = gtco_disconnect, + .name = "gtco", + .id_table = gtco_usbid_table, + .probe = gtco_probe, + .disconnect = gtco_disconnect, }; + /* * Register this module with the USB subsystem */ static int __init gtco_init(void) { - int rc; - rc = usb_register(>co_driverinfo_table); - if (rc) { - err("usb_register() failed rc=0x%x", rc); + int error; + + error = usb_register(>co_driverinfo_table); + if (error) { + err("usb_register() failed rc=0x%x", error); + return error; } - printk("GTCO usb driver version: %s",GTCO_VERSION); - return rc; + + printk("GTCO usb driver version: %s", GTCO_VERSION); + return 0; } /* @@ -1095,7 +1049,7 @@ static void __exit gtco_exit(void) usb_deregister(>co_driverinfo_table); } -module_init (gtco_init); -module_exit (gtco_exit); +module_init(gtco_init); +module_exit(gtco_exit); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c deleted file mode 100644 index aac968a..0000000 --- a/drivers/usb/input/itmtouch.c +++ /dev/null @@ -1,271 +0,0 @@ -/****************************************************************************** - * itmtouch.c -- Driver for ITM touchscreen panel - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Based upon original work by Chris Collins <xfire-itmtouch@xware.cx>. - * - * Kudos to ITM for providing me with the datasheet for the panel, - * even though it was a day later than I had finished writing this - * driver. - * - * It has meant that I've been able to correct my interpretation of the - * protocol packets however. - * - * CC -- 2003/9/29 - * - * History - * 1.0 & 1.1 2003 (CC) vojtech@suse.cz - * Original version for 2.4.x kernels - * - * 1.2 02/03/2005 (HCE) hc@mivu.no - * Complete rewrite to support Linux 2.6.10, thanks to mtouchusb.c for hints. - * Unfortunately no calibration support at this time. - * - * 1.2.1 09/03/2005 (HCE) hc@mivu.no - * Code cleanup and adjusting syntax to start matching kernel standards - * - * 1.2.2 10/05/2006 (MJA) massad@gmail.com - * Flag for detecting if the screen was being touch was incorrectly - * inverted, so no touch events were being detected. - * - *****************************************************************************/ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/usb/input.h> - -/* only an 8 byte buffer necessary for a single packet */ -#define ITM_BUFSIZE 8 -#define PATH_SIZE 64 - -#define USB_VENDOR_ID_ITMINC 0x0403 -#define USB_PRODUCT_ID_TOUCHPANEL 0xf9e9 - -#define DRIVER_AUTHOR "Hans-Christian Egtvedt <hc@mivu.no>" -#define DRIVER_VERSION "v1.2.2" -#define DRIVER_DESC "USB ITM Inc Touch Panel Driver" -#define DRIVER_LICENSE "GPL" - -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_LICENSE( DRIVER_LICENSE ); - -struct itmtouch_dev { - struct usb_device *usbdev; /* usb device */ - struct input_dev *inputdev; /* input device */ - struct urb *readurb; /* urb */ - char rbuf[ITM_BUFSIZE]; /* data */ - int users; - char name[128]; - char phys[64]; -}; - -static struct usb_device_id itmtouch_ids [] = { - { USB_DEVICE(USB_VENDOR_ID_ITMINC, USB_PRODUCT_ID_TOUCHPANEL) }, - { } -}; - -static void itmtouch_irq(struct urb *urb) -{ - struct itmtouch_dev *itmtouch = urb->context; - unsigned char *data = urb->transfer_buffer; - struct input_dev *dev = itmtouch->inputdev; - int retval; - - switch (urb->status) { - case 0: - /* success */ - break; - case -ETIME: - /* this urb is timing out */ - dbg("%s - urb timed out - was the device unplugged?", - __FUNCTION__); - return; - 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; - } - - /* if pressure has been released, then don't report X/Y */ - if (!(data[7] & 0x20)) { - input_report_abs(dev, ABS_X, (data[0] & 0x1F) << 7 | (data[3] & 0x7F)); - input_report_abs(dev, ABS_Y, (data[1] & 0x1F) << 7 | (data[4] & 0x7F)); - } - - input_report_abs(dev, ABS_PRESSURE, (data[2] & 1) << 7 | (data[5] & 0x7F)); - input_report_key(dev, BTN_TOUCH, ~data[7] & 0x20); - input_sync(dev); - -exit: - retval = usb_submit_urb (urb, GFP_ATOMIC); - if (retval) - printk(KERN_ERR "%s - usb_submit_urb failed with result: %d", - __FUNCTION__, retval); -} - -static int itmtouch_open(struct input_dev *input) -{ - struct itmtouch_dev *itmtouch = input->private; - - itmtouch->readurb->dev = itmtouch->usbdev; - - if (usb_submit_urb(itmtouch->readurb, GFP_KERNEL)) - return -EIO; - - return 0; -} - -static void itmtouch_close(struct input_dev *input) -{ - struct itmtouch_dev *itmtouch = input->private; - - usb_kill_urb(itmtouch->readurb); -} - -static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct itmtouch_dev *itmtouch; - struct input_dev *input_dev; - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct usb_device *udev = interface_to_usbdev(intf); - unsigned int pipe; - unsigned int maxp; - - interface = intf->cur_altsetting; - endpoint = &interface->endpoint[0].desc; - - itmtouch = kzalloc(sizeof(struct itmtouch_dev), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!itmtouch || !input_dev) { - err("%s - Out of memory.", __FUNCTION__); - goto fail; - } - - itmtouch->usbdev = udev; - itmtouch->inputdev = input_dev; - - if (udev->manufacturer) - strlcpy(itmtouch->name, udev->manufacturer, sizeof(itmtouch->name)); - - if (udev->product) { - if (udev->manufacturer) - strlcat(itmtouch->name, " ", sizeof(itmtouch->name)); - strlcat(itmtouch->name, udev->product, sizeof(itmtouch->name)); - } - - if (!strlen(itmtouch->name)) - sprintf(itmtouch->name, "USB ITM touchscreen"); - - usb_make_path(udev, itmtouch->phys, sizeof(itmtouch->phys)); - strlcpy(itmtouch->phys, "/input0", sizeof(itmtouch->phys)); - - input_dev->name = itmtouch->name; - input_dev->phys = itmtouch->phys; - usb_to_input_id(udev, &input_dev->id); - input_dev->cdev.dev = &intf->dev; - input_dev->private = itmtouch; - - input_dev->open = itmtouch_open; - input_dev->close = itmtouch_close; - - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); - input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); - - /* device limits */ - /* as specified by the ITM datasheet, X and Y are 12bit, - * Z (pressure) is 8 bit. However, the fields are defined up - * to 14 bits for future possible expansion. - */ - input_set_abs_params(input_dev, ABS_X, 0, 0x0FFF, 2, 0); - input_set_abs_params(input_dev, ABS_Y, 0, 0x0FFF, 2, 0); - input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xFF, 2, 0); - - /* initialise the URB so we can read from the transport stream */ - pipe = usb_rcvintpipe(itmtouch->usbdev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); - - if (maxp > ITM_BUFSIZE) - maxp = ITM_BUFSIZE; - - itmtouch->readurb = usb_alloc_urb(0, GFP_KERNEL); - if (!itmtouch->readurb) { - dbg("%s - usb_alloc_urb failed: itmtouch->readurb", __FUNCTION__); - goto fail; - } - - usb_fill_int_urb(itmtouch->readurb, itmtouch->usbdev, pipe, itmtouch->rbuf, - maxp, itmtouch_irq, itmtouch, endpoint->bInterval); - - input_register_device(itmtouch->inputdev); - - usb_set_intfdata(intf, itmtouch); - - return 0; - - fail: input_free_device(input_dev); - kfree(itmtouch); - return -ENOMEM; -} - -static void itmtouch_disconnect(struct usb_interface *intf) -{ - struct itmtouch_dev *itmtouch = usb_get_intfdata(intf); - - usb_set_intfdata(intf, NULL); - - if (itmtouch) { - input_unregister_device(itmtouch->inputdev); - usb_kill_urb(itmtouch->readurb); - usb_free_urb(itmtouch->readurb); - kfree(itmtouch); - } -} - -MODULE_DEVICE_TABLE(usb, itmtouch_ids); - -static struct usb_driver itmtouch_driver = { - .name = "itmtouch", - .probe = itmtouch_probe, - .disconnect = itmtouch_disconnect, - .id_table = itmtouch_ids, -}; - -static int __init itmtouch_init(void) -{ - info(DRIVER_DESC " " DRIVER_VERSION); - info(DRIVER_AUTHOR); - return usb_register(&itmtouch_driver); -} - -static void __exit itmtouch_exit(void) -{ - usb_deregister(&itmtouch_driver); -} - -module_init(itmtouch_init); -module_exit(itmtouch_exit); diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c index fedbcb1..c4781b9 100644 --- a/drivers/usb/input/kbtab.c +++ b/drivers/usb/input/kbtab.c @@ -100,7 +100,7 @@ MODULE_DEVICE_TABLE(usb, kbtab_ids); static int kbtab_open(struct input_dev *dev) { - struct kbtab *kbtab = dev->private; + struct kbtab *kbtab = input_get_drvdata(dev); kbtab->irq->dev = kbtab->usbdev; if (usb_submit_urb(kbtab->irq, GFP_KERNEL)) @@ -111,7 +111,7 @@ static int kbtab_open(struct input_dev *dev) static void kbtab_close(struct input_dev *dev) { - struct kbtab *kbtab = dev->private; + struct kbtab *kbtab = input_get_drvdata(dev); usb_kill_urb(kbtab->irq); } @@ -122,6 +122,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i struct usb_endpoint_descriptor *endpoint; struct kbtab *kbtab; struct input_dev *input_dev; + int error = -ENOMEM; kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL); input_dev = input_allocate_device(); @@ -145,8 +146,9 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i input_dev->name = "KB Gear Tablet"; input_dev->phys = kbtab->phys; usb_to_input_id(dev, &input_dev->id); - input_dev->cdev.dev = &intf->dev; - input_dev->private = kbtab; + input_dev->dev.parent = &intf->dev; + + input_set_drvdata(input_dev, kbtab); input_dev->open = kbtab_open; input_dev->close = kbtab_close; @@ -168,15 +170,19 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i kbtab->irq->transfer_dma = kbtab->data_dma; kbtab->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - input_register_device(kbtab->dev); + error = input_register_device(kbtab->dev); + if (error) + goto fail3; usb_set_intfdata(intf, kbtab); + return 0; -fail2: usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma); -fail1: input_free_device(input_dev); + fail3: usb_free_urb(kbtab->irq); + fail2: usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma); + fail1: input_free_device(input_dev); kfree(kbtab); - return -ENOMEM; + return error; } static void kbtab_disconnect(struct usb_interface *intf) diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c index 98bd323..1bffc9f 100644 --- a/drivers/usb/input/keyspan_remote.c +++ b/drivers/usb/input/keyspan_remote.c @@ -394,7 +394,7 @@ resubmit: static int keyspan_open(struct input_dev *dev) { - struct usb_keyspan *remote = dev->private; + struct usb_keyspan *remote = input_get_drvdata(dev); remote->irq_urb->dev = remote->udev; if (usb_submit_urb(remote->irq_urb, GFP_KERNEL)) @@ -405,7 +405,7 @@ static int keyspan_open(struct input_dev *dev) static void keyspan_close(struct input_dev *dev) { - struct usb_keyspan *remote = dev->private; + struct usb_keyspan *remote = input_get_drvdata(dev); usb_kill_urb(remote->irq_urb); } @@ -437,7 +437,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic struct usb_endpoint_descriptor *endpoint; struct usb_keyspan *remote; struct input_dev *input_dev; - int i, retval; + int i, error; endpoint = keyspan_get_in_endpoint(interface->cur_altsetting); if (!endpoint) @@ -446,7 +446,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic remote = kzalloc(sizeof(*remote), GFP_KERNEL); input_dev = input_allocate_device(); if (!remote || !input_dev) { - retval = -ENOMEM; + error = -ENOMEM; goto fail1; } @@ -458,19 +458,19 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma); if (!remote->in_buffer) { - retval = -ENOMEM; + error = -ENOMEM; goto fail1; } remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); if (!remote->irq_urb) { - retval = -ENOMEM; + error = -ENOMEM; goto fail2; } - retval = keyspan_setup(udev); - if (retval) { - retval = -ENODEV; + error = keyspan_setup(udev); + if (error) { + error = -ENODEV; goto fail3; } @@ -495,14 +495,15 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic input_dev->name = remote->name; input_dev->phys = remote->phys; usb_to_input_id(udev, &input_dev->id); - input_dev->cdev.dev = &interface->dev; + 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_dev->private = remote; + input_set_drvdata(input_dev, remote); + input_dev->open = keyspan_open; input_dev->close = keyspan_close; @@ -517,7 +518,9 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* we can register the device now, as it is ready */ - input_register_device(remote->input); + error = input_register_device(remote->input); + if (error) + goto fail3; /* save our data pointer in this interface device */ usb_set_intfdata(interface, remote); @@ -529,7 +532,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic fail1: kfree(remote); input_free_device(input_dev); - return retval; + return error; } /* diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c deleted file mode 100644 index 92c4e07..0000000 --- a/drivers/usb/input/mtouchusb.c +++ /dev/null @@ -1,332 +0,0 @@ -/****************************************************************************** - * mtouchusb.c -- Driver for Microtouch (Now 3M) USB Touchscreens - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Based upon original work by Radoslaw Garbacz (usb-support@ite.pl) - * (http://freshmeat.net/projects/3mtouchscreendriver) - * - * History - * - * 0.3 & 0.4 2002 (TEJ) tejohnson@yahoo.com - * Updated to 2.4.18, then 2.4.19 - * Old version still relied on stealing a minor - * - * 0.5 02/26/2004 (TEJ) tejohnson@yahoo.com - * Complete rewrite using Linux Input in 2.6.3 - * Unfortunately no calibration support at this time - * - * 1.4 04/25/2004 (TEJ) tejohnson@yahoo.com - * Changed reset from standard USB dev reset to vendor reset - * Changed data sent to host from compensated to raw coordinates - * Eliminated vendor/product module params - * Performed multiple successful tests with an EXII-5010UC - * - * 1.5 02/27/2005 ddstreet@ieee.org - * Added module parameter to select raw or hw-calibrated coordinate reporting - * - *****************************************************************************/ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/usb/input.h> - -#define MTOUCHUSB_MIN_XC 0x0 -#define MTOUCHUSB_MAX_RAW_XC 0x4000 -#define MTOUCHUSB_MAX_CALIB_XC 0xffff -#define MTOUCHUSB_XC_FUZZ 0x0 -#define MTOUCHUSB_XC_FLAT 0x0 -#define MTOUCHUSB_MIN_YC 0x0 -#define MTOUCHUSB_MAX_RAW_YC 0x4000 -#define MTOUCHUSB_MAX_CALIB_YC 0xffff -#define MTOUCHUSB_YC_FUZZ 0x0 -#define MTOUCHUSB_YC_FLAT 0x0 - -#define MTOUCHUSB_ASYNC_REPORT 1 -#define MTOUCHUSB_RESET 7 -#define MTOUCHUSB_REPORT_DATA_SIZE 11 -#define MTOUCHUSB_REQ_CTRLLR_ID 10 - -#define MTOUCHUSB_GET_RAW_XC(data) (data[8]<<8 | data[7]) -#define MTOUCHUSB_GET_CALIB_XC(data) (data[4]<<8 | data[3]) -#define MTOUCHUSB_GET_RAW_YC(data) (data[10]<<8 | data[9]) -#define MTOUCHUSB_GET_CALIB_YC(data) (data[6]<<8 | data[5]) -#define MTOUCHUSB_GET_XC(data) (raw_coordinates ? \ - MTOUCHUSB_GET_RAW_XC(data) : \ - MTOUCHUSB_GET_CALIB_XC(data)) -#define MTOUCHUSB_GET_YC(data) (raw_coordinates ? \ - MTOUCHUSB_GET_RAW_YC(data) : \ - MTOUCHUSB_GET_CALIB_YC(data)) -#define MTOUCHUSB_GET_TOUCHED(data) ((data[2] & 0x40) ? 1:0) - -#define DRIVER_VERSION "v1.5" -#define DRIVER_AUTHOR "Todd E. Johnson, tejohnson@yahoo.com" -#define DRIVER_DESC "3M USB Touchscreen Driver" -#define DRIVER_LICENSE "GPL" - -static int raw_coordinates = 1; - -module_param(raw_coordinates, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(raw_coordinates, "report raw coordinate values (y, default) or hardware-calibrated coordinate values (n)"); - -struct mtouch_usb { - unsigned char *data; - dma_addr_t data_dma; - struct urb *irq; - struct usb_device *udev; - struct input_dev *input; - char name[128]; - char phys[64]; -}; - -static struct usb_device_id mtouchusb_devices[] = { - { USB_DEVICE(0x0596, 0x0001) }, - { } -}; - -static void mtouchusb_irq(struct urb *urb) -{ - struct mtouch_usb *mtouch = urb->context; - int retval; - - switch (urb->status) { - case 0: - /* success */ - break; - case -ETIME: - /* this urb is timing out */ - dbg("%s - urb timed out - was the device unplugged?", - __FUNCTION__); - return; - 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; - } - - input_report_key(mtouch->input, BTN_TOUCH, - MTOUCHUSB_GET_TOUCHED(mtouch->data)); - input_report_abs(mtouch->input, ABS_X, MTOUCHUSB_GET_XC(mtouch->data)); - input_report_abs(mtouch->input, ABS_Y, - (raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC) - - MTOUCHUSB_GET_YC(mtouch->data)); - input_sync(mtouch->input); - -exit: - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - err("%s - usb_submit_urb failed with result: %d", - __FUNCTION__, retval); -} - -static int mtouchusb_open(struct input_dev *input) -{ - struct mtouch_usb *mtouch = input->private; - - mtouch->irq->dev = mtouch->udev; - - if (usb_submit_urb(mtouch->irq, GFP_ATOMIC)) - return -EIO; - - return 0; -} - -static void mtouchusb_close(struct input_dev *input) -{ - struct mtouch_usb *mtouch = input->private; - - usb_kill_urb(mtouch->irq); -} - -static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) -{ - dbg("%s - called", __FUNCTION__); - - mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_DATA_SIZE, - GFP_ATOMIC, &mtouch->data_dma); - - if (!mtouch->data) - return -1; - - return 0; -} - -static void mtouchusb_free_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) -{ - dbg("%s - called", __FUNCTION__); - - if (mtouch->data) - usb_buffer_free(udev, MTOUCHUSB_REPORT_DATA_SIZE, - mtouch->data, mtouch->data_dma); -} - -static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct mtouch_usb *mtouch; - struct input_dev *input_dev; - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct usb_device *udev = interface_to_usbdev(intf); - int nRet; - - dbg("%s - called", __FUNCTION__); - - dbg("%s - setting interface", __FUNCTION__); - interface = intf->cur_altsetting; - - dbg("%s - setting endpoint", __FUNCTION__); - endpoint = &interface->endpoint[0].desc; - - mtouch = kzalloc(sizeof(struct mtouch_usb), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!mtouch || !input_dev) { - err("%s - Out of memory.", __FUNCTION__); - goto fail1; - } - - dbg("%s - allocating buffers", __FUNCTION__); - if (mtouchusb_alloc_buffers(udev, mtouch)) - goto fail2; - - mtouch->udev = udev; - mtouch->input = input_dev; - - if (udev->manufacturer) - strlcpy(mtouch->name, udev->manufacturer, sizeof(mtouch->name)); - - if (udev->product) { - if (udev->manufacturer) - strlcat(mtouch->name, " ", sizeof(mtouch->name)); - strlcat(mtouch->name, udev->product, sizeof(mtouch->name)); - } - - if (!strlen(mtouch->name)) - snprintf(mtouch->name, sizeof(mtouch->name), - "USB Touchscreen %04x:%04x", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); - - usb_make_path(udev, mtouch->phys, sizeof(mtouch->phys)); - strlcpy(mtouch->phys, "/input0", sizeof(mtouch->phys)); - - input_dev->name = mtouch->name; - input_dev->phys = mtouch->phys; - usb_to_input_id(udev, &input_dev->id); - input_dev->cdev.dev = &intf->dev; - input_dev->private = mtouch; - - input_dev->open = mtouchusb_open; - input_dev->close = mtouchusb_close; - - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); - input_set_abs_params(input_dev, ABS_X, MTOUCHUSB_MIN_XC, - raw_coordinates ? MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC, - MTOUCHUSB_XC_FUZZ, MTOUCHUSB_XC_FLAT); - input_set_abs_params(input_dev, ABS_Y, MTOUCHUSB_MIN_YC, - raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC, - MTOUCHUSB_YC_FUZZ, MTOUCHUSB_YC_FLAT); - - nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0), - MTOUCHUSB_RESET, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); - dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", - __FUNCTION__, nRet); - - dbg("%s - usb_alloc_urb: mtouch->irq", __FUNCTION__); - mtouch->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!mtouch->irq) { - dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__); - goto fail2; - } - - dbg("%s - usb_fill_int_urb", __FUNCTION__); - usb_fill_int_urb(mtouch->irq, mtouch->udev, - usb_rcvintpipe(mtouch->udev, 0x81), - mtouch->data, MTOUCHUSB_REPORT_DATA_SIZE, - mtouchusb_irq, mtouch, endpoint->bInterval); - - dbg("%s - input_register_device", __FUNCTION__); - input_register_device(mtouch->input); - - nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0), - MTOUCHUSB_ASYNC_REPORT, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); - dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", - __FUNCTION__, nRet); - - usb_set_intfdata(intf, mtouch); - return 0; - -fail2: mtouchusb_free_buffers(udev, mtouch); -fail1: input_free_device(input_dev); - kfree(mtouch); - return -ENOMEM; -} - -static void mtouchusb_disconnect(struct usb_interface *intf) -{ - struct mtouch_usb *mtouch = usb_get_intfdata(intf); - - dbg("%s - called", __FUNCTION__); - usb_set_intfdata(intf, NULL); - if (mtouch) { - dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__); - usb_kill_urb(mtouch->irq); - input_unregister_device(mtouch->input); - usb_free_urb(mtouch->irq); - mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch); - kfree(mtouch); - } -} - -MODULE_DEVICE_TABLE(usb, mtouchusb_devices); - -static struct usb_driver mtouchusb_driver = { - .name = "mtouchusb", - .probe = mtouchusb_probe, - .disconnect = mtouchusb_disconnect, - .id_table = mtouchusb_devices, -}; - -static int __init mtouchusb_init(void) -{ - dbg("%s - called", __FUNCTION__); - return usb_register(&mtouchusb_driver); -} - -static void __exit mtouchusb_cleanup(void) -{ - dbg("%s - called", __FUNCTION__); - usb_deregister(&mtouchusb_driver); -} - -module_init(mtouchusb_init); -module_exit(mtouchusb_cleanup); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c index fea97e5..4f93a76 100644 --- a/drivers/usb/input/powermate.c +++ b/drivers/usb/input/powermate.c @@ -252,7 +252,7 @@ static void powermate_pulse_led(struct powermate_device *pm, int static_brightne 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 = dev->private; + struct powermate_device *pm = input_get_drvdata(dev); if (type == EV_MSC && code == MSC_PULSELED){ /* @@ -308,7 +308,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i struct powermate_device *pm; struct input_dev *input_dev; int pipe, maxp; - int err = -ENOMEM; + int error = -ENOMEM; interface = intf->cur_altsetting; endpoint = &interface->endpoint[0].desc; @@ -359,8 +359,9 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i input_dev->phys = pm->phys; usb_to_input_id(udev, &input_dev->id); - input_dev->cdev.dev = &intf->dev; - input_dev->private = pm; + input_dev->dev.parent = &intf->dev; + + input_set_drvdata(input_dev, pm); input_dev->event = powermate_input_event; @@ -387,11 +388,14 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i /* register our interrupt URB with the USB system */ if (usb_submit_urb(pm->irq, GFP_KERNEL)) { - err = -EIO; + error = -EIO; goto fail4; } - input_register_device(pm->input); + 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; @@ -400,12 +404,13 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i usb_set_intfdata(intf, pm); return 0; -fail4: usb_free_urb(pm->config); -fail3: usb_free_urb(pm->irq); -fail2: powermate_free_buffers(udev, pm); -fail1: input_free_device(input_dev); + 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 err; + return error; } /* Called when a USB device we've accepted ownership of is removed */ diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c deleted file mode 100644 index 2a314b0..0000000 --- a/drivers/usb/input/touchkitusb.c +++ /dev/null @@ -1,392 +0,0 @@ -/****************************************************************************** - * touchkitusb.c -- Driver for eGalax TouchKit USB Touchscreens - * - * Copyright (C) 2004-2005 by Daniel Ritz <daniel.ritz@gmx.ch> - * Copyright (C) by Todd E. Johnson (mtouchusb.c) - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Based upon mtouchusb.c - * - *****************************************************************************/ - -//#define DEBUG - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/usb/input.h> - -#define TOUCHKIT_MIN_XC 0x0 -#define TOUCHKIT_MAX_XC 0x07ff -#define TOUCHKIT_XC_FUZZ 0x0 -#define TOUCHKIT_XC_FLAT 0x0 -#define TOUCHKIT_MIN_YC 0x0 -#define TOUCHKIT_MAX_YC 0x07ff -#define TOUCHKIT_YC_FUZZ 0x0 -#define TOUCHKIT_YC_FLAT 0x0 -#define TOUCHKIT_REPORT_DATA_SIZE 16 - -#define TOUCHKIT_DOWN 0x01 - -#define TOUCHKIT_PKT_TYPE_MASK 0xFE -#define TOUCHKIT_PKT_TYPE_REPT 0x80 -#define TOUCHKIT_PKT_TYPE_DIAG 0x0A - -#define DRIVER_VERSION "v0.1" -#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" -#define DRIVER_DESC "eGalax TouchKit USB HID Touchscreen Driver" - -static int swap_xy; -module_param(swap_xy, bool, 0644); -MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); - -struct touchkit_usb { - unsigned char *data; - dma_addr_t data_dma; - char buffer[TOUCHKIT_REPORT_DATA_SIZE]; - int buf_len; - struct urb *irq; - struct usb_device *udev; - struct input_dev *input; - char name[128]; - char phys[64]; -}; - -static struct usb_device_id touchkit_devices[] = { - {USB_DEVICE(0x3823, 0x0001)}, - {USB_DEVICE(0x0123, 0x0001)}, - {USB_DEVICE(0x0eef, 0x0001)}, - {USB_DEVICE(0x0eef, 0x0002)}, - {} -}; - -/* helpers to read the data */ -static inline int touchkit_get_touched(char *data) -{ - return (data[0] & TOUCHKIT_DOWN) ? 1 : 0; -} - -static inline int touchkit_get_x(char *data) -{ - return ((data[3] & 0x0F) << 7) | (data[4] & 0x7F); -} - -static inline int touchkit_get_y(char *data) -{ - return ((data[1] & 0x0F) << 7) | (data[2] & 0x7F); -} - - -/* processes one input packet. */ -static void touchkit_process_pkt(struct touchkit_usb *touchkit, char *pkt) -{ - int x, y; - - /* only process report packets */ - if ((pkt[0] & TOUCHKIT_PKT_TYPE_MASK) != TOUCHKIT_PKT_TYPE_REPT) - return; - - if (swap_xy) { - y = touchkit_get_x(pkt); - x = touchkit_get_y(pkt); - } else { - x = touchkit_get_x(pkt); - y = touchkit_get_y(pkt); - } - - input_report_key(touchkit->input, BTN_TOUCH, touchkit_get_touched(pkt)); - input_report_abs(touchkit->input, ABS_X, x); - input_report_abs(touchkit->input, ABS_Y, y); - input_sync(touchkit->input); -} - - -static int touchkit_get_pkt_len(char *buf) -{ - switch (buf[0] & TOUCHKIT_PKT_TYPE_MASK) { - case TOUCHKIT_PKT_TYPE_REPT: - return 5; - - case TOUCHKIT_PKT_TYPE_DIAG: - return buf[1] + 2; - } - - return 0; -} - -static void touchkit_process(struct touchkit_usb *touchkit, int len) -{ - char *buffer; - int pkt_len, buf_len, pos; - - /* if the buffer contains data, append */ - if (unlikely(touchkit->buf_len)) { - int tmp; - - /* if only 1 byte in buffer, add another one to get length */ - if (touchkit->buf_len == 1) - touchkit->buffer[1] = touchkit->data[0]; - - pkt_len = touchkit_get_pkt_len(touchkit->buffer); - - /* unknown packet: drop everything */ - if (!pkt_len) - return; - - /* append, process */ - tmp = pkt_len - touchkit->buf_len; - memcpy(touchkit->buffer + touchkit->buf_len, touchkit->data, tmp); - touchkit_process_pkt(touchkit, touchkit->buffer); - - buffer = touchkit->data + tmp; - buf_len = len - tmp; - } else { - buffer = touchkit->data; - buf_len = len; - } - - /* only one byte left in buffer */ - if (unlikely(buf_len == 1)) { - touchkit->buffer[0] = buffer[0]; - touchkit->buf_len = 1; - return; - } - - /* loop over the buffer */ - pos = 0; - while (pos < buf_len) { - /* get packet len */ - pkt_len = touchkit_get_pkt_len(buffer + pos); - - /* unknown packet: drop everything */ - if (unlikely(!pkt_len)) - return; - - /* full packet: process */ - if (likely(pkt_len <= buf_len)) { - touchkit_process_pkt(touchkit, buffer + pos); - } else { - /* incomplete packet: save in buffer */ - memcpy(touchkit->buffer, buffer + pos, buf_len - pos); - touchkit->buf_len = buf_len - pos; - } - pos += pkt_len; - } -} - - -static void touchkit_irq(struct urb *urb) -{ - struct touchkit_usb *touchkit = urb->context; - int retval; - - switch (urb->status) { - case 0: - /* success */ - break; - case -ETIME: - /* this urb is timing out */ - dbg("%s - urb timed out - was the device unplugged?", - __FUNCTION__); - return; - 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; - } - - touchkit_process(touchkit, urb->actual_length); - -exit: - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - err("%s - usb_submit_urb failed with result: %d", - __FUNCTION__, retval); -} - -static int touchkit_open(struct input_dev *input) -{ - struct touchkit_usb *touchkit = input->private; - - touchkit->irq->dev = touchkit->udev; - - if (usb_submit_urb(touchkit->irq, GFP_ATOMIC)) - return -EIO; - - return 0; -} - -static void touchkit_close(struct input_dev *input) -{ - struct touchkit_usb *touchkit = input->private; - - usb_kill_urb(touchkit->irq); -} - -static int touchkit_alloc_buffers(struct usb_device *udev, - struct touchkit_usb *touchkit) -{ - touchkit->data = usb_buffer_alloc(udev, TOUCHKIT_REPORT_DATA_SIZE, - GFP_ATOMIC, &touchkit->data_dma); - - if (!touchkit->data) - return -1; - - return 0; -} - -static void touchkit_free_buffers(struct usb_device *udev, - struct touchkit_usb *touchkit) -{ - if (touchkit->data) - usb_buffer_free(udev, TOUCHKIT_REPORT_DATA_SIZE, - touchkit->data, touchkit->data_dma); -} - -static int touchkit_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct touchkit_usb *touchkit; - struct input_dev *input_dev; - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct usb_device *udev = interface_to_usbdev(intf); - - interface = intf->cur_altsetting; - endpoint = &interface->endpoint[0].desc; - - touchkit = kzalloc(sizeof(struct touchkit_usb), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!touchkit || !input_dev) - goto out_free; - - if (touchkit_alloc_buffers(udev, touchkit)) - goto out_free; - - touchkit->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!touchkit->irq) { - dbg("%s - usb_alloc_urb failed: touchkit->irq", __FUNCTION__); - goto out_free_buffers; - } - - touchkit->udev = udev; - touchkit->input = input_dev; - - if (udev->manufacturer) - strlcpy(touchkit->name, udev->manufacturer, sizeof(touchkit->name)); - - if (udev->product) { - if (udev->manufacturer) - strlcat(touchkit->name, " ", sizeof(touchkit->name)); - strlcat(touchkit->name, udev->product, sizeof(touchkit->name)); - } - - if (!strlen(touchkit->name)) - snprintf(touchkit->name, sizeof(touchkit->name), - "USB Touchscreen %04x:%04x", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); - - usb_make_path(udev, touchkit->phys, sizeof(touchkit->phys)); - strlcpy(touchkit->phys, "/input0", sizeof(touchkit->phys)); - - input_dev->name = touchkit->name; - input_dev->phys = touchkit->phys; - usb_to_input_id(udev, &input_dev->id); - input_dev->cdev.dev = &intf->dev; - input_dev->private = touchkit; - input_dev->open = touchkit_open; - input_dev->close = touchkit_close; - - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); - input_set_abs_params(input_dev, ABS_X, TOUCHKIT_MIN_XC, TOUCHKIT_MAX_XC, - TOUCHKIT_XC_FUZZ, TOUCHKIT_XC_FLAT); - input_set_abs_params(input_dev, ABS_Y, TOUCHKIT_MIN_YC, TOUCHKIT_MAX_YC, - TOUCHKIT_YC_FUZZ, TOUCHKIT_YC_FLAT); - - usb_fill_int_urb(touchkit->irq, touchkit->udev, - usb_rcvintpipe(touchkit->udev, 0x81), - touchkit->data, TOUCHKIT_REPORT_DATA_SIZE, - touchkit_irq, touchkit, endpoint->bInterval); - - touchkit->irq->transfer_dma = touchkit->data_dma; - touchkit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - input_register_device(touchkit->input); - - usb_set_intfdata(intf, touchkit); - return 0; - -out_free_buffers: - touchkit_free_buffers(udev, touchkit); -out_free: - input_free_device(input_dev); - kfree(touchkit); - return -ENOMEM; -} - -static void touchkit_disconnect(struct usb_interface *intf) -{ - struct touchkit_usb *touchkit = usb_get_intfdata(intf); - - dbg("%s - called", __FUNCTION__); - - if (!touchkit) - return; - - dbg("%s - touchkit is initialized, cleaning up", __FUNCTION__); - usb_set_intfdata(intf, NULL); - usb_kill_urb(touchkit->irq); - input_unregister_device(touchkit->input); - usb_free_urb(touchkit->irq); - touchkit_free_buffers(interface_to_usbdev(intf), touchkit); - kfree(touchkit); -} - -MODULE_DEVICE_TABLE(usb, touchkit_devices); - -static struct usb_driver touchkit_driver = { - .name = "touchkitusb", - .probe = touchkit_probe, - .disconnect = touchkit_disconnect, - .id_table = touchkit_devices, -}; - -static int __init touchkit_init(void) -{ - return usb_register(&touchkit_driver); -} - -static void __exit touchkit_cleanup(void) -{ - usb_deregister(&touchkit_driver); -} - -module_init(touchkit_init); -module_exit(touchkit_cleanup); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c index 86e37a2..e082941 100644 --- a/drivers/usb/input/usbtouchscreen.c +++ b/drivers/usb/input/usbtouchscreen.c @@ -647,7 +647,7 @@ exit: static int usbtouch_open(struct input_dev *input) { - struct usbtouch_usb *usbtouch = input->private; + struct usbtouch_usb *usbtouch = input_get_drvdata(input); usbtouch->irq->dev = usbtouch->udev; @@ -659,7 +659,7 @@ static int usbtouch_open(struct input_dev *input) static void usbtouch_close(struct input_dev *input) { - struct usbtouch_usb *usbtouch = input->private; + struct usbtouch_usb *usbtouch = input_get_drvdata(input); usb_kill_urb(usbtouch->irq); } @@ -740,8 +740,10 @@ static int usbtouch_probe(struct usb_interface *intf, input_dev->name = usbtouch->name; input_dev->phys = usbtouch->phys; usb_to_input_id(udev, &input_dev->id); - input_dev->cdev.dev = &intf->dev; - input_dev->private = usbtouch; + input_dev->dev.parent = &intf->dev; + + input_set_drvdata(input_dev, usbtouch); + input_dev->open = usbtouch_open; input_dev->close = usbtouch_close; diff --git a/drivers/usb/input/wacom_sys.c b/drivers/usb/input/wacom_sys.c index 12b4274..1fe4820 100644 --- a/drivers/usb/input/wacom_sys.c +++ b/drivers/usb/input/wacom_sys.c @@ -122,7 +122,7 @@ void wacom_input_sync(void *wcombo) static int wacom_open(struct input_dev *dev) { - struct wacom *wacom = dev->private; + struct wacom *wacom = input_get_drvdata(dev); wacom->irq->dev = wacom->usbdev; if (usb_submit_urb(wacom->irq, GFP_KERNEL)) @@ -133,7 +133,7 @@ static int wacom_open(struct input_dev *dev) static void wacom_close(struct input_dev *dev) { - struct wacom *wacom = dev->private; + struct wacom *wacom = input_get_drvdata(dev); usb_kill_urb(wacom->irq); } @@ -201,6 +201,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i struct wacom *wacom; struct wacom_wac *wacom_wac; struct input_dev *input_dev; + int error = -ENOMEM; char rep_data[2], limit = 0; wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); @@ -229,8 +230,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i wacom->wacom_wac = wacom_wac; usb_to_input_id(dev, &input_dev->id); - input_dev->cdev.dev = &intf->dev; - input_dev->private = wacom; + input_dev->dev.parent = &intf->dev; + + input_set_drvdata(input_dev, wacom); + input_dev->open = wacom_open; input_dev->close = wacom_close; @@ -252,7 +255,9 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i wacom->irq->transfer_dma = wacom->data_dma; wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - input_register_device(wacom->dev); + error = input_register_device(wacom->dev); + if (error) + goto fail3; /* Ask the tablet to report tablet data. Repeat until it succeeds */ do { @@ -265,11 +270,12 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i usb_set_intfdata(intf, wacom); return 0; -fail2: usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma); -fail1: input_free_device(input_dev); + fail3: usb_free_urb(wacom->irq); + fail2: usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma); + fail1: input_free_device(input_dev); kfree(wacom); kfree(wacom_wac); - return -ENOMEM; + return error; } static void wacom_disconnect(struct usb_interface *intf) diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c index e4bc76e..7357239 100644 --- a/drivers/usb/input/xpad.c +++ b/drivers/usb/input/xpad.c @@ -267,7 +267,7 @@ exit: static int xpad_open (struct input_dev *dev) { - struct usb_xpad *xpad = dev->private; + struct usb_xpad *xpad = input_get_drvdata(dev); xpad->irq_in->dev = xpad->udev; if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) @@ -278,7 +278,7 @@ static int xpad_open (struct input_dev *dev) static void xpad_close (struct input_dev *dev) { - struct usb_xpad *xpad = dev->private; + struct usb_xpad *xpad = input_get_drvdata(dev); usb_kill_urb(xpad->irq_in); } @@ -312,6 +312,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id struct input_dev *input_dev; struct usb_endpoint_descriptor *ep_irq_in; int i; + int error = -ENOMEM; for (i = 0; xpad_device[i].idVendor; i++) { if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && @@ -344,8 +345,10 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id input_dev->name = xpad_device[i].name; input_dev->phys = xpad->phys; usb_to_input_id(udev, &input_dev->id); - input_dev->cdev.dev = &intf->dev; - input_dev->private = xpad; + input_dev->dev.parent = &intf->dev; + + input_set_drvdata(input_dev, xpad); + input_dev->open = xpad_open; input_dev->close = xpad_close; @@ -373,15 +376,18 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id xpad->irq_in->transfer_dma = xpad->idata_dma; xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - input_register_device(xpad->dev); + error = input_register_device(xpad->dev); + if (error) + goto fail3; usb_set_intfdata(intf, xpad); return 0; -fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); -fail1: input_free_device(input_dev); + fail3: usb_free_urb(xpad->irq_in); + fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); + fail1: input_free_device(input_dev); kfree(xpad); - return -ENOMEM; + return error; } diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c index caff8e6..c54f1a5 100644 --- a/drivers/usb/input/yealink.c +++ b/drivers/usb/input/yealink.c @@ -502,7 +502,7 @@ static int input_ev(struct input_dev *dev, unsigned int type, static int input_open(struct input_dev *dev) { - struct yealink_dev *yld = dev->private; + struct yealink_dev *yld = input_get_drvdata(dev); int i, ret; dbg("%s", __FUNCTION__); @@ -529,7 +529,7 @@ static int input_open(struct input_dev *dev) static void input_close(struct input_dev *dev) { - struct yealink_dev *yld = dev->private; + struct yealink_dev *yld = input_get_drvdata(dev); usb_kill_urb(yld->urb_ctl); usb_kill_urb(yld->urb_irq); @@ -937,9 +937,10 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) input_dev->name = nfo->name; input_dev->phys = yld->phys; usb_to_input_id(udev, &input_dev->id); - input_dev->cdev.dev = &intf->dev; + input_dev->dev.parent = &intf->dev; + + input_set_drvdata(input_dev, yld); - input_dev->private = yld; input_dev->open = input_open; input_dev->close = input_close; /* input_dev->event = input_ev; TODO */ @@ -955,7 +956,9 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) } } - input_register_device(yld->idev); + ret = input_register_device(yld->idev); + if (ret) + return usb_cleanup(yld, ret); usb_set_intfdata(intf, yld); diff --git a/include/asm-arm/arch-pxa/pxa27x_keyboard.h b/include/asm-arm/arch-pxa/pxa27x_keyboard.h new file mode 100644 index 0000000..3aaff92 --- /dev/null +++ b/include/asm-arm/arch-pxa/pxa27x_keyboard.h @@ -0,0 +1,13 @@ +#define PXAKBD_MAXROW 8 +#define PXAKBD_MAXCOL 8 + +struct pxa27x_keyboard_platform_data { + int nr_rows, nr_cols; + int keycodes[PXAKBD_MAXROW][PXAKBD_MAXCOL]; + int gpio_modes[PXAKBD_MAXROW + PXAKBD_MAXCOL]; + +#ifdef CONFIG_PM + u32 reg_kpc; + u32 reg_kprec; +#endif +}; diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h index 2b217c7..265d178 100644 --- a/include/linux/gpio_keys.h +++ b/include/linux/gpio_keys.h @@ -3,10 +3,11 @@ struct gpio_keys_button { /* Configuration parameters */ - int keycode; + int code; /* input event code (KEY_*, SW_*) */ int gpio; int active_low; char *desc; + int type; /* input event type (EV_KEY, EV_SW) */ }; struct gpio_keys_platform_data { diff --git a/include/linux/hp_sdc.h b/include/linux/hp_sdc.h index debd715..9db3d45 100644 --- a/include/linux/hp_sdc.h +++ b/include/linux/hp_sdc.h @@ -71,6 +71,7 @@ typedef struct { struct semaphore *semaphore; /* Semaphore to sleep on. */ } act; } hp_sdc_transaction; +int __hp_sdc_enqueue_transaction(hp_sdc_transaction *this); int hp_sdc_enqueue_transaction(hp_sdc_transaction *this); int hp_sdc_dequeue_transaction(hp_sdc_transaction *this); diff --git a/include/linux/input-polldev.h b/include/linux/input-polldev.h new file mode 100644 index 0000000..597a007 --- /dev/null +++ b/include/linux/input-polldev.h @@ -0,0 +1,46 @@ +#ifndef _INPUT_POLLDEV_H +#define _INPUT_POLLDEV_H + +/* + * Copyright (c) 2007 Dmitry Torokhov + * + * 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/input.h> +#include <linux/workqueue.h> + +/** + * struct input_polled_dev - simple polled input device + * @private: private driver data + * @flush: driver-supplied method that flushes device's state upon + * opening (optional) + * @poll: driver-supplied method that polls the device and posts + * input events (mandatory). + * @poll_interval: specifies how often the poll() method shoudl be called. + * @input: input device structire associated with the polled device. + * Must be properly initialized by the driver (id, name, phys, bits). + * + * Polled input device provides a skeleton for supporting simple input + * devices that do not raise interrupts but have to be periodically + * scanned or polled to detect changes in their state. + */ +struct input_polled_dev { + void *private; + + void (*flush)(struct input_polled_dev *dev); + void (*poll)(struct input_polled_dev *dev); + unsigned int poll_interval; /* msec */ + + struct input_dev *input; + struct delayed_work work; +}; + +struct input_polled_dev *input_allocate_polled_device(void); +void input_free_polled_device(struct input_polled_dev *dev); +int input_register_polled_device(struct input_polled_dev *dev); +void input_unregister_polled_device(struct input_polled_dev *dev); + +#endif diff --git a/include/linux/input.h b/include/linux/input.h index 3271225..439954d 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -506,6 +506,7 @@ struct input_absinfo { #define KEY_VOICEMAIL 0x1ac #define KEY_ADDRESSBOOK 0x1ad #define KEY_MESSENGER 0x1ae +#define KEY_DISPLAYTOGGLE 0x1af /* Turn display (LCD) on and off */ #define KEY_DEL_EOL 0x1c0 #define KEY_DEL_EOS 0x1c1 @@ -914,33 +915,6 @@ struct ff_effect { #define BIT(x) (1UL<<((x)%BITS_PER_LONG)) #define LONG(x) ((x)/BITS_PER_LONG) -#define INPUT_KEYCODE(dev, scancode) ((dev->keycodesize == 1) ? ((u8*)dev->keycode)[scancode] : \ - ((dev->keycodesize == 2) ? ((u16*)dev->keycode)[scancode] : (((u32*)dev->keycode)[scancode]))) - -#define SET_INPUT_KEYCODE(dev, scancode, val) \ - ({ unsigned __old; \ - switch (dev->keycodesize) { \ - case 1: { \ - u8 *k = (u8 *)dev->keycode; \ - __old = k[scancode]; \ - k[scancode] = val; \ - break; \ - } \ - case 2: { \ - u16 *k = (u16 *)dev->keycode; \ - __old = k[scancode]; \ - k[scancode] = val; \ - break; \ - } \ - default: { \ - u32 *k = (u32 *)dev->keycode; \ - __old = k[scancode]; \ - k[scancode] = val; \ - break; \ - } \ - } \ - __old; }) - struct input_dev { void *private; @@ -963,6 +937,8 @@ struct input_dev { unsigned int keycodemax; unsigned int keycodesize; void *keycode; + int (*setkeycode)(struct input_dev *dev, int scancode, int keycode); + int (*getkeycode)(struct input_dev *dev, int scancode, int *keycode); struct ff_device *ff; @@ -997,6 +973,9 @@ struct input_dev { unsigned int users; struct class_device cdev; + union { /* temporarily so while we switching to struct device */ + struct device *parent; + } dev; struct list_head h_list; struct list_head node; @@ -1075,7 +1054,7 @@ struct input_handler { void *private; void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value); - struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id); + int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id); void (*disconnect)(struct input_handle *handle); void (*start)(struct input_handle *handle); @@ -1105,7 +1084,7 @@ struct input_handle { }; #define to_dev(n) container_of(n,struct input_dev,node) -#define to_handler(n) container_of(n,struct input_handler,node); +#define to_handler(n) container_of(n,struct input_handler,node) #define to_handle(n) container_of(n,struct input_handle,d_node) #define to_handle_h(n) container_of(n,struct input_handle,h_node) @@ -1122,12 +1101,25 @@ static inline void input_put_device(struct input_dev *dev) class_device_put(&dev->cdev); } +static inline void *input_get_drvdata(struct input_dev *dev) +{ + return dev->private; +} + +static inline void input_set_drvdata(struct input_dev *dev, void *data) +{ + dev->private = data; +} + int input_register_device(struct input_dev *); void input_unregister_device(struct input_dev *); int input_register_handler(struct input_handler *); void input_unregister_handler(struct input_handler *); +int input_register_handle(struct input_handle *); +void input_unregister_handle(struct input_handle *); + int input_grab_device(struct input_handle *); void input_release_device(struct input_handle *); @@ -1169,6 +1161,8 @@ static inline void input_sync(struct input_dev *dev) input_event(dev, EV_SYN, SYN_REPORT, 0); } +void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code); + static inline void input_set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat) { dev->absmin[axis] = min; |