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

📄 usbip_common.c

📁 Realize the usbip function, which could be simulate usb port through net
💻 C
📖 第 1 页 / 共 2 页
字号:
		msg.msg_namelen = 0;		msg.msg_control = NULL;		msg.msg_controllen = 0;		msg.msg_namelen    = 0;		msg.msg_flags      = msg_flags | MSG_NOSIGNAL;		if (send)			result = kernel_sendmsg(sock, &msg, &iov, 1, size);		else			result = kernel_recvmsg(sock, &msg, &iov, 1, size, MSG_WAITALL);		if (result <= 0) {			udbg("usbip_xmit: %s sock %p buf %p size %u ret %d total %d\n",					send ? "send" : "receive", sock, buf, size, result, total);			goto err;		}		size -= result;		buf += result;		total += result;	} while (size > 0);	if (dbg_flag_xmit) {		if (!send) {			if (!in_interrupt())				printk(KERN_DEBUG "%-10s:", current->comm);			else				printk(KERN_DEBUG "interupt  :");			printk("usbip_xmit: receiving....\n");			usbip_dump_buffer(bp, osize);			printk("usbip_xmit: received, osize %d ret %d size %d total %d\n",					osize, result, size, total);		}		if (send) {			printk("usbip_xmit: send, total %d\n", total);		}	}	return total;err:	return result;}EXPORT_SYMBOL(usbip_xmit);/* now a usrland utility should set options. */#if 0int setquickack(struct socket *socket){	mm_segment_t oldfs;	int val = 1;	int ret;	oldfs = get_fs();	set_fs(get_ds());	ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_QUICKACK,			(char __user *) &val, sizeof(ret));	set_fs(oldfs);	return ret;}int setnodelay(struct socket *socket){	mm_segment_t oldfs;	int val = 1;	int ret;	oldfs = get_fs();	set_fs(get_ds());	ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_NODELAY,			(char __user *) &val, sizeof(ret));	set_fs(oldfs);	return ret;}int setkeepalive(struct socket *socket){	mm_segment_t oldfs;	int val = 1;	int ret;	oldfs = get_fs();	set_fs(get_ds());	ret = socket->ops->setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE,			(char __user *) &val, sizeof(ret));	set_fs(oldfs);	return ret;}void setreuse(struct socket *socket){	socket->sk->sk_reuse = 1;}#endifstruct socket *sockfd_to_socket(unsigned int sockfd){	struct socket *socket;	struct file *file;	struct inode *inode;	file = fget(sockfd);	if (!file) {		uerr("invalid sockfd\n");		return NULL;	}	inode = file->f_dentry->d_inode;	if (!inode || !S_ISSOCK(inode->i_mode))		return NULL;	socket = SOCKET_I(inode);	return socket;}EXPORT_SYMBOL(sockfd_to_socket);/*-------------------------------------------------------------------------*//* pdu routines *//* there may be more cases to tweak the flags. */static unsigned int tweak_transfer_flags(unsigned int flags){	if (flags & URB_NO_TRANSFER_DMA_MAP)		/*		 * vhci_hcd does not provide DMA-mapped I/O. The upper		 * driver does not need to set this flag. The remote		 * usbip.ko does not still perform DMA-mapped I/O for		 * DMA-caplable host controllers. So, clear this flag.		 */		flags &= ~URB_NO_TRANSFER_DMA_MAP;	if (flags & URB_NO_SETUP_DMA_MAP)		flags &= ~URB_NO_SETUP_DMA_MAP;	return flags;}static void usbip_pack_cmd_submit(struct usbip_header *pdu, struct urb *urb, int pack){	struct usbip_header_cmd_submit *spdu = &pdu->u.cmd_submit;	/*	 * Some members are not still implemented in usbip. I hope this issue	 * will be discussed when usbip is ported to other operating systems.	 */	if (pack) {		/* vhci_tx.c */		spdu->transfer_flags		= tweak_transfer_flags(urb->transfer_flags);		spdu->transfer_buffer_length	= urb->transfer_buffer_length;		spdu->start_frame		= urb->start_frame;		spdu->number_of_packets		= urb->number_of_packets;		spdu->interval			= urb->interval;	} else  {		/* stub_rx.c */		urb->transfer_flags         = spdu->transfer_flags;		urb->transfer_buffer_length = spdu->transfer_buffer_length;		urb->start_frame            = spdu->start_frame;		urb->number_of_packets      = spdu->number_of_packets;		urb->interval               = spdu->interval;	}}static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb, int pack){	struct usbip_header_ret_submit *rpdu = &pdu->u.ret_submit;	if (pack) {		/* stub_tx.c */		rpdu->status		= urb->status;		rpdu->actual_length	= urb->actual_length;		rpdu->start_frame	= urb->start_frame;		rpdu->error_count	= urb->error_count;	} else {		/* vhci_rx.c */		urb->status		= rpdu->status;		urb->actual_length	= rpdu->actual_length;		urb->start_frame	= rpdu->start_frame;		urb->error_count	= rpdu->error_count;	}}void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd, int pack){	switch(cmd) {		case USBIP_CMD_SUBMIT:			usbip_pack_cmd_submit(pdu, urb, pack);			break;		case USBIP_RET_SUBMIT:			usbip_pack_ret_submit(pdu, urb, pack);			break;		default:			err("unknown command");			/* NOTREACHED */			//BUG();	}}EXPORT_SYMBOL(usbip_pack_pdu);static void correct_endian_basic(struct usbip_header_basic *base, int send){	if (send) {		base->command	= cpu_to_be32(base->command);		base->busnum	= cpu_to_be32(base->busnum);		base->devnum	= cpu_to_be32(base->devnum);		base->seqnum	= cpu_to_be32(base->seqnum);		base->pipe	= cpu_to_be32(base->pipe);	} else {		base->command	= be32_to_cpu(base->command);		base->busnum	= be32_to_cpu(base->busnum);		base->devnum	= be32_to_cpu(base->devnum);		base->seqnum	= be32_to_cpu(base->seqnum);		base->pipe	= be32_to_cpu(base->pipe);	}}static void correct_endian_cmd_submit(struct usbip_header_cmd_submit *pdu, int send){	if (send) {		pdu->transfer_flags = cpu_to_be32(pdu->transfer_flags);		cpu_to_be32s(&pdu->transfer_buffer_length);		cpu_to_be32s(&pdu->start_frame);		cpu_to_be32s(&pdu->number_of_packets);		cpu_to_be32s(&pdu->interval);	} else {		pdu->transfer_flags = be32_to_cpu(pdu->transfer_flags);		be32_to_cpus(&pdu->transfer_buffer_length);		be32_to_cpus(&pdu->start_frame);		be32_to_cpus(&pdu->number_of_packets);		be32_to_cpus(&pdu->interval);	}}static void correct_endian_ret_submit(struct usbip_header_ret_submit *pdu, int send){	if (send) {		cpu_to_be32s(&pdu->status);		cpu_to_be32s(&pdu->actual_length);		cpu_to_be32s(&pdu->start_frame);		cpu_to_be32s(&pdu->error_count);	} else {		be32_to_cpus(&pdu->status);		be32_to_cpus(&pdu->actual_length);		be32_to_cpus(&pdu->start_frame);		be32_to_cpus(&pdu->error_count);	}}static void correct_endian_cmd_unlink(struct usbip_header_cmd_unlink *pdu, int send){	if (send)		pdu->seqnum = cpu_to_be32(pdu->seqnum);	else		pdu->seqnum = be32_to_cpu(pdu->seqnum);}static void correct_endian_ret_unlink(struct usbip_header_ret_unlink *pdu, int send){	if (send)		cpu_to_be32s(&pdu->status);	else		be32_to_cpus(&pdu->status);}void usbip_header_correct_endian(struct usbip_header *pdu, int send){	__u32 cmd = 0;	if (send)		cmd = pdu->base.command;	correct_endian_basic(&pdu->base, send);	if (!send)		cmd = pdu->base.command;	switch (cmd) {		case USBIP_CMD_SUBMIT:			correct_endian_cmd_submit(&pdu->u.cmd_submit, send);			break;		case USBIP_RET_SUBMIT:			correct_endian_ret_submit(&pdu->u.ret_submit, send);			break;		case USBIP_CMD_UNLINK:			correct_endian_cmd_unlink(&pdu->u.cmd_unlink, send);			break;		case USBIP_RET_UNLINK:			correct_endian_ret_unlink(&pdu->u.ret_unlink, send);			break;		default:			/* NOTREACHED */			err("unknown command in pdu header: %d", cmd);			//BUG();	}}EXPORT_SYMBOL(usbip_header_correct_endian);static void usbip_iso_pakcet_correct_endian(struct usbip_iso_packet_descriptor *iso, int send){	/* does not need all members. but copy all simply. */	if (send) {		iso->offset	= cpu_to_be32(iso->offset);		iso->length	= cpu_to_be32(iso->length);		iso->status	= cpu_to_be32(iso->status);		iso->actual_length = cpu_to_be32(iso->actual_length);	} else {		iso->offset	= be32_to_cpu(iso->offset);		iso->length	= be32_to_cpu(iso->length);		iso->status	= be32_to_cpu(iso->status);		iso->actual_length = be32_to_cpu(iso->actual_length);	}}static void usbip_pack_iso(struct usbip_iso_packet_descriptor *iso,		struct usb_iso_packet_descriptor *uiso, int pack){	if (pack) {		iso->offset		= uiso->offset;		iso->length		= uiso->length;		iso->status		= uiso->status;		iso->actual_length	= uiso->actual_length;	} else {		uiso->offset		= iso->offset;		uiso->length		= iso->length;		uiso->status		= iso->status;		uiso->actual_length	= iso->actual_length;	}}/* must free buffer */void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen){	void *buff;	struct usbip_iso_packet_descriptor *iso;	int np = urb->number_of_packets;	ssize_t size = np * sizeof(*iso);	int i;	buff = kzalloc(size, GFP_KERNEL);	if (!buff)		return NULL;	for (i = 0; i < np; i++) {		iso = buff + (i * sizeof(*iso));		usbip_pack_iso(iso, &urb->iso_frame_desc[i], 1);		usbip_iso_pakcet_correct_endian(iso, 1);	}	*bufflen = size;	return buff;}EXPORT_SYMBOL(usbip_alloc_iso_desc_pdu);/* some members of urb must be substituted before. */int usbip_recv_iso(struct usbip_device *ud, struct urb *urb){	void *buff;	struct usbip_iso_packet_descriptor *iso;	int np = urb->number_of_packets;	int size = np * sizeof(*iso);	int i;	int ret;	if (!usb_pipeisoc(urb->pipe))		return 0;	buff = kzalloc(size, GFP_KERNEL);	if (!buff)		return -ENOMEM;	ret = usbip_xmit(0, ud->tcp_socket, buff, size, 0);	if (ret != size) {		uerr("recv iso_frame_descriptor, %d\n", ret);		kfree(buff);		if (ud->side == USBIP_STUB)			usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);		else			usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);		return -EPIPE;	}	for (i = 0; i < np; i++) {		iso = buff + (i * sizeof(*iso));		usbip_iso_pakcet_correct_endian(iso, 0);		usbip_pack_iso(iso, &urb->iso_frame_desc[i], 0);	}	kfree(buff);	return ret;}EXPORT_SYMBOL(usbip_recv_iso);/* some members of urb must be substituted before. */int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb){	int ret;	int size;	if (ud->side == USBIP_STUB) {		/* stub_rx.c */		/* the direction of urb must be OUT. */		if (usb_pipein(urb->pipe))			return 0;		size = urb->transfer_buffer_length;	} else {		/* vhci_rx.c */		/* the direction of urb must be IN. */		if (usb_pipeout(urb->pipe))			return 0;		size = urb->actual_length;	}	/* no need to recv xbuff */	if (!(size > 0))		return 0;	ret = usbip_xmit(0, ud->tcp_socket, (char *) urb->transfer_buffer, size, 0);	if (ret != size) {		uerr("recv xbuf, %d\n", ret);		if (ud->side == USBIP_STUB) {			usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);		} else {			usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);			return -EPIPE;		}	}	return ret;}EXPORT_SYMBOL(usbip_recv_xbuff);/*-------------------------------------------------------------------------*/static int __init usbip_common_init(void){	info(DRIVER_DESC "" DRIVER_VERSION);	return 0;}static void __exit usbip_common_exit(void){	return;}module_init(usbip_common_init);module_exit(usbip_common_exit);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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