Skip to content
This repository has been archived by the owner on Nov 11, 2024. It is now read-only.

Commit

Permalink
Cellular feature, ESP-IDF only: PPP-level integration.
Browse files Browse the repository at this point in the history
This commit introduces the concept of a PPP interface to ubxlib, currently only for the ESP-IDF platform and with a cellular transport.  This allows the native application protocols of the platform to be used with cellular.

The PPP interface is defined as a new port API, which includes a default implementation that does nothing so that no existing ports are adversely affected by it.  This port API is, internally, called from the cellular code, such that when the cellular network is up the PPP interface of the port layer is automatically activated, connecting into the PPP layer at the bottom of the IP stack of the platform (LWIP in the ESP-IDF case).

This is currently only supported with SARA-R5 and SARA-R422 cellular modules.  U_CFG_PPP_ENABLE must be define when building ubxlib to enable PPP.

Of course, for this to integrate with the platform there will be additional build requirements related to the platform itself (enabling the right components of the platform etc.): see the README.md in the ESP-IDF platform directory for details.

An example is added to the sockets examples showing how to use native ESP-IDF sockets with PPP.
  • Loading branch information
RobMeades committed Nov 21, 2023
1 parent 731256a commit 8549e3e
Show file tree
Hide file tree
Showing 54 changed files with 5,272 additions and 441 deletions.
11 changes: 10 additions & 1 deletion cell/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,13 @@ int app_start() {
while(1);
}
```
```

# PPP-Level Integration With A Platform
PPP-level integration between the bottom of a platform's IP stack and cellular is supported on some platforms and some module types, currently only ESP-IDF with SARA-R5 or SARA-R422. This allows the native clients of the platform (e.g. MQTT etc.) to be used in your application with a cellular transport beneath them.

To enable this integration you must define `U_CFG_PPP_ENABLE` for your build. Other switches/components/whatevers may also be required on the platform side: see the README.md in the relevant platform directory for details.

To use the integration, just make a cellular connection with `ubxlib` in the usual way and the connection will be available to the platform.

