pick_up.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. #include "pick_up.h"
  2. static struct pkup_context *pkup_context_obj;
  3. static struct pkup_init_info *pick_up_init = { 0 }; /* modified */
  4. static void pkup_early_suspend(struct early_suspend *h);
  5. static void pkup_late_resume(struct early_suspend *h);
  6. static int resume_enable_status;
  7. static struct pkup_context *pkup_context_alloc_object(void)
  8. {
  9. struct pkup_context *obj = kzalloc(sizeof(*obj), GFP_KERNEL);
  10. PKUP_LOG("pkup_context_alloc_object++++\n");
  11. if (!obj) {
  12. PKUP_ERR("Alloc pkup object error!\n");
  13. return NULL;
  14. }
  15. atomic_set(&obj->wake, 0);
  16. mutex_init(&obj->pkup_op_mutex);
  17. PKUP_LOG("pkup_context_alloc_object----\n");
  18. return obj;
  19. }
  20. int pkup_notify(void)
  21. {
  22. int err = 0;
  23. int value = 0;
  24. struct pkup_context *cxt = NULL;
  25. cxt = pkup_context_obj;
  26. PKUP_LOG("pkup_notify++++\n");
  27. value = 1;
  28. input_report_rel(cxt->idev, EVENT_TYPE_PKUP_VALUE, value);
  29. input_sync(cxt->idev);
  30. return err;
  31. }
  32. static int pkup_real_enable(int enable)
  33. {
  34. int err = 0;
  35. struct pkup_context *cxt = NULL;
  36. cxt = pkup_context_obj;
  37. if (PKUP_RESUME == enable)
  38. enable = resume_enable_status;
  39. if (1 == enable) {
  40. resume_enable_status = 1;
  41. if (atomic_read(&(pkup_context_obj->early_suspend))) /* not allow to enable under suspend */
  42. return 0;
  43. if (false == cxt->is_active_data) {
  44. err = cxt->pkup_ctl.open_report_data(1);
  45. if (err) {
  46. err = cxt->pkup_ctl.open_report_data(1);
  47. if (err) {
  48. err = cxt->pkup_ctl.open_report_data(1);
  49. if (err) {
  50. PKUP_ERR
  51. ("enable_pick_up enable(%d) err 3 timers = %d\n",
  52. enable, err);
  53. return err;
  54. }
  55. }
  56. }
  57. cxt->is_active_data = true;
  58. PKUP_LOG("enable_pick_up real enable\n");
  59. }
  60. } else if ((0 == enable) || (PKUP_SUSPEND == enable)) {
  61. if (0 == enable)
  62. resume_enable_status = 0;
  63. if (true == cxt->is_active_data) {
  64. err = cxt->pkup_ctl.open_report_data(0);
  65. if (err)
  66. PKUP_ERR("enable_pick_upenable(%d) err = %d\n", enable, err);
  67. cxt->is_active_data = false;
  68. PKUP_LOG("enable_pick_up real disable\n");
  69. }
  70. }
  71. return err;
  72. }
  73. int pkup_enable_nodata(int enable)
  74. {
  75. struct pkup_context *cxt = NULL;
  76. cxt = pkup_context_obj;
  77. if (NULL == cxt->pkup_ctl.open_report_data) {
  78. PKUP_ERR("pkup_enable_nodata:pkup 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. pkup_real_enable(enable);
  86. return 0;
  87. }
  88. static ssize_t pkup_show_enable_nodata(struct device *dev, struct device_attribute *attr, char *buf)
  89. {
  90. struct pkup_context *cxt = NULL;
  91. cxt = pkup_context_obj;
  92. PKUP_LOG("pkup active: %d\n", cxt->is_active_nodata);
  93. return snprintf(buf, PAGE_SIZE, "%d\n", cxt->is_active_nodata);
  94. }
  95. static ssize_t pkup_store_enable_nodata(struct device *dev, struct device_attribute *attr,
  96. const char *buf, size_t count)
  97. {
  98. struct pkup_context *cxt = NULL;
  99. PKUP_LOG("pkup_store_enable nodata buf=%s\n", buf);
  100. mutex_lock(&pkup_context_obj->pkup_op_mutex);
  101. cxt = pkup_context_obj;
  102. if (NULL == cxt->pkup_ctl.open_report_data) {
  103. PKUP_LOG("pkup_ctl enable nodata NULL\n");
  104. mutex_unlock(&pkup_context_obj->pkup_op_mutex);
  105. return count;
  106. }
  107. if (!strncmp(buf, "1", 1))
  108. pkup_enable_nodata(1);
  109. else if (!strncmp(buf, "0", 1))
  110. pkup_enable_nodata(0);
  111. else
  112. PKUP_ERR(" pkup_store enable nodata cmd error !!\n");
  113. mutex_unlock(&pkup_context_obj->pkup_op_mutex);
  114. return count;
  115. }
  116. static ssize_t pkup_store_active(struct device *dev, struct device_attribute *attr,
  117. const char *buf, size_t count)
  118. {
  119. struct pkup_context *cxt = NULL;
  120. int res = 0;
  121. int en = 0;
  122. PKUP_LOG("pkup_store_active buf=%s\n", buf);
  123. mutex_lock(&pkup_context_obj->pkup_op_mutex);
  124. cxt = pkup_context_obj;
  125. res = kstrtoint(buf, 10, &en);
  126. if (res != 0)
  127. PKUP_LOG(" pkup_store_active param error: res = %d\n", res);
  128. PKUP_LOG(" pkup_store_active en=%d\n", en);
  129. if (1 == en)
  130. pkup_real_enable(1);
  131. else if (0 == en)
  132. pkup_real_enable(0);
  133. else
  134. PKUP_ERR(" pkup_store_active error !!\n");
  135. mutex_unlock(&pkup_context_obj->pkup_op_mutex);
  136. PKUP_LOG(" pkup_store_active done\n");
  137. return count;
  138. }
  139. /*----------------------------------------------------------------------------*/
  140. static ssize_t pkup_show_active(struct device *dev, struct device_attribute *attr, char *buf)
  141. {
  142. struct pkup_context *cxt = NULL;
  143. cxt = pkup_context_obj;
  144. PKUP_LOG("pkup active: %d\n", cxt->is_active_data);
  145. return snprintf(buf, PAGE_SIZE, "%d\n", cxt->is_active_data);
  146. }
  147. static ssize_t pkup_store_delay(struct device *dev, struct device_attribute *attr, char *buf)
  148. {
  149. int len = 0;
  150. PKUP_LOG(" not support now\n");
  151. return len;
  152. }
  153. static ssize_t pkup_show_delay(struct device *dev, struct device_attribute *attr, char *buf)
  154. {
  155. int len = 0;
  156. PKUP_LOG(" not support now\n");
  157. return len;
  158. }
  159. static ssize_t pkup_store_batch(struct device *dev, struct device_attribute *attr,
  160. const char *buf, size_t count)
  161. {
  162. int len = 0;
  163. PKUP_LOG(" not support now\n");
  164. return len;
  165. }
  166. static ssize_t pkup_show_batch(struct device *dev, struct device_attribute *attr, char *buf)
  167. {
  168. int len = 0;
  169. PKUP_LOG(" not support now\n");
  170. return len;
  171. }
  172. static ssize_t pkup_store_flush(struct device *dev, struct device_attribute *attr,
  173. const char *buf, size_t count)
  174. {
  175. int len = 0;
  176. PKUP_LOG(" not support now\n");
  177. return len;
  178. }
  179. static ssize_t pkup_show_flush(struct device *dev, struct device_attribute *attr, char *buf)
  180. {
  181. int len = 0;
  182. PKUP_LOG(" not support now\n");
  183. return len;
  184. }
  185. static ssize_t pkup_show_devnum(struct device *dev, struct device_attribute *attr, char *buf)
  186. {
  187. char *devname = NULL;
  188. devname = dev_name(&pkup_context_obj->idev->dev);
  189. return snprintf(buf, PAGE_SIZE, "%s\n", devname + 5); /* TODO: why +5? */
  190. }
  191. static int pick_up_remove(struct platform_device *pdev)
  192. {
  193. PKUP_LOG("pick_up_remove\n");
  194. return 0;
  195. }
  196. static int pick_up_probe(struct platform_device *pdev)
  197. {
  198. PKUP_LOG("pick_up_probe\n");
  199. return 0;
  200. }
  201. #ifdef CONFIG_OF
  202. static const struct of_device_id pick_up_of_match[] = {
  203. {.compatible = "mediatek,pick_up",},
  204. {},
  205. };
  206. #endif
  207. static struct platform_driver pick_up_driver = {
  208. .probe = pick_up_probe,
  209. .remove = pick_up_remove,
  210. .driver = {
  211. .name = "pick_up",
  212. #ifdef CONFIG_OF
  213. .of_match_table = pick_up_of_match,
  214. #endif
  215. }
  216. };
  217. static int pkup_real_driver_init(void)
  218. {
  219. int err = 0;
  220. PKUP_LOG(" pkup_real_driver_init +\n");
  221. if (0 != pick_up_init) {
  222. PKUP_LOG(" pkup try to init driver %s\n", pick_up_init->name);
  223. err = pick_up_init->init();
  224. if (0 == err)
  225. PKUP_LOG(" pkup real driver %s probe ok\n", pick_up_init->name);
  226. }
  227. return err;
  228. }
  229. int pkup_driver_add(struct pkup_init_info *obj)
  230. {
  231. int err = 0;
  232. PKUP_FUN();
  233. PKUP_LOG("register pick_up driver for the first time\n");
  234. if (platform_driver_register(&pick_up_driver))
  235. PKUP_ERR("failed to register gensor driver already exist\n");
  236. if (NULL == pick_up_init) {
  237. obj->platform_diver_addr = &pick_up_driver;
  238. pick_up_init = obj;
  239. }
  240. if (NULL == pick_up_init) {
  241. PKUP_ERR("PKUP driver add err\n");
  242. err = -1;
  243. }
  244. return err;
  245. } EXPORT_SYMBOL_GPL(pkup_driver_add);
  246. static int pkup_misc_init(struct pkup_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_PKUP_MISC_MINOR;
  252. cxt->mdev.name = PKUP_MISC_DEV_NAME;
  253. err = misc_register(&cxt->mdev);
  254. if (err)
  255. PKUP_ERR("unable to register pkup misc device!!\n");
  256. return err;
  257. }
  258. static void pkup_input_destroy(struct pkup_context *cxt)
  259. {
  260. struct input_dev *dev = cxt->idev;
  261. input_unregister_device(dev);
  262. input_free_device(dev);
  263. }
  264. static int pkup_input_init(struct pkup_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 = PKUP_INPUTDEV_NAME;
  272. input_set_capability(dev, EV_REL, EVENT_TYPE_PKUP_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(pkupenablenodata, S_IWUSR | S_IRUGO, pkup_show_enable_nodata, pkup_store_enable_nodata);
  284. DEVICE_ATTR(pkupactive, S_IWUSR | S_IRUGO, pkup_show_active, pkup_store_active);
  285. DEVICE_ATTR(pkupdelay, S_IWUSR | S_IRUGO, pkup_show_delay, pkup_store_delay);
  286. DEVICE_ATTR(pkupbatch, S_IWUSR | S_IRUGO, pkup_show_batch, pkup_store_batch);
  287. DEVICE_ATTR(pkupflush, S_IWUSR | S_IRUGO, pkup_show_flush, pkup_store_flush);
  288. DEVICE_ATTR(pkupdevnum, S_IWUSR | S_IRUGO, pkup_show_devnum, NULL);
  289. static struct attribute *pkup_attributes[] = {
  290. &dev_attr_pkupenablenodata.attr,
  291. &dev_attr_pkupactive.attr,
  292. &dev_attr_pkupdelay.attr,
  293. &dev_attr_pkupbatch.attr,
  294. &dev_attr_pkupflush.attr,
  295. &dev_attr_pkupdevnum.attr,
  296. NULL
  297. };
  298. static struct attribute_group pkup_attribute_group = {
  299. .attrs = pkup_attributes
  300. };
  301. int pkup_register_data_path(struct pkup_data_path *data)
  302. {
  303. struct pkup_context *cxt = NULL;
  304. cxt = pkup_context_obj;
  305. cxt->pkup_data.get_data = data->get_data;
  306. if (NULL == cxt->pkup_data.get_data) {
  307. PKUP_LOG("pkup register data path fail\n");
  308. return -1;
  309. }
  310. return 0;
  311. }
  312. int pkup_register_control_path(struct pkup_control_path *ctl)
  313. {
  314. struct pkup_context *cxt = NULL;
  315. int err = 0;
  316. cxt = pkup_context_obj;
  317. /* cxt->pkup_ctl.enable = ctl->enable; */
  318. /* cxt->pkup_ctl.enable_nodata = ctl->enable_nodata; */
  319. cxt->pkup_ctl.open_report_data = ctl->open_report_data;
  320. if (NULL == cxt->pkup_ctl.open_report_data) {
  321. PKUP_LOG("pkup register control path fail\n");
  322. return -1;
  323. }
  324. /* add misc dev for sensor hal control cmd */
  325. err = pkup_misc_init(pkup_context_obj);
  326. if (err) {
  327. PKUP_ERR("unable to register pkup misc device!!\n");
  328. return -2;
  329. }
  330. err = sysfs_create_group(&pkup_context_obj->mdev.this_device->kobj, &pkup_attribute_group);
  331. if (err < 0) {
  332. PKUP_ERR("unable to create pkup attribute file\n");
  333. return -3;
  334. }
  335. kobject_uevent(&pkup_context_obj->mdev.this_device->kobj, KOBJ_ADD);
  336. return 0;
  337. }
  338. static int pkup_probe(struct platform_device *pdev)
  339. {
  340. int err;
  341. PKUP_LOG("+++++++++++++pkup_probe!!\n");
  342. pkup_context_obj = pkup_context_alloc_object();
  343. if (!pkup_context_obj) {
  344. err = -ENOMEM;
  345. PKUP_ERR("unable to allocate devobj!\n");
  346. goto exit_alloc_data_failed;
  347. }
  348. /* init real pkup driver */
  349. err = pkup_real_driver_init();
  350. if (err) {
  351. PKUP_ERR("pkup real driver init fail\n");
  352. goto real_driver_init_fail;
  353. }
  354. /* init input dev */
  355. err = pkup_input_init(pkup_context_obj);
  356. if (err) {
  357. PKUP_ERR("unable to register pkup input device!\n");
  358. goto exit_alloc_input_dev_failed;
  359. }
  360. #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_EARLYSUSPEND)
  361. atomic_set(&(pkup_context_obj->early_suspend), 0);
  362. pkup_context_obj->early_drv.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING - 1,
  363. pkup_context_obj->early_drv.suspend = pkup_early_suspend,
  364. pkup_context_obj->early_drv.resume = pkup_late_resume,
  365. register_early_suspend(&pkup_context_obj->early_drv);
  366. #endif /* #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_EARLYSUSPEND) */
  367. PKUP_LOG("----pkup_probe OK !!\n");
  368. return 0;
  369. if (err) {
  370. PKUP_ERR("sysfs node creation error\n");
  371. pkup_input_destroy(pkup_context_obj);
  372. }
  373. real_driver_init_fail:
  374. exit_alloc_input_dev_failed:
  375. kfree(pkup_context_obj);
  376. exit_alloc_data_failed:
  377. PKUP_LOG("----pkup_probe fail !!!\n");
  378. return err;
  379. }
  380. static int pkup_remove(struct platform_device *pdev)
  381. {
  382. int err = 0;
  383. PKUP_FUN(f);
  384. input_unregister_device(pkup_context_obj->idev);
  385. sysfs_remove_group(&pkup_context_obj->idev->dev.kobj, &pkup_attribute_group);
  386. err = misc_deregister(&pkup_context_obj->mdev);
  387. if (err)
  388. PKUP_ERR("misc_deregister fail: %d\n", err);
  389. kfree(pkup_context_obj);
  390. return 0;
  391. }
  392. static void pkup_early_suspend(struct early_suspend *h)
  393. {
  394. atomic_set(&(pkup_context_obj->early_suspend), 1);
  395. if (!atomic_read(&pkup_context_obj->wake)) /* not wake up, disable in early suspend */
  396. pkup_real_enable(PKUP_SUSPEND);
  397. PKUP_LOG(" pkup_early_suspend ok------->hwm_obj->early_suspend=%d\n",
  398. atomic_read(&(pkup_context_obj->early_suspend)));
  399. }
  400. /*----------------------------------------------------------------------------*/
  401. static void pkup_late_resume(struct early_suspend *h)
  402. {
  403. atomic_set(&(pkup_context_obj->early_suspend), 0);
  404. if (!atomic_read(&pkup_context_obj->wake) && resume_enable_status)
  405. pkup_real_enable(PKUP_RESUME);
  406. PKUP_LOG(" pkup_late_resume ok------->hwm_obj->early_suspend=%d\n",
  407. atomic_read(&(pkup_context_obj->early_suspend)));
  408. }
  409. #if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(USE_EARLY_SUSPEND)
  410. static int pkup_suspend(struct platform_device *dev, pm_message_t state)
  411. {
  412. atomic_set(&(pkup_context_obj->suspend), 1);
  413. if (!atomic_read(&pkup_context_obj->wake))/* not wake up, disable in early suspend */
  414. pkup_real_enable(PKUP_SUSPEND);
  415. PKUP_LOG(" pkup_suspend ok------->hwm_obj->suspend=%d\n",
  416. atomic_read(&(pkup_context_obj->suspend)));
  417. return 0;
  418. }
  419. /*----------------------------------------------------------------------------*/
  420. static int pkup_resume(struct platform_device *dev)
  421. {
  422. atomic_set(&(pkup_context_obj->suspend), 0);
  423. if (!atomic_read(&pkup_context_obj->wake) && resume_enable_status)
  424. pkup_real_enable(PKUP_RESUME);
  425. PKUP_LOG(" pkup_resume ok------->hwm_obj->suspend=%d\n",
  426. atomic_read(&(pkup_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_pkup_pl_of_match[] = {
  432. {.compatible = "mediatek,m_pkup_pl",},
  433. {},
  434. };
  435. #endif
  436. static struct platform_driver pkup_driver = {
  437. .probe = pkup_probe,
  438. .remove = pkup_remove,
  439. #if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(USE_EARLY_SUSPEND)
  440. .suspend = pkup_suspend,
  441. .resume = pkup_resume,
  442. #endif
  443. .driver = {
  444. .name = PKUP_PL_DEV_NAME,
  445. #ifdef CONFIG_OF
  446. .of_match_table = m_pkup_pl_of_match,
  447. #endif
  448. }
  449. };
  450. static int __init pkup_init(void)
  451. {
  452. PKUP_FUN();
  453. if (platform_driver_register(&pkup_driver)) {
  454. PKUP_ERR("failed to register pkup driver\n");
  455. return -ENODEV;
  456. }
  457. return 0;
  458. }
  459. static void __exit pkup_exit(void)
  460. {
  461. platform_driver_unregister(&pkup_driver);
  462. platform_driver_unregister(&pick_up_driver);
  463. }
  464. late_initcall(pkup_init);
  465. /* module_init(pkup_init); */
  466. /* module_exit(pkup_exit); */
  467. MODULE_LICENSE("GPL");
  468. MODULE_DESCRIPTION("PKUP device driver");
  469. MODULE_AUTHOR("Mediatek");