⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb_ohci.c

📁 看到最近大家都关心 usbhost 的实现, 论坛上能找到的代码仅是一些简单的 demo , 完整的源码级的协议层是找不到的 我就贡献一把, 将我前一段时间移植成功的 USBHost 代码奉上 注
💻 C
📖 第 1 页 / 共 4 页
字号:
    cc = TD_CC_GET (tdINFO);
    if (cc != 0) {
      dbg("ConditionCode %#x", cc);
      stat = cc_to_error[cc];
    }

    /* see if this done list makes for all TD's of current URB,
     * and mark the URB finished if so */
    if (++(lurb_priv->td_cnt) == lurb_priv->length) {
#if 1
      if ((ed->state & (ED_OPER | ED_UNLINK)) &&
          (lurb_priv->state != URB_DEL))
#else
      if ((ed->state & (ED_OPER | ED_UNLINK)))
#endif
        lurb_priv->finished = sohci_return_job(ohci,
            lurb_priv);
      else
        dbg("dl_done_list: strange.., ED state %x, ed->state\n");
    } else
      dbg("dl_done_list: processing TD %x, len %x\n", lurb_priv->td_cnt,
        lurb_priv->length);
    if (ed->state != ED_NEW &&
        (usb_pipetype (lurb_priv->pipe) != PIPE_INTERRUPT)) {
      edHeadP = m32_swap (ed->hwHeadP) & 0xfffffff0;
      edTailP = m32_swap (ed->hwTailP);

      /* unlink eds if they are not busy */
      if ((edHeadP == edTailP) && (ed->state == ED_OPER))
        ep_unlink (ohci, ed);
    }

    td_list = td_list_next;
  }
  return stat;
}

/*-------------------------------------------------------------------------*
 * Virtual Root Hub
 *-------------------------------------------------------------------------*/

/* Device descriptor */
static unsigned char root_hub_dev_des[] =
{
  0x12,      /*  unsigned char  bLength; */
  0x01,      /*  unsigned char  bDescriptorType; Device */
  0x10,      /*  unsigned short bcdUSB; v1.1 */
  0x01,
  0x09,      /*  unsigned char  bDeviceClass; HUB_CLASSCODE */
  0x00,      /*  unsigned char  bDeviceSubClass; */
  0x00,      /*  unsigned char  bDeviceProtocol; */
  0x08,      /*  unsigned char  bMaxPacketSize0; 8 Bytes */
  0x00,      /*  unsigned short idVendor; */
  0x00,
  0x00,      /*  unsigned short idProduct; */
  0x00,
  0x00,      /*  unsigned short bcdDevice; */
  0x00,
  0x00,      /*  unsigned char  iManufacturer; */
  0x01,      /*  unsigned char  iProduct; */
  0x00,      /*  unsigned char  iSerialNumber; */
  0x01      /*  unsigned char  bNumConfigurations; */
};

/* Configuration descriptor */
static unsigned char root_hub_config_des[] =
{
  0x09,      /*  unsigned char  bLength; */
  0x02,      /*  unsigned char  bDescriptorType; Configuration */
  0x19,      /*  unsigned short wTotalLength; */
  0x00,
  0x01,      /*  unsigned char  bNumInterfaces; */
  0x01,      /*  unsigned char  bConfigurationValue; */
  0x00,      /*  unsigned char  iConfiguration; */
  0x40,      /*  unsigned char  bmAttributes;
     Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
  0x00,      /*  unsigned char  MaxPower; */

  /* interface */
  0x09,      /*  unsigned char  if_bLength; */
  0x04,      /*  unsigned char  if_bDescriptorType; Interface */
  0x00,      /*  unsigned char  if_bInterfaceNumber; */
  0x00,      /*  unsigned char  if_bAlternateSetting; */
  0x01,      /*  unsigned char  if_bNumEndpoints; */
  0x09,      /*  unsigned char  if_bInterfaceClass; HUB_CLASSCODE */
  0x00,      /*  unsigned char  if_bInterfaceSubClass; */
  0x00,      /*  unsigned char  if_bInterfaceProtocol; */
  0x00,      /*  unsigned char  if_iInterface; */

  /* endpoint */
  0x07,      /*  unsigned char  ep_bLength; */
  0x05,      /*  unsigned char  ep_bDescriptorType; Endpoint */
  0x81,      /*  unsigned char  ep_bEndpointAddress; IN Endpoint 1 */
  0x03,      /*  unsigned char  ep_bmAttributes; Interrupt */
  0x02,      /*  unsigned short ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
  0x00,
  0xff      /*  unsigned char  ep_bInterval; 255 ms */
};

static unsigned char root_hub_str_index0[] =
{
  0x04,      /*  unsigned char  bLength; */
  0x03,      /*  unsigned char  bDescriptorType; String-descriptor */
  0x09,      /*  unsigned char  lang ID */
  0x04,      /*  unsigned char  lang ID */
};

