diff options
author | Jiri Kosina <jkosina@suse.cz> | 2014-04-01 13:05:30 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2014-04-01 13:05:30 -0400 |
commit | ded75664d1a7d74c1976da0969ddb31ad9839d4c (patch) | |
tree | 9a33e95fae5518df8a60231066ffa1b115853921 /drivers/hid/hid-sensor-hub.c | |
parent | ad295b6d5739ab24880a31be403bbc8fab62e177 (diff) | |
parent | ca2ed12f163bf430a425ec725ef76df5254b9f45 (diff) |
Merge branch 'for-3.15/hid-sensor-hub' into for-linus
Diffstat (limited to 'drivers/hid/hid-sensor-hub.c')
-rw-r--r-- | drivers/hid/hid-sensor-hub.c | 210 |
1 files changed, 124 insertions, 86 deletions
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 9021c9ce8851..5182031f7b52 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c | |||
@@ -56,9 +56,9 @@ struct sensor_hub_pending { | |||
56 | * @dyn_callback_lock: spin lock to protect callback list | 56 | * @dyn_callback_lock: spin lock to protect callback list |
57 | * @hid_sensor_hub_client_devs: Stores all MFD cells for a hub instance. | 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). | 58 | * @hid_sensor_client_cnt: Number of MFD cells, (no of sensors attached). |
59 | * @ref_cnt: Number of MFD clients have opened this device | ||
59 | */ | 60 | */ |
60 | struct sensor_hub_data { | 61 | struct sensor_hub_data { |
61 | struct hid_sensor_hub_device *hsdev; | ||
62 | struct mutex mutex; | 62 | struct mutex mutex; |
63 | spinlock_t lock; | 63 | spinlock_t lock; |
64 | struct sensor_hub_pending pending; | 64 | struct sensor_hub_pending pending; |
@@ -67,6 +67,7 @@ struct sensor_hub_data { | |||
67 | struct mfd_cell *hid_sensor_hub_client_devs; | 67 | struct mfd_cell *hid_sensor_hub_client_devs; |
68 | int hid_sensor_client_cnt; | 68 | int hid_sensor_client_cnt; |
69 | unsigned long quirks; | 69 | unsigned long quirks; |
70 | int ref_cnt; | ||
70 | }; | 71 | }; |
71 | 72 | ||
72 | /** | 73 | /** |
@@ -79,6 +80,7 @@ struct sensor_hub_data { | |||
79 | struct hid_sensor_hub_callbacks_list { | 80 | struct hid_sensor_hub_callbacks_list { |
80 | struct list_head list; | 81 | struct list_head list; |
81 | u32 usage_id; | 82 | u32 usage_id; |
83 | struct hid_sensor_hub_device *hsdev; | ||
82 | struct hid_sensor_hub_callbacks *usage_callback; | 84 | struct hid_sensor_hub_callbacks *usage_callback; |
83 | void *priv; | 85 | void *priv; |
84 | }; | 86 | }; |
@@ -97,20 +99,18 @@ static struct hid_report *sensor_hub_report(int id, struct hid_device *hdev, | |||
97 | return NULL; | 99 | return NULL; |
98 | } | 100 | } |
99 | 101 | ||
100 | static int sensor_hub_get_physical_device_count( | 102 | static int sensor_hub_get_physical_device_count(struct hid_device *hdev) |
101 | struct hid_report_enum *report_enum) | ||
102 | { | 103 | { |
103 | struct hid_report *report; | 104 | int i; |
104 | struct hid_field *field; | 105 | int count = 0; |
105 | int cnt = 0; | ||
106 | 106 | ||
107 | list_for_each_entry(report, &report_enum->report_list, list) { | 107 | for (i = 0; i < hdev->maxcollection; ++i) { |
108 | field = report->field[0]; | 108 | struct hid_collection *collection = &hdev->collection[i]; |
109 | if (report->maxfield && field && field->physical) | 109 | if (collection->type == HID_COLLECTION_PHYSICAL) |
110 | cnt++; | 110 | ++count; |
111 | } | 111 | } |
112 | 112 | ||
113 | return cnt; | 113 | return count; |
114 | } | 114 | } |
115 | 115 | ||
116 | static void sensor_hub_fill_attr_info( | 116 | static void sensor_hub_fill_attr_info( |
@@ -128,15 +128,23 @@ static void sensor_hub_fill_attr_info( | |||
128 | 128 | ||
129 | static struct hid_sensor_hub_callbacks *sensor_hub_get_callback( | 129 | static struct hid_sensor_hub_callbacks *sensor_hub_get_callback( |
130 | struct hid_device *hdev, | 130 | struct hid_device *hdev, |
131 | u32 usage_id, void **priv) | 131 | u32 usage_id, |
132 | int collection_index, | ||
133 | struct hid_sensor_hub_device **hsdev, | ||
134 | void **priv) | ||
132 | { | 135 | { |
133 | struct hid_sensor_hub_callbacks_list *callback; | 136 | struct hid_sensor_hub_callbacks_list *callback; |
134 | struct sensor_hub_data *pdata = hid_get_drvdata(hdev); | 137 | struct sensor_hub_data *pdata = hid_get_drvdata(hdev); |
135 | 138 | ||
136 | spin_lock(&pdata->dyn_callback_lock); | 139 | spin_lock(&pdata->dyn_callback_lock); |
137 | list_for_each_entry(callback, &pdata->dyn_callback_list, list) | 140 | list_for_each_entry(callback, &pdata->dyn_callback_list, list) |
138 | if (callback->usage_id == usage_id) { | 141 | if (callback->usage_id == usage_id && |
142 | (collection_index >= | ||
143 | callback->hsdev->start_collection_index) && | ||
144 | (collection_index < | ||
145 | callback->hsdev->end_collection_index)) { | ||
139 | *priv = callback->priv; | 146 | *priv = callback->priv; |
147 | *hsdev = callback->hsdev; | ||
140 | spin_unlock(&pdata->dyn_callback_lock); | 148 | spin_unlock(&pdata->dyn_callback_lock); |
141 | return callback->usage_callback; | 149 | return callback->usage_callback; |
142 | } | 150 | } |
@@ -154,7 +162,8 @@ int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev, | |||
154 | 162 | ||
155 | spin_lock(&pdata->dyn_callback_lock); | 163 | spin_lock(&pdata->dyn_callback_lock); |
156 | list_for_each_entry(callback, &pdata->dyn_callback_list, list) | 164 | list_for_each_entry(callback, &pdata->dyn_callback_list, list) |
157 | if (callback->usage_id == usage_id) { | 165 | if (callback->usage_id == usage_id && |
166 | callback->hsdev == hsdev) { | ||
158 | spin_unlock(&pdata->dyn_callback_lock); | 167 | spin_unlock(&pdata->dyn_callback_lock); |
159 | return -EINVAL; | 168 | return -EINVAL; |
160 | } | 169 | } |
@@ -163,6 +172,7 @@ int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev, | |||
163 | spin_unlock(&pdata->dyn_callback_lock); | 172 | spin_unlock(&pdata->dyn_callback_lock); |
164 | return -ENOMEM; | 173 | return -ENOMEM; |
165 | } | 174 | } |
175 | callback->hsdev = hsdev; | ||
166 | callback->usage_callback = usage_callback; | 176 | callback->usage_callback = usage_callback; |
167 | callback->usage_id = usage_id; | 177 | callback->usage_id = usage_id; |
168 | callback->priv = NULL; | 178 | callback->priv = NULL; |
@@ -181,7 +191,8 @@ int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev, | |||
181 | 191 | ||
182 | spin_lock(&pdata->dyn_callback_lock); | 192 | spin_lock(&pdata->dyn_callback_lock); |
183 | list_for_each_entry(callback, &pdata->dyn_callback_list, list) | 193 | list_for_each_entry(callback, &pdata->dyn_callback_list, list) |
184 | if (callback->usage_id == usage_id) { | 194 | if (callback->usage_id == usage_id && |
195 | callback->hsdev == hsdev) { | ||
185 | list_del(&callback->list); | 196 | list_del(&callback->list); |
186 | kfree(callback); | 197 | kfree(callback); |
187 | break; | 198 | break; |
@@ -290,6 +301,28 @@ err_free: | |||
290 | } | 301 | } |
291 | EXPORT_SYMBOL_GPL(sensor_hub_input_attr_get_raw_value); | 302 | EXPORT_SYMBOL_GPL(sensor_hub_input_attr_get_raw_value); |
292 | 303 | ||
304 | int hid_sensor_get_usage_index(struct hid_sensor_hub_device *hsdev, | ||
305 | u32 report_id, int field_index, u32 usage_id) | ||
306 | { | ||
307 | struct hid_report *report; | ||
308 | struct hid_field *field; | ||
309 | int i; | ||
310 | |||
311 | report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT); | ||
312 | if (!report || (field_index >= report->maxfield)) | ||
313 | goto done_proc; | ||
314 | |||
315 | field = report->field[field_index]; | ||
316 | for (i = 0; i < field->maxusage; ++i) { | ||
317 | if (field->usage[i].hid == usage_id) | ||
318 | return field->usage[i].usage_index; | ||
319 | } | ||
320 | |||
321 | done_proc: | ||
322 | return -EINVAL; | ||
323 | } | ||
324 | EXPORT_SYMBOL_GPL(hid_sensor_get_usage_index); | ||
325 | |||
293 | int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev, | 326 | int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev, |
294 | u8 type, | 327 | u8 type, |
295 | u32 usage_id, | 328 | u32 usage_id, |
@@ -297,8 +330,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev, | |||
297 | struct hid_sensor_hub_attribute_info *info) | 330 | struct hid_sensor_hub_attribute_info *info) |
298 | { | 331 | { |
299 | int ret = -1; | 332 | int ret = -1; |
300 | int i, j; | 333 | int i; |
301 | int collection_index = -1; | ||
302 | struct hid_report *report; | 334 | struct hid_report *report; |
303 | struct hid_field *field; | 335 | struct hid_field *field; |
304 | struct hid_report_enum *report_enum; | 336 | struct hid_report_enum *report_enum; |
@@ -312,44 +344,31 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev, | |||
312 | info->units = -1; | 344 | info->units = -1; |
313 | info->unit_expo = -1; | 345 | info->unit_expo = -1; |
314 | 346 | ||
315 | for (i = 0; i < hdev->maxcollection; ++i) { | ||
316 | struct hid_collection *collection = &hdev->collection[i]; | ||
317 | if (usage_id == collection->usage) { | ||
318 | collection_index = i; | ||
319 | break; | ||
320 | } | ||
321 | } | ||
322 | if (collection_index == -1) | ||
323 | goto err_ret; | ||
324 | |||
325 | report_enum = &hdev->report_enum[type]; | 347 | report_enum = &hdev->report_enum[type]; |
326 | list_for_each_entry(report, &report_enum->report_list, list) { | 348 | list_for_each_entry(report, &report_enum->report_list, list) { |
327 | for (i = 0; i < report->maxfield; ++i) { | 349 | for (i = 0; i < report->maxfield; ++i) { |
328 | field = report->field[i]; | 350 | field = report->field[i]; |
329 | if (field->physical == usage_id && | 351 | if (field->maxusage) { |
330 | field->logical == attr_usage_id) { | 352 | if (field->physical == usage_id && |
331 | sensor_hub_fill_attr_info(info, i, report->id, | 353 | (field->logical == attr_usage_id || |
332 | field); | 354 | field->usage[0].hid == |
333 | ret = 0; | 355 | attr_usage_id) && |
334 | } else { | 356 | (field->usage[0].collection_index >= |
335 | for (j = 0; j < field->maxusage; ++j) { | 357 | hsdev->start_collection_index) && |
336 | if (field->usage[j].hid == | 358 | (field->usage[0].collection_index < |
337 | attr_usage_id && | 359 | hsdev->end_collection_index)) { |
338 | field->usage[j].collection_index == | 360 | |
339 | collection_index) { | 361 | sensor_hub_fill_attr_info(info, i, |
340 | sensor_hub_fill_attr_info(info, | 362 | report->id, |
341 | i, report->id, field); | 363 | field); |
342 | ret = 0; | 364 | ret = 0; |
343 | break; | 365 | break; |
344 | } | ||
345 | } | 366 | } |
346 | } | 367 | } |
347 | if (ret == 0) | ||
348 | break; | ||
349 | } | 368 | } |
369 | |||
350 | } | 370 | } |
351 | 371 | ||
352 | err_ret: | ||
353 | return ret; | 372 | return ret; |
354 | } | 373 | } |
355 | EXPORT_SYMBOL_GPL(sensor_hub_input_get_attribute_info); | 374 | EXPORT_SYMBOL_GPL(sensor_hub_input_get_attribute_info); |
@@ -365,7 +384,7 @@ static int sensor_hub_suspend(struct hid_device *hdev, pm_message_t message) | |||
365 | list_for_each_entry(callback, &pdata->dyn_callback_list, list) { | 384 | list_for_each_entry(callback, &pdata->dyn_callback_list, list) { |
366 | if (callback->usage_callback->suspend) | 385 | if (callback->usage_callback->suspend) |
367 | callback->usage_callback->suspend( | 386 | callback->usage_callback->suspend( |
368 | pdata->hsdev, callback->priv); | 387 | callback->hsdev, callback->priv); |
369 | } | 388 | } |
370 | spin_unlock(&pdata->dyn_callback_lock); | 389 | spin_unlock(&pdata->dyn_callback_lock); |
371 | 390 | ||
@@ -382,7 +401,7 @@ static int sensor_hub_resume(struct hid_device *hdev) | |||
382 | list_for_each_entry(callback, &pdata->dyn_callback_list, list) { | 401 | list_for_each_entry(callback, &pdata->dyn_callback_list, list) { |
383 | if (callback->usage_callback->resume) | 402 | if (callback->usage_callback->resume) |
384 | callback->usage_callback->resume( | 403 | callback->usage_callback->resume( |
385 | pdata->hsdev, callback->priv); | 404 | callback->hsdev, callback->priv); |
386 | } | 405 | } |
387 | spin_unlock(&pdata->dyn_callback_lock); | 406 | spin_unlock(&pdata->dyn_callback_lock); |
388 | 407 | ||
@@ -409,6 +428,7 @@ static int sensor_hub_raw_event(struct hid_device *hdev, | |||
409 | struct hid_sensor_hub_callbacks *callback = NULL; | 428 | struct hid_sensor_hub_callbacks *callback = NULL; |
410 | struct hid_collection *collection = NULL; | 429 | struct hid_collection *collection = NULL; |
411 | void *priv = NULL; | 430 | void *priv = NULL; |
431 | struct hid_sensor_hub_device *hsdev = NULL; | ||
412 | 432 | ||
413 | hid_dbg(hdev, "sensor_hub_raw_event report id:0x%x size:%d type:%d\n", | 433 | hid_dbg(hdev, "sensor_hub_raw_event report id:0x%x size:%d type:%d\n", |
414 | report->id, size, report->type); | 434 | report->id, size, report->type); |
@@ -443,23 +463,26 @@ static int sensor_hub_raw_event(struct hid_device *hdev, | |||
443 | report->field[i]->usage->collection_index]; | 463 | report->field[i]->usage->collection_index]; |
444 | hid_dbg(hdev, "collection->usage %x\n", | 464 | hid_dbg(hdev, "collection->usage %x\n", |
445 | collection->usage); | 465 | collection->usage); |
446 | callback = sensor_hub_get_callback(pdata->hsdev->hdev, | 466 | |
447 | report->field[i]->physical, | 467 | callback = sensor_hub_get_callback(hdev, |
448 | &priv); | 468 | report->field[i]->physical, |
469 | report->field[i]->usage[0].collection_index, | ||
470 | &hsdev, &priv); | ||
471 | |||
449 | if (callback && callback->capture_sample) { | 472 | if (callback && callback->capture_sample) { |
450 | if (report->field[i]->logical) | 473 | if (report->field[i]->logical) |
451 | callback->capture_sample(pdata->hsdev, | 474 | callback->capture_sample(hsdev, |
452 | report->field[i]->logical, sz, ptr, | 475 | report->field[i]->logical, sz, ptr, |
453 | callback->pdev); | 476 | callback->pdev); |
454 | else | 477 | else |
455 | callback->capture_sample(pdata->hsdev, | 478 | callback->capture_sample(hsdev, |
456 | report->field[i]->usage->hid, sz, ptr, | 479 | report->field[i]->usage->hid, sz, ptr, |
457 | callback->pdev); | 480 | callback->pdev); |
458 | } | 481 | } |
459 | ptr += sz; | 482 | ptr += sz; |
460 | } | 483 | } |
461 | if (callback && collection && callback->send_event) | 484 | if (callback && collection && callback->send_event) |
462 | callback->send_event(pdata->hsdev, collection->usage, | 485 | callback->send_event(hsdev, collection->usage, |
463 | callback->pdev); | 486 | callback->pdev); |
464 | spin_unlock_irqrestore(&pdata->lock, flags); | 487 | spin_unlock_irqrestore(&pdata->lock, flags); |
465 | 488 | ||
@@ -472,7 +495,7 @@ int sensor_hub_device_open(struct hid_sensor_hub_device *hsdev) | |||
472 | struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev); | 495 | struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev); |
473 | 496 | ||
474 | mutex_lock(&data->mutex); | 497 | mutex_lock(&data->mutex); |
475 | if (!hsdev->ref_cnt) { | 498 | if (!data->ref_cnt) { |
476 | ret = hid_hw_open(hsdev->hdev); | 499 | ret = hid_hw_open(hsdev->hdev); |
477 | if (ret) { | 500 | if (ret) { |
478 | hid_err(hsdev->hdev, "failed to open hid device\n"); | 501 | hid_err(hsdev->hdev, "failed to open hid device\n"); |
@@ -480,7 +503,7 @@ int sensor_hub_device_open(struct hid_sensor_hub_device *hsdev) | |||
480 | return ret; | 503 | return ret; |
481 | } | 504 | } |
482 | } | 505 | } |
483 | hsdev->ref_cnt++; | 506 | data->ref_cnt++; |
484 | mutex_unlock(&data->mutex); | 507 | mutex_unlock(&data->mutex); |
485 | 508 | ||
486 | return ret; | 509 | return ret; |
@@ -492,8 +515,8 @@ void sensor_hub_device_close(struct hid_sensor_hub_device *hsdev) | |||
492 | struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev); | 515 | struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev); |
493 | 516 | ||
494 | mutex_lock(&data->mutex); | 517 | mutex_lock(&data->mutex); |
495 | hsdev->ref_cnt--; | 518 | data->ref_cnt--; |
496 | if (!hsdev->ref_cnt) | 519 | if (!data->ref_cnt) |
497 | hid_hw_close(hsdev->hdev); | 520 | hid_hw_close(hsdev->hdev); |
498 | mutex_unlock(&data->mutex); | 521 | mutex_unlock(&data->mutex); |
499 | } | 522 | } |
@@ -540,26 +563,19 @@ static int sensor_hub_probe(struct hid_device *hdev, | |||
540 | struct sensor_hub_data *sd; | 563 | struct sensor_hub_data *sd; |
541 | int i; | 564 | int i; |
542 | char *name; | 565 | char *name; |
543 | struct hid_report *report; | ||
544 | struct hid_report_enum *report_enum; | ||
545 | struct hid_field *field; | ||
546 | int dev_cnt; | 566 | int dev_cnt; |
567 | struct hid_sensor_hub_device *hsdev; | ||
568 | struct hid_sensor_hub_device *last_hsdev = NULL; | ||
547 | 569 | ||
548 | sd = devm_kzalloc(&hdev->dev, sizeof(*sd), GFP_KERNEL); | 570 | sd = devm_kzalloc(&hdev->dev, sizeof(*sd), GFP_KERNEL); |
549 | if (!sd) { | 571 | if (!sd) { |
550 | hid_err(hdev, "cannot allocate Sensor data\n"); | 572 | hid_err(hdev, "cannot allocate Sensor data\n"); |
551 | return -ENOMEM; | 573 | return -ENOMEM; |
552 | } | 574 | } |
553 | sd->hsdev = devm_kzalloc(&hdev->dev, sizeof(*sd->hsdev), GFP_KERNEL); | 575 | |
554 | if (!sd->hsdev) { | ||
555 | hid_err(hdev, "cannot allocate hid_sensor_hub_device\n"); | ||
556 | return -ENOMEM; | ||
557 | } | ||
558 | hid_set_drvdata(hdev, sd); | 576 | hid_set_drvdata(hdev, sd); |
559 | sd->quirks = id->driver_data; | 577 | sd->quirks = id->driver_data; |
560 | sd->hsdev->hdev = hdev; | 578 | |
561 | sd->hsdev->vendor_id = hdev->vendor; | ||
562 | sd->hsdev->product_id = hdev->product; | ||
563 | spin_lock_init(&sd->lock); | 579 | spin_lock_init(&sd->lock); |
564 | spin_lock_init(&sd->dyn_callback_lock); | 580 | spin_lock_init(&sd->dyn_callback_lock); |
565 | mutex_init(&sd->mutex); | 581 | mutex_init(&sd->mutex); |
@@ -577,9 +593,8 @@ static int sensor_hub_probe(struct hid_device *hdev, | |||
577 | } | 593 | } |
578 | INIT_LIST_HEAD(&sd->dyn_callback_list); | 594 | INIT_LIST_HEAD(&sd->dyn_callback_list); |
579 | sd->hid_sensor_client_cnt = 0; | 595 | sd->hid_sensor_client_cnt = 0; |
580 | report_enum = &hdev->report_enum[HID_INPUT_REPORT]; | ||
581 | 596 | ||
582 | dev_cnt = sensor_hub_get_physical_device_count(report_enum); | 597 | dev_cnt = sensor_hub_get_physical_device_count(hdev); |
583 | if (dev_cnt > HID_MAX_PHY_DEVICES) { | 598 | if (dev_cnt > HID_MAX_PHY_DEVICES) { |
584 | hid_err(hdev, "Invalid Physical device count\n"); | 599 | hid_err(hdev, "Invalid Physical device count\n"); |
585 | ret = -EINVAL; | 600 | ret = -EINVAL; |
@@ -593,42 +608,63 @@ static int sensor_hub_probe(struct hid_device *hdev, | |||
593 | ret = -ENOMEM; | 608 | ret = -ENOMEM; |
594 | goto err_stop_hw; | 609 | goto err_stop_hw; |
595 | } | 610 | } |
596 | list_for_each_entry(report, &report_enum->report_list, list) { | 611 | |
597 | hid_dbg(hdev, "Report id:%x\n", report->id); | 612 | for (i = 0; i < hdev->maxcollection; ++i) { |
598 | field = report->field[0]; | 613 | struct hid_collection *collection = &hdev->collection[i]; |
599 | if (report->maxfield && field && | 614 | |
600 | field->physical) { | 615 | if (collection->type == HID_COLLECTION_PHYSICAL) { |
616 | |||
617 | hsdev = kzalloc(sizeof(*hsdev), GFP_KERNEL); | ||
618 | if (!hsdev) { | ||
619 | hid_err(hdev, "cannot allocate hid_sensor_hub_device\n"); | ||
620 | ret = -ENOMEM; | ||
621 | goto err_no_mem; | ||
622 | } | ||
623 | hsdev->hdev = hdev; | ||
624 | hsdev->vendor_id = hdev->vendor; | ||
625 | hsdev->product_id = hdev->product; | ||
626 | hsdev->start_collection_index = i; | ||
627 | if (last_hsdev) | ||
628 | last_hsdev->end_collection_index = i; | ||
629 | last_hsdev = hsdev; | ||
601 | name = kasprintf(GFP_KERNEL, "HID-SENSOR-%x", | 630 | name = kasprintf(GFP_KERNEL, "HID-SENSOR-%x", |
602 | field->physical); | 631 | collection->usage); |
603 | if (name == NULL) { | 632 | if (name == NULL) { |
604 | hid_err(hdev, "Failed MFD device name\n"); | 633 | hid_err(hdev, "Failed MFD device name\n"); |
605 | ret = -ENOMEM; | 634 | ret = -ENOMEM; |
606 | goto err_free_names; | 635 | goto err_no_mem; |
607 | } | 636 | } |
608 | sd->hid_sensor_hub_client_devs[ | 637 | sd->hid_sensor_hub_client_devs[ |
609 | sd->hid_sensor_client_cnt].id = PLATFORM_DEVID_AUTO; | 638 | sd->hid_sensor_client_cnt].id = |
639 | PLATFORM_DEVID_AUTO; | ||
610 | sd->hid_sensor_hub_client_devs[ | 640 | sd->hid_sensor_hub_client_devs[ |
611 | sd->hid_sensor_client_cnt].name = name; | 641 | sd->hid_sensor_client_cnt].name = name; |
612 | sd->hid_sensor_hub_client_devs[ | 642 | sd->hid_sensor_hub_client_devs[ |
613 | sd->hid_sensor_client_cnt].platform_data = | 643 | sd->hid_sensor_client_cnt].platform_data = |
614 | sd->hsdev; | 644 | hsdev; |
615 | sd->hid_sensor_hub_client_devs[ | 645 | sd->hid_sensor_hub_client_devs[ |
616 | sd->hid_sensor_client_cnt].pdata_size = | 646 | sd->hid_sensor_client_cnt].pdata_size = |
617 | sizeof(*sd->hsdev); | 647 | sizeof(*hsdev); |
618 | hid_dbg(hdev, "Adding %s:%p\n", name, sd); | 648 | hid_dbg(hdev, "Adding %s:%d\n", name, |
649 | hsdev->start_collection_index); | ||
619 | sd->hid_sensor_client_cnt++; | 650 | sd->hid_sensor_client_cnt++; |
620 | } | 651 | } |
621 | } | 652 | } |
653 | if (last_hsdev) | ||
654 | last_hsdev->end_collection_index = i; | ||
655 | |||
622 | ret = mfd_add_devices(&hdev->dev, 0, sd->hid_sensor_hub_client_devs, | 656 | ret = mfd_add_devices(&hdev->dev, 0, sd->hid_sensor_hub_client_devs, |
623 | sd->hid_sensor_client_cnt, NULL, 0, NULL); | 657 | sd->hid_sensor_client_cnt, NULL, 0, NULL); |
624 | if (ret < 0) | 658 | if (ret < 0) |
625 | goto err_free_names; | 659 | goto err_no_mem; |
626 | 660 | ||
627 | return ret; | 661 | return ret; |
628 | 662 | ||
629 | err_free_names: | 663 | err_no_mem: |
630 | for (i = 0; i < sd->hid_sensor_client_cnt ; ++i) | 664 | for (i = 0; i < sd->hid_sensor_client_cnt; ++i) { |
631 | kfree(sd->hid_sensor_hub_client_devs[i].name); | 665 | kfree(sd->hid_sensor_hub_client_devs[i].name); |
666 | kfree(sd->hid_sensor_hub_client_devs[i].platform_data); | ||
667 | } | ||
632 | kfree(sd->hid_sensor_hub_client_devs); | 668 | kfree(sd->hid_sensor_hub_client_devs); |
633 | err_stop_hw: | 669 | err_stop_hw: |
634 | hid_hw_stop(hdev); | 670 | hid_hw_stop(hdev); |
@@ -650,8 +686,10 @@ static void sensor_hub_remove(struct hid_device *hdev) | |||
650 | complete(&data->pending.ready); | 686 | complete(&data->pending.ready); |
651 | spin_unlock_irqrestore(&data->lock, flags); | 687 | spin_unlock_irqrestore(&data->lock, flags); |
652 | mfd_remove_devices(&hdev->dev); | 688 | mfd_remove_devices(&hdev->dev); |
653 | for (i = 0; i < data->hid_sensor_client_cnt ; ++i) | 689 | for (i = 0; i < data->hid_sensor_client_cnt; ++i) { |
654 | kfree(data->hid_sensor_hub_client_devs[i].name); | 690 | kfree(data->hid_sensor_hub_client_devs[i].name); |
691 | kfree(data->hid_sensor_hub_client_devs[i].platform_data); | ||
692 | } | ||
655 | kfree(data->hid_sensor_hub_client_devs); | 693 | kfree(data->hid_sensor_hub_client_devs); |
656 | hid_set_drvdata(hdev, NULL); | 694 | hid_set_drvdata(hdev, NULL); |
657 | mutex_destroy(&data->mutex); | 695 | mutex_destroy(&data->mutex); |