| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- // Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
- //
- // 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 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/>.
- #include "device.h"
- #include "config.h"
- #include "USBFS.h"
- #include "led.h"
- #include <string.h>
- // CYDEV_EEPROM_ROW_SIZE == 16.
- static char magic[CYDEV_EEPROM_ROW_SIZE] = "codesrc_00000001";
- // Config shadow RAM (copy of EEPROM)
- static Config shadow =
- {
- 0, // SCSI ID
- " codesrc", // vendor (68k Apple Drive Setup: Set to " SEAGATE")
- " SCSI2SD", //prodId (68k Apple Drive Setup: Set to " ST225N")
- "2.0a", // revision (68k Apple Drive Setup: Set to "1.0 ")
- 1, // enable parity
- 0, // disable unit attention,
- 0 // Max blocks (0 == disabled)
- // reserved bytes will be initialised to 0.
- };
- enum USB_ENDPOINTS
- {
- USB_EP_OUT = 1,
- USB_EP_IN = 2
- };
- enum USB_STATE
- {
- USB_IDLE,
- USB_DATA_SENT
- };
- int usbInEpState;
- int usbReady;
- // Global
- Config* config = NULL;
- // The PSoC 5LP compile to little-endian format.
- static uint32_t ntohl(uint32_t val)
- {
- return
- ((val & 0xFF) << 24) |
- ((val & 0xFF00) << 8) |
- ((val >> 8) & 0xFF00) |
- ((val >> 24) & 0xFF);
- }
- static uint32_t htonl(uint32_t val)
- {
- return
- ((val & 0xFF) << 24) |
- ((val & 0xFF00) << 8) |
- ((val >> 8) & 0xFF00) |
- ((val >> 24) & 0xFF);
- }
- static void saveConfig()
- {
- int shadowRows = (sizeof(shadow) / CYDEV_EEPROM_ROW_SIZE) + 1;
- int row;
- int status = CYRET_SUCCESS;
- CySetTemp();
- for (row = 0; (row < shadowRows) && (status == CYRET_SUCCESS); ++row)
- {
- CFG_EEPROM_Write(((uint8*)&shadow) + (row * CYDEV_EEPROM_ROW_SIZE), row);
- }
- if (status == CYRET_SUCCESS)
- {
- CFG_EEPROM_Write((uint8*)magic, row);
- }
- }
- void configInit()
- {
- int shadowRows, shadowBytes;
- uint8* eeprom = (uint8*)CYDEV_EE_BASE;
-
- // We could map cfgPtr directly into the EEPROM memory,
- // but that would waste power. Copy it to RAM then turn off
- // the EEPROM.
- CFG_EEPROM_Start();
- CyDelayUs(5); // 5us to start per datasheet.
- // Check magic
- shadowRows = (sizeof(shadow) / CYDEV_EEPROM_ROW_SIZE) + 1;
- shadowBytes = CYDEV_EEPROM_ROW_SIZE * shadowRows;
- if (memcmp(eeprom + shadowBytes, magic, sizeof(magic)))
- {
- saveConfig();
- }
- else
- {
- memcpy(&shadow, eeprom, sizeof(shadow));
- }
- config = &shadow;
- CFG_EEPROM_Stop();
- // The USB block will be powered by an internal 3.3V regulator.
- // The PSoC must be operating between 4.6V and 5V for the regulator
- // to work.
- USBFS_Start(0, USBFS_5V_OPERATION);
- usbInEpState = USB_IDLE;
- usbReady = 0; // We don't know if host is connected yet.
- }
- void configPoll()
- {
- int reset = 0;
- if (!usbReady || USBFS_IsConfigurationChanged())
- {
- reset = 1;
- }
- usbReady = USBFS_bGetConfiguration();
- if (!usbReady)
- {
- return;
- }
-
- if (reset)
- {
- USBFS_EnableOutEP(USB_EP_OUT);
- usbInEpState = USB_IDLE;
- }
- if(USBFS_GetEPState(USB_EP_OUT) == USBFS_OUT_BUFFER_FULL)
- {
- int byteCount;
-
- ledOn();
-
- // The host sent us some data!
- byteCount = USBFS_GetEPCount(USB_EP_OUT);
- // Assume that byteCount <= sizeof(shadow).
- // shadow should be padded out to 64bytes, which is the largest
- // possible HID transfer.
- USBFS_ReadOutEP(USB_EP_OUT, (uint8 *)&shadow, byteCount);
- shadow.maxBlocks = htonl(shadow.maxBlocks);
- CFG_EEPROM_Start();
- saveConfig(); // write to eeprom
- CFG_EEPROM_Stop();
-
- // Send the updated data.
- usbInEpState = USB_IDLE;
- // Allow the host to send us another updated config.
- USBFS_EnableOutEP(USB_EP_OUT);
- ledOff();
- }
- switch (usbInEpState)
- {
- case USB_IDLE:
- shadow.maxBlocks = htonl(shadow.maxBlocks);
- USBFS_LoadInEP(USB_EP_IN, (uint8 *)&shadow, sizeof(shadow));
- shadow.maxBlocks = ntohl(shadow.maxBlocks);
- usbInEpState = USB_DATA_SENT;
- break;
- case USB_DATA_SENT:
- if (USBFS_bGetEPAckState(USB_EP_IN))
- {
- // Data accepted.
- usbInEpState = USB_IDLE;
- }
- break;
- }
- }
|