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

📄 bthandler.c

📁 linux下bluetooth后台服务程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	char* argv[9];	char ttyname[BTS_TTY_NAME_LEN];	char bdaddrstr[BT_BDADDR_LEN];	struct stat s;	if (!con)		return BT_ERR_ARGUMENT;	switch (con->state) {		case BT_STATE_UNINITIALIZED:			break;		case BT_STATE_INITIALIZED:			/* clean-up after pppd finished, sometimes it takes ages to bring it down */			if (con->profile == BT_PROFILE_DUN)				if (con->ppp.pid > 0)					if (waitpid(con->ppp.pid, &res, WNOHANG))						con->ppp.pid = -1;			break;		case BT_STATE_START_LISTENING:			/* put socket into the listening mode */			if (!BTTimerExpired(&con->listenretrytr) && !BTTimerExpired(&con->listentotaltr))				break;			res = BTSocketListen(con->sock, (con->profile == BT_PROFILE_HF) ? BT_CHANNEL_HF : ( (con->profile == BT_PROFILE_HS) ? BT_CHANNEL_HS : con->sock->chan ) );			if (res != BT_ERR_NONE) {				if (BTTimerExpired(&con->listentotaltr)) {					DEBUG_LOG1("cannot start listening, error=%s", ERROR2STR(res));					UPDATE_STATE(con->state, BT_STATE_INITIALIZED);				} else {					BTSetTimer(&con->listenretrytr, BT_TO_LISTEN_RETRY);				}			} else {				UPDATE_STATE(con->state, BT_STATE_LISTENING);			}			break;		case BT_STATE_LISTENING:			/* try to accept a new connection */			res = BTSocketAccept(con->sock, BT_TO_NONE);			switch (res) {				case BT_ERR_TIMEOUT:					break;				case BT_ERR_NONE:					UPDATE_STATE(con->state, BT_STATE_CONNECTED);					break;				default:					DEBUG_LOG1("cannot accept, error=%s", ERROR2STR(res));					BTSocketStopListen(con->sock);					BTSetTimer(&con->listenretrytr, BT_TO_LISTEN_RETRY);					UPDATE_STATE(con->state, BT_STATE_START_LISTENING);					break;			}			break;		case BT_STATE_START_CONNECTING:			/* put the socket into connecting mode */			if (!BTTimerExpired(&con->connectretrytr) && !BTTimerExpired(&con->connecttotaltr))				break;			/* wait till ACL link is down (the hack needed by some phones) */			if (!(con->flags & BT_FLAG_MULTICHANNEL)) {				if (BTSocketGetAddress(con->sock, bdaddrstr) == BT_ERR_NONE) {					if (BTIsAclLinkActive(bdaddrstr)) {						DEBUG_LOG("ACL link is up, waiting...");						BTSetTimer(&con->aclremovetr, BT_TO_REMOVEACL);						UPDATE_STATE(con->state, BT_STATE_REMOVE_CONNECTION);						break;					}				}			}			res = BTSocketConnect(con->sock, BT_TO_NONE);			switch (res) {				case BT_ERR_NONE:					UPDATE_STATE(con->state, BT_STATE_CONNECTED);					break;				case BT_ERR_TIMEOUT:					UPDATE_STATE(con->state, BT_STATE_CONNECTING);					break;				default:					DEBUG_LOG1("cannot start connecting, error=%s", ERROR2STR(res));					if (con->flags & BT_FLAG_DONOTRECONNECT) {						if (con->flags & BT_FLAG_LISTEN) {							DEBUG_LOG("reconnect disabled, listening");							INIT_LISTEN_TIMER(con, BT_TO_LISTEN_TOTAL);							UPDATE_STATE(con->state, BT_STATE_START_LISTENING);						} else {							DEBUG_LOG("reconnect disabled, initialized");							UPDATE_STATE(con->state, BT_STATE_INITIALIZED);						}					}					if (BTTimerExpired(&con->connecttotaltr)) {						if (con->flags & BT_FLAG_AUTORECONNECT) {							DEBUG_LOG("autoreconnect enabled, reconnecting");							INIT_CONNECT_TIMER(con, BT_TO_CONNECT_TOTAL);						}						else if (con->flags & BT_FLAG_LISTEN) {							DEBUG_LOG("number of retries exceeded, listening");							INIT_LISTEN_TIMER(con, BT_TO_LISTEN_TOTAL);							UPDATE_STATE(con->state, BT_STATE_START_LISTENING);						} else {							DEBUG_LOG("number of retries exceeded, initialized");							UPDATE_STATE(con->state, BT_STATE_INITIALIZED);						}					} else {						int modelid = BTGetFileInt(BT_FILENAME_MODELID);						if (!con->reconnecting &&  modelid != GOTYPE_VALENCIA500 && modelid != GOTYPE_VALENCIA700) {							DEBUG_LOG("reconnecting using short timeout");							BTSetTimer(&con->connectretrytr, BT_TO_CONNECT_RETRY_1);						} else {							DEBUG_LOG("reconnecting using normal timeout");							BTSetTimer(&con->connectretrytr, BT_TO_CONNECT_RETRY);						}					}					break;			}			break;		case BT_STATE_REMOVE_CONNECTION:			/* wait till ACL link is down (the hack needed by some phones) */			if (BTSocketGetAddress(con->sock, bdaddrstr) == BT_ERR_NONE) {				if (BTIsAclLinkActive(bdaddrstr) == BT_TRUE) {					if (!BTTimerExpired(&con->aclremovetr))						break;					DEBUG_LOG("destroying ACL link.");					BTDestroyAclLink(bdaddrstr);				} else {					DEBUG_LOG("ACL link is down.");				}			}			BTSetTimer(&con->connectretrytr, 0);			UPDATE_STATE(con->state, BT_STATE_START_CONNECTING);			break;		case BT_STATE_CONNECTING:			/* check if connection is ready, no global timeout here - user may need to enter a PIN code for example */			res = BTSocketIsConnected(con->sock, BT_TO_NONE);			switch (res) {				case BT_ERR_TIMEOUT:					break;				case BT_ERR_NONE:					UPDATE_STATE(con->state, BT_STATE_CONNECTED);					break;				default:					DEBUG_LOG1("connecting failed, error=%s", ERROR2STR(res));					BTSocketClose(con->sock);					if (con->flags & BT_FLAG_DONOTRECONNECT) {						if (con->flags & BT_FLAG_LISTEN) {							DEBUG_LOG("reconnect disabled, listening");							INIT_LISTEN_TIMER(con, BT_TO_LISTEN_TOTAL);							UPDATE_STATE(con->state, BT_STATE_START_LISTENING);						} else {							DEBUG_LOG("reconnect disabled, initialized");							UPDATE_STATE(con->state, BT_STATE_INITIALIZED);						}					}					if (BTTimerExpired(&con->connecttotaltr)) {						if (con->flags & BT_FLAG_AUTORECONNECT) {							DEBUG_LOG("autoreconnect enabled, reconnecting");							INIT_CONNECT_TIMER(con, BT_TO_CONNECT_TOTAL);							UPDATE_STATE(con->state, BT_STATE_START_CONNECTING);						} else if (con->flags & BT_FLAG_LISTEN) {							DEBUG_LOG("number of retries exceeded, listening");							INIT_LISTEN_TIMER(con, BT_TO_LISTEN_TOTAL);							UPDATE_STATE(con->state, BT_STATE_START_LISTENING);						} else {							DEBUG_LOG("number of retries exceeded, initialized");							UPDATE_STATE(con->state, BT_STATE_INITIALIZED);						}					} else {						int modelid = BTGetFileInt(BT_FILENAME_MODELID);						if (!con->reconnecting &&  modelid != GOTYPE_VALENCIA500 && modelid != GOTYPE_VALENCIA700) {							DEBUG_LOG("reconnecting using short timeout");							BTSetTimer(&con->connectretrytr, BT_TO_CONNECT_RETRY_1);						} else {							DEBUG_LOG("reconnecting using normal timeout");							BTSetTimer(&con->connectretrytr, BT_TO_CONNECT_RETRY);						}						UPDATE_STATE(con->state, BT_STATE_START_CONNECTING);					}					break;			}			break;		case BT_STATE_CONNECTED:			if (!con->sendbuf)				break;			res = BTSocketSend(con->sock, con->sendbuf, con->sendbuflen, &sent, BT_TO_NONE);			if (res == BT_ERR_TIMEOUT)				break;			if (res != BT_ERR_NONE) {				DEBUG_LOG("sending buffer: connection is lost");				BTSocketClose(con->sock);				if (BTTimerExpired(&con->connecttotaltr)) {					free(con->sendbuf);					con->sendbuf = NULL;					con->sendbuflen = 0;					if (con->flags & BT_FLAG_AUTORECONNECT) {						DEBUG_LOG("autoreconnect enabled, reconnecting");						con->reconnecting = 1;						INIT_CONNECT_TIMER(con, BT_TO_CONNECT_TOTAL);						UPDATE_STATE(con->state, BT_STATE_START_CONNECTING);					}					else if (con->flags & BT_FLAG_LISTEN) {						DEBUG_LOG("number of retries exceeded, listening");						INIT_LISTEN_TIMER(con, BT_TO_LISTEN_TOTAL);						UPDATE_STATE(con->state, BT_STATE_START_LISTENING);					} else {						DEBUG_LOG("number of retries exceeded, initialized");						UPDATE_STATE(con->state, BT_STATE_INITIALIZED);					}				} else {					BTSetTimer(&con->connectretrytr, 0);					UPDATE_STATE(con->state, BT_STATE_START_CONNECTING);				}				break;			}			if (sent < con->sendbuflen) {				DEBUG_LOG("send buffer partially sent");				memcpy(con->sendbuf, con->sendbuf + sent, con->sendbuflen - sent);				con->sendbuflen -= sent;			} else {				DEBUG_LOG("send buffer purged");				free(con->sendbuf);				con->sendbuf = NULL;				con->sendbuflen = 0;			}			break;		case BT_STATE_APP_START:			switch(con->ppp.state){			case BT_PPP_STATE_INIT:				pid = BTGetFileInt(BT_PPP_PIDFILE);				if (pid > 0) {					DEBUG_LOG1("removing previous instance of %s", BT_PPP_NAME);					kill(pid, SIGTERM);					BTSetTimer(&con->ppp.removetr, BT_TO_APPREMOVE);					UPDATE_STATE(con->ppp.state, BT_PPP_STATE_REMOVE);					break;				}				if (!(con->flags & BT_FLAG_MULTICHANNEL)) {					if (BTSocketGetAddress(con->sock, bdaddrstr) == BT_ERR_NONE) {						if (BTIsAclLinkActive(bdaddrstr)) {							DEBUG_LOG("ACL link is up, waiting.");							BTSetTimer(&con->aclremovetr, BT_TO_REMOVEACL);							UPDATE_STATE(con->state, BT_STATE_APP_REMOVE_CONNECTION);							break;						}					}				}				UPDATE_STATE(con->ppp.state, BT_PPP_STATE_CREATETTY);				//fall trough			case BT_PPP_STATE_CREATETTY:				if (BTSocketCreateTTY(con->sock) != BT_ERR_NONE) {					UPDATE_STATE(con->state, BT_STATE_INITIALIZED);					break;				}				BTSetTimer(&con->ppp.ttytr, BT_TO_TTYCREATE);				UPDATE_STATE(con->ppp.state, BT_PPP_STATE_CHECKTTY);				//fall though			case BT_PPP_STATE_CHECKTTY:				if (BTSocketIsTTYReady(con->sock, &res) != BT_ERR_NONE) {					BTSocketReleaseTTY(con->sock);					UPDATE_STATE(con->state, BT_STATE_INITIALIZED);					break;				}								if (res == BT_FALSE && !BTTimerExpired(&con->ppp.ttytr))					break;				if (res == BT_FALSE) {					BTSocketReleaseTTY(con->sock);					UPDATE_STATE(con->state, BT_STATE_INITIALIZED);					break;				}				UPDATE_STATE(con->ppp.state, BT_PPP_STATE_START);				BTSetTimer(&con->ppp.startretrytr, 0);				BTSetTimer(&con->ppp.starttotaltr, BT_TO_PPPSTARTTOTAL);				//fall through			case BT_PPP_STATE_START:				/* put the socket into connecting mode */				if (!BTTimerExpired(&con->ppp.startretrytr))					break;				i = 0;				argv[i++] = BT_PPP_NAME;				if (BTSocketGetTTYName(con->sock, ttyname) != BT_ERR_NONE) {					DEBUG_LOG("failed to get TTY name");					BTSocketReleaseTTY(con->sock);					UPDATE_STATE(con->state, BT_STATE_INITIALIZED);					break;				}				//PLEASECHECK (Victor): work around, removing the PPP lock file				unlink("/var/lock/LCK..rfcomm0");				argv[i++] = ttyname;				argv[i++] = BT_PPP_BAUDRATE;				if (strlen(con->ppp.param)) {					argv[i++] = "call";					argv[i++] = con->ppp.param;				}				argv[i++] = "linkname";				argv[i++] = BT_PPP_LINKNAME;				argv[i++] = NULL;				con->ppp.pid = vfork();				if (!con->ppp.pid) {					if (execvp(BT_PPP_NAME, argv) < 0) {						DEBUG_LOG2("%s failed to start: %s", BT_PPP_NAME, strerror(errno));						exit(1);					}				} else if (con->ppp.pid > 0) {					DEBUG_LOG2("%s started with pid=%d", BT_PPP_NAME, con->ppp.pid);					BTSetTimer(&con->ppp.readytr, BT_TO_PPPREADY);					UPDATE_STATE(con->ppp.state, BT_PPP_STATE_CHECKREADY);				} else {					DEBUG_LOG1("failed to start %s", BT_PPP_NAME);					BTSocketReleaseTTY(con->sock);					UPDATE_STATE(con->state, BT_STATE_INITIALIZED);				}				break;			case BT_PPP_STATE_CHECKREADY:				if (BTTimerExpired(&con->ppp.readytr) || waitpid(con->ppp.pid, &res, WNOHANG)) {					if (!BTTimerExpired(&con->ppp.readytr)) {						if (WIFEXITED(res)) {							DEBUG_LOG1("terminated normally, exit status =  %d", WEXITSTATUS(res));							if (WEXITSTATUS(res) == 7 && !BTTimerExpired(&con->ppp.starttotaltr)) {								DEBUG_LOG("retrying ppp startup: busy device");								BTSetTimer(&con->ppp.startretrytr, BT_TO_PPPSTARTRETRY);								UPDATE_STATE(con->ppp.state, BT_PPP_STATE_START);								break;							}						}						DEBUG_LOG1("%s failed after start", BT_PPP_NAME);					} else {						DEBUG_LOG1("%s timeout expired", BT_PPP_NAME);					}					BTSocketReleaseTTY(con->sock);					pid = BTGetFileInt(BT_PPP_PIDFILE);					if (pid > 0) {						DEBUG_LOG1("terminating %d", pid);						kill(pid, SIGTERM);					}					BTSetTimer(&con->ppp.removetr, BT_TO_APPREMOVE);					UPDATE_STATE(con->state, BT_STATE_APP_CLOSING);				} else if (stat(BT_PPP_UPFILE, &s) >= 0 ) {					BTSocketReleaseTTY(con->sock);					UPDATE_STATE(con->state, BT_STATE_APP_READY);				}				break;			case BT_PPP_STATE_REMOVE:				pid = BTGetFileInt(BT_PPP_PIDFILE);				if (pid > 0) {					if (!waitpid(pid, &res, WNOHANG) && !BTTimerExpired(&con->ppp.removetr))						break;					pid = BTGetFileInt(BT_PPP_PIDFILE);					if (pid > 0) {						DEBUG_LOG1("sending KILL to %s", BT_PPP_NAME);						kill(pid, SIGKILL);						waitpid(pid, &res, WNOHANG);					}				}				UPDATE_STATE(con->ppp.state, BT_PPP_STATE_INIT);				break;			default:				break;			}			break;		case BT_STATE_APP_REMOVE_CONNECTION:			if (BTSocketGetAddress(con->sock, bdaddrstr) == BT_ERR_NONE) {				if (BTIsAclLinkActive(bdaddrstr) == BT_TRUE) {					if (!BTTimerExpired(&con->aclremovetr))						break;					DEBUG_LOG("destroying ACL link.");					BTDestroyAclLink(bdaddrstr);				} else {					DEBUG_LOG("ACL link is down.");				}			}			UPDATE_STATE(con->state, BT_STATE_APP_START);			break;		case BT_STATE_APP_READY:			if (waitpid(con->ppp.pid, &res, WNOHANG))				UPDATE_STATE(con->state, BT_STATE_INITIALIZED);			break;		case BT_STATE_APP_CLOSING:			if (BTTimerExpired(&con->ppp.removetr) || waitpid(con->ppp.pid, &res, WNOHANG)) {				if (!BTTimerExpired(&con->ppp.removetr))					con->ppp.pid = -1;				UPDATE_STATE(con->state, BT_STATE_INITIALIZED);			}			break;		case BT_STATE_CLOSING:			switch(con->ppp.state){			case BT_PPP_STATE_CLOSING:				if (BTTimerExpired(&con->ppp.removetr) || waitpid(con->ppp.pid, &res, WNOHANG)) {					if (!BTTimerExpired(&con->ppp.removetr))						con->ppp.pid = -1;					UPDATE_STATE(con->state, BT_STATE_UNINITIALIZED);				}				break;			case BT_PPP_STATE_UNINITIALIZED:			default:				UPDATE_STATE(con->state, BT_STATE_UNINITIALIZED);				break;			}			break;		default:			break;				}	return BT_ERR_NONE;}

⌨️ 快捷键说明

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