Esempio n. 1
0
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;

}
Esempio n. 2
0
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;
}