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

📄 descriptor.c

📁 最新的libusb库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * USB descriptor handling functions for libusb * Copyright (C) 2007 Daniel Drake <dsd@gentoo.org> * Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */#include <errno.h>#include <stdlib.h>#include <string.h>#include "libusbi.h"#define DESC_HEADER_LENGTH		2#define DEVICE_DESC_LENGTH		18#define CONFIG_DESC_LENGTH		9#define INTERFACE_DESC_LENGTH		9#define ENDPOINT_DESC_LENGTH		7#define ENDPOINT_AUDIO_DESC_LENGTH	9/** @defgroup desc USB descriptors * This page details how to examine the various standard USB descriptors * for detected devices *//* set host_endian if the w values are already in host endian format, * as opposed to bus endian. */int usbi_parse_descriptor(unsigned char *source, char *descriptor, void *dest,	int host_endian){	unsigned char *sp = source, *dp = dest;	uint16_t w;	char *cp;	for (cp = descriptor; *cp; cp++) {		switch (*cp) {			case 'b':	/* 8-bit byte */				*dp++ = *sp++;				break;			case 'w':	/* 16-bit word, convert from little endian to CPU */				dp += ((unsigned long)dp & 1);	/* Align to word boundary */				if (host_endian) {					memcpy(dp, sp, 2);				} else {					w = (sp[1] << 8) | sp[0];					*((uint16_t *)dp) = w;				}				sp += 2;				dp += 2;				break;		}	}	return sp - source;}static void clear_endpoint(struct libusb_endpoint_descriptor *endpoint){	if (endpoint->extra)		free((unsigned char *) endpoint->extra);}static int parse_endpoint(struct libusb_context *ctx,	struct libusb_endpoint_descriptor *endpoint, unsigned char *buffer,	int size, int host_endian){	struct usb_descriptor_header header;	unsigned char *extra;	unsigned char *begin;	int parsed = 0;	int len;	usbi_parse_descriptor(buffer, "bb", &header, 0);	/* Everything should be fine being passed into here, but we sanity */	/*  check JIC */	if (header.bLength > size) {		usbi_err(ctx, "ran out of descriptors parsing");		return -1;	}	if (header.bDescriptorType != LIBUSB_DT_ENDPOINT) {		usbi_err(ctx, "unexpected descriptor %x (expected %x)",			header.bDescriptorType, LIBUSB_DT_ENDPOINT);		return parsed;	}	if (header.bLength >= ENDPOINT_AUDIO_DESC_LENGTH)		usbi_parse_descriptor(buffer, "bbbbwbbb", endpoint, host_endian);	else if (header.bLength >= ENDPOINT_DESC_LENGTH)		usbi_parse_descriptor(buffer, "bbbbwb", endpoint, host_endian);	buffer += header.bLength;	size -= header.bLength;	parsed += header.bLength;	/* Skip over the rest of the Class Specific or Vendor Specific */	/*  descriptors */	begin = buffer;	while (size >= DESC_HEADER_LENGTH) {		usbi_parse_descriptor(buffer, "bb", &header, 0);		if (header.bLength < 2) {			usbi_err(ctx, "invalid descriptor length %d", header.bLength);			return -1;		}		/* If we find another "proper" descriptor then we're done  */		if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||				(header.bDescriptorType == LIBUSB_DT_INTERFACE) ||				(header.bDescriptorType == LIBUSB_DT_CONFIG) ||				(header.bDescriptorType == LIBUSB_DT_DEVICE))			break;		usbi_dbg("skipping descriptor %x", header.bDescriptorType);		buffer += header.bLength;		size -= header.bLength;		parsed += header.bLength;	}	/* Copy any unknown descriptors into a storage area for drivers */	/*  to later parse */	len = (int)(buffer - begin);	if (!len) {		endpoint->extra = NULL;		endpoint->extra_length = 0;		return parsed;	}	extra = malloc(len);	endpoint->extra = extra;	if (!extra) {		endpoint->extra_length = 0;		return LIBUSB_ERROR_NO_MEM;	}	memcpy(extra, begin, len);	endpoint->extra_length = len;	return parsed;}static void clear_interface(struct libusb_interface *interface){	int i;	int j;	if (interface->altsetting) {		for (i = 0; i < interface->num_altsetting; i++) {			struct libusb_interface_descriptor *ifp =				(struct libusb_interface_descriptor *)				interface->altsetting + i;			if (ifp->extra)				free((void *) ifp->extra);			if (ifp->endpoint) {				for (j = 0; j < ifp->bNumEndpoints; j++)					clear_endpoint((struct libusb_endpoint_descriptor *)						ifp->endpoint + j);				free((void *) ifp->endpoint);			}		}		free((void *) interface->altsetting);	}	}static int parse_interface(libusb_context *ctx,	struct libusb_interface *interface, unsigned char *buffer, int size,	int host_endian){	int i;	int len;	int r;	int parsed = 0;	int tmp;	struct usb_descriptor_header header;	struct libusb_interface_descriptor *ifp;	unsigned char *begin;	interface->num_altsetting = 0;	while (size >= INTERFACE_DESC_LENGTH) {		struct libusb_interface_descriptor *altsetting =			(struct libusb_interface_descriptor *) interface->altsetting;		altsetting = realloc(altsetting,			sizeof(struct libusb_interface_descriptor) *			(interface->num_altsetting + 1));		if (!altsetting) {			r = LIBUSB_ERROR_NO_MEM;			goto err;		}		interface->altsetting = altsetting;		ifp = altsetting + interface->num_altsetting;		interface->num_altsetting++;		usbi_parse_descriptor(buffer, "bbbbbbbbb", ifp, 0);		ifp->extra = NULL;		ifp->extra_length = 0;		ifp->endpoint = NULL;		/* Skip over the interface */		buffer += ifp->bLength;		parsed += ifp->bLength;		size -= ifp->bLength;		begin = buffer;		/* Skip over any interface, class or vendor descriptors */		while (size >= DESC_HEADER_LENGTH) {			usbi_parse_descriptor(buffer, "bb", &header, 0);			if (header.bLength < 2) {				usbi_err(ctx, "invalid descriptor of length %d",					header.bLength);				r = LIBUSB_ERROR_IO;				goto err;			}			/* If we find another "proper" descriptor then we're done */			if ((header.bDescriptorType == LIBUSB_DT_INTERFACE) ||					(header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||					(header.bDescriptorType == LIBUSB_DT_CONFIG) ||					(header.bDescriptorType == LIBUSB_DT_DEVICE))				break;			buffer += header.bLength;			parsed += header.bLength;			size -= header.bLength;		}		/* Copy any unknown descriptors into a storage area for */		/*  drivers to later parse */		len = (int)(buffer - begin);		if (len) {			ifp->extra = malloc(len);			if (!ifp->extra) {				r = LIBUSB_ERROR_NO_MEM;				goto err;			}			memcpy((unsigned char *) ifp->extra, begin, len);			ifp->extra_length = len;		}		/* Did we hit an unexpected descriptor? */		usbi_parse_descriptor(buffer, "bb", &header, 0);		if ((size >= DESC_HEADER_LENGTH) &&				((header.bDescriptorType == LIBUSB_DT_CONFIG) ||				 (header.bDescriptorType == LIBUSB_DT_DEVICE)))			return parsed;		if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {			usbi_err(ctx, "too many endpoints (%d)", ifp->bNumEndpoints);			r = LIBUSB_ERROR_IO;			goto err;		}		if (ifp->bNumEndpoints > 0) {			struct libusb_endpoint_descriptor *endpoint;			tmp = ifp->bNumEndpoints * sizeof(struct libusb_endpoint_descriptor);			endpoint = malloc(tmp);			ifp->endpoint = endpoint;			if (!endpoint) {				r = LIBUSB_ERROR_NO_MEM;				goto err;			}			memset(endpoint, 0, tmp);			for (i = 0; i < ifp->bNumEndpoints; i++) {				usbi_parse_descriptor(buffer, "bb", &header, 0);				if (header.bLength > size) {					usbi_err(ctx, "ran out of descriptors parsing");					r = LIBUSB_ERROR_IO;					goto err;				}				r = parse_endpoint(ctx, endpoint + i, buffer, size,					host_endian);				if (r < 0)					goto err;				buffer += r;				parsed += r;				size -= r;			}		}		/* We check to see if it's an alternate to this one */		ifp = (struct libusb_interface_descriptor *) buffer;		if (size < LIBUSB_DT_INTERFACE_SIZE ||				ifp->bDescriptorType != LIBUSB_DT_INTERFACE ||				!ifp->bAlternateSetting)			return parsed;	}	return parsed;err:	clear_interface(interface);	return r;}static void clear_configuration(struct libusb_config_descriptor *config){	if (config->interface) {		int i;		for (i = 0; i < config->bNumInterfaces; i++)			clear_interface((struct libusb_interface *)				config->interface + i);		free((void *) config->interface);	}	if (config->extra)		free((void *) config->extra);}static int parse_configuration(struct libusb_context *ctx,	struct libusb_config_descriptor *config, unsigned char *buffer,	int host_endian){	int i;	int r;	int size;	int tmp;	struct usb_descriptor_header header;	struct libusb_interface *interface;	usbi_parse_descriptor(buffer, "bbwbbbbb", config, host_endian);	size = config->wTotalLength;	if (config->bNumInterfaces > USB_MAXINTERFACES) {		usbi_err(ctx, "too many interfaces (%d)", config->bNumInterfaces);		return LIBUSB_ERROR_IO;	}	tmp = config->bNumInterfaces * sizeof(struct libusb_interface);	interface = malloc(tmp);	config->interface = interface;	if (!config->interface)		return LIBUSB_ERROR_NO_MEM;	memset(interface, 0, tmp);	buffer += config->bLength;	size -= config->bLength;	config->extra = NULL;	config->extra_length = 0;

⌨️ 快捷键说明

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