diff options
| -rw-r--r-- | drivers/hid/hid-sensor-hub.c | 210 | ||||
| -rw-r--r-- | drivers/iio/common/hid-sensors/hid-sensor-trigger.c | 39 | ||||
| -rw-r--r-- | include/linux/hid-sensor-hub.h | 9 | ||||
| -rw-r--r-- | include/linux/hid-sensor-ids.h | 16 |
4 files changed, 164 insertions, 110 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); |
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index 7dcf83998e6f..dbefbdaf7cd1 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c | |||
| @@ -38,29 +38,40 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, | |||
| 38 | if (state) { | 38 | if (state) { |
| 39 | if (sensor_hub_device_open(st->hsdev)) | 39 | if (sensor_hub_device_open(st->hsdev)) |
| 40 | return -EIO; | 40 | return -EIO; |
| 41 | state_val = | 41 | state_val = hid_sensor_get_usage_index(st->hsdev, |
| 42 | HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM; | 42 | st->power_state.report_id, |
| 43 | report_val = | 43 | st->power_state.index, |
| 44 | HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM; | 44 | HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM); |
| 45 | 45 | report_val = hid_sensor_get_usage_index(st->hsdev, | |
| 46 | st->report_state.report_id, | ||
| 47 | st->report_state.index, | ||
| 48 | HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM); | ||
| 46 | } else { | 49 | } else { |
| 47 | sensor_hub_device_close(st->hsdev); | 50 | sensor_hub_device_close(st->hsdev); |
| 48 | state_val = | 51 | state_val = hid_sensor_get_usage_index(st->hsdev, |
| 49 | HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM; | 52 | st->power_state.report_id, |
| 50 | report_val = | 53 | st->power_state.index, |
| 51 | HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM; | 54 | HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM); |
| 55 | report_val = hid_sensor_get_usage_index(st->hsdev, | ||
| 56 | st->report_state.report_id, | ||
| 57 | st->report_state.index, | ||
| 58 | HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM); | ||
| 52 | } | 59 | } |
| 53 | |||
| 54 | st->data_ready = state; | 60 | st->data_ready = state; |
| 55 | state_val += st->power_state.logical_minimum; | 61 | |
| 56 | report_val += st->report_state.logical_minimum; | 62 | if (state_val >= 0) { |
| 57 | sensor_hub_set_feature(st->hsdev, st->power_state.report_id, | 63 | state_val += st->power_state.logical_minimum; |
| 64 | sensor_hub_set_feature(st->hsdev, st->power_state.report_id, | ||
| 58 | st->power_state.index, | 65 | st->power_state.index, |
| 59 | (s32)state_val); | 66 | (s32)state_val); |
| 67 | } | ||
| 60 | 68 | ||
| 61 | sensor_hub_set_feature(st->hsdev, st->report_state.report_id, | 69 | if (report_val >= 0) { |
| 70 | report_val += st->report_state.logical_minimum; | ||
| 71 | sensor_hub_set_feature(st->hsdev, st->report_state.report_id, | ||
| 62 | st->report_state.index, | 72 | st->report_state.index, |
| 63 | (s32)report_val); | 73 | (s32)report_val); |
| 74 | } | ||
| 64 | 75 | ||
| 65 | return 0; | 76 | return 0; |
| 66 | } | 77 | } |
diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-sensor-hub.h index b914ca3f57ba..b70cfd7ff29c 100644 --- a/include/linux/hid-sensor-hub.h +++ b/include/linux/hid-sensor-hub.h | |||
| @@ -51,13 +51,15 @@ struct hid_sensor_hub_attribute_info { | |||
| 51 | * @hdev: Stores the hid instance. | 51 | * @hdev: Stores the hid instance. |
| 52 | * @vendor_id: Vendor id of hub device. | 52 | * @vendor_id: Vendor id of hub device. |
| 53 | * @product_id: Product id of hub device. | 53 | * @product_id: Product id of hub device. |
| 54 | * @ref_cnt: Number of MFD clients have opened this device | 54 | * @start_collection_index: Starting index for a phy type collection |
| 55 | * @end_collection_index: Last index for a phy type collection | ||
| 55 | */ | 56 | */ |
| 56 | struct hid_sensor_hub_device { | 57 | struct hid_sensor_hub_device { |
| 57 | struct hid_device *hdev; | 58 | struct hid_device *hdev; |
| 58 | u32 vendor_id; | 59 | u32 vendor_id; |
| 59 | u32 product_id; | 60 | u32 product_id; |
| 60 | int ref_cnt; | 61 | int start_collection_index; |
| 62 | int end_collection_index; | ||
| 61 | }; | 63 | }; |
| 62 | 64 | ||
| 63 | /** | 65 | /** |
| @@ -218,4 +220,7 @@ int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st, | |||
| 218 | int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st, | 220 | int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st, |
| 219 | int *val1, int *val2); | 221 | int *val1, int *val2); |
| 220 | 222 | ||
| 223 | int hid_sensor_get_usage_index(struct hid_sensor_hub_device *hsdev, | ||
| 224 | u32 report_id, int field_index, u32 usage_id); | ||
| 225 | |||
| 221 | #endif | 226 | #endif |
diff --git a/include/linux/hid-sensor-ids.h b/include/linux/hid-sensor-ids.h index beaf965621c1..f8607605a31c 100644 --- a/include/linux/hid-sensor-ids.h +++ b/include/linux/hid-sensor-ids.h | |||
| @@ -130,15 +130,15 @@ | |||
| 130 | #define HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS 0x1000 | 130 | #define HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS 0x1000 |
| 131 | 131 | ||
| 132 | /* Power state enumerations */ | 132 | /* Power state enumerations */ |
| 133 | #define HID_USAGE_SENSOR_PROP_POWER_STATE_UNDEFINED_ENUM 0x00 | 133 | #define HID_USAGE_SENSOR_PROP_POWER_STATE_UNDEFINED_ENUM 0x200850 |
| 134 | #define HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM 0x01 | 134 | #define HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM 0x200851 |
| 135 | #define HID_USAGE_SENSOR_PROP_POWER_STATE_D1_LOW_POWER_ENUM 0x02 | 135 | #define HID_USAGE_SENSOR_PROP_POWER_STATE_D1_LOW_POWER_ENUM 0x200852 |
| 136 | #define HID_USAGE_SENSOR_PROP_POWER_STATE_D2_STANDBY_WITH_WAKE_ENUM 0x03 | 136 | #define HID_USAGE_SENSOR_PROP_POWER_STATE_D2_STANDBY_WITH_WAKE_ENUM 0x200853 |
| 137 | #define HID_USAGE_SENSOR_PROP_POWER_STATE_D3_SLEEP_WITH_WAKE_ENUM 0x04 | 137 | #define HID_USAGE_SENSOR_PROP_POWER_STATE_D3_SLEEP_WITH_WAKE_ENUM 0x200854 |
| 138 | #define HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM 0x05 | 138 | #define HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM 0x200855 |
| 139 | 139 | ||
| 140 | /* Report State enumerations */ | 140 | /* Report State enumerations */ |
| 141 | #define HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM 0x00 | 141 | #define HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM 0x200840 |
| 142 | #define HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM 0x01 | 142 | #define HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM 0x200841 |
| 143 | 143 | ||
| 144 | #endif | 144 | #endif |
