⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbd_udp.c

📁 Atmel的AT91SAM9263芯片的usb HID设备keyboard的源程序
💻 C
📖 第 1 页 / 共 3 页
字号:
    Parameters:
        eptnum - Endpoint number.
        data - Pointer to a buffer with the data to send.
        size - Size of the data buffer.
        callback - Optional callback function to invoke when the transfer is
                   complete.
        argument - Optional argument to the callback function.

    Returns:
        USBD_STATUS_SUCCESS if the transfer has been started; otherwise, the
        corresponding error status code.
*/
char USBD_Write(unsigned char eptnum,
                const void *data,
                unsigned int size,
                TransferCallback callback,
                void *argument)
{
    Endpoint *endpoint = &(endpoints[eptnum]);
    Transfer *transfer = &(endpoint->transfer);

    // Check that the endpoint is in Idle state
    if (endpoint->state != UDP_ENDPOINT_IDLE) {

        return USBD_STATUS_LOCKED;
    }

    trace_LOG(trace_INFO, "Write%d(%d) ", eptnum, size);

    // Setup the transfer descriptor
    transfer->data = (void *) data;
    transfer->remaining = size;
    transfer->buffered = 0;
    transfer->transferred = 0;
    transfer->callback = callback;
    transfer->argument = argument;

    // Send the first packet
    endpoint->state = UDP_ENDPOINT_SENDING;
    UDP_WritePayload(eptnum);
    SET_CSR(eptnum, AT91C_UDP_TXPKTRDY);

    // If double buffering is enabled and there is data remaining,
    // prepare another packet
    if ((BOARD_USB_ENDPOINTS_BANKS(eptnum) > 1) && (transfer->remaining > 0)) {

        UDP_WritePayload(eptnum);
    }

    // Enable interrupt on endpoint
    AT91C_BASE_UDP->UDP_IER |= 1 << eptnum;

    return USBD_STATUS_SUCCESS;
}

/*
    Function: USBD_Read
        Reads incoming data on an USB endpoint This methods sets the transfer
        descriptor and activate the endpoint interrupt. The actual transfer is
        then carried out by the endpoint interrupt handler. The Read operation
        finishes either when the buffer is full, or a short packet (inferior to
        endpoint maximum  size) is received.

        *The buffer must be kept allocated until the transfer is finished*.

    Parameters:
        eptnum - Endpoint number.
        data - Pointer to a data buffer.
        size - Size of the data buffer in bytes.
        callback - Optional end-of-transfer callback function.
        argument - Optional argument to the callback function.

    Returns:
        USBD_STATUS_SUCCESS if the read operation has been started; otherwise,
        the corresponding error code.
*/
char USBD_Read(unsigned char eptnum,
               void *data,
               unsigned int size,
               TransferCallback callback,
               void *argument)
{
    Endpoint *endpoint = &(endpoints[eptnum]);
    Transfer *transfer = &(endpoint->transfer);

    // Return if the endpoint is not in IDLE state
    if (endpoint->state != UDP_ENDPOINT_IDLE) {

        return USBD_STATUS_LOCKED;
    }

    trace_LOG(trace_INFO, "Read%d(%d) ", eptnum, size);

    // Endpoint enters Receiving state
    endpoint->state = UDP_ENDPOINT_RECEIVING;

    // Set the transfer descriptor
    transfer->data = data;
    transfer->remaining = size;
    transfer->buffered = 0;
    transfer->transferred = 0;
    transfer->callback = callback;
    transfer->argument = argument;

    // Enable interrupt on endpoint
    AT91C_BASE_UDP->UDP_IER |= 1 << eptnum;

    return USBD_STATUS_SUCCESS;
}

/*
    Function: USBD_Halt
        Sets the HALT feature on the given endpoint (if not already in this
        state).

    Parameters:
        eptnum - Endpoint number.
*/
void USBD_Halt(unsigned char eptnum)
{
    Endpoint *endpoint = &(endpoints[eptnum]);
    
    // Check that endpoint is enabled and not already in Halt state
    if ((endpoint->state != UDP_ENDPOINT_DISABLED)
        && (endpoint->state != UDP_ENDPOINT_HALTED)) {

        trace_LOG(trace_INFO, "Halt%d ", eptnum);

        // Abort the current transfer if necessary
        UDP_EndOfTransfer(eptnum, USBD_STATUS_ABORTED);

        // Put endpoint into Halt state
        SET_CSR(eptnum, AT91C_UDP_FORCESTALL);
        endpoint->state = UDP_ENDPOINT_HALTED;

        // Enable the endpoint interrupt
        AT91C_BASE_UDP->UDP_IER |= 1 << eptnum;
    }
}

