0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 #include <linux/delay.h>
0053 #include <linux/slab.h>
0054 #include <linux/module.h>
0055 #include <linux/interrupt.h>
0056 #include <linux/input.h>
0057 #include <linux/serio.h>
0058 #include <linux/workqueue.h>
0059
0060 #define DRIVER_DESC "LK keyboard driver"
0061
0062 MODULE_AUTHOR("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
0063 MODULE_DESCRIPTION(DRIVER_DESC);
0064 MODULE_LICENSE("GPL");
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074 static int bell_volume = 100;
0075 module_param(bell_volume, int, 0);
0076 MODULE_PARM_DESC(bell_volume, "Bell volume (in %). default is 100%");
0077
0078 static int keyclick_volume = 100;
0079 module_param(keyclick_volume, int, 0);
0080 MODULE_PARM_DESC(keyclick_volume, "Keyclick volume (in %), default is 100%");
0081
0082 static int ctrlclick_volume = 100;
0083 module_param(ctrlclick_volume, int, 0);
0084 MODULE_PARM_DESC(ctrlclick_volume, "Ctrlclick volume (in %), default is 100%");
0085
0086 static int lk201_compose_is_alt;
0087 module_param(lk201_compose_is_alt, int, 0);
0088 MODULE_PARM_DESC(lk201_compose_is_alt,
0089 "If set non-zero, LK201' Compose key will act as an Alt key");
0090
0091
0092
0093 #undef LKKBD_DEBUG
0094 #ifdef LKKBD_DEBUG
0095 #define DBG(x...) printk(x)
0096 #else
0097 #define DBG(x...) do {} while (0)
0098 #endif
0099
0100
0101 #define LK_LED_WAIT 0x81
0102 #define LK_LED_COMPOSE 0x82
0103 #define LK_LED_SHIFTLOCK 0x84
0104 #define LK_LED_SCROLLLOCK 0x88
0105 #define LK_CMD_LED_ON 0x13
0106 #define LK_CMD_LED_OFF 0x11
0107
0108
0109 #define LK_MODE_DOWN 0x80
0110 #define LK_MODE_AUTODOWN 0x82
0111 #define LK_MODE_UPDOWN 0x86
0112 #define LK_CMD_SET_MODE(mode, div) ((mode) | ((div) << 3))
0113
0114
0115 #define LK_CMD_ENABLE_KEYCLICK 0x1b
0116 #define LK_CMD_DISABLE_KEYCLICK 0x99
0117 #define LK_CMD_DISABLE_BELL 0xa1
0118 #define LK_CMD_SOUND_BELL 0xa7
0119 #define LK_CMD_ENABLE_BELL 0x23
0120 #define LK_CMD_DISABLE_CTRCLICK 0xb9
0121 #define LK_CMD_ENABLE_CTRCLICK 0xbb
0122 #define LK_CMD_SET_DEFAULTS 0xd3
0123 #define LK_CMD_POWERCYCLE_RESET 0xfd
0124 #define LK_CMD_ENABLE_LK401 0xe9
0125 #define LK_CMD_REQUEST_ID 0xab
0126
0127
0128 #define LK_STUCK_KEY 0x3d
0129 #define LK_SELFTEST_FAILED 0x3e
0130 #define LK_ALL_KEYS_UP 0xb3
0131 #define LK_METRONOME 0xb4
0132 #define LK_OUTPUT_ERROR 0xb5
0133 #define LK_INPUT_ERROR 0xb6
0134 #define LK_KBD_LOCKED 0xb7
0135 #define LK_KBD_TEST_MODE_ACK 0xb8
0136 #define LK_PREFIX_KEY_DOWN 0xb9
0137 #define LK_MODE_CHANGE_ACK 0xba
0138 #define LK_RESPONSE_RESERVED 0xbb
0139
0140 #define LK_NUM_KEYCODES 256
0141 #define LK_NUM_IGNORE_BYTES 6
0142
0143 static unsigned short lkkbd_keycode[LK_NUM_KEYCODES] = {
0144 [0x56] = KEY_F1,
0145 [0x57] = KEY_F2,
0146 [0x58] = KEY_F3,
0147 [0x59] = KEY_F4,
0148 [0x5a] = KEY_F5,
0149 [0x64] = KEY_F6,
0150 [0x65] = KEY_F7,
0151 [0x66] = KEY_F8,
0152 [0x67] = KEY_F9,
0153 [0x68] = KEY_F10,
0154 [0x71] = KEY_F11,
0155 [0x72] = KEY_F12,
0156 [0x73] = KEY_F13,
0157 [0x74] = KEY_F14,
0158 [0x7c] = KEY_F15,
0159 [0x7d] = KEY_F16,
0160 [0x80] = KEY_F17,
0161 [0x81] = KEY_F18,
0162 [0x82] = KEY_F19,
0163 [0x83] = KEY_F20,
0164 [0x8a] = KEY_FIND,
0165 [0x8b] = KEY_INSERT,
0166 [0x8c] = KEY_DELETE,
0167 [0x8d] = KEY_SELECT,
0168 [0x8e] = KEY_PAGEUP,
0169 [0x8f] = KEY_PAGEDOWN,
0170 [0x92] = KEY_KP0,
0171 [0x94] = KEY_KPDOT,
0172 [0x95] = KEY_KPENTER,
0173 [0x96] = KEY_KP1,
0174 [0x97] = KEY_KP2,
0175 [0x98] = KEY_KP3,
0176 [0x99] = KEY_KP4,
0177 [0x9a] = KEY_KP5,
0178 [0x9b] = KEY_KP6,
0179 [0x9c] = KEY_KPCOMMA,
0180 [0x9d] = KEY_KP7,
0181 [0x9e] = KEY_KP8,
0182 [0x9f] = KEY_KP9,
0183 [0xa0] = KEY_KPMINUS,
0184 [0xa1] = KEY_PROG1,
0185 [0xa2] = KEY_PROG2,
0186 [0xa3] = KEY_PROG3,
0187 [0xa4] = KEY_PROG4,
0188 [0xa7] = KEY_LEFT,
0189 [0xa8] = KEY_RIGHT,
0190 [0xa9] = KEY_DOWN,
0191 [0xaa] = KEY_UP,
0192 [0xab] = KEY_RIGHTSHIFT,
0193 [0xac] = KEY_LEFTALT,
0194 [0xad] = KEY_COMPOSE,
0195 [0xae] = KEY_LEFTSHIFT,
0196 [0xaf] = KEY_LEFTCTRL,
0197 [0xb0] = KEY_CAPSLOCK,
0198 [0xb1] = KEY_COMPOSE,
0199 [0xb2] = KEY_RIGHTALT,
0200 [0xbc] = KEY_BACKSPACE,
0201 [0xbd] = KEY_ENTER,
0202 [0xbe] = KEY_TAB,
0203 [0xbf] = KEY_ESC,
0204 [0xc0] = KEY_1,
0205 [0xc1] = KEY_Q,
0206 [0xc2] = KEY_A,
0207 [0xc3] = KEY_Z,
0208 [0xc5] = KEY_2,
0209 [0xc6] = KEY_W,
0210 [0xc7] = KEY_S,
0211 [0xc8] = KEY_X,
0212 [0xc9] = KEY_102ND,
0213 [0xcb] = KEY_3,
0214 [0xcc] = KEY_E,
0215 [0xcd] = KEY_D,
0216 [0xce] = KEY_C,
0217 [0xd0] = KEY_4,
0218 [0xd1] = KEY_R,
0219 [0xd2] = KEY_F,
0220 [0xd3] = KEY_V,
0221 [0xd4] = KEY_SPACE,
0222 [0xd6] = KEY_5,
0223 [0xd7] = KEY_T,
0224 [0xd8] = KEY_G,
0225 [0xd9] = KEY_B,
0226 [0xdb] = KEY_6,
0227 [0xdc] = KEY_Y,
0228 [0xdd] = KEY_H,
0229 [0xde] = KEY_N,
0230 [0xe0] = KEY_7,
0231 [0xe1] = KEY_U,
0232 [0xe2] = KEY_J,
0233 [0xe3] = KEY_M,
0234 [0xe5] = KEY_8,
0235 [0xe6] = KEY_I,
0236 [0xe7] = KEY_K,
0237 [0xe8] = KEY_COMMA,
0238 [0xea] = KEY_9,
0239 [0xeb] = KEY_O,
0240 [0xec] = KEY_L,
0241 [0xed] = KEY_DOT,
0242 [0xef] = KEY_0,
0243 [0xf0] = KEY_P,
0244 [0xf2] = KEY_SEMICOLON,
0245 [0xf3] = KEY_SLASH,
0246 [0xf5] = KEY_EQUAL,
0247 [0xf6] = KEY_RIGHTBRACE,
0248 [0xf7] = KEY_BACKSLASH,
0249 [0xf9] = KEY_MINUS,
0250 [0xfa] = KEY_LEFTBRACE,
0251 [0xfb] = KEY_APOSTROPHE,
0252 };
0253
0254 #define CHECK_LED(LK, VAR_ON, VAR_OFF, LED, BITS) do { \
0255 if (test_bit(LED, (LK)->dev->led)) \
0256 VAR_ON |= BITS; \
0257 else \
0258 VAR_OFF |= BITS; \
0259 } while (0)
0260
0261
0262
0263
0264 struct lkkbd {
0265 unsigned short keycode[LK_NUM_KEYCODES];
0266 int ignore_bytes;
0267 unsigned char id[LK_NUM_IGNORE_BYTES];
0268 struct input_dev *dev;
0269 struct serio *serio;
0270 struct work_struct tq;
0271 char name[64];
0272 char phys[32];
0273 char type;
0274 int bell_volume;
0275 int keyclick_volume;
0276 int ctrlclick_volume;
0277 };
0278
0279 #ifdef LKKBD_DEBUG
0280
0281
0282
0283 static struct {
0284 unsigned char value;
0285 unsigned char *name;
0286 } lk_response[] = {
0287 #define RESPONSE(x) { .value = (x), .name = #x, }
0288 RESPONSE(LK_STUCK_KEY),
0289 RESPONSE(LK_SELFTEST_FAILED),
0290 RESPONSE(LK_ALL_KEYS_UP),
0291 RESPONSE(LK_METRONOME),
0292 RESPONSE(LK_OUTPUT_ERROR),
0293 RESPONSE(LK_INPUT_ERROR),
0294 RESPONSE(LK_KBD_LOCKED),
0295 RESPONSE(LK_KBD_TEST_MODE_ACK),
0296 RESPONSE(LK_PREFIX_KEY_DOWN),
0297 RESPONSE(LK_MODE_CHANGE_ACK),
0298 RESPONSE(LK_RESPONSE_RESERVED),
0299 #undef RESPONSE
0300 };
0301
0302 static unsigned char *response_name(unsigned char value)
0303 {
0304 int i;
0305
0306 for (i = 0; i < ARRAY_SIZE(lk_response); i++)
0307 if (lk_response[i].value == value)
0308 return lk_response[i].name;
0309
0310 return "<unknown>";
0311 }
0312 #endif
0313
0314
0315
0316
0317 static unsigned char volume_to_hw(int volume_percent)
0318 {
0319 unsigned char ret = 0;
0320
0321 if (volume_percent < 0)
0322 volume_percent = 0;
0323 if (volume_percent > 100)
0324 volume_percent = 100;
0325
0326 if (volume_percent >= 0)
0327 ret = 7;
0328 if (volume_percent >= 13)
0329 ret = 6;
0330 if (volume_percent >= 25)
0331 ret = 5;
0332 if (volume_percent >= 38)
0333 ret = 4;
0334 if (volume_percent >= 50)
0335 ret = 3;
0336 if (volume_percent >= 63)
0337 ret = 2;
0338 if (volume_percent >= 75)
0339 ret = 1;
0340 if (volume_percent >= 88)
0341 ret = 0;
0342
0343 ret |= 0x80;
0344
0345 return ret;
0346 }
0347
0348 static void lkkbd_detection_done(struct lkkbd *lk)
0349 {
0350 int i;
0351
0352
0353
0354
0355 lk->keycode[0xb1] = KEY_COMPOSE;
0356
0357
0358
0359
0360 switch (lk->id[4]) {
0361 case 1:
0362 strlcpy(lk->name, "DEC LK201 keyboard", sizeof(lk->name));
0363
0364 if (lk201_compose_is_alt)
0365 lk->keycode[0xb1] = KEY_LEFTALT;
0366 break;
0367
0368 case 2:
0369 strlcpy(lk->name, "DEC LK401 keyboard", sizeof(lk->name));
0370 break;
0371
0372 default:
0373 strlcpy(lk->name, "Unknown DEC keyboard", sizeof(lk->name));
0374 printk(KERN_ERR
0375 "lkkbd: keyboard on %s is unknown, please report to "
0376 "Jan-Benedict Glaw <jbglaw@lug-owl.de>\n", lk->phys);
0377 printk(KERN_ERR "lkkbd: keyboard ID'ed as:");
0378 for (i = 0; i < LK_NUM_IGNORE_BYTES; i++)
0379 printk(" 0x%02x", lk->id[i]);
0380 printk("\n");
0381 break;
0382 }
0383
0384 printk(KERN_INFO "lkkbd: keyboard on %s identified as: %s\n",
0385 lk->phys, lk->name);
0386
0387
0388
0389
0390 switch (lk->id[2]) {
0391 case 0x00:
0392
0393 break;
0394
0395 case LK_STUCK_KEY:
0396 printk(KERN_ERR "lkkbd: Stuck key on keyboard at %s\n",
0397 lk->phys);
0398 break;
0399
0400 case LK_SELFTEST_FAILED:
0401 printk(KERN_ERR
0402 "lkkbd: Selftest failed on keyboard at %s, "
0403 "keyboard may not work properly\n", lk->phys);
0404 break;
0405
0406 default:
0407 printk(KERN_ERR
0408 "lkkbd: Unknown error %02x on keyboard at %s\n",
0409 lk->id[2], lk->phys);
0410 break;
0411 }
0412
0413
0414
0415
0416 if (lk->id[2] == LK_STUCK_KEY && lk->id[3] != 0)
0417 printk(KERN_ERR
0418 "Scancode of stuck key is 0x%02x, keycode is 0x%04x\n",
0419 lk->id[3], lk->keycode[lk->id[3]]);
0420 }
0421
0422
0423
0424
0425
0426 static irqreturn_t lkkbd_interrupt(struct serio *serio,
0427 unsigned char data, unsigned int flags)
0428 {
0429 struct lkkbd *lk = serio_get_drvdata(serio);
0430 struct input_dev *input_dev = lk->dev;
0431 unsigned int keycode;
0432 int i;
0433
0434 DBG(KERN_INFO "Got byte 0x%02x\n", data);
0435
0436 if (lk->ignore_bytes > 0) {
0437 DBG(KERN_INFO "Ignoring a byte on %s\n", lk->name);
0438 lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data;
0439
0440 if (lk->ignore_bytes == 0)
0441 lkkbd_detection_done(lk);
0442
0443 return IRQ_HANDLED;
0444 }
0445
0446 switch (data) {
0447 case LK_ALL_KEYS_UP:
0448 for (i = 0; i < ARRAY_SIZE(lkkbd_keycode); i++)
0449 input_report_key(input_dev, lk->keycode[i], 0);
0450 input_sync(input_dev);
0451 break;
0452
0453 case 0x01:
0454 DBG(KERN_INFO "Got 0x01, scheduling re-initialization\n");
0455 lk->ignore_bytes = LK_NUM_IGNORE_BYTES;
0456 lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data;
0457 schedule_work(&lk->tq);
0458 break;
0459
0460 case LK_METRONOME:
0461 case LK_OUTPUT_ERROR:
0462 case LK_INPUT_ERROR:
0463 case LK_KBD_LOCKED:
0464 case LK_KBD_TEST_MODE_ACK:
0465 case LK_PREFIX_KEY_DOWN:
0466 case LK_MODE_CHANGE_ACK:
0467 case LK_RESPONSE_RESERVED:
0468 DBG(KERN_INFO "Got %s and don't know how to handle...\n",
0469 response_name(data));
0470 break;
0471
0472 default:
0473 keycode = lk->keycode[data];
0474 if (keycode != KEY_RESERVED) {
0475 input_report_key(input_dev, keycode,
0476 !test_bit(keycode, input_dev->key));
0477 input_sync(input_dev);
0478 } else {
0479 printk(KERN_WARNING
0480 "%s: Unknown key with scancode 0x%02x on %s.\n",
0481 __FILE__, data, lk->name);
0482 }
0483 }
0484
0485 return IRQ_HANDLED;
0486 }
0487
0488 static void lkkbd_toggle_leds(struct lkkbd *lk)
0489 {
0490 struct serio *serio = lk->serio;
0491 unsigned char leds_on = 0;
0492 unsigned char leds_off = 0;
0493
0494 CHECK_LED(lk, leds_on, leds_off, LED_CAPSL, LK_LED_SHIFTLOCK);
0495 CHECK_LED(lk, leds_on, leds_off, LED_COMPOSE, LK_LED_COMPOSE);
0496 CHECK_LED(lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK);
0497 CHECK_LED(lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT);
0498 if (leds_on != 0) {
0499 serio_write(serio, LK_CMD_LED_ON);
0500 serio_write(serio, leds_on);
0501 }
0502 if (leds_off != 0) {
0503 serio_write(serio, LK_CMD_LED_OFF);
0504 serio_write(serio, leds_off);
0505 }
0506 }
0507
0508 static void lkkbd_toggle_keyclick(struct lkkbd *lk, bool on)
0509 {
0510 struct serio *serio = lk->serio;
0511
0512 if (on) {
0513 DBG("%s: Activating key clicks\n", __func__);
0514 serio_write(serio, LK_CMD_ENABLE_KEYCLICK);
0515 serio_write(serio, volume_to_hw(lk->keyclick_volume));
0516 serio_write(serio, LK_CMD_ENABLE_CTRCLICK);
0517 serio_write(serio, volume_to_hw(lk->ctrlclick_volume));
0518 } else {
0519 DBG("%s: Deactivating key clicks\n", __func__);
0520 serio_write(serio, LK_CMD_DISABLE_KEYCLICK);
0521 serio_write(serio, LK_CMD_DISABLE_CTRCLICK);
0522 }
0523
0524 }
0525
0526
0527
0528
0529 static int lkkbd_event(struct input_dev *dev,
0530 unsigned int type, unsigned int code, int value)
0531 {
0532 struct lkkbd *lk = input_get_drvdata(dev);
0533
0534 switch (type) {
0535 case EV_LED:
0536 lkkbd_toggle_leds(lk);
0537 return 0;
0538
0539 case EV_SND:
0540 switch (code) {
0541 case SND_CLICK:
0542 lkkbd_toggle_keyclick(lk, value);
0543 return 0;
0544
0545 case SND_BELL:
0546 if (value != 0)
0547 serio_write(lk->serio, LK_CMD_SOUND_BELL);
0548
0549 return 0;
0550 }
0551
0552 break;
0553
0554 default:
0555 printk(KERN_ERR "%s(): Got unknown type %d, code %d, value %d\n",
0556 __func__, type, code, value);
0557 }
0558
0559 return -1;
0560 }
0561
0562
0563
0564
0565
0566 static void lkkbd_reinit(struct work_struct *work)
0567 {
0568 struct lkkbd *lk = container_of(work, struct lkkbd, tq);
0569 int division;
0570
0571
0572 serio_write(lk->serio, LK_CMD_REQUEST_ID);
0573
0574
0575 serio_write(lk->serio, LK_CMD_SET_DEFAULTS);
0576
0577
0578 lkkbd_toggle_leds(lk);
0579
0580
0581
0582
0583
0584
0585 serio_write(lk->serio, LK_CMD_ENABLE_LK401);
0586
0587
0588 for (division = 1; division <= 14; division++)
0589 serio_write(lk->serio,
0590 LK_CMD_SET_MODE(LK_MODE_UPDOWN, division));
0591
0592
0593 serio_write(lk->serio, LK_CMD_ENABLE_BELL);
0594 serio_write(lk->serio, volume_to_hw(lk->bell_volume));
0595
0596
0597 lkkbd_toggle_keyclick(lk, test_bit(SND_CLICK, lk->dev->snd));
0598
0599
0600 if (test_bit(SND_BELL, lk->dev->snd))
0601 serio_write(lk->serio, LK_CMD_SOUND_BELL);
0602 }
0603
0604
0605
0606
0607 static int lkkbd_connect(struct serio *serio, struct serio_driver *drv)
0608 {
0609 struct lkkbd *lk;
0610 struct input_dev *input_dev;
0611 int i;
0612 int err;
0613
0614 lk = kzalloc(sizeof(struct lkkbd), GFP_KERNEL);
0615 input_dev = input_allocate_device();
0616 if (!lk || !input_dev) {
0617 err = -ENOMEM;
0618 goto fail1;
0619 }
0620
0621 lk->serio = serio;
0622 lk->dev = input_dev;
0623 INIT_WORK(&lk->tq, lkkbd_reinit);
0624 lk->bell_volume = bell_volume;
0625 lk->keyclick_volume = keyclick_volume;
0626 lk->ctrlclick_volume = ctrlclick_volume;
0627 memcpy(lk->keycode, lkkbd_keycode, sizeof(lk->keycode));
0628
0629 strlcpy(lk->name, "DEC LK keyboard", sizeof(lk->name));
0630 snprintf(lk->phys, sizeof(lk->phys), "%s/input0", serio->phys);
0631
0632 input_dev->name = lk->name;
0633 input_dev->phys = lk->phys;
0634 input_dev->id.bustype = BUS_RS232;
0635 input_dev->id.vendor = SERIO_LKKBD;
0636 input_dev->id.product = 0;
0637 input_dev->id.version = 0x0100;
0638 input_dev->dev.parent = &serio->dev;
0639 input_dev->event = lkkbd_event;
0640
0641 input_set_drvdata(input_dev, lk);
0642
0643 __set_bit(EV_KEY, input_dev->evbit);
0644 __set_bit(EV_LED, input_dev->evbit);
0645 __set_bit(EV_SND, input_dev->evbit);
0646 __set_bit(EV_REP, input_dev->evbit);
0647 __set_bit(LED_CAPSL, input_dev->ledbit);
0648 __set_bit(LED_SLEEP, input_dev->ledbit);
0649 __set_bit(LED_COMPOSE, input_dev->ledbit);
0650 __set_bit(LED_SCROLLL, input_dev->ledbit);
0651 __set_bit(SND_BELL, input_dev->sndbit);
0652 __set_bit(SND_CLICK, input_dev->sndbit);
0653
0654 input_dev->keycode = lk->keycode;
0655 input_dev->keycodesize = sizeof(lk->keycode[0]);
0656 input_dev->keycodemax = ARRAY_SIZE(lk->keycode);
0657
0658 for (i = 0; i < LK_NUM_KEYCODES; i++)
0659 __set_bit(lk->keycode[i], input_dev->keybit);
0660 __clear_bit(KEY_RESERVED, input_dev->keybit);
0661
0662 serio_set_drvdata(serio, lk);
0663
0664 err = serio_open(serio, drv);
0665 if (err)
0666 goto fail2;
0667
0668 err = input_register_device(lk->dev);
0669 if (err)
0670 goto fail3;
0671
0672 serio_write(lk->serio, LK_CMD_POWERCYCLE_RESET);
0673
0674 return 0;
0675
0676 fail3: serio_close(serio);
0677 fail2: serio_set_drvdata(serio, NULL);
0678 fail1: input_free_device(input_dev);
0679 kfree(lk);
0680 return err;
0681 }
0682
0683
0684
0685
0686 static void lkkbd_disconnect(struct serio *serio)
0687 {
0688 struct lkkbd *lk = serio_get_drvdata(serio);
0689
0690 input_get_device(lk->dev);
0691 input_unregister_device(lk->dev);
0692 serio_close(serio);
0693 serio_set_drvdata(serio, NULL);
0694 input_put_device(lk->dev);
0695 kfree(lk);
0696 }
0697
0698 static const struct serio_device_id lkkbd_serio_ids[] = {
0699 {
0700 .type = SERIO_RS232,
0701 .proto = SERIO_LKKBD,
0702 .id = SERIO_ANY,
0703 .extra = SERIO_ANY,
0704 },
0705 { 0 }
0706 };
0707
0708 MODULE_DEVICE_TABLE(serio, lkkbd_serio_ids);
0709
0710 static struct serio_driver lkkbd_drv = {
0711 .driver = {
0712 .name = "lkkbd",
0713 },
0714 .description = DRIVER_DESC,
0715 .id_table = lkkbd_serio_ids,
0716 .connect = lkkbd_connect,
0717 .disconnect = lkkbd_disconnect,
0718 .interrupt = lkkbd_interrupt,
0719 };
0720
0721 module_serio_driver(lkkbd_drv);