Exemplo n.º 1
0
uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed)
{
	const uint8_t constBufSize = sizeof(USB_DEVICE_DESCRIPTOR);

	uint8_t		buf[constBufSize];
	uint8_t		rcode;
	UsbDevice	*p = NULL;
	EpInfo		*oldep_ptr = NULL;
	uint8_t		num_of_conf;	// number of configurations

	AddressPool	&addrPool = pUsb->GetAddressPool();

	USBTRACE("MS Init\r\n");

	if (bAddress)
		return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;

	// Get pointer to pseudo device with address 0 assigned
	p = addrPool.GetUsbDevicePtr(0);

	if (!p)
		return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;

	if (!p->epinfo)
	{
		USBTRACE("epinfo\r\n");
		return USB_ERROR_EPINFO_IS_NULL;
	}

	// Save old pointer to EP_RECORD of address 0
	oldep_ptr = p->epinfo;

	// Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
	p->epinfo = epInfo;

	p->lowspeed = lowspeed;

	// Get device descriptor
	rcode = pUsb->getDevDescr( 0, 0, constBufSize, (uint8_t*)buf );

	// Restore p->epinfo
	p->epinfo = oldep_ptr;

	if( rcode ) 
		goto FailGetDevDescr;

	// Allocate new address according to device class
	bAddress = addrPool.AllocAddress(parent, false, port);

	if (!bAddress)
		return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;

	// Extract Max Packet Size from the device descriptor
	epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; 

	// Assign new address to the device
	rcode = pUsb->setAddr( 0, 0, bAddress );

	if (rcode)
	{
		p->lowspeed = false;
		addrPool.FreeAddress(bAddress);
		bAddress = 0;
		USBTRACE2("setAddr:",rcode);
		return rcode;
	}

	USBTRACE2("Addr:", bAddress);

	p->lowspeed = false;

	p = addrPool.GetUsbDevicePtr(bAddress);

	if (!p)
		return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;

	p->lowspeed = lowspeed;

	num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;

	// Assign epInfo to epinfo pointer
	rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);

	if (rcode)
		goto FailSetDevTblEntry;

	USBTRACE2("NC:", num_of_conf);

	for (uint8_t i=0; i<num_of_conf; i++)
	{
		HexDumper<USBReadParser, uint16_t, uint16_t>		HexDump;
		ConfigDescParser<	USB_CLASS_MASS_STORAGE, 
							MASS_SUBCLASS_SCSI, 
							MASS_PROTO_BBB, 
							CP_MASK_COMPARE_CLASS | 
							CP_MASK_COMPARE_SUBCLASS | 
							CP_MASK_COMPARE_PROTOCOL>		BulkOnlyParser(this);
		
		rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
		rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser);


		if (bNumEP > 1)
			break;
	} // for
	
	if (bNumEP < 3)
		return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;

	// Assign epInfo to epinfo pointer
	rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);

	USBTRACE2("Conf:", bConfNum);

	// Set Configuration Value
	rcode = pUsb->setConf(bAddress, 0, bConfNum);

	if (rcode)
		goto FailSetConf;

	delay(5000);

	//rcode = pAsync->OnInit(this);

	//if (rcode)
	//	goto FailOnInit;

	rcode = GetMaxLUN(&bMaxLUN);

	if (rcode)
		goto FailGetMaxLUN;

	delay(10);

    {
        InquiryResponse response;
        rcode = Inquiry(bMaxLUN, sizeof(InquiryResponse), (uint8_t*)&response);

		if (rcode)
			goto FailInquiry;

		//if (response.DeviceType != 0)
		//	goto FailInvalidDevice;
	}

	delay(10);

	USBTRACE("MS configured\r\n");

	bPollEnable = true;

	//USBTRACE("Poll enabled\r\n");
	return 0;

FailGetDevDescr:
	USBTRACE("getDevDescr:");
	goto Fail;

