0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/acpi.h>
0009 #include <linux/sysfs.h>
0010
0011 #include "physical_location.h"
0012
0013 bool dev_add_physical_location(struct device *dev)
0014 {
0015 struct acpi_pld_info *pld;
0016 acpi_status status;
0017
0018 if (!has_acpi_companion(dev))
0019 return false;
0020
0021 status = acpi_get_physical_device_location(ACPI_HANDLE(dev), &pld);
0022 if (ACPI_FAILURE(status))
0023 return false;
0024
0025 dev->physical_location =
0026 kzalloc(sizeof(*dev->physical_location), GFP_KERNEL);
0027 if (!dev->physical_location)
0028 return false;
0029 dev->physical_location->panel = pld->panel;
0030 dev->physical_location->vertical_position = pld->vertical_position;
0031 dev->physical_location->horizontal_position = pld->horizontal_position;
0032 dev->physical_location->dock = pld->dock;
0033 dev->physical_location->lid = pld->lid;
0034
0035 ACPI_FREE(pld);
0036 return true;
0037 }
0038
0039 static ssize_t panel_show(struct device *dev, struct device_attribute *attr,
0040 char *buf)
0041 {
0042 const char *panel;
0043
0044 switch (dev->physical_location->panel) {
0045 case DEVICE_PANEL_TOP:
0046 panel = "top";
0047 break;
0048 case DEVICE_PANEL_BOTTOM:
0049 panel = "bottom";
0050 break;
0051 case DEVICE_PANEL_LEFT:
0052 panel = "left";
0053 break;
0054 case DEVICE_PANEL_RIGHT:
0055 panel = "right";
0056 break;
0057 case DEVICE_PANEL_FRONT:
0058 panel = "front";
0059 break;
0060 case DEVICE_PANEL_BACK:
0061 panel = "back";
0062 break;
0063 default:
0064 panel = "unknown";
0065 }
0066 return sysfs_emit(buf, "%s\n", panel);
0067 }
0068 static DEVICE_ATTR_RO(panel);
0069
0070 static ssize_t vertical_position_show(struct device *dev,
0071 struct device_attribute *attr, char *buf)
0072 {
0073 const char *vertical_position;
0074
0075 switch (dev->physical_location->vertical_position) {
0076 case DEVICE_VERT_POS_UPPER:
0077 vertical_position = "upper";
0078 break;
0079 case DEVICE_VERT_POS_CENTER:
0080 vertical_position = "center";
0081 break;
0082 case DEVICE_VERT_POS_LOWER:
0083 vertical_position = "lower";
0084 break;
0085 default:
0086 vertical_position = "unknown";
0087 }
0088 return sysfs_emit(buf, "%s\n", vertical_position);
0089 }
0090 static DEVICE_ATTR_RO(vertical_position);
0091
0092 static ssize_t horizontal_position_show(struct device *dev,
0093 struct device_attribute *attr, char *buf)
0094 {
0095 const char *horizontal_position;
0096
0097 switch (dev->physical_location->horizontal_position) {
0098 case DEVICE_HORI_POS_LEFT:
0099 horizontal_position = "left";
0100 break;
0101 case DEVICE_HORI_POS_CENTER:
0102 horizontal_position = "center";
0103 break;
0104 case DEVICE_HORI_POS_RIGHT:
0105 horizontal_position = "right";
0106 break;
0107 default:
0108 horizontal_position = "unknown";
0109 }
0110 return sysfs_emit(buf, "%s\n", horizontal_position);
0111 }
0112 static DEVICE_ATTR_RO(horizontal_position);
0113
0114 static ssize_t dock_show(struct device *dev, struct device_attribute *attr,
0115 char *buf)
0116 {
0117 return sysfs_emit(buf, "%s\n",
0118 dev->physical_location->dock ? "yes" : "no");
0119 }
0120 static DEVICE_ATTR_RO(dock);
0121
0122 static ssize_t lid_show(struct device *dev, struct device_attribute *attr,
0123 char *buf)
0124 {
0125 return sysfs_emit(buf, "%s\n",
0126 dev->physical_location->lid ? "yes" : "no");
0127 }
0128 static DEVICE_ATTR_RO(lid);
0129
0130 static struct attribute *dev_attr_physical_location[] = {
0131 &dev_attr_panel.attr,
0132 &dev_attr_vertical_position.attr,
0133 &dev_attr_horizontal_position.attr,
0134 &dev_attr_dock.attr,
0135 &dev_attr_lid.attr,
0136 NULL,
0137 };
0138
0139 const struct attribute_group dev_attr_physical_location_group = {
0140 .name = "physical_location",
0141 .attrs = dev_attr_physical_location,
0142 };
0143