📄 usbip_common.c
字号:
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 + -