LCOV - code coverage report
Current view: top level - drivers/input - mousedev.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 592 597 99.2 %
Date: 2017-01-25 Functions: 35 36 97.2 %

          Line data    Source code
       1             : /*
       2             :  * Input driver to ExplorerPS/2 device driver module.
       3             :  *
       4             :  * Copyright (c) 1999-2002 Vojtech Pavlik
       5             :  * Copyright (c) 2004      Dmitry Torokhov
       6             :  *
       7             :  * This program is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License version 2 as published by
       9             :  * the Free Software Foundation.
      10             :  */
      11             : 
      12             : #define MOUSEDEV_MINOR_BASE     32
      13             : #define MOUSEDEV_MINORS         32
      14             : #define MOUSEDEV_MIX            31
      15             : 
      16             : #include <linux/sched.h>
      17             : #include <linux/slab.h>
      18             : #include <linux/smp_lock.h>
      19             : #include <linux/poll.h>
      20             : #include <linux/module.h>
      21             : #include <linux/init.h>
      22             : #include <linux/input.h>
      23             : #include <linux/random.h>
      24             : #include <linux/major.h>
      25             : #include <linux/device.h>
      26             : #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
      27             : #include <linux/miscdevice.h>
      28             : #endif
      29             : 
      30             : MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
      31             : MODULE_DESCRIPTION("Mouse (ExplorerPS/2) device interfaces");
      32             : MODULE_LICENSE("GPL");
      33             : 
      34             : #ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_X
      35             : #define CONFIG_INPUT_MOUSEDEV_SCREEN_X  1024
      36             : #endif
      37             : #ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_Y
      38             : #define CONFIG_INPUT_MOUSEDEV_SCREEN_Y  768
      39             : #endif
      40             : 
      41           1 : static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X;
      42             : module_param(xres, uint, 0644);
      43             : MODULE_PARM_DESC(xres, "Horizontal screen resolution");
      44             : 
      45           1 : static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y;
      46             : module_param(yres, uint, 0644);
      47             : MODULE_PARM_DESC(yres, "Vertical screen resolution");
      48             : 
      49           1 : static unsigned tap_time = 200;
      50             : module_param(tap_time, uint, 0644);
      51           1 : MODULE_PARM_DESC(tap_time, "Tap time for touchpads in absolute mode (msecs)");
      52             : 
      53             : struct mousedev_hw_data {
      54             :         int dx, dy, dz;
      55             :         int x, y;
      56             :         int abs_event;
      57             :         unsigned long buttons;
      58             : };
      59           1 : 
      60             : struct mousedev {
      61             :         int exist;
      62             :         int open;
      63             :         int minor;
      64             :         struct input_handle handle;
      65             :         wait_queue_head_t wait;
      66             :         struct list_head client_list;
      67             :         spinlock_t client_lock; /* protects client_list */
      68             :         struct mutex mutex;
      69             :         struct device dev;
      70             : 
      71             :         struct list_head mixdev_node;
      72             :         int mixdev_open;
      73             : 
      74             :         struct mousedev_hw_data packet;
      75             :         unsigned int pkt_count;
      76             :         int old_x[4], old_y[4];
      77             :         int frac_dx, frac_dy;
      78             :         unsigned long touch;
      79             : };
      80           1 : 
      81             : enum mousedev_emul {
      82             :         MOUSEDEV_EMUL_PS2,
      83             :         MOUSEDEV_EMUL_IMPS,
      84             :         MOUSEDEV_EMUL_EXPS
      85             : };
      86           1 : 
      87             : struct mousedev_motion {
      88             :         int dx, dy, dz;
      89             :         unsigned long buttons;
      90             : };
      91           1 : 
      92             : #define PACKET_QUEUE_LEN        16
      93             : struct mousedev_client {
      94             :         struct fasync_struct *fasync;
      95             :         struct mousedev *mousedev;
      96             :         struct list_head node;
      97             : 
      98             :         struct mousedev_motion packets[PACKET_QUEUE_LEN];
      99             :         unsigned int head, tail;
     100             :         spinlock_t packet_lock;
     101             :         int pos_x, pos_y;
     102             : 
     103             :         signed char ps2[6];
     104             :         unsigned char ready, buffer, bufsiz;
     105             :         unsigned char imexseq, impsseq;
     106             :         enum mousedev_emul mode;
     107             :         unsigned long last_buttons;
     108             : };
     109             : 
     110             : #define MOUSEDEV_SEQ_LEN        6
     111             : 
     112           1 : static unsigned char mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 };
     113           1 : static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 };
     114             : 
     115           1 : static struct input_handler mousedev_handler;
     116             : 
     117           1 : static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
     118           1 : static DEFINE_MUTEX(mousedev_table_mutex);
     119           1 : static struct mousedev *mousedev_mix;
     120           1 : static LIST_HEAD(mousedev_mix_list);
     121             : 
     122             : static void mixdev_open_devices(void);
     123             : static void mixdev_close_devices(void);
     124             : 
     125             : #define fx(i)  (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
     126             : #define fy(i)  (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])
     127             : 
     128             : static void mousedev_touchpad_event(struct input_dev *dev,
     129             :                                     struct mousedev *mousedev,
     130             :                                     unsigned int code, int value)
     131           1 : {
     132           1 :         int size, tmp;
     133             :         enum { FRACTION_DENOM = 128 };
     134             : 
     135           1 :         switch (code) {
     136           1 : 
     137           3 :         case ABS_X:
     138           1 :                 fx(0) = value;
     139           4 :                 if (mousedev->touch && mousedev->pkt_count >= 2) {
     140           1 :                         size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
     141           2 :                         if (size == 0)
     142           1 :                                 size = 256 * 2;
     143           1 :                         tmp = ((value - fx(2)) * 256 * FRACTION_DENOM) / size;
     144           1 :                         tmp += mousedev->frac_dx;
     145           1 :                         mousedev->packet.dx = tmp / FRACTION_DENOM;
     146           1 :                         mousedev->frac_dx =
     147             :                                 tmp - mousedev->packet.dx * FRACTION_DENOM;
     148             :                 }
     149           1 :                 break;
     150           1 : 
     151           3 :         case ABS_Y:
     152           1 :                 fy(0) = value;
     153           4 :                 if (mousedev->touch && mousedev->pkt_count >= 2) {
     154             :                         /* use X size to keep the same scale */
     155           1 :                         size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
     156           2 :                         if (size == 0)
     157           1 :                                 size = 256 * 2;
     158           1 :                         tmp = -((value - fy(2)) * 256 * FRACTION_DENOM) / size;
     159           1 :                         tmp += mousedev->frac_dy;
     160           1 :                         mousedev->packet.dy = tmp / FRACTION_DENOM;
     161           1 :                         mousedev->frac_dy = tmp -
     162             :                                 mousedev->packet.dy * FRACTION_DENOM;
     163             :                 }
     164           1 :                 break;
     165           1 :         }
     166             : }
     167           2 : 
     168             : static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev,
     169             :                                 unsigned int code, int value)
     170             : {
     171           1 :         int size;
     172             : 
     173           1 :         switch (code) {
     174           1 : 
     175           3 :         case ABS_X:
     176           1 :                 size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
     177           2 :                 if (size == 0)
     178           6 :                         size = xres ? : 1;
     179           2 :                 if (value > dev->absmax[ABS_X])
     180           1 :                         value = dev->absmax[ABS_X];
     181           2 :                 if (value < dev->absmin[ABS_X])
     182           1 :                         value = dev->absmin[ABS_X];
     183           1 :                 mousedev->packet.x =
     184             :                         ((value - dev->absmin[ABS_X]) * xres) / size;
     185           1 :                 mousedev->packet.abs_event = 1;
     186           1 :                 break;
     187           1 : 
     188           3 :         case ABS_Y:
     189           1 :                 size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y];
     190           2 :                 if (size == 0)
     191           6 :                         size = yres ? : 1;
     192           2 :                 if (value > dev->absmax[ABS_Y])
     193           1 :                         value = dev->absmax[ABS_Y];
     194           2 :                 if (value < dev->absmin[ABS_Y])
     195           1 :                         value = dev->absmin[ABS_Y];
     196           1 :                 mousedev->packet.y = yres -
     197             :                         ((value - dev->absmin[ABS_Y]) * yres) / size;
     198           1 :                 mousedev->packet.abs_event = 1;
     199           1 :                 break;
     200           1 :         }
     201             : }
     202           2 : 
     203             : static void mousedev_rel_event(struct mousedev *mousedev,
     204             :                                 unsigned int code, int value)
     205             : {
     206           1 :         switch (code) {
     207           4 :         case REL_X:
     208           1 :                 mousedev->packet.dx += value;
     209           1 :                 break;
     210           1 : 
     211           3 :         case REL_Y:
     212           1 :                 mousedev->packet.dy -= value;
     213           1 :                 break;
     214           1 : 
     215           3 :         case REL_WHEEL:
     216           1 :                 mousedev->packet.dz -= value;
     217           1 :                 break;
     218           1 :         }
     219             : }
     220           2 : 
     221             : static void mousedev_key_event(struct mousedev *mousedev,
     222             :                                 unsigned int code, int value)
     223           2 : {
     224             :         int index;
     225             : 
     226             :         switch (code) {
     227             : 
     228           6 :         case BTN_TOUCH:
     229           6 :         case BTN_0:
     230          10 :         case BTN_LEFT:          index = 0; break;
     231           2 : 
     232           8 :         case BTN_STYLUS:
     233           8 :         case BTN_1:
     234          10 :         case BTN_RIGHT:         index = 1; break;
     235           2 : 
     236           8 :         case BTN_2:
     237           8 :         case BTN_FORWARD:
     238           8 :         case BTN_STYLUS2:
     239          10 :         case BTN_MIDDLE:        index = 2; break;
     240           2 : 
     241           8 :         case BTN_3:
     242           8 :         case BTN_BACK:
     243          10 :         case BTN_SIDE:          index = 3; break;
     244           2 : 
     245           8 :         case BTN_4:
     246          10 :         case BTN_EXTRA:         index = 4; break;
     247           2 : 
     248           4 :         default:                return;
     249           2 :         }
     250           2 : 
     251           6 :         if (value) {
     252           4 :                 set_bit(index, &mousedev->packet.buttons);
     253           4 :                 set_bit(index, &mousedev_mix->packet.buttons);
     254             :         } else {
     255           4 :                 clear_bit(index, &mousedev->packet.buttons);
     256           4 :                 clear_bit(index, &mousedev_mix->packet.buttons);
     257             :         }
     258           4 : }
     259             : 
     260             : static void mousedev_notify_readers(struct mousedev *mousedev,
     261             :                                     struct mousedev_hw_data *packet)
     262           4 : {
     263           4 :         struct mousedev_client *client;
     264           4 :         struct mousedev_motion *p;
     265           4 :         unsigned int new_head;
     266           8 :         int wake_readers = 0;
     267           4 : 
     268          12 :         rcu_read_lock();
     269          44 :         list_for_each_entry_rcu(client, &mousedev->client_list, node) {
     270          12 : 
     271           4 :                 /* Just acquire the lock, interrupts already disabled */
     272           8 :                 spin_lock(&client->packet_lock);
     273             : 
     274           8 :                 p = &client->packets[client->head];
     275          20 :                 if (client->ready && p->buttons != mousedev->packet.buttons) {
     276           4 :                         new_head = (client->head + 1) % PACKET_QUEUE_LEN;
     277           8 :                         if (new_head != client->tail) {
     278          12 :                                 p = &client->packets[client->head = new_head];
     279           4 :                                 memset(p, 0, sizeof(struct mousedev_motion));
     280             :                         }
     281             :                 }
     282             : 
     283           8 :                 if (packet->abs_event) {
     284           4 :                         p->dx += packet->x - client->pos_x;
     285           4 :                         p->dy += packet->y - client->pos_y;
     286           4 :                         client->pos_x = packet->x;
     287           4 :                         client->pos_y = packet->y;
     288             :                 }
     289             : 
     290           4 :                 client->pos_x += packet->dx;
     291          44 :                 client->pos_x = client->pos_x < 0 ?
     292             :                         0 : (client->pos_x >= xres ? xres : client->pos_x);
     293           4 :                 client->pos_y += packet->dy;
     294          44 :                 client->pos_y = client->pos_y < 0 ?
     295             :                         0 : (client->pos_y >= yres ? yres : client->pos_y);
     296             : 
     297           4 :                 p->dx += packet->dx;
     298           4 :                 p->dy += packet->dy;
     299           4 :                 p->dz += packet->dz;
     300           4 :                 p->buttons = mousedev->packet.buttons;
     301             : 
     302          24 :                 if (p->dx || p->dy || p->dz ||
     303             :                     p->buttons != client->last_buttons)
     304           4 :                         client->ready = 1;
     305             : 
     306           8 :                 spin_unlock(&client->packet_lock);
     307             : 
     308          12 :                 if (client->ready) {
     309           4 :                         kill_fasync(&client->fasync, SIGIO, POLL_IN);
     310           4 :                         wake_readers = 1;
     311             :                 }
     312             :         }
     313           8 :         rcu_read_unlock();
     314             : 
     315           8 :         if (wake_readers)
     316           4 :                 wake_up_interruptible(&mousedev->wait);
     317           4 : }
     318             : 
     319             : static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
     320             : {
     321           3 :         if (!value) {
     322             :                 if (mousedev->touch &&
     323           5 :                     time_before(jiffies,
     324             :                                 mousedev->touch + msecs_to_jiffies(tap_time))) {
     325             :                         /*
     326             :                          * Toggle left button to emulate tap.
     327             :                          * We rely on the fact that mousedev_mix always has 0
     328             :                          * motion packet so we won't mess current position.
     329             :                          */
     330           2 :                         set_bit(0, &mousedev->packet.buttons);
     331           2 :                         set_bit(0, &mousedev_mix->packet.buttons);
     332           2 :                         mousedev_notify_readers(mousedev, &mousedev_mix->packet);
     333           2 :                         mousedev_notify_readers(mousedev_mix,
     334             :                                                 &mousedev_mix->packet);
     335           2 :                         clear_bit(0, &mousedev->packet.buttons);
     336           2 :                         clear_bit(0, &mousedev_mix->packet.buttons);
     337             :                 }
     338           4 :                 mousedev->touch = mousedev->pkt_count = 0;
     339           2 :                 mousedev->frac_dx = 0;
     340           2 :                 mousedev->frac_dy = 0;
     341             : 
     342           2 :         } else if (!mousedev->touch)
     343           1 :                 mousedev->touch = jiffies;
     344           2 : }
     345             : 
     346             : static void mousedev_event(struct input_handle *handle,
     347             :                            unsigned int type, unsigned int code, int value)
     348             : {
     349           3 :         struct mousedev *mousedev = handle->private;
     350           1 : 
     351           2 :         switch (type) {
     352           2 : 
     353           4 :         case EV_ABS:
     354           1 :                 /* Ignore joysticks */
     355           4 :                 if (test_bit(BTN_TRIGGER, handle->dev->keybit))
     356           1 :                         return;
     357             : 
     358           4 :                 if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit))
     359           2 :                         mousedev_touchpad_event(handle->dev,
     360             :                                                 mousedev, code, value);
     361             :                 else
     362           2 :                         mousedev_abs_event(handle->dev, mousedev, code, value);
     363             : 
     364           2 :                 break;
     365           1 : 
     366           3 :         case EV_REL:
     367           2 :                 mousedev_rel_event(mousedev, code, value);
     368           1 :                 break;
     369           1 : 
     370           3 :         case EV_KEY:
     371           2 :                 if (value != 2) {
     372           6 :                         if (code == BTN_TOUCH &&
     373             :                             test_bit(BTN_TOOL_FINGER, handle->dev->keybit))
     374           3 :                                 mousedev_touchpad_touch(mousedev, value);
     375             :                         else
     376           8 :                                 mousedev_key_event(mousedev, code, value);
     377             :                 }
     378           4 :                 break;
     379           1 : 
     380           3 :         case EV_SYN:
     381           2 :                 if (code == SYN_REPORT) {
     382           2 :                         if (mousedev->touch) {
     383           1 :                                 mousedev->pkt_count++;
     384             :                                 /*
     385             :                                  * Input system eats duplicate events,
     386             :                                  * but we need all of them to do correct
     387             :                                  * averaging so apply present one forward
     388             :                                  */
     389           1 :                                 fx(0) = fx(1);
     390           1 :                                 fy(0) = fy(1);
     391             :                         }
     392             : 
     393           2 :                         mousedev_notify_readers(mousedev, &mousedev->packet);
     394           2 :                         mousedev_notify_readers(mousedev_mix, &mousedev->packet);
     395             : 
     396           5 :                         mousedev->packet.dx = mousedev->packet.dy =
     397             :                                 mousedev->packet.dz = 0;
     398           1 :                         mousedev->packet.abs_event = 0;
     399             :                 }
     400           2 :                 break;
     401           1 :         }
     402             : }
     403           9 : 
     404             : static int mousedev_fasync(int fd, struct file *file, int on)
     405             : {
     406           3 :         struct mousedev_client *client = file->private_data;
     407           1 : 
     408           2 :         return fasync_helper(fd, file, on, &client->fasync);
     409             : }
     410             : 
     411             : static void mousedev_free(struct device *dev)
     412             : {
     413           0 :         struct mousedev *mousedev = container_of(dev, struct mousedev, dev);
     414           0 : 
     415           0 :         input_put_device(mousedev->handle.dev);
     416           0 :         kfree(mousedev);
     417           0 : }
     418             : 
     419             : static int mousedev_open_device(struct mousedev *mousedev)
     420             : {
     421           2 :         int retval;
     422           2 : 
     423           2 :         retval = mutex_lock_interruptible(&mousedev->mutex);
     424           4 :         if (retval)
     425           2 :                 return retval;
     426             : 
     427           4 :         if (mousedev->minor == MOUSEDEV_MIX)
     428           6 :                 mixdev_open_devices();
     429           4 :         else if (!mousedev->exist)
     430           2 :                 retval = -ENODEV;
     431           8 :         else if (!mousedev->open++) {
     432           2 :                 retval = input_open_device(&mousedev->handle);
     433           4 :                 if (retval)
     434           2 :                         mousedev->open--;
     435             :         }
     436             : 
     437           4 :         mutex_unlock(&mousedev->mutex);
     438           4 :         return retval;
     439             : }
     440             : 
     441             : static void mousedev_close_device(struct mousedev *mousedev)
     442             : {
     443           2 :         mutex_lock(&mousedev->mutex);
     444             : 
     445           4 :         if (mousedev->minor == MOUSEDEV_MIX)
     446           6 :                 mixdev_close_devices();
     447          10 :         else if (mousedev->exist && !--mousedev->open)
     448           2 :                 input_close_device(&mousedev->handle);
     449             : 
     450           4 :         mutex_unlock(&mousedev->mutex);
     451           4 : }
     452             : 
     453             : /*
     454             :  * Open all available devices so they can all be multiplexed in one.
     455             :  * stream. Note that this function is called with mousedev_mix->mutex
     456             :  * held.
     457             :  */
     458             : static void mixdev_open_devices(void)
     459             : {
     460           2 :         struct mousedev *mousedev;
     461           2 : 
     462          10 :         if (mousedev_mix->open++)
     463           4 :                 return;
     464           2 : 
     465          20 :         list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
     466          10 :                 if (!mousedev->mixdev_open) {
     467           8 :                         if (mousedev_open_device(mousedev))
     468           2 :                                 continue;
     469             : 
     470           2 :                         mousedev->mixdev_open = 1;
     471             :                 }
     472           2 :         }
     473             : }
     474           4 : 
     475             : /*
     476             :  * Close all devices that were opened as part of multiplexed
     477             :  * device. Note that this function is called with mousedev_mix->mutex
     478             :  * held.
     479             :  */
     480             : static void mixdev_close_devices(void)
     481             : {
     482           2 :         struct mousedev *mousedev;
     483           2 : 
     484           8 :         if (--mousedev_mix->open)
     485           2 :                 return;
     486             : 
     487          20 :         list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
     488          10 :                 if (mousedev->mixdev_open) {
     489           4 :                         mousedev->mixdev_open = 0;
     490           2 :                         mousedev_close_device(mousedev);
     491             :                 }
     492             :         }
     493             : }
     494           2 : 
     495             : 
     496             : static void mousedev_attach_client(struct mousedev *mousedev,
     497             :                                    struct mousedev_client *client)
     498             : {
     499           2 :         spin_lock(&mousedev->client_lock);
     500           2 :         list_add_tail_rcu(&client->node, &mousedev->client_list);
     501           2 :         spin_unlock(&mousedev->client_lock);
     502           1 :         synchronize_rcu();
     503           1 : }
     504             : 
     505             : static void mousedev_detach_client(struct mousedev *mousedev,
     506             :                                    struct mousedev_client *client)
     507             : {
     508           4 :         spin_lock(&mousedev->client_lock);
     509           4 :         list_del_rcu(&client->node);
     510           4 :         spin_unlock(&mousedev->client_lock);
     511           2 :         synchronize_rcu();
     512           2 : }
     513             : 
     514             : static int mousedev_release(struct inode *inode, struct file *file)
     515             : {
     516           3 :         struct mousedev_client *client = file->private_data;
     517           2 :         struct mousedev *mousedev = client->mousedev;
     518             : 
     519           2 :         mousedev_detach_client(mousedev, client);
     520           1 :         kfree(client);
     521             : 
     522           3 :         mousedev_close_device(mousedev);
     523           1 :         put_device(&mousedev->dev);
     524             : 
     525           1 :         return 0;
     526             : }
     527             : 
     528             : static int mousedev_open(struct inode *inode, struct file *file)
     529             : {
     530           1 :         struct mousedev_client *client;
     531           1 :         struct mousedev *mousedev;
     532           1 :         int error;
     533           1 :         int i;
     534           1 : 
     535           1 : #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
     536           5 :         if (imajor(inode) == MISC_MAJOR)
     537           2 :                 i = MOUSEDEV_MIX;
     538             :         else
     539             : #endif
     540           3 :                 i = iminor(inode) - MOUSEDEV_MINOR_BASE;
     541             : 
     542           4 :         if (i >= MOUSEDEV_MINORS)
     543           2 :                 return -ENODEV;
     544             : 
     545           2 :         lock_kernel();
     546           2 :         error = mutex_lock_interruptible(&mousedev_table_mutex);
     547           4 :         if (error) {
     548           2 :                 unlock_kernel();
     549           2 :                 return error;
     550             :         }
     551           2 :         mousedev = mousedev_table[i];
     552           4 :         if (mousedev)
     553           2 :                 get_device(&mousedev->dev);
     554           2 :         mutex_unlock(&mousedev_table_mutex);
     555             : 
     556           4 :         if (!mousedev) {
     557           2 :                 unlock_kernel();
     558           2 :                 return -ENODEV;
     559             :         }
     560             : 
     561           5 :         client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
     562           2 :         if (!client) {
     563           1 :                 error = -ENOMEM;
     564           1 :                 goto err_put_mousedev;
     565             :         }
     566             : 
     567           4 :         spin_lock_init(&client->packet_lock);
     568           1 :         client->pos_x = xres / 2;
     569           1 :         client->pos_y = yres / 2;
     570           1 :         client->mousedev = mousedev;
     571           2 :         mousedev_attach_client(mousedev, client);
     572             : 
     573           3 :         error = mousedev_open_device(mousedev);
     574           2 :         if (error)
     575           1 :                 goto err_free_client;
     576             : 
     577           1 :         file->private_data = client;
     578           1 :         unlock_kernel();
     579           1 :         return 0;
     580           1 : 
     581             :  err_free_client:
     582           2 :         mousedev_detach_client(mousedev, client);
     583           1 :         kfree(client);
     584             :  err_put_mousedev:
     585           3 :         put_device(&mousedev->dev);
     586           2 :         unlock_kernel();
     587           2 :         return error;
     588             : }
     589             : 
     590             : static inline int mousedev_limit_delta(int delta, int limit)
     591             : {
     592          88 :         return delta > limit ? limit : (delta < -limit ? -limit : delta);
     593             : }
     594             : 
     595             : static void mousedev_packet(struct mousedev_client *client,
     596             :                             signed char *ps2_data)
     597           2 : {
     598           6 :         struct mousedev_motion *p = &client->packets[client->tail];
     599           2 : 
     600          26 :         ps2_data[0] = 0x08 |
     601           2 :                 ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07);
     602           6 :         ps2_data[1] = mousedev_limit_delta(p->dx, 127);
     603           6 :         ps2_data[2] = mousedev_limit_delta(p->dy, 127);
     604           2 :         p->dx -= ps2_data[1];
     605           2 :         p->dy -= ps2_data[2];
     606             : 
     607             :         switch (client->mode) {
     608           8 :         case MOUSEDEV_EMUL_EXPS:
     609           6 :                 ps2_data[3] = mousedev_limit_delta(p->dz, 7);
     610           2 :                 p->dz -= ps2_data[3];
     611           4 :                 ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1);
     612           2 :                 client->bufsiz = 4;
     613           2 :                 break;
     614           2 : 
     615           8 :         case MOUSEDEV_EMUL_IMPS:
     616           2 :                 ps2_data[0] |=
     617             :                         ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
     618           6 :                 ps2_data[3] = mousedev_limit_delta(p->dz, 127);
     619           2 :                 p->dz -= ps2_data[3];
     620           2 :                 client->bufsiz = 4;
     621           2 :                 break;
     622           2 : 
     623           2 :         case MOUSEDEV_EMUL_PS2:
     624             :         default:
     625           4 :                 ps2_data[0] |=
     626             :                         ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
     627           2 :                 p->dz = 0;
     628           2 :                 client->bufsiz = 3;
     629           2 :                 break;
     630             :         }
     631             : 
     632          24 :         if (!p->dx && !p->dy && !p->dz) {
     633          12 :                 if (client->tail == client->head) {
     634           6 :                         client->ready = 0;
     635           6 :                         client->last_buttons = p->buttons;
     636             :                 } else
     637           6 :                         client->tail = (client->tail + 1) % PACKET_QUEUE_LEN;
     638           6 :         }
     639             : }
     640             : 
     641             : static void mousedev_generate_response(struct mousedev_client *client,
     642             :                                         int command)
     643           1 : {
     644           1 :         client->ps2[0] = 0xfa; /* ACK */
     645             : 
     646             :         switch (command) {
     647             : 
     648           3 :         case 0xeb: /* Poll */
     649           4 :                 mousedev_packet(client, &client->ps2[1]);
     650           2 :                 client->bufsiz++; /* account for leading ACK */
     651           1 :                 break;
     652           1 : 
     653           3 :         case 0xf2: /* Get ID */
     654           1 :                 switch (client->mode) {
     655           5 :                 case MOUSEDEV_EMUL_PS2:
     656           1 :                         client->ps2[1] = 0;
     657           1 :                         break;
     658           5 :                 case MOUSEDEV_EMUL_IMPS:
     659           1 :                         client->ps2[1] = 3;
     660           1 :                         break;
     661           5 :                 case MOUSEDEV_EMUL_EXPS:
     662           1 :                         client->ps2[1] = 4;
     663           1 :                         break;
     664           1 :                 }
     665           1 :                 client->bufsiz = 2;
     666           2 :                 break;
     667           1 : 
     668           3 :         case 0xe9: /* Get info */
     669           3 :                 client->ps2[1] = 0x60; client->ps2[2] = 3; client->ps2[3] = 200;
     670           1 :                 client->bufsiz = 4;
     671           1 :                 break;
     672           1 : 
     673           3 :         case 0xff: /* Reset */
     674           3 :                 client->impsseq = client->imexseq = 0;
     675           1 :                 client->mode = MOUSEDEV_EMUL_PS2;
     676           2 :                 client->ps2[1] = 0xaa; client->ps2[2] = 0x00;
     677           1 :                 client->bufsiz = 3;
     678           1 :                 break;
     679           1 : 
     680           1 :         default:
     681           2 :                 client->bufsiz = 1;
     682           1 :                 break;
     683             :         }
     684           2 :         client->buffer = client->bufsiz;
     685           2 : }
     686             : 
     687             : static ssize_t mousedev_write(struct file *file, const char __user *buffer,
     688             :                                 size_t count, loff_t *ppos)
     689             : {
     690           3 :         struct mousedev_client *client = file->private_data;
     691           1 :         unsigned char c;
     692           1 :         unsigned int i;
     693           1 : 
     694           6 :         for (i = 0; i < count; i++) {
     695           1 : 
     696          11 :                 if (get_user(c, buffer + i))
     697           2 :                         return -EFAULT;
     698             : 
     699           2 :                 spin_lock_irq(&client->packet_lock);
     700             : 
     701           3 :                 if (c == mousedev_imex_seq[client->imexseq]) {
     702           5 :                         if (++client->imexseq == MOUSEDEV_SEQ_LEN) {
     703           1 :                                 client->imexseq = 0;
     704           1 :                                 client->mode = MOUSEDEV_EMUL_EXPS;
     705             :                         }
     706             :                 } else
     707           1 :                         client->imexseq = 0;
     708             : 
     709           3 :                 if (c == mousedev_imps_seq[client->impsseq]) {
     710           5 :                         if (++client->impsseq == MOUSEDEV_SEQ_LEN) {
     711           1 :                                 client->impsseq = 0;
     712           1 :                                 client->mode = MOUSEDEV_EMUL_IMPS;
     713             :                         }
     714             :                 } else
     715           1 :                         client->impsseq = 0;
     716             : 
     717           3 :                 mousedev_generate_response(client, c);
     718             : 
     719           2 :                 spin_unlock_irq(&client->packet_lock);
     720             :         }
     721             : 
     722           1 :         kill_fasync(&client->fasync, SIGIO, POLL_IN);
     723           1 :         wake_up_interruptible(&client->mousedev->wait);
     724             : 
     725           1 :         return count;
     726             : }
     727             : 
     728             : static ssize_t mousedev_read(struct file *file, char __user *buffer,
     729             :                              size_t count, loff_t *ppos)
     730           1 : {
     731           3 :         struct mousedev_client *client = file->private_data;
     732           2 :         struct mousedev *mousedev = client->mousedev;
     733           1 :         signed char data[sizeof(client->ps2)];
     734           2 :         int retval = 0;
     735           1 : 
     736           7 :         if (!client->ready && !client->buffer && mousedev->exist &&
     737           1 :             (file->f_flags & O_NONBLOCK))
     738           2 :                 return -EAGAIN;
     739           1 : 
     740          34 :         retval = wait_event_interruptible(mousedev->wait,
     741           3 :                         !mousedev->exist || client->ready || client->buffer);
     742           7 :         if (retval)
     743           3 :                 return retval;
     744             : 
     745           6 :         if (!mousedev->exist)
     746           3 :                 return -ENODEV;
     747             : 
     748           6 :         spin_lock_irq(&client->packet_lock);
     749             : 
     750           6 :         if (!client->buffer && client->ready) {
     751           4 :                 mousedev_packet(client, client->ps2);
     752           1 :                 client->buffer = client->bufsiz;
     753             :         }
     754             : 
     755           6 :         if (count > client->buffer)
     756           4 :                 count = client->buffer;
     757             : 
     758           6 :         memcpy(data, client->ps2 + client->bufsiz - client->buffer, count);
     759           4 :         client->buffer -= count;
     760             : 
     761           4 :         spin_unlock_irq(&client->packet_lock);
     762             : 
     763           4 :         if (copy_to_user(buffer, data, count))
     764           1 :                 return -EFAULT;
     765             : 
     766           1 :         return count;
     767             : }
     768             : 
     769             : /* No kernel lock - fine */
     770             : static unsigned int mousedev_poll(struct file *file, poll_table *wait)
     771             : {
     772           3 :         struct mousedev_client *client = file->private_data;
     773           2 :         struct mousedev *mousedev = client->mousedev;
     774             : 
     775           2 :         poll_wait(file, &mousedev->wait, wait);
     776          11 :         return ((client->ready || client->buffer) ? (POLLIN | POLLRDNORM) : 0) |
     777             :                 (mousedev->exist ? 0 : (POLLHUP | POLLERR));
     778             : }
     779             : 
     780           1 : static const struct file_operations mousedev_fops = {
     781             :         .owner =        THIS_MODULE,
     782             :         .read =         mousedev_read,
     783             :         .write =        mousedev_write,
     784             :         .poll =         mousedev_poll,
     785             :         .open =         mousedev_open,
     786             :         .release =      mousedev_release,
     787             :         .fasync =       mousedev_fasync,
     788             : };
     789             : 
     790             : static int mousedev_install_chrdev(struct mousedev *mousedev)
     791             : {
     792           2 :         mousedev_table[mousedev->minor] = mousedev;
     793           2 :         return 0;
     794             : }
     795             : 
     796             : static void mousedev_remove_chrdev(struct mousedev *mousedev)
     797             : {
     798           9 :         mutex_lock(&mousedev_table_mutex);
     799           9 :         mousedev_table[mousedev->minor] = NULL;
     800           9 :         mutex_unlock(&mousedev_table_mutex);
     801           9 : }
     802             : 
     803             : /*
     804             :  * Mark device non-existent. This disables writes, ioctls and
     805             :  * prevents new users from opening the device. Already posted
     806             :  * blocking reads will stay, however new ones will fail.
     807             :  */
     808             : static void mousedev_mark_dead(struct mousedev *mousedev)
     809             : {
     810           9 :         mutex_lock(&mousedev->mutex);
     811           9 :         mousedev->exist = 0;
     812           9 :         mutex_unlock(&mousedev->mutex);
     813           9 : }
     814             : 
     815             : /*
     816             :  * Wake up users waiting for IO so they can disconnect from
     817             :  * dead device.
     818             :  */
     819             : static void mousedev_hangup(struct mousedev *mousedev)
     820             : {
     821           9 :         struct mousedev_client *client;
     822           9 : 
     823          27 :         spin_lock(&mousedev->client_lock);
     824          72 :         list_for_each_entry(client, &mousedev->client_list, node)
     825          18 :                 kill_fasync(&client->fasync, SIGIO, POLL_HUP);
     826          36 :         spin_unlock(&mousedev->client_lock);
     827             : 
     828           9 :         wake_up_interruptible(&mousedev->wait);
     829           9 : }
     830             : 
     831             : static void mousedev_cleanup(struct mousedev *mousedev)
     832             : {
     833          18 :         struct input_handle *handle = &mousedev->handle;
     834             : 
     835          18 :         mousedev_mark_dead(mousedev);
     836          18 :         mousedev_hangup(mousedev);
     837          18 :         mousedev_remove_chrdev(mousedev);
     838             : 
     839             :         /* mousedev is marked dead so no one else accesses mousedev->open */
     840          18 :         if (mousedev->open)
     841           9 :                 input_close_device(handle);
     842           9 : }
     843             : 
     844             : static struct mousedev *mousedev_create(struct input_dev *dev,
     845             :                                         struct input_handler *handler,
     846             :                                         int minor)
     847           2 : {
     848           2 :         struct mousedev *mousedev;
     849           2 :         int error;
     850           2 : 
     851           8 :         mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
     852           6 :         if (!mousedev) {
     853           4 :                 error = -ENOMEM;
     854           2 :                 goto err_out;
     855             :         }
     856             : 
     857           4 :         INIT_LIST_HEAD(&mousedev->client_list);
     858           4 :         INIT_LIST_HEAD(&mousedev->mixdev_node);
     859           8 :         spin_lock_init(&mousedev->client_lock);
     860           2 :         mutex_init(&mousedev->mutex);
     861             :         lockdep_set_subclass(&mousedev->mutex,
     862             :                              minor == MOUSEDEV_MIX ? MOUSEDEV_MIX : 0);
     863           2 :         init_waitqueue_head(&mousedev->wait);
     864             : 
     865           4 :         if (minor == MOUSEDEV_MIX)
     866           2 :                 dev_set_name(&mousedev->dev, "mice");
     867             :         else
     868           2 :                 dev_set_name(&mousedev->dev, "mouse%d", minor);
     869             : 
     870           2 :         mousedev->minor = minor;
     871           2 :         mousedev->exist = 1;
     872           4 :         mousedev->handle.dev = input_get_device(dev);
     873           4 :         mousedev->handle.name = dev_name(&mousedev->dev);
     874           2 :         mousedev->handle.handler = handler;
     875           2 :         mousedev->handle.private = mousedev;
     876             : 
     877           2 :         mousedev->dev.class = &input_class;
     878           4 :         if (dev)
     879           2 :                 mousedev->dev.parent = &dev->dev;
     880           2 :         mousedev->dev.devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor);
     881           2 :         mousedev->dev.release = mousedev_free;
     882           2 :         device_initialize(&mousedev->dev);
     883             : 
     884           4 :         if (minor != MOUSEDEV_MIX) {
     885           2 :                 error = input_register_handle(&mousedev->handle);
     886           4 :                 if (error)
     887           2 :                         goto err_free_mousedev;
     888             :         }
     889             : 
     890           4 :         error = mousedev_install_chrdev(mousedev);
     891           4 :         if (error)
     892           2 :                 goto err_unregister_handle;
     893             : 
     894           2 :         error = device_add(&mousedev->dev);
     895           4 :         if (error)
     896           2 :                 goto err_cleanup_mousedev;
     897             : 
     898           2 :         return mousedev;
     899           2 : 
     900             :  err_cleanup_mousedev:
     901           4 :         mousedev_cleanup(mousedev);
     902             :  err_unregister_handle:
     903          10 :         if (minor != MOUSEDEV_MIX)
     904           4 :                 input_unregister_handle(&mousedev->handle);
     905             :  err_free_mousedev:
     906           6 :         put_device(&mousedev->dev);
     907             :  err_out:
     908          24 :         return ERR_PTR(error);
     909           4 : }
     910             : 
     911             : static void mousedev_destroy(struct mousedev *mousedev)
     912             : {
     913           7 :         device_del(&mousedev->dev);
     914          14 :         mousedev_cleanup(mousedev);
     915          14 :         if (mousedev->minor != MOUSEDEV_MIX)
     916           7 :                 input_unregister_handle(&mousedev->handle);
     917           7 :         put_device(&mousedev->dev);
     918           7 : }
     919             : 
     920             : static int mixdev_add_device(struct mousedev *mousedev)
     921             : {
     922           1 :         int retval;
     923             : 
     924           1 :         retval = mutex_lock_interruptible(&mousedev_mix->mutex);
     925           2 :         if (retval)
     926           1 :                 return retval;
     927             : 
     928           2 :         if (mousedev_mix->open) {
     929           3 :                 retval = mousedev_open_device(mousedev);
     930           2 :                 if (retval)
     931           1 :                         goto out;
     932             : 
     933           1 :                 mousedev->mixdev_open = 1;
     934             :         }
     935             : 
     936           2 :         get_device(&mousedev->dev);
     937           4 :         list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);
     938             : 
     939           1 :  out:
     940           2 :         mutex_unlock(&mousedev_mix->mutex);
     941           2 :         return retval;
     942             : }
     943             : 
     944             : static void mixdev_remove_device(struct mousedev *mousedev)
     945             : {
     946           1 :         mutex_lock(&mousedev_mix->mutex);
     947             : 
     948           2 :         if (mousedev->mixdev_open) {
     949           1 :                 mousedev->mixdev_open = 0;
     950           3 :                 mousedev_close_device(mousedev);
     951             :         }
     952             : 
     953           4 :         list_del_init(&mousedev->mixdev_node);
     954           1 :         mutex_unlock(&mousedev_mix->mutex);
     955             : 
     956           1 :         put_device(&mousedev->dev);
     957           1 : }
     958             : 
     959             : static int mousedev_connect(struct input_handler *handler,
     960             :                             struct input_dev *dev,
     961             :                             const struct input_device_id *id)
     962           1 : {
     963           1 :         struct mousedev *mousedev;
     964           1 :         int minor;
     965           1 :         int error;
     966           1 : 
     967           5 :         for (minor = 0; minor < MOUSEDEV_MINORS; minor++)
     968           4 :                 if (!mousedev_table[minor])
     969           2 :                         break;
     970             : 
     971           2 :         if (minor == MOUSEDEV_MINORS) {
     972           1 :                 printk(KERN_ERR "mousedev: no more free mousedev devices\n");
     973           2 :                 return -ENFILE;
     974             :         }
     975             : 
     976           3 :         mousedev = mousedev_create(dev, handler, minor);
     977           4 :         if (IS_ERR(mousedev))
     978           3 :                 return PTR_ERR(mousedev);
     979             : 
     980           4 :         error = mixdev_add_device(mousedev);
     981           2 :         if (error) {
     982           2 :                 mousedev_destroy(mousedev);
     983           1 :                 return error;
     984             :         }
     985             : 
     986           1 :         return 0;
     987             : }
     988             : 
     989             : static void mousedev_disconnect(struct input_handle *handle)
     990             : {
     991           3 :         struct mousedev *mousedev = handle->private;
     992             : 
     993           2 :         mixdev_remove_device(mousedev);
     994           2 :         mousedev_destroy(mousedev);
     995           1 : }
     996             : 
     997           1 : static const struct input_device_id mousedev_ids[] = {
     998             :         {
     999             :                 .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
    1000             :                                 INPUT_DEVICE_ID_MATCH_KEYBIT |
    1001             :                                 INPUT_DEVICE_ID_MATCH_RELBIT,
    1002             :                 .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_REL) },
    1003             :                 .keybit = { [BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) },
    1004             :                 .relbit = { BIT_MASK(REL_X) | BIT_MASK(REL_Y) },
    1005             :         },      /* A mouse like device, at least one button,
    1006             :                    two relative axes */
    1007             :         {
    1008             :                 .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
    1009             :                                 INPUT_DEVICE_ID_MATCH_RELBIT,
    1010             :                 .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_REL) },
    1011             :                 .relbit = { BIT_MASK(REL_WHEEL) },
    1012             :         },      /* A separate scrollwheel */
    1013             :         {
    1014             :                 .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
    1015             :                                 INPUT_DEVICE_ID_MATCH_KEYBIT |
    1016             :                                 INPUT_DEVICE_ID_MATCH_ABSBIT,
    1017             :                 .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) },
    1018             :                 .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
    1019             :                 .absbit = { BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) },
    1020             :         },      /* A tablet like device, at least touch detection,
    1021             :                    two absolute axes */
    1022             :         {
    1023             :                 .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
    1024             :                                 INPUT_DEVICE_ID_MATCH_KEYBIT |
    1025             :                                 INPUT_DEVICE_ID_MATCH_ABSBIT,
    1026             :                 .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) },
    1027             :                 .keybit = { [BIT_WORD(BTN_TOOL_FINGER)] =
    1028             :                                 BIT_MASK(BTN_TOOL_FINGER) },
    1029             :                 .absbit = { BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
    1030             :                                 BIT_MASK(ABS_PRESSURE) |
    1031             :                                 BIT_MASK(ABS_TOOL_WIDTH) },
    1032             :         },      /* A touchpad */
    1033             :         {
    1034             :                 .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
    1035             :                         INPUT_DEVICE_ID_MATCH_KEYBIT |
    1036             :                         INPUT_DEVICE_ID_MATCH_ABSBIT,
    1037             :                 .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) },
    1038             :                 .keybit = { [BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) },
    1039             :                 .absbit = { BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) },
    1040             :         },      /* Mouse-like device with absolute X and Y but ordinary
    1041             :                    clicks, like hp ILO2 High Performance mouse */
    1042             : 
    1043             :         { },    /* Terminating entry */
    1044             : };
    1045             : 
    1046             : MODULE_DEVICE_TABLE(input, mousedev_ids);
    1047             : 
    1048           1 : static struct input_handler mousedev_handler = {
    1049             :         .event =        mousedev_event,
    1050             :         .connect =      mousedev_connect,
    1051             :         .disconnect =   mousedev_disconnect,
    1052             :         .fops =         &mousedev_fops,
    1053             :         .minor =        MOUSEDEV_MINOR_BASE,
    1054             :         .name =         "mousedev",
    1055             :         .id_table =     mousedev_ids,
    1056             : };
    1057             : 
    1058             : #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
    1059           1 : static struct miscdevice psaux_mouse = {
    1060             :         PSMOUSE_MINOR, "psaux", &mousedev_fops
    1061             : };
    1062           1 : static int psaux_registered;
    1063             : #endif
    1064             : 
    1065             : static int __init mousedev_init(void)
    1066             : {
    1067           1 :         int error;
    1068           1 : 
    1069           4 :         mousedev_mix = mousedev_create(NULL, &mousedev_handler, MOUSEDEV_MIX);
    1070           4 :         if (IS_ERR(mousedev_mix))
    1071           3 :                 return PTR_ERR(mousedev_mix);
    1072             : 
    1073           1 :         error = input_register_handler(&mousedev_handler);
    1074           2 :         if (error) {
    1075           2 :                 mousedev_destroy(mousedev_mix);
    1076           1 :                 return error;
    1077             :         }
    1078             : 
    1079             : #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
    1080           2 :         error = misc_register(&psaux_mouse);
    1081           2 :         if (error)
    1082           1 :                 printk(KERN_WARNING "mice: could not register psaux device, "
    1083             :                         "error: %d\n", error);
    1084             :         else
    1085           1 :                 psaux_registered = 1;
    1086             : #endif
    1087             : 
    1088           1 :         printk(KERN_INFO "mice: PS/2 mouse device common for all mice\n");
    1089             : 
    1090           1 :         return 0;
    1091             : }
    1092             : 
    1093             : static void __exit mousedev_exit(void)
    1094             : {
    1095             : #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
    1096           4 :         if (psaux_registered)
    1097           4 :                 misc_deregister(&psaux_mouse);
    1098             : #endif
    1099           4 :         input_unregister_handler(&mousedev_handler);
    1100           8 :         mousedev_destroy(mousedev_mix);
    1101           2 : }
    1102             : 
    1103             : module_init(mousedev_init);
    1104             : module_exit(mousedev_exit);

Generated by: LCOV version 1.10