ssp_ak8963c.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /*
  2. * Copyright (C) 2012, Samsung Electronics Co. Ltd. All Rights Reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. */
  15. #include "ssp.h"
  16. /*************************************************************************/
  17. /* AKM Daemon Library ioctl */
  18. /*************************************************************************/
  19. static int akmd_copy_in(unsigned int cmd, void __user *argp,
  20. void *buf, size_t buf_size)
  21. {
  22. if (!(cmd & IOC_IN))
  23. return 0;
  24. if (_IOC_SIZE(cmd) > buf_size)
  25. return -EINVAL;
  26. if (copy_from_user(buf, argp, _IOC_SIZE(cmd)))
  27. return -EFAULT;
  28. return 0;
  29. }
  30. static int akmd_copy_out(unsigned int cmd, void __user *argp,
  31. void *buf, size_t buf_size)
  32. {
  33. if (!(cmd & IOC_OUT))
  34. return 0;
  35. if (_IOC_SIZE(cmd) > buf_size)
  36. return -EINVAL;
  37. if (copy_to_user(argp, buf, _IOC_SIZE(cmd)))
  38. return -EFAULT;
  39. return 0;
  40. }
  41. static long akmd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  42. {
  43. int iRet;
  44. void __user *argp = (void __user *)arg;
  45. struct ssp_data *data = container_of(file->private_data,
  46. struct ssp_data, akmd_device);
  47. union {
  48. u8 uData[8];
  49. u8 uMagData[8];
  50. u8 uFuseData[3];
  51. int iAccData[3];
  52. } akmdbuf;
  53. iRet = akmd_copy_in(cmd, argp, akmdbuf.uData, sizeof(akmdbuf));
  54. if (iRet)
  55. return iRet;
  56. switch (cmd) {
  57. case ECS_IOCTL_GET_MAGDATA:
  58. akmdbuf.uMagData[0] = 1;
  59. akmdbuf.uMagData[1] = data->buf[GEOMAGNETIC_SENSOR].x & 0xff;
  60. akmdbuf.uMagData[2] = data->buf[GEOMAGNETIC_SENSOR].x >> 8;
  61. akmdbuf.uMagData[3] = data->buf[GEOMAGNETIC_SENSOR].y & 0xff;
  62. akmdbuf.uMagData[4] = data->buf[GEOMAGNETIC_SENSOR].y >> 8;
  63. akmdbuf.uMagData[5] = data->buf[GEOMAGNETIC_SENSOR].z & 0xff;
  64. akmdbuf.uMagData[6] = data->buf[GEOMAGNETIC_SENSOR].z >> 8;
  65. akmdbuf.uMagData[7] = 0x10;
  66. break;
  67. case ECS_IOCTL_GET_ACCDATA:
  68. akmdbuf.iAccData[0] = data->buf[ACCELEROMETER_SENSOR].x;
  69. akmdbuf.iAccData[1] = data->buf[ACCELEROMETER_SENSOR].y;
  70. akmdbuf.iAccData[2] = data->buf[ACCELEROMETER_SENSOR].z;
  71. break;
  72. case ECS_IOCTL_GET_FUSEROMDATA:
  73. akmdbuf.uFuseData[0] = data->uFuseRomData[0];
  74. akmdbuf.uFuseData[1] = data->uFuseRomData[1];
  75. akmdbuf.uFuseData[2] = data->uFuseRomData[2];
  76. break;
  77. default:
  78. return -ENOTTY;
  79. }
  80. if (iRet < 0)
  81. return iRet;
  82. return akmd_copy_out(cmd, argp, akmdbuf.uData, sizeof(akmdbuf));
  83. }
  84. static const struct file_operations akmd_fops = {
  85. .owner = THIS_MODULE,
  86. .open = nonseekable_open,
  87. .unlocked_ioctl = akmd_ioctl,
  88. };
  89. void initialize_magnetic(struct ssp_data *data)
  90. {
  91. data->akmd_device.minor = MISC_DYNAMIC_MINOR;
  92. data->akmd_device.name = "akm8963";
  93. data->akmd_device.fops = &akmd_fops;
  94. }