From b444aeea9de2d8e507f2301f9fed1eb64dcc7e1e Mon Sep 17 00:00:00 2001
From: Petr Cvek <petr.cvek@tul.cz>
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(-)
@@ -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;
@@ -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,
@@ -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;
@@ -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");
@@ -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;
@@ -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),
}
};
@@ -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