Skip to content

Commit

Permalink
[nrf noup] zephyr: qt: Initialization of WFA QT on boot
Browse files Browse the repository at this point in the history
Added boot time thread to start QT

Signed-off-by: Triveni Danda <[email protected]>
  • Loading branch information
D-Triveni committed Jul 24, 2023
1 parent cadef7d commit 0f6bb06
Show file tree
Hide file tree
Showing 4 changed files with 262 additions and 2 deletions.
12 changes: 10 additions & 2 deletions eloop.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#ifdef CONFIG_ZEPHYR
#include <zephyr/posix/sys/select.h>
#else
#include "sys/select.h"
#endif

#ifdef CONFIG_NATIVE_WINDOWS
#include "common.h"
Expand Down Expand Up @@ -235,7 +239,7 @@ int qt_eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx),
}


#ifndef CONFIG_NATIVE_WINDOWS
#if !defined(CONFIG_NATIVE_WINDOWS) && !defined(CONFIG_ZEPHYR)
static void eloop_handle_alarm(int sig)
{
(void) sig;
Expand All @@ -247,9 +251,10 @@ static void eloop_handle_alarm(int sig)
vendor_deinit();
exit(1);
}
#endif /* CONFIG_NATIVE_WINDOWS */
#endif /* CONFIG_NATIVE_WINDOWS && CONFIG_ZEPHYR*/


#ifndef CONFIG_ZEPHYR
static void eloop_handle_signal(int sig)
{
int i;
Expand Down Expand Up @@ -324,6 +329,7 @@ int qt_eloop_register_signal(int sig,

return 0;
}
#endif

void qt_eloop_run(void)
{
Expand Down Expand Up @@ -361,7 +367,9 @@ void qt_eloop_run(void)
free(rfds);
return;
}
#ifndef CONFIG_ZEPHYR
eloop_process_pending_signals();
#endif

/* check if some registered timeouts have occurred */
if (eloop.timeout) {
Expand Down
1 change: 1 addition & 0 deletions zephyr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ zephyr_include_directories_ifdef(CONFIG_WFA_QT_CONTROL_APP

zephyr_library_sources_ifdef(CONFIG_WFA_QT_CONTROL_APP
# Zephyr's port of the Indigo API
${SOURCES_BASE}/zephyr/src/zephyr_dut_main.c
${SOURCES_BASE}/zephyr/src/indigo_api_callback_dut.c
${SOURCES_BASE}/zephyr/src/vendor_specific_dut.c
${SOURCES_BASE}/zephyr/src/utils.c
Expand Down
6 changes: 6 additions & 0 deletions zephyr/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ config WFA_QT_CONTROL_APP
depends on !POSIX_API
select PTHREAD_IPC
bool "WFA Quicktrack control app"

config WFA_QT_THREAD_STACK_SIZE
int "Thread stack size"
default 4096
help
Thread stack size.
245 changes: 245 additions & 0 deletions zephyr/src/zephyr_dut_main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
/* Copyright (c) 2020 Wi-Fi Alliance */

/* Permission to use, copy, modify, and/or distribute this software for any */
/* purpose with or without fee is hereby granted, provided that the above */
/* copyright notice and this permission notice appear in all copies. */

/* THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL */
/* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED */
/* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL */
/* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR */
/* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING */
/* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF */
/* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT */
/* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS */
/* SOFTWARE. */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <zephyr/net/socket.h>
#include <unistd.h>
#include <errno.h>

#include "vendor_specific.h"
#include "eloop.h"
#include "indigo_api.h"
#include "utils.h"

#include <zephyr/posix/pthread.h>

void qt_main(void);
K_THREAD_DEFINE(qt_main_tid,
CONFIG_WFA_QT_THREAD_STACK_SIZE,
qt_main,
NULL,
NULL,
NULL,
0,
0,
0);

static pthread_t main_thread;
#define STACK_SIZE 4096
K_THREAD_STACK_DEFINE(main_thread_stack, STACK_SIZE);

unsigned char *cmd_rcv_buf = NULL; /*Buffer to receive the message*/

/* Internal functions */
static void control_receive_message(int sock, void *eloop_ctx, void *sock_ctx);

/* Initiate the service port. */
static int control_socket_init(int port) {
int s = -1;
struct sockaddr_in addr;

/* Open UDP socket */
s = socket(PF_INET, SOCK_DGRAM, 0);
if (s < 0) {
indigo_logger(LOG_LEVEL_ERROR, "Failed to open server socket: %s", strerror(errno));
return -1;
}

/* Bind specific port */
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
indigo_logger(LOG_LEVEL_ERROR, "Failed to bind server socket: %s", strerror(errno));
close(s);
return -1;
}

/* Register to eloop and ready for the socket event */
if (qt_eloop_register_read_sock(s, control_receive_message, NULL, NULL)) {
indigo_logger(LOG_LEVEL_ERROR, "Failed to initiate ControlAppC");
close(s);
return -1;
}
return s;
}

void *main_thread_handler() {
int service_socket = -1;

/* Bind the service port and register to eloop */
service_socket = control_socket_init(get_service_port());
if (service_socket >= 0) {
qt_eloop_run();
} else {
indigo_logger(LOG_LEVEL_INFO, "Failed to initiate the UDP socket");
}

/* Stop eloop */
qt_eloop_destroy();
indigo_logger(LOG_LEVEL_INFO, "ControlAppC stops");
if (service_socket >= 0) {
indigo_logger(LOG_LEVEL_INFO, "Close service port: %d", get_service_port());
close(service_socket);
free(cmd_rcv_buf);
}

return 0;
}

struct sockaddr_in *tool_addr; // For HTTP Post
/* Callback function of the QuickTrack API. */
static void control_receive_message(int sock, void *eloop_ctx, void *sock_ctx) {
int ret; // return code
int fromlen, len; // structure size and received length
struct sockaddr_storage from; // source address of the message
struct packet_wrapper req, resp; // packet wrapper for the received message and response
struct indigo_api *api = NULL; // used for API search, validation and handler call

(void) eloop_ctx;
(void) sock_ctx;

memset(cmd_rcv_buf, '\0', BUFFER_LEN);
/* Receive request */
fromlen = sizeof(from);
len = recvfrom(sock, cmd_rcv_buf, BUFFER_LEN, 0, (struct sockaddr *) &from, (socklen_t*)&fromlen);
if (len < 0) {
indigo_logger(LOG_LEVEL_ERROR, "Server: Failed to receive the packet");
return ;
} else {
indigo_logger(LOG_LEVEL_DEBUG, "Server: Receive the packet");
}
tool_addr = (struct sockaddr_in *)&from;

/* Parse request to HDR and TLV. Response NACK if parser fails. Otherwises, ACK. */
memset(&req, 0, sizeof(struct packet_wrapper));
memset(&resp, 0, sizeof(struct packet_wrapper));
ret = parse_packet(&req, cmd_rcv_buf, len);
if (ret == 0) {
indigo_logger(LOG_LEVEL_DEBUG, "Server: Parsed packet successfully");
} else {
indigo_logger(LOG_LEVEL_ERROR, "Server: Failed to parse the packet");
fill_wrapper_ack(&resp, req.hdr.seq, 0x31, "Unable to parse the packet");
len = assemble_packet(cmd_rcv_buf, BUFFER_LEN, &resp);

sendto(sock, (const char *)cmd_rcv_buf, len, MSG_CONFIRM, (const struct sockaddr *) &from, fromlen);
goto done;
}

/* Find API by ID. If API is not supported, assemble NACK. */
api = get_api_by_id(req.hdr.type);
if (api) {
indigo_logger(LOG_LEVEL_DEBUG, "API %s: Found handler", api->name);
} else {
indigo_logger(LOG_LEVEL_ERROR, "API Unknown (0x%04x): No registered handler", req.hdr.type);
fill_wrapper_ack(&resp, req.hdr.seq, 0x31, "Unable to find the API handler");
len = assemble_packet(cmd_rcv_buf, BUFFER_LEN, &resp);
sendto(sock, (const char *)cmd_rcv_buf, len, MSG_CONFIRM, (const struct sockaddr *) &from, fromlen);
goto done;
}

/* Verify. Optional. If validation is failed, then return NACK. */
if (api->verify == NULL || (api->verify && api->verify(&req, &resp) == 0)) {
indigo_logger(LOG_LEVEL_INFO, "API %s: Return ACK", api->name);
fill_wrapper_ack(&resp, req.hdr.seq, 0x30, "ACK: Command received");
len = assemble_packet(cmd_rcv_buf, BUFFER_LEN, &resp);
sendto(sock, (const char *)cmd_rcv_buf, len, MSG_CONFIRM, (const struct sockaddr *) &from, fromlen);
free_packet_wrapper(&resp);
} else {
indigo_logger(LOG_LEVEL_ERROR, "API %s: Failed to verify and return NACK", api->name);
fill_wrapper_ack(&resp, req.hdr.seq, 1, "Unable to find the API handler");
len = assemble_packet(cmd_rcv_buf, BUFFER_LEN, &resp);
sendto(sock, (const char *)cmd_rcv_buf, len, MSG_CONFIRM, (const struct sockaddr *) &from, fromlen);
goto done;
}

/* Optional, use timer to handle the execution */
/* Handle & Response. Call API handle(), assemble packet by response wrapper and send back to source address. */
if (api->handle && api->handle(&req, &resp) == 0) {
indigo_logger(LOG_LEVEL_INFO, "API %s: Return execution result", api->name);
len = assemble_packet(cmd_rcv_buf, BUFFER_LEN, &resp);
sendto(sock, (const char *)cmd_rcv_buf, len, MSG_CONFIRM, (const struct sockaddr *) &from, fromlen);
} else {
indigo_logger(LOG_LEVEL_DEBUG, "API %s (0x%04x): No handle function", api ? api->name : "Unknown", req.hdr.type);
}

done:
/* Clean up resource */
free_packet_wrapper(&req);
free_packet_wrapper(&resp);
indigo_logger(LOG_LEVEL_DEBUG, "API %s: Complete", api ? api->name : "Unknown");
}

/* Show the welcome message with role and version */
static void print_welcome() {
printf("Welcome to use QuickTrack Control App DUT version %s \n", TLV_VALUE_APP_VERSION);
}

void qt_main(void) {
int ret =0;

pthread_attr_t ptAttr;
struct sched_param ptSchedParam;
int ptPolicy;

/* Welcome message */
print_welcome();

/* Print the run-time information */
indigo_logger(LOG_LEVEL_INFO, "QuickTrack control app running at: %d", get_service_port());
indigo_logger(LOG_LEVEL_INFO, "Wireless Interface: %s", WIRELESS_INTERFACE_DEFAULT);

/* Register the callback */
register_apis();

/* Intiate the vendor's specific startup commands */
vendor_init();

/* Start eloop */
qt_eloop_init(NULL);

/* Allocate memory to receive the control message*/
cmd_rcv_buf = malloc(BUFFER_LEN);
if(!cmd_rcv_buf) {
indigo_logger(LOG_LEVEL_ERROR, "Malloc Failure for receive buffer");
return;
}

ret = pthread_attr_init(&ptAttr);
if (ret != 0) {
printf("%s:%d ret: %d\n", __func__, __LINE__, ret);
return;
}

ptSchedParam.sched_priority = 10;
pthread_attr_setschedparam(&ptAttr, &ptSchedParam);
pthread_attr_getschedpolicy(&ptAttr, &ptPolicy);
pthread_attr_setschedpolicy(&ptAttr, SCHED_RR);
pthread_attr_getschedpolicy(&ptAttr, &ptPolicy);

ret = pthread_attr_setstack(&ptAttr, &main_thread_stack, 4096);
if (ret != 0) {
printf("%s:%d ret: %d\n", __func__, __LINE__, ret);
return;
}

pthread_create(&main_thread, &ptAttr, main_thread_handler, NULL);
}

0 comments on commit 0f6bb06

Please sign in to comment.