linux/drivers/input/joydev.c
<<
>>
Prefs
   1/*
   2 * Joystick device driver for the input driver suite.
   3 *
   4 * Copyright (c) 1999-2002 Vojtech Pavlik
   5 * Copyright (c) 1999 Colin Van Dyke
   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 as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 */
  12
  13#include <asm/io.h>
  14#include <asm/system.h>
  15#include <linux/delay.h>
  16#include <linux/errno.h>
  17#include <linux/joystick.h>
  18#include <linux/input.h>
  19#include <linux/kernel.h>
  20#include <linux/major.h>
  21#include <linux/slab.h>
  22#include <linux/mm.h>
  23#include <linux/miscdevice.h>
  24#include <linux/module.h>
  25#include <linux/poll.h>
  26#include <linux/init.h>
  27#include <linux/device.h>
  28
  29MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
  30MODULE_DESCRIPTION("Joystick device interfaces");
  31MODULE_SUPPORTED_DEVICE("input/js");
  32MODULE_LICENSE("GPL");
  33
  34#define JOYDEV_MINOR_BASE       0
  35#define JOYDEV_MINORS           16
  36#define JOYDEV_BUFFER_SIZE      64
  37
  38struct joydev {
  39        int exist;
  40        int open;
  41        int minor;
  42        char name[16];
  43        struct input_handle handle;
  44        wait_queue_head_t wait;
  45        struct list_head client_list;
  46        spinlock_t client_lock; /* protects client_list */
  47        struct mutex mutex;
  48        struct device dev;
  49
  50        struct js_corr corr[ABS_MAX + 1];
  51        struct JS_DATA_SAVE_TYPE glue;
  52        int nabs;
  53        int nkey;
  54        __u16 keymap[KEY_MAX - BTN_MISC + 1];
  55        __u16 keypam[KEY_MAX - BTN_MISC + 1];
  56        __u8 absmap[ABS_MAX + 1];
  57        __u8 abspam[ABS_MAX + 1];
  58        __s16 abs[ABS_MAX + 1];
  59};
  60
  61struct joydev_client {
  62        struct js_event buffer[JOYDEV_BUFFER_SIZE];
  63        int head;
  64        int tail;
  65        int startup;
  66        spinlock_t buffer_lock; /* protects access to buffer, head and tail */
  67        struct fasync_struct *fasync;
  68        struct joydev *joydev;
  69        struct list_head node;
  70};
  71
  72static struct joydev *joydev_table[JOYDEV_MINORS];
  73static DEFINE_MUTEX(joydev_table_mutex);
  74
  75static int joydev_correct(int value, struct js_corr *corr)
  76{
  77        switch (corr->type) {
  78
  79        case JS_CORR_NONE:
  80                break;
  81
  82        case JS_CORR_BROKEN:
  83                value = value > corr->coef[0] ? (value < corr->coef[1] ? 0 :
  84                        ((corr->coef[3] * (value - corr->coef[1])) >> 14)) :
  85                        ((corr->coef[2] * (value - corr->coef[0])) >> 14);
  86                break;
  87
  88        default:
  89                return 0;
  90        }
  91
  92        return value < -32767 ? -32767 : (value > 32767 ? 32767 : value);
  93}
  94
  95static void joydev_pass_event(struct joydev_client *client,
  96                              struct js_event *event)
  97{
  98        struct joydev *joydev = client->joydev;
  99
 100        /*
 101         * IRQs already disabled, just acquire the lock
 102         */
 103        spin_lock(&client->buffer_lock);
 104
 105        client->buffer[client->head] = *event;
 106
 107        if (client->startup == joydev->nabs + joydev->nkey) {
 108                client->head++;
 109                client->head &= JOYDEV_BUFFER_SIZE - 1;
 110                if (client->tail == client->head)
 111                        client->startup = 0;
 112        }
 113
 114        spin_unlock(&client->buffer_lock);
 115
 116        kill_fasync(&client->fasync, SIGIO, POLL_IN);
 117}
 118
 119static void joydev_event(struct input_handle *handle,
 120                         unsigned int type, unsigned int code, int value)
 121{
 122        struct joydev *joydev = handle->private;
 123        struct joydev_client *client;
 124        struct js_event event;
 125
 126        switch (type) {
 127
 128        case EV_KEY:
 129                if (code < BTN_MISC || value == 2)
 130                        return;
 131                event.type = JS_EVENT_BUTTON;
 132                event.number = joydev->keymap[code - BTN_MISC];
 133                event.value = value;
 134                break;
 135
 136        case EV_ABS:
 137                event.type = JS_EVENT_AXIS;
 138                event.number = joydev->absmap[code];
 139                event.value = joydev_correct(value,
 140                                        &joydev->corr[event.number]);
 141                if (event.value == joydev->abs[event.number])
 142                        return;
 143                joydev->abs[event.number] = event.value;
 144                break;
 145
 146        default:
 147                return;
 148        }
 149
 150        event.time = jiffies_to_msecs(jiffies);
 151
 152        rcu_read_lock();
 153        list_for_each_entry_rcu(client, &joydev->client_list, node)
 154                joydev_pass_event(client, &event);
 155        rcu_read_unlock();
 156
 157        wake_up_interruptible(&joydev->wait);
 158}
 159
 160static int joydev_fasync(int fd, struct file *file, int on)
 161{
 162        struct joydev_client *client = file->private_data;
 163
 164        return fasync_helper(fd, file, on, &client->fasync);
 165}
 166
 167static void joydev_free(struct device *dev)
 168{
 169        struct joydev *joydev = container_of(dev, struct joydev, dev);
 170
 171        input_put_device(joydev->handle.dev);
 172        kfree(joydev);
 173}
 174
 175static void joydev_attach_client(struct joydev *joydev,
 176                                 struct joydev_client *client)
 177{
 178        spin_lock(&joydev->client_lock);
 179        list_add_tail_rcu(&client->node, &joydev->client_list);
 180        spin_unlock(&joydev->client_lock);
 181        synchronize_rcu();
 182}
 183
 184static void joydev_detach_client(struct joydev *joydev,
 185                                 struct joydev_client *client)
 186{
 187        spin_lock(&joydev->client_lock);
 188        list_del_rcu(&client->node);
 189        spin_unlock(&joydev->client_lock);
 190        synchronize_rcu();
 191}
 192
 193static int joydev_open_device(struct joydev *joydev)
 194{
 195        int retval;
 196
 197        retval = mutex_lock_interruptible(&joydev->mutex);
 198        if (retval)
 199                return retval;
 200
 201        if (!joydev->exist)
 202                retval = -ENODEV;
 203        else if (!joydev->open++) {
 204                retval = input_open_device(&joydev->handle);
 205                if (retval)
 206                        joydev->open--;
 207        }
 208
 209        mutex_unlock(&joydev->mutex);
 210        return retval;
 211}
 212
 213static void joydev_close_device(struct joydev *joydev)
 214{
 215        mutex_lock(&joydev->mutex);
 216
 217        if (joydev->exist && !--joydev->open)
 218                input_close_device(&joydev->handle);
 219
 220        mutex_unlock(&joydev->mutex);
 221}
 222
 223/*
 224 * Wake up users waiting for IO so they can disconnect from
 225 * dead device.
 226 */
 227static void joydev_hangup(struct joydev *joydev)
 228{
 229        struct joydev_client *client;
 230
 231        spin_lock(&joydev->client_lock);
 232        list_for_each_entry(client, &joydev->client_list, node)
 233                kill_fasync(&client->fasync, SIGIO, POLL_HUP);
 234        spin_unlock(&joydev->client_lock);
 235
 236        wake_up_interruptible(&joydev->wait);
 237}
 238
 239static int joydev_release(struct inode *inode, struct file *file)
 240{
 241        struct joydev_client *client = file->private_data;
 242        struct joydev *joydev = client->joydev;
 243
 244        joydev_detach_client(joydev, client);
 245        kfree(client);
 246
 247        joydev_close_device(joydev);
 248        put_device(&joydev->dev);
 249
 250        return 0;
 251}
 252
 253static int joydev_open(struct inode *inode, struct file *file)
 254{
 255        struct joydev_client *client;
 256        struct joydev *joydev;
 257        int i = iminor(inode) - JOYDEV_MINOR_BASE;
 258        int error;
 259
 260        if (i >= JOYDEV_MINORS)
 261                return -ENODEV;
 262
 263        error = mutex_lock_interruptible(&joydev_table_mutex);
 264        if (error)
 265                return error;
 266        joydev = joydev_table[i];
 267        if (joydev)
 268                get_device(&joydev->dev);
 269        mutex_unlock(&joydev_table_mutex);
 270
 271        if (!joydev)
 272                return -ENODEV;
 273
 274        client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
 275        if (!client) {
 276                error = -ENOMEM;
 277                goto err_put_joydev;
 278        }
 279
 280        spin_lock_init(&client->buffer_lock);
 281        client->joydev = joydev;
 282        joydev_attach_client(joydev, client);
 283
 284        error = joydev_open_device(joydev);
 285        if (error)
 286                goto err_free_client;
 287
 288        file->private_data = client;
 289        return 0;
 290
 291 err_free_client:
 292        joydev_detach_client(joydev, client);
 293        kfree(client);
 294 err_put_joydev:
 295        put_device(&joydev->dev);
 296        return error;
 297}
 298
 299static int joydev_generate_startup_event(struct joydev_client *client,
 300                                         struct input_dev *input,
 301                                         struct js_event *event)
 302{
 303        struct joydev *joydev = client->joydev;
 304        int have_event;
 305
 306        spin_lock_irq(&client->buffer_lock);
 307
 308        have_event = client->startup < joydev->nabs + joydev->nkey;
 309
 310        if (have_event) {
 311
 312                event->time = jiffies_to_msecs(jiffies);
 313                if (client->startup < joydev->nkey) {
 314                        event->type = JS_EVENT_BUTTON | JS_EVENT_INIT;
 315                        event->number = client->startup;
 316                        event->value = !!test_bit(joydev->keypam[event->number],
 317                                                  input->key);
 318                } else {
 319                        event->type = JS_EVENT_AXIS | JS_EVENT_INIT;
 320                        event->number = client->startup - joydev->nkey;
 321                        event->value = joydev->abs[event->number];
 322                }
 323                client->startup++;
 324        }
 325
 326        spin_unlock_irq(&client->buffer_lock);
 327
 328        return have_event;
 329}
 330
 331static int joydev_fetch_next_event(struct joydev_client *client,
 332                                   struct js_event *event)
 333{
 334        int have_event;
 335
 336        spin_lock_irq(&client->buffer_lock);
 337
 338        have_event = client->head != client->tail;
 339        if (have_event) {
 340                *event = client->buffer[client->tail++];
 341                client->tail &= JOYDEV_BUFFER_SIZE - 1;
 342        }
 343
 344        spin_unlock_irq(&client->buffer_lock);
 345
 346        return have_event;
 347}
 348
 349/*
 350 * Old joystick interface
 351 */
 352static ssize_t joydev_0x_read(struct joydev_client *client,
 353                              struct input_dev *input,
 354                              char __user *buf)
 355{
 356        struct joydev *joydev = client->joydev;
 357        struct JS_DATA_TYPE data;
 358        int i;
 359
 360        spin_lock_irq(&input->event_lock);
 361
 362        /*
 363         * Get device state
 364         */
 365        for (data.buttons = i = 0; i < 32 && i < joydev->nkey; i++)
 366                data.buttons |=
 367                        test_bit(joydev->keypam[i], input->key) ? (1 << i) : 0;
 368        data.x = (joydev->abs[0] / 256 + 128) >> joydev->glue.JS_CORR.x;
 369        data.y = (joydev->abs[1] / 256 + 128) >> joydev->glue.JS_CORR.y;
 370
 371        /*
 372         * Reset reader's event queue
 373         */
 374        spin_lock(&client->buffer_lock);
 375        client->startup = 0;
 376        client->tail = client->head;
 377        spin_unlock(&client->buffer_lock);
 378
 379        spin_unlock_irq(&input->event_lock);
 380
 381        if (copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE)))
 382                return -EFAULT;
 383
 384        return sizeof(struct JS_DATA_TYPE);
 385}
 386
 387static inline int joydev_data_pending(struct joydev_client *client)
 388{
 389        struct joydev *joydev = client->joydev;
 390
 391        return client->startup < joydev->nabs + joydev->nkey ||
 392                client->head != client->tail;
 393}
 394
 395static ssize_t joydev_read(struct file *file, char __user *buf,
 396                           size_t count, loff_t *ppos)
 397{
 398        struct joydev_client *client = file->private_data;
 399        struct joydev *joydev = client->joydev;
 400        struct input_dev *input = joydev->handle.dev;
 401        struct js_event event;
 402        int retval;
 403
 404        if (!joydev->exist)
 405                return -ENODEV;
 406
 407        if (count < sizeof(struct js_event))
 408                return -EINVAL;
 409
 410        if (count == sizeof(struct JS_DATA_TYPE))
 411                return joydev_0x_read(client, input, buf);
 412
 413        if (!joydev_data_pending(client) && (file->f_flags & O_NONBLOCK))
 414                return -EAGAIN;
 415
 416        retval = wait_event_interruptible(joydev->wait,
 417                        !joydev->exist || joydev_data_pending(client));
 418        if (retval)
 419                return retval;
 420
 421        if (!joydev->exist)
 422                return -ENODEV;
 423
 424        while (retval + sizeof(struct js_event) <= count &&
 425               joydev_generate_startup_event(client, input, &event)) {
 426
 427                if (copy_to_user(buf + retval, &event, sizeof(struct js_event)))
 428                        return -EFAULT;
 429
 430                retval += sizeof(struct js_event);
 431        }
 432
 433        while (retval + sizeof(struct js_event) <= count &&
 434               joydev_fetch_next_event(client, &event)) {
 435
 436                if (copy_to_user(buf + retval, &event, sizeof(struct js_event)))
 437                        return -EFAULT;
 438
 439                retval += sizeof(struct js_event);
 440        }
 441
 442        return retval;
 443}
 444
 445/* No kernel lock - fine */
 446static unsigned int joydev_poll(struct file *file, poll_table *wait)
 447{
 448        struct joydev_client *client = file->private_data;
 449        struct joydev *joydev = client->joydev;
 450
 451        poll_wait(file, &joydev->wait, wait);
 452        return (joydev_data_pending(client) ? (POLLIN | POLLRDNORM) : 0) |
 453                (joydev->exist ?  0 : (POLLHUP | POLLERR));
 454}
 455
 456static int joydev_ioctl_common(struct joydev *joydev,
 457                                unsigned int cmd, void __user *argp)
 458{
 459        struct input_dev *dev = joydev->handle.dev;
 460        int i, j;
 461
 462        switch (cmd) {
 463
 464        case JS_SET_CAL:
 465                return copy_from_user(&joydev->glue.JS_CORR, argp,
 466                                sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0;
 467
 468        case JS_GET_CAL:
 469                return copy_to_user(argp, &joydev->glue.JS_CORR,
 470                                sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0;
 471
 472        case JS_SET_TIMEOUT:
 473                return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp);
 474
 475        case JS_GET_TIMEOUT:
 476                return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp);
 477
 478        case JSIOCGVERSION:
 479                return put_user(JS_VERSION, (__u32 __user *) argp);
 480
 481        case JSIOCGAXES:
 482                return put_user(joydev->nabs, (__u8 __user *) argp);
 483
 484        case JSIOCGBUTTONS:
 485                return put_user(joydev->nkey, (__u8 __user *) argp);
 486
 487        case JSIOCSCORR:
 488                if (copy_from_user(joydev->corr, argp,
 489                              sizeof(joydev->corr[0]) * joydev->nabs))
 490                    return -EFAULT;
 491
 492                for (i = 0; i < joydev->nabs; i++) {
 493                        j = joydev->abspam[i];
 494                        joydev->abs[i] = joydev_correct(dev->abs[j],
 495                                                        &joydev->corr[i]);
 496                }
 497                return 0;
 498
 499        case JSIOCGCORR:
 500                return copy_to_user(argp, joydev->corr,
 501                        sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0;
 502
 503        case JSIOCSAXMAP:
 504                if (copy_from_user(joydev->abspam, argp,
 505                                   sizeof(__u8) * (ABS_MAX + 1)))
 506                        return -EFAULT;
 507
 508                for (i = 0; i < joydev->nabs; i++) {
 509                        if (joydev->abspam[i] > ABS_MAX)
 510                                return -EINVAL;
 511                        joydev->absmap[joydev->abspam[i]] = i;
 512                }
 513                return 0;
 514
 515        case JSIOCGAXMAP:
 516                return copy_to_user(argp, joydev->abspam,
 517                        sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0;
 518
 519        case JSIOCSBTNMAP:
 520                if (copy_from_user(joydev->keypam, argp,
 521                                   sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)))
 522                        return -EFAULT;
 523
 524                for (i = 0; i < joydev->nkey; i++) {
 525                        if (joydev->keypam[i] > KEY_MAX ||
 526                            joydev->keypam[i] < BTN_MISC)
 527                                return -EINVAL;
 528                        joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
 529                }
 530
 531                return 0;
 532
 533        case JSIOCGBTNMAP:
 534                return copy_to_user(argp, joydev->keypam,
 535                        sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0;
 536
 537        default:
 538                if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) {
 539                        int len;
 540                        if (!dev->name)
 541                                return 0;
 542                        len = strlen(dev->name) + 1;
 543                        if (len > _IOC_SIZE(cmd))
 544                                len = _IOC_SIZE(cmd);
 545                        if (copy_to_user(argp, dev->name, len))
 546                                return -EFAULT;
 547                        return len;
 548                }
 549        }
 550        return -EINVAL;
 551}
 552
 553#ifdef CONFIG_COMPAT
 554static long joydev_compat_ioctl(struct file *file,
 555                                unsigned int cmd, unsigned long arg)
 556{
 557        struct joydev_client *client = file->private_data;
 558        struct joydev *joydev = client->joydev;
 559        void __user *argp = (void __user *)arg;
 560        s32 tmp32;
 561        struct JS_DATA_SAVE_TYPE_32 ds32;
 562        int retval;
 563
 564        retval = mutex_lock_interruptible(&joydev->mutex);
 565        if (retval)
 566                return retval;
 567
 568        if (!joydev->exist) {
 569                retval = -ENODEV;
 570                goto out;
 571        }
 572
 573        switch (cmd) {
 574
 575        case JS_SET_TIMELIMIT:
 576                retval = get_user(tmp32, (s32 __user *) arg);
 577                if (retval == 0)
 578                        joydev->glue.JS_TIMELIMIT = tmp32;
 579                break;
 580
 581        case JS_GET_TIMELIMIT:
 582                tmp32 = joydev->glue.JS_TIMELIMIT;
 583                retval = put_user(tmp32, (s32 __user *) arg);
 584                break;
 585
 586        case JS_SET_ALL:
 587                retval = copy_from_user(&ds32, argp,
 588                                        sizeof(ds32)) ? -EFAULT : 0;
 589                if (retval == 0) {
 590                        joydev->glue.JS_TIMEOUT    = ds32.JS_TIMEOUT;
 591                        joydev->glue.BUSY          = ds32.BUSY;
 592                        joydev->glue.JS_EXPIRETIME = ds32.JS_EXPIRETIME;
 593                        joydev->glue.JS_TIMELIMIT  = ds32.JS_TIMELIMIT;
 594                        joydev->glue.JS_SAVE       = ds32.JS_SAVE;
 595                        joydev->glue.JS_CORR       = ds32.JS_CORR;
 596                }
 597                break;
 598
 599        case JS_GET_ALL:
 600                ds32.JS_TIMEOUT    = joydev->glue.JS_TIMEOUT;
 601                ds32.BUSY          = joydev->glue.BUSY;
 602                ds32.JS_EXPIRETIME = joydev->glue.JS_EXPIRETIME;
 603                ds32.JS_TIMELIMIT  = joydev->glue.JS_TIMELIMIT;
 604                ds32.JS_SAVE       = joydev->glue.JS_SAVE;
 605                ds32.JS_CORR       = joydev->glue.JS_CORR;
 606
 607                retval = copy_to_user(argp, &ds32, sizeof(ds32)) ? -EFAULT : 0;
 608                break;
 609
 610        default:
 611                retval = joydev_ioctl_common(joydev, cmd, argp);
 612                break;
 613        }
 614
 615 out:
 616        mutex_unlock(&joydev->mutex);
 617        return retval;
 618}
 619#endif /* CONFIG_COMPAT */
 620
 621static long joydev_ioctl(struct file *file,
 622                         unsigned int cmd, unsigned long arg)
 623{
 624        struct joydev_client *client = file->private_data;
 625        struct joydev *joydev = client->joydev;
 626        void __user *argp = (void __user *)arg;
 627        int retval;
 628
 629        retval = mutex_lock_interruptible(&joydev->mutex);
 630        if (retval)
 631                return retval;
 632
 633        if (!joydev->exist) {
 634                retval = -ENODEV;
 635                goto out;
 636        }
 637
 638        switch (cmd) {
 639
 640        case JS_SET_TIMELIMIT:
 641                retval = get_user(joydev->glue.JS_TIMELIMIT,
 642                                  (long __user *) arg);
 643                break;
 644
 645        case JS_GET_TIMELIMIT:
 646                retval = put_user(joydev->glue.JS_TIMELIMIT,
 647                                  (long __user *) arg);
 648                break;
 649
 650        case JS_SET_ALL:
 651                retval = copy_from_user(&joydev->glue, argp,
 652                                        sizeof(joydev->glue)) ? -EFAULT: 0;
 653                break;
 654
 655        case JS_GET_ALL:
 656                retval = copy_to_user(argp, &joydev->glue,
 657                                      sizeof(joydev->glue)) ? -EFAULT : 0;
 658                break;
 659
 660        default:
 661                retval = joydev_ioctl_common(joydev, cmd, argp);
 662                break;
 663        }
 664 out:
 665        mutex_unlock(&joydev->mutex);
 666        return retval;
 667}
 668
 669static const struct file_operations joydev_fops = {
 670        .owner          = THIS_MODULE,
 671        .read           = joydev_read,
 672        .poll           = joydev_poll,
 673        .open           = joydev_open,
 674        .release        = joydev_release,
 675        .unlocked_ioctl = joydev_ioctl,
 676#ifdef CONFIG_COMPAT
 677        .compat_ioctl   = joydev_compat_ioctl,
 678#endif
 679        .fasync         = joydev_fasync,
 680};
 681
 682static int joydev_install_chrdev(struct joydev *joydev)
 683{
 684        joydev_table[joydev->minor] = joydev;
 685        return 0;
 686}
 687
 688static void joydev_remove_chrdev(struct joydev *joydev)
 689{
 690        mutex_lock(&joydev_table_mutex);
 691        joydev_table[joydev->minor] = NULL;
 692        mutex_unlock(&joydev_table_mutex);
 693}
 694
 695/*
 696 * Mark device non-existant. This disables writes, ioctls and
 697 * prevents new users from opening the device. Already posted
 698 * blocking reads will stay, however new ones will fail.
 699 */
 700static void joydev_mark_dead(struct joydev *joydev)
 701{
 702        mutex_lock(&joydev->mutex);
 703        joydev->exist = 0;
 704        mutex_unlock(&joydev->mutex);
 705}
 706
 707static void joydev_cleanup(struct joydev *joydev)
 708{
 709        struct input_handle *handle = &joydev->handle;
 710
 711        joydev_mark_dead(joydev);
 712        joydev_hangup(joydev);
 713        joydev_remove_chrdev(joydev);
 714
 715        /* joydev is marked dead so noone else accesses joydev->open */
 716        if (joydev->open)
 717                input_close_device(handle);
 718}
 719
 720static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
 721                          const struct input_device_id *id)
 722{
 723        struct joydev *joydev;
 724        int i, j, t, minor;
 725        int error;
 726
 727        for (minor = 0; minor < JOYDEV_MINORS; minor++)
 728                if (!joydev_table[minor])
 729                        break;
 730
 731        if (minor == JOYDEV_MINORS) {
 732                printk(KERN_ERR "joydev: no more free joydev devices\n");
 733                return -ENFILE;
 734        }
 735
 736        joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL);
 737        if (!joydev)
 738                return -ENOMEM;
 739
 740        INIT_LIST_HEAD(&joydev->client_list);
 741        spin_lock_init(&joydev->client_lock);
 742        mutex_init(&joydev->mutex);
 743        init_waitqueue_head(&joydev->wait);
 744
 745        snprintf(joydev->name, sizeof(joydev->name), "js%d", minor);
 746        joydev->exist = 1;
 747        joydev->minor = minor;
 748
 749        joydev->exist = 1;
 750        joydev->handle.dev = input_get_device(dev);
 751        joydev->handle.name = joydev->name;
 752        joydev->handle.handler = handler;
 753        joydev->handle.private = joydev;
 754
 755        for (i = 0; i < ABS_MAX + 1; i++)
 756                if (test_bit(i, dev->absbit)) {
 757                        joydev->absmap[i] = joydev->nabs;
 758                        joydev->abspam[joydev->nabs] = i;
 759                        joydev->nabs++;
 760                }
 761
 762        for (i = BTN_JOYSTICK - BTN_MISC; i < KEY_MAX - BTN_MISC + 1; i++)
 763                if (test_bit(i + BTN_MISC, dev->keybit)) {
 764                        joydev->keymap[i] = joydev->nkey;
 765                        joydev->keypam[joydev->nkey] = i + BTN_MISC;
 766                        joydev->nkey++;
 767                }
 768
 769        for (i = 0; i < BTN_JOYSTICK - BTN_MISC; i++)
 770                if (test_bit(i + BTN_MISC, dev->keybit)) {
 771                        joydev->keymap[i] = joydev->nkey;
 772                        joydev->keypam[joydev->nkey] = i + BTN_MISC;
 773                        joydev->nkey++;
 774                }
 775
 776        for (i = 0; i < joydev->nabs; i++) {
 777                j = joydev->abspam[i];
 778                if (dev->absmax[j] == dev->absmin[j]) {
 779                        joydev->corr[i].type = JS_CORR_NONE;
 780                        joydev->abs[i] = dev->abs[j];
 781                        continue;
 782                }
 783                joydev->corr[i].type = JS_CORR_BROKEN;
 784                joydev->corr[i].prec = dev->absfuzz[j];
 785                joydev->corr[i].coef[0] =
 786                        (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j];
 787                joydev->corr[i].coef[1] =
 788                        (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j];
 789
 790                t = (dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j];
 791                if (t) {
 792                        joydev->corr[i].coef[2] = (1 << 29) / t;
 793                        joydev->corr[i].coef[3] = (1 << 29) / t;
 794
 795                        joydev->abs[i] = joydev_correct(dev->abs[j],
 796                                                        joydev->corr + i);
 797                }
 798        }
 799
 800        dev_set_name(&joydev->dev, joydev->name);
 801        joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor);
 802        joydev->dev.class = &input_class;
 803        joydev->dev.parent = &dev->dev;
 804        joydev->dev.release = joydev_free;
 805        device_initialize(&joydev->dev);
 806
 807        error = input_register_handle(&joydev->handle);
 808        if (error)
 809                goto err_free_joydev;
 810
 811        error = joydev_install_chrdev(joydev);
 812        if (error)
 813                goto err_unregister_handle;
 814
 815        error = device_add(&joydev->dev);
 816        if (error)
 817                goto err_cleanup_joydev;
 818
 819        return 0;
 820
 821 err_cleanup_joydev:
 822        joydev_cleanup(joydev);
 823 err_unregister_handle:
 824        input_unregister_handle(&joydev->handle);
 825 err_free_joydev:
 826        put_device(&joydev->dev);
 827        return error;
 828}
 829
 830static void joydev_disconnect(struct input_handle *handle)
 831{
 832        struct joydev *joydev = handle->private;
 833
 834        device_del(&joydev->dev);
 835        joydev_cleanup(joydev);
 836        input_unregister_handle(handle);
 837        put_device(&joydev->dev);
 838}
 839
 840static const struct input_device_id joydev_blacklist[] = {
 841        {
 842                .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
 843                                INPUT_DEVICE_ID_MATCH_KEYBIT,
 844                .evbit = { BIT_MASK(EV_KEY) },
 845                .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
 846        },      /* Avoid itouchpads and touchscreens */
 847        {
 848                .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
 849                                INPUT_DEVICE_ID_MATCH_KEYBIT,
 850                .evbit = { BIT_MASK(EV_KEY) },
 851                .keybit = { [BIT_WORD(BTN_DIGI)] = BIT_MASK(BTN_DIGI) },
 852        },      /* Avoid tablets, digitisers and similar devices */
 853        { }     /* Terminating entry */
 854};
 855
 856static const struct input_device_id joydev_ids[] = {
 857        {
 858                .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
 859                                INPUT_DEVICE_ID_MATCH_ABSBIT,
 860                .evbit = { BIT_MASK(EV_ABS) },
 861                .absbit = { BIT_MASK(ABS_X) },
 862        },
 863        {
 864                .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
 865                                INPUT_DEVICE_ID_MATCH_ABSBIT,
 866                .evbit = { BIT_MASK(EV_ABS) },
 867                .absbit = { BIT_MASK(ABS_WHEEL) },
 868        },
 869        {
 870                .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
 871                                INPUT_DEVICE_ID_MATCH_ABSBIT,
 872                .evbit = { BIT_MASK(EV_ABS) },
 873                .absbit = { BIT_MASK(ABS_THROTTLE) },
 874        },
 875        { }     /* Terminating entry */
 876};
 877
 878MODULE_DEVICE_TABLE(input, joydev_ids);
 879
 880static struct input_handler joydev_handler = {
 881        .event          = joydev_event,
 882        .connect        = joydev_connect,
 883        .disconnect     = joydev_disconnect,
 884        .fops           = &joydev_fops,
 885        .minor          = JOYDEV_MINOR_BASE,
 886        .name           = "joydev",
 887        .id_table       = joydev_ids,
 888        .blacklist      = joydev_blacklist,
 889};
 890
 891static int __init joydev_init(void)
 892{
 893        return input_register_handler(&joydev_handler);
 894}
 895
 896static void __exit joydev_exit(void)
 897{
 898        input_unregister_handler(&joydev_handler);
 899}
 900
 901module_init(joydev_init);
 902module_exit(joydev_exit);
 903
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.