backlight.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/init.h>
  4. #include <linux/fs.h>
  5. #include <linux/cdev.h>
  6. #include <linux/device.h>
  7. #include <linux/uaccess.h>
  8. #include <linux/slab.h>
  9. #include <linux/pci.h>
  10. #include <linux/i2c.h>
  11. #include <linux/acpi.h>
  12. #include <linux/interrupt.h>
  13. #include <linux/wait.h>
  14. #include <linux/sched.h>
  15. #include <linux/poll.h>
  16. #include <linux/mutex.h>
  17. #include <linux/delay.h>
  18. #include "light_ring.h"
  19. extern struct kobject *vfiec_kobj;
  20. static struct kobject *backlight_kobj = NULL;
  21. static int brightness_val = 0;
  22. static int max_brightness_val = 1;
  23. #define BACKLIGHT_PATH "/sys/class/backlight/intel_backlight/brightness"
  24. // Read the current brightness value from sysfs
  25. static int read_current_brightness(void)
  26. {
  27. struct file *filp = NULL;
  28. char buf[32] = {0};
  29. loff_t pos = 0;
  30. int ret = -EIO;
  31. int brightness = -1;
  32. filp = filp_open(BACKLIGHT_PATH, O_RDONLY, 0);
  33. if (IS_ERR(filp)) {
  34. pr_err("Failed to open backlight file: %ld\n", PTR_ERR(filp));
  35. return -EIO;
  36. }
  37. ret = kernel_read(filp, buf, sizeof(buf) - 1, &pos);
  38. if (ret > 0) {
  39. buf[ret] = '\0';
  40. if (kstrtoint(buf, 10, &brightness) != 0) {
  41. pr_err("Failed to parse brightness value\n");
  42. brightness = -EINVAL;
  43. }
  44. }
  45. filp_close(filp, NULL);
  46. return brightness;
  47. }
  48. static int read_max_brightness(void)
  49. {
  50. struct file *filp = NULL;
  51. loff_t pos = 0;
  52. int max_brightness;
  53. filp = filp_open("/sys/class/backlight/intel_backlight/max_brightness", O_RDONLY, 0);
  54. if (!IS_ERR(filp)) {
  55. char max_buf[32] = {0};
  56. kernel_read(filp, max_buf, sizeof(max_buf) - 1, &pos);
  57. if (kstrtoint(max_buf, 10, &max_brightness) != 0)
  58. {
  59. filp_close(filp, NULL);
  60. return -EINVAL;
  61. }
  62. filp_close(filp, NULL);
  63. }
  64. return max_brightness;
  65. }
  66. // Write brightness value to sysfs
  67. static int write_brightness_value(int value)
  68. {
  69. struct file *filp = NULL;
  70. char buf[32] = {0};
  71. loff_t pos = 0;
  72. int ret = -EIO;
  73. int max_brightness;
  74. // First read the maximum value for boundary checking
  75. filp = filp_open("/sys/class/backlight/intel_backlight/max_brightness", O_RDONLY, 0);
  76. if (!IS_ERR(filp)) {
  77. char max_buf[32] = {0};
  78. kernel_read(filp, max_buf, sizeof(max_buf) - 1, &pos);
  79. if (kstrtoint(max_buf, 10, &max_brightness) == 0) {
  80. if (value < 0 || value > max_brightness) {
  81. pr_err("Brightness value %d out of range [0, %d]\n", value, max_brightness);
  82. filp_close(filp, NULL);
  83. return -EINVAL;
  84. }
  85. }
  86. filp_close(filp, NULL);
  87. }
  88. // Write brightness value
  89. filp = filp_open(BACKLIGHT_PATH, O_WRONLY, 0);
  90. if (IS_ERR(filp)) {
  91. pr_err("Failed to open backlight file for write: %ld\n", PTR_ERR(filp));
  92. return -EIO;
  93. }
  94. snprintf(buf, sizeof(buf), "%d", value);
  95. ret = kernel_write(filp, buf, strlen(buf), &pos);
  96. filp_close(filp, NULL);
  97. return (ret > 0) ? 0 : -EIO;
  98. }
  99. /* ==================== mode ==================== */
  100. static ssize_t brightness_show(struct kobject *kobj, struct kobj_attribute *attr,
  101. char *buf)
  102. {
  103. static int val = 0;
  104. brightness_val = read_current_brightness();
  105. if(max_brightness_val == 0 || max_brightness_val > 960)
  106. {
  107. max_brightness_val = 960;
  108. }
  109. val = brightness_val*100/max_brightness_val;
  110. if(val > 100)
  111. {
  112. val = 100;
  113. }
  114. return sprintf(buf, "%d\n", val);
  115. }
  116. static ssize_t brightness_store(struct kobject *kobj, struct kobj_attribute *attr,
  117. const char *buf, size_t count)
  118. {
  119. int ret = 0;
  120. long val;
  121. if (kstrtol(buf, 10, &val) < 0 || val < 0 || val > 100)
  122. {
  123. return -EINVAL;
  124. }
  125. brightness_val = val*max_brightness_val/100;
  126. if(brightness_val > 960)
  127. {
  128. brightness_val = 960;
  129. }
  130. ret = write_brightness_value(brightness_val);
  131. return count;
  132. }
  133. static struct kobj_attribute brightness =
  134. __ATTR(brightness, 0644, brightness_show, brightness_store);
  135. static struct attribute *backlight_attrs[] = {
  136. &brightness.attr,
  137. NULL,
  138. };
  139. static struct attribute_group backlight_attr_group = {
  140. .attrs = backlight_attrs,
  141. };
  142. int backlight_init(void)
  143. {
  144. int ret;
  145. #ifndef C181
  146. return 0;
  147. #endif
  148. max_brightness_val = read_max_brightness();
  149. if(max_brightness_val <= 0)
  150. {
  151. pr_err("Failed to read max brightness value\n");
  152. return -EIO;
  153. }
  154. brightness_val = read_current_brightness();
  155. /* Create /sys/kernel/vfiec/lightring */
  156. backlight_kobj = kobject_create_and_add("backlight", vfiec_kobj);
  157. if (!backlight_kobj)
  158. {
  159. ret = -ENOMEM;
  160. }
  161. /* Create property file */
  162. ret = sysfs_create_group(backlight_kobj, &backlight_attr_group);
  163. if (ret)
  164. {
  165. pr_err("Faibacklight to create sysfs group: %d\n", ret);
  166. }
  167. return ret;
  168. }
  169. void backlight_exit(void)
  170. {
  171. #ifndef C181
  172. return ;
  173. #endif
  174. sysfs_remove_group(backlight_kobj, &backlight_attr_group);
  175. kobject_put(backlight_kobj);
  176. }