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

📄 usb_storage.c

📁 看到最近大家都关心 usbhost 的实现, 论坛上能找到的代码仅是一些简单的 demo , 完整的源码级的协议层是找不到的 我就贡献一把, 将我前一段时间移植成功的 USBHost 代码奉上 注
💻 C
📖 第 1 页 / 共 3 页
字号:
    { return -1;  /* usb_stor_BBB_comdat:cmdlen too large\n"); */
    }
    
    cbw = (umass_bbb_cbw_t *)malloc(sizeof(umass_bbb_cbw_t));
    if(cbw == NULL) return -1;

    /* always OUT to the ep */
    pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
    cbw->dCBWSignature = swap_32(CBWSIGNATURE);
    cbw->dCBWTag     = swap_32(CBWTag++);
    cbw->dCBWDataTransferLength = swap_32(srb->datalen);
    cbw->bCBWFlags   = (dir_in? CBWFLAGS_IN : CBWFLAGS_OUT);
    cbw->bCBWLUN     = srb->lun;
    cbw->bCDBLength  = srb->cmdlen;
    /* copy the command data into the CBW command data buffer */
    /* DST SRC LEN!!! */
    memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
    result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE, &actlen, USB_CNTL_TIMEOUT*5);

    free(cbw);
    return result;
}


/* FIXME: we also need a CBI_command which sets up the completion
 * interrupt, and waits for it
 */
int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
{
int result = 0;
int dir_in,retry;
unsigned int pipe;
unsigned long status;

    retry  = 5;
    dir_in = US_DIRECTION(srb->cmd[0]);
    
    if(dir_in)
    { pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);  }
    else
    { pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); }

    while(retry--) 
    {
      /* let's send the command via the control pipe */
      result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
                            US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
                            0, us->ifnum,
                            srb->cmd, srb->cmdlen, USB_CNTL_TIMEOUT*5);
      
      /* check the return code for the command */
      if (result < 0) 
      {
        if(us->pusb_dev->status & USB_ST_STALLED) 
        {
          status = us->pusb_dev->status;
          
          usb_clear_halt(us->pusb_dev,  usb_sndctrlpipe(us->pusb_dev,0));
          us->pusb_dev->status = status;
        }
        return result;
      }
      
      /* transfer the data payload for this command, if one exists*/
      if (srb->datalen) 
      {
        result = us_one_transfer(us, pipe, (char *)srb->pdata, srb->datalen);
        
        if(!(us->pusb_dev->status & USB_ST_NAK_REC))
        { break;  }
      } 
      /* if (srb->datalen) */
      else
      { break;  }
    }
    /* return result */
    return result;
}


