📄 btsrv.c
字号:
err = HCI_LinkKeyRequestReply(fd, &evt->bda, btdev->link_key); } else { err = HCI_LinkKeyRequestNegativeReply(fd, &evt->bda); } if (err) { BTERROR("unable to set link key: %d", err); } btdev_cache_unlock(&btdevs); hci_close(fd); return err;}int event_link_key_notification(struct Link_Key_Notification_Event *evt, int devnum){ btdev_struct *btdev; if (!managekey) return 0; btdev_cache_reload(&btdevs); btdev = btdev_cache_add(&btdevs, &evt->bda); if (btdev == NULL) return -1; btdev->key_type = evt->Key_Type; memcpy(btdev->link_key, evt->Link_Key, 16); btdev->flags |= BTDEV_KEY; btdev_cache_save(&btdevs); return 0;}int event_handler(int fd){ __u8 buf[HCI_MAX_EVENT_SIZE]; int devnum; HCI_Event_Packet_Header *hdr = (void*)buf; hci_recv_event_any(fd, &devnum, buf, sizeof(buf)); DBPRT("got event: %#x, from: %d", hdr->EventCode, devnum); switch (hdr->EventCode) { case HCI_E_LINK_KEY_REQUEST: event_link_key_request((void*)hdr, devnum); break; case HCI_E_LINK_KEY_NOTIFICATION: event_link_key_notification((void*)hdr, devnum); break; case HCI_E_PIN_CODE_REQUEST: event_pin_code_request((void*)hdr, devnum); break; default: break; } return 0;}int message_handler(int fd){ __u8 buf[HCI_MAX_MSG_SIZE]; struct hci_msg_hdr *msg = (void*)(buf+1); int err; recv(fd, buf, sizeof(buf), 0); DBPRT("got message: %x", msg->opcode); if (msg->opcode == HCICTL_STATE_CHANGE) { struct hci_state_change *cmd = (void*)msg; if (cmd->event == HCIDEV_UP) { DBPRT("device is up\n"); err = btsrv_devconf(cmd->devnum); if (err) { BTERROR("Unable to configure device: %d", cmd->devnum); return err; } } } return 0;}int handle_input(void){ int i, err = 0; int fd_cnt; fd_set fds_read; int max_fd; for(;;) { FD_ZERO(&fds_read); max_fd = -1; /* set service fd */ for (i = 0; i < svcnums; i++) { if (services[i].running && services[i].srv_fd != -1) { FD_SET(services[i].srv_fd, &fds_read); if (max_fd < services[i].srv_fd) max_fd = services[i].srv_fd; } } /* set event fd */ FD_SET(efd, &fds_read); if (max_fd < efd) max_fd = efd; FD_SET(mfd, &fds_read); if (max_fd < mfd) max_fd = mfd; /* poll data */ fd_cnt = select(max_fd + 1, &fds_read, NULL, NULL, NULL); if (fd_cnt <= 0) { BTERROR("Select error"); err = -1; goto exit; } if (FD_ISSET(efd, &fds_read)) { event_handler(efd); } if (FD_ISSET(mfd, &fds_read)) { message_handler(mfd); } for (i = 0; fd_cnt && (i < svcnums); i++) { if (services[i].running && services[i].srv_fd != -1 && FD_ISSET(services[i].srv_fd, &fds_read)) { int newsock; struct sockaddr_affix caddr; socklen_t calen = sizeof(caddr); int pid; newsock = accept(services[i].srv_fd, (struct sockaddr*)&caddr, &calen); if (newsock == -1) { BTERROR("Accept error"); continue; } BTINFO("Connection from %s\nchannel %d (%s Profile)", bda2str(&caddr.bda), caddr.port, services[i].name); if (services[i].cmd[0] != '\0') { pid = fork(); if (pid < 0) { BTERROR("Fork error"); continue; } if (pid == 0) { int res, j; for (j = 0; j < svcnums; j++) close(services[j].srv_fd); res = execute_cmd(services[i].cmd, newsock, caddr.port, &caddr.bda, services[i].flags); /* In case of error.. */ exit(res); } } close(newsock); fd_cnt--; } } }exit: return err;}/* * read HCI events and kernel messages */int start_event_handler(void){ __u64 mask = 0; efd = hci_open_event(); if (efd < 0) { BTERROR("Unable to open hci(NULL)"); return efd; } mfd = hci_open_mgr(); if (mfd < 0) { BTERROR("Unable to open mgr"); close(efd); return mfd; } if (managepin) { hci_set_mode(mfd, AFFIX_MODE_PIN); mask |= PIN_CODE_REQUEST_MASK; } if (managekey) { hci_set_mode(mfd, AFFIX_MODE_KEY); mask |= LINK_KEY_NOTIFICATION_MASK | LINK_KEY_REQUEST_MASK; } if (mask) hci_event_mask(efd, mask); return 0;}void stop_event_handler(void){ close(mfd); close(efd);}int btsrv_setdev(int fd, device_t *dev){ int err; err = HCI_WriteSecurityMode(fd, dev->security); if (err < 0) { BTERROR("hci_set_secmode() failed\n"); return err; } err = hci_set_role(fd, dev->role); if (err < 0) { BTERROR("hci_set_role() failed\n"); return err; } err = hci_set_pkttype(fd, dev->pkt_type); if (err < 0) { BTERROR("hci_set_pkttype() failed\n"); return err; } err = HCI_WriteClassOfDevice(fd, dev->cod); if (err) { BTERROR("WriteScanEnable error\n"); return err; } if (dev->btname) { err = HCI_ChangeLocalName(fd, dev->btname); if (err) { BTERROR("WriteScanEnable error\n"); return err; } } err = HCI_WriteScanEnable(fd, dev->scan); if (err) { BTERROR("WriteScanEnable error\n"); return err; } return 0;}int btsrv_devconf(int devnum){ int err = 0, i, fd; device_t *dev; struct hci_dev_attr da; if (!initdev) return 0; err = hci_get_attr_id(devnum, &da); if (err) return err; fd = hci_open(da.name); if (fd < 0) { BTERROR("hci_open_id() failed: %s\n", da.name); return fd; } for (i = 0; i < devnums; i++) { dev = &devices[i]; if ((i == 0 && dev->name[0] == '*') || (strcasecmp(dev->name, da.name) == 0)) { err = btsrv_setdev(fd, dev); if (err) break; } } close(fd); return err;}int btsrv_devinit(void){ int i, err, num; int devs[HCI_MAX_DEVS]; struct hci_dev_attr da; num = hci_get_devs(devs); if (num < 0) { BTERROR("Unable to get device info\n"); return num; } for (i = 0; i < num; i++) { err = hci_get_attr_id(devs[i], &da); if (err < 0) { BTERROR("hci_get_attr() failed: %d\n", devs[i]); continue; } if (!(da.flags & HCI_FLAGS_UP)) continue; err = btsrv_devconf(da.devnum); if (err) return err; } return 0;}int btsrv_cleanup(void){ int i; device_t *dev; stop_event_handler(); stop_all_services(); BTINFO("Terminating ..");#if defined(CONFIG_AFFIX_SDP) sdpreg_cleanup();#endif free(config_file); for (i = 0; i < svcnums; i++) { if (services[i].name) free(services[i].name); if (services[i].prov) free(services[i].prov); if (services[i].desc) free(services[i].prov); } for (i = 0; i < devnums; i++) { dev = &devices[i]; if (dev->btname) free(dev->btname); } return 0;}void signal_handler(int sig){ BTINFO("Sig handler : %d", sig); btsrv_cleanup(); exit(0);}void get_cmd_opts(int argc, char **argv){ int c, lind = 0; struct option opts[] = { {"help", 0, 0, 'h'}, {"daemon", 0, 0, 'd'}, {"config", 1, 0, 'C'}, {"debug", 0, 0, 'v'}, {"initdev", 0, 0, 'i'}, {"noinitdev", 0, 0, 'I'}, {"startsvc", 0, 0, 's'}, {"nostartsvc", 0, 0, 'S'}, {"managepin", 0, 0, 'p'}, {"nomanagepin", 0, 0, 'P'}, {"managekey", 0, 0, 'k'}, {"nomanagekey", 0, 0, 'K'}, {"expression", 0, 0, 'e'}, {0, 0, 0, 0} }; optind = 0; for (;;) { c = getopt_long(argc, argv, "hdpskvC:e:", opts, &lind); if (c == -1) break; switch (c) { case 'h': printusage(); exit(0); break; case 'd': _daemon = 1; break; case 'C': config_file = strdup(optarg); break; case 'v': affix_logmask = BTDEBUG_MODULE; break; case 'p': managepin = 1; break; case 'P': managepin = 0; break; case 'k': managekey = 1; break; case 'K': managekey = 0; break; case 'i': initdev = 1; break; case 'I': initdev = 0; break; case 's': startsvc = 1; break; case 'S': startsvc = 0; break; case 'e': config_expr = strdup(optarg); break; case '?': fprintf(stderr, "Unknown option: %c\n", optopt); exit(1); break; } }}int main(int argc, char **argv){ int err; char cachefile[80]; openlog(NULL/*argv[0]*/, LOG_PERROR, LOG_DAEMON); BTINFO("%s started [%s].", argv[0], affix_version); if (affix_init()) { BTERROR("Affix initialization failed\n"); return 1; } affix_logmask = BTDEBUG_MODULE; // read first to get config_file get_cmd_opts(argc, argv); if (config_expr) { // use command line configuration if (btsrv_read_config_buf(config_expr, &svcnums, &devnums)) { BTERROR("Invalid config expr: %s", config_expr); return -1; } startsvc = 1; // default action for this } else { if (!config_file) config_file = strdup(DEF_CONFIG_FILE); // read config_file if (btsrv_read_config(config_file, &svcnums, &devnums)) { BTERROR("Invalid config file: %s", config_file); return -1; } } // read to overwride config file setting by command line get_cmd_opts(argc, argv); 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) { BTERROR("Unable to create dir [%s]: %s", confdir, strerror(errno)); return 1; } /* load device list from the cache */ sprintf(cachefile, "%s/%s", confdir, "devcache"); btdev_cache_load(cachefile, &btdevs); /* test X access */ if (managepin) { err = system("/etc/affix/btsrv-gui try 2>/dev/null"); if (err) { BTERROR("Unable to launch to /etc/affix/btsrv-gui\n" "-> maybe unable to connect to X-server or python-gtk problems\n" "-> Disable options requiring btsrv-gui (e.g. give --nomanagepin)\n"); return 1; } } if (startsvc && svcnums < 1) BTINFO("No services found in %s", config_file);#if defined(CONFIG_AFFIX_SDP) if (sdpreg_init() != 0) { BTERROR("SDP initialization failed"); return -1; }#endif /* initialize devices */ err = btsrv_devinit(); if (err) { BTERROR("Unable to initialize devices\n"); return -1; } signal(SIGCHLD, SIG_IGN); if (start_event_handler() < 0) { BTERROR("Cannot start event handler"); return -1; } if (start_all_services() < 0) { BTERROR("Cannot start services"); return -1; } /* Exit the parent process if run as a daemon */ if (_daemon && become_daemon(1)) return 0; /* install signal handlers to unregister services from SDP */ signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); signal(SIGABRT, signal_handler); signal(SIGQUIT, signal_handler); if (handle_input() < 0) { BTERROR("Unable to listen to incoming connections"); } btsrv_cleanup(); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -