diff options
Diffstat (limited to 'sound/usb/mixer.c')
-rw-r--r-- | sound/usb/mixer.c | 49 |
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 */ |
2163 | static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) | 2177 | static 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; |