hil_kbd.c 14.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
/*
 * Generic linux-input device driver for keyboard devices
 *
 * Copyright (c) 2001 Brian S. Julin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification.
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL").
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 *
 * References:
 * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
 *
 */

#include <linux/hil.h>
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/kernel.h>
#include <linux/module.h>
39
#include <linux/completion.h>
L
Linus Torvalds 已提交
40 41 42
#include <linux/slab.h>
#include <linux/pci_ids.h>

43
#define PREFIX "HIL: "
L
Linus Torvalds 已提交
44 45

MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
46
MODULE_DESCRIPTION("HIL keyboard/mouse driver");
L
Linus Torvalds 已提交
47
MODULE_LICENSE("Dual BSD/GPL");
48 49
MODULE_ALIAS("serio:ty03pr25id00ex*"); /* HIL keyboard */
MODULE_ALIAS("serio:ty03pr25id0Fex*"); /* HIL mouse */
L
Linus Torvalds 已提交
50

51
#define HIL_PACKET_MAX_LENGTH 16
L
Linus Torvalds 已提交
52 53 54

#define HIL_KBD_SET1_UPBIT 0x01
#define HIL_KBD_SET1_SHIFT 1
55
static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] __read_mostly =
L
Linus Torvalds 已提交
56 57 58 59 60 61 62 63
	{ HIL_KEYCODES_SET1 };

#define HIL_KBD_SET2_UPBIT 0x01
#define HIL_KBD_SET2_SHIFT 1
/* Set2 is user defined */

#define HIL_KBD_SET3_UPBIT 0x80
#define HIL_KBD_SET3_SHIFT 0
64
static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] __read_mostly =
L
Linus Torvalds 已提交
65 66
	{ HIL_KEYCODES_SET3 };

67
static const char hil_language[][16] = { HIL_LOCALE_MAP };
L
Linus Torvalds 已提交
68

69
struct hil_dev {
70
	struct input_dev *dev;
L
Linus Torvalds 已提交
71 72 73
	struct serio *serio;

	/* Input buffer and index for packets from HIL bus. */
74
	hil_packet data[HIL_PACKET_MAX_LENGTH];
L
Linus Torvalds 已提交
75 76 77
	int idx4; /* four counts per packet */

	/* Raw device info records from HIL bus, see hil.h for fields. */
78 79 80 81
	char	idd[HIL_PACKET_MAX_LENGTH];	/* DID byte and IDD record */
	char	rsc[HIL_PACKET_MAX_LENGTH];	/* RSC record */
	char	exd[HIL_PACKET_MAX_LENGTH];	/* EXD record */
	char	rnm[HIL_PACKET_MAX_LENGTH + 1];	/* RNM record + NULL term. */
L
Linus Torvalds 已提交
82

83
	struct completion cmd_done;
84 85 86 87 88

	bool is_pointer;
	/* Extra device details needed for pointing devices. */
	unsigned int nbtn, naxes;
	unsigned int btnmap[7];
L
Linus Torvalds 已提交
89 90
};

91
static bool hil_dev_is_command_response(hil_packet p)
L
Linus Torvalds 已提交
92
{
93 94
	if ((p & ~HIL_CMDCT_POL) == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL))
		return false;
L
Linus Torvalds 已提交
95

96 97 98 99 100 101
	if ((p & ~HIL_CMDCT_RPL) == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL))
		return false;

	return true;
}

102
static void hil_dev_handle_command_response(struct hil_dev *dev)
103 104 105 106
{
	hil_packet p;
	char *buf;
	int i, idx;
L
Linus Torvalds 已提交
107

108 109
	idx = dev->idx4 / 4;
	p = dev->data[idx - 1];
L
Linus Torvalds 已提交
110 111 112

	switch (p & HIL_PKT_DATA_MASK) {
	case HIL_CMD_IDD:
113
		buf = dev->idd;
L
Linus Torvalds 已提交
114
		break;
H
Helge Deller 已提交
115

L
Linus Torvalds 已提交
116
	case HIL_CMD_RSC:
117
		buf = dev->rsc;
L
Linus Torvalds 已提交
118
		break;
H
Helge Deller 已提交
119

L
Linus Torvalds 已提交
120
	case HIL_CMD_EXD:
121
		buf = dev->exd;
L
Linus Torvalds 已提交
122
		break;
H
Helge Deller 已提交
123

L
Linus Torvalds 已提交
124
	case HIL_CMD_RNM:
125 126
		dev->rnm[HIL_PACKET_MAX_LENGTH] = 0;
		buf = dev->rnm;
L
Linus Torvalds 已提交
127
		break;
H
Helge Deller 已提交
128

L
Linus Torvalds 已提交
129 130
	default:
		/* These occur when device isn't present */
131 132 133 134 135
		if (p != (HIL_ERR_INT | HIL_PKT_CMD)) {
			/* Anything else we'd like to know about. */
			printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
		}
		goto out;
L
Linus Torvalds 已提交
136 137
	}

138
	for (i = 0; i < idx; i++)
139 140
		buf[i] = dev->data[i] & HIL_PKT_DATA_MASK;
	for (; i < HIL_PACKET_MAX_LENGTH; i++)
141 142
		buf[i] = 0;
 out:
143
	complete(&dev->cmd_done);
144 145
}

146
static void hil_dev_handle_kbd_events(struct hil_dev *kbd)
147 148 149 150 151
{
	struct input_dev *dev = kbd->dev;
	int idx = kbd->idx4 / 4;
	int i;

L
Linus Torvalds 已提交
152 153
	switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) {
	case HIL_POL_CHARTYPE_NONE:
154
		return;
H
Helge Deller 已提交
155

L
Linus Torvalds 已提交
156
	case HIL_POL_CHARTYPE_ASCII:
157 158
		for (i = 1; i < idx - 1; i++)
			input_report_key(dev, kbd->data[i] & 0x7f, 1);
L
Linus Torvalds 已提交
159
		break;
H
Helge Deller 已提交
160

L
Linus Torvalds 已提交
161 162 163
	case HIL_POL_CHARTYPE_RSVD1:
	case HIL_POL_CHARTYPE_RSVD2:
	case HIL_POL_CHARTYPE_BINARY:
164 165
		for (i = 1; i < idx - 1; i++)
			input_report_key(dev, kbd->data[i], 1);
L
Linus Torvalds 已提交
166
		break;
H
Helge Deller 已提交
167

L
Linus Torvalds 已提交
168
	case HIL_POL_CHARTYPE_SET1:
169 170 171 172
		for (i = 1; i < idx - 1; i++) {
			unsigned int key = kbd->data[i];
			int up = key & HIL_KBD_SET1_UPBIT;

L
Linus Torvalds 已提交
173 174
			key &= (~HIL_KBD_SET1_UPBIT & 0xff);
			key = hil_kbd_set1[key >> HIL_KBD_SET1_SHIFT];
175
			input_report_key(dev, key, !up);
L
Linus Torvalds 已提交
176 177
		}
		break;
H
Helge Deller 已提交
178

L
Linus Torvalds 已提交
179
	case HIL_POL_CHARTYPE_SET2:
180 181 182 183
		for (i = 1; i < idx - 1; i++) {
			unsigned int key = kbd->data[i];
			int up = key & HIL_KBD_SET2_UPBIT;

L
Linus Torvalds 已提交
184 185
			key &= (~HIL_KBD_SET1_UPBIT & 0xff);
			key = key >> HIL_KBD_SET2_SHIFT;
186
			input_report_key(dev, key, !up);
L
Linus Torvalds 已提交
187 188
		}
		break;
H
Helge Deller 已提交
189

L
Linus Torvalds 已提交
190
	case HIL_POL_CHARTYPE_SET3:
191 192 193 194
		for (i = 1; i < idx - 1; i++) {
			unsigned int key = kbd->data[i];
			int up = key & HIL_KBD_SET3_UPBIT;

L
Linus Torvalds 已提交
195 196
			key &= (~HIL_KBD_SET1_UPBIT & 0xff);
			key = hil_kbd_set3[key >> HIL_KBD_SET3_SHIFT];
197
			input_report_key(dev, key, !up);
L
Linus Torvalds 已提交
198 199 200
		}
		break;
	}
