bt_cli.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. #include <furi.h>
  2. #include <furi_hal.h>
  3. #include <applications/cli/cli.h>
  4. #include <lib/toolbox/args.h>
  5. #include "bt_settings.h"
  6. static const char* bt_cli_address_types[] = {
  7. "Public Device Address",
  8. "Random Device Address",
  9. "Public Identity Address",
  10. "Random (Static) Identity Address",
  11. };
  12. static void bt_cli_command_hci_info(Cli* cli, string_t args, void* context) {
  13. UNUSED(cli);
  14. UNUSED(args);
  15. UNUSED(context);
  16. string_t buffer;
  17. string_init(buffer);
  18. furi_hal_bt_dump_state(buffer);
  19. printf("%s", string_get_cstr(buffer));
  20. string_clear(buffer);
  21. }
  22. static void bt_cli_command_carrier_tx(Cli* cli, string_t args, void* context) {
  23. UNUSED(context);
  24. int channel = 0;
  25. int power = 0;
  26. do {
  27. if(!args_read_int_and_trim(args, &channel) && (channel < 0 || channel > 39)) {
  28. printf("Incorrect or missing channel, expected int 0-39");
  29. break;
  30. }
  31. if(!args_read_int_and_trim(args, &power) && (power < 0 || power > 6)) {
  32. printf("Incorrect or missing power, expected int 0-6");
  33. break;
  34. }
  35. furi_hal_bt_stop_advertising();
  36. printf("Transmitting carrier at %d channel at %d dB power\r\n", channel, power);
  37. printf("Press CTRL+C to stop\r\n");
  38. furi_hal_bt_start_tone_tx(channel, 0x19 + power);
  39. while(!cli_cmd_interrupt_received(cli)) {
  40. osDelay(250);
  41. }
  42. furi_hal_bt_stop_tone_tx();
  43. } while(false);
  44. }
  45. static void bt_cli_command_carrier_rx(Cli* cli, string_t args, void* context) {
  46. UNUSED(context);
  47. int channel = 0;
  48. do {
  49. if(!args_read_int_and_trim(args, &channel) && (channel < 0 || channel > 39)) {
  50. printf("Incorrect or missing channel, expected int 0-39");
  51. break;
  52. }
  53. furi_hal_bt_stop_advertising();
  54. printf("Receiving carrier at %d channel\r\n", channel);
  55. printf("Press CTRL+C to stop\r\n");
  56. furi_hal_bt_start_packet_rx(channel, 1);
  57. while(!cli_cmd_interrupt_received(cli)) {
  58. osDelay(250);
  59. printf("RSSI: %6.1f dB\r", furi_hal_bt_get_rssi());
  60. fflush(stdout);
  61. }
  62. furi_hal_bt_stop_packet_test();
  63. } while(false);
  64. }
  65. static void bt_cli_command_packet_tx(Cli* cli, string_t args, void* context) {
  66. UNUSED(context);
  67. int channel = 0;
  68. int pattern = 0;
  69. int datarate = 1;
  70. do {
  71. if(!args_read_int_and_trim(args, &channel) && (channel < 0 || channel > 39)) {
  72. printf("Incorrect or missing channel, expected int 0-39");
  73. break;
  74. }
  75. if(!args_read_int_and_trim(args, &pattern) && (pattern < 0 || pattern > 5)) {
  76. printf("Incorrect or missing pattern, expected int 0-5 \r\n");
  77. printf("0 - Pseudo-Random bit sequence 9\r\n");
  78. printf("1 - Pattern of alternating bits '11110000'\r\n");
  79. printf("2 - Pattern of alternating bits '10101010'\r\n");
  80. printf("3 - Pseudo-Random bit sequence 15\r\n");
  81. printf("4 - Pattern of All '1' bits\r\n");
  82. printf("5 - Pattern of All '0' bits\r\n");
  83. break;
  84. }
  85. if(!args_read_int_and_trim(args, &datarate) && (datarate < 1 || datarate > 2)) {
  86. printf("Incorrect or missing datarate, expected int 1-2");
  87. break;
  88. }
  89. furi_hal_bt_stop_advertising();
  90. printf(
  91. "Transmitting %d pattern packet at %d channel at %d M datarate\r\n",
  92. pattern,
  93. channel,
  94. datarate);
  95. printf("Press CTRL+C to stop\r\n");
  96. furi_hal_bt_start_packet_tx(channel, pattern, datarate);
  97. while(!cli_cmd_interrupt_received(cli)) {
  98. osDelay(250);
  99. }
  100. furi_hal_bt_stop_packet_test();
  101. printf("Transmitted %lu packets", furi_hal_bt_get_transmitted_packets());
  102. } while(false);
  103. }
  104. static void bt_cli_command_packet_rx(Cli* cli, string_t args, void* context) {
  105. UNUSED(context);
  106. int channel = 0;
  107. int datarate = 1;
  108. do {
  109. if(!args_read_int_and_trim(args, &channel) && (channel < 0 || channel > 39)) {
  110. printf("Incorrect or missing channel, expected int 0-39");
  111. break;
  112. }
  113. if(!args_read_int_and_trim(args, &datarate) && (datarate < 1 || datarate > 2)) {
  114. printf("Incorrect or missing datarate, expected int 1-2");
  115. break;
  116. }
  117. furi_hal_bt_stop_advertising();
  118. printf("Receiving packets at %d channel at %d M datarate\r\n", channel, datarate);
  119. printf("Press CTRL+C to stop\r\n");
  120. furi_hal_bt_start_packet_rx(channel, datarate);
  121. float rssi_raw = 0;
  122. while(!cli_cmd_interrupt_received(cli)) {
  123. osDelay(250);
  124. rssi_raw = furi_hal_bt_get_rssi();
  125. printf("RSSI: %03.1f dB\r", rssi_raw);
  126. fflush(stdout);
  127. }
  128. uint16_t packets_received = furi_hal_bt_stop_packet_test();
  129. printf("Received %hu packets", packets_received);
  130. } while(false);
  131. }
  132. static void bt_cli_scan_callback(GapAddress address, void* context) {
  133. furi_assert(context);
  134. osMessageQueueId_t queue = context;
  135. osMessageQueuePut(queue, &address, 0, 250);
  136. }
  137. static void bt_cli_command_scan(Cli* cli, string_t args, void* context) {
  138. UNUSED(context);
  139. UNUSED(args);
  140. osMessageQueueId_t queue = osMessageQueueNew(20, sizeof(GapAddress), NULL);
  141. furi_hal_bt_start_scan(bt_cli_scan_callback, queue);
  142. GapAddress address = {};
  143. bool exit = false;
  144. while(!exit) {
  145. if(osMessageQueueGet(queue, &address, NULL, 250) == osOK) {
  146. if(address.type < sizeof(bt_cli_address_types)) {
  147. printf("Found new device. Type: %s, MAC: ", bt_cli_address_types[address.type]);
  148. for(uint8_t i = 0; i < sizeof(address.mac) - 1; i++) {
  149. printf("%02X:", address.mac[i]);
  150. }
  151. printf("%02X\r\n", address.mac[sizeof(address.mac) - 1]);
  152. }
  153. }
  154. exit = cli_cmd_interrupt_received(cli);
  155. }
  156. furi_hal_bt_stop_scan();
  157. osMessageQueueDelete(queue);
  158. }
  159. static void bt_cli_print_usage() {
  160. printf("Usage:\r\n");
  161. printf("bt <cmd> <args>\r\n");
  162. printf("Cmd list:\r\n");
  163. printf("\thci_info\t - HCI info\r\n");
  164. if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug) &&
  165. furi_hal_bt_get_radio_stack() == FuriHalBtStackHciLayer) {
  166. printf("\ttx_carrier <channel:0-39> <power:0-6>\t - start tx carrier test\r\n");
  167. printf("\trx_carrier <channel:0-39>\t - start rx carrier test\r\n");
  168. printf("\ttx_pt <channel:0-39> <pattern:0-5> <datarate:1-2>\t - start tx packet test\r\n");
  169. printf("\trx_pt <channel:0-39> <datarate:1-2>\t - start rx packer test\r\n");
  170. printf("\tscan\t - start scanner\r\n");
  171. }
  172. }
  173. static void bt_cli(Cli* cli, string_t args, void* context) {
  174. UNUSED(context);
  175. furi_record_open("bt");
  176. string_t cmd;
  177. string_init(cmd);
  178. BtSettings bt_settings;
  179. bt_settings_load(&bt_settings);
  180. do {
  181. if(!args_read_string_and_trim(args, cmd)) {
  182. bt_cli_print_usage();
  183. break;
  184. }
  185. if(string_cmp_str(cmd, "hci_info") == 0) {
  186. bt_cli_command_hci_info(cli, args, NULL);
  187. break;
  188. }
  189. if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug) &&
  190. furi_hal_bt_get_radio_stack() == FuriHalBtStackHciLayer) {
  191. if(string_cmp_str(cmd, "carrier_tx") == 0) {
  192. bt_cli_command_carrier_tx(cli, args, NULL);
  193. break;
  194. }
  195. if(string_cmp_str(cmd, "carrier_rx") == 0) {
  196. bt_cli_command_carrier_rx(cli, args, NULL);
  197. break;
  198. }
  199. if(string_cmp_str(cmd, "packet_tx") == 0) {
  200. bt_cli_command_packet_tx(cli, args, NULL);
  201. break;
  202. }
  203. if(string_cmp_str(cmd, "packet_rx") == 0) {
  204. bt_cli_command_packet_rx(cli, args, NULL);
  205. break;
  206. }
  207. if(string_cmp_str(cmd, "scan") == 0) {
  208. bt_cli_command_scan(cli, args, NULL);
  209. break;
  210. }
  211. }
  212. bt_cli_print_usage();
  213. } while(false);
  214. if(bt_settings.enabled) {
  215. furi_hal_bt_start_advertising();
  216. }
  217. string_clear(cmd);
  218. furi_record_close("bt");
  219. }
  220. void bt_on_system_start() {
  221. #ifdef SRV_CLI
  222. Cli* cli = furi_record_open("cli");
  223. cli_add_command(cli, "bt", CliCommandFlagDefault, bt_cli, NULL);
  224. furi_record_close("cli");
  225. #else
  226. UNUSED(bt_cli);
  227. #endif
  228. }