Note: if you are required to supply a username and password for your connection then, when using PPP, you must call `uCellNetSetAuthenticationMode()` to set the authentication mode explicitly; automatic authentication mode will not work with PPP.
6 changes: 3 additions & 3 deletions cell/api/u_cell_mux.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ extern "C" {
#define U_CELL_MUX_CHANNEL_ID_GNSS 0xFF

#ifndef U_CELL_MUX_MAX_CHANNELS
/** Enough room for the control channel, an AT channel and a
* GNSS serial channel.
/** Enough room for the control channel, an AT channel, a
* GNSS serial channel and potentially a PPP data channel.
*/
# define U_CELL_MUX_MAX_CHANNELS 3
# define U_CELL_MUX_MAX_CHANNELS 4
#endif

/* ----------------------------------------------------------------
Expand Down
4 changes: 4 additions & 0 deletions cell/api/u_cell_net.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,10 @@ typedef enum {
} uCellNetRegDomain_t;

/** The possible authentication modes for the network connection.
*
* Note: there is also a #uPortPppAuthenticationMode_t enumeration
* which is set to match this one. If you make a change here you
* may need to make a change there also.
*/
typedef enum {
U_CELL_NET_AUTHENTICATION_MODE_NONE = 0, /**< \deprecated please use #U_CELL_NET_AUTHENTICATION_MODE_NOT_SET. */
Expand Down
3 changes: 3 additions & 0 deletions cell/src/u_cell.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
#include "u_cell_private.h" // don't change it
#include "u_cell_mux.h"
#include "u_cell_mux_private.h"
#include "u_cell_ppp_private.h"

// The headers below necessary to work around an Espressif linker problem, see uCellInit()
#include "u_sock.h"
Expand Down Expand Up @@ -143,6 +144,8 @@ static void removeCellInstance(uCellPrivateInstance_t *pInstance)
uPortFree(pInstance->pFotaContext);
// Free any HTTP context
uCellPrivateHttpRemoveContext(pInstance);
// Free any PPP context
uCellPppPrivateRemoveContext(pInstance);
// Free any CMUX context
uCellMuxPrivateRemoveContext(pInstance);
// Free any CellTime context
Expand Down
536 changes: 354 additions & 182 deletions cell/src/u_cell_mux.c

Large diffs are not rendered by default.

100 changes: 4 additions & 96 deletions cell/src/u_cell_mux_private.c
Original file line number Diff line number Diff line change
Expand Up @@ -388,31 +388,6 @@ int32_t uCellMuxPrivateParseCmux(uParseHandle_t parseHandle, void *pUserParam)
* PUBLIC FUNCTIONS: MISC
* -------------------------------------------------------------- */

// Get the serial device for the given channel.
uDeviceSerial_t *pUCellMuxPrivateGetDeviceSerial(uCellMuxPrivateContext_t *pContext,
uint8_t channel)
{
uDeviceSerial_t *pDeviceSerial = NULL;
uCellMuxPrivateChannelContext_t *pChannelContext;

if ((pContext != NULL) && (channel <= U_CELL_MUX_PRIVATE_CHANNEL_ID_MAX)) {
for (size_t x = 0;
(x < sizeof(pContext->pDeviceSerial) / sizeof(pContext->pDeviceSerial[0])) &&
(pDeviceSerial == NULL); x++) {
if (pContext->pDeviceSerial[x] != NULL) {
pChannelContext = (uCellMuxPrivateChannelContext_t *) pUInterfaceContext(
pContext->pDeviceSerial[x]);
if ((pChannelContext != NULL) && !pChannelContext->markedForDeletion &&
(pChannelContext->channel == channel)) {
pDeviceSerial = pContext->pDeviceSerial[x];
}
}
}
}

return pDeviceSerial;
}

// Copy the settings of one AT client into another AT client.
int32_t uCellMuxPrivateCopyAtClient(uAtClientHandle_t atHandleSource,
uAtClientHandle_t atHandleDestination)
Expand Down Expand Up @@ -503,77 +478,6 @@ int32_t uCellMuxPrivateCopyAtClient(uAtClientHandle_t atHandleSource,
return errorCode;
}

// Close a CMUX channel.
void uCellMuxPrivateCloseChannel(uCellMuxPrivateContext_t *pContext, uint8_t channel)
{
uDeviceSerial_t *pDeviceSerial = pUCellMuxPrivateGetDeviceSerial(pContext, channel);

if (pDeviceSerial != NULL) {
pDeviceSerial->close(pDeviceSerial);
#ifdef U_CELL_MUX_ENABLE_DEBUG
uPortLog("U_CELL_CMUX_%d: channel closed.\n", channel);
#endif
}
}

// Disable multiplexer mode. This involves a few steps:
//
// 1. Send DISC on the virtual serial interface of any currently
// open channels and close the virtual serial interfaces;
// do channel 0, the control interface, last and it will
// end CMUX mode.
// 2. Move AT client operations back to the original AT client.
// 3. DO NOT fee memory; only uCellMuxPrivateRemoveContext() does
// that, to ensure thread-safety.
int32_t uCellMuxPrivateDisable(uCellPrivateInstance_t *pInstance)
{
int32_t errorCode = (int32_t) U_ERROR_COMMON_INVALID_PARAMETER;
uAtClientHandle_t atHandle;
uCellMuxPrivateContext_t *pContext;
uCellMuxPrivateChannelContext_t *pChannelContext;

if (pInstance != NULL) {
atHandle = pInstance->atHandle;
errorCode = (int32_t) U_ERROR_COMMON_SUCCESS;
if (pInstance->pMuxContext != NULL) {
pContext = (uCellMuxPrivateContext_t *) pInstance->pMuxContext;
// Start from the top, so that we do channel 0, which
// will always be at index 0, last
for (int32_t x = (sizeof(pContext->pDeviceSerial) / sizeof(pContext->pDeviceSerial[0])) - 1;
x >= 0; x--) {
pChannelContext = (uCellMuxPrivateChannelContext_t *) pUInterfaceContext(
pContext->pDeviceSerial[x]);
if (pChannelContext != NULL) {
uCellMuxPrivateCloseChannel(pContext, pChannelContext->channel);
}
}
if (pContext->savedAtHandle != NULL) {
// Copy the settings of the AT handler on channel 1
// back into the original one, in case they have changed
errorCode = uCellMuxPrivateCopyAtClient(atHandle, pContext->savedAtHandle);
// While we set the error code above, there's not a whole lot
// we can do if this fails, so continue anyway; close the
// AT handler that was on channel 1
uAtClientIgnoreAsync(atHandle);
uAtClientRemove(atHandle);
// Unhijack the old AT handler and unlock it
atHandle = pContext->savedAtHandle;
uAtClientUrcHandlerHijackExt(atHandle, NULL, NULL);
uAtClientUnlock(atHandle);
pInstance->atHandle = atHandle;
pContext->savedAtHandle = NULL;
#ifdef U_CELL_MUX_ENABLE_DEBUG
uPortLog("U_CELL_CMUX: closed.\n");
#endif
}
// Give the module a moment for the MUX switcheroo
uPortTaskBlock(U_CELL_MUX_PRIVATE_ENABLE_DISABLE_DELAY_MS);
}
}

return (int32_t) errorCode;
}

// Remove the CMUX context for the given cellular instance.
void uCellMuxPrivateRemoveContext(uCellPrivateInstance_t *pInstance)
{
Expand Down Expand Up @@ -605,4 +509,8 @@ void uCellMuxPrivateRemoveContext(uCellPrivateInstance_t *pInstance)
}
}

/* ----------------------------------------------------------------
* PUBLIC FUNCTIONS: THERE ARE MORE uCellMuxPrivateXxx() FUNCTIONS IN U_CELL_MUX.C
* -------------------------------------------------------------- */

// End of file
Loading

0 comments on commit 8549e3e

Please sign in to comment.