>From b444aeea9de2d8e507f2301f9fed1eb64dcc7e1e Mon Sep 17 00:00:00 2001 From: Petr Cvek Date: Wed, 3 Aug 2016 22:29:44 +0200 Subject: [PATCH] PXA27x UDC more endpoints for more gadgets + UVC gadget (configfs) --- drivers/usb/gadget/function/f_uvc.c | 6 ++- drivers/usb/gadget/function/uvc_v4l2.c | 34 +++++++++++++- drivers/usb/gadget/function/uvc_video.c | 3 +- drivers/usb/gadget/legacy/webcam.c | 35 +++++++-------- drivers/usb/gadget/udc/core.c | 3 ++ drivers/usb/gadget/udc/pxa27x_udc.c | 79 +++++++++++++++++++++------------ drivers/usb/gadget/udc/pxa27x_udc.h | 7 ++- 7 files changed, 116 insertions(+), 51 deletions(-) diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index 27ed51b5082f..ff20eacad4c4 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -597,6 +597,9 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) opts = fi_to_f_uvc_opts(f->fi); /* Sanity check the streaming endpoint module parameters. */ + + pr_info("[DEBUG] opts->streaming_maxpacket=%i\n",opts->streaming_maxpacket); + opts->streaming_interval = clamp(opts->streaming_interval, 1U, 16U); opts->streaming_maxpacket = clamp(opts->streaming_maxpacket, 1U, 3072U); opts->streaming_maxburst = min(opts->streaming_maxburst, 15U); @@ -845,7 +848,8 @@ static struct usb_function_instance *uvc_alloc_inst(void) (const struct uvc_descriptor_header * const *)ctl_cls; opts->streaming_interval = 1; - opts->streaming_maxpacket = 1024; + + opts->streaming_maxpacket = 256; //for PXA limit (PXA should support 1023) uvcg_attach_configfs(opts); return &opts->func_inst; diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index 3e22b45687d3..4a2957b765ae 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c @@ -61,6 +61,7 @@ struct uvc_format { static struct uvc_format uvc_formats[] = { { 16, V4L2_PIX_FMT_YUYV }, { 0, V4L2_PIX_FMT_MJPEG }, + { 0, V4L2_PIX_FMT_JPEG }, }; static int @@ -81,6 +82,34 @@ uvc_v4l2_querycap(struct file *file, void *fh, struct v4l2_capability *cap) return 0; } +//around v3.10 for v4l2 compliance +static int uvc_v4l2_enum_format(struct file *file, void *priv, + struct v4l2_fmtdesc *fmt) +{ + struct uvc_format *format; + enum v4l2_buf_type type = fmt->type; + + if (fmt->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) { + pr_info("wcam: bad type %i\n",fmt->type); + return -EINVAL; + } + + if (fmt->index >= ARRAY_SIZE(uvc_formats)) { + pr_info("wcam: index to high %i/%i\n",fmt->index,ARRAY_SIZE(uvc_formats)); + return -EINVAL; + } + + fmt->pixelformat = uvc_formats[fmt->index].fcc; + fmt->flags = 0; //V4L2_FMT_FLAG_COMPRESSED or V4L2_FMT_FLAG_EMULATED + + strlcpy(fmt->description, "TODO\0", + sizeof(fmt->description)); + + fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + + return 0; +} + static int uvc_v4l2_get_format(struct file *file, void *fh, struct v4l2_format *fmt) { @@ -94,7 +123,9 @@ uvc_v4l2_get_format(struct file *file, void *fh, struct v4l2_format *fmt) fmt->fmt.pix.field = V4L2_FIELD_NONE; fmt->fmt.pix.bytesperline = video->bpp * video->width / 8; fmt->fmt.pix.sizeimage = video->imagesize; - fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; +// fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; + fmt->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; + fmt->fmt.pix.priv = 0; return 0; @@ -263,6 +294,7 @@ uvc_v4l2_ioctl_default(struct file *file, void *fh, bool valid_prio, const struct v4l2_ioctl_ops uvc_v4l2_ioctl_ops = { .vidioc_querycap = uvc_v4l2_querycap, + .vidioc_enum_fmt_vid_out = uvc_v4l2_enum_format, .vidioc_g_fmt_vid_out = uvc_v4l2_get_format, .vidioc_s_fmt_vid_out = uvc_v4l2_set_format, .vidioc_reqbufs = uvc_v4l2_reqbufs, diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index 0f01c04d7cbd..e746b3bce90f 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -384,7 +384,8 @@ int uvcg_video_init(struct uvc_video *video) INIT_LIST_HEAD(&video->req_free); spin_lock_init(&video->req_lock); - video->fcc = V4L2_PIX_FMT_YUYV; +// video->fcc = V4L2_PIX_FMT_YUYV; +video->fcc = V4L2_PIX_FMT_MJPEG; video->bpp = 16; video->width = 320; video->height = 240; diff --git a/drivers/usb/gadget/legacy/webcam.c b/drivers/usb/gadget/legacy/webcam.c index f9661cd627c8..9478412b224d 100644 --- a/drivers/usb/gadget/legacy/webcam.c +++ b/drivers/usb/gadget/legacy/webcam.c @@ -42,7 +42,7 @@ MODULE_PARM_DESC(trace, "Trace level bitmask"); */ #define WEBCAM_VENDOR_ID 0x1d6b /* Linux Foundation */ -#define WEBCAM_PRODUCT_ID 0x0102 /* Webcam A/V gadget */ +#define WEBCAM_PRODUCT_ID 0x0666 /* Webcam A/V gadget, dummy PID */ #define WEBCAM_DEVICE_BCD 0x0010 /* 0.10 */ static char webcam_vendor_label[] = "Linux Foundation"; @@ -235,14 +235,14 @@ static const struct uvc_format_mjpeg uvc_format_mjpg = { DECLARE_UVC_FRAME_MJPEG(1); DECLARE_UVC_FRAME_MJPEG(3); -static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_360p = { +static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_240p = { .bLength = UVC_DT_FRAME_MJPEG_SIZE(3), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = UVC_VS_FRAME_MJPEG, .bFrameIndex = 1, .bmCapabilities = 0, - .wWidth = cpu_to_le16(640), - .wHeight = cpu_to_le16(360), + .wWidth = cpu_to_le16(320), + .wHeight = cpu_to_le16(240), .dwMinBitRate = cpu_to_le32(18432000), .dwMaxBitRate = cpu_to_le32(55296000), .dwMaxVideoFrameBufferSize = cpu_to_le32(460800), @@ -253,14 +253,14 @@ static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_360p = { .dwFrameInterval[2] = cpu_to_le32(5000000), }; -static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p = { +static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_480p = { .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = UVC_VS_FRAME_MJPEG, .bFrameIndex = 2, .bmCapabilities = 0, - .wWidth = cpu_to_le16(1280), - .wHeight = cpu_to_le16(720), + .wWidth = cpu_to_le16(640), + .wHeight = cpu_to_le16(480), .dwMinBitRate = cpu_to_le32(29491200), .dwMaxBitRate = cpu_to_le32(29491200), .dwMaxVideoFrameBufferSize = cpu_to_le32(1843200), @@ -296,12 +296,9 @@ static const struct uvc_descriptor_header * const uvc_ss_control_cls[] = { static const struct uvc_descriptor_header * const uvc_fs_streaming_cls[] = { (const struct uvc_descriptor_header *) &uvc_input_header, - (const struct uvc_descriptor_header *) &uvc_format_yuv, - (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p, - (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p, (const struct uvc_descriptor_header *) &uvc_format_mjpg, - (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p, - (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, + (const struct uvc_descriptor_header *) &uvc_frame_mjpg_240p, + (const struct uvc_descriptor_header *) &uvc_frame_mjpg_480p, (const struct uvc_descriptor_header *) &uvc_color_matching, NULL, }; @@ -312,8 +309,8 @@ static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = { (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p, (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p, (const struct uvc_descriptor_header *) &uvc_format_mjpg, - (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p, - (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, + (const struct uvc_descriptor_header *) &uvc_frame_mjpg_240p, + (const struct uvc_descriptor_header *) &uvc_frame_mjpg_480p, (const struct uvc_descriptor_header *) &uvc_color_matching, NULL, }; @@ -324,8 +321,8 @@ static const struct uvc_descriptor_header * const uvc_ss_streaming_cls[] = { (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p, (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p, (const struct uvc_descriptor_header *) &uvc_format_mjpg, - (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p, - (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, + (const struct uvc_descriptor_header *) &uvc_frame_mjpg_240p, + (const struct uvc_descriptor_header *) &uvc_frame_mjpg_480p, (const struct uvc_descriptor_header *) &uvc_color_matching, NULL, }; @@ -352,7 +349,7 @@ webcam_config_bind(struct usb_configuration *c) static struct usb_configuration webcam_config_driver = { .label = webcam_config_label, - .bConfigurationValue = 1, + .bConfigurationValue = 3, // set during userspace program test .iConfiguration = 0, /* dynamic */ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, .MaxPower = CONFIG_USB_GADGET_VBUS_DRAW, @@ -406,8 +403,10 @@ webcam_bind(struct usb_composite_dev *cdev) /* Register our configuration. */ if ((ret = usb_add_config(cdev, &webcam_config_driver, - webcam_config_bind)) < 0) + webcam_config_bind)) < 0) { + pr_err("ERR: webcam usb_add_config ret=%i\n",ret); goto error; + } usb_composite_overwrite_options(cdev, &coverwrite); INFO(cdev, "Webcam Video Gadget\n"); diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 0402177f93cd..382baf40d32b 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -897,6 +897,8 @@ int usb_gadget_ep_match_desc(struct usb_gadget *gadget, u16 max; int num_req_streams = 0; + pr_info("====name: %s, mp=%i\n",ep->name,ep->maxpacket_limit); + /* endpoint already claimed? */ if (ep->claimed) return 0; @@ -906,6 +908,7 @@ int usb_gadget_ep_match_desc(struct usb_gadget *gadget, if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in) return 0; + if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out) return 0; diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c index 7fa60f5b7ae4..654605412cfd 100644 --- a/drivers/usb/gadget/udc/pxa27x_udc.c +++ b/drivers/usb/gadget/udc/pxa27x_udc.c @@ -2381,38 +2381,61 @@ static struct pxa_udc memory = { .udc_usb_ep = { USB_EP_CTRL, - USB_EP_OUT_BULK(1), - USB_EP_IN_BULK(2), - USB_EP_IN_ISO(3), - USB_EP_OUT_ISO(4), - USB_EP_IN_INT(5), + USB_EP_IN_INT(1), + USB_EP_IN_INT(2), + USB_EP_OUT_INT(3), + + USB_EP_IN_ISO(4), + USB_EP_OUT_ISO(5), + USB_EP_IN_BULK(6), + USB_EP_OUT_BULK(7), + + USB_EP_IN_BULK(8), + USB_EP_OUT_BULK(9), + + USB_EP_IN_ISO(10), + USB_EP_OUT_BULK(11), + USB_EP_IN_BULK(12), + USB_EP_IN_INT(13), + USB_EP_OUT_INT(14), }, .pxa_ep = { PXA_EP_CTRL, - /* Endpoints for gadget zero */ - PXA_EP_OUT_BULK(1, 1, 3, 0, 0), - PXA_EP_IN_BULK(2, 2, 3, 0, 0), - /* Endpoints for ether gadget, file storage gadget */ - PXA_EP_OUT_BULK(3, 1, 1, 0, 0), - PXA_EP_IN_BULK(4, 2, 1, 0, 0), - PXA_EP_IN_ISO(5, 3, 1, 0, 0), - PXA_EP_OUT_ISO(6, 4, 1, 0, 0), - PXA_EP_IN_INT(7, 5, 1, 0, 0), - /* Endpoints for RNDIS, serial */ - PXA_EP_OUT_BULK(8, 1, 2, 0, 0), - PXA_EP_IN_BULK(9, 2, 2, 0, 0), - PXA_EP_IN_INT(10, 5, 2, 0, 0), - /* - * All the following endpoints are only for completion. They - * won't never work, as multiple interfaces are really broken on - * the pxa. - */ - PXA_EP_OUT_BULK(11, 1, 2, 1, 0), - PXA_EP_IN_BULK(12, 2, 2, 1, 0), - /* Endpoint for CDC Ether */ - PXA_EP_OUT_BULK(13, 1, 1, 1, 1), - PXA_EP_IN_BULK(14, 2, 1, 1, 1), + +/* NOTICE these endpoints were crafted (around 3.13) before changes in the UDC +endpoint lookup functions. They may be redundant now. */ + + /*g_hid*/ + PXA_EP_IN_INT(1, 1, 1, 0, 0), + PXA_EP_OUT_INT(2, 3, 1, 0, 0), + /*g_audio uac2*/ + PXA_EP_OUT_ISO(3, 5, 1, 1, 1), + PXA_EP_IN_ISO(4, 4, 1, 2, 1), + /*g_ether, mass storage*/ + PXA_EP_IN_BULK(5, 6, 1, 0, 0), + PXA_EP_OUT_BULK(6, 7, 1, 0, 0), + /*g_webcam*/ + PXA_EP_IN_INT(7, 1, 3, 0, 0), + PXA_EP_IN_ISO(8, 4, 3, 1, 1), + /*g_cdc maybe?*/ + PXA_EP_IN_BULK(9, 6, 1, 1, 1), + PXA_EP_OUT_BULK(10, 7, 1, 1, 1), + PXA_EP_IN_INT(11, 1, 1, 0, 0), + PXA_EP_IN_BULK(12, 6, 1, 0, 0), + PXA_EP_OUT_BULK(13, 7, 1, 0, 0), + PXA_EP_IN_INT(14, 2, 1, 0, 0), + /*additional userspace gadget?*/ + PXA_EP_IN_BULK(15, 6, 1, 2, 0), + PXA_EP_OUT_BULK(16, 7, 1, 2, 0), + PXA_EP_IN_ISO(17, 4, 1, 1, 1), + /*free*/ + PXA_EP_OUT_BULK(18, 11, 1, 1, 0), + PXA_EP_IN_BULK(19, 12, 2, 0, 0), + PXA_EP_OUT_BULK(20, 11, 2, 0, 0), + PXA_EP_IN_BULK(21, 12, 2, 1, 0), + PXA_EP_OUT_BULK(22, 11, 2, 1, 0), + PXA_EP_IN_INT(23, 13, 3, 0, 0), } }; diff --git a/drivers/usb/gadget/udc/pxa27x_udc.h b/drivers/usb/gadget/udc/pxa27x_udc.h index cea2cb79b30c..586c9bc9a748 100644 --- a/drivers/usb/gadget/udc/pxa27x_udc.h +++ b/drivers/usb/gadget/udc/pxa27x_udc.h @@ -261,6 +261,8 @@ USB_EP_CAPS_DIR_OUT) #define USB_EP_IN_INT(n) USB_EP_INT(n, "ep" #n "in-int", 1, \ USB_EP_CAPS_DIR_IN) +#define USB_EP_OUT_INT(n) USB_EP_INT(n, "ep" #n "out-int", 0, \ + USB_EP_CAPS_DIR_OUT) #define USB_EP_CTRL USB_EP_DEF(0, "ep0", 0, CONTROL, EP0_FIFO_SIZE, \ USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL) @@ -287,6 +289,7 @@ #define PXA_EP_IN_ISO(i, adr, c, f, a) PXA_EP_ISO(i, adr, 1, c, f, a) #define PXA_EP_OUT_ISO(i, adr, c, f, a) PXA_EP_ISO(i, adr, 0, c, f, a) #define PXA_EP_IN_INT(i, adr, c, f, a) PXA_EP_INT(i, adr, 1, c, f, a) +#define PXA_EP_OUT_INT(i, adr, c, f, a) PXA_EP_INT(i, adr, 0, c, f, a) #define PXA_EP_CTRL PXA_EP_DEF(0, 0, 0, 0, EP0_FIFO_SIZE, 0, 0, 0) struct pxa27x_udc; @@ -419,8 +422,8 @@ struct udc_stats { unsigned long irqs_reconfig; }; -#define NR_USB_ENDPOINTS (1 + 5) /* ep0 + ep1in-bulk + .. + ep3in-iso */ -#define NR_PXA_ENDPOINTS (1 + 14) /* ep0 + epA + epB + .. + epX */ +#define NR_USB_ENDPOINTS (1 + 14) /* ep0 + ep1in-int + .. + ep14out-int */ +#define NR_PXA_ENDPOINTS (1 + 23) /* ep0 + epA + epB + .. + epX */ /** * struct pxa_udc - udc structure -- 2.11.0