drivers/media/usb/uvc/uvc_status.c

Source file repositories/reference/linux-study-clean/drivers/media/usb/uvc/uvc_status.c

File Facts

System
Linux kernel
Corpus path
drivers/media/usb/uvc/uvc_status.c
Extension
.c
Size
9928 bytes
Lines
423
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

list_for_each_entry(entity, &(*chain)->entities, chain) {
			if (entity->id != status->bOriginator)
				continue;

			ctrl = uvc_event_entity_find_ctrl(entity,
						     status->control.bSelector);
			if (ctrl)
				return ctrl;
		}
	}

	return NULL;
}

static bool uvc_event_control(struct urb *urb,
			      const struct uvc_status *status, int len)
{
	static const char *attrs[] = { "value", "info", "failure", "min", "max" };
	struct uvc_device *dev = urb->context;
	struct uvc_video_chain *chain;
	struct uvc_control *ctrl;

	if (len < 6 || status->bEvent != 0 ||
	    status->control.bAttribute >= ARRAY_SIZE(attrs)) {
		uvc_dbg(dev, STATUS, "Invalid control status event received\n");
		return false;
	}

	uvc_dbg(dev, STATUS, "Control %u/%u %s change len %d\n",
		status->bOriginator, status->control.bSelector,
		attrs[status->control.bAttribute], len);

	/* Find the control. */
	ctrl = uvc_event_find_ctrl(dev, status, &chain);
	if (!ctrl)
		return false;

	switch (status->control.bAttribute) {
	case UVC_CTRL_VALUE_CHANGE:
		return uvc_ctrl_status_event_async(urb, chain, ctrl,
						   status->control.bValue);

	case UVC_CTRL_INFO_CHANGE:
	case UVC_CTRL_FAILURE_CHANGE:
	case UVC_CTRL_MIN_CHANGE:
	case UVC_CTRL_MAX_CHANGE:
		break;
	}

	return false;
}

static void uvc_status_complete(struct urb *urb)
{
	struct uvc_device *dev = urb->context;
	int len, ret;

	switch (urb->status) {
	case 0:
		break;

	case -ENOENT:		/* usb_kill_urb() called. */
	case -ECONNRESET:	/* usb_unlink_urb() called. */
	case -ESHUTDOWN:	/* The endpoint is being disabled. */
	case -EPROTO:		/* Device is disconnected (reported by some host controllers). */
		return;

	default:
		dev_warn(&dev->intf->dev,
			 "Non-zero status (%d) in status completion handler.\n",
			 urb->status);
		return;
	}

	len = urb->actual_length;
	if (len > 0) {
		switch (dev->status->bStatusType & 0x0f) {
		case UVC_STATUS_TYPE_CONTROL: {
			if (uvc_event_control(urb, dev->status, len))
				/* The URB will be resubmitted in work context. */
				return;
			break;
		}

		case UVC_STATUS_TYPE_STREAMING: {
			uvc_event_streaming(dev, dev->status, len);
			break;
		}

		default:

Annotation

Implementation Notes