558 lines
15 KiB
C
558 lines
15 KiB
C
/*
|
|
Copyright (c) 2014 Arduino LLC. All right reserved.
|
|
SAMD51 support added by Adafruit - Copyright (c) 2018 Dean Miller for Adafruit Industries
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
See the GNU Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#ifndef USE_TINYUSB
|
|
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
#include "../Arduino.h"
|
|
#include "variant.h"
|
|
#include "USB_host.h"
|
|
#include "samd21_host.h"
|
|
#include "sam.h"
|
|
#include "wiring_digital.h"
|
|
#include "wiring_private.h"
|
|
|
|
#define HOST_DEFINED
|
|
#ifdef HOST_DEFINED
|
|
|
|
//#define TRACE_UOTGHS_HOST(x) x
|
|
#define TRACE_UOTGHS_HOST(x)
|
|
|
|
// Handle UOTGHS Host driver state
|
|
static uhd_vbus_state_t uhd_state = UHD_STATE_NO_VBUS;
|
|
|
|
__attribute__((__aligned__(4))) volatile UsbHostDescriptor usb_pipe_table[USB_EPT_NUM];
|
|
|
|
extern void (*gpf_isr)(void);
|
|
|
|
|
|
// NVM Software Calibration Area Mapping
|
|
// USB TRANSN calibration value. Should be written to the USB PADCAL register.
|
|
#define NVM_USB_PAD_TRANSN_POS 45
|
|
#define NVM_USB_PAD_TRANSN_SIZE 5
|
|
// USB TRANSP calibration value. Should be written to the USB PADCAL register.
|
|
#define NVM_USB_PAD_TRANSP_POS 50
|
|
#define NVM_USB_PAD_TRANSP_SIZE 5
|
|
// USB TRIM calibration value. Should be written to the USB PADCAL register.
|
|
#define NVM_USB_PAD_TRIM_POS 55
|
|
#define NVM_USB_PAD_TRIM_SIZE 3
|
|
|
|
/**
|
|
* \brief Initialize the SAMD21 host driver.
|
|
*/
|
|
void UHD_Init(void)
|
|
{
|
|
uint32_t pad_transn;
|
|
uint32_t pad_transp;
|
|
uint32_t pad_trim;
|
|
|
|
USB_SetHandler(&UHD_Handler);
|
|
|
|
/* Enable USB clock */
|
|
#if defined(__SAMD51__)
|
|
MCLK->APBBMASK.reg |= MCLK_APBBMASK_USB;
|
|
#else
|
|
PM->APBBMASK.reg |= PM_APBBMASK_USB;
|
|
#endif
|
|
|
|
/* Set up the USB DP/DM pins */
|
|
pinPeripheral( PIN_USB_DM, PIO_COM );
|
|
pinPeripheral( PIN_USB_DP, PIO_COM );
|
|
// PORT->Group[0].PINCFG[PIN_PA24G_USB_DM].bit.PMUXEN = 1;
|
|
// PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24G_USB_DM & 0x01u)));
|
|
// PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg |= MUX_PA24G_USB_DM << (4 * (PIN_PA24G_USB_DM & 0x01u));
|
|
// PORT->Group[0].PINCFG[PIN_PA25G_USB_DP].bit.PMUXEN = 1;
|
|
// PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25G_USB_DP & 0x01u)));
|
|
// PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg |= MUX_PA25G_USB_DP << (4 * (PIN_PA25G_USB_DP & 0x01u));
|
|
|
|
|
|
/* ----------------------------------------------------------------------------------------------
|
|
* Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference)
|
|
*/
|
|
|
|
#if defined(__SAMD51__)
|
|
GCLK->PCHCTRL[USB_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
|
|
#else
|
|
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(6) | // Generic Clock Multiplexer 6
|
|
GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
|
|
GCLK_CLKCTRL_CLKEN;
|
|
|
|
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY)
|
|
{
|
|
/* Wait for synchronization */
|
|
}
|
|
#endif
|
|
|
|
/* Reset */
|
|
USB->HOST.CTRLA.bit.SWRST = 1;
|
|
while (USB->HOST.SYNCBUSY.bit.SWRST)
|
|
{
|
|
/* Sync wait */
|
|
}
|
|
|
|
// uhd_enable();
|
|
USB->DEVICE.CTRLA.reg |= USB_CTRLA_ENABLE | USB_CTRLA_MODE;
|
|
uhd_force_host_mode();
|
|
while (USB->HOST.SYNCBUSY.reg == USB_SYNCBUSY_ENABLE);
|
|
|
|
|
|
/* Load Pad Calibration */
|
|
#if defined(__SAMD51__)
|
|
pad_transn = (*((uint32_t *)(NVMCTRL_SW0) // Non-Volatile Memory Controller
|
|
#else
|
|
pad_transn = (*((uint32_t *)(NVMCTRL_OTP4) // Non-Volatile Memory Controller
|
|
#endif
|
|
|
|
+ (NVM_USB_PAD_TRANSN_POS / 32))
|
|
>> (NVM_USB_PAD_TRANSN_POS % 32))
|
|
& ((1 << NVM_USB_PAD_TRANSN_SIZE) - 1);
|
|
|
|
if (pad_transn == 0x1F) // maximum value (31)
|
|
{
|
|
pad_transn = 5;
|
|
}
|
|
|
|
USB->HOST.PADCAL.bit.TRANSN = pad_transn;
|
|
|
|
#if defined(__SAMD51__)
|
|
pad_transp = (*((uint32_t *)(NVMCTRL_SW0)
|
|
#else
|
|
pad_transp = (*((uint32_t *)(NVMCTRL_OTP4)
|
|
#endif
|
|
+ (NVM_USB_PAD_TRANSP_POS / 32))
|
|
>> (NVM_USB_PAD_TRANSP_POS % 32))
|
|
& ((1 << NVM_USB_PAD_TRANSP_SIZE) - 1);
|
|
|
|
if (pad_transp == 0x1F) // maximum value (31)
|
|
{
|
|
pad_transp = 29;
|
|
}
|
|
|
|
USB->HOST.PADCAL.bit.TRANSP = pad_transp;
|
|
|
|
#if defined(__SAMD51__)
|
|
pad_trim = (*((uint32_t *)(NVMCTRL_SW0)
|
|
#else
|
|
pad_trim = (*((uint32_t *)(NVMCTRL_OTP4)
|
|
#endif
|
|
+ (NVM_USB_PAD_TRIM_POS / 32))
|
|
>> (NVM_USB_PAD_TRIM_POS % 32))
|
|
& ((1 << NVM_USB_PAD_TRIM_SIZE) - 1);
|
|
|
|
if (pad_trim == 0x7) // maximum value (7)
|
|
{
|
|
pad_trim = 3;
|
|
}
|
|
|
|
USB->HOST.PADCAL.bit.TRIM = pad_trim;
|
|
|
|
|
|
/* Set the configuration */
|
|
uhd_run_in_standby();
|
|
// Set address of USB SRAM
|
|
USB->HOST.DESCADD.reg = (uint32_t)(&usb_pipe_table[0]);
|
|
// For USB_SPEED_FULL
|
|
uhd_force_full_speed();
|
|
memset((void *)usb_pipe_table, 0, sizeof(usb_pipe_table));
|
|
|
|
uhd_state = UHD_STATE_NO_VBUS;
|
|
|
|
// Put VBUS on USB port
|
|
pinMode( PIN_USB_HOST_ENABLE, OUTPUT );
|
|
digitalWrite( PIN_USB_HOST_ENABLE, HIGH );
|
|
|
|
uhd_enable_connection_int();
|
|
|
|
USB->HOST.INTENSET.reg = USB_HOST_INTENSET_DCONN;
|
|
USB->HOST.INTENSET.reg = USB_HOST_INTENSET_WAKEUP;
|
|
USB->HOST.INTENSET.reg = USB_HOST_INTENSET_DDISC;
|
|
|
|
USB->HOST.CTRLB.bit.VBUSOK = 1;
|
|
|
|
// Configure interrupts
|
|
#if defined(__SAMD51__)
|
|
NVIC_SetPriority((IRQn_Type)USB_0_IRQn, 0UL);
|
|
NVIC_SetPriority((IRQn_Type)USB_1_IRQn, 0UL);
|
|
NVIC_SetPriority((IRQn_Type)USB_2_IRQn, 0UL);
|
|
NVIC_SetPriority((IRQn_Type)USB_3_IRQn, 0UL);
|
|
|
|
NVIC_EnableIRQ((IRQn_Type)USB_0_IRQn);
|
|
NVIC_EnableIRQ((IRQn_Type)USB_1_IRQn);
|
|
NVIC_EnableIRQ((IRQn_Type)USB_2_IRQn);
|
|
NVIC_EnableIRQ((IRQn_Type)USB_3_IRQn);
|
|
#else
|
|
NVIC_SetPriority((IRQn_Type)USB_IRQn, 0UL);
|
|
NVIC_EnableIRQ((IRQn_Type)USB_IRQn);
|
|
#endif
|
|
}
|
|
|
|
|
|
/**
|
|
* \brief Interrupt sub routine for USB Host state machine management.
|
|
*/
|
|
void UHD_Handler(void)
|
|
{
|
|
uint16_t flags;
|
|
|
|
if (USB->HOST.CTRLA.bit.MODE) {
|
|
/*host mode ISR */
|
|
|
|
/* get interrupt flags */
|
|
flags = USB->HOST.INTFLAG.reg;
|
|
|
|
/* host SOF interrupt */
|
|
if (flags & USB_HOST_INTFLAG_HSOF)
|
|
{
|
|
/* clear the flag */
|
|
USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_HSOF;
|
|
uhd_state = UHD_STATE_CONNECTED;
|
|
return;
|
|
}
|
|
|
|
/* host reset interrupt */
|
|
if (flags & USB_HOST_INTFLAG_RST)
|
|
{
|
|
/* clear the flag */
|
|
USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_RST;
|
|
uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
|
|
return;
|
|
}
|
|
|
|
/* host upstream resume interrupts */
|
|
if (flags & USB_HOST_INTFLAG_UPRSM)
|
|
{
|
|
/* clear the flags */
|
|
USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_UPRSM;
|
|
uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
|
|
return;
|
|
}
|
|
|
|
/* host downstream resume interrupts */
|
|
if (flags & USB_HOST_INTFLAG_DNRSM)
|
|
{
|
|
/* clear the flags */
|
|
USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_DNRSM;
|
|
uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
|
|
return;
|
|
}
|
|
|
|
/* host wakeup interrupts */
|
|
if (flags & USB_HOST_INTFLAG_WAKEUP)
|
|
{
|
|
/* clear the flags */
|
|
USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_WAKEUP;
|
|
uhd_state = UHD_STATE_CONNECTED; //UHD_STATE_ERROR;
|
|
return;
|
|
}
|
|
|
|
/* host ram access interrupt */
|
|
if (flags & USB_HOST_INTFLAG_RAMACER)
|
|
{
|
|
/* clear the flag */
|
|
USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_RAMACER;
|
|
uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
|
|
return;
|
|
}
|
|
|
|
/* host connect interrupt */
|
|
if (flags & USB_HOST_INTFLAG_DCONN)
|
|
{
|
|
TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Connection INT\r\n");
|
|
)
|
|
/* clear the flag */
|
|
uhd_ack_connection();
|
|
uhd_disable_connection_int();
|
|
uhd_ack_disconnection();
|
|
uhd_enable_disconnection_int();
|
|
//uhd_enable_sof();
|
|
uhd_state = UHD_STATE_CONNECTED;
|
|
return;
|
|
}
|
|
|
|
/* host disconnect interrupt */
|
|
if (flags & USB_HOST_INTFLAG_DDISC)
|
|
{
|
|
TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Disconnection INT\r\n");
|
|
)
|
|
/* clear the flag */
|
|
uhd_ack_disconnection();
|
|
uhd_disable_disconnection_int();
|
|
// Stop reset signal, in case of disconnection during reset
|
|
uhd_stop_reset();
|
|
// Disable wakeup/resumes interrupts,
|
|
// in case of disconnection during suspend mode
|
|
uhd_ack_connection();
|
|
uhd_enable_connection_int();
|
|
uhd_state = UHD_STATE_DISCONNECTED;
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
while(1);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* \brief Get VBUS state.
|
|
*
|
|
* \return VBUS status.
|
|
*/
|
|
uhd_vbus_state_t UHD_GetVBUSState(void)
|
|
{
|
|
return uhd_state;
|
|
}
|
|
|
|
|
|
/**
|
|
* \brief Allocate FIFO for pipe 0.
|
|
*
|
|
* \param ul_add Address of remote device for pipe 0.
|
|
* \param ul_ep_size Actual size of the FIFO in bytes.
|
|
*
|
|
* \retval 0 success.
|
|
* \retval 1 error.
|
|
*/
|
|
uint32_t UHD_Pipe0_Alloc(uint32_t ul_add , uint32_t ul_ep_size)
|
|
{
|
|
(void)(ul_add); // Unused argument
|
|
|
|
if( USB->HOST.STATUS.reg & USB_HOST_STATUS_SPEED(1) )
|
|
ul_ep_size = USB_PCKSIZE_SIZE_8_BYTES; // Low Speed
|
|
else
|
|
ul_ep_size = USB_PCKSIZE_SIZE_64_BYTES; // Full Speed
|
|
|
|
USB->HOST.HostPipe[0].PCFG.bit.PTYPE = 1; //USB_HOST_PCFG_PTYPE_CTRL;
|
|
usb_pipe_table[0].HostDescBank[0].CTRL_PIPE.bit.PEPNUM = 0;
|
|
usb_pipe_table[0].HostDescBank[0].PCKSIZE.bit.SIZE = ul_ep_size;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* \brief Allocate a new pipe.
|
|
*
|
|
* \note UOTGHS maximum pipe number is limited to 10, meaning that only a limited
|
|
* amount of devices can be connected. Unfortunately, using only one pipe shared accross
|
|
* various endpoints and devices is not possible because the UOTGHS IP does not allow to
|
|
* change the data toggle value through register interface.
|
|
*
|
|
* \param ul_dev_addr Address of remote device.
|
|
* \param ul_dev_ep Targeted endpoint of remote device.
|
|
* \param ul_type Pipe type.
|
|
* \param ul_dir Pipe direction.
|
|
* \param ul_maxsize Pipe size.
|
|
* \param ul_interval Polling interval (if applicable to pipe type).
|
|
* \param ul_nb_bank Number of banks associated with this pipe.
|
|
*
|
|
* \return 1.
|
|
*/
|
|
uint32_t UHD_Pipe_Alloc(uint32_t ul_dev_addr, uint32_t ul_dev_ep, uint32_t ul_type, uint32_t ul_dir, uint32_t ul_maxsize, uint32_t ul_interval, uint32_t ul_nb_bank)
|
|
{
|
|
/* set pipe config */
|
|
USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.BK = ul_nb_bank;
|
|
// PTYPE:
|
|
USB->HOST.HostPipe[ul_dev_ep].PCFG.reg &= ~USB_HOST_PCFG_MASK; // USB->HOST.HostPipe[0].PCFG.bit.PTYPE = 1; //USB_HOST_PCFG_PTYPE_CTRL;
|
|
USB->HOST.HostPipe[ul_dev_ep].PCFG.reg |= ul_type;
|
|
USB->HOST.HostPipe[ul_dev_ep].BINTERVAL.reg = ul_interval;
|
|
|
|
if (ul_dir & USB_EP_DIR_IN)
|
|
{
|
|
USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.PTOKEN = USB_HOST_PCFG_PTOKEN_IN;
|
|
USB->HOST.HostPipe[ul_dev_ep].PSTATUSSET.reg = USB_HOST_PSTATUSSET_BK0RDY;
|
|
}
|
|
else
|
|
{
|
|
USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.PTOKEN = USB_HOST_PCFG_PTOKEN_OUT;
|
|
USB->HOST.HostPipe[ul_dev_ep].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_BK0RDY;
|
|
}
|
|
|
|
if( USB->HOST.STATUS.reg & USB_HOST_STATUS_SPEED(1) )
|
|
ul_maxsize = USB_PCKSIZE_SIZE_8_BYTES; // Low Speed
|
|
else
|
|
ul_maxsize = USB_PCKSIZE_SIZE_64_BYTES; // Full Speed
|
|
|
|
memset((uint8_t *)&usb_pipe_table[ul_dev_ep], 0, sizeof(usb_pipe_table[ul_dev_ep]));
|
|
|
|
usb_pipe_table[ul_dev_ep].HostDescBank[0].CTRL_PIPE.bit.PDADDR = ul_dev_addr;
|
|
usb_pipe_table[ul_dev_ep].HostDescBank[0].CTRL_PIPE.bit.PEPNUM = ul_dev_ep;
|
|
usb_pipe_table[ul_dev_ep].HostDescBank[0].PCKSIZE.bit.SIZE = ul_maxsize;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
void UHD_Pipe_CountZero(uint32_t ul_pipe)
|
|
{
|
|
usb_pipe_table[ul_pipe].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
|
|
}
|
|
|
|
/**
|
|
* \brief Free a pipe.
|
|
*
|
|
* \param ul_pipe Pipe number to free.
|
|
*/
|
|
void UHD_Pipe_Free(uint32_t ul_pipe)
|
|
{
|
|
// The Pipe is frozen and no additional requests will be sent to the device on this pipe address.
|
|
USB->HOST.HostPipe[ul_pipe].PSTATUSSET.reg = USB_HOST_PSTATUSSET_PFREEZE;
|
|
}
|
|
|
|
|
|
/**
|
|
* \brief Read from a pipe.
|
|
*
|
|
* \param ul_pipe Pipe number.
|
|
* \param ul_size Maximum number of data to read.
|
|
* \param data Buffer to store the data.
|
|
*
|
|
* \return number of data read.
|
|
*/
|
|
uint32_t UHD_Pipe_Read(uint32_t pipe_num, uint32_t buf_size, uint8_t *buf)
|
|
{
|
|
if (USB->HOST.HostPipe[pipe_num].PCFG.bit.PTYPE == USB_HOST_PTYPE_DIS)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* get pipe config from setting register */
|
|
usb_pipe_table[pipe_num].HostDescBank[0].ADDR.reg = (uint32_t)buf;
|
|
usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
|
|
usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = buf_size;
|
|
USB->HOST.HostPipe[pipe_num].PCFG.bit.PTOKEN = USB_HOST_PCFG_PTOKEN_IN;
|
|
|
|
/* Start transfer */
|
|
USB->HOST.HostPipe[pipe_num].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_BK0RDY;
|
|
|
|
// Unfreeze pipe
|
|
USB->HOST.HostPipe[pipe_num].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_PFREEZE;
|
|
|
|
return buf_size;
|
|
}
|
|
|
|
|
|
/**
|
|
* \brief Write into a pipe.
|
|
*
|
|
* \param ul_pipe Pipe number.
|
|
* \param ul_size Maximum number of data to read.
|
|
* \param data Buffer containing data to write.
|
|
*/
|
|
void UHD_Pipe_Write(uint32_t ul_pipe, uint32_t ul_size, uint8_t *buf)
|
|
{
|
|
/* get pipe config from setting register */
|
|
usb_pipe_table[ul_pipe].HostDescBank[0].ADDR.reg = (uint32_t)buf;
|
|
usb_pipe_table[ul_pipe].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = ul_size;
|
|
usb_pipe_table[ul_pipe].HostDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 0;
|
|
}
|
|
|
|
/**
|
|
* \brief Send a pipe content.
|
|
*
|
|
* \param ul_pipe Pipe number.
|
|
* \param ul_token_type Token type.
|
|
*/
|
|
void UHD_Pipe_Send(uint32_t ul_pipe, uint32_t ul_token_type)
|
|
{
|
|
USB->HOST.HostPipe[ul_pipe].PCFG.bit.PTOKEN = ul_token_type;
|
|
|
|
/* Start transfer */
|
|
if(ul_token_type == USB_HOST_PCFG_PTOKEN_SETUP )
|
|
{
|
|
USB->HOST.HostPipe[ul_pipe].PINTFLAG.reg = USB_HOST_PINTFLAG_TXSTP;
|
|
USB->HOST.HostPipe[ul_pipe].PSTATUSSET.reg = USB_HOST_PSTATUSSET_BK0RDY;
|
|
}
|
|
else if(ul_token_type == USB_HOST_PCFG_PTOKEN_IN )
|
|
{
|
|
USB->HOST.HostPipe[ul_pipe].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_BK0RDY;
|
|
}
|
|
else
|
|
{
|
|
USB->HOST.HostPipe[ul_pipe].PINTFLAG.reg = USB_HOST_PINTFLAG_TRCPT(1); // Transfer Complete 0
|
|
USB->HOST.HostPipe[ul_pipe].PSTATUSSET.reg = USB_HOST_PSTATUSSET_BK0RDY;
|
|
}
|
|
|
|
// Unfreeze pipe
|
|
uhd_unfreeze_pipe(ul_pipe);
|
|
}
|
|
|
|
/**
|
|
* \brief Check for pipe transfer completion.
|
|
*
|
|
* \param ul_pipe Pipe number.
|
|
* \param ul_token_type Token type.
|
|
*
|
|
* \retval 0 transfer is not complete.
|
|
* \retval 1 transfer is complete.
|
|
*/
|
|
uint32_t UHD_Pipe_Is_Transfer_Complete(uint32_t ul_pipe, uint32_t ul_token_type)
|
|
{
|
|
// Check for transfer completion depending on token type
|
|
switch (ul_token_type)
|
|
{
|
|
case USB_HOST_PCFG_PTOKEN_SETUP:
|
|
if (Is_uhd_setup_ready(ul_pipe))
|
|
{
|
|
uhd_ack_setup_ready(ul_pipe);
|
|
uhd_freeze_pipe(ul_pipe);
|
|
return 1;
|
|
}
|
|
break;
|
|
|
|
case USB_HOST_PCFG_PTOKEN_IN:
|
|
if (Is_uhd_in_received(ul_pipe))
|
|
{
|
|
// IN packet received
|
|
uhd_ack_in_received(ul_pipe);
|
|
// Freeze will stop after the transfer
|
|
uhd_freeze_pipe(ul_pipe);
|
|
return 1;
|
|
}
|
|
break;
|
|
|
|
case USB_HOST_PCFG_PTOKEN_OUT:
|
|
if (Is_uhd_out_ready(ul_pipe))
|
|
{
|
|
// OUT packet sent
|
|
uhd_ack_out_ready(ul_pipe);
|
|
uhd_freeze_pipe(ul_pipe);
|
|
return 1;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
// USB_Handler ISR
|
|
// void USB_Handler(void) {
|
|
// UHD_Handler();
|
|
// }
|
|
|
|
#endif // HOST_DEFINED
|
|
|
|
#endif // USE_TINYUSB
|