Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 182665
b: refs/heads/master
c: c3a3e04
h: refs/heads/master
i:
  182663: 36c09eb
v: v3
  • Loading branch information
Jaroslav Kysela committed Feb 11, 2010
1 parent 8a07383 commit 3986f0a
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 56 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d5e1ca05f758fec2845a97fd7aa1eeca91c51a21
refs/heads/master: c3a3e040f01457d2ea4f199f75ca205401001a3b
125 changes: 76 additions & 49 deletions trunk/sound/usb/usbmixer.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ struct usb_mixer_elem_info {
int channels;
int val_type;
int min, max, res;
int dBmin, dBmax;
int cached;
int cache_val[MAX_CHANNELS];
u8 initialized;
Expand Down Expand Up @@ -194,42 +195,50 @@ enum {
*/
#include "usbmixer_maps.c"

/* get the mapped name if the unit matches */
static int check_mapped_name(struct mixer_build *state, int unitid, int control, char *buf, int buflen)
static const struct usbmix_name_map *
find_map(struct mixer_build *state, int unitid, int control)
{
const struct usbmix_name_map *p;
const struct usbmix_name_map *p = state->map;

if (! state->map)
return 0;
if (!p)
return NULL;

for (p = state->map; p->id; p++) {
if (p->id == unitid && p->name &&
(! control || ! p->control || control == p->control)) {
buflen--;
return strlcpy(buf, p->name, buflen);
}
if (p->id == unitid &&
(!control || !p->control || control == p->control))
return p;
}
return 0;
return NULL;
}

/* check whether the control should be ignored */
static int check_ignored_ctl(struct mixer_build *state, int unitid, int control)
/* get the mapped name if the unit matches */
static int
check_mapped_name(const struct usbmix_name_map *p, char *buf, int buflen)
{
const struct usbmix_name_map *p;
if (!p || !p->name)
return 0;

if (! state->map)
buflen--;
return strlcpy(buf, p->name, buflen);
}

/* check whether the control should be ignored */
static inline int
check_ignored_ctl(const struct usbmix_name_map *p)
{
if (!p || p->name || p->dB)
return 0;
for (p = state->map; p->id; p++) {
if (p->id == unitid && ! p->name &&
(! control || ! p->control || control == p->control)) {
/*
printk(KERN_DEBUG "ignored control %d:%d\n",
unitid, control);
*/
return 1;
}
return 1;
}

/* dB mapping */
static inline void check_mapped_dB(const struct usbmix_name_map *p,
struct usb_mixer_elem_info *cval)
{
if (p && p->dB) {
cval->dBmin = p->dB->min;
cval->dBmax = p->dB->max;
}
return 0;
}

/* get the mapped selector source name */
Expand Down Expand Up @@ -466,20 +475,8 @@ static int mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,

if (size < sizeof(scale))
return -ENOMEM;
/* USB descriptions contain the dB scale in 1/256 dB unit
* while ALSA TLV contains in 1/100 dB unit
*/
scale[2] = (convert_signed_value(cval, cval->min) * 100) / 256;
scale[3] = (convert_signed_value(cval, cval->max) * 100) / 256;
if (scale[3] <= scale[2]) {
/* something is wrong; assume it's either from/to 0dB */
if (scale[2] < 0)
scale[3] = 0;
else if (scale[2] > 0)
scale[2] = 0;
else /* totally crap, return an error */
return -EINVAL;
}
scale[2] = cval->dBmin;
scale[3] = cval->dBmax;
if (copy_to_user(_tlv, scale, sizeof(scale)))
return -EFAULT;
return 0;
Expand Down Expand Up @@ -720,6 +717,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
cval->min = default_min;
cval->max = cval->min + 1;
cval->res = 1;
cval->dBmin = cval->dBmax = 0;

if (cval->val_type == USB_MIXER_BOOLEAN ||
cval->val_type == USB_MIXER_INV_BOOLEAN) {
Expand Down Expand Up @@ -787,6 +785,24 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)

cval->initialized = 1;
}

/* USB descriptions contain the dB scale in 1/256 dB unit
* while ALSA TLV contains in 1/100 dB unit
*/
cval->dBmin = (convert_signed_value(cval, cval->min) * 100) / 256;
cval->dBmax = (convert_signed_value(cval, cval->max) * 100) / 256;
if (cval->dBmin > cval->dBmax) {
/* something is wrong; assume it's either from/to 0dB */
if (cval->dBmin < 0)
cval->dBmax = 0;
else if (cval->dBmin > 0)
cval->dBmin = 0;
if (cval->dBmin > cval->dBmax) {
/* totally crap, return an error */
return -EINVAL;
}
}

return 0;
}

Expand Down Expand Up @@ -912,6 +928,7 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc,
int nameid = desc[desc[0] - 1];
struct snd_kcontrol *kctl;
struct usb_mixer_elem_info *cval;
const struct usbmix_name_map *map;

control++; /* change from zero-based to 1-based value */

Expand All @@ -920,7 +937,8 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc,
return;
}

