SCSI2SD_HID.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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. while (hidInfo)
  32. {
  33. if (hidInfo->interface_number == CONFIG_INTERFACE)
  34. {
  35. myConfigHandle = hid_open_path(hidInfo->path);
  36. }
  37. else if (hidInfo->interface_number == DEBUG_INTERFACE)
  38. {
  39. myDebugHandle = hid_open_path(hidInfo->path);
  40. readDebugData();
  41. }
  42. hidInfo = hidInfo->next;
  43. }
  44. }
  45. HID::~HID()
  46. {
  47. if (myConfigHandle)
  48. {
  49. hid_close(myConfigHandle);
  50. }
  51. if (myDebugHandle)
  52. {
  53. hid_close(myDebugHandle);
  54. }
  55. hid_free_enumeration(myHidInfo);
  56. }
  57. HID*
  58. HID::Open()
  59. {
  60. hid_device_info* dev = hid_enumerate(VENDOR_ID, PRODUCT_ID);
  61. if (dev)
  62. {
  63. return new HID(dev);
  64. }
  65. else
  66. {
  67. return NULL;
  68. }
  69. }
  70. void
  71. HID::enterBootloader()
  72. {
  73. // Reboot commands added in firmware 3.5
  74. if (!myDebugHandle)
  75. {
  76. throw std::runtime_error(
  77. "Cannot enter SCSI2SD bootloader: debug interface not found");
  78. }
  79. else if (myFirmwareVersion == 0)
  80. {
  81. throw std::runtime_error(
  82. "Cannot enter SCSI2SD bootloader: old firmware version running.\n"
  83. "The SCSI2SD board cannot reset itself. Please disconnect and \n"
  84. "reconnect the USB cable.\n");
  85. }
  86. else
  87. {
  88. uint8_t hidBuf[HID_PACKET_SIZE + 1] =
  89. {
  90. 0x00, // Report ID;
  91. 0x01 // Reboot command
  92. // 63 bytes unused.
  93. };
  94. int result = hid_write(myDebugHandle, hidBuf, sizeof(hidBuf));
  95. if (result < 0)
  96. {
  97. const wchar_t* err = hid_error(myDebugHandle);
  98. std::stringstream ss;
  99. ss << "USB HID write failure: " << err;
  100. throw std::runtime_error(ss.str());
  101. }
  102. }
  103. }
  104. void
  105. HID::readConfig(uint8_t* buffer, size_t len)
  106. {
  107. assert(len >= 0);
  108. buffer[0] = 0; // report id
  109. int result = hid_read(myConfigHandle, buffer, len);
  110. if (result < 0)
  111. {
  112. const wchar_t* err = hid_error(myConfigHandle);
  113. std::stringstream ss;
  114. ss << "USB HID read failure: " << err;
  115. throw std::runtime_error(ss.str());
  116. }
  117. }
  118. void
  119. HID::saveConfig(uint8_t* buffer, size_t len)
  120. {
  121. assert(len >= 0 && len <= HID_PACKET_SIZE);
  122. uint8_t hidBuf[HID_PACKET_SIZE + 1] =
  123. {
  124. 0x00, // Report ID;
  125. };
  126. memcpy(&hidBuf[1], buffer, len);
  127. int result = hid_write(myConfigHandle, hidBuf, len + 1);
  128. if (result < 0)
  129. {
  130. const wchar_t* err = hid_error(myConfigHandle);
  131. std::stringstream ss;
  132. ss << "USB HID write failure: " << err;
  133. throw std::runtime_error(ss.str());
  134. }
  135. }
  136. void
  137. HID::readDebugData()
  138. {
  139. uint8_t buf[HID_PACKET_SIZE];
  140. buf[0] = 0; // report id
  141. int result = hid_read(myDebugHandle, buf, HID_PACKET_SIZE);
  142. if (result < 0)
  143. {
  144. const wchar_t* err = hid_error(myDebugHandle);
  145. std::stringstream ss;
  146. ss << "USB HID read failure: " << err;
  147. throw std::runtime_error(ss.str());
  148. }
  149. myFirmwareVersion = (((uint16_t)buf[62]) << 8) | buf[63];
  150. mySDCapacity =
  151. (((uint32_t)buf[58]) << 24) |
  152. (((uint32_t)buf[59]) << 16) |
  153. (((uint32_t)buf[60]) << 8) |
  154. ((uint32_t)buf[61]);
  155. }
  156. std::string
  157. HID::getFirmwareVersionStr() const
  158. {
  159. if (myFirmwareVersion == 0)
  160. {
  161. return "Unknown (3.0 - 3.4)";
  162. }
  163. else
  164. {
  165. std::stringstream ver;
  166. ver << std::hex <<
  167. (myFirmwareVersion >> 8) <<
  168. '.' << (myFirmwareVersion & 0xFF);
  169. return ver.str();
  170. }
  171. }