Skip to content

Commit 052632f

Browse files
committed
Enhance dmdevfs module: add driver configuration and error handling in initialization
1 parent 46a0ca7 commit 052632f

File tree

2 files changed

+253
-5
lines changed

2 files changed

+253
-5
lines changed

CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
1515
if(NOT DEFINED DMOD_MODULE_VERSION)
1616
set(DMOD_MODULE_VERSION "0.1" CACHE STRING "DMOD module version")
1717
endif()
18+
set(DMOD_MODE "DMOD_MODULE" CACHE STRING "DMOD build mode")
1819

1920
# ======================================================================
2021
# Fetch DMOD repository
@@ -78,8 +79,11 @@ dmod_add_library(${DMOD_MODULE_NAME} ${DMOD_MODULE_VERSION}
7879
# Link to other DMOD modules (will be downloaded on build time)
7980
dmod_link_modules(${DMOD_MODULE_NAME}
8081
dmfsi
82+
dmdrvi
83+
dmini
84+
dmlist
8185
)
8286

8387
target_include_directories(${DMOD_MODULE_NAME} PRIVATE
8488
${CMAKE_CURRENT_SOURCE_DIR}/include
85-
)
89+
)

src/dmdevfs.c

Lines changed: 248 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,45 @@
1212
#include "dmod.h"
1313
#include "dmdevfs.h"
1414
#include "dmfsi.h"
15+
#include "dmlist.h"
16+
#include "dmini.h"
17+
#include "dmdrvi.h"
1518
#include <string.h>
1619

1720
/**
1821
* @brief Magic number for DMDEVFS context validation
1922
*/
2023
#define DMDEVFS_CONTEXT_MAGIC 0x444D4456 // 'DMDV'
2124

25+
typedef struct
26+
{
27+
dmdrvi_context_t driver_context; // Driver-specific context
28+
Dmod_Context_t* driver; // Driver module context
29+
dmdrvi_dev_num_t dev_num; // Device number assigned to the driver
30+
} driver_node_t;
31+
2232
/**
2333
* @brief File system context structure
2434
*/
2535
struct dmfsi_context
2636
{
27-
uint32_t magic;
28-
void* driver_context; // Driver-specific context
37+
uint32_t magic;
38+
const char* config_path; // Path with the configuration files
39+
dmlist_context_t* drivers; // List of loaded drivers
2940
};
3041

