physical_location.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Device physical location support
  4. *
  5. * Author: Won Chung <[email protected]>
  6. */
  7. #include <linux/acpi.h>
  8. #include <linux/sysfs.h>
  9. #include "physical_location.h"
  10. bool dev_add_physical_location(struct device *dev)
  11. {
  12. struct acpi_pld_info *pld;
  13. acpi_status status;
  14. if (!has_acpi_companion(dev))
  15. return false;
  16. status = acpi_get_physical_device_location(ACPI_HANDLE(dev), &pld);
  17. if (ACPI_FAILURE(status))
  18. return false;
  19. dev->physical_location =
  20. kzalloc(sizeof(*dev->physical_location), GFP_KERNEL);
  21. if (!dev->physical_location) {
  22. ACPI_FREE(pld);
  23. return false;
  24. }
  25. dev->physical_location->panel = pld->panel;
  26. dev->physical_location->vertical_position = pld->vertical_position;
  27. dev->physical_location->horizontal_position = pld->horizontal_position;
  28. dev->physical_location->dock = pld->dock;
  29. dev->physical_location->lid = pld->lid;
  30. ACPI_FREE(pld);
  31. return true;
  32. }
  33. static ssize_t panel_show(struct device *dev, struct device_attribute *attr,
  34. char *buf)
  35. {
  36. const char *panel;
  37. switch (dev->physical_location->panel) {
  38. case DEVICE_PANEL_TOP:
  39. panel = "top";
  40. break;
  41. case DEVICE_PANEL_BOTTOM:
  42. panel = "bottom";
  43. break;
  44. case DEVICE_PANEL_LEFT:
  45. panel = "left";
  46. break;
  47. case DEVICE_PANEL_RIGHT:
  48. panel = "right";
  49. break;
  50. case DEVICE_PANEL_FRONT:
  51. panel = "front";
  52. break;
  53. case DEVICE_PANEL_BACK:
  54. panel = "back";
  55. break;
  56. default:
  57. panel = "unknown";
  58. }
  59. return sysfs_emit(buf, "%s\n", panel);
  60. }
  61. static DEVICE_ATTR_RO(panel);
  62. static ssize_t vertical_position_show(struct device *dev,
  63. struct device_attribute *attr, char *buf)
  64. {
  65. const char *vertical_position;
  66. switch (dev->physical_location->vertical_position) {
  67. case DEVICE_VERT_POS_UPPER:
  68. vertical_position = "upper";
  69. break;
  70. case DEVICE_VERT_POS_CENTER:
  71. vertical_position = "center";
  72. break;
  73. case DEVICE_VERT_POS_LOWER:
  74. vertical_position = "lower";
  75. break;
  76. default:
  77. vertical_position = "unknown";
  78. }
  79. return sysfs_emit(buf, "%s\n", vertical_position);
  80. }
  81. static DEVICE_ATTR_RO(vertical_position);
  82. static ssize_t horizontal_position_show(struct device *dev,
  83. struct device_attribute *attr, char *buf)
  84. {
  85. const char *horizontal_position;
  86. switch (dev->physical_location->horizontal_position) {
  87. case DEVICE_HORI_POS_LEFT:
  88. horizontal_position = "left";
  89. break;
  90. case DEVICE_HORI_POS_CENTER:
  91. horizontal_position = "center";
  92. break;
  93. case DEVICE_HORI_POS_RIGHT:
  94. horizontal_position = "right";
  95. break;
  96. default:
  97. horizontal_position = "unknown";
  98. }
  99. return sysfs_emit(buf, "%s\n", horizontal_position);
  100. }
  101. static DEVICE_ATTR_RO(horizontal_position);
  102. static ssize_t dock_show(struct device *dev, struct device_attribute *attr,
  103. char *buf)
  104. {
  105. return sysfs_emit(buf, "%s\n",
  106. dev->physical_location->dock ? "yes" : "no");
  107. }
  108. static DEVICE_ATTR_RO(dock);
  109. static ssize_t lid_show(struct device *dev, struct device_attribute *attr,
  110. char *buf)
  111. {
  112. return sysfs_emit(buf, "%s\n",
  113. dev->physical_location->lid ? "yes" : "no");
  114. }
  115. static DEVICE_ATTR_RO(lid);
  116. static struct attribute *dev_attr_physical_location[] = {
  117. &dev_attr_panel.attr,
  118. &dev_attr_vertical_position.attr,
  119. &dev_attr_horizontal_position.attr,
  120. &dev_attr_dock.attr,
  121. &dev_attr_lid.attr,
  122. NULL,
  123. };
  124. const struct attribute_group dev_attr_physical_location_group = {
  125. .name = "physical_location",
  126. .attrs = dev_attr_physical_location,
  127. };