1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include <linux/configfs.h> |
3 | #include <linux/module.h> |
4 | #include <linux/slab.h> |
5 | #include <linux/device.h> |
6 | #include <linux/kstrtox.h> |
7 | #include <linux/nls.h> |
8 | #include <linux/usb/composite.h> |
9 | #include <linux/usb/gadget_configfs.h> |
10 | #include <linux/usb/webusb.h> |
11 | #include "configfs.h" |
12 | #include "u_f.h" |
13 | #include "u_os_desc.h" |
14 | |
15 | int check_user_usb_string(const char *name, |
16 | struct usb_gadget_strings *stringtab_dev) |
17 | { |
18 | u16 num; |
19 | int ret; |
20 | |
21 | ret = kstrtou16(s: name, base: 0, res: &num); |
22 | if (ret) |
23 | return ret; |
24 | |
25 | if (!usb_validate_langid(langid: num)) |
26 | return -EINVAL; |
27 | |
28 | stringtab_dev->language = num; |
29 | return 0; |
30 | } |
31 | |
32 | #define MAX_NAME_LEN 40 |
33 | #define MAX_USB_STRING_LANGS 2 |
34 | |
35 | static const struct usb_descriptor_header *otg_desc[2]; |
36 | |
37 | struct gadget_info { |
38 | struct config_group group; |
39 | struct config_group functions_group; |
40 | struct config_group configs_group; |
41 | struct config_group strings_group; |
42 | struct config_group os_desc_group; |
43 | struct config_group webusb_group; |
44 | |
45 | struct mutex lock; |
46 | struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1]; |
47 | struct list_head string_list; |
48 | struct list_head available_func; |
49 | |
50 | struct usb_composite_driver composite; |
51 | struct usb_composite_dev cdev; |
52 | bool use_os_desc; |
53 | char b_vendor_code; |
54 | char qw_sign[OS_STRING_QW_SIGN_LEN]; |
55 | bool use_webusb; |
56 | u16 bcd_webusb_version; |
57 | u8 b_webusb_vendor_code; |
58 | char landing_page[WEBUSB_URL_RAW_MAX_LENGTH]; |
59 | |
60 | spinlock_t spinlock; |
61 | bool unbind; |
62 | }; |
63 | |
64 | static inline struct gadget_info *to_gadget_info(struct config_item *item) |
65 | { |
66 | return container_of(to_config_group(item), struct gadget_info, group); |
67 | } |
68 | |
69 | struct config_usb_cfg { |
70 | struct config_group group; |
71 | struct config_group strings_group; |
72 | struct list_head string_list; |
73 | struct usb_configuration c; |
74 | struct list_head func_list; |
75 | struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1]; |
76 | }; |
77 | |
78 | static inline struct config_usb_cfg *to_config_usb_cfg(struct config_item *item) |
79 | { |
80 | return container_of(to_config_group(item), struct config_usb_cfg, |
81 | group); |
82 | } |
83 | |
84 | static inline struct gadget_info *cfg_to_gadget_info(struct config_usb_cfg *cfg) |
85 | { |
86 | return container_of(cfg->c.cdev, struct gadget_info, cdev); |
87 | } |
88 | |
89 | struct gadget_language { |
90 | struct usb_gadget_strings stringtab_dev; |
91 | struct usb_string strings[USB_GADGET_FIRST_AVAIL_IDX]; |
92 | char *manufacturer; |
93 | char *product; |
94 | char *serialnumber; |
95 | |
96 | struct config_group group; |
97 | struct list_head list; |
98 | struct list_head gadget_strings; |
99 | unsigned int nstrings; |
100 | }; |
101 | |
102 | struct gadget_config_name { |
103 | struct usb_gadget_strings stringtab_dev; |
104 | struct usb_string strings; |
105 | char *configuration; |
106 | |
107 | struct config_group group; |
108 | struct list_head list; |
109 | }; |
110 | |
111 | #define USB_MAX_STRING_WITH_NULL_LEN (USB_MAX_STRING_LEN+1) |
112 | |
113 | static int usb_string_copy(const char *s, char **s_copy) |
114 | { |
115 | int ret; |
116 | char *str; |
117 | char *copy = *s_copy; |
118 | ret = strlen(s); |
119 | if (ret > USB_MAX_STRING_LEN) |
120 | return -EOVERFLOW; |
121 | |
122 | if (copy) { |
123 | str = copy; |
124 | } else { |
125 | str = kmalloc(USB_MAX_STRING_WITH_NULL_LEN, GFP_KERNEL); |
126 | if (!str) |
127 | return -ENOMEM; |
128 | } |
129 | strcpy(p: str, q: s); |
130 | if (str[ret - 1] == '\n') |
131 | str[ret - 1] = '\0'; |
132 | *s_copy = str; |
133 | return 0; |
134 | } |
135 | |
136 | #define GI_DEVICE_DESC_SIMPLE_R_u8(__name) \ |
137 | static ssize_t gadget_dev_desc_##__name##_show(struct config_item *item, \ |
138 | char *page) \ |
139 | { \ |
140 | return sprintf(page, "0x%02x\n", \ |
141 | to_gadget_info(item)->cdev.desc.__name); \ |
142 | } |
143 | |
144 | #define GI_DEVICE_DESC_SIMPLE_R_u16(__name) \ |
145 | static ssize_t gadget_dev_desc_##__name##_show(struct config_item *item, \ |
146 | char *page) \ |
147 | { \ |
148 | return sprintf(page, "0x%04x\n", \ |
149 | le16_to_cpup(&to_gadget_info(item)->cdev.desc.__name)); \ |
150 | } |
151 | |
152 | |
153 | #define GI_DEVICE_DESC_SIMPLE_W_u8(_name) \ |
154 | static ssize_t gadget_dev_desc_##_name##_store(struct config_item *item, \ |
155 | const char *page, size_t len) \ |
156 | { \ |
157 | u8 val; \ |
158 | int ret; \ |
159 | ret = kstrtou8(page, 0, &val); \ |
160 | if (ret) \ |
161 | return ret; \ |
162 | to_gadget_info(item)->cdev.desc._name = val; \ |
163 | return len; \ |
164 | } |
165 | |
166 | #define GI_DEVICE_DESC_SIMPLE_W_u16(_name) \ |
167 | static ssize_t gadget_dev_desc_##_name##_store(struct config_item *item, \ |
168 | const char *page, size_t len) \ |
169 | { \ |
170 | u16 val; \ |
171 | int ret; \ |
172 | ret = kstrtou16(page, 0, &val); \ |
173 | if (ret) \ |
174 | return ret; \ |
175 | to_gadget_info(item)->cdev.desc._name = cpu_to_le16p(&val); \ |
176 | return len; \ |
177 | } |
178 | |
179 | #define GI_DEVICE_DESC_SIMPLE_RW(_name, _type) \ |
180 | GI_DEVICE_DESC_SIMPLE_R_##_type(_name) \ |
181 | GI_DEVICE_DESC_SIMPLE_W_##_type(_name) |
182 | |
183 | GI_DEVICE_DESC_SIMPLE_R_u16(bcdUSB); |
184 | GI_DEVICE_DESC_SIMPLE_RW(bDeviceClass, u8); |
185 | GI_DEVICE_DESC_SIMPLE_RW(bDeviceSubClass, u8); |
186 | GI_DEVICE_DESC_SIMPLE_RW(bDeviceProtocol, u8); |
187 | GI_DEVICE_DESC_SIMPLE_RW(bMaxPacketSize0, u8); |
188 | GI_DEVICE_DESC_SIMPLE_RW(idVendor, u16); |
189 | GI_DEVICE_DESC_SIMPLE_RW(idProduct, u16); |
190 | GI_DEVICE_DESC_SIMPLE_R_u16(bcdDevice); |
191 | |
192 | static ssize_t is_valid_bcd(u16 bcd_val) |
193 | { |
194 | if ((bcd_val & 0xf) > 9) |
195 | return -EINVAL; |
196 | if (((bcd_val >> 4) & 0xf) > 9) |
197 | return -EINVAL; |
198 | if (((bcd_val >> 8) & 0xf) > 9) |
199 | return -EINVAL; |
200 | if (((bcd_val >> 12) & 0xf) > 9) |
201 | return -EINVAL; |
202 | return 0; |
203 | } |
204 | |
205 | static ssize_t gadget_dev_desc_bcdDevice_store(struct config_item *item, |
206 | const char *page, size_t len) |
207 | { |
208 | u16 bcdDevice; |
209 | int ret; |
210 | |
211 | ret = kstrtou16(s: page, base: 0, res: &bcdDevice); |
212 | if (ret) |
213 | return ret; |
214 | ret = is_valid_bcd(bcd_val: bcdDevice); |
215 | if (ret) |
216 | return ret; |
217 | |
218 | to_gadget_info(item)->cdev.desc.bcdDevice = cpu_to_le16(bcdDevice); |
219 | return len; |
220 | } |
221 | |
222 | static ssize_t gadget_dev_desc_bcdUSB_store(struct config_item *item, |
223 | const char *page, size_t len) |
224 | { |
225 | u16 bcdUSB; |
226 | int ret; |
227 | |
228 | ret = kstrtou16(s: page, base: 0, res: &bcdUSB); |
229 | if (ret) |
230 | return ret; |
231 | ret = is_valid_bcd(bcd_val: bcdUSB); |
232 | if (ret) |
233 | return ret; |
234 | |
235 | to_gadget_info(item)->cdev.desc.bcdUSB = cpu_to_le16(bcdUSB); |
236 | return len; |
237 | } |
238 | |
239 | static ssize_t gadget_dev_desc_UDC_show(struct config_item *item, char *page) |
240 | { |
241 | struct gadget_info *gi = to_gadget_info(item); |
242 | char *udc_name; |
243 | int ret; |
244 | |
245 | mutex_lock(&gi->lock); |
246 | udc_name = gi->composite.gadget_driver.udc_name; |
247 | ret = sprintf(buf: page, fmt: "%s\n" , udc_name ?: "" ); |
248 | mutex_unlock(lock: &gi->lock); |
249 | |
250 | return ret; |
251 | } |
252 | |
253 | static int unregister_gadget(struct gadget_info *gi) |
254 | { |
255 | int ret; |
256 | |
257 | if (!gi->composite.gadget_driver.udc_name) |
258 | return -ENODEV; |
259 | |
260 | ret = usb_gadget_unregister_driver(driver: &gi->composite.gadget_driver); |
261 | if (ret) |
262 | return ret; |
263 | kfree(objp: gi->composite.gadget_driver.udc_name); |
264 | gi->composite.gadget_driver.udc_name = NULL; |
265 | return 0; |
266 | } |
267 | |
268 | static ssize_t gadget_dev_desc_UDC_store(struct config_item *item, |
269 | const char *page, size_t len) |
270 | { |
271 | struct gadget_info *gi = to_gadget_info(item); |
272 | char *name; |
273 | int ret; |
274 | |
275 | if (strlen(page) < len) |
276 | return -EOVERFLOW; |
277 | |
278 | name = kstrdup(s: page, GFP_KERNEL); |
279 | if (!name) |
280 | return -ENOMEM; |
281 | if (name[len - 1] == '\n') |
282 | name[len - 1] = '\0'; |
283 | |
284 | mutex_lock(&gi->lock); |
285 | |
286 | if (!strlen(name)) { |
287 | ret = unregister_gadget(gi); |
288 | if (ret) |
289 | goto err; |
290 | kfree(objp: name); |
291 | } else { |
292 | if (gi->composite.gadget_driver.udc_name) { |
293 | ret = -EBUSY; |
294 | goto err; |
295 | } |
296 | gi->composite.gadget_driver.udc_name = name; |
297 | ret = usb_gadget_register_driver(&gi->composite.gadget_driver); |
298 | if (ret) { |
299 | gi->composite.gadget_driver.udc_name = NULL; |
300 | goto err; |
301 | } |
302 | } |
303 | mutex_unlock(lock: &gi->lock); |
304 | return len; |
305 | err: |
306 | kfree(objp: name); |
307 | mutex_unlock(lock: &gi->lock); |
308 | return ret; |
309 | } |
310 | |
311 | static ssize_t gadget_dev_desc_max_speed_show(struct config_item *item, |
312 | char *page) |
313 | { |
314 | enum usb_device_speed speed = to_gadget_info(item)->composite.max_speed; |
315 | |
316 | return sprintf(buf: page, fmt: "%s\n" , usb_speed_string(speed)); |
317 | } |
318 | |
319 | static ssize_t gadget_dev_desc_max_speed_store(struct config_item *item, |
320 | const char *page, size_t len) |
321 | { |
322 | struct gadget_info *gi = to_gadget_info(item); |
323 | |
324 | mutex_lock(&gi->lock); |
325 | |
326 | /* Prevent changing of max_speed after the driver is binded */ |
327 | if (gi->composite.gadget_driver.udc_name) |
328 | goto err; |
329 | |
330 | if (strncmp(page, "super-speed-plus" , 16) == 0) |
331 | gi->composite.max_speed = USB_SPEED_SUPER_PLUS; |
332 | else if (strncmp(page, "super-speed" , 11) == 0) |
333 | gi->composite.max_speed = USB_SPEED_SUPER; |
334 | else if (strncmp(page, "high-speed" , 10) == 0) |
335 | gi->composite.max_speed = USB_SPEED_HIGH; |
336 | else if (strncmp(page, "full-speed" , 10) == 0) |
337 | gi->composite.max_speed = USB_SPEED_FULL; |
338 | else if (strncmp(page, "low-speed" , 9) == 0) |
339 | gi->composite.max_speed = USB_SPEED_LOW; |
340 | else |
341 | goto err; |
342 | |
343 | gi->composite.gadget_driver.max_speed = gi->composite.max_speed; |
344 | |
345 | mutex_unlock(lock: &gi->lock); |
346 | return len; |
347 | err: |
348 | mutex_unlock(lock: &gi->lock); |
349 | return -EINVAL; |
350 | } |
351 | |
352 | CONFIGFS_ATTR(gadget_dev_desc_, bDeviceClass); |
353 | CONFIGFS_ATTR(gadget_dev_desc_, bDeviceSubClass); |
354 | CONFIGFS_ATTR(gadget_dev_desc_, bDeviceProtocol); |
355 | CONFIGFS_ATTR(gadget_dev_desc_, bMaxPacketSize0); |
356 | CONFIGFS_ATTR(gadget_dev_desc_, idVendor); |
357 | CONFIGFS_ATTR(gadget_dev_desc_, idProduct); |
358 | CONFIGFS_ATTR(gadget_dev_desc_, bcdDevice); |
359 | CONFIGFS_ATTR(gadget_dev_desc_, bcdUSB); |
360 | CONFIGFS_ATTR(gadget_dev_desc_, UDC); |
361 | CONFIGFS_ATTR(gadget_dev_desc_, max_speed); |
362 | |
363 | static struct configfs_attribute *gadget_root_attrs[] = { |
364 | &gadget_dev_desc_attr_bDeviceClass, |
365 | &gadget_dev_desc_attr_bDeviceSubClass, |
366 | &gadget_dev_desc_attr_bDeviceProtocol, |
367 | &gadget_dev_desc_attr_bMaxPacketSize0, |
368 | &gadget_dev_desc_attr_idVendor, |
369 | &gadget_dev_desc_attr_idProduct, |
370 | &gadget_dev_desc_attr_bcdDevice, |
371 | &gadget_dev_desc_attr_bcdUSB, |
372 | &gadget_dev_desc_attr_UDC, |
373 | &gadget_dev_desc_attr_max_speed, |
374 | NULL, |
375 | }; |
376 | |
377 | static inline struct gadget_language *to_gadget_language(struct config_item *item) |
378 | { |
379 | return container_of(to_config_group(item), struct gadget_language, |
380 | group); |
381 | } |
382 | |
383 | static inline struct gadget_config_name *to_gadget_config_name( |
384 | struct config_item *item) |
385 | { |
386 | return container_of(to_config_group(item), struct gadget_config_name, |
387 | group); |
388 | } |
389 | |
390 | static inline struct usb_function_instance *to_usb_function_instance( |
391 | struct config_item *item) |
392 | { |
393 | return container_of(to_config_group(item), |
394 | struct usb_function_instance, group); |
395 | } |
396 | |
397 | static void gadget_info_attr_release(struct config_item *item) |
398 | { |
399 | struct gadget_info *gi = to_gadget_info(item); |
400 | |
401 | WARN_ON(!list_empty(&gi->cdev.configs)); |
402 | WARN_ON(!list_empty(&gi->string_list)); |
403 | WARN_ON(!list_empty(&gi->available_func)); |
404 | kfree(objp: gi->composite.gadget_driver.function); |
405 | kfree(objp: gi->composite.gadget_driver.driver.name); |
406 | kfree(objp: gi); |
407 | } |
408 | |
409 | static struct configfs_item_operations gadget_root_item_ops = { |
410 | .release = gadget_info_attr_release, |
411 | }; |
412 | |
413 | static void gadget_config_attr_release(struct config_item *item) |
414 | { |
415 | struct config_usb_cfg *cfg = to_config_usb_cfg(item); |
416 | |
417 | WARN_ON(!list_empty(&cfg->c.functions)); |
418 | list_del(entry: &cfg->c.list); |
419 | kfree(objp: cfg->c.label); |
420 | kfree(objp: cfg); |
421 | } |
422 | |
423 | static int config_usb_cfg_link( |
424 | struct config_item *usb_cfg_ci, |
425 | struct config_item *usb_func_ci) |
426 | { |
427 | struct config_usb_cfg *cfg = to_config_usb_cfg(item: usb_cfg_ci); |
428 | struct gadget_info *gi = cfg_to_gadget_info(cfg); |
429 | |
430 | struct usb_function_instance *fi = |
431 | to_usb_function_instance(item: usb_func_ci); |
432 | struct usb_function_instance *a_fi = NULL, *iter; |
433 | struct usb_function *f; |
434 | int ret; |
435 | |
436 | mutex_lock(&gi->lock); |
437 | /* |
438 | * Make sure this function is from within our _this_ gadget and not |
439 | * from another gadget or a random directory. |
440 | * Also a function instance can only be linked once. |
441 | */ |
442 | |
443 | if (gi->composite.gadget_driver.udc_name) { |
444 | ret = -EINVAL; |
445 | goto out; |
446 | } |
447 | |
448 | list_for_each_entry(iter, &gi->available_func, cfs_list) { |
449 | if (iter != fi) |
450 | continue; |
451 | a_fi = iter; |
452 | break; |
453 | } |
454 | if (!a_fi) { |
455 | ret = -EINVAL; |
456 | goto out; |
457 | } |
458 | |
459 | list_for_each_entry(f, &cfg->func_list, list) { |
460 | if (f->fi == fi) { |
461 | ret = -EEXIST; |
462 | goto out; |
463 | } |
464 | } |
465 | |
466 | f = usb_get_function(fi); |
467 | if (IS_ERR(ptr: f)) { |
468 | ret = PTR_ERR(ptr: f); |
469 | goto out; |
470 | } |
471 | |
472 | /* stash the function until we bind it to the gadget */ |
473 | list_add_tail(new: &f->list, head: &cfg->func_list); |
474 | ret = 0; |
475 | out: |
476 | mutex_unlock(lock: &gi->lock); |
477 | return ret; |
478 | } |
479 | |
480 | static void config_usb_cfg_unlink( |
481 | struct config_item *usb_cfg_ci, |
482 | struct config_item *usb_func_ci) |
483 | { |
484 | struct config_usb_cfg *cfg = to_config_usb_cfg(item: usb_cfg_ci); |
485 | struct gadget_info *gi = cfg_to_gadget_info(cfg); |
486 | |
487 | struct usb_function_instance *fi = |
488 | to_usb_function_instance(item: usb_func_ci); |
489 | struct usb_function *f; |
490 | |
491 | /* |
492 | * ideally I would like to forbid to unlink functions while a gadget is |
493 | * bound to an UDC. Since this isn't possible at the moment, we simply |
494 | * force an unbind, the function is available here and then we can |
495 | * remove the function. |
496 | */ |
497 | mutex_lock(&gi->lock); |
498 | if (gi->composite.gadget_driver.udc_name) |
499 | unregister_gadget(gi); |
500 | WARN_ON(gi->composite.gadget_driver.udc_name); |
501 | |
502 | list_for_each_entry(f, &cfg->func_list, list) { |
503 | if (f->fi == fi) { |
504 | list_del(entry: &f->list); |
505 | usb_put_function(f); |
506 | mutex_unlock(lock: &gi->lock); |
507 | return; |
508 | } |
509 | } |
510 | mutex_unlock(lock: &gi->lock); |
511 | WARN(1, "Unable to locate function to unbind\n" ); |
512 | } |
513 | |
514 | static struct configfs_item_operations gadget_config_item_ops = { |
515 | .release = gadget_config_attr_release, |
516 | .allow_link = config_usb_cfg_link, |
517 | .drop_link = config_usb_cfg_unlink, |
518 | }; |
519 | |
520 | |
521 | static ssize_t gadget_config_desc_MaxPower_show(struct config_item *item, |
522 | char *page) |
523 | { |
524 | struct config_usb_cfg *cfg = to_config_usb_cfg(item); |
525 | |
526 | return sprintf(buf: page, fmt: "%u\n" , cfg->c.MaxPower); |
527 | } |
528 | |
529 | static ssize_t gadget_config_desc_MaxPower_store(struct config_item *item, |
530 | const char *page, size_t len) |
531 | { |
532 | struct config_usb_cfg *cfg = to_config_usb_cfg(item); |
533 | u16 val; |
534 | int ret; |
535 | ret = kstrtou16(s: page, base: 0, res: &val); |
536 | if (ret) |
537 | return ret; |
538 | if (DIV_ROUND_UP(val, 8) > 0xff) |
539 | return -ERANGE; |
540 | cfg->c.MaxPower = val; |
541 | return len; |
542 | } |
543 | |
544 | static ssize_t gadget_config_desc_bmAttributes_show(struct config_item *item, |
545 | char *page) |
546 | { |
547 | struct config_usb_cfg *cfg = to_config_usb_cfg(item); |
548 | |
549 | return sprintf(buf: page, fmt: "0x%02x\n" , cfg->c.bmAttributes); |
550 | } |
551 | |
552 | static ssize_t gadget_config_desc_bmAttributes_store(struct config_item *item, |
553 | const char *page, size_t len) |
554 | { |
555 | struct config_usb_cfg *cfg = to_config_usb_cfg(item); |
556 | u8 val; |
557 | int ret; |
558 | ret = kstrtou8(s: page, base: 0, res: &val); |
559 | if (ret) |
560 | return ret; |
561 | if (!(val & USB_CONFIG_ATT_ONE)) |
562 | return -EINVAL; |
563 | if (val & ~(USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER | |
564 | USB_CONFIG_ATT_WAKEUP)) |
565 | return -EINVAL; |
566 | cfg->c.bmAttributes = val; |
567 | return len; |
568 | } |
569 | |
570 | CONFIGFS_ATTR(gadget_config_desc_, MaxPower); |
571 | CONFIGFS_ATTR(gadget_config_desc_, bmAttributes); |
572 | |
573 | static struct configfs_attribute *gadget_config_attrs[] = { |
574 | &gadget_config_desc_attr_MaxPower, |
575 | &gadget_config_desc_attr_bmAttributes, |
576 | NULL, |
577 | }; |
578 | |
579 | static const struct config_item_type gadget_config_type = { |
580 | .ct_item_ops = &gadget_config_item_ops, |
581 | .ct_attrs = gadget_config_attrs, |
582 | .ct_owner = THIS_MODULE, |
583 | }; |
584 | |
585 | static const struct config_item_type gadget_root_type = { |
586 | .ct_item_ops = &gadget_root_item_ops, |
587 | .ct_attrs = gadget_root_attrs, |
588 | .ct_owner = THIS_MODULE, |
589 | }; |
590 | |
591 | static void composite_init_dev(struct usb_composite_dev *cdev) |
592 | { |
593 | spin_lock_init(&cdev->lock); |
594 | INIT_LIST_HEAD(list: &cdev->configs); |
595 | INIT_LIST_HEAD(list: &cdev->gstrings); |
596 | } |
597 | |
598 | static struct config_group *function_make( |
599 | struct config_group *group, |
600 | const char *name) |
601 | { |
602 | struct gadget_info *gi; |
603 | struct usb_function_instance *fi; |
604 | char buf[MAX_NAME_LEN]; |
605 | char *func_name; |
606 | char *instance_name; |
607 | int ret; |
608 | |
609 | ret = snprintf(buf, MAX_NAME_LEN, fmt: "%s" , name); |
610 | if (ret >= MAX_NAME_LEN) |
611 | return ERR_PTR(error: -ENAMETOOLONG); |
612 | |
613 | func_name = buf; |
614 | instance_name = strchr(func_name, '.'); |
615 | if (!instance_name) { |
616 | pr_err("Unable to locate . in FUNC.INSTANCE\n" ); |
617 | return ERR_PTR(error: -EINVAL); |
618 | } |
619 | *instance_name = '\0'; |
620 | instance_name++; |
621 | |
622 | fi = usb_get_function_instance(name: func_name); |
623 | if (IS_ERR(ptr: fi)) |
624 | return ERR_CAST(ptr: fi); |
625 | |
626 | ret = config_item_set_name(&fi->group.cg_item, "%s" , name); |
627 | if (ret) { |
628 | usb_put_function_instance(fi); |
629 | return ERR_PTR(error: ret); |
630 | } |
631 | if (fi->set_inst_name) { |
632 | ret = fi->set_inst_name(fi, instance_name); |
633 | if (ret) { |
634 | usb_put_function_instance(fi); |
635 | return ERR_PTR(error: ret); |
636 | } |
637 | } |
638 | |
639 | gi = container_of(group, struct gadget_info, functions_group); |
640 | |
641 | mutex_lock(&gi->lock); |
642 | list_add_tail(new: &fi->cfs_list, head: &gi->available_func); |
643 | mutex_unlock(lock: &gi->lock); |
644 | return &fi->group; |
645 | } |
646 | |
647 | static void function_drop( |
648 | struct config_group *group, |
649 | struct config_item *item) |
650 | { |
651 | struct usb_function_instance *fi = to_usb_function_instance(item); |
652 | struct gadget_info *gi; |
653 | |
654 | gi = container_of(group, struct gadget_info, functions_group); |
655 | |
656 | mutex_lock(&gi->lock); |
657 | list_del(entry: &fi->cfs_list); |
658 | mutex_unlock(lock: &gi->lock); |
659 | config_item_put(item); |
660 | } |
661 | |
662 | static struct configfs_group_operations functions_ops = { |
663 | .make_group = &function_make, |
664 | .drop_item = &function_drop, |
665 | }; |
666 | |
667 | static const struct config_item_type functions_type = { |
668 | .ct_group_ops = &functions_ops, |
669 | .ct_owner = THIS_MODULE, |
670 | }; |
671 | |
672 | GS_STRINGS_RW(gadget_config_name, configuration); |
673 | |
674 | static struct configfs_attribute *gadget_config_name_langid_attrs[] = { |
675 | &gadget_config_name_attr_configuration, |
676 | NULL, |
677 | }; |
678 | |
679 | static void gadget_config_name_attr_release(struct config_item *item) |
680 | { |
681 | struct gadget_config_name *cn = to_gadget_config_name(item); |
682 | |
683 | kfree(objp: cn->configuration); |
684 | |
685 | list_del(entry: &cn->list); |
686 | kfree(objp: cn); |
687 | } |
688 | |
689 | USB_CONFIG_STRING_RW_OPS(gadget_config_name); |
690 | USB_CONFIG_STRINGS_LANG(gadget_config_name, config_usb_cfg); |
691 | |
692 | static struct config_group *config_desc_make( |
693 | struct config_group *group, |
694 | const char *name) |
695 | { |
696 | struct gadget_info *gi; |
697 | struct config_usb_cfg *cfg; |
698 | char buf[MAX_NAME_LEN]; |
699 | char *num_str; |
700 | u8 num; |
701 | int ret; |
702 | |
703 | gi = container_of(group, struct gadget_info, configs_group); |
704 | ret = snprintf(buf, MAX_NAME_LEN, fmt: "%s" , name); |
705 | if (ret >= MAX_NAME_LEN) |
706 | return ERR_PTR(error: -ENAMETOOLONG); |
707 | |
708 | num_str = strchr(buf, '.'); |
709 | if (!num_str) { |
710 | pr_err("Unable to locate . in name.bConfigurationValue\n" ); |
711 | return ERR_PTR(error: -EINVAL); |
712 | } |
713 | |
714 | *num_str = '\0'; |
715 | num_str++; |
716 | |
717 | if (!strlen(buf)) |
718 | return ERR_PTR(error: -EINVAL); |
719 | |
720 | ret = kstrtou8(s: num_str, base: 0, res: &num); |
721 | if (ret) |
722 | return ERR_PTR(error: ret); |
723 | |
724 | cfg = kzalloc(size: sizeof(*cfg), GFP_KERNEL); |
725 | if (!cfg) |
726 | return ERR_PTR(error: -ENOMEM); |
727 | cfg->c.label = kstrdup(s: buf, GFP_KERNEL); |
728 | if (!cfg->c.label) { |
729 | ret = -ENOMEM; |
730 | goto err; |
731 | } |
732 | cfg->c.bConfigurationValue = num; |
733 | cfg->c.MaxPower = CONFIG_USB_GADGET_VBUS_DRAW; |
734 | cfg->c.bmAttributes = USB_CONFIG_ATT_ONE; |
735 | INIT_LIST_HEAD(list: &cfg->string_list); |
736 | INIT_LIST_HEAD(list: &cfg->func_list); |
737 | |
738 | config_group_init_type_name(group: &cfg->group, name, |
739 | type: &gadget_config_type); |
740 | |
741 | config_group_init_type_name(group: &cfg->strings_group, name: "strings" , |
742 | type: &gadget_config_name_strings_type); |
743 | configfs_add_default_group(new_group: &cfg->strings_group, group: &cfg->group); |
744 | |
745 | ret = usb_add_config_only(cdev: &gi->cdev, config: &cfg->c); |
746 | if (ret) |
747 | goto err; |
748 | |
749 | return &cfg->group; |
750 | err: |
751 | kfree(objp: cfg->c.label); |
752 | kfree(objp: cfg); |
753 | return ERR_PTR(error: ret); |
754 | } |
755 | |
756 | static void config_desc_drop( |
757 | struct config_group *group, |
758 | struct config_item *item) |
759 | { |
760 | config_item_put(item); |
761 | } |
762 | |
763 | static struct configfs_group_operations config_desc_ops = { |
764 | .make_group = &config_desc_make, |
765 | .drop_item = &config_desc_drop, |
766 | }; |
767 | |
768 | static const struct config_item_type config_desc_type = { |
769 | .ct_group_ops = &config_desc_ops, |
770 | .ct_owner = THIS_MODULE, |
771 | }; |
772 | |
773 | GS_STRINGS_RW(gadget_language, manufacturer); |
774 | GS_STRINGS_RW(gadget_language, product); |
775 | GS_STRINGS_RW(gadget_language, serialnumber); |
776 | |
777 | static struct configfs_attribute *gadget_language_langid_attrs[] = { |
778 | &gadget_language_attr_manufacturer, |
779 | &gadget_language_attr_product, |
780 | &gadget_language_attr_serialnumber, |
781 | NULL, |
782 | }; |
783 | |
784 | static void gadget_language_attr_release(struct config_item *item) |
785 | { |
786 | struct gadget_language *gs = to_gadget_language(item); |
787 | |
788 | kfree(objp: gs->manufacturer); |
789 | kfree(objp: gs->product); |
790 | kfree(objp: gs->serialnumber); |
791 | |
792 | list_del(entry: &gs->list); |
793 | kfree(objp: gs); |
794 | } |
795 | |
796 | static struct configfs_item_operations gadget_language_langid_item_ops = { |
797 | .release = gadget_language_attr_release, |
798 | }; |
799 | |
800 | static ssize_t gadget_string_id_show(struct config_item *item, char *page) |
801 | { |
802 | struct gadget_string *string = to_gadget_string(item); |
803 | int ret; |
804 | |
805 | ret = sprintf(buf: page, fmt: "%u\n" , string->usb_string.id); |
806 | return ret; |
807 | } |
808 | CONFIGFS_ATTR_RO(gadget_string_, id); |
809 | |
810 | static ssize_t gadget_string_s_show(struct config_item *item, char *page) |
811 | { |
812 | struct gadget_string *string = to_gadget_string(item); |
813 | int ret; |
814 | |
815 | ret = snprintf(buf: page, size: sizeof(string->string), fmt: "%s\n" , string->string); |
816 | return ret; |
817 | } |
818 | |
819 | static ssize_t gadget_string_s_store(struct config_item *item, const char *page, |
820 | size_t len) |
821 | { |
822 | struct gadget_string *string = to_gadget_string(item); |
823 | int size = min(sizeof(string->string), len + 1); |
824 | |
825 | if (len > USB_MAX_STRING_LEN) |
826 | return -EINVAL; |
827 | |
828 | return strscpy(p: string->string, q: page, size); |
829 | } |
830 | CONFIGFS_ATTR(gadget_string_, s); |
831 | |
832 | static struct configfs_attribute *gadget_string_attrs[] = { |
833 | &gadget_string_attr_id, |
834 | &gadget_string_attr_s, |
835 | NULL, |
836 | }; |
837 | |
838 | static void gadget_string_release(struct config_item *item) |
839 | { |
840 | struct gadget_string *string = to_gadget_string(item); |
841 | |
842 | kfree(objp: string); |
843 | } |
844 | |
845 | static struct configfs_item_operations gadget_string_item_ops = { |
846 | .release = gadget_string_release, |
847 | }; |
848 | |
849 | static const struct config_item_type gadget_string_type = { |
850 | .ct_item_ops = &gadget_string_item_ops, |
851 | .ct_attrs = gadget_string_attrs, |
852 | .ct_owner = THIS_MODULE, |
853 | }; |
854 | |
855 | static struct config_item *gadget_language_string_make(struct config_group *group, |
856 | const char *name) |
857 | { |
858 | struct gadget_language *language; |
859 | struct gadget_string *string; |
860 | |
861 | language = to_gadget_language(item: &group->cg_item); |
862 | |
863 | string = kzalloc(size: sizeof(*string), GFP_KERNEL); |
864 | if (!string) |
865 | return ERR_PTR(error: -ENOMEM); |
866 | |
867 | string->usb_string.id = language->nstrings++; |
868 | string->usb_string.s = string->string; |
869 | list_add_tail(new: &string->list, head: &language->gadget_strings); |
870 | |
871 | config_item_init_type_name(item: &string->item, name, type: &gadget_string_type); |
872 | |
873 | return &string->item; |
874 | } |
875 | |
876 | static void gadget_language_string_drop(struct config_group *group, |
877 | struct config_item *item) |
878 | { |
879 | struct gadget_language *language; |
880 | struct gadget_string *string; |
881 | unsigned int i = USB_GADGET_FIRST_AVAIL_IDX; |
882 | |
883 | language = to_gadget_language(item: &group->cg_item); |
884 | string = to_gadget_string(item); |
885 | |
886 | list_del(entry: &string->list); |
887 | language->nstrings--; |
888 | |
889 | /* Reset the ids for the language's strings to guarantee a continuous set */ |
890 | list_for_each_entry(string, &language->gadget_strings, list) |
891 | string->usb_string.id = i++; |
892 | } |
893 | |
894 | static struct configfs_group_operations gadget_language_langid_group_ops = { |
895 | .make_item = gadget_language_string_make, |
896 | .drop_item = gadget_language_string_drop, |
897 | }; |
898 | |
899 | static struct config_item_type gadget_language_type = { |
900 | .ct_item_ops = &gadget_language_langid_item_ops, |
901 | .ct_group_ops = &gadget_language_langid_group_ops, |
902 | .ct_attrs = gadget_language_langid_attrs, |
903 | .ct_owner = THIS_MODULE, |
904 | }; |
905 | |
906 | static struct config_group *gadget_language_make(struct config_group *group, |
907 | const char *name) |
908 | { |
909 | struct gadget_info *gi; |
910 | struct gadget_language *gs; |
911 | struct gadget_language *new; |
912 | int langs = 0; |
913 | int ret; |
914 | |
915 | new = kzalloc(size: sizeof(*new), GFP_KERNEL); |
916 | if (!new) |
917 | return ERR_PTR(error: -ENOMEM); |
918 | |
919 | ret = check_user_usb_string(name, stringtab_dev: &new->stringtab_dev); |
920 | if (ret) |
921 | goto err; |
922 | config_group_init_type_name(group: &new->group, name, |
923 | type: &gadget_language_type); |
924 | |
925 | gi = container_of(group, struct gadget_info, strings_group); |
926 | ret = -EEXIST; |
927 | list_for_each_entry(gs, &gi->string_list, list) { |
928 | if (gs->stringtab_dev.language == new->stringtab_dev.language) |
929 | goto err; |
930 | langs++; |
931 | } |
932 | ret = -EOVERFLOW; |
933 | if (langs >= MAX_USB_STRING_LANGS) |
934 | goto err; |
935 | |
936 | list_add_tail(new: &new->list, head: &gi->string_list); |
937 | INIT_LIST_HEAD(list: &new->gadget_strings); |
938 | |
939 | /* We have the default manufacturer, product and serialnumber strings */ |
940 | new->nstrings = 3; |
941 | return &new->group; |
942 | err: |
943 | kfree(objp: new); |
944 | return ERR_PTR(error: ret); |
945 | } |
946 | |
947 | static void gadget_language_drop(struct config_group *group, |
948 | struct config_item *item) |
949 | { |
950 | config_item_put(item); |
951 | } |
952 | |
953 | static struct configfs_group_operations gadget_language_group_ops = { |
954 | .make_group = &gadget_language_make, |
955 | .drop_item = &gadget_language_drop, |
956 | }; |
957 | |
958 | static struct config_item_type gadget_language_strings_type = { |
959 | .ct_group_ops = &gadget_language_group_ops, |
960 | .ct_owner = THIS_MODULE, |
961 | }; |
962 | |
963 | static inline struct gadget_info *webusb_item_to_gadget_info( |
964 | struct config_item *item) |
965 | { |
966 | return container_of(to_config_group(item), |
967 | struct gadget_info, webusb_group); |
968 | } |
969 | |
970 | static ssize_t webusb_use_show(struct config_item *item, char *page) |
971 | { |
972 | return sysfs_emit(buf: page, fmt: "%d\n" , |
973 | webusb_item_to_gadget_info(item)->use_webusb); |
974 | } |
975 | |
976 | static ssize_t webusb_use_store(struct config_item *item, const char *page, |
977 | size_t len) |
978 | { |
979 | struct gadget_info *gi = webusb_item_to_gadget_info(item); |
980 | int ret; |
981 | bool use; |
982 | |
983 | ret = kstrtobool(s: page, res: &use); |
984 | if (ret) |
985 | return ret; |
986 | |
987 | mutex_lock(&gi->lock); |
988 | gi->use_webusb = use; |
989 | mutex_unlock(lock: &gi->lock); |
990 | |
991 | return len; |
992 | } |
993 | |
994 | static ssize_t webusb_bcdVersion_show(struct config_item *item, char *page) |
995 | { |
996 | return sysfs_emit(buf: page, fmt: "0x%04x\n" , |
997 | webusb_item_to_gadget_info(item)->bcd_webusb_version); |
998 | } |
999 | |
1000 | static ssize_t webusb_bcdVersion_store(struct config_item *item, |
1001 | const char *page, size_t len) |
1002 | { |
1003 | struct gadget_info *gi = webusb_item_to_gadget_info(item); |
1004 | u16 bcdVersion; |
1005 | int ret; |
1006 | |
1007 | ret = kstrtou16(s: page, base: 0, res: &bcdVersion); |
1008 | if (ret) |
1009 | return ret; |
1010 | |
1011 | ret = is_valid_bcd(bcd_val: bcdVersion); |
1012 | if (ret) |
1013 | return ret; |
1014 | |
1015 | mutex_lock(&gi->lock); |
1016 | gi->bcd_webusb_version = bcdVersion; |
1017 | mutex_unlock(lock: &gi->lock); |
1018 | |
1019 | return len; |
1020 | } |
1021 | |
1022 | static ssize_t webusb_bVendorCode_show(struct config_item *item, char *page) |
1023 | { |
1024 | return sysfs_emit(buf: page, fmt: "0x%02x\n" , |
1025 | webusb_item_to_gadget_info(item)->b_webusb_vendor_code); |
1026 | } |
1027 | |
1028 | static ssize_t webusb_bVendorCode_store(struct config_item *item, |
1029 | const char *page, size_t len) |
1030 | { |
1031 | struct gadget_info *gi = webusb_item_to_gadget_info(item); |
1032 | int ret; |
1033 | u8 b_vendor_code; |
1034 | |
1035 | ret = kstrtou8(s: page, base: 0, res: &b_vendor_code); |
1036 | if (ret) |
1037 | return ret; |
1038 | |
1039 | mutex_lock(&gi->lock); |
1040 | gi->b_webusb_vendor_code = b_vendor_code; |
1041 | mutex_unlock(lock: &gi->lock); |
1042 | |
1043 | return len; |
1044 | } |
1045 | |
1046 | static ssize_t webusb_landingPage_show(struct config_item *item, char *page) |
1047 | { |
1048 | return sysfs_emit(buf: page, fmt: "%s\n" , webusb_item_to_gadget_info(item)->landing_page); |
1049 | } |
1050 | |
1051 | static ssize_t webusb_landingPage_store(struct config_item *item, const char *page, |
1052 | size_t len) |
1053 | { |
1054 | struct gadget_info *gi = webusb_item_to_gadget_info(item); |
1055 | unsigned int bytes_to_strip = 0; |
1056 | int l = len; |
1057 | |
1058 | if (page[l - 1] == '\n') { |
1059 | --l; |
1060 | ++bytes_to_strip; |
1061 | } |
1062 | |
1063 | if (l > sizeof(gi->landing_page)) { |
1064 | pr_err("webusb: landingPage URL too long\n" ); |
1065 | return -EINVAL; |
1066 | } |
1067 | |
1068 | // validation |
1069 | if (strncasecmp(s1: page, s2: "https://" , n: 8) == 0) |
1070 | bytes_to_strip = 8; |
1071 | else if (strncasecmp(s1: page, s2: "http://" , n: 7) == 0) |
1072 | bytes_to_strip = 7; |
1073 | else |
1074 | bytes_to_strip = 0; |
1075 | |
1076 | if (l > U8_MAX - WEBUSB_URL_DESCRIPTOR_HEADER_LENGTH + bytes_to_strip) { |
1077 | pr_err("webusb: landingPage URL %d bytes too long for given URL scheme\n" , |
1078 | l - U8_MAX + WEBUSB_URL_DESCRIPTOR_HEADER_LENGTH - bytes_to_strip); |
1079 | return -EINVAL; |
1080 | } |
1081 | |
1082 | mutex_lock(&gi->lock); |
1083 | // ensure 0 bytes are set, in case the new landing page is shorter then the old one. |
1084 | memcpy_and_pad(dest: gi->landing_page, dest_len: sizeof(gi->landing_page), src: page, count: l, pad: 0); |
1085 | mutex_unlock(lock: &gi->lock); |
1086 | |
1087 | return len; |
1088 | } |
1089 | |
1090 | CONFIGFS_ATTR(webusb_, use); |
1091 | CONFIGFS_ATTR(webusb_, bVendorCode); |
1092 | CONFIGFS_ATTR(webusb_, bcdVersion); |
1093 | CONFIGFS_ATTR(webusb_, landingPage); |
1094 | |
1095 | static struct configfs_attribute *webusb_attrs[] = { |
1096 | &webusb_attr_use, |
1097 | &webusb_attr_bcdVersion, |
1098 | &webusb_attr_bVendorCode, |
1099 | &webusb_attr_landingPage, |
1100 | NULL, |
1101 | }; |
1102 | |
1103 | static struct config_item_type webusb_type = { |
1104 | .ct_attrs = webusb_attrs, |
1105 | .ct_owner = THIS_MODULE, |
1106 | }; |
1107 | |
1108 | static inline struct gadget_info *os_desc_item_to_gadget_info( |
1109 | struct config_item *item) |
1110 | { |
1111 | return container_of(to_config_group(item), |
1112 | struct gadget_info, os_desc_group); |
1113 | } |
1114 | |
1115 | static ssize_t os_desc_use_show(struct config_item *item, char *page) |
1116 | { |
1117 | return sprintf(buf: page, fmt: "%d\n" , |
1118 | os_desc_item_to_gadget_info(item)->use_os_desc); |
1119 | } |
1120 | |
1121 | static ssize_t os_desc_use_store(struct config_item *item, const char *page, |
1122 | size_t len) |
1123 | { |
1124 | struct gadget_info *gi = os_desc_item_to_gadget_info(item); |
1125 | int ret; |
1126 | bool use; |
1127 | |
1128 | ret = kstrtobool(s: page, res: &use); |
1129 | if (ret) |
1130 | return ret; |
1131 | |
1132 | mutex_lock(&gi->lock); |
1133 | gi->use_os_desc = use; |
1134 | mutex_unlock(lock: &gi->lock); |
1135 | |
1136 | return len; |
1137 | } |
1138 | |
1139 | static ssize_t os_desc_b_vendor_code_show(struct config_item *item, char *page) |
1140 | { |
1141 | return sprintf(buf: page, fmt: "0x%02x\n" , |
1142 | os_desc_item_to_gadget_info(item)->b_vendor_code); |
1143 | } |
1144 | |
1145 | static ssize_t os_desc_b_vendor_code_store(struct config_item *item, |
1146 | const char *page, size_t len) |
1147 | { |
1148 | struct gadget_info *gi = os_desc_item_to_gadget_info(item); |
1149 | int ret; |
1150 | u8 b_vendor_code; |
1151 | |
1152 | ret = kstrtou8(s: page, base: 0, res: &b_vendor_code); |
1153 | if (ret) |
1154 | return ret; |
1155 | |
1156 | mutex_lock(&gi->lock); |
1157 | gi->b_vendor_code = b_vendor_code; |
1158 | mutex_unlock(lock: &gi->lock); |
1159 | |
1160 | return len; |
1161 | } |
1162 | |
1163 | static ssize_t os_desc_qw_sign_show(struct config_item *item, char *page) |
1164 | { |
1165 | struct gadget_info *gi = os_desc_item_to_gadget_info(item); |
1166 | int res; |
1167 | |
1168 | res = utf16s_to_utf8s(pwcs: (wchar_t *) gi->qw_sign, OS_STRING_QW_SIGN_LEN, |
1169 | endian: UTF16_LITTLE_ENDIAN, s: page, PAGE_SIZE - 1); |
1170 | page[res++] = '\n'; |
1171 | |
1172 | return res; |
1173 | } |
1174 | |
1175 | static ssize_t os_desc_qw_sign_store(struct config_item *item, const char *page, |
1176 | size_t len) |
1177 | { |
1178 | struct gadget_info *gi = os_desc_item_to_gadget_info(item); |
1179 | int res, l; |
1180 | |
1181 | l = min((int)len, OS_STRING_QW_SIGN_LEN >> 1); |
1182 | if (page[l - 1] == '\n') |
1183 | --l; |
1184 | |
1185 | mutex_lock(&gi->lock); |
1186 | res = utf8s_to_utf16s(s: page, len: l, |
1187 | endian: UTF16_LITTLE_ENDIAN, pwcs: (wchar_t *) gi->qw_sign, |
1188 | OS_STRING_QW_SIGN_LEN); |
1189 | if (res > 0) |
1190 | res = len; |
1191 | mutex_unlock(lock: &gi->lock); |
1192 | |
1193 | return res; |
1194 | } |
1195 | |
1196 | CONFIGFS_ATTR(os_desc_, use); |
1197 | CONFIGFS_ATTR(os_desc_, b_vendor_code); |
1198 | CONFIGFS_ATTR(os_desc_, qw_sign); |
1199 | |
1200 | static struct configfs_attribute *os_desc_attrs[] = { |
1201 | &os_desc_attr_use, |
1202 | &os_desc_attr_b_vendor_code, |
1203 | &os_desc_attr_qw_sign, |
1204 | NULL, |
1205 | }; |
1206 | |
1207 | static int os_desc_link(struct config_item *os_desc_ci, |
1208 | struct config_item *usb_cfg_ci) |
1209 | { |
1210 | struct gadget_info *gi = os_desc_item_to_gadget_info(item: os_desc_ci); |
1211 | struct usb_composite_dev *cdev = &gi->cdev; |
1212 | struct config_usb_cfg *c_target = to_config_usb_cfg(item: usb_cfg_ci); |
1213 | struct usb_configuration *c = NULL, *iter; |
1214 | int ret; |
1215 | |
1216 | mutex_lock(&gi->lock); |
1217 | list_for_each_entry(iter, &cdev->configs, list) { |
1218 | if (iter != &c_target->c) |
1219 | continue; |
1220 | c = iter; |
1221 | break; |
1222 | } |
1223 | if (!c) { |
1224 | ret = -EINVAL; |
1225 | goto out; |
1226 | } |
1227 | |
1228 | if (cdev->os_desc_config) { |
1229 | ret = -EBUSY; |
1230 | goto out; |
1231 | } |
1232 | |
1233 | cdev->os_desc_config = &c_target->c; |
1234 | ret = 0; |
1235 | |
1236 | out: |
1237 | mutex_unlock(lock: &gi->lock); |
1238 | return ret; |
1239 | } |
1240 | |
1241 | static void os_desc_unlink(struct config_item *os_desc_ci, |
1242 | struct config_item *usb_cfg_ci) |
1243 | { |
1244 | struct gadget_info *gi = os_desc_item_to_gadget_info(item: os_desc_ci); |
1245 | struct usb_composite_dev *cdev = &gi->cdev; |
1246 | |
1247 | mutex_lock(&gi->lock); |
1248 | if (gi->composite.gadget_driver.udc_name) |
1249 | unregister_gadget(gi); |
1250 | cdev->os_desc_config = NULL; |
1251 | WARN_ON(gi->composite.gadget_driver.udc_name); |
1252 | mutex_unlock(lock: &gi->lock); |
1253 | } |
1254 | |
1255 | static struct configfs_item_operations os_desc_ops = { |
1256 | .allow_link = os_desc_link, |
1257 | .drop_link = os_desc_unlink, |
1258 | }; |
1259 | |
1260 | static struct config_item_type os_desc_type = { |
1261 | .ct_item_ops = &os_desc_ops, |
1262 | .ct_attrs = os_desc_attrs, |
1263 | .ct_owner = THIS_MODULE, |
1264 | }; |
1265 | |
1266 | static inline struct usb_os_desc_ext_prop |
1267 | *to_usb_os_desc_ext_prop(struct config_item *item) |
1268 | { |
1269 | return container_of(item, struct usb_os_desc_ext_prop, item); |
1270 | } |
1271 | |
1272 | static ssize_t ext_prop_type_show(struct config_item *item, char *page) |
1273 | { |
1274 | return sprintf(buf: page, fmt: "%d\n" , to_usb_os_desc_ext_prop(item)->type); |
1275 | } |
1276 | |
1277 | static ssize_t ext_prop_type_store(struct config_item *item, |
1278 | const char *page, size_t len) |
1279 | { |
1280 | struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item); |
1281 | struct usb_os_desc *desc = to_usb_os_desc(item: ext_prop->item.ci_parent); |
1282 | u8 type; |
1283 | int ret; |
1284 | |
1285 | ret = kstrtou8(s: page, base: 0, res: &type); |
1286 | if (ret) |
1287 | return ret; |
1288 | |
1289 | if (type < USB_EXT_PROP_UNICODE || type > USB_EXT_PROP_UNICODE_MULTI) |
1290 | return -EINVAL; |
1291 | |
1292 | if (desc->opts_mutex) |
1293 | mutex_lock(desc->opts_mutex); |
1294 | |
1295 | if ((ext_prop->type == USB_EXT_PROP_BINARY || |
1296 | ext_prop->type == USB_EXT_PROP_LE32 || |
1297 | ext_prop->type == USB_EXT_PROP_BE32) && |
1298 | (type == USB_EXT_PROP_UNICODE || |
1299 | type == USB_EXT_PROP_UNICODE_ENV || |
1300 | type == USB_EXT_PROP_UNICODE_LINK)) |
1301 | ext_prop->data_len <<= 1; |
1302 | else if ((ext_prop->type == USB_EXT_PROP_UNICODE || |
1303 | ext_prop->type == USB_EXT_PROP_UNICODE_ENV || |
1304 | ext_prop->type == USB_EXT_PROP_UNICODE_LINK) && |
1305 | (type == USB_EXT_PROP_BINARY || |
1306 | type == USB_EXT_PROP_LE32 || |
1307 | type == USB_EXT_PROP_BE32)) |
1308 | ext_prop->data_len >>= 1; |
1309 | ext_prop->type = type; |
1310 | |
1311 | if (desc->opts_mutex) |
1312 | mutex_unlock(lock: desc->opts_mutex); |
1313 | return len; |
1314 | } |
1315 | |
1316 | static ssize_t ext_prop_data_show(struct config_item *item, char *page) |
1317 | { |
1318 | struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item); |
1319 | int len = ext_prop->data_len; |
1320 | |
1321 | if (ext_prop->type == USB_EXT_PROP_UNICODE || |
1322 | ext_prop->type == USB_EXT_PROP_UNICODE_ENV || |
1323 | ext_prop->type == USB_EXT_PROP_UNICODE_LINK) |
1324 | len >>= 1; |
1325 | memcpy(page, ext_prop->data, len); |
1326 | |
1327 | return len; |
1328 | } |
1329 | |
1330 | static ssize_t ext_prop_data_store(struct config_item *item, |
1331 | const char *page, size_t len) |
1332 | { |
1333 | struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item); |
1334 | struct usb_os_desc *desc = to_usb_os_desc(item: ext_prop->item.ci_parent); |
1335 | char *new_data; |
1336 | size_t ret_len = len; |
1337 | |
1338 | if (page[len - 1] == '\n' || page[len - 1] == '\0') |
1339 | --len; |
1340 | new_data = kmemdup(p: page, size: len, GFP_KERNEL); |
1341 | if (!new_data) |
1342 | return -ENOMEM; |
1343 | |
1344 | if (desc->opts_mutex) |
1345 | mutex_lock(desc->opts_mutex); |
1346 | kfree(objp: ext_prop->data); |
1347 | ext_prop->data = new_data; |
1348 | desc->ext_prop_len -= ext_prop->data_len; |
1349 | ext_prop->data_len = len; |
1350 | desc->ext_prop_len += ext_prop->data_len; |
1351 | if (ext_prop->type == USB_EXT_PROP_UNICODE || |
1352 | ext_prop->type == USB_EXT_PROP_UNICODE_ENV || |
1353 | ext_prop->type == USB_EXT_PROP_UNICODE_LINK) { |
1354 | desc->ext_prop_len -= ext_prop->data_len; |
1355 | ext_prop->data_len <<= 1; |
1356 | ext_prop->data_len += 2; |
1357 | desc->ext_prop_len += ext_prop->data_len; |
1358 | } |
1359 | if (desc->opts_mutex) |
1360 | mutex_unlock(lock: desc->opts_mutex); |
1361 | return ret_len; |
1362 | } |
1363 | |
1364 | CONFIGFS_ATTR(ext_prop_, type); |
1365 | CONFIGFS_ATTR(ext_prop_, data); |
1366 | |
1367 | static struct configfs_attribute *ext_prop_attrs[] = { |
1368 | &ext_prop_attr_type, |
1369 | &ext_prop_attr_data, |
1370 | NULL, |
1371 | }; |
1372 | |
1373 | static void usb_os_desc_ext_prop_release(struct config_item *item) |
1374 | { |
1375 | struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item); |
1376 | |
1377 | kfree(objp: ext_prop); /* frees a whole chunk */ |
1378 | } |
1379 | |
1380 | static struct configfs_item_operations ext_prop_ops = { |
1381 | .release = usb_os_desc_ext_prop_release, |
1382 | }; |
1383 | |
1384 | static struct config_item *ext_prop_make( |
1385 | struct config_group *group, |
1386 | const char *name) |
1387 | { |
1388 | struct usb_os_desc_ext_prop *ext_prop; |
1389 | struct config_item_type *ext_prop_type; |
1390 | struct usb_os_desc *desc; |
1391 | char *vlabuf; |
1392 | |
1393 | vla_group(data_chunk); |
1394 | vla_item(data_chunk, struct usb_os_desc_ext_prop, ext_prop, 1); |
1395 | vla_item(data_chunk, struct config_item_type, ext_prop_type, 1); |
1396 | |
1397 | vlabuf = kzalloc(vla_group_size(data_chunk), GFP_KERNEL); |
1398 | if (!vlabuf) |
1399 | return ERR_PTR(error: -ENOMEM); |
1400 | |
1401 | ext_prop = vla_ptr(vlabuf, data_chunk, ext_prop); |
1402 | ext_prop_type = vla_ptr(vlabuf, data_chunk, ext_prop_type); |
1403 | |
1404 | desc = container_of(group, struct usb_os_desc, group); |
1405 | ext_prop_type->ct_item_ops = &ext_prop_ops; |
1406 | ext_prop_type->ct_attrs = ext_prop_attrs; |
1407 | ext_prop_type->ct_owner = desc->owner; |
1408 | |
1409 | config_item_init_type_name(item: &ext_prop->item, name, type: ext_prop_type); |
1410 | |
1411 | ext_prop->name = kstrdup(s: name, GFP_KERNEL); |
1412 | if (!ext_prop->name) { |
1413 | kfree(objp: vlabuf); |
1414 | return ERR_PTR(error: -ENOMEM); |
1415 | } |
1416 | desc->ext_prop_len += 14; |
1417 | ext_prop->name_len = 2 * strlen(ext_prop->name) + 2; |
1418 | if (desc->opts_mutex) |
1419 | mutex_lock(desc->opts_mutex); |
1420 | desc->ext_prop_len += ext_prop->name_len; |
1421 | list_add_tail(new: &ext_prop->entry, head: &desc->ext_prop); |
1422 | ++desc->ext_prop_count; |
1423 | if (desc->opts_mutex) |
1424 | mutex_unlock(lock: desc->opts_mutex); |
1425 | |
1426 | return &ext_prop->item; |
1427 | } |
1428 | |
1429 | static void ext_prop_drop(struct config_group *group, struct config_item *item) |
1430 | { |
1431 | struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item); |
1432 | struct usb_os_desc *desc = to_usb_os_desc(item: &group->cg_item); |
1433 | |
1434 | if (desc->opts_mutex) |
1435 | mutex_lock(desc->opts_mutex); |
1436 | list_del(entry: &ext_prop->entry); |
1437 | --desc->ext_prop_count; |
1438 | kfree(objp: ext_prop->name); |
1439 | desc->ext_prop_len -= (ext_prop->name_len + ext_prop->data_len + 14); |
1440 | if (desc->opts_mutex) |
1441 | mutex_unlock(lock: desc->opts_mutex); |
1442 | config_item_put(item); |
1443 | } |
1444 | |
1445 | static struct configfs_group_operations interf_grp_ops = { |
1446 | .make_item = &ext_prop_make, |
1447 | .drop_item = &ext_prop_drop, |
1448 | }; |
1449 | |
1450 | static ssize_t interf_grp_compatible_id_show(struct config_item *item, |
1451 | char *page) |
1452 | { |
1453 | memcpy(page, to_usb_os_desc(item)->ext_compat_id, 8); |
1454 | return 8; |
1455 | } |
1456 | |
1457 | static ssize_t interf_grp_compatible_id_store(struct config_item *item, |
1458 | const char *page, size_t len) |
1459 | { |
1460 | struct usb_os_desc *desc = to_usb_os_desc(item); |
1461 | int l; |
1462 | |
1463 | l = min_t(int, 8, len); |
1464 | if (page[l - 1] == '\n') |
1465 | --l; |
1466 | if (desc->opts_mutex) |
1467 | mutex_lock(desc->opts_mutex); |
1468 | memcpy(desc->ext_compat_id, page, l); |
1469 | |
1470 | if (desc->opts_mutex) |
1471 | mutex_unlock(lock: desc->opts_mutex); |
1472 | |
1473 | return len; |
1474 | } |
1475 | |
1476 | static ssize_t interf_grp_sub_compatible_id_show(struct config_item *item, |
1477 | char *page) |
1478 | { |
1479 | memcpy(page, to_usb_os_desc(item)->ext_compat_id + 8, 8); |
1480 | return 8; |
1481 | } |
1482 | |
1483 | static ssize_t interf_grp_sub_compatible_id_store(struct config_item *item, |
1484 | const char *page, size_t len) |
1485 | { |
1486 | struct usb_os_desc *desc = to_usb_os_desc(item); |
1487 | int l; |
1488 | |
1489 | l = min_t(int, 8, len); |
1490 | if (page[l - 1] == '\n') |
1491 | --l; |
1492 | if (desc->opts_mutex) |
1493 | mutex_lock(desc->opts_mutex); |
1494 | memcpy(desc->ext_compat_id + 8, page, l); |
1495 | |
1496 | if (desc->opts_mutex) |
1497 | mutex_unlock(lock: desc->opts_mutex); |
1498 | |
1499 | return len; |
1500 | } |
1501 | |
1502 | CONFIGFS_ATTR(interf_grp_, compatible_id); |
1503 | CONFIGFS_ATTR(interf_grp_, sub_compatible_id); |
1504 | |
1505 | static struct configfs_attribute *interf_grp_attrs[] = { |
1506 | &interf_grp_attr_compatible_id, |
1507 | &interf_grp_attr_sub_compatible_id, |
1508 | NULL |
1509 | }; |
1510 | |
1511 | struct config_group *usb_os_desc_prepare_interf_dir( |
1512 | struct config_group *parent, |
1513 | int n_interf, |
1514 | struct usb_os_desc **desc, |
1515 | char **names, |
1516 | struct module *owner) |
1517 | { |
1518 | struct config_group *os_desc_group; |
1519 | struct config_item_type *os_desc_type, *interface_type; |
1520 | |
1521 | vla_group(data_chunk); |
1522 | vla_item(data_chunk, struct config_group, os_desc_group, 1); |
1523 | vla_item(data_chunk, struct config_item_type, os_desc_type, 1); |
1524 | vla_item(data_chunk, struct config_item_type, interface_type, 1); |
1525 | |
1526 | char *vlabuf = kzalloc(vla_group_size(data_chunk), GFP_KERNEL); |
1527 | if (!vlabuf) |
1528 | return ERR_PTR(error: -ENOMEM); |
1529 | |
1530 | os_desc_group = vla_ptr(vlabuf, data_chunk, os_desc_group); |
1531 | os_desc_type = vla_ptr(vlabuf, data_chunk, os_desc_type); |
1532 | interface_type = vla_ptr(vlabuf, data_chunk, interface_type); |
1533 | |
1534 | os_desc_type->ct_owner = owner; |
1535 | config_group_init_type_name(group: os_desc_group, name: "os_desc" , type: os_desc_type); |
1536 | configfs_add_default_group(new_group: os_desc_group, group: parent); |
1537 | |
1538 | interface_type->ct_group_ops = &interf_grp_ops; |
1539 | interface_type->ct_attrs = interf_grp_attrs; |
1540 | interface_type->ct_owner = owner; |
1541 | |
1542 | while (n_interf--) { |
1543 | struct usb_os_desc *d; |
1544 | |
1545 | d = desc[n_interf]; |
1546 | d->owner = owner; |
1547 | config_group_init_type_name(group: &d->group, name: "" , type: interface_type); |
1548 | config_item_set_name(&d->group.cg_item, "interface.%s" , |
1549 | names[n_interf]); |
1550 | configfs_add_default_group(new_group: &d->group, group: os_desc_group); |
1551 | } |
1552 | |
1553 | return os_desc_group; |
1554 | } |
1555 | EXPORT_SYMBOL(usb_os_desc_prepare_interf_dir); |
1556 | |
1557 | static int configfs_do_nothing(struct usb_composite_dev *cdev) |
1558 | { |
1559 | WARN_ON(1); |
1560 | return -EINVAL; |
1561 | } |
1562 | |
1563 | int composite_dev_prepare(struct usb_composite_driver *composite, |
1564 | struct usb_composite_dev *dev); |
1565 | |
1566 | int composite_os_desc_req_prepare(struct usb_composite_dev *cdev, |
1567 | struct usb_ep *ep0); |
1568 | |
1569 | static void purge_configs_funcs(struct gadget_info *gi) |
1570 | { |
1571 | struct usb_configuration *c; |
1572 | |
1573 | list_for_each_entry(c, &gi->cdev.configs, list) { |
1574 | struct usb_function *f, *tmp; |
1575 | struct config_usb_cfg *cfg; |
1576 | |
1577 | cfg = container_of(c, struct config_usb_cfg, c); |
1578 | |
1579 | list_for_each_entry_safe_reverse(f, tmp, &c->functions, list) { |
1580 | |
1581 | list_move(list: &f->list, head: &cfg->func_list); |
1582 | if (f->unbind) { |
1583 | dev_dbg(&gi->cdev.gadget->dev, |
1584 | "unbind function '%s'/%p\n" , |
1585 | f->name, f); |
1586 | f->unbind(c, f); |
1587 | } |
1588 | } |
1589 | c->next_interface_id = 0; |
1590 | memset(c->interface, 0, sizeof(c->interface)); |
1591 | c->superspeed_plus = 0; |
1592 | c->superspeed = 0; |
1593 | c->highspeed = 0; |
1594 | c->fullspeed = 0; |
1595 | } |
1596 | } |
1597 | |
1598 | static struct usb_string * |
1599 | configfs_attach_gadget_strings(struct gadget_info *gi) |
1600 | { |
1601 | struct usb_gadget_strings **gadget_strings; |
1602 | struct gadget_language *language; |
1603 | struct gadget_string *string; |
1604 | unsigned int nlangs = 0; |
1605 | struct list_head *iter; |
1606 | struct usb_string *us; |
1607 | unsigned int i = 0; |
1608 | int nstrings = -1; |
1609 | unsigned int j; |
1610 | |
1611 | list_for_each(iter, &gi->string_list) |
1612 | nlangs++; |
1613 | |
1614 | /* Bail out early if no languages are configured */ |
1615 | if (!nlangs) |
1616 | return NULL; |
1617 | |
1618 | gadget_strings = kcalloc(n: nlangs + 1, /* including NULL terminator */ |
1619 | size: sizeof(struct usb_gadget_strings *), GFP_KERNEL); |
1620 | if (!gadget_strings) |
1621 | return ERR_PTR(error: -ENOMEM); |
1622 | |
1623 | list_for_each_entry(language, &gi->string_list, list) { |
1624 | struct usb_string *stringtab; |
1625 | |
1626 | if (nstrings == -1) { |
1627 | nstrings = language->nstrings; |
1628 | } else if (nstrings != language->nstrings) { |
1629 | pr_err("languages must contain the same number of strings\n" ); |
1630 | us = ERR_PTR(error: -EINVAL); |
1631 | goto cleanup; |
1632 | } |
1633 | |
1634 | stringtab = kcalloc(n: language->nstrings + 1, size: sizeof(struct usb_string), |
1635 | GFP_KERNEL); |
1636 | if (!stringtab) { |
1637 | us = ERR_PTR(error: -ENOMEM); |
1638 | goto cleanup; |
1639 | } |
1640 | |
1641 | stringtab[USB_GADGET_MANUFACTURER_IDX].id = USB_GADGET_MANUFACTURER_IDX; |
1642 | stringtab[USB_GADGET_MANUFACTURER_IDX].s = language->manufacturer; |
1643 | stringtab[USB_GADGET_PRODUCT_IDX].id = USB_GADGET_PRODUCT_IDX; |
1644 | stringtab[USB_GADGET_PRODUCT_IDX].s = language->product; |
1645 | stringtab[USB_GADGET_SERIAL_IDX].id = USB_GADGET_SERIAL_IDX; |
1646 | stringtab[USB_GADGET_SERIAL_IDX].s = language->serialnumber; |
1647 | |
1648 | j = USB_GADGET_FIRST_AVAIL_IDX; |
1649 | list_for_each_entry(string, &language->gadget_strings, list) { |
1650 | memcpy(&stringtab[j], &string->usb_string, sizeof(struct usb_string)); |
1651 | j++; |
1652 | } |
1653 | |
1654 | language->stringtab_dev.strings = stringtab; |
1655 | gadget_strings[i] = &language->stringtab_dev; |
1656 | i++; |
1657 | } |
1658 | |
1659 | us = usb_gstrings_attach(cdev: &gi->cdev, sp: gadget_strings, n_strings: nstrings); |
1660 | |
1661 | cleanup: |
1662 | list_for_each_entry(language, &gi->string_list, list) { |
1663 | kfree(objp: language->stringtab_dev.strings); |
1664 | language->stringtab_dev.strings = NULL; |
1665 | } |
1666 | |
1667 | kfree(objp: gadget_strings); |
1668 | |
1669 | return us; |
1670 | } |
1671 | |
1672 | static int configfs_composite_bind(struct usb_gadget *gadget, |
1673 | struct usb_gadget_driver *gdriver) |
1674 | { |
1675 | struct usb_composite_driver *composite = to_cdriver(gdrv: gdriver); |
1676 | struct gadget_info *gi = container_of(composite, |
1677 | struct gadget_info, composite); |
1678 | struct usb_composite_dev *cdev = &gi->cdev; |
1679 | struct usb_configuration *c; |
1680 | struct usb_string *s; |
1681 | unsigned i; |
1682 | int ret; |
1683 | |
1684 | /* the gi->lock is hold by the caller */ |
1685 | gi->unbind = 0; |
1686 | cdev->gadget = gadget; |
1687 | set_gadget_data(gadget, data: cdev); |
1688 | ret = composite_dev_prepare(composite, dev: cdev); |
1689 | if (ret) |
1690 | return ret; |
1691 | /* and now the gadget bind */ |
1692 | ret = -EINVAL; |
1693 | |
1694 | if (list_empty(head: &gi->cdev.configs)) { |
1695 | pr_err("Need at least one configuration in %s.\n" , |
1696 | gi->composite.name); |
1697 | goto err_comp_cleanup; |
1698 | } |
1699 | |
1700 | |
1701 | list_for_each_entry(c, &gi->cdev.configs, list) { |
1702 | struct config_usb_cfg *cfg; |
1703 | |
1704 | cfg = container_of(c, struct config_usb_cfg, c); |
1705 | if (list_empty(head: &cfg->func_list)) { |
1706 | pr_err("Config %s/%d of %s needs at least one function.\n" , |
1707 | c->label, c->bConfigurationValue, |
1708 | gi->composite.name); |
1709 | goto err_comp_cleanup; |
1710 | } |
1711 | } |
1712 | |
1713 | /* init all strings */ |
1714 | if (!list_empty(head: &gi->string_list)) { |
1715 | s = configfs_attach_gadget_strings(gi); |
1716 | if (IS_ERR(ptr: s)) { |
1717 | ret = PTR_ERR(ptr: s); |
1718 | goto err_comp_cleanup; |
1719 | } |
1720 | |
1721 | gi->cdev.desc.iManufacturer = s[USB_GADGET_MANUFACTURER_IDX].id; |
1722 | gi->cdev.desc.iProduct = s[USB_GADGET_PRODUCT_IDX].id; |
1723 | gi->cdev.desc.iSerialNumber = s[USB_GADGET_SERIAL_IDX].id; |
1724 | |
1725 | gi->cdev.usb_strings = s; |
1726 | } |
1727 | |
1728 | if (gi->use_webusb) { |
1729 | cdev->use_webusb = true; |
1730 | cdev->bcd_webusb_version = gi->bcd_webusb_version; |
1731 | cdev->b_webusb_vendor_code = gi->b_webusb_vendor_code; |
1732 | memcpy(cdev->landing_page, gi->landing_page, WEBUSB_URL_RAW_MAX_LENGTH); |
1733 | } |
1734 | |
1735 | if (gi->use_os_desc) { |
1736 | cdev->use_os_string = true; |
1737 | cdev->b_vendor_code = gi->b_vendor_code; |
1738 | memcpy(cdev->qw_sign, gi->qw_sign, OS_STRING_QW_SIGN_LEN); |
1739 | } |
1740 | |
1741 | if (gadget_is_otg(g: gadget) && !otg_desc[0]) { |
1742 | struct usb_descriptor_header *usb_desc; |
1743 | |
1744 | usb_desc = usb_otg_descriptor_alloc(gadget); |
1745 | if (!usb_desc) { |
1746 | ret = -ENOMEM; |
1747 | goto err_comp_cleanup; |
1748 | } |
1749 | usb_otg_descriptor_init(gadget, otg_desc: usb_desc); |
1750 | otg_desc[0] = usb_desc; |
1751 | otg_desc[1] = NULL; |
1752 | } |
1753 | |
1754 | /* Go through all configs, attach all functions */ |
1755 | list_for_each_entry(c, &gi->cdev.configs, list) { |
1756 | struct config_usb_cfg *cfg; |
1757 | struct usb_function *f; |
1758 | struct usb_function *tmp; |
1759 | struct gadget_config_name *cn; |
1760 | |
1761 | if (gadget_is_otg(g: gadget)) |
1762 | c->descriptors = otg_desc; |
1763 | |
1764 | /* Properly configure the bmAttributes wakeup bit */ |
1765 | check_remote_wakeup_config(g: gadget, c); |
1766 | |
1767 | cfg = container_of(c, struct config_usb_cfg, c); |
1768 | if (!list_empty(head: &cfg->string_list)) { |
1769 | i = 0; |
1770 | list_for_each_entry(cn, &cfg->string_list, list) { |
1771 | cfg->gstrings[i] = &cn->stringtab_dev; |
1772 | cn->stringtab_dev.strings = &cn->strings; |
1773 | cn->strings.s = cn->configuration; |
1774 | i++; |
1775 | } |
1776 | cfg->gstrings[i] = NULL; |
1777 | s = usb_gstrings_attach(cdev: &gi->cdev, sp: cfg->gstrings, n_strings: 1); |
1778 | if (IS_ERR(ptr: s)) { |
1779 | ret = PTR_ERR(ptr: s); |
1780 | goto err_comp_cleanup; |
1781 | } |
1782 | c->iConfiguration = s[0].id; |
1783 | } |
1784 | |
1785 | list_for_each_entry_safe(f, tmp, &cfg->func_list, list) { |
1786 | list_del(entry: &f->list); |
1787 | ret = usb_add_function(c, f); |
1788 | if (ret) { |
1789 | list_add(new: &f->list, head: &cfg->func_list); |
1790 | goto err_purge_funcs; |
1791 | } |
1792 | } |
1793 | ret = usb_gadget_check_config(gadget: cdev->gadget); |
1794 | if (ret) |
1795 | goto err_purge_funcs; |
1796 | |
1797 | usb_ep_autoconfig_reset(cdev->gadget); |
1798 | } |
1799 | if (cdev->use_os_string) { |
1800 | ret = composite_os_desc_req_prepare(cdev, ep0: gadget->ep0); |
1801 | if (ret) |
1802 | goto err_purge_funcs; |
1803 | } |
1804 | |
1805 | usb_ep_autoconfig_reset(cdev->gadget); |
1806 | return 0; |
1807 | |
1808 | err_purge_funcs: |
1809 | purge_configs_funcs(gi); |
1810 | err_comp_cleanup: |
1811 | composite_dev_cleanup(cdev); |
1812 | return ret; |
1813 | } |
1814 | |
1815 | static void configfs_composite_unbind(struct usb_gadget *gadget) |
1816 | { |
1817 | struct usb_composite_dev *cdev; |
1818 | struct gadget_info *gi; |
1819 | unsigned long flags; |
1820 | |
1821 | /* the gi->lock is hold by the caller */ |
1822 | |
1823 | cdev = get_gadget_data(gadget); |
1824 | gi = container_of(cdev, struct gadget_info, cdev); |
1825 | spin_lock_irqsave(&gi->spinlock, flags); |
1826 | gi->unbind = 1; |
1827 | spin_unlock_irqrestore(lock: &gi->spinlock, flags); |
1828 | |
1829 | kfree(objp: otg_desc[0]); |
1830 | otg_desc[0] = NULL; |
1831 | purge_configs_funcs(gi); |
1832 | composite_dev_cleanup(cdev); |
1833 | usb_ep_autoconfig_reset(cdev->gadget); |
1834 | spin_lock_irqsave(&gi->spinlock, flags); |
1835 | cdev->gadget = NULL; |
1836 | cdev->deactivations = 0; |
1837 | gadget->deactivated = false; |
1838 | set_gadget_data(gadget, NULL); |
1839 | spin_unlock_irqrestore(lock: &gi->spinlock, flags); |
1840 | } |
1841 | |
1842 | static int configfs_composite_setup(struct usb_gadget *gadget, |
1843 | const struct usb_ctrlrequest *ctrl) |
1844 | { |
1845 | struct usb_composite_dev *cdev; |
1846 | struct gadget_info *gi; |
1847 | unsigned long flags; |
1848 | int ret; |
1849 | |
1850 | cdev = get_gadget_data(gadget); |
1851 | if (!cdev) |
1852 | return 0; |
1853 | |
1854 | gi = container_of(cdev, struct gadget_info, cdev); |
1855 | spin_lock_irqsave(&gi->spinlock, flags); |
1856 | cdev = get_gadget_data(gadget); |
1857 | if (!cdev || gi->unbind) { |
1858 | spin_unlock_irqrestore(lock: &gi->spinlock, flags); |
1859 | return 0; |
1860 | } |
1861 | |
1862 | ret = composite_setup(gadget, ctrl); |
1863 | spin_unlock_irqrestore(lock: &gi->spinlock, flags); |
1864 | return ret; |
1865 | } |
1866 | |
1867 | static void configfs_composite_disconnect(struct usb_gadget *gadget) |
1868 | { |
1869 | struct usb_composite_dev *cdev; |
1870 | struct gadget_info *gi; |
1871 | unsigned long flags; |
1872 | |
1873 | cdev = get_gadget_data(gadget); |
1874 | if (!cdev) |
1875 | return; |
1876 | |
1877 | gi = container_of(cdev, struct gadget_info, cdev); |
1878 | spin_lock_irqsave(&gi->spinlock, flags); |
1879 | cdev = get_gadget_data(gadget); |
1880 | if (!cdev || gi->unbind) { |
1881 | spin_unlock_irqrestore(lock: &gi->spinlock, flags); |
1882 | return; |
1883 | } |
1884 | |
1885 | composite_disconnect(gadget); |
1886 | spin_unlock_irqrestore(lock: &gi->spinlock, flags); |
1887 | } |
1888 | |
1889 | static void configfs_composite_reset(struct usb_gadget *gadget) |
1890 | { |
1891 | struct usb_composite_dev *cdev; |
1892 | struct gadget_info *gi; |
1893 | unsigned long flags; |
1894 | |
1895 | cdev = get_gadget_data(gadget); |
1896 | if (!cdev) |
1897 | return; |
1898 | |
1899 | gi = container_of(cdev, struct gadget_info, cdev); |
1900 | spin_lock_irqsave(&gi->spinlock, flags); |
1901 | cdev = get_gadget_data(gadget); |
1902 | if (!cdev || gi->unbind) { |
1903 | spin_unlock_irqrestore(lock: &gi->spinlock, flags); |
1904 | return; |
1905 | } |
1906 | |
1907 | composite_reset(gadget); |
1908 | spin_unlock_irqrestore(lock: &gi->spinlock, flags); |
1909 | } |
1910 | |
1911 | static void configfs_composite_suspend(struct usb_gadget *gadget) |
1912 | { |
1913 | struct usb_composite_dev *cdev; |
1914 | struct gadget_info *gi; |
1915 | unsigned long flags; |
1916 | |
1917 | cdev = get_gadget_data(gadget); |
1918 | if (!cdev) |
1919 | return; |
1920 | |
1921 | gi = container_of(cdev, struct gadget_info, cdev); |
1922 | spin_lock_irqsave(&gi->spinlock, flags); |
1923 | cdev = get_gadget_data(gadget); |
1924 | if (!cdev || gi->unbind) { |
1925 | spin_unlock_irqrestore(lock: &gi->spinlock, flags); |
1926 | return; |
1927 | } |
1928 | |
1929 | composite_suspend(gadget); |
1930 | spin_unlock_irqrestore(lock: &gi->spinlock, flags); |
1931 | } |
1932 | |
1933 | static void configfs_composite_resume(struct usb_gadget *gadget) |
1934 | { |
1935 | struct usb_composite_dev *cdev; |
1936 | struct gadget_info *gi; |
1937 | unsigned long flags; |
1938 | |
1939 | cdev = get_gadget_data(gadget); |
1940 | if (!cdev) |
1941 | return; |
1942 | |
1943 | gi = container_of(cdev, struct gadget_info, cdev); |
1944 | spin_lock_irqsave(&gi->spinlock, flags); |
1945 | cdev = get_gadget_data(gadget); |
1946 | if (!cdev || gi->unbind) { |
1947 | spin_unlock_irqrestore(lock: &gi->spinlock, flags); |
1948 | return; |
1949 | } |
1950 | |
1951 | composite_resume(gadget); |
1952 | spin_unlock_irqrestore(lock: &gi->spinlock, flags); |
1953 | } |
1954 | |
1955 | static const struct usb_gadget_driver configfs_driver_template = { |
1956 | .bind = configfs_composite_bind, |
1957 | .unbind = configfs_composite_unbind, |
1958 | |
1959 | .setup = configfs_composite_setup, |
1960 | .reset = configfs_composite_reset, |
1961 | .disconnect = configfs_composite_disconnect, |
1962 | |
1963 | .suspend = configfs_composite_suspend, |
1964 | .resume = configfs_composite_resume, |
1965 | |
1966 | .max_speed = USB_SPEED_SUPER_PLUS, |
1967 | .driver = { |
1968 | .owner = THIS_MODULE, |
1969 | }, |
1970 | .match_existing_only = 1, |
1971 | }; |
1972 | |
1973 | static struct config_group *gadgets_make( |
1974 | struct config_group *group, |
1975 | const char *name) |
1976 | { |
1977 | struct gadget_info *gi; |
1978 | |
1979 | gi = kzalloc(size: sizeof(*gi), GFP_KERNEL); |
1980 | if (!gi) |
1981 | return ERR_PTR(error: -ENOMEM); |
1982 | |
1983 | config_group_init_type_name(group: &gi->group, name, type: &gadget_root_type); |
1984 | |
1985 | config_group_init_type_name(group: &gi->functions_group, name: "functions" , |
1986 | type: &functions_type); |
1987 | configfs_add_default_group(new_group: &gi->functions_group, group: &gi->group); |
1988 | |
1989 | config_group_init_type_name(group: &gi->configs_group, name: "configs" , |
1990 | type: &config_desc_type); |
1991 | configfs_add_default_group(new_group: &gi->configs_group, group: &gi->group); |
1992 | |
1993 | config_group_init_type_name(group: &gi->strings_group, name: "strings" , |
1994 | type: &gadget_language_strings_type); |
1995 | configfs_add_default_group(new_group: &gi->strings_group, group: &gi->group); |
1996 | |
1997 | config_group_init_type_name(group: &gi->os_desc_group, name: "os_desc" , |
1998 | type: &os_desc_type); |
1999 | configfs_add_default_group(new_group: &gi->os_desc_group, group: &gi->group); |
2000 | |
2001 | config_group_init_type_name(group: &gi->webusb_group, name: "webusb" , |
2002 | type: &webusb_type); |
2003 | configfs_add_default_group(new_group: &gi->webusb_group, group: &gi->group); |
2004 | |
2005 | gi->composite.bind = configfs_do_nothing; |
2006 | gi->composite.unbind = configfs_do_nothing; |
2007 | gi->composite.suspend = NULL; |
2008 | gi->composite.resume = NULL; |
2009 | gi->composite.max_speed = USB_SPEED_SUPER_PLUS; |
2010 | |
2011 | spin_lock_init(&gi->spinlock); |
2012 | mutex_init(&gi->lock); |
2013 | INIT_LIST_HEAD(list: &gi->string_list); |
2014 | INIT_LIST_HEAD(list: &gi->available_func); |
2015 | |
2016 | composite_init_dev(cdev: &gi->cdev); |
2017 | gi->cdev.desc.bLength = USB_DT_DEVICE_SIZE; |
2018 | gi->cdev.desc.bDescriptorType = USB_DT_DEVICE; |
2019 | gi->cdev.desc.bcdDevice = cpu_to_le16(get_default_bcdDevice()); |
2020 | |
2021 | gi->composite.gadget_driver = configfs_driver_template; |
2022 | |
2023 | gi->composite.gadget_driver.driver.name = kasprintf(GFP_KERNEL, |
2024 | fmt: "configfs-gadget.%s" , name); |
2025 | if (!gi->composite.gadget_driver.driver.name) |
2026 | goto err; |
2027 | |
2028 | gi->composite.gadget_driver.function = kstrdup(s: name, GFP_KERNEL); |
2029 | gi->composite.name = gi->composite.gadget_driver.function; |
2030 | |
2031 | if (!gi->composite.gadget_driver.function) |
2032 | goto out_free_driver_name; |
2033 | |
2034 | return &gi->group; |
2035 | |
2036 | out_free_driver_name: |
2037 | kfree(objp: gi->composite.gadget_driver.driver.name); |
2038 | err: |
2039 | kfree(objp: gi); |
2040 | return ERR_PTR(error: -ENOMEM); |
2041 | } |
2042 | |
2043 | static void gadgets_drop(struct config_group *group, struct config_item *item) |
2044 | { |
2045 | config_item_put(item); |
2046 | } |
2047 | |
2048 | static struct configfs_group_operations gadgets_ops = { |
2049 | .make_group = &gadgets_make, |
2050 | .drop_item = &gadgets_drop, |
2051 | }; |
2052 | |
2053 | static const struct config_item_type gadgets_type = { |
2054 | .ct_group_ops = &gadgets_ops, |
2055 | .ct_owner = THIS_MODULE, |
2056 | }; |
2057 | |
2058 | static struct configfs_subsystem gadget_subsys = { |
2059 | .su_group = { |
2060 | .cg_item = { |
2061 | .ci_namebuf = "usb_gadget" , |
2062 | .ci_type = &gadgets_type, |
2063 | }, |
2064 | }, |
2065 | .su_mutex = __MUTEX_INITIALIZER(gadget_subsys.su_mutex), |
2066 | }; |
2067 | |
2068 | void unregister_gadget_item(struct config_item *item) |
2069 | { |
2070 | struct gadget_info *gi = to_gadget_info(item); |
2071 | |
2072 | mutex_lock(&gi->lock); |
2073 | unregister_gadget(gi); |
2074 | mutex_unlock(lock: &gi->lock); |
2075 | } |
2076 | EXPORT_SYMBOL_GPL(unregister_gadget_item); |
2077 | |
2078 | static int __init gadget_cfs_init(void) |
2079 | { |
2080 | int ret; |
2081 | |
2082 | config_group_init(group: &gadget_subsys.su_group); |
2083 | |
2084 | ret = configfs_register_subsystem(subsys: &gadget_subsys); |
2085 | return ret; |
2086 | } |
2087 | module_init(gadget_cfs_init); |
2088 | |
2089 | static void __exit gadget_cfs_exit(void) |
2090 | { |
2091 | configfs_unregister_subsystem(subsys: &gadget_subsys); |
2092 | } |
2093 | module_exit(gadget_cfs_exit); |
2094 | |