📄 r8a66597-hcd.c
字号:
return -1; return 0;}static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port){ int count = R8A66597_MAX_SAMPLING; unsigned short syssts, old_syssts; R8A66597_DPRINT("%s\n", __func__); old_syssts = r8a66597_read(r8a66597, get_syssts_reg(port) & LNST); while (count > 0) { wait_ms(R8A66597_RH_POLL_TIME); syssts = r8a66597_read(r8a66597, get_syssts_reg(port) & LNST); if (syssts == old_syssts) { count--; } else { count = R8A66597_MAX_SAMPLING; old_syssts = syssts; } }}static void r8a66597_bus_reset(struct r8a66597 *r8a66597, int port){ wait_ms(10); r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT, get_dvstctr_reg(port)); wait_ms(50); r8a66597_mdfy(r8a66597, UACT, USBRST | UACT, get_dvstctr_reg(port)); wait_ms(50);}static int check_usb_device_connecting(struct r8a66597 *r8a66597){ int timeout = 10000; /* 100usec * 10000 = 1sec */ int i; for (i = 0; i < 5; i++) { /* check a usb cable connect */ while (!(r8a66597_read(r8a66597, INTSTS1) & ATTCH)) { if (timeout-- < 0) { printf("%s timeout.\n", __func__); return -1; } udelay(100); } /* check a data line */ r8a66597_check_syssts(r8a66597, 0); r8a66597_bus_reset(r8a66597, 0); r8a66597->speed = get_rh_usb_speed(r8a66597, 0); if (!(r8a66597_read(r8a66597, INTSTS1) & DTCH)) { r8a66597->port_change = USB_PORT_STAT_C_CONNECTION; r8a66597->port_status = USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE; return 0; /* success */ } R8A66597_DPRINT("USB device has detached. retry = %d\n", i); r8a66597_write(r8a66597, ~DTCH, INTSTS1); } return -1; /* fail */}/* based on usb_ohci.c */#define min_t(type, x, y) \ ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })/*-------------------------------------------------------------------------* * Virtual Root Hub *-------------------------------------------------------------------------*//* Device descriptor */static __u8 root_hub_dev_des[] ={ 0x12, /* __u8 bLength; */ 0x01, /* __u8 bDescriptorType; Device */ 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; */ 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[] ={ 34, /* __u8 bLength; */ 0x03, /* __u8 bDescriptorType; String-descriptor */ 'R', /* __u8 Unicode */ 0, /* __u8 Unicode */ '8', /* __u8 Unicode */ 0, /* __u8 Unicode */ 'A', /* __u8 Unicode */ 0, /* __u8 Unicode */ '6', /* __u8 Unicode */ 0, /* __u8 Unicode */ '6', /* __u8 Unicode */ 0, /* __u8 Unicode */ '5', /* __u8 Unicode */ 0, /* __u8 Unicode */ '9', /* __u8 Unicode */ 0, /* __u8 Unicode */ '7', /* __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 */ 'H', /* __u8 Unicode */ 0, /* __u8 Unicode */ 'u', /* __u8 Unicode */ 0, /* __u8 Unicode */ 'b', /* __u8 Unicode */ 0, /* __u8 Unicode */};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 wIndex; __u16 wLength; unsigned char data[32]; R8A66597_DPRINT("%s\n", __func__); if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) { printf("Root-Hub submit IRQ: NOT implemented"); return 0; } bmRType_bReq = cmd->requesttype | (cmd->request << 8); wValue = cpu_to_le16 (cmd->value); wIndex = cpu_to_le16 (cmd->index); 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; } 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: dbg("unsupported root hub command"); stat = USB_ST_STALLED; } wait_ms(1); len = min_t(int, len, leni); dev->act_len = len; dev->status = stat; return stat;}int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len){ struct r8a66597 *r8a66597 = &gr8a66597; int ret = 0; R8A66597_DPRINT("%s\n", __func__); R8A66597_DPRINT("pipe = %08x, buffer = %p, len = %d, devnum = %d\n", pipe, buffer, transfer_len, dev->devnum); set_devadd_reg(r8a66597, dev->devnum, r8a66597->speed, 0, 0, 0); pipe_buffer_setting(r8a66597, dev, pipe); dev->act_len = 0; while (dev->act_len < transfer_len && ret == 0) { if (ctrlc()) return -1; if (usb_pipein(pipe)) ret = receive_bulk_packet(r8a66597, dev, pipe, buffer, transfer_len); else ret = send_bulk_packet(r8a66597, dev, pipe, buffer, transfer_len); } if (ret == 0) dev->status = 0; return ret;}int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, struct devrequest *setup){ struct r8a66597 *r8a66597 = &gr8a66597; u16 r8a66597_address = setup->request == USB_REQ_SET_ADDRESS ? 0 : dev->devnum; R8A66597_DPRINT("%s\n", __func__); if (usb_pipedevice(pipe) == r8a66597->rh_devnum) return r8a66597_submit_rh_msg(dev, pipe, buffer, transfer_len, setup); R8A66597_DPRINT("%s: setup\n", __func__); set_devadd_reg(r8a66597, r8a66597_address, r8a66597->speed, 0, 0, 0); if (send_setup_packet(r8a66597, dev, setup) < 0) { printf("setup packet send error\n"); return -1; } if (usb_pipein(pipe)) if (receive_control_packet(r8a66597, dev, buffer, transfer_len) < 0) return -1; if (send_status_packet(r8a66597, pipe) < 0) return -1; dev->status = 0; return 0;}int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, int interval){ /* no implement */ R8A66597_DPRINT("%s\n", __func__); return 0;}void usb_event_poll(void){ /* no implement */ R8A66597_DPRINT("%s\n", __func__);}int usb_lowlevel_init(void){ struct r8a66597 *r8a66597 = &gr8a66597; R8A66597_DPRINT("%s\n", __func__); memset(r8a66597, 0, sizeof(r8a66597)); r8a66597->reg = CONFIG_R8A66597_BASE_ADDR; disable_controller(r8a66597); wait_ms(100); enable_controller(r8a66597); r8a66597_port_power(r8a66597, 0 , 1); /* check usb device */ check_usb_device_connecting(r8a66597); wait_ms(50); return 0;}int usb_lowlevel_stop(void){ disable_controller(&gr8a66597); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -