diff options
Diffstat (limited to 'sound/usb/mixer.c')
| -rw-r--r-- | sound/usb/mixer.c | 259 |
1 files changed, 143 insertions, 116 deletions
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 9105ec623120..3af71d42b9b9 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -313,8 +313,8 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int timeout = 10; int idx = 0, err; - err = snd_usb_lock_shutdown(chip); - if (err < 0) + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) return -EIO; while (timeout-- > 0) { @@ -324,20 +324,15 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, validx, idx, buf, val_len); if (err >= val_len) { *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); - err = 0; - goto out; + return 0; } else if (err == -ETIMEDOUT) { - goto out; + return err; } } usb_audio_dbg(chip, "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", request, validx, idx, cval->val_type); - err = -EINVAL; - - out: - snd_usb_unlock_shutdown(chip); - return err; + return -EINVAL; } static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, @@ -362,14 +357,16 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, memset(buf, 0, sizeof(buf)); - if (snd_usb_lock_shutdown(chip)) - return -EIO; + { + CLASS(snd_usb_lock, pm)(chip); + if (pm.err) + return -EIO; - idx = mixer_ctrl_intf(cval->head.mixer) | (cval->head.id << 8); - ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, - USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - validx, idx, buf, size); - snd_usb_unlock_shutdown(chip); + idx = mixer_ctrl_intf(cval->head.mixer) | (cval->head.id << 8); + ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, + validx, idx, buf, size); + } if (ret < 0) { usb_audio_dbg(chip, @@ -433,7 +430,7 @@ int snd_usb_get_cur_mix_value(struct usb_mixer_elem_info *cval, { int err; - if (cval->cached & (1 << channel)) { + if (cval->cached & BIT(channel)) { *value = cval->cache_val[index]; return 0; } @@ -445,7 +442,7 @@ int snd_usb_get_cur_mix_value(struct usb_mixer_elem_info *cval, cval->control, channel, err); return err; } - cval->cached |= 1 << channel; + cval->cached |= BIT(channel); cval->cache_val[index] = *value; return 0; } @@ -484,8 +481,8 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, buf[2] = (value_set >> 16) & 0xff; buf[3] = (value_set >> 24) & 0xff; - err = snd_usb_lock_shutdown(chip); - if (err < 0) + CLASS(snd_usb_lock, pm)(chip); + if (pm.err < 0) return -EIO; while (timeout-- > 0) { @@ -494,20 +491,14 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, usb_sndctrlpipe(chip->dev, 0), request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, validx, idx, buf, val_len); - if (err >= 0) { - err = 0; - goto out; - } else if (err == -ETIMEDOUT) { - goto out; - } + if (err >= 0) + return 0; + else if (err == -ETIMEDOUT) + return err; } 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]); - err = -EINVAL; - - out: - snd_usb_unlock_shutdown(chip); - return err; + return -EINVAL; } static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, @@ -522,7 +513,7 @@ int snd_usb_set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int err; unsigned int read_only = (channel == 0) ? cval->master_readonly : - cval->ch_readonly & (1 << (channel - 1)); + cval->ch_readonly & BIT(channel - 1); if (read_only) { usb_audio_dbg(cval->head.mixer->chip, @@ -536,7 +527,7 @@ int snd_usb_set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, value); if (err < 0) return err; - cval->cached |= 1 << channel; + cval->cached |= BIT(channel); cval->cache_val[index] = value; return 0; } @@ -547,7 +538,7 @@ int snd_usb_set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, unsigned int size, unsigned int __user *_tlv) { - struct usb_mixer_elem_info *cval = kcontrol->private_data; + struct usb_mixer_elem_info *cval = snd_kcontrol_chip(kcontrol); DECLARE_TLV_DB_MINMAX(scale, 0, 0); if (size < sizeof(scale)) @@ -674,40 +665,40 @@ static int get_term_name(struct snd_usb_audio *chip, struct usb_audio_term *iter return 0; switch (iterm->type >> 16) { case UAC3_SELECTOR_UNIT: - strcpy(name, "Selector"); + strscpy(name, "Selector", maxlen); return 8; case UAC3_PROCESSING_UNIT: - strcpy(name, "Process Unit"); + strscpy(name, "Process Unit", maxlen); return 12; case UAC3_EXTENSION_UNIT: - strcpy(name, "Ext Unit"); + strscpy(name, "Ext Unit", maxlen); return 8; case UAC3_MIXER_UNIT: - strcpy(name, "Mixer"); + strscpy(name, "Mixer", maxlen); return 5; default: - return sprintf(name, "Unit %d", iterm->id); + return scnprintf(name, maxlen, "Unit %d", iterm->id); } } switch (iterm->type & 0xff00) { case 0x0100: - strcpy(name, "PCM"); + strscpy(name, "PCM", maxlen); return 3; case 0x0200: - strcpy(name, "Mic"); + strscpy(name, "Mic", maxlen); return 3; case 0x0400: - strcpy(name, "Headset"); + strscpy(name, "Headset", maxlen); return 7; case 0x0500: - strcpy(name, "Phone"); + strscpy(name, "Phone", maxlen); return 5; } for (names = iterm_names; names->type; names++) { if (names->type == iterm->type) { - strcpy(name, names->name); + strscpy(name, names->name, maxlen); return strlen(names->name); } } @@ -728,7 +719,7 @@ static int get_cluster_channels_v3(struct mixer_build *state, unsigned int clust UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, cluster_id, - snd_usb_ctrl_intf(state->chip), + snd_usb_ctrl_intf(state->mixer->hostif), &c_header, sizeof(c_header)); if (err < 0) goto error; @@ -930,7 +921,7 @@ static int parse_term_uac2_clock_source(struct mixer_build *state, { struct uac_clock_source_descriptor *d = p1; - term->type = UAC3_CLOCK_SOURCE << 16; /* virtual type */ + term->type = UAC2_CLOCK_SOURCE << 16; /* virtual type */ term->id = id; term->name = d->iClockSource; return 0; @@ -1084,6 +1075,21 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, struct snd_kcontrol *kctl) { struct snd_usb_audio *chip = cval->head.mixer->chip; + + if (chip->quirk_flags & QUIRK_FLAG_MIC_RES_384) { + if (!strcmp(kctl->id.name, "Mic Capture Volume")) { + usb_audio_info(chip, + "set resolution quirk: cval->res = 384\n"); + cval->res = 384; + } + } else if (chip->quirk_flags & QUIRK_FLAG_MIC_RES_16) { + if (!strcmp(kctl->id.name, "Mic Capture Volume")) { + usb_audio_info(chip, + "set resolution quirk: cval->res = 16\n"); + cval->res = 16; + } + } + switch (chip->usb_id) { case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */ @@ -1141,6 +1147,14 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, } break; + case USB_ID(0x045e, 0x070f): /* MS LifeChat LX-3000 Headset */ + if (!strcmp(kctl->id.name, "Speaker Playback Volume")) { + usb_audio_info(chip, + "set volume quirk for MS LifeChat LX-3000\n"); + cval->res = 192; + } + break; + case USB_ID(0x0471, 0x0101): case USB_ID(0x0471, 0x0104): case USB_ID(0x0471, 0x0105): @@ -1168,27 +1182,6 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, } break; - case USB_ID(0x046d, 0x0807): /* Logitech Webcam C500 */ - case USB_ID(0x046d, 0x0808): - case USB_ID(0x046d, 0x0809): - case USB_ID(0x046d, 0x0819): /* Logitech Webcam C210 */ - case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */ - case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */ - case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */ - case USB_ID(0x046d, 0x0826): /* HD Webcam c525 */ - case USB_ID(0x046d, 0x08ca): /* Logitech Quickcam Fusion */ - case USB_ID(0x046d, 0x0991): - case USB_ID(0x046d, 0x09a2): /* QuickCam Communicate Deluxe/S7500 */ - /* Most audio usb devices lie about volume resolution. - * Most Logitech webcams have res = 384. - * Probably there is some logitech magic behind this number --fishor - */ - if (!strcmp(kctl->id.name, "Mic Capture Volume")) { - usb_audio_info(chip, - "set resolution quirk: cval->res = 384\n"); - cval->res = 384; - } - break; case USB_ID(0x0495, 0x3042): /* ESS Technology Asus USB DAC */ if ((strstr(kctl->id.name, "Playback Volume") != NULL) || strstr(kctl->id.name, "Capture Volume") != NULL) { @@ -1197,11 +1190,18 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, cval->res = 1; } break; - case USB_ID(0x1224, 0x2a25): /* Jieli Technology USB PHY 2.0 */ - if (!strcmp(kctl->id.name, "Mic Capture Volume")) { + case USB_ID(0x3302, 0x12db): /* MOONDROP Quark2 */ + if (!strcmp(kctl->id.name, "PCM Playback Volume")) { usb_audio_info(chip, - "set resolution quirk: cval->res = 16\n"); - cval->res = 16; + "set volume quirk for MOONDROP Quark2\n"); + cval->min = -14208; /* Mute under it */ + } + break; + case USB_ID(0x12d1, 0x3a07): /* Huawei Technologies Co., Ltd. CM-Q3 */ + if (!strcmp(kctl->id.name, "PCM Playback Volume")) { + usb_audio_info(chip, + "set volume quirk for Huawei Technologies Co., Ltd. CM-Q3\n"); + cval->min = -11264; /* Mute under it */ } break; } @@ -1246,7 +1246,7 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval, int minchn = 0; if (cval->cmask) { for (i = 0; i < MAX_CHANNELS; i++) - if (cval->cmask & (1 << i)) { + if (cval->cmask & BIT(i)) { minchn = i + 1; break; } @@ -1351,7 +1351,7 @@ no_res_check: } else { idx = 0; for (i = 0; i < MAX_CHANNELS; i++) { - if (cval->cmask & (1 << i)) { + if (cval->cmask & BIT(i)) { init_cur_mix_raw(cval, i + 1, idx); idx++; } @@ -1363,11 +1363,24 @@ no_res_check: #define get_min_max(cval, def) get_min_max_with_quirks(cval, def, NULL) +/* get the max value advertised via control API */ +static int get_max_exposed(struct usb_mixer_elem_info *cval) +{ + if (!cval->max_exposed) { + if (cval->res) + cval->max_exposed = + DIV_ROUND_UP(cval->max - cval->min, cval->res); + else + cval->max_exposed = cval->max - cval->min; + } + return cval->max_exposed; +} + /* get a feature/mixer unit info */ 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 = snd_kcontrol_chip(kcontrol); if (cval->val_type == USB_MIXER_BOOLEAN || cval->val_type == USB_MIXER_INV_BOOLEAN) @@ -1375,11 +1388,8 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, else uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = cval->channels; - if (cval->val_type == USB_MIXER_BOOLEAN || - cval->val_type == USB_MIXER_INV_BOOLEAN) { - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - } else { + if (cval->val_type != USB_MIXER_BOOLEAN && + cval->val_type != USB_MIXER_INV_BOOLEAN) { if (!cval->initialized) { get_min_max_with_quirks(cval, 0, kcontrol); if (cval->initialized && cval->dBmin >= cval->dBmax) { @@ -1391,10 +1401,10 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, &kcontrol->id); } } - uinfo->value.integer.min = 0; - uinfo->value.integer.max = - DIV_ROUND_UP(cval->max - cval->min, cval->res); } + + uinfo->value.integer.min = 0; + uinfo->value.integer.max = get_max_exposed(cval); return 0; } @@ -1402,14 +1412,14 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, 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 = snd_kcontrol_chip(kcontrol); int c, cnt, val, err; ucontrol->value.integer.value[0] = cval->min; if (cval->cmask) { cnt = 0; for (c = 0; c < MAX_CHANNELS; c++) { - if (!(cval->cmask & (1 << c))) + if (!(cval->cmask & BIT(c))) continue; err = snd_usb_get_cur_mix_value(cval, c + 1, cnt, &val); if (err < 0) @@ -1434,19 +1444,22 @@ static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, 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 = snd_kcontrol_chip(kcontrol); + int max_val = get_max_exposed(cval); int c, cnt, val, oval, err; int changed = 0; if (cval->cmask) { cnt = 0; for (c = 0; c < MAX_CHANNELS; c++) { - if (!(cval->cmask & (1 << c))) + if (!(cval->cmask & BIT(c))) continue; err = snd_usb_get_cur_mix_value(cval, c + 1, cnt, &oval); if (err < 0) return filter_error(cval, err); val = ucontrol->value.integer.value[cnt]; + if (val < 0 || val > max_val) + return -EINVAL; val = get_abs_value(cval, val); if (oval != val) { snd_usb_set_cur_mix_value(cval, c + 1, cnt, val); @@ -1460,6 +1473,8 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, if (err < 0) return filter_error(cval, err); val = ucontrol->value.integer.value[0]; + if (val < 0 || val > max_val) + return -EINVAL; val = get_abs_value(cval, val); if (val != oval) { snd_usb_set_cur_mix_value(cval, 0, 0, val); @@ -1473,7 +1488,7 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, static int mixer_ctl_master_bool_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 = snd_kcontrol_chip(kcontrol); int val, err; err = snd_usb_get_cur_mix_value(cval, 0, 0, &val); @@ -1492,9 +1507,11 @@ static int get_connector_value(struct usb_mixer_elem_info *cval, validx = cval->control << 8 | 0; - ret = snd_usb_lock_shutdown(chip) ? -EIO : 0; - if (ret) + CLASS(snd_usb_lock, pm)(chip); + if (pm.err) { + ret = -EIO; goto error; + } idx = mixer_ctrl_intf(cval->head.mixer) | (cval->head.id << 8); if (cval->head.mixer->protocol == UAC_VERSION_2) { @@ -1515,8 +1532,6 @@ static int get_connector_value(struct usb_mixer_elem_info *cval, *val = !!uac3_conn.bmConInserted; } - snd_usb_unlock_shutdown(chip); - if (ret < 0) { if (name && strstr(name, "Speaker")) { if (val) @@ -1541,7 +1556,7 @@ error: static int mixer_ctl_connector_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 = snd_kcontrol_chip(kcontrol); int ret, val; ret = get_connector_value(cval, kcontrol->id.name, &val); @@ -1693,7 +1708,7 @@ static void __build_feature_ctl(struct usb_mixer_interface *mixer, } else { int i, c = 0; for (i = 0; i < 16; i++) - if (ctl_mask & (1 << i)) + if (ctl_mask & BIT(i)) c++; cval->channels = c; cval->ch_readonly = readonly_mask; @@ -1929,7 +1944,6 @@ static int parse_clock_source_unit(struct mixer_build *state, int unitid, struct uac_clock_source_descriptor *hdr = _ftr; struct usb_mixer_elem_info *cval; struct snd_kcontrol *kctl; - char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; int ret; if (state->mixer->protocol != UAC_VERSION_2) @@ -1966,10 +1980,9 @@ static int parse_clock_source_unit(struct mixer_build *state, int unitid, kctl->private_free = snd_usb_mixer_elem_free; ret = snd_usb_copy_string_desc(state->chip, hdr->iClockSource, - name, sizeof(name)); + kctl->id.name, sizeof(kctl->id.name)); if (ret > 0) - snprintf(kctl->id.name, sizeof(kctl->id.name), - "%s Validity", name); + append_ctl_name(kctl, " Validity"); else snprintf(kctl->id.name, sizeof(kctl->id.name), "Clock Source %d Validity", hdr->bClockID); @@ -2009,6 +2022,13 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, bmaControls = ftr->bmaControls; } + if (channels > 32) { + usb_audio_info(state->chip, + "usbmixer: too many channels (%d) in unit %d\n", + channels, unitid); + return -EINVAL; + } + /* parse the source unit */ err = parse_audio_unit(state, hdr->bSourceID); if (err < 0) @@ -2048,8 +2068,8 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, mask = snd_usb_combine_bytes(bmaControls + csize * (j+1), csize); - if (mask & (1 << i)) - ch_bits |= (1 << j); + if (mask & BIT(i)) + ch_bits |= BIT(j); } /* audio class v1 controls are never read-only */ @@ -2060,7 +2080,7 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, if (ch_bits & 1) build_feature_ctl(state, _ftr, ch_bits, control, &iterm, unitid, 0); - if (master_bits & (1 << i)) + if (master_bits & BIT(i)) build_feature_ctl(state, _ftr, 0, control, &iterm, unitid, 0); } @@ -2076,9 +2096,9 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, mask = snd_usb_combine_bytes(bmaControls + csize * (j+1), csize); if (uac_v2v3_control_is_readable(mask, control)) { - ch_bits |= (1 << j); + ch_bits |= BIT(j); if (!uac_v2v3_control_is_writeable(mask, control)) - ch_read_only |= (1 << j); + ch_read_only |= BIT(j); } } @@ -2169,7 +2189,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, __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 |= BIT(i); cval->channels++; } } @@ -2190,7 +2210,8 @@ static void build_mixer_unit_ctl(struct mixer_build *state, len = get_term_name(state->chip, iterm, kctl->id.name, sizeof(kctl->id.name), 0); if (!len) - len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1); + snprintf(kctl->id.name, sizeof(kctl->id.name), "Mixer Source %d", in_ch + 1); + append_ctl_name(kctl, " Volume"); usb_audio_dbg(state->chip, "[%d] MU [%s] ch = %d, val = %d/%d\n", @@ -2294,7 +2315,7 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, 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 = snd_kcontrol_chip(kcontrol); int err, val; err = get_cur_ctl_value(cval, cval->control << 8, &val); @@ -2311,13 +2332,15 @@ static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol, 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 = snd_kcontrol_chip(kcontrol); int val, oval, err; err = get_cur_ctl_value(cval, cval->control << 8, &oval); if (err < 0) return filter_error(cval, err); val = ucontrol->value.integer.value[0]; + if (val < 0 || val > get_max_exposed(cval)) + return -EINVAL; val = get_abs_value(cval, val); if (val != oval) { set_cur_ctl_value(cval, cval->control << 8, val); @@ -2492,7 +2515,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, if (state->mixer->protocol == UAC_VERSION_1) { if (!(controls[valinfo->control / 8] & - (1 << ((valinfo->control % 8) - 1)))) + BIT((valinfo->control % 8) - 1))) continue; } else { /* UAC_VERSION_2/3 */ if (!uac_v2v3_control_is_readable(controls[valinfo->control / 8], @@ -2644,7 +2667,7 @@ static int parse_audio_extension_unit(struct mixer_build *state, int unitid, 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 = snd_kcontrol_chip(kcontrol); const char **itemlist = (const char **)kcontrol->private_value; if (snd_BUG_ON(!itemlist)) @@ -2656,7 +2679,7 @@ static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, 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 = snd_kcontrol_chip(kcontrol); int val, err; err = get_cur_ctl_value(cval, cval->control << 8, &val); @@ -2673,13 +2696,15 @@ static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, 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 = snd_kcontrol_chip(kcontrol); int val, oval, err; err = get_cur_ctl_value(cval, cval->control << 8, &oval); if (err < 0) return filter_error(cval, err); val = ucontrol->value.enumerated.item[0]; + if (val < 0 || val >= cval->max) /* here cval->max = # elements */ + return -EINVAL; val = get_abs_value(cval, val); if (val != oval) { set_cur_ctl_value(cval, cval->control << 8, val); @@ -2792,7 +2817,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, len = get_term_name(state->chip, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0); if (! len) - sprintf(namelist[i], "Input %u", i); + scnprintf(namelist[i], MAX_ITEM_NAME_LEN, "Input %u", i); } kctl = snd_ctl_new1(&mixer_selectunit_ctl, cval); @@ -3061,6 +3086,8 @@ static int snd_usb_mixer_controls_badd(struct usb_mixer_interface *mixer, int i; assoc = usb_ifnum_to_if(dev, ctrlif)->intf_assoc; + if (!assoc) + return -EINVAL; /* Detect BADD capture/playback channels from AS EP descriptors */ for (i = 0; i < assoc->bInterfaceCount; i++) { @@ -3436,7 +3463,7 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer, case UAC2_CS_CUR: /* invalidate cache, so the value is read from the device */ if (channel) - info->cached &= ~(1 << channel); + info->cached &= ~BIT(channel); else /* master channel */ info->cached = 0; @@ -3557,7 +3584,7 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif) struct usb_mixer_interface *mixer; int err; - strcpy(chip->card->mixername, "USB Mixer"); + strscpy(chip->card->mixername, "USB Mixer"); mixer = kzalloc(sizeof(*mixer), GFP_KERNEL); if (!mixer) @@ -3672,9 +3699,9 @@ static int restore_mixer_value(struct usb_mixer_elem_list *list) if (cval->cmask) { idx = 0; for (c = 0; c < MAX_CHANNELS; c++) { - if (!(cval->cmask & (1 << c))) + if (!(cval->cmask & BIT(c))) continue; - if (cval->cached & (1 << (c + 1))) { + if (cval->cached & BIT(c + 1)) { err = snd_usb_set_cur_mix_value(cval, c + 1, idx, cval->cache_val[idx]); if (err < 0) |
