From d56fbdb350f607e9673d931faad2e172928fb41c Mon Sep 17 00:00:00 2001 From: Ayush Singh <ayushsingh1325@gmail.com> Date: Tue, 11 Jul 2023 23:46:21 +0530 Subject: [PATCH] Initial interface discovery support Node, does not completely work yet since more SVC operations are needed. Signed-off-by: Ayush Singh <ayushsingh1325@gmail.com> --- include/greybus_protocol.h | 7 +- include/node.h | 5 ++ include/operations.h | 17 ++++- include/svc.h | 3 + src/main.c | 30 ++++---- src/node.c | 143 +++++++++++++++++++++++++++++++++---- src/operations.c | 37 +++++++++- src/svc.c | 39 ++++++---- 8 files changed, 234 insertions(+), 47 deletions(-) diff --git a/include/greybus_protocol.h b/include/greybus_protocol.h index cb3f44e..fe6004c 100644 --- a/include/greybus_protocol.h +++ b/include/greybus_protocol.h @@ -37,11 +37,14 @@ #define GB_SVC_TYPE_INTF_SET_PWRM_REQUEST 0x10 #define GB_SVC_TYPE_INTF_SET_PWRM_RESPONSE \ OP_RESPONSE | GB_SVC_TYPE_INTF_SET_PWRM_REQUEST +#define GB_SVC_TYPE_MODULE_INSERTED_REQUEST 0x1f +#define GB_SVC_TYPE_MODULE_INSERTED_RESPONSE \ + OP_RESPONSE | GB_SVC_TYPE_MODULE_INSERTED_REQUEST #define GB_SVC_UNIPRO_HIBERNATE_MODE 0x11 -#define GB_SVC_SETPWRM_PWR_OK 0x00 -#define GB_SVC_SETPWRM_PWR_LOCAL 0x01 +#define GB_SVC_SETPWRM_PWR_OK 0x00 +#define GB_SVC_SETPWRM_PWR_LOCAL 0x01 /* * All operation messages (both requests and responses) begin with diff --git a/include/node.h b/include/node.h index 7c7f64f..deade08 100644 --- a/include/node.h +++ b/include/node.h @@ -1,5 +1,10 @@ #ifndef _NODE_H_ #define _NODE_H_ +#include <zephyr/net/net_ip.h> + +struct gb_interface *node_find_by_addr(struct in6_addr *); + +struct gb_interface *node_create_interface(struct in6_addr *); #endif diff --git a/include/operations.h b/include/operations.h index 5654458..b8b3d76 100644 --- a/include/operations.h +++ b/include/operations.h @@ -17,6 +17,13 @@ #define E_NULL_REQUEST 1 #define E_ALREADY_SENT 2 +struct gb_controller; + +typedef struct gb_message *(*gb_controller_read_callback_t)( + struct gb_controller *, uint16_t); +typedef int (*gb_controller_write_callback_t)(struct gb_controller *, + struct gb_message *, uint16_t); + /* * Struct to represent greybus message. This is a variable sized type. * @@ -41,8 +48,8 @@ struct gb_message { * @param ctrl_data: private controller data */ struct gb_controller { - struct gb_message *(*read)(struct gb_controller *, uint16_t); - int (*write)(struct gb_controller *, struct gb_message *, uint16_t); + gb_controller_read_callback_t read; + gb_controller_write_callback_t write; void *ctrl_data; }; @@ -55,6 +62,7 @@ struct gb_controller { struct gb_interface { uint8_t id; struct gb_controller controller; + sys_dnode_t node; }; /* @@ -171,4 +179,9 @@ struct gb_message *gb_message_request_alloc(const void *, size_t, uint8_t, struct gb_message *gb_message_response_alloc(const void *, size_t, uint8_t, uint16_t); +struct gb_interface *gb_interface_alloc(gb_controller_read_callback_t, + gb_controller_write_callback_t, void *); + +void gb_interface_dealloc(struct gb_interface *); + #endif diff --git a/include/svc.h b/include/svc.h index e1c6417..ee2bce9 100644 --- a/include/svc.h +++ b/include/svc.h @@ -33,4 +33,7 @@ struct gb_interface *svc_init(); */ bool svc_is_ready(); + +int svc_send_module_inserted(uint8_t); + #endif diff --git a/src/main.c b/src/main.c index cef6a23..46b0799 100644 --- a/src/main.c +++ b/src/main.c @@ -6,10 +6,11 @@ #include "ap.h" #include "hdlc.h" -#include "node_handler.h" -#include "node_table.h" +// #include "node_handler.h" +// #include "node_table.h" #include "operations.h" #include "svc.h" +#include "node.h" #include <zephyr/sys/dlist.h> #include <stdbool.h> #include <zephyr/drivers/uart.h> @@ -24,10 +25,6 @@ #define UART_DEVICE_NODE DT_CHOSEN(zephyr_shell_uart) #define NODE_DISCOVERY_INTERVAL 5000 #define MAX_GREYBUS_NODES CONFIG_BEAGLEPLAY_GREYBUS_MAX_NODES -#define MAX_NUMBER_OF_SOCKETS CONFIG_NET_SOCKETS_POLL_MAX -#define NODE_READER_INTERVAL 500 -#define NODE_WRITER_INTERVAL 500 -#define NODE_POLL_TIMEOUT 500 LOG_MODULE_REGISTER(cc1352_greybus, CONFIG_BEAGLEPLAY_GREYBUS_LOG_LEVEL); @@ -38,8 +35,8 @@ static sys_dlist_t gb_connections_list = SYS_DLIST_STATIC_INIT(&gb_connections_list); // Thread responsible for beagleconnect node discovery. -// K_THREAD_DEFINE(node_discovery, 1024, node_discovery_entry, NULL, NULL, NULL, 5, -// 0, 0); +K_THREAD_DEFINE(node_discovery, 1024, node_discovery_entry, NULL, NULL, NULL, 5, + 0, 0); K_THREAD_DEFINE(apbridge, 2048, apbridge_entry, NULL, NULL, NULL, 5, 0, 0); @@ -84,6 +81,12 @@ static int get_all_nodes(struct in6_addr *node_array, static void node_discovery_entry(void *p1, void *p2, void *p3) { int ret; struct in6_addr node_array[MAX_GREYBUS_NODES]; + struct gb_interface *intf; + + // Wait until SVC is ready + while(!svc_is_ready()) { + k_sleep(K_MSEC(1000)); + } while (1) { ret = get_all_nodes(node_array, MAX_GREYBUS_NODES); @@ -94,13 +97,10 @@ static void node_discovery_entry(void *p1, void *p2, void *p3) { // LOG_INF("Discoverd %u nodes", ret); for (size_t i = 0; i < ret; ++i) { - if (!node_table_is_active_by_addr(&node_array[i])) { - if (node_table_add_node(&node_array[i]) < 0) { - LOG_WRN("Failed to add node"); - } else { - node_handler_setup_node_queue(&node_array[i], 0); - LOG_INF("Added Greybus Node"); - } + intf = node_find_by_addr(&node_array[i]); + if (intf == NULL) { + intf = node_create_interface(&node_array[i]); + svc_send_module_inserted(intf->id); } } diff --git a/src/node.c b/src/node.c index e4b880d..126f213 100644 --- a/src/node.c +++ b/src/node.c @@ -1,9 +1,14 @@ +#include "greybus_protocol.h" #include "operations.h" +#include "zephyr/sys/dlist.h" #include <zephyr/logging/log.h> #include <zephyr/net/socket.h> LOG_MODULE_DECLARE(cc1352_greybus, CONFIG_BEAGLEPLAY_GREYBUS_LOG_LEVEL); +static sys_dlist_t node_interface_list = + SYS_DLIST_STATIC_INIT(&node_interface_list); + static int write_data(int sock, const void *data, size_t len) { int ret; int transmitted = 0; @@ -35,34 +40,121 @@ static int read_data(int sock, void *data, size_t len) { return recieved; } +static struct gb_message *gb_message_receive(int sock, bool *flag) { + int ret; + struct gb_operation_msg_hdr hdr; + struct gb_message *msg; + size_t payload_size; + + ret = read_data(sock, &hdr, sizeof(struct gb_operation_msg_hdr)); + if (ret <= 0) { + *flag = ret == 0; + goto early_exit; + } + + payload_size = hdr.size - sizeof(struct gb_operation_msg_hdr); + msg = k_malloc(sizeof(struct gb_message) + payload_size); + if (msg == NULL) { + LOG_ERR("Failed to allocate node message"); + goto free_msg; + } + + memcpy(&msg->header, &hdr, sizeof(struct gb_operation_msg_hdr)); + msg->payload_size = payload_size; + ret = read_data(sock, msg->payload, msg->payload_size); + if (ret <= 0) { + *flag = ret == 0; + goto free_msg; + } + + return msg; + +free_msg: + k_free(msg); +early_exit: + return NULL; +} + +static int gb_message_send(int sock, const struct gb_message *msg) { + int ret; + + ret = write_data(sock, &msg->header, sizeof(struct gb_operation_msg_hdr)); + if (ret < 0) { + return -1; + } + + ret = write_data(sock, msg->payload, msg->payload_size); + if (ret < 0) { + return -1; + } + + return SUCCESS; +} + struct node_control_data { + int *cports; + uint16_t cports_len; + struct in6_addr addr; }; - static struct gb_message *node_inf_read(struct gb_controller *ctrl, - uint16_t cport_id) { + uint16_t cport_id) { + struct zsock_pollfd fd[1]; + int ret; + bool flag = false; + struct gb_message *msg = NULL; + struct node_control_data *ctrl_data = ctrl->ctrl_data; + + if (cport_id >= ctrl_data->cports_len) { + goto early_exit; + } + + fd[0].fd = ctrl_data->cports[cport_id]; + fd[0].events = ZSOCK_POLLIN; + + ret = zsock_poll(fd, 1, 0); + if (ret <= 0) { + goto early_exit; + } + + if (fd[0].revents & ZSOCK_POLLIN) { + msg = gb_message_receive(fd[0].fd, &flag); + if (flag) { + LOG_ERR("Socket closed by Peer Node"); + } + } + +early_exit: return NULL; } static int node_inf_write(struct gb_controller *ctrl, struct gb_message *msg, - uint16_t cport_id) { - return -1; -} + uint16_t cport_id) { + struct node_control_data *ctrl_data = ctrl->ctrl_data; + if (cport_id >= ctrl_data->cports_len) { + return -1; + } + return gb_message_send(ctrl_data->cports[cport_id], msg); +} -struct gb_interface *node_create_interface() { - struct node_control_data *ctrl_data = k_malloc(sizeof(struct node_control_data)); +struct gb_interface *node_create_interface(struct in6_addr *addr) { + struct node_control_data *ctrl_data = + k_malloc(sizeof(struct node_control_data)); if (ctrl_data == NULL) { return NULL; } - struct gb_interface *inf = k_malloc(sizeof(struct gb_interface)); + ctrl_data->cports = NULL; + ctrl_data->cports_len = 0; + memcpy(&ctrl_data->addr, addr, sizeof(struct in6_addr)); + + struct gb_interface *inf = + gb_interface_alloc(node_inf_read, node_inf_write, ctrl_data); if (inf == NULL) { goto free_ctrl_data; } - inf->controller.ctrl_data = ctrl_data; - inf->controller.read = node_inf_read; - inf->controller.write = node_inf_write; + sys_dlist_append(&node_interface_list, &inf->node); return inf; @@ -76,6 +168,33 @@ void node_destroy_interface(struct gb_interface *inf) { return; } + sys_dlist_remove(&inf->node); k_free(inf->controller.ctrl_data); - k_free(inf); + gb_interface_dealloc(inf); +} + +struct gb_interface *node_find_by_id(uint8_t id) { + struct gb_interface *inf; + + SYS_DLIST_FOR_EACH_CONTAINER(&node_interface_list, inf, node) { + if (inf->id == id) { + return inf; + } + } + + return NULL; +} + +struct gb_interface *node_find_by_addr(struct in6_addr *addr) { + struct gb_interface *inf; + struct node_control_data *ctrl_data; + + SYS_DLIST_FOR_EACH_CONTAINER(&node_interface_list, inf, node) { + ctrl_data = inf->controller.ctrl_data; + if (memcmp(&ctrl_data->addr, addr, sizeof(struct in6_addr)) == 0) { + return inf; + } + } + + return NULL; } diff --git a/src/operations.c b/src/operations.c index 9132491..6f9c731 100644 --- a/src/operations.c +++ b/src/operations.c @@ -12,12 +12,24 @@ LOG_MODULE_DECLARE(cc1352_greybus, CONFIG_BEAGLEPLAY_GREYBUS_LOG_LEVEL); -static atomic_t operation_id_counter = ATOMIC_INIT(1); +#define OPERATION_ID_START 1 +#define INTERFACE_ID_START 2 + +static atomic_t operation_id_counter = ATOMIC_INIT(OPERATION_ID_START); +static atomic_t interface_id_counter = ATOMIC_INIT(INTERFACE_ID_START); static uint16_t new_operation_id() { atomic_val_t temp = atomic_inc(&operation_id_counter); if (temp == UINT16_MAX) { - atomic_set(&operation_id_counter, 1); + atomic_set(&operation_id_counter, OPERATION_ID_START); + } + return temp; +} + +static uint8_t new_interface_id() { + atomic_val_t temp = atomic_inc(&interface_id_counter); + if (temp == UINT8_MAX) { + atomic_set(&interface_id_counter, INTERFACE_ID_START); } return temp; } @@ -97,3 +109,24 @@ struct gb_message *gb_message_response_alloc(const void *payload, return gb_message_alloc(payload, payload_len, OP_RESPONSE | request_type, operation_id); } + +struct gb_interface *gb_interface_alloc(gb_controller_read_callback_t read_cb, + gb_controller_write_callback_t write_cb, + void *ctrl_data) { + struct gb_interface *intf = k_malloc(sizeof(struct gb_interface)); + if (intf == NULL) { + return NULL; + } + + intf->id = new_interface_id(); + intf->controller.read = read_cb; + intf->controller.write = write_cb; + intf->controller.ctrl_data = ctrl_data; + sys_dnode_init(&intf->node); + + return intf; +} + +void gb_interface_dealloc(struct gb_interface *intf) { + k_free(intf); +} diff --git a/src/svc.c b/src/svc.c index 3700749..a3e65eb 100644 --- a/src/svc.c +++ b/src/svc.c @@ -2,11 +2,11 @@ #include "ap.h" #include "greybus_protocol.h" #include "operations.h" -#include <zephyr/sys/atomic.h> #include <errno.h> #include <zephyr/kernel.h> #include <zephyr/logging/log.h> #include <zephyr/net/socket.h> +#include <zephyr/sys/atomic.h> #define ENDO_ID 0x4755 @@ -20,6 +20,12 @@ struct svc_control_data { static struct svc_control_data svc_ctrl_data; +struct gb_svc_module_inserted_request { + uint8_t primary_intf_id; + uint8_t intf_count; + uint16_t flags; +} __packed; + struct gb_svc_version_request { uint8_t major; uint8_t minor; @@ -115,11 +121,6 @@ static void svc_version_response_handler(struct gb_message *msg) { svc_send_hello(); } -static void svc_ping_response_handler(struct gb_message *msg) { - ARG_UNUSED(msg); - LOG_DBG("Received Pong"); -} - static void svc_hello_response_handler(struct gb_message *msg) { LOG_DBG("Hello Response Success"); atomic_set_bit(svc_is_read_flag, 0); @@ -137,17 +138,17 @@ static void svc_pwrm_get_rail_count_handler(struct gb_message *msg) { static void svc_intf_set_pwrm_handler(struct gb_message *msg) { uint8_t tx_mode, rx_mode; - struct gb_svc_intf_set_pwrm_response resp = { - .result_code = GB_SVC_SETPWRM_PWR_LOCAL - }; - struct gb_svc_intf_set_pwrm_request *req = (struct gb_svc_intf_set_pwrm_request *)msg->payload; + struct gb_svc_intf_set_pwrm_response resp = {.result_code = + GB_SVC_SETPWRM_PWR_LOCAL}; + struct gb_svc_intf_set_pwrm_request *req = + (struct gb_svc_intf_set_pwrm_request *)msg->payload; tx_mode = req->tx_mode; rx_mode = req->rx_mode; if (tx_mode == GB_SVC_UNIPRO_HIBERNATE_MODE && rx_mode == GB_SVC_UNIPRO_HIBERNATE_MODE) { resp.result_code = GB_SVC_SETPWRM_PWR_OK; - } + } svc_response_helper(msg, &resp, sizeof(struct gb_svc_intf_set_pwrm_response)); } @@ -172,11 +173,14 @@ static void gb_handle_msg(struct gb_message *msg) { svc_version_response_handler(msg); break; case GB_SVC_TYPE_PING_RESPONSE: - svc_ping_response_handler(msg); + LOG_DBG("Received Pong"); break; case GB_SVC_TYPE_HELLO_RESPONSE: svc_hello_response_handler(msg); break; + case GB_SVC_TYPE_MODULE_INSERTED_RESPONSE: + LOG_DBG("Successful Module Inserted Response"); + break; default: LOG_WRN("Handling SVC operation Type %X not supported yet", msg->header.type); @@ -207,6 +211,13 @@ struct gb_interface *svc_init() { return &intf; } -bool svc_is_ready() { - return atomic_test_bit(svc_is_read_flag, 0); +bool svc_is_ready() { return atomic_test_bit(svc_is_read_flag, 0); } + +int svc_send_module_inserted(uint8_t primary_intf_id) { + struct gb_svc_module_inserted_request req = { + .primary_intf_id = primary_intf_id, .intf_count = 1, .flags = 0}; + + return control_send_request(&req, + sizeof(struct gb_svc_module_inserted_request), + GB_SVC_TYPE_MODULE_INSERTED_REQUEST); } -- GitLab