This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit eb965d5fec1c7d4585d24d94248edad376cafe66
Author: raiden00pl <[email protected]>
AuthorDate: Sat Jul 22 14:19:37 2023 +0200

    arch/nrf91: add support for modem sockets
---
 arch/arm/src/nrf91/CMakeLists.txt     |   62 +-
 arch/arm/src/nrf91/Kconfig            |    2 +
 arch/arm/src/nrf91/Make.defs          |    2 +-
 arch/arm/src/nrf91/nrf91_modem_sock.c | 1204 +++++++++++++++++++++++++++++++++
 arch/arm/src/nrf91/nrf91_modem_sock.h |   29 +
 5 files changed, 1268 insertions(+), 31 deletions(-)

diff --git a/arch/arm/src/nrf91/CMakeLists.txt 
b/arch/arm/src/nrf91/CMakeLists.txt
index 8ec367033e..a908b5f1ae 100644
--- a/arch/arm/src/nrf91/CMakeLists.txt
+++ b/arch/arm/src/nrf91/CMakeLists.txt
@@ -1,23 +1,22 @@
-############################################################################
+# 
##############################################################################
 # arch/arm/src/nrf91/CMakeLists.txt
 #
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
+# Licensed to the Apache Software Foundation (ASF) under one or more 
contributor
+# license agreements.  See the NOTICE file distributed with this work for
+# additional information regarding copyright ownership.  The ASF licenses this
+# file to you under the Apache License, Version 2.0 (the "License"); you may 
not
+# use this file except in compliance with the License.  You may obtain a copy 
of
+# the License at
 #
-#   http://www.apache.org/licenses/LICENSE-2.0
+# http://www.apache.org/licenses/LICENSE-2.0
 #
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
+# License for the specific language governing permissions and limitations under
+# the License.
 #
-############################################################################
-
+# 
##############################################################################
 
 set(SRCS
     nrf91_start.c
@@ -98,18 +97,18 @@ if(CONFIG_NRF91_MODEM)
       DOWNLOAD_NAME "sdk-nrfxlib-v${NRFXLIB_VER}.tar.gz"
       DOWNLOAD_DIR ${CMAKE_CURRENT_LIST_DIR}
       URL "${NRFXLIB_URL}/v${NRFXLIB_VER}.tar.gz"
-      SOURCE_DIR
-      ${CMAKE_CURRENT_LIST_DIR}/sdk-nrfxlib
-      BINARY_DIR
-      ${CMAKE_BINARY_DIR}/arch/sdk-nrfxlib
-      CONFIGURE_COMMAND
-      ""
-      BUILD_COMMAND
-      ""
-      INSTALL_COMMAND
-      ""
-      TEST_COMMAND
-      ""
+          SOURCE_DIR
+          ${CMAKE_CURRENT_LIST_DIR}/sdk-nrfxlib
+          BINARY_DIR
+          ${CMAKE_BINARY_DIR}/arch/sdk-nrfxlib
+          CONFIGURE_COMMAND
+          ""
+          BUILD_COMMAND
+          ""
+          INSTALL_COMMAND
+          ""
+          TEST_COMMAND
+          ""
       DOWNLOAD_NO_PROGRESS true
       TIMEOUT 30)
 
@@ -120,7 +119,8 @@ if(CONFIG_NRF91_MODEM)
     endif()
   endif()
 
-  list(APPEND SRCS nrf91_modem.c nrf91_modem_os.c nrf91_nrfx_ipc.c)
+  list(APPEND SRCS nrf91_modem.c nrf91_modem_os.c nrf91_nrfx_ipc.c
+       nrf91_modem_sock.c)
 
   if(CONFIG_NRF91_MODEM_AT)
     list(APPEND SRCS nrf91_modem_at.c)
@@ -130,22 +130,24 @@ if(CONFIG_NRF91_MODEM)
 
   if(CONFIG_ARCH_FPU)
     set(NRFXLIB_LIB_VARIANT hard-float)
-  else ()
+  else()
     set(NRFXLIB_LIB_VARIANT soft-float)
   endif()
 
   if(CONFIG_NRF91_MODEM_LOG)
     set(MODEM_LIB_VARIANT libmodem_log.a)
   else()
-    set(MODEM_LIB_VARIANT libmodem_log.a)
+    set(MODEM_LIB_VARIANT libmodem.a)
   endif()
 
-  nuttx_library_import(modem
-    
${NRFXLIB_DIR}/nrf_modem/lib/cortex-m33/${NRFXLIB_LIB_VARIANT}/${MODEM_LIB_VARIANT})
+  nuttx_library_import(
+    modem
+    
${NRFXLIB_DIR}/nrf_modem/lib/cortex-m33/${NRFXLIB_LIB_VARIANT}/${MODEM_LIB_VARIANT}
+  )
   target_include_directories(arch PRIVATE ${NRFXLIB_DIR}/nrf_modem/include)
 
   target_link_libraries(arch PRIVATE modem)
-  target_link_libraries(modem INTERFACE arch c)
+  target_link_libraries(modem INTERFACE arch c net)
 endif()
 
 target_sources(arch PRIVATE ${SRCS})
diff --git a/arch/arm/src/nrf91/Kconfig b/arch/arm/src/nrf91/Kconfig
index d9415a9905..34a5a48618 100644
--- a/arch/arm/src/nrf91/Kconfig
+++ b/arch/arm/src/nrf91/Kconfig
@@ -703,6 +703,8 @@ config NRF91_MODEM
        select ARCH_IRQPRIO
        select NRF91_IPC
        select NRF91_USE_LFCLK
+       select MODEM
+       select NETDEV_MODEM_LTE_IOCTL
        default n
 
 if NRF91_MODEM
