Skip to content

Commit

Permalink
UDP server support to send CSI data to UDP client
Browse files Browse the repository at this point in the history
	ADD sample client file for datadump over UDP
  • Loading branch information
manish1-garg committed Sep 16, 2024
1 parent 98b1d78 commit d6f39fb
Show file tree
Hide file tree
Showing 7 changed files with 448 additions and 0 deletions.
1 change: 1 addition & 0 deletions build/configs/rtl8730e/loadable_ext_psram/defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1671,6 +1671,7 @@ CONFIG_EXAMPLE_LCD_FPS_TEST=5000
# CONFIG_EXAMPLES_WIFIMANAGER_TEST is not set
# CONFIG_WIFIMANAGER_TEST_TRIAL=5
# CONFIG_EXAMPLES_WIFIMANAGER_AP_LIST_ITEMS_COUNT=10
# CONFIG_CSI_DATA_DUMP_OVER_NETWORK is not set

#
# Platform-specific Support
Expand Down
209 changes: 209 additions & 0 deletions framework/src/csifw/CSILogsDumper.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
#include "include/CSILogsDumper.h"
#include <sys/socket.h>
#include <netdb.h>
#include <pthread.h>
#include <errno.h>

#define PORT 5000
#define CONTROL_COMMAND_BUFFER_SIZE 128
#define CSI_DATA_DUMP_BUFFER_SIZE 1024

unsigned char gCSIDataDumpBuffer[CSI_DATA_DUMP_BUFFER_SIZE];
char gControlCommandBuffer[CONTROL_COMMAND_BUFFER_SIZE];

csiDataDumpListener gListener = NULL;
static pthread_t gThreadId = -1;
static int gSockFd = -1, gFifoFd = -1;
struct sockaddr_in gServerAddr, gClientAddr;
socklen_t gClientLen = sizeof(gClientAddr);
fd_set readfds;
int maxfd;

static int gWaitingForData = 0;
static int gRemainingBytes = 0;
static int gBytesReadSofar = 0;

static int recv_message(int fd, void *buf, int buflen)
{
int received = 0;
while (1) {
int res = read(fd, buf + received, buflen - received);
if (res < 0) {
int err_no = errno;
if (err_no == EAGAIN || err_no == EINTR) {
continue;
}
CSIFW_LOGE("read error %d\n", err_no);
return -1;
}
received += res;
if (received == buflen) {
break;
}
}
return received;
}

static int print_log(const char *format, ...)
{
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
return 1;
}

static void print_buf(const unsigned char* buf, int len)
{
print_log("\n RAW DATA %d\n\n", len);
unsigned long long *buff_tmp = (u64 *)buf;
int buff_len = (len/8) + 1;
for (int i = 0; i < buff_len; i++)
print_log("[%02d]0x%016llx\n", i, buff_tmp[i]);
}

void set_event_listener(csiDataDumpListener listener)
{
gListener = listener;
}

void *dataTransmitter(void *arg)
{
int len;
while (1) {
FD_ZERO(&readfds);
FD_SET(gSockFd, &readfds);
FD_SET(gFifoFd, &readfds);
maxfd = (gSockFd > gFifoFd) ? gSockFd : gFifoFd;

CSIFW_LOGI("Wait for an activity on one of the file descriptors");
int ret = select(maxfd + 1, &readfds, NULL, NULL, NULL);
if (ret < 0) {
if (errno == EBADF){
CSIFW_LOGE("select operation failed due to file descripter close: %d", errno);
return;
}
else if(errno == EINTR){
CSIFW_LOGE("select operation failed due to Temporary Interrupt: %d", errno);
continue;;
}
CSIFW_LOGE("select operation failed over file descripters: %d", errno);
return;
}

// Check if there's data on the UDP socket
if (FD_ISSET(gSockFd, &readfds)) {
CSIFW_LOGI("Received an activity on sockfd descriptors");
len = recvfrom(gSockFd, gControlCommandBuffer, CONTROL_COMMAND_BUFFER_SIZE-1, 0, (struct sockaddr *)&gClientAddr, &gClientLen);
if (len < 0) {
continue;
}
gControlCommandBuffer[len] = '\0';
if (strncmp(gControlCommandBuffer, "START", 6) == 0) {
gListener(START_DUMP);
CSIFW_LOGI("Received START command. Starting to send data to client from FIFO");
} else if (strncmp(gControlCommandBuffer, "STOP", 5) == 0) {
gListener(STOP_DUMP);
CSIFW_LOGI("Received STOP command. Stopping data transfer to client from FIFO");
} else {
CSIFW_LOGI("Received unknown command: %s", gControlCommandBuffer);
continue;
}
}

// Check if there's data on the FIFO
if (FD_ISSET(gFifoFd, &readfds)) {
CSIFW_LOGI("Received an activity on Fifo descriptors");

if (!gWaitingForData) {
// Get the length from the first 2 bytes
len = recv_message(gFifoFd, (void *)gCSIDataDumpBuffer, 2);
if (len <= 0) {
CSIFW_LOGE("operation to read length of data from FIFO Failed");
continue;
}
uint16_t length;
memcpy(&length , gCSIDataDumpBuffer, sizeof(length));
CSIFW_LOGI("Read %d length to client:", length);
gRemainingBytes = length;
gWaitingForData = 1;
gBytesReadSofar = 0;
}
if (gWaitingForData) {
// We are expecting to read the actual data
ssize_t bytes_read = read(gFifoFd, gCSIDataDumpBuffer + gBytesReadSofar, gRemainingBytes);
if (bytes_read < 0) {
int err_no = errno;
if (err_no == EAGAIN || err_no == EINTR) {
continue;
}
CSIFW_LOGE("read error %d\n", err_no);
continue; // or return
}

gBytesReadSofar += bytes_read;
gRemainingBytes -= bytes_read;

if (gRemainingBytes == 0) {
// Complete data received
gWaitingForData = 0;
// Send the data to the client
len = sendto(gSockFd, gCSIDataDumpBuffer, gBytesReadSofar, 0, (struct sockaddr *)&gClientAddr, sizeof(gClientAddr));
if (len == -1) {
CSIFW_LOGE("sendto error:%d", errno);
continue;
}
CSIFW_LOGI("Sent %d bytes to client", len);
print_buf(gCSIDataDumpBuffer,len);
}
}
}
}
}

CSIFW_RES csi_logs_dumper_init()
{
if ((gSockFd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
CSIFW_LOGE("failed to create a socket fd");
return CSIFW_ERROR;
}

memset(&gServerAddr, 0, sizeof(gServerAddr));
gServerAddr.sin_family = AF_INET;
gServerAddr.sin_addr.s_addr = INADDR_ANY;
gServerAddr.sin_port = htons(PORT);

if (bind(gSockFd, (struct sockaddr*)&gServerAddr, sizeof(gServerAddr)) < 0) {
CSIFW_LOGE("binding socket failed");
close(gSockFd);
return CSIFW_ERROR;
}
printf("server Socket Created\n");
gFifoFd = open(CSI_DUMP_DATA_QUEUE_NAME, O_RDONLY | O_NONBLOCK);
if (gFifoFd < 0) {
CSIFW_LOGE("open CSI_DUMP_DATA_QUEUE fail %d", errno);
close(gSockFd);
return CSIFW_ERROR;
}

if (pthread_create(&gThreadId, NULL, dataTransmitter, NULL) != 0) {
CSIFW_LOGE("Failed to create dataTransmitter thread %d", errno);
close(gSockFd);
close(gFifoFd);
return CSIFW_ERROR;
}

if (pthread_setname_np(gThreadId, "CSI_DataDumpOverNetwork") != 0) {
CSIFW_LOGE("Error in setting dataTransmitter thread name, error_no: %d", errno);
}
CSIFW_LOGI("CSI_DataDumpOverNetwork created");
return CSIFW_OK;
}

CSIFW_RES csi_logs_dumper_deinit()
{
gListener = NULL;
close(gSockFd);
close(gFifoFd);
return CSIFW_OK;
}
92 changes: 92 additions & 0 deletions framework/src/csifw/CSIService.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
#include "include/CSIParser.h"
#include "include/CSIPacketReceiver.h"
#include "include/CSINetworkMonitor.h"
#ifdef CONFIG_CSI_DATA_DUMP_OVER_NETWORK
#include "include/CSILogsDumper.h"
#endif
#include <errno.h>
#include <fcntl.h>

COLLECT_STATE g_service_state = CSI_STATE_UNITIALIZED;
CONNECTION_STATE g_nw_state;
Expand All @@ -15,6 +20,57 @@ upd_parsed_data_listener g_parsed_callback;
static void* g_ptr;
static csi_action_param_t g_csifw_config __attribute__((aligned(64))) = {0,};

#ifdef CONFIG_CSI_DATA_DUMP_OVER_NETWORK
#define CSI_DATA_BUFFER_SIZE 1024

unsigned char gCSIDataBuffer[CSI_DATA_BUFFER_SIZE];
int gDataDumpDescriptor;
bool gCSIDataDumpEvent = STOP_DUMP;

static void csi_data_dump_listener(EVENT event) {
CSIFW_LOGD("csi_data_dump_listener called\n");
gCSIDataDumpEvent = event;
return;
}

static int send_message(int fd, void *buf, int buflen)
{
int sent = 0;
while (1) {
int res = write(fd, (void *)buf + sent, buflen - sent);
if (res < 0) {
int err_no = errno;
if (err_no == EAGAIN || err_no == EINTR) {
continue;
}
CSIFW_LOGE("write error %d", err_no);
return -1;
}
sent += res;
if (sent == buflen) {
break;
}
}
return 0;
}

CSIFW_RES csi_logs_dumper_send_to_queue(unsigned char *csi_buf, int len)
{
// Copy the length to the first two bytes and the data to the rest of the output buffer
uint16_t dest_len = (uint16_t)len;
memcpy(gCSIDataBuffer, &dest_len, 2);
memcpy(gCSIDataBuffer + 2, csi_buf, len);

int res = send_message(gDataDumpDescriptor, (void *)gCSIDataBuffer, len + 2);

if (res < 0) {
CSIFW_LOGE("Failed to send message to CSI_DUMP_DATA_QUEUE");
return CSIFW_ERROR;
}
return CSIFW_OK;
}
#endif

static void CSIRawDataListener(CSIFW_RES res, int raw_csi_buff_len, unsigned char *raw_csi_buff, int raw_csi_data_len)
{
//Send raw data to UPD
Expand All @@ -24,6 +80,15 @@ static void CSIRawDataListener(CSIFW_RES res, int raw_csi_buff_len, unsigned cha
}
if (g_raw_callback) {
g_raw_callback(res, raw_csi_buff_len, raw_csi_buff, g_ptr);
#ifdef CONFIG_CSI_DATA_DUMP_OVER_NETWORK
if (gCSIDataDumpEvent) {
CSIFW_RES ret = csi_logs_dumper_send_to_queue(raw_csi_buff, raw_csi_buff_len);
if (ret != CSIFW_OK) {
CSIFW_LOGE("Failed to send CSI data to CSI_DUMP_DATA_QUEUE");
}
CSIFW_LOGD("CSI data sent to CSI_DUMP_DATA_QUEUE");
}
#endif
}
}

Expand All @@ -44,6 +109,28 @@ CSIFW_RES csi_manager_init(void)

CSIFW_RES csi_service_init(upd_raw_data_listener raw_callback, upd_parsed_data_listener parsed_callback, unsigned int interval, void* ptr)
{
#ifdef CONFIG_CSI_DATA_DUMP_OVER_NETWORK
int result = mkfifo(CSI_DUMP_DATA_QUEUE_NAME, 0666);
if (result < 0 && result != -EEXIST) {
CSIFW_LOGE("create CSI_DUMP_DATA_QUEUE fail %d", errno);
return CSIFW_ERROR;
}
gDataDumpDescriptor = open(CSI_DUMP_DATA_QUEUE_NAME, O_WRONLY | O_NONBLOCK);
if (gDataDumpDescriptor < 0) {
CSIFW_LOGE("open CSI_DUMP_DATA_QUEUE fail %d", errno);
unlink(CSI_DUMP_DATA_QUEUE_NAME);
return CSIFW_ERROR;
}
result = csi_logs_dumper_init();
if (result != CSIFW_OK) {
CSIFW_LOGE("open csi_logs_dumper_init fail");
close(gDataDumpDescriptor);
unlink(CSI_DUMP_DATA_QUEUE_NAME);
return CSIFW_ERROR;
}
set_event_listener(csi_data_dump_listener);
#endif

g_ptr = ptr;
if (g_service_state != CSI_STATE_UNITIALIZED) {
CSIFW_LOGE("Already Initialized");
Expand Down Expand Up @@ -128,6 +215,11 @@ CSIFW_RES csi_service_deinit()
}
g_service_state = CSI_STATE_UNITIALIZED;
csi_packet_receiver_deinit();
#ifdef CONFIG_CSI_DATA_DUMP_OVER_NETWORK
csi_logs_dumper_deinit();
close(gDataDumpDescriptor);
unlink(CSI_DUMP_DATA_QUEUE_NAME);
#endif
if (g_parsed_buffptr) {
free(g_parsed_buffptr);
g_parsed_buffptr = NULL;
Expand Down
3 changes: 3 additions & 0 deletions framework/src/csifw/Make.defs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ ifeq ($(CONFIG_CSIFW), y)
CFLAGS += -I${TOPDIR}/os/include
CSRCS += CSIPacketReceiver.c CSIParser.c CSIService.c PingGenerator.c CSINetworkMonitor.c rb.c

ifeq ($(CONFIG_CSI_DATA_DUMP_OVER_NETWORK), y)
CSRCS += CSILogsDumper.c
endif

DEPPATH += --dep-path src/csifw
VPATH += :src/csifw
Expand Down
21 changes: 21 additions & 0 deletions framework/src/csifw/include/CSILogsDumper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef __CSI_LOGS_DUMPER__
#define __CSI_LOGS_DUMPER__

#include "csifw.h"

#ifdef CONFIG_CSI_DATA_DUMP_OVER_NETWORK
#define CSI_DUMP_DATA_QUEUE_NAME "/dev/csidump_data"

typedef enum EVENT {
STOP_DUMP,
START_DUMP
} EVENT;

CSIFW_RES csi_logs_dumper_init();
CSIFW_RES csi_logs_dumper_deinit();

typedef void (*csiDataDumpListener)(EVENT event);
void set_event_listener(csiDataDumpListener listener);
#endif

#endif /* __CSI_LOGS_DUMPER__ */
16 changes: 16 additions & 0 deletions tools/csi_datadump/README_csi_datadump_udp_client.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# How To Run csi_datadump_udp_client.c File

## Steps:
### 1. First compile the file:
```bash
gcc -o program csi_datadump_udp_client.c -lpthread
```

### 2. Run the program
Command Format: ./program <IP_ADDRESS> <PORT>
```bash
./program 192.168.1.120 5000
```

## How to STOP the datadump
#### Type *STOP* in terminal and press enter.
Loading

0 comments on commit d6f39fb

Please sign in to comment.