int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, u32 usage_id, struct hid_sensor_common *st) { struct hid_sensor_hub_attribute_info timestamp; s32 value; int ret; hid_sensor_get_reporting_interval(hsdev, usage_id, st); sensor_hub_input_get_attribute_info(hsdev, HID_FEATURE_REPORT, usage_id, HID_USAGE_SENSOR_PROP_REPORT_STATE, &st->report_state); sensor_hub_input_get_attribute_info(hsdev, HID_FEATURE_REPORT, usage_id, HID_USAGE_SENSOR_PROY_POWER_STATE, &st->power_state); sensor_hub_input_get_attribute_info(hsdev, HID_FEATURE_REPORT, usage_id, HID_USAGE_SENSOR_PROP_SENSITIVITY_ABS, &st->sensitivity); st->raw_hystersis = -1; sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT, usage_id, HID_USAGE_SENSOR_TIME_TIMESTAMP, ×tamp); if (timestamp.index >= 0 && timestamp.report_id) { int val0, val1; hid_sensor_format_scale(HID_USAGE_SENSOR_TIME_TIMESTAMP, ×tamp, &val0, &val1); st->timestamp_ns_scale = val0; } else st->timestamp_ns_scale = 1000000000; hid_sensor_get_report_latency_info(hsdev, usage_id, st); hid_dbg(hsdev->hdev, "common attributes: %x:%x, %x:%x, %x:%x %x:%x %x:%x\n", st->poll.index, st->poll.report_id, st->report_state.index, st->report_state.report_id, st->power_state.index, st->power_state.report_id, st->sensitivity.index, st->sensitivity.report_id, timestamp.index, timestamp.report_id); ret = sensor_hub_get_feature(hsdev, st->power_state.report_id, st->power_state.index, sizeof(value), &value); if (ret < 0) return ret; if (value < 0) return -EINVAL; return 0; }
int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st, int val1, int val2) { s32 value; int ret; if (val1 < 0 || val2 < 0) return -EINVAL; value = convert_to_vtf_format(st->sensitivity.size, st->sensitivity.unit_expo, val1, val2); ret = sensor_hub_set_feature(st->hsdev, st->sensitivity.report_id, st->sensitivity.index, sizeof(value), &value); if (ret < 0 || value < 0) return -EINVAL; ret = sensor_hub_get_feature(st->hsdev, st->sensitivity.report_id, st->sensitivity.index, sizeof(value), &value); if (ret < 0 || value < 0) return -EINVAL; st->raw_hystersis = value; return 0; }
int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st, int *val1, int *val2) { s32 value; int ret; ret = sensor_hub_get_feature(st->hsdev, st->poll.report_id, st->poll.index, sizeof(value), &value); if (ret < 0 || value < 0) { *val1 = *val2 = 0; return -EINVAL; } else { if (st->poll.units == HID_USAGE_SENSOR_UNITS_MILLISECOND) simple_div(1000, value, val1, val2); else if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND) simple_div(1, value, val1, val2); else { *val1 = *val2 = 0; return -EINVAL; } } return IIO_VAL_INT_PLUS_MICRO; }
int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st, int val1, int val2) { s32 value; int ret; if (val1 < 0 || val2 < 0) return -EINVAL; value = val1 * pow_10(6) + val2; if (value) { if (st->poll.units == HID_USAGE_SENSOR_UNITS_MILLISECOND) value = pow_10(9)/value; else if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND) value = pow_10(6)/value; else value = 0; } ret = sensor_hub_set_feature(st->hsdev, st->poll.report_id, st->poll.index, sizeof(value), &value); if (ret < 0 || value < 0) return -EINVAL; ret = sensor_hub_get_feature(st->hsdev, st->poll.report_id, st->poll.index, sizeof(value), &value); if (ret < 0 || value < 0) return -EINVAL; st->poll_interval = value; return 0; }
static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state) { int state_val; int report_val; s32 poll_value = 0; if (state) { if (sensor_hub_device_open(st->hsdev)) return -EIO; atomic_inc(&st->data_ready); state_val = hid_sensor_get_usage_index(st->hsdev, st->power_state.report_id, st->power_state.index, HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM); report_val = hid_sensor_get_usage_index(st->hsdev, st->report_state.report_id, st->report_state.index, HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM); poll_value = hid_sensor_read_poll_value(st); } else { if (!atomic_dec_and_test(&st->data_ready)) return 0; sensor_hub_device_close(st->hsdev); state_val = hid_sensor_get_usage_index(st->hsdev, st->power_state.report_id, st->power_state.index, HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM); report_val = hid_sensor_get_usage_index(st->hsdev, st->report_state.report_id, st->report_state.index, HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM); } if (state_val >= 0) { state_val += st->power_state.logical_minimum; sensor_hub_set_feature(st->hsdev, st->power_state.report_id, st->power_state.index, (s32)state_val); } if (report_val >= 0) { report_val += st->report_state.logical_minimum; sensor_hub_set_feature(st->hsdev, st->report_state.report_id, st->report_state.index, (s32)report_val); } sensor_hub_get_feature(st->hsdev, st->power_state.report_id, st->power_state.index, &state_val); if (state && poll_value) msleep_interruptible(poll_value * 2); return 0; }
int hid_sensor_get_report_latency(struct hid_sensor_common *st) { int ret; int value; ret = sensor_hub_get_feature(st->hsdev, st->report_latency.report_id, st->report_latency.index, sizeof(value), &value); if (ret < 0) return ret; return value; }
static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, bool state) { struct hid_sensor_common *st = iio_trigger_get_drvdata(trig); s32 power_state_val; s32 report_state_val; st->data_ready = state; if (state) { power_state_val = hid_sensor_get_usage_index(st->hsdev, st->power_state.report_id, st->power_state.index, HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM); report_state_val = hid_sensor_get_usage_index(st->hsdev, st->report_state.report_id, st->report_state.index, HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM); } else { power_state_val = hid_sensor_get_usage_index(st->hsdev, st->power_state.report_id, st->power_state.index, HID_USAGE_SENSOR_PROP_POWER_STATE_D1_LOW_POWER_ENUM); report_state_val = hid_sensor_get_usage_index(st->hsdev, st->report_state.report_id, st->report_state.index, HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM); } power_state_val += st->power_state.logical_minimum; report_state_val += st->report_state.logical_minimum; if (power_state_val >= 0) sensor_hub_set_feature(st->hsdev, st->power_state.report_id, st->power_state.index, power_state_val); if (report_state_val >= 0) sensor_hub_set_feature(st->hsdev, st->report_state.report_id, st->report_state.index, report_state_val); /* Some hubs require this read as a 'sync' point. */ sensor_hub_get_feature(st->hsdev, st->power_state.report_id, st->power_state.index, &power_state_val); sensor_hub_set_feature(st->hsdev, st->conn_type.report_id, st->conn_type.index, hid_sensor_conn_type); return 0; }
s32 hid_sensor_read_poll_value(struct hid_sensor_common *st) { s32 value = 0; int ret; ret = sensor_hub_get_feature(st->hsdev, st->poll.report_id, st->poll.index, sizeof(value), &value); if (ret < 0 || value < 0) { return -EINVAL; } else { if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND) value = value * 1000; } return value; }
int hid_sensor_read_raw_hyst_value(struct hid_sensor_iio_common *st, int *val1, int *val2) { s32 value; int ret; ret = sensor_hub_get_feature(st->hsdev, st->sensitivity.report_id, st->sensitivity.index, &value); if (ret < 0 || value < 0) { *val1 = *val2 = 0; return -EINVAL; } else { convert_from_vtf_format(value, st->sensitivity.size, st->sensitivity.unit_expo, val1, val2); } return IIO_VAL_INT_PLUS_MICRO; }
int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st, int val1, int val2) { s32 value; int ret; s32 current_value = 0; if (val1 < 0 || val2 < 0) return -EINVAL; value = val1 * pow_10(6) + val2; if (value) { if (st->poll.units == HID_USAGE_SENSOR_UNITS_MILLISECOND) value = pow_10(9)/value; else if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND) value = pow_10(6)/value; else value = 0; } ret = sensor_hub_set_feature(st->hsdev, st->poll.report_id, st->poll.index, value); if (ret < 0 || value < 0) return -EINVAL; ret = sensor_hub_get_feature(st->hsdev, st->poll.report_id, st->poll.index, ¤t_value); if (ret < 0) { printk(KERN_ERR "sensor_hub_get_feature failed\n"); return ret; } if (current_value != value) { printk(KERN_ERR "sensor_hub_set_feature_failed\n"); return -EINVAL; } return 0; }