hid-sensor-accel-3d.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * HID Sensors Driver
  4. * Copyright (c) 2012, Intel Corporation.
  5. */
  6. #include <linux/device.h>
  7. #include <linux/platform_device.h>
  8. #include <linux/module.h>
  9. #include <linux/mod_devicetable.h>
  10. #include <linux/slab.h>
  11. #include <linux/hid-sensor-hub.h>
  12. #include <linux/iio/iio.h>
  13. #include <linux/iio/buffer.h>
  14. #include "../common/hid-sensors/hid-sensor-trigger.h"
  15. enum accel_3d_channel {
  16. CHANNEL_SCAN_INDEX_X,
  17. CHANNEL_SCAN_INDEX_Y,
  18. CHANNEL_SCAN_INDEX_Z,
  19. ACCEL_3D_CHANNEL_MAX,
  20. };
  21. #define CHANNEL_SCAN_INDEX_TIMESTAMP ACCEL_3D_CHANNEL_MAX
  22. struct accel_3d_state {
  23. struct hid_sensor_hub_callbacks callbacks;
  24. struct hid_sensor_common common_attributes;
  25. struct hid_sensor_hub_attribute_info accel[ACCEL_3D_CHANNEL_MAX];
  26. /* Ensure timestamp is naturally aligned */
  27. struct {
  28. u32 accel_val[3];
  29. s64 timestamp __aligned(8);
  30. } scan;
  31. int scale_pre_decml;
  32. int scale_post_decml;
  33. int scale_precision;
  34. int value_offset;
  35. int64_t timestamp;
  36. };
  37. static const u32 accel_3d_addresses[ACCEL_3D_CHANNEL_MAX] = {
  38. HID_USAGE_SENSOR_ACCEL_X_AXIS,
  39. HID_USAGE_SENSOR_ACCEL_Y_AXIS,
  40. HID_USAGE_SENSOR_ACCEL_Z_AXIS
  41. };
  42. static const u32 accel_3d_sensitivity_addresses[] = {
  43. HID_USAGE_SENSOR_DATA_ACCELERATION,
  44. };
  45. /* Channel definitions */
  46. static const struct iio_chan_spec accel_3d_channels[] = {
  47. {
  48. .type = IIO_ACCEL,
  49. .modified = 1,
  50. .channel2 = IIO_MOD_X,
  51. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  52. .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
  53. BIT(IIO_CHAN_INFO_SCALE) |
  54. BIT(IIO_CHAN_INFO_SAMP_FREQ) |
  55. BIT(IIO_CHAN_INFO_HYSTERESIS),
  56. .scan_index = CHANNEL_SCAN_INDEX_X,
  57. }, {
  58. .type = IIO_ACCEL,
  59. .modified = 1,
  60. .channel2 = IIO_MOD_Y,
  61. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  62. .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
  63. BIT(IIO_CHAN_INFO_SCALE) |
  64. BIT(IIO_CHAN_INFO_SAMP_FREQ) |
  65. BIT(IIO_CHAN_INFO_HYSTERESIS),
  66. .scan_index = CHANNEL_SCAN_INDEX_Y,
  67. }, {
  68. .type = IIO_ACCEL,
  69. .modified = 1,
  70. .channel2 = IIO_MOD_Z,
  71. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  72. .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
  73. BIT(IIO_CHAN_INFO_SCALE) |
  74. BIT(IIO_CHAN_INFO_SAMP_FREQ) |
  75. BIT(IIO_CHAN_INFO_HYSTERESIS),
  76. .scan_index = CHANNEL_SCAN_INDEX_Z,
  77. },
  78. IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP)
  79. };
  80. /* Channel definitions */
  81. static const struct iio_chan_spec gravity_channels[] = {
  82. {
  83. .type = IIO_GRAVITY,
  84. .modified = 1,
  85. .channel2 = IIO_MOD_X,
  86. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  87. .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
  88. BIT(IIO_CHAN_INFO_SCALE) |
  89. BIT(IIO_CHAN_INFO_SAMP_FREQ) |
  90. BIT(IIO_CHAN_INFO_HYSTERESIS),
  91. .scan_index = CHANNEL_SCAN_INDEX_X,
  92. }, {
  93. .type = IIO_GRAVITY,
  94. .modified = 1,
  95. .channel2 = IIO_MOD_Y,
  96. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  97. .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
  98. BIT(IIO_CHAN_INFO_SCALE) |
  99. BIT(IIO_CHAN_INFO_SAMP_FREQ) |
  100. BIT(IIO_CHAN_INFO_HYSTERESIS),
  101. .scan_index = CHANNEL_SCAN_INDEX_Y,
  102. }, {
  103. .type = IIO_GRAVITY,
  104. .modified = 1,
  105. .channel2 = IIO_MOD_Z,
  106. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  107. .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
  108. BIT(IIO_CHAN_INFO_SCALE) |
  109. BIT(IIO_CHAN_INFO_SAMP_FREQ) |
  110. BIT(IIO_CHAN_INFO_HYSTERESIS),
  111. .scan_index = CHANNEL_SCAN_INDEX_Z,
  112. },
  113. IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP),
  114. };
  115. /* Adjust channel real bits based on report descriptor */
  116. static void accel_3d_adjust_channel_bit_mask(struct iio_chan_spec *channels,
  117. int channel, int size)
  118. {
  119. channels[channel].scan_type.sign = 's';
  120. /* Real storage bits will change based on the report desc. */
  121. channels[channel].scan_type.realbits = size * 8;
  122. /* Maximum size of a sample to capture is u32 */
  123. channels[channel].scan_type.storagebits = sizeof(u32) * 8;
  124. }
  125. /* Channel read_raw handler */
  126. static int accel_3d_read_raw(struct iio_dev *indio_dev,
  127. struct iio_chan_spec const *chan,
  128. int *val, int *val2,
  129. long mask)
  130. {
  131. struct accel_3d_state *accel_state = iio_priv(indio_dev);
  132. int report_id = -1;
  133. u32 address;
  134. int ret_type;
  135. s32 min;
  136. struct hid_sensor_hub_device *hsdev =
  137. accel_state->common_attributes.hsdev;
  138. *val = 0;
  139. *val2 = 0;
  140. switch (mask) {
  141. case IIO_CHAN_INFO_RAW:
  142. hid_sensor_power_state(&accel_state->common_attributes, true);
  143. report_id = accel_state->accel[chan->scan_index].report_id;
  144. min = accel_state->accel[chan->scan_index].logical_minimum;
  145. address = accel_3d_addresses[chan->scan_index];
  146. if (report_id >= 0)
  147. *val = sensor_hub_input_attr_get_raw_value(
  148. accel_state->common_attributes.hsdev,
  149. hsdev->usage, address, report_id,
  150. SENSOR_HUB_SYNC,
  151. min < 0);
  152. else {
  153. *val = 0;
  154. hid_sensor_power_state(&accel_state->common_attributes,
  155. false);
  156. return -EINVAL;
  157. }
  158. hid_sensor_power_state(&accel_state->common_attributes, false);
  159. ret_type = IIO_VAL_INT;
  160. break;
  161. case IIO_CHAN_INFO_SCALE:
  162. *val = accel_state->scale_pre_decml;
  163. *val2 = accel_state->scale_post_decml;
  164. ret_type = accel_state->scale_precision;
  165. break;
  166. case IIO_CHAN_INFO_OFFSET:
  167. *val = accel_state->value_offset;
  168. ret_type = IIO_VAL_INT;
  169. break;
  170. case IIO_CHAN_INFO_SAMP_FREQ:
  171. ret_type = hid_sensor_read_samp_freq_value(
  172. &accel_state->common_attributes, val, val2);
  173. break;
  174. case IIO_CHAN_INFO_HYSTERESIS:
  175. ret_type = hid_sensor_read_raw_hyst_value(
  176. &accel_state->common_attributes, val, val2);
  177. break;
  178. default:
  179. ret_type = -EINVAL;
  180. break;
  181. }
  182. return ret_type;
  183. }
  184. /* Channel write_raw handler */
  185. static int accel_3d_write_raw(struct iio_dev *indio_dev,
  186. struct iio_chan_spec const *chan,
  187. int val,
  188. int val2,
  189. long mask)
  190. {
  191. struct accel_3d_state *accel_state = iio_priv(indio_dev);
  192. int ret = 0;
  193. switch (mask) {
  194. case IIO_CHAN_INFO_SAMP_FREQ:
  195. ret = hid_sensor_write_samp_freq_value(
  196. &accel_state->common_attributes, val, val2);
  197. break;
  198. case IIO_CHAN_INFO_HYSTERESIS:
  199. ret = hid_sensor_write_raw_hyst_value(
  200. &accel_state->common_attributes, val, val2);
  201. break;
  202. default:
  203. ret = -EINVAL;
  204. }
  205. return ret;
  206. }
  207. static const struct iio_info accel_3d_info = {
  208. .read_raw = &accel_3d_read_raw,
  209. .write_raw = &accel_3d_write_raw,
  210. };
  211. /* Function to push data to buffer */
  212. static void hid_sensor_push_data(struct iio_dev *indio_dev, void *data,
  213. int len, int64_t timestamp)
  214. {
  215. dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
  216. iio_push_to_buffers_with_timestamp(indio_dev, data, timestamp);
  217. }
  218. /* Callback handler to send event after all samples are received and captured */
  219. static int accel_3d_proc_event(struct hid_sensor_hub_device *hsdev,
  220. unsigned usage_id,
  221. void *priv)
  222. {
  223. struct iio_dev *indio_dev = platform_get_drvdata(priv);
  224. struct accel_3d_state *accel_state = iio_priv(indio_dev);
  225. dev_dbg(&indio_dev->dev, "accel_3d_proc_event\n");
  226. if (atomic_read(&accel_state->common_attributes.data_ready)) {
  227. if (!accel_state->timestamp)
  228. accel_state->timestamp = iio_get_time_ns(indio_dev);
  229. hid_sensor_push_data(indio_dev,
  230. &accel_state->scan,
  231. sizeof(accel_state->scan),
  232. accel_state->timestamp);
  233. accel_state->timestamp = 0;
  234. }
  235. return 0;
  236. }
  237. /* Capture samples in local storage */
  238. static int accel_3d_capture_sample(struct hid_sensor_hub_device *hsdev,
  239. unsigned usage_id,
  240. size_t raw_len, char *raw_data,
  241. void *priv)
  242. {
  243. struct iio_dev *indio_dev = platform_get_drvdata(priv);
  244. struct accel_3d_state *accel_state = iio_priv(indio_dev);
  245. int offset;
  246. int ret = -EINVAL;
  247. switch (usage_id) {
  248. case HID_USAGE_SENSOR_ACCEL_X_AXIS:
  249. case HID_USAGE_SENSOR_ACCEL_Y_AXIS:
  250. case HID_USAGE_SENSOR_ACCEL_Z_AXIS:
  251. offset = usage_id - HID_USAGE_SENSOR_ACCEL_X_AXIS;
  252. accel_state->scan.accel_val[CHANNEL_SCAN_INDEX_X + offset] =
  253. *(u32 *)raw_data;
  254. ret = 0;
  255. break;
  256. case HID_USAGE_SENSOR_TIME_TIMESTAMP:
  257. accel_state->timestamp =
  258. hid_sensor_convert_timestamp(
  259. &accel_state->common_attributes,
  260. *(int64_t *)raw_data);
  261. ret = 0;
  262. break;
  263. default:
  264. break;
  265. }
  266. return ret;
  267. }
  268. /* Parse report which is specific to an usage id*/
  269. static int accel_3d_parse_report(struct platform_device *pdev,
  270. struct hid_sensor_hub_device *hsdev,
  271. struct iio_chan_spec *channels,
  272. unsigned usage_id,
  273. struct accel_3d_state *st)
  274. {
  275. int ret;
  276. int i;
  277. for (i = 0; i <= CHANNEL_SCAN_INDEX_Z; ++i) {
  278. ret = sensor_hub_input_get_attribute_info(hsdev,
  279. HID_INPUT_REPORT,
  280. usage_id,
  281. HID_USAGE_SENSOR_ACCEL_X_AXIS + i,
  282. &st->accel[CHANNEL_SCAN_INDEX_X + i]);
  283. if (ret < 0)
  284. break;
  285. accel_3d_adjust_channel_bit_mask(channels,
  286. CHANNEL_SCAN_INDEX_X + i,
  287. st->accel[CHANNEL_SCAN_INDEX_X + i].size);
  288. }
  289. dev_dbg(&pdev->dev, "accel_3d %x:%x, %x:%x, %x:%x\n",
  290. st->accel[0].index,
  291. st->accel[0].report_id,
  292. st->accel[1].index, st->accel[1].report_id,
  293. st->accel[2].index, st->accel[2].report_id);
  294. st->scale_precision = hid_sensor_format_scale(
  295. hsdev->usage,
  296. &st->accel[CHANNEL_SCAN_INDEX_X],
  297. &st->scale_pre_decml, &st->scale_post_decml);
  298. return ret;
  299. }
  300. /* Function to initialize the processing for usage id */
  301. static int hid_accel_3d_probe(struct platform_device *pdev)
  302. {
  303. int ret = 0;
  304. const char *name;
  305. struct iio_dev *indio_dev;
  306. struct accel_3d_state *accel_state;
  307. const struct iio_chan_spec *channel_spec;
  308. int channel_size;
  309. struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
  310. indio_dev = devm_iio_device_alloc(&pdev->dev,
  311. sizeof(struct accel_3d_state));
  312. if (indio_dev == NULL)
  313. return -ENOMEM;
  314. platform_set_drvdata(pdev, indio_dev);
  315. accel_state = iio_priv(indio_dev);
  316. accel_state->common_attributes.hsdev = hsdev;
  317. accel_state->common_attributes.pdev = pdev;
  318. if (hsdev->usage == HID_USAGE_SENSOR_ACCEL_3D) {
  319. name = "accel_3d";
  320. channel_spec = accel_3d_channels;
  321. channel_size = sizeof(accel_3d_channels);
  322. indio_dev->num_channels = ARRAY_SIZE(accel_3d_channels);
  323. } else {
  324. name = "gravity";
  325. channel_spec = gravity_channels;
  326. channel_size = sizeof(gravity_channels);
  327. indio_dev->num_channels = ARRAY_SIZE(gravity_channels);
  328. }
  329. ret = hid_sensor_parse_common_attributes(hsdev,
  330. hsdev->usage,
  331. &accel_state->common_attributes,
  332. accel_3d_sensitivity_addresses,
  333. ARRAY_SIZE(accel_3d_sensitivity_addresses));
  334. if (ret) {
  335. dev_err(&pdev->dev, "failed to setup common attributes\n");
  336. return ret;
  337. }
  338. indio_dev->channels = devm_kmemdup(&pdev->dev, channel_spec,
  339. channel_size, GFP_KERNEL);
  340. if (!indio_dev->channels) {
  341. dev_err(&pdev->dev, "failed to duplicate channels\n");
  342. return -ENOMEM;
  343. }
  344. ret = accel_3d_parse_report(pdev, hsdev,
  345. (struct iio_chan_spec *)indio_dev->channels,
  346. hsdev->usage, accel_state);
  347. if (ret) {
  348. dev_err(&pdev->dev, "failed to setup attributes\n");
  349. return ret;
  350. }
  351. indio_dev->info = &accel_3d_info;
  352. indio_dev->name = name;
  353. indio_dev->modes = INDIO_DIRECT_MODE;
  354. atomic_set(&accel_state->common_attributes.data_ready, 0);
  355. ret = hid_sensor_setup_trigger(indio_dev, name,
  356. &accel_state->common_attributes);
  357. if (ret < 0) {
  358. dev_err(&pdev->dev, "trigger setup failed\n");
  359. return ret;
  360. }
  361. ret = iio_device_register(indio_dev);
  362. if (ret) {
  363. dev_err(&pdev->dev, "device register failed\n");
  364. goto error_remove_trigger;
  365. }
  366. accel_state->callbacks.send_event = accel_3d_proc_event;
  367. accel_state->callbacks.capture_sample = accel_3d_capture_sample;
  368. accel_state->callbacks.pdev = pdev;
  369. ret = sensor_hub_register_callback(hsdev, hsdev->usage,
  370. &accel_state->callbacks);
  371. if (ret < 0) {
  372. dev_err(&pdev->dev, "callback reg failed\n");
  373. goto error_iio_unreg;
  374. }
  375. return ret;
  376. error_iio_unreg:
  377. iio_device_unregister(indio_dev);
  378. error_remove_trigger:
  379. hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes);
  380. return ret;
  381. }
  382. /* Function to deinitialize the processing for usage id */
  383. static int hid_accel_3d_remove(struct platform_device *pdev)
  384. {
  385. struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
  386. struct iio_dev *indio_dev = platform_get_drvdata(pdev);
  387. struct accel_3d_state *accel_state = iio_priv(indio_dev);
  388. sensor_hub_remove_callback(hsdev, hsdev->usage);
  389. iio_device_unregister(indio_dev);
  390. hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes);
  391. return 0;
  392. }
  393. static const struct platform_device_id hid_accel_3d_ids[] = {
  394. {
  395. /* Format: HID-SENSOR-usage_id_in_hex_lowercase */
  396. .name = "HID-SENSOR-200073",
  397. },
  398. { /* gravity sensor */
  399. .name = "HID-SENSOR-20007b",
  400. },
  401. { /* sentinel */ }
  402. };
  403. MODULE_DEVICE_TABLE(platform, hid_accel_3d_ids);
  404. static struct platform_driver hid_accel_3d_platform_driver = {
  405. .id_table = hid_accel_3d_ids,
  406. .driver = {
  407. .name = KBUILD_MODNAME,
  408. .pm = &hid_sensor_pm_ops,
  409. },
  410. .probe = hid_accel_3d_probe,
  411. .remove = hid_accel_3d_remove,
  412. };
  413. module_platform_driver(hid_accel_3d_platform_driver);
  414. MODULE_DESCRIPTION("HID Sensor Accel 3D");
  415. MODULE_AUTHOR("Srinivas Pandruvada <[email protected]>");
  416. MODULE_LICENSE("GPL");
  417. MODULE_IMPORT_NS(IIO_HID);