lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250705004036.3828-7-damien.riegel@silabs.com>
Date: Fri,  4 Jul 2025 20:40:36 -0400
From: Damien Riégel <damien.riegel@...abs.com>
To: greybus-dev@...ts.linaro.org
Cc: linux-kernel@...r.kernel.org, linux-devel@...abs.com,
        Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
        Alex Elder <elder@...nel.org>, Johan Hovold <johan@...nel.org>,
        Damien Riégel <damien.riegel@...abs.com>
Subject: [RFC 6/6] greybus: add class driver for Silabs Bluetooth

This class only supports one type of operation:
  - name: BLE_TRANSFER
  - id: 0x01
  - unidirectional
  - payload is:
    - first byte: HCI packet type
    - HCI packet

Implementation is very naive and doesn't keep track of in-flight frames.
The goal of this commit is mostly to open a discussion. What would be
the process to add new bundle and protocol to Greybus? Should Linux be
considered the actual standard (as it already differs in subtle ways
from the official specification)? Or should the (official? [1])
specifications be updated first?

[1] https://github.com/projectara/greybus-spec

Signed-off-by: Damien Riégel <damien.riegel@...abs.com>
---
 MAINTAINERS                          |   6 +
 drivers/staging/greybus/Kconfig      |   9 ++
 drivers/staging/greybus/Makefile     |   6 +
 drivers/staging/greybus/silabs-ble.c | 203 +++++++++++++++++++++++++++
 4 files changed, 224 insertions(+)
 create mode 100644 drivers/staging/greybus/silabs-ble.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 10385b5344b..ea0923741cf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10009,6 +10009,12 @@ F:	drivers/staging/greybus/sdio.c
 F:	drivers/staging/greybus/spi.c
 F:	drivers/staging/greybus/spilib.c
 
+GREYBUS BLUETOOTH DRIVER
+M:	Damien Riégel <damien.riegel@...abs.com>
+R:	Silicon Labs Kernel Team <linux-devel@...abs.com>
+S:	Supported
+F:	drivers/staging/greybus/silabs-ble.c
+
 GREYBUS BEAGLEPLAY DRIVERS
 M:	Ayush Singh <ayushdevel1325@...il.com>
 L:	greybus-dev@...ts.linaro.org (moderated for non-subscribers)
diff --git a/drivers/staging/greybus/Kconfig b/drivers/staging/greybus/Kconfig
index 1e745a8d439..3d14eabb196 100644
--- a/drivers/staging/greybus/Kconfig
+++ b/drivers/staging/greybus/Kconfig
@@ -213,4 +213,13 @@ config GREYBUS_ARCHE
 	  To compile this code as a module, chose M here: the module
 	  will be called gb-arche.ko
 
+config GREYBUS_SILABS_BLUETOOTH
+	tristate "Greybus Silabs Bluetooth Class driver"
+	help
+	  Select this option if you have a Silicon Labs device that
+	  supports Bluetooth over Greybus.
+
+	  To compile this code as a module, chose M here: the module
+	  will be called gb-silabs-ble.ko
+
 endif	# GREYBUS
diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile
index 7c5e8962233..c61e402595a 100644
--- a/drivers/staging/greybus/Makefile
+++ b/drivers/staging/greybus/Makefile
@@ -71,3 +71,9 @@ obj-$(CONFIG_GREYBUS_USB)		+= gb-usb.o
 gb-arche-y	:= arche-platform.o arche-apb-ctrl.o
 
 obj-$(CONFIG_GREYBUS_ARCHE)	+= gb-arche.o
