- Implement notification of Downstream USB device removal, and

corresponding Upstream disconnection
- Improve Upstream handling of TxOk signal from Downstream
- Misc tweaks
pull/7/head
Robert Fisk 9 years ago
parent f24714cd8c
commit 750c2f3a21

@ -49,5 +49,13 @@ typedef enum
InterfaceCommandMscTypeDef;
typedef enum
{
COMMAND_ERROR_GENERIC,
COMMAND_ERROR_DEVICE_DISCONNECTED,
}
InterfaceCommandErrorTypeDef;
#endif /* INC_DOWNSTREAM_INTERFACE_DEF_H_ */

@ -17,22 +17,12 @@
#define DOWNSTREAM_PACKET_LEN_MIN (DOWNSTREAM_PACKET_HEADER_LEN)
#define DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID \
#define DOWNSTREAM_SPI_FREAKOUT \
do { \
LED_Fault_SetBlinkRate(LED_FAST_BLINK_RATE); \
Downstream_PacketProcessor_SetErrorState(); \
DownstreamInterfaceState = DOWNSTREAM_INTERFACE_ERROR; \
while (1); \
/*return;*/ \
} while (0);
#define DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR \
do { \
LED_Fault_SetBlinkRate(LED_FAST_BLINK_RATE); \
Downstream_PacketProcessor_SetErrorState(); \
DownstreamInterfaceState = DOWNSTREAM_INTERFACE_ERROR; \
while (1); \
/*return HAL_ERROR;*/ \
} while (0);

@ -25,14 +25,6 @@ typedef enum
#define DOWNSTREAM_STATEMACHINE_FREAKOUT \
do { \
LED_Fault_SetBlinkRate(LED_FAST_BLINK_RATE); \
DownstreamState = STATE_ERROR; \
return; \
} while (0);
#define DOWNSTREAM_STATEMACHINE_FREAKOUT_NORETURN \
do { \
LED_Fault_SetBlinkRate(LED_FAST_BLINK_RATE); \
DownstreamState = STATE_ERROR; \
@ -44,7 +36,7 @@ typedef enum
void Downstream_InitStateMachine(void);
void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id);
void Downstream_PacketProcessor(DownstreamPacketTypeDef* receivedPacket);
void Downstream_PacketProcessor_ErrorReply(DownstreamPacketTypeDef* replyPacket);
void Downstream_PacketProcessor_GenericErrorReply(DownstreamPacketTypeDef* replyPacket);
void Downstream_PacketProcessor_ClassReply(DownstreamPacketTypeDef* replyPacket);
void Downstream_PacketProcessor_SetErrorState(void);
void Downstream_PacketProcessor_FreakOut(void);

@ -151,7 +151,7 @@ void Downstream_MSC_PacketProcessor_RdWrCompleteCallback(USBH_StatusTypeDef resu
{
if (result != USBH_OK)
{
Downstream_GetFreePacket(Downstream_PacketProcessor_ErrorReply);
Downstream_GetFreePacket(Downstream_PacketProcessor_GenericErrorReply);
return;
}
Downstream_ReceivePacket(Downstream_PacketProcessor);

@ -26,7 +26,7 @@ SpiPacketReceivedCallbackTypeDef ReceivePacketCallback = NULL; //Indicates some
HAL_StatusTypeDef Downstream_CheckPreparePacketReception(void);
void Downstream_PreparePacketReception(DownstreamPacketTypeDef* freePacket);
void Downstream_PrepareReceivePacketSize(DownstreamPacketTypeDef* freePacket);
@ -62,7 +62,8 @@ HAL_StatusTypeDef Downstream_GetFreePacket(FreePacketCallbackTypeDef callback)
//Do we already have a queued callback?
if (PendingFreePacketCallback != NULL)
{
DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR;
DOWNSTREAM_SPI_FREAKOUT;
return HAL_ERROR;
}
//Check if there is a free buffer now
@ -98,7 +99,8 @@ void Downstream_ReleasePacket(DownstreamPacketTypeDef* packetToRelease)
if ((packetToRelease != &DownstreamPacket0) &&
(packetToRelease != &DownstreamPacket1))
{
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT;
return;
}
if (PendingFreePacketCallback != NULL)
@ -125,10 +127,14 @@ HAL_StatusTypeDef Downstream_ReceivePacket(SpiPacketReceivedCallbackTypeDef call
return HAL_ERROR;
}
if (ReceivePacketCallback != NULL)
if ((DownstreamInterfaceState == DOWNSTREAM_INTERFACE_RX_SIZE_WAIT) ||
(DownstreamInterfaceState == DOWNSTREAM_INTERFACE_RX_PACKET_WAIT) ||
(ReceivePacketCallback != NULL))
{
DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR;
DOWNSTREAM_SPI_FREAKOUT;
return HAL_ERROR;
}
ReceivePacketCallback = callback;
return Downstream_CheckPreparePacketReception();
}
@ -137,21 +143,32 @@ HAL_StatusTypeDef Downstream_ReceivePacket(SpiPacketReceivedCallbackTypeDef call
//Internal use only
HAL_StatusTypeDef Downstream_CheckPreparePacketReception(void)
{
if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR)
{
return HAL_ERROR;
}
if (DownstreamInterfaceState == DOWNSTREAM_INTERFACE_IDLE)
{
DownstreamInterfaceState = DOWNSTREAM_INTERFACE_RX_SIZE_WAIT;
return Downstream_GetFreePacket(Downstream_PreparePacketReception);
return Downstream_GetFreePacket(Downstream_PrepareReceivePacketSize);
}
return HAL_OK;
}
//Internal use only
void Downstream_PreparePacketReception(DownstreamPacketTypeDef* freePacket)
void Downstream_PrepareReceivePacketSize(DownstreamPacketTypeDef* freePacket)
{
if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR)
{
return;
}
if (DownstreamInterfaceState != DOWNSTREAM_INTERFACE_RX_SIZE_WAIT)
{
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT;
return;
}
CurrentWorkingPacket = freePacket;
//CurrentWorkingPacket->Length = 0;
@ -160,7 +177,8 @@ void Downstream_PreparePacketReception(DownstreamPacketTypeDef* freePacket)
(uint8_t*)&CurrentWorkingPacket->Length,
(2 + 1)) != HAL_OK) //"When the CRC feature is enabled the pData Length must be Size + 1"
{
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT;
return;
}
UPSTREAM_TX_REQUEST_ASSERT;
@ -185,14 +203,16 @@ void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
if ((CurrentWorkingPacket->Length < DOWNSTREAM_PACKET_LEN_MIN) ||
(CurrentWorkingPacket->Length > DOWNSTREAM_PACKET_LEN))
{
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT;
return;
}
DownstreamInterfaceState = DOWNSTREAM_INTERFACE_RX_PACKET_WAIT;
if ((HAL_SPI_Receive_DMA(&Hspi1,
&CurrentWorkingPacket->CommandClass,
CurrentWorkingPacket->Length + 1)) != HAL_OK) //"When the CRC feature is enabled the pData Length must be Size + 1"
{
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT;
return;
}
UPSTREAM_TX_REQUEST_ASSERT;
return;
@ -203,7 +223,8 @@ void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
DownstreamInterfaceState = DOWNSTREAM_INTERFACE_IDLE;
if (ReceivePacketCallback == NULL)
{
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT;
return;
}
//Packet processor may want to receive another packet immediately,
//so clear ReceivePacketCallback before the call.
@ -214,7 +235,8 @@ void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
return;
}
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
//case default:
DOWNSTREAM_SPI_FREAKOUT;
}
@ -233,17 +255,20 @@ HAL_StatusTypeDef Downstream_TransmitPacket(DownstreamPacketTypeDef* packetToWri
if ((packetToWrite != &DownstreamPacket0) &&
(packetToWrite != &DownstreamPacket1))
{
DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR;
DOWNSTREAM_SPI_FREAKOUT;
return HAL_ERROR;
}
if ((packetToWrite->Busy != BUSY) ||
(packetToWrite->Length < DOWNSTREAM_PACKET_LEN_MIN) ||
(packetToWrite->Length > DOWNSTREAM_PACKET_LEN))
{
DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR;
DOWNSTREAM_SPI_FREAKOUT;
return HAL_ERROR;
}
if (NextTxPacket != NULL)
{
DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR;
DOWNSTREAM_SPI_FREAKOUT;
return HAL_ERROR;
}
switch (DownstreamInterfaceState)
@ -261,13 +286,15 @@ HAL_StatusTypeDef Downstream_TransmitPacket(DownstreamPacketTypeDef* packetToWri
(uint8_t*)&CurrentWorkingPacket->Length,
2 + 1) != HAL_OK) //"When the CRC feature is enabled the pRxData Length must be Size + 1"
{
DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR;
DOWNSTREAM_SPI_FREAKOUT;
return HAL_ERROR;
}
UPSTREAM_TX_REQUEST_ASSERT;
break;
default:
DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR;
DOWNSTREAM_SPI_FREAKOUT;
return HAL_ERROR;
}
return HAL_OK;
@ -289,14 +316,16 @@ void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
if (DownstreamInterfaceState != DOWNSTREAM_INTERFACE_TX_SIZE_WAIT)
{
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT;
return;
}
if (CurrentWorkingPacket->Length != 0)
{
//Currently we just freak out if Upstream sends us an unexpected command.
//Theoretically we could reset our downstream state machine and accept the new command...
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT;
return;
}
DownstreamInterfaceState = DOWNSTREAM_INTERFACE_TX_PACKET_WAIT;
@ -304,7 +333,8 @@ void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
&CurrentWorkingPacket->CommandClass,
CurrentWorkingPacket->Length)) != HAL_OK)
{
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT;
return;
}
UPSTREAM_TX_REQUEST_ASSERT;
}
@ -323,7 +353,8 @@ void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
if (DownstreamInterfaceState != DOWNSTREAM_INTERFACE_TX_PACKET_WAIT)
{
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT;
return;
}
Downstream_ReleasePacket(CurrentWorkingPacket);
@ -339,7 +370,8 @@ void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
(uint8_t*)&CurrentWorkingPacket->Length,
2 + 1) != HAL_OK) //"When the CRC feature is enabled the pRxData Length must be Size + 1"
{
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT;
return;
}
UPSTREAM_TX_REQUEST_ASSERT;
return;
@ -357,6 +389,6 @@ void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
//Something bad happened! Possibly CRC error...
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
{
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT;
}

@ -43,21 +43,38 @@ void Downstream_PacketProcessor(DownstreamPacketTypeDef* receivedPacket)
return;
}
switch (receivedPacket->CommandClass)
if (receivedPacket->CommandClass == COMMAND_CLASS_INTERFACE)
{
case COMMAND_CLASS_INTERFACE:
if (DownstreamState > STATE_DEVICE_READY)
{
DOWNSTREAM_STATEMACHINE_FREAKOUT;
return;
}
Downstream_PacketProcessor_Interface(receivedPacket);
break;
return;
}
case COMMAND_CLASS_MASS_STORAGE:
//If we get a class-specific message when our device is disconnected,
//we need to tell Upstream of the fact (and not freak out).
if (DownstreamState == STATE_DEVICE_NOT_READY)
{
receivedPacket->Length = DOWNSTREAM_PACKET_HEADER_LEN;
receivedPacket->CommandClass = COMMAND_CLASS_ERROR;
receivedPacket->Command = COMMAND_ERROR_DEVICE_DISCONNECTED;
Downstream_PacketProcessor_ClassReply(receivedPacket);
return;
}
//We should only receive class-specific messages when we are in the Active state.
if (DownstreamState != STATE_ACTIVE)
{
DOWNSTREAM_STATEMACHINE_FREAKOUT;
return;
}
switch (receivedPacket->CommandClass)
{
case COMMAND_CLASS_MASS_STORAGE:
Downstream_MSC_PacketProcessor(receivedPacket);
break;
@ -89,11 +106,9 @@ void Downstream_PacketProcessor_Interface(DownstreamPacketTypeDef* receivedPacke
switch (receivedPacket->Command)
{
case COMMAND_INTERFACE_ECHO:
if (Downstream_TransmitPacket(receivedPacket) == HAL_OK)
{
Downstream_TransmitPacket(receivedPacket);
Downstream_ReceivePacket(Downstream_PacketProcessor);
}
return;
break;
case COMMAND_INTERFACE_NOTIFY_DEVICE:
if (DownstreamState == STATE_DEVICE_READY)
@ -109,7 +124,7 @@ void Downstream_PacketProcessor_Interface(DownstreamPacketTypeDef* receivedPacke
return;
}
DOWNSTREAM_STATEMACHINE_FREAKOUT;
return;
break;
default:
@ -133,25 +148,22 @@ void Downstream_PacketProcessor_Interface_ReplyNotifyDevice(DownstreamPacketType
}
void Downstream_PacketProcessor_ErrorReply(DownstreamPacketTypeDef* replyPacket)
void Downstream_PacketProcessor_GenericErrorReply(DownstreamPacketTypeDef* replyPacket)
{
replyPacket->Length = DOWNSTREAM_PACKET_HEADER_LEN;
replyPacket->CommandClass = COMMAND_CLASS_ERROR;
replyPacket->Command = COMMAND_ERROR_GENERIC;
if (Downstream_TransmitPacket(replyPacket) == HAL_OK)
{
Downstream_TransmitPacket(replyPacket);
Downstream_ReceivePacket(Downstream_PacketProcessor);
}
}
void Downstream_PacketProcessor_ClassReply(DownstreamPacketTypeDef* replyPacket)
{
if (Downstream_TransmitPacket(replyPacket) == HAL_OK)
{
Downstream_TransmitPacket(replyPacket);
Downstream_ReceivePacket(Downstream_PacketProcessor);
}
}
//This callback receives various event ids from the host stack,
@ -173,14 +185,12 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id)
return;
}
//Elevate our priority level so we aren't interrupted
__set_BASEPRI(INT_PRIORITY_OTG_FS);
__set_BASEPRI(INT_PRIORITY_OTG_FS); //Elevate our priority level so we aren't interrupted
//Called from main()
if (id == HOST_USER_UNRECOVERED_ERROR)
{
DOWNSTREAM_STATEMACHINE_FREAKOUT_NORETURN;
DOWNSTREAM_STATEMACHINE_FREAKOUT;
__set_BASEPRI(0);
return;
}
@ -212,7 +222,7 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id)
//If the new device has failed its 'approval' checks, we are sufficiently freaked out.
if (newActiveClass == COMMAND_CLASS_INTERFACE)
{
DOWNSTREAM_STATEMACHINE_FREAKOUT_NORETURN;
DOWNSTREAM_STATEMACHINE_FREAKOUT;
__set_BASEPRI(0);
return;
}
@ -222,7 +232,7 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id)
if ((ConfiguredDeviceClass != COMMAND_CLASS_INTERFACE) &&
(ConfiguredDeviceClass != newActiveClass))
{
DOWNSTREAM_STATEMACHINE_FREAKOUT_NORETURN;
DOWNSTREAM_STATEMACHINE_FREAKOUT;
__set_BASEPRI(0);
return;
}
@ -242,7 +252,7 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id)
return;
}
DOWNSTREAM_STATEMACHINE_FREAKOUT_NORETURN;
DOWNSTREAM_STATEMACHINE_FREAKOUT;
__set_BASEPRI(0);
return;
}

@ -51,4 +51,13 @@ typedef enum
InterfaceCommandMscTypeDef;
typedef enum
{
COMMAND_ERROR_GENERIC,
COMMAND_ERROR_DEVICE_DISCONNECTED,
}
InterfaceCommandErrorTypeDef;
#endif /* INC_UPSTREAM_INTERFACE_DEF_H_ */

@ -27,7 +27,6 @@
typedef enum
{
UPSTREAM_INTERFACE_IDLE,

@ -33,6 +33,7 @@ typedef enum
void Upstream_InitStateMachine(void);
void Upstream_StateMachine_SetErrorState(void);
HAL_StatusTypeDef Upstream_StateMachine_CheckClassOperationOk(void);
void Upstream_StateMachine_DeviceDisconnected(void);

@ -24,12 +24,16 @@ InterfaceStateTypeDef UpstreamInterfaceState = UPSTREAM_INTERFACE_IDLE;
FreePacketCallbackTypeDef PendingFreePacketCallback = NULL; //Indicates someone is waiting for a packet buffer to become available
SpiPacketReceivedCallbackTypeDef ReceivePacketCallback = NULL; //Indicates someone is waiting for a received packet
uint8_t TxOkInterruptReceived = 0;
uint8_t SentCommandClass;
uint8_t SentCommand;
static HAL_StatusTypeDef Upstream_CheckBeginPacketReception(void);
static void Upstream_BeginPacketReception(UpstreamPacketTypeDef* freePacket);
void Upstream_BeginTransmitPacketSize(void);
void Upstream_BeginTransmitPacketBody(void);
HAL_StatusTypeDef Upstream_CheckBeginPacketReception(void);
void Upstream_BeginReceivePacketSize(UpstreamPacketTypeDef* freePacket);
void Upstream_BeginReceivePacketBody(void);
@ -191,6 +195,14 @@ HAL_StatusTypeDef Upstream_TransmitPacket(UpstreamPacketTypeDef* packetToWrite)
CurrentWorkingPacket = packetToWrite;
SentCommandClass = CurrentWorkingPacket->CommandClass;
SentCommand = CurrentWorkingPacket->Command;
//Downstream may have set TxOk pin before we wanted to transmit.
//In this case we can go ahead and transmit now.
if (TxOkInterruptReceived)
{
TxOkInterruptReceived = 0;
Upstream_BeginTransmitPacketSize();
}
break;
default:
@ -217,6 +229,11 @@ void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
if (UpstreamInterfaceState == UPSTREAM_INTERFACE_TX_SIZE)
{
UpstreamInterfaceState = UPSTREAM_INTERFACE_TX_PACKET_WAIT;
if (TxOkInterruptReceived)
{
TxOkInterruptReceived = 0;
Upstream_BeginTransmitPacketBody();
}
return;
}
@ -241,6 +258,11 @@ void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
UpstreamInterfaceState = UPSTREAM_INTERFACE_TX_SIZE_WAIT;
CurrentWorkingPacket = NextTxPacket;
NextTxPacket = NULL;
if (TxOkInterruptReceived)
{
TxOkInterruptReceived = 0;
Upstream_BeginTransmitPacketSize();
}
return;
}
@ -286,7 +308,7 @@ HAL_StatusTypeDef Upstream_CheckBeginPacketReception(void)
return HAL_ERROR;
}
if (UpstreamInterfaceState > UPSTREAM_INTERFACE_RX_SIZE_WAIT)
if (UpstreamInterfaceState >= UPSTREAM_INTERFACE_RX_SIZE_WAIT)
{
UPSTREAM_SPI_FREAKOUT;
return HAL_ERROR;
@ -295,6 +317,11 @@ HAL_StatusTypeDef Upstream_CheckBeginPacketReception(void)
if (UpstreamInterfaceState == UPSTREAM_INTERFACE_IDLE)
{
UpstreamInterfaceState = UPSTREAM_INTERFACE_RX_SIZE_WAIT;
if (TxOkInterruptReceived)
{
TxOkInterruptReceived = 0;
Upstream_GetFreePacket(Upstream_BeginReceivePacketSize);
}
}
return HAL_OK;
}
@ -311,7 +338,34 @@ void Upstream_TxOkInterrupt(void)
switch (UpstreamInterfaceState)
{
case UPSTREAM_INTERFACE_IDLE:
TxOkInterruptReceived = 1;
break;
case UPSTREAM_INTERFACE_TX_SIZE_WAIT:
Upstream_BeginTransmitPacketSize();
break;
case UPSTREAM_INTERFACE_TX_PACKET_WAIT:
Upstream_BeginTransmitPacketBody();
break;
case UPSTREAM_INTERFACE_RX_SIZE_WAIT:
Upstream_GetFreePacket(Upstream_BeginReceivePacketSize);
break;
case UPSTREAM_INTERFACE_RX_PACKET_WAIT:
Upstream_BeginReceivePacketBody();
break;
default:
UPSTREAM_SPI_FREAKOUT;
}
}
void Upstream_BeginTransmitPacketSize(void)
{
UpstreamInterfaceState = UPSTREAM_INTERFACE_TX_SIZE;
SPI1_NSS_ASSERT;
if (HAL_SPI_Transmit_DMA(&Hspi1,
@ -320,9 +374,11 @@ void Upstream_TxOkInterrupt(void)
{
UPSTREAM_SPI_FREAKOUT;
}
break;
}
case UPSTREAM_INTERFACE_TX_PACKET_WAIT:
void Upstream_BeginTransmitPacketBody(void)
{
UpstreamInterfaceState = UPSTREAM_INTERFACE_TX_PACKET;
SPI1_NSS_ASSERT;
if ((HAL_SPI_Transmit_DMA(&Hspi1,
@ -331,32 +387,12 @@ void Upstream_TxOkInterrupt(void)
{
UPSTREAM_SPI_FREAKOUT;
}
break;
case UPSTREAM_INTERFACE_RX_SIZE_WAIT:
Upstream_GetFreePacket(Upstream_BeginPacketReception);
break;
case UPSTREAM_INTERFACE_RX_PACKET_WAIT:
UpstreamInterfaceState = UPSTREAM_INTERFACE_RX_PACKET;
SPI1_NSS_ASSERT;
if ((HAL_SPI_Receive_DMA(&Hspi1,
&CurrentWorkingPacket->CommandClass,
(CurrentWorkingPacket->Length + 1))) != HAL_OK) //"When the CRC feature is enabled the pData Length must be Size + 1"
{
UPSTREAM_SPI_FREAKOUT;
}
break;
default:
UPSTREAM_SPI_FREAKOUT;
}
}
//Internal use only.
//Called when we want to receive downstream packet, and a packet buffer has become free.
void Upstream_BeginPacketReception(UpstreamPacketTypeDef* freePacket)
void Upstream_BeginReceivePacketSize(UpstreamPacketTypeDef* freePacket)
{
if (UpstreamInterfaceState >= UPSTREAM_INTERFACE_ERROR)
{
@ -381,6 +417,19 @@ void Upstream_BeginPacketReception(UpstreamPacketTypeDef* freePacket)
}
void Upstream_BeginReceivePacketBody(void)
{
UpstreamInterfaceState = UPSTREAM_INTERFACE_RX_PACKET;
SPI1_NSS_ASSERT;
if ((HAL_SPI_Receive_DMA(&Hspi1,
&CurrentWorkingPacket->CommandClass,
(CurrentWorkingPacket->Length + 1))) != HAL_OK) //"When the CRC feature is enabled the pData Length must be Size + 1"
{
UPSTREAM_SPI_FREAKOUT;
}
}
//Called at the end of the SPI RX DMA transfer,
//at DMA2 interrupt priority. Assume *hspi points to our hspi1.
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
@ -403,20 +452,34 @@ void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
return;
}
UpstreamInterfaceState = UPSTREAM_INTERFACE_RX_PACKET_WAIT;
if (TxOkInterruptReceived)
{
TxOkInterruptReceived = 0;
Upstream_BeginReceivePacketBody();
}
return;
}
if (UpstreamInterfaceState == UPSTREAM_INTERFACE_RX_PACKET)
{
UpstreamInterfaceState = UPSTREAM_INTERFACE_IDLE;
if (ReceivePacketCallback == NULL)
{
UPSTREAM_SPI_FREAKOUT;
return;
}
UpstreamInterfaceState = UPSTREAM_INTERFACE_IDLE;
if ((SentCommandClass != (CurrentWorkingPacket->CommandClass & COMMAND_CLASS_MASK)) ||
(SentCommand != CurrentWorkingPacket->Command))
if ((CurrentWorkingPacket->CommandClass == COMMAND_CLASS_ERROR) &&
(CurrentWorkingPacket->Command == COMMAND_ERROR_DEVICE_DISCONNECTED))
{
Upstream_ReleasePacket(CurrentWorkingPacket);
ReceivePacketCallback = NULL;
Upstream_StateMachine_DeviceDisconnected();
return;
}
if (((CurrentWorkingPacket->CommandClass & COMMAND_CLASS_MASK) != SentCommandClass) ||
(CurrentWorkingPacket->Command != SentCommand))
{
UPSTREAM_SPI_FREAKOUT;
Upstream_ReleasePacket(CurrentWorkingPacket);

@ -15,11 +15,12 @@
UpstreamStateTypeDef UpstreamState = STATE_TEST_INTERFACE;
InterfaceCommandClassTypeDef ActiveDeviceClass = COMMAND_CLASS_INTERFACE;
InterfaceCommandClassTypeDef ConfiguredDeviceClass = COMMAND_CLASS_INTERFACE;
void Upstream_TestInterfaceReplyCallback(UpstreamPacketTypeDef* replyPacket);
void Upstream_NotifyDeviceReplyCallback(UpstreamPacketTypeDef* replyPacket);
void Upstream_StateMachine_TestInterfaceReplyCallback(UpstreamPacketTypeDef* replyPacket);
void Upstream_StateMachine_NotifyDevice(UpstreamPacketTypeDef* freePacket);
void Upstream_StateMachine_NotifyDeviceReplyCallback(UpstreamPacketTypeDef* replyPacket);
@ -42,9 +43,9 @@ void Upstream_InitStateMachine(void)
freePacket->Length = UPSTREAM_PACKET_HEADER_LEN + MSC_MEDIA_PACKET;
freePacket->CommandClass = COMMAND_CLASS_INTERFACE;
freePacket->Command = COMMAND_INTERFACE_ECHO;
testDataValue = 0xFF;
//Fill our test packet with some junk
testDataValue = 0xFF;
for (i = 0; i < MSC_MEDIA_PACKET; i++)
{
freePacket->Data[i] = testDataValue;
@ -53,7 +54,7 @@ void Upstream_InitStateMachine(void)
if (Upstream_TransmitPacket(freePacket) == HAL_OK)
{
Upstream_ReceivePacket(Upstream_TestInterfaceReplyCallback);
Upstream_ReceivePacket(Upstream_StateMachine_TestInterfaceReplyCallback);
}
}
@ -62,8 +63,8 @@ void Upstream_InitStateMachine(void)
void Upstream_StateMachine_SetErrorState(void)
{
UpstreamState = STATE_ERROR;
if ((ActiveDeviceClass > COMMAND_CLASS_INTERFACE) &&
(ActiveDeviceClass < COMMAND_CLASS_ERROR))
if ((ConfiguredDeviceClass > COMMAND_CLASS_INTERFACE) &&
(ConfiguredDeviceClass < COMMAND_CLASS_ERROR))
{
USBD_Stop(&hUsbDeviceFS);
}
@ -87,7 +88,7 @@ HAL_StatusTypeDef Upstream_StateMachine_CheckClassOperationOk(void)
}
void Upstream_TestInterfaceReplyCallback(UpstreamPacketTypeDef* replyPacket)
void Upstream_StateMachine_TestInterfaceReplyCallback(UpstreamPacketTypeDef* replyPacket)
{
uint16_t i;
uint8_t testDataValue;
@ -121,21 +122,29 @@ void Upstream_TestInterfaceReplyCallback(UpstreamPacketTypeDef* replyPacket)
testDataValue += 39;
}
//SPI interface passed checks. Now we wait for a device to be attached to downstream.
Upstream_StateMachine_NotifyDevice(replyPacket);
}
void Upstream_StateMachine_NotifyDevice(UpstreamPacketTypeDef* freePacket)
{
UpstreamState = STATE_WAIT_DEVICE;
replyPacket->Length = UPSTREAM_PACKET_HEADER_LEN;
replyPacket->CommandClass = COMMAND_CLASS_INTERFACE;
replyPacket->Command = COMMAND_INTERFACE_NOTIFY_DEVICE;
if (Upstream_TransmitPacket(replyPacket) == HAL_OK)
freePacket->Length = UPSTREAM_PACKET_HEADER_LEN;
freePacket->CommandClass = COMMAND_CLASS_INTERFACE;
freePacket->Command = COMMAND_INTERFACE_NOTIFY_DEVICE;
if (Upstream_TransmitPacket(freePacket) == HAL_OK)
{
Upstream_ReceivePacket(Upstream_NotifyDeviceReplyCallback);
Upstream_ReceivePacket(Upstream_StateMachine_NotifyDeviceReplyCallback);
}
}
void Upstream_NotifyDeviceReplyCallback(UpstreamPacketTypeDef* replyPacket)
void Upstream_StateMachine_NotifyDeviceReplyCallback(UpstreamPacketTypeDef* replyPacket)
{
InterfaceCommandClassTypeDef newActiveClass = COMMAND_CLASS_INTERFACE;
USBD_ClassTypeDef* newClassPointer;
if (UpstreamState >= STATE_ERROR)
{
return;
@ -157,20 +166,47 @@ void Upstream_NotifyDeviceReplyCallback(UpstreamPacketTypeDef* replyPacket)
switch (replyPacket->Data[0])
{
case COMMAND_CLASS_MASS_STORAGE:
USBD_RegisterClass(&hUsbDeviceFS, &USBD_MSC);
newActiveClass = COMMAND_CLASS_MASS_STORAGE;
newClassPointer = &USBD_MSC;
break;
default:
//Add other supported classes here...
}
if (newActiveClass == COMMAND_CLASS_INTERFACE)
{
UPSTREAM_STATEMACHINE_FREAKOUT;
return;
}
//Downstream should never change the active device class without rebooting!
if ((ConfiguredDeviceClass != COMMAND_CLASS_INTERFACE) &&
(ConfiguredDeviceClass != newActiveClass))
{
UPSTREAM_STATEMACHINE_FREAKOUT;
return;
}
USBD_Start(&hUsbDeviceFS);
UpstreamState = STATE_DEVICE_ACTIVE;
ActiveDeviceClass = replyPacket->Data[0];
ConfiguredDeviceClass = newActiveClass;
USBD_RegisterClass(&hUsbDeviceFS, newClassPointer);
USBD_Start(&hUsbDeviceFS);
//The USB device stack will now receive commands from our host.
//All we need to do is check for downstream device removal.
//All we need to do is monitor for downstream device disconnection.
}
void Upstream_StateMachine_DeviceDisconnected(void)
{
if ((ConfiguredDeviceClass == COMMAND_CLASS_INTERFACE) ||
(ConfiguredDeviceClass >= COMMAND_CLASS_ERROR))
{
UPSTREAM_STATEMACHINE_FREAKOUT;
return;
}
USBD_Stop(&hUsbDeviceFS);
Upstream_GetFreePacket(Upstream_StateMachine_NotifyDevice);
}

Loading…
Cancel
Save