static void dump_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int len, char *str) { #if defined(VERBOSE) int i; #endif DBG("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d stat:%#lx", str, isp116x_get_current_frame_number(dev), usb_pipedevice(pipe), usb_pipeendpoint(pipe), usb_pipeout(pipe) ? 'O' : 'I', usb_pipetype(pipe) < 2 ? (usb_pipeint(pipe) ? "INTR" : "ISOC") : (usb_pipecontrol(pipe) ? "CTRL" : "BULK"), len, dev->status); #if defined(VERBOSE) if (len > 0 && buffer) { printf(__FILE__ ": data(%d):", len); for (i = 0; i < 16 && i < len; i++) printf(" %02x", ((__u8 *) buffer)[i]); printf("%s\n", i < len ? "..." : ""); } #endif }
static inline void qtd_copy_status (struct urb *urb, size_t length, u32 token) { /* count IN/OUT bytes, not SETUP (even short packets) */ if (likely (QTD_PID (token) != 2)) urb->actual_length += length - QTD_LENGTH (token); /* don't modify error codes */ if (unlikely (urb->status == -EINPROGRESS && (token & QTD_STS_HALT))) { if (token & QTD_STS_BABBLE) { /* FIXME "must" disable babbling device's port too */ urb->status = -EOVERFLOW; } else if (token & QTD_STS_MMF) { /* fs/ls interrupt xfer missed the complete-split */ urb->status = -EPROTO; } else if (token & QTD_STS_DBE) { urb->status = (QTD_PID (token) == 1) /* IN ? */ ? -ENOSR /* hc couldn't read data */ : -ECOMM; /* hc couldn't write data */ } else if (token & QTD_STS_XACT) { /* timeout, bad crc, wrong PID, etc; retried */ if (QTD_CERR (token)) urb->status = -EPIPE; else { dbg ("3strikes"); urb->status = -EPROTO; } /* CERR nonzero + no errors + halt --> stall */ } else if (QTD_CERR (token)) urb->status = -EPIPE; else /* unknown */ urb->status = -EPROTO; dbg ("ep %d-%s qtd token %08x --> status %d", /* devpath */ usb_pipeendpoint (urb->pipe), usb_pipein (urb->pipe) ? "in" : "out", token, urb->status); /* stall indicates some recovery action is needed */ if (urb->status == -EPIPE) { int pipe = urb->pipe; if (!usb_pipecontrol (pipe)) usb_endpoint_halt (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)); if (urb->dev->tt && !usb_pipeint (pipe)) { err ("must CLEAR_TT_BUFFER, hub port %d%s addr %d ep %d", urb->dev->ttport, /* devpath */ urb->dev->tt->multi ? "" : " (all-ports TT)", urb->dev->devnum, usb_pipeendpoint (urb->pipe)); // FIXME something (khubd?) should make the hub // CLEAR_TT_BUFFER ASAP, it's blocking other // fs/ls requests... hub_tt_clear_buffer() ? } } } }
static int dwc_otg_submit_rh_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int txlen, struct devrequest *cmd) { int stat = 0; if (usb_pipeint(pipe)) { puts("Root-Hub submit IRQ: NOT implemented\n"); return 0; } if (cmd->requesttype & USB_DIR_IN) stat = dwc_otg_submit_rh_msg_in(dev, buffer, txlen, cmd); else stat = dwc_otg_submit_rh_msg_out(dev, buffer, txlen, cmd); mdelay(1); return stat; }
void urb_print (urb_t * urb, char * str, int small) { unsigned int pipe= urb->pipe; int i, len; if (!urb->dev || !urb->dev->bus) { dbg("%s URB: no dev", str); return; } printk("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,flags:%4x,len:%d/%d,stat:%d(%x)\n", str, hci_get_current_frame_number (urb->dev), usb_pipedevice (pipe), usb_pipeendpoint (pipe), usb_pipeout (pipe)? 'O': 'I', usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"): (usb_pipecontrol (pipe)? "CTRL": "BULK"), urb->transfer_flags, urb->actual_length, urb->transfer_buffer_length, urb->status, urb->status); if (!small) { if (usb_pipecontrol (pipe)) { printk ( __FILE__ ": cmd(8):"); for (i = 0; i < 8 ; i++) printk (" %02x", ((__u8 *) urb->setup_packet) [i]); printk ("\n"); } if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) { printk ( __FILE__ ": data(%d/%d):", urb->actual_length, urb->transfer_buffer_length); len = usb_pipeout (pipe)? urb->transfer_buffer_length: urb->actual_length; for (i = 0; i < 16 && i < len; i++) printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]); printk ("%s stat:%d\n", i < len? "...": "", urb->status); } } }
static int hcs_return_urb (hci_t * hci, urb_t * urb, int resub_ok) { int resubmit = 0; struct dmaWork* dw=NULL; if (urb_debug) urb_print (urb, "RET", usb_pipeout (urb->pipe)); resubmit = urb->interval && resub_ok; if (!resubmit) { urb->dev = NULL; dw = urb->hcpriv; urb->hcpriv = NULL; } if (urb->complete) { if ((!resubmit)||!IntervalStatus(urb)) { urb->complete (urb); /* call complete */ } } if (resubmit) { /* requeue the URB */ if (!usb_pipeint (urb->pipe) || (urb->interval==0)) { urb->start_frame = hci->frame_no; hcs_urb_queue (hci, urb); } else { urb->start_frame = hci->frame_no + urb->interval; list_add (&urb->urb_list, &hci->waiting_intr_list); hc116x_enable_sofint(hci); } } else { if (dw) FreeDmaWork(hci,dw); //this also wakes anyone waiting on its destruction } return 0; }
static int r8a66597_submit_rh_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, struct devrequest *cmd) { struct r8a66597 *r8a66597 = &gr8a66597; int leni = transfer_len; int len = 0; int stat = 0; __u16 bmRType_bReq; __u16 wValue; __u16 wLength; unsigned char data[32]; R8A66597_DPRINT("%s\n", __func__); if (usb_pipeint(pipe)) { printf("Root-Hub submit IRQ: NOT implemented"); return 0; } bmRType_bReq = cmd->requesttype | (cmd->request << 8); wValue = cpu_to_le16 (cmd->value); wLength = cpu_to_le16 (cmd->length); switch (bmRType_bReq) { case RH_GET_STATUS: *(__u16 *)buffer = cpu_to_le16(1); len = 2; break; case RH_GET_STATUS | RH_INTERFACE: *(__u16 *)buffer = cpu_to_le16(0); len = 2; break; case RH_GET_STATUS | RH_ENDPOINT: *(__u16 *)buffer = cpu_to_le16(0); len = 2; break; case RH_GET_STATUS | RH_CLASS: *(__u32 *)buffer = cpu_to_le32(0); len = 4; break; case RH_GET_STATUS | RH_OTHER | RH_CLASS: *(__u32 *)buffer = cpu_to_le32(r8a66597->port_status | (r8a66597->port_change << 16)); len = 4; break; case RH_CLEAR_FEATURE | RH_ENDPOINT: case RH_CLEAR_FEATURE | RH_CLASS: break; case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: switch (wValue) { case RH_C_PORT_CONNECTION: r8a66597->port_change &= ~USB_PORT_STAT_C_CONNECTION; break; } break; case RH_SET_FEATURE | RH_OTHER | RH_CLASS: switch (wValue) { case (RH_PORT_SUSPEND): break; case (RH_PORT_RESET): r8a66597_bus_reset(r8a66597, 0); break; case (RH_PORT_POWER): break; case (RH_PORT_ENABLE): break; } break; case RH_SET_ADDRESS: gr8a66597.rh_devnum = wValue; break; case RH_GET_DESCRIPTOR: switch ((wValue & 0xff00) >> 8) { case (0x01): /* device descriptor */ len = min_t(unsigned int, leni, min_t(unsigned int, sizeof(root_hub_dev_des), wLength)); memcpy(buffer, root_hub_dev_des, len); break; case (0x02): /* configuration descriptor */ len = min_t(unsigned int, leni, min_t(unsigned int, sizeof(root_hub_config_des), wLength)); memcpy(buffer, root_hub_config_des, len); break; case (0x03): /* string descriptors */ if (wValue == 0x0300) { len = min_t(unsigned int, leni, min_t(unsigned int, sizeof(root_hub_str_index0), wLength)); memcpy(buffer, root_hub_str_index0, len); } if (wValue == 0x0301) { len = min_t(unsigned int, leni, min_t(unsigned int, sizeof(root_hub_str_index1), wLength)); memcpy(buffer, root_hub_str_index1, len); } break; default: stat = USB_ST_STALLED; }
static vsf_err_t vsfusbh_rh_submit_urb(struct vsfusbh_t *usbh, struct vsfusbh_urb_t *vsfurb) { uint16_t typeReq, wValue, wLength; struct usb_ctrlrequest_t *cmd = &vsfurb->setup_packet; uint32_t pipe = vsfurb->pipe; uint8_t data[32]; uint8_t len = 0; if (usb_pipeint(pipe)) { // WARNING: not support int transfer for HUB return VSFERR_NOT_SUPPORT; } vsfurb->actual_length = 0; typeReq = (cmd->bRequestType << 8) | cmd->bRequest; wValue = cmd->wValue; wLength = cmd->wLength; if (wLength > vsfurb->transfer_length) goto error; switch (typeReq) { case DeviceRequest | USB_REQ_GET_STATUS: data[0] = 1; data[1] = 0; len = 2; break; case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: case DeviceOutRequest | USB_REQ_SET_FEATURE: break; case DeviceRequest | USB_REQ_GET_CONFIGURATION: data[0] = 1; len = 1; break; case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: break; case DeviceRequest | USB_REQ_GET_DESCRIPTOR: switch (wValue & 0xff00) { case USB_DT_DEVICE << 8: switch (vsfurb->vsfdev->speed) { case USB_SPEED_LOW: case USB_SPEED_FULL: memcpy (data, usb11_rh_dev_descriptor, 18); break; case USB_SPEED_HIGH: memcpy (data, usb2_rh_dev_descriptor, 18); break; //case USB_SPEED_VARIABLE: // break; //case USB_SPEED_SUPER: // break; default: goto error; } len = 18; break; case USB_DT_CONFIG << 8: switch (vsfurb->vsfdev->speed) { case USB_SPEED_LOW: case USB_SPEED_FULL: len = sizeof(fs_rh_config_descriptor); memcpy (data, fs_rh_config_descriptor, len); break; case USB_SPEED_HIGH: case USB_SPEED_VARIABLE: \ len = sizeof(hs_rh_config_descriptor); memcpy (data, hs_rh_config_descriptor, len); break; //case USB_SPEED_SUPER: // break; default: goto error; } break; case USB_DT_STRING << 8: goto nongeneric; default: goto error; } break; case DeviceRequest | USB_REQ_GET_INTERFACE: data[0] = 0; len = 1; break; case DeviceOutRequest | USB_REQ_SET_INTERFACE: break; case DeviceOutRequest | USB_REQ_SET_ADDRESS: break; case EndpointRequest | USB_REQ_GET_STATUS: data[0] = 0; data[1] = 0; len = 2; break; case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: case EndpointOutRequest | USB_REQ_SET_FEATURE: break; default: nongeneric: return usbh->hcd->rh_control(usbh->hcd_data, vsfurb); } if (len) { if (vsfurb->transfer_length < len) len = vsfurb->transfer_length; vsfurb->actual_length = len; memcpy (vsfurb->transfer_buffer, data, len); } vsfurb->status = URB_OK; vsfsm_post_evt_pending(vsfurb->sm, VSFSM_EVT_URB_COMPLETE); return VSFERR_NONE; error: vsfurb->status = URB_FAIL; return VSFERR_FAIL; }
/* * This function handles all USB request to the the virtual root hub */ static int sl811_rh_submit_urb(struct usb_device *usb_dev, unsigned long pipe, void *data, int buf_len, struct devrequest *cmd) { __u8 data_buf[16]; __u8 *bufp = data_buf; int len = 0; int status = 0; __u16 bmRType_bReq; __u16 wValue = le16_to_cpu (cmd->value); __u16 wLength = le16_to_cpu (cmd->length); #ifdef SL811_DEBUG __u16 wIndex = le16_to_cpu (cmd->index); #endif if (usb_pipeint(pipe)) { PDEBUG(0, "interrupt transfer unimplemented!\n"); return 0; } bmRType_bReq = cmd->requesttype | (cmd->request << 8); PDEBUG(5, "submit rh urb, req = %d(%x) val = %#x index = %#x len=%d\n", bmRType_bReq, bmRType_bReq, wValue, wIndex, wLength); /* Request Destination: without flags: Device, USB_RECIP_INTERFACE: interface, USB_RECIP_ENDPOINT: endpoint, USB_TYPE_CLASS means HUB here, USB_RECIP_OTHER | USB_TYPE_CLASS almost ever means HUB_PORT here */ switch (bmRType_bReq) { case RH_GET_STATUS: *(__u16 *)bufp = cpu_to_le16(1); OK(2); case RH_GET_STATUS | USB_RECIP_INTERFACE: *(__u16 *)bufp = cpu_to_le16(0); OK(2); case RH_GET_STATUS | USB_RECIP_ENDPOINT: *(__u16 *)bufp = cpu_to_le16(0); OK(2); case RH_GET_STATUS | USB_TYPE_CLASS: *(__u32 *)bufp = cpu_to_le32(0); OK(4); case RH_GET_STATUS | USB_RECIP_OTHER | USB_TYPE_CLASS: *(__u32 *)bufp = cpu_to_le32(rh_status.wPortChange<<16 | rh_status.wPortStatus); OK(4); case RH_CLEAR_FEATURE | USB_RECIP_ENDPOINT: switch (wValue) { case 1: OK(0); } break; case RH_CLEAR_FEATURE | USB_TYPE_CLASS: switch (wValue) { case C_HUB_LOCAL_POWER: OK(0); case C_HUB_OVER_CURRENT: OK(0); } break; case RH_CLEAR_FEATURE | USB_RECIP_OTHER | USB_TYPE_CLASS: switch (wValue) { case USB_PORT_FEAT_ENABLE: rh_status.wPortStatus &= ~USB_PORT_STAT_ENABLE; OK(0); case USB_PORT_FEAT_SUSPEND: rh_status.wPortStatus &= ~USB_PORT_STAT_SUSPEND; OK(0); case USB_PORT_FEAT_POWER: rh_status.wPortStatus &= ~USB_PORT_STAT_POWER; OK(0); case USB_PORT_FEAT_C_CONNECTION: rh_status.wPortChange &= ~USB_PORT_STAT_C_CONNECTION; OK(0); case USB_PORT_FEAT_C_ENABLE: rh_status.wPortChange &= ~USB_PORT_STAT_C_ENABLE; OK(0); case USB_PORT_FEAT_C_SUSPEND: rh_status.wPortChange &= ~USB_PORT_STAT_C_SUSPEND; OK(0); case USB_PORT_FEAT_C_OVER_CURRENT: rh_status.wPortChange &= ~USB_PORT_STAT_C_OVERCURRENT; OK(0); case USB_PORT_FEAT_C_RESET: rh_status.wPortChange &= ~USB_PORT_STAT_C_RESET; OK(0); } break; case RH_SET_FEATURE | USB_RECIP_OTHER | USB_TYPE_CLASS: switch (wValue) { case USB_PORT_FEAT_SUSPEND: rh_status.wPortStatus |= USB_PORT_STAT_SUSPEND; OK(0); case USB_PORT_FEAT_RESET: rh_status.wPortStatus |= USB_PORT_STAT_RESET; rh_status.wPortChange = 0; rh_status.wPortChange |= USB_PORT_STAT_C_RESET; rh_status.wPortStatus &= ~USB_PORT_STAT_RESET; rh_status.wPortStatus |= USB_PORT_STAT_ENABLE; OK(0); case USB_PORT_FEAT_POWER: rh_status.wPortStatus |= USB_PORT_STAT_POWER; OK(0); case USB_PORT_FEAT_ENABLE: rh_status.wPortStatus |= USB_PORT_STAT_ENABLE; OK(0); } break; case RH_SET_ADDRESS: root_hub_devnum = wValue; OK(0); case RH_GET_DESCRIPTOR: switch ((wValue & 0xff00) >> 8) { case USB_DT_DEVICE: len = sizeof(sl811_rh_dev_des); bufp = sl811_rh_dev_des; OK(len); case USB_DT_CONFIG: len = sizeof(sl811_rh_config_des); bufp = sl811_rh_config_des; OK(len); case USB_DT_STRING: len = usb_root_hub_string(wValue & 0xff, (int)(long)0, "SL811HS", data, wLength); if (len > 0) { bufp = data; OK(len); } default: status = -32; } break; case RH_GET_DESCRIPTOR | USB_TYPE_CLASS: len = sizeof(sl811_rh_hub_des); bufp = sl811_rh_hub_des; OK(len); case RH_GET_CONFIGURATION: bufp[0] = 0x01; OK(1); case RH_SET_CONFIGURATION: OK(0); default: PDEBUG(1, "unsupported root hub command\n"); status = -32; } len = min(len, buf_len); if (data != bufp) memcpy(data, bufp, len); PDEBUG(5, "len = %d, status = %d\n", len, status); usb_dev->status = status; usb_dev->act_len = len; return status == 0 ? len : status; }
static int dwc_otg_submit_rh_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, struct devrequest *cmd) { int leni = transfer_len; int len = 0; int stat = 0; __u16 bmRType_bReq; __u16 wValue; __u16 wLength; unsigned char data[32]; hprt0_data_t hprt0 = {.d32 = 0 }; if (usb_pipeint(pipe)) { printf("Root-Hub submit IRQ: NOT implemented"); return 0; } bmRType_bReq = cmd->requesttype | (cmd->request << 8); wValue = cpu_to_le16 (cmd->value); wLength = cpu_to_le16 (cmd->length); switch (bmRType_bReq) { case RH_GET_STATUS: *(__u16 *)buffer = cpu_to_le16(1); len = 2; break; case RH_GET_STATUS | RH_INTERFACE: *(__u16 *)buffer = cpu_to_le16(0); len = 2; break; case RH_GET_STATUS | RH_ENDPOINT: *(__u16 *)buffer = cpu_to_le16(0); len = 2; break; case RH_GET_STATUS | RH_CLASS: *(__u32 *)buffer = cpu_to_le32(0); len = 4; break; case RH_GET_STATUS | RH_OTHER | RH_CLASS: { uint32_t port_status = 0; uint32_t port_change = 0; hprt0.d32 = dwc_read_reg32(g_core_if.host_if->hprt0); if (hprt0.b.prtconnsts) port_status |= USB_PORT_STAT_CONNECTION; if (hprt0.b.prtena) port_status |= USB_PORT_STAT_ENABLE; if (hprt0.b.prtsusp) port_status |= USB_PORT_STAT_SUSPEND; if (hprt0.b.prtovrcurract) port_status |= USB_PORT_STAT_OVERCURRENT; if (hprt0.b.prtrst) port_status |= USB_PORT_STAT_RESET; if (hprt0.b.prtpwr) port_status |= USB_PORT_STAT_POWER; port_status |= USB_PORT_STAT_HIGH_SPEED; if (hprt0.b.prtenchng) port_change |= USB_PORT_STAT_C_ENABLE; if (hprt0.b.prtconndet) port_change |= USB_PORT_STAT_C_CONNECTION; if (hprt0.b.prtovrcurrchng) port_change |= USB_PORT_STAT_C_OVERCURRENT; *(__u32 *)buffer = cpu_to_le32(port_status | (port_change << 16)); len = 4; } break; case RH_CLEAR_FEATURE | RH_ENDPOINT: case RH_CLEAR_FEATURE | RH_CLASS: break; case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: switch (wValue) { case RH_C_PORT_CONNECTION: hprt0.d32 = dwc_read_reg32(g_core_if.host_if->hprt0); hprt0.b.prtconndet = 1; dwc_write_reg32(g_core_if.host_if->hprt0, hprt0.d32); break; } break; case RH_SET_FEATURE | RH_OTHER | RH_CLASS: switch (wValue) { case (RH_PORT_SUSPEND): break; case (RH_PORT_RESET): hprt0.d32 = dwc_otg_read_hprt0(&g_core_if); hprt0.b.prtrst = 1; dwc_write_reg32(g_core_if.host_if->hprt0, hprt0.d32); mdelay(50); hprt0.b.prtrst = 0; dwc_write_reg32(g_core_if.host_if->hprt0, hprt0.d32); break; case (RH_PORT_POWER): hprt0.d32 = dwc_otg_read_hprt0(&g_core_if); hprt0.b.prtpwr = 1; dwc_write_reg32(g_core_if.host_if->hprt0, hprt0.d32); break; case (RH_PORT_ENABLE): break; } break; case RH_SET_ADDRESS: root_hub_devnum = wValue; break; case RH_GET_DESCRIPTOR: switch ((wValue & 0xff00) >> 8) { case (0x01): /* device descriptor */ len = min_t(unsigned int, leni, min_t(unsigned int, sizeof(root_hub_dev_des), wLength)); memcpy(buffer, root_hub_dev_des, len); break; case (0x02): /* configuration descriptor */ len = min_t(unsigned int, leni, min_t(unsigned int, sizeof(root_hub_config_des), wLength)); memcpy(buffer, root_hub_config_des, len); break; case (0x03): /* string descriptors */ if (wValue == 0x0300) { len = min_t(unsigned int, leni, min_t(unsigned int, sizeof(root_hub_str_index0), wLength)); memcpy(buffer, root_hub_str_index0, len); } if (wValue == 0x0301) { len = min_t(unsigned int, leni, min_t(unsigned int, sizeof(root_hub_str_index1), wLength)); memcpy(buffer, root_hub_str_index1, len); } break; default: stat = USB_ST_STALLED; } break; case RH_GET_DESCRIPTOR | RH_CLASS: { __u32 temp = 0x00000001; data[0] = 9; /* min length; */ data[1] = 0x29; data[2] = temp & RH_A_NDP; data[3] = 0; if (temp & RH_A_PSM) data[3] |= 0x1; if (temp & RH_A_NOCP) data[3] |= 0x10; else if (temp & RH_A_OCPM) data[3] |= 0x8; /* corresponds to data[4-7] */ data[5] = (temp & RH_A_POTPGT) >> 24; data[7] = temp & RH_B_DR; if (data[2] < 7) { data[8] = 0xff; } else { data[0] += 2; data[8] = (temp & RH_B_DR) >> 8; data[10] = data[9] = 0xff; } len = min_t(unsigned int, leni, min_t(unsigned int, data[0], wLength)); memcpy(buffer, data, len); break; } case RH_GET_CONFIGURATION: *(__u8 *) buffer = 0x01; len = 1; break; case RH_SET_CONFIGURATION: break; default: printf("unsupported root hub command\n"); stat = USB_ST_STALLED; }
/* Set up PTD's. */ static void prepare_ptd(struct isp1362_hcd *isp1362_hcd, struct urb *urb, struct isp1362_ep *ep, struct isp1362_ep_queue *epq, u16 fno) { struct ptd *ptd; int toggle; int dir; u16 len; size_t buf_len = urb->transfer_buffer_length - urb->actual_length; DBG(3, "%s: %s ep %p\n", __func__, epq->name, ep); ptd = &ep->ptd; ep->data = (unsigned char *)urb->transfer_buffer + urb->actual_length; switch (ep->nextpid) { case USB_PID_IN: toggle = usb_gettoggle(urb->dev, ep->epnum, 0); dir = PTD_DIR_IN; if (usb_pipecontrol(urb->pipe)) { len = min_t(size_t, ep->maxpacket, buf_len); } else if (usb_pipeisoc(urb->pipe)) { len = min_t(size_t, urb->iso_frame_desc[fno].length, MAX_XFER_SIZE); ep->data = urb->transfer_buffer + urb->iso_frame_desc[fno].offset; } else len = max_transfer_size(epq, buf_len, ep->maxpacket); DBG(1, "%s: IN len %d/%d/%d from URB\n", __func__, len, ep->maxpacket, (int)buf_len); break; case USB_PID_OUT: toggle = usb_gettoggle(urb->dev, ep->epnum, 1); dir = PTD_DIR_OUT; if (usb_pipecontrol(urb->pipe)) len = min_t(size_t, ep->maxpacket, buf_len); else if (usb_pipeisoc(urb->pipe)) len = min_t(size_t, urb->iso_frame_desc[0].length, MAX_XFER_SIZE); else len = max_transfer_size(epq, buf_len, ep->maxpacket); if (len == 0) pr_info("%s: Sending ZERO packet: %d\n", __func__, urb->transfer_flags & URB_ZERO_PACKET); DBG(1, "%s: OUT len %d/%d/%d from URB\n", __func__, len, ep->maxpacket, (int)buf_len); break; case USB_PID_SETUP: toggle = 0; dir = PTD_DIR_SETUP; len = sizeof(struct usb_ctrlrequest); DBG(1, "%s: SETUP len %d\n", __func__, len); ep->data = urb->setup_packet; break; case USB_PID_ACK: toggle = 1; len = 0; dir = (urb->transfer_buffer_length && usb_pipein(urb->pipe)) ? PTD_DIR_OUT : PTD_DIR_IN; DBG(1, "%s: ACK len %d\n", __func__, len); break; default: toggle = dir = len = 0; pr_err("%s@%d: ep->nextpid %02x\n", __func__, __LINE__, ep->nextpid); BUG_ON(1); } ep->length = len; if (!len) ep->data = NULL; ptd->count = PTD_CC_MSK | PTD_ACTIVE_MSK | PTD_TOGGLE(toggle); ptd->mps = PTD_MPS(ep->maxpacket) | PTD_SPD(urb->dev->speed == USB_SPEED_LOW) | PTD_EP(ep->epnum); ptd->len = PTD_LEN(len) | PTD_DIR(dir); ptd->faddr = PTD_FA(usb_pipedevice(urb->pipe)); if (usb_pipeint(urb->pipe)) { ptd->faddr |= PTD_SF_INT(ep->branch); ptd->faddr |= PTD_PR(ep->interval ? __ffs(ep->interval) : 0); } if (usb_pipeisoc(urb->pipe)) ptd->faddr |= PTD_SF_ISO(fno); DBG(1, "%s: Finished\n", __func__); }
/*************************************************************************** * Function Name : rh_submit_urb * * This function handles all USB request to the the virtual root hub * * Input: urb = USB request block * * Return: 0 **************************************************************************/ static int rh_submit_urb (struct urb * urb) { struct usb_device *usb_dev = urb->dev; hci_t *hci = usb_dev->bus->hcpriv; unsigned int pipe = urb->pipe; struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) urb->setup_packet; void *data = urb->transfer_buffer; int leni = urb->transfer_buffer_length; int len = 0; int status = TD_CC_NOERROR; __u32 datab[4]; __u8 *data_buf = (__u8 *) datab; __u16 bmRType_bReq; __u16 wValue; __u16 wIndex; __u16 wLength; DBGFUNC ("enter rh_submit_urb\n"); if (usb_pipeint (pipe)) { hci->rh.urb = urb; hci->rh.send = 1; hci->rh.interval = urb->interval; rh_init_int_timer (urb); urb->status = cc_to_error (TD_CC_NOERROR); return 0; } bmRType_bReq = cmd->bRequestType | (cmd->bRequest << 8); wValue = le16_to_cpu (cmd->wValue); wIndex = le16_to_cpu (cmd->wIndex); wLength = le16_to_cpu (cmd->wLength); DBG ("rh_submit_urb, req = %d(%x) len=%d", bmRType_bReq, bmRType_bReq, wLength); switch (bmRType_bReq) { /* Request Destination: without flags: Device, RH_INTERFACE: interface, RH_ENDPOINT: endpoint, RH_CLASS means HUB here, RH_OTHER | RH_CLASS almost ever means HUB_PORT here */ case RH_GET_STATUS: *(__u16 *) data_buf = cpu_to_le16 (1); OK (2); case RH_GET_STATUS | RH_INTERFACE: *(__u16 *) data_buf = cpu_to_le16 (0); OK (2); case RH_GET_STATUS | RH_ENDPOINT: *(__u16 *) data_buf = cpu_to_le16 (0); OK (2); case RH_GET_STATUS | RH_CLASS: *(__u32 *) data_buf = cpu_to_le32 (0); OK (4); case RH_GET_STATUS | RH_OTHER | RH_CLASS: *(__u32 *) data_buf = cpu_to_le32 (getPortStatusAndChange (hci)); OK (4); case RH_CLEAR_FEATURE | RH_ENDPOINT: switch (wValue) { case (RH_ENDPOINT_STALL): OK (0); } break; case RH_CLEAR_FEATURE | RH_CLASS: switch (wValue) { case RH_C_HUB_LOCAL_POWER: OK (0); case (RH_C_HUB_OVER_CURRENT): /* Over Current Not Implemented */ OK (0); } break; case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: switch (wValue) { case (RH_PORT_ENABLE): clrPortStatus (hci, PORT_ENABLE_STAT); OK (0); case (RH_PORT_SUSPEND): clrPortStatus (hci, PORT_SUSPEND_STAT); OK (0); case (RH_PORT_POWER): clrPortStatus (hci, PORT_POWER_STAT); OK (0); case (RH_C_PORT_CONNECTION): clrPortChange (hci, PORT_CONNECT_STAT); OK (0); case (RH_C_PORT_ENABLE): clrPortChange (hci, PORT_ENABLE_STAT); OK (0); case (RH_C_PORT_SUSPEND): clrPortChange (hci, PORT_SUSPEND_STAT); OK (0); case (RH_C_PORT_OVER_CURRENT): clrPortChange (hci, PORT_OVER_CURRENT_STAT); OK (0); case (RH_C_PORT_RESET): clrPortChange (hci, PORT_RESET_STAT); OK (0); } break; case RH_SET_FEATURE | RH_OTHER | RH_CLASS: switch (wValue) { case (RH_PORT_SUSPEND): setPortStatus (hci, PORT_SUSPEND_STAT); OK (0); case (RH_PORT_RESET): setPortStatus (hci, PORT_RESET_STAT); // USBReset(hci); clrPortChange (hci, PORT_CONNECT_CHANGE | PORT_ENABLE_CHANGE | PORT_SUSPEND_CHANGE | PORT_OVER_CURRENT_CHANGE); setPortChange (hci, PORT_RESET_CHANGE); clrPortStatus (hci, PORT_RESET_STAT); setPortStatus (hci, PORT_ENABLE_STAT); OK (0); case (RH_PORT_POWER): setPortStatus (hci, PORT_POWER_STAT); OK (0); case (RH_PORT_ENABLE): setPortStatus (hci, PORT_ENABLE_STAT); OK (0); } break; case RH_SET_ADDRESS: hci->rh.devnum = wValue; OK (0); case RH_GET_DESCRIPTOR: DBGVERBOSE ("rh_submit_urb: RH_GET_DESCRIPTOR, wValue = 0x%x\n", wValue); switch ((wValue & 0xff00) >> 8) { case (0x01): /* device descriptor */ len = min (leni, min ((__u16)sizeof (root_hub_dev_des), wLength)); data_buf = root_hub_dev_des; OK (len); case (0x02): /* configuration descriptor */ len = min (leni, min ((__u16)sizeof (root_hub_config_des), wLength)); data_buf = root_hub_config_des; OK (len); case (0x03): /* string descriptors */ len = root_hub_string (wValue & 0xff, (int) (long) 0, "SL811HS", data, wLength); if (len > 0) { data_buf = data; OK (min (leni, len)); } default: status = SL11H_STATMASK_STALL; } break; case RH_GET_DESCRIPTOR | RH_CLASS: data_buf[0] = 9; // min length; data_buf[1] = 0x29; data_buf[2] = 1; // # of downstream port data_buf[3] = 0; datab[1] = 0; data_buf[5] = 50; // 100 ms for port reset data_buf[7] = 0xfc; // which port is attachable if (data_buf[2] < 7) { data_buf[8] = 0xff; } else { } len = min (leni, min ((__u16)data_buf[0], wLength)); OK (len); case RH_GET_CONFIGURATION: *(__u8 *) data_buf = 0x01; OK (1); case RH_SET_CONFIGURATION: OK (0); default: DBGERR ("unsupported root hub command"); status = SL11H_STATMASK_STALL; } len = min (len, leni); if (data != data_buf) memcpy (data, data_buf, len); urb->actual_length = len; urb->status = cc_to_error (status); urb->hcpriv = NULL; urb->dev = NULL; if (urb->complete) { urb->complete (urb, NULL); } return 0; }
int32 USBHost::aranym_submit_rh_msg(uint32 pipe, memptr buffer, int32 transfer_len, devrequest *cmd) { D(bug("USBHost: aranym_submit_rh_msg()")); int32 leni = transfer_len; int32 len = 0; uint32 datab[4]; uint8 *data_buf = (uint8 *) datab; int32 stat = 0; uint16 bmRType_bReq; uint16 wValue; uint16 wIndex; uint16 wLength; if (usb_pipeint(pipe)) { D(bug("USBHost: Root-Hub submit IRQ: NOT implemented")); return -1; } bmRType_bReq = cmd->requesttype | (cmd->request << 8); wValue = cmd->value; wIndex = cmd->index; wLength = cmd->length; D(bug("USBHost: --- HUB ----------------------------------------")); D(bug("USBHost: submit rh urb, req=%x val=%#x index=%#x len=%d", bmRType_bReq, wValue, wIndex, wLength)); D(bug("USBHost: ------------------------------------------------")); switch (bmRType_bReq) { case RH_GET_STATUS: D(bug("USBHost: RH_GET_STATUS")); *data_buf = (SDL_BYTEORDER == SDL_BIG_ENDIAN) ? (uint16) SDL_Swap16(1) : (uint16)(1) ; len = 2; break; case RH_GET_STATUS | RH_INTERFACE: D(bug("USBHost: RH_GET_STATUS | RH_INTERFACE")); *data_buf = (SDL_BYTEORDER == SDL_BIG_ENDIAN) ? (uint16) SDL_Swap16(0) : (uint16)(0) ; len = 2; break; case RH_GET_STATUS | RH_ENDPOINT: D(bug("USBHost: RH_GET_STATUS | RH_ENDPOINT")); *data_buf = (SDL_BYTEORDER == SDL_BIG_ENDIAN) ? (uint16) SDL_Swap16(0) : (uint16)(0) ; len = 2; break; case RH_GET_STATUS | RH_CLASS: D(bug("USBHost: RH_GET_STATUS | RH_CLASS")); data_buf = root_hub_class_st; len = 4; break; case RH_GET_STATUS | RH_OTHER | RH_CLASS: D(bug("USBHost: RH_GET_STATUS | RH_OTHER | RH_CLASS")); *(uint32 *)data_buf = (SDL_BYTEORDER == SDL_BIG_ENDIAN) ? SDL_Swap32(port_status[wIndex - 1]) : port_status[wIndex - 1]; len = 4; break; case RH_CLEAR_FEATURE | RH_ENDPOINT: D(bug("USBHost: RH_CLEAR_FEATURE | RH_ENDPOINT")); switch (wValue) { case RH_ENDPOINT_STALL: D(bug("USBHost: C_HUB_ENDPOINT_STALL")); len = 0; break; } break; case RH_CLEAR_FEATURE | RH_CLASS: D(bug("USBHost: RH_CLEAR_FEATURE | RH_CLASS")); switch (wValue) { case RH_C_HUB_LOCAL_POWER: D(bug("USBHost: C_HUB_LOCAL_POWER")); len = 0; break; case RH_C_HUB_OVER_CURRENT: D(bug("USBHost: C_HUB_OVER_CURRENT")); len = 0; break; } break; case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: D(bug("USBHost: RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS")); switch (wValue) { case RH_PORT_ENABLE: port_status[wIndex - 1] &= ~RH_PS_PES; len = 0; break; case RH_PORT_SUSPEND: port_status[wIndex - 1] |= RH_PS_PSS; len = 0; break; case RH_PORT_POWER: len = 0; break; case RH_C_PORT_CONNECTION: port_status[wIndex - 1] &= ~RH_PS_CSC; len = 0; break; case RH_C_PORT_ENABLE: port_status[wIndex - 1] &= ~RH_PS_PESC; len = 0; break; case RH_C_PORT_SUSPEND: len = 0; break; case RH_C_PORT_OVER_CURRENT: port_status[wIndex - 1] &= ~RH_PS_OCIC; len = 0; break; case RH_C_PORT_RESET: port_status[wIndex - 1] &= ~RH_PS_PRSC; len = 0; break; default: D(bug("USBHost: invalid wValue")); stat = USB_ST_STALLED; } break; case RH_SET_FEATURE | RH_OTHER | RH_CLASS: D(bug("USBHost: RH_SET_FEATURE | RH_OTHER | RH_CLASS")); switch (wValue) { case RH_PORT_SUSPEND: len = 0; break; case RH_PORT_RESET: port_status[wIndex - 1] |= RH_PS_PRS; len = 0; break; case RH_PORT_POWER: port_status[wIndex - 1] |= RH_PS_PPS; len = 0; break; case RH_PORT_ENABLE: len = 0; break; default: D(bug("USBHost: invalid wValue")); stat = USB_ST_STALLED; } break; case RH_SET_ADDRESS: D(bug("USBHost: RH_SET_ADDRESS")); rh_devnum = wValue; len = 0; break; case RH_GET_DESCRIPTOR: D(bug("USBHost: RH_GET_DESCRIPTOR: %x, %d", wValue, wLength)); switch (wValue) { case (USB_DT_DEVICE << 8): /* device descriptor */ len = min1_t(uint32, leni, min2_t(uint32, sizeof(root_hub_dev_des), wLength)); data_buf = root_hub_dev_des; break; case (USB_DT_CONFIG << 8): /* configuration descriptor */ len = min1_t(uint32, leni, min2_t(uint32, sizeof(root_hub_config_des), wLength)); data_buf = root_hub_config_des; break; case ((USB_DT_STRING << 8) | 0x00): /* string 0 descriptors */ len = min1_t(uint32, leni, min2_t(uint32, sizeof(root_hub_str_index0), wLength)); data_buf = root_hub_str_index0; break; case ((USB_DT_STRING << 8) | 0x01): /* string 1 descriptors */ len = min1_t(uint32, leni, min2_t(uint32, sizeof(root_hub_str_index1), wLength)); data_buf = root_hub_str_index1; break; default: D(bug("USBHost: invalid wValue")); stat = USB_ST_STALLED; } break; case RH_GET_DESCRIPTOR | RH_CLASS: D(bug("USBHost: RH_GET_DESCRIPTOR | RH_CLASS")); data_buf = root_hub_class_des; len = min1_t(uint32, leni, min2_t(uint32, data_buf[0], wLength)); break; case RH_GET_CONFIGURATION: D(bug("USBHost: RH_GET_CONFIGURATION")); *(uint8 *) data_buf = 0x01; len = 1; break; case RH_SET_CONFIGURATION: D(bug("USBHost: RH_SET_CONFIGURATION")); len = 0; break; default: D(bug("USBHost: *** *** *** unsupported root hub command *** *** ***")); stat = USB_ST_STALLED; } len = min1_t(int32, len, leni); if(buffer != 0) Host2Atari_memcpy(buffer, data_buf, len); return (stat ? -1 : len); }