summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZiyang Cheng <ziyangch@google.com>2023-02-23 07:58:26 +0000
committerZiyang Cheng <ziyangch@google.com>2023-03-09 22:34:25 +0000
commit5586f9fedb8664fdf9e5ad4c4cc3ea823e1395ae (patch)
tree3c294e2605e63c3094afa8fb796a840b9f4b24ae
parenta626f65972e2f0d41a3efc0478ed30d3ba58236b (diff)
downloadnanohub-5586f9fedb8664fdf9e5ad4c4cc3ea823e1395ae.tar.gz
Add |on_message_received| callback in |nanohub_io|.
-Currently /dev/nanohub_audio is not used. -nanohub_audio channel can only be accessible by the kernel. -Always drop the message if the channel is a kernel channel and notify the listener through the |on_message_received| callback if it is valid. See: go/mcu-to-kernel-messaging Test:Send a message when AudioService is started. Verify mic_codec receives the message. Bug: 271341684 Change-Id: I856f162206e3c619da24c3c3b5027a44647e386d Signed-off-by: Ziyang Cheng <ziyangch@google.com>
-rw-r--r--main.c82
-rw-r--r--main.h2
-rw-r--r--nanohub_exports.h15
3 files changed, 76 insertions, 23 deletions
diff --git a/main.c b/main.c
index ce658ad..4225120 100644
--- a/main.c
+++ b/main.c
@@ -92,6 +92,12 @@ struct gpio_config {
u16 data_off;
};
+struct device_config {
+ const char *name;
+ const uint8_t channels;
+ const bool is_kernel;
+};
+
#define GPIO_OPT_HAS_IRQ 0x0001
#define GPIO_OPT_OPTIONAL 0x8000
@@ -115,6 +121,8 @@ static int nanohub_hw_reset(struct nanohub_data *data, int boot_mode);
// Kernel client support.
static struct nanohub_data *priv_nanohub_data;
EXPORT_SYMBOL(nanohub_send_message);
+EXPORT_SYMBOL(nanohub_register_listener);
+EXPORT_SYMBOL(nanohub_unregister_listener);
static struct class *sensor_class;
static int major;
@@ -176,13 +184,15 @@ static inline void nanohub_notify_thread(struct nanohub_data *data)
static inline void nanohub_io_init(struct nanohub_io *io,
struct nanohub_data *data,
struct device *dev,
- int id)
+ int id,
+ bool is_kernel)
{
init_waitqueue_head(&io->buf_wait);
INIT_LIST_HEAD(&io->buf_list);
io->data = data;
io->dev = dev;
io->id = id;
+ io->is_kernel = is_kernel;
atomic_set(&io->busy, 0);
}
@@ -1383,38 +1393,35 @@ done:
static int nanohub_create_devices(struct nanohub_data *data)
{
int i, j, k, ret;
- static const char *names[] = {
- "nanohub_comms",
- "nanohub",
- "nanohub_audio",
- "nanohub_display",
- "nanohub_render",
- "nanohub_debug_log",
- "nanohub_metrics",
- "nanohub_console",
- "nanohub_rpc0",
- "nanohub_rpc1",
- "nanohub_brightness"
- };
- const uint8_t ids[] = {
- 1, ID_NANOHUB_CLIENT_NUM_IDS, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ static const struct device_config device_configs[] = {
+ {"nanohub_comms", 1, false},
+ {"nanohub", ID_NANOHUB_CLIENT_NUM_IDS, false},
+ {"nanohub_audio", 1, true},
+ {"nanohub_display", 1, false},
+ {"nanohub_render", 1, false},
+ {"nanohub_debug_log", 1, false},
+ {"nanohub_metrics", 1, false},
+ {"nanohub_console", 1, false},
+ {"nanohub_rpc0", 1, false},
+ {"nanohub_rpc1", 1, false},
+ {"nanohub_brightness", 1, false},
};
for (i = 0, j = 0; j < ID_NANOHUB_MAX - ID_NANOHUB_CLIENT_NUM_IDS + 1; ++j) {
struct device *dev = device_create(sensor_class, NULL,
MKDEV(major, i), data,
- names[j]);
+ device_configs[j].name);
if (IS_ERR(dev)) {
ret = PTR_ERR(dev);
pr_err("nanohub: device_create failed for %s; err=%d\n",
- names[j], ret);
+ device_configs[j].name, ret);
goto fail_dev;
}
- for (k = 0; k < ids[j]; ++i, ++k) {
+ for (k = 0; k < device_configs[j].channels; ++i, ++k) {
struct nanohub_io *io = &data->io[i];
- nanohub_io_init(io, data, dev, i);
+ nanohub_io_init(io, data, dev, i, device_configs[j].is_kernel);
}
}
@@ -1516,7 +1523,7 @@ ssize_t nanohub_send_message(int channel_id, const char *buffer, size_t length)
int ret;
if (!data) {
- pr_warn("nanohub is not ready for kernel access\n");
+ pr_warn("%s: nanohub is not ready for kernel access\n", __func__);
return -EAGAIN;
}
@@ -1531,6 +1538,32 @@ ssize_t nanohub_send_message(int channel_id, const char *buffer, size_t length)
return ret;
}
+void nanohub_register_listener(int channel_id,
+ void (*on_message_received)(const char *buffer,
+ size_t length))
+{
+ struct nanohub_data *data = priv_nanohub_data;
+ struct nanohub_io *io;
+ if (!data) {
+ pr_warn("%s: nanohub is not ready for kernel access\n", __func__);
+ return;
+ }
+ io = &data->io[channel_id];
+ io->on_message_received = on_message_received;
+}
+
+void nanohub_unregister_listener(int channel_id)
+{
+ struct nanohub_data *data = priv_nanohub_data;
+ struct nanohub_io *io;
+ if (!data) {
+ pr_warn("%s: nanohub is not ready for kernel access\n", __func__);
+ return;
+ }
+ io = &data->io[channel_id];
+ io->on_message_received = NULL;
+}
+
static unsigned int nanohub_poll(struct file *file, poll_table *wait)
{
struct nanohub_io *io = file->private_data;
@@ -1655,7 +1688,7 @@ static void nanohub_process_buffer(struct nanohub_data *data, uint8_t id,
if (id == ID_NANOHUB_CLIENT && atomic_read(&io->busy) != 1) {
pr_info("nanohub: dropping packet for /dev/nanohub/%d\n", id);
- } else {
+ } else if (!io->is_kernel) {
nanohub_io_put_buf(io, *buf);
*buf = NULL;
}
@@ -1663,6 +1696,9 @@ static void nanohub_process_buffer(struct nanohub_data *data, uint8_t id,
if (wakeup)
__pm_wakeup_event(&data->wakesrc_read, data->wakeup_event_msec);
release_wakeup(data);
+ if (io->is_kernel && io->on_message_received) {
+ io->on_message_received((*buf)->buffer, (*buf)->length);
+ }
}
static int nanohub_kthread(void *arg)
@@ -2176,7 +2212,7 @@ struct iio_dev *nanohub_probe(struct device *dev, struct iio_dev *iio_dev)
init_waitqueue_head(&data->kthread_wait);
- nanohub_io_init(&data->free_pool, data, dev, 0);
+ nanohub_io_init(&data->free_pool, data, dev, 0, false);
buf = vmalloc(sizeof(*buf) * READ_QUEUE_DEPTH);
data->vbuf = buf;
diff --git a/main.h b/main.h
index aef303e..b956343 100644
--- a/main.h
+++ b/main.h
@@ -50,6 +50,8 @@ struct nanohub_io {
struct list_head buf_list;
atomic_t busy;
uint8_t id;
+ bool is_kernel;
+ void (*on_message_received)(const char *buffer, size_t length);
};
#ifdef CONFIG_NANOHUB_BL_NXP
diff --git a/nanohub_exports.h b/nanohub_exports.h
index 8967724..f09a8af 100644
--- a/nanohub_exports.h
+++ b/nanohub_exports.h
@@ -31,4 +31,19 @@
extern ssize_t nanohub_send_message(int channel_id, const char *buffer,
size_t length);
+/**
+ * Register a message listener of a nanohub channel.
+ *
+ * on_message_received callback will be invoked when nanohub receives a new message
+ * from MCU on that channel.
+ */
+extern void nanohub_register_listener(
+ int channel_id,
+ void (*on_message_received)(const char *buffer, size_t length));
+
+/**
+ * Unregister the message listener of a nanohub channel.
+ */
+extern void nanohub_unregister_listener(int channel_id);
+
#endif /* _NANOHUB_EXPORTS_H_ */