diff options
| -rw-r--r-- | uvc-gadget.c | 82 | 
1 files changed, 33 insertions, 49 deletions
| diff --git a/uvc-gadget.c b/uvc-gadget.c index 0ad0923..b1c4eeb 100644 --- a/uvc-gadget.c +++ b/uvc-gadget.c @@ -252,34 +252,40 @@ static const struct uvc_format_info uvc_formats[] = {  static void  uvc_fill_streaming_control(struct uvc_device *dev,  			   struct uvc_streaming_control *ctrl, -			   int iframe, int iformat) +			   int iformat, int iframe, unsigned int ival)  {  	const struct uvc_format_info *format;  	const struct uvc_frame_info *frame; +	const unsigned int *interval;  	unsigned int nframes; -	if (iformat < 0) -		iformat = ARRAY_SIZE(uvc_formats) + iformat; -	if (iformat < 0 || iformat >= (int)ARRAY_SIZE(uvc_formats)) -		return; -	format = &uvc_formats[iformat]; +	/* +	 * Restrict the iformat, iframe and ival to valid values. Negative +	 * values for iformat or iframe will result in the maximum valid value +	 * being selected. +	 */ +        iformat = clamp((unsigned int)iformat, 1U, +                        (unsigned int)ARRAY_SIZE(uvc_formats)); +	format = &uvc_formats[iformat-1];  	nframes = 0;  	while (format->frames[nframes].width != 0)  		++nframes; -	if (iframe < 0) -		iframe = nframes + iframe; -	if (iframe < 0 || iframe >= (int)nframes) -		return; -	frame = &format->frames[iframe]; +	iframe = clamp((unsigned int)iframe, 1U, nframes); +	frame = &format->frames[iframe-1]; + +	interval = frame->intervals; +	while (interval[0] < ival && interval[1]) +		++interval;  	memset(ctrl, 0, sizeof *ctrl);  	ctrl->bmHint = 1; -	ctrl->bFormatIndex = iformat + 1; -	ctrl->bFrameIndex = iframe + 1; -	ctrl->dwFrameInterval = frame->intervals[0]; +	ctrl->bFormatIndex = iformat; +	ctrl->bFrameIndex = iframe ; +	ctrl->dwFrameInterval = *interval; +  	switch (format->fcc) {  	case V4L2_PIX_FMT_YUYV:  		ctrl->dwMaxVideoFrameSize = frame->width * frame->height * 2; @@ -288,6 +294,7 @@ uvc_fill_streaming_control(struct uvc_device *dev,  		ctrl->dwMaxVideoFrameSize = dev->imgsize;  		break;  	} +  	ctrl->dwMaxPayloadTransferSize = 512;	/* TODO this should be filled by the driver. */  	ctrl->bmFramingInfo = 3;  	ctrl->bPreferedVersion = 1; @@ -343,8 +350,8 @@ uvc_events_process_streaming(struct uvc_device *dev, uint8_t req, uint8_t cs,  	case UVC_GET_MIN:  	case UVC_GET_MAX:  	case UVC_GET_DEF: -		uvc_fill_streaming_control(dev, ctrl, req == UVC_GET_MAX ? -1 : 0, -					   req == UVC_GET_MAX ? -1 : 0); +		uvc_fill_streaming_control(dev, ctrl, req == UVC_GET_MAX ? -1 : 1, +					   req == UVC_GET_MAX ? -1 : 1, 0);  		break;  	case UVC_GET_RES: @@ -414,11 +421,6 @@ uvc_events_process_data(struct uvc_device *dev, struct uvc_request_data *data)  {  	struct uvc_streaming_control *target;  	struct uvc_streaming_control *ctrl; -	const struct uvc_format_info *format; -	const struct uvc_frame_info *frame; -	const unsigned int *interval; -	unsigned int iformat, iframe; -	unsigned int nframes;  	switch (dev->control) {  	case UVC_VS_PROBE_CONTROL: @@ -437,36 +439,17 @@ uvc_events_process_data(struct uvc_device *dev, struct uvc_request_data *data)  	}  	ctrl = (struct uvc_streaming_control *)&data->data; -	iformat = clamp((unsigned int)ctrl->bFormatIndex, 1U, -			(unsigned int)ARRAY_SIZE(uvc_formats)); -	format = &uvc_formats[iformat-1]; - -	nframes = 0; -	while (format->frames[nframes].width != 0) -		++nframes; -	iframe = clamp((unsigned int)ctrl->bFrameIndex, 1U, nframes); -	frame = &format->frames[iframe-1]; -	interval = frame->intervals; +	uvc_fill_streaming_control(dev, target, ctrl->bFormatIndex, +				   ctrl->bFrameIndex, ctrl->dwFrameInterval); -	while (interval[0] < ctrl->dwFrameInterval && interval[1]) -		++interval; +	if (dev->control == UVC_VS_COMMIT_CONTROL) { +		const struct uvc_format_info *format; +		const struct uvc_frame_info *frame; -	target->bFormatIndex = iformat; -	target->bFrameIndex = iframe; -	switch (format->fcc) { -	case V4L2_PIX_FMT_YUYV: -		target->dwMaxVideoFrameSize = frame->width * frame->height * 2; -		break; -	case V4L2_PIX_FMT_MJPEG: -		if (dev->imgsize == 0) -			printf("WARNING: MJPEG requested and no image loaded.\n"); -		target->dwMaxVideoFrameSize = dev->imgsize; -		break; -	} -	target->dwFrameInterval = *interval; +		format = &uvc_formats[target->bFormatIndex-1]; +		frame = &format->frames[target->bFrameIndex-1]; -	if (dev->control == UVC_VS_COMMIT_CONTROL) {  		dev->fcc = format->fcc;  		dev->width = frame->width;  		dev->height = frame->height; @@ -531,8 +514,9 @@ uvc_events_init(struct uvc_device *dev)  {  	struct v4l2_event_subscription sub; -	uvc_fill_streaming_control(dev, &dev->probe, 0, 0); -	uvc_fill_streaming_control(dev, &dev->commit, 0, 0); +	/* Default to the minimum values. */ +	uvc_fill_streaming_control(dev, &dev->probe, 1, 1, 0); +	uvc_fill_streaming_control(dev, &dev->commit, 1, 1, 0);  	if (dev->bulk) {  		/* FIXME Crude hack, must be negotiated with the driver. */ | 
