/** * struct sensor_hub_data - Hold a instance data for a HID hub device * @mutex: Mutex to serialize synchronous request. * @lock: Spin lock to protect pending request structure. * @dyn_callback_list: Holds callback function * @dyn_callback_lock: spin lock to protect callback list * @hid_sensor_hub_client_devs: Stores all MFD cells for a hub instance. * @hid_sensor_client_cnt: Number of MFD cells, (no of sensors attached). * @ref_cnt: Number of MFD clients have opened this device
*/ struct sensor_hub_data { struct mutex mutex;
spinlock_t lock; struct list_head dyn_callback_list;
spinlock_t dyn_callback_lock; struct mfd_cell *hid_sensor_hub_client_devs; int hid_sensor_client_cnt; int ref_cnt;
};
/** * struct hid_sensor_hub_callbacks_list - Stores callback list * @list: list head. * @usage_id: usage id for a physical device. * @hsdev: Stored hid instance for current hub device. * @usage_callback: Stores registered callback functions. * @priv: Private data for a physical device.
*/ struct hid_sensor_hub_callbacks_list { struct list_head list;
u32 usage_id; struct hid_sensor_hub_device *hsdev; struct hid_sensor_hub_callbacks *usage_callback; void *priv;
};
list_for_each_entry(report, &hdev->report_enum[dir].report_list, list) { if (report->id == id) return report;
}
hid_warn(hdev, "No report with id 0x%x found\n", id);
return NULL;
}
staticint sensor_hub_get_physical_device_count(struct hid_device *hdev)
{ int i; int count = 0;
for (i = 0; i < hdev->maxcollection; ++i) { struct hid_collection *collection = &hdev->collection[i]; if (collection->type == HID_COLLECTION_PHYSICAL ||
collection->type == HID_COLLECTION_APPLICATION)
++count;
}
spin_lock_irqsave(&pdata->dyn_callback_lock, flags);
list_for_each_entry(callback, &pdata->dyn_callback_list, list) if (callback->usage_id == usage_id &&
callback->hsdev == hsdev) {
spin_unlock_irqrestore(&pdata->dyn_callback_lock, flags); return -EINVAL;
}
callback = kzalloc(sizeof(*callback), GFP_ATOMIC); if (!callback) {
spin_unlock_irqrestore(&pdata->dyn_callback_lock, flags); return -ENOMEM;
}
callback->hsdev = hsdev;
callback->usage_callback = usage_callback;
callback->usage_id = usage_id;
callback->priv = NULL; /* * If there is a handler registered for the collection type, then * it will handle all reports for sensors in this collection. If * there is also an individual sensor handler registration, then * we want to make sure that the reports are directed to collection * handler, as this may be a fusion sensor. So add collection handlers * to the beginning of the list, so that they are matched first.
*/ if (usage_id == HID_USAGE_SENSOR_COLLECTION)
list_add(&callback->list, &pdata->dyn_callback_list); else
list_add_tail(&callback->list, &pdata->dyn_callback_list);
spin_unlock_irqrestore(&pdata->dyn_callback_lock, flags);
int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
u32 field_index, int buffer_size, void *buffer)
{ struct hid_report *report; struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
__s32 *buf32 = buffer; int i = 0; int remaining_bytes;
__s32 value; int ret = 0;
mutex_lock(&data->mutex);
report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT); if (!report || (field_index >= report->maxfield)) {
ret = -EINVAL; goto done_proc;
}
remaining_bytes = buffer_size % sizeof(__s32);
buffer_size = buffer_size / sizeof(__s32); if (buffer_size) { for (i = 0; i < buffer_size; ++i) {
ret = hid_set_field(report->field[field_index], i,
(__force __s32)cpu_to_le32(*buf32)); if (ret) goto done_proc;
++buf32;
}
} if (remaining_bytes) {
value = 0;
memcpy(&value, (u8 *)buf32, remaining_bytes);
ret = hid_set_field(report->field[field_index], i,
(__force __s32)cpu_to_le32(value)); if (ret) goto done_proc;
}
hid_hw_request(hsdev->hdev, report, HID_REQ_SET_REPORT);
hid_hw_wait(hsdev->hdev);
int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
u32 field_index, int buffer_size, void *buffer)
{ struct hid_report *report; struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev); int report_size; int ret = 0;
u8 *val_ptr; int buffer_index = 0; int i;
/* calculate number of bytes required to read this field */
report_size = DIV_ROUND_UP(report->field[field_index]->report_size,
8) *
report->field[field_index]->report_count; if (!report_size) {
ret = -EINVAL; goto done_proc;
}
ret = min(report_size, buffer_size);
val_ptr = (u8 *)report->field[field_index]->value; for (i = 0; i < report->field[field_index]->report_count; ++i) { if (buffer_index >= ret) break;
int sensor_hub_device_open(struct hid_sensor_hub_device *hsdev)
{ int ret = 0; struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
mutex_lock(&data->mutex); if (!data->ref_cnt) {
ret = hid_hw_open(hsdev->hdev); if (ret) {
hid_err(hsdev->hdev, "failed to open hid device\n");
mutex_unlock(&data->mutex); return ret;
}
}
data->ref_cnt++;
mutex_unlock(&data->mutex);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.