int usb_stor_CBI_get_status (ccb * srb, struct us_data *us)
{
int timeout;
    us->ip_wanted = 1;
    
    submit_int_msg (us->pusb_dev, us->irqpipe, (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
    timeout = 1000;
    
    while (timeout--) 
    {
      if ((volatile int *) us->ip_wanted == 0)
      { break;  }
      os_dly_wait (1);
    }
    
    if (us->ip_wanted) 
    { /*  Did not get interrupt on CBI\n"); */
      us->ip_wanted = 0;
      return USB_STOR_TRANSPORT_ERROR;
    }
    
    /* UFI gives us ASC and ASCQ, like a request sense */
    if (us->subclass == US_SC_UFI) 
    {
      if((srb->cmd[0] == SCSI_REQ_SENSE) ||
         (srb->cmd[0] == SCSI_INQUIRY))
      { return USB_STOR_TRANSPORT_GOOD;   }/* Good */
      else if (us->ip_data)
      { return USB_STOR_TRANSPORT_FAILED; }
      else
      { return USB_STOR_TRANSPORT_GOOD;   }
    }

    /* otherwise, we interpret the data normally */
    switch (us->ip_data) {
    case 0x0001:
      return USB_STOR_TRANSPORT_GOOD;
    case 0x0002:
      return USB_STOR_TRANSPORT_FAILED;
    default:
      return USB_STOR_TRANSPORT_ERROR;
    }
}


#define USB_TRANSPORT_UNKNOWN_RETRY 5
#define USB_TRANSPORT_NOT_READY_RETRY 10

/* clear a stall on an endpoint - special for BBB devices */
int usb_stor_BBB_clear_endpt_stall(struct us_data *us, unsigned char endpt)
{
int result;
    /* ENDPOINT_HALT = 0, so set value to 0 */
    result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
                          USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
                          0, endpt, 0, 0, USB_CNTL_TIMEOUT*5);
    return result;
}


int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
{
int result, retry;
int dir_in;
int actlen, data_actlen;
unsigned int pipe, pipein, pipeout;
umass_bbb_csw_t *csw;
    dir_in = US_DIRECTION(srb->cmd[0]);
    
    /* COMMAND phase */
    result = usb_stor_BBB_comdat(srb, us);
    if(result < 0)
    { /* failed to send CBW status %ld\n", us->pusb_dev->status); */
      usb_stor_BBB_reset(us);
      return USB_STOR_TRANSPORT_FAILED;
    }

    os_dly_wait(1);   //os_dly_waitms(5);

    pipein  = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
    pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
    
    /* DATA phase + error handling */
    data_actlen = 0;
    /* no data, go immediately to the STATUS phase */
    if(srb->datalen == 0)
    { goto st;  }
    
    
    if (dir_in)
    { pipe = pipein;  }
    else
    { pipe = pipeout; }

    result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen, &data_actlen, USB_CNTL_TIMEOUT*5);
    /* special handling of STALL in DATA phase */
    if((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) 
    {
      /* clear the STALL on the endpoint */
      result = usb_stor_BBB_clear_endpt_stall(us, dir_in? us->ep_in : us->ep_out);
      if (result >= 0)
      /* continue on to STATUS phase */
      { goto st;  }
    }
    if (result < 0) 
    {       
      usb_stor_BBB_reset(us);     /* usb_bulk_msg error status %ld\n", us->pusb_dev->status); */
      return USB_STOR_TRANSPORT_FAILED;
    }

    /* STATUS phase + error handling */
st:
    retry = 0;
    csw = (umass_bbb_csw_t *)malloc(sizeof(umass_bbb_csw_t));
    if(csw == NULL) return -1;
again:
    result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE, &actlen, USB_CNTL_TIMEOUT*5);

    /* special handling of STALL in STATUS phase */
    if((result < 0) && (retry < 1) && (us->pusb_dev->status & USB_ST_STALLED)) 
    {
      /* clear the STALL on the endpoint */
      result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
      if (result >= 0 && (retry++ < 1))
      { /* do a retry */
        goto again;
      }
    }
    if (result < 0) 
    {
      /* usb_bulk_msg error status %ld\n", us->pusb_dev->status); */
      usb_stor_BBB_reset(us);
      free(csw);
      return USB_STOR_TRANSPORT_FAILED;
    }
    
    /* misuse pipe to get the residue */
    pipe = swap_32(csw->dCSWDataResidue);
    
    if((pipe == 0) && (srb->datalen != 0) && (srb->datalen - data_actlen != 0))
    { pipe = srb->datalen - data_actlen;  }

    if (CSWSIGNATURE != swap_32(csw->dCSWSignature)) 
    {
      usb_stor_BBB_reset(us);
      free(csw);
      return USB_STOR_TRANSPORT_FAILED;
    } 
    else if ((CBWTag - 1) != swap_32(csw->dCSWTag)) 
    {
      usb_stor_BBB_reset(us);
      free(csw);
      return USB_STOR_TRANSPORT_FAILED;
    } 
    else if (csw->bCSWStatus > CSWSTATUS_PHASE) 
    {
      usb_stor_BBB_reset(us);
      free(csw);
      return USB_STOR_TRANSPORT_FAILED;
    } 
    else if (csw->bCSWStatus == CSWSTATUS_PHASE) 
    {
      usb_stor_BBB_reset(us);
      free(csw);
      return USB_STOR_TRANSPORT_FAILED;
    } 
    else if (data_actlen > srb->datalen) 
    { free(csw);
      return USB_STOR_TRANSPORT_FAILED;
    } 
    else if (csw->bCSWStatus == CSWSTATUS_FAILED) 
    { free(csw);
      return USB_STOR_TRANSPORT_FAILED;
    }
    free(csw);
    return result;
}


