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

📄 btsocket.c

📁 linux下bluetooth后台服务程序
💻 C
字号:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <fcntl.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/stat.h>#include "btdefines.h"#include "btsocket.h"#include "btutils.h"#define SETTIMEOUT(timeout, tv, ptv) \	if (timeout < 0) { \		ptv = NULL; \	} else { \		if (timeout < 1000000) { \			tv.tv_sec = 0; \			tv.tv_usec = timeout; \		} else { \			tv.tv_sec = timeout / 1000000; \			tv.tv_usec = timeout % 1000000; \		} \		ptv = &tv; \	}int BTSocketCompare(cBTSocket sk, const char* bdaddr, int chan, int *res){	bdaddr_t addr;		if (!sk || !bdaddr)		return BT_ERR_ARGUMENT;	str2ba(bdaddr, &addr);	if (!bacmp(&addr, &sk->bdaddr) && sk->chan == chan)		*res = BT_TRUE;	else		*res = BT_FALSE;	return BT_ERR_NONE;}int BTSocketCreate(BTSocket* sk, const char* bdaddr, int chan){	BTSocket s;		if (!bdaddr || chan < 0 || chan > 30)		return BT_ERR_ARGUMENT;	s = (BTSocket)malloc(sizeof(struct sBTSocket));	if (!s)		return BT_ERR_NOMEMORY;	str2ba(bdaddr, &s->bdaddr);	s->chan = chan;	s->sock = -1;	s->accsock = -1;	sprintf(s->tty, "%s", "");	*sk = s;	return BT_ERR_NONE;}int BTSocketDestroy(BTSocket sk){	if (!sk)		return BT_ERR_ARGUMENT;	if (sk->sock > 0)		close(sk->sock);	if (sk->accsock > 0)		close(sk->accsock);	if (strlen(sk->tty))		BTSocketReleaseTTY(sk);	free(sk);	return BT_ERR_NONE;}int BTSocketListen(BTSocket sk, int chan){	bdaddr_t local;	struct sockaddr_rc addr;	int s;	if (!sk)		return BT_ERR_ARGUMENT;	if (sk->sock > 0 || sk->accsock > 0)		return BT_ERR_INUSE;	if ((s = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {		DEBUG_LOG1("creating socket: %s", strerror(errno));		return BT_ERR_FAILED;	}	if (fcntl(s, F_SETFD, FD_CLOEXEC) < 0) {		DEBUG_LOG1("setting FD_CLOEXEC failed: %s", strerror(errno));		close(s);		return BT_ERR_FAILED;	}	memset(&addr, 0, sizeof(addr));	addr.rc_family = AF_BLUETOOTH;	hci_devba(0, &local);	bacpy(&addr.rc_bdaddr, &local);	addr.rc_channel = chan;	if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {		DEBUG_LOG1("binding socket: %s", strerror(errno));		close(s);		return BT_ERR_FAILED;	}	if (listen(s, 1) < 0) {		DEBUG_LOG1("listening socket: %s", strerror(errno));		close(s);		return BT_ERR_FAILED;	}	sk->accsock  = s;		return BT_ERR_NONE;}int BTSocketStopListen(BTSocket sk){	if (!sk)		return BT_ERR_ARGUMENT;	if (sk->accsock > 0)		close(sk->accsock);	sk->accsock = -1;		return BT_ERR_NONE;}int BTSocketAccept(BTSocket sk, int timeout){	fd_set rset;	struct timeval *ptv;	struct timeval tv, tvstart, tvstop, tvreq;	socklen_t socklen;	struct sockaddr_rc addr;	int res;	if (!sk)		return BT_ERR_ARGUMENT;	if (sk->accsock < 0)		return BT_ERR_ARGUMENT;	if (sk->sock > 0)		return BT_ERR_INUSE;	SETTIMEOUT(timeout, tv, ptv);	tvreq = tv;retry:	FD_ZERO(&rset);	FD_SET(sk->accsock, &rset);	if (ptv)		gettimeofday(&tvstart, NULL);	res = select(sk->accsock + 1, &rset, NULL, NULL, ptv);	if (res < 0 || res > 1) {		if (res < 0) {			DEBUG_LOG1("select failed with %s", strerror(errno));		} else {			DEBUG_LOG1("select failed %d events pending", res);		}		return BT_ERR_FAILED;	} else if (res == 0)		return BT_ERR_TIMEOUT;	memset(&addr, 0, sizeof(addr));	socklen = sizeof(addr);	res = accept(sk->accsock, (struct sockaddr *) &addr, &socklen);	if (res < 0) {		DEBUG_LOG1("accept failed with %s", strerror(errno));		return BT_ERR_FAILED;	}	/* check if the connect is coming from the right bt device */	if (bacmp(&sk->bdaddr, &addr.rc_bdaddr)) {		DEBUG_LOG("connected to a wrong device");		close(res);		/* calculate remained timeout */		if (!ptv)			goto retry;		gettimeofday(&tvstop, NULL);		tv.tv_sec = tvstop.tv_sec - tvstart.tv_sec;		if (tvstop.tv_usec > tvstart.tv_usec)			tv.tv_usec = tvstop.tv_usec - tvstart.tv_usec;		else			tv.tv_usec = tvstart.tv_usec - tvstop.tv_usec;		if (tv.tv_sec < tvreq.tv_sec || (tv.tv_sec == tvreq.tv_sec && tv.tv_usec < tvreq.tv_usec)) {			tv.tv_sec = tvreq.tv_sec - tv.tv_sec;			tv.tv_usec = (tv.tv_usec < tvreq.tv_usec) ? tvreq.tv_usec - tv.tv_usec : tv.tv_usec - tvreq.tv_usec;			tvreq = tv;			goto retry;		}		return BT_ERR_TIMEOUT;	}	sk->sock = res;	close(sk->accsock);	sk->accsock = -1;		return BT_ERR_NONE;}int BTSocketReceive(cBTSocket sk, char *buf, int len, int* received, int timeout){	fd_set rset;	struct timeval *ptv;	struct timeval tv;	int res, nr;	if (!sk)		return BT_ERR_ARGUMENT;	if (sk->sock < 0 || !buf || len < 0 || !received)		return BT_ERR_ARGUMENT;	SETTIMEOUT(timeout, tv, ptv);	FD_ZERO(&rset);	FD_SET(sk->sock, &rset);	res = select(sk->sock + 1, &rset, NULL, NULL, ptv);	if (res < 0 || res > 1) {		DEBUG_LOG1("select() failed: %s", strerror(errno));		return BT_ERR_FAILED;	}	else if (res == 0)		return BT_ERR_TIMEOUT;	nr = recv(sk->sock, buf, len, MSG_NOSIGNAL);	if (nr < 0) {		DEBUG_LOG1("recv() failed: %s", strerror(errno));		return BT_ERR_FAILED;	}	*received = nr;		return BT_ERR_NONE;}int BTSocketConnect(BTSocket sk, int timeout){	struct sockaddr_rc addr;	int s, res;	if (!sk)		return BT_ERR_ARGUMENT;	if (sk->sock > 0 || sk->accsock > 0)		return BT_ERR_INUSE;		if ((s = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {		DEBUG_LOG1("creating socket: %s", strerror(errno));		return BT_ERR_FAILED;	}	res = fcntl(s, F_GETFL, 0);	if (res < 0 || fcntl(s, F_SETFL, res | O_NONBLOCK) < 0) {		DEBUG_LOG1("setting non-blocking: %s", strerror(errno));		close(s);		return BT_ERR_FAILED;	}	if (fcntl(s, F_SETFD, FD_CLOEXEC) < 0) {		DEBUG_LOG1("setting FD_CLOEXEC failed: %s", strerror(errno));		close(s);		return BT_ERR_FAILED;	}	memset(&addr, 0, sizeof(addr));	addr.rc_family = AF_BLUETOOTH;	bacpy(&addr.rc_bdaddr, &sk->bdaddr);	addr.rc_channel = sk->chan;	if (!connect(s, (struct sockaddr *)&addr, sizeof(addr))) {		sk->sock = s;		return BT_ERR_NONE;	}	if (errno != EAGAIN) {		DEBUG_LOG1("connect failed: %s", strerror(errno));		close(s);		return BT_ERR_FAILED;	}	sk->sock = s;	res = BTSocketIsConnected(sk, timeout);	if (res == BT_ERR_FAILED) {		close(sk->sock);		sk->sock = -1;	}	return res;}int BTSocketIsConnected(cBTSocket sk, int timeout){	fd_set wset;	struct timeval *ptv;	struct timeval tv;	int res, err, optlen;	if (!sk)		return BT_ERR_ARGUMENT;	if (sk->sock < 0)		return BT_ERR_ARGUMENT;	SETTIMEOUT(timeout, tv, ptv);	FD_ZERO(&wset);	FD_SET(sk->sock, &wset);	res = select(sk->sock + 1, NULL, &wset, NULL, ptv);	if (res < 0 || res > 1) {		DEBUG_LOG1("select failed %s", strerror(errno));		return BT_ERR_FAILED;	}	if (res == 0)		return BT_ERR_TIMEOUT;	optlen = sizeof(err);	res = getsockopt(sk->sock, SOL_SOCKET, SO_ERROR, (void*)&err, &optlen);	if (res < 0) {		DEBUG_LOG1("getsockopt failed: %s", strerror(errno));		return BT_ERR_FAILED;	}	if (err != 0) {		DEBUG_LOG1("connect failed %s", strerror(err));		return BT_ERR_FAILED;	}	return BT_ERR_NONE;}int BTSocketSend(cBTSocket sk, const char* buf, int len, int *sent, int timeout){	fd_set wset;	struct timeval *ptv;	struct timeval tv;	int res;	ssize_t ns;	if (!sk)		return BT_ERR_ARGUMENT;	if (sk->sock < 0 || !buf || len < 0 || !sent)		return BT_ERR_ARGUMENT;	FD_ZERO(&wset);	FD_SET(sk->sock, &wset);	SETTIMEOUT(timeout, tv, ptv);	res = select(sk->sock + 1, NULL, &wset, NULL, ptv);	if (res < 0 || res > 1) {		DEBUG_LOG1("select failed %s", strerror(errno));		return BT_ERR_FAILED;	}	else if (res == 0)		return BT_ERR_TIMEOUT;	ns = send(sk->sock, buf, len, MSG_NOSIGNAL);	if (ns < 0) {		DEBUG_LOG1("send failed %s", strerror(errno));		return BT_ERR_FAILED;	}	*sent = ns;	return BT_ERR_NONE;}int BTSocketClose(BTSocket sk){	if (!sk)		return BT_ERR_ARGUMENT;	close(sk->sock);	sk->sock = -1;	close(sk->accsock);	sk->accsock = -1;	return BT_ERR_NONE;}int BTSocketCreateTTY(BTSocket sk){	int ctl;	struct rfcomm_dev_req req;	char bdstr[BT_BDADDR_LEN];	if (!sk)		return BT_ERR_ARGUMENT;	ba2str(&sk->bdaddr, bdstr);	if ((ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM)) < 0) {		DEBUG_LOG1("creating control socket: %s", strerror(errno));		return BT_ERR_FAILED;	}	memset(&req, 0, sizeof(req));	req.dev_id = BTS_TTY_ID;	bacpy(&req.src, BDADDR_ANY);	bacpy(&req.dst, &sk->bdaddr);	req.channel = sk->chan;	if (ioctl(ctl, RFCOMMCREATEDEV, &req) < 0) {		DEBUG_LOG1("ioctl: %s", strerror(errno));		close(ctl);		return BT_ERR_FAILED;	}	close(ctl);	sprintf(sk->tty, BTS_TTY);	return BT_ERR_NONE;}int BTSocketIsTTYReady(cBTSocket sk, int *ready){	struct stat st;	if (!sk)		return BT_ERR_ARGUMENT;	if (stat(BTS_TTY1, &st) < 0) {		if (stat(BTS_TTY2, &st) < 0)			*ready = BT_FALSE;		else			*ready = BT_TRUE;	} else		*ready = BT_TRUE;	return BT_ERR_NONE;}int BTSocketReleaseTTY(BTSocket sk){	int ctl;	struct rfcomm_dev_req req;	if (!sk)		return BT_ERR_ARGUMENT;	memset(&req, 0, sizeof(req));	req.dev_id = BTS_TTY_ID;	if ((ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM)) < 0) {		DEBUG_LOG1("creating control socket: %s", strerror(errno));		return BT_ERR_FAILED;	}	if (ioctl(ctl, RFCOMMRELEASEDEV, &req)  < 0) {		DEBUG_LOG1("ioctl: %s", strerror(errno));		close( ctl );		return BT_ERR_FAILED;	}	close(ctl);	sprintf(sk->tty, "%s", "");	return BT_ERR_NONE;}int BTSocketGetTTYName(cBTSocket sk, char* ttyname){	if (!sk)		return BT_ERR_ARGUMENT;	strcpy(ttyname, BTS_TTY);	return BT_ERR_NONE;}int BTSocketGetAddress(cBTSocket sk, char *addr){	if (!sk)		return BT_ERR_ARGUMENT;	ba2str(&sk->bdaddr, addr);	return BT_ERR_NONE;}int BTSocketGetChannel(cBTSocket sk, int *chan){	if (!sk)		return BT_ERR_ARGUMENT;	*chan = sk->chan;	return BT_ERR_NONE;}

⌨️ 快捷键说明

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