diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-08-02 18:35:17 -0700 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-08-02 18:35:17 -0700 |
commit | d01d0756f75e7a5b4b43764ad45b83c4340f11d6 (patch) | |
tree | 90db2ff7ccb35a8fdcf98366e6404afe1f845bc4 /drivers/input | |
parent | b326b853dca2f410b254198ee89abad71a2f4668 (diff) | |
parent | 0d87c7228a49e8342d60dd552892e470e0b291fa (diff) |
Merge branch 'next' into for-linus
Diffstat (limited to 'drivers/input')
41 files changed, 5760 insertions, 885 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 2ee6c7a68bdc..054edf346e0b 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -10,7 +10,8 @@ #define EVDEV_MINOR_BASE 64 #define EVDEV_MINORS 32 -#define EVDEV_BUFFER_SIZE 64 +#define EVDEV_MIN_BUFFER_SIZE 64U +#define EVDEV_BUF_PACKETS 8 #include <linux/poll.h> #include <linux/sched.h> @@ -23,7 +24,6 @@ #include "input-compat.h" struct evdev { - int exist; int open; int minor; struct input_handle handle; @@ -33,16 +33,18 @@ struct evdev { spinlock_t client_lock; /* protects client_list */ struct mutex mutex; struct device dev; + bool exist; }; struct evdev_client { - struct input_event buffer[EVDEV_BUFFER_SIZE]; int head; int tail; spinlock_t buffer_lock; /* protects access to buffer, head and tail */ struct fasync_struct *fasync; struct evdev *evdev; struct list_head node; + int bufsize; + struct input_event buffer[]; }; static struct evdev *evdev_table[EVDEV_MINORS]; @@ -52,11 +54,15 @@ static void evdev_pass_event(struct evdev_client *client, struct input_event *event) { /* - * Interrupts are disabled, just acquire the lock + * Interrupts are disabled, just acquire the lock. + * Make sure we don't leave with the client buffer + * "empty" by having client->head == client->tail. */ spin_lock(&client->buffer_lock); - client->buffer[client->head++] = *event; - client->head &= EVDEV_BUFFER_SIZE - 1; + do { + client->buffer[client->head++] = *event; + client->head &= client->bufsize - 1; + } while (client->head == client->tail); spin_unlock(&client->buffer_lock); if (event->type == EV_SYN) @@ -242,11 +248,21 @@ static int evdev_release(struct inode *inode, struct file *file) return 0; } +static unsigned int evdev_compute_buffer_size(struct input_dev *dev) +{ + unsigned int n_events = + max(dev->hint_events_per_packet * EVDEV_BUF_PACKETS, + EVDEV_MIN_BUFFER_SIZE); + + return roundup_pow_of_two(n_events); +} + static int evdev_open(struct inode *inode, struct file *file) { struct evdev *evdev; struct evdev_client *client; int i = iminor(inode) - EVDEV_MINOR_BASE; + unsigned int bufsize; int error; if (i >= EVDEV_MINORS) @@ -263,12 +279,17 @@ static int evdev_open(struct inode *inode, struct file *file) if (!evdev) return -ENODEV; - client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL); + bufsize = evdev_compute_buffer_size(evdev->handle.dev); + + client = kzalloc(sizeof(struct evdev_client) + + bufsize * sizeof(struct input_event), + GFP_KERNEL); if (!client) { error = -ENOMEM; goto err_put_evdev; } + client->bufsize = bufsize; spin_lock_init(&client->buffer_lock); client->evdev = evdev; evdev_attach_client(evdev, client); @@ -334,7 +355,7 @@ static int evdev_fetch_next_event(struct evdev_client *client, have_event = client->head != client->tail; if (have_event) { *event = client->buffer[client->tail++]; - client->tail &= EVDEV_BUFFER_SIZE - 1; + client->tail &= client->bufsize - 1; } spin_unlock_irq(&client->buffer_lock); @@ -382,10 +403,15 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait) { struct evdev_client *client = file->private_data; struct evdev *evdev = client->evdev; + unsigned int mask; poll_wait(file, &evdev->wait, wait); - return ((client->head == client->tail) ? 0 : (POLLIN | POLLRDNORM)) | - (evdev->exist ? 0 : (POLLHUP | POLLERR)); + + mask = evdev->exist ? POLLOUT | POLLWRNORM : POLLHUP | POLLERR; + if (client->head != client->tail) + mask |= POLLIN | POLLRDNORM; + + return mask; } #ifdef CONFIG_COMPAT @@ -665,6 +691,10 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, sizeof(struct input_absinfo)))) return -EFAULT; + /* We can't change number of reserved MT slots */ + if (t == ABS_MT_SLOT) + return -EINVAL; + /* * Take event lock to ensure that we are not * changing device parameters in the middle @@ -768,7 +798,7 @@ static void evdev_remove_chrdev(struct evdev *evdev) static void evdev_mark_dead(struct evdev *evdev) { mutex_lock(&evdev->mutex); - evdev->exist = 0; + evdev->exist = false; mutex_unlock(&evdev->mutex); } @@ -817,7 +847,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, init_waitqueue_head(&evdev->wait); dev_set_name(&evdev->dev, "event%d", minor); - evdev->exist = 1; + evdev->exist = true; evdev->minor = minor; evdev->handle.dev = input_get_device(dev); diff --git a/drivers/input/input.c b/drivers/input/input.c index 9c79bd56b51a..e1243b4b32a5 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -33,25 +33,6 @@ MODULE_LICENSE("GPL"); #define INPUT_DEVICES 256 -/* - * EV_ABS events which should not be cached are listed here. - */ -static unsigned int input_abs_bypass_init_data[] __initdata = { - ABS_MT_TOUCH_MAJOR, - ABS_MT_TOUCH_MINOR, - ABS_MT_WIDTH_MAJOR, - ABS_MT_WIDTH_MINOR, - ABS_MT_ORIENTATION, - ABS_MT_POSITION_X, - ABS_MT_POSITION_Y, - ABS_MT_TOOL_TYPE, - ABS_MT_BLOB_ID, - ABS_MT_TRACKING_ID, - ABS_MT_PRESSURE, - 0 -}; -static unsigned long input_abs_bypass[BITS_TO_LONGS(ABS_CNT)]; - static LIST_HEAD(input_dev_list); static LIST_HEAD(input_handler_list); @@ -181,6 +162,56 @@ static void input_stop_autorepeat(struct input_dev *dev) #define INPUT_PASS_TO_DEVICE 2 #define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE) +static int input_handle_abs_event(struct input_dev *dev, + unsigned int code, int *pval) +{ + bool is_mt_event; + int *pold; + + if (code == ABS_MT_SLOT) { + /* + * "Stage" the event; we'll flush it later, when we + * get actiual touch data. + */ + if (*pval >= 0 && *pval < dev->mtsize) + dev->slot = *pval; + + return INPUT_IGNORE_EVENT; + } + + is_mt_event = code >= ABS_MT_FIRST && code <= ABS_MT_LAST; + + if (!is_mt_event) { + pold = &dev->abs[code]; + } else if (dev->mt) { + struct input_mt_slot *mtslot = &dev->mt[dev->slot]; + pold = &mtslot->abs[code - ABS_MT_FIRST]; + } else { + /* + * Bypass filtering for multitouch events when + * not employing slots. + */ + pold = NULL; + } + + if (pold) { + *pval = input_defuzz_abs_event(*pval, *pold, + dev->absfuzz[code]); + if (*pold == *pval) + return INPUT_IGNORE_EVENT; + + *pold = *pval; + } + + /* Flush pending "slot" event */ + if (is_mt_event && dev->slot != dev->abs[ABS_MT_SLOT]) { + dev->abs[ABS_MT_SLOT] = dev->slot; + input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot); + } + + return INPUT_PASS_TO_HANDLERS; +} + static void input_handle_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { @@ -196,12 +227,12 @@ static void input_handle_event(struct input_dev *dev, case SYN_REPORT: if (!dev->sync) { - dev->sync = 1; + dev->sync = true; disposition = INPUT_PASS_TO_HANDLERS; } break; case SYN_MT_REPORT: - dev->sync = 0; + dev->sync = false; disposition = INPUT_PASS_TO_HANDLERS; break; } @@ -233,21 +264,9 @@ static void input_handle_event(struct input_dev *dev, break; case EV_ABS: - if (is_event_supported(code, dev->absbit, ABS_MAX)) { - - if (test_bit(code, input_abs_bypass)) { - disposition = INPUT_PASS_TO_HANDLERS; - break; - } + if (is_event_supported(code, dev->absbit, ABS_MAX)) + disposition = input_handle_abs_event(dev, code, &value); - value = input_defuzz_abs_event(value, - dev->abs[code], dev->absfuzz[code]); - - if (dev->abs[code] != value) { - dev->abs[code] = value; - disposition = INPUT_PASS_TO_HANDLERS; - } - } break; case EV_REL: @@ -298,7 +317,7 @@ static void input_handle_event(struct input_dev *dev, } if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN) - dev->sync = 0; + dev->sync = false; if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event) dev->event(dev, type, code, value); @@ -528,12 +547,30 @@ void input_close_device(struct input_handle *handle) EXPORT_SYMBOL(input_close_device); /* + * Simulate keyup events for all keys that are marked as pressed. + * The function must be called with dev->event_lock held. + */ +static void input_dev_release_keys(struct input_dev *dev) +{ + int code; + + if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) { + for (code = 0; code <= KEY_MAX; code++) { + if (is_event_supported(code, dev->keybit, KEY_MAX) && + __test_and_clear_bit(code, dev->key)) { + input_pass_event(dev, EV_KEY, code, 0); + } + } + input_pass_event(dev, EV_SYN, SYN_REPORT, 1); + } +} + +/* * Prepare device for unregistering */ static void input_disconnect_device(struct input_dev *dev) { struct input_handle *handle; - int code; /* * Mark device as going away. Note that we take dev->mutex here @@ -552,15 +589,7 @@ static void input_disconnect_device(struct input_dev *dev) * generate events even after we done here but they will not * reach any handlers. */ - if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) { - for (code = 0; code <= KEY_MAX; code++) { - if (is_event_supported(code, dev->keybit, KEY_MAX) && - __test_and_clear_bit(code, dev->key)) { - input_pass_event(dev, EV_KEY, code, 0); - } - } - input_pass_event(dev, EV_SYN, SYN_REPORT, 1); - } + input_dev_release_keys(dev); list_for_each_entry(handle, &dev->h_list, d_node) handle->open = 0; @@ -684,7 +713,7 @@ int input_set_keycode(struct input_dev *dev, unsigned int scancode, unsigned int keycode) { unsigned long flags; - int old_keycode; + unsigned int old_keycode; int retval; if (keycode > KEY_MAX) @@ -1278,6 +1307,7 @@ static void input_dev_release(struct device *device) struct input_dev *dev = to_input_dev(device); input_ff_destroy(dev); + input_mt_destroy_slots(dev); kfree(dev); module_put(THIS_MODULE); @@ -1433,6 +1463,15 @@ static int input_dev_resume(struct device *dev) mutex_lock(&input_dev->mutex); input_dev_reset(input_dev, true); + + /* + * Keys that have been pressed at suspend time are unlikely + * to be still pressed when we resume. + */ + spin_lock_irq(&input_dev->event_lock); + input_dev_release_keys(input_dev); + spin_unlock_irq(&input_dev->event_lock); + mutex_unlock(&input_dev->mutex); return 0; @@ -1518,6 +1557,45 @@ void input_free_device(struct input_dev *dev) EXPORT_SYMBOL(input_free_device); /** + * input_mt_create_slots() - create MT input slots + * @dev: input device supporting MT events and finger tracking + * @num_slots: number of slots used by the device + * + * This function allocates all necessary memory for MT slot handling + * in the input device, and adds ABS_MT_SLOT to the device capabilities. + */ +int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots) +{ + if (!num_slots) + return 0; + + dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL); + if (!dev->mt) + return -ENOMEM; + + dev->mtsize = num_slots; + input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0); + + return 0; +} +EXPORT_SYMBOL(input_mt_create_slots); + +/** + * input_mt_destroy_slots() - frees the MT slots of the input device + * @dev: input device with allocated MT slots + * + * This function is only needed in error path as the input core will + * automatically free the MT slots when the device is destroyed. + */ +void input_mt_destroy_slots(struct input_dev *dev) +{ + kfree(dev->mt); + dev->mt = NULL; + dev->mtsize = 0; +} +EXPORT_SYMBOL(input_mt_destroy_slots); + +/** * 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...) @@ -1926,20 +2004,10 @@ static const struct file_operations input_fops = { .open = input_open_file, }; -static void __init input_init_abs_bypass(void) -{ - const unsigned int *p; - - for (p = input_abs_bypass_init_data; *p; p++) - input_abs_bypass[BIT_WORD(*p)] |= BIT_MASK(*p); -} - static int __init input_init(void) { int err; - input_init_abs_bypass(); - err = class_register(&input_class); if (err) { printk(KERN_ERR "input: unable to register input_dev class\n"); diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 34157bb97ed6..63834585c283 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -37,7 +37,6 @@ MODULE_LICENSE("GPL"); #define JOYDEV_BUFFER_SIZE 64 struct joydev { - int exist; int open; int minor; struct input_handle handle; @@ -46,6 +45,7 @@ struct joydev { spinlock_t client_lock; /* protects client_list */ struct mutex mutex; struct device dev; + bool exist; struct js_corr corr[ABS_CNT]; struct JS_DATA_SAVE_TYPE glue; @@ -760,7 +760,7 @@ static void joydev_remove_chrdev(struct joydev *joydev) static void joydev_mark_dead(struct joydev *joydev) { mutex_lock(&joydev->mutex); - joydev->exist = 0; + joydev->exist = false; mutex_unlock(&joydev->mutex); } @@ -817,10 +817,9 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, init_waitqueue_head(&joydev->wait); dev_set_name(&joydev->dev, "js%d", minor); - joydev->exist = 1; + joydev->exist = true; joydev->minor = minor; - joydev->exist = 1; joydev->handle.dev = input_get_device(dev); joydev->handle.name = dev_name(&joydev->dev); joydev->handle.handler = handler; diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index a2b426d6a4ec..269a846f3694 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -9,6 +9,7 @@ * 2005 Dominic Cerquetti <binary1230@yahoo.com> * 2006 Adam Buchbinder <adam.buchbinder@gmail.com> * 2007 Jan Kratochvil <honza@jikos.cz> + * 2010 Christoph Fritz <chf.fritz@googlemail.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -88,6 +89,9 @@ but we map them to axes when possible to simplify things */ #define MAP_DPAD_TO_BUTTONS (1 << 0) #define MAP_TRIGGERS_TO_BUTTONS (1 << 1) +#define MAP_STICKS_TO_NULL (1 << 2) +#define DANCEPAD_MAP_CONFIG (MAP_DPAD_TO_BUTTONS | \ + MAP_TRIGGERS_TO_BUTTONS | MAP_STICKS_TO_NULL) #define XTYPE_XBOX 0 #define XTYPE_XBOX360 1 @@ -102,6 +106,10 @@ static int triggers_to_buttons; module_param(triggers_to_buttons, bool, S_IRUGO); MODULE_PARM_DESC(triggers_to_buttons, "Map triggers to buttons rather than axes for unknown pads"); +static int sticks_to_null; +module_param(sticks_to_null, bool, S_IRUGO); +MODULE_PARM_DESC(sticks_to_null, "Do not map sticks at all for unknown pads"); + static const struct xpad_device { u16 idVendor; u16 idProduct; @@ -114,7 +122,7 @@ static const struct xpad_device { { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", 0, XTYPE_XBOX }, { 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX }, { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, - { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, + { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", DANCEPAD_MAP_CONFIG, XTYPE_XBOX }, { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, { 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 }, { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX }, @@ -159,7 +167,7 @@ static const struct xpad_device { /* buttons shared with xbox and xbox360 */ static const signed short xpad_common_btn[] = { BTN_A, BTN_B, BTN_X, BTN_Y, /* "analog" buttons */ - BTN_START, BTN_BACK, BTN_THUMBL, BTN_THUMBR, /* start/back/sticks */ + BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR, /* start/back/sticks */ -1 /* terminating entry */ }; @@ -169,10 +177,10 @@ static const signed short xpad_btn[] = { -1 /* terminating entry */ }; -/* used when dpad is mapped to nuttons */ +/* used when dpad is mapped to buttons */ static const signed short xpad_btn_pad[] = { - BTN_LEFT, BTN_RIGHT, /* d-pad left, right */ - BTN_0, BTN_1, /* d-pad up, down (XXX names??) */ + BTN_TRIGGER_HAPPY1, BTN_TRIGGER_HAPPY2, /* d-pad left, right */ + BTN_TRIGGER_HAPPY3, BTN_TRIGGER_HAPPY4, /* d-pad up, down */ -1 /* terminating entry */ }; @@ -280,17 +288,19 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d { struct input_dev *dev = xpad->dev; - /* left stick */ - input_report_abs(dev, ABS_X, - (__s16) le16_to_cpup((__le16 *)(data + 12))); - input_report_abs(dev, ABS_Y, - ~(__s16) le16_to_cpup((__le16 *)(data + 14))); - - /* right stick */ - input_report_abs(dev, ABS_RX, - (__s16) le16_to_cpup((__le16 *)(data + 16))); - input_report_abs(dev, ABS_RY, - ~(__s16) le16_to_cpup((__le16 *)(data + 18))); + if (!(xpad->mapping & MAP_STICKS_TO_NULL)) { + /* left stick */ + input_report_abs(dev, ABS_X, + (__s16) le16_to_cpup((__le16 *)(data + 12))); + input_report_abs(dev, ABS_Y, + ~(__s16) le16_to_cpup((__le16 *)(data + 14))); + + /* right stick */ + input_report_abs(dev, ABS_RX, + (__s16) le16_to_cpup((__le16 *)(data + 16))); + input_report_abs(dev, ABS_RY, + ~(__s16) le16_to_cpup((__le16 *)(data + 18))); + } /* triggers left/right */ if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) { @@ -303,10 +313,11 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d /* digital pad */ if (xpad->mapping & MAP_DPAD_TO_BUTTONS) { - input_report_key(dev, BTN_LEFT, data[2] & 0x04); - input_report_key(dev, BTN_RIGHT, data[2] & 0x08); - input_report_key(dev, BTN_0, data[2] & 0x01); /* up */ - input_report_key(dev, BTN_1, data[2] & 0x02); /* down */ + /* dpad as buttons (left, right, up, down) */ + input_report_key(dev, BTN_TRIGGER_HAPPY1, data[2] & 0x04); + input_report_key(dev, BTN_TRIGGER_HAPPY2, data[2] & 0x08); + input_report_key(dev, BTN_TRIGGER_HAPPY3, data[2] & 0x01); + input_report_key(dev, BTN_TRIGGER_HAPPY4, data[2] & 0x02); } else { input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); @@ -316,7 +327,7 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d /* start/back buttons and stick press left/right */ input_report_key(dev, BTN_START, data[2] & 0x10); - input_report_key(dev, BTN_BACK, data[2] & 0x20); + input_report_key(dev, BTN_SELECT, data[2] & 0x20); input_report_key(dev, BTN_THUMBL, data[2] & 0x40); input_report_key(dev, BTN_THUMBR, data[2] & 0x80); @@ -350,11 +361,11 @@ static void xpad360_process_packet(struct usb_xpad *xpad, /* digital pad */ if (xpad->mapping & MAP_DPAD_TO_BUTTONS) { - /* dpad as buttons (right, left, down, up) */ - input_report_key(dev, BTN_LEFT, data[2] & 0x04); - input_report_key(dev, BTN_RIGHT, data[2] & 0x08); - input_report_key(dev, BTN_0, data[2] & 0x01); /* up */ - input_report_key(dev, BTN_1, data[2] & 0x02); /* down */ + /* dpad as buttons (left, right, up, down) */ + input_report_key(dev, BTN_TRIGGER_HAPPY1, data[2] & 0x04); + input_report_key(dev, BTN_TRIGGER_HAPPY2, data[2] & 0x08); + input_report_key(dev, BTN_TRIGGER_HAPPY3, data[2] & 0x01); + input_report_key(dev, BTN_TRIGGER_HAPPY4, data[2] & 0x02); } else { input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); @@ -364,7 +375,7 @@ static void xpad360_process_packet(struct usb_xpad *xpad, /* start/back buttons */ input_report_key(dev, BTN_START, data[2] & 0x10); - input_report_key(dev, BTN_BACK, data[2] & 0x20); + input_report_key(dev, BTN_SELECT, data[2] & 0x20); /* stick press left/right */ input_report_key(dev, BTN_THUMBL, data[2] & 0x40); @@ -379,17 +390,19 @@ static void xpad360_process_packet(struct usb_xpad *xpad, input_report_key(dev, BTN_TR, data[3] & 0x02); input_report_key(dev, BTN_MODE, data[3] & 0x04); - /* left stick */ - input_report_abs(dev, ABS_X, - (__s16) le16_to_cpup((__le16 *)(data + 6))); - input_report_abs(dev, ABS_Y, - ~(__s16) le16_to_cpup((__le16 *)(data + 8))); - - /* right stick */ - input_report_abs(dev, ABS_RX, - (__s16) le16_to_cpup((__le16 *)(data + 10))); - input_report_abs(dev, ABS_RY, - ~(__s16) le16_to_cpup((__le16 *)(data + 12))); + if (!(xpad->mapping & MAP_STICKS_TO_NULL)) { + /* left stick */ + input_report_abs(dev, ABS_X, + (__s16) le16_to_cpup((__le16 *)(data + 6))); + input_report_abs(dev, ABS_Y, + ~(__s16) le16_to_cpup((__le16 *)(data + 8))); + + /* right stick */ + input_report_abs(dev, ABS_RX, + (__s16) le16_to_cpup((__le16 *)(data + 10))); + input_report_abs(dev, ABS_RY, + ~(__s16) le16_to_cpup((__le16 *)(data + 12))); + } /* triggers left/right */ if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) { @@ -815,6 +828,8 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id xpad->mapping |= MAP_DPAD_TO_BUTTONS; if (triggers_to_buttons) xpad->mapping |= MAP_TRIGGERS_TO_BUTTONS; + if (sticks_to_null) + xpad->mapping |= MAP_STICKS_TO_NULL; } xpad->dev = input_dev; @@ -831,16 +846,20 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id input_dev->open = xpad_open; input_dev->close = xpad_close; - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + input_dev->evbit[0] = BIT_MASK(EV_KEY); + + if (!(xpad->mapping & MAP_STICKS_TO_NULL)) { + input_dev->evbit[0] |= BIT_MASK(EV_ABS); + /* set up axes */ + for (i = 0; xpad_abs[i] >= 0; i++) + xpad_set_up_abs(input_dev, xpad_abs[i]); + } - /* set up standard buttons and axes */ + /* set up standard buttons */ for (i = 0; xpad_common_btn[i] >= 0; i++) __set_bit(xpad_common_btn[i], input_dev->keybit); - for (i = 0; xpad_abs[i] >= 0; i++) - xpad_set_up_abs(input_dev, xpad_abs[i]); - - /* Now set up model-specific ones */ + /* set up model-specific ones */ if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W) { for (i = 0; xpad360_btn[i] >= 0; i++) __set_bit(xpad360_btn[i], input_dev->keybit); diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index c96ccc136492..dd4937f4815e 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -297,6 +297,18 @@ config KEYBOARD_MAX7359 To compile this driver as a module, choose M here: the module will be called max7359_keypad. +config KEYBOARD_MCS + tristate "MELFAS MCS Touchkey" + depends on I2C + help + Say Y here if you have the MELFAS MCS5000/5080 touchkey controller + chip in your system. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called mcs_touchkey. + config KEYBOARD_IMX tristate "IMX keypad support" depends on ARCH_MXC @@ -342,6 +354,15 @@ config KEYBOARD_PXA930_ROTARY To compile this driver as a module, choose M here: the module will be called pxa930_rotary. +config KEYBOARD_SAMSUNG + tristate "Samsung keypad support" + depends on SAMSUNG_DEV_KEYPAD + help + Say Y here if you want to use the Samsung keypad. + + To compile this driver as a module, choose M here: the + module will be called samsung-keypad. + config KEYBOARD_STOWAWAY tristate "Stowaway keyboard" select SERIO diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 4596d0c6f922..1a66d5f1ca8b 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -26,12 +26,14 @@ obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o obj-$(CONFIG_KEYBOARD_MAX7359) += max7359_keypad.o +obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o |