if (check_ignored_ctl(state, unitid, control))
map = find_map(state, unitid, control);
if (check_ignored_ctl(map))
return;

cval = kzalloc(sizeof(*cval), GFP_KERNEL);
Expand Down Expand Up @@ -954,10 +972,11 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc,
}
kctl->private_free = usb_mixer_elem_free;

len = check_mapped_name(state, unitid, control, kctl->id.name, sizeof(kctl->id.name));
len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
mapped_name = len != 0;
if (! len && nameid)
len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name));
len = snd_usb_copy_string_desc(state, nameid,
kctl->id.name, sizeof(kctl->id.name));

switch (control) {
case USB_FEATURE_MUTE:
Expand Down Expand Up @@ -995,6 +1014,7 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc,
kctl->vd[0].access |=
SNDRV_CTL_ELEM_ACCESS_TLV_READ |
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
check_mapped_dB(map, cval);
}
break;

Expand Down Expand Up @@ -1122,8 +1142,10 @@ static void build_mixer_unit_ctl(struct mixer_build *state, unsigned char *desc,
unsigned int num_outs = desc[5 + input_pins];
unsigned int i, len;
struct snd_kcontrol *kctl;
const struct usbmix_name_map *map;

if (check_ignored_ctl(state, unitid, 0))
map = find_map(state, unitid, 0);
if (check_ignored_ctl(map))
return;

cval = kzalloc(sizeof(*cval), GFP_KERNEL);
Expand Down Expand Up @@ -1152,7 +1174,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, unsigned char *desc,
}
kctl->private_free = usb_mixer_elem_free;

len = check_mapped_name(state, unitid, 0, kctl->id.name, sizeof(kctl->id.name));
len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
if (! len)
len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 0);
if (! len)
Expand Down Expand Up @@ -1342,6 +1364,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned
int i, err, nameid, type, len;
struct procunit_info *info;
struct procunit_value_info *valinfo;
const struct usbmix_name_map *map;
static struct procunit_value_info default_value_info[] = {
{ 0x01, "Switch", USB_MIXER_BOOLEAN },
{ 0 }
Expand Down Expand Up @@ -1371,7 +1394,8 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned
/* FIXME: bitmap might be longer than 8bit */
if (! (dsc[12 + num_ins] & (1 << (valinfo->control - 1))))
continue;
if (check_ignored_ctl(state, unitid, valinfo->control))
map = find_map(state, unitid, valinfo->control);
if (check_ignored_ctl(map))
continue;
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
if (! cval) {
Expand Down Expand Up @@ -1402,8 +1426,9 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned
}
kctl->private_free = usb_mixer_elem_free;

if (check_mapped_name(state, unitid, cval->control, kctl->id.name, sizeof(kctl->id.name)))
;
if (check_mapped_name(map, kctl->id.name,
sizeof(kctl->id.name)))
/* nothing */ ;
else if (info->name)
strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name));
else {
Expand Down Expand Up @@ -1542,6 +1567,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi
int err;
struct usb_mixer_elem_info *cval;
struct snd_kcontrol *kctl;
const struct usbmix_name_map *map;
char **namelist;

if (! num_ins || desc[0] < 5 + num_ins) {
Expand All @@ -1557,7 +1583,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi
if (num_ins == 1) /* only one ? nonsense! */
return 0;

if (check_ignored_ctl(state, unitid, 0))
map = find_map(state, unitid, 0);
if (check_ignored_ctl(map))
return 0;

cval = kzalloc(sizeof(*cval), GFP_KERNEL);
Expand Down Expand Up @@ -1612,7 +1639,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi
kctl->private_free = usb_mixer_selector_elem_free;

nameid = desc[desc[0] - 1];
len = check_mapped_name(state, unitid, 0, kctl->id.name, sizeof(kctl->id.name));
len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
if (len)
;
else if (nameid)
Expand Down
23 changes: 17 additions & 6 deletions trunk/sound/usb/usbmixer_maps.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,16 @@
*
*/

struct usbmix_dB_map {
u32 min;
u32 max;
};

struct usbmix_name_map {
int id;
const char *name;
int control;
struct usbmix_dB_map *dB;
};

struct usbmix_selector_map {
Expand Down Expand Up @@ -72,7 +77,7 @@ static struct usbmix_name_map extigy_map[] = {
{ 8, "Line Playback" }, /* FU */
/* 9: IT mic */
{ 10, "Mic Playback" }, /* FU */
{ 11, "Capture Input Source" }, /* SU */
{ 11, "Capture Source" }, /* SU */
{ 12, "Capture" }, /* FU */
/* 13: OT pcm capture */
/* 14: MU (w/o controls) */
Expand Down Expand Up @@ -102,6 +107,9 @@ static struct usbmix_name_map extigy_map[] = {
* e.g. no Master and fake PCM volume
* Pavel Mihaylov <bin@bash.info>
*/
static struct usbmix_dB_map mp3plus_dB_1 = {-4781, 0}; /* just guess */
static struct usbmix_dB_map mp3plus_dB_2 = {-1781, 618}; /* just guess */

static struct usbmix_name_map mp3plus_map[] = {
/* 1: IT pcm */
/* 2: IT mic */
Expand All @@ -110,16 +118,19 @@ static struct usbmix_name_map mp3plus_map[] = {
/* 5: OT digital out */
/* 6: OT speaker */
/* 7: OT pcm capture */
{ 8, "Capture Input Source" }, /* FU, default PCM Capture Source */
{ 8, "Capture Source" }, /* FU, default PCM Capture Source */
/* (Mic, Input 1 = Line input, Input 2 = Optical input) */
{ 9, "Master Playback" }, /* FU, default Speaker 1 */
/* { 10, "Mic Capture", 1 }, */ /* FU, Mic Capture */
/* { 10, "Mic Capture", 2 }, */ /* FU, Mic Capture */
{ 10, /* "Mic Capture", */ NULL, 2, .dB = &mp3plus_dB_2 },
/* FU, Mic Capture */
{ 10, "Mic Boost", 7 }, /* FU, default Auto Gain Input */
{ 11, "Line Capture" }, /* FU, default PCM Capture */
{ 11, "Line Capture", .dB = &mp3plus_dB_2 },
/* FU, default PCM Capture */
{ 12, "Digital In Playback" }, /* FU, default PCM 1 */
/* { 13, "Mic Playback" }, */ /* FU, default Mic Playback */
{ 14, "Line Playback" }, /* FU, default Speaker */
{ 13, /* "Mic Playback", */ .dB = &mp3plus_dB_1 },
/* FU, default Mic Playback */
{ 14, "Line Playback", .dB = &mp3plus_dB_1 }, /* FU, default Speaker */
/* 15: MU */
{ 0 } /* terminator */
};
Expand Down

0 comments on commit 3986f0a

Please sign in to comment.