From patchwork Sat May 13 20:20:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Orlov X-Patchwork-Id: 13241328 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 13E62C77B7D for ; Mon, 15 May 2023 12:27:21 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 9332C1EF; Mon, 15 May 2023 14:26:29 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 9332C1EF DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1684153639; bh=bPKHJLxt6Wpo1+Kxpf04rXqb1UT97XW7pOUFS/DkcJI=; h=From:To:Cc:Subject:Date:List-Id:List-Archive:List-Help:List-Owner: List-Post:List-Subscribe:List-Unsubscribe:From; b=o2djIQmSSqflbD2k2InqfPN1v+e0t9pz7z1udVRmqXAB+ZdId892dx97iwORxcvib ezRlOF9upeqs/4M6hn2tUgnzDJWWyFhw2pnA+5xHdIeavkV6qNx/ZPqBYbqlwc9jwe F6/KK6UiZ6Shxbhe6QtTcO/se7dL9OGCgcTBsoeE= Received: by alsa1.perex.cz (Postfix, from userid 50401) id BA621F80549; Mon, 15 May 2023 14:26:03 +0200 (CEST) Received: from mailman-core.alsa-project.org (mailman-core.alsa-project.org [10.254.200.10]) by alsa1.perex.cz (Postfix) with ESMTP id 0E381F8016D; Mon, 15 May 2023 14:26:03 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id BBB6AF8053B; Sat, 13 May 2023 22:21:25 +0200 (CEST) Received: from mail-ed1-x532.google.com (mail-ed1-x532.google.com [IPv6:2a00:1450:4864:20::532]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id E0749F8014C for ; Sat, 13 May 2023 22:21:11 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz E0749F8014C Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20221208 header.b=SZ4hSMKs Received: by mail-ed1-x532.google.com with SMTP id 4fb4d7f45d1cf-5068638856dso2583025a12.1 for ; Sat, 13 May 2023 13:21:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1684009269; x=1686601269; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=pI0vsmpY7mdUr70LiqqOXYMCiqJ/xh4FarR28VDA3tQ=; b=SZ4hSMKsHGaXlLqSku8AD4/x/CeRqwaHcZPywriobqnvKyvivb450tjcJFRpNAplQx ZKkGZ6Lqjt/vAKFOsFwm9bznpX59kYJB6YzxqyLmF5awylrSTXjZzSNgfXJjPvc7nS9/ Kt8p97wvKXfucnIIbQdPjEIUb6iV22hbEdFAOT28HuG72UtKb6En97RAbmd5O3EukoaG 7dkx5q5T+1oOG8ScWGsZWtox3HC/dF2y7dRLPHjx1zqEy2pNE8tzJLlzGXQYeazEgq1e 9WHh9jcz4vQj0NmgmyF2cUfhfD758KbgJ/Tguy+OXnpKQiDz3MxnRz6AmAuSvO833RON I3Lg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1684009269; x=1686601269; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=pI0vsmpY7mdUr70LiqqOXYMCiqJ/xh4FarR28VDA3tQ=; b=FyaFGTkPPWY1ZCo8cqYUzjYo0e7bW6AGGpl4MZBwcAuJzatWhlgLfwtF8EeawQRvy4 Pnex1VdOTC08jXxHwYkii396ayS1WWSp0LRfPPWsPcdDUBggRg+/hsuRJz+FqTj2CIkE EAqYup7eIW62zsiEaFWiWCBKUexKKmuWvKc+1Ouiv3Y5QeU9kN+xkwvVDTR6fbjP2vXn EGIrRuz8yD2EpZLd2DuFgc+5cfGGdOhTGKpjYsquuv8M1H2RtstRcF/ajv2wL6ro8Dyz 92NTlgEAmGVy6XV1sA8AD0E911xbt33gJqQZkLT0470gXF54i95tF0Ci4oFyFb3DcV0e M7jg== X-Gm-Message-State: AC+VfDwTW3cfrLOv0uFN0z4sInl8e/ecbASvD0eTlU3zefL+0ipf/5ve oXr6rhnW8MPmhyDCaH91eWU= X-Google-Smtp-Source: ACHHUZ625/aVC/WnxBwyH6Dh1+EYRSKpvxQlGTanFoaRhbxtj1LMDThxQmKD1kACZ7pmrqVwVNpu8g== X-Received: by 2002:a05:6402:27cd:b0:50c:79f:c693 with SMTP id c13-20020a05640227cd00b0050c079fc693mr26358719ede.1.1684009269048; Sat, 13 May 2023 13:21:09 -0700 (PDT) Received: from ivan-B550MH.. ([37.252.94.55]) by smtp.gmail.com with ESMTPSA id d14-20020a50fb0e000000b0050bc6d0e880sm5109637edq.61.2023.05.13.13.21.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 13 May 2023 13:21:08 -0700 (PDT) From: Ivan Orlov To: corbet@lwn.net, akpm@linux-foundation.org, perex@perex.cz, tiwai@suse.com, broonie@kernel.org, skhan@linuxfoundation.org Cc: Ivan Orlov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, alsa-devel@alsa-project.org, linux-kselftest@vger.kernel.org, gregkh@linuxfoundation.org, himadrispandya@gmail.com, linux-kernel-mentees@lists.linuxfoundation.org Subject: [PATCH 1/3] docs: admin-guide: add valsa driver documentation Date: Sun, 14 May 2023 00:20:35 +0400 Message-Id: <20230513202037.158777-1-ivan.orlov0322@gmail.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 X-MailFrom: ivan.orlov0322@gmail.com X-Mailman-Rule-Hits: nonmember-moderation X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-alsa-devel.alsa-project.org-0; header-match-alsa-devel.alsa-project.org-1 Message-ID-Hash: ZMAACJ3YWAFZUMIWD3KCXKJHN3WQT4FW X-Message-ID-Hash: ZMAACJ3YWAFZUMIWD3KCXKJHN3WQT4FW X-Mailman-Approved-At: Mon, 15 May 2023 12:26:00 +0000 X-Mailman-Version: 3.3.8 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Add documentation for the new Virtual ALSA driver. It covers all possible usage cases: errors and delay injections, random and pattern-based data generation, playback and ioctl redefinition functionalities testing. We have a lot of different virtual media drivers, which can be used for testing of the userspace applications and media subsystem middle layer. However, all of them are aimed at testing the video functionality and simulating the video devices. For audio devices we have only snd-dummy module, which is good in simulating the correct behavior of an ALSA device. I decided to write a tool, which would help to test the userspace ALSA programs (and the PCM middle layer as well) under unusual circumstances to figure out how they would behave. So I came up with this Virtual ALSA Driver. This new Virtual ALSA Driver has several features which can be useful during the userspace ALSA applications testing/fuzzing, or testing/fuzzing of the PCM middle layer. Not all of them can be implemented using the existing virtual drivers (like dummy or loopback). Here is what can this driver do: - Simulate both capture and playback processes - Check the playback stream for containing the looped pattern - Generate random or pattern-based capture data - Inject delays into the playback and capturing processes - Inject errors during the PCM callbacks Also, this driver can check the playback stream for containing the predefined pattern, which is used in the corresponding selftest to check the PCM middle layer data transferring functionality. Additionally, this driver redefines the default RESET ioctl, and the selftest covers this PCM API functionality as well. Signed-off-by: Ivan Orlov --- Documentation/admin-guide/index.rst | 1 + Documentation/admin-guide/valsa.rst | 114 ++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 Documentation/admin-guide/valsa.rst diff --git a/Documentation/admin-guide/index.rst b/Documentation/admin-guide/index.rst index 43ea35613dfc..328cc59275a1 100644 --- a/Documentation/admin-guide/index.rst +++ b/Documentation/admin-guide/index.rst @@ -131,6 +131,7 @@ configure specific aspects of kernel behavior to your liking. thunderbolt ufs unicode + valsa vga-softcursor video-output xfs diff --git a/Documentation/admin-guide/valsa.rst b/Documentation/admin-guide/valsa.rst new file mode 100644 index 000000000000..64ffc130fb4c --- /dev/null +++ b/Documentation/admin-guide/valsa.rst @@ -0,0 +1,114 @@ +.. SPDX-License-Identifier: GPL-2.0 + +The Virtual ALSA Driver +======================= + +The Virtual ALSA Driver emulates a generic ALSA device, and can be used for +testing/fuzzing of the userspace ALSA applications, as well as for testing/fuzzing of +the ALSA middle layer. Additionally, it can be used for simulating hard to reproduce +problems with PCM devices. + +What can this driver do? +~~~~~~~~~~~~~~~~~~~~~~~~ + +At this moment the driver can do the following things: + * Simulate both capture and playback processes + * Generate random or pattern-based capturing data + * Inject delays into the playback and capturing processes + * Inject errors during the PCM callbacks + +Also, this driver can check the playback stream for containing the +predefined pattern, which is used in the corresponding selftest (alsa/valsa-test.sh) +to check the PCM middle layer data transferring functionality. Additionally, this +driver redefines the default RESET ioctl, and the selftest covers this PCM +API functionality as well. + +Configuration +------------- + +The driver has several parameters besides the common ALSA module parameters: + + * fill_mode (bool) - Buffer fill mode (see below) + * inject_delay (int) + * inject_hwpars_err (bool) + * inject_prepare_err (bool) + * inject_trigger_err (bool) + + +Capture Data Generation +----------------------- + +The driver has two modes of data generation: the first (0 in the fill_mode parameter) +means random data generation, the second (1 in the fill_mode) - pattern-based +data generation. Let's look at the second mode. + +First of all, you may want to specify the pattern for data generation. You can do it +by writing the pattern to the debugfs file (/sys/kernel/debug/valsa/fill_pattern). +Like that: + +.. code-block:: bash + + echo -n mycoolpattern > /sys/kernel/debug/valsa/fill_pattern + +After this, every capture action performed on the 'valsa' device will return +'mycoolpatternmycoolpatternmycoolpatternmy...' in the capturing buffer. + +The pattern itself can be up to 4096 bytes long. + +Delay injection +--------------- + +The driver has 'inject_delay' parameter, which has very self-descriptive name and +can be used for time delay/speedup simulations. The parameter has integer type, and +it means the delay added between module's internal timer ticks. + +If the 'inject_delay' value is positive, the buffer will be filled slower, if it is +negative - faster. You can try it yourself by starting a recording in any +audiorecording application (like Audacity) and selecting the 'valsa' device as a +source. + +This parameter can be also used for generating a huge amount of sound data in a very +short period of time (with the negative 'inject_delay' value). + +Errors injection +---------------- + +This module can be used for injecting errors into the PCM communication process. This +action can help you to figure out how the userspace ALSA program behaves under unusual +circumstances. + +For example, you can make all 'hw_params' PCM callback calls return EBUSY error by +writing '1' to the 'inject_hwpars_err' module parameter: + +.. code-block:: bash + + echo 1 > /sys/module/snd_valsa/parameters/inject_hwpars_err + +Errors can be injected into the following PCM callbacks: + + * hw_params (EBUSY) + * prepare (EINVAL) + * trigger (EINVAL) + + +Playback test +------------- + +This driver can be also used for the playback functionality testing - every time you +write the playback data to the 'valsa' PCM device and close it, the driver checks the +buffer for containing the looped pattern (which is specified in the fill_pattern +debugfs file). If the playback buffer content represents the looped pattern, 'pc_test' +debugfs entry is set into '1'. Otherwise, the driver sets it to '0'. + +ioctl redefinition test +----------------------- + +The driver redefines the 'reset' ioctl, which is default for all PCM devices. To test +this functionality, we can trigger the reset ioctl and check the 'ioctl_test' debugfs +entry: + +.. code-block:: bash + + cat /sys/kernel/debug/valsa/ioctl_test + +If the ioctl is triggered successfully, this file will contain '1', and '0' otherwise. From patchwork Sat May 13 20:20:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Orlov X-Patchwork-Id: 13241329 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2A189C77B7D for ; Mon, 15 May 2023 12:27:46 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 333FB827; Mon, 15 May 2023 14:26:54 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 333FB827 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1684153664; bh=iVO4DMxIV0t9VCc8ZDxns+fTK5ZxdMSHFXjZLMfkMyk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=vihP+I6/M9xl8/XA103MyWLn1RWAus67zscdR6Ll2Cz/h5JJeGZSCkP5lOT+TKJJe tqojUznjeMNaMJcAfuVbKRi6NYoWmtgv7aGd9LNMU3zDCniYUn7CpJNv4S+JQCdyL8 vGtk4r7a0BxiAyZNMP1tqW0slytv7h4Q3jR4q330= Received: by alsa1.perex.cz (Postfix, from userid 50401) id 0A9FCF80563; Mon, 15 May 2023 14:26:06 +0200 (CEST) Received: from mailman-core.alsa-project.org (mailman-core.alsa-project.org [10.254.200.10]) by alsa1.perex.cz (Postfix) with ESMTP id 60B6EF8055B; Mon, 15 May 2023 14:26:06 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 1523CF80534; Sat, 13 May 2023 22:21:34 +0200 (CEST) Received: from mail-ed1-x52e.google.com (mail-ed1-x52e.google.com [IPv6:2a00:1450:4864:20::52e]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id E162BF80310 for ; Sat, 13 May 2023 22:21:17 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz E162BF80310 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20221208 header.b=QsOK8sM1 Received: by mail-ed1-x52e.google.com with SMTP id 4fb4d7f45d1cf-50bcd46bf47so2562315a12.0 for ; Sat, 13 May 2023 13:21:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1684009276; x=1686601276; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=t7vo6BvW2H1vdB7sMH0xHmduoG7LKDTk7q43+7gCjYM=; b=QsOK8sM1+RcCQPn/F+LeLnhD2jkarLmEL8vto4eeeg5vJc5g2NhEpuvfC0ZP60VOAM gtSV+xeiMO5WYN1Jet6h3LhASDIwK3L3toK+dKlVcfNHOxvMmr9pfzSTHN/Vj/MK4GfH TlpodxL/3sx6Tz/eBwGarMWWu3scLpqedLcf4ibX4WEn2m6ZgEPKQbKH218/w/vV98X5 ktZAwaKB39/duWH50VbB+V3saawtmBGKOjRUb/Xb5lG8rWrFcoME6XPPXaRFyB4MN0pk NCqk24lI6kl5SSS997iHIAdDfMmwNf3ihWyC+1iPmj+LdzXr+6SC2jFM5imCzGdz0o4r tzfQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1684009276; x=1686601276; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=t7vo6BvW2H1vdB7sMH0xHmduoG7LKDTk7q43+7gCjYM=; b=gZ/grs9bP7HJighh6XMEqWkpn5BMrqKKvasMO+YKa7tVQk9cg1ZjjiiqWfV0hboUTe nWEfjUu0h1tBB75bsQ4O2wzA0/iLawo7ecIfWKHwg3GDbjIbvSSA//HatpyhVv68teD7 Cn2MCqBP8j5b1j7lDNStSlB30mGaUSlluROev9MxajAUH2aO7b66fhz+zCcgYtQyKeTB UhjRQJqPlq2+RnVoMP1nYEwv0+xs1/65poecqfAAuMfks8nZ4zDj1Pi2tyogaKV0TBG6 yqPY+a3zBpu6vc3DaD7z0TrTotde5JCQuS+0l3Uqra1bFO7x3zvxAdvQZzeDA6Zq5sjh yAnA== X-Gm-Message-State: AC+VfDwaJxQiWqDTTPqVpBXktCr3KooEvAw4HgsABNigcxcflrimtC3v UpN7j8QeFt7qYE10sryo13E= X-Google-Smtp-Source: ACHHUZ5hid9I++hBx0EwKI6R2injk6s4YAQ2g6slhk/csvD/qpe6PMhL33RI0WDCORk/E8+PeNv6dA== X-Received: by 2002:a05:6402:510c:b0:50d:a9bb:356c with SMTP id m12-20020a056402510c00b0050da9bb356cmr18973011edd.0.1684009275640; Sat, 13 May 2023 13:21:15 -0700 (PDT) Received: from ivan-B550MH.. ([37.252.94.55]) by smtp.gmail.com with ESMTPSA id d14-20020a50fb0e000000b0050bc6d0e880sm5109637edq.61.2023.05.13.13.21.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 13 May 2023 13:21:15 -0700 (PDT) From: Ivan Orlov To: corbet@lwn.net, akpm@linux-foundation.org, perex@perex.cz, tiwai@suse.com, broonie@kernel.org, skhan@linuxfoundation.org Cc: Ivan Orlov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, alsa-devel@alsa-project.org, linux-kselftest@vger.kernel.org, gregkh@linuxfoundation.org, himadrispandya@gmail.com, linux-kernel-mentees@lists.linuxfoundation.org Subject: [PATCH 2/3] ALSA: Implement the new virtual driver Date: Sun, 14 May 2023 00:20:36 +0400 Message-Id: <20230513202037.158777-2-ivan.orlov0322@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230513202037.158777-1-ivan.orlov0322@gmail.com> References: <20230513202037.158777-1-ivan.orlov0322@gmail.com> MIME-Version: 1.0 X-MailFrom: ivan.orlov0322@gmail.com X-Mailman-Rule-Hits: nonmember-moderation X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-alsa-devel.alsa-project.org-0; header-match-alsa-devel.alsa-project.org-1 Message-ID-Hash: PCNISC334MSZWNITFD2YEQS47JXGGN3Q X-Message-ID-Hash: PCNISC334MSZWNITFD2YEQS47JXGGN3Q X-Mailman-Approved-At: Mon, 15 May 2023 12:26:00 +0000 X-Mailman-Version: 3.3.8 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: We have a lot of different virtual media drivers, which can be used for testing of the userspace applications and media subsystem middle layer. However, all of them are aimed at testing the video functionality and simulating the video devices. For audio devices we have only snd-dummy module, which is good in simulating the correct behavior of an ALSA device. I decided to write a tool, which would help to test the userspace ALSA programs (and the PCM middle layer as well) under unusual circumstances to figure out how they would behave. So I came up with this Virtual ALSA Driver. This new Virtual ALSA Driver has several features which can be useful during the userspace ALSA applications testing/fuzzing, or testing/fuzzing of the PCM middle layer. Not all of them can be implemented using the existing virtual drivers (like dummy or loopback). Here is what can this driver do: - Simulate both capture and playback processes - Generate random or pattern-based capture data - Inject delays into the playback and capturing processes - Inject errors during the PCM callbacks Also, this driver can check the playback stream for containing the predefined pattern, which is used in the corresponding selftest to check the PCM middle layer data transferring functionality. Additionally, this driver redefines the default RESET ioctl, and the selftest covers this PCM API functionality as well. Pattern-based capture stream data generation works in the following way: user can set the pattern by writing to the 'fill_pattern' debugfs file. After that, the capture stream in case of reading will be filled with this pattern (for example, if the pattern is 'abc', the capture stream will contain 'abcabcabc...'). The pattern itself can be up to 4096 bytes long. After all, I think this driver would be a good start, and I believe in the future we will see more virtual sound drivers. Signed-off-by: Ivan Orlov --- MAINTAINERS | 7 + sound/drivers/Kconfig | 15 ++ sound/drivers/Makefile | 2 + sound/drivers/valsa.c | 508 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 532 insertions(+) create mode 100644 sound/drivers/valsa.c diff --git a/MAINTAINERS b/MAINTAINERS index 7e0b87d5aa2e..6dcb09d5f3d7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22411,6 +22411,13 @@ S: Maintained F: drivers/nvdimm/virtio_pmem.c F: drivers/nvdimm/nd_virtio.c +VIRTUAL ALSA DRIVER +M: Ivan Orlov +S: Maintained +F: Documentation/admin-guide/valsa.rst +F: sound/drivers/valsa.c +F: tools/testing/selftests/alsa/valsa-test.sh + VIRTUAL BOX GUEST DEVICE DRIVER M: Hans de Goede M: Arnd Bergmann diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig index be3009746f3a..fa7d6f22ff06 100644 --- a/sound/drivers/Kconfig +++ b/sound/drivers/Kconfig @@ -109,6 +109,21 @@ config SND_ALOOP To compile this driver as a module, choose M here: the module will be called snd-aloop. +config SND_VALSA + tristate "Virtual ALSA driver" + select SND_PCM + help + Say 'Y' or 'M' to include support for the Virtual ALSA driver. This + driver is aimed at extended testing of the userspace applications + which use the ALSA API, as well as the ALSA middle layer testing. + + It can generate random or pattern-based data into the capture stream, + check the playback stream for containing the selected pattern, inject + time delays during capture/playback, inject errors into the PCM + callbacks, redefine the RESET ioctl operation to perform the PCM middle + layer testing and inject errors during the PCM callbacks. You can find + the corresponding selftest in the 'alsa' selftests folder. + config SND_VIRMIDI tristate "Virtual MIDI soundcard" depends on SND_SEQUENCER diff --git a/sound/drivers/Makefile b/sound/drivers/Makefile index b60303180a1b..229eeb788995 100644 --- a/sound/drivers/Makefile +++ b/sound/drivers/Makefile @@ -8,6 +8,7 @@ snd-dummy-objs := dummy.o snd-aloop-objs := aloop.o snd-mtpav-objs := mtpav.o snd-mts64-objs := mts64.o +snd-valsa-objs := valsa.o snd-portman2x4-objs := portman2x4.o snd-serial-u16550-objs := serial-u16550.o snd-serial-generic-objs := serial-generic.o @@ -17,6 +18,7 @@ snd-virmidi-objs := virmidi.o obj-$(CONFIG_SND_DUMMY) += snd-dummy.o obj-$(CONFIG_SND_ALOOP) += snd-aloop.o obj-$(CONFIG_SND_VIRMIDI) += snd-virmidi.o +obj-$(CONFIG_SND_VALSA) += snd-valsa.o obj-$(CONFIG_SND_SERIAL_U16550) += snd-serial-u16550.o obj-$(CONFIG_SND_SERIAL_GENERIC) += snd-serial-generic.o obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o diff --git a/sound/drivers/valsa.c b/sound/drivers/valsa.c new file mode 100644 index 000000000000..62f05271cbad --- /dev/null +++ b/sound/drivers/valsa.c @@ -0,0 +1,508 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ALSA virtual driver + * + * Copyright 2023 Ivan Orlov + * + * This is a simple virtual ALSA driver, which can be used for audio applications/ALSA middle layer + * testing or fuzzing. + * It can: + * - Simulate 'playback' and 'capture' actions + * - Generate random or pattern-based capture data + * - Check playback buffer for containing looped template, and notify about the results + * through the debugfs entry + * - Inject delays into the playback and capturing processes. See 'inject_delay' parameter. + * - Inject errors during the PCM callbacks. + * - Register custom RESET ioctl and notify when it is called through the debugfs entry + * + * The driver supports framerates from 8 kHz to 48 kHz. At the moment, only one substream + * is supported. + * + * You can find the corresponding selftest in the 'alsa' selftests folder. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEVNAME "valsad" +#define CARD_NAME "virtualcard" +#define TIMER_PER_SEC 5 +#define TIMER_INTERVAL (HZ / TIMER_PER_SEC) +#define DELAY_JIFFIES HZ + +#define FILL_MODE_RAND 0 +#define FILL_MODE_PAT 1 + +#define MAX_PATTERN_LEN 4096 + +static int index = -1; +static char *id = "valsa"; +static bool enable = true; +static int inject_delay; +static bool inject_hwpars_err; +static bool inject_prepare_err; +static bool inject_trigger_err; + +static short fill_mode = FILL_MODE_PAT; +static char fill_pattern[MAX_PATTERN_LEN] = "abacaba"; +static ssize_t pattern_len = 7; +static struct timer_list timer; + +static u8 playback_capture_test; +static u8 ioctl_reset_test; +static struct dentry *driver_debug_dir; + +module_param(index, int, 0444); +MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard"); +module_param(id, charp, 0444); +MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard"); +module_param(enable, bool, 0444); +MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); +module_param(fill_mode, short, 0600); +MODULE_PARM_DESC(fill_mode, "Buffer fill mode: rand(0) or pattern(1)"); +module_param(inject_delay, int, 0600); +MODULE_PARM_DESC(inject_delay, "Inject delays during playback/capture (in jiffies)"); +module_param(inject_hwpars_err, bool, 0600); +MODULE_PARM_DESC(inject_hwpars_err, "Inject EBUSY error in the 'hw_params' callback"); +module_param(inject_prepare_err, bool, 0600); +MODULE_PARM_DESC(inject_prepare_err, "Inject EINVAL error in the 'prepare' callback"); +module_param(inject_trigger_err, bool, 0600); +MODULE_PARM_DESC(inject_trigger_err, "Inject EINVAL error in the 'trigger' callback"); + +struct valsa { + struct snd_pcm_substream *substream; + struct snd_pcm *pcm; + size_t buf_pos; + size_t period_pos; + size_t b_rw; + bool is_buf_corrupted; + size_t period_bytes; + size_t total_bytes; + struct platform_device *pdev; + struct snd_card *card; +}; + +static struct valsa *valsa; + +static struct snd_pcm_hardware snd_valsa_hw = { + .info = (SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = SNDRV_PCM_RATE_8000_48000, + .rate_min = 8000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 2, + .buffer_bytes_max = 32768, + .period_bytes_min = 4096, + .period_bytes_max = 32768, + .periods_min = 1, + .periods_max = 1024, +}; + +static inline void inc_buf_pos(size_t by, size_t bytes) +{ + valsa->total_bytes += by; + valsa->buf_pos += by; + valsa->buf_pos %= bytes; +} + +/* + * Check one block of the buffer. Here we iterate the buffer until we find '0'. This condition is + * necessary because we need to detect when the reading/writing ends, so we assume that the pattern + * doesn't contain zeros. + */ +static void check_buf_block(struct valsa *valsa, struct snd_pcm_runtime *runtime) +{ + size_t i; + u8 current_byte; + + for (i = 0; i < valsa->b_rw; i++) { + current_byte = runtime->dma_area[valsa->buf_pos]; + if (!current_byte) + break; + if (current_byte != fill_pattern[valsa->total_bytes % pattern_len]) { + valsa->is_buf_corrupted = true; + break; + } + inc_buf_pos(1, runtime->dma_bytes); + } + inc_buf_pos(valsa->b_rw - i, runtime->dma_bytes); +} + +static void fill_block_pattern(struct valsa *valsa, struct snd_pcm_runtime *runtime) +{ + size_t i; + + for (i = 0; i < valsa->b_rw; i++) { + runtime->dma_area[valsa->buf_pos] = fill_pattern[valsa->total_bytes % pattern_len]; + inc_buf_pos(1, runtime->dma_bytes); + } +} + +static void fill_block_random(struct valsa *valsa, struct snd_pcm_runtime *runtime) +{ + size_t in_cur_block = runtime->dma_bytes - valsa->buf_pos; + + if (valsa->b_rw <= in_cur_block) { + get_random_bytes(&runtime->dma_area[valsa->buf_pos], valsa->b_rw); + } else { + get_random_bytes(&runtime->dma_area[valsa->buf_pos], in_cur_block); + get_random_bytes(runtime->dma_area, valsa->b_rw - in_cur_block); + } + inc_buf_pos(valsa->b_rw, runtime->dma_bytes); +} + +static void fill_block(struct valsa *valsa, struct snd_pcm_runtime *runtime) +{ + switch (fill_mode) { + case FILL_MODE_RAND: + fill_block_random(valsa, runtime); + break; + case FILL_MODE_PAT: + fill_block_pattern(valsa, runtime); + break; + } +} + +/* + * Here we iterate through the buffer by (buffer_size / iterates_per_second) bytes. + * The driver uses timer to simulate the hardware pointer moving, and notify the PCM middle layer + * about period elapsed. + */ +static void timer_timeout(struct timer_list *data) +{ + struct snd_pcm_runtime *runtime; + + if (!valsa->substream) + return; + runtime = valsa->substream->runtime; + + if (valsa->substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !valsa->is_buf_corrupted) + check_buf_block(valsa, runtime); + else if (valsa->substream->stream == SNDRV_PCM_STREAM_CAPTURE) + fill_block(valsa, runtime); + else + inc_buf_pos(valsa->b_rw, runtime->dma_bytes); + + valsa->period_pos += valsa->b_rw; + if (valsa->period_pos >= valsa->period_bytes) { + valsa->period_pos %= valsa->period_bytes; + snd_pcm_period_elapsed(valsa->substream); + } + + mod_timer(&timer, jiffies + TIMER_INTERVAL + inject_delay); +} + +static int snd_valsa_pcm_open(struct snd_pcm_substream *substream) +{ + struct valsa *valsa = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + + runtime->hw = snd_valsa_hw; + valsa->substream = substream; + valsa->buf_pos = 0; + valsa->is_buf_corrupted = false; + valsa->period_pos = 0; + valsa->total_bytes = 0; + + playback_capture_test = 0; + ioctl_reset_test = 0; + + timer_shutdown_sync(&timer); + timer_setup(&timer, timer_timeout, 0); + mod_timer(&timer, jiffies + TIMER_INTERVAL); + return 0; +} + +static int snd_valsa_pcm_close(struct snd_pcm_substream *substream) +{ + struct valsa *valsa = snd_pcm_substream_chip(substream); + + timer_shutdown_sync(&timer); + valsa->substream = NULL; + playback_capture_test = !valsa->is_buf_corrupted; + return 0; +} + +static int snd_valsa_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + if (inject_trigger_err) + return -EINVAL; + + valsa->period_bytes = frames_to_bytes(runtime, runtime->period_size); + // We want to record RATE samples per sec, it is rate * sample_bytes bytes + valsa->b_rw = runtime->rate * runtime->sample_bits / 8 / TIMER_PER_SEC; + return 0; +} + +static snd_pcm_uframes_t snd_valsa_pcm_pointer(struct snd_pcm_substream *substream) +{ + return bytes_to_frames(substream->runtime, valsa->buf_pos); +} + +static int snd_valsa_free(struct valsa *valsa) +{ + if (!valsa) + return 0; + kfree(valsa); + return 0; +} + +// These callbacks are required, but empty - all freeing occurs in pdev_remove +static int snd_valsa_dev_free(struct snd_device *device) +{ + return 0; +} + +static void valsa_pdev_release(struct device *dev) +{ +} + +static int snd_valsa_pcm_prepare(struct snd_pcm_substream *substream) +{ + if (inject_prepare_err) + return -EINVAL; + return 0; +} + +static int snd_valsa_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + if (inject_hwpars_err) + return -EBUSY; + return 0; +} + +static int snd_valsa_pcm_hw_free(struct snd_pcm_substream *substream) +{ + return 0; +} + +static int snd_valsa_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg) +{ + switch (cmd) { + case SNDRV_PCM_IOCTL1_RESET: + ioctl_reset_test = 1; + break; + } + return snd_pcm_lib_ioctl(substream, cmd, arg); +} + +static const struct snd_pcm_ops snd_valsa_playback_ops = { + .open = snd_valsa_pcm_open, + .close = snd_valsa_pcm_close, + .trigger = snd_valsa_pcm_trigger, + .hw_params = snd_valsa_pcm_hw_params, + .ioctl = snd_valsa_ioctl, + .hw_free = snd_valsa_pcm_hw_free, + .prepare = snd_valsa_pcm_prepare, + .pointer = snd_valsa_pcm_pointer, +}; + +static const struct snd_pcm_ops snd_valsa_capture_ops = { + .open = snd_valsa_pcm_open, + .close = snd_valsa_pcm_close, + .trigger = snd_valsa_pcm_trigger, + .hw_params = snd_valsa_pcm_hw_params, + .hw_free = snd_valsa_pcm_hw_free, + .ioctl = snd_valsa_ioctl, + .prepare = snd_valsa_pcm_prepare, + .pointer = snd_valsa_pcm_pointer, +}; + +static int snd_valsa_new_pcm(struct valsa *valsa) +{ + struct snd_pcm *pcm; + int err; + + err = snd_pcm_new(valsa->card, "VirtualAlsa", 0, 1, 1, &pcm); + if (err < 0) + return err; + pcm->private_data = valsa; + strcpy(pcm->name, "VirtualAlsa"); + valsa->pcm = pcm; + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_valsa_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_valsa_capture_ops); + + err = snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &valsa->pdev->dev, + 64 * 1024, 64 * 1024); + return err; +} + +static int snd_valsa_create(struct snd_card *card, struct platform_device *pdev, + struct valsa **r_valsa) +{ + struct valsa *valsa; + int err; + static const struct snd_device_ops ops = { + .dev_free = snd_valsa_dev_free, + }; + + valsa = kzalloc(sizeof(*valsa), GFP_KERNEL); + if (!valsa) + return -ENOMEM; + valsa->card = card; + valsa->pdev = pdev; + valsa->buf_pos = 0; + valsa->period_pos = 0; + + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, valsa, &ops); + if (err < 0) + goto _err_free_chip; + + err = snd_valsa_new_pcm(valsa); + if (err < 0) + goto _err_free_chip; + + *r_valsa = valsa; + return 0; + +_err_free_chip: + snd_valsa_free(valsa); + return err; +} + +static int valsa_probe(struct platform_device *pdev) +{ + struct snd_card *card; + int err; + + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (err) + return err; + + err = snd_devm_card_new(&pdev->dev, index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; + err = snd_valsa_create(card, pdev, &valsa); + if (err < 0) + return err; + + strcpy(card->driver, "VirtualALSA"); + strcpy(card->shortname, "VirtualALSA"); + strcpy(card->longname, "Virtual ALSA card"); + + err = snd_card_register(card); + if (err < 0) + return err; + + return 0; +} + +static int pdev_remove(struct platform_device *dev) +{ + snd_valsa_free(valsa); + return 0; +} + +static struct platform_device valsa_pdev = { + .name = "valsa", + .dev.release = valsa_pdev_release, +}; + +static struct platform_driver valsa_pdrv = { + .probe = valsa_probe, + .remove = pdev_remove, + .driver = { + .name = "valsa", + }, +}; + +static ssize_t pattern_write(struct file *file, const char __user *buff, size_t len, loff_t *off) +{ + ssize_t to_write = len; + + if (*off + to_write > MAX_PATTERN_LEN) + to_write = MAX_PATTERN_LEN - *off; + + // Crop silently everything over the buffer + if (to_write <= 0) + return len; + + if (copy_from_user(fill_pattern + *off, buff, to_write)) + return -EFAULT; + pattern_len = *off + to_write; + *off += to_write; + + return to_write; +} + +static ssize_t pattern_read(struct file *file, char __user *buff, size_t len, loff_t *off) +{ + ssize_t to_read = len; + + if (*off + to_read >= MAX_PATTERN_LEN) + to_read = MAX_PATTERN_LEN - *off; + if (to_read <= 0) + return 0; + + if (copy_to_user(buff, fill_pattern + *off, to_read)) + to_read = 0; + else + *off += to_read; + + return to_read; +} + +static const struct file_operations fill_pattern_fops = { + .read = pattern_read, + .write = pattern_write, +}; + +static int init_debug_files(void) +{ + driver_debug_dir = debugfs_create_dir("valsa", NULL); + if (IS_ERR(driver_debug_dir)) + return PTR_ERR(driver_debug_dir); + debugfs_create_u8("pc_test", 0444, driver_debug_dir, &playback_capture_test); + debugfs_create_u8("ioctl_test", 0444, driver_debug_dir, &ioctl_reset_test); + debugfs_create_file("fill_pattern", 0600, driver_debug_dir, NULL, &fill_pattern_fops); + + return 0; +} + +static void clear_debug_files(void) +{ + debugfs_remove_recursive(driver_debug_dir); +} + +static int __init mod_init(void) +{ + int err = 0; + + err = init_debug_files(); + if (err) + return err; + err = platform_device_register(&valsa_pdev); + if (err) + return err; + err = platform_driver_register(&valsa_pdrv); + if (err) + platform_device_unregister(&valsa_pdev); + return err; +} + +static void __exit mod_exit(void) +{ + clear_debug_files(); + + platform_driver_unregister(&valsa_pdrv); + platform_device_unregister(&valsa_pdev); +} + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ivan Orlov"); +module_init(mod_init); +module_exit(mod_exit); From patchwork Sat May 13 20:20:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Orlov X-Patchwork-Id: 13241330 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6ECF6C7EE22 for ; Mon, 15 May 2023 12:27:54 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 6BDA683A; Mon, 15 May 2023 14:27:02 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 6BDA683A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1684153672; bh=7T30ksgMN7TtrHdNMdqcNGf4b9CnIptZCewubzbAMro=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=ZKT6wSdCj2A3SCQyd3OlQ6lxUTdfpjiRH3TUUiwKnLVtEDCHpgqU1QdiDdob42pzw 3JIvb6RU8CQZehCSCurzMdpN2uCl9QIskqS0ip64jGUn+w7HB4agaCA8P99aSJ/kvg XlUd+7SoOZ9z578ggq03olbussxdrbENY9TGppRQ= Received: by alsa1.perex.cz (Postfix, from userid 50401) id 01EA1F80578; Mon, 15 May 2023 14:26:11 +0200 (CEST) Received: from mailman-core.alsa-project.org (mailman-core.alsa-project.org [10.254.200.10]) by alsa1.perex.cz (Postfix) with ESMTP id 6A7BAF80568; Mon, 15 May 2023 14:26:11 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 0CCB9F8052E; Sat, 13 May 2023 22:21:36 +0200 (CEST) Received: from mail-ed1-x531.google.com (mail-ed1-x531.google.com [IPv6:2a00:1450:4864:20::531]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id A6921F8032D for ; Sat, 13 May 2023 22:21:22 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz A6921F8032D Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20221208 header.b=jfdhvxTI Received: by mail-ed1-x531.google.com with SMTP id 4fb4d7f45d1cf-50bfd66ba3eso2596381a12.0 for ; Sat, 13 May 2023 13:21:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1684009279; x=1686601279; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=phVfYEyjqUA1/8JzWnwWyJem9HZ6085CTPXJTMUib4g=; b=jfdhvxTIOPKnh+n2ESRxn+iltKq4nh61eRKsxsBV3oW1Ii/X7aBXAv5Nou7cNo3LDK RkQWrcskIMLc2WGI/FXV6llw+fSYLG8RM7SNaurWDObJLBtDDXxaJHfKN/k14P+q0wpT r/R1zhu7SRLCOUKIRIxnvf4WSrTNIEwiGlwlpJnN3XTtUBv87y2s3BfYYYOxyjIO9tCs MJDYr1yzY6cMjC8UXgHF6eC/UOXpuaiXRsfiKCRbj1/Z3s5TV+vNeMW/u1nrNA9I8zOp UrHGgaaaTZOkwa9wtKPliidEM/bI0RQnKBFKIYuLx+/HlLFhzNmVsMa8PGoYxEldKW9c GTrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1684009279; x=1686601279; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=phVfYEyjqUA1/8JzWnwWyJem9HZ6085CTPXJTMUib4g=; b=Idqy/WcNFt4sHEOTiUx3SHeuvA+8vDNuBgOOoGJv+C3ICsjfXfJPEndfoZg6zBS4mu 2Bqpnrgw1vPlOUvV3LYzJGN9HAkaTM6+SQ0t0X9JfvuC2owxK4DexI7atBcAe+wnJG0n v7GSmPNTxggBhNGnd8tlmdQkgxPt4K4GW8SyRo9eqobEl+FLWo61lh6nn1W40WUgUv5x 1p0N318+HFZOXPdI3qWec/kDHNGYreW1J3IbDN75+LynTmXKSnT7zFgSbtN4DgKzg+91 OlDkowsuutyl5LqzzJ8SAuyMdehTcDaQ6nIPkQAP701mMSdXAcVZl6Y+3KuATjpWVmKl WR8A== X-Gm-Message-State: AC+VfDxHJAkIQZw2Fl6uMcoXnYLQEt1666eeSqLHSmSqfW2jJDbqDpza IGjLUDlUxs8HQUYw/Rne5gE= X-Google-Smtp-Source: ACHHUZ6D50diLOr1mJEybUqQgqdZ/OhjmdX7JuUmJJIFtY8WY3xSxqG/VvvFG+eERIrAaYaD9xdCPg== X-Received: by 2002:a05:6402:3482:b0:508:40a5:beb4 with SMTP id v2-20020a056402348200b0050840a5beb4mr28652324edc.3.1684009279137; Sat, 13 May 2023 13:21:19 -0700 (PDT) Received: from ivan-B550MH.. ([37.252.94.55]) by smtp.gmail.com with ESMTPSA id d14-20020a50fb0e000000b0050bc6d0e880sm5109637edq.61.2023.05.13.13.21.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 13 May 2023 13:21:18 -0700 (PDT) From: Ivan Orlov To: corbet@lwn.net, akpm@linux-foundation.org, perex@perex.cz, tiwai@suse.com, broonie@kernel.org, skhan@linuxfoundation.org Cc: Ivan Orlov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, alsa-devel@alsa-project.org, linux-kselftest@vger.kernel.org, gregkh@linuxfoundation.org, himadrispandya@gmail.com, linux-kernel-mentees@lists.linuxfoundation.org Subject: [PATCH 3/3] selftests: ALSA: Add test for the 'valsa' driver Date: Sun, 14 May 2023 00:20:37 +0400 Message-Id: <20230513202037.158777-3-ivan.orlov0322@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230513202037.158777-1-ivan.orlov0322@gmail.com> References: <20230513202037.158777-1-ivan.orlov0322@gmail.com> MIME-Version: 1.0 X-MailFrom: ivan.orlov0322@gmail.com X-Mailman-Rule-Hits: nonmember-moderation X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-alsa-devel.alsa-project.org-0; header-match-alsa-devel.alsa-project.org-1 Message-ID-Hash: 2VSZS75MZ2AD3UXS7XGFW4XRDJ5JF43M X-Message-ID-Hash: 2VSZS75MZ2AD3UXS7XGFW4XRDJ5JF43M X-Mailman-Approved-At: Mon, 15 May 2023 12:26:01 +0000 X-Mailman-Version: 3.3.8 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: This test covers the new Virtual ALSA driver, including the capturing, playback and ioctl redefinition functionalities. This test is also helpful as an usage example of the 'valsa' driver. We have a lot of different virtual media drivers, which can be used for testing of the userspace applications and media subsystem middle layer. However, all of them are aimed at testing the video functionality and simulating the video devices. For audio devices we have only snd-dummy module, which is good in simulating the correct behavior of an ALSA device. I decided to write a tool, which would help to test the userspace ALSA programs (and the PCM middle layer as well) under unusual circumstances to figure out how they would behave. So I came up with this Virtual ALSA Driver. This new Virtual ALSA Driver has several features which can be useful during the userspace ALSA applications testing/fuzzing, or testing/fuzzing of the PCM middle layer. Not all of them can be implemented using the existing virtual drivers (like dummy or loopback). Here is what can this driver do: - Simulate both capture and playback processes - Generate random or pattern-based capture data - Check the playback stream for containing the looped pattern - Inject delays into the playback and capturing processes - Inject errors during the PCM callbacks Also, this driver can check the playback stream for containing the predefined pattern, which is used in the corresponding selftest to check the PCM middle layer data transferring functionality. Additionally, this driver redefines the default RESET ioctl, and the selftest covers this PCM API functionality as well. After all, I think this driver would be a good start, and I believe in the future we will see more virtual sound drivers. Signed-off-by: Ivan Orlov --- tools/testing/selftests/alsa/valsa-test.sh | 55 ++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100755 tools/testing/selftests/alsa/valsa-test.sh diff --git a/tools/testing/selftests/alsa/valsa-test.sh b/tools/testing/selftests/alsa/valsa-test.sh new file mode 100755 index 000000000000..872dfac138c2 --- /dev/null +++ b/tools/testing/selftests/alsa/valsa-test.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Test for the 'valsa' virtual driver. It tests capture and playback functionalities, +# as well as the 'reset' ioctl redefinition. + +uid=$(id -u) +if [ $uid -ne 0 ]; then + echo "$0: Must be run as root" + exit 1 +fi + +if ! which modprobe > /dev/null 2>&1; then + echo "$0: You need modprobe installed" + exit 4 +fi + +if ! modinfo snd-valsa > /dev/null 2>&1; then + echo "$0: You must have the following enabled in your kernel:" + echo "CONFIG_SND_ALSAV=m" + exit 4 +fi + +modprobe snd-valsa + +if [ ! -e /sys/kernel/debug/valsa/pc_test ]; then + mount -t debugfs none /sys/kernel/debug + + if [ ! -e /sys/kernel/debug/valsa/pc_test ]; then + echo "$0: Error mounting debugfs" + exit 4 + fi +fi + +success="1" +arecord -D hw:CARD=valsa,DEV=0 -c 1 --buffer-size=8192 -f S16_LE -r 8000 --duration=4 out.wav + +if [[ $(< /sys/kernel/debug/valsa/ioctl_test) == "$success" ]]; then + echo "$0: ioctl test: success" +else + echo "$0: ioctl test: fail" +fi + +aplay -D hw:CARD=valsa,DEV=0 -c 1 --buffer-size=8192 -f S16_LE -r 8000 out.wav + +if [[ $(< /sys/kernel/debug/valsa/pc_test) == "$success" ]]; then + echo "$0: playback test: success" +else + echo "$0: playback test: fail" +fi + +rm -rf out.wav +if ! rmmod snd-valsa > /dev/null 2>&1; then + echo "$0: Can't remove 'valsa' module: disable PulseAudio and unload it manually" +fi