diff options
-rw-r--r-- | core.c | 88 | ||||
-rw-r--r-- | core.h | 18 | ||||
-rw-r--r-- | dummy/dummy.c | 13 | ||||
-rw-r--r-- | loopback/loopback.c | 40 | ||||
-rw-r--r-- | sound/avirt.h | 48 |
5 files changed, 106 insertions, 101 deletions
@@ -44,9 +44,9 @@ struct snd_avirt_audiopath_obj { static struct kset *snd_avirt_audiopath_kset; static struct kobject *kobj; -#define to_audiopath_obj(d) \ +#define to_audiopath_obj(d) \ container_of(d, struct snd_avirt_audiopath_obj, kobj) -#define to_audiopath_attr(a) \ +#define to_audiopath_attr(a) \ container_of(a, struct snd_avirt_audiopath_attribute, attr) /** @@ -188,6 +188,15 @@ static struct snd_avirt_audiopath_obj * return snd_avirt_audiopath; } +/** + * destroy_snd_avirt_audiopath_obj - destroys an Audio Path object + * @name: the Audio Path object + */ +static void destroy_snd_avirt_audiopath_obj(struct snd_avirt_audiopath_obj *p) +{ + kobject_put(&p->kobj); +} + static struct snd_pcm *pcm_create(struct snd_avirt_stream *stream) { bool playback = false, capture = false; @@ -223,13 +232,22 @@ static struct snd_pcm *pcm_create(struct snd_avirt_stream *stream) return pcm; } -/** - * destroy_snd_avirt_audiopath_obj - destroys an Audio Path object - * @name: the Audio Path object - */ -static void destroy_snd_avirt_audiopath_obj(struct snd_avirt_audiopath_obj *p) +static int snd_avirt_streams_get(const char *map, + struct snd_avirt_stream_array *stream_array) { - kobject_put(&p->kobj); + struct list_head *entry; + struct config_item *item; + struct snd_avirt_stream *stream; + + list_for_each (entry, &core.stream_group->cg_children) { + item = container_of(entry, struct config_item, ci_entry); + stream = snd_avirt_stream_from_config_item(item); + if (!strcmp(map, stream->map)) { + stream_array->streams[stream_array->count++] = stream; + } + } + + return 0; } /** @@ -258,6 +276,7 @@ struct snd_avirt_audiopath *snd_avirt_audiopath_get(const char *uid) int snd_avirt_audiopath_register(struct snd_avirt_audiopath *audiopath) { struct snd_avirt_audiopath_obj *audiopath_obj; + struct snd_avirt_stream_array stream_array; if (!audiopath) { D_ERRORK("Audio Path is NULL!"); @@ -277,11 +296,11 @@ int snd_avirt_audiopath_register(struct snd_avirt_audiopath *audiopath) list_add_tail(&audiopath_obj->list, &audiopath_list); // If we have already sealed the streams, configure this AP - if (core.streams_sealed) - audiopath->configure(core.card, core.stream_group, - core.stream_count); - - *info = &coreinfo; + if (core.streams_sealed) { + stream_array.count = 0; + snd_avirt_streams_get(audiopath->uid, &stream_array); + audiopath->configure(core.card, &stream_array); + } return 0; } @@ -317,34 +336,6 @@ int snd_avirt_audiopath_deregister(struct snd_avirt_audiopath *audiopath) EXPORT_SYMBOL_GPL(snd_avirt_audiopath_deregister); /** - * 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 snd_avirt_stream_count(unsigned int direction) -{ - struct list_head *entry; - struct config_item *item; - struct snd_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 = snd_avirt_stream_from_config_item(item); - if (!stream) - return -EFAULT; - if (stream->direction == direction) - count++; - } - - return count; -} -EXPORT_SYMBOL_GPL(snd_avirt_stream_count); - -/** * 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 @@ -356,6 +347,11 @@ struct snd_avirt_stream *snd_avirt_stream_create(const char *name, { struct snd_avirt_stream *stream; + if ((core.stream_count + 1) > MAX_STREAMS) { + D_ERRORK("Cannot add stream %s, PCMs are maxxed out!", name); + return ERR_PTR(-EPERM); + } + stream = kzalloc(sizeof(*stream), GFP_KERNEL); if (!stream) return ERR_PTR(-ENOMEM); @@ -373,9 +369,10 @@ struct snd_avirt_stream *snd_avirt_stream_create(const char *name, int snd_avirt_streams_seal(void) { - int err = 0; + int err = 0, i = 0; struct snd_avirt_audiopath_obj *ap_obj; struct snd_avirt_stream *stream; + struct snd_avirt_stream_array stream_array; struct config_item *item; struct list_head *entry; @@ -396,8 +393,11 @@ int snd_avirt_streams_seal(void) 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); + for (i = 0; i < MAX_STREAMS; i++) + stream_array.streams[i] = NULL; + stream_array.count = 0; + snd_avirt_streams_get(ap_obj->path->uid, &stream_array); + ap_obj->path->configure(core.card, &stream_array); } err = snd_card_register(core.card); @@ -68,4 +68,22 @@ struct snd_avirt_stream *snd_avirt_stream_find_by_device(unsigned int device); struct snd_avirt_stream *snd_avirt_stream_create(const char *name, int direction); +/** + * snd_avirt_audiopath_get - retrieves the Audio Path by it's UID + * @uid: Unique ID for the Audio Path + * @return: Corresponding Audio Path + */ +struct snd_avirt_audiopath *snd_avirt_audiopath_get(const char *uid); + +/** + * 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 snd_avirt_stream if successful, NULL otherwise + */ +static inline struct snd_avirt_stream * +snd_avirt_stream_from_config_item(struct config_item *item) +{ + return item ? container_of(item, struct snd_avirt_stream, item) : NULL; +} + #endif /* __SOUND_AVIRT_CORE_H */ diff --git a/dummy/dummy.c b/dummy/dummy.c index 7c85531..872ade9 100644 --- a/dummy/dummy.c +++ b/dummy/dummy.c @@ -240,17 +240,14 @@ static struct snd_pcm_ops dummyap_pcm_ops = { * Dummy Audio Path AVIRT registration ******************************************************************************/ static int dummy_configure(struct snd_card *card, - struct config_group *snd_avirt_stream_group, - unsigned int stream_count) + struct snd_avirt_stream_array *stream_array) { // Do something with streams + int idx = 0; + struct snd_avirt_stream *stream; - struct list_head *entry; - list_for_each (entry, &snd_avirt_stream_group->cg_children) { - struct config_item *item = - container_of(entry, struct config_item, ci_entry); - struct snd_avirt_stream *stream = - snd_avirt_stream_from_config_item(item); + for (idx = 0; idx < stream_array->count; idx++) { + stream = stream_array->streams[idx]; AP_INFOK("stream name:%s device:%d channels:%d", stream->name, stream->device, stream->channels); } diff --git a/loopback/loopback.c b/loopback/loopback.c index c3e06be..9646706 100644 --- a/loopback/loopback.c +++ b/loopback/loopback.c @@ -78,6 +78,8 @@ struct loopback { struct loopback_cable *cables[MAX_STREAMS]; struct snd_pcm *pcm[MAX_STREAMS]; struct loopback_setup setup[MAX_STREAMS]; + int playback_count; + int capture_count; }; struct loopback_pcm { @@ -932,13 +934,13 @@ static int loopback_mixer_new(struct loopback *loopback, int notify) struct snd_pcm *pcm; struct snd_kcontrol *kctl; struct loopback_setup *setup; - int dev, dev_count, idx, err; + int dev_idx, dev_count, idx, err; strcpy(card->mixername, "Loopback Mixer"); - 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]; + dev_count = loopback->playback_count + loopback->capture_count; + for (dev_idx = 0; dev_idx < dev_count; dev_idx++) { + pcm = loopback->pcm[dev_idx]; + setup = &loopback->setup[dev_idx]; setup->notify = notify; setup->rate_shift = NO_PITCH; setup->format = SNDRV_PCM_FORMAT_S16_LE; @@ -948,7 +950,7 @@ static int loopback_mixer_new(struct loopback *loopback, int notify) kctl = snd_ctl_new1(&loopback_controls[idx], loopback); if (!kctl) return -ENOMEM; - kctl->id.device = dev; + kctl->id.device = pcm->device; kctl->id.subdevice = 0; switch (idx) { case ACTIVE_IDX: @@ -1043,25 +1045,29 @@ static int loopback_proc_new(struct loopback *loopback, int cidx) } static int loopbackap_configure(struct snd_card *card, - struct config_group *snd_avirt_stream_group, - unsigned int stream_count) + struct snd_avirt_stream_array *stream_array) { - int err; - struct list_head *entry; + int err, idx; + struct snd_avirt_stream *stream; loopback = kzalloc(sizeof(struct loopback), GFP_KERNEL); if (!loopback) return -ENOMEM; loopback->card = card; + loopback->playback_count = 0; + loopback->capture_count = 0; mutex_init(&loopback->cable_lock); - list_for_each (entry, &snd_avirt_stream_group->cg_children) { - struct config_item *item = - container_of(entry, struct config_item, ci_entry); - struct snd_avirt_stream *stream = - snd_avirt_stream_from_config_item(item); - loopback->pcm[stream->device] = stream->pcm; - + for (idx = 0; idx < stream_array->count; idx++) { + stream = stream_array->streams[idx]; + if (!stream) + return -EFAULT; + loopback->pcm[loopback->playback_count + + loopback->capture_count] = stream->pcm; + if (stream->direction) + loopback->playback_count++; + else + loopback->capture_count++; AP_INFOK("stream name:%s device:%d channels:%d", stream->name, stream->device, stream->channels); } diff --git a/sound/avirt.h b/sound/avirt.h index b077bbc..55db1eb 100644 --- a/sound/avirt.h +++ b/sound/avirt.h @@ -17,23 +17,24 @@ #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) +struct snd_avirt_stream_array; /* Forward declaration */ + /** * AVIRT Audio Path configure function type * 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 (*snd_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 snd_avirt_stream_array *stream_array); /** * AVIRT Audio Path info @@ -49,7 +50,7 @@ struct snd_avirt_audiopath { void *context; }; -/* +/** * Audio stream configuration */ struct snd_avirt_stream { @@ -63,6 +64,14 @@ struct snd_avirt_stream { }; /** + * Audio stream group + */ +struct snd_avirt_stream_array { + struct snd_avirt_stream *streams[MAX_STREAMS]; + int count; +}; + +/** * snd_avirt_audiopath_register - register Audio Path with AVIRT * @audiopath: Audio Path to be registered * @return: 0 on success or error code otherwise @@ -77,31 +86,6 @@ int snd_avirt_audiopath_register(struct snd_avirt_audiopath *audiopath); int snd_avirt_audiopath_deregister(struct snd_avirt_audiopath *audiopath); /** - * snd_avirt_audiopath_get - retrieves the Audio Path by it's UID - * @uid: Unique ID for the Audio Path - * @return: Corresponding Audio Path - */ -struct snd_avirt_audiopath *snd_avirt_audiopath_get(const char *uid); - -/** - * 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 snd_avirt_stream_count(unsigned int direction); - -/** - * 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 snd_avirt_stream if successful, NULL otherwise - */ -static inline struct snd_avirt_stream * - snd_avirt_stream_from_config_item(struct config_item *item) -{ - return item ? container_of(item, struct snd_avirt_stream, item) : NULL; -} - -/** * snd_avirt_pcm_period_elapsed - PCM buffer complete callback * @substream: pointer to ALSA PCM substream * |