42+
43+
// ============================================================================
44+
// Local prototypes
45+
// ============================================================================
46+
static int configure_drivers(dmfsi_context_t ctx, const char* driver_name, const char* config_path);
47+
static driver_node_t* configure_driver(const char* driver_name, dmini_context_t config_ctx);
48+
static bool is_file(const char* path);
49+
static void read_base_name(const char* path, char* base_name, size_t name_size);
50+
static dmini_context_t read_driver_for_config(const char* config_path, char* driver_name, size_t name_size, const char* default_driver);
51+
static Dmod_Context_t* prepare_driver_module(const char* driver_name, bool* was_loaded, bool* was_enabled);
52+
static void cleanup_driver_module(const char* driver_name, bool was_loaded, bool was_enabled);
53+
3154
// ============================================================================
3255
// Module Interface Implementation
3356
// ============================================================================
@@ -67,6 +90,18 @@ int dmod_deinit(void)
6790
*/
6891
dmod_dmfsi_dif_api_declaration( 1.0, dmdevfs, dmfsi_context_t, _init, (const char* config) )
6992
{
93+
if(config == NULL)
94+
{
95+
DMOD_LOG_ERROR("dmdevfs: Config path is NULL\n");
96+
return NULL;
97+
}
98+
99+
if(strlen(config) == 0)
100+
{
101+
DMOD_LOG_ERROR("dmdevfs: Config path is empty\n");
102+
return NULL;
103+
}
104+
70105
dmfsi_context_t ctx = Dmod_Malloc(sizeof(struct dmfsi_context));
71106
if (ctx == NULL)
72107
{
@@ -75,9 +110,18 @@ dmod_dmfsi_dif_api_declaration( 1.0, dmdevfs, dmfsi_context_t, _init, (const cha
75110
}
76111

77112
ctx->magic = DMDEVFS_CONTEXT_MAGIC;
78-
ctx->driver_context = NULL;
113+
ctx->config_path = Dmod_StrDup(config);
114+
ctx->drivers = dmlist_create(DMOD_MODULE_NAME);
79115

80-
// TODO: Initialize driver context based on config
116+
int res = configure_drivers(ctx, NULL, ctx->config_path);
117+
if (res != DMFSI_OK)
118+
{
119+
DMOD_LOG_ERROR("dmdevfs: Failed to configure drivers\n");
120+
dmlist_destroy(ctx->drivers);
121+
Dmod_Free((void*)ctx->config_path);
122+
Dmod_Free(ctx);
123+
return NULL;
124+
}
81125

82126
return ctx;
83127
}
@@ -406,3 +450,203 @@ dmod_dmfsi_dif_api_declaration( 1.0, dmdevfs, int, _rename, (dmfsi_context_t ctx
406450
// TODO: Implement file renaming
407451
return DMFSI_ERR_GENERAL;
408452
}
453+
454+
455+
// ============================================================================
456+
// Local functions
457+
// ============================================================================
458+
459+
/**
460+
* @brief Configure drivers based on the configuration file
461+
*/
462+
static int configure_drivers(dmfsi_context_t ctx, const char* driver_name, const char* config_path)
463+
{
464+
void* dir = Dmod_OpenDir(config_path);
465+
if (dir == NULL)
466+
{
467+
DMOD_LOG_ERROR("dmdevfs: Failed to open config directory: %s\n", ctx->config_path);
468+
return DMFSI_ERR_NOT_FOUND;
469+
}
470+
471+
const char* entry;
472+
while ((entry = Dmod_ReadDir(dir)) != NULL)
473+
{
474+
if (is_file(entry))
475+
{
476+
char module_name[DMOD_MAX_MODULE_NAME_LENGTH];
477+
dmini_context_t config_ctx = read_driver_for_config(entry, module_name, sizeof(module_name), driver_name);
478+
if (config_ctx == NULL)
479+
{
480+
DMOD_LOG_ERROR("dmdevfs: Failed to read driver for config: %s\n", entry);
481+
continue;
482+
}
483+
484+
driver_node_t* driver_node = configure_driver(module_name, config_ctx);
485+
dmini_destroy(config_ctx);
486+
if (driver_node == NULL)
487+
{
488+
DMOD_LOG_ERROR("dmdevfs: Failed to configure driver: %s\n", module_name);
489+
continue;
490+
}
491+
if(dmlist_push_back(ctx->drivers, driver_node) != 0)
492+
{
493+
DMOD_LOG_ERROR("dmdevfs: Failed to add driver to list: %s\n", module_name);
494+
Dmod_Free(driver_node);
495+
continue;
496+
}
497+
}
498+
else
499+
{
500+
// read driver name from directory name
501+
char module_name[DMOD_MAX_MODULE_NAME_LENGTH];
502+
read_base_name(entry, module_name, sizeof(module_name));
503+
int res = configure_drivers(ctx, driver_name, entry);
504+
if (res != DMFSI_OK)
505+
{
506+
DMOD_LOG_ERROR("dmdevfs: Failed to configure drivers in directory: %s\n", entry);
507+
}
508+
}
509+
}
510+
Dmod_CloseDir(dir);
511+
return DMFSI_OK;
512+
}
513+
514+
/**
515+
* @brief Configure a single driver based on its name and configuration file
516+
*/
517+
static driver_node_t* configure_driver(const char* driver_name, dmini_context_t config_ctx)
518+
{
519+
bool was_loaded = false;
520+
bool was_enabled = false;
521+
Dmod_Context_t* driver = prepare_driver_module(driver_name, &was_loaded, &was_enabled);
522+
if (driver == NULL)
523+
{
524+
return NULL;
525+
}
526+
527+
dmod_dmdrvi_create_t dmdrvi_create = Dmod_GetDifFunction(driver, dmod_dmdrvi_create_sig);
528+
if (dmdrvi_create == NULL)
529+
{
530+
DMOD_LOG_ERROR("Driver module does not implement dmdrvi_create: %s\n", driver_name);
531+
cleanup_driver_module(driver_name, was_loaded, was_enabled);
532+
return NULL;
533+
}
534+
535+
driver_node_t* driver_node = Dmod_Malloc(sizeof(driver_node_t));
536+
if (driver_node == NULL)
537+
{
538+
DMOD_LOG_ERROR("Failed to allocate memory for driver node: %s\n", driver_name);
539+
cleanup_driver_module(driver_name, was_loaded, was_enabled);
540+
return NULL;
541+
}
542+
543+
driver_node->driver = driver;
544+
driver_node->driver_context = dmdrvi_create(config_ctx, &driver_node->dev_num);
545+
if (driver_node->driver_context == NULL)
546+
{
547+
DMOD_LOG_ERROR("Failed to create driver context: %s\n", driver_name);
548+
cleanup_driver_module(driver_name, was_loaded, was_enabled);
549+
Dmod_Free(driver_node);
550+
return NULL;
551+
}
552+
553+
return driver_node;
554+
}
555+
556+
/**
557+
* @brief Check if a path is a file
558+
*/
559+
static bool is_file(const char* path)
560+
{
561+
return Dmod_Access(path, DMOD_F_OK) == 0;
562+
}
563+
564+
/**
565+
* @brief Extract base name from a path
566+
*/
567+
static void read_base_name(const char* path, char* base_name, size_t name_size)
568+
{
569+
const char* last_slash = strrchr(path, '/');
570+
const char* name_start = (last_slash != NULL) ? last_slash + 1 : path;
571+
strncpy(base_name, name_start, name_size);
572+
base_name[name_size - 1] = '\0';
573+
}
574+
575+
/**
576+
* @brief Read driver name from configuration file
577+
*/
578+
static dmini_context_t read_driver_for_config(const char* config_path, char* driver_name, size_t name_size, const char* default_driver)
579+
{
580+
dmini_context_t ctx = dmini_create();
581+
if (ctx == NULL)
582+
{
583+
DMOD_LOG_ERROR("dmdevfs: Failed to create INI context\n");
584+
return NULL;
585+
}
586+
587+
int res = dmini_parse_file(ctx, config_path);
588+
if (res != DMINI_OK)
589+
{
590+
DMOD_LOG_ERROR("dmdevfs: Failed to parse INI file: %s\n", config_path);
591+
dmini_destroy(ctx);
592+
return NULL;
593+
}
594+
595+
const char* name = dmini_get_string(ctx, "main", "driver_name", default_driver);
596+
if(name != NULL)
597+
{
598+
strncpy(driver_name, name, name_size);
599+
driver_name[name_size - 1] = '\0';
600+
return ctx;
601+
}
602+
603+
read_base_name(config_path, driver_name, name_size);
604+
605+
// cut the `.ini` extension if present
606+
char* ext = strrchr(driver_name, '.');
607+
if (ext != NULL && strcmp(ext, ".ini") == 0)
608+
{
609+
*ext = '\0';
610+
}
611+
return ctx;
612+
}
613+
614+
/**
615+
* @brief Prepare and load a driver module
616+
*/
617+
static Dmod_Context_t* prepare_driver_module(const char* driver_name, bool* was_loaded, bool* was_enabled)
618+
{
619+
*was_loaded = Dmod_IsModuleLoaded(driver_name);
620+
*was_enabled = Dmod_IsModuleEnabled(driver_name);
621+
Dmod_Context_t* driver = Dmod_LoadModuleByName(driver_name);
622+
if (driver == NULL)
623+
{
624+
DMOD_LOG_ERROR("Failed to load driver module: %s\n", driver_name);
625+
return NULL;
626+
}
627+
if (!*was_enabled && !Dmod_EnableModule(driver_name, true, NULL))
628+
{
629+
DMOD_LOG_ERROR("Failed to enable driver module: %s\n", driver_name);
630+
if(!*was_loaded)
631+
{
632+
Dmod_UnloadModule(driver_name, false);
633+
}
634+
return NULL;
635+
}
636+
return driver;
637+
}
638+
639+
/**
640+
* @brief Cleanup and unload a driver module
641+
*/
642+
static void cleanup_driver_module(const char* driver_name, bool was_loaded, bool was_enabled)
643+
{
644+
if(!was_enabled)
645+
{
646+
Dmod_DisableModule(driver_name, false);
647+
}
648+
if(!was_loaded)
649+
{
650+
Dmod_UnloadModule(driver_name, false);
651+
}
652+
}

0 commit comments

Comments
 (0)