Update of /cvsroot/alsa/alsa-kernel/usb
In directory usw-pr-cvs1:/tmp/cvs-serv19914
Modified Files:
usbmixer.c
Added Files:
usbmixer_maps.c
Log Message:
- added the manual mixer mapping.
used for the complex mixer topology such as SB extigy.
- more strict buffer-overflow checks.
--- NEW FILE: usbmixer_maps.c ---
/*
* Additional mixer mapping
*
* Copyright (c) 2002 by Takashi Iwai <[EMAIL PROTECTED]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
struct usbmix_name_map {
int id;
const char *name;
};
struct usbmix_ctl_map {
int vendor;
int product;
const struct usbmix_name_map *map;
};
/*
* USB control mappers for SB Exitigy
*/
/*
* Topology of SB Extigy (see on the wide screen :)
USB_IN[1] --->FU[2] -----------------------------+->MU[16] - PE[17]-+- FU[18] -+-
EU[27] -+- EU[21] - FU[22] -+- FU[23] > Dig_OUT[24]
| | |
| |
USB_IN[3] -+->SU[5] - FU[6] -+- MU[14] - PE[15] -+ | |
| +- FU[25] > Dig_OUT[26]
^ | | | |
|
Dig_IN[4] -+ | | | |
+- FU[28] --------------------> Spk_OUT[19]
| | | |
Lin-IN[7] -+-- FU[8] --------+ | |
+----------------------------------------> Hph_OUT[20]
| | |
Mic-IN[9] --+- FU[10] ---------------------------+ |
|| |
|| +----------------------------------------------------+
VV V
++--+->SU[11] ->FU[12]
-------------------------------------------------------------------------------------->
USB_OUT[13]
*/
static struct usbmix_name_map extigy_map[] = {
{ 2, "PCM Playback" }, /* FU */
{ 5, "Digital Playback Source" }, /* SU */
{ 6, "Digital" }, /* FU */
{ 8, "Line Playback" }, /* FU */
{ 10, "Mic Playback" }, /* FU */
{ 11, "Capture Source" }, /* SU */
{ 12, "Capture" }, /* FU */
{ 18, "Master Playback" }, /* FU */
/* FIXME: more to come here... */
{ 0 } /* terminator */
};
/*
* Control map entries
*/
static struct usbmix_ctl_map usbmix_ctl_maps[] = {
{ 0x41e, 0x3000, extigy_map },
{ 0 } /* terminator */
};
Index: usbmixer.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/usb/usbmixer.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- usbmixer.c 3 Oct 2002 10:33:09 -0000 1.4
+++ usbmixer.c 10 Oct 2002 13:45:32 -0000 1.5
@@ -103,6 +103,37 @@
/*
+ * manual mapping of mixer names
+ * if the mixer topology is too complicated and the parsed names are
+ * ambiguous, add the entries in usbmixer_maps.c.
+ */
+#include "usbmixer_maps.c"
+
+/* get the mapped name if the unit matches */
+static int check_mapped_name(mixer_build_t *state, int unitid, char *buf, int buflen)
+{
+ const struct usbmix_ctl_map *map;
+ const struct usbmix_name_map *p;
+ struct usb_device_descriptor *dev = &state->chip->dev->descriptor;
+
+ for (map = usbmix_ctl_maps; map->vendor; map++) {
+ if (map->vendor != dev->idVendor ||
+ map->product != dev->idProduct)
+ continue;
+ for (p = map->map; p->id; p++) {
+ if (p->id == unitid) {
+ buflen--;
+ strncpy(buf, p->name, buflen - 1);
+ buf[buflen] = 0;
+ return strlen(buf);
+ }
+ }
+ }
+ return 0;
+}
+
+
+/*
* find an audio control unit with the given unit id
*/
static void *find_audio_control_unit(mixer_build_t *state, unsigned char unit)
@@ -610,7 +641,7 @@
unsigned int ctl_mask, int control,
usb_audio_term_t *iterm, int unitid)
{
- int len = 0;
+ int len = 0, mapped_name = 0;
int nameid = desc[desc[0] - 1];
snd_kcontrol_t *kctl;
usb_mixer_elem_info_t *cval;
@@ -666,7 +697,9 @@
}
kctl->private_free = usb_mixer_elem_free;
- if (nameid)
+ len = check_mapped_name(state, unitid, 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));
switch (control) {
@@ -679,7 +712,7 @@
* - if the connected output can be determined, use it.
* - otherwise, anonymous name.
*/
- if (! nameid) {
+ if (! len) {
len = get_term_name(state, iterm, kctl->id.name,
sizeof(kctl->id.name), 1);
if (! len)
len = get_term_name(state, &state->oterm,
kctl->id.name, sizeof(kctl->id.name), 1);
@@ -690,20 +723,25 @@
* if the connected output is USB stream, then it's likely a
* capture stream. otherwise it should be playback (hopefully :)
*/
- if (! (state->oterm.type >> 16)) {
+ if (! mapped_name && ! (state->oterm.type >> 16)) {
if ((state->oterm.type & 0xff00) == 0x0100) {
- strcpy(kctl->id.name + len, " Capture");
- len += 8;
+ if (len + 8 < sizeof(kctl->id.name)) {
+ strcpy(kctl->id.name + len, " Capture");
+ len += 8;
+ }
} else {
- strcpy(kctl->id.name + len, " Playback");
- len += 9;
+ if (len + 9 < sizeof(kctl->id.name)) {
+ strcpy(kctl->id.name + len, " Playback");
+ len += 9;
+ }
}
}
- strcpy(kctl->id.name + len, control == USB_FEATURE_MUTE ? " Switch" :
" Volume");
+ if (len + 7 < sizeof(kctl->id.name))
+ strcpy(kctl->id.name + len, control == USB_FEATURE_MUTE ? "
+Switch" : " Volume");
break;
default:
- if (! nameid)
+ if (! len)
strcpy(kctl->id.name, audio_feature_info[control].name);
break;
}
@@ -823,10 +861,13 @@
}
kctl->private_free = usb_mixer_elem_free;
- len = get_term_name(state, &iterm, kctl->id.name, sizeof(kctl->id.name), 0);
+ len = check_mapped_name(state, unitid, 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)
len = sprintf(kctl->id.name, "Mixer Source %d", in_ch);
- strcpy(kctl->id.name + len, " Volume");
+ if (len + 7 < sizeof(kctl->id.name))
+ strcpy(kctl->id.name + len, " Volume");
snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n",
cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
@@ -973,7 +1014,7 @@
int num_ins = dsc[6];
usb_mixer_elem_info_t *cval;
snd_kcontrol_t *kctl;
- int i, err, nameid, type;
+ int i, err, nameid, type, len;
struct procunit_info *info;
struct procunit_value_info *valinfo;
static struct procunit_value_info default_value_info[] = {
@@ -1035,17 +1076,25 @@
}
kctl->private_free = usb_mixer_elem_free;
- if (info->name)
- sprintf(kctl->id.name, "%s %s", info->name, valinfo->suffix);
+ if (check_mapped_name(state, unitid, kctl->id.name,
+sizeof(kctl->id.name)))
+ ;
+ else if (info->name)
+ strcpy(kctl->id.name, info->name);
else {
nameid = dsc[12 + num_ins + dsc[11 + num_ins]];
- if (nameid) {
- int len = snd_usb_copy_string_desc(state, nameid,
kctl->id.name, sizeof(kctl->id.name));
- strcpy(kctl->id.name + len, valinfo->suffix);
- } else
- sprintf(kctl->id.name, "%s %s", name, valinfo->suffix);
+ len = 0;
+ if (nameid)
+ len = snd_usb_copy_string_desc(state, nameid,
+kctl->id.name, sizeof(kctl->id.name));
+ if (! len) {
+ strncpy(kctl->id.name, name, sizeof(kctl->id.name) -
+1);
+ kctl->id.name[sizeof(kctl->id.name)-1] = 0;
+ }
+ }
+ len = strlen(kctl->id.name);
+ if (len + sizeof(valinfo->suffix) + 1 < sizeof(kctl->id.name)) {
+ kctl->id.name[len] = ' ';
+ strcpy(kctl->id.name + len + 1, valinfo->suffix);
}
-
snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n",
cval->id, kctl->id.name, cval->channels, cval->min,
cval->max);
if ((err = add_control_to_empty(state->chip->card, kctl)) < 0)
@@ -1158,7 +1207,7 @@
static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned char
*desc)
{
int num_ins = desc[4];
- int i, err, nameid;
+ int i, err, nameid, len;
usb_mixer_elem_info_t *cval;
snd_kcontrol_t *kctl;
char **namelist;
@@ -1196,7 +1245,7 @@
#define MAX_ITEM_NAME_LEN 64
for (i = 0; i < num_ins; i++) {
usb_audio_term_t iterm;
- int len = 0;
+ len = 0;
namelist[i] = kmalloc(MAX_ITEM_NAME_LEN, GFP_KERNEL);
if (! namelist[i]) {
snd_printk(KERN_ERR "cannot malloc\n");
@@ -1222,17 +1271,23 @@
kctl->private_free = usb_mixer_selector_elem_free;
nameid = desc[desc[0] - 1];
- if (nameid)
+ len = check_mapped_name(state, unitid, kctl->id.name, sizeof(kctl->id.name));
+ if (len)
+ ;
+ else if (nameid)
snd_usb_copy_string_desc(state, nameid, kctl->id.name,
sizeof(kctl->id.name));
else {
- int len = get_term_name(state, &state->oterm,
- kctl->id.name, sizeof(kctl->id.name), 0);
+ len = get_term_name(state, &state->oterm,
+ kctl->id.name, sizeof(kctl->id.name), 0);
if (! len)
len = sprintf(kctl->id.name, "USB");
- if ((state->oterm.type & 0xff00) == 0x0100)
- strcpy(kctl->id.name + len, " Capture Source");
- else
- strcpy(kctl->id.name + len, " Playback Source");
+ if ((state->oterm.type & 0xff00) == 0x0100) {
+ if (len + 15 < sizeof(kctl->id.name))
+ strcpy(kctl->id.name + len, " Capture Source");
+ } else {
+ if (len + 16 < sizeof(kctl->id.name))
+ strcpy(kctl->id.name + len, " Playback Source");
+ }
}
snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n",
-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog