KissModem.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. #include "KissModem.h"
  2. #include <CayenneLPP.h>
  3. KissModem::KissModem(Stream& serial, mesh::LocalIdentity& identity, mesh::RNG& rng,
  4. mesh::Radio& radio, mesh::MainBoard& board, SensorManager& sensors)
  5. : _serial(serial), _identity(identity), _rng(rng), _radio(radio), _board(board), _sensors(sensors) {
  6. _rx_len = 0;
  7. _rx_escaped = false;
  8. _rx_active = false;
  9. _has_pending_tx = false;
  10. _pending_tx_len = 0;
  11. _setRadioCallback = nullptr;
  12. _setTxPowerCallback = nullptr;
  13. _getCurrentRssiCallback = nullptr;
  14. _getStatsCallback = nullptr;
  15. _config = {0, 0, 0, 0, 0};
  16. }
  17. void KissModem::begin() {
  18. _rx_len = 0;
  19. _rx_escaped = false;
  20. _rx_active = false;
  21. _has_pending_tx = false;
  22. }
  23. void KissModem::writeByte(uint8_t b) {
  24. if (b == KISS_FEND) {
  25. _serial.write(KISS_FESC);
  26. _serial.write(KISS_TFEND);
  27. } else if (b == KISS_FESC) {
  28. _serial.write(KISS_FESC);
  29. _serial.write(KISS_TFESC);
  30. } else {
  31. _serial.write(b);
  32. }
  33. }
  34. void KissModem::writeFrame(uint8_t cmd, const uint8_t* data, uint16_t len) {
  35. _serial.write(KISS_FEND);
  36. writeByte(cmd);
  37. for (uint16_t i = 0; i < len; i++) {
  38. writeByte(data[i]);
  39. }
  40. _serial.write(KISS_FEND);
  41. }
  42. void KissModem::writeErrorFrame(uint8_t error_code) {
  43. writeFrame(RESP_ERROR, &error_code, 1);
  44. }
  45. void KissModem::loop() {
  46. while (_serial.available()) {
  47. uint8_t b = _serial.read();
  48. if (b == KISS_FEND) {
  49. if (_rx_active && _rx_len > 0) {
  50. processFrame();
  51. }
  52. _rx_len = 0;
  53. _rx_escaped = false;
  54. _rx_active = true;
  55. continue;
  56. }
  57. if (!_rx_active) continue;
  58. if (b == KISS_FESC) {
  59. _rx_escaped = true;
  60. continue;
  61. }
  62. if (_rx_escaped) {
  63. _rx_escaped = false;
  64. if (b == KISS_TFEND) b = KISS_FEND;
  65. else if (b == KISS_TFESC) b = KISS_FESC;
  66. }
  67. if (_rx_len < KISS_MAX_FRAME_SIZE) {
  68. _rx_buf[_rx_len++] = b;
  69. }
  70. }
  71. }
  72. void KissModem::processFrame() {
  73. if (_rx_len < 1) return;
  74. uint8_t cmd = _rx_buf[0];
  75. const uint8_t* data = &_rx_buf[1];
  76. uint16_t data_len = _rx_len - 1;
  77. switch (cmd) {
  78. case CMD_DATA:
  79. if (data_len < 2) {
  80. writeErrorFrame(ERR_INVALID_LENGTH);
  81. } else if (data_len > KISS_MAX_PACKET_SIZE) {
  82. writeErrorFrame(ERR_INVALID_LENGTH);
  83. } else if (_has_pending_tx) {
  84. writeErrorFrame(ERR_TX_PENDING);
  85. } else {
  86. memcpy(_pending_tx, data, data_len);
  87. _pending_tx_len = data_len;
  88. _has_pending_tx = true;
  89. }
  90. break;
  91. case CMD_GET_IDENTITY:
  92. handleGetIdentity();
  93. break;
  94. case CMD_GET_RANDOM:
  95. handleGetRandom(data, data_len);
  96. break;
  97. case CMD_VERIFY_SIGNATURE:
  98. handleVerifySignature(data, data_len);
  99. break;
  100. case CMD_SIGN_DATA:
  101. handleSignData(data, data_len);
  102. break;
  103. case CMD_ENCRYPT_DATA:
  104. handleEncryptData(data, data_len);
  105. break;
  106. case CMD_DECRYPT_DATA:
  107. handleDecryptData(data, data_len);
  108. break;
  109. case CMD_KEY_EXCHANGE:
  110. handleKeyExchange(data, data_len);
  111. break;
  112. case CMD_HASH:
  113. handleHash(data, data_len);
  114. break;
  115. case CMD_SET_RADIO:
  116. handleSetRadio(data, data_len);
  117. break;
  118. case CMD_SET_TX_POWER:
  119. handleSetTxPower(data, data_len);
  120. break;
  121. case CMD_GET_RADIO:
  122. handleGetRadio();
  123. break;
  124. case CMD_GET_TX_POWER:
  125. handleGetTxPower();
  126. break;
  127. case CMD_GET_VERSION:
  128. handleGetVersion();
  129. break;
  130. case CMD_GET_CURRENT_RSSI:
  131. handleGetCurrentRssi();
  132. break;
  133. case CMD_IS_CHANNEL_BUSY:
  134. handleIsChannelBusy();
  135. break;
  136. case CMD_GET_AIRTIME:
  137. handleGetAirtime(data, data_len);
  138. break;
  139. case CMD_GET_NOISE_FLOOR:
  140. handleGetNoiseFloor();
  141. break;
  142. case CMD_GET_STATS:
  143. handleGetStats();
  144. break;
  145. case CMD_GET_BATTERY:
  146. handleGetBattery();
  147. break;
  148. case CMD_PING:
  149. handlePing();
  150. break;
  151. case CMD_GET_SENSORS:
  152. handleGetSensors(data, data_len);
  153. break;
  154. default:
  155. writeErrorFrame(ERR_UNKNOWN_CMD);
  156. break;
  157. }
  158. }
  159. void KissModem::handleGetIdentity() {
  160. writeFrame(RESP_IDENTITY, _identity.pub_key, PUB_KEY_SIZE);
  161. }
  162. void KissModem::handleGetRandom(const uint8_t* data, uint16_t len) {
  163. if (len < 1) {
  164. writeErrorFrame(ERR_INVALID_LENGTH);
  165. return;
  166. }
  167. uint8_t requested = data[0];
  168. if (requested < 1 || requested > 64) {
  169. writeErrorFrame(ERR_INVALID_PARAM);
  170. return;
  171. }
  172. uint8_t buf[64];
  173. _rng.random(buf, requested);
  174. writeFrame(RESP_RANDOM, buf, requested);
  175. }
  176. void KissModem::handleVerifySignature(const uint8_t* data, uint16_t len) {
  177. if (len < PUB_KEY_SIZE + SIGNATURE_SIZE + 1) {
  178. writeErrorFrame(ERR_INVALID_LENGTH);
  179. return;
  180. }
  181. mesh::Identity signer(data);
  182. const uint8_t* signature = data + PUB_KEY_SIZE;
  183. const uint8_t* msg = data + PUB_KEY_SIZE + SIGNATURE_SIZE;
  184. uint16_t msg_len = len - PUB_KEY_SIZE - SIGNATURE_SIZE;
  185. uint8_t result = signer.verify(signature, msg, msg_len) ? 0x01 : 0x00;
  186. writeFrame(RESP_VERIFY, &result, 1);
  187. }
  188. void KissModem::handleSignData(const uint8_t* data, uint16_t len) {
  189. if (len < 1) {
  190. writeErrorFrame(ERR_INVALID_LENGTH);
  191. return;
  192. }
  193. uint8_t signature[SIGNATURE_SIZE];
  194. _identity.sign(signature, data, len);
  195. writeFrame(RESP_SIGNATURE, signature, SIGNATURE_SIZE);
  196. }
  197. void KissModem::handleEncryptData(const uint8_t* data, uint16_t len) {
  198. if (len < PUB_KEY_SIZE + 1) {
  199. writeErrorFrame(ERR_INVALID_LENGTH);
  200. return;
  201. }
  202. const uint8_t* key = data;
  203. const uint8_t* plaintext = data + PUB_KEY_SIZE;
  204. uint16_t plaintext_len = len - PUB_KEY_SIZE;
  205. uint8_t buf[KISS_MAX_FRAME_SIZE];
  206. int encrypted_len = mesh::Utils::encryptThenMAC(key, buf, plaintext, plaintext_len);
  207. if (encrypted_len > 0) {
  208. writeFrame(RESP_ENCRYPTED, buf, encrypted_len);
  209. } else {
  210. writeErrorFrame(ERR_ENCRYPT_FAILED);
  211. }
  212. }
  213. void KissModem::handleDecryptData(const uint8_t* data, uint16_t len) {
  214. if (len < PUB_KEY_SIZE + CIPHER_MAC_SIZE + 1) {
  215. writeErrorFrame(ERR_INVALID_LENGTH);
  216. return;
  217. }
  218. const uint8_t* key = data;
  219. const uint8_t* ciphertext = data + PUB_KEY_SIZE;
  220. uint16_t ciphertext_len = len - PUB_KEY_SIZE;
  221. uint8_t buf[KISS_MAX_FRAME_SIZE];
  222. int decrypted_len = mesh::Utils::MACThenDecrypt(key, buf, ciphertext, ciphertext_len);
  223. if (decrypted_len > 0) {
  224. writeFrame(RESP_DECRYPTED, buf, decrypted_len);
  225. } else {
  226. writeErrorFrame(ERR_MAC_FAILED);
  227. }
  228. }
  229. void KissModem::handleKeyExchange(const uint8_t* data, uint16_t len) {
  230. if (len < PUB_KEY_SIZE) {
  231. writeErrorFrame(ERR_INVALID_LENGTH);
  232. return;
  233. }
  234. uint8_t shared_secret[PUB_KEY_SIZE];
  235. _identity.calcSharedSecret(shared_secret, data);
  236. writeFrame(RESP_SHARED_SECRET, shared_secret, PUB_KEY_SIZE);
  237. }
  238. void KissModem::handleHash(const uint8_t* data, uint16_t len) {
  239. if (len < 1) {
  240. writeErrorFrame(ERR_INVALID_LENGTH);
  241. return;
  242. }
  243. uint8_t hash[32];
  244. mesh::Utils::sha256(hash, 32, data, len);
  245. writeFrame(RESP_HASH, hash, 32);
  246. }
  247. bool KissModem::getPacketToSend(uint8_t* packet, uint16_t* len) {
  248. if (!_has_pending_tx) return false;
  249. memcpy(packet, _pending_tx, _pending_tx_len);
  250. *len = _pending_tx_len;
  251. _has_pending_tx = false;
  252. return true;
  253. }
  254. void KissModem::onPacketReceived(int8_t snr, int8_t rssi, const uint8_t* packet, uint16_t len) {
  255. uint8_t buf[2 + KISS_MAX_PACKET_SIZE];
  256. buf[0] = (uint8_t)snr;
  257. buf[1] = (uint8_t)rssi;
  258. memcpy(&buf[2], packet, len);
  259. writeFrame(CMD_DATA, buf, 2 + len);
  260. }
  261. void KissModem::handleSetRadio(const uint8_t* data, uint16_t len) {
  262. if (len < 10) {
  263. writeErrorFrame(ERR_INVALID_LENGTH);
  264. return;
  265. }
  266. if (!_setRadioCallback) {
  267. writeErrorFrame(ERR_NO_CALLBACK);
  268. return;
  269. }
  270. uint32_t freq_hz, bw_hz;
  271. memcpy(&freq_hz, data, 4);
  272. memcpy(&bw_hz, data + 4, 4);
  273. uint8_t sf = data[8];
  274. uint8_t cr = data[9];
  275. _config.freq_hz = freq_hz;
  276. _config.bw_hz = bw_hz;
  277. _config.sf = sf;
  278. _config.cr = cr;
  279. float freq = freq_hz / 1000000.0f;
  280. float bw = bw_hz / 1000.0f;
  281. _setRadioCallback(freq, bw, sf, cr);
  282. writeFrame(RESP_OK, nullptr, 0);
  283. }
  284. void KissModem::handleSetTxPower(const uint8_t* data, uint16_t len) {
  285. if (len < 1) {
  286. writeErrorFrame(ERR_INVALID_LENGTH);
  287. return;
  288. }
  289. if (!_setTxPowerCallback) {
  290. writeErrorFrame(ERR_NO_CALLBACK);
  291. return;
  292. }
  293. _config.tx_power = data[0];
  294. _setTxPowerCallback(data[0]);
  295. writeFrame(RESP_OK, nullptr, 0);
  296. }
  297. void KissModem::handleGetRadio() {
  298. uint8_t buf[10];
  299. memcpy(buf, &_config.freq_hz, 4);
  300. memcpy(buf + 4, &_config.bw_hz, 4);
  301. buf[8] = _config.sf;
  302. buf[9] = _config.cr;
  303. writeFrame(RESP_RADIO, buf, 10);
  304. }
  305. void KissModem::handleGetTxPower() {
  306. writeFrame(RESP_TX_POWER, &_config.tx_power, 1);
  307. }
  308. void KissModem::handleGetVersion() {
  309. uint8_t buf[2];
  310. buf[0] = KISS_FIRMWARE_VERSION;
  311. buf[1] = 0;
  312. writeFrame(RESP_VERSION, buf, 2);
  313. }
  314. void KissModem::onTxComplete(bool success) {
  315. uint8_t result = success ? 0x01 : 0x00;
  316. writeFrame(RESP_TX_DONE, &result, 1);
  317. }
  318. void KissModem::handleGetCurrentRssi() {
  319. if (!_getCurrentRssiCallback) {
  320. writeErrorFrame(ERR_NO_CALLBACK);
  321. return;
  322. }
  323. float rssi = _getCurrentRssiCallback();
  324. int8_t rssi_byte = (int8_t)rssi;
  325. writeFrame(RESP_CURRENT_RSSI, (uint8_t*)&rssi_byte, 1);
  326. }
  327. void KissModem::handleIsChannelBusy() {
  328. uint8_t busy = _radio.isReceiving() ? 0x01 : 0x00;
  329. writeFrame(RESP_CHANNEL_BUSY, &busy, 1);
  330. }
  331. void KissModem::handleGetAirtime(const uint8_t* data, uint16_t len) {
  332. if (len < 1) {
  333. writeErrorFrame(ERR_INVALID_LENGTH);
  334. return;
  335. }
  336. uint8_t packet_len = data[0];
  337. uint32_t airtime = _radio.getEstAirtimeFor(packet_len);
  338. writeFrame(RESP_AIRTIME, (uint8_t*)&airtime, 4);
  339. }
  340. void KissModem::handleGetNoiseFloor() {
  341. int16_t noise_floor = _radio.getNoiseFloor();
  342. writeFrame(RESP_NOISE_FLOOR, (uint8_t*)&noise_floor, 2);
  343. }
  344. void KissModem::handleGetStats() {
  345. if (!_getStatsCallback) {
  346. writeErrorFrame(ERR_NO_CALLBACK);
  347. return;
  348. }
  349. uint32_t rx, tx, errors;
  350. _getStatsCallback(&rx, &tx, &errors);
  351. uint8_t buf[12];
  352. memcpy(buf, &rx, 4);
  353. memcpy(buf + 4, &tx, 4);
  354. memcpy(buf + 8, &errors, 4);
  355. writeFrame(RESP_STATS, buf, 12);
  356. }
  357. void KissModem::handleGetBattery() {
  358. uint16_t mv = _board.getBattMilliVolts();
  359. writeFrame(RESP_BATTERY, (uint8_t*)&mv, 2);
  360. }
  361. void KissModem::handlePing() {
  362. writeFrame(RESP_PONG, nullptr, 0);
  363. }
  364. void KissModem::handleGetSensors(const uint8_t* data, uint16_t len) {
  365. if (len < 1) {
  366. writeErrorFrame(ERR_INVALID_LENGTH);
  367. return;
  368. }
  369. uint8_t permissions = data[0];
  370. CayenneLPP telemetry(255);
  371. if (_sensors.querySensors(permissions, telemetry)) {
  372. writeFrame(RESP_SENSORS, telemetry.getBuffer(), telemetry.getSize());
  373. } else {
  374. writeFrame(RESP_SENSORS, nullptr, 0);
  375. }
  376. }