static unsigned char root_hub_str_index1[] =
{
  28,      /*  unsigned char  bLength; */
  0x03,      /*  unsigned char  bDescriptorType; String-descriptor */
  'O',      /*  unsigned char  Unicode */
  0,        /*  unsigned char  Unicode */
  'H',      /*  unsigned char  Unicode */
  0,        /*  unsigned char  Unicode */
  'C',      /*  unsigned char  Unicode */
  0,        /*  unsigned char  Unicode */
  'I',      /*  unsigned char  Unicode */
  0,        /*  unsigned char  Unicode */
  ' ',      /*  unsigned char  Unicode */
  0,        /*  unsigned char  Unicode */
  'R',      /*  unsigned char  Unicode */
  0,        /*  unsigned char  Unicode */
  'o',      /*  unsigned char  Unicode */
  0,        /*  unsigned char  Unicode */
  'o',      /*  unsigned char  Unicode */
  0,        /*  unsigned char  Unicode */
  't',      /*  unsigned char  Unicode */
  0,        /*  unsigned char  Unicode */
  ' ',      /*  unsigned char  Unicode */
  0,        /*  unsigned char  Unicode */
  'H',      /*  unsigned char  Unicode */
  0,        /*  unsigned char  Unicode */
  'u',      /*  unsigned char  Unicode */
  0,        /*  unsigned char  Unicode */
  'b',      /*  unsigned char  Unicode */
  0,        /*  unsigned char  Unicode */
};

/* Hub class-specific descriptor is constructed dynamically */

/*-------------------------------------------------------------------------*/

#define OK(x)      len = (x); break

#define WR_RH_STAT(x)     writel((x), &gohci.regs->roothub.status)
#define WR_RH_PORTSTAT(x) writel((x), &gohci.regs->roothub.portstatus[wIndex-1])

#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)
{
  unsigned int temp, ndp, i;
  int res;

  res = -1;
  temp = roothub_a (controller);
  ndp = (temp & RH_A_NDP);
#ifdef CONFIG_AT91C_PQFP_UHPBUG
  ndp = (ndp == 2) ? 1:0;
#endif
  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;
  unsigned int datab[4];
  unsigned char *data_buf = (unsigned char *)datab;
  unsigned short bmRType_bReq;
  unsigned short wValue;
  unsigned short wIndex;
  unsigned short wLength;

  os_dly_waitms(1);

  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:
      *(unsigned short *) data_buf = m16_swap (1); OK (2);
  case RH_GET_STATUS | RH_INTERFACE:
      *(unsigned short *) data_buf = m16_swap (0); OK (2);
  case RH_GET_STATUS | RH_ENDPOINT:
      *(unsigned short *) data_buf = m16_swap (0); OK (2);
  case RH_GET_STATUS | RH_CLASS:
      *(unsigned int *) data_buf = m32_swap (
        RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE));
      OK (4);
  case RH_GET_STATUS | RH_OTHER | RH_CLASS:
      *(unsigned int *) 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 );
          os_dly_waitms(100);
          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( leni, min_t( sizeof (root_hub_dev_des), wLength));

        data_buf = root_hub_dev_des; OK(len);
      case (0x02): /* configuration descriptor */
        len = min_t(leni, min_t(sizeof (root_hub_config_des), wLength));

        data_buf = root_hub_config_des; OK(len);
      case (0x03): /* string descriptors */
        if(wValue==0x0300) {
          len = min_t(leni, min_t(sizeof (root_hub_str_index0), wLength));
          data_buf = root_hub_str_index0;
          OK(len);
        }
        if(wValue==0x0301) {
          len = min_t(leni, min_t(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:
  {
    unsigned int temp = roothub_a (&gohci);

    data_buf [0] = 9;    /* min length; */
    data_buf [1] = 0x29;
    data_buf [2] = temp & RH_A_NDP;
#ifdef CONFIG_AT91C_PQFP_UHPBUG
    data_buf [2] = (data_buf [2] == 2) ? 1:0;
#endif
    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(leni, min_t(data_buf [0], wLength));
    OK (len);
  }

  case RH_GET_CONFIGURATION:  *(unsigned char *) 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;
  }

  os_dly_waitms(1);

  len = min_t(len, leni);
  if (data != data_buf)
      memcpy (data, data_buf, len);
  dev->act_len = len;
  dev->status = stat;

  os_dly_waitms(1);

  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;
  urb_priv_t *urb;

  urb = malloc(sizeof(urb_priv_t));
  if(urb == NULL) return -1;

  memset(urb, 0, sizeof(urb_priv_t));

  urb->dev = dev;
  urb->pipe = pipe;
  urb->transfer_buffer = buffer;
  urb->transfer_buffer_length = transfer_len;
  urb->interval = interval;

  /* device pulled? Shortcut the action. */
  if (devgone == dev) {
    dev->status = USB_ST_CRC_ERR;
    urb_free_priv (urb);
    return 0;
  }

  os_dly_waitms(1);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -