From b9b612364214d29f18ef2b5c7db5db138423ba6c Mon Sep 17 00:00:00 2001 From: Robert Fisk Date: Thu, 13 Aug 2015 20:14:57 +1200 Subject: [PATCH] Commit of Downstream before diving into USB MSC class driver modifications. Also correct project settings to compile for Cortex M4 architecture. --- Downstream/.cproject | 6 +- Downstream/.settings/language.settings.xml | 2 +- Downstream/Inc/downstream_interface_def.h | 2 + Downstream/Inc/downstream_msc.h | 20 ++++ Downstream/Inc/downstream_statemachine.h | 11 +- Downstream/Src/downstream_msc.c | 132 +++++++++++++++++++++ Downstream/Src/downstream_statemachine.c | 93 ++++++++++----- Upstream/.cproject | 18 ++- Upstream/.settings/language.settings.xml | 2 +- Upstream/Inc/upstream_interface_def.h | 4 +- 10 files changed, 247 insertions(+), 43 deletions(-) create mode 100644 Downstream/Inc/downstream_msc.h create mode 100644 Downstream/Src/downstream_msc.c diff --git a/Downstream/.cproject b/Downstream/.cproject index ae7ab7c..e7f3c64 100644 --- a/Downstream/.cproject +++ b/Downstream/.cproject @@ -15,7 +15,7 @@ - diff --git a/Downstream/.settings/language.settings.xml b/Downstream/.settings/language.settings.xml index 1974b05..7febaad 100644 --- a/Downstream/.settings/language.settings.xml +++ b/Downstream/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/Downstream/Inc/downstream_interface_def.h b/Downstream/Inc/downstream_interface_def.h index d0f2947..5121572 100644 --- a/Downstream/Inc/downstream_interface_def.h +++ b/Downstream/Inc/downstream_interface_def.h @@ -25,6 +25,8 @@ typedef enum { COMMAND_CLASS_INTERFACE, COMMAND_CLASS_MASS_STORAGE, + //... + COMMAND_CLASS_ERROR } InterfaceCommandClassTypeDef; diff --git a/Downstream/Inc/downstream_msc.h b/Downstream/Inc/downstream_msc.h new file mode 100644 index 0000000..8b1e5b4 --- /dev/null +++ b/Downstream/Inc/downstream_msc.h @@ -0,0 +1,20 @@ +/* + * downstream_msc.h + * + * Created on: 8/08/2015 + * Author: Robert Fisk + */ + +#ifndef INC_DOWNSTREAM_MSC_H_ +#define INC_DOWNSTREAM_MSC_H_ + + +#include "downstream_spi.h" + + +HAL_StatusTypeDef Downstream_MSC_ApproveConnectedDevice(void); +void Downstream_MSC_PacketProcessor(DownstreamPacketTypeDef* receivedPacket); + + + +#endif /* INC_DOWNSTREAM_MSC_H_ */ diff --git a/Downstream/Inc/downstream_statemachine.h b/Downstream/Inc/downstream_statemachine.h index 8fce582..dc61ce4 100644 --- a/Downstream/Inc/downstream_statemachine.h +++ b/Downstream/Inc/downstream_statemachine.h @@ -10,13 +10,15 @@ #include "usbh_def.h" +#include "downstream_spi.h" typedef enum { - STATE_NOT_READY, - STATE_WAIT_DEVICE_READY_CALLBACK, - STATE_DEVICE_READY, + STATE_DEVICE_NOT_READY, + STATE_DEVICE_READY, //HOST_USER_CLASS_ACTIVE callback arrives first + STATE_WAIT_DEVICE_READY, //COMMAND_INTERFACE_NOTIFY_DEVICE message arrives first + STATE_ACTIVE, STATE_ERROR } DownstreamStateTypeDef; @@ -24,7 +26,8 @@ typedef enum void Downstream_InitStateMachine(void); void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id); - +void Downstream_PacketProcessor_ErrorReply(DownstreamPacketTypeDef* replyPacket); +void Downstream_PacketProcessor_ClassReply(DownstreamPacketTypeDef* replyPacket); #endif /* INC_DOWNSTREAM_STATEMACHINE_H_ */ diff --git a/Downstream/Src/downstream_msc.c b/Downstream/Src/downstream_msc.c new file mode 100644 index 0000000..a721cbe --- /dev/null +++ b/Downstream/Src/downstream_msc.c @@ -0,0 +1,132 @@ +/* + * downstream_msc.c + * + * Created on: 8/08/2015 + * Author: Robert Fisk + */ + + +#include "downstream_msc.h" +#include "downstream_interface_def.h" +#include "downstream_statemachine.h" +#include "usbh_msc.h" + + +extern USBH_HandleTypeDef hUsbHostFS; //Hard-link ourselves to usb_host.c + + +void Downstream_MSC_PacketProcessor_TestUnitReady(DownstreamPacketTypeDef* receivedPacket); +void Downstream_MSC_PacketProcessor_GetCapacity(DownstreamPacketTypeDef* receivedPacket); +void Downstream_MSC_PacketProcessor_BeginRead(DownstreamPacketTypeDef* receivedPacket); + + + +//High-level checks on the connected device. We don't want some weirdly +//configured device to bomb our USB stack, accidentally or otherwise. +HAL_StatusTypeDef Downstream_MSC_ApproveConnectedDevice(void) +{ + MSC_HandleTypeDef* MSC_Handle = (MSC_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; + + if ((MSC_Handle->unit[0].capacity.block_nbr == 0) || + (MSC_Handle->unit[0].capacity.block_nbr == UINT32_MAX)) + { + return HAL_ERROR; + } + + if (MSC_Handle->unit[0].capacity.block_size != 512) + { + return HAL_ERROR; + } + + return HAL_OK; +} + + +void Downstream_MSC_PacketProcessor(DownstreamPacketTypeDef* receivedPacket) +{ + switch (receivedPacket->Command) + { + case COMMAND_MSC_TEST_UNIT_READY: + Downstream_MSC_PacketProcessor_TestUnitReady(receivedPacket); + break; + + case COMMAND_MSC_GET_CAPACITY: + Downstream_MSC_PacketProcessor_GetCapacity(receivedPacket); + break; + + case COMMAND_MSC_BEGIN_READ: + Downstream_MSC_PacketProcessor_BeginRead(receivedPacket); + break; + + default: + Downstream_PacketProcessor_ErrorReply(receivedPacket); + } + +} + + +void Downstream_MSC_PacketProcessor_TestUnitReady(DownstreamPacketTypeDef* receivedPacket) +{ + if (USBH_MSC_UnitIsReady(&hUsbHostFS, 0)) + { + receivedPacket->Data[0] = HAL_OK; + } + else + { + receivedPacket->Data[0] = HAL_ERROR; + } + receivedPacket->Length = DOWNSTREAM_PACKET_HEADER_LEN + 1; + Downstream_PacketProcessor_ClassReply(receivedPacket); +} + + +void Downstream_MSC_PacketProcessor_GetCapacity(DownstreamPacketTypeDef* receivedPacket) +{ + MSC_HandleTypeDef* MSC_Handle = (MSC_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; + + receivedPacket->Length = DOWNSTREAM_PACKET_HEADER_LEN + 8; + *(uint32_t*)&(receivedPacket->Data[0]) = MSC_Handle->unit[0].capacity.block_nbr; + *(uint32_t*)&(receivedPacket->Data[4]) = (uint32_t)MSC_Handle->unit[0].capacity.block_size; + Downstream_PacketProcessor_ClassReply(receivedPacket); +} + + + +void Downstream_MSC_PacketProcessor_BeginRead(DownstreamPacketTypeDef* receivedPacket) +{ + uint64_t address; + uint32_t count; + MSC_HandleTypeDef* MSC_Handle = (MSC_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; + + if (receivedPacket->Length != (DOWNSTREAM_PACKET_HEADER_LEN + (4 * 3))) + { + Downstream_PacketProcessor_ErrorReply(receivedPacket); + return; + } + + address = *(uint64_t*)&(receivedPacket->Data[0]); + count = *(uint32_t*)&(receivedPacket->Data[8]); + if ((address >= (uint64_t)MSC_Handle->unit[0].capacity.block_nbr) || + ((address + count - 1) >= (uint64_t)MSC_Handle->unit[0].capacity.block_nbr)) + { + Downstream_PacketProcessor_ErrorReply(receivedPacket); + return; + } + + if (USBH_MSC_UnitIsReady(&hUsbHostFS, 0)) + { + receivedPacket->Data[0] = HAL_OK; + } + else + { + receivedPacket->Data[0] = HAL_ERROR; + } + receivedPacket->Length = DOWNSTREAM_PACKET_HEADER_LEN + 1; + Downstream_TransmitPacket(receivedPacket); + + USBH_MSC_Read(&hUsbHostFS, + 0, + (uint32_t)address, + count); +} + diff --git a/Downstream/Src/downstream_statemachine.c b/Downstream/Src/downstream_statemachine.c index 5f4924b..3a9f97a 100644 --- a/Downstream/Src/downstream_statemachine.c +++ b/Downstream/Src/downstream_statemachine.c @@ -9,6 +9,7 @@ #include "downstream_statemachine.h" #include "downstream_interface_def.h" #include "downstream_spi.h" +#include "downstream_msc.h" #include "usbh_core.h" #include "usbh_msc.h" @@ -21,13 +22,12 @@ InterfaceCommandClassTypeDef ConfiguredDeviceClass; void Downstream_PacketProcessor(DownstreamPacketTypeDef* receivedPacket); void Downstream_PacketProcessor_Interface(DownstreamPacketTypeDef* receivedPacket); void Downstream_PacketProcessor_Interface_ReplyNotifyDevice(DownstreamPacketTypeDef* replyPacket); -void Downstream_PacketProcessor_EmptyReply(DownstreamPacketTypeDef* replyPacket); void Downstream_InitStateMachine(void) { - DownstreamState = STATE_NOT_READY; + DownstreamState = STATE_DEVICE_NOT_READY; ConfiguredDeviceClass = COMMAND_CLASS_INTERFACE; Downstream_InitSPI(); @@ -41,7 +41,7 @@ void Downstream_PacketProcessor(DownstreamPacketTypeDef* receivedPacket) switch (receivedPacket->CommandClass) { case COMMAND_CLASS_INTERFACE: - if (DownstreamState != STATE_NOT_READY) + if (DownstreamState > STATE_DEVICE_READY) { SPI_INTERFACE_FREAKOUT_RETURN_VOID; } @@ -49,17 +49,18 @@ void Downstream_PacketProcessor(DownstreamPacketTypeDef* receivedPacket) break; case COMMAND_CLASS_MASS_STORAGE: - if (DownstreamState != STATE_DEVICE_READY) + if (DownstreamState != STATE_ACTIVE) { - Downstream_PacketProcessor_EmptyReply(receivedPacket); + Downstream_PacketProcessor_ErrorReply(receivedPacket); + return; } - //Mass storage packet processor... + Downstream_MSC_PacketProcessor(receivedPacket); break; //Add other classes here... default: - SPI_INTERFACE_FREAKOUT_RETURN_VOID; + Downstream_PacketProcessor_ErrorReply(receivedPacket); } } @@ -72,22 +73,27 @@ void Downstream_PacketProcessor_Interface(DownstreamPacketTypeDef* receivedPacke case COMMAND_INTERFACE_ECHO: Downstream_TransmitPacket(receivedPacket); Downstream_ReceivePacket(Downstream_PacketProcessor); - break; + return; case COMMAND_INTERFACE_NOTIFY_DEVICE: - if (ConfiguredDeviceClass != COMMAND_CLASS_INTERFACE) + if (DownstreamState == STATE_DEVICE_READY) { Downstream_PacketProcessor_Interface_ReplyNotifyDevice(receivedPacket); + return; } - else + + if (DownstreamState == STATE_DEVICE_NOT_READY) { + DownstreamState = STATE_WAIT_DEVICE_READY; Downstream_ReleasePacket(receivedPacket); - DownstreamState = STATE_WAIT_DEVICE_READY_CALLBACK; + return; } - break; + Downstream_PacketProcessor_ErrorReply(receivedPacket); + return; + default: - SPI_INTERFACE_FREAKOUT_RETURN_VOID; + Downstream_PacketProcessor_ErrorReply(receivedPacket); } } @@ -100,60 +106,85 @@ void Downstream_PacketProcessor_Interface_ReplyNotifyDevice(DownstreamPacketType replyPacket->Data[0] = ConfiguredDeviceClass; Downstream_TransmitPacket(replyPacket); - DownstreamState = STATE_DEVICE_READY; + DownstreamState = STATE_ACTIVE; Downstream_ReceivePacket(Downstream_PacketProcessor); } -//An empty reply implies and error processing class-specific requests. -void Downstream_PacketProcessor_EmptyReply(DownstreamPacketTypeDef* replyPacket) +void Downstream_PacketProcessor_ErrorReply(DownstreamPacketTypeDef* replyPacket) { replyPacket->Length = DOWNSTREAM_PACKET_HEADER_LEN; + replyPacket->CommandClass = COMMAND_CLASS_ERROR; + Downstream_TransmitPacket(replyPacket); + Downstream_ReceivePacket(Downstream_PacketProcessor); +} + + +void Downstream_PacketProcessor_ClassReply(DownstreamPacketTypeDef* replyPacket) +{ Downstream_TransmitPacket(replyPacket); Downstream_ReceivePacket(Downstream_PacketProcessor); } +//This callback receives various event ids from the host stack, either +//at INT_PRIORITY_OTG_FS or from main(). We should therefore be prepared +//for pre-emption by USB or SPI/DMA interrupts. void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id) { - InterfaceCommandClassTypeDef newActiveClass; + InterfaceCommandClassTypeDef newActiveClass = COMMAND_CLASS_INTERFACE; + //Called from USB interrupt if (id == HOST_USER_DISCONNECTION) { - DownstreamState = STATE_NOT_READY; + DownstreamState = STATE_DEVICE_NOT_READY; return; } - + //Called from main(). Beware pre-emption! if (id == HOST_USER_CLASS_ACTIVE) { - if (DownstreamState > STATE_WAIT_DEVICE_READY_CALLBACK) - { - SPI_INTERFACE_FREAKOUT_RETURN_VOID; - } - switch (phost->pActiveClass->ClassCode) { case USB_MSC_CLASS: - newActiveClass = COMMAND_CLASS_MASS_STORAGE; + if (Downstream_MSC_ApproveConnectedDevice() == HAL_OK) + { + newActiveClass = COMMAND_CLASS_MASS_STORAGE; + } break; //Add other classes here... - - default: - newActiveClass = COMMAND_CLASS_INTERFACE; } + //To change device class, we must reboot. if ((ConfiguredDeviceClass != COMMAND_CLASS_INTERFACE) && - (ConfiguredDeviceClass != newActiveClass)) //To change device class, we must reboot. + (ConfiguredDeviceClass != newActiveClass)) { - SPI_INTERFACE_FREAKOUT_RETURN_VOID; + SPI_INTERFACE_FREAKOUT_NO_RETURN; + DownstreamState = STATE_ERROR; + return; } + + if (newActiveClass == COMMAND_CLASS_INTERFACE) + { + return; + } + ConfiguredDeviceClass = newActiveClass; - if (DownstreamState == STATE_WAIT_DEVICE_READY_CALLBACK) + if (DownstreamState == STATE_WAIT_DEVICE_READY) { Downstream_GetFreePacket(Downstream_PacketProcessor_Interface_ReplyNotifyDevice); + return; + } + + if (DownstreamState == STATE_DEVICE_NOT_READY) + { + DownstreamState = STATE_DEVICE_READY; + return; } + + SPI_INTERFACE_FREAKOUT_NO_RETURN; + DownstreamState = STATE_ERROR; return; } } diff --git a/Upstream/.cproject b/Upstream/.cproject index 6331ec4..d430332 100755 --- a/Upstream/.cproject +++ b/Upstream/.cproject @@ -153,7 +153,7 @@ - + + diff --git a/Upstream/.settings/language.settings.xml b/Upstream/.settings/language.settings.xml index e0f7243..c8d28e9 100755 --- a/Upstream/.settings/language.settings.xml +++ b/Upstream/.settings/language.settings.xml @@ -16,7 +16,7 @@ - + diff --git a/Upstream/Inc/upstream_interface_def.h b/Upstream/Inc/upstream_interface_def.h index ae7eb24..24e12de 100644 --- a/Upstream/Inc/upstream_interface_def.h +++ b/Upstream/Inc/upstream_interface_def.h @@ -26,7 +26,9 @@ typedef enum { COMMAND_CLASS_INTERFACE, - COMMAND_CLASS_MASS_STORAGE + COMMAND_CLASS_MASS_STORAGE, + //... + COMMAND_CLASS_ERROR } InterfaceCommandClassTypeDef;