face_down.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. #include "face_down.h"
  2. static struct fdn_context *fdn_context_obj;
  3. static struct fdn_init_info *face_down_init = { 0 }; /* modified */
  4. static void fdn_early_suspend(struct early_suspend *h);
  5. static void fdn_late_resume(struct early_suspend *h);
  6. static int resume_enable_status;
  7. static struct fdn_context *fdn_context_alloc_object(void)
  8. {
  9. struct fdn_context *obj = kzalloc(sizeof(*obj), GFP_KERNEL);
  10. FDN_LOG("fdn_context_alloc_object++++\n");
  11. if (!obj) {
  12. FDN_ERR("Alloc fdn object error!\n");
  13. return NULL;
  14. }
  15. atomic_set(&obj->wake, 0);
  16. mutex_init(&obj->fdn_op_mutex);
  17. FDN_LOG("fdn_context_alloc_object----\n");
  18. return obj;
  19. }
  20. int fdn_notify(void)
  21. {
  22. int err = 0;
  23. int value = 0;
  24. struct fdn_context *cxt = NULL;
  25. cxt = fdn_context_obj;
  26. FDN_LOG("fdn_notify++++\n");
  27. value = 1;
  28. input_report_rel(cxt->idev, EVENT_TYPE_FDN_VALUE, value);
  29. input_sync(cxt->idev);
  30. return err;
  31. }
  32. static int fdn_real_enable(int enable)
  33. {
  34. int err = 0;
  35. struct fdn_context *cxt = NULL;
  36. cxt = fdn_context_obj;
  37. if (FDN_RESUME == enable)
  38. enable = resume_enable_status;
  39. if (1 == enable) {
  40. resume_enable_status = 1;
  41. if (atomic_read(&(fdn_context_obj->early_suspend)))
  42. return 0;
  43. if (false == cxt->is_active_data) {
  44. err = cxt->fdn_ctl.open_report_data(1);
  45. if (err) {
  46. err = cxt->fdn_ctl.open_report_data(1);
  47. if (err) {
  48. err = cxt->fdn_ctl.open_report_data(1);
  49. if (err) {
  50. FDN_ERR
  51. ("enable_face_down enable(%d) err 3 timers = %d\n",
  52. enable, err);
  53. return err;
  54. }
  55. }
  56. }
  57. cxt->is_active_data = true;
  58. FDN_LOG("enable_face_down real enable\n");
  59. }
  60. } else if ((0 == enable) || (FDN_SUSPEND == enable)) {
  61. if (0 == enable)
  62. resume_enable_status = 0;
  63. if (true == cxt->is_active_data) {
  64. err = cxt->fdn_ctl.open_report_data(0);
  65. if (err)
  66. FDN_ERR("enable_face_downenable(%d) err = %d\n", enable, err);
  67. cxt->is_active_data = false;
  68. FDN_LOG("enable_face_down real disable\n");
  69. }
  70. }
  71. return err;
  72. }
  73. int fdn_enable_nodata(int enable)
  74. {
  75. struct fdn_context *cxt = NULL;
  76. cxt = fdn_context_obj;
  77. if (NULL == cxt->fdn_ctl.open_report_data) {
  78. FDN_ERR("fdn_enable_nodata:fdn ctl path is NULL\n");
  79. return -1;
  80. }
  81. if (1 == enable)
  82. cxt->is_active_nodata = true;
  83. if (0 == enable)
  84. cxt->is_active_nodata = false;
  85. fdn_real_enable(enable);
  86. return 0;
  87. }
  88. static ssize_t fdn_show_enable_nodata(struct device *dev, struct device_attribute *attr, char *buf)
  89. {
  90. struct fdn_context *cxt = NULL;
  91. cxt = fdn_context_obj;
  92. FDN_LOG("fdn active: %d\n", cxt->is_active_nodata);
  93. return snprintf(buf, PAGE_SIZE, "%d\n", cxt->is_active_nodata);
  94. }
  95. static ssize_t fdn_store_enable_nodata(struct device *dev, struct device_attribute *attr,
  96. const char *buf, size_t count)
  97. {
  98. struct fdn_context *cxt = NULL;
  99. FDN_LOG("fdn_store_enable nodata buf=%s\n", buf);
  100. mutex_lock(&fdn_context_obj->fdn_op_mutex);
  101. cxt = fdn_context_obj;
  102. if (NULL == cxt->fdn_ctl.open_report_data) {
  103. FDN_LOG("fdn_ctl enable nodata NULL\n");
  104. mutex_unlock(&fdn_context_obj->fdn_op_mutex);
  105. return count;
  106. }
  107. if (!strncmp(buf, "1", 1))
  108. fdn_enable_nodata(1);
  109. else if (!strncmp(buf, "0", 1))
  110. fdn_enable_nodata(0);
  111. else
  112. FDN_ERR(" fdn_store enable nodata cmd error !!\n");
  113. mutex_unlock(&fdn_context_obj->fdn_op_mutex);
  114. return count;
  115. }
  116. static ssize_t fdn_store_active(struct device *dev, struct device_attribute *attr,
  117. const char *buf, size_t count)
  118. {
  119. struct fdn_context *cxt = NULL;
  120. int res = 0;
  121. int en = 0;
  122. FDN_LOG("fdn_store_active buf=%s\n", buf);
  123. mutex_lock(&fdn_context_obj->fdn_op_mutex);
  124. cxt = fdn_context_obj;
  125. res = kstrtoint(buf, 10, &en);
  126. if (res != 0)
  127. FDN_LOG(" fdn_store_active param error: res = %d\n", res);
  128. FDN_LOG(" fdn_store_active en=%d\n", en);
  129. if (1 == en)
  130. fdn_real_enable(1);
  131. else if (0 == en)
  132. fdn_real_enable(0);
  133. else
  134. FDN_ERR(" fdn_store_active error !!\n");
  135. mutex_unlock(&fdn_context_obj->fdn_op_mutex);
  136. FDN_LOG(" fdn_store_active done\n");
  137. return count;
  138. }
  139. /*----------------------------------------------------------------------------*/
  140. static ssize_t fdn_show_active(struct device *dev, struct device_attribute *attr, char *buf)
  141. {
  142. struct fdn_context *cxt = NULL;
  143. cxt = fdn_context_obj;
  144. FDN_LOG("fdn active: %d\n", cxt->is_active_data);
  145. return snprintf(buf, PAGE_SIZE, "%d\n", cxt->is_active_data);
  146. }
  147. static ssize_t fdn_store_delay(struct device *dev, struct device_attribute *attr, char *buf)
  148. {
  149. int len = 0;
  150. FDN_LOG(" not support now\n");
  151. return len;
  152. }
  153. static ssize_t fdn_show_delay(struct device *dev, struct device_attribute *attr, char *buf)
  154. {
  155. int len = 0;
  156. FDN_LOG(" not support now\n");
  157. return len;
  158. }
  159. static ssize_t fdn_store_batch(struct device *dev, struct device_attribute *attr,
  160. const char *buf, size_t count)
  161. {
  162. int len = 0;
  163. FDN_LOG(" not support now\n");
  164. return len;
  165. }
  166. static ssize_t fdn_show_batch(struct device *dev, struct device_attribute *attr, char *buf)
  167. {
  168. int len = 0;
  169. FDN_LOG(" not support now\n");
  170. return len;
  171. }
  172. static ssize_t fdn_store_flush(struct device *dev, struct device_attribute *attr,
  173. const char *buf, size_t count)
  174. {
  175. int len = 0;
  176. FDN_LOG(" not support now\n");
  177. return len;
  178. }
  179. static ssize_t fdn_show_flush(struct device *dev, struct device_attribute *attr, char *buf)
  180. {
  181. int len = 0;
  182. FDN_LOG(" not support now\n");
  183. return len;
  184. }
  185. static ssize_t fdn_show_devnum(struct device *dev, struct device_attribute *attr, char *buf)
  186. {
  187. char *devname = NULL;
  188. devname = dev_name(&fdn_context_obj->idev->dev);
  189. return snprintf(buf, PAGE_SIZE, "%s\n", devname + 5); /* TODO: why +5? */
  190. }
  191. static int face_down_remove(struct platform_device *pdev)
  192. {
  193. FDN_LOG("face_down_remove\n");
  194. return 0;
  195. }
  196. static int face_down_probe(struct platform_device *pdev)
  197. {
  198. FDN_LOG("face_down_probe\n");
  199. return 0;
  200. }
  201. #ifdef CONFIG_OF
  202. static const struct of_device_id face_down_of_match[] = {
  203. {.compatible = "mediatek,face_down",},
  204. {},
  205. };
  206. #endif
  207. static struct platform_driver face_down_driver = {
  208. .probe = face_down_probe,
  209. .remove = face_down_remove,
  210. .driver = {
  211. .name = "face_down",
  212. #ifdef CONFIG_OF
  213. .of_match_table = face_down_of_match,
  214. #endif
  215. }
  216. };
  217. static int fdn_real_driver_init(void)
  218. {
  219. int err = 0;
  220. FDN_LOG(" fdn_real_driver_init +\n");
  221. if (0 != face_down_init) {
  222. FDN_LOG(" fdn try to init driver %s\n", face_down_init->name);
  223. err = face_down_init->init();
  224. if (0 == err)
  225. FDN_LOG(" fdn real driver %s probe ok\n", face_down_init->name);
  226. }
  227. return err;
  228. }
  229. int fdn_driver_add(struct fdn_init_info *obj)
  230. {
  231. int err = 0;
  232. FDN_FUN();
  233. FDN_LOG("register face_down driver for the first time\n");
  234. if (platform_driver_register(&face_down_driver))
  235. FDN_ERR("failed to register gensor driver already exist\n");
  236. if (NULL == face_down_init) {
  237. obj->platform_diver_addr = &face_down_driver;
  238. face_down_init = obj;
  239. }
  240. if (NULL == face_down_init) {
  241. FDN_ERR("FDN driver add err\n");
  242. err = -1;
  243. }
  244. return err;
  245. } EXPORT_SYMBOL_GPL(fdn_driver_add);
  246. static int fdn_misc_init(struct fdn_context *cxt)
  247. {
  248. int err = 0;
  249. /* kernel-3.10\include\linux\Miscdevice.h */
  250. /* use MISC_DYNAMIC_MINOR exceed 64 */
  251. cxt->mdev.minor = M_FDN_MISC_MINOR;
  252. cxt->mdev.name = FDN_MISC_DEV_NAME;
  253. err = misc_register(&cxt->mdev);
  254. if (err)
  255. FDN_ERR("unable to register fdn misc device!!\n");
  256. return err;
  257. }
  258. static void fdn_input_destroy(struct fdn_context *cxt)
  259. {
  260. struct input_dev *dev = cxt->idev;
  261. input_unregister_device(dev);
  262. input_free_device(dev);
  263. }
  264. static int fdn_input_init(struct fdn_context *cxt)
  265. {
  266. struct input_dev *dev;
  267. int err = 0;
  268. dev = input_allocate_device();
  269. if (NULL == dev)
  270. return -ENOMEM;
  271. dev->name = FDN_INPUTDEV_NAME;
  272. input_set_capability(dev, EV_REL, EVENT_TYPE_FDN_VALUE);
  273. input_set_drvdata(dev, cxt);
  274. set_bit(EV_REL, dev->evbit);
  275. err = input_register_device(dev);
  276. if (err < 0) {
  277. input_free_device(dev);
  278. return err;
  279. }
  280. cxt->idev = dev;
  281. return 0;
  282. }
  283. DEVICE_ATTR(fdnenablenodata, S_IWUSR | S_IRUGO, fdn_show_enable_nodata, fdn_store_enable_nodata);
  284. DEVICE_ATTR(fdnactive, S_IWUSR | S_IRUGO, fdn_show_active, fdn_store_active);
  285. DEVICE_ATTR(fdndelay, S_IWUSR | S_IRUGO, fdn_show_delay, fdn_store_delay);
  286. DEVICE_ATTR(fdnbatch, S_IWUSR | S_IRUGO, fdn_show_batch, fdn_store_batch);
  287. DEVICE_ATTR(fdnflush, S_IWUSR | S_IRUGO, fdn_show_flush, fdn_store_flush);
  288. DEVICE_ATTR(fdndevnum, S_IWUSR | S_IRUGO, fdn_show_devnum, NULL);
  289. static struct attribute *fdn_attributes[] = {
  290. &dev_attr_fdnenablenodata.attr,
  291. &dev_attr_fdnactive.attr,
  292. &dev_attr_fdndelay.attr,
  293. &dev_attr_fdnbatch.attr,
  294. &dev_attr_fdnflush.attr,
  295. &dev_attr_fdndevnum.attr,
  296. NULL
  297. };
  298. static struct attribute_group fdn_attribute_group = {
  299. .attrs = fdn_attributes
  300. };
  301. int fdn_register_data_path(struct fdn_data_path *data)
  302. {
  303. struct fdn_context *cxt = NULL;
  304. cxt = fdn_context_obj;
  305. cxt->fdn_data.get_data = data->get_data;
  306. if (NULL == cxt->fdn_data.get_data) {
  307. FDN_LOG("fdn register data path fail\n");
  308. return -1;
  309. }
  310. return 0;
  311. }
  312. int fdn_register_control_path(struct fdn_control_path *ctl)
  313. {
  314. struct fdn_context *cxt = NULL;
  315. int err = 0;
  316. cxt = fdn_context_obj;
  317. /* cxt->fdn_ctl.enable = ctl->enable; */
  318. /* cxt->fdn_ctl.enable_nodata = ctl->enable_nodata; */
  319. cxt->fdn_ctl.open_report_data = ctl->open_report_data;
  320. if (NULL == cxt->fdn_ctl.open_report_data) {
  321. FDN_LOG("fdn register control path fail\n");
  322. return -1;
  323. }
  324. /* add misc dev for sensor hal control cmd */
  325. err = fdn_misc_init(fdn_context_obj);
  326. if (err) {
  327. FDN_ERR("unable to register fdn misc device!!\n");
  328. return -2;
  329. }
  330. err = sysfs_create_group(&fdn_context_obj->mdev.this_device->kobj, &fdn_attribute_group);
  331. if (err < 0) {
  332. FDN_ERR("unable to create fdn attribute file\n");
  333. return -3;
  334. }
  335. kobject_uevent(&fdn_context_obj->mdev.this_device->kobj, KOBJ_ADD);
  336. return 0;
  337. }
  338. static int fdn_probe(struct platform_device *pdev)
  339. {
  340. int err;
  341. FDN_LOG("+++++++++++++fdn_probe!!\n");
  342. fdn_context_obj = fdn_context_alloc_object();
  343. if (!fdn_context_obj) {
  344. err = -ENOMEM;
  345. FDN_ERR("unable to allocate devobj!\n");
  346. goto exit_alloc_data_failed;
  347. }
  348. /* init real fdn driver */
  349. err = fdn_real_driver_init();
  350. if (err) {
  351. FDN_ERR("fdn real driver init fail\n");
  352. goto real_driver_init_fail;
  353. }
  354. /* init input dev */
  355. err = fdn_input_init(fdn_context_obj);
  356. if (err) {
  357. FDN_ERR("unable to register fdn input device!\n");
  358. goto exit_alloc_input_dev_failed;
  359. }
  360. #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_EARLYSUSPEND)
  361. atomic_set(&(fdn_context_obj->early_suspend), 0);
  362. fdn_context_obj->early_drv.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING - 1,
  363. fdn_context_obj->early_drv.suspend = fdn_early_suspend,
  364. fdn_context_obj->early_drv.resume = fdn_late_resume,
  365. register_early_suspend(&fdn_context_obj->early_drv);
  366. #endif /* #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_EARLYSUSPEND) */
  367. FDN_LOG("----fdn_probe OK !!\n");
  368. return 0;
  369. if (err) {
  370. FDN_ERR("sysfs node creation error\n");
  371. fdn_input_destroy(fdn_context_obj);
  372. }
  373. real_driver_init_fail:
  374. exit_alloc_input_dev_failed:
  375. kfree(fdn_context_obj);
  376. exit_alloc_data_failed:
  377. FDN_LOG("----fdn_probe fail !!!\n");
  378. return err;
  379. }
  380. static int fdn_remove(struct platform_device *pdev)
  381. {
  382. int err = 0;
  383. FDN_FUN(f);
  384. input_unregister_device(fdn_context_obj->idev);
  385. sysfs_remove_group(&fdn_context_obj->idev->dev.kobj, &fdn_attribute_group);
  386. err = misc_deregister(&fdn_context_obj->mdev);
  387. if (err)
  388. FDN_ERR("misc_deregister fail: %d\n", err);
  389. kfree(fdn_context_obj);
  390. return 0;
  391. }
  392. static void fdn_early_suspend(struct early_suspend *h)
  393. {
  394. atomic_set(&(fdn_context_obj->early_suspend), 1);
  395. if (!atomic_read(&fdn_context_obj->wake))
  396. fdn_real_enable(FDN_SUSPEND);
  397. FDN_LOG(" fdn_early_suspend ok------->hwm_obj->early_suspend=%d\n",
  398. atomic_read(&(fdn_context_obj->early_suspend)));
  399. }
  400. /*----------------------------------------------------------------------------*/
  401. static void fdn_late_resume(struct early_suspend *h)
  402. {
  403. atomic_set(&(fdn_context_obj->early_suspend), 0);
  404. if (!atomic_read(&fdn_context_obj->wake) && resume_enable_status)
  405. fdn_real_enable(FDN_RESUME);
  406. FDN_LOG(" fdn_late_resume ok------->hwm_obj->early_suspend=%d\n",
  407. atomic_read(&(fdn_context_obj->early_suspend)));
  408. }
  409. #if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(USE_EARLY_SUSPEND)
  410. static int fdn_suspend(struct platform_device *dev, pm_message_t state)
  411. {
  412. atomic_set(&(fdn_context_obj->suspend), 1);
  413. if (!atomic_read(&fdn_context_obj->wake))
  414. fdn_real_enable(FDN_SUSPEND);
  415. FDN_LOG(" fdn_suspend ok------->hwm_obj->suspend=%d\n",
  416. atomic_read(&(fdn_context_obj->suspend)));
  417. return 0;
  418. }
  419. /*----------------------------------------------------------------------------*/
  420. static int fdn_resume(struct platform_device *dev)
  421. {
  422. atomic_set(&(fdn_context_obj->suspend), 0);
  423. if (!atomic_read(&fdn_context_obj->wake) && resume_enable_status)
  424. fdn_real_enable(FDN_RESUME);
  425. FDN_LOG(" fdn_resume ok------->hwm_obj->suspend=%d\n",
  426. atomic_read(&(fdn_context_obj->suspend)));
  427. return 0;
  428. }
  429. #endif /* #if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(USE_EARLY_SUSPEND) */
  430. #ifdef CONFIG_OF
  431. static const struct of_device_id m_fdn_pl_of_match[] = {
  432. {.compatible = "mediatek,m_fdn_pl",},
  433. {},
  434. };
  435. #endif
  436. static struct platform_driver fdn_driver = {
  437. .probe = fdn_probe,
  438. .remove = fdn_remove,
  439. #if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(USE_EARLY_SUSPEND)
  440. .suspend = fdn_suspend,
  441. .resume = fdn_resume,
  442. #endif
  443. .driver = {
  444. .name = FDN_PL_DEV_NAME,
  445. #ifdef CONFIG_OF
  446. .of_match_table = m_fdn_pl_of_match,
  447. #endif
  448. }
  449. };
  450. static int __init fdn_init(void)
  451. {
  452. FDN_FUN();
  453. if (platform_driver_register(&fdn_driver)) {
  454. FDN_ERR("failed to register fdn driver\n");
  455. return -ENODEV;
  456. }
  457. return 0;
  458. }
  459. static void __exit fdn_exit(void)
  460. {
  461. platform_driver_unregister(&fdn_driver);
  462. platform_driver_unregister(&face_down_driver);
  463. }
  464. late_initcall(fdn_init);
  465. /* module_init(fdn_init); */
  466. /* module_exit(fdn_exit); */
  467. MODULE_LICENSE("GPL");
  468. MODULE_DESCRIPTION("FDN device driver");
  469. MODULE_AUTHOR("Mediatek");