201 202

	input_sync(dev);
L
Linus Torvalds 已提交
203 204
}

205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
static void hil_dev_handle_ptr_events(struct hil_dev *ptr)
{
	struct input_dev *dev = ptr->dev;
	int idx = ptr->idx4 / 4;
	hil_packet p = ptr->data[idx - 1];
	int i, cnt, laxis;
	bool absdev, ax16;

	if ((p & HIL_CMDCT_POL) != idx - 1) {
		printk(KERN_WARNING PREFIX
			"Malformed poll packet %x (idx = %i)\n", p, idx);
		return;
	}

	i = (p & HIL_POL_AXIS_ALT) ? 3 : 0;
	laxis = (p & HIL_POL_NUM_AXES_MASK) + i;

	ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */
	absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS;

	for (cnt = 1; i < laxis; i++) {
		unsigned int lo, hi, val;

		lo = ptr->data[cnt++] & HIL_PKT_DATA_MASK;
		hi = ax16 ? (ptr->data[cnt++] & HIL_PKT_DATA_MASK) : 0;

		if (absdev) {
			val = lo + (hi << 8);
#ifdef TABLET_AUTOADJUST
234
			if (val < input_abs_get_min(dev, ABS_X + i))
235
				input_abs_set_min(dev, ABS_X + i, val);
236
			if (val > input_abs_get_max(dev, ABS_X + i))
D
Daniel Mack 已提交
237
				input_abs_set_max(dev, ABS_X + i, val);
238
#endif
239
			if (i % 3)
240
				val = input_abs_get_max(dev, ABS_X + i) - val;
241 242
			input_report_abs(dev, ABS_X + i, val);
		} else {
243
			val = (int) (((int8_t) lo) | ((int8_t) hi << 8));
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
			if (i % 3)
				val *= -1;
			input_report_rel(dev, REL_X + i, val);
		}
	}

	while (cnt < idx - 1) {
		unsigned int btn = ptr->data[cnt++];
		int up = btn & 1;

		btn &= 0xfe;
		if (btn == 0x8e)
			continue; /* TODO: proximity == touch? */
		if (btn > 0x8c || btn < 0x80)
			continue;
		btn = (btn - 0x80) >> 1;
		btn = ptr->btnmap[btn];
		input_report_key(dev, btn, !up);
	}

	input_sync(dev);
}

267
static void hil_dev_process_err(struct hil_dev *dev)
H
Helge Deller 已提交
268
{
L
Linus Torvalds 已提交
269
	printk(KERN_WARNING PREFIX "errored HIL packet\n");
270 271
	dev->idx4 = 0;
	complete(&dev->cmd_done); /* just in case somebody is waiting */
L
Linus Torvalds 已提交
272 273
}

274
static irqreturn_t hil_dev_interrupt(struct serio *serio,
H
Helge Deller 已提交
275
				unsigned char data, unsigned int flags)
