hid-lenovo.c 18.9 KB
Newer Older
1
/*
2 3
 *  HID driver for Lenovo:
 *  - ThinkPad USB Keyboard with TrackPoint (tpkbd)
4 5
 *  - ThinkPad Compact Bluetooth Keyboard with TrackPoint (cptkbd)
 *  - ThinkPad Compact USB Keyboard with TrackPoint (cptkbd)
6 7
 *
 *  Copyright (c) 2012 Bernhard Seibold
8
 *  Copyright (c) 2014 Jamie Lentin <jm@lentin.co.uk>
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 */

/*
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 */

#include <linux/module.h>
#include <linux/sysfs.h>
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/input.h>
#include <linux/leds.h>

#include "hid-ids.h"

27
struct lenovo_drvdata_tpkbd {
28 29 30 31 32 33 34 35 36 37 38
	int led_state;
	struct led_classdev led_mute;
	struct led_classdev led_micmute;
	int press_to_select;
	int dragging;
	int release_to_select;
	int select_right;
	int sensitivity;
	int press_speed;
};

39 40 41 42
struct lenovo_drvdata_cptkbd {
	bool fn_lock;
};

43 44
#define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))

45
static int lenovo_input_mapping_tpkbd(struct hid_device *hdev,
46 47 48
		struct hid_input *hi, struct hid_field *field,
		struct hid_usage *usage, unsigned long **bit, int *max)
{
49
	if (usage->hid == (HID_UP_BUTTON | 0x0010)) {
50
		/* This sub-device contains trackpoint, mark it */
51
		hid_set_drvdata(hdev, (void *)1);
52 53 54 55 56 57
		map_key_clear(KEY_MICMUTE);
		return 1;
	}
	return 0;
}

58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
static int lenovo_input_mapping_cptkbd(struct hid_device *hdev,
		struct hid_input *hi, struct hid_field *field,
		struct hid_usage *usage, unsigned long **bit, int *max)
{
	/* HID_UP_LNVENDOR = USB, HID_UP_MSVENDOR = BT */
	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR ||
	    (usage->hid & HID_USAGE_PAGE) == HID_UP_LNVENDOR) {
		set_bit(EV_REP, hi->input->evbit);
		switch (usage->hid & HID_USAGE) {
		case 0x00f1: /* Fn-F4: Mic mute */
			map_key_clear(KEY_MICMUTE);
			return 1;
		case 0x00f2: /* Fn-F5: Brightness down */
			map_key_clear(KEY_BRIGHTNESSDOWN);
			return 1;
		case 0x00f3: /* Fn-F6: Brightness up */
			map_key_clear(KEY_BRIGHTNESSUP);
			return 1;
		case 0x00f4: /* Fn-F7: External display (projector) */
			map_key_clear(KEY_SWITCHVIDEOMODE);
			return 1;
		case 0x00f5: /* Fn-F8: Wireless */
			map_key_clear(KEY_WLAN);
			return 1;
		case 0x00f6: /* Fn-F9: Control panel */
			map_key_clear(KEY_CONFIG);
			return 1;
		case 0x00f8: /* Fn-F11: View open applications (3 boxes) */
			map_key_clear(KEY_SCALE);
			return 1;
		case 0x00fa: /* Fn-Esc: Fn-lock toggle */
			map_key_clear(KEY_FN_ESC);
			return 1;
		case 0x00fb: /* Fn-F12: Open My computer (6 boxes) USB-only */
			/* NB: This mapping is invented in raw_event below */
			map_key_clear(KEY_FILE);
			return 1;
		}
	}

	return 0;
}

101 102 103 104 105 106 107 108
static int lenovo_input_mapping(struct hid_device *hdev,
		struct hid_input *hi, struct hid_field *field,
		struct hid_usage *usage, unsigned long **bit, int *max)
{
	switch (hdev->product) {
	case USB_DEVICE_ID_LENOVO_TPKBD:
		return lenovo_input_mapping_tpkbd(hdev, hi, field,
							usage, bit, max);
109 110 111 112
	case USB_DEVICE_ID_LENOVO_CUSBKBD:
	case USB_DEVICE_ID_LENOVO_CBTKBD:
		return lenovo_input_mapping_cptkbd(hdev, hi, field,
							usage, bit, max);
113 114 115 116 117
	default:
		return 0;
	}
}

118 119
#undef map_key_clear

120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
/* Send a config command to the keyboard */
static int lenovo_send_cmd_cptkbd(struct hid_device *hdev,
			unsigned char byte2, unsigned char byte3)
{
	int ret;
	unsigned char buf[] = {0x18, byte2, byte3};

	switch (hdev->product) {
	case USB_DEVICE_ID_LENOVO_CUSBKBD:
		ret = hid_hw_raw_request(hdev, 0x13, buf, sizeof(buf),
					HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
		break;
	case USB_DEVICE_ID_LENOVO_CBTKBD:
		ret = hid_hw_output_report(hdev, buf, sizeof(buf));
		break;
	default:
		ret = -EINVAL;
		break;
	}

	return ret < 0 ? ret : 0; /* BT returns 0, USB returns sizeof(buf) */
}

static void lenovo_features_set_cptkbd(struct hid_device *hdev)
{
	int ret;
	struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);

	ret = lenovo_send_cmd_cptkbd(hdev, 0x05, cptkbd_data->fn_lock);
	if (ret)
		hid_err(hdev, "Fn-lock setting failed: %d\n", ret);
}

static ssize_t attr_fn_lock_show_cptkbd(struct device *dev,
		struct device_attribute *attr,
		char *buf)
{
	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
	struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);

	return snprintf(buf, PAGE_SIZE, "%u\n", cptkbd_data->fn_lock);
}

static ssize_t attr_fn_lock_store_cptkbd(struct device *dev,
		struct device_attribute *attr,
		const char *buf,
		size_t count)
{
	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
	struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
	int value;

	if (kstrtoint(buf, 10, &value))
		return -EINVAL;
	if (value < 0 || value > 1)
		return -EINVAL;

	cptkbd_data->fn_lock = !!value;
	lenovo_features_set_cptkbd(hdev);

	return count;
}

static struct device_attribute dev_attr_fn_lock_cptkbd =
	__ATTR(fn_lock, S_IWUSR | S_IRUGO,
			attr_fn_lock_show_cptkbd,
			attr_fn_lock_store_cptkbd);

static struct attribute *lenovo_attributes_cptkbd[] = {
	&dev_attr_fn_lock_cptkbd.attr,
	NULL
};

static const struct attribute_group lenovo_attr_group_cptkbd = {
	.attrs = lenovo_attributes_cptkbd,
};

static int lenovo_raw_event(struct hid_device *hdev,
			struct hid_report *report, u8 *data, int size)
{
	/*
	 * Compact USB keyboard's Fn-F12 report holds down many other keys, and
	 * its own key is outside the usage page range. Remove extra
	 * keypresses and remap to inside usage page.
	 */
	if (unlikely(hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD
			&& size == 3
			&& data[0] == 0x15
			&& data[1] == 0x94
			&& data[2] == 0x01)) {
		data[1] = 0x0;
		data[2] = 0x4;
	}

	return 0;
}

217
static int lenovo_features_set_tpkbd(struct hid_device *hdev)
218 219
{
	struct hid_report *report;
220
	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
221 222 223 224 225 226 227 228 229 230 231

	report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4];

	report->field[0]->value[0]  = data_pointer->press_to_select   ? 0x01 : 0x02;
	report->field[0]->value[0] |= data_pointer->dragging          ? 0x04 : 0x08;
	report->field[0]->value[0] |= data_pointer->release_to_select ? 0x10 : 0x20;
	report->field[0]->value[0] |= data_pointer->select_right      ? 0x80 : 0x40;
	report->field[1]->value[0] = 0x03; // unknown setting, imitate windows driver
	report->field[2]->value[0] = data_pointer->sensitivity;
	report->field[3]->value[0] = data_pointer->press_speed;

232
	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
233 234 235
	return 0;
}

236
static ssize_t attr_press_to_select_show_tpkbd(struct device *dev,
237 238 239
		struct device_attribute *attr,
		char *buf)
{
240
	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
241
	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
242 243 244 245

	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select);
}

246
static ssize_t attr_press_to_select_store_tpkbd(struct device *dev,
247 248 249 250
		struct device_attribute *attr,
		const char *buf,
		size_t count)
{
251
	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
252
	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
253 254 255 256 257 258 259 260
	int value;

	if (kstrtoint(buf, 10, &value))
		return -EINVAL;
	if (value < 0 || value > 1)
		return -EINVAL;

	data_pointer->press_to_select = value;
261
	lenovo_features_set_tpkbd(hdev);
262 263 264 265

	return count;
}

266
static ssize_t attr_dragging_show_tpkbd(struct device *dev,
267 268 269
		struct device_attribute *attr,
		char *buf)
{
270
	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
271
	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
272 273 274 275

	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging);
}

