Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions framework/include/csimanager/csifw_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,22 @@ extern "C" {
#include <tinyara/wifi_csi/wifi_csi_struct.h>

typedef enum _CSIFW_RES {
CSIFW_ERROR_MAX_NUM_SERVICE_REGISTERED = -11, /* ERROR: MAX number of Services is alreay Registered */
CSIFW_ERROR_NOT_INITIALIZED = -10, /* ERROR: Not Initialized */
CSIFW_ERROR_INVALID_SERVICE_STATE = -9, /* ERROR: Invalid Service State */
CSIFW_ERROR_ALREADY_INIT_WITH_DIFFERENT_CONFIG = -8, /* ERROR: Service already initialized with different CSI_Configuration */
CSIFW_ERROR_SERVICE_NOT_REGISTERED = -7, /* ERROR: Service not registered. Cannot start/stop/deinit */
CSIFW_ERROR_WIFI_DIS_CONNECTED = -6, /* ERROR: WIFI WIFI_DISCONNECTED */
CSIFW_INVALID_RAWDATA = -5, /* Invalid Raw Data */
CSIFW_INVALID_ARG = -4, /* Invalid argument */
CSIFW_NOT_ENOUGH_SPACE = -3, /* read/write/other buffer has empty space less than required size */
CSIFW_NO_MEM = -2, /* Memory allocation (malloc/calloc) failed */
CSIFW_ERROR = -1, /* ERROR: All other types of error not specified by any following enum */
CSIFW_OK = 0, /* OK: Without any error */
CSIFW_OK_WIFI_CONNECTED = 1, /* OK: Without any error */
CSIFW_OK_ALREADY_STOPPED = 2, /* CSIFW already stopped by running service, but no error */
CSIFW_OK_ALREADY_STARTED = 3, /* CSIFW already started by running service, but no error */
CSIFW_OK_WIFI_NOT_CONNECTED = 4 /* CSIFW already started but WIFI not connected */
CSIFW_ERROR_MAX_NUM_SERVICE_REGISTERED = -11, /* ERROR: MAX number of Services is alreay Registered */
CSIFW_ERROR_NOT_INITIALIZED = -10, /* ERROR: Not Initialized */
CSIFW_ERROR_INVALID_SERVICE_STATE = -9, /* ERROR: Invalid Service State */
CSIFW_ERROR_ALREADY_INIT_WITH_DIFFERENT_CONFIG = -8, /* ERROR: Service already initialized with different CSI_Configuration*/
CSIFW_ERROR_SERVICE_NOT_REGISTERED = -7, /* ERROR: Service not registered. Cannot start/stop/deinit */
CSIFW_ERROR_WIFI_DIS_CONNECTED = -6, /* ERROR: WIFI WIFI_DISCONNECTED */
CSIFW_ERROR_DATA_NOT_AVAILABLE = -5, /* ERROR: CSI Data Not Available */
CSIFW_INVALID_ARG = -4, /* Invalid argument */
CSIFW_NOT_ENOUGH_SPACE = -3, /* read/write/other buffer has empty space less than required size */
CSIFW_NO_MEM = -2, /* Memory allocation (malloc/calloc) failed */
CSIFW_ERROR = -1, /* ERROR: All other types of error not specified by any following enum */
CSIFW_OK = 0, /* OK: Without any error */
CSIFW_OK_WIFI_CONNECTED = 1, /* OK: Without any error */
CSIFW_OK_ALREADY_STOPPED = 2, /* CSIFW already stopped by running service, but no error */
CSIFW_OK_ALREADY_STARTED = 3, /* CSIFW already started by running service, but no error */
CSIFW_OK_WIFI_NOT_CONNECTED = 4 /* CSIFW already started but WIFI not connected */
} CSIFW_RES;

typedef int csifw_service_handle;
Expand Down
82 changes: 75 additions & 7 deletions framework/src/csimanager/CSIFrameworkMain.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const static int CSIFW_TASK_PRIORITY = 100;
const static int CSIFW_TASK_PERMISSION = TM_APP_PERMISSION_ALL;

int csifw_task_Main(int argc, char *argv[]);
static void task_manager_stop_and_unregister(int m_task_handle);

int start_csi_framework(csifw_context_t *p_ctx)
{
Expand Down Expand Up @@ -84,8 +85,14 @@ int start_csi_framework(csifw_context_t *p_ctx)
int result = task_manager_start(handle, TM_RESPONSE_WAIT_INF);
if (result < 0) {
CSIFW_LOGE("Failed to start %s (handle=%d). Return: %d. Cleaning up...", CSIFW_TASK_NAME, handle, result);
task_manager_unregister(handle, TM_RESPONSE_WAIT_INF);
CSIFW_LOGD("Unregistered task %s (handle=%d) after failed start", CSIFW_TASK_NAME, handle);
CSIFW_LOGD("Unregistering task %s (handle=%d)", CSIFW_TASK_NAME, handle);
int tm_unregister_return = task_manager_unregister(handle, TM_RESPONSE_WAIT_INF);
if (tm_unregister_return < 0) {
CSIFW_LOGE("Failed to unregister csifw task to the task manager! Return: %d", tm_unregister_return);
//To-Do: Error handling logic to be addressed later.
} else {
CSIFW_LOGD("Unregistered successfully csifw task to the task manager! Return: %d", tm_unregister_return);
}
sem_destroy(&p_ctx->csifw_task_sema);
CSIFW_LOGD("Destroyed semaphore for %s after failed start", CSIFW_TASK_NAME);
} else {
Expand All @@ -94,7 +101,7 @@ int start_csi_framework(csifw_context_t *p_ctx)

if (!p_ctx->task_run_success) {
CSIFW_LOGE("CSI framework task initialization failed");
task_manager_unregister(handle, TM_RESPONSE_WAIT_INF);
task_manager_stop_and_unregister(p_ctx->task_handle);
sem_destroy(&p_ctx->csifw_task_sema);
return -1;
}
Expand All @@ -113,8 +120,7 @@ int stop_csi_framework(csifw_context_t *p_ctx)
p_ctx->task_run_state = STOPPED; //stop the main loop of the task
CSIFW_LOGD("Waiting for csifw_task to complete...");
sem_wait(&p_ctx->csifw_task_sema);
CSIFW_LOGD("Unregistering task %s (handle=%d)", CSIFW_TASK_NAME, p_ctx->task_handle);
task_manager_unregister(p_ctx->task_handle, TM_RESPONSE_WAIT_INF);
task_manager_stop_and_unregister(p_ctx->task_handle);
CSIFW_LOGD("Destroying semaphore for %s", CSIFW_TASK_NAME);
sem_destroy(&p_ctx->csifw_task_sema);
return 0;
Expand All @@ -136,7 +142,6 @@ int csifw_task_Main(int argc, char *argv[])
sem_post(&p_csifw_ctx->csifw_task_sema);
return -1;
}

if (csi_ping_generator_initialize() != CSIFW_OK) {
CSIFW_LOGE("CSI ping generator initialize failed");
csi_packet_receiver_stop_collect();
Expand Down Expand Up @@ -173,9 +178,72 @@ int csifw_task_Main(int argc, char *argv[])
CSIFW_LOGE("CSI packet receiver stop failed");
}
if (csi_packet_receiver_cleanup() == CSIFW_ERROR){
CSIFW_LOGD("CSI packet receiver cleanup failed");
CSIFW_LOGE("CSI packet receiver cleanup failed");
}
//to unlock stop_csi_framework()
sem_post(&p_csifw_ctx->csifw_task_sema);
return 0;
}

static void task_manager_stop_and_unregister(int m_task_handle)
{
CSIFW_LOGD("Stopping task %s (Task_Handle=%d)", CSIFW_TASK_NAME, m_task_handle);
tm_appinfo_t *info = task_manager_getinfo_with_handle(m_task_handle, TM_RESPONSE_WAIT_INF);
if (info == NULL) {
CSIFW_LOGE("Failed to get task info for handle %d", m_task_handle);
return;
}

//Print task status
switch (info->status) {
case TM_APP_STATE_RUNNING:
CSIFW_LOGI("Task (handle=%d) status: RUNNING", m_task_handle);
break;
case TM_APP_STATE_PAUSE:
CSIFW_LOGI("Task (handle=%d) status: PAUSED", m_task_handle);
break;
case TM_APP_STATE_STOP:
CSIFW_LOGI("Task (handle=%d) status: STOPPED", m_task_handle);
break;
case TM_APP_STATE_UNREGISTERED:
CSIFW_LOGI("Task (handle=%d) status: UNREGISTERED", m_task_handle);
break;
case TM_APP_STATE_CANCELLING:
CSIFW_LOGI("Task (handle=%d) status: CANCELLING", m_task_handle);
break;
case TM_APP_STATE_WAIT_UNREGISTER:
CSIFW_LOGI("Task (handle=%d) status: WAIT_UNREGISTER", m_task_handle);
break;
default:
CSIFW_LOGE("Task (handle=%d) status: UNKNOWN (%d)", m_task_handle, info->status);
break;
}

if (info->status == TM_APP_STATE_RUNNING) {
int tm_stop_return = task_manager_stop(m_task_handle, TM_RESPONSE_WAIT_INF);
if (tm_stop_return != 0) {
CSIFW_LOGE("Failed to stop (Task_Handle=%d). Return: %d.", m_task_handle, tm_stop_return);
} else {
CSIFW_LOGD("Stopped successfully (Task_Handle=%d). Return: %d.", m_task_handle, tm_stop_return);
}
} else if (info->status == TM_APP_STATE_STOP) {
CSIFW_LOGD("Task already stopped (Task_Handle=%d)", m_task_handle);
} else {
CSIFW_LOGD("Task state unknown Failed to stop (Task_Handle=%d)", m_task_handle);
}

CSIFW_LOGD("Unregistering task %s (Task_Handle=%d)", CSIFW_TASK_NAME, m_task_handle);
int tm_unregister_return = task_manager_unregister(m_task_handle, TM_RESPONSE_WAIT_INF);
if (tm_unregister_return < 0) {
CSIFW_LOGE("Failed to unregister csifw task to the task manager! Return: %d", tm_unregister_return);
//To-Do: Error handling logic to be addressed later.
} else {
CSIFW_LOGD("Unregistered successfully csifw task to the task manager! Return: %d", tm_unregister_return);
}

task_manager_clean_info(&info);
if (info != NULL) {
CSIFW_LOGE("Failed to clean task info memory");
}
}

14 changes: 13 additions & 1 deletion framework/src/csimanager/CSIManager.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,11 @@ static void CSIRawDataListener(CSIFW_RES res, int raw_csi_buff_len, unsigned cha
&g_pcsifw_context->ParsedDataBufferLen);
}

// we use this service state but if its called parelly this is will stuck
// CSIRawDataListener callback can be invoked from a background thread when CSI data arrives.
// Simultaneously, application threads may call `csifw_start()/csifw_stop()` to modify service states.
// Without this mutex, race conditions will occur
CSIFW_MUTEX_LOCK(&g_pcsifw_context->data_reciever_mutex);

for (int i = 0; i < CSIFW_MAX_NUM_APPS; i++) {
// send raw
if (g_pcsifw_context->csi_services[i].svc_id != 0 && g_pcsifw_context->csi_services[i].svc_state == CSI_SERVICE_START) {
Expand Down Expand Up @@ -401,6 +404,10 @@ CSIFW_RES csifw_set_interval(csifw_service_handle hnd, unsigned int interval)
ping_generator_change_interval(g_pcsifw_context->csi_interval);
} else {
res = csi_packet_receiver_change_interval();
if (res != CSIFW_OK) {
CSIFW_LOGE("Interval update Failed %d", res);
goto on_error;
}
}
CSIFW_LOGD("Interval updated : %u", g_pcsifw_context->csi_interval);

Expand Down Expand Up @@ -482,6 +489,10 @@ CSIFW_RES csifw_get_ap_mac_addr(csifw_service_handle hnd, csifw_mac_info *p_mac_
}

res = csi_packet_receiver_get_mac_addr(p_mac_info);
if (res != CSIFW_OK) {
CSIFW_LOGE("Failed to get AP MAC %d", res);
goto on_error;
}

on_error:
CSIFW_MUTEX_UNLOCK(&g_api_mutex);
Expand Down Expand Up @@ -702,3 +713,4 @@ static int all_services_stopped(void)
CSIFW_LOGI("All services are stopped\n");
return 1;
}

