Example #1
0
// Assumption: The user has previously called usbComRxAvailable and its return value
// was greater than or equal to size.
void usbComRxReceive(uint8 XDATA* buffer, uint8 size)
{
    usbReadFifo(CDC_DATA_ENDPOINT, size, buffer);

    if (USBCNTL == 0)
    {
        USBCSOL &= ~USBCSOL_OUTPKT_RDY;   // Tell the USB module we are done reading this packet, so it can receive more.
    }
}
Example #2
0
void usbPoll()
{
    uint8 usbcif;
    uint8 usbiif;
    //uint8 usboif = USBOIF;

    if (!usbPowerPresent())
    {
        // The VBUS line is low.  This usually means that the USB cable has been
        // disconnected or the computer has been turned off.

        SLEEP &= ~(1<<7); // Disable the USB module (SLEEP.USB_EN = 0).

        disableUsbPullup();
        usbDeviceState = USB_STATE_DETACHED;
        usbSuspendMode = 0;
        return;
    }

    if (usbDeviceState == USB_STATE_DETACHED)
    {
        enableUsbPullup();
        SLEEP |= (1<<7);            // Enable the USB module (SLEEP.USB_EN = 1).
        __asm nop __endasm;         // Datasheet doesn't say so, but David suspects we need some NOPs here before writing to USB registers.
        __asm nop __endasm;
        __asm nop __endasm;
        __asm nop __endasm;
        usbDeviceState = USB_STATE_POWERED;

        basicUsbInit();
    }

    usbcif = USBCIF;
    usbiif = USBIIF;

    if (usbcif & (1<<0)) // Check SUSPENDIF
    {
        // The bus has been idle for 3 ms, so we are now in Suspend mode.
        // It is the user's responsibility to check usbSuspended() and go to sleep (PM1)
        // if necessary.
        usbSuspendMode = 1;
    }

    if (usbcif & (1<<2))  // check RSTIF, the reset flag
    {
        // A USB reset signal has been received.
        usbDeviceState = USB_STATE_DEFAULT;
        controlTransferState = CONTROL_TRANSFER_STATE_NONE;

        basicUsbInit();
    }

    if (usbcif & (1<<1)) // Check RESUMEIF
    {
        usbSuspendMode = 0;
    }

    if (usbiif & (1<<0)) // Check EP0IF
    {
        // Something happened on Endpoint 0, the endpoint for control transfers.
        uint8 usbcs0;
        USBINDEX = 0;
        usbcs0 = USBCS0;

        usbActivityFlag = 1;

        if (usbcs0 & (1<<4)) // Check SETUP_END
        {
            // A new setup packet has arrived, prematurely ending the previous control transfer.
            USBCS0 = 0x80; // Clear the SETUP_END bit
            controlTransferState = CONTROL_TRANSFER_STATE_NONE;
        }

        if (usbcs0 & (1<<2))  // Check SENT_STALL
        {
            // A STALL packet was sent
            USBCS0 = 0x00;  // Reset endpoint 0.
            controlTransferState = CONTROL_TRANSFER_STATE_NONE;
        }

        if (usbcs0 & (1<<0))  // Check OUTPKT_RDY
        {
            // Requirement: Every codepath from here must result in writing a 1 to
            // bit 6 of USBCS0 to clear the OUTPKT_RDY flag: USBCS0 = (1<<6).

            if (controlTransferState == CONTROL_TRANSFER_STATE_WRITE)
            {
                // A data packet has been received as part of a control write transfer.
                uint8 bytesReceived = USBCNT0;
                if (bytesReceived > controlTransferBytesLeft)
                {
                    bytesReceived = controlTransferBytesLeft;
                }
                usbReadFifo(0, bytesReceived, controlTransferPointer);
                controlTransferPointer += bytesReceived;
                controlTransferBytesLeft -= bytesReceived;

                if (controlTransferBytesLeft)
                {
                    // Arm the endpoint to receive more bytes
                    USBCS0 = (1<<6);  // De-asserts the OUTPKT_RDY bit (bit 0).
                }
                else
                {
                    // The host has sent all the data we were expecting.

                    if (usbSetupPacket.requestType != USB_REQUEST_TYPE_STANDARD) // OPT: remove this check
                    {
                        usbCallbackControlWriteHandler();
                    }

                    USBINDEX = 0;  // Just in case USBINDEX was changed above.

                    if (controlTransferState == CONTROL_TRANSFER_STATE_NONE)
                    {
                        // The data received was invalid.
                        USBCS0 = (1<<6) | (1<<3) | (1<<5); // clear OUTPKT_RDY, set DATA_END, SEND_STALL
                    }
                    else
                    {
                        // The data received was valid.
                        USBCS0 = (1<<6) | (1<<3); // clear OUTPKT_RDY, set DATA_END
                        controlTransferState = CONTROL_TRANSFER_STATE_NONE;
                    }
                }
            }
            else if (USBCNT0 == 8)
            {
                // A SETUP packet has been received from the computer, starting a new
                // control transfer.

                usbReadFifo(0, 8, (uint8 XDATA *)&usbSetupPacket); // Store the data in usbSetupPacket.

                // Wipe out the information about the last control transfer.
                controlTransferState = CONTROL_TRANSFER_STATE_NONE;

                if (usbSetupPacket.requestType == USB_REQUEST_TYPE_STANDARD)
                {
                    // The request_type field indicates that this is a Standard Device Request
                    // as described in USB2.0 Chapter 9.4 Standard Device Requests.
                    // These requests are handled by the library in the function below.
                    usbStandardDeviceRequestHandler();
                }
                else
                {
                    // Otherwise, we use this callback so the user can decide how to handle the
                    // setup packet.  In this callback, the user can call various helper
                    // functions that set controlTransferState.
                    usbCallbackSetupHandler();
                }

                USBINDEX = 0;  // Select EP0 again because the functions above might have changed USBINDEX.

                // Modify the count so that we don't send more data than the host requested.
                if(controlTransferBytesLeft > usbSetupPacket.wLength)
                {
                    controlTransferBytesLeft = usbSetupPacket.wLength;
                }

                // Prepare for the first transaction after the SETUP packet.
                if (controlTransferState == CONTROL_TRANSFER_STATE_NONE)
                {
                    // This is invalid/unrecognized control transfer, so send a STALL packet.
                    USBCS0 = (1<<6) | (1<<5); // Clears the OUTPKT_RDY flag because we've handled it, and sends a STALL.
                }
                else if (controlTransferState == CONTROL_TRANSFER_STATE_WRITE)
                {
                    if (controlTransferBytesLeft)
                    {
                        // Arm the endpoint to receive the first data packet of a control write transfer.
                        USBCS0 = (1<<6);  // De-asserts the OUTPKT_RDY bit.
                    }
                    else
                    {
                        // Acknowledge a control write transfer with no data phase.
                        USBCS0 = (1<<6) | (1<<3) | (1<<1);  // De-asserts OUTPKY_RDY, asserts DATA_END, asserts INPKT_RDY.
                        controlTransferState = CONTROL_TRANSFER_STATE_NONE;
                    }
                }
            }
            else
            {
                // An OUT packet was received on Endpoint 0, but we are not in the middle of a
                // control write transfer and it was not the right length to be a setup packet.
                // This situation is not expected.
                USBCS0 = (1<<6);  // De-asserts the OUTPKT_RDY.
            }
        }

        if (!(usbcs0 & (1<<1)) && (controlTransferState == CONTROL_TRANSFER_STATE_READ))
        {
            // We are doing a control read transfer, and Endpoint 0 is ready to accept another
            // IN packet to send to the computer.
            uint8 bytesToSend;
            if (controlTransferBytesLeft < USB_EP0_PACKET_SIZE)
            {
                // Send the last packet (might be an empty packet).
                usbcs0 = (1<<1)|(1<<3);  // INPKT_RDY and DATA_END
                bytesToSend = controlTransferBytesLeft;
                controlTransferState = CONTROL_TRANSFER_STATE_NONE;
            }
            else
            {
                // Send a packet.
                usbcs0 = (1<<1); // INPKT_RDY
                bytesToSend = USB_EP0_PACKET_SIZE;
            }

            // Arm endpoint 0 to send the next packet.
            usbWriteFifo(0, bytesToSend, controlTransferPointer);
            USBCS0 = usbcs0;

            // Update the control transfer state.
            controlTransferPointer += bytesToSend;
            controlTransferBytesLeft -= bytesToSend;
        }
    }
}