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

📄 linux_usbfs.c

📁 最新的libusb库
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (*config == -1)		*config = 0;	return 0;}static int op_set_configuration(struct libusb_device_handle *handle, int config){	struct linux_device_priv *priv = __device_priv(handle->dev);	int fd = __device_handle_priv(handle)->fd;	int r = ioctl(fd, IOCTL_USBFS_SETCONFIG, &config);	if (r) {		if (errno == EINVAL)			return LIBUSB_ERROR_NOT_FOUND;		else if (errno == EBUSY)			return LIBUSB_ERROR_BUSY;		else if (errno == ENODEV)			return LIBUSB_ERROR_NO_DEVICE;		usbi_err(HANDLE_CTX(handle), "failed, error %d errno %d", r, errno);		return LIBUSB_ERROR_OTHER;	}	if (!sysfs_has_descriptors) {		/* update our cached active config descriptor */		if (config == -1) {			if (priv->config_descriptor) {				free(priv->config_descriptor);				priv->config_descriptor = NULL;			}		} else {			r = cache_active_config(handle->dev, fd, config);			if (r < 0)				usbi_warn(HANDLE_CTX(handle),					"failed to update cached config descriptor, error %d", r);		}	}	return 0;}static int op_claim_interface(struct libusb_device_handle *handle, int iface){	int fd = __device_handle_priv(handle)->fd;	int r = ioctl(fd, IOCTL_USBFS_CLAIMINTF, &iface);	if (r) {		if (errno == ENOENT)			return LIBUSB_ERROR_NOT_FOUND;		else if (errno == EBUSY)			return LIBUSB_ERROR_BUSY;		else if (errno == ENODEV)			return LIBUSB_ERROR_NO_DEVICE;		usbi_err(HANDLE_CTX(handle),			"claim interface failed, error %d errno %d", r, errno);		return LIBUSB_ERROR_OTHER;	}	return 0;}static int op_release_interface(struct libusb_device_handle *handle, int iface){	int fd = __device_handle_priv(handle)->fd;	int r = ioctl(fd, IOCTL_USBFS_RELEASEINTF, &iface);	if (r) {		if (errno == ENODEV)			return LIBUSB_ERROR_NO_DEVICE;		usbi_err(HANDLE_CTX(handle),			"release interface failed, error %d errno %d", r, errno);		return LIBUSB_ERROR_OTHER;	}	return 0;}static int op_set_interface(struct libusb_device_handle *handle, int iface,	int altsetting){	int fd = __device_handle_priv(handle)->fd;	struct usbfs_setinterface setintf;	int r;	setintf.interface = iface;	setintf.altsetting = altsetting;	r = ioctl(fd, IOCTL_USBFS_SETINTF, &setintf);	if (r) {		if (errno == EINVAL)			return LIBUSB_ERROR_NOT_FOUND;		else if (errno == ENODEV)			return LIBUSB_ERROR_NO_DEVICE;		usbi_err(HANDLE_CTX(handle),			"setintf failed error %d errno %d", r, errno);		return LIBUSB_ERROR_OTHER;	}	return 0;}static int op_clear_halt(struct libusb_device_handle *handle,	unsigned char endpoint){	int fd = __device_handle_priv(handle)->fd;	unsigned int _endpoint = endpoint;	int r = ioctl(fd, IOCTL_USBFS_CLEAR_HALT, &_endpoint);	if (r) {		if (errno == ENOENT)			return LIBUSB_ERROR_NOT_FOUND;		else if (errno == ENODEV)			return LIBUSB_ERROR_NO_DEVICE;		usbi_err(HANDLE_CTX(handle),			"clear_halt failed error %d errno %d", r, errno);		return LIBUSB_ERROR_OTHER;	}	return 0;}static int op_reset_device(struct libusb_device_handle *handle){	int fd = __device_handle_priv(handle)->fd;	int r = ioctl(fd, IOCTL_USBFS_RESET, NULL);	if (r) {		if (errno == ENODEV)			return LIBUSB_ERROR_NOT_FOUND;		usbi_err(HANDLE_CTX(handle),			"reset failed error %d errno %d", r, errno);		return LIBUSB_ERROR_OTHER;	}	return 0;}static int op_kernel_driver_active(struct libusb_device_handle *handle,	int interface){	int fd = __device_handle_priv(handle)->fd;	struct usbfs_getdriver getdrv;	int r;	getdrv.interface = interface;	r = ioctl(fd, IOCTL_USBFS_GETDRIVER, &getdrv);	if (r) {		if (errno == ENODATA)			return 0;		else if (errno == ENODEV)			return LIBUSB_ERROR_NO_DEVICE;		usbi_err(HANDLE_CTX(handle),			"get driver failed error %d errno %d", r, errno);		return LIBUSB_ERROR_OTHER;	}	return 1;}static int op_detach_kernel_driver(struct libusb_device_handle *handle,	int interface){	int fd = __device_handle_priv(handle)->fd;	struct usbfs_ioctl command;	int r;	command.ifno = interface;	command.ioctl_code = IOCTL_USBFS_DISCONNECT;	command.data = NULL;	r = ioctl(fd, IOCTL_USBFS_IOCTL, &command);	if (r) {		if (errno == ENODATA)			return LIBUSB_ERROR_NOT_FOUND;		else if (errno == EINVAL)			return LIBUSB_ERROR_INVALID_PARAM;		else if (errno == ENODEV)			return LIBUSB_ERROR_NO_DEVICE;		usbi_err(HANDLE_CTX(handle),			"detach failed error %d errno %d", r, errno);		return LIBUSB_ERROR_OTHER;	}	return 0;}static void op_destroy_device(struct libusb_device *dev){	struct linux_device_priv *priv = __device_priv(dev);	if (!sysfs_has_descriptors) {		if (priv->dev_descriptor)			free(priv->dev_descriptor);		if (priv->config_descriptor)			free(priv->config_descriptor);	}	if (priv->sysfs_dir)		free(priv->sysfs_dir);}static void free_iso_urbs(struct linux_transfer_priv *tpriv){	int i;	for (i = 0; i < tpriv->num_urbs; i++) {		struct usbfs_urb *urb = tpriv->iso_urbs[i];		if (!urb)			break;		free(urb);	}	free(tpriv->iso_urbs);}static int submit_bulk_transfer(struct usbi_transfer *itransfer,	unsigned char urb_type){	struct libusb_transfer *transfer =		__USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);	struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);	struct linux_device_handle_priv *dpriv =		__device_handle_priv(transfer->dev_handle);	struct usbfs_urb *urbs;	int r;	int i;	size_t alloc_size;	/* usbfs places a 16kb limit on bulk URBs. we divide up larger requests	 * into smaller units to meet such restriction, then fire off all the	 * units at once. it would be simpler if we just fired one unit at a time,	 * but there is a big performance gain through doing it this way. */	int num_urbs = transfer->length / MAX_BULK_BUFFER_LENGTH;	int last_urb_partial = 0;	if ((transfer->length % MAX_BULK_BUFFER_LENGTH) > 0) {		last_urb_partial = 1;		num_urbs++;	}	usbi_dbg("need %d urbs for new transfer with length %d", num_urbs,		transfer->length);	alloc_size = num_urbs * sizeof(struct usbfs_urb);	urbs = malloc(alloc_size);	if (!urbs)		return LIBUSB_ERROR_NO_MEM;	memset(urbs, 0, alloc_size);	tpriv->urbs = urbs;	tpriv->num_urbs = num_urbs;	tpriv->awaiting_discard = 0;	tpriv->awaiting_reap = 0;	tpriv->reap_action = NORMAL;	for (i = 0; i < num_urbs; i++) {		struct usbfs_urb *urb = &urbs[i];		urb->usercontext = itransfer;		urb->type = urb_type;		urb->endpoint = transfer->endpoint;		urb->buffer = transfer->buffer + (i * MAX_BULK_BUFFER_LENGTH);		if (i == num_urbs - 1 && last_urb_partial)			urb->buffer_length = transfer->length % MAX_BULK_BUFFER_LENGTH;		else			urb->buffer_length = MAX_BULK_BUFFER_LENGTH;		r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urb);		if (r < 0) {			int j;			if (errno == ENODEV) {				r = LIBUSB_ERROR_NO_DEVICE;			} else {				usbi_err(TRANSFER_CTX(transfer),					"submiturb failed error %d errno=%d", r, errno);				r = LIBUSB_ERROR_IO;			}				/* if the first URB submission fails, we can simply free up and			 * return failure immediately. */			if (i == 0) {				usbi_dbg("first URB failed, easy peasy");				free(urbs);				return r;			}			/* if it's not the first URB that failed, the situation is a bit			 * tricky. we must discard all previous URBs. there are			 * complications:			 *  - discarding is asynchronous - discarded urbs will be reaped			 *    later. the user must not have freed the transfer when the			 *    discarded URBs are reaped, otherwise libusb will be using			 *    freed memory.			 *  - the earlier URBs may have completed successfully and we do			 *    not want to throw away any data.			 * so, in this case we discard all the previous URBs BUT we report			 * that the transfer was submitted successfully. then later when			 * the final discard completes we can report error to the user.			 */			tpriv->reap_action = SUBMIT_FAILED;			for (j = 0; j < i; j++) {				int tmp = ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, &urbs[j]);				if (tmp == 0)					tpriv->awaiting_discard++;				else if (errno == EINVAL)					tpriv->awaiting_reap++;				else					usbi_warn(TRANSFER_CTX(transfer),						"unrecognised discard return %d", tmp);			}			usbi_dbg("reporting successful submission but waiting for %d "				"discards and %d reaps before reporting error",				tpriv->awaiting_discard, tpriv->awaiting_reap);			return 0;		}	}	return 0;}static int submit_iso_transfer(struct usbi_transfer *itransfer){	struct libusb_transfer *transfer =		__USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);	struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);	struct linux_device_handle_priv *dpriv =		__device_handle_priv(transfer->dev_handle);	struct usbfs_urb **urbs;	size_t alloc_size;	int num_packets = transfer->num_iso_packets;	int i;	int this_urb_len = 0;	int num_urbs = 1;	int packet_offset = 0;	unsigned int packet_len;	unsigned char *urb_buffer = transfer->buffer;	/* usbfs places a 32kb limit on iso URBs. we divide up larger requests	 * into smaller units to meet such restriction, then fire off all the	 * units at once. it would be simpler if we just fired one unit at a time,	 * but there is a big performance gain through doing it this way. */	/* calculate how many URBs we need */	for (i = 0; i < num_packets; i++) {		int space_remaining = MAX_ISO_BUFFER_LENGTH - this_urb_len;		packet_len = transfer->iso_packet_desc[i].length;		if (packet_len > space_remaining) {			num_urbs++;			this_urb_len = packet_len;		} else {			this_urb_len += packet_len;		}	}	usbi_dbg("need %d 32k URBs for transfer", num_urbs);	alloc_size = num_urbs * sizeof(*urbs);	urbs = malloc(alloc_size);	if (!urbs)		return LIBUSB_ERROR_NO_MEM;	memset(urbs, 0, alloc_size);	tpriv->iso_urbs = urbs;	tpriv->num_urbs = num_urbs;	tpriv->awaiting_discard = 0;	tpriv->awaiting_reap = 0;	tpriv->reap_action = NORMAL;	tpriv->iso_packet_offset = 0;	/* allocate + initialize each URB with the correct number of packets */	for (i = 0; i < num_urbs; i++) {		struct usbfs_urb *urb;		int space_remaining_in_urb = MAX_ISO_BUFFER_LENGTH;		int urb_packet_offset = 0;		unsigned char *urb_buffer_orig = urb_buffer;		int j;		int k;		/* swallow up all the packets we can fit into this URB */		while (packet_offset < transfer->num_iso_packets) {			packet_len = transfer->iso_packet_desc[packet_offset].length;			if (packet_len <= space_remaining_in_urb) {				/* throw it in */				urb_packet_offset++;				packet_offset++;				space_remaining_in_urb -= packet_len;				urb_buffer += packet_len;			} else {				/* it can't fit, save it for the next URB */				break;			}		}		alloc_size = sizeof(*urb)			+ (urb_packet_offset * sizeof(struct usbfs_iso_packet_desc));		urb = malloc(alloc_size);		if (!urb) {			free_iso_urbs(tpriv);			return LIBUSB_ERROR_NO_MEM;		}		memset(urb, 0, alloc_size);		urbs[i] = urb;		/* populate packet lengths */		for (j = 0, k = packet_offset - urb_packet_offset;				k < packet_offset; k++, j++) {			packet_len = transfer->iso_packet_desc[k].length;			urb->iso_frame_desc[j].length = packet_len;		}		urb->usercontext = itransfer;		urb->type = USBFS_URB_TYPE_ISO;		/* FIXME: interface for non-ASAP data? */		urb->flags = USBFS_URB_ISO_ASAP;		urb->endpoint = transfer->endpoint;		urb->number_of_packets = urb_packet_offset;		urb->buffer = urb_buffer_orig;	}	/* submit URBs */	for (i = 0; i < num_urbs; i++) {		int r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urbs[i]);		if (r < 0) {			int j;			if (errno == ENODEV) {				r = LIBUSB_ERROR_NO_DEVICE;			} else {				usbi_err(TRANSFER_CTX(transfer),					"submiturb failed error %d errno=%d", r, errno);				r = LIBUSB_ERROR_IO;			}			/* if the first URB submission fails, we can simply free up and			 * return failure immediately. */			if (i == 0) {				usbi_dbg("first URB failed, easy peasy");				free_iso_urbs(tpriv);				return r;			}			/* if it's not the first URB that failed, the situation is a bit			 * tricky. we must discard all previous URBs. there are			 * complications:			 *  - discarding is asynchronous - discarded urbs will be reaped			 *    later. the user must not have freed the transfer when the			 *    discarded URBs are reaped, otherwise libusb will be using			 *    freed memory.			 *  - the earlier URBs may have completed successfully and we do			 *    not want to throw away any data.			 * so, in this case we discard all the previous URBs BUT we report			 * that the transfer was submitted successfully. then later when			 * the final discard completes we can report error to the user.			 */			tpriv->reap_action = SUBMIT_FAILED;			for (j = 0; j < i; j++) {				int tmp = ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, urbs[j]);				if (tmp == 0)					tpriv->awaiting_discard++;				else if (errno == EINVAL)					tpriv->awaiting_reap++;				else					usbi_warn(TRANSFER_CTX(transfer),						"unrecognised discard return %d", tmp);			}			usbi_dbg("reporting successful submission but waiting for %d "				"discards and %d reaps before reporting error",				tpriv->awaiting_discard, tpriv->awaiting_reap);			return 0;		}	}	return 0;}static int submit_control_transfer(struct usbi_transfer *itransfer){	struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);	struct libusb_transfer *transfer =		__USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);	struct linux_device_handle_priv *dpriv =		__device_handle_priv(transfer->dev_handle);	struct usbfs_urb *urb;	int r;	if (transfer->length - LIBUSB_CONTROL_SETUP_SIZE > MAX_CTRL_BUFFER_LENGTH)		return LIBUSB_ERROR_INVALID_PARAM;	urb = malloc(sizeof(struct usbfs_urb));	if (!urb)		return LIBUSB_ERROR_NO_MEM;	memset(urb, 0, sizeof(struct usbfs_urb));	tpriv->urbs = urb;	tpriv->reap_action = NORMAL;	urb->usercontext = itransfer;	urb->type = USBFS_URB_TYPE_CONTROL;	urb->endpoint = transfer->endpoint;	urb->buffer = transfer->buffer;	urb->buffer_length = transfer->length;	r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urb);	if (r < 0) {		free(urb);		if (errno == ENODEV)			return LIBUSB_ERROR_NO_DEVICE;

⌨️ 快捷键说明

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