|
|
@@ -1,19 +1,19 @@
|
|
|
-// Copyright (C) 2014 Michael McMaster <michael@codesrc.com>
|
|
|
+// Copyright (C) 2014 Michael McMaster <michael@codesrc.com>
|
|
|
//
|
|
|
-// This file is part of SCSI2SD.
|
|
|
+// This file is part of SCSI2SD.
|
|
|
//
|
|
|
-// SCSI2SD 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.
|
|
|
+// SCSI2SD 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.
|
|
|
//
|
|
|
-// SCSI2SD 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.
|
|
|
+// SCSI2SD 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.
|
|
|
//
|
|
|
-// You should have received a copy of the GNU General Public License
|
|
|
-// along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
|
|
|
+// You should have received a copy of the GNU General Public License
|
|
|
+// along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
#include "config.h"
|
|
|
#include "led.h"
|
|
|
@@ -50,12 +50,12 @@ extern uint8_t* __fixed_config;
|
|
|
// 1 flash row
|
|
|
static const uint8_t DEFAULT_CONFIG[128] =
|
|
|
{
|
|
|
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3F, 0x00,
|
|
|
- 0x00, 0x02, 0x3F, 0x00, 0xFF, 0x00, 0x20, 0x63, 0x6F, 0x64, 0x65, 0x73,
|
|
|
- 0x72, 0x63, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53,
|
|
|
- 0x43, 0x53, 0x49, 0x32, 0x53, 0x44, 0x20, 0x31, 0x2E, 0x30, 0x31, 0x32,
|
|
|
- 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
|
|
|
- 0x37, 0x38, 0x00, 0x00
|
|
|
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3F, 0x00,
|
|
|
+ 0x00, 0x02, 0x3F, 0x00, 0xFF, 0x00, 0x20, 0x63, 0x6F, 0x64, 0x65, 0x73,
|
|
|
+ 0x72, 0x63, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53,
|
|
|
+ 0x43, 0x53, 0x49, 0x32, 0x53, 0x44, 0x20, 0x31, 0x2E, 0x30, 0x31, 0x32,
|
|
|
+ 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
|
|
|
+ 0x37, 0x38, 0x00, 0x00
|
|
|
};
|
|
|
|
|
|
|
|
|
@@ -65,8 +65,8 @@ static uint8_t configDmaBuf[512] S2S_DMA_ALIGN; // For SD card writes.
|
|
|
|
|
|
enum USB_STATE
|
|
|
{
|
|
|
- USB_IDLE,
|
|
|
- USB_DATA_SENT
|
|
|
+ USB_IDLE,
|
|
|
+ USB_DATA_SENT
|
|
|
};
|
|
|
|
|
|
|
|
|
@@ -79,419 +79,424 @@ static void s2s_debugTimer();
|
|
|
static s2s_lock_t usbDevLock = s2s_lock_init;
|
|
|
TIM_HandleTypeDef htim7;
|
|
|
static int debugTimerStarted = 0;
|
|
|
+
|
|
|
void TIM7_IRQHandler()
|
|
|
{
|
|
|
- HAL_TIM_IRQHandler(&htim7);
|
|
|
+ HAL_TIM_IRQHandler(&htim7);
|
|
|
}
|
|
|
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
|
|
|
{
|
|
|
- if (s2s_spin_trylock(&usbDevLock)) {
|
|
|
- s2s_debugTimer();
|
|
|
- s2s_spin_unlock(&usbDevLock);
|
|
|
- }
|
|
|
+ if (s2s_spin_trylock(&usbDevLock)) {
|
|
|
+ s2s_debugTimer();
|
|
|
+ s2s_spin_unlock(&usbDevLock);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void s2s_configInit(S2S_BoardCfg* config)
|
|
|
{
|
|
|
- usbInEpState = USB_IDLE;
|
|
|
-
|
|
|
- if (memcmp(__fixed_config, "BCFG", 4) == 0)
|
|
|
- {
|
|
|
- // Use hardcoded config
|
|
|
- memcpy(s2s_cfg, __fixed_config, S2S_CFG_SIZE);
|
|
|
- memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));
|
|
|
- }
|
|
|
-
|
|
|
- else if ((blockDev.state & DISK_PRESENT) && sdDev.capacity)
|
|
|
- {
|
|
|
- int cfgSectors = (S2S_CFG_SIZE + 511) / 512;
|
|
|
- BSP_SD_ReadBlocks_DMA(
|
|
|
- &s2s_cfg[0],
|
|
|
- sdDev.capacity - cfgSectors,
|
|
|
- cfgSectors);
|
|
|
-
|
|
|
- memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));
|
|
|
-
|
|
|
- if (memcmp(config->magic, "BCFG", 4))
|
|
|
- {
|
|
|
- // Invalid SD card config, use default.
|
|
|
- memset(&s2s_cfg[0], 0, S2S_CFG_SIZE);
|
|
|
- memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));
|
|
|
- memcpy(config->magic, "BCFG", 4);
|
|
|
- config->selectionDelay = 255; // auto
|
|
|
- config->flags6 = S2S_CFG_ENABLE_TERMINATOR;
|
|
|
-
|
|
|
- memcpy(
|
|
|
- &s2s_cfg[0] + sizeof(S2S_BoardCfg),
|
|
|
- DEFAULT_CONFIG,
|
|
|
- sizeof(S2S_TargetCfg));
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // No SD card, use existing config if valid
|
|
|
- if (memcmp(config->magic, "BCFG", 4))
|
|
|
- {
|
|
|
- // Not valid, use empty config with no disks.
|
|
|
- memset(&s2s_cfg[0], 0, S2S_CFG_SIZE);
|
|
|
- memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));
|
|
|
- config->selectionDelay = 255; // auto
|
|
|
- config->flags6 = S2S_CFG_ENABLE_TERMINATOR;
|
|
|
- }
|
|
|
- }
|
|
|
+ usbInEpState = USB_IDLE;
|
|
|
+
|
|
|
+ if (memcmp(__fixed_config, "BCFG", 4) == 0)
|
|
|
+ {
|
|
|
+ // Use hardcoded config
|
|
|
+ memcpy(s2s_cfg, __fixed_config, S2S_CFG_SIZE);
|
|
|
+ memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));
|
|
|
+ }
|
|
|
+
|
|
|
+ else if ((blockDev.state & DISK_PRESENT) && sdDev.capacity)
|
|
|
+ {
|
|
|
+ int cfgSectors = (S2S_CFG_SIZE + 511) / 512;
|
|
|
+ BSP_SD_ReadBlocks_DMA(
|
|
|
+ &s2s_cfg[0],
|
|
|
+ sdDev.capacity - cfgSectors,
|
|
|
+ cfgSectors);
|
|
|
+
|
|
|
+ memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));
|
|
|
+
|
|
|
+ if (memcmp(config->magic, "BCFG", 4))
|
|
|
+ {
|
|
|
+ // Invalid SD card config, use default.
|
|
|
+ memset(&s2s_cfg[0], 0, S2S_CFG_SIZE);
|
|
|
+ memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));
|
|
|
+ memcpy(config->magic, "BCFG", 4);
|
|
|
+ config->selectionDelay = 255; // auto
|
|
|
+ config->flags6 = S2S_CFG_ENABLE_TERMINATOR;
|
|
|
+
|
|
|
+ memcpy(
|
|
|
+ &s2s_cfg[0] + sizeof(S2S_BoardCfg),
|
|
|
+ DEFAULT_CONFIG,
|
|
|
+ sizeof(S2S_TargetCfg));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // No SD card, use existing config if valid
|
|
|
+ if (memcmp(config->magic, "BCFG", 4))
|
|
|
+ {
|
|
|
+ // Not valid, use empty config with no disks.
|
|
|
+ memset(&s2s_cfg[0], 0, S2S_CFG_SIZE);
|
|
|
+ memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));
|
|
|
+ config->selectionDelay = 255; // auto
|
|
|
+ config->flags6 = S2S_CFG_ENABLE_TERMINATOR;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static void debugInit(void)
|
|
|
{
|
|
|
- if (debugTimerStarted == 1) return;
|
|
|
+ if (debugTimerStarted == 1) return;
|
|
|
|
|
|
- debugTimerStarted = 1;
|
|
|
- // 10ms debug timer to capture logs over USB
|
|
|
- __TIM7_CLK_ENABLE();
|
|
|
- htim7.Instance = TIM7;
|
|
|
+ debugTimerStarted = 1;
|
|
|
+ // 10ms debug timer to capture logs over USB
|
|
|
+ __TIM7_CLK_ENABLE();
|
|
|
+ htim7.Instance = TIM7;
|
|
|
#ifdef STM32F2xx
|
|
|
- htim7.Init.Prescaler = 10800 - 1; // 16bit. 108MHz down to 10KHz
|
|
|
+ htim7.Init.Prescaler = 10800 - 1; // 16bit. 108MHz down to 10KHz
|
|
|
#else
|
|
|
- htim7.Init.Prescaler = 18000 - 1; // 16bit. 180MHz down to 10KHz
|
|
|
+ htim7.Init.Prescaler = 18000 - 1; // 16bit. 180MHz down to 10KHz
|
|
|
#endif
|
|
|
|
|
|
- htim7.Init.CounterMode = TIM_COUNTERMODE_UP;
|
|
|
- htim7.Init.Period = 100 - 1; // 16bit. 10KHz down to 10ms.
|
|
|
- htim7.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
|
|
- HAL_TIM_Base_Init(&htim7);
|
|
|
- HAL_TIM_Base_Start_IT(&htim7);
|
|
|
+ htim7.Init.CounterMode = TIM_COUNTERMODE_UP;
|
|
|
+ htim7.Init.Period = 100 - 1; // 16bit. 10KHz down to 10ms.
|
|
|
+ htim7.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
|
|
+ HAL_TIM_Base_Init(&htim7);
|
|
|
+ HAL_TIM_Base_Start_IT(&htim7);
|
|
|
|
|
|
- HAL_NVIC_SetPriority(TIM7_IRQn, 10, 0);
|
|
|
- HAL_NVIC_EnableIRQ(TIM7_IRQn);
|
|
|
+ HAL_NVIC_SetPriority(TIM7_IRQn, 10, 0);
|
|
|
+ HAL_NVIC_EnableIRQ(TIM7_IRQn);
|
|
|
}
|
|
|
|
|
|
|
|
|
static void
|
|
|
pingCommand()
|
|
|
{
|
|
|
- uint8_t response[] =
|
|
|
- {
|
|
|
- S2S_CFG_STATUS_GOOD
|
|
|
- };
|
|
|
- hidPacket_send(response, sizeof(response));
|
|
|
+ uint8_t response[] =
|
|
|
+ {
|
|
|
+ S2S_CFG_STATUS_GOOD
|
|
|
+ };
|
|
|
+ hidPacket_send(response, sizeof(response));
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
sdInfoCommand()
|
|
|
{
|
|
|
- uint8_t response[sizeof(sdDev.csd) + sizeof(sdDev.cid)];
|
|
|
- memcpy(response, sdDev.csd, sizeof(sdDev.csd));
|
|
|
- memcpy(response + sizeof(sdDev.csd), sdDev.cid, sizeof(sdDev.cid));
|
|
|
+ uint8_t response[sizeof(sdDev.csd) + sizeof(sdDev.cid)];
|
|
|
+ memcpy(response, sdDev.csd, sizeof(sdDev.csd));
|
|
|
+ memcpy(response + sizeof(sdDev.csd), sdDev.cid, sizeof(sdDev.cid));
|
|
|
|
|
|
- hidPacket_send(response, sizeof(response));
|
|
|
+ hidPacket_send(response, sizeof(response));
|
|
|
}
|
|
|
|
|
|
|
|
|
static void
|
|
|
scsiTestCommand()
|
|
|
{
|
|
|
- int resultCode = scsiSelfTest();
|
|
|
- uint8_t response[] =
|
|
|
- {
|
|
|
- resultCode == 0 ? S2S_CFG_STATUS_GOOD : S2S_CFG_STATUS_ERR,
|
|
|
- resultCode
|
|
|
- };
|
|
|
- hidPacket_send(response, sizeof(response));
|
|
|
+ int resultCode = scsiSelfTest();
|
|
|
+ uint8_t response[] =
|
|
|
+ {
|
|
|
+ resultCode == 0 ? S2S_CFG_STATUS_GOOD : S2S_CFG_STATUS_ERR,
|
|
|
+ resultCode
|
|
|
+ };
|
|
|
+ hidPacket_send(response, sizeof(response));
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
scsiDevInfoCommand()
|
|
|
{
|
|
|
- uint8_t response[] =
|
|
|
- {
|
|
|
- FIRMWARE_VERSION >> 8,
|
|
|
- FIRMWARE_VERSION & 0xff,
|
|
|
- sdDev.capacity >> 24,
|
|
|
- sdDev.capacity >> 16,
|
|
|
- sdDev.capacity >> 8,
|
|
|
- sdDev.capacity,
|
|
|
- 1 // useSdConfig, always true for V6.
|
|
|
- };
|
|
|
- hidPacket_send(response, sizeof(response));
|
|
|
+ uint8_t response[] =
|
|
|
+ {
|
|
|
+ FIRMWARE_VERSION >> 8,
|
|
|
+ FIRMWARE_VERSION & 0xff,
|
|
|
+ sdDev.capacity >> 24,
|
|
|
+ sdDev.capacity >> 16,
|
|
|
+ sdDev.capacity >> 8,
|
|
|
+ sdDev.capacity,
|
|
|
+ 1 // useSdConfig, always true for V6.
|
|
|
+ };
|
|
|
+ hidPacket_send(response, sizeof(response));
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
debugCommand()
|
|
|
{
|
|
|
- uint8_t response[32];
|
|
|
- memcpy(&response, &scsiDev.cdb, 12);
|
|
|
- response[12] = scsiDev.msgIn;
|
|
|
- response[13] = scsiDev.msgOut;
|
|
|
- response[14] = scsiDev.lastStatus;
|
|
|
- response[15] = scsiDev.lastSense;
|
|
|
- response[16] = scsiDev.phase;
|
|
|
- response[17] = *SCSI_STS_SCSI;
|
|
|
- response[18] = scsiDev.target != NULL ? scsiDev.target->syncOffset : 0;
|
|
|
- response[19] = scsiDev.target != NULL ? scsiDev.target->syncPeriod : 0;
|
|
|
- response[20] = scsiDev.minSyncPeriod;
|
|
|
- response[21] = scsiDev.rstCount;
|
|
|
- response[22] = scsiDev.selCount;
|
|
|
- response[23] = scsiDev.msgCount;
|
|
|
- response[24] = scsiDev.cmdCount;
|
|
|
- response[25] = scsiDev.watchdogTick;
|
|
|
- response[26] = blockDev.state;
|
|
|
- response[27] = scsiDev.lastSenseASC >> 8;
|
|
|
- response[28] = scsiDev.lastSenseASC;
|
|
|
- response[29] = *SCSI_STS_DBX & 0xff; // What we've read
|
|
|
- response[30] = *SCSI_STS_SELECTED;
|
|
|
- response[31] = *SCSI_STS_DBX >> 8; // What we're writing
|
|
|
- hidPacket_send(response, sizeof(response));
|
|
|
+ uint8_t response[32];
|
|
|
+ memcpy(&response, &scsiDev.cdb, 12);
|
|
|
+ response[12] = scsiDev.msgIn;
|
|
|
+ response[13] = scsiDev.msgOut;
|
|
|
+ response[14] = scsiDev.lastStatus;
|
|
|
+ response[15] = scsiDev.lastSense;
|
|
|
+ response[16] = scsiDev.phase;
|
|
|
+ response[17] = *SCSI_STS_SCSI;
|
|
|
+ response[18] = scsiDev.target != NULL ? scsiDev.target->syncOffset : 0;
|
|
|
+ response[19] = scsiDev.target != NULL ? scsiDev.target->syncPeriod : 0;
|
|
|
+ response[20] = scsiDev.minSyncPeriod;
|
|
|
+ response[21] = scsiDev.rstCount;
|
|
|
+ response[22] = scsiDev.selCount;
|
|
|
+ response[23] = scsiDev.msgCount;
|
|
|
+ response[24] = scsiDev.cmdCount;
|
|
|
+ response[25] = scsiDev.watchdogTick;
|
|
|
+ response[26] = blockDev.state;
|
|
|
+ response[27] = scsiDev.lastSenseASC >> 8;
|
|
|
+ response[28] = scsiDev.lastSenseASC;
|
|
|
+ response[29] = *SCSI_STS_DBX & 0xff; // What we've read
|
|
|
+ response[30] = *SCSI_STS_SELECTED;
|
|
|
+ response[31] = *SCSI_STS_DBX >> 8; // What we're writing
|
|
|
+ hidPacket_send(response, sizeof(response));
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
sdWriteCommand(const uint8_t* cmd, size_t cmdSize)
|
|
|
{
|
|
|
- if (cmdSize < 517)
|
|
|
- {
|
|
|
- return; // ignore.
|
|
|
- }
|
|
|
- uint32_t lba =
|
|
|
- (((uint32_t)cmd[1]) << 24) |
|
|
|
- (((uint32_t)cmd[2]) << 16) |
|
|
|
- (((uint32_t)cmd[3]) << 8) |
|
|
|
- ((uint32_t)cmd[4]);
|
|
|
-
|
|
|
- memcpy(configDmaBuf, &cmd[5], 512);
|
|
|
- BSP_SD_WriteBlocks_DMA(configDmaBuf, lba, 1);
|
|
|
-
|
|
|
- uint8_t response[] =
|
|
|
- {
|
|
|
- S2S_CFG_STATUS_GOOD
|
|
|
- };
|
|
|
- hidPacket_send(response, sizeof(response));
|
|
|
+ if (cmdSize < 517)
|
|
|
+ {
|
|
|
+ return; // ignore.
|
|
|
+ }
|
|
|
+ uint32_t lba =
|
|
|
+ (((uint32_t)cmd[1]) << 24) |
|
|
|
+ (((uint32_t)cmd[2]) << 16) |
|
|
|
+ (((uint32_t)cmd[3]) << 8) |
|
|
|
+ ((uint32_t)cmd[4]);
|
|
|
+
|
|
|
+ memcpy(configDmaBuf, &cmd[5], 512);
|
|
|
+ BSP_SD_WriteBlocks_DMA(configDmaBuf, lba, 1);
|
|
|
+
|
|
|
+ uint8_t response[] =
|
|
|
+ {
|
|
|
+ S2S_CFG_STATUS_GOOD
|
|
|
+ };
|
|
|
+ hidPacket_send(response, sizeof(response));
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
sdReadCommand(const uint8_t* cmd, size_t cmdSize)
|
|
|
{
|
|
|
- if (cmdSize < 5)
|
|
|
- {
|
|
|
- return; // ignore.
|
|
|
- }
|
|
|
- uint32_t lba =
|
|
|
- (((uint32_t)cmd[1]) << 24) |
|
|
|
- (((uint32_t)cmd[2]) << 16) |
|
|
|
- (((uint32_t)cmd[3]) << 8) |
|
|
|
- ((uint32_t)cmd[4]);
|
|
|
-
|
|
|
- BSP_SD_ReadBlocks_DMA(configDmaBuf, lba, 1);
|
|
|
- hidPacket_send(configDmaBuf, 512);
|
|
|
+ if (cmdSize < 5)
|
|
|
+ {
|
|
|
+ return; // ignore.
|
|
|
+ }
|
|
|
+ uint32_t lba =
|
|
|
+ (((uint32_t)cmd[1]) << 24) |
|
|
|
+ (((uint32_t)cmd[2]) << 16) |
|
|
|
+ (((uint32_t)cmd[3]) << 8) |
|
|
|
+ ((uint32_t)cmd[4]);
|
|
|
+
|
|
|
+ BSP_SD_ReadBlocks_DMA(configDmaBuf, lba, 1);
|
|
|
+ hidPacket_send(configDmaBuf, 512);
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
processCommand(const uint8_t* cmd, size_t cmdSize)
|
|
|
{
|
|
|
- switch (cmd[0])
|
|
|
- {
|
|
|
- case S2S_CMD_PING:
|
|
|
- pingCommand();
|
|
|
- break;
|
|
|
-
|
|
|
- case S2S_CMD_REBOOT:
|
|
|
- s2s_enterBootloader();
|
|
|
- break;
|
|
|
-
|
|
|
- case S2S_CMD_SDINFO:
|
|
|
- sdInfoCommand();
|
|
|
- break;
|
|
|
-
|
|
|
- case S2S_CMD_SCSITEST:
|
|
|
- scsiTestCommand();
|
|
|
- break;
|
|
|
-
|
|
|
- case S2S_CMD_DEVINFO:
|
|
|
- scsiDevInfoCommand();
|
|
|
- break;
|
|
|
-
|
|
|
- case S2S_CMD_SD_WRITE:
|
|
|
- sdWriteCommand(cmd, cmdSize);
|
|
|
- break;
|
|
|
-
|
|
|
- case S2S_CMD_SD_READ:
|
|
|
- sdReadCommand(cmd, cmdSize);
|
|
|
- break;
|
|
|
-
|
|
|
- case S2S_CMD_DEBUG:
|
|
|
- if (debugTimerStarted == 0) {
|
|
|
- debugInit();
|
|
|
- }
|
|
|
- debugCommand();
|
|
|
- break;
|
|
|
-
|
|
|
- case S2S_CMD_NONE: // invalid
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
+ switch (cmd[0])
|
|
|
+ {
|
|
|
+ case S2S_CMD_PING:
|
|
|
+ pingCommand();
|
|
|
+ break;
|
|
|
+
|
|
|
+ case S2S_CMD_REBOOT:
|
|
|
+ s2s_enterBootloader();
|
|
|
+ break;
|
|
|
+
|
|
|
+ case S2S_CMD_SDINFO:
|
|
|
+ sdInfoCommand();
|
|
|
+ break;
|
|
|
+
|
|
|
+ case S2S_CMD_SCSITEST:
|
|
|
+ scsiTestCommand();
|
|
|
+ break;
|
|
|
+
|
|
|
+ case S2S_CMD_DEVINFO:
|
|
|
+ scsiDevInfoCommand();
|
|
|
+ break;
|
|
|
+
|
|
|
+ case S2S_CMD_SD_WRITE:
|
|
|
+ sdWriteCommand(cmd, cmdSize);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case S2S_CMD_SD_READ:
|
|
|
+ sdReadCommand(cmd, cmdSize);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case S2S_CMD_DEBUG:
|
|
|
+ if (debugTimerStarted == 0) {
|
|
|
+ debugInit();
|
|
|
+ debugCommand();
|
|
|
+ }
|
|
|
+ // Always triggered from timer for consistent behaviour
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case S2S_CMD_NONE: // invalid
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void s2s_configPoll()
|
|
|
{
|
|
|
- s2s_spin_lock(&usbDevLock);
|
|
|
-
|
|
|
- if (!USBD_Composite_IsConfigured(&configUsbDev))
|
|
|
- {
|
|
|
- usbInEpState = USB_IDLE;
|
|
|
- hidPacket_reset();
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- if (USBD_HID_IsReportReady(&configUsbDev))
|
|
|
- {
|
|
|
- // Check if we have a previous command outstanding
|
|
|
- // before accepting another
|
|
|
- size_t cmdSize;
|
|
|
- if (hidPacket_peekPacket(&cmdSize) == NULL)
|
|
|
- {
|
|
|
- uint8_t hidBuffer[USBHID_LEN];
|
|
|
- int byteCount = USBD_HID_GetReport(&configUsbDev, hidBuffer, sizeof(hidBuffer));
|
|
|
- hidPacket_recv(hidBuffer, byteCount);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (hidPacket_getHIDBytesReady() == 0) // Nothing queued to send
|
|
|
- {
|
|
|
- size_t cmdSize;
|
|
|
- const uint8_t* cmd = hidPacket_getPacket(&cmdSize);
|
|
|
- if (cmd && (cmdSize > 0))
|
|
|
- {
|
|
|
- s2s_ledOn();
|
|
|
- processCommand(cmd, cmdSize);
|
|
|
- s2s_ledOff();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- switch (usbInEpState)
|
|
|
- {
|
|
|
- case USB_IDLE:
|
|
|
- {
|
|
|
- uint8_t hidBuffer[USBHID_LEN];
|
|
|
- const uint8_t* nextChunk = hidPacket_getHIDBytes(hidBuffer);
|
|
|
-
|
|
|
- if (nextChunk)
|
|
|
- {
|
|
|
- USBD_HID_SendReport (&configUsbDev, nextChunk, sizeof(hidBuffer));
|
|
|
- usbInEpState = USB_DATA_SENT;
|
|
|
- }
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- case USB_DATA_SENT:
|
|
|
- if (!USBD_HID_IsBusy(&configUsbDev))
|
|
|
- {
|
|
|
- // Data accepted.
|
|
|
- usbInEpState = USB_IDLE;
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
+ s2s_spin_lock(&usbDevLock);
|
|
|
+
|
|
|
+ if (!USBD_Composite_IsConfigured(&configUsbDev))
|
|
|
+ {
|
|
|
+ usbInEpState = USB_IDLE;
|
|
|
+ hidPacket_reset();
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (USBD_HID_IsReportReady(&configUsbDev))
|
|
|
+ {
|
|
|
+ // Check if we have a previous command outstanding
|
|
|
+ // before accepting another
|
|
|
+ size_t cmdSize;
|
|
|
+ if (hidPacket_peekPacket(&cmdSize) == NULL)
|
|
|
+ {
|
|
|
+ uint8_t hidBuffer[USBHID_LEN];
|
|
|
+ int byteCount = USBD_HID_GetReport(&configUsbDev, hidBuffer, sizeof(hidBuffer));
|
|
|
+ hidPacket_recv(hidBuffer, byteCount);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (hidPacket_getHIDBytesReady() == 0) // Nothing queued to send
|
|
|
+ {
|
|
|
+ size_t cmdSize;
|
|
|
+ const uint8_t* cmd = hidPacket_peekPacket(&cmdSize);
|
|
|
+ if (cmd && (cmdSize > 0))
|
|
|
+ {
|
|
|
+ if (!debugTimerStarted || (cmd[0] != S2S_CMD_DEBUG))
|
|
|
+ {
|
|
|
+ hidPacket_getPacket(&cmdSize);
|
|
|
+ s2s_ledOn();
|
|
|
+ processCommand(cmd, cmdSize);
|
|
|
+ s2s_ledOff();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (usbInEpState)
|
|
|
+ {
|
|
|
+ case USB_IDLE:
|
|
|
+ {
|
|
|
+ uint8_t hidBuffer[USBHID_LEN];
|
|
|
+ const uint8_t* nextChunk = hidPacket_getHIDBytes(hidBuffer);
|
|
|
+
|
|
|
+ if (nextChunk)
|
|
|
+ {
|
|
|
+ USBD_HID_SendReport (&configUsbDev, nextChunk, sizeof(hidBuffer));
|
|
|
+ usbInEpState = USB_DATA_SENT;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case USB_DATA_SENT:
|
|
|
+ if (!USBD_HID_IsBusy(&configUsbDev))
|
|
|
+ {
|
|
|
+ // Data accepted.
|
|
|
+ usbInEpState = USB_IDLE;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
out:
|
|
|
- s2s_spin_unlock(&usbDevLock);
|
|
|
+ s2s_spin_unlock(&usbDevLock);
|
|
|
}
|
|
|
|
|
|
void s2s_debugTimer()
|
|
|
{
|
|
|
- if (!USBD_Composite_IsConfigured(&configUsbDev))
|
|
|
- {
|
|
|
- usbInEpState = USB_IDLE;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (USBD_HID_IsReportReady(&configUsbDev))
|
|
|
- {
|
|
|
- // Check if we have a previous command outstanding
|
|
|
- // before accepting another
|
|
|
- size_t cmdSize;
|
|
|
- if (hidPacket_peekPacket(&cmdSize) == NULL)
|
|
|
- {
|
|
|
- uint8_t hidBuffer[USBHID_LEN];
|
|
|
- int byteCount = USBD_HID_GetReport(&configUsbDev, hidBuffer, sizeof(hidBuffer));
|
|
|
- hidPacket_recv(hidBuffer, byteCount);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (hidPacket_getHIDBytesReady() == 0) // Nothing queued to send
|
|
|
- {
|
|
|
- size_t cmdSize;
|
|
|
- const uint8_t* cmd = hidPacket_peekPacket(&cmdSize);
|
|
|
- // This is called from an ISR, only process simple commands.
|
|
|
- if (cmd && (cmdSize > 0))
|
|
|
- {
|
|
|
- if (cmd[0] == S2S_CMD_DEBUG)
|
|
|
- {
|
|
|
- hidPacket_getPacket(&cmdSize);
|
|
|
- debugCommand();
|
|
|
- }
|
|
|
- else if (cmd[0] == S2S_CMD_PING)
|
|
|
- {
|
|
|
- hidPacket_getPacket(&cmdSize);
|
|
|
- pingCommand();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- switch (usbInEpState)
|
|
|
- {
|
|
|
- case USB_IDLE:
|
|
|
- {
|
|
|
- uint8_t hidBuffer[USBHID_LEN];
|
|
|
- const uint8_t* nextChunk = hidPacket_getHIDBytes(hidBuffer);
|
|
|
-
|
|
|
- if (nextChunk)
|
|
|
- {
|
|
|
- USBD_HID_SendReport (&configUsbDev, nextChunk, sizeof(hidBuffer));
|
|
|
- usbInEpState = USB_DATA_SENT;
|
|
|
- }
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- case USB_DATA_SENT:
|
|
|
- if (!USBD_HID_IsBusy(&configUsbDev))
|
|
|
- {
|
|
|
- // Data accepted.
|
|
|
- usbInEpState = USB_IDLE;
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
+ if (!USBD_Composite_IsConfigured(&configUsbDev))
|
|
|
+ {
|
|
|
+ usbInEpState = USB_IDLE;
|
|
|
+ hidPacket_reset();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (USBD_HID_IsReportReady(&configUsbDev))
|
|
|
+ {
|
|
|
+ // Check if we have a previous command outstanding
|
|
|
+ // before accepting another
|
|
|
+ size_t cmdSize;
|
|
|
+ if (hidPacket_peekPacket(&cmdSize) == NULL)
|
|
|
+ {
|
|
|
+ uint8_t hidBuffer[USBHID_LEN];
|
|
|
+ int byteCount = USBD_HID_GetReport(&configUsbDev, hidBuffer, sizeof(hidBuffer));
|
|
|
+ hidPacket_recv(hidBuffer, byteCount);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (hidPacket_getHIDBytesReady() == 0) // Nothing queued to send
|
|
|
+ {
|
|
|
+ size_t cmdSize;
|
|
|
+ const uint8_t* cmd = hidPacket_peekPacket(&cmdSize);
|
|
|
+ // This is called from an ISR, only process simple commands.
|
|
|
+ if (cmd && (cmdSize > 0))
|
|
|
+ {
|
|
|
+ if (cmd[0] == S2S_CMD_DEBUG)
|
|
|
+ {
|
|
|
+ hidPacket_getPacket(&cmdSize);
|
|
|
+ debugCommand();
|
|
|
+ }
|
|
|
+ else if (cmd[0] == S2S_CMD_PING)
|
|
|
+ {
|
|
|
+ hidPacket_getPacket(&cmdSize);
|
|
|
+ pingCommand();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (usbInEpState)
|
|
|
+ {
|
|
|
+ case USB_IDLE:
|
|
|
+ {
|
|
|
+ uint8_t hidBuffer[USBHID_LEN];
|
|
|
+ const uint8_t* nextChunk = hidPacket_getHIDBytes(hidBuffer);
|
|
|
+
|
|
|
+ if (nextChunk)
|
|
|
+ {
|
|
|
+ USBD_HID_SendReport (&configUsbDev, nextChunk, sizeof(hidBuffer));
|
|
|
+ usbInEpState = USB_DATA_SENT;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case USB_DATA_SENT:
|
|
|
+ if (!USBD_HID_IsBusy(&configUsbDev))
|
|
|
+ {
|
|
|
+ // Data accepted.
|
|
|
+ usbInEpState = USB_IDLE;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
// Public method for storing MODE SELECT results.
|
|
|
void s2s_configSave(int scsiId, uint16_t bytesPerSector)
|
|
|
{
|
|
|
- S2S_TargetCfg* cfg = (S2S_TargetCfg*) s2s_getConfigById(scsiId);
|
|
|
- cfg->bytesPerSector = bytesPerSector;
|
|
|
+ S2S_TargetCfg* cfg = (S2S_TargetCfg*) s2s_getConfigById(scsiId);
|
|
|
+ cfg->bytesPerSector = bytesPerSector;
|
|
|
|
|
|
- BSP_SD_WriteBlocks_DMA(
|
|
|
- &s2s_cfg[0],
|
|
|
- sdDev.capacity - S2S_CFG_SIZE,
|
|
|
- (S2S_CFG_SIZE + 511) / 512);
|
|
|
+ BSP_SD_WriteBlocks_DMA(
|
|
|
+ &s2s_cfg[0],
|
|
|
+ sdDev.capacity - S2S_CFG_SIZE,
|
|
|
+ (S2S_CFG_SIZE + 511) / 512);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
const S2S_TargetCfg* s2s_getConfigByIndex(int i)
|
|
|
{
|
|
|
- return (const S2S_TargetCfg*)
|
|
|
- (s2s_cfg + sizeof(S2S_BoardCfg) + (i * sizeof(S2S_TargetCfg)));
|
|
|
+ return (const S2S_TargetCfg*)
|
|
|
+ (s2s_cfg + sizeof(S2S_BoardCfg) + (i * sizeof(S2S_TargetCfg)));
|
|
|
}
|
|
|
|
|
|
const S2S_TargetCfg* s2s_getConfigById(int scsiId)
|
|
|
{
|
|
|
- int i;
|
|
|
- for (i = 0; i < S2S_MAX_TARGETS; ++i)
|
|
|
- {
|
|
|
- const S2S_TargetCfg* tgt = s2s_getConfigByIndex(i);
|
|
|
- if ((tgt->scsiId & S2S_CFG_TARGET_ID_BITS) == scsiId)
|
|
|
- {
|
|
|
- return tgt;
|
|
|
- }
|
|
|
- }
|
|
|
- return NULL;
|
|
|
-
|
|
|
+ int i;
|
|
|
+ for (i = 0; i < S2S_MAX_TARGETS; ++i)
|
|
|
+ {
|
|
|
+ const S2S_TargetCfg* tgt = s2s_getConfigByIndex(i);
|
|
|
+ if ((tgt->scsiId & S2S_CFG_TARGET_ID_BITS) == scsiId)
|
|
|
+ {
|
|
|
+ return tgt;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return NULL;
|
|
|
}
|
|
|
|