xref: /openbmc/linux/drivers/hid/hid-google-hammer.c (revision 8ebc80a25f9d9bf7a8e368b266d5b740c485c362)
1  // SPDX-License-Identifier: GPL-2.0+
2  /*
3   *  HID driver for Google Hammer device.
4   *
5   *  Copyright (c) 2017 Google Inc.
6   *  Author: Wei-Ning Huang <wnhuang@google.com>
7   */
8  
9  /*
10   * This program is free software; you can redistribute it and/or modify it
11   * under the terms of the GNU General Public License as published by the Free
12   * Software Foundation; either version 2 of the License, or (at your option)
13   * any later version.
14   */
15  
16  #include <linux/acpi.h>
17  #include <linux/hid.h>
18  #include <linux/input/vivaldi-fmap.h>
19  #include <linux/leds.h>
20  #include <linux/module.h>
21  #include <linux/of.h>
22  #include <linux/platform_data/cros_ec_commands.h>
23  #include <linux/platform_data/cros_ec_proto.h>
24  #include <linux/platform_device.h>
25  #include <linux/pm_wakeup.h>
26  #include <asm/unaligned.h>
27  
28  #include "hid-ids.h"
29  #include "hid-vivaldi-common.h"
30  
31  /*
32   * C(hrome)B(ase)A(ttached)S(witch) - switch exported by Chrome EC and reporting
33   * state of the "Whiskers" base - attached or detached. Whiskers USB device also
34   * reports position of the keyboard - folded or not. Combining base state and
35   * position allows us to generate proper "Tablet mode" events.
36   */
37  struct cbas_ec {
38  	struct device *dev;	/* The platform device (EC) */
39  	struct input_dev *input;
40  	bool base_present;
41  	bool base_folded;
42  	struct notifier_block notifier;
43  };
44  
45  static struct cbas_ec cbas_ec;
46  static DEFINE_SPINLOCK(cbas_ec_lock);
47  static DEFINE_MUTEX(cbas_ec_reglock);
48  
cbas_parse_base_state(const void * data)49  static bool cbas_parse_base_state(const void *data)
50  {
51  	u32 switches = get_unaligned_le32(data);
52  
53  	return !!(switches & BIT(EC_MKBP_BASE_ATTACHED));
54  }
55  
cbas_ec_query_base(struct cros_ec_device * ec_dev,bool get_state,bool * state)56  static int cbas_ec_query_base(struct cros_ec_device *ec_dev, bool get_state,
57  				  bool *state)
58  {
59  	struct ec_params_mkbp_info *params;
60  	struct cros_ec_command *msg;
61  	int ret;
62  
63  	msg = kzalloc(struct_size(msg, data, max(sizeof(u32), sizeof(*params))),
64  		      GFP_KERNEL);
65  	if (!msg)
66  		return -ENOMEM;
67  
68  	msg->command = EC_CMD_MKBP_INFO;
69  	msg->version = 1;
70  	msg->outsize = sizeof(*params);
71  	msg->insize = sizeof(u32);
72  	params = (struct ec_params_mkbp_info *)msg->data;
73  	params->info_type = get_state ?
74  		EC_MKBP_INFO_CURRENT : EC_MKBP_INFO_SUPPORTED;
75  	params->event_type = EC_MKBP_EVENT_SWITCH;
76  
77  	ret = cros_ec_cmd_xfer_status(ec_dev, msg);
78  	if (ret >= 0) {
79  		if (ret != sizeof(u32)) {
80  			dev_warn(ec_dev->dev, "wrong result size: %d != %zu\n",
81  				 ret, sizeof(u32));
82  			ret = -EPROTO;
83  		} else {
84  			*state = cbas_parse_base_state(msg->data);
85  			ret = 0;
86  		}
87  	}
88  
89  	kfree(msg);
90  
91  	return ret;
92  }
93  
cbas_ec_notify(struct notifier_block * nb,unsigned long queued_during_suspend,void * _notify)94  static int cbas_ec_notify(struct notifier_block *nb,
95  			      unsigned long queued_during_suspend,
96  			      void *_notify)
97  {
98  	struct cros_ec_device *ec = _notify;
99  	unsigned long flags;
100  	bool base_present;
101  
102  	if (ec->event_data.event_type == EC_MKBP_EVENT_SWITCH) {
103  		base_present = cbas_parse_base_state(
104  					&ec->event_data.data.switches);
105  		dev_dbg(cbas_ec.dev,
106  			"%s: base: %d\n", __func__, base_present);
107  
108  		if (device_may_wakeup(cbas_ec.dev) ||
109  		    !queued_during_suspend) {
110  
111  			pm_wakeup_event(cbas_ec.dev, 0);
112  
113  			spin_lock_irqsave(&cbas_ec_lock, flags);
114  
115  			/*
116  			 * While input layer dedupes the events, we do not want
117  			 * to disrupt the state reported by the base by
118  			 * overriding it with state reported by the LID. Only
119  			 * report changes, as we assume that on attach the base
120  			 * is not folded.
121  			 */
122  			if (base_present != cbas_ec.base_present) {
123  				input_report_switch(cbas_ec.input,
124  						    SW_TABLET_MODE,
125  						    !base_present);
126  				input_sync(cbas_ec.input);
127  				cbas_ec.base_present = base_present;
128  			}
129  
130  			spin_unlock_irqrestore(&cbas_ec_lock, flags);
131  		}
132  	}
133  
134  	return NOTIFY_OK;
135  }
136  
cbas_ec_resume(struct device * dev)137  static __maybe_unused int cbas_ec_resume(struct device *dev)
138  {
139  	struct cros_ec_device *ec = dev_get_drvdata(dev->parent);
140  	bool base_present;
141  	int error;
142  
143  	error = cbas_ec_query_base(ec, true, &base_present);
144  	if (error) {
145  		dev_warn(dev, "failed to fetch base state on resume: %d\n",
146  			 error);
147  	} else {
148  		spin_lock_irq(&cbas_ec_lock);
149  
150  		cbas_ec.base_present = base_present;
151  
152  		/*
153  		 * Only report if base is disconnected. If base is connected,
154  		 * it will resend its state on resume, and we'll update it
155  		 * in hammer_event().
156  		 */
157  		if (!cbas_ec.base_present) {
158  			input_report_switch(cbas_ec.input, SW_TABLET_MODE, 1);
159  			input_sync(cbas_ec.input);
160  		}
161  
162  		spin_unlock_irq(&cbas_ec_lock);
163  	}
164  
165  	return 0;
166  }
167  
168  static SIMPLE_DEV_PM_OPS(cbas_ec_pm_ops, NULL, cbas_ec_resume);
169  
cbas_ec_set_input(struct input_dev * input)170  static void cbas_ec_set_input(struct input_dev *input)
171  {
172  	/* Take the lock so hammer_event() does not race with us here */
173  	spin_lock_irq(&cbas_ec_lock);
174  	cbas_ec.input = input;
175  	spin_unlock_irq(&cbas_ec_lock);
176  }
177  
__cbas_ec_probe(struct platform_device * pdev)178  static int __cbas_ec_probe(struct platform_device *pdev)
179  {
180  	struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
181  	struct input_dev *input;
182  	bool base_supported;
183  	int error;
184  
185  	error = cbas_ec_query_base(ec, false, &base_supported);
186  	if (error)
187  		return error;
188  
189  	if (!base_supported)
190  		return -ENXIO;
191  
192  	input = devm_input_allocate_device(&pdev->dev);
193  	if (!input)
194  		return -ENOMEM;
195  
196  	input->name = "Whiskers Tablet Mode Switch";
197  	input->id.bustype = BUS_HOST;
198  
199  	input_set_capability(input, EV_SW, SW_TABLET_MODE);
200  
201  	error = input_register_device(input);
202  	if (error) {
203  		dev_err(&pdev->dev, "cannot register input device: %d\n",
204  			error);
205  		return error;
206  	}
207  
208  	/* Seed the state */
209  	error = cbas_ec_query_base(ec, true, &cbas_ec.base_present);
210  	if (error) {
211  		dev_err(&pdev->dev, "cannot query base state: %d\n", error);
212  		return error;
213  	}
214  
215  	if (!cbas_ec.base_present)
216  		cbas_ec.base_folded = false;
217  
218  	dev_dbg(&pdev->dev, "%s: base: %d, folded: %d\n", __func__,
219  		cbas_ec.base_present, cbas_ec.base_folded);
220  
221  	input_report_switch(input, SW_TABLET_MODE,
222  			    !cbas_ec.base_present || cbas_ec.base_folded);
223  
224  	cbas_ec_set_input(input);
225  
226  	cbas_ec.dev = &pdev->dev;
227  	cbas_ec.notifier.notifier_call = cbas_ec_notify;
228  	error = blocking_notifier_chain_register(&ec->event_notifier,
229  						 &cbas_ec.notifier);
230  	if (error) {
231  		dev_err(&pdev->dev, "cannot register notifier: %d\n", error);
232  		cbas_ec_set_input(NULL);
233  		return error;
234  	}
235  
236  	device_init_wakeup(&pdev->dev, true);
237  	return 0;
238  }
239  
cbas_ec_probe(struct platform_device * pdev)240  static int cbas_ec_probe(struct platform_device *pdev)
241  {
242  	int retval;
243  
244  	mutex_lock(&cbas_ec_reglock);
245  
246  	if (cbas_ec.input) {
247  		retval = -EBUSY;
248  		goto out;
249  	}
250  
251  	retval = __cbas_ec_probe(pdev);
252  
253  out:
254  	mutex_unlock(&cbas_ec_reglock);
255  	return retval;
256  }
257  
cbas_ec_remove(struct platform_device * pdev)258  static int cbas_ec_remove(struct platform_device *pdev)
259  {
260  	struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
261  
262  	mutex_lock(&cbas_ec_reglock);
263  
264  	blocking_notifier_chain_unregister(&ec->event_notifier,
265  					   &cbas_ec.notifier);
266  	cbas_ec_set_input(NULL);
267  
268  	mutex_unlock(&cbas_ec_reglock);
269  	return 0;
270  }
271  
272  #ifdef CONFIG_ACPI
273  static const struct acpi_device_id cbas_ec_acpi_ids[] = {
274  	{ "GOOG000B", 0 },
275  	{ }
276  };
277  MODULE_DEVICE_TABLE(acpi, cbas_ec_acpi_ids);
278  #endif
279  
280  #ifdef CONFIG_OF
281  static const struct of_device_id cbas_ec_of_match[] = {
282  	{ .compatible = "google,cros-cbas" },
283  	{ },
284  };
285  MODULE_DEVICE_TABLE(of, cbas_ec_of_match);
286  #endif
287  
288  static struct platform_driver cbas_ec_driver = {
289  	.probe = cbas_ec_probe,
290  	.remove = cbas_ec_remove,
291  	.driver = {
292  		.name = "cbas_ec",
293  		.acpi_match_table = ACPI_PTR(cbas_ec_acpi_ids),
294  		.of_match_table = of_match_ptr(cbas_ec_of_match),
295  		.pm = &cbas_ec_pm_ops,
296  	},
297  };
298  
299  #define MAX_BRIGHTNESS 100
300  
301  struct hammer_kbd_leds {
302  	struct led_classdev cdev;
303  	struct hid_device *hdev;
304  	u8 buf[2] ____cacheline_aligned;
305  };
306  
hammer_kbd_brightness_set_blocking(struct led_classdev * cdev,enum led_brightness br)307  static int hammer_kbd_brightness_set_blocking(struct led_classdev *cdev,
308  		enum led_brightness br)
309  {
310  	struct hammer_kbd_leds *led = container_of(cdev,
311  						   struct hammer_kbd_leds,
312  						   cdev);
313  	int ret;
314  
315  	led->buf[0] = 0;
316  	led->buf[1] = br;
317  
318  	/*
319  	 * Request USB HID device to be in Full On mode, so that sending
320  	 * hardware output report and hardware raw request won't fail.
321  	 */
322  	ret = hid_hw_power(led->hdev, PM_HINT_FULLON);
323  	if (ret < 0) {
324  		hid_err(led->hdev, "failed: device not resumed %d\n", ret);
325  		return ret;
326  	}
327  
328  	ret = hid_hw_output_report(led->hdev, led->buf, sizeof(led->buf));
329  	if (ret == -ENOSYS)
330  		ret = hid_hw_raw_request(led->hdev, 0, led->buf,
331  					 sizeof(led->buf),
332  					 HID_OUTPUT_REPORT,
333  					 HID_REQ_SET_REPORT);
334  	if (ret < 0)
335  		hid_err(led->hdev, "failed to set keyboard backlight: %d\n",
336  			ret);
337  
338  	/* Request USB HID device back to Normal Mode. */
339  	hid_hw_power(led->hdev, PM_HINT_NORMAL);
340  
341  	return ret;
342  }
343  
hammer_register_leds(struct hid_device * hdev)344  static int hammer_register_leds(struct hid_device *hdev)
345  {
346  	struct hammer_kbd_leds *kbd_backlight;
347  
348  	kbd_backlight = devm_kzalloc(&hdev->dev, sizeof(*kbd_backlight),
349  				     GFP_KERNEL);
350  	if (!kbd_backlight)
351  		return -ENOMEM;
352  
353  	kbd_backlight->hdev = hdev;
354  	kbd_backlight->cdev.name = "hammer::kbd_backlight";
355  	kbd_backlight->cdev.max_brightness = MAX_BRIGHTNESS;
356  	kbd_backlight->cdev.brightness_set_blocking =
357  		hammer_kbd_brightness_set_blocking;
358  	kbd_backlight->cdev.flags = LED_HW_PLUGGABLE;
359  
360  	/* Set backlight to 0% initially. */
361  	hammer_kbd_brightness_set_blocking(&kbd_backlight->cdev, 0);
362  
363  	return devm_led_classdev_register(&hdev->dev, &kbd_backlight->cdev);
364  }
365  
366  #define HID_UP_GOOGLEVENDOR	0xffd10000
367  #define HID_VD_KBD_FOLDED	0x00000019
368  #define HID_USAGE_KBD_FOLDED	(HID_UP_GOOGLEVENDOR | HID_VD_KBD_FOLDED)
369  
370  /* HID usage for keyboard backlight (Alphanumeric display brightness) */
371  #define HID_AD_BRIGHTNESS	0x00140046
372  
hammer_input_mapping(struct hid_device * hdev,struct hid_input * hi,struct hid_field * field,struct hid_usage * usage,unsigned long ** bit,int * max)373  static int hammer_input_mapping(struct hid_device *hdev, struct hid_input *hi,
374  				struct hid_field *field,
375  				struct hid_usage *usage,
376  				unsigned long **bit, int *max)
377  {
378  	if (usage->hid == HID_USAGE_KBD_FOLDED) {
379  		/*
380  		 * We do not want to have this usage mapped as it will get
381  		 * mixed in with "base attached" signal and delivered over
382  		 * separate input device for tablet switch mode.
383  		 */
384  		return -1;
385  	}
386  
387  	return 0;
388  }
389  
hammer_folded_event(struct hid_device * hdev,bool folded)390  static void hammer_folded_event(struct hid_device *hdev, bool folded)
391  {
392  	unsigned long flags;
393  
394  	spin_lock_irqsave(&cbas_ec_lock, flags);
395  
396  	/*
397  	 * If we are getting events from Whiskers that means that it
398  	 * is attached to the lid.
399  	 */
400  	cbas_ec.base_present = true;
401  	cbas_ec.base_folded = folded;
402  	hid_dbg(hdev, "%s: base: %d, folded: %d\n", __func__,
403  		cbas_ec.base_present, cbas_ec.base_folded);
404  
405  	if (cbas_ec.input) {
406  		input_report_switch(cbas_ec.input, SW_TABLET_MODE, folded);
407  		input_sync(cbas_ec.input);
408  	}
409  
410  	spin_unlock_irqrestore(&cbas_ec_lock, flags);
411  }
412  
hammer_event(struct hid_device * hid,struct hid_field * field,struct hid_usage * usage,__s32 value)413  static int hammer_event(struct hid_device *hid, struct hid_field *field,
414  			struct hid_usage *usage, __s32 value)
415  {
416  	if (usage->hid == HID_USAGE_KBD_FOLDED) {
417  		hammer_folded_event(hid, value);
418  		return 1; /* We handled this event */
419  	}
420  
421  	return 0;
422  }
423  
hammer_has_usage(struct hid_device * hdev,unsigned int report_type,unsigned application,unsigned usage)424  static bool hammer_has_usage(struct hid_device *hdev, unsigned int report_type,
425  			unsigned application, unsigned usage)
426  {
427  	struct hid_report_enum *re = &hdev->report_enum[report_type];
428  	struct hid_report *report;
429  	int i, j;
430  
431  	list_for_each_entry(report, &re->report_list, list) {
432  		if (report->application != application)
433  			continue;
434  
435  		for (i = 0; i < report->maxfield; i++) {
436  			struct hid_field *field = report->field[i];
437  
438  			for (j = 0; j < field->maxusage; j++)
439  				if (field->usage[j].hid == usage)
440  					return true;
441  		}
442  	}
443  
444  	return false;
445  }
446  
hammer_has_folded_event(struct hid_device * hdev)447  static bool hammer_has_folded_event(struct hid_device *hdev)
448  {
449  	return hammer_has_usage(hdev, HID_INPUT_REPORT,
450  				HID_GD_KEYBOARD, HID_USAGE_KBD_FOLDED);
451  }
452  
hammer_has_backlight_control(struct hid_device * hdev)453  static bool hammer_has_backlight_control(struct hid_device *hdev)
454  {
455  	return hammer_has_usage(hdev, HID_OUTPUT_REPORT,
456  				HID_GD_KEYBOARD, HID_AD_BRIGHTNESS);
457  }
458  
hammer_get_folded_state(struct hid_device * hdev)459  static void hammer_get_folded_state(struct hid_device *hdev)
460  {
461  	struct hid_report *report;
462  	char *buf;
463  	int len, rlen;
464  	int a;
465  
466  	report = hdev->report_enum[HID_INPUT_REPORT].report_id_hash[0x0];
467  
468  	if (!report || report->maxfield < 1)
469  		return;
470  
471  	len = hid_report_len(report) + 1;
472  
473  	buf = kmalloc(len, GFP_KERNEL);
474  	if (!buf)
475  		return;
476  
477  	rlen = hid_hw_raw_request(hdev, report->id, buf, len, report->type, HID_REQ_GET_REPORT);
478  
479  	if (rlen != len) {
480  		hid_warn(hdev, "Unable to read base folded state: %d (expected %d)\n", rlen, len);
481  		goto out;
482  	}
483  
484  	for (a = 0; a < report->maxfield; a++) {
485  		struct hid_field *field = report->field[a];
486  
487  		if (field->usage->hid == HID_USAGE_KBD_FOLDED) {
488  			u32 value = hid_field_extract(hdev, buf+1,
489  					field->report_offset, field->report_size);
490  
491  			hammer_folded_event(hdev, value);
492  			break;
493  		}
494  	}
495  
496  out:
497  	kfree(buf);
498  }
499  
hammer_stop(void * hdev)500  static void hammer_stop(void *hdev)
501  {
502  	hid_hw_stop(hdev);
503  }
504  
hammer_probe(struct hid_device * hdev,const struct hid_device_id * id)505  static int hammer_probe(struct hid_device *hdev,
506  			const struct hid_device_id *id)
507  {
508  	struct vivaldi_data *vdata;
509  	int error;
510  
511  	vdata = devm_kzalloc(&hdev->dev, sizeof(*vdata), GFP_KERNEL);
512  	if (!vdata)
513  		return -ENOMEM;
514  
515  	hid_set_drvdata(hdev, vdata);
516  
517  	error = hid_parse(hdev);
518  	if (error)
519  		return error;
520  
521  	error = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
522  	if (error)
523  		return error;
524  
525  	error = devm_add_action(&hdev->dev, hammer_stop, hdev);
526  	if (error)
527  		return error;
528  
529  	/*
530  	 * We always want to poll for, and handle tablet mode events from
531  	 * devices that have folded usage, even when nobody has opened the input
532  	 * device. This also prevents the hid core from dropping early tablet
533  	 * mode events from the device.
534  	 */
535  	if (hammer_has_folded_event(hdev)) {
536  		hdev->quirks |= HID_QUIRK_ALWAYS_POLL;
537  		error = hid_hw_open(hdev);
538  		if (error)
539  			return error;
540  
541  		hammer_get_folded_state(hdev);
542  	}
543  
544  	if (hammer_has_backlight_control(hdev)) {
545  		error = hammer_register_leds(hdev);
546  		if (error)
547  			hid_warn(hdev,
548  				"Failed to register keyboard backlight: %d\n",
549  				error);
550  	}
551  
552  	return 0;
553  }
554  
hammer_remove(struct hid_device * hdev)555  static void hammer_remove(struct hid_device *hdev)
556  {
557  	unsigned long flags;
558  
559  	if (hammer_has_folded_event(hdev)) {
560  		hid_hw_close(hdev);
561  
562  		/*
563  		 * If we are disconnecting then most likely Whiskers is
564  		 * being removed. Even if it is not removed, without proper
565  		 * keyboard we should not stay in clamshell mode.
566  		 *
567  		 * The reason for doing it here and not waiting for signal
568  		 * from EC, is that on some devices there are high leakage
569  		 * on Whiskers pins and we do not detect disconnect reliably,
570  		 * resulting in devices being stuck in clamshell mode.
571  		 */
572  		spin_lock_irqsave(&cbas_ec_lock, flags);
573  		if (cbas_ec.input && cbas_ec.base_present) {
574  			input_report_switch(cbas_ec.input, SW_TABLET_MODE, 1);
575  			input_sync(cbas_ec.input);
576  		}
577  		cbas_ec.base_present = false;
578  		spin_unlock_irqrestore(&cbas_ec_lock, flags);
579  	}
580  
581  	/* Unregistering LEDs and stopping the hardware is done via devm */
582  }
583  
584  static const struct hid_device_id hammer_devices[] = {
585  	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
586  		     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_DON) },
587  	{ HID_DEVICE(BUS_USB, HID_GROUP_VIVALDI,
588  		     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_EEL) },
589  	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
590  		     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_HAMMER) },
591  	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
592  		     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_JEWEL) },
593  	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
594  		     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MAGNEMITE) },
595  	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
596  		     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MASTERBALL) },
597  	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
598  		     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MOONBALL) },
599  	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
600  		     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_STAFF) },
601  	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
602  		     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_WAND) },
603  	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
604  		     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_WHISKERS) },
605  	{ }
606  };
607  MODULE_DEVICE_TABLE(hid, hammer_devices);
608  
609  static struct hid_driver hammer_driver = {
610  	.name = "hammer",
611  	.id_table = hammer_devices,
612  	.probe = hammer_probe,
613  	.remove = hammer_remove,
614  	.feature_mapping = vivaldi_feature_mapping,
615  	.input_mapping = hammer_input_mapping,
616  	.event = hammer_event,
617  	.driver = {
618  		.dev_groups = vivaldi_attribute_groups,
619  	},
620  };
621  
hammer_init(void)622  static int __init hammer_init(void)
623  {
624  	int error;
625  
626  	error = platform_driver_register(&cbas_ec_driver);
627  	if (error)
628  		return error;
629  
630  	error = hid_register_driver(&hammer_driver);
631  	if (error) {
632  		platform_driver_unregister(&cbas_ec_driver);
633  		return error;
634  	}
635  
636  	return 0;
637  }
638  module_init(hammer_init);
639  
hammer_exit(void)640  static void __exit hammer_exit(void)
641  {
642  	hid_unregister_driver(&hammer_driver);
643  	platform_driver_unregister(&cbas_ec_driver);
644  }
645  module_exit(hammer_exit);
646  
647  MODULE_LICENSE("GPL");
648