diff --git a/.gitignore b/.gitignore index 93d2a28d..a872aadf 100644 --- a/.gitignore +++ b/.gitignore @@ -16,12 +16,14 @@ *.sct *.MajerleT *.tjuln +*.tilen *.dbgconf *.uvguix *.uvoptx *.__i *.i *.txt +!docs/*.txt RTE/ # IAR Settings @@ -73,6 +75,7 @@ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ +_build/ # Visual Studio 2015/2017 cache/options directory .vs/ @@ -377,7 +380,6 @@ log_file.txt .metadata/ .mxproject .settings/ -template/ project.ioc mx.scratch *.tilen majerle diff --git a/.gitmodules b/.gitmodules index 23b80ae4..cab36ce5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "third_party/Embedded_Libs"] - path = third_party/Embedded_Libs - url = https://github.com/MaJerle/Embedded_Libs +[submodule "third_party/embedded-libs"] + path = third_party/embedded-libs + url = https://github.com/MaJerle/embedded-libs diff --git a/LICENSE b/LICENSE index 68bd738f..aa603174 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018 Tilen Majerle +Copyright (c) 2020 Tilen MAJERLE Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index ef7f23f8..4892610a 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,36 @@ -# GSM AT commands parser for RTOS systems +# Lightweight GSM-AT parser -GSM-AT Library commands parser is a generic, platform independent, library for communicating with SIMCOM based modules SIM800/SIM900 or SIM70xx. Module is written in C99 and is independent from used platform. Its main targets are embedded system devices like ARM Cortex-M, AVR, PIC and others, but can easily work under `Windows`, `Linux` or `MAC` environments. +LwGSM is lightweight, platform independent, AT commands parser, targeting for communicion with SIMCOM based modules SIM800/SIM900 or SIM70xx. Module is written in C99 and is independent from used platform. Its main targets are embedded system devices like ARM Cortex-M, AVR, PIC and others, but can easily work under `Windows`, `Linux` or `MAC` environments. -## Features - -- Supports `SIM800/SIM900 (2G)` and `SIM7000/SIM7020 (NB-Iot LTE)` modules - -## Documentation +

Read first: Documentation

-Full API documentation with description and examples is available and is regulary updated with the source changes - -http://majerle.eu/documentation/gsm_at/html/index.html - -## Contribution +## Features -I invite you to give feature request or report a bug. Please use issues tracker. +* Supports ``SIM800/SIM900 (2G)`` and ``SIM7000/SIM7020 (NB-Iot LTE)`` modules +* Platform independent and very easy to port + * Development of library under Win32 platform + * Provided examples for ARM Cortex-M or Win32 platforms +* Written in C language (C99) +* Allows different configurations to optimize user requirements +* Supports implementation with operating systems with advanced inter-thread communications + * Currently only OS mode is supported + * 2 different threads handling user data and received data + * First (producer) thread (collects user commands from user threads and starts the command processing) + * Second (process) thread reads the data from GSM device and does the job accordingly +* Allows sequential API for connections in client and server mode +* Includes several applications built on top of library: + * MQTT client for MQTT connection +* User friendly MIT license + +## Contribute + +Fresh contributions are always welcome. Simple instructions to proceed:: + +1. Fork Github repository +2. Respect [C style & coding rules](https://github.com/MaJerle/c-code-style) used by the library +3. Create a pull request to develop branch with new features or bug fixes + +Alternatively you may: + +1. Report a bug +2. Ask for a feature request \ No newline at end of file diff --git a/dev/VisualStudio/gsm_config.h b/dev/VisualStudio/gsm_config.h deleted file mode 100644 index 6102100e..00000000 --- a/dev/VisualStudio/gsm_config.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - * \file gsm_config.h - * \brief Configuration for GSM - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_CONFIG_H -#define GSM_HDR_CONFIG_H - -/** - * User specific config which overwrites setup from gsm_config_default.h file - */ - -#if !__DOXYGEN__ -#define GSM_CFG_DBG GSM_DBG_ON -#define GSM_CFG_DBG_TYPES_ON GSM_DBG_TYPE_TRACE | GSM_DBG_TYPE_STATE -#define GSM_CFG_DBG_MQTT GSM_DBG_OFF - -#define GSM_CFG_IPD_MAX_BUFF_SIZE 1460 -#define GSM_CFG_INPUT_USE_PROCESS 1 -#define GSM_CFG_AT_ECHO 0 - -#define GSM_CFG_NETWORK 1 - -#define GSM_CFG_CONN 1 -#define GSM_CFG_SMS 1 -#define GSM_CFG_CALL 1 -#define GSM_CFG_PHONEBOOK 1 -#define GSM_CFG_USSD 1 - -#define GSM_CFG_USE_API_FUNC_EVT 1 - -#define GSM_CFG_NETCONN 1 - -#define GSM_CFG_MEM_CUSTOM 1 - -#if defined(WIN32) -#define GSM_CFG_SYS_PORT GSM_SYS_PORT_WIN32 -#endif - -#endif /* !__DOXYGEN__ */ - -/* Include default configuration setup */ -#include "gsm/gsm_config_default.h" - -/** - * \} - */ - -#endif /* GSM_HDR_CONFIG_H */ diff --git a/dev/VisualStudio/gsm_at_lib_dev.sln b/dev/VisualStudio/lwgsm_dev.sln similarity index 88% rename from dev/VisualStudio/gsm_at_lib_dev.sln rename to dev/VisualStudio/lwgsm_dev.sln index 1dbe6fed..0c851a0f 100644 --- a/dev/VisualStudio/gsm_at_lib_dev.sln +++ b/dev/VisualStudio/lwgsm_dev.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.28803.452 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gsm_at_lib_dev", "gsm_at_lib_dev.vcxproj", "{87E5EEE1-1C99-458B-A893-DDDB00775631}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lwgsm_dev", "lwgsm_dev.vcxproj", "{87E5EEE1-1C99-458B-A893-DDDB00775631}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -13,8 +13,8 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {87E5EEE1-1C99-458B-A893-DDDB00775631}.Debug|x64.ActiveCfg = Debug|Win32 - {87E5EEE1-1C99-458B-A893-DDDB00775631}.Debug|x64.Build.0 = Debug|Win32 + {87E5EEE1-1C99-458B-A893-DDDB00775631}.Debug|x64.ActiveCfg = Debug|x64 + {87E5EEE1-1C99-458B-A893-DDDB00775631}.Debug|x64.Build.0 = Debug|x64 {87E5EEE1-1C99-458B-A893-DDDB00775631}.Debug|x86.ActiveCfg = Debug|Win32 {87E5EEE1-1C99-458B-A893-DDDB00775631}.Debug|x86.Build.0 = Debug|Win32 {87E5EEE1-1C99-458B-A893-DDDB00775631}.Release|x64.ActiveCfg = Release|x64 diff --git a/dev/VisualStudio/gsm_at_lib_dev.vcxproj b/dev/VisualStudio/lwgsm_dev.vcxproj similarity index 71% rename from dev/VisualStudio/gsm_at_lib_dev.vcxproj rename to dev/VisualStudio/lwgsm_dev.vcxproj index 0cf840ad..75d614b4 100644 --- a/dev/VisualStudio/gsm_at_lib_dev.vcxproj +++ b/dev/VisualStudio/lwgsm_dev.vcxproj @@ -22,7 +22,7 @@ 15.0 {87E5EEE1-1C99-458B-A893-DDDB00775631} Win32Proj - gsm_dev_os + lwgsm_dev_os 10.0 @@ -72,17 +72,19 @@ true - .;..\..\snippets\include;..\..\GSM_AT_Lib\src\include;..\..\..\lwmem\lwmem\src\include;$(IncludePath) + .;..\..\lwgsm\src\include;..\..\lwgsm\src\include\system\port\win32;..\..\snippets\include;..\..\..\lwmem\lwmem\src\include;$(IncludePath) true - .;..\..\snippets\include;..\..\GSM_AT_Lib\src\include;$(IncludePath) + .;..\..\lwgsm\src\include;..\..\lwgsm\src\include\system\port\win32;..\..\snippets\include;$(IncludePath) false + .;..\..\lwgsm\src\include;..\..\lwgsm\src\include\system\port\win32;..\..\snippets\include;$(IncludePath) false + .;..\..\lwgsm\src\include;..\..\lwgsm\src\include\system\port\win32;..\..\snippets\include;$(IncludePath) @@ -142,42 +144,47 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/VisualStudio/gsm_at_lib_dev.vcxproj.filters b/dev/VisualStudio/lwgsm_dev.vcxproj.filters similarity index 60% rename from dev/VisualStudio/gsm_at_lib_dev.vcxproj.filters rename to dev/VisualStudio/lwgsm_dev.vcxproj.filters index cd91658e..1c6956f0 100644 --- a/dev/VisualStudio/gsm_at_lib_dev.vcxproj.filters +++ b/dev/VisualStudio/lwgsm_dev.vcxproj.filters @@ -28,119 +28,134 @@ Source Files - - Source Files\GSM CORE + + Source Files\GSM SNIPPETS - - Source Files\GSM CORE + + Source Files\GSM SNIPPETS - - Source Files\GSM CORE + + Source Files\GSM SNIPPETS - - Source Files\GSM CORE + + Source Files\GSM SNIPPETS - - Source Files\GSM CORE + + Source Files\GSM SNIPPETS - - Source Files\GSM CORE + + Source Files\LWMEM - - Source Files\GSM CORE + + Source Files\LWMEM - - Source Files\GSM CORE + + Source Files\GSM SNIPPETS - - Source Files\GSM CORE + + Source Files\GSM SNIPPETS - - Source Files\GSM CORE + + Source Files\GSM SNIPPETS - - Source Files\GSM CORE + + Source Files\GSM SNIPPETS - - Source Files\GSM LL + + Source Files\GSM SNIPPETS - - Source Files\GSM LL + + Source Files\GSM CORE - + Source Files\GSM CORE - + Source Files\GSM CORE - + Source Files\GSM CORE - + Source Files\GSM CORE - + Source Files\GSM CORE - + Source Files\GSM CORE - + Source Files\GSM CORE - + Source Files\GSM CORE - + Source Files\GSM CORE - - Source Files\GSM API + + Source Files\GSM LL + + + Source Files\LWMEM + + + Source Files\GSM CORE - + Source Files\GSM APP MQTT - + Source Files\GSM APP MQTT - + Source Files\GSM APP MQTT - - Source Files\GSM SNIPPETS + + Source Files\GSM API - - Source Files\GSM SNIPPETS + + Source Files\GSM CORE - - Source Files\GSM SNIPPETS + + Source Files\GSM CORE - - Source Files\GSM SNIPPETS + + Source Files\GSM CORE - + Source Files\GSM CORE - + Source Files\GSM CORE - + + Source Files\GSM CORE + + + Source Files\GSM CORE + + + Source Files\GSM CORE + + Source Files\GSM LL - - Source Files\GSM SNIPPETS + + Source Files\GSM CORE - - Source Files\GSM API + + Source Files\GSM CORE - + Source Files\GSM CORE - - Source Files\LWMEM + + Source Files\GSM CORE - - Source Files\LWMEM + + Source Files\GSM CORE \ No newline at end of file diff --git a/dev/VisualStudio/lwgsm_opts.h b/dev/VisualStudio/lwgsm_opts.h new file mode 100644 index 00000000..686224fe --- /dev/null +++ b/dev/VisualStudio/lwgsm_opts.h @@ -0,0 +1,72 @@ +/** + * \file lwgsm_opts.h + * \brief GSM application options + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_OPTS_H +#define LWGSM_HDR_OPTS_H + +/* Rename this file to "lwgsm_opts.h" for your application */ + +/* + * Open "include/lwgsm/lwgsm_opt.h" and + * copy & replace here settings you want to change values + */ +#if !__DOXYGEN__ +#define LWGSM_CFG_DBG LWGSM_DBG_ON +#define LWGSM_CFG_DBG_TYPES_ON LWGSM_DBG_TYPE_TRACE | LWGSM_DBG_TYPE_STATE +#define LWGSM_CFG_DBG_MQTT LWGSM_DBG_OFF + +#define LWGSM_CFG_IPD_MAX_BUFF_SIZE 1460 +#define LWGSM_CFG_INPUT_USE_PROCESS 1 +#define LWGSM_CFG_AT_ECHO 0 + +#define LWGSM_CFG_NETWORK 1 + +#define LWGSM_CFG_CONN 1 +#define LWGSM_CFG_SMS 1 +#define LWGSM_CFG_CALL 1 +#define LWGSM_CFG_PHONEBOOK 1 +#define LWGSM_CFG_USSD 1 + +#define LWGSM_CFG_USE_API_FUNC_EVT 1 + +#define LWGSM_CFG_NETCONN 1 + +#define LWGSM_CFG_MEM_CUSTOM 1 + +#if defined(WIN32) +#define LWGSM_CFG_SYS_PORT LWGSM_SYS_PORT_WIN32 +#endif + +#endif /* !__DOXYGEN__ */ + +#endif /* LWGSM_HDR_OPTS_H */ diff --git a/dev/VisualStudio/lwmem_config.h b/dev/VisualStudio/lwmem_opts.h similarity index 75% rename from dev/VisualStudio/lwmem_config.h rename to dev/VisualStudio/lwmem_opts.h index 225127fe..08ea296b 100644 --- a/dev/VisualStudio/lwmem_config.h +++ b/dev/VisualStudio/lwmem_opts.h @@ -1,10 +1,10 @@ /** - * \file lwmem_config.h - * \brief LwMEM configuration file + * \file lwmem_opts.h + * \brief LwMEM application options */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -29,23 +29,20 @@ * This file is part of LwMEM - Lightweight dynamic memory manager library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef LWMEM_HDR_CONFIG_H -#define LWMEM_HDR_CONFIG_H +#ifndef LWMEM_HDR_OPTS_H +#define LWMEM_HDR_OPTS_H -/* Rename this file to "lwmem_config.h" for your application */ +/* Rename this file to "lwmem_opts.h" for your application */ #include "windows.h" /* - * Open "include/lwmem/lwmem_config_default.h" and + * Open "include/lwmem/lwmem_opt.h" and * copy & replace here settings you want to change values */ #define LWMEM_CFG_OS 1 #define LWMEM_CFG_OS_MUTEX_HANDLE HANDLE -/* After user configuration, call default config to merge config together */ -#include "lwmem/lwmem_config_default.h" - -#endif /* LWMEM_HDR_CONFIG_H */ +#endif /* LWMEM_HDR_OPTS_H */ diff --git a/dev/VisualStudio/main.c b/dev/VisualStudio/main.c index d7c37c46..9c4a8718 100644 --- a/dev/VisualStudio/main.c +++ b/dev/VisualStudio/main.c @@ -1,36 +1,39 @@ -// gsm_dev_os.cpp : Defines the entry point for the console application. +// lwgsm_dev_os.cpp : Defines the entry point for the console application. // #include "windows.h" -#include "gsm/gsm.h" +#include "lwgsm/lwgsm.h" -#include "gsm/apps/gsm_mqtt_client_api.h" -#include "gsm/gsm_mem.h" -#include "gsm/gsm_network_api.h" +#include "lwgsm/apps/lwgsm_mqtt_client_api.h" +#include "lwgsm/lwgsm_mem.h" +#include "lwgsm/lwgsm_network_api.h" #include "mqtt_client_api.h" #include "netconn_client.h" #include "sms_send_receive.h" +#include "network_apn_settings.h" +#include "sms_send_receive_thread.h" +#include "client.h" #include "lwmem/lwmem.h" static void main_thread(void* arg); DWORD main_thread_id; -static gsmr_t gsm_evt(gsm_evt_t* evt); -static gsmr_t gsm_conn_evt(gsm_evt_t* evt); +static lwgsmr_t lwgsm_evt(lwgsm_evt_t* evt); +static lwgsmr_t lwgsm_conn_evt(lwgsm_evt_t* evt); -gsm_operator_t operators[10]; +lwgsm_operator_t operators[10]; size_t operators_len; -static gsm_sms_entry_t sms_entry; +static lwgsm_sms_entry_t sms_entry; -gsm_sms_entry_t sms_entries[10]; +lwgsm_sms_entry_t sms_entries[10]; size_t sms_entries_read; -gsm_pb_entry_t pb_entries[10]; +lwgsm_pb_entry_t pb_entries[10]; size_t pb_entries_read; -gsm_operator_curr_t operator_curr; +lwgsm_operator_curr_t operator_curr; char model_str[20]; @@ -40,8 +43,8 @@ typedef struct { const char* puk; } my_sim_t; my_sim_t sim = { - .pin = "7600", - .puk = "08475703", + .pin = "7958", + .puk = "10663647", }; uint8_t lwmem_region_1[0x4000]; @@ -66,7 +69,7 @@ main() { /* Do nothing at this point but do not close the program */ while (1) { - gsm_delay(1000); + lwgsm_delay(1000); } } @@ -79,12 +82,12 @@ uint8_t request_data[] = "" "\r\n"; void -pin_evt(gsmr_t res, void* arg) { +pin_evt(lwgsmr_t res, void* arg) { printf("PIN EVT function!\r\n"); } void -puk_evt(gsmr_t res, void* arg) { +puk_evt(lwgsmr_t res, void* arg) { printf("PUK EVT function!\r\n"); } @@ -106,93 +109,95 @@ input_thread(void* arg) { fgets(buff, sizeof(buff), stdin); if (IS_LINE("reset")) { - gsm_reset(NULL, NULL, 1); + lwgsm_reset(NULL, NULL, 1); } else if (IS_LINE("devicemanufacturer")) { - gsm_device_get_manufacturer(model_str, sizeof(model_str), NULL, NULL, 1); + lwgsm_device_get_manufacturer(model_str, sizeof(model_str), NULL, NULL, 1); printf("Manuf: %s\r\n", model_str); } else if (IS_LINE("devicemodel")) { - gsm_device_get_model(model_str, sizeof(model_str), NULL, NULL, 1); + lwgsm_device_get_model(model_str, sizeof(model_str), NULL, NULL, 1); printf("Model: %s\r\n", model_str); } else if (IS_LINE("deviceserial")) { - gsm_device_get_serial_number(model_str, sizeof(model_str), NULL, NULL, 1); + lwgsm_device_get_serial_number(model_str, sizeof(model_str), NULL, NULL, 1); printf("Serial: %s\r\n", model_str); } else if (IS_LINE("devicerevision")) { - gsm_device_get_revision(model_str, sizeof(model_str), NULL, NULL, 1); + lwgsm_device_get_revision(model_str, sizeof(model_str), NULL, NULL, 1); printf("Revision: %s\r\n", model_str); } else if (IS_LINE("simstatus")) { - switch (gsm_sim_get_current_state()) { - case GSM_SIM_STATE_READY: printf("SIM state ready!\r\n"); break; - case GSM_SIM_STATE_PIN: printf("SIM state PIN\r\n"); break; - case GSM_SIM_STATE_PUK: printf("SIM state PIN\r\n"); break; - case GSM_SIM_STATE_NOT_READY: printf("SIM state not ready\r\n"); break; - case GSM_SIM_STATE_NOT_INSERTED: printf("SIM state not inserted\r\n"); break; + switch (lwgsm_sim_get_current_state()) { + case LWGSM_SIM_STATE_READY: printf("SIM state ready!\r\n"); break; + case LWGSM_SIM_STATE_PIN: printf("SIM state PIN\r\n"); break; + case LWGSM_SIM_STATE_PUK: printf("SIM state PIN\r\n"); break; + case LWGSM_SIM_STATE_NOT_READY: printf("SIM state not ready\r\n"); break; + case LWGSM_SIM_STATE_NOT_INSERTED: printf("SIM state not inserted\r\n"); break; default: printf("Unknown pin state\r\n"); break; } } else if (IS_LINE("simpinadd")) { - gsm_sim_pin_add(sim.pin, NULL, NULL, 1); + lwgsm_sim_pin_add(sim.pin, NULL, NULL, 1); } else if (IS_LINE("simpinchange")) { - gsm_sim_pin_change(sim.pin, "1234", NULL, NULL, 1); - gsm_sim_pin_change("1234", sim.pin, NULL, NULL, 1); + lwgsm_sim_pin_change(sim.pin, "1234", NULL, NULL, 1); + lwgsm_sim_pin_change("1234", sim.pin, NULL, NULL, 1); } else if (IS_LINE("simpinremove")) { - gsm_sim_pin_remove(sim.pin, NULL, NULL, 1); + lwgsm_sim_pin_remove(sim.pin, NULL, NULL, 1); } else if (IS_LINE("simpinenter")) { - gsm_sim_pin_enter(sim.pin, NULL, NULL, 1); + lwgsm_sim_pin_enter(sim.pin, NULL, NULL, 1); } else if (IS_LINE("simpuk")) { - gsm_sim_puk_enter(sim.puk, sim.pin, puk_evt, NULL, 1); + lwgsm_sim_puk_enter(sim.puk, sim.pin, puk_evt, NULL, 1); } else if (IS_LINE("operatorscan")) { - gsm_operator_scan(operators, GSM_ARRAYSIZE(operators), &operators_len, NULL, NULL, 1); + lwgsm_operator_scan(operators, LWGSM_ARRAYSIZE(operators), &operators_len, NULL, NULL, 1); } else if (IS_LINE("join")) { - gsm_network_request_attach(); + lwgsm_network_request_attach(); } else if (IS_LINE("quit")) { - gsm_network_request_detach(); + lwgsm_network_request_detach(); } else if (IS_LINE("netconnclient")) { - gsm_sys_sem_t sem; - gsm_sys_sem_create(&sem, 0); - gsm_sys_thread_create(NULL, "netconn_client", (gsm_sys_thread_fn)netconn_client_thread, &sem, GSM_SYS_THREAD_SS, GSM_SYS_THREAD_PRIO); - gsm_sys_sem_wait(&sem, 0); - gsm_sys_sem_delete(&sem); -#if GSM_CFG_SMS + lwgsm_sys_sem_t sem; + lwgsm_sys_sem_create(&sem, 0); + lwgsm_sys_thread_create(NULL, "netconn_client", (lwgsm_sys_thread_fn)netconn_client_thread, &sem, LWGSM_SYS_THREAD_SS, LWGSM_SYS_THREAD_PRIO); + lwgsm_sys_sem_wait(&sem, 0); + lwgsm_sys_sem_delete(&sem); +#if LWGSM_CFG_SMS } else if (IS_LINE("smsenable")) { - gsm_sms_enable(NULL, NULL, 1); + lwgsm_sms_enable(NULL, NULL, 1); } else if (IS_LINE("smsdisable")) { - gsm_sms_disable(NULL, NULL, 1); + lwgsm_sms_disable(NULL, NULL, 1); } else if (IS_LINE("smssend")) { - gsm_sms_send("+38631779982", "Hello world!", NULL, NULL, 1); + lwgsm_sms_send("+38631779982", "Hello world!", NULL, NULL, 1); } else if (IS_LINE("smslist")) { - gsm_sms_list(GSM_MEM_CURRENT, GSM_SMS_STATUS_ALL, sms_entries, GSM_ARRAYSIZE(sms_entries), &sms_entries_read, 0, NULL, NULL, 1); + lwgsm_sms_list(LWGSM_MEM_CURRENT, LWGSM_SMS_STATUS_ALL, sms_entries, LWGSM_ARRAYSIZE(sms_entries), &sms_entries_read, 0, NULL, NULL, 1); } else if (IS_LINE("smsdeleteall")) { - gsm_sms_delete_all(GSM_SMS_STATUS_ALL, NULL, NULL, 1); + lwgsm_sms_delete_all(LWGSM_SMS_STATUS_ALL, NULL, NULL, 1); } else if (IS_LINE("smsthread")) { - gsm_sys_thread_create(NULL, "sms_recv_send", (gsm_sys_thread_fn)sms_send_receive_thread, NULL, GSM_SYS_THREAD_SS, GSM_SYS_THREAD_PRIO); -#endif /* GSM_CFG_SMS */ -#if GSM_CFG_CALL + lwgsm_sys_thread_create(NULL, "sms_recv_send", (lwgsm_sys_thread_fn)sms_send_receive_thread, NULL, LWGSM_SYS_THREAD_SS, LWGSM_SYS_THREAD_PRIO); +#endif /* LWGSM_CFG_SMS */ +#if LWGSM_CFG_CALL } else if (IS_LINE("callenable")) { - gsm_call_enable(NULL, NULL, 1); + lwgsm_call_enable(NULL, NULL, 1); } else if (IS_LINE("calldisable")) { - gsm_call_disable(NULL, NULL, 1); + lwgsm_call_disable(NULL, NULL, 1); } else if (IS_LINE("callstart")) { - gsm_call_start("+38631779982", NULL, NULL, 1); + lwgsm_call_start("+38631779982", NULL, NULL, 1); } else if (IS_LINE("callhangup")) { - gsm_call_hangup(NULL, NULL, 1); + lwgsm_call_hangup(NULL, NULL, 1); } else if (IS_LINE("callanswer")) { - gsm_call_answer(NULL, NULL, 1); -#endif /* GSM_CFG_CALL */ -#if GSM_CFG_PHONEBOOK + lwgsm_call_answer(NULL, NULL, 1); +#endif /* LWGSM_CFG_CALL */ +#if LWGSM_CFG_PHONEBOOK } else if (IS_LINE("pbenable")) { - gsm_pb_enable(NULL, NULL, 1); + lwgsm_pb_enable(NULL, NULL, 1); } else if (IS_LINE("pbread")) { - gsm_pb_read(GSM_MEM_CURRENT, 1, pb_entries, NULL, NULL, 1); + lwgsm_pb_read(LWGSM_MEM_CURRENT, 1, pb_entries, NULL, NULL, 1); } else if (IS_LINE("pblist")) { - gsm_pb_list(GSM_MEM_CURRENT, 1, pb_entries, GSM_ARRAYSIZE(pb_entries), &pb_entries_read, NULL, NULL, 1); -#endif /* GSM_CFG_PHONEBOOK */ + lwgsm_pb_list(LWGSM_MEM_CURRENT, 1, pb_entries, LWGSM_ARRAYSIZE(pb_entries), &pb_entries_read, NULL, NULL, 1); +#endif /* LWGSM_CFG_PHONEBOOK */ } else if (IS_LINE("mqttthread")) { - gsm_sys_thread_create(NULL, "mqtt_client_api", (gsm_sys_thread_fn)mqtt_client_api_thread, NULL, GSM_SYS_THREAD_SS, GSM_SYS_THREAD_PRIO); -#if GSM_CFG_USSD + lwgsm_sys_thread_create(NULL, "mqtt_client_api", (lwgsm_sys_thread_fn)mqtt_client_api_thread, NULL, LWGSM_SYS_THREAD_SS, LWGSM_SYS_THREAD_PRIO); + } else if (IS_LINE("client")) { + client_connect(); +#if LWGSM_CFG_USSD } else if (IS_LINE("ussd")) { char response[128]; - gsm_ussd_run("*123#", response, sizeof(response), NULL, NULL, 1); + lwgsm_ussd_run("*123#", response, sizeof(response), NULL, NULL, 1); printf("Command finished!\r\n"); -#endif /* GSM_CFG_USSD */ +#endif /* LWGSM_CFG_USSD */ } else { printf("Unknown input!\r\n"); } @@ -204,144 +209,144 @@ input_thread(void* arg) { */ static void main_thread(void* arg) { - gsm_sim_state_t sim_state; + lwgsm_sim_state_t sim_state; /* Init GSM library */ - gsm_init(gsm_evt, 1); + lwgsm_init(lwgsm_evt, 1); /* Set global network credentials */ - gsm_network_set_credentials("internet", "", ""); + lwgsm_network_set_credentials(NETWORK_APN, NETWORK_APN_USER, NETWORK_APN_PASS); /* Start input thread */ - gsm_sys_thread_create(NULL, "input", (gsm_sys_thread_fn)input_thread, NULL, 0, GSM_SYS_THREAD_PRIO); + lwgsm_sys_thread_create(NULL, "input", (lwgsm_sys_thread_fn)input_thread, NULL, 0, LWGSM_SYS_THREAD_PRIO); while (1) { /* Check for sim card */ - while ((sim_state = gsm_sim_get_current_state()) != GSM_SIM_STATE_READY) { - if (sim_state == GSM_SIM_STATE_PIN) { + while ((sim_state = lwgsm_sim_get_current_state()) != LWGSM_SIM_STATE_READY) { + if (sim_state == LWGSM_SIM_STATE_PIN) { printf("GSM state PIN\r\n"); - gsm_sim_pin_enter(sim.pin, pin_evt, NULL, 1); - } else if (sim_state == GSM_SIM_STATE_PUK) { + lwgsm_sim_pin_enter(sim.pin, pin_evt, NULL, 1); + } else if (sim_state == LWGSM_SIM_STATE_PUK) { printf("GSM state PUK\r\n"); - gsm_sim_puk_enter(sim.puk, sim.pin, puk_evt, NULL, 1); - } else if (sim_state == GSM_SIM_STATE_NOT_READY) { + lwgsm_sim_puk_enter(sim.puk, sim.pin, puk_evt, NULL, 1); + } else if (sim_state == LWGSM_SIM_STATE_NOT_READY) { printf("GSM SIM state not ready!\r\n"); - } else if (sim_state == GSM_SIM_STATE_NOT_INSERTED) { + } else if (sim_state == LWGSM_SIM_STATE_NOT_INSERTED) { printf("GSM SIM not inserted!\r\n"); } - gsm_delay(1000); + lwgsm_delay(1000); } /* Some delay */ - gsm_delay(1000); + lwgsm_delay(1000); } /* Terminate thread */ - gsm_sys_thread_terminate(NULL); + lwgsm_sys_thread_terminate(NULL); } -static gsmr_t -gsm_conn_evt(gsm_evt_t* evt) { - gsm_conn_p c; - c = gsm_conn_get_from_evt(evt); - switch (gsm_evt_get_type(evt)) { -#if GSM_CFG_CONN - case GSM_EVT_CONN_ACTIVE: { +static lwgsmr_t +lwgsm_conn_evt(lwgsm_evt_t* evt) { + lwgsm_conn_p c; + c = lwgsm_conn_get_from_evt(evt); + switch (lwgsm_evt_get_type(evt)) { +#if LWGSM_CFG_CONN + case LWGSM_EVT_CONN_ACTIVE: { printf("Connection active\r\n"); - //gsm_conn_send(c, request_data, sizeof(request_data) - 1, NULL, 0); + //lwgsm_conn_send(c, request_data, sizeof(request_data) - 1, NULL, 0); break; } - case GSM_EVT_CONN_ERROR: { + case LWGSM_EVT_CONN_ERROR: { printf("Connection error\r\n"); break; } - case GSM_EVT_CONN_CLOSE: { + case LWGSM_EVT_CONN_CLOSE: { printf("Connection closed\r\n"); break; } - case GSM_EVT_CONN_SEND: { - gsmr_t res = gsm_evt_conn_send_get_result(evt); - if (res == gsmOK) { + case LWGSM_EVT_CONN_SEND: { + lwgsmr_t res = lwgsm_evt_conn_send_get_result(evt); + if (res == lwgsmOK) { printf("Data sent!\r\n"); } else { printf("Data send error!\r\n"); } break; } - case GSM_EVT_CONN_RECV: { - gsm_pbuf_p p = gsm_evt_conn_recv_get_buff(evt); - printf("DATA RECEIVED: %d\r\n", (int)gsm_pbuf_length(p, 1)); - gsm_conn_recved(c, p); + case LWGSM_EVT_CONN_RECV: { + lwgsm_pbuf_p p = lwgsm_evt_conn_recv_get_buff(evt); + printf("DATA RECEIVED: %d\r\n", (int)lwgsm_pbuf_length(p, 1)); + lwgsm_conn_recved(c, p); break; } -#endif /* GSM_CFG_CONN */ +#endif /* LWGSM_CFG_CONN */ default: break; } - return gsmOK; + return lwgsmOK; } /** * \brief Global GSM event function callback * \param[in] cb: Event information - * \return gsmOK on success, member of \ref gsmr_t otherwise + * \return lwgsmOK on success, member of \ref lwgsmr_t otherwise */ -static gsmr_t -gsm_evt(gsm_evt_t* evt) { - switch (gsm_evt_get_type(evt)) { - case GSM_EVT_INIT_FINISH: { +static lwgsmr_t +lwgsm_evt(lwgsm_evt_t* evt) { + switch (lwgsm_evt_get_type(evt)) { + case LWGSM_EVT_INIT_FINISH: { break; } - case GSM_EVT_RESET: { - if (gsm_evt_reset_get_result(evt) == gsmOK) { + case LWGSM_EVT_RESET: { + if (lwgsm_evt_reset_get_result(evt) == lwgsmOK) { printf("Reset sequence finished with success!\r\n"); } break; } - case GSM_EVT_SIM_STATE_CHANGED: { + case LWGSM_EVT_SIM_STATE_CHANGED: { break; } - case GSM_EVT_DEVICE_IDENTIFIED: { + case LWGSM_EVT_DEVICE_IDENTIFIED: { printf("Device has been identified!\r\n"); break; } - case GSM_EVT_SIGNAL_STRENGTH: { - int16_t rssi = gsm_evt_signal_strength_get_rssi(evt); + case LWGSM_EVT_SIGNAL_STRENGTH: { + int16_t rssi = lwgsm_evt_signal_strength_get_rssi(evt); printf("Signal strength: %d\r\n", (int)rssi); break; } - case GSM_EVT_NETWORK_REG_CHANGED: { - gsm_network_reg_status_t status = gsm_network_get_reg_status(); + case LWGSM_EVT_NETWORK_REG_CHANGED: { + lwgsm_network_reg_status_t status = lwgsm_network_get_reg_status(); printf("Network registration changed. New status: %d! ", (int)status); switch (status) { - case GSM_NETWORK_REG_STATUS_CONNECTED: printf("Connected to home network!\r\n"); break; - case GSM_NETWORK_REG_STATUS_CONNECTED_ROAMING: printf("Connected to network and roaming!\r\n"); break; - case GSM_NETWORK_REG_STATUS_SEARCHING: printf("Searching for network!\r\n"); break; - case GSM_NETWORK_REG_STATUS_SIM_ERR: printf("SIM error\r\n"); break; + case LWGSM_NETWORK_REG_STATUS_CONNECTED: printf("Connected to home network!\r\n"); break; + case LWGSM_NETWORK_REG_STATUS_CONNECTED_ROAMING: printf("Connected to network and roaming!\r\n"); break; + case LWGSM_NETWORK_REG_STATUS_SEARCHING: printf("Searching for network!\r\n"); break; + case LWGSM_NETWORK_REG_STATUS_SIM_ERR: printf("SIM error\r\n"); break; default: break; } break; } - case GSM_EVT_NETWORK_OPERATOR_CURRENT: { - const gsm_operator_curr_t* op = gsm_evt_network_operator_get_current(evt); + case LWGSM_EVT_NETWORK_OPERATOR_CURRENT: { + const lwgsm_operator_curr_t* op = lwgsm_evt_network_operator_get_current(evt); if (op != NULL) { - if (op->format == GSM_OPERATOR_FORMAT_LONG_NAME) { + if (op->format == LWGSM_OPERATOR_FORMAT_LONG_NAME) { printf("Operator long name: %s\r\n", op->data.long_name); - } else if (op->format == GSM_OPERATOR_FORMAT_SHORT_NAME) { + } else if (op->format == LWGSM_OPERATOR_FORMAT_SHORT_NAME) { printf("Operator short name: %s\r\n", op->data.short_name); - } else if (op->format == GSM_OPERATOR_FORMAT_NUMBER) { + } else if (op->format == LWGSM_OPERATOR_FORMAT_NUMBER) { printf("Operator number: %d\r\n", (int)op->data.num); } } break; } - case GSM_EVT_OPERATOR_SCAN: { - gsm_operator_t* ops; + case LWGSM_EVT_OPERATOR_SCAN: { + lwgsm_operator_t* ops; size_t length; printf("Operator scan finished!\r\n"); - if (gsm_evt_operator_scan_get_result(evt) == gsmOK) { - ops = gsm_evt_operator_scan_get_entries(evt); - length = gsm_evt_operator_scan_get_length(evt); + if (lwgsm_evt_operator_scan_get_result(evt) == lwgsmOK) { + ops = lwgsm_evt_operator_scan_get_entries(evt); + length = lwgsm_evt_operator_scan_get_length(evt); for (size_t i = 0; i < length; i++) { printf("Operator %2d: %s: %s\r\n", (int)i, ops[i].short_name, ops[i].long_name); @@ -351,66 +356,66 @@ gsm_evt(gsm_evt_t* evt) { } break; } -#if GSM_CFG_NETWORK - case GSM_EVT_NETWORK_ATTACHED: { - gsm_ip_t ip; +#if LWGSM_CFG_NETWORK + case LWGSM_EVT_NETWORK_ATTACHED: { + lwgsm_ip_t ip; printf("\r\n---\r\n--- Network attached! ---\r\n---\r\n"); - if (gsm_network_copy_ip(&ip) == gsmOK) { + if (lwgsm_network_copy_ip(&ip) == lwgsmOK) { printf("\r\n---\r\n--- IP: %d.%d.%d.%d ---\r\n---\r\n", (int)ip.ip[0], (int)ip.ip[1], (int)ip.ip[2], (int)ip.ip[3] ); } break; } - case GSM_EVT_NETWORK_DETACHED: { + case LWGSM_EVT_NETWORK_DETACHED: { printf("\r\n---\r\n--- Network detached! ---\r\n---\r\n"); break; } -#endif /* GSM_CFG_NETWORK */ -#if GSM_CFG_CALL - case GSM_EVT_CALL_READY: { +#endif /* LWGSM_CFG_NETWORK */ +#if LWGSM_CFG_CALL + case LWGSM_EVT_CALL_READY: { printf("Call is ready!\r\n"); break; } - case GSM_EVT_CALL_CHANGED: { - const gsm_call_t* call = evt->evt.call_changed.call; + case LWGSM_EVT_CALL_CHANGED: { + const lwgsm_call_t* call = evt->evt.call_changed.call; printf("Call changed!\r\n"); - if (call->state == GSM_CALL_STATE_ACTIVE) { + if (call->state == LWGSM_CALL_STATE_ACTIVE) { printf("Call active!\r\n"); - } else if (call->state == GSM_CALL_STATE_INCOMING) { + } else if (call->state == LWGSM_CALL_STATE_INCOMING) { printf("Incoming call. Answering...\r\n"); } break; } -#endif /* GSM_CFG_CALL */ -#if GSM_CFG_SMS - case GSM_EVT_SMS_READY: { +#endif /* LWGSM_CFG_CALL */ +#if LWGSM_CFG_SMS + case LWGSM_EVT_SMS_READY: { printf("SMS is ready!\r\n"); - //gsm_sms_send("+38640167724", "Device reset and ready for more operations!", 0); + //lwgsm_sms_send("+38640167724", "Device reset and ready for more operations!", 0); break; } - case GSM_EVT_SMS_SEND: { - if (evt->evt.sms_send.res == gsmOK) { + case LWGSM_EVT_SMS_SEND: { + if (evt->evt.sms_send.res == lwgsmOK) { printf("SMS sent successfully!\r\n"); } else { printf("SMS was not sent!\r\n"); } break; } - case GSM_EVT_SMS_RECV: { + case LWGSM_EVT_SMS_RECV: { printf("SMS received: %d\r\n", (int)evt->evt.sms_recv.pos); - gsm_sms_read(evt->evt.sms_recv.mem, evt->evt.sms_recv.pos, &sms_entry, 0, NULL, NULL, 0); - //gsm_sms_delete(evt->evt.sms_recv.mem, evt->evt.sms_recv.pos, NULL, NULL, 0); + lwgsm_sms_read(evt->evt.sms_recv.mem, evt->evt.sms_recv.pos, &sms_entry, 0, NULL, NULL, 0); + //lwgsm_sms_delete(evt->evt.sms_recv.mem, evt->evt.sms_recv.pos, NULL, NULL, 0); break; } - case GSM_EVT_SMS_READ: { - gsm_sms_entry_t* e = evt->evt.sms_read.entry; + case LWGSM_EVT_SMS_READ: { + lwgsm_sms_entry_t* e = evt->evt.sms_read.entry; printf("SMS read: num: %s, name: %s, data: %s\r\n", e->number, e->name, e->data); break; } - case GSM_EVT_SMS_LIST: { - gsm_sms_entry_t* e = evt->evt.sms_list.entries; + case LWGSM_EVT_SMS_LIST: { + lwgsm_sms_entry_t* e = evt->evt.sms_list.entries; size_t i; for (i = 0; i < evt->evt.sms_list.size; i++) { @@ -420,10 +425,10 @@ gsm_evt(gsm_evt_t* evt) { } break; } -#endif /* GSM_CFG_SMS */ -#if GSM_CFG_PHONEBOOK - case GSM_EVT_PB_LIST: { - gsm_pb_entry_t* e = evt->evt.pb_list.entries; +#endif /* LWGSM_CFG_SMS */ +#if LWGSM_CFG_PHONEBOOK + case LWGSM_EVT_PB_LIST: { + lwgsm_pb_entry_t* e = evt->evt.pb_list.entries; size_t i; for (i = 0; i < evt->evt.pb_list.size; i++) { @@ -433,8 +438,8 @@ gsm_evt(gsm_evt_t* evt) { } break; } - case GSM_EVT_PB_SEARCH: { - gsm_pb_entry_t* e = evt->evt.pb_search.entries; + case LWGSM_EVT_PB_SEARCH: { + lwgsm_pb_entry_t* e = evt->evt.pb_search.entries; size_t i; for (i = 0; i < evt->evt.pb_search.size; i++) { @@ -444,16 +449,16 @@ gsm_evt(gsm_evt_t* evt) { } break; } -#endif /* GSM_CFG_PHONECALL */ +#endif /* LWGSM_CFG_PHONECALL */ default: break; } - return gsmOK; + return lwgsmOK; } -#if GSM_CFG_MEM_CUSTOM && 0 +#if LWGSM_CFG_MEM_CUSTOM && 0 void * -gsm_mem_malloc(size_t size) { +lwgsm_mem_malloc(size_t size) { void* ptr; while (WaitForSingleObject(allocation_mutex, INFINITE) != WAIT_OBJECT_0) {} @@ -463,7 +468,7 @@ gsm_mem_malloc(size_t size) { } void * -gsm_mem_realloc(void* ptr, size_t size) { +lwgsm_mem_realloc(void* ptr, size_t size) { void* p; while (WaitForSingleObject(allocation_mutex, INFINITE) != WAIT_OBJECT_0) {} @@ -473,7 +478,7 @@ gsm_mem_realloc(void* ptr, size_t size) { } void * -gsm_mem_calloc(size_t num, size_t size) { +lwgsm_mem_calloc(size_t num, size_t size) { void* ptr; while (WaitForSingleObject(allocation_mutex, INFINITE) != WAIT_OBJECT_0) {} @@ -483,9 +488,9 @@ gsm_mem_calloc(size_t num, size_t size) { } void -gsm_mem_free(void* ptr) { +lwgsm_mem_free(void* ptr) { while (WaitForSingleObject(allocation_mutex, INFINITE) != WAIT_OBJECT_0) {} free(ptr); ReleaseMutex(allocation_mutex); } -#endif /* GSM_CFG_MEM_CUSTOM */ +#endif /* LWGSM_CFG_MEM_CUSTOM */ diff --git a/docs/4a-esp8266_at_instruction_set_en.pdf b/docs/4a-esp8266_at_instruction_set_en.pdf new file mode 100644 index 00000000..8ce6e9f9 Binary files /dev/null and b/docs/4a-esp8266_at_instruction_set_en.pdf differ diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..d4bb2cbb --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/api-reference/apps/index.rst b/docs/api-reference/apps/index.rst new file mode 100644 index 00000000..86bb8c46 --- /dev/null +++ b/docs/api-reference/apps/index.rst @@ -0,0 +1,10 @@ +.. _api_apps: + +Applications +============ + +.. toctree:: + :maxdepth: 2 + :glob: + + * \ No newline at end of file diff --git a/docs/api-reference/apps/mqtt_client.rst b/docs/api-reference/apps/mqtt_client.rst new file mode 100644 index 00000000..6e17b43f --- /dev/null +++ b/docs/api-reference/apps/mqtt_client.rst @@ -0,0 +1,14 @@ +.. _api_app_mqtt_client: + +MQTT Client +=========== + +MQTT client v3.1.1 implementation, based on callback (non-netconn) connection API. + +.. literalinclude:: ../../../snippets/mqtt_client.c + :language: c + :linenos: + :caption: MQTT application example code + +.. doxygengroup:: LWGSM_APP_MQTT_CLIENT +.. doxygengroup:: LWGSM_APP_MQTT_CLIENT_EVT \ No newline at end of file diff --git a/docs/api-reference/apps/mqtt_client_api.rst b/docs/api-reference/apps/mqtt_client_api.rst new file mode 100644 index 00000000..3220fc4f --- /dev/null +++ b/docs/api-reference/apps/mqtt_client_api.rst @@ -0,0 +1,13 @@ +.. _api_app_mqtt_client_api: + +MQTT Client API +=============== + +*MQTT Client API* provides sequential API built on top of :ref:`api_app_mqtt_client`. + +.. literalinclude:: ../../../snippets/mqtt_client_api.c + :language: c + :linenos: + :caption: MQTT API application example code + +.. doxygengroup:: LWGSM_APP_MQTT_CLIENT_API \ No newline at end of file diff --git a/docs/api-reference/apps/netconn.rst b/docs/api-reference/apps/netconn.rst new file mode 100644 index 00000000..33dbd489 --- /dev/null +++ b/docs/api-reference/apps/netconn.rst @@ -0,0 +1,55 @@ +.. _api_app_netconn: + +Netconn API +=========== + +*Netconn API* is addon on top of existing connection module and allows sending and receiving data with sequential API calls, similar to *POSIX socket* API. + +It can operate in client mode and uses operating system features, such as message queues and semaphore to link non-blocking callback API for connections with sequential API for application thread. + +.. note:: + Connection API does not directly allow receiving data with sequential and linear code execution. + All is based on connection event system. + Netconn adds this functionality as it is implemented on top of regular connection API. + +.. warning:: + Netconn API are designed to be called from application threads ONLY. + It is not allowed to call any of *netconn API* functions from within interrupt or callback event functions. + +Netconn client +^^^^^^^^^^^^^^ + +.. figure:: ../../static/images/netconn_client.svg + :align: center + :alt: Netconn API client block diagram + + Netconn API client block diagram + +Above block diagram shows basic architecture of netconn client application. +There is always one application thread (in green) which calls *netconn API* functions to interact with connection API in synchronous mode. + +Every netconn connection uses dedicated structure to handle message queue for data received packet buffers. +Each time new packet is received (red block, *data received event*), reference to it is written to message queue of netconn structure, while application thread reads new entries from the same queue to get packets. + +.. literalinclude:: ../../../snippets/netconn_client.c + :language: c + :linenos: + :caption: Netconn client example + +Non-blocking receive +^^^^^^^^^^^^^^^^^^^^ + +By default, netconn API is written to only work in separate application thread, +dedicated for network connection processing. Because of that, by default every function is fully blocking. +It will wait until result is ready to be used by application. + +It is, however, possible to enable timeout feature for receiving data only. +When this feature is enabled, :cpp:func:`lwgsm_netconn_receive` will block for maximal timeout set with +:cpp:func:`lwgsm_netconn_set_receive_timeout` function. + +When enabled, if there is no received data for timeout amount of time, function will return with timeout status and application needs to process it accordingly. + +.. tip:: + :c:macro:`LWGSM_CFG_NETCONN_RECEIVE_TIMEOUT` must be set to ``1`` to use this feature. + +.. doxygengroup:: LWGSM_NETCONN \ No newline at end of file diff --git a/docs/api-reference/index.rst b/docs/api-reference/index.rst new file mode 100644 index 00000000..5abaa6fa --- /dev/null +++ b/docs/api-reference/index.rst @@ -0,0 +1,14 @@ +.. _api_reference: + +API reference +============= + +List of all the modules: + +.. toctree:: + :maxdepth: 2 + + lwgsm/index + opt + port/index + apps/index \ No newline at end of file diff --git a/docs/api-reference/lwgsm/buff.rst b/docs/api-reference/lwgsm/buff.rst new file mode 100644 index 00000000..d64b47ff --- /dev/null +++ b/docs/api-reference/lwgsm/buff.rst @@ -0,0 +1,6 @@ +.. _api_lwgsm_buff: + +Ring buffer +=========== + +.. doxygengroup:: LWGSM_BUFF \ No newline at end of file diff --git a/docs/api-reference/lwgsm/conn.rst b/docs/api-reference/lwgsm/conn.rst new file mode 100644 index 00000000..949f2946 --- /dev/null +++ b/docs/api-reference/lwgsm/conn.rst @@ -0,0 +1,69 @@ +.. _api_lwgsm_conn: + +Connections +=========== + +Connections are essential feature of WiFi device and middleware. +It is developed with strong focus on its performance and since it may interact with huge amount of data, +it tries to use zero-copy (when available) feature, to decrease processing time. + +*GSM AT Firmware* by default supports up to ``5`` connections being active at the same time and supports: + +* Up to ``5`` TCP connections active at the same time +* Up to ``5`` UDP connections active at the same time +* Up to ``1`` SSL connection active at a time + +.. note:: + Client or server connections are available. + Same API function call are used to send/receive data or close connection. + +Architecture of the connection API is using callback event functions. +This allows maximal optimization in terms of responsiveness on different kind of events. + +Example below shows *bare minimum* implementation to: + +* Start a new connection to remote host +* Send *HTTP GET* request to remote host +* Process received data in event and print number of received bytes + +.. literalinclude:: ../../../snippets/client.c + :language: c + :linenos: + :caption: Client connection minimum example + +Sending data +^^^^^^^^^^^^ + +Receiving data flow is always the same. Whenever new data packet arrives, corresponding event is called to notify application layer. +When it comes to sending data, application may decide between ``2`` options (*this is valid only for non-UDP connections): + +* Write data to temporary transmit buffer +* Execute *send command* for every API function call + +Temporary transmit buffer +************************* + +By calling :cpp:func:`lwgsm_conn_write` on active connection, temporary buffer is allocated and input data are copied to it. +There is always up to ``1`` internal buffer active. When it is full (or if input data length is longer than maximal size), +data are immediately send out and are not written to buffer. + +*GSM AT Firmware* allows (current revision) to transmit up to ``2048`` bytes at a time with single command. +When trying to send more than this, application would need to issue multiple *send commands* on *AT commands level*. + +Write option is used mostly when application needs to write many different small chunks of data. +Temporary buffer hence prevents many *send command* instructions as it is faster to send single command with big buffer, +than many of them with smaller chunks of bytes. + +.. literalinclude:: ../../examples_src/conn_write.c + :language: c + :linenos: + :caption: Write data to connection output buffer + +Transmit packet manually +************************ + +In some cases it is not possible to use temporary buffers, +mostly because of memory constraints. +Application can directly start *send data* instructions on *AT* level by using :cpp:func:`lwgsm_conn_send` or :cpp:func:`lwgsm_conn_sendto` functions. + +.. doxygengroup:: LWGSM_CONN \ No newline at end of file diff --git a/docs/api-reference/lwgsm/debug.rst b/docs/api-reference/lwgsm/debug.rst new file mode 100644 index 00000000..a9953e53 --- /dev/null +++ b/docs/api-reference/lwgsm/debug.rst @@ -0,0 +1,39 @@ +.. _api_lwgsm_debug: + +Debug support +============= + +Middleware has extended debugging capabilities. +These consist of different debugging levels and types of debug messages, +allowing to track and catch different types of warnings, severe problems or simply output messages +program flow messages (trace messages). + +Module is highly configurable using library configuration methods. +Application must enable some options to decide what type of messages and for which modules it would like to output messages. + +With default configuration, ``printf`` is used as output function. +This behavior can be changed with :c:macro:`LWGSM_CFG_DBG_OUT` configuration. + +For successful debugging, application must: + +* Enable global debugging by setting :c:macro:`LWGSM_CFG_DBG` to :c:macro:`LWGSM_DBG_ON` +* Configure which types of messages to output +* Configure debugging level, from all messages to severe only +* Enable specific modules to debug, by setting its configuration value to :c:macro:`LWGSM_DBG_ON` + +.. tip:: + Check :ref:`api_lwgsm_opt` for all modules with debug implementation. + +An example code with config and latter usage: + +.. literalinclude:: ../../examples_src/debug_opts.h + :language: c + :linenos: + :caption: Debug configuration setup + +.. literalinclude:: ../../examples_src/debug.c + :language: c + :linenos: + :caption: Debug usage within middleware + +.. doxygengroup:: LWGSM_DEBUG \ No newline at end of file diff --git a/docs/api-reference/lwgsm/device_info.rst b/docs/api-reference/lwgsm/device_info.rst new file mode 100644 index 00000000..17386aa5 --- /dev/null +++ b/docs/api-reference/lwgsm/device_info.rst @@ -0,0 +1,6 @@ +.. _api_lwgsm_device_info: + +Device info +=========== + +.. doxygengroup:: LWGSM_DEVICE_INFO \ No newline at end of file diff --git a/docs/api-reference/lwgsm/evt.rst b/docs/api-reference/lwgsm/evt.rst new file mode 100644 index 00000000..3029e7a0 --- /dev/null +++ b/docs/api-reference/lwgsm/evt.rst @@ -0,0 +1,6 @@ +.. _api_lwgsm_evt: + +Event management +================ + +.. doxygengroup:: LWGSM_EVT \ No newline at end of file diff --git a/docs/api-reference/lwgsm/ftp.rst b/docs/api-reference/lwgsm/ftp.rst new file mode 100644 index 00000000..1f64016a --- /dev/null +++ b/docs/api-reference/lwgsm/ftp.rst @@ -0,0 +1,6 @@ +.. _api_lwgsm_ftp: + +File Transfer Protocol +====================== + +.. doxygengroup:: LWGSM_FTP \ No newline at end of file diff --git a/docs/api-reference/lwgsm/http.rst b/docs/api-reference/lwgsm/http.rst new file mode 100644 index 00000000..31717e33 --- /dev/null +++ b/docs/api-reference/lwgsm/http.rst @@ -0,0 +1,6 @@ +.. _api_lwgsm_http: + +HTTP +==== + +.. doxygengroup:: LWGSM_HTTP \ No newline at end of file diff --git a/docs/api-reference/lwgsm/index.rst b/docs/api-reference/lwgsm/index.rst new file mode 100644 index 00000000..3fe6d2fe --- /dev/null +++ b/docs/api-reference/lwgsm/index.rst @@ -0,0 +1,12 @@ +.. _api_lwgsm: + +LwGSM +===== + +.. toctree:: + :maxdepth: 2 + :glob: + + * + +.. doxygengroup:: LWGSM \ No newline at end of file diff --git a/docs/api-reference/lwgsm/input.rst b/docs/api-reference/lwgsm/input.rst new file mode 100644 index 00000000..ba8c05b6 --- /dev/null +++ b/docs/api-reference/lwgsm/input.rst @@ -0,0 +1,43 @@ +.. _api_lwgsm_input: + +Input module +============ + +Input module is used to input received data from *GSM* device to *LwGSM-Lib* middleware part. +``2`` processing options are possible: + +* Indirect processing with :cpp:func:`lwgsm_input` (default mode) +* Direct processing with :cpp:func:`lwgsm_input_process` + +.. tip:: + Direct or indirect processing mode is select by setting :c:macro:`LWGSM_CFG_INPUT_USE_PROCESS` configuration value. + +Indirect processing +^^^^^^^^^^^^^^^^^^^ + +With indirect processing mode, every received character from *GSM* physical device is written to +intermediate buffer between low-level driver and *processing* thread. + +Function :cpp:func:`lwgsm_input` is used to write data to buffer, which is later processed +by *processing* thread. + +Indirect processing mode allows embedded systems to write received data to buffer from interrupt context (outside threads). +As a drawback, its performance is decreased as it involves copying every receive character to intermediate buffer, +and may also introduce RAM memory footprint increase. + +Direct processing +^^^^^^^^^^^^^^^^^ + +Direct processing is targeting more advanced host controllers, like STM32 or WIN32 implementation use. +It is developed with DMA support in mind, allowing low-level drivers to skip intermediate data buffer +and process input bytes directly. + +.. note:: + When using this mode, function :cpp:func:`lwgsm_input_process` must be used and it may + only be called from thread context. Processing of input bytes is done in low-level + input thread, started by application. + +.. tip:: + Check :ref:`um_porting_guide` for implementation examples. + +.. doxygengroup:: LWGSM_INPUT \ No newline at end of file diff --git a/docs/api-reference/lwgsm/mem.rst b/docs/api-reference/lwgsm/mem.rst new file mode 100644 index 00000000..d832e187 --- /dev/null +++ b/docs/api-reference/lwgsm/mem.rst @@ -0,0 +1,6 @@ +.. _api_lwgsm_mem: + +Memory manager +============== + +.. doxygengroup:: LWGSM_MEM \ No newline at end of file diff --git a/docs/api-reference/lwgsm/network.rst b/docs/api-reference/lwgsm/network.rst new file mode 100644 index 00000000..d7cababd --- /dev/null +++ b/docs/api-reference/lwgsm/network.rst @@ -0,0 +1,6 @@ +.. _api_lwgsm_network: + +Network +======= + +.. doxygengroup:: LWGSM_NETWORK \ No newline at end of file diff --git a/docs/api-reference/lwgsm/network_api.rst b/docs/api-reference/lwgsm/network_api.rst new file mode 100644 index 00000000..0ac40da8 --- /dev/null +++ b/docs/api-reference/lwgsm/network_api.rst @@ -0,0 +1,11 @@ +.. _api_lwgsm_network_api: + +Network API +=========== + +Network API provides functions for multi-thread application network management. +It allows multiple threads to request to join to network (internet access). + +Network API module controls when network connection shall be active or can be closed. + +.. doxygengroup:: LWGSM_NETWORK_API \ No newline at end of file diff --git a/docs/api-reference/lwgsm/operator.rst b/docs/api-reference/lwgsm/operator.rst new file mode 100644 index 00000000..bb5af651 --- /dev/null +++ b/docs/api-reference/lwgsm/operator.rst @@ -0,0 +1,6 @@ +.. _api_lwgsm_operator: + +Network operator +================ + +.. doxygengroup:: LWGSM_OPERATOR \ No newline at end of file diff --git a/docs/api-reference/lwgsm/pbuf.rst b/docs/api-reference/lwgsm/pbuf.rst new file mode 100644 index 00000000..31499c86 --- /dev/null +++ b/docs/api-reference/lwgsm/pbuf.rst @@ -0,0 +1,164 @@ +.. _api_lwgsm_pbuf: + +Packet buffer +============= + +Packet buffer (or *pbuf*) is buffer manager to handle received data from any connection. +It is optimized to construct big buffer of smaller chunks of fragmented data as received bytes are not always coming as single packet. + +Pbuf block diagram +^^^^^^^^^^^^^^^^^^ + +.. figure:: ../../static/images/pbuf_block_diagram.svg + :align: center + :alt: Block diagram of pbuf chain + + Block diagram of pbuf chain + +Image above shows structure of *pbuf* chain. Each *pbuf* consists of: + +* Pointer to next *pbuf*, or ``NULL`` when it is last in chain +* Length of current packet length +* Length of current packet and all next in chain + + * If *pbuf* is last in chain, total length is the same as current packet length + +* Reference counter, indicating how many pointers point to current *pbuf* +* Actual buffer data + +Top image shows ``3`` pbufs connected to single chain. +There are ``2`` custom pointer variables to point at different *pbuf* structures. Second *pbuf* has reference counter set to ``2``, as ``2`` variables point to it: + +* *next* of *pbuf 1* is the first one +* *User variable 2* is the second one + +.. table:: Block structure + + +--------------+-----------+------------+---------------------+-------------------+ + | Block number | Next pbuf | Block size | Total size in chain | Reference counter | + +==============+===========+============+=====================+===================+ + | Block 1 | *Block 2* | ``150`` | ``550`` | ``1`` | + +--------------+-----------+------------+---------------------+-------------------+ + | Block 2 | *Block 3* | ``130`` | ``400`` | ``2`` | + +--------------+-----------+------------+---------------------+-------------------+ + | Block 3 | ``NULL`` | ``270`` | ``270`` | ``1`` | + +--------------+-----------+------------+---------------------+-------------------+ + +Reference counter +^^^^^^^^^^^^^^^^^ + +Reference counter holds number of references (or variables) pointing to this block. +It is used to properly handle memory free operation, especially when *pbuf* is used by lib core and application layer. + +.. note:: + If there would be no reference counter information and application would free memory while another part of library still uses its reference, application would invoke *undefined behavior* and system could crash instantly. + +When application tries to free pbuf chain as on first image, it would normally call :cpp:func:`lwgsm_pbuf_free` function. That would: + +* Decrease reference counter by ``1`` +* If reference counter ``== 0``, it removes it from chain list and frees packet buffer memory +* If reference counter ``!= 0`` after decrease, it stops free procedure +* Go to next pbuf in chain and repeat steps + +As per first example, result of freeing from *user variable 1* would look similar to image and table below. +First block (blue) had reference counter set to ``1`` prior freeing operation. +It was successfully removed as *user variable 1* was the only one pointing to it, +while second (green) block had reference counter set to ``2``, preventing free operation. + +.. figure:: ../../static/images/pbuf_block_diagram_after_free.svg + :align: center + :alt: Block diagram of pbuf chain after free from *user variable 1* + + Block diagram of pbuf chain after free from *user variable 1* + +.. table:: Block diagram of pbuf chain after free from *user variable 1* + + +--------------+-----------+------------+---------------------+-------------------+ + | Block number | Next pbuf | Block size | Total size in chain | Reference counter | + +==============+===========+============+=====================+===================+ + | Block 2 | *Block 3* | ``130`` | ``400`` | ``1`` | + +--------------+-----------+------------+---------------------+-------------------+ + | Block 3 | ``NULL`` | ``270`` | ``270`` | ``1`` | + +--------------+-----------+------------+---------------------+-------------------+ + +.. note:: + *Block 1* has been successfully freed, but since *block 2* had reference counter set to ``2`` before, it was only decreased by ``1`` to a new value ``1`` and free operation stopped instead. + *User variable 2* is still using *pbuf* starting at *block 2* and must manually call :cpp:func:`lwgsm_pbuf_free` to free it. + +Concatenating vs chaining +^^^^^^^^^^^^^^^^^^^^^^^^^ + +This section will explain difference between *concat* and *chain* operations. +Both operations link ``2`` pbufs together in a chain of pbufs, +difference is that *chain* operation increases *reference counter* to linked pbuf, +while *concat* keeps *reference counter* at its current status. + +.. figure:: ../../static/images/pbuf_cat_vs_chain_1.svg + :align: center + :alt: Different pbufs, each pointed to by its own variable + + Different pbufs, each pointed to by its own variable + +Concat operation +**************** + +Concat operation shall be used when ``2`` pbufs are linked together and reference to *second* is no longer used. + +.. figure:: ../../static/images/pbuf_cat_vs_chain_2.svg + :align: center + :alt: Structure after pbuf concat + + Structure after pbuf concat + +After concating *2 pbufs* together, reference counter of second is still set to ``1``, however we can see that ``2`` pointers point to *second pbuf*. + +.. note:: + After application calls :cpp:func:`lwgsm_pbuf_cat`, it must not use pointer which points to *second pbuf*. + This would invoke *undefined behavior* if one pointer tries to free memory while second still points to it. + +An example code showing proper usage of concat operation: + +.. literalinclude:: ../../examples_src/pbuf_cat.c + :language: c + :linenos: + :caption: Packet buffer concat example + +Chain operation +*************** + +Chain operation shall be used when ``2`` pbufs are linked together and reference to *second* is still required. + +.. figure:: ../../static/images/pbuf_cat_vs_chain_3.svg + :align: center + :alt: Structure after pbuf chain + + Structure after pbuf chain + +After chainin *2 pbufs* together, reference counter of second is increased by ``1``, which allows application to reference second *pbuf* separatelly. + +.. note:: + After application calls :cpp:func:`lwgsm_pbuf_chain`, + it also has to manually free its reference using :cpp:func:`lwgsm_pbuf_free` function. + Forgetting to free pbuf invokes memory leak + +An example code showing proper usage of chain operation: + +.. literalinclude:: ../../examples_src/pbuf_chain.c + :language: c + :linenos: + :caption: Packet buffer chain example + +Extract pbuf data +***************** + +Each *pbuf* holds some amount of data bytes. When multiple *pbufs* are linked together (either chained or concated), blocks of raw data are not linked to contiguous memory block. +It is necessary to process block by block manually. + +An example code showing proper reading of any *pbuf*: + +.. literalinclude:: ../../examples_src/pbuf_extract.c + :language: c + :linenos: + :caption: Packet buffer data extraction + +.. doxygengroup:: LWGSM_PBUF \ No newline at end of file diff --git a/docs/api-reference/lwgsm/phonebook.rst b/docs/api-reference/lwgsm/phonebook.rst new file mode 100644 index 00000000..6c8b9c46 --- /dev/null +++ b/docs/api-reference/lwgsm/phonebook.rst @@ -0,0 +1,6 @@ +.. _api_lwgsm_pb: + +Phonebook +========= + +.. doxygengroup:: LWGSM_PHONEBOOK \ No newline at end of file diff --git a/docs/api-reference/lwgsm/ping.rst b/docs/api-reference/lwgsm/ping.rst new file mode 100644 index 00000000..4834d61b --- /dev/null +++ b/docs/api-reference/lwgsm/ping.rst @@ -0,0 +1,6 @@ +.. _api_lwgsm_ping: + +Ping support +============ + +.. doxygengroup:: LWGSM_PING \ No newline at end of file diff --git a/docs/api-reference/lwgsm/sim.rst b/docs/api-reference/lwgsm/sim.rst new file mode 100644 index 00000000..930c131b --- /dev/null +++ b/docs/api-reference/lwgsm/sim.rst @@ -0,0 +1,6 @@ +.. _api_lwgsm_sim: + +SIM card +======== + +.. doxygengroup:: LWGSM_SIM \ No newline at end of file diff --git a/docs/api-reference/lwgsm/sms.rst b/docs/api-reference/lwgsm/sms.rst new file mode 100644 index 00000000..8c57adf5 --- /dev/null +++ b/docs/api-reference/lwgsm/sms.rst @@ -0,0 +1,6 @@ +.. _api_lwgsm_sms: + +SMS +=== + +.. doxygengroup:: LWGSM_SMS \ No newline at end of file diff --git a/docs/api-reference/lwgsm/timeout.rst b/docs/api-reference/lwgsm/timeout.rst new file mode 100644 index 00000000..3bae5147 --- /dev/null +++ b/docs/api-reference/lwgsm/timeout.rst @@ -0,0 +1,18 @@ +.. _api_lwgsm_timeout: + +Timeout manager +=============== + +Timeout manager allows application to call specific function at desired time. +It is used in middleware (and can be used by application too) to poll active connections. + +.. note:: + Callback function is called from *processing* thread. + It is not allowed to call any blocking API function from it. + +When application registers timeout, it needs to set timeout, callback function and optional user argument. +When timeout elapses, GSM middleware will call timeout callback. + +This feature can be considered as single-shot software timer. + +.. doxygengroup:: LWGSM_TIMEOUT \ No newline at end of file diff --git a/docs/api-reference/lwgsm/typedefs.rst b/docs/api-reference/lwgsm/typedefs.rst new file mode 100644 index 00000000..c5086ee1 --- /dev/null +++ b/docs/api-reference/lwgsm/typedefs.rst @@ -0,0 +1,6 @@ +.. _api_lwgsm_typedefs: + +Structures and enumerations +=========================== + +.. doxygengroup:: LWGSM_TYPEDEFS \ No newline at end of file diff --git a/docs/api-reference/lwgsm/unicode.rst b/docs/api-reference/lwgsm/unicode.rst new file mode 100644 index 00000000..4e19ad12 --- /dev/null +++ b/docs/api-reference/lwgsm/unicode.rst @@ -0,0 +1,12 @@ +.. _api_lwgsm_unicode: + +Unicode +======= + +Unicode decoder block. It can decode sequence of *UTF-8* characters, +between ``1`` and ``4`` bytes long. + +.. note:: + This is simple implementation and does not support string encoding. + +.. doxygengroup:: LWGSM_UNICODE \ No newline at end of file diff --git a/docs/api-reference/lwgsm/ussd.rst b/docs/api-reference/lwgsm/ussd.rst new file mode 100644 index 00000000..15f01118 --- /dev/null +++ b/docs/api-reference/lwgsm/ussd.rst @@ -0,0 +1,6 @@ +.. _api_lwgsm_ussd: + +Unstructured Supplementary Service Data +======================================= + +.. doxygengroup:: LWGSM_USSD \ No newline at end of file diff --git a/docs/api-reference/lwgsm/utils.rst b/docs/api-reference/lwgsm/utils.rst new file mode 100644 index 00000000..13a4005e --- /dev/null +++ b/docs/api-reference/lwgsm/utils.rst @@ -0,0 +1,9 @@ +.. _api_lwgsm_utils: + +Utilities +========= + +Utility functions for various cases. +These function are used across entire middleware and can also be used by application. + +.. doxygengroup:: LWGSM_UTILS \ No newline at end of file diff --git a/docs/api-reference/opt.rst b/docs/api-reference/opt.rst new file mode 100644 index 00000000..cdbee775 --- /dev/null +++ b/docs/api-reference/opt.rst @@ -0,0 +1,18 @@ +.. _api_lwgsm_opt: + +Configuration +============= + +This is the default configuration of the middleware. +When any of the settings shall be modified, it shall be done in dedicated application config ``lwgsm_opts.h`` file. + +.. note:: + Check :ref:`getting_started` for guidelines on how to create and use configuration file. + +.. doxygengroup:: LWGSM_OPT +.. doxygengroup:: LWGSM_OPT_DBG +.. doxygengroup:: LWGSM_OPT_OS +.. doxygengroup:: LWGSM_OPT_STD_LIB +.. doxygengroup:: LWGSM_OPT_MODULES +.. doxygengroup:: LWGSM_OPT_MODULES_NETCONN +.. doxygengroup:: LWGSM_OPT_MODULES_MQTT diff --git a/docs/api-reference/port/index.rst b/docs/api-reference/port/index.rst new file mode 100644 index 00000000..171db230 --- /dev/null +++ b/docs/api-reference/port/index.rst @@ -0,0 +1,12 @@ +.. _api_lwgsm_port: + +Platform specific +================= + +List of all the modules: + +.. toctree:: + :maxdepth: 2 + :glob: + + * \ No newline at end of file diff --git a/docs/api-reference/port/ll.rst b/docs/api-reference/port/ll.rst new file mode 100644 index 00000000..1db83deb --- /dev/null +++ b/docs/api-reference/port/ll.rst @@ -0,0 +1,12 @@ +.. _api_lwgsm_ll: + +Low-Level functions +=================== + +Low-level module consists of callback-only functions, which are called by middleware +and must be implemented by final application. + +.. tip:: + Check :ref:`um_porting_guide` for actual implementation + +.. doxygengroup:: LWGSM_LL \ No newline at end of file diff --git a/docs/api-reference/port/sys.rst b/docs/api-reference/port/sys.rst new file mode 100644 index 00000000..6702a6cd --- /dev/null +++ b/docs/api-reference/port/sys.rst @@ -0,0 +1,20 @@ +.. _api_lwgsm_sys: + +System functions +================ + +System functions are bridge between operating system system calls and middleware system calls. +Middleware is tightly coupled with operating system features hence it is important to include OS features directly. + +It includes support for: + +* Thread management, to start/stop threads +* Mutex management for recursive mutexes +* Semaphore management for binary-only semaphores +* Message queues for thread-safe data exchange between threads +* Core system protection for mutual exclusion to access shared resources + +.. tip:: + Check :ref:`um_porting_guide` for actual implementation guidelines. + +.. doxygengroup:: LWGSM_SYS \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 00000000..0a19cb89 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,129 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) +from sphinx.builders.html import StandaloneHTMLBuilder +import subprocess, os + +# Run doxygen first +# read_the_docs_build = os.environ.get('READTHEDOCS', None) == 'True' +# if read_the_docs_build: +subprocess.call('doxygen doxyfile.doxy', shell=True) +# -- Project information ----------------------------------------------------- + +project = 'LwGSM' +copyright = '2020, Tilen MAJERLE' +author = 'Tilen MAJERLE' + +# The full version, including alpha/beta/rc tags +version = '0.1.0' + +# Try to get branch at which this is running +# and try to determine which version to display in sphinx +git_branch = '' +res = os.popen('git branch').read().strip() +for line in res.split("\n"): + if line[0] == '*': + git_branch = line[1:].strip() + +# Decision for display version +try: + if git_branch.index('develop') >= 0: + version = "latest-develop" +except Exception: + print("Exception for index check") + +# For debugging purpose +print("GIT BRANCH: " + git_branch) +print("VERSION: " + version) + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.intersphinx', + 'sphinx.ext.autosectionlabel', + 'sphinx.ext.todo', + 'sphinx.ext.coverage', + 'sphinx.ext.mathjax', + 'sphinx.ext.ifconfig', + 'sphinx.ext.viewcode', + 'sphinx_sitemap', + + 'breathe', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +highlight_language = 'c' + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'sphinx_rtd_theme' +html_theme_options = { + 'canonical_url': '', + 'analytics_id': '', # Provided by Google in your dashboard + 'display_version': True, + 'prev_next_buttons_location': 'bottom', + 'style_external_links': False, + + 'logo_only': False, + + # Toc options + 'collapse_navigation': True, + 'sticky_navigation': True, + 'navigation_depth': 4, + 'includehidden': True, + 'titles_only': False +} +html_logo = 'static/images/logo_tm.png' +github_url = 'https://github.com/MaJerle/gsm-at-lib' +html_baseurl = 'https://docs.majerle.eu/projects/gsm-at-lib/' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['static'] +html_css_files = [ + 'css/common.css', + 'css/custom.css', +] +html_js_files = [ + 'https://kit.fontawesome.com/3102794088.js' +] + +master_doc = 'index' + +# +# Breathe configuration +# +# +# +breathe_projects = { + "gsm_at_lib": "_build/xml/" +} +breathe_default_project = "gsm_at_lib" +breathe_default_members = ('members', 'undoc-members') \ No newline at end of file diff --git a/docs/doxyfile.doxy b/docs/doxyfile.doxy new file mode 100644 index 00000000..8c7e3e0b --- /dev/null +++ b/docs/doxyfile.doxy @@ -0,0 +1,2456 @@ +# Doxyfile 1.8.10 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "LwGSM" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = "" + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "LwGSM" + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = "_build" + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = NO + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = YES + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = YES + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = NO + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = YES + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = "../lwgsm/" + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, +# *.vhdl, *.ucf, *.qsf, *.as and *.js. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.for \ + *.tcl \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf \ + *.as \ + *.js + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# compiled with the --with-libclang option. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = "" + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = "" + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = YES + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , / - - Source Files - Source Files\GSM API @@ -109,5 +106,11 @@ Source Files\GSM CORE + + Source Files + + + Source Files\GSM SNIPPETS + \ No newline at end of file diff --git a/examples/win32/call_rtos/gsm_config.h b/examples/win32/call_rtos/gsm_config.h deleted file mode 100644 index 8d66b547..00000000 --- a/examples/win32/call_rtos/gsm_config.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * \file gsm_config.h - * \brief Configuration file - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_CONFIG_H -#define GSM_HDR_CONFIG_H - -/* - * Rename this file to "gsm_config.h" for your application - */ - -/* First include debug before any config changes */ -#include "gsm/gsm_debug.h" - -/* - * Check default configuration settings for more information - */ -#define GSM_CFG_AT_ECHO 1 -#define GSM_CFG_SYS_PORT GSM_SYS_PORT_WIN32 -#define GSM_CFG_INPUT_USE_PROCESS 1 - -#define GSM_CFG_CALL 1 - -/* After user configuration, call default config to merge config together */ -#include "gsm/gsm_config_default.h" - -#endif /* GSM_HDR_CONFIG_H */ diff --git a/examples/win32/call_rtos/lwgsm_opts.h b/examples/win32/call_rtos/lwgsm_opts.h new file mode 100644 index 00000000..f46d0829 --- /dev/null +++ b/examples/win32/call_rtos/lwgsm_opts.h @@ -0,0 +1,48 @@ +/** + * \file lwgsm_opts.h + * \brief GSM application options + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_OPTS_H +#define LWGSM_HDR_OPTS_H + +/* Rename this file to "lwgsm_opts.h" for your application */ + +/* + * Open "include/lwgsm/lwgsm_opt.h" and + * copy & replace here settings you want to change values + */ +#define LWGSM_CFG_AT_ECHO 1 +#define LWGSM_CFG_INPUT_USE_PROCESS 1 + +#define LWGSM_CFG_CALL 1 + +#endif /* LWGSM_HDR_OPTS_H */ diff --git a/examples/win32/call_rtos/main.c b/examples/win32/call_rtos/main.c index 6555ade6..f8998103 100644 --- a/examples/win32/call_rtos/main.c +++ b/examples/win32/call_rtos/main.c @@ -4,38 +4,39 @@ */ /* - * Copyright (c) 2019 Tilen MAJERLE - * + * Copyright (c) 2020 Tilen MAJERLE + * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Before you start using WIN32 implementation with USB and VCP, - * check gsm_ll_win32.c implementation and choose your COM port! + * check lwgsm_ll_win32.c implementation and choose your COM port! */ -#include "gsm/gsm.h" +#include "lwgsm/lwgsm.h" #include "sim_manager.h" #include "network_utils.h" +#include "call.h" -static gsmr_t gsm_callback_func(gsm_evt_t* evt); +static lwgsmr_t lwgsm_callback_func(lwgsm_evt_t* evt); /** * \brief Program entry point @@ -45,32 +46,28 @@ main(void) { printf("Starting GSM application!\r\n"); /* Initialize GSM with default callback function */ - if (gsm_init(gsm_callback_func, 1) != gsmOK) { - printf("Cannot initialize GSM-AT Library\r\n"); + if (lwgsm_init(lwgsm_callback_func, 1) != lwgsmOK) { + printf("Cannot initialize LwGSM\r\n"); } /* Configure device by unlocking SIM card */ if (configure_sim_card()) { printf("SIM card configured. Adding delay to stabilize SIM card.\r\n"); - gsm_delay(10000); + lwgsm_delay(10000); } else { printf("Cannot configure SIM card! Is it inserted, pin valid and not under PUK? Closing down...\r\n"); - while (1) { gsm_delay(1000); } + while (1) { lwgsm_delay(1000); } } - /* Enable calls */ - if (gsm_call_enable(NULL, NULL, 1) == gsmOK) { - printf("Calls enabled. You may take your phone and call modem.\r\n"); - } else { - printf("Could not enabled call functionality!\r\n"); - } + /* Start call example */ + call_start(); /* * Do not stop program here. * New threads were created for GSM processing */ while (1) { - gsm_delay(1000); + lwgsm_delay(1000); } return 0; @@ -79,43 +76,22 @@ main(void) { /** * \brief Event callback function for GSM stack * \param[in] evt: Event information with data - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise */ -static gsmr_t -gsm_callback_func(gsm_evt_t* evt) { - switch (gsm_evt_get_type(evt)) { - case GSM_EVT_INIT_FINISH: printf("Library initialized!\r\n"); break; +static lwgsmr_t +lwgsm_callback_func(lwgsm_evt_t* evt) { + switch (lwgsm_evt_get_type(evt)) { + case LWGSM_EVT_INIT_FINISH: printf("Library initialized!\r\n"); break; /* Process and print registration change */ - case GSM_EVT_NETWORK_REG_CHANGED: network_utils_process_reg_change(evt); break; + case LWGSM_EVT_NETWORK_REG_CHANGED: network_utils_process_reg_change(evt); break; /* Process current network operator */ - case GSM_EVT_NETWORK_OPERATOR_CURRENT: network_utils_process_curr_operator(evt); break; + case LWGSM_EVT_NETWORK_OPERATOR_CURRENT: network_utils_process_curr_operator(evt); break; /* Process signal strength */ - case GSM_EVT_SIGNAL_STRENGTH: network_utils_process_rssi(evt); break; + case LWGSM_EVT_SIGNAL_STRENGTH: network_utils_process_rssi(evt); break; /* Other user events here... */ -#if GSM_CFG_CALL - case GSM_EVT_CALL_CHANGED: { - const gsm_call_t* call = gsm_evt_call_changed_get_call(evt); - if (call->state == GSM_CALL_STATE_ACTIVE) { - printf("Call is active!\r\n"); - - /* In case of mobile originated direction */ - if (call->dir == GSM_CALL_DIR_MO) { - gsm_call_hangup(NULL, NULL, 0); /* Manually hangup call */ - } - } else if (call->state == GSM_CALL_STATE_INCOMING) { - printf("We received incoming call! Phone number: %s\r\n", call->number); - gsm_call_answer(NULL, NULL, 0); /* Answer to a call */ - } else if (call->state == GSM_CALL_STATE_DIALING) { - printf("Call is dialing!\r\n"); - } else if (call->state == GSM_CALL_STATE_DISCONNECT) { - printf("Call ended!\r\n"); - } - break; - } -#endif /* GSM_CFG_CALL */ default: break; } - return gsmOK; + return lwgsmOK; } diff --git a/examples/win32/call_sms_rtos/call_sms_rtos.vcxproj b/examples/win32/call_sms_rtos/call_sms_rtos.vcxproj index 852ae6f1..ab08d50d 100644 --- a/examples/win32/call_sms_rtos/call_sms_rtos.vcxproj +++ b/examples/win32/call_sms_rtos/call_sms_rtos.vcxproj @@ -73,18 +73,18 @@ true - ..\..\..\GSM_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) - ..\..\..\ESP_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) true - ..\..\..\ESP_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) false - ..\..\..\ESP_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) false @@ -140,33 +140,34 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/win32/call_sms_rtos/call_sms_rtos.vcxproj.filters b/examples/win32/call_sms_rtos/call_sms_rtos.vcxproj.filters index f0dc5fee..d0a65c04 100644 --- a/examples/win32/call_sms_rtos/call_sms_rtos.vcxproj.filters +++ b/examples/win32/call_sms_rtos/call_sms_rtos.vcxproj.filters @@ -109,5 +109,8 @@ Source Files\GSM CORE + + Source Files\GSM SNIPPETS + \ No newline at end of file diff --git a/examples/win32/call_sms_rtos/gsm_config.h b/examples/win32/call_sms_rtos/gsm_config.h deleted file mode 100644 index 441ea47f..00000000 --- a/examples/win32/call_sms_rtos/gsm_config.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * \file gsm_config.h - * \brief Configuration file - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_CONFIG_H -#define GSM_HDR_CONFIG_H - -/* - * Rename this file to "gsm_config.h" for your application - */ - -/* First include debug before any config changes */ -#include "gsm/gsm_debug.h" - -/* - * Check default configuration settings for more information - */ -#define GSM_CFG_AT_ECHO 1 -#define GSM_CFG_SYS_PORT GSM_SYS_PORT_WIN32 -#define GSM_CFG_INPUT_USE_PROCESS 1 - -#define GSM_CFG_SMS 1 -#define GSM_CFG_CALL 1 - -/* After user configuration, call default config to merge config together */ -#include "gsm/gsm_config_default.h" - -#endif /* GSM_HDR_CONFIG_H */ diff --git a/examples/win32/call_sms_rtos/lwgsm_opts.h b/examples/win32/call_sms_rtos/lwgsm_opts.h new file mode 100644 index 00000000..8eb2bc30 --- /dev/null +++ b/examples/win32/call_sms_rtos/lwgsm_opts.h @@ -0,0 +1,49 @@ +/** + * \file lwgsm_opts.h + * \brief GSM application options + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_OPTS_H +#define LWGSM_HDR_OPTS_H + +/* Rename this file to "lwgsm_opts.h" for your application */ + +/* + * Open "include/lwgsm/lwgsm_opt.h" and + * copy & replace here settings you want to change values + */ +#define LWGSM_CFG_AT_ECHO 1 +#define LWGSM_CFG_INPUT_USE_PROCESS 1 + +#define LWGSM_CFG_SMS 1 +#define LWGSM_CFG_CALL 1 + +#endif /* LWGSM_HDR_OPTS_H */ diff --git a/examples/win32/call_sms_rtos/main.c b/examples/win32/call_sms_rtos/main.c index 5b40b347..227cd824 100644 --- a/examples/win32/call_sms_rtos/main.c +++ b/examples/win32/call_sms_rtos/main.c @@ -4,43 +4,44 @@ */ /* - * Copyright (c) 2019 Tilen MAJERLE - * + * Copyright (c) 2020 Tilen MAJERLE + * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Before you start using WIN32 implementation with USB and VCP, - * check gsm_ll_win32.c implementation and choose your COM port! + * check lwgsm_ll_win32.c implementation and choose your COM port! */ -#include "gsm/gsm.h" +#include "lwgsm/lwgsm.h" #include "sim_manager.h" #include "network_utils.h" +#include "call_sms.h" -static gsmr_t gsm_callback_func(gsm_evt_t* evt); +static lwgsmr_t lwgsm_callback_func(lwgsm_evt_t* evt); /** * \brief SMS entry */ -gsm_sms_entry_t +lwgsm_sms_entry_t sms_entry; /** @@ -51,39 +52,28 @@ main(void) { printf("Starting GSM application!\r\n"); /* Initialize GSM with default callback function */ - if (gsm_init(gsm_callback_func, 1) != gsmOK) { - printf("Cannot initialize GSM-AT Library\r\n"); + if (lwgsm_init(lwgsm_callback_func, 1) != lwgsmOK) { + printf("Cannot initialize LwGSM\r\n"); } /* Configure device by unlocking SIM card */ if (configure_sim_card()) { printf("SIM card configured. Adding delay to stabilize SIM card.\r\n"); - gsm_delay(10000); + lwgsm_delay(10000); } else { printf("Cannot configure SIM card! Is it inserted, pin valid and not under PUK? Closing down...\r\n"); - while (1) { gsm_delay(1000); } + while (1) { lwgsm_delay(1000); } } - /* First enable SMS functionality */ - if (gsm_sms_enable(NULL, NULL, 1) == gsmOK) { - printf("SMS enabled. Send new SMS from your phone to device.\r\n"); - } else { - printf("Cannot enable SMS functionality!\r\n"); - } - - /* Then enable call functionality */ - if (gsm_call_enable(NULL, NULL, 1) == gsmOK) { - printf("Call enabled. You may now take your phone and call modem\r\n"); - } else { - printf("Cannot enable call functionality!\r\n"); - } + /* Start call & SMS example */ + call_sms_start(); /* * Do not stop program here. * New threads were created for GSM processing */ while (1) { - gsm_delay(1000); + lwgsm_delay(1000); } return 0; @@ -92,82 +82,22 @@ main(void) { /** * \brief Event callback function for GSM stack * \param[in] evt: Event information with data - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise */ -static gsmr_t -gsm_callback_func(gsm_evt_t* evt) { - switch (gsm_evt_get_type(evt)) { - case GSM_EVT_INIT_FINISH: printf("Library initialized!\r\n"); break; +static lwgsmr_t +lwgsm_callback_func(lwgsm_evt_t* evt) { + switch (lwgsm_evt_get_type(evt)) { + case LWGSM_EVT_INIT_FINISH: printf("Library initialized!\r\n"); break; /* Process and print registration change */ - case GSM_EVT_NETWORK_REG_CHANGED: network_utils_process_reg_change(evt); break; + case LWGSM_EVT_NETWORK_REG_CHANGED: network_utils_process_reg_change(evt); break; /* Process current network operator */ - case GSM_EVT_NETWORK_OPERATOR_CURRENT: network_utils_process_curr_operator(evt); break; + case LWGSM_EVT_NETWORK_OPERATOR_CURRENT: network_utils_process_curr_operator(evt); break; /* Process signal strength */ - case GSM_EVT_SIGNAL_STRENGTH: network_utils_process_rssi(evt); break; + case LWGSM_EVT_SIGNAL_STRENGTH: network_utils_process_rssi(evt); break; /* Other user events here... */ - - case GSM_EVT_SMS_READY: { /* SMS is ready notification from device */ - printf("SIM device SMS service is ready!\r\n"); - break; - } - case GSM_EVT_SMS_RECV: { /* New SMS received indicator */ - gsmr_t res; - - printf("New SMS received!\r\n"); /* Notify user */ - - /* Try to read SMS */ - res = gsm_sms_read(gsm_evt_sms_recv_get_mem(evt), gsm_evt_sms_recv_get_pos(evt), &sms_entry, 1, NULL, NULL, 0); - if (res == gsmOK) { - printf("SMS read in progress!\r\n"); - } else { - printf("Cannot start SMS read procedure!\r\n"); - } - break; - } - case GSM_EVT_SMS_READ: { /* SMS read event */ - gsm_sms_entry_t* entry = gsm_evt_sms_read_get_entry(evt); - if (gsm_evt_sms_read_get_result(evt) == gsmOK && entry != NULL) { - /* Print SMS data */ - printf("SMS read. From: %s, content: %s\r\n", - entry->number, entry->data - ); - - /* Try to send SMS back */ - if (gsm_sms_send(entry->number, entry->data, NULL, NULL, 0) == gsmOK) { - printf("SMS send in progress!\r\n"); - } else { - printf("Cannot start SMS send procedure!\r\n"); - } - - /* Delete SMS from device memory */ - gsm_sms_delete(entry->mem, entry->pos, NULL, NULL, 0); - } - break; - } - case GSM_EVT_SMS_SEND: { /* SMS send event */ - if (gsm_evt_sms_send_get_result(evt) == gsmOK) { - printf("SMS has been successfully sent!\r\n"); - } else { - printf("SMS has not been sent successfully!\r\n"); - } - break; - } - - case GSM_EVT_CALL_READY: { /* Call is ready notification from device */ - printf("SIM device Call service is ready!\r\n"); - break; - } - case GSM_EVT_CALL_CHANGED: { - const gsm_call_t* call = gsm_evt_call_changed_get_call(evt); - if (call->state == GSM_CALL_STATE_INCOMING) { /* On incoming call */ - gsm_call_hangup(NULL, NULL, 0); /* Hangup call */ - gsm_sms_send(call->number, "Cannot answer call. Please send SMS\r\n", NULL, NULL, 0); - } - break; - } default: break; } - return gsmOK; + return lwgsmOK; } diff --git a/examples/win32/device_info_rtos/device_info_rtos.vcxproj b/examples/win32/device_info_rtos/device_info_rtos.vcxproj index b66891e5..23c98ba5 100644 --- a/examples/win32/device_info_rtos/device_info_rtos.vcxproj +++ b/examples/win32/device_info_rtos/device_info_rtos.vcxproj @@ -73,18 +73,18 @@ true - ..\..\..\GSM_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) - ..\..\..\ESP_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) true - ..\..\..\ESP_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) false - ..\..\..\ESP_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) false @@ -140,33 +140,34 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/win32/device_info_rtos/device_info_rtos.vcxproj.filters b/examples/win32/device_info_rtos/device_info_rtos.vcxproj.filters index f0dc5fee..f4e7cdbd 100644 --- a/examples/win32/device_info_rtos/device_info_rtos.vcxproj.filters +++ b/examples/win32/device_info_rtos/device_info_rtos.vcxproj.filters @@ -109,5 +109,8 @@ Source Files\GSM CORE + + Source Files\GSM SNIPPETS + \ No newline at end of file diff --git a/examples/win32/device_info_rtos/gsm_config.h b/examples/win32/device_info_rtos/gsm_config.h deleted file mode 100644 index a1b7ac9f..00000000 --- a/examples/win32/device_info_rtos/gsm_config.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * \file gsm_config.h - * \brief Configuration file - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_CONFIG_H -#define GSM_HDR_CONFIG_H - -/* - * Rename this file to "gsm_config.h" for your application - */ - -/* First include debug before any config changes */ -#include "gsm/gsm_debug.h" - -/* - * Check default configuration settings for more information - */ -#define GSM_CFG_AT_ECHO 1 -#define GSM_CFG_SYS_PORT GSM_SYS_PORT_WIN32 -#define GSM_CFG_INPUT_USE_PROCESS 1 - -/* Enable SMS API */ -#define GSM_CFG_SMS 1 - -/* After user configuration, call default config to merge config together */ -#include "gsm/gsm_config_default.h" - -#endif /* GSM_HDR_CONFIG_H */ diff --git a/examples/win32/device_info_rtos/lwgsm_opts.h b/examples/win32/device_info_rtos/lwgsm_opts.h new file mode 100644 index 00000000..d2a82e98 --- /dev/null +++ b/examples/win32/device_info_rtos/lwgsm_opts.h @@ -0,0 +1,49 @@ +/** + * \file lwgsm_opts.h + * \brief GSM application options + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_OPTS_H +#define LWGSM_HDR_OPTS_H + +/* Rename this file to "lwgsm_opts.h" for your application */ + +/* + * Open "include/lwgsm/lwgsm_opt.h" and + * copy & replace here settings you want to change values + */ +#define LWGSM_CFG_AT_ECHO 1 +#define LWGSM_CFG_INPUT_USE_PROCESS 1 + +/* Enable SMS API */ +#define LWGSM_CFG_SMS 1 + +#endif /* LWGSM_HDR_OPTS_H */ diff --git a/examples/win32/device_info_rtos/main.c b/examples/win32/device_info_rtos/main.c index 621cff67..3276e3ac 100644 --- a/examples/win32/device_info_rtos/main.c +++ b/examples/win32/device_info_rtos/main.c @@ -4,41 +4,39 @@ */ /* - * Copyright (c) 2019 Tilen MAJERLE - * + * Copyright (c) 2020 Tilen MAJERLE + * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Before you start using WIN32 implementation with USB and VCP, - * check gsm_ll_win32.c implementation and choose your COM port! + * check lwgsm_ll_win32.c implementation and choose your COM port! */ -#include "gsm/gsm.h" +#include "lwgsm/lwgsm.h" #include "sim_manager.h" #include "network_utils.h" +#include "device_info.h" -static gsmr_t gsm_callback_func(gsm_evt_t* evt); - -/* Device info string array */ -char dev_str[20]; +static lwgsmr_t lwgsm_callback_func(lwgsm_evt_t* evt); /** * \brief Program entry point @@ -48,34 +46,19 @@ main(void) { printf("Starting GSM application!\r\n"); /* Initialize GSM with default callback function */ - if (gsm_init(gsm_callback_func, 1) != gsmOK) { - printf("Cannot initialize GSM-AT Library\r\n"); + if (lwgsm_init(lwgsm_callback_func, 1) != lwgsmOK) { + printf("Cannot initialize LwGSM\r\n"); } - /* Read information */ - - /* Read device manufacturer */ - gsm_device_get_manufacturer(dev_str, sizeof(dev_str), NULL, NULL, 1); - printf("Manuf: %s\r\n", dev_str); - - /* Read device model */ - gsm_device_get_model(dev_str, sizeof(dev_str), NULL, NULL, 1); - printf("Model: %s\r\n", dev_str); - - /* Read device serial number */ - gsm_device_get_serial_number(dev_str, sizeof(dev_str), NULL, NULL, 1); - printf("Serial: %s\r\n", dev_str); - - /* Read device revision */ - gsm_device_get_revision(dev_str, sizeof(dev_str), NULL, NULL, 1); - printf("Revision: %s\r\n", dev_str); + /* Read device info */ + read_device_info(); /* * Do not stop program here. * New threads were created for GSM processing */ while (1) { - gsm_delay(1000); + lwgsm_delay(1000); } return 0; @@ -84,23 +67,23 @@ main(void) { /** * \brief Event callback function for GSM stack * \param[in] evt: Event information with data - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise */ -static gsmr_t -gsm_callback_func(gsm_evt_t* evt) { - switch (gsm_evt_get_type(evt)) { - case GSM_EVT_INIT_FINISH: printf("Library initialized!\r\n"); break; +static lwgsmr_t +lwgsm_callback_func(lwgsm_evt_t* evt) { + switch (lwgsm_evt_get_type(evt)) { + case LWGSM_EVT_INIT_FINISH: printf("Library initialized!\r\n"); break; /* Process and print registration change */ - case GSM_EVT_NETWORK_REG_CHANGED: network_utils_process_reg_change(evt); break; + case LWGSM_EVT_NETWORK_REG_CHANGED: network_utils_process_reg_change(evt); break; /* Process current network operator */ - case GSM_EVT_NETWORK_OPERATOR_CURRENT: network_utils_process_curr_operator(evt); break; + case LWGSM_EVT_NETWORK_OPERATOR_CURRENT: network_utils_process_curr_operator(evt); break; /* Process signal strength */ - case GSM_EVT_SIGNAL_STRENGTH: network_utils_process_rssi(evt); break; + case LWGSM_EVT_SIGNAL_STRENGTH: network_utils_process_rssi(evt); break; /* Other user events here... */ default: break; } - return gsmOK; + return lwgsmOK; } diff --git a/examples/win32/gsm_examples.sln b/examples/win32/lwgsm_examples.sln similarity index 100% rename from examples/win32/gsm_examples.sln rename to examples/win32/lwgsm_examples.sln diff --git a/examples/win32/mqtt_client_api_rtos/gsm_config.h b/examples/win32/mqtt_client_api_rtos/gsm_config.h deleted file mode 100644 index 19afce73..00000000 --- a/examples/win32/mqtt_client_api_rtos/gsm_config.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * \file gsm_config.h - * \brief Configuration file - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_CONFIG_H -#define GSM_HDR_CONFIG_H - -/* - * Rename this file to "gsm_config.h" for your application - */ - -/* First include debug before any config changes */ -#include "gsm/gsm_debug.h" - -/* - * Check default configuration settings for more information - */ -#define GSM_CFG_AT_ECHO 1 -#define GSM_CFG_SYS_PORT GSM_SYS_PORT_WIN32 -#define GSM_CFG_INPUT_USE_PROCESS 1 - -/* Enable network, conn and netconn APIs */ -#define GSM_CFG_NETWORK 1 -#define GSM_CFG_CONN 1 -#define GSM_CFG_NETCONN 1 - -/* After user configuration, call default config to merge config together */ -#include "gsm/gsm_config_default.h" - -#endif /* GSM_HDR_CONFIG_H */ diff --git a/examples/win32/mqtt_client_api_rtos/lwgsm_opts.h b/examples/win32/mqtt_client_api_rtos/lwgsm_opts.h new file mode 100644 index 00000000..c1a64fe2 --- /dev/null +++ b/examples/win32/mqtt_client_api_rtos/lwgsm_opts.h @@ -0,0 +1,51 @@ +/** + * \file lwgsm_opts.h + * \brief GSM application options + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_OPTS_H +#define LWGSM_HDR_OPTS_H + +/* Rename this file to "lwgsm_opts.h" for your application */ + +/* + * Open "include/lwgsm/lwgsm_opt.h" and + * copy & replace here settings you want to change values + */ +#define LWGSM_CFG_AT_ECHO 1 +#define LWGSM_CFG_INPUT_USE_PROCESS 1 + +/* Enable network, conn and netconn APIs */ +#define LWGSM_CFG_NETWORK 1 +#define LWGSM_CFG_CONN 1 +#define LWGSM_CFG_NETCONN 1 + +#endif /* LWGSM_HDR_OPTS_H */ diff --git a/examples/win32/mqtt_client_api_rtos/main.c b/examples/win32/mqtt_client_api_rtos/main.c index b35ca48b..f180a4f2 100644 --- a/examples/win32/mqtt_client_api_rtos/main.c +++ b/examples/win32/mqtt_client_api_rtos/main.c @@ -4,40 +4,40 @@ */ /* - * Copyright (c) 2019 Tilen MAJERLE - * + * Copyright (c) 2020 Tilen MAJERLE + * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Before you start using WIN32 implementation with USB and VCP, - * check gsm_ll_win32.c implementation and choose your COM port! + * check lwgsm_ll_win32.c implementation and choose your COM port! */ -#include "gsm/gsm.h" +#include "lwgsm/lwgsm.h" #include "sim_manager.h" #include "network_utils.h" #include "network_apn_settings.h" #include "mqtt_client_api.h" -static gsmr_t gsm_callback_func(gsm_evt_t* evt); +static lwgsmr_t lwgsm_callback_func(lwgsm_evt_t* evt); /** * \brief Program entry point @@ -47,35 +47,31 @@ main(void) { printf("Starting GSM application!\r\n"); /* Initialize GSM with default callback function */ - if (gsm_init(gsm_callback_func, 1) != gsmOK) { - printf("Cannot initialize GSM-AT Library\r\n"); + if (lwgsm_init(lwgsm_callback_func, 1) != lwgsmOK) { + printf("Cannot initialize LwGSM\r\n"); } /* Configure device by unlocking SIM card */ if (configure_sim_card()) { printf("SIM card configured. Adding delay to stabilize SIM card.\r\n"); - gsm_delay(10000); + lwgsm_delay(10000); } else { printf("Cannot configure SIM card! Is it inserted, pin valid and not under PUK? Closing down...\r\n"); - while (1) { gsm_delay(1000); } + while (1) { lwgsm_delay(1000); } } - /* Connect to network for TCP/IP */ - if (gsm_network_attach(NETWORK_APN, NETWORK_APN_USER, NETWORK_APN_PASS, NULL, NULL, 1) == gsmOK) { - printf("Attached to network!\r\n"); + /* Set APN credentials */ + lwgsm_network_set_credentials(NETWORK_APN, NETWORK_APN_USER, NETWORK_APN_PASS); - /* Start netconn thread */ - gsm_sys_thread_create(NULL, "mqtt_thread", (gsm_sys_thread_t)mqtt_client_api_thread, NULL, GSM_SYS_THREAD_SS, GSM_SYS_THREAD_PRIO); - } else { - printf("Cannot attach to network!\r\n"); - } + /* Start MQTT thread */ + lwgsm_sys_thread_create(NULL, "mqtt_thread", (lwgsm_sys_thread_t)mqtt_client_api_thread, NULL, LWGSM_SYS_THREAD_SS, LWGSM_SYS_THREAD_PRIO); /* * Do not stop program here. * New threads were created for GSM processing */ while (1) { - gsm_delay(1000); + lwgsm_delay(1000); } return 0; @@ -84,22 +80,22 @@ main(void) { /** * \brief Event callback function for GSM stack * \param[in] evt: Event information with data - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise */ -static gsmr_t -gsm_callback_func(gsm_evt_t* evt) { - switch (gsm_evt_get_type(evt)) { - case GSM_EVT_INIT_FINISH: printf("Library initialized!\r\n"); break; +static lwgsmr_t +lwgsm_callback_func(lwgsm_evt_t* evt) { + switch (lwgsm_evt_get_type(evt)) { + case LWGSM_EVT_INIT_FINISH: printf("Library initialized!\r\n"); break; /* Process and print registration change */ - case GSM_EVT_NETWORK_REG_CHANGED: network_utils_process_reg_change(evt); break; + case LWGSM_EVT_NETWORK_REG_CHANGED: network_utils_process_reg_change(evt); break; /* Process current network operator */ - case GSM_EVT_NETWORK_OPERATOR_CURRENT: network_utils_process_curr_operator(evt); break; + case LWGSM_EVT_NETWORK_OPERATOR_CURRENT: network_utils_process_curr_operator(evt); break; /* Process signal strength */ - case GSM_EVT_SIGNAL_STRENGTH: network_utils_process_rssi(evt); break; + case LWGSM_EVT_SIGNAL_STRENGTH: network_utils_process_rssi(evt); break; /* Other user events here... */ default: break; } - return gsmOK; + return lwgsmOK; } diff --git a/examples/win32/mqtt_client_api_rtos/mqtt_client_api_rtos.vcxproj b/examples/win32/mqtt_client_api_rtos/mqtt_client_api_rtos.vcxproj index ff0792b4..444315e2 100644 --- a/examples/win32/mqtt_client_api_rtos/mqtt_client_api_rtos.vcxproj +++ b/examples/win32/mqtt_client_api_rtos/mqtt_client_api_rtos.vcxproj @@ -73,18 +73,18 @@ true - ..\..\..\GSM_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) - ..\..\..\ESP_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) true - ..\..\..\ESP_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) false - ..\..\..\ESP_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) false @@ -140,37 +140,37 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/win32/netconn_client_rtos/gsm_config.h b/examples/win32/netconn_client_rtos/gsm_config.h deleted file mode 100644 index 19afce73..00000000 --- a/examples/win32/netconn_client_rtos/gsm_config.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * \file gsm_config.h - * \brief Configuration file - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_CONFIG_H -#define GSM_HDR_CONFIG_H - -/* - * Rename this file to "gsm_config.h" for your application - */ - -/* First include debug before any config changes */ -#include "gsm/gsm_debug.h" - -/* - * Check default configuration settings for more information - */ -#define GSM_CFG_AT_ECHO 1 -#define GSM_CFG_SYS_PORT GSM_SYS_PORT_WIN32 -#define GSM_CFG_INPUT_USE_PROCESS 1 - -/* Enable network, conn and netconn APIs */ -#define GSM_CFG_NETWORK 1 -#define GSM_CFG_CONN 1 -#define GSM_CFG_NETCONN 1 - -/* After user configuration, call default config to merge config together */ -#include "gsm/gsm_config_default.h" - -#endif /* GSM_HDR_CONFIG_H */ diff --git a/examples/win32/netconn_client_rtos/lwgsm_opts.h b/examples/win32/netconn_client_rtos/lwgsm_opts.h new file mode 100644 index 00000000..c1a64fe2 --- /dev/null +++ b/examples/win32/netconn_client_rtos/lwgsm_opts.h @@ -0,0 +1,51 @@ +/** + * \file lwgsm_opts.h + * \brief GSM application options + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_OPTS_H +#define LWGSM_HDR_OPTS_H + +/* Rename this file to "lwgsm_opts.h" for your application */ + +/* + * Open "include/lwgsm/lwgsm_opt.h" and + * copy & replace here settings you want to change values + */ +#define LWGSM_CFG_AT_ECHO 1 +#define LWGSM_CFG_INPUT_USE_PROCESS 1 + +/* Enable network, conn and netconn APIs */ +#define LWGSM_CFG_NETWORK 1 +#define LWGSM_CFG_CONN 1 +#define LWGSM_CFG_NETCONN 1 + +#endif /* LWGSM_HDR_OPTS_H */ diff --git a/examples/win32/netconn_client_rtos/main.c b/examples/win32/netconn_client_rtos/main.c index 873003a4..5529e173 100644 --- a/examples/win32/netconn_client_rtos/main.c +++ b/examples/win32/netconn_client_rtos/main.c @@ -4,40 +4,40 @@ */ /* - * Copyright (c) 2019 Tilen MAJERLE - * + * Copyright (c) 2020 Tilen MAJERLE + * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Before you start using WIN32 implementation with USB and VCP, - * check gsm_ll_win32.c implementation and choose your COM port! + * check lwgsm_ll_win32.c implementation and choose your COM port! */ -#include "gsm/gsm.h" +#include "lwgsm/lwgsm.h" #include "sim_manager.h" #include "network_utils.h" #include "netconn_client.h" #include "network_apn_settings.h" -static gsmr_t gsm_callback_func(gsm_evt_t* evt); +static lwgsmr_t lwgsm_callback_func(lwgsm_evt_t* evt); /** * \brief Program entry point @@ -47,35 +47,31 @@ main(void) { printf("Starting GSM application!\r\n"); /* Initialize GSM with default callback function */ - if (gsm_init(gsm_callback_func, 1) != gsmOK) { - printf("Cannot initialize GSM-AT Library\r\n"); + if (lwgsm_init(lwgsm_callback_func, 1) != lwgsmOK) { + printf("Cannot initialize LwGSM\r\n"); } /* Configure device by unlocking SIM card */ if (configure_sim_card()) { printf("SIM card configured. Adding delay to stabilize SIM card.\r\n"); - gsm_delay(10000); + lwgsm_delay(10000); } else { printf("Cannot configure SIM card! Is it inserted, pin valid and not under PUK? Closing down...\r\n"); - while (1) { gsm_delay(1000); } + while (1) { lwgsm_delay(1000); } } - /* Connect to network for TCP/IP */ - if (gsm_network_attach(NETWORK_APN, NETWORK_APN_USER, NETWORK_APN_PASS, NULL, NULL, 1) == gsmOK) { - printf("Attached to network!\r\n"); + /* Set APN credentials */ + lwgsm_network_set_credentials(NETWORK_APN, NETWORK_APN_USER, NETWORK_APN_PASS); - /* Start netconn thread */ - gsm_sys_thread_create(NULL, "netconn_thread", (gsm_sys_thread_t)netconn_client_thread, NULL, GSM_SYS_THREAD_SS, GSM_SYS_THREAD_PRIO); - } else { - printf("Cannot attach to network!\r\n"); - } + /* Start netconn thread */ + lwgsm_sys_thread_create(NULL, "netconn_thread", (lwgsm_sys_thread_t)netconn_client_thread, NULL, LWGSM_SYS_THREAD_SS, LWGSM_SYS_THREAD_PRIO); /* * Do not stop program here. * New threads were created for GSM processing */ while (1) { - gsm_delay(1000); + lwgsm_delay(1000); } return 0; @@ -84,22 +80,22 @@ main(void) { /** * \brief Event callback function for GSM stack * \param[in] evt: Event information with data - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise */ -static gsmr_t -gsm_callback_func(gsm_evt_t* evt) { - switch (gsm_evt_get_type(evt)) { - case GSM_EVT_INIT_FINISH: printf("Library initialized!\r\n"); break; +static lwgsmr_t +lwgsm_callback_func(lwgsm_evt_t* evt) { + switch (lwgsm_evt_get_type(evt)) { + case LWGSM_EVT_INIT_FINISH: printf("Library initialized!\r\n"); break; /* Process and print registration change */ - case GSM_EVT_NETWORK_REG_CHANGED: network_utils_process_reg_change(evt); break; + case LWGSM_EVT_NETWORK_REG_CHANGED: network_utils_process_reg_change(evt); break; /* Process current network operator */ - case GSM_EVT_NETWORK_OPERATOR_CURRENT: network_utils_process_curr_operator(evt); break; + case LWGSM_EVT_NETWORK_OPERATOR_CURRENT: network_utils_process_curr_operator(evt); break; /* Process signal strength */ - case GSM_EVT_SIGNAL_STRENGTH: network_utils_process_rssi(evt); break; + case LWGSM_EVT_SIGNAL_STRENGTH: network_utils_process_rssi(evt); break; /* Other user events here... */ default: break; } - return gsmOK; + return lwgsmOK; } diff --git a/examples/win32/netconn_client_rtos/netconn_client_rtos.vcxproj b/examples/win32/netconn_client_rtos/netconn_client_rtos.vcxproj index af18f75a..21cbe55c 100644 --- a/examples/win32/netconn_client_rtos/netconn_client_rtos.vcxproj +++ b/examples/win32/netconn_client_rtos/netconn_client_rtos.vcxproj @@ -73,18 +73,18 @@ true - ..\..\..\GSM_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) - ..\..\..\ESP_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) true - ..\..\..\ESP_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) false - ..\..\..\ESP_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) false @@ -140,34 +140,34 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/win32/sms_send_receive_rtos/gsm_config.h b/examples/win32/sms_send_receive_rtos/gsm_config.h deleted file mode 100644 index a1b7ac9f..00000000 --- a/examples/win32/sms_send_receive_rtos/gsm_config.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * \file gsm_config.h - * \brief Configuration file - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_CONFIG_H -#define GSM_HDR_CONFIG_H - -/* - * Rename this file to "gsm_config.h" for your application - */ - -/* First include debug before any config changes */ -#include "gsm/gsm_debug.h" - -/* - * Check default configuration settings for more information - */ -#define GSM_CFG_AT_ECHO 1 -#define GSM_CFG_SYS_PORT GSM_SYS_PORT_WIN32 -#define GSM_CFG_INPUT_USE_PROCESS 1 - -/* Enable SMS API */ -#define GSM_CFG_SMS 1 - -/* After user configuration, call default config to merge config together */ -#include "gsm/gsm_config_default.h" - -#endif /* GSM_HDR_CONFIG_H */ diff --git a/examples/win32/sms_send_receive_rtos/lwgsm_opts.h b/examples/win32/sms_send_receive_rtos/lwgsm_opts.h new file mode 100644 index 00000000..d2a82e98 --- /dev/null +++ b/examples/win32/sms_send_receive_rtos/lwgsm_opts.h @@ -0,0 +1,49 @@ +/** + * \file lwgsm_opts.h + * \brief GSM application options + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_OPTS_H +#define LWGSM_HDR_OPTS_H + +/* Rename this file to "lwgsm_opts.h" for your application */ + +/* + * Open "include/lwgsm/lwgsm_opt.h" and + * copy & replace here settings you want to change values + */ +#define LWGSM_CFG_AT_ECHO 1 +#define LWGSM_CFG_INPUT_USE_PROCESS 1 + +/* Enable SMS API */ +#define LWGSM_CFG_SMS 1 + +#endif /* LWGSM_HDR_OPTS_H */ diff --git a/examples/win32/sms_send_receive_rtos/main.c b/examples/win32/sms_send_receive_rtos/main.c index 220b93f7..7078eaab 100644 --- a/examples/win32/sms_send_receive_rtos/main.c +++ b/examples/win32/sms_send_receive_rtos/main.c @@ -4,44 +4,39 @@ */ /* - * Copyright (c) 2019 Tilen MAJERLE - * + * Copyright (c) 2020 Tilen MAJERLE + * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Before you start using WIN32 implementation with USB and VCP, - * check gsm_ll_win32.c implementation and choose your COM port! + * check lwgsm_ll_win32.c implementation and choose your COM port! */ -#include "gsm/gsm.h" +#include "lwgsm/lwgsm.h" #include "sim_manager.h" #include "network_utils.h" +#include "sms_send_receive.h" -static gsmr_t gsm_callback_func(gsm_evt_t* evt); - -/** - * \brief SMS entry - */ -gsm_sms_entry_t -sms_entry; +static lwgsmr_t lwgsm_callback_func(lwgsm_evt_t* evt); /** * \brief Program entry point @@ -51,37 +46,28 @@ main(void) { printf("Starting GSM application!\r\n"); /* Initialize GSM with default callback function */ - if (gsm_init(gsm_callback_func, 1) != gsmOK) { - printf("Cannot initialize GSM-AT Library\r\n"); + if (lwgsm_init(lwgsm_callback_func, 1) != lwgsmOK) { + printf("Cannot initialize LwGSM\r\n"); } /* Configure device by unlocking SIM card */ if (configure_sim_card()) { printf("SIM card configured. Adding delay to stabilize SIM card.\r\n"); - gsm_delay(10000); + lwgsm_delay(10000); } else { printf("Cannot configure SIM card! Is it inserted, pin valid and not under PUK? Closing down...\r\n"); - while (1) { gsm_delay(1000); } - } - -#if GSM_CFG_SMS - /* First enable SMS functionality */ - if (gsm_sms_enable(NULL, NULL, 1) == gsmOK) { - printf("SMS enabled. Send new SMS from your phone to device.\r\n"); - } else { - printf("Cannot enable SMS functionality!\r\n"); + while (1) { lwgsm_delay(1000); } } - /* Now send SMS from phone to device */ - printf("Start by sending SMS message to device...\r\n"); -#endif /* GSM_CFG_SMS */ + /* Start SMS send receive example */ + sms_send_receive_start(); /* * Do not stop program here. * New threads were created for GSM processing */ while (1) { - gsm_delay(1000); + lwgsm_delay(1000); } return 0; @@ -90,79 +76,22 @@ main(void) { /** * \brief Event callback function for GSM stack * \param[in] evt: Event information with data - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise */ -static gsmr_t -gsm_callback_func(gsm_evt_t* evt) { - switch (gsm_evt_get_type(evt)) { - case GSM_EVT_INIT_FINISH: printf("Library initialized!\r\n"); break; +static lwgsmr_t +lwgsm_callback_func(lwgsm_evt_t* evt) { + switch (lwgsm_evt_get_type(evt)) { + case LWGSM_EVT_INIT_FINISH: printf("Library initialized!\r\n"); break; /* Process and print registration change */ - case GSM_EVT_NETWORK_REG_CHANGED: network_utils_process_reg_change(evt); break; + case LWGSM_EVT_NETWORK_REG_CHANGED: network_utils_process_reg_change(evt); break; /* Process current network operator */ - case GSM_EVT_NETWORK_OPERATOR_CURRENT: network_utils_process_curr_operator(evt); break; + case LWGSM_EVT_NETWORK_OPERATOR_CURRENT: network_utils_process_curr_operator(evt); break; /* Process signal strength */ - case GSM_EVT_SIGNAL_STRENGTH: network_utils_process_rssi(evt); break; + case LWGSM_EVT_SIGNAL_STRENGTH: network_utils_process_rssi(evt); break; /* Other user events here... */ -#if GSM_CFG_SMS - case GSM_EVT_SMS_READY: { /* SMS is ready notification from device */ - printf("SIM device SMS service is ready!\r\n"); - break; - } - case GSM_EVT_SMS_RECV: { /* New SMS received indicator */ - gsmr_t res; - - printf("New SMS received!\r\n"); /* Notify user */ - - /* Try to read SMS */ - res = gsm_sms_read(gsm_evt_sms_recv_get_mem(evt), gsm_evt_sms_recv_get_pos(evt), &sms_entry, 1, NULL, NULL, 0); - if (res == gsmOK) { - printf("SMS read in progress!\r\n"); - } else { - printf("Cannot start SMS read procedure!\r\n"); - } - break; - } - case GSM_EVT_SMS_READ: { /* SMS read event */ - gsm_sms_entry_t* entry = gsm_evt_sms_read_get_entry(evt); - if (gsm_evt_sms_read_get_result(evt) == gsmOK && entry != NULL) { - /* Print SMS data */ - printf("SMS read. From: %s, content: %s\r\n", - entry->number, entry->data - ); - - /* Try to send SMS back */ - if (gsm_sms_send(entry->number, entry->data, NULL, NULL, 0) == gsmOK) { - printf("SMS send in progress!\r\n"); - } else { - printf("Cannot start SMS send procedure!\r\n"); - } - - /* Delete SMS from device memory */ - gsm_sms_delete(entry->mem, entry->pos, NULL, NULL, 0); - } - break; - } - case GSM_EVT_SMS_SEND: { /* SMS send event */ - if (gsm_evt_sms_send_get_result(evt) == gsmOK) { - printf("SMS has been successfully sent!\r\n"); - } else { - printf("SMS has not been sent successfully!\r\n"); - } - break; - } - case GSM_EVT_SMS_DELETE: { - if (gsm_evt_sms_delete_get_result(evt) == gsmOK) { - printf("SMS deleted, memory position: %d\r\n", (int)gsm_evt_sms_delete_get_pos(evt)); - } else { - printf("SMS delete operation failed!\r\n"); - } - break; - } -#endif /* GSM_CFG_SMS */ - default: break; } - return gsmOK; + return lwgsmOK; } diff --git a/examples/win32/sms_send_receive_rtos/sms_send_receive_rtos.vcxproj b/examples/win32/sms_send_receive_rtos/sms_send_receive_rtos.vcxproj index d7e1a2df..0eef6d7e 100644 --- a/examples/win32/sms_send_receive_rtos/sms_send_receive_rtos.vcxproj +++ b/examples/win32/sms_send_receive_rtos/sms_send_receive_rtos.vcxproj @@ -73,18 +73,18 @@ true - ..\..\..\GSM_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) - ..\..\..\ESP_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) true - ..\..\..\ESP_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) false - ..\..\..\ESP_AT_Lib\src\include;.;..\..\..\snippets\include;$(IncludePath) + .;..\..\..\lwgsm\src\include;..\..\..\lwgsm\src\include\system\port\win32;..\..\..\snippets\include;$(IncludePath) false @@ -140,35 +140,36 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/win32/sms_send_receive_rtos/sms_send_receive_rtos.vcxproj.filters b/examples/win32/sms_send_receive_rtos/sms_send_receive_rtos.vcxproj.filters index f0dc5fee..44fede1f 100644 --- a/examples/win32/sms_send_receive_rtos/sms_send_receive_rtos.vcxproj.filters +++ b/examples/win32/sms_send_receive_rtos/sms_send_receive_rtos.vcxproj.filters @@ -109,5 +109,8 @@ Source Files\GSM CORE + + Source Files\GSM SNIPPETS + \ No newline at end of file diff --git a/gsm_at_lib/src/apps/mqtt/gsm_mqtt_client_api.c b/gsm_at_lib/src/apps/mqtt/gsm_mqtt_client_api.c deleted file mode 100644 index adde5f6f..00000000 --- a/gsm_at_lib/src/apps/mqtt/gsm_mqtt_client_api.c +++ /dev/null @@ -1,523 +0,0 @@ -/** - * \file gsm_mqtt_client_api.c - * \brief MQTT client API - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#include "gsm/apps/gsm_mqtt_client_api.h" -#include "gsm/gsm_mem.h" - -/* Tracing debug message */ -#define GSM_CFG_DBG_MQTT_API_TRACE (GSM_CFG_DBG_MQTT_API | GSM_DBG_TYPE_TRACE) -#define GSM_CFG_DBG_MQTT_API_STATE (GSM_CFG_DBG_MQTT_API | GSM_DBG_TYPE_STATE) -#define GSM_CFG_DBG_MQTT_API_TRACE_WARNING (GSM_CFG_DBG_MQTT_API | GSM_DBG_TYPE_TRACE | GSM_DBG_LVL_WARNING) -#define GSM_CFG_DBG_MQTT_API_TRACE_SEVERE (GSM_CFG_DBG_MQTT_API | GSM_DBG_TYPE_TRACE | GSM_DBG_LVL_SEVERE) - -/** - * \brief MQTT API client structure - */ -struct gsm_mqtt_client_api { - gsm_mqtt_client_p mc; /*!< MQTT client handle */ - gsm_sys_mbox_t rcv_mbox; /*!< Received data mbox */ - gsm_sys_sem_t sync_sem; /*!< Synchronization semaphore */ - gsm_sys_mutex_t mutex; /*!< Mutex handle */ - uint8_t release_sem; /*!< Set to `1` to release semaphore */ - gsm_mqtt_conn_status_t connect_resp; /*!< Response when connecting to server */ - gsmr_t sub_pub_resp; /*!< Subscribe/Unsubscribe/Publish response */ -} gsm_mqtt_client_api_t; - -/** - * \brief Variable used as pointer for message queue when MQTT connection is closed - */ -static uint8_t -mqtt_closed = 0xFF; - -/** - * \brief Release user semaphore - * \param[in] client: Client handle - */ -static void -release_sem(gsm_mqtt_client_api_p client) { - if (client->release_sem) { - client->release_sem = 0; - gsm_sys_sem_release(&client->sync_sem); - } -} - -/** - * \brief MQTT event callback function - */ -static void -mqtt_evt(gsm_mqtt_client_p client, gsm_mqtt_evt_t* evt) { - gsm_mqtt_client_api_p api_client = gsm_mqtt_client_get_arg(client); - if (api_client == NULL) { - return; - } - switch (gsm_mqtt_client_evt_get_type(client, evt)) { - case GSM_MQTT_EVT_CONNECT: { - gsm_mqtt_conn_status_t status = gsm_mqtt_client_evt_connect_get_status(client, evt); - - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API_TRACE, - "[MQTT API] Connect event with status: %d\r\n", (int)status); - - api_client->connect_resp = status; - - /* - * By MQTT 3.1.1 specification, broker must close connection - * if client CONNECT packet was not accepted. - * - * If client is accepted or connection did not even start, - * release semaphore, otherwise wait CLOSED event - * and release semaphore from there, - * to make sure we are fully ready for next connection - */ - if (status == GSM_MQTT_CONN_STATUS_TCP_FAILED - || status == GSM_MQTT_CONN_STATUS_ACCEPTED) { - release_sem(api_client); /* Release semaphore */ - } - - break; - } - case GSM_MQTT_EVT_PUBLISH_RECV: { - /* Check valid receive mbox */ - if (gsm_sys_mbox_isvalid(&api_client->rcv_mbox)) { - gsm_mqtt_client_api_buf_p buf; - size_t size, buf_size, topic_size, payload_size; - - /* Get event data */ - const char* topic = gsm_mqtt_client_evt_publish_recv_get_topic(client, evt); - size_t topic_len = gsm_mqtt_client_evt_publish_recv_get_topic_len(client, evt); - const uint8_t* payload = gsm_mqtt_client_evt_publish_recv_get_payload(client, evt); - size_t payload_len = gsm_mqtt_client_evt_publish_recv_get_payload_len(client, evt); - gsm_mqtt_qos_t qos = gsm_mqtt_client_evt_publish_recv_get_qos(client, evt); - - /* Print debug message */ - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API_TRACE, - "[MQTT API] New publish received on topic %.*s\r\n", (int)topic_len, topic); - - /* Calculate memory sizes */ - buf_size = GSM_MEM_ALIGN(sizeof(*buf)); - topic_size = GSM_MEM_ALIGN(sizeof(*topic) * (topic_len + 1)); - payload_size = GSM_MEM_ALIGN(sizeof(*payload) * (payload_len + 1)); - - size = buf_size + topic_size + payload_size; - buf = gsm_mem_malloc(size); - if (buf != NULL) { - GSM_MEMSET(buf, 0x00, size); - buf->topic = (void *)((uint8_t *)buf + buf_size); - buf->payload = (void *)((uint8_t *)buf + buf_size + topic_size); - buf->topic_len = topic_len; - buf->payload_len = payload_len; - buf->qos = qos; - - /* Copy content to new memory */ - GSM_MEMCPY(buf->topic, topic, sizeof(*topic) * topic_len); - GSM_MEMCPY(buf->payload, payload, sizeof(*payload) * payload_len); - - /* Write to receive queue */ - if (!gsm_sys_mbox_putnow(&api_client->rcv_mbox, buf)) { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API_TRACE_WARNING, - "[MQTT API] Cannot put new received MQTT publish to queue\r\n"); - gsm_mem_free_s((void **)&buf); - } - } else { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API_TRACE_WARNING, - "[MQTT API] Cannot allocate memory for packet buffer of size %d bytes\r\n", - (int)size); - } - } - break; - } - case GSM_MQTT_EVT_PUBLISH: { - api_client->sub_pub_resp = gsm_mqtt_client_evt_publish_get_result(client, evt); - - /* Print debug message */ - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API_TRACE, - "[MQTT API] Publish event with response: %d\r\n", - (int)api_client->sub_pub_resp); - - release_sem(api_client); /* Release semaphore */ - break; - } - case GSM_MQTT_EVT_SUBSCRIBE: { - api_client->sub_pub_resp = gsm_mqtt_client_evt_subscribe_get_result(client, evt); - - /* Print debug message */ - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API_TRACE, - "[MQTT API] Subscribe event with response: %d\r\n", - (int)api_client->sub_pub_resp); - - release_sem(api_client); /* Release semaphore */ - break; - } - case GSM_MQTT_EVT_UNSUBSCRIBE: { - api_client->sub_pub_resp = gsm_mqtt_client_evt_unsubscribe_get_result(client, evt); - - /* Print debug message */ - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API_TRACE, - "[MQTT API] Unsubscribe event with response: %d\r\n", - (int)api_client->sub_pub_resp); - - release_sem(api_client); /* Release semaphore */ - break; - } - case GSM_MQTT_EVT_DISCONNECT: { - uint8_t is_accepted = gsm_mqtt_client_evt_disconnect_is_accepted(client, evt); - /* Disconnect event happened */ - //api_client->connect_resp = MQTT_CONN_STATUS_TCP_FAILED; - - /* Print debug message */ - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API_TRACE, - "[MQTT API] Disconnect event\r\n"); - - /* Write to receive mbox to wakeup receive thread */ - if (is_accepted && gsm_sys_mbox_isvalid(&api_client->rcv_mbox)) { - gsm_sys_mbox_putnow(&api_client->rcv_mbox, &mqtt_closed); - } - - release_sem(api_client); /* Release semaphore */ - break; - } - default: break; - } -} - -/** - * \brief Create new MQTT client API - * \param[in] tx_buff_len: Maximal TX buffer for maximal packet length - * \param[in] rx_buff_len: Maximal RX buffer - * \return Client handle on success, `NULL` otherwise - */ -gsm_mqtt_client_api_p -gsm_mqtt_client_api_new(size_t tx_buff_len, size_t rx_buff_len) { - gsm_mqtt_client_api_p client; - size_t size; - - size = GSM_MEM_ALIGN(sizeof(*client)); /* Get size of client itself */ - - /* Create client APi structure */ - client = gsm_mem_calloc(1, size); /* Allocate client memory */ - if (client != NULL) { - /* Create MQTT raw client structure */ - client->mc = gsm_mqtt_client_new(tx_buff_len, rx_buff_len); - if (client->mc != NULL) { - /* Create receive mbox queue */ - if (gsm_sys_mbox_create(&client->rcv_mbox, 5)) { - /* Create synchronization semaphore */ - if (gsm_sys_sem_create(&client->sync_sem, 1)) { - /* Create mutex */ - if (gsm_sys_mutex_create(&client->mutex)) { - gsm_mqtt_client_set_arg(client->mc, client);/* Set client to mqtt client argument */ - return client; - } else { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API, - "[MQTT API] Cannot allocate mutex\r\n"); - } - } else { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API, - "[MQTT API] Cannot allocate sync semaphore\r\n"); - } - } else { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API, - "[MQTT API] Cannot allocate receive queue\r\n"); - } - } else { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API, - "[MQTT API] Cannot allocate MQTT client\r\n"); - } - } else { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API, - "[MQTT API] Cannot allocate memory for client\r\n"); - } - - gsm_mqtt_client_api_delete(client); - client = NULL; - return NULL; -} - -/** - * \brief Delete client from memory - * \param[in] client: MQTT API client handle - */ -void -gsm_mqtt_client_api_delete(gsm_mqtt_client_api_p client) { - if (client == NULL) { - return; - } - if (gsm_sys_sem_isvalid(&client->sync_sem)) { - gsm_sys_sem_delete(&client->sync_sem); - gsm_sys_sem_invalid(&client->sync_sem); - } - if (gsm_sys_mutex_isvalid(&client->mutex)) { - gsm_sys_mutex_delete(&client->mutex); - gsm_sys_mutex_invalid(&client->mutex); - } - if (gsm_sys_mbox_isvalid(&client->rcv_mbox)) { - void* d; - while (gsm_sys_mbox_getnow(&client->rcv_mbox, &d)) { - if ((uint8_t *)d != (uint8_t *)&mqtt_closed) { - gsm_mqtt_client_api_buf_free(d); - } - } - gsm_sys_mbox_delete(&client->rcv_mbox); - gsm_sys_mbox_invalid(&client->rcv_mbox); - } - if (client->mc != NULL) { - gsm_mqtt_client_delete(client->mc); - client->mc = NULL; - } - gsm_mem_free_s((void **)&client); -} - -/** - * \brief Connect to MQTT broker - * \param[in] client: MQTT API client handle - * \param[in] host: TCP host - * \param[in] port: TCP port - * \param[in] info: MQTT client info - * \return \ref GSM_MQTT_CONN_STATUS_ACCEPTED on success, member of \ref gsm_mqtt_conn_status_t otherwise - */ -gsm_mqtt_conn_status_t -gsm_mqtt_client_api_connect(gsm_mqtt_client_api_p client, const char* host, - gsm_port_t port, const gsm_mqtt_client_info_t* info) { - if (client == NULL || host == NULL - || !port || info == NULL) { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API_TRACE_WARNING, - "[MQTT API] Invalid parameters in function\r\n"); - return GSM_MQTT_CONN_STATUS_TCP_FAILED; - } - - gsm_sys_mutex_lock(&client->mutex); - client->connect_resp = GSM_MQTT_CONN_STATUS_TCP_FAILED; - gsm_sys_sem_wait(&client->sync_sem, 0); - client->release_sem = 1; - if (gsm_mqtt_client_connect(client->mc, host, port, mqtt_evt, info) == gsmOK) { - gsm_sys_sem_wait(&client->sync_sem, 0); - } else { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API_TRACE_WARNING, - "[MQTT API] Cannot connect to %s\r\n", host); - } - client->release_sem = 0; - gsm_sys_sem_release(&client->sync_sem); - gsm_sys_mutex_unlock(&client->mutex); - return client->connect_resp; -} - -/** - * \brief Close MQTT connection - * \param[in] client: MQTT API client handle - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_mqtt_client_api_close(gsm_mqtt_client_api_p client) { - gsmr_t res = gsmERR; - - GSM_ASSERT("client != NULL", client != NULL); - - gsm_sys_mutex_lock(&client->mutex); - gsm_sys_sem_wait(&client->sync_sem, 0); - client->release_sem = 1; - if (gsm_mqtt_client_disconnect(client->mc) == gsmOK) { - res = gsmOK; - gsm_sys_sem_wait(&client->sync_sem, 0); - } else { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API_TRACE_WARNING, - "[MQTT API] Cannot close API connection\r\n"); - } - client->release_sem = 0; - gsm_sys_sem_release(&client->sync_sem); - gsm_sys_mutex_unlock(&client->mutex); - return res; -} - -/** - * \brief Subscribe to topic - * \param[in] client: MQTT API client handle - * \param[in] topic: Topic to subscribe on - * \param[in] qos: Quality of service. This parameter can be a value of \ref gsm_mqtt_qos_t - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_mqtt_client_api_subscribe(gsm_mqtt_client_api_p client, const char* topic, - gsm_mqtt_qos_t qos) { - gsmr_t res = gsmERR; - - GSM_ASSERT("client != NULL", client != NULL); - GSM_ASSERT("topic != NULL", topic != NULL); - - gsm_sys_mutex_lock(&client->mutex); - gsm_sys_sem_wait(&client->sync_sem, 0); - client->release_sem = 1; - if (gsm_mqtt_client_subscribe(client->mc, topic, qos, NULL) == gsmOK) { - gsm_sys_sem_wait(&client->sync_sem, 0); - res = client->sub_pub_resp; - } else { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API_TRACE_WARNING, - "[MQTT API] Cannot subscribe to topic %s\r\n", topic); - } - client->release_sem = 0; - gsm_sys_sem_release(&client->sync_sem); - gsm_sys_mutex_unlock(&client->mutex); - - return res; -} - -/** - * \brief Unsubscribe from topic - * \param[in] client: MQTT API client handle - * \param[in] topic: Topic to unsubscribe from - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_mqtt_client_api_unsubscribe(gsm_mqtt_client_api_p client, const char* topic) { - gsmr_t res = gsmERR; - - GSM_ASSERT("client != NULL", client != NULL); - GSM_ASSERT("topic != NULL", topic != NULL); - - gsm_sys_mutex_lock(&client->mutex); - gsm_sys_sem_wait(&client->sync_sem, 0); - client->release_sem = 1; - if (gsm_mqtt_client_unsubscribe(client->mc, topic, NULL) == gsmOK) { - gsm_sys_sem_wait(&client->sync_sem, 0); - res = client->sub_pub_resp; - } else { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API_TRACE_WARNING, - "[MQTT API] Cannot unsubscribe from topic %s\r\n", topic); - } - client->release_sem = 0; - gsm_sys_sem_release(&client->sync_sem); - gsm_sys_mutex_unlock(&client->mutex); - - return res; -} - -/** - * \brief Publish new packet to MQTT network - * \param[in] client: MQTT API client handle - * \param[in] topic: Topic to publish on - * \param[in] data: Data to send - * \param[in] btw: Number of bytes to send for data parameter - * \param[in] qos: Quality of service. This parameter can be a value of \ref gsm_mqtt_qos_t - * \param[in] retain: Set to `1` for retain flag, `0` otherwise - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_mqtt_client_api_publish(gsm_mqtt_client_api_p client, const char* topic, const void* data, - size_t btw, gsm_mqtt_qos_t qos, uint8_t retain) { - gsmr_t res = gsmERR; - - GSM_ASSERT("client != NULL", client != NULL); - GSM_ASSERT("topic != NULL", topic != NULL); - GSM_ASSERT("data != NULL", data != NULL); - GSM_ASSERT("btw > 0", btw > 0); - - gsm_sys_mutex_lock(&client->mutex); - gsm_sys_sem_wait(&client->sync_sem, 0); - client->release_sem = 1; - if (gsm_mqtt_client_publish(client->mc, topic, data, GSM_U16(btw), qos, retain, NULL) == gsmOK) { - gsm_sys_sem_wait(&client->sync_sem, 0); - res = client->sub_pub_resp; - } else { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API_TRACE_WARNING, - "[MQTT API] Cannot publish new packet\r\n"); - } - client->release_sem = 0; - gsm_sys_sem_release(&client->sync_sem); - gsm_sys_mutex_unlock(&client->mutex); - - return res; -} - -/** - * \brief Check if client MQTT connection is active - * \param[in] client: MQTT API client handle - * \return `1` on success, `0` otherwise - */ -uint8_t -gsm_mqtt_client_api_is_connected(gsm_mqtt_client_api_p client) { - uint8_t ret; - - if (client == NULL) { - return 0; - } - - gsm_sys_mutex_lock(&client->mutex); - ret = gsm_mqtt_client_is_connected(client->mc); - gsm_sys_mutex_unlock(&client->mutex); - return ret; -} - -/** - * \brief Receive next packet in specific timeout time - * \note This function can be called from separate thread - * than the rest of API function, which allows you to - * handle receive data separated with custom timeout - * \param[in] client: MQTT API client handle - * \param[in] p: Pointer to output buffer - * \param[in] timeout: Maximal time to wait before function returns timeout - * \return \ref gsmOK on success, \ref gsmCLOSED if MQTT is closed, \ref gsmTIMEOUT on timeout - */ -gsmr_t -gsm_mqtt_client_api_receive(gsm_mqtt_client_api_p client, gsm_mqtt_client_api_buf_p* p, - uint32_t timeout) { - GSM_ASSERT("client != NULL", client != NULL); - GSM_ASSERT("p != NULL", p != NULL); - - *p = NULL; - - /* Get new entry from mbox */ - if (timeout == 0) { - if (!gsm_sys_mbox_getnow(&client->rcv_mbox, (void **)p)) { - return gsmTIMEOUT; - } - } else if (gsm_sys_mbox_get(&client->rcv_mbox, (void **)p, timeout) == GSM_SYS_TIMEOUT) { - return gsmTIMEOUT; - } - - /* Check for MQTT closed event */ - if ((uint8_t *)(*p) == (uint8_t *)&mqtt_closed) { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_API_TRACE, - "[MQTT API] Closed event received from queue\r\n"); - - *p = NULL; - return gsmCLOSED; - } - return gsmOK; -} - -/** - * \brief Free buffer memory after usage - * \param[in] p: Buffer to free - */ -void -gsm_mqtt_client_api_buf_free(gsm_mqtt_client_api_buf_p p) { - gsm_mem_free_s((void **)&p); -} diff --git a/gsm_at_lib/src/gsm/gsm.c b/gsm_at_lib/src/gsm/gsm.c deleted file mode 100644 index 564d40ec..00000000 --- a/gsm_at_lib/src/gsm/gsm.c +++ /dev/null @@ -1,334 +0,0 @@ -/** - * \file gsm.c - * \brief Main GSM core file - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_mem.h" -#include "gsm/gsm_threads.h" -#include "system/gsm_ll.h" - -#if GSM_CFG_OS != 1 -#error GSM_CFG_OS must be set to 1! -#endif - -static gsmr_t def_callback(gsm_evt_t* cb); -static gsm_evt_func_t def_evt_link; - -gsm_t gsm; - -/** - * \brief Default callback function for events - * \param[in] evt: Pointer to callback data structure - * \return Member of \ref gsmr_t enumeration - */ -static gsmr_t -def_callback(gsm_evt_t* evt) { - GSM_UNUSED(evt); - return gsmOK; -} - -/** - * \brief Init and prepare GSM stack for device operation - * \note Function must be called from operating system thread context. - * It creates necessary threads and waits them to start, thus running operating system is important. - * - When \ref GSM_CFG_RESET_ON_INIT is enabled, reset sequence will be sent to device - * otherwise manual call to \ref gsm_reset is required to setup device - * - * \param[in] evt_func: Global event callback function for all major events - * \param[in] blocking: Status whether command should be blocking or not. - * Used when \ref GSM_CFG_RESET_ON_INIT is enabled. - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsm_init(gsm_evt_fn evt_func, const uint32_t blocking) { - gsmr_t res = gsmOK; - - gsm.status.f.initialized = 0; /* Clear possible init flag */ - - def_evt_link.fn = evt_func != NULL ? evt_func : def_callback; - gsm.evt_func = &def_evt_link; /* Set callback function */ - - if (!gsm_sys_init()) { /* Init low-level system */ - goto cleanup; - } - - if (!gsm_sys_sem_create(&gsm.sem_sync, 1)) {/* Create sync semaphore between threads */ - GSM_DEBUGF(GSM_CFG_DBG_INIT | GSM_DBG_LVL_SEVERE | GSM_DBG_TYPE_TRACE, - "[CORE] Cannot allocate sync semaphore!\r\n"); - goto cleanup; - } - - /* Create message queues */ - if (!gsm_sys_mbox_create(&gsm.mbox_producer, GSM_CFG_THREAD_PRODUCER_MBOX_SIZE)) { /* Producer */ - GSM_DEBUGF(GSM_CFG_DBG_INIT | GSM_DBG_LVL_SEVERE | GSM_DBG_TYPE_TRACE, - "[CORE] Cannot allocate producer mbox queue!\r\n"); - goto cleanup; - } - if (!gsm_sys_mbox_create(&gsm.mbox_process, GSM_CFG_THREAD_PROCESS_MBOX_SIZE)) { /* Process */ - GSM_DEBUGF(GSM_CFG_DBG_INIT | GSM_DBG_LVL_SEVERE | GSM_DBG_TYPE_TRACE, - "[CORE] Cannot allocate process mbox queue!\r\n"); - goto cleanup; - } - - /* Create threads */ - gsm_sys_sem_wait(&gsm.sem_sync, 0); /* Lock semaphore */ - if (!gsm_sys_thread_create(&gsm.thread_produce, "gsm_produce", gsm_thread_produce, &gsm.sem_sync, GSM_SYS_THREAD_SS, GSM_SYS_THREAD_PRIO)) { - GSM_DEBUGF(GSM_CFG_DBG_INIT | GSM_DBG_LVL_SEVERE | GSM_DBG_TYPE_TRACE, - "[CORE] Cannot create producing thread!\r\n"); - gsm_sys_sem_release(&gsm.sem_sync); /* Release semaphore and return */ - goto cleanup; - } - gsm_sys_sem_wait(&gsm.sem_sync, 0); /* Wait semaphore, should be unlocked in produce thread */ - if (!gsm_sys_thread_create(&gsm.thread_process, "gsm_process", gsm_thread_process, &gsm.sem_sync, GSM_SYS_THREAD_SS, GSM_SYS_THREAD_PRIO)) { - GSM_DEBUGF(GSM_CFG_DBG_INIT | GSM_DBG_LVL_SEVERE | GSM_DBG_TYPE_TRACE, - "[CORE] Cannot allocate processing thread!\r\n"); - gsm_sys_thread_terminate(&gsm.thread_produce); /* Delete produce thread */ - gsm_sys_sem_release(&gsm.sem_sync); /* Release semaphore and return */ - goto cleanup; - } - gsm_sys_sem_wait(&gsm.sem_sync, 0); /* Wait semaphore, should be unlocked in produce thread */ - gsm_sys_sem_release(&gsm.sem_sync); /* Release semaphore manually */ - - gsm_core_lock(); - gsm.ll.uart.baudrate = GSM_CFG_AT_PORT_BAUDRATE; - gsm_ll_init(&gsm.ll); /* Init low-level communication */ - -#if !GSM_CFG_INPUT_USE_PROCESS - gsm_buff_init(&gsm.buff, GSM_CFG_RCV_BUFF_SIZE); /* Init buffer for input data */ -#endif /* !GSM_CFG_INPUT_USE_PROCESS */ - - gsm.status.f.initialized = 1; /* We are initialized now */ - gsm.status.f.dev_present = 1; /* We assume device is present at this point */ - - gsmi_send_cb(GSM_EVT_INIT_FINISH); /* Call user callback function */ - - /* - * Call reset command and call default - * AT commands to prepare basic setup for device - */ -#if GSM_CFG_RESET_ON_INIT - if (gsm.status.f.dev_present) { - gsm_core_unlock(); - res = gsm_reset_with_delay(GSM_CFG_RESET_DELAY_DEFAULT, NULL, NULL, blocking); /* Send reset sequence with delay */ - gsm_core_lock(); - } -#else /* GSM_CFG_RESET_ON_INIT */ - GSM_UNUSED(blocking); /* Unused variable */ -#endif /* !GSM_CFG_RESET_ON_INIT */ - gsm_core_unlock(); - - return res; - -cleanup: - if (gsm_sys_mbox_isvalid(&gsm.mbox_producer)) { - gsm_sys_mbox_delete(&gsm.mbox_producer); - gsm_sys_mbox_invalid(&gsm.mbox_producer); - } - if (gsm_sys_mbox_isvalid(&gsm.mbox_process)) { - gsm_sys_mbox_delete(&gsm.mbox_process); - gsm_sys_mbox_invalid(&gsm.mbox_process); - } - if (gsm_sys_sem_isvalid(&gsm.sem_sync)) { - gsm_sys_sem_delete(&gsm.sem_sync); - gsm_sys_sem_invalid(&gsm.sem_sync); - } - return gsmERRMEM; -} - -/** - * \brief Execute reset and send default commands - * \param[in] evt_fn: Callback function called when command is finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsm_reset(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - return gsm_reset_with_delay(0, evt_fn, evt_arg, blocking); -} - -/** - * \brief Execute reset and send default commands with delay - * \param[in] delay: Number of milliseconds to wait before initiating first command to device - * \param[in] evt_fn: Callback function called when command is finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsm_reset_with_delay(uint32_t delay, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_RESET; - GSM_MSG_VAR_REF(msg).msg.reset.delay = delay; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); -} - -/** - * \brief Lock stack from multi-thread access, enable atomic access to core - * - * If lock was `0` prior funcion call, lock is enabled and increased - * - * \note Function may be called multiple times to increase locks. - * Application must take care to call \ref gsm_core_unlock - * the same amount of time to make sure lock gets back to `0` - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsm_core_lock(void) { - gsm_sys_protect(); - gsm.locked_cnt++; - return gsmOK; -} - -/** - * \brief Unlock stack for multi-thread access - * - * Used in conjunction with \ref gsm_core_lock function - * - * If lock was non-zero before function call, lock is decreased. - * When `lock == 0`, protection is disabled and other threads may access to core - * - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsm_core_unlock(void) { - gsm.locked_cnt--; - gsm_sys_unprotect(); - return gsmOK; -} - -/** - * \brief Delay for amount of milliseconds - * - * Delay is based on operating system semaphores. - * It locks semaphore and waits for timeout in `ms` time. - * Based on operating system, thread may be put to \e blocked list during delay and may improve execution speed - * - * \param[in] ms: Milliseconds to delay - * \return `1` on success, `0` otherwise - */ -uint8_t -gsm_delay(uint32_t ms) { - gsm_sys_sem_t sem; - if (ms == 0) { - return 1; - } - if (gsm_sys_sem_create(&sem, 0)) { - gsm_sys_sem_wait(&sem, ms); - gsm_sys_sem_release(&sem); - gsm_sys_sem_delete(&sem); - return 1; - } - return 0; -} - -/** - * \brief Set modem function mode - * \note Use this function to set modem to normal or low-power mode - * \param[in] mode: Mode status. Set to `1` for full functionality or `0` for low-power mode (no functionality) - * \param[in] evt_fn: Callback function called when command is finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsm_set_func_mode(uint8_t mode, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CFUN_SET; - GSM_MSG_VAR_REF(msg).msg.cfun.mode = mode; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); -} - -/** - * \brief Notify stack if device is present or not - * - * Use this function to notify stack that device is not physically connected - * and not ready to communicate with host device - * - * \param[in] present: Flag indicating device is present - * \param[in] evt_fn: Callback function called when command is finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsm_device_set_present(uint8_t present, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - gsmr_t res = gsmOK; - gsm_core_lock(); - present = present ? 1 : 0; - if (present != gsm.status.f.dev_present) { - gsm.status.f.dev_present = present; - - if (!gsm.status.f.dev_present) { - /* Manually reset stack to default device state */ - gsmi_reset_everything(1); - } else { -#if GSM_CFG_RESET_ON_DEVICE_PRESENT - gsm_core_unlock(); - res = gsm_reset_with_delay(GSM_CFG_RESET_DELAY_DEFAULT, evt_fn, evt_arg, blocking); /* Reset with delay */ - gsm_core_lock(); -#endif /* GSM_CFG_RESET_ON_DEVICE_PRESENT */ - } - gsmi_send_cb(GSM_EVT_DEVICE_PRESENT); /* Send present event */ - } - gsm_core_unlock(); - - GSM_UNUSED(evt_fn); - GSM_UNUSED(evt_arg); - GSM_UNUSED(blocking); - - return res; -} - -/** - * \brief Check if device is present - * \return `1` on success, `0` otherwise - */ -uint8_t -gsm_device_is_present(void) { - uint8_t res; - gsm_core_lock(); - res = gsm.status.f.dev_present; - gsm_core_unlock(); - return res; -} diff --git a/gsm_at_lib/src/gsm/gsm_int.c b/gsm_at_lib/src/gsm/gsm_int.c deleted file mode 100644 index 095f58ef..00000000 --- a/gsm_at_lib/src/gsm/gsm_int.c +++ /dev/null @@ -1,2305 +0,0 @@ -/** - * \file gsm_int.c - * \brief Internal functions - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#include "gsm/gsm_private.h" -#include "gsm/gsm.h" -#include "gsm/gsm_int.h" -#include "gsm/gsm_mem.h" -#include "gsm/gsm_parser.h" -#include "gsm/gsm_unicode.h" -#include "system/gsm_ll.h" - -#if !__DOXYGEN__ -/** - * \brief Receive character structure to handle full line terminated with `\n` character - */ -typedef struct { - char data[128]; /*!< Received characters */ - size_t len; /*!< Length of valid characters */ -} gsm_recv_t; - -/* Receive character macros */ -#define RECV_ADD(ch) do { if (recv_buff.len < (sizeof(recv_buff.data)) - 1) { recv_buff.data[recv_buff.len++] = ch; recv_buff.data[recv_buff.len] = 0; } } while (0) -#define RECV_RESET() do { recv_buff.len = 0; recv_buff.data[0] = 0; } while (0) -#define RECV_LEN() ((size_t)recv_buff.len) -#define RECV_IDX(index) recv_buff.data[index] - -/* Send data over AT port */ -#define AT_PORT_SEND_STR(str) gsm.ll.send_fn((const void *)(str), (size_t)strlen(str)) -#define AT_PORT_SEND_CONST_STR(str) gsm.ll.send_fn((const void *)(str), (size_t)(sizeof(str) - 1)) -#define AT_PORT_SEND_CHR(ch) gsm.ll.send_fn((const void *)(ch), (size_t)1) -#define AT_PORT_SEND_FLUSH() gsm.ll.send_fn(NULL, 0) -#define AT_PORT_SEND(d, l) gsm.ll.send_fn((const void *)(d), (size_t)(l)) -#define AT_PORT_SEND_WITH_FLUSH(d, l) do { AT_PORT_SEND((d), (l)); AT_PORT_SEND_FLUSH(); } while (0) - -/* Beginning and end of every AT command */ -#define AT_PORT_SEND_BEGIN_AT() do { AT_PORT_SEND_CONST_STR("AT"); } while (0) -#define AT_PORT_SEND_END_AT() do { AT_PORT_SEND(CRLF, CRLF_LEN); AT_PORT_SEND(NULL, 0); } while (0) - -/* Send special characters over AT port with condition */ -#define AT_PORT_SEND_QUOTE_COND(q) do { if ((q)) { AT_PORT_SEND_CONST_STR("\""); } } while (0) -#define AT_PORT_SEND_COMMA_COND(c) do { if ((c)) { AT_PORT_SEND_CONST_STR(","); } } while (0) -#define AT_PORT_SEND_EQUAL_COND(e) do { if ((e)) { AT_PORT_SEND_CONST_STR("="); } } while (0) - -/* Send special characters */ -#define AT_PORT_SEND_CTRL_Z() AT_PORT_SEND_STR("\x1A") -#define AT_PORT_SEND_ESC() AT_PORT_SEND_STR("\x1B") -#endif /* !__DOXYGEN__ */ - -static gsm_recv_t recv_buff; -static gsmr_t gsmi_process_sub_cmd(gsm_msg_t* msg, uint8_t* is_ok, uint16_t* is_error); - -/** - * \brief Memory mapping - */ -const gsm_dev_mem_map_t -gsm_dev_mem_map[] = { -#define GSM_DEV_MEMORY_ENTRY(name, str_code) { GSM_MEM_ ## name, str_code }, -#include "gsm/gsm_memories.h" -}; - -/** - * \brief Size of device memory mapping array - */ -const size_t -gsm_dev_mem_map_size = GSM_ARRAYSIZE(gsm_dev_mem_map); - -/** - * \brief List of supported devices - */ -const gsm_dev_model_map_t -gsm_dev_model_map[] = { -#define GSM_DEVICE_MODEL_ENTRY(name, str_id, is_2g, is_lte) { GSM_DEVICE_MODEL_ ## name, str_id, is_2g, is_lte }, -#include "gsm/gsm_models.h" -}; - -/** - * \brief Size of device models mapping array - */ -const size_t -gsm_dev_model_map_size = GSM_ARRAYSIZE(gsm_dev_model_map); - -/** - * \brief Free connection send data memory - * \param[in] m: Send data message type - */ -#define CONN_SEND_DATA_FREE(m) do { \ - if ((m) != NULL && (m)->msg.conn_send.fau) { \ - (m)->msg.conn_send.fau = 0; \ - if ((m)->msg.conn_send.data != NULL) { \ - GSM_DEBUGF(GSM_CFG_DBG_CONN | GSM_DBG_TYPE_TRACE, \ - "[CONN] Free write buffer fau: %p\r\n", (void *)(m)->msg.conn_send.data); \ - gsm_mem_free_s((void **)&((m)->msg.conn_send.data)); \ - } \ - } \ -} while (0) - -/** - * \brief Send connection callback for "data send" - * \param[in] m: Command message - * \param[in] err: Error of type \ref gsmr_t - */ -#define CONN_SEND_DATA_SEND_EVT(m, err) do { \ - CONN_SEND_DATA_FREE(m); \ - gsm.evt.type = GSM_EVT_CONN_SEND; \ - gsm.evt.evt.conn_data_send.res = err; \ - gsm.evt.evt.conn_data_send.conn = (m)->msg.conn_send.conn; \ - gsm.evt.evt.conn_data_send.sent = (m)->msg.conn_send.sent_all; \ - gsmi_send_conn_cb((m)->msg.conn_send.conn, NULL); \ -} while (0) - -/** - * \brief Send reset sequence event - * \param[in] m: Command message - * \param[in] err: Error of type \ref gsmr_t - */ -#define RESET_SEND_EVT(m, err) do { \ - gsm.evt.evt.reset.res = err; \ - gsmi_send_cb(GSM_EVT_RESET); \ -} while (0) - -/** - * \brief Send restore sequence event - * \param[in] m: Connection send message - * \param[in] err: Error of type \ref gsmr_t - */ -#define RESTORE_SEND_EVT(m, err) do { \ - gsm.evt.evt.restore.res = err; \ - gsmi_send_cb(GSM_EVT_RESTORE); \ -} while (0) - -/** - * \brief Send operator scan sequence event - * \param[in] m: Command message - * \param[in] err: Error of type \ref gsmr_t - */ -#define OPERATOR_SCAN_SEND_EVT(m, err) do { \ - gsm.evt.evt.operator_scan.res = err; \ - gsm.evt.evt.operator_scan.ops = (m)->msg.cops_scan.ops; \ - gsm.evt.evt.operator_scan.opf = *(m)->msg.cops_scan.opf;\ - gsmi_send_cb(GSM_EVT_OPERATOR_SCAN); \ -} while (0) - - /** - * \brief Send SMS delete operation event - * \param[in] m: SMS delete message - * \param[in] err: Error of type \ref gsmr_t - */ -#define SMS_SEND_DELETE_EVT(m, err) do { \ - gsm.evt.evt.sms_delete.res = err; \ - gsm.evt.evt.sms_delete.mem = (m)->msg.sms_delete.mem; \ - gsm.evt.evt.sms_delete.pos = (m)->msg.sms_delete.pos; \ - gsmi_send_cb(GSM_EVT_SMS_DELETE); \ -} while (0) - -/** - * \brief Send SMS read operation event - * \param[in] m: SMS read message - * \param[in] err: Error of type \ref gsmr_t - */ -#define SMS_SEND_READ_EVT(m, err) do { \ - gsm.evt.evt.sms_read.res = err; \ - gsm.evt.evt.sms_read.entry = (m)->msg.sms_read.entry; \ - gsmi_send_cb(GSM_EVT_SMS_READ); \ -} while (0) - -/** - * \brief Send SMS read operation event - * \param[in] _m_: SMS list message - * \param[in] err: Error of type \ref gsmr_t - */ -#define SMS_SEND_LIST_EVT(_m_, err) do { \ - gsm.evt.evt.sms_list.mem = gsm.m.sms.mem[0].current;\ - gsm.evt.evt.sms_list.entries = (_m_)->msg.sms_list.entries; \ - gsm.evt.evt.sms_list.size = (_m_)->msg.sms_list.ei; \ - gsm.evt.evt.sms_list.res = err; \ - gsmi_send_cb(GSM_EVT_SMS_LIST); \ -} while (0) - -/** - * \brief Send SMS send operation event - * \param[in] m: SMS send message - * \param[in] err: Error of type \ref gsmr_t - */ -#define SMS_SEND_SEND_EVT(m, err) do { \ - gsm.evt.evt.sms_send.pos = (m)->msg.sms_send.pos; \ - gsm.evt.evt.sms_send.res = err; \ - gsmi_send_cb(GSM_EVT_SMS_SEND); \ -} while (0) - -/** - * \brief Get SIM info when SIM is ready - * \param[in] blocking: Blocking command - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsmi_get_sim_info(const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_SIM_PROCESS_BASIC_CMDS; - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CNUM; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); -} - -/** - * \brief Send IP or MAC address to AT port - * \param[in] d: Pointer to IP or MAC address - * \param[in] is_ip: Set to `1` when sending IP, `0` when MAC - * \param[in] q: Set to `1` to include start and ending quotes - * \param[in] c: Set to `1` to include comma before string - */ -void -gsmi_send_ip_mac(const void* d, uint8_t is_ip, uint8_t q, uint8_t c) { - uint8_t ch; - char str[4]; - const gsm_mac_t* mac = d; - const gsm_ip_t* ip = d; - - AT_PORT_SEND_COMMA_COND(c); /* Send comma */ - if (d == NULL) { - return; - } - AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ - ch = is_ip ? '.' : ':'; /* Get delimiter character */ - for (uint8_t i = 0; i < (is_ip ? 4 : 6); i++) { /* Process byte by byte */ - if (is_ip) { /* In case of IP ... */ - gsm_u8_to_str(ip->ip[i], str); /* ... go to decimal format ... */ - } else { /* ... in case of MAC ... */ - gsm_u8_to_hex_str(mac->mac[i], str, 2); /* ... go to HEX format */ - } - AT_PORT_SEND_STR(str); /* Send str */ - if (i < (is_ip ? 4 : 6) - 1) { /* Check end if characters */ - AT_PORT_SEND_CHR(&ch); /* Send character */ - } - } - AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ -} - -/** - * \brief Send string to AT port, either plain or escaped - * \param[in] str: Pointer to input string to string - * \param[in] e: Value to indicate string send format, escaped (`1`) or plain (`0`) - * \param[in] q: Value to indicate starting and ending quotes, enabled (`1`) or disabled (`0`) - * \param[in] c: Set to `1` to include comma before string - */ -void -gsmi_send_string(const char* str, uint8_t e, uint8_t q, uint8_t c) { - char special = '\\'; - - AT_PORT_SEND_COMMA_COND(c); /* Send comma */ - AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ - if (str != NULL) { - if (e) { /* Do we have to escape string? */ - while (*str) { /* Go through string */ - if (*str == ',' || *str == '"' || *str == '\\') { /* Check for special character */ - AT_PORT_SEND_CHR(&special); /* Send special character */ - } - AT_PORT_SEND_CHR(str); /* Send character */ - str++; - } - } else { - AT_PORT_SEND_STR(str); /* Send plain string */ - } - } - AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ -} - -/** - * \brief Send number (decimal) to AT port - * \param[in] num: Number to send to AT port - * \param[in] q: Value to indicate starting and ending quotes, enabled (`1`) or disabled (`0`) - * \param[in] c: Set to `1` to include comma before string - */ -void -gsmi_send_number(uint32_t num, uint8_t q, uint8_t c) { - char str[11]; - - gsm_u32_to_str(num, str); /* Convert digit to decimal string */ - - AT_PORT_SEND_COMMA_COND(c); /* Send comma */ - AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ - AT_PORT_SEND_STR(str); /* Send string with number */ - AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ -} - -/** - * \brief Send port number to AT port - * \param[in] port: Port number to send - * \param[in] q: Value to indicate starting and ending quotes, enabled (`1`) or disabled (`0`) - * \param[in] c: Set to `1` to include comma before string - */ -void -gsmi_send_port(gsm_port_t port, uint8_t q, uint8_t c) { - char str[6]; - - gsm_u16_to_str(GSM_PORT2NUM(port), str); /* Convert digit to decimal string */ - - AT_PORT_SEND_COMMA_COND(c); /* Send comma */ - AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ - AT_PORT_SEND_STR(str); /* Send string with number */ - AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ -} - -/** - * \brief Send signed number to AT port - * \param[in] num: Number to send to AT port - * \param[in] q: Value to indicate starting and ending quotes, enabled (`1`) or disabled (`0`) - * \param[in] c: Set to `1` to include comma before string - */ -void -gsmi_send_signed_number(int32_t num, uint8_t q, uint8_t c) { - char str[11]; - - gsm_i32_to_str(num, str); /* Convert digit to decimal string */ - - AT_PORT_SEND_COMMA_COND(c); /* Send comma */ - AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ - AT_PORT_SEND_STR(str); /* Send string with number */ - AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ -} - -/** - * \brief Send memory string to device - * \param[in] mem: Memory index to send - * \param[in] q: Value to indicate starting and ending quotes, enabled (`1`) or disabled (`0`) - * \param[in] c: Set to `1` to include comma before string - */ -void -gsmi_send_dev_memory(gsm_mem_t mem, uint8_t q, uint8_t c) { - if (mem < GSM_MEM_END) { /* Check valid range */ - gsmi_send_string(gsm_dev_mem_map[GSM_SZ(mem)].mem_str, 0, q, c); - } -} - -#if GSM_CFG_SMS || __DOXYGEN__ - -/** - * \brief Send SMS status text - * \param[in] status: SMS status - * \param[in] q: Value to indicate starting and ending quotes, enabled (`1`) or disabled (`0`) - * \param[in] c: Set to `1` to include comma before string - */ -void -gsmi_send_sms_stat(gsm_sms_status_t status, uint8_t q, uint8_t c) { - const char* t; - switch (status) { - case GSM_SMS_STATUS_UNREAD: t = "REC UNREAD"; break; - case GSM_SMS_STATUS_READ: t = "REC READ"; break; - case GSM_SMS_STATUS_UNSENT: t = "STO UNSENT"; break; - case GSM_SMS_STATUS_SENT: t = "STO SENT"; break; - case GSM_SMS_STATUS_ALL: - default: t = "ALL"; break; - } - gsmi_send_string(t, 0, q, c); -} - -#endif /* GSM_CFG_SMS */ - -#if GSM_CFG_CONN || __DOXYGEN__ - -/** - * \brief Reset all connections - * \note Used to notify upper layer stack to close everything and reset the memory if necessary - * \param[in] forced: Flag indicating reset was forced by user - */ -static void -reset_connections(uint8_t forced) { - gsm.evt.type = GSM_EVT_CONN_CLOSE; - gsm.evt.evt.conn_active_close.forced = forced; - gsm.evt.evt.conn_active_close.res = gsmOK; - - for (size_t i = 0; i < GSM_CFG_MAX_CONNS; i++) {/* Check all connections */ - if (gsm.m.conns[i].status.f.active) { - gsm.m.conns[i].status.f.active = 0; - - gsm.evt.evt.conn_active_close.conn = &gsm.m.conns[i]; - gsm.evt.evt.conn_active_close.client = gsm.m.conns[i].status.f.client; - gsmi_send_conn_cb(&gsm.m.conns[i], NULL); /* Send callback function */ - } - } -} - -#endif /* GSM_CFG_CONN || __DOXYGEN__ */ - -/** - * \brief Reset everything after reset was detected - * \param[in] forced: Set to `1` if reset forced by user - */ -void -gsmi_reset_everything(uint8_t forced) { - /** - * \todo: Put stack to default state: - * - Close all the connection in memory - * - Clear entire data memory - * - Reset GSM structure - */ - -#if GSM_CFG_CONN - /* Manually close all connections in memory */ - reset_connections(forced); - - /* Check if IPD active */ - if (gsm.m.ipd.buff != NULL) { - gsm_pbuf_free(gsm.m.ipd.buff); - gsm.m.ipd.buff = NULL; - } -#endif /* GSM_CFG_CONN */ - -#if GSM_CFG_NETWORK - /* Notify app about detached network PDP context */ - if (gsm.m.network.is_attached) { - gsm.m.network.is_attached = 0; - gsmi_send_cb(GSM_EVT_NETWORK_DETACHED); - } -#endif /* GSM_CFG_NETWORK */ - - /* Invalid GSM modules */ - GSM_MEMSET(&gsm.m, 0x00, sizeof(gsm.m)); - - /* Manually set states */ - gsm.m.sim.state = (gsm_sim_state_t)-1; - gsm.m.model = GSM_DEVICE_MODEL_UNKNOWN; -} - -/** - * \brief Process callback function to user with specific type - * \param[in] type: Callback event type - * \return Member of \ref gsmr_t enumeration - */ -gsmr_t -gsmi_send_cb(gsm_evt_type_t type) { - gsm.evt.type = type; /* Set callback type to process */ - - /* Call callback function for all registered functions */ - for (gsm_evt_func_t* link = gsm.evt_func; link != NULL; link = link->next) { - link->fn(&gsm.evt); - } - return gsmOK; -} - -#if GSM_CFG_CONN || __DOXYGEN__ - -/** - * \brief Process connection callback - * \note Before calling function, callback structure must be prepared - * \param[in] conn: Pointer to connection to use as callback - * \param[in] evt: Event callback function for connection - * \return Member of \ref gsmr_t enumeration - */ -gsmr_t -gsmi_send_conn_cb(gsm_conn_t* conn, gsm_evt_fn evt) { - if (conn->status.f.in_closing && gsm.evt.type != GSM_EVT_CONN_CLOSE) { /* Do not continue if in closing mode */ - /* return gsmOK; */ - } - - if (evt != NULL) { /* Try with user connection */ - return evt(&gsm.evt); /* Call temporary function */ - } else if (conn != NULL && conn->evt_func != NULL) {/* Connection custom callback? */ - return conn->evt_func(&gsm.evt); /* Process callback function */ - } else if (conn == NULL) { - return gsmOK; - } - - /* - * On normal API operation, - * we should never enter to this part of code - */ - - /* - * If connection doesn't have callback function - * automatically close the connection? - * - * Since function call is non-blocking, - * it will set active connection to closing mode - * and further callback events should not be executed anymore - */ - return gsm_conn_close(conn, 0); -} - -/** - * \brief Process and send data from device buffer - * \return Member of \ref gsmr_t enumeration - */ -static gsmr_t -gsmi_tcpip_process_send_data(void) { - gsm_conn_t* c = gsm.msg->msg.conn_send.conn; - if (!gsm_conn_is_active(c) || /* Is the connection already closed? */ - gsm.msg->msg.conn_send.val_id != c->val_id /* Did validation ID change after we set parameter? */ - ) { - /* Send event to user about failed send event */ - CONN_SEND_DATA_SEND_EVT(gsm.msg, gsmCLOSED); - return gsmERR; - } - gsm.msg->msg.conn_send.sent = GSM_MIN(gsm.msg->msg.conn_send.btw, GSM_CFG_CONN_MAX_DATA_LEN); - - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CIPSEND="); - gsmi_send_number(GSM_U32(c->num), 0, 0); /* Send connection number */ - gsmi_send_number(GSM_U32(gsm.msg->msg.conn_send.sent), 0, 1); /* Send length number */ - - /* On UDP connections, IP address and port may be selected */ - if (c->type == GSM_CONN_TYPE_UDP) { - if (gsm.msg->msg.conn_send.remote_ip != NULL && gsm.msg->msg.conn_send.remote_port) { - gsmi_send_ip_mac(gsm.msg->msg.conn_send.remote_ip, 1, 1, 1);/* Send IP address including quotes */ - gsmi_send_port(gsm.msg->msg.conn_send.remote_port, 0, 1); /* Send length number */ - } - } - AT_PORT_SEND_END_AT(); - return gsmOK; -} - -/** - * \brief Process data sent and send remaining - * \param[in] sent: Status whether data were sent or not, - * info received from GSM with "SEND OK" or "SEND FAIL" - * \return `1` in case we should stop sending or `0` if we still have data to process - */ -static uint8_t -gsmi_tcpip_process_data_sent(uint8_t sent) { - if (sent) { /* Data were successfully sent */ - gsm.msg->msg.conn_send.sent_all += gsm.msg->msg.conn_send.sent; - gsm.msg->msg.conn_send.btw -= gsm.msg->msg.conn_send.sent; - gsm.msg->msg.conn_send.ptr += gsm.msg->msg.conn_send.sent; - if (gsm.msg->msg.conn_send.bw != NULL) { - *gsm.msg->msg.conn_send.bw += gsm.msg->msg.conn_send.sent; - } - gsm.msg->msg.conn_send.tries = 0; - } else { /* We were not successful */ - gsm.msg->msg.conn_send.tries++; /* Increase number of tries */ - if (gsm.msg->msg.conn_send.tries == GSM_CFG_MAX_SEND_RETRIES) { /* In case we reached max number of retransmissions */ - return 1; /* Return 1 and indicate error */ - } - } - if (gsm.msg->msg.conn_send.btw > 0) { /* Do we still have data to send? */ - if (gsmi_tcpip_process_send_data() != gsmOK) { /* Check if we can continue */ - return 1; /* Finish at this point */ - } - return 0; /* We still have data to send */ - } - return 1; /* Everything was sent, we can stop execution */ -} - -/** - * \brief Process CIPSEND response - * \param[in] rcv: Received data - * \param[in,out] is_ok: Pointer to current ok status - * \param[in,out] is_ok: Pointer to current error status - */ -void -gsmi_process_cipsend_response(gsm_recv_t* rcv, uint8_t* is_ok, uint16_t* is_error) { - if (gsm.msg->msg.conn_send.wait_send_ok_err) { - if (GSM_CHARISNUM(rcv->data[0]) && rcv->data[1] == ',') { - uint8_t num = GSM_CHARTONUM(rcv->data[0]); - if (!strncmp(&rcv->data[3], "SEND OK" CRLF, 7 + CRLF_LEN)) { - gsm.msg->msg.conn_send.wait_send_ok_err = 0; - *is_ok = gsmi_tcpip_process_data_sent(1); /* Process as data were sent */ - if (*is_ok && gsm.msg->msg.conn_send.conn->status.f.active) { - CONN_SEND_DATA_SEND_EVT(gsm.msg, gsmOK); - } - } else if (!strncmp(&rcv->data[3], "SEND FAIL" CRLF, 9 + CRLF_LEN)) { - gsm.msg->msg.conn_send.wait_send_ok_err = 0; - *is_error = gsmi_tcpip_process_data_sent(0);/* Data were not sent due to SEND FAIL or command didn't even start */ - if (*is_error && gsm.msg->msg.conn_send.conn->status.f.active) { - CONN_SEND_DATA_SEND_EVT(gsm.msg, gsmERR); - } - } - GSM_UNUSED(num); - } - /* Check for an error or if connection closed in the meantime */ - } else if (*is_error) { - CONN_SEND_DATA_SEND_EVT(gsm.msg, gsmERR); - } -} - -/** - * \brief Send error event to application layer - * \param[in] msg: Message from user with connection start - */ -static void -gsmi_send_conn_error_cb(gsm_msg_t* msg, gsmr_t error) { - gsm.evt.type = GSM_EVT_CONN_ERROR; /* Connection error */ - gsm.evt.evt.conn_error.host = gsm.msg->msg.conn_start.host; - gsm.evt.evt.conn_error.port = gsm.msg->msg.conn_start.port; - gsm.evt.evt.conn_error.type = gsm.msg->msg.conn_start.type; - gsm.evt.evt.conn_error.arg = gsm.msg->msg.conn_start.arg; - gsm.evt.evt.conn_error.err = error; - - /* Call callback specified by user on connection startup */ - gsm.msg->msg.conn_start.evt_func(&gsm.evt); - GSM_UNUSED(msg); -} - -/** - * \brief Checks if connection pointer has valid address - * \param[in] conn: Address to check if valid connection ptr - * \return 1 on success, 0 otherwise - */ -uint8_t -gsmi_is_valid_conn_ptr(gsm_conn_p conn) { - uint8_t i = 0; - for (i = 0; i < GSM_ARRAYSIZE(gsm.m.conns); i++) { - if (conn == &gsm.m.conns[i]) { - return 1; - } - } - return 0; -} - -/** - * \brief Connection close event detected, process with callback to user - * \param[in] conn_num: Connection number - * \param[in] forced: Set to `1` if close forced by command, `0` otherwise - * \return `1` on success, `0` otherwise - */ -uint8_t -gsmi_conn_closed_process(uint8_t conn_num, uint8_t forced) { - gsm_conn_t* conn = &gsm.m.conns[conn_num]; - - conn->status.f.active = 0; - - /* Check if write buffer is set */ - if (conn->buff.buff != NULL) { - GSM_DEBUGF(GSM_CFG_DBG_CONN | GSM_DBG_TYPE_TRACE, - "[CONN] Free write buffer: %p\r\n", conn->buff.buff); - gsm_mem_free_s((void **)&conn->buff.buff); - } - - /* Send event */ - gsm.evt.type = GSM_EVT_CONN_CLOSE; - gsm.evt.evt.conn_active_close.conn = conn; - gsm.evt.evt.conn_active_close.forced = forced; - gsm.evt.evt.conn_active_close.res = gsmOK; - gsm.evt.evt.conn_active_close.client = conn->status.f.client; - gsmi_send_conn_cb(conn, NULL); - - return 1; -} - -#endif /* GSM_CFG_CONN || __DOXYGEN__ */ - -/** - * \brief Process received string from GSM - * \param[in] recv: Pointer to \ref gsm_rect_t structure with input string - */ -static void -gsmi_parse_received(gsm_recv_t* rcv) { - uint8_t is_ok = 0; - uint16_t is_error = 0; - - /* Try to remove non-parsable strings */ - if (rcv->len == 2 && rcv->data[0] == '\r' && rcv->data[1] == '\n') { - return; - } - - /* Check OK response */ - is_ok = rcv->len == (2 + CRLF_LEN) && !strcmp(rcv->data, "OK" CRLF); /* Check if received string is OK */ - if (!is_ok) { /* Check for SHUT OK string */ - is_ok = rcv->len == (7 + CRLF_LEN) && !strcmp(rcv->data, "SEND OK" CRLF); - } - - /* Check error response */ - if (!is_ok) { /* If still not ok, check if error? */ - is_error = rcv->data[0] == '+' && !strncmp(rcv->data, "+CME ERROR", 10); /* First check +CME coded errors */ - if (!is_error) { /* Check basic error aswell */ - is_error = rcv->data[0] == '+' && !strncmp(rcv->data, "+CMS ERROR", 10); /* First check +CME coded errors */ - if (!is_error) { - is_error = !strcmp(rcv->data, "ERROR" CRLF) || !strcmp(rcv->data, "FAIL" CRLF); - } - } - } - - /* Scan received strings which start with '+' */ - if (rcv->data[0] == '+') { - if (!strncmp(rcv->data, "+CSQ", 4)) { - gsmi_parse_csq(rcv->data); /* Parse +CSQ response */ -#if GSM_CFG_NETWORK - } else if (!strncmp(rcv->data, "+PDP: DEACT", 11)) { - /* PDP has been deactivated */ - gsm_network_check_status(NULL, NULL, 0);/* Update status */ -#endif /* GSM_CFG_NETWORK */ -#if GSM_CFG_CONN - } else if (!strncmp(rcv->data, "+RECEIVE", 8)) { - gsmi_parse_ipd(rcv->data); /* Parse IPD */ -#endif /* GSM_CFG_CONN */ - } else if (!strncmp(rcv->data, "+CREG", 5)) { /* Check for +CREG indication */ - gsmi_parse_creg(rcv->data, GSM_U8(CMD_IS_CUR(GSM_CMD_CREG_GET))); /* Parse +CREG response */ - } else if (!strncmp(rcv->data, "+CPIN", 5)) { /* Check for +CPIN indication for SIM */ - gsmi_parse_cpin(rcv->data, 1 /* !CMD_IS_DEF(GSM_CMD_CPIN_SET) */); /* Parse +CPIN response */ - } else if (CMD_IS_CUR(GSM_CMD_COPS_GET) && !strncmp(rcv->data, "+COPS", 5)) { - gsmi_parse_cops(rcv->data); /* Parse current +COPS */ -#if GSM_CFG_SMS - } else if (CMD_IS_CUR(GSM_CMD_CMGS) && !strncmp(rcv->data, "+CMGS", 5)) { - gsmi_parse_cmgs(rcv->data, &gsm.msg->msg.sms_send.pos); /* Parse +CMGS response */ - } else if (CMD_IS_CUR(GSM_CMD_CMGR) && !strncmp(rcv->data, "+CMGR", 5)) { - if (gsmi_parse_cmgr(rcv->data)) { /* Parse +CMGR response */ - gsm.msg->msg.sms_read.read = 2; /* Set read flag and process the data */ - } else { - gsm.msg->msg.sms_read.read = 1; /* Read but ignore data */ - } - } else if (CMD_IS_CUR(GSM_CMD_CMGL) && !strncmp(rcv->data, "+CMGL", 5)) { - if (gsmi_parse_cmgl(rcv->data)) { /* Parse +CMGL response */ - gsm.msg->msg.sms_list.read = 2; /* Set read flag and process the data */ - } else { - gsm.msg->msg.sms_list.read = 1; /* Read but ignore data */ - } - } else if (!strncmp(rcv->data, "+CMTI", 5)) { - gsmi_parse_cmti(rcv->data, 1); /* Parse +CMTI response with received SMS */ - } else if (CMD_IS_CUR(GSM_CMD_CPMS_GET_OPT) && !strncmp(rcv->data, "+CPMS", 5)) { - gsmi_parse_cpms(rcv->data, 0); /* Parse +CPMS with SMS memories info */ - } else if (CMD_IS_CUR(GSM_CMD_CPMS_GET) && !strncmp(rcv->data, "+CPMS", 5)) { - gsmi_parse_cpms(rcv->data, 1); /* Parse +CPMS with SMS memories info */ - } else if (CMD_IS_CUR(GSM_CMD_CPMS_SET) && !strncmp(rcv->data, "+CPMS", 5)) { - gsmi_parse_cpms(rcv->data, 2); /* Parse +CPMS with SMS memories info */ -#endif /* GSM_CFG_SMS */ -#if GSM_CFG_CALL - } else if (!strncmp(rcv->data, "+CLCC", 5)) { - gsmi_parse_clcc(rcv->data, 1); /* Parse +CLCC response with call info change */ -#endif /* GSM_CFG_CALL */ -#if GSM_CFG_PHONEBOOK - } else if (CMD_IS_CUR(GSM_CMD_CPBS_GET_OPT) && !strncmp(rcv->data, "+CPBS", 5)) { - gsmi_parse_cpbs(rcv->data, 0); /* Parse +CPBS response */ - } else if (CMD_IS_CUR(GSM_CMD_CPBS_GET) && !strncmp(rcv->data, "+CPBS", 5)) { - gsmi_parse_cpbs(rcv->data, 1); /* Parse +CPBS response */ - } else if (CMD_IS_CUR(GSM_CMD_CPBS_SET) && !strncmp(rcv->data, "+CPBS", 5)) { - gsmi_parse_cpbs(rcv->data, 2); /* Parse +CPBS response */ - } else if (CMD_IS_CUR(GSM_CMD_CPBR) && !strncmp(rcv->data, "+CPBR", 5)) { - gsmi_parse_cpbr(rcv->data); /* Parse +CPBR statement */ - } else if (CMD_IS_CUR(GSM_CMD_CPBF) && !strncmp(rcv->data, "+CPBF", 5)) { - gsmi_parse_cpbf(rcv->data); /* Parse +CPBR statement */ -#endif /* GSM_CFG_PHONEBOOK */ - } - - /* Messages not starting with '+' sign */ - } else { - if (rcv->data[0] == 'S' && !strncmp(rcv->data, "SHUT OK" CRLF, 7 + CRLF_LEN)) { - is_ok = 1; -#if GSM_CFG_CONN - } else if (GSM_CHARISNUM(rcv->data[0]) && rcv->data[1] == ',' && rcv->data[2] == ' ' - && (!strncmp(&rcv->data[3], "CLOSE OK" CRLF, 8 + CRLF_LEN) || !strncmp(&rcv->data[3], "CLOSED" CRLF, 6 + CRLF_LEN))) { - uint8_t forced = 0, num; - - num = GSM_CHARTONUM(rcv->data[0]); /* Get connection number */ - if (CMD_IS_CUR(GSM_CMD_CIPCLOSE) && gsm.msg->msg.conn_close.conn->num == num) { - forced = 1; - is_ok = 1; /* If forced and connection is closed, command is OK */ - } - - /* Manually stop send command? */ - if (CMD_IS_CUR(GSM_CMD_CIPSEND) && gsm.msg->msg.conn_send.conn->num == num) { - /* - * If active command is CIPSEND and CLOSED event received, - * manually set error and process usual "ERROR" event on senddata - */ - is_error = 1; /* This is an error in response */ - gsmi_process_cipsend_response(rcv, &is_ok, &is_error); - } - gsmi_conn_closed_process(num, forced); /* Connection closed, process */ -#endif /* GSM_CFG_CONN */ -#if GSM_CFG_CALL - } else if (rcv->data[0] == 'C' && !strncmp(rcv->data, "Call Ready" CRLF, 10 + CRLF_LEN)) { - gsm.m.call.ready = 1; - gsmi_send_cb(GSM_EVT_CALL_READY); /* Send CALL ready event */ - } else if (rcv->data[0] == 'R' && !strncmp(rcv->data, "RING" CRLF, 4 + CRLF_LEN)) { - gsmi_send_cb(GSM_EVT_CALL_RING); /* Send call ring */ - } else if (rcv->data[0] == 'N' && !strncmp(rcv->data, "NO CARRIER" CRLF, 10 + CRLF_LEN)) { - gsmi_send_cb(GSM_EVT_CALL_NO_CARRIER); /* Send call no carrier event */ - } else if (rcv->data[0] == 'B' && !strncmp(rcv->data, "BUSY" CRLF, 4 + CRLF_LEN)) { - gsmi_send_cb(GSM_EVT_CALL_BUSY); /* Send call busy message */ -#endif /* GSM_CFG_CALL */ -#if GSM_CFG_SMS - } else if (rcv->data[0] == 'S' && !strncmp(rcv->data, "SMS Ready" CRLF, 9 + CRLF_LEN)) { - gsm.m.sms.ready = 1; /* SMS ready flag */ - gsmi_send_cb(GSM_EVT_SMS_READY); /* Send SMS ready event */ -#endif /* GSM_CFG_SMS */ - } else if ((CMD_IS_CUR(GSM_CMD_CGMI_GET) || CMD_IS_CUR(GSM_CMD_CGMM_GET) || CMD_IS_CUR(GSM_CMD_CGSN_GET) || CMD_IS_CUR(GSM_CMD_CGMR_GET)) - && !is_ok && !is_error && strncmp(rcv->data, "AT+", 3)) { - const char* tmp = rcv->data; - size_t tocopy; - if (CMD_IS_CUR(GSM_CMD_CGMI_GET)) { /* Check device manufacturer */ - gsmi_parse_string(&tmp, gsm.m.model_manufacturer, sizeof(gsm.m.model_manufacturer), 1); - if (CMD_IS_DEF(GSM_CMD_CGMI_GET)) { - tocopy = GSM_MIN(sizeof(gsm.m.model_manufacturer), gsm.msg->msg.device_info.len); - GSM_MEMCPY(gsm.msg->msg.device_info.str, gsm.m.model_manufacturer, tocopy); - gsm.msg->msg.device_info.str[tocopy - 1] = 0; - } - } else if (CMD_IS_CUR(GSM_CMD_CGMM_GET)) { /* Check device model number */ - gsmi_parse_string(&tmp, gsm.m.model_number, sizeof(gsm.m.model_number), 1); - if (CMD_IS_DEF(GSM_CMD_CGMM_GET)) { - tocopy = GSM_MIN(sizeof(gsm.m.model_number), gsm.msg->msg.device_info.len); - GSM_MEMCPY(gsm.msg->msg.device_info.str, gsm.m.model_number, tocopy); - gsm.msg->msg.device_info.str[tocopy - 1] = 0; - } - for (size_t i = 0; i < gsm_dev_model_map_size; i++) { - if (strstr(gsm.m.model_number, gsm_dev_model_map[i].id_str) != NULL) { - gsm.m.model = gsm_dev_model_map[i].model; - break; - } - } - } else if (CMD_IS_CUR(GSM_CMD_CGSN_GET)) { /* Check device serial number */ - gsmi_parse_string(&tmp, gsm.m.model_serial_number, sizeof(gsm.m.model_serial_number), 1); - if (CMD_IS_DEF(GSM_CMD_CGSN_GET)) { - tocopy = GSM_MIN(sizeof(gsm.m.model_serial_number), gsm.msg->msg.device_info.len); - GSM_MEMCPY(gsm.msg->msg.device_info.str, gsm.m.model_serial_number, tocopy); - gsm.msg->msg.device_info.str[tocopy - 1] = 0; - } - } else if (CMD_IS_CUR(GSM_CMD_CGMR_GET)) { /* Check device revision */ - if (!strncmp(tmp, "Revision:", 9)) { - tmp += 9; - } - gsmi_parse_string(&tmp, gsm.m.model_revision, sizeof(gsm.m.model_revision), 1); - if (CMD_IS_DEF(GSM_CMD_CGMR_GET)) { - tocopy = GSM_MIN(sizeof(gsm.m.model_revision), gsm.msg->msg.device_info.len); - GSM_MEMCPY(gsm.msg->msg.device_info.str, gsm.m.model_revision, tocopy); - gsm.msg->msg.device_info.str[tocopy - 1] = 0; - } - } - } else if (CMD_IS_CUR(GSM_CMD_CIFSR) && GSM_CHARISNUM(rcv->data[0])) { - const char* tmp = rcv->data; - gsmi_parse_ip(&tmp, &gsm.m.network.ip_addr);/* Parse IP address */ - - is_ok = 1; /* Manually set OK flag as we don't expect OK in CIFSR command */ - } - } - - /* Check general responses for active commands */ - if (gsm.msg != NULL) { - if (0) { -#if GSM_CFG_SMS - } else if (CMD_IS_CUR(GSM_CMD_CMGS) && is_ok) { - /* At this point we have to wait for "> " to send data */ -#endif /* GSM_CFG_SMS */ -#if GSM_CFG_CONN - } else if (CMD_IS_CUR(GSM_CMD_CIPSTATUS)) { - /* For CIPSTATUS, OK is returned before important data */ - if (is_ok) { - is_ok = 0; - } - /* Check if connection data received */ - if (rcv->len > 3) { - uint8_t continueScan, processed = 0; - if (rcv->data[0] == 'C' && rcv->data[1] == ':' && rcv->data[2] == ' ') { - processed = 1; - gsmi_parse_cipstatus_conn(rcv->data, 1, &continueScan); - - if (gsm.m.active_conns_cur_parse_num == (GSM_CFG_MAX_CONNS - 1)) { - is_ok = 1; - } - } else if (!strncmp(rcv->data, "STATE:", 6)) { - processed = 1; - gsmi_parse_cipstatus_conn(rcv->data, 0, &continueScan); - } - - /* Check if we shall stop processing at this stage */ - if (processed && !continueScan) { - is_ok = 1; - } - } - } else if (CMD_IS_CUR(GSM_CMD_CIPSTART)) { - /* For CIPSTART, OK is returned before important data */ - if (is_ok) { - is_ok = 0; - } - - /* Wait here for CONNECT status before we cancel connection */ - if (GSM_CHARISNUM(rcv->data[0]) - && rcv->data[1] == ',' && rcv->data[2] == ' ') { - uint8_t num = GSM_CHARTONUM(rcv->data[0]); - if (num < GSM_CFG_MAX_CONNS) { - uint8_t id; - gsm_conn_t* conn = &gsm.m.conns[num]; /* Get connection handle */ - - if (!strncmp(&rcv->data[3], "CONNECT OK" CRLF, 10 + CRLF_LEN)) { - id = conn->val_id; - GSM_MEMSET(conn, 0x00, sizeof(*conn)); /* Reset connection parameters */ - conn->num = num; - conn->status.f.active = 1; - conn->val_id = ++id; /* Set new validation ID */ - - /* Set connection parameters */ - conn->status.f.client = 1; - conn->evt_func = gsm.msg->msg.conn_start.evt_func; - conn->arg = gsm.msg->msg.conn_start.arg; - - /* Set status */ - gsm.msg->msg.conn_start.conn_res = GSM_CONN_CONNECT_OK; - is_ok = 1; - } else if (!strncmp(&rcv->data[3], "CONNECT FAIL" CRLF, 12 + CRLF_LEN)) { - gsm.msg->msg.conn_start.conn_res = GSM_CONN_CONNECT_ERROR; - is_error = 1; - } else if (!strncmp(&rcv->data[3], "ALREADY CONNECT" CRLF, 15 + CRLF_LEN)) { - gsm.msg->msg.conn_start.conn_res = GSM_CONN_CONNECT_ALREADY; - is_error = 1; - } - } - } - } else if (CMD_IS_CUR(GSM_CMD_CIPSEND)) { - if (is_ok) { - is_ok = 0; - } - gsmi_process_cipsend_response(rcv, &is_ok, &is_error); -#endif /* GSM_CFG_CONN */ -#if GSM_CFG_USSD - } else if (CMD_IS_CUR(GSM_CMD_CUSD)) { - /* OK is returned before +CUSD */ - /* Command is not finished yet, unless it was an ERROR */ - if (is_ok) { - is_ok = 0; - } - - /* Check for manual CUSTOM OK message */ - if (!strcmp(rcv->data, "CUSTOM_OK\r\n")) { - is_ok = 1; - } -#endif /* GSM_CFG_USSD */ - } - } - - /* - * In case of any of these events, simply release semaphore - * and proceed with next command - */ - if (is_ok || is_error) { - gsmr_t res = gsmOK; - if (gsm.msg != NULL) { /* Do we have active message? */ - res = gsmi_process_sub_cmd(gsm.msg, &is_ok, &is_error); - if (res != gsmCONT) { /* Shall we continue with next subcommand under this one? */ - if (is_ok) { /* Check OK status */ - res = gsm.msg->res = gsmOK; - } else { /* Or error status */ - res = gsm.msg->res = res; /* Set the error status */ - } - } else { - gsm.msg->i++; /* Number of continue calls */ - } - - /* - * When the command is finished, - * release synchronization semaphore - * from user thread and start with next command - */ - if (res != gsmCONT) { /* Do we have to continue to wait for command? */ - gsm_sys_sem_release(&gsm.sem_sync); /* Release semaphore */ - } - } - } -} - -#if !GSM_CFG_INPUT_USE_PROCESS || __DOXYGEN__ -/** - * \brief Process data from input buffer - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsmi_process_buffer(void) { - void* data; - size_t len; - - do { - /* - * Get length of linear memory in buffer - * we can process directly as memory - */ - len = gsm_buff_get_linear_block_read_length(&gsm.buff); - if (len > 0) { - /* - * Get memory address of first element - * in linear block of data to process - */ - data = gsm_buff_get_linear_block_read_address(&gsm.buff); - - /* Process actual received data */ - gsmi_process(data, len); - - /* - * Once data is processed, simply skip - * the buffer memory and start over - */ - gsm_buff_skip(&gsm.buff, len); - } - } while (len); - return gsmOK; -} -#endif /* !GSM_CFG_INPUT_USE_PROCESS || __DOXYGEN__ */ - -/** - * \brief Process input data received from GSM device - * \param[in] data: Pointer to data to process - * \param[in] data_len: Length of data to process in units of bytes - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsmi_process(const void* data, size_t data_len) { - uint8_t ch; - const uint8_t* d = data; - size_t d_len = data_len; - static uint8_t ch_prev1, ch_prev2; - static gsm_unicode_t unicode; - - /* Check status if device is available */ - if (!gsm.status.f.dev_present) { - return gsmERRNODEVICE; - } - - while (d_len) { /* Read entire set of characters from buffer */ - ch = *d++; /* Get next character */ - d_len--; /* Decrease remaining length */ - - if (0) { -#if GSM_CFG_CONN - } else if (gsm.m.ipd.read) { /* Read connection data */ - size_t len; - - if (gsm.m.ipd.buff != NULL) { /* Do we have active buffer? */ - gsm.m.ipd.buff->payload[gsm.m.ipd.buff_ptr] = ch; /* Save data character */ - } - gsm.m.ipd.buff_ptr++; - gsm.m.ipd.rem_len--; - - /* Try to read more data directly from buffer */ - len = GSM_MIN(d_len, GSM_MIN(gsm.m.ipd.rem_len, gsm.m.ipd.buff != NULL ? (gsm.m.ipd.buff->len - gsm.m.ipd.buff_ptr) : gsm.m.ipd.rem_len)); - GSM_DEBUGF(GSM_CFG_DBG_IPD | GSM_DBG_TYPE_TRACE, - "[IPD] New length to read: %d bytes\r\n", (int)len); - if (len > 0) { - if (gsm.m.ipd.buff != NULL) { /* Is buffer valid? */ - GSM_MEMCPY(&gsm.m.ipd.buff->payload[gsm.m.ipd.buff_ptr], d, len); - GSM_DEBUGF(GSM_CFG_DBG_IPD | GSM_DBG_TYPE_TRACE, - "[IPD] Bytes read: %d\r\n", (int)len); - } else { /* Simply skip the data in buffer */ - GSM_DEBUGF(GSM_CFG_DBG_IPD | GSM_DBG_TYPE_TRACE, - "[IPD] Bytes skipped: %d\r\n", (int)len); - } - d_len -= len; /* Decrease effective length */ - d += len; /* Skip remaining length */ - gsm.m.ipd.buff_ptr += len; /* Forward buffer pointer */ - gsm.m.ipd.rem_len -= len; /* Decrease remaining length */ - } - - /* Did we reach end of buffer or no more data? */ - if (gsm.m.ipd.rem_len == 0 || (gsm.m.ipd.buff != NULL && gsm.m.ipd.buff_ptr == gsm.m.ipd.buff->len)) { - gsmr_t res = gsmOK; - - /* Call user callback function with received data */ - if (gsm.m.ipd.buff != NULL) { /* Do we have valid buffer? */ - gsm.m.ipd.conn->total_recved += gsm.m.ipd.buff->tot_len;/* Increase number of bytes received */ - - /* - * Send data buffer to upper layer - * - * From this moment, user is responsible for packet - * buffer and must free it manually - */ - gsm.evt.type = GSM_EVT_CONN_RECV; - gsm.evt.evt.conn_data_recv.buff = gsm.m.ipd.buff; - gsm.evt.evt.conn_data_recv.conn = gsm.m.ipd.conn; - res = gsmi_send_conn_cb(gsm.m.ipd.conn, NULL); - - gsm_pbuf_free(gsm.m.ipd.buff); /* Free packet buffer at this point */ - GSM_DEBUGF(GSM_CFG_DBG_IPD | GSM_DBG_TYPE_TRACE, - "[IPD] Free packet buffer\r\n"); - if (res == gsmOKIGNOREMORE) { /* We should ignore more data */ - GSM_DEBUGF(GSM_CFG_DBG_IPD | GSM_DBG_TYPE_TRACE, - "[IPD] Ignoring more data from this IPD if available\r\n"); - gsm.m.ipd.buff = NULL; /* Set to NULL to ignore more data if possibly available */ - } - - /* - * Create new data packet if case if: - * - * - Previous one was successful and more data to read and - * - Connection is not in closing state - */ - if (gsm.m.ipd.buff != NULL && gsm.m.ipd.rem_len > 0 && !gsm.m.ipd.conn->status.f.in_closing) { - size_t new_len = GSM_MIN(gsm.m.ipd.rem_len, GSM_CFG_IPD_MAX_BUFF_SIZE); /* Calculate new buffer length */ - - GSM_DEBUGF(GSM_CFG_DBG_IPD | GSM_DBG_TYPE_TRACE, - "[IPD] Allocating new packet buffer of size: %d bytes\r\n", (int)new_len); - gsm.m.ipd.buff = gsm_pbuf_new(new_len); /* Allocate new packet buffer */ - - GSM_DEBUGW(GSM_CFG_DBG_IPD | GSM_DBG_TYPE_TRACE | GSM_DBG_LVL_WARNING, - gsm.m.ipd.buff == NULL, "[IPD] Buffer allocation failed for %d bytes\r\n", (int)new_len); - } else { - gsm.m.ipd.buff = NULL; /* Reset it */ - } - } - if (gsm.m.ipd.rem_len == 0) { /* Check if we read everything */ - gsm.m.ipd.buff = NULL; /* Reset buffer pointer */ - gsm.m.ipd.read = 0; /* Stop reading data */ - } - gsm.m.ipd.buff_ptr = 0; /* Reset input buffer pointer */ - } -#endif /* GSM_CFG_CONN */ - /* - * Check if operators scan command is active - * and if we are ready to read the incoming data - */ - } else if (CMD_IS_CUR(GSM_CMD_COPS_GET_OPT) && gsm.msg->msg.cops_scan.read) { - if (ch == '\n') { - gsm.msg->msg.cops_scan.read = 0; - } else { - gsmi_parse_cops_scan(ch, 0); /* Parse character by character */ - } -#if GSM_CFG_SMS - } else if (CMD_IS_CUR(GSM_CMD_CMGR) && gsm.msg->msg.sms_read.read) { - gsm_sms_entry_t* e = gsm.msg->msg.sms_read.entry; - if (gsm.msg->msg.sms_read.read == 2) { /* Read only if set to 2 */ - if (e != NULL) { /* Check if valid entry */ - if (e->length < (sizeof(e->data) - 1)) { - e->data[e->length++] = ch; - } - } else { - gsm.msg->msg.sms_read.read = 1; /* Read but ignore data */ - } - } - if (ch == '\n' && ch_prev1 == '\r') { - if (gsm.msg->msg.sms_read.read == 2) { - - } - gsm.msg->msg.sms_read.read = 0; - } - } else if (CMD_IS_CUR(GSM_CMD_CMGL) && gsm.msg->msg.sms_list.read) { - if (gsm.msg->msg.sms_list.read == 2) { - gsm_sms_entry_t* e = &gsm.msg->msg.sms_list.entries[gsm.msg->msg.sms_list.ei]; - if (e->length < (sizeof(e->data) - 1)) { - e->data[e->length++] = ch; - } - } - if (ch == '\n' && ch_prev1 == '\r') { - if (gsm.msg->msg.sms_list.read == 2) { - gsm.msg->msg.sms_list.ei++; /* Go to next entry */ - if (gsm.msg->msg.sms_list.er != NULL) { /* Check and update user variable */ - *gsm.msg->msg.sms_list.er = gsm.msg->msg.sms_list.ei; - } - } - gsm.msg->msg.sms_list.read = 0; - } -#endif /* GSM_CFG_SMS */ -#if GSM_CFG_USSD - } else if (CMD_IS_CUR(GSM_CMD_CUSD) && gsm.msg->msg.ussd.read) { - if (ch == '"') { - gsm.msg->msg.ussd.resp[gsm.msg->msg.ussd.resp_write_ptr] = 0; - gsm.msg->msg.ussd.quote_det = !gsm.msg->msg.ussd.quote_det; - } else if (gsm.msg->msg.ussd.quote_det) { - if (gsm.msg->msg.ussd.resp_write_ptr < gsm.msg->msg.ussd.resp_len) { - gsm.msg->msg.ussd.resp[gsm.msg->msg.ussd.resp_write_ptr++] = ch; - gsm.msg->msg.ussd.resp[gsm.msg->msg.ussd.resp_write_ptr] = 0; - } - } else if (ch == '\n' && ch_prev1 == '\r') { - /* End of reading, command finished! */ - /* Return OK at this point! */ - strcpy(recv_buff.data, "CUSTOM_OK\r\n"); - recv_buff.len = strlen(recv_buff.data); - gsmi_parse_received(&recv_buff); - } -#endif /* GSM_CFG_USSD */ - /* - * We are in command mode where we have to process byte by byte - * Simply check for ASCII and unicode format and process data accordingly - */ - } else { - gsmr_t res = gsmERR; - if (GSM_ISVALIDASCII(ch)) { /* Manually check if valid ASCII character */ - res = gsmOK; - unicode.t = 1; /* Manually set total to 1 */ - unicode.r = 0; /* Reset remaining bytes */ - } else if (ch >= 0x80) { /* Process only if more than ASCII can hold */ - res = gsmi_unicode_decode(&unicode, ch); /* Try to decode unicode format */ - } - - if (res == gsmERR) { /* In case of an ERROR */ - unicode.r = 0; - } - if (res == gsmOK) { /* Can we process the character(s) */ - if (unicode.t == 1) { /* Totally 1 character? */ - switch (ch) { - case '\n': - RECV_ADD(ch); /* Add character to input buffer */ - gsmi_parse_received(&recv_buff); /* Parse received string */ - RECV_RESET(); /* Reset received string */ - break; - default: - RECV_ADD(ch); /* Any ASCII valid character */ - break; - } - -#if GSM_CFG_CONN - /* Check if we have to read data */ - if (ch == '\n' && gsm.m.ipd.read) { - size_t len; - GSM_DEBUGF(GSM_CFG_DBG_IPD | GSM_DBG_TYPE_TRACE, - "[IPD] Data on connection %d with total size %d byte(s)\r\n", - (int)gsm.m.ipd.conn->num, (int)gsm.m.ipd.tot_len); - - len = GSM_MIN(gsm.m.ipd.rem_len, GSM_CFG_IPD_MAX_BUFF_SIZE); - - /* - * Read received data in case of: - * - * - Connection is active and - * - Connection is not in closing mode - */ - if (gsm.m.ipd.conn->status.f.active && !gsm.m.ipd.conn->status.f.in_closing) { - gsm.m.ipd.buff = gsm_pbuf_new(len); /* Allocate new packet buffer */ - GSM_DEBUGW(GSM_CFG_DBG_IPD | GSM_DBG_TYPE_TRACE | GSM_DBG_LVL_WARNING, gsm.m.ipd.buff == NULL, - "[IPD] Buffer allocation failed for %d byte(s)\r\n", (int)len); - } else { - gsm.m.ipd.buff = NULL; /* Ignore reading on closed connection */ - GSM_DEBUGF(GSM_CFG_DBG_IPD | GSM_DBG_TYPE_TRACE, - "[IPD] Connection %d closed or in closing, skipping %d byte(s)\r\n", - (int)gsm.m.ipd.conn->num, (int)len); - } - gsm.m.ipd.conn->status.f.data_received = 1; /* We have first received data */ - - gsm.m.ipd.buff_ptr = 0; /* Reset buffer write pointer */ - } -#endif /* GSM_CFG_CONN */ - - /* - * Do we have a special sequence "> "? - * - * Check if any command active which may expect that kind of response - */ - if (ch_prev2 == '\n' && ch_prev1 == '>' && ch == ' ') { - if (0) { -#if GSM_CFG_CONN - } else if (CMD_IS_CUR(GSM_CMD_CIPSEND)) { - RECV_RESET(); /* Reset received object */ - - /* Now actually send the data prepared before */ - AT_PORT_SEND_WITH_FLUSH(&gsm.msg->msg.conn_send.data[gsm.msg->msg.conn_send.ptr], gsm.msg->msg.conn_send.sent); - gsm.msg->msg.conn_send.wait_send_ok_err = 1; /* Now we are waiting for "SEND OK" or "SEND ERROR" */ -#endif /* GSM_CFG_CONN */ -#if GSM_CFG_SMS - } else if (CMD_IS_CUR(GSM_CMD_CMGS)) { /* Send SMS? */ - AT_PORT_SEND(gsm.msg->msg.sms_send.text, strlen(gsm.msg->msg.sms_send.text)); - AT_PORT_SEND_CTRL_Z(); - AT_PORT_SEND_FLUSH(); -#endif /* GSM_CFG_SMS */ - } - } else if (CMD_IS_CUR(GSM_CMD_COPS_GET_OPT)) { - if (RECV_LEN() > 5 && !strncmp(recv_buff.data, "+COPS:", 6)) { - RECV_RESET(); /* Reset incoming buffer */ - gsmi_parse_cops_scan(0, 1); /* Reset parser state */ - gsm.msg->msg.cops_scan.read = 1; /* Start reading incoming bytes */ - } -#if GSM_CFG_USSD - } else if (CMD_IS_CUR(GSM_CMD_CUSD)) { - if (RECV_LEN() > 5 && !strncmp(recv_buff.data, "+CUSD:", 6)) { - RECV_RESET(); /* Reset incoming buffer */ - gsm.msg->msg.ussd.read = 1; /* Start reading incoming bytes */ - } -#endif /* GSM_CFG_USSD */ - } - } else { /* We have sequence of unicode characters */ - /* - * Unicode sequence characters are not "meta" characters - * so it is safe to just add them to receive array without checking - * what are the actual values - */ - for (uint8_t i = 0; i < unicode.t; i++) { - RECV_ADD(unicode.ch[i]);/* Add character to receive array */ - } - } - } else if (res != gsmINPROG) { /* Not in progress? */ - RECV_RESET(); /* Invalid character in sequence */ - } - } - - ch_prev2 = ch_prev1; /* Save previous character as previous previous */ - ch_prev1 = ch; /* Set current as previous */ - } - return gsmOK; -} - -/* Temporary macros, only available for inside gsmi_process_sub_cmd function */ -/* Set new command, but first check for error on previous */ -#define SET_NEW_CMD_CHECK_ERROR(new_cmd) do { \ - if (!*(is_error)) { \ - n_cmd = (new_cmd); \ - } \ -} while (0) - -/* Set new command, ignore result of previous */ -#define SET_NEW_CMD(new_cmd) do { \ - n_cmd = (new_cmd); \ -} while (0) - -/** - * \brief Process current command with known execution status and start another if necessary - * \param[in] msg: Pointer to current message - * \param[in] is_ok: pointer to status whether last command result was OK - * \param[in] is_error: Pointer to status whether last command result was ERROR - * \return \ref gsmCONT if you sent more data and we need to process more data, \ref gsmOK on success, or \ref gsmERR on error - */ -static gsmr_t -gsmi_process_sub_cmd(gsm_msg_t* msg, uint8_t* is_ok, uint16_t* is_error) { - gsm_cmd_t n_cmd = GSM_CMD_IDLE; - if (CMD_IS_DEF(GSM_CMD_RESET)) { - switch (CMD_GET_CUR()) { /* Check current command */ - case GSM_CMD_RESET: { - gsmi_reset_everything(1); /* Reset everything */ - SET_NEW_CMD(GSM_CFG_AT_ECHO ? GSM_CMD_ATE1 : GSM_CMD_ATE0); /* Set ECHO mode */ - gsm_delay(5000); /* Delay for some time before we can continue after reset */ - break; - } - case GSM_CMD_ATE0: - case GSM_CMD_ATE1: SET_NEW_CMD(GSM_CMD_CFUN_SET); break; /* Set full functionality */ - case GSM_CMD_CFUN_SET: SET_NEW_CMD(GSM_CMD_CMEE_SET); break; /* Set detailed error reporting */ - case GSM_CMD_CMEE_SET: SET_NEW_CMD(GSM_CMD_CGMI_GET); break; /* Get manufacturer */ - case GSM_CMD_CGMI_GET: SET_NEW_CMD(GSM_CMD_CGMM_GET); break; /* Get model */ - case GSM_CMD_CGMM_GET: SET_NEW_CMD(GSM_CMD_CGSN_GET); break; /* Get product serial number */ - case GSM_CMD_CGSN_GET: SET_NEW_CMD(GSM_CMD_CGMR_GET); break; /* Get product revision */ - case GSM_CMD_CGMR_GET: { - /* - * At this point we have modem info. - * It is now time to send info to user - * to select between device drivers - */ - gsmi_send_cb(GSM_EVT_DEVICE_IDENTIFIED); - - SET_NEW_CMD(GSM_CMD_CREG_SET); /* Enable unsolicited code for CREG */ - break; - } - case GSM_CMD_CREG_SET: SET_NEW_CMD(GSM_CMD_CLCC_SET); break;/* Set call state */ - case GSM_CMD_CLCC_SET: SET_NEW_CMD(GSM_CMD_CPIN_GET); break;/* Get SIM state */ - case GSM_CMD_CPIN_GET: break; - default: break; - } - - /* Send event */ - if (n_cmd == GSM_CMD_IDLE) { - RESET_SEND_EVT(msg, gsmOK); - } - } else if (CMD_IS_DEF(GSM_CMD_COPS_GET)) { - if (CMD_IS_CUR(GSM_CMD_COPS_GET)) { - gsm.evt.evt.operator_current.operator_current = &gsm.m.network.curr_operator; - gsmi_send_cb(GSM_EVT_NETWORK_OPERATOR_CURRENT); - } - } else if (CMD_IS_DEF(GSM_CMD_COPS_GET_OPT)) { - if (CMD_IS_CUR(GSM_CMD_COPS_GET_OPT)) { - OPERATOR_SCAN_SEND_EVT(gsm.msg, *is_ok ? gsmOK : gsmERR); - } - } else if (CMD_IS_DEF(GSM_CMD_SIM_PROCESS_BASIC_CMDS)) { - switch (CMD_GET_CUR()) { - case GSM_CMD_CNUM: { /* Get own phone number */ - if (!*is_ok) { - /* Sometimes SIM is not ready just after PIN entered */ - if (msg->msg.sim_info.cnum_tries < 5) { - msg->msg.sim_info.cnum_tries++; - SET_NEW_CMD(GSM_CMD_CNUM); - gsm_delay(1000); - } - } - } - default: break; - } - } else if (CMD_IS_DEF(GSM_CMD_CPIN_SET)) { /* Set PIN code */ - switch (CMD_GET_CUR()) { - case GSM_CMD_CPIN_GET: { /* Get own phone number */ - if (*is_ok && gsm.m.sim.state == GSM_SIM_STATE_PIN) { - SET_NEW_CMD(GSM_CMD_CPIN_SET); /* Set command to write PIN */ - } else if (gsm.m.sim.state != GSM_SIM_STATE_READY) { - *is_ok = 0; - *is_error = 1; - } - break; - } - case GSM_CMD_CPIN_SET: { /* Set CPIN */ - if (*is_ok) { - gsm_delay(5000); /* Make delay to make sure SIM is ready */ - } - break; - } - default: - break; - } -#if GSM_CFG_SMS - } else if (CMD_IS_DEF(GSM_CMD_SMS_ENABLE)) { - switch (CMD_GET_CUR()) { - case GSM_CMD_CPMS_GET_OPT: SET_NEW_CMD(GSM_CMD_CPMS_GET); break; - case GSM_CMD_CPMS_GET: break; - default: break; - } - if (!*is_ok || n_cmd == GSM_CMD_IDLE) { /* Stop execution on any command */ - SET_NEW_CMD(GSM_CMD_IDLE); - gsm.m.sms.enabled = n_cmd == GSM_CMD_IDLE; /* Set enabled status */ - gsm.evt.evt.sms_enable.status = gsm.m.sms.enabled ? gsmOK : gsmERR; - gsmi_send_cb(GSM_EVT_SMS_ENABLE); /* Send to user */ - } - } else if (CMD_IS_DEF(GSM_CMD_CMGS)) { /* Send SMS default command */ - if (CMD_IS_CUR(GSM_CMD_CMGF) && *is_ok) { /* Set message format current command */ - SET_NEW_CMD(GSM_CMD_CMGS); /* Now send actual message */ - } - - /* Send event on finish */ - if (n_cmd == GSM_CMD_IDLE) { - SMS_SEND_SEND_EVT(gsm.msg, *is_ok ? gsmOK : gsmERR); - } - } else if (CMD_IS_DEF(GSM_CMD_CMGR)) { /* Read SMS message */ - if (CMD_IS_CUR(GSM_CMD_CPMS_GET) && *is_ok) { - SET_NEW_CMD(GSM_CMD_CPMS_SET); /* Set memory */ - } else if (CMD_IS_CUR(GSM_CMD_CPMS_SET) && *is_ok) { - SET_NEW_CMD(GSM_CMD_CMGF); /* Set text mode */ - } else if (CMD_IS_CUR(GSM_CMD_CMGF) && *is_ok) {/* Set message format current command*/ - SET_NEW_CMD(GSM_CMD_CMGR); /* Start message read */ - } else if (CMD_IS_CUR(GSM_CMD_CMGR) && *is_ok) { - msg->msg.sms_read.mem = gsm.m.sms.mem[0].current; /* Set current memory */ - } - - /* Send event on finish */ - if (n_cmd == GSM_CMD_IDLE) { - SMS_SEND_READ_EVT(gsm.msg, *is_ok ? gsmOK : gsmERR); - } - } else if (CMD_IS_DEF(GSM_CMD_CMGD)) { /* Delete SMS message*/ - if (CMD_IS_CUR(GSM_CMD_CPMS_GET) && *is_ok) { - SET_NEW_CMD(GSM_CMD_CPMS_SET); /* Set memory */ - } else if (CMD_IS_CUR(GSM_CMD_CPMS_SET) && *is_ok) { - SET_NEW_CMD(GSM_CMD_CMGD); /* Delete message */ - } - - /* Send event on finish */ - if (n_cmd == GSM_CMD_IDLE) { - SMS_SEND_DELETE_EVT(msg, *is_ok ? gsmOK : gsmERR); - } - } else if (CMD_IS_DEF(GSM_CMD_CMGDA)) { - if (CMD_IS_CUR(GSM_CMD_CMGF) && *is_ok) { - SET_NEW_CMD(GSM_CMD_CMGDA); /* Mass storage */ - } - } else if (CMD_IS_DEF(GSM_CMD_CMGL)) { /* List SMS messages */ - if (CMD_IS_CUR(GSM_CMD_CPMS_GET) && *is_ok) { - SET_NEW_CMD(GSM_CMD_CPMS_SET); /* Set memory */ - } else if (CMD_IS_CUR(GSM_CMD_CPMS_SET) && *is_ok) { - SET_NEW_CMD(GSM_CMD_CMGF); /* Set text format */ - } else if (CMD_IS_CUR(GSM_CMD_CMGF) && *is_ok) { - SET_NEW_CMD(GSM_CMD_CMGL); /* List messages */ - } - - /* Send event on finish */ - if (n_cmd == GSM_CMD_IDLE) { - SMS_SEND_LIST_EVT(msg, *is_ok ? gsmOK : gsmERR); - } - } else if (CMD_IS_DEF(GSM_CMD_CPMS_SET)) { /* Set preferred memory */ - if (CMD_IS_CUR(GSM_CMD_CPMS_GET) && *is_ok) { - SET_NEW_CMD(GSM_CMD_CPMS_SET); /* Now set the command */ - } -#endif /* GSM_CFG_SMS */ -#if GSM_CFG_CALL - } else if (CMD_IS_DEF(GSM_CMD_CALL_ENABLE)) { - gsm.m.call.enabled = *is_ok; /* Set enabled status */ - gsm.evt.evt.call_enable.res = gsm.m.call.enabled ? gsmOK : gsmERR; - gsmi_send_cb(GSM_EVT_CALL_ENABLE); /* Send to user */ -#endif /* GSM_CFG_CALL */ -#if GSM_CFG_PHONEBOOK - } else if (CMD_IS_DEF(GSM_CMD_PHONEBOOK_ENABLE)) { - gsm.m.pb.enabled = *is_ok; /* Set enabled status */ - gsm.evt.evt.pb_enable.res = gsm.m.pb.enabled ? gsmOK : gsmERR; - gsmi_send_cb(GSM_EVT_PB_ENABLE); /* Send to user */ - } else if (CMD_IS_DEF(GSM_CMD_CPBW_SET)) { /* Write phonebook entry */ - if (CMD_IS_CUR(GSM_CMD_CPBS_GET) && *is_ok) { /* Get current memory */ - SET_NEW_CMD(GSM_CMD_CPBS_SET); /* Set current memory */ - } else if (CMD_IS_CUR(GSM_CMD_CPBS_SET) && *is_ok) { - SET_NEW_CMD(GSM_CMD_CPBW_SET); /* Write entry to phonebook */ - } - } else if (CMD_IS_DEF(GSM_CMD_CPBR)) { - if (CMD_IS_CUR(GSM_CMD_CPBS_GET) && *is_ok) {/* Get current memory */ - SET_NEW_CMD(GSM_CMD_CPBS_SET); /* Set current memory */ - } else if (CMD_IS_CUR(GSM_CMD_CPBS_SET) && *is_ok) { - SET_NEW_CMD(GSM_CMD_CPBR); /* Read entries */ - } else if (CMD_IS_CUR(GSM_CMD_CPBR)) { - gsm.evt.evt.pb_list.mem = gsm.m.pb.mem.current; - gsm.evt.evt.pb_list.entries = gsm.msg->msg.pb_list.entries; - gsm.evt.evt.pb_list.size = gsm.msg->msg.pb_list.ei; - gsm.evt.evt.pb_list.res = *is_ok ? gsmOK : gsmERR; - gsmi_send_cb(GSM_EVT_PB_LIST); - } - } else if (CMD_IS_DEF(GSM_CMD_CPBF)) { - if (CMD_IS_CUR(GSM_CMD_CPBS_GET) && *is_ok) {/* Get current memory */ - SET_NEW_CMD(GSM_CMD_CPBS_SET); /* Set current memory */ - } else if (CMD_IS_CUR(GSM_CMD_CPBS_SET) && *is_ok) { - SET_NEW_CMD(GSM_CMD_CPBF); /* Read entries */ - } else if (CMD_IS_CUR(GSM_CMD_CPBF)) { - gsm.evt.evt.pb_search.mem = gsm.m.pb.mem.current; - gsm.evt.evt.pb_search.search = gsm.msg->msg.pb_search.search; - gsm.evt.evt.pb_search.entries = gsm.msg->msg.pb_search.entries; - gsm.evt.evt.pb_search.size = gsm.msg->msg.pb_search.ei; - gsm.evt.evt.pb_search.res = *is_ok ? gsmOK : gsmERR; - gsmi_send_cb(GSM_EVT_PB_SEARCH); - } -#endif /* GSM_CFG_PHONEBOOK */ -#if GSM_CFG_NETWORK - } if (CMD_IS_DEF(GSM_CMD_NETWORK_ATTACH)) { - switch (msg->i) { - case 0: SET_NEW_CMD_CHECK_ERROR(GSM_CMD_CGACT_SET_0); break; - case 1: SET_NEW_CMD(GSM_CMD_CGACT_SET_1); break; -#if GSM_CFG_NETWORK_IGNORE_CGACT_RESULT - case 2: SET_NEW_CMD(GSM_CMD_CGATT_SET_0); break; -#else /* GSM_CFG_NETWORK_IGNORE_CGACT_RESULT */ - case 2: SET_NEW_CMD_CHECK_ERROR(GSM_CMD_CGATT_SET_0); break; -#endif /* !GSM_CFG_NETWORK_IGNORE_CGACT_RESULT */ - case 3: SET_NEW_CMD(GSM_CMD_CGATT_SET_1); break; - case 4: SET_NEW_CMD_CHECK_ERROR(GSM_CMD_CIPSHUT); break; - case 5: SET_NEW_CMD_CHECK_ERROR(GSM_CMD_CIPMUX_SET); break; - case 6: SET_NEW_CMD_CHECK_ERROR(GSM_CMD_CIPRXGET_SET); break; - case 7: SET_NEW_CMD_CHECK_ERROR(GSM_CMD_CSTT_SET); break; - case 8: SET_NEW_CMD_CHECK_ERROR(GSM_CMD_CIICR); break; - case 9: SET_NEW_CMD_CHECK_ERROR(GSM_CMD_CIFSR); break; - case 10: SET_NEW_CMD(GSM_CMD_CIPSTATUS); break; - default: break; - } - } else if (CMD_IS_DEF(GSM_CMD_NETWORK_DETACH)) { - switch (msg->i) { - case 0: SET_NEW_CMD(GSM_CMD_CGATT_SET_0); break; - case 1: SET_NEW_CMD(GSM_CMD_CGACT_SET_0); break; -#if GSM_CFG_CONN - case 2: SET_NEW_CMD(GSM_CMD_CIPSTATUS); break; -#endif /* GSM_CFG_CONN */ - default: break; - } - if (!n_cmd) { - *is_ok = 1; - } -#endif /* GSM_CFG_NETWORK */ -#if GSM_CFG_CONN - } else if (CMD_IS_DEF(GSM_CMD_CIPSTART)) { - if (!msg->i && CMD_IS_CUR(GSM_CMD_CIPSTATUS)) { /* Was the current command status info? */ - if (*is_ok) { - SET_NEW_CMD(GSM_CMD_CIPSSL); /* Set SSL */ - } - } else if (msg->i == 1 && CMD_IS_CUR(GSM_CMD_CIPSSL)) { - SET_NEW_CMD(GSM_CMD_CIPSTART); /* Now actually start connection */ - } else if (msg->i == 2 && CMD_IS_CUR(GSM_CMD_CIPSTART)) { - SET_NEW_CMD(GSM_CMD_CIPSTATUS); /* Go to status mode */ - if (*is_error) { - msg->msg.conn_start.conn_res = GSM_CONN_CONNECT_ERROR; - } - } else if (msg->i == 3 && CMD_IS_CUR(GSM_CMD_CIPSTATUS)) { - /* After second CIP status, define what to do next */ - switch (msg->msg.conn_start.conn_res) { - case GSM_CONN_CONNECT_OK: { /* Successfully connected */ - gsm_conn_t* conn = &gsm.m.conns[msg->msg.conn_start.num]; /* Get connection number */ - - gsm.evt.type = GSM_EVT_CONN_ACTIVE; /* Connection just active */ - gsm.evt.evt.conn_active_close.client = 1; - gsm.evt.evt.conn_active_close.conn = conn; - gsm.evt.evt.conn_active_close.forced = 1; - gsmi_send_conn_cb(conn, NULL); - gsmi_conn_start_timeout(conn); /* Start connection timeout timer */ - break; - } - case GSM_CONN_CONNECT_ERROR: { /* Connection error */ - gsmi_send_conn_error_cb(msg, gsmERRCONNFAIL); - *is_error = 1; /* Manually set error */ - *is_ok = 0; /* Reset success */ - break; - } - default: { - /* Do nothing as of now */ - break; - } - } - } - } else if (CMD_IS_DEF(GSM_CMD_CIPCLOSE)) { - /* - * It is unclear in which state connection is when ERROR is received on close command. - * Stack checks if connection is closed before it allows and sends close command, - * however it was detected that no automatic close event has been received from device - * and AT+CIPCLOSE returned ERROR. - * - * Is it device firmware bug? - */ - if (CMD_IS_CUR(GSM_CMD_CIPCLOSE) && *is_error) { - /* Notify upper layer about failed close event */ - gsm.evt.type = GSM_EVT_CONN_CLOSE; - gsm.evt.evt.conn_active_close.conn = msg->msg.conn_close.conn; - gsm.evt.evt.conn_active_close.forced = 1; - gsm.evt.evt.conn_active_close.res = gsmERR; - gsm.evt.evt.conn_active_close.client = msg->msg.conn_close.conn->status.f.active && msg->msg.conn_close.conn->status.f.client; - gsmi_send_conn_cb(msg->msg.conn_close.conn, NULL); - } -#endif /* GSM_CFG_CONN */ -#if GSM_CFG_USSD - } else if (CMD_IS_DEF(GSM_CMD_CUSD)) { - if (CMD_IS_CUR(GSM_CMD_CUSD_GET)) { - if (*is_ok) { - SET_NEW_CMD(GSM_CMD_CUSD); /* Run next command */ - } - } - /* The rest is handled in one layer above */ -#endif /* GSM_CFG_USSD */ - } - - /* Check if new command was set for execution */ - if (n_cmd != GSM_CMD_IDLE) { - gsmr_t res; - msg->cmd = n_cmd; - if ((res = msg->fn(msg)) == gsmOK) { - return gsmCONT; - } else { - *is_ok = 0; - *is_error = 1; - return res; - } - } else { - msg->cmd = GSM_CMD_IDLE; - } - return *is_ok ? gsmOK : gsmERR; -} - -/** - * \brief Function to initialize every AT command - * \note Never call this function directly. Set as initialization function for command and use `msg->fn(msg)` - * \param[in] msg: Pointer to \ref gsm_msg_t with data - * \return Member of \ref gsmr_t enumeration - */ -gsmr_t -gsmi_initiate_cmd(gsm_msg_t* msg) { - switch (CMD_GET_CUR()) { /* Check current message we want to send over AT */ - case GSM_CMD_RESET: { /* Reset modem with AT commands */ - /* Try with hardware reset */ - if (gsm.ll.reset_fn != NULL && gsm.ll.reset_fn(1)) { - gsm_delay(2); - gsm.ll.reset_fn(0); - gsm_delay(500); - } - - /* Send manual AT command */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CFUN=1,1"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_RESET_DEVICE_FIRST_CMD: { /* First command for device driver specific reset */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_ATE0: - case GSM_CMD_ATE1: { - AT_PORT_SEND_BEGIN_AT(); - if (CMD_IS_CUR(GSM_CMD_ATE0)) { - AT_PORT_SEND_CONST_STR("E0"); - } else { - AT_PORT_SEND_CONST_STR("E1"); - } - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CMEE_SET: { /* Enable detailed error messages */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CMEE=1"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CLCC_SET: { /* Enable detailed call info */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CLCC=1"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CGMI_GET: { /* Get manufacturer */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CGMI"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CGMM_GET: { /* Get model */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CGMM"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CGSN_GET: { /* Get serial number */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CGSN"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CGMR_GET: { /* Get revision */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CGMR"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CREG_SET: { /* Enable +CREG message */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CREG=1"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CREG_GET: { /* Get network registration status */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CREG?"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CFUN_SET: { - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CFUN="); - /** - * \todo: If CFUN command forced, check value - */ - if (CMD_IS_DEF(GSM_CMD_RESET) - || (CMD_IS_DEF(GSM_CMD_CFUN_SET) && msg->msg.cfun.mode)) { - AT_PORT_SEND_CONST_STR("1"); - } else { - AT_PORT_SEND_CONST_STR("0"); - } - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CPIN_GET: { /* Read current SIM status */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CPIN?"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CPIN_SET: { /* Set SIM pin code */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CPIN="); - gsmi_send_string(msg->msg.cpin_enter.pin, 0, 1, 0); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CPIN_ADD: { /* Add new pin code */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CLCK=\"SC\",1,"); - gsmi_send_string(msg->msg.cpin_add.pin, 0, 1, 0); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CPIN_CHANGE: { /* Change already active SIM */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CPWD=\"SC\""); - gsmi_send_string(msg->msg.cpin_change.current_pin, 0, 1, 1); - gsmi_send_string(msg->msg.cpin_change.new_pin, 0, 1, 1); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CPIN_REMOVE: { /* Remove current PIN */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CLCK=\"SC\",0,"); - gsmi_send_string(msg->msg.cpin_remove.pin, 0, 1, 0); - AT_PORT_SEND_END_AT(); - break; - } - case GMM_CMD_CPUK_SET: { /* Enter PUK and set new PIN */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CPIN="); - gsmi_send_string(msg->msg.cpuk_enter.puk, 0, 1, 0); - gsmi_send_string(msg->msg.cpuk_enter.pin, 0, 1, 1); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_COPS_SET: { /* Set current operator */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+COPS="); - gsmi_send_number(GSM_U32(msg->msg.cops_set.mode), 0, 0); - if (msg->msg.cops_set.mode != GSM_OPERATOR_MODE_AUTO) { - gsmi_send_number(GSM_U32(msg->msg.cops_set.format), 0, 1); - switch (msg->msg.cops_set.format) { - case GSM_OPERATOR_FORMAT_LONG_NAME: - case GSM_OPERATOR_FORMAT_SHORT_NAME: - gsmi_send_string(msg->msg.cops_set.name, 1, 1, 1); - break; - default: - gsmi_send_number(GSM_U32(msg->msg.cops_set.num), 0, 1); - } - } - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_COPS_GET: { /* Get current operator */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+COPS?"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_COPS_GET_OPT: { /* Get list of available operators */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+COPS=?"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CSQ_GET: { /* Get signal strength */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CSQ"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CNUM: { /* Get SIM number */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CNUM"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CIPSHUT: { /* Shut down network connection and put to reset state */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CIPSHUT"); - AT_PORT_SEND_END_AT(); - break; - } -#if GSM_CFG_CONN - case GSM_CMD_CIPMUX: { /* Enable multiple connections */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CIPMUX=1"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CIPHEAD: { /* Enable information on receive data about connection and length */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CIPHEAD=1"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CIPSRIP: { - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CIPSRIP=1"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CIPSSL: { /* Set SSL configuration */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CIPSSL="); - gsmi_send_number((msg->msg.conn_start.type == GSM_CONN_TYPE_SSL) ? 1 : 0, 0, 0); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CIPSTART: { /* Start a new connection */ - gsm_conn_t* c = NULL; - - /* Do we have network connection? */ - /* Check if we are connected to network */ - - msg->msg.conn_start.num = 0; /* Start with max value = invalidated */ - for (int16_t i = GSM_CFG_MAX_CONNS - 1; i >= 0; i--) { /* Find available connection */ - if (!gsm.m.conns[i].status.f.active) { - c = &gsm.m.conns[i]; - c->num = GSM_U8(i); - msg->msg.conn_start.num = GSM_U8(i); /* Set connection number for message structure */ - break; - } - } - if (c == NULL) { - gsmi_send_conn_error_cb(msg, gsmERRNOFREECONN); - return gsmERRNOFREECONN; /* We don't have available connection */ - } - - if (msg->msg.conn_start.conn != NULL) { /* Is user interested about connection info? */ - *msg->msg.conn_start.conn = c; /* Save connection for user */ - } - - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CIPSTART="); - gsmi_send_number(GSM_U32(c->num), 0, 0); - if (msg->msg.conn_start.type == GSM_CONN_TYPE_TCP) { - gsmi_send_string("TCP", 0, 1, 1); - } else if (msg->msg.conn_start.type == GSM_CONN_TYPE_UDP) { - gsmi_send_string("UDP", 0, 1, 1); - } - gsmi_send_string(msg->msg.conn_start.host, 0, 1, 1); - gsmi_send_port(msg->msg.conn_start.port, 0, 1); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CIPCLOSE: { /* Close the connection */ - gsm_conn_p c = msg->msg.conn_close.conn; - if (c != NULL && - /* Is connection already closed or command for this connection is not valid anymore? */ - (!gsm_conn_is_active(c) || c->val_id != msg->msg.conn_close.val_id)) { - return gsmERR; - } - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CIPCLOSE="); - gsmi_send_number(GSM_U32(msg->msg.conn_close.conn ? msg->msg.conn_close.conn->num : GSM_CFG_MAX_CONNS), 0, 0); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CIPSEND: { /* Send data to connection */ - return gsmi_tcpip_process_send_data(); /* Process send data */ - } - case GSM_CMD_CIPSTATUS: { /* Get status of device and all connections */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CIPSTATUS"); - AT_PORT_SEND_END_AT(); - break; - } -#endif /* GSM_CFG_CONN */ -#if GSM_CFG_SMS - case GSM_CMD_CMGF: { /* Select SMS message format */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CMGF="); - if (CMD_IS_DEF(GSM_CMD_CMGS)) { - gsmi_send_number(GSM_U32(!!msg->msg.sms_send.format), 0, 0); - } else if (CMD_IS_DEF(GSM_CMD_CMGR)) { - gsmi_send_number(GSM_U32(!!msg->msg.sms_read.format), 0, 0); - } else if (CMD_IS_DEF(GSM_CMD_CMGL)) { - gsmi_send_number(GSM_U32(!!msg->msg.sms_list.format), 0, 0); - } else { - /* Used for all other operations like delete all messages, etc */ - AT_PORT_SEND_CONST_STR("1"); - } - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CMGS: { /* Send SMS */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CMGS="); - gsmi_send_string(msg->msg.sms_send.num, 0, 1, 0); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CMGR: { /* Read message */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CMGR="); - gsmi_send_number(GSM_U32(msg->msg.sms_read.pos), 0, 0); - gsmi_send_number(GSM_U32(!msg->msg.sms_read.update), 0, 1); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CMGD: { /* Delete SMS message */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CMGD="); - gsmi_send_number(GSM_U32(msg->msg.sms_delete.pos), 0, 0); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CMGDA: { /* Mass delete SMS messages */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CMGDA="); - switch (msg->msg.sms_delete_all.status) { - case GSM_SMS_STATUS_READ: gsmi_send_string("DEL READ", 0, 1, 0); break; - case GSM_SMS_STATUS_UNREAD: gsmi_send_string("DEL UNREAD", 0, 1, 0); break; - case GSM_SMS_STATUS_SENT: gsmi_send_string("DEL SENT", 0, 1, 0); break; - case GSM_SMS_STATUS_UNSENT: gsmi_send_string("DEL UNSENT", 0, 1, 0); break; - case GSM_SMS_STATUS_INBOX: gsmi_send_string("DEL INBOX", 0, 1, 0); break; - case GSM_SMS_STATUS_ALL: gsmi_send_string("DEL ALL", 0, 1, 0); break; - default: break; - } - AT_PORT_SEND_END_AT(); - break; - } - - case GSM_CMD_CMGL: { /* Delete SMS message */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CMGL="); - gsmi_send_sms_stat(msg->msg.sms_list.status, 1, 0); - gsmi_send_number(GSM_U32(!msg->msg.sms_list.update), 0, 1); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CPMS_GET_OPT: { /* Get available SMS storages */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CPMS=?"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CPMS_GET: { /* Get current SMS storage info */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CPMS?"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CPMS_SET: { /* Set active SMS storage(s) */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CPMS="); - if (CMD_IS_DEF(GSM_CMD_CMGR)) { /* Read SMS original command? */ - gsmi_send_dev_memory(msg->msg.sms_read.mem == GSM_MEM_CURRENT ? gsm.m.sms.mem[0].current : msg->msg.sms_read.mem, 1, 0); - } else if(CMD_IS_DEF(GSM_CMD_CMGD)) { /* Delete SMS original command? */ - gsmi_send_dev_memory(msg->msg.sms_delete.mem == GSM_MEM_CURRENT ? gsm.m.sms.mem[0].current : msg->msg.sms_delete.mem, 1, 0); - } else if(CMD_IS_DEF(GSM_CMD_CMGL)) { /* List SMS original command? */ - gsmi_send_dev_memory(msg->msg.sms_list.mem == GSM_MEM_CURRENT ? gsm.m.sms.mem[0].current : msg->msg.sms_list.mem, 1, 0); - } else if (CMD_IS_DEF(GSM_CMD_CPMS_SET)) { /* Do we want to set memory for read/delete,sent/write,receive? */ - for (size_t i = 0; i < 3; i++) {/* Write 3 memories */ - gsmi_send_dev_memory(msg->msg.sms_memory.mem[i] == GSM_MEM_CURRENT ? gsm.m.sms.mem[i].current : msg->msg.sms_memory.mem[i], 1, !!i); - } - } - AT_PORT_SEND_END_AT(); - break; - } -#endif /* GSM_CFG_SMS */ -#if GSM_CFG_CALL - case GSM_CMD_ATD: { /* Start new call */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("D"); - gsmi_send_string(msg->msg.call_start.number, 0, 0, 0); - AT_PORT_SEND_CONST_STR(";"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_ATA: { /* Answer phone call */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("A"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_ATH: { /* Disconnect existing connection (hang-up phone call) */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("H"); - AT_PORT_SEND_END_AT(); - break; - } -#endif /* GSM_CFG_CALL */ -#if GSM_CFG_PHONEBOOK - case GSM_CMD_CPBS_GET_OPT: { /* Get available phonebook storages */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CPBS=?"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CPBS_GET: { /* Get current memory info */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CPBS?"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CPBS_SET: { /* Get current memory info */ - gsm_mem_t mem; - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CPBS="); - switch (CMD_GET_DEF()) { - case GSM_CMD_CPBW_SET: mem = msg->msg.pb_write.mem; break; - case GSM_CMD_CPBR: mem = msg->msg.pb_list.mem; break; - case GSM_CMD_CPBF: mem = msg->msg.pb_search.mem; break; - default: break; - } - gsmi_send_dev_memory(mem == GSM_MEM_CURRENT ? gsm.m.pb.mem.current : mem, 1, 0); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CPBW_SET: { /* Write/Delete new/old entry */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CPBW="); - if (msg->msg.pb_write.pos > 0) { /* Write number if more than 0 */ - gsmi_send_number(GSM_U32(msg->msg.pb_write.pos), 0, 0); - } - if (!msg->msg.pb_write.del) { - gsmi_send_string(msg->msg.pb_write.num, 0, 1, 1); - gsmi_send_number(GSM_U32(msg->msg.pb_write.type), 0, 1); - gsmi_send_string(msg->msg.pb_write.name, 0, 1, 1); - } - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CPBR: { /* Read entires */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CPBR="); - gsmi_send_number(GSM_U32(msg->msg.pb_list.start_index), 0, 0); - gsmi_send_number(GSM_U32(msg->msg.pb_list.etr), 0, 1); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CPBF: { /* Find entires */ - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CPBF="); - gsmi_send_string(msg->msg.pb_search.search, 1, 1, 0); - AT_PORT_SEND_END_AT(); - break; - } -#endif /* GSM_CFG_PHONEBOOK */ -#if GSM_CFG_NETWORK - case GSM_CMD_NETWORK_ATTACH: - case GSM_CMD_CGACT_SET_0: { - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CGACT=0"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CGACT_SET_1: { - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CGACT=1"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_NETWORK_DETACH: - case GSM_CMD_CGATT_SET_0: { - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CGATT=0"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CGATT_SET_1: { - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CGATT=1"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CIPMUX_SET: { - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CIPMUX=1"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CIPRXGET_SET: { - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CIPRXGET=0"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CSTT_SET: { - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CSTT="); - gsmi_send_string(msg->msg.network_attach.apn, 1, 1, 0); - gsmi_send_string(msg->msg.network_attach.user, 1, 1, 1); - gsmi_send_string(msg->msg.network_attach.pass, 1, 1, 1); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CIICR: { - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CIICR"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CIFSR: { - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CIFSR"); - AT_PORT_SEND_END_AT(); - break; - } -#endif /* GSM_CFG_NETWORK */ -#if GSM_CFG_USSD - case GSM_CMD_CUSD_GET: { - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CUSD?"); - AT_PORT_SEND_END_AT(); - break; - } - case GSM_CMD_CUSD: { - AT_PORT_SEND_BEGIN_AT(); - AT_PORT_SEND_CONST_STR("+CUSD=1,"); - gsmi_send_string(msg->msg.ussd.code, 1, 1, 0); - AT_PORT_SEND_END_AT(); - break; - } -#endif /* GSM_CFG_USSD */ - default: - return gsmERR; /* Invalid command */ - } - return gsmOK; /* Valid command */ -} - -/** - * \brief Send message from API function to producer queue for further processing - * \param[in] msg: New message to process - * \param[in] process_fn: callback function used to process message - * \param[in] max_block_time: Maximal time command can block in units of milliseconds - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsmi_send_msg_to_producer_mbox(gsm_msg_t* msg, gsmr_t (*process_fn)(gsm_msg_t *), uint32_t max_block_time) { - gsmr_t res = msg->res = gsmOK; - - /* Check here if stack is even enabled or shall we disable new command entry? */ - gsm_core_lock(); - /* If locked more than 1 time, means we were called from callback or internally */ - if (gsm.locked_cnt > 1 && msg->is_blocking) { - res = gsmERRBLOCKING; /* Blocking mode not allowed */ - } - /* Check if device present */ - if (res == gsmOK && !gsm.status.f.dev_present) { - res = gsmERRNODEVICE; /* No device connected */ - } - gsm_core_unlock(); - if (res != gsmOK) { - GSM_MSG_VAR_FREE(msg); /* Free memory and return */ - return res; - } - - if (msg->is_blocking) { /* In case message is blocking */ - if (!gsm_sys_sem_create(&msg->sem, 0)) {/* Create semaphore and lock it immediatelly */ - GSM_MSG_VAR_FREE(msg); /* Release memory and return */ - return gsmERRMEM; - } - } - if (!msg->cmd) { /* Set start command if not set by user */ - msg->cmd = msg->cmd_def; /* Set it as default */ - } - msg->block_time = max_block_time; /* Set blocking status if necessary */ - msg->fn = process_fn; /* Save processing function to be called as callback */ - if (msg->is_blocking) { - gsm_sys_mbox_put(&gsm.mbox_producer, msg); /* Write message to producer queue and wait forever */ - } else { - if (!gsm_sys_mbox_putnow(&gsm.mbox_producer, msg)) { /* Write message to producer queue immediatelly */ - GSM_MSG_VAR_FREE(msg); /* Release message */ - return gsmERRMEM; - } - } - if (res == gsmOK && msg->is_blocking) { /* In case we have blocking request */ - uint32_t time; - time = gsm_sys_sem_wait(&msg->sem, 0); /* Wait forever for semaphore */ - if (time == GSM_SYS_TIMEOUT) { /* If semaphore was not accessed in given time */ - res = gsmTIMEOUT; /* Semaphore not released in time */ - } else { - res = msg->res; /* Set response status from message response */ - } - GSM_MSG_VAR_FREE(msg); /* Release message */ - } - return res; -} - -/** - * \brief Process events in case of timeout on command or invalid message (if device is not present) - * - * Function is called from processing thread: - * - * - On command timeout error - * - If command was sent to queue and before processed, device present status changed - * - * \param[in] msg: Current message - * \param[in] err: Error message to send - */ -void -gsmi_process_events_for_timeout_or_error(gsm_msg_t* msg, gsmr_t err) { - switch (msg->cmd_def) { - case GSM_CMD_RESET: { - /* Reset command error */ - RESET_SEND_EVT(msg, err); - break; - } - - case GSM_CMD_RESTORE: { - /* Restore command error */ - RESTORE_SEND_EVT(msg, err); - break; - } - - case GSM_CMD_COPS_GET_OPT: { - /* Operator scan command error */ - OPERATOR_SCAN_SEND_EVT(msg, err); - break; - } - -#if GSM_CFG_CONN - case GSM_CMD_CIPSTART: { - /* Start connection error */ - gsmi_send_conn_error_cb(msg, err); - break; - } - - case GSM_CMD_CIPSEND: { - /* Send data error event */ - CONN_SEND_DATA_SEND_EVT(msg, err); - break; - } -#endif /* GSM_CFG_CONN */ - -#if GSM_CFG_SMS - case GSM_CMD_CMGS: { - /* Send error event */ - SMS_SEND_SEND_EVT(msg, err); - break; - } - - case GSM_CMD_CMGR: { - /* Read error event */ - SMS_SEND_READ_EVT(msg, err); - break; - } - - case GSM_CMD_CMGL: { - /* List error event */ - SMS_SEND_LIST_EVT(msg, err); - break; - } - - case GSM_CMD_CMGD: { - /* Delete error event */ - SMS_SEND_DELETE_EVT(msg, err); - break; - } -#endif /* GSM_CFG_SMS */ - - default: break; - } -} diff --git a/gsm_at_lib/src/gsm/gsm_network.c b/gsm_at_lib/src/gsm/gsm_network.c deleted file mode 100644 index 1869942d..00000000 --- a/gsm_at_lib/src/gsm/gsm_network.c +++ /dev/null @@ -1,170 +0,0 @@ -/** - * \file gsm_network.c - * \brief Network API - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_network.h" -#include "gsm/gsm_mem.h" - -#if GSM_CFG_NETWORK || __DOXYGEN__ - -/** - * \brief Attach to network and active PDP context - * \param[in] apn: APN name - * \param[in] user: User name to attach. Set to `NULL` if not used - * \param[in] pass: User password to attach. Set to `NULL` if not used - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsm_network_attach(const char* apn, const char* user, const char* pass, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_NETWORK_ATTACH; -#if GSM_CFG_CONN - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CIPSTATUS; -#endif /* GSM_CFG_CONN */ - GSM_MSG_VAR_REF(msg).msg.network_attach.apn = apn; - GSM_MSG_VAR_REF(msg).msg.network_attach.user = user; - GSM_MSG_VAR_REF(msg).msg.network_attach.pass = pass; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 200000); -} - -/** - * \brief Detach from network - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsm_network_detach(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_NETWORK_DETACH; -#if GSM_CFG_CONN - /* GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CIPSTATUS; */ -#endif /* GSM_CFG_CONN */ - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); -} - -/** - * \brief Check network PDP status - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsm_network_check_status(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CIPSTATUS; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); -} - -/** - * \brief Copy IP address from internal value to user variable - * \param[out] ip: Pointer to output IP variable - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsm_network_copy_ip(gsm_ip_t* ip) { - if (gsm_network_is_attached()) { - gsm_core_lock(); - GSM_MEMCPY(ip, &gsm.m.network.ip_addr, sizeof(*ip)); - gsm_core_unlock(); - return gsmOK; - } - return gsmERR; -} - -/** - * \brief Check if device is attached to network and PDP context is active - * \return `1` on success, `0` otherwise - */ -uint8_t -gsm_network_is_attached(void) { - uint8_t res; - gsm_core_lock(); - res = GSM_U8(gsm.m.network.is_attached); - gsm_core_unlock(); - return res; -} - -#endif /* GSM_CFG_NETWORK || __DOXYGEN__ */ - -/** - * \brief Read RSSI signal from network operator - * \param[out] rssi: RSSI output variable. When set to `0`, RSSI is not valid - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsm_network_rssi(int16_t* rssi, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CSQ_GET; - GSM_MSG_VAR_REF(msg).msg.csq.rssi = rssi; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 120000); -} - -/** - * \brief Get network registration status - * \return Member of \ref gsm_network_reg_status_t enumeration - */ -gsm_network_reg_status_t -gsm_network_get_reg_status(void) { - gsm_network_reg_status_t ret; - gsm_core_lock(); - ret = gsm.m.network.status; - gsm_core_unlock(); - return ret; -} diff --git a/gsm_at_lib/src/gsm/gsm_phonebook.c b/gsm_at_lib/src/gsm/gsm_phonebook.c deleted file mode 100644 index e7e3b01f..00000000 --- a/gsm_at_lib/src/gsm/gsm_phonebook.c +++ /dev/null @@ -1,334 +0,0 @@ -/** - * \file gsm_phonebook.c - * \brief Phonebook API - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_phonebook.h" -#include "gsm/gsm_mem.h" - -#if GSM_CFG_PHONEBOOK || __DOXYGEN__ - -#if !__DOXYGEN__ -#define CHECK_ENABLED() if (!(check_enabled() == gsmOK)) { return gsmERRNOTENABLED; } -#endif /* !__DOXYGEN__ */ - -/** - * \brief Check if phonebook is enabled - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -static gsmr_t -check_enabled(void) { - gsmr_t res; - gsm_core_lock(); - res = gsm.m.pb.enabled ? gsmOK : gsmERR; - gsm_core_unlock(); - return res; -} - -/** - * \brief Check if input memory is available in modem - * \param[in] mem: Memory to test - * \param[in] can_curr: Flag indicates if \ref GSM_MEM_CURRENT option can be used - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -static gsmr_t -check_mem(gsm_mem_t mem, uint8_t can_curr) { - gsmr_t res = gsmERRMEM; - gsm_core_lock(); - if ((mem < GSM_MEM_END && gsm.m.pb.mem.mem_available & (1 << (uint32_t)mem)) || - (can_curr && mem == GSM_MEM_CURRENT)) { - res = gsmOK; - } - gsm_core_unlock(); - return res; -} - -/** - * \brief Enable phonebook functionality - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_pb_enable(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_PHONEBOOK_ENABLE; - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPBS_GET_OPT; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); -} - -/** - * \brief Disable phonebook functionality - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_pb_disable(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - gsm_core_lock(); - gsm.m.pb.enabled = 0; - if (evt_fn != NULL) { - evt_fn(gsmOK, evt_arg); - } - gsm_core_unlock(); - return gsmOK; -} - -/** - * \brief Add new phonebook entry to desired memory - * \param[in] mem: Memory to use to save entry. Use \ref GSM_MEM_CURRENT to use current memory - * \param[in] name: Entry name - * \param[in] num: Entry phone number - * \param[in] type: Entry phone number type - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_pb_add(gsm_mem_t mem, const char* name, const char* num, gsm_number_type_t type, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_ASSERT("name != NULL", name != NULL); - GSM_ASSERT("num != NULL", num != NULL); - CHECK_ENABLED(); /* Check if enabled */ - GSM_ASSERT("check_mem() == gsmOK", check_mem(mem, 1) == gsmOK); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CPBW_SET; - if (mem == GSM_MEM_CURRENT) { /* Should be always false */ - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPBS_GET;/* First get memory */ - } else { - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPBS_SET;/* First set memory */ - } - - GSM_MSG_VAR_REF(msg).msg.pb_write.pos = 0; - GSM_MSG_VAR_REF(msg).msg.pb_write.mem = mem; - GSM_MSG_VAR_REF(msg).msg.pb_write.name = name; - GSM_MSG_VAR_REF(msg).msg.pb_write.num = num; - GSM_MSG_VAR_REF(msg).msg.pb_write.type = type; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); -} - -/** - * \brief Read single phonebook entry - * \param[in] mem: Memory to use to save entry. Use \ref GSM_MEM_CURRENT to use current memory - * \param[in] pos: Entry position in memory to read - * \param[out] entry: Pointer to entry variable to save data - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_pb_read(gsm_mem_t mem, size_t pos, gsm_pb_entry_t* entry, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - return gsm_pb_list(mem, pos, entry, 1, NULL, evt_fn, evt_arg, blocking); -} - -/** - * \brief Edit or overwrite phonebook entry at desired memory and position - * \param[in] mem: Memory to use to save entry. Use \ref GSM_MEM_CURRENT to use current memory - * \param[in] pos: Entry position in memory to edit - * \param[in] name: New entry name - * \param[in] num: New entry phone number - * \param[in] type: New entry phone number type - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_pb_edit(gsm_mem_t mem, size_t pos, const char* name, const char* num, gsm_number_type_t type, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_ASSERT("name != NULL", name != NULL); - GSM_ASSERT("num != NULL", num != NULL); - CHECK_ENABLED(); /* Check if enabled */ - GSM_ASSERT("check_mem() == mem", check_mem(mem, 1) == gsmOK); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CPBW_SET; - if (mem == GSM_MEM_CURRENT) { /* Should be always false */ - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPBS_GET;/* First get memory */ - } else { - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPBS_SET;/* First set memory */ - } - - GSM_MSG_VAR_REF(msg).msg.pb_write.pos = pos; - GSM_MSG_VAR_REF(msg).msg.pb_write.mem = mem; - GSM_MSG_VAR_REF(msg).msg.pb_write.name = name; - GSM_MSG_VAR_REF(msg).msg.pb_write.num = num; - GSM_MSG_VAR_REF(msg).msg.pb_write.type = type; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); -} - -/** - * \brief Delete phonebook entry at desired memory and position - * \param[in] mem: Memory to use to save entry. Use \ref GSM_MEM_CURRENT to use current memory - * \param[in] pos: Entry position in memory to delete - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_pb_delete(gsm_mem_t mem, size_t pos, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_ASSERT("pos > 0", pos > 0); - CHECK_ENABLED(); /* Check if enabled */ - GSM_ASSERT("check_mem() == gsmOK", check_mem(mem, 1) == gsmOK); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CPBW_SET; - if (mem == GSM_MEM_CURRENT) { /* Should be always false */ - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPBS_GET; /* First get memory */ - } else { - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPBS_SET; /* First set memory */ - } - - GSM_MSG_VAR_REF(msg).msg.pb_write.mem = mem; - GSM_MSG_VAR_REF(msg).msg.pb_write.pos = pos; - GSM_MSG_VAR_REF(msg).msg.pb_write.del = 1; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); -} - -/** - * \brief List entires from specific memory - * \param[in] mem: Memory to use to save entry. Use \ref GSM_MEM_CURRENT to use current memory - * \param[in] start_index: Start position in memory to list - * \param[out] entries: Pointer to array to save entries - * \param[in] etr: Number of entries to read - * \param[out] er: Pointer to output variable to save entries listed - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_pb_list(gsm_mem_t mem, size_t start_index, gsm_pb_entry_t* entries, size_t etr, size_t* er, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_ASSERT("start_index", start_index); - GSM_ASSERT("entries != NULL", entries != NULL); - GSM_ASSERT("etr > 0", etr > 0); - CHECK_ENABLED(); - GSM_ASSERT("check_mem() == gsmOK", check_mem(mem, 1) == gsmOK); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - - if (er != NULL) { - *er = 0; - } - GSM_MEMSET(entries, 0x00, sizeof(*entries) * etr); /* Reset data structure */ - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CPBR; - if (mem == GSM_MEM_CURRENT) { /* Should be always false */ - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPBS_GET; /* First get memory */ - } else { - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPBS_SET; /* First set memory */ - } - - GSM_MSG_VAR_REF(msg).msg.pb_list.mem = mem; - GSM_MSG_VAR_REF(msg).msg.pb_list.start_index = start_index; - GSM_MSG_VAR_REF(msg).msg.pb_list.entries = entries; - GSM_MSG_VAR_REF(msg).msg.pb_list.etr = etr; - GSM_MSG_VAR_REF(msg).msg.pb_list.er = er; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); -} - -/** - * \brief Search for entires with specific name from specific memory - * \note Search works by entry name only. Phone number search is not available - * \param[in] mem: Memory to use to save entry. Use \ref GSM_MEM_CURRENT to use current memory - * \param[in] search: String to search for - * \param[out] entries: Pointer to array to save entries - * \param[in] etr: Number of entries to read - * \param[out] er: Pointer to output variable to save entries found - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_pb_search(gsm_mem_t mem, const char* search, gsm_pb_entry_t* entries, size_t etr, size_t* er, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_ASSERT("search != NULL", search != NULL); - GSM_ASSERT("entries != NULL", entries != NULL); - GSM_ASSERT("etr > 0", etr > 0); - CHECK_ENABLED(); /* Check if enabled */ - GSM_ASSERT("check_mem() == mem", check_mem(mem, 1) == gsmOK); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - - if (er != NULL) { - *er = 0; - } - GSM_MEMSET(entries, 0x00, sizeof(*entries) * etr); /* Reset data structure */ - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CPBF; - if (mem == GSM_MEM_CURRENT) { /* Should be always false */ - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPBS_GET; /* First get memory */ - } else { - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPBS_SET; /* First set memory */ - } - - GSM_MSG_VAR_REF(msg).msg.pb_search.mem = mem; - GSM_MSG_VAR_REF(msg).msg.pb_search.search = search; - GSM_MSG_VAR_REF(msg).msg.pb_search.entries = entries; - GSM_MSG_VAR_REF(msg).msg.pb_search.etr = etr; - GSM_MSG_VAR_REF(msg).msg.pb_search.er = er; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); -} - -#endif /* GSM_CFG_PHONEBOOK || __DOXYGEN__ */ diff --git a/gsm_at_lib/src/gsm/gsm_sim.c b/gsm_at_lib/src/gsm/gsm_sim.c deleted file mode 100644 index 371790ee..00000000 --- a/gsm_at_lib/src/gsm/gsm_sim.c +++ /dev/null @@ -1,174 +0,0 @@ -/** - * \file gsm_sim.c - * \brief SIM API - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_sim.h" -#include "gsm/gsm_mem.h" - -/** - * \brief Get current cached SIM state from stack - * \note Information is always valid, starting after successful device reset using \ref gsm_reset function call - * \return Member of \ref gsm_sim_state_t enumeration - */ -gsm_sim_state_t -gsm_sim_get_current_state(void) { - gsm_sim_state_t state; - gsm_core_lock(); - state = gsm.m.sim.state; - gsm_core_unlock(); - return state; -} - -/** - * \brief Enter pin code to unlock SIM - * \param[in] pin: Pin code in string format - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsm_sim_pin_enter(const char* pin, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_ASSERT("pin != NULL", pin != NULL); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CPIN_SET; - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPIN_GET; - GSM_MSG_VAR_REF(msg).msg.cpin_enter.pin = pin; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 30000); -} - -/** - * \brief Add pin number to open SIM card - * \note Use this function only if your SIM card doesn't have PIN code. - * If you wish to change current pin, use \ref gsm_sim_pin_change instead - * \param[in] pin: Current SIM pin code - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsm_sim_pin_add(const char* pin, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_ASSERT("pin != NULL", pin != NULL); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CPIN_ADD; - GSM_MSG_VAR_REF(msg).msg.cpin_add.pin = pin; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 10000); -} - -/** - * \brief Change current pin code - * \param[in] pin: Current pin code - * \param[in] new_pin: New pin code - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsm_sim_pin_change(const char* pin, const char* new_pin, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_ASSERT("pin != NULL", pin != NULL); - GSM_ASSERT("new_pin != NULL", new_pin != NULL); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CPIN_CHANGE; - GSM_MSG_VAR_REF(msg).msg.cpin_change.current_pin = pin; - GSM_MSG_VAR_REF(msg).msg.cpin_change.new_pin = new_pin; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 10000); -} - -/** - * \brief Remove pin code from SIM - * \param[in] pin: Current pin code - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsm_sim_pin_remove(const char* pin, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_ASSERT("pin != NULL", pin != NULL); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CPIN_REMOVE; - GSM_MSG_VAR_REF(msg).msg.cpin_remove.pin = pin; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 10000); -} - -/** - * \brief Enter PUK code and new PIN to unlock SIM card - * \param[in] puk: PUK code associated with SIM card - * \param[in] new_pin: New PIN code to use - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsm_sim_puk_enter(const char* puk, const char* new_pin, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_ASSERT("puk != NULL", puk != NULL); - GSM_ASSERT("new_pin != NULL", new_pin != NULL); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GMM_CMD_CPUK_SET; - GSM_MSG_VAR_REF(msg).msg.cpuk_enter.puk = puk; - GSM_MSG_VAR_REF(msg).msg.cpuk_enter.pin = new_pin; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 10000); -} diff --git a/gsm_at_lib/src/gsm/gsm_sms.c b/gsm_at_lib/src/gsm/gsm_sms.c deleted file mode 100644 index 39dd449d..00000000 --- a/gsm_at_lib/src/gsm/gsm_sms.c +++ /dev/null @@ -1,346 +0,0 @@ -/** - * \file gsm_sms.c - * \brief SMS API - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_sms.h" -#include "gsm/gsm_mem.h" - -#if GSM_CFG_SMS || __DOXYGEN__ - -#define GSM_SMS_OPERATION_IDX 0 /*!< Operation index for memory array (read, delete, list) */ -#define GSM_SMS_SEND_IDX 1 /*!< Send index for memory array */ -#define GSM_SMS_RECEIVE_IDX 2 /*!< Receive index for memory array */ - -#if !__DOXYGEN__ -#define CHECK_ENABLED() if (!(check_enabled() == gsmOK)) { return gsmERRNOTENABLED; } -#define CHECK_READY() if (!(check_ready() == gsmOK)) { return gsmERR; } -#endif /* !__DOXYGEN__ */ - -/** - * \brief Check if sms is enabled - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -static gsmr_t -check_enabled(void) { - gsmr_t res; - gsm_core_lock(); - res = gsm.m.sms.enabled ? gsmOK : gsmERR; - gsm_core_unlock(); - return res; -} - -/** - * \brief Check if SMS is available - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -static gsmr_t -check_ready(void) { - gsmr_t res; - gsm_core_lock(); - res = gsm.m.sms.ready ? gsmOK : gsmERR; - gsm_core_unlock(); - return res; -} - -/** - * \brief Check if input memory is available in modem - * \param[in] mem: Memory to test - * \param[in] can_curr: Flag indicates if \ref GSM_MEM_CURRENT option can be used - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -static gsmr_t -check_sms_mem(gsm_mem_t mem, uint8_t can_curr) { - gsmr_t res = gsmERRMEM; - gsm_core_lock(); - if ((mem < GSM_MEM_END && gsm.m.sms.mem[GSM_SMS_OPERATION_IDX].mem_available & (1 << (uint32_t)mem)) || - (can_curr && mem == GSM_MEM_CURRENT)) { - res = gsmOK; - } - gsm_core_unlock(); - return res; -} - -/** - * \brief Enable SMS functionality - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_sms_enable(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_SMS_ENABLE; - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPMS_GET_OPT; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); -} - -/** - * \brief Disable SMS functionality - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_sms_disable(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - gsm_core_lock(); - gsm.m.sms.enabled = 0; - if (evt_fn != NULL) { - evt_fn(gsmOK, evt_arg); - } - gsm_core_unlock(); - GSM_UNUSED(blocking); - return gsmOK; -} - -/** - * \brief Send SMS text to phone number - * \param[in] num: String number - * \param[in] text: Text to send. Maximal `160` characters - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_sms_send(const char* num, const char* text, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_ASSERT("num != NULL && num[0] > 0", num != NULL && num[0] > 0); - GSM_ASSERT("text != NULL && text[0] > 0 && strlen(text) <= 160", text != NULL && text[0] > 0 && strlen(text) <= 160); - CHECK_ENABLED(); /* Check if enabled */ - CHECK_READY(); /* Check if ready */ - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CMGS; - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CMGF; - GSM_MSG_VAR_REF(msg).msg.sms_send.num = num; - GSM_MSG_VAR_REF(msg).msg.sms_send.text = text; - GSM_MSG_VAR_REF(msg).msg.sms_send.format = 1; /* Send as plain text */ - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); -} - -/** - * \brief Read SMS entry at specific memory and position - * \param[in] mem: Memory used to read message from - * \param[in] pos: Position number in memory to read - * \param[out] entry: Pointer to SMS entry structure to fill data to - * \param[in] update: Flag indicates update. Set to `1` to change `UNREAD` messages to `READ` or `0` to leave as is - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_sms_read(gsm_mem_t mem, size_t pos, gsm_sms_entry_t* entry, uint8_t update, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_ASSERT("entry != NULL", entry != NULL); - CHECK_ENABLED(); /* Check if enabled */ - CHECK_READY(); /* Check if ready */ - GSM_ASSERT("check_sms_mem() == gsmOK", check_sms_mem(mem, 1) == gsmOK); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - - GSM_MEMSET(entry, 0x00, sizeof(*entry)); /* Reset data structure */ - - entry->mem = mem; /* Set memory */ - entry->pos = pos; /* Set device position */ - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CMGR; - if (mem == GSM_MEM_CURRENT) { /* Should be always false */ - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPMS_GET; /* First get memory */ - } else { - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPMS_SET; /* First set memory */ - } - GSM_MSG_VAR_REF(msg).msg.sms_read.mem = mem; - GSM_MSG_VAR_REF(msg).msg.sms_read.pos = pos; - GSM_MSG_VAR_REF(msg).msg.sms_read.entry = entry; - GSM_MSG_VAR_REF(msg).msg.sms_read.update = update; - GSM_MSG_VAR_REF(msg).msg.sms_read.format = 1; /* Send as plain text */ - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); -} - -/** - * \brief Delete SMS entry at specific memory and position - * \param[in] mem: Memory used to read message from - * \param[in] pos: Position number in memory to read - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_sms_delete(gsm_mem_t mem, size_t pos, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - CHECK_ENABLED(); /* Check if enabled */ - CHECK_READY(); /* Check if ready */ - GSM_ASSERT("check_sms_mem() == gsmOK", check_sms_mem(mem, 1) == gsmOK); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CMGD; - if (mem == GSM_MEM_CURRENT) { /* Should be always false */ - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPMS_GET; /* First get memory */ - } else { - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPMS_SET; /* First set memory */ - } - GSM_MSG_VAR_REF(msg).msg.sms_delete.mem = mem; - GSM_MSG_VAR_REF(msg).msg.sms_delete.pos = pos; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 1000); -} - -/** - * \brief Delete all SMS entries with specific status - * \param[in] status: SMS status. This parameter can be one of all possible types in \ref gsm_sms_status_t enumeration - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_sms_delete_all(gsm_sms_status_t status, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - CHECK_ENABLED(); /* Check if enabled */ - CHECK_READY(); /* Check if ready */ - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CMGDA; - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CMGF; /* By default format = 1 */ - GSM_MSG_VAR_REF(msg).msg.sms_delete_all.status = status; - - /* This command may take a while */ - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); -} - -/** - * \brief List SMS from SMS memory - * \param[in] mem: Memory to read entries from. Use \ref GSM_MEM_CURRENT to read from current memory - * \param[in] stat: SMS status to read, either `read`, `unread`, `sent`, `unsent` or `all` - * \param[out] entries: Pointer to array to save SMS entries - * \param[in] etr: Number of entries to read - * \param[out] er: Pointer to output variable to save number of entries in array - * \param[in] update: Flag indicates update. Set to `1` to change `UNREAD` messages to `READ` or `0` to leave as is - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_sms_list(gsm_mem_t mem, gsm_sms_status_t stat, gsm_sms_entry_t* entries, size_t etr, size_t* er, uint8_t update, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_ASSERT("entires != NULL", entries != NULL); - GSM_ASSERT("etr > 0", etr > 0); - CHECK_ENABLED(); /* Check if enabled */ - CHECK_READY(); /* Check if ready */ - GSM_ASSERT("check_sms_mem() == gsmOK", check_sms_mem(mem, 1) == gsmOK); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - - if (er != NULL) { - *er = 0; - } - GSM_MEMSET(entries, 0x00, sizeof(*entries) * etr); /* Reset data structure */ - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CMGL; - if (mem == GSM_MEM_CURRENT) { /* Should be always false */ - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPMS_GET; /* First get memory */ - } else { - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPMS_SET; /* First set memory */ - } - GSM_MSG_VAR_REF(msg).msg.sms_list.mem = mem; - GSM_MSG_VAR_REF(msg).msg.sms_list.status = stat; - GSM_MSG_VAR_REF(msg).msg.sms_list.entries = entries; - GSM_MSG_VAR_REF(msg).msg.sms_list.etr = etr; - GSM_MSG_VAR_REF(msg).msg.sms_list.er = er; - GSM_MSG_VAR_REF(msg).msg.sms_list.update = update; - GSM_MSG_VAR_REF(msg).msg.sms_list.format = 1; /* Send as plain text */ - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); -} - -/** - * \brief Set preferred storage for SMS - * \param[in] mem1: Preferred memory for read/delete SMS operations. Use \ref GSM_MEM_CURRENT to keep it as is - * \param[in] mem2: Preferred memory for sent/write SMS operations. Use \ref GSM_MEM_CURRENT to keep it as is - * \param[in] mem3: Preferred memory for received SMS entries. Use \ref GSM_MEM_CURRENT to keep it as is - * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used - * \param[in] evt_arg: Custom argument for event callback function - * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -gsmr_t -gsm_sms_set_preferred_storage(gsm_mem_t mem1, gsm_mem_t mem2, gsm_mem_t mem3, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - CHECK_ENABLED(); /* Check if enabled */ - CHECK_READY(); /* Check if ready */ - GSM_ASSERT("check_sms_mem(1) == gsmOK", check_sms_mem(mem1, 1) == gsmOK); - GSM_ASSERT("check_sms_mem(2) == gsmOK", check_sms_mem(mem2, 1) == gsmOK); - GSM_ASSERT("check_sms_mem(3) == gsmOK", check_sms_mem(mem3, 1) == gsmOK); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CPMS_SET; - - /* In case any of memories is set to current, read current status first from device */ - if (mem1 == GSM_MEM_CURRENT || mem2 == GSM_MEM_CURRENT || mem3 == GSM_MEM_CURRENT) { - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CPMS_GET; - } - GSM_MSG_VAR_REF(msg).msg.sms_memory.mem[0] = mem1; - GSM_MSG_VAR_REF(msg).msg.sms_memory.mem[1] = mem2; - GSM_MSG_VAR_REF(msg).msg.sms_memory.mem[2] = mem3; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); -} - -#endif /* GSM_CFG_SMS || __DOXYGEN__ */ diff --git a/gsm_at_lib/src/include/gsm/apps/gsm_mqtt_client_api.h b/gsm_at_lib/src/include/gsm/apps/gsm_mqtt_client_api.h deleted file mode 100644 index 4b3c4896..00000000 --- a/gsm_at_lib/src/include/gsm/apps/gsm_mqtt_client_api.h +++ /dev/null @@ -1,96 +0,0 @@ -/** - * \file gsm_mqtt_client_api.h - * \brief MQTT client API - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_APP_MQTT_CLIENT_API_H -#define GSM_HDR_APP_MQTT_CLIENT_API_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "gsm/gsm.h" -#include "gsm/apps/gsm_mqtt_client.h" - -/** - * \ingroup GSM_APPS - * \defgroup GSM_APP_MQTT_CLIENT_API MQTT client API - * \brief Sequential, single thread MQTT client API - * \{ - */ - -/** - * \brief MQTT API client structure - */ -struct gsm_mqtt_client_api; - -/** - * \brief MQTT API RX buffer - */ -typedef struct gsm_mqtt_client_api_buf { - char* topic; /*!< Topic data */ - size_t topic_len; /*!< Topic length */ - uint8_t* payload; /*!< Payload data */ - size_t payload_len; /*!< Payload length */ - gsm_mqtt_qos_t qos; /*!< Quality of service */ -} gsm_mqtt_client_api_buf_t; - -/** - * \brief Pointer to \ref gsm_mqtt_client_api structure - */ -typedef struct gsm_mqtt_client_api* gsm_mqtt_client_api_p; - -/** - * \brief Pointer to \ref gsm_mqtt_client_api_buf_t structure - */ -typedef struct gsm_mqtt_client_api_buf* gsm_mqtt_client_api_buf_p; - -gsm_mqtt_client_api_p gsm_mqtt_client_api_new(size_t tx_buff_len, size_t rx_buff_len); -void gsm_mqtt_client_api_delete(gsm_mqtt_client_api_p client); -gsm_mqtt_conn_status_t gsm_mqtt_client_api_connect(gsm_mqtt_client_api_p client, const char* host, gsm_port_t port, const gsm_mqtt_client_info_t* info); -gsmr_t gsm_mqtt_client_api_close(gsm_mqtt_client_api_p client); -gsmr_t gsm_mqtt_client_api_subscribe(gsm_mqtt_client_api_p client, const char* topic, gsm_mqtt_qos_t qos); -gsmr_t gsm_mqtt_client_api_unsubscribe(gsm_mqtt_client_api_p client, const char* topic); -gsmr_t gsm_mqtt_client_api_publish(gsm_mqtt_client_api_p client, const char* topic, const void* data, size_t btw, gsm_mqtt_qos_t qos, uint8_t retain); -uint8_t gsm_mqtt_client_api_is_connected(gsm_mqtt_client_api_p client); -gsmr_t gsm_mqtt_client_api_receive(gsm_mqtt_client_api_p client, gsm_mqtt_client_api_buf_p* p, uint32_t timeout); -void gsm_mqtt_client_api_buf_free(gsm_mqtt_client_api_buf_p p); - -/** - * \} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* GSM_HDR_APP_MQTT_CLIENT_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_conn.h b/gsm_at_lib/src/include/gsm/gsm_conn.h deleted file mode 100644 index d8864abf..00000000 --- a/gsm_at_lib/src/include/gsm/gsm_conn.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * \file gsm_conn.h - * \brief Connection API - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_CONN_H -#define GSM_HDR_CONN_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "gsm/gsm.h" - -/** - * \ingroup GSM - * \defgroup GSM_CONN Connection API - * \brief Connection API functions - * \{ - */ - -gsmr_t gsm_conn_start(gsm_conn_p* conn, gsm_conn_type_t type, const char* const host, gsm_port_t port, void* const arg, gsm_evt_fn conn_evt_fn, const uint32_t blocking); -gsmr_t gsm_conn_close(gsm_conn_p conn, const uint32_t blocking); -gsmr_t gsm_conn_send(gsm_conn_p conn, const void* data, size_t btw, size_t* const bw, const uint32_t blocking); -gsmr_t gsm_conn_sendto(gsm_conn_p conn, const gsm_ip_t* const ip, gsm_port_t port, const void* data, size_t btw, size_t* bw, const uint32_t blocking); -gsmr_t gsm_conn_set_arg(gsm_conn_p conn, void* const arg); -void * gsm_conn_get_arg(gsm_conn_p conn); -uint8_t gsm_conn_is_client(gsm_conn_p conn); -uint8_t gsm_conn_is_active(gsm_conn_p conn); -uint8_t gsm_conn_is_closed(gsm_conn_p conn); -int8_t gsm_conn_getnum(gsm_conn_p conn); -gsmr_t gsm_get_conns_status(const uint32_t blocking); -gsm_conn_p gsm_conn_get_from_evt(gsm_evt_t* evt); -gsmr_t gsm_conn_write(gsm_conn_p conn, const void* data, size_t btw, uint8_t flush, size_t* const mem_available); -gsmr_t gsm_conn_recved(gsm_conn_p conn, gsm_pbuf_p pbuf); -size_t gsm_conn_get_total_recved_count(gsm_conn_p conn); - -uint8_t gsm_conn_get_remote_ip(gsm_conn_p conn, gsm_ip_t* ip); -gsm_port_t gsm_conn_get_remote_port(gsm_conn_p conn); -gsm_port_t gsm_conn_get_local_port(gsm_conn_p conn); - -/** - * \} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* GSM_HDR_CONN_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_debug.h b/gsm_at_lib/src/include/gsm/gsm_debug.h deleted file mode 100644 index 6d4b6116..00000000 --- a/gsm_at_lib/src/include/gsm/gsm_debug.h +++ /dev/null @@ -1,130 +0,0 @@ -/** - * \file gsm_debug.h - * \brief Debugging inside GSM stack - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_DEBUG_H -#define GSM_HDR_DEBUG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -/** - * \ingroup GSM - * \defgroup GSM_DEBUG Debugging support - * \brief Debugging support module to track stack - * \{ - */ - -#define GSM_DBG_ON 0x80 /*!< Indicates debug is enabled */ -#define GSM_DBG_OFF 0 /*!< Indicates debug is disabled */ - -/** - * \anchor GSM_DBG_LVL - * \name Debug levels - * \brief List of debug levels - * \{ - */ - -#define GSM_DBG_LVL_ALL 0x00 /*!< Print all messages of all types */ -#define GSM_DBG_LVL_WARNING 0x01 /*!< Print warning and upper messages */ -#define GSM_DBG_LVL_DANGER 0x02 /*!< Print danger errors */ -#define GSM_DBG_LVL_SEVERE 0x03 /*!< Print severe problems affecting program flow */ -#define GSM_DBG_LVL_MASK 0x03 /*!< Mask for getting debug level */ - -/** - * \} - */ - -/** - * \anchor GSM_DBG_TYPE - * \name Debug types - * \brief List of possible debugging types - * \{ - */ - -#define GSM_DBG_TYPE_TRACE 0x40 /*!< Debug trace messages for program flow */ -#define GSM_DBG_TYPE_STATE 0x20 /*!< Debug state messages (such as state machines) */ -#define GSM_DBG_TYPE_ALL (GSM_DBG_TYPE_TRACE | GSM_DBG_TYPE_STATE) /*!< All debug types */ - -/** - * \} - */ - -#if GSM_CFG_DBG && !defined(GSM_CFG_DBG_OUT) -#warning "GSM_CFG_DBG_OUT is not defined but debugging is enabled!" -#endif - -#if (GSM_CFG_DBG && defined(GSM_CFG_DBG_OUT)) || __DOXYGEN__ -/** - * \brief Print message to the debug "window" if enabled - * \param[in] c: Condition if debug of specific type is enabled - * \param[in] fmt: Formatted string for debug - * \param[in] ...: Variable parameters for formatted string - */ -#define GSM_DEBUGF(c, fmt, ...) do {\ - if (((c) & (GSM_DBG_ON)) && ((c) & (GSM_CFG_DBG_TYPES_ON)) && ((c) & GSM_DBG_LVL_MASK) >= (GSM_CFG_DBG_LVL_MIN)) { \ - GSM_CFG_DBG_OUT(fmt, ## __VA_ARGS__); \ - } \ -} while (0) - -/** - * \brief Print message to the debug "window" if enabled when specific condition is met - * \param[in] c: Condition if debug of specific type is enabled - * \param[in] cond: Debug only if this condition is true - * \param[in] fmt: Formatted string for debug - * \param[in] ...: Variable parameters for formatted string - */ -#define GSM_DEBUGW(c, cond, fmt, ...) do {\ - if (cond) { \ - GSM_DEBUGF(c, fmt, ## __VA_ARGS__); \ - } \ -} while (0) -#else -#undef GSM_CFG_DBG -#define GSM_CFG_DBG GSM_DBG_OFF -#define GSM_DEBUGF(c, fmt, ...) -#define GSM_DEBUGW(c, cond, fmt, ...) -#endif /* (GSM_CFG_DBG && defined(GSM_CFG_DBG_OUT)) || __DOXYGEN__ */ - -/** - * \} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* GSM_HDR_DEBUG_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_evt.h b/gsm_at_lib/src/include/gsm/gsm_evt.h deleted file mode 100644 index 5dc5a5e2..00000000 --- a/gsm_at_lib/src/include/gsm/gsm_evt.h +++ /dev/null @@ -1,272 +0,0 @@ -/** - * \file gsm_evt.h - * \brief Event helper functions - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_EVT_H -#define GSM_HDR_EVT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "gsm/gsm.h" - -/** - * \ingroup GSM - * \defgroup GSM_EVT Events management - * \brief Event helper functions - * \{ - */ - -gsmr_t gsm_evt_register(gsm_evt_fn fn); -gsmr_t gsm_evt_unregister(gsm_evt_fn fn); -gsm_evt_type_t gsm_evt_get_type(gsm_evt_t* cc); - -/** - * \anchor GSM_EVT_RESET - * \name Reset event - * \brief Event helper functions for \ref GSM_EVT_RESET event - */ - -gsmr_t gsm_evt_reset_get_result(gsm_evt_t* cc); - -/** - * \} - */ - -/** - * \anchor GSM_EVT_RESTORE - * \name Restore event - * \brief Event helper functions for \ref GSM_EVT_RESTORE event - */ - -gsmr_t gsm_evt_restore_get_result(gsm_evt_t* cc); - -/** - * \} - */ - -/** - * \anchor GSM_EVT_NETWORK_OPERATOR_CURRENT - * \name Current network operator - * \brief Event helper functions for \ref GSM_EVT_NETWORK_OPERATOR_CURRENT event - */ - -const gsm_operator_curr_t* gsm_evt_network_operator_get_current(gsm_evt_t* cc); - -/** - * \} - */ - -/** - * \anchor GSM_EVT_CONN_RECV - * \name Connection data received - * \brief Event helper functions for \ref GSM_EVT_CONN_RECV event - */ - -gsm_pbuf_p gsm_evt_conn_recv_get_buff(gsm_evt_t* cc); -gsm_conn_p gsm_evt_conn_recv_get_conn(gsm_evt_t* cc); - -/** - * \} - */ - -/** - * \anchor GSM_EVT_CONN_SEND - * \name Connection data send - * \brief Event helper functions for \ref GSM_EVT_CONN_SEND event - */ - -gsm_conn_p gsm_evt_conn_send_get_conn(gsm_evt_t* cc); -size_t gsm_evt_conn_send_get_length(gsm_evt_t* cc); -gsmr_t gsm_evt_conn_send_get_result(gsm_evt_t* cc); - -/** - * \} - */ - -/** - * \anchor GSM_EVT_CONN_ACTIVE - * \name Connection active - * \brief Event helper functions for \ref GSM_EVT_CONN_ACTIVE event - */ - -gsm_conn_p gsm_evt_conn_active_get_conn(gsm_evt_t* cc); -uint8_t gsm_evt_conn_active_is_client(gsm_evt_t* cc); - -/** - * \} - */ - -/** - * \anchor GSM_EVT_CONN_CLOSE - * \name Connection close event - * \brief Event helper functions for \ref GSM_EVT_CONN_CLOSE event - */ - -gsm_conn_p gsm_evt_conn_close_get_conn(gsm_evt_t* cc); -uint8_t gsm_evt_conn_close_is_client(gsm_evt_t* cc); -uint8_t gsm_evt_conn_close_is_forced(gsm_evt_t* cc); -gsmr_t gsm_evt_conn_close_get_result(gsm_evt_t* cc); - -/** - * \} - */ - -/** - * \anchor GSM_EVT_CONN_POLL - * \name Connection poll - * \brief Event helper functions for \ref GSM_EVT_CONN_POLL event - */ - -gsm_conn_p gsm_evt_conn_poll_get_conn(gsm_evt_t* cc); - -/** - * \} - */ - -/** - * \anchor GSM_EVT_CONN_ERROR - * \name Connection error - * \brief Event helper functions for \ref GSM_EVT_CONN_ERROR event - */ - -gsmr_t gsm_evt_conn_error_get_error(gsm_evt_t* cc); -gsm_conn_type_t gsm_evt_conn_error_get_type(gsm_evt_t* cc); -const char* gsm_evt_conn_error_get_host(gsm_evt_t* cc); -gsm_port_t gsm_evt_conn_error_get_port(gsm_evt_t* cc); -void* gsm_evt_conn_error_get_arg(gsm_evt_t* cc); - -/** - * \} - */ - -/** - * \anchor GSM_EVT_SIGNAL_STRENGTH - * \name Signal strength - * \brief Event helper functions for \ref GSM_EVT_CONN_RECV event - */ - -int16_t gsm_evt_signal_strength_get_rssi(gsm_evt_t* cc); - -/** - * \} - */ - -/** - * \anchor GSM_EVT_SMS_RECV - * \name SMS received - * \brief Event helper functions for \ref GSM_EVT_SMS_RECV event - */ - -size_t gsm_evt_sms_recv_get_pos(gsm_evt_t* cc); -gsm_mem_t gsm_evt_sms_recv_get_mem(gsm_evt_t* cc); - -/** - * \} - */ - -/** - * \anchor GSM_EVT_SMS_READ - * \name SMS content read - * \brief Event helper functions for \ref GSM_EVT_SMS_READ event - */ - -gsm_sms_entry_t* gsm_evt_sms_read_get_entry(gsm_evt_t* cc); -gsmr_t gsm_evt_sms_read_get_result(gsm_evt_t* cc); - -/** - * \} - */ - -/** - * \anchor GSM_EVT_SMS_SEND - * \name SMS send - * \brief Event helper functions for \ref GSM_EVT_SMS_SEND event - */ - -gsmr_t gsm_evt_sms_send_get_result(gsm_evt_t* cc); -size_t gsm_evt_sms_send_get_pos(gsm_evt_t* cc); - -/** - * \} - */ - -/** - * \anchor GSM_EVT_SMS_DELETE - * \name SMS delete - * \brief Event helper functions for \ref GSM_EVT_SMS_DELETE event - */ - -gsmr_t gsm_evt_sms_delete_get_result(gsm_evt_t* cc); -size_t gsm_evt_sms_delete_get_pos(gsm_evt_t* cc); -gsm_mem_t gsm_evt_sms_delete_get_mem(gsm_evt_t* cc); - -/** - * \} - */ - -/** - * \anchor GSM_EVT_CALL_CHANGED - * \name Call status changed - * \brief Event helper functions for \ref GSM_EVT_CALL_CHANGED event - */ - -const gsm_call_t* gsm_evt_call_changed_get_call(gsm_evt_t* cc); - -/** - * \} - */ - -/** - * \anchor GSM_EVT_OPERATOR_SCAN - * \name Operator scan - * \brief Event helper functions for \ref GSM_EVT_OPERATOR_SCAN event - */ - -gsmr_t gsm_evt_operator_scan_get_result(gsm_evt_t* cc); -gsm_operator_t* gsm_evt_operator_scan_get_entries(gsm_evt_t* cc); -size_t gsm_evt_operator_scan_get_length(gsm_evt_t* cc); - -/** - * \} - */ - -/** - * \} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* GSM_HDR_EVT_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_includes.h b/gsm_at_lib/src/include/gsm/gsm_includes.h deleted file mode 100644 index a3a5fa0b..00000000 --- a/gsm_at_lib/src/include/gsm/gsm_includes.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * \file gsm_includes.h - * \brief All main includes - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_INCLUDES_H -#define GSM_HDR_INCLUDES_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include "gsm_config.h" -#include "gsm/gsm_typedefs.h" -#include "gsm/gsm_buff.h" -#include "gsm/gsm_input.h" -#include "gsm/gsm_debug.h" -#include "gsm/gsm_utils.h" -#include "gsm/gsm_pbuf.h" -#include "gsm/gsm_sim.h" -#include "gsm/gsm_operator.h" -#include "gsm/gsm_evt.h" -#include "gsm/gsm_network.h" -#include "gsm/gsm_device_info.h" -#include "system/gsm_sys.h" - -#if GSM_CFG_SMS || __DOXYGEN__ -#include "gsm/gsm_sms.h" -#endif /* GSM_CFG_SMS || __DOXYGEN__ */ -#if GSM_CFG_CALL || __DOXYGEN__ -#include "gsm/gsm_call.h" -#endif /* GSM_CFG_CALL || __DOXYGEN__ */ -#if GSM_CFG_PHONEBOOK || __DOXYGEN__ -#include "gsm/gsm_phonebook.h" -#endif /* GSM_CFG_PHONEBOOK || __DOXYGEN__ */ -#if GSM_CFG_CONN || __DOXYGEN__ -#include "gsm/gsm_conn.h" -#endif /* GSM_CFG_CONN || __DOXYGEN__ */ -#if GSM_CFG_NETCONN || __DOXYGEN__ -#include "gsm/gsm_netconn.h" -#endif /* GSM_CFG_NETCONN || __DOXYGEN__ */ -#if GSM_CFG_USSD || __DOXYGEN__ -#include "gsm/gsm_ussd.h" -#endif /* GSM_CFG_USSD || __DOXYGEN__ */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* GSM_HDR_INCLUDES_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_netconn.h b/gsm_at_lib/src/include/gsm/gsm_netconn.h deleted file mode 100644 index 9d0dc870..00000000 --- a/gsm_at_lib/src/include/gsm/gsm_netconn.h +++ /dev/null @@ -1,91 +0,0 @@ -/** - * \file gsm_netconn.h - * \brief API functions for sequential calls - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_NETCONN_H -#define GSM_HDR_NETCONN_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include "gsm/gsm.h" - -/** - * \ingroup GSM_API - * \defgroup GSM_NETCONN Network connection - * \brief Network connection - * \{ - */ - -struct gsm_netconn; - -/** - * \brief Netconn object structure - */ -typedef struct gsm_netconn* gsm_netconn_p; - -/** - * \brief Netconn connection type - */ -typedef enum { - GSM_NETCONN_TYPE_TCP = GSM_CONN_TYPE_TCP, /*!< TCP connection */ - GSM_NETCONN_TYPE_UDP = GSM_CONN_TYPE_UDP, /*!< UDP connection */ - GSM_NETCONN_TYPE_SSL = GSM_CONN_TYPE_SSL, /*!< TCP connection over SSL */ -} gsm_netconn_type_t; - -gsm_netconn_p gsm_netconn_new(gsm_netconn_type_t type); -gsmr_t gsm_netconn_delete(gsm_netconn_p nc); -gsmr_t gsm_netconn_connect(gsm_netconn_p nc, const char* host, gsm_port_t port); -gsmr_t gsm_netconn_receive(gsm_netconn_p nc, gsm_pbuf_p* pbuf); -gsmr_t gsm_netconn_close(gsm_netconn_p nc); -int8_t gsm_netconn_getconnnum(gsm_netconn_p nc); -void gsm_netconn_set_receive_timeout(gsm_netconn_p nc, uint32_t timeout); -uint32_t gsm_netconn_get_receive_timeout(gsm_netconn_p nc); - -/* TCP only */ -gsmr_t gsm_netconn_write(gsm_netconn_p nc, const void* data, size_t btw); -gsmr_t gsm_netconn_flush(gsm_netconn_p nc); - -/* UDP only */ -gsmr_t gsm_netconn_send(gsm_netconn_p nc, const void* data, size_t btw); -gsmr_t gsm_netconn_sendto(gsm_netconn_p nc, const gsm_ip_t* ip, gsm_port_t port, const void* data, size_t btw); - -/** - * \} - */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* GSM_HDR_NETCONN_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_parser.h b/gsm_at_lib/src/include/gsm/gsm_parser.h deleted file mode 100644 index d772e7ae..00000000 --- a/gsm_at_lib/src/include/gsm/gsm_parser.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * \file gsm_parser.h - * \brief Parser of AT responses - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_PARSER_H -#define GSM_HDR_PARSER_H - -#if defined(__cplusplus) -extern "C" { -#endif /* defined(__cplusplus) */ - -#include "gsm/gsm.h" - -int32_t gsmi_parse_number(const char** str); -uint8_t gsmi_parse_string(const char** src, char* dst, size_t dst_len, uint8_t trim); -uint8_t gsmi_parse_ip(const char** src, gsm_ip_t* ip); -uint8_t gsmi_parse_mac(const char** src, gsm_mac_t* mac); - -uint8_t gsmi_parse_cpin(const char* str, uint8_t send_evt); -uint8_t gsmi_parse_creg(const char* str, uint8_t skip_first); -uint8_t gsmi_parse_csq(const char* str); - -uint8_t gsmi_parse_cmgs(const char* str, size_t* num); -uint8_t gsmi_parse_cmti(const char* str, uint8_t send_evt); -uint8_t gsmi_parse_cmgr(const char* str); -uint8_t gsmi_parse_cmgl(const char* str); - -uint8_t gsmi_parse_at_sdk_version(const char* str, uint32_t* version_out); - -uint8_t gsmi_parse_cops_scan(uint8_t ch, uint8_t reset); -uint8_t gsmi_parse_cops(const char* str); -uint8_t gsmi_parse_clcc(const char* str, uint8_t send_evt); - -uint8_t gsmi_parse_cpbs(const char* str, uint8_t opt); -uint8_t gsmi_parse_cpms(const char* str, uint8_t opt); -uint8_t gsmi_parse_cpbr(const char* str); -uint8_t gsmi_parse_cpbf(const char* str); - -uint8_t gsmi_parse_cipstatus_conn(const char* str, uint8_t is_conn_line, uint8_t* continueScan); - -uint8_t gsmi_parse_ipd(const char* str); - -#if defined(__cplusplus) -} -#endif /* defined(__cplusplus) */ - -#endif /* GSM_HDR_PARSER_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_pbuf.h b/gsm_at_lib/src/include/gsm/gsm_pbuf.h deleted file mode 100644 index 1942c37d..00000000 --- a/gsm_at_lib/src/include/gsm/gsm_pbuf.h +++ /dev/null @@ -1,82 +0,0 @@ -/** - * \file gsm_pbuf.h - * \brief Packet buffer manager - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_PBUF_H -#define GSM_HDR_PBUF_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "gsm/gsm.h" - -/** - * \ingroup GSM - * \defgroup GSM_PBUF Packet buffer - * \brief Packet buffer manager - * \{ - */ - -gsm_pbuf_p gsm_pbuf_new(size_t len); -size_t gsm_pbuf_free(gsm_pbuf_p pbuf); -void * gsm_pbuf_data(const gsm_pbuf_p pbuf); -size_t gsm_pbuf_length(const gsm_pbuf_p pbuf, uint8_t tot); -gsmr_t gsm_pbuf_take(gsm_pbuf_p pbuf, const void* data, size_t len, size_t offset); -size_t gsm_pbuf_copy(gsm_pbuf_p pbuf, void* data, size_t len, size_t offset); - -gsmr_t gsm_pbuf_cat(gsm_pbuf_p head, const gsm_pbuf_p tail); -gsmr_t gsm_pbuf_chain(gsm_pbuf_p head, gsm_pbuf_p tail); -gsmr_t gsm_pbuf_ref(gsm_pbuf_p pbuf); - -uint8_t gsm_pbuf_get_at(const gsm_pbuf_p pbuf, size_t pos, uint8_t* el); -size_t gsm_pbuf_memcmp(const gsm_pbuf_p pbuf, const void* data, size_t len, size_t offset); -size_t gsm_pbuf_strcmp(const gsm_pbuf_p pbuf, const char* str, size_t offset); -size_t gsm_pbuf_memfind(const gsm_pbuf_p pbuf, const void* data, size_t len, size_t off); -size_t gsm_pbuf_strfind(const gsm_pbuf_p pbuf, const char* str, size_t off); - -uint8_t gsm_pbuf_advance(gsm_pbuf_p pbuf, int len); -gsm_pbuf_p gsm_pbuf_skip(gsm_pbuf_p pbuf, size_t offset, size_t* new_offset); - -void * gsm_pbuf_get_linear_addr(const gsm_pbuf_p pbuf, size_t offset, size_t* new_len); - -void gsm_pbuf_set_ip(gsm_pbuf_p pbuf, const gsm_ip_t* ip, gsm_port_t port); - -/** - * \} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* GSM_HDR_PBUF_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_phonebook.h b/gsm_at_lib/src/include/gsm/gsm_phonebook.h deleted file mode 100644 index b2a902e1..00000000 --- a/gsm_at_lib/src/include/gsm/gsm_phonebook.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * \file gsm_phonebook.h - * \brief Phonebook API - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_PHONEBOOK_H -#define GSM_HDR_PHONEBOOK_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "gsm/gsm.h" - -/** - * \ingroup GSM - * \defgroup GSM_PHONEBOOK Phonebook API - * \brief Phonebook manager - * \{ - */ - -gsmr_t gsm_pb_enable(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_pb_disable(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); - -gsmr_t gsm_pb_add(gsm_mem_t mem, const char* name, const char* num, gsm_number_type_t type, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_pb_edit(gsm_mem_t mem, size_t pos, const char* name, const char* num, gsm_number_type_t type, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_pb_delete(gsm_mem_t mem, size_t pos, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_pb_read(gsm_mem_t mem, size_t pos, gsm_pb_entry_t* entry, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_pb_list(gsm_mem_t mem, size_t start_index, gsm_pb_entry_t* entries, size_t etr, size_t* er, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_pb_search(gsm_mem_t mem, const char* search, gsm_pb_entry_t* entries, size_t etr, size_t* er, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); - -/** - * \} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* GSM_HDR_PHONEBOOK_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_private.h b/gsm_at_lib/src/include/gsm/gsm_private.h deleted file mode 100644 index 8b2adb5c..00000000 --- a/gsm_at_lib/src/include/gsm/gsm_private.h +++ /dev/null @@ -1,803 +0,0 @@ -/** - * \file gsm_private.h - * \brief Private structures and enumerations - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef __GSM_PRIV_H -#define __GSM_PRIV_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include "gsm/gsm.h" -#include "gsm/gsm_typedefs.h" -#include "gsm/gsm_debug.h" - -/** - * \addtogroup GSM_TYPEDEFS - * \{ - */ - -/** - * \brief List of possible messages - */ -typedef enum { - GSM_CMD_IDLE = 0, /*!< IDLE mode */ - - /* Basic AT commands */ - GSM_CMD_RESET, /*!< Reset device */ - GSM_CMD_RESET_DEVICE_FIRST_CMD, /*!< Reset device first driver specific command */ - GSM_CMD_ATE0, /*!< Disable ECHO mode on AT commands */ - GSM_CMD_ATE1, /*!< Enable ECHO mode on AT commands */ - GSM_CMD_GSLP, /*!< Set GSM to sleep mode */ - GSM_CMD_RESTORE, /*!< Restore GSM internal settings to default values */ - GSM_CMD_UART, - - GSM_CMD_CGACT_SET_0, - GSM_CMD_CGACT_SET_1, - GSM_CMD_CGATT_SET_0, - GSM_CMD_CGATT_SET_1, - GSM_CMD_NETWORK_ATTACH, /*!< Attach to a network */ - GSM_CMD_NETWORK_DETACH, /*!< Detach from network */ - - GSM_CMD_CIPMUX_SET, - GSM_CMD_CIPRXGET_SET, - GSM_CMD_CSTT_SET, - - - - /* AT commands according to the V.25TER */ - GSM_CMD_CALL_ENABLE, - GSM_CMD_A, /*!< Re-issues the Last Command Given */ - GSM_CMD_ATA, /*!< Answer an Incoming Call */ - GSM_CMD_ATD, /*!< Mobile Originated Call to Dial A Number */ - GSM_CMD_ATD_N, /*!< Originate Call to Phone Number in Current Memory: ATD */ - GSM_CMD_ATD_STR, /*!< Originate Call to Phone Number in Memory Which Corresponds to Field "str": ATD>str */ - GSM_CMD_ATDL, /*!< Redial Last Telephone Number Used */ - GSM_CMD_ATE, /*!< Set Command Echo Mode */ - GSM_CMD_ATH, /*!< Disconnect Existing */ - GSM_CMD_ATI, /*!< Display Product Identification Information */ - GSM_CMD_ATL, /*!< Set Monitor speaker */ - GSM_CMD_ATM, /*!< Set Monitor Speaker Mode */ - GSM_CMD_PPP, /*!< Switch from Data Mode or PPP Online Mode to Command Mode, "+++" originally */ - GSM_CMD_ATO, /*!< Switch from Command Mode to Data Mode */ - GSM_CMD_ATP, /*!< Select Pulse Dialing */ - GSM_CMD_ATQ, /*!< Set Result Code Presentation Mode */ - GSM_CMD_ATS0, /*!< Set Number of Rings before Automatically Answering the Call */ - GSM_CMD_ATS3, /*!< Set Command Line Termination Character */ - GSM_CMD_ATS4, /*!< Set Response Formatting Character */ - GSM_CMD_ATS5, /*!< Set Command Line Editing Character */ - GSM_CMD_ATS6, /*!< Pause Before Blind */ - GSM_CMD_ATS7, /*!< Set Number of Seconds to Wait for Connection Completion */ - GSM_CMD_ATS8, /*!< Set Number of Seconds to Wait for Comma Dial Modifier Encountered in Dial String of D Command */ - GSM_CMD_ATS10, /*!< Set Disconnect Delay after Indicating the Absence of Data Carrier */ - GSM_CMD_ATT, /*!< Select Tone Dialing */ - GSM_CMD_ATV, /*!< TA Response Format */ - GSM_CMD_ATX, /*!< Set CONNECT Result Code Format and Monitor Call Progress */ - GSM_CMD_ATZ, /*!< Reset Default Configuration */ - GSM_CMD_AT_C, /*!< Set DCD Function Mode, AT&C */ - GSM_CMD_AT_D, /*!< Set DTR Function, AT&D */ - GSM_CMD_AT_F, /*!< Factory Defined Configuration, AT&F */ - GSM_CMD_AT_V, /*!< Display Current Configuration, AT&V */ - GSM_CMD_AT_W, /*!< Store Active Profile, AT&W */ - GSM_CMD_GCAP, /*!< Request Complete TA Capabilities List */ - GSM_CMD_GMI, /*!< Request Manufacturer Identification */ - GSM_CMD_GMM, /*!< Request TA Model Identification */ - GSM_CMD_GMR, /*!< Request TA Revision Identification of Software Release */ - GSM_CMD_GOI, /*!< Request Global Object Identification */ - GSM_CMD_GSN, /*!< Request TA Serial Number Identification (IMEI) */ - GSM_CMD_ICF, /*!< Set TE-TA Control Character Framing */ - GSM_CMD_IFC, /*!< Set TE-TA Local Data Flow Control */ - GSM_CMD_IPR, /*!< Set TE-TA Fixed Local Rate */ - GSM_CMD_HVOIC, /*!< Disconnect Voice Call Only */ - - /* AT commands according to 3GPP TS 27.007 */ - GSM_CMD_COPS_SET, /*!< Set operator */ - GSM_CMD_COPS_GET, /*!< Get current operator */ - GSM_CMD_COPS_GET_OPT, /*!< Get a list of available operators */ - GSM_CMD_CPAS, /*!< Phone Activity Status */ - GSM_CMD_CGMI_GET, /*!< Request Manufacturer Identification */ - GSM_CMD_CGMM_GET, /*!< Request Model Identification */ - GSM_CMD_CGMR_GET, /*!< Request TA Revision Identification of Software Release */ - GSM_CMD_CGSN_GET, /*!< Request Product Serial Number Identification (Identical with +GSN) */ - - GSM_CMD_CLCC_SET, /*!< List Current Calls of ME */ - GSM_CMD_CLCK, /*!< Facility Lock */ - - GSM_CMD_CACM, /*!< Accumulated Call Meter (ACM) Reset or Query */ - GSM_CMD_CAMM, /*!< Accumulated Call Meter Maximum (ACM max) Set or Query */ - GSM_CMD_CAOC, /*!< Advice of Charge */ - GSM_CMD_CBST, /*!< Select Bearer Service Type */ - GSM_CMD_CCFC, /*!< Call Forwarding Number and Conditions Control */ - GSM_CMD_CCWA, /*!< Call Waiting Control */ - GSM_CMD_CEER, /*!< Extended Error Report */ - GSM_CMD_CSCS, /*!< Select TE Character Set */ - GSM_CMD_CSTA, /*!< Select Type of Address */ - GSM_CMD_CHLD, /*!< Call Hold and Multiparty */ - GSM_CMD_CIMI, /*!< Request International Mobile Subscriber Identity */ - GSM_CMD_CLIP, /*!< Calling Line Identification Presentation */ - GSM_CMD_CLIR, /*!< Calling Line Identification Restriction */ - GSM_CMD_CMEE_SET, /*!< Report Mobile Equipment Error */ - GSM_CMD_COLP, /*!< Connected Line Identification Presentation */ - - GSM_CMD_PHONEBOOK_ENABLE, - GSM_CMD_CPBF, /*!< Find Phonebook Entries */ - GSM_CMD_CPBR, /*!< Read Current Phonebook Entries */ - GSM_CMD_CPBS_SET, /*!< Select Phonebook Memory Storage */ - GSM_CMD_CPBS_GET, /*!< Get current Phonebook Memory Storage */ - GSM_CMD_CPBS_GET_OPT, /*!< Get available Phonebook Memory Storages */ - GSM_CMD_CPBW_SET, /*!< Write Phonebook Entry */ - GSM_CMD_CPBW_GET_OPT, /*!< Get options for write Phonebook Entry */ - - GSM_CMD_SIM_PROCESS_BASIC_CMDS, /*!< Command setup, executed when SIM is in READY state */ - GSM_CMD_CPIN_SET, /*!< Enter PIN */ - GSM_CMD_CPIN_GET, /*!< Read current SIM status */ - GSM_CMD_CPIN_ADD, /*!< Add new PIN to SIM if pin is not set */ - GSM_CMD_CPIN_CHANGE, /*!< Change already active SIM */ - GSM_CMD_CPIN_REMOVE, /*!< Remove current PIN */ - GMM_CMD_CPUK_SET, /*!< Enter PUK and set new PIN */ - - GSM_CMD_CSQ_GET, /*!< Signal Quality Report */ - GSM_CMD_CFUN_SET, /*!< Set Phone Functionality */ - GSM_CMD_CFUN_GET, /*!< Get Phone Functionality */ - GSM_CMD_CREG_SET, /*!< Network Registration set output */ - GSM_CMD_CREG_GET, /*!< Get current network registration status */ - GSM_CMD_CBC, /*!< Battery Charge */ - GSM_CMD_CNUM, /*!< Subscriber Number */ - - GSM_CMD_CPWD, /*!< Change Password */ - GSM_CMD_CR, /*!< Service Reporting Control */ - GSM_CMD_CRC, /*!< Set Cellular Result Codes for Incoming Call Indication */ - GSM_CMD_CRLP, /*!< Select Radio Link Protocol Parameters */ - GSM_CMD_CRSM, /*!< Restricted SIM Access */ - GSM_CMD_VTD, /*!< Tone Duration */ - GSM_CMD_VTS, /*!< DTMF and Tone Generation */ - GSM_CMD_CMUX, /*!< Multiplexer Control */ - GSM_CMD_CPOL, /*!< Preferred Operator List */ - GSM_CMD_COPN, /*!< Read Operator Names */ - GSM_CMD_CCLK, /*!< Clock */ - GSM_CMD_CSIM, /*!< Generic SIM Access */ - GSM_CMD_CALM, /*!< Alert Sound Mode */ - GSM_CMD_CALS, /*!< Alert Sound Select */ - GSM_CMD_CRSL, /*!< Ringer Sound Level */ - GSM_CMD_CLVL, /*!< Loud Speaker Volume Level */ - GSM_CMD_CMUT, /*!< Mute Control */ - GSM_CMD_CPUC, /*!< Price Per Unit and Currency Table */ - GSM_CMD_CCWE, /*!< Call Meter Maximum Event */ - GSM_CMD_CUSD_SET, /*!< Unstructured Supplementary Service Data, Set command */ - GSM_CMD_CUSD_GET, /*!< Unstructured Supplementary Service Data, Get command */ - GSM_CMD_CUSD, /*!< Unstructured Supplementary Service Data, Execute command */ - GSM_CMD_CSSN, /*!< Supplementary Services Notification */ - - GSM_CMD_CIPMUX, /*!< Start Up Multi-IP Connection */ - GSM_CMD_CIPSTART, /*!< Start Up TCP or UDP Connection */ - GSM_CMD_CIPSEND, /*!< Send Data Through TCP or UDP Connection */ - GSM_CMD_CIPQSEND, /*!< Select Data Transmitting Mode */ - GSM_CMD_CIPACK, /*!< Query Previous Connection Data Transmitting State */ - GSM_CMD_CIPCLOSE, /*!< Close TCP or UDP Connection */ - GSM_CMD_CIPSHUT, /*!< Deactivate GPRS PDP Context */ - GSM_CMD_CLPORT, /*!< Set Local Port */ - GSM_CMD_CSTT, /*!< Start Task and Set APN, username, password */ - GSM_CMD_CIICR, /*!< Bring Up Wireless Connection with GPRS or CSD */ - GSM_CMD_CIFSR, /*!< Get Local IP Address */ - GSM_CMD_CIPSTATUS, /*!< Query Current Connection Status */ - GSM_CMD_CDNSCFG, /*!< Configure Domain Name Server */ - GSM_CMD_CDNSGIP, /*!< Query the IP Address of Given Domain Name */ - GSM_CMD_CIPHEAD, /*!< Add an IP Head at the Beginning of a Package Received */ - GSM_CMD_CIPATS, /*!< Set Auto Sending Timer */ - GSM_CMD_CIPSPRT, /*!< Set Prompt of ‘>’ When Module Sends Data */ - GSM_CMD_CIPSERVER, /*!< Configure Module as Server */ - GSM_CMD_CIPCSGP, /*!< Set CSD or GPRS for Connection Mode */ - GSM_CMD_CIPSRIP, /*!< Show Remote IP Address and Port When Received Data */ - GSM_CMD_CIPDPDP, /*!< Set Whether to Check State of GPRS Network Timing */ - GSM_CMD_CIPMODE, /*!< Select TCPIP Application Mode */ - GSM_CMD_CIPCCFG, /*!< Configure Transparent Transfer Mode */ - GSM_CMD_CIPSHOWTP, /*!< Display Transfer Protocol in IP Head When Received Data */ - GSM_CMD_CIPUDPMODE, /*!< UDP Extended Mode */ - GSM_CMD_CIPRXGET, /*!< Get Data from Network Manually */ - GSM_CMD_CIPSCONT, /*!< Save TCPIP Application Context */ - GSM_CMD_CIPRDTIMER, /*!< Set Remote Delay Timer */ - GSM_CMD_CIPSGTXT, /*!< Select GPRS PDP context */ - GSM_CMD_CIPTKA, /*!< Set TCP Keepalive Parameters */ - GSM_CMD_CIPSSL, /*!< Connection SSL function */ - - GSM_CMD_SMS_ENABLE, - GSM_CMD_CMGD, /*!< Delete SMS Message */ - GSM_CMD_CMGF, /*!< Select SMS Message Format */ - GSM_CMD_CMGL, /*!< List SMS Messages from Preferred Store */ - GSM_CMD_CMGR, /*!< Read SMS Message */ - GSM_CMD_CMGS, /*!< Send SMS Message */ - GSM_CMD_CMGW, /*!< Write SMS Message to Memory */ - GSM_CMD_CMSS, /*!< Send SMS Message from Storage */ - GSM_CMD_CMGDA, /*!< MASS SMS delete */ - GSM_CMD_CNMI, /*!< New SMS Message Indications */ - GSM_CMD_CPMS_SET, /*!< Set preferred SMS Message Storage */ - GSM_CMD_CPMS_GET, /*!< Get preferred SMS Message Storage */ - GSM_CMD_CPMS_GET_OPT, /*!< Get optional SMS message storages */ - GSM_CMD_CRES, /*!< Restore SMS Settings */ - GSM_CMD_CSAS, /*!< Save SMS Settings */ - GSM_CMD_CSCA, /*!< SMS Service Center Address */ - GSM_CMD_CSCB, /*!< Select Cell Broadcast SMS Messages */ - GSM_CMD_CSDH, /*!< Show SMS Text Mode Parameters */ - GSM_CMD_CSMP, /*!< Set SMS Text Mode Parameters */ - GSM_CMD_CSMS, /*!< Select Message Service */ - - GSM_CMD_END, /*!< Last CMD entry */ -} gsm_cmd_t; - -/** - * \brief Connection structure - */ -typedef struct gsm_conn { - gsm_conn_type_t type; /*!< Connection type */ - uint8_t num; /*!< Connection number */ - gsm_ip_t remote_ip; /*!< Remote IP address */ - gsm_port_t remote_port; /*!< Remote port number */ - gsm_port_t local_port; /*!< Local IP address */ - gsm_evt_fn evt_func; /*!< Callback function for connection */ - void* arg; /*!< User custom argument */ - - uint8_t val_id; /*!< Validation ID number. It is increased each time a new connection is established. - It protects sending data to wrong connection in case we have data in send queue, - and connection was closed and active again in between. */ - - gsm_linbuff_t buff; /*!< Linear buffer structure */ - - size_t total_recved; /*!< Total number of bytes received */ - - union { - struct { - uint8_t active:1; /*!< Status whether connection is active */ - uint8_t client:1; /*!< Status whether connection is in client mode */ - uint8_t data_received:1; /*!< Status whether first data were received on connection */ - uint8_t in_closing:1; /*!< Status if connection is in closing mode. - When in closing mode, ignore any possible received data from function */ - uint8_t bearer:1; /*!< Bearer used. Can be `1` or `0` */ - } f; /*!< Connection flags */ - } status; /*!< Connection status union with flag bits */ -} gsm_conn_t; - -/** - * \ingroup GSM_PBUF - * \brief Packet buffer structure - */ -typedef struct gsm_pbuf { - struct gsm_pbuf* next; /*!< Next pbuf in chain list */ - size_t tot_len; /*!< Total length of pbuf chain */ - size_t len; /*!< Length of payload */ - size_t ref; /*!< Number of references to this structure */ - uint8_t* payload; /*!< Pointer to payload memory */ - gsm_ip_t ip; /*!< Remote address for received IPD data */ - gsm_port_t port; /*!< Remote port for received IPD data */ -} gsm_pbuf_t; - -/** - * \brief Incoming network data read structure - */ -typedef struct { - uint8_t read; /*!< Set to 1 when we should process input data as connection data */ - size_t tot_len; /*!< Total length of packet */ - size_t rem_len; /*!< Remaining bytes to read in current +IPD statement */ - gsm_conn_p conn; /*!< Pointer to connection for network data */ - - size_t buff_ptr; /*!< Buffer pointer to save data to. - When set to `NULL` while `read = 1`, reading should ignore incoming data */ - gsm_pbuf_p buff; /*!< Pointer to data buffer used for receiving data */ -} gsm_ipd_t; - -/** - * \brief Connection result on connect command - */ -typedef enum { - GSM_CONN_CONNECT_UNKNOWN, /*!< No valid result */ - GSM_CONN_CONNECT_OK, /*!< Connected OK */ - GSM_CONN_CONNECT_ERROR, /*!< Error on connection */ - GSM_CONN_CONNECT_ALREADY, /*!< Already connected */ -} gsm_conn_connect_res_t; - -/** - * \brief Message queue structure to share between threads - */ -typedef struct gsm_msg { - gsm_cmd_t cmd_def; /*!< Default message type received from queue */ - gsm_cmd_t cmd; /*!< Since some commands can have different subcommands, sub command is used here */ - uint8_t i; /*!< Variable to indicate order number of subcommands */ - gsm_sys_sem_t sem; /*!< Semaphore for the message */ - uint8_t is_blocking; /*!< Status if command is blocking */ - uint32_t block_time; /*!< Maximal blocking time in units of milliseconds. Use 0 to for non-blocking call */ - gsmr_t res; /*!< Result of message operation */ - gsmr_t (*fn)(struct gsm_msg *); /*!< Processing callback function to process packet */ - -#if GSM_CFG_USE_API_FUNC_EVT - gsm_api_cmd_evt_fn evt_fn; /*!< Command callback API function */ - void* evt_arg; /*!< Command callback API callback parameter */ -#endif /* GSM_CFG_USE_API_FUNC_EVT */ - - union { - struct { - uint32_t delay; /*!< Delay to use before sending first reset AT command */ - } reset; /*!< Reset device */ - struct { - uint32_t baudrate; /*!< Baudrate for AT port */ - } uart; /*!< UART configuration */ - - struct { - uint8_t mode; /*!< Functionality mode */ - } cfun; /*!< Set phone functionality */ - - struct { - const char* pin; /*!< Pin code to write */ - } cpin_enter; /*!< Enter pin code */ - struct { - const char* pin; /*!< New pin code */ - } cpin_add; /*!< Add pin code if previously wasn't set */ - struct { - const char* current_pin; /*!< Current pin code */ - const char* new_pin; /*!< New pin code */ - } cpin_change; /*!< Change current pin code */ - struct { - const char* pin; /*!< Current pin code */ - } cpin_remove; /*!< Remove PIN code */ - struct { - const char* puk; /*!< PUK code */ - const char* pin; /*!< New PIN code */ - } cpuk_enter; /*!< Enter PUK and new PIN */ - struct { - size_t cnum_tries; /*!< Number of tries */ - } sim_info; /*!< Get information for SIM card */ - - struct { - char* str; /*!< Pointer to output string array */ - size_t len; /*!< Length of output string array including trailing zero memory */ - } device_info; /*!< All kind of device info, serial number, model, manufacturer, revision */ - - struct { - int16_t* rssi; /*!< Pointer to RSSI variable */ - } csq; /*!< Signal strength */ - struct { - uint8_t read; /*!< Flag indicating we can read the COPS actual data */ - gsm_operator_t* ops; /*!< Pointer to operators array */ - size_t opsl; /*!< Length of operators array */ - size_t opsi; /*!< Current operator index array */ - size_t* opf; /*!< Pointer to number of operators found */ - } cops_scan; /*!< Scan operators */ - struct { - gsm_operator_curr_t* curr; /*!< Pointer to output current operator */ - } cops_get; /*!< Get current operator info */ - struct { - gsm_operator_mode_t mode; /*!< COPS mode */ - gsm_operator_format_t format; /*!< Operator format to print */ - const char* name; /*!< Short or long name, according to format */ - uint32_t num; /*!< Number in case format is number */ - } cops_set; /*!< Set operator settings */ - -#if GSM_CFG_CONN || __DOXYGEN__ - /* Connection based commands */ - struct { - gsm_conn_t** conn; /*!< Pointer to pointer to save connection used */ - const char* host; /*!< Host to use for connection */ - gsm_port_t port; /*!< Remote port used for connection */ - gsm_conn_type_t type; /*!< Connection type */ - void* arg; /*!< Connection custom argument */ - gsm_evt_fn evt_func; /*!< Callback function to use on connection */ - uint8_t num; /*!< Connection number used for start */ - gsm_conn_connect_res_t conn_res; /*!< Connection result status */ - } conn_start; /*!< Structure for starting new connection */ - struct { - gsm_conn_t* conn; /*!< Pointer to connection to close */ - uint8_t val_id; /*!< Connection current validation ID when command was sent to queue */ - } conn_close; /*!< Close connection */ - struct { - gsm_conn_t* conn; /*!< Pointer to connection to send data */ - size_t btw; /*!< Number of remaining bytes to write */ - size_t ptr; /*!< Current write pointer for data */ - const uint8_t* data; /*!< Data to send */ - size_t sent; /*!< Number of bytes sent in last packet */ - size_t sent_all; /*!< Number of bytes sent all together */ - uint8_t tries; /*!< Number of tries used for last packet */ - uint8_t wait_send_ok_err; /*!< Set to 1 when we wait for SEND OK or SEND ERROR */ - const gsm_ip_t* remote_ip; /*!< Remote IP address for UDP connection */ - gsm_port_t remote_port; /*!< Remote port address for UDP connection */ - uint8_t fau; /*!< Free after use flag to free memory after data are sent (or not) */ - size_t* bw; /*!< Number of bytes written so far */ - uint8_t val_id; /*!< Connection current validation ID when command was sent to queue */ - } conn_send; /*!< Structure to send data on connection */ -#endif /* GSM_CFG_CONN || __DOXYGEN__ */ -#if GSM_CFG_SMS || __DOXYGEN__ - struct { - const char* num; /*!< Phone number */ - const char* text; /*!< SMS content to send */ - uint8_t format; /*!< SMS format, `0 = PDU`, `1 = text` */ - size_t pos; /*!< Set on +CMGS response if command is OK */ - } sms_send; /*!< Send SMS */ - struct { - gsm_mem_t mem; /*!< Memory to read from */ - size_t pos; /*!< SMS position in memory */ - gsm_sms_entry_t* entry; /*!< Pointer to entry to write info */ - uint8_t update; /*!< Update SMS status after read operation */ - uint8_t format; /*!< SMS format, `0 = PDU`, `1 = text` */ - uint8_t read; /*!< Read the data flag */ - } sms_read; /*!< Read single SMS */ - struct { - gsm_mem_t mem; /*!< Memory to delete from */ - size_t pos; /*!< SMS position in memory */ - } sms_delete; /*!< Delete SMS message */ - struct { - gsm_sms_status_t status; /*!< SMS status to delete */ - } sms_delete_all; /*!< Mass delete SMS messages */ - struct { - gsm_mem_t mem; /*!< Memory to use for read */ - gsm_sms_status_t status; /*!< SMS entries status */ - gsm_sms_entry_t* entries; /*!< Pointer to entries */ - size_t etr; /*!< Entries to read (array length) */ - size_t ei; /*!< Current entry index in array */ - size_t* er; /*!< Final entries read pointer for user */ - uint8_t update; /*!< Update SMS status after read operation */ - uint8_t format; /*!< SMS format, `0 = PDU`, `1 = text` */ - uint8_t read; /*!< Read the data flag */ - } sms_list; /*!< List SMS messages */ - struct { - gsm_mem_t mem[3]; /*!< Array of memories */ - } sms_memory; /*!< Set preferred memories */ -#endif /* GSM_CFG_SMS || __DOXYGEN__ */ -#if GSM_CFG_CALL || __DOXYGEN__ - struct { - const char* number; /*!< Phone number to dial */ - } call_start; /*!< Start a new call */ -#endif /* GSM_CFG_CALL || __DOXYGEN__ */ -#if GSM_CFG_PHONEBOOK || __DOXYGEN__ - struct { - gsm_mem_t mem; /*!< Memory to use */ - size_t pos; /*!< Memory position. Set to 0 to use new one or SIZE_T MAX to delete entry */ - const char* name; /*!< Entry name */ - const char* num; /*!< Entry number */ - gsm_number_type_t type; /*!< Entry phone number type */ - uint8_t del; /*!< Flag indicates delete */ - } pb_write; /*!< Write/Edit/Delete entry */ - struct { - gsm_mem_t mem; /*!< Memory to use */ - size_t start_index; /*!< Start index in phonebook to read */ - gsm_pb_entry_t* entries; /*!< Pointer to entries array */ - size_t etr; /*!< NUmber of entries to read */ - size_t ei; /*!< Current entry index */ - size_t* er; /*!< Final entries read pointer for user */ - } pb_list; /*!< List phonebook entries */ - struct { - gsm_mem_t mem; /*!< Memory to use */ - gsm_pb_entry_t* entries; /*!< Pointer to entries array */ - size_t etr; /*!< NUmber of entries to read */ - size_t ei; /*!< Current entry index */ - size_t* er; /*!< Final entries read pointer for user */ - const char* search; /*!< Search string */ - } pb_search; /*!< Search phonebook entries */ -#endif /* GSM_CFG_PHONEBOOK || __DOXYGEN__ */ - struct { - const char* code; /*!< Code to send */ - char* resp; /*!< Response array */ - size_t resp_len; /*!< Length of response array */ - uint8_t read; /*!< Flag indicating we can read the COPS actual data */ - size_t resp_write_ptr; /*!< Write pointer for response */ - uint8_t quote_det; /*!< Information if quote has been detected */ - } ussd; /*!< Execute USSD command */ -#if GSM_CFG_NETWORK || __DOXYGEN__ - struct { - const char* apn; /*!< APN address */ - const char* user; /*!< APN username */ - const char* pass; /*!< APN password */ - } network_attach; /*!< Settings for network attach */ -#endif /* GSM_CFG_NETWORK || __DOXYGEN__ */ - } msg; /*!< Group of different possible message contents */ -} gsm_msg_t; - -/** - * \brief IP and MAC structure with netmask and gateway addresses - */ -typedef struct { - gsm_ip_t ip; /*!< IP address */ - gsm_ip_t gw; /*!< Gateway address */ - gsm_ip_t nm; /*!< Netmask address */ - gsm_mac_t mac; /*!< MAC address */ -} gsm_ip_mac_t; - -/** - * \brief Link connection active info - */ -typedef struct { - uint8_t failed; /*!< Status if connection successful */ - uint8_t num; /*!< Connection number */ - uint8_t is_server; /*!< Status if connection is client or server */ - gsm_conn_type_t type; /*!< Connection type */ - gsm_ip_t remote_ip; /*!< Remote IP address */ - gsm_port_t remote_port; /*!< Remote port */ - gsm_port_t local_port; /*!< Local port number */ -} gsm_link_conn_t; - -/** - * \brief Callback function linked list prototype - */ -typedef struct gsm_evt_func { - struct gsm_evt_func* next; /*!< Next function in the list */ - gsm_evt_fn fn; /*!< Function pointer itself */ -} gsm_evt_func_t; - -/** - * \ingroup GSM_SMS - * \brief SMS memory information - */ -typedef struct { - uint32_t mem_available; /*!< Bit field of available memories */ - gsm_mem_t current; /*!< Current memory choice */ - size_t total; /*!< Size of memory in units of entries */ - size_t used; /*!< Number of used entries */ -} gsm_sms_mem_t; - -/** - * \ingroup GSM_SMS - * \brief SMS structure - */ -typedef struct { - uint8_t ready; /*!< Flag indicating feature ready by device */ - uint8_t enabled; /*!< Flag indicating feature enabled */ - - gsm_sms_mem_t mem[3]; /*!< 3 memory info for operation,receive,sent storage */ -} gsm_sms_t; - -/** - * \ingroup GSM_SMS - * \brief SMS memory information - */ -typedef struct { - uint32_t mem_available; /*!< Bit field of available memories */ - gsm_mem_t current; /*!< Current memory choice */ - size_t total; /*!< Size of memory in units of entries */ - size_t used; /*!< Number of used entries */ -} gsm_pb_mem_t; - -/** - * \ingroup GSM_PB - * \brief Phonebook structure - */ -typedef struct { - uint8_t ready; /*!< Flag indicating feature ready by device */ - uint8_t enabled; /*!< Flag indicating feature enabled */ - - gsm_pb_mem_t mem; /*!< Memory information */ -} gsm_pb_t; - -/** - * \brief SIM structure - */ -typedef struct { - gsm_sim_state_t state; /*!< Current SIM status */ -} gsm_sim_t; - -/** - * \brief Network info - */ -typedef struct { - gsm_network_reg_status_t status; /*!< Network registration status */ - gsm_operator_curr_t curr_operator; /*!< Current operator information */ - - uint8_t is_attached; /*!< Flag indicating device is attached and PDP context is active */ - gsm_ip_t ip_addr; /*!< Device IP address when network PDP context is enabled */ -} gsm_network_t; - -/** - * \brief GSM modules structure - */ -typedef struct { - /* Device identification */ - char model_manufacturer[20]; /*!< Device manufacturer */ - char model_number[20]; /*!< Device model number */ - char model_serial_number[20];/*!< Device serial number */ - char model_revision[20]; /*!< Device revision */ - gsm_device_model_t model; /*!< Device model */ - - /* Network&operator specific */ - gsm_sim_t sim; /*!< SIM data */ - gsm_network_t network; /*!< Network status */ - int16_t rssi; /*!< RSSI signal strength. `0` = invalid, `-53 % -113` = valid */ - - /* Device specific */ -#if GSM_CFG_CONN || __DOXYGEN__ - uint8_t active_conns_cur_parse_num; /*!< Current connection number used for parsing */ - - gsm_conn_t conns[GSM_CFG_MAX_CONNS]; /*!< Array of all connection structures */ - gsm_ipd_t ipd; /*!< Connection incoming data structure */ - uint8_t conn_val_id; /*!< Validation ID increased each time device connects to network */ -#endif /* GSM_CFG_CONNS || __DOXYGEN__ */ -#if GSM_CFG_SMS || __DOXYGEN__ - gsm_sms_t sms; /*!< SMS information */ -#endif /* GSM_CFG_SMS || __DOXYGEN__ */ -#if GSM_CFG_PHONEBOOK || __DOXYGEN__ - gsm_pb_t pb; /*!< Phonebook information */ -#endif /* GSM_CFG_PHONEBOOK || __DOXYGEN__ */ -#if GSM_CFG_CALL || __DOXYGEN__ - gsm_call_t call; /*!< Call information */ -#endif /* GSM_CFG_CALL || __DOXYGEN__ */ -} gsm_modules_t; - -/** - * \brief GSM global structure - */ -typedef struct { - size_t locked_cnt; /*!< Counter how many times (recursive) stack is currently locked */ - - gsm_sys_sem_t sem_sync; /*!< Synchronization semaphore between threads */ - gsm_sys_mbox_t mbox_producer; /*!< Producer message queue handle */ - gsm_sys_mbox_t mbox_process; /*!< Consumer message queue handle */ - gsm_sys_thread_t thread_produce; /*!< Producer thread handle */ - gsm_sys_thread_t thread_process; /*!< Processing thread handle */ -#if !GSM_CFG_INPUT_USE_PROCESS || __DOXYGEN__ - gsm_buff_t buff; /*!< Input processing buffer */ -#endif /* !GSM_CFG_INPUT_USE_PROCESS || __DOXYGEN__ */ - gsm_ll_t ll; /*!< Low level functions */ - - gsm_msg_t* msg; /*!< Pointer to current user message being executed */ - - gsm_evt_t evt; /*!< Callback processing structure */ - gsm_evt_func_t* evt_func; /*!< Callback function linked list */ - - gsm_modules_t m; /*!< All modules. When resetting, reset structure */ - - union { - struct { - uint8_t initialized:1; /*!< Flag indicating GSM library is initialized */ - uint8_t dev_present:1; /*!< Flag indicating GSM device is present */ - } f; /*!< Flags structure */ - } status; /*!< Status structure */ -} gsm_t; - -/** - * \brief Memory mapping structure between string and value in app - */ -typedef struct { - gsm_mem_t mem; /*!< Mem indication */ - const char* mem_str; /*!< Memory string */ -} gsm_dev_mem_map_t; - -/** - * \brief Device models map between model and other information - */ -typedef struct { - gsm_device_model_t model; /*!< Device model */ - const char* id_str; /*!< Model string identification */ - uint8_t is_2g; /*!< Status if modem is 2G */ - uint8_t is_lte; /*!< Status if modem is LTE */ -} gsm_dev_model_map_t; - -/** - * \ingroup GSM_UNICODE - * \brief Unicode support structure - */ -typedef struct { - uint8_t ch[4]; /*!< UTF-8 max characters */ - uint8_t t; /*!< Total expected length in UTF-8 sequence */ - uint8_t r; /*!< Remaining bytes in UTF-8 sequence */ - gsmr_t res; /*!< Current result of processing */ -} gsm_unicode_t; - -/** - * \} - */ - -#if !__DOXYGEN__ - -/** - * \ingroup GSM - * \defgroup GSM_PRIVATE Internal functions - * \brief Functions, structures and enumerations - * \{ - */ - -extern gsm_t gsm; - -extern const gsm_dev_mem_map_t gsm_dev_mem_map[]; -extern const size_t gsm_dev_mem_map_size; - -extern const gsm_dev_model_map_t gsm_dev_model_map[]; -extern const size_t gsm_dev_model_map_size; - -#define CMD_IS_CUR(c) (gsm.msg != NULL && gsm.msg->cmd == (c)) -#define CMD_IS_DEF(c) (gsm.msg != NULL && gsm.msg->cmd_def == (c)) -#define CMD_GET_CUR() ((gsm_cmd_t)(((gsm.msg != NULL) ? gsm.msg->cmd : GSM_CMD_IDLE))) -#define CMD_GET_DEF() ((gsm_cmd_t)(((gsm.msg != NULL) ? gsm.msg->cmd_def : GSM_CMD_IDLE))) - -#define CRLF "\r\n" -#define CRLF_LEN 2 - -#define GSM_MSG_VAR_DEFINE(name) gsm_msg_t* name -#define GSM_MSG_VAR_ALLOC(name, blocking) do {\ - (name) = gsm_mem_malloc(sizeof(*(name))); \ - GSM_DEBUGW(GSM_CFG_DBG_VAR | GSM_DBG_TYPE_TRACE, (name) != NULL, "[MSG VAR] Allocated %d bytes at %p\r\n", sizeof(*(name)), (name)); \ - GSM_DEBUGW(GSM_CFG_DBG_VAR | GSM_DBG_TYPE_TRACE, (name) == NULL, "[MSG VAR] Error allocating %d bytes\r\n", sizeof(*(name))); \ - if ((name) == NULL) { \ - return gsmERRMEM; \ - } \ - GSM_MEMSET((name), 0x00, sizeof(*(name))); \ - (name)->is_blocking = GSM_U8((blocking) > 0); \ -} while (0) -#define GSM_MSG_VAR_REF(name) (*(name)) -#define GSM_MSG_VAR_FREE(name) do {\ - GSM_DEBUGF(GSM_CFG_DBG_VAR | GSM_DBG_TYPE_TRACE, "[MSG VAR] Free memory: %p\r\n", (name)); \ - if (gsm_sys_sem_isvalid(&((name)->sem))) { \ - gsm_sys_sem_delete(&((name)->sem)); \ - gsm_sys_sem_invalid(&((name)->sem)); \ - } \ - gsm_mem_free_s((void **)&(name)); \ -} while (0) -#if GSM_CFG_USE_API_FUNC_EVT -#define GSM_MSG_VAR_SET_EVT(name, evt_fn, evt_arg) do {\ - (name)->evt_fn = (evt_fn); \ - (name)->evt_arg = (evt_arg); \ -} while (0) -#else /* GSM_CFG_USE_API_FUNC_EVT */ -#define GSM_MSG_VAR_SET_EVT(name, evt_fn, evt_arg) do { GSM_UNUSED(evt_fn); GSM_UNUSED(evt_arg); } while (0) -#endif /* !GSM_CFG_USE_API_FUNC_EVT */ - -#define GSM_CHARISNUM(x) ((x) >= '0' && (x) <= '9') -#define GSM_CHARTONUM(x) ((x) - '0') -#define GSM_CHARISHEXNUM(x) (((x) >= '0' && (x) <= '9') || ((x) >= 'a' && (x) <= 'f') || ((x) >= 'A' && (x) <= 'F')) -#define GSM_CHARHEXTONUM(x) (((x) >= '0' && (x) <= '9') ? ((x) - '0') : (((x) >= 'a' && (x) <= 'f') ? ((x) - 'a' + 10) : (((x) >= 'A' && (x) <= 'F') ? ((x) - 'A' + 10) : 0))) -#define GSM_ISVALIDASCII(x) (((x) >= 32 && (x) <= 126) || (x) == '\r' || (x) == '\n') - -#define GSM_PORT2NUM(port) ((uint32_t)(port)) - -const char * gsmi_dbg_msg_to_string(gsm_cmd_t cmd); -gsmr_t gsmi_process(const void* data, size_t len); -gsmr_t gsmi_process_buffer(void); -gsmr_t gsmi_initiate_cmd(gsm_msg_t* msg); -uint8_t gsmi_is_valid_conn_ptr(gsm_conn_p conn); -gsmr_t gsmi_send_cb(gsm_evt_type_t type); -gsmr_t gsmi_send_conn_cb(gsm_conn_t* conn, gsm_evt_fn cb); -void gsmi_conn_init(void); -gsmr_t gsmi_send_msg_to_producer_mbox(gsm_msg_t* msg, gsmr_t (*process_fn)(gsm_msg_t *), uint32_t max_block_time); -uint32_t gsmi_get_from_mbox_with_timeout_checks(gsm_sys_mbox_t* b, void** m, uint32_t timeout); -uint8_t gsmi_conn_closed_process(uint8_t conn_num, uint8_t forced); -void gsmi_conn_start_timeout(gsm_conn_p conn); - -gsmr_t gsmi_get_sim_info(const uint32_t blocking); - -void gsmi_reset_everything(uint8_t forced); -void gsmi_process_events_for_timeout_or_error(gsm_msg_t* msg, gsmr_t err); - -/** - * \} - */ - -#endif /* !__DOXYGEN__ */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __GSM_PRIV_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_sms.h b/gsm_at_lib/src/include/gsm/gsm_sms.h deleted file mode 100644 index 2cac273b..00000000 --- a/gsm_at_lib/src/include/gsm/gsm_sms.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * \file gsm_sms.h - * \brief SMS API - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_SMS_H -#define GSM_HDR_SMS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "gsm/gsm.h" - -/** - * \ingroup GSM - * \defgroup GSM_SMS SMS API - * \brief SMS manager - * \{ - */ - -gsmr_t gsm_sms_enable(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_sms_disable(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); - -gsmr_t gsm_sms_send(const char* num, const char* text, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_sms_read(gsm_mem_t mem, size_t pos, gsm_sms_entry_t* entry, uint8_t update, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_sms_delete(gsm_mem_t mem, size_t pos, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_sms_delete_all(gsm_sms_status_t status, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_sms_list(gsm_mem_t mem, gsm_sms_status_t stat, gsm_sms_entry_t* entries, size_t etr, size_t* er, uint8_t update, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_sms_set_preferred_storage(gsm_mem_t mem1, gsm_mem_t mem2, gsm_mem_t mem3, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); - -/** - * \} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* GSM_HDR_SMS_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_typedefs.h b/gsm_at_lib/src/include/gsm/gsm_typedefs.h deleted file mode 100644 index a9b5b190..00000000 --- a/gsm_at_lib/src/include/gsm/gsm_typedefs.h +++ /dev/null @@ -1,629 +0,0 @@ -/** - * \file gsm_typedefs.h - * \brief List of structures and enumerations for public usage - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_DEFS_H -#define GSM_HDR_DEFS_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include -#include -#include -#include - -/** - * \ingroup GSM - * \defgroup GSM_TYPEDEFS Structures and enumerations - * \brief List of core structures and enumerations - * \{ - */ - -/** - * \} - */ - -/** - * \ingroup GSM_TYPEDEFS - * \brief Result enumeration used across application functions - */ -typedef enum { - gsmOK = 0, /*!< Function returned OK */ - gsmOKIGNOREMORE, /*!< Function succedded, should continue as gsmOK but ignore sending more data. This result is possible on connection data receive callback */ - gsmERR, - gsmPARERR, /*!< Wrong parameters on function call */ - gsmERRMEM, /*!< Memory error occurred */ - gsmTIMEOUT, /*!< Timeout occurred on command */ - gsmCONT, /*!< There is still some command to be processed in current command */ - gsmCLOSED, /*!< Connection just closed */ - gsmINPROG, /*!< Operation is in progress */ - - gsmERRNOTENABLED, /*!< Feature not enabled error */ - gsmERRNOIP, /*!< Station does not have IP address */ - gsmERRNOFREECONN, /*!< There is no free connection available to start */ - gsmERRCONNTIMEOUT, /*!< Timeout received when connection to access point */ - gsmERRPASS, /*!< Invalid password for access point */ - gsmERRNOAP, /*!< No access point found with specific SSID and MAC address */ - gsmERRCONNFAIL, /*!< Connection failed to access point */ - gsmERRWIFINOTCONNECTED, /*!< Wifi not connected to access point */ - gsmERRNODEVICE, /*!< Device is not present */ - gsmERRBLOCKING, /*!< Blocking mode command is not allowed */ -} gsmr_t; - -/** - * \ingroup GSM_TYPEDEFS - * \brief GSM device model type - */ -typedef enum { -#define GSM_DEVICE_MODEL_ENTRY(name, str_id, is_2g, is_lte) GSM_DEVICE_MODEL_ ## name, -#include "gsm/gsm_models.h" - GSM_DEVICE_MODEL_END, /*!< End of device model */ - GSM_DEVICE_MODEL_UNKNOWN, /*!< Unknown device model */ -} gsm_device_model_t; - -/** - * \ingroup GSM_SIM - * \brief SIM state - */ -typedef enum { - GSM_SIM_STATE_NOT_INSERTED, /*!< SIM is not inserted in socket */ - GSM_SIM_STATE_READY, /*!< SIM is ready for operations */ - GSM_SIM_STATE_NOT_READY, /*!< SIM is not ready for any operation */ - GSM_SIM_STATE_PIN, /*!< SIM is waiting for SIM to be given */ - GSM_SIM_STATE_PUK, /*!< SIM is waiting for PUT to be given */ - GSM_SIM_STATE_PH_PIN, - GSM_SIM_STATE_PH_PUK, -} gsm_sim_state_t; - -/** - * \ingroup GSM_TYPEDEFS - * \brief IP structure - */ -typedef struct { - uint8_t ip[4]; /*!< IPv4 address */ -} gsm_ip_t; - -/** - * \ingroup GSM_TYPEDEFS - * \brief Port variable - */ -typedef uint16_t gsm_port_t; - -/** - * \ingroup GSM_TYPEDEFS - * \brief MAC address - */ -typedef struct { - uint8_t mac[6]; /*!< MAC address */ -} gsm_mac_t; - -/** - * \ingroup GSM_TYPEDEFS - * \brief Date and time structure - */ -typedef struct { - uint8_t date; /*!< Day in a month, from `1` to up to `31` */ - uint8_t month; /*!< Month in a year, from `1` to `12` */ - uint16_t year; /*!< Year */ - uint8_t day; /*!< Day in a week, from `1` to `7`, 0 = invalid */ - uint8_t hours; /*!< Hours in a day, from `0` to `23` */ - uint8_t minutes; /*!< Minutes in a hour, from `0` to `59` */ - uint8_t seconds; /*!< Seconds in a minute, from `0` to `59` */ -} gsm_datetime_t; - -/** - * \ingroup GSM_CONN - * \brief List of possible connection types - */ -typedef enum { - GSM_CONN_TYPE_TCP, /*!< Connection type is TCP */ - GSM_CONN_TYPE_UDP, /*!< Connection type is UDP */ - GSM_CONN_TYPE_SSL, /*!< Connection type is TCP over SSL */ -} gsm_conn_type_t; - -/** - * \ingroup GSM_TYPEDEFS - * \brief Available device memories - */ -typedef enum { -#define GSM_DEV_MEMORY_ENTRY(name, str_code) GSM_MEM_ ## name, -#include "gsm/gsm_memories.h" - GSM_MEM_END, /*!< End of memory list */ - GSM_MEM_CURRENT, /*!< Use current memory for read/delete operation */ - GSM_MEM_UNKNOWN = 0x1F, /*!< Unknown memory */ -} gsm_mem_t; - -/** - * \ingroup GSM_TYPEDEFS - * \brief GSM number type - */ -typedef enum { - GSM_NUMBER_TYPE_NATIONAL = 129, /*!< Number is national */ - GSM_NUMBER_TYPE_INTERNATIONAL = 145, /*!< Number is international */ -} gsm_number_type_t; - -/** - * \ingroup GSM_SMS - * \brief SMS status in current memory - */ -typedef enum { - GSM_SMS_STATUS_ALL, /*!< Process all SMS, used for mass delete or SMS list */ - GSM_SMS_STATUS_READ, /*!< SMS status is read */ - GSM_SMS_STATUS_UNREAD, /*!< SMS status is unread */ - GSM_SMS_STATUS_SENT, /*!< SMS status is sent */ - GSM_SMS_STATUS_UNSENT, /*!< SMS status is unsent */ - GSM_SMS_STATUS_INBOX, /*!< SMS status, used only for mass delete operation */ -} gsm_sms_status_t; - -/** - * \ingroup GSM_SMS - * \brief SMS entry structure - */ -typedef struct { - gsm_mem_t mem; /*!< Memory storage */ - size_t pos; /*!< Memory position */ - gsm_datetime_t datetime; /*!< Date and time */ - gsm_sms_status_t status; /*!< Message status */ - char number[26]; /*!< Phone number */ - char name[20]; /*!< Name in phonebook if exists */ - char data[161]; /*!< Data memory */ - size_t length; /*!< Length of SMS data */ -} gsm_sms_entry_t; - -/** - * \ingroup GSM_PB - * \brief Phonebook entry structure - */ -typedef struct { - gsm_mem_t mem; /*!< Memory position */ - size_t pos; /*!< Position in memory */ - char name[20]; /*!< Name of phonebook entry */ - char number[26]; /*!< Phone number */ - gsm_number_type_t type; /*!< Phone number type */ -} gsm_pb_entry_t; - -/** - * \ingroup GSM_OPERATOR - * \brief Operator status value - */ -typedef enum { - GSM_OPERATOR_STATUS_UNKNOWN = 0x00, /*!< Unknown operator */ - GSM_OPERATOR_STATUS_AVAILABLE, /*!< Operator is available */ - GSM_OPERATOR_STATUS_CURRENT, /*!< Operator is currently active */ - GSM_OPERATOR_STATUS_FORBIDDEN /*!< Operator is forbidden */ -} gsm_operator_status_t; - -/** - * \ingroup GSM_OPERATOR - * \brief Operator selection mode - */ -typedef enum { - GSM_OPERATOR_MODE_AUTO = 0x00, /*!< Operator automatic mode */ - GSM_OPERATOR_MODE_MANUAL = 0x01, /*!< Operator manual mode */ - GSM_OPERATOR_MODE_DEREGISTER = 0x02, /*!< Operator deregistered from network */ - GSM_OPERATOR_MODE_MANUAL_AUTO = 0x04, /*!< Operator manual mode first. If fails, auto mode enabled */ -} gsm_operator_mode_t; - -/** - * \ingroup GSM_OPERATOR - * \brief Operator data format - */ -typedef enum { - GSM_OPERATOR_FORMAT_LONG_NAME = 0x00, /*!< COPS command returned long name */ - GSM_OPERATOR_FORMAT_SHORT_NAME, /*!< COPS command returned short name */ - GSM_OPERATOR_FORMAT_NUMBER, /*!< COPS command returned number */ - GSM_OPERATOR_FORMAT_INVALID /*!< Unknown format */ -} gsm_operator_format_t; - -/** - * \ingroup GSM_OPERATOR - * \brief Operator details for scan - */ -typedef struct { - gsm_operator_status_t stat; /*!< Operator status */ - char long_name[20]; /*!< Operator long name */ - char short_name[20]; /*!< Operator short name */ - uint32_t num; /*!< Operator numeric value */ -} gsm_operator_t; - -/** - * \ingroup GSM_OPERATOR - * \brief Current operator info - */ -typedef struct { - gsm_operator_mode_t mode; /*!< Operator mode */ - gsm_operator_format_t format; /*!< Data format */ - union { - char long_name[20]; /*!< Long name format */ - char short_name[20]; /*!< Short name format */ - uint32_t num; /*!< Number format */ - } data; /*!< Operator data union */ -} gsm_operator_curr_t; - -/** - * \ingroup GSM_NETWORK - * \brief Network Registration status - */ -typedef enum { - GSM_NETWORK_REG_STATUS_SIM_ERR = 0x00, /*!< SIM card error */ - GSM_NETWORK_REG_STATUS_CONNECTED = 0x01, /*!< Device is connected to network */ - GSM_NETWORK_REG_STATUS_SEARCHING = 0x02, /*!< Network search is in progress */ - GSM_NETWORK_REG_STATUS_DENIED = 0x03, /*!< Registration denied */ - GSM_NETWORK_REG_STATUS_CONNECTED_ROAMING = 0x05,/*!< Device is connected and is roaming */ - GSM_NETWORK_REG_STATUS_CONNECTED_SMS_ONLY = 0x06, /*!< Device is connected to home network in SMS-only mode */ - GSM_NETWORK_REG_STATUS_CONNECTED_ROAMING_SMS_ONLY = 0x07/*!< Device is roaming in SMS-only mode */ -} gsm_network_reg_status_t; - -/** - * \ingroup GSM_CALL - * \brief List of call directions - */ -typedef enum { - GSM_CALL_DIR_MO = 0x00, /*!< Mobile Originated, outgoing call */ - GSM_CALL_DIR_MT, /*!< Mobile Terminated, incoming call */ -} gsm_call_dir_t; - -/** - * \ingroup GSM_CALL - * \brief List of call states - */ -typedef enum { - GSM_CALL_STATE_ACTIVE = 0x00, /*!< Call is active */ - GSM_CALL_STATE_HELD, /*!< Call is held */ - GSM_CALL_STATE_DIALING, /*!< Call is dialing */ - GSM_CALL_STATE_ALERTING, /*!< Call is alerting */ - GSM_CALL_STATE_INCOMING, /*!< Call is incoming */ - GSM_CALL_STATE_WAITING, /*!< Call is waiting */ - GSM_CALL_STATE_DISCONNECT, /*!< Call disconnected, call finished */ -} gsm_call_state_t; - -/** - * \ingroup GSM_CALL - * \brief List of call types - */ -typedef enum { - GSM_CALL_TYPE_VOICE = 0x00, /*!< Voice call */ - GSM_CALL_TYPE_DATA, /*!< Data call */ - GSM_CALL_TYPE_FAX, /*!< Fax call */ -} gsm_call_type_t; - -/** - * \ingroup GSM_CALL - * \brief Call information - * \note Data received on `+CLCC` info - */ -typedef struct { - uint8_t ready; /*!< Flag indicating feature ready by device */ - uint8_t enabled; /*!< Flag indicating feature enabled */ - - uint8_t id; /*!< Call identification number, 0-7 */ - gsm_call_dir_t dir; /*!< Call direction */ - gsm_call_state_t state; /*!< Call state */ - gsm_call_type_t type; /*!< Call type */ - char number[20]; /*!< Phone number */ - char is_multipart; /*!< Multipart status */ - uint8_t addr_type; /*!< Address type */ - char name[20]; /*!< Phone book name if exists for current number */ -} gsm_call_t; - -/* Forward declarations */ -struct gsm_evt; -struct gsm_conn; -struct gsm_pbuf; - -/** - * \ingroup GSM_CONN - * \brief Pointer to \ref gsm_conn_t structure - */ -typedef struct gsm_conn* gsm_conn_p; - -/** - * \ingroup GSM_PBUF - * \brief Pointer to \ref gsm_pbuf_t structure - */ -typedef struct gsm_pbuf* gsm_pbuf_p; - -/** - * \ingroup GSM_EVT - * \brief Event function prototype - * \param[in] evt: Callback event data - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - */ -typedef gsmr_t (*gsm_evt_fn)(struct gsm_evt* evt); - -/** - * \ingroup GSM_EVT - * \brief List of possible callback types received to user - */ -typedef enum gsm_cb_type_t { - GSM_EVT_INIT_FINISH, /*!< Initialization has been finished at this point */ - - GSM_EVT_RESET, /*!< Device reset operation finished */ - GSM_EVT_RESTORE, /*!< Device restore operation finished */ - - GSM_EVT_CMD_TIMEOUT, /*!< Timeout on command. - When application receives this event, - it may reset system as there was (maybe) a problem in device */ - - GSM_EVT_DEVICE_PRESENT, /*!< Notification when device present status changes */ - GSM_EVT_DEVICE_IDENTIFIED, /*!< Device identified event */ - - GSM_EVT_SIGNAL_STRENGTH, /*!< Signal strength event */ - - GSM_EVT_SIM_STATE_CHANGED, /*!< SIM card state changed */ - - GSM_EVT_OPERATOR_SCAN, /*!< Operator scan finished event */ - - GSM_EVT_NETWORK_OPERATOR_CURRENT, /*!< Current operator event */ - GSM_EVT_NETWORK_REG_CHANGED, /*!< Network registration changed. Available even when \ref GSM_CFG_NETWORK is disabled */ -#if GSM_CFG_NETWORK || __DOXYGEN__ - GSM_EVT_NETWORK_ATTACHED, /*!< Attached to network, PDP context active and ready for TCP/IP application */ - GSM_EVT_NETWORK_DETACHED, /*!< Detached from network, PDP context not active anymore */ -#endif /* GSM_CFG_NETWORK || __DOXYGEN__ */ - -#if GSM_CFG_CONN || __DOXYGEN__ - GSM_EVT_CONN_RECV, /*!< Connection data received */ - GSM_EVT_CONN_SEND, /*!< Connection data send */ - GSM_EVT_CONN_ACTIVE, /*!< Connection just became active */ - GSM_EVT_CONN_ERROR, /*!< Client connection start was not successful */ - GSM_EVT_CONN_CLOSE, /*!< Connection close event. Check status if successful */ - GSM_EVT_CONN_POLL, /*!< Poll for connection if there are any changes */ -#endif /* GSM_CFG_CONN || __DOXYGEN__ */ - -#if GSM_CFG_SMS || __DOXYGEN__ - GSM_EVT_SMS_ENABLE, /*!< SMS enable event */ - GSM_EVT_SMS_READY, /*!< SMS ready event */ - GSM_EVT_SMS_SEND, /*!< SMS send event */ - GSM_EVT_SMS_RECV, /*!< SMS received */ - GSM_EVT_SMS_READ, /*!< SMS read */ - GSM_EVT_SMS_DELETE, /*!< SMS delete */ - GSM_EVT_SMS_LIST, /*!< SMS list */ -#endif /* GSM_CFG_SMS || __DOXYGEN__ */ -#if GSM_CFG_CALL || __DOXYGEN__ - GSM_EVT_CALL_ENABLE, /*!< Call enable event */ - GSM_EVT_CALL_READY, /*!< Call ready event */ - GSM_EVT_CALL_CHANGED, /*!< Call info changed, `+CLCK` statement received */ - GSM_EVT_CALL_RING, /*!< Call is ringing event */ - GSM_EVT_CALL_BUSY, /*!< Call is busy */ - GSM_EVT_CALL_NO_CARRIER, /*!< No carrier to make a call */ -#endif /* GSM_CFG_CALL || __DOXYGEN__ */ -#if GSM_CFG_PHONEBOOK || __DOXYGEN__ - GSM_EVT_PB_ENABLE, /*!< Phonebook enable event */ - GSM_EVT_PB_LIST, /*!< Phonebook list event */ - GSM_EVT_PB_SEARCH, /*!< Phonebook search event */ -#endif /* GSM_CFG_PHONEBOOK || __DOXYGEN__ */ -} gsm_evt_type_t; - -/** - * \ingroup GSM_EVT - * \brief Global callback structure to pass as parameter to callback function - */ -typedef struct gsm_evt { - gsm_evt_type_t type; /*!< Callback type */ - union { - struct { - gsmr_t res; /*!< Reset operation result */ - } reset; /*!< Reset sequence finish. Use with \ref GSM_EVT_RESET event */ - struct { - gsmr_t res; /*!< Restore operation result */ - } restore; /*!< Restore sequence finish. Use with \ref GSM_EVT_RESTORE event */ - - struct { - gsm_sim_state_t state; /*!< SIM state */ - } cpin; /*!< CPIN event */ - struct { - const gsm_operator_curr_t* operator_current; /*!< Current operator info */ - } operator_current; /*!< Current operator event. Use with \ref GSM_EVT_NETWORK_OPERATOR_CURRENT event */ - struct { - gsm_operator_t* ops; /*!< Pointer to operators */ - size_t opf; /*!< Number of operators found */ - gsmr_t res; /*!< Scan operation result */ - } operator_scan; /*!< Operator scan event. Use with \ref GSM_EVT_OPERATOR_SCAN event */ - - struct { - int16_t rssi; /*!< Strength in units of dBm */ - } rssi; /*!< Signal strength event. Use with \ref GSM_EVT_SIGNAL_STRENGTH event */ - -#if GSM_CFG_CONN || __DOXYGEN__ - struct { - gsm_conn_p conn; /*!< Connection where data were received */ - gsm_pbuf_p buff; /*!< Pointer to received data */ - } conn_data_recv; /*!< Network data received. Use with \ref GSM_EVT_CONN_RECV event */ - struct { - gsm_conn_p conn; /*!< Connection where data were sent */ - size_t sent; /*!< Number of bytes sent on connection */ - gsmr_t res; /*!< Send data result */ - } conn_data_send; /*!< Data successfully sent. Use with \ref GSM_EVT_CONN_SEND event */ - struct { - const char* host; /*!< Host to use for connection */ - gsm_port_t port; /*!< Remote port used for connection */ - gsm_conn_type_t type; /*!< Connection type */ - void* arg; /*!< Connection argument used on connection */ - gsmr_t err; /*!< Error value */ - } conn_error; /*!< Client connection start error. Use with \ref GSM_EVT_CONN_ERROR event */ - struct { - gsm_conn_p conn; /*!< Pointer to connection */ - uint8_t client; /*!< Set to `1` if connection is/was client mode */ - uint8_t forced; /*!< Set to `1` if connection action was forced (when active: 1 = CLIENT, 0 = SERVER: when closed, 1 = CMD, 0 = REMOTE) */ - gsmr_t res; /*!< Result of close event. Set to \ref gsmOK on success. */ - } conn_active_close; /*!< Process active and closed statuses at the same time. Use with \ref GSM_EVT_CONN_ACTIVE or \ref GSM_EVT_CONN_CLOSE events */ - struct { - gsm_conn_p conn; /*!< Set connection pointer */ - } conn_poll; /*!< Polling active connection to check for timeouts. Use with \ref GSM_EVT_CONN_POLL event */ -#endif /* GSM_CFG_CONN || __DOXYGEN__ */ - -#if GSM_CFG_SMS || __DOXYGEN__ - struct { - gsmr_t status; /*!< Enable status */ - } sms_enable; /*!< SMS enable event. Use with \ref GSM_EVT_SMS_ENABLE event */ - struct { - size_t pos; /*!< Position in memory */ - gsmr_t res; /*!< SMS send result information */ - } sms_send; /*!< SMS sent info. Use with \ref GSM_EVT_SMS_SEND event */ - struct { - gsm_mem_t mem; /*!< Memory of received message */ - size_t pos; /*!< Received position in memory for sent SMS */ - } sms_recv; /*!< SMS received info. Use with \ref GSM_EVT_SMS_RECV event */ - struct { - gsm_sms_entry_t* entry; /*!< SMS entry */ - gsmr_t res; /*!< SMS read result information */ - } sms_read; /*!< SMS read. Use with \ref GSM_EVT_SMS_READ event */ - struct { - gsm_mem_t mem; /*!< Memory of deleted message */ - size_t pos; /*!< Deleted position in memory for sent SMS */ - gsmr_t res; /*!< Operation success */ - } sms_delete; /*!< SMS delete. Use with \ref GSM_EVT_SMS_DELETE event */ - struct { - gsm_mem_t mem; /*!< Memory used for scan */ - gsm_sms_entry_t* entries; /*!< Pointer to entries */ - size_t size; /*!< Number of valid entries */ - gsmr_t res; /*!< Result on command */ - } sms_list; /*!< SMS list. Use with \ref GSM_EVT_SMS_LIST event */ -#endif /* GSM_CFG_SMS || __DOXYGEN__ */ -#if GSM_CFG_CALL || __DOXYGEN__ - struct { - gsmr_t res; /*!< Enable status */ - } call_enable; /*!< Call enable event. Use with \ref GSM_EVT_CALL_ENABLE event */ - struct { - const gsm_call_t* call; /*!< Call information */ - } call_changed; /*!< Call changed info. Use with \ref GSM_EVT_CALL_CHANGED event */ -#endif /* GSM_CFG_CALL || __DOXYGEN__ */ -#if GSM_CFG_PHONEBOOK || __DOXYGEN__ - struct { - gsmr_t res; /*!< Enable status */ - } pb_enable; /*!< Phonebook enable event. Use with \ref GSM_EVT_PB_ENABLE event */ - struct { - gsm_mem_t mem; /*!< Memory used for scan */ - gsm_pb_entry_t* entries; /*!< Pointer to entries */ - size_t size; /*!< Number of valid entries */ - gsmr_t res; /*!< Operation success */ - } pb_list; /*!< Phonebok list. Use with \ref GSM_EVT_PB_LIST event */ - struct { - const char* search; /*!< Search string */ - gsm_mem_t mem; /*!< Memory used for scan */ - gsm_pb_entry_t* entries; /*!< Pointer to entries */ - size_t size; /*!< Number of valid entries */ - gsmr_t res; /*!< Operation success */ - } pb_search; /*!< Phonebok search list. Use with \ref GSM_EVT_PB_SEARCH event */ -#endif /* GSM_CFG_PHONEBOOK || __DOXYGEN__ */ - } evt; /*!< Callback event union */ -} gsm_evt_t; - -#define GSM_SIZET_MAX ((size_t)(-1)) /*!< Maximal value of size_t variable type */ - -/** - * \ingroup GSM_LL - * \brief Function prototype for AT output data - * \param[in] data: Pointer to data to send. This parameter can be set to `NULL` - * \param[in] len: Number of bytes to send. This parameter can be set to `0` - * to indicate that internal buffer can be flushed to stream. - * This is implementation defined and feature might be ignored - * \return Number of bytes sent - */ -typedef size_t (*gsm_ll_send_fn)(const void* data, size_t len); - -/** - * \ingroup GSM_LL - * \brief Function prototype for hardware reset of GSM device - * \param[in] state: State indicating reset. When set to `1`, reset must be active (usually pin active low), - * or set to `0` when reset is cleared - * \return `1` on successful action, `0` otherwise - */ -typedef uint8_t (*gsm_ll_reset_fn)(uint8_t state); - -/** - * \ingroup GSM_LL - * \brief Low level user specific functions - */ -typedef struct { - gsm_ll_send_fn send_fn; /*!< Callback function to transmit data */ - gsm_ll_reset_fn reset_fn; /*!< Reset callback function */ - struct { - uint32_t baudrate; /*!< UART baudrate value */ - } uart; /*!< UART communication parameters */ -} gsm_ll_t; - -/** - * \ingroup GSM_TIMEOUT - * \brief Timeout callback function prototype - * \param[in] arg: Custom user argument - */ -typedef void (*gsm_timeout_fn)(void* arg); - -/** - * \ingroup GSM_TIMEOUT - * \brief Timeout structure - */ -typedef struct gsm_timeout { - struct gsm_timeout* next; /*!< Pointer to next timeout entry */ - uint32_t time; /*!< Time difference from previous entry */ - void* arg; /*!< Argument to pass to callback function */ - gsm_timeout_fn fn; /*!< Callback function for timeout */ -} gsm_timeout_t; - -/** - * \ingroup GSM_BUFF - * \brief Buffer structure - */ -typedef struct { - uint8_t* buff; /*!< Pointer to buffer data. - Buffer is considered initialized when `buff != NULL` */ - size_t size; /*!< Size of buffer data. Size of actual buffer is `1` byte less than this value */ - size_t r; /*!< Next read pointer. Buffer is considered empty when `r == w` and full when `w == r - 1` */ - size_t w; /*!< Next write pointer. Buffer is considered empty when `r == w` and full when `w == r - 1` */ -} gsm_buff_t; - -/** - * \ingroup GSM_TYPEDEFS - * \brief Linear buffer structure - */ -typedef struct { - uint8_t* buff; /*!< Pointer to buffer data array */ - size_t len; /*!< Length of buffer array */ - size_t ptr; /*!< Current buffer pointer */ -} gsm_linbuff_t; - -/** - * \ingroup GSM_TYPEDEFS - * \brief Function declaration for API function command event callback function - * \param[in] res: Operation result, member of \ref gsmr_t enumeration - * \param[in] arg: Custom user argument - */ -typedef void (*gsm_api_cmd_evt_fn) (gsmr_t res, void* arg); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* GSM_HDR_DEFS_H */ diff --git a/gsm_at_lib/src/include/system/gsm_sys.h b/gsm_at_lib/src/include/system/gsm_sys.h deleted file mode 100644 index dbcff241..00000000 --- a/gsm_at_lib/src/include/system/gsm_sys.h +++ /dev/null @@ -1,128 +0,0 @@ -/** - * \file gsm_sys.h - * \brief Main system include file which decides later include file - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_MAIN_SYS_H -#define GSM_HDR_MAIN_SYS_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include "gsm_config.h" - -/** - * \ingroup GSM_PORT - * \defgroup GSM_SYS System functions - * \brief System based function for OS management, timings, etc - * \{ - */ - -/** - * \brief Thread function prototype - */ -typedef void (*gsm_sys_thread_fn)(void *); - -/** - * \anchor GSM_SYS_PORTS - * \name System ports - * \{ - * - * List of already available system ports. - * Configure \ref GSM_CFG_SYS_PORT with one of these values to use preconfigured ports - */ - -#define GSM_SYS_PORT_CMSIS_OS 1 /*!< CMSIS-OS based port for OS systems capable of ARM CMSIS standard */ -#define GSM_SYS_PORT_WIN32 2 /*!< WIN32 based port to use GSM library with Windows applications */ -#define GSM_SYS_PORT_CMSIS_OS2 3 /*!< CMSIS-OS v2 based port for OS systems capable of ARM CMSIS standard */ -#define GSM_SYS_PORT_USER 99 /*!< User custom implementation. - When port is selected to user mode, user must provide "gsm_sys_user.h" file, - which is not provided with library. Refer to `system/gsm_sys_template.h` file for more information - */ - -/** - * \} - */ - -/* Decide which port to include */ -#if GSM_CFG_SYS_PORT == GSM_SYS_PORT_CMSIS_OS -#include "system/gsm_sys_cmsis_os.h" -#elif ESP_CFG_SYS_PORT == GSM_SYS_PORT_CMSIS_OS2 -#include "system/esp_sys_cmsis_os2.h" -#elif GSM_CFG_SYS_PORT == GSM_SYS_PORT_WIN32 -#include "system/gsm_sys_win32.h" -#elif GSM_CFG_SYS_PORT == GSM_SYS_PORT_USER -#include "gsm_sys_user.h" -#endif - -uint8_t gsm_sys_init(void); -uint32_t gsm_sys_now(void); - -uint8_t gsm_sys_protect(void); -uint8_t gsm_sys_unprotect(void); - -uint8_t gsm_sys_mutex_create(gsm_sys_mutex_t* p); -uint8_t gsm_sys_mutex_delete(gsm_sys_mutex_t* p); -uint8_t gsm_sys_mutex_lock(gsm_sys_mutex_t* p); -uint8_t gsm_sys_mutex_unlock(gsm_sys_mutex_t* p); -uint8_t gsm_sys_mutex_isvalid(gsm_sys_mutex_t* p); -uint8_t gsm_sys_mutex_invalid(gsm_sys_mutex_t* p); - -uint8_t gsm_sys_sem_create(gsm_sys_sem_t* p, uint8_t cnt); -uint8_t gsm_sys_sem_delete(gsm_sys_sem_t* p); -uint32_t gsm_sys_sem_wait(gsm_sys_sem_t* p, uint32_t timeout); -uint8_t gsm_sys_sem_release(gsm_sys_sem_t* p); -uint8_t gsm_sys_sem_isvalid(gsm_sys_sem_t* p); -uint8_t gsm_sys_sem_invalid(gsm_sys_sem_t* p); - -uint8_t gsm_sys_mbox_create(gsm_sys_mbox_t* b, size_t size); -uint8_t gsm_sys_mbox_delete(gsm_sys_mbox_t* b); -uint32_t gsm_sys_mbox_put(gsm_sys_mbox_t* b, void* m); -uint32_t gsm_sys_mbox_get(gsm_sys_mbox_t* b, void** m, uint32_t timeout); -uint8_t gsm_sys_mbox_putnow(gsm_sys_mbox_t* b, void* m); -uint8_t gsm_sys_mbox_getnow(gsm_sys_mbox_t* b, void** m); -uint8_t gsm_sys_mbox_isvalid(gsm_sys_mbox_t* b); -uint8_t gsm_sys_mbox_invalid(gsm_sys_mbox_t* b); - -uint8_t gsm_sys_thread_create(gsm_sys_thread_t* t, const char* name, gsm_sys_thread_fn thread_func, void* const arg, size_t stack_size, gsm_sys_thread_prio_t prio); -uint8_t gsm_sys_thread_terminate(gsm_sys_thread_t* t); -uint8_t gsm_sys_thread_yield(void); - -/** - * \} - */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* GSM_HDR_MAIN_LL_H */ diff --git a/gsm_at_lib/src/include/system/gsm_sys_cmsis_os2.h b/gsm_at_lib/src/include/system/gsm_sys_cmsis_os2.h deleted file mode 100644 index 04d9d572..00000000 --- a/gsm_at_lib/src/include/system/gsm_sys_cmsis_os2.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * \file gsm_sys_cmsis_os2.h - * \brief CMSIS-OS V2 based system file - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_SYSTEM_CMSIS_OS2_H -#define GSM_HDR_SYSTEM_CMSIS_OS2_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include -#include - -#include "gsm_config.h" - -#if GSM_CFG_OS && !__DOXYGEN__ - -#include "cmsis_os2.h" - -typedef osMutexId_t gsm_sys_mutex_t; -typedef osSemaphoreId_t gsm_sys_sem_t; -typedef osMessageQueueId_t gsm_sys_mbox_t; -typedef osThreadId_t gsm_sys_thread_t; -typedef osPriority_t gsm_sys_thread_prio_t; -#define GSM_SYS_MBOX_NULL (gsm_sys_mbox_t)0 -#define GSM_SYS_SEM_NULL (gsm_sys_sem_t)0 -#define GSM_SYS_MUTEX_NULL (gsm_sys_mutex_t)0 -#define GSM_SYS_TIMEOUT ((uint32_t)osWaitForever) -#define GSM_SYS_THREAD_PRIO (osPriorityNormal) -#define GSM_SYS_THREAD_SS (256) - -#endif /* GSM_CFG_OS && !__DOXYGEN__ */ - -#ifdef __cplusplus -}; -#endif /* __cplusplus */ - -#endif /* GSM_HDR_SYSTEM_CMSIS_OS2_H */ diff --git a/gsm_at_lib/src/include/system/gsm_sys_template.h b/gsm_at_lib/src/include/system/gsm_sys_template.h deleted file mode 100644 index 9d7ab38e..00000000 --- a/gsm_at_lib/src/include/system/gsm_sys_template.h +++ /dev/null @@ -1,131 +0,0 @@ -/** - * \file gsm_sys_template.h - * \brief Template file for system functions - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#ifndef GSM_HDR_SYSTEM_H -#define GSM_HDR_SYSTEM_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include -#include - -#include "gsm_config.h" - -/** - * \addtogroup GSM_SYS - * \{ - */ - -#if GSM_CFG_OS || __DOXYGEN__ -#include "cmsis_os.h" - -/** - * \brief GSM system mutex ID type - * \note Keep as is in case of CMSIS based OS, otherwise change for your OS - */ -typedef osMutexId gsm_sys_mutex_t; - -/** - * \brief GSM system semaphore ID type - * \note Keep as is in case of CMSIS based OS, otherwise change for your OS - */ -typedef osSemaphoreId gsm_sys_sem_t; - -/** - * \brief GSM system message queue ID type - * \note Keep as is in case of CMSIS based OS, otherwise change for your OS - */ -typedef osMessageQId gsm_sys_mbox_t; - -/** - * \brief GSM system thread ID type - * \note Keep as is in case of CMSIS based OS, otherwise change for your OS - */ -typedef osThreadId gsm_sys_thread_t; - -/** - * \brief GSM system thread priority type - * \note Keep as is in case of CMSIS based OS, otherwise change for your OS - */ -typedef osPriority gsm_sys_thread_prio_t; - -/** - * \brief Value indicating message queue is not valid - * \note Keep as is in case of CMSIS based OS, otherwise change for your OS - */ -#define GSM_SYS_MBOX_NULL (osMessageQId)0 - -/** - * \brief Value indicating semaphore is not valid - * \note Keep as is in case of CMSIS based OS, otherwise change for your OS - */ -#define GSM_SYS_SEM_NULL (osSemaphoreId)0 - -/** - * \brief Value indicating mutex is not valid - * \note Keep as is in case of CMSIS based OS, otherwise change for your OS - */ -#define GSM_SYS_MUTEX_NULL (osMutexId)0 - -/** - * \brief Value indicating timeout for OS timings - * \note Keep as is in case of CMSIS based OS, otherwise change for your OS - */ -#define GSM_SYS_TIMEOUT ((uint32_t)osWaitForever) - -/** - * \brief GSM stack threads priority parameter - * \note Usually normal priority is ok. If many threads are in the system and high traffic is introduced - * This value might need to be set to higher value - * \note Keep as is in case of CMSIS based OS, otherwise change for your OS - */ -#define GSM_SYS_THREAD_PRIO (osPriorityNormal) - -/** - * \brief Stack size of system threads - * \note Keep as is in case of CMSIS based OS, otherwise change for your OS - */ -#define GSM_SYS_THREAD_SS (1024) -#endif /* GSM_CFG_OS || __DOXYGEN__ */ - -/** - * \} - */ - -#ifdef __cplusplus -}; -#endif /* __cplusplus */ - -#endif /* GSM_HDR_SYSTEM_H */ diff --git a/gsm_at_lib/src/system/gsm_ll_stm32.c b/gsm_at_lib/src/system/gsm_ll_stm32.c deleted file mode 100644 index a6f062dc..00000000 --- a/gsm_at_lib/src/system/gsm_ll_stm32.c +++ /dev/null @@ -1,409 +0,0 @@ -/** - * \file gsm_ll_stm32.c - * \brief Generic STM32 driver, included in various STM32 driver variants - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ - -/* - * How it works - * - * On first call to \ref gsm_ll_init, new thread is created and processed in usart_ll_thread function. - * USART is configured in RX DMA mode and any incoming bytes are processed inside thread function. - * DMA and USART implement interrupt handlers to notify main thread about new data ready to send to upper layer. - * - * More about UART + RX DMA: https://github.com/MaJerle/STM32_USART_DMA_RX - * - * \ref GSM_CFG_INPUT_USE_PROCESS must be enabled in `gsm_config.h` to use this driver. - */ -#include "gsm/gsm.h" -#include "gsm/gsm_mem.h" -#include "gsm/gsm_input.h" -#include "system/gsm_ll.h" - -#if !__DOXYGEN__ - -#if !GSM_CFG_INPUT_USE_PROCESS -#error "GSM_CFG_INPUT_USE_PROCESS must be enabled in `gsm_config.h` to use this driver." -#endif /* GSM_CFG_INPUT_USE_PROCESS */ - -#if !defined(GSM_USART_DMA_RX_BUFF_SIZE) -#define GSM_USART_DMA_RX_BUFF_SIZE 0x1000 -#endif /* !defined(GSM_USART_DMA_RX_BUFF_SIZE) */ - -#if !defined(GSM_MEM_SIZE) -#define GSM_MEM_SIZE 0x1000 -#endif /* !defined(GSM_MEM_SIZE) */ - -#if !defined(GSM_USART_RDR_NAME) -#define GSM_USART_RDR_NAME RDR -#endif /* !defined(GSM_USART_RDR_NAME) */ - -/* USART memory */ -static uint8_t usart_mem[GSM_USART_DMA_RX_BUFF_SIZE]; -static uint8_t is_running, initialized; -static size_t old_pos; - -/* USART thread */ -static void usart_ll_thread(void const * arg); -static osThreadDef(usart_ll_thread, usart_ll_thread, osPriorityNormal, 0, 1024); -static osThreadId usart_ll_thread_id; - -/* Message queue */ -static osMessageQDef(usart_ll_mbox, 10, uint8_t); -static osMessageQId usart_ll_mbox_id; - -/** - * \brief USART data processing - */ -static void -usart_ll_thread(void const * arg) { - osEvent evt; - size_t pos; - static size_t old_pos; - - GSM_UNUSED(arg); - - while (1) { - /* Wait for the event message from DMA or USART */ - evt = osMessageGet(usart_ll_mbox_id, osWaitForever); - if (evt.status != osEventMessage) { - continue; - } - - /* Read data */ -#if defined(GSM_USART_DMA_RX_STREAM) - pos = sizeof(usart_mem) - LL_DMA_GetDataLength(GSM_USART_DMA, GSM_USART_DMA_RX_STREAM); -#else - pos = sizeof(usart_mem) - LL_DMA_GetDataLength(GSM_USART_DMA, GSM_USART_DMA_RX_CH); -#endif /* defined(GSM_USART_DMA_RX_STREAM) */ - if (pos != old_pos && is_running) { - if (pos > old_pos) { - gsm_input_process(&usart_mem[old_pos], pos - old_pos); - } else { - gsm_input_process(&usart_mem[old_pos], sizeof(usart_mem) - old_pos); - if (pos > 0) { - gsm_input_process(&usart_mem[0], pos); - } - } - old_pos = pos; - if (old_pos == sizeof(usart_mem)) { - old_pos = 0; - } - } - } -} - -/** - * \brief Configure UART using DMA for receive in double buffer mode and IDLE line detection - */ -static void -configure_uart(uint32_t baudrate) { - static LL_USART_InitTypeDef usart_init; - static LL_DMA_InitTypeDef dma_init; - LL_GPIO_InitTypeDef gpio_init; - - if (!initialized) { - /* Enable peripheral clocks */ - GSM_USART_CLK; - GSM_USART_DMA_CLK; - GSM_USART_TX_PORT_CLK; - GSM_USART_RX_PORT_CLK; - -#if defined(GSM_RESET_PIN) - GSM_RESET_PORT_CLK; -#endif /* defined(GSM_RESET_PIN) */ - -#if defined(GSM_GPIO0_PIN) - GSM_GPIO0_PORT_CLK; -#endif /* defined(GSM_GPIO0_PIN) */ - -#if defined(GSM_GPIO2_PIN) - GSM_GPIO2_PORT_CLK; -#endif /* defined(GSM_GPIO2_PIN) */ - -#if defined(GSM_CH_PD_PIN) - GSM_CH_PD_PORT_CLK; -#endif /* defined(GSM_CH_PD_PIN) */ - - /* Global pin configuration */ - LL_GPIO_StructInit(&gpio_init); - gpio_init.OutputType = LL_GPIO_OUTPUT_PUSHPULL; - gpio_init.Pull = LL_GPIO_PULL_UP; - gpio_init.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; - gpio_init.Mode = LL_GPIO_MODE_OUTPUT; - -#if defined(GSM_RESET_PIN) - /* Configure RESET pin */ - gpio_init.Pin = GSM_RESET_PIN; - LL_GPIO_Init(GSM_RESET_PORT, &gpio_init); -#endif /* defined(GSM_RESET_PIN) */ - -#if defined(GSM_GPIO0_PIN) - /* Configure GPIO0 pin */ - gpio_init.Pin = GSM_GPIO0_PIN; - LL_GPIO_Init(GSM_GPIO0_PORT, &gpio_init); - LL_GPIO_SetOutputPin(GSM_GPIO0_PORT, GSM_GPIO0_PIN); -#endif /* defined(GSM_GPIO0_PIN) */ - -#if defined(GSM_GPIO2_PIN) - /* Configure GPIO2 pin */ - gpio_init.Pin = GSM_GPIO2_PIN; - LL_GPIO_Init(GSM_GPIO2_PORT, &gpio_init); - LL_GPIO_SetOutputPin(GSM_GPIO2_PORT, GSM_GPIO2_PIN); -#endif /* defined(GSM_GPIO2_PIN) */ - -#if defined(GSM_CH_PD_PIN) - /* Configure CH_PD pin */ - gpio_init.Pin = GSM_CH_PD_PIN; - LL_GPIO_Init(GSM_CH_PD_PORT, &gpio_init); - LL_GPIO_SetOutputPin(GSM_CH_PD_PORT, GSM_CH_PD_PIN); -#endif /* defined(GSM_CH_PD_PIN) */ - - /* Configure USART pins */ - gpio_init.Mode = LL_GPIO_MODE_ALTERNATE; - - /* TX PIN */ - gpio_init.Alternate = GSM_USART_TX_PIN_AF; - gpio_init.Pin = GSM_USART_TX_PIN; - LL_GPIO_Init(GSM_USART_TX_PORT, &gpio_init); - - /* RX PIN */ - gpio_init.Alternate = GSM_USART_RX_PIN_AF; - gpio_init.Pin = GSM_USART_RX_PIN; - LL_GPIO_Init(GSM_USART_RX_PORT, &gpio_init); - - /* Configure UART */ - LL_USART_DeInit(GSM_USART); - LL_USART_StructInit(&usart_init); - usart_init.BaudRate = baudrate; - usart_init.DataWidth = LL_USART_DATAWIDTH_8B; - usart_init.HardwareFlowControl = LL_USART_HWCONTROL_NONE; - usart_init.OverSampling = LL_USART_OVERSAMPLING_16; - usart_init.Parity = LL_USART_PARITY_NONE; - usart_init.StopBits = LL_USART_STOPBITS_1; - usart_init.TransferDirection = LL_USART_DIRECTION_TX_RX; - LL_USART_Init(GSM_USART, &usart_init); - - /* Enable USART interrupts and DMA request */ - LL_USART_EnableIT_IDLE(GSM_USART); - LL_USART_EnableIT_PE(GSM_USART); - LL_USART_EnableIT_ERROR(GSM_USART); - LL_USART_EnableDMAReq_RX(GSM_USART); - - /* Enable USART interrupts */ - NVIC_SetPriority(GSM_USART_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x07, 0x00)); - NVIC_EnableIRQ(GSM_USART_IRQ); - - /* Configure DMA */ - is_running = 0; -#if defined(GSM_USART_DMA_RX_STREAM) - LL_DMA_DeInit(GSM_USART_DMA, GSM_USART_DMA_RX_STREAM); - dma_init.Channel = GSM_USART_DMA_RX_CH; -#else - LL_DMA_DeInit(GSM_USART_DMA, GSM_USART_DMA_RX_CH); - dma_init.PeriphRequest = GSM_USART_DMA_RX_REQ_NUM; -#endif /* defined(GSM_USART_DMA_RX_STREAM) */ - dma_init.PeriphOrM2MSrcAddress = (uint32_t)&GSM_USART->GSM_USART_RDR_NAME; - dma_init.MemoryOrM2MDstAddress = (uint32_t)usart_mem; - dma_init.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY; - dma_init.Mode = LL_DMA_MODE_CIRCULAR; - dma_init.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; - dma_init.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; - dma_init.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE; - dma_init.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE; - dma_init.NbData = sizeof(usart_mem); - dma_init.Priority = LL_DMA_PRIORITY_MEDIUM; -#if defined(GSM_USART_DMA_RX_STREAM) - LL_DMA_Init(GSM_USART_DMA, GSM_USART_DMA_RX_STREAM, &dma_init); -#else - LL_DMA_Init(GSM_USART_DMA, GSM_USART_DMA_RX_CH, &dma_init); -#endif /* defined(GSM_USART_DMA_RX_STREAM) */ - - /* Enable DMA interrupts */ -#if defined(GSM_USART_DMA_RX_STREAM) - LL_DMA_EnableIT_HT(GSM_USART_DMA, GSM_USART_DMA_RX_STREAM); - LL_DMA_EnableIT_TC(GSM_USART_DMA, GSM_USART_DMA_RX_STREAM); - LL_DMA_EnableIT_TE(GSM_USART_DMA, GSM_USART_DMA_RX_STREAM); - LL_DMA_EnableIT_FE(GSM_USART_DMA, GSM_USART_DMA_RX_STREAM); - LL_DMA_EnableIT_DME(GSM_USART_DMA, GSM_USART_DMA_RX_STREAM); -#else - LL_DMA_EnableIT_HT(GSM_USART_DMA, GSM_USART_DMA_RX_CH); - LL_DMA_EnableIT_TC(GSM_USART_DMA, GSM_USART_DMA_RX_CH); - LL_DMA_EnableIT_TE(GSM_USART_DMA, GSM_USART_DMA_RX_CH); -#endif /* defined(GSM_USART_DMA_RX_STREAM) */ - - /* Enable DMA interrupts */ - NVIC_SetPriority(GSM_USART_DMA_RX_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x07, 0x00)); - NVIC_EnableIRQ(GSM_USART_DMA_RX_IRQ); - - old_pos = 0; - is_running = 1; - - /* Start DMA and USART */ -#if defined(GSM_USART_DMA_RX_STREAM) - LL_DMA_EnableStream(GSM_USART_DMA, GSM_USART_DMA_RX_STREAM); -#else - LL_DMA_EnableChannel(GSM_USART_DMA, GSM_USART_DMA_RX_CH); -#endif /* defined(GSM_USART_DMA_RX_STREAM) */ - LL_USART_Enable(GSM_USART); - } else { - osDelay(10); - LL_USART_Disable(GSM_USART); - usart_init.BaudRate = baudrate; - LL_USART_Init(GSM_USART, &usart_init); - LL_USART_Enable(GSM_USART); - } - - /* Create mbox and start thread */ - if (usart_ll_mbox_id == NULL) { - usart_ll_mbox_id = osMessageCreate(osMessageQ(usart_ll_mbox), NULL); - } - if (usart_ll_thread_id == NULL) { - usart_ll_thread_id = osThreadCreate(osThread(usart_ll_thread), usart_ll_mbox_id); - } -} - -#if defined(GSM_RESET_PIN) -/** - * \brief Hardware reset callback - */ -static uint8_t -reset_device(uint8_t state) { - if (state) { /* Activate reset line */ - LL_GPIO_ResetOutputPin(GSM_RESET_PORT, GSM_RESET_PIN); - } else { - LL_GPIO_SetOutputPin(GSM_RESET_PORT, GSM_RESET_PIN); - } - return 1; -} -#endif /* defined(GSM_RESET_PIN) */ - -/** - * \brief Send data to GSM device - * \param[in] data: Pointer to data to send - * \param[in] len: Number of bytes to send - * \return Number of bytes sent - */ -static size_t -send_data(const void* data, size_t len) { - const uint8_t* d = data; - - for (size_t i = 0; i < len; i++, d++) { - LL_USART_TransmitData8(GSM_USART, *d); - while (!LL_USART_IsActiveFlag_TXE(GSM_USART)) {} - } - return len; -} - -/** - * \brief Callback function called from initialization process - * \note This function may be called multiple times if AT baudrate is changed from application - * \param[in,out] ll: Pointer to \ref gsm_ll_t structure to fill data for communication functions - * \param[in] baudrate: Baudrate to use on AT port - * \return Member of \ref gsmr_t enumeration - */ -gsmr_t -gsm_ll_init(gsm_ll_t* ll) { -#if !GSM_CFG_MEM_CUSTOM - static uint8_t memory[GSM_MEM_SIZE]; - gsm_mem_region_t mem_regions[] = { - { memory, sizeof(memory) } - }; - - if (!initialized) { - gsm_mem_assignmemory(mem_regions, GSM_ARRAYSIZE(mem_regions)); /* Assign memory for allocations */ - } -#endif /* !GSM_CFG_MEM_CUSTOM */ - - if (!initialized) { - ll->send_fn = send_data; /* Set callback function to send data */ -#if defined(GSM_RESET_PIN) - ll->reset_fn = reset_device; /* Set callback for hardware reset */ -#endif /* defined(GSM_RESET_PIN) */ - } - - configure_uart(ll->uart.baudrate); /* Initialize UART for communication */ - initialized = 1; - return gsmOK; -} - -/** - * \brief Callback function to de-init low-level communication part - * \param[in,out] ll: Pointer to \ref gsm_ll_t structure to fill data for communication functions - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - */ -gsmr_t -gsm_ll_deinit(gsm_ll_t* ll) { - if (usart_ll_mbox_id != NULL) { - osMessageQId tmp = usart_ll_mbox_id; - usart_ll_mbox_id = NULL; - osMessageDelete(tmp); - } - if (usart_ll_thread_id != NULL) { - osThreadId tmp = usart_ll_thread_id; - usart_ll_thread_id = NULL; - osThreadTerminate(tmp); - } - initialized = 0; - GSM_UNUSED(ll); - return gsmOK; -} - -/** - * \brief UART global interrupt handler - */ -void -GSM_USART_IRQHANDLER(void) { - LL_USART_ClearFlag_IDLE(GSM_USART); - LL_USART_ClearFlag_PE(GSM_USART); - LL_USART_ClearFlag_FE(GSM_USART); - LL_USART_ClearFlag_ORE(GSM_USART); - LL_USART_ClearFlag_NE(GSM_USART); - - if (usart_ll_mbox_id != NULL) { - osMessagePut(usart_ll_mbox_id, 0, 0); - } -} - -/** - * \brief UART DMA stream/channel handler - */ -void -GSM_USART_DMA_RX_IRQHANDLER(void) { - GSM_USART_DMA_RX_CLEAR_TC; - GSM_USART_DMA_RX_CLEAR_HT; - - if (usart_ll_mbox_id != NULL) { - osMessagePut(usart_ll_mbox_id, 0, 0); - } -} - -#endif /* !__DOXYGEN__ */ diff --git a/gsm_at_lib/src/system/gsm_ll_stm32f429zi_nucleo.c b/gsm_at_lib/src/system/gsm_ll_stm32f429zi_nucleo.c deleted file mode 100644 index 6b9749ff..00000000 --- a/gsm_at_lib/src/system/gsm_ll_stm32f429zi_nucleo.c +++ /dev/null @@ -1,101 +0,0 @@ -/** - * \file gsm_ll_stm32f429zi_nucleo.c - * \brief Low-level communication with GSM device for STM32F429ZI-Nucleo using DMA - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ - -/* - * Default UART configuration is: - * - * UART: USART6 - * STM32 TX (GSM RX): GPIOC, GPIO_PIN_6 - * STM32 RX (GSM TX): GPIOC, GPIO_PIN_7 - * RESET: GPIOC, GPIO_PIN_5 - * - * USART_DMA: DMA2 - * USART_DMA_STREAM: DMA_STREAM_1 - * USART_DMA_CHANNEL: DMA_CHANNEL_5 - */ -#include "gsm/gsm.h" -#include "gsm/gsm_mem.h" -#include "gsm/gsm_input.h" -#include "system/gsm_ll.h" - -#if !__DOXYGEN__ - -#include "stm32f4xx_ll_bus.h" -#include "stm32f4xx_ll_usart.h" -#include "stm32f4xx_ll_gpio.h" -#include "stm32f4xx_ll_dma.h" -#include "stm32f4xx_ll_rcc.h" - -/* USART */ -#define GSM_USART USART6 -#define GSM_USART_CLK LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART6) -#define GSM_USART_IRQ USART6_IRQn -#define GSM_USART_IRQHANDLER USART6_IRQHandler -#define GSM_USART_RDR_NAME DR - -/* DMA settings */ -#define GSM_USART_DMA DMA2 -#define GSM_USART_DMA_CLK LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA2) -#define GSM_USART_DMA_RX_STREAM LL_DMA_STREAM_1 -#define GSM_USART_DMA_RX_CH LL_DMA_CHANNEL_5 -#define GSM_USART_DMA_RX_IRQ DMA2_Stream1_IRQn -#define GSM_USART_DMA_RX_IRQHANDLER DMA2_Stream1_IRQHandler - -/* DMA flags management */ -#define GSM_USART_DMA_RX_IS_TC LL_DMA_IsActiveFlag_TC1(GSM_USART_DMA) -#define GSM_USART_DMA_RX_IS_HT LL_DMA_IsActiveFlag_HT1(GSM_USART_DMA) -#define GSM_USART_DMA_RX_CLEAR_TC LL_DMA_ClearFlag_TC1(GSM_USART_DMA) -#define GSM_USART_DMA_RX_CLEAR_HT LL_DMA_ClearFlag_HT1(GSM_USART_DMA) - -/* USART TX PIN */ -#define GSM_USART_TX_PORT_CLK LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOC) -#define GSM_USART_TX_PORT GPIOC -#define GSM_USART_TX_PIN LL_GPIO_PIN_6 -#define GSM_USART_TX_PIN_AF LL_GPIO_AF_8 - -/* USART RX PIN */ -#define GSM_USART_RX_PORT_CLK LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOC) -#define GSM_USART_RX_PORT GPIOC -#define GSM_USART_RX_PIN LL_GPIO_PIN_7 -#define GSM_USART_RX_PIN_AF LL_GPIO_AF_8 - -/* RESET PIN */ -#define GSM_RESET_PORT_CLK LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOC) -#define GSM_RESET_PORT GPIOC -#define GSM_RESET_PIN LL_GPIO_PIN_5 - -/* Include STM32 generic driver */ -#include "../system/gsm_ll_stm32.c" - -#endif /* !__DOXYGEN__ */ diff --git a/gsm_at_lib/src/system/gsm_sys_cmsis_os.c b/gsm_at_lib/src/system/gsm_sys_cmsis_os.c deleted file mode 100644 index 079405d6..00000000 --- a/gsm_at_lib/src/system/gsm_sys_cmsis_os.c +++ /dev/null @@ -1,220 +0,0 @@ -/** - * \file gsm_sys_cmsis_os.c - * \brief System dependant functions for STM32 MCU with CMSIS OS - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#include "system/gsm_sys.h" -#include "cmsis_os.h" - -#if !__DOXYGEN__ - -static osMutexId sys_mutex; /* Mutex ID for main protection */ - -uint8_t -gsm_sys_init(void) { - gsm_sys_mutex_create(&sys_mutex); /* Create system mutex */ - return 1; -} - -uint32_t -gsm_sys_now(void) { - return osKernelSysTick(); /* Get current tick in units of milliseconds */ -} - -uint8_t -gsm_sys_protect(void) { - gsm_sys_mutex_lock(&sys_mutex); /* Lock system and protect it */ - return 1; -} - -uint8_t -gsm_sys_unprotect(void) { - gsm_sys_mutex_unlock(&sys_mutex); /* Release lock */ - return 1; -} - -uint8_t -gsm_sys_mutex_create(gsm_sys_mutex_t* p) { - osMutexDef(MUT); /* Define a mutex */ - *p = osRecursiveMutexCreate(osMutex(MUT)); /* Create recursive mutex */ - return *p != NULL; /* Return status */ -} - -uint8_t -gsm_sys_mutex_delete(gsm_sys_mutex_t* p) { - return osMutexDelete(*p) == osOK; /* Delete mutex */ -} - -uint8_t -gsm_sys_mutex_lock(gsm_sys_mutex_t* p) { - return osRecursiveMutexWait(*p, osWaitForever) == osOK; /* Wait forever for mutex */ -} - -uint8_t -gsm_sys_mutex_unlock(gsm_sys_mutex_t* p) { - return osRecursiveMutexRelease(*p) == osOK; /* Release mutex */ -} - -uint8_t -gsm_sys_mutex_isvalid(gsm_sys_mutex_t* p) { - return p != NULL && *p != NULL; /* Check if mutex is valid */ -} - -uint8_t -gsm_sys_mutex_invalid(gsm_sys_mutex_t* p) { - *p = GSM_SYS_MUTEX_NULL; /* Set mutex as invalid */ - return 1; -} - -uint8_t -gsm_sys_sem_create(gsm_sys_sem_t* p, uint8_t cnt) { - osSemaphoreDef(SEM); /* Define semaphore info */ - *p = osSemaphoreCreate(osSemaphore(SEM), 1);/* Create semaphore with one token */ - - if (*p != NULL && !cnt) { /* We have valid entry */ - osSemaphoreWait(*p, 0); /* Lock semaphore immediatelly */ - } - return *p != NULL; -} - -uint8_t -gsm_sys_sem_delete(gsm_sys_sem_t* p) { - return osSemaphoreDelete(*p) == osOK; /* Delete semaphore */ -} - -uint32_t -gsm_sys_sem_wait(gsm_sys_sem_t* p, uint32_t timeout) { - uint32_t tick = osKernelSysTick(); /* Get start tick time */ - return (osSemaphoreWait(*p, !timeout ? osWaitForever : timeout) == osOK) ? (osKernelSysTick() - tick) : GSM_SYS_TIMEOUT; /* Wait for semaphore with specific time */ -} - -uint8_t -gsm_sys_sem_release(gsm_sys_sem_t* p) { - return osSemaphoreRelease(*p) == osOK; /* Release semaphore */ -} - -uint8_t -gsm_sys_sem_isvalid(gsm_sys_sem_t* p) { - return p != NULL && *p != NULL; /* Check if valid */ -} - -uint8_t -gsm_sys_sem_invalid(gsm_sys_sem_t* p) { - *p = GSM_SYS_SEM_NULL; /* Invaldiate semaphore */ - return 1; -} - -uint8_t -gsm_sys_mbox_create(gsm_sys_mbox_t* b, size_t size) { - osMessageQDef(MBOX, size, void *); /* Define message box */ - *b = osMessageCreate(osMessageQ(MBOX), NULL); /* Create message box */ - return *b != NULL; -} - -uint8_t -gsm_sys_mbox_delete(gsm_sys_mbox_t* b) { - if (osMessageWaiting(*b)) { /* We still have messages in queue, should not delete queue */ - return 0; /* Return error as we still have entries in message queue */ - } - return osMessageDelete(*b) == osOK; /* Delete message queue */ -} - -uint32_t -gsm_sys_mbox_put(gsm_sys_mbox_t* b, void* m) { - uint32_t tick = osKernelSysTick(); /* Get start time */ - return osMessagePut(*b, (uint32_t)m, osWaitForever) == osOK ? (osKernelSysTick() - tick) : GSM_SYS_TIMEOUT; /* Put new message with forever timeout */ -} - -uint32_t -gsm_sys_mbox_get(gsm_sys_mbox_t* b, void** m, uint32_t timeout) { - osEvent evt; - uint32_t time = osKernelSysTick(); /* Get current time */ - - evt = osMessageGet(*b, !timeout ? osWaitForever : timeout); /* Get message event */ - if (evt.status == osEventMessage) { /* Did we get a message? */ - *m = evt.value.p; /* Set value */ - return osKernelSysTick() - time; /* Return time required for reading message */ - } - return GSM_SYS_TIMEOUT; -} - -uint8_t -gsm_sys_mbox_putnow(gsm_sys_mbox_t* b, void* m) { - return osMessagePut(*b, (uint32_t)m, 0) == osOK; /* Put new message without timeout */ -} - -uint8_t -gsm_sys_mbox_getnow(gsm_sys_mbox_t* b, void** m) { - osEvent evt; - - evt = osMessageGet(*b, 0); /* Get message event */ - if (evt.status == osEventMessage) { /* Did we get a message? */ - *m = evt.value.p; /* Set value */ - return 1; - } - return 0; -} - -uint8_t -gsm_sys_mbox_isvalid(gsm_sys_mbox_t* b) { - return b != NULL && *b != NULL; /* Return status if message box is valid */ -} - -uint8_t -gsm_sys_mbox_invalid(gsm_sys_mbox_t* b) { - *b = GSM_SYS_MBOX_NULL; /* Invalidate message box */ - return 1; -} - -uint8_t -gsm_sys_thread_create(gsm_sys_thread_t* t, const char* name, gsm_sys_thread_fn thread_func, void* const arg, size_t stack_size, gsm_sys_thread_prio_t prio) { - gsm_sys_thread_t id; - const osThreadDef_t thread_def = {(char *)name, (os_pthread)thread_func, (osPriority)prio, 0, stack_size ? stack_size : GSM_SYS_THREAD_SS }; /* Create thread description */ - id = osThreadCreate(&thread_def, arg); /* Create thread */ - if (t != NULL) { - *t = id; - } - return id != NULL; -} - -uint8_t -gsm_sys_thread_terminate(gsm_sys_thread_t* t) { - osThreadTerminate(t != NULL ? *t : NULL); /* Terminate thread */ - return 1; -} - -uint8_t -gsm_sys_thread_yield(void) { - osThreadYield(); /* Yield current thread */ - return 1; -} - -#endif /* !__DOXYGEN__ */ diff --git a/gsm_at_lib/src/system/gsm_sys_cmsis_os2.c b/gsm_at_lib/src/system/gsm_sys_cmsis_os2.c deleted file mode 100644 index a986cfbd..00000000 --- a/gsm_at_lib/src/system/gsm_sys_cmsis_os2.c +++ /dev/null @@ -1,218 +0,0 @@ -/** - * \file gsm_sys_cmsis_os2.c - * \brief System dependant functions for CMSIS based operating system - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * This file is part of GSM-AT library. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#include "system/gsm_sys.h" -#include "cmsis_os2.h" - -#if !__DOXYGEN__ -static osMutexId_t sys_mutex; - -uint8_t -gsm_sys_init(void) { - gsm_sys_mutex_create(&sys_mutex); - return 1; -} - -uint32_t -gsm_sys_now(void) { - return osKernelGetTickCount(); -} - -#if GSM_CFG_OS - -uint8_t -gsm_sys_protect(void) { - gsm_sys_mutex_lock(&sys_mutex); - return 1; -} - -uint8_t -gsm_sys_unprotect(void) { - gsm_sys_mutex_unlock(&sys_mutex); - return 1; -} - -uint8_t -gsm_sys_mutex_create(gsm_sys_mutex_t* p) { - const osMutexAttr_t attr = { - .attr_bits = osMutexRecursive - }; - - *p = osMutexNew(&attr); - return *p != NULL; -} - -uint8_t -gsm_sys_mutex_delete(gsm_sys_mutex_t* p) { - return osMutexDelete(*p) == osOK; -} - -uint8_t -gsm_sys_mutex_lock(gsm_sys_mutex_t* p) { - return osMutexAcquire(*p, osWaitForever) == osOK; -} - -uint8_t -gsm_sys_mutex_unlock(gsm_sys_mutex_t* p) { - return osMutexRelease(*p); -} - -uint8_t -gsm_sys_mutex_isvalid(gsm_sys_mutex_t* p) { - return p != NULL && *p != NULL; -} - -uint8_t -gsm_sys_mutex_invalid(gsm_sys_mutex_t* p) { - *p = GSM_SYS_MUTEX_NULL; - return 1; -} - -uint8_t -gsm_sys_sem_create(gsm_sys_sem_t* p, uint8_t cnt) { - *p = osSemaphoreNew(1, cnt > 0, NULL); - return *p != NULL; -} - -uint8_t -gsm_sys_sem_delete(gsm_sys_sem_t* p) { - return osSemaphoreDelete(*p) == osOK; -} - -uint32_t -gsm_sys_sem_wait(gsm_sys_sem_t* p, uint32_t timeout) { - uint32_t tick = osKernelGetTickCount(); - return (osSemaphoreAcquire(*p, !timeout ? osWaitForever : timeout) == osOK) ? (osKernelGetTickCount() - tick) : GSM_SYS_TIMEOUT; -} - -uint8_t -gsm_sys_sem_release(gsm_sys_sem_t* p) { - return osSemaphoreRelease(*p) == osOK; -} - -uint8_t -gsm_sys_sem_isvalid(gsm_sys_sem_t* p) { - return p != NULL && *p != NULL; -} - -uint8_t -gsm_sys_sem_invalid(gsm_sys_sem_t* p) { - *p = GSM_SYS_SEM_NULL; - return 1; -} - -uint8_t -gsm_sys_mbox_create(gsm_sys_mbox_t* b, size_t size) { - *b = osMessageQueueNew(size, sizeof(void *), NULL); - return *b != NULL; -} - -uint8_t -gsm_sys_mbox_delete(gsm_sys_mbox_t* b) { - if (osMessageQueueGetCount(*b)) { - return 0; - } - return osMessageQueueDelete(*b) == osOK; -} - -uint32_t -gsm_sys_mbox_put(gsm_sys_mbox_t* b, void* m) { - uint32_t tick = osKernelGetTickCount(); - return osMessageQueuePut(*b, m, 0, osWaitForever) == osOK ? (osKernelGetTickCount() - tick) : GSM_SYS_TIMEOUT; -} - -uint32_t -gsm_sys_mbox_get(gsm_sys_mbox_t* b, void** m, uint32_t timeout) { - osStatus_t evt; - uint32_t time = osKernelGetTickCount(); - - evt = osMessageQueueGet(*b, *m, NULL, !timeout ? osWaitForever : timeout); - if (evt == osOK) { - return osKernelGetTickCount() - time; - } - return GSM_SYS_TIMEOUT; -} - -uint8_t -gsm_sys_mbox_putnow(gsm_sys_mbox_t* b, void* m) { - return osMessageQueuePut(*b, m, 0, 0) == osOK; -} - -uint8_t -gsm_sys_mbox_getnow(gsm_sys_mbox_t* b, void** m) { - osStatus_t evt; - - evt = osMessageQueueGet(*b, *m, 0, 0); - return evt == osOK; -} - -uint8_t -gsm_sys_mbox_isvalid(gsm_sys_mbox_t* b) { - return b != NULL && *b != NULL; -} - -uint8_t -gsm_sys_mbox_invalid(gsm_sys_mbox_t* b) { - *b = GSM_SYS_MBOX_NULL; - return 1; -} - -uint8_t -gsm_sys_thread_create(gsm_sys_thread_t* t, const char* name, gsm_sys_thread_fn thread_func, void* const arg, size_t stack_size, gsm_sys_thread_prio_t prio) { - gsm_sys_thread_t id; - const osThreadAttr_t attr = { - .name = name, - .priority = prio, - .stack_size = stack_size > 0 ? stack_size : GSM_SYS_THREAD_SS - }; - id = osThreadNew(thread_func, arg, &attr); - if (t != NULL) { - *t = id; - } - return id != NULL; -} - -uint8_t -gsm_sys_thread_terminate(gsm_sys_thread_t* t) { - osThreadTerminate(t != NULL ? *t : NULL); - return 1; -} - -uint8_t -gsm_sys_thread_yield(void) { - osThreadYield(); - return 1; -} - -#endif /* GSM_CFG_OS */ -#endif /* !__DOXYGEN__ */ diff --git a/gsm_at_lib/src/system/gsm_sys_template.c b/gsm_at_lib/src/system/gsm_sys_template.c deleted file mode 100644 index e7a4b8f2..00000000 --- a/gsm_at_lib/src/system/gsm_sys_template.c +++ /dev/null @@ -1,395 +0,0 @@ -/** - * \file gsm_sys_template.c - * \brief System dependant functions - */ - -/* - * Copyright (c) 2019 Tilen MAJERLE - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Author: Tilen MAJERLE - * Version: v0.6.0 - */ -#include "system/gsm_sys.h" -#include "cmsis_os.h" - -/*******************************************/ -/*******************************************/ -/** Modify this file for your system **/ -/*******************************************/ -/*******************************************/ - -static osMutexId sys_mutex; /* Mutex ID for main protection */ - -/** - * \brief Init system dependant parameters - * \note Called from high-level application layer when required - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_init(void) { - gsm_sys_mutex_create(&sys_mutex); /* Create system mutex */ - return 1; -} - -/** - * \brief Get current time in units of milliseconds - * \return Current time in units of milliseconds - */ -uint32_t -gsm_sys_now(void) { - return osKernelSysTick(); /* Get current tick in units of milliseconds */ -} - -/** - * \brief Protect stack core - * \note This function is required with OS - * - * \note This function may be called multiple times, recursive protection is required - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_protect(void) { - gsm_sys_mutex_lock(&sys_mutex); /* Lock system and protect it */ - return 1; -} - -/** - * \brief Protect stack core - * \note This function is required with OS - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_unprotect(void) { - gsm_sys_mutex_unlock(&sys_mutex); /* Release lock */ - return 1; -} - -/** - * \brief Create a new mutex and pass it to input pointer - * \note This function is required with OS - * \note Recursive mutex must be created as it may be locked multiple times before unlocked - * \param[out] p: Pointer to mutex structure to save result to - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_mutex_create(gsm_sys_mutex_t* p) { - osMutexDef(MUT); /* Define a mutex */ - *p = osRecursiveMutexCreate(osMutex(MUT)); /* Create recursive mutex */ - return !!*p; /* Return status */ -} - -/** - * \brief Delete mutex from OS - * \note This function is required with OS - * \param[in] p: Pointer to mutex structure - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_mutex_delete(gsm_sys_mutex_t* p) { - return osMutexDelete(*p) == osOK; /* Delete mutex */ -} - -/** - * \brief Wait forever to lock the mutex - * \note This function is required with OS - * \param[in] p: Pointer to mutex structure - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_mutex_lock(gsm_sys_mutex_t* p) { - return osRecursiveMutexWait(*p, osWaitForever) == osOK; /* Wait forever for mutex */ -} - -/** - * \brief Unlock mutex - * \note This function is required with OS - * \param[in] p: Pointer to mutex structure - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_mutex_unlock(gsm_sys_mutex_t* p) { - return osRecursiveMutexRelease(*p) == osOK; /* Release mutex */ -} - -/** - * \brief Check if mutex structure is valid OS entry - * \note This function is required with OS - * \param[in] p: Pointer to mutex structure - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_mutex_isvalid(gsm_sys_mutex_t* p) { - return p != NULL && *p != NULL; /* Check if mutex is valid */ -} - -/** - * \brief Set mutex structure as invalid - * \note This function is required with OS - * \param[in] p: Pointer to mutex structure - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_mutex_invalid(gsm_sys_mutex_t* p) { - *p = GSM_SYS_MUTEX_NULL; /* Set mutex as invalid */ - return 1; -} - -/** - * \brief Create a new binary semaphore and set initial state - * \note Semaphore may only have 1 token available - * \note This function is required with OS - * \param[out] p: Pointer to semaphore structure to fill with result - * \param[in] cnt: Count indicating default semaphore state: - * 0: Lock it immediteally - * 1: Leave it unlocked - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_sem_create(gsm_sys_sem_t* p, uint8_t cnt) { - osSemaphoreDef(SEM); /* Define semaphore info */ - *p = osSemaphoreCreate(osSemaphore(SEM), 1); /* Create semaphore with one token */ - - if (*p && !cnt) { /* We have valid entry */ - osSemaphoreWait(*p, 0); /* Lock semaphore immediatelly */ - } - return !!*p; -} - -/** - * \brief Delete binary semaphore - * \note This function is required with OS - * \param[in] p: Pointer to semaphore structure - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_sem_delete(gsm_sys_sem_t* p) { - return osSemaphoreDelete(*p) == osOK; /* Delete semaphore */ -} - -/** - * \brief Wait for semaphore to be available - * \note This function is required with OS - * \param[in] p: Pointer to semaphore structure - * \param[in] timeout: Timeout to wait in milliseconds. When 0 is applied, wait forever - * \return Number of milliseconds waited for semaphore to become available - */ -uint32_t -gsm_sys_sem_wait(gsm_sys_sem_t* p, uint32_t timeout) { - uint32_t tick = osKernelSysTick(); /* Get start tick time */ - return (osSemaphoreWait(*p, !timeout ? osWaitForever : timeout) == osOK) ? (osKernelSysTick() - tick) : GSM_SYS_TIMEOUT; /* Wait for semaphore with specific time */ -} - -/** - * \brief Release semaphore - * \note This function is required with OS - * \param[in] p: Pointer to semaphore structure - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_sem_release(gsm_sys_sem_t* p) { - return osSemaphoreRelease(*p) == osOK; /* Release semaphore */ -} - -/** - * \brief Check if semaphore is valid - * \note This function is required with OS - * \param[in] p: Pointer to semaphore structure - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_sem_isvalid(gsm_sys_sem_t* p) { - return p != NULL && *p != NULL; /* Check if valid */ -} - -/** - * \brief Invalid semaphore - * \note This function is required with OS - * \param[in] p: Pointer to semaphore structure - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_sem_invalid(gsm_sys_sem_t* p) { - *p = GSM_SYS_SEM_NULL; /* Invaldiate semaphore */ - return 1; -} - -/** - * \brief Create a new message queue with entry type of "void *" - * \note This function is required with OS - * \param[out] b: Pointer to message queue structure - * \param[in] size: Number of entries for message queue to hold - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_mbox_create(gsm_sys_mbox_t* b, size_t size) { - osMessageQDef(MBOX, size, void *); /* Define message box */ - *b = osMessageCreate(osMessageQ(MBOX), NULL); /* Create message box */ - return !!*b; -} - -/** - * \brief Delete message queue - * \note This function is required with OS - * \param[in] b: Pointer to message queue structure - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_mbox_delete(gsm_sys_mbox_t* b) { - if (osMessageWaiting(*b)) { /* We still have messages in queue, should not delete queue */ - return 0; /* Return error as we still have entries in message queue */ - } - return osMessageDelete(*b) == osOK; /* Delete message queue */ -} - -/** - * \brief Put a new entry to message queue and wait until memory available - * \note This function is required with OS - * \param[in] b: Pointer to message queue structure - * \param[in] m: Pointer to entry to insert to message queue - * \return Time in units of milliseconds needed to put a message to queue - */ -uint32_t -gsm_sys_mbox_put(gsm_sys_mbox_t* b, void* m) { - uint32_t tick = osKernelSysTick(); /* Get start time */ - return osMessagePut(*b, (uint32_t)m, osWaitForever) == osOK ? (osKernelSysTick() - tick) : GSM_SYS_TIMEOUT; /* Put new message with forever timeout */ -} - -/** - * \brief Get a new entry from message queue with timeout - * \note This function is required with OS - * \param[in] b: Pointer to message queue structure - * \param[in] m: Pointer to pointer to result to save value from message queue to - * \param[in] timeout: Maximal timeout to wait for new message. When 0 is applied, wait for unlimited time - * \return Time in units of milliseconds needed to put a message to queue - */ -uint32_t -gsm_sys_mbox_get(gsm_sys_mbox_t* b, void** m, uint32_t timeout) { - osEvent evt; - uint32_t time = osKernelSysTick(); /* Get current time */ - - evt = osMessageGet(*b, !timeout ? osWaitForever : timeout); /* Get message event */ - if (evt.status == osEventMessage) { /* Did we get a message? */ - *m = evt.value.p; /* Set value */ - return osKernelSysTick() - time; /* Return time required for reading message */ - } - return GSM_SYS_TIMEOUT; -} - -/** - * \brief Put a new entry to message queue without timeout (now or fail) - * \note This function is required with OS - * \param[in] b: Pointer to message queue structure - * \param[in] m: Pointer to message to save to queue - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_mbox_putnow(gsm_sys_mbox_t* b, void* m) { - return osMessagePut(*b, (uint32_t)m, 0) == osOK; /* Put new message without timeout */ -} - -/** - * \brief Get an entry from message queue immediatelly - * \note This function is required with OS - * \param[in] b: Pointer to message queue structure - * \param[in] m: Pointer to pointer to result to save value from message queue to - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_mbox_getnow(gsm_sys_mbox_t* b, void** m) { - osEvent evt; - - evt = osMessageGet(*b, 0); /* Get message event */ - if (evt.status == osEventMessage) { /* Did we get a message? */ - *m = evt.value.p; /* Set value */ - return 1; - } - return 0; -} - -/** - * \brief Check if message queue is valid - * \note This function is required with OS - * \param[in] b: Pointer to message queue structure - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_mbox_isvalid(gsm_sys_mbox_t* b) { - return b != NULL && *b != NULL; /* Return status if message box is valid */ -} - -/** - * \brief Invalid message queue - * \note This function is required with OS - * \param[in] b: Pointer to message queue structure - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_mbox_invalid(gsm_sys_mbox_t* b) { - *b = GSM_SYS_MBOX_NULL; /* Invalidate message box */ - return 1; -} - -/** - * \brief Create a new thread - * \note This function is required with OS - * \param[out] t: Pointer to thread identifier if create was successful - * \param[in] name: Name of a new thread - * \param[in] thread_func: Thread function to use as thread body - * \param[in] arg: Thread function argument - * \param[in] stack_size: Size of thread stack in uints of bytes. If set to 0, reserve default stack size - * \param[in] prio: Thread priority - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_thread_create(gsm_sys_thread_t* t, const char* name, gsm_sys_thread_fn thread_func, void* const arg, size_t stack_size, gsm_sys_thread_prio_t prio) { - gsm_sys_thread_t id; - const osThreadDef_t thread_def = {(char *)name, (os_pthread)thread_func, (osPriority)prio, 0, stack_size ? stack_size : GSM_SYS_THREAD_SS }; /* Create thread description */ - id = osThreadCreate(&thread_def, arg); /* Create thread */ - if (t != NULL) { - *t = id; - } - return !!id; -} - -/** - * \brief Terminate thread (shut it down and remove) - * \note This function is required with OS - * \param[in] t: Pointer to thread handle to terminate. If set to NULL, terminate current thread (thread from where function is called) - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_thread_terminate(gsm_sys_thread_t* t) { - osThreadTerminate(t != NULL ? *t : NULL); /* Terminate thread */ - return 1; -} - -/** - * \brief Yield current thread - * \note This function is required with OS - * \return 1 on success, 0 otherwise - */ -uint8_t -gsm_sys_thread_yield(void) { - osThreadYield(); /* Yield current thread */ - return 1; -} diff --git a/gsm_at_lib/src/api/gsm_netconn.c b/lwgsm/src/api/lwgsm_netconn.c similarity index 50% rename from gsm_at_lib/src/api/gsm_netconn.c rename to lwgsm/src/api/lwgsm_netconn.c index b6ae8ca5..73e92dd5 100644 --- a/gsm_at_lib/src/api/gsm_netconn.c +++ b/lwgsm/src/api/lwgsm_netconn.c @@ -1,10 +1,10 @@ /** - * \file gsm_netconn.c + * \file lwgsm_netconn.c * \brief API functions for sequential calls */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,113 +26,118 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_netconn.h" -#include "gsm/gsm_private.h" -#include "gsm/gsm_conn.h" -#include "gsm/gsm_mem.h" +#include "lwgsm/lwgsm_netconn.h" +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_conn.h" +#include "lwgsm/lwgsm_mem.h" -#if GSM_CFG_NETCONN || __DOXYGEN__ +#if LWGSM_CFG_NETCONN || __DOXYGEN__ /* Check conditions */ -#if !GSM_CFG_CONN -#error "GSM_CFG_CONN must be enabled for NETCONN API!" -#endif /* !GSM_CFG_CONN */ +#if !LWGSM_CFG_CONN +#error "LWGSM_CFG_CONN must be enabled for NETCONN API!" +#endif /* !LWGSM_CFG_CONN */ + +#if LWGSM_CFG_NETCONN_RECEIVE_QUEUE_LEN < 2 +#error "LWGSM_CFG_NETCONN_RECEIVE_QUEUE_LEN must be greater or equal to 2" +#endif /* LWGSM_CFG_NETCONN_RECEIVE_QUEUE_LEN < 2 */ /** * \brief Sequential API structure */ -typedef struct gsm_netconn { - struct gsm_netconn* next; /*!< Linked list entry */ +typedef struct lwgsm_netconn { + struct lwgsm_netconn* next; /*!< Linked list entry */ - gsm_netconn_type_t type; /*!< Netconn type */ + lwgsm_netconn_type_t type; /*!< Netconn type */ size_t rcv_packets; /*!< Number of received packets so far on this connection */ - gsm_conn_p conn; /*!< Pointer to actual connection */ + lwgsm_conn_p conn; /*!< Pointer to actual connection */ - gsm_sys_mbox_t mbox_receive; /*!< Message queue for receive mbox */ + lwgsm_sys_mbox_t mbox_receive; /*!< Message queue for receive mbox */ - gsm_linbuff_t buff; /*!< Linear buffer structure */ + lwgsm_linbuff_t buff; /*!< Linear buffer structure */ uint16_t conn_timeout; /*!< Connection timeout in units of seconds when netconn is in server (listen) mode. Connection will be automatically closed if there is no data exchange in time. Set to `0` when timeout feature is disabled. */ -#if GSM_CFG_NETCONN_RECEIVE_TIMEOUT || __DOXYGEN__ +#if LWGSM_CFG_NETCONN_RECEIVE_TIMEOUT || __DOXYGEN__ uint32_t rcv_timeout; /*!< Receive timeout in unit of milliseconds */ #endif -} gsm_netconn_t; +} lwgsm_netconn_t; static uint8_t recv_closed = 0xFF; -static gsm_netconn_t* netconn_list; /*!< Linked list of netconn entries */ +static lwgsm_netconn_t* netconn_list; /*!< Linked list of netconn entries */ /** * \brief Flush all mboxes and clear possible used memories * \param[in] nc: Pointer to netconn to flush + * \param[in] protect: Set to 1 to protect against multi-thread access */ static void -flush_mboxes(gsm_netconn_t* nc, uint8_t protect) { - gsm_pbuf_p pbuf; +flush_mboxes(lwgsm_netconn_t* nc, uint8_t protect) { + lwgsm_pbuf_p pbuf; if (protect) { - gsm_core_lock(); + lwgsm_core_lock(); } - if (gsm_sys_mbox_isvalid(&nc->mbox_receive)) { - while (gsm_sys_mbox_getnow(&nc->mbox_receive, (void **)&pbuf)) { - if (pbuf != NULL && (uint8_t *)pbuf != (uint8_t *)&recv_closed) { - gsm_pbuf_free(pbuf); /* Free received data buffers */ + if (lwgsm_sys_mbox_isvalid(&nc->mbox_receive)) { + while (lwgsm_sys_mbox_getnow(&nc->mbox_receive, (void**)&pbuf)) { + if (pbuf != NULL && (uint8_t*)pbuf != (uint8_t*)&recv_closed) { + lwgsm_pbuf_free(pbuf); /* Free received data buffers */ } } - gsm_sys_mbox_delete(&nc->mbox_receive); /* Delete message queue */ - gsm_sys_mbox_invalid(&nc->mbox_receive);/* Invalid handle */ + lwgsm_sys_mbox_delete(&nc->mbox_receive); /* Delete message queue */ + lwgsm_sys_mbox_invalid(&nc->mbox_receive); /* Invalid handle */ } if (protect) { - gsm_core_unlock(); + lwgsm_core_unlock(); } } /** * \brief Callback function for every server connection * \param[in] evt: Pointer to callback structure - * \return Member of \ref gsmr_t enumeration + * \return Member of \ref lwgsmr_t enumeration */ -static gsmr_t -netconn_evt(gsm_evt_t* evt) { - gsm_conn_p conn; - gsm_netconn_t* nc = NULL; +static lwgsmr_t +netconn_evt(lwgsm_evt_t* evt) { + lwgsm_conn_p conn; + lwgsm_netconn_t* nc = NULL; uint8_t close = 0; - conn = gsm_conn_get_from_evt(evt); /* Get connection from event */ - switch (gsm_evt_get_type(evt)) { + conn = lwgsm_conn_get_from_evt(evt); /* Get connection from event */ + switch (lwgsm_evt_get_type(evt)) { /* * A new connection has been active * and should be handled by netconn API */ - case GSM_EVT_CONN_ACTIVE: { /* A new connection active is active */ - if (gsm_conn_is_client(conn)) { /* Was connection started by us? */ - nc = gsm_conn_get_arg(conn); /* Argument should be already set */ + case LWGSM_EVT_CONN_ACTIVE: { /* A new connection active is active */ + if (lwgsm_conn_is_client(conn)) { /* Was connection started by us? */ + nc = lwgsm_conn_get_arg(conn); /* Argument should be already set */ if (nc != NULL) { nc->conn = conn; /* Save actual connection */ } else { close = 1; /* Close this connection, invalid netconn */ } } else { - GSM_DEBUGF(GSM_CFG_DBG_NETCONN | GSM_DBG_TYPE_TRACE | GSM_DBG_LVL_WARNING, - "[NETCONN] Closing connection, it is not in client mode!\r\n"); + LWGSM_DEBUGF(LWGSM_CFG_DBG_NETCONN | LWGSM_DBG_TYPE_TRACE | LWGSM_DBG_LVL_WARNING, + "[NETCONN] Closing connection, it is not in client mode!\r\n"); close = 1; /* Close the connection at this point */ } /* Decide if some events want to close the connection */ if (close) { if (nc != NULL) { - gsm_conn_set_arg(conn, NULL); /* Reset argument */ - gsm_netconn_delete(nc); /* Free memory for API */ + lwgsm_conn_set_arg(conn, NULL); /* Reset argument */ + lwgsm_netconn_delete(nc); /* Free memory for API */ } - gsm_conn_close(conn, 0); /* Close the connection */ + lwgsm_conn_close(conn, 0); /* Close the connection */ close = 0; } break; @@ -142,60 +147,61 @@ netconn_evt(gsm_evt_t* evt) { * We have a new data received which * should have netconn structure as argument */ - case GSM_EVT_CONN_RECV: { - gsm_pbuf_p pbuf; + case LWGSM_EVT_CONN_RECV: { + lwgsm_pbuf_p pbuf; - nc = gsm_conn_get_arg(conn); /* Get API from connection */ - pbuf = gsm_evt_conn_recv_get_buff(evt);/* Get received buff */ + nc = lwgsm_conn_get_arg(conn); /* Get API from connection */ + pbuf = lwgsm_evt_conn_recv_get_buff(evt); /* Get received buff */ - gsm_conn_recved(conn, pbuf); /* Notify stack about received data */ + lwgsm_conn_recved(conn, pbuf); /* Notify stack about received data */ - gsm_pbuf_ref(pbuf); /* Increase reference counter */ - if (nc == NULL || !gsm_sys_mbox_isvalid(&nc->mbox_receive) - || !gsm_sys_mbox_putnow(&nc->mbox_receive, pbuf)) { - GSM_DEBUGF(GSM_CFG_DBG_NETCONN, - "[NETCONN] Ignoring more data for receive!\r\n"); - gsm_pbuf_free(pbuf); /* Free pbuf */ - return gsmOKIGNOREMORE; /* Return OK to free the memory and ignore further data */ + lwgsm_pbuf_ref(pbuf); /* Increase reference counter */ + if (nc == NULL || !lwgsm_sys_mbox_isvalid(&nc->mbox_receive) + || !lwgsm_sys_mbox_putnow(&nc->mbox_receive, pbuf)) { + LWGSM_DEBUGF(LWGSM_CFG_DBG_NETCONN, + "[NETCONN] Ignoring more data for receive!\r\n"); + lwgsm_pbuf_free(pbuf); /* Free pbuf */ + return lwgsmOKIGNOREMORE; /* Return OK to free the memory and ignore further data */ } - nc->rcv_packets++; /* Increase number of received packets */ - GSM_DEBUGF(GSM_CFG_DBG_NETCONN | GSM_DBG_TYPE_TRACE, - "[NETCONN] Received pbuf contains %d bytes. Handle written to receive mbox\r\n", - (int)gsm_pbuf_length(pbuf, 0)); + ++nc->rcv_packets; /* Increase number of received packets */ + LWGSM_DEBUGF(LWGSM_CFG_DBG_NETCONN | LWGSM_DBG_TYPE_TRACE, + "[NETCONN] Received pbuf contains %d bytes. Handle written to receive mbox\r\n", + (int)lwgsm_pbuf_length(pbuf, 0)); break; } /* Connection was just closed */ - case GSM_EVT_CONN_CLOSE: { - nc = gsm_conn_get_arg(conn); /* Get API from connection */ + case LWGSM_EVT_CONN_CLOSE: { + nc = lwgsm_conn_get_arg(conn); /* Get API from connection */ /* * In case we have a netconn available, * simply write pointer to received variable to indicate closed state */ - if (nc != NULL && gsm_sys_mbox_isvalid(&nc->mbox_receive)) { - gsm_sys_mbox_putnow(&nc->mbox_receive, (void *)&recv_closed); + if (nc != NULL && lwgsm_sys_mbox_isvalid(&nc->mbox_receive)) { + lwgsm_sys_mbox_putnow(&nc->mbox_receive, (void*)&recv_closed); } break; } default: - return gsmERR; + return lwgsmERR; } - return gsmOK; + return lwgsmOK; } /** * \brief Global event callback function * \param[in] evt: Callback information and data - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise */ -static gsmr_t -gsm_evt(gsm_evt_t* evt) { - switch (gsm_evt_get_type(evt)) { - default: break; +static lwgsmr_t +lwgsm_evt(lwgsm_evt_t* evt) { + switch (lwgsm_evt_get_type(evt)) { + default: + break; } - return gsmOK; + return lwgsmOK; } /** @@ -203,44 +209,44 @@ gsm_evt(gsm_evt_t* evt) { * \param[in] type: Netconn connection type * \return New netconn connection on success, `NULL` otherwise */ -gsm_netconn_p -gsm_netconn_new(gsm_netconn_type_t type) { - gsm_netconn_t* a; +lwgsm_netconn_p +lwgsm_netconn_new(lwgsm_netconn_type_t type) { + lwgsm_netconn_t* a; static uint8_t first = 1; /* Register only once! */ - gsm_core_lock(); + lwgsm_core_lock(); if (first) { first = 0; - gsm_evt_register(gsm_evt); /* Register global event function */ + lwgsm_evt_register(lwgsm_evt); /* Register global event function */ } - gsm_core_unlock(); - a = gsm_mem_calloc(1, sizeof(*a)); /* Allocate memory for core object */ + lwgsm_core_unlock(); + a = lwgsm_mem_calloc(1, sizeof(*a)); /* Allocate memory for core object */ if (a != NULL) { a->type = type; /* Save netconn type */ a->conn_timeout = 0; /* Default connection timeout */ - if (!gsm_sys_mbox_create(&a->mbox_receive, GSM_CFG_NETCONN_RECEIVE_QUEUE_LEN)) { /* Allocate memory for receiving message box */ - GSM_DEBUGF(GSM_CFG_DBG_NETCONN | GSM_DBG_TYPE_TRACE | GSM_DBG_LVL_DANGER, - "[NETCONN] Cannot create receive MBOX\r\n"); + if (!lwgsm_sys_mbox_create(&a->mbox_receive, LWGSM_CFG_NETCONN_RECEIVE_QUEUE_LEN)) {/* Allocate memory for receiving message box */ + LWGSM_DEBUGF(LWGSM_CFG_DBG_NETCONN | LWGSM_DBG_TYPE_TRACE | LWGSM_DBG_LVL_DANGER, + "[NETCONN] Cannot create receive MBOX\r\n"); goto free_ret; } - gsm_core_lock(); + lwgsm_core_lock(); if (netconn_list == NULL) { /* Add new netconn to the existing list */ netconn_list = a; } else { a->next = netconn_list; /* Add it to beginning of the list */ netconn_list = a; } - gsm_core_unlock(); + lwgsm_core_unlock(); } return a; free_ret: - if (gsm_sys_mbox_isvalid(&a->mbox_receive)) { - gsm_sys_mbox_delete(&a->mbox_receive); - gsm_sys_mbox_invalid(&a->mbox_receive); + if (lwgsm_sys_mbox_isvalid(&a->mbox_receive)) { + lwgsm_sys_mbox_delete(&a->mbox_receive); + lwgsm_sys_mbox_invalid(&a->mbox_receive); } if (a != NULL) { - gsm_mem_free_s((void **)&a); + lwgsm_mem_free_s((void**)&a); } return NULL; } @@ -248,33 +254,33 @@ gsm_netconn_new(gsm_netconn_type_t type) { /** * \brief Delete netconn connection * \param[in] nc: Netconn handle - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_netconn_delete(gsm_netconn_p nc) { - GSM_ASSERT("netconn != NULL", nc != NULL); +lwgsmr_t +lwgsm_netconn_delete(lwgsm_netconn_p nc) { + LWGSM_ASSERT("netconn != NULL", nc != NULL); - gsm_core_lock(); + lwgsm_core_lock(); flush_mboxes(nc, 0); /* Clear mboxes */ /* Remove netconn from linkedlist */ if (netconn_list == nc) { netconn_list = netconn_list->next; /* Remove first from linked list */ } else if (netconn_list != NULL) { - gsm_netconn_p tmp, prev; + lwgsm_netconn_p tmp, prev; /* Find element on the list */ for (prev = netconn_list, tmp = netconn_list->next; - tmp != NULL; prev = tmp, tmp = tmp->next) { + tmp != NULL; prev = tmp, tmp = tmp->next) { if (nc == tmp) { prev->next = tmp->next; /* Remove tmp from linked list */ break; } } } - gsm_core_unlock(); + lwgsm_core_unlock(); - gsm_mem_free_s((void **)&nc); - return gsmOK; + lwgsm_mem_free_s((void**)&nc); + return lwgsmOK; } /** @@ -282,15 +288,15 @@ gsm_netconn_delete(gsm_netconn_p nc) { * \param[in] nc: Netconn handle * \param[in] host: Pointer to host, such as domain name or IP address in string format * \param[in] port: Target port to use - * \return \ref gsmOK if successfully connected, member of \ref gsmr_t otherwise + * \return \ref lwgsmOK if successfully connected, member of \ref lwgsmr_t otherwise */ -gsmr_t -gsm_netconn_connect(gsm_netconn_p nc, const char* host, gsm_port_t port) { - gsmr_t res; +lwgsmr_t +lwgsm_netconn_connect(lwgsm_netconn_p nc, const char* host, lwgsm_port_t port) { + lwgsmr_t res; - GSM_ASSERT("nc != NULL", nc != NULL); - GSM_ASSERT("host != NULL", host != NULL); - GSM_ASSERT("port > 0", port > 0); + LWGSM_ASSERT("nc != NULL", nc != NULL); + LWGSM_ASSERT("host != NULL", host != NULL); + LWGSM_ASSERT("port > 0", port > 0); /* * Start a new connection as client and: @@ -299,7 +305,7 @@ gsm_netconn_connect(gsm_netconn_p nc, const char* host, gsm_port_t port) { * - Set netconn callback function for connection management * - Start connection in blocking mode */ - res = gsm_conn_start(NULL, (gsm_conn_type_t)nc->type, host, port, nc, netconn_evt, 1); + res = lwgsm_conn_start(NULL, (lwgsm_conn_type_t)nc->type, host, port, nc, netconn_evt, 1); return res; } @@ -309,33 +315,33 @@ gsm_netconn_connect(gsm_netconn_p nc, const char* host, gsm_port_t port) { * \param[in] nc: Netconn handle used to write data to * \param[in] data: Pointer to data to write * \param[in] btw: Number of bytes to write - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_netconn_write(gsm_netconn_p nc, const void* data, size_t btw) { +lwgsmr_t +lwgsm_netconn_write(lwgsm_netconn_p nc, const void* data, size_t btw) { size_t len, sent; const uint8_t* d = data; - gsmr_t res; + lwgsmr_t res; - GSM_ASSERT("nc != NULL", nc != NULL); - GSM_ASSERT("nc->type must be TCP or SSL", nc->type == GSM_NETCONN_TYPE_TCP || nc->type == GSM_NETCONN_TYPE_SSL); - GSM_ASSERT("nc->conn must be active", gsm_conn_is_active(nc->conn)); + LWGSM_ASSERT("nc != NULL", nc != NULL); + LWGSM_ASSERT("nc->type must be TCP or SSL", nc->type == LWGSM_NETCONN_TYPE_TCP || nc->type == LWGSM_NETCONN_TYPE_SSL); + LWGSM_ASSERT("nc->conn must be active", lwgsm_conn_is_active(nc->conn)); /* * Several steps are done in write process * * 1. Check if buffer is set and check if there is something to write to it. * 1. In case buffer will be full after copy, send it and free memory. - * 2. Check how many bytes we can write directly without needed to copy + * 2. Check how many bytes we can write directly without need to copy * 3. Try to allocate a new buffer and copy remaining input data to it * 4. In case buffer allocation fails, send data directly (may affect on speed and effectivenes) */ /* Step 1 */ if (nc->buff.buff != NULL) { /* Is there a write buffer ready to accept more data? */ - len = GSM_MIN(nc->buff.len - nc->buff.ptr, btw); /* Get number of bytes we can write to buffer */ + len = LWGSM_MIN(nc->buff.len - nc->buff.ptr, btw); /* Get number of bytes we can write to buffer */ if (len > 0) { - GSM_MEMCPY(&nc->buff.buff[nc->buff.ptr], data, len);/* Copy memory to temporary write buffer */ + LWGSM_MEMCPY(&nc->buff.buff[nc->buff.ptr], data, len); /* Copy memory to temporary write buffer */ d += len; nc->buff.ptr += len; btw -= len; @@ -343,23 +349,23 @@ gsm_netconn_write(gsm_netconn_p nc, const void* data, size_t btw) { /* Step 1.1 */ if (nc->buff.ptr == nc->buff.len) { - res = gsm_conn_send(nc->conn, nc->buff.buff, nc->buff.len, &sent, 1); + res = lwgsm_conn_send(nc->conn, nc->buff.buff, nc->buff.len, &sent, 1); - gsm_mem_free_s((void **)&nc->buff.buff); - if (res != gsmOK) { + lwgsm_mem_free_s((void**)&nc->buff.buff); + if (res != lwgsmOK) { return res; } } else { - return gsmOK; /* Buffer is not yet full yet */ + return lwgsmOK; /* Buffer is not yet full yet */ } } /* Step 2 */ - if (btw >= GSM_CFG_CONN_MAX_DATA_LEN) { + if (btw >= LWGSM_CFG_CONN_MAX_DATA_LEN) { size_t rem; - rem = btw % GSM_CFG_CONN_MAX_DATA_LEN; /* Get remaining bytes for max data length */ - res = gsm_conn_send(nc->conn, d, btw - rem, &sent, 1); /* Write data directly */ - if (res != gsmOK) { + rem = btw % LWGSM_CFG_CONN_MAX_DATA_LEN;/* Get remaining bytes for max data length */ + res = lwgsm_conn_send(nc->conn, d, btw - rem, &sent, 1);/* Write data directly */ + if (res != lwgsmOK) { return res; } d += sent; /* Advance in data pointer */ @@ -367,37 +373,37 @@ gsm_netconn_write(gsm_netconn_p nc, const void* data, size_t btw) { } if (btw == 0) { /* Sent everything? */ - return gsmOK; + return lwgsmOK; } /* Step 3 */ if (nc->buff.buff == NULL) { /* Check if we should allocate a new buffer */ - nc->buff.buff = gsm_mem_malloc(sizeof(*nc->buff.buff) * GSM_CFG_CONN_MAX_DATA_LEN); - nc->buff.len = GSM_CFG_CONN_MAX_DATA_LEN; /* Save buffer length */ + nc->buff.buff = lwgsm_mem_malloc(sizeof(*nc->buff.buff) * LWGSM_CFG_CONN_MAX_DATA_LEN); + nc->buff.len = LWGSM_CFG_CONN_MAX_DATA_LEN; /* Save buffer length */ nc->buff.ptr = 0; /* Save buffer pointer */ } /* Step 4 */ if (nc->buff.buff != NULL) { /* Memory available? */ - GSM_MEMCPY(&nc->buff.buff[nc->buff.ptr], d, btw); /* Copy data to buffer */ + LWGSM_MEMCPY(&nc->buff.buff[nc->buff.ptr], d, btw); /* Copy data to buffer */ nc->buff.ptr += btw; } else { /* Still no memory available? */ - return gsm_conn_send(nc->conn, data, btw, NULL, 1); /* Simply send directly blocking */ + return lwgsm_conn_send(nc->conn, data, btw, NULL, 1); /* Simply send directly blocking */ } - return gsmOK; + return lwgsmOK; } /** * \brief Flush buffered data on netconn \e TCP/SSL connection * \note This function may only be used on \e TCP/SSL connection * \param[in] nc: Netconn handle to flush data - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_netconn_flush(gsm_netconn_p nc) { - GSM_ASSERT("nc != NULL", nc != NULL); - GSM_ASSERT("nc->type must be TCP or SSL", nc->type == GSM_NETCONN_TYPE_TCP || nc->type == GSM_NETCONN_TYPE_SSL); - GSM_ASSERT("nc->conn must be active", gsm_conn_is_active(nc->conn)); +lwgsmr_t +lwgsm_netconn_flush(lwgsm_netconn_p nc) { + LWGSM_ASSERT("nc != NULL", nc != NULL); + LWGSM_ASSERT("nc->type must be TCP or SSL", nc->type == LWGSM_NETCONN_TYPE_TCP || nc->type == LWGSM_NETCONN_TYPE_SSL); + LWGSM_ASSERT("nc->conn must be active", lwgsm_conn_is_active(nc->conn)); /* * In case we have data in write buffer, @@ -405,11 +411,11 @@ gsm_netconn_flush(gsm_netconn_p nc) { */ if (nc->buff.buff != NULL) { /* Check remaining data */ if (nc->buff.ptr > 0) { /* Do we have data in current buffer? */ - gsm_conn_send(nc->conn, nc->buff.buff, nc->buff.ptr, NULL, 1); /* Send data */ + lwgsm_conn_send(nc->conn, nc->buff.buff, nc->buff.ptr, NULL, 1);/* Send data */ } - gsm_mem_free_s((void **)&nc->buff.buff); + lwgsm_mem_free_s((void**)&nc->buff.buff); } - return gsmOK; + return lwgsmOK; } /** @@ -417,15 +423,15 @@ gsm_netconn_flush(gsm_netconn_p nc) { * \param[in] nc: Netconn handle used to send * \param[in] data: Pointer to data to write * \param[in] btw: Number of bytes to write - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_netconn_send(gsm_netconn_p nc, const void* data, size_t btw) { - GSM_ASSERT("nc != NULL", nc != NULL); - GSM_ASSERT("nc->type must be UDP", nc->type == GSM_NETCONN_TYPE_UDP); - GSM_ASSERT("nc->conn must be active", gsm_conn_is_active(nc->conn)); +lwgsmr_t +lwgsm_netconn_send(lwgsm_netconn_p nc, const void* data, size_t btw) { + LWGSM_ASSERT("nc != NULL", nc != NULL); + LWGSM_ASSERT("nc->type must be UDP", nc->type == LWGSM_NETCONN_TYPE_UDP); + LWGSM_ASSERT("nc->conn must be active", lwgsm_conn_is_active(nc->conn)); - return gsm_conn_send(nc->conn, data, btw, NULL, 1); + return lwgsm_conn_send(nc->conn, data, btw, NULL, 1); } /** @@ -436,15 +442,15 @@ gsm_netconn_send(gsm_netconn_p nc, const void* data, size_t btw) { * \param[in] port: Port number used to send data * \param[in] data: Pointer to data to write * \param[in] btw: Number of bytes to write - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_netconn_sendto(gsm_netconn_p nc, const gsm_ip_t* ip, gsm_port_t port, const void* data, size_t btw) { - GSM_ASSERT("nc != NULL", nc != NULL); - GSM_ASSERT("nc->type must be UDP", nc->type == GSM_NETCONN_TYPE_UDP); - GSM_ASSERT("nc->conn must be active", gsm_conn_is_active(nc->conn)); +lwgsmr_t +lwgsm_netconn_sendto(lwgsm_netconn_p nc, const lwgsm_ip_t* ip, lwgsm_port_t port, const void* data, size_t btw) { + LWGSM_ASSERT("nc != NULL", nc != NULL); + LWGSM_ASSERT("nc->type must be UDP", nc->type == LWGSM_NETCONN_TYPE_UDP); + LWGSM_ASSERT("nc->conn must be active", lwgsm_conn_is_active(nc->conn)); - return gsm_conn_sendto(nc->conn, ip, port, data, btw, NULL, 1); + return lwgsm_conn_sendto(nc->conn, ip, port, data, btw, NULL, 1); } /** @@ -452,88 +458,88 @@ gsm_netconn_sendto(gsm_netconn_p nc, const gsm_ip_t* ip, gsm_port_t port, const * \param[in] nc: Netconn handle used to receive from * \param[in] pbuf: Pointer to pointer to save new receive buffer to. * When function returns, user must check for valid pbuf value `pbuf != NULL` - * \return \ref gsmOK when new data ready, - * \return \ref gsmCLOSED when connection closed by remote side, - * \return \ref gsmTIMEOUT when receive timeout occurs - * \return Any other member of \ref gsmr_t otherwise + * \return \ref lwgsmOK when new data ready, + * \return \ref lwgsmCLOSED when connection closed by remote side, + * \return \ref lwgsmTIMEOUT when receive timeout occurs + * \return Any other member of \ref lwgsmr_t otherwise */ -gsmr_t -gsm_netconn_receive(gsm_netconn_p nc, gsm_pbuf_p* pbuf) { - GSM_ASSERT("nc != NULL", nc != NULL); - GSM_ASSERT("pbuf != NULL", pbuf != NULL); +lwgsmr_t +lwgsm_netconn_receive(lwgsm_netconn_p nc, lwgsm_pbuf_p* pbuf) { + LWGSM_ASSERT("nc != NULL", nc != NULL); + LWGSM_ASSERT("pbuf != NULL", pbuf != NULL); *pbuf = NULL; -#if GSM_CFG_NETCONN_RECEIVE_TIMEOUT +#if LWGSM_CFG_NETCONN_RECEIVE_TIMEOUT /* * Wait for new received data for up to specific timeout * or throw error for timeout notification */ - if (gsm_sys_mbox_get(&nc->mbox_receive, (void **)pbuf, nc->rcv_timeout) == GSM_SYS_TIMEOUT) { - return gsmTIMEOUT; + if (lwgsm_sys_mbox_get(&nc->mbox_receive, (void**)pbuf, nc->rcv_timeout) == LWGSM_SYS_TIMEOUT) { + return lwgsmTIMEOUT; } -#else /* GSM_CFG_NETCONN_RECEIVE_TIMEOUT */ +#else /* LWGSM_CFG_NETCONN_RECEIVE_TIMEOUT */ /* Forever wait for new receive packet */ - gsm_sys_mbox_get(&nc->mbox_receive, (void **)pbuf, 0); -#endif /* !GSM_CFG_NETCONN_RECEIVE_TIMEOUT */ + lwgsm_sys_mbox_get(&nc->mbox_receive, (void**)pbuf, 0); +#endif /* !LWGSM_CFG_NETCONN_RECEIVE_TIMEOUT */ /* Check if connection closed */ - if ((uint8_t *)(*pbuf) == (uint8_t *)&recv_closed) { + if ((uint8_t*)(*pbuf) == (uint8_t*)&recv_closed) { *pbuf = NULL; /* Reset pbuf */ - return gsmCLOSED; + return lwgsmCLOSED; } - return gsmOK; /* We have data available */ + return lwgsmOK; /* We have data available */ } /** * \brief Close a netconn connection * \param[in] nc: Netconn handle to close - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_netconn_close(gsm_netconn_p nc) { - gsm_conn_p conn; +lwgsmr_t +lwgsm_netconn_close(lwgsm_netconn_p nc) { + lwgsm_conn_p conn; - GSM_ASSERT("nc != NULL", nc != NULL); - GSM_ASSERT("nc->conn != NULL", nc->conn != NULL); - GSM_ASSERT("nc->conn must be active", gsm_conn_is_active(nc->conn)); + LWGSM_ASSERT("nc != NULL", nc != NULL); + LWGSM_ASSERT("nc->conn != NULL", nc->conn != NULL); + LWGSM_ASSERT("nc->conn must be active", lwgsm_conn_is_active(nc->conn)); - gsm_netconn_flush(nc); /* Flush data and ignore result */ + lwgsm_netconn_flush(nc); /* Flush data and ignore result */ conn = nc->conn; nc->conn = NULL; - gsm_conn_set_arg(conn, NULL); /* Reset argument */ - gsm_conn_close(conn, 1); /* Close the connection */ + lwgsm_conn_set_arg(conn, NULL); /* Reset argument */ + lwgsm_conn_close(conn, 1); /* Close the connection */ flush_mboxes(nc, 1); /* Flush message queues */ - return gsmOK; + return lwgsmOK; } /** * \brief Get connection number used for netconn * \param[in] nc: Netconn handle - * \return `-1` on failure, connection number between `0` and \ref GSM_CFG_MAX_CONNS otherwise + * \return `-1` on failure, connection number between `0` and \ref LWGSM_CFG_MAX_CONNS otherwise */ int8_t -gsm_netconn_getconnnum(gsm_netconn_p nc) { +lwgsm_netconn_getconnnum(lwgsm_netconn_p nc) { if (nc != NULL && nc->conn != NULL) { - return gsm_conn_getnum(nc->conn); + return lwgsm_conn_getnum(nc->conn); } return -1; } -#if GSM_CFG_NETCONN_RECEIVE_TIMEOUT || __DOXYGEN__ +#if LWGSM_CFG_NETCONN_RECEIVE_TIMEOUT || __DOXYGEN__ /** * \brief Set timeout value for receiving data. * - * When enabled, \ref gsm_netconn_receive will only block for up to + * When enabled, \ref lwgsm_netconn_receive will only block for up to * \e timeout value and will return if no new data within this time * * \param[in] nc: Netconn handle * \param[in] timeout: Timeout in units of milliseconds. - * Set to `0` to disable timeout for \ref gsm_netconn_receive function + * Set to `0` to disable timeout for \ref lwgsm_netconn_receive function */ void -gsm_netconn_set_receive_timeout(gsm_netconn_p nc, uint32_t timeout) { +lwgsm_netconn_set_receive_timeout(lwgsm_netconn_p nc, uint32_t timeout) { nc->rcv_timeout = timeout; } @@ -544,10 +550,10 @@ gsm_netconn_set_receive_timeout(gsm_netconn_p nc, uint32_t timeout) { * If value is `0`, timeout is disabled (wait forever) */ uint32_t -gsm_netconn_get_receive_timeout(gsm_netconn_p nc) { +lwgsm_netconn_get_receive_timeout(lwgsm_netconn_p nc) { return nc->rcv_timeout; /* Return receive timeout */ } -#endif /* GSM_CFG_NETCONN_RECEIVE_TIMEOUT || __DOXYGEN__ */ +#endif /* LWGSM_CFG_NETCONN_RECEIVE_TIMEOUT || __DOXYGEN__ */ -#endif /* GSM_CFG_NETCONN || __DOXYGEN__ */ +#endif /* LWGSM_CFG_NETCONN || __DOXYGEN__ */ diff --git a/gsm_at_lib/src/api/gsm_network_api.c b/lwgsm/src/api/lwgsm_network_api.c similarity index 60% rename from gsm_at_lib/src/api/gsm_network_api.c rename to lwgsm/src/api/lwgsm_network_api.c index aa5cd1af..dc7d9cf7 100644 --- a/gsm_at_lib/src/api/gsm_network_api.c +++ b/lwgsm/src/api/lwgsm_network_api.c @@ -1,10 +1,10 @@ /** - * \file gsm_network_api.c + * \file lwgsm_network_api.c * \brief API functions for multi-thread network functions */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,16 +26,16 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_network_api.h" -#include "gsm/gsm_private.h" -#include "gsm/gsm_network.h" +#include "lwgsm/lwgsm_network_api.h" +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_network.h" -#if GSM_CFG_NETWORK || __DOXYGEN__ +#if LWGSM_CFG_NETWORK || __DOXYGEN__ /* Network credentials used during connect operation */ static const char* network_apn; @@ -48,40 +48,47 @@ static uint32_t network_counter; * \param[in] apn: APN domain. Set to `NULL` if not used * \param[in] user: APN username. Set to `NULL` if not used * \param[in] pass: APN password. Set to `NULL` if not used - * \return \ref espOK on success, member of \ref espr_t otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise */ -gsmr_t -gsm_network_set_credentials(const char* apn, const char* user, const char* pass) { - network_apn = apn; - network_user = user; - network_pass = pass; +lwgsmr_t +lwgsm_network_set_credentials(const char* apn, const char* user, const char* pass) { + network_apn = apn; + network_user = user; + network_pass = pass; - return gsmOK; + return lwgsmOK; } /** * \brief Request manager to attach to network * \note This function is blocking and cannot be called from event functions - * \return \gsmOK on success (when attached), member of \ref gsmr_t otherwise + * \return \ref lwgsmOK on success (when attached), member of \ref lwgsmr_t otherwise */ -gsmr_t -gsm_network_request_attach(void) { - gsmr_t res = gsmOK; +lwgsmr_t +lwgsm_network_request_attach(void) { + lwgsmr_t res = lwgsmOK; uint8_t do_conn = 0; /* Check if we need to connect */ - gsm_core_lock(); + lwgsm_core_lock(); if (network_counter == 0) { - if (!gsm_network_is_attached()) { + if (!lwgsm_network_is_attached()) { do_conn = 1; } } - network_counter++; - gsm_core_unlock(); + if (!do_conn) { + ++network_counter; + } + lwgsm_core_unlock(); /* Connect to network */ if (do_conn) { - res = gsm_network_attach(network_apn, network_user, network_pass, NULL, NULL, 1); + res = lwgsm_network_attach(network_apn, network_user, network_pass, NULL, NULL, 1); + if (res == lwgsmOK) { + lwgsm_core_lock(); + ++network_counter; + lwgsm_core_unlock(); + } } return res; } @@ -93,28 +100,34 @@ gsm_network_request_attach(void) { * otherwise it will disable network access * * \note This function is blocking and cannot be called from event functions - * \return \gsmOK on success (when attached), member of \ref gsmr_t otherwise + * \return \ref lwgsmOK on success (when attached), member of \ref lwgsmr_t otherwise */ -gsmr_t -gsm_network_request_detach(void) { - gsmr_t res = gsmOK; +lwgsmr_t +lwgsm_network_request_detach(void) { + lwgsmr_t res = lwgsmOK; uint8_t do_disconn = 0; /* Check if we need to disconnect */ - gsm_core_lock(); + lwgsm_core_lock(); if (network_counter > 0) { - network_counter--; - if (network_counter == 0) { + if (network_counter == 1) { do_disconn = 1; + } else { + --network_counter; } } - gsm_core_unlock(); + lwgsm_core_unlock(); /* Connect to network */ if (do_disconn) { - res = gsm_network_detach(NULL, NULL, 1); + res = lwgsm_network_detach(NULL, NULL, 1); + if (res == lwgsmOK) { + lwgsm_core_lock(); + --network_counter; + lwgsm_core_unlock(); + } } return res; } -#endif /* GSM_CFG_NETWORK || __DOXYGEN__ */ +#endif /* LWGSM_CFG_NETWORK || __DOXYGEN__ */ diff --git a/gsm_at_lib/src/apps/mqtt/gsm_mqtt_client.c b/lwgsm/src/apps/mqtt/lwgsm_mqtt_client.c similarity index 66% rename from gsm_at_lib/src/apps/mqtt/gsm_mqtt_client.c rename to lwgsm/src/apps/mqtt/lwgsm_mqtt_client.c index cd71b66c..2997fb86 100644 --- a/gsm_at_lib/src/apps/mqtt/gsm_mqtt_client.c +++ b/lwgsm/src/apps/mqtt/lwgsm_mqtt_client.c @@ -1,10 +1,10 @@ /** - * \file gsm_mqtt_client.c + * \file lwgsm_mqtt_client.c * \brief MQTT client */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,29 +26,29 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/apps/gsm_mqtt_client.h" -#include "gsm/gsm_mem.h" -#include "gsm/gsm_pbuf.h" +#include "lwgsm/apps/lwgsm_mqtt_client.h" +#include "lwgsm/lwgsm_mem.h" +#include "lwgsm/lwgsm_pbuf.h" /** * \brief MQTT client connection */ -typedef struct gsm_mqtt_client { - gsm_conn_p conn; /*!< Active used connection for MQTT */ - const gsm_mqtt_client_info_t* info; /*!< Connection info */ - gsm_mqtt_state_t conn_state; /*!< MQTT connection state */ +typedef struct lwgsm_mqtt_client { + lwgsm_conn_p conn; /*!< Active used connection for MQTT */ + const lwgsm_mqtt_client_info_t* info; /*!< Connection info */ + lwgsm_mqtt_state_t conn_state; /*!< MQTT connection state */ uint32_t poll_time; /*!< Poll time, increased every 500ms */ - gsm_mqtt_evt_t evt; /*!< MQTT event callback */ - gsm_mqtt_evt_fn evt_fn; /*!< Event callback function */ + lwgsm_mqtt_evt_t evt; /*!< MQTT event callback */ + lwgsm_mqtt_evt_fn evt_fn; /*!< Event callback function */ - gsm_buff_t tx_buff; /*!< Buffer for raw output data to transmit */ + lwgsm_buff_t tx_buff; /*!< Buffer for raw output data to transmit */ uint8_t is_sending; /*!< Flag if we are sending data currently */ uint32_t sent_total; /*!< Total number of bytes sent so far on connection */ @@ -56,7 +56,7 @@ typedef struct gsm_mqtt_client { uint16_t last_packet_id; /*!< Packet ID used on last packet */ - gsm_mqtt_request_t requests[GSM_CFG_MQTT_MAX_REQUESTS]; /*!< List of requests */ + lwgsm_mqtt_request_t requests[LWGSM_CFG_MQTT_MAX_REQUESTS]; /*!< List of requests */ uint8_t* rx_buff; /*!< Raw RX buffer */ size_t rx_buff_len; /*!< Length of raw RX buffer */ @@ -68,15 +68,15 @@ typedef struct gsm_mqtt_client { uint32_t msg_curr_pos; /*!< Current buffer write pointer */ void* arg; /*!< User argument */ -} gsm_mqtt_client_t; +} lwgsm_mqtt_client_t; /* Tracing debug message */ -#define GSM_CFG_DBG_MQTT_TRACE (GSM_CFG_DBG_MQTT | GSM_DBG_TYPE_TRACE) -#define GSM_CFG_DBG_MQTT_STATE (GSM_CFG_DBG_MQTT | GSM_DBG_TYPE_STATE) -#define GSM_CFG_DBG_MQTT_TRACE_WARNING (GSM_CFG_DBG_MQTT | GSM_DBG_TYPE_TRACE | GSM_DBG_LVL_WARNING) +#define LWGSM_CFG_DBG_MQTT_TRACE (LWGSM_CFG_DBG_MQTT | LWGSM_DBG_TYPE_TRACE) +#define LWGSM_CFG_DBG_MQTT_STATE (LWGSM_CFG_DBG_MQTT | LWGSM_DBG_TYPE_STATE) +#define LWGSM_CFG_DBG_MQTT_TRACE_WARNING (LWGSM_CFG_DBG_MQTT | LWGSM_DBG_TYPE_TRACE | LWGSM_DBG_LVL_WARNING) -static gsmr_t mqtt_conn_cb(gsm_evt_t* evt); -static void send_data(gsm_mqtt_client_p client); +static lwgsmr_t mqtt_conn_cb(lwgsm_evt_t* evt); +static void send_data(lwgsm_mqtt_client_p client); /** * \brief List of MQTT message types @@ -112,7 +112,7 @@ typedef enum { /* Get packet type from incoming byte */ #define MQTT_RCV_GET_PACKET_TYPE(d) ((mqtt_msg_type_t)(((d) >> 0x04) & 0x0F)) -#define MQTT_RCV_GET_PACKET_QOS(d) ((gsm_mqtt_qos_t)(((d) >> 0x01) & 0x03)) +#define MQTT_RCV_GET_PACKET_QOS(d) ((lwgsm_mqtt_qos_t)(((d) >> 0x01) & 0x03)) #define MQTT_RCV_GET_PACKET_DUP(d) (((d) >> 0x03) & 0x01) /* Requests status */ @@ -121,11 +121,11 @@ typedef enum { #define MQTT_REQUEST_FLAG_SUBSCRIBE 0x04 /*!< Request object has subscribe type */ #define MQTT_REQUEST_FLAG_UNSUBSCRIBE 0x08 /*!< Request object has unsubscribe type */ -#if GSM_CFG_DBG +#if LWGSM_CFG_DBG -static const char * +static const char* mqtt_msg_type_to_str(mqtt_msg_type_t msg_type) { - static const char * strings[] = { + static const char* strings[] = { "UNKNOWN", "CONNECT", "CONNACK", "PUBLISH", "PUBACK", "PUBREC", "PUBREL", "PUBCOMP", "SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK", @@ -134,16 +134,17 @@ mqtt_msg_type_to_str(mqtt_msg_type_t msg_type) { return strings[(uint8_t)msg_type]; } -#endif /* GSM_CFG_DBG */ +#endif /* LWGSM_CFG_DBG */ /** * \brief Default event callback function + * \param[in] client: MQTT client * \param[in] evt: MQTT event */ static void -mqtt_evt_fn_default(gsm_mqtt_client_p client, gsm_mqtt_evt_t* evt) { - GSM_UNUSED(client); - GSM_UNUSED(evt); +mqtt_evt_fn_default(lwgsm_mqtt_client_p client, lwgsm_mqtt_evt_t* evt) { + LWGSM_UNUSED(client); + LWGSM_UNUSED(evt); } /** @@ -152,9 +153,8 @@ mqtt_evt_fn_default(gsm_mqtt_client_p client, gsm_mqtt_evt_t* evt) { * \return New packet ID */ static uint16_t -create_packet_id(gsm_mqtt_client_p client) { - client->last_packet_id++; - if (client->last_packet_id == 0) { +create_packet_id(lwgsm_mqtt_client_p client) { + if (++client->last_packet_id == 0) { client->last_packet_id = 1; } return client->last_packet_id; @@ -173,13 +173,13 @@ create_packet_id(gsm_mqtt_client_p client) { * \param[in] arg: User optional argument for identifying packets * \return Pointer to new request ready to use or `NULL` if no available memory */ -static gsm_mqtt_request_t * -request_create(gsm_mqtt_client_p client, uint16_t packet_id, void* arg) { - gsm_mqtt_request_t* request; +static lwgsm_mqtt_request_t* +request_create(lwgsm_mqtt_client_p client, uint16_t packet_id, void* arg) { + lwgsm_mqtt_request_t* request; uint16_t i; /* Try to find a new request which does not have IN_USE flag set */ - for (request = NULL, i = 0; i < GSM_CFG_MQTT_MAX_REQUESTS; i++) { + for (request = NULL, i = 0; i < LWGSM_CFG_MQTT_MAX_REQUESTS; ++i) { if (!(client->requests[i].status & MQTT_REQUEST_FLAG_IN_USE)) { request = &client->requests[i]; /* We have empty request */ break; @@ -199,9 +199,9 @@ request_create(gsm_mqtt_client_p client, uint16_t packet_id, void* arg) { * \param[in] request: Request object to delete */ static void -request_delete(gsm_mqtt_client_p client, gsm_mqtt_request_t* request) { +request_delete(lwgsm_mqtt_client_p client, lwgsm_mqtt_request_t* request) { request->status = 0; /* Reset status to make request unused */ - GSM_UNUSED(client); + LWGSM_UNUSED(client); } /** @@ -210,10 +210,10 @@ request_delete(gsm_mqtt_client_p client, gsm_mqtt_request_t* request) { * \param[in] request: Request object to delete */ static void -request_set_pending(gsm_mqtt_client_p client, gsm_mqtt_request_t* request) { - request->timeout_start_time = gsm_sys_now();/* Set timeout start time */ +request_set_pending(lwgsm_mqtt_client_p client, lwgsm_mqtt_request_t* request) { + request->timeout_start_time = lwgsm_sys_now(); /* Set timeout start time */ request->status |= MQTT_REQUEST_FLAG_PENDING; /* Set pending flag */ - GSM_UNUSED(client); + LWGSM_UNUSED(client); } /** @@ -222,10 +222,10 @@ request_set_pending(gsm_mqtt_client_p client, gsm_mqtt_request_t* request) { * \param[in] pkt_id: Packet id to get request for. Use `-1` to get first pending request * \return Request on success, `NULL` otherwise */ -static gsm_mqtt_request_t * -request_get_pending(gsm_mqtt_client_p client, int32_t pkt_id) { +static lwgsm_mqtt_request_t* +request_get_pending(lwgsm_mqtt_client_p client, int32_t pkt_id) { /* Try to find a new request which does not have IN_USE flag set */ - for (size_t i = 0; i < GSM_CFG_MQTT_MAX_REQUESTS; i++) { + for (size_t i = 0; i < LWGSM_CFG_MQTT_MAX_REQUESTS; ++i) { if ((client->requests[i].status & MQTT_REQUEST_FLAG_PENDING) && (pkt_id == -1 || client->requests[i].packet_id == (uint16_t)pkt_id)) { return &client->requests[i]; @@ -241,21 +241,21 @@ request_get_pending(gsm_mqtt_client_p client, int32_t pkt_id) { * \param[in] arg: User argument */ static void -request_send_err_callback(gsm_mqtt_client_p client, uint8_t status, void* arg) { +request_send_err_callback(lwgsm_mqtt_client_p client, uint8_t status, void* arg) { if (status & MQTT_REQUEST_FLAG_SUBSCRIBE) { - client->evt.type = GSM_MQTT_EVT_SUBSCRIBE; + client->evt.type = LWGSM_MQTT_EVT_SUBSCRIBE; } else if (status & MQTT_REQUEST_FLAG_UNSUBSCRIBE) { - client->evt.type = GSM_MQTT_EVT_UNSUBSCRIBE; + client->evt.type = LWGSM_MQTT_EVT_UNSUBSCRIBE; } else { - client->evt.type = GSM_MQTT_EVT_PUBLISH; + client->evt.type = LWGSM_MQTT_EVT_PUBLISH; } - if (client->evt.type == GSM_MQTT_EVT_PUBLISH) { + if (client->evt.type == LWGSM_MQTT_EVT_PUBLISH) { client->evt.evt.publish.arg = arg; - client->evt.evt.publish.res = gsmERR; + client->evt.evt.publish.res = lwgsmERR; } else { client->evt.evt.sub_unsub_scribed.arg = arg; - client->evt.evt.sub_unsub_scribed.res = gsmERR; + client->evt.evt.sub_unsub_scribed.res = lwgsmERR; } client->evt_fn(client, &client->evt); } @@ -276,22 +276,38 @@ request_send_err_callback(gsm_mqtt_client_p client, uint8_t status, void* arg) { * \param[in] rem_len: Remaining packet length, excluding variable length part */ static void -write_fixed_header(gsm_mqtt_client_p client, mqtt_msg_type_t type, uint8_t dup, gsm_mqtt_qos_t qos, uint8_t retain, uint16_t rem_len) { +write_fixed_header(lwgsm_mqtt_client_p client, mqtt_msg_type_t type, uint8_t dup, lwgsm_mqtt_qos_t qos, uint8_t retain, uint16_t rem_len) { uint8_t b; - b = GSM_U8(((GSM_U8(type)) << 0x04) | (GSM_U8(!!dup) << 0x03) | ((GSM_U8(qos) & 0x03) << 0x01) | GSM_U8(!!retain)); - gsm_buff_write(&client->tx_buff, &b, 1); /* Write start of packet parameters */ + /* + * Fixed header flags according to: + * http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718020 + */ + b = LWGSM_U8(type) << 0x04; + switch (type) { + case MQTT_MSG_TYPE_PUBLISH: + b |= LWGSM_U8(!!dup) << 0x03 | (LWGSM_U8(qos & 0x03)) << 0x01 | LWGSM_U8(!!retain); + break; + case MQTT_MSG_TYPE_PUBREL: + case MQTT_MSG_TYPE_SUBSCRIBE: + case MQTT_MSG_TYPE_UNSUBSCRIBE: + b |= LWGSM_U8(LWGSM_MQTT_QOS_AT_LEAST_ONCE) << 0x01; + break; + default: + break; + } + lwgsm_buff_write(&client->tx_buff, &b, 1); /* Write start of packet parameters */ - GSM_DEBUGF(GSM_CFG_DBG_MQTT_TRACE, - "[MQTT] Writing packet type %s to output buffer\r\n", mqtt_msg_type_to_str(type)); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_TRACE, + "[MQTT] Writing packet type %s to output buffer\r\n", mqtt_msg_type_to_str(type)); do { /* Encode length, we must write a len byte even if 0 */ /* * Length is encoded LSB first up to 127 (0x7F) long, * where bit 7 indicates we have more data in queue for length parameter */ - b = GSM_U8((rem_len & 0x7F) | (rem_len > 0x7F ? 0x80 : 0)); - gsm_buff_write(&client->tx_buff, &b, 1);/* Write single byte */ + b = LWGSM_U8((rem_len & 0x7F) | (rem_len > 0x7F ? 0x80 : 0)); + lwgsm_buff_write(&client->tx_buff, &b, 1); /* Write single byte */ rem_len >>= 7; /* Go to next 127 bytes */ } while (rem_len > 0); } @@ -302,8 +318,8 @@ write_fixed_header(gsm_mqtt_client_p client, mqtt_msg_type_t type, uint8_t dup, * \param[in] num: Number to write */ static void -write_u8(gsm_mqtt_client_p client, uint8_t num) { - gsm_buff_write(&client->tx_buff, &num, 1); /* Write single byte */ +write_u8(lwgsm_mqtt_client_p client, uint8_t num) { + lwgsm_buff_write(&client->tx_buff, &num, 1);/* Write single byte */ } /** @@ -312,9 +328,9 @@ write_u8(gsm_mqtt_client_p client, uint8_t num) { * \param[in] num: Number to write */ static void -write_u16(gsm_mqtt_client_p client, uint16_t num) { - write_u8(client, GSM_U8(num >> 8)); /* Write MSB first... */ - write_u8(client, GSM_U8(num & 0xFF)); /* ...followed by LSB */ +write_u16(lwgsm_mqtt_client_p client, uint16_t num) { + write_u8(client, LWGSM_U8(num >> 8)); /* Write MSB first... */ + write_u8(client, LWGSM_U8(num & 0xFF)); /* ...followed by LSB */ } /** @@ -324,8 +340,8 @@ write_u16(gsm_mqtt_client_p client, uint16_t num) { * \param[in] len: Length of data to write */ static void -write_data(gsm_mqtt_client_p client, const void* data, size_t len) { - gsm_buff_write(&client->tx_buff, data, len);/* Write raw data to buffer */ +write_data(lwgsm_mqtt_client_p client, const void* data, size_t len) { + lwgsm_buff_write(&client->tx_buff, data, len); /* Write raw data to buffer */ } /** @@ -339,15 +355,15 @@ write_data(gsm_mqtt_client_p client, const void* data, size_t len) { * \return Number of required RAW bytes or `0` if no memory available */ static uint16_t -output_check_enough_memory(gsm_mqtt_client_p client, uint16_t rem_len) { +output_check_enough_memory(lwgsm_mqtt_client_p client, uint16_t rem_len) { uint16_t total_len = rem_len + 1; /* Remaining length + first (packet start) byte */ do { /* Calculate bytes for encoding remaining length itself */ - total_len++; + ++total_len; rem_len >>= 7; /* Encoded with 7 bits per byte */ } while (rem_len > 0); - return GSM_U16(gsm_buff_get_free(&client->tx_buff)) >= total_len ? total_len : 0; + return LWGSM_U16(lwgsm_buff_get_free(&client->tx_buff)) >= total_len ? total_len : 0; } /** @@ -359,17 +375,17 @@ output_check_enough_memory(gsm_mqtt_client_p client, uint16_t rem_len) { * \return `1` on success, `0` otherwise */ static uint8_t -write_ack_rec_rel_resp(gsm_mqtt_client_p client, mqtt_msg_type_t msg_type, uint16_t pkt_id, gsm_mqtt_qos_t qos) { +write_ack_rec_rel_resp(lwgsm_mqtt_client_p client, mqtt_msg_type_t msg_type, uint16_t pkt_id, lwgsm_mqtt_qos_t qos) { if (output_check_enough_memory(client, 2)) {/* Check memory for response packet */ write_fixed_header(client, msg_type, 0, qos, 0, 2); /* Write fixed header with 2 more bytes for packet id */ write_u16(client, pkt_id); /* Write packet ID */ send_data(client); /* Flush data to output */ - GSM_DEBUGF(GSM_CFG_DBG_MQTT_TRACE, - "[MQTT] Response %s written to output memory\r\n", mqtt_msg_type_to_str(msg_type)); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_TRACE, + "[MQTT] Response %s written to output memory\r\n", mqtt_msg_type_to_str(msg_type)); return 1; } else { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_TRACE, - "[MQTT] No memory to write %s packet\r\n", mqtt_msg_type_to_str(msg_type)); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_TRACE, + "[MQTT] No memory to write %s packet\r\n", mqtt_msg_type_to_str(msg_type)); } return 0; } @@ -378,11 +394,12 @@ write_ack_rec_rel_resp(gsm_mqtt_client_p client, mqtt_msg_type_t msg_type, uint1 * \brief Write string to output buffer * \param[in] client: MQTT client * \param[in] str: String to write to buffer + * \param[in] len: Length of string */ static void -write_string(gsm_mqtt_client_p client, const char* str, uint16_t len) { +write_string(lwgsm_mqtt_client_p client, const char* str, uint16_t len) { write_u16(client, len); /* Write string length */ - gsm_buff_write(&client->tx_buff, str, len); /* Write string to buffer */ + lwgsm_buff_write(&client->tx_buff, str, len); /* Write string to buffer */ } /** @@ -390,7 +407,7 @@ write_string(gsm_mqtt_client_p client, const char* str, uint16_t len) { * \param[in] client: MQTT client */ static void -send_data(gsm_mqtt_client_p client) { +send_data(lwgsm_mqtt_client_p client) { size_t len; const void* addr; @@ -398,42 +415,42 @@ send_data(gsm_mqtt_client_p client) { return; } - len = gsm_buff_get_linear_block_read_length(&client->tx_buff); /* Get length of linear memory */ - if (len > 0) { /* Anything to send? */ - gsmr_t res; - addr = gsm_buff_get_linear_block_read_address(&client->tx_buff);/* Get address of linear memory */ - if ((res = gsm_conn_send(client->conn, addr, len, NULL, 0)) == gsmOK) { + len = lwgsm_buff_get_linear_block_read_length(&client->tx_buff);/* Get length of linear memory */ + if (len > 0) { /* Anything to send? */ + lwgsmr_t res; + addr = lwgsm_buff_get_linear_block_read_address(&client->tx_buff); /* Get address of linear memory */ + if ((res = lwgsm_conn_send(client->conn, addr, len, NULL, 0)) == lwgsmOK) { client->written_total += len; /* Increase number of bytes written to queue */ client->is_sending = 1; /* Remember active sending flag */ } else { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_TRACE_WARNING, - "[MQTT] Cannot send data with error: %d\r\n", (int)res); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_TRACE_WARNING, + "[MQTT] Cannot send data with error: %d\r\n", (int)res); } } else { - /* + /* * If buffer is empty, reset it to default state (read & write pointers) * This is to make sure everytime function needs to send data, * it can do it in single shot rather than in 2 attempts (when read > write pointer). * Effectively this means faster transmission of MQTT packets and lower latency. */ - gsm_buff_reset(&client->tx_buff); + lwgsm_buff_reset(&client->tx_buff); } } /** * \brief Close a MQTT connection with server * \param[in] client: MQTT client - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -static gsmr_t -mqtt_close(gsm_mqtt_client_p client) { - gsmr_t res = gsmERR; - if (client->conn_state != GSM_MQTT_CONN_DISCONNECTED - && client->conn_state != GSM_MQTT_CONN_DISCONNECTING) { - - res = gsm_conn_close(client->conn, 0); /* Close the connection in non-blocking mode */ - if (res == gsmOK) { - client->conn_state = GSM_MQTT_CONN_DISCONNECTING; +static lwgsmr_t +mqtt_close(lwgsm_mqtt_client_p client) { + lwgsmr_t res = lwgsmERR; + if (client->conn_state != LWGSM_MQTT_CONN_DISCONNECTED + && client->conn_state != LWGSM_MQTT_CONN_DISCONNECTING) { + + res = lwgsm_conn_close(client->conn, 0);/* Close the connection in non-blocking mode */ + if (res == lwgsmOK) { + client->conn_state = LWGSM_MQTT_CONN_DISCONNECTING; } } return res; @@ -444,17 +461,18 @@ mqtt_close(gsm_mqtt_client_p client) { * \param[in] client: MQTT client * \param[in] topic: MQTT topic to (un)subscribe * \param[in] qos: Quality of service, used only on subscribe part + * \param[in] arg: Custom argument * \param[in] sub: Status set to `1` on subscribe or `0` on unsubscribe * \return `1` on success, `0` otherwise */ static uint8_t -sub_unsub(gsm_mqtt_client_p client, const char* topic, gsm_mqtt_qos_t qos, void* arg, uint8_t sub) { - gsm_mqtt_request_t* request; +sub_unsub(lwgsm_mqtt_client_p client, const char* topic, lwgsm_mqtt_qos_t qos, void* arg, uint8_t sub) { + lwgsm_mqtt_request_t* request; uint32_t rem_len; uint16_t len_topic, pkt_id; uint8_t ret = 0; - - if ((len_topic = GSM_U16(strlen(topic))) == 0) { + + if ((len_topic = LWGSM_U16(strlen(topic))) == 0) { return 0; } @@ -465,20 +483,20 @@ sub_unsub(gsm_mqtt_client_p client, const char* topic, gsm_mqtt_qos_t qos, void* */ rem_len = 2 + len_topic + 2; if (sub) { - rem_len++; + ++rem_len; } - gsm_core_lock(); - if (client->conn_state == GSM_MQTT_CONNECTED + lwgsm_core_lock(); + if (client->conn_state == LWGSM_MQTT_CONNECTED && output_check_enough_memory(client, rem_len)) { /* Check if enough memory to write packet data */ pkt_id = create_packet_id(client); /* Create new packet ID */ request = request_create(client, pkt_id, arg); /* Create request for packet */ if (request != NULL) { /* Do we have a request */ - write_fixed_header(client, sub ? MQTT_MSG_TYPE_SUBSCRIBE : MQTT_MSG_TYPE_UNSUBSCRIBE, 0, (gsm_mqtt_qos_t)1, 0, rem_len); + write_fixed_header(client, sub ? MQTT_MSG_TYPE_SUBSCRIBE : MQTT_MSG_TYPE_UNSUBSCRIBE, 0, (lwgsm_mqtt_qos_t)1, 0, rem_len); write_u16(client, pkt_id); /* Write packet ID */ write_string(client, topic, len_topic); /* Write topic string to packet */ if (sub) { /* Send quality of service only on subscribe */ - write_u8(client, GSM_MIN(GSM_U8(qos), GSM_U8(GSM_MQTT_QOS_EXACTLY_ONCE))); /* Write quality of service */ + write_u8(client, LWGSM_MIN(LWGSM_U8(qos), LWGSM_U8(LWGSM_MQTT_QOS_EXACTLY_ONCE))); /* Write quality of service */ } request->status |= sub ? MQTT_REQUEST_FLAG_SUBSCRIBE : MQTT_REQUEST_FLAG_UNSUBSCRIBE; @@ -487,7 +505,7 @@ sub_unsub(gsm_mqtt_client_p client, const char* topic, gsm_mqtt_qos_t qos, void* ret = 1; } } - gsm_core_unlock(); + lwgsm_core_unlock(); return ret; } @@ -497,45 +515,45 @@ sub_unsub(gsm_mqtt_client_p client, const char* topic, gsm_mqtt_qos_t qos, void* * \return `1` on success, `0` otherwise */ static uint8_t -mqtt_process_incoming_message(gsm_mqtt_client_p client) { +mqtt_process_incoming_message(lwgsm_mqtt_client_p client) { mqtt_msg_type_t msg_type; - gsm_mqtt_qos_t qos; + lwgsm_mqtt_qos_t qos; uint16_t pkt_id; msg_type = MQTT_RCV_GET_PACKET_TYPE(client->msg_hdr_byte); /* Get packet type from message header byte */ /* Debug message */ - GSM_DEBUGF(GSM_CFG_DBG_MQTT_STATE, - "[MQTT] Processing packet type %s\r\n", mqtt_msg_type_to_str(msg_type)); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_STATE, + "[MQTT] Processing packet type %s\r\n", mqtt_msg_type_to_str(msg_type)); /* Check received packet type */ switch (msg_type) { case MQTT_MSG_TYPE_CONNACK: { - gsm_mqtt_conn_status_t err = (gsm_mqtt_conn_status_t)client->rx_buff[1]; - if (client->conn_state == GSM_MQTT_CONNECTING) { - if (err == GSM_MQTT_CONN_STATUS_ACCEPTED) { - client->conn_state = GSM_MQTT_CONNECTED; + lwgsm_mqtt_conn_status_t err = (lwgsm_mqtt_conn_status_t)client->rx_buff[1]; + if (client->conn_state == LWGSM_MQTT_CONNECTING) { + if (err == LWGSM_MQTT_CONN_STATUS_ACCEPTED) { + client->conn_state = LWGSM_MQTT_CONNECTED; } - GSM_DEBUGF(GSM_CFG_DBG_MQTT_TRACE, - "[MQTT] CONNACK received with result: %d\r\n", (int)err); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_TRACE, + "[MQTT] CONNACK received with result: %d\r\n", (int)err); /* Notify user layer */ - client->evt.type = GSM_MQTT_EVT_CONNECT; + client->evt.type = LWGSM_MQTT_EVT_CONNECT; client->evt.evt.connect.status = err; client->evt_fn(client, &client->evt); } else { /* Protocol violation here */ - GSM_DEBUGF(GSM_CFG_DBG_MQTT_TRACE, - "[MQTT] Protocol violation. CONNACK received when already connected!\r\n"); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_TRACE, + "[MQTT] Protocol violation. CONNACK received when already connected!\r\n"); } break; } case MQTT_MSG_TYPE_PUBLISH: { uint16_t topic_len, data_len; - uint8_t *topic, *data, dup; + uint8_t* topic, *data, dup; - qos = MQTT_RCV_GET_PACKET_QOS(client->msg_hdr_byte); /* Get QoS from received packet */ - dup = MQTT_RCV_GET_PACKET_DUP(client->msg_hdr_byte); /* Get duplicate flag */ + qos = MQTT_RCV_GET_PACKET_QOS(client->msg_hdr_byte);/* Get QoS from received packet */ + dup = MQTT_RCV_GET_PACKET_DUP(client->msg_hdr_byte);/* Get duplicate flag */ topic_len = (client->rx_buff[0] << 8) | client->rx_buff[1]; topic = &client->rx_buff[2]; /* Start of topic */ @@ -551,9 +569,9 @@ mqtt_process_incoming_message(gsm_mqtt_client_p client) { } data_len = client->msg_rem_len - (data - client->rx_buff); /* Calculate length of remaining data */ - GSM_DEBUGF(GSM_CFG_DBG_MQTT_TRACE, - "[MQTT] Publish packet received on topic %.*s; QoS: %d; pkt_id: %d; data_len: %d\r\n", - (int)topic_len, (const char *)topic, (int)qos, (int)pkt_id, (int)data_len); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_TRACE, + "[MQTT] Publish packet received on topic %.*s; QoS: %d; pkt_id: %d; data_len: %d\r\n", + (int)topic_len, (const char*)topic, (int)qos, (int)pkt_id, (int)data_len); /* * We have to send respond to command if @@ -564,14 +582,14 @@ mqtt_process_incoming_message(gsm_mqtt_client_p client) { */ if (qos > 0) { /* We have to reply on QoS > 0 */ mqtt_msg_type_t resp_msg_type = qos == 1 ? MQTT_MSG_TYPE_PUBACK : MQTT_MSG_TYPE_PUBREC; - GSM_DEBUGF(GSM_CFG_DBG_MQTT_TRACE, "[MQTT] Sending publish resp: %s on pkt_id: %d\r\n", \ - mqtt_msg_type_to_str(resp_msg_type), (int)pkt_id); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_TRACE, "[MQTT] Sending publish resp: %s on pkt_id: %d\r\n", \ + mqtt_msg_type_to_str(resp_msg_type), (int)pkt_id); write_ack_rec_rel_resp(client, resp_msg_type, pkt_id, qos); } /* Notify application layer about received packet */ - client->evt.type = GSM_MQTT_EVT_PUBLISH_RECV; + client->evt.type = LWGSM_MQTT_EVT_PUBLISH_RECV; client->evt.evt.publish_recv.topic = topic; client->evt.evt.publish_recv.topic_len = topic_len; client->evt.evt.publish_recv.payload = data; @@ -582,9 +600,9 @@ mqtt_process_incoming_message(gsm_mqtt_client_p client) { break; } case MQTT_MSG_TYPE_PINGRESP: { /* Respond to PINGREQ received */ - GSM_DEBUGF(GSM_CFG_DBG_MQTT_TRACE, "[MQTT] Ping response received\r\n"); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_TRACE, "[MQTT] Ping response received\r\n"); - client->evt.type = GSM_MQTT_EVT_KEEP_ALIVE; + client->evt.type = LWGSM_MQTT_EVT_KEEP_ALIVE; client->evt_fn(client, &client->evt); break; } @@ -597,14 +615,14 @@ mqtt_process_incoming_message(gsm_mqtt_client_p client) { pkt_id = client->rx_buff[0] << 8 | client->rx_buff[1]; /* Get packet ID */ if (msg_type == MQTT_MSG_TYPE_PUBREC) { /* Publish record received from server */ - write_ack_rec_rel_resp(client, MQTT_MSG_TYPE_PUBREL, pkt_id, (gsm_mqtt_qos_t)1); /* Send back publish release message */ + write_ack_rec_rel_resp(client, MQTT_MSG_TYPE_PUBREL, pkt_id, (lwgsm_mqtt_qos_t)1); /* Send back publish release message */ } else if (msg_type == MQTT_MSG_TYPE_PUBREL) { /* Publish release was received */ - write_ack_rec_rel_resp(client, MQTT_MSG_TYPE_PUBCOMP, pkt_id, (gsm_mqtt_qos_t)0); /* Send back publish complete */ + write_ack_rec_rel_resp(client, MQTT_MSG_TYPE_PUBCOMP, pkt_id, (lwgsm_mqtt_qos_t)0); /* Send back publish complete */ } else if (msg_type == MQTT_MSG_TYPE_SUBACK - || msg_type == MQTT_MSG_TYPE_UNSUBACK - || msg_type == MQTT_MSG_TYPE_PUBACK - || msg_type == MQTT_MSG_TYPE_PUBCOMP) { - gsm_mqtt_request_t* request; + || msg_type == MQTT_MSG_TYPE_UNSUBACK + || msg_type == MQTT_MSG_TYPE_PUBACK + || msg_type == MQTT_MSG_TYPE_PUBCOMP) { + lwgsm_mqtt_request_t* request; /* * We can enter here only if we received final acknowledge @@ -617,27 +635,27 @@ mqtt_process_incoming_message(gsm_mqtt_client_p client) { if (request != NULL) { if (msg_type == MQTT_MSG_TYPE_SUBACK || msg_type == MQTT_MSG_TYPE_UNSUBACK) { - client->evt.type = msg_type == MQTT_MSG_TYPE_SUBACK ? GSM_MQTT_EVT_SUBSCRIBE : GSM_MQTT_EVT_UNSUBSCRIBE; + client->evt.type = msg_type == MQTT_MSG_TYPE_SUBACK ? LWGSM_MQTT_EVT_SUBSCRIBE : LWGSM_MQTT_EVT_UNSUBSCRIBE; client->evt.evt.sub_unsub_scribed.arg = request->arg; - client->evt.evt.sub_unsub_scribed.res = client->rx_buff[2] < 3 ? gsmOK : gsmERR; + client->evt.evt.sub_unsub_scribed.res = client->rx_buff[2] < 3 ? lwgsmOK : lwgsmERR; client->evt_fn(client, &client->evt); - /* - * Final acknowledge of packet received - * Ack type depends on QoS level being sent to server on request - */ + /* + * Final acknowledge of packet received + * Ack type depends on QoS level being sent to server on request + */ } else if (msg_type == MQTT_MSG_TYPE_PUBCOMP - || msg_type == MQTT_MSG_TYPE_PUBACK) { - client->evt.type = GSM_MQTT_EVT_PUBLISH; + || msg_type == MQTT_MSG_TYPE_PUBACK) { + client->evt.type = LWGSM_MQTT_EVT_PUBLISH; client->evt.evt.publish.arg = request->arg; - client->evt.evt.publish.res = gsmOK; + client->evt.evt.publish.res = lwgsmOK; client->evt_fn(client, &client->evt); } - request_delete(client, request); /* Delete request object */ + request_delete(client, request);/* Delete request object */ } else { /* Protocol violation at this point! */ - GSM_DEBUGF(GSM_CFG_DBG_MQTT_TRACE, - "[MQTT] Protocol violation. Received ACK without sent packet\r\n"); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_TRACE, + "[MQTT] Protocol violation. Received ACK without sent packet\r\n"); } } break; @@ -655,22 +673,22 @@ mqtt_process_incoming_message(gsm_mqtt_client_p client) { * \return `1` on success, `0` otherwise */ static uint8_t -mqtt_parse_incoming(gsm_mqtt_client_p client, gsm_pbuf_p pbuf) { - size_t idx, buff_len = 0, buff_offset = 0; +mqtt_parse_incoming(lwgsm_mqtt_client_p client, lwgsm_pbuf_p pbuf) { + size_t buff_len = 0, buff_offset = 0; uint8_t ch, *d; do { buff_offset += buff_len; /* Calculate new offset of buffer */ - d = gsm_pbuf_get_linear_addr(pbuf, buff_offset, &buff_len); /* Get address pointer */ + d = lwgsm_pbuf_get_linear_addr(pbuf, buff_offset, &buff_len); /* Get address pointer */ if (d == NULL) { break; } - for (idx = 0; idx < buff_len; idx++) { /* Process entire linear buffer */ + for (size_t idx = 0; idx < buff_len; ++idx) { /* Process entire linear buffer */ ch = d[idx]; switch (client->parser_state) { /* Check parser state */ case MQTT_PARSER_STATE_INIT: { /* We are waiting for start byte and packet type */ - GSM_DEBUGF(GSM_CFG_DBG_MQTT_STATE, - "[MQTT] Parser init state, received first byte of packet 0x%02X\r\n", (unsigned)ch); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_STATE, + "[MQTT] Parser init state, received first byte of packet 0x%02X\r\n", (unsigned)ch); /* Save other info about message */ client->msg_hdr_byte = ch; /* Save first entry */ @@ -683,11 +701,12 @@ mqtt_parse_incoming(gsm_mqtt_client_p client, gsm_pbuf_p pbuf) { } case MQTT_PARSER_STATE_CALC_REM_LEN: { /* Calculate remaining length of packet */ /* Length of packet is LSB first, each consist of up to 7 bits */ - client->msg_rem_len |= (ch & 0x7F) << ((size_t)7 * (size_t)client->msg_rem_len_mult++); + client->msg_rem_len |= (ch & 0x7F) << ((size_t)7 * (size_t)client->msg_rem_len_mult); + ++client->msg_rem_len_mult; if (!(ch & 0x80)) { /* Is this last entry? */ - GSM_DEBUGF(GSM_CFG_DBG_MQTT_STATE, - "[MQTT] Remaining length received: %d bytes\r\n", (int)client->msg_rem_len); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_STATE, + "[MQTT] Remaining length received: %d bytes\r\n", (int)client->msg_rem_len); if (client->msg_rem_len > 0) { /* @@ -726,18 +745,18 @@ mqtt_parse_incoming(gsm_mqtt_client_p client, gsm_pbuf_p pbuf) { if (client->msg_curr_pos < client->rx_buff_len) { client->rx_buff[client->msg_curr_pos] = ch; /* Write received character */ } - client->msg_curr_pos++; + ++client->msg_curr_pos; /* We reached end of received characters? */ if (client->msg_curr_pos == client->msg_rem_len) { if (client->msg_curr_pos <= client->rx_buff_len) { /* Check if it was possible to write all data to rx buffer */ - GSM_DEBUGF(GSM_CFG_DBG_MQTT_STATE, - "[MQTT] Packet parsed and ready for processing\r\n"); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_STATE, + "[MQTT] Packet parsed and ready for processing\r\n"); mqtt_process_incoming_message(client); /* Process incoming packet */ } else { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_TRACE_WARNING, - "[MQTT] Packet too big for rx buffer. Packet discarded\r\n"); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_TRACE_WARNING, + "[MQTT] Packet too big for rx buffer. Packet discarded\r\n"); } client->parser_state = MQTT_PARSER_STATE_INIT; /* Go to initial state and listen for next received packet */ } @@ -762,7 +781,7 @@ mqtt_parse_incoming(gsm_mqtt_client_p client, gsm_pbuf_p pbuf) { * \param[in] client: MQTT client */ static void -mqtt_connected_cb(gsm_mqtt_client_p client) { +mqtt_connected_cb(lwgsm_mqtt_client_p client) { uint16_t rem_len, len_id, len_pass = 0, len_user = 0, len_will_topic = 0, len_will_message = 0; uint8_t flags = 0; @@ -776,15 +795,15 @@ mqtt_connected_cb(gsm_mqtt_client_p client) { */ rem_len = 10; /* Set remaining length of fixed header */ - len_id = GSM_U16(strlen(client->info->id)); /* Get cliend ID length */ + len_id = LWGSM_U16(strlen(client->info->id)); /* Get cliend ID length */ rem_len += len_id + 2; /* Add client id length including length entries */ if (client->info->will_topic != NULL && client->info->will_message != NULL) { flags |= MQTT_FLAG_CONNECT_WILL; - flags |= GSM_MIN(GSM_U8(client->info->will_qos), 2) << 0x03;/* Set qos to flags */ + flags |= LWGSM_MIN(LWGSM_U8(client->info->will_qos), 2) << 0x03;/* Set qos to flags */ - len_will_topic = GSM_U16(strlen(client->info->will_topic)); - len_will_message = GSM_U16(strlen(client->info->will_message)); + len_will_topic = LWGSM_U16(strlen(client->info->will_topic)); + len_will_message = LWGSM_U16(strlen(client->info->will_message)); rem_len += len_will_topic + 2; /* Add will topic parameter */ rem_len += len_will_message + 2; /* Add will message parameter */ @@ -793,14 +812,14 @@ mqtt_connected_cb(gsm_mqtt_client_p client) { if (client->info->user != NULL) { /* Check for username */ flags |= MQTT_FLAG_CONNECT_USERNAME; /* Username is included */ - len_user = GSM_U16(strlen(client->info->user)); /* Get username length */ + len_user = LWGSM_U16(strlen(client->info->user)); /* Get username length */ rem_len += len_user + 2; /* Add username length including length entries */ } if (client->info->pass != NULL) { /* Check for password */ flags |= MQTT_FLAG_CONNECT_PASSWORD; /* Password is included */ - len_pass = GSM_U16(strlen(client->info->pass)); /* Get username length */ + len_pass = LWGSM_U16(strlen(client->info->pass)); /* Get username length */ rem_len += len_pass + 2; /* Add password length including length entries */ } @@ -809,7 +828,7 @@ mqtt_connected_cb(gsm_mqtt_client_p client) { } /* Write everything to output buffer */ - write_fixed_header(client, MQTT_MSG_TYPE_CONNECT, 0, (gsm_mqtt_qos_t)0, 0, rem_len); + write_fixed_header(client, MQTT_MSG_TYPE_CONNECT, 0, (lwgsm_mqtt_qos_t)0, 0, rem_len); write_string(client, "MQTT", 4); /* Protocol name */ write_u8(client, 4); /* Protocol version */ write_u8(client, flags); /* Flags for CONNECT message */ @@ -829,7 +848,7 @@ mqtt_connected_cb(gsm_mqtt_client_p client) { client->parser_state = MQTT_PARSER_STATE_INIT; /* Reset parser state */ client->poll_time = 0; /* Reset kep alive time */ - client->conn_state = GSM_MQTT_CONNECTING; /* MQTT is connecting to server */ + client->conn_state = LWGSM_MQTT_CONNECTING; /* MQTT is connecting to server */ send_data(client); /* Flush and send the actual data */ } @@ -841,10 +860,9 @@ mqtt_connected_cb(gsm_mqtt_client_p client) { * \return `1` on success, `0` otherwise */ static uint8_t -mqtt_data_recv_cb(gsm_mqtt_client_p client, gsm_pbuf_p pbuf) { - client->poll_time = 0; /* Reset kep alive time */ - mqtt_parse_incoming(client, pbuf); - gsm_conn_recved(client->conn, pbuf); /* Notify stack about received data */ +mqtt_data_recv_cb(lwgsm_mqtt_client_p client, lwgsm_pbuf_p pbuf) { + mqtt_parse_incoming(client, pbuf); /* We need to process incoming data */ + lwgsm_conn_recved(client->conn, pbuf); /* Notify stack about received data */ return 1; } @@ -856,8 +874,8 @@ mqtt_data_recv_cb(gsm_mqtt_client_p client, gsm_pbuf_p pbuf) { * \return `1` on success, `0` otherwise */ static uint8_t -mqtt_data_sent_cb(gsm_mqtt_client_p client, size_t sent_len, uint8_t successful) { - gsm_mqtt_request_t* request; +mqtt_data_sent_cb(lwgsm_mqtt_client_p client, size_t sent_len, uint8_t successful) { + lwgsm_mqtt_request_t* request; client->is_sending = 0; /* We are not sending anymore */ client->sent_total += sent_len; @@ -870,13 +888,13 @@ mqtt_data_sent_cb(gsm_mqtt_client_p client, size_t sent_len, uint8_t successful) * and clear all pending requests in closed callback function */ if (!successful) { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_TRACE_WARNING, - "[MQTT] Failed to send %d bytes. Manually closing down..\r\n", (int)sent_len); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_TRACE_WARNING, + "[MQTT] Failed to send %d bytes. Manually closing down..\r\n", (int)sent_len); mqtt_close(client); return 0; } - gsm_buff_skip(&client->tx_buff, sent_len); /* Skip buffer for actual sent data */ + lwgsm_buff_skip(&client->tx_buff, sent_len);/* Skip buffer for actual sent data */ /* * Check pending publish requests without QoS because there is no confirmation received by server. @@ -891,9 +909,9 @@ mqtt_data_sent_cb(gsm_mqtt_client_p client, size_t sent_len, uint8_t successful) request_delete(client, request); /* Delete request and make space for next command */ /* Call published callback */ - client->evt.type = GSM_MQTT_EVT_PUBLISH; + client->evt.type = LWGSM_MQTT_EVT_PUBLISH; client->evt.evt.publish.arg = arg; - client->evt.evt.publish.res = gsmOK; + client->evt.evt.publish.res = lwgsmOK; client->evt_fn(client, &client->evt); } else { break; @@ -906,15 +924,15 @@ mqtt_data_sent_cb(gsm_mqtt_client_p client, size_t sent_len, uint8_t successful) /** * \brief Poll for client connection - * Called every GSM_CFG_CONN_POLL_INTERVAL ms when MQTT client TCP connection is established + * Called every LWGSM_CFG_CONN_POLL_INTERVAL ms when MQTT client TCP connection is established * \param[in] client: MQTT client * \return `1` on success, `0` otherwise */ static uint8_t -mqtt_poll_cb(gsm_mqtt_client_p client) { - client->poll_time++; +mqtt_poll_cb(lwgsm_mqtt_client_p client) { + ++client->poll_time; - if (client->conn_state == GSM_MQTT_CONN_DISCONNECTING) { + if (client->conn_state == LWGSM_MQTT_CONN_DISCONNECTING) { return 0; } @@ -924,18 +942,18 @@ mqtt_poll_cb(gsm_mqtt_client_p client) { * to make sure we are still alive */ if (client->info->keep_alive /* Keep alive must be enabled */ - /* Poll time is in units of GSM_CFG_CONN_POLL_INTERVAL milliseconds, + /* Poll time is in units of LWGSM_CFG_CONN_POLL_INTERVAL milliseconds, while keep_alive is in units of seconds */ - && (client->poll_time * GSM_CFG_CONN_POLL_INTERVAL) >= (uint32_t)(client->info->keep_alive * 1000)) { + && (client->poll_time * LWGSM_CFG_CONN_POLL_INTERVAL) >= (uint32_t)(client->info->keep_alive * 1000)) { if (output_check_enough_memory(client, 0)) {/* Check if memory available in output buffer */ - write_fixed_header(client, MQTT_MSG_TYPE_PINGREQ, 0, (gsm_mqtt_qos_t)0, 0, 0); /* Write PINGREQ command to output buffer */ + write_fixed_header(client, MQTT_MSG_TYPE_PINGREQ, 0, (lwgsm_mqtt_qos_t)0, 0, 0);/* Write PINGREQ command to output buffer */ send_data(client); /* Force send data */ client->poll_time = 0; /* Reset polling time */ - GSM_DEBUGF(GSM_CFG_DBG_MQTT_TRACE, "[MQTT] Sending PINGREQ packet\r\n"); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_TRACE, "[MQTT] Sending PINGREQ packet\r\n"); } else { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_TRACE_WARNING, "[MQTT] No memory to send PINGREQ packet\r\n"); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_TRACE_WARNING, "[MQTT] No memory to send PINGREQ packet\r\n"); } } @@ -954,17 +972,17 @@ mqtt_poll_cb(gsm_mqtt_client_p client) { * \return `1` on success, `0` otherwise */ static uint8_t -mqtt_closed_cb(gsm_mqtt_client_p client, gsmr_t res, uint8_t forced) { - gsm_mqtt_state_t state = client->conn_state; - gsm_mqtt_request_t* request; +mqtt_closed_cb(lwgsm_mqtt_client_p client, lwgsmr_t res, uint8_t forced) { + lwgsm_mqtt_state_t state = client->conn_state; + lwgsm_mqtt_request_t* request; /* * Call user function only if connection was closed * when we are connected or in disconnecting mode */ - client->conn_state = GSM_MQTT_CONN_DISCONNECTED;/* Connection is disconnected, ready to be established again */ - client->evt.evt.disconnect.is_accepted = state == GSM_MQTT_CONNECTED || state == GSM_MQTT_CONN_DISCONNECTING; /* Set connection state */ - client->evt.type = GSM_MQTT_EVT_DISCONNECT; /* Connection disconnected from server */ + client->conn_state = LWGSM_MQTT_CONN_DISCONNECTED; /* Connection is disconnected, ready to be established again */ + client->evt.evt.disconnect.is_accepted = state == LWGSM_MQTT_CONNECTED || state == LWGSM_MQTT_CONN_DISCONNECTING; /* Set connection state */ + client->evt.type = LWGSM_MQTT_EVT_DISCONNECT; /* Connection disconnected from server */ client->evt_fn(client, &client->evt); /* Notify upper layer about closed connection */ client->conn = NULL; /* Reset connection handle */ @@ -976,13 +994,13 @@ mqtt_closed_cb(gsm_mqtt_client_p client, gsmr_t res, uint8_t forced) { request_delete(client, request); /* Delete request */ request_send_err_callback(client, status, arg); /* Send error callback to user */ } - GSM_MEMSET(client->requests, 0x00, sizeof(client->requests)); + LWGSM_MEMSET(client->requests, 0x00, sizeof(client->requests)); client->is_sending = client->sent_total = client->written_total = 0; client->parser_state = MQTT_PARSER_STATE_INIT; - gsm_buff_reset(&client->tx_buff); /* Reset TX buffer */ + lwgsm_buff_reset(&client->tx_buff); /* Reset TX buffer */ - GSM_UNUSED(forced); + LWGSM_UNUSED(forced); return 1; } @@ -990,81 +1008,81 @@ mqtt_closed_cb(gsm_mqtt_client_p client, gsmr_t res, uint8_t forced) { /** * \brief Connection callback * \param[in] evt: Callback parameters - * \result \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \result \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -static gsmr_t -mqtt_conn_cb(gsm_evt_t* evt) { - gsm_conn_p conn; - gsm_mqtt_client_p client = NULL; +static lwgsmr_t +mqtt_conn_cb(lwgsm_evt_t* evt) { + lwgsm_conn_p conn; + lwgsm_mqtt_client_p client = NULL; - conn = gsm_conn_get_from_evt(evt); /* Get connection from event */ + conn = lwgsm_conn_get_from_evt(evt); /* Get connection from event */ if (conn != NULL) { - client = gsm_conn_get_arg(conn); /* Get client structure from connection */ + client = lwgsm_conn_get_arg(conn); /* Get client structure from connection */ if (client == NULL) { - gsm_conn_close(conn, 0); /* Force connection close immediatelly */ - return gsmERR; + lwgsm_conn_close(conn, 0); /* Force connection close immediately */ + return lwgsmERR; } - } else if (evt->type != GSM_EVT_CONN_ERROR) { - return gsmERR; + } else if (evt->type != LWGSM_EVT_CONN_ERROR) { + return lwgsmERR; } /* Check and process events */ - switch (gsm_evt_get_type(evt)) { + switch (lwgsm_evt_get_type(evt)) { /* * Connection error. Connection to external * server was not successful */ - case GSM_EVT_CONN_ERROR: { - gsm_mqtt_client_p client; - client = gsm_evt_conn_error_get_arg(evt); /* Get connection argument */ + case LWGSM_EVT_CONN_ERROR: { + lwgsm_mqtt_client_p client; + client = lwgsm_evt_conn_error_get_arg(evt); /* Get connection argument */ if (client != NULL) { - client->conn_state = GSM_MQTT_CONN_DISCONNECTED;/* Set back to disconnected state */ + client->conn_state = LWGSM_MQTT_CONN_DISCONNECTED; /* Set back to disconnected state */ /* Notify user upper layer */ - client->evt.type = GSM_MQTT_EVT_CONNECT; - client->evt.evt.connect.status = GSM_MQTT_CONN_STATUS_TCP_FAILED; /* TCP connection failed */ + client->evt.type = LWGSM_MQTT_EVT_CONNECT; + client->evt.evt.connect.status = LWGSM_MQTT_CONN_STATUS_TCP_FAILED; /* TCP connection failed */ client->evt_fn(client, &client->evt); /* Notify upper layer about closed connection */ } break; } /* Connection active to MQTT server */ - case GSM_EVT_CONN_ACTIVE: { + case LWGSM_EVT_CONN_ACTIVE: { mqtt_connected_cb(client); /* Call function to process status */ break; } /* A new packet of data received on MQTT client connection */ - case GSM_EVT_CONN_RECV: { - mqtt_data_recv_cb(client, gsm_evt_conn_recv_get_buff(evt));/* Call user to process received data */ + case LWGSM_EVT_CONN_RECV: { + mqtt_data_recv_cb(client, lwgsm_evt_conn_recv_get_buff(evt)); /* Call user to process received data */ break; } /* Data send event */ - case GSM_EVT_CONN_SEND: { + case LWGSM_EVT_CONN_SEND: { /* Data sent callback */ mqtt_data_sent_cb(client, - gsm_evt_conn_send_get_length(evt), - gsm_evt_conn_send_get_result(evt) == gsmOK); + lwgsm_evt_conn_send_get_length(evt), + lwgsm_evt_conn_send_get_result(evt) == lwgsmOK); break; } /* Periodic poll for connection */ - case GSM_EVT_CONN_POLL: { + case LWGSM_EVT_CONN_POLL: { mqtt_poll_cb(client); /* Poll client */ break; } /* Connection closed */ - case GSM_EVT_CONN_CLOSE: { + case LWGSM_EVT_CONN_CLOSE: { mqtt_closed_cb(client, - gsm_evt_conn_close_get_result(evt) == gsmOK, - gsm_evt_conn_close_is_forced(evt)); + lwgsm_evt_conn_close_get_result(evt) == lwgsmOK, + lwgsm_evt_conn_close_is_forced(evt)); break; } default: break; } - return gsmOK; + return lwgsmOK; } /** @@ -1073,24 +1091,24 @@ mqtt_conn_cb(gsm_evt_t* evt) { * \param[in] rx_buff_len: Length of raw data input buffer * \return Pointer to new allocated MQTT client structure or `NULL` on failure */ -gsm_mqtt_client_t * -gsm_mqtt_client_new(size_t tx_buff_len, size_t rx_buff_len) { - gsm_mqtt_client_p client; +lwgsm_mqtt_client_t* +lwgsm_mqtt_client_new(size_t tx_buff_len, size_t rx_buff_len) { + lwgsm_mqtt_client_p client; - client = gsm_mem_malloc(sizeof(*client)); + client = lwgsm_mem_malloc(sizeof(*client)); if (client != NULL) { - GSM_MEMSET(client, 0x00, sizeof(*client)); - client->conn_state = GSM_MQTT_CONN_DISCONNECTED;/* Set to disconnected mode */ + LWGSM_MEMSET(client, 0x00, sizeof(*client)); + client->conn_state = LWGSM_MQTT_CONN_DISCONNECTED; /* Set to disconnected mode */ - if (!gsm_buff_init(&client->tx_buff, tx_buff_len)) { - gsm_mem_free_s((void **)&client); + if (!lwgsm_buff_init(&client->tx_buff, tx_buff_len)) { + lwgsm_mem_free_s((void**)&client); } if (client != NULL) { client->rx_buff_len = rx_buff_len; - client->rx_buff = gsm_mem_malloc(rx_buff_len); + client->rx_buff = lwgsm_mem_malloc(rx_buff_len); if (client->rx_buff == NULL) { - gsm_buff_free(&client->tx_buff); - gsm_mem_free_s((void **)&client); + lwgsm_buff_free(&client->tx_buff); + lwgsm_mem_free_s((void**)&client); } } } @@ -1103,11 +1121,11 @@ gsm_mqtt_client_new(size_t tx_buff_len, size_t rx_buff_len) { * \param[in] client: MQTT client */ void -gsm_mqtt_client_delete(gsm_mqtt_client_p client) { +lwgsm_mqtt_client_delete(lwgsm_mqtt_client_p client) { if (client != NULL) { - gsm_mem_free_s((void **)&client->rx_buff); - gsm_buff_free(&client->tx_buff); - gsm_mem_free_s((void **)&client); + lwgsm_mem_free_s((void**)&client->rx_buff); + lwgsm_buff_free(&client->tx_buff); + lwgsm_mem_free_s((void**)&client); } } @@ -1119,30 +1137,30 @@ gsm_mqtt_client_delete(gsm_mqtt_client_p client) { * \param[in] port: Host port number * \param[in] evt_fn: Callback function for all events on this MQTT client * \param[in] info: Information structure for connection - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_mqtt_client_connect(gsm_mqtt_client_p client, const char* host, gsm_port_t port, - gsm_mqtt_evt_fn evt_fn, const gsm_mqtt_client_info_t* info) { - gsmr_t res = gsmERR; - - GSM_ASSERT("client != NULL", client != NULL); /* t input parameters */ - GSM_ASSERT("host != NULL", host != NULL); - GSM_ASSERT("port > 0", port > 0); - GSM_ASSERT("info != NULL", info != NULL); - - gsm_core_lock(); - if (gsm_network_is_attached() && client->conn_state == GSM_MQTT_CONN_DISCONNECTED) { +lwgsmr_t +lwgsm_mqtt_client_connect(lwgsm_mqtt_client_p client, const char* host, lwgsm_port_t port, + lwgsm_mqtt_evt_fn evt_fn, const lwgsm_mqtt_client_info_t* info) { + lwgsmr_t res = lwgsmERR; + + LWGSM_ASSERT("client != NULL", client != NULL); /* t input parameters */ + LWGSM_ASSERT("host != NULL", host != NULL); + LWGSM_ASSERT("port > 0", port > 0); + LWGSM_ASSERT("info != NULL", info != NULL); + + lwgsm_core_lock(); + if (lwgsm_network_is_attached() && client->conn_state == LWGSM_MQTT_CONN_DISCONNECTED) { client->info = info; /* Save client info parameters */ client->evt_fn = evt_fn != NULL ? evt_fn : mqtt_evt_fn_default; /* Start a new connection in non-blocking mode */ - res = gsm_conn_start(&client->conn, GSM_CONN_TYPE_TCP, host, port, client, mqtt_conn_cb, 0); - if (res == gsmOK) { - client->conn_state = GSM_MQTT_CONN_CONNECTING; + res = lwgsm_conn_start(&client->conn, LWGSM_CONN_TYPE_TCP, host, port, client, mqtt_conn_cb, 0); + if (res == lwgsmOK) { + client->conn_state = LWGSM_MQTT_CONN_CONNECTING; } } - gsm_core_unlock(); + lwgsm_core_unlock(); return res; } @@ -1150,18 +1168,18 @@ gsm_mqtt_client_connect(gsm_mqtt_client_p client, const char* host, gsm_port_t p /** * \brief Disconnect from MQTT server * \param[in] client: MQTT client - * \return \ref gsmOK if request sent to queue or member of \ref gsmr_t otherwise + * \return \ref lwgsmOK if request sent to queue or member of \ref lwgsmr_t otherwise */ -gsmr_t -gsm_mqtt_client_disconnect(gsm_mqtt_client_p client) { - gsmr_t res = gsmERR; +lwgsmr_t +lwgsm_mqtt_client_disconnect(lwgsm_mqtt_client_p client) { + lwgsmr_t res = lwgsmERR; - gsm_core_lock(); - if (client->conn_state != GSM_MQTT_CONN_DISCONNECTED - && client->conn_state != GSM_MQTT_CONN_DISCONNECTING) { + lwgsm_core_lock(); + if (client->conn_state != LWGSM_MQTT_CONN_DISCONNECTED + && client->conn_state != LWGSM_MQTT_CONN_DISCONNECTING) { res = mqtt_close(client); /* Close client connection */ } - gsm_core_unlock(); + lwgsm_core_unlock(); return res; } @@ -1169,13 +1187,13 @@ gsm_mqtt_client_disconnect(gsm_mqtt_client_p client) { * \brief Subscribe to MQTT topic * \param[in] client: MQTT client * \param[in] topic: Topic name to subscribe to - * \param[in] qos: Quality of service. This parameter can be a value of \ref gsm_mqtt_qos_t + * \param[in] qos: Quality of service. This parameter can be a value of \ref lwgsm_mqtt_qos_t * \param[in] arg: User custom argument used in callback - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_mqtt_client_subscribe(gsm_mqtt_client_p client, const char* topic, gsm_mqtt_qos_t qos, void* arg) { - return sub_unsub(client, topic, qos, arg, 1) == 1 ? gsmOK : gsmERR; /* Subscribe to topic */ +lwgsmr_t +lwgsm_mqtt_client_subscribe(lwgsm_mqtt_client_p client, const char* topic, lwgsm_mqtt_qos_t qos, void* arg) { + return sub_unsub(client, topic, qos, arg, 1) == 1 ? lwgsmOK : lwgsmERR; /* Subscribe to topic */ } /** @@ -1183,11 +1201,11 @@ gsm_mqtt_client_subscribe(gsm_mqtt_client_p client, const char* topic, gsm_mqtt_ * \param[in] client: MQTT client * \param[in] topic: Topic name to unsubscribe from * \param[in] arg: User custom argument used in callback - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_mqtt_client_unsubscribe(gsm_mqtt_client_p client, const char* topic, void* arg) { - return sub_unsub(client, topic, (gsm_mqtt_qos_t)0, arg, 0) == 1 ? gsmOK : gsmERR; /* Unsubscribe from topic */ +lwgsmr_t +lwgsm_mqtt_client_unsubscribe(lwgsm_mqtt_client_p client, const char* topic, void* arg) { + return sub_unsub(client, topic, (lwgsm_mqtt_qos_t)0, arg, 0) == 1 ? lwgsmOK : lwgsmERR; /* Unsubscribe from topic */ } /** @@ -1196,22 +1214,22 @@ gsm_mqtt_client_unsubscribe(gsm_mqtt_client_p client, const char* topic, void* a * \param[in] topic: Topic to send message to * \param[in] payload: Message data * \param[in] payload_len: Length of payload data - * \param[in] qos: Quality of service. This parameter can be a value of \ref gsm_mqtt_qos_t enumeration + * \param[in] qos: Quality of service. This parameter can be a value of \ref lwgsm_mqtt_qos_t enumeration * \param[in] retain: Retian parameter value * \param[in] arg: User custom argument used in callback - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_mqtt_client_publish(gsm_mqtt_client_p client, const char* topic, const void* payload, - uint16_t payload_len, gsm_mqtt_qos_t qos, uint8_t retain, void* arg) { - gsmr_t res = gsmOK; - gsm_mqtt_request_t* request = NULL; +lwgsmr_t +lwgsm_mqtt_client_publish(lwgsm_mqtt_client_p client, const char* topic, const void* payload, + uint16_t payload_len, lwgsm_mqtt_qos_t qos, uint8_t retain, void* arg) { + lwgsmr_t res = lwgsmOK; + lwgsm_mqtt_request_t* request = NULL; uint32_t rem_len, raw_len; uint16_t len_topic, pkt_id; - uint8_t qos_u8 = GSM_U8(qos); + uint8_t qos_u8 = LWGSM_U8(qos); - if (!(len_topic = GSM_U16(strlen(topic)))) { /* Get length of topic */ - return gsmERR; + if (!(len_topic = LWGSM_U16(strlen(topic)))) { /* Get length of topic */ + return lwgsmERR; } /* @@ -1224,9 +1242,9 @@ gsm_mqtt_client_publish(gsm_mqtt_client_p client, const char* topic, const void* rem_len += 2; } - gsm_core_lock(); - if (client->conn_state != GSM_MQTT_CONNECTED) { - res = gsmCLOSED; + lwgsm_core_lock(); + if (client->conn_state != LWGSM_MQTT_CONNECTED) { + res = lwgsmCLOSED; } else if ((raw_len = output_check_enough_memory(client, rem_len)) != 0) { pkt_id = qos_u8 > 0 ? create_packet_id(client) : 0; /* Create new packet ID */ request = request_create(client, pkt_id, arg); /* Create request for packet */ @@ -1240,7 +1258,7 @@ gsm_mqtt_client_publish(gsm_mqtt_client_p client, const char* topic, const void* */ request->expected_sent_len = client->written_total + raw_len; - write_fixed_header(client, MQTT_MSG_TYPE_PUBLISH, 0, (gsm_mqtt_qos_t)GSM_MIN(qos_u8, GSM_U8(GSM_MQTT_QOS_EXACTLY_ONCE)), retain, rem_len); + write_fixed_header(client, MQTT_MSG_TYPE_PUBLISH, 0, (lwgsm_mqtt_qos_t)LWGSM_MIN(qos_u8, LWGSM_U8(LWGSM_MQTT_QOS_EXACTLY_ONCE)), retain, rem_len); write_string(client, topic, len_topic); /* Write topic string to packet */ if (qos_u8) { write_u16(client, pkt_id); /* Write packet ID */ @@ -1252,17 +1270,17 @@ gsm_mqtt_client_publish(gsm_mqtt_client_p client, const char* topic, const void* send_data(client); /* Try to send data */ - GSM_DEBUGF(GSM_CFG_DBG_MQTT_TRACE, - "[MQTT] Pkt publish start. QoS: %d, pkt_id: %d\r\n", (int)qos_u8, (int)pkt_id); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_TRACE, + "[MQTT] Pkt publish start. QoS: %d, pkt_id: %d\r\n", (int)qos_u8, (int)pkt_id); } else { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_TRACE, "[MQTT] No free request available to publish message\r\n"); - res = gsmERRMEM; + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_TRACE, "[MQTT] No free request available to publish message\r\n"); + res = lwgsmERRMEM; } } else { - GSM_DEBUGF(GSM_CFG_DBG_MQTT_TRACE, "[MQTT] Not enough memory to publish message\r\n"); - res = gsmERRMEM; + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_TRACE, "[MQTT] Not enough memory to publish message\r\n"); + res = lwgsmERRMEM; } - gsm_core_unlock(); + lwgsm_core_unlock(); return res; } @@ -1273,12 +1291,12 @@ gsm_mqtt_client_publish(gsm_mqtt_client_p client, const char* topic, const void* * \return `1` on success, `0` otherwise */ uint8_t -gsm_mqtt_client_is_connected(gsm_mqtt_client_p client) { +lwgsm_mqtt_client_is_connected(lwgsm_mqtt_client_p client) { uint8_t res; - gsm_core_lock(); - res = GSM_U8(client->conn_state == GSM_MQTT_CONNECTED); - gsm_core_unlock(); + lwgsm_core_lock(); + res = LWGSM_U8(client->conn_state == LWGSM_MQTT_CONNECTED); + lwgsm_core_unlock(); return res; } @@ -1289,10 +1307,10 @@ gsm_mqtt_client_is_connected(gsm_mqtt_client_p client) { * \param[in] arg: User argument */ void -gsm_mqtt_client_set_arg(gsm_mqtt_client_p client, void* arg) { - gsm_core_lock(); +lwgsm_mqtt_client_set_arg(lwgsm_mqtt_client_p client, void* arg) { + lwgsm_core_lock(); client->arg = arg; - gsm_core_unlock(); + lwgsm_core_unlock(); } /** @@ -1300,7 +1318,7 @@ gsm_mqtt_client_set_arg(gsm_mqtt_client_p client, void* arg) { * \param[in] client: MQTT client handle * \return User argument */ -void * -gsm_mqtt_client_get_arg(gsm_mqtt_client_p client) { +void* +lwgsm_mqtt_client_get_arg(lwgsm_mqtt_client_p client) { return client->arg; } diff --git a/lwgsm/src/apps/mqtt/lwgsm_mqtt_client_api.c b/lwgsm/src/apps/mqtt/lwgsm_mqtt_client_api.c new file mode 100644 index 00000000..9a8f739a --- /dev/null +++ b/lwgsm/src/apps/mqtt/lwgsm_mqtt_client_api.c @@ -0,0 +1,524 @@ +/** + * \file lwgsm_mqtt_client_api.c + * \brief MQTT client API + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#include "lwgsm/apps/lwgsm_mqtt_client_api.h" +#include "lwgsm/lwgsm_mem.h" + +/* Tracing debug message */ +#define LWGSM_CFG_DBG_MQTT_API_TRACE (LWGSM_CFG_DBG_MQTT_API | LWGSM_DBG_TYPE_TRACE) +#define LWGSM_CFG_DBG_MQTT_API_STATE (LWGSM_CFG_DBG_MQTT_API | LWGSM_DBG_TYPE_STATE) +#define LWGSM_CFG_DBG_MQTT_API_TRACE_WARNING (LWGSM_CFG_DBG_MQTT_API | LWGSM_DBG_TYPE_TRACE | LWGSM_DBG_LVL_WARNING) +#define LWGSM_CFG_DBG_MQTT_API_TRACE_SEVERE (LWGSM_CFG_DBG_MQTT_API | LWGSM_DBG_TYPE_TRACE | LWGSM_DBG_LVL_SEVERE) + +/** + * \brief MQTT API client structure + */ +struct lwgsm_mqtt_client_api { + lwgsm_mqtt_client_p mc; /*!< MQTT client handle */ + lwgsm_sys_mbox_t rcv_mbox; /*!< Received data mbox */ + lwgsm_sys_sem_t sync_sem; /*!< Synchronization semaphore */ + lwgsm_sys_mutex_t mutex; /*!< Mutex handle */ + uint8_t release_sem; /*!< Set to `1` to release semaphore */ + lwgsm_mqtt_conn_status_t connect_resp; /*!< Response when connecting to server */ + lwgsmr_t sub_pub_resp; /*!< Subscribe/Unsubscribe/Publish response */ +} lwgsm_mqtt_client_api_t; + +/** + * \brief Variable used as pointer for message queue when MQTT connection is closed + */ +static uint8_t +mqtt_closed = 0xFF; + +/** + * \brief Release user semaphore + * \param[in] client: Client handle + */ +static void +release_sem(lwgsm_mqtt_client_api_p client) { + if (client->release_sem) { + client->release_sem = 0; + lwgsm_sys_sem_release(&client->sync_sem); + } +} + +/** + * \brief MQTT event callback function + */ +static void +mqtt_evt(lwgsm_mqtt_client_p client, lwgsm_mqtt_evt_t* evt) { + lwgsm_mqtt_client_api_p api_client = lwgsm_mqtt_client_get_arg(client); + if (api_client == NULL) { + return; + } + switch (lwgsm_mqtt_client_evt_get_type(client, evt)) { + case LWGSM_MQTT_EVT_CONNECT: { + lwgsm_mqtt_conn_status_t status = lwgsm_mqtt_client_evt_connect_get_status(client, evt); + + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API_TRACE, + "[MQTT API] Connect event with status: %d\r\n", (int)status); + + api_client->connect_resp = status; + + /* + * By MQTT 3.1.1 specification, broker must close connection + * if client CONNECT packet was not accepted. + * + * If client is accepted or connection did not even start, + * release semaphore, otherwise wait CLOSED event + * and release semaphore from there, + * to make sure we are fully ready for next connection + */ + if (status == LWGSM_MQTT_CONN_STATUS_TCP_FAILED + || status == LWGSM_MQTT_CONN_STATUS_ACCEPTED) { + release_sem(api_client); /* Release semaphore */ + } + + break; + } + case LWGSM_MQTT_EVT_PUBLISH_RECV: { + /* Check valid receive mbox */ + if (lwgsm_sys_mbox_isvalid(&api_client->rcv_mbox)) { + lwgsm_mqtt_client_api_buf_p buf; + size_t size, buf_size, topic_size, payload_size; + + /* Get event data */ + const char* topic = lwgsm_mqtt_client_evt_publish_recv_get_topic(client, evt); + size_t topic_len = lwgsm_mqtt_client_evt_publish_recv_get_topic_len(client, evt); + const uint8_t* payload = lwgsm_mqtt_client_evt_publish_recv_get_payload(client, evt); + size_t payload_len = lwgsm_mqtt_client_evt_publish_recv_get_payload_len(client, evt); + lwgsm_mqtt_qos_t qos = lwgsm_mqtt_client_evt_publish_recv_get_qos(client, evt); + + /* Print debug message */ + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API_TRACE, + "[MQTT API] New publish received on topic %.*s\r\n", (int)topic_len, topic); + + /* Calculate memory sizes */ + buf_size = LWGSM_MEM_ALIGN(sizeof(*buf)); + topic_size = LWGSM_MEM_ALIGN(sizeof(*topic) * (topic_len + 1)); + payload_size = LWGSM_MEM_ALIGN(sizeof(*payload) * (payload_len + 1)); + + size = buf_size + topic_size + payload_size; + buf = lwgsm_mem_malloc(size); + if (buf != NULL) { + LWGSM_MEMSET(buf, 0x00, size); + buf->topic = (void*)((uint8_t*)buf + buf_size); + buf->payload = (void*)((uint8_t*)buf + buf_size + topic_size); + buf->topic_len = topic_len; + buf->payload_len = payload_len; + buf->qos = qos; + + /* Copy content to new memory */ + LWGSM_MEMCPY(buf->topic, topic, sizeof(*topic) * topic_len); + LWGSM_MEMCPY(buf->payload, payload, sizeof(*payload) * payload_len); + + /* Write to receive queue */ + if (!lwgsm_sys_mbox_putnow(&api_client->rcv_mbox, buf)) { + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API_TRACE_WARNING, + "[MQTT API] Cannot put new received MQTT publish to queue\r\n"); + lwgsm_mem_free_s((void**)&buf); + } + } else { + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API_TRACE_WARNING, + "[MQTT API] Cannot allocate memory for packet buffer of size %d bytes\r\n", + (int)size); + } + } + break; + } + case LWGSM_MQTT_EVT_PUBLISH: { + api_client->sub_pub_resp = lwgsm_mqtt_client_evt_publish_get_result(client, evt); + + /* Print debug message */ + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API_TRACE, + "[MQTT API] Publish event with response: %d\r\n", + (int)api_client->sub_pub_resp); + + release_sem(api_client); /* Release semaphore */ + break; + } + case LWGSM_MQTT_EVT_SUBSCRIBE: { + api_client->sub_pub_resp = lwgsm_mqtt_client_evt_subscribe_get_result(client, evt); + + /* Print debug message */ + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API_TRACE, + "[MQTT API] Subscribe event with response: %d\r\n", + (int)api_client->sub_pub_resp); + + release_sem(api_client); /* Release semaphore */ + break; + } + case LWGSM_MQTT_EVT_UNSUBSCRIBE: { + api_client->sub_pub_resp = lwgsm_mqtt_client_evt_unsubscribe_get_result(client, evt); + + /* Print debug message */ + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API_TRACE, + "[MQTT API] Unsubscribe event with response: %d\r\n", + (int)api_client->sub_pub_resp); + + release_sem(api_client); /* Release semaphore */ + break; + } + case LWGSM_MQTT_EVT_DISCONNECT: { + uint8_t is_accepted = lwgsm_mqtt_client_evt_disconnect_is_accepted(client, evt); + /* Disconnect event happened */ + //api_client->connect_resp = MQTT_CONN_STATUS_TCP_FAILED; + + /* Print debug message */ + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API_TRACE, + "[MQTT API] Disconnect event\r\n"); + + /* Write to receive mbox to wakeup receive thread */ + if (is_accepted && lwgsm_sys_mbox_isvalid(&api_client->rcv_mbox)) { + lwgsm_sys_mbox_putnow(&api_client->rcv_mbox, &mqtt_closed); + } + + release_sem(api_client); /* Release semaphore */ + break; + } + default: + break; + } +} + +/** + * \brief Create new MQTT client API + * \param[in] tx_buff_len: Maximal TX buffer for maximal packet length + * \param[in] rx_buff_len: Maximal RX buffer + * \return Client handle on success, `NULL` otherwise + */ +lwgsm_mqtt_client_api_p +lwgsm_mqtt_client_api_new(size_t tx_buff_len, size_t rx_buff_len) { + lwgsm_mqtt_client_api_p client; + size_t size; + + size = LWGSM_MEM_ALIGN(sizeof(*client)); /* Get size of client itself */ + + /* Create client APi structure */ + client = lwgsm_mem_calloc(1, size); /* Allocate client memory */ + if (client != NULL) { + /* Create MQTT raw client structure */ + client->mc = lwgsm_mqtt_client_new(tx_buff_len, rx_buff_len); + if (client->mc != NULL) { + /* Create receive mbox queue */ + if (lwgsm_sys_mbox_create(&client->rcv_mbox, 5)) { + /* Create synchronization semaphore */ + if (lwgsm_sys_sem_create(&client->sync_sem, 1)) { + /* Create mutex */ + if (lwgsm_sys_mutex_create(&client->mutex)) { + lwgsm_mqtt_client_set_arg(client->mc, client); /* Set client to mqtt client argument */ + return client; + } else { + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API, + "[MQTT API] Cannot allocate mutex\r\n"); + } + } else { + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API, + "[MQTT API] Cannot allocate sync semaphore\r\n"); + } + } else { + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API, + "[MQTT API] Cannot allocate receive queue\r\n"); + } + } else { + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API, + "[MQTT API] Cannot allocate MQTT client\r\n"); + } + } else { + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API, + "[MQTT API] Cannot allocate memory for client\r\n"); + } + + lwgsm_mqtt_client_api_delete(client); + client = NULL; + return NULL; +} + +/** + * \brief Delete client from memory + * \param[in] client: MQTT API client handle + */ +void +lwgsm_mqtt_client_api_delete(lwgsm_mqtt_client_api_p client) { + if (client == NULL) { + return; + } + if (lwgsm_sys_sem_isvalid(&client->sync_sem)) { + lwgsm_sys_sem_delete(&client->sync_sem); + lwgsm_sys_sem_invalid(&client->sync_sem); + } + if (lwgsm_sys_mutex_isvalid(&client->mutex)) { + lwgsm_sys_mutex_delete(&client->mutex); + lwgsm_sys_mutex_invalid(&client->mutex); + } + if (lwgsm_sys_mbox_isvalid(&client->rcv_mbox)) { + void* d; + while (lwgsm_sys_mbox_getnow(&client->rcv_mbox, &d)) { + if ((uint8_t*)d != (uint8_t*)&mqtt_closed) { + lwgsm_mqtt_client_api_buf_free(d); + } + } + lwgsm_sys_mbox_delete(&client->rcv_mbox); + lwgsm_sys_mbox_invalid(&client->rcv_mbox); + } + if (client->mc != NULL) { + lwgsm_mqtt_client_delete(client->mc); + client->mc = NULL; + } + lwgsm_mem_free_s((void**)&client); +} + +/** + * \brief Connect to MQTT broker + * \param[in] client: MQTT API client handle + * \param[in] host: TCP host + * \param[in] port: TCP port + * \param[in] info: MQTT client info + * \return \ref LWGSM_MQTT_CONN_STATUS_ACCEPTED on success, member of \ref lwgsm_mqtt_conn_status_t otherwise + */ +lwgsm_mqtt_conn_status_t +lwgsm_mqtt_client_api_connect(lwgsm_mqtt_client_api_p client, const char* host, + lwgsm_port_t port, const lwgsm_mqtt_client_info_t* info) { + if (client == NULL || host == NULL + || !port || info == NULL) { + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API_TRACE_WARNING, + "[MQTT API] Invalid parameters in function\r\n"); + return LWGSM_MQTT_CONN_STATUS_TCP_FAILED; + } + + lwgsm_sys_mutex_lock(&client->mutex); + client->connect_resp = LWGSM_MQTT_CONN_STATUS_TCP_FAILED; + lwgsm_sys_sem_wait(&client->sync_sem, 0); + client->release_sem = 1; + if (lwgsm_mqtt_client_connect(client->mc, host, port, mqtt_evt, info) == lwgsmOK) { + lwgsm_sys_sem_wait(&client->sync_sem, 0); + } else { + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API_TRACE_WARNING, + "[MQTT API] Cannot connect to %s\r\n", host); + } + client->release_sem = 0; + lwgsm_sys_sem_release(&client->sync_sem); + lwgsm_sys_mutex_unlock(&client->mutex); + return client->connect_resp; +} + +/** + * \brief Close MQTT connection + * \param[in] client: MQTT API client handle + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_mqtt_client_api_close(lwgsm_mqtt_client_api_p client) { + lwgsmr_t res = lwgsmERR; + + LWGSM_ASSERT("client != NULL", client != NULL); + + lwgsm_sys_mutex_lock(&client->mutex); + lwgsm_sys_sem_wait(&client->sync_sem, 0); + client->release_sem = 1; + if (lwgsm_mqtt_client_disconnect(client->mc) == lwgsmOK) { + res = lwgsmOK; + lwgsm_sys_sem_wait(&client->sync_sem, 0); + } else { + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API_TRACE_WARNING, + "[MQTT API] Cannot close API connection\r\n"); + } + client->release_sem = 0; + lwgsm_sys_sem_release(&client->sync_sem); + lwgsm_sys_mutex_unlock(&client->mutex); + return res; +} + +/** + * \brief Subscribe to topic + * \param[in] client: MQTT API client handle + * \param[in] topic: Topic to subscribe on + * \param[in] qos: Quality of service. This parameter can be a value of \ref lwgsm_mqtt_qos_t + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_mqtt_client_api_subscribe(lwgsm_mqtt_client_api_p client, const char* topic, + lwgsm_mqtt_qos_t qos) { + lwgsmr_t res = lwgsmERR; + + LWGSM_ASSERT("client != NULL", client != NULL); + LWGSM_ASSERT("topic != NULL", topic != NULL); + + lwgsm_sys_mutex_lock(&client->mutex); + lwgsm_sys_sem_wait(&client->sync_sem, 0); + client->release_sem = 1; + if (lwgsm_mqtt_client_subscribe(client->mc, topic, qos, NULL) == lwgsmOK) { + lwgsm_sys_sem_wait(&client->sync_sem, 0); + res = client->sub_pub_resp; + } else { + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API_TRACE_WARNING, + "[MQTT API] Cannot subscribe to topic %s\r\n", topic); + } + client->release_sem = 0; + lwgsm_sys_sem_release(&client->sync_sem); + lwgsm_sys_mutex_unlock(&client->mutex); + + return res; +} + +/** + * \brief Unsubscribe from topic + * \param[in] client: MQTT API client handle + * \param[in] topic: Topic to unsubscribe from + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_mqtt_client_api_unsubscribe(lwgsm_mqtt_client_api_p client, const char* topic) { + lwgsmr_t res = lwgsmERR; + + LWGSM_ASSERT("client != NULL", client != NULL); + LWGSM_ASSERT("topic != NULL", topic != NULL); + + lwgsm_sys_mutex_lock(&client->mutex); + lwgsm_sys_sem_wait(&client->sync_sem, 0); + client->release_sem = 1; + if (lwgsm_mqtt_client_unsubscribe(client->mc, topic, NULL) == lwgsmOK) { + lwgsm_sys_sem_wait(&client->sync_sem, 0); + res = client->sub_pub_resp; + } else { + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API_TRACE_WARNING, + "[MQTT API] Cannot unsubscribe from topic %s\r\n", topic); + } + client->release_sem = 0; + lwgsm_sys_sem_release(&client->sync_sem); + lwgsm_sys_mutex_unlock(&client->mutex); + + return res; +} + +/** + * \brief Publish new packet to MQTT network + * \param[in] client: MQTT API client handle + * \param[in] topic: Topic to publish on + * \param[in] data: Data to send + * \param[in] btw: Number of bytes to send for data parameter + * \param[in] qos: Quality of service. This parameter can be a value of \ref lwgsm_mqtt_qos_t + * \param[in] retain: Set to `1` for retain flag, `0` otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_mqtt_client_api_publish(lwgsm_mqtt_client_api_p client, const char* topic, const void* data, + size_t btw, lwgsm_mqtt_qos_t qos, uint8_t retain) { + lwgsmr_t res = lwgsmERR; + + LWGSM_ASSERT("client != NULL", client != NULL); + LWGSM_ASSERT("topic != NULL", topic != NULL); + LWGSM_ASSERT("data != NULL", data != NULL); + LWGSM_ASSERT("btw > 0", btw > 0); + + lwgsm_sys_mutex_lock(&client->mutex); + lwgsm_sys_sem_wait(&client->sync_sem, 0); + client->release_sem = 1; + if (lwgsm_mqtt_client_publish(client->mc, topic, data, LWGSM_U16(btw), qos, retain, NULL) == lwgsmOK) { + lwgsm_sys_sem_wait(&client->sync_sem, 0); + res = client->sub_pub_resp; + } else { + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API_TRACE_WARNING, + "[MQTT API] Cannot publish new packet\r\n"); + } + client->release_sem = 0; + lwgsm_sys_sem_release(&client->sync_sem); + lwgsm_sys_mutex_unlock(&client->mutex); + + return res; +} + +/** + * \brief Check if client MQTT connection is active + * \param[in] client: MQTT API client handle + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_mqtt_client_api_is_connected(lwgsm_mqtt_client_api_p client) { + uint8_t ret; + + if (client == NULL) { + return 0; + } + + lwgsm_sys_mutex_lock(&client->mutex); + ret = lwgsm_mqtt_client_is_connected(client->mc); + lwgsm_sys_mutex_unlock(&client->mutex); + return ret; +} + +/** + * \brief Receive next packet in specific timeout time + * \note This function can be called from separate thread + * than the rest of API function, which allows you to + * handle receive data separated with custom timeout + * \param[in] client: MQTT API client handle + * \param[in] p: Pointer to output buffer + * \param[in] timeout: Maximal time to wait before function returns timeout + * \return \ref lwgsmOK on success, \ref lwgsmCLOSED if MQTT is closed, \ref lwgsmTIMEOUT on timeout + */ +lwgsmr_t +lwgsm_mqtt_client_api_receive(lwgsm_mqtt_client_api_p client, lwgsm_mqtt_client_api_buf_p* p, + uint32_t timeout) { + LWGSM_ASSERT("client != NULL", client != NULL); + LWGSM_ASSERT("p != NULL", p != NULL); + + *p = NULL; + + /* Get new entry from mbox */ + if (timeout == 0) { + if (!lwgsm_sys_mbox_getnow(&client->rcv_mbox, (void**)p)) { + return lwgsmTIMEOUT; + } + } else if (lwgsm_sys_mbox_get(&client->rcv_mbox, (void**)p, timeout) == LWGSM_SYS_TIMEOUT) { + return lwgsmTIMEOUT; + } + + /* Check for MQTT closed event */ + if ((uint8_t*)(*p) == (uint8_t*)&mqtt_closed) { + LWGSM_DEBUGF(LWGSM_CFG_DBG_MQTT_API_TRACE, + "[MQTT API] Closed event received from queue\r\n"); + + *p = NULL; + return lwgsmCLOSED; + } + return lwgsmOK; +} + +/** + * \brief Free buffer memory after usage + * \param[in] p: Buffer to free + */ +void +lwgsm_mqtt_client_api_buf_free(lwgsm_mqtt_client_api_buf_p p) { + lwgsm_mem_free_s((void**)&p); +} diff --git a/gsm_at_lib/src/apps/mqtt/gsm_mqtt_client_evt.c b/lwgsm/src/apps/mqtt/lwgsm_mqtt_client_evt.c similarity index 85% rename from gsm_at_lib/src/apps/mqtt/gsm_mqtt_client_evt.c rename to lwgsm/src/apps/mqtt/lwgsm_mqtt_client_evt.c index 5b48691d..824b23d5 100644 --- a/gsm_at_lib/src/apps/mqtt/gsm_mqtt_client_evt.c +++ b/lwgsm/src/apps/mqtt/lwgsm_mqtt_client_evt.c @@ -1,10 +1,10 @@ /** - * \file gsm_mqtt_client_evt.c + * \file lwgsm_mqtt_client_evt.c * \brief MQTT client event helper functions */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,10 +26,10 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/apps/gsm_mqtt_client_evt.h" +#include "lwgsm/apps/lwgsm_mqtt_client_evt.h" diff --git a/gsm_at_lib/src/include/gsm/apps/gsm_apps.h b/lwgsm/src/include/lwgsm/apps/lwgsm_apps.h similarity index 81% rename from gsm_at_lib/src/include/gsm/apps/gsm_apps.h rename to lwgsm/src/include/lwgsm/apps/lwgsm_apps.h index 7f00fb68..ce963a01 100644 --- a/gsm_at_lib/src/include/gsm/apps/gsm_apps.h +++ b/lwgsm/src/include/lwgsm/apps/lwgsm_apps.h @@ -1,10 +1,10 @@ /** - * \file gsm_apps.h + * \file lwgsm_apps.h * \brief Applications main header file */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,22 +26,22 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_APPS_H -#define GSM_HDR_APPS_H +#ifndef LWGSM_HDR_APPS_H +#define LWGSM_HDR_APPS_H + +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -#include "gsm/gsm.h" - /** - * \defgroup GSM_APPS Applications + * \defgroup LWGSM_APPS Applications * \brief Applications based on GSM stack * \{ */ @@ -51,7 +51,7 @@ extern "C" { */ #ifdef __cplusplus -}; +} #endif /* __cplusplus */ -#endif /* GSM_HDR_APPS_H */ +#endif /* LWGSM_HDR_APPS_H */ diff --git a/gsm_at_lib/src/include/gsm/apps/gsm_mqtt_client.h b/lwgsm/src/include/lwgsm/apps/lwgsm_mqtt_client.h similarity index 60% rename from gsm_at_lib/src/include/gsm/apps/gsm_mqtt_client.h rename to lwgsm/src/include/lwgsm/apps/lwgsm_mqtt_client.h index f7f1c7b6..8b12fbe3 100644 --- a/gsm_at_lib/src/include/gsm/apps/gsm_mqtt_client.h +++ b/lwgsm/src/include/lwgsm/apps/lwgsm_mqtt_client.h @@ -1,10 +1,10 @@ /** - * \file gsm_mqtt_client.h + * \file lwgsm_mqtt_client.h * \brief MQTT client */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,24 +26,24 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_APP_MQTT_CLIENT_H -#define GSM_HDR_APP_MQTT_CLIENT_H +#ifndef LWGSM_HDR_APP_MQTT_CLIENT_H +#define LWGSM_HDR_APP_MQTT_CLIENT_H + +#include "lwgsm/lwgsm.h" +#include "lwgsm/apps/lwgsm_mqtt_client_evt.h" #ifdef __cplusplus extern "C" { -#endif - -#include "gsm/gsm.h" -#include "gsm/apps/gsm_mqtt_client_evt.h" +#endif /* __cplusplus */ /** - * \ingroup GSM_APPS - * \defgroup GSM_APP_MQTT_CLIENT MQTT client + * \ingroup LWGSM_APPS + * \defgroup LWGSM_APP_MQTT_CLIENT MQTT client * \brief MQTT client * \{ */ @@ -52,28 +52,28 @@ extern "C" { * \brief Quality of service enumeration */ typedef enum { - GSM_MQTT_QOS_AT_MOST_ONCE = 0x00, /*!< Delivery is not guaranteed to arrive, but can arrive `up to 1 time` = non-critical packets where losses are allowed */ - GSM_MQTT_QOS_AT_LEAST_ONCE = 0x01, /*!< Delivery is quaranteed `at least once`, but it may be delivered multiple times with the same content */ - GSM_MQTT_QOS_EXACTLY_ONCE = 0x02, /*!< Delivery is quaranteed `exactly once` = very critical packets such as billing informations or similar */ -} gsm_mqtt_qos_t; + LWGSM_MQTT_QOS_AT_MOST_ONCE = 0x00, /*!< Delivery is not guaranteed to arrive, but can arrive `up to 1 time` = non-critical packets where losses are allowed */ + LWGSM_MQTT_QOS_AT_LEAST_ONCE = 0x01, /*!< Delivery is quaranteed `at least once`, but it may be delivered multiple times with the same content */ + LWGSM_MQTT_QOS_EXACTLY_ONCE = 0x02, /*!< Delivery is quaranteed `exactly once` = very critical packets such as billing informations or similar */ +} lwgsm_mqtt_qos_t; -struct gsm_mqtt_client; +struct lwgsm_mqtt_client; /** - * \brief Pointer to \ref gsm_mqtt_client_t structure + * \brief Pointer to \ref lwgsm_mqtt_client_t structure */ -typedef struct gsm_mqtt_client* gsm_mqtt_client_p; +typedef struct lwgsm_mqtt_client* lwgsm_mqtt_client_p; /** * \brief State of MQTT client */ typedef enum { - GSM_MQTT_CONN_DISCONNECTED = 0x00, /*!< Connection with server is not established */ - GSM_MQTT_CONN_CONNECTING, /*!< Client is connecting to server */ - GSM_MQTT_CONN_DISCONNECTING, /*!< Client connection is disconnecting from server */ - GSM_MQTT_CONNECTING, /*!< MQTT client is connecting... CONNECT command has been sent to server */ - GSM_MQTT_CONNECTED, /*!< MQTT is fully connected and ready to send data on topics */ -} gsm_mqtt_state_t; + LWGSM_MQTT_CONN_DISCONNECTED = 0x00, /*!< Connection with server is not established */ + LWGSM_MQTT_CONN_CONNECTING, /*!< Client is connecting to server */ + LWGSM_MQTT_CONN_DISCONNECTING, /*!< Client connection is disconnecting from server */ + LWGSM_MQTT_CONNECTING, /*!< MQTT client is connecting... CONNECT command has been sent to server */ + LWGSM_MQTT_CONNECTED, /*!< MQTT is fully connected and ready to send data on topics */ +} lwgsm_mqtt_state_t; /** * \brief MQTT client information structure @@ -89,8 +89,8 @@ typedef struct { const char* will_topic; /*!< Will topic */ const char* will_message; /*!< Will message */ - gsm_mqtt_qos_t will_qos; /*!< Will topic quality of service */ -} gsm_mqtt_client_info_t; + lwgsm_mqtt_qos_t will_qos; /*!< Will topic quality of service */ +} lwgsm_mqtt_client_info_t; /** * \brief MQTT request object @@ -104,56 +104,56 @@ typedef struct { on connection before we can say "packet was sent". */ uint32_t timeout_start_time; /*!< Timeout start time in units of milliseconds */ -} gsm_mqtt_request_t; +} lwgsm_mqtt_request_t; /** * \brief MQTT event types */ typedef enum { - GSM_MQTT_EVT_CONNECT, /*!< MQTT client connect event */ - GSM_MQTT_EVT_SUBSCRIBE, /*!< MQTT client subscribed to specific topic */ - GSM_MQTT_EVT_UNSUBSCRIBE, /*!< MQTT client unsubscribed from specific topic */ - GSM_MQTT_EVT_PUBLISH, /*!< MQTT client publish message to server event. - \note When publishing packet with quality of service \ref GSM_MQTT_QOS_AT_MOST_ONCE, + LWGSM_MQTT_EVT_CONNECT, /*!< MQTT client connect event */ + LWGSM_MQTT_EVT_SUBSCRIBE, /*!< MQTT client subscribed to specific topic */ + LWGSM_MQTT_EVT_UNSUBSCRIBE, /*!< MQTT client unsubscribed from specific topic */ + LWGSM_MQTT_EVT_PUBLISH, /*!< MQTT client publish message to server event. + \note When publishing packet with quality of service \ref LWGSM_MQTT_QOS_AT_MOST_ONCE, you may not receive event, even if packet was successfully sent, - thus do not rely on this event for packet with `qos = GSM_MQTT_QOS_AT_MOST_ONCE` */ - GSM_MQTT_EVT_PUBLISH_RECV, /*!< MQTT client received a publish message from server */ - GSM_MQTT_EVT_DISCONNECT, /*!< MQTT client disconnected from MQTT server */ - GSM_MQTT_EVT_KEEP_ALIVE, /*!< MQTT keep-alive sent to server and reply received */ -} gsm_mqtt_evt_type_t; + thus do not rely on this event for packet with `qos = LWGSM_MQTT_QOS_AT_MOST_ONCE` */ + LWGSM_MQTT_EVT_PUBLISH_RECV, /*!< MQTT client received a publish message from server */ + LWGSM_MQTT_EVT_DISCONNECT, /*!< MQTT client disconnected from MQTT server */ + LWGSM_MQTT_EVT_KEEP_ALIVE, /*!< MQTT keep-alive sent to server and reply received */ +} lwgsm_mqtt_evt_type_t; /** * \brief List of possible results from MQTT server when executing connect command */ typedef enum { - GSM_MQTT_CONN_STATUS_ACCEPTED = 0x00, /*!< Connection accepted and ready to use */ - GSM_MQTT_CONN_STATUS_REFUSED_PROTOCOL_VERSION = 0x01, /*!< Connection Refused, unacceptable protocol version */ - GSM_MQTT_CONN_STATUS_REFUSED_ID = 0x02, /*!< Connection refused, identifier rejected */ - GSM_MQTT_CONN_STATUS_REFUSED_SERVER = 0x03, /*!< Connection refused, server unavailable */ - GSM_MQTT_CONN_STATUS_REFUSED_USER_PASS = 0x04, /*!< Connection refused, bad user name or password */ - GSM_MQTT_CONN_STATUS_REFUSED_NOT_AUTHORIZED = 0x05, /*!< Connection refused, not authorized */ - GSM_MQTT_CONN_STATUS_TCP_FAILED = 0x100, /*!< TCP connection to server was not successful */ -} gsm_mqtt_conn_status_t; + LWGSM_MQTT_CONN_STATUS_ACCEPTED = 0x00, /*!< Connection accepted and ready to use */ + LWGSM_MQTT_CONN_STATUS_REFUSED_PROTOCOL_VERSION = 0x01, /*!< Connection Refused, unacceptable protocol version */ + LWGSM_MQTT_CONN_STATUS_REFUSED_ID = 0x02, /*!< Connection refused, identifier rejected */ + LWGSM_MQTT_CONN_STATUS_REFUSED_SERVER = 0x03, /*!< Connection refused, server unavailable */ + LWGSM_MQTT_CONN_STATUS_REFUSED_USER_PASS = 0x04, /*!< Connection refused, bad user name or password */ + LWGSM_MQTT_CONN_STATUS_REFUSED_NOT_AUTHORIZED = 0x05, /*!< Connection refused, not authorized */ + LWGSM_MQTT_CONN_STATUS_TCP_FAILED = 0x100,/*!< TCP connection to server was not successful */ +} lwgsm_mqtt_conn_status_t; /** * \brief MQTT event structure for callback function */ typedef struct { - gsm_mqtt_evt_type_t type; /*!< Event type */ + lwgsm_mqtt_evt_type_t type; /*!< Event type */ union { struct { - gsm_mqtt_conn_status_t status; /*!< Connection status with MQTT */ + lwgsm_mqtt_conn_status_t status; /*!< Connection status with MQTT */ } connect; /*!< Event for connecting to server */ struct { uint8_t is_accepted; /*!< Status if client was accepted to MQTT prior disconnect event */ } disconnect; /*!< Event for disconnecting from server */ struct { void* arg; /*!< User argument for callback function */ - gsmr_t res; /*!< Rgsmonse status */ + lwgsmr_t res; /*!< Response status */ } sub_unsub_scribed; /*!< Event for (un)subscribe to/from topics */ struct { void* arg; /*!< User argument for callback function */ - gsmr_t res; /*!< Rgsmonse status */ + lwgsmr_t res; /*!< Response status */ } publish; /*!< Published event */ struct { const uint8_t* topic; /*!< Pointer to topic identifier */ @@ -161,32 +161,32 @@ typedef struct { const void* payload; /*!< Topic payload */ size_t payload_len; /*!< Length of topic payload */ uint8_t dup; /*!< Duplicate flag if message was sent again */ - gsm_mqtt_qos_t qos; /*!< Received packet quality of service */ + lwgsm_mqtt_qos_t qos; /*!< Received packet quality of service */ } publish_recv; /*!< Publish received event */ } evt; /*!< Event data parameters */ -} gsm_mqtt_evt_t; +} lwgsm_mqtt_evt_t; /** * \brief MQTT event callback function * \param[in] client: MQTT client * \param[in] evt: MQTT event with type and related data */ -typedef void (*gsm_mqtt_evt_fn)(gsm_mqtt_client_p client, gsm_mqtt_evt_t* evt); +typedef void (*lwgsm_mqtt_evt_fn)(lwgsm_mqtt_client_p client, lwgsm_mqtt_evt_t* evt); -gsm_mqtt_client_p gsm_mqtt_client_new(size_t tx_buff_len, size_t rx_buff_len); -void gsm_mqtt_client_delete(gsm_mqtt_client_p client); +lwgsm_mqtt_client_p lwgsm_mqtt_client_new(size_t tx_buff_len, size_t rx_buff_len); +void lwgsm_mqtt_client_delete(lwgsm_mqtt_client_p client); -gsmr_t gsm_mqtt_client_connect(gsm_mqtt_client_p client, const char* host, gsm_port_t port, gsm_mqtt_evt_fn evt_fn, const gsm_mqtt_client_info_t* info); -gsmr_t gsm_mqtt_client_disconnect(gsm_mqtt_client_p client); -uint8_t gsm_mqtt_client_is_connected(gsm_mqtt_client_p client); +lwgsmr_t lwgsm_mqtt_client_connect(lwgsm_mqtt_client_p client, const char* host, lwgsm_port_t port, lwgsm_mqtt_evt_fn evt_fn, const lwgsm_mqtt_client_info_t* info); +lwgsmr_t lwgsm_mqtt_client_disconnect(lwgsm_mqtt_client_p client); +uint8_t lwgsm_mqtt_client_is_connected(lwgsm_mqtt_client_p client); -gsmr_t gsm_mqtt_client_subscribe(gsm_mqtt_client_p client, const char* topic, gsm_mqtt_qos_t qos, void* arg); -gsmr_t gsm_mqtt_client_unsubscribe(gsm_mqtt_client_p client, const char* topic, void* arg); +lwgsmr_t lwgsm_mqtt_client_subscribe(lwgsm_mqtt_client_p client, const char* topic, lwgsm_mqtt_qos_t qos, void* arg); +lwgsmr_t lwgsm_mqtt_client_unsubscribe(lwgsm_mqtt_client_p client, const char* topic, void* arg); -gsmr_t gsm_mqtt_client_publish(gsm_mqtt_client_p client, const char* topic, const void* payload, uint16_t len, gsm_mqtt_qos_t qos, uint8_t retain, void* arg); +lwgsmr_t lwgsm_mqtt_client_publish(lwgsm_mqtt_client_p client, const char* topic, const void* payload, uint16_t len, lwgsm_mqtt_qos_t qos, uint8_t retain, void* arg); -void* gsm_mqtt_client_get_arg(gsm_mqtt_client_p client); -void gsm_mqtt_client_set_arg(gsm_mqtt_client_p client, void* arg); +void* lwgsm_mqtt_client_get_arg(lwgsm_mqtt_client_p client); +void lwgsm_mqtt_client_set_arg(lwgsm_mqtt_client_p client, void* arg); /** * \} @@ -194,6 +194,6 @@ void gsm_mqtt_client_set_arg(gsm_mqtt_client_p client, void* arg) #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif /* GSM_HDR_APP_MQTT_CLIENT_H */ +#endif /* LWGSM_HDR_APP_MQTT_CLIENT_H */ diff --git a/lwgsm/src/include/lwgsm/apps/lwgsm_mqtt_client_api.h b/lwgsm/src/include/lwgsm/apps/lwgsm_mqtt_client_api.h new file mode 100644 index 00000000..7684c9ab --- /dev/null +++ b/lwgsm/src/include/lwgsm/apps/lwgsm_mqtt_client_api.h @@ -0,0 +1,96 @@ +/** + * \file lwgsm_mqtt_client_api.h + * \brief MQTT client API + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_APP_MQTT_CLIENT_API_H +#define LWGSM_HDR_APP_MQTT_CLIENT_API_H + +#include "lwgsm/lwgsm.h" +#include "lwgsm/apps/lwgsm_mqtt_client.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * \ingroup LWGSM_APPS + * \defgroup LWGSM_APP_MQTT_CLIENT_API MQTT client API + * \brief Sequential, single thread MQTT client API + * \{ + */ + +/** + * \brief MQTT API client structure + */ +struct lwgsm_mqtt_client_api; + +/** + * \brief MQTT API RX buffer + */ +typedef struct lwgsm_mqtt_client_api_buf { + char* topic; /*!< Topic data */ + size_t topic_len; /*!< Topic length */ + uint8_t* payload; /*!< Payload data */ + size_t payload_len; /*!< Payload length */ + lwgsm_mqtt_qos_t qos; /*!< Quality of service */ +} lwgsm_mqtt_client_api_buf_t; + +/** + * \brief Pointer to \ref lwgsm_mqtt_client_api structure + */ +typedef struct lwgsm_mqtt_client_api* lwgsm_mqtt_client_api_p; + +/** + * \brief Pointer to \ref lwgsm_mqtt_client_api_buf_t structure + */ +typedef struct lwgsm_mqtt_client_api_buf* lwgsm_mqtt_client_api_buf_p; + +lwgsm_mqtt_client_api_p lwgsm_mqtt_client_api_new(size_t tx_buff_len, size_t rx_buff_len); +void lwgsm_mqtt_client_api_delete(lwgsm_mqtt_client_api_p client); +lwgsm_mqtt_conn_status_t lwgsm_mqtt_client_api_connect(lwgsm_mqtt_client_api_p client, const char* host, lwgsm_port_t port, const lwgsm_mqtt_client_info_t* info); +lwgsmr_t lwgsm_mqtt_client_api_close(lwgsm_mqtt_client_api_p client); +lwgsmr_t lwgsm_mqtt_client_api_subscribe(lwgsm_mqtt_client_api_p client, const char* topic, lwgsm_mqtt_qos_t qos); +lwgsmr_t lwgsm_mqtt_client_api_unsubscribe(lwgsm_mqtt_client_api_p client, const char* topic); +lwgsmr_t lwgsm_mqtt_client_api_publish(lwgsm_mqtt_client_api_p client, const char* topic, const void* data, size_t btw, lwgsm_mqtt_qos_t qos, uint8_t retain); +uint8_t lwgsm_mqtt_client_api_is_connected(lwgsm_mqtt_client_api_p client); +lwgsmr_t lwgsm_mqtt_client_api_receive(lwgsm_mqtt_client_api_p client, lwgsm_mqtt_client_api_buf_p* p, uint32_t timeout); +void lwgsm_mqtt_client_api_buf_free(lwgsm_mqtt_client_api_buf_p p); + +/** + * \} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LWGSM_HDR_APP_MQTT_CLIENT_H */ diff --git a/gsm_at_lib/src/include/gsm/apps/gsm_mqtt_client_evt.h b/lwgsm/src/include/lwgsm/apps/lwgsm_mqtt_client_evt.h similarity index 52% rename from gsm_at_lib/src/include/gsm/apps/gsm_mqtt_client_evt.h rename to lwgsm/src/include/lwgsm/apps/lwgsm_mqtt_client_evt.h index 7f6316ce..6d137961 100644 --- a/gsm_at_lib/src/include/gsm/apps/gsm_mqtt_client_evt.h +++ b/lwgsm/src/include/lwgsm/apps/lwgsm_mqtt_client_evt.h @@ -1,10 +1,10 @@ /** - * \file gsm_mqtt_client_evt.h + * \file lwgsm_mqtt_client_evt.h * \brief MQTT client event helper functions */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,23 +26,23 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_APP_MQTT_CLIENT_EVT_H -#define GSM_HDR_APP_MQTT_CLIENT_EVT_H +#ifndef LWGSM_HDR_APP_MQTT_CLIENT_EVT_H +#define LWGSM_HDR_APP_MQTT_CLIENT_EVT_H + +#include "lwgsm/apps/lwgsm_mqtt_client.h" #ifdef __cplusplus extern "C" { -#endif - -#include "gsm/apps/gsm_mqtt_client.h" +#endif /* __cplusplus */ /** - * \ingroup GSM_APP_MQTT_CLIENT - * \defgroup GSM_APP_MQTT_CLIENT_EVT Event helper functions + * \ingroup LWGSM_APP_MQTT_CLIENT + * \defgroup LWGSM_APP_MQTT_CLIENT_EVT Event helper functions * \brief Event helper functions * \{ */ @@ -51,38 +51,38 @@ extern "C" { * \brief Get MQTT event type * \param[in] client: MQTT client * \param[in] evt: Event handle - * \return MQTT Event type, value of \ref gsm_mqtt_evt_type_t enumeration + * \return MQTT Event type, value of \ref lwgsm_mqtt_evt_type_t enumeration * \hideinitializer */ -#define gsm_mqtt_client_evt_get_type(client, evt) ((gsm_mqtt_evt_type_t)(evt)->type) +#define lwgsm_mqtt_client_evt_get_type(client, evt) ((lwgsm_mqtt_evt_type_t)(evt)->type) /** - * \anchor GSM_APP_MQTT_CLIENT_EVT_CONNECT + * \anchor LWGSM_APP_MQTT_CLIENT_EVT_CONNECT * \name Connect event * \{ * - * \note Use these functions on \ref GSM_MQTT_EVT_CONNECT event + * \note Use these functions on \ref LWGSM_MQTT_EVT_CONNECT event */ /** * \brief Get connection status * \param[in] client: MQTT client * \param[in] evt: Event handle - * \return Connection status. Member of \ref gsm_mqtt_conn_status_t + * \return Connection status. Member of \ref lwgsm_mqtt_conn_status_t * \hideinitializer */ -#define gsm_mqtt_client_evt_connect_get_status(client, evt) ((gsm_mqtt_conn_status_t)(evt)->evt.connect.status) +#define lwgsm_mqtt_client_evt_connect_get_status(client, evt) ((lwgsm_mqtt_conn_status_t)(evt)->evt.connect.status) /** * \} */ /** - * \anchor GSM_APP_MQTT_CLIENT_EVT_DISCONNECT + * \anchor LWGSM_APP_MQTT_CLIENT_EVT_DISCONNECT * \name Disconnect event * \{ * - * \note Use these functions on \ref GSM_MQTT_EVT_DISCONNECT event + * \note Use these functions on \ref LWGSM_MQTT_EVT_DISCONNECT event */ /** @@ -92,66 +92,66 @@ extern "C" { * \return `1` on success, `0` otherwise * \hideinitializer */ -#define gsm_mqtt_client_evt_disconnect_is_accepted(client, evt) ((gsm_mqtt_conn_status_t)(evt)->evt.disconnect.is_accepted) +#define lwgsm_mqtt_client_evt_disconnect_is_accepted(client, evt) ((lwgsm_mqtt_conn_status_t)(evt)->evt.disconnect.is_accepted) /** * \} */ /** - * \anchor GSM_APP_MQTT_CLIENT_EVT_SUB_UNSUB + * \anchor LWGSM_APP_MQTT_CLIENT_EVT_SUB_UNSUB * \name Subscribe/unsubscribe event * \{ * - * \note Use these functions on \ref GSM_MQTT_EVT_SUBSCRIBE or \ref GSM_MQTT_EVT_UNSUBSCRIBE events + * \note Use these functions on \ref LWGSM_MQTT_EVT_SUBSCRIBE or \ref LWGSM_MQTT_EVT_UNSUBSCRIBE events */ /** - * \brief Get user argument used on \ref gsm_mqtt_client_subscribe + * \brief Get user argument used on \ref lwgsm_mqtt_client_subscribe * \param[in] client: MQTT client * \param[in] evt: Event handle * \return User argument * \hideinitializer */ -#define gsm_mqtt_client_evt_subscribe_get_argument(client, evt) ((void *)(evt)->evt.sub_unsub_scribed.arg) +#define lwgsm_mqtt_client_evt_subscribe_get_argument(client, evt) ((void *)(evt)->evt.sub_unsub_scribed.arg) /** * \brief Get result of subscribe event * \param[in] client: MQTT client * \param[in] evt: Event handle - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise * \hideinitializer */ -#define gsm_mqtt_client_evt_subscribe_get_result(client, evt) ((gsmr_t)(evt)->evt.sub_unsub_scribed.res) +#define lwgsm_mqtt_client_evt_subscribe_get_result(client, evt) ((lwgsmr_t)(evt)->evt.sub_unsub_scribed.res) /** - * \brief Get user argument used on \ref gsm_mqtt_client_unsubscribe + * \brief Get user argument used on \ref lwgsm_mqtt_client_unsubscribe * \param[in] client: MQTT client * \param[in] evt: Event handle * \return User argument * \hideinitializer */ -#define gsm_mqtt_client_evt_unsubscribe_get_argument(client, evt) ((void *)(evt)->evt.sub_unsub_scribed.arg) +#define lwgsm_mqtt_client_evt_unsubscribe_get_argument(client, evt) ((void *)(evt)->evt.sub_unsub_scribed.arg) /** * \brief Get result of unsubscribe event * \param[in] client: MQTT client * \param[in] evt: Event handle - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise * \hideinitializer */ -#define gsm_mqtt_client_evt_unsubscribe_get_result(client, evt) ((gsmr_t)(evt)->evt.sub_unsub_scribed.res) +#define lwgsm_mqtt_client_evt_unsubscribe_get_result(client, evt) ((lwgsmr_t)(evt)->evt.sub_unsub_scribed.res) /** * \} */ /** - * \anchor GSM_APP_MQTT_CLIENT_EVT_PUBLISH_RECV + * \anchor LWGSM_APP_MQTT_CLIENT_EVT_PUBLISH_RECV * \name Publish receive event * \{ * - * \note Use these functions on \ref GSM_MQTT_EVT_PUBLISH_RECV event + * \note Use these functions on \ref LWGSM_MQTT_EVT_PUBLISH_RECV event */ /** @@ -161,7 +161,7 @@ extern "C" { * \return Topic name * \hideinitializer */ -#define gsm_mqtt_client_evt_publish_recv_get_topic(client, evt) ((const void *)(evt)->evt.publish_recv.topic) +#define lwgsm_mqtt_client_evt_publish_recv_get_topic(client, evt) ((const void *)(evt)->evt.publish_recv.topic) /** * \brief Get topic length from received publish packet @@ -170,7 +170,7 @@ extern "C" { * \return Topic length * \hideinitializer */ -#define gsm_mqtt_client_evt_publish_recv_get_topic_len(client, evt) (GSM_SZ((evt)->evt.publish_recv.topic_len)) +#define lwgsm_mqtt_client_evt_publish_recv_get_topic_len(client, evt) (LWGSM_SZ((evt)->evt.publish_recv.topic_len)) /** * \brief Get payload from received publish packet @@ -179,7 +179,7 @@ extern "C" { * \return Packet payload * \hideinitializer */ -#define gsm_mqtt_client_evt_publish_recv_get_payload(client, evt) ((const void *)(evt)->evt.publish_recv.payload) +#define lwgsm_mqtt_client_evt_publish_recv_get_payload(client, evt) ((const void *)(evt)->evt.publish_recv.payload) /** * \brief Get payload length from received publish packet @@ -188,7 +188,7 @@ extern "C" { * \return Payload length * \hideinitializer */ -#define gsm_mqtt_client_evt_publish_recv_get_payload_len(client, evt) (GSM_SZ((evt)->evt.publish_recv.payload_len)) +#define lwgsm_mqtt_client_evt_publish_recv_get_payload_len(client, evt) (LWGSM_SZ((evt)->evt.publish_recv.payload_len)) /** * \brief Check if packet is duplicated @@ -197,46 +197,46 @@ extern "C" { * \return `1` if duplicated, `0` otherwise * \hideinitializer */ -#define gsm_mqtt_client_evt_publish_recv_is_duplicate(client, evt) (GSM_U8((evt)->evt.publish_recv.dup)) +#define lwgsm_mqtt_client_evt_publish_recv_is_duplicate(client, evt) (LWGSM_U8((evt)->evt.publish_recv.dup)) /** * \brief Get received quality of service * \param[in] client: MQTT client * \param[in] evt: Event handle - * \return Member of \ref gsm_mqtt_qos_t enumeration + * \return Member of \ref lwgsm_mqtt_qos_t enumeration * \hideinitializer */ -#define gsm_mqtt_client_evt_publish_recv_get_qos(client, evt) ((evt)->evt.publish_recv.qos) +#define lwgsm_mqtt_client_evt_publish_recv_get_qos(client, evt) ((evt)->evt.publish_recv.qos) /** * \} */ /** - * \anchor GSM_APP_MQTT_CLIENT_EVT_PUBLISH + * \anchor LWGSM_APP_MQTT_CLIENT_EVT_PUBLISH * \name Publish event * \{ * - * \note Use these functions on \ref GSM_MQTT_EVT_PUBLISH event + * \note Use these functions on \ref LWGSM_MQTT_EVT_PUBLISH event */ /** - * \brief Get user argument used on \ref gsm_mqtt_client_publish + * \brief Get user argument used on \ref lwgsm_mqtt_client_publish * \param[in] client: MQTT client * \param[in] evt: Event handle * \return User argument * \hideinitializer */ -#define gsm_mqtt_client_evt_publish_get_argument(client, evt) ((void *)(evt)->evt.publish.arg) +#define lwgsm_mqtt_client_evt_publish_get_argument(client, evt) ((void *)(evt)->evt.publish.arg) - /** - * \brief Get result of publish event - * \param[in] client: MQTT client - * \param[in] evt: Event handle - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise - * \hideinitializer - */ -#define gsm_mqtt_client_evt_publish_get_result(client, evt) ((gsmr_t)(evt)->evt.publish.res) +/** +* \brief Get result of publish event +* \param[in] client: MQTT client +* \param[in] evt: Event handle +* \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise +* \hideinitializer +*/ +#define lwgsm_mqtt_client_evt_publish_get_result(client, evt) ((lwgsmr_t)(evt)->evt.publish.res) /** * \} @@ -248,6 +248,6 @@ extern "C" { #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif /* GSM_HDR_APP_MQTT_CLIENT_EVT_H */ +#endif /* LWGSM_HDR_APP_MQTT_CLIENT_EVT_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm.h b/lwgsm/src/include/lwgsm/lwgsm.h similarity index 53% rename from gsm_at_lib/src/include/gsm/gsm.h rename to lwgsm/src/include/lwgsm/lwgsm.h index fe3c225f..80775d6f 100644 --- a/gsm_at_lib/src/include/gsm/gsm.h +++ b/lwgsm/src/include/lwgsm/lwgsm.h @@ -1,10 +1,10 @@ /** - * \file gsm.h - * \brief GSM AT commands parser + * \file lwgsm.h + * \brief Lightweight GSM-AT library */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,40 +26,40 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_H -#define GSM_HDR_H +#ifndef LWGSM_HDR_H +#define LWGSM_HDR_H + +/* Get most important include files */ +#include "lwgsm/lwgsm_includes.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -/* Get most important include files */ -#include "gsm/gsm_includes.h" - /** - * \defgroup GSM GSM-AT Lib - * \brief GSM stack + * \defgroup LWGSM Lightweight GSM-AT parser library + * \brief Lightweight GSM-AT parser library * \{ */ -gsmr_t gsm_init(gsm_evt_fn evt_func, const uint32_t blocking); -gsmr_t gsm_reset(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_reset_with_delay(uint32_t delay, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_init(lwgsm_evt_fn evt_func, const uint32_t blocking); +lwgsmr_t lwgsm_reset(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_reset_with_delay(uint32_t delay, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_set_func_mode(uint8_t mode, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_set_func_mode(uint8_t mode, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_core_lock(void); -gsmr_t gsm_core_unlock(void); +lwgsmr_t lwgsm_core_lock(void); +lwgsmr_t lwgsm_core_unlock(void); -gsmr_t gsm_device_set_present(uint8_t present, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -uint8_t gsm_device_is_present(void); +lwgsmr_t lwgsm_device_set_present(uint8_t present, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +uint8_t lwgsm_device_is_present(void); -uint8_t gsm_delay(uint32_t ms); +uint8_t lwgsm_delay(uint32_t ms); /** * \} @@ -69,4 +69,4 @@ uint8_t gsm_delay(uint32_t ms); } #endif /* __cplusplus */ -#endif /* GSM_HDR_H */ +#endif /* LWGSM_HDR_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_buff.h b/lwgsm/src/include/lwgsm/lwgsm_buff.h similarity index 79% rename from gsm_at_lib/src/include/gsm/gsm_buff.h rename to lwgsm/src/include/lwgsm/lwgsm_buff.h index b746aadc..d67e2c94 100644 --- a/gsm_at_lib/src/include/gsm/gsm_buff.h +++ b/lwgsm/src/include/lwgsm/lwgsm_buff.h @@ -1,10 +1,10 @@ -/** - * \file gsm_buff.h +/** + * \file lwgsm_buff.h * \brief Ring buffer manager */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,23 +26,23 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_BUFF_H -#define GSM_HDR_BUFF_H +#ifndef LWGSM_HDR_BUFF_H +#define LWGSM_HDR_BUFF_H + +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { -#endif - -#include "gsm/gsm.h" +#endif /* __cplusplus */ /** - * \ingroup GSM - * \defgroup GSM_BUFF Ring buffer + * \ingroup LWGSM + * \defgroup LWGSM_BUFF Ring buffer * \brief Generic ring buffer * \{ */ @@ -50,13 +50,13 @@ extern "C" { /* --- Buffer unique part starts --- */ /** * \brief Buffer function/typedef prefix string - * + * * It is used to change function names in zero time to easily re-use same library between applications. - * Use `#define BUF_PREF(x) my_prefix_ ## x` to change all function names to (for example) `my_prefix_buff_init` + * Use `#define BUF_PREF(x) my_prefix_ ## x` to change all function names to (for example) `my_prefix_buff_init` * * \note Modification of this macro must be done in header and source file aswell */ -#define BUF_PREF(x) gsm_ ## x +#define BUF_PREF(x) lwgsm_ ## x /* --- Buffer unique part ends --- */ uint8_t BUF_PREF(buff_init)(BUF_PREF(buff_t)* buff, size_t size); @@ -73,16 +73,16 @@ size_t BUF_PREF(buff_get_free)(BUF_PREF(buff_t)* buff); size_t BUF_PREF(buff_get_full)(BUF_PREF(buff_t)* buff); /* Read data block management */ -void * BUF_PREF(buff_get_linear_block_read_address)(BUF_PREF(buff_t)* buff); +void* BUF_PREF(buff_get_linear_block_read_address)(BUF_PREF(buff_t)* buff); size_t BUF_PREF(buff_get_linear_block_read_length)(BUF_PREF(buff_t)* buff); size_t BUF_PREF(buff_skip)(BUF_PREF(buff_t)* buff, size_t len); /* Write data block management */ -void * BUF_PREF(buff_get_linear_block_write_address)(BUF_PREF(buff_t)* buff); +void* BUF_PREF(buff_get_linear_block_write_address)(BUF_PREF(buff_t)* buff); size_t BUF_PREF(buff_get_linear_block_write_length)(BUF_PREF(buff_t)* buff); size_t BUF_PREF(buff_advance)(BUF_PREF(buff_t)* buff, size_t len); -#undef BUF_PREF /* Prefix not needed anymore */ +#undef BUF_PREF /* Prefix not needed anymore */ /** * \} @@ -90,6 +90,6 @@ size_t BUF_PREF(buff_advance)(BUF_PREF(buff_t)* buff, size_t len); #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif /* GSM_HDR_BUFF_H */ +#endif /* LWGSM_HDR_BUFF_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_call.h b/lwgsm/src/include/lwgsm/lwgsm_call.h similarity index 57% rename from gsm_at_lib/src/include/gsm/gsm_call.h rename to lwgsm/src/include/lwgsm/lwgsm_call.h index 469c0a80..1dbb2ce7 100644 --- a/gsm_at_lib/src/include/gsm/gsm_call.h +++ b/lwgsm/src/include/lwgsm/lwgsm_call.h @@ -1,10 +1,10 @@ -/** - * \file gsm_call.h +/** + * \file lwgsm_call.h * \brief Call API */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,33 +26,33 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_CALL_H -#define GSM_HDR_CALL_H +#ifndef LWGSM_HDR_CALL_H +#define LWGSM_HDR_CALL_H + +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { -#endif - -#include "gsm/gsm.h" +#endif /* __cplusplus */ /** - * \ingroup GSM - * \defgroup GSM_CALL Call API + * \ingroup LWGSM + * \defgroup LWGSM_CALL Call API * \brief Call manager * \{ */ -gsmr_t gsm_call_enable(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_call_disable(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_call_enable(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_call_disable(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_call_start(const char* number, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_call_answer(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_call_hangup(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_call_start(const char* number, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_call_answer(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_call_hangup(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); /** * \} @@ -60,6 +60,6 @@ gsmr_t gsm_call_hangup(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif /* GSM_HDR_CALL_H */ +#endif /* LWGSM_HDR_CALL_H */ diff --git a/lwgsm/src/include/lwgsm/lwgsm_conn.h b/lwgsm/src/include/lwgsm/lwgsm_conn.h new file mode 100644 index 00000000..891bd3f8 --- /dev/null +++ b/lwgsm/src/include/lwgsm/lwgsm_conn.h @@ -0,0 +1,78 @@ +/** + * \file lwgsm_conn.h + * \brief Connection API + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_CONN_H +#define LWGSM_HDR_CONN_H + +#include "lwgsm/lwgsm.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * \ingroup LWGSM + * \defgroup LWGSM_CONN Connection API + * \brief Connection API functions + * \{ + */ + +lwgsmr_t lwgsm_conn_start(lwgsm_conn_p* conn, lwgsm_conn_type_t type, const char* const host, lwgsm_port_t port, void* const arg, lwgsm_evt_fn conn_evt_fn, const uint32_t blocking); +lwgsmr_t lwgsm_conn_close(lwgsm_conn_p conn, const uint32_t blocking); +lwgsmr_t lwgsm_conn_send(lwgsm_conn_p conn, const void* data, size_t btw, size_t* const bw, const uint32_t blocking); +lwgsmr_t lwgsm_conn_sendto(lwgsm_conn_p conn, const lwgsm_ip_t* const ip, lwgsm_port_t port, const void* data, size_t btw, size_t* bw, const uint32_t blocking); +lwgsmr_t lwgsm_conn_set_arg(lwgsm_conn_p conn, void* const arg); +void* lwgsm_conn_get_arg(lwgsm_conn_p conn); +uint8_t lwgsm_conn_is_client(lwgsm_conn_p conn); +uint8_t lwgsm_conn_is_active(lwgsm_conn_p conn); +uint8_t lwgsm_conn_is_closed(lwgsm_conn_p conn); +int8_t lwgsm_conn_getnum(lwgsm_conn_p conn); +lwgsmr_t lwgsm_get_conns_status(const uint32_t blocking); +lwgsm_conn_p lwgsm_conn_get_from_evt(lwgsm_evt_t* evt); +lwgsmr_t lwgsm_conn_write(lwgsm_conn_p conn, const void* data, size_t btw, uint8_t flush, size_t* const mem_available); +lwgsmr_t lwgsm_conn_recved(lwgsm_conn_p conn, lwgsm_pbuf_p pbuf); +size_t lwgsm_conn_get_total_recved_count(lwgsm_conn_p conn); + +uint8_t lwgsm_conn_get_remote_ip(lwgsm_conn_p conn, lwgsm_ip_t* ip); +lwgsm_port_t lwgsm_conn_get_remote_port(lwgsm_conn_p conn); +lwgsm_port_t lwgsm_conn_get_local_port(lwgsm_conn_p conn); + +/** + * \} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LWGSM_HDR_CONN_H */ diff --git a/lwgsm/src/include/lwgsm/lwgsm_debug.h b/lwgsm/src/include/lwgsm/lwgsm_debug.h new file mode 100644 index 00000000..23d47228 --- /dev/null +++ b/lwgsm/src/include/lwgsm/lwgsm_debug.h @@ -0,0 +1,130 @@ +/** + * \file lwgsm_debug.h + * \brief Debugging inside GSM stack + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_DEBUG_H +#define LWGSM_HDR_DEBUG_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * \ingroup LWGSM + * \defgroup LWGSM_DEBUG Debugging support + * \brief Debugging support module to track stack + * \{ + */ + +#define LWGSM_DBG_ON 0x80 /*!< Indicates debug is enabled */ +#define LWGSM_DBG_OFF 0 /*!< Indicates debug is disabled */ + +/** + * \anchor LWGSM_DBG_LVL + * \name Debug levels + * \brief List of debug levels + * \{ + */ + +#define LWGSM_DBG_LVL_ALL 0x00 /*!< Print all messages of all types */ +#define LWGSM_DBG_LVL_WARNING 0x01 /*!< Print warning and upper messages */ +#define LWGSM_DBG_LVL_DANGER 0x02 /*!< Print danger errors */ +#define LWGSM_DBG_LVL_SEVERE 0x03 /*!< Print severe problems affecting program flow */ +#define LWGSM_DBG_LVL_MASK 0x03 /*!< Mask for getting debug level */ + +/** + * \} + */ + +/** + * \anchor LWGSM_DBG_TYPE + * \name Debug types + * \brief List of possible debugging types + * \{ + */ + +#define LWGSM_DBG_TYPE_TRACE 0x40 /*!< Debug trace messages for program flow */ +#define LWGSM_DBG_TYPE_STATE 0x20 /*!< Debug state messages (such as state machines) */ +#define LWGSM_DBG_TYPE_ALL (LWGSM_DBG_TYPE_TRACE | LWGSM_DBG_TYPE_STATE) /*!< All debug types */ + +/** + * \} + */ + +#if LWGSM_CFG_DBG && !defined(LWGSM_CFG_DBG_OUT) +#warning "LWGSM_CFG_DBG_OUT is not defined but debugging is enabled!" +#endif + +#if (LWGSM_CFG_DBG && defined(LWGSM_CFG_DBG_OUT)) || __DOXYGEN__ +/** + * \brief Print message to the debug "window" if enabled + * \param[in] c: Condition if debug of specific type is enabled + * \param[in] fmt: Formatted string for debug + * \param[in] ...: Variable parameters for formatted string + */ +#define LWGSM_DEBUGF(c, fmt, ...) do {\ + if (((c) & (LWGSM_DBG_ON)) && ((c) & (LWGSM_CFG_DBG_TYPES_ON)) && ((c) & LWGSM_DBG_LVL_MASK) >= (LWGSM_CFG_DBG_LVL_MIN)) { \ + LWGSM_CFG_DBG_OUT(fmt, ## __VA_ARGS__); \ + } \ + } while (0) + +/** + * \brief Print message to the debug "window" if enabled when specific condition is met + * \param[in] c: Condition if debug of specific type is enabled + * \param[in] cond: Debug only if this condition is true + * \param[in] fmt: Formatted string for debug + * \param[in] ...: Variable parameters for formatted string + */ +#define LWGSM_DEBUGW(c, cond, fmt, ...) do {\ + if (cond) { \ + LWGSM_DEBUGF(c, fmt, ## __VA_ARGS__); \ + } \ + } while (0) +#else +#undef LWGSM_CFG_DBG +#define LWGSM_CFG_DBG LWGSM_DBG_OFF +#define LWGSM_DEBUGF(c, fmt, ...) +#define LWGSM_DEBUGW(c, cond, fmt, ...) +#endif /* (LWGSM_CFG_DBG && defined(LWGSM_CFG_DBG_OUT)) || __DOXYGEN__ */ + +/** + * \} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LWGSM_HDR_DEBUG_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_device_info.h b/lwgsm/src/include/lwgsm/lwgsm_device_info.h similarity index 57% rename from gsm_at_lib/src/include/gsm/gsm_device_info.h rename to lwgsm/src/include/lwgsm/lwgsm_device_info.h index 46d617ac..759fe60b 100644 --- a/gsm_at_lib/src/include/gsm/gsm_device_info.h +++ b/lwgsm/src/include/lwgsm/lwgsm_device_info.h @@ -1,10 +1,10 @@ -/** - * \file gsm_device_info.h +/** + * \file lwgsm_device_info.h * \brief Basic device information */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,31 +26,31 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_DEVICE_INFO_H -#define GSM_HDR_DEVICE_INFO_H +#ifndef LWGSM_HDR_DEVICE_INFO_H +#define LWGSM_HDR_DEVICE_INFO_H + +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { -#endif - -#include "gsm/gsm.h" +#endif /* __cplusplus */ /** - * \ingroup GSM - * \defgroup GSM_DEVICE_INFO Device information + * \ingroup LWGSM + * \defgroup LWGSM_DEVICE_INFO Device information * \brief Basic device information * \{ */ -gsmr_t gsm_device_get_manufacturer(char* manuf, size_t len, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_device_get_model(char* model, size_t len, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_device_get_revision(char* rev, size_t len, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_device_get_serial_number(char* serial, size_t len, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_device_get_manufacturer(char* manuf, size_t len, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_device_get_model(char* model, size_t len, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_device_get_revision(char* rev, size_t len, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_device_get_serial_number(char* serial, size_t len, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); /** * \} @@ -58,6 +58,6 @@ gsmr_t gsm_device_get_serial_number(char* serial, size_t len, const gsm_api #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif /* GSM_HDR_DEVICE_INFO_H */ +#endif /* LWGSM_HDR_DEVICE_INFO_H */ diff --git a/lwgsm/src/include/lwgsm/lwgsm_evt.h b/lwgsm/src/include/lwgsm/lwgsm_evt.h new file mode 100644 index 00000000..8d506824 --- /dev/null +++ b/lwgsm/src/include/lwgsm/lwgsm_evt.h @@ -0,0 +1,272 @@ +/** + * \file lwgsm_evt.h + * \brief Event helper functions + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_EVT_H +#define LWGSM_HDR_EVT_H + +#include "lwgsm/lwgsm.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * \ingroup LWGSM + * \defgroup LWGSM_EVT Events management + * \brief Event helper functions + * \{ + */ + +lwgsmr_t lwgsm_evt_register(lwgsm_evt_fn fn); +lwgsmr_t lwgsm_evt_unregister(lwgsm_evt_fn fn); +lwgsm_evt_type_t lwgsm_evt_get_type(lwgsm_evt_t* cc); + +/** + * \anchor LWGSM_EVT_RESET + * \name Reset event + * \brief Event helper functions for \ref LWGSM_EVT_RESET event + */ + +lwgsmr_t lwgsm_evt_reset_get_result(lwgsm_evt_t* cc); + +/** + * \} + */ + +/** + * \anchor LWGSM_EVT_RESTORE + * \name Restore event + * \brief Event helper functions for \ref LWGSM_EVT_RESTORE event + */ + +lwgsmr_t lwgsm_evt_restore_get_result(lwgsm_evt_t* cc); + +/** + * \} + */ + +/** + * \anchor LWGSM_EVT_NETWORK_OPERATOR_CURRENT + * \name Current network operator + * \brief Event helper functions for \ref LWGSM_EVT_NETWORK_OPERATOR_CURRENT event + */ + +const lwgsm_operator_curr_t* lwgsm_evt_network_operator_get_current(lwgsm_evt_t* cc); + +/** + * \} + */ + +/** + * \anchor LWGSM_EVT_CONN_RECV + * \name Connection data received + * \brief Event helper functions for \ref LWGSM_EVT_CONN_RECV event + */ + +lwgsm_pbuf_p lwgsm_evt_conn_recv_get_buff(lwgsm_evt_t* cc); +lwgsm_conn_p lwgsm_evt_conn_recv_get_conn(lwgsm_evt_t* cc); + +/** + * \} + */ + +/** + * \anchor LWGSM_EVT_CONN_SEND + * \name Connection data send + * \brief Event helper functions for \ref LWGSM_EVT_CONN_SEND event + */ + +lwgsm_conn_p lwgsm_evt_conn_send_get_conn(lwgsm_evt_t* cc); +size_t lwgsm_evt_conn_send_get_length(lwgsm_evt_t* cc); +lwgsmr_t lwgsm_evt_conn_send_get_result(lwgsm_evt_t* cc); + +/** + * \} + */ + +/** + * \anchor LWGSM_EVT_CONN_ACTIVE + * \name Connection active + * \brief Event helper functions for \ref LWGSM_EVT_CONN_ACTIVE event + */ + +lwgsm_conn_p lwgsm_evt_conn_active_get_conn(lwgsm_evt_t* cc); +uint8_t lwgsm_evt_conn_active_is_client(lwgsm_evt_t* cc); + +/** + * \} + */ + +/** + * \anchor LWGSM_EVT_CONN_CLOSE + * \name Connection close event + * \brief Event helper functions for \ref LWGSM_EVT_CONN_CLOSE event + */ + +lwgsm_conn_p lwgsm_evt_conn_close_get_conn(lwgsm_evt_t* cc); +uint8_t lwgsm_evt_conn_close_is_client(lwgsm_evt_t* cc); +uint8_t lwgsm_evt_conn_close_is_forced(lwgsm_evt_t* cc); +lwgsmr_t lwgsm_evt_conn_close_get_result(lwgsm_evt_t* cc); + +/** + * \} + */ + +/** + * \anchor LWGSM_EVT_CONN_POLL + * \name Connection poll + * \brief Event helper functions for \ref LWGSM_EVT_CONN_POLL event + */ + +lwgsm_conn_p lwgsm_evt_conn_poll_get_conn(lwgsm_evt_t* cc); + +/** + * \} + */ + +/** + * \anchor LWGSM_EVT_CONN_ERROR + * \name Connection error + * \brief Event helper functions for \ref LWGSM_EVT_CONN_ERROR event + */ + +lwgsmr_t lwgsm_evt_conn_error_get_error(lwgsm_evt_t* cc); +lwgsm_conn_type_t lwgsm_evt_conn_error_get_type(lwgsm_evt_t* cc); +const char* lwgsm_evt_conn_error_get_host(lwgsm_evt_t* cc); +lwgsm_port_t lwgsm_evt_conn_error_get_port(lwgsm_evt_t* cc); +void* lwgsm_evt_conn_error_get_arg(lwgsm_evt_t* cc); + +/** + * \} + */ + +/** + * \anchor LWGSM_EVT_SIGNAL_STRENGTH + * \name Signal strength + * \brief Event helper functions for \ref LWGSM_EVT_CONN_RECV event + */ + +int16_t lwgsm_evt_signal_strength_get_rssi(lwgsm_evt_t* cc); + +/** + * \} + */ + +/** + * \anchor LWGSM_EVT_SMS_RECV + * \name SMS received + * \brief Event helper functions for \ref LWGSM_EVT_SMS_RECV event + */ + +size_t lwgsm_evt_sms_recv_get_pos(lwgsm_evt_t* cc); +lwgsm_mem_t lwgsm_evt_sms_recv_get_mem(lwgsm_evt_t* cc); + +/** + * \} + */ + +/** + * \anchor LWGSM_EVT_SMS_READ + * \name SMS content read + * \brief Event helper functions for \ref LWGSM_EVT_SMS_READ event + */ + +lwgsm_sms_entry_t* lwgsm_evt_sms_read_get_entry(lwgsm_evt_t* cc); +lwgsmr_t lwgsm_evt_sms_read_get_result(lwgsm_evt_t* cc); + +/** + * \} + */ + +/** + * \anchor LWGSM_EVT_SMS_SEND + * \name SMS send + * \brief Event helper functions for \ref LWGSM_EVT_SMS_SEND event + */ + +lwgsmr_t lwgsm_evt_sms_send_get_result(lwgsm_evt_t* cc); +size_t lwgsm_evt_sms_send_get_pos(lwgsm_evt_t* cc); + +/** + * \} + */ + +/** + * \anchor LWGSM_EVT_SMS_DELETE + * \name SMS delete + * \brief Event helper functions for \ref LWGSM_EVT_SMS_DELETE event + */ + +lwgsmr_t lwgsm_evt_sms_delete_get_result(lwgsm_evt_t* cc); +size_t lwgsm_evt_sms_delete_get_pos(lwgsm_evt_t* cc); +lwgsm_mem_t lwgsm_evt_sms_delete_get_mem(lwgsm_evt_t* cc); + +/** + * \} + */ + +/** + * \anchor LWGSM_EVT_CALL_CHANGED + * \name Call status changed + * \brief Event helper functions for \ref LWGSM_EVT_CALL_CHANGED event + */ + +const lwgsm_call_t* lwgsm_evt_call_changed_get_call(lwgsm_evt_t* cc); + +/** + * \} + */ + +/** + * \anchor LWGSM_EVT_OPERATOR_SCAN + * \name Operator scan + * \brief Event helper functions for \ref LWGSM_EVT_OPERATOR_SCAN event + */ + +lwgsmr_t lwgsm_evt_operator_scan_get_result(lwgsm_evt_t* cc); +lwgsm_operator_t* lwgsm_evt_operator_scan_get_entries(lwgsm_evt_t* cc); +size_t lwgsm_evt_operator_scan_get_length(lwgsm_evt_t* cc); + +/** + * \} + */ + +/** + * \} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LWGSM_HDR_EVT_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_ftp.h b/lwgsm/src/include/lwgsm/lwgsm_ftp.h similarity index 77% rename from gsm_at_lib/src/include/gsm/gsm_ftp.h rename to lwgsm/src/include/lwgsm/lwgsm_ftp.h index 419a2e72..073aa922 100644 --- a/gsm_at_lib/src/include/gsm/gsm_ftp.h +++ b/lwgsm/src/include/lwgsm/lwgsm_ftp.h @@ -1,10 +1,10 @@ -/** - * \file gsm_ftp.h +/** + * \file lwgsm_ftp.h * \brief FTP API */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,23 +26,23 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_FTP_H -#define GSM_HDR_FTP_H +#ifndef LWGSM_HDR_FTP_H +#define LWGSM_HDR_FTP_H + +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { -#endif - -#include "gsm/gsm.h" +#endif /* __cplusplus */ /** - * \ingroup GSM - * \defgroup GSM_FTP File transfer protocol + * \ingroup LWGSM + * \defgroup LWGSM_FTP File transfer protocol * \brief File Transfer Protocol (FTP) manager * * Currently it is under development @@ -56,6 +56,6 @@ extern "C" { #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif /* GSM_HDR_FTP_H */ +#endif /* LWGSM_HDR_FTP_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_http.h b/lwgsm/src/include/lwgsm/lwgsm_http.h similarity index 77% rename from gsm_at_lib/src/include/gsm/gsm_http.h rename to lwgsm/src/include/lwgsm/lwgsm_http.h index 8e0803e4..a42942d6 100644 --- a/gsm_at_lib/src/include/gsm/gsm_http.h +++ b/lwgsm/src/include/lwgsm/lwgsm_http.h @@ -1,10 +1,10 @@ -/** - * \file gsm_http.h +/** + * \file lwgsm_http.h * \brief HTTP API */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,23 +26,23 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_HTTP_H -#define GSM_HDR_HTTP_H +#ifndef LWGSM_HDR_HTTP_H +#define LWGSM_HDR_HTTP_H + +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { -#endif - -#include "gsm/gsm.h" +#endif /* __cplusplus */ /** - * \ingroup GSM - * \defgroup GSM_HTTP Hyper Text Transfer Protocol + * \ingroup LWGSM + * \defgroup LWGSM_HTTP Hyper Text Transfer Protocol * \brief Hyper Text Transfer Protocol (HTTP) manager * \{ * @@ -56,6 +56,6 @@ extern "C" { #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif /* GSM_HDR_HTTP_H */ +#endif /* LWGSM_HDR_HTTP_H */ diff --git a/lwgsm/src/include/lwgsm/lwgsm_includes.h b/lwgsm/src/include/lwgsm/lwgsm_includes.h new file mode 100644 index 00000000..94c32a7c --- /dev/null +++ b/lwgsm/src/include/lwgsm/lwgsm_includes.h @@ -0,0 +1,80 @@ +/** + * \file lwgsm_includes.h + * \brief All main includes + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_INCLUDES_H +#define LWGSM_HDR_INCLUDES_H + +#include "lwgsm/lwgsm_opt.h" +#include "lwgsm/lwgsm_typedefs.h" +#include "lwgsm/lwgsm_buff.h" +#include "lwgsm/lwgsm_input.h" +#include "lwgsm/lwgsm_debug.h" +#include "lwgsm/lwgsm_utils.h" +#include "lwgsm/lwgsm_pbuf.h" +#include "lwgsm/lwgsm_sim.h" +#include "lwgsm/lwgsm_operator.h" +#include "lwgsm/lwgsm_evt.h" +#include "lwgsm/lwgsm_network.h" +#include "lwgsm/lwgsm_device_info.h" +#include "system/lwgsm_sys.h" + +#if LWGSM_CFG_SMS || __DOXYGEN__ +#include "lwgsm/lwgsm_sms.h" +#endif /* LWGSM_CFG_SMS || __DOXYGEN__ */ +#if LWGSM_CFG_CALL || __DOXYGEN__ +#include "lwgsm/lwgsm_call.h" +#endif /* LWGSM_CFG_CALL || __DOXYGEN__ */ +#if LWGSM_CFG_PHONEBOOK || __DOXYGEN__ +#include "lwgsm/lwgsm_phonebook.h" +#endif /* LWGSM_CFG_PHONEBOOK || __DOXYGEN__ */ +#if LWGSM_CFG_CONN || __DOXYGEN__ +#include "lwgsm/lwgsm_conn.h" +#endif /* LWGSM_CFG_CONN || __DOXYGEN__ */ +#if LWGSM_CFG_NETCONN || __DOXYGEN__ +#include "lwgsm/lwgsm_netconn.h" +#endif /* LWGSM_CFG_NETCONN || __DOXYGEN__ */ +#if LWGSM_CFG_USSD || __DOXYGEN__ +#include "lwgsm/lwgsm_ussd.h" +#endif /* LWGSM_CFG_USSD || __DOXYGEN__ */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LWGSM_HDR_INCLUDES_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_input.h b/lwgsm/src/include/lwgsm/lwgsm_input.h similarity index 75% rename from gsm_at_lib/src/include/gsm/gsm_input.h rename to lwgsm/src/include/lwgsm/lwgsm_input.h index 3fa4c046..91216e56 100644 --- a/gsm_at_lib/src/include/gsm/gsm_input.h +++ b/lwgsm/src/include/lwgsm/lwgsm_input.h @@ -1,10 +1,10 @@ /** - * \file gsm_input.h + * \file lwgsm_input.h * \brief Initialization process */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,30 +26,30 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_INPUT_H -#define GSM_HDR_INPUT_H +#ifndef LWGSM_HDR_INPUT_H +#define LWGSM_HDR_INPUT_H + +#include +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -#include -#include "gsm/gsm.h" - /** - * \ingroup GSM - * \defgroup GSM_INPUT Input processing + * \ingroup LWGSM + * \defgroup LWGSM_INPUT Input processing * \brief Input function for received data * \{ */ -gsmr_t gsm_input(const void* data, size_t len); -gsmr_t gsm_input_process(const void* data, size_t len); +lwgsmr_t lwgsm_input(const void* data, size_t len); +lwgsmr_t lwgsm_input_process(const void* data, size_t len); /** * \} @@ -59,4 +59,4 @@ gsmr_t gsm_input_process(const void* data, size_t len); } #endif /* __cplusplus */ -#endif /* GSM_HDR_INPUT_H */ +#endif /* LWGSM_HDR_INPUT_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_int.h b/lwgsm/src/include/lwgsm/lwgsm_int.h similarity index 84% rename from gsm_at_lib/src/include/gsm/gsm_int.h rename to lwgsm/src/include/lwgsm/lwgsm_int.h index 29491d40..178996f1 100644 --- a/gsm_at_lib/src/include/gsm/gsm_int.h +++ b/lwgsm/src/include/lwgsm/lwgsm_int.h @@ -1,10 +1,10 @@ /** - * \file gsm_int.h + * \file lwgsm_int.h * \brief Internal functions */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,13 +26,13 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_INT_H -#define GSM_HDR_INT_H +#ifndef LWGSM_HDR_INT_H +#define LWGSM_HDR_INT_H #ifdef __cplusplus extern "C" { @@ -42,4 +42,4 @@ extern "C" { } #endif /* __cplusplus */ -#endif /* GSM_HDR_INT_H */ +#endif /* LWGSM_HDR_INT_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_mem.h b/lwgsm/src/include/lwgsm/lwgsm_mem.h similarity index 68% rename from gsm_at_lib/src/include/gsm/gsm_mem.h rename to lwgsm/src/include/lwgsm/lwgsm_mem.h index 2fdc97c3..5bee7c67 100644 --- a/gsm_at_lib/src/include/gsm/gsm_mem.h +++ b/lwgsm/src/include/lwgsm/lwgsm_mem.h @@ -1,10 +1,10 @@ -/** - * \file gsm_mem.h +/** + * \file lwgsm_mem.h * \brief Memory manager */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,28 +26,28 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_MEM_H -#define GSM_HDR_MEM_H +#ifndef LWGSM_HDR_MEM_H +#define LWGSM_HDR_MEM_H + +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -#include "gsm/gsm.h" - /** - * \ingroup GSM - * \defgroup GSM_MEM Memory manager + * \ingroup LWGSM + * \defgroup LWGSM_MEM Memory manager * \brief Dynamic memory manager * \{ */ -#if !GSM_CFG_MEM_CUSTOM || __DOXYGEN__ +#if !LWGSM_CFG_MEM_CUSTOM || __DOXYGEN__ /** * \brief Single memory region descriptor @@ -55,17 +55,17 @@ extern "C" { typedef struct { void* start_addr; /*!< Start address of region */ size_t size; /*!< Size in units of bytes of region */ -} gsm_mem_region_t; +} lwgsm_mem_region_t; -uint8_t gsm_mem_assignmemory(const gsm_mem_region_t* regions, size_t size); +uint8_t lwgsm_mem_assignmemory(const lwgsm_mem_region_t* regions, size_t size); -#endif /* !GSM_CFG_MEM_CUSTOM || __DOXYGEN__ */ +#endif /* !LWGSM_CFG_MEM_CUSTOM || __DOXYGEN__ */ -void* gsm_mem_malloc(size_t size); -void* gsm_mem_realloc(void* ptr, size_t size); -void* gsm_mem_calloc(size_t num, size_t size); -void gsm_mem_free(void* ptr); -uint8_t gsm_mem_free_s(void** ptr); +void* lwgsm_mem_malloc(size_t size); +void* lwgsm_mem_realloc(void* ptr, size_t size); +void* lwgsm_mem_calloc(size_t num, size_t size); +void lwgsm_mem_free(void* ptr); +uint8_t lwgsm_mem_free_s(void** ptr); /** @@ -76,4 +76,4 @@ uint8_t gsm_mem_free_s(void** ptr); } #endif /* __cplusplus */ -#endif /* GSM_HDR_MEM_H */ +#endif /* LWGSM_HDR_MEM_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_memories.h b/lwgsm/src/include/lwgsm/lwgsm_memories.h similarity index 70% rename from gsm_at_lib/src/include/gsm/gsm_memories.h rename to lwgsm/src/include/lwgsm/lwgsm_memories.h index c2219678..7e5d1393 100644 --- a/gsm_at_lib/src/include/gsm/gsm_memories.h +++ b/lwgsm/src/include/lwgsm/lwgsm_memories.h @@ -1,10 +1,10 @@ /** - * \file gsm_memories.h + * \file lwgsm_memories.h * \brief Supported GSM device memories */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,20 +26,20 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -GSM_DEV_MEMORY_ENTRY(SM_P, "SM_P") -GSM_DEV_MEMORY_ENTRY(ME_P, "ME_P") -GSM_DEV_MEMORY_ENTRY(SM, "SM") -GSM_DEV_MEMORY_ENTRY(ME, "ME") -GSM_DEV_MEMORY_ENTRY(MT, "MT") -GSM_DEV_MEMORY_ENTRY(BM, "BM") -GSM_DEV_MEMORY_ENTRY(SR, "SR") -GSM_DEV_MEMORY_ENTRY(ON, "ON") -GSM_DEV_MEMORY_ENTRY(FD, "FD") +LWGSM_DEV_MEMORY_ENTRY(SM_P, "SM_P") +LWGSM_DEV_MEMORY_ENTRY(ME_P, "ME_P") +LWGSM_DEV_MEMORY_ENTRY(SM, "SM") +LWGSM_DEV_MEMORY_ENTRY(ME, "ME") +LWGSM_DEV_MEMORY_ENTRY(MT, "MT") +LWGSM_DEV_MEMORY_ENTRY(BM, "BM") +LWGSM_DEV_MEMORY_ENTRY(SR, "SR") +LWGSM_DEV_MEMORY_ENTRY(ON, "ON") +LWGSM_DEV_MEMORY_ENTRY(FD, "FD") -#undef GSM_DEV_MEMORY_ENTRY \ No newline at end of file +#undef LWGSM_DEV_MEMORY_ENTRY \ No newline at end of file diff --git a/gsm_at_lib/src/include/gsm/gsm_models.h b/lwgsm/src/include/lwgsm/lwgsm_models.h similarity index 76% rename from gsm_at_lib/src/include/gsm/gsm_models.h rename to lwgsm/src/include/lwgsm/lwgsm_models.h index 9a6d9736..24c2953d 100644 --- a/gsm_at_lib/src/include/gsm/gsm_models.h +++ b/lwgsm/src/include/lwgsm/lwgsm_models.h @@ -1,10 +1,10 @@ /** - * \file gsm_models.h + * \file lwgsm_models.h * \brief Supported GSM devices */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,16 +26,16 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ /* Order: Device name; Device model identification, Is_2G, Is_LTE */ -GSM_DEVICE_MODEL_ENTRY(SIM800x, "SIM800", 1, 0) -GSM_DEVICE_MODEL_ENTRY(SIM900x, "SIM900", 1, 0) -//GSM_DEVICE_MODEL_ENTRY(SIM7000x, "SIM7000", 1, 0) -//GSM_DEVICE_MODEL_ENTRY(SIM7020x, "SIM7020", 1, 0) +LWGSM_DEVICE_MODEL_ENTRY(SIM800x, "SIM800", 1, 0) +LWGSM_DEVICE_MODEL_ENTRY(SIM900x, "SIM900", 1, 0) +//LWGSM_DEVICE_MODEL_ENTRY(SIM7000x, "SIM7000", 1, 0) +//LWGSM_DEVICE_MODEL_ENTRY(SIM7020x, "SIM7020", 1, 0) -#undef GSM_DEVICE_MODEL_ENTRY \ No newline at end of file +#undef LWGSM_DEVICE_MODEL_ENTRY \ No newline at end of file diff --git a/lwgsm/src/include/lwgsm/lwgsm_netconn.h b/lwgsm/src/include/lwgsm/lwgsm_netconn.h new file mode 100644 index 00000000..9416dd0b --- /dev/null +++ b/lwgsm/src/include/lwgsm/lwgsm_netconn.h @@ -0,0 +1,91 @@ +/** + * \file lwgsm_netconn.h + * \brief API functions for sequential calls + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_NETCONN_H +#define LWGSM_HDR_NETCONN_H + +#include "lwgsm/lwgsm.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * \ingroup LWGSM_API + * \defgroup LWGSM_NETCONN Network connection + * \brief Network connection + * \{ + */ + +struct lwgsm_netconn; + +/** + * \brief Netconn object structure + */ +typedef struct lwgsm_netconn* lwgsm_netconn_p; + +/** + * \brief Netconn connection type + */ +typedef enum { + LWGSM_NETCONN_TYPE_TCP = LWGSM_CONN_TYPE_TCP, /*!< TCP connection */ + LWGSM_NETCONN_TYPE_UDP = LWGSM_CONN_TYPE_UDP, /*!< UDP connection */ + LWGSM_NETCONN_TYPE_SSL = LWGSM_CONN_TYPE_SSL, /*!< TCP connection over SSL */ +} lwgsm_netconn_type_t; + +lwgsm_netconn_p lwgsm_netconn_new(lwgsm_netconn_type_t type); +lwgsmr_t lwgsm_netconn_delete(lwgsm_netconn_p nc); +lwgsmr_t lwgsm_netconn_connect(lwgsm_netconn_p nc, const char* host, lwgsm_port_t port); +lwgsmr_t lwgsm_netconn_receive(lwgsm_netconn_p nc, lwgsm_pbuf_p* pbuf); +lwgsmr_t lwgsm_netconn_close(lwgsm_netconn_p nc); +int8_t lwgsm_netconn_getconnnum(lwgsm_netconn_p nc); +void lwgsm_netconn_set_receive_timeout(lwgsm_netconn_p nc, uint32_t timeout); +uint32_t lwgsm_netconn_get_receive_timeout(lwgsm_netconn_p nc); + +/* TCP only */ +lwgsmr_t lwgsm_netconn_write(lwgsm_netconn_p nc, const void* data, size_t btw); +lwgsmr_t lwgsm_netconn_flush(lwgsm_netconn_p nc); + +/* UDP only */ +lwgsmr_t lwgsm_netconn_send(lwgsm_netconn_p nc, const void* data, size_t btw); +lwgsmr_t lwgsm_netconn_sendto(lwgsm_netconn_p nc, const lwgsm_ip_t* ip, lwgsm_port_t port, const void* data, size_t btw); + +/** + * \} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LWGSM_HDR_NETCONN_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_network.h b/lwgsm/src/include/lwgsm/lwgsm_network.h similarity index 57% rename from gsm_at_lib/src/include/gsm/gsm_network.h rename to lwgsm/src/include/lwgsm/lwgsm_network.h index f773322b..2adfb785 100644 --- a/gsm_at_lib/src/include/gsm/gsm_network.h +++ b/lwgsm/src/include/lwgsm/lwgsm_network.h @@ -1,10 +1,10 @@ -/** - * \file gsm_network.h +/** + * \file lwgsm_network.h * \brief Network API */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,37 +26,37 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_NETWORK_H -#define GSM_HDR_NETWORK_H +#ifndef LWGSM_HDR_NETWORK_H +#define LWGSM_HDR_NETWORK_H + +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { -#endif - -#include "gsm/gsm.h" +#endif /* __cplusplus */ /** - * \ingroup GSM - * \defgroup GSM_NETWORK Network API + * \ingroup LWGSM + * \defgroup LWGSM_NETWORK Network API * \brief Network manager * \{ */ /* Basic commands, always available */ -gsmr_t gsm_network_rssi(int16_t* rssi, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsm_network_reg_status_t gsm_network_get_reg_status(void); +lwgsmr_t lwgsm_network_rssi(int16_t* rssi, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsm_network_reg_status_t lwgsm_network_get_reg_status(void); /* TCP/IP related commands */ -gsmr_t gsm_network_attach(const char* apn, const char* user, const char* pass, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_network_detach(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -uint8_t gsm_network_is_attached(void); -gsmr_t gsm_network_copy_ip(gsm_ip_t* ip); -gsmr_t gsm_network_check_status(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_network_attach(const char* apn, const char* user, const char* pass, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_network_detach(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +uint8_t lwgsm_network_is_attached(void); +lwgsmr_t lwgsm_network_copy_ip(lwgsm_ip_t* ip); +lwgsmr_t lwgsm_network_check_status(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); /** * \} @@ -64,6 +64,6 @@ gsmr_t gsm_network_check_status(const gsm_api_cmd_evt_fn evt_fn, void* cons #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif /* GSM_HDR_NETWORK_H */ +#endif /* LWGSM_HDR_NETWORK_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_network_api.h b/lwgsm/src/include/lwgsm/lwgsm_network_api.h similarity index 65% rename from gsm_at_lib/src/include/gsm/gsm_network_api.h rename to lwgsm/src/include/lwgsm/lwgsm_network_api.h index a794b2f5..2225b5e9 100644 --- a/gsm_at_lib/src/include/gsm/gsm_network_api.h +++ b/lwgsm/src/include/lwgsm/lwgsm_network_api.h @@ -1,10 +1,10 @@ /** - * \file gsm_network_api.h + * \file lwgsm_network_api.h * \brief API functions for multi-thread network functions */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,37 +26,30 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_NETWORK_API_H -#define GSM_HDR_NETWORK_API_H +#ifndef LWGSM_HDR_NETWORK_API_H +#define LWGSM_HDR_NETWORK_API_H + +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -#include "gsm/gsm.h" - /** - * \ingroup GSM_API - * \defgroup GSM_NETWORK_API Network API + * \ingroup LWGSM_API + * \defgroup LWGSM_NETWORK_API Network API * \brief Network API functions for multi-thread operations * \{ - * - * Its purpose is to control network attach status when multiple threads needs - * to enable/disable network connection. - * - * Each thread asks to attach network connection and manager - * controls when it is necessary to connect or disconnect. - * */ -gsmr_t gsm_network_set_credentials(const char* apn, const char* user, const char* pass); -gsmr_t gsm_network_request_attach(void); -gsmr_t gsm_network_request_detach(void); +lwgsmr_t lwgsm_network_set_credentials(const char* apn, const char* user, const char* pass); +lwgsmr_t lwgsm_network_request_attach(void); +lwgsmr_t lwgsm_network_request_detach(void); /** * \} @@ -66,4 +59,4 @@ gsmr_t gsm_network_request_detach(void); } #endif /* __cplusplus */ -#endif /* GSM_HDR_NETWORK_API_H */ +#endif /* LWGSM_HDR_NETWORK_API_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_operator.h b/lwgsm/src/include/lwgsm/lwgsm_operator.h similarity index 58% rename from gsm_at_lib/src/include/gsm/gsm_operator.h rename to lwgsm/src/include/lwgsm/lwgsm_operator.h index a35451d7..0bfc0500 100644 --- a/gsm_at_lib/src/include/gsm/gsm_operator.h +++ b/lwgsm/src/include/lwgsm/lwgsm_operator.h @@ -1,10 +1,10 @@ -/** - * \file gsm_operator.h +/** + * \file lwgsm_operator.h * \brief Operator API */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,31 +26,31 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_OPERATOR_H -#define GSM_HDR_OPERATOR_H +#ifndef LWGSM_HDR_OPERATOR_H +#define LWGSM_HDR_OPERATOR_H + +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { -#endif - -#include "gsm/gsm.h" +#endif /* __cplusplus */ /** - * \ingroup GSM - * \defgroup GSM_OPERATOR Network operator API + * \ingroup LWGSM + * \defgroup LWGSM_OPERATOR Network operator API * \brief network operator API * \{ */ -gsmr_t gsm_operator_get(gsm_operator_curr_t* curr, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_operator_set(gsm_operator_mode_t mode, gsm_operator_format_t format, const char* name, uint32_t num, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_operator_get(lwgsm_operator_curr_t* curr, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_operator_set(lwgsm_operator_mode_t mode, lwgsm_operator_format_t format, const char* name, uint32_t num, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_operator_scan(gsm_operator_t* ops, size_t opsl, size_t* opf, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_operator_scan(lwgsm_operator_t* ops, size_t opsl, size_t* opf, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); /** * \} @@ -58,6 +58,6 @@ gsmr_t gsm_operator_scan(gsm_operator_t* ops, size_t opsl, size_t* opf, con #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif /* GSM_HDR_OPERATOR_H */ +#endif /* LWGSM_HDR_OPERATOR_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_config_default.h b/lwgsm/src/include/lwgsm/lwgsm_opt.h similarity index 60% rename from gsm_at_lib/src/include/gsm/gsm_config_default.h rename to lwgsm/src/include/lwgsm/lwgsm_opt.h index a4683197..4f7cb635 100644 --- a/gsm_at_lib/src/include/gsm/gsm_config_default.h +++ b/lwgsm/src/include/lwgsm/lwgsm_opt.h @@ -1,10 +1,10 @@ /** - * \file gsm_config_default.h - * \brief Default configuration for GSM-AT library + * \file lwgsm_opt.h + * \brief GSM-AT options */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,17 +26,22 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_DEFAULT_CONFIG_H -#define GSM_HDR_DEFAULT_CONFIG_H +#ifndef LWGSM_HDR_OPT_H +#define LWGSM_HDR_OPT_H + +/* Include application options */ +#ifndef LWGSM_IGNORE_USER_OPTS +#include "lwgsm_opts.h" +#endif /* LWGSM_IGNORE_USER_OPTS */ /** - * \defgroup GSM_CONFIG Configuration - * \brief Configuration parameters + * \defgroup LWGSM_OPT Configuration + * \brief GSM-AT options * \{ * */ @@ -46,40 +51,29 @@ * * \note Value must be set to 1 in the current revision * - * \note Check \ref GSM_CONFIG_OS group for more configuration related to operating system - * - */ -#ifndef GSM_CFG_OS -#define GSM_CFG_OS 1 -#endif - -/** - * \brief Default system port implementation - * - * According to selected port, stack will automatically include appropriate file + * \note Check \ref LWGSM_OPT_OS group for more configuration related to operating system * - * Parameter can be a value of \ref GSM_SYS_PORTS choices */ -#ifndef GSM_CFG_SYS_PORT -#define GSM_CFG_SYS_PORT GSM_SYS_PORT_CMSIS_OS +#ifndef LWGSM_CFG_OS +#define LWGSM_CFG_OS 1 #endif /** * \brief Enables `1` or disables `0` custom memory management functions * - * When set to `1`, \ref GSM_MEM block must be provided manually. - * This includes implementation of functions \ref gsm_mem_malloc, - * \ref gsm_mem_calloc, \ref gsm_mem_realloc and \ref gsm_mem_free + * When set to `1`, \ref LWGSM_MEM block must be provided manually. + * This includes implementation of functions \ref lwgsm_mem_malloc, + * \ref lwgsm_mem_calloc, \ref lwgsm_mem_realloc and \ref lwgsm_mem_free * * \note Function declaration follows standard C functions `malloc, calloc, realloc, free`. - * Declaration is available in `gsm/gsm_mem.h` file. Include this file to final + * Declaration is available in `lwgsm/lwgsm_mem.h` file. Include this file to final * implementation file * * \note When implementing custom memory allocation, it is necessary * to take care of multiple threads accessing same resource for custom allocator */ -#ifndef GSM_CFG_MEM_CUSTOM -#define GSM_CFG_MEM_CUSTOM 0 +#ifndef LWGSM_CFG_MEM_CUSTOM +#define LWGSM_CFG_MEM_CUSTOM 0 #endif /** @@ -94,8 +88,8 @@ * * \note This value must be power of `2` */ -#ifndef GSM_CFG_MEM_ALIGNMENT -#define GSM_CFG_MEM_ALIGNMENT 4 +#ifndef LWGSM_CFG_MEM_ALIGNMENT +#define LWGSM_CFG_MEM_ALIGNMENT 4 #endif /** @@ -104,16 +98,16 @@ * When enabled, `2` additional parameters are available in API functions. * When command is executed, callback function with its parameter could be called when not set to `NULL`. */ -#ifndef GSM_CFG_USE_API_FUNC_EVT -#define GSM_CFG_USE_API_FUNC_EVT 1 +#ifndef LWGSM_CFG_USE_API_FUNC_EVT +#define LWGSM_CFG_USE_API_FUNC_EVT 1 #endif /** * \brief Maximal number of connections AT software can support on GSM device * */ -#ifndef GSM_CFG_MAX_CONNS -#define GSM_CFG_MAX_CONNS 6 +#ifndef LWGSM_CFG_MAX_CONNS +#define LWGSM_CFG_MAX_CONNS 6 #endif /** @@ -124,8 +118,8 @@ * is not an issue, it should be set to maximal value (`1460`) * to optimize data transfer speed performance */ -#ifndef GSM_CFG_CONN_MAX_DATA_LEN -#define GSM_CFG_CONN_MAX_DATA_LEN 1460 +#ifndef LWGSM_CFG_CONN_MAX_DATA_LEN +#define LWGSM_CFG_CONN_MAX_DATA_LEN 1460 #endif /** @@ -134,8 +128,8 @@ * Sometimes it may happen that `AT+SEND` command fails due to different problems. * Trying to send the same data multiple times can raise chances we are successful. */ -#ifndef GSM_CFG_MAX_SEND_RETRIES -#define GSM_CFG_MAX_SEND_RETRIES 3 +#ifndef LWGSM_CFG_MAX_SEND_RETRIES +#define LWGSM_CFG_MAX_SEND_RETRIES 3 #endif /** @@ -143,8 +137,8 @@ * * \note When GSM sends buffer buffer than maximal, multiple buffers are created */ -#ifndef GSM_CFG_IPD_MAX_BUFF_SIZE -#define GSM_CFG_IPD_MAX_BUFF_SIZE 1460 +#ifndef LWGSM_CFG_IPD_MAX_BUFF_SIZE +#define LWGSM_CFG_IPD_MAX_BUFF_SIZE 1460 #endif /** @@ -152,8 +146,8 @@ * * \note Later, user may call API function to change to desired baudrate if necessary */ -#ifndef GSM_CFG_AT_PORT_BAUDRATE -#define GSM_CFG_AT_PORT_BAUDRATE 115200 +#ifndef LWGSM_CFG_AT_PORT_BAUDRATE +#define LWGSM_CFG_AT_PORT_BAUDRATE 115200 #endif /** @@ -165,42 +159,42 @@ * In case of DMA (CPU can work other tasks), buffer may be smaller as CPU * will have more time to process all the incoming bytes * - * \note This parameter has no meaning when \ref GSM_CFG_INPUT_USE_PROCESS is enabled + * \note This parameter has no meaning when \ref LWGSM_CFG_INPUT_USE_PROCESS is enabled */ -#ifndef GSM_CFG_RCV_BUFF_SIZE -#define GSM_CFG_RCV_BUFF_SIZE 0x400 +#ifndef LWGSM_CFG_RCV_BUFF_SIZE +#define LWGSM_CFG_RCV_BUFF_SIZE 0x400 #endif /** - * \brief Enables `1` or disables `0` reset sequence after \ref gsm_init call + * \brief Enables `1` or disables `0` reset sequence after \ref lwgsm_init call * - * \note When this functionality is disabled, user must manually call \ref gsm_reset to send + * \note When this functionality is disabled, user must manually call \ref lwgsm_reset to send * reset sequence to GSM device. */ -#ifndef GSM_CFG_RESET_ON_INIT -#define GSM_CFG_RESET_ON_INIT 1 +#ifndef LWGSM_CFG_RESET_ON_INIT +#define LWGSM_CFG_RESET_ON_INIT 1 #endif /** - * \brief Enables `1` or disables `0` reset sequence after \ref gsm_device_set_present call + * \brief Enables `1` or disables `0` reset sequence after \ref lwgsm_device_set_present call * - * \note When this functionality is disabled, user must manually call \ref gsm_reset to send + * \note When this functionality is disabled, user must manually call \ref lwgsm_reset to send * reset sequence to GSM device. */ -#ifndef GSM_CFG_RESET_ON_DEVICE_PRESENT -#define GSM_CFG_RESET_ON_DEVICE_PRESENT 1 +#ifndef LWGSM_CFG_RESET_ON_DEVICE_PRESENT +#define LWGSM_CFG_RESET_ON_DEVICE_PRESENT 1 #endif /** * \brief Default delay (milliseconds unit) before sending first AT command on reset sequence */ -#ifndef GSM_CFG_RESET_DELAY_DEFAULT -#define GSM_CFG_RESET_DELAY_DEFAULT 1000 +#ifndef LWGSM_CFG_RESET_DELAY_DEFAULT +#define LWGSM_CFG_RESET_DELAY_DEFAULT 1000 #endif /** - * \defgroup GSM_CONFIG_DBG Debugging + * \defgroup LWGSM_OPT_DBG Debugging * \brief Debugging configurations * \{ */ @@ -208,12 +202,12 @@ /** * \brief Set global debug support. * - * Possible values are \ref GSM_DBG_ON or \ref GSM_DBG_OFF + * Possible values are \ref LWGSM_DBG_ON or \ref LWGSM_DBG_OFF * - * \note Set to \ref GSM_DBG_OFF to globally disable all debugs + * \note Set to \ref LWGSM_DBG_OFF to globally disable all debugs */ -#ifndef GSM_CFG_DBG -#define GSM_CFG_DBG GSM_DBG_OFF +#ifndef LWGSM_CFG_DBG +#define LWGSM_CFG_DBG LWGSM_DBG_OFF #endif /** @@ -221,119 +215,119 @@ * * Called with format and optional parameters for printf style debug */ -#ifndef GSM_CFG_DBG_OUT -#define GSM_CFG_DBG_OUT(fmt, ...) do { extern int printf( const char * format, ... ); printf(fmt, ## __VA_ARGS__); } while (0) +#ifndef LWGSM_CFG_DBG_OUT +#define LWGSM_CFG_DBG_OUT(fmt, ...) do { extern int printf( const char * format, ... ); printf(fmt, ## __VA_ARGS__); } while (0) #endif /** * \brief Minimal debug level * - * Check \ref GSM_DBG_LVL for possible values + * Check \ref LWGSM_DBG_LVL for possible values */ -#ifndef GSM_CFG_DBG_LVL_MIN -#define GSM_CFG_DBG_LVL_MIN GSM_DBG_LVL_ALL +#ifndef LWGSM_CFG_DBG_LVL_MIN +#define LWGSM_CFG_DBG_LVL_MIN LWGSM_DBG_LVL_ALL #endif /** * \brief Enabled debug types * - * When debug is globally enabled with \ref GSM_CFG_DBG parameter, + * When debug is globally enabled with \ref LWGSM_CFG_DBG parameter, * user must enable debug types such as TRACE or STATE messages. * - * Check \ref GSM_DBG_TYPE for possible options. Separate values with `bitwise OR` operator + * Check \ref LWGSM_DBG_TYPE for possible options. Separate values with `bitwise OR` operator */ -#ifndef GSM_CFG_DBG_TYPES_ON -#define GSM_CFG_DBG_TYPES_ON 0 +#ifndef LWGSM_CFG_DBG_TYPES_ON +#define LWGSM_CFG_DBG_TYPES_ON 0 #endif /** * \brief Set debug level for init function * - * Possible values are \ref GSM_DBG_ON or \ref GSM_DBG_OFF + * Possible values are \ref LWGSM_DBG_ON or \ref LWGSM_DBG_OFF */ -#ifndef GSM_CFG_DBG_INIT -#define GSM_CFG_DBG_INIT GSM_DBG_OFF +#ifndef LWGSM_CFG_DBG_INIT +#define LWGSM_CFG_DBG_INIT LWGSM_DBG_OFF #endif /** * \brief Set debug level for memory manager * - * Possible values are \ref GSM_DBG_ON or \ref GSM_DBG_OFF + * Possible values are \ref LWGSM_DBG_ON or \ref LWGSM_DBG_OFF */ -#ifndef GSM_CFG_DBG_MEM -#define GSM_CFG_DBG_MEM GSM_DBG_OFF +#ifndef LWGSM_CFG_DBG_MEM +#define LWGSM_CFG_DBG_MEM LWGSM_DBG_OFF #endif /** * \brief Set debug level for input module * - * Possible values are \ref GSM_DBG_ON or \ref GSM_DBG_OFF + * Possible values are \ref LWGSM_DBG_ON or \ref LWGSM_DBG_OFF */ -#ifndef GSM_CFG_DBG_INPUT -#define GSM_CFG_DBG_INPUT GSM_DBG_OFF +#ifndef LWGSM_CFG_DBG_INPUT +#define LWGSM_CFG_DBG_INPUT LWGSM_DBG_OFF #endif /** * \brief Set debug level for GSM threads * - * Possible values are \ref GSM_DBG_ON or \ref GSM_DBG_OFF + * Possible values are \ref LWGSM_DBG_ON or \ref LWGSM_DBG_OFF */ -#ifndef GSM_CFG_DBG_THREAD -#define GSM_CFG_DBG_THREAD GSM_DBG_OFF +#ifndef LWGSM_CFG_DBG_THREAD +#define LWGSM_CFG_DBG_THREAD LWGSM_DBG_OFF #endif /** * \brief Set debug level for asserting of input variables * - * Possible values are \ref GSM_DBG_ON or \ref GSM_DBG_OFF + * Possible values are \ref LWGSM_DBG_ON or \ref LWGSM_DBG_OFF */ -#ifndef GSM_CFG_DBG_ASSERT -#define GSM_CFG_DBG_ASSERT GSM_DBG_OFF +#ifndef LWGSM_CFG_DBG_ASSERT +#define LWGSM_CFG_DBG_ASSERT LWGSM_DBG_OFF #endif /** * \brief Set debug level for incoming data received from device * - * Possible values are \ref GSM_DBG_ON or \ref GSM_DBG_OFF + * Possible values are \ref LWGSM_DBG_ON or \ref LWGSM_DBG_OFF */ -#ifndef GSM_CFG_DBG_IPD -#define GSM_CFG_DBG_IPD GSM_DBG_OFF +#ifndef LWGSM_CFG_DBG_IPD +#define LWGSM_CFG_DBG_IPD LWGSM_DBG_OFF #endif /** * \brief Set debug level for packet buffer manager * - * Possible values are \ref GSM_DBG_ON or \ref GSM_DBG_OFF + * Possible values are \ref LWGSM_DBG_ON or \ref LWGSM_DBG_OFF */ -#ifndef GSM_CFG_DBG_PBUF -#define GSM_CFG_DBG_PBUF GSM_DBG_OFF +#ifndef LWGSM_CFG_DBG_PBUF +#define LWGSM_CFG_DBG_PBUF LWGSM_DBG_OFF #endif /** * \brief Set debug level for connections * - * Possible values are \ref GSM_DBG_ON or \ref GSM_DBG_OFF + * Possible values are \ref LWGSM_DBG_ON or \ref LWGSM_DBG_OFF */ -#ifndef GSM_CFG_DBG_CONN -#define GSM_CFG_DBG_CONN GSM_DBG_OFF +#ifndef LWGSM_CFG_DBG_CONN +#define LWGSM_CFG_DBG_CONN LWGSM_DBG_OFF #endif /** * \brief Set debug level for dynamic variable allocations * - * Possible values are \ref GSM_DBG_ON or \ref GSM_DBG_OFF + * Possible values are \ref LWGSM_DBG_ON or \ref LWGSM_DBG_OFF */ -#ifndef GSM_CFG_DBG_VAR -#define GSM_CFG_DBG_VAR GSM_DBG_OFF +#ifndef LWGSM_CFG_DBG_VAR +#define LWGSM_CFG_DBG_VAR LWGSM_DBG_OFF #endif /** * \brief Set debug level for netconn sequential API * - * Possible values are \ref GSM_DBG_ON or \ref GSM_DBG_OFF + * Possible values are \ref LWGSM_DBG_ON or \ref LWGSM_DBG_OFF */ -#ifndef GSM_CFG_DBG_NETCONN -#define GSM_CFG_DBG_NETCONN GSM_DBG_OFF +#ifndef LWGSM_CFG_DBG_NETCONN +#define LWGSM_CFG_DBG_NETCONN LWGSM_DBG_OFF #endif /** @@ -342,8 +336,8 @@ * * \note This mode is useful when debugging GSM communication */ -#ifndef GSM_CFG_AT_ECHO -#define GSM_CFG_AT_ECHO 0 +#ifndef LWGSM_CFG_AT_ECHO +#define LWGSM_CFG_AT_ECHO 0 #endif /** @@ -351,7 +345,7 @@ */ /** - * \defgroup GSM_CONFIG_OS OS configuration + * \defgroup LWGSM_OPT_OS OS configuration * \brief Operating system dependant configuration * \{ */ @@ -361,8 +355,8 @@ * * Message queue is used for storing memory address to command data */ -#ifndef GSM_CFG_THREAD_PRODUCER_MBOX_SIZE -#define GSM_CFG_THREAD_PRODUCER_MBOX_SIZE 16 +#ifndef LWGSM_CFG_THREAD_PRODUCER_MBOX_SIZE +#define LWGSM_CFG_THREAD_PRODUCER_MBOX_SIZE 16 #endif /** @@ -370,8 +364,8 @@ * * Message queue is used to notify processing thread about new received data on AT port */ -#ifndef GSM_CFG_THREAD_PROCESS_MBOX_SIZE -#define GSM_CFG_THREAD_PROCESS_MBOX_SIZE 16 +#ifndef LWGSM_CFG_THREAD_PROCESS_MBOX_SIZE +#define LWGSM_CFG_THREAD_PROCESS_MBOX_SIZE 16 #endif /** @@ -380,15 +374,15 @@ * When this mode is enabled, no overhead is included for copying data * to receive buffer because bytes are processed directly. * - * \note This mode can only be used when \ref GSM_CFG_OS is enabled + * \note This mode can only be used when \ref LWGSM_CFG_OS is enabled * * \note When using this mode, separate thread must be dedicated only * for reading data on AT port * * \note Best case for using this mode is if DMA receive is supported by host device */ -#ifndef GSM_CFG_INPUT_USE_PROCESS -#define GSM_CFG_INPUT_USE_PROCESS 0 +#ifndef LWGSM_CFG_INPUT_USE_PROCESS +#define LWGSM_CFG_INPUT_USE_PROCESS 0 #endif /** @@ -396,8 +390,8 @@ * * It can be used to check if thread is alive. */ -#ifndef GSM_THREAD_PRODUCER_HOOK -#define GSM_THREAD_PRODUCER_HOOK() +#ifndef LWGSM_THREAD_PRODUCER_HOOK +#define LWGSM_THREAD_PRODUCER_HOOK() #endif /** @@ -405,8 +399,8 @@ * * It can be used to check if thread is alive. */ -#ifndef GSM_THREAD_PROCESS_HOOK -#define GSM_THREAD_PROCESS_HOOK() +#ifndef LWGSM_THREAD_PROCESS_HOOK +#define LWGSM_THREAD_PROCESS_HOOK() #endif /** @@ -414,13 +408,13 @@ */ /** - * \defgroup GSM_CONFIG_MODULES Modules + * \defgroup LWGSM_OPT_MODULES Modules * \brief Configuration of specific modules * \{ */ /** - * \defgroup GSM_CONFIG_MODULES_NETCONN Netconn module + * \defgroup LWGSM_OPT_MODULES_NETCONN Netconn module * \brief Configuration of netconn API module * \{ */ @@ -429,10 +423,10 @@ * \brief Enables `1` or disables `0` NETCONN sequential API support for OS systems * * \note To use this feature, OS support is mandatory. - * \sa GSM_CFG_OS + * \sa LWGSM_CFG_OS */ -#ifndef GSM_CFG_NETCONN -#define GSM_CFG_NETCONN 0 +#ifndef LWGSM_CFG_NETCONN +#define LWGSM_CFG_NETCONN 0 #endif /** @@ -445,8 +439,8 @@ * \note Even if this option is enabled, user must still manually set timeout, * by default time will be set to 0 which means no timeout. */ -#ifndef GSM_CFG_NETCONN_RECEIVE_TIMEOUT -#define GSM_CFG_NETCONN_RECEIVE_TIMEOUT 1 +#ifndef LWGSM_CFG_NETCONN_RECEIVE_TIMEOUT +#define LWGSM_CFG_NETCONN_RECEIVE_TIMEOUT 1 #endif /** @@ -454,8 +448,8 @@ * * Defines number of maximal clients waiting in accept queue of server connection */ -#ifndef GSM_CFG_NETCONN_ACCEPT_QUEUE_LEN -#define GSM_CFG_NETCONN_ACCEPT_QUEUE_LEN 5 +#ifndef LWGSM_CFG_NETCONN_ACCEPT_QUEUE_LEN +#define LWGSM_CFG_NETCONN_ACCEPT_QUEUE_LEN 5 #endif /** @@ -463,8 +457,8 @@ * * Defines maximal number of pbuf data packet references for receive */ -#ifndef GSM_CFG_NETCONN_RECEIVE_QUEUE_LEN -#define GSM_CFG_NETCONN_RECEIVE_QUEUE_LEN 8 +#ifndef LWGSM_CFG_NETCONN_RECEIVE_QUEUE_LEN +#define LWGSM_CFG_NETCONN_RECEIVE_QUEUE_LEN 8 #endif /** @@ -472,7 +466,7 @@ */ /** - * \defgroup GSM_CONFIG_MODULES_MQTT MQTT client module + * \defgroup LWGSM_OPT_MODULES_MQTT MQTT client module * \brief Configuration of MQTT and MQTT API client modules * \{ */ @@ -481,26 +475,26 @@ * \brief Maximal number of open MQTT requests at a time * */ -#ifndef GSM_CFG_MQTT_MAX_REQUESTS -#define GSM_CFG_MQTT_MAX_REQUESTS 8 +#ifndef LWGSM_CFG_MQTT_MAX_REQUESTS +#define LWGSM_CFG_MQTT_MAX_REQUESTS 8 #endif /** * \brief Set debug level for MQTT client module * - * Possible values are \ref GSM_DBG_ON or \ref GSM_DBG_OFF + * Possible values are \ref LWGSM_DBG_ON or \ref LWGSM_DBG_OFF */ -#ifndef GSM_CFG_DBG_MQTT -#define GSM_CFG_DBG_MQTT GSM_DBG_OFF +#ifndef LWGSM_CFG_DBG_MQTT +#define LWGSM_CFG_DBG_MQTT LWGSM_DBG_OFF #endif /** * \brief Set debug level for MQTT API client module * - * Possible values are \ref GSM_DBG_ON or \ref GSM_DBG_OFF + * Possible values are \ref LWGSM_DBG_ON or \ref LWGSM_DBG_OFF */ -#ifndef GSM_CFG_DBG_MQTT_API -#define GSM_CFG_DBG_MQTT_API GSM_DBG_OFF +#ifndef LWGSM_CFG_DBG_MQTT_API +#define LWGSM_CFG_DBG_MQTT_API LWGSM_DBG_OFF #endif /** @@ -514,8 +508,8 @@ * Network must be enabled to use all GPRS/LTE functions such * as connection API, FTP, HTTP, etc. */ -#ifndef GSM_CFG_NETWORK -#define GSM_CFG_NETWORK 0 +#ifndef LWGSM_CFG_NETWORK +#define LWGSM_CFG_NETWORK 0 #endif /** @@ -524,76 +518,76 @@ * \note This may be used for data-only SIM cards where command might fail * when trying to attach to network for data transfer */ -#ifndef GSM_CFG_NETWORK_IGNORE_CGACT_RESULT -#define GSM_CFG_NETWORK_IGNORE_CGACT_RESULT 0 +#ifndef LWGSM_CFG_NETWORK_IGNORE_CGACT_RESULT +#define LWGSM_CFG_NETWORK_IGNORE_CGACT_RESULT 0 #endif /** * \brief Enables `1` or disables `0` connection API. * - * \note \ref GSM_CFG_NETWORK must be enabled to use connection feature + * \note \ref LWGSM_CFG_NETWORK must be enabled to use connection feature */ -#ifndef GSM_CFG_CONN -#define GSM_CFG_CONN 0 +#ifndef LWGSM_CFG_CONN +#define LWGSM_CFG_CONN 0 #endif /** * \brief Enables `1` or disables `0` SMS API. * */ -#ifndef GSM_CFG_SMS -#define GSM_CFG_SMS 0 +#ifndef LWGSM_CFG_SMS +#define LWGSM_CFG_SMS 0 #endif /** * \brief Enables `1` or disables `0` call API. * */ -#ifndef GSM_CFG_CALL -#define GSM_CFG_CALL 0 +#ifndef LWGSM_CFG_CALL +#define LWGSM_CFG_CALL 0 #endif /** * \brief Enables `1` or disables `0` phonebook API. * */ -#ifndef GSM_CFG_PHONEBOOK -#define GSM_CFG_PHONEBOOK 0 +#ifndef LWGSM_CFG_PHONEBOOK +#define LWGSM_CFG_PHONEBOOK 0 #endif /** * \brief Enables `1` or disables `0` HTTP API. * - * \note \ref GSM_CFG_NETWORK must be enabled to use connection feature + * \note \ref LWGSM_CFG_NETWORK must be enabled to use connection feature */ -#ifndef GSM_CFG_HTTP -#define GSM_CFG_HTTP 0 +#ifndef LWGSM_CFG_HTTP +#define LWGSM_CFG_HTTP 0 #endif /** * \brief Enables `1` or disables `0` FTP API. * - * \note \ref GSM_CFG_NETWORK must be enabled to use connection feature + * \note \ref LWGSM_CFG_NETWORK must be enabled to use connection feature */ -#ifndef GSM_CFG_FTP -#define GSM_CFG_FTP 0 +#ifndef LWGSM_CFG_FTP +#define LWGSM_CFG_FTP 0 #endif /** * \brief Enables `1` or disables `0` PING API. * - * \note \ref GSM_CFG_NETWORK must be enabled to use connection feature + * \note \ref LWGSM_CFG_NETWORK must be enabled to use connection feature */ -#ifndef GSM_CFG_PING -#define GSM_CFG_PING 0 +#ifndef LWGSM_CFG_PING +#define LWGSM_CFG_PING 0 #endif /** * \brief Enables `1` or disables `0` USSD API. * */ -#ifndef GSM_CFG_USSD -#define GSM_CFG_USSD 0 +#ifndef LWGSM_CFG_USSD +#define LWGSM_CFG_USSD 0 #endif /** @@ -607,12 +601,12 @@ * * \note Single poll interval applies for all connections */ -#ifndef GSM_CFG_CONN_POLL_INTERVAL -#define GSM_CFG_CONN_POLL_INTERVAL 500 +#ifndef LWGSM_CFG_CONN_POLL_INTERVAL +#define LWGSM_CFG_CONN_POLL_INTERVAL 500 #endif /** - * \defgroup GSM_CONFIG_STD_LIB Standard library + * \defgroup LWGSM_OPT_STD_LIB Standard library * \brief Standard C library configuration * \{ * @@ -637,8 +631,8 @@ void * my_memcpy(void* dst, const void* src, size_t len); * \param[in] len: Number of bytes to copy * \return Destination memory start address */ -#ifndef GSM_MEMCPY -#define GSM_MEMCPY(dst, src, len) memcpy(dst, src, len) +#ifndef LWGSM_MEMCPY +#define LWGSM_MEMCPY(dst, src, len) memcpy(dst, src, len) #endif /** @@ -655,8 +649,8 @@ void * my_memset(void* dst, int b, size_t len); * \param[in] len: Number of bytes to set * \return Destination memory start address */ -#ifndef GSM_MEMSET -#define GSM_MEMSET(dst, b, len) memset(dst, b, len) +#ifndef LWGSM_MEMSET +#define LWGSM_MEMSET(dst, b, len) memset(dst, b, len) #endif /** @@ -669,12 +663,14 @@ void * my_memset(void* dst, int b, size_t len); #if !__DOXYGEN__ -#if !GSM_CFG_OS - #if GSM_CFG_INPUT_USE_PROCESS - #error "GSM_CFG_INPUT_USE_PROCESS may only be enabled when OS is used!" - #endif /* GSM_CFG_INPUT_USE_PROCESS */ -#endif /* !GSM_CFG_OS */ +#if !LWGSM_CFG_OS +#if LWGSM_CFG_INPUT_USE_PROCESS +#error "LWGSM_CFG_INPUT_USE_PROCESS may only be enabled when OS is used!" +#endif /* LWGSM_CFG_INPUT_USE_PROCESS */ +#endif /* !LWGSM_CFG_OS */ #endif /* !__DOXYGEN__ */ -#endif /* GSM_HDR_DEFAULT_CONFIG_H */ +#include "lwgsm/lwgsm_debug.h" + +#endif /* LWGSM_HDR_OPT_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_config_template.h b/lwgsm/src/include/lwgsm/lwgsm_opts_template.h similarity index 73% rename from gsm_at_lib/src/include/gsm/gsm_config_template.h rename to lwgsm/src/include/lwgsm/lwgsm_opts_template.h index 20aa0d4a..cabb69bd 100644 --- a/gsm_at_lib/src/include/gsm/gsm_config_template.h +++ b/lwgsm/src/include/lwgsm/lwgsm_opts_template.h @@ -1,10 +1,10 @@ /** - * \file gsm_config_template.h + * \file lwgsm_opts_template.h * \brief Template config file */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,22 +26,19 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_CONFIG_H -#define GSM_HDR_CONFIG_H +#ifndef LWGSM_HDR_OPTS_H +#define LWGSM_HDR_OPTS_H -/* Rename this file to "gsm_config.h" for your application */ +/* Rename this file to "lwgsm_opts.h" for your application */ /* - * Open "include/gsm/gsm_config_default.h" and + * Open "include/lwgsm/lwgsm_opt.h" and * copy & replace here settings you want to change values */ -/* After user configuration, call default config to merge config together */ -#include "gsm/gsm_config_default.h" - -#endif /* GSM_HDR_CONFIG_H */ +#endif /* LWGSM_HDR_OPTS_H */ diff --git a/lwgsm/src/include/lwgsm/lwgsm_parser.h b/lwgsm/src/include/lwgsm/lwgsm_parser.h new file mode 100644 index 00000000..34d99006 --- /dev/null +++ b/lwgsm/src/include/lwgsm/lwgsm_parser.h @@ -0,0 +1,76 @@ +/** + * \file lwgsm_parser.h + * \brief Parser of AT responses + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_PARSER_H +#define LWGSM_HDR_PARSER_H + +#if defined(__cplusplus) +extern "C" { +#endif /* defined(__cplusplus) */ + +#include "lwgsm/lwgsm.h" + +int32_t lwgsmi_parse_number(const char** str); +uint8_t lwgsmi_parse_string(const char** src, char* dst, size_t dst_len, uint8_t trim); +uint8_t lwgsmi_parse_ip(const char** src, lwgsm_ip_t* ip); +uint8_t lwgsmi_parse_mac(const char** src, lwgsm_mac_t* mac); + +uint8_t lwgsmi_parse_cpin(const char* str, uint8_t send_evt); +uint8_t lwgsmi_parse_creg(const char* str, uint8_t skip_first); +uint8_t lwgsmi_parse_csq(const char* str); + +uint8_t lwgsmi_parse_cmgs(const char* str, size_t* num); +uint8_t lwgsmi_parse_cmti(const char* str, uint8_t send_evt); +uint8_t lwgsmi_parse_cmgr(const char* str); +uint8_t lwgsmi_parse_cmgl(const char* str); + +uint8_t lwgsmi_parse_at_sdk_version(const char* str, uint32_t* version_out); + +uint8_t lwgsmi_parse_cops_scan(uint8_t ch, uint8_t reset); +uint8_t lwgsmi_parse_cops(const char* str); +uint8_t lwgsmi_parse_clcc(const char* str, uint8_t send_evt); + +uint8_t lwgsmi_parse_cpbs(const char* str, uint8_t opt); +uint8_t lwgsmi_parse_cpms(const char* str, uint8_t opt); +uint8_t lwgsmi_parse_cpbr(const char* str); +uint8_t lwgsmi_parse_cpbf(const char* str); + +uint8_t lwgsmi_parse_cipstatus_conn(const char* str, uint8_t is_conn_line, uint8_t* continueScan); + +uint8_t lwgsmi_parse_ipd(const char* str); + +#if defined(__cplusplus) +} +#endif /* defined(__cplusplus) */ + +#endif /* LWGSM_HDR_PARSER_H */ diff --git a/lwgsm/src/include/lwgsm/lwgsm_pbuf.h b/lwgsm/src/include/lwgsm/lwgsm_pbuf.h new file mode 100644 index 00000000..55975302 --- /dev/null +++ b/lwgsm/src/include/lwgsm/lwgsm_pbuf.h @@ -0,0 +1,82 @@ +/** + * \file lwgsm_pbuf.h + * \brief Packet buffer manager + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_PBUF_H +#define LWGSM_HDR_PBUF_H + +#include "lwgsm/lwgsm.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * \ingroup LWGSM + * \defgroup LWGSM_PBUF Packet buffer + * \brief Packet buffer manager + * \{ + */ + +lwgsm_pbuf_p lwgsm_pbuf_new(size_t len); +size_t lwgsm_pbuf_free(lwgsm_pbuf_p pbuf); +void* lwgsm_pbuf_data(const lwgsm_pbuf_p pbuf); +size_t lwgsm_pbuf_length(const lwgsm_pbuf_p pbuf, uint8_t tot); +lwgsmr_t lwgsm_pbuf_take(lwgsm_pbuf_p pbuf, const void* data, size_t len, size_t offset); +size_t lwgsm_pbuf_copy(lwgsm_pbuf_p pbuf, void* data, size_t len, size_t offset); + +lwgsmr_t lwgsm_pbuf_cat(lwgsm_pbuf_p head, const lwgsm_pbuf_p tail); +lwgsmr_t lwgsm_pbuf_chain(lwgsm_pbuf_p head, lwgsm_pbuf_p tail); +lwgsmr_t lwgsm_pbuf_ref(lwgsm_pbuf_p pbuf); + +uint8_t lwgsm_pbuf_get_at(const lwgsm_pbuf_p pbuf, size_t pos, uint8_t* el); +size_t lwgsm_pbuf_memcmp(const lwgsm_pbuf_p pbuf, const void* data, size_t len, size_t offset); +size_t lwgsm_pbuf_strcmp(const lwgsm_pbuf_p pbuf, const char* str, size_t offset); +size_t lwgsm_pbuf_memfind(const lwgsm_pbuf_p pbuf, const void* data, size_t len, size_t off); +size_t lwgsm_pbuf_strfind(const lwgsm_pbuf_p pbuf, const char* str, size_t off); + +uint8_t lwgsm_pbuf_advance(lwgsm_pbuf_p pbuf, int len); +lwgsm_pbuf_p lwgsm_pbuf_skip(lwgsm_pbuf_p pbuf, size_t offset, size_t* new_offset); + +void* lwgsm_pbuf_get_linear_addr(const lwgsm_pbuf_p pbuf, size_t offset, size_t* new_len); + +void lwgsm_pbuf_set_ip(lwgsm_pbuf_p pbuf, const lwgsm_ip_t* ip, lwgsm_port_t port); + +/** + * \} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LWGSM_HDR_PBUF_H */ diff --git a/lwgsm/src/include/lwgsm/lwgsm_phonebook.h b/lwgsm/src/include/lwgsm/lwgsm_phonebook.h new file mode 100644 index 00000000..8a0cc4f9 --- /dev/null +++ b/lwgsm/src/include/lwgsm/lwgsm_phonebook.h @@ -0,0 +1,68 @@ +/** + * \file lwgsm_phonebook.h + * \brief Phonebook API + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_PHONEBOOK_H +#define LWGSM_HDR_PHONEBOOK_H + +#include "lwgsm/lwgsm.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * \ingroup LWGSM + * \defgroup LWGSM_PHONEBOOK Phonebook API + * \brief Phonebook manager + * \{ + */ + +lwgsmr_t lwgsm_pb_enable(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_pb_disable(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); + +lwgsmr_t lwgsm_pb_add(lwgsm_mem_t mem, const char* name, const char* num, lwgsm_number_type_t type, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_pb_edit(lwgsm_mem_t mem, size_t pos, const char* name, const char* num, lwgsm_number_type_t type, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_pb_delete(lwgsm_mem_t mem, size_t pos, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_pb_read(lwgsm_mem_t mem, size_t pos, lwgsm_pb_entry_t* entry, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_pb_list(lwgsm_mem_t mem, size_t start_index, lwgsm_pb_entry_t* entries, size_t etr, size_t* er, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_pb_search(lwgsm_mem_t mem, const char* search, lwgsm_pb_entry_t* entries, size_t etr, size_t* er, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); + +/** + * \} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LWGSM_HDR_PHONEBOOK_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_ping.h b/lwgsm/src/include/lwgsm/lwgsm_ping.h similarity index 77% rename from gsm_at_lib/src/include/gsm/gsm_ping.h rename to lwgsm/src/include/lwgsm/lwgsm_ping.h index 4f4ea6b9..c0a7389f 100644 --- a/gsm_at_lib/src/include/gsm/gsm_ping.h +++ b/lwgsm/src/include/lwgsm/lwgsm_ping.h @@ -1,10 +1,10 @@ -/** - * \file gsm_ping.h +/** + * \file lwgsm_ping.h * \brief PING API */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,23 +26,23 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_PING_H -#define GSM_HDR_PING_H +#ifndef LWGSM_HDR_PING_H +#define LWGSM_HDR_PING_H + +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { -#endif - -#include "gsm/gsm.h" +#endif /* __cplusplus */ /** - * \ingroup GSM - * \defgroup GSM_PING PING API + * \ingroup LWGSM + * \defgroup LWGSM_PING PING API * \brief PING manager * \{ */ @@ -53,6 +53,6 @@ extern "C" { #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif /* GSM_HDR_PING_H */ +#endif /* LWGSM_HDR_PING_H */ diff --git a/lwgsm/src/include/lwgsm/lwgsm_private.h b/lwgsm/src/include/lwgsm/lwgsm_private.h new file mode 100644 index 00000000..60fe00f0 --- /dev/null +++ b/lwgsm/src/include/lwgsm/lwgsm_private.h @@ -0,0 +1,803 @@ +/** + * \file lwgsm_private.h + * \brief Private structures and enumerations + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_PRIV_H +#define LWGSM_HDR_PRIV_H + +#include "lwgsm/lwgsm.h" +#include "lwgsm/lwgsm_typedefs.h" +#include "lwgsm/lwgsm_debug.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * \addtogroup LWGSM_TYPEDEFS + * \{ + */ + +/** + * \brief List of possible messages + */ +typedef enum { + LWGSM_CMD_IDLE = 0, /*!< IDLE mode */ + + /* Basic AT commands */ + LWGSM_CMD_RESET, /*!< Reset device */ + LWGSM_CMD_RESET_DEVICE_FIRST_CMD, /*!< Reset device first driver specific command */ + LWGSM_CMD_ATE0, /*!< Disable ECHO mode on AT commands */ + LWGSM_CMD_ATE1, /*!< Enable ECHO mode on AT commands */ + LWGSM_CMD_GSLP, /*!< Set GSM to sleep mode */ + LWGSM_CMD_RESTORE, /*!< Restore GSM internal settings to default values */ + LWGSM_CMD_UART, + + LWGSM_CMD_CGACT_SET_0, + LWGSM_CMD_CGACT_SET_1, + LWGSM_CMD_CGATT_SET_0, + LWGSM_CMD_CGATT_SET_1, + LWGSM_CMD_NETWORK_ATTACH, /*!< Attach to a network */ + LWGSM_CMD_NETWORK_DETACH, /*!< Detach from network */ + + LWGSM_CMD_CIPMUX_SET, + LWGSM_CMD_CIPRXGET_SET, + LWGSM_CMD_CSTT_SET, + + + + /* AT commands according to the V.25TER */ + LWGSM_CMD_CALL_ENABLE, + LWGSM_CMD_A, /*!< Re-issues the Last Command Given */ + LWGSM_CMD_ATA, /*!< Answer an Incoming Call */ + LWGSM_CMD_ATD, /*!< Mobile Originated Call to Dial A Number */ + LWGSM_CMD_ATD_N, /*!< Originate Call to Phone Number in Current Memory: ATD */ + LWGSM_CMD_ATD_STR, /*!< Originate Call to Phone Number in Memory Which Corresponds to Field "str": ATD>str */ + LWGSM_CMD_ATDL, /*!< Redial Last Telephone Number Used */ + LWGSM_CMD_ATE, /*!< Set Command Echo Mode */ + LWGSM_CMD_ATH, /*!< Disconnect Existing */ + LWGSM_CMD_ATI, /*!< Display Product Identification Information */ + LWGSM_CMD_ATL, /*!< Set Monitor speaker */ + LWGSM_CMD_ATM, /*!< Set Monitor Speaker Mode */ + LWGSM_CMD_PPP, /*!< Switch from Data Mode or PPP Online Mode to Command Mode, "+++" originally */ + LWGSM_CMD_ATO, /*!< Switch from Command Mode to Data Mode */ + LWGSM_CMD_ATP, /*!< Select Pulse Dialing */ + LWGSM_CMD_ATQ, /*!< Set Result Code Presentation Mode */ + LWGSM_CMD_ATS0, /*!< Set Number of Rings before Automatically Answering the Call */ + LWGSM_CMD_ATS3, /*!< Set Command Line Termination Character */ + LWGSM_CMD_ATS4, /*!< Set Response Formatting Character */ + LWGSM_CMD_ATS5, /*!< Set Command Line Editing Character */ + LWGSM_CMD_ATS6, /*!< Pause Before Blind */ + LWGSM_CMD_ATS7, /*!< Set Number of Seconds to Wait for Connection Completion */ + LWGSM_CMD_ATS8, /*!< Set Number of Seconds to Wait for Comma Dial Modifier Encountered in Dial String of D Command */ + LWGSM_CMD_ATS10, /*!< Set Disconnect Delay after Indicating the Absence of Data Carrier */ + LWGSM_CMD_ATT, /*!< Select Tone Dialing */ + LWGSM_CMD_ATV, /*!< TA Response Format */ + LWGSM_CMD_ATX, /*!< Set CONNECT Result Code Format and Monitor Call Progress */ + LWGSM_CMD_ATZ, /*!< Reset Default Configuration */ + LWGSM_CMD_AT_C, /*!< Set DCD Function Mode, AT&C */ + LWGSM_CMD_AT_D, /*!< Set DTR Function, AT&D */ + LWGSM_CMD_AT_F, /*!< Factory Defined Configuration, AT&F */ + LWGSM_CMD_AT_V, /*!< Display Current Configuration, AT&V */ + LWGSM_CMD_AT_W, /*!< Store Active Profile, AT&W */ + LWGSM_CMD_GCAP, /*!< Request Complete TA Capabilities List */ + LWGSM_CMD_GMI, /*!< Request Manufacturer Identification */ + LWGSM_CMD_GMM, /*!< Request TA Model Identification */ + LWGSM_CMD_GMR, /*!< Request TA Revision Identification of Software Release */ + LWGSM_CMD_GOI, /*!< Request Global Object Identification */ + LWGSM_CMD_GSN, /*!< Request TA Serial Number Identification (IMEI) */ + LWGSM_CMD_ICF, /*!< Set TE-TA Control Character Framing */ + LWGSM_CMD_IFC, /*!< Set TE-TA Local Data Flow Control */ + LWGSM_CMD_IPR, /*!< Set TE-TA Fixed Local Rate */ + LWGSM_CMD_HVOIC, /*!< Disconnect Voice Call Only */ + + /* AT commands according to 3GPP TS 27.007 */ + LWGSM_CMD_COPS_SET, /*!< Set operator */ + LWGSM_CMD_COPS_GET, /*!< Get current operator */ + LWGSM_CMD_COPS_GET_OPT, /*!< Get a list of available operators */ + LWGSM_CMD_CPAS, /*!< Phone Activity Status */ + LWGSM_CMD_CGMI_GET, /*!< Request Manufacturer Identification */ + LWGSM_CMD_CGMM_GET, /*!< Request Model Identification */ + LWGSM_CMD_CGMR_GET, /*!< Request TA Revision Identification of Software Release */ + LWGSM_CMD_CGSN_GET, /*!< Request Product Serial Number Identification (Identical with +GSN) */ + + LWGSM_CMD_CLCC_SET, /*!< List Current Calls of ME */ + LWGSM_CMD_CLCK, /*!< Facility Lock */ + + LWGSM_CMD_CACM, /*!< Accumulated Call Meter (ACM) Reset or Query */ + LWGSM_CMD_CAMM, /*!< Accumulated Call Meter Maximum (ACM max) Set or Query */ + LWGSM_CMD_CAOC, /*!< Advice of Charge */ + LWGSM_CMD_CBST, /*!< Select Bearer Service Type */ + LWGSM_CMD_CCFC, /*!< Call Forwarding Number and Conditions Control */ + LWGSM_CMD_CCWA, /*!< Call Waiting Control */ + LWGSM_CMD_CEER, /*!< Extended Error Report */ + LWGSM_CMD_CSCS, /*!< Select TE Character Set */ + LWGSM_CMD_CSTA, /*!< Select Type of Address */ + LWGSM_CMD_CHLD, /*!< Call Hold and Multiparty */ + LWGSM_CMD_CIMI, /*!< Request International Mobile Subscriber Identity */ + LWGSM_CMD_CLIP, /*!< Calling Line Identification Presentation */ + LWGSM_CMD_CLIR, /*!< Calling Line Identification Restriction */ + LWGSM_CMD_CMEE_SET, /*!< Report Mobile Equipment Error */ + LWGSM_CMD_COLP, /*!< Connected Line Identification Presentation */ + + LWGSM_CMD_PHONEBOOK_ENABLE, + LWGSM_CMD_CPBF, /*!< Find Phonebook Entries */ + LWGSM_CMD_CPBR, /*!< Read Current Phonebook Entries */ + LWGSM_CMD_CPBS_SET, /*!< Select Phonebook Memory Storage */ + LWGSM_CMD_CPBS_GET, /*!< Get current Phonebook Memory Storage */ + LWGSM_CMD_CPBS_GET_OPT, /*!< Get available Phonebook Memory Storages */ + LWGSM_CMD_CPBW_SET, /*!< Write Phonebook Entry */ + LWGSM_CMD_CPBW_GET_OPT, /*!< Get options for write Phonebook Entry */ + + LWGSM_CMD_SIM_PROCESS_BASIC_CMDS, /*!< Command setup, executed when SIM is in READY state */ + LWGSM_CMD_CPIN_SET, /*!< Enter PIN */ + LWGSM_CMD_CPIN_GET, /*!< Read current SIM status */ + LWGSM_CMD_CPIN_ADD, /*!< Add new PIN to SIM if pin is not set */ + LWGSM_CMD_CPIN_CHANGE, /*!< Change already active SIM */ + LWGSM_CMD_CPIN_REMOVE, /*!< Remove current PIN */ + LWGSM_CMD_CPUK_SET, /*!< Enter PUK and set new PIN */ + + LWGSM_CMD_CSQ_GET, /*!< Signal Quality Report */ + LWGSM_CMD_CFUN_SET, /*!< Set Phone Functionality */ + LWGSM_CMD_CFUN_GET, /*!< Get Phone Functionality */ + LWGSM_CMD_CREG_SET, /*!< Network Registration set output */ + LWGSM_CMD_CREG_GET, /*!< Get current network registration status */ + LWGSM_CMD_CBC, /*!< Battery Charge */ + LWGSM_CMD_CNUM, /*!< Subscriber Number */ + + LWGSM_CMD_CPWD, /*!< Change Password */ + LWGSM_CMD_CR, /*!< Service Reporting Control */ + LWGSM_CMD_CRC, /*!< Set Cellular Result Codes for Incoming Call Indication */ + LWGSM_CMD_CRLP, /*!< Select Radio Link Protocol Parameters */ + LWGSM_CMD_CRSM, /*!< Restricted SIM Access */ + LWGSM_CMD_VTD, /*!< Tone Duration */ + LWGSM_CMD_VTS, /*!< DTMF and Tone Generation */ + LWGSM_CMD_CMUX, /*!< Multiplexer Control */ + LWGSM_CMD_CPOL, /*!< Preferred Operator List */ + LWGSM_CMD_COPN, /*!< Read Operator Names */ + LWGSM_CMD_CCLK, /*!< Clock */ + LWGSM_CMD_CSIM, /*!< Generic SIM Access */ + LWGSM_CMD_CALM, /*!< Alert Sound Mode */ + LWGSM_CMD_CALS, /*!< Alert Sound Select */ + LWGSM_CMD_CRSL, /*!< Ringer Sound Level */ + LWGSM_CMD_CLVL, /*!< Loud Speaker Volume Level */ + LWGSM_CMD_CMUT, /*!< Mute Control */ + LWGSM_CMD_CPUC, /*!< Price Per Unit and Currency Table */ + LWGSM_CMD_CCWE, /*!< Call Meter Maximum Event */ + LWGSM_CMD_CUSD_SET, /*!< Unstructured Supplementary Service Data, Set command */ + LWGSM_CMD_CUSD_GET, /*!< Unstructured Supplementary Service Data, Get command */ + LWGSM_CMD_CUSD, /*!< Unstructured Supplementary Service Data, Execute command */ + LWGSM_CMD_CSSN, /*!< Supplementary Services Notification */ + + LWGSM_CMD_CIPMUX, /*!< Start Up Multi-IP Connection */ + LWGSM_CMD_CIPSTART, /*!< Start Up TCP or UDP Connection */ + LWGSM_CMD_CIPSEND, /*!< Send Data Through TCP or UDP Connection */ + LWGSM_CMD_CIPQSEND, /*!< Select Data Transmitting Mode */ + LWGSM_CMD_CIPACK, /*!< Query Previous Connection Data Transmitting State */ + LWGSM_CMD_CIPCLOSE, /*!< Close TCP or UDP Connection */ + LWGSM_CMD_CIPSHUT, /*!< Deactivate GPRS PDP Context */ + LWGSM_CMD_CLPORT, /*!< Set Local Port */ + LWGSM_CMD_CSTT, /*!< Start Task and Set APN, username, password */ + LWGSM_CMD_CIICR, /*!< Bring Up Wireless Connection with GPRS or CSD */ + LWGSM_CMD_CIFSR, /*!< Get Local IP Address */ + LWGSM_CMD_CIPSTATUS, /*!< Query Current Connection Status */ + LWGSM_CMD_CDNSCFG, /*!< Configure Domain Name Server */ + LWGSM_CMD_CDNSGIP, /*!< Query the IP Address of Given Domain Name */ + LWGSM_CMD_CIPHEAD, /*!< Add an IP Head at the Beginning of a Package Received */ + LWGSM_CMD_CIPATS, /*!< Set Auto Sending Timer */ + LWGSM_CMD_CIPSPRT, /*!< Set Prompt of greater than sign When Module Sends Data */ + LWGSM_CMD_CIPSERVER, /*!< Configure Module as Server */ + LWGSM_CMD_CIPCSGP, /*!< Set CSD or GPRS for Connection Mode */ + LWGSM_CMD_CIPSRIP, /*!< Show Remote IP Address and Port When Received Data */ + LWGSM_CMD_CIPDPDP, /*!< Set Whether to Check State of GPRS Network Timing */ + LWGSM_CMD_CIPMODE, /*!< Select TCPIP Application Mode */ + LWGSM_CMD_CIPCCFG, /*!< Configure Transparent Transfer Mode */ + LWGSM_CMD_CIPSHOWTP, /*!< Display Transfer Protocol in IP Head When Received Data */ + LWGSM_CMD_CIPUDPMODE, /*!< UDP Extended Mode */ + LWGSM_CMD_CIPRXGET, /*!< Get Data from Network Manually */ + LWGSM_CMD_CIPSCONT, /*!< Save TCPIP Application Context */ + LWGSM_CMD_CIPRDTIMER, /*!< Set Remote Delay Timer */ + LWGSM_CMD_CIPSGTXT, /*!< Select GPRS PDP context */ + LWGSM_CMD_CIPTKA, /*!< Set TCP Keepalive Parameters */ + LWGSM_CMD_CIPSSL, /*!< Connection SSL function */ + + LWGSM_CMD_SMS_ENABLE, + LWGSM_CMD_CMGD, /*!< Delete SMS Message */ + LWGSM_CMD_CMGF, /*!< Select SMS Message Format */ + LWGSM_CMD_CMGL, /*!< List SMS Messages from Preferred Store */ + LWGSM_CMD_CMGR, /*!< Read SMS Message */ + LWGSM_CMD_CMGS, /*!< Send SMS Message */ + LWGSM_CMD_CMGW, /*!< Write SMS Message to Memory */ + LWGSM_CMD_CMSS, /*!< Send SMS Message from Storage */ + LWGSM_CMD_CMGDA, /*!< MASS SMS delete */ + LWGSM_CMD_CNMI, /*!< New SMS Message Indications */ + LWGSM_CMD_CPMS_SET, /*!< Set preferred SMS Message Storage */ + LWGSM_CMD_CPMS_GET, /*!< Get preferred SMS Message Storage */ + LWGSM_CMD_CPMS_GET_OPT, /*!< Get optional SMS message storages */ + LWGSM_CMD_CRES, /*!< Restore SMS Settings */ + LWGSM_CMD_CSAS, /*!< Save SMS Settings */ + LWGSM_CMD_CSCA, /*!< SMS Service Center Address */ + LWGSM_CMD_CSCB, /*!< Select Cell Broadcast SMS Messages */ + LWGSM_CMD_CSDH, /*!< Show SMS Text Mode Parameters */ + LWGSM_CMD_CSMP, /*!< Set SMS Text Mode Parameters */ + LWGSM_CMD_CSMS, /*!< Select Message Service */ + + LWGSM_CMD_END, /*!< Last CMD entry */ +} lwgsm_cmd_t; + +/** + * \brief Connection structure + */ +typedef struct lwgsm_conn { + lwgsm_conn_type_t type; /*!< Connection type */ + uint8_t num; /*!< Connection number */ + lwgsm_ip_t remote_ip; /*!< Remote IP address */ + lwgsm_port_t remote_port; /*!< Remote port number */ + lwgsm_port_t local_port; /*!< Local IP address */ + lwgsm_evt_fn evt_func; /*!< Callback function for connection */ + void* arg; /*!< User custom argument */ + + uint8_t val_id; /*!< Validation ID number. It is increased each time a new connection is established. + It protects sending data to wrong connection in case we have data in send queue, + and connection was closed and active again in between. */ + + lwgsm_linbuff_t buff; /*!< Linear buffer structure */ + + size_t total_recved; /*!< Total number of bytes received */ + + union { + struct { + uint8_t active: 1; /*!< Status whether connection is active */ + uint8_t client: 1; /*!< Status whether connection is in client mode */ + uint8_t data_received: 1; /*!< Status whether first data were received on connection */ + uint8_t in_closing: 1; /*!< Status if connection is in closing mode. + When in closing mode, ignore any possible received data from function */ + uint8_t bearer: 1; /*!< Bearer used. Can be `1` or `0` */ + } f; /*!< Connection flags */ + } status; /*!< Connection status union with flag bits */ +} lwgsm_conn_t; + +/** + * \ingroup LWGSM_PBUF + * \brief Packet buffer structure + */ +typedef struct lwgsm_pbuf { + struct lwgsm_pbuf* next; /*!< Next pbuf in chain list */ + size_t tot_len; /*!< Total length of pbuf chain */ + size_t len; /*!< Length of payload */ + size_t ref; /*!< Number of references to this structure */ + uint8_t* payload; /*!< Pointer to payload memory */ + lwgsm_ip_t ip; /*!< Remote address for received IPD data */ + lwgsm_port_t port; /*!< Remote port for received IPD data */ +} lwgsm_pbuf_t; + +/** + * \brief Incoming network data read structure + */ +typedef struct { + uint8_t read; /*!< Set to 1 when we should process input data as connection data */ + size_t tot_len; /*!< Total length of packet */ + size_t rem_len; /*!< Remaining bytes to read in current +IPD statement */ + lwgsm_conn_p conn; /*!< Pointer to connection for network data */ + + size_t buff_ptr; /*!< Buffer pointer to save data to. + When set to `NULL` while `read = 1`, reading should ignore incoming data */ + lwgsm_pbuf_p buff; /*!< Pointer to data buffer used for receiving data */ +} lwgsm_ipd_t; + +/** + * \brief Connection result on connect command + */ +typedef enum { + LWGSM_CONN_CONNECT_UNKNOWN, /*!< No valid result */ + LWGSM_CONN_CONNECT_OK, /*!< Connected OK */ + LWGSM_CONN_CONNECT_ERROR, /*!< Error on connection */ + LWGSM_CONN_CONNECT_ALREADY, /*!< Already connected */ +} lwgsm_conn_connect_res_t; + +/** + * \brief Message queue structure to share between threads + */ +typedef struct lwgsm_msg { + lwgsm_cmd_t cmd_def; /*!< Default message type received from queue */ + lwgsm_cmd_t cmd; /*!< Since some commands can have different subcommands, sub command is used here */ + uint8_t i; /*!< Variable to indicate order number of subcommands */ + lwgsm_sys_sem_t sem; /*!< Semaphore for the message */ + uint8_t is_blocking; /*!< Status if command is blocking */ + uint32_t block_time; /*!< Maximal blocking time in units of milliseconds. Use 0 to for non-blocking call */ + lwgsmr_t res; /*!< Result of message operation */ + lwgsmr_t (*fn)(struct lwgsm_msg*); /*!< Processing callback function to process packet */ + +#if LWGSM_CFG_USE_API_FUNC_EVT + lwgsm_api_cmd_evt_fn evt_fn; /*!< Command callback API function */ + void* evt_arg; /*!< Command callback API callback parameter */ +#endif /* LWGSM_CFG_USE_API_FUNC_EVT */ + + union { + struct { + uint32_t delay; /*!< Delay to use before sending first reset AT command */ + } reset; /*!< Reset device */ + struct { + uint32_t baudrate; /*!< Baudrate for AT port */ + } uart; /*!< UART configuration */ + + struct { + uint8_t mode; /*!< Functionality mode */ + } cfun; /*!< Set phone functionality */ + + struct { + const char* pin; /*!< Pin code to write */ + } cpin_enter; /*!< Enter pin code */ + struct { + const char* pin; /*!< New pin code */ + } cpin_add; /*!< Add pin code if previously wasn't set */ + struct { + const char* current_pin; /*!< Current pin code */ + const char* new_pin; /*!< New pin code */ + } cpin_change; /*!< Change current pin code */ + struct { + const char* pin; /*!< Current pin code */ + } cpin_remove; /*!< Remove PIN code */ + struct { + const char* puk; /*!< PUK code */ + const char* pin; /*!< New PIN code */ + } cpuk_enter; /*!< Enter PUK and new PIN */ + struct { + size_t cnum_tries; /*!< Number of tries */ + } sim_info; /*!< Get information for SIM card */ + + struct { + char* str; /*!< Pointer to output string array */ + size_t len; /*!< Length of output string array including trailing zero memory */ + } device_info; /*!< All kind of device info, serial number, model, manufacturer, revision */ + + struct { + int16_t* rssi; /*!< Pointer to RSSI variable */ + } csq; /*!< Signal strength */ + struct { + uint8_t read; /*!< Flag indicating we can read the COPS actual data */ + lwgsm_operator_t* ops; /*!< Pointer to operators array */ + size_t opsl; /*!< Length of operators array */ + size_t opsi; /*!< Current operator index array */ + size_t* opf; /*!< Pointer to number of operators found */ + } cops_scan; /*!< Scan operators */ + struct { + lwgsm_operator_curr_t* curr; /*!< Pointer to output current operator */ + } cops_get; /*!< Get current operator info */ + struct { + lwgsm_operator_mode_t mode; /*!< COPS mode */ + lwgsm_operator_format_t format; /*!< Operator format to print */ + const char* name; /*!< Short or long name, according to format */ + uint32_t num; /*!< Number in case format is number */ + } cops_set; /*!< Set operator settings */ + +#if LWGSM_CFG_CONN || __DOXYGEN__ + /* Connection based commands */ + struct { + lwgsm_conn_t** conn; /*!< Pointer to pointer to save connection used */ + const char* host; /*!< Host to use for connection */ + lwgsm_port_t port; /*!< Remote port used for connection */ + lwgsm_conn_type_t type; /*!< Connection type */ + void* arg; /*!< Connection custom argument */ + lwgsm_evt_fn evt_func; /*!< Callback function to use on connection */ + uint8_t num; /*!< Connection number used for start */ + lwgsm_conn_connect_res_t conn_res; /*!< Connection result status */ + } conn_start; /*!< Structure for starting new connection */ + struct { + lwgsm_conn_t* conn; /*!< Pointer to connection to close */ + uint8_t val_id; /*!< Connection current validation ID when command was sent to queue */ + } conn_close; /*!< Close connection */ + struct { + lwgsm_conn_t* conn; /*!< Pointer to connection to send data */ + size_t btw; /*!< Number of remaining bytes to write */ + size_t ptr; /*!< Current write pointer for data */ + const uint8_t* data; /*!< Data to send */ + size_t sent; /*!< Number of bytes sent in last packet */ + size_t sent_all; /*!< Number of bytes sent all together */ + uint8_t tries; /*!< Number of tries used for last packet */ + uint8_t wait_send_ok_err; /*!< Set to 1 when we wait for SEND OK or SEND ERROR */ + const lwgsm_ip_t* remote_ip; /*!< Remote IP address for UDP connection */ + lwgsm_port_t remote_port; /*!< Remote port address for UDP connection */ + uint8_t fau; /*!< Free after use flag to free memory after data are sent (or not) */ + size_t* bw; /*!< Number of bytes written so far */ + uint8_t val_id; /*!< Connection current validation ID when command was sent to queue */ + } conn_send; /*!< Structure to send data on connection */ +#endif /* LWGSM_CFG_CONN || __DOXYGEN__ */ +#if LWGSM_CFG_SMS || __DOXYGEN__ + struct { + const char* num; /*!< Phone number */ + const char* text; /*!< SMS content to send */ + uint8_t format; /*!< SMS format, `0 = PDU`, `1 = text` */ + size_t pos; /*!< Set on +CMGS response if command is OK */ + } sms_send; /*!< Send SMS */ + struct { + lwgsm_mem_t mem; /*!< Memory to read from */ + size_t pos; /*!< SMS position in memory */ + lwgsm_sms_entry_t* entry; /*!< Pointer to entry to write info */ + uint8_t update; /*!< Update SMS status after read operation */ + uint8_t format; /*!< SMS format, `0 = PDU`, `1 = text` */ + uint8_t read; /*!< Read the data flag */ + } sms_read; /*!< Read single SMS */ + struct { + lwgsm_mem_t mem; /*!< Memory to delete from */ + size_t pos; /*!< SMS position in memory */ + } sms_delete; /*!< Delete SMS message */ + struct { + lwgsm_sms_status_t status; /*!< SMS status to delete */ + } sms_delete_all; /*!< Mass delete SMS messages */ + struct { + lwgsm_mem_t mem; /*!< Memory to use for read */ + lwgsm_sms_status_t status; /*!< SMS entries status */ + lwgsm_sms_entry_t* entries; /*!< Pointer to entries */ + size_t etr; /*!< Entries to read (array length) */ + size_t ei; /*!< Current entry index in array */ + size_t* er; /*!< Final entries read pointer for user */ + uint8_t update; /*!< Update SMS status after read operation */ + uint8_t format; /*!< SMS format, `0 = PDU`, `1 = text` */ + uint8_t read; /*!< Read the data flag */ + } sms_list; /*!< List SMS messages */ + struct { + lwgsm_mem_t mem[3]; /*!< Array of memories */ + } sms_memory; /*!< Set preferred memories */ +#endif /* LWGSM_CFG_SMS || __DOXYGEN__ */ +#if LWGSM_CFG_CALL || __DOXYGEN__ + struct { + const char* number; /*!< Phone number to dial */ + } call_start; /*!< Start a new call */ +#endif /* LWGSM_CFG_CALL || __DOXYGEN__ */ +#if LWGSM_CFG_PHONEBOOK || __DOXYGEN__ + struct { + lwgsm_mem_t mem; /*!< Memory to use */ + size_t pos; /*!< Memory position. Set to 0 to use new one or SIZE_T MAX to delete entry */ + const char* name; /*!< Entry name */ + const char* num; /*!< Entry number */ + lwgsm_number_type_t type; /*!< Entry phone number type */ + uint8_t del; /*!< Flag indicates delete */ + } pb_write; /*!< Write/Edit/Delete entry */ + struct { + lwgsm_mem_t mem; /*!< Memory to use */ + size_t start_index; /*!< Start index in phonebook to read */ + lwgsm_pb_entry_t* entries; /*!< Pointer to entries array */ + size_t etr; /*!< NUmber of entries to read */ + size_t ei; /*!< Current entry index */ + size_t* er; /*!< Final entries read pointer for user */ + } pb_list; /*!< List phonebook entries */ + struct { + lwgsm_mem_t mem; /*!< Memory to use */ + lwgsm_pb_entry_t* entries; /*!< Pointer to entries array */ + size_t etr; /*!< NUmber of entries to read */ + size_t ei; /*!< Current entry index */ + size_t* er; /*!< Final entries read pointer for user */ + const char* search; /*!< Search string */ + } pb_search; /*!< Search phonebook entries */ +#endif /* LWGSM_CFG_PHONEBOOK || __DOXYGEN__ */ + struct { + const char* code; /*!< Code to send */ + char* resp; /*!< Response array */ + size_t resp_len; /*!< Length of response array */ + uint8_t read; /*!< Flag indicating we can read the COPS actual data */ + size_t resp_write_ptr; /*!< Write pointer for response */ + uint8_t quote_det; /*!< Information if quote has been detected */ + } ussd; /*!< Execute USSD command */ +#if LWGSM_CFG_NETWORK || __DOXYGEN__ + struct { + const char* apn; /*!< APN address */ + const char* user; /*!< APN username */ + const char* pass; /*!< APN password */ + } network_attach; /*!< Settings for network attach */ +#endif /* LWGSM_CFG_NETWORK || __DOXYGEN__ */ + } msg; /*!< Group of different possible message contents */ +} lwgsm_msg_t; + +/** + * \brief IP and MAC structure with netmask and gateway addresses + */ +typedef struct { + lwgsm_ip_t ip; /*!< IP address */ + lwgsm_ip_t gw; /*!< Gateway address */ + lwgsm_ip_t nm; /*!< Netmask address */ + lwgsm_mac_t mac; /*!< MAC address */ +} lwgsm_ip_mac_t; + +/** + * \brief Link connection active info + */ +typedef struct { + uint8_t failed; /*!< Status if connection successful */ + uint8_t num; /*!< Connection number */ + uint8_t is_server; /*!< Status if connection is client or server */ + lwgsm_conn_type_t type; /*!< Connection type */ + lwgsm_ip_t remote_ip; /*!< Remote IP address */ + lwgsm_port_t remote_port; /*!< Remote port */ + lwgsm_port_t local_port; /*!< Local port number */ +} lwgsm_link_conn_t; + +/** + * \brief Callback function linked list prototype + */ +typedef struct lwgsm_evt_func { + struct lwgsm_evt_func* next; /*!< Next function in the list */ + lwgsm_evt_fn fn; /*!< Function pointer itself */ +} lwgsm_evt_func_t; + +/** + * \ingroup LWGSM_SMS + * \brief SMS memory information + */ +typedef struct { + uint32_t mem_available; /*!< Bit field of available memories */ + lwgsm_mem_t current; /*!< Current memory choice */ + size_t total; /*!< Size of memory in units of entries */ + size_t used; /*!< Number of used entries */ +} lwgsm_sms_mem_t; + +/** + * \ingroup LWGSM_SMS + * \brief SMS structure + */ +typedef struct { + uint8_t ready; /*!< Flag indicating feature ready by device */ + uint8_t enabled; /*!< Flag indicating feature enabled */ + + lwgsm_sms_mem_t mem[3]; /*!< 3 memory info for operation,receive,sent storage */ +} lwgsm_sms_t; + +/** + * \ingroup LWGSM_SMS + * \brief SMS memory information + */ +typedef struct { + uint32_t mem_available; /*!< Bit field of available memories */ + lwgsm_mem_t current; /*!< Current memory choice */ + size_t total; /*!< Size of memory in units of entries */ + size_t used; /*!< Number of used entries */ +} lwgsm_pb_mem_t; + +/** + * \ingroup LWGSM_PB + * \brief Phonebook structure + */ +typedef struct { + uint8_t ready; /*!< Flag indicating feature ready by device */ + uint8_t enabled; /*!< Flag indicating feature enabled */ + + lwgsm_pb_mem_t mem; /*!< Memory information */ +} lwgsm_pb_t; + +/** + * \brief SIM structure + */ +typedef struct { + lwgsm_sim_state_t state; /*!< Current SIM status */ +} lwgsm_sim_t; + +/** + * \brief Network info + */ +typedef struct { + lwgsm_network_reg_status_t status; /*!< Network registration status */ + lwgsm_operator_curr_t curr_operator; /*!< Current operator information */ + + uint8_t is_attached; /*!< Flag indicating device is attached and PDP context is active */ + lwgsm_ip_t ip_addr; /*!< Device IP address when network PDP context is enabled */ +} lwgsm_network_t; + +/** + * \brief GSM modules structure + */ +typedef struct { + /* Device identification */ + char model_manufacturer[20]; /*!< Device manufacturer */ + char model_number[20]; /*!< Device model number */ + char model_serial_number[20];/*!< Device serial number */ + char model_revision[20]; /*!< Device revision */ + lwgsm_device_model_t model; /*!< Device model */ + + /* Network&operator specific */ + lwgsm_sim_t sim; /*!< SIM data */ + lwgsm_network_t network; /*!< Network status */ + int16_t rssi; /*!< RSSI signal strength. `0` = invalid, `-53 % -113` = valid */ + + /* Device specific */ +#if LWGSM_CFG_CONN || __DOXYGEN__ + uint8_t active_conns_cur_parse_num; /*!< Current connection number used for parsing */ + + lwgsm_conn_t conns[LWGSM_CFG_MAX_CONNS]; /*!< Array of all connection structures */ + lwgsm_ipd_t ipd; /*!< Connection incoming data structure */ + uint8_t conn_val_id; /*!< Validation ID increased each time device connects to network */ +#endif /* LWGSM_CFG_CONNS || __DOXYGEN__ */ +#if LWGSM_CFG_SMS || __DOXYGEN__ + lwgsm_sms_t sms; /*!< SMS information */ +#endif /* LWGSM_CFG_SMS || __DOXYGEN__ */ +#if LWGSM_CFG_PHONEBOOK || __DOXYGEN__ + lwgsm_pb_t pb; /*!< Phonebook information */ +#endif /* LWGSM_CFG_PHONEBOOK || __DOXYGEN__ */ +#if LWGSM_CFG_CALL || __DOXYGEN__ + lwgsm_call_t call; /*!< Call information */ +#endif /* LWGSM_CFG_CALL || __DOXYGEN__ */ +} lwgsm_modules_t; + +/** + * \brief GSM global structure + */ +typedef struct { + size_t locked_cnt; /*!< Counter how many times (recursive) stack is currently locked */ + + lwgsm_sys_sem_t sem_sync; /*!< Synchronization semaphore between threads */ + lwgsm_sys_mbox_t mbox_producer; /*!< Producer message queue handle */ + lwgsm_sys_mbox_t mbox_process; /*!< Consumer message queue handle */ + lwgsm_sys_thread_t thread_produce; /*!< Producer thread handle */ + lwgsm_sys_thread_t thread_process; /*!< Processing thread handle */ +#if !LWGSM_CFG_INPUT_USE_PROCESS || __DOXYGEN__ + lwgsm_buff_t buff; /*!< Input processing buffer */ +#endif /* !LWGSM_CFG_INPUT_USE_PROCESS || __DOXYGEN__ */ + lwgsm_ll_t ll; /*!< Low level functions */ + + lwgsm_msg_t* msg; /*!< Pointer to current user message being executed */ + + lwgsm_evt_t evt; /*!< Callback processing structure */ + lwgsm_evt_func_t* evt_func; /*!< Callback function linked list */ + + lwgsm_modules_t m; /*!< All modules. When resetting, reset structure */ + + union { + struct { + uint8_t initialized: 1; /*!< Flag indicating GSM library is initialized */ + uint8_t dev_present: 1; /*!< Flag indicating GSM device is present */ + } f; /*!< Flags structure */ + } status; /*!< Status structure */ +} lwgsm_t; + +/** + * \brief Memory mapping structure between string and value in app + */ +typedef struct { + lwgsm_mem_t mem; /*!< Mem indication */ + const char* mem_str; /*!< Memory string */ +} lwgsm_dev_mem_map_t; + +/** + * \brief Device models map between model and other information + */ +typedef struct { + lwgsm_device_model_t model; /*!< Device model */ + const char* id_str; /*!< Model string identification */ + uint8_t is_2g; /*!< Status if modem is 2G */ + uint8_t is_lte; /*!< Status if modem is LTE */ +} lwgsm_dev_model_map_t; + +/** + * \ingroup LWGSM_UNICODE + * \brief Unicode support structure + */ +typedef struct { + uint8_t ch[4]; /*!< UTF-8 max characters */ + uint8_t t; /*!< Total expected length in UTF-8 sequence */ + uint8_t r; /*!< Remaining bytes in UTF-8 sequence */ + lwgsmr_t res; /*!< Current result of processing */ +} lwgsm_unicode_t; + +/** + * \} + */ + +#if !__DOXYGEN__ + +/** + * \ingroup LWGSM + * \defgroup LWGSM_PRIVATE Internal functions + * \brief Functions, structures and enumerations + * \{ + */ + +extern lwgsm_t lwgsm; + +extern const lwgsm_dev_mem_map_t lwgsm_dev_mem_map[]; +extern const size_t lwgsm_dev_mem_map_size; + +extern const lwgsm_dev_model_map_t lwgsm_dev_model_map[]; +extern const size_t lwgsm_dev_model_map_size; + +#define CMD_IS_CUR(c) (lwgsm.msg != NULL && lwgsm.msg->cmd == (c)) +#define CMD_IS_DEF(c) (lwgsm.msg != NULL && lwgsm.msg->cmd_def == (c)) +#define CMD_GET_CUR() ((lwgsm_cmd_t)(((lwgsm.msg != NULL) ? lwgsm.msg->cmd : LWGSM_CMD_IDLE))) +#define CMD_GET_DEF() ((lwgsm_cmd_t)(((lwgsm.msg != NULL) ? lwgsm.msg->cmd_def : LWGSM_CMD_IDLE))) + +#define CRLF "\r\n" +#define CRLF_LEN 2 + +#define LWGSM_MSG_VAR_DEFINE(name) lwgsm_msg_t* name +#define LWGSM_MSG_VAR_ALLOC(name, blocking) do {\ + (name) = lwgsm_mem_malloc(sizeof(*(name))); \ + LWGSM_DEBUGW(LWGSM_CFG_DBG_VAR | LWGSM_DBG_TYPE_TRACE, (name) != NULL, "[MSG VAR] Allocated %d bytes at %p\r\n", sizeof(*(name)), (name)); \ + LWGSM_DEBUGW(LWGSM_CFG_DBG_VAR | LWGSM_DBG_TYPE_TRACE, (name) == NULL, "[MSG VAR] Error allocating %d bytes\r\n", sizeof(*(name))); \ + if ((name) == NULL) { \ + return lwgsmERRMEM; \ + } \ + LWGSM_MEMSET((name), 0x00, sizeof(*(name))); \ + (name)->is_blocking = LWGSM_U8((blocking) > 0); \ + } while (0) +#define LWGSM_MSG_VAR_REF(name) (*(name)) +#define LWGSM_MSG_VAR_FREE(name) do {\ + LWGSM_DEBUGF(LWGSM_CFG_DBG_VAR | LWGSM_DBG_TYPE_TRACE, "[MSG VAR] Free memory: %p\r\n", (name)); \ + if (lwgsm_sys_sem_isvalid(&((name)->sem))) { \ + lwgsm_sys_sem_delete(&((name)->sem)); \ + lwgsm_sys_sem_invalid(&((name)->sem)); \ + } \ + lwgsm_mem_free_s((void **)&(name)); \ + } while (0) +#if LWGSM_CFG_USE_API_FUNC_EVT +#define LWGSM_MSG_VAR_SET_EVT(name, e_fn, e_arg) do {\ + (name)->evt_fn = (e_fn); \ + (name)->evt_arg = (e_arg); \ + } while (0) +#else /* LWGSM_CFG_USE_API_FUNC_EVT */ +#define LWGSM_MSG_VAR_SET_EVT(name, e_fn, e_arg) do { LWGSM_UNUSED(e_fn); LWGSM_UNUSED(e_arg); } while (0) +#endif /* !LWGSM_CFG_USE_API_FUNC_EVT */ + +#define LWGSM_CHARISNUM(x) ((x) >= '0' && (x) <= '9') +#define LWGSM_CHARTONUM(x) ((x) - '0') +#define LWGSM_CHARISHEXNUM(x) (((x) >= '0' && (x) <= '9') || ((x) >= 'a' && (x) <= 'f') || ((x) >= 'A' && (x) <= 'F')) +#define LWGSM_CHARHEXTONUM(x) (((x) >= '0' && (x) <= '9') ? ((x) - '0') : (((x) >= 'a' && (x) <= 'f') ? ((x) - 'a' + 10) : (((x) >= 'A' && (x) <= 'F') ? ((x) - 'A' + 10) : 0))) +#define LWGSM_ISVALIDASCII(x) (((x) >= 32 && (x) <= 126) || (x) == '\r' || (x) == '\n') + +#define LWGSM_PORT2NUM(port) ((uint32_t)(port)) + +const char* lwgsmi_dbg_msg_to_string(lwgsm_cmd_t cmd); +lwgsmr_t lwgsmi_process(const void* data, size_t len); +lwgsmr_t lwgsmi_process_buffer(void); +lwgsmr_t lwgsmi_initiate_cmd(lwgsm_msg_t* msg); +uint8_t lwgsmi_is_valid_conn_ptr(lwgsm_conn_p conn); +lwgsmr_t lwgsmi_send_cb(lwgsm_evt_type_t type); +lwgsmr_t lwgsmi_send_conn_cb(lwgsm_conn_t* conn, lwgsm_evt_fn cb); +void lwgsmi_conn_init(void); +lwgsmr_t lwgsmi_send_msg_to_producer_mbox(lwgsm_msg_t* msg, lwgsmr_t (*process_fn)(lwgsm_msg_t*), uint32_t max_block_time); +uint32_t lwgsmi_get_from_mbox_with_timeout_checks(lwgsm_sys_mbox_t* b, void** m, uint32_t timeout); +uint8_t lwgsmi_conn_closed_process(uint8_t conn_num, uint8_t forced); +void lwgsmi_conn_start_timeout(lwgsm_conn_p conn); + +lwgsmr_t lwgsmi_get_sim_info(const uint32_t blocking); + +void lwgsmi_reset_everything(uint8_t forced); +void lwgsmi_process_events_for_timeout_or_error(lwgsm_msg_t* msg, lwgsmr_t err); + +/** + * \} + */ + +#endif /* !__DOXYGEN__ */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LWGSM_HDR_PRIV_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_sim.h b/lwgsm/src/include/lwgsm/lwgsm_sim.h similarity index 53% rename from gsm_at_lib/src/include/gsm/gsm_sim.h rename to lwgsm/src/include/lwgsm/lwgsm_sim.h index 901a74cd..d1f66eef 100644 --- a/gsm_at_lib/src/include/gsm/gsm_sim.h +++ b/lwgsm/src/include/lwgsm/lwgsm_sim.h @@ -1,10 +1,10 @@ -/** - * \file gsm_sim.h +/** + * \file lwgsm_sim.h * \brief SIM API */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,33 +26,33 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_SIM_H -#define GSM_HDR_SIM_H +#ifndef LWGSM_HDR_SIM_H +#define LWGSM_HDR_SIM_H + +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { -#endif - -#include "gsm/gsm.h" +#endif /* __cplusplus */ /** - * \ingroup GSM - * \defgroup GSM_SIM SIM API + * \ingroup LWGSM + * \defgroup LWGSM_SIM SIM API * \brief SIM card manager * \{ */ -gsm_sim_state_t gsm_sim_get_current_state(void); -gsmr_t gsm_sim_pin_enter(const char* pin, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_sim_pin_add(const char* pin, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_sim_pin_remove(const char* pin, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_sim_pin_change(const char* pin, const char* new_pin, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); -gsmr_t gsm_sim_puk_enter(const char* puk, const char* new_pin, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsm_sim_state_t lwgsm_sim_get_current_state(void); +lwgsmr_t lwgsm_sim_pin_enter(const char* pin, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_sim_pin_add(const char* pin, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_sim_pin_remove(const char* pin, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_sim_pin_change(const char* pin, const char* new_pin, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_sim_puk_enter(const char* puk, const char* new_pin, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); /** * \} @@ -60,6 +60,6 @@ gsmr_t gsm_sim_puk_enter(const char* puk, const char* new_pin, const gsm_ap #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif /* GSM_HDR_SIM_H */ +#endif /* LWGSM_HDR_SIM_H */ diff --git a/lwgsm/src/include/lwgsm/lwgsm_sms.h b/lwgsm/src/include/lwgsm/lwgsm_sms.h new file mode 100644 index 00000000..292f4bd0 --- /dev/null +++ b/lwgsm/src/include/lwgsm/lwgsm_sms.h @@ -0,0 +1,69 @@ +/** + * \file lwgsm_sms.h + * \brief SMS API + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_SMS_H +#define LWGSM_HDR_SMS_H + +#include "lwgsm/lwgsm.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * \ingroup LWGSM + * \defgroup LWGSM_SMS SMS API + * \brief SMS manager + * \{ + */ + +lwgsmr_t lwgsm_sms_enable(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_sms_disable(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); + +lwgsmr_t lwgsm_sms_send(const char* num, const char* text, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_sms_read(lwgsm_mem_t mem, size_t pos, lwgsm_sms_entry_t* entry, uint8_t update, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_sms_delete(lwgsm_mem_t mem, size_t pos, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_sms_delete_all(lwgsm_sms_status_t status, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_sms_list(lwgsm_mem_t mem, lwgsm_sms_status_t stat, lwgsm_sms_entry_t* entries, size_t etr, size_t* er, uint8_t update, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, + const uint32_t blocking); +lwgsmr_t lwgsm_sms_set_preferred_storage(lwgsm_mem_t mem1, lwgsm_mem_t mem2, lwgsm_mem_t mem3, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); + +/** + * \} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LWGSM_HDR_SMS_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_threads.h b/lwgsm/src/include/lwgsm/lwgsm_threads.h similarity index 78% rename from gsm_at_lib/src/include/gsm/gsm_threads.h rename to lwgsm/src/include/lwgsm/lwgsm_threads.h index f11f59a4..2cd1ff18 100644 --- a/gsm_at_lib/src/include/gsm/gsm_threads.h +++ b/lwgsm/src/include/lwgsm/lwgsm_threads.h @@ -1,10 +1,10 @@ /** - * \file gsm_threads.h + * \file lwgsm_threads.h * \brief OS threads implementations */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,25 +26,25 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_THREADS_H -#define GSM_HDR_THREADS_H +#ifndef LWGSM_HDR_THREADS_H +#define LWGSM_HDR_THREADS_H + +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -#include "gsm/gsm.h" - -void gsm_thread_produce(void* const arg); -void gsm_thread_process(void* const arg); +void lwgsm_thread_produce(void* const arg); +void lwgsm_thread_process(void* const arg); #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* GSM_HDR_THREADS_H */ +#endif /* LWGSM_HDR_THREADS_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_timeout.h b/lwgsm/src/include/lwgsm/lwgsm_timeout.h similarity index 70% rename from gsm_at_lib/src/include/gsm/gsm_timeout.h rename to lwgsm/src/include/lwgsm/lwgsm_timeout.h index 2405d18b..26020e88 100644 --- a/gsm_at_lib/src/include/gsm/gsm_timeout.h +++ b/lwgsm/src/include/lwgsm/lwgsm_timeout.h @@ -1,10 +1,10 @@ -/** - * \file gsm_timeout.h +/** + * \file lwgsm_timeout.h * \brief Timeout manager */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,29 +26,29 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_TIMEOUT_H -#define GSM_HDR_TIMEOUT_H +#ifndef LWGSM_HDR_TIMEOUT_H +#define LWGSM_HDR_TIMEOUT_H + +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { -#endif - -#include "gsm/gsm.h" +#endif /* __cplusplus */ /** - * \ingroup GSM - * \defgroup GSM_TIMEOUT Timeout manager + * \ingroup LWGSM + * \defgroup LWGSM_TIMEOUT Timeout manager * \brief Timeout manager * \{ */ -gsmr_t gsm_timeout_add(uint32_t time, gsm_timeout_fn fn, void* arg); -gsmr_t gsm_timeout_remove(gsm_timeout_fn fn); +lwgsmr_t lwgsm_timeout_add(uint32_t time, lwgsm_timeout_fn fn, void* arg); +lwgsmr_t lwgsm_timeout_remove(lwgsm_timeout_fn fn); /** * \} @@ -56,6 +56,6 @@ gsmr_t gsm_timeout_remove(gsm_timeout_fn fn); #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif /* GSM_HDR_TIMEOUT_H */ +#endif /* LWGSM_HDR_TIMEOUT_H */ diff --git a/lwgsm/src/include/lwgsm/lwgsm_typedefs.h b/lwgsm/src/include/lwgsm/lwgsm_typedefs.h new file mode 100644 index 00000000..da2bf637 --- /dev/null +++ b/lwgsm/src/include/lwgsm/lwgsm_typedefs.h @@ -0,0 +1,635 @@ +/** + * \file lwgsm_typedefs.h + * \brief List of structures and enumerations for public usage + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_DEFS_H +#define LWGSM_HDR_DEFS_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * \ingroup LWGSM + * \defgroup LWGSM_TYPEDEFS Structures and enumerations + * \brief List of core structures and enumerations + * \{ + */ + +/** + * \} + */ + +/** + * \ingroup LWGSM_TYPEDEFS + * \brief Result enumeration used across application functions + */ +typedef enum { + lwgsmOK = 0, /*!< Function returned OK */ + lwgsmOKIGNOREMORE, /*!< Function succedded, should continue as \ref lwgsmOK + but ignore sending more data. + This result is possible on connection data receive callback */ + lwgsmERR, /*!< Generic error */ + lwgsmPARERR, /*!< Wrong parameters on function call */ + lwgsmERRMEM, /*!< Memory error occurred */ + lwgsmTIMEOUT, /*!< Timeout occurred on command */ + lwgsmCONT, /*!< There is still some command to be processed in current command */ + lwgsmCLOSED, /*!< Connection just closed */ + lwgsmINPROG, /*!< Operation is in progress */ + + lwgsmERRNOTENABLED, /*!< Feature not enabled error */ + lwgsmERRNOIP, /*!< Station does not have IP address */ + lwgsmERRNOFREECONN, /*!< There is no free connection available to start */ + lwgsmERRCONNTIMEOUT, /*!< Timeout received when connection to access point */ + lwgsmERRPASS, /*!< Invalid password for access point */ + lwgsmERRNOAP, /*!< No access point found with specific SSID and MAC address */ + lwgsmERRCONNFAIL, /*!< Connection failed to access point */ + lwgsmERRWIFINOTCONNECTED, /*!< Wifi not connected to access point */ + lwgsmERRNODEVICE, /*!< Device is not present */ + lwgsmERRBLOCKING, /*!< Blocking mode command is not allowed */ +} lwgsmr_t; + +/** + * \ingroup LWGSM_TYPEDEFS + * \brief GSM device model type + */ +typedef enum { +#define LWGSM_DEVICE_MODEL_ENTRY(name, str_id, is_2g, is_lte) LWGSM_DEVICE_MODEL_ ## name, +#include "lwgsm/lwgsm_models.h" + LWGSM_DEVICE_MODEL_END, /*!< End of device model */ + LWGSM_DEVICE_MODEL_UNKNOWN, /*!< Unknown device model */ +} lwgsm_device_model_t; + +/** + * \ingroup LWGSM_SIM + * \brief SIM state + */ +typedef enum { + LWGSM_SIM_STATE_NOT_INSERTED, /*!< SIM is not inserted in socket */ + LWGSM_SIM_STATE_READY, /*!< SIM is ready for operations */ + LWGSM_SIM_STATE_NOT_READY, /*!< SIM is not ready for any operation */ + LWGSM_SIM_STATE_PIN, /*!< SIM is waiting for SIM to be given */ + LWGSM_SIM_STATE_PUK, /*!< SIM is waiting for PUT to be given */ + LWGSM_SIM_STATE_PH_PIN, + LWGSM_SIM_STATE_PH_PUK, +} lwgsm_sim_state_t; + +/** + * \ingroup LWGSM_TYPEDEFS + * \brief IP structure + */ +typedef struct { + uint8_t ip[4]; /*!< IPv4 address */ +} lwgsm_ip_t; + +/** + * \ingroup LWGSM_TYPEDEFS + * \brief Port variable + */ +typedef uint16_t lwgsm_port_t; + +/** + * \ingroup LWGSM_TYPEDEFS + * \brief MAC address + */ +typedef struct { + uint8_t mac[6]; /*!< MAC address */ +} lwgsm_mac_t; + +/** + * \ingroup LWGSM_TYPEDEFS + * \brief Date and time structure + */ +typedef struct { + uint8_t date; /*!< Day in a month, from `1` to up to `31` */ + uint8_t month; /*!< Month in a year, from `1` to `12` */ + uint16_t year; /*!< Year */ + uint8_t day; /*!< Day in a week, from `1` to `7`, 0 = invalid */ + uint8_t hours; /*!< Hours in a day, from `0` to `23` */ + uint8_t minutes; /*!< Minutes in a hour, from `0` to `59` */ + uint8_t seconds; /*!< Seconds in a minute, from `0` to `59` */ +} lwgsm_datetime_t; + +/** + * \ingroup LWGSM_CONN + * \brief List of possible connection types + */ +typedef enum { + LWGSM_CONN_TYPE_TCP, /*!< Connection type is TCP */ + LWGSM_CONN_TYPE_UDP, /*!< Connection type is UDP */ + LWGSM_CONN_TYPE_SSL, /*!< Connection type is TCP over SSL */ +} lwgsm_conn_type_t; + +/** + * \ingroup LWGSM_TYPEDEFS + * \brief Available device memories + */ +typedef enum { +#define LWGSM_DEV_MEMORY_ENTRY(name, str_code) LWGSM_MEM_ ## name, +#include "lwgsm/lwgsm_memories.h" + LWGSM_MEM_END, /*!< End of memory list */ + LWGSM_MEM_CURRENT, /*!< Use current memory for read/delete operation */ + LWGSM_MEM_UNKNOWN = 0x1F, /*!< Unknown memory */ +} lwgsm_mem_t; + +/** + * \ingroup LWGSM_TYPEDEFS + * \brief GSM number type + */ +typedef enum { + LWGSM_NUMBER_TYPE_NATIONAL = 129, /*!< Number is national */ + LWGSM_NUMBER_TYPE_INTERNATIONAL = 145, /*!< Number is international */ +} lwgsm_number_type_t; + +/** + * \ingroup LWGSM_SMS + * \brief SMS status in current memory + */ +typedef enum { + LWGSM_SMS_STATUS_ALL, /*!< Process all SMS, used for mass delete or SMS list */ + LWGSM_SMS_STATUS_READ, /*!< SMS status is read */ + LWGSM_SMS_STATUS_UNREAD, /*!< SMS status is unread */ + LWGSM_SMS_STATUS_SENT, /*!< SMS status is sent */ + LWGSM_SMS_STATUS_UNSENT, /*!< SMS status is unsent */ + LWGSM_SMS_STATUS_INBOX, /*!< SMS status, used only for mass delete operation */ +} lwgsm_sms_status_t; + +/** + * \ingroup LWGSM_SMS + * \brief SMS entry structure + */ +typedef struct { + lwgsm_mem_t mem; /*!< Memory storage */ + size_t pos; /*!< Memory position */ + lwgsm_datetime_t datetime; /*!< Date and time */ + lwgsm_sms_status_t status; /*!< Message status */ + char number[26]; /*!< Phone number */ + char name[20]; /*!< Name in phonebook if exists */ + char data[161]; /*!< Data memory */ + size_t length; /*!< Length of SMS data */ +} lwgsm_sms_entry_t; + +/** + * \ingroup LWGSM_PB + * \brief Phonebook entry structure + */ +typedef struct { + lwgsm_mem_t mem; /*!< Memory position */ + size_t pos; /*!< Position in memory */ + char name[20]; /*!< Name of phonebook entry */ + char number[26]; /*!< Phone number */ + lwgsm_number_type_t type; /*!< Phone number type */ +} lwgsm_pb_entry_t; + +/** + * \ingroup LWGSM_OPERATOR + * \brief Operator status value + */ +typedef enum { + LWGSM_OPERATOR_STATUS_UNKNOWN = 0x00, /*!< Unknown operator */ + LWGSM_OPERATOR_STATUS_AVAILABLE, /*!< Operator is available */ + LWGSM_OPERATOR_STATUS_CURRENT, /*!< Operator is currently active */ + LWGSM_OPERATOR_STATUS_FORBIDDEN /*!< Operator is forbidden */ +} lwgsm_operator_status_t; + +/** + * \ingroup LWGSM_OPERATOR + * \brief Operator selection mode + */ +typedef enum { + LWGSM_OPERATOR_MODE_AUTO = 0x00, /*!< Operator automatic mode */ + LWGSM_OPERATOR_MODE_MANUAL = 0x01, /*!< Operator manual mode */ + LWGSM_OPERATOR_MODE_DEREGISTER = 0x02, /*!< Operator deregistered from network */ + LWGSM_OPERATOR_MODE_MANUAL_AUTO = 0x04, /*!< Operator manual mode first. If fails, auto mode enabled */ +} lwgsm_operator_mode_t; + +/** + * \ingroup LWGSM_OPERATOR + * \brief Operator data format + */ +typedef enum { + LWGSM_OPERATOR_FORMAT_LONG_NAME = 0x00, /*!< COPS command returned long name */ + LWGSM_OPERATOR_FORMAT_SHORT_NAME, /*!< COPS command returned short name */ + LWGSM_OPERATOR_FORMAT_NUMBER, /*!< COPS command returned number */ + LWGSM_OPERATOR_FORMAT_INVALID /*!< Unknown format */ +} lwgsm_operator_format_t; + +/** + * \ingroup LWGSM_OPERATOR + * \brief Operator details for scan + */ +typedef struct { + lwgsm_operator_status_t stat; /*!< Operator status */ + char long_name[20]; /*!< Operator long name */ + char short_name[20]; /*!< Operator short name */ + uint32_t num; /*!< Operator numeric value */ +} lwgsm_operator_t; + +/** + * \ingroup LWGSM_OPERATOR + * \brief Current operator info + */ +typedef struct { + lwgsm_operator_mode_t mode; /*!< Operator mode */ + lwgsm_operator_format_t format; /*!< Data format */ + union { + char long_name[20]; /*!< Long name format */ + char short_name[20]; /*!< Short name format */ + uint32_t num; /*!< Number format */ + } data; /*!< Operator data union */ +} lwgsm_operator_curr_t; + +/** + * \ingroup LWGSM_NETWORK + * \brief Network Registration status + */ +typedef enum { + LWGSM_NETWORK_REG_STATUS_SIM_ERR = 0x00, /*!< SIM card error */ + LWGSM_NETWORK_REG_STATUS_CONNECTED = 0x01, /*!< Device is connected to network */ + LWGSM_NETWORK_REG_STATUS_SEARCHING = 0x02, /*!< Network search is in progress */ + LWGSM_NETWORK_REG_STATUS_DENIED = 0x03, /*!< Registration denied */ + LWGSM_NETWORK_REG_STATUS_CONNECTED_ROAMING = 0x05, /*!< Device is connected and is roaming */ + LWGSM_NETWORK_REG_STATUS_CONNECTED_SMS_ONLY = 0x06, /*!< Device is connected to home network in SMS-only mode */ + LWGSM_NETWORK_REG_STATUS_CONNECTED_ROAMING_SMS_ONLY = 0x07 /*!< Device is roaming in SMS-only mode */ +} lwgsm_network_reg_status_t; + +/** + * \ingroup LWGSM_CALL + * \brief List of call directions + */ +typedef enum { + LWGSM_CALL_DIR_MO = 0x00, /*!< Mobile Originated, outgoing call */ + LWGSM_CALL_DIR_MT, /*!< Mobile Terminated, incoming call */ +} lwgsm_call_dir_t; + +/** + * \ingroup LWGSM_CALL + * \brief List of call states + */ +typedef enum { + LWGSM_CALL_STATE_ACTIVE = 0x00, /*!< Call is active */ + LWGSM_CALL_STATE_HELD, /*!< Call is held */ + LWGSM_CALL_STATE_DIALING, /*!< Call is dialing */ + LWGSM_CALL_STATE_ALERTING, /*!< Call is alerting */ + LWGSM_CALL_STATE_INCOMING, /*!< Call is incoming */ + LWGSM_CALL_STATE_WAITING, /*!< Call is waiting */ + LWGSM_CALL_STATE_DISCONNECT, /*!< Call disconnected, call finished */ +} lwgsm_call_state_t; + +/** + * \ingroup LWGSM_CALL + * \brief List of call types + */ +typedef enum { + LWGSM_CALL_TYPE_VOICE = 0x00, /*!< Voice call */ + LWGSM_CALL_TYPE_DATA, /*!< Data call */ + LWGSM_CALL_TYPE_FAX, /*!< Fax call */ +} lwgsm_call_type_t; + +/** + * \ingroup LWGSM_CALL + * \brief Call information + * \note Data received on `+CLCC` info + */ +typedef struct { + uint8_t ready; /*!< Flag indicating feature ready by device */ + uint8_t enabled; /*!< Flag indicating feature enabled */ + + uint8_t id; /*!< Call identification number, 0-7 */ + lwgsm_call_dir_t dir; /*!< Call direction */ + lwgsm_call_state_t state; /*!< Call state */ + lwgsm_call_type_t type; /*!< Call type */ + char number[20]; /*!< Phone number */ + char is_multipart; /*!< Multipart status */ + uint8_t addr_type; /*!< Address type */ + char name[20]; /*!< Phone book name if exists for current number */ +} lwgsm_call_t; + +/* Forward declarations */ +struct lwgsm_evt; +struct lwgsm_conn; +struct lwgsm_pbuf; + +/** + * \ingroup LWGSM_CONN + * \brief Pointer to \ref lwgsm_conn_t structure + */ +typedef struct lwgsm_conn* lwgsm_conn_p; + +/** + * \ingroup LWGSM_PBUF + * \brief Pointer to \ref lwgsm_pbuf_t structure + */ +typedef struct lwgsm_pbuf* lwgsm_pbuf_p; + +/** + * \ingroup LWGSM_EVT + * \brief Event function prototype + * \param[in] evt: Callback event data + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +typedef lwgsmr_t (*lwgsm_evt_fn)(struct lwgsm_evt* evt); + +/** + * \ingroup LWGSM_EVT + * \brief List of possible callback types received to user + */ +typedef enum lwgsm_cb_type_t { + LWGSM_EVT_INIT_FINISH, /*!< Initialization has been finished at this point */ + + LWGSM_EVT_RESET, /*!< Device reset operation finished */ + LWGSM_EVT_RESTORE, /*!< Device restore operation finished */ + + LWGSM_EVT_CMD_TIMEOUT, /*!< Timeout on command. + When application receives this event, + it may reset system as there was (maybe) a problem in device */ + + LWGSM_EVT_DEVICE_PRESENT, /*!< Notification when device present status changes */ + LWGSM_EVT_DEVICE_IDENTIFIED, /*!< Device identified event */ + + LWGSM_EVT_SIGNAL_STRENGTH, /*!< Signal strength event */ + + LWGSM_EVT_SIM_STATE_CHANGED, /*!< SIM card state changed */ + + LWGSM_EVT_OPERATOR_SCAN, /*!< Operator scan finished event */ + + LWGSM_EVT_NETWORK_OPERATOR_CURRENT, /*!< Current operator event */ + LWGSM_EVT_NETWORK_REG_CHANGED, /*!< Network registration changed. + Available even when \ref LWGSM_CFG_NETWORK is disabled */ +#if LWGSM_CFG_NETWORK || __DOXYGEN__ + LWGSM_EVT_NETWORK_ATTACHED, /*!< Attached to network, PDP context active and ready for TCP/IP application */ + LWGSM_EVT_NETWORK_DETACHED, /*!< Detached from network, PDP context not active anymore */ +#endif /* LWGSM_CFG_NETWORK || __DOXYGEN__ */ + +#if LWGSM_CFG_CONN || __DOXYGEN__ + LWGSM_EVT_CONN_RECV, /*!< Connection data received */ + LWGSM_EVT_CONN_SEND, /*!< Connection data send */ + LWGSM_EVT_CONN_ACTIVE, /*!< Connection just became active */ + LWGSM_EVT_CONN_ERROR, /*!< Client connection start was not successful */ + LWGSM_EVT_CONN_CLOSE, /*!< Connection close event. Check status if successful */ + LWGSM_EVT_CONN_POLL, /*!< Poll for connection if there are any changes */ +#endif /* LWGSM_CFG_CONN || __DOXYGEN__ */ + +#if LWGSM_CFG_SMS || __DOXYGEN__ + LWGSM_EVT_SMS_ENABLE, /*!< SMS enable event */ + LWGSM_EVT_SMS_READY, /*!< SMS ready event */ + LWGSM_EVT_SMS_SEND, /*!< SMS send event */ + LWGSM_EVT_SMS_RECV, /*!< SMS received */ + LWGSM_EVT_SMS_READ, /*!< SMS read */ + LWGSM_EVT_SMS_DELETE, /*!< SMS delete */ + LWGSM_EVT_SMS_LIST, /*!< SMS list */ +#endif /* LWGSM_CFG_SMS || __DOXYGEN__ */ +#if LWGSM_CFG_CALL || __DOXYGEN__ + LWGSM_EVT_CALL_ENABLE, /*!< Call enable event */ + LWGSM_EVT_CALL_READY, /*!< Call ready event */ + LWGSM_EVT_CALL_CHANGED, /*!< Call info changed, `+CLCK` statement received */ + LWGSM_EVT_CALL_RING, /*!< Call is ringing event */ + LWGSM_EVT_CALL_BUSY, /*!< Call is busy */ + LWGSM_EVT_CALL_NO_CARRIER, /*!< No carrier to make a call */ +#endif /* LWGSM_CFG_CALL || __DOXYGEN__ */ +#if LWGSM_CFG_PHONEBOOK || __DOXYGEN__ + LWGSM_EVT_PB_ENABLE, /*!< Phonebook enable event */ + LWGSM_EVT_PB_LIST, /*!< Phonebook list event */ + LWGSM_EVT_PB_SEARCH, /*!< Phonebook search event */ +#endif /* LWGSM_CFG_PHONEBOOK || __DOXYGEN__ */ +} lwgsm_evt_type_t; + +/** + * \ingroup LWGSM_EVT + * \brief Global callback structure to pass as parameter to callback function + */ +typedef struct lwgsm_evt { + lwgsm_evt_type_t type; /*!< Callback type */ + union { + struct { + lwgsmr_t res; /*!< Reset operation result */ + } reset; /*!< Reset sequence finish. Use with \ref LWGSM_EVT_RESET event */ + struct { + lwgsmr_t res; /*!< Restore operation result */ + } restore; /*!< Restore sequence finish. Use with \ref LWGSM_EVT_RESTORE event */ + + struct { + lwgsm_sim_state_t state; /*!< SIM state */ + } cpin; /*!< CPIN event */ + struct { + const lwgsm_operator_curr_t* operator_current; /*!< Current operator info */ + } operator_current; /*!< Current operator event. Use with \ref LWGSM_EVT_NETWORK_OPERATOR_CURRENT event */ + struct { + lwgsm_operator_t* ops; /*!< Pointer to operators */ + size_t opf; /*!< Number of operators found */ + lwgsmr_t res; /*!< Scan operation result */ + } operator_scan; /*!< Operator scan event. Use with \ref LWGSM_EVT_OPERATOR_SCAN event */ + + struct { + int16_t rssi; /*!< Strength in units of dBm */ + } rssi; /*!< Signal strength event. Use with \ref LWGSM_EVT_SIGNAL_STRENGTH event */ + +#if LWGSM_CFG_CONN || __DOXYGEN__ + struct { + lwgsm_conn_p conn; /*!< Connection where data were received */ + lwgsm_pbuf_p buff; /*!< Pointer to received data */ + } conn_data_recv; /*!< Network data received. Use with \ref LWGSM_EVT_CONN_RECV event */ + struct { + lwgsm_conn_p conn; /*!< Connection where data were sent */ + size_t sent; /*!< Number of bytes sent on connection */ + lwgsmr_t res; /*!< Send data result */ + } conn_data_send; /*!< Data successfully sent. Use with \ref LWGSM_EVT_CONN_SEND event */ + struct { + const char* host; /*!< Host to use for connection */ + lwgsm_port_t port; /*!< Remote port used for connection */ + lwgsm_conn_type_t type; /*!< Connection type */ + void* arg; /*!< Connection argument used on connection */ + lwgsmr_t err; /*!< Error value */ + } conn_error; /*!< Client connection start error. Use with \ref LWGSM_EVT_CONN_ERROR event */ + struct { + lwgsm_conn_p conn; /*!< Pointer to connection */ + uint8_t client; /*!< Set to `1` if connection is/was client mode */ + uint8_t forced; /*!< Set to `1` if connection action was forced */ + lwgsmr_t res; /*!< Result of close event. Set to \ref lwgsmOK on success. */ + } conn_active_close; /*!< Process active and closed statuses at the same time. Use with \ref LWGSM_EVT_CONN_ACTIVE or \ref LWGSM_EVT_CONN_CLOSE events */ + struct { + lwgsm_conn_p conn; /*!< Set connection pointer */ + } conn_poll; /*!< Polling active connection to check for timeouts. Use with \ref LWGSM_EVT_CONN_POLL event */ +#endif /* LWGSM_CFG_CONN || __DOXYGEN__ */ + +#if LWGSM_CFG_SMS || __DOXYGEN__ + struct { + lwgsmr_t status; /*!< Enable status */ + } sms_enable; /*!< SMS enable event. Use with \ref LWGSM_EVT_SMS_ENABLE event */ + struct { + size_t pos; /*!< Position in memory */ + lwgsmr_t res; /*!< SMS send result information */ + } sms_send; /*!< SMS sent info. Use with \ref LWGSM_EVT_SMS_SEND event */ + struct { + lwgsm_mem_t mem; /*!< Memory of received message */ + size_t pos; /*!< Received position in memory for sent SMS */ + } sms_recv; /*!< SMS received info. Use with \ref LWGSM_EVT_SMS_RECV event */ + struct { + lwgsm_sms_entry_t* entry; /*!< SMS entry */ + lwgsmr_t res; /*!< SMS read result information */ + } sms_read; /*!< SMS read. Use with \ref LWGSM_EVT_SMS_READ event */ + struct { + lwgsm_mem_t mem; /*!< Memory of deleted message */ + size_t pos; /*!< Deleted position in memory for sent SMS */ + lwgsmr_t res; /*!< Operation success */ + } sms_delete; /*!< SMS delete. Use with \ref LWGSM_EVT_SMS_DELETE event */ + struct { + lwgsm_mem_t mem; /*!< Memory used for scan */ + lwgsm_sms_entry_t* entries; /*!< Pointer to entries */ + size_t size; /*!< Number of valid entries */ + lwgsmr_t res; /*!< Result on command */ + } sms_list; /*!< SMS list. Use with \ref LWGSM_EVT_SMS_LIST event */ +#endif /* LWGSM_CFG_SMS || __DOXYGEN__ */ +#if LWGSM_CFG_CALL || __DOXYGEN__ + struct { + lwgsmr_t res; /*!< Enable status */ + } call_enable; /*!< Call enable event. Use with \ref LWGSM_EVT_CALL_ENABLE event */ + struct { + const lwgsm_call_t* call; /*!< Call information */ + } call_changed; /*!< Call changed info. Use with \ref LWGSM_EVT_CALL_CHANGED event */ +#endif /* LWGSM_CFG_CALL || __DOXYGEN__ */ +#if LWGSM_CFG_PHONEBOOK || __DOXYGEN__ + struct { + lwgsmr_t res; /*!< Enable status */ + } pb_enable; /*!< Phonebook enable event. Use with \ref LWGSM_EVT_PB_ENABLE event */ + struct { + lwgsm_mem_t mem; /*!< Memory used for scan */ + lwgsm_pb_entry_t* entries; /*!< Pointer to entries */ + size_t size; /*!< Number of valid entries */ + lwgsmr_t res; /*!< Operation success */ + } pb_list; /*!< Phonebok list. Use with \ref LWGSM_EVT_PB_LIST event */ + struct { + const char* search; /*!< Search string */ + lwgsm_mem_t mem; /*!< Memory used for scan */ + lwgsm_pb_entry_t* entries; /*!< Pointer to entries */ + size_t size; /*!< Number of valid entries */ + lwgsmr_t res; /*!< Operation success */ + } pb_search; /*!< Phonebok search list. Use with \ref LWGSM_EVT_PB_SEARCH event */ +#endif /* LWGSM_CFG_PHONEBOOK || __DOXYGEN__ */ + } evt; /*!< Callback event union */ +} lwgsm_evt_t; + +#define LWGSM_SIZET_MAX ((size_t)(-1)) /*!< Maximal value of size_t variable type */ + +/** + * \ingroup LWGSM_LL + * \brief Function prototype for AT output data + * \param[in] data: Pointer to data to send. This parameter can be set to `NULL` + * \param[in] len: Number of bytes to send. This parameter can be set to `0` + * to indicate that internal buffer can be flushed to stream. + * This is implementation defined and feature might be ignored + * \return Number of bytes sent + */ +typedef size_t (*lwgsm_ll_send_fn)(const void* data, size_t len); + +/** + * \ingroup LWGSM_LL + * \brief Function prototype for hardware reset of GSM device + * \param[in] state: State indicating reset. When set to `1`, reset must be active (usually pin active low), + * or set to `0` when reset is cleared + * \return `1` on successful action, `0` otherwise + */ +typedef uint8_t (*lwgsm_ll_reset_fn)(uint8_t state); + +/** + * \ingroup LWGSM_LL + * \brief Low level user specific functions + */ +typedef struct { + lwgsm_ll_send_fn send_fn; /*!< Callback function to transmit data */ + lwgsm_ll_reset_fn reset_fn; /*!< Reset callback function */ + struct { + uint32_t baudrate; /*!< UART baudrate value */ + } uart; /*!< UART communication parameters */ +} lwgsm_ll_t; + +/** + * \ingroup LWGSM_TIMEOUT + * \brief Timeout callback function prototype + * \param[in] arg: Custom user argument + */ +typedef void (*lwgsm_timeout_fn)(void* arg); + +/** + * \ingroup LWGSM_TIMEOUT + * \brief Timeout structure + */ +typedef struct lwgsm_timeout { + struct lwgsm_timeout* next; /*!< Pointer to next timeout entry */ + uint32_t time; /*!< Time difference from previous entry */ + void* arg; /*!< Argument to pass to callback function */ + lwgsm_timeout_fn fn; /*!< Callback function for timeout */ +} lwgsm_timeout_t; + +/** + * \ingroup LWGSM_BUFF + * \brief Buffer structure + */ +typedef struct { + uint8_t* buff; /*!< Pointer to buffer data. + Buffer is considered initialized when `buff != NULL` */ + size_t size; /*!< Size of buffer data. + Size of actual buffer is `1` byte less than this value */ + size_t r; /*!< Next read pointer. + Buffer is considered empty when `r == w` and full when `w == r - 1` */ + size_t w; /*!< Next write pointer. + Buffer is considered empty when `r == w` and full when `w == r - 1` */ +} lwgsm_buff_t; + +/** + * \ingroup LWGSM_TYPEDEFS + * \brief Linear buffer structure + */ +typedef struct { + uint8_t* buff; /*!< Pointer to buffer data array */ + size_t len; /*!< Length of buffer array */ + size_t ptr; /*!< Current buffer pointer */ +} lwgsm_linbuff_t; + +/** + * \ingroup LWGSM_TYPEDEFS + * \brief Function declaration for API function command event callback function + * \param[in] res: Operation result, member of \ref lwgsmr_t enumeration + * \param[in] arg: Custom user argument + */ +typedef void (*lwgsm_api_cmd_evt_fn)(lwgsmr_t res, void* arg); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LWGSM_HDR_DEFS_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_unicode.h b/lwgsm/src/include/lwgsm/lwgsm_unicode.h similarity index 73% rename from gsm_at_lib/src/include/gsm/gsm_unicode.h rename to lwgsm/src/include/lwgsm/lwgsm_unicode.h index 0a84ab70..2ab6d667 100644 --- a/gsm_at_lib/src/include/gsm/gsm_unicode.h +++ b/lwgsm/src/include/lwgsm/lwgsm_unicode.h @@ -1,10 +1,10 @@ -/** - * \file gsm_unicode.h +/** + * \file lwgsm_unicode.h * \brief Unicode support */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,28 +26,28 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_UNICODE_H -#define GSM_HDR_UNICODE_H +#ifndef LWGSM_HDR_UNICODE_H +#define LWGSM_HDR_UNICODE_H + +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { -#endif - -#include "gsm/gsm.h" +#endif /* __cplusplus */ /** - * \ingroup GSM - * \defgroup GSM_UNICODE Unicode manager + * \ingroup LWGSM + * \defgroup LWGSM_UNICODE Unicode manager * \brief Unicode support manager * \{ */ -gsmr_t gsmi_unicode_decode(gsm_unicode_t* uni, uint8_t ch); +lwgsmr_t lwgsmi_unicode_decode(lwgsm_unicode_t* uni, uint8_t ch); /** * \} @@ -55,6 +55,6 @@ gsmr_t gsmi_unicode_decode(gsm_unicode_t* uni, uint8_t ch); #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif /* GSM_HDR_UNICODE_H */ +#endif /* LWGSM_HDR_UNICODE_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_ussd.h b/lwgsm/src/include/lwgsm/lwgsm_ussd.h similarity index 70% rename from gsm_at_lib/src/include/gsm/gsm_ussd.h rename to lwgsm/src/include/lwgsm/lwgsm_ussd.h index 4ffd947c..26236d05 100644 --- a/gsm_at_lib/src/include/gsm/gsm_ussd.h +++ b/lwgsm/src/include/lwgsm/lwgsm_ussd.h @@ -1,10 +1,10 @@ -/** - * \file gsm_ussd.h +/** + * \file lwgsm_ussd.h * \brief Unstructured Supplementary Service Data */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,28 +26,28 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_USSD_H -#define GSM_HDR_USSD_H +#ifndef LWGSM_HDR_USSD_H +#define LWGSM_HDR_USSD_H + +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { -#endif - -#include "gsm/gsm.h" +#endif /* __cplusplus */ /** - * \ingroup GSM - * \defgroup GSM_USSD Unstructured Supplementary Service Data + * \ingroup LWGSM + * \defgroup LWGSM_USSD Unstructured Supplementary Service Data * \brief Unstructured Supplementary Service Data * \{ */ -gsmr_t gsm_ussd_run(const char* code, char* resp, size_t resp_len, const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); +lwgsmr_t lwgsm_ussd_run(const char* code, char* resp, size_t resp_len, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking); /** * \} @@ -55,6 +55,6 @@ gsmr_t gsm_ussd_run(const char* code, char* resp, size_t resp_len, const gsm_ap #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif /* GSM_HDR_HTTP_H */ +#endif /* LWGSM_HDR_HTTP_H */ diff --git a/gsm_at_lib/src/include/gsm/gsm_utils.h b/lwgsm/src/include/lwgsm/lwgsm_utils.h similarity index 69% rename from gsm_at_lib/src/include/gsm/gsm_utils.h rename to lwgsm/src/include/lwgsm/lwgsm_utils.h index 3c103b3d..eb850077 100644 --- a/gsm_at_lib/src/include/gsm/gsm_utils.h +++ b/lwgsm/src/include/lwgsm/lwgsm_utils.h @@ -1,10 +1,10 @@ /** - * \file gsm_utils.h + * \file lwgsm_utils.h * \brief Utilities */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,47 +26,47 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_UTILS_H -#define GSM_HDR_UTILS_H +#ifndef LWGSM_HDR_UTILS_H +#define LWGSM_HDR_UTILS_H + +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { -#endif - -#include "gsm/gsm.h" +#endif /* __cplusplus */ /** - * \ingroup GSM - * \defgroup GSM_UTILS Utilities + * \ingroup LWGSM + * \defgroup LWGSM_UTILS Utilities * \brief Utilities * \{ */ /** * \brief Assert an input parameter if in valid range - * \note Since this is a macro, it may only be used on a functions where return status is of type \ref gsmr_t enumeration + * \note Since this is a macro, it may only be used on a functions where return status is of type \ref lwgsmr_t enumeration * \param[in] msg: message to print to debug if test fails * \param[in] c: Condition to test */ -#define GSM_ASSERT(msg, c) do { \ - if (!(c)) { \ - GSM_DEBUGF(GSM_CFG_DBG_ASSERT, "Wrong parameters on file %s and line %d: %s\r\n", __FILE__, (int)__LINE__, msg);\ - return gsmPARERR; \ - } \ -} while (0) +#define LWGSM_ASSERT(msg, c) do { \ + if (!(c)) { \ + LWGSM_DEBUGF(LWGSM_CFG_DBG_ASSERT, "Wrong parameters on file %s and line %d: %s\r\n", __FILE__, (int)__LINE__, msg);\ + return lwgsmPARERR; \ + } \ + } while (0) /** - * \brief Align `x` value to specific number of bytes, provided by \ref GSM_CFG_MEM_ALIGNMENT configuration + * \brief Align `x` value to specific number of bytes, provided by \ref LWGSM_CFG_MEM_ALIGNMENT configuration * \param[in] x: Input value to align * \return Input value aligned to specific number of bytes * \hideinitializer */ -#define GSM_MEM_ALIGN(x) ((x + (GSM_CFG_MEM_ALIGNMENT - 1)) & ~(GSM_CFG_MEM_ALIGNMENT - 1)) +#define LWGSM_MEM_ALIGN(x) ((x + (LWGSM_CFG_MEM_ALIGNMENT - 1)) & ~(LWGSM_CFG_MEM_ALIGNMENT - 1)) /** * \brief Get minimal value between `x` and `y` inputs @@ -75,7 +75,7 @@ extern "C" { * \return Minimal value between `x` and `y` parameters * \hideinitializer */ -#define GSM_MIN(x, y) ((x) < (y) ? (x) : (y)) +#define LWGSM_MIN(x, y) ((x) < (y) ? (x) : (y)) /** * \brief Get maximal value between `x` and `y` inputs @@ -84,7 +84,7 @@ extern "C" { * \return Maximal value between `x` and `y` parameters * \hideinitializer */ -#define GSM_MAX(x, y) ((x) > (y) ? (x) : (y)) +#define LWGSM_MAX(x, y) ((x) > (y) ? (x) : (y)) /** * \brief Get size of statically declared array @@ -92,7 +92,7 @@ extern "C" { * \return Number of array elements * \hideinitializer */ -#define GSM_ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0])) +#define LWGSM_ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0])) /** * \brief Unused argument in a function call @@ -101,56 +101,56 @@ extern "C" { * \param[in] x: Variable which is not used * \hideinitializer */ -#define GSM_UNUSED(x) ((void)(x)) +#define LWGSM_UNUSED(x) ((void)(x)) /** * \brief Get input value casted to `unsigned 32-bit` value * \param[in] x: Input value * \hideinitializer */ -#define GSM_U32(x) ((uint32_t)(x)) +#define LWGSM_U32(x) ((uint32_t)(x)) /** * \brief Get input value casted to `unsigned 16-bit` value * \param[in] x: Input value * \hideinitializer */ -#define GSM_U16(x) ((uint16_t)(x)) +#define LWGSM_U16(x) ((uint16_t)(x)) /** * \brief Get input value casted to `unsigned 8-bit` value * \param[in] x: Input value * \hideinitializer */ -#define GSM_U8(x) ((uint8_t)(x)) +#define LWGSM_U8(x) ((uint8_t)(x)) /** * \brief Get input value casted to `signed 32-bit` value * \param[in] x: Input value * \hideinitializer */ -#define GSM_I32(x) ((int32_t)(x)) +#define LWGSM_I32(x) ((int32_t)(x)) /** * \brief Get input value casted to `signed 16-bit` value * \param[in] x: Input value * \hideinitializer */ -#define GSM_I16(x) ((int16_t)(x)) +#define LWGSM_I16(x) ((int16_t)(x)) /** * \brief Get input value casted to `signed 8-bit` value * \param[in] x: Input value * \hideinitializer */ -#define GSM_I8(x) ((int8_t)(x)) +#define LWGSM_I8(x) ((int8_t)(x)) /** * \brief Get input value casted to `size_t` value * \param[in] x: Input value * \hideinitializer */ -#define GSM_SZ(x) ((size_t)(x)) +#define LWGSM_SZ(x) ((size_t)(x)) /** * \brief Convert `unsigned 32-bit` number to string @@ -159,7 +159,7 @@ extern "C" { * \return Pointer to output variable * \hideinitializer */ -#define gsm_u32_to_str(num, out) gsm_u32_to_gen_str(GSM_U32(num), (out), 0, 0) +#define lwgsm_u32_to_str(num, out) lwgsm_u32_to_gen_str(LWGSM_U32(num), (out), 0, 0) /** * \brief Convert `unsigned 32-bit` number to HEX string @@ -170,7 +170,7 @@ extern "C" { * \return Pointer to output variable * \hideinitializer */ -#define gsm_u32_to_hex_str(num, out, w) gsm_u32_to_gen_str(GSM_U32(num), (out), 1, (w)) +#define lwgsm_u32_to_hex_str(num, out, w) lwgsm_u32_to_gen_str(LWGSM_U32(num), (out), 1, (w)) /** * \brief Convert `signed 32-bit` number to string @@ -179,7 +179,7 @@ extern "C" { * \return Pointer to output variable * \hideinitializer */ -#define gsm_i32_to_str(num, out) gsm_i32_to_gen_str(GSM_I32(num), (out)) +#define lwgsm_i32_to_str(num, out) lwgsm_i32_to_gen_str(LWGSM_I32(num), (out)) /** * \brief Convert `unsigned 16-bit` number to string @@ -188,7 +188,7 @@ extern "C" { * \return Pointer to output variable * \hideinitializer */ -#define gsm_u16_to_str(num, out) gsm_u32_to_gen_str(GSM_U32(GSM_U16(num)), (out), 0, 0) +#define lwgsm_u16_to_str(num, out) lwgsm_u32_to_gen_str(LWGSM_U32(LWGSM_U16(num)), (out), 0, 0) /** * \brief Convert `unsigned 16-bit` number to HEX string @@ -199,7 +199,7 @@ extern "C" { * \return Pointer to output variable * \hideinitializer */ -#define gsm_u16_to_hex_str(num, out, w) gsm_u32_to_gen_str(GSM_U32(GSM_U16(num)), (out), 1, (w)) +#define lwgsm_u16_to_hex_str(num, out, w) lwgsm_u32_to_gen_str(LWGSM_U32(LWGSM_U16(num)), (out), 1, (w)) /** * \brief Convert `signed 16-bit` number to string @@ -208,7 +208,7 @@ extern "C" { * \return Pointer to output variable * \hideinitializer */ -#define gsm_i16_to_str(num, out) gsm_i32_to_gen_str(GSM_I32(GSM_I16(num)), (out)) +#define lwgsm_i16_to_str(num, out) lwgsm_i32_to_gen_str(LWGSM_I32(LWGSM_I16(num)), (out)) /** * \brief Convert `unsigned 8-bit` number to string @@ -217,7 +217,7 @@ extern "C" { * \return Pointer to output variable * \hideinitializer */ -#define gsm_u8_to_str(num, out) gsm_u32_to_gen_str(GSM_U32(GSM_U8(num)), (out), 0, 0) +#define lwgsm_u8_to_str(num, out) lwgsm_u32_to_gen_str(LWGSM_U32(LWGSM_U8(num)), (out), 0, 0) /** * \brief Convert `unsigned 16-bit` number to HEX string @@ -228,7 +228,7 @@ extern "C" { * \return Pointer to output variable * \hideinitializer */ -#define gsm_u8_to_hex_str(num, out, w) gsm_u32_to_gen_str(GSM_U32(GSM_U8(num)), (out), 1, (w)) +#define lwgsm_u8_to_hex_str(num, out, w) lwgsm_u32_to_gen_str(LWGSM_U32(LWGSM_U8(num)), (out), 1, (w)) /** * \brief Convert `signed 8-bit` number to string @@ -237,10 +237,10 @@ extern "C" { * \return Pointer to output variable * \hideinitializer */ -#define gsm_i8_to_str(num, out) gsm_i32_to_gen_str(GSM_I32(GSM_I8(num)), (out)) +#define lwgsm_i8_to_str(num, out) lwgsm_i32_to_gen_str(LWGSM_I32(LWGSM_I8(num)), (out)) -char * gsm_u32_to_gen_str(uint32_t num, char* out, uint8_t is_hex, uint8_t padding); -char * gsm_i32_to_gen_str(int32_t num, char* out); +char* lwgsm_u32_to_gen_str(uint32_t num, char* out, uint8_t is_hex, uint8_t padding); +char* lwgsm_i32_to_gen_str(int32_t num, char* out); /** * \} @@ -248,6 +248,6 @@ char * gsm_i32_to_gen_str(int32_t num, char* out); #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif /* GSM_HDR_UTILITIES_H */ +#endif /* LWGSM_HDR_UTILITIES_H */ diff --git a/gsm_at_lib/src/include/system/gsm_ll.h b/lwgsm/src/include/system/lwgsm_ll.h similarity index 78% rename from gsm_at_lib/src/include/system/gsm_ll.h rename to lwgsm/src/include/system/lwgsm_ll.h index 793f966e..2a14c2c9 100644 --- a/gsm_at_lib/src/include/system/gsm_ll.h +++ b/lwgsm/src/include/system/lwgsm_ll.h @@ -1,10 +1,10 @@ /** - * \file gsm_ll.h + * \file lwgsm_ll.h * \brief Low-level communication implementation */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,29 +26,28 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_LL_H -#define GSM_HDR_LL_H +#ifndef LWGSM_HDR_LL_H +#define LWGSM_HDR_LL_H + +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -#include "gsm/gsm.h" - /** - * \ingroup GSM_PORT - * \defgroup GSM_LL Low-level functions + * \defgroup LWGSM_LL Low-level functions * \brief Low-level communication functions * \{ */ -gsmr_t gsm_ll_init(gsm_ll_t* ll); -gsmr_t gsm_ll_deinit(gsm_ll_t* ll); +lwgsmr_t lwgsm_ll_init(lwgsm_ll_t* ll); +lwgsmr_t lwgsm_ll_deinit(lwgsm_ll_t* ll); /** * \} @@ -58,4 +57,4 @@ gsmr_t gsm_ll_deinit(gsm_ll_t* ll); } #endif /* __cplusplus */ -#endif /* GSM_HDR_LL_H */ +#endif /* LWGSM_HDR_LL_H */ diff --git a/lwgsm/src/include/system/lwgsm_sys.h b/lwgsm/src/include/system/lwgsm_sys.h new file mode 100644 index 00000000..11ad52ad --- /dev/null +++ b/lwgsm/src/include/system/lwgsm_sys.h @@ -0,0 +1,144 @@ +/** + * \file lwgsm_sys.h + * \brief Main system include file which decides later include file + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_MAIN_SYS_H +#define LWGSM_HDR_MAIN_SYS_H + +#include +#include "lwgsm/lwgsm_opt.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * \defgroup LWGSM_SYS System functions + * \brief System based function for OS management, timings, etc + * \{ + */ + +/** + * \brief Thread function prototype + */ +typedef void (*lwgsm_sys_thread_fn)(void*); + +/* Include system port file from portable folder */ +#include "lwgsm_sys_port.h" + +/** + * \anchor LWGSM_SYS_CORE + * \name Main + */ + +uint8_t lwgsm_sys_init(void); +uint32_t lwgsm_sys_now(void); + +uint8_t lwgsm_sys_protect(void); +uint8_t lwgsm_sys_unprotect(void); + +/** + * \} + */ + +/** + * \anchor LWGSM_SYS_MUTEX + * \name Mutex + */ + +uint8_t lwgsm_sys_mutex_create(lwgsm_sys_mutex_t* p); +uint8_t lwgsm_sys_mutex_delete(lwgsm_sys_mutex_t* p); +uint8_t lwgsm_sys_mutex_lock(lwgsm_sys_mutex_t* p); +uint8_t lwgsm_sys_mutex_unlock(lwgsm_sys_mutex_t* p); +uint8_t lwgsm_sys_mutex_isvalid(lwgsm_sys_mutex_t* p); +uint8_t lwgsm_sys_mutex_invalid(lwgsm_sys_mutex_t* p); + +/** + * \} + */ + +/** + * \anchor LWGSM_SYS_SEM + * \name Semaphores + */ + +uint8_t lwgsm_sys_sem_create(lwgsm_sys_sem_t* p, uint8_t cnt); +uint8_t lwgsm_sys_sem_delete(lwgsm_sys_sem_t* p); +uint32_t lwgsm_sys_sem_wait(lwgsm_sys_sem_t* p, uint32_t timeout); +uint8_t lwgsm_sys_sem_release(lwgsm_sys_sem_t* p); +uint8_t lwgsm_sys_sem_isvalid(lwgsm_sys_sem_t* p); +uint8_t lwgsm_sys_sem_invalid(lwgsm_sys_sem_t* p); + +/** + * \} + */ + +/** + * \anchor LWGSM_SYS_MBOX + * \name Message queues + */ + +uint8_t lwgsm_sys_mbox_create(lwgsm_sys_mbox_t* b, size_t size); +uint8_t lwgsm_sys_mbox_delete(lwgsm_sys_mbox_t* b); +uint32_t lwgsm_sys_mbox_put(lwgsm_sys_mbox_t* b, void* m); +uint32_t lwgsm_sys_mbox_get(lwgsm_sys_mbox_t* b, void** m, uint32_t timeout); +uint8_t lwgsm_sys_mbox_putnow(lwgsm_sys_mbox_t* b, void* m); +uint8_t lwgsm_sys_mbox_getnow(lwgsm_sys_mbox_t* b, void** m); +uint8_t lwgsm_sys_mbox_isvalid(lwgsm_sys_mbox_t* b); +uint8_t lwgsm_sys_mbox_invalid(lwgsm_sys_mbox_t* b); + +/** + * \} + */ + +/** + * \anchor LWGSM_SYS_THREAD + * \name Threads + */ + +uint8_t lwgsm_sys_thread_create(lwgsm_sys_thread_t* t, const char* name, lwgsm_sys_thread_fn thread_func, void* const arg, size_t stack_size, lwgsm_sys_thread_prio_t prio); +uint8_t lwgsm_sys_thread_terminate(lwgsm_sys_thread_t* t); +uint8_t lwgsm_sys_thread_yield(void); + +/** + * \} + */ + +/** + * \} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LWGSM_HDR_MAIN_LL_H */ diff --git a/gsm_at_lib/src/include/system/gsm_sys_cmsis_os.h b/lwgsm/src/include/system/port/cmsis_os/lwgsm_sys_port.h similarity index 55% rename from gsm_at_lib/src/include/system/gsm_sys_cmsis_os.h rename to lwgsm/src/include/system/port/cmsis_os/lwgsm_sys_port.h index 4a3aeccc..3c773989 100644 --- a/gsm_at_lib/src/include/system/gsm_sys_cmsis_os.h +++ b/lwgsm/src/include/system/port/cmsis_os/lwgsm_sys_port.h @@ -1,10 +1,10 @@ -/** - * \file gsm_sys_cmsis_os.h - * \brief CMSIS-OS based system file +/** + * \file lwgsm_sys_port.h + * \brief System dependent functions for CMSIS-OS based operating system */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,43 +26,42 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_SYSTEM_CMSIS_OS_H -#define GSM_HDR_SYSTEM_CMSIS_OS_H +#ifndef LWGSM_HDR_SYSTEM_PORT_H +#define LWGSM_HDR_SYSTEM_PORT_H + +#include +#include +#include "lwgsm/lwgsm_opt.h" +#include "cmsis_os.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -#include -#include +#if LWGSM_CFG_OS && !__DOXYGEN__ -#include "gsm_config.h" -#include "gsm_sys.h" - -#if GSM_CFG_OS && !__DOXYGEN__ -#include "cmsis_os.h" +typedef osMutexId_t lwgsm_sys_mutex_t; +typedef osSemaphoreId_t lwgsm_sys_sem_t; +typedef osMessageQueueId_t lwgsm_sys_mbox_t; +typedef osThreadId_t lwgsm_sys_thread_t; +typedef osPriority_t lwgsm_sys_thread_prio_t; -typedef osMutexId gsm_sys_mutex_t; -typedef osSemaphoreId gsm_sys_sem_t; -typedef osMessageQId gsm_sys_mbox_t; -typedef osThreadId gsm_sys_thread_t; -typedef osPriority gsm_sys_thread_prio_t; -#define GSM_SYS_MBOX_NULL (gsm_sys_mbox_t)0 -#define GSM_SYS_SEM_NULL (gsm_sys_sem_t)0 -#define GSM_SYS_MUTEX_NULL (gsm_sys_mutex_t)0 -#define GSM_SYS_TIMEOUT ((uint32_t)osWaitForever) -#define GSM_SYS_THREAD_PRIO (osPriorityNormal) -#define GSM_SYS_THREAD_SS (512) +#define LWGSM_SYS_MUTEX_NULL ((lwgsm_sys_mutex_t)0) +#define LWGSM_SYS_SEM_NULL ((lwgsm_sys_sem_t)0) +#define LWGSM_SYS_MBOX_NULL ((lwgsm_sys_mbox_t)0) +#define LWGSM_SYS_TIMEOUT ((uint32_t)osWaitForever) +#define LWGSM_SYS_THREAD_PRIO (osPriorityNormal) +#define LWGSM_SYS_THREAD_SS (512) -#endif /* GSM_CFG_OS && !__DOXYGEN__ */ +#endif /* LWGSM_CFG_OS && !__DOXYGEN__ */ #ifdef __cplusplus -}; +} #endif /* __cplusplus */ -#endif /* GSM_HDR_SYSTEM_CMSIS_OS_H */ +#endif /* LWGSM_HDR_SYSTEM_PORT_H */ diff --git a/lwgsm/src/include/system/port/template/lwgsm_sys_port.h b/lwgsm/src/include/system/port/template/lwgsm_sys_port.h new file mode 100644 index 00000000..75c41f14 --- /dev/null +++ b/lwgsm/src/include/system/port/template/lwgsm_sys_port.h @@ -0,0 +1,143 @@ +/** + * \file lwgsm_sys_port.h + * \brief Template file for system functions + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#ifndef LWGSM_HDR_SYSTEM_PORT_H +#define LWGSM_HDR_SYSTEM_PORT_H + +#include +#include +#include "lwgsm/lwgsm_opt.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * \addtogroup LWGSM_SYS + * \{ + */ + +#if LWGSM_CFG_OS || __DOXYGEN__ + +/* Include any OS specific features */ +#include "cmsis_os.h" + +/** + * \brief System mutex type + * + * It is used by middleware as base type of mutex. + */ +typedef osMutexId_t lwgsm_sys_mutex_t; + +/** + * \brief System semaphore type + * + * It is used by middleware as base type of mutex. + */ +typedef osSemaphoreId_t lwgsm_sys_sem_t; + +/** + * \brief System message queue type + * + * It is used by middleware as base type of mutex. + */ +typedef osMessageQueueId_t lwgsm_sys_mbox_t; + +/** + * \brief System thread ID type + */ +typedef osThreadId_t lwgsm_sys_thread_t; + +/** + * \brief System thread priority type + * + * It is used as priority type for system function, + * to start new threads by middleware. + */ +typedef osPriority lwgsm_sys_thread_prio_t; + +/** + * \brief Mutex invalid value + * + * Value assigned to \ref lwgsm_sys_mutex_t type when it is not valid. + */ +#define LWGSM_SYS_MUTEX_NULL ((lwgsm_sys_mutex_t)0) + +/** + * \brief Semaphore invalid value + * + * Value assigned to \ref lwgsm_sys_sem_t type when it is not valid. + */ +#define LWGSM_SYS_SEM_NULL ((lwgsm_sys_sem_t)0) + +/** + * \brief Message box invalid value + * + * Value assigned to \ref lwgsm_sys_mbox_t type when it is not valid. + */ +#define LWGSM_SYS_MBOX_NULL ((lwgsm_sys_mbox_t)0) + +/** + * \brief OS timeout value + * + * Value returned by operating system functions (mutex wait, sem wait, mbox wait) + * when it returns timeout and does not give valid value to application + */ +#define LWGSM_SYS_TIMEOUT ((uint32_t)osWaitForever) + +/** + * \brief Default thread priority value used by middleware to start built-in threads + * + * Threads can well operate with normal (default) priority and do not require + * any special feature in terms of priority for prioer operation. + */ +#define LWGSM_SYS_THREAD_PRIO (osPriorityNormal) + +/** + * \brief Stack size in units of bytes for system threads + * + * It is used as default stack size for all built-in threads. + */ +#define LWGSM_SYS_THREAD_SS (1024) + +#endif /* LWGSM_CFG_OS || __DOXYGEN__ */ + +/** + * \} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LWGSM_HDR_SYSTEM_PORT_H */ diff --git a/gsm_at_lib/src/include/system/gsm_sys_win32.h b/lwgsm/src/include/system/port/win32/lwgsm_sys_port.h similarity index 59% rename from gsm_at_lib/src/include/system/gsm_sys_win32.h rename to lwgsm/src/include/system/port/win32/lwgsm_sys_port.h index 1a837fdf..8276f751 100644 --- a/gsm_at_lib/src/include/system/gsm_sys_win32.h +++ b/lwgsm/src/include/system/port/win32/lwgsm_sys_port.h @@ -1,10 +1,10 @@ -/** - * \file gsm_sys_win32.h +/** + * \file lwgsm_sys_port.h * \brief WIN32 based system file implementation */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,42 +26,42 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#ifndef GSM_HDR_SYSTEM_WIN32_H -#define GSM_HDR_SYSTEM_WIN32_H +#ifndef LWGSM_HDR_SYSTEM_PORT_H +#define LWGSM_HDR_SYSTEM_PORT_H + +#include +#include +#include "lwgsm/lwgsm_opt.h" +#include "windows.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -#include -#include - -#include "gsm_config.h" -#include "windows.h" +#if LWGSM_CFG_OS && !__DOXYGEN__ -#if GSM_CFG_OS && !__DOXYGEN__ +typedef HANDLE lwgsm_sys_mutex_t; +typedef HANDLE lwgsm_sys_sem_t; +typedef HANDLE lwgsm_sys_mbox_t; +typedef HANDLE lwgsm_sys_thread_t; +typedef int lwgsm_sys_thread_prio_t; -typedef HANDLE gsm_sys_mutex_t; -typedef HANDLE gsm_sys_sem_t; -typedef HANDLE gsm_sys_mbox_t; -typedef HANDLE gsm_sys_thread_t; -typedef int gsm_sys_thread_prio_t; -#define GSM_SYS_MBOX_NULL (HANDLE)0 -#define GSM_SYS_SEM_NULL (HANDLE)0 -#define GSM_SYS_MUTEX_NULL (HANDLE)0 -#define GSM_SYS_TIMEOUT (INFINITE) -#define GSM_SYS_THREAD_PRIO (0) -#define GSM_SYS_THREAD_SS (4096) +#define LWGSM_SYS_MUTEX_NULL ((HANDLE)0) +#define LWGSM_SYS_SEM_NULL ((HANDLE)0) +#define LWGSM_SYS_MBOX_NULL ((HANDLE)0) +#define LWGSM_SYS_TIMEOUT (INFINITE) +#define LWGSM_SYS_THREAD_PRIO (0) +#define LWGSM_SYS_THREAD_SS (4096) -#endif /* GSM_CFG_OS && !__DOXYGEN__ */ +#endif /* LWGSM_CFG_OS && !__DOXYGEN__ */ #ifdef __cplusplus -}; +} #endif /* __cplusplus */ -#endif /* GSM_HDR_SYSTEM_WIN32_H */ +#endif /* LWGSM_HDR_SYSTEM_PORT_H */ diff --git a/lwgsm/src/lwgsm/lwgsm.c b/lwgsm/src/lwgsm/lwgsm.c new file mode 100644 index 00000000..3213be33 --- /dev/null +++ b/lwgsm/src/lwgsm/lwgsm.c @@ -0,0 +1,334 @@ +/** + * \file lwgsm.c + * \brief Main GSM core file + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_mem.h" +#include "lwgsm/lwgsm_threads.h" +#include "system/lwgsm_ll.h" + +#if LWGSM_CFG_OS != 1 +#error LWGSM_CFG_OS must be set to 1! +#endif + +static lwgsmr_t def_callback(lwgsm_evt_t* cb); +static lwgsm_evt_func_t def_evt_link; + +lwgsm_t lwgsm; + +/** + * \brief Default callback function for events + * \param[in] evt: Pointer to callback data structure + * \return Member of \ref lwgsmr_t enumeration + */ +static lwgsmr_t +def_callback(lwgsm_evt_t* evt) { + LWGSM_UNUSED(evt); + return lwgsmOK; +} + +/** + * \brief Init and prepare GSM stack for device operation + * \note Function must be called from operating system thread context. + * It creates necessary threads and waits them to start, thus running operating system is important. + * - When \ref LWGSM_CFG_RESET_ON_INIT is enabled, reset sequence will be sent to device + * otherwise manual call to \ref lwgsm_reset is required to setup device + * + * \param[in] evt_func: Global event callback function for all major events + * \param[in] blocking: Status whether command should be blocking or not. + * Used when \ref LWGSM_CFG_RESET_ON_INIT is enabled. + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsm_init(lwgsm_evt_fn evt_func, const uint32_t blocking) { + lwgsmr_t res = lwgsmOK; + + lwgsm.status.f.initialized = 0; /* Clear possible init flag */ + + def_evt_link.fn = evt_func != NULL ? evt_func : def_callback; + lwgsm.evt_func = &def_evt_link; /* Set callback function */ + + if (!lwgsm_sys_init()) { /* Init low-level system */ + goto cleanup; + } + + if (!lwgsm_sys_sem_create(&lwgsm.sem_sync, 1)) {/* Create sync semaphore between threads */ + LWGSM_DEBUGF(LWGSM_CFG_DBG_INIT | LWGSM_DBG_LVL_SEVERE | LWGSM_DBG_TYPE_TRACE, + "[CORE] Cannot allocate sync semaphore!\r\n"); + goto cleanup; + } + + /* Create message queues */ + if (!lwgsm_sys_mbox_create(&lwgsm.mbox_producer, LWGSM_CFG_THREAD_PRODUCER_MBOX_SIZE)) { + LWGSM_DEBUGF(LWGSM_CFG_DBG_INIT | LWGSM_DBG_LVL_SEVERE | LWGSM_DBG_TYPE_TRACE, + "[CORE] Cannot allocate producer mbox queue!\r\n"); + goto cleanup; + } + if (!lwgsm_sys_mbox_create(&lwgsm.mbox_process, LWGSM_CFG_THREAD_PROCESS_MBOX_SIZE)) { + LWGSM_DEBUGF(LWGSM_CFG_DBG_INIT | LWGSM_DBG_LVL_SEVERE | LWGSM_DBG_TYPE_TRACE, + "[CORE] Cannot allocate process mbox queue!\r\n"); + goto cleanup; + } + + /* Create threads */ + lwgsm_sys_sem_wait(&lwgsm.sem_sync, 0); + if (!lwgsm_sys_thread_create(&lwgsm.thread_produce, "lwgsm_produce", lwgsm_thread_produce, &lwgsm.sem_sync, LWGSM_SYS_THREAD_SS, LWGSM_SYS_THREAD_PRIO)) { + LWGSM_DEBUGF(LWGSM_CFG_DBG_INIT | LWGSM_DBG_LVL_SEVERE | LWGSM_DBG_TYPE_TRACE, + "[CORE] Cannot create producing thread!\r\n"); + lwgsm_sys_sem_release(&lwgsm.sem_sync); /* Release semaphore and return */ + goto cleanup; + } + lwgsm_sys_sem_wait(&lwgsm.sem_sync, 0); /* Wait semaphore, should be unlocked in produce thread */ + if (!lwgsm_sys_thread_create(&lwgsm.thread_process, "lwgsm_process", lwgsm_thread_process, &lwgsm.sem_sync, LWGSM_SYS_THREAD_SS, LWGSM_SYS_THREAD_PRIO)) { + LWGSM_DEBUGF(LWGSM_CFG_DBG_INIT | LWGSM_DBG_LVL_SEVERE | LWGSM_DBG_TYPE_TRACE, + "[CORE] Cannot create processing thread!\r\n"); + lwgsm_sys_thread_terminate(&lwgsm.thread_produce); /* Delete produce thread */ + lwgsm_sys_sem_release(&lwgsm.sem_sync); /* Release semaphore and return */ + goto cleanup; + } + lwgsm_sys_sem_wait(&lwgsm.sem_sync, 0); /* Wait semaphore, should be unlocked in produce thread */ + lwgsm_sys_sem_release(&lwgsm.sem_sync); /* Release semaphore manually */ + + lwgsm_core_lock(); + lwgsm.ll.uart.baudrate = LWGSM_CFG_AT_PORT_BAUDRATE; + lwgsm_ll_init(&lwgsm.ll); /* Init low-level communication */ + +#if !LWGSM_CFG_INPUT_USE_PROCESS + lwgsm_buff_init(&lwgsm.buff, LWGSM_CFG_RCV_BUFF_SIZE); /* Init buffer for input data */ +#endif /* !LWGSM_CFG_INPUT_USE_PROCESS */ + + lwgsm.status.f.initialized = 1; /* We are initialized now */ + lwgsm.status.f.dev_present = 1; /* We assume device is present at this point */ + + lwgsmi_send_cb(LWGSM_EVT_INIT_FINISH); /* Call user callback function */ + + /* + * Call reset command and call default + * AT commands to prepare basic setup for device + */ +#if LWGSM_CFG_RESET_ON_INIT + if (lwgsm.status.f.dev_present) { + lwgsm_core_unlock(); + res = lwgsm_reset_with_delay(LWGSM_CFG_RESET_DELAY_DEFAULT, NULL, NULL, blocking); /* Send reset sequence with delay */ + lwgsm_core_lock(); + } +#else /* LWGSM_CFG_RESET_ON_INIT */ + LWGSM_UNUSED(blocking); +#endif /* !LWGSM_CFG_RESET_ON_INIT */ + lwgsm_core_unlock(); + + return res; + +cleanup: + if (lwgsm_sys_mbox_isvalid(&lwgsm.mbox_producer)) { + lwgsm_sys_mbox_delete(&lwgsm.mbox_producer); + lwgsm_sys_mbox_invalid(&lwgsm.mbox_producer); + } + if (lwgsm_sys_mbox_isvalid(&lwgsm.mbox_process)) { + lwgsm_sys_mbox_delete(&lwgsm.mbox_process); + lwgsm_sys_mbox_invalid(&lwgsm.mbox_process); + } + if (lwgsm_sys_sem_isvalid(&lwgsm.sem_sync)) { + lwgsm_sys_sem_delete(&lwgsm.sem_sync); + lwgsm_sys_sem_invalid(&lwgsm.sem_sync); + } + return lwgsmERRMEM; +} + +/** + * \brief Execute reset and send default commands + * \param[in] evt_fn: Callback function called when command is finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsm_reset(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + return lwgsm_reset_with_delay(0, evt_fn, evt_arg, blocking); +} + +/** + * \brief Execute reset and send default commands with delay + * \param[in] delay: Number of milliseconds to wait before initiating first command to device + * \param[in] evt_fn: Callback function called when command is finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsm_reset_with_delay(uint32_t delay, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_RESET; + LWGSM_MSG_VAR_REF(msg).msg.reset.delay = delay; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); +} + +/** + * \brief Lock stack from multi-thread access, enable atomic access to core + * + * If lock was `0` prior function call, lock is enabled and increased + * + * \note Function may be called multiple times to increase locks. + * Application must take care to call \ref lwgsm_core_unlock + * the same amount of time to make sure lock gets back to `0` + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsm_core_lock(void) { + lwgsm_sys_protect(); + ++lwgsm.locked_cnt; + return lwgsmOK; +} + +/** + * \brief Unlock stack for multi-thread access + * + * Used in conjunction with \ref lwgsm_core_lock function + * + * If lock was non-zero before function call, lock is decreased. + * When `lock == 0`, protection is disabled and other threads may access to core + * + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsm_core_unlock(void) { + --lwgsm.locked_cnt; + lwgsm_sys_unprotect(); + return lwgsmOK; +} + +/** + * \brief Delay for amount of milliseconds + * + * Delay is based on operating system semaphores. + * It locks semaphore and waits for timeout in `ms` time. + * Based on operating system, thread may be put to \e blocked list during delay and may improve execution speed + * + * \param[in] ms: Milliseconds to delay + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_delay(uint32_t ms) { + lwgsm_sys_sem_t sem; + if (ms == 0) { + return 1; + } + if (lwgsm_sys_sem_create(&sem, 0)) { + lwgsm_sys_sem_wait(&sem, ms); + lwgsm_sys_sem_release(&sem); + lwgsm_sys_sem_delete(&sem); + return 1; + } + return 0; +} + +/** + * \brief Set modem function mode + * \note Use this function to set modem to normal or low-power mode + * \param[in] mode: Mode status. Set to `1` for full functionality or `0` for low-power mode (no functionality) + * \param[in] evt_fn: Callback function called when command is finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsm_set_func_mode(uint8_t mode, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CFUN_SET; + LWGSM_MSG_VAR_REF(msg).msg.cfun.mode = mode; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); +} + +/** + * \brief Notify stack if device is present or not + * + * Use this function to notify stack that device is not physically connected + * and not ready to communicate with host device + * + * \param[in] present: Flag indicating device is present + * \param[in] evt_fn: Callback function called when command is finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsm_device_set_present(uint8_t present, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + lwgsmr_t res = lwgsmOK; + lwgsm_core_lock(); + present = present ? 1 : 0; + if (present != lwgsm.status.f.dev_present) { + lwgsm.status.f.dev_present = present; + + if (!lwgsm.status.f.dev_present) { + /* Manually reset stack to default device state */ + lwgsmi_reset_everything(1); + } else { +#if LWGSM_CFG_RESET_ON_DEVICE_PRESENT + lwgsm_core_unlock(); + res = lwgsm_reset_with_delay(LWGSM_CFG_RESET_DELAY_DEFAULT, evt_fn, evt_arg, blocking); /* Reset with delay */ + lwgsm_core_lock(); +#endif /* LWGSM_CFG_RESET_ON_DEVICE_PRESENT */ + } + lwgsmi_send_cb(LWGSM_EVT_DEVICE_PRESENT); /* Send present event */ + } + lwgsm_core_unlock(); + + LWGSM_UNUSED(evt_fn); + LWGSM_UNUSED(evt_arg); + LWGSM_UNUSED(blocking); + + return res; +} + +/** + * \brief Check if device is present + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_device_is_present(void) { + uint8_t res; + lwgsm_core_lock(); + res = lwgsm.status.f.dev_present; + lwgsm_core_unlock(); + return res; +} diff --git a/gsm_at_lib/src/gsm/gsm_buff.c b/lwgsm/src/lwgsm/lwgsm_buff.c similarity index 94% rename from gsm_at_lib/src/gsm/gsm_buff.c rename to lwgsm/src/lwgsm/lwgsm_buff.c index 8c530c34..4a93604d 100644 --- a/gsm_at_lib/src/gsm/gsm_buff.c +++ b/lwgsm/src/lwgsm/lwgsm_buff.c @@ -1,10 +1,10 @@ -/** - * \file gsm_buff.c +/** + * \file lwgsm_buff.c * \brief Ring buffer manager */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,23 +26,23 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_buff.h" -#include "gsm/gsm_mem.h" +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_buff.h" +#include "lwgsm/lwgsm_mem.h" /* --- Buffer unique part starts --- */ /* Prefix for all buffer functions and typedefs */ -#define BUF_PREF(x) gsm_ ## x +#define BUF_PREF(x) lwgsm_ ## x /* --- Buffer unique part ends --- */ /* Buffer utility macros */ -#define BUF_MEMSET GSM_MEMSET -#define BUF_MEMCPY GSM_MEMCPY +#define BUF_MEMSET LWGSM_MEMSET +#define BUF_MEMCPY LWGSM_MEMCPY #define BUF_IS_VALID(b) ((b) != NULL && (b)->buff != NULL && (b)->size > 0) #define BUF_MIN(x, y) ((x) < (y) ? (x) : (y)) #define BUF_MAX(x, y) ((x) > (y) ? (x) : (y)) @@ -61,7 +61,7 @@ BUF_PREF(buff_init)(BUF_PREF(buff_t)* buff, size_t size) { BUF_MEMSET(buff, 0, sizeof(*buff)); buff->size = size; /* Set default values */ - buff->buff = gsm_mem_malloc(sizeof(*buff->buff) * size);/* Allocate memory for buffer */ + buff->buff = lwgsm_mem_malloc(sizeof(*buff->buff) * size); /* Allocate memory for buffer */ if (buff->buff == NULL) { /* Check allocation */ return 0; @@ -76,7 +76,7 @@ BUF_PREF(buff_init)(BUF_PREF(buff_t)* buff, size_t size) { void BUF_PREF(buff_free)(BUF_PREF(buff_t)* buff) { if (BUF_IS_VALID(buff)) { - gsm_mem_free_s((void **)&buff->buff); + lwgsm_mem_free_s((void**)&buff->buff); } } @@ -114,7 +114,7 @@ BUF_PREF(buff_write)(BUF_PREF(buff_t)* buff, const void* data, size_t btw) { /* Step 2: Write data to beginning of buffer (overflow part) */ if (btw > 0) { - BUF_MEMCPY(buff->buff, (void *)&d[tocopy], btw); + BUF_MEMCPY(buff->buff, (void*)&d[tocopy], btw); buff->w = btw; } @@ -135,7 +135,7 @@ BUF_PREF(buff_write)(BUF_PREF(buff_t)* buff, const void* data, size_t btw) { size_t BUF_PREF(buff_read)(BUF_PREF(buff_t)* buff, void* data, size_t btr) { size_t tocopy, full; - uint8_t *d = data; + uint8_t* d = data; if (!BUF_IS_VALID(buff) || btr == 0) { return 0; @@ -178,12 +178,12 @@ BUF_PREF(buff_read)(BUF_PREF(buff_t)* buff, void* data, size_t btr) { size_t BUF_PREF(buff_peek)(BUF_PREF(buff_t)* buff, size_t skip_count, void* data, size_t btp) { size_t full, tocopy, r; - uint8_t *d = data; + uint8_t* d = data; if (!BUF_IS_VALID(buff) || btp == 0) { return 0; } - + r = buff->r; /* Calculate maximum number of bytes available to read */ @@ -288,7 +288,7 @@ BUF_PREF(buff_reset)(BUF_PREF(buff_t)* buff) { * \param[in] buff: Buffer handle * \return Linear buffer start address */ -void * +void* BUF_PREF(buff_get_linear_block_read_address)(BUF_PREF(buff_t)* buff) { if (!BUF_IS_VALID(buff)) { return NULL; @@ -351,7 +351,7 @@ BUF_PREF(buff_skip)(BUF_PREF(buff_t)* buff, size_t len) { * \param[in] buff: Buffer handle * \return Linear buffer start address */ -void * +void* BUF_PREF(buff_get_linear_block_write_address)(BUF_PREF(buff_t)* buff) { if (!BUF_IS_VALID(buff)) { return NULL; @@ -379,7 +379,7 @@ BUF_PREF(buff_get_linear_block_write_length)(BUF_PREF(buff_t)* buff) { len = buff->size - w; /* * When read pointer is 0, - * maximal length is one less as if too many bytes + * maximal length is one less as if too many bytes * are written, buffer would be considered empty again (r == w) */ if (r == 0) { @@ -388,7 +388,7 @@ BUF_PREF(buff_get_linear_block_write_length)(BUF_PREF(buff_t)* buff) { * - If r is not 0, statement does not get called * - buff->size cannot be 0 and if r is 0, len is greater 0 */ - len--; + --len; } } else { len = r - w - 1; diff --git a/gsm_at_lib/src/gsm/gsm_call.c b/lwgsm/src/lwgsm/lwgsm_call.c similarity index 50% rename from gsm_at_lib/src/gsm/gsm_call.c rename to lwgsm/src/lwgsm/lwgsm_call.c index 145905f5..49ca440d 100644 --- a/gsm_at_lib/src/gsm/gsm_call.c +++ b/lwgsm/src/lwgsm/lwgsm_call.c @@ -1,10 +1,10 @@ -/** - * \file gsm_call.c +/** + * \file lwgsm_call.c * \brief Call API functions */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,44 +26,44 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_call.h" -#include "gsm/gsm_mem.h" +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_call.h" +#include "lwgsm/lwgsm_mem.h" -#if GSM_CFG_CALL || __DOXYGEN__ +#if LWGSM_CFG_CALL || __DOXYGEN__ #if !__DOXYGEN__ -#define CHECK_ENABLED() if (!(check_enabled() == gsmOK)) { return gsmERRNOTENABLED; } +#define CHECK_ENABLED() if (!(check_enabled() == lwgsmOK)) { return lwgsmERRNOTENABLED; } #endif /* !__DOXYGEN__ */ /** * \brief Check if sms is enabled - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise */ -static gsmr_t +static lwgsmr_t check_enabled(void) { - gsmr_t res; - gsm_core_lock(); - res = gsm.m.call.enabled ? gsmOK : gsmERR; - gsm_core_unlock(); + lwgsmr_t res; + lwgsm_core_lock(); + res = lwgsm.m.call.enabled ? lwgsmOK : lwgsmERR; + lwgsm_core_unlock(); return res; } /** * \brief Check if call is available - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -static gsmr_t +static lwgsmr_t check_ready(void) { - gsmr_t res; - gsm_core_lock(); - res = gsm.m.call.ready ? gsmOK : gsmERR; - gsm_core_unlock(); + lwgsmr_t res; + lwgsm_core_lock(); + res = lwgsm.m.call.ready ? lwgsmOK : lwgsmERR; + lwgsm_core_unlock(); return res; } @@ -72,18 +72,18 @@ check_ready(void) { * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used * \param[in] evt_arg: Custom argument for event callback function * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise */ -gsmr_t -gsm_call_enable(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); +lwgsmr_t +lwgsm_call_enable(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CALL_ENABLE; - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CLCC_SET; + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CALL_ENABLE; + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CLCC_SET; - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); } /** @@ -91,17 +91,17 @@ gsm_call_enable(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used * \param[in] evt_arg: Custom argument for event callback function * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise */ -gsmr_t -gsm_call_disable(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - gsm_core_lock(); - gsm.m.call.enabled = 0; +lwgsmr_t +lwgsm_call_disable(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + lwgsm_core_lock(); + lwgsm.m.call.enabled = 0; if (evt_fn != NULL) { - evt_fn(gsmOK, evt_arg); + evt_fn(lwgsmOK, evt_arg); } - gsm_core_unlock(); - return gsmOK; + lwgsm_core_unlock(); + return lwgsmOK; } /** @@ -110,23 +110,23 @@ gsm_call_disable(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uin * \param[in] evt_arg: Custom argument for event callback function * \param[in] number: Phone number to call, including country code starting with `+` sign * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_call_start(const char* number, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); +lwgsmr_t +lwgsm_call_start(const char* number, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); - GSM_ASSERT("number != NULL", number != NULL); + LWGSM_ASSERT("number != NULL", number != NULL); CHECK_ENABLED(); /* Check if enabled */ - GSM_ASSERT("check_ready == gsmOK", check_ready() == gsmOK); + LWGSM_ASSERT("check_ready == lwgsmOK", check_ready() == lwgsmOK); - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_ATD; - GSM_MSG_VAR_REF(msg).msg.call_start.number = number; + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_ATD; + LWGSM_MSG_VAR_REF(msg).msg.call_start.number = number; - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 10000); + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 10000); } /** @@ -134,19 +134,19 @@ gsm_call_start(const char* number, * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used * \param[in] evt_arg: Custom argument for event callback function * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_call_answer(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); +lwgsmr_t +lwgsm_call_answer(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); CHECK_ENABLED(); - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_ATA; + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_ATA; - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 10000); + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 10000); } /** @@ -154,19 +154,19 @@ gsm_call_answer(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used * \param[in] evt_arg: Custom argument for event callback function * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_call_hangup(const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); +lwgsmr_t +lwgsm_call_hangup(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); CHECK_ENABLED(); - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_ATH; + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_ATH; - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 10000); + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 10000); } -#endif /* GSM_CFG_CALL || __DOXYGEN__ */ +#endif /* LWGSM_CFG_CALL || __DOXYGEN__ */ diff --git a/gsm_at_lib/src/gsm/gsm_conn.c b/lwgsm/src/lwgsm/lwgsm_conn.c similarity index 54% rename from gsm_at_lib/src/gsm/gsm_conn.c rename to lwgsm/src/lwgsm/lwgsm_conn.c index ef68e07e..1376ccc0 100644 --- a/gsm_at_lib/src/gsm/gsm_conn.c +++ b/lwgsm/src/lwgsm/lwgsm_conn.c @@ -1,10 +1,10 @@ /** - * \file gsm_conn.c + * \file lwgsm_conn.c * \brief Connection API */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,33 +26,33 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_conn.h" -#include "gsm/gsm_mem.h" -#include "gsm/gsm_timeout.h" +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_conn.h" +#include "lwgsm/lwgsm_mem.h" +#include "lwgsm/lwgsm_timeout.h" -#if GSM_CFG_CONN || __DOXYGEN__ +#if LWGSM_CFG_CONN || __DOXYGEN__ /** * \brief Check if connection is closed or in closing state * \param[in] conn: Connection handle */ #define CONN_CHECK_CLOSED_IN_CLOSING(conn) do { \ - gsmr_t r = gsmOK; \ - gsm_core_lock(); \ - if (conn->status.f.in_closing || !conn->status.f.active) { \ - r = gsmCLOSED; \ - } \ - gsm_core_unlock(); \ - if (r != gsmOK) { \ - return r; \ - } \ -} while (0) + lwgsmr_t r = lwgsmOK; \ + lwgsm_core_lock(); \ + if (conn->status.f.in_closing || !conn->status.f.active) { \ + r = lwgsmCLOSED; \ + } \ + lwgsm_core_unlock(); \ + if (r != lwgsmOK) { \ + return r; \ + } \ + } while (0) /** * \brief Timeout callback for connection @@ -60,16 +60,16 @@ */ static void conn_timeout_cb(void* arg) { - gsm_conn_p conn = arg; /* Argument is actual connection */ + lwgsm_conn_p conn = arg; /* Argument is actual connection */ if (conn->status.f.active) { /* Handle only active connections */ - gsm.evt.type = GSM_EVT_CONN_POLL; /* Poll connection event */ - gsm.evt.evt.conn_poll.conn = conn; /* Set connection pointer */ - gsmi_send_conn_cb(conn, NULL); /* Send connection callback */ + lwgsm.evt.type = LWGSM_EVT_CONN_POLL; /* Poll connection event */ + lwgsm.evt.evt.conn_poll.conn = conn; /* Set connection pointer */ + lwgsmi_send_conn_cb(conn, NULL); /* Send connection callback */ - gsmi_conn_start_timeout(conn); /* Schedule new timeout */ - GSM_DEBUGF(GSM_CFG_DBG_CONN | GSM_DBG_TYPE_TRACE, - "[CONN] Poll event: %p\r\n", conn); + lwgsmi_conn_start_timeout(conn); /* Schedule new timeout */ + LWGSM_DEBUGF(LWGSM_CFG_DBG_CONN | LWGSM_DBG_TYPE_TRACE, + "[CONN] Poll event: %p\r\n", conn); } } @@ -78,8 +78,8 @@ conn_timeout_cb(void* arg) { * \param[in] conn: Connection handle as user argument */ void -gsmi_conn_start_timeout(gsm_conn_p conn) { - gsm_timeout_add(GSM_CFG_CONN_POLL_INTERVAL, conn_timeout_cb, conn); /* Add connection timeout */ +lwgsmi_conn_start_timeout(lwgsm_conn_p conn) { + lwgsm_timeout_add(LWGSM_CFG_CONN_POLL_INTERVAL, conn_timeout_cb, conn); /* Add connection timeout */ } /** @@ -88,11 +88,11 @@ gsmi_conn_start_timeout(gsm_conn_p conn) { * \return Connection current validation ID */ uint8_t -gsmi_conn_get_val_id(gsm_conn_p conn) { +lwgsmi_conn_get_val_id(lwgsm_conn_p conn) { uint8_t val_id; - gsm_core_lock(); + lwgsm_core_lock(); val_id = conn->val_id; - gsm_core_unlock(); + lwgsm_core_unlock(); return val_id; } @@ -108,16 +108,16 @@ gsmi_conn_get_val_id(gsm_conn_p conn) { * \param[out] bw: Pointer to output variable to save number of sent data when successfully sent * \param[in] fau: "Free After Use" flag. Set to `1` if stack should free the memory after data sent * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -static gsmr_t -conn_send(gsm_conn_p conn, const gsm_ip_t* const ip, gsm_port_t port, const void* data, - size_t btw, size_t* const bw, uint8_t fau, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); +static lwgsmr_t +conn_send(lwgsm_conn_p conn, const lwgsm_ip_t* const ip, lwgsm_port_t port, const void* data, + size_t btw, size_t* const bw, uint8_t fau, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); - GSM_ASSERT("conn != NULL", conn != NULL); - GSM_ASSERT("data != NULL", data != NULL); - GSM_ASSERT("btw > 0", btw > 0); + LWGSM_ASSERT("conn != NULL", conn != NULL); + LWGSM_ASSERT("data != NULL", data != NULL); + LWGSM_ASSERT("btw > 0", btw > 0); if (bw != NULL) { *bw = 0; @@ -125,30 +125,30 @@ conn_send(gsm_conn_p conn, const gsm_ip_t* const ip, gsm_port_t port, const void CONN_CHECK_CLOSED_IN_CLOSING(conn); /* Check if we can continue */ - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CIPSEND; + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CIPSEND; - GSM_MSG_VAR_REF(msg).msg.conn_send.conn = conn; - GSM_MSG_VAR_REF(msg).msg.conn_send.data = data; - GSM_MSG_VAR_REF(msg).msg.conn_send.btw = btw; - GSM_MSG_VAR_REF(msg).msg.conn_send.bw = bw; - GSM_MSG_VAR_REF(msg).msg.conn_send.remote_ip = ip; - GSM_MSG_VAR_REF(msg).msg.conn_send.remote_port = port; - GSM_MSG_VAR_REF(msg).msg.conn_send.fau = fau; - GSM_MSG_VAR_REF(msg).msg.conn_send.val_id = gsmi_conn_get_val_id(conn); + LWGSM_MSG_VAR_REF(msg).msg.conn_send.conn = conn; + LWGSM_MSG_VAR_REF(msg).msg.conn_send.data = data; + LWGSM_MSG_VAR_REF(msg).msg.conn_send.btw = btw; + LWGSM_MSG_VAR_REF(msg).msg.conn_send.bw = bw; + LWGSM_MSG_VAR_REF(msg).msg.conn_send.remote_ip = ip; + LWGSM_MSG_VAR_REF(msg).msg.conn_send.remote_port = port; + LWGSM_MSG_VAR_REF(msg).msg.conn_send.fau = fau; + LWGSM_MSG_VAR_REF(msg).msg.conn_send.val_id = lwgsmi_conn_get_val_id(conn); - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); } /** * \brief Flush buffer on connection * \param[in] conn: Connection to flush buffer on - * \return \ref gsmOK if data flushed and put to queue, member of \ref gsmr_t otherwise + * \return \ref lwgsmOK if data flushed and put to queue, member of \ref lwgsmr_t otherwise */ -static gsmr_t -flush_buff(gsm_conn_p conn) { - gsmr_t res = gsmOK; - gsm_core_lock(); +static lwgsmr_t +flush_buff(lwgsm_conn_p conn) { + lwgsmr_t res = lwgsmOK; + lwgsm_core_lock(); if (conn != NULL && conn->buff.buff != NULL) { /* Do we have something ready? */ /* * If there is nothing to write or if write was not successful, @@ -157,16 +157,16 @@ flush_buff(gsm_conn_p conn) { if (conn->buff.ptr > 0) { /* Anything to send at the moment? */ res = conn_send(conn, NULL, 0, conn->buff.buff, conn->buff.ptr, NULL, 1, 0); } else { - res = gsmERR; + res = lwgsmERR; } - if (res != gsmOK) { - GSM_DEBUGF(GSM_CFG_DBG_CONN | GSM_DBG_TYPE_TRACE, - "[CONN] Free write buffer: %p\r\n", (void *)conn->buff.buff); - gsm_mem_free_s((void **)&conn->buff.buff); + if (res != lwgsmOK) { + LWGSM_DEBUGF(LWGSM_CFG_DBG_CONN | LWGSM_DBG_TYPE_TRACE, + "[CONN] Free write buffer: %p\r\n", (void*)conn->buff.buff); + lwgsm_mem_free_s((void**)&conn->buff.buff); } conn->buff.buff = NULL; } - gsm_core_unlock(); + lwgsm_core_unlock(); return res; } @@ -174,73 +174,73 @@ flush_buff(gsm_conn_p conn) { * \brief Initialize connection module */ void -gsmi_conn_init(void) { +lwgsmi_conn_init(void) { } /** * \brief Start a new connection of specific type * \param[out] conn: Pointer to connection handle to set new connection reference in case of successful connection - * \param[in] type: Connection type. This parameter can be a value of \ref gsm_conn_type_t enumeration + * \param[in] type: Connection type. This parameter can be a value of \ref lwgsm_conn_type_t enumeration * \param[in] host: Connection host. In case of IP, write it as string, ex. "192.168.1.1" * \param[in] port: Connection port * \param[in] arg: Pointer to user argument passed to connection if successfully connected * \param[in] conn_evt_fn: Callback function for this connection * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_conn_start(gsm_conn_p* conn, gsm_conn_type_t type, const char* const host, gsm_port_t port, - void* const arg, gsm_evt_fn conn_evt_fn, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); - - GSM_ASSERT("host != NULL", host != NULL); - GSM_ASSERT("port > 0", port > 0); - GSM_ASSERT("conn_evt_fn != NULL", conn_evt_fn != NULL); - - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CIPSTART; - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CIPSTATUS; - GSM_MSG_VAR_REF(msg).msg.conn_start.num = GSM_CFG_MAX_CONNS;/* Set maximal value as invalid number */ - GSM_MSG_VAR_REF(msg).msg.conn_start.conn = conn; - GSM_MSG_VAR_REF(msg).msg.conn_start.type = type; - GSM_MSG_VAR_REF(msg).msg.conn_start.host = host; - GSM_MSG_VAR_REF(msg).msg.conn_start.port = port; - GSM_MSG_VAR_REF(msg).msg.conn_start.evt_func = conn_evt_fn; - GSM_MSG_VAR_REF(msg).msg.conn_start.arg = arg; - - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 60000); +lwgsmr_t +lwgsm_conn_start(lwgsm_conn_p* conn, lwgsm_conn_type_t type, const char* const host, lwgsm_port_t port, + void* const arg, lwgsm_evt_fn conn_evt_fn, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_ASSERT("host != NULL", host != NULL); + LWGSM_ASSERT("port > 0", port > 0); + LWGSM_ASSERT("conn_evt_fn != NULL", conn_evt_fn != NULL); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CIPSTART; + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CIPSTATUS; + LWGSM_MSG_VAR_REF(msg).msg.conn_start.num = LWGSM_CFG_MAX_CONNS;/* Set maximal value as invalid number */ + LWGSM_MSG_VAR_REF(msg).msg.conn_start.conn = conn; + LWGSM_MSG_VAR_REF(msg).msg.conn_start.type = type; + LWGSM_MSG_VAR_REF(msg).msg.conn_start.host = host; + LWGSM_MSG_VAR_REF(msg).msg.conn_start.port = port; + LWGSM_MSG_VAR_REF(msg).msg.conn_start.evt_func = conn_evt_fn; + LWGSM_MSG_VAR_REF(msg).msg.conn_start.arg = arg; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); } /** * \brief Close specific or all connections * \param[in] conn: Connection handle to close. Set to NULL if you want to close all connections. * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_conn_close(gsm_conn_p conn, const uint32_t blocking) { - gsmr_t res = gsmOK; - GSM_MSG_VAR_DEFINE(msg); +lwgsmr_t +lwgsm_conn_close(lwgsm_conn_p conn, const uint32_t blocking) { + lwgsmr_t res = lwgsmOK; + LWGSM_MSG_VAR_DEFINE(msg); - GSM_ASSERT("conn != NULL", conn != NULL); + LWGSM_ASSERT("conn != NULL", conn != NULL); CONN_CHECK_CLOSED_IN_CLOSING(conn); /* Check if we can continue */ /* Proceed with close event at this point! */ - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CIPCLOSE; - GSM_MSG_VAR_REF(msg).msg.conn_close.conn = conn; - GSM_MSG_VAR_REF(msg).msg.conn_close.val_id = gsmi_conn_get_val_id(conn); + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CIPCLOSE; + LWGSM_MSG_VAR_REF(msg).msg.conn_close.conn = conn; + LWGSM_MSG_VAR_REF(msg).msg.conn_close.val_id = lwgsmi_conn_get_val_id(conn); flush_buff(conn); /* First flush buffer */ - res = gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 1000); - if (res == gsmOK && !blocking) { /* Function succedded in non-blocking mode */ - gsm_core_lock(); - GSM_DEBUGF(GSM_CFG_DBG_CONN | GSM_DBG_TYPE_TRACE, - "[CONN] Connection %d set to closing state\r\n", (int)conn->num); + res = lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 1000); + if (res == lwgsmOK && !blocking) { /* Function succedded in non-blocking mode */ + lwgsm_core_lock(); + LWGSM_DEBUGF(LWGSM_CFG_DBG_CONN | LWGSM_DBG_TYPE_TRACE, + "[CONN] Connection %d set to closing state\r\n", (int)conn->num); conn->status.f.in_closing = 1; /* Connection is in closing mode but not yet closed */ - gsm_core_unlock(); + lwgsm_core_unlock(); } return res; } @@ -255,12 +255,12 @@ gsm_conn_close(gsm_conn_p conn, const uint32_t blocking) { * \param[in] btw: Number of bytes to send * \param[out] bw: Pointer to output variable to save number of sent data when successfully sent * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_conn_sendto(gsm_conn_p conn, const gsm_ip_t* const ip, gsm_port_t port, const void* data, +lwgsmr_t +lwgsm_conn_sendto(lwgsm_conn_p conn, const lwgsm_ip_t* const ip, lwgsm_port_t port, const void* data, size_t btw, size_t* bw, const uint32_t blocking) { - GSM_ASSERT("conn != NULL", conn != NULL); + LWGSM_ASSERT("conn != NULL", conn != NULL); flush_buff(conn); /* Flush currently written memory if exists */ return conn_send(conn, ip, port, data, btw, bw, 0, blocking); @@ -272,32 +272,32 @@ gsm_conn_sendto(gsm_conn_p conn, const gsm_ip_t* const ip, gsm_port_t port, cons * \param[in] data: Data to send * \param[in] btw: Number of bytes to send * \param[out] bw: Pointer to output variable to save number of sent data when successfully sent. - * Parameter value might not be accurate if you combine \ref gsm_conn_write and \ref gsm_conn_send functions + * Parameter value might not be accurate if you combine \ref lwgsm_conn_write and \ref lwgsm_conn_send functions * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_conn_send(gsm_conn_p conn, const void* data, size_t btw, size_t* const bw, - const uint32_t blocking) { - gsmr_t res; +lwgsmr_t +lwgsm_conn_send(lwgsm_conn_p conn, const void* data, size_t btw, size_t* const bw, + const uint32_t blocking) { + lwgsmr_t res; const uint8_t* d = data; - GSM_ASSERT("conn != NULL", conn != NULL); - GSM_ASSERT("data != NULL", data != NULL); - GSM_ASSERT("btw > 0", btw > 0); + LWGSM_ASSERT("conn != NULL", conn != NULL); + LWGSM_ASSERT("data != NULL", data != NULL); + LWGSM_ASSERT("btw > 0", btw > 0); - gsm_core_lock(); + lwgsm_core_lock(); if (conn->buff.buff != NULL) { /* Check if memory available */ size_t to_copy; - to_copy = GSM_MIN(btw, conn->buff.len - conn->buff.ptr); + to_copy = LWGSM_MIN(btw, conn->buff.len - conn->buff.ptr); if (to_copy > 0) { - GSM_MEMCPY(&conn->buff.buff[conn->buff.ptr], d, to_copy); + LWGSM_MEMCPY(&conn->buff.buff[conn->buff.ptr], d, to_copy); conn->buff.ptr += to_copy; d += to_copy; btw -= to_copy; } } - gsm_core_unlock(); + lwgsm_core_unlock(); res = flush_buff(conn); /* Flush currently written memory if exists */ if (btw > 0) { /* Check for remaining data */ res = conn_send(conn, NULL, 0, d, btw, bw, 0, blocking); @@ -317,69 +317,69 @@ gsm_conn_send(gsm_conn_p conn, const void* data, size_t btw, size_t* const bw, * * \param[in] conn: Connection handle * \param[in] pbuf: Packet buffer received on connection - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_conn_recved(gsm_conn_p conn, gsm_pbuf_p pbuf) { -#if GSM_CFG_CONN_MANUAL_TCP_RECEIVE +lwgsmr_t +lwgsm_conn_recved(lwgsm_conn_p conn, lwgsm_pbuf_p pbuf) { +#if LWGSM_CFG_CONN_MANUAL_TCP_RECEIVE size_t len; - len = gsm_pbuf_length(pbuf, 1); /* Get length of pbuf */ + len = lwgsm_pbuf_length(pbuf, 1); /* Get length of pbuf */ if (conn->tcp_available_data > len) { conn->tcp_available_data -= len; /* Decrease for available length */ if (conn->tcp_available_data > 0) { /* Start new manual receive here... */ } } -#else /* GSM_CFG_CONN_MANUAL_TCP_RECEIVE */ - GSM_UNUSED(conn); - GSM_UNUSED(pbuf); -#endif /* !GSM_CFG_CONN_MANUAL_TCP_RECEIVE */ - return gsmOK; +#else /* LWGSM_CFG_CONN_MANUAL_TCP_RECEIVE */ + LWGSM_UNUSED(conn); + LWGSM_UNUSED(pbuf); +#endif /* !LWGSM_CFG_CONN_MANUAL_TCP_RECEIVE */ + return lwgsmOK; } /** * \brief Set argument variable for connection * \param[in] conn: Connection handle to set argument * \param[in] arg: Pointer to argument - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - * \sa gsm_conn_get_arg + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + * \sa lwgsm_conn_get_arg */ -gsmr_t -gsm_conn_set_arg(gsm_conn_p conn, void* const arg) { - gsm_core_lock(); +lwgsmr_t +lwgsm_conn_set_arg(lwgsm_conn_p conn, void* const arg) { + lwgsm_core_lock(); conn->arg = arg; /* Set argument for connection */ - gsm_core_unlock(); - return gsmOK; + lwgsm_core_unlock(); + return lwgsmOK; } /** * \brief Get user defined connection argument * \param[in] conn: Connection handle to get argument * \return User argument - * \sa gsm_conn_set_arg + * \sa lwgsm_conn_set_arg */ -void * -gsm_conn_get_arg(gsm_conn_p conn) { +void* +lwgsm_conn_get_arg(lwgsm_conn_p conn) { void* arg; - gsm_core_lock(); + lwgsm_core_lock(); arg = conn->arg; /* Set argument for connection */ - gsm_core_unlock(); + lwgsm_core_unlock(); return arg; } /** * \brief Gets connections status * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_get_conns_status(const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); +lwgsmr_t +lwgsm_get_conns_status(const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CIPSTATUS; + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CIPSTATUS; - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 1000); + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 1000); } /** @@ -388,12 +388,12 @@ gsm_get_conns_status(const uint32_t blocking) { * \return `1` on success, `0` otherwise */ uint8_t -gsm_conn_is_client(gsm_conn_p conn) { +lwgsm_conn_is_client(lwgsm_conn_p conn) { uint8_t res = 0; - if (conn != NULL && gsmi_is_valid_conn_ptr(conn)) { - gsm_core_lock(); + if (conn != NULL && lwgsmi_is_valid_conn_ptr(conn)) { + lwgsm_core_lock(); res = conn->status.f.active && conn->status.f.client; - gsm_core_unlock(); + lwgsm_core_unlock(); } return res; } @@ -404,12 +404,12 @@ gsm_conn_is_client(gsm_conn_p conn) { * \return `1` on success, `0` otherwise */ uint8_t -gsm_conn_is_active(gsm_conn_p conn) { +lwgsm_conn_is_active(lwgsm_conn_p conn) { uint8_t res = 0; - if (conn != NULL && gsmi_is_valid_conn_ptr(conn)) { - gsm_core_lock(); + if (conn != NULL && lwgsmi_is_valid_conn_ptr(conn)) { + lwgsm_core_lock(); res = conn->status.f.active; - gsm_core_unlock(); + lwgsm_core_unlock(); } return res; } @@ -420,12 +420,12 @@ gsm_conn_is_active(gsm_conn_p conn) { * \return `1` on success, `0` otherwise */ uint8_t -gsm_conn_is_closed(gsm_conn_p conn) { +lwgsm_conn_is_closed(lwgsm_conn_p conn) { uint8_t res = 0; - if (conn != NULL && gsmi_is_valid_conn_ptr(conn)) { - gsm_core_lock(); + if (conn != NULL && lwgsmi_is_valid_conn_ptr(conn)) { + lwgsm_core_lock(); res = !conn->status.f.active; - gsm_core_unlock(); + lwgsm_core_unlock(); } return res; } @@ -436,9 +436,9 @@ gsm_conn_is_closed(gsm_conn_p conn) { * \return Connection number in case of success or -1 on failure */ int8_t -gsm_conn_getnum(gsm_conn_p conn) { +lwgsm_conn_getnum(lwgsm_conn_p conn) { int8_t res = -1; - if (conn != NULL && gsmi_is_valid_conn_ptr(conn)) { + if (conn != NULL && lwgsmi_is_valid_conn_ptr(conn)) { /* Protection not needed as every connection has always the same number */ res = conn->num; /* Get number */ } @@ -450,15 +450,21 @@ gsm_conn_getnum(gsm_conn_p conn) { * \param[in] evt: Event which happened for connection * \return Connection pointer on success, `NULL` otherwise */ -gsm_conn_p -gsm_conn_get_from_evt(gsm_evt_t* evt) { +lwgsm_conn_p +lwgsm_conn_get_from_evt(lwgsm_evt_t* evt) { switch (evt->type) { - case GSM_EVT_CONN_ACTIVE: return gsm_evt_conn_active_get_conn(evt); - case GSM_EVT_CONN_CLOSE: return gsm_evt_conn_close_get_conn(evt); - case GSM_EVT_CONN_RECV: return gsm_evt_conn_recv_get_conn(evt); - case GSM_EVT_CONN_SEND: return gsm_evt_conn_send_get_conn(evt); - case GSM_EVT_CONN_POLL: return gsm_evt_conn_poll_get_conn(evt); - default: return NULL; + case LWGSM_EVT_CONN_ACTIVE: + return lwgsm_evt_conn_active_get_conn(evt); + case LWGSM_EVT_CONN_CLOSE: + return lwgsm_evt_conn_close_get_conn(evt); + case LWGSM_EVT_CONN_RECV: + return lwgsm_evt_conn_recv_get_conn(evt); + case LWGSM_EVT_CONN_SEND: + return lwgsm_evt_conn_send_get_conn(evt); + case LWGSM_EVT_CONN_POLL: + return lwgsm_evt_conn_poll_get_conn(evt); + default: + return NULL; } } @@ -468,20 +474,20 @@ gsm_conn_get_from_evt(gsm_evt_t* evt) { * \param[in] conn: Connection to write * \param[in] data: Data to copy to write buffer * \param[in] btw: Number of bytes to write - * \param[in] flush: Flush flag. Set to `1` if you want to send data immediatelly after copying + * \param[in] flush: Flush flag. Set to `1` if you want to send data immediately after copying * \param[out] mem_available: Available memory size available in current write buffer. * When the buffer length is reached, current one is sent and a new one is automatically created. - * If function returns \ref gsmOK and `*mem_available = 0`, there was a problem + * If function returns \ref lwgsmOK and `*mem_available = 0`, there was a problem * allocating a new buffer for next operation - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_conn_write(gsm_conn_p conn, const void* data, size_t btw, uint8_t flush, size_t* const mem_available) { +lwgsmr_t +lwgsm_conn_write(lwgsm_conn_p conn, const void* data, size_t btw, uint8_t flush, size_t* const mem_available) { size_t len; const uint8_t* d = data; - GSM_ASSERT("conn != NULL", conn != NULL); + LWGSM_ASSERT("conn != NULL", conn != NULL); /* * Steps during write process: @@ -498,8 +504,8 @@ gsm_conn_write(gsm_conn_p conn, const void* data, size_t btw, uint8_t flush, siz /* Step 1 */ if (conn->buff.buff != NULL) { - len = GSM_MIN(conn->buff.len - conn->buff.ptr, btw); - GSM_MEMCPY(&conn->buff.buff[conn->buff.ptr], d, len); + len = LWGSM_MIN(conn->buff.len - conn->buff.ptr, btw); + LWGSM_MEMCPY(&conn->buff.buff[conn->buff.ptr], d, len); d += len; btw -= len; @@ -508,52 +514,52 @@ gsm_conn_write(gsm_conn_p conn, const void* data, size_t btw, uint8_t flush, siz /* Step 1.1 */ if (conn->buff.ptr == conn->buff.len || flush) { /* Try to send to processing queue in non-blocking way */ - if (conn_send(conn, NULL, 0, conn->buff.buff, conn->buff.ptr, NULL, 1, 0) != gsmOK) { - GSM_DEBUGF(GSM_CFG_DBG_CONN | GSM_DBG_TYPE_TRACE, - "[CONN] Free write buffer: %p\r\n", conn->buff.buff); - gsm_mem_free_s((void **)&conn->buff.buff); + if (conn_send(conn, NULL, 0, conn->buff.buff, conn->buff.ptr, NULL, 1, 0) != lwgsmOK) { + LWGSM_DEBUGF(LWGSM_CFG_DBG_CONN | LWGSM_DBG_TYPE_TRACE, + "[CONN] Free write buffer: %p\r\n", conn->buff.buff); + lwgsm_mem_free_s((void**)&conn->buff.buff); } conn->buff.buff = NULL; } } /* Step 2 */ - while (btw >= GSM_CFG_CONN_MAX_DATA_LEN) { + while (btw >= LWGSM_CFG_CONN_MAX_DATA_LEN) { uint8_t* buff; - buff = gsm_mem_malloc(sizeof(*buff) * GSM_CFG_CONN_MAX_DATA_LEN); + buff = lwgsm_mem_malloc(sizeof(*buff) * LWGSM_CFG_CONN_MAX_DATA_LEN); if (buff != NULL) { - GSM_MEMCPY(buff, d, GSM_CFG_CONN_MAX_DATA_LEN); /* Copy data to buffer */ - if (conn_send(conn, NULL, 0, buff, GSM_CFG_CONN_MAX_DATA_LEN, NULL, 1, 0) != gsmOK) { - GSM_DEBUGF(GSM_CFG_DBG_CONN | GSM_DBG_TYPE_TRACE, - "[CONN] Free write buffer: %p\r\n", (void *)buff); - gsm_mem_free_s((void **)&buff); - return gsmERRMEM; + LWGSM_MEMCPY(buff, d, LWGSM_CFG_CONN_MAX_DATA_LEN); /* Copy data to buffer */ + if (conn_send(conn, NULL, 0, buff, LWGSM_CFG_CONN_MAX_DATA_LEN, NULL, 1, 0) != lwgsmOK) { + LWGSM_DEBUGF(LWGSM_CFG_DBG_CONN | LWGSM_DBG_TYPE_TRACE, + "[CONN] Free write buffer: %p\r\n", (void*)buff); + lwgsm_mem_free_s((void**)&buff); + return lwgsmERRMEM; } } else { - return gsmERRMEM; + return lwgsmERRMEM; } - btw -= GSM_CFG_CONN_MAX_DATA_LEN; /* Decrease remaining length */ - d += GSM_CFG_CONN_MAX_DATA_LEN; /* Advance data pointer */ + btw -= LWGSM_CFG_CONN_MAX_DATA_LEN; /* Decrease remaining length */ + d += LWGSM_CFG_CONN_MAX_DATA_LEN; /* Advance data pointer */ } /* Step 3 */ if (conn->buff.buff == NULL) { - conn->buff.buff = gsm_mem_malloc(sizeof(*conn->buff.buff) * GSM_CFG_CONN_MAX_DATA_LEN); - conn->buff.len = GSM_CFG_CONN_MAX_DATA_LEN; + conn->buff.buff = lwgsm_mem_malloc(sizeof(*conn->buff.buff) * LWGSM_CFG_CONN_MAX_DATA_LEN); + conn->buff.len = LWGSM_CFG_CONN_MAX_DATA_LEN; conn->buff.ptr = 0; - GSM_DEBUGW(GSM_CFG_DBG_CONN | GSM_DBG_TYPE_TRACE, conn->buff.buff != NULL, - "[CONN] New write buffer allocated, addr = %p\r\n", conn->buff.buff); - GSM_DEBUGW(GSM_CFG_DBG_CONN | GSM_DBG_TYPE_TRACE, conn->buff.buff == NULL, - "[CONN] Cannot allocate new write buffer\r\n"); + LWGSM_DEBUGW(LWGSM_CFG_DBG_CONN | LWGSM_DBG_TYPE_TRACE, conn->buff.buff != NULL, + "[CONN] New write buffer allocated, addr = %p\r\n", conn->buff.buff); + LWGSM_DEBUGW(LWGSM_CFG_DBG_CONN | LWGSM_DBG_TYPE_TRACE, conn->buff.buff == NULL, + "[CONN] Cannot allocate new write buffer\r\n"); } if (btw > 0) { if (conn->buff.buff != NULL) { - GSM_MEMCPY(conn->buff.buff, d, btw); /* Copy data to memory */ + LWGSM_MEMCPY(conn->buff.buff, d, btw); /* Copy data to memory */ conn->buff.ptr = btw; } else { - return gsmERRMEM; + return lwgsmERRMEM; } } @@ -570,7 +576,7 @@ gsm_conn_write(gsm_conn_p conn, const void* data, size_t btw, uint8_t flush, siz *mem_available = 0; } } - return gsmOK; + return lwgsmOK; } /** @@ -579,14 +585,14 @@ gsm_conn_write(gsm_conn_p conn, const void* data, size_t btw, uint8_t flush, siz * \return Count of received bytes on connection */ size_t -gsm_conn_get_total_recved_count(gsm_conn_p conn) { +lwgsm_conn_get_total_recved_count(lwgsm_conn_p conn) { size_t tot; - GSM_ASSERT("conn != NULL", conn != NULL); + LWGSM_ASSERT("conn != NULL", conn != NULL); - gsm_core_lock(); + lwgsm_core_lock(); tot = conn->total_recved; /* Get total received bytes */ - gsm_core_unlock(); + lwgsm_core_unlock(); return tot; } @@ -598,11 +604,11 @@ gsm_conn_get_total_recved_count(gsm_conn_p conn) { * \return `1` on success, `0` otherwise */ uint8_t -gsm_conn_get_remote_ip(gsm_conn_p conn, gsm_ip_t* ip) { +lwgsm_conn_get_remote_ip(lwgsm_conn_p conn, lwgsm_ip_t* ip) { if (conn != NULL && ip != NULL) { - gsm_core_lock(); - GSM_MEMCPY(ip, &conn->remote_ip, sizeof(*ip)); /* Copy data */ - gsm_core_unlock(); + lwgsm_core_lock(); + LWGSM_MEMCPY(ip, &conn->remote_ip, sizeof(*ip));/* Copy data */ + lwgsm_core_unlock(); return 1; } return 0; @@ -613,13 +619,13 @@ gsm_conn_get_remote_ip(gsm_conn_p conn, gsm_ip_t* ip) { * \param[in] conn: Connection handle * \return Port number on success, `0` otherwise */ -gsm_port_t -gsm_conn_get_remote_port(gsm_conn_p conn) { - gsm_port_t port = 0; +lwgsm_port_t +lwgsm_conn_get_remote_port(lwgsm_conn_p conn) { + lwgsm_port_t port = 0; if (conn != NULL) { - gsm_core_lock(); + lwgsm_core_lock(); port = conn->remote_port; - gsm_core_unlock(); + lwgsm_core_unlock(); } return port; } @@ -629,15 +635,15 @@ gsm_conn_get_remote_port(gsm_conn_p conn) { * \param[in] conn: Connection handle * \return Port number on success, `0` otherwise */ -gsm_port_t -gsm_conn_get_local_port(gsm_conn_p conn) { - gsm_port_t port = 0; +lwgsm_port_t +lwgsm_conn_get_local_port(lwgsm_conn_p conn) { + lwgsm_port_t port = 0; if (conn != NULL) { - gsm_core_lock(); + lwgsm_core_lock(); port = conn->local_port; - gsm_core_unlock(); + lwgsm_core_unlock(); } return port; } -#endif /* GSM_CFG_CONN || __DOXYGEN__ */ +#endif /* LWGSM_CFG_CONN || __DOXYGEN__ */ diff --git a/gsm_at_lib/src/gsm/gsm_debug.c b/lwgsm/src/lwgsm/lwgsm_debug.c similarity index 77% rename from gsm_at_lib/src/gsm/gsm_debug.c rename to lwgsm/src/lwgsm/lwgsm_debug.c index 9be1c0c1..54d22bfd 100644 --- a/gsm_at_lib/src/gsm/gsm_debug.c +++ b/lwgsm/src/lwgsm/lwgsm_debug.c @@ -1,10 +1,10 @@ -/** - * \file gsm_debug.c +/** + * \file lwgsm_debug.c * \brief Debugging inside GSM stack */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,19 +26,19 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_debug.h" -#include "gsm/gsm.h" +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_debug.h" +#include "lwgsm/lwgsm.h" -#if GSM_CFG_DBG || __DOXYGEN__ +#if LWGSM_CFG_DBG || __DOXYGEN__ -const char * -gsmi_dbg_msg_to_string(gsm_cmd_t cmd) { +const char* +lwgsmi_dbg_msg_to_string(lwgsm_cmd_t cmd) { static char tmp_arr[100]; if (cmd) { sprintf(tmp_arr, "%d", (int)cmd); @@ -47,4 +47,4 @@ gsmi_dbg_msg_to_string(gsm_cmd_t cmd) { return ""; } -#endif /* GSM_CFG_DBG || __DOXYGEN__ */ +#endif /* LWGSM_CFG_DBG || __DOXYGEN__ */ diff --git a/gsm_at_lib/src/gsm/gsm_device_info.c b/lwgsm/src/lwgsm/lwgsm_device_info.c similarity index 50% rename from gsm_at_lib/src/gsm/gsm_device_info.c rename to lwgsm/src/lwgsm/lwgsm_device_info.c index 98d72cbc..81bf18b6 100644 --- a/gsm_at_lib/src/gsm/gsm_device_info.c +++ b/lwgsm/src/lwgsm/lwgsm_device_info.c @@ -1,10 +1,10 @@ -/** - * \file gsm_device_info.c +/** + * \file lwgsm_device_info.c * \brief Basic device information */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,14 +26,14 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_device_info.h" -#include "gsm/gsm_mem.h" +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_device_info.h" +#include "lwgsm/lwgsm_mem.h" /** * \brief Get device manufacturer @@ -42,23 +42,23 @@ * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used * \param[in] evt_arg: Custom argument for event callback function * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_device_get_manufacturer(char* manuf, size_t len, const gsm_api_cmd_evt_fn evt_fn, +lwgsmr_t +lwgsm_device_get_manufacturer(char* manuf, size_t len, const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); + LWGSM_MSG_VAR_DEFINE(msg); - GSM_ASSERT("manuf != NULL", manuf != NULL); - GSM_ASSERT("len > 0", len > 0); + LWGSM_ASSERT("manuf != NULL", manuf != NULL); + LWGSM_ASSERT("len > 0", len > 0); - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CGMI_GET; - GSM_MSG_VAR_REF(msg).msg.device_info.str = manuf; - GSM_MSG_VAR_REF(msg).msg.device_info.len = len; + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CGMI_GET; + LWGSM_MSG_VAR_REF(msg).msg.device_info.str = manuf; + LWGSM_MSG_VAR_REF(msg).msg.device_info.len = len; - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 10000); + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 10000); } /** @@ -68,23 +68,23 @@ gsm_device_get_manufacturer(char* manuf, size_t len, const gsm_api_cmd_evt_fn ev * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used * \param[in] evt_arg: Custom argument for event callback function * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_device_get_model(char* model, size_t len, const gsm_api_cmd_evt_fn evt_fn, - void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); +lwgsmr_t +lwgsm_device_get_model(char* model, size_t len, const lwgsm_api_cmd_evt_fn evt_fn, + void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); - GSM_ASSERT("model != NULL", model != NULL); - GSM_ASSERT("len > 0", len > 0); + LWGSM_ASSERT("model != NULL", model != NULL); + LWGSM_ASSERT("len > 0", len > 0); - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CGMM_GET; - GSM_MSG_VAR_REF(msg).msg.device_info.str = model; - GSM_MSG_VAR_REF(msg).msg.device_info.len = len; + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CGMM_GET; + LWGSM_MSG_VAR_REF(msg).msg.device_info.str = model; + LWGSM_MSG_VAR_REF(msg).msg.device_info.len = len; - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 10000); + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 10000); } /** @@ -94,23 +94,23 @@ gsm_device_get_model(char* model, size_t len, const gsm_api_cmd_evt_fn evt_fn, * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used * \param[in] evt_arg: Custom argument for event callback function * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_device_get_revision(char* rev, size_t len, const gsm_api_cmd_evt_fn evt_fn, - void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); +lwgsmr_t +lwgsm_device_get_revision(char* rev, size_t len, const lwgsm_api_cmd_evt_fn evt_fn, + void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); - GSM_ASSERT("rev != NULL", rev != NULL); - GSM_ASSERT("len > 0", len > 0); + LWGSM_ASSERT("rev != NULL", rev != NULL); + LWGSM_ASSERT("len > 0", len > 0); - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CGMR_GET; - GSM_MSG_VAR_REF(msg).msg.device_info.str = rev; - GSM_MSG_VAR_REF(msg).msg.device_info.len = len; + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CGMR_GET; + LWGSM_MSG_VAR_REF(msg).msg.device_info.str = rev; + LWGSM_MSG_VAR_REF(msg).msg.device_info.len = len; - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 10000); + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 10000); } /** @@ -120,21 +120,21 @@ gsm_device_get_revision(char* rev, size_t len, const gsm_api_cmd_evt_fn evt_fn, * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used * \param[in] evt_arg: Custom argument for event callback function * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_device_get_serial_number(char* serial, size_t len, const gsm_api_cmd_evt_fn evt_fn, - void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); +lwgsmr_t +lwgsm_device_get_serial_number(char* serial, size_t len, const lwgsm_api_cmd_evt_fn evt_fn, + void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); - GSM_ASSERT("serial != NULL", serial != NULL); - GSM_ASSERT("len > 0", len > 0); + LWGSM_ASSERT("serial != NULL", serial != NULL); + LWGSM_ASSERT("len > 0", len > 0); - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CGSN_GET; - GSM_MSG_VAR_REF(msg).msg.device_info.str = serial; - GSM_MSG_VAR_REF(msg).msg.device_info.len = len; + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CGSN_GET; + LWGSM_MSG_VAR_REF(msg).msg.device_info.str = serial; + LWGSM_MSG_VAR_REF(msg).msg.device_info.len = len; - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 10000); + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 10000); } diff --git a/gsm_at_lib/src/gsm/gsm_evt.c b/lwgsm/src/lwgsm/lwgsm_evt.c similarity index 62% rename from gsm_at_lib/src/gsm/gsm_evt.c rename to lwgsm/src/lwgsm/lwgsm_evt.c index d1ea3208..dc0ba507 100644 --- a/gsm_at_lib/src/gsm/gsm_evt.c +++ b/lwgsm/src/lwgsm/lwgsm_evt.c @@ -1,10 +1,10 @@ -/** - * \file gsm_evt.c +/** + * \file lwgsm_evt.c * \brief Event helper functions */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,108 +26,108 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_evt.h" -#include "gsm/gsm_mem.h" +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_evt.h" +#include "lwgsm/lwgsm_mem.h" /** * \brief Register callback function for global (non-connection based) events * \param[in] fn: Callback function to call on specific event - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_evt_register(gsm_evt_fn fn) { - gsmr_t res = gsmOK; - gsm_evt_func_t* func, *newFunc; +lwgsmr_t +lwgsm_evt_register(lwgsm_evt_fn fn) { + lwgsmr_t res = lwgsmOK; + lwgsm_evt_func_t* func, *new_func; - GSM_ASSERT("fn != NULL", fn != NULL); + LWGSM_ASSERT("fn != NULL", fn != NULL); - gsm_core_lock(); + lwgsm_core_lock(); /* Check if function already exists on list */ - for (func = gsm.evt_func; func != NULL; func = func->next) { + for (func = lwgsm.evt_func; func != NULL; func = func->next) { if (func->fn == fn) { - res = gsmERR; + res = lwgsmERR; break; } } - if (res == gsmOK) { - newFunc = gsm_mem_malloc(sizeof(*newFunc)); - if (newFunc != NULL) { - GSM_MEMSET(newFunc, 0x00, sizeof(*newFunc)); - newFunc->fn = fn; /* Set function pointer */ - for (func = gsm.evt_func; func != NULL && func->next != NULL; func = func->next) {} + if (res == lwgsmOK) { + new_func = lwgsm_mem_malloc(sizeof(*new_func)); + if (new_func != NULL) { + LWGSM_MEMSET(new_func, 0x00, sizeof(*new_func)); + new_func->fn = fn; /* Set function pointer */ + for (func = lwgsm.evt_func; func != NULL && func->next != NULL; func = func->next) {} if (func != NULL) { - func->next = newFunc; /* Set new function as next */ - res = gsmOK; + func->next = new_func; /* Set new function as next */ + res = lwgsmOK; } else { - gsm_mem_free_s((void**)& newFunc); - res = gsmERRMEM; + lwgsm_mem_free_s((void**)&new_func); + res = lwgsmERRMEM; } } else { - res = gsmERRMEM; + res = lwgsmERRMEM; } } - gsm_core_unlock(); + lwgsm_core_unlock(); return res; } /** * \brief Unregister callback function for global (non-connection based) events - * \note Function must be first registered using \ref gsm_evt_register + * \note Function must be first registered using \ref lwgsm_evt_register * \param[in] fn: Callback function to remove from event list - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_evt_unregister(gsm_evt_fn fn) { - gsm_evt_func_t* func, *prev; - GSM_ASSERT("fn != NULL", fn != NULL); +lwgsmr_t +lwgsm_evt_unregister(lwgsm_evt_fn fn) { + lwgsm_evt_func_t* func, *prev; + LWGSM_ASSERT("fn != NULL", fn != NULL); - gsm_core_lock(); - for (prev = gsm.evt_func, func = gsm.evt_func->next; func != NULL; prev = func, func = func->next) { + lwgsm_core_lock(); + for (prev = lwgsm.evt_func, func = lwgsm.evt_func->next; func != NULL; prev = func, func = func->next) { if (func->fn == fn) { prev->next = func->next; - gsm_mem_free_s((void **)&func); + lwgsm_mem_free_s((void**)&func); break; } } - gsm_core_unlock(); - return gsmOK; + lwgsm_core_unlock(); + return lwgsmOK; } /** * \brief Get event type * \param[in] cc: Event handle - * \return Event type. Member of \ref gsm_evt_type_t enumeration + * \return Event type. Member of \ref lwgsm_evt_type_t enumeration */ -gsm_evt_type_t -gsm_evt_get_type(gsm_evt_t* cc) { +lwgsm_evt_type_t +lwgsm_evt_get_type(lwgsm_evt_t* cc) { return cc->type; } /** * \brief Get reset sequence operation status * \param[in] cc: Event data - * \return Member of \ref gsmr_t enumeration + * \return Member of \ref lwgsmr_t enumeration */ -gsmr_t -gsm_evt_reset_get_result(gsm_evt_t* cc) { +lwgsmr_t +lwgsm_evt_reset_get_result(lwgsm_evt_t* cc) { return cc->evt.reset.res; } /** * \brief Get restore sequence operation status * \param[in] cc: Event data - * \return Member of \ref gsmr_t enumeration + * \return Member of \ref lwgsmr_t enumeration */ -gsmr_t -gsm_evt_restore_get_result(gsm_evt_t* cc) { +lwgsmr_t +lwgsm_evt_restore_get_result(lwgsm_evt_t* cc) { return cc->evt.restore.res; } @@ -136,18 +136,18 @@ gsm_evt_restore_get_result(gsm_evt_t* cc) { * \param[in] cc: Event data * \return Current operator handle */ -const gsm_operator_curr_t * -gsm_evt_network_operator_get_current(gsm_evt_t* cc) { +const lwgsm_operator_curr_t* +lwgsm_evt_network_operator_get_current(lwgsm_evt_t* cc) { return cc->evt.operator_current.operator_current; } /** * \brief Get operator scan operation status * \param[in] cc: Event data - * \return Member of \ref gsmr_t enumeration + * \return Member of \ref lwgsmr_t enumeration */ -gsmr_t -gsm_evt_operator_scan_get_result(gsm_evt_t* cc) { +lwgsmr_t +lwgsm_evt_operator_scan_get_result(lwgsm_evt_t* cc) { return cc->evt.operator_scan.res; } @@ -156,8 +156,8 @@ gsm_evt_operator_scan_get_result(gsm_evt_t* cc) { * \param[in] cc: Event data * \return Pointer to array of operator entries */ -gsm_operator_t * -gsm_evt_operator_scan_get_entries(gsm_evt_t* cc) { +lwgsm_operator_t* +lwgsm_evt_operator_scan_get_entries(lwgsm_evt_t* cc) { return cc->evt.operator_scan.ops; } @@ -167,7 +167,7 @@ gsm_evt_operator_scan_get_entries(gsm_evt_t* cc) { * \return Number of operators scanned */ size_t -gsm_evt_operator_scan_get_length(gsm_evt_t* cc) { +lwgsm_evt_operator_scan_get_length(lwgsm_evt_t* cc) { return cc->evt.operator_scan.opf; } @@ -177,19 +177,19 @@ gsm_evt_operator_scan_get_length(gsm_evt_t* cc) { * \return RSSI value in units of dBm */ int16_t -gsm_evt_signal_strength_get_rssi(gsm_evt_t* cc) { +lwgsm_evt_signal_strength_get_rssi(lwgsm_evt_t* cc) { return cc->evt.rssi.rssi; } -#if GSM_CFG_CONN || __DOXYGEN__ +#if LWGSM_CFG_CONN || __DOXYGEN__ /** * \brief Get buffer from received data * \param[in] cc: Event handle * \return Buffer handle */ -gsm_pbuf_p -gsm_evt_conn_recv_get_buff(gsm_evt_t* cc) { +lwgsm_pbuf_p +lwgsm_evt_conn_recv_get_buff(lwgsm_evt_t* cc) { return cc->evt.conn_data_recv.buff; } @@ -198,8 +198,8 @@ gsm_evt_conn_recv_get_buff(gsm_evt_t* cc) { * \param[in] cc: Event handle * \return Connection handle */ -gsm_conn_p -gsm_evt_conn_recv_get_conn(gsm_evt_t* cc) { +lwgsm_conn_p +lwgsm_evt_conn_recv_get_conn(lwgsm_evt_t* cc) { return cc->evt.conn_data_recv.conn; } @@ -208,8 +208,8 @@ gsm_evt_conn_recv_get_conn(gsm_evt_t* cc) { * \param[in] cc: Event handle * \return Connection handle */ -gsm_conn_p -gsm_evt_conn_send_get_conn(gsm_evt_t* cc) { +lwgsm_conn_p +lwgsm_evt_conn_send_get_conn(lwgsm_evt_t* cc) { return cc->evt.conn_data_send.conn; } @@ -219,17 +219,17 @@ gsm_evt_conn_send_get_conn(gsm_evt_t* cc) { * \return Number of bytes sent */ size_t -gsm_evt_conn_send_get_length(gsm_evt_t* cc) { +lwgsm_evt_conn_send_get_length(lwgsm_evt_t* cc) { return cc->evt.conn_data_send.sent; } /** * \brief Check if connection send was successful * \param[in] cc: Event handle - * \return Member of \ref gsmr_t enumeration + * \return Member of \ref lwgsmr_t enumeration */ -gsmr_t -gsm_evt_conn_send_get_result(gsm_evt_t* cc) { +lwgsmr_t +lwgsm_evt_conn_send_get_result(lwgsm_evt_t* cc) { return cc->evt.conn_data_send.res; } @@ -238,8 +238,8 @@ gsm_evt_conn_send_get_result(gsm_evt_t* cc) { * \param[in] cc: Event handle * \return Connection handle */ -gsm_conn_p -gsm_evt_conn_active_get_conn(gsm_evt_t* cc) { +lwgsm_conn_p +lwgsm_evt_conn_active_get_conn(lwgsm_evt_t* cc) { return cc->evt.conn_active_close.conn; } @@ -249,8 +249,8 @@ gsm_evt_conn_active_get_conn(gsm_evt_t* cc) { * \return `1` if client, `0` otherwise */ uint8_t -gsm_evt_conn_active_is_client(gsm_evt_t* cc) { - return GSM_U8(cc->evt.conn_active_close.client > 0); +lwgsm_evt_conn_active_is_client(lwgsm_evt_t* cc) { + return LWGSM_U8(cc->evt.conn_active_close.client > 0); } /** @@ -258,8 +258,8 @@ gsm_evt_conn_active_is_client(gsm_evt_t* cc) { * \param[in] cc: Event handle * \return Connection handle */ -gsm_conn_p -gsm_evt_conn_close_get_conn(gsm_evt_t* cc) { +lwgsm_conn_p +lwgsm_evt_conn_close_get_conn(lwgsm_evt_t* cc) { return cc->evt.conn_active_close.conn; } @@ -269,7 +269,7 @@ gsm_evt_conn_close_get_conn(gsm_evt_t* cc) { * \return `1` if client, `0` otherwise */ uint8_t -gsm_evt_conn_close_is_client(gsm_evt_t* cc) { +lwgsm_evt_conn_close_is_client(lwgsm_evt_t* cc) { return cc->evt.conn_active_close.client; } @@ -279,17 +279,17 @@ gsm_evt_conn_close_is_client(gsm_evt_t* cc) { * \return `1` if forced, `0` otherwise */ uint8_t -gsm_evt_conn_close_is_forced(gsm_evt_t* cc) { +lwgsm_evt_conn_close_is_forced(lwgsm_evt_t* cc) { return cc->evt.conn_active_close.forced; } /** * \brief Get connection close event result * \param[in] cc: Event handle - * \return Member of \ref gsmr_t enumeration + * \return Member of \ref lwgsmr_t enumeration */ -gsmr_t -gsm_evt_conn_close_get_result(gsm_evt_t* cc) { +lwgsmr_t +lwgsm_evt_conn_close_get_result(lwgsm_evt_t* cc) { return cc->evt.conn_active_close.res; } @@ -298,28 +298,28 @@ gsm_evt_conn_close_get_result(gsm_evt_t* cc) { * \param[in] cc: Event handle * \return Connection handle */ -gsm_conn_p -gsm_evt_conn_poll_get_conn(gsm_evt_t* cc) { +lwgsm_conn_p +lwgsm_evt_conn_poll_get_conn(lwgsm_evt_t* cc) { return cc->evt.conn_poll.conn; } /** * \brief Get connection error type * \param[in] cc: Event handle - * \return Member of \ref gsmr_t enumeration + * \return Member of \ref lwgsmr_t enumeration */ -gsmr_t -gsm_evt_conn_error_get_error(gsm_evt_t* cc) { +lwgsmr_t +lwgsm_evt_conn_error_get_error(lwgsm_evt_t* cc) { return cc->evt.conn_error.err; } /** * \brief Get connection type * \param[in] cc: Event handle - * \return Member of \ref gsmr_t enumeration + * \return Member of \ref lwgsmr_t enumeration */ -gsm_conn_type_t -gsm_evt_conn_error_get_type(gsm_evt_t* cc) { +lwgsm_conn_type_t +lwgsm_evt_conn_error_get_type(lwgsm_evt_t* cc) { return cc->evt.conn_error.type; } @@ -328,8 +328,8 @@ gsm_evt_conn_error_get_type(gsm_evt_t* cc) { * \param[in] cc: Event handle * \return Host name for connection */ -const char * -gsm_evt_conn_error_get_host(gsm_evt_t* cc) { +const char* +lwgsm_evt_conn_error_get_host(lwgsm_evt_t* cc) { return cc->evt.conn_error.host; } @@ -338,8 +338,8 @@ gsm_evt_conn_error_get_host(gsm_evt_t* cc) { * \param[in] cc: Event handle * \return Host port number */ -gsm_port_t -gsm_evt_conn_error_get_port(gsm_evt_t* cc) { +lwgsm_port_t +lwgsm_evt_conn_error_get_port(lwgsm_evt_t* cc) { return cc->evt.conn_error.port; } @@ -348,14 +348,14 @@ gsm_evt_conn_error_get_port(gsm_evt_t* cc) { * \param[in] cc: Event handle * \return User argument */ -void * -gsm_evt_conn_error_get_arg(gsm_evt_t* cc) { +void* +lwgsm_evt_conn_error_get_arg(lwgsm_evt_t* cc) { return cc->evt.conn_error.arg; } -#endif /* GSM_CFG_CONN || __DOXYGEN__ */ +#endif /* LWGSM_CFG_CONN || __DOXYGEN__ */ -#if GSM_CFG_SMS || __DOXYGEN__ +#if LWGSM_CFG_SMS || __DOXYGEN__ /** * \brief Get SMS position in memory which has been saved on receive @@ -363,7 +363,7 @@ gsm_evt_conn_error_get_arg(gsm_evt_t* cc) { * \return SMS position in memory */ size_t -gsm_evt_sms_recv_get_pos(gsm_evt_t* cc) { +lwgsm_evt_sms_recv_get_pos(lwgsm_evt_t* cc) { return cc->evt.sms_recv.pos; } @@ -372,8 +372,8 @@ gsm_evt_sms_recv_get_pos(gsm_evt_t* cc) { * \param[in] cc: Event handle * \return SMS memory location */ -gsm_mem_t -gsm_evt_sms_recv_get_mem(gsm_evt_t* cc) { +lwgsm_mem_t +lwgsm_evt_sms_recv_get_mem(lwgsm_evt_t* cc) { return cc->evt.sms_recv.mem; } @@ -382,8 +382,8 @@ gsm_evt_sms_recv_get_mem(gsm_evt_t* cc) { * \param[in] cc: Event handle * \return SMS entry */ -gsm_sms_entry_t * -gsm_evt_sms_read_get_entry(gsm_evt_t* cc) { +lwgsm_sms_entry_t* +lwgsm_evt_sms_read_get_entry(lwgsm_evt_t* cc) { return cc->evt.sms_read.entry; } @@ -392,18 +392,18 @@ gsm_evt_sms_read_get_entry(gsm_evt_t* cc) { * \param[in] cc: Event handle * \return SMS entry */ -gsmr_t -gsm_evt_sms_read_get_result(gsm_evt_t* cc) { +lwgsmr_t +lwgsm_evt_sms_read_get_result(lwgsm_evt_t* cc) { return cc->evt.sms_read.res; } /** * \brief Get SMS send result status * \param[in] cc: Event handle - * \return Member of \ref gsmr_t enumeration + * \return Member of \ref lwgsmr_t enumeration */ -gsmr_t -gsm_evt_sms_send_get_result(gsm_evt_t* cc) { +lwgsmr_t +lwgsm_evt_sms_send_get_result(lwgsm_evt_t* cc) { return cc->evt.sms_send.res; } @@ -414,17 +414,17 @@ gsm_evt_sms_send_get_result(gsm_evt_t* cc) { * \return Position in memory */ size_t -gsm_evt_sms_send_get_pos(gsm_evt_t* cc) { +lwgsm_evt_sms_send_get_pos(lwgsm_evt_t* cc) { return cc->evt.sms_send.pos; } /** * \brief Get SMS delete result status * \param[in] cc: Event handle - * \return Member of \ref gsmr_t enumeration + * \return Member of \ref lwgsmr_t enumeration */ -gsmr_t -gsm_evt_sms_delete_get_result(gsm_evt_t* cc) { +lwgsmr_t +lwgsm_evt_sms_delete_get_result(lwgsm_evt_t* cc) { return cc->evt.sms_delete.res; } @@ -434,7 +434,7 @@ gsm_evt_sms_delete_get_result(gsm_evt_t* cc) { * \return Deleted position in memory */ size_t -gsm_evt_sms_delete_get_pos(gsm_evt_t* cc) { +lwgsm_evt_sms_delete_get_pos(lwgsm_evt_t* cc) { return cc->evt.sms_delete.pos; } @@ -443,23 +443,23 @@ gsm_evt_sms_delete_get_pos(gsm_evt_t* cc) { * \param[in] cc: Event handle * \return SMS memory for delete operation */ -gsm_mem_t -gsm_evt_sms_delete_get_mem(gsm_evt_t* cc) { +lwgsm_mem_t +lwgsm_evt_sms_delete_get_mem(lwgsm_evt_t* cc) { return cc->evt.sms_delete.mem; } -#endif /* GSM_CFG_SMS || __DOXYGEN__ */ +#endif /* LWGSM_CFG_SMS || __DOXYGEN__ */ -#if GSM_CFG_CALL || __DOXYGEN__ +#if LWGSM_CFG_CALL || __DOXYGEN__ /** * \brief Get call information from changed event * \param[in] cc: Event handle * \return Position in memory */ -const gsm_call_t * -gsm_evt_call_changed_get_call(gsm_evt_t* cc) { - return gsm.evt.evt.call_changed.call; +const lwgsm_call_t* +lwgsm_evt_call_changed_get_call(lwgsm_evt_t* cc) { + return lwgsm.evt.evt.call_changed.call; } -#endif /* GSM_CFG_CALL || __DOXYGEN__ */ +#endif /* LWGSM_CFG_CALL || __DOXYGEN__ */ diff --git a/gsm_at_lib/src/gsm/gsm_ftp.c b/lwgsm/src/lwgsm/lwgsm_ftp.c similarity index 78% rename from gsm_at_lib/src/gsm/gsm_ftp.c rename to lwgsm/src/lwgsm/lwgsm_ftp.c index 8998cb4e..a8450ce4 100644 --- a/gsm_at_lib/src/gsm/gsm_ftp.c +++ b/lwgsm/src/lwgsm/lwgsm_ftp.c @@ -1,10 +1,10 @@ -/** - * \file gsm_ftp.c +/** + * \file lwgsm_ftp.c * \brief FTP API */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,15 +26,15 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_ftp.h" -#include "gsm/gsm_mem.h" +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_ftp.h" +#include "lwgsm/lwgsm_mem.h" -#if GSM_CFG_FTP || __DOXYGEN__ +#if LWGSM_CFG_FTP || __DOXYGEN__ -#endif /* GSM_CFG_FTP || __DOXYGEN__ */ +#endif /* LWGSM_CFG_FTP || __DOXYGEN__ */ diff --git a/gsm_at_lib/src/gsm/gsm_http.c b/lwgsm/src/lwgsm/lwgsm_http.c similarity index 78% rename from gsm_at_lib/src/gsm/gsm_http.c rename to lwgsm/src/lwgsm/lwgsm_http.c index 2b845612..5a1db9d8 100644 --- a/gsm_at_lib/src/gsm/gsm_http.c +++ b/lwgsm/src/lwgsm/lwgsm_http.c @@ -1,10 +1,10 @@ -/** - * \file gsm_http.c +/** + * \file lwgsm_http.c * \brief HTTP API */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,15 +26,15 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_http.h" -#include "gsm/gsm_mem.h" +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_http.h" +#include "lwgsm/lwgsm_mem.h" -#if GSM_CFG_HTTP || __DOXYGEN__ +#if LWGSM_CFG_HTTP || __DOXYGEN__ -#endif /* GSM_CFG_HTTP || __DOXYGEN__ */ +#endif /* LWGSM_CFG_HTTP || __DOXYGEN__ */ diff --git a/gsm_at_lib/src/gsm/gsm_input.c b/lwgsm/src/lwgsm/lwgsm_input.c similarity index 52% rename from gsm_at_lib/src/gsm/gsm_input.c rename to lwgsm/src/lwgsm/lwgsm_input.c index 38dac471..8c82b7ef 100644 --- a/gsm_at_lib/src/gsm/gsm_input.c +++ b/lwgsm/src/lwgsm/lwgsm_input.c @@ -1,10 +1,10 @@ /** - * \file gsm_input.c + * \file lwgsm_input.c * \brief Wrapper for passing input data to stack */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,70 +26,70 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_private.h" -#include "gsm/gsm.h" -#include "gsm/gsm_input.h" -#include "gsm/gsm_buff.h" +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm.h" +#include "lwgsm/lwgsm_input.h" +#include "lwgsm/lwgsm_buff.h" -static uint32_t gsm_recv_total_len; -static uint32_t gsm_recv_calls; +static uint32_t lwgsm_recv_total_len; +static uint32_t lwgsm_recv_calls; -#if !GSM_CFG_INPUT_USE_PROCESS || __DOXYGEN__ +#if !LWGSM_CFG_INPUT_USE_PROCESS || __DOXYGEN__ /** * \brief Write data to input buffer - * \note \ref GSM_CFG_INPUT_USE_PROCESS must be disabled to use this function + * \note \ref LWGSM_CFG_INPUT_USE_PROCESS must be disabled to use this function * \param[in] data: Pointer to data to write * \param[in] len: Number of data elements in units of bytes - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_input(const void* data, size_t len) { - if (!gsm.status.f.initialized || gsm.buff.buff == NULL) { - return gsmERR; +lwgsmr_t +lwgsm_input(const void* data, size_t len) { + if (!lwgsm.status.f.initialized || lwgsm.buff.buff == NULL) { + return lwgsmERR; } - gsm_buff_write(&gsm.buff, data, len); /* Write data to buffer */ - gsm_sys_mbox_putnow(&gsm.mbox_process, NULL); /* Write empty box, don't care if write fails */ - gsm_recv_total_len += len; /* Update total number of received bytes */ - gsm_recv_calls++; /* Update number of calls */ - return gsmOK; + lwgsm_buff_write(&lwgsm.buff, data, len); /* Write data to buffer */ + lwgsm_sys_mbox_putnow(&lwgsm.mbox_process, NULL); /* Write empty box, don't care if write fails */ + lwgsm_recv_total_len += len; /* Update total number of received bytes */ + ++lwgsm_recv_calls; /* Update number of calls */ + return lwgsmOK; } -#endif /* !GSM_CFG_INPUT_USE_PROCESS || __DOXYGEN__ */ +#endif /* !LWGSM_CFG_INPUT_USE_PROCESS || __DOXYGEN__ */ -#if GSM_CFG_INPUT_USE_PROCESS || __DOXYGEN__ +#if LWGSM_CFG_INPUT_USE_PROCESS || __DOXYGEN__ /** * \brief Process input data directly without writing it to input buffer * \note This function may only be used when in OS mode, * where single thread is dedicated for input read of AT receive * - * \note \ref GSM_CFG_INPUT_USE_PROCESS must be enabled to use this function + * \note \ref LWGSM_CFG_INPUT_USE_PROCESS must be enabled to use this function * * \param[in] data: Pointer to received data to be processed * \param[in] len: Length of data to process in units of bytes - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_input_process(const void* data, size_t len) { - gsmr_t res; +lwgsmr_t +lwgsm_input_process(const void* data, size_t len) { + lwgsmr_t res; - if (!gsm.status.f.initialized) { - return gsmERR; + if (!lwgsm.status.f.initialized) { + return lwgsmERR; } - gsm_recv_total_len += len; /* Update total number of received bytes */ - gsm_recv_calls++; /* Update number of calls */ + lwgsm_recv_total_len += len; /* Update total number of received bytes */ + ++lwgsm_recv_calls; /* Update number of calls */ - gsm_core_lock(); - res = gsmi_process(data, len); /* Process input data */ - gsm_core_unlock(); + lwgsm_core_lock(); + res = lwgsmi_process(data, len); /* Process input data */ + lwgsm_core_unlock(); return res; } -#endif /* GSM_CFG_INPUT_USE_PROCESS || __DOXYGEN__ */ +#endif /* LWGSM_CFG_INPUT_USE_PROCESS || __DOXYGEN__ */ diff --git a/lwgsm/src/lwgsm/lwgsm_int.c b/lwgsm/src/lwgsm/lwgsm_int.c new file mode 100644 index 00000000..e9b782a5 --- /dev/null +++ b/lwgsm/src/lwgsm/lwgsm_int.c @@ -0,0 +1,2391 @@ +/** + * \file lwgsm_int.c + * \brief Internal functions + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm.h" +#include "lwgsm/lwgsm_int.h" +#include "lwgsm/lwgsm_mem.h" +#include "lwgsm/lwgsm_parser.h" +#include "lwgsm/lwgsm_unicode.h" +#include "system/lwgsm_ll.h" + +#if !__DOXYGEN__ +/** + * \brief Receive character structure to handle full line terminated with `\n` character + */ +typedef struct { + char data[128]; /*!< Received characters */ + size_t len; /*!< Length of valid characters */ +} lwgsm_recv_t; + +/* Receive character macros */ +#define RECV_ADD(ch) do { if (recv_buff.len < (sizeof(recv_buff.data)) - 1) { recv_buff.data[recv_buff.len++] = ch; recv_buff.data[recv_buff.len] = 0; } } while (0) +#define RECV_RESET() do { recv_buff.len = 0; recv_buff.data[0] = 0; } while (0) +#define RECV_LEN() ((size_t)recv_buff.len) +#define RECV_IDX(index) recv_buff.data[index] + +/* Send data over AT port */ +#define AT_PORT_SEND_STR(str) lwgsm.ll.send_fn((const void *)(str), (size_t)strlen(str)) +#define AT_PORT_SEND_CONST_STR(str) lwgsm.ll.send_fn((const void *)(str), (size_t)(sizeof(str) - 1)) +#define AT_PORT_SEND_CHR(ch) lwgsm.ll.send_fn((const void *)(ch), (size_t)1) +#define AT_PORT_SEND_FLUSH() lwgsm.ll.send_fn(NULL, 0) +#define AT_PORT_SEND(d, l) lwgsm.ll.send_fn((const void *)(d), (size_t)(l)) +#define AT_PORT_SEND_WITH_FLUSH(d, l) do { AT_PORT_SEND((d), (l)); AT_PORT_SEND_FLUSH(); } while (0) + +/* Beginning and end of every AT command */ +#define AT_PORT_SEND_BEGIN_AT() do { AT_PORT_SEND_CONST_STR("AT"); } while (0) +#define AT_PORT_SEND_END_AT() do { AT_PORT_SEND(CRLF, CRLF_LEN); AT_PORT_SEND(NULL, 0); } while (0) + +/* Send special characters over AT port with condition */ +#define AT_PORT_SEND_QUOTE_COND(q) do { if ((q)) { AT_PORT_SEND_CONST_STR("\""); } } while (0) +#define AT_PORT_SEND_COMMA_COND(c) do { if ((c)) { AT_PORT_SEND_CONST_STR(","); } } while (0) +#define AT_PORT_SEND_EQUAL_COND(e) do { if ((e)) { AT_PORT_SEND_CONST_STR("="); } } while (0) + +/* Send special characters */ +#define AT_PORT_SEND_CTRL_Z() AT_PORT_SEND_STR("\x1A") +#define AT_PORT_SEND_ESC() AT_PORT_SEND_STR("\x1B") +#endif /* !__DOXYGEN__ */ + +static lwgsm_recv_t recv_buff; +static lwgsmr_t lwgsmi_process_sub_cmd(lwgsm_msg_t* msg, uint8_t* is_ok, uint16_t* is_error); + +/** + * \brief Memory mapping + */ +const lwgsm_dev_mem_map_t +lwgsm_dev_mem_map[] = { +#define LWGSM_DEV_MEMORY_ENTRY(name, str_code) { LWGSM_MEM_ ## name, str_code }, +#include "lwgsm/lwgsm_memories.h" +}; + +/** + * \brief Size of device memory mapping array + */ +const size_t +lwgsm_dev_mem_map_size = LWGSM_ARRAYSIZE(lwgsm_dev_mem_map); + +/** + * \brief List of supported devices + */ +const lwgsm_dev_model_map_t +lwgsm_dev_model_map[] = { +#define LWGSM_DEVICE_MODEL_ENTRY(name, str_id, is_2g, is_lte) { LWGSM_DEVICE_MODEL_ ## name, str_id, is_2g, is_lte }, +#include "lwgsm/lwgsm_models.h" +}; + +/** + * \brief Size of device models mapping array + */ +const size_t +lwgsm_dev_model_map_size = LWGSM_ARRAYSIZE(lwgsm_dev_model_map); + +/** + * \brief Free connection send data memory + * \param[in] m: Send data message type + */ +#define CONN_SEND_DATA_FREE(m) do { \ + if ((m) != NULL && (m)->msg.conn_send.fau) { \ + (m)->msg.conn_send.fau = 0; \ + if ((m)->msg.conn_send.data != NULL) { \ + LWGSM_DEBUGF(LWGSM_CFG_DBG_CONN | LWGSM_DBG_TYPE_TRACE, \ + "[CONN] Free write buffer fau: %p\r\n", (void *)(m)->msg.conn_send.data); \ + lwgsm_mem_free_s((void **)&((m)->msg.conn_send.data)); \ + } \ + } \ + } while (0) + +/** + * \brief Send connection callback for "data send" + * \param[in] m: Command message + * \param[in] err: Error of type \ref lwgsmr_t + */ +#define CONN_SEND_DATA_SEND_EVT(m, err) do { \ + CONN_SEND_DATA_FREE(m); \ + lwgsm.evt.type = LWGSM_EVT_CONN_SEND; \ + lwgsm.evt.evt.conn_data_send.res = err; \ + lwgsm.evt.evt.conn_data_send.conn = (m)->msg.conn_send.conn; \ + lwgsm.evt.evt.conn_data_send.sent = (m)->msg.conn_send.sent_all; \ + lwgsmi_send_conn_cb((m)->msg.conn_send.conn, NULL); \ + } while (0) + +/** + * \brief Send reset sequence event + * \param[in] m: Command message + * \param[in] err: Error of type \ref lwgsmr_t + */ +#define RESET_SEND_EVT(m, err) do { \ + lwgsm.evt.evt.reset.res = err; \ + lwgsmi_send_cb(LWGSM_EVT_RESET); \ + } while (0) + +/** + * \brief Send restore sequence event + * \param[in] m: Connection send message + * \param[in] err: Error of type \ref lwgsmr_t + */ +#define RESTORE_SEND_EVT(m, err) do { \ + lwgsm.evt.evt.restore.res = err; \ + lwgsmi_send_cb(LWGSM_EVT_RESTORE); \ + } while (0) + +/** + * \brief Send operator scan sequence event + * \param[in] m: Command message + * \param[in] err: Error of type \ref lwgsmr_t + */ +#define OPERATOR_SCAN_SEND_EVT(m, err) do { \ + lwgsm.evt.evt.operator_scan.res = err; \ + lwgsm.evt.evt.operator_scan.ops = (m)->msg.cops_scan.ops; \ + lwgsm.evt.evt.operator_scan.opf = *(m)->msg.cops_scan.opf;\ + lwgsmi_send_cb(LWGSM_EVT_OPERATOR_SCAN); \ + } while (0) + +/** +* \brief Send SMS delete operation event +* \param[in] m: SMS delete message +* \param[in] err: Error of type \ref lwgsmr_t +*/ +#define SMS_SEND_DELETE_EVT(m, err) do { \ + lwgsm.evt.evt.sms_delete.res = err; \ + lwgsm.evt.evt.sms_delete.mem = (m)->msg.sms_delete.mem; \ + lwgsm.evt.evt.sms_delete.pos = (m)->msg.sms_delete.pos; \ + lwgsmi_send_cb(LWGSM_EVT_SMS_DELETE); \ + } while (0) + +/** + * \brief Send SMS read operation event + * \param[in] m: SMS read message + * \param[in] err: Error of type \ref lwgsmr_t + */ +#define SMS_SEND_READ_EVT(m, err) do { \ + lwgsm.evt.evt.sms_read.res = err; \ + lwgsm.evt.evt.sms_read.entry = (m)->msg.sms_read.entry; \ + lwgsmi_send_cb(LWGSM_EVT_SMS_READ); \ + } while (0) + +/** + * \brief Send SMS read operation event + * \param[in] mm: SMS list message + * \param[in] err: Error of type \ref lwgsmr_t + */ +#define SMS_SEND_LIST_EVT(mm, err) do { \ + lwgsm.evt.evt.sms_list.mem = lwgsm.m.sms.mem[0].current;\ + lwgsm.evt.evt.sms_list.entries = (mm)->msg.sms_list.entries; \ + lwgsm.evt.evt.sms_list.size = (mm)->msg.sms_list.ei; \ + lwgsm.evt.evt.sms_list.res = err; \ + lwgsmi_send_cb(LWGSM_EVT_SMS_LIST); \ + } while (0) + +/** + * \brief Send SMS send operation event + * \param[in] m: SMS send message + * \param[in] err: Error of type \ref lwgsmr_t + */ +#define SMS_SEND_SEND_EVT(m, err) do { \ + lwgsm.evt.evt.sms_send.pos = (m)->msg.sms_send.pos; \ + lwgsm.evt.evt.sms_send.res = err; \ + lwgsmi_send_cb(LWGSM_EVT_SMS_SEND); \ + } while (0) + +/** + * \brief Get SIM info when SIM is ready + * \param[in] blocking: Blocking command + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsmi_get_sim_info(const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_SIM_PROCESS_BASIC_CMDS; + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CNUM; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); +} + +/** + * \brief Send IP or MAC address to AT port + * \param[in] d: Pointer to IP or MAC address + * \param[in] is_ip: Set to `1` when sending IP, `0` when MAC + * \param[in] q: Set to `1` to include start and ending quotes + * \param[in] c: Set to `1` to include comma before string + */ +void +lwgsmi_send_ip_mac(const void* d, uint8_t is_ip, uint8_t q, uint8_t c) { + uint8_t ch; + char str[4]; + const lwgsm_mac_t* mac = d; + const lwgsm_ip_t* ip = d; + + AT_PORT_SEND_COMMA_COND(c); /* Send comma */ + if (d == NULL) { + return; + } + AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ + ch = is_ip ? '.' : ':'; /* Get delimiter character */ + for (uint8_t i = 0; i < (is_ip ? 4 : 6); ++i) { /* Process byte by byte */ + if (is_ip) { /* In case of IP ... */ + lwgsm_u8_to_str(ip->ip[i], str); /* ... go to decimal format ... */ + } else { /* ... in case of MAC ... */ + lwgsm_u8_to_hex_str(mac->mac[i], str, 2); /* ... go to HEX format */ + } + AT_PORT_SEND_STR(str); /* Send str */ + if (i < (is_ip ? 4 : 6) - 1) { /* Check end if characters */ + AT_PORT_SEND_CHR(&ch); /* Send character */ + } + } + AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ +} + +/** + * \brief Send string to AT port, either plain or escaped + * \param[in] str: Pointer to input string to string + * \param[in] e: Value to indicate string send format, escaped (`1`) or plain (`0`) + * \param[in] q: Value to indicate starting and ending quotes, enabled (`1`) or disabled (`0`) + * \param[in] c: Set to `1` to include comma before string + */ +void +lwgsmi_send_string(const char* str, uint8_t e, uint8_t q, uint8_t c) { + char special = '\\'; + + AT_PORT_SEND_COMMA_COND(c); /* Send comma */ + AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ + if (str != NULL) { + if (e) { /* Do we have to escape string? */ + while (*str) { /* Go through string */ + if (*str == ',' || *str == '"' || *str == '\\') { /* Check for special character */ + AT_PORT_SEND_CHR(&special); /* Send special character */ + } + AT_PORT_SEND_CHR(str); /* Send character */ + ++str; + } + } else { + AT_PORT_SEND_STR(str); /* Send plain string */ + } + } + AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ +} + +/** + * \brief Send number (decimal) to AT port + * \param[in] num: Number to send to AT port + * \param[in] q: Value to indicate starting and ending quotes, enabled (`1`) or disabled (`0`) + * \param[in] c: Set to `1` to include comma before string + */ +void +lwgsmi_send_number(uint32_t num, uint8_t q, uint8_t c) { + char str[11]; + + lwgsm_u32_to_str(num, str); /* Convert digit to decimal string */ + + AT_PORT_SEND_COMMA_COND(c); /* Send comma */ + AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ + AT_PORT_SEND_STR(str); /* Send string with number */ + AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ +} + +/** + * \brief Send port number to AT port + * \param[in] port: Port number to send + * \param[in] q: Value to indicate starting and ending quotes, enabled (`1`) or disabled (`0`) + * \param[in] c: Set to `1` to include comma before string + */ +void +lwgsmi_send_port(lwgsm_port_t port, uint8_t q, uint8_t c) { + char str[6]; + + lwgsm_u16_to_str(LWGSM_PORT2NUM(port), str);/* Convert digit to decimal string */ + + AT_PORT_SEND_COMMA_COND(c); /* Send comma */ + AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ + AT_PORT_SEND_STR(str); /* Send string with number */ + AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ +} + +/** + * \brief Send signed number to AT port + * \param[in] num: Number to send to AT port + * \param[in] q: Value to indicate starting and ending quotes, enabled (`1`) or disabled (`0`) + * \param[in] c: Set to `1` to include comma before string + */ +void +lwgsmi_send_signed_number(int32_t num, uint8_t q, uint8_t c) { + char str[11]; + + lwgsm_i32_to_str(num, str); /* Convert digit to decimal string */ + + AT_PORT_SEND_COMMA_COND(c); /* Send comma */ + AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ + AT_PORT_SEND_STR(str); /* Send string with number */ + AT_PORT_SEND_QUOTE_COND(q); /* Send quote */ +} + +/** + * \brief Send memory string to device + * \param[in] mem: Memory index to send + * \param[in] q: Value to indicate starting and ending quotes, enabled (`1`) or disabled (`0`) + * \param[in] c: Set to `1` to include comma before string + */ +void +lwgsmi_send_dev_memory(lwgsm_mem_t mem, uint8_t q, uint8_t c) { + if (mem < LWGSM_MEM_END) { /* Check valid range */ + lwgsmi_send_string(lwgsm_dev_mem_map[LWGSM_SZ(mem)].mem_str, 0, q, c); + } +} + +#if LWGSM_CFG_SMS || __DOXYGEN__ + +/** + * \brief Send SMS status text + * \param[in] status: SMS status + * \param[in] q: Value to indicate starting and ending quotes, enabled (`1`) or disabled (`0`) + * \param[in] c: Set to `1` to include comma before string + */ +void +lwgsmi_send_sms_stat(lwgsm_sms_status_t status, uint8_t q, uint8_t c) { + const char* t; + switch (status) { + case LWGSM_SMS_STATUS_UNREAD: + t = "REC UNREAD"; + break; + case LWGSM_SMS_STATUS_READ: + t = "REC READ"; + break; + case LWGSM_SMS_STATUS_UNSENT: + t = "STO UNSENT"; + break; + case LWGSM_SMS_STATUS_SENT: + t = "STO SENT"; + break; + case LWGSM_SMS_STATUS_ALL: + default: + t = "ALL"; + break; + } + lwgsmi_send_string(t, 0, q, c); +} + +#endif /* LWGSM_CFG_SMS */ + +#if LWGSM_CFG_CONN || __DOXYGEN__ + +/** + * \brief Reset all connections + * \note Used to notify upper layer stack to close everything and reset the memory if necessary + * \param[in] forced: Flag indicating reset was forced by user + */ +static void +reset_connections(uint8_t forced) { + lwgsm.evt.type = LWGSM_EVT_CONN_CLOSE; + lwgsm.evt.evt.conn_active_close.forced = forced; + lwgsm.evt.evt.conn_active_close.res = lwgsmOK; + + for (size_t i = 0; i < LWGSM_CFG_MAX_CONNS; ++i) { /* Check all connections */ + if (lwgsm.m.conns[i].status.f.active) { + lwgsm.m.conns[i].status.f.active = 0; + + lwgsm.evt.evt.conn_active_close.conn = &lwgsm.m.conns[i]; + lwgsm.evt.evt.conn_active_close.client = lwgsm.m.conns[i].status.f.client; + lwgsmi_send_conn_cb(&lwgsm.m.conns[i], NULL); /* Send callback function */ + } + } +} + +#endif /* LWGSM_CFG_CONN || __DOXYGEN__ */ + +/** + * \brief Reset everything after reset was detected + * \param[in] forced: Set to `1` if reset forced by user + */ +void +lwgsmi_reset_everything(uint8_t forced) { + /** + * \todo: Put stack to default state: + * - Close all the connection in memory + * - Clear entire data memory + * - Reset GSM structure + */ + +#if LWGSM_CFG_CONN + /* Manually close all connections in memory */ + reset_connections(forced); + + /* Check if IPD active */ + if (lwgsm.m.ipd.buff != NULL) { + lwgsm_pbuf_free(lwgsm.m.ipd.buff); + lwgsm.m.ipd.buff = NULL; + } +#endif /* LWGSM_CFG_CONN */ + +#if LWGSM_CFG_NETWORK + /* Notify app about detached network PDP context */ + if (lwgsm.m.network.is_attached) { + lwgsm.m.network.is_attached = 0; + lwgsmi_send_cb(LWGSM_EVT_NETWORK_DETACHED); + } +#endif /* LWGSM_CFG_NETWORK */ + + /* Invalid GSM modules */ + LWGSM_MEMSET(&lwgsm.m, 0x00, sizeof(lwgsm.m)); + + /* Manually set states */ + lwgsm.m.sim.state = (lwgsm_sim_state_t) -1; + lwgsm.m.model = LWGSM_DEVICE_MODEL_UNKNOWN; +} + +/** + * \brief Process callback function to user with specific type + * \param[in] type: Callback event type + * \return Member of \ref lwgsmr_t enumeration + */ +lwgsmr_t +lwgsmi_send_cb(lwgsm_evt_type_t type) { + lwgsm.evt.type = type; /* Set callback type to process */ + + /* Call callback function for all registered functions */ + for (lwgsm_evt_func_t* link = lwgsm.evt_func; link != NULL; link = link->next) { + link->fn(&lwgsm.evt); + } + return lwgsmOK; +} + +#if LWGSM_CFG_CONN || __DOXYGEN__ + +/** + * \brief Process connection callback + * \note Before calling function, callback structure must be prepared + * \param[in] conn: Pointer to connection to use as callback + * \param[in] evt: Event callback function for connection + * \return Member of \ref lwgsmr_t enumeration + */ +lwgsmr_t +lwgsmi_send_conn_cb(lwgsm_conn_t* conn, lwgsm_evt_fn evt) { + if (conn->status.f.in_closing && lwgsm.evt.type != LWGSM_EVT_CONN_CLOSE) { /* Do not continue if in closing mode */ + /* return lwgsmOK; */ + } + + if (evt != NULL) { /* Try with user connection */ + return evt(&lwgsm.evt); /* Call temporary function */ + } else if (conn != NULL && conn->evt_func != NULL) {/* Connection custom callback? */ + return conn->evt_func(&lwgsm.evt); /* Process callback function */ + } else if (conn == NULL) { + return lwgsmOK; + } + + /* + * On normal API operation, + * we should never enter to this part of code + */ + + /* + * If connection doesn't have callback function + * automatically close the connection? + * + * Since function call is non-blocking, + * it will set active connection to closing mode + * and further callback events should not be executed anymore + */ + return lwgsm_conn_close(conn, 0); +} + +/** + * \brief Process and send data from device buffer + * \return Member of \ref lwgsmr_t enumeration + */ +static lwgsmr_t +lwgsmi_tcpip_process_send_data(void) { + lwgsm_conn_t* c = lwgsm.msg->msg.conn_send.conn; + if (!lwgsm_conn_is_active(c) || /* Is the connection already closed? */ + lwgsm.msg->msg.conn_send.val_id != c->val_id/* Did validation ID change after we set parameter? */ + ) { + /* Send event to user about failed send event */ + CONN_SEND_DATA_SEND_EVT(lwgsm.msg, lwgsmCLOSED); + return lwgsmERR; + } + lwgsm.msg->msg.conn_send.sent = LWGSM_MIN(lwgsm.msg->msg.conn_send.btw, LWGSM_CFG_CONN_MAX_DATA_LEN); + + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CIPSEND="); + lwgsmi_send_number(LWGSM_U32(c->num), 0, 0);/* Send connection number */ + lwgsmi_send_number(LWGSM_U32(lwgsm.msg->msg.conn_send.sent), 0, 1); /* Send length number */ + + /* On UDP connections, IP address and port may be selected */ + if (c->type == LWGSM_CONN_TYPE_UDP) { + if (lwgsm.msg->msg.conn_send.remote_ip != NULL && lwgsm.msg->msg.conn_send.remote_port) { + lwgsmi_send_ip_mac(lwgsm.msg->msg.conn_send.remote_ip, 1, 1, 1);/* Send IP address including quotes */ + lwgsmi_send_port(lwgsm.msg->msg.conn_send.remote_port, 0, 1); /* Send length number */ + } + } + AT_PORT_SEND_END_AT(); + return lwgsmOK; +} + +/** + * \brief Process data sent and send remaining + * \param[in] sent: Status whether data were sent or not, + * info received from GSM with "SEND OK" or "SEND FAIL" + * \return `1` in case we should stop sending or `0` if we still have data to process + */ +static uint8_t +lwgsmi_tcpip_process_data_sent(uint8_t sent) { + if (sent) { /* Data were successfully sent */ + lwgsm.msg->msg.conn_send.sent_all += lwgsm.msg->msg.conn_send.sent; + lwgsm.msg->msg.conn_send.btw -= lwgsm.msg->msg.conn_send.sent; + lwgsm.msg->msg.conn_send.ptr += lwgsm.msg->msg.conn_send.sent; + if (lwgsm.msg->msg.conn_send.bw != NULL) { + *lwgsm.msg->msg.conn_send.bw += lwgsm.msg->msg.conn_send.sent; + } + lwgsm.msg->msg.conn_send.tries = 0; + } else { /* We were not successful */ + ++lwgsm.msg->msg.conn_send.tries; /* Increase number of tries */ + if (lwgsm.msg->msg.conn_send.tries == LWGSM_CFG_MAX_SEND_RETRIES) { /* In case we reached max number of retransmissions */ + return 1; /* Return 1 and indicate error */ + } + } + if (lwgsm.msg->msg.conn_send.btw > 0) { /* Do we still have data to send? */ + if (lwgsmi_tcpip_process_send_data() != lwgsmOK) { /* Check if we can continue */ + return 1; /* Finish at this point */ + } + return 0; /* We still have data to send */ + } + return 1; /* Everything was sent, we can stop execution */ +} + +/** + * \brief Process CIPSEND response + * \param[in] rcv: Received data + * \param[in,out] is_ok: Pointer to current ok status + * \param[in,out] is_error: Pointer to current error status + */ +void +lwgsmi_process_cipsend_response(lwgsm_recv_t* rcv, uint8_t* is_ok, uint16_t* is_error) { + if (lwgsm.msg->msg.conn_send.wait_send_ok_err) { + if (LWGSM_CHARISNUM(rcv->data[0]) && rcv->data[1] == ',') { + uint8_t num = LWGSM_CHARTONUM(rcv->data[0]); + if (!strncmp(&rcv->data[3], "SEND OK" CRLF, 7 + CRLF_LEN)) { + lwgsm.msg->msg.conn_send.wait_send_ok_err = 0; + *is_ok = lwgsmi_tcpip_process_data_sent(1); /* Process as data were sent */ + if (*is_ok && lwgsm.msg->msg.conn_send.conn->status.f.active) { + CONN_SEND_DATA_SEND_EVT(lwgsm.msg, lwgsmOK); + } + } else if (!strncmp(&rcv->data[3], "SEND FAIL" CRLF, 9 + CRLF_LEN)) { + lwgsm.msg->msg.conn_send.wait_send_ok_err = 0; + *is_error = lwgsmi_tcpip_process_data_sent(0); /* Data were not sent due to SEND FAIL or command didn't even start */ + if (*is_error && lwgsm.msg->msg.conn_send.conn->status.f.active) { + CONN_SEND_DATA_SEND_EVT(lwgsm.msg, lwgsmERR); + } + } + LWGSM_UNUSED(num); + } + /* Check for an error or if connection closed in the meantime */ + } else if (*is_error) { + CONN_SEND_DATA_SEND_EVT(lwgsm.msg, lwgsmERR); + } +} + +/** + * \brief Send error event to application layer + * \param[in] msg: Message from user with connection start + * \param[in] error: Error type + */ +static void +lwgsmi_send_conn_error_cb(lwgsm_msg_t* msg, lwgsmr_t error) { + lwgsm.evt.type = LWGSM_EVT_CONN_ERROR; /* Connection error */ + lwgsm.evt.evt.conn_error.host = lwgsm.msg->msg.conn_start.host; + lwgsm.evt.evt.conn_error.port = lwgsm.msg->msg.conn_start.port; + lwgsm.evt.evt.conn_error.type = lwgsm.msg->msg.conn_start.type; + lwgsm.evt.evt.conn_error.arg = lwgsm.msg->msg.conn_start.arg; + lwgsm.evt.evt.conn_error.err = error; + + /* Call callback specified by user on connection startup */ + lwgsm.msg->msg.conn_start.evt_func(&lwgsm.evt); + LWGSM_UNUSED(msg); +} + +/** + * \brief Checks if connection pointer has valid address + * \param[in] conn: Address to check if valid connection ptr + * \return 1 on success, 0 otherwise + */ +uint8_t +lwgsmi_is_valid_conn_ptr(lwgsm_conn_p conn) { + uint8_t i = 0; + for (i = 0; i < LWGSM_ARRAYSIZE(lwgsm.m.conns); ++i) { + if (conn == &lwgsm.m.conns[i]) { + return 1; + } + } + return 0; +} + +/** + * \brief Connection close event detected, process with callback to user + * \param[in] conn_num: Connection number + * \param[in] forced: Set to `1` if close forced by command, `0` otherwise + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsmi_conn_closed_process(uint8_t conn_num, uint8_t forced) { + lwgsm_conn_t* conn = &lwgsm.m.conns[conn_num]; + + conn->status.f.active = 0; + + /* Check if write buffer is set */ + if (conn->buff.buff != NULL) { + LWGSM_DEBUGF(LWGSM_CFG_DBG_CONN | LWGSM_DBG_TYPE_TRACE, + "[CONN] Free write buffer: %p\r\n", conn->buff.buff); + lwgsm_mem_free_s((void**)&conn->buff.buff); + } + + /* Send event */ + lwgsm.evt.type = LWGSM_EVT_CONN_CLOSE; + lwgsm.evt.evt.conn_active_close.conn = conn; + lwgsm.evt.evt.conn_active_close.forced = forced; + lwgsm.evt.evt.conn_active_close.res = lwgsmOK; + lwgsm.evt.evt.conn_active_close.client = conn->status.f.client; + lwgsmi_send_conn_cb(conn, NULL); + + return 1; +} + +#endif /* LWGSM_CFG_CONN || __DOXYGEN__ */ + +/** + * \brief Process received string from GSM + * \param[in] rcv: Pointer to \ref lwgsm_recv_t structure with input string + */ +static void +lwgsmi_parse_received(lwgsm_recv_t* rcv) { + uint8_t is_ok = 0; + uint16_t is_error = 0; + + /* Try to remove non-parsable strings */ + if (rcv->len == 2 && rcv->data[0] == '\r' && rcv->data[1] == '\n') { + return; + } + + /* Check OK response */ + is_ok = rcv->len == (2 + CRLF_LEN) && !strcmp(rcv->data, "OK" CRLF);/* Check if received string is OK */ + if (!is_ok) { /* Check for SHUT OK string */ + is_ok = rcv->len == (7 + CRLF_LEN) && !strcmp(rcv->data, "SEND OK" CRLF); + } + + /* Check error response */ + if (!is_ok) { /* If still not ok, check if error? */ + is_error = rcv->data[0] == '+' && !strncmp(rcv->data, "+CME ERROR", 10);/* First check +CME coded errors */ + if (!is_error) { /* Check basic error aswell */ + is_error = rcv->data[0] == '+' && !strncmp(rcv->data, "+CMS ERROR", 10);/* First check +CME coded errors */ + if (!is_error) { + is_error = !strcmp(rcv->data, "ERROR" CRLF) || !strcmp(rcv->data, "FAIL" CRLF); + } + } + } + + /* Scan received strings which start with '+' */ + if (rcv->data[0] == '+') { + if (!strncmp(rcv->data, "+CSQ", 4)) { + lwgsmi_parse_csq(rcv->data); /* Parse +CSQ response */ +#if LWGSM_CFG_NETWORK + } else if (!strncmp(rcv->data, "+PDP: DEACT", 11)) { + /* PDP has been deactivated */ + lwgsm_network_check_status(NULL, NULL, 0); /* Update status */ +#endif /* LWGSM_CFG_NETWORK */ +#if LWGSM_CFG_CONN + } else if (!strncmp(rcv->data, "+RECEIVE", 8)) { + lwgsmi_parse_ipd(rcv->data); /* Parse IPD */ +#endif /* LWGSM_CFG_CONN */ + } else if (!strncmp(rcv->data, "+CREG", 5)) { /* Check for +CREG indication */ + lwgsmi_parse_creg(rcv->data, LWGSM_U8(CMD_IS_CUR(LWGSM_CMD_CREG_GET))); /* Parse +CREG response */ + } else if (!strncmp(rcv->data, "+CPIN", 5)) { /* Check for +CPIN indication for SIM */ + lwgsmi_parse_cpin(rcv->data, 1 /* !CMD_IS_DEF(LWGSM_CMD_CPIN_SET) */); /* Parse +CPIN response */ + } else if (CMD_IS_CUR(LWGSM_CMD_COPS_GET) && !strncmp(rcv->data, "+COPS", 5)) { + lwgsmi_parse_cops(rcv->data); /* Parse current +COPS */ +#if LWGSM_CFG_SMS + } else if (CMD_IS_CUR(LWGSM_CMD_CMGS) && !strncmp(rcv->data, "+CMGS", 5)) { + lwgsmi_parse_cmgs(rcv->data, &lwgsm.msg->msg.sms_send.pos); /* Parse +CMGS response */ + } else if (CMD_IS_CUR(LWGSM_CMD_CMGR) && !strncmp(rcv->data, "+CMGR", 5)) { + if (lwgsmi_parse_cmgr(rcv->data)) { /* Parse +CMGR response */ + lwgsm.msg->msg.sms_read.read = 2; /* Set read flag and process the data */ + } else { + lwgsm.msg->msg.sms_read.read = 1; /* Read but ignore data */ + } + } else if (CMD_IS_CUR(LWGSM_CMD_CMGL) && !strncmp(rcv->data, "+CMGL", 5)) { + if (lwgsmi_parse_cmgl(rcv->data)) { /* Parse +CMGL response */ + lwgsm.msg->msg.sms_list.read = 2; /* Set read flag and process the data */ + } else { + lwgsm.msg->msg.sms_list.read = 1; /* Read but ignore data */ + } + } else if (!strncmp(rcv->data, "+CMTI", 5)) { + lwgsmi_parse_cmti(rcv->data, 1); /* Parse +CMTI response with received SMS */ + } else if (CMD_IS_CUR(LWGSM_CMD_CPMS_GET_OPT) && !strncmp(rcv->data, "+CPMS", 5)) { + lwgsmi_parse_cpms(rcv->data, 0); /* Parse +CPMS with SMS memories info */ + } else if (CMD_IS_CUR(LWGSM_CMD_CPMS_GET) && !strncmp(rcv->data, "+CPMS", 5)) { + lwgsmi_parse_cpms(rcv->data, 1); /* Parse +CPMS with SMS memories info */ + } else if (CMD_IS_CUR(LWGSM_CMD_CPMS_SET) && !strncmp(rcv->data, "+CPMS", 5)) { + lwgsmi_parse_cpms(rcv->data, 2); /* Parse +CPMS with SMS memories info */ +#endif /* LWGSM_CFG_SMS */ +#if LWGSM_CFG_CALL + } else if (!strncmp(rcv->data, "+CLCC", 5)) { + lwgsmi_parse_clcc(rcv->data, 1); /* Parse +CLCC response with call info change */ +#endif /* LWGSM_CFG_CALL */ +#if LWGSM_CFG_PHONEBOOK + } else if (CMD_IS_CUR(LWGSM_CMD_CPBS_GET_OPT) && !strncmp(rcv->data, "+CPBS", 5)) { + lwgsmi_parse_cpbs(rcv->data, 0); /* Parse +CPBS response */ + } else if (CMD_IS_CUR(LWGSM_CMD_CPBS_GET) && !strncmp(rcv->data, "+CPBS", 5)) { + lwgsmi_parse_cpbs(rcv->data, 1); /* Parse +CPBS response */ + } else if (CMD_IS_CUR(LWGSM_CMD_CPBS_SET) && !strncmp(rcv->data, "+CPBS", 5)) { + lwgsmi_parse_cpbs(rcv->data, 2); /* Parse +CPBS response */ + } else if (CMD_IS_CUR(LWGSM_CMD_CPBR) && !strncmp(rcv->data, "+CPBR", 5)) { + lwgsmi_parse_cpbr(rcv->data); /* Parse +CPBR statement */ + } else if (CMD_IS_CUR(LWGSM_CMD_CPBF) && !strncmp(rcv->data, "+CPBF", 5)) { + lwgsmi_parse_cpbf(rcv->data); /* Parse +CPBR statement */ +#endif /* LWGSM_CFG_PHONEBOOK */ + } + + /* Messages not starting with '+' sign */ + } else { + if (rcv->data[0] == 'S' && !strncmp(rcv->data, "SHUT OK" CRLF, 7 + CRLF_LEN)) { + is_ok = 1; +#if LWGSM_CFG_CONN + } else if (LWGSM_CHARISNUM(rcv->data[0]) && rcv->data[1] == ',' && rcv->data[2] == ' ' + && (!strncmp(&rcv->data[3], "CLOSE OK" CRLF, 8 + CRLF_LEN) || !strncmp(&rcv->data[3], "CLOSED" CRLF, 6 + CRLF_LEN))) { + uint8_t forced = 0, num; + + num = LWGSM_CHARTONUM(rcv->data[0]);/* Get connection number */ + if (CMD_IS_CUR(LWGSM_CMD_CIPCLOSE) && lwgsm.msg->msg.conn_close.conn->num == num) { + forced = 1; + is_ok = 1; /* If forced and connection is closed, command is OK */ + } + + /* Manually stop send command? */ + if (CMD_IS_CUR(LWGSM_CMD_CIPSEND) && lwgsm.msg->msg.conn_send.conn->num == num) { + /* + * If active command is CIPSEND and CLOSED event received, + * manually set error and process usual "ERROR" event on senddata + */ + is_error = 1; /* This is an error in response */ + lwgsmi_process_cipsend_response(rcv, &is_ok, &is_error); + } + lwgsmi_conn_closed_process(num, forced);/* Connection closed, process */ +#endif /* LWGSM_CFG_CONN */ +#if LWGSM_CFG_CALL + } else if (rcv->data[0] == 'C' && !strncmp(rcv->data, "Call Ready" CRLF, 10 + CRLF_LEN)) { + lwgsm.m.call.ready = 1; + lwgsmi_send_cb(LWGSM_EVT_CALL_READY); /* Send CALL ready event */ + } else if (rcv->data[0] == 'R' && !strncmp(rcv->data, "RING" CRLF, 4 + CRLF_LEN)) { + lwgsmi_send_cb(LWGSM_EVT_CALL_RING);/* Send call ring */ + } else if (rcv->data[0] == 'N' && !strncmp(rcv->data, "NO CARRIER" CRLF, 10 + CRLF_LEN)) { + lwgsmi_send_cb(LWGSM_EVT_CALL_NO_CARRIER); /* Send call no carrier event */ + } else if (rcv->data[0] == 'B' && !strncmp(rcv->data, "BUSY" CRLF, 4 + CRLF_LEN)) { + lwgsmi_send_cb(LWGSM_EVT_CALL_BUSY);/* Send call busy message */ +#endif /* LWGSM_CFG_CALL */ +#if LWGSM_CFG_SMS + } else if (rcv->data[0] == 'S' && !strncmp(rcv->data, "SMS Ready" CRLF, 9 + CRLF_LEN)) { + lwgsm.m.sms.ready = 1; /* SMS ready flag */ + lwgsmi_send_cb(LWGSM_EVT_SMS_READY);/* Send SMS ready event */ +#endif /* LWGSM_CFG_SMS */ + } else if ((CMD_IS_CUR(LWGSM_CMD_CGMI_GET) || CMD_IS_CUR(LWGSM_CMD_CGMM_GET) || CMD_IS_CUR(LWGSM_CMD_CGSN_GET) || CMD_IS_CUR(LWGSM_CMD_CGMR_GET)) + && !is_ok && !is_error && strncmp(rcv->data, "AT+", 3)) { + const char* tmp = rcv->data; + size_t tocopy; + if (CMD_IS_CUR(LWGSM_CMD_CGMI_GET)) { /* Check device manufacturer */ + lwgsmi_parse_string(&tmp, lwgsm.m.model_manufacturer, sizeof(lwgsm.m.model_manufacturer), 1); + if (CMD_IS_DEF(LWGSM_CMD_CGMI_GET)) { + tocopy = LWGSM_MIN(sizeof(lwgsm.m.model_manufacturer), lwgsm.msg->msg.device_info.len); + LWGSM_MEMCPY(lwgsm.msg->msg.device_info.str, lwgsm.m.model_manufacturer, tocopy); + lwgsm.msg->msg.device_info.str[tocopy - 1] = 0; + } + } else if (CMD_IS_CUR(LWGSM_CMD_CGMM_GET)) {/* Check device model number */ + lwgsmi_parse_string(&tmp, lwgsm.m.model_number, sizeof(lwgsm.m.model_number), 1); + if (CMD_IS_DEF(LWGSM_CMD_CGMM_GET)) { + tocopy = LWGSM_MIN(sizeof(lwgsm.m.model_number), lwgsm.msg->msg.device_info.len); + LWGSM_MEMCPY(lwgsm.msg->msg.device_info.str, lwgsm.m.model_number, tocopy); + lwgsm.msg->msg.device_info.str[tocopy - 1] = 0; + } + for (size_t i = 0; i < lwgsm_dev_model_map_size; ++i) { + if (strstr(lwgsm.m.model_number, lwgsm_dev_model_map[i].id_str) != NULL) { + lwgsm.m.model = lwgsm_dev_model_map[i].model; + break; + } + } + } else if (CMD_IS_CUR(LWGSM_CMD_CGSN_GET)) {/* Check device serial number */ + lwgsmi_parse_string(&tmp, lwgsm.m.model_serial_number, sizeof(lwgsm.m.model_serial_number), 1); + if (CMD_IS_DEF(LWGSM_CMD_CGSN_GET)) { + tocopy = LWGSM_MIN(sizeof(lwgsm.m.model_serial_number), lwgsm.msg->msg.device_info.len); + LWGSM_MEMCPY(lwgsm.msg->msg.device_info.str, lwgsm.m.model_serial_number, tocopy); + lwgsm.msg->msg.device_info.str[tocopy - 1] = 0; + } + } else if (CMD_IS_CUR(LWGSM_CMD_CGMR_GET)) {/* Check device revision */ + if (!strncmp(tmp, "Revision:", 9)) { + tmp += 9; + } + lwgsmi_parse_string(&tmp, lwgsm.m.model_revision, sizeof(lwgsm.m.model_revision), 1); + if (CMD_IS_DEF(LWGSM_CMD_CGMR_GET)) { + tocopy = LWGSM_MIN(sizeof(lwgsm.m.model_revision), lwgsm.msg->msg.device_info.len); + LWGSM_MEMCPY(lwgsm.msg->msg.device_info.str, lwgsm.m.model_revision, tocopy); + lwgsm.msg->msg.device_info.str[tocopy - 1] = 0; + } + } + } else if (CMD_IS_CUR(LWGSM_CMD_CIFSR) && LWGSM_CHARISNUM(rcv->data[0])) { + const char* tmp = rcv->data; + lwgsmi_parse_ip(&tmp, &lwgsm.m.network.ip_addr);/* Parse IP address */ + + is_ok = 1; /* Manually set OK flag as we don't expect OK in CIFSR command */ + } + } + + /* Check general responses for active commands */ + if (lwgsm.msg != NULL) { + if (0) { +#if LWGSM_CFG_SMS + } else if (CMD_IS_CUR(LWGSM_CMD_CMGS) && is_ok) { + /* At this point we have to wait for "> " to send data */ +#endif /* LWGSM_CFG_SMS */ +#if LWGSM_CFG_CONN + } else if (CMD_IS_CUR(LWGSM_CMD_CIPSTATUS)) { + /* For CIPSTATUS, OK is returned before important data */ + if (is_ok) { + is_ok = 0; + } + /* Check if connection data received */ + if (rcv->len > 3) { + uint8_t continueScan, processed = 0; + if (rcv->data[0] == 'C' && rcv->data[1] == ':' && rcv->data[2] == ' ') { + processed = 1; + lwgsmi_parse_cipstatus_conn(rcv->data, 1, &continueScan); + + if (lwgsm.m.active_conns_cur_parse_num == (LWGSM_CFG_MAX_CONNS - 1)) { + is_ok = 1; + } + } else if (!strncmp(rcv->data, "STATE:", 6)) { + processed = 1; + lwgsmi_parse_cipstatus_conn(rcv->data, 0, &continueScan); + } + + /* Check if we shall stop processing at this stage */ + if (processed && !continueScan) { + is_ok = 1; + } + } + } else if (CMD_IS_CUR(LWGSM_CMD_CIPSTART)) { + /* For CIPSTART, OK is returned before important data */ + if (is_ok) { + is_ok = 0; + } + + /* Wait here for CONNECT status before we cancel connection */ + if (LWGSM_CHARISNUM(rcv->data[0]) + && rcv->data[1] == ',' && rcv->data[2] == ' ') { + uint8_t num = LWGSM_CHARTONUM(rcv->data[0]); + if (num < LWGSM_CFG_MAX_CONNS) { + uint8_t id; + lwgsm_conn_t* conn = &lwgsm.m.conns[num]; /* Get connection handle */ + + if (!strncmp(&rcv->data[3], "CONNECT OK" CRLF, 10 + CRLF_LEN)) { + id = conn->val_id; + LWGSM_MEMSET(conn, 0x00, sizeof(*conn));/* Reset connection parameters */ + conn->num = num; + conn->status.f.active = 1; + conn->val_id = ++id; /* Set new validation ID */ + + /* Set connection parameters */ + conn->status.f.client = 1; + conn->evt_func = lwgsm.msg->msg.conn_start.evt_func; + conn->arg = lwgsm.msg->msg.conn_start.arg; + + /* Set status */ + lwgsm.msg->msg.conn_start.conn_res = LWGSM_CONN_CONNECT_OK; + is_ok = 1; + } else if (!strncmp(&rcv->data[3], "CONNECT FAIL" CRLF, 12 + CRLF_LEN)) { + lwgsm.msg->msg.conn_start.conn_res = LWGSM_CONN_CONNECT_ERROR; + is_error = 1; + } else if (!strncmp(&rcv->data[3], "ALREADY CONNECT" CRLF, 15 + CRLF_LEN)) { + lwgsm.msg->msg.conn_start.conn_res = LWGSM_CONN_CONNECT_ALREADY; + is_error = 1; + } + } + } + } else if (CMD_IS_CUR(LWGSM_CMD_CIPSEND)) { + if (is_ok) { + is_ok = 0; + } + lwgsmi_process_cipsend_response(rcv, &is_ok, &is_error); +#endif /* LWGSM_CFG_CONN */ +#if LWGSM_CFG_USSD + } else if (CMD_IS_CUR(LWGSM_CMD_CUSD)) { + /* OK is returned before +CUSD */ + /* Command is not finished yet, unless it was an ERROR */ + if (is_ok) { + is_ok = 0; + } + + /* Check for manual CUSTOM OK message */ + if (!strcmp(rcv->data, "CUSTOM_OK\r\n")) { + is_ok = 1; + } +#endif /* LWGSM_CFG_USSD */ + } + } + + /* + * In case of any of these events, simply release semaphore + * and proceed with next command + */ + if (is_ok || is_error) { + lwgsmr_t res = lwgsmOK; + if (lwgsm.msg != NULL) { /* Do we have active message? */ + res = lwgsmi_process_sub_cmd(lwgsm.msg, &is_ok, &is_error); + if (res != lwgsmCONT) { /* Shall we continue with next subcommand under this one? */ + if (is_ok) { /* Check OK status */ + res = lwgsm.msg->res = lwgsmOK; + } else { /* Or error status */ + res = lwgsm.msg->res = res; /* Set the error status */ + } + } else { + ++lwgsm.msg->i; /* Number of continue calls */ + } + + /* + * When the command is finished, + * release synchronization semaphore + * from user thread and start with next command + */ + if (res != lwgsmCONT) { /* Do we have to continue to wait for command? */ + lwgsm_sys_sem_release(&lwgsm.sem_sync); /* Release semaphore */ + } + } + } +} + +#if !LWGSM_CFG_INPUT_USE_PROCESS || __DOXYGEN__ +/** + * \brief Process data from input buffer + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsmi_process_buffer(void) { + void* data; + size_t len; + + do { + /* + * Get length of linear memory in buffer + * we can process directly as memory + */ + len = lwgsm_buff_get_linear_block_read_length(&lwgsm.buff); + if (len > 0) { + /* + * Get memory address of first element + * in linear block of data to process + */ + data = lwgsm_buff_get_linear_block_read_address(&lwgsm.buff); + + /* Process actual received data */ + lwgsmi_process(data, len); + + /* + * Once data is processed, simply skip + * the buffer memory and start over + */ + lwgsm_buff_skip(&lwgsm.buff, len); + } + } while (len); + return lwgsmOK; +} +#endif /* !LWGSM_CFG_INPUT_USE_PROCESS || __DOXYGEN__ */ + +/** + * \brief Process input data received from GSM device + * \param[in] data: Pointer to data to process + * \param[in] data_len: Length of data to process in units of bytes + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsmi_process(const void* data, size_t data_len) { + uint8_t ch; + const uint8_t* d = data; + size_t d_len = data_len; + static uint8_t ch_prev1, ch_prev2; + static lwgsm_unicode_t unicode; + + /* Check status if device is available */ + if (!lwgsm.status.f.dev_present) { + return lwgsmERRNODEVICE; + } + + while (d_len > 0) { /* Read entire set of characters from buffer */ + ch = *d; /* Get next character */ + ++d; /* Go to next character, must be here as it is used later on */ + --d_len; /* Decrease remaining length, must be here as it is decreased later too */ + + if (0) { +#if LWGSM_CFG_CONN + } else if (lwgsm.m.ipd.read) { /* Read connection data */ + size_t len; + + if (lwgsm.m.ipd.buff != NULL) { /* Do we have active buffer? */ + lwgsm.m.ipd.buff->payload[lwgsm.m.ipd.buff_ptr] = ch; /* Save data character */ + } + ++lwgsm.m.ipd.buff_ptr; + --lwgsm.m.ipd.rem_len; + + /* Try to read more data directly from buffer */ + len = LWGSM_MIN(d_len, LWGSM_MIN(lwgsm.m.ipd.rem_len, lwgsm.m.ipd.buff != NULL ? (lwgsm.m.ipd.buff->len - lwgsm.m.ipd.buff_ptr) : lwgsm.m.ipd.rem_len)); + LWGSM_DEBUGF(LWGSM_CFG_DBG_IPD | LWGSM_DBG_TYPE_TRACE, + "[IPD] New length to read: %d bytes\r\n", (int)len); + if (len > 0) { + if (lwgsm.m.ipd.buff != NULL) { /* Is buffer valid? */ + LWGSM_MEMCPY(&lwgsm.m.ipd.buff->payload[lwgsm.m.ipd.buff_ptr], d, len); + LWGSM_DEBUGF(LWGSM_CFG_DBG_IPD | LWGSM_DBG_TYPE_TRACE, + "[IPD] Bytes read: %d\r\n", (int)len); + } else { /* Simply skip the data in buffer */ + LWGSM_DEBUGF(LWGSM_CFG_DBG_IPD | LWGSM_DBG_TYPE_TRACE, + "[IPD] Bytes skipped: %d\r\n", (int)len); + } + d_len -= len; /* Decrease effective length */ + d += len; /* Skip remaining length */ + lwgsm.m.ipd.buff_ptr += len; /* Forward buffer pointer */ + lwgsm.m.ipd.rem_len -= len; /* Decrease remaining length */ + } + + /* Did we reach end of buffer or no more data? */ + if (lwgsm.m.ipd.rem_len == 0 || (lwgsm.m.ipd.buff != NULL && lwgsm.m.ipd.buff_ptr == lwgsm.m.ipd.buff->len)) { + lwgsmr_t res = lwgsmOK; + + /* Call user callback function with received data */ + if (lwgsm.m.ipd.buff != NULL) { /* Do we have valid buffer? */ + lwgsm.m.ipd.conn->total_recved += lwgsm.m.ipd.buff->tot_len;/* Increase number of bytes received */ + + /* + * Send data buffer to upper layer + * + * From this moment, user is responsible for packet + * buffer and must free it manually + */ + lwgsm.evt.type = LWGSM_EVT_CONN_RECV; + lwgsm.evt.evt.conn_data_recv.buff = lwgsm.m.ipd.buff; + lwgsm.evt.evt.conn_data_recv.conn = lwgsm.m.ipd.conn; + res = lwgsmi_send_conn_cb(lwgsm.m.ipd.conn, NULL); + + lwgsm_pbuf_free(lwgsm.m.ipd.buff); /* Free packet buffer at this point */ + LWGSM_DEBUGF(LWGSM_CFG_DBG_IPD | LWGSM_DBG_TYPE_TRACE, + "[IPD] Free packet buffer\r\n"); + if (res == lwgsmOKIGNOREMORE) { /* We should ignore more data */ + LWGSM_DEBUGF(LWGSM_CFG_DBG_IPD | LWGSM_DBG_TYPE_TRACE, + "[IPD] Ignoring more data from this IPD if available\r\n"); + lwgsm.m.ipd.buff = NULL;/* Set to NULL to ignore more data if possibly available */ + } + + /* + * Create new data packet if case if: + * + * - Previous one was successful and more data to read and + * - Connection is not in closing state + */ + if (lwgsm.m.ipd.buff != NULL && lwgsm.m.ipd.rem_len > 0 && !lwgsm.m.ipd.conn->status.f.in_closing) { + size_t new_len = LWGSM_MIN(lwgsm.m.ipd.rem_len, LWGSM_CFG_IPD_MAX_BUFF_SIZE); /* Calculate new buffer length */ + + LWGSM_DEBUGF(LWGSM_CFG_DBG_IPD | LWGSM_DBG_TYPE_TRACE, + "[IPD] Allocating new packet buffer of size: %d bytes\r\n", (int)new_len); + lwgsm.m.ipd.buff = lwgsm_pbuf_new(new_len); /* Allocate new packet buffer */ + + LWGSM_DEBUGW(LWGSM_CFG_DBG_IPD | LWGSM_DBG_TYPE_TRACE | LWGSM_DBG_LVL_WARNING, + lwgsm.m.ipd.buff == NULL, "[IPD] Buffer allocation failed for %d bytes\r\n", (int)new_len); + } else { + lwgsm.m.ipd.buff = NULL;/* Reset it */ + } + } + if (lwgsm.m.ipd.rem_len == 0) { /* Check if we read everything */ + lwgsm.m.ipd.buff = NULL; /* Reset buffer pointer */ + lwgsm.m.ipd.read = 0; /* Stop reading data */ + } + lwgsm.m.ipd.buff_ptr = 0; /* Reset input buffer pointer */ + } +#endif /* LWGSM_CFG_CONN */ + /* + * Check if operators scan command is active + * and if we are ready to read the incoming data + */ + } else if (CMD_IS_CUR(LWGSM_CMD_COPS_GET_OPT) && lwgsm.msg->msg.cops_scan.read) { + if (ch == '\n') { + lwgsm.msg->msg.cops_scan.read = 0; + } else { + lwgsmi_parse_cops_scan(ch, 0); /* Parse character by character */ + } +#if LWGSM_CFG_SMS + } else if (CMD_IS_CUR(LWGSM_CMD_CMGR) && lwgsm.msg->msg.sms_read.read) { + lwgsm_sms_entry_t* e = lwgsm.msg->msg.sms_read.entry; + if (lwgsm.msg->msg.sms_read.read == 2) {/* Read only if set to 2 */ + if (e != NULL) { /* Check if valid entry */ + if (e->length < (sizeof(e->data) - 1)) { + e->data[e->length++] = ch; + } + } else { + lwgsm.msg->msg.sms_read.read = 1; /* Read but ignore data */ + } + } + if (ch == '\n' && ch_prev1 == '\r') { + if (lwgsm.msg->msg.sms_read.read == 2) { + + } + lwgsm.msg->msg.sms_read.read = 0; + } + } else if (CMD_IS_CUR(LWGSM_CMD_CMGL) && lwgsm.msg->msg.sms_list.read) { + if (lwgsm.msg->msg.sms_list.read == 2) { + lwgsm_sms_entry_t* e = &lwgsm.msg->msg.sms_list.entries[lwgsm.msg->msg.sms_list.ei]; + if (e->length < (sizeof(e->data) - 1)) { + e->data[e->length++] = ch; + } + } + if (ch == '\n' && ch_prev1 == '\r') { + if (lwgsm.msg->msg.sms_list.read == 2) { + ++lwgsm.msg->msg.sms_list.ei; /* Go to next entry */ + if (lwgsm.msg->msg.sms_list.er != NULL) { /* Check and update user variable */ + *lwgsm.msg->msg.sms_list.er = lwgsm.msg->msg.sms_list.ei; + } + } + lwgsm.msg->msg.sms_list.read = 0; + } +#endif /* LWGSM_CFG_SMS */ +#if LWGSM_CFG_USSD + } else if (CMD_IS_CUR(LWGSM_CMD_CUSD) && lwgsm.msg->msg.ussd.read) { + if (ch == '"') { + lwgsm.msg->msg.ussd.resp[lwgsm.msg->msg.ussd.resp_write_ptr] = 0; + lwgsm.msg->msg.ussd.quote_det = !lwgsm.msg->msg.ussd.quote_det; + } else if (lwgsm.msg->msg.ussd.quote_det) { + if (lwgsm.msg->msg.ussd.resp_write_ptr < lwgsm.msg->msg.ussd.resp_len) { + lwgsm.msg->msg.ussd.resp[lwgsm.msg->msg.ussd.resp_write_ptr++] = ch; + lwgsm.msg->msg.ussd.resp[lwgsm.msg->msg.ussd.resp_write_ptr] = 0; + } + } else if (ch == '\n' && ch_prev1 == '\r') { + /* End of reading, command finished! */ + /* Return OK at this point! */ + strcpy(recv_buff.data, "CUSTOM_OK\r\n"); + recv_buff.len = strlen(recv_buff.data); + lwgsmi_parse_received(&recv_buff); + } +#endif /* LWGSM_CFG_USSD */ + /* + * We are in command mode where we have to process byte by byte + * Simply check for ASCII and unicode format and process data accordingly + */ + } else { + lwgsmr_t res = lwgsmERR; + if (LWGSM_ISVALIDASCII(ch)) { /* Manually check if valid ASCII character */ + res = lwgsmOK; + unicode.t = 1; /* Manually set total to 1 */ + unicode.r = 0; /* Reset remaining bytes */ + } else if (ch >= 0x80) { /* Process only if more than ASCII can hold */ + res = lwgsmi_unicode_decode(&unicode, ch); /* Try to decode unicode format */ + } + + if (res == lwgsmERR) { /* In case of an ERROR */ + unicode.r = 0; + } + if (res == lwgsmOK) { /* Can we process the character(s) */ + if (unicode.t == 1) { /* Totally 1 character? */ + switch (ch) { + case '\n': + RECV_ADD(ch); /* Add character to input buffer */ + lwgsmi_parse_received(&recv_buff); /* Parse received string */ + RECV_RESET(); /* Reset received string */ + break; + default: + RECV_ADD(ch); /* Any ASCII valid character */ + break; + } + +#if LWGSM_CFG_CONN + /* Check if we have to read data */ + if (ch == '\n' && lwgsm.m.ipd.read) { + size_t len; + LWGSM_DEBUGF(LWGSM_CFG_DBG_IPD | LWGSM_DBG_TYPE_TRACE, + "[IPD] Data on connection %d with total size %d byte(s)\r\n", + (int)lwgsm.m.ipd.conn->num, (int)lwgsm.m.ipd.tot_len); + + len = LWGSM_MIN(lwgsm.m.ipd.rem_len, LWGSM_CFG_IPD_MAX_BUFF_SIZE); + + /* + * Read received data in case of: + * + * - Connection is active and + * - Connection is not in closing mode + */ + if (lwgsm.m.ipd.conn->status.f.active && !lwgsm.m.ipd.conn->status.f.in_closing) { + lwgsm.m.ipd.buff = lwgsm_pbuf_new(len); /* Allocate new packet buffer */ + LWGSM_DEBUGW(LWGSM_CFG_DBG_IPD | LWGSM_DBG_TYPE_TRACE | LWGSM_DBG_LVL_WARNING, lwgsm.m.ipd.buff == NULL, + "[IPD] Buffer allocation failed for %d byte(s)\r\n", (int)len); + } else { + lwgsm.m.ipd.buff = NULL;/* Ignore reading on closed connection */ + LWGSM_DEBUGF(LWGSM_CFG_DBG_IPD | LWGSM_DBG_TYPE_TRACE, + "[IPD] Connection %d closed or in closing, skipping %d byte(s)\r\n", + (int)lwgsm.m.ipd.conn->num, (int)len); + } + lwgsm.m.ipd.conn->status.f.data_received = 1; /* We have first received data */ + + lwgsm.m.ipd.buff_ptr = 0; /* Reset buffer write pointer */ + } +#endif /* LWGSM_CFG_CONN */ + + /* + * Do we have a special sequence "> "? + * + * Check if any command active which may expect that kind of response + */ + if (ch_prev2 == '\n' && ch_prev1 == '>' && ch == ' ') { + if (0) { +#if LWGSM_CFG_CONN + } else if (CMD_IS_CUR(LWGSM_CMD_CIPSEND)) { + RECV_RESET(); /* Reset received object */ + + /* Now actually send the data prepared before */ + AT_PORT_SEND_WITH_FLUSH(&lwgsm.msg->msg.conn_send.data[lwgsm.msg->msg.conn_send.ptr], lwgsm.msg->msg.conn_send.sent); + lwgsm.msg->msg.conn_send.wait_send_ok_err = 1; /* Now we are waiting for "SEND OK" or "SEND ERROR" */ +#endif /* LWGSM_CFG_CONN */ +#if LWGSM_CFG_SMS + } else if (CMD_IS_CUR(LWGSM_CMD_CMGS)) {/* Send SMS? */ + AT_PORT_SEND(lwgsm.msg->msg.sms_send.text, strlen(lwgsm.msg->msg.sms_send.text)); + AT_PORT_SEND_CTRL_Z(); + AT_PORT_SEND_FLUSH(); +#endif /* LWGSM_CFG_SMS */ + } + } else if (CMD_IS_CUR(LWGSM_CMD_COPS_GET_OPT)) { + if (RECV_LEN() > 5 && !strncmp(recv_buff.data, "+COPS:", 6)) { + RECV_RESET(); /* Reset incoming buffer */ + lwgsmi_parse_cops_scan(0, 1); /* Reset parser state */ + lwgsm.msg->msg.cops_scan.read = 1; /* Start reading incoming bytes */ + } +#if LWGSM_CFG_USSD + } else if (CMD_IS_CUR(LWGSM_CMD_CUSD)) { + if (RECV_LEN() > 5 && !strncmp(recv_buff.data, "+CUSD:", 6)) { + RECV_RESET(); /* Reset incoming buffer */ + lwgsm.msg->msg.ussd.read = 1; /* Start reading incoming bytes */ + } +#endif /* LWGSM_CFG_USSD */ + } + } else { /* We have sequence of unicode characters */ + /* + * Unicode sequence characters are not "meta" characters + * so it is safe to just add them to receive array without checking + * what are the actual values + */ + for (uint8_t i = 0; i < unicode.t; ++i) { + RECV_ADD(unicode.ch[i]);/* Add character to receive array */ + } + } + } else if (res != lwgsmINPROG) { /* Not in progress? */ + RECV_RESET(); /* Invalid character in sequence */ + } + } + + ch_prev2 = ch_prev1; /* Save previous character as previous previous */ + ch_prev1 = ch; /* Set current as previous */ + } + return lwgsmOK; +} + +/* Temporary macros, only available for inside lwgsmi_process_sub_cmd function */ +/* Set new command, but first check for error on previous */ +#define SET_NEW_CMD_CHECK_ERROR(new_cmd) do { \ + if (!*(is_error)) { \ + n_cmd = (new_cmd); \ + } \ + } while (0) + +/* Set new command, ignore result of previous */ +#define SET_NEW_CMD(new_cmd) do { \ + n_cmd = (new_cmd); \ + } while (0) + +/** + * \brief Process current command with known execution status and start another if necessary + * \param[in] msg: Pointer to current message + * \param[in] is_ok: pointer to status whether last command result was OK + * \param[in] is_error: Pointer to status whether last command result was ERROR + * \return \ref lwgsmCONT if you sent more data and we need to process more data, \ref lwgsmOK on success, or \ref lwgsmERR on error + */ +static lwgsmr_t +lwgsmi_process_sub_cmd(lwgsm_msg_t* msg, uint8_t* is_ok, uint16_t* is_error) { + lwgsm_cmd_t n_cmd = LWGSM_CMD_IDLE; + if (CMD_IS_DEF(LWGSM_CMD_RESET)) { + switch (CMD_GET_CUR()) { /* Check current command */ + case LWGSM_CMD_RESET: { + lwgsmi_reset_everything(1); /* Reset everything */ + SET_NEW_CMD(LWGSM_CFG_AT_ECHO ? LWGSM_CMD_ATE1 : LWGSM_CMD_ATE0); /* Set ECHO mode */ + lwgsm_delay(5000); /* Delay for some time before we can continue after reset */ + break; + } + case LWGSM_CMD_ATE0: + case LWGSM_CMD_ATE1: + SET_NEW_CMD(LWGSM_CMD_CFUN_SET); + break; /* Set full functionality */ + case LWGSM_CMD_CFUN_SET: + SET_NEW_CMD(LWGSM_CMD_CMEE_SET); + break; /* Set detailed error reporting */ + case LWGSM_CMD_CMEE_SET: + SET_NEW_CMD(LWGSM_CMD_CGMI_GET); + break; /* Get manufacturer */ + case LWGSM_CMD_CGMI_GET: + SET_NEW_CMD(LWGSM_CMD_CGMM_GET); + break; /* Get model */ + case LWGSM_CMD_CGMM_GET: + SET_NEW_CMD(LWGSM_CMD_CGSN_GET); + break; /* Get product serial number */ + case LWGSM_CMD_CGSN_GET: + SET_NEW_CMD(LWGSM_CMD_CGMR_GET); + break; /* Get product revision */ + case LWGSM_CMD_CGMR_GET: { + /* + * At this point we have modem info. + * It is now time to send info to user + * to select between device drivers + */ + lwgsmi_send_cb(LWGSM_EVT_DEVICE_IDENTIFIED); + + SET_NEW_CMD(LWGSM_CMD_CREG_SET);/* Enable unsolicited code for CREG */ + break; + } + case LWGSM_CMD_CREG_SET: + SET_NEW_CMD(LWGSM_CMD_CLCC_SET); + break; /* Set call state */ + case LWGSM_CMD_CLCC_SET: + SET_NEW_CMD(LWGSM_CMD_CPIN_GET); + break; /* Get SIM state */ + case LWGSM_CMD_CPIN_GET: + break; + default: + break; + } + + /* Send event */ + if (n_cmd == LWGSM_CMD_IDLE) { + RESET_SEND_EVT(msg, lwgsmOK); + } + } else if (CMD_IS_DEF(LWGSM_CMD_COPS_GET)) { + if (CMD_IS_CUR(LWGSM_CMD_COPS_GET)) { + lwgsm.evt.evt.operator_current.operator_current = &lwgsm.m.network.curr_operator; + lwgsmi_send_cb(LWGSM_EVT_NETWORK_OPERATOR_CURRENT); + } + } else if (CMD_IS_DEF(LWGSM_CMD_COPS_GET_OPT)) { + if (CMD_IS_CUR(LWGSM_CMD_COPS_GET_OPT)) { + OPERATOR_SCAN_SEND_EVT(lwgsm.msg, *is_ok ? lwgsmOK : lwgsmERR); + } + } else if (CMD_IS_DEF(LWGSM_CMD_SIM_PROCESS_BASIC_CMDS)) { + if (CMD_IS_CUR(LWGSM_CMD_CNUM)) { + /* Get own phone number */ + if (!*is_ok) { + /* Sometimes SIM is not ready just after PIN entered */ + if (msg->msg.sim_info.cnum_tries < 5) { + ++msg->msg.sim_info.cnum_tries; + SET_NEW_CMD(LWGSM_CMD_CNUM); + lwgsm_delay(1000); + } + } + } + } else if (CMD_IS_DEF(LWGSM_CMD_CPIN_SET)) {/* Set PIN code */ + switch (CMD_GET_CUR()) { + case LWGSM_CMD_CPIN_GET: { /* Get own phone number */ + if (*is_ok && lwgsm.m.sim.state == LWGSM_SIM_STATE_PIN) { + SET_NEW_CMD(LWGSM_CMD_CPIN_SET);/* Set command to write PIN */ + } else if (lwgsm.m.sim.state != LWGSM_SIM_STATE_READY) { + *is_ok = 0; + *is_error = 1; + } + break; + } + case LWGSM_CMD_CPIN_SET: { /* Set CPIN */ + if (*is_ok) { + lwgsm_delay(5000); /* Make delay to make sure SIM is ready */ + } + break; + } + default: + break; + } +#if LWGSM_CFG_SMS + } else if (CMD_IS_DEF(LWGSM_CMD_SMS_ENABLE)) { + switch (CMD_GET_CUR()) { + case LWGSM_CMD_CPMS_GET_OPT: + SET_NEW_CMD(LWGSM_CMD_CPMS_GET); + break; + case LWGSM_CMD_CPMS_GET: + break; + default: + break; + } + if (!*is_ok || n_cmd == LWGSM_CMD_IDLE) { /* Stop execution on any command */ + SET_NEW_CMD(LWGSM_CMD_IDLE); + lwgsm.m.sms.enabled = n_cmd == LWGSM_CMD_IDLE; /* Set enabled status */ + lwgsm.evt.evt.sms_enable.status = lwgsm.m.sms.enabled ? lwgsmOK : lwgsmERR; + lwgsmi_send_cb(LWGSM_EVT_SMS_ENABLE); /* Send to user */ + } + } else if (CMD_IS_DEF(LWGSM_CMD_CMGS)) { /* Send SMS default command */ + if (CMD_IS_CUR(LWGSM_CMD_CMGF) && *is_ok) { /* Set message format current command */ + SET_NEW_CMD(LWGSM_CMD_CMGS); /* Now send actual message */ + } + + /* Send event on finish */ + if (n_cmd == LWGSM_CMD_IDLE) { + SMS_SEND_SEND_EVT(lwgsm.msg, *is_ok ? lwgsmOK : lwgsmERR); + } + } else if (CMD_IS_DEF(LWGSM_CMD_CMGR)) { /* Read SMS message */ + if (CMD_IS_CUR(LWGSM_CMD_CPMS_GET) && *is_ok) { + SET_NEW_CMD(LWGSM_CMD_CPMS_SET); /* Set memory */ + } else if (CMD_IS_CUR(LWGSM_CMD_CPMS_SET) && *is_ok) { + SET_NEW_CMD(LWGSM_CMD_CMGF); /* Set text mode */ + } else if (CMD_IS_CUR(LWGSM_CMD_CMGF) && *is_ok) { /* Set message format current command*/ + SET_NEW_CMD(LWGSM_CMD_CMGR); /* Start message read */ + } else if (CMD_IS_CUR(LWGSM_CMD_CMGR) && *is_ok) { + msg->msg.sms_read.mem = lwgsm.m.sms.mem[0].current; /* Set current memory */ + } + + /* Send event on finish */ + if (n_cmd == LWGSM_CMD_IDLE) { + SMS_SEND_READ_EVT(lwgsm.msg, *is_ok ? lwgsmOK : lwgsmERR); + } + } else if (CMD_IS_DEF(LWGSM_CMD_CMGD)) { /* Delete SMS message*/ + if (CMD_IS_CUR(LWGSM_CMD_CPMS_GET) && *is_ok) { + SET_NEW_CMD(LWGSM_CMD_CPMS_SET); /* Set memory */ + } else if (CMD_IS_CUR(LWGSM_CMD_CPMS_SET) && *is_ok) { + SET_NEW_CMD(LWGSM_CMD_CMGD); /* Delete message */ + } + + /* Send event on finish */ + if (n_cmd == LWGSM_CMD_IDLE) { + SMS_SEND_DELETE_EVT(msg, *is_ok ? lwgsmOK : lwgsmERR); + } + } else if (CMD_IS_DEF(LWGSM_CMD_CMGDA)) { + if (CMD_IS_CUR(LWGSM_CMD_CMGF) && *is_ok) { + SET_NEW_CMD(LWGSM_CMD_CMGDA); /* Mass storage */ + } + } else if (CMD_IS_DEF(LWGSM_CMD_CMGL)) { /* List SMS messages */ + if (CMD_IS_CUR(LWGSM_CMD_CPMS_GET) && *is_ok) { + SET_NEW_CMD(LWGSM_CMD_CPMS_SET); /* Set memory */ + } else if (CMD_IS_CUR(LWGSM_CMD_CPMS_SET) && *is_ok) { + SET_NEW_CMD(LWGSM_CMD_CMGF); /* Set text format */ + } else if (CMD_IS_CUR(LWGSM_CMD_CMGF) && *is_ok) { + SET_NEW_CMD(LWGSM_CMD_CMGL); /* List messages */ + } + + /* Send event on finish */ + if (n_cmd == LWGSM_CMD_IDLE) { + SMS_SEND_LIST_EVT(msg, *is_ok ? lwgsmOK : lwgsmERR); + } + } else if (CMD_IS_DEF(LWGSM_CMD_CPMS_SET)) {/* Set preferred memory */ + if (CMD_IS_CUR(LWGSM_CMD_CPMS_GET) && *is_ok) { + SET_NEW_CMD(LWGSM_CMD_CPMS_SET); /* Now set the command */ + } +#endif /* LWGSM_CFG_SMS */ +#if LWGSM_CFG_CALL + } else if (CMD_IS_DEF(LWGSM_CMD_CALL_ENABLE)) { + lwgsm.m.call.enabled = *is_ok; /* Set enabled status */ + lwgsm.evt.evt.call_enable.res = lwgsm.m.call.enabled ? lwgsmOK : lwgsmERR; + lwgsmi_send_cb(LWGSM_EVT_CALL_ENABLE); /* Send to user */ +#endif /* LWGSM_CFG_CALL */ +#if LWGSM_CFG_PHONEBOOK + } else if (CMD_IS_DEF(LWGSM_CMD_PHONEBOOK_ENABLE)) { + lwgsm.m.pb.enabled = *is_ok; /* Set enabled status */ + lwgsm.evt.evt.pb_enable.res = lwgsm.m.pb.enabled ? lwgsmOK : lwgsmERR; + lwgsmi_send_cb(LWGSM_EVT_PB_ENABLE); /* Send to user */ + } else if (CMD_IS_DEF(LWGSM_CMD_CPBW_SET)) {/* Write phonebook entry */ + if (CMD_IS_CUR(LWGSM_CMD_CPBS_GET) && *is_ok) { /* Get current memory */ + SET_NEW_CMD(LWGSM_CMD_CPBS_SET); /* Set current memory */ + } else if (CMD_IS_CUR(LWGSM_CMD_CPBS_SET) && *is_ok) { + SET_NEW_CMD(LWGSM_CMD_CPBW_SET); /* Write entry to phonebook */ + } + } else if (CMD_IS_DEF(LWGSM_CMD_CPBR)) { + if (CMD_IS_CUR(LWGSM_CMD_CPBS_GET) && *is_ok) { /* Get current memory */ + SET_NEW_CMD(LWGSM_CMD_CPBS_SET); /* Set current memory */ + } else if (CMD_IS_CUR(LWGSM_CMD_CPBS_SET) && *is_ok) { + SET_NEW_CMD(LWGSM_CMD_CPBR); /* Read entries */ + } else if (CMD_IS_CUR(LWGSM_CMD_CPBR)) { + lwgsm.evt.evt.pb_list.mem = lwgsm.m.pb.mem.current; + lwgsm.evt.evt.pb_list.entries = lwgsm.msg->msg.pb_list.entries; + lwgsm.evt.evt.pb_list.size = lwgsm.msg->msg.pb_list.ei; + lwgsm.evt.evt.pb_list.res = *is_ok ? lwgsmOK : lwgsmERR; + lwgsmi_send_cb(LWGSM_EVT_PB_LIST); + } + } else if (CMD_IS_DEF(LWGSM_CMD_CPBF)) { + if (CMD_IS_CUR(LWGSM_CMD_CPBS_GET) && *is_ok) { /* Get current memory */ + SET_NEW_CMD(LWGSM_CMD_CPBS_SET); /* Set current memory */ + } else if (CMD_IS_CUR(LWGSM_CMD_CPBS_SET) && *is_ok) { + SET_NEW_CMD(LWGSM_CMD_CPBF); /* Read entries */ + } else if (CMD_IS_CUR(LWGSM_CMD_CPBF)) { + lwgsm.evt.evt.pb_search.mem = lwgsm.m.pb.mem.current; + lwgsm.evt.evt.pb_search.search = lwgsm.msg->msg.pb_search.search; + lwgsm.evt.evt.pb_search.entries = lwgsm.msg->msg.pb_search.entries; + lwgsm.evt.evt.pb_search.size = lwgsm.msg->msg.pb_search.ei; + lwgsm.evt.evt.pb_search.res = *is_ok ? lwgsmOK : lwgsmERR; + lwgsmi_send_cb(LWGSM_EVT_PB_SEARCH); + } +#endif /* LWGSM_CFG_PHONEBOOK */ +#if LWGSM_CFG_NETWORK + } + if (CMD_IS_DEF(LWGSM_CMD_NETWORK_ATTACH)) { + switch (msg->i) { + case 0: + SET_NEW_CMD_CHECK_ERROR(LWGSM_CMD_CGACT_SET_0); + break; + case 1: + SET_NEW_CMD(LWGSM_CMD_CGACT_SET_1); + break; +#if LWGSM_CFG_NETWORK_IGNORE_CGACT_RESULT + case 2: + SET_NEW_CMD(LWGSM_CMD_CGATT_SET_0); + break; +#else /* LWGSM_CFG_NETWORK_IGNORE_CGACT_RESULT */ + case 2: + SET_NEW_CMD_CHECK_ERROR(LWGSM_CMD_CGATT_SET_0); + break; +#endif /* !LWGSM_CFG_NETWORK_IGNORE_CGACT_RESULT */ + case 3: + SET_NEW_CMD(LWGSM_CMD_CGATT_SET_1); + break; + case 4: + SET_NEW_CMD_CHECK_ERROR(LWGSM_CMD_CIPSHUT); + break; + case 5: + SET_NEW_CMD_CHECK_ERROR(LWGSM_CMD_CIPMUX_SET); + break; + case 6: + SET_NEW_CMD_CHECK_ERROR(LWGSM_CMD_CIPRXGET_SET); + break; + case 7: + SET_NEW_CMD_CHECK_ERROR(LWGSM_CMD_CSTT_SET); + break; + case 8: + SET_NEW_CMD_CHECK_ERROR(LWGSM_CMD_CIICR); + break; + case 9: + SET_NEW_CMD_CHECK_ERROR(LWGSM_CMD_CIFSR); + break; + case 10: + SET_NEW_CMD(LWGSM_CMD_CIPSTATUS); + break; + default: + break; + } + } else if (CMD_IS_DEF(LWGSM_CMD_NETWORK_DETACH)) { + switch (msg->i) { + case 0: + SET_NEW_CMD(LWGSM_CMD_CGATT_SET_0); + break; + case 1: + SET_NEW_CMD(LWGSM_CMD_CGACT_SET_0); + break; +#if LWGSM_CFG_CONN + case 2: + SET_NEW_CMD(LWGSM_CMD_CIPSTATUS); + break; +#endif /* LWGSM_CFG_CONN */ + default: + break; + } + if (!n_cmd) { + *is_ok = 1; + } +#endif /* LWGSM_CFG_NETWORK */ +#if LWGSM_CFG_CONN + } else if (CMD_IS_DEF(LWGSM_CMD_CIPSTART)) { + if (!msg->i && CMD_IS_CUR(LWGSM_CMD_CIPSTATUS)) { /* Was the current command status info? */ + if (*is_ok) { + SET_NEW_CMD(LWGSM_CMD_CIPSSL); /* Set SSL */ + } + } else if (msg->i == 1 && CMD_IS_CUR(LWGSM_CMD_CIPSSL)) { + SET_NEW_CMD(LWGSM_CMD_CIPSTART); /* Now actually start connection */ + } else if (msg->i == 2 && CMD_IS_CUR(LWGSM_CMD_CIPSTART)) { + SET_NEW_CMD(LWGSM_CMD_CIPSTATUS); /* Go to status mode */ + if (*is_error) { + msg->msg.conn_start.conn_res = LWGSM_CONN_CONNECT_ERROR; + } + } else if (msg->i == 3 && CMD_IS_CUR(LWGSM_CMD_CIPSTATUS)) { + /* After second CIP status, define what to do next */ + switch (msg->msg.conn_start.conn_res) { + case LWGSM_CONN_CONNECT_OK: { /* Successfully connected */ + lwgsm_conn_t* conn = &lwgsm.m.conns[msg->msg.conn_start.num]; /* Get connection number */ + + lwgsm.evt.type = LWGSM_EVT_CONN_ACTIVE; /* Connection just active */ + lwgsm.evt.evt.conn_active_close.client = 1; + lwgsm.evt.evt.conn_active_close.conn = conn; + lwgsm.evt.evt.conn_active_close.forced = 1; + lwgsmi_send_conn_cb(conn, NULL); + lwgsmi_conn_start_timeout(conn);/* Start connection timeout timer */ + break; + } + case LWGSM_CONN_CONNECT_ERROR: {/* Connection error */ + lwgsmi_send_conn_error_cb(msg, lwgsmERRCONNFAIL); + *is_error = 1; /* Manually set error */ + *is_ok = 0; /* Reset success */ + break; + } + default: { + /* Do nothing as of now */ + break; + } + } + } + } else if (CMD_IS_DEF(LWGSM_CMD_CIPCLOSE)) { + /* + * It is unclear in which state connection is when ERROR is received on close command. + * Stack checks if connection is closed before it allows and sends close command, + * however it was detected that no automatic close event has been received from device + * and AT+CIPCLOSE returned ERROR. + * + * Is it device firmware bug? + */ + if (CMD_IS_CUR(LWGSM_CMD_CIPCLOSE) && *is_error) { + /* Notify upper layer about failed close event */ + lwgsm.evt.type = LWGSM_EVT_CONN_CLOSE; + lwgsm.evt.evt.conn_active_close.conn = msg->msg.conn_close.conn; + lwgsm.evt.evt.conn_active_close.forced = 1; + lwgsm.evt.evt.conn_active_close.res = lwgsmERR; + lwgsm.evt.evt.conn_active_close.client = msg->msg.conn_close.conn->status.f.active && msg->msg.conn_close.conn->status.f.client; + lwgsmi_send_conn_cb(msg->msg.conn_close.conn, NULL); + } +#endif /* LWGSM_CFG_CONN */ +#if LWGSM_CFG_USSD + } else if (CMD_IS_DEF(LWGSM_CMD_CUSD)) { + if (CMD_IS_CUR(LWGSM_CMD_CUSD_GET)) { + if (*is_ok) { + SET_NEW_CMD(LWGSM_CMD_CUSD); /* Run next command */ + } + } + /* The rest is handled in one layer above */ +#endif /* LWGSM_CFG_USSD */ + } + + /* Check if new command was set for execution */ + if (n_cmd != LWGSM_CMD_IDLE) { + lwgsmr_t res; + msg->cmd = n_cmd; + if ((res = msg->fn(msg)) == lwgsmOK) { + return lwgsmCONT; + } else { + *is_ok = 0; + *is_error = 1; + return res; + } + } else { + msg->cmd = LWGSM_CMD_IDLE; + } + return *is_ok ? lwgsmOK : lwgsmERR; +} + +/** + * \brief Function to initialize every AT command + * \note Never call this function directly. Set as initialization function for command and use `msg->fn(msg)` + * \param[in] msg: Pointer to \ref lwgsm_msg_t with data + * \return Member of \ref lwgsmr_t enumeration + */ +lwgsmr_t +lwgsmi_initiate_cmd(lwgsm_msg_t* msg) { + switch (CMD_GET_CUR()) { /* Check current message we want to send over AT */ + case LWGSM_CMD_RESET: { /* Reset modem with AT commands */ + /* Try with hardware reset */ + if (lwgsm.ll.reset_fn != NULL && lwgsm.ll.reset_fn(1)) { + lwgsm_delay(2); + lwgsm.ll.reset_fn(0); + lwgsm_delay(500); + } + + /* Send manual AT command */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CFUN=1,1"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_RESET_DEVICE_FIRST_CMD: {/* First command for device driver specific reset */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_ATE0: + case LWGSM_CMD_ATE1: { + AT_PORT_SEND_BEGIN_AT(); + if (CMD_IS_CUR(LWGSM_CMD_ATE0)) { + AT_PORT_SEND_CONST_STR("E0"); + } else { + AT_PORT_SEND_CONST_STR("E1"); + } + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CMEE_SET: { /* Enable detailed error messages */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CMEE=1"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CLCC_SET: { /* Enable detailed call info */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CLCC=1"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CGMI_GET: { /* Get manufacturer */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CGMI"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CGMM_GET: { /* Get model */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CGMM"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CGSN_GET: { /* Get serial number */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CGSN"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CGMR_GET: { /* Get revision */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CGMR"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CREG_SET: { /* Enable +CREG message */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CREG=1"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CREG_GET: { /* Get network registration status */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CREG?"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CFUN_SET: { + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CFUN="); + /** + * \todo: If CFUN command forced, check value + */ + if (CMD_IS_DEF(LWGSM_CMD_RESET) + || (CMD_IS_DEF(LWGSM_CMD_CFUN_SET) && msg->msg.cfun.mode)) { + AT_PORT_SEND_CONST_STR("1"); + } else { + AT_PORT_SEND_CONST_STR("0"); + } + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CPIN_GET: { /* Read current SIM status */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CPIN?"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CPIN_SET: { /* Set SIM pin code */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CPIN="); + lwgsmi_send_string(msg->msg.cpin_enter.pin, 0, 1, 0); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CPIN_ADD: { /* Add new pin code */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CLCK=\"SC\",1,"); + lwgsmi_send_string(msg->msg.cpin_add.pin, 0, 1, 0); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CPIN_CHANGE: { /* Change already active SIM */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CPWD=\"SC\""); + lwgsmi_send_string(msg->msg.cpin_change.current_pin, 0, 1, 1); + lwgsmi_send_string(msg->msg.cpin_change.new_pin, 0, 1, 1); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CPIN_REMOVE: { /* Remove current PIN */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CLCK=\"SC\",0,"); + lwgsmi_send_string(msg->msg.cpin_remove.pin, 0, 1, 0); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CPUK_SET: { /* Enter PUK and set new PIN */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CPIN="); + lwgsmi_send_string(msg->msg.cpuk_enter.puk, 0, 1, 0); + lwgsmi_send_string(msg->msg.cpuk_enter.pin, 0, 1, 1); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_COPS_SET: { /* Set current operator */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+COPS="); + lwgsmi_send_number(LWGSM_U32(msg->msg.cops_set.mode), 0, 0); + if (msg->msg.cops_set.mode != LWGSM_OPERATOR_MODE_AUTO) { + lwgsmi_send_number(LWGSM_U32(msg->msg.cops_set.format), 0, 1); + switch (msg->msg.cops_set.format) { + case LWGSM_OPERATOR_FORMAT_LONG_NAME: + case LWGSM_OPERATOR_FORMAT_SHORT_NAME: + lwgsmi_send_string(msg->msg.cops_set.name, 1, 1, 1); + break; + default: + lwgsmi_send_number(LWGSM_U32(msg->msg.cops_set.num), 0, 1); + } + } + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_COPS_GET: { /* Get current operator */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+COPS?"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_COPS_GET_OPT: { /* Get list of available operators */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+COPS=?"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CSQ_GET: { /* Get signal strength */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CSQ"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CNUM: { /* Get SIM number */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CNUM"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CIPSHUT: { /* Shut down network connection and put to reset state */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CIPSHUT"); + AT_PORT_SEND_END_AT(); + break; + } +#if LWGSM_CFG_CONN + case LWGSM_CMD_CIPMUX: { /* Enable multiple connections */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CIPMUX=1"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CIPHEAD: { /* Enable information on receive data about connection and length */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CIPHEAD=1"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CIPSRIP: { + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CIPSRIP=1"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CIPSSL: { /* Set SSL configuration */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CIPSSL="); + lwgsmi_send_number((msg->msg.conn_start.type == LWGSM_CONN_TYPE_SSL) ? 1 : 0, 0, 0); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CIPSTART: { /* Start a new connection */ + lwgsm_conn_t* c = NULL; + + /* Do we have network connection? */ + /* Check if we are connected to network */ + + msg->msg.conn_start.num = 0; /* Start with max value = invalidated */ + for (int16_t i = LWGSM_CFG_MAX_CONNS - 1; i >= 0; --i) {/* Find available connection */ + if (!lwgsm.m.conns[i].status.f.active) { + c = &lwgsm.m.conns[i]; + c->num = LWGSM_U8(i); + msg->msg.conn_start.num = LWGSM_U8(i); /* Set connection number for message structure */ + break; + } + } + if (c == NULL) { + lwgsmi_send_conn_error_cb(msg, lwgsmERRNOFREECONN); + return lwgsmERRNOFREECONN; /* We don't have available connection */ + } + + if (msg->msg.conn_start.conn != NULL) { /* Is user interested about connection info? */ + *msg->msg.conn_start.conn = c; /* Save connection for user */ + } + + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CIPSTART="); + lwgsmi_send_number(LWGSM_U32(c->num), 0, 0); + if (msg->msg.conn_start.type == LWGSM_CONN_TYPE_TCP) { + lwgsmi_send_string("TCP", 0, 1, 1); + } else if (msg->msg.conn_start.type == LWGSM_CONN_TYPE_UDP) { + lwgsmi_send_string("UDP", 0, 1, 1); + } + lwgsmi_send_string(msg->msg.conn_start.host, 0, 1, 1); + lwgsmi_send_port(msg->msg.conn_start.port, 0, 1); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CIPCLOSE: { /* Close the connection */ + lwgsm_conn_p c = msg->msg.conn_close.conn; + if (c != NULL && + /* Is connection already closed or command for this connection is not valid anymore? */ + (!lwgsm_conn_is_active(c) || c->val_id != msg->msg.conn_close.val_id)) { + return lwgsmERR; + } + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CIPCLOSE="); + lwgsmi_send_number(LWGSM_U32(msg->msg.conn_close.conn ? msg->msg.conn_close.conn->num : LWGSM_CFG_MAX_CONNS), 0, 0); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CIPSEND: { /* Send data to connection */ + return lwgsmi_tcpip_process_send_data();/* Process send data */ + } + case LWGSM_CMD_CIPSTATUS: { /* Get status of device and all connections */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CIPSTATUS"); + AT_PORT_SEND_END_AT(); + break; + } +#endif /* LWGSM_CFG_CONN */ +#if LWGSM_CFG_SMS + case LWGSM_CMD_CMGF: { /* Select SMS message format */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CMGF="); + if (CMD_IS_DEF(LWGSM_CMD_CMGS)) { + lwgsmi_send_number(LWGSM_U32(!!msg->msg.sms_send.format), 0, 0); + } else if (CMD_IS_DEF(LWGSM_CMD_CMGR)) { + lwgsmi_send_number(LWGSM_U32(!!msg->msg.sms_read.format), 0, 0); + } else if (CMD_IS_DEF(LWGSM_CMD_CMGL)) { + lwgsmi_send_number(LWGSM_U32(!!msg->msg.sms_list.format), 0, 0); + } else { + /* Used for all other operations like delete all messages, etc */ + AT_PORT_SEND_CONST_STR("1"); + } + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CMGS: { /* Send SMS */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CMGS="); + lwgsmi_send_string(msg->msg.sms_send.num, 0, 1, 0); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CMGR: { /* Read message */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CMGR="); + lwgsmi_send_number(LWGSM_U32(msg->msg.sms_read.pos), 0, 0); + lwgsmi_send_number(LWGSM_U32(!msg->msg.sms_read.update), 0, 1); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CMGD: { /* Delete SMS message */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CMGD="); + lwgsmi_send_number(LWGSM_U32(msg->msg.sms_delete.pos), 0, 0); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CMGDA: { /* Mass delete SMS messages */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CMGDA="); + switch (msg->msg.sms_delete_all.status) { + case LWGSM_SMS_STATUS_READ: + lwgsmi_send_string("DEL READ", 0, 1, 0); + break; + case LWGSM_SMS_STATUS_UNREAD: + lwgsmi_send_string("DEL UNREAD", 0, 1, 0); + break; + case LWGSM_SMS_STATUS_SENT: + lwgsmi_send_string("DEL SENT", 0, 1, 0); + break; + case LWGSM_SMS_STATUS_UNSENT: + lwgsmi_send_string("DEL UNSENT", 0, 1, 0); + break; + case LWGSM_SMS_STATUS_INBOX: + lwgsmi_send_string("DEL INBOX", 0, 1, 0); + break; + case LWGSM_SMS_STATUS_ALL: + lwgsmi_send_string("DEL ALL", 0, 1, 0); + break; + default: + break; + } + AT_PORT_SEND_END_AT(); + break; + } + + case LWGSM_CMD_CMGL: { /* Delete SMS message */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CMGL="); + lwgsmi_send_sms_stat(msg->msg.sms_list.status, 1, 0); + lwgsmi_send_number(LWGSM_U32(!msg->msg.sms_list.update), 0, 1); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CPMS_GET_OPT: { /* Get available SMS storages */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CPMS=?"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CPMS_GET: { /* Get current SMS storage info */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CPMS?"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CPMS_SET: { /* Set active SMS storage(s) */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CPMS="); + if (CMD_IS_DEF(LWGSM_CMD_CMGR)) { /* Read SMS original command? */ + lwgsmi_send_dev_memory(msg->msg.sms_read.mem == LWGSM_MEM_CURRENT ? lwgsm.m.sms.mem[0].current : msg->msg.sms_read.mem, 1, 0); + } else if (CMD_IS_DEF(LWGSM_CMD_CMGD)) {/* Delete SMS original command? */ + lwgsmi_send_dev_memory(msg->msg.sms_delete.mem == LWGSM_MEM_CURRENT ? lwgsm.m.sms.mem[0].current : msg->msg.sms_delete.mem, 1, 0); + } else if (CMD_IS_DEF(LWGSM_CMD_CMGL)) {/* List SMS original command? */ + lwgsmi_send_dev_memory(msg->msg.sms_list.mem == LWGSM_MEM_CURRENT ? lwgsm.m.sms.mem[0].current : msg->msg.sms_list.mem, 1, 0); + } else if (CMD_IS_DEF(LWGSM_CMD_CPMS_SET)) {/* Do we want to set memory for read/delete,sent/write,receive? */ + for (size_t i = 0; i < 3; ++i) {/* Write 3 memories */ + lwgsmi_send_dev_memory(msg->msg.sms_memory.mem[i] == LWGSM_MEM_CURRENT ? lwgsm.m.sms.mem[i].current : msg->msg.sms_memory.mem[i], 1, !!i); + } + } + AT_PORT_SEND_END_AT(); + break; + } +#endif /* LWGSM_CFG_SMS */ +#if LWGSM_CFG_CALL + case LWGSM_CMD_ATD: { /* Start new call */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("D"); + lwgsmi_send_string(msg->msg.call_start.number, 0, 0, 0); + AT_PORT_SEND_CONST_STR(";"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_ATA: { /* Answer phone call */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("A"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_ATH: { /* Disconnect existing connection (hang-up phone call) */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("H"); + AT_PORT_SEND_END_AT(); + break; + } +#endif /* LWGSM_CFG_CALL */ +#if LWGSM_CFG_PHONEBOOK + case LWGSM_CMD_CPBS_GET_OPT: { /* Get available phonebook storages */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CPBS=?"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CPBS_GET: { /* Get current memory info */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CPBS?"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CPBS_SET: { /* Get current memory info */ + lwgsm_mem_t mem; + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CPBS="); + switch (CMD_GET_DEF()) { + case LWGSM_CMD_CPBW_SET: + mem = msg->msg.pb_write.mem; + break; + case LWGSM_CMD_CPBR: + mem = msg->msg.pb_list.mem; + break; + case LWGSM_CMD_CPBF: + mem = msg->msg.pb_search.mem; + break; + default: + break; + } + lwgsmi_send_dev_memory(mem == LWGSM_MEM_CURRENT ? lwgsm.m.pb.mem.current : mem, 1, 0); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CPBW_SET: { /* Write/Delete new/old entry */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CPBW="); + if (msg->msg.pb_write.pos > 0) { /* Write number if more than 0 */ + lwgsmi_send_number(LWGSM_U32(msg->msg.pb_write.pos), 0, 0); + } + if (!msg->msg.pb_write.del) { + lwgsmi_send_string(msg->msg.pb_write.num, 0, 1, 1); + lwgsmi_send_number(LWGSM_U32(msg->msg.pb_write.type), 0, 1); + lwgsmi_send_string(msg->msg.pb_write.name, 0, 1, 1); + } + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CPBR: { /* Read entires */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CPBR="); + lwgsmi_send_number(LWGSM_U32(msg->msg.pb_list.start_index), 0, 0); + lwgsmi_send_number(LWGSM_U32(msg->msg.pb_list.etr), 0, 1); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CPBF: { /* Find entires */ + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CPBF="); + lwgsmi_send_string(msg->msg.pb_search.search, 1, 1, 0); + AT_PORT_SEND_END_AT(); + break; + } +#endif /* LWGSM_CFG_PHONEBOOK */ +#if LWGSM_CFG_NETWORK + case LWGSM_CMD_NETWORK_ATTACH: + case LWGSM_CMD_CGACT_SET_0: { + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CGACT=0"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CGACT_SET_1: { + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CGACT=1"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_NETWORK_DETACH: + case LWGSM_CMD_CGATT_SET_0: { + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CGATT=0"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CGATT_SET_1: { + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CGATT=1"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CIPMUX_SET: { + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CIPMUX=1"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CIPRXGET_SET: { + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CIPRXGET=0"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CSTT_SET: { + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CSTT="); + lwgsmi_send_string(msg->msg.network_attach.apn, 1, 1, 0); + lwgsmi_send_string(msg->msg.network_attach.user, 1, 1, 1); + lwgsmi_send_string(msg->msg.network_attach.pass, 1, 1, 1); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CIICR: { + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CIICR"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CIFSR: { + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CIFSR"); + AT_PORT_SEND_END_AT(); + break; + } +#endif /* LWGSM_CFG_NETWORK */ +#if LWGSM_CFG_USSD + case LWGSM_CMD_CUSD_GET: { + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CUSD?"); + AT_PORT_SEND_END_AT(); + break; + } + case LWGSM_CMD_CUSD: { + AT_PORT_SEND_BEGIN_AT(); + AT_PORT_SEND_CONST_STR("+CUSD=1,"); + lwgsmi_send_string(msg->msg.ussd.code, 1, 1, 0); + AT_PORT_SEND_END_AT(); + break; + } +#endif /* LWGSM_CFG_USSD */ + default: + return lwgsmERR; /* Invalid command */ + } + return lwgsmOK; /* Valid command */ +} + +/** + * \brief Send message from API function to producer queue for further processing + * \param[in] msg: New message to process + * \param[in] process_fn: callback function used to process message + * \param[in] max_block_time: Maximal time command can block in units of milliseconds + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsmi_send_msg_to_producer_mbox(lwgsm_msg_t* msg, lwgsmr_t (*process_fn)(lwgsm_msg_t*), uint32_t max_block_time) { + lwgsmr_t res = msg->res = lwgsmOK; + + /* Check here if stack is even enabled or shall we disable new command entry? */ + lwgsm_core_lock(); + /* If locked more than 1 time, means we were called from callback or internally */ + if (lwgsm.locked_cnt > 1 && msg->is_blocking) { + res = lwgsmERRBLOCKING; /* Blocking mode not allowed */ + } + /* Check if device present */ + if (res == lwgsmOK && !lwgsm.status.f.dev_present) { + res = lwgsmERRNODEVICE; /* No device connected */ + } + lwgsm_core_unlock(); + if (res != lwgsmOK) { + LWGSM_MSG_VAR_FREE(msg); /* Free memory and return */ + return res; + } + + if (msg->is_blocking) { /* In case message is blocking */ + if (!lwgsm_sys_sem_create(&msg->sem, 0)) { /* Create semaphore and lock it immediately */ + LWGSM_MSG_VAR_FREE(msg); /* Release memory and return */ + return lwgsmERRMEM; + } + } + if (!msg->cmd) { /* Set start command if not set by user */ + msg->cmd = msg->cmd_def; /* Set it as default */ + } + msg->block_time = max_block_time; /* Set blocking status if necessary */ + msg->fn = process_fn; /* Save processing function to be called as callback */ + if (msg->is_blocking) { + lwgsm_sys_mbox_put(&lwgsm.mbox_producer, msg); /* Write message to producer queue and wait forever */ + } else { + if (!lwgsm_sys_mbox_putnow(&lwgsm.mbox_producer, msg)) {/* Write message to producer queue immediately */ + LWGSM_MSG_VAR_FREE(msg); /* Release message */ + return lwgsmERRMEM; + } + } + if (res == lwgsmOK && msg->is_blocking) { /* In case we have blocking request */ + uint32_t time; + time = lwgsm_sys_sem_wait(&msg->sem, 0);/* Wait forever for semaphore */ + if (time == LWGSM_SYS_TIMEOUT) { /* If semaphore was not accessed within given time */ + res = lwgsmTIMEOUT; /* Semaphore not released in time */ + } else { + res = msg->res; /* Set response status from message response */ + } + LWGSM_MSG_VAR_FREE(msg); /* Release message */ + } + return res; +} + +/** + * \brief Process events in case of timeout on command or invalid message (if device is not present) + * + * Function is called from processing thread: + * + * - On command timeout error + * - If command was sent to queue and before processed, device present status changed + * + * \param[in] msg: Current message + * \param[in] err: Error message to send + */ +void +lwgsmi_process_events_for_timeout_or_error(lwgsm_msg_t* msg, lwgsmr_t err) { + switch (msg->cmd_def) { + case LWGSM_CMD_RESET: { + /* Reset command error */ + RESET_SEND_EVT(msg, err); + break; + } + + case LWGSM_CMD_RESTORE: { + /* Restore command error */ + RESTORE_SEND_EVT(msg, err); + break; + } + + case LWGSM_CMD_COPS_GET_OPT: { + /* Operator scan command error */ + OPERATOR_SCAN_SEND_EVT(msg, err); + break; + } + +#if LWGSM_CFG_CONN + case LWGSM_CMD_CIPSTART: { + /* Start connection error */ + lwgsmi_send_conn_error_cb(msg, err); + break; + } + + case LWGSM_CMD_CIPSEND: { + /* Send data error event */ + CONN_SEND_DATA_SEND_EVT(msg, err); + break; + } +#endif /* LWGSM_CFG_CONN */ + +#if LWGSM_CFG_SMS + case LWGSM_CMD_CMGS: { + /* Send error event */ + SMS_SEND_SEND_EVT(msg, err); + break; + } + + case LWGSM_CMD_CMGR: { + /* Read error event */ + SMS_SEND_READ_EVT(msg, err); + break; + } + + case LWGSM_CMD_CMGL: { + /* List error event */ + SMS_SEND_LIST_EVT(msg, err); + break; + } + + case LWGSM_CMD_CMGD: { + /* Delete error event */ + SMS_SEND_DELETE_EVT(msg, err); + break; + } +#endif /* LWGSM_CFG_SMS */ + + default: + break; + } +} diff --git a/gsm_at_lib/src/gsm/gsm_mem.c b/lwgsm/src/lwgsm/lwgsm_mem.c similarity index 71% rename from gsm_at_lib/src/gsm/gsm_mem.c rename to lwgsm/src/lwgsm/lwgsm_mem.c index 291af57d..8502dc27 100644 --- a/gsm_at_lib/src/gsm/gsm_mem.c +++ b/lwgsm/src/lwgsm/lwgsm_mem.c @@ -1,10 +1,10 @@ /** - * \file gsm_mem.c + * \file lwgsm_mem.c * \brief Memory manager */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,16 +26,16 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_mem.h" #include +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_mem.h" -#if !GSM_CFG_MEM_CUSTOM || __DOXYGEN__ +#if !LWGSM_CFG_MEM_CUSTOM || __DOXYGEN__ #if !__DOXYGEN__ typedef struct mem_block { @@ -47,9 +47,9 @@ typedef struct mem_block { /** * \brief Memory alignment bits and absolute number */ -#define MEM_ALIGN_BITS GSM_SZ(GSM_CFG_MEM_ALIGNMENT - 1) -#define MEM_ALIGN_NUM GSM_SZ(GSM_CFG_MEM_ALIGNMENT) -#define MEM_ALIGN(x) GSM_MEM_ALIGN(x) +#define MEM_ALIGN_BITS LWGSM_SZ(LWGSM_CFG_MEM_ALIGNMENT - 1) +#define MEM_ALIGN_NUM LWGSM_SZ(LWGSM_CFG_MEM_ALIGNMENT) +#define MEM_ALIGN(x) LWGSM_MEM_ALIGN(x) #define MEMBLOCK_METASIZE MEM_ALIGN(sizeof(mem_block_t)) @@ -73,19 +73,24 @@ mem_insertfreeblock(mem_block_t* nb) { /* Find block position to insert new block between */ for (ptr = &start_block; ptr != NULL && ptr->next < nb; ptr = ptr->next) {} + /* Check hard error on wrongly used memory */ + if (ptr == NULL) { + return; + } + /* * If the new inserted block and block before create a one big block (contiguous) * then try to merge them together */ - addr = (void *)ptr; - if ((uint8_t *)(addr + ptr->size) == (uint8_t *)nb) { + addr = (void*)ptr; + if ((uint8_t*)(addr + ptr->size) == (uint8_t*)nb) { ptr->size += nb->size; /* Expand size of block before new inserted */ nb = ptr; /* Set new block pointer to block before (expanded block) */ } /* Check if new block and its size is the same address as next free block newBlock points to */ - addr = (void *)nb; - if ((uint8_t *)(addr + nb->size) == (uint8_t *)ptr->next) { + addr = (void*)nb; + if ((uint8_t*)(addr + nb->size) == (uint8_t*)ptr->next) { if (ptr->next == end_block) { /* Does it points to the end? */ nb->next = end_block; /* Set end block pointer */ } else { @@ -114,39 +119,38 @@ mem_insertfreeblock(mem_block_t* nb) { * \param[in] len: Number of regions to assign */ static uint8_t -mem_assignmem(const gsm_mem_region_t* regions, size_t len) { +mem_assignmem(const lwgsm_mem_region_t* regions, size_t len) { uint8_t* mem_start_addr; size_t mem_size; - mem_block_t *first_block, *prev_end_block = NULL; + mem_block_t* first_block, *prev_end_block = NULL; if (end_block != NULL) { /* Regions already defined */ return 0; } /* Check if region address are linear and rising */ - mem_start_addr = (uint8_t *)0; - for (size_t i = 0; i < len; i++) { - if (mem_start_addr >= (uint8_t *)regions[i].start_addr) { /* Check if previous greater than current */ + mem_start_addr = (uint8_t*)0; + for (size_t i = 0; i < len; ++i) { + if (mem_start_addr >= (uint8_t*)regions[i].start_addr) {/* Check if previous greater than current */ return 0; /* Return as invalid and failed */ } - mem_start_addr = (uint8_t *)regions[i].start_addr; /* Save as previous address */ + mem_start_addr = (uint8_t*)regions[i].start_addr; /* Save as previous address */ } - while (len--) { + for (; len > 0; --len, ++regions) { /* Check minimum region size */ mem_size = regions->size; if (mem_size < (MEM_ALIGN_NUM + MEMBLOCK_METASIZE)) { - regions++; continue; } /* * Get start address and check memory alignment * if necessary, decrease memory region size */ - mem_start_addr = (uint8_t *)regions->start_addr;/* Actual heap memory address */ - if (GSM_SZ(mem_start_addr) & MEM_ALIGN_BITS) { /* Check alignment boundary */ - mem_start_addr += MEM_ALIGN_NUM - (GSM_SZ(mem_start_addr) & MEM_ALIGN_BITS); - mem_size -= mem_start_addr - (uint8_t *)regions->start_addr; + mem_start_addr = (uint8_t*)regions->start_addr; /* Actual heap memory address */ + if (LWGSM_SZ(mem_start_addr) & MEM_ALIGN_BITS) {/* Check alignment boundary */ + mem_start_addr += MEM_ALIGN_NUM - (LWGSM_SZ(mem_start_addr) & MEM_ALIGN_BITS); + mem_size -= mem_start_addr - (uint8_t*)regions->start_addr; } /* Check memory size alignment if match */ @@ -162,7 +166,7 @@ mem_assignmem(const gsm_mem_region_t* regions, size_t len) { * Set Start block only if end block is not yet defined = first run */ if (end_block == NULL) { - start_block.next = (mem_block_t *)mem_start_addr; + start_block.next = (mem_block_t*)mem_start_addr; start_block.size = 0; } @@ -172,7 +176,7 @@ mem_assignmem(const gsm_mem_region_t* regions, size_t len) { * Set pointer to end of free memory - block region memory * Calculate new end block in region */ - end_block = (mem_block_t *)((uint8_t *)mem_start_addr + mem_size - MEMBLOCK_METASIZE); + end_block = (mem_block_t*)((uint8_t*)mem_start_addr + mem_size - MEMBLOCK_METASIZE); end_block->next = NULL; /* No more free blocks after end is reached */ end_block->size = 0; /* Empty block */ @@ -180,8 +184,8 @@ mem_assignmem(const gsm_mem_region_t* regions, size_t len) { * Initialize start of region memory * Create first block in region */ - first_block = (mem_block_t *)mem_start_addr; - first_block->size = mem_size - MEMBLOCK_METASIZE; /* Exclude end block in chain */ + first_block = (mem_block_t*)mem_start_addr; + first_block->size = mem_size - MEMBLOCK_METASIZE; /* Exclude end block in chain */ first_block->next = end_block; /* Last block is next free in chain */ /* @@ -196,8 +200,6 @@ mem_assignmem(const gsm_mem_region_t* regions, size_t len) { /* Set number of free bytes available to allocate in region */ mem_available_bytes += first_block->size; - - regions++; /* Go to next region */ } return 1; /* Regions set as expected */ @@ -208,9 +210,9 @@ mem_assignmem(const gsm_mem_region_t* regions, size_t len) { * \param[in] size: Number of bytes to allocate * \return Memory address on success, `NULL` otherwise */ -static void * +static void* mem_alloc(size_t size) { - mem_block_t *prev, *curr, *next; + mem_block_t* prev, *curr, *next; void* retval = NULL; if (end_block == NULL) { /* If end block is not yet defined */ @@ -245,16 +247,16 @@ mem_alloc(size_t size) { * Feature may be very risky later because of fragmentation */ if (curr != end_block) { /* We found empty block of enough memory available */ - retval = (void *)((uint8_t *)prev->next + MEMBLOCK_METASIZE); /* Set return value */ - prev->next = curr->next; /* Since block is now allocated, remove it from free chain */ + retval = (void*)((uint8_t*)prev->next + MEMBLOCK_METASIZE); /* Set return value */ + prev->next = curr->next; /* Since block is now allocated, remove it from free chain */ /* * If found free block is much bigger than required, * then split big block by 2 blocks (one used, second available) * There should be available memory for at least 2 metadata block size = 8 bytes of useful memory */ - if ((curr->size - size) > (2 * MEMBLOCK_METASIZE)) { /* There is more available memory then required = split memory to one free block */ - next = (mem_block_t *)(((uint8_t *)curr) + size); /* Create next memory block which is still free */ + if ((curr->size - size) > (2 * MEMBLOCK_METASIZE)) {/* There is more available memory then required = split memory to one free block */ + next = (mem_block_t*)(((uint8_t*)curr) + size); /* Create next memory block which is still free */ next->size = curr->size - size; /* Set new block size for remaining of before and used */ curr->size = size; /* Set block size for used block */ @@ -276,8 +278,8 @@ mem_alloc(size_t size) { /** * \brief Free memory - * \param[in] ptr: Pointer to memory previously returned using \ref gsm_mem_malloc, - * \ref gsm_mem_calloc or \ref gsm_mem_realloc functions + * \param[in] ptr: Pointer to memory previously returned using \ref lwgsm_mem_malloc, + * \ref lwgsm_mem_calloc or \ref lwgsm_mem_realloc functions */ static void mem_free(void* ptr) { @@ -306,16 +308,17 @@ mem_free(void* ptr) { /** * \brief Allocate memory of specific size - * \param[in] size: Number of bytes to allocate + * \param[in] num: Number of elements to allocate + * \param[in] size: Size of element in units of bytes * \return Memory address on success, `NULL` otherwise */ -static void * +static void* mem_calloc(size_t num, size_t size) { void* ptr; size_t tot_len = num * size; if ((ptr = mem_alloc(tot_len)) != NULL) { /* Try to allocate memory */ - GSM_MEMSET(ptr, 0x00, tot_len); /* Reset entire memory */ + LWGSM_MEMSET(ptr, 0x00, tot_len); /* Reset entire memory */ } return ptr; } @@ -323,12 +326,12 @@ mem_calloc(size_t num, size_t size) { /** * \brief Reallocate memory to specific size * \note After new memory is allocated, content of old one is copied to new memory - * \param[in] ptr: Pointer to current allocated memory to resize, returned using - * \ref gsm_mem_malloc, \ref gsm_mem_calloc or \ref gsm_mem_realloc functions + * \param[in] ptr: Pointer to current allocated memory to resize, returned using + * \ref lwgsm_mem_malloc, \ref lwgsm_mem_calloc or \ref lwgsm_mem_realloc functions * \param[in] size: Number of bytes to allocate on new memory * \return Memory address on success, `NULL` otherwise */ -static void * +static void* mem_realloc(void* ptr, size_t size) { void* new_ptr; size_t old_size; @@ -337,10 +340,10 @@ mem_realloc(void* ptr, size_t size) { return mem_alloc(size); /* Only allocate memory */ } - old_size = MEM_BLOCK_USER_SIZE(ptr); /* Get size of old pointer */ + old_size = MEM_BLOCK_USER_SIZE(ptr); /* Get size of old pointer */ new_ptr = mem_alloc(size); /* Try to allocate new memory block */ if (new_ptr != NULL) { - GSM_MEMCPY(new_ptr, ptr, GSM_MIN(size, old_size)); /* Copy old data to new array */ + LWGSM_MEMCPY(new_ptr, ptr, LWGSM_MIN(size, old_size)); /* Copy old data to new array */ mem_free(ptr); /* Free old pointer */ } return new_ptr; @@ -350,39 +353,39 @@ mem_realloc(void* ptr, size_t size) { * \brief Allocate memory of specific size * \param[in] size: Number of bytes to allocate * \return Memory address on success, `NULL` otherwise - * \note Function is not available when \ref GSM_CFG_MEM_CUSTOM is `1` and must be implemented by user + * \note Function is not available when \ref LWGSM_CFG_MEM_CUSTOM is `1` and must be implemented by user */ -void * -gsm_mem_malloc(size_t size) { +void* +lwgsm_mem_malloc(size_t size) { void* ptr; - gsm_core_lock(); + lwgsm_core_lock(); ptr = mem_calloc(1, size); /* Allocate memory and return pointer */ - gsm_core_unlock(); - GSM_DEBUGW(GSM_CFG_DBG_MEM | GSM_DBG_TYPE_TRACE, ptr == NULL, - "[MEM] Allocation failed: %d bytes\r\n", (int)size); - GSM_DEBUGW(GSM_CFG_DBG_MEM | GSM_DBG_TYPE_TRACE, ptr != NULL, - "[MEM] Allocation OK: %d bytes, addr: %p\r\n", (int)size, ptr); + lwgsm_core_unlock(); + LWGSM_DEBUGW(LWGSM_CFG_DBG_MEM | LWGSM_DBG_TYPE_TRACE, ptr == NULL, + "[MEM] Allocation failed: %d bytes\r\n", (int)size); + LWGSM_DEBUGW(LWGSM_CFG_DBG_MEM | LWGSM_DBG_TYPE_TRACE, ptr != NULL, + "[MEM] Allocation OK: %d bytes, addr: %p\r\n", (int)size, ptr); return ptr; } /** * \brief Reallocate memory to specific size * \note After new memory is allocated, content of old one is copied to new memory - * \param[in] ptr: Pointer to current allocated memory to resize, returned using \ref gsm_mem_malloc, - * \ref gsm_mem_calloc or \ref gsm_mem_realloc functions + * \param[in] ptr: Pointer to current allocated memory to resize, returned using \ref lwgsm_mem_malloc, + * \ref lwgsm_mem_calloc or \ref lwgsm_mem_realloc functions * \param[in] size: Number of bytes to allocate on new memory * \return Memory address on success, `NULL` otherwise - * \note Function is not available when \ref GSM_CFG_MEM_CUSTOM is `1` and must be implemented by user + * \note Function is not available when \ref LWGSM_CFG_MEM_CUSTOM is `1` and must be implemented by user */ -void * -gsm_mem_realloc(void* ptr, size_t size) { - gsm_core_lock(); +void* +lwgsm_mem_realloc(void* ptr, size_t size) { + lwgsm_core_lock(); ptr = mem_realloc(ptr, size); /* Reallocate and return pointer */ - gsm_core_unlock(); - GSM_DEBUGW(GSM_CFG_DBG_MEM | GSM_DBG_TYPE_TRACE, ptr == NULL, - "[MEM] Reallocation failed: %d bytes\r\n", (int)size); - GSM_DEBUGW(GSM_CFG_DBG_MEM | GSM_DBG_TYPE_TRACE, ptr != NULL, - "[MEM] Reallocation OK: %d bytes, addr: %p\r\n", (int)size, ptr); + lwgsm_core_unlock(); + LWGSM_DEBUGW(LWGSM_CFG_DBG_MEM | LWGSM_DBG_TYPE_TRACE, ptr == NULL, + "[MEM] Reallocation failed: %d bytes\r\n", (int)size); + LWGSM_DEBUGW(LWGSM_CFG_DBG_MEM | LWGSM_DBG_TYPE_TRACE, ptr != NULL, + "[MEM] Reallocation OK: %d bytes, addr: %p\r\n", (int)size, ptr); return ptr; } @@ -391,38 +394,38 @@ gsm_mem_realloc(void* ptr, size_t size) { * \param[in] num: Number of elements to allocate * \param[in] size: Size of each element * \return Memory address on success, `NULL` otherwise - * \note Function is not available when \ref GSM_CFG_MEM_CUSTOM is `1` and must be implemented by user + * \note Function is not available when \ref LWGSM_CFG_MEM_CUSTOM is `1` and must be implemented by user */ -void * -gsm_mem_calloc(size_t num, size_t size) { +void* +lwgsm_mem_calloc(size_t num, size_t size) { void* ptr; - gsm_core_lock(); - ptr = mem_calloc(num, size); /* Allocate memory and clear it to 0. Then return pointer */ - gsm_core_unlock(); - GSM_DEBUGW(GSM_CFG_DBG_MEM | GSM_DBG_TYPE_TRACE, ptr == NULL, - "[MEM] Callocation failed: %d bytes\r\n", (int)size * (int)num); - GSM_DEBUGW(GSM_CFG_DBG_MEM | GSM_DBG_TYPE_TRACE, ptr != NULL, - "[MEM] Callocation OK: %d bytes, addr: %p\r\n", (int)size * (int)num, ptr); + lwgsm_core_lock(); + ptr = mem_calloc(num, size); /* Allocate memory and clear it to 0. Then return pointer */ + lwgsm_core_unlock(); + LWGSM_DEBUGW(LWGSM_CFG_DBG_MEM | LWGSM_DBG_TYPE_TRACE, ptr == NULL, + "[MEM] Callocation failed: %d bytes\r\n", (int)size * (int)num); + LWGSM_DEBUGW(LWGSM_CFG_DBG_MEM | LWGSM_DBG_TYPE_TRACE, ptr != NULL, + "[MEM] Callocation OK: %d bytes, addr: %p\r\n", (int)size * (int)num, ptr); return ptr; } /** * \brief Free memory - * \param[in] ptr: Pointer to memory previously returned using \ref gsm_mem_malloc, - * \ref gsm_mem_calloc or \ref gsm_mem_realloc functions - * \note Function is not available when \ref GSM_CFG_MEM_CUSTOM is `1` and must be implemented by user + * \param[in] ptr: Pointer to memory previously returned using \ref lwgsm_mem_malloc, + * \ref lwgsm_mem_calloc or \ref lwgsm_mem_realloc functions + * \note Function is not available when \ref LWGSM_CFG_MEM_CUSTOM is `1` and must be implemented by user */ void -gsm_mem_free(void* ptr) { +lwgsm_mem_free(void* ptr) { if (ptr == NULL) { return; } - GSM_DEBUGF(GSM_CFG_DBG_MEM | GSM_DBG_TYPE_TRACE, - "[MEM] Free size: %d, address: %p\r\n", - (int)MEM_BLOCK_USER_SIZE(ptr), ptr); - gsm_core_lock(); + LWGSM_DEBUGF(LWGSM_CFG_DBG_MEM | LWGSM_DBG_TYPE_TRACE, + "[MEM] Free size: %d, address: %p\r\n", + (int)MEM_BLOCK_USER_SIZE(ptr), ptr); + lwgsm_core_lock(); mem_free(ptr); - gsm_core_unlock(); + lwgsm_core_unlock(); } /** @@ -431,16 +434,16 @@ gsm_mem_free(void* ptr) { * \param[in] regions: Pointer to list of regions to use for allocations * \param[in] len: Number of regions to use * \return `1` on success, `0` otherwise - * \note Function is not available when \ref GSM_CFG_MEM_CUSTOM is `1` + * \note Function is not available when \ref LWGSM_CFG_MEM_CUSTOM is `1` */ uint8_t -gsm_mem_assignmemory(const gsm_mem_region_t* regions, size_t len) { +lwgsm_mem_assignmemory(const lwgsm_mem_region_t* regions, size_t len) { uint8_t ret; ret = mem_assignmem(regions, len); /* Assign memory */ return ret; } -#endif /* !GSM_CFG_MEM_CUSTOM || __DOXYGEN__ */ +#endif /* !LWGSM_CFG_MEM_CUSTOM || __DOXYGEN__ */ /** * \brief Free memory in safe way by invalidating pointer after freeing @@ -448,9 +451,9 @@ gsm_mem_assignmemory(const gsm_mem_region_t* regions, size_t len) { * \return `1` on success, `0` otherwise */ uint8_t -gsm_mem_free_s(void** ptr) { +lwgsm_mem_free_s(void** ptr) { if (ptr != NULL && *ptr != NULL) { - gsm_mem_free(*ptr); + lwgsm_mem_free(*ptr); *ptr = NULL; return 1; } diff --git a/lwgsm/src/lwgsm/lwgsm_network.c b/lwgsm/src/lwgsm/lwgsm_network.c new file mode 100644 index 00000000..8ef59340 --- /dev/null +++ b/lwgsm/src/lwgsm/lwgsm_network.c @@ -0,0 +1,170 @@ +/** + * \file lwgsm_network.c + * \brief Network API + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_network.h" +#include "lwgsm/lwgsm_mem.h" + +#if LWGSM_CFG_NETWORK || __DOXYGEN__ + +/** + * \brief Attach to network and active PDP context + * \param[in] apn: APN name + * \param[in] user: User name to attach. Set to `NULL` if not used + * \param[in] pass: User password to attach. Set to `NULL` if not used + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsm_network_attach(const char* apn, const char* user, const char* pass, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_NETWORK_ATTACH; +#if LWGSM_CFG_CONN + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CIPSTATUS; +#endif /* LWGSM_CFG_CONN */ + LWGSM_MSG_VAR_REF(msg).msg.network_attach.apn = apn; + LWGSM_MSG_VAR_REF(msg).msg.network_attach.user = user; + LWGSM_MSG_VAR_REF(msg).msg.network_attach.pass = pass; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 200000); +} + +/** + * \brief Detach from network + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsm_network_detach(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_NETWORK_DETACH; +#if LWGSM_CFG_CONN + /* LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CIPSTATUS; */ +#endif /* LWGSM_CFG_CONN */ + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); +} + +/** + * \brief Check network PDP status + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsm_network_check_status(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CIPSTATUS; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); +} + +/** + * \brief Copy IP address from internal value to user variable + * \param[out] ip: Pointer to output IP variable + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsm_network_copy_ip(lwgsm_ip_t* ip) { + if (lwgsm_network_is_attached()) { + lwgsm_core_lock(); + LWGSM_MEMCPY(ip, &lwgsm.m.network.ip_addr, sizeof(*ip)); + lwgsm_core_unlock(); + return lwgsmOK; + } + return lwgsmERR; +} + +/** + * \brief Check if device is attached to network and PDP context is active + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_network_is_attached(void) { + uint8_t res; + lwgsm_core_lock(); + res = LWGSM_U8(lwgsm.m.network.is_attached); + lwgsm_core_unlock(); + return res; +} + +#endif /* LWGSM_CFG_NETWORK || __DOXYGEN__ */ + +/** + * \brief Read RSSI signal from network operator + * \param[out] rssi: RSSI output variable. When set to `0`, RSSI is not valid + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsm_network_rssi(int16_t* rssi, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CSQ_GET; + LWGSM_MSG_VAR_REF(msg).msg.csq.rssi = rssi; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 120000); +} + +/** + * \brief Get network registration status + * \return Member of \ref lwgsm_network_reg_status_t enumeration + */ +lwgsm_network_reg_status_t +lwgsm_network_get_reg_status(void) { + lwgsm_network_reg_status_t ret; + lwgsm_core_lock(); + ret = lwgsm.m.network.status; + lwgsm_core_unlock(); + return ret; +} diff --git a/gsm_at_lib/src/gsm/gsm_operator.c b/lwgsm/src/lwgsm/lwgsm_operator.c similarity index 52% rename from gsm_at_lib/src/gsm/gsm_operator.c rename to lwgsm/src/lwgsm/lwgsm_operator.c index ae0c4424..7e06669a 100644 --- a/gsm_at_lib/src/gsm/gsm_operator.c +++ b/lwgsm/src/lwgsm/lwgsm_operator.c @@ -1,10 +1,10 @@ -/** - * \file gsm_operator.c +/** + * \file lwgsm_operator.c * \brief Operator API functions */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,14 +26,14 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_operator.h" -#include "gsm/gsm_mem.h" +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_operator.h" +#include "lwgsm/lwgsm_mem.h" /** * \brief Get current operator @@ -41,54 +41,54 @@ * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used * \param[in] evt_arg: Custom argument for event callback function * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_operator_get(gsm_operator_curr_t* curr, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); +lwgsmr_t +lwgsm_operator_get(lwgsm_operator_curr_t* curr, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_COPS_GET; - GSM_MSG_VAR_REF(msg).msg.cops_get.curr = curr; + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_COPS_GET; + LWGSM_MSG_VAR_REF(msg).msg.cops_get.curr = curr; - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 2000); + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 2000); } /** * \brief Set current operator - * \param[in] mode: Operator mode. This parameter can be a value of \ref gsm_operator_mode_t enumeration - * \param[in] format: Operator data format. This parameter can be a value of \ref gsm_operator_format_t enumeration + * \param[in] mode: Operator mode. This parameter can be a value of \ref lwgsm_operator_mode_t enumeration + * \param[in] format: Operator data format. This parameter can be a value of \ref lwgsm_operator_format_t enumeration * \param[in] name: Operator name. This parameter must be valid according to `format` parameter * \param[in] num: Operator number. This parameter must be valid according to `format` parameter * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used * \param[in] evt_arg: Custom argument for event callback function * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_operator_set(gsm_operator_mode_t mode, gsm_operator_format_t format, const char* name, uint32_t num, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); +lwgsmr_t +lwgsm_operator_set(lwgsm_operator_mode_t mode, lwgsm_operator_format_t format, const char* name, uint32_t num, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); - if (mode != GSM_OPERATOR_MODE_AUTO) { /* Check parameters only if non-auto mode */ - GSM_ASSERT("format < GSM_OPERATOR_FORMAT_INVALID", format < GSM_OPERATOR_FORMAT_INVALID); - if (format != GSM_OPERATOR_FORMAT_NUMBER) { - GSM_ASSERT("name != NULL", name != NULL); + if (mode != LWGSM_OPERATOR_MODE_AUTO) { /* Check parameters only if non-auto mode */ + LWGSM_ASSERT("format < LWGSM_OPERATOR_FORMAT_INVALID", format < LWGSM_OPERATOR_FORMAT_INVALID); + if (format != LWGSM_OPERATOR_FORMAT_NUMBER) { + LWGSM_ASSERT("name != NULL", name != NULL); } } - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_COPS_SET; + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_COPS_SET; - GSM_MSG_VAR_REF(msg).msg.cops_set.mode = mode; - GSM_MSG_VAR_REF(msg).msg.cops_set.format = format; - GSM_MSG_VAR_REF(msg).msg.cops_set.name = name; - GSM_MSG_VAR_REF(msg).msg.cops_set.num = num; + LWGSM_MSG_VAR_REF(msg).msg.cops_set.mode = mode; + LWGSM_MSG_VAR_REF(msg).msg.cops_set.format = format; + LWGSM_MSG_VAR_REF(msg).msg.cops_set.name = name; + LWGSM_MSG_VAR_REF(msg).msg.cops_set.num = num; - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 2000); + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 2000); } /** @@ -99,23 +99,23 @@ gsm_operator_set(gsm_operator_mode_t mode, gsm_operator_format_t format, const c * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used * \param[in] evt_arg: Custom argument for event callback function * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_operator_scan(gsm_operator_t* ops, size_t opsl, size_t* opf, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); +lwgsmr_t +lwgsm_operator_scan(lwgsm_operator_t* ops, size_t opsl, size_t* opf, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); if (opf != NULL) { *opf = 0; } - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_COPS_GET_OPT; - GSM_MSG_VAR_REF(msg).msg.cops_scan.ops = ops; - GSM_MSG_VAR_REF(msg).msg.cops_scan.opsl = opsl; - GSM_MSG_VAR_REF(msg).msg.cops_scan.opf = opf; + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_COPS_GET_OPT; + LWGSM_MSG_VAR_REF(msg).msg.cops_scan.ops = ops; + LWGSM_MSG_VAR_REF(msg).msg.cops_scan.opsl = opsl; + LWGSM_MSG_VAR_REF(msg).msg.cops_scan.opf = opf; - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 120000); + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 120000); } diff --git a/gsm_at_lib/src/gsm/gsm_parser.c b/lwgsm/src/lwgsm/lwgsm_parser.c similarity index 54% rename from gsm_at_lib/src/gsm/gsm_parser.c rename to lwgsm/src/lwgsm/lwgsm_parser.c index a2938bae..198153a9 100644 --- a/gsm_at_lib/src/gsm/gsm_parser.c +++ b/lwgsm/src/lwgsm/lwgsm_parser.c @@ -1,10 +1,10 @@ /** - * \file gsm_parser.c + * \file lwgsm_parser.c * \brief Parse incoming data from AT port */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,55 +26,55 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_parser.h" -#include "gsm/gsm_mem.h" +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_parser.h" +#include "lwgsm/lwgsm_mem.h" /** * \brief Parse number from string * \note Input string pointer is changed and number is skipped - * \param[in] Pointer to pointer to string to parse + * \param[in,out] str: Pointer to pointer to string to parse * \return Parsed number */ int32_t -gsmi_parse_number(const char** str) { +lwgsmi_parse_number(const char** str) { int32_t val = 0; uint8_t minus = 0; const char* p = *str; /* */ if (*p == '"') { /* Skip leading quotes */ - p++; + ++p; } if (*p == ',') { /* Skip leading comma */ - p++; + ++p; } if (*p == '"') { /* Skip leading quotes */ - p++; + ++p; } if (*p == '/') { /* Skip '/' character, used in datetime */ - p++; + ++p; } if (*p == ':') { /* Skip ':' character, used in datetime */ - p++; + ++p; } if (*p == '+') { /* Skip '+' character, used in datetime */ - p++; + ++p; } if (*p == '-') { /* Check negative number */ minus = 1; - p++; + ++p; } - while (GSM_CHARISNUM(*p)) { /* Parse until character is valid number */ - val = val * 10 + GSM_CHARTONUM(*p); - p++; + while (LWGSM_CHARISNUM(*p)) { /* Parse until character is valid number */ + val = val * 10 + LWGSM_CHARTONUM(*p); + ++p; } if (*p == '"') { /* Skip trailling quotes */ - p++; + ++p; } *str = p; /* Save new pointer with new offset */ @@ -84,29 +84,29 @@ gsmi_parse_number(const char** str) { /** * \brief Parse number from string as hex * \note Input string pointer is changed and number is skipped - * \param[in] Pointer to pointer to string to parse + * \param[in,out] str: Pointer to pointer to string to parse * \return Parsed number */ uint32_t -gsmi_parse_hexnumber(const char** str) { +lwgsmi_parse_hexnumber(const char** str) { int32_t val = 0; const char* p = *str; /* */ if (*p == '"') { /* Skip leading quotes */ - p++; + ++p; } if (*p == ',') { /* Skip leading comma */ - p++; + ++p; } if (*p == '"') { /* Skip leading quotes */ - p++; + ++p; } - while (GSM_CHARISHEXNUM(*p)) { /* Parse until character is valid number */ - val = val * 16 + GSM_CHARHEXTONUM(*p); - p++; + while (LWGSM_CHARISHEXNUM(*p)) { /* Parse until character is valid number */ + val = val * 16 + LWGSM_CHARHEXTONUM(*p); + ++p; } if (*p == ',') { /* Go to next entry if possible */ - p++; + ++p; } *str = p; /* Save new pointer with new offset */ return val; @@ -124,34 +124,35 @@ gsmi_parse_hexnumber(const char** str) { * \return `1` on success, `0` otherwise */ uint8_t -gsmi_parse_string(const char** src, char* dst, size_t dst_len, uint8_t trim) { +lwgsmi_parse_string(const char** src, char* dst, size_t dst_len, uint8_t trim) { const char* p = *src; size_t i; if (*p == ',') { - p++; + ++p; } if (*p == '"') { - p++; + ++p; } i = 0; if (dst_len > 0) { - dst_len--; + --dst_len; } while (*p) { - if (*p == '"' && (p[1] == ',' || p[1] == '\r' || p[1] == '\n')) { - p++; + if ((*p == '"' && (p[1] == ',' || p[1] == '\r' || p[1] == '\n')) + || (*p == '\r' || *p == '\n')) { + ++p; break; } if (dst != NULL) { if (i < dst_len) { *dst++ = *p; - i++; + ++i; } else if (!trim) { break; } } - p++; + ++p; } if (dst != NULL) { *dst = 0; @@ -165,37 +166,40 @@ gsmi_parse_string(const char** src, char* dst, size_t dst_len, uint8_t trim) { * \param[in] src: Pointer to pointer to input string */ void -gsmi_check_and_trim(const char** src) { +lwgsmi_check_and_trim(const char** src) { const char* t = *src; if (*t != '"' && *t != '\r' && *t != ',') { /* Check if trim required */ - gsmi_parse_string(src, NULL, 0, 1); /* Trim to the end */ + lwgsmi_parse_string(src, NULL, 0, 1); /* Trim to the end */ } } /** * \brief Parse string as IP address * \param[in,out] src: Pointer to pointer to string to parse from - * \param[in] dst: Destination pointer + * \param[out] ip: Pointer to IP memory * \return `1 on success, 0 otherwise */ uint8_t -gsmi_parse_ip(const char** src, gsm_ip_t* ip) { +lwgsmi_parse_ip(const char** src, lwgsm_ip_t* ip) { const char* p = *src; if (*p == ',') { - p++; + ++p; } if (*p == '"') { - p++; + ++p; } - if (GSM_CHARISNUM(*p)) { - ip->ip[0] = gsmi_parse_number(&p); p++; - ip->ip[1] = gsmi_parse_number(&p); p++; - ip->ip[2] = gsmi_parse_number(&p); p++; - ip->ip[3] = gsmi_parse_number(&p); + if (LWGSM_CHARISNUM(*p)) { + ip->ip[0] = lwgsmi_parse_number(&p); + ++p; + ip->ip[1] = lwgsmi_parse_number(&p); + ++p; + ip->ip[2] = lwgsmi_parse_number(&p); + ++p; + ip->ip[3] = lwgsmi_parse_number(&p); } if (*p == '"') { - p++; + ++p; } *src = p; /* Set new pointer */ @@ -205,27 +209,32 @@ gsmi_parse_ip(const char** src, gsm_ip_t* ip) { /** * \brief Parse string as MAC address * \param[in,out] src: Pointer to pointer to string to parse from - * \param[in] dst: Destination pointer + * \param[out] mac: Pointer to MAC memory * \return 1 on success, 0 otherwise */ uint8_t -gsmi_parse_mac(const char** src, gsm_mac_t* mac) { +lwgsmi_parse_mac(const char** src, lwgsm_mac_t* mac) { const char* p = *src; if (*p == '"') { - p++; - } - mac->mac[0] = gsmi_parse_hexnumber(&p); p++; - mac->mac[1] = gsmi_parse_hexnumber(&p); p++; - mac->mac[2] = gsmi_parse_hexnumber(&p); p++; - mac->mac[3] = gsmi_parse_hexnumber(&p); p++; - mac->mac[4] = gsmi_parse_hexnumber(&p); p++; - mac->mac[5] = gsmi_parse_hexnumber(&p); + ++p; + } + mac->mac[0] = lwgsmi_parse_hexnumber(&p); + ++p; + mac->mac[1] = lwgsmi_parse_hexnumber(&p); + ++p; + mac->mac[2] = lwgsmi_parse_hexnumber(&p); + ++p; + mac->mac[3] = lwgsmi_parse_hexnumber(&p); + ++p; + mac->mac[4] = lwgsmi_parse_hexnumber(&p); + ++p; + mac->mac[5] = lwgsmi_parse_hexnumber(&p); if (*p == '"') { - p++; + ++p; } if (*p == ',') { - p++; + ++p; } *src = p; return 1; @@ -236,34 +245,34 @@ gsmi_parse_mac(const char** src, gsm_mac_t* mac) { * \param[in,out] src: Pointer to pointer to string to parse from * \return Parsed memory */ -gsm_mem_t -gsmi_parse_memory(const char** src) { +lwgsm_mem_t +lwgsmi_parse_memory(const char** src) { size_t i, sl; - gsm_mem_t mem = GSM_MEM_UNKNOWN; + lwgsm_mem_t mem = LWGSM_MEM_UNKNOWN; const char* s = *src; if (*s == ',') { - s++; + ++s; } if (*s == '"') { - s++; + ++s; } /* Scan all memories available for modem */ - for (i = 0; i < gsm_dev_mem_map_size; i++) { - sl = strlen(gsm_dev_mem_map[i].mem_str); - if (!strncmp(s, gsm_dev_mem_map[i].mem_str, sl)) { - mem = gsm_dev_mem_map[i].mem; + for (i = 0; i < lwgsm_dev_mem_map_size; ++i) { + sl = strlen(lwgsm_dev_mem_map[i].mem_str); + if (!strncmp(s, lwgsm_dev_mem_map[i].mem_str, sl)) { + mem = lwgsm_dev_mem_map[i].mem; s += sl; break; } } - if (mem == GSM_MEM_UNKNOWN) { - gsmi_parse_string(&s, NULL, 0, 1); /* Skip string */ + if (mem == LWGSM_MEM_UNKNOWN) { + lwgsmi_parse_string(&s, NULL, 0, 1); /* Skip string */ } if (*s == '"') { - s++; + ++s; } *src = s; return mem; @@ -277,23 +286,23 @@ gsmi_parse_memory(const char** src) { * \return 1 on success, 0 otherwise */ uint8_t -gsmi_parse_memories_string(const char** src, uint32_t* mem_dst) { +lwgsmi_parse_memories_string(const char** src, uint32_t* mem_dst) { const char* str = *src; - gsm_mem_t mem; + lwgsm_mem_t mem; *mem_dst = 0; if (*str == ',') { - str++; + ++str; } if (*str == '(') { - str++; + ++str; } do { - mem = gsmi_parse_memory(&str); /* Parse memory string */ - *mem_dst |= GSM_U32(1 << GSM_U32(mem)); /* Set as bit field */ + mem = lwgsmi_parse_memory(&str); /* Parse memory string */ + *mem_dst |= LWGSM_U32(1 << LWGSM_U32(mem)); /* Set as bit field */ } while (*str && *str != ')'); if (*str == ')') { - str++; + ++str; } *src = str; return 1; @@ -301,37 +310,38 @@ gsmi_parse_memories_string(const char** src, uint32_t* mem_dst) { /** * \brief Parse received +CREG message - * \param[in] str: Input string + * \param[in] str: Input string to parse from + * \param[in] skip_first: Set to `1` to skip first number * \return 1 on success, 0 otherwise */ uint8_t -gsmi_parse_creg(const char* str, uint8_t skip_first) { +lwgsmi_parse_creg(const char* str, uint8_t skip_first) { if (*str == '+') { str += 7; } if (skip_first) { - gsmi_parse_number(&str); + lwgsmi_parse_number(&str); } - gsm.m.network.status = (gsm_network_reg_status_t)gsmi_parse_number(&str); + lwgsm.m.network.status = (lwgsm_network_reg_status_t)lwgsmi_parse_number(&str); /* * In case we are connected to network, * scan for current network info */ - if (gsm.m.network.status == GSM_NETWORK_REG_STATUS_CONNECTED || - gsm.m.network.status == GSM_NETWORK_REG_STATUS_CONNECTED_ROAMING) { + if (lwgsm.m.network.status == LWGSM_NETWORK_REG_STATUS_CONNECTED || + lwgsm.m.network.status == LWGSM_NETWORK_REG_STATUS_CONNECTED_ROAMING) { /* Try to get operator */ /* Notify user in case we are not able to add new command to queue */ - gsm_operator_get(&gsm.m.network.curr_operator, NULL, NULL, 0); -#if GSM_CFG_NETWORK - } else if (gsm_network_is_attached()) { - gsm_network_check_status(NULL, NULL, 0); /* Do the update */ -#endif /* GSM_CFG_NETWORK */ + lwgsm_operator_get(&lwgsm.m.network.curr_operator, NULL, NULL, 0); +#if LWGSM_CFG_NETWORK + } else if (lwgsm_network_is_attached()) { + lwgsm_network_check_status(NULL, NULL, 0); /* Do the update */ +#endif /* LWGSM_CFG_NETWORK */ } /* Send callback event */ - gsmi_send_cb(GSM_EVT_NETWORK_REG_CHANGED); + lwgsmi_send_cb(LWGSM_EVT_NETWORK_REG_CHANGED); return 1; } @@ -342,27 +352,27 @@ gsmi_parse_creg(const char* str, uint8_t skip_first) { * \return 1 on success, 0 otherwise */ uint8_t -gsmi_parse_csq(const char* str) { +lwgsmi_parse_csq(const char* str) { int16_t rssi; if (*str == '+') { str += 6; } - rssi = gsmi_parse_number(&str); + rssi = lwgsmi_parse_number(&str); if (rssi < 32) { rssi = -(113 - (rssi * 2)); } else { rssi = 0; } - gsm.m.rssi = rssi; /* Save RSSI to global variable */ - if (gsm.msg->cmd_def == GSM_CMD_CSQ_GET && - gsm.msg->msg.csq.rssi != NULL) { - *gsm.msg->msg.csq.rssi = rssi; /* Save to user variable */ + lwgsm.m.rssi = rssi; /* Save RSSI to global variable */ + if (lwgsm.msg->cmd_def == LWGSM_CMD_CSQ_GET && + lwgsm.msg->msg.csq.rssi != NULL) { + *lwgsm.msg->msg.csq.rssi = rssi; /* Save to user variable */ } /* Report CSQ status */ - gsm.evt.evt.rssi.rssi = rssi; - gsmi_send_cb(GSM_EVT_SIGNAL_STRENGTH); /* RSSI event type */ + lwgsm.evt.evt.rssi.rssi = rssi; + lwgsmi_send_cb(LWGSM_EVT_SIGNAL_STRENGTH); /* RSSI event type */ return 1; } @@ -374,39 +384,39 @@ gsmi_parse_csq(const char* str) { * \return 1 on success, 0 otherwise */ uint8_t -gsmi_parse_cpin(const char* str, uint8_t send_evt) { - gsm_sim_state_t state; +lwgsmi_parse_cpin(const char* str, uint8_t send_evt) { + lwgsm_sim_state_t state; if (*str == '+') { str += 7; } if (!strncmp(str, "READY", 5)) { - state = GSM_SIM_STATE_READY; + state = LWGSM_SIM_STATE_READY; } else if (!strncmp(str, "NOT READY", 9)) { - state = GSM_SIM_STATE_NOT_READY; + state = LWGSM_SIM_STATE_NOT_READY; } else if (!strncmp(str, "NOT INSERTED", 14)) { - state = GSM_SIM_STATE_NOT_INSERTED; + state = LWGSM_SIM_STATE_NOT_INSERTED; } else if (!strncmp(str, "SIM PIN", 7)) { - state = GSM_SIM_STATE_PIN; + state = LWGSM_SIM_STATE_PIN; } else if (!strncmp(str, "SIM PUK", 7)) { - state = GSM_SIM_STATE_PUK; + state = LWGSM_SIM_STATE_PUK; } else { - state = GSM_SIM_STATE_NOT_READY; + state = LWGSM_SIM_STATE_NOT_READY; } /* React only on change */ - if (state != gsm.m.sim.state) { - gsm.m.sim.state = state; + if (state != lwgsm.m.sim.state) { + lwgsm.m.sim.state = state; /* * In case SIM is ready, * start with basic info about SIM */ - if (gsm.m.sim.state == GSM_SIM_STATE_READY) { - gsmi_get_sim_info(0); + if (lwgsm.m.sim.state == LWGSM_SIM_STATE_READY) { + lwgsmi_get_sim_info(0); } if (send_evt) { - gsm.evt.evt.cpin.state = gsm.m.sim.state; - gsmi_send_cb(GSM_EVT_SIM_STATE_CHANGED); + lwgsm.evt.evt.cpin.state = lwgsm.m.sim.state; + lwgsmi_send_cb(LWGSM_EVT_SIM_STATE_CHANGED); } } return 1; @@ -418,35 +428,36 @@ gsmi_parse_cpin(const char* str, uint8_t send_evt) { * \return 1 on success, 0 otherwise */ uint8_t -gsmi_parse_cops(const char* str) { +lwgsmi_parse_cops(const char* str) { if (*str == '+') { str += 7; } - gsm.m.network.curr_operator.mode = (gsm_operator_mode_t)gsmi_parse_number(&str); + lwgsm.m.network.curr_operator.mode = (lwgsm_operator_mode_t)lwgsmi_parse_number(&str); if (*str != '\r') { - gsm.m.network.curr_operator.format = (gsm_operator_format_t)gsmi_parse_number(&str); + lwgsm.m.network.curr_operator.format = (lwgsm_operator_format_t)lwgsmi_parse_number(&str); if (*str != '\r') { - switch (gsm.m.network.curr_operator.format) { - case GSM_OPERATOR_FORMAT_LONG_NAME: - gsmi_parse_string(&str, gsm.m.network.curr_operator.data.long_name, sizeof(gsm.m.network.curr_operator.data.long_name), 1); + switch (lwgsm.m.network.curr_operator.format) { + case LWGSM_OPERATOR_FORMAT_LONG_NAME: + lwgsmi_parse_string(&str, lwgsm.m.network.curr_operator.data.long_name, sizeof(lwgsm.m.network.curr_operator.data.long_name), 1); + break; + case LWGSM_OPERATOR_FORMAT_SHORT_NAME: + lwgsmi_parse_string(&str, lwgsm.m.network.curr_operator.data.short_name, sizeof(lwgsm.m.network.curr_operator.data.short_name), 1); break; - case GSM_OPERATOR_FORMAT_SHORT_NAME: - gsmi_parse_string(&str, gsm.m.network.curr_operator.data.short_name, sizeof(gsm.m.network.curr_operator.data.short_name), 1); + case LWGSM_OPERATOR_FORMAT_NUMBER: + lwgsm.m.network.curr_operator.data.num = LWGSM_U32(lwgsmi_parse_number(&str)); break; - case GSM_OPERATOR_FORMAT_NUMBER: - gsm.m.network.curr_operator.data.num = GSM_U32(gsmi_parse_number(&str)); + default: break; - default: break; } } } else { - gsm.m.network.curr_operator.format = GSM_OPERATOR_FORMAT_INVALID; + lwgsm.m.network.curr_operator.format = LWGSM_OPERATOR_FORMAT_INVALID; } - if (CMD_IS_DEF(GSM_CMD_COPS_GET) && - gsm.msg->msg.cops_get.curr != NULL) { /* Check and copy to user variable */ - GSM_MEMCPY(gsm.msg->msg.cops_get.curr, &gsm.m.network.curr_operator, sizeof(*gsm.msg->msg.cops_get.curr)); + if (CMD_IS_DEF(LWGSM_CMD_COPS_GET) && + lwgsm.msg->msg.cops_get.curr != NULL) { /* Check and copy to user variable */ + LWGSM_MEMCPY(lwgsm.msg->msg.cops_get.curr, &lwgsm.m.network.curr_operator, sizeof(*lwgsm.msg->msg.cops_get.curr)); } return 1; } @@ -459,19 +470,19 @@ gsmi_parse_cops(const char* str) { * \return 1 on success, 0 otherwise */ uint8_t -gsmi_parse_cops_scan(uint8_t ch, uint8_t reset) { +lwgsmi_parse_cops_scan(uint8_t ch, uint8_t reset) { static union { struct { - uint8_t bo:1; /*!< Bracket open flag (Bracket Open) */ - uint8_t ccd:1; /*!< 2 consecutive commas detected in a row (Comma Comma Detected) */ - uint8_t tn:2; /*!< Term number in response, 2 bits for 4 diff values */ + uint8_t bo: 1; /*!< Bracket open flag (Bracket Open) */ + uint8_t ccd: 1; /*!< 2 consecutive commas detected in a row (Comma Comma Detected) */ + uint8_t tn: 2; /*!< Term number in response, 2 bits for 4 diff values */ uint8_t tp; /*!< Current term character position */ uint8_t ch_prev; /*!< Previous character */ } f; } u; if (reset) { /* Check for reset status */ - GSM_MEMSET(&u, 0x00, sizeof(u)); /* Reset everything */ + LWGSM_MEMSET(&u, 0x00, sizeof(u)); /* Reset everything */ u.f.ch_prev = 0; return 1; } @@ -485,7 +496,7 @@ gsmi_parse_cops_scan(uint8_t ch, uint8_t reset) { } if (u.f.ccd || /* Ignore data after 2 commas in a row */ - gsm.msg->msg.cops_scan.opsi >= gsm.msg->msg.cops_scan.opsl) { /* or if array is full */ + lwgsm.msg->msg.cops_scan.opsi >= lwgsm.msg->msg.cops_scan.opsl) { /* or if array is full */ return 1; } @@ -494,39 +505,40 @@ gsmi_parse_cops_scan(uint8_t ch, uint8_t reset) { u.f.bo = 0; /* Clear bracket open flag */ u.f.tn = 0; /* Go to next term */ u.f.tp = 0; /* Go to beginning of next term */ - gsm.msg->msg.cops_scan.opsi++; /* Increase index */ - if (gsm.msg->msg.cops_scan.opf != NULL) { - *gsm.msg->msg.cops_scan.opf = gsm.msg->msg.cops_scan.opsi; + ++lwgsm.msg->msg.cops_scan.opsi; /* Increase index */ + if (lwgsm.msg->msg.cops_scan.opf != NULL) { + *lwgsm.msg->msg.cops_scan.opf = lwgsm.msg->msg.cops_scan.opsi; } } else if (ch == ',') { - u.f.tn++; /* Go to next term */ + ++u.f.tn; /* Go to next term */ u.f.tp = 0; /* Go to beginning of next term */ } else if (ch != '"') { /* We have valid data */ - size_t i = gsm.msg->msg.cops_scan.opsi; + size_t i = lwgsm.msg->msg.cops_scan.opsi; switch (u.f.tn) { case 0: { /* Parse status info */ - gsm.msg->msg.cops_scan.ops[i].stat = (gsm_operator_status_t)(10 * (size_t)gsm.msg->msg.cops_scan.ops[i].stat + (ch - '0')); + lwgsm.msg->msg.cops_scan.ops[i].stat = (lwgsm_operator_status_t)(10 * (size_t)lwgsm.msg->msg.cops_scan.ops[i].stat + (ch - '0')); break; } case 1: { /*!< Parse long name */ - if (u.f.tp < sizeof(gsm.msg->msg.cops_scan.ops[i].long_name) - 1) { - gsm.msg->msg.cops_scan.ops[i].long_name[u.f.tp++] = ch; - gsm.msg->msg.cops_scan.ops[i].long_name[u.f.tp] = 0; + if (u.f.tp < sizeof(lwgsm.msg->msg.cops_scan.ops[i].long_name) - 1) { + lwgsm.msg->msg.cops_scan.ops[i].long_name[u.f.tp] = ch; + lwgsm.msg->msg.cops_scan.ops[i].long_name[++u.f.tp] = 0; } break; } case 2: { /*!< Parse short name */ - if (u.f.tp < sizeof(gsm.msg->msg.cops_scan.ops[i].short_name) - 1) { - gsm.msg->msg.cops_scan.ops[i].short_name[u.f.tp++] = ch; - gsm.msg->msg.cops_scan.ops[i].short_name[u.f.tp] = 0; + if (u.f.tp < sizeof(lwgsm.msg->msg.cops_scan.ops[i].short_name) - 1) { + lwgsm.msg->msg.cops_scan.ops[i].short_name[u.f.tp] = ch; + lwgsm.msg->msg.cops_scan.ops[i].short_name[++u.f.tp] = 0; } break; } case 3: { /*!< Parse number */ - gsm.msg->msg.cops_scan.ops[i].num = (10 * gsm.msg->msg.cops_scan.ops[i].num) + (ch - '0'); + lwgsm.msg->msg.cops_scan.ops[i].num = (10 * lwgsm.msg->msg.cops_scan.ops[i].num) + (ch - '0'); break; } - default: break; + default: + break; } } } else { @@ -547,19 +559,19 @@ gsmi_parse_cops_scan(uint8_t ch, uint8_t reset) { * \return 1 on success, 0 otherwise */ uint8_t -gsmi_parse_datetime(const char** src, gsm_datetime_t* dt) { - dt->date = gsmi_parse_number(src); - dt->month = gsmi_parse_number(src); - dt->year = GSM_U16(2000) + gsmi_parse_number(src); - dt->hours = gsmi_parse_number(src); - dt->minutes = gsmi_parse_number(src); - dt->seconds = gsmi_parse_number(src); - - gsmi_check_and_trim(src); /* Trim text to the end */ +lwgsmi_parse_datetime(const char** src, lwgsm_datetime_t* dt) { + dt->date = lwgsmi_parse_number(src); + dt->month = lwgsmi_parse_number(src); + dt->year = LWGSM_U16(2000) + lwgsmi_parse_number(src); + dt->hours = lwgsmi_parse_number(src); + dt->minutes = lwgsmi_parse_number(src); + dt->seconds = lwgsmi_parse_number(src); + + lwgsmi_check_and_trim(src); /* Trim text to the end */ return 1; } -#if GSM_CFG_CALL || __DOXYGEN__ +#if LWGSM_CFG_CALL || __DOXYGEN__ /** * \brief Parse received +CLCC with call status info @@ -568,30 +580,30 @@ gsmi_parse_datetime(const char** src, gsm_datetime_t* dt) { * \return 1 on success, 0 otherwise */ uint8_t -gsmi_parse_clcc(const char* str, uint8_t send_evt) { +lwgsmi_parse_clcc(const char* str, uint8_t send_evt) { if (*str == '+') { str += 7; } - gsm.m.call.id = gsmi_parse_number(&str); - gsm.m.call.dir = (gsm_call_dir_t)gsmi_parse_number(&str); - gsm.m.call.state = (gsm_call_state_t)gsmi_parse_number(&str); - gsm.m.call.type = (gsm_call_type_t)gsmi_parse_number(&str); - gsm.m.call.is_multipart = (gsm_call_type_t)gsmi_parse_number(&str); - gsmi_parse_string(&str, gsm.m.call.number, sizeof(gsm.m.call.number), 1); - gsm.m.call.addr_type = gsmi_parse_number(&str); - gsmi_parse_string(&str, gsm.m.call.name, sizeof(gsm.m.call.name), 1); + lwgsm.m.call.id = lwgsmi_parse_number(&str); + lwgsm.m.call.dir = (lwgsm_call_dir_t)lwgsmi_parse_number(&str); + lwgsm.m.call.state = (lwgsm_call_state_t)lwgsmi_parse_number(&str); + lwgsm.m.call.type = (lwgsm_call_type_t)lwgsmi_parse_number(&str); + lwgsm.m.call.is_multipart = (lwgsm_call_type_t)lwgsmi_parse_number(&str); + lwgsmi_parse_string(&str, lwgsm.m.call.number, sizeof(lwgsm.m.call.number), 1); + lwgsm.m.call.addr_type = lwgsmi_parse_number(&str); + lwgsmi_parse_string(&str, lwgsm.m.call.name, sizeof(lwgsm.m.call.name), 1); if (send_evt) { - gsm.evt.evt.call_changed.call = &gsm.m.call; - gsmi_send_cb(GSM_EVT_CALL_CHANGED); + lwgsm.evt.evt.call_changed.call = &lwgsm.m.call; + lwgsmi_send_cb(LWGSM_EVT_CALL_CHANGED); } return 1; } -#endif /* GSM_CFG_CALL || __DOXYGEN__ */ +#endif /* LWGSM_CFG_CALL || __DOXYGEN__ */ -#if GSM_CFG_SMS || __DOXYGEN__ +#if LWGSM_CFG_SMS || __DOXYGEN__ /** * \brief Parse string and check for type of SMS state @@ -600,23 +612,23 @@ gsmi_parse_clcc(const char* str, uint8_t send_evt) { * \return 1 on success, 0 otherwise */ uint8_t -gsmi_parse_sms_status(const char** src, gsm_sms_status_t* stat) { - gsm_sms_status_t s; +lwgsmi_parse_sms_status(const char** src, lwgsm_sms_status_t* stat) { + lwgsm_sms_status_t s; char t[11]; - gsmi_parse_string(src, t, sizeof(t), 1); /* Parse string and advance */ + lwgsmi_parse_string(src, t, sizeof(t), 1); /* Parse string and advance */ if (!strcmp(t, "REC UNREAD")) { - s = GSM_SMS_STATUS_UNREAD; + s = LWGSM_SMS_STATUS_UNREAD; } else if (!strcmp(t, "REC READ")) { - s = GSM_SMS_STATUS_READ; + s = LWGSM_SMS_STATUS_READ; } else if (!strcmp(t, "STO UNSENT")) { - s = GSM_SMS_STATUS_UNSENT; + s = LWGSM_SMS_STATUS_UNSENT; } else if (!strcmp(t, "REC SENT")) { - s = GSM_SMS_STATUS_SENT; + s = LWGSM_SMS_STATUS_SENT; } else { - s = GSM_SMS_STATUS_ALL; /* Error! */ + s = LWGSM_SMS_STATUS_ALL; /* Error! */ } - if (s != GSM_SMS_STATUS_ALL) { + if (s != LWGSM_SMS_STATUS_ALL) { *stat = s; return 1; } @@ -630,13 +642,13 @@ gsmi_parse_sms_status(const char** src, gsm_sms_status_t* stat) { * \return `1` on success, `0` otherwise */ uint8_t -gsmi_parse_cmgs(const char* str, size_t* num) { +lwgsmi_parse_cmgs(const char* str, size_t* num) { if (*str == '+') { str += 7; } if (num != NULL) { - *num = (size_t)gsmi_parse_number(&str); + *num = (size_t)lwgsmi_parse_number(&str); } return 1; } @@ -648,18 +660,18 @@ gsmi_parse_cmgs(const char* str, size_t* num) { * \return 1 on success, 0 otherwise */ uint8_t -gsmi_parse_cmgr(const char* str) { - gsm_sms_entry_t* e; +lwgsmi_parse_cmgr(const char* str) { + lwgsm_sms_entry_t* e; if (*str == '+') { str += 7; } - e = gsm.msg->msg.sms_read.entry; + e = lwgsm.msg->msg.sms_read.entry; e->length = 0; - gsmi_parse_sms_status(&str, &e->status); - gsmi_parse_string(&str, e->number, sizeof(e->number), 1); - gsmi_parse_string(&str, e->name, sizeof(e->name), 1); - gsmi_parse_datetime(&str, &e->datetime); + lwgsmi_parse_sms_status(&str, &e->status); + lwgsmi_parse_string(&str, e->number, sizeof(e->number), 1); + lwgsmi_parse_string(&str, e->name, sizeof(e->name), 1); + lwgsmi_parse_datetime(&str, &e->datetime); return 1; } @@ -671,11 +683,11 @@ gsmi_parse_cmgr(const char* str) { * \return 1 on success, 0 otherwise */ uint8_t -gsmi_parse_cmgl(const char* str) { - gsm_sms_entry_t* e; +lwgsmi_parse_cmgl(const char* str) { + lwgsm_sms_entry_t* e; - if (!CMD_IS_DEF(GSM_CMD_CMGL) || - gsm.msg->msg.sms_list.ei >= gsm.msg->msg.sms_list.etr) { + if (!CMD_IS_DEF(LWGSM_CMD_CMGL) || + lwgsm.msg->msg.sms_list.ei >= lwgsm.msg->msg.sms_list.etr) { return 0; } @@ -683,14 +695,14 @@ gsmi_parse_cmgl(const char* str) { str += 7; } - e = &gsm.msg->msg.sms_list.entries[gsm.msg->msg.sms_list.ei]; + e = &lwgsm.msg->msg.sms_list.entries[lwgsm.msg->msg.sms_list.ei]; e->length = 0; - e->mem = gsm.msg->msg.sms_list.mem; /* Manually set memory */ - e->pos = GSM_SZ(gsmi_parse_number(&str)); /* Scan position */ - gsmi_parse_sms_status(&str, &e->status); - gsmi_parse_string(&str, e->number, sizeof(e->number), 1); - gsmi_parse_string(&str, e->name, sizeof(e->name), 1); - gsmi_parse_datetime(&str, &e->datetime); + e->mem = lwgsm.msg->msg.sms_list.mem; /* Manually set memory */ + e->pos = LWGSM_SZ(lwgsmi_parse_number(&str)); /* Scan position */ + lwgsmi_parse_sms_status(&str, &e->status); + lwgsmi_parse_string(&str, e->number, sizeof(e->number), 1); + lwgsmi_parse_string(&str, e->name, sizeof(e->name), 1); + lwgsmi_parse_datetime(&str, &e->datetime); return 1; } @@ -702,16 +714,16 @@ gsmi_parse_cmgl(const char* str) { * \return 1 on success, 0 otherwise */ uint8_t -gsmi_parse_cmti(const char* str, uint8_t send_evt) { +lwgsmi_parse_cmti(const char* str, uint8_t send_evt) { if (*str == '+') { str += 7; } - gsm.evt.evt.sms_recv.mem = gsmi_parse_memory(&str); /* Parse memory string */ - gsm.evt.evt.sms_recv.pos = gsmi_parse_number(&str); /* Parse number */ + lwgsm.evt.evt.sms_recv.mem = lwgsmi_parse_memory(&str); /* Parse memory string */ + lwgsm.evt.evt.sms_recv.pos = lwgsmi_parse_number(&str); /* Parse number */ if (send_evt) { - gsmi_send_cb(GSM_EVT_SMS_RECV); + lwgsmi_send_cb(LWGSM_EVT_SMS_RECV); } return 1; } @@ -723,43 +735,44 @@ gsmi_parse_cmti(const char* str, uint8_t send_evt) { * \return 1 on success, 0 otherwise */ uint8_t -gsmi_parse_cpms(const char* str, uint8_t opt) { +lwgsmi_parse_cpms(const char* str, uint8_t opt) { uint8_t i; if (*str == '+') { str += 7; } switch (opt) { /* Check expected input string */ case 0: { /* Get list of CPMS options: +CPMS: (("","","",..),("....")("...")) */ - for (i = 0; i < 3; i++) { /* 3 different memories for "operation","receive","sent" */ - if (!gsmi_parse_memories_string(&str, &gsm.m.sms.mem[i].mem_available)) { + for (i = 0; i < 3; ++i) { /* 3 different memories for "operation","receive","sent" */ + if (!lwgsmi_parse_memories_string(&str, &lwgsm.m.sms.mem[i].mem_available)) { return 0; } } break; } case 1: { /* Received statement of current info: +CPMS: "ME",10,20,"SE",2,20,"... */ - for (i = 0; i < 3; i++) { /* 3 memories expected */ - gsm.m.sms.mem[i].current = gsmi_parse_memory(&str); /* Parse memory string and save it as current */ - gsm.m.sms.mem[i].used = gsmi_parse_number(&str);/* Get used memory size */ - gsm.m.sms.mem[i].total = gsmi_parse_number(&str); /* Get total memory size */ + for (i = 0; i < 3; ++i) { /* 3 memories expected */ + lwgsm.m.sms.mem[i].current = lwgsmi_parse_memory(&str); /* Parse memory string and save it as current */ + lwgsm.m.sms.mem[i].used = lwgsmi_parse_number(&str);/* Get used memory size */ + lwgsm.m.sms.mem[i].total = lwgsmi_parse_number(&str); /* Get total memory size */ } break; } case 2: { /* Received statement of set info: +CPMS: 10,20,2,20 */ - for (i = 0; i < 3; i++) { /* 3 memories expected */ - gsm.m.sms.mem[i].used = gsmi_parse_number(&str);/* Get used memory size */ - gsm.m.sms.mem[i].total = gsmi_parse_number(&str); /* Get total memory size */ + for (i = 0; i < 3; ++i) { /* 3 memories expected */ + lwgsm.m.sms.mem[i].used = lwgsmi_parse_number(&str);/* Get used memory size */ + lwgsm.m.sms.mem[i].total = lwgsmi_parse_number(&str); /* Get total memory size */ } break; } - default: break; + default: + break; } return 1; } -#endif /* GSM_CFG_SMS || __DOXYGEN__ */ +#endif /* LWGSM_CFG_SMS || __DOXYGEN__ */ -#if GSM_CFG_PHONEBOOK || __DOXYGEN__ +#if LWGSM_CFG_PHONEBOOK || __DOXYGEN__ /** * \brief Parse +CPBS statement @@ -768,23 +781,23 @@ gsmi_parse_cpms(const char* str, uint8_t opt) { * \return 1 on success, 0 otherwise */ uint8_t -gsmi_parse_cpbs(const char* str, uint8_t opt) { +lwgsmi_parse_cpbs(const char* str, uint8_t opt) { if (*str == '+') { str += 7; } switch (opt) { /* Check expected input string */ case 0: { /* Get list of CPBS options: ("M1","M2","M3",...) */ - return gsmi_parse_memories_string(&str, &gsm.m.pb.mem.mem_available); + return lwgsmi_parse_memories_string(&str, &lwgsm.m.pb.mem.mem_available); } case 1: { /* Received statement of current info: +CPBS: "ME",10,20 */ - gsm.m.pb.mem.current = gsmi_parse_memory(&str); /* Parse memory string and save it as current */ - gsm.m.pb.mem.used = gsmi_parse_number(&str);/* Get used memory size */ - gsm.m.pb.mem.total = gsmi_parse_number(&str); /* Get total memory size */ + lwgsm.m.pb.mem.current = lwgsmi_parse_memory(&str); /* Parse memory string and save it as current */ + lwgsm.m.pb.mem.used = lwgsmi_parse_number(&str);/* Get used memory size */ + lwgsm.m.pb.mem.total = lwgsmi_parse_number(&str); /* Get total memory size */ break; } case 2: { /* Received statement of set info: +CPBS: 10,20 */ - gsm.m.pb.mem.used = gsmi_parse_number(&str);/* Get used memory size */ - gsm.m.pb.mem.total = gsmi_parse_number(&str); /* Get total memory size */ + lwgsm.m.pb.mem.used = lwgsmi_parse_number(&str);/* Get used memory size */ + lwgsm.m.pb.mem.total = lwgsmi_parse_number(&str); /* Get total memory size */ break; } } @@ -797,11 +810,11 @@ gsmi_parse_cpbs(const char* str, uint8_t opt) { * \return 1 on success, 0 otherwise */ uint8_t -gsmi_parse_cpbr(const char* str) { - gsm_pb_entry_t* e; +lwgsmi_parse_cpbr(const char* str) { + lwgsm_pb_entry_t* e; - if (!CMD_IS_DEF(GSM_CMD_CPBR) || - gsm.msg->msg.pb_list.ei >= gsm.msg->msg.pb_list.etr) { + if (!CMD_IS_DEF(LWGSM_CMD_CPBR) || + lwgsm.msg->msg.pb_list.ei >= lwgsm.msg->msg.pb_list.etr) { return 0; } @@ -809,15 +822,15 @@ gsmi_parse_cpbr(const char* str) { str += 7; } - e = &gsm.msg->msg.pb_list.entries[gsm.msg->msg.pb_list.ei]; - e->pos = GSM_SZ(gsmi_parse_number(&str)); - gsmi_parse_string(&str, e->name, sizeof(e->name), 1); - e->type = (gsm_number_type_t)gsmi_parse_number(&str); - gsmi_parse_string(&str, e->number, sizeof(e->number), 1); + e = &lwgsm.msg->msg.pb_list.entries[lwgsm.msg->msg.pb_list.ei]; + e->pos = LWGSM_SZ(lwgsmi_parse_number(&str)); + lwgsmi_parse_string(&str, e->name, sizeof(e->name), 1); + e->type = (lwgsm_number_type_t)lwgsmi_parse_number(&str); + lwgsmi_parse_string(&str, e->number, sizeof(e->number), 1); - gsm.msg->msg.pb_list.ei++; - if (gsm.msg->msg.pb_list.er != NULL) { - *gsm.msg->msg.pb_list.er = gsm.msg->msg.pb_list.ei; + ++lwgsm.msg->msg.pb_list.ei; + if (lwgsm.msg->msg.pb_list.er != NULL) { + *lwgsm.msg->msg.pb_list.er = lwgsm.msg->msg.pb_list.ei; } return 1; } @@ -828,11 +841,11 @@ gsmi_parse_cpbr(const char* str) { * \return 1 on success, 0 otherwise */ uint8_t -gsmi_parse_cpbf(const char* str) { - gsm_pb_entry_t* e; +lwgsmi_parse_cpbf(const char* str) { + lwgsm_pb_entry_t* e; - if (!CMD_IS_DEF(GSM_CMD_CPBF) || - gsm.msg->msg.pb_search.ei >= gsm.msg->msg.pb_search.etr) { + if (!CMD_IS_DEF(LWGSM_CMD_CPBF) || + lwgsm.msg->msg.pb_search.ei >= lwgsm.msg->msg.pb_search.etr) { return 0; } @@ -840,22 +853,22 @@ gsmi_parse_cpbf(const char* str) { str += 7; } - e = &gsm.msg->msg.pb_search.entries[gsm.msg->msg.pb_search.ei]; - e->pos = GSM_SZ(gsmi_parse_number(&str)); - gsmi_parse_string(&str, e->name, sizeof(e->name), 1); - e->type = (gsm_number_type_t)gsmi_parse_number(&str); - gsmi_parse_string(&str, e->number, sizeof(e->number), 1); + e = &lwgsm.msg->msg.pb_search.entries[lwgsm.msg->msg.pb_search.ei]; + e->pos = LWGSM_SZ(lwgsmi_parse_number(&str)); + lwgsmi_parse_string(&str, e->name, sizeof(e->name), 1); + e->type = (lwgsm_number_type_t)lwgsmi_parse_number(&str); + lwgsmi_parse_string(&str, e->number, sizeof(e->number), 1); - gsm.msg->msg.pb_search.ei++; - if (gsm.msg->msg.pb_search.er != NULL) { - *gsm.msg->msg.pb_search.er = gsm.msg->msg.pb_search.ei; + ++lwgsm.msg->msg.pb_search.ei; + if (lwgsm.msg->msg.pb_search.er != NULL) { + *lwgsm.msg->msg.pb_search.er = lwgsm.msg->msg.pb_search.ei; } return 1; } -#endif /* GSM_CFG_PHONEBOOK || __DOXYGEN__ */ +#endif /* LWGSM_CFG_PHONEBOOK || __DOXYGEN__ */ -#if GSM_CFG_CONN +#if LWGSM_CFG_CONN /** * \brief Parse connection info line from CIPSTATUS command @@ -865,9 +878,9 @@ gsmi_parse_cpbf(const char* str) { * \return `1` on success, `0` otherwise */ uint8_t -gsmi_parse_cipstatus_conn(const char* str, uint8_t is_conn_line, uint8_t* continueScan) { +lwgsmi_parse_cipstatus_conn(const char* str, uint8_t is_conn_line, uint8_t* continueScan) { uint8_t num; - gsm_conn_t* conn; + lwgsm_conn_t* conn; char s_tmp[16]; uint8_t tmp_pdp_state; @@ -886,34 +899,34 @@ gsmi_parse_cipstatus_conn(const char* str, uint8_t is_conn_line, uint8_t* contin } /* Check if we have to update status for application */ - if (gsm.m.network.is_attached != tmp_pdp_state) { - gsm.m.network.is_attached = tmp_pdp_state; + if (lwgsm.m.network.is_attached != tmp_pdp_state) { + lwgsm.m.network.is_attached = tmp_pdp_state; /* Notify upper layer */ - gsmi_send_cb(gsm.m.network.is_attached ? GSM_EVT_NETWORK_ATTACHED : GSM_EVT_NETWORK_DETACHED); + lwgsmi_send_cb(lwgsm.m.network.is_attached ? LWGSM_EVT_NETWORK_ATTACHED : LWGSM_EVT_NETWORK_DETACHED); } return 1; } /* Parse connection line */ - num = GSM_U8(gsmi_parse_number(&str)); - conn = &gsm.m.conns[num]; + num = LWGSM_U8(lwgsmi_parse_number(&str)); + conn = &lwgsm.m.conns[num]; - conn->status.f.bearer = GSM_U8(gsmi_parse_number(&str)); - gsmi_parse_string(&str, s_tmp, sizeof(s_tmp), 1); /* Parse TCP/UPD */ + conn->status.f.bearer = LWGSM_U8(lwgsmi_parse_number(&str)); + lwgsmi_parse_string(&str, s_tmp, sizeof(s_tmp), 1); /* Parse TCP/UPD */ if (strlen(s_tmp)) { if (!strcmp(s_tmp, "TCP")) { - conn->type = GSM_CONN_TYPE_TCP; + conn->type = LWGSM_CONN_TYPE_TCP; } else if (!strcmp(s_tmp, "UDP")) { - conn->type = GSM_CONN_TYPE_UDP; + conn->type = LWGSM_CONN_TYPE_UDP; } } - gsmi_parse_ip(&str, &conn->remote_ip); - conn->remote_port = gsmi_parse_number(&str); + lwgsmi_parse_ip(&str, &conn->remote_ip); + conn->remote_port = lwgsmi_parse_number(&str); /* Get connection status */ - gsmi_parse_string(&str, s_tmp, sizeof(s_tmp), 1); + lwgsmi_parse_string(&str, s_tmp, sizeof(s_tmp), 1); /* TODO: Implement all connection states */ if (!strcmp(s_tmp, "INITIAL")) { @@ -928,12 +941,12 @@ gsmi_parse_cipstatus_conn(const char* str, uint8_t is_conn_line, uint8_t* contin } else if (!strcmp(s_tmp, "CLOSED")) { /* Connection closed */ if (conn->status.f.active) { /* Check if connection is not */ - gsmi_conn_closed_process(conn->num, 0); /* Process closed event */ + lwgsmi_conn_closed_process(conn->num, 0); /* Process closed event */ } } /* Save last parsed connection */ - gsm.m.active_conns_cur_parse_num = num; + lwgsm.m.active_conns_cur_parse_num = num; return 1; } @@ -944,13 +957,13 @@ gsmi_parse_cipstatus_conn(const char* str, uint8_t is_conn_line, uint8_t* contin * \return `1` on success, `0` otherwise */ uint8_t -gsmi_parse_ipd(const char* str) { +lwgsmi_parse_ipd(const char* str) { uint8_t conn; size_t len; - gsm_conn_p c; + lwgsm_conn_p c; if (*str == '+') { - str++; + ++str; if (*str == 'R') { str += 8; /* Advance for RECEIVE */ } else { @@ -958,20 +971,20 @@ gsmi_parse_ipd(const char* str) { } } - conn = gsmi_parse_number(&str); /* Parse number for connection number */ - len = gsmi_parse_number(&str); /* Parse number for number of bytes to read */ + conn = lwgsmi_parse_number(&str); /* Parse number for connection number */ + len = lwgsmi_parse_number(&str); /* Parse number for number of bytes to read */ - c = conn < GSM_CFG_MAX_CONNS ? &gsm.m.conns[conn] : NULL; /* Get connection handle */ + c = conn < LWGSM_CFG_MAX_CONNS ? &lwgsm.m.conns[conn] : NULL; /* Get connection handle */ if (c == NULL) { /* Invalid connection number */ return 0; } - gsm.m.ipd.read = 1; /* Start reading network data */ - gsm.m.ipd.tot_len = len; /* Total number of bytes in this received packet */ - gsm.m.ipd.rem_len = len; /* Number of remaining bytes to read */ - gsm.m.ipd.conn = c; /* Pointer to connection we have data for */ + lwgsm.m.ipd.read = 1; /* Start reading network data */ + lwgsm.m.ipd.tot_len = len; /* Total number of bytes in this received packet */ + lwgsm.m.ipd.rem_len = len; /* Number of remaining bytes to read */ + lwgsm.m.ipd.conn = c; /* Pointer to connection we have data for */ return 1; } -#endif /* GSM_CFG_CONN */ +#endif /* LWGSM_CFG_CONN */ diff --git a/gsm_at_lib/src/gsm/gsm_pbuf.c b/lwgsm/src/lwgsm/lwgsm_pbuf.c similarity index 69% rename from gsm_at_lib/src/gsm/gsm_pbuf.c rename to lwgsm/src/lwgsm/lwgsm_pbuf.c index 79b0782d..79367b21 100644 --- a/gsm_at_lib/src/gsm/gsm_pbuf.c +++ b/lwgsm/src/lwgsm/lwgsm_pbuf.c @@ -1,10 +1,10 @@ /** - * \file gsm_pbuf.c + * \file lwgsm_pbuf.c * \brief Packet buffer manager */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,17 +26,17 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_pbuf.h" -#include "gsm/gsm_mem.h" +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_pbuf.h" +#include "lwgsm/lwgsm_mem.h" /* Set size of pbuf structure */ -#define SIZEOF_PBUF_STRUCT GSM_MEM_ALIGN(sizeof(gsm_pbuf_t)) +#define SIZEOF_PBUF_STRUCT LWGSM_MEM_ALIGN(sizeof(lwgsm_pbuf_t)) #define SET_NEW_LEN(v, len) do { if ((v) != NULL) { *(v) = (len); } } while (0) /** @@ -46,8 +46,8 @@ * \param[out] new_off: New offset on new returned pbuf * \return New pbuf where offset was found, `NULL` if offset too big for pbuf chain */ -static gsm_pbuf_p -pbuf_skip(gsm_pbuf_p p, size_t off, size_t* new_off) { +static lwgsm_pbuf_p +pbuf_skip(lwgsm_pbuf_p p, size_t off, size_t* new_off) { if (p == NULL || p->tot_len < off) { /* Check valid parameters */ SET_NEW_LEN(new_off, 0); /* Set output value */ return NULL; @@ -67,20 +67,20 @@ pbuf_skip(gsm_pbuf_p p, size_t off, size_t* new_off) { * \param[in] len: Length of payload memory to allocate * \return Pointer to allocated memory, `NULL` otherwise */ -gsm_pbuf_p -gsm_pbuf_new(size_t len) { - gsm_pbuf_p p; - - p = gsm_mem_malloc(SIZEOF_PBUF_STRUCT + sizeof(*p->payload) * len); - GSM_DEBUGW(GSM_CFG_DBG_PBUF | GSM_DBG_TYPE_TRACE, p == NULL, - "[PBUF] Failed to allocate %d bytes\r\n", (int)len); - GSM_DEBUGW(GSM_CFG_DBG_PBUF | GSM_DBG_TYPE_TRACE, p != NULL, - "[PBUF] Allocated %d bytes on %p\r\n", (int)len, p); +lwgsm_pbuf_p +lwgsm_pbuf_new(size_t len) { + lwgsm_pbuf_p p; + + p = lwgsm_mem_malloc(SIZEOF_PBUF_STRUCT + sizeof(*p->payload) * len); + LWGSM_DEBUGW(LWGSM_CFG_DBG_PBUF | LWGSM_DBG_TYPE_TRACE, p == NULL, + "[PBUF] Failed to allocate %d bytes\r\n", (int)len); + LWGSM_DEBUGW(LWGSM_CFG_DBG_PBUF | LWGSM_DBG_TYPE_TRACE, p != NULL, + "[PBUF] Allocated %d bytes on %p\r\n", (int)len, p); if (p != NULL) { p->next = NULL; /* No next element in chain */ p->tot_len = len; /* Set total length of pbuf chain */ p->len = len; /* Set payload length */ - p->payload = (void *)(((char *)p) + SIZEOF_PBUF_STRUCT);/* Set pointer to payload data */ + p->payload = (void*)(((char*)p) + SIZEOF_PBUF_STRUCT); /* Set pointer to payload data */ p->ref = 1; /* Single reference is used on this pbuf */ } return p; @@ -92,11 +92,11 @@ gsm_pbuf_new(size_t len) { * \return Number of freed pbufs from head */ size_t -gsm_pbuf_free(gsm_pbuf_p pbuf) { - gsm_pbuf_p p, pn; +lwgsm_pbuf_free(lwgsm_pbuf_p pbuf) { + lwgsm_pbuf_p p, pn; size_t ref, cnt; - GSM_ASSERT("pbuf != NULL", pbuf != NULL); + LWGSM_ASSERT("pbuf != NULL", pbuf != NULL); /* * Free all pbufs until first ->ref > 1 is reached @@ -104,16 +104,16 @@ gsm_pbuf_free(gsm_pbuf_p pbuf) { */ cnt = 0; for (p = pbuf; p != NULL;) { - gsm_core_lock(); + lwgsm_core_lock(); ref = --p->ref; /* Decrease current value and save it */ - gsm_core_unlock(); + lwgsm_core_unlock(); if (ref == 0) { /* Did we reach 0 and are ready to free it? */ - GSM_DEBUGF(GSM_CFG_DBG_PBUF | GSM_DBG_TYPE_TRACE, - "[PBUF] Deallocating %p with len/tot_len: %d/%d\r\n", p, (int)p->len, (int)p->tot_len); + LWGSM_DEBUGF(LWGSM_CFG_DBG_PBUF | LWGSM_DBG_TYPE_TRACE, + "[PBUF] Deallocating %p with len/tot_len: %d/%d\r\n", p, (int)p->len, (int)p->tot_len); pn = p->next; /* Save next entry */ - gsm_mem_free_s((void **)&p); /* Free memory for pbuf */ + lwgsm_mem_free_s((void**)&p); /* Free memory for pbuf */ p = pn; /* Restore with next entry */ - cnt++; /* Increase number of freed pbufs */ + ++cnt; /* Increase number of freed pbufs */ } else { break; } @@ -124,18 +124,18 @@ gsm_pbuf_free(gsm_pbuf_p pbuf) { /** * \brief Concatenate `2` packet buffers together to one big packet * \note After `tail` pbuf has been added to `head` pbuf chain, - * it must not be referenced by user anymore as it is now completelly controlled by `head` pbuf. - * In simple words, when user calls this function, it should not call \ref gsm_pbuf_free function anymore, + * it must not be referenced by user anymore as it is now completely controlled by `head` pbuf. + * In simple words, when user calls this function, it should not call \ref lwgsm_pbuf_free function anymore, * as it might make memory undefined for `head` pbuf. * \param[in] head: Head packet buffer to append new pbuf to * \param[in] tail: Tail packet buffer to append to head pbuf - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - * \sa gsm_pbuf_chain + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + * \sa lwgsm_pbuf_chain */ -gsmr_t -gsm_pbuf_cat(gsm_pbuf_p head, const gsm_pbuf_p tail) { - GSM_ASSERT("head != NULL", head != NULL); - GSM_ASSERT("tail != NULL", tail != NULL); +lwgsmr_t +lwgsm_pbuf_cat(lwgsm_pbuf_p head, const lwgsm_pbuf_p tail) { + LWGSM_ASSERT("head != NULL", head != NULL); + LWGSM_ASSERT("tail != NULL", tail != NULL); /* * For all pbuf packets in head, @@ -147,30 +147,30 @@ gsm_pbuf_cat(gsm_pbuf_p head, const gsm_pbuf_p tail) { head->tot_len += tail->tot_len; /* Increase total length of last packet in chain */ head->next = tail; /* Set next packet buffer as next one */ - return gsmOK; + return lwgsmOK; } /** - * \brief Chain 2 pbufs together. Similar to \ref gsm_pbuf_cat + * \brief Chain 2 pbufs together. Similar to \ref lwgsm_pbuf_cat * but now new reference is done from head pbuf to tail pbuf. - * \note After this function call, user must call \ref gsm_pbuf_free to remove - * its reference to tail pbuf and allow control to head pbuf: gsm_pbuf_free(tail) + * \note After this function call, user must call \ref lwgsm_pbuf_free to remove + * its reference to tail pbuf and allow control to head pbuf: `lwgsm_pbuf_free(tail)` * \param[in] head: Head packet buffer to append new pbuf to * \param[in] tail: Tail packet buffer to append to head pbuf - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise - * \sa gsm_pbuf_cat + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + * \sa lwgsm_pbuf_cat */ -gsmr_t -gsm_pbuf_chain(gsm_pbuf_p head, gsm_pbuf_p tail) { - gsmr_t res; +lwgsmr_t +lwgsm_pbuf_chain(lwgsm_pbuf_p head, lwgsm_pbuf_p tail) { + lwgsmr_t res; /* * To prevent issues with multi-thread access, * first reference pbuf and increase counter */ - gsm_pbuf_ref(tail); /* Reference tail pbuf by head pbuf now */ - if ((res = gsm_pbuf_cat(head, tail)) != gsmOK) { /* Did we contencate them together successfully? */ - gsm_pbuf_free(tail); /* Call free to decrease reference counter */ + lwgsm_pbuf_ref(tail); /* Reference tail pbuf by head pbuf now */ + if ((res = lwgsm_pbuf_cat(head, tail)) != lwgsmOK) {/* Did we concatenate them together successfully? */ + lwgsm_pbuf_free(tail); /* Call free to decrease reference counter */ } return res; } @@ -178,14 +178,15 @@ gsm_pbuf_chain(gsm_pbuf_p head, gsm_pbuf_p tail) { /** * \brief Unchain first pbuf from list and return second one * - * `tot_len` and `len` fields are adjusted to reflect new values and reference counter is as is + * `tot_len` and `len` fields are adjusted to reflect new values and reference counter is `as is` + * * \note After unchain, user must take care of both pbufs (`head` and `new returned one`) * \param[in] head: First pbuf in chain to remove from chain * \return Next pbuf after `head` */ -gsm_pbuf_p -gsm_pbuf_unchain(gsm_pbuf_p head) { - gsm_pbuf_p r = NULL; +lwgsm_pbuf_p +lwgsm_pbuf_unchain(lwgsm_pbuf_p head) { + lwgsm_pbuf_p r = NULL; if (head != NULL && head->next != NULL) { /* Check for valid pbuf */ r = head->next; /* Set return value as next pbuf */ @@ -198,14 +199,14 @@ gsm_pbuf_unchain(gsm_pbuf_p head) { /** * \brief Increment reference count on pbuf * \param[in] pbuf: pbuf to increase reference - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_pbuf_ref(gsm_pbuf_p pbuf) { - GSM_ASSERT("pbuf != NULL", pbuf != NULL); +lwgsmr_t +lwgsm_pbuf_ref(lwgsm_pbuf_p pbuf) { + LWGSM_ASSERT("pbuf != NULL", pbuf != NULL); - pbuf->ref++; /* Increase reference count for pbuf */ - return gsmOK; + ++pbuf->ref; /* Increase reference count for pbuf */ + return lwgsmOK; } /** @@ -214,34 +215,34 @@ gsm_pbuf_ref(gsm_pbuf_p pbuf) { * \param[in] data: Input data to copy to pbuf memory * \param[in] len: Length of input data to copy * \param[in] offset: Start offset in pbuf where to start copying - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_pbuf_take(gsm_pbuf_p pbuf, const void* data, size_t len, size_t offset) { +lwgsmr_t +lwgsm_pbuf_take(lwgsm_pbuf_p pbuf, const void* data, size_t len, size_t offset) { const uint8_t* d = data; size_t copy_len; - GSM_ASSERT("pbuf != NULL", pbuf != NULL); - GSM_ASSERT("data != NULL", data != NULL); - GSM_ASSERT("len > 0", len > 0); - GSM_ASSERT("pbuf->tot_len >= len", pbuf->tot_len >= len); + LWGSM_ASSERT("pbuf != NULL", pbuf != NULL); + LWGSM_ASSERT("data != NULL", data != NULL); + LWGSM_ASSERT("len > 0", len > 0); + LWGSM_ASSERT("pbuf->tot_len >= len", pbuf->tot_len >= len); /* Skip if necessary and check if we are in valid range */ if (offset > 0) { - pbuf = pbuf_skip(pbuf, offset, &offset); /* Offset and check for new length */ + pbuf = pbuf_skip(pbuf, offset, &offset);/* Offset and check for new length */ if (pbuf == NULL) { - return gsmERR; + return lwgsmERR; } } if (pbuf->tot_len < (len + offset)) { - return gsmPARERR; + return lwgsmPARERR; } /* First only copy in case we have some offset from first pbuf */ if (offset > 0) { - copy_len = GSM_MIN(pbuf->len - offset, len); /* Get length to copy to current pbuf */ - GSM_MEMCPY(pbuf->payload + offset, d, copy_len);/* Copy to memory with offset */ + copy_len = LWGSM_MIN(pbuf->len - offset, len); /* Get length to copy to current pbuf */ + LWGSM_MEMCPY(pbuf->payload + offset, d, copy_len); /* Copy to memory with offset */ len -= copy_len; /* Decrease remaining bytes to copy */ d += copy_len; /* Increase data pointer */ pbuf = pbuf->next; /* Go to next pbuf */ @@ -249,12 +250,12 @@ gsm_pbuf_take(gsm_pbuf_p pbuf, const void* data, size_t len, size_t offset) { /* Copy user memory to sequence of pbufs */ for (; len; pbuf = pbuf->next) { - copy_len = GSM_MIN(len, pbuf->len); /* Get copy length */ - GSM_MEMCPY(pbuf->payload, d, copy_len); /* Copy memory to pbuf payload */ + copy_len = LWGSM_MIN(len, pbuf->len); /* Get copy length */ + LWGSM_MEMCPY(pbuf->payload, d, copy_len); /* Copy memory to pbuf payload */ len -= copy_len; /* Decrease number of remaining bytes to send */ d += copy_len; /* Increase data pointer */ } - return gsmOK; + return lwgsmOK; } /** @@ -266,7 +267,7 @@ gsm_pbuf_take(gsm_pbuf_p pbuf, const void* data, size_t len, size_t offset) { * \return Number of bytes copied */ size_t -gsm_pbuf_copy(gsm_pbuf_p pbuf, void* data, size_t len, size_t offset) { +lwgsm_pbuf_copy(lwgsm_pbuf_p pbuf, void* data, size_t len, size_t offset) { size_t tot, tc; uint8_t* d = data; @@ -291,8 +292,8 @@ gsm_pbuf_copy(gsm_pbuf_p pbuf, void* data, size_t len, size_t offset) { */ tot = 0; for (; pbuf != NULL && len; pbuf = pbuf->next) { - tc = GSM_MIN(pbuf->len - offset, len); /* Get length of data to copy */ - GSM_MEMCPY(d, pbuf->payload + offset, tc); /* Copy data from pbuf */ + tc = LWGSM_MIN(pbuf->len - offset, len);/* Get length of data to copy */ + LWGSM_MEMCPY(d, pbuf->payload + offset, tc);/* Copy data from pbuf */ d += tc; len -= tc; tot += tc; @@ -309,8 +310,8 @@ gsm_pbuf_copy(gsm_pbuf_p pbuf, void* data, size_t len, size_t offset) { * \return `1` on success, `0` otherwise */ uint8_t -gsm_pbuf_get_at(const gsm_pbuf_p pbuf, size_t pos, uint8_t* el) { - gsm_pbuf_p p; +lwgsm_pbuf_get_at(const lwgsm_pbuf_p pbuf, size_t pos, uint8_t* el) { + lwgsm_pbuf_p p; if (pbuf != NULL) { p = pbuf_skip(pbuf, pos, &pos); /* Skip pbufs to desired position and get new offset from new pbuf */ @@ -328,23 +329,23 @@ gsm_pbuf_get_at(const gsm_pbuf_p pbuf, size_t pos, uint8_t* el) { * \param[in] needle: Data memory used as needle * \param[in] len: Length of needle memory * \param[in] off: Starting offset in pbuf memory - * \return `GSM_SIZET_MAX` if no match or position where in pbuf we have a match - * \sa gsm_pbuf_strfind + * \return `LWGSM_SIZET_MAX` if no match or position where in pbuf we have a match + * \sa lwgsm_pbuf_strfind */ size_t -gsm_pbuf_memfind(const gsm_pbuf_p pbuf, const void* needle, size_t len, size_t off) { +lwgsm_pbuf_memfind(const lwgsm_pbuf_p pbuf, const void* needle, size_t len, size_t off) { if (pbuf != NULL && needle != NULL && pbuf->tot_len >= (len + off)) { /* Check if valid entries */ /* * Try entire buffer element by element * and in case we have a match, report it */ - for (size_t i = off; i <= pbuf->tot_len - len; i++) { - if (!gsm_pbuf_memcmp(pbuf, needle, len, i)) { /* Check if identical */ + for (size_t i = off; i <= pbuf->tot_len - len; ++i) { + if (!lwgsm_pbuf_memcmp(pbuf, needle, len, i)) { /* Check if identical */ return i; /* We have a match! */ } } } - return GSM_SIZET_MAX; /* Return maximal value of size_t variable to indicate error */ + return LWGSM_SIZET_MAX; /* Return maximal value of size_t variable to indicate error */ } /** @@ -352,12 +353,12 @@ gsm_pbuf_memfind(const gsm_pbuf_p pbuf, const void* needle, size_t len, size_t o * \param[in] pbuf: Pbuf used as haystack * \param[in] str: String to search for in pbuf * \param[in] off: Starting offset in pbuf memory - * \return `GSM_SIZET_MAX` if no match or position where in pbuf we have a match - * \sa gsm_pbuf_memfind + * \return `LWGSM_SIZET_MAX` if no match or position where in pbuf we have a match + * \sa lwgsm_pbuf_memfind */ size_t -gsm_pbuf_strfind(const gsm_pbuf_p pbuf, const char* str, size_t off) { - return gsm_pbuf_memfind(pbuf, str, strlen(str), off); +lwgsm_pbuf_strfind(const lwgsm_pbuf_p pbuf, const char* str, size_t off) { + return lwgsm_pbuf_memfind(pbuf, str, strlen(str), off); } /** @@ -367,18 +368,18 @@ gsm_pbuf_strfind(const gsm_pbuf_p pbuf, const char* str, size_t off) { * \param[in] data: Actual data to compare with * \param[in] len: Length of input data in units of bytes * \param[in] offset: Start offset to use when comparing data - * \return `0` if equal, `GSM_SIZET_MAX` if memory/offset too big or anything between if not equal - * \sa gsm_pbuf_strcmp + * \return `0` if equal, `LWGSM_SIZET_MAX` if memory/offset too big or anything between if not equal + * \sa lwgsm_pbuf_strcmp */ size_t -gsm_pbuf_memcmp(const gsm_pbuf_p pbuf, const void* data, size_t len, size_t offset) { - gsm_pbuf_p p; +lwgsm_pbuf_memcmp(const lwgsm_pbuf_p pbuf, const void* data, size_t len, size_t offset) { + lwgsm_pbuf_p p; uint8_t el; const uint8_t* d = data; - if (pbuf == NULL || data == NULL || len == 0 || /* Input parameters check */ - pbuf->tot_len < (offset + len)) { /* Check of valid ranges */ - return GSM_SIZET_MAX; /* Invalid check here */ + if (pbuf == NULL || data == NULL || len == 0/* Input parameters check */ + || pbuf->tot_len < (offset + len)) { /* Check of valid ranges */ + return LWGSM_SIZET_MAX; /* Invalid check here */ } /* @@ -395,8 +396,8 @@ gsm_pbuf_memcmp(const gsm_pbuf_p pbuf, const void* data, size_t len, size_t offs * * Use byte by byte read function to inspect bytes separatelly */ - for (size_t i = 0; i < len; i++) { - if (!gsm_pbuf_get_at(p, offset + i, &el) || el != d[i]) { /* Get value from pbuf at specific offset */ + for (size_t i = 0; i < len; ++i) { + if (!lwgsm_pbuf_get_at(p, offset + i, &el) || el != d[i]) { /* Get value from pbuf at specific offset */ return offset + 1; /* Return value from offset where it failed */ } } @@ -409,12 +410,12 @@ gsm_pbuf_memcmp(const gsm_pbuf_p pbuf, const void* data, size_t len, size_t offs * \param[in] pbuf: Pbuf used to compare with data memory * \param[in] str: String to be compared with pbuf * \param[in] offset: Start memory offset in pbuf - * \return `0` if equal, `GSM_SIZET_MAX` if memory/offset too big or anything between if not equal - * \sa gsm_pbuf_memcmp + * \return `0` if equal, `LWGSM_SIZET_MAX` if memory/offset too big or anything between if not equal + * \sa lwgsm_pbuf_memcmp */ size_t -gsm_pbuf_strcmp(const gsm_pbuf_p pbuf, const char* str, size_t offset) { - return gsm_pbuf_memcmp(pbuf, str, strlen(str), offset); +lwgsm_pbuf_strcmp(const lwgsm_pbuf_p pbuf, const char* str, size_t offset) { + return lwgsm_pbuf_memcmp(pbuf, str, strlen(str), offset); } /** @@ -426,9 +427,9 @@ gsm_pbuf_strcmp(const gsm_pbuf_p pbuf, const char* str, size_t offset) { * \param[out] new_len: Length of memory returned by function * \return Pointer to memory on success, `NULL` otherwise */ -void * -gsm_pbuf_get_linear_addr(const gsm_pbuf_p pbuf, size_t offset, size_t* new_len) { - gsm_pbuf_p p = pbuf; +void* +lwgsm_pbuf_get_linear_addr(const lwgsm_pbuf_p pbuf, size_t offset, size_t* new_len) { + lwgsm_pbuf_p p = pbuf; if (pbuf == NULL || pbuf->tot_len < offset) { /* Check input parameters */ SET_NEW_LEN(new_len, 0); @@ -451,8 +452,8 @@ gsm_pbuf_get_linear_addr(const gsm_pbuf_p pbuf, size_t offset, size_t* new_len) * \param[in] pbuf: Packet buffer * \return Pointer to data buffer on success, `NULL` otherwise */ -void * -gsm_pbuf_data(const gsm_pbuf_p pbuf) { +void* +lwgsm_pbuf_data(const lwgsm_pbuf_p pbuf) { return pbuf != NULL ? pbuf->payload : NULL; } @@ -463,7 +464,7 @@ gsm_pbuf_data(const gsm_pbuf_p pbuf) { * \return Length of data in units of bytes */ size_t -gsm_pbuf_length(const gsm_pbuf_p pbuf, uint8_t tot) { +lwgsm_pbuf_length(const lwgsm_pbuf_p pbuf, uint8_t tot) { return pbuf != NULL ? (tot ? pbuf->tot_len : pbuf->len) : 0; } @@ -474,9 +475,9 @@ gsm_pbuf_length(const gsm_pbuf_p pbuf, uint8_t tot) { * \param[in] port: Port number to assign to packet buffer */ void -gsm_pbuf_set_ip(gsm_pbuf_p pbuf, const gsm_ip_t* ip, gsm_port_t port) { +lwgsm_pbuf_set_ip(lwgsm_pbuf_p pbuf, const lwgsm_ip_t* ip, lwgsm_port_t port) { if (pbuf != NULL && ip != NULL) { - GSM_MEMCPY(&pbuf->ip, ip, sizeof(*ip)); + LWGSM_MEMCPY(&pbuf->ip, ip, sizeof(*ip)); pbuf->port = port; } } @@ -494,7 +495,7 @@ gsm_pbuf_set_ip(gsm_pbuf_p pbuf, const gsm_ip_t* ip, gsm_port_t port) { * \return `1` on success, `0` otherwise */ uint8_t -gsm_pbuf_advance(gsm_pbuf_p pbuf, int len) { +lwgsm_pbuf_advance(lwgsm_pbuf_p pbuf, int len) { uint8_t process = 0; if (pbuf == NULL || len == 0) { return 0; @@ -505,7 +506,7 @@ gsm_pbuf_advance(gsm_pbuf_p pbuf, int len) { } } else { /* Is current payload + new len still higher than pbuf structure? */ - if (((uint8_t *)pbuf + SIZEOF_PBUF_STRUCT) < (pbuf->payload + len)) { + if (((uint8_t*)pbuf + SIZEOF_PBUF_STRUCT) < (pbuf->payload + len)) { process = 1; } } @@ -525,8 +526,8 @@ gsm_pbuf_advance(gsm_pbuf_p pbuf, int len) { * \param[out] new_offset: Pointer to output variable to save new offset in returned pbuf * \return New pbuf on success, `NULL` otherwise */ -gsm_pbuf_p -gsm_pbuf_skip(gsm_pbuf_p pbuf, size_t offset, size_t* new_offset) { +lwgsm_pbuf_p +lwgsm_pbuf_skip(lwgsm_pbuf_p pbuf, size_t offset, size_t* new_offset) { return pbuf_skip(pbuf, offset, new_offset); /* Skip pbufs with internal function */ } @@ -536,19 +537,19 @@ gsm_pbuf_skip(gsm_pbuf_p pbuf, size_t offset, size_t* new_offset) { * \param[in] seq: Set to `1` to dump all `pbufs` in linked list or `0` to dump first one only */ void -gsm_pbuf_dump(gsm_pbuf_p p, uint8_t seq) { +lwgsm_pbuf_dump(lwgsm_pbuf_p p, uint8_t seq) { if (p != NULL) { - GSM_DEBUGF(GSM_CFG_DBG_PBUF | GSM_DBG_TYPE_TRACE, - "[PBUF] Dump start: %p\r\n", p); + LWGSM_DEBUGF(LWGSM_CFG_DBG_PBUF | LWGSM_DBG_TYPE_TRACE, + "[PBUF] Dump start: %p\r\n", p); for (; p != NULL; p = p->next) { - GSM_DEBUGF(GSM_CFG_DBG_PBUF | GSM_DBG_TYPE_TRACE, - "[PBUF] Dump %p; ref: %d; len: %d; tot_len: %d, next: %p\r\n", - p, (int)p->ref, (int)p->len, (int)p->tot_len, p->next); + LWGSM_DEBUGF(LWGSM_CFG_DBG_PBUF | LWGSM_DBG_TYPE_TRACE, + "[PBUF] Dump %p; ref: %d; len: %d; tot_len: %d, next: %p\r\n", + p, (int)p->ref, (int)p->len, (int)p->tot_len, p->next); if (!seq) { break; } } - GSM_DEBUGF(GSM_CFG_DBG_PBUF | GSM_DBG_TYPE_TRACE, - "[PBUF] Dump end\r\n"); + LWGSM_DEBUGF(LWGSM_CFG_DBG_PBUF | LWGSM_DBG_TYPE_TRACE, + "[PBUF] Dump end\r\n"); } } diff --git a/lwgsm/src/lwgsm/lwgsm_phonebook.c b/lwgsm/src/lwgsm/lwgsm_phonebook.c new file mode 100644 index 00000000..c811fed8 --- /dev/null +++ b/lwgsm/src/lwgsm/lwgsm_phonebook.c @@ -0,0 +1,334 @@ +/** + * \file lwgsm_phonebook.c + * \brief Phonebook API + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_phonebook.h" +#include "lwgsm/lwgsm_mem.h" + +#if LWGSM_CFG_PHONEBOOK || __DOXYGEN__ + +#if !__DOXYGEN__ +#define CHECK_ENABLED() if (!(check_enabled() == lwgsmOK)) { return lwgsmERRNOTENABLED; } +#endif /* !__DOXYGEN__ */ + +/** + * \brief Check if phonebook is enabled + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +static lwgsmr_t +check_enabled(void) { + lwgsmr_t res; + lwgsm_core_lock(); + res = lwgsm.m.pb.enabled ? lwgsmOK : lwgsmERR; + lwgsm_core_unlock(); + return res; +} + +/** + * \brief Check if input memory is available in modem + * \param[in] mem: Memory to test + * \param[in] can_curr: Flag indicates if \ref LWGSM_MEM_CURRENT option can be used + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +static lwgsmr_t +check_mem(lwgsm_mem_t mem, uint8_t can_curr) { + lwgsmr_t res = lwgsmERRMEM; + lwgsm_core_lock(); + if ((mem < LWGSM_MEM_END && lwgsm.m.pb.mem.mem_available & (1 << (uint32_t)mem)) || + (can_curr && mem == LWGSM_MEM_CURRENT)) { + res = lwgsmOK; + } + lwgsm_core_unlock(); + return res; +} + +/** + * \brief Enable phonebook functionality + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_pb_enable(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_PHONEBOOK_ENABLE; + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPBS_GET_OPT; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); +} + +/** + * \brief Disable phonebook functionality + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_pb_disable(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + lwgsm_core_lock(); + lwgsm.m.pb.enabled = 0; + if (evt_fn != NULL) { + evt_fn(lwgsmOK, evt_arg); + } + lwgsm_core_unlock(); + return lwgsmOK; +} + +/** + * \brief Add new phonebook entry to desired memory + * \param[in] mem: Memory to use to save entry. Use \ref LWGSM_MEM_CURRENT to use current memory + * \param[in] name: Entry name + * \param[in] num: Entry phone number + * \param[in] type: Entry phone number type + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_pb_add(lwgsm_mem_t mem, const char* name, const char* num, lwgsm_number_type_t type, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_ASSERT("name != NULL", name != NULL); + LWGSM_ASSERT("num != NULL", num != NULL); + CHECK_ENABLED(); /* Check if enabled */ + LWGSM_ASSERT("check_mem() == lwgsmOK", check_mem(mem, 1) == lwgsmOK); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CPBW_SET; + if (mem == LWGSM_MEM_CURRENT) { /* Should be always false */ + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPBS_GET;/* First get memory */ + } else { + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPBS_SET;/* First set memory */ + } + + LWGSM_MSG_VAR_REF(msg).msg.pb_write.pos = 0; + LWGSM_MSG_VAR_REF(msg).msg.pb_write.mem = mem; + LWGSM_MSG_VAR_REF(msg).msg.pb_write.name = name; + LWGSM_MSG_VAR_REF(msg).msg.pb_write.num = num; + LWGSM_MSG_VAR_REF(msg).msg.pb_write.type = type; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); +} + +/** + * \brief Read single phonebook entry + * \param[in] mem: Memory to use to save entry. Use \ref LWGSM_MEM_CURRENT to use current memory + * \param[in] pos: Entry position in memory to read + * \param[out] entry: Pointer to entry variable to save data + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_pb_read(lwgsm_mem_t mem, size_t pos, lwgsm_pb_entry_t* entry, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + return lwgsm_pb_list(mem, pos, entry, 1, NULL, evt_fn, evt_arg, blocking); +} + +/** + * \brief Edit or overwrite phonebook entry at desired memory and position + * \param[in] mem: Memory to use to save entry. Use \ref LWGSM_MEM_CURRENT to use current memory + * \param[in] pos: Entry position in memory to edit + * \param[in] name: New entry name + * \param[in] num: New entry phone number + * \param[in] type: New entry phone number type + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_pb_edit(lwgsm_mem_t mem, size_t pos, const char* name, const char* num, lwgsm_number_type_t type, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_ASSERT("name != NULL", name != NULL); + LWGSM_ASSERT("num != NULL", num != NULL); + CHECK_ENABLED(); /* Check if enabled */ + LWGSM_ASSERT("check_mem() == mem", check_mem(mem, 1) == lwgsmOK); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CPBW_SET; + if (mem == LWGSM_MEM_CURRENT) { /* Should be always false */ + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPBS_GET;/* First get memory */ + } else { + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPBS_SET;/* First set memory */ + } + + LWGSM_MSG_VAR_REF(msg).msg.pb_write.pos = pos; + LWGSM_MSG_VAR_REF(msg).msg.pb_write.mem = mem; + LWGSM_MSG_VAR_REF(msg).msg.pb_write.name = name; + LWGSM_MSG_VAR_REF(msg).msg.pb_write.num = num; + LWGSM_MSG_VAR_REF(msg).msg.pb_write.type = type; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); +} + +/** + * \brief Delete phonebook entry at desired memory and position + * \param[in] mem: Memory to use to save entry. Use \ref LWGSM_MEM_CURRENT to use current memory + * \param[in] pos: Entry position in memory to delete + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_pb_delete(lwgsm_mem_t mem, size_t pos, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_ASSERT("pos > 0", pos > 0); + CHECK_ENABLED(); /* Check if enabled */ + LWGSM_ASSERT("check_mem() == lwgsmOK", check_mem(mem, 1) == lwgsmOK); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CPBW_SET; + if (mem == LWGSM_MEM_CURRENT) { /* Should be always false */ + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPBS_GET;/* First get memory */ + } else { + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPBS_SET;/* First set memory */ + } + + LWGSM_MSG_VAR_REF(msg).msg.pb_write.mem = mem; + LWGSM_MSG_VAR_REF(msg).msg.pb_write.pos = pos; + LWGSM_MSG_VAR_REF(msg).msg.pb_write.del = 1; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); +} + +/** + * \brief List entires from specific memory + * \param[in] mem: Memory to use to save entry. Use \ref LWGSM_MEM_CURRENT to use current memory + * \param[in] start_index: Start position in memory to list + * \param[out] entries: Pointer to array to save entries + * \param[in] etr: Number of entries to read + * \param[out] er: Pointer to output variable to save entries listed + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_pb_list(lwgsm_mem_t mem, size_t start_index, lwgsm_pb_entry_t* entries, size_t etr, size_t* er, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_ASSERT("start_index", start_index); + LWGSM_ASSERT("entries != NULL", entries != NULL); + LWGSM_ASSERT("etr > 0", etr > 0); + CHECK_ENABLED(); + LWGSM_ASSERT("check_mem() == lwgsmOK", check_mem(mem, 1) == lwgsmOK); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + + if (er != NULL) { + *er = 0; + } + LWGSM_MEMSET(entries, 0x00, sizeof(*entries) * etr);/* Reset data structure */ + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CPBR; + if (mem == LWGSM_MEM_CURRENT) { /* Should be always false */ + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPBS_GET;/* First get memory */ + } else { + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPBS_SET;/* First set memory */ + } + + LWGSM_MSG_VAR_REF(msg).msg.pb_list.mem = mem; + LWGSM_MSG_VAR_REF(msg).msg.pb_list.start_index = start_index; + LWGSM_MSG_VAR_REF(msg).msg.pb_list.entries = entries; + LWGSM_MSG_VAR_REF(msg).msg.pb_list.etr = etr; + LWGSM_MSG_VAR_REF(msg).msg.pb_list.er = er; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); +} + +/** + * \brief Search for entires with specific name from specific memory + * \note Search works by entry name only. Phone number search is not available + * \param[in] mem: Memory to use to save entry. Use \ref LWGSM_MEM_CURRENT to use current memory + * \param[in] search: String to search for + * \param[out] entries: Pointer to array to save entries + * \param[in] etr: Number of entries to read + * \param[out] er: Pointer to output variable to save entries found + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_pb_search(lwgsm_mem_t mem, const char* search, lwgsm_pb_entry_t* entries, size_t etr, size_t* er, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_ASSERT("search != NULL", search != NULL); + LWGSM_ASSERT("entries != NULL", entries != NULL); + LWGSM_ASSERT("etr > 0", etr > 0); + CHECK_ENABLED(); /* Check if enabled */ + LWGSM_ASSERT("check_mem() == mem", check_mem(mem, 1) == lwgsmOK); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + + if (er != NULL) { + *er = 0; + } + LWGSM_MEMSET(entries, 0x00, sizeof(*entries) * etr);/* Reset data structure */ + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CPBF; + if (mem == LWGSM_MEM_CURRENT) { /* Should be always false */ + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPBS_GET;/* First get memory */ + } else { + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPBS_SET;/* First set memory */ + } + + LWGSM_MSG_VAR_REF(msg).msg.pb_search.mem = mem; + LWGSM_MSG_VAR_REF(msg).msg.pb_search.search = search; + LWGSM_MSG_VAR_REF(msg).msg.pb_search.entries = entries; + LWGSM_MSG_VAR_REF(msg).msg.pb_search.etr = etr; + LWGSM_MSG_VAR_REF(msg).msg.pb_search.er = er; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); +} + +#endif /* LWGSM_CFG_PHONEBOOK || __DOXYGEN__ */ diff --git a/gsm_at_lib/src/gsm/gsm_ping.c b/lwgsm/src/lwgsm/lwgsm_ping.c similarity index 78% rename from gsm_at_lib/src/gsm/gsm_ping.c rename to lwgsm/src/lwgsm/lwgsm_ping.c index 9a81f328..f95c0f4b 100644 --- a/gsm_at_lib/src/gsm/gsm_ping.c +++ b/lwgsm/src/lwgsm/lwgsm_ping.c @@ -1,10 +1,10 @@ -/** - * \file gsm_ping.c +/** + * \file lwgsm_ping.c * \brief PING API */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,15 +26,15 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_ping.h" -#include "gsm/gsm_mem.h" +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_ping.h" +#include "lwgsm/lwgsm_mem.h" -#if GSM_CFG_PING || __DOXYGEN__ +#if LWGSM_CFG_PING || __DOXYGEN__ -#endif /* GSM_CFG_PING || __DOXYGEN__ */ +#endif /* LWGSM_CFG_PING || __DOXYGEN__ */ diff --git a/lwgsm/src/lwgsm/lwgsm_sim.c b/lwgsm/src/lwgsm/lwgsm_sim.c new file mode 100644 index 00000000..a8712b48 --- /dev/null +++ b/lwgsm/src/lwgsm/lwgsm_sim.c @@ -0,0 +1,174 @@ +/** + * \file lwgsm_sim.c + * \brief SIM API + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_sim.h" +#include "lwgsm/lwgsm_mem.h" + +/** + * \brief Get current cached SIM state from stack + * \note Information is always valid, starting after successful device reset using \ref lwgsm_reset function call + * \return Member of \ref lwgsm_sim_state_t enumeration + */ +lwgsm_sim_state_t +lwgsm_sim_get_current_state(void) { + lwgsm_sim_state_t state; + lwgsm_core_lock(); + state = lwgsm.m.sim.state; + lwgsm_core_unlock(); + return state; +} + +/** + * \brief Enter pin code to unlock SIM + * \param[in] pin: Pin code in string format + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsm_sim_pin_enter(const char* pin, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_ASSERT("pin != NULL", pin != NULL); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CPIN_SET; + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPIN_GET; + LWGSM_MSG_VAR_REF(msg).msg.cpin_enter.pin = pin; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 30000); +} + +/** + * \brief Add pin number to open SIM card + * \note Use this function only if your SIM card doesn't have PIN code. + * If you wish to change current pin, use \ref lwgsm_sim_pin_change instead + * \param[in] pin: Current SIM pin code + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsm_sim_pin_add(const char* pin, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_ASSERT("pin != NULL", pin != NULL); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CPIN_ADD; + LWGSM_MSG_VAR_REF(msg).msg.cpin_add.pin = pin; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 10000); +} + +/** + * \brief Change current pin code + * \param[in] pin: Current pin code + * \param[in] new_pin: New pin code + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsm_sim_pin_change(const char* pin, const char* new_pin, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_ASSERT("pin != NULL", pin != NULL); + LWGSM_ASSERT("new_pin != NULL", new_pin != NULL); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CPIN_CHANGE; + LWGSM_MSG_VAR_REF(msg).msg.cpin_change.current_pin = pin; + LWGSM_MSG_VAR_REF(msg).msg.cpin_change.new_pin = new_pin; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 10000); +} + +/** + * \brief Remove pin code from SIM + * \param[in] pin: Current pin code + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsm_sim_pin_remove(const char* pin, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_ASSERT("pin != NULL", pin != NULL); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CPIN_REMOVE; + LWGSM_MSG_VAR_REF(msg).msg.cpin_remove.pin = pin; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 10000); +} + +/** + * \brief Enter PUK code and new PIN to unlock SIM card + * \param[in] puk: PUK code associated with SIM card + * \param[in] new_pin: New PIN code to use + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsm_sim_puk_enter(const char* puk, const char* new_pin, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_ASSERT("puk != NULL", puk != NULL); + LWGSM_ASSERT("new_pin != NULL", new_pin != NULL); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CPUK_SET; + LWGSM_MSG_VAR_REF(msg).msg.cpuk_enter.puk = puk; + LWGSM_MSG_VAR_REF(msg).msg.cpuk_enter.pin = new_pin; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 10000); +} diff --git a/lwgsm/src/lwgsm/lwgsm_sms.c b/lwgsm/src/lwgsm/lwgsm_sms.c new file mode 100644 index 00000000..41016ee5 --- /dev/null +++ b/lwgsm/src/lwgsm/lwgsm_sms.c @@ -0,0 +1,346 @@ +/** + * \file lwgsm_sms.c + * \brief SMS API + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_sms.h" +#include "lwgsm/lwgsm_mem.h" + +#if LWGSM_CFG_SMS || __DOXYGEN__ + +#define LWGSM_SMS_OPERATION_IDX 0 /*!< Operation index for memory array (read, delete, list) */ +#define LWGSM_SMS_SEND_IDX 1 /*!< Send index for memory array */ +#define LWGSM_SMS_RECEIVE_IDX 2 /*!< Receive index for memory array */ + +#if !__DOXYGEN__ +#define CHECK_ENABLED() if (!(check_enabled() == lwgsmOK)) { return lwgsmERRNOTENABLED; } +#define CHECK_READY() if (!(check_ready() == lwgsmOK)) { return lwgsmERR; } +#endif /* !__DOXYGEN__ */ + +/** + * \brief Check if sms is enabled + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +static lwgsmr_t +check_enabled(void) { + lwgsmr_t res; + lwgsm_core_lock(); + res = lwgsm.m.sms.enabled ? lwgsmOK : lwgsmERR; + lwgsm_core_unlock(); + return res; +} + +/** + * \brief Check if SMS is available + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +static lwgsmr_t +check_ready(void) { + lwgsmr_t res; + lwgsm_core_lock(); + res = lwgsm.m.sms.ready ? lwgsmOK : lwgsmERR; + lwgsm_core_unlock(); + return res; +} + +/** + * \brief Check if input memory is available in modem + * \param[in] mem: Memory to test + * \param[in] can_curr: Flag indicates if \ref LWGSM_MEM_CURRENT option can be used + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +static lwgsmr_t +check_sms_mem(lwgsm_mem_t mem, uint8_t can_curr) { + lwgsmr_t res = lwgsmERRMEM; + lwgsm_core_lock(); + if ((mem < LWGSM_MEM_END && lwgsm.m.sms.mem[LWGSM_SMS_OPERATION_IDX].mem_available & (1 << (uint32_t)mem)) || + (can_curr && mem == LWGSM_MEM_CURRENT)) { + res = lwgsmOK; + } + lwgsm_core_unlock(); + return res; +} + +/** + * \brief Enable SMS functionality + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_sms_enable(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_SMS_ENABLE; + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPMS_GET_OPT; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); +} + +/** + * \brief Disable SMS functionality + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_sms_disable(const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + lwgsm_core_lock(); + lwgsm.m.sms.enabled = 0; + if (evt_fn != NULL) { + evt_fn(lwgsmOK, evt_arg); + } + lwgsm_core_unlock(); + LWGSM_UNUSED(blocking); + return lwgsmOK; +} + +/** + * \brief Send SMS text to phone number + * \param[in] num: String number + * \param[in] text: Text to send. Maximal `160` characters + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_sms_send(const char* num, const char* text, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_ASSERT("num != NULL && num[0] > 0", num != NULL && num[0] > 0); + LWGSM_ASSERT("text != NULL && text[0] > 0 && strlen(text) <= 160", text != NULL && text[0] > 0 && strlen(text) <= 160); + CHECK_ENABLED(); /* Check if enabled */ + CHECK_READY(); /* Check if ready */ + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CMGS; + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CMGF; + LWGSM_MSG_VAR_REF(msg).msg.sms_send.num = num; + LWGSM_MSG_VAR_REF(msg).msg.sms_send.text = text; + LWGSM_MSG_VAR_REF(msg).msg.sms_send.format = 1; /* Send as plain text */ + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); +} + +/** + * \brief Read SMS entry at specific memory and position + * \param[in] mem: Memory used to read message from + * \param[in] pos: Position number in memory to read + * \param[out] entry: Pointer to SMS entry structure to fill data to + * \param[in] update: Flag indicates update. Set to `1` to change `UNREAD` messages to `READ` or `0` to leave as is + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_sms_read(lwgsm_mem_t mem, size_t pos, lwgsm_sms_entry_t* entry, uint8_t update, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_ASSERT("entry != NULL", entry != NULL); + CHECK_ENABLED(); /* Check if enabled */ + CHECK_READY(); /* Check if ready */ + LWGSM_ASSERT("check_sms_mem() == lwgsmOK", check_sms_mem(mem, 1) == lwgsmOK); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + + LWGSM_MEMSET(entry, 0x00, sizeof(*entry)); /* Reset data structure */ + + entry->mem = mem; /* Set memory */ + entry->pos = pos; /* Set device position */ + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CMGR; + if (mem == LWGSM_MEM_CURRENT) { /* Should be always false */ + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPMS_GET;/* First get memory */ + } else { + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPMS_SET;/* First set memory */ + } + LWGSM_MSG_VAR_REF(msg).msg.sms_read.mem = mem; + LWGSM_MSG_VAR_REF(msg).msg.sms_read.pos = pos; + LWGSM_MSG_VAR_REF(msg).msg.sms_read.entry = entry; + LWGSM_MSG_VAR_REF(msg).msg.sms_read.update = update; + LWGSM_MSG_VAR_REF(msg).msg.sms_read.format = 1; /* Send as plain text */ + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); +} + +/** + * \brief Delete SMS entry at specific memory and position + * \param[in] mem: Memory used to read message from + * \param[in] pos: Position number in memory to read + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_sms_delete(lwgsm_mem_t mem, size_t pos, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + CHECK_ENABLED(); /* Check if enabled */ + CHECK_READY(); /* Check if ready */ + LWGSM_ASSERT("check_sms_mem() == lwgsmOK", check_sms_mem(mem, 1) == lwgsmOK); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CMGD; + if (mem == LWGSM_MEM_CURRENT) { /* Should be always false */ + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPMS_GET;/* First get memory */ + } else { + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPMS_SET;/* First set memory */ + } + LWGSM_MSG_VAR_REF(msg).msg.sms_delete.mem = mem; + LWGSM_MSG_VAR_REF(msg).msg.sms_delete.pos = pos; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 1000); +} + +/** + * \brief Delete all SMS entries with specific status + * \param[in] status: SMS status. This parameter can be one of all possible types in \ref lwgsm_sms_status_t enumeration + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_sms_delete_all(lwgsm_sms_status_t status, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + CHECK_ENABLED(); /* Check if enabled */ + CHECK_READY(); /* Check if ready */ + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CMGDA; + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CMGF;/* By default format = 1 */ + LWGSM_MSG_VAR_REF(msg).msg.sms_delete_all.status = status; + + /* This command may take a while */ + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); +} + +/** + * \brief List SMS from SMS memory + * \param[in] mem: Memory to read entries from. Use \ref LWGSM_MEM_CURRENT to read from current memory + * \param[in] stat: SMS status to read, either `read`, `unread`, `sent`, `unsent` or `all` + * \param[out] entries: Pointer to array to save SMS entries + * \param[in] etr: Number of entries to read + * \param[out] er: Pointer to output variable to save number of entries in array + * \param[in] update: Flag indicates update. Set to `1` to change `UNREAD` messages to `READ` or `0` to leave as is + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_sms_list(lwgsm_mem_t mem, lwgsm_sms_status_t stat, lwgsm_sms_entry_t* entries, size_t etr, size_t* er, uint8_t update, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + LWGSM_ASSERT("entires != NULL", entries != NULL); + LWGSM_ASSERT("etr > 0", etr > 0); + CHECK_ENABLED(); /* Check if enabled */ + CHECK_READY(); /* Check if ready */ + LWGSM_ASSERT("check_sms_mem() == lwgsmOK", check_sms_mem(mem, 1) == lwgsmOK); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + + if (er != NULL) { + *er = 0; + } + LWGSM_MEMSET(entries, 0x00, sizeof(*entries) * etr);/* Reset data structure */ + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CMGL; + if (mem == LWGSM_MEM_CURRENT) { /* Should be always false */ + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPMS_GET;/* First get memory */ + } else { + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPMS_SET;/* First set memory */ + } + LWGSM_MSG_VAR_REF(msg).msg.sms_list.mem = mem; + LWGSM_MSG_VAR_REF(msg).msg.sms_list.status = stat; + LWGSM_MSG_VAR_REF(msg).msg.sms_list.entries = entries; + LWGSM_MSG_VAR_REF(msg).msg.sms_list.etr = etr; + LWGSM_MSG_VAR_REF(msg).msg.sms_list.er = er; + LWGSM_MSG_VAR_REF(msg).msg.sms_list.update = update; + LWGSM_MSG_VAR_REF(msg).msg.sms_list.format = 1; /* Send as plain text */ + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); +} + +/** + * \brief Set preferred storage for SMS + * \param[in] mem1: Preferred memory for read/delete SMS operations. Use \ref LWGSM_MEM_CURRENT to keep it as is + * \param[in] mem2: Preferred memory for sent/write SMS operations. Use \ref LWGSM_MEM_CURRENT to keep it as is + * \param[in] mem3: Preferred memory for received SMS entries. Use \ref LWGSM_MEM_CURRENT to keep it as is + * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used + * \param[in] evt_arg: Custom argument for event callback function + * \param[in] blocking: Status whether command should be blocking or not + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +lwgsmr_t +lwgsm_sms_set_preferred_storage(lwgsm_mem_t mem1, lwgsm_mem_t mem2, lwgsm_mem_t mem3, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); + + CHECK_ENABLED(); /* Check if enabled */ + CHECK_READY(); /* Check if ready */ + LWGSM_ASSERT("check_sms_mem(1) == lwgsmOK", check_sms_mem(mem1, 1) == lwgsmOK); + LWGSM_ASSERT("check_sms_mem(2) == lwgsmOK", check_sms_mem(mem2, 1) == lwgsmOK); + LWGSM_ASSERT("check_sms_mem(3) == lwgsmOK", check_sms_mem(mem3, 1) == lwgsmOK); + + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CPMS_SET; + + /* In case any of memories is set to current, read current status first from device */ + if (mem1 == LWGSM_MEM_CURRENT || mem2 == LWGSM_MEM_CURRENT || mem3 == LWGSM_MEM_CURRENT) { + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CPMS_GET; + } + LWGSM_MSG_VAR_REF(msg).msg.sms_memory.mem[0] = mem1; + LWGSM_MSG_VAR_REF(msg).msg.sms_memory.mem[1] = mem2; + LWGSM_MSG_VAR_REF(msg).msg.sms_memory.mem[2] = mem3; + + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000); +} + +#endif /* LWGSM_CFG_SMS || __DOXYGEN__ */ diff --git a/gsm_at_lib/src/gsm/gsm_threads.c b/lwgsm/src/lwgsm/lwgsm_threads.c similarity index 55% rename from gsm_at_lib/src/gsm/gsm_threads.c rename to lwgsm/src/lwgsm/lwgsm_threads.c index d421c5f3..41d7eaeb 100644 --- a/gsm_at_lib/src/gsm/gsm_threads.c +++ b/lwgsm/src/lwgsm/lwgsm_threads.c @@ -1,10 +1,10 @@ /** - * \file gsm_threads.c + * \file lwgsm_threads.c * \brief OS threads implementations */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,47 +26,47 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_threads.h" -#include "gsm/gsm_parser.h" -#include "gsm/gsm_int.h" -#include "gsm/gsm_timeout.h" -#include "gsm/gsm.h" -#include "gsm/gsm_mem.h" -#include "system/gsm_sys.h" +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_threads.h" +#include "lwgsm/lwgsm_parser.h" +#include "lwgsm/lwgsm_int.h" +#include "lwgsm/lwgsm_timeout.h" +#include "lwgsm/lwgsm.h" +#include "lwgsm/lwgsm_mem.h" +#include "system/lwgsm_sys.h" /** * \brief User thread to process input packets from API functions * \param[in] arg: User argument. Semaphore to release when thread starts */ void -gsm_thread_produce(void* const arg) { - gsm_sys_sem_t* sem = arg; - gsm_t* e = &gsm; - gsm_msg_t* msg; - gsmr_t res; +lwgsm_thread_produce(void* const arg) { + lwgsm_sys_sem_t* sem = arg; + lwgsm_t* e = &lwgsm; + lwgsm_msg_t* msg; + lwgsmr_t res; uint32_t time; /* Thread is running, unlock semaphore */ - if (gsm_sys_sem_isvalid(sem)) { - gsm_sys_sem_release(sem); /* Release semaphore */ + if (lwgsm_sys_sem_isvalid(sem)) { + lwgsm_sys_sem_release(sem); /* Release semaphore */ } - gsm_core_lock(); + lwgsm_core_lock(); while (1) { - gsm_core_unlock(); + lwgsm_core_unlock(); do { - time = gsm_sys_mbox_get(&e->mbox_producer, (void **)&msg, 0); /* Get message from queue */ - } while (time == GSM_SYS_TIMEOUT || msg == NULL); - GSM_THREAD_PRODUCER_HOOK(); /* Execute producer thread hook */ - gsm_core_lock(); + time = lwgsm_sys_mbox_get(&e->mbox_producer, (void**)&msg, 0); /* Get message from queue */ + } while (time == LWGSM_SYS_TIMEOUT || msg == NULL); + LWGSM_THREAD_PRODUCER_HOOK(); /* Execute producer thread hook */ + lwgsm_core_lock(); - res = gsmOK; /* Start with OK */ + res = lwgsmOK; /* Start with OK */ e->msg = msg; /* Set message handle */ /* @@ -75,53 +75,53 @@ gsm_thread_produce(void* const arg) { * if device present flag changes */ if (!e->status.f.dev_present) { - res = gsmERRNODEVICE; + res = lwgsmERRNODEVICE; } /* For reset message, we can have delay! */ - if (res == gsmOK && msg->cmd_def == GSM_CMD_RESET) { + if (res == lwgsmOK && msg->cmd_def == LWGSM_CMD_RESET) { if (msg->msg.reset.delay > 0) { - gsm_delay(msg->msg.reset.delay); + lwgsm_delay(msg->msg.reset.delay); } - gsmi_reset_everything(1); /* Reset stack before trying to reset */ + lwgsmi_reset_everything(1); /* Reset stack before trying to reset */ } /* * Try to call function to process this message * Usually it should be function to transmit data to AT port */ - if (res == gsmOK && msg->fn != NULL) { /* Check for callback processing function */ - /* - * Obtain semaphore + if (res == lwgsmOK && msg->fn != NULL) {/* Check for callback processing function */ + /* + * Obtain semaphore * This code should not block at any point. - * If it blocks, severe problems occurred and program should + * If it blocks, severe problems occurred and program should * immediate terminate */ - gsm_core_unlock(); - gsm_sys_sem_wait(&e->sem_sync, 0); /* First call */ - gsm_core_lock(); + lwgsm_core_unlock(); + lwgsm_sys_sem_wait(&e->sem_sync, 0);/* First call */ + lwgsm_core_lock(); res = msg->fn(msg); /* Process this message, check if command started at least */ - time = ~GSM_SYS_TIMEOUT; /* Reset time */ - if (res == gsmOK) { /* We have valid data and data were sent */ - gsm_core_unlock(); - time = gsm_sys_sem_wait(&e->sem_sync, msg->block_time); /* Second call; Wait for synchronization semaphore from processing thread or timeout */ - gsm_core_lock(); - if (time == GSM_SYS_TIMEOUT) { /* Sync timeout occurred? */ - res = gsmTIMEOUT; /* Timeout on command */ + time = ~LWGSM_SYS_TIMEOUT; /* Reset time */ + if (res == lwgsmOK) { /* We have valid data and data were sent */ + lwgsm_core_unlock(); + time = lwgsm_sys_sem_wait(&e->sem_sync, msg->block_time); /* Second call; Wait for synchronization semaphore from processing thread or timeout */ + lwgsm_core_lock(); + if (time == LWGSM_SYS_TIMEOUT) {/* Sync timeout occurred? */ + res = lwgsmTIMEOUT; /* Timeout on command */ } } /* Notify application on command timeout */ - if (res == gsmTIMEOUT) { - gsmi_send_cb(GSM_EVT_CMD_TIMEOUT); + if (res == lwgsmTIMEOUT) { + lwgsmi_send_cb(LWGSM_EVT_CMD_TIMEOUT); } - GSM_DEBUGW(GSM_CFG_DBG_THREAD | GSM_DBG_TYPE_TRACE | GSM_DBG_LVL_SEVERE, - res == gsmTIMEOUT, - "[THREAD] Timeout in produce thread waiting for command to finish in process thread\r\n"); - GSM_DEBUGW(GSM_CFG_DBG_THREAD | GSM_DBG_TYPE_TRACE | GSM_DBG_LVL_SEVERE, - res != gsmOK && res != gsmTIMEOUT, - "[THREAD] Could not start execution for command %d\r\n", (int)msg->cmd); + LWGSM_DEBUGW(LWGSM_CFG_DBG_THREAD | LWGSM_DBG_TYPE_TRACE | LWGSM_DBG_LVL_SEVERE, + res == lwgsmTIMEOUT, + "[THREAD] Timeout in produce thread waiting for command to finish in process thread\r\n"); + LWGSM_DEBUGW(LWGSM_CFG_DBG_THREAD | LWGSM_DBG_TYPE_TRACE | LWGSM_DBG_LVL_SEVERE, + res != lwgsmOK && res != lwgsmTIMEOUT, + "[THREAD] Could not start execution for command %d\r\n", (int)msg->cmd); /* * Manually release semaphore in all cases: @@ -139,25 +139,25 @@ gsm_thread_produce(void* const arg) { * it would not be possible to start a new command after, * because semaphore would be still locked */ - gsm_sys_sem_release(&e->sem_sync); + lwgsm_sys_sem_release(&e->sem_sync); } else { - if (res == gsmOK) { - res = gsmERR; /* Simply set error message */ + if (res == lwgsmOK) { + res = lwgsmERR; /* Simply set error message */ } } - if (res != gsmOK) { + if (res != lwgsmOK) { /* Process global callbacks */ - gsmi_process_events_for_timeout_or_error(msg, res); + lwgsmi_process_events_for_timeout_or_error(msg, res); msg->res = res; /* Save response */ } -#if GSM_CFG_USE_API_FUNC_EVT +#if LWGSM_CFG_USE_API_FUNC_EVT /* Send event function to user */ if (msg->evt_fn != NULL) { msg->evt_fn(msg->res, msg->evt_arg);/* Send event with user argument */ } -#endif /* GSM_CFG_USE_API_FUNC_EVT */ +#endif /* LWGSM_CFG_USE_API_FUNC_EVT */ /* * In case message is blocking, @@ -165,9 +165,9 @@ gsm_thread_produce(void* const arg) { * otherwise directly free memory of message structure */ if (msg->is_blocking) { - gsm_sys_sem_release(&msg->sem); + lwgsm_sys_sem_release(&msg->sem); } else { - GSM_MSG_VAR_FREE(msg); + LWGSM_MSG_VAR_FREE(msg); } e->msg = NULL; } @@ -180,33 +180,33 @@ gsm_thread_produce(void* const arg) { * in correct time order as it is never blocked by user command * * \param[in] arg: User argument. Semaphore to release when thread starts - * \sa GSM_CFG_INPUT_USE_PROCESS + * \sa LWGSM_CFG_INPUT_USE_PROCESS */ void -gsm_thread_process(void* const arg) { - gsm_sys_sem_t* sem = arg; - gsm_t* e = &gsm; - gsm_msg_t* msg; +lwgsm_thread_process(void* const arg) { + lwgsm_sys_sem_t* sem = arg; + lwgsm_t* e = &lwgsm; + lwgsm_msg_t* msg; uint32_t time; /* Thread is running, unlock semaphore */ - if (gsm_sys_sem_isvalid(sem)) { - gsm_sys_sem_release(sem); /* Release semaphore */ + if (lwgsm_sys_sem_isvalid(sem)) { + lwgsm_sys_sem_release(sem); /* Release semaphore */ } -#if !GSM_CFG_INPUT_USE_PROCESS - gsm_core_lock(); +#if !LWGSM_CFG_INPUT_USE_PROCESS + lwgsm_core_lock(); while (1) { - gsm_core_unlock(); - time = gsmi_get_from_mbox_with_timeout_checks(&e->mbox_process, (void **)&msg, 10); - GSM_THREAD_PROCESS_HOOK(); /* Execute process thread hook */ - gsm_core_lock(); + lwgsm_core_unlock(); + time = lwgsmi_get_from_mbox_with_timeout_checks(&e->mbox_process, (void**)&msg, 10); + LWGSM_THREAD_PROCESS_HOOK(); /* Execute process thread hook */ + lwgsm_core_lock(); - if (time == GSM_SYS_TIMEOUT || msg == NULL) { - GSM_UNUSED(time); /* Unused variable */ + if (time == LWGSM_SYS_TIMEOUT || msg == NULL) { + LWGSM_UNUSED(time); /* Unused variable */ } - gsmi_process_buffer(); /* Process input data */ -#else /* GSM_CFG_INPUT_USE_PROCESS */ + lwgsmi_process_buffer(); /* Process input data */ +#else /* LWGSM_CFG_INPUT_USE_PROCESS */ while (1) { /* * Check for next timeout event only here @@ -214,9 +214,9 @@ gsm_thread_process(void* const arg) { * If there are no timeouts to process, we can wait unlimited time. * In case new timeout occurs, thread will wake up by writing new element to mbox process queue */ - time = gsmi_get_from_mbox_with_timeout_checks(&e->mbox_process, (void **)&msg, 0); - GSM_THREAD_PROCESS_HOOK(); /* Execute process thread hook */ - GSM_UNUSED(time); -#endif /* !GSM_CFG_INPUT_USE_PROCESS */ + time = lwgsmi_get_from_mbox_with_timeout_checks(&e->mbox_process, (void**)&msg, 0); + LWGSM_THREAD_PROCESS_HOOK(); /* Execute process thread hook */ + LWGSM_UNUSED(time); +#endif /* !LWGSM_CFG_INPUT_USE_PROCESS */ } } diff --git a/gsm_at_lib/src/gsm/gsm_timeout.c b/lwgsm/src/lwgsm/lwgsm_timeout.c similarity index 75% rename from gsm_at_lib/src/gsm/gsm_timeout.c rename to lwgsm/src/lwgsm/lwgsm_timeout.c index da13f2e2..b3cedc2c 100644 --- a/gsm_at_lib/src/gsm/gsm_timeout.c +++ b/lwgsm/src/lwgsm/lwgsm_timeout.c @@ -1,10 +1,10 @@ -/** - * \file gsm_timeout.c +/** + * \file lwgsm_timeout.c * \brief Timeout manager */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,16 +26,16 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_timeout.h" -#include "gsm/gsm_mem.h" +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_timeout.h" +#include "lwgsm/lwgsm_mem.h" -static gsm_timeout_t* first_timeout; +static lwgsm_timeout_t* first_timeout; static uint32_t last_timeout_time; /** @@ -48,9 +48,9 @@ get_next_timeout_diff(void) { if (first_timeout == NULL) { return 0xFFFFFFFF; } - diff = gsm_sys_now() - last_timeout_time; /* Get difference between current time and last process time */ + diff = lwgsm_sys_now() - last_timeout_time; /* Get difference between current time and last process time */ if (diff >= first_timeout->time) { /* Are we over already? */ - return 0; /* We have to immediatelly process this timeout */ + return 0; /* We have to immediately process this timeout */ } return first_timeout->time - diff; /* Return remaining time for sleep */ } @@ -62,7 +62,7 @@ static void process_next_timeout(void) { uint32_t time; - time = gsm_sys_now(); + time = lwgsm_sys_now(); /* * Before calling timeout callback, update variable @@ -72,7 +72,7 @@ process_next_timeout(void) { last_timeout_time = time; /* Reset variable when we were last processed */ if (first_timeout != NULL) { - gsm_timeout_t* to = first_timeout; + lwgsm_timeout_t* to = first_timeout; /* * Before calling callback remove current timeout from list @@ -81,7 +81,7 @@ process_next_timeout(void) { */ first_timeout = first_timeout->next; /* Set next timeout on a list as first timeout */ to->fn(to->arg); /* Call user callback function */ - gsm_mem_free_s((void **)&to); + lwgsm_mem_free_s((void**)&to); } } @@ -93,17 +93,17 @@ process_next_timeout(void) { * \return Time in milliseconds required for next message */ uint32_t -gsmi_get_from_mbox_with_timeout_checks(gsm_sys_mbox_t* b, void** m, uint32_t timeout) { +lwgsmi_get_from_mbox_with_timeout_checks(lwgsm_sys_mbox_t* b, void** m, uint32_t timeout) { uint32_t wait_time; do { if (first_timeout == NULL) { /* We have no timeouts ready? */ - return gsm_sys_mbox_get(b, m, timeout); /* Get entry from message queue */ + return lwgsm_sys_mbox_get(b, m, timeout); /* Get entry from message queue */ } wait_time = get_next_timeout_diff(); /* Get time to wait for next timeout execution */ - if (wait_time == 0 || gsm_sys_mbox_get(b, m, wait_time) == GSM_SYS_TIMEOUT) { - gsm_core_lock(); + if (wait_time == 0 || lwgsm_sys_mbox_get(b, m, wait_time) == LWGSM_SYS_TIMEOUT) { + lwgsm_core_lock(); process_next_timeout(); /* Process with next timeout */ - gsm_core_unlock(); + lwgsm_core_unlock(); } break; } while (1); @@ -115,31 +115,30 @@ gsmi_get_from_mbox_with_timeout_checks(gsm_sys_mbox_t* b, void** m, uint32_t tim * \param[in] time: Time in units of milliseconds for timeout execution * \param[in] fn: Callback function to call when timeout expires * \param[in] arg: Pointer to user specific argument to call when timeout callback function is executed - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_timeout_add(uint32_t time, gsm_timeout_fn fn, void* arg) { - gsm_timeout_t* to; - uint32_t now, diff = 0; +lwgsmr_t +lwgsm_timeout_add(uint32_t time, lwgsm_timeout_fn fn, void* arg) { + lwgsm_timeout_t* to; + uint32_t now; - GSM_ASSERT("fn != NULL", fn != NULL); + LWGSM_ASSERT("fn != NULL", fn != NULL); - to = gsm_mem_calloc(1, sizeof(*to)); /* Allocate memory for timeout structure */ + to = lwgsm_mem_calloc(1, sizeof(*to)); /* Allocate memory for timeout structure */ if (to == NULL) { - return gsmERR; + return lwgsmERR; } - gsm_core_lock(); - now = gsm_sys_now(); /* Get current time */ + lwgsm_core_lock(); + now = lwgsm_sys_now(); /* Get current time */ if (first_timeout != NULL) { - diff = now - last_timeout_time; /* Get difference between current and last processed time */ + /* + * Since we want timeout value to start from NOW, + * we have to add time when we last processed our timeouts + */ + time += now - last_timeout_time; /* Add difference between now and last processed time */ } - - /* - * Since we want timeout value to start from NOW, - * we have to add time when we last processed our timeouts - */ - to->time = time + diff; + to->time = time; to->arg = arg; to->fn = fn; @@ -161,7 +160,7 @@ gsm_timeout_add(uint32_t time, gsm_timeout_fn fn, void* arg) { to->next = first_timeout; /* Set first timeout as next of new one */ first_timeout = to; /* Set new timeout as first */ } else { /* Go somewhere in between current list */ - for (gsm_timeout_t* t = first_timeout; t != NULL; t = t->next) { + for (lwgsm_timeout_t* t = first_timeout; t != NULL; t = t->next) { to->time -= t->time; /* Decrease new timeout time by time in a linked list */ /* * Enter between 2 entries on a list in case: @@ -182,23 +181,23 @@ gsm_timeout_add(uint32_t time, gsm_timeout_fn fn, void* arg) { } } } - gsm_core_unlock(); - gsm_sys_mbox_putnow(&gsm.mbox_process, NULL); /* Insert dummy value to wakeup process thread */ - return gsmOK; + lwgsm_core_unlock(); + lwgsm_sys_mbox_putnow(&lwgsm.mbox_process, NULL); /* Insert dummy value to wakeup process thread */ + return lwgsmOK; } /** * \brief Remove callback from timeout list * \param[in] fn: Callback function to identify timeout to remove - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_timeout_remove(gsm_timeout_fn fn) { +lwgsmr_t +lwgsm_timeout_remove(lwgsm_timeout_fn fn) { uint8_t success = 0; - gsm_core_lock(); - for (gsm_timeout_t* t = first_timeout, *t_prev = NULL; t != NULL; - t_prev = t, t = t->next) { /* Check all entries */ + lwgsm_core_lock(); + for (lwgsm_timeout_t* t = first_timeout, *t_prev = NULL; t != NULL; + t_prev = t, t = t->next) { /* Check all entries */ if (t->fn == fn) { /* Do we have a match from callback point of view? */ /* @@ -221,11 +220,11 @@ gsm_timeout_remove(gsm_timeout_fn fn) { } else { first_timeout = t->next; } - gsm_mem_free_s((void **)&t); + lwgsm_mem_free_s((void**)&t); success = 1; break; } } - gsm_core_unlock(); - return success ? gsmOK : gsmERR; + lwgsm_core_unlock(); + return success ? lwgsmOK : lwgsmERR; } diff --git a/gsm_at_lib/src/gsm/gsm_unicode.c b/lwgsm/src/lwgsm/lwgsm_unicode.c similarity index 73% rename from gsm_at_lib/src/gsm/gsm_unicode.c rename to lwgsm/src/lwgsm/lwgsm_unicode.c index b928cf39..3f12b2df 100644 --- a/gsm_at_lib/src/gsm/gsm_unicode.c +++ b/lwgsm/src/lwgsm/lwgsm_unicode.c @@ -1,10 +1,10 @@ -/** - * \file gsm_unicode.c +/** + * \file lwgsm_unicode.c * \brief Unicode support */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,31 +26,31 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_unicode.h" +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_unicode.h" /** * \brief Decode single character for unicode (UTF-8 only) format * \param[in,out] s: Pointer to unicode decode control structure * \param[in] c: UTF-8 character sequence to test for device - * \retval gsmOK: Function succedded, there is a valid UTF-8 sequence - * \retval gsmINPROG: Function continues well but expects some more data to finish sequence - * \retval gsmERR: Error in UTF-8 sequence + * \retval lwgsmOK: Function succedded, there is a valid UTF-8 sequence + * \retval lwgsmINPROG: Function continues well but expects some more data to finish sequence + * \retval lwgsmERR: Error in UTF-8 sequence */ -gsmr_t -gsmi_unicode_decode(gsm_unicode_t* s, uint8_t c) { +lwgsmr_t +lwgsmi_unicode_decode(lwgsm_unicode_t* s, uint8_t c) { if (s->r == 0) { /* Are we expecting a first character? */ s->t = 0; /* Reset sequence */ s->ch[0] = c; /* Save current character */ if (c < 0x80) { /* One byte only in UTF-8 representation */ s->r = 0; /* Remaining bytes */ s->t = 1; - return gsmOK; /* Return OK */ + return lwgsmOK; /* Return OK */ } if ((c & 0xE0) == 0xC0) { /* 1 additional byte in a row = 110x xxxx */ s->r = 1; @@ -59,17 +59,17 @@ gsmi_unicode_decode(gsm_unicode_t* s, uint8_t c) { } else if ((c & 0xF8) == 0xF0) { /* 3 additional bytes in a row = 1111 0xxx */ s->r = 3; } else { - return gsmERR; /* Error parsing unicode byte */ + return lwgsmERR; /* Error parsing unicode byte */ } s->t = s->r + 1; /* Number of bytes is 1 byte more than remaining in sequence */ - return gsmINPROG; /* Return in progress status */ + return lwgsmINPROG; /* Return in progress status */ } else if ((c & 0xC0) == 0x80) { /* Next character in sequence */ - s->r--; /* Decrease character */ + --s->r; /* Decrease character */ s->ch[s->t - s->r - 1] = c; /* Save character to array */ if (s->r == 0) { /* Did we finish? */ - return gsmOK; /* Return OK, we are ready to proceed */ + return lwgsmOK; /* Return OK, we are ready to proceed */ } - return gsmINPROG; /* Still in progress */ + return lwgsmINPROG; /* Still in progress */ } - return gsmERR; /* An error, unknown UTF-8 character entered */ + return lwgsmERR; /* An error, unknown UTF-8 character entered */ } diff --git a/gsm_at_lib/src/gsm/gsm_ussd.c b/lwgsm/src/lwgsm/lwgsm_ussd.c similarity index 58% rename from gsm_at_lib/src/gsm/gsm_ussd.c rename to lwgsm/src/lwgsm/lwgsm_ussd.c index 2113d23d..8ce9afd9 100644 --- a/gsm_at_lib/src/gsm/gsm_ussd.c +++ b/lwgsm/src/lwgsm/lwgsm_ussd.c @@ -1,10 +1,10 @@ -/** - * \file gsm_ussd.c +/** + * \file lwgsm_ussd.c * \brief Unstructured Supplementary Service Data */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,16 +26,16 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_ussd.h" -#include "gsm/gsm_mem.h" +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_ussd.h" +#include "lwgsm/lwgsm_mem.h" -#if GSM_CFG_USSD || __DOXYGEN__ +#if LWGSM_CFG_USSD || __DOXYGEN__ /** * \brief Run USSD command, such as `*123#` to get balance on SIM card @@ -45,26 +45,26 @@ * \param[in] evt_fn: Callback function called when command has finished. Set to `NULL` when not used * \param[in] evt_arg: Custom argument for event callback function * \param[in] blocking: Status whether command should be blocking or not - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_ussd_run(const char* code, char* resp, size_t resp_len, - const gsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { - GSM_MSG_VAR_DEFINE(msg); +lwgsmr_t +lwgsm_ussd_run(const char* code, char* resp, size_t resp_len, + const lwgsm_api_cmd_evt_fn evt_fn, void* const evt_arg, const uint32_t blocking) { + LWGSM_MSG_VAR_DEFINE(msg); - GSM_ASSERT("code != NULL && strlen(code) > 0", code != NULL && strlen(code) > 0); - GSM_ASSERT("resp != NULL", resp != NULL); - GSM_ASSERT("resp_len != NULL", resp_len > 0); + LWGSM_ASSERT("code != NULL && strlen(code) > 0", code != NULL && strlen(code) > 0); + LWGSM_ASSERT("resp != NULL", resp != NULL); + LWGSM_ASSERT("resp_len != NULL", resp_len > 0); - GSM_MSG_VAR_ALLOC(msg, blocking); - GSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); - GSM_MSG_VAR_REF(msg).cmd_def = GSM_CMD_CUSD; - GSM_MSG_VAR_REF(msg).cmd = GSM_CMD_CUSD_GET; - GSM_MSG_VAR_REF(msg).msg.ussd.code = code; - GSM_MSG_VAR_REF(msg).msg.ussd.resp = resp; - GSM_MSG_VAR_REF(msg).msg.ussd.resp_len = resp_len; + LWGSM_MSG_VAR_ALLOC(msg, blocking); + LWGSM_MSG_VAR_SET_EVT(msg, evt_fn, evt_arg); + LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CUSD; + LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CUSD_GET; + LWGSM_MSG_VAR_REF(msg).msg.ussd.code = code; + LWGSM_MSG_VAR_REF(msg).msg.ussd.resp = resp; + LWGSM_MSG_VAR_REF(msg).msg.ussd.resp_len = resp_len; - return gsmi_send_msg_to_producer_mbox(&GSM_MSG_VAR_REF(msg), gsmi_initiate_cmd, 10000); + return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 10000); } -#endif /* GSM_CFG_USSD || __DOXYGEN__ */ +#endif /* LWGSM_CFG_USSD || __DOXYGEN__ */ diff --git a/gsm_at_lib/src/gsm/gsm_utils.c b/lwgsm/src/lwgsm/lwgsm_utils.c similarity index 83% rename from gsm_at_lib/src/gsm/gsm_utils.c rename to lwgsm/src/lwgsm/lwgsm_utils.c index 24207e83..24921d48 100644 --- a/gsm_at_lib/src/gsm/gsm_utils.c +++ b/lwgsm/src/lwgsm/lwgsm_utils.c @@ -1,10 +1,10 @@ /** - * \file gsm_utils.c + * \file lwgsm_utils.c * \brief Utilities */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,14 +26,14 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm_private.h" -#include "gsm/gsm_utils.h" #include +#include "lwgsm/lwgsm_private.h" +#include "lwgsm/lwgsm_utils.h" /** * \brief Convert `unsigned 32-bit` number to string @@ -45,8 +45,8 @@ * This parameter is valid only when formatting hex numbers * \return Pointer to output variable */ -char * -gsm_u32_to_gen_str(uint32_t num, char* out, uint8_t is_hex, uint8_t width) { +char* +lwgsm_u32_to_gen_str(uint32_t num, char* out, uint8_t is_hex, uint8_t width) { char* tmp = out; uint8_t i, y; @@ -54,7 +54,7 @@ gsm_u32_to_gen_str(uint32_t num, char* out, uint8_t is_hex, uint8_t width) { i = 0; tmp[0] = '0'; if (num == 0) { - i++; + ++i; } else { if (is_hex) { uint8_t mod; @@ -66,20 +66,20 @@ gsm_u32_to_gen_str(uint32_t num, char* out, uint8_t is_hex, uint8_t width) { tmp[i] = mod - 10 + 'A'; } num >>= 4; - i++; + ++i; } } else { while (num > 0) { tmp[i] = (num % 10) + '0'; num /= 10; - i++; + ++i; } } } if (is_hex) { while (i < width) { tmp[i] = '0'; - i++; + ++i; } } tmp[i] = 0; @@ -90,7 +90,7 @@ gsm_u32_to_gen_str(uint32_t num, char* out, uint8_t is_hex, uint8_t width) { char t = out[i - y - 1]; out[i - y - 1] = tmp[y]; tmp[y] = t; - y++; + ++y; } out[i] = 0; return out; @@ -102,12 +102,12 @@ gsm_u32_to_gen_str(uint32_t num, char* out, uint8_t is_hex, uint8_t width) { * \param[out] out: Output variable to save string * \return Pointer to output variable */ -char * -gsm_i32_to_gen_str(int32_t num, char* out) { +char* +lwgsm_i32_to_gen_str(int32_t num, char* out) { if (num < 0) { *out++ = '-'; - return gsm_u32_to_gen_str(GSM_U32(-num), out, 0, 0) - 1; + return lwgsm_u32_to_gen_str(LWGSM_U32(-num), out, 0, 0) - 1; } else { - return gsm_u32_to_gen_str(GSM_U32(num), out, 0, 0); + return lwgsm_u32_to_gen_str(LWGSM_U32(num), out, 0, 0); } } diff --git a/lwgsm/src/system/lwgsm_ll_stm32.c b/lwgsm/src/system/lwgsm_ll_stm32.c new file mode 100644 index 00000000..77989288 --- /dev/null +++ b/lwgsm/src/system/lwgsm_ll_stm32.c @@ -0,0 +1,375 @@ +/** + * \file lwgsm_ll_stm32.c + * \brief Generic STM32 driver, included in various STM32 driver variants + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ + +/* + * How it works + * + * On first call to \ref lwgsm_ll_init, new thread is created and processed in usart_ll_thread function. + * USART is configured in RX DMA mode and any incoming bytes are processed inside thread function. + * DMA and USART implement interrupt handlers to notify main thread about new data ready to send to upper layer. + * + * More about UART + RX DMA: https://github.com/MaJerle/stm32-usart-dma-rx-tx + * + * \ref LWGSM_CFG_INPUT_USE_PROCESS must be enabled in `lwgsm_config.h` to use this driver. + */ +#include "lwgsm/lwgsm.h" +#include "lwgsm/lwgsm_mem.h" +#include "lwgsm/lwgsm_input.h" +#include "system/lwgsm_ll.h" + +#if !__DOXYGEN__ + +#if !LWGSM_CFG_INPUT_USE_PROCESS +#error "LWGSM_CFG_INPUT_USE_PROCESS must be enabled in `lwgsm_config.h` to use this driver." +#endif /* LWGSM_CFG_INPUT_USE_PROCESS */ + +#if !defined(LWGSM_USART_DMA_RX_BUFF_SIZE) +#define LWGSM_USART_DMA_RX_BUFF_SIZE 0x1000 +#endif /* !defined(LWGSM_USART_DMA_RX_BUFF_SIZE) */ + +#if !defined(LWGSM_MEM_SIZE) +#define LWGSM_MEM_SIZE 0x1000 +#endif /* !defined(LWGSM_MEM_SIZE) */ + +#if !defined(LWGSM_USART_RDR_NAME) +#define LWGSM_USART_RDR_NAME RDR +#endif /* !defined(LWGSM_USART_RDR_NAME) */ + +/* USART memory */ +static uint8_t usart_mem[LWGSM_USART_DMA_RX_BUFF_SIZE]; +static uint8_t is_running, initialized; +static size_t old_pos; + +/* USART thread */ +static void usart_ll_thread(void* arg); +static osThreadId_t usart_ll_thread_id; + +/* Message queue */ +static osMessageQueueId_t usart_ll_mbox_id; + +/** + * \brief USART data processing + */ +static void +usart_ll_thread(void* arg) { + size_t pos; + + LWGSM_UNUSED(arg); + + while (1) { + void* d; + /* Wait for the event message from DMA or USART */ + osMessageQueueGet(usart_ll_mbox_id, &d, NULL, osWaitForever); + + /* Read data */ +#if defined(LWGSM_USART_DMA_RX_STREAM) + pos = sizeof(usart_mem) - LL_DMA_GetDataLength(LWGSM_USART_DMA, LWGSM_USART_DMA_RX_STREAM); +#else + pos = sizeof(usart_mem) - LL_DMA_GetDataLength(LWGSM_USART_DMA, LWGSM_USART_DMA_RX_CH); +#endif /* defined(LWGSM_USART_DMA_RX_STREAM) */ + if (pos != old_pos && is_running) { + if (pos > old_pos) { + lwgsm_input_process(&usart_mem[old_pos], pos - old_pos); + } else { + lwgsm_input_process(&usart_mem[old_pos], sizeof(usart_mem) - old_pos); + if (pos > 0) { + lwgsm_input_process(&usart_mem[0], pos); + } + } + old_pos = pos; + if (old_pos == sizeof(usart_mem)) { + old_pos = 0; + } + } + } +} + +/** + * \brief Configure UART using DMA for receive in double buffer mode and IDLE line detection + */ +static void +configure_uart(uint32_t baudrate) { + static LL_USART_InitTypeDef usart_init; + static LL_DMA_InitTypeDef dma_init; + LL_GPIO_InitTypeDef gpio_init; + + if (!initialized) { + /* Enable peripheral clocks */ + LWGSM_USART_CLK; + LWGSM_USART_DMA_CLK; + LWGSM_USART_TX_PORT_CLK; + LWGSM_USART_RX_PORT_CLK; + +#if defined(LWGSM_RESET_PIN) + LWGSM_RESET_PORT_CLK; +#endif /* defined(LWGSM_RESET_PIN) */ + + /* Global pin configuration */ + LL_GPIO_StructInit(&gpio_init); + gpio_init.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + gpio_init.Pull = LL_GPIO_PULL_UP; + gpio_init.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + gpio_init.Mode = LL_GPIO_MODE_OUTPUT; + +#if defined(LWGSM_RESET_PIN) + /* Configure RESET pin */ + gpio_init.Pin = LWGSM_RESET_PIN; + LL_GPIO_Init(LWGSM_RESET_PORT, &gpio_init); +#endif /* defined(LWGSM_RESET_PIN) */ + + /* Configure USART pins */ + gpio_init.Mode = LL_GPIO_MODE_ALTERNATE; + + /* TX PIN */ + gpio_init.Alternate = LWGSM_USART_TX_PIN_AF; + gpio_init.Pin = LWGSM_USART_TX_PIN; + LL_GPIO_Init(LWGSM_USART_TX_PORT, &gpio_init); + + /* RX PIN */ + gpio_init.Alternate = LWGSM_USART_RX_PIN_AF; + gpio_init.Pin = LWGSM_USART_RX_PIN; + LL_GPIO_Init(LWGSM_USART_RX_PORT, &gpio_init); + + /* Configure UART */ + LL_USART_DeInit(LWGSM_USART); + LL_USART_StructInit(&usart_init); + usart_init.BaudRate = baudrate; + usart_init.DataWidth = LL_USART_DATAWIDTH_8B; + usart_init.HardwareFlowControl = LL_USART_HWCONTROL_NONE; + usart_init.OverSampling = LL_USART_OVERSAMPLING_16; + usart_init.Parity = LL_USART_PARITY_NONE; + usart_init.StopBits = LL_USART_STOPBITS_1; + usart_init.TransferDirection = LL_USART_DIRECTION_TX_RX; + LL_USART_Init(LWGSM_USART, &usart_init); + + /* Enable USART interrupts and DMA request */ + LL_USART_EnableIT_IDLE(LWGSM_USART); + LL_USART_EnableIT_PE(LWGSM_USART); + LL_USART_EnableIT_ERROR(LWGSM_USART); + LL_USART_EnableDMAReq_RX(LWGSM_USART); + + /* Enable USART interrupts */ + NVIC_SetPriority(LWGSM_USART_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x07, 0x00)); + NVIC_EnableIRQ(LWGSM_USART_IRQ); + + /* Configure DMA */ + is_running = 0; +#if defined(LWGSM_USART_DMA_RX_STREAM) + LL_DMA_DeInit(LWGSM_USART_DMA, LWGSM_USART_DMA_RX_STREAM); + dma_init.Channel = LWGSM_USART_DMA_RX_CH; +#else + LL_DMA_DeInit(LWGSM_USART_DMA, LWGSM_USART_DMA_RX_CH); + dma_init.PeriphRequest = LWGSM_USART_DMA_RX_REQ_NUM; +#endif /* defined(LWGSM_USART_DMA_RX_STREAM) */ + dma_init.PeriphOrM2MSrcAddress = (uint32_t)&LWGSM_USART->LWGSM_USART_RDR_NAME; + dma_init.MemoryOrM2MDstAddress = (uint32_t)usart_mem; + dma_init.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY; + dma_init.Mode = LL_DMA_MODE_CIRCULAR; + dma_init.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; + dma_init.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; + dma_init.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE; + dma_init.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE; + dma_init.NbData = sizeof(usart_mem); + dma_init.Priority = LL_DMA_PRIORITY_MEDIUM; +#if defined(LWGSM_USART_DMA_RX_STREAM) + LL_DMA_Init(LWGSM_USART_DMA, LWGSM_USART_DMA_RX_STREAM, &dma_init); +#else + LL_DMA_Init(LWGSM_USART_DMA, LWGSM_USART_DMA_RX_CH, &dma_init); +#endif /* defined(LWGSM_USART_DMA_RX_STREAM) */ + + /* Enable DMA interrupts */ +#if defined(LWGSM_USART_DMA_RX_STREAM) + LL_DMA_EnableIT_HT(LWGSM_USART_DMA, LWGSM_USART_DMA_RX_STREAM); + LL_DMA_EnableIT_TC(LWGSM_USART_DMA, LWGSM_USART_DMA_RX_STREAM); + LL_DMA_EnableIT_TE(LWGSM_USART_DMA, LWGSM_USART_DMA_RX_STREAM); + LL_DMA_EnableIT_FE(LWGSM_USART_DMA, LWGSM_USART_DMA_RX_STREAM); + LL_DMA_EnableIT_DME(LWGSM_USART_DMA, LWGSM_USART_DMA_RX_STREAM); +#else + LL_DMA_EnableIT_HT(LWGSM_USART_DMA, LWGSM_USART_DMA_RX_CH); + LL_DMA_EnableIT_TC(LWGSM_USART_DMA, LWGSM_USART_DMA_RX_CH); + LL_DMA_EnableIT_TE(LWGSM_USART_DMA, LWGSM_USART_DMA_RX_CH); +#endif /* defined(LWGSM_USART_DMA_RX_STREAM) */ + + /* Enable DMA interrupts */ + NVIC_SetPriority(LWGSM_USART_DMA_RX_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x07, 0x00)); + NVIC_EnableIRQ(LWGSM_USART_DMA_RX_IRQ); + + old_pos = 0; + is_running = 1; + + /* Start DMA and USART */ +#if defined(LWGSM_USART_DMA_RX_STREAM) + LL_DMA_EnableStream(LWGSM_USART_DMA, LWGSM_USART_DMA_RX_STREAM); +#else + LL_DMA_EnableChannel(LWGSM_USART_DMA, LWGSM_USART_DMA_RX_CH); +#endif /* defined(LWGSM_USART_DMA_RX_STREAM) */ + LL_USART_Enable(LWGSM_USART); + } else { + osDelay(10); + LL_USART_Disable(LWGSM_USART); + usart_init.BaudRate = baudrate; + LL_USART_Init(LWGSM_USART, &usart_init); + LL_USART_Enable(LWGSM_USART); + } + + /* Create mbox and start thread */ + if (usart_ll_mbox_id == NULL) { + usart_ll_mbox_id = osMessageQueueNew(10, sizeof(void*), NULL); + } + if (usart_ll_thread_id == NULL) { + const osThreadAttr_t attr = { + .stack_size = 1024 + }; + usart_ll_thread_id = osThreadNew(usart_ll_thread, usart_ll_mbox_id, &attr); + } +} + +#if defined(LWGSM_RESET_PIN) +/** + * \brief Hardware reset callback + */ +static uint8_t +reset_device(uint8_t state) { + if (state) { /* Activate reset line */ + LL_GPIO_ResetOutputPin(LWGSM_RESET_PORT, LWGSM_RESET_PIN); + } else { + LL_GPIO_SetOutputPin(LWGSM_RESET_PORT, LWGSM_RESET_PIN); + } + return 1; +} +#endif /* defined(LWGSM_RESET_PIN) */ + +/** + * \brief Send data to GSM device + * \param[in] data: Pointer to data to send + * \param[in] len: Number of bytes to send + * \return Number of bytes sent + */ +static size_t +send_data(const void* data, size_t len) { + const uint8_t* d = data; + + for (size_t i = 0; i < len; ++i, ++d) { + LL_USART_TransmitData8(LWGSM_USART, *d); + while (!LL_USART_IsActiveFlag_TXE(LWGSM_USART)) {} + } + return len; +} + +/** + * \brief Callback function called from initialization process + * \note This function may be called multiple times if AT baudrate is changed from application + * \param[in,out] ll: Pointer to \ref lwgsm_ll_t structure to fill data for communication functions + * \param[in] baudrate: Baudrate to use on AT port + * \return Member of \ref lwgsmr_t enumeration + */ +lwgsmr_t +lwgsm_ll_init(lwgsm_ll_t* ll) { +#if !LWGSM_CFG_MEM_CUSTOM + static uint8_t memory[LWGSM_MEM_SIZE]; + lwgsm_mem_region_t mem_regions[] = { + { memory, sizeof(memory) } + }; + + if (!initialized) { + lwgsm_mem_assignmemory(mem_regions, LWGSM_ARRAYSIZE(mem_regions)); /* Assign memory for allocations */ + } +#endif /* !LWGSM_CFG_MEM_CUSTOM */ + + if (!initialized) { + ll->send_fn = send_data; /* Set callback function to send data */ +#if defined(LWGSM_RESET_PIN) + ll->reset_fn = reset_device; /* Set callback for hardware reset */ +#endif /* defined(LWGSM_RESET_PIN) */ + } + + configure_uart(ll->uart.baudrate); /* Initialize UART for communication */ + initialized = 1; + return lwgsmOK; +} + +/** + * \brief Callback function to de-init low-level communication part + * \param[in,out] ll: Pointer to \ref lwgsm_ll_t structure to fill data for communication functions + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise + */ +lwgsmr_t +lwgsm_ll_deinit(lwgsm_ll_t* ll) { + if (usart_ll_mbox_id != NULL) { + osMessageQueueId_t tmp = usart_ll_mbox_id; + usart_ll_mbox_id = NULL; + osMessageQueueDelete(tmp); + } + if (usart_ll_thread_id != NULL) { + osThreadId_t tmp = usart_ll_thread_id; + usart_ll_thread_id = NULL; + osThreadTerminate(tmp); + } + initialized = 0; + LWGSM_UNUSED(ll); + return lwgsmOK; +} + +/** + * \brief UART global interrupt handler + */ +void +LWGSM_USART_IRQHANDLER(void) { + LL_USART_ClearFlag_IDLE(LWGSM_USART); + LL_USART_ClearFlag_PE(LWGSM_USART); + LL_USART_ClearFlag_FE(LWGSM_USART); + LL_USART_ClearFlag_ORE(LWGSM_USART); + LL_USART_ClearFlag_NE(LWGSM_USART); + + if (usart_ll_mbox_id != NULL) { + void* d = (void*)1; + osMessageQueuePut(usart_ll_mbox_id, &d, 0, 0); + } +} + +/** + * \brief UART DMA stream/channel handler + */ +void +LWGSM_USART_DMA_RX_IRQHANDLER(void) { + LWGSM_USART_DMA_RX_CLEAR_TC; + LWGSM_USART_DMA_RX_CLEAR_HT; + + if (usart_ll_mbox_id != NULL) { + void* d = (void*)1; + osMessageQueuePut(usart_ll_mbox_id, &d, 0, 0); + } +} + +#endif /* !__DOXYGEN__ */ diff --git a/lwgsm/src/system/lwgsm_ll_stm32f429zi_nucleo.c b/lwgsm/src/system/lwgsm_ll_stm32f429zi_nucleo.c new file mode 100644 index 00000000..e644d8b7 --- /dev/null +++ b/lwgsm/src/system/lwgsm_ll_stm32f429zi_nucleo.c @@ -0,0 +1,101 @@ +/** + * \file lwgsm_ll_stm32f429zi_nucleo.c + * \brief Low-level communication with GSM device for STM32F429ZI-Nucleo using DMA + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ + +/* + * Default UART configuration is: + * + * UART: USART6 + * STM32 TX (GSM RX): GPIOC, GPIO_PIN_6 + * STM32 RX (GSM TX): GPIOC, GPIO_PIN_7 + * RESET: GPIOC, GPIO_PIN_5 + * + * USART_DMA: DMA2 + * USART_DMA_STREAM: DMA_STREAM_1 + * USART_DMA_CHANNEL: DMA_CHANNEL_5 + */ +#include "lwgsm/lwgsm.h" +#include "lwgsm/lwgsm_mem.h" +#include "lwgsm/lwgsm_input.h" +#include "system/lwgsm_ll.h" + +#if !__DOXYGEN__ + +#include "stm32f4xx_ll_bus.h" +#include "stm32f4xx_ll_usart.h" +#include "stm32f4xx_ll_gpio.h" +#include "stm32f4xx_ll_dma.h" +#include "stm32f4xx_ll_rcc.h" + +/* USART */ +#define LWGSM_USART USART6 +#define LWGSM_USART_CLK LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART6) +#define LWGSM_USART_IRQ USART6_IRQn +#define LWGSM_USART_IRQHANDLER USART6_IRQHandler +#define LWGSM_USART_RDR_NAME DR + +/* DMA settings */ +#define LWGSM_USART_DMA DMA2 +#define LWGSM_USART_DMA_CLK LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA2) +#define LWGSM_USART_DMA_RX_STREAM LL_DMA_STREAM_1 +#define LWGSM_USART_DMA_RX_CH LL_DMA_CHANNEL_5 +#define LWGSM_USART_DMA_RX_IRQ DMA2_Stream1_IRQn +#define LWGSM_USART_DMA_RX_IRQHANDLER DMA2_Stream1_IRQHandler + +/* DMA flags management */ +#define LWGSM_USART_DMA_RX_IS_TC LL_DMA_IsActiveFlag_TC1(LWGSM_USART_DMA) +#define LWGSM_USART_DMA_RX_IS_HT LL_DMA_IsActiveFlag_HT1(LWGSM_USART_DMA) +#define LWGSM_USART_DMA_RX_CLEAR_TC LL_DMA_ClearFlag_TC1(LWGSM_USART_DMA) +#define LWGSM_USART_DMA_RX_CLEAR_HT LL_DMA_ClearFlag_HT1(LWGSM_USART_DMA) + +/* USART TX PIN */ +#define LWGSM_USART_TX_PORT_CLK LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOC) +#define LWGSM_USART_TX_PORT GPIOC +#define LWGSM_USART_TX_PIN LL_GPIO_PIN_6 +#define LWGSM_USART_TX_PIN_AF LL_GPIO_AF_8 + +/* USART RX PIN */ +#define LWGSM_USART_RX_PORT_CLK LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOC) +#define LWGSM_USART_RX_PORT GPIOC +#define LWGSM_USART_RX_PIN LL_GPIO_PIN_7 +#define LWGSM_USART_RX_PIN_AF LL_GPIO_AF_8 + +/* RESET PIN */ +#define LWGSM_RESET_PORT_CLK LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOC) +#define LWGSM_RESET_PORT GPIOC +#define LWGSM_RESET_PIN LL_GPIO_PIN_5 + +/* Include STM32 generic driver */ +#include "../system/lwgsm_ll_stm32.c" + +#endif /* !__DOXYGEN__ */ diff --git a/gsm_at_lib/src/system/gsm_ll_template.c b/lwgsm/src/system/lwgsm_ll_template.c similarity index 72% rename from gsm_at_lib/src/system/gsm_ll_template.c rename to lwgsm/src/system/lwgsm_ll_template.c index 1c2a959b..c5d96f23 100644 --- a/gsm_at_lib/src/system/gsm_ll_template.c +++ b/lwgsm/src/system/lwgsm_ll_template.c @@ -1,10 +1,10 @@ /** - * \file gsm_ll_template.c + * \file lwgsm_ll_template.c * \brief Low-level communication with GSM device template */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,15 +26,15 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "system/gsm_ll.h" -#include "gsm/gsm.h" -#include "gsm/gsm_mem.h" -#include "gsm/gsm_input.h" +#include "system/lwgsm_ll.h" +#include "lwgsm/lwgsm.h" +#include "lwgsm/lwgsm_mem.h" +#include "lwgsm/lwgsm_input.h" static uint8_t initialized = 0; @@ -45,7 +45,7 @@ static uint8_t initialized = 0; * \return Number of bytes sent */ static size_t -send_data(const void* data, uint16_t size_t) { +send_data(const void* data, size_t len) { /* Implement send function here */ @@ -59,14 +59,14 @@ send_data(const void* data, uint16_t size_t) { * It is important that every configuration except AT baudrate is configured only once! * * \note This function may be called from different threads in GSM stack when using OS. - * When \ref GSM_CFG_INPUT_USE_PROCESS is set to 1, this function may be called from user UART thread. + * When \ref LWGSM_CFG_INPUT_USE_PROCESS is set to 1, this function may be called from user UART thread. * - * \param[in,out] ll: Pointer to \ref gsm_ll_t structure to fill data for communication functions - * \return gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \param[in,out] ll: Pointer to \ref lwgsm_ll_t structure to fill data for communication functions + * \return lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_ll_init(gsm_ll_t* ll) { -#if !GSM_CFG_MEM_CUSTOM +lwgsmr_t +lwgsm_ll_init(lwgsm_ll_t* ll) { +#if !LWGSM_CFG_MEM_CUSTOM /* Step 1: Configure memory for dynamic allocations */ static uint8_t memory[0x10000]; /* Create memory for dynamic allocations with specific size */ @@ -75,13 +75,13 @@ gsm_ll_init(gsm_ll_t* ll) { * If device has internal/external memory available, * multiple memories may be used */ - gsm_mem_region_t mem_regions[] = { + lwgsm_mem_region_t mem_regions[] = { { memory, sizeof(memory) } }; if (!initialized) { - gsm_mem_assignmemory(mem_regions, GSM_ARRAYSIZE(mem_regions)); /* Assign memory for allocations to GSM library */ + lwgsm_mem_assignmemory(mem_regions, LWGSM_ARRAYSIZE(mem_regions)); /* Assign memory for allocations to GSM library */ } -#endif /* !GSM_CFG_MEM_CUSTOM */ +#endif /* !LWGSM_CFG_MEM_CUSTOM */ /* Step 2: Set AT port send function to use when we have data to transmit */ if (!initialized) { @@ -91,16 +91,16 @@ gsm_ll_init(gsm_ll_t* ll) { /* Step 3: Configure AT port to be able to send/receive data to/from GSM device */ configure_uart(ll->uart.baudrate); /* Initialize UART for communication */ initialized = 1; - return gsmOK; + return lwgsmOK; } /** * \brief Callback function to de-init low-level communication part - * \param[in,out] ll: Pointer to \ref gsm_ll_t structure to fill data for communication functions - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \param[in,out] ll: Pointer to \ref lwgsm_ll_t structure to fill data for communication functions + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_ll_deinit(gsm_ll_t* ll) { +lwgsmr_t +lwgsm_ll_deinit(lwgsm_ll_t* ll) { initialized = 0; /* Clear initialized flag */ - return gsmOK; + return lwgsmOK; } diff --git a/gsm_at_lib/src/system/gsm_ll_win32.c b/lwgsm/src/system/lwgsm_ll_win32.c similarity index 75% rename from gsm_at_lib/src/system/gsm_ll_win32.c rename to lwgsm/src/system/lwgsm_ll_win32.c index 7a1f2b32..7f39aa47 100644 --- a/gsm_at_lib/src/system/gsm_ll_win32.c +++ b/lwgsm/src/system/lwgsm_ll_win32.c @@ -1,10 +1,10 @@ /** - * \file gsm_ll_win32.c + * \file lwgsm_ll_win32.c * \brief Low-level communication with GSM device for WIN32 */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,25 +26,24 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "system/gsm_ll.h" -#include "gsm/gsm.h" -#include "gsm/gsm_mem.h" -#include "gsm/gsm_input.h" +#include "system/lwgsm_ll.h" +#include "lwgsm/lwgsm.h" +#include "lwgsm/lwgsm_mem.h" +#include "lwgsm/lwgsm_input.h" #if !__DOXYGEN__ static uint8_t initialized = 0; +static HANDLE thread_handle; +static volatile HANDLE com_port; /*!< COM port handle */ +static uint8_t data_buffer[0x1000]; /*!< Received data array */ -DWORD thread_id; -HANDLE thread_handle; static void uart_thread(void* param); -volatile HANDLE com_port; /*!< COM port handle */ -uint8_t data_buffer[0x1000]; /*!< Received data array */ /** * \brief Send data to GSM device, function called from GSM stack when we have data to send @@ -56,17 +55,17 @@ static size_t send_data(const void* data, size_t len) { DWORD written; if (com_port != NULL) { -#if !GSM_CFG_AT_ECHO +#if !LWGSM_CFG_AT_ECHO const uint8_t* d = data; HANDLE hConsole; hConsole = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hConsole, FOREGROUND_RED); - for (DWORD i = 0; i < len; i++) { + for (DWORD i = 0; i < len; ++i) { printf("%c", d[i]); } SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); -#endif /* !GSM_CFG_AT_ECHO */ +#endif /* !LWGSM_CFG_AT_ECHO */ /* Write data to AT port */ WriteFile(com_port, data, len, &written, NULL); @@ -92,21 +91,22 @@ configure_uart(uint32_t baudrate) { if (!initialized) { static const LPCWSTR com_ports[] = { L"\\\\.\\COM23", + L"\\\\.\\COM12", L"\\\\.\\COM9", L"\\\\.\\COM8", L"\\\\.\\COM4" }; - for (size_t i = 0; i < sizeof(com_ports) / sizeof(com_ports[0]); i++) { + for (size_t i = 0; i < sizeof(com_ports) / sizeof(com_ports[0]); ++i) { com_port = CreateFile(com_ports[i], - GENERIC_READ | GENERIC_WRITE, - 0, - 0, - OPEN_EXISTING, - 0, - NULL - ); + GENERIC_READ | GENERIC_WRITE, + 0, + 0, + OPEN_EXISTING, + 0, + NULL + ); if (GetCommState(com_port, &dcb)) { - printf("COM PORT %s opened!\r\n", (const char *)com_ports[i]); + printf("COM PORT %s opened!\r\n", (const char*)com_ports[i]); break; } } @@ -125,7 +125,7 @@ configure_uart(uint32_t baudrate) { printf("Cannot set COM PORT info\r\n"); } if (GetCommTimeouts(com_port, &timeouts)) { - /* Set timeout to return immediatelly from ReadFile function */ + /* Set timeout to return immediately from ReadFile function */ timeouts.ReadIntervalTimeout = MAXDWORD; timeouts.ReadTotalTimeoutConstant = 0; timeouts.ReadTotalTimeoutMultiplier = 0; @@ -152,13 +152,13 @@ configure_uart(uint32_t baudrate) { static void uart_thread(void* param) { DWORD bytes_read; - gsm_sys_sem_t sem; + lwgsm_sys_sem_t sem; FILE* file = NULL; - gsm_sys_sem_create(&sem, 0); /* Create semaphore for delay functions */ + lwgsm_sys_sem_create(&sem, 0); /* Create semaphore for delay functions */ while (com_port == NULL) { - gsm_sys_sem_wait(&sem, 1); /* Add some delay with yield */ + lwgsm_sys_sem_wait(&sem, 1); /* Add some delay with yield */ } fopen_s(&file, "log_file.txt", "w+"); /* Open debug file in write mode */ @@ -173,17 +173,17 @@ uart_thread(void* param) { HANDLE hConsole; hConsole = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN); - for (DWORD i = 0; i < bytes_read; i++) { + for (DWORD i = 0; i < bytes_read; ++i) { printf("%c", data_buffer[i]); } SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); /* Send received data to input processing module */ -#if GSM_CFG_INPUT_USE_PROCESS - gsm_input_process(data_buffer, (size_t)bytes_read); -#else /* GSM_CFG_INPUT_USE_PROCESS */ - gsm_input(data_buffer, (size_t)bytes_read); -#endif /* !GSM_CFG_INPUT_USE_PROCESS */ +#if LWGSM_CFG_INPUT_USE_PROCESS + lwgsm_input_process(data_buffer, (size_t)bytes_read); +#else /* LWGSM_CFG_INPUT_USE_PROCESS */ + lwgsm_input(data_buffer, (size_t)bytes_read); +#endif /* !LWGSM_CFG_INPUT_USE_PROCESS */ /* Write received data to output debug file */ if (file != NULL) { @@ -194,7 +194,7 @@ uart_thread(void* param) { } while (bytes_read == (DWORD)sizeof(data_buffer)); /* Implement delay to allow other tasks processing */ - gsm_sys_sem_wait(&sem, 1); + lwgsm_sys_sem_wait(&sem, 1); } } @@ -205,14 +205,14 @@ uart_thread(void* param) { * It is important that every configuration except AT baudrate is configured only once! * * \note This function may be called from different threads in GSM stack when using OS. - * When \ref GSM_CFG_INPUT_USE_PROCESS is set to 1, this function may be called from user UART thread. + * When \ref LWGSM_CFG_INPUT_USE_PROCESS is set to 1, this function may be called from user UART thread. * - * \param[in,out] ll: Pointer to \ref gsm_ll_t structure to fill data for communication functions - * \return \ref gsmOK on success, member of \ref gsmr_t enumeration otherwise + * \param[in,out] ll: Pointer to \ref lwgsm_ll_t structure to fill data for communication functions + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t enumeration otherwise */ -gsmr_t -gsm_ll_init(gsm_ll_t* ll) { -#if !GSM_CFG_MEM_CUSTOM +lwgsmr_t +lwgsm_ll_init(lwgsm_ll_t* ll) { +#if !LWGSM_CFG_MEM_CUSTOM /* Step 1: Configure memory for dynamic allocations */ static uint8_t memory[0x10000]; /* Create memory for dynamic allocations with specific size */ @@ -221,13 +221,13 @@ gsm_ll_init(gsm_ll_t* ll) { * If device has internal/external memory available, * multiple memories may be used */ - gsm_mem_region_t mem_regions[] = { + lwgsm_mem_region_t mem_regions[] = { { memory, sizeof(memory) } }; if (!initialized) { - gsm_mem_assignmemory(mem_regions, GSM_ARRAYSIZE(mem_regions)); /* Assign memory for allocations to GSM library */ + lwgsm_mem_assignmemory(mem_regions, LWGSM_ARRAYSIZE(mem_regions)); /* Assign memory for allocations to GSM library */ } -#endif /* !GSM_CFG_MEM_CUSTOM */ +#endif /* !LWGSM_CFG_MEM_CUSTOM */ /* Step 2: Set AT port send function to use when we have data to transmit */ if (!initialized) { @@ -237,7 +237,7 @@ gsm_ll_init(gsm_ll_t* ll) { /* Step 3: Configure AT port to be able to send/receive data to/from GSM device */ configure_uart(ll->uart.baudrate); /* Initialize UART for communication */ initialized = 1; - return gsmOK; + return lwgsmOK; } #endif /* !__DOXYGEN__ */ diff --git a/gsm_at_lib/src/system/gsm_mem_lwmem.c b/lwgsm/src/system/lwgsm_mem_lwmem.c similarity index 75% rename from gsm_at_lib/src/system/gsm_mem_lwmem.c rename to lwgsm/src/system/lwgsm_mem_lwmem.c index e6b76d15..cdcbd0ce 100644 --- a/gsm_at_lib/src/system/gsm_mem_lwmem.c +++ b/lwgsm/src/system/lwgsm_mem_lwmem.c @@ -1,10 +1,10 @@ /** - * \file gsm_mem_lwmem.c + * \file lwgsm_mem_lwmem.c * \brief Dynamic memory manager implemented with LwMEM */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,16 +26,16 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "gsm/gsm.h" +#include "lwgsm/lwgsm.h" -/* See gsm_mem.c file for function documentation on parameters and return values */ +/* See lwgsm_mem.c file for function documentation on parameters and return values */ -#if GSM_CFG_MEM_CUSTOM && !__DOXYGEN__ +#if LWGSM_CFG_MEM_CUSTOM && !__DOXYGEN__ /* * Before this driver can be used, user must: @@ -46,24 +46,24 @@ #include "lwmem/lwmem.h" -void * -gsm_mem_malloc(size_t size) { +void* +lwgsm_mem_malloc(size_t size) { return lwmem_malloc(size); } -void * -gsm_mem_realloc(void* ptr, size_t size) { +void* +lwgsm_mem_realloc(void* ptr, size_t size) { return lwmem_realloc(ptr, size); } -void * -gsm_mem_calloc(size_t num, size_t size) { +void* +lwgsm_mem_calloc(size_t num, size_t size) { return lwmem_calloc(num, size); } void -gsm_mem_free(void* ptr) { +lwgsm_mem_free(void* ptr) { lwmem_free(ptr); } -#endif /* GSM_CFG_MEM_CUSTOM && !__DOXYGEN__ */ \ No newline at end of file +#endif /* LWGSM_CFG_MEM_CUSTOM && !__DOXYGEN__ */ \ No newline at end of file diff --git a/lwgsm/src/system/lwgsm_sys_cmsis_os.c b/lwgsm/src/system/lwgsm_sys_cmsis_os.c new file mode 100644 index 00000000..623d2467 --- /dev/null +++ b/lwgsm/src/system/lwgsm_sys_cmsis_os.c @@ -0,0 +1,209 @@ +/** + * \file lwgsm_sys_cmsis_os.c + * \brief System dependent functions for CMSIS-OS based operating system + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwGSM - Lightweight GSM-AT library. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#include "system/lwgsm_sys.h" +#include "cmsis_os.h" + +#if !__DOXYGEN__ + +static osMutexId_t sys_mutex; + +uint8_t +lwgsm_sys_init(void) { + lwgsm_sys_mutex_create(&sys_mutex); + return 1; +} + +uint32_t +lwgsm_sys_now(void) { + return osKernelSysTick(); +} + +uint8_t +lwgsm_sys_protect(void) { + lwgsm_sys_mutex_lock(&sys_mutex); + return 1; +} + +uint8_t +lwgsm_sys_unprotect(void) { + lwgsm_sys_mutex_unlock(&sys_mutex); + return 1; +} + +uint8_t +lwgsm_sys_mutex_create(lwgsm_sys_mutex_t* p) { + const osMutexAttr_t attr = { + .attr_bits = osMutexRecursive + }; + *p = osMutexNew(&attr); + return *p != NULL; +} + +uint8_t +lwgsm_sys_mutex_delete(lwgsm_sys_mutex_t* p) { + return osMutexDelete(*p) == osOK; +} + +uint8_t +lwgsm_sys_mutex_lock(lwgsm_sys_mutex_t* p) { + return osMutexAcquire(*p, osWaitForever) == osOK; +} + +uint8_t +lwgsm_sys_mutex_unlock(lwgsm_sys_mutex_t* p) { + return osMutexRelease(*p) == osOK; +} + +uint8_t +lwgsm_sys_mutex_isvalid(lwgsm_sys_mutex_t* p) { + return p != NULL && *p != NULL; +} + +uint8_t +lwgsm_sys_mutex_invalid(lwgsm_sys_mutex_t* p) { + *p = LWGSM_SYS_MUTEX_NULL; + return 1; +} + +uint8_t +lwgsm_sys_sem_create(lwgsm_sys_sem_t* p, uint8_t cnt) { + return (*p = osSemaphoreNew(1, cnt > 0 ? 1 : 0, NULL)) != NULL; +} + +uint8_t +lwgsm_sys_sem_delete(lwgsm_sys_sem_t* p) { + return osSemaphoreDelete(*p) == osOK; +} + +uint32_t +lwgsm_sys_sem_wait(lwgsm_sys_sem_t* p, uint32_t timeout) { + uint32_t tick = osKernelSysTick(); + return (osSemaphoreAcquire(*p, timeout == 0 ? osWaitForever : timeout) == osOK) ? (osKernelSysTick() - tick) : LWGSM_SYS_TIMEOUT; +} + +uint8_t +lwgsm_sys_sem_release(lwgsm_sys_sem_t* p) { + return osSemaphoreRelease(*p) == osOK; +} + +uint8_t +lwgsm_sys_sem_isvalid(lwgsm_sys_sem_t* p) { + return p != NULL && *p != NULL; +} + +uint8_t +lwgsm_sys_sem_invalid(lwgsm_sys_sem_t* p) { + *p = LWGSM_SYS_SEM_NULL; + return 1; +} + +uint8_t +lwgsm_sys_mbox_create(lwgsm_sys_mbox_t* b, size_t size) { + return (*b = osMessageQueueNew(size, sizeof(void*), NULL)) != NULL; +} + +uint8_t +lwgsm_sys_mbox_delete(lwgsm_sys_mbox_t* b) { + if (osMessageQueueGetCount(*b) > 0) { + return 0; + } + return osMessageQueueDelete(*b) == osOK; +} + +uint32_t +lwgsm_sys_mbox_put(lwgsm_sys_mbox_t* b, void* m) { + uint32_t tick = osKernelSysTick(); + return osMessageQueuePut(*b, &m, 0, osWaitForever) == osOK ? (osKernelSysTick() - tick) : LWGSM_SYS_TIMEOUT; +} + +uint32_t +lwgsm_sys_mbox_get(lwgsm_sys_mbox_t* b, void** m, uint32_t timeout) { + uint32_t tick = osKernelSysTick(); + return osMessageQueueGet(*b, m, NULL, timeout == 0 ? osWaitForever : timeout) == osOK ? (osKernelSysTick() - tick) : LWGSM_SYS_TIMEOUT; +} + +uint8_t +lwgsm_sys_mbox_putnow(lwgsm_sys_mbox_t* b, void* m) { + return osMessageQueuePut(*b, &m, 0, 0) == osOK; +} + +uint8_t +lwgsm_sys_mbox_getnow(lwgsm_sys_mbox_t* b, void** m) { + return osMessageQueueGet(*b, m, NULL, 0) == osOK; +} + +uint8_t +lwgsm_sys_mbox_isvalid(lwgsm_sys_mbox_t* b) { + return b != NULL && *b != NULL; +} + +uint8_t +lwgsm_sys_mbox_invalid(lwgsm_sys_mbox_t* b) { + *b = LWGSM_SYS_MBOX_NULL; + return 1; +} + +uint8_t +lwgsm_sys_thread_create(lwgsm_sys_thread_t* t, const char* name, lwgsm_sys_thread_fn thread_func, void* const arg, size_t stack_size, lwgsm_sys_thread_prio_t prio) { + lwgsm_sys_thread_t id; + const osThreadAttr_t thread_attr = { + .name = (char*)name, + .priority = (osPriority)prio, + .stack_size = stack_size > 0 ? stack_size : LWGSM_SYS_THREAD_SS + }; + + id = osThreadNew(thread_func, arg, &thread_attr); + if (t != NULL) { + *t = id; + } + return id != NULL; +} + +uint8_t +lwgsm_sys_thread_terminate(lwgsm_sys_thread_t* t) { + if (t != NULL) { + osThreadTerminate(*t); + } else { + osThreadExit(); + } + return 1; +} + +uint8_t +lwgsm_sys_thread_yield(void) { + osThreadYield(); + return 1; +} + +#endif /* !__DOXYGEN__ */ diff --git a/lwgsm/src/system/lwgsm_sys_template.c b/lwgsm/src/system/lwgsm_sys_template.c new file mode 100644 index 00000000..e2d07b65 --- /dev/null +++ b/lwgsm/src/system/lwgsm_sys_template.c @@ -0,0 +1,388 @@ +/** + * \file lwgsm_sys_template.c + * \brief System dependant functions + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Tilen MAJERLE + * Version: v0.1.0 + */ +#include "system/lwgsm_sys.h" +#include "cmsis_os.h" + +static osMutexId sys_mutex; + +/** + * \brief Init system dependant parameters + * + * After this function is called, + * all other system functions must be fully ready. + * + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_init(void) { + lwgsm_sys_mutex_create(&sys_mutex); + return 1; +} + +/** + * \brief Get current time in units of milliseconds + * \return Current time in units of milliseconds + */ +uint32_t +lwgsm_sys_now(void) { + return osKernelSysTick(); +} + +/** + * \brief Protect middleware core + * + * Stack protection must support recursive mode. + * This function may be called multiple times, + * even if access has been granted before. + * + * \note Most operating systems support recursive mutexes. + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_protect(void) { + lwgsm_sys_mutex_lock(&sys_mutex); + return 1; +} + +/** + * \brief Unprotect middleware core + * + * This function must follow number of calls of \ref lwgsm_sys_protect + * and unlock access only when counter reached back zero. + * + * \note Most operating systems support recursive mutexes. + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_unprotect(void) { + lwgsm_sys_mutex_unlock(&sys_mutex); + return 1; +} + +/** + * \brief Create new recursive mutex + * \note Recursive mutex has to be created as it may be locked multiple times before unlocked + * \param[out] p: Pointer to mutex structure to allocate + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_mutex_create(lwgsm_sys_mutex_t* p) { + osMutexDef(MUT); + *p = osRecursiveMutexCreate(osMutex(MUT)); + return *p != NULL; +} + +/** + * \brief Delete recursive mutex from system + * \param[in] p: Pointer to mutex structure + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_mutex_delete(lwgsm_sys_mutex_t* p) { + return osMutexDelete(*p) == osOK; +} + +/** + * \brief Lock recursive mutex, wait forever to lock + * \param[in] p: Pointer to mutex structure + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_mutex_lock(lwgsm_sys_mutex_t* p) { + return osRecursiveMutexWait(*p, osWaitForever) == osOK; +} + +/** + * \brief Unlock recursive mutex + * \param[in] p: Pointer to mutex structure + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_mutex_unlock(lwgsm_sys_mutex_t* p) { + return osRecursiveMutexRelease(*p) == osOK; +} + +/** + * \brief Check if mutex structure is valid system + * \param[in] p: Pointer to mutex structure + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_mutex_isvalid(lwgsm_sys_mutex_t* p) { + return p != NULL && *p != NULL; +} + +/** + * \brief Set recursive mutex structure as invalid + * \param[in] p: Pointer to mutex structure + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_mutex_invalid(lwgsm_sys_mutex_t* p) { + *p = LWGSM_SYS_MUTEX_NULL; + return 1; +} + +/** + * \brief Create a new binary semaphore and set initial state + * \note Semaphore may only have `1` token available + * \param[out] p: Pointer to semaphore structure to fill with result + * \param[in] cnt: Count indicating default semaphore state: + * `0`: Take semaphore token immediately + * `1`: Keep token available + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_sem_create(lwgsm_sys_sem_t* p, uint8_t cnt) { + osSemaphoreDef(SEM); + *p = osSemaphoreCreate(osSemaphore(SEM), 1); + + if (*p != NULL && !cnt) { + osSemaphoreWait(*p, 0); + } + return *p != NULL; +} + +/** + * \brief Delete binary semaphore + * \param[in] p: Pointer to semaphore structure + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_sem_delete(lwgsm_sys_sem_t* p) { + return osSemaphoreDelete(*p) == osOK; +} + +/** + * \brief Wait for semaphore to be available + * \param[in] p: Pointer to semaphore structure + * \param[in] timeout: Timeout to wait in milliseconds. When `0` is applied, wait forever + * \return Number of milliseconds waited for semaphore to become available or + * \ref LWGSM_SYS_TIMEOUT if not available within given time + */ +uint32_t +lwgsm_sys_sem_wait(lwgsm_sys_sem_t* p, uint32_t timeout) { + uint32_t tick = osKernelSysTick(); + return (osSemaphoreWait(*p, !timeout ? osWaitForever : timeout) == osOK) ? (osKernelSysTick() - tick) : LWGSM_SYS_TIMEOUT; +} + +/** + * \brief Release semaphore + * \param[in] p: Pointer to semaphore structure + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_sem_release(lwgsm_sys_sem_t* p) { + return osSemaphoreRelease(*p) == osOK; +} + +/** + * \brief Check if semaphore is valid + * \param[in] p: Pointer to semaphore structure + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_sem_isvalid(lwgsm_sys_sem_t* p) { + return p != NULL && *p != NULL; +} + +/** + * \brief Invalid semaphore + * \param[in] p: Pointer to semaphore structure + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_sem_invalid(lwgsm_sys_sem_t* p) { + *p = LWGSM_SYS_SEM_NULL; + return 1; +} + +/** + * \brief Create a new message queue with entry type of `void *` + * \param[out] b: Pointer to message queue structure + * \param[in] size: Number of entries for message queue to hold + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_mbox_create(lwgsm_sys_mbox_t* b, size_t size) { + osMessageQDef(MBOX, size, void*); + *b = osMessageCreate(osMessageQ(MBOX), NULL); + return *b != NULL; +} + +/** + * \brief Delete message queue + * \param[in] b: Pointer to message queue structure + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_mbox_delete(lwgsm_sys_mbox_t* b) { + if (osMessageWaiting(*b)) { + return 0; + } + return osMessageDelete(*b) == osOK; +} + +/** + * \brief Put a new entry to message queue and wait until memory available + * \param[in] b: Pointer to message queue structure + * \param[in] m: Pointer to entry to insert to message queue + * \return Time in units of milliseconds needed to put a message to queue + */ +uint32_t +lwgsm_sys_mbox_put(lwgsm_sys_mbox_t* b, void* m) { + uint32_t tick = osKernelSysTick(); + return osMessagePut(*b, (uint32_t)m, osWaitForever) == osOK ? (osKernelSysTick() - tick) : LWGSM_SYS_TIMEOUT; +} + +/** + * \brief Get a new entry from message queue with timeout + * \param[in] b: Pointer to message queue structure + * \param[in] m: Pointer to pointer to result to save value from message queue to + * \param[in] timeout: Maximal timeout to wait for new message. When `0` is applied, wait for unlimited time + * \return Time in units of milliseconds needed to put a message to queue + * or \ref LWGSM_SYS_TIMEOUT if it was not successful + */ +uint32_t +lwgsm_sys_mbox_get(lwgsm_sys_mbox_t* b, void** m, uint32_t timeout) { + osEvent evt; + uint32_t time = osKernelSysTick(); + + evt = osMessageGet(*b, !timeout ? osWaitForever : timeout); + if (evt.status == osEventMessage) { + *m = evt.value.p; + return osKernelSysTick() - time; + } + return LWGSM_SYS_TIMEOUT; +} + +/** + * \brief Put a new entry to message queue without timeout (now or fail) + * \param[in] b: Pointer to message queue structure + * \param[in] m: Pointer to message to save to queue + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_mbox_putnow(lwgsm_sys_mbox_t* b, void* m) { + return osMessagePut(*b, (uint32_t)m, 0) == osOK; +} + +/** + * \brief Get an entry from message queue immediately + * \param[in] b: Pointer to message queue structure + * \param[in] m: Pointer to pointer to result to save value from message queue to + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_mbox_getnow(lwgsm_sys_mbox_t* b, void** m) { + osEvent evt; + + evt = osMessageGet(*b, 0); + if (evt.status == osEventMessage) { + *m = evt.value.p; + return 1; + } + return 0; +} + +/** + * \brief Check if message queue is valid + * \param[in] b: Pointer to message queue structure + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_mbox_isvalid(lwgsm_sys_mbox_t* b) { + return b != NULL && *b != NULL; +} + +/** + * \brief Invalid message queue + * \param[in] b: Pointer to message queue structure + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_mbox_invalid(lwgsm_sys_mbox_t* b) { + *b = LWGSM_SYS_MBOX_NULL; + return 1; +} + +/** + * \brief Create a new thread + * \param[out] t: Pointer to thread identifier if create was successful. + * It may be set to `NULL` + * \param[in] name: Name of a new thread + * \param[in] thread_func: Thread function to use as thread body + * \param[in] arg: Thread function argument + * \param[in] stack_size: Size of thread stack in uints of bytes. If set to 0, reserve default stack size + * \param[in] prio: Thread priority + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_thread_create(lwgsm_sys_thread_t* t, const char* name, lwgsm_sys_thread_fn thread_func, + void* const arg, size_t stack_size, lwgsm_sys_thread_prio_t prio) { + const osThreadDef_t thread_def = { + (char*)name, + (os_pthread)thread_func, + (osPriority)prio, + 0, + stack_size > 0 ? stack_size : LWGSM_SYS_THREAD_SS + }; + lwgsm_sys_thread_t id; + + id = osThreadCreate(&thread_def, arg); + if (t != NULL) { + *t = id; + } + return id != NULL; +} + +/** + * \brief Terminate thread (shut it down and remove) + * \param[in] t: Pointer to thread handle to terminate. + * If set to `NULL`, terminate current thread (thread from where function is called) + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_thread_terminate(lwgsm_sys_thread_t* t) { + osThreadTerminate(t != NULL ? *t : NULL); + return 1; +} + +/** + * \brief Yield current thread + * \return `1` on success, `0` otherwise + */ +uint8_t +lwgsm_sys_thread_yield(void) { + osThreadYield(); + return 1; +} diff --git a/gsm_at_lib/src/system/gsm_sys_win32.c b/lwgsm/src/system/lwgsm_sys_win32.c similarity index 55% rename from gsm_at_lib/src/system/gsm_sys_win32.c rename to lwgsm/src/system/lwgsm_sys_win32.c index 5018825f..7ba0d5ce 100644 --- a/gsm_at_lib/src/system/gsm_sys_win32.c +++ b/lwgsm/src/system/lwgsm_sys_win32.c @@ -1,10 +1,10 @@ -/** - * \file gsm_sys_win32.c +/** + * \file lwgsm_sys_win32.c * \brief System dependant functions for WIN32 */ /* - * Copyright (c) 2019 Tilen MAJERLE + * Copyright (c) 2020 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,14 +26,14 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * This file is part of GSM-AT library. + * This file is part of LwGSM - Lightweight GSM-AT library. * * Author: Tilen MAJERLE - * Version: v0.6.0 + * Version: v0.1.0 */ -#include "system/gsm_sys.h" #include #include +#include "system/lwgsm_sys.h" #if !__DOXYGEN__ @@ -41,15 +41,15 @@ * \brief Custom message queue implementation for WIN32 */ typedef struct { - gsm_sys_sem_t sem_not_empty; /*!< Semaphore indicates not empty */ - gsm_sys_sem_t sem_not_full; /*!< Semaphore indicates not full */ - gsm_sys_sem_t sem; /*!< Semaphore to lock access */ + lwgsm_sys_sem_t sem_not_empty; /*!< Semaphore indicates not empty */ + lwgsm_sys_sem_t sem_not_full; /*!< Semaphore indicates not full */ + lwgsm_sys_sem_t sem; /*!< Semaphore to lock access */ size_t in, out, size; void* entries[1]; } win32_mbox_t; static LARGE_INTEGER freq, sys_start_time; -static gsm_sys_mutex_t sys_mutex; /* Mutex ID for main protection */ +static lwgsm_sys_mutex_t sys_mutex; /* Mutex ID for main protection */ static uint8_t mbox_is_full(win32_mbox_t* m) { @@ -79,44 +79,44 @@ osKernelSysTick(void) { } uint8_t -gsm_sys_init(void) { +lwgsm_sys_init(void) { QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&sys_start_time); - gsm_sys_mutex_create(&sys_mutex); + lwgsm_sys_mutex_create(&sys_mutex); return 1; } uint32_t -gsm_sys_now(void) { +lwgsm_sys_now(void) { return osKernelSysTick(); } uint8_t -gsm_sys_protect(void) { - gsm_sys_mutex_lock(&sys_mutex); +lwgsm_sys_protect(void) { + lwgsm_sys_mutex_lock(&sys_mutex); return 1; } uint8_t -gsm_sys_unprotect(void) { - gsm_sys_mutex_unlock(&sys_mutex); +lwgsm_sys_unprotect(void) { + lwgsm_sys_mutex_unlock(&sys_mutex); return 1; } uint8_t -gsm_sys_mutex_create(gsm_sys_mutex_t* p) { +lwgsm_sys_mutex_create(lwgsm_sys_mutex_t* p) { *p = CreateMutex(NULL, FALSE, NULL); return *p != NULL; } uint8_t -gsm_sys_mutex_delete(gsm_sys_mutex_t* p) { +lwgsm_sys_mutex_delete(lwgsm_sys_mutex_t* p) { return CloseHandle(*p); } uint8_t -gsm_sys_mutex_lock(gsm_sys_mutex_t* p) { +lwgsm_sys_mutex_lock(lwgsm_sys_mutex_t* p) { DWORD ret; ret = WaitForSingleObject(*p, INFINITE); if (ret != WAIT_OBJECT_0) { @@ -126,23 +126,23 @@ gsm_sys_mutex_lock(gsm_sys_mutex_t* p) { } uint8_t -gsm_sys_mutex_unlock(gsm_sys_mutex_t* p) { - return (uint8_t)ReleaseMutex(*p); +lwgsm_sys_mutex_unlock(lwgsm_sys_mutex_t* p) { + return (uint8_t)ReleaseMutex(*p); } uint8_t -gsm_sys_mutex_isvalid(gsm_sys_mutex_t* p) { +lwgsm_sys_mutex_isvalid(lwgsm_sys_mutex_t* p) { return p != NULL && *p != NULL; } uint8_t -gsm_sys_mutex_invalid(gsm_sys_mutex_t* p) { - *p = GSM_SYS_MUTEX_NULL; +lwgsm_sys_mutex_invalid(lwgsm_sys_mutex_t* p) { + *p = LWGSM_SYS_MUTEX_NULL; return 1; } uint8_t -gsm_sys_sem_create(gsm_sys_sem_t* p, uint8_t cnt) { +lwgsm_sys_sem_create(lwgsm_sys_sem_t* p, uint8_t cnt) { HANDLE h; h = CreateSemaphore(NULL, !!cnt, 1, NULL); *p = h; @@ -150,15 +150,15 @@ gsm_sys_sem_create(gsm_sys_sem_t* p, uint8_t cnt) { } uint8_t -gsm_sys_sem_delete(gsm_sys_sem_t* p) { +lwgsm_sys_sem_delete(lwgsm_sys_sem_t* p) { return CloseHandle(*p); } uint32_t -gsm_sys_sem_wait(gsm_sys_sem_t* p, uint32_t timeout) { +lwgsm_sys_sem_wait(lwgsm_sys_sem_t* p, uint32_t timeout) { DWORD ret; uint32_t tick = osKernelSysTick(); - + if (timeout == 0) { ret = WaitForSingleObject(*p, INFINITE); return 1; @@ -167,61 +167,61 @@ gsm_sys_sem_wait(gsm_sys_sem_t* p, uint32_t timeout) { if (ret == WAIT_OBJECT_0) { return 1; } else { - return GSM_SYS_TIMEOUT; + return LWGSM_SYS_TIMEOUT; } } } uint8_t -gsm_sys_sem_release(gsm_sys_sem_t* p) { +lwgsm_sys_sem_release(lwgsm_sys_sem_t* p) { return ReleaseSemaphore(*p, 1, NULL); } uint8_t -gsm_sys_sem_isvalid(gsm_sys_sem_t* p) { +lwgsm_sys_sem_isvalid(lwgsm_sys_sem_t* p) { return p != NULL && *p != NULL; } uint8_t -gsm_sys_sem_invalid(gsm_sys_sem_t* p) { - *p = GSM_SYS_SEM_NULL; +lwgsm_sys_sem_invalid(lwgsm_sys_sem_t* p) { + *p = LWGSM_SYS_SEM_NULL; return 1; } uint8_t -gsm_sys_mbox_create(gsm_sys_mbox_t* b, size_t size) { +lwgsm_sys_mbox_create(lwgsm_sys_mbox_t* b, size_t size) { win32_mbox_t* mbox; *b = NULL; - mbox = malloc(sizeof(*mbox) + size * sizeof(void *)); + mbox = malloc(sizeof(*mbox) + size * sizeof(void*)); if (mbox != NULL) { memset(mbox, 0x00, sizeof(*mbox)); mbox->size = size + 1; /* Set it to 1 more as cyclic buffer has only one less than size */ - gsm_sys_sem_create(&mbox->sem, 1); - gsm_sys_sem_create(&mbox->sem_not_empty, 0); - gsm_sys_sem_create(&mbox->sem_not_full, 0); + lwgsm_sys_sem_create(&mbox->sem, 1); + lwgsm_sys_sem_create(&mbox->sem_not_empty, 0); + lwgsm_sys_sem_create(&mbox->sem_not_full, 0); *b = mbox; } return *b != NULL; } uint8_t -gsm_sys_mbox_delete(gsm_sys_mbox_t* b) { +lwgsm_sys_mbox_delete(lwgsm_sys_mbox_t* b) { win32_mbox_t* mbox = *b; - gsm_sys_sem_delete(&mbox->sem); - gsm_sys_sem_delete(&mbox->sem_not_full); - gsm_sys_sem_delete(&mbox->sem_not_empty); + lwgsm_sys_sem_delete(&mbox->sem); + lwgsm_sys_sem_delete(&mbox->sem_not_full); + lwgsm_sys_sem_delete(&mbox->sem_not_empty); free(mbox); return 1; } uint32_t -gsm_sys_mbox_put(gsm_sys_mbox_t* b, void* m) { +lwgsm_sys_mbox_put(lwgsm_sys_mbox_t* b, void* m) { win32_mbox_t* mbox = *b; uint32_t time = osKernelSysTick(); /* Get start time */ - gsm_sys_sem_wait(&mbox->sem, 0); /* Wait for access */ + lwgsm_sys_sem_wait(&mbox->sem, 0); /* Wait for access */ /* * Since function is blocking until ready to write something to queue, @@ -229,120 +229,99 @@ gsm_sys_mbox_put(gsm_sys_mbox_t* b, void* m) { * to process the queue before we can write new value. */ while (mbox_is_full(mbox)) { - gsm_sys_sem_release(&mbox->sem); /* Release semaphore */ - gsm_sys_sem_wait(&mbox->sem_not_full, 0); /* Wait for semaphore indicating not full */ - gsm_sys_sem_wait(&mbox->sem, 0); /* Wait availability again */ + lwgsm_sys_sem_release(&mbox->sem); /* Release semaphore */ + lwgsm_sys_sem_wait(&mbox->sem_not_full, 0); /* Wait for semaphore indicating not full */ + lwgsm_sys_sem_wait(&mbox->sem, 0); /* Wait availability again */ } mbox->entries[mbox->in] = m; - if (mbox->in == mbox->out) { /* Was the previous state empty? */ - gsm_sys_sem_release(&mbox->sem_not_empty); /* Signal non-empty state */ - } if (++mbox->in >= mbox->size) { mbox->in = 0; } - gsm_sys_sem_release(&mbox->sem); /* Release access for other threads */ + lwgsm_sys_sem_release(&mbox->sem_not_empty);/* Signal non-empty state */ + lwgsm_sys_sem_release(&mbox->sem); /* Release access for other threads */ return osKernelSysTick() - time; } uint32_t -gsm_sys_mbox_get(gsm_sys_mbox_t* b, void** m, uint32_t timeout) { +lwgsm_sys_mbox_get(lwgsm_sys_mbox_t* b, void** m, uint32_t timeout) { win32_mbox_t* mbox = *b; - uint32_t time = osKernelSysTick(); /* Get current time */ - uint32_t spent_time; + uint32_t time; + + time = osKernelSysTick(); /* Get exclusive access to message queue */ - if ((spent_time = gsm_sys_sem_wait(&mbox->sem, timeout)) == GSM_SYS_TIMEOUT) { - return spent_time; + if (lwgsm_sys_sem_wait(&mbox->sem, timeout) == LWGSM_SYS_TIMEOUT) { + return LWGSM_SYS_TIMEOUT; } - - /* Make sure we have something to read from queue. */ while (mbox_is_empty(mbox)) { - gsm_sys_sem_release(&mbox->sem); /* Release semaphore and allow other threads to write something */ - /* - * Timeout = 0 means unlimited time - * Wait either unlimited time or for specific timeout - */ - if (timeout == 0) { - gsm_sys_sem_wait(&mbox->sem_not_empty, 0); - } else { - spent_time = gsm_sys_sem_wait(&mbox->sem_not_empty, timeout); - if (spent_time == GSM_SYS_TIMEOUT) { - return spent_time; - } + lwgsm_sys_sem_release(&mbox->sem); + if (lwgsm_sys_sem_wait(&mbox->sem_not_empty, timeout) == LWGSM_SYS_TIMEOUT) { + return LWGSM_SYS_TIMEOUT; } - spent_time = gsm_sys_sem_wait(&mbox->sem, timeout); /* Wait again for exclusive access */ + lwgsm_sys_sem_wait(&mbox->sem, timeout); } - - /* - * At this point, semaphore is not empty and - * we have exclusive access to content - */ *m = mbox->entries[mbox->out]; if (++mbox->out >= mbox->size) { mbox->out = 0; } - - /* Release it only if waiting for it */ - gsm_sys_sem_release(&mbox->sem_not_full); /* Release semaphore as it is not full */ - gsm_sys_sem_release(&mbox->sem); /* Release exclusive access to mbox */ + lwgsm_sys_sem_release(&mbox->sem_not_full); + lwgsm_sys_sem_release(&mbox->sem); return osKernelSysTick() - time; } uint8_t -gsm_sys_mbox_putnow(gsm_sys_mbox_t* b, void* m) { +lwgsm_sys_mbox_putnow(lwgsm_sys_mbox_t* b, void* m) { win32_mbox_t* mbox = *b; - gsm_sys_sem_wait(&mbox->sem, 0); + lwgsm_sys_sem_wait(&mbox->sem, 0); if (mbox_is_full(mbox)) { - gsm_sys_sem_release(&mbox->sem); + lwgsm_sys_sem_release(&mbox->sem); return 0; } mbox->entries[mbox->in] = m; if (mbox->in == mbox->out) { - gsm_sys_sem_release(&mbox->sem_not_empty); + lwgsm_sys_sem_release(&mbox->sem_not_empty); } - mbox->in++; - if (mbox->in >= mbox->size) { + if (++mbox->in >= mbox->size) { mbox->in = 0; } - gsm_sys_sem_release(&mbox->sem); + lwgsm_sys_sem_release(&mbox->sem); return 1; } uint8_t -gsm_sys_mbox_getnow(gsm_sys_mbox_t* b, void** m) { +lwgsm_sys_mbox_getnow(lwgsm_sys_mbox_t* b, void** m) { win32_mbox_t* mbox = *b; - gsm_sys_sem_wait(&mbox->sem, 0); /* Wait exclusive access */ + lwgsm_sys_sem_wait(&mbox->sem, 0); /* Wait exclusive access */ if (mbox->in == mbox->out) { - gsm_sys_sem_release(&mbox->sem); /* Release access */ + lwgsm_sys_sem_release(&mbox->sem); /* Release access */ return 0; } *m = mbox->entries[mbox->out]; - mbox->out++; - if (mbox->out >= mbox->size) { + if (++mbox->out >= mbox->size) { mbox->out = 0; } - gsm_sys_sem_release(&mbox->sem_not_full); /* Queue not full anymore */ - gsm_sys_sem_release(&mbox->sem); /* Release semaphore */ + lwgsm_sys_sem_release(&mbox->sem_not_full); /* Queue not full anymore */ + lwgsm_sys_sem_release(&mbox->sem); /* Release semaphore */ return 1; } uint8_t -gsm_sys_mbox_isvalid(gsm_sys_mbox_t* b) { +lwgsm_sys_mbox_isvalid(lwgsm_sys_mbox_t* b) { return b != NULL && *b != NULL; /* Return status if message box is valid */ } uint8_t -gsm_sys_mbox_invalid(gsm_sys_mbox_t* b) { - *b = GSM_SYS_MBOX_NULL; /* Invalidate message box */ +lwgsm_sys_mbox_invalid(lwgsm_sys_mbox_t* b) { + *b = LWGSM_SYS_MBOX_NULL; /* Invalidate message box */ return 1; } uint8_t -gsm_sys_thread_create(gsm_sys_thread_t* t, const char* name, gsm_sys_thread_fn thread_func, void* const arg, size_t stack_size, gsm_sys_thread_prio_t prio) { +lwgsm_sys_thread_create(lwgsm_sys_thread_t* t, const char* name, lwgsm_sys_thread_fn thread_func, void* const arg, size_t stack_size, lwgsm_sys_thread_prio_t prio) { HANDLE h; DWORD id; h = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)thread_func, arg, 0, &id); @@ -353,7 +332,7 @@ gsm_sys_thread_create(gsm_sys_thread_t* t, const char* name, gsm_sys_thread_fn t } uint8_t -gsm_sys_thread_terminate(gsm_sys_thread_t* t) { +lwgsm_sys_thread_terminate(lwgsm_sys_thread_t* t) { HANDLE h = NULL; if (t == NULL) { /* Shall we terminate ourself? */ @@ -362,13 +341,13 @@ gsm_sys_thread_terminate(gsm_sys_thread_t* t) { h = *t; } TerminateThread(h, 0); - return 1; + return 1; } uint8_t -gsm_sys_thread_yield(void) { +lwgsm_sys_thread_yield(void) { /* Not implemented */ - return 1; + return 1; } #endif /* !__DOXYGEN__ */ diff --git a/snippets/call.c b/snippets/call.c new file mode 100644 index 00000000..8203c7de --- /dev/null +++ b/snippets/call.c @@ -0,0 +1,61 @@ +/* + * Receive call and answer to it example + */ +#include "call.h" +#include "lwgsm/lwgsm.h" + +#if !LWGSM_CFG_CALL +#error "CALL must be enabled to run this example" +#endif /* !LWGSM_CFG_CALL */ + +static lwgsmr_t call_evt_func(lwgsm_evt_t* evt); + +/** + * \brief Start CALL example + */ +void +call_start(void) { + /* Add custom callback */ + lwgsm_evt_register(call_evt_func); + + /* Enable calls */ + if (lwgsm_call_enable(NULL, NULL, 1) == lwgsmOK) { + printf("Calls enabled. You may take your phone and call GSM device number.\r\n"); + } else { + printf("Could not enable call functionality!\r\n"); + } +} + +/** + * \brief Event function for calls + * \param[in] evt: GSM event + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +static lwgsmr_t +call_evt_func(lwgsm_evt_t* evt) { + switch (lwgsm_evt_get_type(evt)) { + case LWGSM_EVT_CALL_CHANGED: { + const lwgsm_call_t* call = lwgsm_evt_call_changed_get_call(evt); + if (call->state == LWGSM_CALL_STATE_ACTIVE) { + printf("Call is active!\r\n"); + + /* In case of mobile originated direction */ + if (call->dir == LWGSM_CALL_DIR_MO) { + lwgsm_call_hangup(NULL, NULL, 0); /* Manually hangup call */ + } + } else if (call->state == LWGSM_CALL_STATE_INCOMING) { + printf("Incoming call received! Phone number: %s\r\n", call->number); + lwgsm_call_answer(NULL, NULL, 0); /* Answer to a call */ + } else if (call->state == LWGSM_CALL_STATE_DIALING) { + printf("Call is dialing!\r\n"); + } else if (call->state == LWGSM_CALL_STATE_DISCONNECT) { + printf("Call ended!\r\n"); + } + break; + } + default: + break; + } + + return lwgsmOK; +} diff --git a/snippets/call_sms.c b/snippets/call_sms.c new file mode 100644 index 00000000..e424ba74 --- /dev/null +++ b/snippets/call_sms.c @@ -0,0 +1,119 @@ +/* + * SMS send and receive basic event based example + * + * Waits for received SMS and then replies with + */ +#include "call_sms.h" +#include "lwgsm/lwgsm.h" + +#if !LWGSM_CFG_SMS || !LWGSM_CFG_CALL +#error "SMS & CALL must be enabled to run this example" +#endif /* !LWGSM_CFG_SMS || !LWGSM_CFG_CALL */ + +static lwgsmr_t call_sms_evt_func(lwgsm_evt_t* evt); + +/** + * \brief SMS entry + */ +static lwgsm_sms_entry_t +sms_entry; + +/** + * \brief Start CALL & SMS combined example + */ +void +call_sms_start(void) { + /* Add custom callback */ + lwgsm_evt_register(call_sms_evt_func); + + /* First enable SMS functionality */ + if (lwgsm_sms_enable(NULL, NULL, 1) == lwgsmOK) { + printf("SMS enabled. Send new SMS from your phone to device.\r\n"); + } else { + printf("Cannot enable SMS functionality!\r\n"); + } + + /* Then enable call functionality */ + if (lwgsm_call_enable(NULL, NULL, 1) == lwgsmOK) { + printf("Call enabled. You may now take your phone and call modem\r\n"); + } else { + printf("Cannot enable call functionality!\r\n"); + } + + /* Now send SMS from phone to device */ + printf("Start by sending SMS message or call device...\r\n"); +} + +/** + * \brief Event function for received SMS or calls + * \param[in] evt: GSM event + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +static lwgsmr_t +call_sms_evt_func(lwgsm_evt_t* evt) { + switch (lwgsm_evt_get_type(evt)) { + case LWGSM_EVT_SMS_READY: { /* SMS is ready notification from device */ + printf("SIM device SMS service is ready!\r\n"); + break; + } + case LWGSM_EVT_SMS_RECV: { /* New SMS received indicator */ + lwgsmr_t res; + + printf("New SMS received!\r\n"); /* Notify user */ + + /* Try to read SMS */ + res = lwgsm_sms_read(lwgsm_evt_sms_recv_get_mem(evt), lwgsm_evt_sms_recv_get_pos(evt), &sms_entry, 1, NULL, NULL, 0); + if (res == lwgsmOK) { + printf("SMS read in progress!\r\n"); + } else { + printf("Cannot start SMS read procedure!\r\n"); + } + break; + } + case LWGSM_EVT_SMS_READ: { /* SMS read event */ + lwgsm_sms_entry_t* entry = lwgsm_evt_sms_read_get_entry(evt); + if (lwgsm_evt_sms_read_get_result(evt) == lwgsmOK && entry != NULL) { + /* Print SMS data */ + printf("SMS read. From: %s, content: %s\r\n", + entry->number, entry->data + ); + + /* Try to send SMS back */ + if (lwgsm_sms_send(entry->number, entry->data, NULL, NULL, 0) == lwgsmOK) { + printf("SMS send in progress!\r\n"); + } else { + printf("Cannot start SMS send procedure!\r\n"); + } + + /* Delete SMS from device memory */ + lwgsm_sms_delete(entry->mem, entry->pos, NULL, NULL, 0); + } + break; + } + case LWGSM_EVT_SMS_SEND: { /* SMS send event */ + if (lwgsm_evt_sms_send_get_result(evt) == lwgsmOK) { + printf("SMS has been successfully sent!\r\n"); + } else { + printf("SMS has not been sent successfully!\r\n"); + } + break; + } + + case LWGSM_EVT_CALL_READY: { /* Call is ready notification from device */ + printf("SIM device Call service is ready!\r\n"); + break; + } + case LWGSM_EVT_CALL_CHANGED: { + const lwgsm_call_t* call = lwgsm_evt_call_changed_get_call(evt); + if (call->state == LWGSM_CALL_STATE_INCOMING) { /* On incoming call */ + lwgsm_call_hangup(NULL, NULL, 0); /* Hangup call */ + lwgsm_sms_send(call->number, "Cannot answer call. Please send SMS\r\n", NULL, NULL, 0); + } + break; + } + default: + break; + } + + return lwgsmOK; +} diff --git a/snippets/client.c b/snippets/client.c new file mode 100644 index 00000000..28aaf8d3 --- /dev/null +++ b/snippets/client.c @@ -0,0 +1,100 @@ +#include "client.h" +#include "lwgsm/lwgsm.h" +#include "lwgsm/lwgsm_network_api.h" + +/* Host parameter */ +#define CONN_HOST "example.com" +#define CONN_PORT 80 + +static lwgsmr_t conn_callback_func(lwgsm_evt_t* evt); + +/** + * \brief Request data for connection + */ +static const +uint8_t req_data[] = "" + "GET / HTTP/1.1\r\n" + "Host: " CONN_HOST "\r\n" + "Connection: close\r\n" + "\r\n"; + +/** + * \brief Start a new connection(s) as client + */ +void +client_connect(void) { + lwgsmr_t res; + + /* Attach to GSM network */ + lwgsm_network_request_attach(); + + /* Start a new connection as client in non-blocking mode */ + if ((res = lwgsm_conn_start(NULL, LWGSM_CONN_TYPE_TCP, "example.com", 80, NULL, conn_callback_func, 0)) == lwgsmOK) { + printf("Connection to " CONN_HOST " started...\r\n"); + } else { + printf("Cannot start connection to " CONN_HOST "!\r\n"); + } +} + +/** + * \brief Event callback function for connection-only + * \param[in] evt: Event information with data + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +static lwgsmr_t +conn_callback_func(lwgsm_evt_t* evt) { + lwgsm_conn_p conn; + lwgsmr_t res; + uint8_t conn_num; + + conn = lwgsm_conn_get_from_evt(evt); /* Get connection handle from event */ + if (conn == NULL) { + return lwgsmERR; + } + conn_num = lwgsm_conn_getnum(conn); /* Get connection number for identification */ + switch (lwgsm_evt_get_type(evt)) { + case LWGSM_EVT_CONN_ACTIVE: { /* Connection just active */ + printf("Connection %d active!\r\n", (int)conn_num); + res = lwgsm_conn_send(conn, req_data, sizeof(req_data) - 1, NULL, 0); /* Start sending data in non-blocking mode */ + if (res == lwgsmOK) { + printf("Sending request data to server...\r\n"); + } else { + printf("Cannot send request data to server. Closing connection manually...\r\n"); + lwgsm_conn_close(conn, 0); /* Close the connection */ + } + break; + } + case LWGSM_EVT_CONN_CLOSE: { /* Connection closed */ + if (lwgsm_evt_conn_close_is_forced(evt)) { + printf("Connection %d closed by client!\r\n", (int)conn_num); + } else { + printf("Connection %d closed by remote side!\r\n", (int)conn_num); + } + break; + } + case LWGSM_EVT_CONN_SEND: { /* Data send event */ + lwgsmr_t res = lwgsm_evt_conn_send_get_result(evt); + if (res == lwgsmOK) { + printf("Data sent successfully on connection %d...waiting to receive data from remote side...\r\n", (int)conn_num); + } else { + printf("Error while sending data on connection %d!\r\n", (int)conn_num); + } + break; + } + case LWGSM_EVT_CONN_RECV: { /* Data received from remote side */ + lwgsm_pbuf_p pbuf = lwgsm_evt_conn_recv_get_buff(evt); + lwgsm_conn_recved(conn, pbuf); /* Notify stack about received pbuf */ + printf("Received %d bytes on connection %d..\r\n", (int)lwgsm_pbuf_length(pbuf, 1), (int)conn_num); + break; + } + case LWGSM_EVT_CONN_ERROR: { /* Error connecting to server */ + const char* host = lwgsm_evt_conn_error_get_host(evt); + lwgsm_port_t port = lwgsm_evt_conn_error_get_port(evt); + printf("Error connecting to %s:%d\r\n", host, (int)port); + break; + } + default: + break; + } + return lwgsmOK; +} diff --git a/snippets/device_info.c b/snippets/device_info.c new file mode 100644 index 00000000..47376be9 --- /dev/null +++ b/snippets/device_info.c @@ -0,0 +1,33 @@ +/* + * Read device information + */ +#include "lwgsm/lwgsm.h" + +/** + * \brief Device info string array + */ +static char dev_str[20]; + +/** + * \brief Start SMS send receive procedure + */ +void +read_device_info(void) { + /* Read information */ + + /* Read device manufacturer */ + lwgsm_device_get_manufacturer(dev_str, sizeof(dev_str), NULL, NULL, 1); + printf("Manuf: %s\r\n", dev_str); + + /* Read device model */ + lwgsm_device_get_model(dev_str, sizeof(dev_str), NULL, NULL, 1); + printf("Model: %s\r\n", dev_str); + + /* Read device serial number */ + lwgsm_device_get_serial_number(dev_str, sizeof(dev_str), NULL, NULL, 1); + printf("Serial: %s\r\n", dev_str); + + /* Read device revision */ + lwgsm_device_get_revision(dev_str, sizeof(dev_str), NULL, NULL, 1); + printf("Revision: %s\r\n", dev_str); +} diff --git a/snippets/include/call.h b/snippets/include/call.h new file mode 100644 index 00000000..51456513 --- /dev/null +++ b/snippets/include/call.h @@ -0,0 +1,14 @@ +#ifndef SNIPPET_HDR_CALL_H +#define SNIPPET_HDR_CALL_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void call_start(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SNIPPET_HDR_CALL_H */ diff --git a/snippets/include/call_sms.h b/snippets/include/call_sms.h new file mode 100644 index 00000000..2ff99aba --- /dev/null +++ b/snippets/include/call_sms.h @@ -0,0 +1,14 @@ +#ifndef SNIPPET_HDR_CALL_SMS_H +#define SNIPPET_HDR_CALL_SMS_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void call_sms_start(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SNIPPET_HDR_CALL_SMS_H */ diff --git a/snippets/include/client.h b/snippets/include/client.h new file mode 100644 index 00000000..eb1d40ff --- /dev/null +++ b/snippets/include/client.h @@ -0,0 +1,14 @@ +#ifndef SNIPPET_HDR_CLIENT_H +#define SNIPPET_HDR_CLIENT_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void client_connect(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SNIPPET_HDR_CLIENT_H */ diff --git a/snippets/include/device_info.h b/snippets/include/device_info.h new file mode 100644 index 00000000..0bf1de1d --- /dev/null +++ b/snippets/include/device_info.h @@ -0,0 +1,14 @@ +#ifndef SNIPPET_HDR_DEVICE_INFO_H +#define SNIPPET_HDR_DEVICE_INFO_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void read_device_info(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SNIPPET_HDR_DEVICE_INFO_H */ diff --git a/snippets/include/mqtt_client_api.h b/snippets/include/mqtt_client_api.h index 16d6e679..efacd6a8 100644 --- a/snippets/include/mqtt_client_api.h +++ b/snippets/include/mqtt_client_api.h @@ -1,14 +1,14 @@ -#ifndef __MQTT_CLIENT_API_H -#define __MQTT_CLIENT_API_H +#ifndef SNIPPET_HDR_MQTT_CLIENT_API_H +#define SNIPPET_HDR_MQTT_CLIENT_API_H #ifdef __cplusplus extern "C" { -#endif +#endif /* __cplusplus */ void mqtt_client_api_thread(void const* arg); #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif +#endif /* SNIPPET_HDR_MQTT_CLIENT_API_H */ diff --git a/snippets/include/netconn_client.h b/snippets/include/netconn_client.h index f07e5402..a6e9d7d5 100644 --- a/snippets/include/netconn_client.h +++ b/snippets/include/netconn_client.h @@ -1,14 +1,14 @@ -#ifndef __NETCONN_CLIENT_H -#define __NETCONN_CLIENT_H +#ifndef SNIPPET_HDR_NETCONN_CLIENT_H +#define SNIPPET_HDR_NETCONN_CLIENT_H #ifdef __cplusplus extern "C" { -#endif +#endif /* __cplusplus */ void netconn_client_thread(void const* arg); #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif +#endif /* SNIPPET_HDR_NETCONN_CLIENT_H */ diff --git a/snippets/include/network_apn_settings.h b/snippets/include/network_apn_settings.h index 781e3282..26e35723 100644 --- a/snippets/include/network_apn_settings.h +++ b/snippets/include/network_apn_settings.h @@ -1,9 +1,11 @@ -#ifndef __NETWORK_APN_SETTINGS_H -#define __NETWORK_APN_SETTINGS_H +#ifndef SNIPPET_HDR_NETWORK_APN_SETTINGS_H +#define SNIPPET_HDR_NETWORK_APN_SETTINGS_H + +#include "lwgsm/lwgsm_network_api.h" #ifdef __cplusplus extern "C" { -#endif +#endif /* __cplusplus */ /* APN settings to attach to network */ #define NETWORK_APN "internet" @@ -12,6 +14,6 @@ extern "C" { #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif +#endif /* SNIPPET_HDR_NETWORK_APN_SETTINGS_H */ diff --git a/snippets/include/network_utils.h b/snippets/include/network_utils.h index a90f20ba..b567a939 100644 --- a/snippets/include/network_utils.h +++ b/snippets/include/network_utils.h @@ -1,19 +1,19 @@ -#ifndef __NETWORK_UTILS_H -#define __NETWORK_UTILS_H +#ifndef SNIPPET_HDR_NETWORK_UTILS_H +#define SNIPPET_HDR_NETWORK_UTILS_H + +#include +#include "lwgsm/lwgsm.h" #ifdef __cplusplus extern "C" { -#endif - -#include -#include "gsm/gsm.h" +#endif /* __cplusplus */ -void network_utils_process_reg_change(gsm_evt_t* evt); -void network_utils_process_curr_operator(gsm_evt_t* evt); -void network_utils_process_rssi(gsm_evt_t* evt); +void network_utils_process_reg_change(lwgsm_evt_t* evt); +void network_utils_process_curr_operator(lwgsm_evt_t* evt); +void network_utils_process_rssi(lwgsm_evt_t* evt); #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif +#endif /* SNIPPET_HDR_NETWORK_UTILS_H */ diff --git a/snippets/include/sim_manager.h b/snippets/include/sim_manager.h index 5f9b283b..3a3596ed 100644 --- a/snippets/include/sim_manager.h +++ b/snippets/include/sim_manager.h @@ -1,16 +1,16 @@ -#ifndef __SIM_MANAGER_H -#define __SIM_MANAGER_H +#ifndef SNIPPET_HDR_SIM_MANAGER_H +#define SNIPPET_HDR_SIM_MANAGER_H + +#include #ifdef __cplusplus extern "C" { -#endif - -#include +#endif /* __cplusplus */ uint8_t configure_sim_card(void); #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif +#endif /* SNIPPET_HDR_SIM_MANAGER_H */ diff --git a/snippets/include/sms_send_receive.h b/snippets/include/sms_send_receive.h index 0af5e0bb..09fea5f4 100644 --- a/snippets/include/sms_send_receive.h +++ b/snippets/include/sms_send_receive.h @@ -1,14 +1,14 @@ -#ifndef __SMS_SEND_RECEIVE_H -#define __SMS_SEND_RECEIVE_H +#ifndef SNIPPET_HDR_SMS_SEND_RECEIVE_H +#define SNIPPET_HDR_SMS_SEND_RECEIVE_H #ifdef __cplusplus extern "C" { -#endif +#endif /* __cplusplus */ -void sms_send_receive_thread(void const* arg); +void sms_send_receive_start(void); #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif +#endif /* SNIPPET_HDR_SMS_SEND_RECEIVE_H */ diff --git a/snippets/include/sms_send_receive_thread.h b/snippets/include/sms_send_receive_thread.h new file mode 100644 index 00000000..4bbfd7b6 --- /dev/null +++ b/snippets/include/sms_send_receive_thread.h @@ -0,0 +1,14 @@ +#ifndef SNIPPET_HDR_SMS_SEND_RECEIVE_THREAD_H +#define SNIPPET_HDR_SMS_SEND_RECEIVE_THREAD_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void sms_send_receive_thread(void const* arg); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SNIPPET_HDR_SMS_SEND_RECEIVE_THREAD_H */ diff --git a/snippets/mqtt_client_api.c b/snippets/mqtt_client_api.c index 40bdb1d5..a303c362 100644 --- a/snippets/mqtt_client_api.c +++ b/snippets/mqtt_client_api.c @@ -4,21 +4,21 @@ * Once device is connected to network, * it will try to connect to mosquitto test server and start the MQTT. * - * If successfully connected, it will publish data to "gsm_mqtt_topic" topic every x seconds. + * If successfully connected, it will publish data to "lwgsm_mqtt_topic" topic every x seconds. * * To check if data are sent, you can use mqtt-spy PC software to inspect * test.mosquitto.org server and subscribe to publishing topic */ -#include "gsm/apps/gsm_mqtt_client_api.h" +#include "lwgsm/apps/lwgsm_mqtt_client_api.h" #include "mqtt_client_api.h" -#include "gsm/gsm_mem.h" -#include "gsm/gsm_network_api.h" +#include "lwgsm/lwgsm_mem.h" +#include "lwgsm/lwgsm_network_api.h" /** * \brief Connection information for MQTT CONNECT packet */ -static const gsm_mqtt_client_info_t +static const lwgsm_mqtt_client_info_t mqtt_client_info = { .keep_alive = 10, @@ -52,19 +52,19 @@ generate_random(char* str) { */ void mqtt_client_api_thread(void const* arg) { - gsm_mqtt_client_api_p client; - gsm_mqtt_conn_status_t conn_status; - gsm_mqtt_client_api_buf_p buf; - gsmr_t res; + lwgsm_mqtt_client_api_p client; + lwgsm_mqtt_conn_status_t conn_status; + lwgsm_mqtt_client_api_buf_p buf; + lwgsmr_t res; char random_str[10]; /* Request network attach */ - while (gsm_network_request_attach() != gsmOK) { - gsm_delay(1000); + while (lwgsm_network_request_attach() != lwgsmOK) { + lwgsm_delay(1000); } /* Create new MQTT API */ - client = gsm_mqtt_client_api_new(256, 128); + client = lwgsm_mqtt_client_api_new(256, 128); if (client == NULL) { goto terminate; } @@ -74,19 +74,19 @@ mqtt_client_api_thread(void const* arg) { printf("Joining MQTT server\r\n"); /* Try to join */ - conn_status = gsm_mqtt_client_api_connect(client, "mqtt.mydevices.com", 1883, &mqtt_client_info); - if (conn_status == GSM_MQTT_CONN_STATUS_ACCEPTED) { + conn_status = lwgsm_mqtt_client_api_connect(client, "mqtt.mydevices.com", 1883, &mqtt_client_info); + if (conn_status == LWGSM_MQTT_CONN_STATUS_ACCEPTED) { printf("Connected and accepted!\r\n"); printf("Client is ready to subscribe and publish to new messages\r\n"); } else { printf("Connect API response: %d\r\n", (int)conn_status); - gsm_delay(5000); + lwgsm_delay(5000); continue; } /* Subscribe to topics */ sprintf(mqtt_topic_str, "v1/%s/things/%s/cmd/#", mqtt_client_info.user, mqtt_client_info.id); - if (gsm_mqtt_client_api_subscribe(client, mqtt_topic_str, GSM_MQTT_QOS_AT_LEAST_ONCE) == gsmOK) { + if (lwgsm_mqtt_client_api_subscribe(client, mqtt_topic_str, LWGSM_MQTT_QOS_AT_LEAST_ONCE) == lwgsmOK) { printf("Subscribed to topic\r\n"); } else { printf("Problem subscribing to topic!\r\n"); @@ -94,32 +94,32 @@ mqtt_client_api_thread(void const* arg) { while (1) { /* Receive MQTT packet with 1000ms timeout */ - res = gsm_mqtt_client_api_receive(client, &buf, 5000); - if (res == gsmOK) { + res = lwgsm_mqtt_client_api_receive(client, &buf, 5000); + if (res == lwgsmOK) { if (buf != NULL) { printf("Publish received!\r\n"); printf("Topic: %s, payload: %s\r\n", buf->topic, buf->payload); - gsm_mqtt_client_api_buf_free(buf); + lwgsm_mqtt_client_api_buf_free(buf); buf = NULL; } - } else if (res == gsmCLOSED) { + } else if (res == lwgsmCLOSED) { printf("MQTT connection closed!\r\n"); break; - } else if (res == gsmTIMEOUT) { + } else if (res == lwgsmTIMEOUT) { printf("Timeout on MQTT receive function. Manually publishing.\r\n"); /* Publish data on channel 1 */ generate_random(random_str); sprintf(mqtt_topic_str, "v1/%s/things/%s/data/1", mqtt_client_info.user, mqtt_client_info.id); - gsm_mqtt_client_api_publish(client, mqtt_topic_str, random_str, strlen(random_str), GSM_MQTT_QOS_AT_LEAST_ONCE, 0); + lwgsm_mqtt_client_api_publish(client, mqtt_topic_str, random_str, strlen(random_str), LWGSM_MQTT_QOS_AT_LEAST_ONCE, 0); } } goto terminate; } -terminate: - gsm_mqtt_client_api_delete(client); - gsm_network_request_detach(); +terminate: + lwgsm_mqtt_client_api_delete(client); + lwgsm_network_request_detach(); printf("MQTT client thread terminate\r\n"); - gsm_sys_thread_terminate(NULL); + lwgsm_sys_thread_terminate(NULL); } diff --git a/snippets/netconn_client.c b/snippets/netconn_client.c index 80026583..743c1d45 100644 --- a/snippets/netconn_client.c +++ b/snippets/netconn_client.c @@ -1,8 +1,8 @@ #include "netconn_client.h" -#include "gsm/gsm.h" -#include "gsm/gsm_network_api.h" +#include "lwgsm/lwgsm.h" +#include "lwgsm/lwgsm_network_api.h" -#if GSM_CFG_NETCONN +#if LWGSM_CFG_NETCONN /** * \brief Host and port settings @@ -15,10 +15,10 @@ */ static const char request_header[] = "" -"GET / HTTP/1.1\r\n" -"Host: " NETCONN_HOST "\r\n" -"Connection: close\r\n" -"\r\n"; + "GET / HTTP/1.1\r\n" + "Host: " NETCONN_HOST "\r\n" + "Connection: close\r\n" + "\r\n"; /** * \brief Netconn client thread implementation @@ -26,14 +26,14 @@ request_header[] = "" */ void netconn_client_thread(void const* arg) { - gsmr_t res; - gsm_pbuf_p pbuf; - gsm_netconn_p client; - gsm_sys_sem_t* sem = (void *)arg; + lwgsmr_t res; + lwgsm_pbuf_p pbuf; + lwgsm_netconn_p client; + lwgsm_sys_sem_t* sem = (void*)arg; /* Request attach to network */ - while (gsm_network_request_attach() != gsmOK) { - gsm_delay(1000); + while (lwgsm_network_request_attach() != lwgsmOK) { + lwgsm_delay(1000); } /* @@ -41,7 +41,7 @@ netconn_client_thread(void const* arg) { * connection and initialize system message boxes * to accept received packet buffers */ - client = gsm_netconn_new(GSM_NETCONN_TYPE_TCP); + client = lwgsm_netconn_new(LWGSM_NETCONN_TYPE_TCP); if (client != NULL) { /* * Connect to external server as client @@ -49,14 +49,14 @@ netconn_client_thread(void const* arg) { * * Function will block thread until we are successfully connected (or not) to server */ - res = gsm_netconn_connect(client, NETCONN_HOST, NETCONN_PORT); - if (res == gsmOK) { /* Are we successfully connected? */ + res = lwgsm_netconn_connect(client, NETCONN_HOST, NETCONN_PORT); + if (res == lwgsmOK) { /* Are we successfully connected? */ printf("Connected to " NETCONN_HOST "\r\n"); - res = gsm_netconn_write(client, request_header, sizeof(request_header) - 1); /* Send data to server */ - if (res == gsmOK) { - res = gsm_netconn_flush(client);/* Flush data to output */ + res = lwgsm_netconn_write(client, request_header, sizeof(request_header) - 1); /* Send data to server */ + if (res == lwgsmOK) { + res = lwgsm_netconn_flush(client);/* Flush data to output */ } - if (res == gsmOK) { /* Were data sent? */ + if (res == lwgsmOK) { /* Were data sent? */ printf("Data were successfully sent to server\r\n"); /* @@ -75,15 +75,15 @@ netconn_client_thread(void const* arg) { * Returned status will give you info in case connection * was closed too early from remote side */ - res = gsm_netconn_receive(client, &pbuf); - if (res == gsmCLOSED) { /* Was the connection closed? This can be checked by return status of receive function */ + res = lwgsm_netconn_receive(client, &pbuf); + if (res == lwgsmCLOSED) { /* Was the connection closed? This can be checked by return status of receive function */ printf("Connection closed by remote side...\r\n"); break; - } else if (res == gsmTIMEOUT) { + } else if (res == lwgsmTIMEOUT) { printf("Netconn timeout while receiving data. You may try multiple readings before deciding to close manually\r\n"); } - if (res == gsmOK && pbuf != NULL) { /* Make sure we have valid packet buffer */ + if (res == lwgsmOK && pbuf != NULL) { /* Make sure we have valid packet buffer */ /* * At this point read and manipulate * with received buffer and check if you expect more data @@ -91,8 +91,8 @@ netconn_client_thread(void const* arg) { * After you are done using it, it is important * you free the memory otherwise memory leaks will appear */ - printf("Received new data packet of %d bytes\r\n", (int)gsm_pbuf_length(pbuf, 1)); - gsm_pbuf_free(pbuf); /* Free the memory after usage */ + printf("Received new data packet of %d bytes\r\n", (int)lwgsm_pbuf_length(pbuf, 1)); + lwgsm_pbuf_free(pbuf); /* Free the memory after usage */ pbuf = NULL; } } while (1); @@ -104,20 +104,20 @@ netconn_client_thread(void const* arg) { * Check if connection was closed by remote server * and in case it wasn't, close it manually */ - if (res != gsmCLOSED) { - gsm_netconn_close(client); + if (res != lwgsmCLOSED) { + lwgsm_netconn_close(client); } } else { printf("Cannot connect to remote host %s:%d!\r\n", NETCONN_HOST, NETCONN_PORT); } - gsm_netconn_delete(client); /* Delete netconn structure */ + lwgsm_netconn_delete(client); /* Delete netconn structure */ } - gsm_network_request_detach(); /* Detach from network */ + lwgsm_network_request_detach(); /* Detach from network */ - if (gsm_sys_sem_isvalid(sem)) { - gsm_sys_sem_release(sem); + if (lwgsm_sys_sem_isvalid(sem)) { + lwgsm_sys_sem_release(sem); } - gsm_sys_thread_terminate(NULL); /* Terminate current thread */ + lwgsm_sys_thread_terminate(NULL); /* Terminate current thread */ } -#endif /* GSM_CFG_NETCONN */ +#endif /* LWGSM_CFG_NETCONN */ diff --git a/snippets/network_utils.c b/snippets/network_utils.c index cb3c05d0..aadc468e 100644 --- a/snippets/network_utils.c +++ b/snippets/network_utils.c @@ -1,5 +1,5 @@ #include "network_utils.h" -#include "gsm/gsm.h" +#include "lwgsm/lwgsm.h" /** * \brief RSSI state on network @@ -12,22 +12,31 @@ rssi; * \param[in] evt: GSM event data */ void -network_utils_process_reg_change(gsm_evt_t* evt) { - gsm_network_reg_status_t stat; +network_utils_process_reg_change(lwgsm_evt_t* evt) { + lwgsm_network_reg_status_t stat; - stat = gsm_network_get_reg_status(); /* Get network status */ + stat = lwgsm_network_get_reg_status(); /* Get network status */ /* Print to console */ printf("Network registration status changed. New status is: "); switch (stat) { - case GSM_NETWORK_REG_STATUS_CONNECTED: printf("Connected to home network!\r\n"); break; - case GSM_NETWORK_REG_STATUS_CONNECTED_ROAMING: printf("Connected to network and roaming!\r\n"); break; - case GSM_NETWORK_REG_STATUS_SEARCHING: printf("Searching for network!\r\n"); break; - case GSM_NETWORK_REG_STATUS_SIM_ERR: printf("SIM CARD ERROR!\r\n"); break; - default: printf("Other\r\n"); + case LWGSM_NETWORK_REG_STATUS_CONNECTED: + printf("Connected to home network!\r\n"); + break; + case LWGSM_NETWORK_REG_STATUS_CONNECTED_ROAMING: + printf("Connected to network and roaming!\r\n"); + break; + case LWGSM_NETWORK_REG_STATUS_SEARCHING: + printf("Searching for network!\r\n"); + break; + case LWGSM_NETWORK_REG_STATUS_SIM_ERR: + printf("SIM CARD ERROR!\r\n"); + break; + default: + printf("Other\r\n"); } - GSM_UNUSED(evt); + LWGSM_UNUSED(evt); } /** @@ -35,31 +44,38 @@ network_utils_process_reg_change(gsm_evt_t* evt) { * \param[in] evt: GSM event data */ void -network_utils_process_curr_operator(gsm_evt_t* evt) { - const gsm_operator_curr_t* o; - o = gsm_evt_network_operator_get_current(evt); +network_utils_process_curr_operator(lwgsm_evt_t* evt) { + const lwgsm_operator_curr_t* o; + o = lwgsm_evt_network_operator_get_current(evt); if (o != NULL) { switch (o->format) { - case GSM_OPERATOR_FORMAT_LONG_NAME: printf("Operator long name: %s\r\n", o->data.long_name); break; - case GSM_OPERATOR_FORMAT_SHORT_NAME: printf("Operator short name: %s\r\n", o->data.short_name); break; - case GSM_OPERATOR_FORMAT_NUMBER: printf("Operator number: %d\r\n", (int)o->data.num); break; - default: break; + case LWGSM_OPERATOR_FORMAT_LONG_NAME: + printf("Operator long name: %s\r\n", o->data.long_name); + break; + case LWGSM_OPERATOR_FORMAT_SHORT_NAME: + printf("Operator short name: %s\r\n", o->data.short_name); + break; + case LWGSM_OPERATOR_FORMAT_NUMBER: + printf("Operator number: %d\r\n", (int)o->data.num); + break; + default: + break; } } /* Start RSSI info */ - gsm_network_rssi(&rssi, NULL, NULL, 0); + lwgsm_network_rssi(&rssi, NULL, NULL, 0); } -/** +/** * \brief Process and print RSSI info * \param[in] evt: GSM event data */ void -network_utils_process_rssi(gsm_evt_t* evt) { +network_utils_process_rssi(lwgsm_evt_t* evt) { int16_t rssi; /* Get RSSi from event */ - rssi = gsm_evt_signal_strength_get_rssi(evt); + rssi = lwgsm_evt_signal_strength_get_rssi(evt); /* Print message to screen */ printf("Network operator RSSI: %d dBm\r\n", (int)rssi); diff --git a/snippets/sim_manager.c b/snippets/sim_manager.c index c43a16cb..162f76aa 100644 --- a/snippets/sim_manager.c +++ b/snippets/sim_manager.c @@ -1,17 +1,17 @@ #include "sim_manager.h" -#include "gsm/gsm.h" +#include "lwgsm/lwgsm.h" /** * \brief SIM card pin code */ -static const char * -pin_code = "7600"; +static const char* +pin_code = "7958"; /** * \brief SIM card puk code */ -static const char * -puk_code = "08475703"; +static const char* +puk_code = "10663647"; /** * \brief Configure and enable SIM card @@ -19,9 +19,9 @@ puk_code = "08475703"; */ uint8_t configure_sim_card(void) { - GSM_UNUSED(puk_code); + LWGSM_UNUSED(puk_code); if (pin_code != NULL && strlen(pin_code)) { - if (gsm_sim_pin_enter(pin_code, NULL, NULL, 1) == gsmOK) { + if (lwgsm_sim_pin_enter(pin_code, NULL, NULL, 1) == lwgsmOK) { return 1; } return 0; diff --git a/snippets/sms_send_receive.c b/snippets/sms_send_receive.c index 8bb9bfb0..1026bd5a 100644 --- a/snippets/sms_send_receive.c +++ b/snippets/sms_send_receive.c @@ -1,138 +1,107 @@ /* - * SMS send and receive thread. + * SMS send and receive basic event based example * * Waits for received SMS and then replies with */ - #include "sms_send_receive.h" -#include "gsm/gsm.h" -#include "gsm/gsm_mem.h" +#include "lwgsm/lwgsm.h" -static gsmr_t sms_evt_func(gsm_evt_t* evt); +#if !LWGSM_CFG_SMS +#error "SMS must be enabled to run this example" +#endif /* !LWGSM_CFG_SMS */ -/** - * \brief SMS entry information - */ -typedef struct { - gsm_mem_t mem; - size_t pos; -} sms_receive_t; +static lwgsmr_t sms_evt_func(lwgsm_evt_t* evt); /** - * \brief SMS message box + * \brief SMS entry */ -static gsm_sys_mbox_t -sms_mbox; - -/** - * \brief SMS read entry - */ -static gsm_sms_entry_t +static lwgsm_sms_entry_t sms_entry; /** - * \brief SMS Receive Send thread function + * \brief Start SMS send receive procedure */ void -sms_send_receive_thread(void const* arg) { - sms_receive_t* sms; - - /* Create message box */ - if (!gsm_sys_mbox_create(&sms_mbox, 5)) { - goto terminate; - } - - /* Register callback function for SMS */ - if (gsm_evt_register(sms_evt_func) != gsmOK) { - goto terminate; - } - - /* User can start now */ - printf("Start by sending first SMS to device...\r\n"); - - while (1) { - /* Get SMS entry from message queue */ - while (gsm_sys_mbox_get(&sms_mbox, (void **)&sms, 0) == GSM_SYS_TIMEOUT || sms == NULL) {} - - /* We have new SMS now */ - printf("New SMS received!\r\n"); - - /* Read SMS from device */ - if (gsm_sms_read(sms->mem, sms->pos, &sms_entry, 1, NULL, NULL, 1) == gsmOK) { - printf("SMS read ok. Number: %s, content: %s\r\n", sms_entry.number, sms_entry.data); - - /* Send reply back */ - if (gsm_sms_send(sms_entry.number, sms_entry.data, NULL, NULL, 1) == gsmOK) { - printf("SMS sent back successfully!\r\n"); - } else { - printf("Cannot send SMS back!\r\n"); - } - - /* Delete SMS from device memory */ - if (gsm_sms_delete(sms->mem, sms->pos, NULL, NULL, 1) == gsmOK) { - printf("Received SMS deleted!\r\n"); - } else { - printf("Cannot delete received SMS!\r\n"); - } - } else { - printf("Cannot read SMS!\r\n"); - } - - /* Now free the memory */ - gsm_mem_free_s((void **)&sms); - } - -terminate: - if (gsm_sys_mbox_isvalid(&sms_mbox)) { - /* Lock to make sure GSM stack won't process any callbacks while we are cleaning */ - gsm_core_lock(); - - /* Clean mbox first */ - while (gsm_sys_mbox_getnow(&sms_mbox, (void **)&sms)) { - gsm_mem_free_s((void **)&sms); - } - - /* Delete mbox */ - gsm_sys_mbox_delete(&sms_mbox); - gsm_sys_mbox_invalid(&sms_mbox); - - gsm_core_unlock(); +sms_send_receive_start(void) { + /* Add custom callback */ + lwgsm_evt_register(sms_evt_func); + + /* First enable SMS functionality */ + if (lwgsm_sms_enable(NULL, NULL, 1) == lwgsmOK) { + printf("SMS enabled. Send new SMS from your phone to device.\r\n"); + } else { + printf("Cannot enable SMS functionality!\r\n"); + } - /* Now mbox is not valid anymore and event won't write any data */ - } + /* Now send SMS from phone to device */ + printf("Start by sending SMS message to device...\r\n"); } /** * \brief Event function for received SMS * \param[in] evt: GSM event - * \return \ref gsmOK on success, member of \ref gsmr_t otherwise + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise */ -static gsmr_t -sms_evt_func(gsm_evt_t* evt) { - switch (gsm_evt_get_type(evt)) { - case GSM_EVT_SMS_RECV: { /* New SMS received indicator */ - uint8_t success = 0; - sms_receive_t* sms_rx = gsm_mem_malloc(sizeof(*sms_rx)); - if (sms_rx != NULL) { - sms_rx->mem = gsm_evt_sms_recv_get_mem(evt); - sms_rx->pos = gsm_evt_sms_recv_get_pos(evt); +static lwgsmr_t +sms_evt_func(lwgsm_evt_t* evt) { + switch (lwgsm_evt_get_type(evt)) { + case LWGSM_EVT_SMS_READY: { /* SMS is ready notification from device */ + printf("SIM device SMS service is ready!\r\n"); + break; + } + case LWGSM_EVT_SMS_RECV: { /* New SMS received indicator */ + lwgsmr_t res; - /* Write to receive queue */ - if (!gsm_sys_mbox_isvalid(&sms_mbox) || !gsm_sys_mbox_putnow(&sms_mbox, sms_rx)) { - gsm_mem_free_s((void **)&sms_rx); + printf("New SMS received!\r\n"); /* Notify user */ + + /* Try to read SMS */ + res = lwgsm_sms_read(lwgsm_evt_sms_recv_get_mem(evt), lwgsm_evt_sms_recv_get_pos(evt), &sms_entry, 1, NULL, NULL, 0); + if (res == lwgsmOK) { + printf("SMS read in progress!\r\n"); + } else { + printf("Cannot start SMS read procedure!\r\n"); + } + break; + } + case LWGSM_EVT_SMS_READ: { /* SMS read event */ + lwgsm_sms_entry_t* entry = lwgsm_evt_sms_read_get_entry(evt); + if (lwgsm_evt_sms_read_get_result(evt) == lwgsmOK && entry != NULL) { + /* Print SMS data */ + printf("SMS read. From: %s, content: %s\r\n", + entry->number, entry->data + ); + + /* Try to send SMS back */ + if (lwgsm_sms_send(entry->number, entry->data, NULL, NULL, 0) == lwgsmOK) { + printf("SMS send in progress!\r\n"); } else { - success = 1; + printf("Cannot start SMS send procedure!\r\n"); } - } - /* Force SMS delete if not written successfully */ - if (!success) { - gsm_sms_delete(gsm_evt_sms_recv_get_mem(evt), gsm_evt_sms_recv_get_pos(evt), NULL, NULL, 0); + /* Delete SMS from device memory */ + lwgsm_sms_delete(entry->mem, entry->pos, NULL, NULL, 0); + } + break; + } + case LWGSM_EVT_SMS_SEND: { /* SMS send event */ + if (lwgsm_evt_sms_send_get_result(evt) == lwgsmOK) { + printf("SMS has been successfully sent!\r\n"); + } else { + printf("SMS has not been sent successfully!\r\n"); } break; } - default: break; + case LWGSM_EVT_SMS_DELETE: { /* SMS delete event */ + if (lwgsm_evt_sms_delete_get_result(evt) == lwgsmOK) { + printf("SMS deleted, memory position: %d\r\n", (int)lwgsm_evt_sms_delete_get_pos(evt)); + } else { + printf("SMS delete operation failed!\r\n"); + } + break; + } + default: + break; } - return gsmOK; + return lwgsmOK; } diff --git a/snippets/sms_send_receive_thread.c b/snippets/sms_send_receive_thread.c new file mode 100644 index 00000000..1a0db1f8 --- /dev/null +++ b/snippets/sms_send_receive_thread.c @@ -0,0 +1,152 @@ +/* + * SMS send and receive thread. + * + * Waits for received SMS and then replies with + */ +#include "sms_send_receive_thread.h" +#include "lwgsm/lwgsm.h" +#include "lwgsm/lwgsm_mem.h" + +#if !LWGSM_CFG_SMS +#error "SMS must be enabled to run this example" +#endif /* !LWGSM_CFG_SMS */ + +static lwgsmr_t sms_evt_func(lwgsm_evt_t* evt); + +/** + * \brief SMS entry information + */ +typedef struct { + lwgsm_mem_t mem; + size_t pos; +} sms_receive_t; + +/** + * \brief SMS message box + */ +static lwgsm_sys_mbox_t +sms_mbox; + +/** + * \brief SMS read entry + */ +static lwgsm_sms_entry_t +sms_entry; + +/** + * \brief SMS Receive Send thread function + */ +void +sms_send_receive_thread(void const* arg) { + sms_receive_t* sms; + + /* Create message box */ + if (!lwgsm_sys_mbox_create(&sms_mbox, 5)) { + goto terminate; + } + + /* Register callback function for SMS */ + if (lwgsm_evt_register(sms_evt_func) != lwgsmOK) { + goto terminate; + } + + /* First enable SMS functionality */ + if (lwgsm_sms_enable(NULL, NULL, 1) == lwgsmOK) { + printf("SMS enabled. Send new SMS from your phone to device.\r\n"); + } else { + printf("Cannot enable SMS functionality!\r\n"); + while (1) { + lwgsm_delay(1000); + } + } + + /* User can start now */ + printf("Start by sending first SMS to device...\r\n"); + + while (1) { + /* Get SMS entry from message queue */ + while (lwgsm_sys_mbox_get(&sms_mbox, (void**)&sms, 0) == LWGSM_SYS_TIMEOUT || sms == NULL) {} + + /* We have new SMS now */ + printf("New SMS received!\r\n"); + + /* Read SMS from device */ + if (lwgsm_sms_read(sms->mem, sms->pos, &sms_entry, 1, NULL, NULL, 1) == lwgsmOK) { + printf("SMS read ok. Number: %s, content: %s\r\n", sms_entry.number, sms_entry.data); + + /* Send reply back */ + if (lwgsm_sms_send(sms_entry.number, sms_entry.data, NULL, NULL, 1) == lwgsmOK) { + printf("SMS sent back successfully!\r\n"); + } else { + printf("Cannot send SMS back!\r\n"); + } + + /* Delete SMS from device memory */ + if (lwgsm_sms_delete(sms->mem, sms->pos, NULL, NULL, 1) == lwgsmOK) { + printf("Received SMS deleted!\r\n"); + } else { + printf("Cannot delete received SMS!\r\n"); + } + } else { + printf("Cannot read SMS!\r\n"); + } + + /* Now free the memory */ + lwgsm_mem_free_s((void**)&sms); + } + +terminate: + if (lwgsm_sys_mbox_isvalid(&sms_mbox)) { + /* Lock to make sure GSM stack won't process any callbacks while we are cleaning */ + lwgsm_core_lock(); + + /* Clean mbox first */ + while (lwgsm_sys_mbox_getnow(&sms_mbox, (void**)&sms)) { + lwgsm_mem_free_s((void**)&sms); + } + + /* Delete mbox */ + lwgsm_sys_mbox_delete(&sms_mbox); + lwgsm_sys_mbox_invalid(&sms_mbox); + + lwgsm_core_unlock(); + + /* Now mbox is not valid anymore and event won't write any data */ + } +} + +/** + * \brief Event function for received SMS + * \param[in] evt: GSM event + * \return \ref lwgsmOK on success, member of \ref lwgsmr_t otherwise + */ +static lwgsmr_t +sms_evt_func(lwgsm_evt_t* evt) { + switch (lwgsm_evt_get_type(evt)) { + case LWGSM_EVT_SMS_RECV: { /* New SMS received indicator */ + uint8_t success = 0; + sms_receive_t* sms_rx = lwgsm_mem_malloc(sizeof(*sms_rx)); + if (sms_rx != NULL) { + sms_rx->mem = lwgsm_evt_sms_recv_get_mem(evt); + sms_rx->pos = lwgsm_evt_sms_recv_get_pos(evt); + + /* Write to receive queue */ + if (!lwgsm_sys_mbox_isvalid(&sms_mbox) || !lwgsm_sys_mbox_putnow(&sms_mbox, sms_rx)) { + lwgsm_mem_free_s((void**)&sms_rx); + } else { + success = 1; + } + } + + /* Force SMS delete if not written successfully */ + if (!success) { + lwgsm_sms_delete(lwgsm_evt_sms_recv_get_mem(evt), lwgsm_evt_sms_recv_get_pos(evt), NULL, NULL, 0); + } + break; + } + default: + break; + } + + return lwgsmOK; +} diff --git a/third_party/Embedded_Libs b/third_party/Embedded_Libs deleted file mode 160000 index fc5b3a0d..00000000 --- a/third_party/Embedded_Libs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fc5b3a0dc07107c63d3f2e6a5a6d31843b0606ca diff --git a/third_party/embedded-libs b/third_party/embedded-libs new file mode 160000 index 00000000..b92511a6 --- /dev/null +++ b/third_party/embedded-libs @@ -0,0 +1 @@ +Subproject commit b92511a69ee11f11efe3fb27adf53cf841291a5e