uvcsink: Respond to control requests with proper error handling
The complete handling on the control interface is currently dead. We return with EOPNOTSUPP for the caller to know that a response to such requests is not valid. The host however may ask control interface why these control requests were not available. For this the UVC_VC_REQUEST_ERROR_CODE_CONTROL is used. As an overall exception for the control interface we just always return 0x06 as an response which is representing "not implemented". This patch is a necessary feature to properly pass the UVC Functionality Test of the USB3CV Compliance Software. Fixes: 69c17461392d ('uvcgadget: Properly implement GET_INFO control responses') Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7524>
This commit is contained in:
parent
50d2d1446f
commit
3b345568bc
@ -640,6 +640,8 @@ gst_uvc_sink_init (GstUvcSink * self)
|
||||
gst_pad_set_query_function (self->sinkpad, gst_uvc_sink_query);
|
||||
gst_pad_set_event_function (self->sinkpad, gst_uvc_sink_event);
|
||||
|
||||
self->request_error_code = REQUEST_ERROR_CODE_NO_ERROR;
|
||||
|
||||
self->cur_caps = gst_caps_new_empty ();
|
||||
}
|
||||
|
||||
@ -985,6 +987,7 @@ gst_uvc_sink_change_state (GstElement * element, GstStateChange transition)
|
||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||
gst_element_sync_state_with_parent (GST_ELEMENT (self->fakesink));
|
||||
gst_uvc_sink_remove_idle_probe (self);
|
||||
self->request_error_code = REQUEST_ERROR_CODE_NO_ERROR;
|
||||
break;
|
||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
||||
if (!gst_uvc_sink_unwatch (self))
|
||||
|
@ -17,6 +17,9 @@
|
||||
|
||||
G_BEGIN_DECLS GST_DEBUG_CATEGORY_EXTERN (uvcsink_debug);
|
||||
|
||||
#define REQUEST_ERROR_CODE_NO_ERROR 0x0
|
||||
#define REQUEST_ERROR_CODE_INVALID_REQUEST 0x6
|
||||
|
||||
#define GST_TYPE_UVCSINK (gst_uvc_sink_get_type())
|
||||
G_DECLARE_FINAL_TYPE (GstUvcSink, gst_uvc_sink, GST, UVCSINK, GstBin)
|
||||
|
||||
@ -54,6 +57,8 @@ struct _GstUvcSink
|
||||
|
||||
int control;
|
||||
|
||||
int request_error_code;
|
||||
|
||||
/* probes */
|
||||
int buffer_peer_probe_id;
|
||||
int idle_probe_id;
|
||||
|
@ -343,7 +343,7 @@ uvc_events_process_streaming (GstUvcSink * self, uint8_t req, uint8_t cs,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
uvc_events_parse_control (GstUvcSink * self, uint8_t req,
|
||||
uint8_t cs, uint8_t entity_id, uint8_t len, struct uvc_request_data *resp)
|
||||
{
|
||||
@ -357,26 +357,50 @@ uvc_events_parse_control (GstUvcSink * self, uint8_t req,
|
||||
case 0:
|
||||
GST_DEBUG_OBJECT (self, "%s",
|
||||
uvc_video_control_interface_control_selector_name (cs));
|
||||
break;
|
||||
/*
|
||||
* For ERROR_CODE_CONTROL requests we have to return not implemented so
|
||||
* bail out gracefully here to properly send control is not
|
||||
* currently implemented. (0x06) (4.2.1.2 Request Error Code Control)
|
||||
*/
|
||||
if (cs == UVC_VC_REQUEST_ERROR_CODE_CONTROL) {
|
||||
resp->data[0] = self->request_error_code;
|
||||
resp->length = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
goto error;
|
||||
|
||||
case 1:
|
||||
GST_DEBUG_OBJECT (self, "%s: %s",
|
||||
uvc_camera_terminal_control_selector_name (cs),
|
||||
uvc_request_name (req));
|
||||
break;
|
||||
goto error;
|
||||
|
||||
case 2:
|
||||
GST_DEBUG_OBJECT (self, "%s: %s",
|
||||
uvc_processing_unit_control_selector_name (cs),
|
||||
uvc_request_name (req));
|
||||
break;
|
||||
goto error;
|
||||
|
||||
default:
|
||||
GST_DEBUG_OBJECT (self,
|
||||
"Unknown entity ID (0x%02x), CS: 0x%02x, Request %s (0x%02x)",
|
||||
entity_id, cs, uvc_request_name (req), req);
|
||||
break;
|
||||
goto error;
|
||||
}
|
||||
|
||||
self->request_error_code = REQUEST_ERROR_CODE_NO_ERROR;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
||||
self->request_error_code = REQUEST_ERROR_CODE_INVALID_REQUEST;
|
||||
/*
|
||||
* Stall and don't response the control requests that are
|
||||
* actually not implemented
|
||||
*/
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -389,9 +413,8 @@ uvc_events_process_class (GstUvcSink * self,
|
||||
return -EINVAL;
|
||||
|
||||
if (interface == UVC_STRING_CONTROL_IDX) {
|
||||
uvc_events_parse_control (self, ctrl->bRequest, ctrl->wValue >> 8,
|
||||
ctrl->wIndex >> 8, ctrl->wLength, resp);
|
||||
return -EOPNOTSUPP;
|
||||
return uvc_events_parse_control (self, ctrl->bRequest,
|
||||
ctrl->wValue >> 8, ctrl->wIndex >> 8, ctrl->wLength, resp);
|
||||
} else if (interface == UVC_STRING_STREAMING_IDX) {
|
||||
return uvc_events_process_streaming (self, ctrl->bRequest,
|
||||
le16toh (ctrl->wValue) >> 8, resp);
|
||||
|
Loading…
x
Reference in New Issue
Block a user