Beispiel #1
0
/* USB main task. Performs enumeration/cleanup */
void USB::Task( void )      //USB state machine
{
    byte i;
    byte rcode;
    static byte tmpaddr;
    byte tmpdata;
    static unsigned long delay = 0;
    USB_DEVICE_DESCRIPTOR buf;
    tmpdata = getVbusState();
    /* modify USB task state if Vbus changed */

    switch( tmpdata ) {
    case SE1:   //illegal state
        usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
        break;
    case SE0:   //disconnected
        if(( usb_task_state & USB_STATE_MASK ) != USB_STATE_DETACHED ) {
            usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
        }
        break;
    case FSHOST:    //attached
    case LSHOST:
        if(( usb_task_state & USB_STATE_MASK ) == USB_STATE_DETACHED ) {
            delay = millis() + USB_SETTLE_DELAY;
            usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
        }
        break;
    }// switch( tmpdata
    //Serial.print("USB task state: ");
    //Serial.println( usb_task_state, HEX );
    switch( usb_task_state ) {
    case USB_DETACHED_SUBSTATE_INITIALIZE:
        init();
        usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
        break;
    case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE:     //just sit here
        break;
    case USB_DETACHED_SUBSTATE_ILLEGAL:             //just sit here
        break;
    case USB_ATTACHED_SUBSTATE_SETTLE:              //setlle time for just attached device
        if( delay < millis() ) {
            usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
        }
        break;
    case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
        regWr( rHCTL, bmBUSRST );                   //issue bus reset
        usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
        break;
    case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
        if(( regRd( rHCTL ) & bmBUSRST ) == 0 ) {
            tmpdata = regRd( rMODE ) | bmSOFKAENAB;                 //start SOF generation
            regWr( rMODE, tmpdata );
//                  regWr( rMODE, bmSOFKAENAB );
            usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
            delay = millis() + 20; //20ms wait after reset per USB spec
        }
        break;
    case USB_ATTACHED_SUBSTATE_WAIT_SOF:  //todo: change check order
        if( regRd( rHIRQ ) & bmFRAMEIRQ ) {                         //when first SOF received we can continue
            if( delay < millis() ) {                                    //20ms passed
                usb_task_state = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE;
            }
        }
        break;
    case USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE:
        // toggle( BPNT_0 );
        devtable[ 0 ].epinfo->MaxPktSize = 8;   //set max.packet size to min.allowed
        rcode = getDevDescr( 0, 0, 8, ( char* )&buf );
        if( rcode == 0 ) {
            devtable[ 0 ].epinfo->MaxPktSize = buf.bMaxPacketSize0;
            usb_task_state = USB_STATE_ADDRESSING;
        }
        else {
            usb_error = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE;
            usb_task_state = USB_STATE_ERROR;
        }
        break;
    case USB_STATE_ADDRESSING:
        for( i = 1; i < USB_NUMDEVICES; i++ ) {
            if( devtable[ i ].epinfo == NULL ) {
                devtable[ i ].epinfo = devtable[ 0 ].epinfo;        //set correct MaxPktSize
                //temporary record
                //until plugged with real device endpoint structure
                rcode = setAddr( 0, 0, i );
                if( rcode == 0 ) {
                    tmpaddr = i;
                    usb_task_state = USB_STATE_CONFIGURING;
                }
                else {
                    usb_error = USB_STATE_ADDRESSING;          //set address error
                    usb_task_state = USB_STATE_ERROR;
                }
                break;  //break if address assigned or error occured during address assignment attempt
            }
        }//for( i = 1; i < USB_NUMDEVICES; i++
        if( usb_task_state == USB_STATE_ADDRESSING ) {     //no vacant place in devtable
            usb_error = 0xfe;
            usb_task_state = USB_STATE_ERROR;
        }
        break;
    case USB_STATE_CONFIGURING:
        break;
    case USB_STATE_RUNNING:
        break;
    case USB_STATE_ERROR:
        break;
    }// switch( usb_task_state
}
Beispiel #2
0
/*
 * This is broken. We need to enumerate differently.
 * It causes major problems with several devices if detected in an unexpected order.
 *
 *
 * Oleg - I wouldn't do anything before the newly connected device is considered sane.
 * i.e.(delays are not indicated for brevity):
 * 1. reset
 * 2. GetDevDescr();
 * 3a. If ACK, continue with allocating address, addressing, etc.
 * 3b. Else reset again, count resets, stop at some number (5?).
 * 4. When max.number of resets is reached, toggle power/fail
 * If desired, this could be modified by performing two resets with GetDevDescr() in the middle - however, from my experience, if a device answers to GDD()
 * it doesn't need to be reset again
 * New steps proposal:
 * 1: get address pool instance. exit on fail
 * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail.
 * 3: bus reset, 100ms delay
 * 4: set address
 * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail
 * 6: while (configurations) {
 *              for(each configuration) {
 *                      for (each driver) {
 *                              6a: Ask device if it likes configuration. Returns 0 on OK.
 *                                      If successful, the driver configured device.
 *                                      The driver now owns the endpoints, and takes over managing them.
 *                                      The following will need codes:
 *                                          Everything went well, instance consumed, exit with success.
 *                                          Instance already in use, ignore it, try next driver.
 *                                          Not a supported device, ignore it, try next driver.
 *                                          Not a supported configuration for this device, ignore it, try next driver.
 *                                          Could not configure device, fatal, exit with fail.
 *                      }
 *              }
 *    }
 * 7: for(each driver) {
 *      7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID
 * 8: if we get here, no driver likes the device plugged in, so exit failure.
 *
 */
uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
        //uint8_t bAddress = 0;
        //printf("Configuring: parent = %i, port = %i\r\n", parent, port);
        uint8_t devConfigIndex;
        uint8_t rcode = 0;
        uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
        USB_DEVICE_DESCRIPTOR *udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR *>(buf);
        UsbDevice *p = NULL;
        EpInfo *oldep_ptr = NULL;
        EpInfo epInfo;

        epInfo.epAddr = 0;
        epInfo.maxPktSize = 8;
        epInfo.epAttribs = 0;
        epInfo.bmNakPower = USB_NAK_MAX_POWER;

        //delay(2000);
        AddressPool &addrPool = GetAddressPool();
        // Get pointer to pseudo device with address 0 assigned
        p = addrPool.GetUsbDevicePtr(0);
        if(!p) {
                //printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n");
                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
        }

        // 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 = getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);

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

        if(rcode) {
                //printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n");
                return rcode;
        }

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

        //if (!bAddress)
        //        return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
        uint16_t vid = udd->idVendor;
        uint16_t pid = udd->idProduct;
        uint8_t klass = udd->bDeviceClass;

        // Attempt to configure if VID/PID or device class matches with a driver
        for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
                if(!devConfig[devConfigIndex]) continue; // no driver
                if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
                if(devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass)) {
                        rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
                        if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED)
                                break;
                }
        }

        if(devConfigIndex < USB_NUMDEVICES) {
                return rcode;
        }


        // blindly attempt to configure
        for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
                if(!devConfig[devConfigIndex]) continue;
                if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
                if(devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass)) continue; // If this is true it means it must have returned USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED above
                rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);

                //printf("ERROR ENUMERATING %2.2x\r\n", rcode);
                if(!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)) {
                        // in case of an error dev_index should be reset to 0
                        //		in order to start from the very beginning the
                        //		next time the program gets here
                        //if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
                        //        devConfigIndex = 0;
                        return rcode;
                }
        }
        // if we get here that means that the device class is not supported by any of registered classes
        rcode = DefaultAddressing(parent, port, lowspeed);

        return rcode;
}
Beispiel #3
0
/*
 * This is broken. We need to enumerate differently.
 * It causes major problems with several devices if detected in an unexpected order.
 *
 *
 * Oleg - I wouldn't do anything before the newly connected device is considered sane.
 * i.e.(delays are not indicated for brevity):
 * 1. reset
 * 2. GetDevDescr();
 * 3a. If ACK, continue with allocating address, addressing, etc.
 * 3b. Else reset again, count resets, stop at some number (5?).
 * 4. When max.number of resets is reached, toggle power/fail
 * If desired, this could be modified by performing two resets with GetDevDescr() in the middle - however, from my experience, if a device answers to GDD()
 * it doesn't need to be reset again
 * New steps proposal:
 * 1: get address pool instance. exit on fail
 * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail.
 * 3: bus reset, 100ms delay
 * 4: set address
 * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail
 * 6: while (configurations) {
 *              for(each configuration) {
 *                      for (each driver) {
 *                              6a: Ask device if it likes configuration. Returns 0 on OK.
 *                                      If successful, the driver configured device.
 *                                      The driver now owns the endpoints, and takes over managing them.
 *                                      The following will need codes:
 *                                          Everything went well, instance consumed, exit with success.
 *                                          Instance already in use, ignore it, try next driver.
 *                                          Not a supported device, ignore it, try next driver.
 *                                          Not a supported configuration for this device, ignore it, try next driver.
 *                                          Could not configure device, fatal, exit with fail.
 *                      }
 *              }
 *    }
 * 7: for(each driver) {
 *      7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID
 * 8: if we get here, no driver likes the device plugged in, so exit failure.
 *
 */
uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
        //uint8_t bAddress = 0;
        //printf("Configuring: parent = %i, port = %i\r\n", parent, port);
        uint8_t devConfigIndex;
        uint8_t rcode = 0;
        uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
        UsbDevice *p = NULL;
        EpInfo *oldep_ptr = NULL;
        EpInfo epInfo;
        USB_OTG_CORE_HANDLE *pdev = coreConfig;

        epInfo.epAddr = 0;
        epInfo.maxPktSize = 8;
        epInfo.epAttribs = 0;
        epInfo.bmNakPower = USB_NAK_MAX_POWER;
		// assume:
		// HC0 for control - out
        // HC1 for control - in
        //uint8_t hcnum = USBH_GetFreeChannel(pdev);
        //if(hcnum > 1) {
        //	USBH_Free_Channel(pdev, epInfo.hcNumOut);
        //	USBH_Free_Channel(pdev, epInfo.hcNumIn);
        //}
        USBH_Free_Channel(pdev, 0);
        USBH_Free_Channel(pdev, 1);
		epInfo.hcNumOut = USBH_Alloc_Channel(pdev, 0x00);	// ep_addr = 0
		epInfo.hcNumIn = USBH_Alloc_Channel(pdev, 0x80);
		USBH_Open_Channel(pdev, epInfo.hcNumOut, 0x0, (lowspeed)?bmLOWSPEED:bmFULLSPEED, EP_TYPE_CTRL, 0x8);
		USBH_Open_Channel(pdev, epInfo.hcNumIn,	0x0, (lowspeed)?bmLOWSPEED:bmFULLSPEED, EP_TYPE_CTRL, 0x8);
		printf("\nControl Pipe: out = %d (0), in = %d (1)", epInfo.hcNumOut, epInfo.hcNumIn);

        delay_ms(1000);
        AddressPool &addrPool = GetAddressPool();
        // Get pointer to pseudo device with address 0 assigned
        p = addrPool.GetUsbDevicePtr(0);
        if (!p) {
			printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n");
			return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
        }

        // 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 = getDevDescr(0, 0, 8, (uint8_t*)buf);	// 8 should be enough, sizeof (USB_DEVICE_DESCRIPTOR)
        printf("\nControl - Got 1st 8 bytes desc");

        // Extract Max Packet Size from the device descriptor
        epInfo.maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
        //USB::USBH_Modify_Channel (pdev, epInfo.hcNumOut, 0, 0, 0, 0, epInfo.maxPktSize);
        //USB::USBH_Modify_Channel (pdev, epInfo.hcNumIn, 0, 0, 0, 0, epInfo.maxPktSize);

        // Restore p->epinfo
//         keep CtrlXfer's hcNumOut/In in p->epinfo. p->epinfo = oldep_ptr;

        if (rcode) {
            printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n");
            return rcode;
        }

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

        //if (!bAddress)
        //        return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
        rcode = getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
        printf("\nControl - Got 2nd 18 bytes desc.");

        uint16_t vid = (uint16_t)((USB_DEVICE_DESCRIPTOR*)buf)->idVendor;
        uint16_t pid = (uint16_t)((USB_DEVICE_DESCRIPTOR*)buf)->idProduct;
        uint8_t klass = ((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass;

        // Attempt to configure if VID/PID or device class matches with a driver
        for (devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
                if (!devConfig[devConfigIndex]) continue; // no driver
                if (devConfig[devConfigIndex]->GetAddress()) continue; // consumed
                if (devConfig[devConfigIndex]->VIDPIDOK(vid, pid)) {
					rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
					break;
                } else if (devConfig[devConfigIndex]->DEVCLASSOK(klass)) {
					rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
					if (!rcode) break;
                }
        }

        if (devConfigIndex < USB_NUMDEVICES) {
                return rcode;
        }


        // blindly attempt to configure
        for (devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
                if (!devConfig[devConfigIndex]) continue;
                if (devConfig[devConfigIndex]->GetAddress()) continue; // consumed
                rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);

                //printf("ERROR ENUMERATING %2.2x\r\n", rcode);
                if (!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)) {
                        // in case of an error dev_index should be reset to 0
                        //		in order to start from the very beginning the
                        //		next time the program gets here
                        //if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
                        //        devConfigIndex = 0;
                        return rcode;
                }
        }
        // if we get here that means that the device class is not supported by any of registered classes
        rcode = DefaultAddressing(parent, port, lowspeed);

        return rcode;
}