276
static ssize_t attr_dragging_store_tpkbd(struct device *dev,
277 278 279 280
		struct device_attribute *attr,
		const char *buf,
		size_t count)
{
281
	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
282
	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
283 284 285 286 287 288 289 290
	int value;

	if (kstrtoint(buf, 10, &value))
		return -EINVAL;
	if (value < 0 || value > 1)
		return -EINVAL;

	data_pointer->dragging = value;
291
	lenovo_features_set_tpkbd(hdev);
292 293 294 295

	return count;
}

296
static ssize_t attr_release_to_select_show_tpkbd(struct device *dev,
297 298 299
		struct device_attribute *attr,
		char *buf)
{
300
	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
301
	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
302 303 304 305

	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select);
}

306
static ssize_t attr_release_to_select_store_tpkbd(struct device *dev,
307 308 309 310
		struct device_attribute *attr,
		const char *buf,
		size_t count)
{
311
	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
312
	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
313 314 315 316 317 318 319 320
	int value;

	if (kstrtoint(buf, 10, &value))
		return -EINVAL;
	if (value < 0 || value > 1)
		return -EINVAL;

	data_pointer->release_to_select = value;
321
	lenovo_features_set_tpkbd(hdev);
322 323 324 325

	return count;
}

326
static ssize_t attr_select_right_show_tpkbd(struct device *dev,
327 328 329
		struct device_attribute *attr,
		char *buf)
{
330
	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
331
	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
332 333 334 335

	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right);
}

336
static ssize_t attr_select_right_store_tpkbd(struct device *dev,
337 338 339 340
		struct device_attribute *attr,
		const char *buf,
		size_t count)
{
341
	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
342
	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
343 344 345 346 347 348 349 350
	int value;

	if (kstrtoint(buf, 10, &value))
		return -EINVAL;
	if (value < 0 || value > 1)
		return -EINVAL;

	data_pointer->select_right = value;
351
	lenovo_features_set_tpkbd(hdev);
352 353 354 355

	return count;
}

356
static ssize_t attr_sensitivity_show_tpkbd(struct device *dev,
357 358 359
		struct device_attribute *attr,
		char *buf)
{
360
	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
361
	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
362 363 364 365 366

	return snprintf(buf, PAGE_SIZE, "%u\n",
		data_pointer->sensitivity);
}

367
static ssize_t attr_sensitivity_store_tpkbd(struct device *dev,
368 369 370 371
		struct device_attribute *attr,
		const char *buf,
		size_t count)
{
372
	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
373
	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
374 375 376 377 378 379
	int value;

	if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
		return -EINVAL;

	data_pointer->sensitivity = value;
380
	lenovo_features_set_tpkbd(hdev);
381 382 383 384

	return count;
}

385
static ssize_t attr_press_speed_show_tpkbd(struct device *dev,
386 387 388
		struct device_attribute *attr,
		char *buf)
{
389
	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
390
	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
391 392 393 394 395

	return snprintf(buf, PAGE_SIZE, "%u\n",
		data_pointer->press_speed);
}

396
static ssize_t attr_press_speed_store_tpkbd(struct device *dev,
397 398 399 400
		struct device_attribute *attr,
		const char *buf,
		size_t count)
{
401
	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
402
	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
403 404 405 406 407 408
	int value;

	if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
		return -EINVAL;

	data_pointer->press_speed = value;
409
	lenovo_features_set_tpkbd(hdev);
410 411 412 413

	return count;
}

414
static struct device_attribute dev_attr_press_to_select_tpkbd =
415
	__ATTR(press_to_select, S_IWUSR | S_IRUGO,
416 417
			attr_press_to_select_show_tpkbd,
			attr_press_to_select_store_tpkbd);
418

419
static struct device_attribute dev_attr_dragging_tpkbd =
420
	__ATTR(dragging, S_IWUSR | S_IRUGO,
421 422
			attr_dragging_show_tpkbd,
			attr_dragging_store_tpkbd);
423

424
static struct device_attribute dev_attr_release_to_select_tpkbd =
425
	__ATTR(release_to_select, S_IWUSR | S_IRUGO,
426 427
			attr_release_to_select_show_tpkbd,
			attr_release_to_select_store_tpkbd);
428

429
static struct device_attribute dev_attr_select_right_tpkbd =
430
	__ATTR(select_right, S_IWUSR | S_IRUGO,
431 432
			attr_select_right_show_tpkbd,
			attr_select_right_store_tpkbd);
433

434
static struct device_attribute dev_attr_sensitivity_tpkbd =
435
	__ATTR(sensitivity, S_IWUSR | S_IRUGO,
436 437
			attr_sensitivity_show_tpkbd,
			attr_sensitivity_store_tpkbd);
438

439
static struct device_attribute dev_attr_press_speed_tpkbd =
440
	__ATTR(press_speed, S_IWUSR | S_IRUGO,
441 442 443 444 445 446 447 448 449 450
			attr_press_speed_show_tpkbd,
			attr_press_speed_store_tpkbd);

static struct attribute *lenovo_attributes_tpkbd[] = {
	&dev_attr_press_to_select_tpkbd.attr,
	&dev_attr_dragging_tpkbd.attr,
	&dev_attr_release_to_select_tpkbd.attr,
	&dev_attr_select_right_tpkbd.attr,
	&dev_attr_sensitivity_tpkbd.attr,
	&dev_attr_press_speed_tpkbd.attr,
451 452 453
	NULL
};

454 455
static const struct attribute_group lenovo_attr_group_tpkbd = {
	.attrs = lenovo_attributes_tpkbd,
456 457
};

458
static enum led_brightness lenovo_led_brightness_get_tpkbd(
459 460
			struct led_classdev *led_cdev)
{
461 462
	struct device *dev = led_cdev->dev->parent;
	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
463
	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
464 465 466 467 468 469 470 471 472 473
	int led_nr = 0;

	if (led_cdev == &data_pointer->led_micmute)
		led_nr = 1;

	return data_pointer->led_state & (1 << led_nr)
				? LED_FULL
				: LED_OFF;
}

474
static void lenovo_led_brightness_set_tpkbd(struct led_classdev *led_cdev,
475 476
			enum led_brightness value)
{
477 478
	struct device *dev = led_cdev->dev->parent;
	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
479
	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
480 481 482 483 484 485 486 487 488 489 490 491 492 493
	struct hid_report *report;
	int led_nr = 0;

	if (led_cdev == &data_pointer->led_micmute)
		led_nr = 1;

	if (value == LED_OFF)
		data_pointer->led_state &= ~(1 << led_nr);
	else
		data_pointer->led_state |= 1 << led_nr;

	report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3];
	report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1;
	report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1;
494
	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
495 496
}

497
static int lenovo_probe_tpkbd(struct hid_device *hdev)
498 499
{
	struct device *dev = &hdev->dev;
500
	struct lenovo_drvdata_tpkbd *data_pointer;
501 502
	size_t name_sz = strlen(dev_name(dev)) + 16;
	char *name_mute, *name_micmute;
503
	int i;
504
	int ret;
505

506 507 508 509 510 511 512 513 514
	/*
	 * Only register extra settings against subdevice where input_mapping
	 * set drvdata to 1, i.e. the trackpoint.
	 */
	if (!hid_get_drvdata(hdev))
		return 0;

	hid_set_drvdata(hdev, NULL);

515 516 517 518 519 520 521
	/* Validate required reports. */
	for (i = 0; i < 4; i++) {
		if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1))
			return -ENODEV;
	}
	if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2))
		return -ENODEV;
522

523 524 525
	ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_tpkbd);
	if (ret)
		hid_warn(hdev, "Could not create sysfs group: %d\n", ret);
526

527
	data_pointer = devm_kzalloc(&hdev->dev,
528
				    sizeof(struct lenovo_drvdata_tpkbd),
529
				    GFP_KERNEL);
530 531 532 533 534 535 536 537 538
	if (data_pointer == NULL) {
		hid_err(hdev, "Could not allocate memory for driver data\n");
		return -ENOMEM;
	}

	// set same default values as windows driver
	data_pointer->sensitivity = 0xa0;
	data_pointer->press_speed = 0x38;

539 540 541
	name_mute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
	name_micmute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
	if (name_mute == NULL || name_micmute == NULL) {
542
		hid_err(hdev, "Could not allocate memory for led data\n");
543
		return -ENOMEM;
544 545 546 547 548 549 550
	}
	snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev));
	snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev));

	hid_set_drvdata(hdev, data_pointer);

	data_pointer->led_mute.name = name_mute;
551 552
	data_pointer->led_mute.brightness_get = lenovo_led_brightness_get_tpkbd;
	data_pointer->led_mute.brightness_set = lenovo_led_brightness_set_tpkbd;
553 554 555 556
	data_pointer->led_mute.dev = dev;
	led_classdev_register(dev, &data_pointer->led_mute);

	data_pointer->led_micmute.name = name_micmute;
557 558 559 560
	data_pointer->led_micmute.brightness_get =
		lenovo_led_brightness_get_tpkbd;
	data_pointer->led_micmute.brightness_set =
		lenovo_led_brightness_set_tpkbd;
561 562 563
	data_pointer->led_micmute.dev = dev;
	led_classdev_register(dev, &data_pointer->led_micmute);

