driver-minergate.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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. * To avoid doubt: Programs using the minergate protocol to interface with
  10. * BFGMiner are considered part of the Corresponding Source, and not an
  11. * independent work. This means that such programs distrbuted with BFGMiner
  12. * must be released under the terms of the GPLv3 license, or sufficiently
  13. * compatible terms.
  14. */
  15. #include "config.h"
  16. #include <stdbool.h>
  17. #include <stdint.h>
  18. #include <sys/epoll.h>
  19. #include <sys/types.h>
  20. #include <sys/socket.h>
  21. #include <sys/un.h>
  22. #include "deviceapi.h"
  23. #include "miner.h"
  24. static const int minergate_max_responses = 300;
  25. BFG_REGISTER_DRIVER(minergate_drv)
  26. enum minergate_reqpkt_flags {
  27. MRPF_FIRST = 1,
  28. MRPF_FLUSH = 2,
  29. };
  30. static
  31. int minergate_open(const char * const devpath)
  32. {
  33. size_t devpath_len = strlen(devpath);
  34. struct sockaddr_un sa = {
  35. .sun_family = AF_UNIX,
  36. };
  37. #ifdef UNIX_PATH_MAX
  38. if (devpath_len >= UNIX_PATH_MAX)
  39. #else
  40. if (devpath_len >= sizeof(sa.sun_path))
  41. #endif
  42. return -1;
  43. const int fd = socket(PF_UNIX, SOCK_STREAM, 0);
  44. strcpy(sa.sun_path, devpath);
  45. if (connect(fd, &sa, sizeof(sa)))
  46. {
  47. close(fd);
  48. return -1;
  49. }
  50. return fd;
  51. }
  52. static
  53. bool minergate_detect_one(const char * const devpath)
  54. {
  55. bool rv = false;
  56. const int fd = minergate_open(devpath);
  57. if (unlikely(fd < 0))
  58. applogr(false, LOG_DEBUG, "%s: %s: Cannot connect", minergate_drv.dname, devpath);
  59. int epfd = -1;
  60. static const int minergate_version = 6;
  61. #define req_sz (8 + (24 * 100))
  62. uint8_t buf[req_sz] = {0xbf, 0x90, minergate_version, MRPF_FIRST, 0,0, 0 /* req count */,};
  63. pk_u16le(buf, 4, 0xcaf4);
  64. if (req_sz != write(fd, buf, req_sz))
  65. return_via_applog(out, , LOG_DEBUG, "%s: %s: write incomplete or failed", minergate_drv.dname, devpath);
  66. epfd = epoll_create(1);
  67. if (epfd < 0)
  68. return_via_applog(out, , LOG_DEBUG, "%s: %s: %s failed", minergate_drv.dname, devpath, "epoll_create");
  69. struct epoll_event eev;
  70. eev.events = EPOLLIN;
  71. if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &eev))
  72. return_via_applog(out, , LOG_DEBUG, "%s: %s: %s failed", minergate_drv.dname, devpath, "epoll_ctl");
  73. size_t read_bytes = 0;
  74. static const size_t read_expect = 8;
  75. ssize_t r;
  76. while (read_bytes < read_expect)
  77. {
  78. if (epoll_wait(epfd, &eev, 1, 1000) != 1)
  79. return_via_applog(out, , LOG_DEBUG, "%s: %s: Timeout waiting for response", minergate_drv.dname, devpath);
  80. r = read(fd, &buf[read_bytes], read_expect - read_bytes);
  81. if (r <= 0)
  82. return_via_applog(out, , LOG_DEBUG, "%s: %s: %s failed", minergate_drv.dname, devpath, "read");
  83. read_bytes += r;
  84. }
  85. if (buf[1] != 0x90)
  86. return_via_applog(out, , LOG_DEBUG, "%s: %s: %s mismatch", minergate_drv.dname, devpath, "request_id");
  87. if (buf[2] != minergate_version)
  88. return_via_applog(out, , LOG_DEBUG, "%s: %s: %s mismatch", minergate_drv.dname, devpath, "minergate_version");
  89. if (upk_u16le(buf, 4) != 0xcaf4)
  90. return_via_applog(out, , LOG_DEBUG, "%s: %s: %s mismatch", minergate_drv.dname, devpath, "magic");
  91. uint16_t responses = upk_u16le(buf, 6);
  92. if (responses > minergate_max_responses)
  93. return_via_applog(out, , LOG_DEBUG, "%s: %s: More than maximum responses", minergate_drv.dname, devpath);
  94. struct cgpu_info * const cgpu = malloc(sizeof(*cgpu));
  95. *cgpu = (struct cgpu_info){
  96. .drv = &minergate_drv,
  97. .device_path = strdup(devpath),
  98. .deven = DEV_ENABLED,
  99. };
  100. rv = add_cgpu(cgpu);
  101. out:
  102. close(fd);
  103. if (epfd >= 0)
  104. close(epfd);
  105. return rv;
  106. }
  107. static
  108. int minergate_detect_auto(void)
  109. {
  110. return minergate_detect_one("/tmp/connection_pipe") ? 1 : 0;
  111. }
  112. static
  113. void minergate_detect(void)
  114. {
  115. generic_detect(&minergate_drv, minergate_detect_one, minergate_detect_auto, 0);
  116. }
  117. struct device_drv minergate_drv = {
  118. .dname = "minergate",
  119. .name = "MGT",
  120. .drv_detect = minergate_detect,
  121. };