SCSI2SD_HID.cc 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. // Copyright (C) 2014 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 "SCSI2SD_HID.hh"
  18. #include <cassert>
  19. #include <stdexcept>
  20. #include <sstream>
  21. #include <iostream>
  22. #include <string.h> // memcpy
  23. using namespace SCSI2SD;
  24. HID::HID(hid_device_info* hidInfo) :
  25. myHidInfo(hidInfo),
  26. myConfigHandle(NULL),
  27. myDebugHandle(NULL),
  28. myFirmwareVersion(0),
  29. mySDCapacity(0)
  30. {
  31. // hidInfo->interface_number not supported on mac, and interfaces
  32. // are enumerated in a random order. :-(
  33. // We rely on the watchdog value of the debug interface changing on each
  34. // read to differentiate the interfaces.
  35. while (hidInfo && !(myConfigHandle && myDebugHandle))
  36. {
  37. if (hidInfo->interface_number == CONFIG_INTERFACE)
  38. {
  39. myConfigHandle = hid_open_path(hidInfo->path);
  40. hidInfo = hidInfo->next;
  41. }
  42. else if (hidInfo->interface_number == DEBUG_INTERFACE)
  43. {
  44. myDebugHandle = hid_open_path(hidInfo->path);
  45. readDebugData();
  46. hidInfo = hidInfo->next;
  47. }
  48. else if (hidInfo->interface_number == -1)
  49. {
  50. // hidInfo->interface_number not supported on mac, and
  51. // interfaces are enumerated in a random order. :-(
  52. // We rely on the watchdog value of the debug interface
  53. // changing on each read to differentiate the interfaces.
  54. hid_device* dev = hid_open_path(hidInfo->path);
  55. if (!dev)
  56. {
  57. hidInfo = hidInfo->next;
  58. continue;
  59. }
  60. uint8_t buf[HID_PACKET_SIZE];
  61. int watchVal = -1;
  62. int configIntFound = 1;
  63. for (int i = 0; i < 4; ++i)
  64. {
  65. buf[0] = 0; // report id
  66. hid_read(dev, buf, HID_PACKET_SIZE);
  67. if (watchVal == -1) watchVal = buf[25];
  68. configIntFound = configIntFound && (buf[25] == watchVal);
  69. }
  70. if (configIntFound)
  71. {
  72. myConfigHandle = dev;
  73. }
  74. else
  75. {
  76. myDebugHandle = dev;
  77. readDebugData();
  78. }
  79. }
  80. }
  81. }
  82. HID::~HID()
  83. {
  84. if (myConfigHandle)
  85. {
  86. hid_close(myConfigHandle);
  87. }
  88. if (myDebugHandle)
  89. {
  90. hid_close(myDebugHandle);
  91. }
  92. hid_free_enumeration(myHidInfo);
  93. }
  94. HID*
  95. HID::Open()
  96. {
  97. hid_device_info* dev = hid_enumerate(VENDOR_ID, PRODUCT_ID);
  98. if (dev)
  99. {
  100. return new HID(dev);
  101. }
  102. else
  103. {
  104. return NULL;
  105. }
  106. }
  107. void
  108. HID::enterBootloader()
  109. {
  110. // Reboot commands added in firmware 3.5
  111. if (!myDebugHandle)
  112. {
  113. throw std::runtime_error(
  114. "Cannot enter SCSI2SD bootloader: debug interface not found");
  115. }
  116. else if (myFirmwareVersion == 0)
  117. {
  118. throw std::runtime_error(
  119. "Cannot enter SCSI2SD bootloader: old firmware version running.\n"
  120. "The SCSI2SD board cannot reset itself. Please disconnect and \n"
  121. "reconnect the USB cable.\n");
  122. }
  123. else
  124. {
  125. uint8_t hidBuf[HID_PACKET_SIZE + 1] =
  126. {
  127. 0x00, // Report ID;
  128. 0x01 // Reboot command
  129. // 63 bytes unused.
  130. };
  131. int result = hid_write(myDebugHandle, hidBuf, sizeof(hidBuf));
  132. if (result < 0)
  133. {
  134. const wchar_t* err = hid_error(myDebugHandle);
  135. std::stringstream ss;
  136. ss << "USB HID write failure: " << err;
  137. throw std::runtime_error(ss.str());
  138. }
  139. }
  140. }
  141. void
  142. HID::readConfig(uint8_t* buffer, size_t len)
  143. {
  144. assert(len >= 0);
  145. buffer[0] = 0; // report id
  146. int result = hid_read(myConfigHandle, buffer, len);
  147. if (result < 0)
  148. {
  149. const wchar_t* err = hid_error(myConfigHandle);
  150. std::stringstream ss;
  151. ss << "USB HID read failure: " << err;
  152. throw std::runtime_error(ss.str());
  153. }
  154. }
  155. void
  156. HID::saveConfig(uint8_t* buffer, size_t len)
  157. {
  158. assert(len >= 0 && len <= HID_PACKET_SIZE);
  159. uint8_t hidBuf[HID_PACKET_SIZE + 1] =
  160. {
  161. 0x00, // Report ID;
  162. };
  163. memcpy(&hidBuf[1], buffer, len);
  164. int result = hid_write(myConfigHandle, hidBuf, len + 1);
  165. if (result < 0)
  166. {
  167. const wchar_t* err = hid_error(myConfigHandle);
  168. std::stringstream ss;
  169. ss << "USB HID write failure: " << err;
  170. throw std::runtime_error(ss.str());
  171. }
  172. }
  173. void
  174. HID::readDebugData()
  175. {
  176. uint8_t buf[HID_PACKET_SIZE];
  177. buf[0] = 0; // report id
  178. int result = hid_read(myDebugHandle, buf, HID_PACKET_SIZE);
  179. if (result < 0)
  180. {
  181. const wchar_t* err = hid_error(myDebugHandle);
  182. std::stringstream ss;
  183. ss << "USB HID read failure: " << err;
  184. throw std::runtime_error(ss.str());
  185. }
  186. myFirmwareVersion = (((uint16_t)buf[62]) << 8) | buf[63];
  187. mySDCapacity =
  188. (((uint32_t)buf[58]) << 24) |
  189. (((uint32_t)buf[59]) << 16) |
  190. (((uint32_t)buf[60]) << 8) |
  191. ((uint32_t)buf[61]);
  192. }
  193. std::string
  194. HID::getFirmwareVersionStr() const
  195. {
  196. if (myFirmwareVersion == 0)
  197. {
  198. return "Unknown (3.0 - 3.4)";
  199. }
  200. else
  201. {
  202. std::stringstream ver;
  203. ver << std::hex <<
  204. (myFirmwareVersion >> 8) <<
  205. '.' << (myFirmwareVersion & 0xFF);
  206. return ver.str();
  207. }
  208. }