⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uvc_driver.c

📁 LINUXvideopPREVIEW, LINUX下面打开图像的工具源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	struct usb_interface *intf = streaming->intf;	struct usb_host_interface *alts = &intf->altsetting[0];	unsigned char *_buffer, *buffer = alts->extra;	int _buflen, buflen = alts->extralen;	unsigned int nformats = 0, nframes = 0, nintervals = 0;	unsigned int size, i, n, p;	__u32 *interval;	__u16 psize;	int ret;	/* Skip the standard interface descriptors. */	while (buflen > 2 && buffer[1] != USB_DT_CS_INTERFACE) {		buflen -= buffer[0];		buffer += buffer[0];	}	if (buflen <= 2)		return -EINVAL;	/* Parse the header descriptor. */	if (buffer[2] == VS_OUTPUT_HEADER) {		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "			"%d OUTPUT HEADER descriptor is not supported.\n",			dev->udev->devnum, alts->desc.bInterfaceNumber);		return -EINVAL;	}	else if (buffer[2] == VS_INPUT_HEADER) {		p = buflen >= 5 ? buffer[3] : 0;		n = buflen >= 12 ? buffer[12] : 0;		if (buflen < 13 + p*n || buffer[2] != VS_INPUT_HEADER) {			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "				"interface %d INPUT HEADER descriptor is "				"invalid.\n", dev->udev->devnum,				alts->desc.bInterfaceNumber);			return -EINVAL;		}		streaming->input.bNumFormats = p;		streaming->input.bEndpointAddress = buffer[6];		streaming->input.bmInfo = buffer[7];		streaming->input.bTerminalLink = buffer[8];		streaming->input.bStillCaptureMethod = buffer[9];		streaming->input.bTriggerSupport = buffer[10];		streaming->input.bTriggerUsage = buffer[11];		streaming->input.bControlSize = n;		streaming->input.bmaControls = kmalloc(p*n, GFP_KERNEL);		if (streaming->input.bmaControls == NULL)			return -ENOMEM;		memcpy(streaming->input.bmaControls, &buffer[13], p*n);	}	else {		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "			"%d HEADER descriptor not found.\n", dev->udev->devnum,			alts->desc.bInterfaceNumber);		return -EINVAL;	}	buflen -= buffer[0];	buffer += buffer[0];	_buffer = buffer;	_buflen = buflen;	/* Count the format and frame descriptors. */	while (_buflen > 2) {		switch (_buffer[2]) {		case VS_FORMAT_UNCOMPRESSED:		case VS_FORMAT_MJPEG:			nformats++;			break;		case VS_FORMAT_MPEG2TS:		case VS_FORMAT_DV:		case VS_FORMAT_FRAME_BASED:		case VS_FORMAT_STREAM_BASED:			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "				"interface %d FORMAT %u is not supported.\n",				dev->udev->devnum,				alts->desc.bInterfaceNumber, _buffer[2]);			break;		case VS_FRAME_UNCOMPRESSED:		case VS_FRAME_MJPEG:			nframes++;			if (_buflen > 25)				nintervals += _buffer[25] ? _buffer[25] : 3;			break;		case VS_FRAME_FRAME_BASED:			nframes++;			if (_buflen > 21)				nintervals += _buffer[21] ? _buffer[21] : 3;			break;		}		_buflen -= _buffer[0];		_buffer += _buffer[0];	}	if (nformats == 0) {		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "			"%d has no supported formats defined.\n",			dev->udev->devnum, alts->desc.bInterfaceNumber);		return -EINVAL;	}	size = nformats * sizeof *format + nframes * sizeof *frame	     + nintervals * sizeof *interval;	format = kzalloc(size, GFP_KERNEL);	if (format == NULL)		return -ENOMEM;	frame = (struct uvc_frame*)&format[nformats];	interval = (__u32*)&frame[nframes];	streaming->format = format;	streaming->nformats = nformats;	/* Parse the format descriptors. */	while (buflen > 2) {		switch (buffer[2]) {		case VS_FORMAT_UNCOMPRESSED:		case VS_FORMAT_MJPEG:			format->frame = frame;			ret = uvc_parse_format(dev, streaming, format,				&interval, buffer, buflen);			if (ret < 0)				return ret;			frame += format->nframes;			format++;			buflen -= ret;			buffer += ret;			continue;		default:			break;		}		buflen -= buffer[0];		buffer += buffer[0];	}	/* Parse the alternate settings to find the maximum bandwidth. */	for (i = 0; i < intf->num_altsetting; ++i) {		struct usb_host_endpoint *ep;		alts = &intf->altsetting[i];		ep = uvc_find_endpoint(alts,				streaming->input.bEndpointAddress);		if (ep == NULL)			continue;		psize = le16_to_cpu(ep->desc.wMaxPacketSize);		psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));		if (psize > streaming->maxpsize)			streaming->maxpsize = psize;	}	return 0;}__u8	bProcessingUnit;__u8	bExtensionUnit;__u8	bInputTerminal;__u8	bControlSelectorUnit;__u8	bExtUnitId;static int uvc_parse_control(struct uvc_device *dev){	struct usb_device *udev = dev->udev;	struct uvc_streaming *streaming;	struct uvc_entity *unit, *term;	struct usb_interface *intf;	struct usb_host_interface *alts = dev->intf->cur_altsetting;	unsigned char *buffer = alts->extra;	int buflen = alts->extralen;	unsigned int i, n, p;	__u16 type;	/* Parse the default alternate setting only, as the UVC specification	 * defines a single alternate setting, the default alternate setting	 * zero.	 */	while (buflen > 2) {		switch (buffer[2]) {		case VC_HEADER:			n = buflen >= 12 ? buffer[11] : 0;			if (buflen < 12 || buflen < 12 + n) {				uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "				       "interface %d HEADER error\n", udev->devnum,				       dev->intf->cur_altsetting->desc.bInterfaceNumber);				return -EINVAL;			}			dev->uvc_version = le16_to_cpup((__le16*)&buffer[3]);			dev->clock_frequency = le32_to_cpup((__le32*)&buffer[7]);			/* Parse all USB Video Streaming interfaces. */			for (i = 0; i < n; ++i) {				intf = usb_ifnum_to_if(udev, buffer[12+i]);				if (intf == NULL) {					uvc_trace(UVC_TRACE_DESCR, "device %d "						"interface %d doesn't exists\n",						udev->devnum, i);					continue;				}				if (usb_interface_claimed(intf)) {					uvc_trace(UVC_TRACE_DESCR, "device %d "						"interface %d is already claimed\n",						udev->devnum, i);					continue;				}				usb_driver_claim_interface(&uvc_driver.driver, intf, (void*)-1);				streaming = kzalloc(sizeof *streaming, GFP_KERNEL);				if (streaming == NULL)					continue;				mutex_init(&streaming->mutex);				streaming->intf = intf; //usb_get_intf(intf);  //[wlq]				streaming->intfnum =					intf->cur_altsetting->desc.bInterfaceNumber;				if (uvc_parse_streaming(dev, streaming) < 0) {				//	usb_put_intf(intf); // [wlq]					kfree(streaming);					continue;				}				list_add_tail(&streaming->list, &dev->streaming);			}			break;		case VC_INPUT_TERMINAL:			if (buflen < 8) {				uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "				       "interface %d INPUT_TERMINAL error\n", udev->devnum,				       dev->intf->cur_altsetting->desc.bInterfaceNumber);				return -EINVAL;			}			/* Make sure the terminal type MSB is not null, otherwise it could be			 * confused with a unit.			 */			type = le16_to_cpup((__le16*)&buffer[4]);			if ((type & 0xff00) == 0) {				uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "				       "interface %d INPUT_TERMINAL %d has invalid "				       "type 0x%04x, skipping\n", udev->devnum,				       dev->intf->cur_altsetting->desc.bInterfaceNumber,				       buffer[3], type);				continue;			}			n = 0;			if (type == ITT_CAMERA) {				if (buflen < 15 || buflen < 15 + buffer[14]) {					uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "					       "interface %d INPUT_TERMINAL error\n", udev->devnum,					       dev->intf->cur_altsetting->desc.bInterfaceNumber);					return -EINVAL;				}				n = buffer[14];			}			term = kzalloc(sizeof *term + n, GFP_KERNEL);			if (term == NULL)				return -ENOMEM;			term->id = buffer[3];			term->type = type;			if (term->type == ITT_CAMERA) {				term->camera.bControlSize = n;				term->camera.bmControls = (__u8*)term + sizeof *term;				term->camera.wObjectiveFocalLengthMin = le16_to_cpup((__le16*)&buffer[8]);				term->camera.wObjectiveFocalLengthMax = le16_to_cpup((__le16*)&buffer[10]);				term->camera.wOcularFocalLength = le16_to_cpup((__le16*)&buffer[12]);				memcpy(term->camera.bmControls, &buffer[15], n);			}			if (buffer[7] != 0)				usb_string(udev, buffer[7], term->name, sizeof term->name);			else if (term->type == ITT_CAMERA)				sprintf(term->name, "Camera %u", buffer[3]);			else				sprintf(term->name, "Input %u", buffer[3]);			list_add_tail(&term->list, &dev->entities);        	uvc_trace(UVC_TRACE_CALLS, "[wlq-uVc] vmuvc_parse_control, Found Input Terminal.\n");			bInputTerminal = 1; //[wlq-uVc]			break;		case VC_OUTPUT_TERMINAL:			if (buflen < 9) {				uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "				       "interface %d OUTPUT_TERMINAL error\n", udev->devnum,				       dev->intf->cur_altsetting->desc.bInterfaceNumber);				return -EINVAL;			}			/* Make sure the terminal type MSB is not null, otherwise it could be			 * confused with a unit.			 */			type = le16_to_cpup((__le16*)&buffer[4]);			if ((type & 0xff00) == 0) {				uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "				       "interface %d OUTPUT_TERMINAL %d has invalid "				       "type 0x%04x, skipping\n", udev->devnum,				       dev->intf->cur_altsetting->desc.bInterfaceNumber,				       buffer[3], type);				continue;			}			term = kzalloc(sizeof *term, GFP_KERNEL);			if (term == NULL)				return -ENOMEM;			term->id = buffer[3];			term->type = type;			term->output.bSourceID = buffer[7];			if (buffer[8] != 0)				usb_string(udev, buffer[8], term->name, sizeof term->name);			else				sprintf(term->name, "Output %u", buffer[3]);			list_add_tail(&term->list, &dev->entities);			break;		case VC_SELECTOR_UNIT:			p = buflen >= 5 ? buffer[4] : 0;			if (buflen < 5 || buflen < 6 + p) {				uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "				       "interface %d SELECTOR_UNIT error\n", udev->devnum,				       dev->intf->cur_altsetting->desc.bInterfaceNumber);				return -EINVAL;			}			unit = kzalloc(sizeof *unit + p, GFP_KERNEL);			if (unit == NULL)				return -ENOMEM;			unit->id = buffer[3];			unit->type = buffer[2];			unit->selector.bNrInPins = buffer[5];			unit->selector.baSourceID = (__u8*)unit + sizeof *unit;			memcpy(unit->selector.baSourceID, &buffer[5], p);			if (buffer[5+p] != 0)				usb_string(udev, buffer[5+p], unit->name, sizeof unit->name);			else				sprintf(unit->name, "Selector %u", buffer[3]);			list_add_tail(&unit->list, &dev->entities);        	uvc_trace(UVC_TRACE_CALLS, "[wlq-uVc] vmuvc_parse_control, Found Control Selector Unit.\n");			bControlSelectorUnit = 1; // [wlq-uVc]			break;		case VC_PROCESSING_UNIT:			n = buflen >= 8 ? buffer[7] : 0;			if (buflen < 8 + n) {				uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "				       "interface %d PROCESSING_UNIT error\n", udev->devnum,				       dev->intf->cur_altsetting->desc.bInterfaceNumber);				return -EINVAL;			}			unit = kzalloc(sizeof *unit + n, GFP_KERNEL);			if (unit == NULL)				return -ENOMEM;			unit->id = buffer[3];			unit->type = buffer[2];			unit->processing.bSourceID = buffer[4];			unit->processing.wMaxMultiplier = le16_to_cpup((__le16*)&buffer[5]);			unit->processing.bControlSize = buffer[7];			unit->processing.bmControls = (__u8*)unit + sizeof *unit;			memcpy(unit->processing.bmControls, &buffer[8], n);			unit->processing.bmVideoStandards = buffer[9+n];			if (buffer[8+n] != 0)				usb_string(udev, buffer[8+n], unit->name, sizeof unit->name);			else				sprintf(unit->name, "Processing %u", buffer[3]);			list_add_tail(&unit->list, &dev->entities);        	uvc_trace(UVC_TRACE_CALLS, "[wlq-uVc] vmuvc_parse_control, Found Processing Unit.\n");			bProcessingUnit = 1; //[wlq-uVc]			break;		case VC_EXTENSION_UNIT:			p = buflen >= 22 ? buffer[21] : 0;			n = buflen >= 24 + p ? buffer[22+p] : 0;			if (buflen < 24 + p + n) {				uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "				       "interface %d EXTENSION_UNIT error\n", udev->devnum,				       dev->intf->cur_altsetting->desc.bInterfaceNumber);				return -EINVAL;			}			unit = kzalloc(sizeof *unit + p + n, GFP_KERNEL);			if (unit == NULL)				return -ENOMEM;			bExtUnitId = unit->id = buffer[3];			unit->type = buffer[2];			memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);			unit->extension.bNumControls = buffer[20];			unit->extension.bNrInPins = le16_to_cpup((__le16*)&buffer[21]);			unit->extension.baSourceID = (__u8*)unit + sizeof *unit;			memcpy(unit->extension.baSourceID, &buffer[22], p);			unit->extension.bControlSize = buffer[22+p];			unit->extension.bmControls = (__u8*)unit + sizeof *unit + p;			memcpy(unit->extension.bmControls, &buffer[23+p], n);			if (buffer[23+p+n] != 0)				usb_string(udev, buffer[23+p+n], unit->name, sizeof unit->name);			else				sprintf(unit->name, "Extension %u", buffer[3]);			list_add_tail(&unit->list, &dev->entities);        	uvc_trace(UVC_TRACE_CALLS, "[wlq-uVc] vmuvc_parse_control, Found Extension Unit.\n");			bExtensionUnit = 1; //[wlq-uVc]			break;		default:			uvc_trace(UVC_TRACE_DESCR, "Found an unknown CS_INTERFACE "				"descriptor (%u)\n", buffer[2]);			break;		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -