aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/mixer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/mixer.c')
-rw-r--r--sound/usb/mixer.c49
1 files changed, 30 insertions, 19 deletions
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index c22fa76e363a..60f65ace7474 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -152,6 +152,7 @@ static inline void check_mapped_dB(const struct usbmix_name_map *p,
152 if (p && p->dB) { 152 if (p && p->dB) {
153 cval->dBmin = p->dB->min; 153 cval->dBmin = p->dB->min;
154 cval->dBmax = p->dB->max; 154 cval->dBmax = p->dB->max;
155 cval->initialized = 1;
155 } 156 }
156} 157}
157 158
@@ -295,7 +296,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
295 if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, 296 if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,
296 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, 297 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
297 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), 298 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
298 buf, val_len, 100) >= val_len) { 299 buf, val_len) >= val_len) {
299 *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); 300 *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
300 snd_usb_autosuspend(cval->mixer->chip); 301 snd_usb_autosuspend(cval->mixer->chip);
301 return 0; 302 return 0;
@@ -332,7 +333,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
332 ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, 333 ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
333 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, 334 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
334 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), 335 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
335 buf, size, 1000); 336 buf, size);
336 snd_usb_autosuspend(chip); 337 snd_usb_autosuspend(chip);
337 338
338 if (ret < 0) { 339 if (ret < 0) {
@@ -444,7 +445,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
444 usb_sndctrlpipe(chip->dev, 0), request, 445 usb_sndctrlpipe(chip->dev, 0), request,
445 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, 446 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
446 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), 447 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
447 buf, val_len, 100) >= 0) { 448 buf, val_len) >= 0) {
448 snd_usb_autosuspend(chip); 449 snd_usb_autosuspend(chip);
449 return 0; 450 return 0;
450 } 451 }
@@ -880,8 +881,17 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_
880 uinfo->value.integer.min = 0; 881 uinfo->value.integer.min = 0;
881 uinfo->value.integer.max = 1; 882 uinfo->value.integer.max = 1;
882 } else { 883 } else {
883 if (! cval->initialized) 884 if (!cval->initialized) {
884 get_min_max(cval, 0); 885 get_min_max(cval, 0);
886 if (cval->initialized && cval->dBmin >= cval->dBmax) {
887 kcontrol->vd[0].access &=
888 ~(SNDRV_CTL_ELEM_ACCESS_TLV_READ |
889 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK);
890 snd_ctl_notify(cval->mixer->chip->card,
891 SNDRV_CTL_EVENT_MASK_INFO,
892 &kcontrol->id);
893 }
894 }
885 uinfo->value.integer.min = 0; 895 uinfo->value.integer.min = 0;
886 uinfo->value.integer.max = 896 uinfo->value.integer.max =
887 (cval->max - cval->min + cval->res - 1) / cval->res; 897 (cval->max - cval->min + cval->res - 1) / cval->res;
@@ -1092,7 +1102,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
1092 " Switch" : " Volume"); 1102 " Switch" : " Volume");
1093 if (control == UAC_FU_VOLUME) { 1103 if (control == UAC_FU_VOLUME) {
1094 check_mapped_dB(map, cval); 1104 check_mapped_dB(map, cval);
1095 if (cval->dBmin < cval->dBmax) { 1105 if (cval->dBmin < cval->dBmax || !cval->initialized) {
1096 kctl->tlv.c = mixer_vol_tlv; 1106 kctl->tlv.c = mixer_vol_tlv;
1097 kctl->vd[0].access |= 1107 kctl->vd[0].access |=
1098 SNDRV_CTL_ELEM_ACCESS_TLV_READ | 1108 SNDRV_CTL_ELEM_ACCESS_TLV_READ |
@@ -1191,6 +1201,11 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
1191 1201
1192 if (state->mixer->protocol == UAC_VERSION_1) { 1202 if (state->mixer->protocol == UAC_VERSION_1) {
1193 csize = hdr->bControlSize; 1203 csize = hdr->bControlSize;
1204 if (!csize) {
1205 snd_printdd(KERN_ERR "usbaudio: unit %u: "
1206 "invalid bControlSize == 0\n", unitid);
1207 return -EINVAL;
1208 }
1194 channels = (hdr->bLength - 7) / csize - 1; 1209 channels = (hdr->bLength - 7) / csize - 1;
1195 bmaControls = hdr->bmaControls; 1210 bmaControls = hdr->bmaControls;
1196 } else { 1211 } else {
@@ -1244,7 +1259,7 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
1244 build_feature_ctl(state, _ftr, 0, i, &iterm, unitid, 0); 1259 build_feature_ctl(state, _ftr, 0, i, &iterm, unitid, 0);
1245 } 1260 }
1246 } else { /* UAC_VERSION_2 */ 1261 } else { /* UAC_VERSION_2 */
1247 for (i = 0; i < 30/2; i++) { 1262 for (i = 0; i < ARRAY_SIZE(audio_feature_info); i++) {
1248 unsigned int ch_bits = 0; 1263 unsigned int ch_bits = 0;
1249 unsigned int ch_read_only = 0; 1264 unsigned int ch_read_only = 0;
1250 1265
@@ -1934,15 +1949,13 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
1934 struct mixer_build state; 1949 struct mixer_build state;
1935 int err; 1950 int err;
1936 const struct usbmix_ctl_map *map; 1951 const struct usbmix_ctl_map *map;
1937 struct usb_host_interface *hostif;
1938 void *p; 1952 void *p;
1939 1953
1940 hostif = mixer->chip->ctrl_intf;
1941 memset(&state, 0, sizeof(state)); 1954 memset(&state, 0, sizeof(state));
1942 state.chip = mixer->chip; 1955 state.chip = mixer->chip;
1943 state.mixer = mixer; 1956 state.mixer = mixer;
1944 state.buffer = hostif->extra; 1957 state.buffer = mixer->hostif->extra;
1945 state.buflen = hostif->extralen; 1958 state.buflen = mixer->hostif->extralen;
1946 1959
1947 /* check the mapping table */ 1960 /* check the mapping table */
1948 for (map = usbmix_ctl_maps; map->id; map++) { 1961 for (map = usbmix_ctl_maps; map->id; map++) {
@@ -1955,7 +1968,8 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
1955 } 1968 }
1956 1969
1957 p = NULL; 1970 p = NULL;
1958 while ((p = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, p, UAC_OUTPUT_TERMINAL)) != NULL) { 1971 while ((p = snd_usb_find_csint_desc(mixer->hostif->extra, mixer->hostif->extralen,
1972 p, UAC_OUTPUT_TERMINAL)) != NULL) {
1959 if (mixer->protocol == UAC_VERSION_1) { 1973 if (mixer->protocol == UAC_VERSION_1) {
1960 struct uac1_output_terminal_descriptor *desc = p; 1974 struct uac1_output_terminal_descriptor *desc = p;
1961 1975
@@ -2162,17 +2176,15 @@ int snd_usb_mixer_activate(struct usb_mixer_interface *mixer)
2162/* create the handler for the optional status interrupt endpoint */ 2176/* create the handler for the optional status interrupt endpoint */
2163static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) 2177static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
2164{ 2178{
2165 struct usb_host_interface *hostif;
2166 struct usb_endpoint_descriptor *ep; 2179 struct usb_endpoint_descriptor *ep;
2167 void *transfer_buffer; 2180 void *transfer_buffer;
2168 int buffer_length; 2181 int buffer_length;
2169 unsigned int epnum; 2182 unsigned int epnum;
2170 2183
2171 hostif = mixer->chip->ctrl_intf;
2172 /* we need one interrupt input endpoint */ 2184 /* we need one interrupt input endpoint */
2173 if (get_iface_desc(hostif)->bNumEndpoints < 1) 2185 if (get_iface_desc(mixer->hostif)->bNumEndpoints < 1)
2174 return 0; 2186 return 0;
2175 ep = get_endpoint(hostif, 0); 2187 ep = get_endpoint(mixer->hostif, 0);
2176 if (!usb_endpoint_dir_in(ep) || !usb_endpoint_xfer_int(ep)) 2188 if (!usb_endpoint_dir_in(ep) || !usb_endpoint_xfer_int(ep))
2177 return 0; 2189 return 0;
2178 2190
@@ -2202,7 +2214,6 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
2202 }; 2214 };
2203 struct usb_mixer_interface *mixer; 2215 struct usb_mixer_interface *mixer;
2204 struct snd_info_entry *entry; 2216 struct snd_info_entry *entry;
2205 struct usb_host_interface *host_iface;
2206 int err; 2217 int err;
2207 2218
2208 strcpy(chip->card->mixername, "USB Mixer"); 2219 strcpy(chip->card->mixername, "USB Mixer");
@@ -2219,8 +2230,8 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
2219 return -ENOMEM; 2230 return -ENOMEM;
2220 } 2231 }
2221 2232
2222 host_iface = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0]; 2233 mixer->hostif = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0];
2223 switch (get_iface_desc(host_iface)->bInterfaceProtocol) { 2234 switch (get_iface_desc(mixer->hostif)->bInterfaceProtocol) {
2224 case UAC_VERSION_1: 2235 case UAC_VERSION_1:
2225 default: 2236 default:
2226 mixer->protocol = UAC_VERSION_1; 2237 mixer->protocol = UAC_VERSION_1;