diff options
author | Mark Farrugia <mark.farrugia@fiberdyne.com.au> | 2018-09-20 12:09:20 +1000 |
---|---|---|
committer | Mark Farrugia <mark.farrugia@fiberdyne.com.au> | 2018-10-26 17:27:33 +1100 |
commit | 3786b607d4dd5e738cbe491dbfb03c2283e74358 (patch) | |
tree | 83f150ee7eee8ab42d827f6a1b3c5af68ac9fcbd | |
parent | 99a09bc4fe16d275b2bf839cb8f37192b2235e24 (diff) |
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 <mark.farrugia@fiberdyne.com.au>
-rw-r--r-- | alsa-pcm.c | 53 | ||||
-rwxr-xr-x | alsa.c | 1 | ||||
-rwxr-xr-x | alsa.h | 20 | ||||
-rw-r--r-- | core.c | 33 | ||||
-rw-r--r-- | core.h | 27 | ||||
-rw-r--r-- | dummy/dummy.c | 1 |
6 files changed, 79 insertions, 56 deletions
@@ -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; } @@ -7,7 +7,6 @@ * Copyright (C) 2010-2018 Fiberdyne Systems Pty Ltd */ -#include <linux/slab.h> #include <sound/core.h> #include <sound/initval.h> @@ -13,10 +13,11 @@ #include "core.h" #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/pcm.h> -#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; @@ -8,7 +8,6 @@ */ #include <linux/module.h> -#include <linux/slab.h> #include <linux/platform_device.h> #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; } @@ -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, |