From bc8c3a602bceaba0e6d34a1ba8b776b56b00d766 Mon Sep 17 00:00:00 2001 From: James O'Shannessy Date: Mon, 27 Aug 2018 15:08:14 +1000 Subject: Public push of AVIRT. Follow readme for building in/out of tree for Ubuntu/AGL/etc. Signed-off-by: James O'Shannessy --- dummy/dummy.c | 278 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 dummy/dummy.c (limited to 'dummy/dummy.c') diff --git a/dummy/dummy.c b/dummy/dummy.c new file mode 100644 index 0000000..7522345 --- /dev/null +++ b/dummy/dummy.c @@ -0,0 +1,278 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * ALSA Virtual Soundcard + * + * dummy_audiopath.c - AVIRT sample Audio Path definition + * + * Copyright (C) 2010-2018 Fiberdyne Systems Pty Ltd + */ + +#include +#include +#include + +MODULE_AUTHOR("JOSHANNE "); +MODULE_AUTHOR("MFARRUGI "); +MODULE_DESCRIPTION("Sample Audio Path Module Interface"); +MODULE_LICENSE("GPL"); + +#define DUMMY_SAMPLE_RATE 48000 +#define DUMMY_BLOCKSIZE 512 +#define DUMMY_PERIODS_MIN 1 +#define DUMMY_PERIODS_MAX 8 + +#define get_dummy_ops(substream) \ + (*(const struct dummy_timer_ops **)(substream)->runtime->private_data) + +static struct avirt_coreinfo *coreinfo; + +/******************************************************************************* + * System Timer Interface + * + * This is used to call the ALSA PCM callbacks required to notify AVIRT of the + * 'periods elapsed', so that buffers can keep getting transmitted here + * + * (Borrowed from the default ALSA 'dummy' driver (sound/driver/dummy.c)) + ******************************************************************************/ +struct dummy_timer_ops { + int (*create)(struct snd_pcm_substream *); + void (*free)(struct snd_pcm_substream *); + int (*prepare)(struct snd_pcm_substream *); + int (*start)(struct snd_pcm_substream *); + int (*stop)(struct snd_pcm_substream *); + snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *); +}; + +struct dummy_systimer_pcm { + /* ops must be the first item */ + const struct dummy_timer_ops *timer_ops; + spinlock_t lock; + struct timer_list timer; + unsigned long base_time; + unsigned int frac_pos; /* fractional sample position (based HZ) */ + unsigned int frac_period_rest; + unsigned int frac_buffer_size; /* buffer_size * HZ */ + unsigned int frac_period_size; /* period_size * HZ */ + unsigned int rate; + int elapsed; + struct snd_pcm_substream *substream; +}; + +static void dummy_systimer_rearm(struct dummy_systimer_pcm *dpcm) +{ + mod_timer(&dpcm->timer, jiffies + (dpcm->frac_period_rest + dpcm->rate - + 1) / dpcm->rate); +} + +static void dummy_systimer_update(struct dummy_systimer_pcm *dpcm) +{ + unsigned long delta; + + delta = jiffies - dpcm->base_time; + if (!delta) + return; + dpcm->base_time += delta; + delta *= dpcm->rate; + dpcm->frac_pos += delta; + while (dpcm->frac_pos >= dpcm->frac_buffer_size) + dpcm->frac_pos -= dpcm->frac_buffer_size; + while (dpcm->frac_period_rest <= delta) { + dpcm->elapsed++; + dpcm->frac_period_rest += dpcm->frac_period_size; + } + dpcm->frac_period_rest -= delta; +} + +static int dummy_systimer_start(struct snd_pcm_substream *substream) +{ + struct dummy_systimer_pcm *dpcm = substream->runtime->private_data; + spin_lock(&dpcm->lock); + dpcm->base_time = jiffies; + dummy_systimer_rearm(dpcm); + spin_unlock(&dpcm->lock); + return 0; +} + +static int dummy_systimer_stop(struct snd_pcm_substream *substream) +{ + struct dummy_systimer_pcm *dpcm = substream->runtime->private_data; + spin_lock(&dpcm->lock); + del_timer(&dpcm->timer); + spin_unlock(&dpcm->lock); + return 0; +} + +static int dummy_systimer_prepare(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct dummy_systimer_pcm *dpcm = runtime->private_data; + + dpcm->frac_pos = 0; + dpcm->rate = runtime->rate; + dpcm->frac_buffer_size = runtime->buffer_size * HZ; + dpcm->frac_period_size = runtime->period_size * HZ; + dpcm->frac_period_rest = dpcm->frac_period_size; + dpcm->elapsed = 0; + + return 0; +} + +static void dummy_systimer_callback(struct timer_list *t) +{ + struct dummy_systimer_pcm *dpcm = from_timer(dpcm, t, timer); + unsigned long flags; + int elapsed = 0; + + spin_lock_irqsave(&dpcm->lock, flags); + dummy_systimer_update(dpcm); + dummy_systimer_rearm(dpcm); + elapsed = dpcm->elapsed; + dpcm->elapsed = 0; + spin_unlock_irqrestore(&dpcm->lock, flags); + if (elapsed) + coreinfo->pcm_buff_complete(dpcm->substream); +} + +static snd_pcm_uframes_t + dummy_systimer_pointer(struct snd_pcm_substream *substream) +{ + struct dummy_systimer_pcm *dpcm = substream->runtime->private_data; + snd_pcm_uframes_t pos; + + spin_lock(&dpcm->lock); + dummy_systimer_update(dpcm); + pos = dpcm->frac_pos / HZ; + spin_unlock(&dpcm->lock); + return pos; +} + +static int dummy_systimer_create(struct snd_pcm_substream *substream) +{ + struct dummy_systimer_pcm *dpcm; + + dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); + if (!dpcm) + return -ENOMEM; + substream->runtime->private_data = dpcm; + timer_setup(&dpcm->timer, dummy_systimer_callback, 0); + spin_lock_init(&dpcm->lock); + dpcm->substream = substream; + return 0; +} + +static void dummy_systimer_free(struct snd_pcm_substream *substream) +{ + kfree(substream->runtime->private_data); +} + +static const struct dummy_timer_ops dummy_systimer_ops = { + .create = dummy_systimer_create, + .free = dummy_systimer_free, + .prepare = dummy_systimer_prepare, + .start = dummy_systimer_start, + .stop = dummy_systimer_stop, + .pointer = dummy_systimer_pointer, +}; + +/******************************************************************************* + * Audio Path ALSA PCM Callbacks + ******************************************************************************/ +static int dummy_pcm_open(struct snd_pcm_substream *substream) +{ + const struct dummy_timer_ops *ops; + int err; + + ops = &dummy_systimer_ops; + err = ops->create(substream); + if (err < 0) + return err; + get_dummy_ops(substream) = ops; + + return 0; +} + +static int dummy_pcm_close(struct snd_pcm_substream *substream) +{ + get_dummy_ops(substream)->free(substream); + return 0; +} + +static snd_pcm_uframes_t dummy_pcm_pointer(struct snd_pcm_substream *substream) +{ + return get_dummy_ops(substream)->pointer(substream); +} + +static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + return get_dummy_ops(substream)->start(substream); + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + return get_dummy_ops(substream)->stop(substream); + } + return -EINVAL; +} + +static int dummy_pcm_prepare(struct snd_pcm_substream *substream) +{ + return get_dummy_ops(substream)->prepare(substream); +} + +static struct snd_pcm_ops dummyap_pcm_ops = { + .open = dummy_pcm_open, + .close = dummy_pcm_close, + .prepare = dummy_pcm_prepare, + .pointer = dummy_pcm_pointer, + .trigger = dummy_pcm_trigger, +}; + +/******************************************************************************* + * Dummy Audio Path AVIRT registration + ******************************************************************************/ +static struct snd_pcm_hardware dummyap_hw = { + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .info = (SNDRV_PCM_INFO_INTERLEAVED // Channel interleaved audio + | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID), + .rates = SNDRV_PCM_RATE_48000, + .rate_min = DUMMY_SAMPLE_RATE, + .rate_max = DUMMY_SAMPLE_RATE, + .periods_min = DUMMY_PERIODS_MIN, + .periods_max = DUMMY_PERIODS_MAX, +}; + +static struct avirt_audiopath dummyap_module = { + .name = "Dummy Audio Path", + .version = { 0, 0, 1 }, + .value = 10, + .hw = &dummyap_hw, + .pcm_ops = &dummyap_pcm_ops, + .blocksize = DUMMY_BLOCKSIZE, +}; + +static int __init dummy_init(void) +{ + int err = 0; + + pr_info("init()\n"); + + err = avirt_register_audiopath(&dummyap_module, &coreinfo); + if ((err < 0) || (!coreinfo)) { + pr_err("%s: coreinfo is NULL!\n", __func__); + return err; + } + + return err; +} + +static void __exit dummy_exit(void) +{ + pr_info("exit()\n"); + + avirt_deregister_audiopath(&dummyap_module); +} + +module_init(dummy_init); +module_exit(dummy_exit); -- cgit 1.2.3-korg From 82a633ffac43f3849c211f13e369236e7e1ab4c6 Mon Sep 17 00:00:00 2001 From: Mark Farrugia Date: Mon, 27 Aug 2018 17:35:18 +1000 Subject: Update licensing Signed-off-by: Mark Farrugia --- LICENSE | 481 ++++++++++++++++++++++++++++++++++------------------------ alsa-pcm.c | 2 +- alsa.c | 2 +- alsa.h | 2 +- core.c | 2 +- core.h | 2 +- dummy/dummy.c | 4 +- 7 files changed, 287 insertions(+), 208 deletions(-) (limited to 'dummy/dummy.c') diff --git a/LICENSE b/LICENSE index e147c80..d8cf7d4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,201 +1,280 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2018 JOSHANNE - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/alsa-pcm.c b/alsa-pcm.c index bd705f4..efe64f2 100644 --- a/alsa-pcm.c +++ b/alsa-pcm.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: GPL-2.0 /* * ALSA Virtual Soundcard * diff --git a/alsa.c b/alsa.c index 0b08744..e283794 100755 --- a/alsa.c +++ b/alsa.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: GPL-2.0 /* * ALSA Virtual Soundcard * diff --git a/alsa.h b/alsa.h index 29fc64d..113b575 100755 --- a/alsa.h +++ b/alsa.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: GPL-2.0 /* * ALSA Virtual Soundcard * diff --git a/core.c b/core.c index d0a24ec..875e844 100644 --- a/core.c +++ b/core.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: GPL-2.0 /* * ALSA Virtual Soundcard * diff --git a/core.h b/core.h index 5eb6026..1cf7c95 100644 --- a/core.h +++ b/core.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: GPL-2.0 /* * ALSA Virtual Soundcard * diff --git a/dummy/dummy.c b/dummy/dummy.c index 7522345..cd5295f 100644 --- a/dummy/dummy.c +++ b/dummy/dummy.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: GPL-2.0 /* * ALSA Virtual Soundcard * @@ -14,7 +14,7 @@ MODULE_AUTHOR("JOSHANNE "); MODULE_AUTHOR("MFARRUGI "); MODULE_DESCRIPTION("Sample Audio Path Module Interface"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); #define DUMMY_SAMPLE_RATE 48000 #define DUMMY_BLOCKSIZE 512 -- cgit 1.2.3-korg From f7f995a28c82c126619858ed40b92b5f33ddf2fe Mon Sep 17 00:00:00 2001 From: Mark Farrugia Date: Mon, 3 Sep 2018 15:18:18 +1000 Subject: Remove test 'value' parameter from avirt_audiopath This is not required any longer Signed-off-by: Mark Farrugia --- core.h | 1 - dummy/dummy.c | 1 - 2 files changed, 2 deletions(-) (limited to 'dummy/dummy.c') diff --git a/core.h b/core.h index 7a562f4..a31c916 100644 --- a/core.h +++ b/core.h @@ -34,7 +34,6 @@ typedef int (*avirt_buff_complete)(struct snd_pcm_substream *substream); struct avirt_audiopath { const char *name; unsigned version[3]; - int value; struct snd_pcm_hardware *hw; struct snd_pcm_ops *pcm_ops; unsigned blocksize; diff --git a/dummy/dummy.c b/dummy/dummy.c index cd5295f..54d4dcc 100644 --- a/dummy/dummy.c +++ b/dummy/dummy.c @@ -246,7 +246,6 @@ static struct snd_pcm_hardware dummyap_hw = { static struct avirt_audiopath dummyap_module = { .name = "Dummy Audio Path", .version = { 0, 0, 1 }, - .value = 10, .hw = &dummyap_hw, .pcm_ops = &dummyap_pcm_ops, .blocksize = DUMMY_BLOCKSIZE, -- cgit 1.2.3-korg From 3786b607d4dd5e738cbe491dbfb03c2283e74358 Mon Sep 17 00:00:00 2001 From: Mark Farrugia Date: Thu, 20 Sep 2018 12:09:20 +1000 Subject: Add 'uid' field to AP, store AP in PCM private data, fix helper macros We want to use a UID when registering APs, that must start with "ap_", and acts as a unique identifier for each AP. To move forward with the adoption of routing PCMs to differing APs, we now store the AP in the PCM private data - set at pcm_open. A fix to the helper macros now allows additional args to be passed in for inclusion to the debug string Signed-off-by: Mark Farrugia --- alsa-pcm.c | 53 ++++++++++++++++++++++++++++------------------------- alsa.c | 1 - alsa.h | 20 ++++++++++++-------- core.c | 33 +++++++++++++++++++-------------- core.h | 27 +++++++++++++++++++-------- dummy/dummy.c | 1 + 6 files changed, 79 insertions(+), 56 deletions(-) (limited to 'dummy/dummy.c') diff --git a/alsa-pcm.c b/alsa-pcm.c index 9b55a14..ac9175b 100644 --- a/alsa-pcm.c +++ b/alsa-pcm.c @@ -9,13 +9,8 @@ #include "alsa.h" -#define AP_LOGNAME "CORE" - -#define DO_AUDIOPATH_CB(callback, substream, ...) \ +#define DO_AUDIOPATH_CB(ap, callback, substream, ...) \ do { \ - struct avirt_audiopath *ap; \ - ap = avirt_get_current_audiopath(); \ - CHK_NULL_V(ap, "Cannot find Audio Path!"); \ if (ap->pcm_ops->callback) { \ return ap->pcm_ops->callback((substream), \ ##__VA_ARGS__); \ @@ -42,8 +37,10 @@ static int pcm_open(struct snd_pcm_substream *substream) struct snd_pcm_hardware *hw; unsigned int bytes_per_sample = 0, blocksize = 0; - audiopath = avirt_get_current_audiopath(); - CHK_NULL_V(audiopath, "Cannot find Audio Path!"); + char *uid = "ap_dummy"; // TD MF: Make this dynamic! + audiopath = avirt_get_audiopath(uid); + CHK_NULL_V(audiopath, "Cannot find Audio Path uid: '%s'!", uid); + substream->private_data = audiopath; blocksize = audiopath->blocksize; @@ -82,7 +79,7 @@ static int pcm_open(struct snd_pcm_substream *substream) hw->period_bytes_max = blocksize * bytes_per_sample * config->channels; // Do additional Audio Path 'open' callback - DO_AUDIOPATH_CB(open, substream); + DO_AUDIOPATH_CB(audiopath, open, substream); return 0; } @@ -99,7 +96,8 @@ static int pcm_close(struct snd_pcm_substream *substream) { DINFO(AP_LOGNAME, ""); // Do additional Audio Path 'close' callback - DO_AUDIOPATH_CB(close, substream); + DO_AUDIOPATH_CB(((struct avirt_audiopath *)substream->private_data), + close, substream); return 0; } @@ -133,9 +131,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - audiopath = avirt_get_current_audiopath(); - CHK_NULL_V(audiopath, "Cannot find Audio Path!"); - + audiopath = ((struct avirt_audiopath *)substream->private_data); bufsz = params_buffer_bytes(hw_params) * audiopath->hw->periods_max; err = snd_pcm_lib_alloc_vmalloc_buffer(substream, bufsz); @@ -183,7 +179,8 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) static int pcm_prepare(struct snd_pcm_substream *substream) { // Do additional Audio Path 'prepare' callback - DO_AUDIOPATH_CB(prepare, substream); + DO_AUDIOPATH_CB(((struct avirt_audiopath *)substream->private_data), + prepare, substream); return 0; } @@ -212,7 +209,8 @@ static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) } // Do additional Audio Path 'trigger' callback - DO_AUDIOPATH_CB(trigger, substream, cmd); + DO_AUDIOPATH_CB(((struct avirt_audiopath *)substream->private_data), + trigger, substream, cmd); return 0; } @@ -230,7 +228,8 @@ static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream) { // Do additional Audio Path 'pointer' callback - DO_AUDIOPATH_CB(pointer, substream); + DO_AUDIOPATH_CB(((struct avirt_audiopath *)substream->private_data), + pointer, substream); return 0; } @@ -258,7 +257,8 @@ static int pcm_get_time_info( group = avirt_alsa_get_group(substream->stream); CHK_NULL(group); - DO_AUDIOPATH_CB(get_time_info, substream, system_ts, audio_ts, + DO_AUDIOPATH_CB(((struct avirt_audiopath *)substream->private_data), + get_time_info, substream, system_ts, audio_ts, audio_tstamp_config, audio_tstamp_report); return 0; @@ -288,8 +288,8 @@ static int pcm_copy_user(struct snd_pcm_substream *substream, int channel, //offset = frames_to_bytes(runtime, pos); // Do additional Audio Path 'copy_user' callback - DINFO(AP_LOGNAME, ""); - DO_AUDIOPATH_CB(copy_user, substream, channel, pos, src, count); + DO_AUDIOPATH_CB(((struct avirt_audiopath *)substream->private_data), + copy_user, substream, channel, pos, src, count); return 0; } @@ -310,8 +310,9 @@ static int pcm_copy_user(struct snd_pcm_substream *substream, int channel, static int pcm_copy_kernel(struct snd_pcm_substream *substream, int channel, unsigned long pos, void *buf, unsigned long count) { - DINFO(AP_LOGNAME, ""); - DO_AUDIOPATH_CB(copy_kernel, substream, channel, pos, buf, count); + DO_AUDIOPATH_CB(((struct avirt_audiopath *)substream->private_data), + copy_kernel, substream, channel, pos, buf, count); + return 0; } @@ -326,16 +327,18 @@ static int pcm_copy_kernel(struct snd_pcm_substream *substream, int channel, */ int pcm_ack(struct snd_pcm_substream *substream) { - DINFO(AP_LOGNAME, ""); - DO_AUDIOPATH_CB(ack, substream); + DO_AUDIOPATH_CB(((struct avirt_audiopath *)substream->private_data), + ack, substream); + return 0; } static int pcm_silence(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count) { - DINFO(AP_LOGNAME, ""); - DO_AUDIOPATH_CB(fill_silence, substream, channel, pos, count); + DO_AUDIOPATH_CB(((struct avirt_audiopath *)substream->private_data), + fill_silence, substream, channel, pos, count); + return 0; } diff --git a/alsa.c b/alsa.c index a899bb1..fdbe6b0 100755 --- a/alsa.c +++ b/alsa.c @@ -7,7 +7,6 @@ * Copyright (C) 2010-2018 Fiberdyne Systems Pty Ltd */ -#include #include #include diff --git a/alsa.h b/alsa.h index 12148b9..c22a93c 100755 --- a/alsa.h +++ b/alsa.h @@ -13,10 +13,11 @@ #include "core.h" #include +#include #include -#define PRINT_ERR(errno, errmsg, ...) \ - pr_err("[%s()] %s [ERRNO:%d]", __func__, errmsg, ##__VA_ARGS__, errno); +#define PRINT_ERR(errno, errmsg) \ + pr_err("[%s]:[ERRNO:%d]: %s ", __func__, errno, (errmsg)); #define CHK_ERR(errno) \ do { \ @@ -38,12 +39,15 @@ return -EFAULT; \ } while (0) -#define CHK_NULL_V(x, errmsg, ...) \ - do { \ - if (!(x)) { \ - PRINT_ERR(EFAULT, (errmsg), ##__VA_ARGS__) \ - return -EFAULT; \ - } \ +#define CHK_NULL_V(x, errmsg, ...) \ + do { \ + if (!(x)) { \ + char *errmsg_done = \ + kasprintf(GFP_KERNEL, errmsg, ##__VA_ARGS__); \ + PRINT_ERR(EFAULT, errmsg_done); \ + kfree(errmsg_done); \ + return -EFAULT; \ + } \ } while (0) extern struct avirt_coreinfo coreinfo; diff --git a/core.c b/core.c index e77dfb9..360f174 100644 --- a/core.c +++ b/core.c @@ -8,7 +8,6 @@ */ #include -#include #include #include "avirt/core.h" @@ -279,13 +278,13 @@ static struct kobj_type avirt_audiopath_ktype = { /** * create_avirt_audiopath_obj - creates an Audio Path object - * @name: name of the Audio Path + * @uid: Unique ID of the Audio Path * * This creates an Audio Path object and assigns the kset and registers * it with sysfs. * @return: Pointer to the Audio Path object or NULL if it failed. */ -static struct avirt_audiopath_obj *create_avirt_audiopath_obj(const char *name) +static struct avirt_audiopath_obj *create_avirt_audiopath_obj(const char *uid) { struct avirt_audiopath_obj *avirt_audiopath; int retval; @@ -295,7 +294,7 @@ static struct avirt_audiopath_obj *create_avirt_audiopath_obj(const char *name) return NULL; avirt_audiopath->kobj.kset = avirt_audiopath_kset; retval = kobject_init_and_add(&avirt_audiopath->kobj, - &avirt_audiopath_ktype, kobj, "%s", name); + &avirt_audiopath_ktype, kobj, "%s", uid); if (retval) { kobject_put(&avirt_audiopath->kobj); return NULL; @@ -314,14 +313,20 @@ static void destroy_avirt_audiopath_obj(struct avirt_audiopath_obj *p) } /** - * avirt_get_current_audiopath - retrieves the current Audio Path - * @return: Current Audio Path + * avirt_get_audiopath - retrieves the Audio Path by its UID + * @uid: Unique ID for the Audio Path + * @return: Corresponding Audio Path */ -struct avirt_audiopath *avirt_get_current_audiopath(void) +struct avirt_audiopath *avirt_get_audiopath(const char *uid) { - struct avirt_audiopath_obj *ap_obj = list_entry( - audiopath_list.next, struct avirt_audiopath_obj, list); - return ap_obj->path; + struct avirt_audiopath_obj *ap_obj; + list_for_each_entry (ap_obj, &audiopath_list, list) { + pr_info("get_ap %s\n", ap_obj->path->uid); + if (!strcmp(ap_obj->path->uid, uid)) + return ap_obj->path; + } + + return NULL; } /** @@ -340,7 +345,7 @@ int avirt_register_audiopath(struct avirt_audiopath *audiopath, return -EINVAL; } - audiopath_obj = create_avirt_audiopath_obj(audiopath->name); + audiopath_obj = create_avirt_audiopath_obj(audiopath->uid); if (!audiopath_obj) { pr_info("failed to alloc driver object\n"); return -ENOMEM; @@ -348,8 +353,8 @@ int avirt_register_audiopath(struct avirt_audiopath *audiopath, audiopath_obj->path = audiopath; audiopath->context = audiopath_obj; - D_INFOK("Registered new Audio Path: %s", audiopath->name); - D_INFOK("\tBlocksize: %d, Periods: %d", audiopath->blocksize, + pr_info("Registered new Audio Path: %s\n", audiopath->uid); + pr_info("\tBlocksize: %d, Periods: %d\n", audiopath->blocksize, audiopath->hw->periods_max); list_add_tail(&audiopath_obj->list, &audiopath_list); @@ -382,7 +387,7 @@ int avirt_deregister_audiopath(struct avirt_audiopath *audiopath) list_del(&audiopath_obj->list); destroy_avirt_audiopath_obj(audiopath_obj); - pr_info("Deregistered Audio Path %s\n", audiopath->name); + pr_info("Deregistered Audio Path %s\n", audiopath->uid); return 0; } diff --git a/core.h b/core.h index fb64030..98d1bbd 100644 --- a/core.h +++ b/core.h @@ -26,11 +26,12 @@ typedef int (*avirt_buff_complete)(struct snd_pcm_substream *substream); * AVIRT Audio Path info */ struct avirt_audiopath { - const char *name; - unsigned int version[3]; - struct snd_pcm_hardware *hw; - struct snd_pcm_ops *pcm_ops; - unsigned int blocksize; + const char *uid; /* Unique identifier */ + const char *name; /* Pretty name */ + unsigned int version[3]; /* Version - Major.Minor.Ext */ + struct snd_pcm_hardware *hw; /* ALSA PCM HW conf */ + struct snd_pcm_ops *pcm_ops; /* ALSA PCM op table */ + unsigned int blocksize; /* Audio frame size accepted */ void *context; }; @@ -80,9 +81,19 @@ int avirt_register_audiopath(struct avirt_audiopath *audiopath, int avirt_deregister_audiopath(struct avirt_audiopath *audiopath); /** - * avirt_get_current_audiopath - retrieves the current Audio Path - * @return: Current Audio Path + * avirt_get_audiopath - retrieves the Audio Path by it's UID + * @uid: Unique ID for the Audio Path + * @return: Corresponding Audio Path + */ +struct avirt_audiopath *avirt_get_audiopath(const char *uid); + +/** + * avirt_subscribe_stream - subscribe the Audio Path to the given streams + * @audiopath: Audio Path to subscribe for + * @streams: The streams to subscribe the Audio Path to + * return: 0 on success or error code otherwise */ -struct avirt_audiopath *avirt_get_current_audiopath(void); +int avirt_subscribe_stream(struct avirt_audiopath *audiopath, + const char **streams); #endif // __AVIRT_CORE_H__ diff --git a/dummy/dummy.c b/dummy/dummy.c index 54d4dcc..fa9dd41 100644 --- a/dummy/dummy.c +++ b/dummy/dummy.c @@ -244,6 +244,7 @@ static struct snd_pcm_hardware dummyap_hw = { }; static struct avirt_audiopath dummyap_module = { + .uid = "ap_dummy", .name = "Dummy Audio Path", .version = { 0, 0, 1 }, .hw = &dummyap_hw, -- cgit 1.2.3-korg From d20d3b185bd84889a1e54b755a8198200c31bc7d Mon Sep 17 00:00:00 2001 From: Mark Farrugia Date: Fri, 21 Sep 2018 17:25:31 +1000 Subject: Refactor top-level AVIRT API to be avirt__ This makes for a more organized function/variable naming convention Signed-off-by: Mark Farrugia --- alsa-pcm.c | 2 +- core.c | 16 ++++++++-------- core.h | 12 ++++++------ dummy/dummy.c | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) (limited to 'dummy/dummy.c') diff --git a/alsa-pcm.c b/alsa-pcm.c index d65809c..798f76c 100644 --- a/alsa-pcm.c +++ b/alsa-pcm.c @@ -68,7 +68,7 @@ static int pcm_open(struct snd_pcm_substream *substream) unsigned int bytes_per_sample = 0, blocksize = 0, chans = 0; char *uid = "ap_fddsp"; // TD MF: Make this dynamic! - audiopath = avirt_get_audiopath(uid); + audiopath = avirt_audiopath_get(uid); CHK_NULL_V(audiopath, "Cannot find Audio Path uid: '%s'!", uid); substream->private_data = audiopath; diff --git a/core.c b/core.c index c9e8d25..e1afce8 100644 --- a/core.c +++ b/core.c @@ -343,11 +343,11 @@ static void destroy_avirt_audiopath_obj(struct avirt_audiopath_obj *p) } /** - * avirt_get_audiopath - retrieves the Audio Path by its UID + * avirt_audiopath_get - retrieves the Audio Path by its UID * @uid: Unique ID for the Audio Path * @return: Corresponding Audio Path */ -struct avirt_audiopath *avirt_get_audiopath(const char *uid) +struct avirt_audiopath *avirt_audiopath_get(const char *uid) { struct avirt_audiopath_obj *ap_obj; list_for_each_entry (ap_obj, &audiopath_list, list) { @@ -360,12 +360,12 @@ struct avirt_audiopath *avirt_get_audiopath(const char *uid) } /** - * avirt_register_audiopath - register Audio Path with ALSA virtual driver + * avirt_audiopath_register - register Audio Path with ALSA virtual driver * @audiopath: Audio Path to be registered * @core: ALSA virtual driver core info * @return: 0 on success or error code otherwise */ -int avirt_register_audiopath(struct avirt_audiopath *audiopath, +int avirt_audiopath_register(struct avirt_audiopath *audiopath, struct avirt_coreinfo **info) { struct avirt_audiopath_obj *audiopath_obj; @@ -392,14 +392,14 @@ int avirt_register_audiopath(struct avirt_audiopath *audiopath, return 0; } -EXPORT_SYMBOL_GPL(avirt_register_audiopath); +EXPORT_SYMBOL_GPL(avirt_audiopath_register); /** - * avirt_deregister_audiopath - deregister Audio Path with ALSA virtual driver + * avirt_audiopath_deregister - deregister Audio Path with ALSA virtual driver * @audiopath: Audio Path to be deregistered * @return: 0 on success or error code otherwise */ -int avirt_deregister_audiopath(struct avirt_audiopath *audiopath) +int avirt_audiopath_deregister(struct avirt_audiopath *audiopath) { struct avirt_audiopath_obj *audiopath_obj; @@ -421,7 +421,7 @@ int avirt_deregister_audiopath(struct avirt_audiopath *audiopath) return 0; } -EXPORT_SYMBOL_GPL(avirt_deregister_audiopath); +EXPORT_SYMBOL_GPL(avirt_audiopath_deregister); /** * avirt_unregister_all - Unregister the platform device driver diff --git a/core.h b/core.h index 4a0157a..c11ee1d 100644 --- a/core.h +++ b/core.h @@ -67,27 +67,27 @@ struct avirt_coreinfo { }; /** - * avirt_register_audiopath - register Audio Path with ALSA virtual driver + * avirt_audiopath_register - register Audio Path with ALSA virtual driver * @audiopath: Audio Path to be registered * @core: ALSA virtual driver core info * @return: 0 on success or error code otherwise */ -int avirt_register_audiopath(struct avirt_audiopath *audiopath, +int avirt_audiopath_register(struct avirt_audiopath *audiopath, struct avirt_coreinfo **coreinfo); /** - * avirt_deregister_audiopath - deregister Audio Path with ALSA virtual driver + * avirt_audiopath_deregister - deregister Audio Path with ALSA virtual driver * @audiopath: Audio Path to be deregistered * @return: 0 on success or error code otherwise */ -int avirt_deregister_audiopath(struct avirt_audiopath *audiopath); +int avirt_audiopath_deregister(struct avirt_audiopath *audiopath); /** - * avirt_get_audiopath - retrieves the Audio Path by it's UID + * avirt_audiopath_get - retrieves the Audio Path by it's UID * @uid: Unique ID for the Audio Path * @return: Corresponding Audio Path */ -struct avirt_audiopath *avirt_get_audiopath(const char *uid); +struct avirt_audiopath *avirt_audiopath_get(const char *uid); /** * avirt_subscribe_stream - subscribe the Audio Path to the given streams diff --git a/dummy/dummy.c b/dummy/dummy.c index fa9dd41..d619786 100644 --- a/dummy/dummy.c +++ b/dummy/dummy.c @@ -258,7 +258,7 @@ static int __init dummy_init(void) pr_info("init()\n"); - err = avirt_register_audiopath(&dummyap_module, &coreinfo); + err = avirt_audiopath_register(&dummyap_module, &coreinfo); if ((err < 0) || (!coreinfo)) { pr_err("%s: coreinfo is NULL!\n", __func__); return err; @@ -271,7 +271,7 @@ static void __exit dummy_exit(void) { pr_info("exit()\n"); - avirt_deregister_audiopath(&dummyap_module); + avirt_audiopath_deregister(&dummyap_module); } module_init(dummy_init); -- cgit 1.2.3-korg From 3247d61d378afd8fc76f1e9182e5691bd538ab3f Mon Sep 17 00:00:00 2001 From: Mark Farrugia Date: Mon, 1 Oct 2018 17:43:39 +1000 Subject: Add configfs interface, revamp stream grouping Add additional callbacks for audio path configuring, after card has been sealed. Signed-off-by: Mark Farrugia --- Makefile | 1 + alsa-pcm.c | 82 +++++-------- alsa-pcm.h | 28 ----- configfs.c | 229 ++++++++++++++++++++++++++++++++++++ core.c | 354 ++++++++++++++++++++++++-------------------------------- core.h | 76 ++++++------ core_internal.h | 50 ++++++++ dummy/dummy.c | 22 +++- utils.h | 50 ++++---- 9 files changed, 548 insertions(+), 344 deletions(-) delete mode 100755 alsa-pcm.h create mode 100644 configfs.c create mode 100644 core_internal.h (limited to 'dummy/dummy.c') diff --git a/Makefile b/Makefile index af92bc5..44874ca 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_AVIRT) += avirt_core.o avirt_core-y := core.o avirt_core-y += alsa-pcm.o +avirt_core-y += configfs.o ifeq ($(CONFIG_AVIRT_BUILDLOCAL),) CCFLAGS_AVIRT := "drivers/staging/" diff --git a/alsa-pcm.c b/alsa-pcm.c index 21287ee..5a30aff 100644 --- a/alsa-pcm.c +++ b/alsa-pcm.c @@ -7,46 +7,30 @@ * Copyright (C) 2010-2018 Fiberdyne Systems Pty Ltd */ -#include "alsa-pcm.h" -#include "utils.h" - -#define DO_AUDIOPATH_CB(ap, callback, substream, ...) \ - do { \ - if (ap->pcm_ops->callback) { \ - return ap->pcm_ops->callback((substream), \ - ##__VA_ARGS__); \ - } \ +#include "core_internal.h" + +#define DO_AUDIOPATH_CB(ap, callback, substream, ...) \ + do { \ + if ((ap)->pcm_ops->callback) { \ + return (ap)->pcm_ops->callback((substream), \ + ##__VA_ARGS__); \ + } \ } while (0) /** - * pcm_buff_complete_cb - PCM buffer complete callback + * avirt_pcm_period_elapsed - PCM buffer complete callback * @substreamid: pointer to ALSA PCM substream - * @return 0 on success or error code otherwise * * This should be called from a child Audio Path once it has finished processing * the pcm buffer */ -int pcm_buff_complete_cb(struct snd_pcm_substream *substream) +void avirt_pcm_period_elapsed(struct snd_pcm_substream *substream) { // Notify ALSA middle layer of the elapsed period boundary snd_pcm_period_elapsed(substream); - - return 0; } +EXPORT_SYMBOL_GPL(avirt_pcm_period_elapsed); -static struct avirt_stream_group *avirt_stream_get_group(int direction) -{ - switch (direction) { - case SNDRV_PCM_STREAM_PLAYBACK: - return &coreinfo.playback; - case SNDRV_PCM_STREAM_CAPTURE: - return &coreinfo.capture; - default: - pr_err("[%s] Direction must be SNDRV_PCM_STREAM_XXX!", - __func__); - return NULL; - } -} /******************************************************************************* * ALSA PCM Callbacks @@ -63,13 +47,14 @@ static struct avirt_stream_group *avirt_stream_get_group(int direction) static int pcm_open(struct snd_pcm_substream *substream) { struct avirt_audiopath *audiopath; - struct avirt_stream_group *group; + struct avirt_stream *stream; struct snd_pcm_hardware *hw; unsigned int bytes_per_sample = 0, blocksize = 0, chans = 0; char *uid = "ap_fddsp"; // TD MF: Make this dynamic! audiopath = avirt_audiopath_get(uid); - CHK_NULL_V(audiopath, "Cannot find Audio Path uid: '%s'!", uid); + CHK_NULL_V(audiopath, -EFAULT, "Cannot find Audio Path uid: '%s'!", + uid); substream->private_data = audiopath; blocksize = audiopath->blocksize; @@ -87,20 +72,12 @@ static int pcm_open(struct snd_pcm_substream *substream) return -EINVAL; } - // Get device group (playback/capture) - group = avirt_stream_get_group(substream->stream); - CHK_NULL(group); - - // Check if substream id is valid - pr_info("%d substream is < %d", substream->pcm->device, group->devices); - if (substream->pcm->device >= group->devices) { - pr_err("%s %d substream id is invalid expecting %d", __func__, - substream->pcm->device, group->devices); - return -1; - } + stream = __avirt_stream_find_by_device(substream->pcm->device); + if (IS_ERR_VALUE(stream) || !stream) + return PTR_ERR(stream); // Setup remaining hw properties - chans = group->streams[substream->pcm->device].channels; + chans = stream->channels; hw->channels_min = chans; hw->channels_max = chans; hw->buffer_bytes_max = @@ -145,18 +122,17 @@ static int pcm_close(struct snd_pcm_substream *substream) static int pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { - int channels, err; + int err; size_t bufsz; struct avirt_audiopath *audiopath; - struct avirt_stream_group *group; - - group = avirt_stream_get_group(substream->stream); - CHK_NULL(group); + struct avirt_stream *stream; - channels = group->streams[substream->pcm->device].channels; + stream = __avirt_stream_find_by_device(substream->pcm->device); + if (IS_ERR_VALUE(stream) || !stream) + return PTR_ERR(stream); - if ((params_channels(hw_params) > channels) || - (params_channels(hw_params) < channels)) { + if ((params_channels(hw_params) > stream->channels) + || (params_channels(hw_params) < stream->channels)) { pr_err("Requested number of channels not supported.\n"); return -EINVAL; } @@ -306,11 +282,11 @@ static int pcm_copy_user(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count) { - //struct snd_pcm_runtime *runtime; - //int offset; + // struct snd_pcm_runtime *runtime; + // int offset; - //runtime = substream->runtime; - //offset = frames_to_bytes(runtime, pos); + // runtime = substream->runtime; + // offset = frames_to_bytes(runtime, pos); // Do additional Audio Path 'copy_user' callback DO_AUDIOPATH_CB(((struct avirt_audiopath *)substream->private_data), diff --git a/alsa-pcm.h b/alsa-pcm.h deleted file mode 100755 index c45e2a7..0000000 --- a/alsa-pcm.h +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * ALSA Virtual Soundcard - * - * alsa-pcm.h - AVIRT ALSA PCM interface - * - * Copyright (C) 2010-2018 Fiberdyne Systems Pty Ltd - */ - -#ifndef __AVIRT_ALSA_PCM_H__ -#define __AVIRT_ALSA_PCM_H__ - -#include "core.h" - -extern struct avirt_coreinfo coreinfo; -extern struct snd_pcm_ops pcm_ops; - -/** - * pcm_buff_complete_cb - PCM buffer complete callback - * @substream: pointer to ALSA PCM substream - * @return 0 on success or error code otherwise - * - * This should be called from a child Audio Path once it has finished processing - * the PCM buffer - */ -int pcm_buff_complete_cb(struct snd_pcm_substream *substream); - -#endif // __AVIRT_ALSA_PCM_H__ diff --git a/configfs.c b/configfs.c new file mode 100644 index 0000000..dd7b7df --- /dev/null +++ b/configfs.c @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ALSA Virtual Soundcard + * + * configfs.c - configfs for virtual ALSA card + * + * Copyright (C) 2010-2018 Fiberdyne Systems Pty Ltd + */ + +#include +#include "core_internal.h" + +static bool streams_sealed = false; + +static ssize_t cfg_avirt_stream_direction_show(struct config_item *item, + char *page) +{ + ssize_t count; + struct avirt_stream *stream = avirt_stream_from_config_item(item); + + count = sprintf(page, "%d\n", stream->direction); + + return count; +} +CONFIGFS_ATTR_RO(cfg_avirt_stream_, direction); + +static ssize_t cfg_avirt_stream_map_show(struct config_item *item, char *page) +{ + struct avirt_stream *stream = avirt_stream_from_config_item(item); + + return sprintf(page, "%s\n", stream->map); +} + +static ssize_t cfg_avirt_stream_map_store(struct config_item *item, + const char *page, size_t count) +{ + struct avirt_stream *stream = avirt_stream_from_config_item(item); + + memcpy(stream->map, (char *)page, count); + + return count; +} +CONFIGFS_ATTR(cfg_avirt_stream_, map); + +static ssize_t cfg_avirt_stream_channels_show(struct config_item *item, + char *page) +{ + ssize_t count; + struct avirt_stream *stream = avirt_stream_from_config_item(item); + + count = sprintf(page, "%d\n", stream->channels); + + return count; +} + +static ssize_t cfg_avirt_stream_channels_store(struct config_item *item, + const char *page, size_t count) +{ + int err; + struct avirt_stream *stream = avirt_stream_from_config_item(item); + unsigned long tmp; + char *p = (char *)page; + + err = kstrtoul(p, 10, &tmp); + if (err < 0) + return err; + + if (tmp > INT_MAX) + return -ERANGE; + + stream->channels = tmp; + + pr_info("%s [ARGS] channels: %d\n", __func__, stream->channels); + + return count; +} +CONFIGFS_ATTR(cfg_avirt_stream_, channels); + +static struct configfs_attribute *cfg_avirt_stream_attrs[] = { + &cfg_avirt_stream_attr_channels, + &cfg_avirt_stream_attr_map, + &cfg_avirt_stream_attr_direction, + NULL, +}; + +static void cfg_avirt_stream_release(struct config_item *item) +{ + pr_info("%s [ARGS] item->name:%s\n", __func__, item->ci_namebuf); + kfree(avirt_stream_from_config_item(item)); +} + +static struct configfs_item_operations cfg_avirt_stream_ops = { + .release = cfg_avirt_stream_release, +}; + +static struct config_item_type cfg_avirt_stream_type = { + .ct_item_ops = &cfg_avirt_stream_ops, + .ct_attrs = cfg_avirt_stream_attrs, + .ct_owner = THIS_MODULE, +}; + +static struct config_item * +cfg_avirt_stream_make_item(struct config_group *group, const char *name) +{ + char *split; + int direction; + struct avirt_stream *stream; + + // Get prefix (playback_ or capture_) + split = strsep((char **)&name, "_"); + if (!split) { + pr_err("Stream name: '%s' invalid!\n", split); + pr_err("Must begin with playback_ * or capture_ *\n"); + return ERR_PTR(-EINVAL); + } + if (!strcmp(split, "playback")) { + direction = SNDRV_PCM_STREAM_PLAYBACK; + } else if (!strcmp(split, "capture")) { + direction = SNDRV_PCM_STREAM_CAPTURE; + } else { + pr_err("Stream name: '%s' invalid!\n", split); + pr_err("Must begin with playback_ * or capture_ *\n"); + return ERR_PTR(-EINVAL); + } + + // Get stream name, and create PCM for stream + split = strsep((char **)&name, "\n"); + stream = __avirt_stream_create(split, direction); + if (IS_ERR(stream)) + return ERR_PTR(PTR_ERR(stream)); + + config_item_init_type_name(&stream->item, name, &cfg_avirt_stream_type); + + return &stream->item; +} + +static ssize_t cfg_avirt_stream_group_sealed_show(struct config_item *item, + char *page) +{ + return snprintf(page, PAGE_SIZE, "%d\n", streams_sealed); +} + +static ssize_t cfg_avirt_stream_group_sealed_store(struct config_item *item, + const char *page, + size_t count) +{ + unsigned long tmp; + char *p = (char *)page; + + if (streams_sealed) { + pr_err("AVIRT streams are already sealed!\n"); + return -EPERM; + } + + CHK_ERR(kstrtoul(p, 10, &tmp)); + + if (tmp != 1) { + pr_err("AVIRT streams can only be sealed, not unsealed!\n"); + return -ERANGE; + } + + streams_sealed = (bool)tmp; + + CHK_ERR(__avirt_card_register()); + + return count; +} +CONFIGFS_ATTR(cfg_avirt_stream_group_, sealed); + +static struct configfs_attribute *cfg_avirt_stream_group_attrs[] = { + &cfg_avirt_stream_group_attr_sealed, + NULL, +}; + +static struct configfs_group_operations cfg_avirt_stream_group_ops = { + .make_item = cfg_avirt_stream_make_item}; + +static struct config_item_type cfg_stream_group_type = { + .ct_group_ops = &cfg_avirt_stream_group_ops, + .ct_attrs = cfg_avirt_stream_group_attrs, + .ct_owner = THIS_MODULE}; + +static struct config_item_type cfg_avirt_group_type = { + .ct_owner = THIS_MODULE, +}; + +static struct configfs_subsystem cfg_subsys = { + .su_group = + { + .cg_item = + { + .ci_namebuf = "avirt", + .ci_type = &cfg_avirt_group_type, + }, + }, +}; + +int __init __avirt_configfs_init(struct avirt_core *core) +{ + int err; + + config_group_init(&cfg_subsys.su_group); + mutex_init(&cfg_subsys.su_mutex); + err = configfs_register_subsystem(&cfg_subsys); + if (err) { + pr_err("Cannot register configfs subsys!\n"); + return err; + } + core->stream_group = configfs_register_default_group( + &cfg_subsys.su_group, "streams", &cfg_stream_group_type); + if (IS_ERR(core->stream_group)) { + err = PTR_ERR(core->stream_group); + pr_err("Cannot register configfs default group 'streams'!\n"); + goto exit_configfs; + } + + return 0; + +exit_configfs: + configfs_unregister_subsystem(&cfg_subsys); + + return err; +} + +void __exit __avirt_configfs_exit(struct avirt_core *core) +{ + configfs_unregister_default_group(core->stream_group); + configfs_unregister_subsystem(&cfg_subsys); +} diff --git a/core.c b/core.c index c9a9aa3..bf122ed 100644 --- a/core.c +++ b/core.c @@ -8,14 +8,12 @@ */ #include -#include #include #include #include +#include -#include "avirt/core.h" -#include "alsa-pcm.h" -#include "utils.h" +#include "core_internal.h" MODULE_AUTHOR("JOSHANNE "); MODULE_AUTHOR("MFARRUGI "); @@ -29,162 +27,19 @@ MODULE_LICENSE("GPL v2"); #define D_ERRORK(fmt, args...) DERROR(AP_LOGNAME, fmt, ##args) #define SND_AVIRTUAL_DRIVER "snd_avirt" -#define MAX_PCM_DEVS 8 -#define MAX_AUDIOPATHS 4 -#define DEFAULT_FILE_PERMS 0644 - -/* Number of playback devices to create (max = MAX_PCM_DEVS) */ -static unsigned int playback_num; -/* Number of capture devices to create (max = MAX_PCM_DEVS) */ -static unsigned int capture_num; -/* Names per playback device */ -static char *playback_names[MAX_PCM_DEVS]; -/* Names per capture device */ -static char *capture_names[MAX_PCM_DEVS]; -/* Channels per playback device */ -static unsigned int playback_chans[MAX_PCM_DEVS]; -/* Channels per capture device */ -static unsigned int capture_chans[MAX_PCM_DEVS]; - -module_param(playback_num, int, DEFAULT_FILE_PERMS); -MODULE_PARM_DESC(playback_num, - "Number of playback devices to create (max = MAX_PCM_DEVS)"); -module_param(capture_num, int, DEFAULT_FILE_PERMS); -MODULE_PARM_DESC(capture_num, - "Number of capture devices to create (max = MAX_PCM_DEVS)"); -module_param_array(playback_names, charp, NULL, DEFAULT_FILE_PERMS); -MODULE_PARM_DESC(playback_names, "Names per playback device"); -module_param_array(capture_names, charp, NULL, DEFAULT_FILE_PERMS); -MODULE_PARM_DESC(capture_names, "Names per capture device"); -module_param_array(playback_chans, int, NULL, DEFAULT_FILE_PERMS); -MODULE_PARM_DESC(playback_chans, "Channels per playback device"); -module_param_array(capture_chans, int, NULL, DEFAULT_FILE_PERMS); -MODULE_PARM_DESC(capture_chans, "Channels per capture device"); - -static struct avirt_core { - struct snd_card *card; - struct device *dev; - struct class *avirt_class; - struct platform_device *platform_dev; -} core; + +extern struct snd_pcm_ops pcm_ops; + +static struct avirt_core core = { + .stream_count = 0, +}; struct avirt_coreinfo coreinfo = { - .version = { 0, 0, 1 }, - .pcm_buff_complete = pcm_buff_complete_cb, + .version = {0, 0, 1}, }; static LIST_HEAD(audiopath_list); -/** - * avirt_probe - Register ALSA soundcard - * @devptr: Platform driver device - * @return: 0 on success or error code otherwise - */ -static int avirt_probe(struct platform_device *devptr) -{ - static struct snd_device_ops device_ops; - struct snd_pcm **pcm; - int err = 0, i = 0; - - if (playback_num == 0 && capture_num == 0) { - pr_err("playback_num or capture_num must be greater than 0!\n"); - return -EINVAL; - } - - // Create the card instance - CHK_ERR_V(snd_card_new(&devptr->dev, SNDRV_DEFAULT_IDX1, "avirt", - THIS_MODULE, 0, &core.card), - "Failed to create sound card"); - - strcpy(core.card->driver, "avirt-alsa-device"); - strcpy(core.card->shortname, "avirt"); - strcpy(core.card->longname, "A virtual sound card driver for ALSA"); - - // Create new sound device - CHK_ERR_V((snd_device_new(core.card, SNDRV_DEV_LOWLEVEL, &coreinfo, - &device_ops)), - "Failed to create sound device"); - - // TEMP - if (playback_num > 0) { - coreinfo.playback.devices = playback_num; - coreinfo.playback.streams = kzalloc( - sizeof(*coreinfo.playback.streams) * playback_num, - GFP_KERNEL); - for (i = 0; i < playback_num; i++) { - pcm = &coreinfo.playback.streams[i].pcm; - CHK_ERR(snd_pcm_new(core.card, playback_names[i], i, 1, - 0, pcm)); - - /** Register driver callbacks */ - snd_pcm_set_ops(*pcm, SNDRV_PCM_STREAM_PLAYBACK, - &pcm_ops); - - (*pcm)->info_flags = 0; - strcpy((*pcm)->name, playback_names[i]); - coreinfo.playback.streams[i].channels = - playback_chans[i]; - pr_info("snd_pcm_new: name: %s, chans: %d\n", - (*pcm)->name, - coreinfo.playback.streams[i].channels); - } - } - - if (capture_num > 0) { - coreinfo.capture.devices = capture_num; - coreinfo.capture.streams = - kzalloc(sizeof(*coreinfo.capture.streams) * capture_num, - GFP_KERNEL); - for (i = 0; i < capture_num; i++) { - pcm = &coreinfo.capture.streams[i].pcm; - CHK_ERR(snd_pcm_new(core.card, capture_names[i], - i + playback_num, 0, 1, pcm)); - - /** Register driver callbacks */ - snd_pcm_set_ops(*pcm, SNDRV_PCM_STREAM_CAPTURE, - &pcm_ops); - - (*pcm)->info_flags = 0; - strcpy((*pcm)->name, capture_names[i]); - coreinfo.capture.streams[i].channels = capture_chans[i]; - pr_info("snd_pcm_new: name: %s, chans: %d\n", - (*pcm)->name, - coreinfo.capture.streams[i].channels); - } - } - // TEMP - - /** Register with the ALSA framework */ - CHK_ERR_V(snd_card_register(core.card), "Device registration failed"); - - return err; -} - -/** - * avirt_remove - Deregister ALSA soundcard - * @devptr: Platform driver device - * @return: 0 on success or error code otherwise - */ -static int avirt_remove(struct platform_device *devptr) -{ - snd_card_free(core.card); - if (coreinfo.playback.streams) - kfree(coreinfo.playback.streams); - if (coreinfo.capture.streams) - kfree(coreinfo.capture.streams); - - return 0; -} - -static struct platform_driver avirt_driver = { - .probe = avirt_probe, - .remove = avirt_remove, - .driver = - { - .name = SND_AVIRTUAL_DRIVER, - }, -}; - struct avirt_audiopath_obj { struct kobject kobj; struct list_head list; @@ -195,7 +50,7 @@ static struct kset *avirt_audiopath_kset; static struct kobject *kobj; #define to_audiopath_obj(d) container_of(d, struct avirt_audiopath_obj, kobj) -#define to_audiopath_attr(a) \ +#define to_audiopath_attr(a) \ container_of(a, struct avirt_audiopath_attribute, attr) /** @@ -350,8 +205,10 @@ static void destroy_avirt_audiopath_obj(struct avirt_audiopath_obj *p) struct avirt_audiopath *avirt_audiopath_get(const char *uid) { struct avirt_audiopath_obj *ap_obj; - list_for_each_entry (ap_obj, &audiopath_list, list) { - pr_info("get_ap %s\n", ap_obj->path->uid); + + list_for_each_entry(ap_obj, &audiopath_list, list) + { + // pr_info("get_ap %s\n", ap_obj->path->uid); if (!strcmp(ap_obj->path->uid, uid)) return ap_obj->path; } @@ -424,12 +281,121 @@ int avirt_audiopath_deregister(struct avirt_audiopath *audiopath) EXPORT_SYMBOL_GPL(avirt_audiopath_deregister); /** - * avirt_unregister_all - Unregister the platform device driver + * avirt_stream_count - get the stream count for the given direction + * @direction: The direction to get the stream count for + * @return: The stream count */ -static void avirt_unregister_all(void) +int avirt_stream_count(unsigned int direction) { - platform_device_unregister(core.platform_dev); - platform_driver_unregister(&avirt_driver); + struct list_head *entry; + struct config_item *item; + struct avirt_stream *stream; + unsigned int count = 0; + + if (direction > 1) + return -ERANGE; + + list_for_each(entry, &core.stream_group->cg_children) + { + item = container_of(entry, struct config_item, ci_entry); + stream = avirt_stream_from_config_item(item); + if (!stream) + return -EFAULT; + if (stream->direction == direction) + count++; + } + + return count; +} +EXPORT_SYMBOL_GPL(avirt_stream_count); + +/** + * __avirt_stream_create - Create audio stream, including it's ALSA PCM device + * @name: The name designated to the audio stream + * @direction: The PCM direction (SNDRV_PCM_STREAM_PLAYBACK or + * SNDRV_PCM_STREAM_CAPTURE) + * @return: The newly created audio stream if successful, or an error pointer + */ +struct avirt_stream *__avirt_stream_create(const char *name, int direction) +{ + struct snd_pcm *pcm; + struct avirt_stream *stream; + int err; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (!stream) + return ERR_PTR(-ENOMEM); + + strcpy(stream->name, name); + strcpy(stream->map, "ap_fddsp"); + stream->channels = 0; + stream->direction = direction; + stream->device = core.stream_count++; + + err = snd_pcm_new(core.card, name, stream->device, !direction, + direction, &pcm); + if (err < 0) + return ERR_PTR(err); + + // TD MF: IMPORTANT: NEED TO TEST >8 PCM DEVICES ON A + // CARD! + /** Register driver callbacks */ + snd_pcm_set_ops(pcm, direction, &pcm_ops); + + pcm->info_flags = 0; + strcpy(pcm->name, name); + + pr_info("%s [ARGS] name: %s device:%d\n", __func__, name, + stream->device); + + // coreinfo.streams[stream_idx] = stream; + + return stream; +} + +int __avirt_card_register(void) +{ + int err = 0; + + struct avirt_audiopath_obj *ap_obj; + list_for_each_entry(ap_obj, &audiopath_list, list) + { + pr_info("Calling configure for AP uid: %s\n", + ap_obj->path->uid); + ap_obj->path->configure(core.stream_group, core.stream_count); + } + + err = snd_card_register(core.card); + if (err < 0) { + pr_err("Sound card registration failed!"); + snd_card_free(core.card); + } + + return err; +} + +struct avirt_stream *__avirt_stream_find_by_device(unsigned int device) +{ + struct avirt_stream *stream; + struct config_item *item; + struct list_head *entry; + + if (device >= core.stream_count) { + pr_err("Stream device number is greater than number streams available\n"); + return ERR_PTR(-EINVAL); + } + + list_for_each(entry, &core.stream_group->cg_children) + { + item = container_of(entry, struct config_item, ci_entry); + stream = avirt_stream_from_config_item(item); + if (!stream) + return ERR_PTR(-EFAULT); + if (stream->device == device) + return stream; + } + + return NULL; } /** @@ -442,23 +408,10 @@ static int __init core_init(void) D_INFOK("Alsa Virtual Sound Driver avirt-%d.%d.%d", coreinfo.version[0], coreinfo.version[1], coreinfo.version[2]); - err = platform_driver_register(&avirt_driver); - if (err < 0) - return err; - - core.platform_dev = platform_device_register_simple(SND_AVIRTUAL_DRIVER, - 0, NULL, 0); - if (IS_ERR(core.platform_dev)) { - err = PTR_ERR(core.platform_dev); - pr_err("platform_dev error [%d]!\n", err); - goto exit_platform_device; - } - core.avirt_class = class_create(THIS_MODULE, SND_AVIRTUAL_DRIVER); if (IS_ERR(core.avirt_class)) { pr_err("No udev support\n"); - err = PTR_ERR(core.avirt_class); - goto exit_bus; + return PTR_ERR(core.avirt_class); } core.dev = device_create(core.avirt_class, NULL, 0, NULL, "avirtcore"); @@ -467,22 +420,38 @@ static int __init core_init(void) goto exit_class; } + // Create the card instance + err = snd_card_new(core.dev, SNDRV_DEFAULT_IDX1, "avirt", THIS_MODULE, + 0, &core.card); + if (err < 0) { + pr_err("Failed to create sound card"); + goto exit_class_container; + } + + strcpy(core.card->driver, "avirt-alsa-device"); + strcpy(core.card->shortname, "avirt"); + strcpy(core.card->longname, "A virtual sound card driver for ALSA"); + avirt_audiopath_kset = kset_create_and_add("audiopaths", NULL, &core.dev->kobj); if (!avirt_audiopath_kset) { err = -ENOMEM; - goto exit_class_container; + goto exit_snd_card; } + err = __avirt_configfs_init(&core); + if (err < 0) + goto exit_snd_card; + return 0; +exit_snd_card: + snd_card_free(core.card); exit_class_container: device_destroy(core.avirt_class, 0); exit_class: class_destroy(core.avirt_class); -exit_bus: -exit_platform_device: - avirt_unregister_all(); + return err; } @@ -491,34 +460,11 @@ exit_platform_device: */ static void __exit core_exit(void) { + __avirt_configfs_exit(&core); + kset_unregister(avirt_audiopath_kset); device_destroy(core.avirt_class, 0); class_destroy(core.avirt_class); - - avirt_unregister_all(); - D_INFOK("Exit begin!"); - pr_info("playback_num: %d, capture_num: %d\n", playback_num, - capture_num); - - pr_info("playback_chans: %d %d %d %d %d %d %d %d\n", playback_chans[0], - playback_chans[1], playback_chans[2], playback_chans[3], - playback_chans[4], playback_chans[5], playback_chans[6], - playback_chans[7]); - - pr_info("capture_chans: %d %d %d %d %d %d %d %d\n", capture_chans[0], - capture_chans[1], capture_chans[2], capture_chans[3], - capture_chans[4], capture_chans[5], capture_chans[6], - capture_chans[7]); - - pr_info("playback_names: %s %s %s %s %s %s %s %s\n", playback_names[0], - playback_names[1], playback_names[2], playback_names[3], - playback_names[4], playback_names[5], playback_names[6], - playback_names[7]); - - pr_info("capture_names: %s %s %s %s %s %s %s %s\n", capture_names[0], - capture_names[1], capture_names[2], capture_names[3], - capture_names[4], capture_names[5], capture_names[6], - capture_names[7]); } module_init(core_init); diff --git a/core.h b/core.h index c11ee1d..493fc2b 100644 --- a/core.h +++ b/core.h @@ -13,26 +13,28 @@ #include #include -#define MAX_NAME_LEN 32 +#define MAX_STREAMS 16 +#define MAX_NAME_LEN 80 /** - * PCM buffer complete callback - * - * These are called from the audiopath when a PCM buffer has completed, and - * new data can be submitted/retrieved + * AVIRT Audio Path configure function type + * Each Audio Path registers this at avirt_audiopath_register time. + * It is then called by the core once AVIRT has been configured */ -typedef int (*avirt_buff_complete)(struct snd_pcm_substream *substream); +typedef int (*avirt_audiopath_configure)(struct config_group *stream_group, + unsigned int stream_count); /** * AVIRT Audio Path info */ struct avirt_audiopath { - const char *uid; /* Unique identifier */ - const char *name; /* Pretty name */ - unsigned int version[3]; /* Version - Major.Minor.Ext */ - struct snd_pcm_hardware *hw; /* ALSA PCM HW conf */ - struct snd_pcm_ops *pcm_ops; /* ALSA PCM op table */ - unsigned int blocksize; /* Audio frame size accepted */ + const char *uid; /* Unique identifier */ + const char *name; /* Pretty name */ + unsigned int version[3]; /* Version - Major.Minor.Ext */ + struct snd_pcm_hardware *hw; /* ALSA PCM HW conf */ + struct snd_pcm_ops *pcm_ops; /* ALSA PCM op table */ + unsigned int blocksize; /* Audio frame size accepted */ + avirt_audiopath_configure configure; /* Configure callback function */ void *context; }; @@ -41,29 +43,19 @@ struct avirt_audiopath { * Audio stream configuration */ struct avirt_stream { - struct snd_pcm *pcm; /* Stream PCM device */ - unsigned int channels; /* Stream channel count */ + char name[MAX_NAME_LEN]; /* Stream name */ + char map[MAX_NAME_LEN]; /* Stream Audio Path mapping */ + unsigned int channels; /* Stream channel count */ + unsigned int device; /* Stream PCM device no. */ + unsigned int direction; /* Stream direction */ struct config_item item; /* configfs item reference */ }; -/** - * Collection of audio streams - */ -struct avirt_stream_group { - struct avirt_stream *streams; /* AVIRT stream array */ - unsigned int devices; /* Number of stream devices */ -}; - /** * AVIRT core info */ struct avirt_coreinfo { unsigned int version[3]; - - struct avirt_stream_group playback; - struct avirt_stream_group capture; - - avirt_buff_complete pcm_buff_complete; }; /** @@ -90,12 +82,30 @@ int avirt_audiopath_deregister(struct avirt_audiopath *audiopath); struct avirt_audiopath *avirt_audiopath_get(const char *uid); /** - * avirt_subscribe_stream - subscribe the Audio Path to the given streams - * @audiopath: Audio Path to subscribe for - * @streams: The streams to subscribe the Audio Path to - * return: 0 on success or error code otherwise + * avirt_stream_count - get the stream count for the given direction + * @direction: The direction to get the stream count for + * @return: The stream count + */ +int avirt_stream_count(unsigned int direction); + +/** + * avirt_stream_from_config_item - Convert a config_item to an avirt_stream + * @item: The config_item to convert from + * @return: The item's avirt_stream if successful, NULL otherwise + */ +static inline struct avirt_stream * +avirt_stream_from_config_item(struct config_item *item) +{ + return item ? container_of(item, struct avirt_stream, item) : NULL; +} + +/** + * avirt_pcm_period_elapsed - PCM buffer complete callback + * @substream: pointer to ALSA PCM substream + * + * This should be called from a child Audio Path once it has finished processing + * the PCM buffer */ -int avirt_subscribe_stream(struct avirt_audiopath *audiopath, - const char **streams); +void avirt_pcm_period_elapsed(struct snd_pcm_substream *substream); #endif // __AVIRT_CORE_H__ diff --git a/core_internal.h b/core_internal.h new file mode 100644 index 0000000..3639d6e --- /dev/null +++ b/core_internal.h @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ALSA Virtual Soundcard + * + * core.h - Internal header for virtual ALSA card + * + * Copyright (C) 2010-2018 Fiberdyne Systems Pty Ltd + */ + +#ifndef __AVIRT_CORE_INTERNAL_H__ +#define __AVIRT_CORE_INTERNAL_H__ + +#include + +#include "utils.h" + +struct avirt_core { + struct snd_card *card; + struct device *dev; + struct class *avirt_class; + struct config_group *stream_group; + unsigned int stream_count; +}; + +int __init __avirt_configfs_init(struct avirt_core *core); +void __exit __avirt_configfs_exit(struct avirt_core *core); + +/** + * __avirt_card_register - Register the sound card to user space + * @return: 0 on success, negative ERRNO on failure + */ +int __avirt_card_register(void); + +/** + * __avirt_stream_find_by_device - Get audio stream from device number + * @device: The PCM device number corresponding to the desired stream + * @return: The audio stream if found, or an error pointer otherwise + */ +struct avirt_stream *__avirt_stream_find_by_device(unsigned int device); + +/** + * __avirt_stream_create - Create audio stream, including it's ALSA PCM device + * @name: The name designated to the audio stream + * @direction: The PCM direction (SNDRV_PCM_STREAM_PLAYBACK or + * SNDRV_PCM_STREAM_CAPTURE) + * @return: The newly created audio stream if successful, or an error pointer + */ +struct avirt_stream *__avirt_stream_create(const char *name, int direction); + +#endif // __AVIRT_CORE_INTERNAL_H__ diff --git a/dummy/dummy.c b/dummy/dummy.c index d619786..606b22d 100644 --- a/dummy/dummy.c +++ b/dummy/dummy.c @@ -130,7 +130,7 @@ static void dummy_systimer_callback(struct timer_list *t) dpcm->elapsed = 0; spin_unlock_irqrestore(&dpcm->lock, flags); if (elapsed) - coreinfo->pcm_buff_complete(dpcm->substream); + avirt_pcm_period_elapsed(dpcm->substream); } static snd_pcm_uframes_t @@ -231,6 +231,25 @@ static struct snd_pcm_ops dummyap_pcm_ops = { /******************************************************************************* * Dummy Audio Path AVIRT registration ******************************************************************************/ +int dummy_configure(struct config_group *avirt_stream_group, + unsigned int stream_count) +{ + // Do something with streams + + struct list_head *entry; + list_for_each(entry, &avirt_stream_group->cg_children) + { + struct config_item *item = + container_of(entry, struct config_item, ci_entry); + struct avirt_stream *stream = + avirt_stream_from_config_item(item); + pr_info("%s: stream name:%s device:%d channels:%d\n", __func__, + stream->name, stream->device, stream->channels); + } + + return 0; +} + static struct snd_pcm_hardware dummyap_hw = { .formats = SNDRV_PCM_FMTBIT_S16_LE, .info = (SNDRV_PCM_INFO_INTERLEAVED // Channel interleaved audio @@ -250,6 +269,7 @@ static struct avirt_audiopath dummyap_module = { .hw = &dummyap_hw, .pcm_ops = &dummyap_pcm_ops, .blocksize = DUMMY_BLOCKSIZE, + .configure = dummy_configure, }; static int __init dummy_init(void) diff --git a/utils.h b/utils.h index b449938..34e273f 100644 --- a/utils.h +++ b/utils.h @@ -12,38 +12,38 @@ #include -#define PRINT_ERR(errno, errmsg) \ - pr_err("[%s]:[ERRNO:%d]: %s ", __func__, errno, (errmsg)); +#define PRINT_ERR(errno, errmsg) \ + pr_err("[%s]:[ERRNO:%d]: %s \n", __func__, errno, (errmsg)); -#define CHK_ERR(errno) \ - do { \ - if ((errno) < 0) \ - return (errno); \ +#define CHK_ERR(errno) \ + do { \ + if ((errno) < 0) \ + return (errno); \ } while (0) -#define CHK_ERR_V(errno, errmsg, ...) \ - do { \ - if ((errno) < 0) { \ - PRINT_ERR((errno), (errmsg), ##__VA_ARGS__) \ - return (errno); \ - } \ +#define CHK_ERR_V(errno, errmsg, ...) \ + do { \ + if ((errno) < 0) { \ + PRINT_ERR((errno), (errmsg), ##__VA_ARGS__) \ + return (errno); \ + } \ } while (0) -#define CHK_NULL(x) \ - do { \ - if (!(x)) \ - return -EFAULT; \ +#define CHK_NULL(x, errno) \ + do { \ + if (!(x)) \ + return errno; \ } while (0) -#define CHK_NULL_V(x, errmsg, ...) \ - do { \ - if (!(x)) { \ - char *errmsg_done = \ - kasprintf(GFP_KERNEL, errmsg, ##__VA_ARGS__); \ - PRINT_ERR(EFAULT, errmsg_done); \ - kfree(errmsg_done); \ - return -EFAULT; \ - } \ +#define CHK_NULL_V(x, errno, errmsg, ...) \ + do { \ + if (!(x)) { \ + char *errmsg_done = \ + kasprintf(GFP_KERNEL, errmsg, ##__VA_ARGS__); \ + PRINT_ERR(EFAULT, errmsg_done); \ + kfree(errmsg_done); \ + return errno; \ + } \ } while (0) #endif -- cgit 1.2.3-korg From 0acef1799beace4dd38d41bda9df77e84a5fe398 Mon Sep 17 00:00:00 2001 From: Mark Farrugia Date: Sun, 7 Oct 2018 22:00:10 +1100 Subject: Remove blocksize from audiopath This is no longer needed in AVIRT, since it is only actually used for the ADSP Audio Path. Clean up white space, add function documentation, remove out of place debug prints Signed-off-by: Mark Farrugia --- alsa-pcm.c | 13 +------------ core.c | 5 ++--- core.h | 21 ++++++++++----------- core_internal.h | 10 ++++++++++ dummy/dummy.c | 1 - loopback/loopback.c | 2 +- 6 files changed, 24 insertions(+), 28 deletions(-) (limited to 'dummy/dummy.c') diff --git a/alsa-pcm.c b/alsa-pcm.c index 5a30aff..958ccbb 100644 --- a/alsa-pcm.c +++ b/alsa-pcm.c @@ -49,7 +49,7 @@ static int pcm_open(struct snd_pcm_substream *substream) struct avirt_audiopath *audiopath; struct avirt_stream *stream; struct snd_pcm_hardware *hw; - unsigned int bytes_per_sample = 0, blocksize = 0, chans = 0; + unsigned int chans = 0; char *uid = "ap_fddsp"; // TD MF: Make this dynamic! audiopath = avirt_audiopath_get(uid); @@ -57,20 +57,9 @@ static int pcm_open(struct snd_pcm_substream *substream) uid); substream->private_data = audiopath; - blocksize = audiopath->blocksize; - // Copy the hw params from the audiopath to the pcm hw = &substream->runtime->hw; memcpy(hw, audiopath->hw, sizeof(struct snd_pcm_hardware)); - pr_info("%s %d %d", __func__, blocksize, hw->periods_max); - - if (hw->formats == SNDRV_PCM_FMTBIT_S16_LE) { - bytes_per_sample = 2; - } else { - pr_err("[%s] PCM only supports SNDRV_PCM_FMTBIT_S16_LE", - __func__); - return -EINVAL; - } stream = __avirt_stream_find_by_device(substream->pcm->device); if (IS_ERR_VALUE(stream) || !stream) diff --git a/core.c b/core.c index d925eae..567021e 100644 --- a/core.c +++ b/core.c @@ -241,9 +241,8 @@ int avirt_audiopath_register(struct avirt_audiopath *audiopath, audiopath_obj->path = audiopath; audiopath->context = audiopath_obj; - pr_info("Registered new Audio Path: %s\n", audiopath->uid); - pr_info("\tBlocksize: %d, Periods: %d\n", audiopath->blocksize, - audiopath->hw->periods_max); + D_INFOK("Registered new Audio Path: %s", audiopath->name); + list_add_tail(&audiopath_obj->list, &audiopath_list); // If we have already sealed the streams, configure this AP diff --git a/core.h b/core.h index 493fc2b..d9b1382 100644 --- a/core.h +++ b/core.h @@ -28,12 +28,11 @@ typedef int (*avirt_audiopath_configure)(struct config_group *stream_group, * AVIRT Audio Path info */ struct avirt_audiopath { - const char *uid; /* Unique identifier */ - const char *name; /* Pretty name */ - unsigned int version[3]; /* Version - Major.Minor.Ext */ - struct snd_pcm_hardware *hw; /* ALSA PCM HW conf */ - struct snd_pcm_ops *pcm_ops; /* ALSA PCM op table */ - unsigned int blocksize; /* Audio frame size accepted */ + const char *uid; /* Unique identifier */ + const char *name; /* Pretty name */ + unsigned int version[3]; /* Version - Major.Minor.Ext */ + const struct snd_pcm_hardware *hw; /* ALSA PCM HW conf */ + const struct snd_pcm_ops *pcm_ops; /* ALSA PCM op table */ avirt_audiopath_configure configure; /* Configure callback function */ void *context; @@ -44,10 +43,10 @@ struct avirt_audiopath { */ struct avirt_stream { char name[MAX_NAME_LEN]; /* Stream name */ - char map[MAX_NAME_LEN]; /* Stream Audio Path mapping */ - unsigned int channels; /* Stream channel count */ - unsigned int device; /* Stream PCM device no. */ - unsigned int direction; /* Stream direction */ + char map[MAX_NAME_LEN]; /* Stream Audio Path mapping */ + unsigned int channels; /* Stream channel count */ + unsigned int device; /* Stream PCM device no. */ + unsigned int direction; /* Stream direction */ struct config_item item; /* configfs item reference */ }; @@ -94,7 +93,7 @@ int avirt_stream_count(unsigned int direction); * @return: The item's avirt_stream if successful, NULL otherwise */ static inline struct avirt_stream * -avirt_stream_from_config_item(struct config_item *item) + avirt_stream_from_config_item(struct config_item *item) { return item ? container_of(item, struct avirt_stream, item) : NULL; } diff --git a/core_internal.h b/core_internal.h index e7bea07..5979a50 100644 --- a/core_internal.h +++ b/core_internal.h @@ -23,7 +23,17 @@ struct avirt_core { bool streams_sealed; }; +/** + * __avirt_configfs_init - Initialise the configfs system + * @core: The avirt_core pointer + * @return: 0 on success, negative ERRNO on failure + */ int __init __avirt_configfs_init(struct avirt_core *core); + +/** + * __avirt_configfs_exit - Clean up and exit the configfs system + * @core: The avirt_core pointer + */ void __exit __avirt_configfs_exit(struct avirt_core *core); /** diff --git a/dummy/dummy.c b/dummy/dummy.c index 606b22d..8808e8e 100644 --- a/dummy/dummy.c +++ b/dummy/dummy.c @@ -268,7 +268,6 @@ static struct avirt_audiopath dummyap_module = { .version = { 0, 0, 1 }, .hw = &dummyap_hw, .pcm_ops = &dummyap_pcm_ops, - .blocksize = DUMMY_BLOCKSIZE, .configure = dummy_configure, }; diff --git a/loopback/loopback.c b/loopback/loopback.c index 5694dce..e9c4bcb 100644 --- a/loopback/loopback.c +++ b/loopback/loopback.c @@ -279,7 +279,7 @@ static struct avirt_audiopath loopbackap_module = { .value = 10, .hw = &loopbackap_hw, .pcm_ops = &loopbackap_pcm_ops, - .blocksize = 512, + .configure = loopback_configure, }; static int __init loopback_init(void) -- cgit 1.2.3-korg From 85510ff4540c13609b3ec749a80638ae502fd098 Mon Sep 17 00:00:00 2001 From: Mark Farrugia Date: Mon, 8 Oct 2018 12:03:56 +1100 Subject: Add card to the configure callback The loopback audio path might need to add it's own controls. Signed-off-by: Mark Farrugia --- core.h | 3 ++- dummy/dummy.c | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'dummy/dummy.c') diff --git a/core.h b/core.h index ec44081..b7c250a 100644 --- a/core.h +++ b/core.h @@ -32,7 +32,8 @@ * Each Audio Path registers this at avirt_audiopath_register time. * It is then called by the core once AVIRT has been configured */ -typedef int (*avirt_audiopath_configure)(struct config_group *stream_group, +typedef int (*avirt_audiopath_configure)(struct snd_card *card, + struct config_group *stream_group, unsigned int stream_count); /** diff --git a/dummy/dummy.c b/dummy/dummy.c index 8808e8e..b77301f 100644 --- a/dummy/dummy.c +++ b/dummy/dummy.c @@ -231,14 +231,14 @@ static struct snd_pcm_ops dummyap_pcm_ops = { /******************************************************************************* * Dummy Audio Path AVIRT registration ******************************************************************************/ -int dummy_configure(struct config_group *avirt_stream_group, +int dummy_configure(struct snd_card *card, + struct config_group *avirt_stream_group, unsigned int stream_count) { // Do something with streams struct list_head *entry; - list_for_each(entry, &avirt_stream_group->cg_children) - { + list_for_each (entry, &avirt_stream_group->cg_children) { struct config_item *item = container_of(entry, struct config_item, ci_entry); struct avirt_stream *stream = -- cgit 1.2.3-korg From f0029c35ecb07fcfcf05b0093b536054f674a303 Mon Sep 17 00:00:00 2001 From: Mark Farrugia Date: Wed, 24 Oct 2018 23:18:26 +1100 Subject: Fix module authors/descriptions These need to be in the format the Linux expects, and uniform across AVIRT Signed-off-by: Mark Farrugia --- core.c | 7 ++++--- dummy/dummy.c | 6 +++--- loopback/loopback.c | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'dummy/dummy.c') diff --git a/core.c b/core.c index 1ea8107..b526949 100644 --- a/core.c +++ b/core.c @@ -15,10 +15,11 @@ #include "core_internal.h" -MODULE_AUTHOR("JOSHANNE "); -MODULE_AUTHOR("MFARRUGI "); -MODULE_DESCRIPTION("A configurable virtual soundcard"); +MODULE_AUTHOR("James O'Shannessy "); +MODULE_AUTHOR("Mark Farrugia "); +MODULE_DESCRIPTION("ALSA virtual, dynamic soundcard"); MODULE_LICENSE("GPL v2"); +MODULE_SUPPORTED_DEVICE("{{ALSA,AVIRT soundcard}}"); #define D_LOGNAME "core" diff --git a/dummy/dummy.c b/dummy/dummy.c index b77301f..660305e 100644 --- a/dummy/dummy.c +++ b/dummy/dummy.c @@ -11,9 +11,9 @@ #include #include -MODULE_AUTHOR("JOSHANNE "); -MODULE_AUTHOR("MFARRUGI "); -MODULE_DESCRIPTION("Sample Audio Path Module Interface"); +MODULE_AUTHOR("James O'Shannessy "); +MODULE_AUTHOR("Mark Farrugia "); +MODULE_DESCRIPTION("Dummy Audio Path for AVIRT"); MODULE_LICENSE("GPL v2"); #define DUMMY_SAMPLE_RATE 48000 diff --git a/loopback/loopback.c b/loopback/loopback.c index 2e02711..8ca23bd 100644 --- a/loopback/loopback.c +++ b/loopback/loopback.c @@ -1,5 +1,5 @@ /* - * Loopback soundcard + * Loopback Audio Path for AVIRT * * Original code: * Copyright (c) by Jaroslav Kysela @@ -48,7 +48,7 @@ #include MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("A loopback soundcard"); +MODULE_DESCRIPTION("Loopback Audio Path for AVIRT"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{ALSA,Loopback soundcard}}"); -- cgit 1.2.3-korg From 6b1a48a65fca8c81a4299f95f2096dbef4815b75 Mon Sep 17 00:00:00 2001 From: Mark Farrugia Date: Thu, 25 Oct 2018 14:02:41 +1100 Subject: Update license headers All license headers need to be uniform across AVIRT Signed-off-by: Mark Farrugia --- alsa-pcm.c | 8 ++++---- configfs.c | 10 +++++----- core.c | 8 ++++---- core_internal.h | 8 ++++---- dummy/dummy.c | 14 +++++++++----- loopback/loopback.c | 46 +++++++++++++++++----------------------------- 6 files changed, 43 insertions(+), 51 deletions(-) (limited to 'dummy/dummy.c') diff --git a/alsa-pcm.c b/alsa-pcm.c index 17c08fd..34a658c 100644 --- a/alsa-pcm.c +++ b/alsa-pcm.c @@ -1,10 +1,10 @@ // SPDX-License-Identifier: GPL-2.0 /* - * ALSA Virtual Soundcard + * AVIRT - ALSA Virtual Soundcard * - * alsa-pcm.c - AVIRT ALSA PCM interface - * - * Copyright (C) 2010-2018 Fiberdyne Systems Pty Ltd + * Copyright (c) 2010-2018 Fiberdyne Systems Pty Ltd + * + * alsa-pcm.c - AVIRT PCM interface */ #include "core_internal.h" diff --git a/configfs.c b/configfs.c index 924866c..ce55aa0 100644 --- a/configfs.c +++ b/configfs.c @@ -1,10 +1,10 @@ // SPDX-License-Identifier: GPL-2.0 -/* - * ALSA Virtual Soundcard +/* + * AVIRT - ALSA Virtual Soundcard * - * configfs.c - configfs for virtual ALSA card - * - * Copyright (C) 2010-2018 Fiberdyne Systems Pty Ltd + * Copyright (c) 2010-2018 Fiberdyne Systems Pty Ltd + * + * configfs.c - AVIRT configfs support */ #include diff --git a/core.c b/core.c index b526949..a8554b7 100644 --- a/core.c +++ b/core.c @@ -1,10 +1,10 @@ // SPDX-License-Identifier: GPL-2.0 /* - * ALSA Virtual Soundcard + * AVIRT - ALSA Virtual Soundcard * - * core.c - Implementation of core module for virtual ALSA card - * - * Copyright (C) 2010-2018 Fiberdyne Systems Pty Ltd + * Copyright (c) 2010-2018 Fiberdyne Systems Pty Ltd + * + * core.c - AVIRT core internals */ #include diff --git a/core_internal.h b/core_internal.h index 1ab8d3c..5bff1c8 100644 --- a/core_internal.h +++ b/core_internal.h @@ -1,10 +1,10 @@ // SPDX-License-Identifier: GPL-2.0 /* - * ALSA Virtual Soundcard + * AVIRT - ALSA Virtual Soundcard * - * core.h - Internal header for virtual ALSA card - * - * Copyright (C) 2010-2018 Fiberdyne Systems Pty Ltd + * Copyright (c) 2010-2018 Fiberdyne Systems Pty Ltd + * + * core_internal.h - AVIRT internal header */ #ifndef __AVIRT_CORE_INTERNAL_H__ diff --git a/dummy/dummy.c b/dummy/dummy.c index 660305e..2841585 100644 --- a/dummy/dummy.c +++ b/dummy/dummy.c @@ -1,10 +1,14 @@ // SPDX-License-Identifier: GPL-2.0 -/* - * ALSA Virtual Soundcard - * - * dummy_audiopath.c - AVIRT sample Audio Path definition +/* + * Dummy Audio Path for AVIRT + * + * Original systimer code: + * Copyright (c) by Jaroslav Kysela * - * Copyright (C) 2010-2018 Fiberdyne Systems Pty Ltd + * Adapt to use AVIRT + * Copyright (c) 2010-2018 Fiberdyne Systems Pty Ltd + * + * dummy.c - Dummy Audio Path driver implementation for AVIRT */ #include diff --git a/loopback/loopback.c b/loopback/loopback.c index 8ca23bd..d465cc6 100644 --- a/loopback/loopback.c +++ b/loopback/loopback.c @@ -1,35 +1,23 @@ -/* - * Loopback Audio Path for AVIRT - * - * Original code: - * Copyright (c) by Jaroslav Kysela - * - * More accurate positioning and full-duplex support: - * Copyright (c) Ahmet Ä°nan - * - * Major (almost complete) rewrite: - * Copyright (c) by Takashi Iwai - * - * A next major update in 2010 (separate timers for playback and capture): - * Copyright (c) Jaroslav Kysela +// SPDX-License-Identifier: GPL-2.0 +/* + * Loopback Audio Path for AVIRT * - * Adapt to use AVIRT, looping is now conducted on the same device - * Copyright (c) by Mark Farrugia - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Original code: + * Copyright (c) by Jaroslav Kysela + * + * More accurate positioning and full-duplex support: + * Copyright (c) Ahmet Ä°nan * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Major (almost complete) rewrite: + * Copyright (c) by Takashi Iwai * + * A next major update in 2010 (separate timers for playback and capture): + * Copyright (c) Jaroslav Kysela + * + * Adapt to use AVIRT, looping is now conducted on the same PCM device + * Copyright (c) 2010-2018 Fiberdyne Systems Pty Ltd + * + * loopback.c - Loopback Audio Path driver implementation for AVIRT */ #include -- cgit 1.2.3-korg From 6e5b92cb45996adaa309b9534a53ed81989986de Mon Sep 17 00:00:00 2001 From: Mark Farrugia Date: Thu, 25 Oct 2018 14:05:10 +1100 Subject: Remove unused MODULE_SUPPORTED_DEVICE macros, removed obsolete comments Added debug macros for Dummy AP Signed-off-by: Mark Farrugia --- configfs.c | 2 -- core.c | 4 +--- dummy/dummy.c | 10 ++++++++-- loopback/loopback.c | 1 - 4 files changed, 9 insertions(+), 8 deletions(-) (limited to 'dummy/dummy.c') diff --git a/configfs.c b/configfs.c index ce55aa0..13e38b2 100644 --- a/configfs.c +++ b/configfs.c @@ -76,8 +76,6 @@ static ssize_t cfg_avirt_stream_channels_store(struct config_item *item, stream->channels = tmp; - D_INFOK("channels: %d", stream->channels); - return count; } CONFIGFS_ATTR(cfg_avirt_stream_, channels); diff --git a/core.c b/core.c index a8554b7..b63944a 100644 --- a/core.c +++ b/core.c @@ -19,7 +19,6 @@ MODULE_AUTHOR("James O'Shannessy "); MODULE_AUTHOR("Mark Farrugia "); MODULE_DESCRIPTION("ALSA virtual, dynamic soundcard"); MODULE_LICENSE("GPL v2"); -MODULE_SUPPORTED_DEVICE("{{ALSA,AVIRT soundcard}}"); #define D_LOGNAME "core" @@ -196,6 +195,7 @@ static struct snd_pcm *pcm_create(struct avirt_stream *stream) struct snd_pcm *pcm; int err; + /** Special case: loopback */ if (!strcmp(stream->map, "ap_loopback")) { playback = true; capture = true; @@ -212,8 +212,6 @@ static struct snd_pcm *pcm_create(struct avirt_stream *stream) if (err < 0) return ERR_PTR(err); - // TD MF: IMPORTANT: NEED TO TEST >8 PCM DEVICES ON A - // CARD! /** Register driver callbacks */ if (playback) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_ops); diff --git a/dummy/dummy.c b/dummy/dummy.c index 2841585..596838d 100644 --- a/dummy/dummy.c +++ b/dummy/dummy.c @@ -20,6 +20,12 @@ MODULE_AUTHOR("Mark Farrugia "); MODULE_DESCRIPTION("Dummy Audio Path for AVIRT"); MODULE_LICENSE("GPL v2"); +#define AP_UID "ap_dummy" + +#define AP_INFOK(fmt, args...) DINFO(AP_UID, fmt, ##args) +#define AP_PRINTK(fmt, args...) DDEBUG(AP_UID, fmt, ##args) +#define AP_ERRORK(fmt, args...) DERROR(AP_UID, fmt, ##args) + #define DUMMY_SAMPLE_RATE 48000 #define DUMMY_BLOCKSIZE 512 #define DUMMY_PERIODS_MIN 1 @@ -247,8 +253,8 @@ int dummy_configure(struct snd_card *card, container_of(entry, struct config_item, ci_entry); struct avirt_stream *stream = avirt_stream_from_config_item(item); - pr_info("%s: stream name:%s device:%d channels:%d\n", __func__, - stream->name, stream->device, stream->channels); + AP_INFOK("stream name:%s device:%d channels:%d", stream->name, + stream->device, stream->channels); } return 0; diff --git a/loopback/loopback.c b/loopback/loopback.c index d465cc6..acddf99 100644 --- a/loopback/loopback.c +++ b/loopback/loopback.c @@ -38,7 +38,6 @@ MODULE_AUTHOR("Jaroslav Kysela "); MODULE_DESCRIPTION("Loopback Audio Path for AVIRT"); MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ALSA,Loopback soundcard}}"); #define AP_UID "ap_loopback" -- cgit 1.2.3-korg From 18007ca500654b48011e8a8cf96c47b1a5aa3be7 Mon Sep 17 00:00:00 2001 From: Mark Farrugia Date: Thu, 25 Oct 2018 15:56:58 +1100 Subject: Move system-leavel header to sound directory Change include guards to reflect Linux sound driver format Signed-off-by: Mark Farrugia --- Makefile | 2 +- configfs.c | 3 +- core.c | 3 +- core.h | 123 ---------------------------------------------------- core_internal.h | 8 ++-- dummy/Makefile | 2 +- dummy/dummy.c | 2 +- loopback/Makefile | 2 +- loopback/loopback.c | 3 +- sound/avirt.h | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++ utils.h | 14 +++--- 11 files changed, 141 insertions(+), 143 deletions(-) delete mode 100644 core.h create mode 100644 sound/avirt.h (limited to 'dummy/dummy.c') diff --git a/Makefile b/Makefile index 44874ca..791a60a 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ avirt_core-y += configfs.o ifeq ($(CONFIG_AVIRT_BUILDLOCAL),) CCFLAGS_AVIRT := "drivers/staging/" else - CCFLAGS_AVIRT := "$(PWD)/../" + CCFLAGS_AVIRT := "$(PWD)" endif ccflags-y += -I${CCFLAGS_AVIRT} diff --git a/configfs.c b/configfs.c index 13e38b2..49eaa78 100644 --- a/configfs.c +++ b/configfs.c @@ -7,7 +7,8 @@ * configfs.c - AVIRT configfs support */ -#include +#include + #include "core_internal.h" #define D_LOGNAME "configfs" diff --git a/core.c b/core.c index b63944a..6509b55 100644 --- a/core.c +++ b/core.c @@ -9,9 +9,8 @@ #include #include -#include +#include #include -#include #include "core_internal.h" diff --git a/core.h b/core.h deleted file mode 100644 index bac4fc0..0000000 --- a/core.h +++ /dev/null @@ -1,123 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * ALSA Virtual Soundcard - * - * core.h - System-level header for virtual ALSA card - * - * Copyright (C) 2010-2018 Fiberdyne Systems Pty Ltd - */ - -#ifndef __AVIRT_CORE_H__ -#define __AVIRT_CORE_H__ - -#include -#include - -#define MAX_STREAMS 16 -#define MAX_NAME_LEN 80 - -#define DINFO(logname, fmt, args...) \ - printk(KERN_INFO "[AVIRT][%s]: " fmt "\n", logname, ##args) - -#define DERROR(logname, fmt, args...) \ - printk(KERN_ERR "[AVIRT][%s]: %d:%s " fmt "\n", logname, __LINE__, \ - __func__, ##args) - -#define DDEBUG(logname, fmt, args...) \ - printk(KERN_DEBUG "[AVIRT][%s]: %d:%s " fmt "\n", logname, __LINE__, \ - __func__, ##args) - -/** - * AVIRT Audio Path configure function type - * Each Audio Path registers this at avirt_audiopath_register time. - * It is then called by the core once AVIRT has been configured - */ -typedef int (*avirt_audiopath_configure)(struct snd_card *card, - struct config_group *stream_group, - unsigned int stream_count); - -/** - * AVIRT Audio Path info - */ -struct avirt_audiopath { - const char *uid; /* Unique identifier */ - const char *name; /* Pretty name */ - unsigned int version[3]; /* Version - Major.Minor.Ext */ - const struct snd_pcm_hardware *hw; /* ALSA PCM HW conf */ - const struct snd_pcm_ops *pcm_ops; /* ALSA PCM op table */ - avirt_audiopath_configure configure; /* Configure callback function */ - - void *context; -}; - -/* - * Audio stream configuration - */ -struct avirt_stream { - char name[MAX_NAME_LEN]; /* Stream name */ - char map[MAX_NAME_LEN]; /* Stream Audio Path mapping */ - unsigned int channels; /* Stream channel count */ - unsigned int device; /* Stream PCM device no. */ - unsigned int direction; /* Stream direction */ - struct snd_pcm *pcm; /* ALSA PCM */ - struct config_item item; /* configfs item reference */ -}; - -/** - * AVIRT core info - */ -struct avirt_coreinfo { - unsigned int version[3]; -}; - -/** - * avirt_audiopath_register - register Audio Path with ALSA virtual driver - * @audiopath: Audio Path to be registered - * @core: ALSA virtual driver core info - * @return: 0 on success or error code otherwise - */ -int avirt_audiopath_register(struct avirt_audiopath *audiopath, - struct avirt_coreinfo **coreinfo); - -/** - * avirt_audiopath_deregister - deregister Audio Path with ALSA virtual driver - * @audiopath: Audio Path to be deregistered - * @return: 0 on success or error code otherwise - */ -int avirt_audiopath_deregister(struct avirt_audiopath *audiopath); - -/** - * avirt_audiopath_get - retrieves the Audio Path by it's UID - * @uid: Unique ID for the Audio Path - * @return: Corresponding Audio Path - */ -struct avirt_audiopath *avirt_audiopath_get(const char *uid); - -/** - * avirt_stream_count - get the stream count for the given direction - * @direction: The direction to get the stream count for - * @return: The stream count - */ -int avirt_stream_count(unsigned int direction); - -/** - * avirt_stream_from_config_item - Convert a config_item to an avirt_stream - * @item: The config_item to convert from - * @return: The item's avirt_stream if successful, NULL otherwise - */ -static inline struct avirt_stream * -avirt_stream_from_config_item(struct config_item *item) -{ - return item ? container_of(item, struct avirt_stream, item) : NULL; -} - -/** - * avirt_pcm_period_elapsed - PCM buffer complete callback - * @substream: pointer to ALSA PCM substream - * - * This should be called from a child Audio Path once it has finished processing - * the PCM buffer - */ -void avirt_pcm_period_elapsed(struct snd_pcm_substream *substream); - -#endif // __AVIRT_CORE_H__ diff --git a/core_internal.h b/core_internal.h index 5bff1c8..f3fcb48 100644 --- a/core_internal.h +++ b/core_internal.h @@ -7,10 +7,10 @@ * core_internal.h - AVIRT internal header */ -#ifndef __AVIRT_CORE_INTERNAL_H__ -#define __AVIRT_CORE_INTERNAL_H__ +#ifndef __SOUND_AVIRT_CORE_H +#define __SOUND_AVIRT_CORE_H -#include +#include #include "utils.h" @@ -64,4 +64,4 @@ struct avirt_stream *__avirt_stream_find_by_device(unsigned int device); */ struct avirt_stream *__avirt_stream_create(const char *name, int direction); -#endif // __AVIRT_CORE_INTERNAL_H__ +#endif /* __SOUND_AVIRT_CORE_H */ diff --git a/dummy/Makefile b/dummy/Makefile index 965bd1a..78579d7 100644 --- a/dummy/Makefile +++ b/dummy/Makefile @@ -3,4 +3,4 @@ obj-$(CONFIG_AVIRT_DUMMYAP) += avirt_dummyap.o $(info $(src)) avirt_dummyap-objs := dummy.o ccflags-y += -Idrivers/staging/ -ccflags-y += -I$(src)/../../ +ccflags-y += -I$(src)/../ diff --git a/dummy/dummy.c b/dummy/dummy.c index 596838d..100972a 100644 --- a/dummy/dummy.c +++ b/dummy/dummy.c @@ -13,7 +13,7 @@ #include #include -#include +#include MODULE_AUTHOR("James O'Shannessy "); MODULE_AUTHOR("Mark Farrugia "); diff --git a/loopback/Makefile b/loopback/Makefile index 0464aba..9d3c606 100644 --- a/loopback/Makefile +++ b/loopback/Makefile @@ -4,4 +4,4 @@ obj-$(CONFIG_AVIRT_LOOPBACKAP) += avirt_loopbackap.o $(info $(src)) avirt_loopbackap-objs := loopback.o ccflags-y += -Idrivers/staging/ -ccflags-y += -I$(src)/../../ +ccflags-y += -I$(src)/../ diff --git a/loopback/loopback.c b/loopback/loopback.c index acddf99..ba9225e 100644 --- a/loopback/loopback.c +++ b/loopback/loopback.c @@ -27,13 +27,12 @@ #include #include #include -#include #include #include #include #include #include -#include +#include MODULE_AUTHOR("Jaroslav Kysela "); MODULE_DESCRIPTION("Loopback Audio Path for AVIRT"); diff --git a/sound/avirt.h b/sound/avirt.h new file mode 100644 index 0000000..5df84fe --- /dev/null +++ b/sound/avirt.h @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * AVIRT - ALSA Virtual Soundcard + * + * Copyright (c) 2010-2018 Fiberdyne Systems Pty Ltd + * + * avirt.h - AVIRT system-level header + */ + +#ifndef __SOUND_AVIRT_H +#define __SOUND_AVIRT_H + +#include +#include +#include + +#define MAX_STREAMS 16 +#define MAX_NAME_LEN 80 + +#define DINFO(logname, fmt, args...) \ + snd_printk(KERN_INFO "AVIRT: %s: " fmt "\n", logname, ##args) + +#define DERROR(logname, fmt, args...) \ + snd_printk(KERN_ERR "AVIRT: %s: " fmt "\n", logname, ##args) + +#define DDEBUG(logname, fmt, args...) \ + snd_printk(KERN_DEBUG "AVIRT: %s: " fmt "\n", logname, ##args) + +/** + * AVIRT Audio Path configure function type + * Each Audio Path registers this at avirt_audiopath_register time. + * It is then called by the core once AVIRT has been configured + */ +typedef int (*avirt_audiopath_configure)(struct snd_card *card, + struct config_group *stream_group, + unsigned int stream_count); + +/** + * AVIRT Audio Path info + */ +struct avirt_audiopath { + const char *uid; /* Unique identifier */ + const char *name; /* Pretty name */ + unsigned int version[3]; /* Version - Major.Minor.Ext */ + const struct snd_pcm_hardware *hw; /* ALSA PCM HW conf */ + const struct snd_pcm_ops *pcm_ops; /* ALSA PCM op table */ + avirt_audiopath_configure configure; /* Configure callback function */ + + void *context; +}; + +/* + * Audio stream configuration + */ +struct avirt_stream { + char name[MAX_NAME_LEN]; /* Stream name */ + char map[MAX_NAME_LEN]; /* Stream Audio Path mapping */ + unsigned int channels; /* Stream channel count */ + unsigned int device; /* Stream PCM device no. */ + unsigned int direction; /* Stream direction */ + struct snd_pcm *pcm; /* ALSA PCM */ + struct config_item item; /* configfs item reference */ +}; + +/** + * AVIRT core info + */ +struct avirt_coreinfo { + unsigned int version[3]; +}; + +/** + * avirt_audiopath_register - register Audio Path with ALSA virtual driver + * @audiopath: Audio Path to be registered + * @core: ALSA virtual driver core info + * @return: 0 on success or error code otherwise + */ +int avirt_audiopath_register(struct avirt_audiopath *audiopath, + struct avirt_coreinfo **coreinfo); + +/** + * avirt_audiopath_deregister - deregister Audio Path with ALSA virtual driver + * @audiopath: Audio Path to be deregistered + * @return: 0 on success or error code otherwise + */ +int avirt_audiopath_deregister(struct avirt_audiopath *audiopath); + +/** + * avirt_audiopath_get - retrieves the Audio Path by it's UID + * @uid: Unique ID for the Audio Path + * @return: Corresponding Audio Path + */ +struct avirt_audiopath *avirt_audiopath_get(const char *uid); + +/** + * avirt_stream_count - get the stream count for the given direction + * @direction: The direction to get the stream count for + * @return: The stream count + */ +int avirt_stream_count(unsigned int direction); + +/** + * avirt_stream_from_config_item - Convert a config_item to an avirt_stream + * @item: The config_item to convert from + * @return: The item's avirt_stream if successful, NULL otherwise + */ +static inline struct avirt_stream * +avirt_stream_from_config_item(struct config_item *item) +{ + return item ? container_of(item, struct avirt_stream, item) : NULL; +} + +/** + * avirt_pcm_period_elapsed - PCM buffer complete callback + * @substream: pointer to ALSA PCM substream + * + * This should be called from a child Audio Path once it has finished processing + * the PCM buffer + */ +void avirt_pcm_period_elapsed(struct snd_pcm_substream *substream); + +#endif // __SOUND_AVIRT_H diff --git a/utils.h b/utils.h index 34e273f..844ee55 100644 --- a/utils.h +++ b/utils.h @@ -1,14 +1,14 @@ // SPDX-License-Identifier: GPL-2.0 /* - * ALSA Virtual Soundcard + * AVIRT - ALSA Virtual Soundcard * - * utils.h - Some useful utilities for AVIRT - * - * Copyright (C) 2010-2018 Fiberdyne Systems Pty Ltd + * Copyright (c) 2010-2018 Fiberdyne Systems Pty Ltd + * + * utils.h - Some useful macros/utils for AVIRT */ -#ifndef __AVIRT_UTILS_H__ -#define __AVIRT_UTILS_H__ +#ifndef __SOUND_AVIRT_UTILS_H +#define __SOUND_AVIRT_UTILS_H #include @@ -46,4 +46,4 @@ } \ } while (0) -#endif +#endif /* __SOUND_AVIRT_UTILS_H */ -- cgit 1.2.3-korg From d66dbf0820e9e7e14a6f723c1ce92b7ac4e0280d Mon Sep 17 00:00:00 2001 From: Mark Farrugia Date: Thu, 25 Oct 2018 17:37:07 +1100 Subject: Refactor all avirt_ symbols to have have snd prefix, as per Linux sound This will aid the eventual migration the the upstream mainline Linux kernel Fix some checkpatch warnings, and other compiler warnings Signed-off-by: Mark Farrugia --- Makefile | 16 ++-- alsa-pcm.c | 70 ++++++++--------- configfs.c | 116 +++++++++++++++------------- core.c | 197 ++++++++++++++++++++++++----------------------- core.h | 33 ++++---- docs/2.Building.md | 2 +- docs/3.Usage.md | 40 +++++----- dummy/Makefile | 4 +- dummy/dummy.c | 22 +++--- loopback/Makefile | 4 +- loopback/loopback.c | 32 ++++---- scripts/load.sh | 6 +- scripts/make-agl.sh | 6 +- scripts/test_configfs.sh | 26 +++---- scripts/unload.sh | 10 +-- sound/avirt.h | 54 ++++++------- 16 files changed, 325 insertions(+), 313 deletions(-) (limited to 'dummy/dummy.c') diff --git a/Makefile b/Makefile index 791a60a..84b8b4d 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_AVIRT) += avirt_core.o -avirt_core-y := core.o -avirt_core-y += alsa-pcm.o -avirt_core-y += configfs.o +obj-$(CONFIG_AVIRT) += snd-avirt-core.o +snd-avirt-core-y := core.o +snd-avirt-core-y += alsa-pcm.o +snd-avirt-core-y += configfs.o ifeq ($(CONFIG_AVIRT_BUILDLOCAL),) CCFLAGS_AVIRT := "drivers/staging/" @@ -13,8 +13,8 @@ endif ccflags-y += -I${CCFLAGS_AVIRT} $(info $(KERNELRELEASE)) -obj-$(CONFIG_AVIRT_DUMMYAP) += dummy/ -obj-$(CONFIG_AVIRT_LOOPBACKAP) += loopback/ +obj-$(CONFIG_AVIRT_AP_DUMMY) += dummy/ +obj-$(CONFIG_AVIRT_AP_LOOPBACK) += loopback/ ### # For out-of-tree building @@ -29,8 +29,8 @@ endif all: CONFIG_AVIRT=m CONFIG_AVIRT_BUILDLOCAL=y \ - CONFIG_AVIRT_DUMMYAP=m \ - CONFIG_AVIRT_LOOPBACKAP=m \ + CONFIG_AVIRT_AP_DUMMY=m \ + CONFIG_AVIRT_AP_LOOPBACK=m \ make -C $(KERNEL_SRC) M=$(PWD) clean: diff --git a/alsa-pcm.c b/alsa-pcm.c index 4d7b549..603c096 100644 --- a/alsa-pcm.c +++ b/alsa-pcm.c @@ -3,7 +3,7 @@ * AVIRT - ALSA Virtual Soundcard * * Copyright (c) 2010-2018 Fiberdyne Systems Pty Ltd - * + * * alsa-pcm.c - AVIRT PCM interface */ @@ -15,24 +15,24 @@ #define D_PRINTK(fmt, args...) DDEBUG(D_LOGNAME, fmt, ##args) #define D_ERRORK(fmt, args...) DERROR(D_LOGNAME, fmt, ##args) -#define DO_AUDIOPATH_CB(ap, callback, substream, ...) \ - (((ap)->pcm_ops->callback) ? \ - (ap)->pcm_ops->callback((substream), ##__VA_ARGS__) : \ +#define DO_AUDIOPATH_CB(ap, callback, substream, ...) \ + (((ap)->pcm_ops->callback) ? \ + (ap)->pcm_ops->callback((substream), ##__VA_ARGS__) : \ 0) /** - * avirt_pcm_period_elapsed - PCM buffer complete callback + * snd_avirt_pcm_period_elapsed - PCM buffer complete callback * @substreamid: pointer to ALSA PCM substream * - * This should be called from a child Audio Path once it has finished processing - * the pcm buffer + * This should be called from a child Audio Path once it has finished + * processing the pcm buffer */ -void avirt_pcm_period_elapsed(struct snd_pcm_substream *substream) +void snd_avirt_pcm_period_elapsed(struct snd_pcm_substream *substream) { // Notify ALSA middle layer of the elapsed period boundary snd_pcm_period_elapsed(substream); } -EXPORT_SYMBOL_GPL(avirt_pcm_period_elapsed); +EXPORT_SYMBOL_GPL(snd_avirt_pcm_period_elapsed); /******************************************************************************* * ALSA PCM Callbacks @@ -41,20 +41,20 @@ EXPORT_SYMBOL_GPL(avirt_pcm_period_elapsed); * pcm_open - Implements 'open' callback for PCM middle layer * @substream: pointer to ALSA PCM substream * - * This is called when an ALSA PCM substream is opened. The substream device is - * configured here. + * This is called when an ALSA PCM substream is opened. The substream device + * is configured here. * * Returns 0 on success or error code otherwise. */ static int pcm_open(struct snd_pcm_substream *substream) { - struct avirt_audiopath *audiopath; - struct avirt_stream *stream; + struct snd_avirt_audiopath *audiopath; + struct snd_avirt_stream *stream; struct snd_pcm_hardware *hw; unsigned int chans = 0; - stream = __avirt_stream_find_by_device(substream->pcm->device); - audiopath = avirt_audiopath_get(stream->map); + stream = snd_avirt_stream_find_by_device(substream->pcm->device); + audiopath = snd_avirt_audiopath_get(stream->map); CHK_NULL_V(audiopath, "Cannot find Audio Path uid: '%s'!", stream->map); substream->private_data = audiopath; @@ -62,7 +62,7 @@ static int pcm_open(struct snd_pcm_substream *substream) hw = &substream->runtime->hw; memcpy(hw, audiopath->hw, sizeof(struct snd_pcm_hardware)); - stream = __avirt_stream_find_by_device(substream->pcm->device); + stream = snd_avirt_stream_find_by_device(substream->pcm->device); if (IS_ERR_VALUE(stream) || !stream) return PTR_ERR(stream); @@ -87,7 +87,7 @@ static int pcm_close(struct snd_pcm_substream *substream) { // Do additional Audio Path 'close' callback return DO_AUDIOPATH_CB( - ((struct avirt_audiopath *)substream->private_data), close, + ((struct snd_avirt_audiopath *)substream->private_data), close, substream); } @@ -106,10 +106,10 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, { int retval; size_t bufsz; - struct avirt_audiopath *audiopath; - struct avirt_stream *stream; + struct snd_avirt_audiopath *audiopath; + struct snd_avirt_stream *stream; - stream = __avirt_stream_find_by_device(substream->pcm->device); + stream = snd_avirt_stream_find_by_device(substream->pcm->device); if (IS_ERR_VALUE(stream) || !stream) return PTR_ERR(stream); @@ -120,7 +120,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - audiopath = ((struct avirt_audiopath *)substream->private_data); + audiopath = ((struct snd_avirt_audiopath *)substream->private_data); bufsz = params_buffer_bytes(hw_params) * audiopath->hw->periods_max; retval = snd_pcm_lib_alloc_vmalloc_buffer(substream, bufsz); @@ -145,8 +145,8 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) // Do additional Audio Path 'hw_free' callback err = DO_AUDIOPATH_CB( - ((struct avirt_audiopath *)substream->private_data), hw_free, - substream); + ((struct snd_avirt_audiopath *)substream->private_data), + hw_free, substream); return snd_pcm_lib_free_vmalloc_buffer(substream); } @@ -165,8 +165,8 @@ static int pcm_prepare(struct snd_pcm_substream *substream) { // Do additional Audio Path 'prepare' callback return DO_AUDIOPATH_CB( - ((struct avirt_audiopath *)substream->private_data), prepare, - substream); + ((struct snd_avirt_audiopath *)substream->private_data), + prepare, substream); } /** @@ -194,8 +194,8 @@ static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) // Do additional Audio Path 'trigger' callback return DO_AUDIOPATH_CB( - ((struct avirt_audiopath *)substream->private_data), trigger, - substream, cmd); + ((struct snd_avirt_audiopath *)substream->private_data), + trigger, substream, cmd); } /** @@ -212,8 +212,8 @@ static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream) { // Do additional Audio Path 'pointer' callback return DO_AUDIOPATH_CB( - ((struct avirt_audiopath *)substream->private_data), pointer, - substream); + ((struct snd_avirt_audiopath *)substream->private_data), + pointer, substream); } /** @@ -235,7 +235,7 @@ static int pcm_get_time_info( struct snd_pcm_audio_tstamp_report *audio_tstamp_report) { return DO_AUDIOPATH_CB( - ((struct avirt_audiopath *)substream->private_data), + ((struct snd_avirt_audiopath *)substream->private_data), get_time_info, substream, system_ts, audio_ts, audio_tstamp_config, audio_tstamp_report); } @@ -265,8 +265,8 @@ static int pcm_copy_user(struct snd_pcm_substream *substream, int channel, // Do additional Audio Path 'copy_user' callback return DO_AUDIOPATH_CB( - ((struct avirt_audiopath *)substream->private_data), copy_user, - substream, channel, pos, src, count); + ((struct snd_avirt_audiopath *)substream->private_data), + copy_user, substream, channel, pos, src, count); } /** @@ -286,7 +286,7 @@ static int pcm_copy_kernel(struct snd_pcm_substream *substream, int channel, unsigned long pos, void *buf, unsigned long count) { return DO_AUDIOPATH_CB( - ((struct avirt_audiopath *)substream->private_data), + ((struct snd_avirt_audiopath *)substream->private_data), copy_kernel, substream, channel, pos, buf, count); } @@ -302,7 +302,7 @@ static int pcm_copy_kernel(struct snd_pcm_substream *substream, int channel, static int pcm_ack(struct snd_pcm_substream *substream) { return DO_AUDIOPATH_CB( - ((struct avirt_audiopath *)substream->private_data), ack, + ((struct snd_avirt_audiopath *)substream->private_data), ack, substream); } @@ -310,7 +310,7 @@ static int pcm_silence(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count) { return DO_AUDIOPATH_CB( - ((struct avirt_audiopath *)substream->private_data), + ((struct snd_avirt_audiopath *)substream->private_data), fill_silence, substream, channel, pos, count); } diff --git a/configfs.c b/configfs.c index 1a7e7c5..12e95a5 100644 --- a/configfs.c +++ b/configfs.c @@ -1,9 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 -/* +/* * AVIRT - ALSA Virtual Soundcard * * Copyright (c) 2010-2018 Fiberdyne Systems Pty Ltd - * + * * configfs.c - AVIRT configfs support */ @@ -17,54 +17,61 @@ #define D_PRINTK(fmt, args...) DDEBUG(D_LOGNAME, fmt, ##args) #define D_ERRORK(fmt, args...) DERROR(D_LOGNAME, fmt, ##args) -static ssize_t cfg_avirt_stream_direction_show(struct config_item *item, - char *page) +static ssize_t cfg_snd_avirt_stream_direction_show(struct config_item *item, + char *page) { ssize_t count; - struct avirt_stream *stream = avirt_stream_from_config_item(item); + struct snd_avirt_stream *stream = + snd_avirt_stream_from_config_item(item); count = sprintf(page, "%d\n", stream->direction); return count; } -CONFIGFS_ATTR_RO(cfg_avirt_stream_, direction); +CONFIGFS_ATTR_RO(cfg_snd_avirt_stream_, direction); -static ssize_t cfg_avirt_stream_map_show(struct config_item *item, char *page) +static ssize_t cfg_snd_avirt_stream_map_show(struct config_item *item, + char *page) { - struct avirt_stream *stream = avirt_stream_from_config_item(item); + struct snd_avirt_stream *stream = + snd_avirt_stream_from_config_item(item); return sprintf(page, "%s\n", stream->map); } -static ssize_t cfg_avirt_stream_map_store(struct config_item *item, - const char *page, size_t count) +static ssize_t cfg_snd_avirt_stream_map_store(struct config_item *item, + const char *page, size_t count) { char *split; - struct avirt_stream *stream = avirt_stream_from_config_item(item); + struct snd_avirt_stream *stream = + snd_avirt_stream_from_config_item(item); split = strsep((char **)&page, "\n"); memcpy(stream->map, (char *)split, count); return count; } -CONFIGFS_ATTR(cfg_avirt_stream_, map); +CONFIGFS_ATTR(cfg_snd_avirt_stream_, map); -static ssize_t cfg_avirt_stream_channels_show(struct config_item *item, - char *page) +static ssize_t cfg_snd_avirt_stream_channels_show(struct config_item *item, + char *page) { ssize_t count; - struct avirt_stream *stream = avirt_stream_from_config_item(item); + struct snd_avirt_stream *stream = + snd_avirt_stream_from_config_item(item); count = sprintf(page, "%d\n", stream->channels); return count; } -static ssize_t cfg_avirt_stream_channels_store(struct config_item *item, - const char *page, size_t count) +static ssize_t cfg_snd_avirt_stream_channels_store(struct config_item *item, + const char *page, + size_t count) { int err; - struct avirt_stream *stream = avirt_stream_from_config_item(item); + struct snd_avirt_stream *stream = + snd_avirt_stream_from_config_item(item); unsigned long tmp; char *p = (char *)page; @@ -79,37 +86,37 @@ static ssize_t cfg_avirt_stream_channels_store(struct config_item *item, return count; } -CONFIGFS_ATTR(cfg_avirt_stream_, channels); +CONFIGFS_ATTR(cfg_snd_avirt_stream_, channels); -static struct configfs_attribute *cfg_avirt_stream_attrs[] = { - &cfg_avirt_stream_attr_channels, - &cfg_avirt_stream_attr_map, - &cfg_avirt_stream_attr_direction, +static struct configfs_attribute *cfg_snd_avirt_stream_attrs[] = { + &cfg_snd_avirt_stream_attr_channels, + &cfg_snd_avirt_stream_attr_map, + &cfg_snd_avirt_stream_attr_direction, NULL, }; -static void cfg_avirt_stream_release(struct config_item *item) +static void cfg_snd_avirt_stream_release(struct config_item *item) { D_INFOK("item->name:%s", item->ci_namebuf); - kfree(avirt_stream_from_config_item(item)); + kfree(snd_avirt_stream_from_config_item(item)); } -static struct configfs_item_operations cfg_avirt_stream_ops = { - .release = cfg_avirt_stream_release, +static struct configfs_item_operations cfg_snd_avirt_stream_ops = { + .release = cfg_snd_avirt_stream_release, }; -static struct config_item_type cfg_avirt_stream_type = { - .ct_item_ops = &cfg_avirt_stream_ops, - .ct_attrs = cfg_avirt_stream_attrs, +static struct config_item_type cfg_snd_avirt_stream_type = { + .ct_item_ops = &cfg_snd_avirt_stream_ops, + .ct_attrs = cfg_snd_avirt_stream_attrs, .ct_owner = THIS_MODULE, }; static struct config_item * - cfg_avirt_stream_make_item(struct config_group *group, const char *name) +cfg_snd_avirt_stream_make_item(struct config_group *group, const char *name) { char *split; int direction; - struct avirt_stream *stream; + struct snd_avirt_stream *stream; // Get prefix (playback_ or capture_) split = strsep((char **)&name, "_"); @@ -130,24 +137,25 @@ static struct config_item * // Get stream name, and create PCM for stream split = strsep((char **)&name, "\n"); - stream = __avirt_stream_create(split, direction); + stream = snd_avirt_stream_create(split, direction); if (IS_ERR(stream)) return ERR_PTR(PTR_ERR(stream)); - config_item_init_type_name(&stream->item, name, &cfg_avirt_stream_type); + config_item_init_type_name(&stream->item, name, + &cfg_snd_avirt_stream_type); return &stream->item; } -static ssize_t cfg_avirt_stream_group_sealed_show(struct config_item *item, - char *page) +static ssize_t cfg_snd_avirt_stream_group_sealed_show(struct config_item *item, + char *page) { - return snprintf(page, PAGE_SIZE, "%d\n", __avirt_streams_sealed()); + return snprintf(page, PAGE_SIZE, "%d\n", snd_avirt_streams_sealed()); } -static ssize_t cfg_avirt_stream_group_sealed_store(struct config_item *item, - const char *page, - size_t count) +static ssize_t cfg_snd_avirt_stream_group_sealed_store(struct config_item *item, + const char *page, + size_t count) { unsigned long tmp; char *p = (char *)page; @@ -159,24 +167,24 @@ static ssize_t cfg_avirt_stream_group_sealed_store(struct config_item *item, return -ERANGE; } - __avirt_streams_seal(); + snd_avirt_streams_seal(); return count; } -CONFIGFS_ATTR(cfg_avirt_stream_group_, sealed); +CONFIGFS_ATTR(cfg_snd_avirt_stream_group_, sealed); -static struct configfs_attribute *cfg_avirt_stream_group_attrs[] = { - &cfg_avirt_stream_group_attr_sealed, +static struct configfs_attribute *cfg_snd_avirt_stream_group_attrs[] = { + &cfg_snd_avirt_stream_group_attr_sealed, NULL, }; -static struct configfs_group_operations cfg_avirt_stream_group_ops = { - .make_item = cfg_avirt_stream_make_item +static struct configfs_group_operations cfg_snd_avirt_stream_group_ops = { + .make_item = cfg_snd_avirt_stream_make_item }; static struct config_item_type cfg_stream_group_type = { - .ct_group_ops = &cfg_avirt_stream_group_ops, - .ct_attrs = cfg_avirt_stream_group_attrs, + .ct_group_ops = &cfg_snd_avirt_stream_group_ops, + .ct_attrs = cfg_snd_avirt_stream_group_attrs, .ct_owner = THIS_MODULE }; @@ -185,17 +193,15 @@ static struct config_item_type cfg_avirt_group_type = { }; static struct configfs_subsystem cfg_subsys = { - .su_group = - { - .cg_item = - { - .ci_namebuf = "avirt", + .su_group = { + .cg_item = { + .ci_namebuf = "snd-avirt", .ci_type = &cfg_avirt_group_type, }, }, }; -int __init __avirt_configfs_init(struct avirt_core *core) +int __init snd_avirt_configfs_init(struct snd_avirt_core *core) { int err; @@ -222,7 +228,7 @@ exit_configfs: return err; } -void __exit __avirt_configfs_exit(struct avirt_core *core) +void __exit snd_avirt_configfs_exit(struct snd_avirt_core *core) { configfs_unregister_default_group(core->stream_group); configfs_unregister_subsystem(&cfg_subsys); diff --git a/core.c b/core.c index 08381e5..aacc0a1 100644 --- a/core.c +++ b/core.c @@ -3,7 +3,7 @@ * AVIRT - ALSA Virtual Soundcard * * Copyright (c) 2010-2018 Fiberdyne Systems Pty Ltd - * + * * core.c - AVIRT core internals */ @@ -27,44 +27,43 @@ MODULE_LICENSE("GPL v2"); #define SND_AVIRTUAL_DRIVER "snd_avirt" -extern struct snd_pcm_ops pcm_ops; - -static struct avirt_core core = { +static struct snd_avirt_core core = { .stream_count = 0, .streams_sealed = false, }; -struct avirt_coreinfo coreinfo = { - .version = {0, 0, 1}, +struct snd_avirt_coreinfo coreinfo = { + .version = { 0, 0, 1 }, }; static LIST_HEAD(audiopath_list); -struct avirt_audiopath_obj { +struct snd_avirt_audiopath_obj { struct kobject kobj; struct list_head list; - struct avirt_audiopath *path; + struct snd_avirt_audiopath *path; }; -static struct kset *avirt_audiopath_kset; +static struct kset *snd_avirt_audiopath_kset; static struct kobject *kobj; -#define to_audiopath_obj(d) container_of(d, struct avirt_audiopath_obj, kobj) -#define to_audiopath_attr(a) \ - container_of(a, struct avirt_audiopath_attribute, attr) +#define to_audiopath_obj(d) \ + container_of(d, struct snd_avirt_audiopath_obj, kobj) +#define to_audiopath_attr(a) \ + container_of(a, struct snd_avirt_audiopath_attribute, attr) /** - * struct avirt_audiopath_attribute - access the attributes of Audio Path + * struct snd_avirt_audiopath_attribute - access the attributes of Audio Path * @attr: attributes of an Audio Path * @show: pointer to the show function * @store: pointer to the store function */ -struct avirt_audiopath_attribute { +struct snd_avirt_audiopath_attribute { struct attribute attr; - ssize_t (*show)(struct avirt_audiopath_obj *d, - struct avirt_audiopath_attribute *attr, char *buf); - ssize_t (*store)(struct avirt_audiopath_obj *d, - struct avirt_audiopath_attribute *attr, + ssize_t (*show)(struct snd_avirt_audiopath_obj *d, + struct snd_avirt_audiopath_attribute *attr, char *buf); + ssize_t (*store)(struct snd_avirt_audiopath_obj *d, + struct snd_avirt_audiopath_attribute *attr, const char *buf, size_t count); }; @@ -77,8 +76,8 @@ struct avirt_audiopath_attribute { static ssize_t audiopath_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) { - struct avirt_audiopath_attribute *audiopath_attr; - struct avirt_audiopath_obj *audiopath_obj; + struct snd_avirt_audiopath_attribute *audiopath_attr; + struct snd_avirt_audiopath_obj *audiopath_obj; audiopath_attr = to_audiopath_attr(attr); audiopath_obj = to_audiopath_obj(kobj); @@ -100,8 +99,8 @@ static ssize_t audiopath_attr_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t len) { - struct avirt_audiopath_attribute *audiopath_attr; - struct avirt_audiopath_obj *audiopath_obj; + struct snd_avirt_audiopath_attribute *audiopath_attr; + struct snd_avirt_audiopath_obj *audiopath_obj; audiopath_attr = to_audiopath_attr(attr); audiopath_obj = to_audiopath_obj(kobj); @@ -111,84 +110,88 @@ static ssize_t audiopath_attr_store(struct kobject *kobj, return audiopath_attr->store(audiopath_obj, audiopath_attr, buf, len); } -static const struct sysfs_ops avirt_audiopath_sysfs_ops = { +static const struct sysfs_ops snd_avirt_audiopath_sysfs_ops = { .show = audiopath_attr_show, .store = audiopath_attr_store, }; /** - * avirt_audiopath_release - Audio Path release function + * snd_avirt_audiopath_release - Audio Path release function * @kobj: pointer to Audio Paths's kobject */ -static void avirt_audiopath_release(struct kobject *kobj) +static void snd_avirt_audiopath_release(struct kobject *kobj) { - struct avirt_audiopath_obj *audiopath_obj = to_audiopath_obj(kobj); + struct snd_avirt_audiopath_obj *audiopath_obj = to_audiopath_obj(kobj); kfree(audiopath_obj); } -static ssize_t audiopath_name_show(struct avirt_audiopath_obj *audiopath_obj, - struct avirt_audiopath_attribute *attr, - char *buf) +static ssize_t + audiopath_name_show(struct snd_avirt_audiopath_obj *audiopath_obj, + struct snd_avirt_audiopath_attribute *attr, + char *buf) { return sprintf(buf, "%s\n", audiopath_obj->path->name); } -static ssize_t audiopath_version_show(struct avirt_audiopath_obj *audiopath_obj, - struct avirt_audiopath_attribute *attr, - char *buf) +static ssize_t + audiopath_version_show(struct snd_avirt_audiopath_obj *audiopath_obj, + struct snd_avirt_audiopath_attribute *attr, + char *buf) { - struct avirt_audiopath *audiopath = audiopath_obj->path; + struct snd_avirt_audiopath *audiopath = audiopath_obj->path; return sprintf(buf, "%d.%d.%d\n", audiopath->version[0], audiopath->version[1], audiopath->version[2]); } -static struct avirt_audiopath_attribute avirt_audiopath_attrs[] = { +static struct snd_avirt_audiopath_attribute snd_avirt_audiopath_attrs[] = { __ATTR_RO(audiopath_name), __ATTR_RO(audiopath_version), }; -static struct attribute *avirt_audiopath_def_attrs[] = { - &avirt_audiopath_attrs[0].attr, - &avirt_audiopath_attrs[1].attr, +static struct attribute *snd_avirt_audiopath_def_attrs[] = { + &snd_avirt_audiopath_attrs[0].attr, + &snd_avirt_audiopath_attrs[1].attr, NULL, }; -static struct kobj_type avirt_audiopath_ktype = { - .sysfs_ops = &avirt_audiopath_sysfs_ops, - .release = avirt_audiopath_release, - .default_attrs = avirt_audiopath_def_attrs, +static struct kobj_type snd_avirt_audiopath_ktype = { + .sysfs_ops = &snd_avirt_audiopath_sysfs_ops, + .release = snd_avirt_audiopath_release, + .default_attrs = snd_avirt_audiopath_def_attrs, }; /** - * create_avirt_audiopath_obj - creates an Audio Path object + * create_snd_avirt_audiopath_obj - creates an Audio Path object * @uid: Unique ID of the Audio Path * * This creates an Audio Path object and assigns the kset and registers * it with sysfs. * @return: Pointer to the Audio Path object or NULL if it failed. */ -static struct avirt_audiopath_obj *create_avirt_audiopath_obj(const char *uid) +static struct snd_avirt_audiopath_obj * + create_snd_avirt_audiopath_obj(const char *uid) { - struct avirt_audiopath_obj *avirt_audiopath; + struct snd_avirt_audiopath_obj *snd_avirt_audiopath; int retval; - avirt_audiopath = kzalloc(sizeof(*avirt_audiopath), GFP_KERNEL); - if (!avirt_audiopath) + snd_avirt_audiopath = kzalloc(sizeof(*snd_avirt_audiopath), GFP_KERNEL); + if (!snd_avirt_audiopath) return NULL; - avirt_audiopath->kobj.kset = avirt_audiopath_kset; - retval = kobject_init_and_add(&avirt_audiopath->kobj, - &avirt_audiopath_ktype, kobj, "%s", uid); + snd_avirt_audiopath->kobj.kset = snd_avirt_audiopath_kset; + retval = kobject_init_and_add(&snd_avirt_audiopath->kobj, + &snd_avirt_audiopath_ktype, kobj, "%s", + uid); if (retval) { - kobject_put(&avirt_audiopath->kobj); + kobject_put(&snd_avirt_audiopath->kobj); return NULL; } - kobject_uevent(&avirt_audiopath->kobj, KOBJ_ADD); - return avirt_audiopath; + kobject_uevent(&snd_avirt_audiopath->kobj, KOBJ_ADD); + return snd_avirt_audiopath; } -static struct snd_pcm *pcm_create(struct avirt_stream *stream) +static struct snd_pcm *pcm_create(struct snd_avirt_stream *stream) { bool playback = false, capture = false; struct snd_pcm *pcm; @@ -224,25 +227,24 @@ static struct snd_pcm *pcm_create(struct avirt_stream *stream) } /** - * destroy_avirt_audiopath_obj - destroys an Audio Path object + * destroy_snd_avirt_audiopath_obj - destroys an Audio Path object * @name: the Audio Path object */ -static void destroy_avirt_audiopath_obj(struct avirt_audiopath_obj *p) +static void destroy_snd_avirt_audiopath_obj(struct snd_avirt_audiopath_obj *p) { kobject_put(&p->kobj); } /** - * avirt_audiopath_get - retrieves the Audio Path by its UID + * snd_avirt_audiopath_get - retrieves the Audio Path by its UID * @uid: Unique ID for the Audio Path * @return: Corresponding Audio Path */ -struct avirt_audiopath *avirt_audiopath_get(const char *uid) +struct snd_avirt_audiopath *snd_avirt_audiopath_get(const char *uid) { - struct avirt_audiopath_obj *ap_obj; + struct snd_avirt_audiopath_obj *ap_obj; - list_for_each_entry(ap_obj, &audiopath_list, list) - { + list_for_each_entry(ap_obj, &audiopath_list, list) { // pr_info("get_ap %s\n", ap_obj->path->uid); if (!strcmp(ap_obj->path->uid, uid)) return ap_obj->path; @@ -252,22 +254,22 @@ struct avirt_audiopath *avirt_audiopath_get(const char *uid) } /** - * avirt_audiopath_register - register Audio Path with ALSA virtual driver + * snd_avirt_audiopath_register - register Audio Path with AVIRT * @audiopath: Audio Path to be registered * @core: ALSA virtual driver core info * @return: 0 on success or error code otherwise */ -int avirt_audiopath_register(struct avirt_audiopath *audiopath, - struct avirt_coreinfo **info) +int snd_avirt_audiopath_register(struct snd_avirt_audiopath *audiopath, + struct snd_avirt_coreinfo **info) { - struct avirt_audiopath_obj *audiopath_obj; + struct snd_avirt_audiopath_obj *audiopath_obj; if (!audiopath) { D_ERRORK("Audio Path is NULL!"); return -EINVAL; } - audiopath_obj = create_avirt_audiopath_obj(audiopath->uid); + audiopath_obj = create_snd_avirt_audiopath_obj(audiopath->uid); if (!audiopath_obj) { D_INFOK("Failed to alloc driver object"); return -ENOMEM; @@ -288,16 +290,16 @@ int avirt_audiopath_register(struct avirt_audiopath *audiopath, return 0; } -EXPORT_SYMBOL_GPL(avirt_audiopath_register); +EXPORT_SYMBOL_GPL(snd_avirt_audiopath_register); /** - * avirt_audiopath_deregister - deregister Audio Path with ALSA virtual driver + * snd_avirt_audiopath_deregister - deregister Audio Path with AVIRT * @audiopath: Audio Path to be deregistered * @return: 0 on success or error code otherwise */ -int avirt_audiopath_deregister(struct avirt_audiopath *audiopath) +int snd_avirt_audiopath_deregister(struct snd_avirt_audiopath *audiopath) { - struct avirt_audiopath_obj *audiopath_obj; + struct snd_avirt_audiopath_obj *audiopath_obj; // Check if audio path is registered if (!audiopath) { @@ -312,32 +314,31 @@ int avirt_audiopath_deregister(struct avirt_audiopath *audiopath) } list_del(&audiopath_obj->list); - destroy_avirt_audiopath_obj(audiopath_obj); + destroy_snd_avirt_audiopath_obj(audiopath_obj); D_INFOK("Deregistered Audio Path %s", audiopath->uid); return 0; } -EXPORT_SYMBOL_GPL(avirt_audiopath_deregister); +EXPORT_SYMBOL_GPL(snd_avirt_audiopath_deregister); /** - * avirt_stream_count - get the stream count for the given direction + * snd_avirt_stream_count - get the stream count for the given direction * @direction: The direction to get the stream count for * @return: The stream count */ -int avirt_stream_count(unsigned int direction) +int snd_avirt_stream_count(unsigned int direction) { struct list_head *entry; struct config_item *item; - struct avirt_stream *stream; + struct snd_avirt_stream *stream; unsigned int count = 0; if (direction > 1) return -ERANGE; - list_for_each(entry, &core.stream_group->cg_children) - { + list_for_each(entry, &core.stream_group->cg_children) { item = container_of(entry, struct config_item, ci_entry); - stream = avirt_stream_from_config_item(item); + stream = snd_avirt_stream_from_config_item(item); if (!stream) return -EFAULT; if (stream->direction == direction) @@ -346,18 +347,19 @@ int avirt_stream_count(unsigned int direction) return count; } -EXPORT_SYMBOL_GPL(avirt_stream_count); +EXPORT_SYMBOL_GPL(snd_avirt_stream_count); /** - * __avirt_stream_create - Create audio stream, including it's ALSA PCM device + * snd_avirt_stream_create - Create audio stream, including it's ALSA PCM device * @name: The name designated to the audio stream * @direction: The PCM direction (SNDRV_PCM_STREAM_PLAYBACK or * SNDRV_PCM_STREAM_CAPTURE) * @return: The newly created audio stream if successful, or an error pointer */ -struct avirt_stream *__avirt_stream_create(const char *name, int direction) +struct snd_avirt_stream *snd_avirt_stream_create(const char *name, + int direction) { - struct avirt_stream *stream; + struct snd_avirt_stream *stream; stream = kzalloc(sizeof(*stream), GFP_KERNEL); if (!stream) @@ -374,11 +376,11 @@ struct avirt_stream *__avirt_stream_create(const char *name, int direction) return stream; } -int __avirt_streams_seal(void) +int snd_avirt_streams_seal(void) { int err = 0; - struct avirt_audiopath_obj *ap_obj; - struct avirt_stream *stream; + struct snd_avirt_audiopath_obj *ap_obj; + struct snd_avirt_stream *stream; struct config_item *item; struct list_head *entry; @@ -387,9 +389,9 @@ int __avirt_streams_seal(void) return -1; } - list_for_each (entry, &core.stream_group->cg_children) { + list_for_each(entry, &core.stream_group->cg_children) { item = container_of(entry, struct config_item, ci_entry); - stream = avirt_stream_from_config_item(item); + stream = snd_avirt_stream_from_config_item(item); if (!stream) return -EFAULT; stream->pcm = pcm_create(stream); @@ -397,7 +399,7 @@ int __avirt_streams_seal(void) return (PTR_ERR(stream->pcm)); } - list_for_each_entry (ap_obj, &audiopath_list, list) { + list_for_each_entry(ap_obj, &audiopath_list, list) { D_INFOK("configure() AP uid: %s", ap_obj->path->uid); ap_obj->path->configure(core.card, core.stream_group, core.stream_count); @@ -414,14 +416,14 @@ int __avirt_streams_seal(void) return err; } -bool __avirt_streams_sealed(void) +bool snd_avirt_streams_sealed(void) { return core.streams_sealed; } -struct avirt_stream *__avirt_stream_find_by_device(unsigned int device) +struct snd_avirt_stream *snd_avirt_stream_find_by_device(unsigned int device) { - struct avirt_stream *stream; + struct snd_avirt_stream *stream; struct config_item *item; struct list_head *entry; @@ -430,10 +432,9 @@ struct avirt_stream *__avirt_stream_find_by_device(unsigned int device) return ERR_PTR(-EINVAL); } - list_for_each(entry, &core.stream_group->cg_children) - { + list_for_each(entry, &core.stream_group->cg_children) { item = container_of(entry, struct config_item, ci_entry); - stream = avirt_stream_from_config_item(item); + stream = snd_avirt_stream_from_config_item(item); if (!stream) return ERR_PTR(-EFAULT); if (stream->device == device) @@ -478,14 +479,14 @@ static int __init core_init(void) strncpy(core.card->longname, "A virtual sound card driver for ALSA", 80); - avirt_audiopath_kset = + snd_avirt_audiopath_kset = kset_create_and_add("audiopaths", NULL, &core.dev->kobj); - if (!avirt_audiopath_kset) { + if (!snd_avirt_audiopath_kset) { err = -ENOMEM; goto exit_snd_card; } - err = __avirt_configfs_init(&core); + err = snd_avirt_configfs_init(&core); if (err < 0) goto exit_snd_card; @@ -506,9 +507,9 @@ exit_class: */ static void __exit core_exit(void) { - __avirt_configfs_exit(&core); + snd_avirt_configfs_exit(&core); - kset_unregister(avirt_audiopath_kset); + kset_unregister(snd_avirt_audiopath_kset); snd_card_free(core.card); device_destroy(core.avirt_class, 0); class_destroy(core.avirt_class); diff --git a/core.h b/core.h index ca47067..735df65 100644 --- a/core.h +++ b/core.h @@ -14,7 +14,9 @@ #include "utils.h" -struct avirt_core { +extern struct snd_pcm_ops pcm_ops; + +struct snd_avirt_core { struct snd_card *card; struct device *dev; struct class *avirt_class; @@ -24,44 +26,45 @@ struct avirt_core { }; /** - * __avirt_configfs_init - Initialise the configfs system - * @core: The avirt_core pointer + * snd_avirt_configfs_init - Initialise the configfs system + * @core: The snd_avirt_core pointer * @return: 0 on success, negative ERRNO on failure */ -int __init __avirt_configfs_init(struct avirt_core *core); +int __init snd_avirt_configfs_init(struct snd_avirt_core *core); /** - * __avirt_configfs_exit - Clean up and exit the configfs system - * @core: The avirt_core pointer + * snd_avirt_configfs_exit - Clean up and exit the configfs system + * @core: The snd_avirt_core pointer */ -void __exit __avirt_configfs_exit(struct avirt_core *core); +void __exit snd_avirt_configfs_exit(struct snd_avirt_core *core); /** - * __avirt_streams_seal - Register the sound card to user space + * snd_avirt_streams_seal - Register the sound card to user space * @return: 0 on success, negative ERRNO on failure */ -int __avirt_streams_seal(void); +int snd_avirt_streams_seal(void); /** - * __avirt_streams_sealed - Check whether the streams have been sealed or not + * snd_avirt_streams_sealed - Check if the streams have been sealed or not * @return: true if sealed, false otherwise */ -bool __avirt_streams_sealed(void); +bool snd_avirt_streams_sealed(void); /** - * __avirt_stream_find_by_device - Get audio stream from device number + * snd_avirt_stream_find_by_device - Get audio stream from device number * @device: The PCM device number corresponding to the desired stream * @return: The audio stream if found, or an error pointer otherwise */ -struct avirt_stream *__avirt_stream_find_by_device(unsigned int device); +struct snd_avirt_stream *snd_avirt_stream_find_by_device(unsigned int device); /** - * __avirt_stream_create - Create audio stream, including it's ALSA PCM device + * snd_avirt_stream_create - Create audio stream, including it's ALSA PCM device * @name: The name designated to the audio stream * @direction: The PCM direction (SNDRV_PCM_STREAM_PLAYBACK or * SNDRV_PCM_STREAM_CAPTURE) * @return: The newly created audio stream if successful, or an error pointer */ -struct avirt_stream *__avirt_stream_create(const char *name, int direction); +struct snd_avirt_stream *snd_avirt_stream_create(const char *name, + int direction); #endif /* __SOUND_AVIRT_CORE_H */ diff --git a/docs/2.Building.md b/docs/2.Building.md index 3e42746..5fd9d23 100644 --- a/docs/2.Building.md +++ b/docs/2.Building.md @@ -28,7 +28,7 @@ $ make or ```sh -$ CONFIG_AVIRT=m CONFIG_AVIRT_BUILDLOCAL=y CONFIG_AVIRT_DUMMYAP=m make -C /lib/modules/$(uname -r)/build/ M=$(pwd) +$ CONFIG_AVIRT=m CONFIG_AVIRT_BUILDLOCAL=y CONFIG_AVIRT_AP_DUMMY=m CONFIG_AVIRT_AP_LOOPBACK=m make -C /lib/modules/$(uname -r)/build/ M=$(pwd) ``` The latter is executed internally with the make file. diff --git a/docs/3.Usage.md b/docs/3.Usage.md index d65d50d..f535a07 100644 --- a/docs/3.Usage.md +++ b/docs/3.Usage.md @@ -18,9 +18,9 @@ As root, load the required `avirt_core.ko` and subsequent audio path. As an example, the Dummy Audiopath is being loaded here. ```sh -insmod avirt_core.ko -insmod dummy/avirt_dummyap.ko -insmod loopback/avirt_loopbackap.ko +insmod snd-avirt-core.ko +insmod dummy/snd-avirt-ap-dummy.ko +insmod loopback/snd-avirt-ap-loopback.ko ``` ### Note: @@ -47,16 +47,16 @@ For example, in AGL: ```sh mkdir -p /lib/modules/$(uname -r)/extra -cp avirt_core.ko avirt_dummyap.ko avirt_loopbackap.ko /lib/modules/$(uname -r)/extra +cp snd-avirt-core.ko snd-avirt-ap-dummy.ko snd-avirt-ap-loopback.ko /lib/modules/$(uname -r)/extra depmod ``` Once the modules are in place, we can load the modules using: ```sh -modprobe avirt_core -modprobe avirt_dummyap -modprobe avirt_loopbackap +modprobe snd-avirt-core +modprobe snd-avirt-ap-dummy +modprobe snd-avirt-ap-loopback ``` @@ -93,24 +93,24 @@ Finally, we can configure AVIRT, for example: ```sh # Set up each of the cards channels -mkdir /config/avirt/streams/playback_media -echo "2">/config/avirt/streams/playback_media/channels -echo "ap_dummy">/config/avirt/streams/playback_media/map +mkdir /config/snd-avirt/streams/playback_media +echo "2">/config/snd-avirt/streams/playback_media/channels +echo "ap_dummy">/config/snd-avirt/streams/playback_media/map -mkdir /config/avirt/streams/playback_navigation -echo "1">/config/avirt/streams/playback_navigation/channels -echo "ap_dummy">/config/avirt/streams/playback_navigation/map +mkdir /config/snd-avirt/streams/playback_navigation +echo "1">/config/snd-avirt/streams/playback_navigation/channels +echo "ap_dummy">/config/snd-avirt/streams/playback_navigation/map -mkdir /config/avirt/streams/playback_emergency -echo "1">/config/avirt/streams/playback_emergency/channels -echo "ap_dummy">/config/avirt/streams/playback_emergency/map +mkdir /config/snd-avirt/streams/playback_emergency +echo "1">/config/snd-avirt/streams/playback_emergency/channels +echo "ap_dummy">/config/snd-avirt/streams/playback_emergency/map -mkdir /config/avirt/streams/capture_voice -echo "1">/config/avirt/streams/capture_voice/channels -echo "ap_dummy">/config/avirt/streams/capture_voice/map +mkdir /config/snd-avirt/streams/capture_voice +echo "1">/config/snd-avirt/streams/capture_voice/channels +echo "ap_dummy">/config/snd-avirt/streams/capture_voice/map # Finally, seal the card, and initiate configuration -echo "1">/config/avirt/streams/sealed +echo "1">/config/snd-avirt/streams/sealed ``` Alternatively, the test script at `scripts/test_configfs.sh` can be used. diff --git a/dummy/Makefile b/dummy/Makefile index 78579d7..11ceceb 100644 --- a/dummy/Makefile +++ b/dummy/Makefile @@ -1,6 +1,6 @@ -obj-$(CONFIG_AVIRT_DUMMYAP) += avirt_dummyap.o +obj-$(CONFIG_AVIRT_AP_DUMMY) += snd-avirt-ap-dummy.o $(info $(src)) -avirt_dummyap-objs := dummy.o +snd-avirt-ap-dummy-objs := dummy.o ccflags-y += -Idrivers/staging/ ccflags-y += -I$(src)/../ diff --git a/dummy/dummy.c b/dummy/dummy.c index 100972a..5f19564 100644 --- a/dummy/dummy.c +++ b/dummy/dummy.c @@ -34,7 +34,7 @@ MODULE_LICENSE("GPL v2"); #define get_dummy_ops(substream) \ (*(const struct dummy_timer_ops **)(substream)->runtime->private_data) -static struct avirt_coreinfo *coreinfo; +static struct snd_avirt_coreinfo *coreinfo; /******************************************************************************* * System Timer Interface @@ -140,7 +140,7 @@ static void dummy_systimer_callback(struct timer_list *t) dpcm->elapsed = 0; spin_unlock_irqrestore(&dpcm->lock, flags); if (elapsed) - avirt_pcm_period_elapsed(dpcm->substream); + snd_avirt_pcm_period_elapsed(dpcm->substream); } static snd_pcm_uframes_t @@ -241,18 +241,18 @@ static struct snd_pcm_ops dummyap_pcm_ops = { /******************************************************************************* * Dummy Audio Path AVIRT registration ******************************************************************************/ -int dummy_configure(struct snd_card *card, - struct config_group *avirt_stream_group, - unsigned int stream_count) +static int dummy_configure(struct snd_card *card, + struct config_group *snd_avirt_stream_group, + unsigned int stream_count) { // Do something with streams struct list_head *entry; - list_for_each (entry, &avirt_stream_group->cg_children) { + list_for_each (entry, &snd_avirt_stream_group->cg_children) { struct config_item *item = container_of(entry, struct config_item, ci_entry); - struct avirt_stream *stream = - avirt_stream_from_config_item(item); + struct snd_avirt_stream *stream = + snd_avirt_stream_from_config_item(item); AP_INFOK("stream name:%s device:%d channels:%d", stream->name, stream->device, stream->channels); } @@ -272,7 +272,7 @@ static struct snd_pcm_hardware dummyap_hw = { .periods_max = DUMMY_PERIODS_MAX, }; -static struct avirt_audiopath dummyap_module = { +static struct snd_avirt_audiopath dummyap_module = { .uid = "ap_dummy", .name = "Dummy Audio Path", .version = { 0, 0, 1 }, @@ -287,7 +287,7 @@ static int __init dummy_init(void) pr_info("init()\n"); - err = avirt_audiopath_register(&dummyap_module, &coreinfo); + err = snd_avirt_audiopath_register(&dummyap_module, &coreinfo); if ((err < 0) || (!coreinfo)) { pr_err("%s: coreinfo is NULL!\n", __func__); return err; @@ -300,7 +300,7 @@ static void __exit dummy_exit(void) { pr_info("exit()\n"); - avirt_audiopath_deregister(&dummyap_module); + snd_avirt_audiopath_deregister(&dummyap_module); } module_init(dummy_init); diff --git a/loopback/Makefile b/loopback/Makefile index 9d3c606..0546168 100644 --- a/loopback/Makefile +++ b/loopback/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_AVIRT_LOOPBACKAP) += avirt_loopbackap.o +obj-$(CONFIG_AVIRT_AP_LOOPBACK) += snd-avirt-ap-loopback.o $(info $(src)) -avirt_loopbackap-objs := loopback.o +snd-avirt-ap-loopback-objs := loopback.o ccflags-y += -Idrivers/staging/ ccflags-y += -I$(src)/../ diff --git a/loopback/loopback.c b/loopback/loopback.c index ba9225e..b4a82e5 100644 --- a/loopback/loopback.c +++ b/loopback/loopback.c @@ -46,7 +46,7 @@ MODULE_LICENSE("GPL"); #define NO_PITCH 100000 -static struct avirt_coreinfo *coreinfo; +static struct snd_avirt_coreinfo *coreinfo; static struct loopback *loopback; struct loopback_pcm; @@ -509,7 +509,7 @@ static void loopback_timer_function(struct timer_list *t) dpcm->period_update_pending = 0; spin_unlock_irqrestore(&dpcm->cable->lock, flags); /* need to unlock before calling below */ - avirt_pcm_period_elapsed(dpcm->substream); + snd_avirt_pcm_period_elapsed(dpcm->substream); return; } } @@ -529,7 +529,7 @@ static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream) return bytes_to_frames(runtime, pos); } -static const struct snd_pcm_hardware loopback_pcm_hardware = { +static const struct snd_pcm_hardware loopbackap_pcm_hardware = { .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), @@ -661,7 +661,7 @@ static int loopback_open(struct snd_pcm_substream *substream) goto unlock; } spin_lock_init(&cable->lock); - cable->hw = loopback_pcm_hardware; + cable->hw = loopbackap_pcm_hardware; loopback->cables[substream->pcm->device] = cable; } dpcm->cable = cable; @@ -689,7 +689,7 @@ static int loopback_open(struct snd_pcm_substream *substream) runtime->private_data = dpcm; runtime->private_free = loopback_runtime_free; if (get_notify(dpcm)) - runtime->hw = loopback_pcm_hardware; + runtime->hw = loopbackap_pcm_hardware; else runtime->hw = cable->hw; @@ -936,7 +936,7 @@ static int loopback_mixer_new(struct loopback *loopback, int notify) int dev, dev_count, idx, err; strcpy(card->mixername, "Loopback Mixer"); - dev_count = avirt_stream_count(SNDRV_PCM_STREAM_PLAYBACK); + dev_count = snd_avirt_stream_count(SNDRV_PCM_STREAM_PLAYBACK); for (dev = 0; dev < dev_count; dev++) { pcm = loopback->pcm[dev]; setup = &loopback->setup[dev]; @@ -1043,9 +1043,9 @@ static int loopback_proc_new(struct loopback *loopback, int cidx) return 0; } -int loopbackap_configure(struct snd_card *card, - struct config_group *avirt_stream_group, - unsigned int stream_count) +static int loopbackap_configure(struct snd_card *card, + struct config_group *snd_avirt_stream_group, + unsigned int stream_count) { int err; struct list_head *entry; @@ -1056,11 +1056,11 @@ int loopbackap_configure(struct snd_card *card, loopback->card = card; mutex_init(&loopback->cable_lock); - list_for_each (entry, &avirt_stream_group->cg_children) { + list_for_each (entry, &snd_avirt_stream_group->cg_children) { struct config_item *item = container_of(entry, struct config_item, ci_entry); - struct avirt_stream *stream = - avirt_stream_from_config_item(item); + struct snd_avirt_stream *stream = + snd_avirt_stream_from_config_item(item); loopback->pcm[stream->device] = stream->pcm; AP_INFOK("stream name:%s device:%d channels:%d", stream->name, @@ -1080,11 +1080,11 @@ int loopbackap_configure(struct snd_card *card, /******************************************************************************* * Loopback Audio Path AVIRT registration ******************************************************************************/ -static struct avirt_audiopath loopbackap_module = { +static struct snd_avirt_audiopath loopbackap_module = { .uid = AP_UID, .name = "Loopback Audio Path", .version = { 0, 0, 1 }, - .hw = &loopback_pcm_hardware, + .hw = &loopbackap_pcm_hardware, .pcm_ops = &loopbackap_pcm_ops, .configure = loopbackap_configure, }; @@ -1093,7 +1093,7 @@ static int __init alsa_card_loopback_init(void) { int err = 0; - err = avirt_audiopath_register(&loopbackap_module, &coreinfo); + err = snd_avirt_audiopath_register(&loopbackap_module, &coreinfo); if ((err < 0) || (!coreinfo)) { AP_ERRORK("coreinfo is NULL!"); return err; @@ -1104,7 +1104,7 @@ static int __init alsa_card_loopback_init(void) static void __exit alsa_card_loopback_exit(void) { - avirt_audiopath_deregister(&loopbackap_module); + snd_avirt_audiopath_deregister(&loopbackap_module); } module_init(alsa_card_loopback_init); diff --git a/scripts/load.sh b/scripts/load.sh index 82f613a..103a63b 100755 --- a/scripts/load.sh +++ b/scripts/load.sh @@ -1,11 +1,11 @@ #!/bin/sh # Load the core -insmod avirt_core.ko +insmod snd-avirt-core.ko # Load the additional Audio Paths -insmod dummy/avirt_dummyap.ko -insmod loopback/avirt_loopbackap.ko +insmod dummy/snd-avirt-ap-dummy.ko +insmod loopback/snd-avirt-ap-loopback.ko # Run the test script ./scripts/test_configfs.sh diff --git a/scripts/make-agl.sh b/scripts/make-agl.sh index 4421af8..6c94fbb 100755 --- a/scripts/make-agl.sh +++ b/scripts/make-agl.sh @@ -7,6 +7,8 @@ long_sdkpath=$(xds-cli sdks get $sdk_id | grep Path) sdkpath=${long_sdkpath:4} # Build -/opt/AGL/bin/xds-cli exec --config xds-project.conf -- \ - LDFLAGS= CONFIG_AVIRT=m CONFIG_AVIRT_BUILDLOCAL=y CONFIG_AVIRT_DUMMYAP=m \ +/opt/AGL/bin/xds-cli exec --config xds-project.conf -- \ + LDFLAGS= CONFIG_AVIRT=m CONFIG_AVIRT_BUILDLOCAL=y \ + CONFIG_AVIRT_AP_DUMMY=m \ + CONFIG_AVIRT_AP_LOOPBACK=m \ make -C $sdkpath/sysroots/aarch64-agl-linux/usr/src/kernel M=$(pwd) $@ diff --git a/scripts/test_configfs.sh b/scripts/test_configfs.sh index baa5e58..b6a56f6 100755 --- a/scripts/test_configfs.sh +++ b/scripts/test_configfs.sh @@ -2,20 +2,20 @@ mkdir -p /config && mount -t configfs none /config -mkdir /config/avirt/streams/playback_media -echo "2">/config/avirt/streams/playback_media/channels -echo "ap_loopback">/config/avirt/streams/playback_media/map +mkdir /config/snd-avirt/streams/playback_media +echo "2">/config/snd-avirt/streams/playback_media/channels +echo "ap_loopback">/config/snd-avirt/streams/playback_media/map -mkdir /config/avirt/streams/playback_navigation -echo "1">/config/avirt/streams/playback_navigation/channels -echo "ap_loopback">/config/avirt/streams/playback_navigation/map +mkdir /config/snd-avirt/streams/playback_navigation +echo "1">/config/snd-avirt/streams/playback_navigation/channels +echo "ap_loopback">/config/snd-avirt/streams/playback_navigation/map -mkdir /config/avirt/streams/playback_emergency -echo "1">/config/avirt/streams/playback_emergency/channels -echo "ap_loopback">/config/avirt/streams/playback_emergency/map +mkdir /config/snd-avirt/streams/playback_emergency +echo "1">/config/snd-avirt/streams/playback_emergency/channels +echo "ap_loopback">/config/snd-avirt/streams/playback_emergency/map -mkdir /config/avirt/streams/capture_voice -echo "1">/config/avirt/streams/capture_voice/channels -echo "ap_loopback">/config/avirt/streams/capture_voice/map +mkdir /config/snd-avirt/streams/capture_voice +echo "1">/config/snd-avirt/streams/capture_voice/channels +echo "ap_loopback">/config/snd-avirt/streams/capture_voice/map -echo "1">/config/avirt/streams/sealed +echo "1">/config/snd-avirt/streams/sealed diff --git a/scripts/unload.sh b/scripts/unload.sh index 2c158d5..a18e1f5 100755 --- a/scripts/unload.sh +++ b/scripts/unload.sh @@ -1,13 +1,13 @@ #!/bin/sh -rmdir /config/avirt/streams/playback_* -rmdir /config/avirt/streams/capture_* +rmdir /config/snd-avirt/streams/playback_* +rmdir /config/snd-avirt/streams/capture_* rm_module() { lsmod |grep "^$1\>" && rmmod $1 || true } -rm_module avirt_loopbackap -rm_module avirt_dummyap -rm_module avirt_core +rm_module snd_avirt_ap_loopback +rm_module snd_avirt_ap_dummy +rm_module snd_avirt_core echo "Drivers Removed!" diff --git a/sound/avirt.h b/sound/avirt.h index 5df84fe..1a5c546 100644 --- a/sound/avirt.h +++ b/sound/avirt.h @@ -17,34 +17,34 @@ #define MAX_STREAMS 16 #define MAX_NAME_LEN 80 -#define DINFO(logname, fmt, args...) \ +#define DINFO(logname, fmt, args...) \ snd_printk(KERN_INFO "AVIRT: %s: " fmt "\n", logname, ##args) -#define DERROR(logname, fmt, args...) \ +#define DERROR(logname, fmt, args...) \ snd_printk(KERN_ERR "AVIRT: %s: " fmt "\n", logname, ##args) -#define DDEBUG(logname, fmt, args...) \ +#define DDEBUG(logname, fmt, args...) \ snd_printk(KERN_DEBUG "AVIRT: %s: " fmt "\n", logname, ##args) /** * AVIRT Audio Path configure function type - * Each Audio Path registers this at avirt_audiopath_register time. + * Each Audio Path registers this at snd_avirt_audiopath_register time. * It is then called by the core once AVIRT has been configured */ -typedef int (*avirt_audiopath_configure)(struct snd_card *card, - struct config_group *stream_group, - unsigned int stream_count); +typedef int (*snd_avirt_audiopath_configure)(struct snd_card *card, + struct config_group *stream_group, + unsigned int stream_count); /** * AVIRT Audio Path info */ -struct avirt_audiopath { +struct snd_avirt_audiopath { const char *uid; /* Unique identifier */ const char *name; /* Pretty name */ unsigned int version[3]; /* Version - Major.Minor.Ext */ const struct snd_pcm_hardware *hw; /* ALSA PCM HW conf */ const struct snd_pcm_ops *pcm_ops; /* ALSA PCM op table */ - avirt_audiopath_configure configure; /* Configure callback function */ + snd_avirt_audiopath_configure configure; /* Config callback function */ void *context; }; @@ -52,7 +52,7 @@ struct avirt_audiopath { /* * Audio stream configuration */ -struct avirt_stream { +struct snd_avirt_stream { char name[MAX_NAME_LEN]; /* Stream name */ char map[MAX_NAME_LEN]; /* Stream Audio Path mapping */ unsigned int channels; /* Stream channel count */ @@ -65,58 +65,58 @@ struct avirt_stream { /** * AVIRT core info */ -struct avirt_coreinfo { +struct snd_avirt_coreinfo { unsigned int version[3]; }; /** - * avirt_audiopath_register - register Audio Path with ALSA virtual driver + * snd_avirt_audiopath_register - register Audio Path with AVIRT * @audiopath: Audio Path to be registered * @core: ALSA virtual driver core info * @return: 0 on success or error code otherwise */ -int avirt_audiopath_register(struct avirt_audiopath *audiopath, - struct avirt_coreinfo **coreinfo); +int snd_avirt_audiopath_register(struct snd_avirt_audiopath *audiopath, + struct snd_avirt_coreinfo **coreinfo); /** - * avirt_audiopath_deregister - deregister Audio Path with ALSA virtual driver + * snd_avirt_audiopath_deregister - deregister Audio Path with AVIRT * @audiopath: Audio Path to be deregistered * @return: 0 on success or error code otherwise */ -int avirt_audiopath_deregister(struct avirt_audiopath *audiopath); +int snd_avirt_audiopath_deregister(struct snd_avirt_audiopath *audiopath); /** - * avirt_audiopath_get - retrieves the Audio Path by it's UID + * snd_avirt_audiopath_get - retrieves the Audio Path by it's UID * @uid: Unique ID for the Audio Path * @return: Corresponding Audio Path */ -struct avirt_audiopath *avirt_audiopath_get(const char *uid); +struct snd_avirt_audiopath *snd_avirt_audiopath_get(const char *uid); /** - * avirt_stream_count - get the stream count for the given direction + * snd_avirt_stream_count - get the stream count for the given direction * @direction: The direction to get the stream count for * @return: The stream count */ -int avirt_stream_count(unsigned int direction); +int snd_avirt_stream_count(unsigned int direction); /** - * avirt_stream_from_config_item - Convert a config_item to an avirt_stream + * snd_avirt_stream_from_config_item - Convert config_item to a snd_avirt_stream * @item: The config_item to convert from - * @return: The item's avirt_stream if successful, NULL otherwise + * @return: The item's snd_avirt_stream if successful, NULL otherwise */ -static inline struct avirt_stream * -avirt_stream_from_config_item(struct config_item *item) +static inline struct snd_avirt_stream * + snd_avirt_stream_from_config_item(struct config_item *item) { - return item ? container_of(item, struct avirt_stream, item) : NULL; + return item ? container_of(item, struct snd_avirt_stream, item) : NULL; } /** - * avirt_pcm_period_elapsed - PCM buffer complete callback + * snd_avirt_pcm_period_elapsed - PCM buffer complete callback * @substream: pointer to ALSA PCM substream * * This should be called from a child Audio Path once it has finished processing * the PCM buffer */ -void avirt_pcm_period_elapsed(struct snd_pcm_substream *substream); +void snd_avirt_pcm_period_elapsed(struct snd_pcm_substream *substream); #endif // __SOUND_AVIRT_H -- cgit 1.2.3-korg