blob: fa34eda6c93ab409c91162553da46c9a1c470cdb [file] [log] [blame]
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <pthread.h>
#include <fcntl.h>
#include <errno.h>
#include <stdint.h>
#include <dlfcn.h>
#include <stdbool.h>
#include "gsw_at.h"
#ifndef LOG_ERR_LEVEL
#define LOG_ERR_LEVEL 3 /* error conditions */
#endif
#ifndef LOG_WARN_LEVEL
#define LOG_WARN_LEVEL 4 /* warning conditions */
#endif
#ifndef LOG_INFO_LEVEL
#define LOG_INFO_LEVEL 6 /* informational */
#endif
#ifndef LOG_DEBUG_LEVEL
#define LOG_DEBUG_LEVEL 7 /* debug-level messages */
#endif
#ifndef LOG_VERBOSE_LEVEL
#define LOG_VERBOSE_LEVEL 8
#endif
#define LOGV(fmt, args ...) \
do{ \
char *file_ptr_1001 = __FILE__; \
char *ptr_1001 = file_ptr_1001 + strlen(file_ptr_1001) - 1; \
char line_1001[10] = {0}; \
sprintf(line_1001, "%d", __LINE__); \
while(ptr_1001 >= file_ptr_1001 && *ptr_1001){ \
if(*ptr_1001 == '/') \
break; \
ptr_1001--; \
} \
fun_ptr_log(LOG_VERBOSE_LEVEL, "%s#%s: " fmt, ptr_1001 + 1, line_1001, ##args); \
} while(0)
#define LOGI(fmt, args...) \
do{ \
char *file_ptr_1001 = __FILE__; \
char *ptr_1001 = file_ptr_1001 + strlen(file_ptr_1001) - 1; \
char line_1001[10] = {0}; \
sprintf(line_1001, "%d", __LINE__); \
while(ptr_1001 >= file_ptr_1001 && *ptr_1001){ \
if(*ptr_1001 == '/') \
break; \
ptr_1001--; \
} \
fun_ptr_log(LOG_INFO_LEVEL, "%s#%s: " fmt, ptr_1001 + 1, line_1001, ##args); \
} while(0)
#define LOGD(fmt, args...) \
do{ \
char *file_ptr_1001 = __FILE__; \
char *ptr_1001 = file_ptr_1001 + strlen(file_ptr_1001) - 1; \
char line_1001[10] = {0}; \
sprintf(line_1001, "%d", __LINE__); \
while(ptr_1001 >= file_ptr_1001 && *ptr_1001){ \
if(*ptr_1001 == '/') \
break; \
ptr_1001--; \
} \
fun_ptr_log(LOG_DEBUG_LEVEL, "%s#%s: " fmt, ptr_1001 + 1, line_1001, ##args); \
} while(0)
#define LOGW(fmt, args...) \
do{ \
char *file_ptr_1001 = __FILE__; \
char *ptr_1001 = file_ptr_1001 + strlen(file_ptr_1001) - 1; \
char line_1001[10] = {0}; \
sprintf(line_1001, "%d", __LINE__); \
while(ptr_1001 >= file_ptr_1001 && *ptr_1001){ \
if(*ptr_1001 == '/') \
break; \
ptr_1001--; \
} \
fun_ptr_log(LOG_WARN_LEVEL, "%s#%s: " fmt, ptr_1001 + 1, line_1001, ##args); \
} while(0)
#define LOGE(fmt, args...) \
do{ \
char *file_ptr_1001 = __FILE__; \
char *ptr_1001 = file_ptr_1001 + strlen(file_ptr_1001) - 1; \
char line_1001[10] = {0}; \
sprintf(line_1001, "%d", __LINE__); \
while(ptr_1001 >= file_ptr_1001 && *ptr_1001){ \
if(*ptr_1001 == '/') \
break; \
ptr_1001--; \
} \
fun_ptr_log(LOG_ERR_LEVEL, "%s#%s: " fmt, ptr_1001 + 1, line_1001, ##args); \
} while(0)
#define GSW_HAL_SUCCESS 0
#define GSW_HAL_FAIL -1 //表示失败(通用性)
#define GSW_HAL_MEM_INVAILD -2 //表示入参地址为NULL
#define OUT_MAX_SIZE 1024
#define LINE __LINE__
#define FUNC __FUNCTION__
#define AT_EXTERSION_SOCKET_NAME "/tmp/atcmdext"
#define SOCKET_ZERO 0
#define SOCKET_SUCC 1
#define SOCKET_FAIL -1
typedef void (*mbtk_log)(int level, const char *format,...);
typedef enum
{
A_SUCCESS = 0,
A_ERROR = -1
}LYNQ_AT_E;
static mbtk_log fun_ptr_log = NULL;
void *dlHandle_at = NULL;
char *lynqLib_at = "/lib/libmbtk_lib.so";
char *output = NULL;
int sockfd = 0;
int result = A_SUCCESS;
char buffer_at[OUT_MAX_SIZE] = {0};
struct sockaddr_in addr_serv;
struct sockaddr_un addr_server;
AT_CALLBACK tmp = NULL;
static pthread_mutex_t s_startupMutex = PTHREAD_MUTEX_INITIALIZER;
socklen_t len;
bool connect_state = false;
int socket_local_client (char* name) {
LOGD("[%d][%s] enter",LINE,FUNC);
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockfd < 0)
{
LOGD("Can't open stream socket (%s)", name);
return -1;
}
addr_server.sun_family = AF_UNIX;
memset(addr_server.sun_path, '\0', sizeof(addr_server.sun_path));
strncpy(addr_server.sun_path, name, sizeof(addr_server.sun_path) - 1);
if (connect(sockfd, (struct sockaddr *) &addr_server, sizeof(struct sockaddr_un)) < 0)
{
close(sockfd);
LOGD("Can't connect to server side, path: %s, %s", name, strerror(errno));
return -1;
}
LOGD("[%d][%s] connect %s success",LINE,FUNC,name);
return sockfd;
}
bool send_msg_to_service(int fd,char *msg,int size)
{
LOGD("[%d][%s] enter",LINE,FUNC);
if (fd < 0)
{
LOGD("fd invalid when send to atci service. errno = %d", errno);
return false;
}
if(NULL == msg)
{
LOGD("atcmd is null.");
return false;
}
int sendLen = send(fd, msg, size, 0);
if (sendLen != size)
{
LOGD("lose data when send to atci service. errno = %d", errno);
return false;
}
LOGD("client send to app demo: %s", msg);
return true;
}
int atsvc_cmd_recv(int fd, char *buf, int len)
{
int ret = 0;
ret = recv(fd, buf, len, 0);
LOGD("[%d][%s] recv after",LINE,FUNC);
if (ret < 0)
{
LOGD("acti_cmd_recv client select error, ret=%d, error=%s(%d),fd=%d", ret,strerror(errno), errno, fd);
return SOCKET_FAIL;
}
else if(ret == 0)
{
LOGD("acti_cmd_recv client recv error, ret=%d, error=%s(%d),fd=%d", ret,strerror(errno), errno, fd);
return SOCKET_ZERO;
}
return SOCKET_SUCC;
}
/**
* @brief send third cmd to service and receive input,then send output to service
*
* @param parm
* @return void*
*/
void *thread_recv(void *parm)
{
LOGD("[%d][%s] enter",LINE,FUNC);
char at_cmd[100] = {0};
int fd = -1;
int ret = 0;
fd = socket_local_client(AT_EXTERSION_SOCKET_NAME);
if(fd <= 0)
{
LOGE("socket_local_client fail\n");
connect_state = false;
pthread_mutex_unlock(&s_startupMutex);
return NULL;
}
int len_buf = strlen(buffer_at);
if(!send_msg_to_service(fd,buffer_at,len_buf))
{
LOGE("send_msg_to_service fail\n");
connect_state = false;
pthread_mutex_unlock(&s_startupMutex);
return NULL;
}
connect_state = true;
pthread_mutex_unlock(&s_startupMutex);
char *input = NULL;
output = (char *)malloc(sizeof(char)*OUT_MAX_SIZE);
if(NULL == output)
{
LOGE("thread_recv malloc fail\n");
return NULL;
}
TryNewLink:
if(connect_state == false)
{
if (connect(fd, (struct sockaddr *) &addr_server, sizeof(struct sockaddr_un)) < 0)
{
close(fd);
LOGE("Can't connect to server side, path: %s, errno:%d", AT_EXTERSION_SOCKET_NAME, errno);
return NULL;
}
connect_state = true;
}
while (1)
{
/*receive at cmd*/
memset(at_cmd, 0, sizeof(at_cmd));
ret = atsvc_cmd_recv(fd, at_cmd,sizeof(at_cmd));
if (ret < 0)
{
LOGE("[%d][%s]receive CMD error",LINE,FUNC);
continue;
}
else if(ret == SOCKET_ZERO)
{
LOGE("maybe client socket closed 1. retry new link!");
connect_state = false;
goto TryNewLink;
}
input = at_cmd;
int len = strlen(input);
while (len > 0 && (input[len - 1] == '\r' || input[len - 1] == '\n'))
{
input[--len] = '\0';
}
//begin deal with callback
tmp(input, output, OUT_MAX_SIZE);
LOGD("lynq_reg_third_at send output to service\n");
if(!send_msg_to_service(fd,output, strlen(output)))
{
LOGE("thread_recv send fail\n");
continue;
}
}
free(output);
output = NULL;
if(fd != 0)
{
close(fd);
}
return NULL;
}
/**
* @brief Threads are created to communicate with the server
*
* @return int
*/
int lynq_connect_service_start(void)
{
LOGD("[%d][%s] enter",LINE,FUNC);
pthread_t lynq_at_tid;
int rt = pthread_create(&lynq_at_tid, NULL, thread_recv, NULL);
pthread_mutex_lock(&s_startupMutex);
LOGD("[%d][%s] pthread mutex unlock",LINE,FUNC);
if((connect_state != true) && rt < 0)
{
LOGE("connect fail,rt:%d,connect state:%d\n",rt,connect_state);
return -1;
}
return 0;
}
/**
* @brief Type:[IN] send third at cmd to service
* @param ext_at Type:[IN] input at cmd
* @param callback Type:[IN]
* @return int
*/
int32_t gsw_reg_atcmd(const char *atcmd,AT_CALLBACK func)
{
if(NULL == atcmd || NULL == func)
{
return GSW_HAL_FAIL;
}
dlHandle_at = dlopen(lynqLib_at, RTLD_NOW);
fun_ptr_log = (mbtk_log)dlsym(dlHandle_at, "mbtk_log");
if(fun_ptr_log == NULL || dlHandle_at == NULL)
{
return GSW_HAL_FAIL;
}
memcpy(buffer_at, atcmd, strlen(atcmd));
tmp = func;
LOGD("lynq_reg_third_at start\n");
int ret = lynq_connect_service_start();
if(ret != 0)
{
LOGE("lynq_connect_service_start start failed\n");
return GSW_HAL_FAIL;
}
LOGD("lynq_connect_service_start success ret:%d\n",ret);
return GSW_HAL_SUCCESS;
}
int32_t gsw_sdk_at_init(void)
{
return GSW_HAL_SUCCESS;
}