PageRenderTime 28ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/iio/orientation/hid-sensor-orientation.c

https://gitlab.com/belos-old/android_kernel_xiaomi_virgo
C | 450 lines | 375 code | 42 blank | 33 comment | 27 complexity | 1bb8803fbd10f4b9b481a1559bc7d5b3 MD5 | raw file
  1. /*
  2. * HID Sensor Orientation Driver
  3. * Copyright (c) 2013, Movea SA, Jean-Baptiste Maneyrol <jbmaneyrol@movea.com>
  4. * Copyright (c) 2012, Intel Corporation.
  5. * Copyright (C) 2015 XiaoMi, Inc.
  6. *
  7. * based on work from Srinivas Pandruvada <srinivas.pandruvada@intel.com>
  8. *
  9. * This program is free software; you can redistribute it and/or modify it
  10. * under the terms and conditions of the GNU General Public License,
  11. * version 2, as published by the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope it will be useful, but WITHOUT
  14. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  16. * more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along with
  19. * this program; if not, write to the Free Software Foundation, Inc.,
  20. * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  21. *
  22. */
  23. #include <linux/kernel.h>
  24. #include <linux/device.h>
  25. #include <linux/platform_device.h>
  26. #include <linux/module.h>
  27. #include <linux/interrupt.h>
  28. #include <linux/irq.h>
  29. #include <linux/slab.h>
  30. #include <linux/hid-sensor-hub.h>
  31. #include <linux/iio/iio.h>
  32. #include <linux/iio/sysfs.h>
  33. #include <linux/iio/buffer.h>
  34. #include <linux/iio/trigger_consumer.h>
  35. #include <linux/iio/triggered_buffer.h>
  36. #include "../common/hid-sensors/hid-sensor-trigger.h"
  37. /*Format: HID-SENSOR-usage_id_in_hex*/
  38. /*Usage ID from spec for Device Orientation: 0x20008a*/
  39. #define DRIVER_NAME "HID-SENSOR-20008a"
  40. #define ORIENT_ATTRIBUTES_NB (HID_SENSOR_COMMON_CHANNEL_NB + 2)
  41. enum orient_channel {
  42. CHANNEL_SCAN_INDEX_QUATERNION_X,
  43. CHANNEL_SCAN_INDEX_QUATERNION_Y,
  44. CHANNEL_SCAN_INDEX_QUATERNION_Z,
  45. CHANNEL_SCAN_INDEX_QUATERNION_W,
  46. CHANNEL_SCAN_INDEX_HEADING_ERROR,
  47. CHANNEL_SCAN_INDEX_COMMON,
  48. ORIENT_CHANNEL_NB = CHANNEL_SCAN_INDEX_COMMON +
  49. HID_SENSOR_COMMON_CHANNEL_NB,
  50. };
  51. struct orient_state {
  52. struct hid_sensor_common common;
  53. struct hid_sensor_hub_callbacks callbacks;
  54. struct hid_sensor_hub_attribute_info orient[ORIENT_ATTRIBUTES_NB];
  55. u32 orient_val[ORIENT_CHANNEL_NB];
  56. };
  57. static const u32 orient_addresses[ORIENT_ATTRIBUTES_NB] = {
  58. [0] = HID_USAGE_SENSOR_DATA_ORIENT_QUATERNION,
  59. [1] = HID_USAGE_SENSOR_DATA_ORIENT_MAGNETIC_HEADING,
  60. HID_SENSOR_COMMON_ADDRESSES(2),
  61. };
  62. /* Channel definitions */
  63. static const struct iio_chan_spec orient_channels[] = {
  64. {
  65. .type = IIO_ROT,
  66. .modified = 1,
  67. .channel2 = IIO_MOD_X,
  68. .info_mask_separate = BIT(IIO_CHAN_INFO_OFFSET) |
  69. BIT(IIO_CHAN_INFO_SCALE),
  70. .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) |
  71. BIT(IIO_CHAN_INFO_HYSTERESIS),
  72. .scan_index = CHANNEL_SCAN_INDEX_QUATERNION_X,
  73. }, {
  74. .type = IIO_ROT,
  75. .modified = 1,
  76. .channel2 = IIO_MOD_Y,
  77. .info_mask_separate = BIT(IIO_CHAN_INFO_OFFSET) |
  78. BIT(IIO_CHAN_INFO_SCALE),
  79. .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) |
  80. BIT(IIO_CHAN_INFO_HYSTERESIS),
  81. .scan_index = CHANNEL_SCAN_INDEX_QUATERNION_Y,
  82. }, {
  83. .type = IIO_ROT,
  84. .modified = 1,
  85. .channel2 = IIO_MOD_Z,
  86. .info_mask_separate = BIT(IIO_CHAN_INFO_OFFSET) |
  87. BIT(IIO_CHAN_INFO_SCALE),
  88. .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) |
  89. BIT(IIO_CHAN_INFO_HYSTERESIS),
  90. .scan_index = CHANNEL_SCAN_INDEX_QUATERNION_Z,
  91. }, {
  92. .type = IIO_ROT,
  93. .modified = 1,
  94. .channel2 = IIO_MOD_W,
  95. .info_mask_separate = BIT(IIO_CHAN_INFO_OFFSET) |
  96. BIT(IIO_CHAN_INFO_SCALE),
  97. .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) |
  98. BIT(IIO_CHAN_INFO_HYSTERESIS),
  99. .scan_index = CHANNEL_SCAN_INDEX_QUATERNION_W,
  100. }, {
  101. .type = IIO_ANGL,
  102. .info_mask_separate = BIT(IIO_CHAN_INFO_OFFSET) |
  103. BIT(IIO_CHAN_INFO_SCALE),
  104. .scan_index = CHANNEL_SCAN_INDEX_HEADING_ERROR,
  105. },
  106. HID_SENSOR_COMMON_CHANNELS(CHANNEL_SCAN_INDEX_COMMON),
  107. };
  108. /* Channel read_raw handler */
  109. static int orient_read_raw(struct iio_dev *indio_dev,
  110. struct iio_chan_spec const *chan,
  111. int *val, int *val2, long mask)
  112. {
  113. struct orient_state *state = iio_priv(indio_dev);
  114. int report_id = -1;
  115. int attr_idx;
  116. u32 num = 0;
  117. int ret_type;
  118. switch (chan->type) {
  119. case IIO_ROT:
  120. attr_idx = 0;
  121. break;
  122. case IIO_ANGL:
  123. attr_idx = 1;
  124. break;
  125. default:
  126. attr_idx = 2 + chan->channel;
  127. break;
  128. }
  129. *val = 0;
  130. *val2 = 0;
  131. switch (mask) {
  132. case 0:
  133. report_id = state->common.report_id;
  134. if (chan->modified)
  135. num = chan->channel2 - IIO_MOD_X;
  136. if (report_id >= 0)
  137. *val = sensor_hub_input_attr_get_raw_value(
  138. state->common.hsdev,
  139. state->common.usage_id,
  140. orient_addresses[attr_idx],
  141. report_id, num);
  142. else {
  143. *val = 0;
  144. return -EINVAL;
  145. }
  146. ret_type = IIO_VAL_INT;
  147. break;
  148. case IIO_CHAN_INFO_SCALE:
  149. *val = state->orient[attr_idx].units;
  150. ret_type = IIO_VAL_INT;
  151. break;
  152. case IIO_CHAN_INFO_OFFSET:
  153. *val = state->orient[attr_idx].unit_expo;
  154. ret_type = IIO_VAL_INT;
  155. break;
  156. case IIO_CHAN_INFO_SAMP_FREQ:
  157. ret_type = hid_sensor_read_samp_freq_value(&state->common,
  158. val, val2);
  159. break;
  160. case IIO_CHAN_INFO_HYSTERESIS:
  161. ret_type = hid_sensor_read_raw_value(&state->common,
  162. &state->common.sensitivity,
  163. val, val2);
  164. break;
  165. default:
  166. ret_type = -EINVAL;
  167. break;
  168. }
  169. return ret_type;
  170. }
  171. /* Channel write_raw handler */
  172. static int orient_write_raw(struct iio_dev *indio_dev,
  173. struct iio_chan_spec const *chan,
  174. int val, int val2, long mask)
  175. {
  176. struct orient_state *state = iio_priv(indio_dev);
  177. int ret = 0;
  178. switch (mask) {
  179. case IIO_CHAN_INFO_SAMP_FREQ:
  180. ret = hid_sensor_write_samp_freq_value(&state->common,
  181. val, val2);
  182. break;
  183. case IIO_CHAN_INFO_HYSTERESIS:
  184. ret = hid_sensor_write_raw_value(&state->common,
  185. &state->common.sensitivity,
  186. val, val2);
  187. break;
  188. default:
  189. ret = -EINVAL;
  190. }
  191. return ret;
  192. }
  193. static int orient_write_raw_get_fmt(struct iio_dev *indio_dev,
  194. struct iio_chan_spec const *chan,
  195. long mask)
  196. {
  197. return IIO_VAL_INT_PLUS_MICRO;
  198. }
  199. static const struct iio_info orient_info = {
  200. .driver_module = THIS_MODULE,
  201. .read_raw = &orient_read_raw,
  202. .write_raw = &orient_write_raw,
  203. .write_raw_get_fmt = &orient_write_raw_get_fmt,
  204. };
  205. /* Function to push data to buffer */
  206. static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
  207. {
  208. dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
  209. iio_push_to_buffers(indio_dev, (u8 *)data);
  210. }
  211. /* Callback handler to send event after all samples are received and captured */
  212. static int orient_proc_event(struct hid_sensor_hub_device *hsdev,
  213. unsigned usage_id, void *priv)
  214. {
  215. struct iio_dev *indio_dev = platform_get_drvdata(priv);
  216. struct orient_state *state = iio_priv(indio_dev);
  217. dev_dbg(&indio_dev->dev, "orient_proc_event [%d]\n",
  218. state->common.data_ready);
  219. if (state->common.data_ready) {
  220. hid_sensor_push_data(indio_dev, (u8 *)&state->orient_val,
  221. sizeof(state->orient_val));
  222. }
  223. return 0;
  224. }
  225. /* Capture samples in local storage */
  226. static int orient_capture_sample(struct hid_sensor_hub_device *hsdev,
  227. unsigned usage_id,
  228. size_t raw_len, size_t raw_count,
  229. char *raw_data, void *priv)
  230. {
  231. struct iio_dev *indio_dev = platform_get_drvdata(priv);
  232. struct orient_state *state = iio_priv(indio_dev);
  233. int i;
  234. u32 val;
  235. int ret = -EINVAL;
  236. switch (usage_id) {
  237. case HID_USAGE_SENSOR_DATA_ORIENT_QUATERNION:
  238. if (raw_count < 4)
  239. break;
  240. for (i = 0; i < 4; i++) {
  241. val = hid_sensor_common_read(&state->orient[0],
  242. raw_data, raw_len);
  243. state->orient_val[CHANNEL_SCAN_INDEX_QUATERNION_X + i] = val;
  244. raw_data += raw_len;
  245. }
  246. ret = 0;
  247. break;
  248. case HID_USAGE_SENSOR_DATA_ORIENT_MAGNETIC_HEADING:
  249. val = hid_sensor_common_read(&state->orient[1], raw_data,
  250. raw_len);
  251. state->orient_val[CHANNEL_SCAN_INDEX_HEADING_ERROR] = val;
  252. ret = 0;
  253. break;
  254. default:
  255. for (i = 0; i < HID_SENSOR_COMMON_CHANNEL_NB; i++)
  256. if (usage_id == orient_addresses[2 + i])
  257. break;
  258. if (i >= HID_SENSOR_COMMON_CHANNEL_NB)
  259. break;
  260. val = hid_sensor_common_read(&state->orient[2 + i], raw_data,
  261. raw_len);
  262. state->orient_val[CHANNEL_SCAN_INDEX_COMMON + i] = val;
  263. ret = 0;
  264. break;
  265. }
  266. return ret;
  267. }
  268. /* Parse report which is specific to an usage id*/
  269. static int orient_parse_report(struct platform_device *pdev,
  270. struct hid_sensor_hub_device *hsdev,
  271. struct iio_chan_spec *channels,
  272. struct orient_state *st)
  273. {
  274. int i, ret;
  275. for (i = 0; i < ORIENT_ATTRIBUTES_NB; ++i) {
  276. ret = sensor_hub_input_get_attribute_info(hsdev,
  277. HID_INPUT_REPORT,
  278. st->common.report_id, st->common.usage_id,
  279. orient_addresses[i],
  280. &st->orient[i]);
  281. if (ret < 0)
  282. return ret;
  283. dev_dbg(&pdev->dev, "orient #%x %d(%d:%u)\n",
  284. st->common.report_id, i,
  285. st->orient[i].index, st->orient[i].count);
  286. }
  287. for (i = CHANNEL_SCAN_INDEX_QUATERNION_X; i <= CHANNEL_SCAN_INDEX_QUATERNION_W; ++i)
  288. hid_sensor_adjust_channel(channels, i, IIO_ROT, &st->common,
  289. &st->orient[0]);
  290. hid_sensor_adjust_channel(channels, CHANNEL_SCAN_INDEX_HEADING_ERROR,
  291. IIO_ROT, &st->common, &st->orient[1]);
  292. for (i = 0; i < HID_SENSOR_COMMON_CHANNEL_NB; ++i)
  293. hid_sensor_adjust_channel(channels,
  294. CHANNEL_SCAN_INDEX_COMMON + i,
  295. IIO_ROT, &st->common,
  296. &st->orient[2 + i]);
  297. return 0;
  298. }
  299. /* Function to initialize the processing for usage id */
  300. static int hid_orient_probe(struct platform_device *pdev)
  301. {
  302. int ret = 0;
  303. static const char *name = "orient";
  304. struct iio_dev *indio_dev;
  305. struct orient_state *state;
  306. struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
  307. struct iio_chan_spec *channels;
  308. indio_dev = iio_device_alloc(sizeof(*state));
  309. if (indio_dev == NULL) {
  310. ret = -ENOMEM;
  311. goto error_ret;
  312. }
  313. platform_set_drvdata(pdev, indio_dev);
  314. state = iio_priv(indio_dev);
  315. ret = hid_sensor_parse_common(hsdev, pdev->id,
  316. HID_USAGE_SENSOR_TYPE_DEVICE_ORIENTATION,
  317. HID_USAGE_SENSOR_DATA_ORIENT_QUATERNION,
  318. &state->common);
  319. if (ret) {
  320. dev_err(&pdev->dev, "failed to setup common attributes\n");
  321. goto error_free_dev;
  322. }
  323. channels = kmemdup(orient_channels, sizeof(orient_channels), GFP_KERNEL);
  324. if (!channels) {
  325. ret = -ENOMEM;
  326. dev_err(&pdev->dev, "failed to duplicate channels\n");
  327. goto error_free_dev_common;
  328. }
  329. ret = orient_parse_report(pdev, hsdev, channels, state);
  330. if (ret) {
  331. dev_err(&pdev->dev, "failed to setup attributes\n");
  332. goto error_free_dev_channels;
  333. }
  334. indio_dev->channels = channels;
  335. indio_dev->num_channels = ARRAY_SIZE(orient_channels);
  336. indio_dev->dev.parent = &pdev->dev;
  337. indio_dev->info = &orient_info;
  338. indio_dev->name = name;
  339. indio_dev->modes = INDIO_DIRECT_MODE;
  340. ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
  341. NULL, NULL);
  342. if (ret) {
  343. dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
  344. goto error_free_dev_channels;
  345. }
  346. state->common.data_ready = false;
  347. ret = hid_sensor_setup_trigger(indio_dev, name, &state->common);
  348. if (ret < 0) {
  349. dev_err(&pdev->dev, "trigger setup failed\n");
  350. goto error_unreg_buffer_funcs;
  351. }
  352. ret = iio_device_register(indio_dev);
  353. if (ret) {
  354. dev_err(&pdev->dev, "device register failed\n");
  355. goto error_remove_trigger;
  356. }
  357. state->callbacks.send_event = orient_proc_event;
  358. state->callbacks.capture_sample = orient_capture_sample;
  359. state->callbacks.pdev = pdev;
  360. ret = sensor_hub_register_callback(hsdev, state->common.report_id,
  361. &state->callbacks);
  362. if (ret < 0) {
  363. dev_err(&pdev->dev, "callback reg failed\n");
  364. goto error_iio_unreg;
  365. }
  366. return ret;
  367. error_iio_unreg:
  368. iio_device_unregister(indio_dev);
  369. error_remove_trigger:
  370. hid_sensor_remove_trigger(indio_dev);
  371. error_unreg_buffer_funcs:
  372. iio_triggered_buffer_cleanup(indio_dev);
  373. error_free_dev_channels:
  374. kfree(channels);
  375. error_free_dev_common:
  376. hid_sensor_free_common(&state->common);
  377. error_free_dev:
  378. iio_device_free(indio_dev);
  379. error_ret:
  380. return ret;
  381. }
  382. /* Function to deinitialize the processing for usage id */
  383. static int hid_orient_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 orient_state *state = iio_priv(indio_dev);
  388. sensor_hub_remove_callback(hsdev, state->common.report_id);
  389. iio_device_unregister(indio_dev);
  390. hid_sensor_remove_trigger(indio_dev);
  391. iio_triggered_buffer_cleanup(indio_dev);
  392. kfree(indio_dev->channels);
  393. hid_sensor_free_common(&state->common);
  394. iio_device_free(indio_dev);
  395. return 0;
  396. }
  397. static struct platform_driver hid_orient_platform_driver = {
  398. .driver = {
  399. .name = DRIVER_NAME,
  400. .owner = THIS_MODULE,
  401. },
  402. .probe = hid_orient_probe,
  403. .remove = hid_orient_remove,
  404. };
  405. module_platform_driver(hid_orient_platform_driver);
  406. MODULE_DESCRIPTION("HID Sensor Orientation");
  407. MODULE_AUTHOR("Jean-Baptiste Maneyrol <jbmaneyrol@movea.com>");
  408. MODULE_LICENSE("GPL");