Advertisement
ruberval

bln.c

May 16th, 2013
51
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.25 KB | None | 0 0
  1. /* drivers/misc/bln.c
  2.  *
  3.  * Copyright 2011  Michael Richter (alias neldar)
  4.  * Copyright 2011  Adam Kent <adam@semicircular.net>
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License version 2 as
  8.  * published by the Free Software Foundation.
  9.  */
  10.  
  11. #include <linux/platform_device.h>
  12. #include <linux/init.h>
  13. #include <linux/earlysuspend.h>
  14. #include <linux/device.h>
  15. #include <linux/miscdevice.h>
  16. #include <linux/bln.h>
  17. #include <linux/mutex.h>
  18. #include <linux/timer.h>
  19. #include <linux/wakelock.h>
  20.  
  21. <<<<<<< HEAD
  22. static bool bln_enabled = true; /* is BLN function is enabled */
  23. =======
  24. bool bln_enabled = false; /* is BLN function is enabled */
  25. EXPORT_SYMBOL(bln_enabled);
  26.  
  27. >>>>>>> e109dc475850e7ba66112cace6cc235ed7bcbd38
  28. static bool bln_ongoing = false; /* ongoing LED Notification */
  29. static int bln_blink_state = 0;
  30. static int bln_blink_interval = 500;
  31. static int bln_blink_max_count = 600;
  32. static bool bln_suspended = false; /* is system suspended */
  33. static struct bln_implementation *bln_imp = NULL;
  34. static bool in_kernel_blink = false;
  35. static uint32_t blink_count;
  36.  
  37. static struct wake_lock bln_wake_lock;
  38.  
  39. void blink_timer_callback(unsigned long data);
  40. static struct timer_list blink_timer =
  41.         TIMER_INITIALIZER(blink_timer_callback, 0, 0);
  42. static void blink_callback(struct work_struct *blink_work);
  43. static DECLARE_WORK(blink_work, blink_callback);
  44.  
  45. #define BACKLIGHTNOTIFICATION_VERSION 9
  46.  
  47. static void bln_enable_backlights(void)
  48. {
  49.     if (bln_imp)
  50.         bln_imp->enable();
  51. }
  52.  
  53. static void bln_disable_backlights(void)
  54. {
  55.     if (bln_imp)
  56.         bln_imp->disable();
  57. }
  58.  
  59. static void bln_early_suspend(struct early_suspend *h)
  60. {
  61.     bln_suspended = true;
  62. }
  63.  
  64. static void bln_late_resume(struct early_suspend *h)
  65. {
  66.     bln_suspended = false;
  67. }
  68.  
  69. static struct early_suspend bln_suspend_data = {
  70.     .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1,
  71.     .suspend = bln_early_suspend,
  72.     .resume = bln_late_resume,
  73. };
  74.  
  75. static void enable_led_notification(void)
  76. {
  77.     if (!bln_enabled)
  78.         return;
  79.  
  80.     if (in_kernel_blink) {
  81.         wake_lock(&bln_wake_lock);
  82.  
  83.         /* Start timer */
  84.         blink_timer.expires = jiffies +
  85.                 msecs_to_jiffies(bln_blink_interval);
  86.         blink_count = bln_blink_max_count;
  87.         add_timer(&blink_timer);
  88.     }
  89.  
  90.     bln_enable_backlights();
  91.     pr_info("%s: notification led enabled\n", __FUNCTION__);
  92.     bln_ongoing = true;
  93. }
  94.  
  95. static void disable_led_notification(void)
  96. {
  97.     pr_info("%s: notification led disabled\n", __FUNCTION__);
  98.  
  99.     bln_blink_state = 0;
  100.     bln_ongoing = false;
  101.  
  102.     if (bln_suspended)
  103.         bln_disable_backlights();
  104.  
  105.     if (in_kernel_blink)
  106.         del_timer(&blink_timer);
  107.  
  108.     wake_unlock(&bln_wake_lock);
  109.  
  110. }
  111.  
  112. static ssize_t backlightnotification_status_read(struct device *dev,
  113.         struct device_attribute *attr, char *buf)
  114. {
  115.     return sprintf(buf, "%u\n", (bln_enabled ? 1 : 0));
  116. }
  117.  
  118. static ssize_t backlightnotification_status_write(struct device *dev,
  119.         struct device_attribute *attr, const char *buf, size_t size)
  120. {
  121.     unsigned int data;
  122.     if(sscanf(buf, "%u\n", &data) == 1) {
  123.         pr_devel("%s: %u \n", __FUNCTION__, data);
  124.         if (data == 1) {
  125.             pr_info("%s: BLN function enabled\n", __FUNCTION__);
  126.             bln_enabled = true;
  127.         } else if (data == 0) {
  128.             pr_info("%s: BLN function disabled\n", __FUNCTION__);
  129.             bln_enabled = false;
  130.             if (bln_ongoing)
  131.                 disable_led_notification();
  132.         } else {
  133.             pr_info("%s: invalid input range %u\n", __FUNCTION__,
  134.                     data);
  135.         }
  136.     } else {
  137.         pr_info("%s: invalid input\n", __FUNCTION__);
  138.     }
  139.  
  140.     return size;
  141. }
  142.  
  143. static ssize_t notification_led_status_read(struct device *dev,
  144.         struct device_attribute *attr, char *buf)
  145. {
  146.     return sprintf(buf,"%u\n", (bln_ongoing ? 1 : 0));
  147. }
  148.  
  149. static ssize_t notification_led_status_write(struct device *dev,
  150.         struct device_attribute *attr, const char *buf, size_t size)
  151. {
  152.     unsigned int data;
  153.  
  154.     if (sscanf(buf, "%u\n", &data) == 1) {
  155.         if (data == 1)
  156.             enable_led_notification();
  157.         else if (data == 0)
  158.             disable_led_notification();
  159.         else
  160.             pr_info("%s: wrong input %u\n", __FUNCTION__, data);
  161.     } else {
  162.         pr_info("%s: input error\n", __FUNCTION__);
  163.     }
  164.  
  165.     return size;
  166. }
  167.  
  168. static ssize_t in_kernel_blink_status_read(struct device *dev,
  169.         struct device_attribute *attr, char *buf)
  170. {
  171.     return sprintf(buf,"%u\n", (in_kernel_blink ? 1 : 0));
  172. }
  173.  
  174. static ssize_t in_kernel_blink_status_write(struct device *dev,
  175.         struct device_attribute *attr, const char *buf, size_t size)
  176. {
  177.     unsigned int data;
  178.  
  179.     if (sscanf(buf, "%u\n", &data) == 1)
  180.         in_kernel_blink = !!(data);
  181.     else
  182.         pr_info("%s: input error\n", __FUNCTION__);
  183.  
  184.     return size;
  185. }
  186. static ssize_t blink_control_read(struct device *dev,
  187.         struct device_attribute *attr, char *buf)
  188. {
  189.     return sprintf(buf, "%u\n", bln_blink_state);
  190. }
  191.  
  192. static ssize_t blink_control_write(struct device *dev,
  193.         struct device_attribute *attr, const char *buf, size_t size)
  194. {
  195.     unsigned int data;
  196.  
  197.     if (!bln_ongoing)
  198.         return size;
  199.  
  200.     if (sscanf(buf, "%u\n", &data) == 1) {
  201.         if (data == 1) {
  202.             bln_blink_state = 1;
  203.             bln_disable_backlights();
  204.         } else if (data == 0) {
  205.             bln_blink_state = 0;
  206.             bln_enable_backlights();
  207.         } else {
  208.             pr_info("%s: wrong input %u\n", __FUNCTION__, data);
  209.         }
  210.     } else {
  211.         pr_info("%s: input error\n", __FUNCTION__);
  212.     }
  213.  
  214.     return size;
  215. }
  216.  
  217. static ssize_t blink_interval_read(struct device *dev,
  218.         struct device_attribute *attr, char *buf)
  219. {
  220.     return sprintf(buf, "%u\n", bln_blink_interval);
  221. }
  222.  
  223. static ssize_t blink_interval_write(struct device *dev,
  224.         struct device_attribute *attr, const char *buf, size_t size)
  225. {
  226.     unsigned int data;
  227.     if (sscanf(buf, "%u\n", &data) == 1) {
  228.         if (data > 0) {
  229.             bln_blink_interval = data;
  230.         } else {
  231.             pr_info("%s: wrong input %u\n", __FUNCTION__, data);
  232.         }
  233.     } else {
  234.         pr_info("%s: input error\n", __FUNCTION__);
  235.     }
  236.  
  237.     return size;
  238. }
  239.  
  240. static ssize_t blink_maxtime_read(struct device *dev,
  241.         struct device_attribute *attr, char *buf)
  242. {
  243.     return sprintf(buf, "%u\n", bln_blink_max_count);
  244. }
  245.  
  246. static ssize_t blink_maxtime_write(struct device *dev,
  247.         struct device_attribute *attr, const char *buf, size_t size)
  248. {
  249.     unsigned int data;
  250.     if (sscanf(buf, "%u\n", &data) == 1) {
  251.         if (data > 0) {
  252.             bln_blink_max_count = data;
  253.         } else {
  254.             pr_info("%s: wrong input %u\n", __FUNCTION__, data);
  255.         }
  256.     } else {
  257.         pr_info("%s: input error\n", __FUNCTION__);
  258.     }
  259.  
  260.     return size;
  261. }
  262.  
  263. static ssize_t backlightnotification_version(struct device *dev,
  264.         struct device_attribute *attr, char *buf)
  265. {
  266.     return sprintf(buf, "%u\n", BACKLIGHTNOTIFICATION_VERSION);
  267. }
  268.  
  269. static DEVICE_ATTR(blink_control, S_IRUGO | S_IWUGO, blink_control_read,
  270.         blink_control_write);
  271. static DEVICE_ATTR(enabled, S_IRUGO | S_IWUGO,
  272.         backlightnotification_status_read,
  273.         backlightnotification_status_write);
  274. static DEVICE_ATTR(notification_led, S_IRUGO | S_IWUGO,
  275.         notification_led_status_read,
  276.         notification_led_status_write);
  277. static DEVICE_ATTR(in_kernel_blink, S_IRUGO | S_IWUGO,
  278.         in_kernel_blink_status_read,
  279.         in_kernel_blink_status_write);
  280. static DEVICE_ATTR(blink_interval, S_IRUGO | S_IWUGO,
  281.         blink_interval_read,
  282.         blink_interval_write);
  283. static DEVICE_ATTR(blink_maxtime, S_IRUGO | S_IWUGO,
  284.         blink_maxtime_read,
  285.         blink_maxtime_write);
  286. static DEVICE_ATTR(version, S_IRUGO , backlightnotification_version, NULL);
  287.  
  288. static struct attribute *bln_notification_attributes[] = {
  289.     &dev_attr_blink_control.attr,
  290.     &dev_attr_enabled.attr,
  291.     &dev_attr_notification_led.attr,
  292.     &dev_attr_in_kernel_blink.attr,
  293.     &dev_attr_blink_interval.attr,
  294.     &dev_attr_blink_maxtime.attr,
  295.     &dev_attr_version.attr,
  296.     NULL
  297. };
  298.  
  299. static struct attribute_group bln_notification_group = {
  300.     .attrs  = bln_notification_attributes,
  301. };
  302.  
  303. static struct miscdevice bln_device = {
  304.     .minor = MISC_DYNAMIC_MINOR,
  305.     .name = "backlightnotification",
  306. };
  307.  
  308. void register_bln_implementation(struct bln_implementation *imp)
  309. {
  310.     bln_imp = imp;
  311. }
  312. EXPORT_SYMBOL(register_bln_implementation);
  313.  
  314. bool bln_is_ongoing()
  315. {
  316.     return bln_ongoing;
  317. }
  318. EXPORT_SYMBOL(bln_is_ongoing);
  319.  
  320.  
  321. static void blink_callback(struct work_struct *blink_work)
  322. {
  323.     if (--blink_count == 0) {
  324.         pr_info("%s: notification timed out\n", __FUNCTION__);
  325.         bln_enable_backlights();
  326.         del_timer(&blink_timer);
  327.         wake_unlock(&bln_wake_lock);
  328.         return;
  329.     }
  330.  
  331.     if (bln_blink_state)
  332.         bln_enable_backlights();
  333.     else
  334.         bln_disable_backlights();
  335.  
  336.     bln_blink_state = !bln_blink_state;
  337. }
  338.  
  339. void blink_timer_callback(unsigned long data)
  340. {
  341.     schedule_work(&blink_work);
  342.     mod_timer(&blink_timer, jiffies + msecs_to_jiffies(bln_blink_interval));
  343. }
  344.  
  345. static int __init bln_control_init(void)
  346. {
  347.     int ret;
  348.  
  349.     pr_info("%s misc_register(%s)\n", __FUNCTION__, bln_device.name);
  350.     ret = misc_register(&bln_device);
  351.     if (ret) {
  352.         pr_err("%s misc_register(%s) fail\n", __FUNCTION__,
  353.                 bln_device.name);
  354.         return 1;
  355.     }
  356.  
  357.     /* add the bln attributes */
  358.     if (sysfs_create_group(&bln_device.this_device->kobj,
  359.                 &bln_notification_group) < 0) {
  360.         pr_err("%s sysfs_create_group fail\n", __FUNCTION__);
  361.         pr_err("Failed to create sysfs group for device (%s)!\n",
  362.                 bln_device.name);
  363.     }
  364.  
  365.     register_early_suspend(&bln_suspend_data);
  366.  
  367.     /* Initialize wake locks */
  368.     wake_lock_init(&bln_wake_lock, WAKE_LOCK_SUSPEND, "bln_wake");
  369.  
  370.     return 0;
  371. }
  372.  
  373. device_initcall(bln_control_init);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement