blob: 235a669a0ac3230c8132c870668891a908b617ed [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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>
Dmitry Torokhov6777f012009-08-07 23:17:46 -070040#include <linux/completion.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/slab.h>
42#include <linux/pci_ids.h>
43
44#define PREFIX "HIL KEYB: "
45#define HIL_GENERIC_NAME "HIL keyboard"
46
47MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
48MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver");
49MODULE_LICENSE("Dual BSD/GPL");
Helge Dellerc10a93a2008-12-29 04:44:44 -080050MODULE_ALIAS("serio:ty03pr25id00ex*");
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
Dmitry Torokhov1437dc32009-08-07 23:17:47 -070052#define HIL_PACKET_MAX_LENGTH 16
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
54#define HIL_KBD_SET1_UPBIT 0x01
55#define HIL_KBD_SET1_SHIFT 1
Helge Deller3acaf542007-02-28 23:51:19 -050056static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] __read_mostly =
Linus Torvalds1da177e2005-04-16 15:20:36 -070057 { HIL_KEYCODES_SET1 };
58
59#define HIL_KBD_SET2_UPBIT 0x01
60#define HIL_KBD_SET2_SHIFT 1
61/* Set2 is user defined */
62
63#define HIL_KBD_SET3_UPBIT 0x80
64#define HIL_KBD_SET3_SHIFT 0
Helge Deller3acaf542007-02-28 23:51:19 -050065static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] __read_mostly =
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 { HIL_KEYCODES_SET3 };
67
Helge Deller3acaf542007-02-28 23:51:19 -050068static const char hil_language[][16] = { HIL_LOCALE_MAP };
Linus Torvalds1da177e2005-04-16 15:20:36 -070069
Dmitry Torokhov1437dc32009-08-07 23:17:47 -070070struct hil_dev {
Helge Deller102c8c72006-03-26 07:41:55 -070071 struct input_dev *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 struct serio *serio;
73
74 /* Input buffer and index for packets from HIL bus. */
Dmitry Torokhov1437dc32009-08-07 23:17:47 -070075 hil_packet data[HIL_PACKET_MAX_LENGTH];
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 int idx4; /* four counts per packet */
77
78 /* Raw device info records from HIL bus, see hil.h for fields. */
Dmitry Torokhov1437dc32009-08-07 23:17:47 -070079 char idd[HIL_PACKET_MAX_LENGTH]; /* DID byte and IDD record */
80 char rsc[HIL_PACKET_MAX_LENGTH]; /* RSC record */
81 char exd[HIL_PACKET_MAX_LENGTH]; /* EXD record */
82 char rnm[HIL_PACKET_MAX_LENGTH + 1]; /* RNM record + NULL term. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
Dmitry Torokhov6777f012009-08-07 23:17:46 -070084 struct completion cmd_done;
Linus Torvalds1da177e2005-04-16 15:20:36 -070085};
86
Dmitry Torokhov1437dc32009-08-07 23:17:47 -070087static bool hil_dev_is_command_response(hil_packet p)
Linus Torvalds1da177e2005-04-16 15:20:36 -070088{
Dmitry Torokhov6777f012009-08-07 23:17:46 -070089 if ((p & ~HIL_CMDCT_POL) == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL))
90 return false;
91
92 if ((p & ~HIL_CMDCT_RPL) == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL))
93 return false;
94
95 return true;
96}
97
Dmitry Torokhov1437dc32009-08-07 23:17:47 -070098static void hil_dev_handle_command_response(struct hil_dev *dev)
Dmitry Torokhov6777f012009-08-07 23:17:46 -070099{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100 hil_packet p;
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700101 char *buf;
102 int i, idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700104 idx = dev->idx4 / 4;
105 p = dev->data[idx - 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 switch (p & HIL_PKT_DATA_MASK) {
108 case HIL_CMD_IDD:
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700109 buf = dev->idd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 break;
Helge Dellerffd51f42007-02-28 23:51:29 -0500111
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 case HIL_CMD_RSC:
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700113 buf = dev->rsc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 break;
Helge Dellerffd51f42007-02-28 23:51:29 -0500115
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 case HIL_CMD_EXD:
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700117 buf = dev->exd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 break;
Helge Dellerffd51f42007-02-28 23:51:29 -0500119
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 case HIL_CMD_RNM:
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700121 dev->rnm[HIL_PACKET_MAX_LENGTH] = 0;
122 buf = dev->rnm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 break;
Helge Dellerffd51f42007-02-28 23:51:29 -0500124
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 default:
126 /* These occur when device isn't present */
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700127 if (p != (HIL_ERR_INT | HIL_PKT_CMD)) {
128 /* Anything else we'd like to know about. */
129 printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
130 }
131 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700134 for (i = 0; i < idx; i++)
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700135 buf[i] = dev->data[i] & HIL_PKT_DATA_MASK;
136 for (; i < HIL_PACKET_MAX_LENGTH; i++)
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700137 buf[i] = 0;
138 out:
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700139 complete(&dev->cmd_done);
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700140}
141
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700142static void hil_dev_handle_key_events(struct hil_dev *kbd)
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700143{
144 struct input_dev *dev = kbd->dev;
145 int idx = kbd->idx4 / 4;
146 int i;
147
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148 switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) {
149 case HIL_POL_CHARTYPE_NONE:
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700150 return;
Helge Dellerffd51f42007-02-28 23:51:29 -0500151
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 case HIL_POL_CHARTYPE_ASCII:
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700153 for (i = 1; i < idx - 1; i++)
154 input_report_key(dev, kbd->data[i] & 0x7f, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 break;
Helge Dellerffd51f42007-02-28 23:51:29 -0500156
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 case HIL_POL_CHARTYPE_RSVD1:
158 case HIL_POL_CHARTYPE_RSVD2:
159 case HIL_POL_CHARTYPE_BINARY:
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700160 for (i = 1; i < idx - 1; i++)
161 input_report_key(dev, kbd->data[i], 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 break;
Helge Dellerffd51f42007-02-28 23:51:29 -0500163
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 case HIL_POL_CHARTYPE_SET1:
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700165 for (i = 1; i < idx - 1; i++) {
166 unsigned int key = kbd->data[i];
167 int up = key & HIL_KBD_SET1_UPBIT;
168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 key &= (~HIL_KBD_SET1_UPBIT & 0xff);
170 key = hil_kbd_set1[key >> HIL_KBD_SET1_SHIFT];
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700171 input_report_key(dev, key, !up);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 }
173 break;
Helge Dellerffd51f42007-02-28 23:51:29 -0500174
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 case HIL_POL_CHARTYPE_SET2:
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700176 for (i = 1; i < idx - 1; i++) {
177 unsigned int key = kbd->data[i];
178 int up = key & HIL_KBD_SET2_UPBIT;
179
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 key &= (~HIL_KBD_SET1_UPBIT & 0xff);
181 key = key >> HIL_KBD_SET2_SHIFT;
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700182 input_report_key(dev, key, !up);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 }
184 break;
Helge Dellerffd51f42007-02-28 23:51:29 -0500185
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 case HIL_POL_CHARTYPE_SET3:
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700187 for (i = 1; i < idx - 1; i++) {
188 unsigned int key = kbd->data[i];
189 int up = key & HIL_KBD_SET3_UPBIT;
190
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 key &= (~HIL_KBD_SET1_UPBIT & 0xff);
192 key = hil_kbd_set3[key >> HIL_KBD_SET3_SHIFT];
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700193 input_report_key(dev, key, !up);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 }
195 break;
196 }
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700197
198 input_sync(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199}
200
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700201static void hil_dev_process_err(struct hil_dev *dev)
Helge Dellerffd51f42007-02-28 23:51:29 -0500202{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 printk(KERN_WARNING PREFIX "errored HIL packet\n");
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700204 dev->idx4 = 0;
205 complete(&dev->cmd_done); /* just in case somebody is waiting */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206}
207
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700208static irqreturn_t hil_dev_interrupt(struct serio *serio,
Helge Dellerffd51f42007-02-28 23:51:29 -0500209 unsigned char data, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210{
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700211 struct hil_dev *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 hil_packet packet;
213 int idx;
214
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700215 dev = serio_get_drvdata(serio);
216 BUG_ON(dev == NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700218 if (dev->idx4 >= HIL_PACKET_MAX_LENGTH * sizeof(hil_packet)) {
219 hil_dev_process_err(dev);
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700220 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 }
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700222
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700223 idx = dev->idx4 / 4;
224 if (!(dev->idx4 % 4))
225 dev->data[idx] = 0;
226 packet = dev->data[idx];
227 packet |= ((hil_packet)data) << ((3 - (dev->idx4 % 4)) * 8);
228 dev->data[idx] = packet;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229
230 /* Records of N 4-byte hil_packets must terminate with a command. */
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700231 if ((++dev->idx4 % 4) == 0) {
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700232 if ((packet & 0xffff0000) != HIL_ERR_INT) {
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700233 hil_dev_process_err(dev);
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700234 } else if (packet & HIL_PKT_CMD) {
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700235 if (hil_dev_is_command_response(packet))
236 hil_dev_handle_command_response(dev);
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700237 else
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700238 hil_dev_handle_key_events(dev);
239 dev->idx4 = 0;
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700240 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 }
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700242 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 return IRQ_HANDLED;
244}
245
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700246static void hil_dev_disconnect(struct serio *serio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247{
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700248 struct hil_dev *dev = serio_get_drvdata(serio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700250 BUG_ON(dev == NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 serio_close(serio);
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700253 input_unregister_device(dev->dev);
254 kfree(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255}
256
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700257static int hil_dev_connect(struct serio *serio, struct serio_driver *drv)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258{
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700259 struct hil_dev *dev;
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700260 struct input_dev *input_dev;
261 uint8_t did, *idd;
262 int i;
263 int error;
Dmitry Torokhov95d465f2006-04-02 00:08:05 -0500264
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700265 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700266 input_dev = input_allocate_device();
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700267 if (!dev || !input_dev) {
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700268 error = -ENOMEM;
269 goto bail0;
270 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700272 dev->serio = serio;
273 dev->dev = input_dev;
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700274
275 error = serio_open(serio, drv);
276 if (error)
Dmitry Torokhov95d465f2006-04-02 00:08:05 -0500277 goto bail0;
278
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700279 serio_set_drvdata(serio, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280
281 /* Get device info. MLC driver supplies devid/status/etc. */
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700282 init_completion(&dev->cmd_done);
Dmitry Torokhovdd0d5442009-08-05 00:30:26 -0700283 serio_write(serio, 0);
284 serio_write(serio, 0);
285 serio_write(serio, HIL_PKT_CMD >> 8);
286 serio_write(serio, HIL_CMD_IDD);
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700287 error = wait_for_completion_killable(&dev->cmd_done);
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700288 if (error)
289 goto bail1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700291 init_completion(&dev->cmd_done);
Dmitry Torokhovdd0d5442009-08-05 00:30:26 -0700292 serio_write(serio, 0);
293 serio_write(serio, 0);
294 serio_write(serio, HIL_PKT_CMD >> 8);
295 serio_write(serio, HIL_CMD_RSC);
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700296 error = wait_for_completion_killable(&dev->cmd_done);
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700297 if (error)
298 goto bail1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700300 init_completion(&dev->cmd_done);
Dmitry Torokhovdd0d5442009-08-05 00:30:26 -0700301 serio_write(serio, 0);
302 serio_write(serio, 0);
303 serio_write(serio, HIL_PKT_CMD >> 8);
304 serio_write(serio, HIL_CMD_RNM);
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700305 error = wait_for_completion_killable(&dev->cmd_done);
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700306 if (error)
307 goto bail1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700309 init_completion(&dev->cmd_done);
Dmitry Torokhovdd0d5442009-08-05 00:30:26 -0700310 serio_write(serio, 0);
311 serio_write(serio, 0);
312 serio_write(serio, HIL_PKT_CMD >> 8);
313 serio_write(serio, HIL_CMD_EXD);
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700314 error = wait_for_completion_killable(&dev->cmd_done);
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700315 if (error)
316 goto bail1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700318 did = dev->idd[0];
319 idd = dev->idd + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 switch (did & HIL_IDD_DID_TYPE_MASK) {
321 case HIL_IDD_DID_TYPE_KB_INTEGRAL:
322 case HIL_IDD_DID_TYPE_KB_ITF:
323 case HIL_IDD_DID_TYPE_KB_RSVD:
324 case HIL_IDD_DID_TYPE_CHAR:
325 printk(KERN_INFO PREFIX "HIL keyboard found (did = 0x%02x, lang = %s)\n",
326 did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]);
327 break;
328 default:
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700329 goto bail1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 }
331
Helge Dellerffd51f42007-02-28 23:51:29 -0500332 if (HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n");
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700334 goto bail1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 }
336
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700337 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
338 input_dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) |
339 BIT_MASK(LED_SCROLLL);
340 input_dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE;
341 input_dev->keycodesize = sizeof(hil_kbd_set1[0]);
342 input_dev->keycode = hil_kbd_set1;
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700343 input_dev->name = strlen(dev->rnm) ? dev->rnm : HIL_GENERIC_NAME;
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700344 input_dev->phys = "hpkbd/input0"; /* XXX */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700346 input_dev->id.bustype = BUS_HIL;
347 input_dev->id.vendor = PCI_VENDOR_ID_HP;
348 input_dev->id.product = 0x0001; /* TODO: get from kbd->rsc */
349 input_dev->id.version = 0x0100; /* TODO: get from kbd->rsc */
350 input_dev->dev.parent = &serio->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351
352 for (i = 0; i < 128; i++) {
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700353 __set_bit(hil_kbd_set1[i], input_dev->keybit);
354 __set_bit(hil_kbd_set3[i], input_dev->keybit);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 }
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700356 __clear_bit(KEY_RESERVED, input_dev->keybit);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
Dmitry Torokhovdd0d5442009-08-05 00:30:26 -0700358 serio_write(serio, 0);
359 serio_write(serio, 0);
360 serio_write(serio, HIL_PKT_CMD >> 8);
361 serio_write(serio, HIL_CMD_EK1); /* Enable Keyswitch Autorepeat 1 */
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700362 /* No need to wait for completion */
363
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700364 error = input_register_device(input_dev);
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700365 if (error)
366 goto bail1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367
Matthew Wilcox6ab0f5c2005-10-21 22:58:51 -0400368 return 0;
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700369
370 bail1:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 serio_close(serio);
Matthew Wilcoxd668da82006-04-03 13:44:17 +0000372 serio_set_drvdata(serio, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 bail0:
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700374 input_free_device(input_dev);
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700375 kfree(dev);
Dmitry Torokhov6777f012009-08-07 23:17:46 -0700376 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377}
378
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700379static struct serio_device_id hil_dev_ids[] = {
Matthew Wilcox6ab0f5c2005-10-21 22:58:51 -0400380 {
381 .type = SERIO_HIL_MLC,
382 .proto = SERIO_HIL,
383 .id = SERIO_ANY,
384 .extra = SERIO_ANY,
385 },
386 { 0 }
387};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700389static struct serio_driver hil_serio_drv = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 .driver = {
391 .name = "hil_kbd",
392 },
393 .description = "HP HIL keyboard driver",
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700394 .id_table = hil_dev_ids,
395 .connect = hil_dev_connect,
396 .disconnect = hil_dev_disconnect,
397 .interrupt = hil_dev_interrupt
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398};
399
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700400static int __init hil_dev_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401{
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700402 return serio_register_driver(&hil_serio_drv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403}
Helge Dellerffd51f42007-02-28 23:51:29 -0500404
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700405static void __exit hil_dev_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406{
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700407 serio_unregister_driver(&hil_serio_drv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408}
Helge Dellerffd51f42007-02-28 23:51:29 -0500409
Dmitry Torokhov1437dc32009-08-07 23:17:47 -0700410module_init(hil_dev_init);
411module_exit(hil_dev_exit);