driver-cointerra.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * Copyright 2014 Luke Dashjr
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the Free
  6. * Software Foundation; either version 3 of the License, or (at your option)
  7. * any later version. See COPYING for more details.
  8. */
  9. #include "config.h"
  10. #include <stdint.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include "deviceapi.h"
  14. #include "logging.h"
  15. #include "lowlevel.h"
  16. #include "lowl-usb.h"
  17. #define COINTERRA_EP_R (LIBUSB_ENDPOINT_IN | 1)
  18. #define COINTERRA_EP_W (LIBUSB_ENDPOINT_OUT | 1)
  19. #define COINTERRA_USB_TIMEOUT 100
  20. #define COINTERRA_PACKET_SIZE 0x40
  21. #define COINTERRA_START_SEQ 0x5a,0x5a
  22. #define COINTERRA_MSG_SIZE (COINTERRA_PACKET_SIZE - sizeof(cointerra_startseq))
  23. BFG_REGISTER_DRIVER(cointerra_drv)
  24. enum cointerra_msg_type_out {
  25. CMTO_RESET = 1,
  26. CMTO_WORK = 2,
  27. CMTO_REQUEST = 4,
  28. CMTO_HWERR = 5,
  29. CMTO_LEDCTL = 6,
  30. CMTO_HASHRATE = 7,
  31. };
  32. enum cointerra_msg_type_in {
  33. CMTI_WORKREQ = 1,
  34. CMTI_MATCH = 2,
  35. CMTI_WORKDONE = 3,
  36. CMTI_STATUS = 4,
  37. CMTI_SETTINGS = 5,
  38. CMTI_INFO = 6,
  39. CMTI_LOGMSG = 7,
  40. CMTI_RESETDONE = 8,
  41. CMTI_ERRINFO = 0xa,
  42. };
  43. static const uint8_t cointerra_startseq[] = {COINTERRA_START_SEQ};
  44. static
  45. int cointerra_read_msg(uint8_t * const out_msgtype, uint8_t * const out, libusb_device_handle * const usbh, const char * const repr, const unsigned timeout)
  46. {
  47. uint8_t ss[] = {COINTERRA_START_SEQ};
  48. uint8_t buf[COINTERRA_PACKET_SIZE];
  49. int e, xfer;
  50. e = libusb_bulk_transfer(usbh, COINTERRA_EP_R, buf, sizeof(buf), &xfer, timeout);
  51. if (e)
  52. return e;
  53. if (xfer != COINTERRA_PACKET_SIZE)
  54. applogr(LIBUSB_ERROR_OTHER, LOG_ERR, "%s: Packet size mismatch (actual=%d expected=%d)",
  55. repr, xfer, (int)COINTERRA_PACKET_SIZE);
  56. for (int i = sizeof(ss); i--; )
  57. if (ss[i] != buf[i])
  58. applogr(LIBUSB_ERROR_OTHER;, LOG_ERR, "%s: Packet start sequence mismatch", repr);
  59. uint8_t * const bufp = &buf[sizeof(ss)];
  60. *out_msgtype = upk_u8(bufp, 0);
  61. memcpy(out, &bufp[1], COINTERRA_MSGBODY_SIZE);
  62. return 0;
  63. }
  64. static
  65. bool cointerra_lowl_match(const struct lowlevel_device_info * const info)
  66. {
  67. return lowlevel_match_lowlproduct(info, &lowl_usb, "GoldStrike");
  68. }
  69. static
  70. bool cointerra_lowl_probe(const struct lowlevel_device_info * const info)
  71. {
  72. int e;
  73. if (info->lowl != &lowl_usb)
  74. applogr(false, LOG_DEBUG, "%s: Matched \"%s\" %s, but lowlevel driver is not usb_generic!",
  75. __func__, info->product, info->devid);
  76. libusb_device_handle *usbh;
  77. e = libusb_open(info->lowl_data, &usbh);
  78. if (e)
  79. applogr(false, LOG_ERR, "%s: Failed to open %s: %s",
  80. cointerra_drv.dname, info->devid, bfg_strerror(e, BST_LIBUSB));
  81. unsigned pipes;
  82. {
  83. uint8_t buf[COINTERRA_PACKET_SIZE] = {
  84. COINTERRA_START_SEQ,
  85. CMTO_REQUEST,
  86. CMTI_INFO, 0,
  87. };
  88. int xfer;
  89. uint8_t msgtype;
  90. e = libusb_bulk_transfer(usbh, COINTERRA_EP_W, buf, sizeof(buf), &xfer, COINTERRA_USB_TIMEOUT);
  91. if (e)
  92. return e;
  93. while (true)
  94. {
  95. e = cointerra_read_msg(&msgtype, buf, usbh, cointerra_drv.dname, COINTERRA_USB_TIMEOUT);
  96. if (e)
  97. return e;
  98. if (msgtype == CMTI_INFO)
  99. break;
  100. // FIXME: Timeout if we keep getting packets we don't care about
  101. }
  102. pipes = upk_u16le(buf, 8);
  103. }
  104. applog(LOG_DEBUG, "%s: Found %u pipes on %s",
  105. __func__, pipes, info->devid);
  106. struct cgpu_info * const cgpu = malloc(sizeof(*cgpu));
  107. *cgpu = (struct cgpu_info){
  108. .drv = &cointerra_drv,
  109. .procs = pipes,
  110. .device_data = lowlevel_ref(info),
  111. .threads = 1,
  112. .device_path = strdup(info->devid),
  113. .dev_manufacturer = maybe_strdup(info->manufacturer),
  114. .dev_product = maybe_strdup(info->product),
  115. .dev_serial = maybe_strdup(info->serial),
  116. .deven = DEV_ENABLED,
  117. };
  118. return add_cgpu(cgpu);
  119. }
  120. struct device_drv cointerra_drv = {
  121. .dname = "cointerra",
  122. .name = "CTA",
  123. .lowl_match = cointerra_lowl_match,
  124. .lowl_probe = cointerra_lowl_probe,
  125. };