From patchwork Sat Jan 14 08:23:55 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: mengdong.lin@linux.intel.com X-Patchwork-Id: 9516941 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id A0352607D6 for ; Sat, 14 Jan 2017 12:16:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 783CE285CB for ; Sat, 14 Jan 2017 12:16:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 596B2285D6; Sat, 14 Jan 2017 12:16:19 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5286E285CB for ; Sat, 14 Jan 2017 12:16:17 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 77F7A266D10; Sat, 14 Jan 2017 13:16:16 +0100 (CET) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id CC4E4266CC8; Sat, 14 Jan 2017 13:13:57 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 66018266834; Sat, 14 Jan 2017 09:20:45 +0100 (CET) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by alsa0.perex.cz (Postfix) with ESMTP id 0DACE2666FB for ; Sat, 14 Jan 2017 09:20:42 +0100 (CET) Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga102.jf.intel.com with ESMTP; 14 Jan 2017 00:20:41 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.33,226,1477983600"; d="scan'208";a="52920266" Received: from amanda-haswell-pc.sh.intel.com ([10.239.159.21]) by orsmga005.jf.intel.com with ESMTP; 14 Jan 2017 00:20:40 -0800 From: mengdong.lin@linux.intel.com To: alsa-devel@alsa-project.org Date: Sat, 14 Jan 2017 16:23:55 +0800 Message-Id: X-Mailer: git-send-email 2.5.0 In-Reply-To: References: Cc: tiwai@suse.de, liam.r.girdwood@linux.intel.com, Mengdong Lin , mengdong.lin@intel.com Subject: [alsa-devel] [PATCH v4 1/2] ucm: Load device-specific configuration file based on the card long name X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP From: Mengdong Lin Intel DSP platform drivers are used by many different devices. For user space to differentiate them, ASoC machine drivers may use the DMI info (vendor-product-version-board) as card long name. Possible card long names are: DellInc.-XPS139343-01-0310JH ASUSTeKCOMPUTERINC.-T100TA-1.0-T100TA Circuitco-MinnowboardMaxD0PLATFORM-D0-MinnowBoardMAX ... And user space can define configuration files like longname\longname.conf for a specific device. When being asked to load configuration file of a card, UCM will try to find the card in the local machine and get its long name. If the card long name is available, try to load the file longname\longname.conf to get the best device-specific configuration; if this file is not available, fall back to load the default configuration file shortname\shortname.conf as before. This update is backward compatible, because if ASoC machine drivers don't explicity use DMI or other means to set the card long name, ASoC core will use the card short name as the long name. And so UCM will load the config file that matches both the card short name and the long name. Signed-off-by: Mengdong Lin diff --git a/src/ucm/parser.c b/src/ucm/parser.c index c98373a..14ee33f 100644 --- a/src/ucm/parser.c +++ b/src/ucm/parser.c @@ -55,6 +55,9 @@ static const char * const component_dir[] = { NULL, /* terminator */ }; +static int filename_filter(const struct dirent *dirent); +static int is_component_directory(const char *dir); + static int parse_sequence(snd_use_case_mgr_t *uc_mgr, struct list_head *base, snd_config_t *cfg); @@ -1328,6 +1331,66 @@ static int parse_master_file(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg) return 0; } +/* find the card in the local machine and store the card long name */ +static int get_card_long_name(snd_use_case_mgr_t *mgr) +{ + const char *card_name = mgr->card_name; + snd_ctl_t *handle; + int card, err; + snd_ctl_card_info_t *info; + const char *_name, *_long_name; + + snd_ctl_card_info_alloca(&info); + + card = -1; + if (snd_card_next(&card) < 0 || card < 0) { + uc_error("no soundcards found..."); + return -1; + } + + while (card >= 0) { + char name[32]; + + sprintf(name, "hw:%d", card); + err = snd_ctl_open(&handle, name, 0); + if (err < 0) { + uc_error("control open (%i): %s", card, + snd_strerror(err)); + goto next_card; + } + + err = snd_ctl_card_info(handle, info); + if (err < 0) { + uc_error("control hardware info (%i): %s", card, + snd_strerror(err)); + snd_ctl_close(handle); + goto next_card; + } + + /* Find the local card by comparing the given name with the + * card name and long name. User may open a card by its long + * name, so the given card name may be a long name. + */ + _name = snd_ctl_card_info_get_name(info); + _long_name = snd_ctl_card_info_get_longname(info); + if (!strncmp(card_name, _name, MAX_CARD_LONG_NAME) + || !strncmp(card_name, _long_name, MAX_CARD_LONG_NAME)) { + strncpy(mgr->card_long_name, _long_name, + MAX_CARD_LONG_NAME - 1); + snd_ctl_close(handle); + return 0; + } + + snd_ctl_close(handle); +next_card: + if (snd_card_next(&card) < 0) { + uc_error("snd_card_next"); + break; + } + } + + return -1; +} static int load_master_config(const char *card_name, snd_config_t **cfg) { char filename[MAX_FILE]; @@ -1349,15 +1412,45 @@ static int load_master_config(const char *card_name, snd_config_t **cfg) return 0; } -/* load master use case file for sound card */ +/* load master use case file for sound card + * + * The same ASoC machine driver can be shared by many different devices. + * For user space to differentiate them and get the best device-specific + * configuration, ASoC machine drivers may use the DMI info + * (vendor.product.board) as the card long name. And user space can define + * configuration files like longname\longname.conf for a specific device. + * + * This function will try to find the card in the local machine and get its + * long name, then load the file longname\longname.conf to get the best + * device-specific configuration. If the card is not found in the local + * machine or the device-specific file is not available, fall back to load + * the default configuration file name\name.conf. + */ int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr) { snd_config_t *cfg; int err; - err = load_master_config(uc_mgr->card_name, &cfg); - if (err < 0) - return err; + err = get_card_long_name(uc_mgr); + if (err == 0) /* load file that maches the card long name */ + err = load_master_config(uc_mgr->card_long_name, &cfg); + + if (err == 0) { + /* got device-specific file that matches the card long name */ + strncpy(uc_mgr->conf_file_name, uc_mgr->card_long_name, + MAX_CARD_LONG_NAME - 1); + } else { + /* Fall back to the file that maches the given card name, + * either short name or long name (users may open a card by + * its name or long name). + */ + err = load_master_config(uc_mgr->card_name, &cfg); + if (err < 0) + return err; + strncpy(uc_mgr->conf_file_name, uc_mgr->card_name, + MAX_CARD_LONG_NAME - 1); + } + err = parse_master_file(uc_mgr, cfg); snd_config_delete(cfg); if (err < 0) diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h index 6d3302f..299a5b9 100644 --- a/src/ucm/ucm_local.h +++ b/src/ucm/ucm_local.h @@ -41,6 +41,7 @@ #include "use-case.h" #define MAX_FILE 256 +#define MAX_CARD_LONG_NAME 80 #define ALSA_USE_CASE_DIR ALSA_CONFIG_DIR "/ucm" #define SEQUENCE_ELEMENT_TYPE_CDEV 1 @@ -190,6 +191,8 @@ struct use_case_verb { */ struct snd_use_case_mgr { char *card_name; + char card_long_name[MAX_CARD_LONG_NAME]; + char conf_file_name[MAX_CARD_LONG_NAME]; char *comment; /* use case verb, devices and modifier configs parsed from files */