| .. | .. |
|---|
| 10 | 10 | #include <linux/ctype.h> |
|---|
| 11 | 11 | #include <linux/debugfs.h> |
|---|
| 12 | 12 | #include <linux/delay.h> |
|---|
| 13 | +#include <linux/idr.h> |
|---|
| 13 | 14 | #include <linux/kref.h> |
|---|
| 14 | 15 | #include <linux/miscdevice.h> |
|---|
| 15 | 16 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 34 | 35 | MODULE_LICENSE("GPL"); |
|---|
| 35 | 36 | |
|---|
| 36 | 37 | /*----------------------------------------------------------------------*/ |
|---|
| 38 | + |
|---|
| 39 | +static DEFINE_IDA(driver_id_numbers); |
|---|
| 40 | +#define DRIVER_DRIVER_NAME_LENGTH_MAX 32 |
|---|
| 37 | 41 | |
|---|
| 38 | 42 | #define RAW_EVENT_QUEUE_SIZE 16 |
|---|
| 39 | 43 | |
|---|
| .. | .. |
|---|
| 144 | 148 | STATE_DEV_INVALID = 0, |
|---|
| 145 | 149 | STATE_DEV_OPENED, |
|---|
| 146 | 150 | STATE_DEV_INITIALIZED, |
|---|
| 151 | + STATE_DEV_REGISTERING, |
|---|
| 147 | 152 | STATE_DEV_RUNNING, |
|---|
| 148 | 153 | STATE_DEV_CLOSED, |
|---|
| 149 | 154 | STATE_DEV_FAILED |
|---|
| .. | .. |
|---|
| 158 | 163 | |
|---|
| 159 | 164 | /* Reference to misc device: */ |
|---|
| 160 | 165 | struct device *dev; |
|---|
| 166 | + |
|---|
| 167 | + /* Make driver names unique */ |
|---|
| 168 | + int driver_id_number; |
|---|
| 161 | 169 | |
|---|
| 162 | 170 | /* Protected by lock: */ |
|---|
| 163 | 171 | enum dev_state state; |
|---|
| .. | .. |
|---|
| 187 | 195 | spin_lock_init(&dev->lock); |
|---|
| 188 | 196 | init_completion(&dev->ep0_done); |
|---|
| 189 | 197 | raw_event_queue_init(&dev->queue); |
|---|
| 198 | + dev->driver_id_number = -1; |
|---|
| 190 | 199 | return dev; |
|---|
| 191 | 200 | } |
|---|
| 192 | 201 | |
|---|
| .. | .. |
|---|
| 197 | 206 | |
|---|
| 198 | 207 | kfree(dev->udc_name); |
|---|
| 199 | 208 | 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); |
|---|
| 200 | 212 | if (dev->req) { |
|---|
| 201 | 213 | if (dev->ep0_urb_queued) |
|---|
| 202 | 214 | usb_ep_dequeue(dev->gadget->ep0, dev->req); |
|---|
| .. | .. |
|---|
| 417 | 429 | static int raw_ioctl_init(struct raw_dev *dev, unsigned long value) |
|---|
| 418 | 430 | { |
|---|
| 419 | 431 | int ret = 0; |
|---|
| 432 | + int driver_id_number; |
|---|
| 420 | 433 | struct usb_raw_init arg; |
|---|
| 421 | 434 | char *udc_driver_name; |
|---|
| 422 | 435 | char *udc_device_name; |
|---|
| 436 | + char *driver_driver_name; |
|---|
| 423 | 437 | unsigned long flags; |
|---|
| 424 | 438 | |
|---|
| 425 | 439 | if (copy_from_user(&arg, (void __user *)value, sizeof(arg))) |
|---|
| .. | .. |
|---|
| 438 | 452 | return -EINVAL; |
|---|
| 439 | 453 | } |
|---|
| 440 | 454 | |
|---|
| 455 | + driver_id_number = ida_alloc(&driver_id_numbers, GFP_KERNEL); |
|---|
| 456 | + if (driver_id_number < 0) |
|---|
| 457 | + return driver_id_number; |
|---|
| 458 | + |
|---|
| 459 | + driver_driver_name = kmalloc(DRIVER_DRIVER_NAME_LENGTH_MAX, GFP_KERNEL); |
|---|
| 460 | + if (!driver_driver_name) { |
|---|
| 461 | + ret = -ENOMEM; |
|---|
| 462 | + goto out_free_driver_id_number; |
|---|
| 463 | + } |
|---|
| 464 | + snprintf(driver_driver_name, DRIVER_DRIVER_NAME_LENGTH_MAX, |
|---|
| 465 | + DRIVER_NAME ".%d", driver_id_number); |
|---|
| 466 | + |
|---|
| 441 | 467 | udc_driver_name = kmalloc(UDC_NAME_LENGTH_MAX, GFP_KERNEL); |
|---|
| 442 | | - if (!udc_driver_name) |
|---|
| 443 | | - return -ENOMEM; |
|---|
| 468 | + if (!udc_driver_name) { |
|---|
| 469 | + ret = -ENOMEM; |
|---|
| 470 | + goto out_free_driver_driver_name; |
|---|
| 471 | + } |
|---|
| 444 | 472 | ret = strscpy(udc_driver_name, &arg.driver_name[0], |
|---|
| 445 | 473 | UDC_NAME_LENGTH_MAX); |
|---|
| 446 | | - if (ret < 0) { |
|---|
| 447 | | - kfree(udc_driver_name); |
|---|
| 448 | | - return ret; |
|---|
| 449 | | - } |
|---|
| 474 | + if (ret < 0) |
|---|
| 475 | + goto out_free_udc_driver_name; |
|---|
| 450 | 476 | ret = 0; |
|---|
| 451 | 477 | |
|---|
| 452 | 478 | udc_device_name = kmalloc(UDC_NAME_LENGTH_MAX, GFP_KERNEL); |
|---|
| 453 | 479 | if (!udc_device_name) { |
|---|
| 454 | | - kfree(udc_driver_name); |
|---|
| 455 | | - return -ENOMEM; |
|---|
| 480 | + ret = -ENOMEM; |
|---|
| 481 | + goto out_free_udc_driver_name; |
|---|
| 456 | 482 | } |
|---|
| 457 | 483 | ret = strscpy(udc_device_name, &arg.device_name[0], |
|---|
| 458 | 484 | UDC_NAME_LENGTH_MAX); |
|---|
| 459 | | - if (ret < 0) { |
|---|
| 460 | | - kfree(udc_driver_name); |
|---|
| 461 | | - kfree(udc_device_name); |
|---|
| 462 | | - return ret; |
|---|
| 463 | | - } |
|---|
| 485 | + if (ret < 0) |
|---|
| 486 | + goto out_free_udc_device_name; |
|---|
| 464 | 487 | ret = 0; |
|---|
| 465 | 488 | |
|---|
| 466 | 489 | spin_lock_irqsave(&dev->lock, flags); |
|---|
| 467 | 490 | if (dev->state != STATE_DEV_OPENED) { |
|---|
| 468 | 491 | dev_dbg(dev->dev, "fail, device is not opened\n"); |
|---|
| 469 | | - kfree(udc_driver_name); |
|---|
| 470 | | - kfree(udc_device_name); |
|---|
| 471 | 492 | ret = -EINVAL; |
|---|
| 472 | 493 | goto out_unlock; |
|---|
| 473 | 494 | } |
|---|
| .. | .. |
|---|
| 482 | 503 | dev->driver.suspend = gadget_suspend; |
|---|
| 483 | 504 | dev->driver.resume = gadget_resume; |
|---|
| 484 | 505 | dev->driver.reset = gadget_reset; |
|---|
| 485 | | - dev->driver.driver.name = DRIVER_NAME; |
|---|
| 506 | + dev->driver.driver.name = driver_driver_name; |
|---|
| 486 | 507 | dev->driver.udc_name = udc_device_name; |
|---|
| 487 | 508 | dev->driver.match_existing_only = 1; |
|---|
| 509 | + dev->driver_id_number = driver_id_number; |
|---|
| 488 | 510 | |
|---|
| 489 | 511 | dev->state = STATE_DEV_INITIALIZED; |
|---|
| 512 | + spin_unlock_irqrestore(&dev->lock, flags); |
|---|
| 513 | + return ret; |
|---|
| 490 | 514 | |
|---|
| 491 | 515 | out_unlock: |
|---|
| 492 | 516 | spin_unlock_irqrestore(&dev->lock, flags); |
|---|
| 517 | +out_free_udc_device_name: |
|---|
| 518 | + kfree(udc_device_name); |
|---|
| 519 | +out_free_udc_driver_name: |
|---|
| 520 | + kfree(udc_driver_name); |
|---|
| 521 | +out_free_driver_driver_name: |
|---|
| 522 | + kfree(driver_driver_name); |
|---|
| 523 | +out_free_driver_id_number: |
|---|
| 524 | + ida_free(&driver_id_numbers, driver_id_number); |
|---|
| 493 | 525 | return ret; |
|---|
| 494 | 526 | } |
|---|
| 495 | 527 | |
|---|
| .. | .. |
|---|
| 507 | 539 | ret = -EINVAL; |
|---|
| 508 | 540 | goto out_unlock; |
|---|
| 509 | 541 | } |
|---|
| 542 | + dev->state = STATE_DEV_REGISTERING; |
|---|
| 510 | 543 | spin_unlock_irqrestore(&dev->lock, flags); |
|---|
| 511 | 544 | |
|---|
| 512 | 545 | ret = usb_gadget_probe_driver(&dev->driver); |
|---|
| .. | .. |
|---|
| 564 | 597 | return -ENODEV; |
|---|
| 565 | 598 | } |
|---|
| 566 | 599 | length = min(arg.length, event->length); |
|---|
| 567 | | - if (copy_to_user((void __user *)value, event, sizeof(*event) + length)) |
|---|
| 600 | + if (copy_to_user((void __user *)value, event, sizeof(*event) + length)) { |
|---|
| 601 | + kfree(event); |
|---|
| 568 | 602 | return -EFAULT; |
|---|
| 603 | + } |
|---|
| 569 | 604 | |
|---|
| 605 | + kfree(event); |
|---|
| 570 | 606 | return 0; |
|---|
| 571 | 607 | } |
|---|
| 572 | 608 | |
|---|
| .. | .. |
|---|
| 1000 | 1036 | ret = -EBUSY; |
|---|
| 1001 | 1037 | goto out_unlock; |
|---|
| 1002 | 1038 | } |
|---|
| 1003 | | - if ((in && !ep->ep->caps.dir_in) || (!in && ep->ep->caps.dir_in)) { |
|---|
| 1039 | + if (in != usb_endpoint_dir_in(ep->ep->desc)) { |
|---|
| 1004 | 1040 | dev_dbg(&dev->gadget->dev, "fail, wrong direction\n"); |
|---|
| 1005 | 1041 | ret = -EINVAL; |
|---|
| 1006 | 1042 | goto out_unlock; |
|---|