2014-02-28 08:57:25 -08:00
|
|
|
/************************************************************************************//**
|
2018-07-17 06:06:06 -07:00
|
|
|
* \file Source/ARMCM4_TM4C/usb.c
|
2014-02-28 08:57:25 -08:00
|
|
|
* \brief Bootloader USB communication interface source file.
|
|
|
|
* \ingroup Target_ARMCM4_TM4C
|
|
|
|
* \internal
|
|
|
|
*----------------------------------------------------------------------------------------
|
|
|
|
* C O P Y R I G H T
|
|
|
|
*----------------------------------------------------------------------------------------
|
|
|
|
* Copyright (c) 2014 by Feaser http://www.feaser.com All rights reserved
|
|
|
|
*
|
|
|
|
*----------------------------------------------------------------------------------------
|
|
|
|
* L I C E N S E
|
|
|
|
*----------------------------------------------------------------------------------------
|
|
|
|
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as published by the Free
|
|
|
|
* Software Foundation, either version 3 of the License, or (at your option) any later
|
|
|
|
* version.
|
|
|
|
*
|
|
|
|
* OpenBLT 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 General Public License for more details.
|
|
|
|
*
|
2016-07-25 01:33:52 -07:00
|
|
|
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
2016-04-30 15:52:15 -07:00
|
|
|
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
2016-03-01 06:24:23 -08:00
|
|
|
*
|
2014-02-28 08:57:25 -08:00
|
|
|
* \endinternal
|
|
|
|
****************************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************************
|
|
|
|
* Include files
|
|
|
|
****************************************************************************************/
|
|
|
|
#include "boot.h" /* bootloader generic header */
|
|
|
|
#if (BOOT_COM_USB_ENABLE > 0)
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdint.h>
|
2018-03-23 03:11:45 -07:00
|
|
|
#include "usb.h"
|
2014-02-28 08:57:25 -08:00
|
|
|
#include "usblib.h"
|
|
|
|
#include "usbdevice.h"
|
|
|
|
#include "usbdbulk.h"
|
|
|
|
#include "usb_bulk_structs.h"
|
|
|
|
|
|
|
|
|
2018-08-02 07:32:30 -07:00
|
|
|
/****************************************************************************************
|
|
|
|
* Configuration macros
|
|
|
|
****************************************************************************************/
|
|
|
|
/* For a USB bootloader, the backdoor needs to stay open long enough for the USB device
|
|
|
|
* to enumerate on the host PC. Therefore the default backdoor open time needs to be
|
|
|
|
* extended. Note that this won't be long enough for a first time USB driver install
|
|
|
|
* on the host PC. In this case the bootloader should be started with the backup backdoor
|
|
|
|
* that uses, for example, a digital input to force the bootloader to stay active. This
|
|
|
|
* can be implemented in CpuUserProgramStartHook(). Feel free to shorten/lengthen this
|
|
|
|
* time for finetuning. Note that adding this configuration macro to blt_conf.h overrides
|
|
|
|
* the value here.
|
|
|
|
*/
|
|
|
|
#ifndef BOOT_COM_USB_BACKDOOR_EXTENSION_MS
|
|
|
|
#define BOOT_COM_USB_BACKDOOR_EXTENSION_MS (2000)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2014-02-28 08:57:25 -08:00
|
|
|
/****************************************************************************************
|
|
|
|
* Macro definitions
|
|
|
|
****************************************************************************************/
|
|
|
|
/** \brief Total number of fifo buffers. */
|
|
|
|
#define FIFO_MAX_BUFFERS (2)
|
|
|
|
/** \brief Invalid value for a fifo buffer handle. */
|
|
|
|
#define FIFO_ERR_INVALID_HANDLE (255)
|
|
|
|
/** \brief Number of bytes that fit in the fifo pipe. */
|
|
|
|
#define FIFO_PIPE_SIZE (64)
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************************
|
|
|
|
* Type definitions
|
|
|
|
****************************************************************************************/
|
|
|
|
/** \brief Structure type for fifo control. */
|
|
|
|
typedef struct t_fifo_ctrl
|
|
|
|
{
|
|
|
|
blt_int8u *startptr; /**< pointer to start of buffer */
|
|
|
|
blt_int8u *endptr; /**< pointer to end of buffer */
|
|
|
|
blt_int8u *readptr; /**< pointer to next read location */
|
|
|
|
blt_int8u *writeptr; /**< pointer to next free location */
|
|
|
|
blt_int8u length; /**< number of buffer elements */
|
|
|
|
blt_int8u entries; /**< # of full buffer elements */
|
2016-03-01 06:24:23 -08:00
|
|
|
blt_int8u handle; /**< handle of the buffer */
|
2014-02-28 08:57:25 -08:00
|
|
|
struct t_fifo_ctrl *fifoctrlptr; /**< pointer to free buffer control */
|
|
|
|
} tFifoCtrl;
|
|
|
|
|
|
|
|
/** \brief Structure type for a fifo pipe. */
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
blt_int8u handle; /**< fifo handle */
|
|
|
|
blt_int8u data[FIFO_PIPE_SIZE]; /**< fifo data buffer */
|
|
|
|
} tFifoPipe; /**< USB pipe fifo type */
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************************
|
|
|
|
* Function prototypes
|
|
|
|
****************************************************************************************/
|
|
|
|
static blt_bool UsbReceiveByte(blt_int8u *data);
|
|
|
|
static blt_bool UsbTransmitByte(blt_int8u data);
|
|
|
|
static void UsbTransmitPipeBulkIN(void);
|
|
|
|
static void UsbReceivePipeBulkOUT(blt_int8u *data, blt_int32u len);
|
|
|
|
static void UsbFifoMgrInit(void);
|
|
|
|
static blt_int8u UsbFifoMgrCreate(blt_int8u *buffer, blt_int8u length);
|
|
|
|
static blt_bool UsbFifoMgrWrite(blt_int8u handle, blt_int8u data);
|
|
|
|
static blt_bool UsbFifoMgrRead(blt_int8u handle, blt_int8u *data);
|
|
|
|
static blt_int8u UsbFifoMgrScan(blt_int8u handle);
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************************
|
|
|
|
* Local data declarations
|
|
|
|
****************************************************************************************/
|
|
|
|
/** \brief Local variable that holds the fifo control structures. */
|
|
|
|
static tFifoCtrl fifoCtrl[FIFO_MAX_BUFFERS];
|
|
|
|
/** \brief Local pointer that points to the next free fifo control structure. */
|
|
|
|
static tFifoCtrl *fifoCtrlFree;
|
|
|
|
/** \brief Fifo pipe used for the bulk in endpoint. */
|
|
|
|
static tFifoPipe fifoPipeBulkIN;
|
|
|
|
/** \brief Fifo pipe used for the bulk out endpoint. */
|
|
|
|
static tFifoPipe fifoPipeBulkOUT;
|
|
|
|
/** \brief Holds a handle to the bulk device instance. */
|
|
|
|
static tBulkInstance *instanceHandle;
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************************//**
|
|
|
|
** \brief Initializes the USB communication interface.
|
|
|
|
** \return none.
|
|
|
|
**
|
|
|
|
****************************************************************************************/
|
|
|
|
void UsbInit(void)
|
|
|
|
{
|
|
|
|
/* initialize the FIFO manager */
|
|
|
|
UsbFifoMgrInit();
|
|
|
|
/* place 2 buffers under FIFO management */
|
|
|
|
fifoPipeBulkIN.handle = UsbFifoMgrCreate(fifoPipeBulkIN.data, FIFO_PIPE_SIZE);
|
|
|
|
fifoPipeBulkOUT.handle = UsbFifoMgrCreate(fifoPipeBulkOUT.data, FIFO_PIPE_SIZE);
|
|
|
|
/* validate fifo handles */
|
2016-03-01 06:24:23 -08:00
|
|
|
ASSERT_RT((fifoPipeBulkIN.handle != FIFO_ERR_INVALID_HANDLE) && \
|
|
|
|
(fifoPipeBulkOUT.handle != FIFO_ERR_INVALID_HANDLE));
|
2014-02-28 08:57:25 -08:00
|
|
|
/* initialize the transmit and receive buffers */
|
|
|
|
USBBufferInit(&g_sTxBuffer);
|
|
|
|
USBBufferInit(&g_sRxBuffer);
|
|
|
|
/* pass our device information to the USB library and place the device on the bus */
|
|
|
|
instanceHandle = USBDBulkInit(0, &g_sBulkDevice);
|
|
|
|
ASSERT_RT(instanceHandle != BLT_NULL);
|
2018-08-02 07:32:30 -07:00
|
|
|
/* extend the time that the backdoor is open in case the default timed backdoor
|
|
|
|
* mechanism is used.
|
|
|
|
*/
|
|
|
|
#if (BOOT_BACKDOOR_HOOKS_ENABLE == 0)
|
|
|
|
if (BackDoorGetExtension() < BOOT_COM_USB_BACKDOOR_EXTENSION_MS)
|
|
|
|
{
|
|
|
|
BackDoorSetExtension(BOOT_COM_USB_BACKDOOR_EXTENSION_MS);
|
|
|
|
}
|
|
|
|
#endif /* BOOT_BACKDOOR_HOOKS_ENABLE == 0 */
|
2014-02-28 08:57:25 -08:00
|
|
|
} /*** end of UsbInit ***/
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************************//**
|
2016-03-01 06:24:23 -08:00
|
|
|
** \brief Releases the USB communication interface.
|
2014-02-28 08:57:25 -08:00
|
|
|
** \return none.
|
|
|
|
**
|
|
|
|
****************************************************************************************/
|
|
|
|
void UsbFree(void)
|
|
|
|
{
|
|
|
|
/* shut down the bulk device */
|
|
|
|
USBDBulkTerm(instanceHandle);
|
|
|
|
/* disconnect the USB device from the USB host */
|
|
|
|
UsbConnectHook(BLT_FALSE);
|
|
|
|
} /*** end of UsbFree ***/
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************************//**
|
|
|
|
** \brief Transmits a packet formatted for the communication interface.
|
|
|
|
** \param data Pointer to byte array with data that it to be transmitted.
|
|
|
|
** \param len Number of bytes that are to be transmitted.
|
|
|
|
** \return none.
|
|
|
|
**
|
|
|
|
****************************************************************************************/
|
|
|
|
void UsbTransmitPacket(blt_int8u *data, blt_int8u len)
|
|
|
|
{
|
|
|
|
blt_int16u data_index;
|
2014-05-26 16:14:30 -07:00
|
|
|
blt_bool result;
|
2014-02-28 08:57:25 -08:00
|
|
|
|
|
|
|
/* verify validity of the len-parameter */
|
2016-03-01 06:24:23 -08:00
|
|
|
ASSERT_RT(len <= BOOT_COM_USB_TX_MAX_DATA);
|
2014-02-28 08:57:25 -08:00
|
|
|
|
2016-03-01 06:24:23 -08:00
|
|
|
/* first transmit the length of the packet */
|
2014-05-26 16:14:30 -07:00
|
|
|
result = UsbTransmitByte(len);
|
2016-03-01 06:24:23 -08:00
|
|
|
ASSERT_RT(result == BLT_TRUE);
|
|
|
|
|
2014-02-28 08:57:25 -08:00
|
|
|
/* transmit all the packet bytes one-by-one */
|
|
|
|
for (data_index = 0; data_index < len; data_index++)
|
|
|
|
{
|
|
|
|
/* keep the watchdog happy */
|
|
|
|
CopService();
|
|
|
|
/* write byte */
|
2014-05-26 16:14:30 -07:00
|
|
|
result = UsbTransmitByte(data[data_index]);
|
2016-03-01 06:24:23 -08:00
|
|
|
ASSERT_RT(result == BLT_TRUE);
|
2014-02-28 08:57:25 -08:00
|
|
|
}
|
2016-03-01 06:24:23 -08:00
|
|
|
|
2014-02-28 08:57:25 -08:00
|
|
|
/* start the transmission */
|
|
|
|
UsbTransmitPipeBulkIN();
|
|
|
|
} /*** end of UsbTransmitPacket ***/
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************************//**
|
|
|
|
** \brief Receives a communication interface packet if one is present.
|
|
|
|
** \param data Pointer to byte array where the data is to be stored.
|
2018-02-09 08:59:41 -08:00
|
|
|
** \param len Pointer where the length of the packet is to be stored.
|
2014-02-28 08:57:25 -08:00
|
|
|
** \return BLT_TRUE if a packet was received, BLT_FALSE otherwise.
|
|
|
|
**
|
|
|
|
****************************************************************************************/
|
2018-02-09 08:59:41 -08:00
|
|
|
blt_bool UsbReceivePacket(blt_int8u *data, blt_int8u *len)
|
2014-02-28 08:57:25 -08:00
|
|
|
{
|
2014-05-26 16:14:30 -07:00
|
|
|
static blt_int8u xcpCtoReqPacket[BOOT_COM_USB_RX_MAX_DATA+1]; /* one extra for length */
|
2014-02-28 08:57:25 -08:00
|
|
|
static blt_int8u xcpCtoRxLength;
|
|
|
|
static blt_bool xcpCtoRxInProgress = BLT_FALSE;
|
|
|
|
|
|
|
|
/* poll for USB events */
|
|
|
|
USB0DeviceIntHandler();
|
2016-03-01 06:24:23 -08:00
|
|
|
|
2014-02-28 08:57:25 -08:00
|
|
|
/* start of cto packet received? */
|
|
|
|
if (xcpCtoRxInProgress == BLT_FALSE)
|
|
|
|
{
|
|
|
|
/* store the message length when received */
|
|
|
|
if (UsbReceiveByte(&xcpCtoReqPacket[0]) == BLT_TRUE)
|
|
|
|
{
|
2018-02-09 02:12:04 -08:00
|
|
|
if ( (xcpCtoReqPacket[0] > 0) &&
|
|
|
|
(xcpCtoReqPacket[0] <= BOOT_COM_USB_RX_MAX_DATA) )
|
2014-09-15 01:17:44 -07:00
|
|
|
{
|
|
|
|
/* indicate that a cto packet is being received */
|
|
|
|
xcpCtoRxInProgress = BLT_TRUE;
|
|
|
|
/* reset packet data count */
|
|
|
|
xcpCtoRxLength = 0;
|
|
|
|
}
|
2014-02-28 08:57:25 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* store the next packet byte */
|
|
|
|
if (UsbReceiveByte(&xcpCtoReqPacket[xcpCtoRxLength+1]) == BLT_TRUE)
|
|
|
|
{
|
|
|
|
/* increment the packet data count */
|
|
|
|
xcpCtoRxLength++;
|
|
|
|
|
|
|
|
/* check to see if the entire packet was received */
|
|
|
|
if (xcpCtoRxLength == xcpCtoReqPacket[0])
|
|
|
|
{
|
|
|
|
/* copy the packet data */
|
2016-03-01 06:24:23 -08:00
|
|
|
CpuMemCopy((blt_int32u)data, (blt_int32u)&xcpCtoReqPacket[1], xcpCtoRxLength);
|
2014-02-28 08:57:25 -08:00
|
|
|
/* done with cto packet reception */
|
|
|
|
xcpCtoRxInProgress = BLT_FALSE;
|
2018-02-09 08:59:41 -08:00
|
|
|
/* set the packet length */
|
|
|
|
*len = xcpCtoRxLength;
|
2014-02-28 08:57:25 -08:00
|
|
|
/* packet reception complete */
|
|
|
|
return BLT_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* packet reception not yet complete */
|
|
|
|
return BLT_FALSE;
|
|
|
|
} /*** end of UsbReceivePacket ***/
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************************//**
|
|
|
|
** \brief Receives a communication interface byte if one is present.
|
|
|
|
** \param data Pointer to byte where the data is to be stored.
|
|
|
|
** \return BLT_TRUE if a byte was received, BLT_FALSE otherwise.
|
|
|
|
**
|
|
|
|
****************************************************************************************/
|
|
|
|
static blt_bool UsbReceiveByte(blt_int8u *data)
|
|
|
|
{
|
|
|
|
blt_bool result;
|
2016-03-01 06:24:23 -08:00
|
|
|
|
2014-02-28 08:57:25 -08:00
|
|
|
/* obtain data from the fifo */
|
|
|
|
result = UsbFifoMgrRead(fifoPipeBulkOUT.handle, data);
|
|
|
|
return result;
|
|
|
|
} /*** end of UsbReceiveByte ***/
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************************//**
|
|
|
|
** \brief Transmits a communication interface byte.
|
|
|
|
** \param data Value of byte that is to be transmitted.
|
|
|
|
** \return BLT_TRUE if the byte was transmitted, BLT_FALSE otherwise.
|
|
|
|
**
|
|
|
|
****************************************************************************************/
|
|
|
|
static blt_bool UsbTransmitByte(blt_int8u data)
|
|
|
|
{
|
|
|
|
blt_bool result;
|
2016-03-01 06:24:23 -08:00
|
|
|
|
2014-02-28 08:57:25 -08:00
|
|
|
/* write data from to fifo */
|
|
|
|
result = UsbFifoMgrWrite(fifoPipeBulkIN.handle, data);
|
|
|
|
return result;
|
|
|
|
} /*** end of UsbTransmitByte ***/
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************************//**
|
|
|
|
** \brief Checks if there is still data left to transmit and if so submits it
|
|
|
|
** for transmission with the USB endpoint.
|
|
|
|
** \return none.
|
|
|
|
**
|
|
|
|
****************************************************************************************/
|
|
|
|
static void UsbTransmitPipeBulkIN(void)
|
|
|
|
{
|
|
|
|
tUSBRingBufObject txRing;
|
|
|
|
blt_int32u txSpace;
|
|
|
|
blt_int32u txWriteIdx;
|
|
|
|
blt_int8u nr_of_bytes_for_tx_endpoint;
|
|
|
|
blt_int8u byte_counter;
|
|
|
|
blt_int8u byte_value;
|
|
|
|
blt_bool result;
|
2016-03-01 06:24:23 -08:00
|
|
|
|
2014-02-28 08:57:25 -08:00
|
|
|
/* read how many bytes should be transmitted */
|
|
|
|
nr_of_bytes_for_tx_endpoint = UsbFifoMgrScan(fifoPipeBulkIN.handle);
|
|
|
|
/* only continue if there is actually data left to transmit */
|
|
|
|
if (nr_of_bytes_for_tx_endpoint == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* get information about the USB transmit buffer */
|
|
|
|
USBBufferInfoGet(&g_sTxBuffer, &txRing);
|
|
|
|
/* determine how many bytes will still fit in the tx buffer */
|
|
|
|
txSpace = USBBufferSpaceAvailable(&g_sTxBuffer);
|
|
|
|
/* only transmit the amount of bytes that will fit in the tx buffer */
|
|
|
|
if (nr_of_bytes_for_tx_endpoint > txSpace)
|
|
|
|
{
|
|
|
|
nr_of_bytes_for_tx_endpoint = txSpace;
|
|
|
|
}
|
|
|
|
/* determine write index for the tx buffer */
|
|
|
|
txWriteIdx = txRing.ui32WriteIndex;
|
|
|
|
|
|
|
|
/* copy the transmit data to the transmit buffer */
|
|
|
|
for (byte_counter=0; byte_counter < nr_of_bytes_for_tx_endpoint; byte_counter++)
|
|
|
|
{
|
|
|
|
/* obtain data from the fifo */
|
|
|
|
result = UsbFifoMgrRead(fifoPipeBulkIN.handle, &byte_value);
|
|
|
|
ASSERT_RT(result == BLT_TRUE);
|
|
|
|
/* store it in the transmit buffer */
|
|
|
|
g_pui8USBTxBuffer[txWriteIdx] = byte_value;
|
|
|
|
/* increment index with wrapping */
|
|
|
|
txWriteIdx++;
|
|
|
|
if (txWriteIdx >= BULK_BUFFER_SIZE)
|
|
|
|
{
|
|
|
|
txWriteIdx = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* inform the usb library that new data are ready for transmission */
|
|
|
|
USBBufferDataWritten(&g_sTxBuffer, nr_of_bytes_for_tx_endpoint);
|
|
|
|
} /*** end of UsbTransmitPipeBulkIN ***/
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************************//**
|
|
|
|
** \brief Stores data that was received on the Bulk OUT pipe in the fifo.
|
|
|
|
** \param data Pointer to buffer with the newly received data
|
|
|
|
** \param len Number of received data bytes.
|
|
|
|
** \return none.
|
|
|
|
**
|
|
|
|
****************************************************************************************/
|
|
|
|
static void UsbReceivePipeBulkOUT(blt_int8u *data, blt_int32u len)
|
|
|
|
{
|
|
|
|
blt_int32u byte_counter;
|
|
|
|
blt_bool result;
|
|
|
|
blt_int32u rxReadIdx;
|
2016-03-01 06:24:23 -08:00
|
|
|
|
|
|
|
|
2014-02-28 08:57:25 -08:00
|
|
|
/* determine read index for the rx buffer */
|
|
|
|
rxReadIdx = (uint32_t)(data - g_pui8USBRxBuffer);
|
2016-03-01 06:24:23 -08:00
|
|
|
|
2014-02-28 08:57:25 -08:00
|
|
|
/* store the received data in the reception fifo */
|
|
|
|
for (byte_counter=0; byte_counter<len; byte_counter++)
|
|
|
|
{
|
|
|
|
/* add the data to the fifo */
|
|
|
|
result = UsbFifoMgrWrite(fifoPipeBulkOUT.handle, g_pui8USBRxBuffer[rxReadIdx]);
|
|
|
|
/* verify that the fifo wasn't full */
|
|
|
|
ASSERT_RT(result == BLT_TRUE);
|
|
|
|
/* increment index with wrapping */
|
|
|
|
rxReadIdx++;
|
|
|
|
if (rxReadIdx >= BULK_BUFFER_SIZE)
|
|
|
|
{
|
|
|
|
rxReadIdx = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} /*** end of UsbReceivePipeBulkOUT ***/
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************************//**
|
|
|
|
** \brief Handles bulk driver notifications related to the transmit channel (data to
|
|
|
|
** the USB host).
|
|
|
|
** \param pvCBData is the client-supplied callback pointer for this channel.
|
|
|
|
** \param ui32Event identifies the event we are being notified about.
|
|
|
|
** \param ui32MsgValue is an event-specific value.
|
|
|
|
** \param pvMsgData is an event-specific pointer.
|
|
|
|
** \return The return value is event-specific.
|
|
|
|
**
|
|
|
|
****************************************************************************************/
|
|
|
|
uint32_t UsbBulkTxHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue, void *pvMsgData)
|
|
|
|
{
|
2016-03-01 06:24:23 -08:00
|
|
|
if (ui32Event == USB_EVENT_TX_COMPLETE)
|
2014-02-28 08:57:25 -08:00
|
|
|
{
|
|
|
|
/* check if more data is waiting to be transmitted */
|
|
|
|
UsbTransmitPipeBulkIN();
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
} /*** end of UsbBulkTxHandler ***/
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************************//**
|
|
|
|
** \brief Handles bulk driver notifications related to the receive channel (data from
|
|
|
|
** the USB host).
|
|
|
|
** \param pvCBData is the client-supplied callback pointer for this channel.
|
|
|
|
** \param ui32Event identifies the event we are being notified about.
|
|
|
|
** \param ui32MsgValue is an event-specific value.
|
|
|
|
** \param pvMsgData is an event-specific pointer.
|
|
|
|
** \return The return value is event-specific.
|
|
|
|
**
|
|
|
|
****************************************************************************************/
|
|
|
|
uint32_t UsbBulkRxHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue, void *pvMsgData)
|
|
|
|
{
|
|
|
|
/* which event are we being sent? */
|
2016-03-01 06:24:23 -08:00
|
|
|
switch (ui32Event)
|
2014-02-28 08:57:25 -08:00
|
|
|
{
|
|
|
|
/* we are connected to a host and communication is now possible */
|
|
|
|
case USB_EVENT_CONNECTED:
|
|
|
|
{
|
|
|
|
/* flush our buffers */
|
|
|
|
USBBufferFlush(&g_sTxBuffer);
|
|
|
|
USBBufferFlush(&g_sRxBuffer);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* the host has disconnected */
|
|
|
|
case USB_EVENT_DISCONNECTED:
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* a new packet has been received */
|
|
|
|
case USB_EVENT_RX_AVAILABLE:
|
|
|
|
{
|
|
|
|
/* handle all newly received bytes */
|
|
|
|
UsbReceivePipeBulkOUT(pvMsgData, ui32MsgValue);
|
|
|
|
return ui32MsgValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ignore SUSPEND and RESUME for now */
|
|
|
|
case USB_EVENT_SUSPEND:
|
|
|
|
/* power-off system clocks and power */
|
|
|
|
UsbEnterLowPowerModeHook();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case USB_EVENT_RESUME:
|
|
|
|
/* restore power and system clocks */
|
|
|
|
UsbLeaveLowPowerModeHook();
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* ignore all other events and return 0 */
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
} /*** end of UsbBulkRxHandler ***/
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************************//**
|
|
|
|
** \brief Initializes the fifo manager. Each controlled fifo is assigned a
|
|
|
|
** unique handle, which is the same as its index into fifoCtrl[]. Each
|
|
|
|
** controlled fifo holds a pointer to the next free fifo control.
|
|
|
|
** For the last fifo in fifoCtrl[] this one is set to a null-pointer as
|
|
|
|
** an out of fifo control indicator. Function should be called once
|
|
|
|
** before any of the other fifo management functions are called.
|
|
|
|
** \return none.
|
|
|
|
**
|
|
|
|
****************************************************************************************/
|
|
|
|
static void UsbFifoMgrInit(void)
|
|
|
|
{
|
|
|
|
blt_int8u i;
|
|
|
|
tFifoCtrl *pbc1, *pbc2;
|
|
|
|
|
|
|
|
pbc1 = &fifoCtrl[0];
|
|
|
|
pbc2 = &fifoCtrl[1];
|
|
|
|
/* assign fifo handles and pointer to next free fifo */
|
|
|
|
for (i = 0; i < (FIFO_MAX_BUFFERS - 1); i++)
|
|
|
|
{
|
|
|
|
pbc1->handle = i;
|
|
|
|
pbc1->fifoctrlptr = pbc2;
|
|
|
|
pbc1++;
|
|
|
|
pbc2++;
|
|
|
|
}
|
|
|
|
/* initialize handle for the last one and use null-pointer for the next free fifo */
|
|
|
|
pbc1->handle = i;
|
|
|
|
pbc1->fifoctrlptr = (tFifoCtrl *)0;
|
|
|
|
fifoCtrlFree = &fifoCtrl[0];
|
|
|
|
} /*** end of UsbFifoMgrInit ***/
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************************//**
|
|
|
|
** \brief Places a data storage array under fifo management control. A handle
|
|
|
|
** for identifying the fifo in subsequent fifo management function
|
|
|
|
** calls is returned, if successful.
|
|
|
|
** \param buffer Pointer to the first element in the data storage fifo.
|
|
|
|
** \param length Maximum number of data elements that can be stored in the fifo.
|
|
|
|
** \return Fifo handle if successfull, or FIFO_ERR_INVALID_HANDLE.
|
|
|
|
**
|
|
|
|
****************************************************************************************/
|
|
|
|
static blt_int8u UsbFifoMgrCreate(blt_int8u *buffer, blt_int8u length)
|
|
|
|
{
|
|
|
|
tFifoCtrl *pbc;
|
|
|
|
|
|
|
|
/* first determine if these is still a free fifo control available */
|
|
|
|
if (fifoCtrlFree == (tFifoCtrl *)0)
|
|
|
|
{
|
|
|
|
return FIFO_ERR_INVALID_HANDLE;
|
|
|
|
}
|
|
|
|
/* store pointer to free fifo and update pointer to next free one */
|
|
|
|
pbc = fifoCtrlFree;
|
|
|
|
fifoCtrlFree = pbc->fifoctrlptr;
|
|
|
|
|
|
|
|
/* initialize the buffer control */
|
|
|
|
pbc->length = length;
|
|
|
|
pbc->readptr = buffer;
|
|
|
|
pbc->writeptr = buffer;
|
|
|
|
pbc->entries = 0;
|
|
|
|
pbc->startptr = buffer;
|
2016-03-01 06:24:23 -08:00
|
|
|
pbc->endptr = (blt_int8u *)(buffer + length - 1);
|
2014-02-28 08:57:25 -08:00
|
|
|
|
|
|
|
/* return the handle to the successfully created fifo control */
|
|
|
|
return pbc->handle;
|
|
|
|
} /*** end of UsbFifoMgrCreate ***/
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************************//**
|
|
|
|
** \brief Stores data in the fifo.
|
|
|
|
** \param handle Identifies the fifo to write data to.
|
|
|
|
** \param data Pointer to the data that is to be written to the fifo.
|
|
|
|
** \return BLT_TRUE if the data was successfully stored in the fifo, BLT_FALSE
|
|
|
|
** otherwise.
|
|
|
|
**
|
|
|
|
****************************************************************************************/
|
|
|
|
static blt_bool UsbFifoMgrWrite(blt_int8u handle, blt_int8u data)
|
|
|
|
{
|
|
|
|
/* check the validity of the handle parameter */
|
|
|
|
ASSERT_RT(handle < FIFO_MAX_BUFFERS);
|
|
|
|
/* check if fifo is full */
|
|
|
|
if (fifoCtrl[handle].entries == fifoCtrl[handle].length)
|
|
|
|
{
|
|
|
|
return BLT_FALSE;
|
|
|
|
}
|
|
|
|
/* copy data to fifo */
|
|
|
|
*fifoCtrl[handle].writeptr = data;
|
|
|
|
/* data written so update number of entries */
|
|
|
|
fifoCtrl[handle].entries++;
|
|
|
|
/* update write pointer */
|
|
|
|
fifoCtrl[handle].writeptr++;
|
|
|
|
/* check end of fifo */
|
|
|
|
if (fifoCtrl[handle].writeptr > fifoCtrl[handle].endptr)
|
|
|
|
{
|
|
|
|
/* set write pointer to start of the cyclic fifo */
|
|
|
|
fifoCtrl[handle].writeptr = fifoCtrl[handle].startptr;
|
|
|
|
}
|
2016-03-01 06:24:23 -08:00
|
|
|
/* still here so all is okay */
|
2014-02-28 08:57:25 -08:00
|
|
|
return BLT_TRUE;
|
|
|
|
} /*** end of UsbFifoMgrWrite ***/
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************************//**
|
|
|
|
** \brief Retrieves data from the fifo.
|
|
|
|
** \param handle Identifies the fifo to read data from.
|
|
|
|
** \param data Pointer to where the read data is to be stored.
|
|
|
|
** \return BLT_TRUE if the data was successfully read from the fifo, BLT_FALSE
|
|
|
|
** otherwise.
|
|
|
|
**
|
|
|
|
****************************************************************************************/
|
|
|
|
static blt_bool UsbFifoMgrRead(blt_int8u handle, blt_int8u *data)
|
|
|
|
{
|
|
|
|
/* check the validity of the handle parameter */
|
|
|
|
ASSERT_RT(handle < FIFO_MAX_BUFFERS);
|
|
|
|
/* check if fifo is empty */
|
|
|
|
if (fifoCtrl[handle].entries == 0)
|
|
|
|
{
|
|
|
|
return BLT_FALSE;
|
|
|
|
}
|
|
|
|
/* read the data */
|
|
|
|
*data = *fifoCtrl[handle].readptr;
|
|
|
|
/* data read so update number of entries */
|
|
|
|
fifoCtrl[handle].entries--;
|
|
|
|
/* update read pointer */
|
|
|
|
fifoCtrl[handle].readptr++;
|
|
|
|
/* check end of fifo */
|
|
|
|
if (fifoCtrl[handle].readptr > fifoCtrl[handle].endptr)
|
|
|
|
{
|
|
|
|
/* set read pointer to start of the cyclic fifo */
|
|
|
|
fifoCtrl[handle].readptr = fifoCtrl[handle].startptr;
|
|
|
|
}
|
|
|
|
/* still here so all is good */
|
|
|
|
return BLT_TRUE;
|
|
|
|
} /*** end of UsbFifoMgrRead ***/
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************************//**
|
|
|
|
** \brief Returns the number of data entries currently present in the fifo.
|
|
|
|
** \param handle Identifies the fifo that is to be scanned.
|
|
|
|
** \return Number of data entries in the fifo if successful, otherwise 0.
|
|
|
|
**
|
|
|
|
****************************************************************************************/
|
|
|
|
static blt_int8u UsbFifoMgrScan(blt_int8u handle)
|
|
|
|
{
|
|
|
|
/* check the validity of the handle parameter */
|
|
|
|
ASSERT_RT(handle < FIFO_MAX_BUFFERS);
|
|
|
|
/* read and return the number of data entries */
|
|
|
|
return fifoCtrl[handle].entries;
|
|
|
|
} /*** end of UsbFifoMgrScan ***/
|
|
|
|
#endif /* BOOT_COM_USB_ENABLE > 0 */
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************** end of usb.c **************************************/
|