L
Linus Torvalds 已提交
276
{
277
	struct hil_dev *dev;
L
Linus Torvalds 已提交
278 279 280
	hil_packet packet;
	int idx;

281 282
	dev = serio_get_drvdata(serio);
	BUG_ON(dev == NULL);
L
Linus Torvalds 已提交
283

284 285
	if (dev->idx4 >= HIL_PACKET_MAX_LENGTH * sizeof(hil_packet)) {
		hil_dev_process_err(dev);
286
		goto out;
L
Linus Torvalds 已提交
287
	}
288

289 290 291 292 293 294
	idx = dev->idx4 / 4;
	if (!(dev->idx4 % 4))
		dev->data[idx] = 0;
	packet = dev->data[idx];
	packet |= ((hil_packet)data) << ((3 - (dev->idx4 % 4)) * 8);
	dev->data[idx] = packet;
L
Linus Torvalds 已提交
295 296

	/* Records of N 4-byte hil_packets must terminate with a command. */
297
	if ((++dev->idx4 % 4) == 0) {
298
		if ((packet & 0xffff0000) != HIL_ERR_INT) {
299
			hil_dev_process_err(dev);
300
		} else if (packet & HIL_PKT_CMD) {
301 302
			if (hil_dev_is_command_response(packet))
				hil_dev_handle_command_response(dev);
303 304
			else if (dev->is_pointer)
				hil_dev_handle_ptr_events(dev);
305
			else
306
				hil_dev_handle_kbd_events(dev);
307
			dev->idx4 = 0;
308
		}
L
Linus Torvalds 已提交
309
	}
310
 out:
L
Linus Torvalds 已提交
311 312 313
	return IRQ_HANDLED;
}

314
static void hil_dev_disconnect(struct serio *serio)
L
Linus Torvalds 已提交
315
{
316
	struct hil_dev *dev = serio_get_drvdata(serio);
L
Linus Torvalds 已提交
317

318
	BUG_ON(dev == NULL);
L
Linus Torvalds 已提交
319 320

	serio_close(serio);
321
	input_unregister_device(dev->dev);
322
	serio_set_drvdata(serio, NULL);
323
	kfree(dev);
L
Linus Torvalds 已提交
324 325
}

326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
static void hil_dev_keyboard_setup(struct hil_dev *kbd)
{
	struct input_dev *input_dev = kbd->dev;
	uint8_t did = kbd->idd[0];
	int i;

	input_dev->evbit[0]	= BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
	input_dev->ledbit[0]	= BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) |
				  BIT_MASK(LED_SCROLLL);

	for (i = 0; i < 128; i++) {
		__set_bit(hil_kbd_set1[i], input_dev->keybit);
		__set_bit(hil_kbd_set3[i], input_dev->keybit);
	}
	__clear_bit(KEY_RESERVED, input_dev->keybit);

	input_dev->keycodemax	= HIL_KEYCODES_SET1_TBLSIZE;
	input_dev->keycodesize	= sizeof(hil_kbd_set1[0]);
	input_dev->keycode	= hil_kbd_set1;

	input_dev->name	= strlen(kbd->rnm) ? kbd->rnm : "HIL keyboard";
	input_dev->phys	= "hpkbd/input0";

	printk(KERN_INFO PREFIX "HIL keyboard found (did = 0x%02x, lang = %s)\n",
		did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]);
}

static void hil_dev_pointer_setup(struct hil_dev *ptr)
{
	struct input_dev *input_dev = ptr->dev;
	uint8_t did = ptr->idd[0];
	uint8_t *idd = ptr->idd + 1;
	unsigned int naxsets = HIL_IDD_NUM_AXSETS(*idd);
	unsigned int i, btntype;
	const char *txt;

	ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd);

	switch (did & HIL_IDD_DID_TYPE_MASK) {
	case HIL_IDD_DID_TYPE_REL:
		input_dev->evbit[0] = BIT_MASK(EV_REL);

		for (i = 0; i < ptr->naxes; i++)
			__set_bit(REL_X + i, input_dev->relbit);

		for (i = 3; naxsets > 1 && i < ptr->naxes + 3; i++)
			__set_bit(REL_X + i, input_dev->relbit);

		txt = "relative";
		break;

	case HIL_IDD_DID_TYPE_ABS:
		input_dev->evbit[0] = BIT_MASK(EV_ABS);

		for (i = 0; i < ptr->naxes; i++)
			input_set_abs_params(input_dev, ABS_X + i,
					0, HIL_IDD_AXIS_MAX(idd, i), 0, 0);

		for (i = 3; naxsets > 1 && i < ptr->naxes + 3; i++)
			input_set_abs_params(input_dev, ABS_X + i,
					0, HIL_IDD_AXIS_MAX(idd, i - 3), 0, 0);

#ifdef TABLET_AUTOADJUST
		for (i = 0; i < ABS_MAX; i++) {
390
			int diff = input_abs_get_max(input_dev, ABS_X + i) / 10;
391
			input_abs_set_min(input_dev, ABS_X + i,
392
				input_abs_get_min(input_dev, ABS_X + i) + diff);
D
Daniel Mack 已提交
393
			input_abs_set_max(input_dev, ABS_X + i,
394
				input_abs_get_max(input_dev, ABS_X + i) - diff);
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
		}
#endif

		txt = "absolute";
		break;

	default:
		BUG();
	}

	ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd);
	if (ptr->nbtn)
		input_dev->evbit[0] |= BIT_MASK(EV_KEY);

	btntype = BTN_MISC;
	if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET)
