diff options
Diffstat (limited to 'drivers/usb/input')
-rw-r--r-- | drivers/usb/input/ati_remote.c | 174 | ||||
-rw-r--r-- | drivers/usb/input/hid-input.c | 3 | ||||
-rw-r--r-- | drivers/usb/input/hiddev.c | 72 |
3 files changed, 139 insertions, 110 deletions
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index 05d2d60..3719fcb 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c @@ -111,14 +111,28 @@ #define NAME_BUFSIZE 80 /* size of product name, path buffers */ #define DATA_BUFSIZE 63 /* size of URB data buffers */ +/* + * Duplicate event filtering time. + * Sequential, identical KIND_FILTERED inputs with less than + * FILTER_TIME milliseconds between them are considered as repeat + * events. The hardware generates 5 events for the first keypress + * and we have to take this into account for an accurate repeat + * behaviour. + */ +#define FILTER_TIME 60 /* msec */ + static unsigned long channel_mask; -module_param(channel_mask, ulong, 0444); +module_param(channel_mask, ulong, 0644); MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); static int debug; -module_param(debug, int, 0444); +module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); +static int repeat_filter = FILTER_TIME; +module_param(repeat_filter, int, 0644); +MODULE_PARM_DESC(repeat_filter, "Repeat filter time, default = 60 msec"); + #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) @@ -143,19 +157,6 @@ MODULE_DEVICE_TABLE(usb, ati_remote_table); static char init1[] = { 0x01, 0x00, 0x20, 0x14 }; static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; -/* Acceleration curve for directional control pad */ -static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; - -/* Duplicate event filtering time. - * Sequential, identical KIND_FILTERED inputs with less than - * FILTER_TIME jiffies between them are considered as repeat - * events. The hardware generates 5 events for the first keypress - * and we have to take this into account for an accurate repeat - * behaviour. - * (HZ / 20) == 50 ms and works well for me. - */ -#define FILTER_TIME (HZ / 20) - struct ati_remote { struct input_dev *idev; struct usb_device *udev; @@ -413,6 +414,43 @@ static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) } /* + * ati_remote_compute_accel + * + * Implements acceleration curve for directional control pad + * If elapsed time since last event is > 1/4 second, user "stopped", + * so reset acceleration. Otherwise, user is probably holding the control + * pad down, so we increase acceleration, ramping up over two seconds to + * a maximum speed. + */ +static int ati_remote_compute_accel(struct ati_remote *ati_remote) +{ + static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; + unsigned long now = jiffies; + int acc; + + if (time_after(now, ati_remote->old_jiffies + msecs_to_jiffies(250))) { + acc = 1; + ati_remote->acc_jiffies = now; + } + else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(125))) + acc = accel[0]; + else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(250))) + acc = accel[1]; + else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(500))) + acc = accel[2]; + else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1000))) + acc = accel[3]; + else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1500))) + acc = accel[4]; + else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(2000))) + acc = accel[5]; + else + acc = accel[6]; + + return acc; +} + +/* * ati_remote_report_input */ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) @@ -465,9 +503,9 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) if (ati_remote_tbl[index].kind == KIND_FILTERED) { /* 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 + FILTER_TIME)) { + 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))) { ati_remote->repeat_count++; } else { ati_remote->repeat_count = 0; @@ -477,75 +515,61 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) ati_remote->old_data[1] = data[2]; ati_remote->old_jiffies = jiffies; - if ((ati_remote->repeat_count > 0) - && (ati_remote->repeat_count < 5)) + if (ati_remote->repeat_count > 0 && + ati_remote->repeat_count < 5) return; input_regs(dev, regs); input_event(dev, ati_remote_tbl[index].type, ati_remote_tbl[index].code, 1); + input_sync(dev); input_event(dev, ati_remote_tbl[index].type, ati_remote_tbl[index].code, 0); input_sync(dev); - return; - } + } else { - /* - * Other event kinds are from the directional control pad, and have an - * acceleration factor applied to them. Without this acceleration, the - * control pad is mostly unusable. - * - * If elapsed time since last event is > 1/4 second, user "stopped", - * so reset acceleration. Otherwise, user is probably holding the control - * pad down, so we increase acceleration, ramping up over two seconds to - * a maximum speed. The acceleration curve is #defined above. - */ - if (time_after(jiffies, ati_remote->old_jiffies + (HZ >> 2))) { - acc = 1; - ati_remote->acc_jiffies = jiffies; - } - else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 3))) acc = accel[0]; - else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 2))) acc = accel[1]; - else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 1))) acc = accel[2]; - else if (time_before(jiffies, ati_remote->acc_jiffies + HZ)) acc = accel[3]; - else if (time_before(jiffies, ati_remote->acc_jiffies + HZ+(HZ>>1))) acc = accel[4]; - else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ << 1))) acc = accel[5]; - else acc = accel[6]; - - input_regs(dev, regs); - switch (ati_remote_tbl[index].kind) { - case KIND_ACCEL: - input_event(dev, ati_remote_tbl[index].type, - ati_remote_tbl[index].code, - ati_remote_tbl[index].value * acc); - break; - case KIND_LU: - input_report_rel(dev, REL_X, -acc); - input_report_rel(dev, REL_Y, -acc); - break; - case KIND_RU: - input_report_rel(dev, REL_X, acc); - input_report_rel(dev, REL_Y, -acc); - break; - case KIND_LD: - input_report_rel(dev, REL_X, -acc); - input_report_rel(dev, REL_Y, acc); - break; - case KIND_RD: - input_report_rel(dev, REL_X, acc); - input_report_rel(dev, REL_Y, acc); - break; - default: - dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", - ati_remote_tbl[index].kind); - } - input_sync(dev); + /* + * Other event kinds are from the directional control pad, and have an + * acceleration factor applied to them. Without this acceleration, the + * control pad is mostly unusable. + */ + acc = ati_remote_compute_accel(ati_remote); + + input_regs(dev, regs); + switch (ati_remote_tbl[index].kind) { + case KIND_ACCEL: + input_event(dev, ati_remote_tbl[index].type, + ati_remote_tbl[index].code, + ati_remote_tbl[index].value * acc); + break; + case KIND_LU: + input_report_rel(dev, REL_X, -acc); + input_report_rel(dev, REL_Y, -acc); + break; + case KIND_RU: + input_report_rel(dev, REL_X, acc); + input_report_rel(dev, REL_Y, -acc); + break; + case KIND_LD: + input_report_rel(dev, REL_X, -acc); + input_report_rel(dev, REL_Y, acc); + break; + case KIND_RD: + input_report_rel(dev, REL_X, acc); + input_report_rel(dev, REL_Y, acc); + break; + default: + dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", + ati_remote_tbl[index].kind); + } + input_sync(dev); - ati_remote->old_jiffies = jiffies; - ati_remote->old_data[0] = data[1]; - ati_remote->old_data[1] = data[2]; + ati_remote->old_jiffies = jiffies; + ati_remote->old_data[0] = data[1]; + ati_remote->old_data[1] = data[2]; + } } /* diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 028e1ad..7208839 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c @@ -607,7 +607,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel } - if (usage->hat_min < usage->hat_max || usage->hat_dir) { + if (usage->type == EV_ABS && + (usage->hat_min < usage->hat_max || usage->hat_dir)) { int i; for (i = usage->code; i < usage->code + 2 && i <= max; i++) { input_set_abs_params(input, i, -1, 1, 0, 0); diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c index 70477f0..f6b839c 100644 --- a/drivers/usb/input/hiddev.c +++ b/drivers/usb/input/hiddev.c @@ -49,7 +49,7 @@ struct hiddev { int open; wait_queue_head_t wait; struct hid_device *hid; - struct hiddev_list *list; + struct list_head list; }; struct hiddev_list { @@ -59,7 +59,7 @@ struct hiddev_list { unsigned flags; struct fasync_struct *fasync; struct hiddev *hiddev; - struct hiddev_list *next; + struct list_head node; }; static struct hiddev *hiddev_table[HIDDEV_MINORS]; @@ -73,12 +73,15 @@ static struct hiddev *hiddev_table[HIDDEV_MINORS]; static struct hid_report * hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) { - unsigned flags = rinfo->report_id & ~HID_REPORT_ID_MASK; + unsigned int flags = rinfo->report_id & ~HID_REPORT_ID_MASK; + unsigned int rid = rinfo->report_id & HID_REPORT_ID_MASK; struct hid_report_enum *report_enum; + struct hid_report *report; struct list_head *list; if (rinfo->report_type < HID_REPORT_TYPE_MIN || - rinfo->report_type > HID_REPORT_TYPE_MAX) return NULL; + rinfo->report_type > HID_REPORT_TYPE_MAX) + return NULL; report_enum = hid->report_enum + (rinfo->report_type - HID_REPORT_TYPE_MIN); @@ -88,21 +91,25 @@ hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) break; case HID_REPORT_ID_FIRST: - list = report_enum->report_list.next; - if (list == &report_enum->report_list) + if (list_empty(&report_enum->report_list)) return NULL; - rinfo->report_id = ((struct hid_report *) list)->id; + + list = report_enum->report_list.next; + report = list_entry(list, struct hid_report, list); + rinfo->report_id = report->id; break; case HID_REPORT_ID_NEXT: - list = (struct list_head *) - report_enum->report_id_hash[rinfo->report_id & HID_REPORT_ID_MASK]; - if (list == NULL) + report = report_enum->report_id_hash[rid]; + if (!report) return NULL; - list = list->next; + + list = report->list.next; if (list == &report_enum->report_list) return NULL; - rinfo->report_id = ((struct hid_report *) list)->id; + + report = list_entry(list, struct hid_report, list); + rinfo->report_id = report->id; break; default: @@ -125,12 +132,13 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref) struct hid_field *field; if (uref->report_type < HID_REPORT_TYPE_MIN || - uref->report_type > HID_REPORT_TYPE_MAX) return NULL; + uref->report_type > HID_REPORT_TYPE_MAX) + return NULL; report_enum = hid->report_enum + (uref->report_type - HID_REPORT_TYPE_MIN); - list_for_each_entry(report, &report_enum->report_list, list) + list_for_each_entry(report, &report_enum->report_list, list) { for (i = 0; i < report->maxfield; i++) { field = report->field[i]; for (j = 0; j < field->maxusage; j++) { @@ -142,6 +150,7 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref) } } } + } return NULL; } @@ -150,9 +159,9 @@ static void hiddev_send_event(struct hid_device *hid, struct hiddev_usage_ref *uref) { struct hiddev *hiddev = hid->hiddev; - struct hiddev_list *list = hiddev->list; + struct hiddev_list *list; - while (list) { + list_for_each_entry(list, &hiddev->list, node) { if (uref->field_index != HID_FIELD_INDEX_NONE || (list->flags & HIDDEV_FLAG_REPORT) != 0) { list->buffer[list->head] = *uref; @@ -160,8 +169,6 @@ static void hiddev_send_event(struct hid_device *hid, (HIDDEV_BUFFER_SIZE - 1); kill_fasync(&list->fasync, SIGIO, POLL_IN); } - - list = list->next; } wake_up_interruptible(&hiddev->wait); @@ -180,7 +187,7 @@ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, uref.report_type = (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : - ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); + ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); uref.report_id = field->report->id; uref.field_index = field->index; uref.usage_index = (usage - field->usage); @@ -200,7 +207,7 @@ void hiddev_report_event(struct hid_device *hid, struct hid_report *report) uref.report_type = (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : - ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); + ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); uref.report_id = report->id; uref.field_index = HID_FIELD_INDEX_NONE; @@ -213,7 +220,9 @@ static int hiddev_fasync(int fd, struct file *file, int on) { int retval; struct hiddev_list *list = file->private_data; + retval = fasync_helper(fd, file, on, &list->fasync); + return retval < 0 ? retval : 0; } @@ -224,14 +233,9 @@ static int hiddev_fasync(int fd, struct file *file, int on) static int hiddev_release(struct inode * inode, struct file * file) { struct hiddev_list *list = file->private_data; - struct hiddev_list **listptr; - listptr = &list->hiddev->list; hiddev_fasync(-1, file, 0); - - while (*listptr && (*listptr != list)) - listptr = &((*listptr)->next); - *listptr = (*listptr)->next; + list_del(&list->node); if (!--list->hiddev->open) { if (list->hiddev->exist) @@ -248,7 +252,8 @@ static int hiddev_release(struct inode * inode, struct file * file) /* * open file op */ -static int hiddev_open(struct inode * inode, struct file * file) { +static int hiddev_open(struct inode *inode, struct file *file) +{ struct hiddev_list *list; int i = iminor(inode) - HIDDEV_MINOR_BASE; @@ -260,9 +265,7 @@ static int hiddev_open(struct inode * inode, struct file * file) { return -ENOMEM; list->hiddev = hiddev_table[i]; - list->next = hiddev_table[i]->list; - hiddev_table[i]->list = list; - + list_add_tail(&list->node, &hiddev_table[i]->list); file->private_data = list; if (!list->hiddev->open++) @@ -362,6 +365,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun static unsigned int hiddev_poll(struct file *file, poll_table *wait) { struct hiddev_list *list = file->private_data; + poll_wait(file, &list->hiddev->wait, wait); if (list->head != list->tail) return POLLIN | POLLRDNORM; @@ -382,7 +386,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd struct hiddev_collection_info cinfo; struct hiddev_report_info rinfo; struct hiddev_field_info finfo; - struct hiddev_usage_ref_multi *uref_multi=NULL; + struct hiddev_usage_ref_multi *uref_multi = NULL; struct hiddev_usage_ref *uref; struct hiddev_devinfo dinfo; struct hid_report *report; @@ -764,15 +768,15 @@ int hiddev_connect(struct hid_device *hid) } init_waitqueue_head(&hiddev->wait); - - hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; - + INIT_LIST_HEAD(&hiddev->list); hiddev->hid = hid; hiddev->exist = 1; hid->minor = hid->intf->minor; hid->hiddev = hiddev; + hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; + return 0; } |