diff options
| -rw-r--r-- | sound/usb/mixer_scarlett2.c | 777 |
1 files changed, 390 insertions, 387 deletions
diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c index bd114be537d7..8390b646c0ae 100644 --- a/sound/usb/mixer_scarlett2.c +++ b/sound/usb/mixer_scarlett2.c @@ -6383,6 +6383,364 @@ static int scarlett2_add_power_status_ctl(struct usb_mixer_interface *mixer) &private->power_status_ctl); } +/*** Notification Handlers ***/ + +/* Notify on sync change */ +static void scarlett2_notify_sync(struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + + private->sync_updated = 1; + + snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->sync_ctl->id); +} + +/* Notify on monitor change (Gen 2/3) */ +static void scarlett2_notify_monitor(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + int i; + + if (!scarlett2_has_config_item(private, SCARLETT2_CONFIG_SW_HW_SWITCH)) + return; + + private->vol_updated = 1; + + snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->master_vol_ctl->id); + + for (i = 0; i < private->num_line_out; i++) + if (private->vol_sw_hw_switch[line_out_remap(private, i)]) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->vol_ctls[i]->id); +} + +/* Notify on volume change (Gen 4) */ +static void scarlett2_notify_volume(struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + + private->vol_updated = 1; + + snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->master_vol_ctl->id); + snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->headphone_vol_ctl->id); +} + +/* Notify on dim/mute change */ +static void scarlett2_notify_dim_mute(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + int i; + + if (!scarlett2_has_config_item(private, SCARLETT2_CONFIG_SW_HW_SWITCH)) + return; + + private->dim_mute_updated = 1; + + for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->dim_mute_ctls[i]->id); + + for (i = 0; i < private->num_line_out; i++) + if (private->vol_sw_hw_switch[line_out_remap(private, i)]) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->mute_ctls[i]->id); +} + +/* Notify on input level switch change */ +static void scarlett2_notify_input_level(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + int i; + + private->input_level_updated = 1; + + for (i = 0; i < info->level_input_count; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->level_ctls[i]->id); +} + +/* Notify on input pad switch change */ +static void scarlett2_notify_input_pad(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + int i; + + private->input_pad_updated = 1; + + for (i = 0; i < info->pad_input_count; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->pad_ctls[i]->id); +} + +/* Notify on input air switch change */ +static void scarlett2_notify_input_air(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + int i; + + private->input_air_updated = 1; + + for (i = 0; i < info->air_input_count; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->air_ctls[i]->id); +} + +/* Notify on input phantom switch change */ +static void scarlett2_notify_input_phantom(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + int i; + + private->input_phantom_updated = 1; + + for (i = 0; i < info->phantom_count; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->phantom_ctls[i]->id); + + scarlett2_phantom_notify_access(mixer); +} + +/* Notify on "input other" change (level/pad/air/phantom) */ +static void scarlett2_notify_input_other(struct usb_mixer_interface *mixer) +{ + scarlett2_notify_input_level(mixer); + scarlett2_notify_input_pad(mixer); + scarlett2_notify_input_air(mixer); + scarlett2_notify_input_phantom(mixer); +} + +/* Notify on input select change */ +static void scarlett2_notify_input_select(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + int i; + + if (!info->gain_input_count) + return; + + private->input_select_updated = 1; + + snd_ctl_notify(card, + SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO, + &private->input_select_ctl->id); + + for (i = 0; i < info->gain_input_count / 2; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->input_link_ctls[i]->id); +} + +/* Notify on input gain change */ +static void scarlett2_notify_input_gain(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + int i; + + if (!info->gain_input_count) + return; + + private->input_gain_updated = 1; + + for (i = 0; i < info->gain_input_count; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->input_gain_ctls[i]->id); +} + +/* Notify on autogain change */ +static void scarlett2_notify_autogain(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + int i; + + if (!info->gain_input_count) + return; + + private->autogain_updated = 1; + + for (i = 0; i < info->gain_input_count; i++) { + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->autogain_ctls[i]->id); + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->autogain_status_ctls[i]->id); + } + + scarlett2_autogain_notify_access(mixer); +} + +/* Notify on input safe switch change */ +static void scarlett2_notify_input_safe(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + int i; + + if (!info->gain_input_count) + return; + + private->input_safe_updated = 1; + + for (i = 0; i < info->gain_input_count; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->safe_ctls[i]->id); +} + +/* Notify on "monitor other" change (speaker switching, talkback) */ +static void scarlett2_notify_monitor_other(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + + private->monitor_other_updated = 1; + + if (info->has_speaker_switching) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->speaker_switching_ctl->id); + + if (info->has_talkback) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->talkback_ctl->id); + + /* if speaker switching was recently enabled or disabled, + * invalidate the dim/mute and mux enum controls + */ + if (private->speaker_switching_switched) { + int i; + + scarlett2_notify_dim_mute(mixer); + + private->speaker_switching_switched = 0; + private->mux_updated = 1; + + for (i = 0; i < private->num_mux_dsts; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->mux_ctls[i]->id); + } +} + +/* Notify on direct monitor switch change */ +static void scarlett2_notify_direct_monitor(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + int count = private->num_mix_in * private->num_mix_out; + int i; + + private->direct_monitor_updated = 1; + + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->direct_monitor_ctl->id); + + if (!scarlett2_has_mixer(private)) + return; + + private->mix_updated = 1; + + /* Notify of change to the mix controls */ + for (i = 0; i < count; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->mix_ctls[i]->id); +} + +/* Notify on power change */ +static void scarlett2_notify_power_status(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + + private->power_status_updated = 1; + + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->power_status_ctl->id); +} + +/* Notify on mux change */ +static void scarlett2_notify_mux(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + int i; + + private->mux_updated = 1; + + for (i = 0; i < private->num_mux_dsts; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->mux_ctls[i]->id); +} + +/* Notify on PCM input switch change */ +static void scarlett2_notify_pcm_input_switch(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + + private->pcm_input_switch_updated = 1; + + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->pcm_input_switch_ctl->id); + + scarlett2_notify_mux(mixer); +} + +/* Interrupt callback */ +static void scarlett2_notify(struct urb *urb) +{ + struct usb_mixer_interface *mixer = urb->context; + int len = urb->actual_length; + int ustatus = urb->status; + u32 data; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_notification *notifications = + private->config_set->notifications; + + if (ustatus != 0 || len != 8) + goto requeue; + + data = le32_to_cpu(*(__le32 *)urb->transfer_buffer); + + while (data && notifications->mask) { + if (data & notifications->mask) { + data &= ~notifications->mask; + if (notifications->func) + notifications->func(mixer); + } + notifications++; + } + + if (data) + usb_audio_warn(mixer->chip, + "%s: Unhandled notification: 0x%08x\n", + __func__, data); + +requeue: + if (ustatus != -ENOENT && + ustatus != -ECONNRESET && + ustatus != -ESHUTDOWN) { + urb->dev = mixer->chip->dev; + usb_submit_urb(urb, GFP_ATOMIC); + } +} + /*** Cleanup/Suspend Callbacks ***/ static void scarlett2_private_free(struct usb_mixer_interface *mixer) @@ -6502,6 +6860,38 @@ static int scarlett2_init_private(struct usb_mixer_interface *mixer, return scarlett2_find_fc_interface(mixer->chip->dev, private); } +/* Submit a URB to receive notifications from the device */ +static int scarlett2_init_notify(struct usb_mixer_interface *mixer) +{ + struct usb_device *dev = mixer->chip->dev; + struct scarlett2_data *private = mixer->private_data; + unsigned int pipe = usb_rcvintpipe(dev, private->bEndpointAddress); + void *transfer_buffer; + + if (mixer->urb) { + usb_audio_err(mixer->chip, + "%s: mixer urb already in use!\n", __func__); + return 0; + } + + if (usb_pipe_type_check(dev, pipe)) + return -EINVAL; + + mixer->urb = usb_alloc_urb(0, GFP_KERNEL); + if (!mixer->urb) + return -ENOMEM; + + transfer_buffer = kmalloc(private->wMaxPacketSize, GFP_KERNEL); + if (!transfer_buffer) + return -ENOMEM; + + usb_fill_int_urb(mixer->urb, dev, pipe, + transfer_buffer, private->wMaxPacketSize, + scarlett2_notify, mixer, private->bInterval); + + return usb_submit_urb(mixer->urb, GFP_KERNEL); +} + /* Cargo cult proprietary initialisation sequence */ static int scarlett2_usb_init(struct usb_mixer_interface *mixer) { @@ -6790,393 +7180,6 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer) return scarlett2_usb_get_mux(mixer); } -/* Notify on sync change */ -static void scarlett2_notify_sync(struct usb_mixer_interface *mixer) -{ - struct scarlett2_data *private = mixer->private_data; - - private->sync_updated = 1; - - snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->sync_ctl->id); -} - -/* Notify on monitor change (Gen 2/3) */ -static void scarlett2_notify_monitor(struct usb_mixer_interface *mixer) -{ - struct snd_card *card = mixer->chip->card; - struct scarlett2_data *private = mixer->private_data; - int i; - - if (!scarlett2_has_config_item(private, SCARLETT2_CONFIG_SW_HW_SWITCH)) - return; - - private->vol_updated = 1; - - snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->master_vol_ctl->id); - - for (i = 0; i < private->num_line_out; i++) - if (private->vol_sw_hw_switch[line_out_remap(private, i)]) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->vol_ctls[i]->id); -} - -/* Notify on volume change (Gen 4) */ -static void scarlett2_notify_volume(struct usb_mixer_interface *mixer) -{ - struct scarlett2_data *private = mixer->private_data; - - private->vol_updated = 1; - - snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->master_vol_ctl->id); - snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->headphone_vol_ctl->id); -} - -/* Notify on dim/mute change */ -static void scarlett2_notify_dim_mute(struct usb_mixer_interface *mixer) -{ - struct snd_card *card = mixer->chip->card; - struct scarlett2_data *private = mixer->private_data; - int i; - - if (!scarlett2_has_config_item(private, SCARLETT2_CONFIG_SW_HW_SWITCH)) - return; - - private->dim_mute_updated = 1; - - for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->dim_mute_ctls[i]->id); - - for (i = 0; i < private->num_line_out; i++) - if (private->vol_sw_hw_switch[line_out_remap(private, i)]) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->mute_ctls[i]->id); -} - -/* Notify on input level switch change */ -static void scarlett2_notify_input_level(struct usb_mixer_interface *mixer) -{ - struct snd_card *card = mixer->chip->card; - struct scarlett2_data *private = mixer->private_data; - const struct scarlett2_device_info *info = private->info; - int i; - - private->input_level_updated = 1; - - for (i = 0; i < info->level_input_count; i++) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->level_ctls[i]->id); -} - -/* Notify on input pad switch change */ -static void scarlett2_notify_input_pad(struct usb_mixer_interface *mixer) -{ - struct snd_card *card = mixer->chip->card; - struct scarlett2_data *private = mixer->private_data; - const struct scarlett2_device_info *info = private->info; - int i; - - private->input_pad_updated = 1; - - for (i = 0; i < info->pad_input_count; i++) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->pad_ctls[i]->id); -} - -/* Notify on input air switch change */ -static void scarlett2_notify_input_air(struct usb_mixer_interface *mixer) -{ - struct snd_card *card = mixer->chip->card; - struct scarlett2_data *private = mixer->private_data; - const struct scarlett2_device_info *info = private->info; - int i; - - private->input_air_updated = 1; - - for (i = 0; i < info->air_input_count; i++) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->air_ctls[i]->id); -} - -/* Notify on input phantom switch change */ -static void scarlett2_notify_input_phantom(struct usb_mixer_interface *mixer) -{ - struct snd_card *card = mixer->chip->card; - struct scarlett2_data *private = mixer->private_data; - const struct scarlett2_device_info *info = private->info; - int i; - - private->input_phantom_updated = 1; - - for (i = 0; i < info->phantom_count; i++) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->phantom_ctls[i]->id); - - scarlett2_phantom_notify_access(mixer); -} - -/* Notify on "input other" change (level/pad/air/phantom) */ -static void scarlett2_notify_input_other(struct usb_mixer_interface *mixer) -{ - scarlett2_notify_input_level(mixer); - scarlett2_notify_input_pad(mixer); - scarlett2_notify_input_air(mixer); - scarlett2_notify_input_phantom(mixer); -} - -/* Notify on input select change */ -static void scarlett2_notify_input_select(struct usb_mixer_interface *mixer) -{ - struct snd_card *card = mixer->chip->card; - struct scarlett2_data *private = mixer->private_data; - const struct scarlett2_device_info *info = private->info; - int i; - - if (!info->gain_input_count) - return; - - private->input_select_updated = 1; - - snd_ctl_notify(card, - SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO, - &private->input_select_ctl->id); - - for (i = 0; i < info->gain_input_count / 2; i++) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->input_link_ctls[i]->id); -} - -/* Notify on input gain change */ -static void scarlett2_notify_input_gain(struct usb_mixer_interface *mixer) -{ - struct snd_card *card = mixer->chip->card; - struct scarlett2_data *private = mixer->private_data; - const struct scarlett2_device_info *info = private->info; - int i; - - if (!info->gain_input_count) - return; - - private->input_gain_updated = 1; - - for (i = 0; i < info->gain_input_count; i++) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->input_gain_ctls[i]->id); -} - -/* Notify on autogain change */ -static void scarlett2_notify_autogain(struct usb_mixer_interface *mixer) -{ - struct snd_card *card = mixer->chip->card; - struct scarlett2_data *private = mixer->private_data; - const struct scarlett2_device_info *info = private->info; - int i; - - if (!info->gain_input_count) - return; - - private->autogain_updated = 1; - - for (i = 0; i < info->gain_input_count; i++) { - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->autogain_ctls[i]->id); - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->autogain_status_ctls[i]->id); - } - - scarlett2_autogain_notify_access(mixer); -} - -/* Notify on input safe switch change */ -static void scarlett2_notify_input_safe(struct usb_mixer_interface *mixer) -{ - struct snd_card *card = mixer->chip->card; - struct scarlett2_data *private = mixer->private_data; - const struct scarlett2_device_info *info = private->info; - int i; - - if (!info->gain_input_count) - return; - - private->input_safe_updated = 1; - - for (i = 0; i < info->gain_input_count; i++) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->safe_ctls[i]->id); -} - -/* Notify on "monitor other" change (speaker switching, talkback) */ -static void scarlett2_notify_monitor_other(struct usb_mixer_interface *mixer) -{ - struct snd_card *card = mixer->chip->card; - struct scarlett2_data *private = mixer->private_data; - const struct scarlett2_device_info *info = private->info; - - private->monitor_other_updated = 1; - - if (info->has_speaker_switching) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->speaker_switching_ctl->id); - - if (info->has_talkback) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->talkback_ctl->id); - - /* if speaker switching was recently enabled or disabled, - * invalidate the dim/mute and mux enum controls - */ - if (private->speaker_switching_switched) { - int i; - - scarlett2_notify_dim_mute(mixer); - - private->speaker_switching_switched = 0; - private->mux_updated = 1; - - for (i = 0; i < private->num_mux_dsts; i++) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->mux_ctls[i]->id); - } -} - -/* Notify on direct monitor switch change */ -static void scarlett2_notify_direct_monitor(struct usb_mixer_interface *mixer) -{ - struct snd_card *card = mixer->chip->card; - struct scarlett2_data *private = mixer->private_data; - int count = private->num_mix_in * private->num_mix_out; - int i; - - private->direct_monitor_updated = 1; - - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->direct_monitor_ctl->id); - - if (!scarlett2_has_mixer(private)) - return; - - private->mix_updated = 1; - - /* Notify of change to the mix controls */ - for (i = 0; i < count; i++) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->mix_ctls[i]->id); -} - -/* Notify on power change */ -static void scarlett2_notify_power_status(struct usb_mixer_interface *mixer) -{ - struct snd_card *card = mixer->chip->card; - struct scarlett2_data *private = mixer->private_data; - - private->power_status_updated = 1; - - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->power_status_ctl->id); -} - -/* Notify on mux change */ -static void scarlett2_notify_mux(struct usb_mixer_interface *mixer) -{ - struct snd_card *card = mixer->chip->card; - struct scarlett2_data *private = mixer->private_data; - int i; - - private->mux_updated = 1; - - for (i = 0; i < private->num_mux_dsts; i++) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->mux_ctls[i]->id); -} - -/* Notify on PCM input switch change */ -static void scarlett2_notify_pcm_input_switch(struct usb_mixer_interface *mixer) -{ - struct snd_card *card = mixer->chip->card; - struct scarlett2_data *private = mixer->private_data; - - private->pcm_input_switch_updated = 1; - - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->pcm_input_switch_ctl->id); - - scarlett2_notify_mux(mixer); -} - -/* Interrupt callback */ -static void scarlett2_notify(struct urb *urb) -{ - struct usb_mixer_interface *mixer = urb->context; - int len = urb->actual_length; - int ustatus = urb->status; - u32 data; - struct scarlett2_data *private = mixer->private_data; - const struct scarlett2_notification *notifications = - private->config_set->notifications; - - if (ustatus != 0 || len != 8) - goto requeue; - - data = le32_to_cpu(*(__le32 *)urb->transfer_buffer); - - while (data && notifications->mask) { - if (data & notifications->mask) { - data &= ~notifications->mask; - if (notifications->func) - notifications->func(mixer); - } - notifications++; - } - - if (data) - usb_audio_warn(mixer->chip, - "%s: Unhandled notification: 0x%08x\n", - __func__, data); - -requeue: - if (ustatus != -ENOENT && - ustatus != -ECONNRESET && - ustatus != -ESHUTDOWN) { - urb->dev = mixer->chip->dev; - usb_submit_urb(urb, GFP_ATOMIC); - } -} - -static int scarlett2_init_notify(struct usb_mixer_interface *mixer) -{ - struct usb_device *dev = mixer->chip->dev; - struct scarlett2_data *private = mixer->private_data; - unsigned int pipe = usb_rcvintpipe(dev, private->bEndpointAddress); - void *transfer_buffer; - - if (mixer->urb) { - usb_audio_err(mixer->chip, - "%s: mixer urb already in use!\n", __func__); - return 0; - } - - if (usb_pipe_type_check(dev, pipe)) - return -EINVAL; - - mixer->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!mixer->urb) - return -ENOMEM; - - transfer_buffer = kmalloc(private->wMaxPacketSize, GFP_KERNEL); - if (!transfer_buffer) - return -ENOMEM; - - usb_fill_int_urb(mixer->urb, dev, pipe, - transfer_buffer, private->wMaxPacketSize, - scarlett2_notify, mixer, private->bInterval); - - return usb_submit_urb(mixer->urb, GFP_KERNEL); -} - static const struct scarlett2_device_entry *get_scarlett2_device_entry( struct usb_mixer_interface *mixer) { |