#ifdef TABLET_SIMULATES_MOUSE
		btntype = BTN_TOUCH;
#else
		btntype = BTN_DIGI;
#endif
	if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN)
		btntype = BTN_TOUCH;

	if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE)
		btntype = BTN_MOUSE;

	for (i = 0; i < ptr->nbtn; i++) {
		__set_bit(btntype | i, input_dev->keybit);
		ptr->btnmap[i] = btntype | i;
	}

	if (btntype == BTN_MOUSE) {
		/* Swap buttons 2 and 3 */
		ptr->btnmap[1] = BTN_MIDDLE;
		ptr->btnmap[2] = BTN_RIGHT;
	}

	input_dev->name = strlen(ptr->rnm) ? ptr->rnm : "HIL pointer device";

	printk(KERN_INFO PREFIX
		"HIL pointer device found (did: 0x%02x, axis: %s)\n",
		did, txt);
	printk(KERN_INFO PREFIX
		"HIL pointer has %i buttons and %i sets of %i axes\n",
		ptr->nbtn, naxsets, ptr->naxes);
}

443
static int hil_dev_connect(struct serio *serio, struct serio_driver *drv)
L
Linus Torvalds 已提交
444
{
445
	struct hil_dev *dev;
446 447 448
	struct input_dev *input_dev;
	uint8_t did, *idd;
	int error;
D
Dmitry Torokhov 已提交
449

450
	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
451
	input_dev = input_allocate_device();
452
	if (!dev || !input_dev) {
453
		error = -ENOMEM;
D
Dmitry Torokhov 已提交
454
		goto bail0;
455
	}
D
Dmitry Torokhov 已提交
456

457 458
	dev->serio = serio;
	dev->dev = input_dev;
459 460 461 462

	error = serio_open(serio, drv);
	if (error)
		goto bail0;
L
Linus Torvalds 已提交
463

464
	serio_set_drvdata(serio, dev);
L
Linus Torvalds 已提交
465 466

	/* Get device info.  MLC driver supplies devid/status/etc. */
467
	init_completion(&dev->cmd_done);
468 469 470 471
	serio_write(serio, 0);
	serio_write(serio, 0);
	serio_write(serio, HIL_PKT_CMD >> 8);
	serio_write(serio, HIL_CMD_IDD);
472
	error = wait_for_completion_killable(&dev->cmd_done);
473 474
	if (error)
		goto bail1;
L
Linus Torvalds 已提交
475

476
	init_completion(&dev->cmd_done);
477 478 479 480
	serio_write(serio, 0);
	serio_write(serio, 0);
	serio_write(serio, HIL_PKT_CMD >> 8);
	serio_write(serio, HIL_CMD_RSC);
481
	error = wait_for_completion_killable(&dev->cmd_done);
482 483
	if (error)
		goto bail1;
L
Linus Torvalds 已提交
484

485
	init_completion(&dev->cmd_done);
486 487 488 489
	serio_write(serio, 0);
	serio_write(serio, 0);
	serio_write(serio, HIL_PKT_CMD >> 8);
	serio_write(serio, HIL_CMD_RNM);
490
	error = wait_for_completion_killable(&dev->cmd_done);
491 492
	if (error)
		goto bail1;
L
Linus Torvalds 已提交
493

494
	init_completion(&dev->cmd_done);
495 496 497 498
	serio_write(serio, 0);
	serio_write(serio, 0);
	serio_write(serio, HIL_PKT_CMD >> 8);
	serio_write(serio, HIL_CMD_EXD);
499
	error = wait_for_completion_killable(&dev->cmd_done);
500 501
	if (error)
		goto bail1;
L
Linus Torvalds 已提交
502

503 504
	did = dev->idd[0];
	idd = dev->idd + 1;
505

L
Linus Torvalds 已提交
506 507 508 509 510
	switch (did & HIL_IDD_DID_TYPE_MASK) {
	case HIL_IDD_DID_TYPE_KB_INTEGRAL:
	case HIL_IDD_DID_TYPE_KB_ITF:
	case HIL_IDD_DID_TYPE_KB_RSVD:
	case HIL_IDD_DID_TYPE_CHAR:
511 512 513 514 515 516 517 518 519
		if (HIL_IDD_NUM_BUTTONS(idd) ||
		    HIL_IDD_NUM_AXES_PER_SET(*idd)) {
			printk(KERN_INFO PREFIX
				"combo devices are not supported.\n");
			goto bail1;
		}

		dev->is_pointer = false;
		hil_dev_keyboard_setup(dev);
L
Linus Torvalds 已提交
520 521
		break;

522 523 524 525 526 527 528
	case HIL_IDD_DID_TYPE_REL:
	case HIL_IDD_DID_TYPE_ABS:
		dev->is_pointer = true;
		hil_dev_pointer_setup(dev);
		break;

	default:
529
		goto bail1;
L
Linus Torvalds 已提交
530 531
	}

532 533 534 535 536
	input_dev->id.bustype	= BUS_HIL;
	input_dev->id.vendor	= PCI_VENDOR_ID_HP;
	input_dev->id.product	= 0x0001; /* TODO: get from kbd->rsc */
	input_dev->id.version	= 0x0100; /* TODO: get from kbd->rsc */
	input_dev->dev.parent	= &serio->dev;
L
Linus Torvalds 已提交
537

538 539 540 541 542 543 544
	if (!dev->is_pointer) {
		serio_write(serio, 0);
		serio_write(serio, 0);
		serio_write(serio, HIL_PKT_CMD >> 8);
		/* Enable Keyswitch Autorepeat 1 */
		serio_write(serio, HIL_CMD_EK1);
		/* No need to wait for completion */
L
Linus Torvalds 已提交
545
	}
546

547
	error = input_register_device(input_dev);
548 549
	if (error)
		goto bail1;
L
Linus Torvalds 已提交
550

551
	return 0;
552 553

 bail1:
L
Linus Torvalds 已提交
554
	serio_close(serio);
555
	serio_set_drvdata(serio, NULL);
L
Linus Torvalds 已提交
556
 bail0:
557
	input_free_device(input_dev);
558
	kfree(dev);
559
	return error;
L
Linus Torvalds 已提交
560 561
}

562
static struct serio_device_id hil_dev_ids[] = {
563 564 565 566 567 568 569 570
	{
		.type = SERIO_HIL_MLC,
		.proto = SERIO_HIL,
		.id = SERIO_ANY,
		.extra = SERIO_ANY,
	},
	{ 0 }
};
L
Linus Torvalds 已提交
571

572 573
MODULE_DEVICE_TABLE(serio, hil_dev_ids);

574
static struct serio_driver hil_serio_drv = {
L
Linus Torvalds 已提交
575
	.driver		= {
576
		.name	= "hil_dev",
L
Linus Torvalds 已提交
577
	},
578
	.description	= "HP HIL keyboard/mouse/tablet driver",
579 580 581 582
	.id_table	= hil_dev_ids,
	.connect	= hil_dev_connect,
	.disconnect	= hil_dev_disconnect,
	.interrupt	= hil_dev_interrupt
L
Linus Torvalds 已提交
583 584
};

585
module_serio_driver(hil_serio_drv);