+
+
+# Greybus vendor driver
+gb-silabs-ble-y := silabs-ble.o
+
+obj-$(CONFIG_GREYBUS_SILABS_BLUETOOTH)	+= gb-silabs-ble.o
diff --git a/drivers/staging/greybus/silabs-ble.c b/drivers/staging/greybus/silabs-ble.c
new file mode 100644
index 00000000000..588e8e067e2
--- /dev/null
+++ b/drivers/staging/greybus/silabs-ble.c
@@ -0,0 +1,203 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Driver for Bluetooth HCI over Greybus.
+ *
+ * Copyright (c) 2025, Silicon Laboratories, Inc.
+ */
+
+#include <linux/greybus.h>
+#include <linux/skbuff.h>
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+#define GREYBUS_VENDOR_SILABS	0xBEEF
+#define GREYBUS_PRODUCT_EFX	0xCAFE
+
+#define GB_BLE_TRANSFER		0x01
+
+struct gb_ble {
+	struct gb_connection *conn;
+	struct hci_dev *hdev;
+	struct sk_buff_head txq;
+};
+
+static int gb_ble_open(struct hci_dev *hdev)
+{
+	struct gb_ble *ble = hci_get_drvdata(hdev);
+
+	skb_queue_head_init(&ble->txq);
+
+	return gb_connection_enable(ble->conn);
+}
+
+static int gb_ble_close(struct hci_dev *hdev)
+{
+	struct gb_ble *ble = hci_get_drvdata(hdev);
+
+	gb_connection_disable(ble->conn);
+
+	return 0;
+}
+
+static void gb_ble_xfer_done(struct gb_operation *operation)
+{
+	struct sk_buff *skb = gb_operation_get_data(operation);
+
+	kfree_skb(skb);
+}
+
+static int gb_ble_send(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct gb_ble *ble = hci_get_drvdata(hdev);
+	int ret;
+
+	memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
+
+	ret = gb_operation_unidirectional_async_timeout(ble->conn,
+							gb_ble_xfer_done, skb,
+							GB_BLE_TRANSFER,
+							skb->data, skb->len + 1,
+							GB_OPERATION_TIMEOUT_DEFAULT);
+
+	return -ENOMEM;
+}
+
+static int gb_ble_request_handler(struct gb_operation *operation)
+{
+	struct gb_ble *ble = gb_connection_get_data(operation->connection);
+	struct device *dev = &operation->connection->bundle->dev;
+	struct sk_buff *skb;
+	unsigned int skb_len;
+
+	switch (operation->type) {
+	case GB_BLE_TRANSFER:
+		/* Must be unidirectional as AP is not responding to this request. */
+		if (!gb_operation_is_unidirectional(operation))
+			return -EINVAL;
+
+		if (operation->request->payload_size < 2)
+			return -EINVAL;
+
+		skb_len = operation->request->payload_size - 1;
+		skb = bt_skb_alloc(skb_len, GFP_KERNEL);
+		if (!skb)
+			return -ENOMEM;
+
+		/* Prepare HCI SKB and pass it to upper layer */
+		hci_skb_pkt_type(skb) = ((u8 *)operation->request->payload)[0];
+		memcpy(skb_put(skb, skb_len), &(((u8 *)operation->request->payload)[1]), skb_len);
+		hci_skb_expect(skb) = skb_len;
+
+		hci_recv_frame(ble->hdev, skb);
+
+		break;
+	default:
+		dev_err(dev, "unsupported request: %u\n", operation->type);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int gb_ble_probe(struct gb_bundle *bundle,
+			const struct greybus_bundle_id *id)
+{
+	struct greybus_descriptor_cport *cport_desc;
+	struct gb_connection *connection;
+	struct gb_ble *ble;
+	int err;
+
+	if (bundle->num_cports != 1)
+		return -ENODEV;
+
+	cport_desc = &bundle->cport_desc[0];
+	if (cport_desc->protocol_id != GREYBUS_PROTOCOL_VENDOR)
+		return -ENODEV;
+
+	ble = kzalloc(sizeof(*ble), GFP_KERNEL);
+	if (!ble) {
+		err = -ENOMEM;
+		goto alloc_ble_fail;
+	}
+
+	greybus_set_drvdata(bundle, ble);
+
+	connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id),
+					  gb_ble_request_handler);
+	if (IS_ERR(connection)) {
+		err = PTR_ERR(connection);
+		goto connection_create_fail;
+	}
+
+	gb_connection_set_data(connection, ble);
+	ble->conn = connection;
+	ble->hdev = hci_alloc_dev();
+	if (!ble->hdev) {
+		err = -ENOMEM;
+		goto alloc_hdev_fail;
+	}
+
+	hci_set_drvdata(ble->hdev, ble);
+	ble->hdev->open = gb_ble_open;
+	ble->hdev->close = gb_ble_close;
+	ble->hdev->send = gb_ble_send;
+
+	err = hci_register_dev(ble->hdev);
+	if (err)
+		goto register_hdev_fail;
+
+	return 0;
+
+register_hdev_fail:
+	hci_free_dev(ble->hdev);
+alloc_hdev_fail:
+	gb_connection_destroy(connection);
+connection_create_fail:
+	kfree(ble);
+alloc_ble_fail:
+	return err;
+}
+
+static void gb_ble_disconnect(struct gb_bundle *bundle)
+{
+	struct gb_ble *ble = greybus_get_drvdata(bundle);
+
+	hci_unregister_dev(ble->hdev);
+	hci_free_dev(ble->hdev);
+
+	/*
+	 * The connection should be disabled by now as unregistering the HCI device
+	 * calls its close callback, so it should be safe to destroy the connection.
+	 */
+	gb_connection_destroy(ble->conn);
+
+	kfree(ble);
+}
+
+static const struct greybus_bundle_id gb_silabs_ble_id_table[] = {
+	{ GREYBUS_DEVICE(GREYBUS_VENDOR_SILABS, GREYBUS_PRODUCT_EFX, 1) },
+	{ }
+};
+MODULE_DEVICE_TABLE(greybus, gb_silabs_ble_id_table);
+
+static struct greybus_driver gb_silabs_ble_driver = {
+	.name		= "silabs-ble",
+	.probe		= gb_ble_probe,
+	.disconnect	= gb_ble_disconnect,
+	.id_table	= gb_silabs_ble_id_table,
+};
+
+static int silabs_ble_init(void)
+{
+	return greybus_register(&gb_silabs_ble_driver);
+}
+module_init(silabs_ble_init);
+
+static void __exit silabs_ble_exit(void)
+{
+	greybus_deregister(&gb_silabs_ble_driver);
+}
+module_exit(silabs_ble_exit);
+
+MODULE_DESCRIPTION("Bluetooth Driver for Silicon Labs EFx devices over Greybus");
+MODULE_LICENSE("GPL");
-- 
2.49.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