Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 80 additions & 13 deletions audio/audio_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ struct stream_out_common {

out_close_fn close;
struct audio_device *dev;
const struct hw_stream *hw;
struct hw_stream *hw;

pthread_mutex_t lock;

Expand Down Expand Up @@ -203,7 +203,7 @@ struct stream_in_common {

in_close_fn close;
struct audio_device *dev;
const struct hw_stream *hw;
struct hw_stream *hw;

pthread_mutex_t lock;

Expand Down Expand Up @@ -379,6 +379,9 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)

struct stream_out_common *out = (struct stream_out_common *)stream;
struct audio_device *adev = out->dev;
static uint32_t cardold, devold;
static bool saved = false;
uint32_t cardnum, devnum;
uint32_t v;
int ret;

Expand All @@ -388,6 +391,23 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)

if (ret >= 0) {
apply_route(out->hw, v);
if (get_device_alsadev(adev->cm, v, &cardnum, &devnum) < 0) {
if (saved) {
ALOGI("restoring params with card=%u dev=%u", cardold, devold);
out->hw->card_number = cardold;
out->hw->device_number = devold;
}
} else {
ALOGI("updating params with card=%u dev=%u", cardnum, devnum);
if (!saved) {
cardold = out->hw->card_number;
devold = out->hw->device_number;
ALOGI("saved params with card=%u dev=%u", cardold, devold);
saved = true;
}
out->hw->card_number = cardnum;
out->hw->device_number = devnum;
}
}

stream_invoke_usecases(out->hw, kvpairs);
Expand Down Expand Up @@ -735,6 +755,8 @@ static void out_pcm_fill_params(struct stream_out_pcm *out,
/* Must be called with hw device and output stream mutexes locked */
static int start_output_pcm(struct stream_out_pcm *out)
{
struct config_mgr *cm = out->common.dev->cm;
uint32_t device, cardnum, devnum;
int ret;

struct pcm_config config = {
Expand All @@ -750,10 +772,21 @@ static int start_output_pcm(struct stream_out_pcm *out)

ALOGV("+start_output_stream(%p)", out);

out->pcm = pcm_open(out->common.hw->card_number,
out->common.hw->device_number,
PCM_OUT | PCM_MONOTONIC,
&config);
device = get_current_routes(out->common.hw);
ret = get_device_alsadev(cm, device, &cardnum, &devnum);
if (ret < 0) {
ALOGI("device = %u (not alsadev, ret=%d)", device, ret);
out->pcm = pcm_open(out->common.hw->card_number,
out->common.hw->device_number,
PCM_OUT | PCM_MONOTONIC,
&config);
} else {
ALOGI("device = %u (alsadev)", device);
out->pcm = pcm_open(cardnum,
devnum,
PCM_OUT | PCM_MONOTONIC,
&config);
}

if (out->pcm && !pcm_is_ready(out->pcm)) {
ALOGE("pcm_open(out) failed: %s", pcm_get_error(out->pcm));
Expand Down Expand Up @@ -1799,6 +1832,8 @@ static void in_pcm_fill_params(struct stream_in_pcm *in,
/* Must be called with hw device and input stream mutexes locked */
static int do_open_pcm_input(struct stream_in_pcm *in)
{
struct config_mgr *cm = in->common.dev->cm;
uint32_t device, cardnum, devnum;
struct pcm_config config;
int ret;

Expand All @@ -1818,10 +1853,21 @@ static int do_open_pcm_input(struct stream_in_pcm *in)
config.format = pcm_format_from_android_format(in->common.format),
config.start_threshold = 0;

in->pcm = pcm_open(in->common.hw->card_number,
in->common.hw->device_number,
PCM_IN | PCM_MONOTONIC,
&config);
device = get_current_routes(in->common.hw);
ret = get_device_alsadev(cm, device, &cardnum, &devnum);
if (ret < 0) {
ALOGV("device = %u (not alsadev, ret=%d)", device, ret);
in->pcm = pcm_open(in->common.hw->card_number,
in->common.hw->device_number,
PCM_IN | PCM_MONOTONIC,
&config);
} else {
ALOGV("device = %u (alsadev)", device);
in->pcm = pcm_open(cardnum,
devnum,
PCM_IN | PCM_MONOTONIC,
&config);
}

if (!in->pcm || !pcm_is_ready(in->pcm)) {
ALOGE_IF(in->pcm,"pcm_open(in) failed: %s", pcm_get_error(in->pcm));
Expand Down Expand Up @@ -1876,7 +1922,7 @@ static int change_input_source_locked(struct stream_in_pcm *in, const char *valu
{
struct audio_config config;
const char *stream_name;
const struct hw_stream *hw = NULL;
struct hw_stream *hw = NULL;
const int new_source = atoi(value);

*was_changed = false;
Expand Down Expand Up @@ -2047,12 +2093,16 @@ static ssize_t in_pcm_read(struct audio_stream_in *stream, void *buffer,
static int in_pcm_set_parameters(struct audio_stream *stream, const char *kvpairs)
{
struct stream_in_pcm *in = (struct stream_in_pcm *)stream;
struct config_mgr *cm = in->common.dev->cm;
struct str_parms *parms;
char value[32];
uint32_t new_routing = 0;
bool routing_changed;
uint32_t devices;
bool input_was_changed;
static uint32_t cardold, devold;
static bool saved = false;
uint32_t cardnum, devnum;
int ret;

ALOGV("+in_pcm_set_parameters(%p) '%s'", stream, kvpairs);
Expand Down Expand Up @@ -2091,6 +2141,23 @@ static int in_pcm_set_parameters(struct audio_stream *stream, const char *kvpair
if (in->common.hw) {
ALOGV("Apply routing=0x%x to input stream", new_routing);
apply_route(in->common.hw, new_routing);
if (get_device_alsadev(cm, new_routing, &cardnum, &devnum) < 0) {
if (saved) {
ALOGV("restoring params with card=%u dev=%u", cardold, devold);
in->common.hw->card_number = cardold;
in->common.hw->device_number = devold;
}
} else {
ALOGV("updating params with card=%u dev=%u", cardnum, devnum);
if (!saved) {
cardold = in->common.hw->card_number;
devold = in->common.hw->device_number;
ALOGV("saved params with card=%u dev=%u", cardold, devold);
saved = true;
}
in->common.hw->card_number = cardnum;
in->common.hw->device_number = devnum;
}
}
}

Expand Down Expand Up @@ -2159,7 +2226,7 @@ static int adev_open_output_stream_v3(struct audio_hw_device *dev,
config->format, config->channel_mask, config->sample_rate, flags);

devices &= AUDIO_DEVICE_OUT_ALL;
const struct hw_stream *hw = get_stream(adev->cm, devices, flags, config);
struct hw_stream *hw = get_stream(adev->cm, devices, flags, config);
if (!hw) {
ALOGE("No suitable output stream for devices=0x%x flags=0x%x format=0x%x",
devices, flags, config->format);
Expand Down Expand Up @@ -2257,7 +2324,7 @@ static int adev_open_input_stream_v3(struct audio_hw_device *dev,
*stream_in = NULL;

devices &= AUDIO_DEVICE_IN_ALL;
const struct hw_stream *hw = get_stream(adev->cm, devices, 0, config);
struct hw_stream *hw = get_stream(adev->cm, devices, 0, config);
if (!hw) {
ALOGE("No suitable input stream for devices=0x%x flags=0x%x format=0x%x",
devices, flags, config->format);
Expand Down
67 changes: 63 additions & 4 deletions configmgr/audio_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ struct codec_probe {
struct device {
uint32_t type; /* 0 is reserved for the global device */
int use_count; /* counts total streams using this device */
uint32_t card_number;
uint32_t device_number;
struct dyn_array path_array;
};

Expand Down Expand Up @@ -863,7 +865,7 @@ static bool open_stream_l(struct config_mgr *cm, struct stream *s)
}
}

const struct hw_stream *get_stream(struct config_mgr *cm,
struct hw_stream *get_stream(struct config_mgr *cm,
const audio_devices_t devices,
const audio_output_flags_t flags,
const struct audio_config *config )
Expand Down Expand Up @@ -907,7 +909,7 @@ const struct hw_stream *get_stream(struct config_mgr *cm,
}
}

const struct hw_stream *get_named_stream(struct config_mgr *cm,
struct hw_stream *get_named_stream(struct config_mgr *cm,
const char *name)
{
struct stream *s;
Expand Down Expand Up @@ -1078,6 +1080,31 @@ int get_stream_constant_int32(const struct hw_stream *stream,
return ret;
}

/*********************************************************************
* Device
*********************************************************************/

int get_device_alsadev(struct config_mgr *cm, uint32_t type, uint32_t *cardnum, uint32_t *devnum)
{
struct device *pdev = cm->device_array.devices;
int dev_count = cm->device_array.count;

while (dev_count > 0) {
if (pdev->type == type) {
cardnum = &pdev->card_number;
devnum = &pdev->device_number;
if (*cardnum < UINT_MAX && *devnum < UINT_MAX) {
return 0;
}
return -ENODEV;
}
--dev_count;
++pdev;
}

return -ENOENT;
}

/*********************************************************************
* Config file parsing
*
Expand Down Expand Up @@ -1133,7 +1160,8 @@ static const struct parse_element elem_table[e_elem_count] = {

[e_elem_device] = {
.name = "device",
.valid_attribs = BIT(e_attrib_name),
.valid_attribs = BIT(e_attrib_name) | BIT(e_attrib_card)
| BIT(e_attrib_cardname) | BIT(e_attrib_device),
.required_attribs = BIT(e_attrib_name),
.valid_subelem = BIT(e_elem_path),
.start_fn = parse_device_start,
Expand Down Expand Up @@ -2505,8 +2533,11 @@ static int parse_device_start(struct parse_state *state)
struct dyn_array *array = &state->cm->device_array;
uint32_t device_flag;
uint32_t *existing_devices;
uint32_t card = UINT_MAX;
uint32_t device_number = UINT_MAX;
const struct parse_device *p;
struct device* d;
int ret;

p = parse_match_device(dev_name);

Expand Down Expand Up @@ -2536,14 +2567,42 @@ static int parse_device_start(struct parse_state *state)
*existing_devices |= device_flag;
}

ALOGV("Add device '%s'", dev_name);
if (state->attribs.value[e_attrib_cardname] != NULL &&
state->attribs.value[e_attrib_card] != NULL) {
ALOGE("device must be configured by only one of 'card' OR 'cardname'. Both provided.");
return -EINVAL;
}

ret = attrib_to_uint(&card, state, e_attrib_card);
if (ret == -EINVAL) {
return ret;
}

if (state->attribs.value[e_attrib_cardname] != NULL &&
get_card_id_for_name(state->attribs.value[e_attrib_cardname], &card) != 0) {
return -EINVAL;
}

ret = attrib_to_uint(&device_number, state, e_attrib_device);
if (ret == -EINVAL) {
return ret;
}

if (card < UINT_MAX && device_number < UINT_MAX) {
ALOGV("Add device '%s' (card=%u device=%u)", dev_name, card, device_number);
} else {
ALOGV("Add device '%s'", dev_name);
}

d = new_device(array, device_flag);
if (d == NULL) {
return -ENOMEM;
}
state->current.device = d;

d->card_number = card;
d->device_number = device_number;

return 0;
}

Expand Down
12 changes: 10 additions & 2 deletions include/tinyhal/audio_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct mixer;
struct mixer_ctl;
struct config_mgr;
struct audio_config;
struct device;

/** Stream type */
enum stream_type {
Expand Down Expand Up @@ -129,13 +130,13 @@ uint32_t get_supported_output_devices( struct config_mgr *cm );
* Note that this only considers unnamed streams (those without a 'name'
* attribute). For named streams use get_named_stream().
*/
const struct hw_stream *get_stream( struct config_mgr *cm,
struct hw_stream *get_stream( struct config_mgr *cm,
const audio_devices_t devices,
const audio_output_flags_t flags,
const struct audio_config *config );

/** Find a named custom stream and return a pointer to it */
const struct hw_stream *get_named_stream(struct config_mgr *cm,
struct hw_stream *get_named_stream(struct config_mgr *cm,
const char *name);

/** Return the value of a constant defined by a <set> element as a string
Expand Down Expand Up @@ -187,6 +188,13 @@ int apply_use_case( const struct hw_stream* stream,
const char *setting,
const char *case_name);

/** Get the ALSA card and device number associated to this device
* @return 0 if the device type has card and device numbers defined
* @return -ENODEV if the device type has no card and device number defined
* @return -ENOENT if the device type was not found
*/
int get_device_alsadev(struct config_mgr *cm, uint32_t type, uint32_t *cardnum, uint32_t *devnum);

#if defined(__cplusplus)
} /* extern "C" */
#endif
Expand Down