FailSetDevTblEntry:
	USBTRACE("setDevTblEn:");
	goto Fail;

FailGetConfDescr:
	USBTRACE("getConf:");
	goto Fail;

FailSetConf:
	USBTRACE("setConf:");
	goto Fail;

FailOnInit:
	USBTRACE("OnInit:");
	goto Fail;

FailGetMaxLUN:
	USBTRACE("GetMaxLUN:");
	goto Fail;

FailInquiry:
	USBTRACE("Inquiry:");
	goto Fail;

Fail:
	Serial.println(rcode, HEX);
	Release();
	return rcode;
}
Exemplo n.º 2
0
/**
 *
 * @param parent (not used)
 * @param port (not used)
 * @param lowspeed true if device is low speed
 * @return 0 for success
 */
uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
        uint8_t rcode;
        uint8_t num_of_conf = epInfo[1].epAddr; // number of configurations
        epInfo[1].epAddr = 0;
        USBTRACE("MS Init\r\n");

        AddressPool &addrPool = pUsb->GetAddressPool();
        UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress);

        if(!p)
                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;

        // Assign new address to the device
        delay(2000);
        rcode = pUsb->setAddr(0, 0, bAddress);

        if(rcode) {
                p->lowspeed = false;
                addrPool.FreeAddress(bAddress);
                bAddress = 0;
                USBTRACE2("setAddr:", rcode);
                return rcode;
        }

        USBTRACE2("Addr:", bAddress);

        p->lowspeed = false;

        p = addrPool.GetUsbDevicePtr(bAddress);

        if(!p)
                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;

        p->lowspeed = lowspeed;

        // Assign epInfo to epinfo pointer
        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);

        if(rcode)
                goto FailSetDevTblEntry;

        USBTRACE2("NC:", num_of_conf);

        for(uint8_t i = 0; i < num_of_conf; i++) {
                ConfigDescParser< USB_CLASS_MASS_STORAGE,
                        MASS_SUBCLASS_SCSI,
                        MASS_PROTO_BBB,
                        CP_MASK_COMPARE_CLASS |
                        CP_MASK_COMPARE_SUBCLASS |
                        CP_MASK_COMPARE_PROTOCOL > BulkOnlyParser(this);

                rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser);

                if(rcode)
                        goto FailGetConfDescr;

                if(bNumEP > 1)
                        break;
        }

        if(bNumEP < 3)
                return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;

        // Assign epInfo to epinfo pointer
        pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);

        USBTRACE2("Conf:", bConfNum);

        // Set Configuration Value
        rcode = pUsb->setConf(bAddress, 0, bConfNum);

        if(rcode)
                goto FailSetConfDescr;

        //Linux does a 1sec delay after this.
        delay(1000);

        rcode = GetMaxLUN(&bMaxLUN);
        if(rcode)
                goto FailGetMaxLUN;

        if(bMaxLUN >= MASS_MAX_SUPPORTED_LUN) bMaxLUN = MASS_MAX_SUPPORTED_LUN - 1;
        ErrorMessage<uint8_t > (PSTR("MaxLUN"), bMaxLUN);

        delay(1000); // Delay a bit for slow firmware.

        for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {
                InquiryResponse response;
                rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response);
                if(rcode) {
                        ErrorMessage<uint8_t > (PSTR("Inquiry"), rcode);
                } else {
#if 0
                        printf("LUN %i `", lun);
                        uint8_t *buf = response.VendorID;
                        for(int i = 0; i < 28; i++) printf("%c", buf[i]);
                        printf("'\r\nQualifier %1.1X ", response.PeripheralQualifier);
                        printf("Device type %2.2X ", response.DeviceType);
                        printf("RMB %1.1X ", response.Removable);
                        printf("SSCS %1.1X ", response.SCCS);
                        uint8_t sv = response.Version;
                        printf("SCSI version %2.2X\r\nDevice conforms to ", sv);
                        switch(sv) {
                                case 0:
                                        printf("No specific");
                                        break;
                                case 1:
                                        printf("ANSI X3.131-1986 (ANSI 1)");
                                        break;
                                case 2:
                                        printf("ANSI X3.131-1994 (ANSI 2)");
                                        break;
                                case 3:
                                        printf("ANSI INCITS 301-1997 (SPC)");
                                        break;
                                case 4:
                                        printf("ANSI INCITS 351-2001 (SPC-2)");
                                        break;
                                case 5:
                                        printf("ANSI INCITS 408-2005 (SPC-4)");
                                        break;
                                case 6:
                                        printf("T10/1731-D (SPC-4)");
                                        break;
                                default:
                                        printf("unknown");
                        }
                        printf(" standards.\r\n");
#endif
                        uint8_t tries = 0xf0;
                        while((rcode = TestUnitReady(lun))) {
                                if(rcode == 0x08) break; // break on no media, this is OK to do.
                                // try to lock media and spin up
                                if(tries < 14) {
                                        LockMedia(lun, 1);
                                        MediaCTL(lun, 1); // I actually have a USB stick that needs this!
                                } else delay(2 * (tries + 1));
                                tries++;
                                if(!tries) break;
                        }
                        if(!rcode) {
                                delay(1000);
                                LUNOk[lun] = CheckLUN(lun);
                                if(!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun);
                        }
                }
        }


        CheckMedia();

        rcode = OnInit();

        if(rcode)
                goto FailOnInit;