int usb_stor_CB_transport(ccb *srb, struct us_data *us)
{
int result,status;
ccb *psrb;
ccb reqsrb;
int retry,notready;
    
    psrb     = &reqsrb;
    status   = USB_STOR_TRANSPORT_GOOD;
    retry    = 0;
    notready = 0;
    /* issue the command */
do_retry:
    result = usb_stor_CB_comdat(srb, us);
    
    /* if this is an CBI Protocol, get IRQ */
    if(us->protocol == US_PR_CBI)
    {
      status = usb_stor_CBI_get_status(srb,us);
      /* if the status is error, report it */
      if(status == USB_STOR_TRANSPORT_ERROR) 
      { return status;
      }
      srb->sense_buf[12] = (unsigned char)(us->ip_data>>8);
      srb->sense_buf[13] = (unsigned char)(us->ip_data&0xff);
      if(!us->ip_data) 
      {
        /* if the status is good, report it */
        if(status == USB_STOR_TRANSPORT_GOOD) 
        {
          return status;
        }
      }
    }
    /* do we have to issue an auto request? */
    /* HERE we have to check the result */
    if((result<0) && !(us->pusb_dev->status & USB_ST_STALLED)) 
    {
      us->transport_reset(us);
      return USB_STOR_TRANSPORT_ERROR;
    }
    if((us->protocol == US_PR_CBI) &&
       ((srb->cmd[0] == SCSI_REQ_SENSE) || (srb->cmd[0] == SCSI_INQUIRY))) 
    {
      /* do not issue an autorequest after request sense */
      return USB_STOR_TRANSPORT_GOOD;
    }
    /* issue an request_sense */
    memset(&psrb->cmd[0], 0, 12);
    psrb->cmd[0]  = SCSI_REQ_SENSE;
    psrb->cmd[1]  = srb->lun<<5;
    psrb->cmd[4]  = 18;
    psrb->datalen = 18;
    psrb->pdata   = &srb->sense_buf[0];
    psrb->cmdlen  = 12;
    /* issue the command */
    result = usb_stor_CB_comdat(psrb, us);
    
    /* if this is an CBI Protocol, get IRQ */
    if(us->protocol == US_PR_CBI) 
    {
      status = usb_stor_CBI_get_status(psrb,us);
    }
    if((result<0) && !(us->pusb_dev->status & USB_ST_STALLED)) 
    {
      return USB_STOR_TRANSPORT_ERROR;
    }
    
    /* Check the auto request result */
    if((srb->sense_buf[2]==0) &&
       (srb->sense_buf[12]==0) &&
       (srb->sense_buf[13]==0)) /* ok, no sense */
    { return USB_STOR_TRANSPORT_GOOD; }

    /* Check the auto request result */
    switch(srb->sense_buf[2]) {
    case 0x01: 
      /* Recovered Error */
      return USB_STOR_TRANSPORT_GOOD;
    case 0x02: 
      /* Not Ready */
      if(notready++ > USB_TRANSPORT_NOT_READY_RETRY) 
      { 
        return USB_STOR_TRANSPORT_FAILED;
      } 
      else 
      { os_dly_wait(10);
        goto do_retry;
      }
    default:
      if(retry++ > USB_TRANSPORT_UNKNOWN_RETRY) 
      {
        return USB_STOR_TRANSPORT_FAILED;
      } 
      else 
      { goto do_retry;
      }
    }
}


static int usb_inquiry(ccb *srb, struct us_data *ss)
{
int retry,i;
    retry = 5;
    do {
      memset(&srb->cmd[0],0,12);
      srb->cmd[0]  = SCSI_INQUIRY;
      srb->cmd[1]  = srb->lun<<5;
      srb->cmd[4]  = 36;
      srb->datalen = 36;
      srb->cmdlen  = 12;
      
      i = ss->transport(srb, ss);
      if(i == 0) break;
    } while(retry--) ;
    
    if(!retry) 
    { return -1;
    }
    return 0;
}


static int usb_request_sense(ccb *srb, struct us_data *ss)
{
char *ptr;
    ptr = (char *)srb->pdata;
    memset(&srb->cmd[0],0,12);
    srb->cmd[0]   = SCSI_REQ_SENSE;
    srb->cmd[1]   = srb->lun<<5;
    srb->cmd[4]   = 18;
    srb->datalen  = 18;
    srb->pdata    = &srb->sense_buf[0];
    srb->cmdlen   = 12;
    ss->transport(srb,ss);
    
    srb->pdata    = (unsigned char *)ptr;
    return 0;
}


static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
{
int retries = 10;
    do {
      memset(&srb->cmd[0],0,12);
      srb->cmd[0]   = SCSI_TST_U_RDY;
      srb->cmd[1]   = srb->lun<<5;
      srb->datalen  = 0;
      srb->cmdlen   = 12;

⌨️ 快捷键说明

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