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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [input/] [keyboard/] [hil_kbd.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
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
 
46
MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
47
MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver");
48
MODULE_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
54
static 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
63
static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] __read_mostly =
64
        { HIL_KEYCODES_SET3 };
65
 
66
static const char hil_language[][16] = { HIL_LOCALE_MAP };
67
 
68
struct 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 */
87
static 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
 
206
static 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
 
213
static 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
 
246
static 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
 
258
static 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
 
369
static 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
 
379
static 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
 
390
static int __init hil_kbd_init(void)
391
{
392
        return serio_register_driver(&hil_kbd_serio_drv);
393
}
394
 
395
static void __exit hil_kbd_exit(void)
396
{
397
        serio_unregister_driver(&hil_kbd_serio_drv);
398
}
399
 
400
module_init(hil_kbd_init);
401
module_exit(hil_kbd_exit);

powered by: WebSVN 2.1.0

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