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

📄 usb_storage.c

📁 看到最近大家都关心 usbhost 的实现, 论坛上能找到的代码仅是一些简单的 demo , 完整的源码级的协议层是找不到的 我就贡献一把, 将我前一段时间移植成功的 USBHost 代码奉上 注
💻 C
📖 第 1 页 / 共 3 页
字号:
      
      if(ss->transport(srb,ss) == USB_STOR_TRANSPORT_GOOD) 
      { return 0;
      }
      usb_request_sense (srb, ss);
      os_dly_wait (10);
    }while(retries--);
    return -1;
}


static int usb_read_capacity(ccb *srb,struct us_data *ss)
{
int retry;
    retry = 3; /* retries */
    do{
      memset(&srb->cmd[0],0,12);
      srb->cmd[0]   = SCSI_RD_CAPAC;
      srb->cmd[1]   = srb->lun<<5;
      srb->datalen  = 8;
      srb->cmdlen   = 12;
      if(ss->transport(srb,ss) == USB_STOR_TRANSPORT_GOOD) 
      { return 0;
      }
    } while(retry--);
    return -1;
}


static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start, unsigned short blocks)
{
    memset(&srb->cmd[0], 0, 12);
    srb->cmd[0] = SCSI_READ10;
    srb->cmd[1] = (srb->lun << 5);
    
    srb->cmd[2] = ((unsigned char) (start>>24))&0xff;
    srb->cmd[3] = ((unsigned char) (start>>16))&0xff;
    srb->cmd[4] = ((unsigned char) (start>>8))&0xff;
    srb->cmd[5] = ((unsigned char) (start))&0xff;

    srb->cmd[7] = ((unsigned char) (blocks>>8))&0xff;
    srb->cmd[8] =  (unsigned char) blocks & 0xff;
    srb->cmdlen = 12;
    
    return ss->transport(srb,ss);
}


#define USB_MAX_READ_BLK 20
unsigned long usb_stor_read(int device, unsigned long blknr, unsigned long blkcnt, void *buffer)
{
unsigned long start,blks, buf_addr;
unsigned short smallblks;
struct usb_device *dev;
int retry;
ccb *srb = &usb_ccb;
    
    if (blkcnt == 0) { return 0; }
    
    device &= 0xff;
    
    /* Setup  device */
    
    dev = usb_device_find(usb_dev_desc[device].target);
    if(dev == NULL)   return 0;
    
    usb_disable_asynch(1); /* asynch transfer not allowed */
    srb->lun  = usb_dev_desc[device].lun;
    buf_addr  = (unsigned long)buffer;
    start     = blknr;
    blks      = blkcnt;
    
    if(usb_test_unit_ready(srb,(struct us_data *)dev->privptr)) 
    { return 0;
    }
    
    do {
      retry = 2;
      srb->pdata = (unsigned char *)buf_addr;
      if(blks > USB_MAX_READ_BLK) 
      { smallblks = USB_MAX_READ_BLK;
      } 
      else 
      { smallblks = (unsigned short) blks;
      }
  retry_it:
      if(smallblks == USB_MAX_READ_BLK)
      { usb_show_progress();  }

      srb->datalen = usb_dev_desc[device].blksz * smallblks;
      srb->pdata   = (unsigned char *)buf_addr;
      
      if(usb_read_10(srb, (struct us_data *)dev->privptr, start, smallblks)) 
      { 
        usb_request_sense(srb,(struct us_data *)dev->privptr);
        if(retry--) goto retry_it;
        blkcnt -= blks;
        break;
      }
      start     += smallblks;
      blks      -= smallblks;
      buf_addr  += srb->datalen;
    } while(blks != 0);

    usb_disable_asynch(0); /* asynch transfer allowed */
    
    return(blkcnt);
}

static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start, unsigned short blocks)
{
    memset(&srb->cmd[0], 0, 12);
    srb->cmd[0] = SCSI_WRITE10;
    srb->cmd[1] = (srb->lun << 5);
    
    srb->cmd[2] = ((unsigned char) (start>>24))&0xff;
    srb->cmd[3] = ((unsigned char) (start>>16))&0xff;
    srb->cmd[4] = ((unsigned char) (start>>8))&0xff;
    srb->cmd[5] = ((unsigned char) (start))&0xff;

    srb->cmd[7] = ((unsigned char) (blocks>>8))&0xff;
    srb->cmd[8] =  (unsigned char) blocks & 0xff;
    srb->cmdlen = 12;
    
    return ss->transport(srb,ss);
}


