ALSA: snd-usb: mixer: coding style fixups
Shorten some over-long lines, multi-line comments, spurious whitespaces, curly brakets etc. No functional change. Signed-off-by: Daniel Mack <zonque@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
038b8455db
commit
6bc170e4e8
@ -162,7 +162,7 @@ static int check_mapped_selector_name(struct mixer_build *state, int unitid,
|
|||||||
{
|
{
|
||||||
const struct usbmix_selector_map *p;
|
const struct usbmix_selector_map *p;
|
||||||
|
|
||||||
if (! state->selector_map)
|
if (!state->selector_map)
|
||||||
return 0;
|
return 0;
|
||||||
for (p = state->selector_map; p->id; p++) {
|
for (p = state->selector_map; p->id; p++) {
|
||||||
if (p->id == unitid && index < p->count)
|
if (p->id == unitid && index < p->count)
|
||||||
@ -174,7 +174,8 @@ static int check_mapped_selector_name(struct mixer_build *state, int unitid,
|
|||||||
/*
|
/*
|
||||||
* find an audio control unit with the given unit id
|
* find an audio control unit with the given unit id
|
||||||
*/
|
*/
|
||||||
static void *find_audio_control_unit(struct mixer_build *state, unsigned char unit)
|
static void *find_audio_control_unit(struct mixer_build *state,
|
||||||
|
unsigned char unit)
|
||||||
{
|
{
|
||||||
/* we just parse the header */
|
/* we just parse the header */
|
||||||
struct uac_feature_unit_descriptor *hdr = NULL;
|
struct uac_feature_unit_descriptor *hdr = NULL;
|
||||||
@ -194,7 +195,8 @@ static void *find_audio_control_unit(struct mixer_build *state, unsigned char un
|
|||||||
/*
|
/*
|
||||||
* copy a string with the given id
|
* copy a string with the given id
|
||||||
*/
|
*/
|
||||||
static int snd_usb_copy_string_desc(struct mixer_build *state, int index, char *buf, int maxlen)
|
static int snd_usb_copy_string_desc(struct mixer_build *state,
|
||||||
|
int index, char *buf, int maxlen)
|
||||||
{
|
{
|
||||||
int len = usb_string(state->chip->dev, index, buf, maxlen - 1);
|
int len = usb_string(state->chip->dev, index, buf, maxlen - 1);
|
||||||
buf[len] = 0;
|
buf[len] = 0;
|
||||||
@ -253,7 +255,7 @@ static int convert_bytes_value(struct usb_mixer_elem_info *cval, int val)
|
|||||||
|
|
||||||
static int get_relative_value(struct usb_mixer_elem_info *cval, int val)
|
static int get_relative_value(struct usb_mixer_elem_info *cval, int val)
|
||||||
{
|
{
|
||||||
if (! cval->res)
|
if (!cval->res)
|
||||||
cval->res = 1;
|
cval->res = 1;
|
||||||
if (val < cval->min)
|
if (val < cval->min)
|
||||||
return 0;
|
return 0;
|
||||||
@ -267,7 +269,7 @@ static int get_abs_value(struct usb_mixer_elem_info *cval, int val)
|
|||||||
{
|
{
|
||||||
if (val < 0)
|
if (val < 0)
|
||||||
return cval->min;
|
return cval->min;
|
||||||
if (! cval->res)
|
if (!cval->res)
|
||||||
cval->res = 1;
|
cval->res = 1;
|
||||||
val *= cval->res;
|
val *= cval->res;
|
||||||
val += cval->min;
|
val += cval->min;
|
||||||
@ -281,7 +283,8 @@ static int get_abs_value(struct usb_mixer_elem_info *cval, int val)
|
|||||||
* retrieve a mixer value
|
* retrieve a mixer value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
|
static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request,
|
||||||
|
int validx, int *value_ret)
|
||||||
{
|
{
|
||||||
struct snd_usb_audio *chip = cval->mixer->chip;
|
struct snd_usb_audio *chip = cval->mixer->chip;
|
||||||
unsigned char buf[2];
|
unsigned char buf[2];
|
||||||
@ -292,6 +295,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
|
|||||||
err = snd_usb_autoresume(cval->mixer->chip);
|
err = snd_usb_autoresume(cval->mixer->chip);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
down_read(&chip->shutdown_rwsem);
|
down_read(&chip->shutdown_rwsem);
|
||||||
while (timeout-- > 0) {
|
while (timeout-- > 0) {
|
||||||
if (chip->shutdown)
|
if (chip->shutdown)
|
||||||
@ -316,10 +320,11 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
|
static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request,
|
||||||
|
int validx, int *value_ret)
|
||||||
{
|
{
|
||||||
struct snd_usb_audio *chip = cval->mixer->chip;
|
struct snd_usb_audio *chip = cval->mixer->chip;
|
||||||
unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */
|
unsigned char buf[2 + 3 * sizeof(__u16)]; /* enough space for one range */
|
||||||
unsigned char *val;
|
unsigned char *val;
|
||||||
int idx = 0, ret, size;
|
int idx = 0, ret, size;
|
||||||
__u8 bRequest;
|
__u8 bRequest;
|
||||||
@ -339,9 +344,9 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
down_read(&chip->shutdown_rwsem);
|
down_read(&chip->shutdown_rwsem);
|
||||||
if (chip->shutdown)
|
if (chip->shutdown) {
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
else {
|
} else {
|
||||||
idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
|
idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
|
||||||
ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
|
ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
|
||||||
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
|
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
|
||||||
@ -382,7 +387,8 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
|
static int get_ctl_value(struct usb_mixer_elem_info *cval, int request,
|
||||||
|
int validx, int *value_ret)
|
||||||
{
|
{
|
||||||
validx += cval->idx_off;
|
validx += cval->idx_off;
|
||||||
|
|
||||||
@ -391,7 +397,8 @@ static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int vali
|
|||||||
get_ctl_value_v2(cval, request, validx, value_ret);
|
get_ctl_value_v2(cval, request, validx, value_ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int *value)
|
static int get_cur_ctl_value(struct usb_mixer_elem_info *cval,
|
||||||
|
int validx, int *value)
|
||||||
{
|
{
|
||||||
return get_ctl_value(cval, UAC_GET_CUR, validx, value);
|
return get_ctl_value(cval, UAC_GET_CUR, validx, value);
|
||||||
}
|
}
|
||||||
@ -400,7 +407,9 @@ static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int *
|
|||||||
static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval,
|
static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval,
|
||||||
int channel, int *value)
|
int channel, int *value)
|
||||||
{
|
{
|
||||||
return get_ctl_value(cval, UAC_GET_CUR, (cval->control << 8) | channel, value);
|
return get_ctl_value(cval, UAC_GET_CUR,
|
||||||
|
(cval->control << 8) | channel,
|
||||||
|
value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_cur_mix_value(struct usb_mixer_elem_info *cval,
|
static int get_cur_mix_value(struct usb_mixer_elem_info *cval,
|
||||||
@ -417,7 +426,7 @@ static int get_cur_mix_value(struct usb_mixer_elem_info *cval,
|
|||||||
if (!cval->mixer->ignore_ctl_error)
|
if (!cval->mixer->ignore_ctl_error)
|
||||||
usb_audio_dbg(cval->mixer->chip,
|
usb_audio_dbg(cval->mixer->chip,
|
||||||
"cannot get current value for control %d ch %d: err = %d\n",
|
"cannot get current value for control %d ch %d: err = %d\n",
|
||||||
cval->control, channel, err);
|
cval->control, channel, err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
cval->cached |= 1 << channel;
|
cval->cached |= 1 << channel;
|
||||||
@ -425,7 +434,6 @@ static int get_cur_mix_value(struct usb_mixer_elem_info *cval,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set a mixer value
|
* set a mixer value
|
||||||
*/
|
*/
|
||||||
@ -474,7 +482,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
usb_audio_dbg(chip, "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
|
usb_audio_dbg(chip, "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
|
||||||
request, validx, idx, cval->val_type, buf[0], buf[1]);
|
request, validx, idx, cval->val_type, buf[0], buf[1]);
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@ -483,7 +491,8 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value)
|
static int set_cur_ctl_value(struct usb_mixer_elem_info *cval,
|
||||||
|
int validx, int value)
|
||||||
{
|
{
|
||||||
return snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, validx, value);
|
return snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, validx, value);
|
||||||
}
|
}
|
||||||
@ -503,8 +512,9 @@ static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, (cval->control << 8) | channel,
|
err = snd_usb_mixer_set_ctl_value(cval,
|
||||||
value);
|
UAC_SET_CUR, (cval->control << 8) | channel,
|
||||||
|
value);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
cval->cached |= 1 << channel;
|
cval->cached |= 1 << channel;
|
||||||
@ -541,13 +551,13 @@ static int parse_audio_unit(struct mixer_build *state, int unitid);
|
|||||||
* check if the input/output channel routing is enabled on the given bitmap.
|
* check if the input/output channel routing is enabled on the given bitmap.
|
||||||
* used for mixer unit parser
|
* used for mixer unit parser
|
||||||
*/
|
*/
|
||||||
static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_outs)
|
static int check_matrix_bitmap(unsigned char *bmap,
|
||||||
|
int ich, int och, int num_outs)
|
||||||
{
|
{
|
||||||
int idx = ich * num_outs + och;
|
int idx = ich * num_outs + och;
|
||||||
return bmap[idx >> 3] & (0x80 >> (idx & 7));
|
return bmap[idx >> 3] & (0x80 >> (idx & 7));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* add an alsa control element
|
* add an alsa control element
|
||||||
* search and increment the index until an empty slot is found.
|
* search and increment the index until an empty slot is found.
|
||||||
@ -564,7 +574,8 @@ int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
|
|||||||
while (snd_ctl_find_id(mixer->chip->card, &kctl->id))
|
while (snd_ctl_find_id(mixer->chip->card, &kctl->id))
|
||||||
kctl->id.index++;
|
kctl->id.index++;
|
||||||
if ((err = snd_ctl_add(mixer->chip->card, kctl)) < 0) {
|
if ((err = snd_ctl_add(mixer->chip->card, kctl)) < 0) {
|
||||||
usb_audio_dbg(mixer->chip, "cannot add control (err = %d)\n", err);
|
usb_audio_dbg(mixer->chip, "cannot add control (err = %d)\n",
|
||||||
|
err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
cval->elem_id = &kctl->id;
|
cval->elem_id = &kctl->id;
|
||||||
@ -573,7 +584,6 @@ int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get a terminal name string
|
* get a terminal name string
|
||||||
*/
|
*/
|
||||||
@ -627,7 +637,8 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm
|
|||||||
struct iterm_name_combo *names;
|
struct iterm_name_combo *names;
|
||||||
|
|
||||||
if (iterm->name)
|
if (iterm->name)
|
||||||
return snd_usb_copy_string_desc(state, iterm->name, name, maxlen);
|
return snd_usb_copy_string_desc(state, iterm->name,
|
||||||
|
name, maxlen);
|
||||||
|
|
||||||
/* virtual type - not a real terminal */
|
/* virtual type - not a real terminal */
|
||||||
if (iterm->type >> 16) {
|
if (iterm->type >> 16) {
|
||||||
@ -635,13 +646,17 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm
|
|||||||
return 0;
|
return 0;
|
||||||
switch (iterm->type >> 16) {
|
switch (iterm->type >> 16) {
|
||||||
case UAC_SELECTOR_UNIT:
|
case UAC_SELECTOR_UNIT:
|
||||||
strcpy(name, "Selector"); return 8;
|
strcpy(name, "Selector");
|
||||||
|
return 8;
|
||||||
case UAC1_PROCESSING_UNIT:
|
case UAC1_PROCESSING_UNIT:
|
||||||
strcpy(name, "Process Unit"); return 12;
|
strcpy(name, "Process Unit");
|
||||||
|
return 12;
|
||||||
case UAC1_EXTENSION_UNIT:
|
case UAC1_EXTENSION_UNIT:
|
||||||
strcpy(name, "Ext Unit"); return 8;
|
strcpy(name, "Ext Unit");
|
||||||
|
return 8;
|
||||||
case UAC_MIXER_UNIT:
|
case UAC_MIXER_UNIT:
|
||||||
strcpy(name, "Mixer"); return 5;
|
strcpy(name, "Mixer");
|
||||||
|
return 5;
|
||||||
default:
|
default:
|
||||||
return sprintf(name, "Unit %d", iterm->id);
|
return sprintf(name, "Unit %d", iterm->id);
|
||||||
}
|
}
|
||||||
@ -649,29 +664,35 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm
|
|||||||
|
|
||||||
switch (iterm->type & 0xff00) {
|
switch (iterm->type & 0xff00) {
|
||||||
case 0x0100:
|
case 0x0100:
|
||||||
strcpy(name, "PCM"); return 3;
|
strcpy(name, "PCM");
|
||||||
|
return 3;
|
||||||
case 0x0200:
|
case 0x0200:
|
||||||
strcpy(name, "Mic"); return 3;
|
strcpy(name, "Mic");
|
||||||
|
return 3;
|
||||||
case 0x0400:
|
case 0x0400:
|
||||||
strcpy(name, "Headset"); return 7;
|
strcpy(name, "Headset");
|
||||||
|
return 7;
|
||||||
case 0x0500:
|
case 0x0500:
|
||||||
strcpy(name, "Phone"); return 5;
|
strcpy(name, "Phone");
|
||||||
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (names = iterm_names; names->type; names++)
|
for (names = iterm_names; names->type; names++) {
|
||||||
if (names->type == iterm->type) {
|
if (names->type == iterm->type) {
|
||||||
strcpy(name, names->name);
|
strcpy(name, names->name);
|
||||||
return strlen(names->name);
|
return strlen(names->name);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* parse the source unit recursively until it reaches to a terminal
|
* parse the source unit recursively until it reaches to a terminal
|
||||||
* or a branched unit.
|
* or a branched unit.
|
||||||
*/
|
*/
|
||||||
static int check_input_term(struct mixer_build *state, int id, struct usb_audio_term *term)
|
static int check_input_term(struct mixer_build *state, int id,
|
||||||
|
struct usb_audio_term *term)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
void *p1;
|
void *p1;
|
||||||
@ -766,7 +787,6 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Feature Unit
|
* Feature Unit
|
||||||
*/
|
*/
|
||||||
@ -794,7 +814,6 @@ static struct usb_feature_control_info audio_feature_info[] = {
|
|||||||
{ "Phase Inverter Control", USB_MIXER_BOOLEAN },
|
{ "Phase Inverter Control", USB_MIXER_BOOLEAN },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* private_free callback */
|
/* private_free callback */
|
||||||
static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
|
static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
|
||||||
{
|
{
|
||||||
@ -802,7 +821,6 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
|
|||||||
kctl->private_data = NULL;
|
kctl->private_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* interface to ALSA control for feature/mixer units
|
* interface to ALSA control for feature/mixer units
|
||||||
*/
|
*/
|
||||||
@ -906,7 +924,6 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
|
|||||||
cval->res = 384;
|
cval->res = 384;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -939,21 +956,26 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
|
|||||||
get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) {
|
get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) {
|
||||||
usb_audio_err(cval->mixer->chip,
|
usb_audio_err(cval->mixer->chip,
|
||||||
"%d:%d: cannot get min/max values for control %d (id %d)\n",
|
"%d:%d: cannot get min/max values for control %d (id %d)\n",
|
||||||
cval->id, snd_usb_ctrl_intf(cval->mixer->chip), cval->control, cval->id);
|
cval->id, snd_usb_ctrl_intf(cval->mixer->chip),
|
||||||
|
cval->control, cval->id);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) {
|
if (get_ctl_value(cval, UAC_GET_RES,
|
||||||
|
(cval->control << 8) | minchn,
|
||||||
|
&cval->res) < 0) {
|
||||||
cval->res = 1;
|
cval->res = 1;
|
||||||
} else {
|
} else {
|
||||||
int last_valid_res = cval->res;
|
int last_valid_res = cval->res;
|
||||||
|
|
||||||
while (cval->res > 1) {
|
while (cval->res > 1) {
|
||||||
if (snd_usb_mixer_set_ctl_value(cval, UAC_SET_RES,
|
if (snd_usb_mixer_set_ctl_value(cval, UAC_SET_RES,
|
||||||
(cval->control << 8) | minchn, cval->res / 2) < 0)
|
(cval->control << 8) | minchn,
|
||||||
|
cval->res / 2) < 0)
|
||||||
break;
|
break;
|
||||||
cval->res /= 2;
|
cval->res /= 2;
|
||||||
}
|
}
|
||||||
if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0)
|
if (get_ctl_value(cval, UAC_GET_RES,
|
||||||
|
(cval->control << 8) | minchn, &cval->res) < 0)
|
||||||
cval->res = last_valid_res;
|
cval->res = last_valid_res;
|
||||||
}
|
}
|
||||||
if (cval->res == 0)
|
if (cval->res == 0)
|
||||||
@ -1017,7 +1039,8 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
|
|||||||
#define get_min_max(cval, def) get_min_max_with_quirks(cval, def, NULL)
|
#define get_min_max(cval, def) get_min_max_with_quirks(cval, def, NULL)
|
||||||
|
|
||||||
/* get a feature/mixer unit info */
|
/* get a feature/mixer unit info */
|
||||||
static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
|
static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
struct usb_mixer_elem_info *cval = kcontrol->private_data;
|
struct usb_mixer_elem_info *cval = kcontrol->private_data;
|
||||||
|
|
||||||
@ -1051,7 +1074,8 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* get the current value from feature/mixer unit */
|
/* get the current value from feature/mixer unit */
|
||||||
static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
{
|
{
|
||||||
struct usb_mixer_elem_info *cval = kcontrol->private_data;
|
struct usb_mixer_elem_info *cval = kcontrol->private_data;
|
||||||
int c, cnt, val, err;
|
int c, cnt, val, err;
|
||||||
@ -1082,7 +1106,8 @@ static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* put the current value to feature/mixer unit */
|
/* put the current value to feature/mixer unit */
|
||||||
static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
{
|
{
|
||||||
struct usb_mixer_elem_info *cval = kcontrol->private_data;
|
struct usb_mixer_elem_info *cval = kcontrol->private_data;
|
||||||
int c, cnt, val, oval, err;
|
int c, cnt, val, oval, err;
|
||||||
@ -1136,22 +1161,25 @@ static struct snd_kcontrol_new usb_feature_unit_ctl_ro = {
|
|||||||
.put = NULL,
|
.put = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This symbol is exported in order to allow the mixer quirks to
|
/*
|
||||||
* hook up to the standard feature unit control mechanism */
|
* This symbol is exported in order to allow the mixer quirks to
|
||||||
|
* hook up to the standard feature unit control mechanism
|
||||||
|
*/
|
||||||
struct snd_kcontrol_new *snd_usb_feature_unit_ctl = &usb_feature_unit_ctl;
|
struct snd_kcontrol_new *snd_usb_feature_unit_ctl = &usb_feature_unit_ctl;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* build a feature control
|
* build a feature control
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str)
|
static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str)
|
||||||
{
|
{
|
||||||
return strlcat(kctl->id.name, str, sizeof(kctl->id.name));
|
return strlcat(kctl->id.name, str, sizeof(kctl->id.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A lot of headsets/headphones have a "Speaker" mixer. Make sure we
|
/*
|
||||||
rename it to "Headphone". We determine if something is a headphone
|
* A lot of headsets/headphones have a "Speaker" mixer. Make sure we
|
||||||
similar to how udev determines form factor. */
|
* rename it to "Headphone". We determine if something is a headphone
|
||||||
|
* similar to how udev determines form factor.
|
||||||
|
*/
|
||||||
static void check_no_speaker_on_headset(struct snd_kcontrol *kctl,
|
static void check_no_speaker_on_headset(struct snd_kcontrol *kctl,
|
||||||
struct snd_card *card)
|
struct snd_card *card)
|
||||||
{
|
{
|
||||||
@ -1201,7 +1229,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
|
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
|
||||||
if (! cval) {
|
if (!cval) {
|
||||||
usb_audio_err(state->chip, "cannot malloc kcontrol\n");
|
usb_audio_err(state->chip, "cannot malloc kcontrol\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1222,15 +1250,17 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
|
|||||||
cval->ch_readonly = readonly_mask;
|
cval->ch_readonly = readonly_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if all channels in the mask are marked read-only, make the control
|
/*
|
||||||
|
* If all channels in the mask are marked read-only, make the control
|
||||||
* read-only. set_cur_mix_value() will check the mask again and won't
|
* read-only. set_cur_mix_value() will check the mask again and won't
|
||||||
* issue write commands to read-only channels. */
|
* issue write commands to read-only channels.
|
||||||
|
*/
|
||||||
if (cval->channels == readonly_mask)
|
if (cval->channels == readonly_mask)
|
||||||
kctl = snd_ctl_new1(&usb_feature_unit_ctl_ro, cval);
|
kctl = snd_ctl_new1(&usb_feature_unit_ctl_ro, cval);
|
||||||
else
|
else
|
||||||
kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);
|
kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);
|
||||||
|
|
||||||
if (! kctl) {
|
if (!kctl) {
|
||||||
usb_audio_err(state->chip, "cannot malloc kcontrol\n");
|
usb_audio_err(state->chip, "cannot malloc kcontrol\n");
|
||||||
kfree(cval);
|
kfree(cval);
|
||||||
return;
|
return;
|
||||||
@ -1239,48 +1269,53 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
|
|||||||
|
|
||||||
len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
|
len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
|
||||||
mapped_name = len != 0;
|
mapped_name = len != 0;
|
||||||
if (! len && nameid)
|
if (!len && nameid)
|
||||||
len = snd_usb_copy_string_desc(state, nameid,
|
len = snd_usb_copy_string_desc(state, nameid,
|
||||||
kctl->id.name, sizeof(kctl->id.name));
|
kctl->id.name, sizeof(kctl->id.name));
|
||||||
|
|
||||||
switch (control) {
|
switch (control) {
|
||||||
case UAC_FU_MUTE:
|
case UAC_FU_MUTE:
|
||||||
case UAC_FU_VOLUME:
|
case UAC_FU_VOLUME:
|
||||||
/* determine the control name. the rule is:
|
/*
|
||||||
|
* determine the control name. the rule is:
|
||||||
* - if a name id is given in descriptor, use it.
|
* - if a name id is given in descriptor, use it.
|
||||||
* - if the connected input can be determined, then use the name
|
* - if the connected input can be determined, then use the name
|
||||||
* of terminal type.
|
* of terminal type.
|
||||||
* - if the connected output can be determined, use it.
|
* - if the connected output can be determined, use it.
|
||||||
* - otherwise, anonymous name.
|
* - otherwise, anonymous name.
|
||||||
*/
|
*/
|
||||||
if (! len) {
|
if (!len) {
|
||||||
len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 1);
|
len = get_term_name(state, iterm, kctl->id.name,
|
||||||
if (! len)
|
sizeof(kctl->id.name), 1);
|
||||||
len = get_term_name(state, &state->oterm, kctl->id.name, sizeof(kctl->id.name), 1);
|
if (!len)
|
||||||
if (! len)
|
len = get_term_name(state, &state->oterm,
|
||||||
len = snprintf(kctl->id.name, sizeof(kctl->id.name),
|
kctl->id.name,
|
||||||
|
sizeof(kctl->id.name), 1);
|
||||||
|
if (!len)
|
||||||
|
len = snprintf(kctl->id.name,
|
||||||
|
sizeof(kctl->id.name),
|
||||||
"Feature %d", unitid);
|
"Feature %d", unitid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mapped_name)
|
if (!mapped_name)
|
||||||
check_no_speaker_on_headset(kctl, state->mixer->chip->card);
|
check_no_speaker_on_headset(kctl, state->mixer->chip->card);
|
||||||
|
|
||||||
/* determine the stream direction:
|
/*
|
||||||
|
* determine the stream direction:
|
||||||
* if the connected output is USB stream, then it's likely a
|
* if the connected output is USB stream, then it's likely a
|
||||||
* capture stream. otherwise it should be playback (hopefully :)
|
* capture stream. otherwise it should be playback (hopefully :)
|
||||||
*/
|
*/
|
||||||
if (! mapped_name && ! (state->oterm.type >> 16)) {
|
if (!mapped_name && !(state->oterm.type >> 16)) {
|
||||||
if ((state->oterm.type & 0xff00) == 0x0100) {
|
if ((state->oterm.type & 0xff00) == 0x0100)
|
||||||
len = append_ctl_name(kctl, " Capture");
|
len = append_ctl_name(kctl, " Capture");
|
||||||
} else {
|
else
|
||||||
len = append_ctl_name(kctl, " Playback");
|
len = append_ctl_name(kctl, " Playback");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
append_ctl_name(kctl, control == UAC_FU_MUTE ?
|
append_ctl_name(kctl, control == UAC_FU_MUTE ?
|
||||||
" Switch" : " Volume");
|
" Switch" : " Volume");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (! len)
|
if (!len)
|
||||||
strlcpy(kctl->id.name, audio_feature_info[control-1].name,
|
strlcpy(kctl->id.name, audio_feature_info[control-1].name,
|
||||||
sizeof(kctl->id.name));
|
sizeof(kctl->id.name));
|
||||||
break;
|
break;
|
||||||
@ -1300,33 +1335,35 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
range = (cval->max - cval->min) / cval->res;
|
range = (cval->max - cval->min) / cval->res;
|
||||||
/* Are there devices with volume range more than 255? I use a bit more
|
/*
|
||||||
|
* Are there devices with volume range more than 255? I use a bit more
|
||||||
* to be sure. 384 is a resolution magic number found on Logitech
|
* to be sure. 384 is a resolution magic number found on Logitech
|
||||||
* devices. It will definitively catch all buggy Logitech devices.
|
* devices. It will definitively catch all buggy Logitech devices.
|
||||||
*/
|
*/
|
||||||
if (range > 384) {
|
if (range > 384) {
|
||||||
usb_audio_warn(state->chip, "Warning! Unlikely big "
|
usb_audio_warn(state->chip,
|
||||||
"volume range (=%u), cval->res is probably wrong.",
|
"Warning! Unlikely big volume range (=%u), "
|
||||||
range);
|
"cval->res is probably wrong.",
|
||||||
|
range);
|
||||||
usb_audio_warn(state->chip, "[%d] FU [%s] ch = %d, "
|
usb_audio_warn(state->chip, "[%d] FU [%s] ch = %d, "
|
||||||
"val = %d/%d/%d", cval->id,
|
"val = %d/%d/%d", cval->id,
|
||||||
kctl->id.name, cval->channels,
|
kctl->id.name, cval->channels,
|
||||||
cval->min, cval->max, cval->res);
|
cval->min, cval->max, cval->res);
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_audio_dbg(state->chip, "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
|
usb_audio_dbg(state->chip, "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
|
||||||
cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res);
|
cval->id, kctl->id.name, cval->channels,
|
||||||
|
cval->min, cval->max, cval->res);
|
||||||
snd_usb_mixer_add_control(state->mixer, kctl);
|
snd_usb_mixer_add_control(state->mixer, kctl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* parse a feature unit
|
* parse a feature unit
|
||||||
*
|
*
|
||||||
* most of controls are defined here.
|
* most of controls are defined here.
|
||||||
*/
|
*/
|
||||||
static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void *_ftr)
|
static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
|
||||||
|
void *_ftr)
|
||||||
{
|
{
|
||||||
int channels, i, j;
|
int channels, i, j;
|
||||||
struct usb_audio_term iterm;
|
struct usb_audio_term iterm;
|
||||||
@ -1400,15 +1437,25 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
|
|||||||
for (i = 0; i < 10; i++) {
|
for (i = 0; i < 10; i++) {
|
||||||
unsigned int ch_bits = 0;
|
unsigned int ch_bits = 0;
|
||||||
for (j = 0; j < channels; j++) {
|
for (j = 0; j < channels; j++) {
|
||||||
unsigned int mask = snd_usb_combine_bytes(bmaControls + csize * (j+1), csize);
|
unsigned int mask;
|
||||||
|
|
||||||
|
mask = snd_usb_combine_bytes(bmaControls +
|
||||||
|
csize * (j+1), csize);
|
||||||
if (mask & (1 << i))
|
if (mask & (1 << i))
|
||||||
ch_bits |= (1 << j);
|
ch_bits |= (1 << j);
|
||||||
}
|
}
|
||||||
/* audio class v1 controls are never read-only */
|
/* audio class v1 controls are never read-only */
|
||||||
if (ch_bits & 1) /* the first channel must be set (for ease of programming) */
|
|
||||||
build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid, 0);
|
/*
|
||||||
|
* The first channel must be set
|
||||||
|
* (for ease of programming).
|
||||||
|
*/
|
||||||
|
if (ch_bits & 1)
|
||||||
|
build_feature_ctl(state, _ftr, ch_bits, i,
|
||||||
|
&iterm, unitid, 0);
|
||||||
if (master_bits & (1 << i))
|
if (master_bits & (1 << i))
|
||||||
build_feature_ctl(state, _ftr, 0, i, &iterm, unitid, 0);
|
build_feature_ctl(state, _ftr, 0, i, &iterm,
|
||||||
|
unitid, 0);
|
||||||
}
|
}
|
||||||
} else { /* UAC_VERSION_2 */
|
} else { /* UAC_VERSION_2 */
|
||||||
for (i = 0; i < ARRAY_SIZE(audio_feature_info); i++) {
|
for (i = 0; i < ARRAY_SIZE(audio_feature_info); i++) {
|
||||||
@ -1416,7 +1463,10 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
|
|||||||
unsigned int ch_read_only = 0;
|
unsigned int ch_read_only = 0;
|
||||||
|
|
||||||
for (j = 0; j < channels; j++) {
|
for (j = 0; j < channels; j++) {
|
||||||
unsigned int mask = snd_usb_combine_bytes(bmaControls + csize * (j+1), csize);
|
unsigned int mask;
|
||||||
|
|
||||||
|
mask = snd_usb_combine_bytes(bmaControls +
|
||||||
|
csize * (j+1), csize);
|
||||||
if (uac2_control_is_readable(mask, i)) {
|
if (uac2_control_is_readable(mask, i)) {
|
||||||
ch_bits |= (1 << j);
|
ch_bits |= (1 << j);
|
||||||
if (!uac2_control_is_writeable(mask, i))
|
if (!uac2_control_is_writeable(mask, i))
|
||||||
@ -1424,12 +1474,22 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: build_feature_ctl() will mark the control read-only if all channels
|
/*
|
||||||
* are marked read-only in the descriptors. Otherwise, the control will be
|
* NOTE: build_feature_ctl() will mark the control
|
||||||
* reported as writeable, but the driver will not actually issue a write
|
* read-only if all channels are marked read-only in
|
||||||
* command for read-only channels */
|
* the descriptors. Otherwise, the control will be
|
||||||
if (ch_bits & 1) /* the first channel must be set (for ease of programming) */
|
* reported as writeable, but the driver will not
|
||||||
build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid, ch_read_only);
|
* actually issue a write command for read-only
|
||||||
|
* channels.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The first channel must be set
|
||||||
|
* (for ease of programming).
|
||||||
|
*/
|
||||||
|
if (ch_bits & 1)
|
||||||
|
build_feature_ctl(state, _ftr, ch_bits, i,
|
||||||
|
&iterm, unitid, ch_read_only);
|
||||||
if (uac2_control_is_readable(master_bits, i))
|
if (uac2_control_is_readable(master_bits, i))
|
||||||
build_feature_ctl(state, _ftr, 0, i, &iterm, unitid,
|
build_feature_ctl(state, _ftr, 0, i, &iterm, unitid,
|
||||||
!uac2_control_is_writeable(master_bits, i));
|
!uac2_control_is_writeable(master_bits, i));
|
||||||
@ -1439,7 +1499,6 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mixer Unit
|
* Mixer Unit
|
||||||
*/
|
*/
|
||||||
@ -1450,7 +1509,6 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
|
|||||||
* the callbacks are identical with feature unit.
|
* the callbacks are identical with feature unit.
|
||||||
* input channel number (zero based) is given in control field instead.
|
* input channel number (zero based) is given in control field instead.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void build_mixer_unit_ctl(struct mixer_build *state,
|
static void build_mixer_unit_ctl(struct mixer_build *state,
|
||||||
struct uac_mixer_unit_descriptor *desc,
|
struct uac_mixer_unit_descriptor *desc,
|
||||||
int in_pin, int in_ch, int unitid,
|
int in_pin, int in_ch, int unitid,
|
||||||
@ -1467,7 +1525,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
|
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
|
||||||
if (! cval)
|
if (!cval)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cval->mixer = state->mixer;
|
cval->mixer = state->mixer;
|
||||||
@ -1475,7 +1533,9 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
|
|||||||
cval->control = in_ch + 1; /* based on 1 */
|
cval->control = in_ch + 1; /* based on 1 */
|
||||||
cval->val_type = USB_MIXER_S16;
|
cval->val_type = USB_MIXER_S16;
|
||||||
for (i = 0; i < num_outs; i++) {
|
for (i = 0; i < num_outs; i++) {
|
||||||
if (check_matrix_bitmap(uac_mixer_unit_bmControls(desc, state->mixer->protocol), in_ch, i, num_outs)) {
|
__u8 *c = uac_mixer_unit_bmControls(desc, state->mixer->protocol);
|
||||||
|
|
||||||
|
if (check_matrix_bitmap(c, in_ch, i, num_outs)) {
|
||||||
cval->cmask |= (1 << i);
|
cval->cmask |= (1 << i);
|
||||||
cval->channels++;
|
cval->channels++;
|
||||||
}
|
}
|
||||||
@ -1485,7 +1545,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
|
|||||||
get_min_max(cval, 0);
|
get_min_max(cval, 0);
|
||||||
|
|
||||||
kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);
|
kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);
|
||||||
if (! kctl) {
|
if (!kctl) {
|
||||||
usb_audio_err(state->chip, "cannot malloc kcontrol\n");
|
usb_audio_err(state->chip, "cannot malloc kcontrol\n");
|
||||||
kfree(cval);
|
kfree(cval);
|
||||||
return;
|
return;
|
||||||
@ -1493,9 +1553,10 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
|
|||||||
kctl->private_free = usb_mixer_elem_free;
|
kctl->private_free = usb_mixer_elem_free;
|
||||||
|
|
||||||
len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
|
len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
|
||||||
if (! len)
|
if (!len)
|
||||||
len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 0);
|
len = get_term_name(state, iterm, kctl->id.name,
|
||||||
if (! len)
|
sizeof(kctl->id.name), 0);
|
||||||
|
if (!len)
|
||||||
len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1);
|
len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1);
|
||||||
append_ctl_name(kctl, " Volume");
|
append_ctl_name(kctl, " Volume");
|
||||||
|
|
||||||
@ -1504,24 +1565,28 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
|
|||||||
snd_usb_mixer_add_control(state->mixer, kctl);
|
snd_usb_mixer_add_control(state->mixer, kctl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* parse a mixer unit
|
* parse a mixer unit
|
||||||
*/
|
*/
|
||||||
static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, void *raw_desc)
|
static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
|
||||||
|
void *raw_desc)
|
||||||
{
|
{
|
||||||
struct uac_mixer_unit_descriptor *desc = raw_desc;
|
struct uac_mixer_unit_descriptor *desc = raw_desc;
|
||||||
struct usb_audio_term iterm;
|
struct usb_audio_term iterm;
|
||||||
int input_pins, num_ins, num_outs;
|
int input_pins, num_ins, num_outs;
|
||||||
int pin, ich, err;
|
int pin, ich, err;
|
||||||
|
|
||||||
if (desc->bLength < 11 || ! (input_pins = desc->bNrInPins) || ! (num_outs = uac_mixer_unit_bNrChannels(desc))) {
|
if (desc->bLength < 11 || !(input_pins = desc->bNrInPins) ||
|
||||||
usb_audio_err(state->chip, "invalid MIXER UNIT descriptor %d\n", unitid);
|
!(num_outs = uac_mixer_unit_bNrChannels(desc))) {
|
||||||
|
usb_audio_err(state->chip,
|
||||||
|
"invalid MIXER UNIT descriptor %d\n",
|
||||||
|
unitid);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
/* no bmControls field (e.g. Maya44) -> ignore */
|
/* no bmControls field (e.g. Maya44) -> ignore */
|
||||||
if (desc->bLength <= 10 + input_pins) {
|
if (desc->bLength <= 10 + input_pins) {
|
||||||
usb_audio_dbg(state->chip, "MU %d has no bmControls field\n", unitid);
|
usb_audio_dbg(state->chip, "MU %d has no bmControls field\n",
|
||||||
|
unitid);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1535,12 +1600,14 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, void *r
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
num_ins += iterm.channels;
|
num_ins += iterm.channels;
|
||||||
for (; ich < num_ins; ++ich) {
|
for (; ich < num_ins; ich++) {
|
||||||
int och, ich_has_controls = 0;
|
int och, ich_has_controls = 0;
|
||||||
|
|
||||||
for (och = 0; och < num_outs; ++och) {
|
for (och = 0; och < num_outs; och++) {
|
||||||
if (check_matrix_bitmap(uac_mixer_unit_bmControls(desc, state->mixer->protocol),
|
__u8 *c = uac_mixer_unit_bmControls(desc,
|
||||||
ich, och, num_outs)) {
|
state->mixer->protocol);
|
||||||
|
|
||||||
|
if (check_matrix_bitmap(c, ich, och, num_outs)) {
|
||||||
ich_has_controls = 1;
|
ich_has_controls = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1553,13 +1620,13 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, void *r
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Processing Unit / Extension Unit
|
* Processing Unit / Extension Unit
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* get callback for processing/extension unit */
|
/* get callback for processing/extension unit */
|
||||||
static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
{
|
{
|
||||||
struct usb_mixer_elem_info *cval = kcontrol->private_data;
|
struct usb_mixer_elem_info *cval = kcontrol->private_data;
|
||||||
int err, val;
|
int err, val;
|
||||||
@ -1577,7 +1644,8 @@ static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol, struct snd_ctl_
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* put callback for processing/extension unit */
|
/* put callback for processing/extension unit */
|
||||||
static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
{
|
{
|
||||||
struct usb_mixer_elem_info *cval = kcontrol->private_data;
|
struct usb_mixer_elem_info *cval = kcontrol->private_data;
|
||||||
int val, oval, err;
|
int val, oval, err;
|
||||||
@ -1606,7 +1674,6 @@ static struct snd_kcontrol_new mixer_procunit_ctl = {
|
|||||||
.put = mixer_ctl_procunit_put,
|
.put = mixer_ctl_procunit_put,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* predefined data for processing units
|
* predefined data for processing units
|
||||||
*/
|
*/
|
||||||
@ -1697,10 +1764,13 @@ static struct procunit_info extunits[] = {
|
|||||||
{ USB_XU_DEVICE_OPTIONS, "AnalogueIn Soft Limit", soft_limit_xu_info },
|
{ USB_XU_DEVICE_OPTIONS, "AnalogueIn Soft Limit", soft_limit_xu_info },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* build a processing/extension unit
|
* build a processing/extension unit
|
||||||
*/
|
*/
|
||||||
static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw_desc, struct procunit_info *list, char *name)
|
static int build_audio_procunit(struct mixer_build *state, int unitid,
|
||||||
|
void *raw_desc, struct procunit_info *list,
|
||||||
|
char *name)
|
||||||
{
|
{
|
||||||
struct uac_processing_unit_descriptor *desc = raw_desc;
|
struct uac_processing_unit_descriptor *desc = raw_desc;
|
||||||
int num_ins = desc->bNrInPins;
|
int num_ins = desc->bNrInPins;
|
||||||
@ -1733,19 +1803,19 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw
|
|||||||
for (info = list; info && info->type; info++)
|
for (info = list; info && info->type; info++)
|
||||||
if (info->type == type)
|
if (info->type == type)
|
||||||
break;
|
break;
|
||||||
if (! info || ! info->type)
|
if (!info || !info->type)
|
||||||
info = &default_info;
|
info = &default_info;
|
||||||
|
|
||||||
for (valinfo = info->values; valinfo->control; valinfo++) {
|
for (valinfo = info->values; valinfo->control; valinfo++) {
|
||||||
__u8 *controls = uac_processing_unit_bmControls(desc, state->mixer->protocol);
|
__u8 *controls = uac_processing_unit_bmControls(desc, state->mixer->protocol);
|
||||||
|
|
||||||
if (! (controls[valinfo->control / 8] & (1 << ((valinfo->control % 8) - 1))))
|
if (!(controls[valinfo->control / 8] & (1 << ((valinfo->control % 8) - 1))))
|
||||||
continue;
|
continue;
|
||||||
map = find_map(state, unitid, valinfo->control);
|
map = find_map(state, unitid, valinfo->control);
|
||||||
if (check_ignored_ctl(map))
|
if (check_ignored_ctl(map))
|
||||||
continue;
|
continue;
|
||||||
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
|
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
|
||||||
if (! cval) {
|
if (!cval) {
|
||||||
usb_audio_err(state->chip, "cannot malloc kcontrol\n");
|
usb_audio_err(state->chip, "cannot malloc kcontrol\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
@ -1765,7 +1835,8 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw
|
|||||||
cval->initialized = 1;
|
cval->initialized = 1;
|
||||||
} else {
|
} else {
|
||||||
if (type == USB_XU_CLOCK_RATE) {
|
if (type == USB_XU_CLOCK_RATE) {
|
||||||
/* E-Mu USB 0404/0202/TrackerPre/0204
|
/*
|
||||||
|
* E-Mu USB 0404/0202/TrackerPre/0204
|
||||||
* samplerate control quirk
|
* samplerate control quirk
|
||||||
*/
|
*/
|
||||||
cval->min = 0;
|
cval->min = 0;
|
||||||
@ -1777,60 +1848,70 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw
|
|||||||
}
|
}
|
||||||
|
|
||||||
kctl = snd_ctl_new1(&mixer_procunit_ctl, cval);
|
kctl = snd_ctl_new1(&mixer_procunit_ctl, cval);
|
||||||
if (! kctl) {
|
if (!kctl) {
|
||||||
usb_audio_err(state->chip, "cannot malloc kcontrol\n");
|
usb_audio_err(state->chip, "cannot malloc kcontrol\n");
|
||||||
kfree(cval);
|
kfree(cval);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
kctl->private_free = usb_mixer_elem_free;
|
kctl->private_free = usb_mixer_elem_free;
|
||||||
|
|
||||||
if (check_mapped_name(map, kctl->id.name,
|
if (check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name))) {
|
||||||
sizeof(kctl->id.name)))
|
|
||||||
/* nothing */ ;
|
/* nothing */ ;
|
||||||
else if (info->name)
|
} else if (info->name) {
|
||||||
strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name));
|
strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name));
|
||||||
else {
|
} else {
|
||||||
nameid = uac_processing_unit_iProcessing(desc, state->mixer->protocol);
|
nameid = uac_processing_unit_iProcessing(desc, state->mixer->protocol);
|
||||||
len = 0;
|
len = 0;
|
||||||
if (nameid)
|
if (nameid)
|
||||||
len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name));
|
len = snd_usb_copy_string_desc(state, nameid,
|
||||||
if (! len)
|
kctl->id.name,
|
||||||
|
sizeof(kctl->id.name));
|
||||||
|
if (!len)
|
||||||
strlcpy(kctl->id.name, name, sizeof(kctl->id.name));
|
strlcpy(kctl->id.name, name, sizeof(kctl->id.name));
|
||||||
}
|
}
|
||||||
append_ctl_name(kctl, " ");
|
append_ctl_name(kctl, " ");
|
||||||
append_ctl_name(kctl, valinfo->suffix);
|
append_ctl_name(kctl, valinfo->suffix);
|
||||||
|
|
||||||
usb_audio_dbg(state->chip,
|
usb_audio_dbg(state->chip,
|
||||||
"[%d] PU [%s] ch = %d, val = %d/%d\n",
|
"[%d] PU [%s] ch = %d, val = %d/%d\n",
|
||||||
cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
|
cval->id, kctl->id.name, cval->channels,
|
||||||
if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0)
|
cval->min, cval->max);
|
||||||
|
|
||||||
|
err = snd_usb_mixer_add_control(state->mixer, kctl);
|
||||||
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int parse_audio_processing_unit(struct mixer_build *state, int unitid,
|
||||||
static int parse_audio_processing_unit(struct mixer_build *state, int unitid, void *raw_desc)
|
void *raw_desc)
|
||||||
{
|
{
|
||||||
return build_audio_procunit(state, unitid, raw_desc, procunits, "Processing Unit");
|
return build_audio_procunit(state, unitid, raw_desc,
|
||||||
|
procunits, "Processing Unit");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_audio_extension_unit(struct mixer_build *state, int unitid, void *raw_desc)
|
static int parse_audio_extension_unit(struct mixer_build *state, int unitid,
|
||||||
|
void *raw_desc)
|
||||||
{
|
{
|
||||||
/* Note that we parse extension units with processing unit descriptors.
|
/*
|
||||||
* That's ok as the layout is the same */
|
* Note that we parse extension units with processing unit descriptors.
|
||||||
return build_audio_procunit(state, unitid, raw_desc, extunits, "Extension Unit");
|
* That's ok as the layout is the same.
|
||||||
|
*/
|
||||||
|
return build_audio_procunit(state, unitid, raw_desc,
|
||||||
|
extunits, "Extension Unit");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Selector Unit
|
* Selector Unit
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* info callback for selector unit
|
/*
|
||||||
|
* info callback for selector unit
|
||||||
* use an enumerator type for routing
|
* use an enumerator type for routing
|
||||||
*/
|
*/
|
||||||
static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
|
static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
struct usb_mixer_elem_info *cval = kcontrol->private_data;
|
struct usb_mixer_elem_info *cval = kcontrol->private_data;
|
||||||
const char **itemlist = (const char **)kcontrol->private_value;
|
const char **itemlist = (const char **)kcontrol->private_value;
|
||||||
@ -1841,7 +1922,8 @@ static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, struct snd_ctl
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* get callback for selector unit */
|
/* get callback for selector unit */
|
||||||
static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
{
|
{
|
||||||
struct usb_mixer_elem_info *cval = kcontrol->private_data;
|
struct usb_mixer_elem_info *cval = kcontrol->private_data;
|
||||||
int val, err;
|
int val, err;
|
||||||
@ -1860,7 +1942,8 @@ static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, struct snd_ctl_
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* put callback for selector unit */
|
/* put callback for selector unit */
|
||||||
static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
{
|
{
|
||||||
struct usb_mixer_elem_info *cval = kcontrol->private_data;
|
struct usb_mixer_elem_info *cval = kcontrol->private_data;
|
||||||
int val, oval, err;
|
int val, oval, err;
|
||||||
@ -1889,8 +1972,8 @@ static struct snd_kcontrol_new mixer_selectunit_ctl = {
|
|||||||
.put = mixer_ctl_selector_put,
|
.put = mixer_ctl_selector_put,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
/* private free callback.
|
* private free callback.
|
||||||
* free both private_data and private_value
|
* free both private_data and private_value
|
||||||
*/
|
*/
|
||||||
static void usb_mixer_selector_elem_free(struct snd_kcontrol *kctl)
|
static void usb_mixer_selector_elem_free(struct snd_kcontrol *kctl)
|
||||||
@ -1915,7 +1998,8 @@ static void usb_mixer_selector_elem_free(struct snd_kcontrol *kctl)
|
|||||||
/*
|
/*
|
||||||
* parse a selector unit
|
* parse a selector unit
|
||||||
*/
|
*/
|
||||||
static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void *raw_desc)
|
static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
|
||||||
|
void *raw_desc)
|
||||||
{
|
{
|
||||||
struct uac_selector_unit_descriptor *desc = raw_desc;
|
struct uac_selector_unit_descriptor *desc = raw_desc;
|
||||||
unsigned int i, nameid, len;
|
unsigned int i, nameid, len;
|
||||||
@ -1944,7 +2028,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
|
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
|
||||||
if (! cval) {
|
if (!cval) {
|
||||||
usb_audio_err(state->chip, "cannot malloc kcontrol\n");
|
usb_audio_err(state->chip, "cannot malloc kcontrol\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
@ -1963,7 +2047,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
|
|||||||
cval->control = 0;
|
cval->control = 0;
|
||||||
|
|
||||||
namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL);
|
namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL);
|
||||||
if (! namelist) {
|
if (!namelist) {
|
||||||
usb_audio_err(state->chip, "cannot malloc\n");
|
usb_audio_err(state->chip, "cannot malloc\n");
|
||||||
kfree(cval);
|
kfree(cval);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -1973,7 +2057,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
|
|||||||
struct usb_audio_term iterm;
|
struct usb_audio_term iterm;
|
||||||
len = 0;
|
len = 0;
|
||||||
namelist[i] = kmalloc(MAX_ITEM_NAME_LEN, GFP_KERNEL);
|
namelist[i] = kmalloc(MAX_ITEM_NAME_LEN, GFP_KERNEL);
|
||||||
if (! namelist[i]) {
|
if (!namelist[i]) {
|
||||||
usb_audio_err(state->chip, "cannot malloc\n");
|
usb_audio_err(state->chip, "cannot malloc\n");
|
||||||
while (i--)
|
while (i--)
|
||||||
kfree(namelist[i]);
|
kfree(namelist[i]);
|
||||||
@ -2004,11 +2088,12 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
|
|||||||
if (len)
|
if (len)
|
||||||
;
|
;
|
||||||
else if (nameid)
|
else if (nameid)
|
||||||
snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name));
|
snd_usb_copy_string_desc(state, nameid, kctl->id.name,
|
||||||
|
sizeof(kctl->id.name));
|
||||||
else {
|
else {
|
||||||
len = get_term_name(state, &state->oterm,
|
len = get_term_name(state, &state->oterm,
|
||||||
kctl->id.name, sizeof(kctl->id.name), 0);
|
kctl->id.name, sizeof(kctl->id.name), 0);
|
||||||
if (! len)
|
if (!len)
|
||||||
strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name));
|
strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name));
|
||||||
|
|
||||||
if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR)
|
if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR)
|
||||||
@ -2027,7 +2112,6 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* parse an audio unit recursively
|
* parse an audio unit recursively
|
||||||
*/
|
*/
|
||||||
@ -2125,14 +2209,16 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
p = NULL;
|
p = NULL;
|
||||||
while ((p = snd_usb_find_csint_desc(mixer->hostif->extra, mixer->hostif->extralen,
|
while ((p = snd_usb_find_csint_desc(mixer->hostif->extra,
|
||||||
|
mixer->hostif->extralen,
|
||||||
p, UAC_OUTPUT_TERMINAL)) != NULL) {
|
p, UAC_OUTPUT_TERMINAL)) != NULL) {
|
||||||
if (mixer->protocol == UAC_VERSION_1) {
|
if (mixer->protocol == UAC_VERSION_1) {
|
||||||
struct uac1_output_terminal_descriptor *desc = p;
|
struct uac1_output_terminal_descriptor *desc = p;
|
||||||
|
|
||||||
if (desc->bLength < sizeof(*desc))
|
if (desc->bLength < sizeof(*desc))
|
||||||
continue; /* invalid descriptor? */
|
continue; /* invalid descriptor? */
|
||||||
set_bit(desc->bTerminalID, state.unitbitmap); /* mark terminal ID as visited */
|
/* mark terminal ID as visited */
|
||||||
|
set_bit(desc->bTerminalID, state.unitbitmap);
|
||||||
state.oterm.id = desc->bTerminalID;
|
state.oterm.id = desc->bTerminalID;
|
||||||
state.oterm.type = le16_to_cpu(desc->wTerminalType);
|
state.oterm.type = le16_to_cpu(desc->wTerminalType);
|
||||||
state.oterm.name = desc->iTerminal;
|
state.oterm.name = desc->iTerminal;
|
||||||
@ -2144,7 +2230,8 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
|
|||||||
|
|
||||||
if (desc->bLength < sizeof(*desc))
|
if (desc->bLength < sizeof(*desc))
|
||||||
continue; /* invalid descriptor? */
|
continue; /* invalid descriptor? */
|
||||||
set_bit(desc->bTerminalID, state.unitbitmap); /* mark terminal ID as visited */
|
/* mark terminal ID as visited */
|
||||||
|
set_bit(desc->bTerminalID, state.unitbitmap);
|
||||||
state.oterm.id = desc->bTerminalID;
|
state.oterm.id = desc->bTerminalID;
|
||||||
state.oterm.type = le16_to_cpu(desc->wTerminalType);
|
state.oterm.type = le16_to_cpu(desc->wTerminalType);
|
||||||
state.oterm.name = desc->iTerminal;
|
state.oterm.name = desc->iTerminal;
|
||||||
@ -2152,7 +2239,10 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
|
|||||||
if (err < 0 && err != -EINVAL)
|
if (err < 0 && err != -EINVAL)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
/* for UAC2, use the same approach to also add the clock selectors */
|
/*
|
||||||
|
* For UAC2, use the same approach to also add the
|
||||||
|
* clock selectors
|
||||||
|
*/
|
||||||
err = parse_audio_unit(&state, desc->bCSourceID);
|
err = parse_audio_unit(&state, desc->bCSourceID);
|
||||||
if (err < 0 && err != -EINVAL)
|
if (err < 0 && err != -EINVAL)
|
||||||
return err;
|
return err;
|
||||||
@ -2306,7 +2396,9 @@ static void snd_usb_mixer_interrupt(struct urb *urb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
requeue:
|
requeue:
|
||||||
if (ustatus != -ENOENT && ustatus != -ECONNRESET && ustatus != -ESHUTDOWN) {
|
if (ustatus != -ENOENT &&
|
||||||
|
ustatus != -ECONNRESET &&
|
||||||
|
ustatus != -ESHUTDOWN) {
|
||||||
urb->dev = mixer->chip->dev;
|
urb->dev = mixer->chip->dev;
|
||||||
usb_submit_urb(urb, GFP_ATOMIC);
|
usb_submit_urb(urb, GFP_ATOMIC);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user