sysfs.c 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #include "impl/sysfs.h"
  2. #include "light.h"
  3. #include "helpers.h"
  4. #include <stdio.h> //snprintf
  5. #include <stdlib.h> // malloc, free
  6. #include <dirent.h> // opendir, readdir
  7. static bool _impl_sysfs_init_leds(light_device_enumerator_t *enumerator)
  8. {
  9. // Create a new backlight device
  10. light_device_t *leds_device = light_create_device(enumerator, "leds", NULL);
  11. // Iterate through the led controllers and create a device_target for each controller
  12. DIR *leds_dir;
  13. struct dirent *curr_entry;
  14. if((leds_dir = opendir("/sys/class/leds")) == NULL)
  15. {
  16. LIGHT_ERR("failed to open leds controller directory for reading");
  17. return false;
  18. }
  19. while((curr_entry = readdir(leds_dir)) != NULL)
  20. {
  21. // Skip dot entries
  22. if(curr_entry->d_name[0] == '.')
  23. {
  24. continue;
  25. }
  26. // Setup the target data
  27. impl_sysfs_data_t *dev_data = malloc(sizeof(impl_sysfs_data_t));
  28. snprintf(dev_data->brightness, sizeof(dev_data->brightness), "/sys/class/leds/%s/brightness", curr_entry->d_name);
  29. snprintf(dev_data->max_brightness, sizeof(dev_data->max_brightness), "/sys/class/leds/%s/max_brightness", curr_entry->d_name);
  30. // Create a new device target for the controller
  31. light_create_device_target(leds_device, curr_entry->d_name, impl_sysfs_set, impl_sysfs_get, impl_sysfs_getmax, impl_sysfs_command, dev_data);
  32. }
  33. closedir(leds_dir);
  34. return true;
  35. }
  36. static bool _impl_sysfs_init_backlight(light_device_enumerator_t *enumerator)
  37. {
  38. // Create a new backlight device
  39. light_device_t *backlight_device = light_create_device(enumerator, "backlight", NULL);
  40. // Iterate through the backlight controllers and create a device_target for each controller
  41. DIR *backlight_dir;
  42. struct dirent *curr_entry;
  43. // Keep track of the best controller, and create an autodevice from that
  44. char best_controller[NAME_MAX];
  45. uint64_t best_value = 0;
  46. if((backlight_dir = opendir("/sys/class/backlight")) == NULL)
  47. {
  48. LIGHT_ERR("failed to open backlight controller directory for reading");
  49. return false;
  50. }
  51. while((curr_entry = readdir(backlight_dir)) != NULL)
  52. {
  53. // Skip dot entries
  54. if(curr_entry->d_name[0] == '.')
  55. {
  56. continue;
  57. }
  58. // Setup the target data
  59. impl_sysfs_data_t *dev_data = malloc(sizeof(impl_sysfs_data_t));
  60. snprintf(dev_data->brightness, sizeof(dev_data->brightness), "/sys/class/backlight/%s/brightness", curr_entry->d_name);
  61. snprintf(dev_data->max_brightness, sizeof(dev_data->max_brightness), "/sys/class/backlight/%s/max_brightness", curr_entry->d_name);
  62. // Create a new device target for the controller
  63. light_create_device_target(backlight_device, curr_entry->d_name, impl_sysfs_set, impl_sysfs_get, impl_sysfs_getmax, impl_sysfs_command, dev_data);
  64. // Read the max brightness to get the best one
  65. uint64_t curr_value = 0;
  66. if(light_file_read_uint64(dev_data->max_brightness, &curr_value))
  67. {
  68. if(curr_value > best_value)
  69. {
  70. best_value = curr_value;
  71. snprintf(best_controller, sizeof(best_controller), "%s", curr_entry->d_name);
  72. }
  73. }
  74. }
  75. closedir(backlight_dir);
  76. // If we found at least one usable controller, create an auto target mapped to that controller
  77. if(best_value > 0)
  78. {
  79. // Setup the target data
  80. impl_sysfs_data_t *dev_data = malloc(sizeof(impl_sysfs_data_t));
  81. snprintf(dev_data->brightness, sizeof(dev_data->brightness), "/sys/class/backlight/%s/brightness", best_controller);
  82. snprintf(dev_data->max_brightness, sizeof(dev_data->max_brightness), "/sys/class/backlight/%s/max_brightness", best_controller);
  83. // Create a new device target for the controller
  84. light_create_device_target(backlight_device, "auto", impl_sysfs_set, impl_sysfs_get, impl_sysfs_getmax, impl_sysfs_command, dev_data);
  85. }
  86. return true;
  87. }
  88. bool impl_sysfs_init(light_device_enumerator_t *enumerator)
  89. {
  90. // Create a device for the backlight
  91. _impl_sysfs_init_backlight(enumerator);
  92. // Create devices for the leds
  93. _impl_sysfs_init_leds(enumerator);
  94. return true;
  95. }
  96. bool impl_sysfs_free(light_device_enumerator_t *enumerator)
  97. {
  98. return true;
  99. }
  100. bool impl_sysfs_set(light_device_target_t *target, uint64_t in_value)
  101. {
  102. impl_sysfs_data_t *data = (impl_sysfs_data_t*)target->device_target_data;
  103. if(!light_file_write_uint64(data->brightness, in_value))
  104. {
  105. LIGHT_ERR("failed to write to sysfs device");
  106. return false;
  107. }
  108. return true;
  109. }
  110. bool impl_sysfs_get(light_device_target_t *target, uint64_t *out_value)
  111. {
  112. impl_sysfs_data_t *data = (impl_sysfs_data_t*)target->device_target_data;
  113. if(!light_file_read_uint64(data->brightness, out_value))
  114. {
  115. LIGHT_ERR("failed to read from sysfs device");
  116. return false;
  117. }
  118. return true;
  119. }
  120. bool impl_sysfs_getmax(light_device_target_t *target, uint64_t *out_value)
  121. {
  122. impl_sysfs_data_t *data = (impl_sysfs_data_t*)target->device_target_data;
  123. if(!light_file_read_uint64(data->max_brightness, out_value))
  124. {
  125. LIGHT_ERR("failed to read from sysfs device");
  126. return false;
  127. }
  128. return true;
  129. }
  130. bool impl_sysfs_command(light_device_target_t *target, char const *command_string)
  131. {
  132. // No current need for custom commands in sysfs enumerator
  133. // To implement support, simply parse the command string to your liking, and return false on invalid input or results!
  134. return true;
  135. }