config.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
  2. //
  3. // This file is part of SCSI2SD.
  4. //
  5. // SCSI2SD is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // SCSI2SD is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
  17. #include "device.h"
  18. #include "config.h"
  19. #include "USBFS.h"
  20. #include "led.h"
  21. #include <string.h>
  22. // CYDEV_EEPROM_ROW_SIZE == 16.
  23. static char magic[CYDEV_EEPROM_ROW_SIZE] = "codesrc_00000001";
  24. // Config shadow RAM (copy of EEPROM)
  25. static Config shadow =
  26. {
  27. 0, // SCSI ID
  28. " codesrc", // vendor (68k Apple Drive Setup: Set to " SEAGATE")
  29. " SCSI2SD", //prodId (68k Apple Drive Setup: Set to " ST225N")
  30. "2.0a", // revision (68k Apple Drive Setup: Set to "1.0 ")
  31. 1, // enable parity
  32. 0, // disable unit attention,
  33. 0 // Max blocks (0 == disabled)
  34. // reserved bytes will be initialised to 0.
  35. };
  36. enum USB_ENDPOINTS
  37. {
  38. USB_EP_OUT = 1,
  39. USB_EP_IN = 2
  40. };
  41. enum USB_STATE
  42. {
  43. USB_IDLE,
  44. USB_DATA_SENT
  45. };
  46. int usbInEpState;
  47. int usbReady;
  48. // Global
  49. Config* config = NULL;
  50. // The PSoC 5LP compile to little-endian format.
  51. static uint32_t ntohl(uint32_t val)
  52. {
  53. return
  54. ((val & 0xFF) << 24) |
  55. ((val & 0xFF00) << 8) |
  56. ((val >> 8) & 0xFF00) |
  57. ((val >> 24) & 0xFF);
  58. }
  59. static uint32_t htonl(uint32_t val)
  60. {
  61. return
  62. ((val & 0xFF) << 24) |
  63. ((val & 0xFF00) << 8) |
  64. ((val >> 8) & 0xFF00) |
  65. ((val >> 24) & 0xFF);
  66. }
  67. static void saveConfig()
  68. {
  69. int shadowRows = (sizeof(shadow) / CYDEV_EEPROM_ROW_SIZE) + 1;
  70. int row;
  71. int status = CYRET_SUCCESS;
  72. CySetTemp();
  73. for (row = 0; (row < shadowRows) && (status == CYRET_SUCCESS); ++row)
  74. {
  75. CFG_EEPROM_Write(((uint8*)&shadow) + (row * CYDEV_EEPROM_ROW_SIZE), row);
  76. }
  77. if (status == CYRET_SUCCESS)
  78. {
  79. CFG_EEPROM_Write((uint8*)magic, row);
  80. }
  81. }
  82. void configInit()
  83. {
  84. int shadowRows, shadowBytes;
  85. uint8* eeprom = (uint8*)CYDEV_EE_BASE;
  86. // We could map cfgPtr directly into the EEPROM memory,
  87. // but that would waste power. Copy it to RAM then turn off
  88. // the EEPROM.
  89. CFG_EEPROM_Start();
  90. CyDelayUs(5); // 5us to start per datasheet.
  91. // Check magic
  92. shadowRows = (sizeof(shadow) / CYDEV_EEPROM_ROW_SIZE) + 1;
  93. shadowBytes = CYDEV_EEPROM_ROW_SIZE * shadowRows;
  94. if (memcmp(eeprom + shadowBytes, magic, sizeof(magic)))
  95. {
  96. saveConfig();
  97. }
  98. else
  99. {
  100. memcpy(&shadow, eeprom, sizeof(shadow));
  101. }
  102. config = &shadow;
  103. CFG_EEPROM_Stop();
  104. // The USB block will be powered by an internal 3.3V regulator.
  105. // The PSoC must be operating between 4.6V and 5V for the regulator
  106. // to work.
  107. USBFS_Start(0, USBFS_5V_OPERATION);
  108. usbInEpState = USB_IDLE;
  109. usbReady = 0; // We don't know if host is connected yet.
  110. }
  111. void configPoll()
  112. {
  113. int reset = 0;
  114. if (!usbReady || USBFS_IsConfigurationChanged())
  115. {
  116. reset = 1;
  117. }
  118. usbReady = USBFS_bGetConfiguration();
  119. if (!usbReady)
  120. {
  121. return;
  122. }
  123. if (reset)
  124. {
  125. USBFS_EnableOutEP(USB_EP_OUT);
  126. usbInEpState = USB_IDLE;
  127. }
  128. if(USBFS_GetEPState(USB_EP_OUT) == USBFS_OUT_BUFFER_FULL)
  129. {
  130. int byteCount;
  131. ledOn();
  132. // The host sent us some data!
  133. byteCount = USBFS_GetEPCount(USB_EP_OUT);
  134. // Assume that byteCount <= sizeof(shadow).
  135. // shadow should be padded out to 64bytes, which is the largest
  136. // possible HID transfer.
  137. USBFS_ReadOutEP(USB_EP_OUT, (uint8 *)&shadow, byteCount);
  138. shadow.maxBlocks = htonl(shadow.maxBlocks);
  139. CFG_EEPROM_Start();
  140. saveConfig(); // write to eeprom
  141. CFG_EEPROM_Stop();
  142. // Send the updated data.
  143. usbInEpState = USB_IDLE;
  144. // Allow the host to send us another updated config.
  145. USBFS_EnableOutEP(USB_EP_OUT);
  146. ledOff();
  147. }
  148. switch (usbInEpState)
  149. {
  150. case USB_IDLE:
  151. shadow.maxBlocks = htonl(shadow.maxBlocks);
  152. USBFS_LoadInEP(USB_EP_IN, (uint8 *)&shadow, sizeof(shadow));
  153. shadow.maxBlocks = ntohl(shadow.maxBlocks);
  154. usbInEpState = USB_DATA_SENT;
  155. break;
  156. case USB_DATA_SENT:
  157. if (USBFS_bGetEPAckState(USB_EP_IN))
  158. {
  159. // Data accepted.
  160. usbInEpState = USB_IDLE;
  161. }
  162. break;
  163. }
  164. }