X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Finput%2Fmousedev.c;h=b685a507955d2c81aa5d6ad239d92d6a04c228a0;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=28ffa54d598851550b6c31aa16e3cbe8da657142;hpb=6a77f38946aaee1cd85eeec6cf4229b204c15071;p=linux-2.6.git diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 28ffa54d5..b685a5079 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -9,7 +9,7 @@ * the Free Software Foundation. */ -#define MOUSEDEV_MINOR_BASE 32 +#define MOUSEDEV_MINOR_BASE 32 #define MOUSEDEV_MINORS 32 #define MOUSEDEV_MIX 31 @@ -24,7 +24,6 @@ #include #include #include -#include #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX #include #endif @@ -41,15 +40,15 @@ MODULE_LICENSE("GPL"); #endif static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X; -module_param(xres, uint, 0); +module_param(xres, uint, 0644); MODULE_PARM_DESC(xres, "Horizontal screen resolution"); static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y; -module_param(yres, uint, 0); +module_param(yres, uint, 0644); MODULE_PARM_DESC(yres, "Vertical screen resolution"); static unsigned tap_time = 200; -module_param(tap_time, uint, 0); +module_param(tap_time, uint, 0644); MODULE_PARM_DESC(tap_time, "Tap time for touchpads in absolute mode (msecs)"); struct mousedev_hw_data { @@ -71,6 +70,7 @@ struct mousedev { struct mousedev_hw_data packet; unsigned int pkt_count; int old_x[4], old_y[4]; + int frac_dx, frac_dy; unsigned long touch; }; @@ -100,6 +100,7 @@ struct mousedev_list { unsigned char ready, buffer, bufsiz; unsigned char imexseq, impsseq; enum mousedev_emul mode; + unsigned long last_buttons; }; #define MOUSEDEV_SEQ_LEN 6 @@ -117,24 +118,31 @@ static struct mousedev mousedev_mix; static void mousedev_touchpad_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value) { - int size; + 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: - size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; - if (size == 0) size = xres; fx(0) = value; - if (mousedev->pkt_count >= 2) - mousedev->packet.dx = ((fx(0) - fx(1)) / 2 + (fx(1) - fx(2)) / 2) * xres / (size * 2); + 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; case ABS_Y: - size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y]; - if (size == 0) size = yres; fy(0) = value; - if (mousedev->pkt_count >= 2) - mousedev->packet.dy = -((fy(0) - fy(1)) / 2 + (fy(1) - fy(2)) / 2) * yres / (size * 2); + 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; } } @@ -147,7 +155,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, switch (code) { case ABS_X: size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; - if (size == 0) size = xres; + if (size == 0) size = xres ? : 1; if (value > dev->absmax[ABS_X]) value = dev->absmax[ABS_X]; if (value < dev->absmin[ABS_X]) value = dev->absmin[ABS_X]; mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size; @@ -156,7 +164,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, case ABS_Y: size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y]; - if (size == 0) size = yres; + if (size == 0) size = yres ? : 1; if (value > dev->absmax[ABS_Y]) value = dev->absmax[ABS_Y]; if (value < dev->absmin[ABS_Y]) value = dev->absmin[ABS_Y]; mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size; @@ -211,12 +219,13 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h struct mousedev_list *list; 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); p = &list->packets[list->head]; - if (list->ready && p->buttons != packet->buttons) { + 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]; @@ -241,13 +250,19 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h p->dz += packet->dz; p->buttons = mousedev->packet.buttons; - list->ready = 1; + if (p->dx || p->dy || p->dz || p->buttons != list->last_buttons) + list->ready = 1; spin_unlock_irqrestore(&list->packet_lock, flags); - kill_fasync(&list->fasync, SIGIO, POLL_IN); + + if (list->ready) { + kill_fasync(&list->fasync, SIGIO, POLL_IN); + wake_readers = 1; + } } - wake_up_interruptible(&mousedev->wait); + if (wake_readers) + wake_up_interruptible(&mousedev->wait); } static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) @@ -268,6 +283,8 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) clear_bit(0, &mousedev_mix.packet.buttons); } mousedev->touch = mousedev->pkt_count = 0; + mousedev->frac_dx = 0; + mousedev->frac_dy = 0; } else if (!mousedev->touch) @@ -339,7 +356,7 @@ static void mousedev_free(struct mousedev *mousedev) kfree(mousedev); } -static int mixdev_release(void) +static void mixdev_release(void) { struct input_handle *handle; @@ -353,8 +370,6 @@ static int mixdev_release(void) mousedev_free(mousedev); } } - - return 0; } static int mousedev_release(struct inode * inode, struct file * file) @@ -367,9 +382,8 @@ static int mousedev_release(struct inode * inode, struct file * file) if (!--list->mousedev->open) { if (list->mousedev->minor == MOUSEDEV_MIX) - return mixdev_release(); - - if (!mousedev_mix.open) { + mixdev_release(); + else if (!mousedev_mix.open) { if (list->mousedev->exist) input_close_device(&list->mousedev->handle); else @@ -398,9 +412,8 @@ static int mousedev_open(struct inode * inode, struct file * file) if (i >= MOUSEDEV_MINORS || !mousedev_table[i]) return -ENODEV; - if (!(list = kmalloc(sizeof(struct mousedev_list), GFP_KERNEL))) + if (!(list = kzalloc(sizeof(struct mousedev_list), GFP_KERNEL))) return -ENOMEM; - memset(list, 0, sizeof(struct mousedev_list)); spin_lock_init(&list->packet_lock); list->pos_x = xres / 2; @@ -445,7 +458,7 @@ static void mousedev_packet(struct mousedev_list *list, signed char *ps2_data) switch (list->mode) { case MOUSEDEV_EMUL_EXPS: - ps2_data[3] = mousedev_limit_delta(p->dz, 127); + 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; @@ -467,9 +480,10 @@ static void mousedev_packet(struct mousedev_list *list, signed char *ps2_data) } if (!p->dx && !p->dy && !p->dz) { - if (list->tail == list->head) + if (list->tail == list->head) { list->ready = 0; - else + list->last_buttons = p->buttons; + } else list->tail = (list->tail + 1) % PACKET_QUEUE_LEN; } @@ -585,12 +599,11 @@ static unsigned int mousedev_poll(struct file *file, poll_table *wait) { struct mousedev_list *list = file->private_data; poll_wait(file, &list->mousedev->wait, wait); - if (list->ready || list->buffer) - return POLLIN | POLLRDNORM; - return 0; + return ((list->ready || list->buffer) ? (POLLIN | POLLRDNORM) : 0) | + (list->mousedev->exist ? 0 : (POLLHUP | POLLERR)); } -struct file_operations mousedev_fops = { +static struct file_operations mousedev_fops = { .owner = THIS_MODULE, .read = mousedev_read, .write = mousedev_write, @@ -603,6 +616,7 @@ struct file_operations mousedev_fops = { static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id) { struct mousedev *mousedev; + struct class_device *cdev; int minor = 0; for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++); @@ -611,9 +625,8 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru return NULL; } - if (!(mousedev = kmalloc(sizeof(struct mousedev), GFP_KERNEL))) + if (!(mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL))) return NULL; - memset(mousedev, 0, sizeof(struct mousedev)); INIT_LIST_HEAD(&mousedev->list); init_waitqueue_head(&mousedev->wait); @@ -631,11 +644,13 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru mousedev_table[minor] = mousedev; - devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor), - S_IFCHR|S_IRUGO|S_IWUSR, "input/mouse%d", minor); - class_simple_device_add(input_class, - MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor), - dev->dev, "mouse%d", minor); + cdev = class_device_create(&input_class, &dev->cdev, + MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor), + dev->cdev.dev, mousedev->name); + + /* temporary symlink to keep userspace happy */ + sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj, + mousedev->name); return &mousedev->handle; } @@ -643,13 +658,18 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru static void mousedev_disconnect(struct input_handle *handle) { struct mousedev *mousedev = handle->private; + struct mousedev_list *list; - class_simple_device_remove(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor)); - devfs_remove("input/mouse%d", mousedev->minor); + sysfs_remove_link(&input_class.subsys.kset.kobj, mousedev->name); + class_device_destroy(&input_class, + MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor)); mousedev->exist = 0; 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); @@ -715,10 +735,8 @@ static int __init mousedev_init(void) mousedev_mix.exist = 1; mousedev_mix.minor = MOUSEDEV_MIX; - devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), - S_IFCHR|S_IRUGO|S_IWUSR, "input/mice"); - class_simple_device_add(input_class, MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), - NULL, "mice"); + class_device_create(&input_class, NULL, + MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice"); #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX if (!(psaux_registered = !misc_register(&psaux_mouse))) @@ -736,8 +754,8 @@ static void __exit mousedev_exit(void) if (psaux_registered) misc_deregister(&psaux_mouse); #endif - devfs_remove("input/mice"); - class_simple_device_remove(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX)); + class_device_destroy(&input_class, + MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX)); input_unregister_handler(&mousedev_handler); }