From 3fdd59a91136e04809d6870a25a47534d7acb311 Mon Sep 17 00:00:00 2001 From: Mark Farrugia Date: Thu, 4 Apr 2019 10:32:06 +1100 Subject: Add ability to cleanup avirt - Add reset all function for streams - Add checks for empty /config dir, to avoid remount of configfs Signed-off-by: Mark Farrugia --- include/avirt/avirt.h | 2 + src/avirt-config.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 102 insertions(+), 7 deletions(-) diff --git a/include/avirt/avirt.h b/include/avirt/avirt.h index 9389f47..afd856f 100644 --- a/include/avirt/avirt.h +++ b/include/avirt/avirt.h @@ -112,6 +112,8 @@ int snd_avirt_audiopaths(struct snd_avirt_audiopath **audiopaths, int *count); */ int snd_avirt_card_configure(); +int snd_avirt_card_unconfigure(); + /** * snd_avirt_pcm_info - Get PCM info for a given PCM name * @pcm_name: The PCM name of which to retrieve the PCM info diff --git a/src/avirt-config.c b/src/avirt-config.c index 6f1391c..a52ef0a 100644 --- a/src/avirt-config.c +++ b/src/avirt-config.c @@ -134,9 +134,29 @@ static bool configfs_mounted = false; static bool card_configured = false; static int card_index = -1; +bool check_dir_empty(char *dirname) +{ + int n = 0; + struct dirent *d; + + DIR *dir = opendir(dirname); + if (dir == NULL) // Not a directory or doesn't exist + return 1; + while ((d = readdir(dir)) != NULL) { + if (++n > 2) // Ignore the '.' and '..' directories + break; + } + + closedir(dir); + if (n <= 2) // Directory Empty + return true; + + return false; +} + static int mount_configfs() { - int err; + int err = 0; char fsline[100]; bool configfs_supported = false; FILE *procfs; @@ -164,14 +184,18 @@ static int mount_configfs() if (stat("/config", &st) == -1) mkdir("/config", S_IRWXU | S_IRWXG | S_IRWXO); - err = mount("none", "/config", "configfs", 0, NULL); - if (!err) + // Check whether configfs is mounted, if not, mount it + if (check_dir_empty("/config")) { - AVIRT_DEBUG("Successfully mounted configfs"); - configfs_mounted = true; + err = mount("none", "/config", "configfs", 0, NULL); + if (!err) + { + AVIRT_DEBUG("Successfully mounted configfs"); + configfs_mounted = true; + } + else + AVIRT_ERROR("Failed to mount configfs filesystem!"); } - else - AVIRT_ERROR("Failed to mount configfs filesystem!"); return err; } @@ -409,6 +433,48 @@ close_handle: return retval; } +static int snd_avirt_stream_reset_all() +{ + int err; + DIR *d; + struct dirent *dir; + char path[AVIRT_CONFIGFS_PATH_MAXLEN]; + + d = opendir(AVIRT_CONFIGFS_PATH_STREAMS); + if (d) + { + while ((dir = readdir(d)) != NULL) + { + // Ignore the directory . and .. + if ((!strcmp(dir->d_name, ".")) || (!strcmp(dir->d_name, ".."))) + continue; + + memset(path, 0, AVIRT_CONFIGFS_PATH_MAXLEN); + strcpy(path, AVIRT_CONFIGFS_PATH_STREAMS); + strcat(path, dir->d_name); + + // If not a directory, continue + struct stat path_stat; + stat(path, &path_stat); + if (S_ISREG(path_stat.st_mode)) + continue; + + err = rmdir(path); + if (err < 0) + { + AVIRT_ERROR_V("Cannot remove config item '%s' at directory '%s'", dir->d_name, path); + return err; + } + } + + AVIRT_DEBUG("Reset streams!"); + + return 0; + } + + return -EPERM; +} + int snd_avirt_stream_new(const char *name, unsigned int channels, int direction, const char *map, bool internal) { @@ -526,6 +592,33 @@ int snd_avirt_card_configure() AVIRT_DEBUG_V("Running router: '%s'", cmd); } + + return 0; +} + +int snd_avirt_card_unconfigure() +{ + // Check if card is already configured + if (!card_configured) + { + AVIRT_ERROR("Card is already unconfigured!"); + return -EPERM; + } + + IS_CONFIGFS_MOUNTED(); + + snd_avirt_stream_reset_all(); + + WRITE_ATTR_TO_DIR(AVIRT_CONFIGFS_PATH_STREAMS, "configured", "%d", 0); + + AVIRT_DEBUG("Card unconfigured!"); + card_configured = false; + + if (card_index < 0) + card_index = snd_avirt_card_index_get(0); + if (card_index < 0) + return card_index; + return 0; } -- cgit 1.2.3-korg