blob: 8721a52483b2e1d5007a43d6510679c2a6addf6a [file] [log] [blame]
#include <termios.h>
#include <pthread.h>
#include <sys/un.h>
#include <stdio.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <signal.h>
#include <unistd.h>
#include "mbtk_log.h"
#define MBTK_AT_SOCK "/tmp/atcmd_at"
#define TEMP_FAILURE_RETRY(exp) ({ \
typeof (exp) _rc; \
do { \
_rc = (exp); \
} while (_rc == -1 && errno == EINTR); \
_rc; })
static char *at_rsp_complete_tag[] = {
"OK",
"ERROR",
"CONNECT",
"+CMS ERROR:",
"+CME ERROR:",
"NO ANSWER",
"NO DIALTONE",
NULL};
static int at_fd = -1;
static int openSocket(const char* sockname)
{
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
LOGE("Error create socket: %s\n", strerror(errno));
return -1;
}
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, sockname, sizeof(addr.sun_path));
while (TEMP_FAILURE_RETRY(connect(sock,(const struct sockaddr*)&addr, sizeof(addr))) != 0) {
LOGE("Error connect to socket %s: %s, try again", sockname, strerror(errno));
sleep(1);
}
#if 0
int sk_flags = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, sk_flags | O_NONBLOCK);
#endif
return sock;
}
static int at_complete(char *rsp)
{
#if 0
char *ptr = at_rsp_complete_tag;
while(ptr) {
LOGD("ptr = %s", ptr);
if(strstr(rsp, ptr)) {
LOGD("%s , %s", rsp, ptr);
return 1;
}
ptr++;
}
#else
int i = 0;
while(at_rsp_complete_tag[i]) {
LOGD("ptr = %s", at_rsp_complete_tag[i]);
if(strstr(rsp, at_rsp_complete_tag[i])) {
LOGD("%s , %s", rsp, at_rsp_complete_tag[i]);
return 1;
}
i++;
}
#endif
return 0;
}
static int at_rsp_read(char* rsp, int rsp_len)
{
int len = 0;
int index = 0;
memset(rsp, 0x0, rsp_len);
while(1) {
if((len = read(at_fd, rsp + index, rsp_len - index)) > 0) {
if(at_complete(rsp)) {
LOGD("AT<%s", rsp);
return 0;
} else {
index += len;
if(index >= rsp_len) {
LOGE("Buffer too small.");
return -1;
}
}
} else {
printf("Read error:%d\n",errno);
return -1;
}
}
}
/*===========================================================================
FUNCTION mbtk_at_init
DESCRIPTION:
Initial MBTK AT.
PARAMETERS:
None.
RETURN VALUE:
int : Return 0 if success,other for failure.
===========================================================================*/
int mbtk_at_init()
{
if(at_fd > 0) {
LOGW("MBTK AT has inited.");
return 0;
}
at_fd = openSocket(MBTK_AT_SOCK);
return at_fd > 0 ? 0 : -1;
}
/*===========================================================================
FUNCTION mbtk_at_deinit
DESCRIPTION:
Deinitial MBTK AT.
PARAMETERS:
None.
RETURN VALUE:
int : Return 0 if success,other for failure.
===========================================================================*/
int mbtk_at_deinit()
{
if(at_fd < 0) {
LOGW("MBTK AT not inited.");
return 0;
}
close(at_fd);
at_fd = -1;
return 0;
}
/*===========================================================================
FUNCTION mbtk_at_send
DESCRIPTION:
Send AT command.
PARAMETERS:
cmd [IN]: AT command.
rsp [OUT]: AT command response.
rsp_len[IN] : AT command response buffer size.
RETURN VALUE:
int : Return 0 if success,other for failure.
===========================================================================*/
int mbtk_at_send(char* cmd, char* rsp, int rsp_len)
{
if(cmd == NULL || strlen(cmd) == 0 || rsp == NULL || rsp_len <= 0) {
return -1;
}
char at_cmd[2048] = {0};
memcpy(at_cmd, cmd, strlen(cmd));
char *ptr = at_cmd + strlen(at_cmd) - 1;
while(ptr >= at_cmd && (*ptr == '\r' || *ptr == '\n'))
{
*ptr-- = '\0';
}
if(!strncasecmp(at_cmd, "at", 2))
{
LOGD("AT>%s", at_cmd);
*(++ptr) = '\r';
*(++ptr) = '\n';
if(write(at_fd, at_cmd, strlen(at_cmd)) != strlen(at_cmd)) {
LOGE("Write error:%d",errno);
return -1;
}
return at_rsp_read(rsp, rsp_len);
} else {
LOGE("AT command error:%s",at_cmd);
return -1;
}
}