On Tue, Apr 18 2017, Jerry Zhang wrote:
> Also change the docs to reflect that ENODEV is no longer returned.
>
> This allows users to make an ioctl call as the first action on a
> connection. Ex, some functions might want to get endpoint size
> before making any i/os.
>
> Previously, calling ioctls before read/write would depending on the
> timing of endpoints being enabled.
>
> Signed-off-by: Jerry Zhang <[email protected]>
> ---
> drivers/usb/gadget/function/f_fs.c | 86
> ++++++++++++++++++++-----------------
> include/uapi/linux/usb/functionfs.h | 5 +--
> 2 files changed, 49 insertions(+), 42 deletions(-)
>
> diff --git a/drivers/usb/gadget/function/f_fs.c
> b/drivers/usb/gadget/function/f_fs.c
> index a0085571824d..48de9e013ba8 100644
> --- a/drivers/usb/gadget/function/f_fs.c
> +++ b/drivers/usb/gadget/function/f_fs.c
> @@ -1190,6 +1190,7 @@ static long ffs_epfile_ioctl(struct file *file,
> unsigned code,
> unsigned long value)
> {
> struct ffs_epfile *epfile = file->private_data;
> + struct ffs_ep *ep;
> int ret;
>
> ENTER();
> @@ -1197,50 +1198,57 @@ static long ffs_epfile_ioctl(struct file *file,
> unsigned code,
> if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
> return -ENODEV;
>
> + /* Wait for endpoint to be enabled */
> + ep = epfile->ep;
> + if (!ep) {
> + if (file->f_flags & O_NONBLOCK)
> + return -EAGAIN;
> +
> + ret = wait_event_interruptible(epfile->wait, (ep = epfile->ep));
> + if (ret)
> + return -EINTR;
> + }
> +
> spin_lock_irq(&epfile->ffs->eps_lock);
epfile->ep may be NULL at this point, you need to handle that.
> - if (likely(epfile->ep)) {
> - switch (code) {
> - case FUNCTIONFS_FIFO_STATUS:
> - ret = usb_ep_fifo_status(epfile->ep->ep);
> - break;
> - case FUNCTIONFS_FIFO_FLUSH:
> - usb_ep_fifo_flush(epfile->ep->ep);
> - ret = 0;
> - break;
> - case FUNCTIONFS_CLEAR_HALT:
> - ret = usb_ep_clear_halt(epfile->ep->ep);
> + switch (code) {
> + case FUNCTIONFS_FIFO_STATUS:
> + ret = usb_ep_fifo_status(epfile->ep->ep);
> + break;
> + case FUNCTIONFS_FIFO_FLUSH:
> + usb_ep_fifo_flush(epfile->ep->ep);
> + ret = 0;
> + break;
> + case FUNCTIONFS_CLEAR_HALT:
> + ret = usb_ep_clear_halt(epfile->ep->ep);
> + break;
> + case FUNCTIONFS_ENDPOINT_REVMAP:
> + ret = epfile->ep->num;
> + break;
> + case FUNCTIONFS_ENDPOINT_DESC:
> + {
> + int desc_idx;
> + struct usb_endpoint_descriptor *desc;
> +
> + switch (epfile->ffs->gadget->speed) {
> + case USB_SPEED_SUPER:
> + desc_idx = 2;
> break;
> - case FUNCTIONFS_ENDPOINT_REVMAP:
> - ret = epfile->ep->num;
> + case USB_SPEED_HIGH:
> + desc_idx = 1;
> break;
> - case FUNCTIONFS_ENDPOINT_DESC:
> - {
> - int desc_idx;
> - struct usb_endpoint_descriptor *desc;
> -
> - switch (epfile->ffs->gadget->speed) {
> - case USB_SPEED_SUPER:
> - desc_idx = 2;
> - break;
> - case USB_SPEED_HIGH:
> - desc_idx = 1;
> - break;
> - default:
> - desc_idx = 0;
> - }
> - desc = epfile->ep->descs[desc_idx];
> -
> - spin_unlock_irq(&epfile->ffs->eps_lock);
> - ret = copy_to_user((void *)value, desc, desc->bLength);
> - if (ret)
> - ret = -EFAULT;
> - return ret;
> - }
> default:
> - ret = -ENOTTY;
> + desc_idx = 0;
> }
> - } else {
> - ret = -ENODEV;
> + desc = epfile->ep->descs[desc_idx];
> +
> + spin_unlock_irq(&epfile->ffs->eps_lock);
> + ret = copy_to_user((void *)value, desc, desc->bLength);
> + if (ret)
> + ret = -EFAULT;
> + return ret;
> + }
> + default:
> + ret = -ENOTTY;
> }
> spin_unlock_irq(&epfile->ffs->eps_lock);
>
> diff --git a/include/uapi/linux/usb/functionfs.h
> b/include/uapi/linux/usb/functionfs.h
> index 93085017513c..1dc0af5b6511 100644
> --- a/include/uapi/linux/usb/functionfs.h
> +++ b/include/uapi/linux/usb/functionfs.h
> @@ -274,13 +274,12 @@ struct usb_functionfs_event {
> #define FUNCTIONFS_INTERFACE_REVMAP _IO('g', 128)
>
> /*
> - * Returns real bEndpointAddress of an endpoint. If function is not
> - * active returns -ENODEV.
> + * Returns real bEndpointAddress of an endpoint.
> */
> #define FUNCTIONFS_ENDPOINT_REVMAP _IO('g', 129)
>
> /*
> - * Returns endpoint descriptor. If function is not active returns -ENODEV.
> + * Returns endpoint descriptor.
> */
> #define FUNCTIONFS_ENDPOINT_DESC _IOR('g', 130, \
> struct usb_endpoint_descriptor)
--
Best regards
ミハウ “𝓶𝓲𝓷𝓪86” ナザレヴイツ
«If at first you don’t succeed, give up skydiving»
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html