1 /* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2010 Nokia Corporation 6 * Copyright (C) 2010 Marcel Holtmann <marcel (at) holtmann.org> 7 * 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 * 23 */ 24 25 #ifdef HAVE_CONFIG_H 26 #include <config.h> 27 #endif 28 29 #include <errno.h> 30 #include <glib.h> 31 #include <stdlib.h> 32 #include <unistd.h> 33 34 #include <bluetooth/bluetooth.h> 35 #include <bluetooth/hci.h> 36 #include <bluetooth/hci_lib.h> 37 #include <bluetooth/uuid.h> 38 39 #include "att.h" 40 #include "btio.h" 41 #include "gattrib.h" 42 #include "gatt.h" 43 #include "gatttool.h" 44 45 static gchar *opt_src = NULL; 46 static gchar *opt_dst = NULL; 47 static gchar *opt_value = NULL; 48 static gchar *opt_sec_level = NULL; 49 static bt_uuid_t *opt_uuid = NULL; 50 static int opt_start = 0x0001; 51 static int opt_end = 0xffff; 52 static int opt_handle = -1; 53 static int opt_mtu = 0; 54 static int opt_psm = 0; 55 static int opt_offset = 0; 56 static gboolean opt_primary = FALSE; 57 static gboolean opt_characteristics = FALSE; 58 static gboolean opt_char_read = FALSE; 59 static gboolean opt_listen = FALSE; 60 static gboolean opt_char_desc = FALSE; 61 static gboolean opt_char_write = FALSE; 62 static gboolean opt_char_write_req = FALSE; 63 static gboolean opt_interactive = FALSE; 64 static GMainLoop *event_loop; 65 static gboolean got_error = FALSE; 66 static GSourceFunc operation; 67 68 struct characteristic_data { 69 GAttrib *attrib; 70 uint16_t start; 71 uint16_t end; 72 }; 73 74 static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data) 75 { 76 GAttrib *attrib = user_data; 77 uint8_t opdu[ATT_MAX_MTU]; 78 uint16_t handle, i, olen = 0; 79 80 handle = att_get_u16(&pdu[1]); 81 82 switch (pdu[0]) { 83 case ATT_OP_HANDLE_NOTIFY: 84 g_print("Notification handle = 0x%04x value: ", handle); 85 break; 86 case ATT_OP_HANDLE_IND: 87 g_print("Indication handle = 0x%04x value: ", handle); 88 break; 89 default: 90 g_print("Invalid opcode\n"); 91 return; 92 } 93 94 for (i = 3; i < len; i++) 95 g_print("%02x ", pdu[i]); 96 97 g_print("\n"); 98 99 if (pdu[0] == ATT_OP_HANDLE_NOTIFY) 100 return; 101 102 olen = enc_confirmation(opdu, sizeof(opdu)); 103 104 if (olen > 0) 105 g_attrib_send(attrib, 0, opdu[0], opdu, olen, NULL, NULL, NULL); 106 } 107 108 static gboolean listen_start(gpointer user_data) 109 { 110 GAttrib *attrib = user_data; 111 112 g_attrib_register(attrib, ATT_OP_HANDLE_NOTIFY, events_handler, 113 attrib, NULL); 114 g_attrib_register(attrib, ATT_OP_HANDLE_IND, events_handler, 115 attrib, NULL); 116 117 return FALSE; 118 } 119 120 static void connect_cb(GIOChannel *io, GError *err, gpointer user_data) 121 { 122 GAttrib *attrib; 123 124 if (err) { 125 g_printerr("%s\n", err->message); 126 got_error = TRUE; 127 g_main_loop_quit(event_loop); 128 } 129 130 attrib = g_attrib_new(io); 131 132 if (opt_listen) 133 g_idle_add(listen_start, attrib); 134 135 operation(attrib); 136 } 137 138 static void primary_all_cb(GSList *services, guint8 status, gpointer user_data) 139 { 140 GSList *l; 141 142 if (status) { 143 g_printerr("Discover all primary services failed: %s\n", 144 att_ecode2str(status)); 145 goto done; 146 } 147 148 for (l = services; l; l = l->next) { 149 struct att_primary *prim = l->data; 150 g_print("attr handle = 0x%04x, end grp handle = 0x%04x " 151 "uuid: %s\n", prim->start, prim->end, prim->uuid); 152 } 153 154 done: 155 g_main_loop_quit(event_loop); 156 } 157 158 static void primary_by_uuid_cb(GSList *ranges, guint8 status, 159 gpointer user_data) 160 { 161 GSList *l; 162 163 if (status != 0) { 164 g_printerr("Discover primary services by UUID failed: %s\n", 165 att_ecode2str(status)); 166 goto done; 167 } 168 169 for (l = ranges; l; l = l->next) { 170 struct att_range *range = l->data; 171 g_print("Starting handle: %04x Ending handle: %04x\n", 172 range->start, range->end); 173 } 174 175 done: 176 g_main_loop_quit(event_loop); 177 } 178 179 static gboolean primary(gpointer user_data) 180 { 181 GAttrib *attrib = user_data; 182 183 if (opt_uuid) 184 gatt_discover_primary(attrib, opt_uuid, primary_by_uuid_cb, 185 NULL); 186 else 187 gatt_discover_primary(attrib, NULL, primary_all_cb, NULL); 188 189 return FALSE; 190 } 191 192 static void char_discovered_cb(GSList *characteristics, guint8 status, 193 gpointer user_data) 194 { 195 GSList *l; 196 197 if (status) { 198 g_printerr("Discover all characteristics failed: %s\n", 199 att_ecode2str(status)); 200 goto done; 201 } 202 203 for (l = characteristics; l; l = l->next) { 204 struct att_char *chars = l->data; 205 206 g_print("handle = 0x%04x, char properties = 0x%02x, char value " 207 "handle = 0x%04x, uuid = %s\n", chars->handle, 208 chars->properties, chars->value_handle, chars->uuid); 209 } 210 211 done: 212 g_main_loop_quit(event_loop); 213 } 214 215 static gboolean characteristics(gpointer user_data) 216 { 217 GAttrib *attrib = user_data; 218 219 gatt_discover_char(attrib, opt_start, opt_end, opt_uuid, 220 char_discovered_cb, NULL); 221 222 return FALSE; 223 } 224 225 static void char_read_cb(guint8 status, const guint8 *pdu, guint16 plen, 226 gpointer user_data) 227 { 228 uint8_t value[ATT_MAX_MTU]; 229 int i, vlen; 230 231 if (status != 0) { 232 g_printerr("Characteristic value/descriptor read failed: %s\n", 233 att_ecode2str(status)); 234 goto done; 235 } 236 if (!dec_read_resp(pdu, plen, value, &vlen)) { 237 g_printerr("Protocol error\n"); 238 goto done; 239 } 240 g_print("Characteristic value/descriptor: "); 241 for (i = 0; i < vlen; i++) 242 g_print("%02x ", value[i]); 243 g_print("\n"); 244 245 done: 246 if (opt_listen == FALSE) 247 g_main_loop_quit(event_loop); 248 } 249 250 static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu, 251 guint16 plen, gpointer user_data) 252 { 253 struct characteristic_data *char_data = user_data; 254 struct att_data_list *list; 255 int i; 256 257 if (status == ATT_ECODE_ATTR_NOT_FOUND && 258 char_data->start != opt_start) 259 goto done; 260 261 if (status != 0) { 262 g_printerr("Read characteristics by UUID failed: %s\n", 263 att_ecode2str(status)); 264 goto done; 265 } 266 267 list = dec_read_by_type_resp(pdu, plen); 268 if (list == NULL) 269 goto done; 270 271 for (i = 0; i < list->num; i++) { 272 uint8_t *value = list->data[i]; 273 int j; 274 275 char_data->start = att_get_u16(value) + 1; 276 277 g_print("handle: 0x%04x \t value: ", att_get_u16(value)); 278 value += 2; 279 for (j = 0; j < list->len - 2; j++, value++) 280 g_print("%02x ", *value); 281 g_print("\n"); 282 } 283 284 att_data_list_free(list); 285 286 done: 287 g_free(char_data); 288 g_main_loop_quit(event_loop); 289 } 290 291 static gboolean characteristics_read(gpointer user_data) 292 { 293 GAttrib *attrib = user_data; 294 295 if (opt_uuid != NULL) { 296 struct characteristic_data *char_data; 297 298 char_data = g_new(struct characteristic_data, 1); 299 char_data->attrib = attrib; 300 char_data->start = opt_start; 301 char_data->end = opt_end; 302 303 gatt_read_char_by_uuid(attrib, opt_start, opt_end, opt_uuid, 304 char_read_by_uuid_cb, char_data); 305 306 return FALSE; 307 } 308 309 if (opt_handle <= 0) { 310 g_printerr("A valid handle is required\n"); 311 g_main_loop_quit(event_loop); 312 return FALSE; 313 } 314 315 gatt_read_char(attrib, opt_handle, opt_offset, char_read_cb, attrib); 316 317 return FALSE; 318 } 319 320 static void mainloop_quit(gpointer user_data) 321 { 322 uint8_t *value = user_data; 323 324 g_free(value); 325 g_main_loop_quit(event_loop); 326 } 327 328 static gboolean characteristics_write(gpointer user_data) 329 { 330 GAttrib *attrib = user_data; 331 uint8_t *value; 332 size_t len; 333 334 if (opt_handle <= 0) { 335 g_printerr("A valid handle is required\n"); 336 goto error; 337 } 338 339 if (opt_value == NULL || opt_value[0] == '\0') { 340 g_printerr("A value is required\n"); 341 goto error; 342 } 343 344 len = gatt_attr_data_from_string(opt_value, &value); 345 if (len == 0) { 346 g_printerr("Invalid value\n"); 347 goto error; 348 } 349 350 gatt_write_cmd(attrib, opt_handle, value, len, mainloop_quit, value); 351 352 return FALSE; 353 354 error: 355 g_main_loop_quit(event_loop); 356 return FALSE; 357 } 358 359 static void char_write_req_cb(guint8 status, const guint8 *pdu, guint16 plen, 360 gpointer user_data) 361 { 362 if (status != 0) { 363 g_printerr("Characteristic Write Request failed: " 364 "%s\n", att_ecode2str(status)); 365 goto done; 366 } 367 368 if (!dec_write_resp(pdu, plen)) { 369 g_printerr("Protocol error\n"); 370 goto done; 371 } 372 373 g_print("Characteristic value was written sucessfully\n"); 374 375 done: 376 if (opt_listen == FALSE) 377 g_main_loop_quit(event_loop); 378 } 379 380 static gboolean characteristics_write_req(gpointer user_data) 381 { 382 GAttrib *attrib = user_data; 383 uint8_t *value; 384 size_t len; 385 386 if (opt_handle <= 0) { 387 g_printerr("A valid handle is required\n"); 388 goto error; 389 } 390 391 if (opt_value == NULL || opt_value[0] == '\0') { 392 g_printerr("A value is required\n"); 393 goto error; 394 } 395 396 len = gatt_attr_data_from_string(opt_value, &value); 397 if (len == 0) { 398 g_printerr("Invalid value\n"); 399 goto error; 400 } 401 402 gatt_write_char(attrib, opt_handle, value, len, char_write_req_cb, 403 NULL); 404 405 return FALSE; 406 407 error: 408 g_main_loop_quit(event_loop); 409 return FALSE; 410 } 411 412 static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen, 413 gpointer user_data) 414 { 415 struct att_data_list *list; 416 guint8 format; 417 int i; 418 419 if (status != 0) { 420 g_printerr("Discover all characteristic descriptors failed: " 421 "%s\n", att_ecode2str(status)); 422 goto done; 423 } 424 425 list = dec_find_info_resp(pdu, plen, &format); 426 if (list == NULL) 427 goto done; 428 429 for (i = 0; i < list->num; i++) { 430 char uuidstr[MAX_LEN_UUID_STR]; 431 uint16_t handle; 432 uint8_t *value; 433 bt_uuid_t uuid; 434 435 value = list->data[i]; 436 handle = att_get_u16(value); 437 438 if (format == 0x01) 439 uuid = att_get_uuid16(&value[2]); 440 else 441 uuid = att_get_uuid128(&value[2]); 442 443 bt_uuid_to_string(&uuid, uuidstr, MAX_LEN_UUID_STR); 444 g_print("handle = 0x%04x, uuid = %s\n", handle, uuidstr); 445 } 446 447 att_data_list_free(list); 448 449 done: 450 if (opt_listen == FALSE) 451 g_main_loop_quit(event_loop); 452 } 453 454 static gboolean characteristics_desc(gpointer user_data) 455 { 456 GAttrib *attrib = user_data; 457 458 gatt_find_info(attrib, opt_start, opt_end, char_desc_cb, NULL); 459 460 return FALSE; 461 } 462 463 static gboolean parse_uuid(const char *key, const char *value, 464 gpointer user_data, GError **error) 465 { 466 if (!value) 467 return FALSE; 468 469 opt_uuid = g_try_malloc(sizeof(bt_uuid_t)); 470 if (opt_uuid == NULL) 471 return FALSE; 472 473 if (bt_string_to_uuid(opt_uuid, value) < 0) 474 return FALSE; 475 476 return TRUE; 477 } 478 479 static GOptionEntry primary_char_options[] = { 480 { "start", 's' , 0, G_OPTION_ARG_INT, &opt_start, 481 "Starting handle(optional)", "0x0001" }, 482 { "end", 'e' , 0, G_OPTION_ARG_INT, &opt_end, 483 "Ending handle(optional)", "0xffff" }, 484 { "uuid", 'u', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, 485 parse_uuid, "UUID16 or UUID128(optional)", "0x1801"}, 486 { NULL }, 487 }; 488 489 static GOptionEntry char_rw_options[] = { 490 { "handle", 'a' , 0, G_OPTION_ARG_INT, &opt_handle, 491 "Read/Write characteristic by handle(required)", "0x0001" }, 492 { "value", 'n' , 0, G_OPTION_ARG_STRING, &opt_value, 493 "Write characteristic value (required for write operation)", 494 "0x0001" }, 495 { "offset", 'o', 0, G_OPTION_ARG_INT, &opt_offset, 496 "Offset to long read characteristic by handle", "N"}, 497 {NULL}, 498 }; 499 500 static GOptionEntry gatt_options[] = { 501 { "primary", 0, 0, G_OPTION_ARG_NONE, &opt_primary, 502 "Primary Service Discovery", NULL }, 503 { "characteristics", 0, 0, G_OPTION_ARG_NONE, &opt_characteristics, 504 "Characteristics Discovery", NULL }, 505 { "char-read", 0, 0, G_OPTION_ARG_NONE, &opt_char_read, 506 "Characteristics Value/Descriptor Read", NULL }, 507 { "char-write", 0, 0, G_OPTION_ARG_NONE, &opt_char_write, 508 "Characteristics Value Write Without Response (Write Command)", 509 NULL }, 510 { "char-write-req", 0, 0, G_OPTION_ARG_NONE, &opt_char_write_req, 511 "Characteristics Value Write (Write Request)", NULL }, 512 { "char-desc", 0, 0, G_OPTION_ARG_NONE, &opt_char_desc, 513 "Characteristics Descriptor Discovery", NULL }, 514 { "listen", 0, 0, G_OPTION_ARG_NONE, &opt_listen, 515 "Listen for notifications and indications", NULL }, 516 { "interactive", 'I', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, 517 &opt_interactive, "Use interactive mode", NULL }, 518 { NULL }, 519 }; 520 521 static GOptionEntry options[] = { 522 { "adapter", 'i', 0, G_OPTION_ARG_STRING, &opt_src, 523 "Specify local adapter interface", "hciX" }, 524 { "device", 'b', 0, G_OPTION_ARG_STRING, &opt_dst, 525 "Specify remote Bluetooth address", "MAC" }, 526 { "mtu", 'm', 0, G_OPTION_ARG_INT, &opt_mtu, 527 "Specify the MTU size", "MTU" }, 528 { "psm", 'p', 0, G_OPTION_ARG_INT, &opt_psm, 529 "Specify the PSM for GATT/ATT over BR/EDR", "PSM" }, 530 { "sec-level", 'l', 0, G_OPTION_ARG_STRING, &opt_sec_level, 531 "Set security level. Default: low", "[low | medium | high]"}, 532 { NULL }, 533 }; 534 535 int main(int argc, char *argv[]) 536 { 537 GOptionContext *context; 538 GOptionGroup *gatt_group, *params_group, *char_rw_group; 539 GError *gerr = NULL; 540 GIOChannel *chan; 541 542 opt_sec_level = g_strdup("low"); 543 544 context = g_option_context_new(NULL); 545 g_option_context_add_main_entries(context, options, NULL); 546 547 /* GATT commands */ 548 gatt_group = g_option_group_new("gatt", "GATT commands", 549 "Show all GATT commands", NULL, NULL); 550 g_option_context_add_group(context, gatt_group); 551 g_option_group_add_entries(gatt_group, gatt_options); 552 553 /* Primary Services and Characteristics arguments */ 554 params_group = g_option_group_new("params", 555 "Primary Services/Characteristics arguments", 556 "Show all Primary Services/Characteristics arguments", 557 NULL, NULL); 558 g_option_context_add_group(context, params_group); 559 g_option_group_add_entries(params_group, primary_char_options); 560 561 /* Characteristics value/descriptor read/write arguments */ 562 char_rw_group = g_option_group_new("char-read-write", 563 "Characteristics Value/Descriptor Read/Write arguments", 564 "Show all Characteristics Value/Descriptor Read/Write " 565 "arguments", 566 NULL, NULL); 567 g_option_context_add_group(context, char_rw_group); 568 g_option_group_add_entries(char_rw_group, char_rw_options); 569 570 if (g_option_context_parse(context, &argc, &argv, &gerr) == FALSE) { 571 g_printerr("%s\n", gerr->message); 572 g_error_free(gerr); 573 } 574 575 if (opt_interactive) { 576 interactive(opt_src, opt_dst, opt_psm); 577 goto done; 578 } 579 580 if (opt_primary) 581 operation = primary; 582 else if (opt_characteristics) 583 operation = characteristics; 584 else if (opt_char_read) 585 operation = characteristics_read; 586 else if (opt_char_write) 587 operation = characteristics_write; 588 else if (opt_char_write_req) 589 operation = characteristics_write_req; 590 else if (opt_char_desc) 591 operation = characteristics_desc; 592 else { 593 gchar *help = g_option_context_get_help(context, TRUE, NULL); 594 g_print("%s\n", help); 595 g_free(help); 596 got_error = TRUE; 597 goto done; 598 } 599 600 chan = gatt_connect(opt_src, opt_dst, opt_sec_level, 601 opt_psm, opt_mtu, connect_cb); 602 if (chan == NULL) { 603 got_error = TRUE; 604 goto done; 605 } 606 607 event_loop = g_main_loop_new(NULL, FALSE); 608 609 g_main_loop_run(event_loop); 610 611 g_main_loop_unref(event_loop); 612 613 done: 614 g_option_context_free(context); 615 g_free(opt_src); 616 g_free(opt_dst); 617 g_free(opt_uuid); 618 g_free(opt_sec_level); 619 620 if (got_error) 621 exit(EXIT_FAILURE); 622 else 623 exit(EXIT_SUCCESS); 624 } 625