779 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * HID Sensors Driver4 * Copyright (c) 2012, Intel Corporation.5 */6 7#include <linux/device.h>8#include <linux/hid.h>9#include <linux/module.h>10#include <linux/slab.h>11#include <linux/mfd/core.h>12#include <linux/list.h>13#include <linux/hid-sensor-ids.h>14#include <linux/hid-sensor-hub.h>15#include "hid-ids.h"16 17#define HID_SENSOR_HUB_ENUM_QUIRK 0x0118 19/**20 * struct sensor_hub_data - Hold a instance data for a HID hub device21 * @mutex: Mutex to serialize synchronous request.22 * @lock: Spin lock to protect pending request structure.23 * @dyn_callback_list: Holds callback function24 * @dyn_callback_lock: spin lock to protect callback list25 * @hid_sensor_hub_client_devs: Stores all MFD cells for a hub instance.26 * @hid_sensor_client_cnt: Number of MFD cells, (no of sensors attached).27 * @ref_cnt: Number of MFD clients have opened this device28 */29struct sensor_hub_data {30 struct mutex mutex;31 spinlock_t lock;32 struct list_head dyn_callback_list;33 spinlock_t dyn_callback_lock;34 struct mfd_cell *hid_sensor_hub_client_devs;35 int hid_sensor_client_cnt;36 int ref_cnt;37};38 39/**40 * struct hid_sensor_hub_callbacks_list - Stores callback list41 * @list: list head.42 * @usage_id: usage id for a physical device.43 * @hsdev: Stored hid instance for current hub device.44 * @usage_callback: Stores registered callback functions.45 * @priv: Private data for a physical device.46 */47struct hid_sensor_hub_callbacks_list {48 struct list_head list;49 u32 usage_id;50 struct hid_sensor_hub_device *hsdev;51 struct hid_sensor_hub_callbacks *usage_callback;52 void *priv;53};54 55static struct hid_report *sensor_hub_report(int id, struct hid_device *hdev,56 int dir)57{58 struct hid_report *report;59 60 list_for_each_entry(report, &hdev->report_enum[dir].report_list, list) {61 if (report->id == id)62 return report;63 }64 hid_warn(hdev, "No report with id 0x%x found\n", id);65 66 return NULL;67}68 69static int sensor_hub_get_physical_device_count(struct hid_device *hdev)70{71 int i;72 int count = 0;73 74 for (i = 0; i < hdev->maxcollection; ++i) {75 struct hid_collection *collection = &hdev->collection[i];76 if (collection->type == HID_COLLECTION_PHYSICAL ||77 collection->type == HID_COLLECTION_APPLICATION)78 ++count;79 }80 81 return count;82}83 84static void sensor_hub_fill_attr_info(85 struct hid_sensor_hub_attribute_info *info,86 s32 index, s32 report_id, struct hid_field *field)87{88 info->index = index;89 info->report_id = report_id;90 info->units = field->unit;91 info->unit_expo = field->unit_exponent;92 info->size = (field->report_size * field->report_count)/8;93 info->logical_minimum = field->logical_minimum;94 info->logical_maximum = field->logical_maximum;95}96 97static struct hid_sensor_hub_callbacks *sensor_hub_get_callback(98 struct hid_device *hdev,99 u32 usage_id,100 int collection_index,101 struct hid_sensor_hub_device **hsdev,102 void **priv)103{104 struct hid_sensor_hub_callbacks_list *callback;105 struct sensor_hub_data *pdata = hid_get_drvdata(hdev);106 unsigned long flags;107 108 spin_lock_irqsave(&pdata->dyn_callback_lock, flags);109 list_for_each_entry(callback, &pdata->dyn_callback_list, list)110 if ((callback->usage_id == usage_id ||111 callback->usage_id == HID_USAGE_SENSOR_COLLECTION) &&112 (collection_index >=113 callback->hsdev->start_collection_index) &&114 (collection_index <115 callback->hsdev->end_collection_index)) {116 *priv = callback->priv;117 *hsdev = callback->hsdev;118 spin_unlock_irqrestore(&pdata->dyn_callback_lock,119 flags);120 return callback->usage_callback;121 }122 spin_unlock_irqrestore(&pdata->dyn_callback_lock, flags);123 124 return NULL;125}126 127int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev,128 u32 usage_id,129 struct hid_sensor_hub_callbacks *usage_callback)130{131 struct hid_sensor_hub_callbacks_list *callback;132 struct sensor_hub_data *pdata = hid_get_drvdata(hsdev->hdev);133 unsigned long flags;134 135 spin_lock_irqsave(&pdata->dyn_callback_lock, flags);136 list_for_each_entry(callback, &pdata->dyn_callback_list, list)137 if (callback->usage_id == usage_id &&138 callback->hsdev == hsdev) {139 spin_unlock_irqrestore(&pdata->dyn_callback_lock, flags);140 return -EINVAL;141 }142 callback = kzalloc(sizeof(*callback), GFP_ATOMIC);143 if (!callback) {144 spin_unlock_irqrestore(&pdata->dyn_callback_lock, flags);145 return -ENOMEM;146 }147 callback->hsdev = hsdev;148 callback->usage_callback = usage_callback;149 callback->usage_id = usage_id;150 callback->priv = NULL;151 /*152 * If there is a handler registered for the collection type, then153 * it will handle all reports for sensors in this collection. If154 * there is also an individual sensor handler registration, then155 * we want to make sure that the reports are directed to collection156 * handler, as this may be a fusion sensor. So add collection handlers157 * to the beginning of the list, so that they are matched first.158 */159 if (usage_id == HID_USAGE_SENSOR_COLLECTION)160 list_add(&callback->list, &pdata->dyn_callback_list);161 else162 list_add_tail(&callback->list, &pdata->dyn_callback_list);163 spin_unlock_irqrestore(&pdata->dyn_callback_lock, flags);164 165 return 0;166}167EXPORT_SYMBOL_GPL(sensor_hub_register_callback);168 169int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev,170 u32 usage_id)171{172 struct hid_sensor_hub_callbacks_list *callback;173 struct sensor_hub_data *pdata = hid_get_drvdata(hsdev->hdev);174 unsigned long flags;175 176 spin_lock_irqsave(&pdata->dyn_callback_lock, flags);177 list_for_each_entry(callback, &pdata->dyn_callback_list, list)178 if (callback->usage_id == usage_id &&179 callback->hsdev == hsdev) {180 list_del(&callback->list);181 kfree(callback);182 break;183 }184 spin_unlock_irqrestore(&pdata->dyn_callback_lock, flags);185 186 return 0;187}188EXPORT_SYMBOL_GPL(sensor_hub_remove_callback);189 190int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,191 u32 field_index, int buffer_size, void *buffer)192{193 struct hid_report *report;194 struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);195 __s32 *buf32 = buffer;196 int i = 0;197 int remaining_bytes;198 __s32 value;199 int ret = 0;200 201 mutex_lock(&data->mutex);202 report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT);203 if (!report || (field_index >= report->maxfield)) {204 ret = -EINVAL;205 goto done_proc;206 }207 208 remaining_bytes = buffer_size % sizeof(__s32);209 buffer_size = buffer_size / sizeof(__s32);210 if (buffer_size) {211 for (i = 0; i < buffer_size; ++i) {212 ret = hid_set_field(report->field[field_index], i,213 (__force __s32)cpu_to_le32(*buf32));214 if (ret)215 goto done_proc;216 217 ++buf32;218 }219 }220 if (remaining_bytes) {221 value = 0;222 memcpy(&value, (u8 *)buf32, remaining_bytes);223 ret = hid_set_field(report->field[field_index], i,224 (__force __s32)cpu_to_le32(value));225 if (ret)226 goto done_proc;227 }228 hid_hw_request(hsdev->hdev, report, HID_REQ_SET_REPORT);229 hid_hw_wait(hsdev->hdev);230 231done_proc:232 mutex_unlock(&data->mutex);233 234 return ret;235}236EXPORT_SYMBOL_GPL(sensor_hub_set_feature);237 238int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,239 u32 field_index, int buffer_size, void *buffer)240{241 struct hid_report *report;242 struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);243 int report_size;244 int ret = 0;245 u8 *val_ptr;246 int buffer_index = 0;247 int i;248 249 memset(buffer, 0, buffer_size);250 251 mutex_lock(&data->mutex);252 report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT);253 if (!report || (field_index >= report->maxfield) ||254 report->field[field_index]->report_count < 1) {255 ret = -EINVAL;256 goto done_proc;257 }258 hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT);259 hid_hw_wait(hsdev->hdev);260 261 /* calculate number of bytes required to read this field */262 report_size = DIV_ROUND_UP(report->field[field_index]->report_size,263 8) *264 report->field[field_index]->report_count;265 if (!report_size) {266 ret = -EINVAL;267 goto done_proc;268 }269 ret = min(report_size, buffer_size);270 271 val_ptr = (u8 *)report->field[field_index]->value;272 for (i = 0; i < report->field[field_index]->report_count; ++i) {273 if (buffer_index >= ret)274 break;275 276 memcpy(&((u8 *)buffer)[buffer_index], val_ptr,277 report->field[field_index]->report_size / 8);278 val_ptr += sizeof(__s32);279 buffer_index += (report->field[field_index]->report_size / 8);280 }281 282done_proc:283 mutex_unlock(&data->mutex);284 285 return ret;286}287EXPORT_SYMBOL_GPL(sensor_hub_get_feature);288 289 290int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,291 u32 usage_id,292 u32 attr_usage_id, u32 report_id,293 enum sensor_hub_read_flags flag,294 bool is_signed)295{296 struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);297 unsigned long flags;298 struct hid_report *report;299 int ret_val = 0;300 301 report = sensor_hub_report(report_id, hsdev->hdev,302 HID_INPUT_REPORT);303 if (!report)304 return -EINVAL;305 306 mutex_lock(hsdev->mutex_ptr);307 if (flag == SENSOR_HUB_SYNC) {308 memset(&hsdev->pending, 0, sizeof(hsdev->pending));309 init_completion(&hsdev->pending.ready);310 hsdev->pending.usage_id = usage_id;311 hsdev->pending.attr_usage_id = attr_usage_id;312 hsdev->pending.raw_size = 0;313 314 spin_lock_irqsave(&data->lock, flags);315 hsdev->pending.status = true;316 spin_unlock_irqrestore(&data->lock, flags);317 }318 mutex_lock(&data->mutex);319 hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT);320 mutex_unlock(&data->mutex);321 if (flag == SENSOR_HUB_SYNC) {322 wait_for_completion_interruptible_timeout(323 &hsdev->pending.ready, HZ*5);324 switch (hsdev->pending.raw_size) {325 case 1:326 if (is_signed)327 ret_val = *(s8 *)hsdev->pending.raw_data;328 else329 ret_val = *(u8 *)hsdev->pending.raw_data;330 break;331 case 2:332 if (is_signed)333 ret_val = *(s16 *)hsdev->pending.raw_data;334 else335 ret_val = *(u16 *)hsdev->pending.raw_data;336 break;337 case 4:338 ret_val = *(u32 *)hsdev->pending.raw_data;339 break;340 default:341 ret_val = 0;342 }343 kfree(hsdev->pending.raw_data);344 hsdev->pending.status = false;345 }346 mutex_unlock(hsdev->mutex_ptr);347 348 return ret_val;349}350EXPORT_SYMBOL_GPL(sensor_hub_input_attr_get_raw_value);351 352int hid_sensor_get_usage_index(struct hid_sensor_hub_device *hsdev,353 u32 report_id, int field_index, u32 usage_id)354{355 struct hid_report *report;356 struct hid_field *field;357 int i;358 359 report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT);360 if (!report || (field_index >= report->maxfield))361 goto done_proc;362 363 field = report->field[field_index];364 for (i = 0; i < field->maxusage; ++i) {365 if (field->usage[i].hid == usage_id)366 return field->usage[i].usage_index;367 }368 369done_proc:370 return -EINVAL;371}372EXPORT_SYMBOL_GPL(hid_sensor_get_usage_index);373 374int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,375 u8 type,376 u32 usage_id,377 u32 attr_usage_id,378 struct hid_sensor_hub_attribute_info *info)379{380 int ret = -1;381 int i;382 struct hid_report *report;383 struct hid_field *field;384 struct hid_report_enum *report_enum;385 struct hid_device *hdev = hsdev->hdev;386 387 /* Initialize with defaults */388 info->usage_id = usage_id;389 info->attrib_id = attr_usage_id;390 info->report_id = -1;391 info->index = -1;392 info->units = -1;393 info->unit_expo = -1;394 395 report_enum = &hdev->report_enum[type];396 list_for_each_entry(report, &report_enum->report_list, list) {397 for (i = 0; i < report->maxfield; ++i) {398 field = report->field[i];399 if (field->maxusage) {400 if ((field->physical == usage_id ||401 field->application == usage_id) &&402 (field->logical == attr_usage_id ||403 field->usage[0].hid ==404 attr_usage_id) &&405 (field->usage[0].collection_index >=406 hsdev->start_collection_index) &&407 (field->usage[0].collection_index <408 hsdev->end_collection_index)) {409 410 sensor_hub_fill_attr_info(info, i,411 report->id,412 field);413 ret = 0;414 break;415 }416 }417 }418 419 }420 421 return ret;422}423EXPORT_SYMBOL_GPL(sensor_hub_input_get_attribute_info);424 425#ifdef CONFIG_PM426static int sensor_hub_suspend(struct hid_device *hdev, pm_message_t message)427{428 struct sensor_hub_data *pdata = hid_get_drvdata(hdev);429 struct hid_sensor_hub_callbacks_list *callback;430 unsigned long flags;431 432 hid_dbg(hdev, " sensor_hub_suspend\n");433 spin_lock_irqsave(&pdata->dyn_callback_lock, flags);434 list_for_each_entry(callback, &pdata->dyn_callback_list, list) {435 if (callback->usage_callback->suspend)436 callback->usage_callback->suspend(437 callback->hsdev, callback->priv);438 }439 spin_unlock_irqrestore(&pdata->dyn_callback_lock, flags);440 441 return 0;442}443 444static int sensor_hub_resume(struct hid_device *hdev)445{446 struct sensor_hub_data *pdata = hid_get_drvdata(hdev);447 struct hid_sensor_hub_callbacks_list *callback;448 unsigned long flags;449 450 hid_dbg(hdev, " sensor_hub_resume\n");451 spin_lock_irqsave(&pdata->dyn_callback_lock, flags);452 list_for_each_entry(callback, &pdata->dyn_callback_list, list) {453 if (callback->usage_callback->resume)454 callback->usage_callback->resume(455 callback->hsdev, callback->priv);456 }457 spin_unlock_irqrestore(&pdata->dyn_callback_lock, flags);458 459 return 0;460}461 462static int sensor_hub_reset_resume(struct hid_device *hdev)463{464 return 0;465}466#endif467 468/*469 * Handle raw report as sent by device470 */471static int sensor_hub_raw_event(struct hid_device *hdev,472 struct hid_report *report, u8 *raw_data, int size)473{474 int i;475 u8 *ptr;476 int sz;477 struct sensor_hub_data *pdata = hid_get_drvdata(hdev);478 unsigned long flags;479 struct hid_sensor_hub_callbacks *callback = NULL;480 struct hid_collection *collection = NULL;481 void *priv = NULL;482 struct hid_sensor_hub_device *hsdev = NULL;483 484 hid_dbg(hdev, "sensor_hub_raw_event report id:0x%x size:%d type:%d\n",485 report->id, size, report->type);486 hid_dbg(hdev, "maxfield:%d\n", report->maxfield);487 if (report->type != HID_INPUT_REPORT)488 return 1;489 490 ptr = raw_data;491 if (report->id)492 ptr++; /* Skip report id */493 494 spin_lock_irqsave(&pdata->lock, flags);495 496 for (i = 0; i < report->maxfield; ++i) {497 hid_dbg(hdev, "%d collection_index:%x hid:%x sz:%x\n",498 i, report->field[i]->usage->collection_index,499 report->field[i]->usage->hid,500 (report->field[i]->report_size *501 report->field[i]->report_count)/8);502 sz = (report->field[i]->report_size *503 report->field[i]->report_count)/8;504 collection = &hdev->collection[505 report->field[i]->usage->collection_index];506 hid_dbg(hdev, "collection->usage %x\n",507 collection->usage);508 509 callback = sensor_hub_get_callback(hdev,510 report->field[i]->physical ? report->field[i]->physical :511 report->field[i]->application,512 report->field[i]->usage[0].collection_index,513 &hsdev, &priv);514 if (!callback) {515 ptr += sz;516 continue;517 }518 if (hsdev->pending.status && (hsdev->pending.attr_usage_id ==519 report->field[i]->usage->hid ||520 hsdev->pending.attr_usage_id ==521 report->field[i]->logical)) {522 hid_dbg(hdev, "data was pending ...\n");523 hsdev->pending.raw_data = kmemdup(ptr, sz, GFP_ATOMIC);524 if (hsdev->pending.raw_data)525 hsdev->pending.raw_size = sz;526 else527 hsdev->pending.raw_size = 0;528 complete(&hsdev->pending.ready);529 }530 if (callback->capture_sample) {531 if (report->field[i]->logical)532 callback->capture_sample(hsdev,533 report->field[i]->logical, sz, ptr,534 callback->pdev);535 else536 callback->capture_sample(hsdev,537 report->field[i]->usage->hid, sz, ptr,538 callback->pdev);539 }540 ptr += sz;541 }542 if (callback && collection && callback->send_event)543 callback->send_event(hsdev, collection->usage,544 callback->pdev);545 spin_unlock_irqrestore(&pdata->lock, flags);546 547 return 1;548}549 550int sensor_hub_device_open(struct hid_sensor_hub_device *hsdev)551{552 int ret = 0;553 struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);554 555 mutex_lock(&data->mutex);556 if (!data->ref_cnt) {557 ret = hid_hw_open(hsdev->hdev);558 if (ret) {559 hid_err(hsdev->hdev, "failed to open hid device\n");560 mutex_unlock(&data->mutex);561 return ret;562 }563 }564 data->ref_cnt++;565 mutex_unlock(&data->mutex);566 567 return ret;568}569EXPORT_SYMBOL_GPL(sensor_hub_device_open);570 571void sensor_hub_device_close(struct hid_sensor_hub_device *hsdev)572{573 struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);574 575 mutex_lock(&data->mutex);576 data->ref_cnt--;577 if (!data->ref_cnt)578 hid_hw_close(hsdev->hdev);579 mutex_unlock(&data->mutex);580}581EXPORT_SYMBOL_GPL(sensor_hub_device_close);582 583static const __u8 *sensor_hub_report_fixup(struct hid_device *hdev, __u8 *rdesc,584 unsigned int *rsize)585{586 /*587 * Checks if the report descriptor of Thinkpad Helix 2 has a logical588 * minimum for magnetic flux axis greater than the maximum.589 */590 if (hdev->product == USB_DEVICE_ID_TEXAS_INSTRUMENTS_LENOVO_YOGA &&591 *rsize == 2558 && rdesc[913] == 0x17 && rdesc[914] == 0x40 &&592 rdesc[915] == 0x81 && rdesc[916] == 0x08 &&593 rdesc[917] == 0x00 && rdesc[918] == 0x27 &&594 rdesc[921] == 0x07 && rdesc[922] == 0x00) {595 /* Sets negative logical minimum for mag x, y and z */596 rdesc[914] = rdesc[935] = rdesc[956] = 0xc0;597 rdesc[915] = rdesc[936] = rdesc[957] = 0x7e;598 rdesc[916] = rdesc[937] = rdesc[958] = 0xf7;599 rdesc[917] = rdesc[938] = rdesc[959] = 0xff;600 }601 602 return rdesc;603}604 605static int sensor_hub_probe(struct hid_device *hdev,606 const struct hid_device_id *id)607{608 int ret;609 struct sensor_hub_data *sd;610 int i;611 char *name;612 int dev_cnt;613 struct hid_sensor_hub_device *hsdev;614 struct hid_sensor_hub_device *last_hsdev = NULL;615 struct hid_sensor_hub_device *collection_hsdev = NULL;616 617 sd = devm_kzalloc(&hdev->dev, sizeof(*sd), GFP_KERNEL);618 if (!sd) {619 hid_err(hdev, "cannot allocate Sensor data\n");620 return -ENOMEM;621 }622 623 hid_set_drvdata(hdev, sd);624 625 spin_lock_init(&sd->lock);626 spin_lock_init(&sd->dyn_callback_lock);627 mutex_init(&sd->mutex);628 ret = hid_parse(hdev);629 if (ret) {630 hid_err(hdev, "parse failed\n");631 return ret;632 }633 INIT_LIST_HEAD(&hdev->inputs);634 635 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | HID_CONNECT_DRIVER);636 if (ret) {637 hid_err(hdev, "hw start failed\n");638 return ret;639 }640 INIT_LIST_HEAD(&sd->dyn_callback_list);641 sd->hid_sensor_client_cnt = 0;642 643 dev_cnt = sensor_hub_get_physical_device_count(hdev);644 if (dev_cnt > HID_MAX_PHY_DEVICES) {645 hid_err(hdev, "Invalid Physical device count\n");646 ret = -EINVAL;647 goto err_stop_hw;648 }649 sd->hid_sensor_hub_client_devs = devm_kcalloc(&hdev->dev,650 dev_cnt,651 sizeof(struct mfd_cell),652 GFP_KERNEL);653 if (sd->hid_sensor_hub_client_devs == NULL) {654 hid_err(hdev, "Failed to allocate memory for mfd cells\n");655 ret = -ENOMEM;656 goto err_stop_hw;657 }658 659 for (i = 0; i < hdev->maxcollection; ++i) {660 struct hid_collection *collection = &hdev->collection[i];661 662 if (collection->type == HID_COLLECTION_PHYSICAL ||663 collection->type == HID_COLLECTION_APPLICATION) {664 665 hsdev = devm_kzalloc(&hdev->dev, sizeof(*hsdev),666 GFP_KERNEL);667 if (!hsdev) {668 hid_err(hdev, "cannot allocate hid_sensor_hub_device\n");669 ret = -ENOMEM;670 goto err_stop_hw;671 }672 hsdev->hdev = hdev;673 hsdev->vendor_id = hdev->vendor;674 hsdev->product_id = hdev->product;675 hsdev->usage = collection->usage;676 hsdev->mutex_ptr = devm_kzalloc(&hdev->dev,677 sizeof(struct mutex),678 GFP_KERNEL);679 if (!hsdev->mutex_ptr) {680 ret = -ENOMEM;681 goto err_stop_hw;682 }683 mutex_init(hsdev->mutex_ptr);684 hsdev->start_collection_index = i;685 if (last_hsdev)686 last_hsdev->end_collection_index = i;687 last_hsdev = hsdev;688 name = devm_kasprintf(&hdev->dev, GFP_KERNEL,689 "HID-SENSOR-%x",690 collection->usage);691 if (name == NULL) {692 hid_err(hdev, "Failed MFD device name\n");693 ret = -ENOMEM;694 goto err_stop_hw;695 }696 sd->hid_sensor_hub_client_devs[697 sd->hid_sensor_client_cnt].name = name;698 sd->hid_sensor_hub_client_devs[699 sd->hid_sensor_client_cnt].platform_data =700 hsdev;701 sd->hid_sensor_hub_client_devs[702 sd->hid_sensor_client_cnt].pdata_size =703 sizeof(*hsdev);704 hid_dbg(hdev, "Adding %s:%d\n", name,705 hsdev->start_collection_index);706 sd->hid_sensor_client_cnt++;707 if (collection_hsdev)708 collection_hsdev->end_collection_index = i;709 if (collection->type == HID_COLLECTION_APPLICATION &&710 collection->usage == HID_USAGE_SENSOR_COLLECTION)711 collection_hsdev = hsdev;712 }713 }714 if (last_hsdev)715 last_hsdev->end_collection_index = i;716 if (collection_hsdev)717 collection_hsdev->end_collection_index = i;718 719 ret = mfd_add_hotplug_devices(&hdev->dev,720 sd->hid_sensor_hub_client_devs,721 sd->hid_sensor_client_cnt);722 if (ret < 0)723 goto err_stop_hw;724 725 return ret;726 727err_stop_hw:728 hid_hw_stop(hdev);729 730 return ret;731}732 733static void sensor_hub_remove(struct hid_device *hdev)734{735 struct sensor_hub_data *data = hid_get_drvdata(hdev);736 unsigned long flags;737 int i;738 739 hid_dbg(hdev, " hardware removed\n");740 hid_hw_close(hdev);741 hid_hw_stop(hdev);742 spin_lock_irqsave(&data->lock, flags);743 for (i = 0; i < data->hid_sensor_client_cnt; ++i) {744 struct hid_sensor_hub_device *hsdev =745 data->hid_sensor_hub_client_devs[i].platform_data;746 if (hsdev->pending.status)747 complete(&hsdev->pending.ready);748 }749 spin_unlock_irqrestore(&data->lock, flags);750 mfd_remove_devices(&hdev->dev);751 mutex_destroy(&data->mutex);752}753 754static const struct hid_device_id sensor_hub_devices[] = {755 { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID,756 HID_ANY_ID) },757 { }758};759MODULE_DEVICE_TABLE(hid, sensor_hub_devices);760 761static struct hid_driver sensor_hub_driver = {762 .name = "hid-sensor-hub",763 .id_table = sensor_hub_devices,764 .probe = sensor_hub_probe,765 .remove = sensor_hub_remove,766 .raw_event = sensor_hub_raw_event,767 .report_fixup = sensor_hub_report_fixup,768#ifdef CONFIG_PM769 .suspend = sensor_hub_suspend,770 .resume = sensor_hub_resume,771 .reset_resume = sensor_hub_reset_resume,772#endif773};774module_hid_driver(sensor_hub_driver);775 776MODULE_DESCRIPTION("HID Sensor Hub driver");777MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");778MODULE_LICENSE("GPL");779