drivers: modem: gsm: Add support for GSM 07.10 muxing protocol
Instead of using physical UART to connection to the modem, use the GSM 07.10 muxing protocol and UART mux driver to create virtual channels to the modem. This will allow simultaneous PPP, AT and other type connections to the modem. Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
900c0e1c7f
commit
eb1ad99cff
2 changed files with 358 additions and 58 deletions
|
@ -11,6 +11,24 @@ config MODEM_GSM_PPP
|
||||||
|
|
||||||
if MODEM_GSM_PPP
|
if MODEM_GSM_PPP
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "Modem type"
|
||||||
|
default MODEM_GSM_GENERIC
|
||||||
|
help
|
||||||
|
Type/manufacturer of the GSM modem
|
||||||
|
|
||||||
|
config MODEM_GSM_GENERIC
|
||||||
|
bool "Generic GSM modem"
|
||||||
|
help
|
||||||
|
The modem does not need any special handling etc.
|
||||||
|
|
||||||
|
config MODEM_GSM_SIMCOM
|
||||||
|
bool "SIMCOM modem"
|
||||||
|
help
|
||||||
|
Use this if you have SIMCOM based modem like SIM800 etc.
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
config MODEM_GSM_UART_NAME
|
config MODEM_GSM_UART_NAME
|
||||||
string "UART device name the modem is connected to"
|
string "UART device name the modem is connected to"
|
||||||
|
|
||||||
|
|
|
@ -12,12 +12,14 @@ LOG_MODULE_REGISTER(modem_gsm, CONFIG_MODEM_LOG_LEVEL);
|
||||||
#include <sys/ring_buffer.h>
|
#include <sys/ring_buffer.h>
|
||||||
#include <sys/util.h>
|
#include <sys/util.h>
|
||||||
#include <net/ppp.h>
|
#include <net/ppp.h>
|
||||||
#include <drivers/console/uart_pipe.h>
|
|
||||||
#include <drivers/uart.h>
|
#include <drivers/uart.h>
|
||||||
|
#include <drivers/console/uart_pipe.h>
|
||||||
|
#include <drivers/console/uart_mux.h>
|
||||||
|
|
||||||
#include "modem_context.h"
|
#include "modem_context.h"
|
||||||
#include "modem_iface_uart.h"
|
#include "modem_iface_uart.h"
|
||||||
#include "modem_cmd_handler.h"
|
#include "modem_cmd_handler.h"
|
||||||
|
#include "../console/gsm_mux.h"
|
||||||
|
|
||||||
#define GSM_CMD_READ_BUF 128
|
#define GSM_CMD_READ_BUF 128
|
||||||
#define GSM_CMD_AT_TIMEOUT K_SECONDS(2)
|
#define GSM_CMD_AT_TIMEOUT K_SECONDS(2)
|
||||||
|
@ -27,6 +29,18 @@ LOG_MODULE_REGISTER(modem_gsm, CONFIG_MODEM_LOG_LEVEL);
|
||||||
#define GSM_RECV_BUF_SIZE 128
|
#define GSM_RECV_BUF_SIZE 128
|
||||||
#define GSM_BUF_ALLOC_TIMEOUT K_SECONDS(1)
|
#define GSM_BUF_ALLOC_TIMEOUT K_SECONDS(1)
|
||||||
|
|
||||||
|
/* During the modem setup, we first create DLCI control channel and then
|
||||||
|
* PPP and AT channels. Currently the modem does not create possible GNSS
|
||||||
|
* channel.
|
||||||
|
*/
|
||||||
|
enum setup_state {
|
||||||
|
STATE_INIT = 0,
|
||||||
|
STATE_CONTROL_CHANNEL = 0,
|
||||||
|
STATE_PPP_CHANNEL,
|
||||||
|
STATE_AT_CHANNEL,
|
||||||
|
STATE_DONE
|
||||||
|
};
|
||||||
|
|
||||||
static struct gsm_modem {
|
static struct gsm_modem {
|
||||||
struct modem_context context;
|
struct modem_context context;
|
||||||
|
|
||||||
|
@ -40,11 +54,19 @@ static struct gsm_modem {
|
||||||
char gsm_isr_buf[PPP_MRU];
|
char gsm_isr_buf[PPP_MRU];
|
||||||
char gsm_rx_rb_buf[PPP_MRU * 3];
|
char gsm_rx_rb_buf[PPP_MRU * 3];
|
||||||
|
|
||||||
bool setup_done;
|
|
||||||
u8_t *ppp_recv_buf;
|
u8_t *ppp_recv_buf;
|
||||||
size_t ppp_recv_buf_len;
|
size_t ppp_recv_buf_len;
|
||||||
uart_pipe_recv_cb ppp_recv_cb;
|
uart_pipe_recv_cb ppp_recv_cb;
|
||||||
struct k_sem ppp_send_sem;
|
struct k_sem ppp_send_sem;
|
||||||
|
|
||||||
|
enum setup_state state;
|
||||||
|
struct device *ppp_dev;
|
||||||
|
struct device *at_dev;
|
||||||
|
struct device *control_dev;
|
||||||
|
|
||||||
|
bool mux_enabled : 1;
|
||||||
|
bool mux_setup_done : 1;
|
||||||
|
bool setup_done : 1;
|
||||||
} gsm;
|
} gsm;
|
||||||
|
|
||||||
static size_t recv_buf_offset;
|
static size_t recv_buf_offset;
|
||||||
|
@ -64,32 +86,40 @@ static void gsm_rx(struct gsm_modem *gsm)
|
||||||
while (true) {
|
while (true) {
|
||||||
k_sem_take(&gsm->gsm_data.rx_sem, K_FOREVER);
|
k_sem_take(&gsm->gsm_data.rx_sem, K_FOREVER);
|
||||||
|
|
||||||
if (gsm->setup_done == false) {
|
if (gsm->mux_enabled == false) {
|
||||||
gsm->context.cmd_handler.process(
|
if (gsm->setup_done == false) {
|
||||||
|
gsm->context.cmd_handler.process(
|
||||||
&gsm->context.cmd_handler,
|
&gsm->context.cmd_handler,
|
||||||
&gsm->context.iface);
|
&gsm->context.iface);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gsm->ppp_recv_cb == NULL || gsm->ppp_recv_buf == NULL ||
|
if (gsm->ppp_recv_cb == NULL ||
|
||||||
gsm->ppp_recv_buf_len == 0) {
|
gsm->ppp_recv_buf == NULL ||
|
||||||
return;
|
gsm->ppp_recv_buf_len == 0) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
r = gsm->context.iface.read(
|
r = gsm->context.iface.read(
|
||||||
&gsm->context.iface,
|
&gsm->context.iface,
|
||||||
&gsm->ppp_recv_buf[recv_buf_offset],
|
&gsm->ppp_recv_buf[recv_buf_offset],
|
||||||
gsm->ppp_recv_buf_len -
|
gsm->ppp_recv_buf_len -
|
||||||
recv_buf_offset,
|
recv_buf_offset,
|
||||||
&bytes);
|
&bytes);
|
||||||
if (r < 0 || bytes == 0) {
|
if (r < 0 || bytes == 0) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
recv_buf_offset += bytes;
|
||||||
|
|
||||||
|
gsm->ppp_recv_buf = gsm->ppp_recv_cb(gsm->ppp_recv_buf,
|
||||||
|
&recv_buf_offset);
|
||||||
|
} else if (IS_ENABLED(CONFIG_GSM_MUX) && gsm->mux_enabled) {
|
||||||
|
/* The handler will listen AT channel */
|
||||||
|
gsm->context.cmd_handler.process(
|
||||||
|
&gsm->context.cmd_handler,
|
||||||
|
&gsm->context.iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
recv_buf_offset += bytes;
|
|
||||||
|
|
||||||
gsm->ppp_recv_buf = gsm->ppp_recv_cb(gsm->ppp_recv_buf,
|
|
||||||
&recv_buf_offset);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,10 +239,14 @@ static struct setup_cmd setup_cmds[] = {
|
||||||
|
|
||||||
/* disable unsolicited network registration codes */
|
/* disable unsolicited network registration codes */
|
||||||
SETUP_CMD_NOHANDLE("AT+CREG=0"),
|
SETUP_CMD_NOHANDLE("AT+CREG=0"),
|
||||||
|
|
||||||
/* create PDP context */
|
/* create PDP context */
|
||||||
SETUP_CMD_NOHANDLE("AT+CGDCONT=1,\"IP\",\"" CONFIG_MODEM_GSM_APN "\""),
|
SETUP_CMD_NOHANDLE("AT+CGDCONT=1,\"IP\",\"" CONFIG_MODEM_GSM_APN "\""),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct setup_cmd connect_cmds[] = {
|
||||||
/* connect to network */
|
/* connect to network */
|
||||||
SETUP_CMD_NOHANDLE("ATD*99#")
|
SETUP_CMD_NOHANDLE("ATD*99#"),
|
||||||
};
|
};
|
||||||
|
|
||||||
static int gsm_setup_mccmno(struct gsm_modem *gsm)
|
static int gsm_setup_mccmno(struct gsm_modem *gsm)
|
||||||
|
@ -245,49 +279,294 @@ static int gsm_setup_mccmno(struct gsm_modem *gsm)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gsm_configure(struct k_work *work)
|
static void set_ppp_carrier_on(struct gsm_modem *gsm)
|
||||||
{
|
{
|
||||||
int r = -1;
|
struct device *ppp_dev = device_get_binding(CONFIG_NET_PPP_DRV_NAME);
|
||||||
struct gsm_modem *gsm = CONTAINER_OF(work, struct gsm_modem,
|
struct net_if *iface;
|
||||||
gsm_configure_work);
|
|
||||||
|
|
||||||
LOG_DBG("Starting modem %p configuration", gsm);
|
if (!ppp_dev) {
|
||||||
|
LOG_ERR("Cannot find PPP %s!", "device");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while (r < 0) {
|
iface = net_if_lookup_by_dev(ppp_dev);
|
||||||
while (true) {
|
if (!iface) {
|
||||||
r = modem_cmd_send(&gsm->context.iface,
|
LOG_ERR("Cannot find PPP %s!", "network interface");
|
||||||
&gsm->context.cmd_handler,
|
return;
|
||||||
&response_cmds[0],
|
}
|
||||||
ARRAY_SIZE(response_cmds),
|
|
||||||
"AT", &gsm->sem_response,
|
|
||||||
GSM_CMD_AT_TIMEOUT);
|
|
||||||
if (r < 0) {
|
|
||||||
LOG_DBG("modem not ready %d", r);
|
|
||||||
} else {
|
|
||||||
LOG_DBG("connect with modem %d", r);
|
|
||||||
(void)gsm_setup_mccmno(gsm);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r = modem_cmd_handler_setup_cmds(&gsm->context.iface,
|
net_ppp_carrier_on(iface);
|
||||||
&gsm->context.cmd_handler,
|
}
|
||||||
setup_cmds,
|
|
||||||
ARRAY_SIZE(setup_cmds),
|
static void gsm_finalize_connection(struct gsm_modem *gsm)
|
||||||
&gsm->sem_response,
|
{
|
||||||
GSM_CMD_SETUP_TIMEOUT);
|
int ret;
|
||||||
if (r < 0) {
|
|
||||||
|
if (IS_ENABLED(CONFIG_GSM_MUX) && gsm->mux_enabled) {
|
||||||
|
ret = modem_cmd_send(&gsm->context.iface,
|
||||||
|
&gsm->context.cmd_handler,
|
||||||
|
&response_cmds[0],
|
||||||
|
ARRAY_SIZE(response_cmds),
|
||||||
|
"AT", &gsm->sem_response,
|
||||||
|
GSM_CMD_AT_TIMEOUT);
|
||||||
|
if (ret < 0) {
|
||||||
LOG_DBG("modem setup returned %d, %s",
|
LOG_DBG("modem setup returned %d, %s",
|
||||||
r, "retrying...");
|
ret, "retrying...");
|
||||||
} else {
|
(void)k_delayed_work_submit(&gsm->gsm_configure_work,
|
||||||
LOG_DBG("modem setup returned %d, %s",
|
K_SECONDS(1));
|
||||||
r, "enable PPP");
|
return;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(void)gsm_setup_mccmno(gsm);
|
||||||
|
|
||||||
|
ret = modem_cmd_handler_setup_cmds(&gsm->context.iface,
|
||||||
|
&gsm->context.cmd_handler,
|
||||||
|
setup_cmds,
|
||||||
|
ARRAY_SIZE(setup_cmds),
|
||||||
|
&gsm->sem_response,
|
||||||
|
GSM_CMD_SETUP_TIMEOUT);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_DBG("modem setup returned %d, %s",
|
||||||
|
ret, "retrying...");
|
||||||
|
(void)k_delayed_work_submit(&gsm->gsm_configure_work,
|
||||||
|
K_SECONDS(1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DBG("modem setup returned %d, %s", ret, "enable PPP");
|
||||||
|
|
||||||
|
ret = modem_cmd_handler_setup_cmds(&gsm->context.iface,
|
||||||
|
&gsm->context.cmd_handler,
|
||||||
|
connect_cmds,
|
||||||
|
ARRAY_SIZE(connect_cmds),
|
||||||
|
&gsm->sem_response,
|
||||||
|
GSM_CMD_SETUP_TIMEOUT);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_DBG("modem setup returned %d, %s",
|
||||||
|
ret, "retrying...");
|
||||||
|
(void)k_delayed_work_submit(&gsm->gsm_configure_work,
|
||||||
|
K_SECONDS(1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
gsm->setup_done = true;
|
gsm->setup_done = true;
|
||||||
|
|
||||||
|
/* FIXME: This will let PPP to start send data. We should actually
|
||||||
|
* change this so that the PPP L2 is initialized after the GSM modem
|
||||||
|
* is working and connection is created. TBDL.
|
||||||
|
*/
|
||||||
k_sem_give(&gsm->ppp_send_sem);
|
k_sem_give(&gsm->ppp_send_sem);
|
||||||
|
|
||||||
|
set_ppp_carrier_on(gsm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mux_enable(struct gsm_modem *gsm)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Turn on muxing */
|
||||||
|
if (IS_ENABLED(CONFIG_MODEM_GSM_SIMCOM)) {
|
||||||
|
ret = modem_cmd_send(
|
||||||
|
&gsm->context.iface,
|
||||||
|
&gsm->context.cmd_handler,
|
||||||
|
&response_cmds[0],
|
||||||
|
ARRAY_SIZE(response_cmds),
|
||||||
|
#if defined(SIMCOM_LTE)
|
||||||
|
/* FIXME */
|
||||||
|
/* Some SIMCOM modems can set the channels */
|
||||||
|
/* Control channel always at DLCI 0 */
|
||||||
|
"AT+CMUXSRVPORT=0,0;"
|
||||||
|
/* PPP should be at DLCI 1 */
|
||||||
|
"+CMUXSRVPORT=" STRINGIFY(DLCI_PPP) ",1;"
|
||||||
|
/* AT should be at DLCI 2 */
|
||||||
|
"+CMUXSRVPORT=" STRINGIFY(DLCI_AT) ",1;"
|
||||||
|
#else
|
||||||
|
"AT"
|
||||||
|
#endif
|
||||||
|
"+CMUX=0,0,5,"
|
||||||
|
STRINGIFY(CONFIG_GSM_MUX_MRU_DEFAULT_LEN),
|
||||||
|
&gsm->sem_response,
|
||||||
|
GSM_CMD_AT_TIMEOUT);
|
||||||
|
} else {
|
||||||
|
/* Generic GSM modem */
|
||||||
|
ret = modem_cmd_send(&gsm->context.iface,
|
||||||
|
&gsm->context.cmd_handler,
|
||||||
|
&response_cmds[0],
|
||||||
|
ARRAY_SIZE(response_cmds),
|
||||||
|
"AT+CMUX=0", &gsm->sem_response,
|
||||||
|
GSM_CMD_AT_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("AT+CMUX ret:%d", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mux_setup_next(struct gsm_modem *gsm)
|
||||||
|
{
|
||||||
|
(void)k_delayed_work_submit(&gsm->gsm_configure_work, K_MSEC(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mux_attach_cb(struct device *mux, int dlci_address,
|
||||||
|
bool connected, void *user_data)
|
||||||
|
{
|
||||||
|
LOG_DBG("DLCI %d to %s %s", dlci_address, mux->config->name,
|
||||||
|
connected ? "connected" : "disconnected");
|
||||||
|
|
||||||
|
if (connected) {
|
||||||
|
uart_irq_rx_enable(mux);
|
||||||
|
uart_irq_tx_enable(mux);
|
||||||
|
}
|
||||||
|
|
||||||
|
mux_setup_next(user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mux_attach(struct device *mux, struct device *uart,
|
||||||
|
int dlci_address, void *user_data)
|
||||||
|
{
|
||||||
|
int ret = uart_mux_attach(mux, uart, dlci_address, mux_attach_cb,
|
||||||
|
user_data);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("Cannot attach DLCI %d (%s) to %s (%d)", dlci_address,
|
||||||
|
mux->config->name, uart->config->name, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mux_setup(struct k_work *work)
|
||||||
|
{
|
||||||
|
struct gsm_modem *gsm = CONTAINER_OF(work, struct gsm_modem,
|
||||||
|
gsm_configure_work);
|
||||||
|
struct device *uart = device_get_binding(CONFIG_MODEM_GSM_UART_NAME);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
switch (gsm->state) {
|
||||||
|
case STATE_CONTROL_CHANNEL:
|
||||||
|
/* Get UART device. There is one dev / DLCI */
|
||||||
|
gsm->control_dev = uart_mux_alloc();
|
||||||
|
if (gsm->control_dev == NULL) {
|
||||||
|
LOG_DBG("Cannot get UART mux for %s channel",
|
||||||
|
"control");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
gsm->state = STATE_PPP_CHANNEL;
|
||||||
|
|
||||||
|
ret = mux_attach(gsm->control_dev, uart, DLCI_CONTROL, gsm);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_PPP_CHANNEL:
|
||||||
|
gsm->ppp_dev = uart_mux_alloc();
|
||||||
|
if (gsm->ppp_dev == NULL) {
|
||||||
|
LOG_DBG("Cannot get UART mux for %s channel", "PPP");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
gsm->state = STATE_AT_CHANNEL;
|
||||||
|
|
||||||
|
ret = mux_attach(gsm->ppp_dev, uart, DLCI_PPP, gsm);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_AT_CHANNEL:
|
||||||
|
gsm->at_dev = uart_mux_alloc();
|
||||||
|
if (gsm->at_dev == NULL) {
|
||||||
|
LOG_DBG("Cannot get UART mux for %s channel", "AT");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
gsm->state = STATE_DONE;
|
||||||
|
|
||||||
|
ret = mux_attach(gsm->at_dev, uart, DLCI_AT, gsm);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_DONE:
|
||||||
|
/* Re-use the original iface for AT channel */
|
||||||
|
ret = modem_iface_uart_init(&gsm->context.iface,
|
||||||
|
&gsm->gsm_data,
|
||||||
|
gsm->at_dev->config->name);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_DBG("iface %suart error %d", "mux ", ret);
|
||||||
|
gsm->mux_enabled = false;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
gsm_finalize_connection(gsm);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
gsm->state = STATE_INIT;
|
||||||
|
gsm->mux_enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gsm_configure(struct k_work *work)
|
||||||
|
{
|
||||||
|
struct gsm_modem *gsm = CONTAINER_OF(work, struct gsm_modem,
|
||||||
|
gsm_configure_work);
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
LOG_DBG("Starting modem %p configuration", gsm);
|
||||||
|
|
||||||
|
ret = modem_cmd_send(&gsm->context.iface,
|
||||||
|
&gsm->context.cmd_handler,
|
||||||
|
&response_cmds[0],
|
||||||
|
ARRAY_SIZE(response_cmds),
|
||||||
|
"AT", &gsm->sem_response,
|
||||||
|
GSM_CMD_AT_TIMEOUT);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_DBG("modem not ready %d", ret);
|
||||||
|
|
||||||
|
(void)k_delayed_work_submit(&gsm->gsm_configure_work, 0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_GSM_MUX) && ret == 0 &&
|
||||||
|
gsm->mux_enabled == false) {
|
||||||
|
gsm->mux_setup_done = false;
|
||||||
|
|
||||||
|
ret = mux_enable(gsm);
|
||||||
|
if (ret == 0) {
|
||||||
|
gsm->mux_enabled = true;
|
||||||
|
} else {
|
||||||
|
gsm->mux_enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DBG("GSM muxing %s", gsm->mux_enabled ? "enabled" :
|
||||||
|
"disabled");
|
||||||
|
|
||||||
|
if (gsm->mux_enabled) {
|
||||||
|
gsm->state = STATE_INIT;
|
||||||
|
|
||||||
|
k_delayed_work_init(&gsm->gsm_configure_work,
|
||||||
|
mux_setup);
|
||||||
|
|
||||||
|
(void)k_delayed_work_submit(&gsm->gsm_configure_work,
|
||||||
|
0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gsm_finalize_connection(gsm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gsm_init(struct device *device)
|
static int gsm_init(struct device *device)
|
||||||
|
@ -331,8 +610,8 @@ static int gsm_init(struct device *device)
|
||||||
gsm->gsm_data.rx_rb_buf = &gsm->gsm_rx_rb_buf[0];
|
gsm->gsm_data.rx_rb_buf = &gsm->gsm_rx_rb_buf[0];
|
||||||
gsm->gsm_data.rx_rb_buf_len = sizeof(gsm->gsm_rx_rb_buf);
|
gsm->gsm_data.rx_rb_buf_len = sizeof(gsm->gsm_rx_rb_buf);
|
||||||
|
|
||||||
r = modem_iface_uart_init(&gsm->context.iface,
|
r = modem_iface_uart_init(&gsm->context.iface, &gsm->gsm_data,
|
||||||
&gsm->gsm_data, CONFIG_MODEM_GSM_UART_NAME);
|
CONFIG_MODEM_GSM_UART_NAME);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
LOG_DBG("iface uart error %d", r);
|
LOG_DBG("iface uart error %d", r);
|
||||||
return r;
|
return r;
|
||||||
|
@ -344,6 +623,9 @@ static int gsm_init(struct device *device)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_DBG("iface->read %p iface->write %p",
|
||||||
|
gsm->context.iface.read, gsm->context.iface.write);
|
||||||
|
|
||||||
k_thread_create(&gsm_rx_thread, gsm_rx_stack,
|
k_thread_create(&gsm_rx_thread, gsm_rx_stack,
|
||||||
K_THREAD_STACK_SIZEOF(gsm_rx_stack),
|
K_THREAD_STACK_SIZEOF(gsm_rx_stack),
|
||||||
(k_thread_entry_t) gsm_rx,
|
(k_thread_entry_t) gsm_rx,
|
||||||
|
@ -353,22 +635,22 @@ static int gsm_init(struct device *device)
|
||||||
|
|
||||||
(void)k_delayed_work_submit(&gsm->gsm_configure_work, K_NO_WAIT);
|
(void)k_delayed_work_submit(&gsm->gsm_configure_work, K_NO_WAIT);
|
||||||
|
|
||||||
LOG_DBG("iface->read %p iface->write %p",
|
|
||||||
gsm->context.iface.read, gsm->context.iface.write);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int uart_pipe_send(const u8_t *data, int len)
|
int uart_pipe_send(const u8_t *buf, int len)
|
||||||
{
|
{
|
||||||
k_sem_take(&gsm.ppp_send_sem, K_FOREVER);
|
k_sem_take(&gsm.ppp_send_sem, K_FOREVER);
|
||||||
|
|
||||||
(void)gsm.context.iface.write(&gsm.context.iface, data, len);
|
(void)gsm.context.iface.write(&gsm.context.iface, buf, len);
|
||||||
|
|
||||||
k_sem_give(&gsm.ppp_send_sem);
|
k_sem_give(&gsm.ppp_send_sem);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Setup the connection to PPP. PPP driver will call this function. */
|
||||||
void uart_pipe_register(u8_t *buf, size_t len, uart_pipe_recv_cb cb)
|
void uart_pipe_register(u8_t *buf, size_t len, uart_pipe_recv_cb cb)
|
||||||
{
|
{
|
||||||
gsm.ppp_recv_buf = buf;
|
gsm.ppp_recv_buf = buf;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue