📄 au1x00_usb_ohci.c
字号:
0x10, /* __u16 bcdUSB; v1.1 */ 0x01, 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ 0x00, /* __u8 bDeviceSubClass; */ 0x00, /* __u8 bDeviceProtocol; */ 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ 0x00, /* __u16 idVendor; */ 0x00, 0x00, /* __u16 idProduct; */ 0x00, 0x00, /* __u16 bcdDevice; */ 0x00, 0x00, /* __u8 iManufacturer; */ 0x01, /* __u8 iProduct; */ 0x00, /* __u8 iSerialNumber; */ 0x01 /* __u8 bNumConfigurations; */};/* Configuration descriptor */static __u8 root_hub_config_des[] ={ 0x09, /* __u8 bLength; */ 0x02, /* __u8 bDescriptorType; Configuration */ 0x19, /* __u16 wTotalLength; */ 0x00, 0x01, /* __u8 bNumInterfaces; */ 0x01, /* __u8 bConfigurationValue; */ 0x00, /* __u8 iConfiguration; */ 0x40, /* __u8 bmAttributes; Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ 0x00, /* __u8 MaxPower; */ /* interface */ 0x09, /* __u8 if_bLength; */ 0x04, /* __u8 if_bDescriptorType; Interface */ 0x00, /* __u8 if_bInterfaceNumber; */ 0x00, /* __u8 if_bAlternateSetting; */ 0x01, /* __u8 if_bNumEndpoints; */ 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ 0x00, /* __u8 if_bInterfaceSubClass; */ 0x00, /* __u8 if_bInterfaceProtocol; */ 0x00, /* __u8 if_iInterface; */ /* endpoint */ 0x07, /* __u8 ep_bLength; */ 0x05, /* __u8 ep_bDescriptorType; Endpoint */ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ 0x03, /* __u8 ep_bmAttributes; Interrupt */ 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */ 0x00, 0xff /* __u8 ep_bInterval; 255 ms */};static unsigned char root_hub_str_index0[] ={ 0x04, /* __u8 bLength; */ 0x03, /* __u8 bDescriptorType; String-descriptor */ 0x09, /* __u8 lang ID */ 0x04, /* __u8 lang ID */};static unsigned char root_hub_str_index1[] ={ 28, /* __u8 bLength; */ 0x03, /* __u8 bDescriptorType; String-descriptor */ 'O', /* __u8 Unicode */ 0, /* __u8 Unicode */ 'H', /* __u8 Unicode */ 0, /* __u8 Unicode */ 'C', /* __u8 Unicode */ 0, /* __u8 Unicode */ 'I', /* __u8 Unicode */ 0, /* __u8 Unicode */ ' ', /* __u8 Unicode */ 0, /* __u8 Unicode */ 'R', /* __u8 Unicode */ 0, /* __u8 Unicode */ 'o', /* __u8 Unicode */ 0, /* __u8 Unicode */ 'o', /* __u8 Unicode */ 0, /* __u8 Unicode */ 't', /* __u8 Unicode */ 0, /* __u8 Unicode */ ' ', /* __u8 Unicode */ 0, /* __u8 Unicode */ 'H', /* __u8 Unicode */ 0, /* __u8 Unicode */ 'u', /* __u8 Unicode */ 0, /* __u8 Unicode */ 'b', /* __u8 Unicode */ 0, /* __u8 Unicode */};/* Hub class-specific descriptor is constructed dynamically *//*-------------------------------------------------------------------------*/#define OK(x) len = (x); break#ifdef DEBUG#define WR_RH_STAT(x) {info("WR:status %#8x", (x));writel((x), &gohci.regs->roothub.status);}#define WR_RH_PORTSTAT(x) {info("WR:portstatus[%d] %#8x", wIndex-1, (x));writel((x), &gohci.regs->roothub.portstatus[wIndex-1]);}#else#define WR_RH_STAT(x) writel((x), &gohci.regs->roothub.status)#define WR_RH_PORTSTAT(x) writel((x), &gohci.regs->roothub.portstatus[wIndex-1])#endif#define RD_RH_STAT roothub_status(&gohci)#define RD_RH_PORTSTAT roothub_portstatus(&gohci,wIndex-1)/* request to virtual root hub */int rh_check_port_status(ohci_t *controller){ __u32 temp, ndp, i; int res; res = -1; temp = roothub_a (controller); ndp = (temp & RH_A_NDP); for (i = 0; i < ndp; i++) { temp = roothub_portstatus (controller, i); /* check for a device disconnect */ if (((temp & (RH_PS_PESC | RH_PS_CSC)) == (RH_PS_PESC | RH_PS_CSC)) && ((temp & RH_PS_CCS) == 0)) { res = i; break; } } return res;}static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, struct devrequest *cmd){ void * data = buffer; int leni = transfer_len; int len = 0; int stat = 0; __u32 datab[4]; __u8 *data_buf = (__u8 *)datab; __u16 bmRType_bReq; __u16 wValue; __u16 wIndex; __u16 wLength;#ifdef DEBUGurb_priv.actual_length = 0;pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe));#else wait_ms(1);#endif if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) { info("Root-Hub submit IRQ: NOT implemented"); return 0; } bmRType_bReq = cmd->requesttype | (cmd->request << 8); wValue = m16_swap (cmd->value); wIndex = m16_swap (cmd->index); wLength = m16_swap (cmd->length); info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x", dev->devnum, 8, bmRType_bReq, wValue, wIndex, 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 = m16_swap (1); OK (2); case RH_GET_STATUS | RH_INTERFACE: *(__u16 *) data_buf = m16_swap (0); OK (2); case RH_GET_STATUS | RH_ENDPOINT: *(__u16 *) data_buf = m16_swap (0); OK (2); case RH_GET_STATUS | RH_CLASS: *(__u32 *) data_buf = m32_swap ( RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); OK (4); case RH_GET_STATUS | RH_OTHER | RH_CLASS: *(__u32 *) data_buf = m32_swap (RD_RH_PORTSTAT); 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): WR_RH_STAT(RH_HS_OCIC); OK (0); } break; case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: switch (wValue) { case (RH_PORT_ENABLE): WR_RH_PORTSTAT (RH_PS_CCS ); OK (0); case (RH_PORT_SUSPEND): WR_RH_PORTSTAT (RH_PS_POCI); OK (0); case (RH_PORT_POWER): WR_RH_PORTSTAT (RH_PS_LSDA); OK (0); case (RH_C_PORT_CONNECTION): WR_RH_PORTSTAT (RH_PS_CSC ); OK (0); case (RH_C_PORT_ENABLE): WR_RH_PORTSTAT (RH_PS_PESC); OK (0); case (RH_C_PORT_SUSPEND): WR_RH_PORTSTAT (RH_PS_PSSC); OK (0); case (RH_C_PORT_OVER_CURRENT): WR_RH_PORTSTAT (RH_PS_OCIC); OK (0); case (RH_C_PORT_RESET): WR_RH_PORTSTAT (RH_PS_PRSC); OK (0); } break; case RH_SET_FEATURE | RH_OTHER | RH_CLASS: switch (wValue) { case (RH_PORT_SUSPEND): WR_RH_PORTSTAT (RH_PS_PSS ); OK (0); case (RH_PORT_RESET): /* BUG IN HUP CODE *********/ if (RD_RH_PORTSTAT & RH_PS_CCS) WR_RH_PORTSTAT (RH_PS_PRS); OK (0); case (RH_PORT_POWER): WR_RH_PORTSTAT (RH_PS_PPS ); OK (0); case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/ if (RD_RH_PORTSTAT & RH_PS_CCS) WR_RH_PORTSTAT (RH_PS_PES ); OK (0); } break; case RH_SET_ADDRESS: gohci.rh.devnum = wValue; OK(0); 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)); data_buf = root_hub_dev_des; OK(len); case (0x02): /* configuration descriptor */ len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_config_des), wLength)); data_buf = root_hub_config_des; OK(len); case (0x03): /* string descriptors */ if(wValue==0x0300) { len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_str_index0), wLength)); data_buf = root_hub_str_index0; OK(len); } if(wValue==0x0301) { len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_str_index1), wLength)); data_buf = root_hub_str_index1; OK(len); } default: stat = USB_ST_STALLED; } break; case RH_GET_DESCRIPTOR | RH_CLASS: { __u32 temp = roothub_a (&gohci); data_buf [0] = 9; /* min length; */ data_buf [1] = 0x29; data_buf [2] = temp & RH_A_NDP; data_buf [3] = 0; if (temp & RH_A_PSM) /* per-port power switching? */ data_buf [3] |= 0x1; if (temp & RH_A_NOCP) /* no overcurrent reporting? */ data_buf [3] |= 0x10; else if (temp & RH_A_OCPM) /* per-port overcurrent reporting? */ data_buf [3] |= 0x8; /* corresponds to data_buf[4-7] */ datab [1] = 0; data_buf [5] = (temp & RH_A_POTPGT) >> 24; temp = roothub_b (&gohci); data_buf [7] = temp & RH_B_DR; if (data_buf [2] < 7) { data_buf [8] = 0xff; } else { data_buf [0] += 2; data_buf [8] = (temp & RH_B_DR) >> 8; data_buf [10] = data_buf [9] = 0xff; } len = min_t(unsigned int, leni, min_t(unsigned int, data_buf [0], wLength)); OK (len); } case RH_GET_CONFIGURATION: *(__u8 *) data_buf = 0x01; OK (1); case RH_SET_CONFIGURATION: WR_RH_STAT (0x10000); OK (0); default: dbg ("unsupported root hub command"); stat = USB_ST_STALLED; }#ifdef DEBUG ohci_dump_roothub (&gohci, 1);#else wait_ms(1);#endif len = min_t(int, len, leni); if (data != data_buf) memcpy (data, data_buf, len); dev->act_len = len; dev->status = stat;#ifdef DEBUG if (transfer_len) urb_priv.actual_length = transfer_len; pkt_print(dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/);#else wait_ms(1);#endif return stat;}/*-------------------------------------------------------------------------*//* common code for handling submit messages - used for all but root hub *//* accesses. */int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, struct devrequest *setup, int interval){ int stat = 0; int maxsize = usb_maxpacket(dev, pipe); int timeout; /* device pulled? Shortcut the action. */ if (devgone == dev) { dev->status = USB_ST_CRC_ERR; return 0; }#ifdef DEBUG urb_priv.actual_length = 0; pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));#else wait_ms(1);#endif if (!maxsize) { err("submit_common_message: pipesize for pipe %lx is zero", pipe); return -1; } if (sohci_submit_job(dev, pipe, buffer, transfer_len, setup, interval) < 0) { err("sohci_submit_job failed"); return -1; } wait_ms(10); /* ohci_dump_status(&gohci); */ /* allow more time for a BULK device to react - some are slow */#define BULK_TO 5000 /* timeout in milliseconds */ if (usb_pipetype (pipe) == PIPE_BULK) timeout = BULK_TO; else timeout = 100; timeout *= 4; /* wait for it to complete */ for (;;) { /* check whether the controller is done */ stat = hc_interrupt(); if (stat < 0) { stat = USB_ST_CRC_ERR; break; } if (stat >= 0 && stat != 0xff) { /* 0xff is returned for an SF-interrupt */ break; } if (--timeout) { udelay(250); /* wait_ms(1); */ } else { err("CTL:TIMEOUT "); stat = USB_ST_CRC_ERR; break; } } /* we got an Root Hub Status Change interrupt */ if (got_rhsc) {#ifdef DEBUG ohci_dump_roothub (&gohci, 1);#endif got_rhsc = 0; /* abuse timeout */ timeout = rh_check_port_status(&gohci); if (timeout >= 0) {#if 0 /* this does nothing useful, but leave it here in case that changes */ /* the called routine adds 1 to the passed value */ usb_hub_port_connect_change(gohci.rh.dev, timeout - 1);#endif /* * XXX * This is potentially dangerous because it assumes * that only one device is ever plugged in! */ devgone = dev;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -