forked from nrfconnect/sdk-wi-fiquicktrack-controlappc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[nrf noup] zephyr: qt: Initialization of WFA QT on boot
Added boot time thread to start QT Signed-off-by: Triveni Danda <[email protected]>
- Loading branch information
Showing
4 changed files
with
261 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,249 @@ | ||
/* 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, "%s: Malloc Failure for receive buffer", __func__); | ||
return; | ||
} | ||
|
||
ret = pthread_attr_init(&ptAttr); | ||
if (ret != 0) { | ||
indigo_logger(LOG_LEVEL_ERROR, "%s: pthread_attr_init failed", __func__); | ||
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) { | ||
indigo_logger(LOG_LEVEL_ERROR, "%s: pthread_attr_setstack failed", __func__); | ||
return; | ||
} | ||
|
||
ret = pthread_create(&main_thread, &ptAttr, main_thread_handler, NULL); | ||
if (ret < 0) { | ||
indigo_logger(LOG_LEVEL_ERROR, "%s: pthread_create failed", __func__); | ||
return; | ||
} | ||
} |