forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/usb/gadget/legacy/raw_gadget.c
....@@ -10,6 +10,7 @@
1010 #include <linux/ctype.h>
1111 #include <linux/debugfs.h>
1212 #include <linux/delay.h>
13
+#include <linux/idr.h>
1314 #include <linux/kref.h>
1415 #include <linux/miscdevice.h>
1516 #include <linux/module.h>
....@@ -34,6 +35,9 @@
3435 MODULE_LICENSE("GPL");
3536
3637 /*----------------------------------------------------------------------*/
38
+
39
+static DEFINE_IDA(driver_id_numbers);
40
+#define DRIVER_DRIVER_NAME_LENGTH_MAX 32
3741
3842 #define RAW_EVENT_QUEUE_SIZE 16
3943
....@@ -144,6 +148,7 @@
144148 STATE_DEV_INVALID = 0,
145149 STATE_DEV_OPENED,
146150 STATE_DEV_INITIALIZED,
151
+ STATE_DEV_REGISTERING,
147152 STATE_DEV_RUNNING,
148153 STATE_DEV_CLOSED,
149154 STATE_DEV_FAILED
....@@ -158,6 +163,9 @@
158163
159164 /* Reference to misc device: */
160165 struct device *dev;
166
+
167
+ /* Make driver names unique */
168
+ int driver_id_number;
161169
162170 /* Protected by lock: */
163171 enum dev_state state;
....@@ -187,6 +195,7 @@
187195 spin_lock_init(&dev->lock);
188196 init_completion(&dev->ep0_done);
189197 raw_event_queue_init(&dev->queue);
198
+ dev->driver_id_number = -1;
190199 return dev;
191200 }
192201
....@@ -197,6 +206,9 @@
197206
198207 kfree(dev->udc_name);
199208 kfree(dev->driver.udc_name);
209
+ kfree(dev->driver.driver.name);
210
+ if (dev->driver_id_number >= 0)
211
+ ida_free(&driver_id_numbers, dev->driver_id_number);
200212 if (dev->req) {
201213 if (dev->ep0_urb_queued)
202214 usb_ep_dequeue(dev->gadget->ep0, dev->req);
....@@ -297,13 +309,15 @@
297309 dev->eps_num = i;
298310 spin_unlock_irqrestore(&dev->lock, flags);
299311
312
+ ret = raw_queue_event(dev, USB_RAW_EVENT_CONNECT, 0, NULL);
313
+ if (ret < 0) {
314
+ dev_err(&gadget->dev, "failed to queue event\n");
315
+ set_gadget_data(gadget, NULL);
316
+ return ret;
317
+ }
318
+
300319 /* Matches kref_put() in gadget_unbind(). */
301320 kref_get(&dev->count);
302
-
303
- ret = raw_queue_event(dev, USB_RAW_EVENT_CONNECT, 0, NULL);
304
- if (ret < 0)
305
- dev_err(&gadget->dev, "failed to queue event\n");
306
-
307321 return ret;
308322 }
309323
....@@ -417,9 +431,11 @@
417431 static int raw_ioctl_init(struct raw_dev *dev, unsigned long value)
418432 {
419433 int ret = 0;
434
+ int driver_id_number;
420435 struct usb_raw_init arg;
421436 char *udc_driver_name;
422437 char *udc_device_name;
438
+ char *driver_driver_name;
423439 unsigned long flags;
424440
425441 if (copy_from_user(&arg, (void __user *)value, sizeof(arg)))
....@@ -438,36 +454,43 @@
438454 return -EINVAL;
439455 }
440456
457
+ driver_id_number = ida_alloc(&driver_id_numbers, GFP_KERNEL);
458
+ if (driver_id_number < 0)
459
+ return driver_id_number;
460
+
461
+ driver_driver_name = kmalloc(DRIVER_DRIVER_NAME_LENGTH_MAX, GFP_KERNEL);
462
+ if (!driver_driver_name) {
463
+ ret = -ENOMEM;
464
+ goto out_free_driver_id_number;
465
+ }
466
+ snprintf(driver_driver_name, DRIVER_DRIVER_NAME_LENGTH_MAX,
467
+ DRIVER_NAME ".%d", driver_id_number);
468
+
441469 udc_driver_name = kmalloc(UDC_NAME_LENGTH_MAX, GFP_KERNEL);
442
- if (!udc_driver_name)
443
- return -ENOMEM;
470
+ if (!udc_driver_name) {
471
+ ret = -ENOMEM;
472
+ goto out_free_driver_driver_name;
473
+ }
444474 ret = strscpy(udc_driver_name, &arg.driver_name[0],
445475 UDC_NAME_LENGTH_MAX);
446
- if (ret < 0) {
447
- kfree(udc_driver_name);
448
- return ret;
449
- }
476
+ if (ret < 0)
477
+ goto out_free_udc_driver_name;
450478 ret = 0;
451479
452480 udc_device_name = kmalloc(UDC_NAME_LENGTH_MAX, GFP_KERNEL);
453481 if (!udc_device_name) {
454
- kfree(udc_driver_name);
455
- return -ENOMEM;
482
+ ret = -ENOMEM;
483
+ goto out_free_udc_driver_name;
456484 }
457485 ret = strscpy(udc_device_name, &arg.device_name[0],
458486 UDC_NAME_LENGTH_MAX);
459
- if (ret < 0) {
460
- kfree(udc_driver_name);
461
- kfree(udc_device_name);
462
- return ret;
463
- }
487
+ if (ret < 0)
488
+ goto out_free_udc_device_name;
464489 ret = 0;
465490
466491 spin_lock_irqsave(&dev->lock, flags);
467492 if (dev->state != STATE_DEV_OPENED) {
468493 dev_dbg(dev->dev, "fail, device is not opened\n");
469
- kfree(udc_driver_name);
470
- kfree(udc_device_name);
471494 ret = -EINVAL;
472495 goto out_unlock;
473496 }
....@@ -482,14 +505,25 @@
482505 dev->driver.suspend = gadget_suspend;
483506 dev->driver.resume = gadget_resume;
484507 dev->driver.reset = gadget_reset;
485
- dev->driver.driver.name = DRIVER_NAME;
508
+ dev->driver.driver.name = driver_driver_name;
486509 dev->driver.udc_name = udc_device_name;
487510 dev->driver.match_existing_only = 1;
511
+ dev->driver_id_number = driver_id_number;
488512
489513 dev->state = STATE_DEV_INITIALIZED;
514
+ spin_unlock_irqrestore(&dev->lock, flags);
515
+ return ret;
490516
491517 out_unlock:
492518 spin_unlock_irqrestore(&dev->lock, flags);
519
+out_free_udc_device_name:
520
+ kfree(udc_device_name);
521
+out_free_udc_driver_name:
522
+ kfree(udc_driver_name);
523
+out_free_driver_driver_name:
524
+ kfree(driver_driver_name);
525
+out_free_driver_id_number:
526
+ ida_free(&driver_id_numbers, driver_id_number);
493527 return ret;
494528 }
495529
....@@ -507,6 +541,7 @@
507541 ret = -EINVAL;
508542 goto out_unlock;
509543 }
544
+ dev->state = STATE_DEV_REGISTERING;
510545 spin_unlock_irqrestore(&dev->lock, flags);
511546
512547 ret = usb_gadget_probe_driver(&dev->driver);
....@@ -564,9 +599,12 @@
564599 return -ENODEV;
565600 }
566601 length = min(arg.length, event->length);
567
- if (copy_to_user((void __user *)value, event, sizeof(*event) + length))
602
+ if (copy_to_user((void __user *)value, event, sizeof(*event) + length)) {
603
+ kfree(event);
568604 return -EFAULT;
605
+ }
569606
607
+ kfree(event);
570608 return 0;
571609 }
572610
....@@ -1000,7 +1038,7 @@
10001038 ret = -EBUSY;
10011039 goto out_unlock;
10021040 }
1003
- if ((in && !ep->ep->caps.dir_in) || (!in && ep->ep->caps.dir_in)) {
1041
+ if (in != usb_endpoint_dir_in(ep->ep->desc)) {
10041042 dev_dbg(&dev->gadget->dev, "fail, wrong direction\n");
10051043 ret = -EINVAL;
10061044 goto out_unlock;