#define USB_MAX_READ_BLK 20
unsigned long usb_stor_write(int device, unsigned long blknr, unsigned long blkcnt, void *buffer)
{
unsigned long start,blks, buf_addr;
unsigned short smallblks;
struct usb_device *dev;
int retry;
ccb *srb = &usb_ccb;
    
    if (blkcnt == 0) { return 0; }
    
    device &= 0xff;
    
    /* Setup  device */
    dev = usb_device_find(usb_dev_desc[device].target);
    if(dev == NULL)   return 0;
    
    usb_disable_asynch(1); /* asynch transfer not allowed */
    srb->lun  = usb_dev_desc[device].lun;
    buf_addr  = (unsigned long)buffer;
    start     = blknr;
    blks      = blkcnt;
    
    if(usb_test_unit_ready(srb,(struct us_data *)dev->privptr)) 
    { return 0;
    }
    
    do {
      retry = 2;
      srb->pdata = (unsigned char *)buf_addr;
      if(blks > USB_MAX_READ_BLK) 
      { smallblks = USB_MAX_READ_BLK;
      } 
      else 
      { smallblks = (unsigned short) blks;
      }
  retry_it:
      if(smallblks == USB_MAX_READ_BLK)
      { usb_show_progress();  }

      srb->datalen = usb_dev_desc[device].blksz * smallblks;
      srb->pdata   = (unsigned char *)buf_addr;
      
      if(usb_write_10(srb, (struct us_data *)dev->privptr, start, smallblks)) 
      { 
        usb_request_sense(srb,(struct us_data *)dev->privptr);
        if(retry--) goto retry_it;
        blkcnt -= blks;
        break;
      }
      start     += smallblks;
      blks      -= smallblks;
      buf_addr  += srb->datalen;
    } while(blks != 0);

    usb_disable_asynch(0); /* asynch transfer allowed */
    
    return(blkcnt);
}

/* Probe to see if a new device is actually a Storage device */
int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data *ss)
{
struct usb_interface_descriptor *iface;
int i;
unsigned int flags = 0;
int protocol = 0;
int subclass = 0;
    /* let's examine the device now */
    iface = &dev->config.if_desc[ifnum];

/*  if it's not a mass storage, we go no further */
    if((dev->descriptor.bDeviceClass != 0) ||
       (iface->bInterfaceClass != USB_CLASS_MASS_STORAGE) ||
       (iface->bInterfaceSubClass < US_SC_MIN) ||
       (iface->bInterfaceSubClass > US_SC_MAX))
    { return 0;
    }

    memset(ss, 0, sizeof(struct us_data));
    /* At this point, we know we've got a live one */
    
    /* Initialize the us_data structure with some useful info */
    ss->flags    = flags;
    ss->ifnum    = ifnum;
    ss->pusb_dev = dev;
    ss->attention_done = 0;
    /* If the device has subclass and protocol, then use that.  Otherwise,
       * take data from the specific interface.
       */
    if (subclass) 
    {
      ss->subclass = subclass;
      ss->protocol = protocol;
    } 
    else 
    {
      ss->subclass = iface->bInterfaceSubClass;
      ss->protocol = iface->bInterfaceProtocol;
    }
    
    /* set the handler pointers based on the protocol */
    switch (ss->protocol) {
    case US_PR_CB:
      ss->transport = usb_stor_CB_transport;
      ss->transport_reset = usb_stor_CB_reset;
      break;
    case US_PR_CBI:
      ss->transport = usb_stor_CB_transport;
      ss->transport_reset = usb_stor_CB_reset;
      break;
    case US_PR_BULK:
      ss->transport = usb_stor_BBB_transport;
      ss->transport_reset = usb_stor_BBB_reset;
      break;
    default:
      return 0;
    }
    /*
       * We are expecting a minimum of 2 endpoints - in and out (bulk).
       * An optional interrupt is OK (necessary for CBI protocol).
       * We will ignore any others.
       */
    for (i = 0; i < iface->bNumEndpoints; i++) 
    {
      /* is it an BULK endpoint? */
      if ((iface->ep_desc[i].bmAttributes &  USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) 
      {
        if (iface->ep_desc[i].bEndpointAddress & USB_DIR_IN)
        { ss->ep_in = iface->ep_desc[i].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;  }
        else
        { ss->ep_out = iface->ep_desc[i].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; }
      }
      /* is it an interrupt endpoint? */
      if ((iface->ep_desc[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) 
      {
        ss->ep_int = iface->ep_desc[i].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
        ss->irqinterval = iface->ep_desc[i].bInterval;
      }
    }

    /* Do some basic sanity checks, and bail if we find a problem */
    usb_set_interface(dev, iface->bInterfaceNumber, 0); /* 有些设备不支持接口设置 */

    if((!ss->ep_in) || (!ss->ep_out) ||
       (ss->protocol == US_PR_CBI && ss->ep_int == 0)) 
    {
      return 0;
    }
    /* set class specific stuff */
    /* We only handle certain protocols.  Currently, these are
       * the only ones.
       * The SFF8070 accepts the requests used in u-boot
       */
    if((ss->subclass != US_SC_UFI) && (ss->subclass != US_SC_SCSI) && (ss->subclass != US_SC_8070))
    {
      return 0;
    }

    if(ss->ep_int) 
    {
      /* we had found an interrupt endpoint, prepare irq pipe */
      /* set up the IRQ pipe and handler */
      ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
      ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
      ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
      dev->irq_handle=usb_stor_irq;
    }
    dev->privptr = (void *)ss;
    return 1;
}


int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t *dev_desc)
{
unsigned char perq,modi;
unsigned long *cap;
unsigned long *capacity,*blksz;
ccb *pccb = &usb_ccb;
unsigned char *usb_stor_buf;

    usb_stor_buf = malloc(512);
    if(usb_stor_buf == NULL) return -1;
    
    memset(usb_stor_buf, 0, sizeof(usb_stor_buf));

  /* for some reasons a couple of devices would not survive this reset */
    if (
      /* Sony USM256E */
      ((dev->descriptor.idVendor == 0x054c) && (dev->descriptor.idProduct == 0x019e))
      ||
      /* USB007 Mini-USB2 Flash Drive */
      ((dev->descriptor.idVendor == 0x066f) && (dev->descriptor.idProduct == 0x2010))
      ||
      /* SanDisk Corporation Cruzer Micro 20044318410546613953 */
      ((dev->descriptor.idVendor == 0x0781) && (dev->descriptor.idProduct == 0x5151))
      )
    {    }
    else
    { ss->transport_reset(ss);  
    }

    pccb->pdata      = usb_stor_buf;
    dev_desc->target = dev->devnum;
    pccb->lun        = dev_desc->lun;
    
    if(usb_inquiry(pccb, ss)) 
    { free( usb_stor_buf ); 
      return -1;  
    }

    perq = usb_stor_buf[0];
    modi = usb_stor_buf[1];

    if((perq & 0x1f) == 0x1f)  
    { free( usb_stor_buf ); 
      return 0; /* skip unknown devices */
    }

    if((modi & 0x80) == 0x80) 
    { /* drive is removable */
      dev_desc->removable = 1;
    }

    memcpy(&dev_desc->vendor[0],    &usb_stor_buf[8],   8);
    memcpy(&dev_desc->product[0],   &usb_stor_buf[16], 16);
    memcpy(&dev_desc->revision[0],  &usb_stor_buf[32],  4);
    free( usb_stor_buf ); 

    dev_desc->vendor[8]   = 0;
    dev_desc->product[16] = 0;
    dev_desc->revision[4] = 0;

    if(usb_test_unit_ready(pccb,ss)) 
    { 
      if(dev_desc->removable == 1) 
      { dev_desc->type = perq;
        return 1;
      }
      else
      { return 0; }
    }
    cap = (unsigned long *)malloc(8);
    if(cap == NULL) return -1;

    pccb->pdata = (unsigned char *)&cap[0];
    memset(pccb->pdata,0,8);
    
    if(usb_read_capacity(pccb,ss) != 0) 
    { 
      cap[0] = 2880;
      cap[1] = 0x200;
    }
    
    cap[0] = ((unsigned long)(
              (((unsigned long)(cap[0]) & (unsigned long)0x000000ffUL) << 24) |
              (((unsigned long)(cap[0]) & (unsigned long)0x0000ff00UL) <<  8) |
              (((unsigned long)(cap[0]) & (unsigned long)0x00ff0000UL) >>  8) |
              (((unsigned long)(cap[0]) & (unsigned long)0xff000000UL) >> 24) ));
    cap[1] = ((unsigned long)(
              (((unsigned long)(cap[1]) & (unsigned long)0x000000ffUL) << 24) |
              (((unsigned long)(cap[1]) & (unsigned long)0x0000ff00UL) <<  8) |
              (((unsigned long)(cap[1]) & (unsigned long)0x00ff0000UL) >>  8) |
              (((unsigned long)(cap[1]) & (unsigned long)0xff000000UL) >> 24) ));
    
    /* this assumes bigendian! */
    cap[0]  += 1;
    capacity = &cap[0];
    blksz    = &cap[1];
    free(cap);

    dev_desc->lba = *capacity;
    dev_desc->blksz = *blksz;
    dev_desc->type = perq;
    
    //init_part(dev_desc);
    dev_desc->part_type = PART_TYPE_DOS;    /* 直接标记, 不检查, 由 FAT_initfiles 检查 */
    return 1;
}

⌨️ 快捷键说明

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