1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * HID Sensors Driver 4 * Copyright (c) 2014, Intel Corporation. 5 */ 6 7 #include <linux/device.h> 8 #include <linux/platform_device.h> 9 #include <linux/module.h> 10 #include <linux/interrupt.h> 11 #include <linux/irq.h> 12 #include <linux/slab.h> 13 #include <linux/hid-sensor-hub.h> 14 #include <linux/iio/iio.h> 15 #include <linux/iio/sysfs.h> 16 #include <linux/iio/buffer.h> 17 #include "../common/hid-sensors/hid-sensor-trigger.h" 18 19 struct dev_rot_state { 20 struct hid_sensor_hub_callbacks callbacks; 21 struct hid_sensor_common common_attributes; 22 struct hid_sensor_hub_attribute_info quaternion; 23 u32 sampled_vals[4]; 24 int scale_pre_decml; 25 int scale_post_decml; 26 int scale_precision; 27 int value_offset; 28 }; 29 30 /* Channel definitions */ 31 static const struct iio_chan_spec dev_rot_channels[] = { 32 { 33 .type = IIO_ROT, 34 .modified = 1, 35 .channel2 = IIO_MOD_QUATERNION, 36 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 37 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | 38 BIT(IIO_CHAN_INFO_OFFSET) | 39 BIT(IIO_CHAN_INFO_SCALE) | 40 BIT(IIO_CHAN_INFO_HYSTERESIS) 41 } 42 }; 43 44 /* Adjust channel real bits based on report descriptor */ 45 static void dev_rot_adjust_channel_bit_mask(struct iio_chan_spec *chan, 46 int size) 47 { 48 chan->scan_type.sign = 's'; 49 /* Real storage bits will change based on the report desc. */ 50 chan->scan_type.realbits = size * 8; 51 /* Maximum size of a sample to capture is u32 */ 52 chan->scan_type.storagebits = sizeof(u32) * 8; 53 chan->scan_type.repeat = 4; 54 } 55 56 /* Channel read_raw handler */ 57 static int dev_rot_read_raw(struct iio_dev *indio_dev, 58 struct iio_chan_spec const *chan, 59 int size, int *vals, int *val_len, 60 long mask) 61 { 62 struct dev_rot_state *rot_state = iio_priv(indio_dev); 63 int ret_type; 64 int i; 65 66 vals[0] = 0; 67 vals[1] = 0; 68 69 switch (mask) { 70 case IIO_CHAN_INFO_RAW: 71 if (size >= 4) { 72 for (i = 0; i < 4; ++i) 73 vals[i] = rot_state->sampled_vals[i]; 74 ret_type = IIO_VAL_INT_MULTIPLE; 75 *val_len = 4; 76 } else 77 ret_type = -EINVAL; 78 break; 79 case IIO_CHAN_INFO_SCALE: 80 vals[0] = rot_state->scale_pre_decml; 81 vals[1] = rot_state->scale_post_decml; 82 return rot_state->scale_precision; 83 84 case IIO_CHAN_INFO_OFFSET: 85 *vals = rot_state->value_offset; 86 return IIO_VAL_INT; 87 88 case IIO_CHAN_INFO_SAMP_FREQ: 89 ret_type = hid_sensor_read_samp_freq_value( 90 &rot_state->common_attributes, &vals[0], &vals[1]); 91 break; 92 case IIO_CHAN_INFO_HYSTERESIS: 93 ret_type = hid_sensor_read_raw_hyst_value( 94 &rot_state->common_attributes, &vals[0], &vals[1]); 95 break; 96 default: 97 ret_type = -EINVAL; 98 break; 99 } 100 101 return ret_type; 102 } 103 104 /* Channel write_raw handler */ 105 static int dev_rot_write_raw(struct iio_dev *indio_dev, 106 struct iio_chan_spec const *chan, 107 int val, 108 int val2, 109 long mask) 110 { 111 struct dev_rot_state *rot_state = iio_priv(indio_dev); 112 int ret; 113 114 switch (mask) { 115 case IIO_CHAN_INFO_SAMP_FREQ: 116 ret = hid_sensor_write_samp_freq_value( 117 &rot_state->common_attributes, val, val2); 118 break; 119 case IIO_CHAN_INFO_HYSTERESIS: 120 ret = hid_sensor_write_raw_hyst_value( 121 &rot_state->common_attributes, val, val2); 122 break; 123 default: 124 ret = -EINVAL; 125 } 126 127 return ret; 128 } 129 130 static const struct iio_info dev_rot_info = { 131 .read_raw_multi = &dev_rot_read_raw, 132 .write_raw = &dev_rot_write_raw, 133 }; 134 135 /* Function to push data to buffer */ 136 static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len) 137 { 138 dev_dbg(&indio_dev->dev, "hid_sensor_push_data >>\n"); 139 iio_push_to_buffers(indio_dev, (u8 *)data); 140 dev_dbg(&indio_dev->dev, "hid_sensor_push_data <<\n"); 141 142 } 143 144 /* Callback handler to send event after all samples are received and captured */ 145 static int dev_rot_proc_event(struct hid_sensor_hub_device *hsdev, 146 unsigned usage_id, 147 void *priv) 148 { 149 struct iio_dev *indio_dev = platform_get_drvdata(priv); 150 struct dev_rot_state *rot_state = iio_priv(indio_dev); 151 152 dev_dbg(&indio_dev->dev, "dev_rot_proc_event\n"); 153 if (atomic_read(&rot_state->common_attributes.data_ready)) 154 hid_sensor_push_data(indio_dev, 155 (u8 *)rot_state->sampled_vals, 156 sizeof(rot_state->sampled_vals)); 157 158 return 0; 159 } 160 161 /* Capture samples in local storage */ 162 static int dev_rot_capture_sample(struct hid_sensor_hub_device *hsdev, 163 unsigned usage_id, 164 size_t raw_len, char *raw_data, 165 void *priv) 166 { 167 struct iio_dev *indio_dev = platform_get_drvdata(priv); 168 struct dev_rot_state *rot_state = iio_priv(indio_dev); 169 170 if (usage_id == HID_USAGE_SENSOR_ORIENT_QUATERNION) { 171 memcpy(rot_state->sampled_vals, raw_data, 172 sizeof(rot_state->sampled_vals)); 173 dev_dbg(&indio_dev->dev, "Recd Quat len:%zu::%zu\n", raw_len, 174 sizeof(rot_state->sampled_vals)); 175 } 176 177 return 0; 178 } 179 180 /* Parse report which is specific to an usage id*/ 181 static int dev_rot_parse_report(struct platform_device *pdev, 182 struct hid_sensor_hub_device *hsdev, 183 struct iio_chan_spec *channels, 184 unsigned usage_id, 185 struct dev_rot_state *st) 186 { 187 int ret; 188 189 ret = sensor_hub_input_get_attribute_info(hsdev, 190 HID_INPUT_REPORT, 191 usage_id, 192 HID_USAGE_SENSOR_ORIENT_QUATERNION, 193 &st->quaternion); 194 if (ret) 195 return ret; 196 197 dev_rot_adjust_channel_bit_mask(&channels[0], 198 st->quaternion.size / 4); 199 200 dev_dbg(&pdev->dev, "dev_rot %x:%x\n", st->quaternion.index, 201 st->quaternion.report_id); 202 203 dev_dbg(&pdev->dev, "dev_rot: attrib size %d\n", 204 st->quaternion.size); 205 206 st->scale_precision = hid_sensor_format_scale( 207 hsdev->usage, 208 &st->quaternion, 209 &st->scale_pre_decml, &st->scale_post_decml); 210 211 /* Set Sensitivity field ids, when there is no individual modifier */ 212 if (st->common_attributes.sensitivity.index < 0) { 213 sensor_hub_input_get_attribute_info(hsdev, 214 HID_FEATURE_REPORT, usage_id, 215 HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS | 216 HID_USAGE_SENSOR_DATA_ORIENTATION, 217 &st->common_attributes.sensitivity); 218 dev_dbg(&pdev->dev, "Sensitivity index:report %d:%d\n", 219 st->common_attributes.sensitivity.index, 220 st->common_attributes.sensitivity.report_id); 221 } 222 223 return 0; 224 } 225 226 /* Function to initialize the processing for usage id */ 227 static int hid_dev_rot_probe(struct platform_device *pdev) 228 { 229 int ret; 230 char *name; 231 struct iio_dev *indio_dev; 232 struct dev_rot_state *rot_state; 233 struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; 234 235 indio_dev = devm_iio_device_alloc(&pdev->dev, 236 sizeof(struct dev_rot_state)); 237 if (indio_dev == NULL) 238 return -ENOMEM; 239 240 platform_set_drvdata(pdev, indio_dev); 241 242 rot_state = iio_priv(indio_dev); 243 rot_state->common_attributes.hsdev = hsdev; 244 rot_state->common_attributes.pdev = pdev; 245 246 switch (hsdev->usage) { 247 case HID_USAGE_SENSOR_DEVICE_ORIENTATION: 248 name = "dev_rotation"; 249 break; 250 case HID_USAGE_SENSOR_RELATIVE_ORIENTATION: 251 name = "relative_orientation"; 252 break; 253 case HID_USAGE_SENSOR_GEOMAGNETIC_ORIENTATION: 254 name = "geomagnetic_orientation"; 255 break; 256 default: 257 return -EINVAL; 258 } 259 260 ret = hid_sensor_parse_common_attributes(hsdev, hsdev->usage, 261 &rot_state->common_attributes); 262 if (ret) { 263 dev_err(&pdev->dev, "failed to setup common attributes\n"); 264 return ret; 265 } 266 267 indio_dev->channels = devm_kmemdup(&pdev->dev, dev_rot_channels, 268 sizeof(dev_rot_channels), 269 GFP_KERNEL); 270 if (!indio_dev->channels) { 271 dev_err(&pdev->dev, "failed to duplicate channels\n"); 272 return -ENOMEM; 273 } 274 275 ret = dev_rot_parse_report(pdev, hsdev, 276 (struct iio_chan_spec *)indio_dev->channels, 277 hsdev->usage, rot_state); 278 if (ret) { 279 dev_err(&pdev->dev, "failed to setup attributes\n"); 280 return ret; 281 } 282 283 indio_dev->num_channels = ARRAY_SIZE(dev_rot_channels); 284 indio_dev->info = &dev_rot_info; 285 indio_dev->name = name; 286 indio_dev->modes = INDIO_DIRECT_MODE; 287 288 atomic_set(&rot_state->common_attributes.data_ready, 0); 289 290 ret = hid_sensor_setup_trigger(indio_dev, name, 291 &rot_state->common_attributes); 292 if (ret) { 293 dev_err(&pdev->dev, "trigger setup failed\n"); 294 return ret; 295 } 296 297 ret = iio_device_register(indio_dev); 298 if (ret) { 299 dev_err(&pdev->dev, "device register failed\n"); 300 goto error_remove_trigger; 301 } 302 303 rot_state->callbacks.send_event = dev_rot_proc_event; 304 rot_state->callbacks.capture_sample = dev_rot_capture_sample; 305 rot_state->callbacks.pdev = pdev; 306 ret = sensor_hub_register_callback(hsdev, hsdev->usage, 307 &rot_state->callbacks); 308 if (ret) { 309 dev_err(&pdev->dev, "callback reg failed\n"); 310 goto error_iio_unreg; 311 } 312 313 return 0; 314 315 error_iio_unreg: 316 iio_device_unregister(indio_dev); 317 error_remove_trigger: 318 hid_sensor_remove_trigger(indio_dev, &rot_state->common_attributes); 319 return ret; 320 } 321 322 /* Function to deinitialize the processing for usage id */ 323 static int hid_dev_rot_remove(struct platform_device *pdev) 324 { 325 struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; 326 struct iio_dev *indio_dev = platform_get_drvdata(pdev); 327 struct dev_rot_state *rot_state = iio_priv(indio_dev); 328 329 sensor_hub_remove_callback(hsdev, hsdev->usage); 330 iio_device_unregister(indio_dev); 331 hid_sensor_remove_trigger(indio_dev, &rot_state->common_attributes); 332 333 return 0; 334 } 335 336 static const struct platform_device_id hid_dev_rot_ids[] = { 337 { 338 /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ 339 .name = "HID-SENSOR-20008a", 340 }, 341 { 342 /* Relative orientation(AG) sensor */ 343 .name = "HID-SENSOR-20008e", 344 }, 345 { 346 /* Geomagnetic orientation(AM) sensor */ 347 .name = "HID-SENSOR-2000c1", 348 }, 349 { /* sentinel */ } 350 }; 351 MODULE_DEVICE_TABLE(platform, hid_dev_rot_ids); 352 353 static struct platform_driver hid_dev_rot_platform_driver = { 354 .id_table = hid_dev_rot_ids, 355 .driver = { 356 .name = KBUILD_MODNAME, 357 .pm = &hid_sensor_pm_ops, 358 }, 359 .probe = hid_dev_rot_probe, 360 .remove = hid_dev_rot_remove, 361 }; 362 module_platform_driver(hid_dev_rot_platform_driver); 363 364 MODULE_DESCRIPTION("HID Sensor Device Rotation"); 365 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 366 MODULE_LICENSE("GPL"); 367