2019-05-29 16:57:49 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2012-09-05 13:56:00 +01:00
/*
* HID Sensors Driver
* Copyright ( c ) 2012 , Intel Corporation .
*/
# include <linux/device.h>
# include <linux/platform_device.h>
# include <linux/module.h>
# include <linux/interrupt.h>
# include <linux/irq.h>
2019-06-19 17:07:02 +03:00
# include <linux/kernel.h>
2012-09-05 13:56:00 +01:00
# include <linux/slab.h>
2019-09-05 14:27:59 +03:00
# include <linux/time.h>
2012-09-05 13:56:00 +01:00
# include <linux/hid-sensor-hub.h>
# include <linux/iio/iio.h>
# include <linux/iio/sysfs.h>
2019-09-05 14:27:59 +03:00
# define HZ_PER_MHZ 1000000L
2014-03-07 07:44:00 +00:00
static struct {
2014-04-19 00:22:00 +01:00
u32 usage_id ;
int unit ; /* 0 for default others from HID sensor spec */
int scale_val0 ; /* scale, whole number */
2016-10-25 01:30:07 +00:00
int scale_val1 ; /* scale, fraction in nanos */
2014-03-07 07:44:00 +00:00
} unit_conversion [ ] = {
2016-10-25 01:30:07 +00:00
{ HID_USAGE_SENSOR_ACCEL_3D , 0 , 9 , 806650000 } ,
2014-04-19 00:22:00 +01:00
{ HID_USAGE_SENSOR_ACCEL_3D ,
HID_USAGE_SENSOR_UNITS_METERS_PER_SEC_SQRD , 1 , 0 } ,
{ HID_USAGE_SENSOR_ACCEL_3D ,
2016-10-25 01:30:07 +00:00
HID_USAGE_SENSOR_UNITS_G , 9 , 806650000 } ,
2014-04-19 00:22:00 +01:00
2017-03-20 17:12:54 +08:00
{ HID_USAGE_SENSOR_GRAVITY_VECTOR , 0 , 9 , 806650000 } ,
{ HID_USAGE_SENSOR_GRAVITY_VECTOR ,
HID_USAGE_SENSOR_UNITS_METERS_PER_SEC_SQRD , 1 , 0 } ,
{ HID_USAGE_SENSOR_GRAVITY_VECTOR ,
HID_USAGE_SENSOR_UNITS_G , 9 , 806650000 } ,
2016-10-25 01:30:07 +00:00
{ HID_USAGE_SENSOR_GYRO_3D , 0 , 0 , 17453293 } ,
2014-04-19 00:22:00 +01:00
{ HID_USAGE_SENSOR_GYRO_3D ,
HID_USAGE_SENSOR_UNITS_RADIANS_PER_SECOND , 1 , 0 } ,
{ HID_USAGE_SENSOR_GYRO_3D ,
2016-10-25 01:30:07 +00:00
HID_USAGE_SENSOR_UNITS_DEGREES_PER_SECOND , 0 , 17453293 } ,
2014-04-19 00:22:00 +01:00
2016-10-25 01:30:07 +00:00
{ HID_USAGE_SENSOR_COMPASS_3D , 0 , 0 , 1000000 } ,
2014-04-19 00:22:00 +01:00
{ HID_USAGE_SENSOR_COMPASS_3D , HID_USAGE_SENSOR_UNITS_GAUSS , 1 , 0 } ,
2016-10-25 01:30:07 +00:00
{ HID_USAGE_SENSOR_INCLINOMETER_3D , 0 , 0 , 17453293 } ,
2014-04-19 00:22:00 +01:00
{ HID_USAGE_SENSOR_INCLINOMETER_3D ,
2016-10-25 01:30:07 +00:00
HID_USAGE_SENSOR_UNITS_DEGREES , 0 , 17453293 } ,
2014-04-19 00:22:00 +01:00
{ HID_USAGE_SENSOR_INCLINOMETER_3D ,
HID_USAGE_SENSOR_UNITS_RADIANS , 1 , 0 } ,
{ HID_USAGE_SENSOR_ALS , 0 , 1 , 0 } ,
{ HID_USAGE_SENSOR_ALS , HID_USAGE_SENSOR_UNITS_LUX , 1 , 0 } ,
2016-08-29 18:50:56 +08:00
{ HID_USAGE_SENSOR_PRESSURE , 0 , 100 , 0 } ,
2016-10-25 01:30:07 +00:00
{ HID_USAGE_SENSOR_PRESSURE , HID_USAGE_SENSOR_UNITS_PASCAL , 0 , 1000000 } ,
2016-11-28 14:41:16 -08:00
{ HID_USAGE_SENSOR_TIME_TIMESTAMP , 0 , 1000000000 , 0 } ,
{ HID_USAGE_SENSOR_TIME_TIMESTAMP , HID_USAGE_SENSOR_UNITS_MILLISECOND ,
1000000 , 0 } ,
2017-03-03 21:44:32 +08:00
2017-05-07 18:24:26 +08:00
{ HID_USAGE_SENSOR_DEVICE_ORIENTATION , 0 , 1 , 0 } ,
{ HID_USAGE_SENSOR_RELATIVE_ORIENTATION , 0 , 1 , 0 } ,
{ HID_USAGE_SENSOR_GEOMAGNETIC_ORIENTATION , 0 , 1 , 0 } ,
2017-03-03 21:44:32 +08:00
{ HID_USAGE_SENSOR_TEMPERATURE , 0 , 1000 , 0 } ,
{ HID_USAGE_SENSOR_TEMPERATURE , HID_USAGE_SENSOR_UNITS_DEGREES , 1000 , 0 } ,
2017-03-20 22:28:45 +08:00
{ HID_USAGE_SENSOR_HUMIDITY , 0 , 1000 , 0 } ,
2014-04-19 00:22:00 +01:00
} ;
2012-09-05 13:56:00 +01:00
static void simple_div ( int dividend , int divisor , int * whole ,
int * micro_frac )
{
int rem ;
int exp = 0 ;
* micro_frac = 0 ;
if ( divisor = = 0 ) {
* whole = 0 ;
return ;
}
* whole = dividend / divisor ;
rem = dividend % divisor ;
if ( rem ) {
while ( rem < = divisor ) {
rem * = 10 ;
exp + + ;
}
2019-06-19 17:07:02 +03:00
* micro_frac = ( rem / divisor ) * int_pow ( 10 , 6 - exp ) ;
2012-09-05 13:56:00 +01:00
}
}
static void split_micro_fraction ( unsigned int no , int exp , int * val1 , int * val2 )
{
2019-09-05 14:27:59 +03:00
int divisor = int_pow ( 10 , exp ) ;
* val1 = no / divisor ;
* val2 = no % divisor * int_pow ( 10 , 6 - exp ) ;
2012-09-05 13:56:00 +01:00
}
/*
VTF format uses exponent and variable size format .
For example if the size is 2 bytes
0x0067 with VTF16E14 format - > + 1.03
To convert just change to 0x67 to decimal and use two decimal as E14 stands
for 10 ^ - 2.
Negative numbers are 2 ' s complement
*/
static void convert_from_vtf_format ( u32 value , int size , int exp ,
int * val1 , int * val2 )
{
int sign = 1 ;
if ( value & BIT ( size * 8 - 1 ) ) {
value = ( ( 1LL < < ( size * 8 ) ) - value ) ;
sign = - 1 ;
}
exp = hid_sensor_convert_exponent ( exp ) ;
if ( exp > = 0 ) {
2019-06-19 17:07:02 +03:00
* val1 = sign * value * int_pow ( 10 , exp ) ;
2012-09-05 13:56:00 +01:00
* val2 = 0 ;
} else {
split_micro_fraction ( value , - exp , val1 , val2 ) ;
if ( * val1 )
* val1 = sign * ( * val1 ) ;
else
* val2 = sign * ( * val2 ) ;
}
}
static u32 convert_to_vtf_format ( int size , int exp , int val1 , int val2 )
{
2019-09-05 14:27:59 +03:00
int divisor ;
2012-09-05 13:56:00 +01:00
u32 value ;
int sign = 1 ;
if ( val1 < 0 | | val2 < 0 )
sign = - 1 ;
exp = hid_sensor_convert_exponent ( exp ) ;
if ( exp < 0 ) {
2019-09-05 14:27:59 +03:00
divisor = int_pow ( 10 , 6 + exp ) ;
2019-06-19 17:07:02 +03:00
value = abs ( val1 ) * int_pow ( 10 , - exp ) ;
2019-09-05 14:27:59 +03:00
value + = abs ( val2 ) / divisor ;
} else {
divisor = int_pow ( 10 , exp ) ;
value = abs ( val1 ) / divisor ;
}
2012-09-05 13:56:00 +01:00
if ( sign < 0 )
value = ( ( 1LL < < ( size * 8 ) ) - value ) ;
return value ;
}
2014-04-19 00:22:00 +01:00
s32 hid_sensor_read_poll_value ( struct hid_sensor_common * st )
{
s32 value = 0 ;
int ret ;
ret = sensor_hub_get_feature ( st - > hsdev ,
2015-02-19 15:35:25 -08:00
st - > poll . report_id ,
st - > poll . index , sizeof ( value ) , & value ) ;
2014-04-19 00:22:00 +01:00
if ( ret < 0 | | value < 0 ) {
return - EINVAL ;
} else {
if ( st - > poll . units = = HID_USAGE_SENSOR_UNITS_SECOND )
value = value * 1000 ;
}
return value ;
}
EXPORT_SYMBOL ( hid_sensor_read_poll_value ) ;
2012-12-15 12:45:00 +00:00
int hid_sensor_read_samp_freq_value ( struct hid_sensor_common * st ,
2012-09-05 13:56:00 +01:00
int * val1 , int * val2 )
{
s32 value ;
int ret ;
ret = sensor_hub_get_feature ( st - > hsdev ,
2015-02-19 15:35:25 -08:00
st - > poll . report_id ,
st - > poll . index , sizeof ( value ) , & value ) ;
2012-09-05 13:56:00 +01:00
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 ;
}
EXPORT_SYMBOL ( hid_sensor_read_samp_freq_value ) ;
2012-12-15 12:45:00 +00:00
int hid_sensor_write_samp_freq_value ( struct hid_sensor_common * st ,
2012-09-05 13:56:00 +01:00
int val1 , int val2 )
{
s32 value ;
int ret ;
if ( val1 < 0 | | val2 < 0 )
2016-11-03 00:45:48 +00:00
return - EINVAL ;
2012-09-05 13:56:00 +01:00
2019-09-05 14:27:59 +03:00
value = val1 * HZ_PER_MHZ + val2 ;
2012-09-05 13:56:00 +01:00
if ( value ) {
if ( st - > poll . units = = HID_USAGE_SENSOR_UNITS_MILLISECOND )
2019-09-05 14:27:59 +03:00
value = NSEC_PER_SEC / value ;
2012-09-05 13:56:00 +01:00
else if ( st - > poll . units = = HID_USAGE_SENSOR_UNITS_SECOND )
2019-09-05 14:27:59 +03:00
value = USEC_PER_SEC / value ;
2012-09-05 13:56:00 +01:00
else
value = 0 ;
}
2015-02-19 15:35:26 -08:00
ret = sensor_hub_set_feature ( st - > hsdev , st - > poll . report_id ,
st - > poll . index , sizeof ( value ) , & value ) ;
2012-09-05 13:56:00 +01:00
if ( ret < 0 | | value < 0 )
2017-04-19 15:35:48 +01:00
return - EINVAL ;
2012-09-05 13:56:00 +01:00
2017-04-07 17:13:17 -07:00
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 ;
2012-09-05 13:56:00 +01:00
}
EXPORT_SYMBOL ( hid_sensor_write_samp_freq_value ) ;
2012-12-15 12:45:00 +00:00
int hid_sensor_read_raw_hyst_value ( struct hid_sensor_common * st ,
2012-09-05 13:56:00 +01:00
int * val1 , int * val2 )
{
s32 value ;
int ret ;
ret = sensor_hub_get_feature ( st - > hsdev ,
2015-02-19 15:35:25 -08:00
st - > sensitivity . report_id ,
st - > sensitivity . index , sizeof ( value ) ,
& value ) ;
2012-09-05 13:56:00 +01:00
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 ;
}
EXPORT_SYMBOL ( hid_sensor_read_raw_hyst_value ) ;
2012-12-15 12:45:00 +00:00
int hid_sensor_write_raw_hyst_value ( struct hid_sensor_common * st ,
2012-09-05 13:56:00 +01:00
int val1 , int val2 )
{
s32 value ;
int ret ;
2016-11-03 00:45:48 +00:00
if ( val1 < 0 | | val2 < 0 )
return - EINVAL ;
2012-09-05 13:56:00 +01:00
value = convert_to_vtf_format ( st - > sensitivity . size ,
st - > sensitivity . unit_expo ,
val1 , val2 ) ;
2015-02-19 15:35:26 -08:00
ret = sensor_hub_set_feature ( st - > hsdev , st - > sensitivity . report_id ,
st - > sensitivity . index , sizeof ( value ) ,
& value ) ;
2012-09-05 13:56:00 +01:00
if ( ret < 0 | | value < 0 )
2017-04-19 15:35:48 +01:00
return - EINVAL ;
2012-09-05 13:56:00 +01:00
2017-04-07 17:13:17 -07:00
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 ;
2012-09-05 13:56:00 +01:00
}
EXPORT_SYMBOL ( hid_sensor_write_raw_hyst_value ) ;
2014-04-19 00:22:00 +01:00
/*
* This fuction applies the unit exponent to the scale .
* For example :
2016-10-25 01:30:07 +00:00
* 9.806650000 - > exp : 2 - > val0 [ 980 ] val1 [ 665000000 ]
* 9.000806000 - > exp : 2 - > val0 [ 900 ] val1 [ 80600000 ]
* 0.174535293 - > exp : 2 - > val0 [ 17 ] val1 [ 453529300 ]
* 1.001745329 - > exp : 0 - > val0 [ 1 ] val1 [ 1745329 ]
* 1.001745329 - > exp : 2 - > val0 [ 100 ] val1 [ 174532900 ]
* 1.001745329 - > exp : 4 - > val0 [ 10017 ] val1 [ 453290000 ]
* 9.806650000 - > exp : - 2 - > val0 [ 0 ] val1 [ 98066500 ]
2014-04-19 00:22:00 +01:00
*/
2016-10-25 01:30:07 +00:00
static void adjust_exponent_nano ( int * val0 , int * val1 , int scale0 ,
2014-04-19 00:22:00 +01:00
int scale1 , int exp )
{
2019-09-05 14:27:59 +03:00
int divisor ;
2014-04-19 00:22:00 +01:00
int i ;
int x ;
int res ;
int rem ;
if ( exp > 0 ) {
2019-06-19 17:07:02 +03:00
* val0 = scale0 * int_pow ( 10 , exp ) ;
2014-04-19 00:22:00 +01:00
res = 0 ;
2016-10-25 01:30:07 +00:00
if ( exp > 9 ) {
2014-04-19 00:22:00 +01:00
* val1 = 0 ;
return ;
}
for ( i = 0 ; i < exp ; + + i ) {
2019-09-05 14:27:59 +03:00
divisor = int_pow ( 10 , 8 - i ) ;
x = scale1 / divisor ;
2019-06-19 17:07:02 +03:00
res + = int_pow ( 10 , exp - 1 - i ) * x ;
2019-09-05 14:27:59 +03:00
scale1 = scale1 % divisor ;
2014-04-19 00:22:00 +01:00
}
* val0 + = res ;
2019-06-19 17:07:02 +03:00
* val1 = scale1 * int_pow ( 10 , exp ) ;
2014-04-19 00:22:00 +01:00
} else if ( exp < 0 ) {
exp = abs ( exp ) ;
2016-10-25 01:30:07 +00:00
if ( exp > 9 ) {
2014-04-19 00:22:00 +01:00
* val0 = * val1 = 0 ;
return ;
}
2019-09-05 14:27:59 +03:00
divisor = int_pow ( 10 , exp ) ;
* val0 = scale0 / divisor ;
rem = scale0 % divisor ;
2014-04-19 00:22:00 +01:00
res = 0 ;
2016-10-25 01:30:07 +00:00
for ( i = 0 ; i < ( 9 - exp ) ; + + i ) {
2019-09-05 14:27:59 +03:00
divisor = int_pow ( 10 , 8 - i ) ;
x = scale1 / divisor ;
2019-06-19 17:07:02 +03:00
res + = int_pow ( 10 , 8 - exp - i ) * x ;
2019-09-05 14:27:59 +03:00
scale1 = scale1 % divisor ;
2014-04-19 00:22:00 +01:00
}
2019-06-19 17:07:02 +03:00
* val1 = rem * int_pow ( 10 , 9 - exp ) + res ;
2014-04-19 00:22:00 +01:00
} else {
* val0 = scale0 ;
* val1 = scale1 ;
}
}
int hid_sensor_format_scale ( u32 usage_id ,
struct hid_sensor_hub_attribute_info * attr_info ,
int * val0 , int * val1 )
{
int i ;
int exp ;
* val0 = 1 ;
* val1 = 0 ;
2014-09-05 12:56:00 +01:00
for ( i = 0 ; i < ARRAY_SIZE ( unit_conversion ) ; + + i ) {
2014-04-19 00:22:00 +01:00
if ( unit_conversion [ i ] . usage_id = = usage_id & &
unit_conversion [ i ] . unit = = attr_info - > units ) {
exp = hid_sensor_convert_exponent (
attr_info - > unit_expo ) ;
2016-10-25 01:30:07 +00:00
adjust_exponent_nano ( val0 , val1 ,
2014-04-19 00:22:00 +01:00
unit_conversion [ i ] . scale_val0 ,
unit_conversion [ i ] . scale_val1 , exp ) ;
break ;
}
}
2016-10-25 01:30:07 +00:00
return IIO_VAL_INT_PLUS_NANO ;
2014-04-19 00:22:00 +01:00
}
EXPORT_SYMBOL ( hid_sensor_format_scale ) ;
2016-11-28 14:41:16 -08:00
int64_t hid_sensor_convert_timestamp ( struct hid_sensor_common * st ,
int64_t raw_value )
{
return st - > timestamp_ns_scale * raw_value ;
}
EXPORT_SYMBOL ( hid_sensor_convert_timestamp ) ;
2014-06-30 10:29:00 +01:00
static
2014-08-05 14:36:00 +01:00
int hid_sensor_get_reporting_interval ( struct hid_sensor_hub_device * hsdev ,
2012-09-05 13:56:00 +01:00
u32 usage_id ,
2012-12-15 12:45:00 +00:00
struct hid_sensor_common * st )
2012-09-05 13:56:00 +01:00
{
sensor_hub_input_get_attribute_info ( hsdev ,
HID_FEATURE_REPORT , usage_id ,
HID_USAGE_SENSOR_PROP_REPORT_INTERVAL ,
& st - > poll ) ;
2014-08-05 14:36:00 +01:00
/* Default unit of measure is milliseconds */
if ( st - > poll . units = = 0 )
st - > poll . units = HID_USAGE_SENSOR_UNITS_MILLISECOND ;
2017-04-07 17:13:17 -07:00
st - > poll_interval = - 1 ;
2014-08-05 14:36:00 +01:00
return 0 ;
}
2017-04-07 19:22:06 -07:00
static void hid_sensor_get_report_latency_info ( struct hid_sensor_hub_device * hsdev ,
u32 usage_id ,
struct hid_sensor_common * st )
{
sensor_hub_input_get_attribute_info ( hsdev , HID_FEATURE_REPORT ,
usage_id ,
HID_USAGE_SENSOR_PROP_REPORT_LATENCY ,
& st - > report_latency ) ;
hid_dbg ( hsdev - > hdev , " Report latency attributes: %x:%x \n " ,
st - > report_latency . index , st - > report_latency . report_id ) ;
}
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 ;
}
EXPORT_SYMBOL ( hid_sensor_get_report_latency ) ;
int hid_sensor_set_report_latency ( struct hid_sensor_common * st , int latency_ms )
{
return sensor_hub_set_feature ( st - > hsdev , st - > report_latency . report_id ,
st - > report_latency . index ,
sizeof ( latency_ms ) , & latency_ms ) ;
}
EXPORT_SYMBOL ( hid_sensor_set_report_latency ) ;
bool hid_sensor_batch_mode_supported ( struct hid_sensor_common * st )
{
return st - > report_latency . index > 0 & & st - > report_latency . report_id > 0 ;
}
EXPORT_SYMBOL ( hid_sensor_batch_mode_supported ) ;
2014-08-05 14:36:00 +01:00
int hid_sensor_parse_common_attributes ( struct hid_sensor_hub_device * hsdev ,
u32 usage_id ,
struct hid_sensor_common * st )
{
2016-11-28 14:41:16 -08:00
struct hid_sensor_hub_attribute_info timestamp ;
2017-03-28 22:23:55 +08:00
s32 value ;
int ret ;
2014-08-05 14:36:00 +01:00
hid_sensor_get_reporting_interval ( hsdev , usage_id , st ) ;
2012-09-05 13:56:00 +01:00
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 ) ;
2017-08-06 21:52:01 -07:00
st - > power_state . logical_minimum = 1 ;
st - > report_state . logical_minimum = 1 ;
2012-09-05 13:56:00 +01:00
sensor_hub_input_get_attribute_info ( hsdev ,
HID_FEATURE_REPORT , usage_id ,
HID_USAGE_SENSOR_PROP_SENSITIVITY_ABS ,
& st - > sensitivity ) ;
2017-04-07 17:13:17 -07:00
st - > raw_hystersis = - 1 ;
2016-11-28 14:41:16 -08:00
sensor_hub_input_get_attribute_info ( hsdev ,
HID_INPUT_REPORT , usage_id ,
HID_USAGE_SENSOR_TIME_TIMESTAMP ,
& timestamp ) ;
if ( timestamp . index > = 0 & & timestamp . report_id ) {
int val0 , val1 ;
hid_sensor_format_scale ( HID_USAGE_SENSOR_TIME_TIMESTAMP ,
& timestamp , & val0 , & val1 ) ;
st - > timestamp_ns_scale = val0 ;
} else
st - > timestamp_ns_scale = 1000000000 ;
2017-04-07 19:22:06 -07:00
hid_sensor_get_report_latency_info ( hsdev , usage_id , st ) ;
2016-11-28 14:41:16 -08:00
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 ) ;
2012-09-05 13:56:00 +01:00
2017-03-28 22:23:55 +08:00
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 ;
2012-09-05 13:56:00 +01:00
return 0 ;
}
EXPORT_SYMBOL ( hid_sensor_parse_common_attributes ) ;
MODULE_AUTHOR ( " Srinivas Pandruvada <srinivas.pandruvada@intel.com> " ) ;
MODULE_DESCRIPTION ( " HID Sensor common attribute processing " ) ;
MODULE_LICENSE ( " GPL " ) ;