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