|
@@ -287,25 +287,32 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
|
|
|
unsigned char buf[2];
|
|
|
int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
|
|
|
int timeout = 10;
|
|
|
- int err;
|
|
|
+ int idx = 0, err;
|
|
|
|
|
|
err = snd_usb_autoresume(cval->mixer->chip);
|
|
|
if (err < 0)
|
|
|
return -EIO;
|
|
|
+ mutex_lock(&chip->shutdown_mutex);
|
|
|
while (timeout-- > 0) {
|
|
|
+ if (chip->shutdown)
|
|
|
+ break;
|
|
|
+ idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
|
|
|
if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,
|
|
|
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
|
|
|
- validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
|
|
|
- buf, val_len) >= val_len) {
|
|
|
+ validx, idx, buf, val_len) >= val_len) {
|
|
|
*value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
|
|
|
- snd_usb_autosuspend(cval->mixer->chip);
|
|
|
- return 0;
|
|
|
+ err = 0;
|
|
|
+ goto out;
|
|
|
}
|
|
|
}
|
|
|
- snd_usb_autosuspend(cval->mixer->chip);
|
|
|
snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
|
|
|
- request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
|
|
|
- return -EINVAL;
|
|
|
+ request, validx, idx, cval->val_type);
|
|
|
+ err = -EINVAL;
|
|
|
+
|
|
|
+ out:
|
|
|
+ mutex_unlock(&chip->shutdown_mutex);
|
|
|
+ snd_usb_autosuspend(cval->mixer->chip);
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
|
|
@@ -313,7 +320,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
|
|
|
struct snd_usb_audio *chip = cval->mixer->chip;
|
|
|
unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */
|
|
|
unsigned char *val;
|
|
|
- int ret, size;
|
|
|
+ int idx = 0, ret, size;
|
|
|
__u8 bRequest;
|
|
|
|
|
|
if (request == UAC_GET_CUR) {
|
|
@@ -330,16 +337,22 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
|
|
|
if (ret)
|
|
|
goto error;
|
|
|
|
|
|
- ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
|
|
|
+ mutex_lock(&chip->shutdown_mutex);
|
|
|
+ if (chip->shutdown)
|
|
|
+ ret = -ENODEV;
|
|
|
+ else {
|
|
|
+ idx = snd_usb_ctrl_intf(chip) | (cval->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, snd_usb_ctrl_intf(chip) | (cval->id << 8),
|
|
|
- buf, size);
|
|
|
+ validx, idx, buf, size);
|
|
|
+ }
|
|
|
+ mutex_unlock(&chip->shutdown_mutex);
|
|
|
snd_usb_autosuspend(chip);
|
|
|
|
|
|
if (ret < 0) {
|
|
|
error:
|
|
|
snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
|
|
|
- request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
|
|
|
+ request, validx, idx, cval->val_type);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -417,7 +430,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
|
|
|
{
|
|
|
struct snd_usb_audio *chip = cval->mixer->chip;
|
|
|
unsigned char buf[2];
|
|
|
- int val_len, err, timeout = 10;
|
|
|
+ int idx = 0, val_len, err, timeout = 10;
|
|
|
|
|
|
if (cval->mixer->protocol == UAC_VERSION_1) {
|
|
|
val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
|
|
@@ -440,19 +453,27 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
|
|
|
err = snd_usb_autoresume(chip);
|
|
|
if (err < 0)
|
|
|
return -EIO;
|
|
|
- while (timeout-- > 0)
|
|
|
+ mutex_lock(&chip->shutdown_mutex);
|
|
|
+ while (timeout-- > 0) {
|
|
|
+ if (chip->shutdown)
|
|
|
+ break;
|
|
|
+ idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
|
|
|
if (snd_usb_ctl_msg(chip->dev,
|
|
|
usb_sndctrlpipe(chip->dev, 0), request,
|
|
|
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
|
|
|
- validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
|
|
|
- buf, val_len) >= 0) {
|
|
|
- snd_usb_autosuspend(chip);
|
|
|
- return 0;
|
|
|
+ validx, idx, buf, val_len) >= 0) {
|
|
|
+ err = 0;
|
|
|
+ goto out;
|
|
|
}
|
|
|
- snd_usb_autosuspend(chip);
|
|
|
+ }
|
|
|
snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
|
|
|
- request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]);
|
|
|
- return -EINVAL;
|
|
|
+ request, validx, idx, cval->val_type, buf[0], buf[1]);
|
|
|
+ err = -EINVAL;
|
|
|
+
|
|
|
+ out:
|
|
|
+ mutex_unlock(&chip->shutdown_mutex);
|
|
|
+ snd_usb_autosuspend(chip);
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value)
|