diff --git a/arch/arm/src/nrf91/Make.defs b/arch/arm/src/nrf91/Make.defs
index d1d7078941..e1938205d3 100644
--- a/arch/arm/src/nrf91/Make.defs
+++ b/arch/arm/src/nrf91/Make.defs
@@ -104,7 +104,7 @@ distclean::
        $(call DELDIR, chip/$(NRFXLIB_UNPACK))
 endif
 
-CHIP_CSRCS += nrf91_modem.c nrf91_modem_os.c nrf91_nrfx_ipc.c
+CHIP_CSRCS += nrf91_modem.c nrf91_modem_os.c nrf91_nrfx_ipc.c 
nrf91_modem_sock.c
 
 ifeq ($(CONFIG_NRF91_MODEM_AT),y)
 CHIP_CSRCS += nrf91_modem_at.c
diff --git a/arch/arm/src/nrf91/nrf91_modem_sock.c 
b/arch/arm/src/nrf91/nrf91_modem_sock.c
new file mode 100644
index 0000000000..0416d21683
--- /dev/null
+++ b/arch/arm/src/nrf91/nrf91_modem_sock.c
@@ -0,0 +1,1204 @@
+/****************************************************************************
+ * arch/arm/src/nrf91/nrf91_modem_sock.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <debug.h>
+#include <errno.h>
+#include <syslog.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include <nuttx/wqueue.h>
+#include <nuttx/arch.h>
+#include <nuttx/net/usrsock.h>
+#include <nuttx/net/ioctl.h>
+
+#include <nuttx/wireless/lte/lte_ioctl.h>
+#include <nuttx/wireless/lte/lte.h>
+
+#undef s6_addr
+#include "nrf_socket.h"
+#include "nrf_modem_at.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_NET_USRSOCK_CUSTOM
+#  error CONFIG_NET_USRSOCK_CUSTOM must be set
+#endif
+
+#ifndef CONFIG_SCHED_LPWORK
+#  error CONFIG_SCHED_LPWORK must be set
+#endif
+
+#define NRF91_USRSOCK_BUFSIZE (4096)
+
+#define MAX_CTRL_SOCKET_COUNT (1)
+#define MAX_SOCKET_COUNT      (NRF_MODEM_MAX_SOCKET_COUNT + \
+                               MAX_CTRL_SOCKET_COUNT)
+#define CTRL_SOCKET_FIRST     (NRF_MODEM_MAX_SOCKET_COUNT)
+
+/****************************************************************************
+ * Private Data Types
+ ****************************************************************************/
+
+struct nrf91_sock_s
+{
+  bool in_use;
+  bool recvpending;
+};
+
+struct nrf91_usrsock_s
+{
+  uint8_t             in[NRF91_USRSOCK_BUFSIZE];
+  uint8_t             out[NRF91_USRSOCK_BUFSIZE];
+  struct work_s       pollwork;
+  struct nrf_pollfd   pollfd;
+  struct nrf91_sock_s sock[MAX_SOCKET_COUNT];
+};
+
+typedef int (*usrsock_handler_t)(struct nrf91_usrsock_s *usrsock,
+                                 const void *data, size_t len);
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int nrf91_usrsock_socket_handler(struct nrf91_usrsock_s *usrsock,
+                                        const void *data, size_t len);
+static int nrf91_usrsock_close_handler(struct nrf91_usrsock_s *usrsock,
+                                       const void *data, size_t len);
+static int nrf91_usrsock_connect_handler(struct nrf91_usrsock_s *usrsock,
+                                         const void *data, size_t len);
+static int nrf91_usrsock_sendto_handler(struct nrf91_usrsock_s *usrsock,
+                                        const void *data, size_t len);
+static int nrf91_usrsock_recvfrom_handler(struct nrf91_usrsock_s *usrsock,
+                                          const void *data, size_t len);
+static int nrf91_usrsock_setsockopt_handler(struct nrf91_usrsock_s *usrsock,
+                                            const void *data, size_t len);
+static int nrf91_usrsock_getsockopt_handler(struct nrf91_usrsock_s *usrsock,
+                                            const void *data, size_t len);
+static int nrf91_usrsock_getsockname_handler(struct nrf91_usrsock_s *usrsock,
+                                             const void *data, size_t len);
+static int nrf91_usrsock_getpeername_handler(struct nrf91_usrsock_s *usrsock,
+                                             const void *data, size_t len);
+static int nrf91_usrsock_bind_handler(struct nrf91_usrsock_s *usrsock,
+                                      const void *data, size_t len);
+static int nrf91_usrsock_listen_handler(struct nrf91_usrsock_s *usrsock,
+                                        const void *data, size_t len);
+static int nrf91_usrsock_accept_handler(struct nrf91_usrsock_s *usrsock,
+                                        const void *data, size_t len);
+static int nrf91_usrsock_ioctl_handler(struct nrf91_usrsock_s *usrsock,
+                                       const void *data, size_t len);
+static int nrf91_usrsock_shutdown_handler(struct nrf91_usrsock_s *usrsock,
+                                          const void *data, size_t len);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct nrf91_usrsock_s g_usrsock;
+
+static const usrsock_handler_t g_usrsock_handler[] =
+{
+  [USRSOCK_REQUEST_SOCKET]      = nrf91_usrsock_socket_handler,
+  [USRSOCK_REQUEST_CLOSE]       = nrf91_usrsock_close_handler,
+  [USRSOCK_REQUEST_CONNECT]     = nrf91_usrsock_connect_handler,
+  [USRSOCK_REQUEST_SENDTO]      = nrf91_usrsock_sendto_handler,
+  [USRSOCK_REQUEST_RECVFROM]    = nrf91_usrsock_recvfrom_handler,
+  [USRSOCK_REQUEST_SETSOCKOPT]  = nrf91_usrsock_setsockopt_handler,
+  [USRSOCK_REQUEST_GETSOCKOPT]  = nrf91_usrsock_getsockopt_handler,
+  [USRSOCK_REQUEST_GETSOCKNAME] = nrf91_usrsock_getsockname_handler,
+  [USRSOCK_REQUEST_GETPEERNAME] = nrf91_usrsock_getpeername_handler,
+  [USRSOCK_REQUEST_BIND]        = nrf91_usrsock_bind_handler,
+  [USRSOCK_REQUEST_LISTEN]      = nrf91_usrsock_listen_handler,
+  [USRSOCK_REQUEST_ACCEPT]      = nrf91_usrsock_accept_handler,
+  [USRSOCK_REQUEST_IOCTL]       = nrf91_usrsock_ioctl_handler,
+  [USRSOCK_REQUEST_SHUTDOWN]    = nrf91_usrsock_shutdown_handler,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf2nx_family
+ ****************************************************************************/
+
+static int nrf2nx_family(int nrf_family)
+{
+  int nx_family = 0;
+
+  if (nrf_family == NRF_AF_UNSPEC)
+    {
+      nx_family = AF_UNSPEC;
+    }
+  else if (nrf_family == NRF_AF_INET)
+    {
+      nx_family = AF_INET;
+    }
+  else if (nrf_family == NRF_AF_INET6)
+    {
+      nx_family = AF_INET6;
+    }
+  else if (nrf_family == NRF_AF_PACKET)
+    {
+      nx_family = AF_PACKET;
+    }
+
+  return nx_family;
+}
+
+/****************************************************************************
+ * Name: nx2nrf_family
+ ****************************************************************************/
+
+static int nx2nrf_family(int nx_family)
+{
+  int nrf_family = 0;
+
+  if (nx_family == AF_UNSPEC)
+    {
+      nrf_family = NRF_AF_UNSPEC;
+    }
+  else if (nx_family == AF_INET)
+    {
+      nrf_family = NRF_AF_INET;
+    }
+  else if (nx_family == AF_INET6)
+    {
+      nrf_family = NRF_AF_INET6;
+    }
+  else if (nx_family == AF_PACKET)
+    {
+      nrf_family = NRF_AF_PACKET;
+    }
+  else
+    {
+      nerr("unsupported nrf family %d\n", nx_family);
+    }
+
+  return nrf_family;
+}
+
+/****************************************************************************
+ * Name: nx2nrf_type
+ ****************************************************************************/
+
+static int nx2nrf_type(int nx_type)
+{
+  int nrf_type = 0;
+
+  if (nx_type == SOCK_STREAM)
+    {
+      nrf_type = NRF_SOCK_STREAM;
+    }
+  else if (nx_type == SOCK_DGRAM)
+    {
+      nrf_type = NRF_SOCK_DGRAM;
+    }
+  else if (nx_type == SOCK_RAW)
+    {
+      nrf_type = NRF_SOCK_RAW;
+    }
+  else
+    {
+      nerr("unsupported nrf type %d\n", nx_type);
+    }
+
+  return nrf_type;
+}
+
+/****************************************************************************
+ * Name: nx2nrf_protocol
+ ****************************************************************************/
+
+static int nx2nrf_protocol(int nx_protocol)
+{
+  int nrf_protocol = 0;
+
+  if (nx_protocol == IPPROTO_IP)
+    {
+      nrf_protocol = NRF_IPPROTO_IP;
+    }
+  else if (nx_protocol == IPPROTO_TCP)
+    {
+      nrf_protocol = NRF_IPPROTO_TCP;
+    }
+  else if (nx_protocol == IPPROTO_UDP)
+    {
+      nrf_protocol = NRF_IPPROTO_UDP;
+    }
+  else if (nx_protocol == IPPROTO_IPV6)
+    {
+      nrf_protocol = NRF_IPPROTO_IPV6;
+    }
+  else if (nx_protocol == IPPROTO_RAW)
+    {
+      nrf_protocol = NRF_IPPROTO_RAW;
+    }
+  else
+    {
+      nerr("unsupported nrf protocol %d\n", nx_protocol);
+    }
+
+  return nrf_protocol;
+}
+
+/****************************************************************************
+ * Name: nx2nrf_sockaddr
+ ****************************************************************************/
+
+static void nx2nrf_sockaddr(struct sockaddr *nxaddress,
+                            struct nrf_sockaddr *address)
+{
+  address->sa_family = nx2nrf_family(nxaddress->sa_family);
+
+  if (address->sa_family == NRF_AF_INET)
+    {
+      struct sockaddr_in     *tmp1 = (struct sockaddr_in *)nxaddress;
+      struct nrf_sockaddr_in *tmp2 = (struct nrf_sockaddr_in *)address;
+
+      tmp2->sin_port        = tmp1->sin_port;
+      tmp2->sin_addr.s_addr = tmp1->sin_addr.s_addr;
+      tmp2->sin_len = sizeof(struct nrf_sockaddr_in);
+    }
+  else if (address->sa_family == NRF_AF_INET6)
+    {
+      struct sockaddr_in6     *tmp1 = (struct sockaddr_in6 *)nxaddress;
+      struct nrf_sockaddr_in6 *tmp2 = (struct nrf_sockaddr_in6 *)address;
+
+      tmp2->sin6_port     = tmp1->sin6_port;
+      memcpy(&tmp2->sin6_addr, &tmp1->sin6_addr, sizeof(struct in6_addr));
+      tmp2->sin6_scope_id = tmp1->sin6_scope_id;
+      tmp2->sin6_len = sizeof(struct nrf_sockaddr_in6);
+    }
+  else
+    {
+      nerr("unsupported nrf sa_family %d\n", address->sa_family);
+      address->sa_family = 0;
+    }
+}
+
+/****************************************************************************
+ * Name: nrf2nx_sockaddr
+ ****************************************************************************/
+
+static void nrf2nx_sockaddr(struct nrf_sockaddr *address,
+                            struct sockaddr *nxaddress)
+{
+  nxaddress->sa_family = nrf2nx_family(address->sa_family);
+
+  if (nxaddress->sa_family == AF_INET)
+    {
+      struct nrf_sockaddr_in *tmp1 = (struct nrf_sockaddr_in *)address;
+      struct sockaddr_in     *tmp2 = (struct sockaddr_in *)nxaddress;
+
+      tmp2->sin_port        = tmp1->sin_port;
+      tmp2->sin_addr.s_addr = tmp1->sin_addr.s_addr;
+    }
+  else if (nxaddress->sa_family == AF_INET6)
+    {
+      struct nrf_sockaddr_in6 *tmp1 = (struct nrf_sockaddr_in6 *)address;
+      struct sockaddr_in6     *tmp2 = (struct sockaddr_in6 *)nxaddress;
+
+      tmp2->sin6_port        = tmp1->sin6_port;
+      tmp2->sin6_flowinfo    = 0;
+      memcpy(&tmp2->sin6_addr, &tmp1->sin6_addr, sizeof(struct in6_addr));
+      tmp2->sin6_scope_id = tmp1->sin6_scope_id;
+    }
+  else
+    {
+      nerr("unsupported nx sa_family %d\n", nxaddress->sa_family);
+      nxaddress->sa_family = 0;
+    }
+}
+
+/****************************************************************************
+ * Name: nrf_usrsock_shutdown
+ ****************************************************************************/
+
+static int nrf_usrsock_shutdown(int sockfd, int how)
+{
+  /* TODO */
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_send
+ ****************************************************************************/
+
+static int nrf91_usrsock_send(struct nrf91_usrsock_s *usrsock,
+                              const void *buf, size_t len)
+{
+  return usrsock_response(buf, len, NULL);
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_send_ack
+ ****************************************************************************/
+
+static int nrf91_usrsock_send_ack(struct nrf91_usrsock_s *usrsock,
+                                  uint32_t xid, int32_t result)
+{
+  struct usrsock_message_req_ack_s ack;
+
+  ack.head.msgid = USRSOCK_MESSAGE_RESPONSE_ACK;
+  ack.head.flags = (result == -EINPROGRESS);
+  ack.head.events = 0;
+
+  ack.xid    = xid;
+  ack.result = result;
+
+  return nrf91_usrsock_send(usrsock, &ack, sizeof(ack));
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_send_dack
+ ****************************************************************************/
+
+static int nrf91_usrsock_send_dack(struct nrf91_usrsock_s *usrsock,
+                                   struct usrsock_message_datareq_ack_s *ack,
+                                   uint32_t xid, int32_t result,
+                                   uint16_t valuelen,
+                                   uint16_t valuelen_nontrunc)
+{
+  ack->reqack.head.msgid = USRSOCK_MESSAGE_RESPONSE_DATA_ACK;
+  ack->reqack.head.flags = 0;
+  ack->reqack.head.events = 0;
+
+  ack->reqack.xid    = xid;
+  ack->reqack.result = result;
+
+  if (result < 0)
+    {
+      result             = 0;
+      valuelen           = 0;
+      valuelen_nontrunc  = 0;
+    }
+  else if (valuelen > valuelen_nontrunc)
+    {
+      valuelen           = valuelen_nontrunc;
+    }
+
+  ack->valuelen          = valuelen;
+  ack->valuelen_nontrunc = valuelen_nontrunc;
+
+  return nrf91_usrsock_send(usrsock, ack, sizeof(*ack) + valuelen + result);
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_send_event
+ ****************************************************************************/
+
+static int nrf91_usrsock_send_event(struct nrf91_usrsock_s *usrsock,
+                                    int16_t usockid, uint16_t events)
+{
+  struct usrsock_message_socket_event_s event;
+
+  event.head.msgid  = USRSOCK_MESSAGE_SOCKET_EVENT;
+  event.head.flags  = USRSOCK_MESSAGE_FLAG_EVENT;
+  event.head.events = events;
+
+  event.usockid = usockid;
+
+  return nrf91_usrsock_send(usrsock, &event, sizeof(event));
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_event_callback
+ ****************************************************************************/
+
+static int nrf91_usrsock_event_callback(int16_t usockid, uint16_t events)
+{
+  return nrf91_usrsock_send_event(&g_usrsock, usockid, events);
+}
+
+/****************************************************************************
+ * Name: nrf91_modem_getver
+ ****************************************************************************/
+
+static int nrf91_modem_getver(lte_version_t *version)
+{
+  char buffer1[16];
+  char buffer2[16];
+  int  ret = OK;
+
+  memset(version, 0, sizeof(*version));
+  ret = nrf_modem_at_scanf("AT%HWVERSION", "%%HWVERSION: %s %s",
+                           buffer1, buffer2);
+  if (ret > 0)
+    {
+      strncpy(version->bb_product, buffer1, LTE_VER_BB_PRODUCT_LEN);
+      strncpy(version->np_package, buffer2, LTE_VER_NP_PACKAGE_LEN);
+    }
+
+  ret = nrf_modem_at_scanf("AT+CGMR", "%s", buffer1);
+  if (ret > 0)
+    {
+      strncpy(version->fw_version, buffer1, LTE_VER_FIRMWARE_LEN);
+      ret = 0;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf91_ioctl_ltecmd
+ ****************************************************************************/
+
+static int nrf91_ioctl_ltecmd(int fd, int cmd, unsigned long arg)
+{
+  struct lte_ioctl_data_s  *ltecmd = (struct lte_ioctl_data_s *)(arg);
+  int                     **result = (int **)ltecmd->outparam;
+  int                       ret    = OK;
+
+  switch (ltecmd->cmdid)
+    {
+      /* TODO: support for Nordic-specific functional modes 20-44 */
+
+      case LTE_CMDID_POWERON:
+        {
+          ret = nrf_modem_at_printf("AT+CFUN=1");
+          break;
+        }
+
+      case LTE_CMDID_POWEROFF:
+        {
+          ret = nrf_modem_at_printf("AT+CFUN=0");
+          break;
+        }
+
+      case LTE_CMDID_GETVER:
+        {
+          lte_version_t **version =
+            (lte_version_t **)(ltecmd->outparam + 1);
+          ret = nrf91_modem_getver(*version);
+          break;
+        }
+
+      case LTE_CMDID_GETIMEI:
+        {
+          char **imei = (char **)(ltecmd->outparam + 1);
+          size_t **len = (size_t **)(ltecmd->outparam + 2);
+          char buffer[32];
+          char *ptr;
+          ret = nrf_modem_at_cmd(buffer, 32, "AT+CGSN=1");
+          ptr = strchr(buffer, '"') + 1;
+          ptr[LTE_IMEI_LEN - 1] = 0;
+          strncpy(*imei, ptr, **len);
+          break;
+        }
+
+      case LTE_CMDID_GETQUAL:
+      {
+        lte_quality_t **quality =
+          (lte_quality_t **)(ltecmd->outparam + 1);
+        int tmp;
+        int rsrp;
+        int rsrq;
+        int rssi;
+
+        ret = nrf_modem_at_scanf("AT+CESQ",
+                                 "+CESQ: %d,%d,%d,%d,%d,%d",
+                                 &tmp, &tmp, &tmp, &tmp,
+                                 &rsrq, &rsrp);
+        if (ret > 0)
+          {
+            (*quality)->rsrq  = (rsrq / 2) - 19;
+            (*quality)->rsrp  = rsrp - 140;
+          }
+        else
+          {
+            nerr("AT+CESQ failed %d\n", ret);
+          }
+
+        ret = nrf_modem_at_scanf("AT+CSQ",
+                                 "+CSQ: %d,%d",
+                                 &rssi, &tmp);
+        if (ret > 0)
+          {
+            (*quality)->rssi  = rssi;
+            (*quality)->sinr  = 0;
+          }
+        else
+          {
+            nerr("AT+CSQ failed %d\n", ret);
+          }
+
+        (*quality)->valid = true;
+      }
+
+      /* TODO: commands from include/nuttx/wireless/lte/lte.h */
+
+      default:
+        {
+          nerr("unsupported cmd = %" PRId32, ltecmd->cmdid);
+          break;
+        }
+    }
+
+  if (result)
+    {
+      **result = ret;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_ioctl
+ ****************************************************************************/
+
+static int nrf91_usrsock_ioctl(int fd, int cmd, unsigned long arg)
+{
+  int ret = OK;
+
+  if (fd < NRF_MODEM_MAX_SOCKET_COUNT)
+    {
+      nerr("ioctl not supported for socket %d", fd);
+      ret = -EACCES;
+      goto errout;
+    }
+
+  switch (cmd)
+    {
+      case SIOCLTECMD:
+        {
+          ret = nrf91_ioctl_ltecmd(fd, cmd, arg);
+          break;
+        }
+
+      default:
+        {
+          ret = -ENOTTY;
+          nerr("ioctl unsupported cmd %d", cmd);
+          break;
+        }
+    }
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_getsockopt_handler
+ ****************************************************************************/
+
+int nrf91_usrsock_setsockopt(int sockfd, int level, int optname,
+                             const void *optval, unsigned int optlen)
+{
+  int ret = OK;
+
+  ret = nrf_setsockopt(sockfd, level, optname, optval,
+                        (nrf_socklen_t)optlen);
+  if (ret < 0)
+    {
+      nerr("nrf_setsockopt failed %d", errno);
+      ret = -errno;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_getsockopt_handler
+ ****************************************************************************/
+
+int nrf91_usrsock_getsockopt(int sockfd, int level, int optname,
+                             void *optval, unsigned int *optlen)
+{
+  int ret = OK;
+
+  ret = nrf_getsockopt(sockfd, level, optname, optval,
+                       (nrf_socklen_t *)optlen);
+  if (ret < 0)
+    {
+      nerr("nrf_getsockopt failed %d", errno);
+      ret = -errno;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_poll_work
+ ****************************************************************************/
+
+static void nrf91_usrsock_poll_work(void *arg)
+{
+  struct nrf_pollfd *pollfd = arg;
+  uint16_t           events = 0;
+  int                ret    = OK;
+
+  if (pollfd->revents & NRF_POLLIN)
+    {
+      events |= USRSOCK_EVENT_RECVFROM_AVAIL;
+    }
+
+  if (pollfd->revents & NRF_POLLERR)
+    {
+      events |= USRSOCK_EVENT_REMOTE_CLOSED;
+    }
+
+  if (pollfd->revents & NRF_POLLHUP)
+    {
+      events |= USRSOCK_EVENT_REMOTE_CLOSED;
+    }
+
+  if (events)
+    {
+      /* REVISIT: postpone REMOTE_CLOSED event if there are data to read */
+
+      if (events & USRSOCK_EVENT_REMOTE_CLOSED)
+        {
+          while (g_usrsock.sock[pollfd->fd].recvpending == true)
+            {
+              usleep(100);
+            }
+        }
+
+      ret = nrf91_usrsock_event_callback(pollfd->fd, events);
+      if (ret < 0)
+        {
+          nerr("usrsock_event_callback failed %d", ret);
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_poll_cb
+ *
+ *   The callback is invoked in an interrupt service routine.
+ *
+ ****************************************************************************/
+
+static void nrf91_usrsock_poll_cb(struct nrf_pollfd *pollfd)
+{
+  memcpy(&g_usrsock.pollfd, pollfd, sizeof(struct nrf_pollfd));
+
+  if (work_available(&g_usrsock.pollwork))
+    {
+      work_queue(LPWORK, &g_usrsock.pollwork, nrf91_usrsock_poll_work,
+                 &g_usrsock.pollfd, 0);
+    }
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_socket_handler
+ ****************************************************************************/
+
+static int nrf91_usrsock_socket_handler(struct nrf91_usrsock_s *usrsock,
+                                        const void *data, size_t len)
+{
+  const struct usrsock_request_socket_s *req = data;
+  struct nrf_modem_pollcb                cb;
+  int                                    fd  = 0;
+  int                                    ret = 0;
+
+  if (req->type == SOCK_CTRL)
+    {
+      /* Only one CTRL socket supported for now */
+
+      fd = CTRL_SOCKET_FIRST;
+    }
+  else
+    {
+      fd = nrf_socket(nx2nrf_family(req->domain),
+                      nx2nrf_type(req->type),
+                      nx2nrf_protocol(req->protocol));
+      if (ret < 0)
+        {
+          nerr("nrf_socket failed %d", errno);
+          ret = -errno;
+        }
+      else
+        {
+          cb.callback = nrf91_usrsock_poll_cb;
+          cb.events   = NRF_POLLIN | NRF_POLLHUP;
+          cb.oneshot  = false;
+
+          ret = nrf_setsockopt(fd, NRF_SOL_SOCKET, NRF_SO_POLLCB, &cb,
+                               sizeof(struct nrf_modem_pollcb));
+          if (ret < 0)
+            {
+              nerr("failed to connect poll cb %d", errno);
+              ret = -errno;
+            }
+        }
+    }
+
+  /* Mark socket as used */
+
+  if (fd >= 0)
+    {
+      usrsock->sock[fd].in_use = true;
+      usrsock->sock[fd].recvpending = false;
+    }
+
+  ret = nrf91_usrsock_send_ack(usrsock, req->head.xid, fd);
+
+  if (ret >= 0 && fd >= 0)
+    {
+      ret = nrf91_usrsock_send_event(usrsock, fd,
+                                     USRSOCK_EVENT_SENDTO_READY);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_close_handler
+ ****************************************************************************/
+
+static int nrf91_usrsock_close_handler(struct nrf91_usrsock_s *usrsock,
+                                       const void *data, size_t len)
+{
+  const struct usrsock_request_close_s *req = data;
+  int                                   ret = OK;
+
+  if (req->usockid < NRF_MODEM_MAX_SOCKET_COUNT)
+    {
+      ret = nrf_close(req->usockid);
+      if (ret < 0)
+        {
+          nerr("nrf_close failed %d", errno);
+          ret = -errno;
+        }
+
+      usrsock->sock[req->usockid].in_use = false;
+    }
+
+  return nrf91_usrsock_send_ack(usrsock, req->head.xid, ret);
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_connect_handler
+ ****************************************************************************/
+
+static int nrf91_usrsock_connect_handler(struct nrf91_usrsock_s *usrsock,
+                                         const void *data, size_t len)
+{
+  const struct usrsock_request_connect_s *req = data;
+  struct nrf_sockaddr_in6                 address;
+  int                                     ret = 0;
+
+  nx2nrf_sockaddr((struct sockaddr *)(req + 1),
+                  (struct nrf_sockaddr *)&address);
+
+  ret = nrf_connect(req->usockid,
+                    (const struct nrf_sockaddr *)&address,
+                    (nrf_socklen_t)req->addrlen);
+  if (ret < 0)
+    {
+      nerr("nrf_connect failed %d", errno);
+      ret = -errno;
+    }
+
+  return nrf91_usrsock_send_ack(usrsock, req->head.xid, ret);
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_sendto_handler
+ ****************************************************************************/
+
+static int nrf91_usrsock_sendto_handler(struct nrf91_usrsock_s *usrsock,
+                                        const void *data, size_t len)
+{
+  const struct usrsock_request_sendto_s *req  = data;
+  struct nrf_sockaddr_in6                address;
+  struct sockaddr                       *tmp  = NULL;
+  int                                    ret  = 0;
+  bool                                   sent = 0;
+
+  if (req->addrlen != 0)
+    {
+      tmp = (struct sockaddr *)(req + 1);
+      nx2nrf_sockaddr(tmp, (struct nrf_sockaddr *)&address);
+    }
+
+  ret = nrf_sendto(req->usockid,
+                   (const void *)(req + 1) + req->addrlen,
+                   req->buflen,
+                   req->flags,
+                   req->addrlen ? (struct nrf_sockaddr *)&address : NULL,
+                   (nrf_socklen_t)req->addrlen);
+  if (ret < 0)
+    {
+      nerr("nrf_sendto failed %d", errno);
+      ret = -errno;
+    }
+
+  sent = (ret > 0);
+  ret = nrf91_usrsock_send_ack(usrsock, req->head.xid, ret);
+  if (ret >= 0 && sent)
+    {
+      ret = nrf91_usrsock_send_event(usrsock, req->usockid,
+                               USRSOCK_EVENT_SENDTO_READY);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_recvfrom_handler
+ ****************************************************************************/
+
+static int nrf91_usrsock_recvfrom_handler(struct nrf91_usrsock_s *usrsock,
+                                          const void *data, size_t len)
+{
+  const struct usrsock_request_recvfrom_s *req        = data;
+  struct usrsock_message_datareq_ack_s    *ack        = NULL;
+  struct sockaddr                         *tmp        = NULL;
+  nrf_socklen_t                            outaddrlen = req->max_addrlen;
+  socklen_t                                inaddrlen  = req->max_addrlen;
+  size_t                                   buflen     = req->max_buflen;
+  struct nrf_sockaddr_in6                  address;
+  int                                      ret;
+  int                                      recvlen;
+
+  ack = (struct usrsock_message_datareq_ack_s *)usrsock->out;
+  if (sizeof(*ack) + inaddrlen + buflen > sizeof(usrsock->out))
+    {
+      buflen = sizeof(usrsock->out) - sizeof(*ack) - inaddrlen;
+    }
+
+  if (outaddrlen != 0)
+    {
+      tmp = (struct sockaddr *)(ack + 1);
+      nx2nrf_sockaddr(tmp, (struct nrf_sockaddr *)&address);
+    }
+
+  ret = nrf_recvfrom(req->usockid,
+                     (void *)(ack + 1) + inaddrlen,
+                     buflen,
+                     req->flags,
+                     outaddrlen ? (struct nrf_sockaddr *)&address: NULL,
+                     (nrf_socklen_t)outaddrlen ? &outaddrlen : NULL);
+  if (ret < 0)
+    {
+      nerr("nrf_recvfrom failed %d", errno);
+      ret = -errno;
+    }
+
+  recvlen = ret;
+
+  if (ret > 0 && outaddrlen < inaddrlen)
+    {
+      memcpy((void *)(ack + 1) + outaddrlen,
+             (void *)(ack + 1) + inaddrlen, ret);
+    }
+
+  /* Send data */
+
+  ret = nrf91_usrsock_send_dack(usrsock, ack, req->head.xid,
+                          ret, inaddrlen, outaddrlen);
+
+  /* REVISIT: signal that more data can be available */
+
+  if (ret >= 0 && buflen == recvlen)
+    {
+      usrsock->sock[req->usockid].recvpending = true;
+      ret = nrf91_usrsock_send_event(usrsock, req->usockid,
+                               USRSOCK_EVENT_RECVFROM_AVAIL);
+    }
+  else
+    {
+      usrsock->sock[req->usockid].recvpending = false;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_setsockopt_handler
+ ****************************************************************************/
+
+static int nrf91_usrsock_setsockopt_handler(struct nrf91_usrsock_s *usrsock,
+                                            const void *data, size_t len)
+{
+  const struct usrsock_request_setsockopt_s *req = data;
+  int                                        ret = 0;
+
+  ret = nrf91_usrsock_setsockopt(req->usockid, req->level, req->option,
+                                 req + 1, req->valuelen);
+  return nrf91_usrsock_send_ack(usrsock, req->head.xid, ret);
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_getsockopt_handler
+ ****************************************************************************/
+
+static int nrf91_usrsock_getsockopt_handler(struct nrf91_usrsock_s *usrsock,
+                                            const void *data, size_t len)
+{
+  const struct usrsock_request_getsockopt_s *req    = data;
+  struct usrsock_message_datareq_ack_s      *ack;
+  socklen_t                                  optlen = req->max_valuelen;
+  int                                        ret;
+
+  ack = (struct usrsock_message_datareq_ack_s *)usrsock->out;
+  ret = nrf91_usrsock_getsockopt(req->usockid, req->level, req->option,
+                                 ack + 1, &optlen);
+
+  return nrf91_usrsock_send_dack(usrsock, ack, req->head.xid,
+                           ret, optlen, optlen);
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_getsockname_handler
+ ****************************************************************************/
+
+static int nrf91_usrsock_getsockname_handler(struct nrf91_usrsock_s *usrsock,
+                                             const void *data, size_t len)
+{
+  return -1;
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_getpeername_handler
+ ****************************************************************************/
+
+static int nrf91_usrsock_getpeername_handler(struct nrf91_usrsock_s *usrsock,
+                                             const void *data, size_t len)
+{
+  return -1;
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_bind_handler
+ ****************************************************************************/
+
+static int nrf91_usrsock_bind_handler(struct nrf91_usrsock_s *usrsock,
+                                      const void *data, size_t len)
+{
+  const struct usrsock_request_bind_s *req = data;
+  struct nrf_sockaddr_in6              address;
+  int                                  ret = 0;
+
+  nx2nrf_sockaddr((struct sockaddr *)(req + 1),
+                  (struct nrf_sockaddr *)&address);
+  ret = nrf_bind(req->usockid, (const struct nrf_sockaddr *)&address,
+                 req->addrlen);
+
+  return nrf91_usrsock_send_ack(usrsock, req->head.xid, ret);
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_listen_handler
+ ****************************************************************************/
+
+static int nrf91_usrsock_listen_handler(struct nrf91_usrsock_s *usrsock,
+                                        const void *data, size_t len)
+{
+  const struct usrsock_request_listen_s *req = data;
+  int                                    ret = 0;
+
+  ret = nrf_listen(req->usockid, req->backlog);
+  if (ret < 0)
+    {
+      ret = -errno;
+    }
+
+  return nrf91_usrsock_send_ack(usrsock, req->head.xid, ret);
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_accept_handler
+ ****************************************************************************/
+
+static int nrf91_usrsock_accept_handler(struct nrf91_usrsock_s *usrsock,
+                                        const void *data, size_t len)
+{
+  const struct usrsock_request_accept_s *req        = data;
+  struct usrsock_message_datareq_ack_s  *ack;
+  struct nrf_sockaddr_in6                address;
+  nrf_socklen_t                          outaddrlen;
+  socklen_t                              inaddrlen  = req->max_addrlen;
+  int                                    sockfd     = 0;
+  int                                    ret        = 0;
+
+  if (inaddrlen == sizeof(struct sockaddr_in))
+    {
+      outaddrlen = sizeof(struct nrf_sockaddr_in);
+    }
+  else
+    {
+      outaddrlen = sizeof(struct nrf_sockaddr_in6);
+    }
+
+  ack = (struct usrsock_message_datareq_ack_s *)usrsock->out;
+  sockfd = nrf_accept(req->usockid,
+                      outaddrlen ? (struct nrf_sockaddr *)&address : NULL,
+                      (nrf_socklen_t)outaddrlen ? &outaddrlen : NULL);
+  if (ret < 0)
+    {
+      nerr("nrf_accpet failed %d", errno);
+      ret = -errno;
+    }
+
+  nrf2nx_sockaddr((struct nrf_sockaddr *)&address,
+                  (struct sockaddr *)(ack + 1));
+
+  if (sockfd >= 0)
+    {
+      /* Append index as usockid to the payload */
+
+      if (outaddrlen <= inaddrlen)
+        {
+          *(int16_t *)((void *)(ack + 1) + outaddrlen) = sockfd;
+        }
+      else
+        {
+          *(int16_t *)((void *)(ack + 1) + inaddrlen) = sockfd;
+        }
+
+      ret = sizeof(int16_t); /* Return usockid size */
+    }
+  else
+    {
+      ret = sockfd;
+    }
+
+  ret = nrf91_usrsock_send_dack(usrsock, ack, req->head.xid, ret,
+                          inaddrlen, outaddrlen);
+  if (ret >= 0 && sockfd >= 0)
+    {
+      ret = nrf91_usrsock_send_event(usrsock, sockfd,
+                                     USRSOCK_EVENT_SENDTO_READY);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_ioctl_handler
+ ****************************************************************************/
+
+static int nrf91_usrsock_ioctl_handler(struct nrf91_usrsock_s *usrsock,
+                                       const void *data, size_t len)
+{
+  const struct usrsock_request_ioctl_s *req = data;
+  struct usrsock_message_datareq_ack_s *ack = NULL;
+  int                                   ret = 0;
+
+  ack = (struct usrsock_message_datareq_ack_s *)usrsock->out;
+  memcpy(ack + 1, req + 1, req->arglen);
+  ret = nrf91_usrsock_ioctl(req->usockid,
+                            req->cmd,
+                            (unsigned long)(ack + 1));
+
+  return nrf91_usrsock_send_dack(usrsock, ack, req->head.xid, ret,
+                           req->arglen, req->arglen);
+}
+
+/****************************************************************************
+ * Name: nrf91_usrsock_shutdown_handler
+ ****************************************************************************/
+
+static int nrf91_usrsock_shutdown_handler(struct nrf91_usrsock_s *usrsock,
+                                          const void *data, size_t len)
+{
+  const struct usrsock_request_shutdown_s *req = data;
+  int                                      ret = 0;
+
+  ret = nrf_usrsock_shutdown(req->usockid, req->how);
+  return nrf91_usrsock_send_ack(usrsock, req->head.xid, ret);
+}
+
+#ifndef CONFIG_NRF91_MODEM_AT
+/****************************************************************************
+ * Name: nrf91_modem_at_notify_handler
+ ****************************************************************************/
+
+static void nrf91_modem_at_notify_handler(const char *notif)
+{
+  /* TODO */
+
+  printf("%s\n", notif);
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: usrsock_register
+ ****************************************************************************/
+
+void usrsock_register(void)
+{
+#ifndef CONFIG_NRF91_MODEM_AT
+  /* Initialize AT modem */
+
+  nrf_modem_at_notif_handler_set(nrf91_modem_at_notify_handler);
+  nrf_modem_at_cmd_custom_set(NULL, 0);
+#endif
+}
+
+/****************************************************************************
+ * Name: usrsock_request
+ ****************************************************************************/
+
+int usrsock_request(struct iovec *iov, unsigned int iovcnt)
+{
+  struct usrsock_request_common_s *common = NULL;
+  int                              ret    = 0;
+
+  /* Copy request to buffer */
+
+  ret = usrsock_iovec_get(g_usrsock.in, sizeof(g_usrsock.in),
+                          iov, iovcnt, 0, NULL);
+  if (ret <= 0)
+    {
+      return ret;
+    }
+
+  common = (struct usrsock_request_common_s *)g_usrsock.in;
+
+  if (common->reqid >= 0 &&
+      common->reqid < USRSOCK_REQUEST__MAX)
+    {
+      ret = g_usrsock_handler[common->reqid](&g_usrsock,
+                                             g_usrsock.in, ret);
+      if (ret < 0)
+        {
+          nerr("Usrsock request %d failed: %d\n", common->reqid, ret);
+        }
+    }
+  else
+    {
+      nerr("Invalid request id: %d\n", common->reqid);
+    }
+
+  return ret;
+}
diff --git a/arch/arm/src/nrf91/nrf91_modem_sock.h 
b/arch/arm/src/nrf91/nrf91_modem_sock.h
new file mode 100644
index 0000000000..8365541dfb
--- /dev/null
+++ b/arch/arm/src/nrf91/nrf91_modem_sock.h
@@ -0,0 +1,29 @@
+/****************************************************************************
+ * arch/arm/src/nrf91/nrf91_modem_sock.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/


Reply via email to