/*
    Function: USBD_Unhalt
        Clears the Halt feature on the given endpoint.

    Parameters:
        eptnum - Endpoint number.
*/
void USBD_Unhalt(unsigned char eptnum)
{
    Endpoint *endpoint = &(endpoints[eptnum]);

    // Check if the endpoint is enabled
    if (endpoint->state != UDP_ENDPOINT_DISABLED) {

        trace_LOG(trace_INFO, "Unhalt%d ", eptnum);

        // Return endpoint to Idle state
        endpoint->state = UDP_ENDPOINT_IDLE;

        // Clear FORCESTALL flag
        CLEAR_CSR(eptnum, AT91C_UDP_FORCESTALL);

        // Reset Endpoint Fifos, beware this is a 2 steps operation
        AT91C_BASE_UDP->UDP_RSTEP |= 1 << eptnum;
        AT91C_BASE_UDP->UDP_RSTEP &= ~(1 << eptnum);
    }
}
    
/*
    Function: USBD_IsHalted
        Returns the current Halt status of an endpoint.

    Parameters:
        eptnum - Endpoint number.

    Returns:
        1 if the endpoint is currently halted; otherwise 0.
*/
unsigned char USBD_IsHalted(unsigned char eptnum)
{
    Endpoint *endpoint = &(endpoints[eptnum]);
    if (endpoint->state == UDP_ENDPOINT_HALTED) {

        return 1;
    }
    else {

        return 0;
    }
}

/*
    Function: USBD_Stall
        Causes the given endpoint to acknowledge the next packet it receives
        with a STALL handshake.

    Parameters:
        eptnum - Endpoint number.

    Returns:
        USBD_STATUS_SUCCESS or USBD_STATUS_LOCKED.
*/
unsigned char USBD_Stall(unsigned char eptnum)
{
    Endpoint *endpoint = &(endpoints[eptnum]);

    // Check that endpoint is in Idle state
    if (endpoint->state != UDP_ENDPOINT_IDLE) {

        trace_LOG(trace_WARNING, "USBD_Stall: Endpoint%d locked\n\r", eptnum);
        return USBD_STATUS_LOCKED;
    }

    trace_LOG(trace_INFO, "Stall%d ", eptnum);
    SET_CSR(eptnum, AT91C_UDP_FORCESTALL);

    return USBD_STATUS_SUCCESS;
}

/*
    Function: USBD_RemoteWakeUp
        Starts a remote wake-up procedure.
*/
void USBD_RemoteWakeUp()
{
    UDP_EnablePeripheralClock();
    UDP_EnableUsbClock();
    UDP_EnableTransceiver();

    trace_LOG(trace_INFO, "RWUp ");

    // Activates a remote wakeup (edge on ESR), then clear ESR
    AT91C_BASE_UDP->UDP_GLBSTATE |= AT91C_UDP_ESR;
    AT91C_BASE_UDP->UDP_GLBSTATE &= ~AT91C_UDP_ESR;
}

/*
    Function: USBD_SetAddress
        Sets the device address to the given value.

    Parameters:
        address - New device address.
*/
void USBD_SetAddress(unsigned char address)
{
    trace_LOG(trace_INFO, "SetAddr(%d) ", address);

    // Set address
    AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN | address;

    // If the address is 0, the device returns to the Default state
    if (address == 0) {

        AT91C_BASE_UDP->UDP_GLBSTATE = 0;
        deviceState = USBD_STATE_DEFAULT;
    }
    // If the address is non-zero, the device enters the Address state
    else {

        AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
        deviceState = USBD_STATE_ADDRESS;
    }
}

/*
    Function: USBD_SetConfiguration
        Sets the current device configuration.

    Parameters:
        cfgnum - Configuration number to set.
*/
void USBD_SetConfiguration(unsigned char cfgnum)
{
    trace_LOG(trace_INFO, "SetCfg(%d) ", cfgnum);

    // If the configuration number if non-zero, the device enters the
    // Configured state
    if (cfgnum != 0) {

        deviceState = USBD_STATE_CONFIGURED;
        AT91C_BASE_UDP->UDP_GLBSTATE |= AT91C_UDP_CONFG;
    }
    // If the configuration number is zero, the device goes back to the Address
    // state
    else {

        deviceState = USBD_STATE_ADDRESS;
        AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;

        // Abort all transfers
        UDP_DisableEndpoints();
    }
}

