From 9ada9cdc52c22fabb658680d3869d3ab6ab87f61 Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Mon, 19 Aug 2024 10:26:57 +0800
Subject: [PATCH] update booster from booster project
---
booster/dictionary.c | 3
booster/at-esp32.c | 388 ++++++
booster/dictionary.h | 3
booster/logger.h | 123 -
booster/ringbuf.h | 12
booster/logger.c | 503 ++-----
booster/ringbuf.c | 17
booster/test/test_logger.c | 45
booster/esp32.c | 166 ++
booster/README.md | 4
booster/linux_list.h | 524 ++++----
booster/test/makefile | 63
booster/util_proc.c | 26
booster/comport.h | 52
booster/esp32.h | 35
booster/atcmd.c | 300 ++++
booster/comport.c | 411 ++---
booster/util_proc.h | 26
booster/list.h | 723 +++++++++++
booster/atcmd.h | 93 +
/dev/null | 42
booster/at-esp32.h | 140 ++
booster/makefile | 25
booster/iniparser.h | 4
booster/iniparser.c | 6
25 files changed, 2,697 insertions(+), 1,037 deletions(-)
diff --git a/booster/README.md b/booster/README.md
new file mode 100644
index 0000000..2b4e7a9
--- /dev/null
+++ b/booster/README.md
@@ -0,0 +1,4 @@
+## booster
+
+LingYun embedded C program basic library
+
diff --git a/booster/at-esp32.c b/booster/at-esp32.c
new file mode 100644
index 0000000..df460c4
--- /dev/null
+++ b/booster/at-esp32.c
@@ -0,0 +1,388 @@
+/*********************************************************************************
+ * Copyright: (C) 2023 LingYun IoT System Studio.
+ * All rights reserved.
+ *
+ * Filename: at-esp32.c
+ * Description: This file is ESP32 AT command low level API functions
+ *
+ * Version: 1.0.0(11/08/23)
+ * Author: Guo Wenxue <guowenxue@gmail.com>
+ * ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
+ *
+ ********************************************************************************/
+
+#include "logger.h"
+#include "at-esp32.h"
+
+/*+------------------------+
+ *| Baisc AT command |
+ *+------------------------+*/
+
+static inline int check_at_ready(comport_t *comport)
+{
+ int times = 6;
+ int ready = 0;
+
+ while( times-- )
+ {
+ if( 0 == send_atcmd_check_ok(comport, "AT", 500) )
+ {
+ ready = 1;
+ break;
+ }
+ }
+
+ return ready;
+}
+
+/* AT command: AT+RST */
+int esp32_reset(comport_t *comport)
+{
+ int rv;
+
+ rv = send_atcmd(comport, "AT+RST", 5000, "ready", AT_ERRSTR, NULL, 0);
+ if( rv < 0)
+ {
+ log_error("send AT command to reset ESP32 failed, rv=%d\n", rv);
+ return -1;
+ }
+
+ if( check_at_ready(comport) )
+ {
+ log_info("send AT to reset ESP32 and AT command ready\n");
+ return 0;
+ }
+ else
+ {
+ log_info("send AT to reset ESP32 but AT command not ready\n");
+ return -3;
+ }
+}
+
+/* AT command: AT+RESTORE */
+int esp32_restore(comport_t *comport)
+{
+ int rv;
+
+ //rv = send_atcmd_check_ok(comport, "AT+RESTORE", 5000);
+ rv = send_atcmd(comport, "AT+RESTORE", 5000, "ready", AT_ERRSTR, NULL, 0);
+ if( rv < 0)
+ {
+ log_error("send AT command to restore ESP32 failed, rv=%d\n", rv);
+ return -1;
+ }
+
+ if( check_at_ready(comport) )
+ {
+ log_info("send AT command to resstore ESP32 ready\n");
+ return 0;
+ }
+ else
+ {
+ log_error("send AT command to restore ESP32 but AT not ready\n");
+ return -3;
+ }
+}
+
+/* AT command: ATE1 or ATE0 */
+int esp32_set_echo(comport_t *comport, int enable)
+{
+ char *at = enable? "ATE1" : "ATE0";
+
+ return send_atcmd_check_ok(comport, at, 500);
+}
+
+/* AT command: AT+GMR */
+int esp32_get_firmware(comport_t *comport, char *version, int size)
+{
+ if( !version || size<=0 )
+ return -1;
+
+ return send_atcmd_check_value(comport, "AT+GMR", 2000, version, size);
+}
+
+/* AT command: AT+SYSSTORE */
+int esp32_set_sysstore(comport_t *comport, int enable)
+{
+ char at[ATCMD_LEN]={'\0'};
+
+ snprintf(at, sizeof(at), "AT+SYSSTORE=%d", enable?1:0);
+
+ return send_atcmd_check_ok(comport, at, 1000);
+}
+
+/*+------------------------+
+ *| WiFi AT command |
+ *+------------------------+*/
+
+/* AT command: AT+CWMODE */
+int esp32_set_wmode(comport_t *comport, workmode_t mode, int autoconn)
+{
+ char at[ATCMD_LEN]={'\0'};
+
+ snprintf(at, sizeof(at), "AT+CWMODE=%d,%d", mode, autoconn?1:0);
+ return send_atcmd_check_ok(comport, at, 1500);
+}
+
+/* AT command: AT+CIPSTAMAC/CIPAPMAC */
+int esp32_get_macaddr(comport_t *comport, workmode_t mode, char *mac)
+{
+ if( !mac )
+ return -1;
+
+ if( MODE_SOFTAP == mode )
+ return send_atcmd_check_request(comport, "AT+CIPAPMAC?", 3000, mac, MAC_LEN);
+ else
+ return send_atcmd_check_request(comport, "AT+CIPSTAMAC?", 3000, mac, MAC_LEN);
+}
+
+/* AT command: AT+CIPSTA/AT+CIPAP */
+int esp32_set_ipaddr(comport_t *comport, workmode_t mode, char *ip, char *gateway)
+{
+ char at[ATCMD_LEN]={'\0'};
+
+ if( !ip || !gateway )
+ return -1;
+
+ if( MODE_SOFTAP == mode )
+ snprintf(at, sizeof(at), "AT+CIPAP=\"%s\",\"%s\"", ip, gateway);
+ else
+ snprintf(at, sizeof(at), "AT+CIPSTA=\"%s\",\"%s\"", ip, gateway);
+
+ return send_atcmd_check_ok(comport, at, 2000);
+}
+
+/* AT command: AT+CIPSTA/AT+CIPAP */
+int esp32_get_ipaddr(comport_t *comport, workmode_t mode, char *ip, char *gateway)
+{
+ char *at = MODE_SOFTAP==mode? "AT+CIPAP?" : "AT+CIPSTA?";
+ char buf[ATCMD_REPLY_LEN];
+ int rv;
+
+ if( !ip || !gateway )
+ return -1;
+
+ rv = send_atcmd_check_value(comport, at, 3000, buf, sizeof(buf));
+ if( rv < 0)
+ {
+ log_error("AT command query IP address failed, rv=%d\n", rv);
+ return rv;
+ }
+
+ rv = parser_request_value(buf, "ip", ip, IP_LEN);
+ if( rv < 0 )
+ {
+ log_error("Parser query IP address failed, rv=%d\n", rv);
+ return rv;
+ }
+
+ rv = parser_request_value(buf, "gateway", gateway, IP_LEN);
+ if( rv < 0 )
+ {
+ log_error("Parser query gateway address failed, rv=%d\n", rv);
+ return rv;
+ }
+
+ return 0;
+}
+
+/* AT command: AT+CWDHCP */
+int esp32_set_dhcp(comport_t *comport, workmode_t mode, int enable)
+{
+ char at[ATCMD_LEN]={'\0'};
+
+ snprintf(at, sizeof(at), "AT+CWDHCP=%d,%d", enable?1:0, mode);
+ return send_atcmd_check_ok(comport, at, 1500);
+}
+
+/* AT command: AT+CWAUTOCONN */
+int esp32_set_autoconn(comport_t *comport, int enable)
+{
+ char at[ATCMD_LEN]={'\0'};
+
+ snprintf(at, sizeof(at), "AT+CWAUTOCONN=%d", enable?1:0);
+ return send_atcmd_check_ok(comport, at, 1500);
+}
+
+/* AT command: AT+CWLAP */
+int esp32_list_ap(comport_t *comport, char *buf, int size)
+{
+ if( !buf || size<=0 )
+ return -1;
+
+ return send_atcmd_check_value(comport, "AT+CWLAP", 8000, buf, size);
+}
+
+/* AT command: AT+CWJAP */
+int esp32_connect_ap(comport_t *comport, char *ssid, char *pwd)
+{
+ char at[ATCMD_LEN]={'\0'};
+
+ if( !ssid || !pwd )
+ return -1;
+
+ snprintf(at, sizeof(at), "AT+CWJAP=\"%s\",\"%s\"", ssid, pwd);
+ return send_atcmd_check_ok(comport, at, 15000);
+}
+
+/* AT command: AT+CWQAP */
+int esp32_disconn_ap(comport_t *comport)
+{
+ return send_atcmd_check_ok(comport, "AT+CWQAP", 5000);
+}
+
+
+/* AT command: AT+CWSTATE? status value:
+ * - 0: ESP32 station has not started any Wi-Fi connection.
+ * - 1: ESP32 station has connected to an AP, but does not get an IPv4 address yet.
+ * - 2: ESP32 station has connected to an AP, and got an IPv4 address.
+ * - 3: ESP32 station is in Wi-Fi connecting or reconnecting state.
+ * - 4: ESP32 station is in Wi-Fi disconnected state
+ */
+int esp32_join_status(comport_t *comport, int *status, char *ssid)
+{
+ char buf[ATCMD_REPLY_LEN];
+ int rv;
+
+ if( !status || !ssid )
+ return -1;
+
+ rv = send_atcmd_check_request(comport, "AT+CWSTATE?", 3000, buf, sizeof(buf));
+ if( rv < 0)
+ {
+ log_error("AT command query join status failed, rv=%d\n", rv);
+ return rv;
+ }
+
+ sscanf(buf, "%d,%s", status, ssid);
+
+ return 0;
+}
+
+/* AT command: AT+PING */
+int esp32_ping(comport_t *comport, char *host, int timeout)
+{
+ char at[ATCMD_LEN]={'\0'};
+
+ if( !host )
+ return -1;
+
+ snprintf(at, sizeof(at), "AT+PING=\"%s\"", host);
+ return send_atcmd_check_ok(comport, at, timeout);
+}
+
+/* AT command: AT+CWSAP */
+int esp32_set_softap(comport_t *comport, char *ssid, char *pwd, int channel, encmode_t encmode)
+{
+ char at[ATCMD_LEN]={'\0'};
+
+ if( !ssid || !pwd )
+ return -1;
+
+ snprintf(at, sizeof(at), "AT+CWSAP=\"%s\",\"%s\",%d,%d", ssid, pwd, channel, encmode);
+ return send_atcmd_check_ok(comport, at, 5000);
+}
+
+/* AT command: AT+CWLIF */
+int esp32_list_client(comport_t *comport, char *buf, int size)
+{
+ if( !buf || size<=0 )
+ return -1;
+
+ return send_atcmd_check_value(comport, "AT+CWLIF", 8000, buf, size);
+}
+
+/*+------------------------+
+ *| Socket AT command |
+ *+------------------------+*/
+
+/* AT command: AT+CIPMUX */
+int esp32_set_socket_mux(comport_t *comport, int enable)
+{
+ char at[ATCMD_LEN]={'\0'};
+
+ snprintf(at, sizeof(at), "AT+CIPMUX=%d", enable?1:0);
+
+ return send_atcmd_check_ok(comport, at, 1500);
+}
+
+/* AT command: AT+CIPSERVERMAXCONN */
+int esp32_set_socket_clients(comport_t *comport, int max)
+{
+ char at[ATCMD_LEN]={'\0'};
+
+ if( max <= 0 )
+ return -1;
+
+ snprintf(at, sizeof(at), "AT+CIPSERVERMAXCONN=%d", max);
+
+ return send_atcmd_check_ok(comport, at, 1500);
+}
+
+/* AT command: AT+CIPSTO, timeout unit second */
+int esp32_set_socket_timeout(comport_t *comport, int timeout)
+{
+ char at[ATCMD_LEN]={'\0'};
+
+ if( timeout <= 0 )
+ return -1;
+
+ snprintf(at, sizeof(at), "AT+CIPSTO=%d", timeout);
+
+ return send_atcmd_check_ok(comport, at, 1500);
+}
+
+/* AT command: AT+CIPSERVER */
+int esp32_set_tcp_server(comport_t *comport, int port)
+{
+ char at[ATCMD_LEN]={'\0'};
+
+ if( port <= 0 )
+ return -1;
+
+ snprintf(at, sizeof(at), "AT+CIPSERVER=1,%d,\"TCP\"", port);
+
+ return send_atcmd_check_ok(comport, at, 1500);
+}
+
+/* AT command: AT+CIPSERVER */
+int esp32_del_tcp_server(comport_t *comport, int port)
+{
+ char at[ATCMD_LEN]={'\0'};
+
+ if( port <= 0 )
+ return -1;
+
+ snprintf(at, sizeof(at), "AT+CIPSERVER=0,%d,\"TCP\"", port);
+
+ return send_atcmd_check_ok(comport, at, 1500);
+}
+
+/* AT command: AT+CIPSTART */
+int esp32_set_tcp_client(comport_t *comport, int mux, char *host, int port)
+{
+ char at[ATCMD_LEN]={'\0'};
+ char buf[ATCMD_REPLY_LEN]={'\0'};
+ int keepalive = 60; /* unit second */
+ int rv,linkid = 0;
+
+ if( !host || port <= 0 )
+ return -1;
+
+ rv = esp32_set_socket_mux(comport, mux);
+ if(rv < 0)
+ return rv;
+
+ if( mux )
+ snprintf(at, sizeof(at), "AT+CIPSTART=1,\"TCP\",\"%s\",%d,%d", host, port, keepalive);
+ else
+ snprintf(at, sizeof(at), "AT+CIPSTART=\"TCP\",\"%s\",%d,%d", host, port, keepalive);
+
+ rv = send_atcmd_check_value(comport, at, 1500, buf, sizeof(buf));
+ if(rv < 0)
+ return rv;
+
+ sscanf(buf, "%d,", &linkid);
+
+ return linkid;
+}
diff --git a/booster/at-esp32.h b/booster/at-esp32.h
new file mode 100644
index 0000000..40d44e0
--- /dev/null
+++ b/booster/at-esp32.h
@@ -0,0 +1,140 @@
+/*********************************************************************************
+ * Copyright: (C) 2023 LingYun IoT System Studio.
+ * All rights reserved.
+ *
+ * Filename: at-esp32.h
+ * Description: This file is ESP32 AT command low level API functions
+ *
+ * Version: 1.0.0(11/08/23)
+ * Author: Guo Wenxue <guowenxue@gmail.com>
+ * ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
+ *
+ ********************************************************************************/
+
+#ifndef _AT_ESP32_H_
+#define _AT_ESP32_H_
+
+#include "atcmd.h"
+
+enum
+{
+ DISABLE = 0, /* common disable */
+ ENABLE, /* common enable */
+};
+
+#define MAC_LEN 18 /* 11:22:33:44:55:66 */
+#define IP_LEN 16 /* 255.255.255.255 */
+
+/*+------------------------+
+ *| Baisc AT command |
+ *+------------------------+*/
+
+/* AT command: AT+RST */
+extern int esp32_reset(comport_t *comport);
+
+/* AT command: AT+RESTORE */
+extern int esp32_restore(comport_t *comport);
+
+/* AT command: ATE1 or ATE0 */
+extern int esp32_set_echo(comport_t *comport, int enable);
+
+/* AT command: AT+GMR */
+extern int esp32_get_firmware(comport_t *comport, char *version, int size);
+
+/* AT command: AT+SYSSTORE */
+extern int esp32_set_sysstore(comport_t *comport, int enable);
+
+
+/*+------------------------+
+ *| WiFi AT command |
+ *+------------------------+*/
+typedef enum
+{
+ MODE_DISABLE=0, /* Wi-Fi RF will be disabled */
+ MODE_STATION, /* Station mode */
+ MODE_SOFTAP, /* SoftAP mode */
+ MODE_WDS, /* Wireless Distribution System: Both Station & SoftAP mode */
+} workmode_t;
+
+/* AT command: AT+CWMODE */
+extern int esp32_set_wmode(comport_t *comport, workmode_t mode, int autoconn);
+
+/* AT command: AT+CWDHCP */
+extern int esp32_set_dhcp(comport_t *comport, workmode_t mode, int enable);
+
+/* AT command: AT+CWAUTOCONN */
+extern int esp32_set_autoconn(comport_t *comport, int enable);
+
+/* AT command: AT+CIPSTAMAC/CIPAPMAC */
+extern int esp32_get_macaddr(comport_t *comport, workmode_t mode, char *mac);
+
+/* AT command: AT+CIPSTA/CIPAP */
+extern int esp32_get_ipaddr(comport_t *comport, workmode_t mode, char *ip, char *gateway);
+
+/* AT command: AT+CIPSTA/AT+CIPAP */
+extern int esp32_set_ipaddr(comport_t *comport, workmode_t mode, char *ip, char *gateway);
+
+/* AT command: AT+CWLAP */
+extern int esp32_list_ap(comport_t *comport, char *buf, int size);
+
+/* AT command: AT+CWJAP */
+extern int esp32_connect_ap(comport_t *comport, char *ssid, char *pwd);
+
+/* AT command: AT+CWQAP */
+extern int esp32_disconn_ap(comport_t *comport);
+
+/* AT command: AT+CWSTATE? , status value:
+ * - 0: ESP32 station has not started any Wi-Fi connection.
+ * - 1: ESP32 station has connected to an AP, but does not get an IPv4 address yet.
+ * - 2: ESP32 station has connected to an AP, and got an IPv4 address.
+ * - 3: ESP32 station is in Wi-Fi connecting or reconnecting state.
+ * - 4: ESP32 station is in Wi-Fi disconnected state
+ */
+extern int esp32_join_status(comport_t *comport, int *status, char *ssid);
+
+/* AT command: AT+PING */
+extern int esp32_ping(comport_t *comport, char *host, int timeout);
+
+/* AT command: AT+CWSAP */
+typedef enum
+{
+ MODE_OPEN,
+ /* WEP not support */
+ MODE_WPAPSK = 2,
+ MODE_WPA2PSK,
+ MODE_WPA_WPA2PSK,
+} encmode_t;
+extern int esp32_set_softap(comport_t *comport, char *ssid, char *pwd, int channel, encmode_t encmode);
+
+/* AT command: AT+CWLIF */
+extern int esp32_list_client(comport_t *comport, char *buf, int size);
+
+
+/*+------------------------+
+ *| Socket AT command |
+ *+------------------------+*/
+
+/* AT command: CIPMUX */
+extern int esp32_set_socket_mux(comport_t *comport, int enable);
+
+/* AT command: AT+CIPSERVERMAXCONN */
+extern int esp32_set_socket_clients(comport_t *comport, int max);
+
+/* AT command: AT+CIPSTO, timeout unit second */
+extern int esp32_set_socket_timeout(comport_t *comport, int timeout);
+
+/* AT command: AT+CIPSERVER */
+extern int esp32_set_tcp_server(comport_t *comport, int port);
+
+/* AT command: AT+CIPSERVER */
+extern int esp32_del_tcp_server(comport_t *comport, int port);
+
+/* AT command: AT+CIPSTART */
+extern int esp32_set_tcp_client(comport_t *comport, int mux, char *host, int port);
+
+/*+------------------------+
+ *| BLE AT command |
+ *+------------------------+*/
+// RFU
+
+#endif /* ----- #ifndef _AT_ESP32_H_ ----- */
diff --git a/booster/atcmd.c b/booster/atcmd.c
new file mode 100644
index 0000000..7308f1b
--- /dev/null
+++ b/booster/atcmd.c
@@ -0,0 +1,300 @@
+/*********************************************************************************
+ * Copyright: (C) 2023 LingYun IoT System Studio.
+ * All rights reserved.
+ *
+ * Filename: atcmd.c
+ * Description: This file is lowlevel AT command send and parser API functions
+ *
+ * Version: 1.0.0(11/08/23)
+ * Author: Guo Wenxue <guowenxue@gmail.com>
+ * ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
+ *
+ ********************************************************************************/
+
+#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;
+}
+
diff --git a/booster/atcmd.h b/booster/atcmd.h
new file mode 100644
index 0000000..0d7853e
--- /dev/null
+++ b/booster/atcmd.h
@@ -0,0 +1,93 @@
+/*********************************************************************************
+ * Copyright: (C) 2023 LingYun IoT System Studio.
+ * All rights reserved.
+ *
+ * Filename: atcmd.h
+ * Description: This file is lowlevel AT command send and parser API functions
+ *
+ * Version: 1.0.0(11/08/23)
+ * Author: Guo Wenxue <guowenxue@gmail.com>
+ * ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
+ *
+ ********************************************************************************/
+
+
+#ifndef _ATCMD_H_
+#define _ATCMD_H_
+
+#include "comport.h"
+
+/* AT command common reply message max length */
+#define ATCMD_REPLY_LEN 1024 /* Max AT command reply message length */
+#define ATCMD_LEN 256 /* Max AT command length */
+
+/* AT command reply message got expect or error string */
+#define AT_OKSTR "\r\nOK\r\n" /* expect string always be OK */
+#define AT_ERRSTR "\r\nERROR\r\n" /* error string always be ERROR */
+
+/* AT command should be end by $AT_SUFFIX */
+#define AT_SUFFIX "\r\n"
+
+/* send_atcmd)( return value status */
+enum
+{
+ ATRES_ERROR, /* AT command reply got error string, such as "ERROR\r\n" */
+ ATRES_EXPECT, /* AT command reply got expect string, such as "OK\r\n" */
+ ATRES_TIMEOUT, /* AT command not get error/expect string, receive util timeout */
+};
+
+/* 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);
+
+
+/*
+ * 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: ERROR
+ */
+int send_atcmd_check_ok(comport_t *comport, char *at, unsigned long timeout);
+
+
+/*
+ * 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: ERROR
+ */
+int send_atcmd_check_value(comport_t *comport, char *at, unsigned long timeout, char *reply, int size);
+
+/*
+ * 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);
+
+
+/*
+ * 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: ERROR
+ */
+int send_atcmd_check_request(comport_t *comport, char *at, unsigned long timeout, char *repy, int size);
+
+
+#endif /* ----- #ifndef _ATCMD_H_ ----- */
+
diff --git a/booster/comport.c b/booster/comport.c
index f6d9d10..4a31278 100644
--- a/booster/comport.c
+++ b/booster/comport.c
@@ -1,25 +1,34 @@
/*********************************************************************************
- * Copyright: (C) 2018 Guo Wenxue <guowenxue@gmail.com>
+ * Copyright: (C) 2023 LingYun IoT System Studio.
* All rights reserved.
*
- * Filename: cp_comport.c
- * Description: It's the comport operate library.
+ * Filename: comport.c
+ * Description: This file is linux comport common API functions
*
- * Version: 2.0.0(10/17/2018~)
+ * Version: 1.0.0(11/08/23)
* Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "10/17/2018 03:33:25 PM"
+ * ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
*
********************************************************************************/
-#include "comport.h"
+#include "comport.h"
-static void set_settings(comport_t *comport, const char *settings);
+#define CONFIG_PRINT_LOGGER
+//#define CONFIG_PRINT_STDOUT
-#ifdef COM_DEBUG
-void disp_settings(comport_t *comport);
+#if ( defined CONFIG_PRINT_LOGGER )
+#include "logger.h"
+#define dbg_print(format,args...) log_error(format, ##args)
+
+#elif ( defined CONFIG_PRINT_STDOUT )
+#define dbg_print(format,args...) printf(format, ##args)
+
+#else
+#define dbg_print(format,args...) do{} while(0);
#endif
+static inline void set_settings(comport_t * comport, const char *settings);
/*
* description: Open the serial port
@@ -40,64 +49,58 @@
if( !comport || !devname )
{
- COM_PRINT("%s() get invalid input arguments.\n", __FUNCTION__);
+ dbg_print("invalid input arugments\n");
return -1;
}
+ /*+-----------------------+
+ *| open the serial port |
+ *+-----------------------+*/
+
memset(comport, 0, sizeof(*comport));
- strncpy(comport->devname, devname, DEVNAME_LEN);
+ strncpy(comport->devname, devname, sizeof(comport->devname));
comport->baudrate = baudrate;
comport->fd = -1;
- comport->frag_size = 128;
-
+ comport->fragsize = CONFIG_DEF_FRAGSIZE;
set_settings(comport, settings);
-#ifdef COM_DEBUG
- disp_settings(comport);
-#endif
- /* Not a TTY device */
- if( !strstr(comport->devname, "tty"))
+ if( !strstr(comport->devname, "tty") )
{
- COM_PRINT("Open Not tty device \"%s\"\n", comport->devname);
+ dbg_print("comport device \"%s\" is not tty device\n", comport->devname);
return -2;
}
comport->fd = open(comport->devname, O_RDWR | O_NOCTTY | O_NONBLOCK);
- if (comport->fd < 0)
+ if( comport->fd<0 )
{
- rv = -3;
- goto CleanUp;
+ dbg_print("comport open \"%s\" failed:%s\n", comport->devname, strerror(errno));
+ return -3;
}
- COM_PRINT("Open device \"%s\"\n", comport->devname);
- if ((-1 != (old_flags = fcntl(comport->fd, F_GETFL, 0)))
- && (-1 != fcntl(comport->fd, F_SETFL, old_flags & ~O_NONBLOCK)))
+ if( (-1 != (old_flags = fcntl(comport->fd, F_GETFL, 0)))
+ && (-1 != fcntl(comport->fd, F_SETFL, old_flags & ~O_NONBLOCK)) )
{
/* Flush input and output */
- if (-1 == tcflush(comport->fd, TCIOFLUSH))
- {
- rv = -4;
- goto CleanUp;
- }
+ tcflush(comport->fd, TCIOFLUSH);
}
else
{
- rv = -5;
+ rv = -4;
goto CleanUp;
}
if (0 != tcgetattr(comport->fd, &old_cfg))
{
- rv = -6; // Failed to get Com settings
+ rv = -5;
goto CleanUp;
}
+
+ /*+-----------------------+
+ *| configure serial port |
+ *+-----------------------+*/
+
memset(&new_cfg, 0, sizeof(new_cfg));
-
- /*=====================================*/
- /* Configure comport */
- /*=====================================*/
-
new_cfg.c_cflag &= ~CSIZE;
new_cfg.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
new_cfg.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
@@ -123,11 +126,11 @@
/* Set the parity */
switch (comport->parity)
{
- case 0x01: // Odd
+ case 0x01: /* Odd */
new_cfg.c_cflag |= (PARENB | PARODD);
new_cfg.c_cflag |= (INPCK | ISTRIP);
break;
- case 0x02: // Even
+ case 0x02: /* Even */
new_cfg.c_cflag |= PARENB;
new_cfg.c_cflag &= ~PARODD;;
new_cfg.c_cflag |= (INPCK | ISTRIP);
@@ -153,16 +156,16 @@
/* Set flow control */
switch (comport->flowctrl)
{
- case 1: // Software control
+ case 1: /* Software control */
case 3:
new_cfg.c_cflag &= ~(CRTSCTS);
new_cfg.c_iflag |= (IXON | IXOFF);
break;
- case 2: // Hardware control
- new_cfg.c_cflag |= CRTSCTS; // Also called CRTSCTS
+ case 2: /* Hardware control */
+ new_cfg.c_cflag |= CRTSCTS;
new_cfg.c_iflag &= ~(IXON | IXOFF);
break;
- default: // NONE
+ default: /* NONE */
new_cfg.c_cflag &= ~(CRTSCTS);
new_cfg.c_iflag &= ~(IXON | IXOFF);
break;
@@ -171,53 +174,54 @@
/* Set baudrate */
switch (comport->baudrate)
{
- /* Upper is not POSIX(bits/termios-baud.h) */
- case 4000000:
- tmp = B4000000;
- break;
- case 3500000:
- tmp = B3500000;
- break;
- case 3000000:
- tmp = B3000000;
- break;
- case 2500000:
- tmp = B2500000;
- break;
- case 2000000:
- tmp = B2000000;
- break;
- case 1500000:
- tmp = B1500000;
- break;
- case 1152000:
- tmp = B1152000;
- break;
- case 1000000:
- tmp = B1000000;
- break;
- case 921600:
- tmp = B921600;
- break;
- case 576000:
- tmp = B576000;
- break;
- case 500000:
- tmp = B500000;
- break;
- case 460800:
- tmp = B460800;
- break;
- case 230400:
- tmp = B230400;
- break;
+ /* Upper is not POSIX(bits/termios-baud.h) */
+ case 4000000:
+ tmp = B4000000;
+ break;
+ case 3500000:
+ tmp = B3500000;
+ break;
+ case 3000000:
+ tmp = B3000000;
+ break;
+ case 2500000:
+ tmp = B2500000;
+ break;
+ case 2000000:
+ tmp = B2000000;
+ break;
+ case 1500000:
+ tmp = B1500000;
+ break;
+ case 1152000:
+ tmp = B1152000;
+ break;
+ case 1000000:
+ tmp = B1000000;
+ break;
+ case 921600:
+ tmp = B921600;
+ break;
+ case 576000:
+ tmp = B576000;
+ break;
+ case 500000:
+ tmp = B500000;
+ break;
+ case 460800:
+ tmp = B460800;
+ break;
+ case 230400:
+ tmp = B230400;
+ break;
case 115200:
tmp = B115200;
break;
case 57600:
tmp = B57600;
break;
- /* Below is POSIX(bits/termios.h) */
+
+ /* Below is POSIX(bits/termios.h) */
case 38400:
tmp = B38400;
break;
@@ -276,19 +280,15 @@
tcflush(comport->fd, TCIFLUSH);
if (0 != tcsetattr(comport->fd, TCSANOW, &new_cfg))
{
- rv = -7; // Failed to set device com port settings
+ rv = -6; // Failed to set device com port settings
goto CleanUp;
}
-
- COM_PRINT("Connected device \"%s\".\n", comport->devname);
rv = comport->fd;
CleanUp:
- COM_PRINT("Open device \"%s\" %s.\n", comport->devname, rv>0 ? "successfully" : "failure");
return rv;
}
-
/*
@@ -300,13 +300,12 @@
{
if( !comport )
{
- COM_PRINT("%s() get invalid input arguments.\n", __FUNCTION__);
+ dbg_print("invalid input arugments\n");
return ;
}
if ( comport->fd >= 0 )
{
- COM_PRINT("Close device \"%s\"\n", comport->devname);
close(comport->fd);
}
@@ -315,165 +314,127 @@
}
/*
- * description: write $send_bytes bytes data from $buf to $comport
+ * description: write $data_bytes $data to $comport
* return value: 0: write ok <0: write failure
*/
-int comport_send(comport_t *comport, char *buf, int send_bytes)
+int comport_send(comport_t *comport, char *data, int data_bytes)
{
+ char *ptr;
+ int left, bytes = 0;
int rv = 0;
- char *ptr, left_bytes;
- int send = 0;
- if ( !comport || !buf || send_bytes<=0 )
+ if( !comport || !data || data_bytes<=0 )
{
- COM_PRINT("%s() get invalid input arguments.\n", __FUNCTION__);
- rv = -1;
- goto CleanUp;
+ dbg_print("invalid input arugments\n");
+ return -1;
}
- if ( comport->fd < 0 ) // Comport not opened ?
+ if( comport->fd < 0 )
{
- rv = -3;
- COM_PRINT("Serail not connected.\n");
- goto CleanUp;
+ dbg_print("Serail port not opened\n");
+ return -2;
}
- //printf("Send %s with %d bytes.\n", buf, send_bytes);
+ ptr = data;
+ left = data_bytes;
-
- left_bytes = send_bytes;
- ptr = buf;
-
- while( left_bytes > 0 )
+ while( left > 0 )
{
/* Large data, then slice them to frag and send */
- send = left_bytes>comport->frag_size ? comport->frag_size : left_bytes;
-
- rv = write(comport->fd, ptr, send);
- if( rv<0 )
- {
- rv = -4;
- goto CleanUp;
- }
-
- left_bytes -= rv;
- ptr += rv;
+ bytes = left>comport->fragsize ? comport->fragsize : left;
+
+ rv = write(comport->fd, ptr, bytes);
+ if( rv<0 )
+ {
+ rv = -3;
+ break;
+ }
+
+ left -= rv;
+ ptr += rv;
}
- rv = 0;
-
-CleanUp:
return rv;
}
/*
- * description: read data from $comport in $timeout <ms> to $buf no more than $bufsize bytes
+ * description: read data from $comport in $timeout <ms> to $buf no more than $buf_size bytes
* return value: the actual read data bytes, <0: read failure
*/
-int comport_recv(comport_t *comport, char *buf, int bufsize, unsigned long timeout)
+int comport_recv(comport_t *comport, char *buf, int buf_size, unsigned long timeout)
{
- int rv = 0;
- int iRet;
fd_set rdfds, exfds;
- struct timeval stTime;
+ struct timeval to, *to_ptr = NULL;
+ int ret, rv = 0;
+ int bytes = 0;
- if ( !comport || !buf || bufsize<=0 )
+ if ( !comport || !buf || buf_size<=0 )
{
- COM_PRINT("%s() get invalid input arguments.\n", __FUNCTION__);
- rv = -1;
- goto CleanUp;
+ dbg_print("invalid input arugments\n");
+ return -1;
}
if ( comport->fd < 0 )
{
- COM_PRINT("%s() comport not connected.\n", __FUNCTION__);
- rv = -2;
- goto CleanUp;
+ dbg_print("Serail port not opened\n");
+ return -2;
}
+
+ memset(buf, 0, buf_size);
FD_ZERO(&rdfds);
FD_ZERO(&exfds);
FD_SET(comport->fd, &rdfds);
FD_SET(comport->fd, &exfds);
- if (0xFFFFFFFF != timeout)
+ if( TIMEOUT_NONE != timeout )
{
- stTime.tv_sec = (time_t) (timeout / 1000);
- stTime.tv_usec = (long)(1000 * (timeout % 1000));
-
- iRet = select(comport->fd + 1, &rdfds, 0, &exfds, &stTime);
- if (0 == iRet)
- {
- rv = 0;
- goto CleanUp;
- }
- else if (0 < iRet)
- {
- if (0 != FD_ISSET(comport->fd, &exfds))
- {
- rv = -6;
- COM_PRINT("Error checking recv status.\n");
- goto CleanUp;
- }
-
- if (0 == FD_ISSET(comport->fd, &rdfds))
- {
- rv = 0;
- COM_PRINT("No incoming data.\n");
- goto CleanUp;
- }
- }
- else
- {
- if (EINTR == errno)
- {
- COM_PRINT("catch interrupt signal.\n");
- rv = 0;
- }
- else
- {
- COM_PRINT("Check recv status failure.\n");
- rv = -7;
- }
-
- goto CleanUp;
- }
+ to.tv_sec = (time_t) (timeout / 1000);
+ to.tv_usec = (long)(1000 * (timeout % 1000));
+ to_ptr = &to;
}
- usleep(10000); /* sleep for 10ms for data incoming */
-
- // Get data from Com port
- iRet = read(comport->fd, buf, bufsize);
- if (0 > iRet)
+ while( 1 )
{
- if (EINTR == errno)
- rv = 0; // Interrupted signal catched
- else
- rv = -3; // Failed to read Com port
-
- goto CleanUp;
- }
-
-#if 0
- {
- int i=0;
- printf("Receive %d bytes data: \n", iRet);
- for(i=0; i<iRet; i++)
+ /* check got data arrive or not */
+ ret = select(comport->fd+1, &rdfds, 0, &exfds, to_ptr);
+ if( ret<0 )
{
- printf("0x%02x ", buf[i]);
+ /* EINTR means catch interrupt signal */
+ dbg_print("comport select() failed: %s\n", strerror(errno));
+ rv = EINTR==errno ? 0 : -3;
+ break;
}
- printf("\n");
+ else if( 0 == ret ) /* timeout */
+ {
+ break;
+ }
+
+ /* read data from comport */
+ ret = read(comport->fd, buf+bytes, buf_size-bytes);
+ if(ret <= 0)
+ {
+ dbg_print("comport read() failed: %s\n", strerror(errno));
+ break;
+ }
+
+ bytes += ret;
+ if( bytes >= buf_size )
+ break;
+
+ /* try to read data in 1ms again, if no data arrive it will break */
+ to.tv_sec = 0;
+ to.tv_usec = 10000;
+ to_ptr = &to;
}
-#endif
- rv = iRet;
+ if( !rv )
+ rv = bytes;
-CleanUp:
return rv;
-
}
@@ -484,11 +445,11 @@
* Output Args: NONE
* Return Value: NONE
*************************************************************************************/
-void set_settings(comport_t * comport, const char *settings)
+static inline void set_settings(comport_t * comport, const char *settings)
{
if( !settings || !comport )
{
- COM_PRINT("%s() get invalid input arguments.\n", __FUNCTION__);
+ dbg_print("invalid input arugments\n");
return ;
}
@@ -556,50 +517,4 @@
break;
}
}
-
-
-
-#ifdef COM_DEBUG
-void disp_settings(comport_t *comport)
-{
- COM_PRINT("Device:\t\t\t\"%s\"\n", comport->devname);
- COM_PRINT("Baudrate:\t\t%ld\n", comport->baudrate);
- COM_PRINT("DataBit:\t\t\'%d\'\n", comport->databit);
-
- switch (comport->parity)
- {
- case 0:
- COM_PRINT("Parity:\t\t\t\'N\'\n");
- break;
- case 1:
- COM_PRINT("Parity:\t\t\t\'O\'\n");
- break;
- case 2:
- COM_PRINT("Parity:\t\t\t\'E\'\n");
- break;
- case 3:
- COM_PRINT("Parity:\t\t\t\'S\'\n");
- break;
- }
- COM_PRINT("StopBit:\t\t\'%ld\'\n", (long int)comport->stopbit);
- switch (comport->flowctrl)
- {
- case 0:
- COM_PRINT("FlowCtrl:\t\t\'N\'\n");
- break;
- case 1:
- COM_PRINT("FlowCtrl:\t\t\'S\'\n");
- break;
- case 2:
- COM_PRINT("FlowCtrl:\t\t\'H\'\n");
- break;
- case 3:
- COM_PRINT("FlowCtrl:\t\t\'B\'\n");
- break;
- }
- COM_PRINT("\n");
- return;
-}
-#endif
-
diff --git a/booster/comport.h b/booster/comport.h
index 755e02e..2754d43 100644
--- a/booster/comport.h
+++ b/booster/comport.h
@@ -1,17 +1,18 @@
/*********************************************************************************
- * Copyright: (C) 2018 LingYun IoT System Studio
+ * Copyright: (C) 2023 LingYun IoT System Studio.
* All rights reserved.
*
- * Filename: comport.h
- * Description: This head file is for the common TTY/Serial port operator library
+ * Filename: comport.c
+ * Description: This file is linux comport common API functions
*
- * Version: 1.0.0(10/17/2018~)
+ * Version: 1.0.0(11/08/23)
* Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "10/17/2018 03:33:25 PM"
+ * ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
*
********************************************************************************/
-#ifndef __COMPORT_H_
-#define __COMPORT_H_
+
+#ifndef _COMPORT_H_
+#define _COMPORT_H_
#include <stdio.h>
#include <stdlib.h>
@@ -27,36 +28,25 @@
#include <sys/stat.h>
#include <sys/select.h>
-
-#ifndef DEVNAME_LEN
-#define DEVNAME_LEN 32
-#endif
-
-//#define COM_DEBUG
-#ifdef COM_DEBUG
-#define COM_PRINT(format,args...) printf(format, ##args)
-#else
-#define COM_PRINT(format,args...) do{} while(0);
-#endif
-
+#define CONFIG_DEF_FRAGSIZE 128
typedef struct comport_s
{
- char devname[DEVNAME_LEN];
+ char devname[32];
unsigned char databit, parity, stopbit, flowctrl;
long baudrate;
int fd;
- int frag_size;
+ int fragsize; /* frag size when do large data send */
} comport_t;
/*
- * description: Open the comport specified by $comport
+ * description: Open the comport and returned by $comport
*
- * input args: $comport: corresponding comport point
+ * input args: $comport: corresponding comport handler
* $devname: The comport device name path, such as '/dev/ttyS3'
- * $baudrate: The baudrate, such as 115200
- * $settings: The databit,parity,stopbit,flowctrl settings, such as '8N1N'
+ * $baudrate: The baudrate, such as 115200
+ * $settings: The databit,parity,stopbit,flowctrl settings, such as '8N1N'
*
* return value: The comport opened file description, <0 means failure
*/
@@ -64,21 +54,21 @@
/*
* description: close comport
- * input args: $comport: corresponding comport point
+ * input args: $comport: corresponding comport handler
*/
extern void comport_close(comport_t *comport);
/*
- * description: write $send_bytes bytes data from $buf to $comport
+ * description: write $bytes $data to $comport
* return value: 0: write ok <0: write failure
*/
-extern int comport_send(comport_t *comport, char *buf, int send_bytes);
+extern int comport_send(comport_t *comport, char *data, int data_bytes);
/*
- * description: read data from $comport in $timeout <ms> to $buf no more than $bufsize bytes
+ * description: read data from $comport in $timeout <ms> to $buf no more than $buf_size bytes
* return value: the actual read data bytes, <0: read failure
*/
-extern int comport_recv(comport_t *comport, char *buf, int bufsize, unsigned long timeout);
-
+#define TIMEOUT_NONE 0
+extern int comport_recv(comport_t *comport, char *buf, int buf_size, unsigned long timeout);
#endif
diff --git a/booster/dictionary.c b/booster/dictionary.c
index cb7ccd4..0fd5000 100644
--- a/booster/dictionary.c
+++ b/booster/dictionary.c
@@ -3,6 +3,7 @@
@file dictionary.c
@author N. Devillard
@brief Implements a dictionary for string variables.
+ @url https://github.com/ndevilla/iniparser
This module implements a simple dictionary object, i.e. a list
of string/string associations. This object is useful to store e.g.
@@ -140,7 +141,7 @@
/**
@brief Create a new dictionary object.
@param size Optional initial size of the dictionary.
- @return 1 newly allocated dictionary objet.
+ @return 1 newly allocated dictionary object.
This function allocates a new dictionary object of given size and returns
it. If you do not know in advance (roughly) the number of entries in the
diff --git a/booster/dictionary.h b/booster/dictionary.h
index d04b6ce..87d31d9 100644
--- a/booster/dictionary.h
+++ b/booster/dictionary.h
@@ -4,6 +4,7 @@
@file dictionary.h
@author N. Devillard
@brief Implements a dictionary for string variables.
+ @url https://github.com/ndevilla/iniparser
This module implements a simple dictionary object, i.e. a list
of string/string associations. This object is useful to store e.g.
@@ -73,7 +74,7 @@
/**
@brief Create a new dictionary object.
@param size Optional initial size of the dictionary.
- @return 1 newly allocated dictionary objet.
+ @return 1 newly allocated dictionary object.
This function allocates a new dictionary object of given size and returns
it. If you do not know in advance (roughly) the number of entries in the
diff --git a/booster/esp32.c b/booster/esp32.c
new file mode 100644
index 0000000..242c4d3
--- /dev/null
+++ b/booster/esp32.c
@@ -0,0 +1,166 @@
+/*********************************************************************************
+ * Copyright: (C) 2023 LingYun IoT System Studio.
+ * All rights reserved.
+ *
+ * Filename: esp32.c
+ * Description: This file is ESP32 high level logic API functions
+ *
+ * Version: 1.0.0(11/08/23)
+ * Author: Guo Wenxue <guowenxue@gmail.com>
+ * ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
+ *
+ ********************************************************************************/
+
+#include "logger.h"
+#include "esp32.h"
+
+int esp32_init_module(comport_t *comport)
+{
+ int rv;
+ char version[256] = {0};
+
+ if( !comport )
+ return -1;
+
+ rv = esp32_reset(comport);
+ if( rv < 0)
+ {
+ log_error("Reset ESP32 WiFi module failed: %d\n", rv);
+ return rv;
+ }
+
+ esp32_set_echo(comport, DISABLE);
+
+ esp32_set_sysstore(comport, ENABLE);
+
+ rv = esp32_get_firmware(comport, version, sizeof(version));
+ if( rv < 0)
+ {
+ log_error("Query ESP32 firmware version failed: %d\n", rv);
+ return rv;
+ }
+
+ log_info("ESP32 firmware version:\n%s\n", version);
+
+ return 0;
+}
+
+int esp32_setup_softap(comport_t *comport, char *ssid, char *pwd)
+{
+ esp32_set_wmode(comport, MODE_SOFTAP, ENABLE);
+
+ esp32_set_ipaddr(comport, MODE_SOFTAP, DEF_SOFTAP_IPADDR, DEF_SOFTAP_IPADDR);
+
+ esp32_set_dhcp(comport, MODE_SOFTAP, ENABLE);
+
+ esp32_set_softap(comport, ssid, pwd, 11, MODE_WPA2PSK);
+
+ return 0;
+}
+
+int esp32_join_network(comport_t *comport, char *ssid, char *pwd)
+{
+ int rv, status = 0;
+ int times=10;
+ char buf[128] = {0};
+
+ if( !comport )
+ return -1;
+
+ esp32_join_status(comport, &status, buf);
+ if( 2==status && !strcmp(buf, ssid) )
+ {
+ log_info("ESP32 connected to \"%s\" already\n", ssid);
+ return 0;
+ }
+
+ esp32_set_wmode(comport, MODE_STATION, ENABLE);
+
+ esp32_set_dhcp(comport, MODE_STATION, ENABLE);
+
+ rv = esp32_connect_ap(comport, ssid, pwd);
+ if( rv < 0 )
+ {
+ log_error("connect to AP \"%s\" failed, rv=%d", ssid, rv);
+ return rv;
+ }
+
+ while(times--)
+ {
+ rv = esp32_join_status(comport, &status, buf);
+ if( 2 == status )
+ {
+ log_info("ESP32 connected to \"%s\" already\n", ssid);
+ return 0;
+ }
+ rv = -3;
+ }
+
+ return rv;
+}
+
+
+int esp32_check_network(comport_t *comport)
+{
+ int rv, times=5;
+ char ip[IP_LEN] = {0};
+ char gateway[IP_LEN] = {0};
+
+ memset(ip, 0, sizeof(ip));
+ memset(gateway, 0, sizeof(gateway));
+ rv = esp32_get_ipaddr(comport, MODE_STATION, ip, gateway);
+ if( rv<0 )
+ return rv;
+
+ if( !strlen(ip) || !strlen(gateway) )
+ return -3;
+
+ log_info("IP address: %s, netmask: %s\n", ip, gateway);
+
+ while( times-- )
+ {
+ if( !(rv=esp32_ping(comport, gateway, 5000)) )
+ {
+ rv = 0;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int esp32_setup_tcp_server(comport_t *comport, int port)
+{
+ int rv;
+
+ rv = esp32_set_socket_mux(comport, ENABLE);
+ if(rv<0)
+ return rv;
+
+ rv = esp32_set_socket_clients(comport, 2);
+ if(rv<0)
+ return rv;
+
+ rv = esp32_set_tcp_server(comport, port);
+ if(rv<0)
+ return rv;
+
+ rv = esp32_set_socket_timeout(comport, 600);
+ if(rv<0)
+ return rv;
+
+ return 0;
+}
+
+int esp32_setup_tcp_client(comport_t *comport, char *host, int port)
+{
+ int rv;
+
+ rv = esp32_set_tcp_client(comport, DISABLE, host, port);
+ if(rv<0)
+ return rv;
+
+
+ return 0;
+}
+
diff --git a/booster/esp32.h b/booster/esp32.h
new file mode 100644
index 0000000..1052679
--- /dev/null
+++ b/booster/esp32.h
@@ -0,0 +1,35 @@
+/*********************************************************************************
+ * Copyright: (C) 2023 LingYun IoT System Studio.
+ * All rights reserved.
+ *
+ * Filename: esp32.h
+ * Description: This file is ESP32 high level logic API functions
+ *
+ * Version: 1.0.0(11/08/23)
+ * Author: Guo Wenxue <guowenxue@gmail.com>
+ * ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
+ *
+ ********************************************************************************/
+
+#ifndef _ESP32_H_
+#define _ESP32_H_
+
+#include "at-esp32.h"
+
+#define DEF_SOFTAP_IPADDR "192.168.8.1"
+#define DEF_SOFTAP_SSID "Router_ESP32"
+#define DEF_SOFTAP_PWD "12345678"
+
+extern int esp32_init_module(comport_t *comport);
+
+extern int esp32_setup_softap(comport_t *comport, char *ssid, char *pwd);
+
+extern int esp32_join_network(comport_t *comport, char *ssid, char *pwd);
+
+extern int esp32_check_network(comport_t *comport);
+
+extern int esp32_setup_tcp_server(comport_t *comport, int port);
+
+extern int esp32_setup_tcp_client(comport_t *comport, char *host, int port);
+
+#endif /* ----- #ifndef _ESP32_H_ ----- */
diff --git a/booster/iniparser.c b/booster/iniparser.c
index 8694dd4..3a446e5 100644
--- a/booster/iniparser.c
+++ b/booster/iniparser.c
@@ -1,10 +1,10 @@
/*-------------------------------------------------------------------------*/
/**
- @file iniparser.c v4.1
+ @file iniparser.c
@author N. Devillard
- @url https://github.com/ndevilla/iniparser
@brief Parser for ini files.
+ @url https://github.com/ndevilla/iniparser
*/
/*--------------------------------------------------------------------------*/
/*---------------------------- Includes ------------------------------------*/
@@ -719,7 +719,7 @@
char line [ASCIILINESZ+1] ;
char section [ASCIILINESZ+1] ;
char key [ASCIILINESZ+1] ;
- char tmp [(ASCIILINESZ * 2) + 1] ;
+ char tmp [(ASCIILINESZ * 2) + 2] ;
char val [ASCIILINESZ+1] ;
int last=0 ;
diff --git a/booster/iniparser.h b/booster/iniparser.h
index 1fdfe58..6a137c5 100644
--- a/booster/iniparser.h
+++ b/booster/iniparser.h
@@ -1,10 +1,10 @@
/*-------------------------------------------------------------------------*/
/**
- @file iniparser.h v4.1
+ @file iniparser.h
@author N. Devillard
- @url https://github.com/ndevilla/iniparser
@brief Parser for ini files.
+ @url https://github.com/ndevilla/iniparser
*/
/*--------------------------------------------------------------------------*/
diff --git a/booster/linux_list.h b/booster/linux_list.h
index 9ac0720..b927b14 100644
--- a/booster/linux_list.h
+++ b/booster/linux_list.h
@@ -66,18 +66,18 @@
*/
struct list_head {
- struct list_head *next, *prev;
+ struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
- struct list_head name = LIST_HEAD_INIT(name)
+ struct list_head name = LIST_HEAD_INIT(name)
static inline void INIT_LIST_HEAD(struct list_head *list)
{
- list->next = list;
- list->prev = list;
+ list->next = list;
+ list->prev = list;
}
/*
@@ -87,13 +87,13 @@
* the prev/next entries already!
*/
static inline void __list_add(struct list_head *new,
- struct list_head *prev,
- struct list_head *next)
+ struct list_head *prev,
+ struct list_head *next)
{
- next->prev = new;
- new->next = next;
- new->prev = prev;
- prev->next = new;
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
}
/**
@@ -106,7 +106,7 @@
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
- __list_add(new, head, head->next);
+ __list_add(new, head, head->next);
}
/**
@@ -119,7 +119,7 @@
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
- __list_add(new, head->prev, head);
+ __list_add(new, head->prev, head);
}
/*
@@ -131,8 +131,8 @@
*/
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
- next->prev = prev;
- prev->next = next;
+ next->prev = prev;
+ prev->next = next;
}
/**
@@ -143,9 +143,9 @@
*/
static inline void list_del(struct list_head *entry)
{
- __list_del(entry->prev, entry->next);
- entry->next = LIST_POISON1;
- entry->prev = LIST_POISON2;
+ __list_del(entry->prev, entry->next);
+ entry->next = LIST_POISON1;
+ entry->prev = LIST_POISON2;
}
/**
@@ -156,19 +156,19 @@
* If @old was empty, it will be overwritten.
*/
static inline void list_replace(struct list_head *old,
- struct list_head *new)
+ struct list_head *new)
{
- new->next = old->next;
- new->next->prev = new;
- new->prev = old->prev;
- new->prev->next = new;
+ new->next = old->next;
+ new->next->prev = new;
+ new->prev = old->prev;
+ new->prev->next = new;
}
static inline void list_replace_init(struct list_head *old,
- struct list_head *new)
+ struct list_head *new)
{
- list_replace(old, new);
- INIT_LIST_HEAD(old);
+ list_replace(old, new);
+ INIT_LIST_HEAD(old);
}
/**
@@ -177,8 +177,8 @@
*/
static inline void list_del_init(struct list_head *entry)
{
- __list_del(entry->prev, entry->next);
- INIT_LIST_HEAD(entry);
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
}
/**
@@ -188,8 +188,8 @@
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
- __list_del(list->prev, list->next);
- list_add(list, head);
+ __list_del(list->prev, list->next);
+ list_add(list, head);
}
/**
@@ -198,10 +198,10 @@
* @head: the head that will follow our entry
*/
static inline void list_move_tail(struct list_head *list,
- struct list_head *head)
+ struct list_head *head)
{
- __list_del(list->prev, list->next);
- list_add_tail(list, head);
+ __list_del(list->prev, list->next);
+ list_add_tail(list, head);
}
/**
@@ -210,9 +210,9 @@
* @head: the head of the list
*/
static inline int list_is_last(const struct list_head *list,
- const struct list_head *head)
+ const struct list_head *head)
{
- return list->next == head;
+ return list->next == head;
}
/**
@@ -221,7 +221,7 @@
*/
static inline int list_empty(const struct list_head *head)
{
- return head->next == head;
+ return head->next == head;
}
/**
@@ -239,8 +239,8 @@
*/
static inline int list_empty_careful(const struct list_head *head)
{
- struct list_head *next = head->next;
- return (next == head) && (next == head->prev);
+ struct list_head *next = head->next;
+ return (next == head) && (next == head->prev);
}
/**
@@ -249,19 +249,19 @@
*/
static inline int list_is_singular(const struct list_head *head)
{
- return !list_empty(head) && (head->next == head->prev);
+ return !list_empty(head) && (head->next == head->prev);
}
static inline void __list_cut_position(struct list_head *list,
- struct list_head *head, struct list_head *entry)
+ struct list_head *head, struct list_head *entry)
{
- struct list_head *new_first = entry->next;
- list->next = head->next;
- list->next->prev = list;
- list->prev = entry;
- entry->next = list;
- head->next = new_first;
- new_first->prev = head;
+ struct list_head *new_first = entry->next;
+ list->next = head->next;
+ list->next->prev = list;
+ list->prev = entry;
+ entry->next = list;
+ head->next = new_first;
+ new_first->prev = head;
}
/**
@@ -269,7 +269,7 @@
* @list: a new list to add all removed entries
* @head: a list with entries
* @entry: an entry within head, could be the head itself
- * and if so we won't cut the list
+ * and if so we won't cut the list
*
* This helper moves the initial part of @head, up to and
* including @entry, from @head to @list. You should
@@ -279,31 +279,31 @@
*
*/
static inline void list_cut_position(struct list_head *list,
- struct list_head *head, struct list_head *entry)
+ struct list_head *head, struct list_head *entry)
{
- if (list_empty(head))
- return;
- if (list_is_singular(head) &&
- (head->next != entry && head != entry))
- return;
- if (entry == head)
- INIT_LIST_HEAD(list);
- else
- __list_cut_position(list, head, entry);
+ if (list_empty(head))
+ return;
+ if (list_is_singular(head) &&
+ (head->next != entry && head != entry))
+ return;
+ if (entry == head)
+ INIT_LIST_HEAD(list);
+ else
+ __list_cut_position(list, head, entry);
}
static inline void __list_splice(const struct list_head *list,
- struct list_head *prev,
- struct list_head *next)
+ struct list_head *prev,
+ struct list_head *next)
{
- struct list_head *first = list->next;
- struct list_head *last = list->prev;
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
- first->prev = prev;
- prev->next = first;
+ first->prev = prev;
+ prev->next = first;
- last->next = next;
- next->prev = last;
+ last->next = next;
+ next->prev = last;
}
/**
@@ -312,10 +312,10 @@
* @head: the place to add it in the first list.
*/
static inline void list_splice(const struct list_head *list,
- struct list_head *head)
+ struct list_head *head)
{
- if (!list_empty(list))
- __list_splice(list, head, head->next);
+ if (!list_empty(list))
+ __list_splice(list, head, head->next);
}
/**
@@ -324,10 +324,10 @@
* @head: the place to add it in the first list.
*/
static inline void list_splice_tail(struct list_head *list,
- struct list_head *head)
+ struct list_head *head)
{
- if (!list_empty(list))
- __list_splice(list, head->prev, head);
+ if (!list_empty(list))
+ __list_splice(list, head->prev, head);
}
/**
@@ -338,12 +338,12 @@
* The list at @list is reinitialised
*/
static inline void list_splice_init(struct list_head *list,
- struct list_head *head)
+ struct list_head *head)
{
- if (!list_empty(list)) {
- __list_splice(list, head, head->next);
- INIT_LIST_HEAD(list);
- }
+ if (!list_empty(list)) {
+ __list_splice(list, head, head->next);
+ INIT_LIST_HEAD(list);
+ }
}
/**
@@ -355,47 +355,47 @@
* The list at @list is reinitialised
*/
static inline void list_splice_tail_init(struct list_head *list,
- struct list_head *head)
+ struct list_head *head)
{
- if (!list_empty(list)) {
- __list_splice(list, head->prev, head);
- INIT_LIST_HEAD(list);
- }
+ if (!list_empty(list)) {
+ __list_splice(list, head->prev, head);
+ INIT_LIST_HEAD(list);
+ }
}
/**
* list_entry - get the struct for this entry
- * @ptr: the &struct list_head pointer.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the list_struct within the struct.
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
- container_of(ptr, type, member)
+ container_of(ptr, type, member)
/**
* list_first_entry - get the first element from a list
- * @ptr: the list head to take the element from.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the list_struct within the struct.
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_first_entry(ptr, type, member) \
- list_entry((ptr)->next, type, member)
+ list_entry((ptr)->next, type, member)
/**
- * list_for_each - iterate over a list
- * @pos: the &struct list_head to use as a loop cursor.
- * @head: the head for your list.
+ * list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
*/
#define list_for_each(pos, head) \
- for (pos = (head)->next; prefetch(pos->next), pos != (head); \
- pos = pos->next)
+ for (pos = (head)->next; prefetch(pos->next), pos != (head); \
+ pos = pos->next)
/**
- * __list_for_each - iterate over a list
- * @pos: the &struct list_head to use as a loop cursor.
- * @head: the head for your list.
+ * __list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
*
* This variant differs from list_for_each() in that it's the
* simplest possible list iteration code, no prefetching is done.
@@ -403,170 +403,170 @@
* or 1 entry) most of the time.
*/
#define __list_for_each(pos, head) \
- for (pos = (head)->next; pos != (head); pos = pos->next)
+ for (pos = (head)->next; pos != (head); pos = pos->next)
/**
- * list_for_each_prev - iterate over a list backwards
- * @pos: the &struct list_head to use as a loop cursor.
- * @head: the head for your list.
+ * list_for_each_prev - iterate over a list backwards
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
*/
#define list_for_each_prev(pos, head) \
- for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
- pos = pos->prev)
+ for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
+ pos = pos->prev)
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
- * @pos: the &struct list_head to use as a loop cursor.
- * @n: another &struct list_head to use as temporary storage
- * @head: the head for your list.
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
*/
#define list_for_each_safe(pos, n, head) \
- for (pos = (head)->next, n = pos->next; pos != (head); \
- pos = n, n = pos->next)
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
/**
* list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
- * @pos: the &struct list_head to use as a loop cursor.
- * @n: another &struct list_head to use as temporary storage
- * @head: the head for your list.
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
*/
#define list_for_each_prev_safe(pos, n, head) \
- for (pos = (head)->prev, n = pos->prev; \
- prefetch(pos->prev), pos != (head); \
- pos = n, n = pos->prev)
+ for (pos = (head)->prev, n = pos->prev; \
+ prefetch(pos->prev), pos != (head); \
+ pos = n, n = pos->prev)
/**
- * list_for_each_entry - iterate over list of given type
- * @pos: the type * to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
*/
-#define list_for_each_entry(pos, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member); \
- prefetch(pos->member.next), &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member))
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member); \
+ prefetch(pos->member.next), &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_reverse - iterate backwards over list of given type.
- * @pos: the type * to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
*/
-#define list_for_each_entry_reverse(pos, head, member) \
- for (pos = list_entry((head)->prev, typeof(*pos), member); \
- prefetch(pos->member.prev), &pos->member != (head); \
- pos = list_entry(pos->member.prev, typeof(*pos), member))
+#define list_for_each_entry_reverse(pos, head, member) \
+ for (pos = list_entry((head)->prev, typeof(*pos), member); \
+ prefetch(pos->member.prev), &pos->member != (head); \
+ pos = list_entry(pos->member.prev, typeof(*pos), member))
/**
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
- * @pos: the type * to use as a start point
- * @head: the head of the list
- * @member: the name of the list_struct within the struct.
+ * @pos: the type * to use as a start point
+ * @head: the head of the list
+ * @member: the name of the list_struct within the struct.
*
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
*/
#define list_prepare_entry(pos, head, member) \
- ((pos) ? : list_entry(head, typeof(*pos), member))
+ ((pos) ? : list_entry(head, typeof(*pos), member))
/**
* list_for_each_entry_continue - continue iteration over list of given type
- * @pos: the type * to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
*
* Continue to iterate over list of given type, continuing after
* the current position.
*/
-#define list_for_each_entry_continue(pos, head, member) \
- for (pos = list_entry(pos->member.next, typeof(*pos), member); \
- prefetch(pos->member.next), &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member))
+#define list_for_each_entry_continue(pos, head, member) \
+ for (pos = list_entry(pos->member.next, typeof(*pos), member); \
+ prefetch(pos->member.next), &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_continue_reverse - iterate backwards from the given point
- * @pos: the type * to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
*
* Start to iterate over list of given type backwards, continuing after
* the current position.
*/
-#define list_for_each_entry_continue_reverse(pos, head, member) \
- for (pos = list_entry(pos->member.prev, typeof(*pos), member); \
- prefetch(pos->member.prev), &pos->member != (head); \
- pos = list_entry(pos->member.prev, typeof(*pos), member))
+#define list_for_each_entry_continue_reverse(pos, head, member) \
+ for (pos = list_entry(pos->member.prev, typeof(*pos), member); \
+ prefetch(pos->member.prev), &pos->member != (head); \
+ pos = list_entry(pos->member.prev, typeof(*pos), member))
/**
* list_for_each_entry_from - iterate over list of given type from the current point
- * @pos: the type * to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing from current position.
*/
-#define list_for_each_entry_from(pos, head, member) \
- for (; prefetch(pos->member.next), &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member))
+#define list_for_each_entry_from(pos, head, member) \
+ for (; prefetch(pos->member.next), &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @pos: the type * to use as a loop cursor.
- * @n: another type * to use as temporary storage
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
*/
-#define list_for_each_entry_safe(pos, n, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member), \
- n = list_entry(pos->member.next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = n, n = list_entry(n->member.next, typeof(*n), member))
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_continue
- * @pos: the type * to use as a loop cursor.
- * @n: another type * to use as temporary storage
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing after current point,
* safe against removal of list entry.
*/
-#define list_for_each_entry_safe_continue(pos, n, head, member) \
- for (pos = list_entry(pos->member.next, typeof(*pos), member), \
- n = list_entry(pos->member.next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = n, n = list_entry(n->member.next, typeof(*n), member))
+#define list_for_each_entry_safe_continue(pos, n, head, member) \
+ for (pos = list_entry(pos->member.next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_from
- * @pos: the type * to use as a loop cursor.
- * @n: another type * to use as temporary storage
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
*
* Iterate over list of given type from current point, safe against
* removal of list entry.
*/
-#define list_for_each_entry_safe_from(pos, n, head, member) \
- for (n = list_entry(pos->member.next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = n, n = list_entry(n->member.next, typeof(*n), member))
+#define list_for_each_entry_safe_from(pos, n, head, member) \
+ for (n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_reverse
- * @pos: the type * to use as a loop cursor.
- * @n: another type * to use as temporary storage
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
*
* Iterate backwards over list of given type, safe against removal
* of list entry.
*/
-#define list_for_each_entry_safe_reverse(pos, n, head, member) \
- for (pos = list_entry((head)->prev, typeof(*pos), member), \
- n = list_entry(pos->member.prev, typeof(*pos), member); \
- &pos->member != (head); \
- pos = n, n = list_entry(n->member.prev, typeof(*n), member))
+#define list_for_each_entry_safe_reverse(pos, n, head, member) \
+ for (pos = list_entry((head)->prev, typeof(*pos), member), \
+ n = list_entry(pos->member.prev, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.prev, typeof(*n), member))
/*
* Double linked lists with a single pointer list head.
@@ -576,11 +576,11 @@
*/
struct hlist_head {
- struct hlist_node *first;
+ struct hlist_node *first;
};
struct hlist_node {
- struct hlist_node *next, **pprev;
+ struct hlist_node *next, **pprev;
};
#define HLIST_HEAD_INIT { .first = NULL }
@@ -588,134 +588,134 @@
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{
- h->next = NULL;
- h->pprev = NULL;
+ h->next = NULL;
+ h->pprev = NULL;
}
static inline int hlist_unhashed(const struct hlist_node *h)
{
- return !h->pprev;
+ return !h->pprev;
}
static inline int hlist_empty(const struct hlist_head *h)
{
- return !h->first;
+ return !h->first;
}
static inline void __hlist_del(struct hlist_node *n)
{
- struct hlist_node *next = n->next;
- struct hlist_node **pprev = n->pprev;
- *pprev = next;
- if (next)
- next->pprev = pprev;
+ struct hlist_node *next = n->next;
+ struct hlist_node **pprev = n->pprev;
+ *pprev = next;
+ if (next)
+ next->pprev = pprev;
}
static inline void hlist_del(struct hlist_node *n)
{
- __hlist_del(n);
- n->next = LIST_POISON1;
- n->pprev = LIST_POISON2;
+ __hlist_del(n);
+ n->next = LIST_POISON1;
+ n->pprev = LIST_POISON2;
}
static inline void hlist_del_init(struct hlist_node *n)
{
- if (!hlist_unhashed(n)) {
- __hlist_del(n);
- INIT_HLIST_NODE(n);
- }
+ if (!hlist_unhashed(n)) {
+ __hlist_del(n);
+ INIT_HLIST_NODE(n);
+ }
}
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
- struct hlist_node *first = h->first;
- n->next = first;
- if (first)
- first->pprev = &n->next;
- h->first = n;
- n->pprev = &h->first;
+ struct hlist_node *first = h->first;
+ n->next = first;
+ if (first)
+ first->pprev = &n->next;
+ h->first = n;
+ n->pprev = &h->first;
}
/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n,
- struct hlist_node *next)
+ struct hlist_node *next)
{
- n->pprev = next->pprev;
- n->next = next;
- next->pprev = &n->next;
- *(n->pprev) = n;
+ n->pprev = next->pprev;
+ n->next = next;
+ next->pprev = &n->next;
+ *(n->pprev) = n;
}
static inline void hlist_add_after(struct hlist_node *n,
- struct hlist_node *next)
+ struct hlist_node *next)
{
- next->next = n->next;
- n->next = next;
- next->pprev = &n->next;
+ next->next = n->next;
+ n->next = next;
+ next->pprev = &n->next;
- if(next->next)
- next->next->pprev = &next->next;
+ if(next->next)
+ next->next->pprev = &next->next;
}
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
#define hlist_for_each(pos, head) \
- for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
- pos = pos->next)
+ for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
+ pos = pos->next)
#define hlist_for_each_safe(pos, n, head) \
- for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
- pos = n)
+ for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
+ pos = n)
/**
- * hlist_for_each_entry - iterate over list of given type
- * @tpos: the type * to use as a loop cursor.
- * @pos: the &struct hlist_node to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the hlist_node within the struct.
+ * hlist_for_each_entry - iterate over list of given type
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
*/
-#define hlist_for_each_entry(tpos, pos, head, member) \
- for (pos = (head)->first; \
- pos && ({ prefetch(pos->next); 1;}) && \
- ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
- pos = pos->next)
+#define hlist_for_each_entry(tpos, pos, head, member) \
+ for (pos = (head)->first; \
+ pos && ({ prefetch(pos->next); 1;}) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
/**
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point
- * @tpos: the type * to use as a loop cursor.
- * @pos: the &struct hlist_node to use as a loop cursor.
- * @member: the name of the hlist_node within the struct.
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @member: the name of the hlist_node within the struct.
*/
-#define hlist_for_each_entry_continue(tpos, pos, member) \
- for (pos = (pos)->next; \
- pos && ({ prefetch(pos->next); 1;}) && \
- ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
- pos = pos->next)
+#define hlist_for_each_entry_continue(tpos, pos, member) \
+ for (pos = (pos)->next; \
+ pos && ({ prefetch(pos->next); 1;}) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
/**
* hlist_for_each_entry_from - iterate over a hlist continuing from current point
- * @tpos: the type * to use as a loop cursor.
- * @pos: the &struct hlist_node to use as a loop cursor.
- * @member: the name of the hlist_node within the struct.
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @member: the name of the hlist_node within the struct.
*/
-#define hlist_for_each_entry_from(tpos, pos, member) \
- for (; pos && ({ prefetch(pos->next); 1;}) && \
- ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
- pos = pos->next)
+#define hlist_for_each_entry_from(tpos, pos, member) \
+ for (; pos && ({ prefetch(pos->next); 1;}) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
/**
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @tpos: the type * to use as a loop cursor.
- * @pos: the &struct hlist_node to use as a loop cursor.
- * @n: another &struct hlist_node to use as temporary storage
- * @head: the head for your list.
- * @member: the name of the hlist_node within the struct.
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @n: another &struct hlist_node to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
*/
-#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
- for (pos = (head)->first; \
- pos && ({ n = pos->next; 1; }) && \
- ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
- pos = n)
+#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
+ for (pos = (head)->first; \
+ pos && ({ n = pos->next; 1; }) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = n)
#endif
diff --git a/booster/list.h b/booster/list.h
new file mode 100644
index 0000000..2a333f4
--- /dev/null
+++ b/booster/list.h
@@ -0,0 +1,723 @@
+/*********************************************************************************
+ * Copyright: (C) 2020 LingYun IoT System Studio
+ * All rights reserved.
+ *
+ * Filename: list.h
+ * Description: This file is copied from Linux kernel, which provide link list API.
+ *
+ * Version: 1.0.0(08/09/2020)
+ * Author: Guo Wenxue <guowenxue@gmail.com>
+ * ChangeLog: 1, Release initial version on "08/09/2020 02:24:34 AM"
+ *
+ ********************************************************************************/
+
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+#include <linux/stddef.h>
+
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr: the pointer to the member.
+ * @type: the type of the container struct this is embedded in.
+ * @member: the name of the member within the struct.
+ *
+ */
+#undef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+
+/*
+ * Architectures might want to move the poison pointer offset
+ * into some well-recognized area such as 0xdead000000000000,
+ * that is also not mappable by user-space exploits:
+ */
+#ifdef CONFIG_ILLEGAL_POINTER_VALUE
+# define POISON_POINTER_DELTA _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL)
+#else
+# define POISON_POINTER_DELTA 0
+#endif
+
+/*
+ * These are non-NULL pointers that will result in page faults
+ * under normal circumstances, used to verify that nobody uses
+ * non-initialized list entries.
+ */
+#define LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA)
+#define LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA)
+
+#ifndef ARCH_HAS_PREFETCH
+#define ARCH_HAS_PREFETCH
+static inline void prefetch(const void *x) {;}
+#endif
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void INIT_LIST_HEAD(struct list_head *list)
+{
+ list->next = list;
+ list->prev = list;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head *prev, struct list_head *next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty() on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ entry->next = LIST_POISON1;
+ entry->prev = LIST_POISON2;
+}
+
+/**
+ * list_replace - replace old entry by new one
+ * @old : the element to be replaced
+ * @new : the new element to insert
+ *
+ * If @old was empty, it will be overwritten.
+ */
+static inline void list_replace(struct list_head *old,
+ struct list_head *new)
+{
+ new->next = old->next;
+ new->next->prev = new;
+ new->prev = old->prev;
+ new->prev->next = new;
+}
+
+static inline void list_replace_init(struct list_head *old,
+ struct list_head *new)
+{
+ list_replace(old, new);
+ INIT_LIST_HEAD(old);
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+ struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add_tail(list, head);
+}
+
+/**
+ * list_is_last - tests whether @list is the last entry in list @head
+ * @list: the entry to test
+ * @head: the head of the list
+ */
+static inline int list_is_last(const struct list_head *list,
+ const struct list_head *head)
+{
+ return list->next == head;
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+ return head->next == head;
+}
+
+/**
+ * list_empty_careful - tests whether a list is empty and not being modified
+ * @head: the list to test
+ *
+ * Description:
+ * tests whether a list is empty _and_ checks that no other CPU might be
+ * in the process of modifying either member (next or prev)
+ *
+ * NOTE: using list_empty_careful() without synchronization
+ * can only be safe if the only activity that can happen
+ * to the list entry is list_del_init(). Eg. it cannot be used
+ * if another CPU could re-list_add() it.
+ */
+static inline int list_empty_careful(const struct list_head *head)
+{
+ struct list_head *next = head->next;
+ return (next == head) && (next == head->prev);
+}
+
+/**
+ * list_is_singular - tests whether a list has just one entry.
+ * @head: the list to test.
+ */
+static inline int list_is_singular(const struct list_head *head)
+{
+ return !list_empty(head) && (head->next == head->prev);
+}
+
+static inline void __list_cut_position(struct list_head *list,
+ struct list_head *head, struct list_head *entry)
+{
+ struct list_head *new_first = entry->next;
+ list->next = head->next;
+ list->next->prev = list;
+ list->prev = entry;
+ entry->next = list;
+ head->next = new_first;
+ new_first->prev = head;
+}
+
+/**
+ * list_cut_position - cut a list into two
+ * @list: a new list to add all removed entries
+ * @head: a list with entries
+ * @entry: an entry within head, could be the head itself
+ * and if so we won't cut the list
+ *
+ * This helper moves the initial part of @head, up to and
+ * including @entry, from @head to @list. You should
+ * pass on @entry an element you know is on @head. @list
+ * should be an empty list or a list you do not care about
+ * losing its data.
+ *
+ */
+static inline void list_cut_position(struct list_head *list,
+ struct list_head *head, struct list_head *entry)
+{
+ if (list_empty(head))
+ return;
+ if (list_is_singular(head) &&
+ (head->next != entry && head != entry))
+ return;
+ if (entry == head)
+ INIT_LIST_HEAD(list);
+ else
+ __list_cut_position(list, head, entry);
+}
+
+static inline void __list_splice(const struct list_head *list,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+
+ first->prev = prev;
+ prev->next = first;
+
+ last->next = next;
+ next->prev = last;
+}
+
+/**
+ * list_splice - join two lists, this is designed for stacks
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(const struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list))
+ __list_splice(list, head, head->next);
+}
+
+/**
+ * list_splice_tail - join two lists, each list being a queue
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice_tail(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list))
+ __list_splice(list, head->prev, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head, head->next);
+ INIT_LIST_HEAD(list);
+ }
+}
+
+/**
+ * list_splice_tail_init - join two lists and reinitialise the emptied list
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * Each of the lists is a queue.
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_tail_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head->prev, head);
+ INIT_LIST_HEAD(list);
+ }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+/**
+ * list_first_entry - get the first element from a list
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_first_entry(ptr, type, member) \
+ list_entry((ptr)->next, type, member)
+
+/**
+ * list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ */
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; prefetch(pos->next), pos != (head); \
+ pos = pos->next)
+
+/**
+ * __list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ *
+ * This variant differs from list_for_each() in that it's the
+ * simplest possible list iteration code, no prefetching is done.
+ * Use this for code that knows the list to be very short (empty
+ * or 1 entry) most of the time.
+ */
+#define __list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_prev - iterate over a list backwards
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+ for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
+ pos = pos->prev)
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/**
+ * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_prev_safe(pos, n, head) \
+ for (pos = (head)->prev, n = pos->prev; \
+ prefetch(pos->prev), pos != (head); \
+ pos = n, n = pos->prev)
+
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member); \
+ prefetch(pos->member.next), &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_reverse - iterate backwards over list of given type.
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_reverse(pos, head, member) \
+ for (pos = list_entry((head)->prev, typeof(*pos), member); \
+ prefetch(pos->member.prev), &pos->member != (head); \
+ pos = list_entry(pos->member.prev, typeof(*pos), member))
+
+/**
+ * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
+ * @pos: the type * to use as a start point
+ * @head: the head of the list
+ * @member: the name of the list_struct within the struct.
+ *
+ * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
+ */
+#define list_prepare_entry(pos, head, member) \
+ ((pos) ? : list_entry(head, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue - continue iteration over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Continue to iterate over list of given type, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue(pos, head, member) \
+ for (pos = list_entry(pos->member.next, typeof(*pos), member); \
+ prefetch(pos->member.next), &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue_reverse - iterate backwards from the given point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Start to iterate over list of given type backwards, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue_reverse(pos, head, member) \
+ for (pos = list_entry(pos->member.prev, typeof(*pos), member); \
+ prefetch(pos->member.prev), &pos->member != (head); \
+ pos = list_entry(pos->member.prev, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_from - iterate over list of given type from the current point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type, continuing from current position.
+ */
+#define list_for_each_entry_from(pos, head, member) \
+ for (; prefetch(pos->member.next), &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_continue
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type, continuing after current point,
+ * safe against removal of list entry.
+ */
+#define list_for_each_entry_safe_continue(pos, n, head, member) \
+ for (pos = list_entry(pos->member.next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_from
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type from current point, safe against
+ * removal of list entry.
+ */
+#define list_for_each_entry_safe_from(pos, n, head, member) \
+ for (n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_reverse
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate backwards over list of given type, safe against removal
+ * of list entry.
+ */
+#define list_for_each_entry_safe_reverse(pos, n, head, member) \
+ for (pos = list_entry((head)->prev, typeof(*pos), member), \
+ n = list_entry(pos->member.prev, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.prev, typeof(*n), member))
+
+/*
+ * Double linked lists with a single pointer list head.
+ * Mostly useful for hash tables where the two pointer list head is
+ * too wasteful.
+ * You lose the ability to access the tail in O(1).
+ */
+
+struct hlist_head {
+ struct hlist_node *first;
+};
+
+struct hlist_node {
+ struct hlist_node *next, **pprev;
+};
+
+#define HLIST_HEAD_INIT { .first = NULL }
+#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
+#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
+static inline void INIT_HLIST_NODE(struct hlist_node *h)
+{
+ h->next = NULL;
+ h->pprev = NULL;
+}
+
+static inline int hlist_unhashed(const struct hlist_node *h)
+{
+ return !h->pprev;
+}
+
+static inline int hlist_empty(const struct hlist_head *h)
+{
+ return !h->first;
+}
+
+static inline void __hlist_del(struct hlist_node *n)
+{
+ struct hlist_node *next = n->next;
+ struct hlist_node **pprev = n->pprev;
+ *pprev = next;
+ if (next)
+ next->pprev = pprev;
+}
+
+static inline void hlist_del(struct hlist_node *n)
+{
+ __hlist_del(n);
+ n->next = LIST_POISON1;
+ n->pprev = LIST_POISON2;
+}
+
+static inline void hlist_del_init(struct hlist_node *n)
+{
+ if (!hlist_unhashed(n)) {
+ __hlist_del(n);
+ INIT_HLIST_NODE(n);
+ }
+}
+
+static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
+{
+ struct hlist_node *first = h->first;
+ n->next = first;
+ if (first)
+ first->pprev = &n->next;
+ h->first = n;
+ n->pprev = &h->first;
+}
+
+/* next must be != NULL */
+static inline void hlist_add_before(struct hlist_node *n,
+ struct hlist_node *next)
+{
+ n->pprev = next->pprev;
+ n->next = next;
+ next->pprev = &n->next;
+ *(n->pprev) = n;
+}
+
+static inline void hlist_add_after(struct hlist_node *n,
+ struct hlist_node *next)
+{
+ next->next = n->next;
+ n->next = next;
+ next->pprev = &n->next;
+
+ if(next->next)
+ next->next->pprev = &next->next;
+}
+
+#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
+
+#define hlist_for_each(pos, head) \
+ for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
+ pos = pos->next)
+
+#define hlist_for_each_safe(pos, n, head) \
+ for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
+ pos = n)
+
+/**
+ * hlist_for_each_entry - iterate over list of given type
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry(tpos, pos, head, member) \
+ for (pos = (head)->first; \
+ pos && ({ prefetch(pos->next); 1;}) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_continue(tpos, pos, member) \
+ for (pos = (pos)->next; \
+ pos && ({ prefetch(pos->next); 1;}) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_from - iterate over a hlist continuing from current point
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_from(tpos, pos, member) \
+ for (; pos && ({ prefetch(pos->next); 1;}) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @n: another &struct hlist_node to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
+ for (pos = (head)->first; \
+ pos && ({ n = pos->next; 1; }) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = n)
+
+
+#endif
+
+
diff --git a/booster/logger.c b/booster/logger.c
index a821e1e..364fa72 100644
--- a/booster/logger.c
+++ b/booster/logger.c
@@ -1,383 +1,250 @@
/*********************************************************************************
- * Copyright: (C) 2020 LingYun IoT System Studio
+ * Copyright: (C) 2023 LingYun IoT System Studio.
* All rights reserved.
*
* Filename: logger.c
- * Description: This file is the linux infrastructural logger system library
+ * Description: This file is common logger API functions
*
- * Version: 1.0.0(08/08/2020~)
+ * Version: 1.0.0(11/08/23)
* Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "08/08/2020 04:24:01 PM"
+ * ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
*
********************************************************************************/
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <pthread.h>
+
#include "logger.h"
-#define PRECISE_TIME_FACTOR 1000
+typedef void (*log_LockFn)(void *udata, int lock);
-static unsigned long log_rollback_size = LOG_ROLLBACK_NONE;
+static struct {
+ char file[32]; /* logger file name */
+ FILE *fp; /* logger file pointer */
+ long size; /* logger file max size */
+ int level; /* logger level */
+ log_LockFn lockfn; /* lock function */
+ void *udata; /* lock data */
+} L;
-/* This library is not thread safe */
-static logger_t *logger = NULL;
+static const char *level_names[] = {
+ "ERROR",
+ "WARN",
+ "INFO",
+ "DEBUG",
+ "TRACE"
+};
-char *log_str[LOG_LEVEL_MAX + 1] = { "", "E", "W", "N", "D", "I", "M" };
+static const char *level_colors[] = {
+ "\x1b[31m",
+ "\x1b[33m",
+ "\x1b[32m",
+ "\x1b[36m",
+ "\x1b[94m"
+};
-#define LOG_TIME_FMT "%Y-%m-%d %H:%M:%S"
-
-static void log_signal_handler(int sig)
+static inline void time_to_str(char *buf)
{
- if(!logger)
- return ;
+ struct timeval tv;
+ struct tm *tm;
+ int len;
- if (sig == SIGHUP)
+ gettimeofday(&tv, NULL);
+ tm = localtime(&tv.tv_sec);
+
+ len = sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d.%06d ",
+ tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec, (int)tv.tv_usec);
+
+ buf[len] = '\0';
+}
+
+static void mutex_lock(void *udata, int lock)
+{
+ int err;
+ pthread_mutex_t *l = (pthread_mutex_t *) udata;
+
+ if (lock)
{
- signal(SIGHUP, log_signal_handler);
- log_err("SIGHUP received - reopenning log file [%s]", logger->file);
- log_reopen();
+ if ( (err = pthread_mutex_lock(l)) != 0 )
+ log_error("Unable to lock log lock: %s", strerror(err));
+ }
+ else
+ {
+ if ( (err = pthread_mutex_unlock(l) != 0) )
+ log_error("Unable to unlock log lock: %s", strerror(err));
}
}
-static void logger_banner(char *prefix)
+int log_open(char *fname, int level, int size, int lock)
{
- if(!logger)
- return ;
+ FILE *fp;
- fprintf(logger->fp, "%s log \"%s\" on level [%s] size [%lu] KiB, log system version %s\n",
- prefix, logger->file, log_str[logger->level], log_rollback_size / 1024, LOG_VERSION_STR);
-#ifdef LOG_FILE_LINE
- fprintf(logger->fp, " [ Date ] [ Time ] [ Level ] [ File/Line ] [ Message ]\n");
-#else
- fprintf(logger->fp, " [ Date ] [ Time ] [ Level ] [ Message ]\n");
-#endif
- fprintf(logger->fp, "-------------------------------------------------------------\n");
-}
+ L.level = level;
+ L.size = size*1024;
-static void check_and_rollback(void)
-{
- if(!logger)
- return ;
-
- if (log_rollback_size != LOG_ROLLBACK_NONE)
+ if( !fname || !strcmp(fname, "console") || !strcmp(fname, "stderr") )
{
- long _curOffset = ftell(logger->fp);
-
- if ((_curOffset != -1) && (_curOffset >= log_rollback_size))
+ strcpy(L.file, "console");
+ L.fp = stderr;
+ L.size = 0; /* console don't need rollback */
+ }
+ else
+ {
+ if ( !(fp = fopen(fname, "a+")) )
{
- char cmd[512];
-
- snprintf(cmd, sizeof(cmd), "cp -f %s %s.roll", logger->file, logger->file);
- system(cmd);
-
- if (-1 == fseek(logger->fp, 0L, SEEK_SET))
- fprintf(logger->fp, "log rollback fseek failed \n");
-
- rewind(logger->fp);
-
- truncate(logger->file, 0);
- logger_banner("Already rollback");
+ fprintf(stderr, "%s() failed: %s\n", __func__, strerror(errno));
+ return -2;
}
+ L.fp = fp;
+ strncpy(L.file, fname, sizeof(L.file));
}
-}
-/* log_size unit is KB */
-int log_open(logger_t *log, char *log_file, int level, int log_size)
-{
- struct sigaction act;
- char *filemode;
-
- if(!log)
+ if( lock )
{
- printf("ERROR: Invalid input arguments\n");
- return -1;
+ static pthread_mutex_t log_lock;
+
+ pthread_mutex_init(&log_lock, NULL);
+ L.udata = (void *)&log_lock;
+ L.lockfn = mutex_lock;
}
- /* set static global $logger point to argument $log */
- logger = log;
+ fprintf(L.fp, "\n");
+ log_info("logger system(%s) start: file:\"%s\", level:%s, maxsize:%luKiB\n\n",
+ LOG_VERSION, L.file, level_names[level], size);
-
- /* use standard error as output */
- if( !log_file || log_file[0]=='\0' || !strcmp(log_file, LOG_STDERR))
- {
- strncpy(logger->file, LOG_STDERR, FILENAME_LEN);
- logger->flag |= FLAG_LOGGER_CONSOLE;
- logger->level = level;
- logger->fp = stderr;
-
- log_rollback_size = LOG_ROLLBACK_NONE;
- goto OUT;
- }
-
- strncpy(logger->file, log_file, FILENAME_LEN);
- logger->flag |= FLAG_LOGGER_FILE;
- logger->level = level;
- logger->size = log_size;
-
- log_rollback_size = log_size <= 0 ? LOG_ROLLBACK_NONE : log_size*1024; /* Unit KiB */
-
- filemode = (log_rollback_size==LOG_ROLLBACK_NONE) ? "a+" : "w+";
-
- logger->fp = fopen(logger->file, filemode);
- if ( !logger->fp )
- {
- fprintf(stderr, "Open log file \"%s\" in %s failure: %s\n", logger->file, filemode, strerror(errno));
- return -2;
- }
-
- act.sa_handler = log_signal_handler;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
- sigaction(SIGHUP, &act, NULL);
-
- OUT:
- logger_banner("Initialize");
return 0;
}
void log_close(void)
{
- if (!logger || !logger->fp )
- return;
+ if( L.fp && L.fp!=stderr )
+ fclose(L.fp);
- logger_banner("\nTerminate");
- logger_raw("\n\n\n\n");
+ if (L.udata )
+ pthread_mutex_destroy( L.udata);
+}
- fflush(logger->fp);
+static void log_rollback(void)
+{
+ char cmd[128]={0};
+ long fsize;
- fclose(logger->fp);
- logger->fp = NULL;
+ /* don't need rollback */
+ if(L.size <= 0 )
+ return ;
+
+ fsize = ftell(L.fp);
+ if( fsize < L.size )
+ return ;
+
+ /* backup current log file */
+ snprintf(cmd, sizeof(cmd), "cp %s %s.bak", L.file, L.file);
+ system(cmd);
+
+ /* rollback file */
+ fseek(L.fp, 0, SEEK_SET);
+ truncate(L.file, 0);
+
+ fprintf(L.fp, "\n");
+ log_info("logger system(%s) rollback: file:\"%s\", level:%s, maxsize:%luKiB\n\n",
+ LOG_VERSION, L.file, level_names[L.level], L.size/1024);
return ;
}
-int log_reopen(void)
+void _log_write(int level, const char *file, int line, const char *fmt, ...)
{
- int rc = 0;
- char *filemode;
+ va_list args;
+ char time_string[100];
- if( !logger )
- return -1;
-
- if (logger->flag & FLAG_LOGGER_CONSOLE )
- {
- fflush(logger->fp);
- logger->fp = stderr;
- return 0;
- }
-
- if (logger->fp)
- {
- log_close();
- filemode = log_rollback_size==LOG_ROLLBACK_NONE ? "a+" : "w+";
- logger->fp = fopen(logger->file, filemode);
-
- if (logger->fp == NULL)
- rc = -2;
- }
- else
- {
- rc = -3;
- }
-
- if (!rc)
- {
- logger_banner("\nReopen");
- }
- return rc;
-}
-
-
-void logger_raw(const char *fmt, ...)
-{
- va_list argp;
-
- if (!logger || !logger->fp)
+ if ( !L.fp || level>L.level )
return;
- check_and_rollback();
+ /* Acquire lock */
+ if ( L.lockfn )
+ L.lockfn(L.udata, 1);
- va_start(argp, fmt);
- vfprintf(logger->fp, fmt, argp);
- va_end(argp);
-}
+ log_rollback();
-static void cp_printout(char *level, char *fmt, va_list argp)
-{
- char buf[MAX_LOG_MESSAGE_LEN];
- struct tm *local;
- struct timeval now;
- char timestr[256];
+ /* check and rollback file */
+ time_to_str(time_string);
- if(!logger)
- return ;
-
- check_and_rollback();
-
- gettimeofday(&now, NULL);
- local = localtime(&now.tv_sec);
-
- strftime(timestr, 256, LOG_TIME_FMT, local);
- vsnprintf(buf, MAX_LOG_MESSAGE_LEN, fmt, argp);
-
-#ifdef DUMPLICATE_OUTPUT
- printf("%s.%03ld [%s] : %s",
- timestr, now.tv_usec / PRECISE_TIME_FACTOR, level, buf);
-#endif
-
- if (logger->fp)
- fprintf(logger->fp, "%s.%03ld [%s] : %s", timestr, now.tv_usec / PRECISE_TIME_FACTOR, level, buf);
-
- if (logger->fp)
- fflush(logger->fp);
-}
-
-static void cp_printout_line(char *level, char *fmt, char *file, int line, va_list argp)
-{
- char buf[MAX_LOG_MESSAGE_LEN];
- struct tm *local;
- struct timeval now;
- char timestr[256];
-
- if(!logger)
- return ;
-
- check_and_rollback();
-
- gettimeofday(&now, NULL);
- local = localtime(&now.tv_sec);
-
- strftime(timestr, 256, LOG_TIME_FMT, local);
- vsnprintf(buf, MAX_LOG_MESSAGE_LEN, fmt, argp);
-
-#ifdef DUMPLICATE_OUTPUT
- printf("[%s.%03ld] <%s> <%s:%04d> : %s",
- timestr, now.tv_usec / PRECISE_TIME_FACTOR, level, file, line, buf);
-#endif
-
- if (logger->fp)
+ /* Log to stderr */
+ if ( L.fp == stderr )
{
- fprintf(logger->fp, "[%s.%03ld] <%s> <%s:%04d> : %s",
- timestr, now.tv_usec / PRECISE_TIME_FACTOR, level, file, line, buf);
-
- fflush(logger->fp);
+ fprintf(L.fp, "%s %s %-5s\x1b[0m \x1b[90m%s:%03d:\x1b[0m ",
+ time_string, level_colors[level], level_names[level], file, line);
}
-}
-
-void logger_str(int level, const char *msg)
-{
- if (!logger || level>logger->level)
- return;
-
- check_and_rollback();
-
- if (logger->fp)
- fwrite(msg, 1, strlen(msg), logger->fp);
-
- if(logger->fp)
- fflush(logger->fp);
-}
-
-void logger_min(int level, char *fmt, ...)
-{
- va_list argp;
-
- if (!logger || level>logger->level)
- return;
-
- va_start(argp, fmt);
- cp_printout(log_str[level], fmt, argp);
- va_end(argp);
-}
-
-void logger_line(int level, char *file, int line, char *fmt, ...)
-{
- va_list argp;
-
- if (!logger || level>logger->level)
- return;
-
- va_start(argp, fmt);
- cp_printout_line(log_str[level], fmt, file, line, argp);
-
- va_end(argp);
-}
-
-#define LINELEN 81
-#define CHARS_PER_LINE 16
-static char *print_char =
- " "
- " "
- " !\"#$%&'()*+,-./"
- "0123456789:;<=>?"
- "@ABCDEFGHIJKLMNO"
- "PQRSTUVWXYZ[\\]^_"
- "`abcdefghijklmno"
- "pqrstuvwxyz{|}~ "
- " "
- " "
- " ???????????????"
- "????????????????"
- "????????????????"
- "????????????????"
- "????????????????"
- "????????????????";
-
-void logger_dump(int level, char *buf, int len)
-{
- int rc;
- int idx;
- char prn[LINELEN];
- char lit[CHARS_PER_LINE + 2];
- char hc[4];
- short line_done = 1;
-
- if (!logger || level>logger->level)
- return;
-
- rc = len;
- idx = 0;
- lit[CHARS_PER_LINE] = '\0';
-
- while (rc > 0)
+ else /* Log to file */
{
- if (line_done)
- snprintf(prn, LINELEN, "%08X: ", idx);
+ fprintf(L.fp, "%s %-5s %s:%03d: ", time_string, level_names[level], file, line);
+ }
- do
+ va_start(args, fmt);
+ vfprintf(L.fp, fmt, args);
+ va_end(args);
+
+ fflush(L.fp);
+
+ /* Release lock */
+ if ( L.lockfn )
+ L.lockfn(L.udata, 0);
+}
+
+
+void log_dump(int level, const char *prompt, char *buf, size_t len)
+{
+ int i, j, ofset;
+ char line[256];
+ unsigned char c;
+ unsigned char *buffer = (unsigned char *)buf;
+
+ if (!L.fp || level>L.level)
+ return;
+
+ if( prompt )
+ _log_write(level, __FILE__, __LINE__, "%s\r\n", prompt);
+
+ for(i=0; i<len; i+=16)
+ {
+ ofset = snprintf(line, sizeof(line), "%04x: ", i);
+
+ /* print hex representation, and print spaces if end of buffer */
+ for(j=0; j<16; j++)
{
- unsigned char c = buf[idx];
- snprintf(hc, 4, "%02X ", c);
- strncat(prn, hc, LINELEN);
-
- lit[idx % CHARS_PER_LINE] = print_char[c];
+ if(i+j < len)
+ ofset += snprintf(line+ofset, sizeof(line)-ofset, "%02x ", buffer[i+j]);
+ else
+ ofset += snprintf(line+ofset, sizeof(line)-ofset, " ");
}
- while (--rc > 0 && (++idx % CHARS_PER_LINE != 0));
+ ofset += snprintf(line+ofset, sizeof(line)-ofset, " ");
- line_done = (idx % CHARS_PER_LINE) == 0;
- if (line_done)
+ /* print ASCII representation */
+ for(j=0; j<16; j++)
{
-#ifdef DUMPLICATE_OUTPUT
- printf("%s %s\n", prn, lit);
-#endif
- if (logger->fp)
- fprintf(logger->fp, "%s %s\n", prn, lit);
+ if (i+j < len)
+ {
+ c = buffer[i+j];
+ ofset += snprintf(line+ofset, sizeof(line)-ofset, "%c", (c>=32 && c<=126) ? c : '.');
+ }
+ else
+ {
+ ofset += snprintf(line+ofset, sizeof(line)-ofset, " ");
+ }
}
- }
- if (!line_done)
- {
- int ldx = idx % CHARS_PER_LINE;
- lit[ldx++] = print_char[(int)buf[idx]];
- lit[ldx] = '\0';
-
- while ((++idx % CHARS_PER_LINE) != 0)
- strncat(prn, " ", sizeof(prn));
-
-#ifdef DUMPLICATE_OUTPUT
- printf("%s %s\n", prn, lit);
-#endif
- if (logger->fp)
- fprintf(logger->fp, "%s %s\n", prn, lit);
-
+ if (L.fp)
+ fprintf(L.fp, "%s\r\n", line);
}
}
+
diff --git a/booster/logger.h b/booster/logger.h
index 5505101..ef8569e 100644
--- a/booster/logger.h
+++ b/booster/logger.h
@@ -1,105 +1,68 @@
-/********************************************************************************
- * Copyright: (C) 2020 LingYun IoT System Studio
+/*********************************************************************************
+ * Copyright: (C) 2023 LingYun IoT System Studio.
* All rights reserved.
*
* Filename: logger.h
- * Description: This file is the linux infrastructural logger system library
+ * Description: This file is common logger API functions
*
- * Version: 1.0.0(08/08/2020~)
+ * Version: 1.0.0(11/08/23)
* Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "08/08/2020 05:16:56 PM"
+ * ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
*
********************************************************************************/
#ifndef _LOGGER_H_
#define _LOGGER_H_
-#include <stdarg.h>
#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <signal.h>
-#include <time.h>
-#include <errno.h>
+#include <stdarg.h>
-#include <sys/types.h>
-#include <sys/time.h>
+#define LOG_VERSION "v0.1"
-#define LOG_VERSION_STR "1.0.0"
-
-#ifndef FILENAME_LEN
-#define FILENAME_LEN 64
-#endif
-
-#define LOG_STDERR "stderr" /* Debug mode log file is console */
-
-#define LOG_ROLLBACK_SIZE 512 /* Default rollback log size */
-#define LOG_ROLLBACK_NONE 0 /* Set rollback size to 0 will not rollback */
-
-#define DEFAULT_TIME_FORMAT "%Y-%m-%d %H:%M:%S"
-#define MAX_LOG_MESSAGE_LEN 0x1000
-
-//#define DUMPLICATE_OUTPUT /* Log to file and printf on console */
-
-enum
-{
- LOG_LEVEL_DISB = 0, /* Disable "Debug" */
- LOG_LEVEL_ERROR, /* Debug Level "ERROR" */
- LOG_LEVEL_WARN, /* Debug Level "warnning" */
- LOG_LEVEL_NRML, /* Debug Level "Normal" */
- LOG_LEVEL_DEBUG, /* Debug Level "Debug" */
- LOG_LEVEL_INFO, /* Debug Level "Information" */
- LOG_LEVEL_MAX,
+/* log level */
+enum {
+ LOG_LEVEL_ERROR,
+ LOG_LEVEL_WARN,
+ LOG_LEVEL_INFO,
+ LOG_LEVEL_DEBUG,
+ LOG_LEVEL_TRACE,
+ LOG_LEVEL_MAX
};
+enum {
+ LOG_LOCK_DISABLE, /* disable lock */
+ LOG_LOCK_ENABLE, /* enable lock */
+};
+
+#define ROLLBACK_NONE 0
+
+/* description: Initial the logger system
+ * arguments :
+ * $fname: logger file name, NULL/"console"/"stderr" will log to console
+ * $level: logger level above;
+ * $size : logger file max size in KiB
+ * $lock : thread lock enable or not
+ * return : <0: Failed ==0: Sucessfully
+ */
+int log_open(char *fname, int level, int size, int lock);
-/* logger->flag definition */
-#define FLAG_LOGGER_LEVEL_OPT 1<<0 /* The log level is sepcified by the command option */
+/* description: Terminate the logger system */
+void log_close(void);
-#define FLAG_LOGGER_CONSOLE 1<<1
-#define FLAG_LOGGER_FILE 0<<1
-typedef struct logger_s
-{
- unsigned char flag;
- char file[FILENAME_LEN];
- int level;
- int size;
+/* description: log message into log file. Don't call this function directly. */
+void _log_write(int level, const char *file, int line, const char *fmt, ...);
- FILE *fp;
-} logger_t;
-extern char *log_str[];
+/* description: dump a buffer in hex to logger file */
+void log_dump(int level, const char *prompt, char *buf, size_t len);
-/* log_size unit is KB */
-extern int log_open(logger_t *logger, char *filename, int level, int log_size);
-extern int log_reopen(void);
-extern void log_close(void);
+/* function: log message into logger file with different log level */
+#define log_trace(...) _log_write(LOG_LEVEL_TRACE, __FILE__, __LINE__, __VA_ARGS__)
+#define log_debug(...) _log_write(LOG_LEVEL_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
+#define log_info(...) _log_write(LOG_LEVEL_INFO, __FILE__, __LINE__, __VA_ARGS__)
+#define log_warn(...) _log_write(LOG_LEVEL_WARN, __FILE__, __LINE__, __VA_ARGS__)
+#define log_error(...) _log_write(LOG_LEVEL_ERROR, __FILE__, __LINE__, __VA_ARGS__)
-/* lowlvel API */
-extern void logger_raw(const char *fmt, ...);
-extern void logger_min(int level, char *fmt, ...);
-extern void logger_line(int level, char *file, int line, char *fmt, ...);
-extern void logger_str(int level, const char *msg);
-extern void logger_dump(int level, char *buf, int len);
-
-#define LOG_FILE_LINE /* Log the file and line */
-
-#ifdef LOG_FILE_LINE
-#define log_info(fmt, ...) logger_line(LOG_LEVEL_INFO, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
-#define log_dbg(fmt, ...) logger_line(LOG_LEVEL_DEBUG, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
-#define log_nrml(fmt, ...) logger_line(LOG_LEVEL_NRML, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
-#define log_warn(fmt, ...) logger_line(LOG_LEVEL_WARN, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
-#define log_err(fmt, ...) logger_line(LOG_LEVEL_ERROR, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
-#else
-#define log_info(fmt, ...) logger_min(LOG_LEVEL_INFO, fmt, ##__VA_ARGS__)
-#define log_dbg(fmt, ...) logger_min(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__)
-#define log_nrml(fmt, ...) logger_min(LOG_LEVEL_NRML, fmt, ##__VA_ARGS__)
-#define log_warn(fmt, ...) logger_min(LOG_LEVEL_WARN, fmt, ##__VA_ARGS__)
-#define log_err(fmt, ...) logger_min(LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__)
#endif
-
-#endif /* ----- #ifndef _LOGGER_H_ ----- */
-
diff --git a/booster/makefile b/booster/makefile
index 745ae81..0fd869e 100644
--- a/booster/makefile
+++ b/booster/makefile
@@ -1,13 +1,33 @@
+#********************************************************************************
+# Copyright: (C) 2023 LingYun IoT System Studio
+# All rights reserved.
+#
+# Filename: Makefile
+# Description: This file used compile all the source code to static library
+#
+# Version: 1.0.0(11/08/23)
+# Author: Guo Wenxue <guowenxue@gmail.com>
+# ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
+#
+#*******************************************************************************
PWD=$(shell pwd )
+BUILD_ARCH=$(shell uname -m)
+ifneq ($(findstring $(BUILD_ARCH), "x86_64" "i386"),)
+ CROSS_COMPILE?=arm-linux-gnueabihf-
+endif
+
+#CROSS_COMPILE=
+
LIBNAME=$(shell basename ${PWD} )
TOPDIR=$(shell dirname ${PWD} )
+CFLAGS+=-D_GNU_SOURCE
all: clean
@rm -f *.o
- @${CROSSTOOL}gcc ${CFLAGS} -I${TOPDIR} -c *.c
- ${CROSSTOOL}ar -rcs lib${LIBNAME}.a *.o
+ @${CROSS_COMPILE}gcc ${CFLAGS} -I${TOPDIR} -c *.c
+ ${CROSS_COMPILE}ar -rcs lib${LIBNAME}.a *.o
clean:
@rm -f *.o
@@ -15,4 +35,3 @@
distclean:
@make clean
- @rm -f cscope.* tags
diff --git a/booster/ringbuf.c b/booster/ringbuf.c
index f79d496..8902a4d 100644
--- a/booster/ringbuf.c
+++ b/booster/ringbuf.c
@@ -1,15 +1,16 @@
-/********************************************************************************
- * Copyright: (C) 2021 LingYun IoT System Studio
+/*********************************************************************************
+ * Copyright: (C) 2023 LingYun IoT System Studio.
* All rights reserved.
*
- * Filename: ringbuf.h
- * Description: This head file
+ * Filename: ringbuf.c
+ * Description: This file is common ring buffer API functions
*
- * Version: 1.0.0(2021年04月29日)
+ * Version: 1.0.0(11/08/23)
* Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "2021年04月29日 12时18分32秒"
+ * ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
*
********************************************************************************/
+
#include <string.h>
#include <assert.h>
#include "ringbuf.h"
@@ -100,7 +101,7 @@
unsigned char rb_peek(struct ring_buffer* rb, int index)
{
- assert(index < rb_data_size(rb));
+ assert(index < rb_data_size(rb));
- return rb->buffer[((rb->rd_pointer + index) % rb->size)];
+ return rb->buffer[((rb->rd_pointer + index) % rb->size)];
}
diff --git a/booster/ringbuf.h b/booster/ringbuf.h
index 23553cc..26153eb 100644
--- a/booster/ringbuf.h
+++ b/booster/ringbuf.h
@@ -1,13 +1,13 @@
-/********************************************************************************
- * Copyright: (C) 2021 LingYun IoT System Studio
+/*********************************************************************************
+ * Copyright: (C) 2023 LingYun IoT System Studio.
* All rights reserved.
*
* Filename: ringbuf.h
- * Description: This head file
+ * Description: This file is common ring buffer API functions
*
- * Version: 1.0.0(2021年04月29日)
+ * Version: 1.0.0(11/08/23)
* Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "2021年04月29日 12时18分32秒"
+ * ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
*
********************************************************************************/
@@ -16,7 +16,7 @@
struct ring_buffer
{
- unsigned char *buffer;
+ unsigned char *buffer;
int wr_pointer;
int rd_pointer;
int size;
diff --git a/booster/test/gpio-scripts/pinctrl-rzboard b/booster/test/gpio-scripts/pinctrl-rzboard
deleted file mode 100755
index facd6cf..0000000
--- a/booster/test/gpio-scripts/pinctrl-rzboard
+++ /dev/null
@@ -1,144 +0,0 @@
-#!/bin/bash
-# This shell script used to control GPIO port on RzBoard
-
-direction=out
-sysdir=/sys/class/gpio/
-pinbase=120
-groupin=8
-
-pinnum=
-pindir=
-action=
-
-set -u
-set -e
-
-# RedLed: P8_1 GreenLed: P17_2 BlueLed: P19_1
-# UserKey: P39_0
-function usage()
-{
- echo "Show pinmap Usage: $0 [-v]"
- echo "Output set Usage: $0 P9_1 [1/0]"
- echo "Input read Usage: $0 [-i] P9_1"
- echo "Unexport Usage: $0 [-u] P9_1"
- exit;
-}
-
-function show_pinmap()
-{
- echo "
- +--------------------+--RzBoard--+--------------------+
- | Name/GPIO | Physical | Name/GPIO |
- +--------------------+-----++----+--------------------+
- | 3.3v | 1 || 2 | 5v |
- | SDA2(P3_0) | 3 || 4 | 5v |
- | SCL2(P3_1) | 5 || 6 | GND |
- | GPIO(P12_0) | 7 || 8 | TXD2(P48_0) |
- | GND | 9 || 10 | RXD2(P48_1) |
- | SCL3(P48_3) | 11 || 12 | GPIO(P17_1) |
- | SDA3(P48_2) | 13 || 14 | GND |
- | GPIO(P17_0) | 15 || 16 | GPIO(P13_2) |
- | 3.3v | 17 || 18 | GPIO(P14_0) |
- | SPI1_MOSI(P44_1) | 19 || 20 | GND |
- | SPI1_MISO(P44_2) | 21 || 22 | GPIO(P39_1) |
- | SPI1_CLK(P44_0) | 23 || 24 | SPI1_SS(P44_3) |
- | GND | 25 || 26 | GPIO(P0_1) |
- | GPIO(P14_1) | 27 || 28 | GPIO(P46_3) |
- | GPIO(P42_3) | 29 || 30 | GND |
- | GPIO(P42_4) | 31 || 32 | GPIO(P15_1) |
- | GPIO(P10_0) | 33 || 34 | GND |
- | GPIO(P9_1) | 35 || 36 | RTS2(P48_4) |
- | GPIO(P13_1) | 37 || 38 | CAN0_RX(P11_0) |
- | GND | 39 || 40 | CAN0_TX(P10_1) |
- +--------------------+-----++----+--------------------+
- | Name/GPIO | Physical | Name/GPIO |
- +--------------------+--RzBoard--+--------------------+
- "
- exit 0;
-}
-
-function calc_pinum()
-{
- pinstr=$1
-
- group=`echo $pinstr | cut -d_ -f1 | tr -cd "[0-9]"`
- pin=`echo $pinstr | cut -d_ -f2 | tr -cd "[0-9]"`
-
- pinum=`expr $group \* $groupin + $pin + $pinbase`
- pindir=$sysdir/gpio$pinum
-
- #echo "INFO: GPIO $pinstr map to pinum[$pinum]"
-}
-
-function export_gpio()
-{
- if [ -e $pindir ] ; then
- return ;
- fi
-
- echo $pinum > $sysdir/export
-}
-
-function unexport_gpio()
-{
- if [ ! -e $pindir ] ; then
- return ;
- fi
-
- echo $pinum > $sysdir/unexport
-}
-
-function set_gpio()
-{
- echo out > $pindir/direction
- echo $1 > $pindir/value
-}
-
-function read_gpio()
-{
- echo in > $pindir/direction
- cat $pindir/value
-}
-
-if [ $# -lt 1 ] ; then
- usage;
-fi
-
-while getopts "iuvh" OPTNAME
-do
- case "${OPTNAME}" in
- "i")
- direction=in
- shift
- ;;
-
- "u")
- action=unexport;
- shift
- ;;
-
- "v")
- show_pinmap;
- shift
- ;;
-
- "h")
- usage;
- ;;
- esac
-done
-
-calc_pinum $1
-
-if [[ $action == unexport ]] ; then
- unexport_gpio
- exit;
-fi
-
-export_gpio
-
-if [ $direction == in ] ; then
- read_gpio
-else
- set_gpio $2
-fi
diff --git a/booster/test/logger.c b/booster/test/logger.c
deleted file mode 100644
index 851ba9a..0000000
--- a/booster/test/logger.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*********************************************************************************
- * Copyright: (C) 2021 LingYun IoT System Studio
- * All rights reserved.
- *
- * Filename: logger.c
- * Description: This file is logger system sample code.
- *
- * Version: 1.0.0(17/07/21)
- * Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "17/07/21 15:51:04"
- *
- ********************************************************************************/
-#include "logger.h"
-
-#define LOG_FILE "test.log"
-
-int main (int argc, char **argv)
-{
- int rv;
- logger_t log;
-
-#ifdef LOG_FILE
- if( log_open(&log, "test.log", LOG_LEVEL_NRML, 512) < 0 )
-#else
- if( log_open(&log, LOG_STDERR, LOG_LEVEL_DEBUG, LOG_ROLLBACK_NONE) < 0 )
-#endif
- {
- fprintf(stderr, "initialise logger system failure, rv=%d\n", rv);
- return -1;
- }
-
- log_info("logger level [information] message\n");
- log_dbg ("logger level [ debug ] message\n");
- log_nrml("logger level [ normal ] message\n");
- log_warn("logger level [ warnning ] message\n");
- log_err ("logger level [ error ] message\n");
-
- log_close();
-
- return 0;
-}
-
diff --git a/booster/test/makefile b/booster/test/makefile
index 43a40ee..27eda01 100644
--- a/booster/test/makefile
+++ b/booster/test/makefile
@@ -1,37 +1,64 @@
+#*********************************************************************************
+# Copyright: (C) 2022 Guo Wenxue
+# All rights reserved.
+#
+# Filename: Makefile
+# Description: This Makefile used to compile all the C source code file in current
+# folder to respective excutable binary files.
+#
+# Version: 1.0.0(03/15/2022~)
+# Author: Guo Wenxue <guowenxue@gmail.com>
+# ChangeLog: 1, Release initial version on "03/15/2022 01:29:33 PM"
+#
+#********************************************************************************/
PWD=$(shell pwd)
+LIB_PATH=$(shell dirname ${PWD})
+LIB_NAME=$(shell basename ${LIB_PATH})
+INSTPATH=/tftp
-INST_PATH=/tftp
+#ARCH ?= i386
+#ARCH?=arm926t
+ARCH?=arm920t
-LIB_PATH=$(shell dirname ${PWD} )
-LIB_NAME=$(shell basename ${LIB_PATH} )
+#LINK_MODE=STATIC
+MODE=PRODUCTION
+DEBUG=1
-CFLAGS+=-I${LIB_PATH}
-LDFLAGS+=-L${LIB_PATH} -l${LIB_NAME} -lpthread
+INSTPATH=/tftp
+
+CROSS_COMPILE?=arm-linux-gnueabihf-
+
+export CC=${CROSS_COMPILE}gcc
+export CXX=${CROSS_COMPILE}g++
+export AR=${CROSS_COMPILE}ar
+export AS=${CROSS_COMPILE}as
+export RANLIB=${CROSS_COMPILE}ranlib
+export STRIP=${CROSS_COMPILE}strip
+
+SRCS = $(wildcard ${VPATH}/*.c)
+OBJS = $(patsubst %.c,%.o,$(SRCS))
SRCFILES = $(wildcard *.c)
BINARIES=$(SRCFILES:%.c=%)
-all: libs binaries
- @make install
+CFLAGS+=-I${LIB_PATH}
+LDFLAGS+=-L${LIB_PATH} -l${LIB_NAME}
-libs:
- make -C ${LIB_PATH}
+all: binaries install
binaries: ${BINARIES}
- @echo " Compile over"
%: %.c
- ${CROSSTOOL}gcc $(CFLAGS) -o $@ $< $(LDFLAGS)
+ $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
install:
- cp ${BINARIES} ${INST_PATH}
+ cp $(BINARIES) ${INSTPATH}
clean:
- @rm -f ${BINARIES}
- @rm -f *.log
+ @rm -f *.o *.log $(BINARIES)
-distclean:
- @make clean
- @make clean -C ${LIB_PATH}
- @rm -f cscope.* tags
+distclean: clean
+ @rm -f tags cscope*
+
+.PHONY: clean entry
diff --git a/booster/test/test_logger.c b/booster/test/test_logger.c
new file mode 100644
index 0000000..e6ee293
--- /dev/null
+++ b/booster/test/test_logger.c
@@ -0,0 +1,45 @@
+/*********************************************************************************
+ * Copyright: (C) 2012 Guo Wenxue <guowenxue@gmail.com>
+ * All rights reserved.
+ *
+ * Filename: test_logger.c
+ * Description: This is the linux logger system test code.
+ *
+ * Version: 1.0.0(08/08/2012~)
+ * Author: Guo Wenxue <guowenxue@gmail.com>
+ * ChangeLog: 1, Release initial version on "08/08/2012 06:51:40 PM"
+ *
+ ********************************************************************************/
+
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <libgen.h>
+#include "logger.h"
+
+int main (int argc, char **argv)
+{
+ char buf[256];
+ int i;
+
+ for(i=0; i<sizeof(buf); i++)
+ buf[i] = i;
+
+#if 1
+ log_open("console", LOG_LEVEL_DEBUG, 0, LOG_LOCK_DISABLE);
+#else
+ log_open("test.log", LOG_LEVEL_DEBUG, 10, LOG_LOCK_DISABLE);
+#endif
+
+ log_error("This is a errorr message\n");
+ log_warn("This is a warnning message\n");
+ log_info("This is a informat message\n");
+ log_debug("This is a debug message\n");
+ log_trace("This is a trace message\n");
+
+ log_dump(LOG_LEVEL_DEBUG, "Hex dump buffer content:", buf, sizeof(buf));
+
+ log_close();
+ return 0;
+}
+
diff --git a/booster/util_proc.c b/booster/util_proc.c
index a17ea29..dfdabae 100644
--- a/booster/util_proc.c
+++ b/booster/util_proc.c
@@ -13,12 +13,14 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
-#include <libgen.h>
+#include <errno.h>
#include <fcntl.h>
+#include <libgen.h>
+#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <pthread.h>
#include "util_proc.h"
#include "logger.h"
@@ -64,7 +66,7 @@
{
struct sigaction sigact, sigign;
- log_nrml("Install default signal handler.\n");
+ log_info("Install default signal handler.\n");
/* Initialize the catch signal structure. */
sigemptyset(&sigact.sa_mask);
@@ -159,7 +161,7 @@
if( check_daemon_running(pidfile) )
{
- log_err("Program already running, process exit now");
+ log_error("Program already running, process exit now");
return -1;
}
@@ -167,7 +169,7 @@
{
if( set_daemon_running(pidfile) < 0 )
{
- log_err("set program running as daemon failure\n");
+ log_error("set program running as daemon failure\n");
return -2;
}
}
@@ -175,7 +177,7 @@
{
if( record_daemon_pid(pidfile) < 0 )
{
- log_err("record program running PID failure\n");
+ log_error("record program running PID failure\n");
return -3;
}
}
@@ -209,7 +211,7 @@
{
if (mkdir(ipc_dir, mode) < 0)
{
- log_err("cannot create %s: %s\n", ipc_dir, strerror(errno));
+ log_error("cannot create %s: %s\n", ipc_dir, strerror(errno));
return -1;
}
@@ -225,11 +227,11 @@
write(fd, pid, strlen(pid));
close(fd);
- log_dbg("Record PID<%u> to file %s.\n", getpid(), pid_file);
+ log_debug("Record PID<%u> to file %s.\n", getpid(), pid_file);
}
else
{
- log_err("cannot create %s: %s\n", pid_file, strerror(errno));
+ log_error("cannot create %s: %s\n", pid_file, strerror(errno));
return -1;
}
@@ -257,7 +259,7 @@
}
else
{
- log_err("Can't open PID record file %s: %s\n", pid_file, strerror(errno));
+ log_error("Can't open PID record file %s: %s\n", pid_file, strerror(errno));
return -1;
}
return pid;
@@ -356,11 +358,11 @@
int set_daemon_running(const char *pid_file)
{
daemonize(0, 1);
- log_nrml("Program running as daemon [PID:%d].\n", getpid());
+ log_info("Program running as daemon [PID:%d].\n", getpid());
if (record_daemon_pid(pid_file) < 0)
{
- log_err("Record PID to file \"%s\" failure.\n", pid_file);
+ log_error("Record PID to file \"%s\" failure.\n", pid_file);
return -2;
}
diff --git a/booster/util_proc.h b/booster/util_proc.h
index 4af3cf2..89856c6 100644
--- a/booster/util_proc.h
+++ b/booster/util_proc.h
@@ -15,6 +15,7 @@
#define __UTIL_PROC_H_
#include <signal.h>
+#include <time.h>
#define PID_ASCII_SIZE 11
@@ -59,9 +60,30 @@
* | Low level API |
* +---------------------+*/
-
-
/* get daemon process ID from $pid_file */
extern pid_t get_daemon_pid(const char *pid_file);
+/* +------------------------+
+ * | inline functions API |
+ * +------------------------+*/
+static inline void msleep(unsigned long ms)
+{
+ struct timespec cSleep;
+ unsigned long ulTmp;
+
+ cSleep.tv_sec = ms / 1000;
+ if (cSleep.tv_sec == 0)
+ {
+ ulTmp = ms * 10000;
+ cSleep.tv_nsec = ulTmp * 100;
+ }
+ else
+ {
+ cSleep.tv_nsec = 0;
+ }
+
+ nanosleep(&cSleep, 0);
+ return ;
+}
+
#endif
--
Gitblit v1.9.1