cariboulabs-cariboulite/software/libcariboulite/src/caribou_smi/caribou_smi_modules.c

119 wiersze
2.7 KiB
C

#ifndef ZF_LOG_LEVEL
#define ZF_LOG_LEVEL ZF_LOG_VERBOSE
#endif
#define ZF_LOG_DEF_SRCLOC ZF_LOG_SRCLOC_LONG
#define ZF_LOG_TAG "CARIBOU_SMI_MODULES"
#define _GNU_SOURCE
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include "zf_log/zf_log.h"
#include "caribou_smi.h"
#include "kernel/smi_stream_dev_gen.h"
#define delete_module(name, flags) syscall(__NR_delete_module, name, flags)
#define init_module(module_image, len, param_values) syscall(__NR_init_module, module_image, len, param_values)
#define finit_module(fd, param_values, flags) syscall(__NR_finit_module, fd, param_values, flags)
//===========================================================
int caribou_smi_check_modules_loaded(char* mod_name)
{
char line[256] = {0};
int found = 0;
FILE *fid = fopen ("/proc/modules", "r");
if (fid == NULL)
{
return -1;
}
while (fgets(line, sizeof(line), fid))
{
char* srch = strstr(line, mod_name);
if (srch != NULL)
{
if (!isspace(srch[strlen(mod_name)])) continue;
found = 1;
}
}
fclose(fid);
return found;
}
//===========================================================
int caribou_smi_remove_module(char* module_name)
{
if (delete_module(module_name, O_NONBLOCK) != 0)
{
ZF_LOGE("Module removing '%s' failed", module_name);
return -1;
}
return 0;
}
//===========================================================
int caribou_smi_insert_smi_modules(char* module_name,
uint8_t* buffer,
size_t len,
const char* params)
{
if (init_module(buffer, len, params) != 0)
{
ZF_LOGE("Module insertion '%s' failed", module_name);
return -1;
}
return 0;
}
//===========================================================
int caribou_smi_check_modules(bool reload)
{
int ret = 0;
int bcm_smi_dev_loaded = caribou_smi_check_modules_loaded("bcm2835_smi_dev");
int smi_stream_dev_loaded = caribou_smi_check_modules_loaded("smi_stream_dev");
int bcm_smi_loaded = caribou_smi_check_modules_loaded("bcm2835_smi");
if (bcm_smi_loaded != 1)
{
ZF_LOGE("SMI base driver not loaded - check device tree");
return -1;
}
if (smi_stream_dev_loaded == 1 && reload)
{
ZF_LOGD("Unloading smi-stream module");
ret = caribou_smi_remove_module("smi_stream_dev");
smi_stream_dev_loaded = 0;
}
if (bcm_smi_dev_loaded == 1)
{
ret = caribou_smi_remove_module("bcm2835_smi_dev");
}
if (ret != 0)
{
ZF_LOGE("Error unloading module from system");
return -1;
}
if (!smi_stream_dev_loaded || reload)
{
ZF_LOGD("Loading smi-stream module");
return caribou_smi_insert_smi_modules("smi_stream_dev", smi_stream_dev, sizeof(smi_stream_dev), "");
}
return 0;
}