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 */
2535struct 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 */
6891dmod_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