⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 btsrv.c

📁 affix是一个Open Source的蓝牙协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
	btdev_cache_unlock();	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();	btdev = btdev_cache_add(&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();	return 0;}int event_handler(int fd){	uint8_t			buf[HCI_MAX_EVENT_SIZE];	int			err, devnum;	HCI_Event_Packet_Header	*hdr = (void*)buf;	err = hci_recv_event_any(fd, &devnum, buf, sizeof(buf));	if (err < 0)		return err;	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){	uint8_t			buf[HCI_MAX_MSG_SIZE];	struct hci_msg_hdr	*msg = (void*)(buf+1);	int			err;	err = recv(fd, buf, sizeof(buf), 0);	if (err < 0)		return err;	DBPRT("got message: %x", msg->opcode);	if (msg->opcode == HCICTL_STATE_CHANGE) {		struct hci_state_change	*cmd = (void*)msg;		if (cmd->event == HCIDEV_UP) {			updevnums++;			BTINFO("device %d is up, count: %d\n", cmd->devnum, updevnums);			err = btsrv_devconf(cmd->devnum);			if (err) {				BTERROR("Unable to configure device: %d", cmd->devnum);				return err;			}			start_services();		} else if (cmd->event == HCIDEV_DOWN) {			updevnums--;			BTINFO("device %d is down, count: %d\n", cmd->devnum, updevnums);			if (updevnums < 1) {				// no active devices.. stop services				stop_services();			}		}	}	return 0;}int handle_connections(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) {			if (errno != EINTR) {				BTERROR("Select error: %s", strerror(errno));				err = -1;			}			goto exit;		} else if (fd_cnt == 0) {			//should not happen		}		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 = 0;				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) {						// child						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);					}				}				if (pid < 0) {					BTERROR("Fork error");				}				close(newsock);				fd_cnt--;			}		}	}exit:	return err;}/* * read HCI events and kernel messages */int start_event_handler(void){	uint64_t	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, struct btdevice *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;	struct btdevice		*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;	struct hci_dev_attr	da;	int			devs[HCI_MAX_DEVS];	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;		updevnums++;		err = btsrv_devconf(da.devnum);		if (err)			return err;	}	return 0;}int btsrv_startup(void){	if (start_event_handler() < 0) {		BTERROR("Cannot start event handler");		return -1;	}	/* initialize devices */	if (btsrv_devinit()) {		BTERROR("Unable to initialize devices\n");		return -1;	}	if (start_services() < 0) {		BTERROR("Cannot start services");		return -1;	}	return 0;}int btsrv_cleanup(void){	int		i;	struct btdevice	*dev;	BTINFO("Terminating ..");	stop_event_handler();	stop_services();	free(config_file); config_file = NULL;	free(config_expr); config_expr = NULL;	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);	}	memset(services, 0, sizeof(services));	memset(services, 0, sizeof(devices));	return 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':					gobackground = 1;				break;			case 'C':				config_file = strdup(optarg);				break;			case 'v':				verboseflag = 1;				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;		}	}}void signal_handler(int sig){	BTINFO("Sig handler : %d", sig);	if (sig != SIGHUP)		exit(0);	restart = 1;}void do_exit(void){	btsrv_cleanup();}int main(int argc, char **argv){	int	err;	if (affix_init(argc, argv, LOG_DAEMON)) {		BTERROR("Affix initialization failed\n");		return 1;	}	BTINFO("%s started [%s].", argv[0], affix_version);	restart:	// 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 again to overwride config file setting by command line	get_cmd_opts(argc, argv);		/* 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 (btsrv_startup() < 0) {		return -1;	}	if (!restart) {		if (gobackground)			affix_background();				atexit(do_exit);	// exit handler				signal(SIGHUP, signal_handler);		signal(SIGINT, signal_handler);		signal(SIGTERM, signal_handler);		signal(SIGABRT, signal_handler);		signal(SIGQUIT, signal_handler);	}	signal(SIGCHLD, SIG_IGN);	restart = 0;	if (handle_connections() < 0) {		BTERROR("Unable to listen to incoming connections");	}	signal(SIGCHLD, SIG_DFL);	if (restart) {		BTINFO("restarting...");		btsrv_cleanup();	// cleanup first		goto restart;	}	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -