summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core.c88
-rw-r--r--core.h18
-rw-r--r--dummy/dummy.c13
-rw-r--r--loopback/loopback.c40
-rw-r--r--sound/avirt.h48
5 files changed, 106 insertions, 101 deletions
diff --git a/core.c b/core.c
index 827ee5c..f31c61a 100644
--- a/core.c
+++ b/core.c
@@ -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);
diff --git a/core.h b/core.h
index 16f186a..8804573 100644
--- a/core.h
+++ b/core.h
@@ -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
*