You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
usb-firewall-fork/Upstream/Src/upstream_statemachine.c

177 lines
3.6 KiB

/*
* upstream_statemachine.c
*
* Created on: 20/08/2015
* Author: Robert Fisk
*/
#include "upstream_statemachine.h"
#include "upstream_spi.h"
#include "upstream_interface_def.h"
#include "usb_device.h"
#include "usbd_core.h"
#include "usbd_msc.h"
UpstreamStateTypeDef UpstreamState = STATE_TEST_INTERFACE;
InterfaceCommandClassTypeDef ActiveDeviceClass = COMMAND_CLASS_INTERFACE;
void Upstream_TestInterfaceReplyCallback(UpstreamPacketTypeDef* replyPacket);
void Upstream_NotifyDeviceReplyCallback(UpstreamPacketTypeDef* replyPacket);
void Upstream_InitStateMachine(void)
{
UpstreamPacketTypeDef* freePacket;
uint16_t i;
uint8_t testDataValue;
Upstream_InitSPI();
//Prepare SPI test packet
freePacket = Upstream_GetFreePacketImmediately();
if (freePacket == NULL)
{
UpstreamState = STATE_ERROR;
return;
}
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
for (i = 0; i < MSC_MEDIA_PACKET; i++)
{
freePacket->Data[i] = testDataValue;
testDataValue += 39;
}
if (Upstream_TransmitPacket(freePacket) == HAL_OK)
{
Upstream_ReceivePacket(Upstream_TestInterfaceReplyCallback);
}
}
//Used by upstream_spi freakout macro, indicates we should stop everything.
void Upstream_StateMachine_SetErrorState(void)
{
UpstreamState = STATE_ERROR;
if ((ActiveDeviceClass > COMMAND_CLASS_INTERFACE) &&
(ActiveDeviceClass < COMMAND_CLASS_ERROR))
{
USBD_Stop(&hUsbDeviceFS);
}
}
HAL_StatusTypeDef Upstream_StateMachine_CheckClassOperationOk(void)
{
if (UpstreamState == STATE_ERROR)
{
return HAL_ERROR;
}
if (UpstreamState != STATE_DEVICE_ACTIVE)
{
UPSTREAM_STATEMACHINE_FREAKOUT;
return HAL_ERROR;
}
return HAL_OK;
}
void Upstream_TestInterfaceReplyCallback(UpstreamPacketTypeDef* replyPacket)
{
uint16_t i;
uint8_t testDataValue;
if (UpstreamState >= STATE_ERROR)
{
return;
}
if ((UpstreamState != STATE_TEST_INTERFACE) ||
(replyPacket == NULL))
{
UPSTREAM_STATEMACHINE_FREAKOUT;
return;
}
if (replyPacket->Length != (UPSTREAM_PACKET_HEADER_LEN + MSC_MEDIA_PACKET))
{
UPSTREAM_STATEMACHINE_FREAKOUT;
return;
}
testDataValue = 0xFF;
for (i = 0; i < MSC_MEDIA_PACKET; i++)
{
if (replyPacket->Data[i] != testDataValue)
{
UPSTREAM_STATEMACHINE_FREAKOUT;
return;
}
testDataValue += 39;
}
//SPI interface passed checks. Now we wait for a device to be attached to downstream.
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)
{
Upstream_ReceivePacket(Upstream_NotifyDeviceReplyCallback);
}
}
void Upstream_NotifyDeviceReplyCallback(UpstreamPacketTypeDef* replyPacket)
{
if (UpstreamState >= STATE_ERROR)
{
return;
}
if ((UpstreamState != STATE_WAIT_DEVICE) ||
(replyPacket == NULL))
{
UPSTREAM_STATEMACHINE_FREAKOUT;
return;
}
if (replyPacket->Length != (UPSTREAM_PACKET_HEADER_LEN + 1))
{
UPSTREAM_STATEMACHINE_FREAKOUT;
return;
}
switch (replyPacket->Data[0])
{
case COMMAND_CLASS_MASS_STORAGE:
USBD_RegisterClass(&hUsbDeviceFS, &USBD_MSC);
break;
default:
UPSTREAM_STATEMACHINE_FREAKOUT;
return;
}
USBD_Start(&hUsbDeviceFS);
UpstreamState = STATE_DEVICE_ACTIVE;
ActiveDeviceClass = replyPacket->Data[0];
//The USB device stack will now receive commands from our host.
//All we need to do is check for downstream device removal.
}