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;

}
Пример #2
0
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 {
Пример #3
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;

}
Пример #4
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;
}
Пример #5
0
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;
}