btgatt-client.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * BlueZ - Bluetooth protocol stack for Linux
  4. *
  5. * Copyright (C) 2014 Google Inc.
  6. *
  7. *
  8. */
  9. #ifdef HAVE_CONFIG_H
  10. #include <config.h>
  11. #endif
  12. #define _GNU_SOURCE
  13. #include <stdio.h>
  14. #include <stdbool.h>
  15. #include <stdint.h>
  16. #include <stdlib.h>
  17. #include <unistd.h>
  18. #include <getopt.h>
  19. #include <limits.h>
  20. #include <errno.h>
  21. #include "lib/bluetooth.h"
  22. #include "lib/hci.h"
  23. #include "lib/hci_lib.h"
  24. #include "lib/l2cap.h"
  25. #include "lib/uuid.h"
  26. #include "src/shared/mainloop.h"
  27. #include "src/shared/util.h"
  28. #include "src/shared/att.h"
  29. #include "src/shared/queue.h"
  30. #include "src/shared/gatt-db.h"
  31. #include "src/shared/gatt-client.h"
  32. #define ATT_CID 4
  33. #define PRLOG(...) \
  34. printf(__VA_ARGS__); print_prompt();
  35. #define COLOR_OFF "\x1B[0m"
  36. #define COLOR_RED "\x1B[0;91m"
  37. #define COLOR_GREEN "\x1B[0;92m"
  38. #define COLOR_YELLOW "\x1B[0;93m"
  39. #define COLOR_BLUE "\x1B[0;94m"
  40. #define COLOR_MAGENTA "\x1B[0;95m"
  41. #define COLOR_BOLDGRAY "\x1B[1;30m"
  42. #define COLOR_BOLDWHITE "\x1B[1;37m"
  43. static bool verbose = false;
  44. struct client {
  45. int fd;
  46. struct bt_att *att;
  47. struct gatt_db *db;
  48. struct bt_gatt_client *gatt;
  49. unsigned int reliable_session_id;
  50. };
  51. static void print_prompt(void)
  52. {
  53. printf(COLOR_BLUE "[GATT client]" COLOR_OFF "# ");
  54. fflush(stdout);
  55. }
  56. static const char *ecode_to_string(uint8_t ecode)
  57. {
  58. switch (ecode) {
  59. case BT_ATT_ERROR_INVALID_HANDLE:
  60. return "Invalid Handle";
  61. case BT_ATT_ERROR_READ_NOT_PERMITTED:
  62. return "Read Not Permitted";
  63. case BT_ATT_ERROR_WRITE_NOT_PERMITTED:
  64. return "Write Not Permitted";
  65. case BT_ATT_ERROR_INVALID_PDU:
  66. return "Invalid PDU";
  67. case BT_ATT_ERROR_AUTHENTICATION:
  68. return "Authentication Required";
  69. case BT_ATT_ERROR_REQUEST_NOT_SUPPORTED:
  70. return "Request Not Supported";
  71. case BT_ATT_ERROR_INVALID_OFFSET:
  72. return "Invalid Offset";
  73. case BT_ATT_ERROR_AUTHORIZATION:
  74. return "Authorization Required";
  75. case BT_ATT_ERROR_PREPARE_QUEUE_FULL:
  76. return "Prepare Write Queue Full";
  77. case BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND:
  78. return "Attribute Not Found";
  79. case BT_ATT_ERROR_ATTRIBUTE_NOT_LONG:
  80. return "Attribute Not Long";
  81. case BT_ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE:
  82. return "Insuficient Encryption Key Size";
  83. case BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN:
  84. return "Invalid Attribute value len";
  85. case BT_ATT_ERROR_UNLIKELY:
  86. return "Unlikely Error";
  87. case BT_ATT_ERROR_INSUFFICIENT_ENCRYPTION:
  88. return "Insufficient Encryption";
  89. case BT_ATT_ERROR_UNSUPPORTED_GROUP_TYPE:
  90. return "Group type Not Supported";
  91. case BT_ATT_ERROR_INSUFFICIENT_RESOURCES:
  92. return "Insufficient Resources";
  93. case BT_ERROR_CCC_IMPROPERLY_CONFIGURED:
  94. return "CCC Improperly Configured";
  95. case BT_ERROR_ALREADY_IN_PROGRESS:
  96. return "Procedure Already in Progress";
  97. case BT_ERROR_OUT_OF_RANGE:
  98. return "Out of Range";
  99. default:
  100. return "Unknown error type";
  101. }
  102. }
  103. static void att_disconnect_cb(int err, void *user_data)
  104. {
  105. printf("Device disconnected: %s\n", strerror(err));
  106. mainloop_quit();
  107. }
  108. static void att_debug_cb(const char *str, void *user_data)
  109. {
  110. const char *prefix = user_data;
  111. PRLOG(COLOR_BOLDGRAY "%s" COLOR_BOLDWHITE "%s\n" COLOR_OFF, prefix, str);
  112. }
  113. static void gatt_debug_cb(const char *str, void *user_data)
  114. {
  115. const char *prefix = user_data;
  116. PRLOG(COLOR_GREEN "%s%s\n" COLOR_OFF, prefix, str);
  117. }
  118. static void ready_cb(bool success, uint8_t att_ecode, void *user_data);
  119. static void service_changed_cb(uint16_t start_handle, uint16_t end_handle,
  120. void *user_data);
  121. static void log_service_event(struct gatt_db_attribute *attr, const char *str)
  122. {
  123. char uuid_str[MAX_LEN_UUID_STR];
  124. bt_uuid_t uuid;
  125. uint16_t start, end;
  126. gatt_db_attribute_get_service_uuid(attr, &uuid);
  127. bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
  128. gatt_db_attribute_get_service_handles(attr, &start, &end);
  129. PRLOG("%s - UUID: %s start: 0x%04x end: 0x%04x\n", str, uuid_str,
  130. start, end);
  131. }
  132. static void service_added_cb(struct gatt_db_attribute *attr, void *user_data)
  133. {
  134. log_service_event(attr, "Service Added");
  135. }
  136. static void service_removed_cb(struct gatt_db_attribute *attr, void *user_data)
  137. {
  138. log_service_event(attr, "Service Removed");
  139. }
  140. static struct client *client_create(int fd, uint16_t mtu)
  141. {
  142. struct client *cli;
  143. cli = new0(struct client, 1);
  144. if (!cli) {
  145. fprintf(stderr, "Failed to allocate memory for client\n");
  146. return NULL;
  147. }
  148. cli->att = bt_att_new(fd, false);
  149. if (!cli->att) {
  150. fprintf(stderr, "Failed to initialze ATT transport layer\n");
  151. bt_att_unref(cli->att);
  152. free(cli);
  153. return NULL;
  154. }
  155. if (!bt_att_set_close_on_unref(cli->att, true)) {
  156. fprintf(stderr, "Failed to set up ATT transport layer\n");
  157. bt_att_unref(cli->att);
  158. free(cli);
  159. return NULL;
  160. }
  161. if (!bt_att_register_disconnect(cli->att, att_disconnect_cb, NULL,
  162. NULL)) {
  163. fprintf(stderr, "Failed to set ATT disconnect handler\n");
  164. bt_att_unref(cli->att);
  165. free(cli);
  166. return NULL;
  167. }
  168. cli->fd = fd;
  169. cli->db = gatt_db_new();
  170. if (!cli->db) {
  171. fprintf(stderr, "Failed to create GATT database\n");
  172. bt_att_unref(cli->att);
  173. free(cli);
  174. return NULL;
  175. }
  176. cli->gatt = bt_gatt_client_new(cli->db, cli->att, mtu, 0);
  177. if (!cli->gatt) {
  178. fprintf(stderr, "Failed to create GATT client\n");
  179. gatt_db_unref(cli->db);
  180. bt_att_unref(cli->att);
  181. free(cli);
  182. return NULL;
  183. }
  184. gatt_db_register(cli->db, service_added_cb, service_removed_cb,
  185. NULL, NULL);
  186. if (verbose) {
  187. bt_att_set_debug(cli->att, BT_ATT_DEBUG_VERBOSE, att_debug_cb,
  188. "att: ", NULL);
  189. bt_gatt_client_set_debug(cli->gatt, gatt_debug_cb, "gatt: ",
  190. NULL);
  191. }
  192. bt_gatt_client_ready_register(cli->gatt, ready_cb, cli, NULL);
  193. bt_gatt_client_set_service_changed(cli->gatt, service_changed_cb, cli,
  194. NULL);
  195. /* bt_gatt_client already holds a reference */
  196. gatt_db_unref(cli->db);
  197. return cli;
  198. }
  199. static void client_destroy(struct client *cli)
  200. {
  201. bt_gatt_client_unref(cli->gatt);
  202. bt_att_unref(cli->att);
  203. free(cli);
  204. }
  205. static void print_uuid(const bt_uuid_t *uuid)
  206. {
  207. char uuid_str[MAX_LEN_UUID_STR];
  208. bt_uuid_t uuid128;
  209. bt_uuid_to_uuid128(uuid, &uuid128);
  210. bt_uuid_to_string(&uuid128, uuid_str, sizeof(uuid_str));
  211. printf("%s\n", uuid_str);
  212. }
  213. static void print_incl(struct gatt_db_attribute *attr, void *user_data)
  214. {
  215. struct client *cli = user_data;
  216. uint16_t handle, start, end;
  217. struct gatt_db_attribute *service;
  218. bt_uuid_t uuid;
  219. if (!gatt_db_attribute_get_incl_data(attr, &handle, &start, &end))
  220. return;
  221. service = gatt_db_get_attribute(cli->db, start);
  222. if (!service)
  223. return;
  224. gatt_db_attribute_get_service_uuid(service, &uuid);
  225. printf("\t " COLOR_GREEN "include" COLOR_OFF " - handle: "
  226. "0x%04x, - start: 0x%04x, end: 0x%04x,"
  227. "uuid: ", handle, start, end);
  228. print_uuid(&uuid);
  229. }
  230. static void print_desc(struct gatt_db_attribute *attr, void *user_data)
  231. {
  232. printf("\t\t " COLOR_MAGENTA "descr" COLOR_OFF
  233. " - handle: 0x%04x, uuid: ",
  234. gatt_db_attribute_get_handle(attr));
  235. print_uuid(gatt_db_attribute_get_type(attr));
  236. }
  237. static void print_chrc(struct gatt_db_attribute *attr, void *user_data)
  238. {
  239. uint16_t handle, value_handle;
  240. uint8_t properties;
  241. uint16_t ext_prop;
  242. bt_uuid_t uuid;
  243. if (!gatt_db_attribute_get_char_data(attr, &handle,
  244. &value_handle,
  245. &properties,
  246. &ext_prop,
  247. &uuid))
  248. return;
  249. printf("\t " COLOR_YELLOW "charac" COLOR_OFF
  250. " - start: 0x%04x, value: 0x%04x, "
  251. "props: 0x%02x, ext_props: 0x%04x, uuid: ",
  252. handle, value_handle, properties, ext_prop);
  253. print_uuid(&uuid);
  254. gatt_db_service_foreach_desc(attr, print_desc, NULL);
  255. }
  256. static void print_service(struct gatt_db_attribute *attr, void *user_data)
  257. {
  258. struct client *cli = user_data;
  259. uint16_t start, end;
  260. bool primary;
  261. bt_uuid_t uuid;
  262. if (!gatt_db_attribute_get_service_data(attr, &start, &end, &primary,
  263. &uuid))
  264. return;
  265. printf(COLOR_RED "service" COLOR_OFF " - start: 0x%04x, "
  266. "end: 0x%04x, type: %s, uuid: ",
  267. start, end, primary ? "primary" : "secondary");
  268. print_uuid(&uuid);
  269. gatt_db_service_foreach_incl(attr, print_incl, cli);
  270. gatt_db_service_foreach_char(attr, print_chrc, NULL);
  271. printf("\n");
  272. }
  273. static void print_services(struct client *cli)
  274. {
  275. printf("\n");
  276. gatt_db_foreach_service(cli->db, NULL, print_service, cli);
  277. }
  278. static void print_services_by_uuid(struct client *cli, const bt_uuid_t *uuid)
  279. {
  280. printf("\n");
  281. gatt_db_foreach_service(cli->db, uuid, print_service, cli);
  282. }
  283. static void print_services_by_handle(struct client *cli, uint16_t handle)
  284. {
  285. printf("\n");
  286. /* TODO: Filter by handle */
  287. gatt_db_foreach_service(cli->db, NULL, print_service, cli);
  288. }
  289. static void ready_cb(bool success, uint8_t att_ecode, void *user_data)
  290. {
  291. struct client *cli = user_data;
  292. if (!success) {
  293. PRLOG("GATT discovery procedures failed - error code: 0x%02x\n",
  294. att_ecode);
  295. return;
  296. }
  297. PRLOG("GATT discovery procedures complete\n");
  298. print_services(cli);
  299. print_prompt();
  300. }
  301. static void service_changed_cb(uint16_t start_handle, uint16_t end_handle,
  302. void *user_data)
  303. {
  304. struct client *cli = user_data;
  305. printf("\nService Changed handled - start: 0x%04x end: 0x%04x\n",
  306. start_handle, end_handle);
  307. gatt_db_foreach_service_in_range(cli->db, NULL, print_service, cli,
  308. start_handle, end_handle);
  309. print_prompt();
  310. }
  311. static void services_usage(void)
  312. {
  313. printf("Usage: services [options]\nOptions:\n"
  314. "\t -u, --uuid <uuid>\tService UUID\n"
  315. "\t -a, --handle <handle>\tService start handle\n"
  316. "\t -h, --help\t\tShow help message\n"
  317. "e.g.:\n"
  318. "\tservices\n\tservices -u 0x180d\n\tservices -a 0x0009\n");
  319. }
  320. static bool parse_args(char *str, int expected_argc, char **argv, int *argc)
  321. {
  322. char **ap;
  323. for (ap = argv; (*ap = strsep(&str, " \t")) != NULL;) {
  324. if (**ap == '\0')
  325. continue;
  326. (*argc)++;
  327. ap++;
  328. if (*argc > expected_argc)
  329. return false;
  330. }
  331. return true;
  332. }
  333. static void cmd_services(struct client *cli, char *cmd_str)
  334. {
  335. char *argv[3];
  336. int argc = 0;
  337. if (!bt_gatt_client_is_ready(cli->gatt)) {
  338. printf("GATT client not initialized\n");
  339. return;
  340. }
  341. if (!parse_args(cmd_str, 2, argv, &argc)) {
  342. services_usage();
  343. return;
  344. }
  345. if (!argc) {
  346. print_services(cli);
  347. return;
  348. }
  349. if (argc != 2) {
  350. services_usage();
  351. return;
  352. }
  353. if (!strcmp(argv[0], "-u") || !strcmp(argv[0], "--uuid")) {
  354. bt_uuid_t tmp, uuid;
  355. if (bt_string_to_uuid(&tmp, argv[1]) < 0) {
  356. printf("Invalid UUID: %s\n", argv[1]);
  357. return;
  358. }
  359. bt_uuid_to_uuid128(&tmp, &uuid);
  360. print_services_by_uuid(cli, &uuid);
  361. } else if (!strcmp(argv[0], "-a") || !strcmp(argv[0], "--handle")) {
  362. uint16_t handle;
  363. char *endptr = NULL;
  364. handle = strtol(argv[1], &endptr, 0);
  365. if (!endptr || *endptr != '\0') {
  366. printf("Invalid start handle: %s\n", argv[1]);
  367. return;
  368. }
  369. print_services_by_handle(cli, handle);
  370. } else
  371. services_usage();
  372. }
  373. static void read_multiple_usage(void)
  374. {
  375. printf("Usage: read-multiple <handle_1> <handle_2> ...\n");
  376. }
  377. static void read_multiple_cb(bool success, uint8_t att_ecode,
  378. const uint8_t *value, uint16_t length,
  379. void *user_data)
  380. {
  381. int i;
  382. if (!success) {
  383. PRLOG("\nRead multiple request failed: 0x%02x\n", att_ecode);
  384. return;
  385. }
  386. printf("\nRead multiple value (%u bytes):", length);
  387. for (i = 0; i < length; i++)
  388. printf("%02x ", value[i]);
  389. PRLOG("\n");
  390. }
  391. static void cmd_read_multiple(struct client *cli, char *cmd_str)
  392. {
  393. int argc = 0;
  394. uint16_t *value;
  395. char *argv[512];
  396. int i;
  397. char *endptr = NULL;
  398. if (!bt_gatt_client_is_ready(cli->gatt)) {
  399. printf("GATT client not initialized\n");
  400. return;
  401. }
  402. if (!parse_args(cmd_str, sizeof(argv), argv, &argc) || argc < 2) {
  403. read_multiple_usage();
  404. return;
  405. }
  406. value = malloc(sizeof(uint16_t) * argc);
  407. if (!value) {
  408. printf("Failed to construct value\n");
  409. return;
  410. }
  411. for (i = 0; i < argc; i++) {
  412. value[i] = strtol(argv[i], &endptr, 0);
  413. if (endptr == argv[i] || *endptr != '\0' || !value[i]) {
  414. printf("Invalid value byte: %s\n", argv[i]);
  415. free(value);
  416. return;
  417. }
  418. }
  419. if (!bt_gatt_client_read_multiple(cli->gatt, value, argc,
  420. read_multiple_cb, NULL, NULL))
  421. printf("Failed to initiate read multiple procedure\n");
  422. free(value);
  423. }
  424. static void read_value_usage(void)
  425. {
  426. printf("Usage: read-value <value_handle>\n");
  427. }
  428. static void read_cb(bool success, uint8_t att_ecode, const uint8_t *value,
  429. uint16_t length, void *user_data)
  430. {
  431. int i;
  432. if (!success) {
  433. PRLOG("\nRead request failed: %s (0x%02x)\n",
  434. ecode_to_string(att_ecode), att_ecode);
  435. return;
  436. }
  437. printf("\nRead value");
  438. if (length == 0) {
  439. PRLOG(": 0 bytes\n");
  440. return;
  441. }
  442. printf(" (%u bytes): ", length);
  443. for (i = 0; i < length; i++)
  444. printf("%02x ", value[i]);
  445. PRLOG("\n");
  446. }
  447. static void cmd_read_value(struct client *cli, char *cmd_str)
  448. {
  449. char *argv[2];
  450. int argc = 0;
  451. uint16_t handle;
  452. char *endptr = NULL;
  453. if (!bt_gatt_client_is_ready(cli->gatt)) {
  454. printf("GATT client not initialized\n");
  455. return;
  456. }
  457. if (!parse_args(cmd_str, 1, argv, &argc) || argc != 1) {
  458. read_value_usage();
  459. return;
  460. }
  461. handle = strtol(argv[0], &endptr, 0);
  462. if (!endptr || *endptr != '\0' || !handle) {
  463. printf("Invalid value handle: %s\n", argv[0]);
  464. return;
  465. }
  466. if (!bt_gatt_client_read_value(cli->gatt, handle, read_cb,
  467. NULL, NULL))
  468. printf("Failed to initiate read value procedure\n");
  469. }
  470. static void read_long_value_usage(void)
  471. {
  472. printf("Usage: read-long-value <value_handle> <offset>\n");
  473. }
  474. static void cmd_read_long_value(struct client *cli, char *cmd_str)
  475. {
  476. char *argv[3];
  477. int argc = 0;
  478. uint16_t handle;
  479. uint16_t offset;
  480. char *endptr = NULL;
  481. if (!bt_gatt_client_is_ready(cli->gatt)) {
  482. printf("GATT client not initialized\n");
  483. return;
  484. }
  485. if (!parse_args(cmd_str, 2, argv, &argc) || argc != 2) {
  486. read_long_value_usage();
  487. return;
  488. }
  489. handle = strtol(argv[0], &endptr, 0);
  490. if (!endptr || *endptr != '\0' || !handle) {
  491. printf("Invalid value handle: %s\n", argv[0]);
  492. return;
  493. }
  494. endptr = NULL;
  495. offset = strtol(argv[1], &endptr, 0);
  496. if (!endptr || *endptr != '\0') {
  497. printf("Invalid offset: %s\n", argv[1]);
  498. return;
  499. }
  500. if (!bt_gatt_client_read_long_value(cli->gatt, handle, offset, read_cb,
  501. NULL, NULL))
  502. printf("Failed to initiate read long value procedure\n");
  503. }
  504. static void write_value_usage(void)
  505. {
  506. printf("Usage: write-value [options] <value_handle> <value>\n"
  507. "Options:\n"
  508. "\t-w, --without-response\tWrite without response\n"
  509. "\t-s, --signed-write\tSigned write command\n"
  510. "e.g.:\n"
  511. "\twrite-value 0x0001 00 01 00\n");
  512. }
  513. static struct option write_value_options[] = {
  514. { "without-response", 0, 0, 'w' },
  515. { "signed-write", 0, 0, 's' },
  516. { }
  517. };
  518. static void write_cb(bool success, uint8_t att_ecode, void *user_data)
  519. {
  520. if (success) {
  521. PRLOG("\nWrite successful\n");
  522. } else {
  523. PRLOG("\nWrite failed: %s (0x%02x)\n",
  524. ecode_to_string(att_ecode), att_ecode);
  525. }
  526. }
  527. static void cmd_write_value(struct client *cli, char *cmd_str)
  528. {
  529. int opt, i, val;
  530. char *argvbuf[516];
  531. char **argv = argvbuf;
  532. int argc = 1;
  533. uint16_t handle;
  534. char *endptr = NULL;
  535. int length;
  536. uint8_t *value = NULL;
  537. bool without_response = false;
  538. bool signed_write = false;
  539. if (!bt_gatt_client_is_ready(cli->gatt)) {
  540. printf("GATT client not initialized\n");
  541. return;
  542. }
  543. if (!parse_args(cmd_str, 514, argv + 1, &argc)) {
  544. printf("Too many arguments\n");
  545. write_value_usage();
  546. return;
  547. }
  548. optind = 0;
  549. argv[0] = "write-value";
  550. while ((opt = getopt_long(argc, argv, "+ws", write_value_options,
  551. NULL)) != -1) {
  552. switch (opt) {
  553. case 'w':
  554. without_response = true;
  555. break;
  556. case 's':
  557. signed_write = true;
  558. break;
  559. default:
  560. write_value_usage();
  561. return;
  562. }
  563. }
  564. argc -= optind;
  565. argv += optind;
  566. if (argc < 1) {
  567. write_value_usage();
  568. return;
  569. }
  570. handle = strtol(argv[0], &endptr, 0);
  571. if (!endptr || *endptr != '\0' || !handle) {
  572. printf("Invalid handle: %s\n", argv[0]);
  573. return;
  574. }
  575. length = argc - 1;
  576. if (length > 0) {
  577. if (length > UINT16_MAX) {
  578. printf("Write value too long\n");
  579. return;
  580. }
  581. value = malloc(length);
  582. if (!value) {
  583. printf("Failed to construct write value\n");
  584. return;
  585. }
  586. for (i = 1; i < argc; i++) {
  587. val = strtol(argv[i], &endptr, 0);
  588. if (endptr == argv[i] || *endptr != '\0'
  589. || errno == ERANGE || val < 0 || val > 255) {
  590. printf("Invalid value byte: %s\n",
  591. argv[i]);
  592. goto done;
  593. }
  594. value[i-1] = val;
  595. }
  596. }
  597. if (without_response) {
  598. if (!bt_gatt_client_write_without_response(cli->gatt, handle,
  599. signed_write, value, length)) {
  600. printf("Failed to initiate write without response "
  601. "procedure\n");
  602. goto done;
  603. }
  604. printf("Write command sent\n");
  605. goto done;
  606. }
  607. if (!bt_gatt_client_write_value(cli->gatt, handle, value, length,
  608. write_cb,
  609. NULL, NULL))
  610. printf("Failed to initiate write procedure\n");
  611. done:
  612. free(value);
  613. }
  614. static void write_long_value_usage(void)
  615. {
  616. printf("Usage: write-long-value [options] <value_handle> <offset> "
  617. "<value>\n"
  618. "Options:\n"
  619. "\t-r, --reliable-write\tReliable write\n"
  620. "e.g.:\n"
  621. "\twrite-long-value 0x0001 0 00 01 00\n");
  622. }
  623. static struct option write_long_value_options[] = {
  624. { "reliable-write", 0, 0, 'r' },
  625. { }
  626. };
  627. static void write_long_cb(bool success, bool reliable_error, uint8_t att_ecode,
  628. void *user_data)
  629. {
  630. if (success) {
  631. PRLOG("Write successful\n");
  632. } else if (reliable_error) {
  633. PRLOG("Reliable write not verified\n");
  634. } else {
  635. PRLOG("\nWrite failed: %s (0x%02x)\n",
  636. ecode_to_string(att_ecode), att_ecode);
  637. }
  638. }
  639. static void cmd_write_long_value(struct client *cli, char *cmd_str)
  640. {
  641. int opt, i, val;
  642. char *argvbuf[516];
  643. char **argv = argvbuf;
  644. int argc = 1;
  645. uint16_t handle;
  646. uint16_t offset;
  647. char *endptr = NULL;
  648. int length;
  649. uint8_t *value = NULL;
  650. bool reliable_writes = false;
  651. if (!bt_gatt_client_is_ready(cli->gatt)) {
  652. printf("GATT client not initialized\n");
  653. return;
  654. }
  655. if (!parse_args(cmd_str, 514, argv + 1, &argc)) {
  656. printf("Too many arguments\n");
  657. write_value_usage();
  658. return;
  659. }
  660. optind = 0;
  661. argv[0] = "write-long-value";
  662. while ((opt = getopt_long(argc, argv, "+r", write_long_value_options,
  663. NULL)) != -1) {
  664. switch (opt) {
  665. case 'r':
  666. reliable_writes = true;
  667. break;
  668. default:
  669. write_long_value_usage();
  670. return;
  671. }
  672. }
  673. argc -= optind;
  674. argv += optind;
  675. if (argc < 2) {
  676. write_long_value_usage();
  677. return;
  678. }
  679. handle = strtol(argv[0], &endptr, 0);
  680. if (!endptr || *endptr != '\0' || !handle) {
  681. printf("Invalid handle: %s\n", argv[0]);
  682. return;
  683. }
  684. endptr = NULL;
  685. offset = strtol(argv[1], &endptr, 0);
  686. if (!endptr || *endptr != '\0' || errno == ERANGE) {
  687. printf("Invalid offset: %s\n", argv[1]);
  688. return;
  689. }
  690. length = argc - 2;
  691. if (length > 0) {
  692. if (length > UINT16_MAX) {
  693. printf("Write value too long\n");
  694. return;
  695. }
  696. value = malloc(length);
  697. if (!value) {
  698. printf("Failed to construct write value\n");
  699. return;
  700. }
  701. for (i = 2; i < argc; i++) {
  702. val = strtol(argv[i], &endptr, 0);
  703. if (endptr == argv[i] || *endptr != '\0'
  704. || errno == ERANGE || val < 0 || val > 255) {
  705. printf("Invalid value byte: %s\n",
  706. argv[i]);
  707. free(value);
  708. return;
  709. }
  710. value[i-2] = val;
  711. }
  712. }
  713. if (!bt_gatt_client_write_long_value(cli->gatt, reliable_writes, handle,
  714. offset, value, length,
  715. write_long_cb,
  716. NULL, NULL))
  717. printf("Failed to initiate long write procedure\n");
  718. free(value);
  719. }
  720. static void write_prepare_usage(void)
  721. {
  722. printf("Usage: write-prepare [options] <value_handle> <offset> "
  723. "<value>\n"
  724. "Options:\n"
  725. "\t-s, --session-id\tSession id\n"
  726. "e.g.:\n"
  727. "\twrite-prepare -s 1 0x0001 00 01 00\n");
  728. }
  729. static struct option write_prepare_options[] = {
  730. { "session-id", 1, 0, 's' },
  731. { }
  732. };
  733. static void cmd_write_prepare(struct client *cli, char *cmd_str)
  734. {
  735. int opt, i, val;
  736. char *argvbuf[516];
  737. char **argv = argvbuf;
  738. int argc = 0;
  739. unsigned int id = 0;
  740. uint16_t handle;
  741. uint16_t offset;
  742. char *endptr = NULL;
  743. unsigned int length;
  744. uint8_t *value = NULL;
  745. if (!bt_gatt_client_is_ready(cli->gatt)) {
  746. printf("GATT client not initialized\n");
  747. return;
  748. }
  749. if (!parse_args(cmd_str, 514, argv + 1, &argc)) {
  750. printf("Too many arguments\n");
  751. write_value_usage();
  752. return;
  753. }
  754. /* Add command name for getopt_long */
  755. argc++;
  756. argv[0] = "write-prepare";
  757. optind = 0;
  758. while ((opt = getopt_long(argc, argv , "s:", write_prepare_options,
  759. NULL)) != -1) {
  760. switch (opt) {
  761. case 's':
  762. if (!optarg) {
  763. write_prepare_usage();
  764. return;
  765. }
  766. id = atoi(optarg);
  767. break;
  768. default:
  769. write_prepare_usage();
  770. return;
  771. }
  772. }
  773. argc -= optind;
  774. argv += optind;
  775. if (argc < 3) {
  776. write_prepare_usage();
  777. return;
  778. }
  779. if (cli->reliable_session_id != id) {
  780. printf("Session id != Ongoing session id (%u!=%u)\n", id,
  781. cli->reliable_session_id);
  782. return;
  783. }
  784. handle = strtol(argv[0], &endptr, 0);
  785. if (!endptr || *endptr != '\0' || !handle) {
  786. printf("Invalid handle: %s\n", argv[0]);
  787. return;
  788. }
  789. endptr = NULL;
  790. offset = strtol(argv[1], &endptr, 0);
  791. if (!endptr || *endptr != '\0' || errno == ERANGE) {
  792. printf("Invalid offset: %s\n", argv[1]);
  793. return;
  794. }
  795. /*
  796. * First two arguments are handle and offset. What remains is the value
  797. * length
  798. */
  799. length = argc - 2;
  800. if (length == 0)
  801. goto done;
  802. if (length > UINT16_MAX) {
  803. printf("Write value too long\n");
  804. return;
  805. }
  806. value = malloc(length);
  807. if (!value) {
  808. printf("Failed to allocate memory for value\n");
  809. return;
  810. }
  811. for (i = 2; i < argc; i++) {
  812. val = strtol(argv[i], &endptr, 0);
  813. if (endptr == argv[i] || *endptr != '\0' || errno == ERANGE
  814. || val < 0 || val > 255) {
  815. printf("Invalid value byte: %s\n", argv[i]);
  816. free(value);
  817. return;
  818. }
  819. value[i-2] = val;
  820. }
  821. done:
  822. cli->reliable_session_id =
  823. bt_gatt_client_prepare_write(cli->gatt, id,
  824. handle, offset,
  825. value, length,
  826. write_long_cb, NULL,
  827. NULL);
  828. if (!cli->reliable_session_id)
  829. printf("Failed to proceed prepare write\n");
  830. else
  831. printf("Prepare write success.\n"
  832. "Session id: %d to be used on next write\n",
  833. cli->reliable_session_id);
  834. free(value);
  835. }
  836. static void write_execute_usage(void)
  837. {
  838. printf("Usage: write-execute <session_id> <execute>\n"
  839. "e.g.:\n"
  840. "\twrite-execute 1 0\n");
  841. }
  842. static void cmd_write_execute(struct client *cli, char *cmd_str)
  843. {
  844. char *argvbuf[516];
  845. char **argv = argvbuf;
  846. int argc = 0;
  847. char *endptr = NULL;
  848. unsigned int session_id;
  849. bool execute;
  850. if (!bt_gatt_client_is_ready(cli->gatt)) {
  851. printf("GATT client not initialized\n");
  852. return;
  853. }
  854. if (!parse_args(cmd_str, 514, argv, &argc)) {
  855. printf("Too many arguments\n");
  856. write_value_usage();
  857. return;
  858. }
  859. if (argc < 2) {
  860. write_execute_usage();
  861. return;
  862. }
  863. session_id = strtol(argv[0], &endptr, 0);
  864. if (!endptr || *endptr != '\0') {
  865. printf("Invalid session id: %s\n", argv[0]);
  866. return;
  867. }
  868. if (session_id != cli->reliable_session_id) {
  869. printf("Invalid session id: %u != %u\n", session_id,
  870. cli->reliable_session_id);
  871. return;
  872. }
  873. execute = !!strtol(argv[1], &endptr, 0);
  874. if (!endptr || *endptr != '\0') {
  875. printf("Invalid execute: %s\n", argv[1]);
  876. return;
  877. }
  878. if (execute) {
  879. if (!bt_gatt_client_write_execute(cli->gatt, session_id,
  880. write_cb, NULL, NULL))
  881. printf("Failed to proceed write execute\n");
  882. } else {
  883. bt_gatt_client_cancel(cli->gatt, session_id);
  884. }
  885. cli->reliable_session_id = 0;
  886. }
  887. static void register_notify_usage(void)
  888. {
  889. printf("Usage: register-notify <chrc value handle>\n");
  890. }
  891. static void notify_cb(uint16_t value_handle, const uint8_t *value,
  892. uint16_t length, void *user_data)
  893. {
  894. int i;
  895. printf("\n\tHandle Value Not/Ind: 0x%04x - ", value_handle);
  896. if (length == 0) {
  897. PRLOG("(0 bytes)\n");
  898. return;
  899. }
  900. printf("(%u bytes): ", length);
  901. for (i = 0; i < length; i++)
  902. printf("%02x ", value[i]);
  903. PRLOG("\n");
  904. }
  905. static void register_notify_cb(uint16_t att_ecode, void *user_data)
  906. {
  907. if (att_ecode) {
  908. PRLOG("Failed to register notify handler "
  909. "- error code: 0x%02x\n", att_ecode);
  910. return;
  911. }
  912. PRLOG("Registered notify handler!\n");
  913. }
  914. static void cmd_register_notify(struct client *cli, char *cmd_str)
  915. {
  916. char *argv[2];
  917. int argc = 0;
  918. uint16_t value_handle;
  919. unsigned int id;
  920. char *endptr = NULL;
  921. if (!bt_gatt_client_is_ready(cli->gatt)) {
  922. printf("GATT client not initialized\n");
  923. return;
  924. }
  925. if (!parse_args(cmd_str, 1, argv, &argc) || argc != 1) {
  926. register_notify_usage();
  927. return;
  928. }
  929. value_handle = strtol(argv[0], &endptr, 0);
  930. if (!endptr || *endptr != '\0' || !value_handle) {
  931. printf("Invalid value handle: %s\n", argv[0]);
  932. return;
  933. }
  934. id = bt_gatt_client_register_notify(cli->gatt, value_handle,
  935. register_notify_cb,
  936. notify_cb, NULL, NULL);
  937. if (!id) {
  938. printf("Failed to register notify handler\n");
  939. return;
  940. }
  941. printf("Registering notify handler with id: %u\n", id);
  942. }
  943. static void unregister_notify_usage(void)
  944. {
  945. printf("Usage: unregister-notify <notify id>\n");
  946. }
  947. static void cmd_unregister_notify(struct client *cli, char *cmd_str)
  948. {
  949. char *argv[2];
  950. int argc = 0;
  951. unsigned int id;
  952. char *endptr = NULL;
  953. if (!bt_gatt_client_is_ready(cli->gatt)) {
  954. printf("GATT client not initialized\n");
  955. return;
  956. }
  957. if (!parse_args(cmd_str, 1, argv, &argc) || argc != 1) {
  958. unregister_notify_usage();
  959. return;
  960. }
  961. id = strtol(argv[0], &endptr, 0);
  962. if (!endptr || *endptr != '\0' || !id) {
  963. printf("Invalid notify id: %s\n", argv[0]);
  964. return;
  965. }
  966. if (!bt_gatt_client_unregister_notify(cli->gatt, id)) {
  967. printf("Failed to unregister notify handler with id: %u\n", id);
  968. return;
  969. }
  970. printf("Unregistered notify handler with id: %u\n", id);
  971. }
  972. static void set_security_usage(void)
  973. {
  974. printf("Usage: set-security <level>\n"
  975. "level: 1-3\n"
  976. "e.g.:\n"
  977. "\tset-security 2\n");
  978. }
  979. static void cmd_set_security(struct client *cli, char *cmd_str)
  980. {
  981. char *argv[2];
  982. int argc = 0;
  983. char *endptr = NULL;
  984. int level;
  985. if (!bt_gatt_client_is_ready(cli->gatt)) {
  986. printf("GATT client not initialized\n");
  987. return;
  988. }
  989. if (!parse_args(cmd_str, 1, argv, &argc)) {
  990. printf("Too many arguments\n");
  991. set_security_usage();
  992. return;
  993. }
  994. if (argc < 1) {
  995. set_security_usage();
  996. return;
  997. }
  998. level = strtol(argv[0], &endptr, 0);
  999. if (!endptr || *endptr != '\0' || level < 1 || level > 3) {
  1000. printf("Invalid level: %s\n", argv[0]);
  1001. return;
  1002. }
  1003. if (!bt_gatt_client_set_security(cli->gatt, level))
  1004. printf("Could not set sec level\n");
  1005. else
  1006. printf("Setting security level %d success\n", level);
  1007. }
  1008. static void cmd_get_security(struct client *cli, char *cmd_str)
  1009. {
  1010. int level;
  1011. if (!bt_gatt_client_is_ready(cli->gatt)) {
  1012. printf("GATT client not initialized\n");
  1013. return;
  1014. }
  1015. level = bt_gatt_client_get_security(cli->gatt);
  1016. if (level < 0)
  1017. printf("Could not set sec level\n");
  1018. else
  1019. printf("Security level: %u\n", level);
  1020. }
  1021. static bool convert_sign_key(char *optarg, uint8_t key[16])
  1022. {
  1023. int i;
  1024. if (strlen(optarg) != 32) {
  1025. printf("sign-key length is invalid\n");
  1026. return false;
  1027. }
  1028. for (i = 0; i < 16; i++) {
  1029. if (sscanf(optarg + (i * 2), "%2hhx", &key[i]) != 1)
  1030. return false;
  1031. }
  1032. return true;
  1033. }
  1034. static void set_sign_key_usage(void)
  1035. {
  1036. printf("Usage: set-sign-key [options]\nOptions:\n"
  1037. "\t -c, --sign-key <csrk>\tCSRK\n"
  1038. "e.g.:\n"
  1039. "\tset-sign-key -c D8515948451FEA320DC05A2E88308188\n");
  1040. }
  1041. static bool local_counter(uint32_t *sign_cnt, void *user_data)
  1042. {
  1043. static uint32_t cnt = 0;
  1044. *sign_cnt = cnt++;
  1045. return true;
  1046. }
  1047. static void cmd_set_sign_key(struct client *cli, char *cmd_str)
  1048. {
  1049. char *argv[3];
  1050. int argc = 0;
  1051. uint8_t key[16];
  1052. memset(key, 0, 16);
  1053. if (!parse_args(cmd_str, 2, argv, &argc)) {
  1054. set_sign_key_usage();
  1055. return;
  1056. }
  1057. if (argc != 2) {
  1058. set_sign_key_usage();
  1059. return;
  1060. }
  1061. if (!strcmp(argv[0], "-c") || !strcmp(argv[0], "--sign-key")) {
  1062. if (convert_sign_key(argv[1], key))
  1063. bt_att_set_local_key(cli->att, key, local_counter, cli);
  1064. } else
  1065. set_sign_key_usage();
  1066. }
  1067. static void cmd_help(struct client *cli, char *cmd_str);
  1068. typedef void (*command_func_t)(struct client *cli, char *cmd_str);
  1069. static struct {
  1070. char *cmd;
  1071. command_func_t func;
  1072. char *doc;
  1073. } command[] = {
  1074. { "help", cmd_help, "\tDisplay help message" },
  1075. { "services", cmd_services, "\tShow discovered services" },
  1076. { "read-value", cmd_read_value,
  1077. "\tRead a characteristic or descriptor value" },
  1078. { "read-long-value", cmd_read_long_value,
  1079. "\tRead a long characteristic or desctriptor value" },
  1080. { "read-multiple", cmd_read_multiple, "\tRead Multiple" },
  1081. { "write-value", cmd_write_value,
  1082. "\tWrite a characteristic or descriptor value" },
  1083. { "write-long-value", cmd_write_long_value,
  1084. "Write long characteristic or descriptor value" },
  1085. { "write-prepare", cmd_write_prepare,
  1086. "\tWrite prepare characteristic or descriptor value" },
  1087. { "write-execute", cmd_write_execute,
  1088. "\tExecute already prepared write" },
  1089. { "register-notify", cmd_register_notify,
  1090. "\tSubscribe to not/ind from a characteristic" },
  1091. { "unregister-notify", cmd_unregister_notify,
  1092. "Unregister a not/ind session"},
  1093. { "set-security", cmd_set_security,
  1094. "\tSet security level on le connection"},
  1095. { "get-security", cmd_get_security,
  1096. "\tGet security level on le connection"},
  1097. { "set-sign-key", cmd_set_sign_key,
  1098. "\tSet signing key for signed write command"},
  1099. { }
  1100. };
  1101. static void cmd_help(struct client *cli, char *cmd_str)
  1102. {
  1103. int i;
  1104. printf("Commands:\n");
  1105. for (i = 0; command[i].cmd; i++)
  1106. printf("\t%-15s\t%s\n", command[i].cmd, command[i].doc);
  1107. }
  1108. static void prompt_read_cb(int fd, uint32_t events, void *user_data)
  1109. {
  1110. ssize_t read;
  1111. size_t len = 0;
  1112. char *line = NULL;
  1113. char *cmd = NULL, *args;
  1114. struct client *cli = user_data;
  1115. int i;
  1116. if (events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR)) {
  1117. mainloop_quit();
  1118. return;
  1119. }
  1120. if ((read = getline(&line, &len, stdin)) == -1)
  1121. return;
  1122. if (read <= 1) {
  1123. cmd_help(cli, NULL);
  1124. print_prompt();
  1125. return;
  1126. }
  1127. line[read-1] = '\0';
  1128. args = line;
  1129. while ((cmd = strsep(&args, " \t")))
  1130. if (*cmd != '\0')
  1131. break;
  1132. if (!cmd)
  1133. goto failed;
  1134. for (i = 0; command[i].cmd; i++) {
  1135. if (strcmp(command[i].cmd, cmd) == 0)
  1136. break;
  1137. }
  1138. if (command[i].cmd)
  1139. command[i].func(cli, args);
  1140. else
  1141. fprintf(stderr, "Unknown command: %s\n", line);
  1142. failed:
  1143. print_prompt();
  1144. free(line);
  1145. }
  1146. static void signal_cb(int signum, void *user_data)
  1147. {
  1148. switch (signum) {
  1149. case SIGINT:
  1150. case SIGTERM:
  1151. mainloop_quit();
  1152. break;
  1153. default:
  1154. break;
  1155. }
  1156. }
  1157. static int l2cap_le_att_connect(bdaddr_t *src, bdaddr_t *dst, uint8_t dst_type,
  1158. int sec)
  1159. {
  1160. int sock;
  1161. struct sockaddr_l2 srcaddr, dstaddr;
  1162. struct bt_security btsec;
  1163. if (verbose) {
  1164. char srcaddr_str[18], dstaddr_str[18];
  1165. ba2str(src, srcaddr_str);
  1166. ba2str(dst, dstaddr_str);
  1167. printf("btgatt-client: Opening L2CAP LE connection on ATT "
  1168. "channel:\n\t src: %s\n\tdest: %s\n",
  1169. srcaddr_str, dstaddr_str);
  1170. }
  1171. sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
  1172. if (sock < 0) {
  1173. perror("Failed to create L2CAP socket");
  1174. return -1;
  1175. }
  1176. /* Set up source address */
  1177. memset(&srcaddr, 0, sizeof(srcaddr));
  1178. srcaddr.l2_family = AF_BLUETOOTH;
  1179. srcaddr.l2_cid = htobs(ATT_CID);
  1180. srcaddr.l2_bdaddr_type = 0;
  1181. bacpy(&srcaddr.l2_bdaddr, src);
  1182. if (bind(sock, (struct sockaddr *)&srcaddr, sizeof(srcaddr)) < 0) {
  1183. perror("Failed to bind L2CAP socket");
  1184. close(sock);
  1185. return -1;
  1186. }
  1187. /* Set the security level */
  1188. memset(&btsec, 0, sizeof(btsec));
  1189. btsec.level = sec;
  1190. if (setsockopt(sock, SOL_BLUETOOTH, BT_SECURITY, &btsec,
  1191. sizeof(btsec)) != 0) {
  1192. fprintf(stderr, "Failed to set L2CAP security level\n");
  1193. close(sock);
  1194. return -1;
  1195. }
  1196. /* Set up destination address */
  1197. memset(&dstaddr, 0, sizeof(dstaddr));
  1198. dstaddr.l2_family = AF_BLUETOOTH;
  1199. dstaddr.l2_cid = htobs(ATT_CID);
  1200. dstaddr.l2_bdaddr_type = dst_type;
  1201. bacpy(&dstaddr.l2_bdaddr, dst);
  1202. printf("Connecting to device...");
  1203. fflush(stdout);
  1204. if (connect(sock, (struct sockaddr *) &dstaddr, sizeof(dstaddr)) < 0) {
  1205. perror(" Failed to connect");
  1206. close(sock);
  1207. return -1;
  1208. }
  1209. printf(" Done\n");
  1210. return sock;
  1211. }
  1212. static void usage(void)
  1213. {
  1214. printf("btgatt-client\n");
  1215. printf("Usage:\n\tbtgatt-client [options]\n");
  1216. printf("Options:\n"
  1217. "\t-i, --index <id>\t\tSpecify adapter index, e.g. hci0\n"
  1218. "\t-d, --dest <addr>\t\tSpecify the destination address\n"
  1219. "\t-t, --type [random|public] \tSpecify the LE address type\n"
  1220. "\t-m, --mtu <mtu> \t\tThe ATT MTU to use\n"
  1221. "\t-s, --security-level <sec> \tSet security level (low|medium|"
  1222. "high|fips)\n"
  1223. "\t-v, --verbose\t\t\tEnable extra logging\n"
  1224. "\t-h, --help\t\t\tDisplay help\n");
  1225. }
  1226. static struct option main_options[] = {
  1227. { "index", 1, 0, 'i' },
  1228. { "dest", 1, 0, 'd' },
  1229. { "type", 1, 0, 't' },
  1230. { "mtu", 1, 0, 'm' },
  1231. { "security-level", 1, 0, 's' },
  1232. { "verbose", 0, 0, 'v' },
  1233. { "help", 0, 0, 'h' },
  1234. { }
  1235. };
  1236. int main(int argc, char *argv[])
  1237. {
  1238. int opt;
  1239. int sec = BT_SECURITY_LOW;
  1240. uint16_t mtu = 0;
  1241. uint8_t dst_type = BDADDR_LE_PUBLIC;
  1242. bool dst_addr_given = false;
  1243. bdaddr_t src_addr, dst_addr;
  1244. int dev_id = -1;
  1245. int fd;
  1246. struct client *cli;
  1247. while ((opt = getopt_long(argc, argv, "+hvs:m:t:d:i:",
  1248. main_options, NULL)) != -1) {
  1249. switch (opt) {
  1250. case 'h':
  1251. usage();
  1252. return EXIT_SUCCESS;
  1253. case 'v':
  1254. verbose = true;
  1255. break;
  1256. case 's':
  1257. if (strcmp(optarg, "low") == 0)
  1258. sec = BT_SECURITY_LOW;
  1259. else if (strcmp(optarg, "medium") == 0)
  1260. sec = BT_SECURITY_MEDIUM;
  1261. else if (strcmp(optarg, "high") == 0)
  1262. sec = BT_SECURITY_HIGH;
  1263. else if (strcmp(optarg, "fips") == 0)
  1264. sec = BT_SECURITY_FIPS;
  1265. else {
  1266. fprintf(stderr, "Invalid security level\n");
  1267. return EXIT_FAILURE;
  1268. }
  1269. break;
  1270. case 'm': {
  1271. int arg;
  1272. arg = atoi(optarg);
  1273. if (arg <= 0) {
  1274. fprintf(stderr, "Invalid MTU: %d\n", arg);
  1275. return EXIT_FAILURE;
  1276. }
  1277. if (arg > UINT16_MAX) {
  1278. fprintf(stderr, "MTU too large: %d\n", arg);
  1279. return EXIT_FAILURE;
  1280. }
  1281. mtu = (uint16_t)arg;
  1282. break;
  1283. }
  1284. case 't':
  1285. if (strcmp(optarg, "random") == 0)
  1286. dst_type = BDADDR_LE_RANDOM;
  1287. else if (strcmp(optarg, "public") == 0)
  1288. dst_type = BDADDR_LE_PUBLIC;
  1289. else {
  1290. fprintf(stderr,
  1291. "Allowed types: random, public\n");
  1292. return EXIT_FAILURE;
  1293. }
  1294. break;
  1295. case 'd':
  1296. if (str2ba(optarg, &dst_addr) < 0) {
  1297. fprintf(stderr, "Invalid remote address: %s\n",
  1298. optarg);
  1299. return EXIT_FAILURE;
  1300. }
  1301. dst_addr_given = true;
  1302. break;
  1303. case 'i':
  1304. dev_id = hci_devid(optarg);
  1305. if (dev_id < 0) {
  1306. perror("Invalid adapter");
  1307. return EXIT_FAILURE;
  1308. }
  1309. break;
  1310. default:
  1311. fprintf(stderr, "Invalid option: %c\n", opt);
  1312. return EXIT_FAILURE;
  1313. }
  1314. }
  1315. if (!argc) {
  1316. usage();
  1317. return EXIT_SUCCESS;
  1318. }
  1319. argc -= optind;
  1320. argv += optind;
  1321. optind = 0;
  1322. if (argc) {
  1323. usage();
  1324. return EXIT_SUCCESS;
  1325. }
  1326. if (dev_id == -1)
  1327. bacpy(&src_addr, BDADDR_ANY);
  1328. else if (hci_devba(dev_id, &src_addr) < 0) {
  1329. perror("Adapter not available");
  1330. return EXIT_FAILURE;
  1331. }
  1332. if (!dst_addr_given) {
  1333. fprintf(stderr, "Destination address required!\n");
  1334. return EXIT_FAILURE;
  1335. }
  1336. mainloop_init();
  1337. fd = l2cap_le_att_connect(&src_addr, &dst_addr, dst_type, sec);
  1338. if (fd < 0)
  1339. return EXIT_FAILURE;
  1340. cli = client_create(fd, mtu);
  1341. if (!cli) {
  1342. close(fd);
  1343. return EXIT_FAILURE;
  1344. }
  1345. if (mainloop_add_fd(fileno(stdin),
  1346. EPOLLIN | EPOLLRDHUP | EPOLLHUP | EPOLLERR,
  1347. prompt_read_cb, cli, NULL) < 0) {
  1348. fprintf(stderr, "Failed to initialize console\n");
  1349. return EXIT_FAILURE;
  1350. }
  1351. print_prompt();
  1352. mainloop_run_with_signal(signal_cb, NULL);
  1353. printf("\n\nShutting down...\n");
  1354. client_destroy(cli);
  1355. return EXIT_SUCCESS;
  1356. }