564
	lenovo_features_set_tpkbd(hdev);
565 566 567 568

	return 0;
}

569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
static int lenovo_probe_cptkbd(struct hid_device *hdev)
{
	int ret;
	struct lenovo_drvdata_cptkbd *cptkbd_data;

	/* All the custom action happens on the USBMOUSE device for USB */
	if (hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD
			&& hdev->type != HID_TYPE_USBMOUSE) {
		hid_dbg(hdev, "Ignoring keyboard half of device\n");
		return 0;
	}

	cptkbd_data = devm_kzalloc(&hdev->dev,
					sizeof(*cptkbd_data),
					GFP_KERNEL);
	if (cptkbd_data == NULL) {
		hid_err(hdev, "can't alloc keyboard descriptor\n");
		return -ENOMEM;
	}
	hid_set_drvdata(hdev, cptkbd_data);

	/*
	 * Tell the keyboard a driver understands it, and turn F7, F9, F11 into
	 * regular keys
	 */
	ret = lenovo_send_cmd_cptkbd(hdev, 0x01, 0x03);
	if (ret)
		hid_warn(hdev, "Failed to switch F7/9/11 mode: %d\n", ret);

	/* Turn Fn-Lock on by default */
	cptkbd_data->fn_lock = true;
	lenovo_features_set_cptkbd(hdev);

	ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_cptkbd);
	if (ret)
		hid_warn(hdev, "Could not create sysfs group: %d\n", ret);

	return 0;
}

609
static int lenovo_probe(struct hid_device *hdev,
610 611 612 613 614 615 616
		const struct hid_device_id *id)
{
	int ret;

	ret = hid_parse(hdev);
	if (ret) {
		hid_err(hdev, "hid_parse failed\n");
617
		goto err;
618 619 620 621 622
	}

	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
	if (ret) {
		hid_err(hdev, "hid_hw_start failed\n");
623
		goto err;
624 625
	}

626 627
	switch (hdev->product) {
	case USB_DEVICE_ID_LENOVO_TPKBD:
628
		ret = lenovo_probe_tpkbd(hdev);
629
		break;
630 631 632 633
	case USB_DEVICE_ID_LENOVO_CUSBKBD:
	case USB_DEVICE_ID_LENOVO_CBTKBD:
		ret = lenovo_probe_cptkbd(hdev);
		break;
634 635 636
	default:
		ret = 0;
		break;
637
	}
638 639
	if (ret)
		goto err_hid;
640 641

	return 0;
642 643 644
err_hid:
	hid_hw_stop(hdev);
err:
645 646 647
	return ret;
}

648
static void lenovo_remove_tpkbd(struct hid_device *hdev)
649
{
650
	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
651

652 653 654 655 656 657 658
	/*
	 * Only the trackpoint half of the keyboard has drvdata and stuff that
	 * needs unregistering.
	 */
	if (data_pointer == NULL)
		return;

659
	sysfs_remove_group(&hdev->dev.kobj,
660
			&lenovo_attr_group_tpkbd);
661 662 663 664 665 666 667

	led_classdev_unregister(&data_pointer->led_micmute);
	led_classdev_unregister(&data_pointer->led_mute);

	hid_set_drvdata(hdev, NULL);
}

668 669 670 671 672 673
static void lenovo_remove_cptkbd(struct hid_device *hdev)
{
	sysfs_remove_group(&hdev->dev.kobj,
			&lenovo_attr_group_cptkbd);
}

674
static void lenovo_remove(struct hid_device *hdev)
675
{
676 677
	switch (hdev->product) {
	case USB_DEVICE_ID_LENOVO_TPKBD:
678
		lenovo_remove_tpkbd(hdev);
679
		break;
680 681 682 683
	case USB_DEVICE_ID_LENOVO_CUSBKBD:
	case USB_DEVICE_ID_LENOVO_CBTKBD:
		lenovo_remove_cptkbd(hdev);
		break;
684
	}
685 686 687 688

	hid_hw_stop(hdev);
}

689
static const struct hid_device_id lenovo_devices[] = {
690
	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
691 692
	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) },
	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) },
693 694 695
	{ }
};

696
MODULE_DEVICE_TABLE(hid, lenovo_devices);
697

698 699 700
static struct hid_driver lenovo_driver = {
	.name = "lenovo",
	.id_table = lenovo_devices,
701
	.input_mapping = lenovo_input_mapping,
702 703
	.probe = lenovo_probe,
	.remove = lenovo_remove,
704
	.raw_event = lenovo_raw_event,
705
};
706
module_hid_driver(lenovo_driver);
707 708

MODULE_LICENSE("GPL");