freefall.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. #include "freefall.h"
  2. static struct freefall_context *freefall_context_obj;
  3. static struct freefall_init_info *freefall_sensor_init = { 0 }; /* modified */
  4. static void freefall_early_suspend(struct early_suspend *h);
  5. static void freefall_late_resume(struct early_suspend *h);
  6. static int resume_enable_status;
  7. static struct wake_lock freefall_lock;
  8. static void notify_freefall_timeout(unsigned long);
  9. static struct freefall_context *freefall_context_alloc_object(void)
  10. {
  11. struct freefall_context *obj = kzalloc(sizeof(*obj), GFP_KERNEL);
  12. FREEFALL_LOG("freefall_context_alloc_object++++\n");
  13. if (!obj) {
  14. FREEFALL_ERR("Alloc freefall object error!\n");
  15. return NULL;
  16. }
  17. atomic_set(&obj->wake, 0);
  18. mutex_init(&obj->freefall_op_mutex);
  19. FREEFALL_LOG("freefall_context_alloc_object----\n");
  20. return obj;
  21. }
  22. static void notify_freefall_timeout(unsigned long data)
  23. {
  24. wake_unlock(&freefall_lock);
  25. }
  26. int freefall_notify(void)
  27. {
  28. int err = 0;
  29. int value = 0;
  30. struct freefall_context *cxt = NULL;
  31. cxt = freefall_context_obj;
  32. FREEFALL_LOG("freefall_notify++++\n");
  33. value = 1;
  34. input_report_rel(cxt->idev, EVENT_TYPE_FREEFALL_VALUE, value);
  35. input_sync(cxt->idev);
  36. wake_lock(&freefall_lock);
  37. mod_timer(&cxt->notify_timer, jiffies + HZ / 5);
  38. return err;
  39. }
  40. static int freefall_real_enable(int enable)
  41. {
  42. int err = 0;
  43. struct freefall_context *cxt = NULL;
  44. cxt = freefall_context_obj;
  45. if (FREEFALL_RESUME == enable)
  46. enable = resume_enable_status;
  47. if (1 == enable) {
  48. resume_enable_status = 1;
  49. if (atomic_read(&(freefall_context_obj->early_suspend)))
  50. return 0;
  51. if (false == cxt->is_active_data) {
  52. err = cxt->freefall_ctl.open_report_data(1);
  53. if (err) {
  54. err = cxt->freefall_ctl.open_report_data(1);
  55. if (err) {
  56. err = cxt->freefall_ctl.open_report_data(1);
  57. if (err) {
  58. GLG_ERR
  59. ("enable_glance_gesture enable(%d) err 3 timers = %d\n",
  60. enable, err);
  61. return err;
  62. }
  63. }
  64. }
  65. cxt->is_active_data = true;
  66. FREEFALL_LOG("enable_glance_gesture real enable\n");
  67. }
  68. } else if ((0 == enable) || (FREEFALL_SUSPEND == enable)) {
  69. if (0 == enable)
  70. resume_enable_status = 0;
  71. if (true == cxt->is_active_data) {
  72. err = cxt->freefall_ctl.open_report_data(0);
  73. if (err)
  74. GLG_ERR("enable_glance_gestureenable(%d) err = %d\n", enable, err);
  75. cxt->is_active_data = false;
  76. FREEFALL_LOG("enable_glance_gesture real disable\n");
  77. }
  78. }
  79. return err;
  80. }
  81. int freefall_enable_nodata(int enable)
  82. {
  83. struct freefall_context *cxt = NULL;
  84. cxt = freefall_context_obj;
  85. if (NULL == cxt->freefall_ctl.open_report_data) {
  86. GLG_ERR("freefall_enable_nodata:freefall ctl path is NULL\n");
  87. return -1;
  88. }
  89. if (1 == enable)
  90. cxt->is_active_nodata = true;
  91. if (0 == enable)
  92. cxt->is_active_nodata = false;
  93. freefall_real_enable(enable);
  94. return 0;
  95. }
  96. static ssize_t freefall_show_enable_nodata(struct device *dev,
  97. struct device_attribute *attr, char *buf)
  98. {
  99. struct freefall_context *cxt = NULL;
  100. cxt = freefall_context_obj;
  101. FREEFALL_LOG("freefall active: %d\n", cxt->is_active_nodata);
  102. return snprintf(buf, PAGE_SIZE, "%d\n", cxt->is_active_nodata);
  103. }
  104. static ssize_t freefall_store_enable_nodata(struct device *dev, struct device_attribute *attr,
  105. const char *buf, size_t count)
  106. {
  107. struct freefall_context *cxt = NULL;
  108. FREEFALL_LOG("freefall_store_enable nodata buf=%s\n", buf);
  109. mutex_lock(&freefall_context_obj->freefall_op_mutex);
  110. cxt = freefall_context_obj;
  111. if (NULL == cxt->freefall_ctl.open_report_data) {
  112. FREEFALL_LOG("freefall_ctl enable nodata NULL\n");
  113. mutex_unlock(&freefall_context_obj->freefall_op_mutex);
  114. return count;
  115. }
  116. if (!strncmp(buf, "1", 1))
  117. freefall_enable_nodata(1);
  118. else if (!strncmp(buf, "0", 1))
  119. freefall_enable_nodata(0);
  120. else
  121. GLG_ERR(" freefall_store enable nodata cmd error !!\n");
  122. mutex_unlock(&freefall_context_obj->freefall_op_mutex);
  123. return count;
  124. }
  125. static ssize_t freefall_store_active(struct device *dev, struct device_attribute *attr,
  126. const char *buf, size_t count)
  127. {
  128. struct freefall_context *cxt = NULL;
  129. int res = 0;
  130. int en = 0;
  131. FREEFALL_LOG("freefall_store_active buf=%s\n", buf);
  132. mutex_lock(&freefall_context_obj->freefall_op_mutex);
  133. cxt = freefall_context_obj;
  134. res = kstrtoint(buf, 10, &en);
  135. if (res != 0)
  136. FREEFALL_LOG(" freefall_store_active param error: res = %d\n", res);
  137. FREEFALL_LOG(" freefall_store_active en=%d\n", en);
  138. if (1 == en)
  139. freefall_real_enable(1);
  140. else if (0 == en)
  141. freefall_real_enable(0);
  142. else
  143. FREEFALL_ERR(" freefall_store_active error !!\n");
  144. mutex_unlock(&freefall_context_obj->freefall_op_mutex);
  145. FREEFALL_LOG(" freefall_store_active done\n");
  146. return count;
  147. }
  148. /*----------------------------------------------------------------------------*/
  149. static ssize_t freefall_show_active(struct device *dev, struct device_attribute *attr, char *buf)
  150. {
  151. struct freefall_context *cxt = NULL;
  152. cxt = freefall_context_obj;
  153. FREEFALL_LOG("freefall active: %d\n", cxt->is_active_data);
  154. return snprintf(buf, PAGE_SIZE, "%d\n", cxt->is_active_data);
  155. }
  156. static ssize_t freefall_store_delay(struct device *dev, struct device_attribute *attr, char *buf)
  157. {
  158. int len = 0;
  159. FREEFALL_LOG(" not support now\n");
  160. return len;
  161. }
  162. static ssize_t freefall_show_delay(struct device *dev, struct device_attribute *attr, char *buf)
  163. {
  164. int len = 0;
  165. FREEFALL_LOG(" not support now\n");
  166. return len;
  167. }
  168. static ssize_t freefall_store_batch(struct device *dev, struct device_attribute *attr,
  169. const char *buf, size_t count)
  170. {
  171. int len = 0;
  172. FREEFALL_LOG(" not support now\n");
  173. return len;
  174. }
  175. static ssize_t freefall_show_batch(struct device *dev, struct device_attribute *attr, char *buf)
  176. {
  177. int len = 0;
  178. FREEFALL_LOG(" not support now\n");
  179. return len;
  180. }
  181. static ssize_t freefall_store_flush(struct device *dev, struct device_attribute *attr,
  182. const char *buf, size_t count)
  183. {
  184. int len = 0;
  185. FREEFALL_LOG(" not support now\n");
  186. return len;
  187. }
  188. static ssize_t freefall_show_flush(struct device *dev, struct device_attribute *attr, char *buf)
  189. {
  190. int len = 0;
  191. FREEFALL_LOG(" not support now\n");
  192. return len;
  193. }
  194. static ssize_t freefall_show_devnum(struct device *dev, struct device_attribute *attr, char *buf)
  195. {
  196. char *devname = NULL;
  197. devname = dev_name(&freefall_context_obj->idev->dev);
  198. return snprintf(buf, PAGE_SIZE, "%s\n", devname + 5); /* TODO: why +5? */
  199. }
  200. static int freefall_remove(struct platform_device *pdev)
  201. {
  202. FREEFALL_LOG("freefall_remove\n");
  203. return 0;
  204. }
  205. static int freefall_probe(struct platform_device *pdev)
  206. {
  207. FREEFALL_LOG("freefall_probe\n");
  208. return 0;
  209. }
  210. #ifdef CONFIG_OF
  211. static const struct of_device_id freefall_of_match[] = {
  212. {.compatible = "mediatek,freefall_sensor",},
  213. {},
  214. };
  215. #endif
  216. static struct platform_driver freefall_driver = {
  217. .probe = freefall_probe,
  218. .remove = freefall_remove,
  219. .driver = {
  220. .name = "freefall_sensor",
  221. #ifdef CONFIG_OF
  222. .of_match_table = freefall_of_match,
  223. #endif
  224. }
  225. };
  226. static int freefall_real_driver_init(void)
  227. {
  228. int err = 0;
  229. FREEFALL_LOG(" freefall_real_driver_init +\n");
  230. if (0 != freefall_sensor_init) {
  231. FREEFALL_LOG(" freefall try to init driver %s\n", freefall_sensor_init->name);
  232. err = freefall_sensor_init->init();
  233. if (0 == err) {
  234. FREEFALL_LOG(" freefall real driver %s probe ok\n",
  235. freefall_sensor_init->name);
  236. }
  237. }
  238. wake_lock_init(&freefall_lock, WAKE_LOCK_SUSPEND, "freefall wakelock");
  239. init_timer(&freefall_context_obj->notify_timer);
  240. freefall_context_obj->notify_timer.expires = HZ / 5; /* 200 ms */
  241. freefall_context_obj->notify_timer.function = notify_freefall_timeout;
  242. freefall_context_obj->notify_timer.data = (unsigned long)freefall_context_obj;
  243. return err;
  244. }
  245. int freefall_driver_add(struct freefall_init_info *obj)
  246. {
  247. int err = 0;
  248. FREEFALL_FUN();
  249. FREEFALL_LOG("register glance_gesture driver for the first time\n");
  250. if (platform_driver_register(&freefall_driver))
  251. GLG_ERR("failed to register gensor driver already exist\n");
  252. if (NULL == freefall_sensor_init) {
  253. obj->platform_diver_addr = &freefall_driver;
  254. freefall_sensor_init = obj;
  255. }
  256. if (NULL == freefall_sensor_init) {
  257. GLG_ERR("GLG driver add err\n");
  258. err = -1;
  259. }
  260. return err;
  261. } EXPORT_SYMBOL_GPL(freefall_driver_add);
  262. static int freefall_misc_init(struct freefall_context *cxt)
  263. {
  264. int err = 0;
  265. /* kernel-3.10\include\linux\Miscdevice.h */
  266. /* use MISC_DYNAMIC_MINOR exceed 64 */
  267. cxt->mdev.minor = M_GLG_MISC_MINOR;
  268. cxt->mdev.name = GLG_MISC_DEV_NAME;
  269. err = misc_register(&cxt->mdev);
  270. if (err)
  271. GLG_ERR("unable to register freefall misc device!!\n");
  272. return err;
  273. }
  274. static void freefall_input_destroy(struct freefall_context *cxt)
  275. {
  276. struct input_dev *dev = cxt->idev;
  277. input_unregister_device(dev);
  278. input_free_device(dev);
  279. }
  280. static int freefall_input_init(struct freefall_context *cxt)
  281. {
  282. struct input_dev *dev;
  283. int err = 0;
  284. dev = input_allocate_device();
  285. if (NULL == dev)
  286. return -ENOMEM;
  287. dev->name = GLG_INPUTDEV_NAME;
  288. input_set_capability(dev, EV_REL, EVENT_TYPE_FREEFALL_VALUE);
  289. input_set_drvdata(dev, cxt);
  290. set_bit(EV_REL, dev->evbit);
  291. err = input_register_device(dev);
  292. if (err < 0) {
  293. input_free_device(dev);
  294. return err;
  295. }
  296. cxt->idev = dev;
  297. return 0;
  298. }
  299. DEVICE_ATTR(freefallenablenodata, S_IWUSR | S_IRUGO, freefall_show_enable_nodata,
  300. freefall_store_enable_nodata);
  301. DEVICE_ATTR(freefallactive, S_IWUSR | S_IRUGO, freefall_show_active, freefall_store_active);
  302. DEVICE_ATTR(freefalldelay, S_IWUSR | S_IRUGO, freefall_show_delay, freefall_store_delay);
  303. DEVICE_ATTR(freefallbatch, S_IWUSR | S_IRUGO, freefall_show_batch, freefall_store_batch);
  304. DEVICE_ATTR(freefallflush, S_IWUSR | S_IRUGO, freefall_show_flush, freefall_store_flush);
  305. DEVICE_ATTR(freefalldevnum, S_IWUSR | S_IRUGO, freefall_show_devnum, NULL);
  306. static struct attribute *freefall_attributes[] = {
  307. &dev_attr_freefallenablenodata.attr,
  308. &dev_attr_freefallactive.attr,
  309. &dev_attr_freefalldelay.attr,
  310. &dev_attr_freefallbatch.attr,
  311. &dev_attr_freefallflush.attr,
  312. &dev_attr_freefalldevnum.attr,
  313. NULL
  314. };
  315. static struct attribute_group freefall_attribute_group = {
  316. .attrs = freefall_attributes
  317. };
  318. int freefall_register_data_path(struct freefall_data_path *data)
  319. {
  320. struct freefall_context *cxt = NULL;
  321. cxt = freefall_context_obj;
  322. cxt->freefall_data.get_data = data->get_data;
  323. if (NULL == cxt->freefall_data.get_data) {
  324. FREEFALL_LOG("freefall register data path fail\n");
  325. return -1;
  326. }
  327. return 0;
  328. }
  329. int freefall_register_control_path(struct freefall_control_path *ctl)
  330. {
  331. struct freefall_context *cxt = NULL;
  332. int err = 0;
  333. cxt = freefall_context_obj;
  334. /* cxt->freefall_ctl.enable = ctl->enable; */
  335. /* cxt->freefall_ctl.enable_nodata = ctl->enable_nodata; */
  336. cxt->freefall_ctl.open_report_data = ctl->open_report_data;
  337. if (NULL == cxt->freefall_ctl.open_report_data) {
  338. FREEFALL_LOG("freefall register control path fail\n");
  339. return -1;
  340. }
  341. /* add misc dev for sensor hal control cmd */
  342. err = freefall_misc_init(freefall_context_obj);
  343. if (err) {
  344. GLG_ERR("unable to register freefall misc device!!\n");
  345. return -2;
  346. }
  347. err = sysfs_create_group(&freefall_context_obj->mdev.this_device->kobj,
  348. &freefall_attribute_group);
  349. if (err < 0) {
  350. GLG_ERR("unable to create freefall attribute file\n");
  351. return -3;
  352. }
  353. kobject_uevent(&freefall_context_obj->mdev.this_device->kobj, KOBJ_ADD);
  354. return 0;
  355. }
  356. static int freefall_probe(struct platform_device *pdev)
  357. {
  358. int err;
  359. FREEFALL_LOG("+++++++++++++freefall_probe!!\n");
  360. freefall_context_obj = freefall_context_alloc_object();
  361. if (!freefall_context_obj) {
  362. err = -ENOMEM;
  363. GLG_ERR("unable to allocate devobj!\n");
  364. goto exit_alloc_data_failed;
  365. }
  366. /* init real freefall driver */
  367. err = freefall_real_driver_init();
  368. if (err) {
  369. GLG_ERR("freefall real driver init fail\n");
  370. goto real_driver_init_fail;
  371. }
  372. /* init input dev */
  373. err = freefall_input_init(freefall_context_obj);
  374. if (err) {
  375. GLG_ERR("unable to register freefall input device!\n");
  376. goto exit_alloc_input_dev_failed;
  377. }
  378. #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_EARLYSUSPEND)
  379. atomic_set(&(freefall_context_obj->early_suspend), 0);
  380. freefall_context_obj->early_drv.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING - 1,
  381. freefall_context_obj->early_drv.suspend = freefall_early_suspend,
  382. freefall_context_obj->early_drv.resume = freefall_late_resume,
  383. register_early_suspend(&freefall_context_obj->early_drv);
  384. #endif /* #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_EARLYSUSPEND) */
  385. FREEFALL_LOG("----freefall_probe OK !!\n");
  386. return 0;
  387. if (err) {
  388. GLG_ERR("sysfs node creation error\n");
  389. freefall_input_destroy(freefall_context_obj);
  390. }
  391. real_driver_init_fail:
  392. exit_alloc_input_dev_failed:
  393. kfree(freefall_context_obj);
  394. exit_alloc_data_failed:
  395. FREEFALL_LOG("----freefall_probe fail !!!\n");
  396. return err;
  397. }
  398. static int freefall_remove(struct platform_device *pdev)
  399. {
  400. int err = 0;
  401. GLG_FUN();
  402. input_unregister_device(freefall_context_obj->idev);
  403. sysfs_remove_group(&freefall_context_obj->idev->dev.kobj, &freefall_attribute_group);
  404. err = misc_deregister(&freefall_context_obj->mdev);
  405. if (err)
  406. GLG_ERR("misc_deregister fail: %d\n", err);
  407. kfree(freefall_context_obj);
  408. return 0;
  409. }
  410. static void freefall_early_suspend(struct early_suspend *h)
  411. {
  412. atomic_set(&(freefall_context_obj->early_suspend), 1);
  413. if (!atomic_read(&freefall_context_obj->wake)) /* not wake up, disable in early suspend */
  414. freefall_real_enable(GLG_SUSPEND);
  415. FREEFALL_LOG(" freefall_early_suspend ok------->hwm_obj->early_suspend=%d\n",
  416. atomic_read(&(freefall_context_obj->early_suspend)));
  417. }
  418. /*----------------------------------------------------------------------------*/
  419. static void freefall_late_resume(struct early_suspend *h)
  420. {
  421. atomic_set(&(freefall_context_obj->early_suspend), 0);
  422. if (!atomic_read(&freefall_context_obj->wake) && resume_enable_status)
  423. freefall_real_enable(GLG_RESUME);
  424. FREEFALL_LOG(" freefall_late_resume ok------->hwm_obj->early_suspend=%d\n",
  425. atomic_read(&(freefall_context_obj->early_suspend)));
  426. }
  427. #if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(USE_EARLY_SUSPEND)
  428. static int freefall_suspend(struct platform_device *dev, pm_message_t state)
  429. {
  430. atomic_set(&(freefall_context_obj->suspend), 1);
  431. if (!atomic_read(&freefall_context_obj->wake))
  432. freefall_real_enable(GLG_SUSPEND);
  433. FREEFALL_LOG(" freefall_suspend ok------->hwm_obj->suspend=%d\n",
  434. atomic_read(&(freefall_context_obj->suspend)));
  435. return 0;
  436. }
  437. /*----------------------------------------------------------------------------*/
  438. static int freefall_resume(struct platform_device *dev)
  439. {
  440. atomic_set(&(freefall_context_obj->suspend), 0);
  441. if (!atomic_read(&freefall_context_obj->wake) && resume_enable_status)
  442. freefall_real_enable(GLG_RESUME);
  443. FREEFALL_LOG(" freefall_resume ok------->hwm_obj->suspend=%d\n",
  444. atomic_read(&(freefall_context_obj->suspend)));
  445. return 0;
  446. }
  447. #endif /* #if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(USE_EARLY_SUSPEND) */
  448. #ifdef CONFIG_OF
  449. static const struct of_device_id m_freefall_pl_of_match[] = {
  450. {.compatible = "mediatek,m_freefall_pl",},
  451. {},
  452. };
  453. #endif
  454. static struct platform_driver freefall_driver = {
  455. .probe = freefall_probe,
  456. .remove = freefall_remove,
  457. #if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(USE_EARLY_SUSPEND)
  458. .suspend = freefall_suspend,
  459. .resume = freefall_resume,
  460. #endif
  461. .driver = {
  462. .name = GLG_FREEFALL_DEV_NAME,
  463. #ifdef CONFIG_OF
  464. .of_match_table = m_freefall_pl_of_match,
  465. #endif
  466. }
  467. };
  468. static int __init freefall_init(void)
  469. {
  470. GLG_FUN();
  471. if (platform_driver_register(&freefall_driver)) {
  472. GLG_ERR("failed to register freefall driver\n");
  473. return -ENODEV;
  474. }
  475. return 0;
  476. }
  477. static void __exit freefall_exit(void)
  478. {
  479. platform_driver_unregister(&freefall_driver);
  480. platform_driver_unregister(&freefall_driver);
  481. }
  482. late_initcall(freefall_init);
  483. /* module_init(freefall_init); */
  484. /* module_exit(freefall_exit); */
  485. MODULE_LICENSE("GPL");
  486. MODULE_DESCRIPTION("GLG device driver");
  487. MODULE_AUTHOR("Mediatek");