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

📄 vhci_attach.c

📁 linux virtual usb host source
💻 C
字号:
/* * $Id: vhci_attach.c 42 2007-09-07 12:07:51Z hirofuchi $ * * Copyright (C) 2005-2007 Takahiro Hirofuchi */#ifdef HAVE_CONFIG_H#include "../config.h"#endif#include "usbip.h"#include "usbip_network.h"#include <ctype.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <glib.h>static const char version[] = PACKAGE_STRING	" ($Id: vhci_attach.c 42 2007-09-07 12:07:51Z hirofuchi $)";/* /sys/devices/platform/vhci_hcd/usb6/6-1/6-1:1.1  -> 1 */static int get_interface_number(char *path){	char *c;	c = strstr(path, vhci_driver->hc_device->bus_id);	if (!c)		return -1;	/* hc exist? */	c++;	/* -> usb6/6-1/6-1:1.1 */	c = strchr(c, '/');	if (!c)		return -1;	/* hc exist? */	c++;	/* -> 6-1/6-1:1.1 */	c = strchr(c, '/');	if (!c)		return -1;	/* no interface path */	c++;	/* -> 6-1:1.1 */	c = strchr(c, ':');	if (!c)		return -1;	/* no configuration? */	c++;	/* -> 1.1 */	c = strchr(c, '.');	if (!c)		return -1;	/* no interface? */	c++;	/* -> 1 */	return atoi(c);}static struct sysfs_device *open_usb_interface(struct usb_device *udev, int i){	struct sysfs_device *suinf;	char busid[SYSFS_BUS_ID_SIZE];	snprintf(busid, SYSFS_BUS_ID_SIZE, "%s:%d.%d",			udev->busid, udev->bConfigurationValue, i);	suinf = sysfs_open_device("usb", busid);	if (!suinf)		err("sysfs_open_device %s", busid);	return suinf;}#define MAX_BUFF 100static int record_connection(char *host, char *port, char *busid, int rhport){	int fd;	char path[PATH_MAX+1];	char buff[MAX_BUFF+1];	int ret;	mkdir("/tmp/vhci_hcd", 0700);	snprintf(path, PATH_MAX, "/tmp/vhci_hcd/port%d", rhport);	fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);	if (fd < 0)		return -1;	snprintf(buff, MAX_BUFF, "%s %s %s\n",			host, port, busid);	ret = write(fd, buff, strlen(buff));	if (ret != (ssize_t) strlen(buff)) {		close(fd);		return -1;	}	close(fd);	return 0;}static int read_record(int rhport, char *host, char *port, char *busid){	FILE *file;	char path[PATH_MAX+1];	snprintf(path, PATH_MAX, "/tmp/vhci_hcd/port%d", rhport);	file = fopen(path, "r");	if (!file) {		err("fopen");		return -1;	}	fscanf(file, "%s %s %s\n", host, port, busid);	fclose(file);	return 0;}void usbip_vhci_imported_device_dump(struct usbip_imported_device *idev){	char product_name[100];	char host[NI_MAXHOST] = "unknown host";	char serv[NI_MAXSERV] = "unknown port";	char remote_busid[SYSFS_BUS_ID_SIZE];	int ret;	if (idev->status == VDEV_ST_NULL || idev->status == VDEV_ST_NOTASSIGNED) {		info("Port %02d: <%s>", idev->port, usbip_status_string(idev->status));		return;	}	ret = read_record(idev->port, host, serv, remote_busid);	if (ret)		err("red_record");	info("Port %02d: <%s> at %s", idev->port,			usbip_status_string(idev->status), usbip_speed_string(idev->udev.speed));	usbip_names_get_product(product_name, sizeof(product_name),			idev->udev.idVendor, idev->udev.idProduct);	info("       %s",  product_name);	info("%10s -> usbip://%s:%s/%s  (remote devid %08x (bus/dev %03d/%03d))",			idev->udev.busid, host, serv, remote_busid,			idev->devid,			idev->busnum, idev->devnum);	for (int i=0; i < idev->udev.bNumInterfaces; i++) {		/* show interface information */		struct sysfs_device *suinf;		suinf = open_usb_interface(&idev->udev, i);		if (!suinf)			continue;		info("       %6s used by %-17s", suinf->bus_id, suinf->driver_name);		sysfs_close_device(suinf);		/* show class device information */		struct class_device *cdev;		dlist_for_each_data(idev->cdev_list, cdev, struct class_device) {			int ifnum = get_interface_number(cdev->devpath);			if (ifnum == i) {				info("           %s", cdev->clspath);			}		}	}}static int query_exported_devices(int sockfd){	int ret;	struct op_devlist_reply rep;	uint16_t code = OP_REP_DEVLIST;	bzero(&rep, sizeof(rep));	ret = usbip_send_op_common(sockfd, OP_REQ_DEVLIST, 0);	if (ret < 0) {		err("send op_common");		return -1;	}	ret = usbip_recv_op_common(sockfd, &code);	if (ret < 0) {		err("recv op_common");		return -1;	}	ret = usbip_recv(sockfd, (void *) &rep, sizeof(rep));	if (ret < 0) {		err("recv op_devlist");		return -1;	}	PACK_OP_DEVLIST_REPLY(0, &rep);	dbg("exportable %d devices", rep.ndev);	for (unsigned int i=0; i < rep.ndev; i++) {		char product_name[100];		char class_name[100];		struct usb_device udev;		bzero(&udev, sizeof(udev));		ret = usbip_recv(sockfd, (void *) &udev, sizeof(udev));		if (ret < 0) {			err("recv usb_device[%d]", i);			return -1;		}		pack_usb_device(0, &udev);		usbip_names_get_product(product_name, sizeof(product_name),				udev.idVendor, udev.idProduct);		usbip_names_get_class(class_name, sizeof(class_name), udev.bDeviceClass,				udev.bDeviceSubClass, udev.bDeviceProtocol);		info("%8s: %s", udev.busid, product_name);		info("%8s: %s", " ", udev.path);		info("%8s: %s", " ", class_name);		for (int j=0; j < udev.bNumInterfaces; j++) {			struct usb_interface uinf;			ret = usbip_recv(sockfd, (void *) &uinf, sizeof(uinf));			if (ret < 0) {				err("recv usb_interface[%d]", j);				return -1;			}			pack_usb_interface(0, &uinf);			usbip_names_get_class(class_name, sizeof(class_name), uinf.bInterfaceClass,					uinf.bInterfaceSubClass, uinf.bInterfaceProtocol);			info("%8s: %2d - %s", " ", j, class_name);		}		info(" ");	}	return rep.ndev;}static int import_device(int sockfd, struct usb_device *udev){	int ret;	int port;	ret = usbip_vhci_driver_open();	if (ret < 0) {		err("open vhci_driver");		return -1;	}	port = usbip_vhci_get_free_port();	if (port < 0) {		err("no free port");		usbip_vhci_driver_close();		return -1;	}	ret = usbip_vhci_attach_device(port, sockfd, udev->busnum,			udev->devnum, udev->speed);	if (ret < 0) {		err("import device");		usbip_vhci_driver_close();		return -1;	}	usbip_vhci_driver_close();	return port;}static int query_import_device(int sockfd, char *busid){	int ret;	struct op_import_request request;	struct op_import_reply   reply;	uint16_t code = OP_REP_IMPORT;	bzero(&request, sizeof(request));	bzero(&reply, sizeof(reply));	/* send a request */	ret = usbip_send_op_common(sockfd, OP_REQ_IMPORT, 0);	if (ret < 0) {		err("send op_common");		return -1;	}	memcpy(&request.busid, busid, SYSFS_BUS_ID_SIZE);	PACK_OP_IMPORT_REQUEST(0, &request);	ret = usbip_send(sockfd, (void *) &request, sizeof(request));	if (ret < 0) {		err("send op_import_request");		return -1;	}	/* recieve a reply */	ret = usbip_recv_op_common(sockfd, &code);	if (ret < 0) {		err("recv op_common");		return -1;	}	ret = usbip_recv(sockfd, (void *) &reply, sizeof(reply));	if (ret < 0) {		err("recv op_import_reply");		return -1;	}	PACK_OP_IMPORT_REPLY(0, &reply);	/* check the reply */	if (strncmp(reply.udev.busid, busid, SYSFS_BUS_ID_SIZE)) {		err("recv different busid %s", reply.udev.busid);		return -1;	}	/* import a device */	return import_device(sockfd, &reply.udev);}static void attach_device(char *host, char *busid){	int sockfd;	int ret;	int rhport;	sockfd = tcp_connect(host, USBIP_PORT_STRING);	if (sockfd < 0) {		err("tcp connect");		return;	}	rhport = query_import_device(sockfd, busid);	if (rhport < 0) {		err("query");		return;	}	close(sockfd);	ret = record_connection(host, USBIP_PORT_STRING,			busid, rhport);	if (ret < 0)		err("record connection");	return;}static void detach_port(char *port){	int ret;	uint8_t portnum;	for (unsigned int i=0; i < strlen(port); i++)		if (!isdigit(port[i])) {			err("invalid port %s", port);			return;		}	/* check max port */	portnum = atoi(port);	ret = usbip_vhci_driver_open();	if (ret < 0) {		err("open vhci_driver");		return;	}	usbip_vhci_detach_device(portnum);	usbip_vhci_driver_close();}static void show_exported_devices(char *host){	int ret;	int sockfd;	sockfd = tcp_connect(host, USBIP_PORT_STRING);	if (sockfd < 0) {		info("- %s failed", host);		return;	}	info("- %s", host);	ret = query_exported_devices(sockfd);	if (ret < 0) {		err("query");	}	close(sockfd);}static int attach_exported_devices(char *host, int sockfd){	int ret;	struct op_devlist_reply rep;	uint16_t code = OP_REP_DEVLIST;	bzero(&rep, sizeof(rep));	ret = usbip_send_op_common(sockfd, OP_REQ_DEVLIST, 0);	if(ret < 0) {		err("send op_common");		return -1;	}	ret = usbip_recv_op_common(sockfd, &code);	if(ret < 0) {		err("recv op_common");		return -1;	}	ret = usbip_recv(sockfd, (void *) &rep, sizeof(rep));	if(ret < 0) {		err("recv op_devlist");		return -1;	}	PACK_OP_DEVLIST_REPLY(0, &rep);	dbg("exportable %d devices", rep.ndev);	for(unsigned int i=0; i < rep.ndev; i++) {		char product_name[100];		char class_name[100];		struct usb_device udev;		bzero(&udev, sizeof(udev));		ret = usbip_recv(sockfd, (void *) &udev, sizeof(udev));		if(ret < 0) {			err("recv usb_device[%d]", i);			return -1;		}		pack_usb_device(0, &udev);		usbip_names_get_product(product_name, sizeof(product_name),				udev.idVendor, udev.idProduct);		usbip_names_get_class(class_name, sizeof(class_name), udev.bDeviceClass,				udev.bDeviceSubClass, udev.bDeviceProtocol);		dbg("Attaching usb port %s from host %s on usbip, with deviceid: %s", udev.busid, host, product_name);		attach_device(host, udev.busid);	}	return rep.ndev;}static void attach_devices_all(char *host){	int ret;	int sockfd;	sockfd = tcp_connect(host, USBIP_PORT_STRING);	if(sockfd < 0) {		info("- %s failed", host);		return;	}	info("- %s", host);	ret = attach_exported_devices(host, sockfd);	if(ret < 0) {		err("query");	}	close(sockfd);}const char help_message[] = "\Usage: usbip [options]				\n\	-a, --attach [host] [bus_id]		\n\		Attach a remote USB device.	\n\						\n\	-x, --attachall [host]		\n\		Attach all remote USB devices on the specific host.	\n\						\n\	-d, --detach [ports]			\n\		Detach an imported USB device.	\n\						\n\	-l, --list [hosts]			\n\		List exported USB devices.	\n\						\n\	-p, --port				\n\		List virtual USB port status. 	\n\						\n\	-D, --debug				\n\		Print debugging information.	\n\						\n\	-v, --version				\n\		Show version.			\n\						\n\	-h, --help 				\n\		Print this help.		\n";static void show_help(void){	printf("%s", help_message);}static void show_port_status(void){	int ret;	struct usbip_imported_device *idev;	ret = usbip_vhci_driver_open();	if (ret < 0)		return;	for (int i = 0; i < vhci_driver->nports; i++) {		idev = &vhci_driver->idev[i];		usbip_vhci_imported_device_dump(idev);	}	usbip_vhci_driver_close();}#define _GNU_SOURCE#include <getopt.h>static const struct option longopts[] = {	{"attach",	no_argument,	NULL, 'a'},	{"attachall",	no_argument,	NULL, 'x'},	{"detach",	no_argument,	NULL, 'd'},	{"port",	no_argument,	NULL, 'p'},	{"list",	no_argument,	NULL, 'l'},	{"version",	no_argument,	NULL, 'v'},	{"help",	no_argument,	NULL, 'h'},	{"debug",	no_argument,	NULL, 'D'},	{"syslog",	no_argument,	NULL, 'S'},	{NULL,		0,		NULL,  0}};int main(int argc, char *argv[]){	int ret;	enum {		cmd_attach = 1,		cmd_attachall,		cmd_detach,		cmd_port,		cmd_list,		cmd_help,		cmd_version	} cmd = 0;	usbip_use_stderr = 1;	if (geteuid() != 0)		g_warning("running non-root?"); 	ret = usbip_names_init(USBIDS_FILE); 	if (ret) 		err("open usb.ids");	for (;;) {		int c;		int index = 0;		c = getopt_long(argc, argv, "adplvhDSx", longopts, &index);		if (c == -1)			break;		switch(c) {			case 'a':				if (!cmd)					cmd = cmd_attach;				else					cmd = cmd_help;				break;			case 'd':				if (!cmd)					cmd = cmd_detach;				else					cmd = cmd_help;				break;			case 'p':				if (!cmd)					cmd = cmd_port;				else cmd = cmd_help;				break;			case 'l':				if (!cmd)					cmd = cmd_list;				else					cmd = cmd_help;				break;			case 'v':				if (!cmd)					cmd = cmd_version;				else					cmd = cmd_help;				break;			case 'x':				if(!cmd)					cmd = cmd_attachall;				else					cmd = cmd_help;				break;			case 'h':				cmd = cmd_help;				break;			case 'D':				usbip_use_debug = 1;				break;			case 'S':				usbip_use_syslog = 1;				break;			case '?':				break;			default:				err("getopt");		}	}	switch(cmd) {		case cmd_attach:			if (optind == argc - 2)				attach_device(argv[optind], argv[optind+1]);			else				show_help();			break;		case cmd_detach:			while (optind < argc)				detach_port(argv[optind++]);			break;		case cmd_port:			show_port_status();			break;		case cmd_list:			while (optind < argc)				show_exported_devices(argv[optind++]);			break;		case cmd_attachall:			while(optind < argc)				attach_devices_all(argv[optind++]);			break;		case cmd_version:			printf("%s\n", version);			break;		case cmd_help:			show_help();			break;		default:			show_help();	}	usbip_names_free();	return 0;}

⌨️ 快捷键说明

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