linux/drivers/input/keyboard/hil_kbd.c
<<
>>
Prefs
   1/*
   2 * Generic linux-input device driver for keyboard devices
   3 *
   4 * Copyright (c) 2001 Brian S. Julin
   5 * All rights reserved.
   6 *
   7 * Redistribution and use in source and binary forms, with or without
   8 * modification, are permitted provided that the following conditions
   9 * are met:
  10 * 1. Redistributions of source code must retain the above copyright
  11 *    notice, this list of conditions, and the following disclaimer,
  12 *    without modification.
  13 * 2. The name of the author may not be used to endorse or promote products
  14 *    derived from this software without specific prior written permission.
  15 *
  16 * Alternatively, this software may be distributed under the terms of the
  17 * GNU General Public License ("GPL").
  18 *
  19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28 *
  29 * References:
  30 * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
  31 *
  32 */
  33
  34#include <linux/hil.h>
  35#include <linux/input.h>
  36#include <linux/serio.h>
  37#include <linux/kernel.h>
  38#include <linux/module.h>
  39#include <linux/init.h>
  40#include <linux/slab.h>
  41#include <linux/pci_ids.h>
  42
  43#define PREFIX "HIL KEYB: "
  44#define HIL_GENERIC_NAME "HIL keyboard"
  45
  46MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
  47MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver");
  48MODULE_LICENSE("Dual BSD/GPL");
  49
  50#define HIL_KBD_MAX_LENGTH 16
  51
  52#define HIL_KBD_SET1_UPBIT 0x01
  53#define HIL_KBD_SET1_SHIFT 1
  54static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] __read_mostly =
  55        { HIL_KEYCODES_SET1 };
  56
  57#define HIL_KBD_SET2_UPBIT 0x01
  58#define HIL_KBD_SET2_SHIFT 1
  59/* Set2 is user defined */
  60
  61#define HIL_KBD_SET3_UPBIT 0x80
  62#define HIL_KBD_SET3_SHIFT 0
  63static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] __read_mostly =
  64        { HIL_KEYCODES_SET3 };
  65
  66static const char hil_language[][16] = { HIL_LOCALE_MAP };
  67
  68struct hil_kbd {
  69        struct input_dev *dev;
  70        struct serio *serio;
  71
  72        /* Input buffer and index for packets from HIL bus. */
  73        hil_packet data[HIL_KBD_MAX_LENGTH];
  74        int idx4; /* four counts per packet */
  75
  76        /* Raw device info records from HIL bus, see hil.h for fields. */
  77        char    idd[HIL_KBD_MAX_LENGTH];        /* DID byte and IDD record */
  78        char    rsc[HIL_KBD_MAX_LENGTH];        /* RSC record */
  79        char    exd[HIL_KBD_MAX_LENGTH];        /* EXD record */
  80        char    rnm[HIL_KBD_MAX_LENGTH + 1];    /* RNM record + NULL term. */
  81
  82        /* Something to sleep around with. */
  83        struct semaphore sem;
  84};
  85
  86/* Process a complete packet after transfer from the HIL */
  87static void hil_kbd_process_record(struct hil_kbd *kbd)
  88{
  89        struct input_dev *dev = kbd->dev;
  90        hil_packet *data = kbd->data;
  91        hil_packet p;
  92        int idx, i, cnt;
  93
  94        idx = kbd->idx4/4;
  95        p = data[idx - 1];
  96
  97        if ((p & ~HIL_CMDCT_POL) ==
  98            (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL))
  99                goto report;
 100        if ((p & ~HIL_CMDCT_RPL) ==
 101            (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL))
 102                goto report;
 103
 104        /* Not a poll response.  See if we are loading config records. */
 105        switch (p & HIL_PKT_DATA_MASK) {
 106        case HIL_CMD_IDD:
 107                for (i = 0; i < idx; i++)
 108                        kbd->idd[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
 109                for (; i < HIL_KBD_MAX_LENGTH; i++)
 110                        kbd->idd[i] = 0;
 111                break;
 112
 113        case HIL_CMD_RSC:
 114                for (i = 0; i < idx; i++)
 115                        kbd->rsc[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
 116                for (; i < HIL_KBD_MAX_LENGTH; i++)
 117                        kbd->rsc[i] = 0;
 118                break;
 119
 120        case HIL_CMD_EXD:
 121                for (i = 0; i < idx; i++)
 122                        kbd->exd[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
 123                for (; i < HIL_KBD_MAX_LENGTH; i++)
 124                        kbd->exd[i] = 0;
 125                break;
 126
 127        case HIL_CMD_RNM:
 128                for (i = 0; i < idx; i++)
 129                        kbd->rnm[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
 130                for (; i < HIL_KBD_MAX_LENGTH + 1; i++)
 131                        kbd->rnm[i] = '\0';
 132                break;
 133
 134        default:
 135                /* These occur when device isn't present */
 136                if (p == (HIL_ERR_INT | HIL_PKT_CMD))
 137                        break;
 138                /* Anything else we'd like to know about. */
 139                printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
 140                break;
 141        }
 142        goto out;
 143
 144 report:
 145        cnt = 1;
 146        switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) {
 147        case HIL_POL_CHARTYPE_NONE:
 148                break;
 149
 150        case HIL_POL_CHARTYPE_ASCII:
 151                while (cnt < idx - 1)
 152                        input_report_key(dev, kbd->data[cnt++] & 0x7f, 1);
 153                break;
 154
 155        case HIL_POL_CHARTYPE_RSVD1:
 156        case HIL_POL_CHARTYPE_RSVD2:
 157        case HIL_POL_CHARTYPE_BINARY:
 158                while (cnt < idx - 1)
 159                        input_report_key(dev, kbd->data[cnt++], 1);
 160                break;
 161
 162        case HIL_POL_CHARTYPE_SET1:
 163                while (cnt < idx - 1) {
 164                        unsigned int key;
 165                        int up;
 166                        key = kbd->data[cnt++];
 167                        up = key & HIL_KBD_SET1_UPBIT;
 168                        key &= (~HIL_KBD_SET1_UPBIT & 0xff);
 169                        key = hil_kbd_set1[key >> HIL_KBD_SET1_SHIFT];
 170                        if (key != KEY_RESERVED)
 171                                input_report_key(dev, key, !up);
 172                }
 173                break;
 174
 175        case HIL_POL_CHARTYPE_SET2:
 176                while (cnt < idx - 1) {
 177                        unsigned int key;
 178                        int up;
 179                        key = kbd->data[cnt++];
 180                        up = key & HIL_KBD_SET2_UPBIT;
 181                        key &= (~HIL_KBD_SET1_UPBIT & 0xff);
 182                        key = key >> HIL_KBD_SET2_SHIFT;
 183                        if (key != KEY_RESERVED)
 184                                input_report_key(dev, key, !up);
 185                }
 186                break;
 187
 188        case HIL_POL_CHARTYPE_SET3:
 189                while (cnt < idx - 1) {
 190                        unsigned int key;
 191                        int up;
 192                        key = kbd->data[cnt++];
 193                        up = key & HIL_KBD_SET3_UPBIT;
 194                        key &= (~HIL_KBD_SET1_UPBIT & 0xff);
 195                        key = hil_kbd_set3[key >> HIL_KBD_SET3_SHIFT];
 196                        if (key != KEY_RESERVED)
 197                                input_report_key(dev, key, !up);
 198                }
 199                break;
 200        }
 201 out:
 202        kbd->idx4 = 0;
 203        up(&kbd->sem);
 204}
 205
 206static void hil_kbd_process_err(struct hil_kbd *kbd)
 207{
 208        printk(KERN_WARNING PREFIX "errored HIL packet\n");
 209        kbd->idx4 = 0;
 210        up(&kbd->sem);
 211}
 212
 213static irqreturn_t hil_kbd_interrupt(struct serio *serio,
 214                                unsigned char data, unsigned int flags)
 215{
 216        struct hil_kbd *kbd;
 217        hil_packet packet;
 218        int idx;
 219
 220        kbd = serio_get_drvdata(serio);
 221        BUG_ON(kbd == NULL);
 222
 223        if (kbd->idx4 >= (HIL_KBD_MAX_LENGTH * sizeof(hil_packet))) {
 224                hil_kbd_process_err(kbd);
 225                return IRQ_HANDLED;
 226        }
 227        idx = kbd->idx4/4;
 228        if (!(kbd->idx4 % 4))
 229                kbd->data[idx] = 0;
 230        packet = kbd->data[idx];
 231        packet |= ((hil_packet)data) << ((3 - (kbd->idx4 % 4)) * 8);
 232        kbd->data[idx] = packet;
 233
 234        /* Records of N 4-byte hil_packets must terminate with a command. */
 235        if ((++(kbd->idx4)) % 4)
 236                return IRQ_HANDLED;
 237        if ((packet & 0xffff0000) != HIL_ERR_INT) {
 238                hil_kbd_process_err(kbd);
 239                return IRQ_HANDLED;
 240        }
 241        if (packet & HIL_PKT_CMD)
 242                hil_kbd_process_record(kbd);
 243        return IRQ_HANDLED;
 244}
 245
 246static void hil_kbd_disconnect(struct serio *serio)
 247{
 248        struct hil_kbd *kbd;
 249
 250        kbd = serio_get_drvdata(serio);
 251        BUG_ON(kbd == NULL);
 252
 253        serio_close(serio);
 254        input_unregister_device(kbd->dev);
 255        kfree(kbd);
 256}
 257
 258static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
 259{
 260        struct hil_kbd  *kbd;
 261        uint8_t         did, *idd;
 262        int             i;
 263
 264        kbd = kzalloc(sizeof(*kbd), GFP_KERNEL);
 265        if (!kbd)
 266                return -ENOMEM;
 267
 268        kbd->dev = input_allocate_device();
 269        if (!kbd->dev)
 270                goto bail0;
 271
 272        if (serio_open(serio, drv))
 273                goto bail1;
 274
 275        serio_set_drvdata(serio, kbd);
 276        kbd->serio = serio;
 277
 278        init_MUTEX_LOCKED(&kbd->sem);
 279
 280        /* Get device info.  MLC driver supplies devid/status/etc. */
 281        serio->write(serio, 0);
 282        serio->write(serio, 0);
 283        serio->write(serio, HIL_PKT_CMD >> 8);
 284        serio->write(serio, HIL_CMD_IDD);
 285        down(&kbd->sem);
 286
 287        serio->write(serio, 0);
 288        serio->write(serio, 0);
 289        serio->write(serio, HIL_PKT_CMD >> 8);
 290        serio->write(serio, HIL_CMD_RSC);
 291        down(&kbd->sem);
 292
 293        serio->write(serio, 0);
 294        serio->write(serio, 0);
 295        serio->write(serio, HIL_PKT_CMD >> 8);
 296        serio->write(serio, HIL_CMD_RNM);
 297        down(&kbd->sem);
 298
 299        serio->write(serio, 0);
 300        serio->write(serio, 0);
 301        serio->write(serio, HIL_PKT_CMD >> 8);
 302        serio->write(serio, HIL_CMD_EXD);
 303        down(&kbd->sem);
 304
 305        up(&kbd->sem);
 306
 307        did = kbd->idd[0];
 308        idd = kbd->idd + 1;
 309        switch (did & HIL_IDD_DID_TYPE_MASK) {
 310        case HIL_IDD_DID_TYPE_KB_INTEGRAL:
 311        case HIL_IDD_DID_TYPE_KB_ITF:
 312        case HIL_IDD_DID_TYPE_KB_RSVD:
 313        case HIL_IDD_DID_TYPE_CHAR:
 314                printk(KERN_INFO PREFIX "HIL keyboard found (did = 0x%02x, lang = %s)\n",
 315                        did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]);
 316                break;
 317        default:
 318                goto bail2;
 319        }
 320
 321        if (HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) {
 322                printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n");
 323                goto bail2;
 324        }
 325
 326        kbd->dev->evbit[0]      = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
 327        kbd->dev->ledbit[0]     = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) |
 328                BIT_MASK(LED_SCROLLL);
 329        kbd->dev->keycodemax    = HIL_KEYCODES_SET1_TBLSIZE;
 330        kbd->dev->keycodesize   = sizeof(hil_kbd_set1[0]);
 331        kbd->dev->keycode       = hil_kbd_set1;
 332        kbd->dev->name          = strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME;
 333        kbd->dev->phys          = "hpkbd/input0";       /* XXX */
 334
 335        kbd->dev->id.bustype    = BUS_HIL;
 336        kbd->dev->id.vendor     = PCI_VENDOR_ID_HP;
 337        kbd->dev->id.product    = 0x0001; /* TODO: get from kbd->rsc */
 338        kbd->dev->id.version    = 0x0100; /* TODO: get from kbd->rsc */
 339        kbd->dev->dev.parent    = &serio->dev;
 340
 341        for (i = 0; i < 128; i++) {
 342                set_bit(hil_kbd_set1[i], kbd->dev->keybit);
 343                set_bit(hil_kbd_set3[i], kbd->dev->keybit);
 344        }
 345        clear_bit(0, kbd->dev->keybit);
 346
 347        input_register_device(kbd->dev);
 348        printk(KERN_INFO "input: %s, ID: %d\n",
 349                kbd->dev->name, did);
 350
 351        serio->write(serio, 0);
 352        serio->write(serio, 0);
 353        serio->write(serio, HIL_PKT_CMD >> 8);
 354        serio->write(serio, HIL_CMD_EK1); /* Enable Keyswitch Autorepeat 1 */
 355        down(&kbd->sem);
 356        up(&kbd->sem);
 357
 358        return 0;
 359 bail2:
 360        serio_close(serio);
 361        serio_set_drvdata(serio, NULL);
 362 bail1:
 363        input_free_device(kbd->dev);
 364 bail0:
 365        kfree(kbd);
 366        return -EIO;
 367}
 368
 369static struct serio_device_id hil_kbd_ids[] = {
 370        {
 371                .type = SERIO_HIL_MLC,
 372                .proto = SERIO_HIL,
 373                .id = SERIO_ANY,
 374                .extra = SERIO_ANY,
 375        },
 376        { 0 }
 377};
 378
 379static struct serio_driver hil_kbd_serio_drv = {
 380        .driver         = {
 381                .name   = "hil_kbd",
 382        },
 383        .description    = "HP HIL keyboard driver",
 384        .id_table       = hil_kbd_ids,
 385        .connect        = hil_kbd_connect,
 386        .disconnect     = hil_kbd_disconnect,
 387        .interrupt      = hil_kbd_interrupt
 388};
 389
 390static int __init hil_kbd_init(void)
 391{
 392        return serio_register_driver(&hil_kbd_serio_drv);
 393}
 394
 395static void __exit hil_kbd_exit(void)
 396{
 397        serio_unregister_driver(&hil_kbd_serio_drv);
 398}
 399
 400module_init(hil_kbd_init);
 401module_exit(hil_kbd_exit);
 402