OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [hil/] [hil_kbd.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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
 
42
#ifdef DEBUG    /* DEBUG */
43
#undef input_report_key
44
#define input_report_key(a,b,c) { printk("input_report_key(%p, %d, %d)\n", a, b, !!(c)); input_event(a, EV_KEY, b, !!(c)); }
45
#endif
46
 
47
#define PREFIX "HIL KEYB: "
48
#define HIL_GENERIC_NAME "generic HIL keyboard device"
49
 
50
MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
51
MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver");
52
MODULE_LICENSE("Dual BSD/GPL");
53
 
54
#define HIL_KBD_MAX_LENGTH 16
55
 
56
#define HIL_KBD_SET1_UPBIT 0x01
57
#define HIL_KBD_SET1_SHIFT 1
58
 
59
static uint8_t hil_kbd_set1[128] = {
60
   KEY_5,               KEY_RESERVED,   KEY_RIGHTALT,   KEY_LEFTALT,
61
   KEY_RIGHTSHIFT,      KEY_LEFTSHIFT,  KEY_LEFTCTRL,   KEY_SYSRQ,
62
   KEY_KP4,             KEY_KP8,        KEY_KP5,        KEY_KP9,
63
   KEY_KP6,             KEY_KP7,        KEY_KPCOMMA,    KEY_KPENTER,
64
   KEY_KP1,             KEY_KPSLASH,    KEY_KP2,        KEY_KPPLUS,
65
   KEY_KP3,             KEY_KPASTERISK, KEY_KP0,        KEY_KPMINUS,
66
   KEY_B,               KEY_V,          KEY_C,          KEY_X,
67
   KEY_Z,               KEY_UNKNOWN,    KEY_RESERVED,   KEY_ESC,
68
   KEY_6,               KEY_F10,        KEY_3,          KEY_F11,
69
   KEY_KPDOT,           KEY_F9,         KEY_TAB /*KP*/, KEY_F12,
70
   KEY_H,               KEY_G,          KEY_F,          KEY_D,
71
   KEY_S,               KEY_A,          KEY_RESERVED,   KEY_CAPSLOCK,
72
   KEY_U,               KEY_Y,          KEY_T,          KEY_R,
73
   KEY_E,               KEY_W,          KEY_Q,          KEY_TAB,
74
   KEY_7,               KEY_6,          KEY_5,          KEY_4,
75
   KEY_3,               KEY_2,          KEY_1,          KEY_GRAVE,
76
   KEY_INTL1,           KEY_INTL2,      KEY_INTL3,      KEY_INTL4, /*Buttons*/
77
   KEY_INTL5,           KEY_INTL6,      KEY_INTL7,      KEY_INTL8,
78
   KEY_MENU,            KEY_F4,         KEY_F3,         KEY_F2,
79
   KEY_F1,              KEY_VOLUMEUP,   KEY_STOP,       KEY_SENDFILE/*Enter/Print*/,
80
   KEY_SYSRQ,           KEY_F5,         KEY_F6,         KEY_F7,
81
   KEY_F8,              KEY_VOLUMEDOWN, KEY_CUT /*CLEAR_LINE*/, KEY_REFRESH /*CLEAR_DISPLAY*/,
82
   KEY_8,               KEY_9,          KEY_0,          KEY_MINUS,
83
   KEY_EQUAL,           KEY_BACKSPACE,  KEY_INSERT/*KPINSERT_LINE*/, KEY_DELETE /*KPDELETE_LINE*/,
84
   KEY_I,               KEY_O,          KEY_P,          KEY_LEFTBRACE,
85
   KEY_RIGHTBRACE,      KEY_BACKSLASH,  KEY_INSERT,     KEY_DELETE,
86
   KEY_J,               KEY_K,          KEY_L,          KEY_SEMICOLON,
87
   KEY_APOSTROPHE,      KEY_ENTER,      KEY_HOME,       KEY_SCROLLUP,
88
   KEY_M,               KEY_COMMA,      KEY_DOT,        KEY_SLASH,
89
   KEY_RESERVED,        KEY_OPEN/*Select*/,KEY_RESERVED,KEY_SCROLLDOWN/*KPNEXT*/,
90
   KEY_N,               KEY_SPACE,      KEY_SCROLLDOWN/*Next*/, KEY_UNKNOWN,
91
   KEY_LEFT,            KEY_DOWN,       KEY_UP,         KEY_RIGHT
92
};
93
 
94
#define HIL_KBD_SET2_UPBIT 0x01
95
#define HIL_KBD_SET2_SHIFT 1
96
 
97
/* Set2 is user defined */
98
 
99
#define HIL_KBD_SET3_UPBIT 0x80
100
#define HIL_KBD_SET3_SHIFT 0
101
 
102
static uint8_t hil_kbd_set3[128] = {
103
  KEY_RESERVED, KEY_ESC,        KEY_1,          KEY_2,
104
  KEY_3,        KEY_4,          KEY_5,          KEY_6,
105
  KEY_7,        KEY_8,          KEY_9,          KEY_0,
106
  KEY_MINUS,    KEY_EQUAL,      KEY_BACKSPACE,  KEY_TAB,
107
  KEY_Q,        KEY_W,          KEY_E,          KEY_R,
108
  KEY_T,        KEY_Y,          KEY_U,          KEY_I,
109
  KEY_O,        KEY_P,          KEY_LEFTBRACE,  KEY_RIGHTBRACE,
110
  KEY_ENTER,    KEY_LEFTCTRL,   KEY_A,          KEY_S,
111
  KEY_D,        KEY_F,          KEY_G,          KEY_H,
112
  KEY_J,        KEY_K,          KEY_L,          KEY_SEMICOLON,
113
  KEY_APOSTROPHE,KEY_GRAVE,     KEY_LEFTSHIFT,  KEY_BACKSLASH,
114
  KEY_Z,        KEY_X,          KEY_C,          KEY_V,
115
  KEY_B,        KEY_N,          KEY_M,          KEY_COMMA,
116
  KEY_DOT,      KEY_SLASH,      KEY_RIGHTSHIFT, KEY_KPASTERISK,
117
  KEY_LEFTALT,  KEY_SPACE,      KEY_CAPSLOCK,   KEY_F1,
118
  KEY_F2,       KEY_F3,         KEY_F4,         KEY_F5,
119
  KEY_F6,       KEY_F7,         KEY_F8,         KEY_F9,
120
  KEY_F10,      KEY_NUMLOCK,    KEY_SCROLLLOCK, KEY_KP7,
121
  KEY_KP8,      KEY_KP9,        KEY_KPMINUS,    KEY_KP4,
122
  KEY_KP5,      KEY_KP6,        KEY_KPPLUS,     KEY_KP1,
123
  KEY_KP2,      KEY_KP3,        KEY_KP0,        KEY_KPDOT,
124
  KEY_SYSRQ,    KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,
125
  KEY_RESERVED, KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,
126
  KEY_RESERVED, KEY_RESERVED,   KEY_UNKNOWN,    KEY_UNKNOWN,
127
  KEY_UP,       KEY_LEFT,       KEY_DOWN,       KEY_RIGHT,
128
  KEY_HOME,     KEY_PAGEUP,     KEY_END,        KEY_PAGEDOWN,
129
  KEY_INSERT,   KEY_DELETE,     KEY_102ND,      KEY_RESERVED,
130
  KEY_RESERVED, KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,
131
  KEY_F1,       KEY_F2,         KEY_F3,         KEY_F4,
132
  KEY_F5,       KEY_F6,         KEY_F7,         KEY_F8,
133
  KEY_RESERVED, KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED,
134
  KEY_RESERVED, KEY_RESERVED,   KEY_RESERVED,   KEY_RESERVED
135
};
136
 
137
static char *hil_language[] = { HIL_LOCALE_MAP };
138
 
139
struct hil_kbd {
140
        struct input_dev dev;
141
        struct serio *serio;
142
 
143
        /* Input buffer and index for packets from HIL bus. */
144
        hil_packet data[HIL_KBD_MAX_LENGTH];
145
        int idx4; /* four counts per packet */
146
 
147
        /* Raw device info records from HIL bus, see hil.h for fields. */
148
        char    idd[HIL_KBD_MAX_LENGTH];        /* DID byte and IDD record */
149
        char    rsc[HIL_KBD_MAX_LENGTH];        /* RSC record */
150
        char    exd[HIL_KBD_MAX_LENGTH];        /* EXD record */
151
        char    rnm[HIL_KBD_MAX_LENGTH + 1];    /* RNM record + NULL term. */
152
 
153
        /* Something to sleep around with. */
154
        struct semaphore sem;
155
};
156
 
157
/* Process a complete packet after transfer from the HIL */
158
static void hil_kbd_process_record(struct hil_kbd *kbd)
159
{
160
        struct input_dev *dev = &kbd->dev;
161
        hil_packet *data = kbd->data;
162
        hil_packet p;
163
        int idx, i, cnt;
164
 
165
        idx = kbd->idx4/4;
166
        p = data[idx - 1];
167
 
168
        if ((p & ~HIL_CMDCT_POL) ==
169
            (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report;
170
        if ((p & ~HIL_CMDCT_RPL) ==
171
            (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report;
172
 
173
        /* Not a poll response.  See if we are loading config records. */
174
        switch (p & HIL_PKT_DATA_MASK) {
175
        case HIL_CMD_IDD:
176
                for (i = 0; i < idx; i++)
177
                        kbd->idd[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
178
                for (; i < HIL_KBD_MAX_LENGTH; i++)
179
                        kbd->idd[i] = 0;
180
                break;
181
        case HIL_CMD_RSC:
182
                for (i = 0; i < idx; i++)
183
                        kbd->rsc[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
184
                for (; i < HIL_KBD_MAX_LENGTH; i++)
185
                        kbd->rsc[i] = 0;
186
                break;
187
        case HIL_CMD_EXD:
188
                for (i = 0; i < idx; i++)
189
                        kbd->exd[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
190
                for (; i < HIL_KBD_MAX_LENGTH; i++)
191
                        kbd->exd[i] = 0;
192
                break;
193
        case HIL_CMD_RNM:
194
                for (i = 0; i < idx; i++)
195
                        kbd->rnm[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
196
                for (; i < HIL_KBD_MAX_LENGTH + 1; i++)
197
                        kbd->rnm[i] = '\0';
198
                break;
199
        default:
200
                /* These occur when device isn't present */
201
                if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break;
202
                /* Anything else we'd like to know about. */
203
                printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
204
                break;
205
        }
206
        goto out;
207
 
208
 report:
209
        cnt = 1;
210
        switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) {
211
        case HIL_POL_CHARTYPE_NONE:
212
                break;
213
        case HIL_POL_CHARTYPE_ASCII:
214
                while (cnt < idx - 1)
215
                        input_report_key(dev, kbd->data[cnt++] & 0x7f, 1);
216
                break;
217
        case HIL_POL_CHARTYPE_RSVD1:
218
        case HIL_POL_CHARTYPE_RSVD2:
219
        case HIL_POL_CHARTYPE_BINARY:
220
                while (cnt < idx - 1)
221
                        input_report_key(dev, kbd->data[cnt++], 1);
222
                break;
223
        case HIL_POL_CHARTYPE_SET1:
224
                while (cnt < idx - 1) {
225
                        unsigned int key;
226
                        int up;
227
                        key = kbd->data[cnt++];
228
                        up = key & HIL_KBD_SET1_UPBIT;
229
                        key &= (~HIL_KBD_SET1_UPBIT & 0xff);
230
                        key = key >> HIL_KBD_SET1_SHIFT;
231
                        if (key != KEY_RESERVED && key != KEY_UNKNOWN)
232
                                input_report_key(dev, hil_kbd_set1[key], !up);
233
                }
234
                break;
235
        case HIL_POL_CHARTYPE_SET2:
236
                while (cnt < idx - 1) {
237
                        unsigned int key;
238
                        int up;
239
                        key = kbd->data[cnt++];
240
                        up = key & HIL_KBD_SET2_UPBIT;
241
                        key &= (~HIL_KBD_SET1_UPBIT & 0xff);
242
                        key = key >> HIL_KBD_SET2_SHIFT;
243
                        if (key != KEY_RESERVED && key != KEY_UNKNOWN)
244
                                input_report_key(dev, key, !up);
245
                }
246
                break;
247
        case HIL_POL_CHARTYPE_SET3:
248
                while (cnt < idx - 1) {
249
                        unsigned int key;
250
                        int up;
251
                        key = kbd->data[cnt++];
252
                        up = key & HIL_KBD_SET3_UPBIT;
253
                        key &= (~HIL_KBD_SET1_UPBIT & 0xff);
254
                        key = key >> HIL_KBD_SET3_SHIFT;
255
                        if (key != KEY_RESERVED && key != KEY_UNKNOWN)
256
                                input_report_key(dev, hil_kbd_set3[key], !up);
257
                }
258
                break;
259
        }
260
 out:
261
        kbd->idx4 = 0;
262
        up(&kbd->sem);
263
}
264
 
265
static void hil_kbd_process_err(struct hil_kbd *kbd) {
266
        printk(KERN_WARNING PREFIX "errored HIL packet\n");
267
        kbd->idx4 = 0;
268
        up(&kbd->sem);
269
        return;
270
}
271
 
272
static void hil_kbd_interrupt(struct serio *serio,
273
                              unsigned char data,
274
                              unsigned int flags)
275
{
276
        struct hil_kbd *kbd;
277
        hil_packet packet;
278
        int idx;
279
 
280
        kbd = (struct hil_kbd *)serio->private;
281
        if (kbd == NULL) {
282
                BUG();
283
                return;
284
        }
285
 
286
        if (kbd->idx4 >= (HIL_KBD_MAX_LENGTH * sizeof(hil_packet))) {
287
                hil_kbd_process_err(kbd);
288
                return;
289
        }
290
        idx = kbd->idx4/4;
291
        if (!(kbd->idx4 % 4)) kbd->data[idx] = 0;
292
        packet = kbd->data[idx];
293
        packet |= ((hil_packet)data) << ((3 - (kbd->idx4 % 4)) * 8);
294
        kbd->data[idx] = packet;
295
 
296
        /* Records of N 4-byte hil_packets must terminate with a command. */
297
        if ((++(kbd->idx4)) % 4) return;
298
        if ((packet & 0xffff0000) != HIL_ERR_INT) {
299
                hil_kbd_process_err(kbd);
300
                return;
301
        }
302
        if (packet & HIL_PKT_CMD) hil_kbd_process_record(kbd);
303
}
304
 
305
static void hil_kbd_disconnect(struct serio *serio)
306
{
307
        struct hil_kbd *kbd;
308
 
309
        kbd = (struct hil_kbd *)serio->private;
310
        if (kbd == NULL) {
311
                BUG();
312
                return;
313
        }
314
 
315
        input_unregister_device(&kbd->dev);
316
        serio_close(serio);
317
        kfree(kbd);
318
}
319
 
320
static void hil_kbd_connect(struct serio *serio, struct serio_dev *dev)
321
{
322
        struct hil_kbd  *kbd;
323
        uint8_t         did, *idd;
324
        int             i;
325
 
326
        if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return;
327
 
328
        if (!(kbd = kmalloc(sizeof(struct hil_kbd), GFP_KERNEL))) return;
329
        memset(kbd, 0, sizeof(struct hil_kbd));
330
 
331
        if (serio_open(serio, dev)) goto bail0;
332
 
333
        serio->private = kbd;
334
        kbd->serio = serio;
335
        kbd->dev.private = kbd;
336
 
337
        init_MUTEX_LOCKED(&(kbd->sem));
338
 
339
        /* Get device info.  MLC driver supplies devid/status/etc. */
340
        serio->write(serio, 0);
341
        serio->write(serio, 0);
342
        serio->write(serio, HIL_PKT_CMD >> 8);
343
        serio->write(serio, HIL_CMD_IDD);
344
        down(&(kbd->sem));
345
 
346
        serio->write(serio, 0);
347
        serio->write(serio, 0);
348
        serio->write(serio, HIL_PKT_CMD >> 8);
349
        serio->write(serio, HIL_CMD_RSC);
350
        down(&(kbd->sem));
351
 
352
        serio->write(serio, 0);
353
        serio->write(serio, 0);
354
        serio->write(serio, HIL_PKT_CMD >> 8);
355
        serio->write(serio, HIL_CMD_RNM);
356
        down(&(kbd->sem));
357
 
358
        serio->write(serio, 0);
359
        serio->write(serio, 0);
360
        serio->write(serio, HIL_PKT_CMD >> 8);
361
        serio->write(serio, HIL_CMD_EXD);
362
        down(&(kbd->sem));
363
 
364
        up(&(kbd->sem));
365
 
366
        did = kbd->idd[0];
367
        idd = kbd->idd + 1;
368
        switch (did & HIL_IDD_DID_TYPE_MASK) {
369
        case HIL_IDD_DID_TYPE_KB_INTEGRAL:
370
        case HIL_IDD_DID_TYPE_KB_ITF:
371
        case HIL_IDD_DID_TYPE_KB_RSVD:
372
        case HIL_IDD_DID_TYPE_CHAR:
373
                printk(KERN_INFO PREFIX "HIL keyboard found (did = 0x%02x, lang = %s)\n",
374
                        did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]);
375
                break;
376
        default:
377
                goto bail1;
378
        }
379
 
380
        if(HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) {
381
                printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n");
382
                goto bail1;
383
        }
384
 
385
        kbd->dev.name = strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME;
386
 
387
        kbd->dev.idbus          = BUS_HIL;
388
        kbd->dev.idvendor       = SERIO_HIL;
389
        kbd->dev.idproduct      = 0x0001; /* TODO: get from kbd->rsc */
390
        kbd->dev.idversion      = 0x0100; /* TODO: get from kbd->rsc */
391
 
392
        kbd->dev.evbit[0] |= BIT(EV_KEY);
393
 
394
        for (i = 0; i < 128; i++) {
395
                set_bit(hil_kbd_set1[i], kbd->dev.keybit);
396
                set_bit(hil_kbd_set3[i], kbd->dev.keybit);
397
        }
398
        clear_bit(0, kbd->dev.keybit);
399
 
400
#if 1
401
        /* XXX: HACK !!!
402
         * remove this call if hp_psaux.c/hp_keyb.c is converted
403
         * to the input layer... */
404
        register_ps2_keybfuncs();
405
#endif
406
 
407
        input_register_device(&kbd->dev);
408
        printk(KERN_INFO "input%d: %s on hil%d\n",
409
                kbd->dev.number, "HIL keyboard", 0);
410
 
411
        /* HIL keyboards don't have a numlock key,
412
         * simulate a up-down sequence of numlock to
413
         * make the keypad work at expected. */
414
        input_report_key(&kbd->dev, KEY_NUMLOCK, 1);
415
/*      input_report_key(&kbd->dev, KEY_NUMLOCK, 0); */
416
 
417
        serio->write(serio, 0);
418
        serio->write(serio, 0);
419
        serio->write(serio, HIL_PKT_CMD >> 8);
420
        serio->write(serio, HIL_CMD_EK1); /* Enable Keyswitch Autorepeat 1 */
421
        down(&(kbd->sem));
422
        up(&(kbd->sem));
423
 
424
        return;
425
 bail1:
426
        serio_close(serio);
427
 bail0:
428
        kfree(kbd);
429
        return;
430
}
431
 
432
 
433
struct serio_dev hil_kbd_serio_dev = {
434
        .connect =      hil_kbd_connect,
435
        .disconnect =   hil_kbd_disconnect,
436
        .interrupt =    hil_kbd_interrupt
437
};
438
 
439
static int __init hil_kbd_init(void)
440
{
441
        serio_register_device(&hil_kbd_serio_dev);
442
        return 0;
443
}
444
 
445
static void __exit hil_kbd_exit(void)
446
{
447
        serio_unregister_device(&hil_kbd_serio_dev);
448
 
449
#if 1
450
        /* XXX: HACK !!!
451
         * remove this call if hp_psaux.c/hp_keyb.c is converted
452
         * to the input layer... */
453
        unregister_kbd_ops();
454
#endif
455
}
456
 
457
module_init(hil_kbd_init);
458
module_exit(hil_kbd_exit);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.