/* keep_module.c * * This is a very simple driver who's objective is to allow a module to * call * * open(, "O_RDONLY) * * and be kept loaded by the system. This is useful when developing modules that * require modules to be kept loaded but in order to develop having to reboot * to test revisions isn't a useful way of spending development time :) * * To configure it for your module, simply change the MODULE_TO_SAVE define below * to reflect the name of the module you wish to save. Different modules can be * assigned to different device numbers as desired. * * To unload the driver you simply issue * * cat * * This command will report a failure, but it will have relesed the module * reference allowing it to be unloaded by the kernel. * * To build: * * gcc -fno-pic -g -O0 -D_KERNEL_MODE=1 -nostdlib /boot/develop/lib/x86/_KERNEL_ \ * -o keep_module keep_module.c * * To install: * * cp keep_module ~/config/add-ons/kernel/drivers/bin/ * ln -s ~/config/add-ons/kernel/drivers/bin/keep_module \ * ~/config/add-ons/kernel/drivers/dev/misc * rescan keep_module * */ #include #include #include #include static module_info *mod = NULL; #define MODULE_TO_SAVE "network/interfaces/bone_ieee80211" #define DEVFS_ENTRY "misc/keep_module/0" static status_t km_open(const char *, uint32, void **); static status_t km_close(void *); static status_t km_free(void *); static status_t km_ioctl(void *, uint32, void *, size_t); static status_t km_read(void *, off_t, void *, size_t *); static status_t km_write(void *, off_t, const void *, size_t *); static opened = 0; static char *names[2] = { DEVFS_ENTRY, NULL }; struct keep_alive { int open; }; static device_hooks keep_module_hooks = { km_open, /* open */ km_close, /* close */ km_free, /* free */ km_ioctl, /* ioctl */ km_read, /* read */ km_write, /* write */ NULL, /* select */ NULL, /* deselect */ NULL, /* readv */ NULL, /* writev */ }; status_t init_hardware(void) { return B_NO_ERROR; } status_t init_driver(void) { return B_OK; } void uninit_driver(void) { } device_hooks *find_device(const char *name) { return &keep_module_hooks; } const char **publish_devices(void) { return (const char**)names; } static status_t km_open(const char *name, uint32 flags, void **cookie) { struct keep_alive *ka = NULL; status_t status = B_OK; set_dprintf_enabled(true); dprintf("km_open: opened = %d\n", opened); if (opened == 0) { status = get_module(MODULE_TO_SAVE, &mod); if (status != B_NO_ERROR) { dprintf("Unable to act as keepalive for " MODULE_TO_SAVE "\n"); return status; } ka = (struct keep_alive*)malloc(sizeof(*ka)); if (!ka) { put_module(MODULE_TO_SAVE); return B_ERROR; } dprintf("Saving module " MODULE_TO_SAVE " from it's impending death\n"); opened = 1; } else { status = B_ERROR; dprintf("Releasing module " MODULE_TO_SAVE " to it's doom\n"); put_module(MODULE_TO_SAVE); opened = 0; } *cookie = (void*)ka; return B_OK; } static status_t km_close(void *cookie) { if (opened == 1) { dprintf("Releasing module " MODULE_TO_SAVE " to it's doom\n"); put_module(MODULE_TO_SAVE); opened = 0; } return B_NO_ERROR; } static status_t km_free(void *cookie) { free(cookie); return B_NO_ERROR; } static status_t km_ioctl(void *cookie, uint32 msg, void *buf, size_t len) { return B_ERROR; } static status_t km_read(void *cookie, off_t pos, void *buf, size_t *len) { *len = -1; return B_ERROR; } static status_t km_write(void *cookie, off_t pos, const void *buf, size_t *len) { *len = -1; return B_ERROR; }