📄 sdptool.c
字号:
} } argc -= optind; argv += optind; if (argc < 1) { printf(add_help); return -1; } si.name = strdup(argv[0]); return add_service(0, &si);}/* Delete local service */int del_service(bdaddr_t *bdaddr, void *arg) { uint32_t handle, range = 0x0000ffff; sdp_list_t *attr; sdp_session_t *sess; sdp_record_t *rec; if (!arg) { printf("Record handle was not specified.\n"); return -1; } sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY); if (!sess) { printf("No local SDP server!\n"); return -1; } handle = strtoul((char *)arg, 0, 16); attr = sdp_list_append(0, &range); rec = sdp_service_attr_req(sess, handle, SDP_ATTR_REQ_RANGE, attr); sdp_list_free(attr, 0); if (!rec) { printf("Service Record not found.\n"); sdp_close(sess); return -1; } if (sdp_record_unregister(sess, rec)) { printf("Failed to unregister service record: %s\n", strerror(errno)); sdp_close(sess); return -1; } printf("Service Record deleted.\n"); sdp_close(sess); return 0;}static struct option del_options[] = { {"help", 0,0, 'h'}, {0, 0, 0, 0}};static char *del_help = "Usage:\n" "\tdel record_handle\n";int cmd_del(int argc, char **argv){ int opt; for_each_opt(opt, del_options, 0) { switch(opt) { default: printf(del_help); return -1; } } argc -= optind; argv += optind; if (argc < 1) { printf(del_help); return -1; } return del_service(0, argv[0]);}/* * Perform an inquiry and search/browse all peer found. */static void inquiry(handler_t handler, void *arg){ inquiry_info ii[20]; uint8_t count = 0; int i; printf("Inquiring ...\n"); if (sdp_general_inquiry(ii, 20, 8, &count) < 0) { printf("Inquiry failed\n"); return; } for (i=0; i<count; i++) handler(&ii[i].bdaddr, arg);}/* * Search for a specific SDP service */int do_search(bdaddr_t *bdaddr, struct search_context *context){ sdp_list_t *attrid, *search, *seq, *next; uint32_t range = 0x0000ffff; char str[20]; sdp_session_t *sess; if (!bdaddr) { inquiry(do_search, context); return 0; } sess = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY); ba2str(bdaddr, str); if (!sess) { printf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno)); return -1; } if (context->svc) printf("Searching for %s on %s ...\n", context->svc, str); else printf("Browsing %s ...\n", str); attrid = sdp_list_append(0, &range); search = sdp_list_append(0, &context->group); if (sdp_service_search_attr_req(sess, search, SDP_ATTR_REQ_RANGE, attrid, &seq)) { printf("Service Search failed: %s\n", strerror(errno)); sdp_close(sess); return -1; } sdp_list_free(attrid, 0); sdp_list_free(search, 0); for (; seq; seq = next) { sdp_record_t *rec = (sdp_record_t *) seq->data; struct search_context sub_context; if (context->tree) { /* Display full tree */ sdp_printf_service_attr(rec); } else { /* Display user friendly form */ print_service_attr(rec); } printf("\n"); if (sdp_get_group_id(rec, &sub_context.group) != -1) { /* Set the subcontext for browsing the sub tree */ memcpy(&sub_context, context, sizeof(struct search_context)); /* Browse the next level down if not done */ if (sub_context.group.value.uuid16 != context->group.value.uuid16) do_search(bdaddr, &sub_context); } next = seq->next; free(seq); sdp_record_free(rec); } sdp_close(sess); return 0;}static struct option browse_options[] = { {"help", 0,0, 'h'}, {"tree", 0,0, 't'}, {0, 0, 0, 0}};static char *browse_help = "Usage:\n" "\tbrowse [--tree] [bdaddr]\n";/* * Browse the full SDP database (i.e. list all services starting from the * root/top-level). */int cmd_browse(int argc, char **argv){ struct search_context context; int opt; /* Initialise context */ memset(&context, '\0', sizeof(struct search_context)); /* We want to browse the top-level/root */ sdp_uuid16_create(&(context.group), PUBLIC_BROWSE_GROUP); for_each_opt(opt, browse_options, 0) { switch(opt) { case 't': context.tree = 1; break; default: printf(browse_help); return -1; } } argc -= optind; argv += optind; if (argc >= 1) { bdaddr_t bdaddr; estr2ba(argv[0], &bdaddr); return do_search(&bdaddr, &context); } return do_search(0, &context);}static struct option search_options[] = { {"help", 0,0, 'h'}, {"bdaddr", 1,0, 'b'}, {"tree", 0,0, 't'}, {0, 0, 0, 0}};static char *search_help = "Usage:\n" "\tsearch [--bdaddr bdaddr] [--tree] SERVICE\n" "SERVICE is a name (string) or UUID (0x1002)\n";/* * Search for a specific SDP service * * Note : we should support multiple services on the command line : * sdptool search 0x0100 0x000f 0x1002 * (this would search a service supporting both L2CAP and BNEP directly in * the top level browse group) */int cmd_search(int argc, char **argv){ struct search_context context; uint16_t class = 0; bdaddr_t bdaddr; int has_addr = 0; int i; int opt; /* Initialise context */ memset(&context, '\0', sizeof(struct search_context)); for_each_opt(opt, search_options, 0) { switch(opt) { case 'b': estr2ba(optarg, &bdaddr); has_addr = 1; break; case 't': context.tree = 1; break; default: printf(search_help); return -1; } } argc -= optind; argv += optind; if (argc < 1) { printf(search_help); return -1; } /* Note : we need to find a way to support search combining * multiple services - Jean II */ context.svc = strdup(argv[0]); if (!strncasecmp(context.svc, "0x", 2)) { int num; /* This is a UUID16, just convert to int */ sscanf(context.svc + 2, "%X", &num); class = num; printf("Class 0x%X\n", class); } else { /* Convert class name to an UUID */ for (i=0; service[i].name; i++) if (strcasecmp(context.svc, service[i].name) == 0) { class = service[i].class; break; } if (!class) { printf("Unknown service %s\n", context.svc); return -1; } } sdp_uuid16_create(&context.group, class); if (has_addr) return do_search(&bdaddr, &context); return do_search(0, &context);}/* * Show how to get a specific SDP record by its handle. * Not really useful to the user, just show how it can be done... * Jean II */int get_service(bdaddr_t *bdaddr, struct search_context *context) { sdp_list_t *attrid; uint32_t range = 0x0000ffff; sdp_record_t *rec; sdp_session_t *session = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY); if (!session) { char str[20]; ba2str(bdaddr, str); printf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno)); return -1; } attrid = sdp_list_append(0, &range); rec = sdp_service_attr_req(session, context->handle, SDP_ATTR_REQ_RANGE, attrid); sdp_list_free(attrid, 0); sdp_close(session); if (!rec) { printf("Service get request failed.\n"); return -1; } if (context->tree) { /* Display full tree */ sdp_printf_service_attr(rec); } else { /* Display user friendly form */ print_service_attr(rec); } printf("\n"); sdp_record_free(rec); return 0;}static struct option get_options[] = { {"help", 0,0, 'h'}, {"bdaddr", 1,0, 'b'}, {"tree", 0,0, 't'}, {0, 0, 0, 0}};static char *get_help = "Usage:\n" "\tget [--tree] [--bdaddr bdaddr] record_handle\n";/* * Get a specific SDP record on the local SDP server */int cmd_get(int argc, char **argv){ struct search_context context; bdaddr_t bdaddr; int has_addr = 0; int opt; /* Initialise context */ memset(&context, '\0', sizeof(struct search_context)); for_each_opt(opt, get_options, 0) { switch(opt) { case 'b': estr2ba(optarg, &bdaddr); has_addr = 1; break; case 't': context.tree = 1; break; default: printf(get_help); return -1; } } argc -= optind; argv += optind; if (argc < 1) { printf(get_help); return -1; } /* Convert command line parameters */ context.handle = strtoul(argv[0], 0, 16); return get_service(has_addr? &bdaddr: BDADDR_LOCAL, &context);}struct { char *cmd; int (*func)(int argc, char **argv); char *doc;} command[] = { { "search", cmd_search, "Search for a service" }, { "browse", cmd_browse, "Browse all available services" }, { "add", cmd_add, "Add local service" }, { "del", cmd_del, "Delete local service" }, { "get", cmd_get, "Get local service" }, { "setattr", cmd_setattr, "Set/Add attribute to a SDP record" }, { "setseq", cmd_setseq, "Set/Add attribute sequence to a SDP record" }, { 0, 0, 0}};static void usage(void){ int i; printf("sdptool - SDP Tool v%s\n", VERSION); printf("Usage:\n" "\tsdptool [options] <command> [command parameters]\n"); printf("Options:\n" "\t--help\t\tDisplay help\n" "\t--source\tSpecify source interface\n"); printf("Commands:\n"); for (i=0; command[i].cmd; i++) printf("\t%-4s\t\t%s\n", command[i].cmd, command[i].doc); printf("\nServices:\n\t"); for (i=0; service[i].name; i++) printf("%s ", service[i].name); printf("\n");}static struct option main_options[] = { {"help", 0, 0, 'h'}, {"source", 1, 0, 'S'}, {0, 0, 0, 0}};int main(int argc, char **argv){ int opt, i; bacpy(&interface, BDADDR_ANY); while ((opt=getopt_long(argc, argv, "+hS:", main_options, 0)) != -1) { switch(opt) { case 'S': str2ba(optarg, &interface); break; case 'h': default: usage(); return -1; } } argc -= optind; argv += optind; optind = 0; if (argc < 1) { usage(); return -1; } for (i=0; command[i].cmd; i++) if (strncmp(command[i].cmd, argv[0], 4) == 0) return command[i].func(argc, argv); return -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -