This source file includes following definitions.
- usb_acpi_power_manageable
- usb_acpi_set_power_state
- usb_acpi_get_connect_type
- usb_acpi_find_port
- usb_acpi_get_companion_for_port
- usb_acpi_find_companion_for_port
- usb_acpi_find_companion_for_device
- usb_acpi_find_companion
- usb_acpi_bus_match
- usb_acpi_register
- usb_acpi_unregister
1
2
3
4
5
6
7 #include <linux/module.h>
8 #include <linux/usb.h>
9 #include <linux/device.h>
10 #include <linux/errno.h>
11 #include <linux/kernel.h>
12 #include <linux/acpi.h>
13 #include <linux/pci.h>
14 #include <linux/usb/hcd.h>
15
16 #include "hub.h"
17
18
19
20
21
22
23
24
25
26 bool usb_acpi_power_manageable(struct usb_device *hdev, int index)
27 {
28 acpi_handle port_handle;
29 int port1 = index + 1;
30
31 port_handle = usb_get_hub_port_acpi_handle(hdev,
32 port1);
33 if (port_handle)
34 return acpi_bus_power_manageable(port_handle);
35 else
36 return false;
37 }
38 EXPORT_SYMBOL_GPL(usb_acpi_power_manageable);
39
40
41
42
43
44
45
46
47
48
49
50
51
52 int usb_acpi_set_power_state(struct usb_device *hdev, int index, bool enable)
53 {
54 struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
55 struct usb_port *port_dev;
56 acpi_handle port_handle;
57 unsigned char state;
58 int port1 = index + 1;
59 int error = -EINVAL;
60
61 if (!hub)
62 return -ENODEV;
63 port_dev = hub->ports[port1 - 1];
64
65 port_handle = (acpi_handle) usb_get_hub_port_acpi_handle(hdev, port1);
66 if (!port_handle)
67 return error;
68
69 if (enable)
70 state = ACPI_STATE_D0;
71 else
72 state = ACPI_STATE_D3_COLD;
73
74 error = acpi_bus_set_power(port_handle, state);
75 if (!error)
76 dev_dbg(&port_dev->dev, "acpi: power was set to %d\n", enable);
77 else
78 dev_dbg(&port_dev->dev, "acpi: power failed to be set\n");
79
80 return error;
81 }
82 EXPORT_SYMBOL_GPL(usb_acpi_set_power_state);
83
84 static enum usb_port_connect_type usb_acpi_get_connect_type(acpi_handle handle,
85 struct acpi_pld_info *pld)
86 {
87 enum usb_port_connect_type connect_type = USB_PORT_CONNECT_TYPE_UNKNOWN;
88 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
89 union acpi_object *upc;
90 acpi_status status;
91
92
93
94
95
96
97
98
99
100 status = acpi_evaluate_object(handle, "_UPC", NULL, &buffer);
101 upc = buffer.pointer;
102 if (!upc || (upc->type != ACPI_TYPE_PACKAGE)
103 || upc->package.count != 4) {
104 goto out;
105 }
106
107 if (upc->package.elements[0].integer.value)
108 if (pld->user_visible)
109 connect_type = USB_PORT_CONNECT_TYPE_HOT_PLUG;
110 else
111 connect_type = USB_PORT_CONNECT_TYPE_HARD_WIRED;
112 else if (!pld->user_visible)
113 connect_type = USB_PORT_NOT_USED;
114 out:
115 kfree(upc);
116 return connect_type;
117 }
118
119
120
121
122
123
124 #define USB_ACPI_LOCATION_VALID (1 << 31)
125
126 static struct acpi_device *usb_acpi_find_port(struct acpi_device *parent,
127 int raw)
128 {
129 struct acpi_device *adev;
130
131 if (!parent)
132 return NULL;
133
134 list_for_each_entry(adev, &parent->children, node) {
135 if (acpi_device_adr(adev) == raw)
136 return adev;
137 }
138
139 return acpi_find_child_device(parent, raw, false);
140 }
141
142 static struct acpi_device *
143 usb_acpi_get_companion_for_port(struct usb_port *port_dev)
144 {
145 struct usb_device *udev;
146 struct acpi_device *adev;
147 acpi_handle *parent_handle;
148 int port1;
149
150
151 udev = to_usb_device(port_dev->dev.parent->parent);
152
153
154
155
156
157
158 if (!udev->parent) {
159 adev = ACPI_COMPANION(&udev->dev);
160 port1 = usb_hcd_find_raw_port_number(bus_to_hcd(udev->bus),
161 port_dev->portnum);
162 } else {
163 parent_handle = usb_get_hub_port_acpi_handle(udev->parent,
164 udev->portnum);
165 if (!parent_handle)
166 return NULL;
167
168 acpi_bus_get_device(parent_handle, &adev);
169 port1 = port_dev->portnum;
170 }
171
172 return usb_acpi_find_port(adev, port1);
173 }
174
175 static struct acpi_device *
176 usb_acpi_find_companion_for_port(struct usb_port *port_dev)
177 {
178 struct acpi_device *adev;
179 struct acpi_pld_info *pld;
180 acpi_handle *handle;
181 acpi_status status;
182
183 adev = usb_acpi_get_companion_for_port(port_dev);
184 if (!adev)
185 return NULL;
186
187 handle = adev->handle;
188 status = acpi_get_physical_device_location(handle, &pld);
189 if (!ACPI_FAILURE(status) && pld) {
190 port_dev->location = USB_ACPI_LOCATION_VALID
191 | pld->group_token << 8 | pld->group_position;
192 port_dev->connect_type = usb_acpi_get_connect_type(handle, pld);
193 ACPI_FREE(pld);
194 }
195
196 return adev;
197 }
198
199 static struct acpi_device *
200 usb_acpi_find_companion_for_device(struct usb_device *udev)
201 {
202 struct acpi_device *adev;
203 struct usb_port *port_dev;
204 struct usb_hub *hub;
205
206 if (!udev->parent) {
207
208 adev = ACPI_COMPANION(udev->dev.parent);
209 return acpi_find_child_device(adev, 0, false);
210 }
211
212 hub = usb_hub_to_struct_hub(udev->parent);
213 if (!hub)
214 return NULL;
215
216
217
218
219
220 port_dev = hub->ports[udev->portnum - 1];
221 return usb_acpi_get_companion_for_port(port_dev);
222 }
223
224 static struct acpi_device *usb_acpi_find_companion(struct device *dev)
225 {
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254 if (is_usb_device(dev))
255 return usb_acpi_find_companion_for_device(to_usb_device(dev));
256 else if (is_usb_port(dev))
257 return usb_acpi_find_companion_for_port(to_usb_port(dev));
258
259 return NULL;
260 }
261
262 static bool usb_acpi_bus_match(struct device *dev)
263 {
264 return is_usb_device(dev) || is_usb_port(dev);
265 }
266
267 static struct acpi_bus_type usb_acpi_bus = {
268 .name = "USB",
269 .match = usb_acpi_bus_match,
270 .find_companion = usb_acpi_find_companion,
271 };
272
273 int usb_acpi_register(void)
274 {
275 return register_acpi_bus_type(&usb_acpi_bus);
276 }
277
278 void usb_acpi_unregister(void)
279 {
280 unregister_acpi_bus_type(&usb_acpi_bus);
281 }