static usbh_baseclassdriver_t *_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem) { int i; USBHCustomDriver *custp; (void)dev; if (_usbh_match_vid_pid(dev, 0xABCD, 0x0123) != HAL_SUCCESS) return NULL; const usbh_interface_descriptor_t * const ifdesc = (const usbh_interface_descriptor_t *)descriptor; /* alloc driver */ for (i = 0; i < USBH_CUSTOM_CLASS_MAX_INSTANCES; i++) { if (USBHCUSTOMD[i].dev == NULL) { custp = &USBHCUSTOMD[i]; goto alloc_ok; } } uwarn("Can't alloc CUSTOM driver"); /* can't alloc */ return NULL; alloc_ok: /* initialize the driver's variables */ custp->ifnum = ifdesc->bInterfaceNumber; /* parse the configuration descriptor */ if_iterator_t iif; generic_iterator_t iep; iif.iad = 0; iif.curr = descriptor; iif.rem = rem; for (ep_iter_init(&iep, &iif); iep.valid; ep_iter_next(&iep)) { const usbh_endpoint_descriptor_t *const epdesc = ep_get(&iep); if ((epdesc->bEndpointAddress & 0x80) && (epdesc->bmAttributes == USBH_EPTYPE_INT)) { /* ... */ } else { uinfof("unsupported endpoint found: bEndpointAddress=%02x, bmAttributes=%02x", epdesc->bEndpointAddress, epdesc->bmAttributes); } } custp->state = USBHCUSTOM_STATE_ACTIVE; return (usbh_baseclassdriver_t *)custp; }
static uint32_t _get_divisor(uint32_t baud, usbhftdi_type_t type) { static const uint8_t divfrac[8] = {0, 3, 2, 4, 1, 5, 6, 7}; uint32_t divisor; if (type == USBHFTDI_TYPE_A) { uint32_t divisor3 = ((48000000UL / 2) + baud / 2) / baud; uinfof("FTDI: desired=%dbps, real=%dbps", baud, (48000000UL / 2) / divisor3); if ((divisor3 & 0x7) == 7) divisor3++; /* round x.7/8 up to x+1 */ divisor = divisor3 >> 3; divisor3 &= 0x7; if (divisor3 == 1) divisor |= 0xc000; else if (divisor3 >= 4) divisor |= 0x4000; else if (divisor3 != 0) divisor |= 0x8000; else if (divisor == 1) divisor = 0; /* special case for maximum baud rate */ } else {
static usbh_baseclassdriver_t *_ftdi_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem) { int i; USBHFTDIDriver *ftdip; if (dev->devDesc.idVendor != 0x0403) { uerr("FTDI: Unrecognized VID"); return NULL; } switch (dev->devDesc.idProduct) { case 0x6001: case 0x6010: case 0x6011: case 0x6014: case 0x6015: break; default: uerr("FTDI: Unrecognized PID"); return NULL; } if ((rem < descriptor[0]) || (descriptor[1] != USBH_DT_INTERFACE)) return NULL; const usbh_interface_descriptor_t * const ifdesc = (const usbh_interface_descriptor_t * const)descriptor; if (ifdesc->bInterfaceNumber != 0) { uwarn("FTDI: Will allocate driver along with IF #0"); } /* alloc driver */ for (i = 0; i < HAL_USBHFTDI_MAX_INSTANCES; i++) { if (USBHFTDID[i].dev == NULL) { ftdip = &USBHFTDID[i]; goto alloc_ok; } } uwarn("FTDI: Can't alloc driver"); /* can't alloc */ return NULL; alloc_ok: /* initialize the driver's variables */ ftdip->ports = 0; switch (dev->devDesc.bcdDevice) { case 0x200: //AM uinfo("FTDI: Type A chip"); ftdip->type = USBHFTDI_TYPE_A; break; case 0x400: //BM case 0x500: //2232C case 0x600: //R case 0x1000: //230X uinfo("FTDI: Type B chip"); ftdip->type = USBHFTDI_TYPE_B; break; case 0x700: //2232H; case 0x800: //4232H; case 0x900: //232H; uinfo("FTDI: Type H chip"); ftdip->type = USBHFTDI_TYPE_H; default: uerr("FTDI: Unrecognized chip type"); return NULL; } usbhEPSetName(&dev->ctrl, "FTD[CTRL]"); /* parse the configuration descriptor */ generic_iterator_t iep, icfg; if_iterator_t iif; cfg_iter_init(&icfg, dev->fullConfigurationDescriptor, dev->basicConfigDesc.wTotalLength); for (if_iter_init(&iif, &icfg); iif.valid; if_iter_next(&iif)) { const usbh_interface_descriptor_t *const ifdesc = if_get(&iif); uinfof("FTDI: Interface #%d", ifdesc->bInterfaceNumber); USBHFTDIPortDriver *const prt = _find_port(); if (prt == NULL) { uwarn("\tCan't alloc port for this interface"); break; } prt->ifnum = ifdesc->bInterfaceNumber; prt->epin.status = USBH_EPSTATUS_UNINITIALIZED; prt->epout.status = USBH_EPSTATUS_UNINITIALIZED; for (ep_iter_init(&iep, &iif); iep.valid; ep_iter_next(&iep)) { const usbh_endpoint_descriptor_t *const epdesc = ep_get(&iep); if ((epdesc->bEndpointAddress & 0x80) && (epdesc->bmAttributes == USBH_EPTYPE_BULK)) { uinfof("BULK IN endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); usbhEPObjectInit(&prt->epin, dev, epdesc); usbhEPSetName(&prt->epin, "FTD[BIN ]"); } else if (((epdesc->bEndpointAddress & 0x80) == 0) && (epdesc->bmAttributes == USBH_EPTYPE_BULK)) { uinfof("BULK OUT endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); usbhEPObjectInit(&prt->epout, dev, epdesc); usbhEPSetName(&prt->epout, "FTD[BOUT]"); } else { uinfof("unsupported endpoint found: bEndpointAddress=%02x, bmAttributes=%02x", epdesc->bEndpointAddress, epdesc->bmAttributes); } } if ((prt->epin.status != USBH_EPSTATUS_CLOSED) || (prt->epout.status != USBH_EPSTATUS_CLOSED)) { uwarn("\tCouldn't find endpoints; can't alloc port for this interface"); continue; } /* link the new block driver to the list */ prt->next = ftdip->ports; ftdip->ports = prt; prt->ftdip = ftdip; prt->state = USBHFTDIP_STATE_ACTIVE; } return (usbh_baseclassdriver_t *)ftdip; }
static usbh_baseclassdriver_t *_msd_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem) { int i; USBHMassStorageDriver *msdp; uint8_t luns; usbh_urbstatus_t stat; if (_usbh_match_descriptor(descriptor, rem, USBH_DT_INTERFACE, 0x08, 0x06, 0x50) != HAL_SUCCESS) return NULL; const usbh_interface_descriptor_t * const ifdesc = (const usbh_interface_descriptor_t *)descriptor; if ((ifdesc->bAlternateSetting != 0) || (ifdesc->bNumEndpoints < 2)) { return NULL; } /* alloc driver */ for (i = 0; i < HAL_USBHMSD_MAX_INSTANCES; i++) { if (USBHMSD[i].dev == NULL) { msdp = &USBHMSD[i]; goto alloc_ok; } } uwarn("Can't alloc MSD driver"); /* can't alloc */ return NULL; alloc_ok: /* initialize the driver's variables */ msdp->epin.status = USBH_EPSTATUS_UNINITIALIZED; msdp->epout.status = USBH_EPSTATUS_UNINITIALIZED; msdp->max_lun = 0; msdp->tag = 0; msdp->luns = 0; msdp->ifnum = ifdesc->bInterfaceNumber; usbhEPSetName(&dev->ctrl, "MSD[CTRL]"); /* parse the configuration descriptor */ if_iterator_t iif; generic_iterator_t iep; iif.iad = 0; iif.curr = descriptor; iif.rem = rem; for (ep_iter_init(&iep, &iif); iep.valid; ep_iter_next(&iep)) { const usbh_endpoint_descriptor_t *const epdesc = ep_get(&iep); if ((epdesc->bEndpointAddress & 0x80) && (epdesc->bmAttributes == USBH_EPTYPE_BULK)) { uinfof("BULK IN endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); usbhEPObjectInit(&msdp->epin, dev, epdesc); usbhEPSetName(&msdp->epin, "MSD[BIN ]"); } else if (((epdesc->bEndpointAddress & 0x80) == 0) && (epdesc->bmAttributes == USBH_EPTYPE_BULK)) { uinfof("BULK OUT endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); usbhEPObjectInit(&msdp->epout, dev, epdesc); usbhEPSetName(&msdp->epout, "MSD[BOUT]"); } else { uinfof("unsupported endpoint found: bEndpointAddress=%02x, bmAttributes=%02x", epdesc->bEndpointAddress, epdesc->bmAttributes); } } if ((msdp->epin.status != USBH_EPSTATUS_CLOSED) || (msdp->epout.status != USBH_EPSTATUS_CLOSED)) { goto deinit; } /* read the number of LUNs */ uinfo("Reading Max LUN:"); USBH_DEFINE_BUFFER(uint8_t buff[4]); stat = usbhControlRequest(dev, USBH_REQTYPE_CLASSIN(USBH_REQTYPE_RECIP_INTERFACE), MSD_GET_MAX_LUN, 0, msdp->ifnum, 1, buff); if (stat == USBH_URBSTATUS_OK) { msdp->max_lun = buff[0] + 1; uinfof("\tmax_lun = %d", msdp->max_lun); if (msdp->max_lun > HAL_USBHMSD_MAX_LUNS) { msdp->max_lun = HAL_USBHMSD_MAX_LUNS; uwarnf("\tUsing max_lun = %d", msdp->max_lun); } } else if (stat == USBH_URBSTATUS_STALL) { uwarn("\tStall, max_lun = 1"); msdp->max_lun = 1; } else { uerr("\tError"); goto deinit; } /* open the bulk IN/OUT endpoints */ usbhEPOpen(&msdp->epin); usbhEPOpen(&msdp->epout); /* Alloc one block device per logical unit found */ luns = msdp->max_lun; for (i = 0; (luns > 0) && (i < HAL_USBHMSD_MAX_LUNS); i++) { if (MSBLKD[i].msdp == NULL) { /* link the new block driver to the list */ MSBLKD[i].next = msdp->luns; msdp->luns = &MSBLKD[i]; MSBLKD[i].msdp = msdp; MSBLKD[i].state = BLK_ACTIVE; luns--; } } return (usbh_baseclassdriver_t *)msdp; deinit: /* Here, the enpoints are closed, and the driver is unlinked */ return NULL; }
bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp) { osalDbgCheck(lunp != NULL); osalDbgCheck(lunp->msdp != NULL); msd_result_t res; chSemWait(&lunp->sem); osalDbgAssert((lunp->state == BLK_READY) || (lunp->state == BLK_ACTIVE), "invalid state"); if (lunp->state == BLK_READY) { chSemSignal(&lunp->sem); return HAL_SUCCESS; } lunp->state = BLK_CONNECTING; { USBH_DEFINE_BUFFER(scsi_inquiry_response_t inq); uinfo("INQUIRY..."); res = scsi_inquiry(lunp, &inq); if (res == MSD_RESULT_DISCONNECTED) { goto failed; } else if (res == MSD_RESULT_TRANSPORT_ERROR) { //retry? goto failed; } else if (res == MSD_RESULT_FAILED) { //retry? goto failed; } uinfof("\tPDT=%02x", inq.peripheral & 0x1f); if (inq.peripheral != 0) { uerr("\tUnsupported PDT"); goto failed; } } // Test if unit ready uint8_t i; for (i = 0; i < 10; i++) { uinfo("TEST UNIT READY..."); res = scsi_testunitready(lunp); if (res == MSD_RESULT_DISCONNECTED) { goto failed; } else if (res == MSD_RESULT_TRANSPORT_ERROR) { //retry? goto failed; } else if (res == MSD_RESULT_FAILED) { uinfo("\tTEST UNIT READY: Command Failed, retry"); osalThreadSleepMilliseconds(200); continue; } uinfo("\tReady."); break; } if (i == 10) goto failed; { USBH_DEFINE_BUFFER(scsi_readcapacity10_response_t cap); // Read capacity uinfo("READ CAPACITY(10)..."); res = scsi_readcapacity10(lunp, &cap); if (res == MSD_RESULT_DISCONNECTED) { goto failed; } else if (res == MSD_RESULT_TRANSPORT_ERROR) { //retry? goto failed; } else if (res == MSD_RESULT_FAILED) { //retry? goto failed; } lunp->info.blk_size = __REV(cap.block_size); lunp->info.blk_num = __REV(cap.last_block_addr) + 1; } uinfof("\tBlock size=%dbytes, blocks=%u (~%u MB)", lunp->info.blk_size, lunp->info.blk_num, (uint32_t)(((uint64_t)lunp->info.blk_size * lunp->info.blk_num) / (1024UL * 1024UL))); uinfo("MSD Connected."); lunp->state = BLK_READY; chSemSignal(&lunp->sem); return HAL_SUCCESS; /* Connection failed, state reset to BLK_ACTIVE.*/ failed: uinfo("MSD Connect failed."); lunp->state = BLK_ACTIVE; chSemSignal(&lunp->sem); return HAL_FAILED; }