?? states.c
字號:
else { sdp_close(hs_sdp_session); hspd_sockets[IDX_SDP_SOCK] = 0; }}void headsetPagingTimedout(struct State *this){ appl_send_error_pkt(EHOSTUNREACH); syslog(LOG_NOTICE, "Timeout connecting L2CAP socket to headset, aborting."); this->_next_state = &HeadsetIdleState;}int headsetPagingGetTimeout(struct State *this){ return hs_pagingtimeout;}struct State HeadsetPagingState = { .name = "Paging", .pollEvents = { [IDX_CTL_APPL_SRV_SOCK] = POLLIN, [IDX_SDP_SOCK] = POLLOUT, }, .readSdp = headsetPagingReadSdp, .timedout = headsetPagingTimedout, .getTimeout = headsetPagingGetTimeout, .readCtlAppl = unconnectedReadCtlAppl, .getNextState = genericGetNextState,};/* Connecting State */static void headsetConnectingReadRfcomm(struct State *this, short revents){ /* Fectching result code */ int errcode; unsigned int opt_size = sizeof(int); /* default next state is back to home : idle */ this->_next_state = &HeadsetIdleState; if(getsockopt(hspd_sockets[IDX_RFCOMM_SOCK], SOL_SOCKET, SO_ERROR, &errcode, &opt_size) == 0) { if(errcode == 0) { hs_connected = 1; signalHeadsetConnected(&hs_bdaddr); /* Go to HeadsetReady state */ this->_next_state = &HeadsetReadyState; } else { appl_send_error_pkt(errcode); syslog(LOG_NOTICE, "unable to connect to headset: %s", strerror(errcode)); /* go to default state : idle */ } }}struct State HeadsetConnectingState = { .name = "Connecting", .pollEvents = { [IDX_CTL_APPL_SRV_SOCK] = POLLIN, [IDX_RFCOMM_SOCK] = POLLOUT, }, .readRfcomm = headsetConnectingReadRfcomm, .readCtlAppl = unconnectedReadCtlAppl, .getNextState = genericGetNextState,};/* Connected State */static void headsetConnectedEnter(struct State *this){ /* killing useless sockets */ if(hspd_sockets[IDX_PCM_APPL_SOCK] != 0) { close(hspd_sockets[IDX_PCM_APPL_SOCK]); hspd_sockets[IDX_PCM_APPL_SOCK] = 0; } if(hspd_sockets[IDX_SCO_SOCK] != 0) { close(hspd_sockets[IDX_SCO_SOCK]); hspd_sockets[IDX_SCO_SOCK] = 0; } /* This is not a transitional state */ this->_next_state = this; }static void headsetConnectedHandleApplConnReq(struct State *this){ struct sockaddr_un client_addr; unsigned int client_addr_len = sizeof(client_addr); /* Per default stay in same state */ this->_next_state = this; /* Connect Appli to us */ int _appl_sock = accept(hspd_sockets[IDX_PCM_APPL_SRV_SOCK], (struct sockaddr *)&client_addr, &client_addr_len); if(_appl_sock != -1) { fcntl(_appl_sock, F_SETFL, O_NONBLOCK); if(recv_cfg(_appl_sock, 0, 0) >= 0) { hspd_sockets[IDX_PCM_APPL_SOCK] = _appl_sock; /* Go to HeadsetReady state */ this->_next_state = &HeadsetReadyState; } else { /* else : stay where we are */ close(_appl_sock); } } else { syslog(LOG_ERR, "unable to accept local application connection, %s", strerror(errno)); }}struct State HeadsetConnectedState = { .name = "Connected", .pollEvents = { [IDX_PCM_APPL_SRV_SOCK] = POLLIN, [IDX_CTL_APPL_SRV_SOCK] = POLLIN, [IDX_RFCOMM_SOCK] = POLLIN }, .enter = headsetConnectedEnter, .handleApplConnReq = headsetConnectedHandleApplConnReq, .readRfcomm = genericReadRfcomm, .readCtlAppl = unconnectedReadCtlAppl, .getNextState = genericGetNextState,};/* Ready State */static void headsetReadyEnter(struct State *this){ /* Check if application socket is still there */ struct pollfd pfd = {.fd = hspd_sockets[IDX_PCM_APPL_SOCK], .events = POLLOUT}; int ret = poll(&pfd, 1, 0); if((ret == 1) && !(pfd.revents & (POLLHUP | POLLERR))) { /* Application still there : go go go !!! */ /* Launch SCO connection */ int _sco_sock = scoConnectAsync(&hs_bdaddr); if(_sco_sock >= 0) { hspd_sockets[IDX_SCO_SOCK] = _sco_sock; /* Go to HeadsetOpeningState state */ this->_next_state = &HeadsetOpeningState; } else { appl_send_error_pkt(errno); syslog(LOG_ERR, "unable to open bluetooth SCO socket"); close(_sco_sock); this->_next_state = &HeadsetConnectedState; } } else { /* Application closed connection : keep headset connection */ this->_next_state = &HeadsetConnectedState; }}struct State HeadsetReadyState = { .name = "Ready", .pollEvents = {}, /* Empty pollEvents : this state is purely transitionnal */ .enter = headsetReadyEnter, .readCtlAppl = unconnectedReadCtlAppl, .getNextState = genericGetNextState,};/* Opening State */static void headsetOpeningReadSco(struct State *this, short revents){ /* Fetching result code */ int errcode; unsigned int opt_size = sizeof(int); /* default next state is back to Connected */ this->_next_state = &HeadsetConnectedState; if(getsockopt(hspd_sockets[IDX_SCO_SOCK], SOL_SOCKET, SO_ERROR, &errcode, &opt_size) == 0) { if(errcode == 0) { struct sco_conninfo conn; struct sco_options opts; unsigned int size; size = sizeof(conn); if (getsockopt(hspd_sockets[IDX_SCO_SOCK], SOL_SCO, SCO_CONNINFO, &conn, &size) == 0) { size = sizeof(opts); if (getsockopt(hspd_sockets[IDX_SCO_SOCK], SOL_SCO, SCO_OPTIONS, &opts, &size) == 0) { /* Make sure we will block per default - clear 0_NONBLOCK flag */ fcntl(hspd_sockets[IDX_SCO_SOCK], F_SETFL, 0); syslog(LOG_INFO, "SCO channel opened handle=0x%04x mtu=%d", conn.hci_handle, opts.mtu); this->_next_state = &HeadsetStreamingState; } else { appl_send_error_pkt(errno); syslog(LOG_ERR, "unable to query SCO channel info: %s", strerror(errno)); /* go to default state : idle */ } } else { appl_send_error_pkt(errno); syslog(LOG_ERR, "unable to query SCO channel info: %s", strerror(errno)); /* go to default state : idle */ } } else { appl_send_error_pkt(errcode); syslog(LOG_ERR, "unable to open SCO channel to headset: %s", strerror(errcode)); /* go to default state : idle */ } } else { appl_send_error_pkt(errno); }}struct State HeadsetOpeningState = { .name = "Opening", .pollEvents = { [IDX_CTL_APPL_SRV_SOCK] = POLLIN, [IDX_RFCOMM_SOCK] = POLLIN, [IDX_SCO_SOCK] = POLLOUT, }, .readSco = headsetOpeningReadSco, .readRfcomm = genericReadRfcomm, .readCtlAppl = unconnectedReadCtlAppl, .getNextState = genericGetNextState,};/* Streaming State */static void headsetStreamingEnter(struct State *this){ /* Send sco socket to application using ancilliary data - see man 7 unix*/ char cmsg_b[CMSG_SPACE(sizeof(int))]; /* ancillary data buffer */ struct cmsghdr *cmsg; ipc_packet_t pkt = {.type = PKT_TYPE_STREAMING_IND}; struct iovec iov = { .iov_base = &pkt, /* Starting address */ .iov_len = sizeof(pkt) /* Number of bytes */ }; struct msghdr msgh = { .msg_name = 0, .msg_namelen = 0, .msg_iov = &iov, .msg_iovlen = 1, .msg_control = &cmsg_b, .msg_controllen = CMSG_LEN(sizeof(int)), .msg_flags = 0 }; cmsg = CMSG_FIRSTHDR(&msgh); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(int)); /* Initialize the payload */ (*(int *)CMSG_DATA(cmsg)) = hspd_sockets[IDX_SCO_SOCK]; /* finally send it -we ignore PIPE signal & return code, as any errors will be caught later */ int ret = sendmsg(hspd_sockets[IDX_PCM_APPL_SOCK], &msgh, MSG_NOSIGNAL); if(ret == -1) { syslog(LOG_ERR, "Unable to send SCO socket to appl: %s", strerror(errno)); } /* This is not a transitional state */ this->_next_state = this; }static void headsetStreamingReadAppl(struct State *this, short revents){ if((revents & (POLLHUP | POLLERR)) == 0) { /* Should not happen, treat as error */ this->_next_state = &HeadsetConnectedState; } else { syslog(LOG_INFO, "Appli closed socket"); /* go to Closewaiting state */ this->_next_state = &HeadsetClosewaitingState; }}struct State HeadsetStreamingState = { .name = "Streaming", .pollEvents = { [IDX_CTL_APPL_SRV_SOCK] = POLLIN, [IDX_PCM_APPL_SOCK] = POLLIN, [IDX_RFCOMM_SOCK] = POLLIN, [IDX_SCO_SOCK] = POLLERR, /* We are interested in nothing but errors */ }, .enter = headsetStreamingEnter, .readRfcomm = genericReadRfcomm, .readPcmAppl = headsetStreamingReadAppl, .readSco = genericReadSco, .readCtlAppl = connectedReadCtlAppl, .getNextState = genericGetNextState,};/* Closewaiting State */static void headsetClosewaitingEnter(struct State *this){ if(hspd_sockets[IDX_PCM_APPL_SOCK] != 0) { close(hspd_sockets[IDX_PCM_APPL_SOCK]); hspd_sockets[IDX_PCM_APPL_SOCK] = 0; } /* This is not a transitional state */ this->_next_state = this; }static void headsetClosewaitingHandleApplConnReq(struct State *this){ struct sockaddr_un client_addr; unsigned int client_addr_len = sizeof(client_addr); /* Per default stay in same state */ this->_next_state = this; /* Connect Appli to us */ int _appl_sock = accept(hspd_sockets[IDX_PCM_APPL_SRV_SOCK], (struct sockaddr *)&client_addr, &client_addr_len); if(_appl_sock != -1) { fcntl(_appl_sock, F_SETFL, O_NONBLOCK); if((recv_cfg(_appl_sock, 0, 0) >= 0)) { hspd_sockets[IDX_PCM_APPL_SOCK] = _appl_sock; this->_next_state = &HeadsetStreamingState; } else { /* else : stay where we are */ close(_appl_sock); } } else { syslog(LOG_ERR, "unable to accept local application connection"); }}void headsetClosewaitingTimedout(struct State *this){ appl_send_error_pkt(EHOSTUNREACH); syslog(LOG_NOTICE, "Nobody uses SCO channel anymore, closing it."); this->_next_state = &HeadsetConnectedState;}int headsetClosewaitingGetTimeout(struct State *this){ return 4000;}struct State HeadsetClosewaitingState = { .name = "Closewaiting", .pollEvents = { [IDX_PCM_APPL_SRV_SOCK] = POLLIN, [IDX_CTL_APPL_SRV_SOCK] = POLLIN, [IDX_RFCOMM_SOCK] = POLLIN, [IDX_SCO_SOCK] = POLLERR, }, .enter = headsetClosewaitingEnter, .readRfcomm = genericReadRfcomm, .readSco = genericReadSco, .handleApplConnReq = headsetClosewaitingHandleApplConnReq, .timedout = headsetClosewaitingTimedout, .getTimeout = headsetClosewaitingGetTimeout, .readCtlAppl = connectedReadCtlAppl, .getNextState = genericGetNextState,};/* AT commands processing */struct commands_table { const char * command; int (*process_func)(const char *cmd);};static void respOK(){ const char resp_ok[] = "\r\nOK\r\n"; send(hspd_sockets[IDX_RFCOMM_SOCK], resp_ok, sizeof(resp_ok) - 1, MSG_NOSIGNAL);}static void respError(){ const char resp_error[] = "\r\nERROR\r\n"; send(hspd_sockets[IDX_RFCOMM_SOCK], resp_error, sizeof(resp_error) - 1, MSG_NOSIGNAL);}static int doVolChanged(const char * cmd){ return volctl_write_fromhs(cmd);}static int doBtnPushed(const char * cmd){ signalHeadsetButtonPushed(&hs_bdaddr); return 0;}static void process_at_command(const char* buffer, unsigned int datalen){ int i; int answered = 0; const struct commands_table tbl[] = { {"AT+CKPD=200", doBtnPushed }, {"AT+VGS=", doVolChanged }, {"AT+VGM=", doVolChanged }, {0, 0 }, }; #ifndef NDEBUG fprintf(stderr, "Received from HS: %s\n", buffer); #endif for(i = 0; tbl[i].command != 0; i++) { if(strncmp(buffer, tbl[i].command, strlen(tbl[i].command)) == 0) { if(tbl[i].process_func(buffer) != 0) { /* Error happened while processing */ respError(); } else { /* Everything's fine */ respOK(); } answered = 1; break; } } if(!answered) { /* command not found in list */ respError(); }}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -