diff options
Diffstat (limited to 'sound/usb/mixer.c')
| -rw-r--r-- | sound/usb/mixer.c | 65 | 
1 files changed, 43 insertions, 22 deletions
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index fe56c9da38e..298070e8f2d 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -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; +	down_read(&chip->shutdown_rwsem);  	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: +	up_read(&chip->shutdown_rwsem); +	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, +	down_read(&chip->shutdown_rwsem); +	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); +	} +	up_read(&chip->shutdown_rwsem);  	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) +	down_read(&chip->shutdown_rwsem); +	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: +	up_read(&chip->shutdown_rwsem); +	snd_usb_autosuspend(chip); +	return err;  }  static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value)  |