📄 btctl.c
字号:
}, {"auth", cmd_auth, 0, "<address>", "authenticate remote device\n" }, {"pkt_type", cmd_pkttype, 0, "[<0xXXX> | <mnemonic>]", "\tmnemonic: DM1 DH1 DM3 DH3 DM5 DH5 HV1 HV2 HV3>]\n" }, {"page_to", cmd_control, 0, "[to]", "get/set page timeout\n" }, {"hdisc", cmd_control, 1, "<handle | address>", "disconnect ACL/SCO link\n" }, {"hconnect", cmd_control, 2, "<address>", "create ACL connection\n" }, {"hpkt", cmd_control, 3, "<address> [pkt_type]", "change pkt_type\n" }, {"readbroad", cmd_control, 4, "", "Read Broadcast Retransmissions\n" }, {"writebroad", cmd_control, 5, "", "Write Broadcast Retransmissions\n" }, {"reset", cmd_reset, 0, "", "reset device\n" }, {"ping", cmd_ping, 0, "<bda> <size>", "Send ping packet to remote device\n" }, {"lq", cmd_link_info, 0, "<bda>", "Show link quality\n" }, {"rssi", cmd_link_info, 1, "<bda>", "Show Received Signal Strength Indication (RSSI)\n" }, {"cpl", cmd_link_info, 2, "<bda>", "Show Current Transmit Power Level (CTPL)\n" }, {"linkinfo", cmd_link_info, 3, "<bda> [<interval>]", "Show HCI debug dump\n" }, {"pinq_start", cmd_periodic_inquiry, 0, "<length> [<max_period_len> <min_period_len> <len>]", "Start periodic inquiry mode\n" }, {"pinq_stop", cmd_periodic_inquiry, 1, "<length>", "Stop periodic inquiry mode start\n" }, {"speed", cmd_ping, 1, }, /* UART */#if defined(CONFIG_AFFIX_UART) {0, 0, 0, 0, "---->>>> UART commands <<<<----\n"}, {"init_uart", cmd_uart, CMD_INIT_UART, "<name> <vendor> [speed] [flags]", "open UART interface\n" "\tvendor: any|csr|ericsson|...]\n" }, {"open_uart", cmd_uart, CMD_OPEN_UART, "<name> <vendor> [speed] [flags]", "open UART interface\n" "\tvendor: any|csr|ericsson|...]\n" }, {"close_uart", cmd_uart, CMD_CLOSE_UART, "<name>" },#else#endif /* AUDIO */#if defined(CONFIG_AFFIX_AUDIO) {0, 0, 0, 0, "---->>>> AUDIO commands <<<<----\n"}, {"path", cmd_audio, 0, "0x00 | 0x01", "set Ericsson SCO data path" }, {"audio", cmd_audio, 1, "on|off [sync | async] [setting <SCO setting>]", "enable/disable audio (SCO) support\n" }, {"scoflow", cmd_audio, 2, }, {"addsco", cmd_addsco, 0, }, {"play", cmd_play, 0, "<bda> [<file> | -]", "send an audio stream from a file or stdin to remote device\n" }, {"record", cmd_record, 0, "<bda> [<file> | -]", "store an audio stream in a file or stdout received from remote device\n" },#else#endif /* RFCOMM */#if defined(CONFIG_AFFIX_RFCOMM) || defined(CONFIG_AFFIX_RFCOMM_MOD) {0, 0, 0, 0, "---->>>> RFCOMM commands <<<<----\n"}, {"port", cmd_connect, 0, "<address> [channel | service]", "Make SDP request to get RFCOMM server channel for a service" }, {"connect", cmd_connect, 1, "<address> [channel | service] [line number]", "create RFCOMM connection.\n" "\tservice_type: SERial | DUN | FAX | LAN | HEAdset.\n" }, {"bind", cmd_connect, 2, "<address> [channel | service] [line number]", "bind RFCOMM connection.\n" }, {"disconnect", cmd_disconnect, 1, "[line]", "disconnect RFCOMM port\n" }, {"status", cmd_status, 1, "", "shows connected lines\n" },#else#endif /* SDP */#if defined(CONFIG_AFFIX_SDP) {0, 0, 0, 0, "---->>>> SDP commands <<<<----\n"}, {"browse", cmd_browse, 0, "<address>", "browse for services on remote device\n" }, {"search", cmd_search, 0, "<address>", "search for services on remote device\n" "notes: used if browse does not find anything, because\n" "some devices does not suport browseing\n" },#else#endif /* OBEX */#if defined(CONFIG_AFFIX_OBEX) {0, 0, 0, 0, "---->>>> OBEX commands <<<<----\n"}, {"ftp", cmd_prompt, 0, "", "enter interactive mode\n" }, {"open", cmd_open, 0, "<address> [<channel>]", "open connection to obex ftp server\n" }, {"close", cmd_close, 0, "", "close connection to obex ftp server\n" }, {"ls", cmd_ls, 0, "[<address> [<channel>]]" }, {"put", cmd_put, 0, "[<address> [<channel>]] <local-file> [remote-file]" }, {"get", cmd_get, 0, "[<address> [<channel>]] <remote-file> [local-file]" }, {"push", cmd_push, 0, "<address> [<channel>] <local-file> [remote-file]" }, {"rm", cmd_rm, 0, "[<address> [<channel>]] <remote-file>" }, {"cd", cmd_cd, 0, "<dir name>" }, {"mkdir", cmd_mkdir, 0, "<dir name>" },#else#endif /* PAN */#if defined(CONFIG_AFFIX_PAN) || defined(CONFIG_AFFIX_PAN_MOD) {0, 0, 0, 0, "---->>>> PAN commands <<<<----\n"}, {"paninit", cmd_pan_init, CMD_PAN_INIT, "[role] [flags]", "\tinitialize PAN\n" "\trole: panu, nap, gn\n" }, {"panstop", cmd_pan_init, CMD_PAN_STOP, "", "\tstop PAN\n" }, {"pandiscovery", cmd_pan_discovery, 0, "[service]", "discover PAN device.\n" "service: panu, nap, gn\n" }, {"panconnect", cmd_pan_connect, 0, "<address> [service]", "connects to the NAP service.\n" "service: nap, gn\n" }, {"pandisconnect", cmd_pan_disconnect, 0, "", "close connection to connected service.\n" }, {"panctl", cmd_panctl, 2, "<interface> [m (start_addr stop_addr)* ] [p (range_start range_stop)* ]", "Examples:\n" "\t1. lists all filters of PAN device pan0:\n" "\t panctl pan0\n" "\t2. set multicast filter to 03:00:00:20:00:00 only:\n" "\t panctl pan0 m 03:00:00:20:00:00 03:00:00:20:00:00\n" "\t3. set protocol filter to range 0x800 - 0x801 and 0x806\n" "\t panctl pan0 p 0x800 0x801 0x806 0x806\n" "\t4. reset protocol filter\n" "\t panctl pan0 p\n" },#else#endif {0, 0, 0, 0, "---->>>> Testing commands <<<<----\n"}, {"test", cmd_test, 0, }, {"switch", cmd_switch, 0, }, {"policy", cmd_switch, 1, }, {0, 0, 0, NULL}};int cmdnum = sizeof(cmds)/sizeof(cmds[0]);void print_help(struct btctl_command *cmd){ if (cmd->name) printf("usage: %s %s\n", cmd->name, cmd->arg?cmd->arg:""); if (cmd->msg) printf("description:\n%s", cmd->msg);}void print_usage(struct btctl_command *cmd){ printf("usage: %s %s\n", cmd->name, cmd->arg?cmd->arg:"");}int cmd_help(struct btctl_command *cmd){ int i; if (!argv[argind]) { print_usage(cmd); exit(0); } for (i = 0; i < cmdnum; i++) { if (cmds[i].name) if (strcmp(cmds[i].name, argv[argind]) == 0) { print_help(&cmds[i]); return 0; } } printf("invalid command: %s\n", argv[argind]); return 0;}void usage(void){ int i; printf("Usage: btctl [-i <name>] [-a] [--nosdp | -s] [<command> [parameters..]>\n"); for (i = 0; i < cmdnum; i++) { if (cmds[i].name && cmds[i].arg) printf("%s %s\n", cmds[i].name, cmds[i].arg); else if (cmds[i].msg) printf("%s", cmds[i].msg); } printf("\n" "Notes:\n" "\t1. *address* argument can be replaced by cache entry number (btctl list)\n" "\t2. *--nosdp* option required to manually define server channel\n" "\t3. use *search* command if *browse* returns nothing\n" "\t4. argument *channel* is not used in SDP mode\n" "\t5. arguments *address* and *channel* are not used with\n" "\t commands: *ls*, *get*, *put*, *rm* in FTP (prompt) mode\n" "\n" );}/* Command line mode */static inline int white_space(char c){ return (c == ' ' || c == '\t');}static inline int end_line(char c){ return (c == '\n' || c == '\0');}static inline char *find_non_white(char *str){ while (white_space(*str)) str++; return (!end_line(*str)?str:NULL);}static inline char *find_white(char *str){ while (!end_line(*str) && !white_space(*str)) str++; return str;}static inline char *find_char(char *str, char c){ while (*str && *str != c) str++; return (*str?str:NULL);}char *get_string(char **str){ char *first, *next; int quotes = 0; if (*str == NULL) return NULL; first = find_non_white(*str); if (first == NULL) return NULL; if (*first == '"') { quotes = 1; first++; } next = first; if (quotes) { next = find_char(next, '"'); if (!next) { printf("parse error\n"); return NULL; } *next = '\0'; next++; } else { next = find_white(next); if (*next) { *next = '\0'; next++; } } if (*next) next = find_non_white(next); *str = next; return first;}char **parse_command_line(char *str){ static char *_argv[32]; // for 32 arguments char *arg; int i; _argv[0] = argv[0]; for (i = 1; (arg = get_string(&str)) ; i++) { _argv[i] = arg; //printf("argv[%d]: %s\n", i, arg); } _argv[i] = NULL; return (i>1)?_argv:NULL;}sigjmp_buf sigj;void signal_handler(int sig){ if (sig == SIGINT) { printf("\n"); siglongjmp(sigj, 0); } BTINFO("Sig handler : %d", sig);#if defined(CONFIG_AFFIX_OBEX) cmd_close(0);#endif printf("Terminating on signal (%d) ...\n", sig); exit(0);}int cmd_prompt(struct btctl_command *_cmd){ char cmd_line[80], *str, **cmd; int err; affix_logmask |= 0xffff;//BTDEBUG_MODULE_OBEX; ftpmode = 1; /* install signal handlers to unregister services from SDP */ signal(SIGCHLD, SIG_IGN); signal(SIGINT, signal_handler); // CTRL-C signal(SIGTERM, signal_handler); signal(SIGABRT, signal_handler); signal(SIGQUIT, signal_handler); printf("Affix version: %s\n", affix_version); printf("Wellcome to OBEX ftp. Type ? for help.\n"); printf("Mode: %s\n", linkmode == PF_INET ? "TCP" : "Bluetooth"); printf("SDP: %s\n", sdpmode?"yes":"no"); for (;;) { sigsetjmp(sigj, 1); printf("ftp> "); // get a line str = fgets(cmd_line, 80, stdin); //str = readline("ftp> "); if (str == NULL) { //printf("\n"); break; } //printf("got: %s, len: %d\n", str, strlen(str)); cmd = parse_command_line(str); if (cmd == NULL) continue; argv = cmd++; argind = 2; if (strcasecmp(*cmd, "quit") == 0) { printf("Bye!!!\n"); break; } else if (strcasecmp(*cmd, "mode") == 0) { if (argv[argind]) { if (strcasecmp(argv[argind], "tcp") == 0) linkmode = PF_INET; else linkmode = PF_AFFIX; } printf("Mode: %s\n", linkmode == PF_INET ? "TCP" : "Bluetooth"); } else if (strcasecmp(*cmd, "lls") == 0) { system("ls"); } else if (strcasecmp(*cmd, "lcd") == 0) { char *name; if (argv[argind] == NULL) { printf("No dir name.\n"); continue; } name = argv[argind]; chdir(name); } else if (strcasecmp(*cmd, "debug") == 0) { affix_logmask |= 0xffff;//BTDEBUG_MODULE_OBEX; } else if (strcasecmp(*cmd, "?") == 0 || strcasecmp(*cmd, "help") == 0) { usage(); } else if (strcasecmp(*cmd, "sdp") == 0) { sdpmode = !sdpmode; printf("sdp: %s\n", sdpmode?"yes":"no"); } else { int i; for (i = 0; i < cmdnum || (printf("Invalid command.\n") && 0); i++) if (cmds[i].name) if (strcmp(cmds[i].name, *cmd) == 0) { err = cmds[i].func(&cmds[i]); break; } } }#if defined(CONFIG_AFFIX_OBEX) cmd_close(0);#endif printf("Terminating ...\n"); ftpmode = 0; return 0;}int main(int _argc, char **_argv){ int c, lind, i, err = 0; char cachefile[80]; struct option opts[] = { {"help", 0, 0, 'h'}, {"tcp", 0, 0, 't'}, {"nosdp", 0, 0, 's'}, {"speed", 1, 0, 'r'}, {"version", 0, 0, 'V'}, {0, 0, 0, 0} }; if (affix_init()) { fprintf(stderr, "Affix initialization failed\n"); return 1; } /* set environment */ argc = _argc; argv = _argv; openlog(_argv[0], LOG_PERROR, LOG_USER); if (getuid() == 0) { /* root -> put the stuff to /var/spool/affix */ sprintf(confdir, "/var/spool/affix"); } else sprintf(confdir, "%s/.bluetooth", getenv("HOME")); err = rmkdir(confdir, 0700); if (err < 0) { perror("Unable to create dir\n"); return 1; } sprintf(cachefile, "%s/devcache", confdir); devcache = &_devcache; btdev_cache_load(cachefile, devcache);#if defined(CONFIG_AFFIX_SDP) sdpmode = 1;#else sdpmode = 0;#endif for (;;) { c = getopt_long(argc, argv, "+htrvsVam:i:r:", opts, &lind); if (c == -1) break; switch (c) { case 'h': usage(); return 0; break; case 'v': verbose = 1; break; case 'i': strncpy(btdev, optarg, IFNAMSIZ); break; case 't': linkmode = PF_INET; break; case 's': sdpmode = 0; break; case 'a': showall = 1; break; case 'r': uart_rate = atoi(optarg); break; case 'm': uart_map = optarg; break; case 'V': printf("Affix version: %s\n", affix_version); return 0; break; case ':': printf("Missing parameters for option: %c\n", optopt); return 1; break; case '?': printf("Unknown option: %c\n", optopt); return 1; break; } } affix_logmask = 0xffff; argind = optind; if (argv[argind] && sscanf(argv[argind], "bt%d", &i) > 0) { /* interface name */ sprintf(btdev, "bt%d", i); argind++; nameset = 1; } if (strcmp(argv[0], "btftp") == 0) { err = cmd_prompt(NULL); goto exit; } if (argv[argind] == NULL) { err = devinfo(); goto exit; } for (i = 0; i < cmdnum; i++) { if (cmds[i].name) if (strcmp(cmds[i].name, argv[argind]) == 0) { argind++; err = cmds[i].func(&cmds[i]); break; } } if (i == cmdnum) printf("Invalid command: %s\n", argv[argind]);exit: btdev_cache_free(devcache); return err;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -