From c13c9806f957ebc675462737f4b328d3ab89e028 Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Mon, 10 Jul 2023 17:29:22 +0800
Subject: [PATCH] update gpsd.c

---
 gpsd/booster/atcmd.c |  296 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 296 insertions(+), 0 deletions(-)

diff --git a/gpsd/booster/atcmd.c b/gpsd/booster/atcmd.c
new file mode 100644
index 0000000..623bd96
--- /dev/null
+++ b/gpsd/booster/atcmd.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2023 Guo Wenxue
+ * Author: Guo Wenxue <guowenxue@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GPL license.
+ */
+
+#include <ctype.h>
+
+#include "logger.h"
+#include "atcmd.h"
+
+/*  Description: this function used to send an AT command from serial port and wait for reply message from
+ *               the communication module, and it will return once get expet/error string or timeout.
+ *
+ *    Arugments:
+ *         $comport: the serial port which connected to GPRS/3G/4G/NB-IoT/WiFi/BLE/Zigbee/LoRa...
+ *              $at: the AT command need to be sent, without "\r\n"
+ *         $timeout: wait for module reply for AT command timeout value, unit micro seconds(ms)
+ *          $exepct: the expect string reply from communication module
+ *           $error: the error string reply from communication module
+ *           $reply: the module reply message output buffer
+ *            $size: the output buffer ($reply) size
+ *
+ * Return value: <0: Function error   0: Got error string   1: Got expect string 2: Receive util timeout
+ *
+ */
+
+int send_atcmd(comport_t *comport, char *at, unsigned long timeout, char *expect, char *error, char *reply, int size)
+{
+    int                    i, rv = 0;
+    int                    res = ATRES_TIMEOUT;
+    int                    bytes = 0;
+    char                   buf[ATCMD_REPLY_LEN] = {'\0'};
+    char                   atcmd[ATCMD_LEN] = {'\0'};
+
+    if( !comport || !at )
+    {
+        log_error("Invalid input arguments\n");
+        return -1;
+    }
+
+    if( comport->fd <= 0 )
+    {
+        log_error("comport[%s] not opened\n");
+        return -2;
+    }
+
+    /* flushes both data received but not read, and data written but not transmitted in serial port */
+    tcflush(comport->fd, TCIOFLUSH);
+
+    snprintf(atcmd, sizeof(atcmd), "%s%s", at, AT_SUFFIX);
+    rv=comport_send( comport, atcmd, strlen(atcmd) );
+    if(rv < 0)
+    {
+        log_error("send AT command \"%s\" to \"%s\" failed, rv=%d\n", at, comport->devname, rv);
+        return -3;
+    }
+
+    res = ATRES_TIMEOUT;
+    memset( buf, 0, sizeof(buf) );
+
+    for(i=0; i<timeout/10; i++)
+    {
+        if( bytes >= sizeof(buf) )
+            break;
+
+        rv=comport_recv( comport, buf+bytes, sizeof(buf)-bytes, 10);
+        if(rv < 0)
+        {
+            log_error("send AT command \'%s\' to \'%s\' failed, rv=%d\n", at, comport->devname, rv);
+            return -3;
+        }
+
+        bytes += rv;
+
+        if( expect && strstr(buf, expect) )
+        {
+            log_debug("send AT command \"%s\" and got reply \"OK\"\n", at);
+            res = ATRES_EXPECT;
+            break;
+        }
+
+        if( error && strstr(buf, error) )
+        {
+            log_debug("send AT command \"%s\" and got reply \"ERROR\"\n", at);
+            res = ATRES_ERROR;
+            break;
+        }
+    }
+
+    if( bytes > 0 )
+        log_trace("AT command reply:%s", buf);
+
+    if( reply && size>0 )
+    {
+        bytes = strlen(buf)>size ? size : strlen(buf);
+        memset(reply, 0, size);
+        strncpy(reply, buf, bytes);
+
+        log_debug("copy out AT command \"%s\" reply message: \n%s", at, reply);
+    }
+
+    return res;
+}
+
+
+/*
+ *  Description: Send AT command which will only reply by "OK" or "ERROR", such as AT:
+ *                 Reply:   \r\nOK\r\n
+ * Return Value: 0: OK     -X: Failure
+ */
+int send_atcmd_check_ok(comport_t *comport, char *at, unsigned long timeout)
+{
+    int                     rv;
+
+    if( !comport || !at )
+    {
+        log_error("Invalid input arguments\n");
+        return -1;
+    }
+
+    rv=send_atcmd(comport, at, timeout, AT_OKSTR, AT_ERRSTR, NULL, 0);
+    if( ATRES_EXPECT == rv )
+    {
+        return 0;
+    }
+    else
+    {
+        return -2;
+    }
+}
+
+
+/*
+ *  Description: Send AT command which will reply by a value directly in a single line, such as AT+CGMM:
+ *                  Reply:   \r\nEC20F\r\nOK\r\n
+ *
+ * Return Value: 0: OK     -X: Failure
+ */
+int send_atcmd_check_value(comport_t *comport, char *at, unsigned long timeout, char *reply, int size)
+{
+    int                     rv, len;
+    char                    buf[ATCMD_REPLY_LEN];
+    char                   *ptr_start = buf;
+    char                   *ptr_end;
+
+    if( !comport || !at || !reply || size<=0 )
+    {
+        log_error("Invalid input arguments\n");
+        return -1;
+    }
+
+    rv = send_atcmd(comport, at, timeout, AT_OKSTR, AT_ERRSTR, buf, ATCMD_REPLY_LEN);
+    if( rv <= 0 )
+    {
+        return -2;
+    }
+
+    /* Skip the echo back command line */
+    if( !strncmp(buf, at, strlen(at)) )
+    {
+        ptr_start=strchr(buf, '\n');
+        if( !ptr_start )
+        {
+            log_error("reply message got wrong\n");
+            return -3;
+        }
+
+        ptr_start++;   /* skip '\n'  */
+    }
+
+    /* find end reply string "\r\nOK\r\n"  */
+    ptr_end = strstr(ptr_start, AT_OKSTR);
+    if( ptr_end )
+    {
+        len = ptr_end - ptr_start;
+    }
+    else
+    {
+        len = strlen(buf) - (ptr_start-buf);
+    }
+
+    memset(reply, 0, size);
+
+    len = len>size ? size : len;
+    memcpy(reply, ptr_start, len);
+
+    return 0;
+}
+
+/*
+ *  Description: Parser the $value from $key like "xxx: " line, such as AT+CSQ:
+ *                  Reply:   \r\n+CSQ: 26,99\r\nOK\r\n
+ *
+ * Return Value: 0: OK     -X: Failure
+ */
+int parser_request_value(char *buf, char *key, char *value, int size)
+{
+    char                   *ptr;
+    int                    i = 0;
+
+    if( !buf || !key || !value || size<=0 )
+    {
+        log_error("Invalid input arguments\n");
+        return -1;
+    }
+
+    ptr = strstr(buf, key);
+    if( !ptr )
+    {
+        log_debug("Not found key \"%s\" in %s\n", key, buf);
+        return -2;
+    }
+
+    ptr=strchr(ptr, ':');  /* found ':' before the value */
+    if( !ptr )
+    {
+        log_debug("Not found ':' before value\n");
+        return -3;
+    }
+    ptr++;   /* skip ':'  */
+
+    if( *ptr == '\"' ) /* skip " */
+        ptr++;
+
+    memset(value, 0, size);
+    while(*ptr!='\r' && i<size-1)
+    {
+        if( !isspace(*ptr) && *ptr!='\"') /* skip space,\r,\n ...  */
+            value[i++] = *ptr;
+        ptr ++;
+    }
+
+    ptr++; /* skip  */
+
+    return 0;
+}
+
+/*
+ *  Description: Send AT command which will reply by the value  with a prefix "+CMD: " line, such as AT+CSQ:
+ *                  Reply:   \r\n+CSQ: 26,99\r\nOK\r\n
+ *
+ * Return Value: 0: OK     -X: Failure
+ */
+int send_atcmd_check_request(comport_t *comport, char *at, unsigned long timeout, char *reply, int size)
+{
+    int                     i = 0;
+    int                     rv;
+    char                    buf[ATCMD_REPLY_LEN];
+    char                   *ptr;
+
+    if( !comport || !at || !reply || size<=0 )
+    {
+        log_error("Invalid input arguments\n");
+        return -1;
+    }
+
+    rv = send_atcmd(comport, at, timeout, AT_OKSTR, AT_ERRSTR, buf, ATCMD_REPLY_LEN);
+    if( rv <= 0 )
+    {
+        return -2;
+    }
+
+    ptr=strchr(buf, '+');  /* found '+' before the value */
+    if( !ptr )
+    {
+        log_error("reply message got wrong\n");
+        return -3;
+    }
+    ptr++;   /* skip '+'  */
+
+
+    ptr=strchr(buf, ':');  /* found ':' before the value */
+    if( !ptr )
+    {
+        log_error("reply message got wrong\n");
+        return -3;
+    }
+    ptr++;   /* skip ':'  */
+
+    if( *ptr == '\"' ) /* skip " */
+        ptr++;
+
+    memset(reply, 0, size);
+    while(*ptr!='\r' && i<size-1)
+    {
+        if( !isspace(*ptr) && *ptr!='\"') /* skip space,\r,\n ...  */
+            reply[i++] = *ptr;
+        ptr ++;
+    }
+
+    return 0;
+}
+

--
Gitblit v1.9.1