diff options
author | Ziyang Cheng <ziyangch@google.com> | 2023-02-23 07:58:26 +0000 |
---|---|---|
committer | Ziyang Cheng <ziyangch@google.com> | 2023-03-09 22:34:25 +0000 |
commit | 5586f9fedb8664fdf9e5ad4c4cc3ea823e1395ae (patch) | |
tree | 3c294e2605e63c3094afa8fb796a840b9f4b24ae | |
parent | a626f65972e2f0d41a3efc0478ed30d3ba58236b (diff) | |
download | nanohub-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.c | 82 | ||||
-rw-r--r-- | main.h | 2 | ||||
-rw-r--r-- | nanohub_exports.h | 15 |
3 files changed, 76 insertions, 23 deletions
@@ -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; @@ -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_ */ |