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

📄 stub_driver.c

📁 linux virtual usb host source
💻 C
字号:
/* * Copyright (C) 2005-2007 Takahiro Hirofuchi */#include "usbip.h"static const char *usbip_stub_driver_name = "usbip";struct usbip_stub_driver *stub_driver;static struct sysfs_driver *open_sysfs_stub_driver(void){	int ret;	char sysfs_mntpath[SYSFS_PATH_MAX];	char stub_driver_path[SYSFS_PATH_MAX];	struct sysfs_driver *stub_driver;	ret = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX);	if (ret < 0) {		err("sysfs must be mounted");		return NULL;	}	snprintf(stub_driver_path, SYSFS_PATH_MAX, "%s/%s/usb/%s/%s",			sysfs_mntpath, SYSFS_BUS_NAME, SYSFS_DRIVERS_NAME,			usbip_stub_driver_name);	stub_driver = sysfs_open_driver_path(stub_driver_path);	if (!stub_driver) {		err("usbip_common_mod.ko and usbip.ko must be loaded");		return NULL;	}	return stub_driver;}/* only the first interface value is true! */static int32_t read_attr_usbip_status(struct usb_device *udev){	char attrpath[SYSFS_PATH_MAX];	struct sysfs_attribute *attr;	int value = 0;	int  ret;	snprintf(attrpath, SYSFS_PATH_MAX, "%s/%s:%d.%d/usbip_status",			udev->path, udev->busid,			udev->bConfigurationValue,			0);	attr = sysfs_open_attribute(attrpath);	if (!attr) {		err("open %s", attrpath);		return -1;	}	ret = sysfs_read_attribute(attr);	if (ret) {		err("read %s", attrpath);		sysfs_close_attribute(attr);		return -1;	}	value = atoi(attr->value);	sysfs_close_attribute(attr);	return value;}static void usbip_exported_device_delete(void *dev){	struct usbip_exported_device *edev =		(struct usbip_exported_device *) dev;	sysfs_close_device(edev->sudev);	free(dev);}static struct usbip_exported_device *usbip_exported_device_new(char *sdevpath){	struct usbip_exported_device *edev = NULL;	edev = (struct usbip_exported_device *) calloc(1, sizeof(*edev));	if (!edev) {		err("alloc device");		return NULL;	}	edev->sudev = sysfs_open_device_path(sdevpath);	if (!edev->sudev) {		err("open %s", sdevpath);		goto err;	}	read_usb_device(edev->sudev, &edev->udev);	edev->status = read_attr_usbip_status(&edev->udev);	if (edev->status < 0)		goto err;	/* reallocate buffer to include usb interface data */	size_t size = sizeof(*edev) + edev->udev.bNumInterfaces * sizeof(struct usb_interface);	edev = (struct usbip_exported_device *) realloc(edev, size);	if (!edev) {		err("alloc device");		goto err;	}	for (int i=0; i < edev->udev.bNumInterfaces; i++)		read_usb_interface(&edev->udev, i, &edev->uinf[i]);	return edev;err:	if (edev && edev->sudev)		sysfs_close_device(edev->sudev);	if (edev)		free(edev);	return NULL;}static int check_new(struct dlist *dlist, struct sysfs_device *target){	struct sysfs_device *dev;	dlist_for_each_data(dlist, dev, struct sysfs_device) {		if (!strncmp(dev->bus_id, target->bus_id, SYSFS_BUS_ID_SIZE))			/* found. not new */			return 0;	}	return 1;}static void delete_nothing(void *dev){	/* do not delete anything. but, its container will be deleted. */}static int refresh_exported_devices(void){	struct sysfs_device	*suinf;  /* sysfs_device of usb_interface */	struct dlist		*suinf_list;	struct sysfs_device	*sudev;  /* sysfs_device of usb_device */	struct dlist		*sudev_list;	sudev_list = dlist_new_with_delete(sizeof(struct sysfs_device), delete_nothing);	suinf_list = sysfs_get_driver_devices(stub_driver->sysfs_driver);	if (!suinf_list) {		printf("Bind usbip.ko to a usb device to be exportable!\n");		goto bye;	}	/* collect unique USB devices (not interfaces) */	dlist_for_each_data(suinf_list, suinf, struct sysfs_device) {		/* get usb device of this usb interface */		sudev = sysfs_get_device_parent(suinf);		if (!sudev) {			err("get parent dev of %s", suinf->name);			continue;		}		if (check_new(sudev_list, sudev)) {			dlist_unshift(sudev_list, sudev);		}	}	dlist_for_each_data(sudev_list, sudev, struct sysfs_device) {		struct usbip_exported_device *edev;		edev = usbip_exported_device_new(sudev->path);		if (!edev) {			err("usbip_exported_device new");			continue;		}		dlist_unshift(stub_driver->edev_list, (void *) edev);		stub_driver->ndevs++;	}	dlist_destroy(sudev_list);bye:	return 0;}int usbip_stub_refresh_device_list(void){	int ret;	if (stub_driver->edev_list)		dlist_destroy(stub_driver->edev_list);	stub_driver->ndevs = 0;	stub_driver->edev_list = dlist_new_with_delete(sizeof(struct usbip_exported_device),			usbip_exported_device_delete);	if (!stub_driver->edev_list) {		err("alloc dlist");		return -1;	}	ret = refresh_exported_devices();	if (ret < 0)		return ret;	return 0;}int usbip_stub_driver_open(void){	int ret;	stub_driver = (struct usbip_stub_driver *) calloc(1, sizeof(*stub_driver));	if (!stub_driver) {		err("alloc stub_driver");		return -1;	}	stub_driver->ndevs = 0;	stub_driver->edev_list = dlist_new_with_delete(sizeof(struct usbip_exported_device),			usbip_exported_device_delete);	if (!stub_driver->edev_list) {		err("alloc dlist");		goto err;	}	stub_driver->sysfs_driver = open_sysfs_stub_driver();	if (!stub_driver->sysfs_driver)		goto err;	ret = refresh_exported_devices();	if (ret < 0)		goto err;	return 0;err:	if (stub_driver->sysfs_driver)		sysfs_close_driver(stub_driver->sysfs_driver);	if (stub_driver->edev_list)		dlist_destroy(stub_driver->edev_list);	free(stub_driver);	stub_driver = NULL;	return -1;}void usbip_stub_driver_close(void){	if (!stub_driver)		return;	if (stub_driver->edev_list)		dlist_destroy(stub_driver->edev_list);	if (stub_driver->sysfs_driver)		sysfs_close_driver(stub_driver->sysfs_driver);	free(stub_driver);	stub_driver = NULL;}int usbip_stub_export_device(struct usbip_exported_device *edev, int sockfd){	char attrpath[SYSFS_PATH_MAX];	struct sysfs_attribute *attr;	char sockfd_buff[30];	int ret;	if (edev->status != SDEV_ST_AVAILABLE) {		info("device not available, %s", edev->udev.busid);		switch( edev->status ) {			case SDEV_ST_ERROR:				info("     status SDEV_ST_ERROR");				break;			case SDEV_ST_USED:				info("     status SDEV_ST_USED");				break;			default:				info("     status unknown: 0x%x", edev->status);		}		return -1;	}	/* only the first interface is true */	snprintf(attrpath, sizeof(attrpath), "%s/%s:%d.%d/%s",			edev->udev.path,			edev->udev.busid,			edev->udev.bConfigurationValue, 0,			"usbip_sockfd");	attr = sysfs_open_attribute(attrpath);	if (!attr) {		err("open %s", attrpath);		return -1;	}	snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd);	dbg("write: %s", sockfd_buff);	ret = sysfs_write_attribute(attr, sockfd_buff, strlen(sockfd_buff));	if (ret < 0) {		err("write sockfd %s to %s", sockfd_buff, attrpath);		goto err_write_sockfd;	}	info("connect %s", edev->udev.busid);err_write_sockfd:	sysfs_close_attribute(attr);	return ret;}struct usbip_exported_device *usbip_stub_get_device(int num){	struct usbip_exported_device *edev;	struct dlist		*dlist = stub_driver->edev_list;	int count = 0;	dlist_for_each_data(dlist, edev, struct usbip_exported_device) {		if (num == count)			return edev;		else			count++ ;	}	return NULL;}

⌨️ 快捷键说明

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