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

📄 main.c

📁 Linux的蓝牙操作工具。配合bluez-lib使用
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * *  BlueZ - Bluetooth protocol stack for Linux * *  Copyright (C) 2002-2007  Marcel Holtmann <marcel@holtmann.org> * * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA * */#ifdef HAVE_CONFIG_H#include <config.h>#endif#define _GNU_SOURCE#include <stdio.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <malloc.h>#include <string.h>#include <getopt.h>#include <signal.h>#include <termios.h>#include <sys/poll.h>#include <sys/param.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <sys/wait.h>#include <bluetooth/bluetooth.h>#include <bluetooth/hci.h>#include <bluetooth/hci_lib.h>#include <bluetooth/rfcomm.h>#include "kword.h"#ifdef NEED_PPOLL#include "ppoll.h"#endifstatic char *rfcomm_config_file = NULL;static int rfcomm_raw_tty = 0;static int auth = 0;static int encryption = 0;static int secure = 0;static int master = 0;static int linger = 0;static char *rfcomm_state[] = {	"unknown",	"connected",	"clean",	"bound",	"listening",	"connecting",	"connecting",	"config",	"disconnecting",	"closed"};static volatile sig_atomic_t __io_canceled = 0;static void sig_hup(int sig){	return;}static void sig_term(int sig){	__io_canceled = 1;}static char *rfcomm_flagstostr(uint32_t flags){	static char str[100];	str[0] = 0;	strcat(str, "[");	if (flags & (1 << RFCOMM_REUSE_DLC))		strcat(str, "reuse-dlc ");	if (flags & (1 << RFCOMM_RELEASE_ONHUP))		strcat(str, "release-on-hup ");	if (flags & (1 << RFCOMM_TTY_ATTACHED))		strcat(str, "tty-attached");	strcat(str, "]");	return str;}static void print_dev_info(struct rfcomm_dev_info *di){	char src[18], dst[18], addr[40];	ba2str(&di->src, src); ba2str(&di->dst, dst);	if (bacmp(&di->src, BDADDR_ANY) == 0)		sprintf(addr, "%s", dst);	else		sprintf(addr, "%s -> %s", src, dst);	printf("rfcomm%d: %s channel %d %s %s\n",		di->id, addr, di->channel,		rfcomm_state[di->state], 		di->flags ? rfcomm_flagstostr(di->flags) : "");}static void print_dev_list(int ctl, int flags){	struct rfcomm_dev_list_req *dl;	struct rfcomm_dev_info *di;	int i;	dl = malloc(sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di));	if (!dl) {		perror("Can't allocate memory");		exit(1);	}	dl->dev_num = RFCOMM_MAX_DEV;	di = dl->dev_info;	if (ioctl(ctl, RFCOMMGETDEVLIST, (void *) dl) < 0) {		perror("Can't get device list");		exit(1);	}	for (i = 0; i < dl->dev_num; i++)		print_dev_info(di + i);}static int create_dev(int ctl, int dev, uint32_t flags, bdaddr_t *bdaddr, int argc, char **argv){	struct rfcomm_dev_req req;	int err;	memset(&req, 0, sizeof(req));	req.dev_id = dev;	req.flags = flags;	bacpy(&req.src, bdaddr);	if (argc < 2) {		err = rfcomm_read_config(rfcomm_config_file);		if (err < 0) {			perror("Can't open RFCOMM config file");			return err;		}		bacpy(&req.dst, &rfcomm_opts[dev].bdaddr);		req.channel = rfcomm_opts[dev].channel;		if (bacmp(&req.dst, BDADDR_ANY) == 0) {			fprintf(stderr, "Can't find a config entry for rfcomm%d\n", dev);			return -EFAULT;		}	} else {		str2ba(argv[1], &req.dst);		if (argc > 2)			req.channel = atoi(argv[2]);		else			req.channel = 1;	}	err = ioctl(ctl, RFCOMMCREATEDEV, &req);	if (err == EOPNOTSUPP)		fprintf(stderr, "RFCOMM TTY support not available\n");	else if (err < 0)		perror("Can't create device");	return err;}static int create_all(int ctl){	struct rfcomm_dev_req req;	int i, err;	err = rfcomm_read_config(rfcomm_config_file);	if (err < 0) {		perror("Can't open RFCOMM config file");		return err;	}	for (i = 0; i < RFCOMM_MAX_DEV; i++) {		if (!rfcomm_opts[i].bind)			continue;		memset(&req, 0, sizeof(req));		req.dev_id = i;		req.flags = 0;		bacpy(&req.src, BDADDR_ANY);		bacpy(&req.dst, &rfcomm_opts[i].bdaddr);		req.channel = rfcomm_opts[i].channel;		if (bacmp(&req.dst, BDADDR_ANY) != 0)			ioctl(ctl, RFCOMMCREATEDEV, &req);	}	return 0;}static int release_dev(int ctl, int dev, uint32_t flags){	struct rfcomm_dev_req req;	int err;	memset(&req, 0, sizeof(req));	req.dev_id = dev;	err = ioctl(ctl, RFCOMMRELEASEDEV, &req);	if (err < 0)		perror("Can't release device");	return err;}static int release_all(int ctl){	struct rfcomm_dev_list_req *dl;	struct rfcomm_dev_info *di;	int i;	dl = malloc(sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di));	if (!dl) {		perror("Can't allocate memory");		exit(1);	}	dl->dev_num = RFCOMM_MAX_DEV;	di = dl->dev_info;	if (ioctl(ctl, RFCOMMGETDEVLIST, (void *) dl) < 0) {		perror("Can't get device list");		exit(1);	}	for (i = 0; i < dl->dev_num; i++)		release_dev(ctl, (di + i)->id, 0);	return 0;}static void run_cmdline(struct pollfd *p, sigset_t* sigs, char *devname,			int argc, char **argv){	int i;	pid_t pid;	char **cmdargv;	cmdargv = malloc((argc + 1) * sizeof(char*));	if (!cmdargv)		return;	for (i = 0; i < argc; i++)		cmdargv[i] = (strcmp(argv[i], "{}") == 0) ? devname : argv[i];	cmdargv[i] = NULL;	pid = fork();	switch (pid) {	case 0:		i = execvp(cmdargv[0], cmdargv);		fprintf(stderr, "Couldn't execute command %s (errno=%d:%s)\n",				cmdargv[0], errno, strerror(errno));		break;	case -1:		fprintf(stderr, "Couldn't fork to execute command %s\n",				cmdargv[0]);		break;	default:		while (1) {			int status;			pid_t child;			struct timespec ts;			child = waitpid(-1, &status, WNOHANG);			if (child == pid || (child < 0 && errno != EAGAIN))				break;			p->revents = 0;			ts.tv_sec  = 0;			ts.tv_nsec = 200;			if (ppoll(p, 1, &ts, sigs) || __io_canceled) {				kill(pid, SIGTERM);				waitpid(pid, &status, 0);				break;			}		}		break;	}	free(cmdargv);}static void cmd_connect(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv){	struct sockaddr_rc laddr, raddr;	struct rfcomm_dev_req req;	struct termios ti;	struct sigaction sa;	struct pollfd p;	sigset_t sigs;	socklen_t alen;	char dst[18], devname[MAXPATHLEN];	int sk, fd, try = 30;	laddr.rc_family = AF_BLUETOOTH;	bacpy(&laddr.rc_bdaddr, bdaddr);	laddr.rc_channel = 0;	if (argc < 2) {		if (rfcomm_read_config(rfcomm_config_file) < 0) {			perror("Can't open RFCOMM config file");			return;		}		raddr.rc_family = AF_BLUETOOTH;		bacpy(&raddr.rc_bdaddr, &rfcomm_opts[dev].bdaddr);		raddr.rc_channel = rfcomm_opts[dev].channel;		if (bacmp(&raddr.rc_bdaddr, BDADDR_ANY) == 0) {			fprintf(stderr, "Can't find a config entry for rfcomm%d\n", dev);			return;		}	} else {		raddr.rc_family = AF_BLUETOOTH;		str2ba(argv[1], &raddr.rc_bdaddr);		if (argc > 2)			raddr.rc_channel = atoi(argv[2]);		else			raddr.rc_channel = 1;	}	sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);	if (sk < 0) {		perror("Can't create RFCOMM socket");		return;	}	if (linger) {		struct linger l = { .l_onoff = 1, .l_linger = linger };		if (setsockopt(sk, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0) {			perror("Can't set linger option");			return;		}	}	if (bind(sk, (struct sockaddr *) &laddr, sizeof(laddr)) < 0) {		perror("Can't bind RFCOMM socket");		close(sk);		return;	}	if (connect(sk, (struct sockaddr *) &raddr, sizeof(raddr)) < 0) {		perror("Can't connect RFCOMM socket");		close(sk);		return;	}	alen = sizeof(laddr);	if (getsockname(sk, (struct sockaddr *)&laddr, &alen) < 0) {		perror("Can't get RFCOMM socket name");		close(sk);		return;	}	memset(&req, 0, sizeof(req));	req.dev_id = dev;	req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP);	bacpy(&req.src, &laddr.rc_bdaddr);	bacpy(&req.dst, &raddr.rc_bdaddr);	req.channel = raddr.rc_channel;	dev = ioctl(sk, RFCOMMCREATEDEV, &req);	if (dev < 0) {		perror("Can't create RFCOMM TTY");		close(sk);		return;	}	snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);	while ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {		if (errno == EACCES) {			perror("Can't open RFCOMM device");			goto release;		}		snprintf(devname, MAXPATHLEN - 1, "/dev/bluetooth/rfcomm/%d", dev);		if ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {			if (try--) {				snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);				usleep(100 * 1000);				continue;			}			perror("Can't open RFCOMM device");			goto release;		}	}	if (rfcomm_raw_tty) {		tcflush(fd, TCIOFLUSH);

⌨️ 快捷键说明

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