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 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; }