1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * drivers/usb/core/sysfs.c |
4 | * |
5 | * (C) Copyright 2002 David Brownell |
6 | * (C) Copyright 2002,2004 Greg Kroah-Hartman |
7 | * (C) Copyright 2002,2004 IBM Corp. |
8 | * |
9 | * All of the sysfs file attributes for usb devices and interfaces. |
10 | * |
11 | * Released under the GPLv2 only. |
12 | */ |
13 | |
14 | |
15 | #include <linux/kernel.h> |
16 | #include <linux/kstrtox.h> |
17 | #include <linux/string.h> |
18 | #include <linux/usb.h> |
19 | #include <linux/usb/hcd.h> |
20 | #include <linux/usb/quirks.h> |
21 | #include <linux/of.h> |
22 | #include "usb.h" |
23 | |
24 | /* Active configuration fields */ |
25 | #define usb_actconfig_show(field, format_string) \ |
26 | static ssize_t field##_show(struct device *dev, \ |
27 | struct device_attribute *attr, char *buf) \ |
28 | { \ |
29 | struct usb_device *udev; \ |
30 | struct usb_host_config *actconfig; \ |
31 | ssize_t rc; \ |
32 | \ |
33 | udev = to_usb_device(dev); \ |
34 | rc = usb_lock_device_interruptible(udev); \ |
35 | if (rc < 0) \ |
36 | return -EINTR; \ |
37 | actconfig = udev->actconfig; \ |
38 | if (actconfig) \ |
39 | rc = sysfs_emit(buf, format_string, \ |
40 | actconfig->desc.field); \ |
41 | usb_unlock_device(udev); \ |
42 | return rc; \ |
43 | } \ |
44 | |
45 | #define usb_actconfig_attr(field, format_string) \ |
46 | usb_actconfig_show(field, format_string) \ |
47 | static DEVICE_ATTR_RO(field) |
48 | |
49 | usb_actconfig_attr(bNumInterfaces, "%2d\n" ); |
50 | usb_actconfig_attr(bmAttributes, "%2x\n" ); |
51 | |
52 | static ssize_t bMaxPower_show(struct device *dev, |
53 | struct device_attribute *attr, char *buf) |
54 | { |
55 | struct usb_device *udev; |
56 | struct usb_host_config *actconfig; |
57 | ssize_t rc; |
58 | |
59 | udev = to_usb_device(dev); |
60 | rc = usb_lock_device_interruptible(udev); |
61 | if (rc < 0) |
62 | return -EINTR; |
63 | actconfig = udev->actconfig; |
64 | if (actconfig) |
65 | rc = sysfs_emit(buf, fmt: "%dmA\n" , usb_get_max_power(udev, c: actconfig)); |
66 | usb_unlock_device(udev); |
67 | return rc; |
68 | } |
69 | static DEVICE_ATTR_RO(bMaxPower); |
70 | |
71 | static ssize_t configuration_show(struct device *dev, |
72 | struct device_attribute *attr, char *buf) |
73 | { |
74 | struct usb_device *udev; |
75 | struct usb_host_config *actconfig; |
76 | ssize_t rc; |
77 | |
78 | udev = to_usb_device(dev); |
79 | rc = usb_lock_device_interruptible(udev); |
80 | if (rc < 0) |
81 | return -EINTR; |
82 | actconfig = udev->actconfig; |
83 | if (actconfig && actconfig->string) |
84 | rc = sysfs_emit(buf, fmt: "%s\n" , actconfig->string); |
85 | usb_unlock_device(udev); |
86 | return rc; |
87 | } |
88 | static DEVICE_ATTR_RO(configuration); |
89 | |
90 | /* configuration value is always present, and r/w */ |
91 | usb_actconfig_show(bConfigurationValue, "%u\n" ); |
92 | |
93 | static ssize_t bConfigurationValue_store(struct device *dev, |
94 | struct device_attribute *attr, |
95 | const char *buf, size_t count) |
96 | { |
97 | struct usb_device *udev = to_usb_device(dev); |
98 | int config, value, rc; |
99 | |
100 | if (sscanf(buf, "%d" , &config) != 1 || config < -1 || config > 255) |
101 | return -EINVAL; |
102 | rc = usb_lock_device_interruptible(udev); |
103 | if (rc < 0) |
104 | return -EINTR; |
105 | value = usb_set_configuration(dev: udev, configuration: config); |
106 | usb_unlock_device(udev); |
107 | return (value < 0) ? value : count; |
108 | } |
109 | static DEVICE_ATTR_IGNORE_LOCKDEP(bConfigurationValue, S_IRUGO | S_IWUSR, |
110 | bConfigurationValue_show, bConfigurationValue_store); |
111 | |
112 | #ifdef CONFIG_OF |
113 | static ssize_t devspec_show(struct device *dev, struct device_attribute *attr, |
114 | char *buf) |
115 | { |
116 | struct device_node *of_node = dev->of_node; |
117 | |
118 | return sysfs_emit(buf, fmt: "%pOF\n" , of_node); |
119 | } |
120 | static DEVICE_ATTR_RO(devspec); |
121 | #endif |
122 | |
123 | /* String fields */ |
124 | #define usb_string_attr(name) \ |
125 | static ssize_t name##_show(struct device *dev, \ |
126 | struct device_attribute *attr, char *buf) \ |
127 | { \ |
128 | struct usb_device *udev; \ |
129 | int retval; \ |
130 | \ |
131 | udev = to_usb_device(dev); \ |
132 | retval = usb_lock_device_interruptible(udev); \ |
133 | if (retval < 0) \ |
134 | return -EINTR; \ |
135 | retval = sysfs_emit(buf, "%s\n", udev->name); \ |
136 | usb_unlock_device(udev); \ |
137 | return retval; \ |
138 | } \ |
139 | static DEVICE_ATTR_RO(name) |
140 | |
141 | usb_string_attr(product); |
142 | usb_string_attr(manufacturer); |
143 | usb_string_attr(serial); |
144 | |
145 | static ssize_t speed_show(struct device *dev, struct device_attribute *attr, |
146 | char *buf) |
147 | { |
148 | struct usb_device *udev; |
149 | char *speed; |
150 | |
151 | udev = to_usb_device(dev); |
152 | |
153 | switch (udev->speed) { |
154 | case USB_SPEED_LOW: |
155 | speed = "1.5" ; |
156 | break; |
157 | case USB_SPEED_UNKNOWN: |
158 | case USB_SPEED_FULL: |
159 | speed = "12" ; |
160 | break; |
161 | case USB_SPEED_HIGH: |
162 | speed = "480" ; |
163 | break; |
164 | case USB_SPEED_SUPER: |
165 | speed = "5000" ; |
166 | break; |
167 | case USB_SPEED_SUPER_PLUS: |
168 | if (udev->ssp_rate == USB_SSP_GEN_2x2) |
169 | speed = "20000" ; |
170 | else |
171 | speed = "10000" ; |
172 | break; |
173 | default: |
174 | speed = "unknown" ; |
175 | } |
176 | return sysfs_emit(buf, fmt: "%s\n" , speed); |
177 | } |
178 | static DEVICE_ATTR_RO(speed); |
179 | |
180 | static ssize_t rx_lanes_show(struct device *dev, struct device_attribute *attr, |
181 | char *buf) |
182 | { |
183 | struct usb_device *udev; |
184 | |
185 | udev = to_usb_device(dev); |
186 | return sysfs_emit(buf, fmt: "%d\n" , udev->rx_lanes); |
187 | } |
188 | static DEVICE_ATTR_RO(rx_lanes); |
189 | |
190 | static ssize_t tx_lanes_show(struct device *dev, struct device_attribute *attr, |
191 | char *buf) |
192 | { |
193 | struct usb_device *udev; |
194 | |
195 | udev = to_usb_device(dev); |
196 | return sysfs_emit(buf, fmt: "%d\n" , udev->tx_lanes); |
197 | } |
198 | static DEVICE_ATTR_RO(tx_lanes); |
199 | |
200 | static ssize_t busnum_show(struct device *dev, struct device_attribute *attr, |
201 | char *buf) |
202 | { |
203 | struct usb_device *udev; |
204 | |
205 | udev = to_usb_device(dev); |
206 | return sysfs_emit(buf, fmt: "%d\n" , udev->bus->busnum); |
207 | } |
208 | static DEVICE_ATTR_RO(busnum); |
209 | |
210 | static ssize_t devnum_show(struct device *dev, struct device_attribute *attr, |
211 | char *buf) |
212 | { |
213 | struct usb_device *udev; |
214 | |
215 | udev = to_usb_device(dev); |
216 | return sysfs_emit(buf, fmt: "%d\n" , udev->devnum); |
217 | } |
218 | static DEVICE_ATTR_RO(devnum); |
219 | |
220 | static ssize_t devpath_show(struct device *dev, struct device_attribute *attr, |
221 | char *buf) |
222 | { |
223 | struct usb_device *udev; |
224 | |
225 | udev = to_usb_device(dev); |
226 | return sysfs_emit(buf, fmt: "%s\n" , udev->devpath); |
227 | } |
228 | static DEVICE_ATTR_RO(devpath); |
229 | |
230 | static ssize_t version_show(struct device *dev, struct device_attribute *attr, |
231 | char *buf) |
232 | { |
233 | struct usb_device *udev; |
234 | u16 bcdUSB; |
235 | |
236 | udev = to_usb_device(dev); |
237 | bcdUSB = le16_to_cpu(udev->descriptor.bcdUSB); |
238 | return sysfs_emit(buf, fmt: "%2x.%02x\n" , bcdUSB >> 8, bcdUSB & 0xff); |
239 | } |
240 | static DEVICE_ATTR_RO(version); |
241 | |
242 | static ssize_t maxchild_show(struct device *dev, struct device_attribute *attr, |
243 | char *buf) |
244 | { |
245 | struct usb_device *udev; |
246 | |
247 | udev = to_usb_device(dev); |
248 | return sysfs_emit(buf, fmt: "%d\n" , udev->maxchild); |
249 | } |
250 | static DEVICE_ATTR_RO(maxchild); |
251 | |
252 | static ssize_t quirks_show(struct device *dev, struct device_attribute *attr, |
253 | char *buf) |
254 | { |
255 | struct usb_device *udev; |
256 | |
257 | udev = to_usb_device(dev); |
258 | return sysfs_emit(buf, fmt: "0x%x\n" , udev->quirks); |
259 | } |
260 | static DEVICE_ATTR_RO(quirks); |
261 | |
262 | static ssize_t avoid_reset_quirk_show(struct device *dev, |
263 | struct device_attribute *attr, char *buf) |
264 | { |
265 | struct usb_device *udev; |
266 | |
267 | udev = to_usb_device(dev); |
268 | return sysfs_emit(buf, fmt: "%d\n" , !!(udev->quirks & USB_QUIRK_RESET)); |
269 | } |
270 | |
271 | static ssize_t avoid_reset_quirk_store(struct device *dev, |
272 | struct device_attribute *attr, |
273 | const char *buf, size_t count) |
274 | { |
275 | struct usb_device *udev = to_usb_device(dev); |
276 | bool val; |
277 | int rc; |
278 | |
279 | if (kstrtobool(s: buf, res: &val) != 0) |
280 | return -EINVAL; |
281 | rc = usb_lock_device_interruptible(udev); |
282 | if (rc < 0) |
283 | return -EINTR; |
284 | if (val) |
285 | udev->quirks |= USB_QUIRK_RESET; |
286 | else |
287 | udev->quirks &= ~USB_QUIRK_RESET; |
288 | usb_unlock_device(udev); |
289 | return count; |
290 | } |
291 | static DEVICE_ATTR_RW(avoid_reset_quirk); |
292 | |
293 | static ssize_t urbnum_show(struct device *dev, struct device_attribute *attr, |
294 | char *buf) |
295 | { |
296 | struct usb_device *udev; |
297 | |
298 | udev = to_usb_device(dev); |
299 | return sysfs_emit(buf, fmt: "%d\n" , atomic_read(v: &udev->urbnum)); |
300 | } |
301 | static DEVICE_ATTR_RO(urbnum); |
302 | |
303 | static ssize_t ltm_capable_show(struct device *dev, |
304 | struct device_attribute *attr, char *buf) |
305 | { |
306 | if (usb_device_supports_ltm(to_usb_device(dev))) |
307 | return sysfs_emit(buf, fmt: "%s\n" , "yes" ); |
308 | return sysfs_emit(buf, fmt: "%s\n" , "no" ); |
309 | } |
310 | static DEVICE_ATTR_RO(ltm_capable); |
311 | |
312 | #ifdef CONFIG_PM |
313 | |
314 | static ssize_t persist_show(struct device *dev, struct device_attribute *attr, |
315 | char *buf) |
316 | { |
317 | struct usb_device *udev = to_usb_device(dev); |
318 | |
319 | return sysfs_emit(buf, fmt: "%d\n" , udev->persist_enabled); |
320 | } |
321 | |
322 | static ssize_t persist_store(struct device *dev, struct device_attribute *attr, |
323 | const char *buf, size_t count) |
324 | { |
325 | struct usb_device *udev = to_usb_device(dev); |
326 | bool value; |
327 | int rc; |
328 | |
329 | /* Hubs are always enabled for USB_PERSIST */ |
330 | if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) |
331 | return -EPERM; |
332 | |
333 | if (kstrtobool(s: buf, res: &value) != 0) |
334 | return -EINVAL; |
335 | |
336 | rc = usb_lock_device_interruptible(udev); |
337 | if (rc < 0) |
338 | return -EINTR; |
339 | udev->persist_enabled = !!value; |
340 | usb_unlock_device(udev); |
341 | return count; |
342 | } |
343 | static DEVICE_ATTR_RW(persist); |
344 | |
345 | static int add_persist_attributes(struct device *dev) |
346 | { |
347 | int rc = 0; |
348 | |
349 | if (is_usb_device(dev)) { |
350 | struct usb_device *udev = to_usb_device(dev); |
351 | |
352 | /* Hubs are automatically enabled for USB_PERSIST, |
353 | * no point in creating the attribute file. |
354 | */ |
355 | if (udev->descriptor.bDeviceClass != USB_CLASS_HUB) |
356 | rc = sysfs_add_file_to_group(kobj: &dev->kobj, |
357 | attr: &dev_attr_persist.attr, |
358 | group: power_group_name); |
359 | } |
360 | return rc; |
361 | } |
362 | |
363 | static void remove_persist_attributes(struct device *dev) |
364 | { |
365 | sysfs_remove_file_from_group(kobj: &dev->kobj, |
366 | attr: &dev_attr_persist.attr, |
367 | group: power_group_name); |
368 | } |
369 | |
370 | static ssize_t connected_duration_show(struct device *dev, |
371 | struct device_attribute *attr, char *buf) |
372 | { |
373 | struct usb_device *udev = to_usb_device(dev); |
374 | |
375 | return sysfs_emit(buf, fmt: "%u\n" , |
376 | jiffies_to_msecs(j: jiffies - udev->connect_time)); |
377 | } |
378 | static DEVICE_ATTR_RO(connected_duration); |
379 | |
380 | /* |
381 | * If the device is resumed, the last time the device was suspended has |
382 | * been pre-subtracted from active_duration. We add the current time to |
383 | * get the duration that the device was actually active. |
384 | * |
385 | * If the device is suspended, the active_duration is up-to-date. |
386 | */ |
387 | static ssize_t active_duration_show(struct device *dev, |
388 | struct device_attribute *attr, char *buf) |
389 | { |
390 | struct usb_device *udev = to_usb_device(dev); |
391 | int duration; |
392 | |
393 | if (udev->state != USB_STATE_SUSPENDED) |
394 | duration = jiffies_to_msecs(j: jiffies + udev->active_duration); |
395 | else |
396 | duration = jiffies_to_msecs(j: udev->active_duration); |
397 | return sysfs_emit(buf, fmt: "%u\n" , duration); |
398 | } |
399 | static DEVICE_ATTR_RO(active_duration); |
400 | |
401 | static ssize_t autosuspend_show(struct device *dev, |
402 | struct device_attribute *attr, char *buf) |
403 | { |
404 | return sysfs_emit(buf, fmt: "%d\n" , dev->power.autosuspend_delay / 1000); |
405 | } |
406 | |
407 | static ssize_t autosuspend_store(struct device *dev, |
408 | struct device_attribute *attr, const char *buf, |
409 | size_t count) |
410 | { |
411 | int value; |
412 | |
413 | if (sscanf(buf, "%d" , &value) != 1 || value >= INT_MAX/1000 || |
414 | value <= -INT_MAX/1000) |
415 | return -EINVAL; |
416 | |
417 | pm_runtime_set_autosuspend_delay(dev, delay: value * 1000); |
418 | return count; |
419 | } |
420 | static DEVICE_ATTR_RW(autosuspend); |
421 | |
422 | static const char on_string[] = "on" ; |
423 | static const char auto_string[] = "auto" ; |
424 | |
425 | static void warn_level(void) |
426 | { |
427 | static int level_warned; |
428 | |
429 | if (!level_warned) { |
430 | level_warned = 1; |
431 | printk(KERN_WARNING "WARNING! power/level is deprecated; " |
432 | "use power/control instead\n" ); |
433 | } |
434 | } |
435 | |
436 | static ssize_t level_show(struct device *dev, struct device_attribute *attr, |
437 | char *buf) |
438 | { |
439 | struct usb_device *udev = to_usb_device(dev); |
440 | const char *p = auto_string; |
441 | |
442 | warn_level(); |
443 | if (udev->state != USB_STATE_SUSPENDED && !udev->dev.power.runtime_auto) |
444 | p = on_string; |
445 | return sysfs_emit(buf, fmt: "%s\n" , p); |
446 | } |
447 | |
448 | static ssize_t level_store(struct device *dev, struct device_attribute *attr, |
449 | const char *buf, size_t count) |
450 | { |
451 | struct usb_device *udev = to_usb_device(dev); |
452 | int len = count; |
453 | char *cp; |
454 | int rc = count; |
455 | int rv; |
456 | |
457 | warn_level(); |
458 | cp = memchr(p: buf, c: '\n', size: count); |
459 | if (cp) |
460 | len = cp - buf; |
461 | |
462 | rv = usb_lock_device_interruptible(udev); |
463 | if (rv < 0) |
464 | return -EINTR; |
465 | |
466 | if (len == sizeof on_string - 1 && |
467 | strncmp(buf, on_string, len) == 0) |
468 | usb_disable_autosuspend(udev); |
469 | |
470 | else if (len == sizeof auto_string - 1 && |
471 | strncmp(buf, auto_string, len) == 0) |
472 | usb_enable_autosuspend(udev); |
473 | |
474 | else |
475 | rc = -EINVAL; |
476 | |
477 | usb_unlock_device(udev); |
478 | return rc; |
479 | } |
480 | static DEVICE_ATTR_RW(level); |
481 | |
482 | static ssize_t usb2_hardware_lpm_show(struct device *dev, |
483 | struct device_attribute *attr, char *buf) |
484 | { |
485 | struct usb_device *udev = to_usb_device(dev); |
486 | const char *p; |
487 | |
488 | if (udev->usb2_hw_lpm_allowed == 1) |
489 | p = "enabled" ; |
490 | else |
491 | p = "disabled" ; |
492 | |
493 | return sysfs_emit(buf, fmt: "%s\n" , p); |
494 | } |
495 | |
496 | static ssize_t usb2_hardware_lpm_store(struct device *dev, |
497 | struct device_attribute *attr, |
498 | const char *buf, size_t count) |
499 | { |
500 | struct usb_device *udev = to_usb_device(dev); |
501 | bool value; |
502 | int ret; |
503 | |
504 | ret = usb_lock_device_interruptible(udev); |
505 | if (ret < 0) |
506 | return -EINTR; |
507 | |
508 | ret = kstrtobool(s: buf, res: &value); |
509 | |
510 | if (!ret) { |
511 | udev->usb2_hw_lpm_allowed = value; |
512 | if (value) |
513 | ret = usb_enable_usb2_hardware_lpm(udev); |
514 | else |
515 | ret = usb_disable_usb2_hardware_lpm(udev); |
516 | } |
517 | |
518 | usb_unlock_device(udev); |
519 | |
520 | if (!ret) |
521 | return count; |
522 | |
523 | return ret; |
524 | } |
525 | static DEVICE_ATTR_RW(usb2_hardware_lpm); |
526 | |
527 | static ssize_t usb2_lpm_l1_timeout_show(struct device *dev, |
528 | struct device_attribute *attr, |
529 | char *buf) |
530 | { |
531 | struct usb_device *udev = to_usb_device(dev); |
532 | return sysfs_emit(buf, fmt: "%d\n" , udev->l1_params.timeout); |
533 | } |
534 | |
535 | static ssize_t usb2_lpm_l1_timeout_store(struct device *dev, |
536 | struct device_attribute *attr, |
537 | const char *buf, size_t count) |
538 | { |
539 | struct usb_device *udev = to_usb_device(dev); |
540 | u16 timeout; |
541 | |
542 | if (kstrtou16(s: buf, base: 0, res: &timeout)) |
543 | return -EINVAL; |
544 | |
545 | udev->l1_params.timeout = timeout; |
546 | |
547 | return count; |
548 | } |
549 | static DEVICE_ATTR_RW(usb2_lpm_l1_timeout); |
550 | |
551 | static ssize_t usb2_lpm_besl_show(struct device *dev, |
552 | struct device_attribute *attr, char *buf) |
553 | { |
554 | struct usb_device *udev = to_usb_device(dev); |
555 | return sysfs_emit(buf, fmt: "%d\n" , udev->l1_params.besl); |
556 | } |
557 | |
558 | static ssize_t usb2_lpm_besl_store(struct device *dev, |
559 | struct device_attribute *attr, |
560 | const char *buf, size_t count) |
561 | { |
562 | struct usb_device *udev = to_usb_device(dev); |
563 | u8 besl; |
564 | |
565 | if (kstrtou8(s: buf, base: 0, res: &besl) || besl > 15) |
566 | return -EINVAL; |
567 | |
568 | udev->l1_params.besl = besl; |
569 | |
570 | return count; |
571 | } |
572 | static DEVICE_ATTR_RW(usb2_lpm_besl); |
573 | |
574 | static ssize_t usb3_hardware_lpm_u1_show(struct device *dev, |
575 | struct device_attribute *attr, char *buf) |
576 | { |
577 | struct usb_device *udev = to_usb_device(dev); |
578 | const char *p; |
579 | int rc; |
580 | |
581 | rc = usb_lock_device_interruptible(udev); |
582 | if (rc < 0) |
583 | return -EINTR; |
584 | |
585 | if (udev->usb3_lpm_u1_enabled) |
586 | p = "enabled" ; |
587 | else |
588 | p = "disabled" ; |
589 | |
590 | usb_unlock_device(udev); |
591 | |
592 | return sysfs_emit(buf, fmt: "%s\n" , p); |
593 | } |
594 | static DEVICE_ATTR_RO(usb3_hardware_lpm_u1); |
595 | |
596 | static ssize_t usb3_hardware_lpm_u2_show(struct device *dev, |
597 | struct device_attribute *attr, char *buf) |
598 | { |
599 | struct usb_device *udev = to_usb_device(dev); |
600 | const char *p; |
601 | int rc; |
602 | |
603 | rc = usb_lock_device_interruptible(udev); |
604 | if (rc < 0) |
605 | return -EINTR; |
606 | |
607 | if (udev->usb3_lpm_u2_enabled) |
608 | p = "enabled" ; |
609 | else |
610 | p = "disabled" ; |
611 | |
612 | usb_unlock_device(udev); |
613 | |
614 | return sysfs_emit(buf, fmt: "%s\n" , p); |
615 | } |
616 | static DEVICE_ATTR_RO(usb3_hardware_lpm_u2); |
617 | |
618 | static struct attribute *usb2_hardware_lpm_attr[] = { |
619 | &dev_attr_usb2_hardware_lpm.attr, |
620 | &dev_attr_usb2_lpm_l1_timeout.attr, |
621 | &dev_attr_usb2_lpm_besl.attr, |
622 | NULL, |
623 | }; |
624 | static const struct attribute_group usb2_hardware_lpm_attr_group = { |
625 | .name = power_group_name, |
626 | .attrs = usb2_hardware_lpm_attr, |
627 | }; |
628 | |
629 | static struct attribute *usb3_hardware_lpm_attr[] = { |
630 | &dev_attr_usb3_hardware_lpm_u1.attr, |
631 | &dev_attr_usb3_hardware_lpm_u2.attr, |
632 | NULL, |
633 | }; |
634 | static const struct attribute_group usb3_hardware_lpm_attr_group = { |
635 | .name = power_group_name, |
636 | .attrs = usb3_hardware_lpm_attr, |
637 | }; |
638 | |
639 | static struct attribute *power_attrs[] = { |
640 | &dev_attr_autosuspend.attr, |
641 | &dev_attr_level.attr, |
642 | &dev_attr_connected_duration.attr, |
643 | &dev_attr_active_duration.attr, |
644 | NULL, |
645 | }; |
646 | static const struct attribute_group power_attr_group = { |
647 | .name = power_group_name, |
648 | .attrs = power_attrs, |
649 | }; |
650 | |
651 | static int add_power_attributes(struct device *dev) |
652 | { |
653 | int rc = 0; |
654 | |
655 | if (is_usb_device(dev)) { |
656 | struct usb_device *udev = to_usb_device(dev); |
657 | rc = sysfs_merge_group(kobj: &dev->kobj, grp: &power_attr_group); |
658 | if (udev->usb2_hw_lpm_capable == 1) |
659 | rc = sysfs_merge_group(kobj: &dev->kobj, |
660 | grp: &usb2_hardware_lpm_attr_group); |
661 | if ((udev->speed == USB_SPEED_SUPER || |
662 | udev->speed == USB_SPEED_SUPER_PLUS) && |
663 | udev->lpm_capable == 1) |
664 | rc = sysfs_merge_group(kobj: &dev->kobj, |
665 | grp: &usb3_hardware_lpm_attr_group); |
666 | } |
667 | |
668 | return rc; |
669 | } |
670 | |
671 | static void remove_power_attributes(struct device *dev) |
672 | { |
673 | sysfs_unmerge_group(kobj: &dev->kobj, grp: &usb2_hardware_lpm_attr_group); |
674 | sysfs_unmerge_group(kobj: &dev->kobj, grp: &power_attr_group); |
675 | } |
676 | |
677 | #else |
678 | |
679 | #define add_persist_attributes(dev) 0 |
680 | #define remove_persist_attributes(dev) do {} while (0) |
681 | |
682 | #define add_power_attributes(dev) 0 |
683 | #define remove_power_attributes(dev) do {} while (0) |
684 | |
685 | #endif /* CONFIG_PM */ |
686 | |
687 | |
688 | /* Descriptor fields */ |
689 | #define usb_descriptor_attr_le16(field, format_string) \ |
690 | static ssize_t \ |
691 | field##_show(struct device *dev, struct device_attribute *attr, \ |
692 | char *buf) \ |
693 | { \ |
694 | struct usb_device *udev; \ |
695 | \ |
696 | udev = to_usb_device(dev); \ |
697 | return sysfs_emit(buf, format_string, \ |
698 | le16_to_cpu(udev->descriptor.field)); \ |
699 | } \ |
700 | static DEVICE_ATTR_RO(field) |
701 | |
702 | usb_descriptor_attr_le16(idVendor, "%04x\n" ); |
703 | usb_descriptor_attr_le16(idProduct, "%04x\n" ); |
704 | usb_descriptor_attr_le16(bcdDevice, "%04x\n" ); |
705 | |
706 | #define usb_descriptor_attr(field, format_string) \ |
707 | static ssize_t \ |
708 | field##_show(struct device *dev, struct device_attribute *attr, \ |
709 | char *buf) \ |
710 | { \ |
711 | struct usb_device *udev; \ |
712 | \ |
713 | udev = to_usb_device(dev); \ |
714 | return sysfs_emit(buf, format_string, udev->descriptor.field); \ |
715 | } \ |
716 | static DEVICE_ATTR_RO(field) |
717 | |
718 | usb_descriptor_attr(bDeviceClass, "%02x\n" ); |
719 | usb_descriptor_attr(bDeviceSubClass, "%02x\n" ); |
720 | usb_descriptor_attr(bDeviceProtocol, "%02x\n" ); |
721 | usb_descriptor_attr(bNumConfigurations, "%d\n" ); |
722 | usb_descriptor_attr(bMaxPacketSize0, "%d\n" ); |
723 | |
724 | |
725 | /* show if the device is authorized (1) or not (0) */ |
726 | static ssize_t authorized_show(struct device *dev, |
727 | struct device_attribute *attr, char *buf) |
728 | { |
729 | struct usb_device *usb_dev = to_usb_device(dev); |
730 | return sysfs_emit(buf, fmt: "%u\n" , usb_dev->authorized); |
731 | } |
732 | |
733 | /* |
734 | * Authorize a device to be used in the system |
735 | * |
736 | * Writing a 0 deauthorizes the device, writing a 1 authorizes it. |
737 | */ |
738 | static ssize_t authorized_store(struct device *dev, |
739 | struct device_attribute *attr, const char *buf, |
740 | size_t size) |
741 | { |
742 | ssize_t result; |
743 | struct usb_device *usb_dev = to_usb_device(dev); |
744 | bool val; |
745 | |
746 | if (kstrtobool(s: buf, res: &val) != 0) |
747 | result = -EINVAL; |
748 | else if (val) |
749 | result = usb_authorize_device(usb_dev); |
750 | else |
751 | result = usb_deauthorize_device(usb_dev); |
752 | return result < 0 ? result : size; |
753 | } |
754 | static DEVICE_ATTR_IGNORE_LOCKDEP(authorized, S_IRUGO | S_IWUSR, |
755 | authorized_show, authorized_store); |
756 | |
757 | /* "Safely remove a device" */ |
758 | static ssize_t remove_store(struct device *dev, struct device_attribute *attr, |
759 | const char *buf, size_t count) |
760 | { |
761 | struct usb_device *udev = to_usb_device(dev); |
762 | int rc = 0; |
763 | |
764 | usb_lock_device(udev); |
765 | if (udev->state != USB_STATE_NOTATTACHED) { |
766 | |
767 | /* To avoid races, first unconfigure and then remove */ |
768 | usb_set_configuration(dev: udev, configuration: -1); |
769 | rc = usb_remove_device(udev); |
770 | } |
771 | if (rc == 0) |
772 | rc = count; |
773 | usb_unlock_device(udev); |
774 | return rc; |
775 | } |
776 | static DEVICE_ATTR_IGNORE_LOCKDEP(remove, S_IWUSR, NULL, remove_store); |
777 | |
778 | |
779 | static struct attribute *dev_attrs[] = { |
780 | /* current configuration's attributes */ |
781 | &dev_attr_configuration.attr, |
782 | &dev_attr_bNumInterfaces.attr, |
783 | &dev_attr_bConfigurationValue.attr, |
784 | &dev_attr_bmAttributes.attr, |
785 | &dev_attr_bMaxPower.attr, |
786 | /* device attributes */ |
787 | &dev_attr_urbnum.attr, |
788 | &dev_attr_idVendor.attr, |
789 | &dev_attr_idProduct.attr, |
790 | &dev_attr_bcdDevice.attr, |
791 | &dev_attr_bDeviceClass.attr, |
792 | &dev_attr_bDeviceSubClass.attr, |
793 | &dev_attr_bDeviceProtocol.attr, |
794 | &dev_attr_bNumConfigurations.attr, |
795 | &dev_attr_bMaxPacketSize0.attr, |
796 | &dev_attr_speed.attr, |
797 | &dev_attr_rx_lanes.attr, |
798 | &dev_attr_tx_lanes.attr, |
799 | &dev_attr_busnum.attr, |
800 | &dev_attr_devnum.attr, |
801 | &dev_attr_devpath.attr, |
802 | &dev_attr_version.attr, |
803 | &dev_attr_maxchild.attr, |
804 | &dev_attr_quirks.attr, |
805 | &dev_attr_avoid_reset_quirk.attr, |
806 | &dev_attr_authorized.attr, |
807 | &dev_attr_remove.attr, |
808 | &dev_attr_ltm_capable.attr, |
809 | #ifdef CONFIG_OF |
810 | &dev_attr_devspec.attr, |
811 | #endif |
812 | NULL, |
813 | }; |
814 | static const struct attribute_group dev_attr_grp = { |
815 | .attrs = dev_attrs, |
816 | }; |
817 | |
818 | /* When modifying this list, be sure to modify dev_string_attrs_are_visible() |
819 | * accordingly. |
820 | */ |
821 | static struct attribute *dev_string_attrs[] = { |
822 | &dev_attr_manufacturer.attr, |
823 | &dev_attr_product.attr, |
824 | &dev_attr_serial.attr, |
825 | NULL |
826 | }; |
827 | |
828 | static umode_t dev_string_attrs_are_visible(struct kobject *kobj, |
829 | struct attribute *a, int n) |
830 | { |
831 | struct device *dev = kobj_to_dev(kobj); |
832 | struct usb_device *udev = to_usb_device(dev); |
833 | |
834 | if (a == &dev_attr_manufacturer.attr) { |
835 | if (udev->manufacturer == NULL) |
836 | return 0; |
837 | } else if (a == &dev_attr_product.attr) { |
838 | if (udev->product == NULL) |
839 | return 0; |
840 | } else if (a == &dev_attr_serial.attr) { |
841 | if (udev->serial == NULL) |
842 | return 0; |
843 | } |
844 | return a->mode; |
845 | } |
846 | |
847 | static const struct attribute_group dev_string_attr_grp = { |
848 | .attrs = dev_string_attrs, |
849 | .is_visible = dev_string_attrs_are_visible, |
850 | }; |
851 | |
852 | /* Binary descriptors */ |
853 | |
854 | static ssize_t |
855 | descriptors_read(struct file *filp, struct kobject *kobj, |
856 | struct bin_attribute *attr, |
857 | char *buf, loff_t off, size_t count) |
858 | { |
859 | struct device *dev = kobj_to_dev(kobj); |
860 | struct usb_device *udev = to_usb_device(dev); |
861 | size_t nleft = count; |
862 | size_t srclen, n; |
863 | int cfgno; |
864 | void *src; |
865 | |
866 | /* The binary attribute begins with the device descriptor. |
867 | * Following that are the raw descriptor entries for all the |
868 | * configurations (config plus subsidiary descriptors). |
869 | */ |
870 | for (cfgno = -1; cfgno < udev->descriptor.bNumConfigurations && |
871 | nleft > 0; ++cfgno) { |
872 | if (cfgno < 0) { |
873 | src = &udev->descriptor; |
874 | srclen = sizeof(struct usb_device_descriptor); |
875 | } else { |
876 | src = udev->rawdescriptors[cfgno]; |
877 | srclen = le16_to_cpu(udev->config[cfgno].desc. |
878 | wTotalLength); |
879 | } |
880 | if (off < srclen) { |
881 | n = min(nleft, srclen - (size_t) off); |
882 | memcpy(buf, src + off, n); |
883 | nleft -= n; |
884 | buf += n; |
885 | off = 0; |
886 | } else { |
887 | off -= srclen; |
888 | } |
889 | } |
890 | return count - nleft; |
891 | } |
892 | static BIN_ATTR_RO(descriptors, 18 + 65535); /* dev descr + max-size raw descriptor */ |
893 | |
894 | static ssize_t |
895 | bos_descriptors_read(struct file *filp, struct kobject *kobj, |
896 | struct bin_attribute *attr, |
897 | char *buf, loff_t off, size_t count) |
898 | { |
899 | struct device *dev = kobj_to_dev(kobj); |
900 | struct usb_device *udev = to_usb_device(dev); |
901 | struct usb_host_bos *bos = udev->bos; |
902 | struct usb_bos_descriptor *desc; |
903 | size_t desclen, n = 0; |
904 | |
905 | if (bos) { |
906 | desc = bos->desc; |
907 | desclen = le16_to_cpu(desc->wTotalLength); |
908 | if (off < desclen) { |
909 | n = min(count, desclen - (size_t) off); |
910 | memcpy(buf, (void *) desc + off, n); |
911 | } |
912 | } |
913 | return n; |
914 | } |
915 | static BIN_ATTR_RO(bos_descriptors, 65535); /* max-size BOS */ |
916 | |
917 | /* When modifying this list, be sure to modify dev_bin_attrs_are_visible() |
918 | * accordingly. |
919 | */ |
920 | static struct bin_attribute *dev_bin_attrs[] = { |
921 | &bin_attr_descriptors, |
922 | &bin_attr_bos_descriptors, |
923 | NULL |
924 | }; |
925 | |
926 | static umode_t dev_bin_attrs_are_visible(struct kobject *kobj, |
927 | struct bin_attribute *a, int n) |
928 | { |
929 | struct device *dev = kobj_to_dev(kobj); |
930 | struct usb_device *udev = to_usb_device(dev); |
931 | |
932 | /* |
933 | * There's no need to check if the descriptors attribute should |
934 | * be visible because all devices have a device descriptor. The |
935 | * bos_descriptors attribute should be visible if and only if |
936 | * the device has a BOS, so check if it exists here. |
937 | */ |
938 | if (a == &bin_attr_bos_descriptors) { |
939 | if (udev->bos == NULL) |
940 | return 0; |
941 | } |
942 | return a->attr.mode; |
943 | } |
944 | |
945 | static const struct attribute_group dev_bin_attr_grp = { |
946 | .bin_attrs = dev_bin_attrs, |
947 | .is_bin_visible = dev_bin_attrs_are_visible, |
948 | }; |
949 | |
950 | const struct attribute_group *usb_device_groups[] = { |
951 | &dev_attr_grp, |
952 | &dev_string_attr_grp, |
953 | &dev_bin_attr_grp, |
954 | NULL |
955 | }; |
956 | |
957 | /* |
958 | * Show & store the current value of authorized_default |
959 | */ |
960 | static ssize_t authorized_default_show(struct device *dev, |
961 | struct device_attribute *attr, char *buf) |
962 | { |
963 | struct usb_device *rh_usb_dev = to_usb_device(dev); |
964 | struct usb_bus *usb_bus = rh_usb_dev->bus; |
965 | struct usb_hcd *hcd; |
966 | |
967 | hcd = bus_to_hcd(bus: usb_bus); |
968 | return sysfs_emit(buf, fmt: "%u\n" , hcd->dev_policy); |
969 | } |
970 | |
971 | static ssize_t authorized_default_store(struct device *dev, |
972 | struct device_attribute *attr, |
973 | const char *buf, size_t size) |
974 | { |
975 | ssize_t result; |
976 | unsigned int val; |
977 | struct usb_device *rh_usb_dev = to_usb_device(dev); |
978 | struct usb_bus *usb_bus = rh_usb_dev->bus; |
979 | struct usb_hcd *hcd; |
980 | |
981 | hcd = bus_to_hcd(bus: usb_bus); |
982 | result = sscanf(buf, "%u\n" , &val); |
983 | if (result == 1) { |
984 | hcd->dev_policy = val <= USB_DEVICE_AUTHORIZE_INTERNAL ? |
985 | val : USB_DEVICE_AUTHORIZE_ALL; |
986 | result = size; |
987 | } else { |
988 | result = -EINVAL; |
989 | } |
990 | return result; |
991 | } |
992 | static DEVICE_ATTR_RW(authorized_default); |
993 | |
994 | /* |
995 | * interface_authorized_default_show - show default authorization status |
996 | * for USB interfaces |
997 | * |
998 | * note: interface_authorized_default is the default value |
999 | * for initializing the authorized attribute of interfaces |
1000 | */ |
1001 | static ssize_t interface_authorized_default_show(struct device *dev, |
1002 | struct device_attribute *attr, char *buf) |
1003 | { |
1004 | struct usb_device *usb_dev = to_usb_device(dev); |
1005 | struct usb_hcd *hcd = bus_to_hcd(bus: usb_dev->bus); |
1006 | |
1007 | return sysfs_emit(buf, fmt: "%u\n" , !!HCD_INTF_AUTHORIZED(hcd)); |
1008 | } |
1009 | |
1010 | /* |
1011 | * interface_authorized_default_store - store default authorization status |
1012 | * for USB interfaces |
1013 | * |
1014 | * note: interface_authorized_default is the default value |
1015 | * for initializing the authorized attribute of interfaces |
1016 | */ |
1017 | static ssize_t interface_authorized_default_store(struct device *dev, |
1018 | struct device_attribute *attr, const char *buf, size_t count) |
1019 | { |
1020 | struct usb_device *usb_dev = to_usb_device(dev); |
1021 | struct usb_hcd *hcd = bus_to_hcd(bus: usb_dev->bus); |
1022 | int rc = count; |
1023 | bool val; |
1024 | |
1025 | if (kstrtobool(s: buf, res: &val) != 0) |
1026 | return -EINVAL; |
1027 | |
1028 | if (val) |
1029 | set_bit(HCD_FLAG_INTF_AUTHORIZED, addr: &hcd->flags); |
1030 | else |
1031 | clear_bit(HCD_FLAG_INTF_AUTHORIZED, addr: &hcd->flags); |
1032 | |
1033 | return rc; |
1034 | } |
1035 | static DEVICE_ATTR_RW(interface_authorized_default); |
1036 | |
1037 | /* Group all the USB bus attributes */ |
1038 | static struct attribute *usb_bus_attrs[] = { |
1039 | &dev_attr_authorized_default.attr, |
1040 | &dev_attr_interface_authorized_default.attr, |
1041 | NULL, |
1042 | }; |
1043 | |
1044 | static const struct attribute_group usb_bus_attr_group = { |
1045 | .name = NULL, /* we want them in the same directory */ |
1046 | .attrs = usb_bus_attrs, |
1047 | }; |
1048 | |
1049 | |
1050 | static int add_default_authorized_attributes(struct device *dev) |
1051 | { |
1052 | int rc = 0; |
1053 | |
1054 | if (is_usb_device(dev)) |
1055 | rc = sysfs_create_group(kobj: &dev->kobj, grp: &usb_bus_attr_group); |
1056 | |
1057 | return rc; |
1058 | } |
1059 | |
1060 | static void remove_default_authorized_attributes(struct device *dev) |
1061 | { |
1062 | if (is_usb_device(dev)) { |
1063 | sysfs_remove_group(kobj: &dev->kobj, grp: &usb_bus_attr_group); |
1064 | } |
1065 | } |
1066 | |
1067 | int usb_create_sysfs_dev_files(struct usb_device *udev) |
1068 | { |
1069 | struct device *dev = &udev->dev; |
1070 | int retval; |
1071 | |
1072 | retval = add_persist_attributes(dev); |
1073 | if (retval) |
1074 | goto error; |
1075 | |
1076 | retval = add_power_attributes(dev); |
1077 | if (retval) |
1078 | goto error; |
1079 | |
1080 | if (is_root_hub(udev)) { |
1081 | retval = add_default_authorized_attributes(dev); |
1082 | if (retval) |
1083 | goto error; |
1084 | } |
1085 | return retval; |
1086 | |
1087 | error: |
1088 | usb_remove_sysfs_dev_files(dev: udev); |
1089 | return retval; |
1090 | } |
1091 | |
1092 | void usb_remove_sysfs_dev_files(struct usb_device *udev) |
1093 | { |
1094 | struct device *dev = &udev->dev; |
1095 | |
1096 | if (is_root_hub(udev)) |
1097 | remove_default_authorized_attributes(dev); |
1098 | |
1099 | remove_power_attributes(dev); |
1100 | remove_persist_attributes(dev); |
1101 | } |
1102 | |
1103 | /* Interface Association Descriptor fields */ |
1104 | #define usb_intf_assoc_attr(field, format_string) \ |
1105 | static ssize_t \ |
1106 | iad_##field##_show(struct device *dev, struct device_attribute *attr, \ |
1107 | char *buf) \ |
1108 | { \ |
1109 | struct usb_interface *intf = to_usb_interface(dev); \ |
1110 | \ |
1111 | return sysfs_emit(buf, format_string, \ |
1112 | intf->intf_assoc->field); \ |
1113 | } \ |
1114 | static DEVICE_ATTR_RO(iad_##field) |
1115 | |
1116 | usb_intf_assoc_attr(bFirstInterface, "%02x\n" ); |
1117 | usb_intf_assoc_attr(bInterfaceCount, "%02d\n" ); |
1118 | usb_intf_assoc_attr(bFunctionClass, "%02x\n" ); |
1119 | usb_intf_assoc_attr(bFunctionSubClass, "%02x\n" ); |
1120 | usb_intf_assoc_attr(bFunctionProtocol, "%02x\n" ); |
1121 | |
1122 | /* Interface fields */ |
1123 | #define usb_intf_attr(field, format_string) \ |
1124 | static ssize_t \ |
1125 | field##_show(struct device *dev, struct device_attribute *attr, \ |
1126 | char *buf) \ |
1127 | { \ |
1128 | struct usb_interface *intf = to_usb_interface(dev); \ |
1129 | \ |
1130 | return sysfs_emit(buf, format_string, \ |
1131 | intf->cur_altsetting->desc.field); \ |
1132 | } \ |
1133 | static DEVICE_ATTR_RO(field) |
1134 | |
1135 | usb_intf_attr(bInterfaceNumber, "%02x\n" ); |
1136 | usb_intf_attr(bAlternateSetting, "%2d\n" ); |
1137 | usb_intf_attr(bNumEndpoints, "%02x\n" ); |
1138 | usb_intf_attr(bInterfaceClass, "%02x\n" ); |
1139 | usb_intf_attr(bInterfaceSubClass, "%02x\n" ); |
1140 | usb_intf_attr(bInterfaceProtocol, "%02x\n" ); |
1141 | |
1142 | static ssize_t interface_show(struct device *dev, struct device_attribute *attr, |
1143 | char *buf) |
1144 | { |
1145 | struct usb_interface *intf; |
1146 | char *string; |
1147 | |
1148 | intf = to_usb_interface(dev); |
1149 | string = READ_ONCE(intf->cur_altsetting->string); |
1150 | if (!string) |
1151 | return 0; |
1152 | return sysfs_emit(buf, fmt: "%s\n" , string); |
1153 | } |
1154 | static DEVICE_ATTR_RO(interface); |
1155 | |
1156 | static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, |
1157 | char *buf) |
1158 | { |
1159 | struct usb_interface *intf; |
1160 | struct usb_device *udev; |
1161 | struct usb_host_interface *alt; |
1162 | |
1163 | intf = to_usb_interface(dev); |
1164 | udev = interface_to_usbdev(intf); |
1165 | alt = READ_ONCE(intf->cur_altsetting); |
1166 | |
1167 | return sysfs_emit(buf, |
1168 | fmt: "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X" |
1169 | "ic%02Xisc%02Xip%02Xin%02X\n" , |
1170 | le16_to_cpu(udev->descriptor.idVendor), |
1171 | le16_to_cpu(udev->descriptor.idProduct), |
1172 | le16_to_cpu(udev->descriptor.bcdDevice), |
1173 | udev->descriptor.bDeviceClass, |
1174 | udev->descriptor.bDeviceSubClass, |
1175 | udev->descriptor.bDeviceProtocol, |
1176 | alt->desc.bInterfaceClass, |
1177 | alt->desc.bInterfaceSubClass, |
1178 | alt->desc.bInterfaceProtocol, |
1179 | alt->desc.bInterfaceNumber); |
1180 | } |
1181 | static DEVICE_ATTR_RO(modalias); |
1182 | |
1183 | static ssize_t supports_autosuspend_show(struct device *dev, |
1184 | struct device_attribute *attr, |
1185 | char *buf) |
1186 | { |
1187 | int s; |
1188 | |
1189 | s = device_lock_interruptible(dev); |
1190 | if (s < 0) |
1191 | return -EINTR; |
1192 | /* Devices will be autosuspended even when an interface isn't claimed */ |
1193 | s = (!dev->driver || to_usb_driver(dev->driver)->supports_autosuspend); |
1194 | device_unlock(dev); |
1195 | |
1196 | return sysfs_emit(buf, fmt: "%u\n" , s); |
1197 | } |
1198 | static DEVICE_ATTR_RO(supports_autosuspend); |
1199 | |
1200 | /* |
1201 | * interface_authorized_show - show authorization status of an USB interface |
1202 | * 1 is authorized, 0 is deauthorized |
1203 | */ |
1204 | static ssize_t interface_authorized_show(struct device *dev, |
1205 | struct device_attribute *attr, char *buf) |
1206 | { |
1207 | struct usb_interface *intf = to_usb_interface(dev); |
1208 | |
1209 | return sysfs_emit(buf, fmt: "%u\n" , intf->authorized); |
1210 | } |
1211 | |
1212 | /* |
1213 | * interface_authorized_store - authorize or deauthorize an USB interface |
1214 | */ |
1215 | static ssize_t interface_authorized_store(struct device *dev, |
1216 | struct device_attribute *attr, const char *buf, size_t count) |
1217 | { |
1218 | struct usb_interface *intf = to_usb_interface(dev); |
1219 | bool val; |
1220 | struct kernfs_node *kn; |
1221 | |
1222 | if (kstrtobool(s: buf, res: &val) != 0) |
1223 | return -EINVAL; |
1224 | |
1225 | if (val) { |
1226 | usb_authorize_interface(intf); |
1227 | } else { |
1228 | /* |
1229 | * Prevent deadlock if another process is concurrently |
1230 | * trying to unregister intf. |
1231 | */ |
1232 | kn = sysfs_break_active_protection(kobj: &dev->kobj, attr: &attr->attr); |
1233 | if (kn) { |
1234 | usb_deauthorize_interface(intf); |
1235 | sysfs_unbreak_active_protection(kn); |
1236 | } |
1237 | } |
1238 | |
1239 | return count; |
1240 | } |
1241 | static struct device_attribute dev_attr_interface_authorized = |
1242 | __ATTR(authorized, S_IRUGO | S_IWUSR, |
1243 | interface_authorized_show, interface_authorized_store); |
1244 | |
1245 | static struct attribute *intf_attrs[] = { |
1246 | &dev_attr_bInterfaceNumber.attr, |
1247 | &dev_attr_bAlternateSetting.attr, |
1248 | &dev_attr_bNumEndpoints.attr, |
1249 | &dev_attr_bInterfaceClass.attr, |
1250 | &dev_attr_bInterfaceSubClass.attr, |
1251 | &dev_attr_bInterfaceProtocol.attr, |
1252 | &dev_attr_modalias.attr, |
1253 | &dev_attr_supports_autosuspend.attr, |
1254 | &dev_attr_interface_authorized.attr, |
1255 | NULL, |
1256 | }; |
1257 | static const struct attribute_group intf_attr_grp = { |
1258 | .attrs = intf_attrs, |
1259 | }; |
1260 | |
1261 | static struct attribute *intf_assoc_attrs[] = { |
1262 | &dev_attr_iad_bFirstInterface.attr, |
1263 | &dev_attr_iad_bInterfaceCount.attr, |
1264 | &dev_attr_iad_bFunctionClass.attr, |
1265 | &dev_attr_iad_bFunctionSubClass.attr, |
1266 | &dev_attr_iad_bFunctionProtocol.attr, |
1267 | NULL, |
1268 | }; |
1269 | |
1270 | static umode_t intf_assoc_attrs_are_visible(struct kobject *kobj, |
1271 | struct attribute *a, int n) |
1272 | { |
1273 | struct device *dev = kobj_to_dev(kobj); |
1274 | struct usb_interface *intf = to_usb_interface(dev); |
1275 | |
1276 | if (intf->intf_assoc == NULL) |
1277 | return 0; |
1278 | return a->mode; |
1279 | } |
1280 | |
1281 | static const struct attribute_group intf_assoc_attr_grp = { |
1282 | .attrs = intf_assoc_attrs, |
1283 | .is_visible = intf_assoc_attrs_are_visible, |
1284 | }; |
1285 | |
1286 | static ssize_t wireless_status_show(struct device *dev, |
1287 | struct device_attribute *attr, char *buf) |
1288 | { |
1289 | struct usb_interface *intf; |
1290 | |
1291 | intf = to_usb_interface(dev); |
1292 | if (intf->wireless_status == USB_WIRELESS_STATUS_DISCONNECTED) |
1293 | return sysfs_emit(buf, fmt: "%s\n" , "disconnected" ); |
1294 | return sysfs_emit(buf, fmt: "%s\n" , "connected" ); |
1295 | } |
1296 | static DEVICE_ATTR_RO(wireless_status); |
1297 | |
1298 | static struct attribute *intf_wireless_status_attrs[] = { |
1299 | &dev_attr_wireless_status.attr, |
1300 | NULL |
1301 | }; |
1302 | |
1303 | static umode_t intf_wireless_status_attr_is_visible(struct kobject *kobj, |
1304 | struct attribute *a, int n) |
1305 | { |
1306 | struct device *dev = kobj_to_dev(kobj); |
1307 | struct usb_interface *intf = to_usb_interface(dev); |
1308 | |
1309 | if (a != &dev_attr_wireless_status.attr || |
1310 | intf->wireless_status != USB_WIRELESS_STATUS_NA) |
1311 | return a->mode; |
1312 | return 0; |
1313 | } |
1314 | |
1315 | static const struct attribute_group intf_wireless_status_attr_grp = { |
1316 | .attrs = intf_wireless_status_attrs, |
1317 | .is_visible = intf_wireless_status_attr_is_visible, |
1318 | }; |
1319 | |
1320 | int usb_update_wireless_status_attr(struct usb_interface *intf) |
1321 | { |
1322 | struct device *dev = &intf->dev; |
1323 | int ret; |
1324 | |
1325 | ret = sysfs_update_group(kobj: &dev->kobj, grp: &intf_wireless_status_attr_grp); |
1326 | if (ret < 0) |
1327 | return ret; |
1328 | |
1329 | sysfs_notify(kobj: &dev->kobj, NULL, attr: "wireless_status" ); |
1330 | kobject_uevent(kobj: &dev->kobj, action: KOBJ_CHANGE); |
1331 | |
1332 | return 0; |
1333 | } |
1334 | |
1335 | const struct attribute_group *usb_interface_groups[] = { |
1336 | &intf_attr_grp, |
1337 | &intf_assoc_attr_grp, |
1338 | &intf_wireless_status_attr_grp, |
1339 | NULL |
1340 | }; |
1341 | |
1342 | void usb_create_sysfs_intf_files(struct usb_interface *intf) |
1343 | { |
1344 | struct usb_device *udev = interface_to_usbdev(intf); |
1345 | struct usb_host_interface *alt = intf->cur_altsetting; |
1346 | |
1347 | if (intf->sysfs_files_created || intf->unregistering) |
1348 | return; |
1349 | |
1350 | if (!alt->string && !(udev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) |
1351 | alt->string = usb_cache_string(udev, index: alt->desc.iInterface); |
1352 | if (alt->string && device_create_file(device: &intf->dev, entry: &dev_attr_interface)) { |
1353 | /* This is not a serious error */ |
1354 | dev_dbg(&intf->dev, "interface string descriptor file not created\n" ); |
1355 | } |
1356 | intf->sysfs_files_created = 1; |
1357 | } |
1358 | |
1359 | void usb_remove_sysfs_intf_files(struct usb_interface *intf) |
1360 | { |
1361 | if (!intf->sysfs_files_created) |
1362 | return; |
1363 | |
1364 | device_remove_file(dev: &intf->dev, attr: &dev_attr_interface); |
1365 | intf->sysfs_files_created = 0; |
1366 | } |
1367 | |