Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 1 | ===================== |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 2 | HID Sensors Framework |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 3 | ===================== |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 4 | HID sensor framework provides necessary interfaces to implement sensor drivers, |
| 5 | which are connected to a sensor hub. The sensor hub is a HID device and it provides |
| 6 | a report descriptor conforming to HID 1.12 sensor usage tables. |
| 7 | |
| 8 | Description from the HID 1.12 "HID Sensor Usages" specification: |
| 9 | "Standardization of HID usages for sensors would allow (but not require) sensor |
| 10 | hardware vendors to provide a consistent Plug And Play interface at the USB boundary, |
| 11 | thereby enabling some operating systems to incorporate common device drivers that |
| 12 | could be reused between vendors, alleviating any need for the vendors to provide |
| 13 | the drivers themselves." |
| 14 | |
| 15 | This specification describes many usage IDs, which describe the type of sensor |
| 16 | and also the individual data fields. Each sensor can have variable number of |
| 17 | data fields. The length and order is specified in the report descriptor. For |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 18 | example a part of report descriptor can look like:: |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 19 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 20 | INPUT(1)[INPUT] |
| 21 | .. |
| 22 | Field(2) |
| 23 | Physical(0020.0073) |
| 24 | Usage(1) |
| 25 | 0020.045f |
| 26 | Logical Minimum(-32767) |
| 27 | Logical Maximum(32767) |
| 28 | Report Size(8) |
| 29 | Report Count(1) |
| 30 | Report Offset(16) |
| 31 | Flags(Variable Absolute) |
| 32 | .. |
| 33 | .. |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 34 | |
| 35 | The report is indicating "sensor page (0x20)" contains an accelerometer-3D (0x73). |
| 36 | This accelerometer-3D has some fields. Here for example field 2 is motion intensity |
| 37 | (0x045f) with a logical minimum value of -32767 and logical maximum of 32767. The |
| 38 | order of fields and length of each field is important as the input event raw |
| 39 | data will use this format. |
| 40 | |
| 41 | |
| 42 | Implementation |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 43 | ============== |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 44 | |
| 45 | This specification defines many different types of sensors with different sets of |
| 46 | data fields. It is difficult to have a common input event to user space applications, |
| 47 | for different sensors. For example an accelerometer can send X,Y and Z data, whereas |
| 48 | an ambient light sensor can send illumination data. |
| 49 | So the implementation has two parts: |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 50 | |
Randy Dunlap | ce6bf2d | 2020-12-28 12:53:25 -0800 | [diff] [blame] | 51 | - Core HID driver |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 52 | - Individual sensor processing part (sensor drivers) |
| 53 | |
| 54 | Core driver |
| 55 | ----------- |
Randy Dunlap | ce6bf2d | 2020-12-28 12:53:25 -0800 | [diff] [blame] | 56 | The core driver (hid-sensor-hub) registers as a HID driver. It parses |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 57 | report descriptors and identifies all the sensors present. It adds an MFD device |
| 58 | with name HID-SENSOR-xxxx (where xxxx is usage id from the specification). |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 59 | |
| 60 | For example: |
| 61 | |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 62 | HID-SENSOR-200073 is registered for an Accelerometer 3D driver. |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 63 | |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 64 | So if any driver with this name is inserted, then the probe routine for that |
| 65 | function will be called. So an accelerometer processing driver can register |
| 66 | with this name and will be probed if there is an accelerometer-3D detected. |
| 67 | |
| 68 | The core driver provides a set of APIs which can be used by the processing |
| 69 | drivers to register and get events for that usage id. Also it provides parsing |
| 70 | functions, which get and set each input/feature/output report. |
| 71 | |
| 72 | Individual sensor processing part (sensor drivers) |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 73 | -------------------------------------------------- |
| 74 | |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 75 | The processing driver will use an interface provided by the core driver to parse |
| 76 | the report and get the indexes of the fields and also can get events. This driver |
| 77 | can use IIO interface to use the standard ABI defined for a type of sensor. |
| 78 | |
| 79 | |
| 80 | Core driver Interface |
| 81 | ===================== |
| 82 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 83 | Callback structure:: |
| 84 | |
| 85 | Each processing driver can use this structure to set some callbacks. |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 86 | int (*suspend)(..): Callback when HID suspend is received |
| 87 | int (*resume)(..): Callback when HID resume is received |
| 88 | int (*capture_sample)(..): Capture a sample for one of its data fields |
| 89 | int (*send_event)(..): One complete event is received which can have |
| 90 | multiple data fields. |
| 91 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 92 | Registration functions:: |
| 93 | |
| 94 | int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev, |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 95 | u32 usage_id, |
| 96 | struct hid_sensor_hub_callbacks *usage_callback): |
| 97 | |
Randy Dunlap | ce6bf2d | 2020-12-28 12:53:25 -0800 | [diff] [blame] | 98 | Registers callbacks for a usage id. The callback functions are not allowed |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 99 | to sleep:: |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 100 | |
| 101 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 102 | int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev, |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 103 | u32 usage_id): |
| 104 | |
Randy Dunlap | ce6bf2d | 2020-12-28 12:53:25 -0800 | [diff] [blame] | 105 | Removes callbacks for a usage id. |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 106 | |
| 107 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 108 | Parsing function:: |
| 109 | |
| 110 | int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev, |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 111 | u8 type, |
| 112 | u32 usage_id, u32 attr_usage_id, |
| 113 | struct hid_sensor_hub_attribute_info *info); |
| 114 | |
| 115 | A processing driver can look for some field of interest and check if it exists |
| 116 | in a report descriptor. If it exists it will store necessary information |
| 117 | so that fields can be set or get individually. |
| 118 | These indexes avoid searching every time and getting field index to get or set. |
| 119 | |
| 120 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 121 | Set Feature report:: |
| 122 | |
| 123 | int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 124 | u32 field_index, s32 value); |
| 125 | |
| 126 | This interface is used to set a value for a field in feature report. For example |
| 127 | if there is a field report_interval, which is parsed by a call to |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 128 | sensor_hub_input_get_attribute_info before, then it can directly set that |
| 129 | individual field:: |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 130 | |
| 131 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 132 | int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 133 | u32 field_index, s32 *value); |
| 134 | |
| 135 | This interface is used to get a value for a field in input report. For example |
| 136 | if there is a field report_interval, which is parsed by a call to |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 137 | sensor_hub_input_get_attribute_info before, then it can directly get that |
| 138 | individual field value:: |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 139 | |
| 140 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 141 | int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev, |
srinivas pandruvada | 620c789 | 2012-09-05 13:56:00 +0100 | [diff] [blame] | 142 | u32 usage_id, |
| 143 | u32 attr_usage_id, u32 report_id); |
| 144 | |
| 145 | This is used to get a particular field value through input reports. For example |
| 146 | accelerometer wants to poll X axis value, then it can call this function with |
| 147 | the usage id of X axis. HID sensors can provide events, so this is not necessary |
| 148 | to poll for any field. If there is some new sample, the core driver will call |
| 149 | registered callback function to process the sample. |
Srinivas Pandruvada | b2eafd7 | 2015-04-10 11:22:23 -0700 | [diff] [blame] | 150 | |
| 151 | |
| 152 | ---------- |
| 153 | |
| 154 | HID Custom and generic Sensors |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 155 | ------------------------------ |
| 156 | |
Srinivas Pandruvada | b2eafd7 | 2015-04-10 11:22:23 -0700 | [diff] [blame] | 157 | |
| 158 | HID Sensor specification defines two special sensor usage types. Since they |
| 159 | don't represent a standard sensor, it is not possible to define using Linux IIO |
| 160 | type interfaces. |
| 161 | The purpose of these sensors is to extend the functionality or provide a |
| 162 | way to obfuscate the data being communicated by a sensor. Without knowing the |
| 163 | mapping between the data and its encapsulated form, it is difficult for |
| 164 | an application/driver to determine what data is being communicated by the sensor. |
| 165 | This allows some differentiating use cases, where vendor can provide applications. |
| 166 | Some common use cases are debug other sensors or to provide some events like |
| 167 | keyboard attached/detached or lid open/close. |
| 168 | |
Randy Dunlap | ce6bf2d | 2020-12-28 12:53:25 -0800 | [diff] [blame] | 169 | To allow application to utilize these sensors, here they are exported using sysfs |
Srinivas Pandruvada | b2eafd7 | 2015-04-10 11:22:23 -0700 | [diff] [blame] | 170 | attribute groups, attributes and misc device interface. |
| 171 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 172 | An example of this representation on sysfs:: |
| 173 | |
| 174 | /sys/devices/pci0000:00/INT33C2:00/i2c-0/i2c-INT33D1:00/0018:8086:09FA.0001/HID-SENSOR-2000e1.6.auto$ tree -R |
| 175 | . |
| 176 | │ ├── enable_sensor |
| 177 | │ │ ├── feature-0-200316 |
| 178 | │ │ │ ├── feature-0-200316-maximum |
| 179 | │ │ │ ├── feature-0-200316-minimum |
| 180 | │ │ │ ├── feature-0-200316-name |
| 181 | │ │ │ ├── feature-0-200316-size |
| 182 | │ │ │ ├── feature-0-200316-unit-expo |
| 183 | │ │ │ ├── feature-0-200316-units |
| 184 | │ │ │ ├── feature-0-200316-value |
| 185 | │ │ ├── feature-1-200201 |
| 186 | │ │ │ ├── feature-1-200201-maximum |
| 187 | │ │ │ ├── feature-1-200201-minimum |
| 188 | │ │ │ ├── feature-1-200201-name |
| 189 | │ │ │ ├── feature-1-200201-size |
| 190 | │ │ │ ├── feature-1-200201-unit-expo |
| 191 | │ │ │ ├── feature-1-200201-units |
| 192 | │ │ │ ├── feature-1-200201-value |
| 193 | │ │ ├── input-0-200201 |
| 194 | │ │ │ ├── input-0-200201-maximum |
| 195 | │ │ │ ├── input-0-200201-minimum |
| 196 | │ │ │ ├── input-0-200201-name |
| 197 | │ │ │ ├── input-0-200201-size |
| 198 | │ │ │ ├── input-0-200201-unit-expo |
| 199 | │ │ │ ├── input-0-200201-units |
| 200 | │ │ │ ├── input-0-200201-value |
| 201 | │ │ ├── input-1-200202 |
| 202 | │ │ │ ├── input-1-200202-maximum |
| 203 | │ │ │ ├── input-1-200202-minimum |
| 204 | │ │ │ ├── input-1-200202-name |
| 205 | │ │ │ ├── input-1-200202-size |
| 206 | │ │ │ ├── input-1-200202-unit-expo |
| 207 | │ │ │ ├── input-1-200202-units |
| 208 | │ │ │ ├── input-1-200202-value |
Srinivas Pandruvada | b2eafd7 | 2015-04-10 11:22:23 -0700 | [diff] [blame] | 209 | |
Randy Dunlap | ce6bf2d | 2020-12-28 12:53:25 -0800 | [diff] [blame] | 210 | Here there is a custom sensor with four fields: two feature and two inputs. |
Srinivas Pandruvada | b2eafd7 | 2015-04-10 11:22:23 -0700 | [diff] [blame] | 211 | Each field is represented by a set of attributes. All fields except the "value" |
Randy Dunlap | ce6bf2d | 2020-12-28 12:53:25 -0800 | [diff] [blame] | 212 | are read only. The value field is a read-write field. |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 213 | |
| 214 | Example:: |
| 215 | |
| 216 | /sys/bus/platform/devices/HID-SENSOR-2000e1.6.auto/feature-0-200316$ grep -r . * |
| 217 | feature-0-200316-maximum:6 |
| 218 | feature-0-200316-minimum:0 |
| 219 | feature-0-200316-name:property-reporting-state |
| 220 | feature-0-200316-size:1 |
| 221 | feature-0-200316-unit-expo:0 |
| 222 | feature-0-200316-units:25 |
| 223 | feature-0-200316-value:1 |
Srinivas Pandruvada | b2eafd7 | 2015-04-10 11:22:23 -0700 | [diff] [blame] | 224 | |
| 225 | How to enable such sensor? |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 226 | ^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 227 | |
Srinivas Pandruvada | b2eafd7 | 2015-04-10 11:22:23 -0700 | [diff] [blame] | 228 | By default sensor can be power gated. To enable sysfs attribute "enable" can be |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 229 | used:: |
| 230 | |
| 231 | $ echo 1 > enable_sensor |
Srinivas Pandruvada | b2eafd7 | 2015-04-10 11:22:23 -0700 | [diff] [blame] | 232 | |
| 233 | Once enabled and powered on, sensor can report value using HID reports. |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 234 | These reports are pushed using misc device interface in a FIFO order:: |
| 235 | |
| 236 | /dev$ tree | grep HID-SENSOR-2000e1.6.auto |
| 237 | │ │ │ ├── 10:53 -> ../HID-SENSOR-2000e1.6.auto |
| 238 | │ ├── HID-SENSOR-2000e1.6.auto |
Srinivas Pandruvada | b2eafd7 | 2015-04-10 11:22:23 -0700 | [diff] [blame] | 239 | |
Randy Dunlap | ce6bf2d | 2020-12-28 12:53:25 -0800 | [diff] [blame] | 240 | Each report can be of variable length preceded by a header. This header |
| 241 | consists of a 32-bit usage id, 64-bit time stamp and 32-bit length field of raw |
Srinivas Pandruvada | b2eafd7 | 2015-04-10 11:22:23 -0700 | [diff] [blame] | 242 | data. |