/*************************************************************************** conf_driver.h Copyright (C) 2007 Christoph Reichenbach This program may be modified and copied freely according to the terms of the GNU general public license (GPL), as long as the above copyright notice and the licensing information contained herein are preserved. Please refer to www.gnu.org for licensing details. This work is provided AS IS, without warranty of any kind, expressed or implied, including but not limited to the warranties of merchantibility, noninfringement, and fitness for a specific purpose. The author will not be held liable for any damage caused by this work or derivatives of it. By using this source code, you agree to the licensing terms as stated above. Please contact the maintainer for bug reports or inquiries. Current Maintainer: Christoph Reichenbach (CR) ***************************************************************************/ #ifndef CONF_DRIVER_H_ #define CONF_DRIVER_H_ /* Possible values for enum types */ typedef struct { char *name; int value; } conf_value_t; typedef struct { char *name; char *description; unsigned int type; unsigned int flags; union { char * str; int nr } default; /* Optional default value */ int min; /* For subrange types */ int max; /* For subrange types; for enum types */ conf_value_t *values; /* For enum types; NULL-terminated */ void *data; /* User data */ } conf_option_t; #define CONF_OPTION_TYPE_INT 0 #define CONF_OPTION_TYPE_SUBRANGE 1 /* ``interval'' type, i.e. bounded int */ #define CONF_OPTION_TYPE_STRING 2 #define CONF_OPTION_TYPE_BOOL 3 /* special built-in enum */ #define CONF_OPTION_TYPE_ENUM 4 #define CONF_OPTION_FLAG_MANDATORY (1<<0) /* Option MUST be set */ #define CONF_OPTION_FLAG_HAS_DEFAULT (1<<1) /* Option has a default value */ #define CONF_OPTION_FLAG_DYNAMIC (1<<2) /* Option may be altered after initialisation */ #define CONF_DRIVER_FAIL 1 #define CONF_DRIVER_SUCCESS 0 typedef struct conf_header { char [16] magic; /* MUST be CONF_DRIVER_MAGIC */ int freesci_version; /* MUST be CONF_DRIVER_VERSION */ int subsystem_id; /* CONF_SUBSYSTEM_*, if appropriate */ int subsystem_version; char *name; /* Long driver name */ char *version; /* Long driver version */ unsigned int dependencies; /* CONF_DRIVER_DEPENDENCY_* */ conf_option_t *options; /* Last option has name of NULL */ char * (*set_option)(void * self, /* points to base struct */ conf_option_t *, union { char *str; int nr }); /* Set option, return static error (if applicable) or NULL on success */ } conf_header_t; /* Universal driver header */ struct conf_driver; struct conf_subsystem; struct conf_main; #define CONF_SUBSYSTEM_GFX 0 #define CONF_SUBSYSTEM_SOUND 1 /* The sfx/player subsystem */ #define CONF_SUBSYSTEM_PCM_DEVICE 2 #define CONF_SUBSYSTEM_MIXER 3 #define CONF_SUBSYSTEM_SEQ 4 /* HW sequencer or generic softseq interface */ #define CONF_SUBSYSTEM_SOFTSEQ 5 #define CONF_SUBSYSTEM_TIMER 6 #define CONF_SUBSYSTEMS_NR 7 typedef struct conf_driver { conf_header_t header; char * (*init)(struct conf_driver *self, struct conf_subsystem *owner); /* Initialise, return static error message on error or NULL on success. ** The owner is guaranteed to have been configured and guaranteed NOT to have ** been initialised. */ void (*exit)(void); } conf_driver_t; typedef struct conf_subsystem { conf_header_t header; char * (*init)(struct conf_subsystem *self, struct conf_main *main, struct conf_driver *driver); /* Initialise, return static error message on error or NULL on success. ** The driver is configured and initialised, the main reference configured but ** not initialised. */ void (*exit)(void); char *(*get_default_driver)(struct conf_subsystem *self, int index); /* Get the nth default driver name, or NULL if there is none. These are tried in order if ** there is no explicit choice. */ conf_driver_t **builtin_drivers; /* NULL terminated list of built-in drivers */ char *dynamic_driver_prefix; /* string prefix to dynamically loaded drivers for this subsystem */ } conf_subsystem_t; typedef struct conf_main { conf_header_t header; conf_subsystem_t *[CONF_SUBSYSTEMS_NR]; char **dynamic_driver_locations; /* NULL terminated list of locations to check for dynamically loadable drivers */ char * (*init)(struct conf_main *self); /* Return static error message, or NULL on success. */ void (*exit)(void); } conf_main_t; #define CONF_DRIVER_MAGIC "FreeSCI driver" #define CONF_DRIVER_VERSION 1 /* Dependency flags */ #define CONF_DRIVER_DEPENDENCY_GFX (1 << CONF_SUBSYSTEM_GFX) #define CONF_DRIVER_DEPENDENCY_SOUND (1 << CONF_SUBSYSTEM_SOUND) #define CONF_DRIVER_DEPENDENCY_PCM_DEVICE (1 << CONF_SUBSYSTEM_PCM_DEVICE) #define CONF_DRIVER_DEPENDENCY_MIXER (1 << CONF_SUBSYSTEM_MIXER) #define CONF_DRIVER_DEPENDENCY_SEQ (1 << CONF_SUBSYSTEM_SEQ) #define CONF_DRIVER_DEPENDENCY_SOFTSEQ (1 << CONF_SUBSYSTEM_SOFTSEQ) #define CONF_DRIVER_DEPENDENCY_TIMER (1 << CONF_SUBSYSTEM_TIMER) #define CONF_BUILTIN_DEPENDENCIES (CONF_DRIVER_DEPENDENCY_GFX | CONF_DRIVER_DEPENDENCY_SOUND) /* ---------------------------------------------- */ /* -- convenience macros for driver developers -- */ /* ---------------------------------------------- */ char * conf_default_set_option(void * self, conf_option_t *option, union { char *str; int nr } value); /* Default implementation of the option setting function ** Parameters: (void *) self: Reference to the structure we should be accessing ** (conf_option_t *) option: The option to set ** (char * | nr) value: The value to set ** Returns : (char *) NULL on success, a static error string otherwise */ #define CONF_MK_HEADER(NAME, VERSION, SUBSYSTEM, DEPENDENCIES, OPTIONS, SETOPTION) \ { \ CONF_DRIVER_MAGIC, \ CONF_DRIVER_VERSION, \ SUBSYSTEM, \ 0, \ NAME, \ VERSION, \ DEPENDENCIES, \ OPTIONS, \ SETOPTION } #define CONF_OPT_ANY(STRUCTURE, FIELD, NAME, TYPE, DEFAULT, MIN, MAX, VALUES, FLAGS, DESCRIPTION) \ { \ NAME, \ DESCRIPTION, \ TYPE, \ FLAGS, \ DEFAULT, \ MIN, \ MAX, \ VALUES, \ (void *)(offsetof (STRUCTURE, FIELD)) \ } #define CONF_OPT_INT(S, F, NAME, DEFAULT, FLAGS, DESCR) CONF_OPT_ANY(S, F, NAME, CONF_OPTION_TYPE_INT, {.nr = DEFAULT}, 0, 0, NULL, (FLAGS) | CONF_OPTION_HAS_DEFAULT, DESCR) #define CONF_OPT_INT_NODEFAULT(S, F, NAME, FLAGS, DESCR) CONF_OPT_ANY(S, F, NAME, CONF_OPTION_TYPE_INT, {.nr = 0}, 0, 0, NULL, (FLAGS), DESCR) #define CONF_OPT_SUBRANGE(S, F, NAME, DEFAULT, MIN, MAX, FLAGS, DESCR) CONF_OPT_ANY(S, F, NAME, CONF_OPTION_TYPE_SUBRANGE, {.nr = DEFAULT}, MIN, MAX, NULL, (FLAGS) | CONF_OPTION_HAS_DEFAULT, DESCR) #define CONF_OPT_SUBRANGE_NODEFAULT(S, F, NAME, MIN, MAX, FLAGS, DESCR) CONF_OPT_ANY(S, F, NAME, CONF_OPTION_TYPE_SUBRANGE, {.nr = 0}, MIN, MAX, NULL, (FLAGS), DESCR) #define CONF_OPT_STRING(S, F, NAME, DEFAULT, FLAGS, DESCR) CONF_OPT_ANY(S, F, NAME, CONF_OPTION_TYPE_STRING, {.str = DEFAULT}, 0, 0, NULL, (FLAGS) | CONF_OPTION_HAS_DEFAULT, DESCR) #define CONF_OPT_STRING_NODEFAULT(S, F, NAME, FLAGS, DESCR) CONF_OPT_ANY(S, F, NAME, CONF_OPTION_TYPE_STRING, {.str = NULL}, 0, 0, NULL, (FLAGS), DESCR) #define CONF_OPT_BOOL(S, F, NAME, DEFAULT, FLAGS, DESCR) CONF_OPT_ANY(S, F, NAME, CONF_OPTION_TYPE_INT, {.nr = DEFAULT}, 0, 0, NULL, (FLAGS) | CONF_OPTION_HAS_DEFAULT, DESCR) #define CONF_OPT_BOOL_NODEFAULT(S, F, NAME, FLAGS, DESCR) CONF_OPT_ANY(S, F, NAME, CONF_OPTION_TYPE_INT, {.nr = 0}, 0, 0, NULL, (FLAGS), DESCR) #define CONF_OPT_ENUM(S, F, NAME, DEFAULT, CHOICES, FLAGS, DESCR) CONF_OPT_ANY(S, F, NAME, CONF_OPTION_TYPE_INT, {.nr = DEFAULT}, 0, 0, CHOICES, (FLAGS) | CONF_OPTION_HAS_DEFAULT, DESCR) #define CONF_OPT_ENUM_NODEFAULT(S, F, NAME, CHOICES, FLAGS, DESCR) CONF_OPT_ANY(S, F, NAME, CONF_OPTION_TYPE_INT, {.nr = 0}, 0, 0, CHOICES, (FLAGS), DESCR) #define CONF_LAST_OPTION { NULL, NULL, -1, 0, 0, 0, 0, NULL } #endif /* !defined(CONF_DRIVER_H_) */