hil_kbd.c 14.7 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 39
/*
 * 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>
#include <linux/init.h>
40
#include <linux/completion.h>
L
Linus Torvalds 已提交
41 42 43
#include <linux/slab.h>
#include <linux/pci_ids.h>

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

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

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

#define HIL_KBD_SET1_UPBIT 0x01
#define HIL_KBD_SET1_SHIFT 1
56
static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] __read_mostly =
L
Linus Torvalds 已提交
57 58 59 60 61 62 63 64
	{ 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
65
static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] __read_mostly =
L
Linus Torvalds 已提交
66 67
	{ HIL_KEYCODES_SET3 };

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

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

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

	/* Raw device info records from HIL bus, see hil.h for fields. */
79 80 81 82
	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 已提交
83

84
	struct completion cmd_done;
85 86 87 88 89

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

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

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

	return true;
}

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

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

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

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

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

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

L
Linus Torvalds 已提交
130 131
	default:
		/* These occur when device isn't present */
132 133 134 135 136
		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 已提交
137 138
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

290 291 292 293 294 295
	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 已提交
296 297

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

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

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

	serio_close(serio);
322
	input_unregister_device(dev->dev);
323
	serio_set_drvdata(serio, NULL);
324
	kfree(dev);
L
Linus Torvalds 已提交
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 390
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++) {
391
			int diff = input_abs_get_max(input_dev, ABS_X + i) / 10;
392
			input_abs_set_min(input_dev, ABS_X + i,
393
				input_abs_get_min(input_dev, ABS_X + i) + diff);
D
Daniel Mack 已提交
394
			input_abs_set_max(input_dev, ABS_X + i,
395
				input_abs_get_max(input_dev, ABS_X + i) - diff);
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 443
		}
#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);
}

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

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

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

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

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

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

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

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

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

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

L
Linus Torvalds 已提交
507 508 509 510 511
	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:
512 513 514 515 516 517 518 519 520
		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 已提交
521 522
		break;

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

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

533 534 535 536 537
	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 已提交
538

539 540 541 542 543 544 545
	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 已提交
546
	}
547

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

552
	return 0;
553 554

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

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

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

584
static int __init hil_dev_init(void)
L
Linus Torvalds 已提交
585
{
586
	return serio_register_driver(&hil_serio_drv);
L
Linus Torvalds 已提交
587
}
H
Helge Deller 已提交
588

589
static void __exit hil_dev_exit(void)
L
Linus Torvalds 已提交
590
{
591
	serio_unregister_driver(&hil_serio_drv);
L
Linus Torvalds 已提交
592
}
H
Helge Deller 已提交
593

594 595
module_init(hil_dev_init);
module_exit(hil_dev_exit);