aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorsrinivas pandruvada <srinivas.pandruvada@intel.com>2012-09-05 08:56:00 -0400
committerJonathan Cameron <jic23@kernel.org>2012-09-06 14:13:13 -0400
commit401ca24fb34aee0cedf9c4fef361e533224f15a1 (patch)
tree6841fc321a073643ebe8a4f9fd1a8c32fac13c3a /drivers
parentc8147d9ea19bfe7d8e569351bc7239e118dd6997 (diff)
HID: sensors: introduce sensor framework
Adding processing for HID Sensor usage table as defined by HID 1.12, Request #: HUTRR39, dated 05 May, 2011. This driver uses HID driver framework to register, send and receive events. This uses MFD framework, so that actual processing for a specific usage id can be done in a different driver. For example an accelerometer driver can be a separate driver and use the interface provided by this driver to register for events. Signed-off-by: srinivas pandruvada <srinivas.pandruvada@intel.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hid/Kconfig14
-rw-r--r--drivers/hid/Makefile1
-rw-r--r--drivers/hid/hid-sensor-hub.c695
3 files changed, 710 insertions, 0 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index fbf49503508d..f8d314060853 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -690,6 +690,20 @@ config HID_ZYDACRON
690 ---help--- 690 ---help---
691 Support for Zydacron remote control. 691 Support for Zydacron remote control.
692 692
693config HID_SENSOR_HUB
694 tristate "HID Sensors framework support"
695 depends on USB_HID
696 select MFD_CORE
697 default n
698 -- help---
699 Support for HID Sensor framework. This creates a MFD instance
700 for a sensor hub and identifies all the sensors connected to it.
701 Each sensor is registered as a MFD cell, so that sensor specific
702 processing can be done in a separate driver. Each sensor
703 drivers can use the service provided by this driver to register
704 for events and handle data streams. Each sensor driver can format
705 data and present to user mode using input or IIO interface.
706
693endmenu 707endmenu
694 708
695endif # HID 709endif # HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index f975485f88b2..1173d7af20e8 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -91,6 +91,7 @@ obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o
91obj-$(CONFIG_HID_WACOM) += hid-wacom.o 91obj-$(CONFIG_HID_WACOM) += hid-wacom.o
92obj-$(CONFIG_HID_WALTOP) += hid-waltop.o 92obj-$(CONFIG_HID_WALTOP) += hid-waltop.o
93obj-$(CONFIG_HID_WIIMOTE) += hid-wiimote.o 93obj-$(CONFIG_HID_WIIMOTE) += hid-wiimote.o
94obj-$(CONFIG_HID_SENSOR_HUB) += hid-sensor-hub.o
94 95
95obj-$(CONFIG_USB_HID) += usbhid/ 96obj-$(CONFIG_USB_HID) += usbhid/
96obj-$(CONFIG_USB_MOUSE) += usbhid/ 97obj-$(CONFIG_USB_MOUSE) += usbhid/
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
new file mode 100644
index 000000000000..34a35ba95fc1
--- /dev/null
+++ b/drivers/hid/hid-sensor-hub.c
@@ -0,0 +1,695 @@
1/*
2 * HID Sensors Driver
3 * Copyright (c) 2012, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19#include <linux/device.h>
20#include <linux/hid.h>
21#include <linux/usb.h>
22#include "usbhid/usbhid.h"
23#include <linux/module.h>
24#include <linux/slab.h>
25#include <linux/mfd/core.h>
26#include <linux/list.h>
27#include <linux/hid-sensor-ids.h>
28#include <linux/hid-sensor-hub.h>
29#include "hid-ids.h"
30
31/**
32 * struct sensor_hub_pending - Synchronous read pending information
33 * @status: Pending status true/false.
34 * @ready: Completion synchronization data.
35 * @usage_id: Usage id for physical device, E.g. Gyro usage id.
36 * @attr_usage_id: Usage Id of a field, E.g. X-AXIS for a gyro.
37 * @raw_size: Response size for a read request.
38 * @raw_data: Place holder for received response.
39 */
40struct sensor_hub_pending {
41 bool status;
42 struct completion ready;
43 u32 usage_id;
44 u32 attr_usage_id;
45 int raw_size;
46 u8 *raw_data;
47};
48
49/**
50 * struct sensor_hub_data - Hold a instance data for a HID hub device
51 * @hsdev: Stored hid instance for current hub device.
52 * @mutex: Mutex to serialize synchronous request.
53 * @lock: Spin lock to protect pending request structure.
54 * @pending: Holds information of pending sync read request.
55 * @dyn_callback_list: Holds callback function
56 * @dyn_callback_lock: spin lock to protect callback list
57 * @hid_sensor_hub_client_devs: Stores all MFD cells for a hub instance.
58 * @hid_sensor_client_cnt: Number of MFD cells, (no of sensors attached).
59 */
60struct sensor_hub_data {
61 struct hid_sensor_hub_device *hsdev;
62 struct mutex mutex;
63 spinlock_t lock;
64 struct sensor_hub_pending pending;
65 struct list_head dyn_callback_list;
66 spinlock_t dyn_callback_lock;
67 struct mfd_cell *hid_sensor_hub_client_devs;
68 int hid_sensor_client_cnt;
69};
70
71/**
72 * struct hid_sensor_hub_callbacks_list - Stores callback list
73 * @list: list head.
74 * @usage_id: usage id for a physical device.
75 * @usage_callback: Stores registered callback functions.
76 * @priv: Private data for a physical device.
77 */
78struct hid_sensor_hub_callbacks_list {
79 struct list_head list;
80 u32 usage_id;
81 struct hid_sensor_hub_callbacks *usage_callback;
82 void *priv;
83};
84
85static int sensor_hub_check_for_sensor_page(struct hid_device *hdev)
86{
87 int i;
88 int ret = -EINVAL;
89
90 for (i = 0; i < hdev->maxcollection; i++) {
91 struct hid_collection *col = &hdev->collection[i];
92 if (col->type == HID_COLLECTION_PHYSICAL &&
93 (col->usage & HID_USAGE_PAGE) == HID_UP_SENSOR) {
94 ret = 0;
95 break;
96 }
97 }
98
99 return ret;
100}
101
102static struct hid_report *sensor_hub_report(int id, struct hid_device *hdev,
103 int dir)
104{
105 struct hid_report *report;
106
107 list_for_each_entry(report, &hdev->report_enum[dir].report_list, list) {
108 if (report->id == id)
109 return report;
110 }
111 hid_warn(hdev, "No report with id 0x%x found\n", id);
112
113 return NULL;
114}
115
116static int sensor_hub_get_physical_device_count(
117 struct hid_report_enum *report_enum)
118{
119 struct hid_report *report;
120 struct hid_field *field;
121 int cnt = 0;
122
123 list_for_each_entry(report, &report_enum->report_list, list) {
124 field = report->field[0];
125 if (report->maxfield && field &&
126 field->physical)
127 cnt++;
128 }
129
130 return cnt;
131}
132
133static void sensor_hub_fill_attr_info(
134 struct hid_sensor_hub_attribute_info *info,
135 s32 index, s32 report_id, s32 units, s32 unit_expo, s32 size)
136{
137 info->index = index;
138 info->report_id = report_id;
139 info->units = units;
140 info->unit_expo = unit_expo;
141 info->size = size/8;
142}
143
144static struct hid_sensor_hub_callbacks *sensor_hub_get_callback(
145 struct hid_device *hdev,
146 u32 usage_id, void **priv)
147{
148 struct hid_sensor_hub_callbacks_list *callback;
149 struct sensor_hub_data *pdata = hid_get_drvdata(hdev);
150
151 spin_lock(&pdata->dyn_callback_lock);
152 list_for_each_entry(callback, &pdata->dyn_callback_list, list)
153 if (callback->usage_id == usage_id) {
154 *priv = callback->priv;
155 spin_unlock(&pdata->dyn_callback_lock);
156 return callback->usage_callback;
157 }
158 spin_unlock(&pdata->dyn_callback_lock);
159
160 return NULL;
161}
162
163int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev,
164 u32 usage_id,
165 struct hid_sensor_hub_callbacks *usage_callback)
166{
167 struct hid_sensor_hub_callbacks_list *callback;
168 struct sensor_hub_data *pdata = hid_get_drvdata(hsdev->hdev);
169
170 spin_lock(&pdata->dyn_callback_lock);
171 list_for_each_entry(callback, &pdata->dyn_callback_list, list)
172 if (callback->usage_id == usage_id) {
173 spin_unlock(&pdata->dyn_callback_lock);
174 return -EINVAL;
175 }
176 callback = kzalloc(sizeof(*callback), GFP_KERNEL);
177 if (!callback) {
178 spin_unlock(&pdata->dyn_callback_lock);
179 return -ENOMEM;
180 }
181 callback->usage_callback = usage_callback;
182 callback->usage_id = usage_id;
183 callback->priv = NULL;
184 list_add_tail(&callback->list, &pdata->dyn_callback_list);
185 spin_unlock(&pdata->dyn_callback_lock);
186
187 return 0;
188}
189EXPORT_SYMBOL_GPL(sensor_hub_register_callback);
190
191int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev,
192 u32 usage_id)
193{
194 struct hid_sensor_hub_callbacks_list *callback;
195 struct sensor_hub_data *pdata = hid_get_drvdata(hsdev->hdev);
196
197 spin_lock(&pdata->dyn_callback_lock);
198 list_for_each_entry(callback, &pdata->dyn_callback_list, list)
199 if (callback->usage_id == usage_id) {
200 list_del(&callback->list);
201 kfree(callback);
202 break;
203 }
204 spin_unlock(&pdata->dyn_callback_lock);
205
206 return 0;
207}
208EXPORT_SYMBOL_GPL(sensor_hub_remove_callback);
209
210int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
211 u32 field_index, s32 value)
212{
213 struct hid_report *report;
214 struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
215 int ret = 0;
216
217 if (report_id < 0)
218 return -EINVAL;
219
220 mutex_lock(&data->mutex);
221 report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT);
222 if (!report || (field_index >= report->maxfield)) {
223 ret = -EINVAL;
224 goto done_proc;
225 }
226 hid_set_field(report->field[field_index], 0, value);
227 usbhid_submit_report(hsdev->hdev, report, USB_DIR_OUT);
228 usbhid_wait_io(hsdev->hdev);
229
230done_proc:
231 mutex_unlock(&data->mutex);
232
233 return ret;
234}
235EXPORT_SYMBOL_GPL(sensor_hub_set_feature);
236
237int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
238 u32 field_index, s32 *value)
239{
240 struct hid_report *report;
241 struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
242 int ret = 0;
243
244 if (report_id < 0)
245 return -EINVAL;
246
247 mutex_lock(&data->mutex);
248 report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT);
249 if (!report || (field_index >= report->maxfield)) {
250 ret = -EINVAL;
251 goto done_proc;
252 }
253 usbhid_submit_report(hsdev->hdev, report, USB_DIR_IN);
254 usbhid_wait_io(hsdev->hdev);
255 *value = report->field[field_index]->value[0];
256
257done_proc:
258 mutex_unlock(&data->mutex);
259
260 return ret;
261}
262EXPORT_SYMBOL_GPL(sensor_hub_get_feature);
263
264
265int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
266 u32 usage_id,
267 u32 attr_usage_id, u32 report_id)
268{
269 struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
270 unsigned long flags;
271 struct hid_report *report;
272 int ret_val = 0;
273
274 if (report_id < 0)
275 return -EINVAL;
276
277 mutex_lock(&data->mutex);
278 memset(&data->pending, 0, sizeof(data->pending));
279 init_completion(&data->pending.ready);
280 data->pending.usage_id = usage_id;
281 data->pending.attr_usage_id = attr_usage_id;
282 data->pending.raw_size = 0;
283
284 spin_lock_irqsave(&data->lock, flags);
285 data->pending.status = true;
286 report = sensor_hub_report(report_id, hsdev->hdev, HID_INPUT_REPORT);
287 if (!report) {
288 spin_unlock_irqrestore(&data->lock, flags);
289 goto err_free;
290 }
291 usbhid_submit_report(hsdev->hdev, report, USB_DIR_IN);
292 spin_unlock_irqrestore(&data->lock, flags);
293 wait_for_completion_interruptible_timeout(&data->pending.ready, HZ*5);
294 switch (data->pending.raw_size) {
295 case 1:
296 ret_val = *(u8 *)data->pending.raw_data;
297 break;
298 case 2:
299 ret_val = *(u16 *)data->pending.raw_data;
300 break;
301 case 4:
302 ret_val = *(u32 *)data->pending.raw_data;
303 break;
304 default:
305 ret_val = 0;
306 }
307 kfree(data->pending.raw_data);
308
309err_free:
310 data->pending.status = false;
311 mutex_unlock(&data->mutex);
312
313 return ret_val;
314}
315EXPORT_SYMBOL_GPL(sensor_hub_input_attr_get_raw_value);
316
317int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
318 u8 type,
319 u32 usage_id,
320 u32 attr_usage_id,
321 struct hid_sensor_hub_attribute_info *info)
322{
323 int ret = -1;
324 int i, j;
325 int collection_index = -1;
326 struct hid_report *report;
327 struct hid_field *field;
328 struct hid_report_enum *report_enum;
329 struct hid_device *hdev = hsdev->hdev;
330
331 /* Initialize with defaults */
332 info->usage_id = usage_id;
333 info->attrib_id = attr_usage_id;
334 info->report_id = -1;
335 info->index = -1;
336 info->units = -1;
337 info->unit_expo = -1;
338
339 for (i = 0; i < hdev->maxcollection; ++i) {
340 struct hid_collection *collection = &hdev->collection[i];
341 if (usage_id == collection->usage) {
342 collection_index = i;
343 break;
344 }
345 }
346 if (collection_index == -1)
347 goto err_ret;
348
349 report_enum = &hdev->report_enum[type];
350 list_for_each_entry(report, &report_enum->report_list, list) {
351 for (i = 0; i < report->maxfield; ++i) {
352 field = report->field[i];
353 if (field->physical == usage_id &&
354 field->logical == attr_usage_id) {
355 sensor_hub_fill_attr_info(info, i, report->id,
356 field->unit, field->unit_exponent,
357 field->report_size);
358 ret = 0;
359 } else {
360 for (j = 0; j < field->maxusage; ++j) {
361 if (field->usage[j].hid ==
362 attr_usage_id &&
363 field->usage[j].collection_index ==
364 collection_index) {
365 sensor_hub_fill_attr_info(info,
366 i, report->id,
367 field->unit,
368 field->unit_exponent,
369 field->report_size);
370 ret = 0;
371 break;
372 }
373 }
374 }
375 if (ret == 0)
376 break;
377 }
378 }
379
380err_ret:
381 return ret;
382}
383EXPORT_SYMBOL_GPL(sensor_hub_input_get_attribute_info);
384
385#ifdef CONFIG_PM
386static int sensor_hub_suspend(struct hid_device *hdev, pm_message_t message)
387{
388 struct sensor_hub_data *pdata = hid_get_drvdata(hdev);
389 struct hid_sensor_hub_callbacks_list *callback;
390
391 hid_dbg(hdev, " sensor_hub_suspend\n");
392 spin_lock(&pdata->dyn_callback_lock);
393 list_for_each_entry(callback, &pdata->dyn_callback_list, list) {
394 if (callback->usage_callback->suspend)
395 callback->usage_callback->suspend(
396 pdata->hsdev, callback->priv);
397 }
398 spin_unlock(&pdata->dyn_callback_lock);
399
400 return 0;
401}
402
403static int sensor_hub_resume(struct hid_device *hdev)
404{
405 struct sensor_hub_data *pdata = hid_get_drvdata(hdev);
406 struct hid_sensor_hub_callbacks_list *callback;
407
408 hid_dbg(hdev, " sensor_hub_resume\n");
409 spin_lock(&pdata->dyn_callback_lock);
410 list_for_each_entry(callback, &pdata->dyn_callback_list, list) {
411 if (callback->usage_callback->resume)
412 callback->usage_callback->resume(
413 pdata->hsdev, callback->priv);
414 }
415 spin_unlock(&pdata->dyn_callback_lock);
416
417 return 0;
418}
419
420static int sensor_hub_reset_resume(struct hid_device *hdev)
421{
422 return 0;
423}
424#endif
425/*
426 * Handle raw report as sent by device
427 */
428static int sensor_hub_raw_event(struct hid_device *hdev,
429 struct hid_report *report, u8 *raw_data, int size)
430{
431 int i;
432 u8 *ptr;
433 int sz;
434 struct sensor_hub_data *pdata = hid_get_drvdata(hdev);
435 unsigned long flags;
436 struct hid_sensor_hub_callbacks *callback = NULL;
437 struct hid_collection *collection = NULL;
438 void *priv = NULL;
439
440 hid_dbg(hdev, "sensor_hub_raw_event report id:0x%x size:%d type:%d\n",
441 report->id, size, report->type);
442 hid_dbg(hdev, "maxfield:%d\n", report->maxfield);
443 if (report->type != HID_INPUT_REPORT)
444 return 1;
445
446 ptr = raw_data;
447 ptr++; /*Skip report id*/
448
449 if (!report)
450 goto err_report;
451
452 spin_lock_irqsave(&pdata->lock, flags);
453
454 for (i = 0; i < report->maxfield; ++i) {
455
456 hid_dbg(hdev, "%d collection_index:%x hid:%x sz:%x\n",
457 i, report->field[i]->usage->collection_index,
458 report->field[i]->usage->hid,
459 report->field[i]->report_size/8);
460
461 sz = report->field[i]->report_size/8;
462 if (pdata->pending.status && pdata->pending.attr_usage_id ==
463 report->field[i]->usage->hid) {
464 hid_dbg(hdev, "data was pending ...\n");
465 pdata->pending.raw_data = kmalloc(sz, GFP_KERNEL);
466 if (pdata->pending.raw_data) {
467 memcpy(pdata->pending.raw_data, ptr, sz);
468 pdata->pending.raw_size = sz;
469 } else
470 pdata->pending.raw_size = 0;
471 complete(&pdata->pending.ready);
472 }
473 collection = &hdev->collection[
474 report->field[i]->usage->collection_index];
475 hid_dbg(hdev, "collection->usage %x\n",
476 collection->usage);
477 callback = sensor_hub_get_callback(pdata->hsdev->hdev,
478 report->field[i]->physical,
479 &priv);
480 if (callback && callback->capture_sample) {
481 if (report->field[i]->logical)
482 callback->capture_sample(pdata->hsdev,
483 report->field[i]->logical, sz, ptr,
484 callback->pdev);
485 else
486 callback->capture_sample(pdata->hsdev,
487 report->field[i]->usage->hid, sz, ptr,
488 callback->pdev);
489 }
490 ptr += sz;
491 }
492 if (callback && collection && callback->send_event)
493 callback->send_event(pdata->hsdev, collection->usage,
494 callback->pdev);
495 spin_unlock_irqrestore(&pdata->lock, flags);
496
497err_report:
498 return 1;
499}
500
501static int sensor_hub_probe(struct hid_device *hdev,
502 const struct hid_device_id *id)
503{
504 int ret;
505 struct sensor_hub_data *sd;
506 int i;
507 char *name;
508 struct hid_report *report;
509 struct hid_report_enum *report_enum;
510 struct hid_field *field;
511 int dev_cnt;
512
513 sd = kzalloc(sizeof(struct sensor_hub_data), GFP_KERNEL);
514 if (!sd) {
515 hid_err(hdev, "cannot allocate Sensor data\n");
516 return -ENOMEM;
517 }
518 sd->hsdev = kzalloc(sizeof(struct hid_sensor_hub_device), GFP_KERNEL);
519 if (!sd->hsdev) {
520 hid_err(hdev, "cannot allocate hid_sensor_hub_device\n");
521 ret = -ENOMEM;
522 goto err_free_hub;
523 }
524 hid_set_drvdata(hdev, sd);
525 sd->hsdev->hdev = hdev;
526 sd->hsdev->vendor_id = hdev->vendor;
527 sd->hsdev->product_id = hdev->product;
528 spin_lock_init(&sd->lock);
529 spin_lock_init(&sd->dyn_callback_lock);
530 mutex_init(&sd->mutex);
531 ret = hid_parse(hdev);
532 if (ret) {
533 hid_err(hdev, "parse failed\n");
534 goto err_free;
535 }
536 if (sensor_hub_check_for_sensor_page(hdev) < 0) {
537 hid_err(hdev, "sensor page not found\n");
538 goto err_free;
539 }
540 INIT_LIST_HEAD(&hdev->inputs);
541
542 hdev->claimed = HID_CLAIMED_INPUT;
543 ret = hid_hw_start(hdev, 0);
544 if (ret) {
545 hid_err(hdev, "hw start failed\n");
546 goto err_free;
547 }
548 ret = hid_hw_open(hdev);
549 if (ret) {
550 hid_err(hdev, "failed to open input interrupt pipe\n");
551 goto err_stop_hw;
552 }
553
554 INIT_LIST_HEAD(&sd->dyn_callback_list);
555 sd->hid_sensor_client_cnt = 0;
556 report_enum = &hdev->report_enum[HID_INPUT_REPORT];
557
558 dev_cnt = sensor_hub_get_physical_device_count(report_enum);
559 if (dev_cnt > HID_MAX_PHY_DEVICES) {
560 hid_err(hdev, "Invalid Physical device count\n");
561 ret = -EINVAL;
562 goto err_close;
563 }
564 sd->hid_sensor_hub_client_devs = kzalloc(dev_cnt *
565 sizeof(struct mfd_cell),
566 GFP_KERNEL);
567 if (sd->hid_sensor_hub_client_devs == NULL) {
568 hid_err(hdev,
569 "Failed to allocate memory for mfd cells\n");
570 ret = -ENOMEM;
571 goto err_close;
572 }
573 list_for_each_entry(report, &report_enum->report_list, list) {
574 hid_dbg(hdev, "Report id:%x\n", report->id);
575 field = report->field[0];
576 if (report->maxfield && field &&
577 field->physical) {
578 name = kasprintf(GFP_KERNEL, "HID-SENSOR-%x",
579 field->physical);
580 if (name == NULL) {
581 hid_err(hdev,
582 "Failed MFD device name\n");
583 ret = -ENOMEM;
584 goto err_free_cells;
585 }
586 sd->hid_sensor_hub_client_devs[
587 sd->hid_sensor_client_cnt].name = name;
588 sd->hid_sensor_hub_client_devs[
589 sd->hid_sensor_client_cnt].platform_data =
590 sd->hsdev;
591 sd->hid_sensor_hub_client_devs[
592 sd->hid_sensor_client_cnt].pdata_size =
593 sizeof(*sd->hsdev);
594 hid_dbg(hdev, "Adding %s:%p\n", name, sd);
595 sd->hid_sensor_client_cnt++;
596 }
597 }
598 ret = mfd_add_devices(&hdev->dev, 0, sd->hid_sensor_hub_client_devs,
599 sd->hid_sensor_client_cnt, NULL, 0);
600 if (ret < 0)
601 goto err_free_names;
602
603 return ret;
604
605err_free_names:
606 for (i = 0; i < sd->hid_sensor_client_cnt ; ++i)
607 kfree(sd->hid_sensor_hub_client_devs[i].name);
608err_free_cells:
609 kfree(sd->hid_sensor_hub_client_devs);
610err_close:
611 hid_hw_stop(hdev);
612 hid_hw_close(hdev);
613err_stop_hw:
614 hid_hw_stop(hdev);
615err_free:
616 kfree(sd->hsdev);
617err_free_hub:
618 kfree(sd);
619
620 return ret;
621}
622
623static void sensor_hub_remove(struct hid_device *hdev)
624{
625 struct sensor_hub_data *data = hid_get_drvdata(hdev);
626 unsigned long flags;
627 int i;
628
629 hid_dbg(hdev, " hardware removed\n");
630 hdev->claimed &= ~HID_CLAIMED_INPUT;
631 hid_hw_stop(hdev);
632 hid_hw_close(hdev);
633 spin_lock_irqsave(&data->lock, flags);
634 if (data->pending.status)
635 complete(&data->pending.ready);
636 spin_unlock_irqrestore(&data->lock, flags);
637 mfd_remove_devices(&hdev->dev);
638 for (i = 0; i < data->hid_sensor_client_cnt ; ++i)
639 kfree(data->hid_sensor_hub_client_devs[i].name);
640 kfree(data->hid_sensor_hub_client_devs);
641 hid_set_drvdata(hdev, NULL);
642 mutex_destroy(&data->mutex);
643 kfree(data->hsdev);
644 kfree(data);
645}
646
647static const struct hid_device_id sensor_hub_devices[] = {
648 { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086,
649 USB_DEVICE_ID_SENSOR_HUB_1020) },
650 { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087,
651 USB_DEVICE_ID_SENSOR_HUB_1020) },
652 { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086,
653 USB_DEVICE_ID_SENSOR_HUB_09FA) },
654 { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087,
655 USB_DEVICE_ID_SENSOR_HUB_09FA) },
656 { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
657 USB_DEVICE_ID_SENSOR_HUB_7014) },
658 { }
659};
660MODULE_DEVICE_TABLE(hid, sensor_hub_devices);
661
662static const struct hid_usage_id sensor_hub_grabbed_usages[] = {
663 { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
664 { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1 }
665};
666
667static struct hid_driver sensor_hub_driver = {
668 .name = "hid-sensor-hub",
669 .id_table = sensor_hub_devices,
670 .probe = sensor_hub_probe,
671 .remove = sensor_hub_remove,
672 .raw_event = sensor_hub_raw_event,
673#ifdef CONFIG_PM
674 .suspend = sensor_hub_suspend,
675 .resume = sensor_hub_resume,
676 .reset_resume = sensor_hub_reset_resume,
677#endif
678};
679
680static int __init sensor_hub_init(void)
681{
682 return hid_register_driver(&sensor_hub_driver);
683}
684
685static void __exit sensor_hub_exit(void)
686{
687 hid_unregister_driver(&sensor_hub_driver);
688}
689
690module_init(sensor_hub_init);
691module_exit(sensor_hub_exit);
692
693MODULE_DESCRIPTION("HID Sensor Hub driver");
694MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
695MODULE_LICENSE("GPL");