39 changes: 34 additions & 5 deletions framework/src/csimanager/CSIPacketReceiver.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <tinyara/wifi_csi/wifi_csi.h>

#define RCVR_TH_NAME "csifw_data_receiver_th"
#define MAX_CONSECUTIVE_FAILURES 50
static unsigned long long get_monotonic_time_us(void);

static inline CSIFW_RES open_driver(int *fd) {
*fd = open(CONFIG_WIFICSI_CUSTOM_DEV_PATH, O_RDONLY);
Expand Down Expand Up @@ -68,16 +70,23 @@ static void *dataReceiverThread(void *vargp)
int prio;
size_t size;
int csi_data_len = 0;
int timeout_count = 0;
struct wifi_csi_msg_s msg;
int consecutive_failures = 0;
struct timespec st_time = {0,};
int fd = p_csifw_ctx->data_receiver_fd;
mqd_t mq_handle = p_csifw_ctx->mq_handle;
unsigned long long last_data_read_timestamp_us = 0;
unsigned char *get_data_buffptr = p_csifw_ctx->get_data_buffptr;

while (!p_csifw_ctx->data_receiver_thread_stop) {
size = mq_receive(mq_handle, (char *)&msg, sizeof(msg), &prio);
if (size != sizeof(msg)) {
CSIFW_LOGE("Interrupted while waiting for deque message from kernel %zu, errno: %d (%s)", size, get_errno(), strerror(get_errno()));
} else {
last_data_read_timestamp_us = get_monotonic_time_us();
CSIFW_LOGD("last_data_read_timestamp_us before mq_timedreceive:%llu",last_data_read_timestamp_us);
clock_gettime(CLOCK_REALTIME, &st_time);
st_time.tv_sec += 1;
size = mq_timedreceive(mq_handle, (char *)&msg, sizeof(msg), &prio, &st_time);
if (size >= 0) {
CSIFW_LOGD("Message received - msgId: %d, data_len: %d, size: %zu: %d", msg.msgId, msg.data_len, size);
switch (msg.msgId) {
case CSI_MSG_DATA_READY_CB:
if (msg.data_len == 0 || msg.data_len > CSIFW_MAX_RAW_BUFF_LEN) {
Expand All @@ -86,6 +95,8 @@ static void *dataReceiverThread(void *vargp)
}
csi_data_len = msg.data_len;
len = readCSIData(fd, get_data_buffptr, csi_data_len);
last_data_read_timestamp_us = get_monotonic_time_us();
CSIFW_LOGD("last_data_read_timestamp_us after readCSIData:%llu",last_data_read_timestamp_us);
if (len < 0) {
CSIFW_LOGE("Skipping packet: error: %d", len);
continue;
Expand Down Expand Up @@ -218,7 +229,6 @@ CSIFW_RES csi_packet_receiver_start_collect(void)
}
if (p_csifw_ctx->disable_required) {
CSIFW_LOGD("WiFi reconnected: Disabling CSI config");
csi_packet_receiver_set_csi_config(CSI_CONFIG_ENABLE);
csi_packet_receiver_set_csi_config(CSI_CONFIG_DISABLE);
p_csifw_ctx->disable_required = false;
}
Expand All @@ -229,6 +239,17 @@ CSIFW_RES csi_packet_receiver_start_collect(void)
}
p_csifw_ctx->data_receiver_thread_stop = false;

// allocate buffer for receiveing data from driver
if (!p_csifw_ctx->get_data_buffptr) {
p_csifw_ctx->get_data_buffptr = (unsigned char *)malloc(CSIFW_MAX_RAW_BUFF_LEN);
if (!p_csifw_ctx->get_data_buffptr) {
csi_packet_receiver_set_csi_config(CSI_CONFIG_DISABLE);
CSIFW_LOGE("Buffer allocation Fail.");
return CSIFW_ERROR;
}
CSIFW_LOGD("CSI data buffer allocated successfully, size: %d bytes", CSIFW_MAX_RAW_BUFF_LEN);
}

pthread_attr_t recv_th_attr;
if (pthread_attr_init(&recv_th_attr) != 0) {
CSIFW_LOGE("Failed to initialize receiver thread attributes - errno: %d (%s)", get_errno(), strerror(get_errno()));
Expand Down Expand Up @@ -369,3 +390,11 @@ CSIFW_RES csi_packet_receiver_deinit(void)
CSIFW_LOGD("CSI packet receiver successfully deinitialized (callback: %p)", p_csifw_ctx->CSI_DataCallback);
return CSIFW_OK;
}

static unsigned long long get_monotonic_time_us(void)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (unsigned long long)ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000ULL;
}

4 changes: 4 additions & 0 deletions framework/src/csimanager/inc/CSIManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
#define CSIFW_MIN_INTERVAL_MS 30 // Minimum supported CSI interval in milliseconds
#define CSIFW_MAX_RAW_BUFF_LEN 1024 // CSI data buffer xax size

#ifndef CONFIG_CSI_DATA_TIMEOUT_SEC /* In case not defined in defconfig, force it to default value*/
#define CONFIG_CSI_DATA_TIMEOUT_SEC 15
#endif

typedef unsigned long long u64; // for u64
typedef void (*CSIDataListener)(CSIFW_RES res, int csi_buff_len, unsigned char *csi_buff, int csi_data_len);

Expand Down