/*
    Function: USBD_Connect
        Connects the pull-up on the D+ line of the USB.
*/
void USBD_Connect()
{
    trace_LOG(trace_DEBUG, "Conn ");

#if defined(BOARD_USB_PULLUP_EXTERNAL)
    const Pin pinPullUp = PIN_USB_PULLUP;
    if (pinPullUp.attribute == PIO_OUTPUT_0) {

        PIO_Set(&pinPullUp);
    }
    else {

        PIO_Clear(&pinPullUp);
    }
#elif defined(BOARD_USB_PULLUP_INTERNAL)
    AT91C_BASE_UDP->UDP_TXVC |= AT91C_UDP_PUON;
#elif defined(BOARD_USB_PULLUP_MATRIX)
    AT91C_BASE_MATRIX->MATRIX_USBPCR |= AT91C_MATRIX_USBPCR_PUON;
#elif !defined(BOARD_USB_PULLUP_ALWAYSON)
    #error Unsupported pull-up type.
#endif
}

/*
    Function: USBD_Disconnect
        Disconnects the pull-up from the D+ line of the USB.
*/
void USBD_Disconnect()
{
    trace_LOG(trace_DEBUG, "Disc ");

#if defined(BOARD_USB_PULLUP_EXTERNAL)
    const Pin pinPullUp = PIN_USB_PULLUP;
    if (pinPullUp.attribute == PIO_OUTPUT_0) {

        PIO_Clear(&pinPullUp);
    }
    else {

        PIO_Set(&pinPullUp);
    }
#elif defined(BOARD_USB_PULLUP_INTERNAL)
    AT91C_BASE_UDP->UDP_TXVC &= ~AT91C_UDP_PUON;
#elif defined(BOARD_USB_PULLUP_MATRIX)
    AT91C_BASE_MATRIX->MATRIX_USBPCR &= ~AT91C_MATRIX_USBPCR_PUON;
#elif !defined(BOARD_USB_PULLUP_ALWAYSON)
    #error Unsupported pull-up type.
#endif

    // Device returns to the Powered state
    if (deviceState > USBD_STATE_POWERED) {
    
        deviceState = USBD_STATE_POWERED;
    }
}

/*
    Function: USBD_Init
        Initializes the USB driver.
*/
void USBD_Init()
{
    trace_LOG(trace_INFO, "USBD_Init\n\r");

    // Reset endpoint structures
    UDP_ResetEndpoints();

    // Configure the pull-up on D+ and disconnect it
#if defined(BOARD_USB_PULLUP_EXTERNAL)
    const Pin pinPullUp = PIN_USB_PULLUP;
    PIO_Configure(&pinPullUp, 1);
#elif defined(BOARD_USB_PULLUP_INTERNAL)
    AT91C_BASE_UDP->UDP_TXVC &= ~AT91C_UDP_PUON;
#elif defined(BOARD_USB_PULLUP_MATRIX)
    AT91C_BASE_MATRIX->MATRIX_USBPCR &= ~AT91C_MATRIX_USBPCR_PUON;
#elif !defined(BOARD_USB_PULLUP_ALWAYSON)
    #error Missing pull-up definition.
#endif

    // Device is in the Attached state
    deviceState = USBD_STATE_SUSPENDED;
    previousDeviceState = USBD_STATE_POWERED;
    UDP_EnablePeripheralClock();
    UDP_EnableUsbClock();
    AT91C_BASE_UDP->UDP_IER = AT91C_UDP_WAKEUP;

    // Configure interrupts
    USBDCallbacks_Initialized();
}

/*
    Function: USBD_GetState
        Returns the current state of the USB device.

    Returns:
        Device current state.
*/
unsigned char USBD_GetState()
{
    return deviceState;
}

//------------------------------------------------------------------------------
/// Indicates if the device is running in high or full-speed. Always returns 0
/// since UDP does not support high-speed mode.
//------------------------------------------------------------------------------
unsigned char USBD_IsHighSpeed(void)
{
    return 0;
}


#endif //#if defined(BOARD_USB_UDP)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -