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


The following commit(s) were added to refs/heads/master by this push:
     new a6c1ef3c52 wireless/bluetooth: add RPMSG HCI controller support
a6c1ef3c52 is described below

commit a6c1ef3c5236ea8f0071ae92b74ee4d76baa7c25
Author: raiden00pl <raide...@railab.me>
AuthorDate: Sat Mar 11 11:06:51 2023 +0100

    wireless/bluetooth: add RPMSG HCI controller support
---
 drivers/wireless/bluetooth/Kconfig              |  10 +
 drivers/wireless/bluetooth/Make.defs            |   8 +
 drivers/wireless/bluetooth/bt_rpmsghci.c        | 528 +++++++++++++++++++++++
 drivers/wireless/bluetooth/bt_rpmsghci.h        |  96 +++++
 drivers/wireless/bluetooth/bt_rpmsghci_server.c | 540 ++++++++++++++++++++++++
 include/nuttx/wireless/bluetooth/bt_rpmsghci.h  |  88 ++++
 6 files changed, 1270 insertions(+)

diff --git a/drivers/wireless/bluetooth/Kconfig 
b/drivers/wireless/bluetooth/Kconfig
index 41cd7d37d0..356830f96b 100644
--- a/drivers/wireless/bluetooth/Kconfig
+++ b/drivers/wireless/bluetooth/Kconfig
@@ -75,4 +75,14 @@ config BLUETOOTH_NULL
                loop" and nothing more:  It is a just a bit-bucket for outgoing
                packets; it generates no incoming packets.
 
+config BLUETOOTH_RPMSG_SERVER
+       bool "RPMSG Bluetooth HCI server support"
+       depends on EXPERIMENTAL
+       default n
+
+config BLUETOOTH_RPMSG
+       bool "RPMSG Bluetooth HCI client support"
+       depends on EXPERIMENTAL
+       default n
+
 endif # DRIVERS_BLUETOOTH
diff --git a/drivers/wireless/bluetooth/Make.defs 
b/drivers/wireless/bluetooth/Make.defs
index 0b7ab95ab7..963a172347 100644
--- a/drivers/wireless/bluetooth/Make.defs
+++ b/drivers/wireless/bluetooth/Make.defs
@@ -48,6 +48,14 @@ ifeq ($(CONFIG_BLUETOOTH_NULL),y)
 CSRCS += bt_null.c
 endif
 
+ifeq ($(CONFIG_BLUETOOTH_RPMSG_SERVER),y)
+CSRCS += bt_rpmsghci_server.c
+endif
+
+ifeq ($(CONFIG_BLUETOOTH_RPMSG),y)
+CSRCS += bt_rpmsghci.c
+endif
+
 # Include common Bluetooth driver build support
 
 DEPPATH += --dep-path wireless$(DELIM)bluetooth
diff --git a/drivers/wireless/bluetooth/bt_rpmsghci.c 
b/drivers/wireless/bluetooth/bt_rpmsghci.c
new file mode 100644
index 0000000000..29cf7288f6
--- /dev/null
+++ b/drivers/wireless/bluetooth/bt_rpmsghci.c
@@ -0,0 +1,528 @@
+/****************************************************************************
+ * drivers/wireless/bluetooth/bt_rpmsghci.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 <sys/param.h>
+
+#include <assert.h>
+#include <debug.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/net/bluetooth.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/rptun/openamp.h>
+#include <nuttx/wireless/bluetooth/bt_rpmsghci.h>
+
+#include "bt_rpmsghci.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct rpmsghci_s
+{
+  /* This must be te first thung in the structure so we can simply cast from
+   * struct rpmsghci_s to struct bt_driver_s.
+   */
+
+  struct bt_driver_s    btdev;
+  struct rpmsg_endpoint ept;
+  FAR const char       *cpuname;
+  FAR const char       *name;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int rpmsghci_default_handler(FAR struct rpmsg_endpoint *ept,
+                                    FAR void *data, size_t len,
+                                    uint32_t src, FAR void *priv);
+static int rpmsghci_recv_handler(FAR struct rpmsg_endpoint *ept,
+                                 FAR void *data, size_t len,
+                                 uint32_t src, FAR void *priv);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const rpmsg_ept_cb g_rpmsghci_handler[] =
+{
+  rpmsghci_default_handler, /* RPMSGHCI_OPEN */
+  rpmsghci_default_handler, /* RPMSGHCI_CLOSE */
+  rpmsghci_default_handler, /* RPMSGHCI_SEND */
+  rpmsghci_default_handler, /* RPMSGHCI_IOCTL */
+  rpmsghci_recv_handler,    /* RPMSGHCI_RECV */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rpmsghci_get_tx_payload_buffer
+ ****************************************************************************/
+
+static FAR void *
+rpmsghci_get_tx_payload_buffer(FAR struct rpmsghci_s *priv,
+                               FAR uint32_t *len)
+{
+  return rpmsg_get_tx_payload_buffer(&priv->ept, len, true);
+}
+
+/****************************************************************************
+ * Name: rpmsghci_send
+ *
+ * Description:
+ *   Send the rpmsg data and wait for ACK.
+ *
+ * Parameters:
+ *   priv    - rpmsg device handle
+ *   command - the command, RPMSGHCI_OPEN, RPMSGHCI_CLOSE, RPMSGHCI_SEND,
+ *                          RPMSGHCI_IOCTL
+ *   msg     - the message header
+ *   len     - length of the payload
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsghci_send(FAR struct rpmsghci_s *priv, uint32_t command,
+                         FAR struct rpmsghci_header_s *msg, int len)
+{
+  struct rpmsghci_cookie_s cookie;
+  int                      ret = OK;
+
+  memset(&cookie, 0, sizeof(struct rpmsghci_cookie_s));
+  nxsem_init(&cookie.sem, 0, 0);
+
+  msg->command = command;
+  msg->result  = -ENXIO;
+  msg->cookie  = (uintptr_t)&cookie;
+
+  ret = rpmsg_send_nocopy(&priv->ept, msg, len);
+  if (ret < 0)
+    {
+      goto errout;
+    }
+
+  ret = rpmsg_wait(&priv->ept, &cookie.sem);
+  if (ret >= 0)
+    {
+      ret = msg->result;
+    }
+
+errout:
+  nxsem_destroy(&cookie.sem);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: rpmsghci_bt_open
+ *
+ * Description:
+ *   Rpmsg-HCI open operation
+ *
+ * Parameters:
+ *   btdev  - the bt instance
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsghci_bt_open(struct bt_driver_s *btdev)
+{
+  FAR struct rpmsghci_s      *priv = NULL;
+  FAR struct rpmsghci_open_s *msg  = NULL;
+  uint32_t                    space = 0;
+  int                         ret  = OK;
+
+  /* Get RPMSG-HCI data */
+
+  DEBUGASSERT(btdev != NULL);
+  priv = (FAR struct rpmsghci_s *)btdev;
+
+  /* Perform the rpmsg write */
+
+  msg = rpmsghci_get_tx_payload_buffer(priv, &space);
+  if (msg == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  return rpmsghci_send(priv, RPMSGHCI_OPEN, &msg->header,
+                       sizeof(struct rpmsghci_open_s));
+}
+
+/****************************************************************************
+ * Name: rpmsghci_bt_close
+ *
+ * Description:
+ *   Rpmsg-HCI close operation
+ *
+ * Parameters:
+ *   btdev  - the bt instance
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static void rpmsghci_bt_close(struct bt_driver_s *btdev)
+{
+  FAR struct rpmsghci_s       *priv  = NULL;
+  FAR struct rpmsghci_close_s *msg   = NULL;
+  uint32_t                     space = 0;
+
+  /* Get RPMSG-HCI data */
+
+  DEBUGASSERT(btdev != NULL);
+  priv = (FAR struct rpmsghci_s *)btdev;
+
+  /* Perform the rpmsg write */
+
+  msg = rpmsghci_get_tx_payload_buffer(priv, &space);
+  if (msg == NULL)
+    {
+      return;
+    }
+
+  rpmsghci_send(priv, RPMSGHCI_CLOSE, &msg->header,
+                sizeof(struct rpmsghci_close_s));
+}
+
+/****************************************************************************
+ * Name: rpmsghci_bt_send
+ *
+ * Description:
+ *   Rpmsg-HCI send operation
+ *
+ * Parameters:
+ *   btdev  - the bt instance
+ *   type   - bt command type
+ *   data   - bt command data
+ *   len    - bt command data length
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsghci_bt_send(struct bt_driver_s *btdev, uint8_t type,
+                            void *data, size_t len)
+{
+  FAR struct rpmsghci_s      *priv  = NULL;
+  FAR struct rpmsghci_data_s *msg   = NULL;
+  uint32_t                    space = 0;
+  int                         ret   = OK;
+
+  wlinfo("rpmsghci_bt_send %d\n", type);
+
+  /* Get RPMSG-HCI data */
+
+  DEBUGASSERT(btdev != NULL);
+  priv = (FAR struct rpmsghci_s *)btdev;
+
+  if (data == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Perform the rpmsg write */
+
+  msg = rpmsghci_get_tx_payload_buffer(priv, &space);
+  if (msg == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  DEBUGASSERT(sizeof(struct rpmsghci_data_s) - 1 + len <= space);
+  memcpy(msg->data, data, len);
+  msg->type = type;
+  return rpmsghci_send(priv, RPMSGHCI_SEND, &msg->header,
+                       sizeof(struct rpmsghci_data_s) -1 + len);
+}
+
+/****************************************************************************
+ * Name: rpmsghci_bt_ioctl
+ *
+ * Description:
+ *   Rpmsg-HCI ioctl operation
+ *
+ * Parameters:
+ *   btdev  - the bt instance
+ *   cmd    - the ioctl command
+ *   arg    - the ioctl arguments
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsghci_bt_ioctl(FAR struct bt_driver_s *btdev, int cmd,
+                              unsigned long arg)
+{
+  /* TODO */
+
+  return -ENOTTY;
+}
+
+/****************************************************************************
+ * Name: rpmsghci_default_handler
+ *
+ * Description:
+ *   Default rpmsg-HCI response handler, this function will be called to
+ *   process the return message of rpmsghci_open(), rpmsghci_close(),
+ *   rpmsghci_send(), rpmsghci_ioctl().
+ *
+ * Parameters:
+ *   ept  - The rpmsg endpoint
+ *   data - The return message
+ *   len  - The return message length
+ *   src  - unknow
+ *   priv - unknow
+ *
+ * Returned Values:
+ *   Always OK
+ *
+ ****************************************************************************/
+
+static int rpmsghci_default_handler(FAR struct rpmsg_endpoint *ept,
+                                    FAR void *data, size_t len,
+                                    uint32_t src, FAR void *priv)
+{
+  FAR struct rpmsghci_header_s *header = data;
+  FAR struct rpmsghci_cookie_s *cookie = NULL;
+
+  if (header->cookie != 0)
+    {
+      cookie = (FAR struct rpmsghci_cookie_s *)(uintptr_t)header->cookie;
+      return rpmsg_post(ept, &cookie->sem);
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: rpmsghci_recv_handler
+ *
+ * Description:
+ *   Rpmsg-HCI receive handler.
+ *
+ * Parameters:
+ *   ept  - The rpmsg endpoint
+ *   data - The return message
+ *   len  - The return message length
+ *   src  - unknow
+ *   priv - unknow
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsghci_recv_handler(FAR struct rpmsg_endpoint *ept,
+                                 FAR void *data, size_t len,
+                                 uint32_t src, FAR void *priv)
+{
+  FAR struct rpmsghci_s      *client = NULL;
+  FAR struct rpmsghci_data_s *msg    = data;
+  int                         ret    = OK;
+
+  DEBUGASSERT(priv);
+  client = priv;
+
+  wlinfo("rpmsghci_recv_handler %d\n", msg->type);
+
+  ret = bt_netdev_receive(&client->btdev, msg->type, msg->data,
+                          len - sizeof(struct rpmsghci_data_s) + 1);
+  msg->header.result = ret;
+
+  return rpmsg_send(ept, msg, sizeof(struct rpmsghci_header_s));
+}
+
+/****************************************************************************
+ * Name: rpmsghci_client_ept_cb
+ *
+ * Description:
+ *   Rpmsg HCI end point callback function, this function will be called
+ *   when receive the remote cpu message.
+ *
+ * Parameters:
+ *   ept  - The rpmsg-HCI end point
+ *   data - The received data
+ *   len  - The received data length
+ *   src  - unknow
+ *   priv - unknow
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsghci_client_ept_cb(FAR struct rpmsg_endpoint *ept,
+                                  FAR void *data, size_t len,
+                                  uint32_t src, FAR void *priv)
+{
+  FAR struct rpmsghci_header_s *header  = data;
+  uint32_t                      command = header->command;
+
+  if (command < nitems(g_rpmsghci_handler))
+    {
+      return g_rpmsghci_handler[command](ept, data, len, src, priv);
+    }
+
+  return -EINVAL;
+}
+
+/****************************************************************************
+ * Name: rpmsghci_client_created
+ *
+ * Description:
+ *   Rpmsg HCI create function, this function will be called by rptun to
+ *   create a rpmsg-hci end point.
+ *
+ * Parameters:
+ *   rdev  - The rpmsg-hci end point
+ *   priv_ - Rpmsg-hci handle
+ *
+ * Returned Values:
+ *   None
+ *
+ ****************************************************************************/
+
+static void rpmsghci_client_created(FAR struct rpmsg_device *rdev,
+                                    FAR void *priv_)
+{
+  FAR struct rpmsghci_s *priv = priv_;
+  char                   eptname[RPMSG_NAME_SIZE];
+
+  if (strcmp(priv->cpuname, rpmsg_get_cpuname(rdev)) == 0)
+    {
+      snprintf(eptname, RPMSG_NAME_SIZE, "%s%s", RPMSGHCI_NAME_PREFIX,
+               priv->name);
+      priv->ept.priv = priv;
+      rpmsg_create_ept(&priv->ept, rdev, eptname,
+                       RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
+                       rpmsghci_client_ept_cb, NULL);
+    }
+}
+
+/****************************************************************************
+ * Name: rpmsghci_client_destroy
+ *
+ * Description:
+ *   Rpmsg HCI destroy function, this function will be called by rptun to
+ *   destroy rpmsg-HCI end point.
+ *
+ * Parameters:
+ *   rdev  - The rpmsg-HCI end point
+ *   priv_ - Rpmsg-HCI handle
+ *
+ * Returned Values:
+ *   None
+ *
+ ****************************************************************************/
+
+static void rpmsghci_client_destroy(FAR struct rpmsg_device *rdev,
+                                    FAR void *priv_)
+{
+  FAR struct rpmsghci_s *priv = priv_;
+
+  if (!strcmp(priv->cpuname, rpmsg_get_cpuname(rdev)))
+    {
+      rpmsg_destroy_ept(&priv->ept);
+    }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rpmsghci_register
+ *
+ * Description:
+ *   Rpmsg-HCI client initialize function, the client cpu should call
+ *   this function in the board initialize process.
+ *
+ * Parameters:
+ *   cpuname  - the server cpu name
+ *   name     - the HCI device you want to access in the remote cpu
+ *
+ * Returned Values:
+ *    A non-NULL handle is returned on success;
+ *    A NULL is returned on any failure.
+ *
+ ****************************************************************************/
+
+FAR struct bt_driver_s *rpmsghci_register(FAR const char *cpuname,
+                                          FAR const char *name)
+{
+  FAR struct rpmsghci_s *priv = NULL;
+
+  /* Validate input */
+
+  if (!cpuname || !name)
+    {
+      return NULL;
+    }
+
+  /* Create RPMSG-HCI driver */
+
+  priv = kmm_zalloc(sizeof(struct rpmsghci_s));
+  if (!priv)
+    {
+      return NULL;
+    }
+
+  /* Initialize BT driver */
+
+  priv->btdev.open  = rpmsghci_bt_open;
+  priv->btdev.close = rpmsghci_bt_close;
+  priv->btdev.send  = rpmsghci_bt_send;
+  priv->btdev.ioctl = rpmsghci_bt_ioctl;
+
+  /* Initialize RPMSG-HCI client data */
+
+  priv->cpuname = cpuname;
+  priv->name    = name;
+
+  /* Register the device with the openamp */
+
+  rpmsg_register_callback(priv,
+                          rpmsghci_client_created,
+                          rpmsghci_client_destroy,
+                          NULL,
+                          NULL);
+
+  return &priv->btdev;
+}
diff --git a/drivers/wireless/bluetooth/bt_rpmsghci.h 
b/drivers/wireless/bluetooth/bt_rpmsghci.h
new file mode 100644
index 0000000000..f34b0bd6af
--- /dev/null
+++ b/drivers/wireless/bluetooth/bt_rpmsghci.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+ * drivers/wireless/bluetooth/bt_rpmsghci.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.
+ *
+ ****************************************************************************/
+
+#ifndef __DRIVERS_WIRELESS_BLUETOOTH_BT_RPMSGHCI_H
+#define __DRIVERS_WIRELESS_BLUETOOTH_BT_RPMSGHCI_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdint.h>
+
+#include <nuttx/compiler.h>
+#include <nuttx/semaphore.h>
+
+/****************************************************************************
+ * Pre-processor definitions
+ ****************************************************************************/
+
+#define RPMSGHCI_NAME_PREFIX     "rpmsghci-"
+#define RPMSGHCI_NAME_PREFIX_LEN 9
+
+#define RPMSGHCI_OPEN            0 /* Device open */
+#define RPMSGHCI_CLOSE           1 /* Device close */
+#define RPMSGHCI_SEND            2 /* Data to a HCI controller */
+#define RPMSGHCI_IOCTL           3 /* Device ioctl */
+#define RPMSGHCI_RECV            4 /* Data from a HCI controller */
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* Rpmsg device cookie used to handle the response from the remote cpu */
+
+struct rpmsghci_cookie_s
+{
+  sem_t sem;
+};
+
+begin_packed_struct struct rpmsghci_header_s
+{
+  uint32_t                 command;
+  int32_t                  result;
+  uint64_t                 cookie;
+} end_packed_struct;
+
+begin_packed_struct struct rpmsghci_open_s
+{
+  struct rpmsghci_header_s header;
+} end_packed_struct;
+
+#define rpmsghci_close_s rpmsghci_open_s
+
+begin_packed_struct struct rpmsghci_data_s
+{
+  struct rpmsghci_header_s header;
+  uint8_t                  type;
+  char                     data[1];
+} end_packed_struct;
+
+begin_packed_struct struct rpmsghci_ioctl_s
+{
+  struct rpmsghci_header_s header;
+  uint64_t                 filep;
+  uint64_t                 arg;
+  uint32_t                 arglen;
+  int32_t                  request;
+  char                     buf[1];
+} end_packed_struct;
+
+/****************************************************************************
+ * Internal function prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Internal data
+ ****************************************************************************/
+
+#endif /* __DRIVERS_WIRELESS_BLUETOOTH_BT_RPMSGHCI_H */
diff --git a/drivers/wireless/bluetooth/bt_rpmsghci_server.c 
b/drivers/wireless/bluetooth/bt_rpmsghci_server.c
new file mode 100644
index 0000000000..b91cf59770
--- /dev/null
+++ b/drivers/wireless/bluetooth/bt_rpmsghci_server.c
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * drivers/wireless/bluetooth/bt_rpmsghci_server.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 <sys/param.h>
+
+#include <assert.h>
+#include <debug.h>
+#include <stdlib.h>
+
+#include <nuttx/rptun/openamp.h>
+#include <nuttx/wireless/bluetooth/bt_rpmsghci.h>
+
+#include "bt_rpmsghci.h"
+
+/****************************************************************************
+ * Pre-processor definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct rpmsghci_server_s
+{
+  struct rpmsg_endpoint   ept;
+  FAR struct bt_driver_s *btdev;
+  FAR const char         *name;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int rpmsghci_open_handler(FAR struct rpmsg_endpoint *ept,
+                                 FAR void *data, size_t len,
+                                 uint32_t src, FAR void *priv);
+static int rpmsghci_close_handler(FAR struct rpmsg_endpoint *ept,
+                                  FAR void *data, size_t len,
+                                  uint32_t src, FAR void *priv);
+static int rpmsghci_send_handler(FAR struct rpmsg_endpoint *ept,
+                                 FAR void *data, size_t len,
+                                 uint32_t src, FAR void *priv);
+static int rpmsghci_ioctl_handler(FAR struct rpmsg_endpoint *ept,
+                                  FAR void *data, size_t len,
+                                  uint32_t src, FAR void *priv);
+static int rpmsghci_default_handler(FAR struct rpmsg_endpoint *ept,
+                                    FAR void *data, size_t len,
+                                    uint32_t src, FAR void *priv);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const rpmsg_ept_cb g_rpmsghci_handler[] =
+{
+  rpmsghci_open_handler,       /* RPMSGHCI_OPEN */
+  rpmsghci_close_handler,      /* RPMSGHCI_CLOSE */
+  rpmsghci_send_handler,       /* RPMSGHCI_SEND */
+  rpmsghci_ioctl_handler,      /* RPMSGHCI_IOCTL */
+  rpmsghci_default_handler,    /* RPMSGHCI_RECV */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rpmsghci_get_tx_payload_buffer
+ ****************************************************************************/
+
+static FAR void *
+rpmsghci_get_tx_payload_buffer(FAR struct rpmsghci_server_s *priv,
+                               FAR uint32_t *len)
+{
+  return rpmsg_get_tx_payload_buffer(&priv->ept, len, true);
+}
+
+/****************************************************************************
+ * Name: rpmsghci_send
+ *
+ * Description:
+ *   Send the rpmsg data and wait for ACK.
+ *
+ * Parameters:
+ *   priv    - rpmsg device handle
+ *   command - the command, RPMSGHCI_OPEN, RPMSGHCI_CLOSE, RPMSGHCI_SEND,
+ *                          RPMSGHCI_IOCTL
+ *   msg     - the message header
+ *   len     - length of the payload
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsghci_send(FAR struct rpmsghci_server_s *priv,
+                         uint32_t command, FAR struct rpmsghci_header_s *msg,
+                         int len)
+{
+  struct rpmsghci_cookie_s cookie;
+  int                      ret = OK;
+
+  memset(&cookie, 0, sizeof(struct rpmsghci_cookie_s));
+  nxsem_init(&cookie.sem, 0, 0);
+
+  msg->command = command;
+  msg->result  = -ENXIO;
+  msg->cookie  = (uintptr_t)&cookie;
+
+  ret = rpmsg_send_nocopy(&priv->ept, msg, len);
+  if (ret < 0)
+    {
+      goto errout;
+    }
+
+  ret = rpmsg_wait(&priv->ept, &cookie.sem);
+  if (ret >= 0)
+    {
+      ret = msg->result;
+    }
+
+errout:
+  nxsem_destroy(&cookie.sem);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: rpmsghci_open_handler
+ *
+ * Description:
+ *   Rpmsg-HCI device open handler.
+ *
+ * Parameters:
+ *   ept  - The rpmsg endpoint
+ *   data - The return message
+ *   len  - The return message length
+ *   src  - unknow
+ *   priv - unknow
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsghci_open_handler(FAR struct rpmsg_endpoint *ept,
+                                 FAR void *data, size_t len,
+                                 uint32_t src, FAR void *priv)
+{
+  FAR struct rpmsghci_server_s *server = NULL;
+  FAR struct bt_driver_s       *btdev  = NULL;
+  FAR struct rpmsghci_data_s   *msg    = data;
+  int                           ret    = OK;
+
+  DEBUGASSERT(priv);
+  server = priv;
+  DEBUGASSERT(server->btdev);
+  btdev = server->btdev;
+
+  if (btdev->open)
+    {
+      ret = btdev->open(btdev);
+    }
+
+  msg->header.result = ret;
+
+  return rpmsg_send(ept, msg, sizeof(struct rpmsghci_header_s));
+}
+
+/****************************************************************************
+ * Name: rpmsghci_close_handler
+ *
+ * Description:
+ *   Rpmsg-HCI close handler.
+ *
+ * Parameters:
+ *   ept  - The rpmsg endpoint
+ *   data - The return message
+ *   len  - The return message length
+ *   src  - unknow
+ *   priv - unknow
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsghci_close_handler(FAR struct rpmsg_endpoint *ept,
+                                 FAR void *data, size_t len,
+                                 uint32_t src, FAR void *priv)
+{
+  FAR struct rpmsghci_server_s *server = NULL;
+  FAR struct bt_driver_s       *btdev  = NULL;
+  FAR struct rpmsghci_data_s   *msg    = data;
+  int                           ret    = OK;
+
+  DEBUGASSERT(priv);
+  server = priv;
+  DEBUGASSERT(server->btdev);
+  btdev = server->btdev;
+
+  if (btdev->close)
+    {
+      btdev->close(btdev);
+    }
+
+  msg->header.result = ret;
+
+  return rpmsg_send(ept, msg, sizeof(struct rpmsghci_header_s));
+}
+
+/****************************************************************************
+ * Name: rpmsghci_send_handler
+ *
+ * Description:
+ *   Rpmsg-HCI send handler.
+ *
+ * Parameters:
+ *   ept  - The rpmsg endpoint
+ *   data - The return message
+ *   len  - The return message length
+ *   src  - unknow
+ *   priv - unknow
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsghci_send_handler(FAR struct rpmsg_endpoint *ept,
+                                  FAR void *data, size_t len,
+                                  uint32_t src, FAR void *priv)
+{
+  FAR struct rpmsghci_server_s *server = NULL;
+  FAR struct bt_driver_s       *btdev  = NULL;
+  FAR struct rpmsghci_data_s   *msg    = data;
+  int                           ret    = OK;
+
+  DEBUGASSERT(priv);
+  server = priv;
+  DEBUGASSERT(server->btdev);
+  btdev = server->btdev;
+
+  wlinfo("rpmsghci_send_handler %d\n", msg->type);
+
+  ret = btdev->send(btdev, msg->type, msg->data,
+                    len - sizeof(struct rpmsghci_data_s) + 1);
+
+  msg->header.result = ret;
+
+  return rpmsg_send(ept, msg, sizeof(struct rpmsghci_header_s));
+}
+
+/****************************************************************************
+ * Name: rpmsghci_ioctl_handler
+ *
+ * Description:
+ *   Rpmsg-HCI ioctl handler.
+ *
+ * Parameters:
+ *   ept  - The rpmsg endpoint
+ *   data - The return message
+ *   len  - The return message length
+ *   src  - unknow
+ *   priv - unknow
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsghci_ioctl_handler(FAR struct rpmsg_endpoint *ept,
+                                  FAR void *data, size_t len,
+                                  uint32_t src, FAR void *priv)
+{
+  FAR struct rpmsghci_server_s *server = NULL;
+  FAR struct bt_driver_s       *btdev  = NULL;
+  FAR struct rpmsghci_ioctl_s  *msg    = data;
+  int                           ret    = OK;
+
+  DEBUGASSERT(priv);
+  server = priv;
+  DEBUGASSERT(server->btdev);
+  btdev = server->btdev;
+
+  ret = btdev->ioctl(btdev, msg->request,
+                     msg->arglen > 0 ? (unsigned long)msg->buf :
+                     msg->arg);
+
+  msg->header.result = ret;
+
+  /* Send the entire frame so as not to lose ioctl returned data */
+
+  return rpmsg_send(ept, msg, len);
+}
+
+/****************************************************************************
+ * Name: rpmsghci_default_handler
+ *
+ * Description:
+ *   Default rpmsg-HCI response handler, this function will be called to
+ *   process the return message of rpmsghci_recv()
+ *
+ * Parameters:
+ *   ept  - The rpmsg endpoint
+ *   data - The return message
+ *   len  - The return message length
+ *   src  - unknow
+ *   priv - unknow
+ *
+ * Returned Values:
+ *   Always OK
+ *
+ ****************************************************************************/
+
+static int rpmsghci_default_handler(FAR struct rpmsg_endpoint *ept,
+                                    FAR void *data, size_t len,
+                                    uint32_t src, FAR void *priv)
+{
+  FAR struct rpmsghci_header_s *header = data;
+  FAR struct rpmsghci_cookie_s *cookie = NULL;
+
+  if (header->cookie != 0)
+    {
+      cookie = (FAR struct rpmsghci_cookie_s *)(uintptr_t)header->cookie;
+      return rpmsg_post(ept, &cookie->sem);
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: rpmsghci_ns_match
+ *
+ * Description:
+ *   Check if we match to the rpmsg name service.
+ *
+ ****************************************************************************/
+
+static bool rpmsghci_ns_match(FAR struct rpmsg_device *rdev, FAR void *priv,
+                              FAR const char *name, uint32_t dest)
+{
+  return !strncmp(name, RPMSGHCI_NAME_PREFIX, RPMSGHCI_NAME_PREFIX_LEN);
+}
+
+/****************************************************************************
+ * Name: rpmsghci_ept_cb
+ *
+ * Description:
+ *   Rpmsg HCI end point callback function, this function will be called
+ *   when receive the client cpu message.
+ *
+ * Parameters:
+ *   ept  - The rpmsg-HCI end point
+ *   data - The received data
+ *   len  - The received data length
+ *   src  - unknow
+ *   priv - unknow
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsghci_ept_cb(FAR struct rpmsg_endpoint *ept, FAR void *data,
+                           size_t len, uint32_t src, FAR void *priv)
+{
+  FAR struct rpmsghci_header_s *header  = data;
+  uint32_t                      command = header->command;
+
+  if (command < nitems(g_rpmsghci_handler))
+    {
+      return g_rpmsghci_handler[command](ept, data, len, src, priv);
+    }
+
+  return -EINVAL;
+}
+
+/****************************************************************************
+ * Name: rpmsghci_ns_unbind
+ *
+ * Description:
+ *   Unbind from the rpmsg name service.
+ *
+ ****************************************************************************/
+
+static void rpmsghci_ns_unbind(FAR struct rpmsg_endpoint *ept)
+{
+  rpmsg_destroy_ept(ept);
+  kmm_free(ept);
+}
+
+/****************************************************************************
+ * Name: rpmsghci_ns_bind
+ *
+ * Description:
+ *   Bind to the rpmsg name service.
+ *
+ ****************************************************************************/
+
+static void rpmsghci_ns_bind(FAR struct rpmsg_device *rdev, FAR void *priv,
+                             FAR const char *name, uint32_t dest)
+{
+  FAR struct rpmsghci_server_s *server = priv;
+
+  server->ept.priv = priv;
+  rpmsg_create_ept(&server->ept, rdev, name,
+                   RPMSG_ADDR_ANY, dest,
+                   rpmsghci_ept_cb, rpmsghci_ns_unbind);
+}
+
+/****************************************************************************
+ * Name: rpmsghci_bt_receive
+ *
+ * Description:
+ *   Called by the Bluetooth low-level driver when new data is received from
+ *   the radio.  Transfers data to the RPMSG client.
+ *
+ *   This callback should not be called from the interrupt context !
+ *
+ * Returned Value:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+int rpmsghci_bt_receive(FAR struct bt_driver_s *btdev, uint8_t type,
+                        FAR void *data, size_t len)
+{
+  FAR struct rpmsghci_server_s *priv  = NULL;
+  FAR struct rpmsghci_data_s   *msg   = NULL;
+  uint32_t                      space = 0;
+  int                           ret   = OK;
+
+  wlinfo("rpmsghci_bt_receive %d\n", type);
+
+  /* Get RPMSG-HCI data */
+
+  DEBUGASSERT(btdev != NULL);
+  priv = btdev->priv;
+
+  if (data == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Perform the rpmsg write */
+
+  msg = rpmsghci_get_tx_payload_buffer(priv, &space);
+  if (msg == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  DEBUGASSERT(sizeof(struct rpmsghci_data_s) - 1 + len <= space);
+  memcpy(msg->data, data, len);
+  msg->type = type;
+  return rpmsghci_send(priv, RPMSGHCI_RECV, &msg->header,
+                       sizeof(struct rpmsghci_data_s) -1 + len);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rpmsghci_server_init
+ *
+ * Description:
+ *   Rpmsg-HCI server initialize function, the server cpu should call
+ *   this function.
+ *
+ * Parameters:
+ *   name - RPMSG-HCI server name
+ *   bt   - BT device handler
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+int rpmshci_server_init(FAR const char *name, FAR struct bt_driver_s *btdev)
+{
+  struct rpmsghci_server_s *priv = NULL;
+  int                       ret  = OK;
+
+  /* Validate input */
+
+  if (!name || !btdev)
+    {
+      return -EINVAL;
+    }
+
+  /* Create RPMSG-HCI server */
+
+  priv = kmm_zalloc(sizeof(struct rpmsghci_server_s));
+  if (!priv)
+    {
+      return -ENOMEM;
+    }
+
+  /* Connect BT receive callback and RPMSG as priv */
+
+  btdev->receive = rpmsghci_bt_receive;
+  btdev->priv    = priv;
+
+  /* Initialize RPMSG-HCI server data */
+
+  priv->name  = name;
+  priv->btdev = btdev;
+
+  ret = rpmsg_register_callback(priv, NULL, NULL,
+                                rpmsghci_ns_match,
+                                rpmsghci_ns_bind);
+  if (ret < 0)
+    {
+      kmm_free(priv);
+    }
+
+  return ret;
+}
diff --git a/include/nuttx/wireless/bluetooth/bt_rpmsghci.h 
b/include/nuttx/wireless/bluetooth/bt_rpmsghci.h
new file mode 100644
index 0000000000..fb0381179a
--- /dev/null
+++ b/include/nuttx/wireless/bluetooth/bt_rpmsghci.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+ * include/nuttx/wireless/bluetooth/bt_rpmsghci.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.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_WIRELESS_BLUETOOTH_BT_RPMSGHCI_H
+#define __INCLUDE_NUTTX_WIRELESS_BLUETOOTH_BT_RPMSGHCI_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/wireless/bluetooth/bt_driver.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef CONFIG_BLUETOOTH_RPMSG_SERVER
+
+/****************************************************************************
+ * Name: rpmsghci_server_init
+ *
+ * Description:
+ *   Rpmsg-HCI server initialize function, the server cpu should call
+ *   this function.
+ *
+ * Parameters:
+ *   name - RPMSG-HCI server name
+ *   bt   - BT device handler
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+int rpmshci_server_init(FAR const char *name, FAR struct bt_driver_s *dev);
+#endif
+
+#ifdef CONFIG_BLUETOOTH_RPMSG
+
+/****************************************************************************
+ * Name: rpmsghci_register
+ *
+ * Description:
+ *   Rpmsg-HCI client initialize function, the client cpu should call
+ *   this function in the board initialize process.
+ *
+ * Parameters:
+ *   cpuname  - the server cpu name
+ *   name     - the HCI device you want to access in the remote cpu
+ *
+ * Returned Values:
+ *    A non-NULL handle is returned on success;
+ *    A NULL is returned on any failure.
+ *
+ ****************************************************************************/
+
+FAR struct bt_driver_s *rpmsghci_register(FAR const char *remotecpu,
+                                          FAR const char *name);
+#endif
+
+#endif /* __INCLUDE_NUTTX_WIRELESS_BLUETOOTH_BT_RPMSGHCI_H */


Reply via email to