physical_location.c 3.2 KB

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