mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers
Before this commit sensor_hub_input_attr_get_raw_value() failed to take the signedness of 16 and 8 bit values into account, returning e.g. 65436 instead of -100 for the z-axis reading of an accelerometer. This commit adds a new is_signed parameter to the function and makes all callers pass the appropriate value for this. While at it, this commit also fixes up some neighboring lines where statements were needlessly split over 2 lines to improve readability. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Acked-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Cc: <Stable@vger.kernel.org> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
parent
fe5192ac81
commit
0145b50566
@ -358,7 +358,7 @@ static ssize_t show_value(struct device *dev, struct device_attribute *attr,
|
||||
sensor_inst->hsdev,
|
||||
sensor_inst->hsdev->usage,
|
||||
usage, report_id,
|
||||
SENSOR_HUB_SYNC);
|
||||
SENSOR_HUB_SYNC, false);
|
||||
} else if (!strncmp(name, "units", strlen("units")))
|
||||
value = sensor_inst->fields[field_index].attribute.units;
|
||||
else if (!strncmp(name, "unit-expo", strlen("unit-expo")))
|
||||
|
@ -299,7 +299,8 @@ EXPORT_SYMBOL_GPL(sensor_hub_get_feature);
|
||||
int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
|
||||
u32 usage_id,
|
||||
u32 attr_usage_id, u32 report_id,
|
||||
enum sensor_hub_read_flags flag)
|
||||
enum sensor_hub_read_flags flag,
|
||||
bool is_signed)
|
||||
{
|
||||
struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
|
||||
unsigned long flags;
|
||||
@ -331,10 +332,16 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
|
||||
&hsdev->pending.ready, HZ*5);
|
||||
switch (hsdev->pending.raw_size) {
|
||||
case 1:
|
||||
ret_val = *(u8 *)hsdev->pending.raw_data;
|
||||
if (is_signed)
|
||||
ret_val = *(s8 *)hsdev->pending.raw_data;
|
||||
else
|
||||
ret_val = *(u8 *)hsdev->pending.raw_data;
|
||||
break;
|
||||
case 2:
|
||||
ret_val = *(u16 *)hsdev->pending.raw_data;
|
||||
if (is_signed)
|
||||
ret_val = *(s16 *)hsdev->pending.raw_data;
|
||||
else
|
||||
ret_val = *(u16 *)hsdev->pending.raw_data;
|
||||
break;
|
||||
case 4:
|
||||
ret_val = *(u32 *)hsdev->pending.raw_data;
|
||||
|
@ -149,6 +149,7 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
|
||||
int report_id = -1;
|
||||
u32 address;
|
||||
int ret_type;
|
||||
s32 min;
|
||||
struct hid_sensor_hub_device *hsdev =
|
||||
accel_state->common_attributes.hsdev;
|
||||
|
||||
@ -158,12 +159,14 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
hid_sensor_power_state(&accel_state->common_attributes, true);
|
||||
report_id = accel_state->accel[chan->scan_index].report_id;
|
||||
min = accel_state->accel[chan->scan_index].logical_minimum;
|
||||
address = accel_3d_addresses[chan->scan_index];
|
||||
if (report_id >= 0)
|
||||
*val = sensor_hub_input_attr_get_raw_value(
|
||||
accel_state->common_attributes.hsdev,
|
||||
hsdev->usage, address, report_id,
|
||||
SENSOR_HUB_SYNC);
|
||||
SENSOR_HUB_SYNC,
|
||||
min < 0);
|
||||
else {
|
||||
*val = 0;
|
||||
hid_sensor_power_state(&accel_state->common_attributes,
|
||||
|
@ -111,6 +111,7 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
|
||||
int report_id = -1;
|
||||
u32 address;
|
||||
int ret_type;
|
||||
s32 min;
|
||||
|
||||
*val = 0;
|
||||
*val2 = 0;
|
||||
@ -118,13 +119,15 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
hid_sensor_power_state(&gyro_state->common_attributes, true);
|
||||
report_id = gyro_state->gyro[chan->scan_index].report_id;
|
||||
min = gyro_state->gyro[chan->scan_index].logical_minimum;
|
||||
address = gyro_3d_addresses[chan->scan_index];
|
||||
if (report_id >= 0)
|
||||
*val = sensor_hub_input_attr_get_raw_value(
|
||||
gyro_state->common_attributes.hsdev,
|
||||
HID_USAGE_SENSOR_GYRO_3D, address,
|
||||
report_id,
|
||||
SENSOR_HUB_SYNC);
|
||||
SENSOR_HUB_SYNC,
|
||||
min < 0);
|
||||
else {
|
||||
*val = 0;
|
||||
hid_sensor_power_state(&gyro_state->common_attributes,
|
||||
|
@ -75,7 +75,8 @@ static int humidity_read_raw(struct iio_dev *indio_dev,
|
||||
HID_USAGE_SENSOR_HUMIDITY,
|
||||
HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY,
|
||||
humid_st->humidity_attr.report_id,
|
||||
SENSOR_HUB_SYNC);
|
||||
SENSOR_HUB_SYNC,
|
||||
humid_st->humidity_attr.logical_minimum < 0);
|
||||
hid_sensor_power_state(&humid_st->common_attributes, false);
|
||||
|
||||
return IIO_VAL_INT;
|
||||
|
@ -93,6 +93,7 @@ static int als_read_raw(struct iio_dev *indio_dev,
|
||||
int report_id = -1;
|
||||
u32 address;
|
||||
int ret_type;
|
||||
s32 min;
|
||||
|
||||
*val = 0;
|
||||
*val2 = 0;
|
||||
@ -102,8 +103,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
|
||||
case CHANNEL_SCAN_INDEX_INTENSITY:
|
||||
case CHANNEL_SCAN_INDEX_ILLUM:
|
||||
report_id = als_state->als_illum.report_id;
|
||||
address =
|
||||
HID_USAGE_SENSOR_LIGHT_ILLUM;
|
||||
min = als_state->als_illum.logical_minimum;
|
||||
address = HID_USAGE_SENSOR_LIGHT_ILLUM;
|
||||
break;
|
||||
default:
|
||||
report_id = -1;
|
||||
@ -116,7 +117,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
|
||||
als_state->common_attributes.hsdev,
|
||||
HID_USAGE_SENSOR_ALS, address,
|
||||
report_id,
|
||||
SENSOR_HUB_SYNC);
|
||||
SENSOR_HUB_SYNC,
|
||||
min < 0);
|
||||
hid_sensor_power_state(&als_state->common_attributes,
|
||||
false);
|
||||
} else {
|
||||
|
@ -73,6 +73,7 @@ static int prox_read_raw(struct iio_dev *indio_dev,
|
||||
int report_id = -1;
|
||||
u32 address;
|
||||
int ret_type;
|
||||
s32 min;
|
||||
|
||||
*val = 0;
|
||||
*val2 = 0;
|
||||
@ -81,8 +82,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,
|
||||
switch (chan->scan_index) {
|
||||
case CHANNEL_SCAN_INDEX_PRESENCE:
|
||||
report_id = prox_state->prox_attr.report_id;
|
||||
address =
|
||||
HID_USAGE_SENSOR_HUMAN_PRESENCE;
|
||||
min = prox_state->prox_attr.logical_minimum;
|
||||
address = HID_USAGE_SENSOR_HUMAN_PRESENCE;
|
||||
break;
|
||||
default:
|
||||
report_id = -1;
|
||||
@ -95,7 +96,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,
|
||||
prox_state->common_attributes.hsdev,
|
||||
HID_USAGE_SENSOR_PROX, address,
|
||||
report_id,
|
||||
SENSOR_HUB_SYNC);
|
||||
SENSOR_HUB_SYNC,
|
||||
min < 0);
|
||||
hid_sensor_power_state(&prox_state->common_attributes,
|
||||
false);
|
||||
} else {
|
||||
|
@ -163,21 +163,23 @@ static int magn_3d_read_raw(struct iio_dev *indio_dev,
|
||||
int report_id = -1;
|
||||
u32 address;
|
||||
int ret_type;
|
||||
s32 min;
|
||||
|
||||
*val = 0;
|
||||
*val2 = 0;
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
hid_sensor_power_state(&magn_state->magn_flux_attributes, true);
|
||||
report_id =
|
||||
magn_state->magn[chan->address].report_id;
|
||||
report_id = magn_state->magn[chan->address].report_id;
|
||||
min = magn_state->magn[chan->address].logical_minimum;
|
||||
address = magn_3d_addresses[chan->address];
|
||||
if (report_id >= 0)
|
||||
*val = sensor_hub_input_attr_get_raw_value(
|
||||
magn_state->magn_flux_attributes.hsdev,
|
||||
HID_USAGE_SENSOR_COMPASS_3D, address,
|
||||
report_id,
|
||||
SENSOR_HUB_SYNC);
|
||||
SENSOR_HUB_SYNC,
|
||||
min < 0);
|
||||
else {
|
||||
*val = 0;
|
||||
hid_sensor_power_state(
|
||||
|
@ -111,21 +111,23 @@ static int incl_3d_read_raw(struct iio_dev *indio_dev,
|
||||
int report_id = -1;
|
||||
u32 address;
|
||||
int ret_type;
|
||||
s32 min;
|
||||
|
||||
*val = 0;
|
||||
*val2 = 0;
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
hid_sensor_power_state(&incl_state->common_attributes, true);
|
||||
report_id =
|
||||
incl_state->incl[chan->scan_index].report_id;
|
||||
report_id = incl_state->incl[chan->scan_index].report_id;
|
||||
min = incl_state->incl[chan->scan_index].logical_minimum;
|
||||
address = incl_3d_addresses[chan->scan_index];
|
||||
if (report_id >= 0)
|
||||
*val = sensor_hub_input_attr_get_raw_value(
|
||||
incl_state->common_attributes.hsdev,
|
||||
HID_USAGE_SENSOR_INCLINOMETER_3D, address,
|
||||
report_id,
|
||||
SENSOR_HUB_SYNC);
|
||||
SENSOR_HUB_SYNC,
|
||||
min < 0);
|
||||
else {
|
||||
hid_sensor_power_state(&incl_state->common_attributes,
|
||||
false);
|
||||
|
@ -77,6 +77,7 @@ static int press_read_raw(struct iio_dev *indio_dev,
|
||||
int report_id = -1;
|
||||
u32 address;
|
||||
int ret_type;
|
||||
s32 min;
|
||||
|
||||
*val = 0;
|
||||
*val2 = 0;
|
||||
@ -85,8 +86,8 @@ static int press_read_raw(struct iio_dev *indio_dev,
|
||||
switch (chan->scan_index) {
|
||||
case CHANNEL_SCAN_INDEX_PRESSURE:
|
||||
report_id = press_state->press_attr.report_id;
|
||||
address =
|
||||
HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
|
||||
min = press_state->press_attr.logical_minimum;
|
||||
address = HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
|
||||
break;
|
||||
default:
|
||||
report_id = -1;
|
||||
@ -99,7 +100,8 @@ static int press_read_raw(struct iio_dev *indio_dev,
|
||||
press_state->common_attributes.hsdev,
|
||||
HID_USAGE_SENSOR_PRESSURE, address,
|
||||
report_id,
|
||||
SENSOR_HUB_SYNC);
|
||||
SENSOR_HUB_SYNC,
|
||||
min < 0);
|
||||
hid_sensor_power_state(&press_state->common_attributes,
|
||||
false);
|
||||
} else {
|
||||
|
@ -76,7 +76,8 @@ static int temperature_read_raw(struct iio_dev *indio_dev,
|
||||
HID_USAGE_SENSOR_TEMPERATURE,
|
||||
HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE,
|
||||
temp_st->temperature_attr.report_id,
|
||||
SENSOR_HUB_SYNC);
|
||||
SENSOR_HUB_SYNC,
|
||||
temp_st->temperature_attr.logical_minimum < 0);
|
||||
hid_sensor_power_state(
|
||||
&temp_st->common_attributes,
|
||||
false);
|
||||
|
@ -213,7 +213,7 @@ static int hid_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
/* get a report with all values through requesting one value */
|
||||
sensor_hub_input_attr_get_raw_value(time_state->common_attributes.hsdev,
|
||||
HID_USAGE_SENSOR_TIME, hid_time_addresses[0],
|
||||
time_state->info[0].report_id, SENSOR_HUB_SYNC);
|
||||
time_state->info[0].report_id, SENSOR_HUB_SYNC, false);
|
||||
/* wait for all values (event) */
|
||||
ret = wait_for_completion_killable_timeout(
|
||||
&time_state->comp_last_time, HZ*6);
|
||||
|
@ -177,6 +177,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
|
||||
* @attr_usage_id: Attribute usage id as per spec
|
||||
* @report_id: Report id to look for
|
||||
* @flag: Synchronous or asynchronous read
|
||||
* @is_signed: If true then fields < 32 bits will be sign-extended
|
||||
*
|
||||
* Issues a synchronous or asynchronous read request for an input attribute.
|
||||
* Returns data upto 32 bits.
|
||||
@ -190,7 +191,8 @@ enum sensor_hub_read_flags {
|
||||
int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
|
||||
u32 usage_id,
|
||||
u32 attr_usage_id, u32 report_id,
|
||||
enum sensor_hub_read_flags flag
|
||||
enum sensor_hub_read_flags flag,
|
||||
bool is_signed
|
||||
);
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user