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

📄 usbip_common.c

📁 Realize the usbip function, which could be simulate usb port through net
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: usbip_common.c 15 2007-06-18 12:22:03Z hirofuchi $ * * Copyright (C) 2003-2007 Takahiro Hirofuchi * * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */#include <linux/kernel.h>#include <linux/file.h>#include <linux/tcp.h>#include <linux/in.h>#include "usbip_common.h"/* version information */#define DRIVER_VERSION "$Id: usbip_common.c 15 2007-06-18 12:22:03Z hirofuchi $"#define DRIVER_AUTHOR "Takahiro Hirofuchi <hirofuchi _at_ users.sourceforge.net>"#define DRIVER_DESC "usbip common driver"/*-------------------------------------------------------------------------*//* debug routines */#ifdef CONFIG_USB_DEBUGunsigned long usbip_debug_flag = 0xffffffff;#elseunsigned long usbip_debug_flag = 0;#endifEXPORT_SYMBOL(usbip_debug_flag);/* FIXME */struct device_attribute dev_attr_usbip_debug;EXPORT_SYMBOL(dev_attr_usbip_debug);static ssize_t show_flag(struct device *dev, struct device_attribute *attr, char *buf){	return sprintf(buf, "%lx\n", usbip_debug_flag);}static ssize_t store_flag(struct device *dev, struct device_attribute *attr,		const char *buf, size_t count){	unsigned long flag;	sscanf(buf, "%lx", &flag);	usbip_debug_flag = flag;	return count;}DEVICE_ATTR(usbip_debug, (S_IRUGO | S_IWUSR), show_flag, store_flag);static void usbip_dump_buffer(char *buff, int bufflen){	int i;	if (bufflen > 128) {		for (i = 0; i< 128; i++) {			if (i%24 == 0)				printk("   ");			printk("%02x ", (unsigned char ) buff[i]);			if (i%4 == 3) printk("| ");			if (i%24 == 23) printk("\n");		}		printk("... (%d byte)\n", bufflen);		return;	}	for (i = 0; i< bufflen; i++) {		if (i%24 == 0)			printk("   ");		printk("%02x ", (unsigned char ) buff[i]);		if (i%4 == 3)			printk("| ");		if (i%24 == 23)			printk("\n");	}	printk("\n");}static void usbip_dump_pipe(unsigned int p){	unsigned char type = usb_pipetype(p);	unsigned char ep = usb_pipeendpoint(p);	unsigned char dev = usb_pipedevice(p);	unsigned char dir = usb_pipein(p);	printk("dev(%d) ", dev);	printk("ep(%d) ",  ep);	printk("%s ", dir ? "IN" : "OUT");	switch(type) {		case PIPE_ISOCHRONOUS :			printk("%s ", "ISO");			break;		case PIPE_INTERRUPT :			printk("%s ", "INT");			break;		case PIPE_CONTROL :			printk("%s ", "CTL");			break;		case PIPE_BULK :			printk("%s ", "BLK");			break;		default :			printk("ERR");	}	printk("\n");}static void usbip_dump_usb_device(struct usb_device *dev){	int i;	if (!dev) {		printk("      dump usb dev: null pointer!!\n");		return;	}	printk("       devnum(%d) devpath(%s)", dev->devnum, dev->devpath);	switch(dev->speed) {		case USB_SPEED_HIGH :			printk(" SPD_HIGH");			break;		case USB_SPEED_FULL :			printk(" SPD_FULL");			break;		case USB_SPEED_LOW :			printk(" SPD_LOW");			break;		case USB_SPEED_UNKNOWN :			printk(" SPD_UNKNOWN");			break;		default :			printk(" SPD_ERROR");	}	printk(" tt %p, ttport %d", dev->tt, dev->ttport);	printk("\n");	printk("                    ");	for (i = 0; i < 16; i++) {		printk(" %2u", i);	}	printk("\n");	printk("       toggle0(IN) :");	for (i = 0; i< 16; i++) {		printk(" %2u", ( dev->toggle[0] & (1 << i) ) ? 1 : 0);	}	printk("\n");	printk("       toggle1(OUT):");	for (i = 0; i< 16; i++) {		printk(" %2u", ( dev->toggle[1] & (1 << i) ) ? 1 : 0);	}	printk("\n");	printk("       epmaxp_in   :");	for (i = 0; i < 16; i++) {		if (dev->ep_in[i])			printk(" %2u",  dev->ep_in[i]->desc.wMaxPacketSize);	}	printk("\n");	printk("       epmaxp_out  :");	for (i = 0; i < 16; i++) {		if (dev->ep_out[i])			printk(" %2u",  dev->ep_out[i]->desc.wMaxPacketSize);	}	printk("\n       ");	printk("parent %p, bus %p", dev->parent, dev->bus);	printk("\n       ");	printk("descriptor %p, config %p, actconfig %p, rawdescriptors %p",			&dev->descriptor, dev->config, dev->actconfig, dev->rawdescriptors);	printk("\n       ");	printk("have_langid %d, string_langid %d", dev->have_langid, dev->string_langid);	printk("\n       ");	printk("maxchild %d, children %p", dev->maxchild, dev->children);	printk("\n");}static void usbip_dump_request_type(__u8 rt){	switch(rt & USB_RECIP_MASK) {		case USB_RECIP_DEVICE:			printk("DEVICE");			break;		case USB_RECIP_INTERFACE:			printk("INTERF");			break;		case USB_RECIP_ENDPOINT:			printk("ENDPOI");			break;		case USB_RECIP_OTHER:			printk("OTHER ");			break;		default:			printk("------");	}}static void usbip_dump_usb_ctrlrequest(struct usb_ctrlrequest *cmd){	if (!cmd) {		printk("      %s : null pointer\n", __FUNCTION__);		return;	}	printk("       ");	printk("bRequestType(%02X) ", cmd->bRequestType);	printk("bRequest(%02X) " , cmd->bRequest);	printk("wValue(%04X) ", cmd->wValue);	printk("wIndex(%04X) ", cmd->wIndex);	printk("wLength(%04X) ", cmd->wLength);	printk("\n       ");	if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {		printk("STANDARD ");		switch(cmd->bRequest) {			case USB_REQ_GET_STATUS:				printk("GET_STATUS");				break;			case USB_REQ_CLEAR_FEATURE:				printk("CLEAR_FEAT");				break;			case USB_REQ_SET_FEATURE:				printk("SET_FEAT  ");				break;			case USB_REQ_SET_ADDRESS:				printk("SET_ADDRRS");				break;			case USB_REQ_GET_DESCRIPTOR:				printk("GET_DESCRI");				break;			case USB_REQ_SET_DESCRIPTOR:				printk("SET_DESCRI");				break;			case USB_REQ_GET_CONFIGURATION:				printk("GET_CONFIG");				break;			case USB_REQ_SET_CONFIGURATION:				printk("SET_CONFIG");				break;			case USB_REQ_GET_INTERFACE:				printk("GET_INTERF");				break;			case USB_REQ_SET_INTERFACE:				printk("SET_INTERF");				break;			case USB_REQ_SYNCH_FRAME:				printk("SYNC_FRAME");				break;			default:				printk("REQ(%02X) ", cmd->bRequest);		}		printk(" ");		usbip_dump_request_type(cmd->bRequestType);	} else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS)		printk("CLASS   ");	else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_VENDOR)		printk("VENDOR  ");	else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_RESERVED)		printk("RESERVED");	printk("\n");}void usbip_dump_urb (struct urb *purb){	if (!purb) {		printk("   dump urb: null pointer!!\n");		return;	}	printk("   urb                   :%p\n", purb);	printk("   dev                   :%p\n", purb->dev);	usbip_dump_usb_device(purb->dev);	printk("   pipe                  :%08x ", purb->pipe);	usbip_dump_pipe(purb->pipe);	printk("   status                :%d\n", purb->status);	printk("   transfer_flags        :%08X\n", purb->transfer_flags);	printk("   transfer_buffer       :%p\n", purb->transfer_buffer);	printk("   transfer_buffer_length:%d\n", purb->transfer_buffer_length);	printk("   actual_length         :%d\n", purb->actual_length);	printk("   setup_packet          :%p\n", purb->setup_packet);	if (purb->setup_packet && usb_pipetype(purb->pipe) == PIPE_CONTROL)		usbip_dump_usb_ctrlrequest((struct usb_ctrlrequest *) purb->setup_packet);	printk("   start_frame           :%d\n", purb->start_frame);	printk("   number_of_packets     :%d\n", purb->number_of_packets);	printk("   interval              :%d\n", purb->interval);	printk("   error_count           :%d\n", purb->error_count);	printk("   context               :%p\n", purb->context);	printk("   complete              :%p\n", purb->complete);}EXPORT_SYMBOL(usbip_dump_urb);void usbip_dump_header(struct usbip_header *pdu){	udbg("BASE: cmd %u bus %u dev %u seq %u pipe %04x\n",			pdu->base.command,			pdu->base.busnum,			pdu->base.devnum,			pdu->base.seqnum,			pdu->base.pipe);	usbip_dump_pipe(pdu->base.pipe);	switch(pdu->base.command) {		case USBIP_CMD_SUBMIT:			udbg("CMD_SUBMIT: x_flags %u x_len %u sf %u #p %u iv %u\n",					pdu->u.cmd_submit.transfer_flags,					pdu->u.cmd_submit.transfer_buffer_length,					pdu->u.cmd_submit.start_frame,					pdu->u.cmd_submit.number_of_packets,					pdu->u.cmd_submit.interval);					break;		case USBIP_CMD_UNLINK:			udbg("CMD_UNLINK: seq %u\n", pdu->u.cmd_unlink.seqnum);			break;		case USBIP_RET_SUBMIT:			udbg("RET_SUBMIT: st %d al %u sf %d ec %d\n",					pdu->u.ret_submit.status,					pdu->u.ret_submit.actual_length,					pdu->u.ret_submit.start_frame,					pdu->u.ret_submit.error_count);		case USBIP_RET_UNLINK:			udbg("RET_UNLINK: status %d\n", pdu->u.ret_unlink.status);			break;		default:			/* NOT REACHED */			udbg("UNKNOWN\n");	}}EXPORT_SYMBOL(usbip_dump_header);/*-------------------------------------------------------------------------*//* thread routines */int usbip_thread(void *param){	struct usbip_task *ut = (struct usbip_task *) param;	if (!ut)		return -EINVAL;	lock_kernel();	daemonize(ut->name);	allow_signal(SIGKILL);	ut->thread = current;	unlock_kernel();	/* srv.rb must wait for rx_thread starting */	complete(&ut->thread_done);	/* start of while loop */	ut->loop_ops(ut);	/* end of loop */	ut->thread = NULL;	complete_and_exit(&ut->thread_done, 0);}void usbip_start_threads(struct usbip_device *ud){	/*	 * threads are invoked per one device (per one connection).	 */	kernel_thread((int(*)(void *))usbip_thread, (void *)&ud->tcp_rx, 0);	kernel_thread((int(*)(void *))usbip_thread, (void *)&ud->tcp_tx, 0);	/* confirm threads are starting */	wait_for_completion(&ud->tcp_rx.thread_done);	wait_for_completion(&ud->tcp_tx.thread_done);}EXPORT_SYMBOL(usbip_start_threads);void usbip_stop_threads(struct usbip_device *ud){        /* kill threads related to this sdev, if v.c. exists */	if (ud->tcp_rx.thread != NULL) {		send_sig(SIGKILL, ud->tcp_rx.thread, 1);		wait_for_completion(&ud->tcp_rx.thread_done);		udbg("rx_thread for ud %p has finished\n", ud);	}	if (ud->tcp_tx.thread != NULL) {		send_sig(SIGKILL, ud->tcp_tx.thread, 1);		wait_for_completion(&ud->tcp_tx.thread_done);		udbg("tx_thread for ud %p has finished\n", ud);	}}EXPORT_SYMBOL(usbip_stop_threads);void usbip_task_init(struct usbip_task *ut, char *name,		void (*loop_ops)(struct usbip_task *)){	ut->thread = NULL;	init_completion(&ut->thread_done);	ut->name = name;	ut->loop_ops = loop_ops;}EXPORT_SYMBOL(usbip_task_init);/*-------------------------------------------------------------------------*//* socket routines */ /*  Send/receive messages over TCP/IP. I refer drivers/block/nbd.c */int usbip_xmit(int send, struct socket *sock, char *buf, int size, int msg_flags){	int result;	struct msghdr msg;	struct kvec iov;	int total = 0;	/* for blocks of if (dbg_flag_xmit) */	char *bp = buf;	int osize= size;	dbg_xmit("enter\n");	if (!sock || !buf || !size) {		uerr("usbip_xmit: invalid arg, sock %p buff %p size %d\n",				sock, buf, size);		return -EINVAL;	}	if (dbg_flag_xmit) {		if (send) {			if (!in_interrupt())				printk(KERN_DEBUG "%-10s:", current->comm);			else				printk(KERN_DEBUG "interupt  :");			printk("usbip_xmit: sending... , sock %p, buf %p, size %d, msg_flags %d\n",					sock, buf, size, msg_flags);			usbip_dump_buffer(buf, size);		}	}	do {		sock->sk->sk_allocation = GFP_NOIO;		iov.iov_base    = buf;		iov.iov_len     = size;		msg.msg_name    = NULL;

⌨️ 快捷键说明

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