#ifdef DEBUG_USB_HOST
        USBTRACE("MS configured\r\n\r\n");
#endif

        bPollEnable = true;

        //USBTRACE("Poll enabled\r\n");
        return 0;

FailSetConfDescr:
#ifdef DEBUG_USB_HOST
        NotifyFailSetConfDescr();
        goto Fail;
#endif

FailOnInit:
#ifdef DEBUG_USB_HOST
        USBTRACE("OnInit:");
        goto Fail;
#endif

FailGetMaxLUN:
#ifdef DEBUG_USB_HOST
        USBTRACE("GetMaxLUN:");
        goto Fail;
#endif

        //#ifdef DEBUG_USB_HOST
        //FailInvalidSectorSize:
        //        USBTRACE("Sector Size is NOT VALID: ");
        //        goto Fail;
        //#endif

FailSetDevTblEntry:
#ifdef DEBUG_USB_HOST
        NotifyFailSetDevTblEntry();
        goto Fail;
#endif

FailGetConfDescr:
#ifdef DEBUG_USB_HOST
        NotifyFailGetConfDescr();
#endif

#ifdef DEBUG_USB_HOST
Fail:
        NotifyFail(rcode);
#endif
        Release();
        return rcode;
}
Exemplo n.º 3
0
/**
 *
 * @param parent (not used)
 * @param port (not used)
 * @param lowspeed true if device is low speed
 * @return 0 for success
 */
uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
        uint8_t rcode;
        uint8_t num_of_conf = epInfo[1].epAddr; // number of configurations
        epInfo[1].epAddr = 0;
        USBTRACE("MS Init\r\n");

        AddressPool &addrPool = pUsb->GetAddressPool();
        UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress);

        if (!p)
                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;

        // Assign new address to the device
        delay(2000);
        rcode = pUsb->setAddr(0, 0, bAddress);

        if (rcode) {
                p->lowspeed = false;
                addrPool.FreeAddress(bAddress);
                bAddress = 0;
                USBTRACE2("setAddr:", rcode);
                return rcode;
        }

        USBTRACE2("Addr:", bAddress);

        p->lowspeed = false;

        p = addrPool.GetUsbDevicePtr(bAddress);

        if (!p)
                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;

        p->lowspeed = lowspeed;

        // Assign epInfo to epinfo pointer
        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);

        if (rcode)
                goto FailSetDevTblEntry;

        USBTRACE2("NC:", num_of_conf);

        for (uint8_t i = 0; i < num_of_conf; i++) {
                ConfigDescParser< USB_CLASS_MASS_STORAGE,
                        MASS_SUBCLASS_SCSI,
                        MASS_PROTO_BBB,
                        CP_MASK_COMPARE_CLASS |
                        CP_MASK_COMPARE_SUBCLASS |
                        CP_MASK_COMPARE_PROTOCOL > BulkOnlyParser(this);

                rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser);

                if (rcode)
                        goto FailGetConfDescr;

                if (bNumEP > 1)
                        break;
        } // for

        if (bNumEP < 3)
                return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;

        // Assign epInfo to epinfo pointer
        pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);

        USBTRACE2("Conf:", bConfNum);

        // Set Configuration Value
        rcode = pUsb->setConf(bAddress, 0, bConfNum);

        if (rcode)
                goto FailSetConfDescr;

        //Linux does a 1sec delay after this.
        delay(1000);

        rcode = GetMaxLUN(&bMaxLUN);
        if (rcode)
                goto FailGetMaxLUN;

        if (bMaxLUN >= MASS_MAX_SUPPORTED_LUN) bMaxLUN = MASS_MAX_SUPPORTED_LUN - 1;
        ErrorMessage<uint8_t > (PSTR("MaxLUN"), bMaxLUN);

        delay(1000); // Delay a bit for slow firmware.

        //bTheLUN = bMaxLUN;

        for (uint8_t lun = 0; lun <= bMaxLUN; lun++) {
                InquiryResponse response;
                rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response);
                if (rcode) {
                        ErrorMessage<uint8_t > (PSTR("Inquiry"), rcode);
                } else {
                        uint8_t tries = 0xf0;
                        while (rcode = TestUnitReady(lun)) {
                                if (rcode == 0x08) break; // break on no media, this is OK to do.
                                // try to lock media and spin up
                                if (tries < 14) {
                                        LockMedia(lun, 1);
                                        MediaCTL(lun, 1); // I actually have a USB stick that needs this!
                                } else delay(2 * (tries + 1));
                                tries++;
                                if (!tries) break;
                        }
                        if (!rcode) {
                                delay(1000);
                                LUNOk[lun] = CheckLUN(lun);
                                if (!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun);
                        }
                }
        }


#if 0
        {
                bool good;
                for (uint8_t i = 1; i == 0; i++) {
                        good = false;
                        CheckMedia();
                        for (uint8_t lun = 0; lun <= bMaxLUN; lun++) good |= LUNOk[lun];
                        if (good) break;
                        delay(118); // 255 loops =~ 30 seconds to allow for spin up, as per SCSI spec.
                }
        }
#else
        CheckMedia();
#endif

        rcode = OnInit();

        if (rcode)
                goto FailOnInit;

        USBTRACE("MS configured\r\n\r\n");

        bPollEnable = true;

        //USBTRACE("Poll enabled\r\n");
        return 0;

FailSetConfDescr:
#ifdef DEBUG_USB_HOST
        NotifyFailSetConfDescr();
        goto Fail;
#endif

FailOnInit:
#ifdef DEBUG_USB_HOST
        USBTRACE("OnInit:");
        goto Fail;
#endif

FailGetMaxLUN:
#ifdef DEBUG_USB_HOST
        USBTRACE("GetMaxLUN:");
        goto Fail;
#endif

FailInvalidSectorSize:
#ifdef DEBUG_USB_HOST
        USBTRACE("Sector Size is NOT VALID: ");
        goto Fail;
#endif

FailSetDevTblEntry:
#ifdef DEBUG_USB_HOST
        NotifyFailSetDevTblEntry();
        goto Fail;
#endif

FailGetConfDescr:
#ifdef DEBUG_USB_HOST
        NotifyFailGetConfDescr();
#endif

Fail:
#ifdef DEBUG_USB_HOST
        NotifyFail(rcode);
#endif
        Release();
        return rcode;
}