?? stub_rx.c
字號:
if (pdu->base.devid == sdev->devid) { spin_lock(&ud->lock); if (ud->status == SDEV_ST_USED) { /* A request is valid. */ spin_unlock(&ud->lock); return 1; } spin_unlock(&ud->lock); } return 0;}static struct stub_priv *stub_priv_alloc(struct stub_device *sdev, struct usbip_header *pdu){ struct stub_priv *priv; struct usbip_device *ud = &sdev->ud; unsigned long flags; spin_lock_irqsave(&sdev->priv_lock, flags); priv = kmem_cache_alloc(stub_priv_cache, GFP_ATOMIC); if (!priv) { uerr("alloc stub_priv\n"); spin_unlock_irqrestore(&sdev->priv_lock, flags); usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); return NULL; } memset(priv, 0, sizeof(struct stub_priv)); priv->seqnum = pdu->base.seqnum; priv->sdev = sdev; /* * After a stub_priv is linked to a list_head, * our error handler can free allocated data. */ list_add_tail(&priv->list, &sdev->priv_init); spin_unlock_irqrestore(&sdev->priv_lock, flags); return priv;}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)static inline int usb_endpoint_xfer_bulk( const struct usb_endpoint_descriptor *epd){ return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK);}static inline int usb_endpoint_xfer_control( const struct usb_endpoint_descriptor *epd){ return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_CONTROL);}static inline int usb_endpoint_xfer_int( const struct usb_endpoint_descriptor *epd){ return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT);}static inline int usb_endpoint_xfer_isoc( const struct usb_endpoint_descriptor *epd){ return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC);}#endifstatic struct usb_host_endpoint *get_ep_from_epnum(struct usb_device *udev, int epnum0){ struct usb_host_config *config; int i = 0, j = 0; struct usb_host_endpoint *ep = NULL; int epnum; int found = 0; if (epnum0 == 0) return &udev->ep0; config = udev->actconfig; if (!config) return NULL; for (i = 0; i < config->desc.bNumInterfaces; i++) { struct usb_host_interface *setting; setting = config->interface[i]->cur_altsetting; for (j = 0; j < setting->desc.bNumEndpoints; j++) { ep = &setting->endpoint[j]; epnum = (ep->desc.bEndpointAddress & 0x7f); if (epnum == epnum0) { //uinfo("found epnum %d\n", epnum0); found = 1; break; } } } if (found) return ep; else return NULL;}static int get_pipe(struct stub_device *sdev, int epnum, int dir){ struct usb_device *udev = interface_to_usbdev(sdev->interface); struct usb_host_endpoint *ep; struct usb_endpoint_descriptor *epd = NULL; ep = get_ep_from_epnum(udev, epnum); if (!ep) { uerr("no such endpoint?, %d", epnum); BUG(); } epd = &ep->desc;#if 0 /* epnum 0 is always control */ if (epnum == 0) { if (dir == USBIP_DIR_OUT) return usb_sndctrlpipe(udev, 0); else return usb_rcvctrlpipe(udev, 0); }#endif if (usb_endpoint_xfer_control(epd)) { if (dir == USBIP_DIR_OUT) return usb_sndctrlpipe(udev, epnum); else return usb_rcvctrlpipe(udev, epnum); } if (usb_endpoint_xfer_bulk(epd)) { if (dir == USBIP_DIR_OUT) return usb_sndbulkpipe(udev, epnum); else return usb_rcvbulkpipe(udev, epnum); } if (usb_endpoint_xfer_int(epd)) { if (dir == USBIP_DIR_OUT) return usb_sndintpipe(udev, epnum); else return usb_rcvintpipe(udev, epnum); } if (usb_endpoint_xfer_isoc(epd)) { if (dir == USBIP_DIR_OUT) return usb_sndisocpipe(udev, epnum); else return usb_rcvisocpipe(udev, epnum); } /* NOT REACHED */ uerr("get pipe, epnum %d\n", epnum); return 0;}static void stub_recv_cmd_submit(struct stub_device *sdev, struct usbip_header *pdu){ int ret; struct stub_priv *priv; struct usbip_device *ud = &sdev->ud; struct usb_device *udev = interface_to_usbdev(sdev->interface); int pipe = get_pipe(sdev, pdu->base.ep, pdu->base.direction); priv = stub_priv_alloc(sdev, pdu); if (!priv) return; /* setup a urb */ if (usb_pipeisoc(pipe)) priv->urb = usb_alloc_urb(pdu->u.cmd_submit.number_of_packets, GFP_KERNEL); else priv->urb = usb_alloc_urb(0, GFP_KERNEL); if (!priv->urb) { uerr("malloc urb\n"); usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); return; } /* set priv->urb->transfer_buffer */ if (pdu->u.cmd_submit.transfer_buffer_length > 0) { priv->urb->transfer_buffer = kzalloc(pdu->u.cmd_submit.transfer_buffer_length, GFP_KERNEL); if (!priv->urb->transfer_buffer) { uerr("malloc x_buff\n"); usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); return; } } /* set priv->urb->setup_packet */ priv->urb->setup_packet = kzalloc(8, GFP_KERNEL); if (!priv->urb->setup_packet) { uerr("allocate setup_packet\n"); usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); return; } memcpy(priv->urb->setup_packet, &pdu->u.cmd_submit.setup, 8); /* set other members from the base header of pdu */ priv->urb->context = (void *) priv; priv->urb->dev = udev; priv->urb->pipe = pipe; priv->urb->complete = stub_complete; usbip_pack_pdu(pdu, priv->urb, USBIP_CMD_SUBMIT, 0); if (usbip_recv_xbuff(ud, priv->urb) < 0) return; if (usbip_recv_iso(ud, priv->urb) < 0) return; /* no need to submit an intercepted request, but harmless? */ tweak_special_requests(priv->urb); /* urb is now ready to submit */ ret = usb_submit_urb(priv->urb, GFP_KERNEL); if (ret == 0) dbg_stub_rx("submit urb ok, seqnum %u\n", pdu->base.seqnum); else { uerr("submit_urb error, %d\n", ret); usbip_dump_header(pdu); usbip_dump_urb(priv->urb); /* * Pessimistic. * This connection will be discarded. */ usbip_event_add(ud, SDEV_EVENT_ERROR_SUBMIT); } dbg_stub_rx("Leave\n"); return;}/* recv a pdu */static void stub_rx_pdu(struct usbip_device *ud){ int ret; struct usbip_header pdu; struct stub_device *sdev = container_of(ud, struct stub_device, ud); dbg_stub_rx("Enter\n"); memset(&pdu, 0, sizeof(pdu)); /* 1. receive a pdu header */ ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu),0); if (ret != sizeof(pdu)) { uerr("recv a header, %d\n", ret); usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); return; } usbip_header_correct_endian(&pdu, 0); if (dbg_flag_stub_rx) usbip_dump_header(&pdu); if (!valid_request(sdev, &pdu)) { uerr("recv invalid request\n"); usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); return; } switch (pdu.base.command) { case USBIP_CMD_UNLINK: stub_recv_cmd_unlink(sdev, &pdu); break; case USBIP_CMD_SUBMIT: stub_recv_cmd_submit(sdev, &pdu); break; default: /* NOTREACHED */ uerr("unknown pdu\n"); usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); return; }}void stub_rx_loop(struct usbip_task *ut){ struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx); while (1) { if (signal_pending(current)) { dbg_stub_rx("signal caught!\n"); break; } if (usbip_event_happend(ud)) break; stub_rx_pdu(ud); }}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -