From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Google-Smtp-Source: AIpwx49/RYrfgKkizOlJadyx88beQugozDBmy6PdsJymt0U7ll9UZlwopxrtT0IpoSe4yj8NpFBv ARC-Seal: i=1; a=rsa-sha256; t=1523728515; cv=none; d=google.com; s=arc-20160816; b=avFjq68stY/RcyD8EMr7/xJPF8mAomyilipJksD5Mo/skzYG8MQndsL0Pkqskehk/2 VFqfS/U6Y2M4hnl5rBe7FDZ48YPSL/AjfApZcsrDrU2maUPPlf+cwenepxxeVvUUTOJH 750QRK81Kqf8e+tm8/P8mWBK0buL+UQbC3PnFabiGqHPGQ6kl+M8LacKyQOZ2tk6gFbj BNfIN0m4OL6uyCUMxGA/A0iWxG3/oo03D0k5+9bDfHj5ENcoQLgPSbDM54VlvjXdGsFk 8y7NYYxOBDZuAHxICmKzVEy7ykmkOG8wSX6z2FL+V3rbtGdd/FuZlRMNkNxdgvOdpzey TSVQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=user-agent:message-id:references:in-reply-to:subject:cc:to:from :date:content-transfer-encoding:mime-version :arc-authentication-results; bh=Sz92GfqS7Df+vyuWKB+G+zoAEJ724ua6P8GfKgbZ4wQ=; b=bTuatD2X+hXUq0elLnQ4PKCMlN5XUh7iRXrGPXdWeg15BAsdkimFP7/s7KCQtcuVz+ YHw0wh4G0AI3sM7oKmzTdl64UwglfTFUQCFQaUuFT9FKA32DbY0ujZnoh7KMrW4yZnhL 3QlpxT7vzuu5qyY1rD+MQ20tksILRLiVEfqD8KExq4BvpbkN34+viGTHw45TOuyaYdGQ 5X5vFAly7x0TpSwaz1o7VlhJ3YLS4npPZ/Sa8xZYkT2XZheE7wd7IeTMG7KAYhlJRBje m35AcNBwBTs4XOKtLlAKWywQ7TdWnt4tbwKDWrtt8WoZHM/zo9Iehc53gSBCDx0kgyiv tRXw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of jorge.sanjuan@codethink.co.uk designates 176.9.8.82 as permitted sender) smtp.mailfrom=jorge.sanjuan@codethink.co.uk; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=codethink.co.uk Authentication-Results: mx.google.com; spf=pass (google.com: domain of jorge.sanjuan@codethink.co.uk designates 176.9.8.82 as permitted sender) smtp.mailfrom=jorge.sanjuan@codethink.co.uk; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=codethink.co.uk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Date: Sat, 14 Apr 2018 18:55:13 +0100 From: Jorge Sanjuan To: Ruslan Bilovol Cc: Takashi Iwai , Greg Kroah-Hartman , alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH 4/4] ALSA: usb: add UAC3 BADD profiles support In-Reply-To: <1523658266-2259-5-git-send-email-ruslan.bilovol@gmail.com> References: <1523658266-2259-1-git-send-email-ruslan.bilovol@gmail.com> <1523658266-2259-5-git-send-email-ruslan.bilovol@gmail.com> Message-ID: <298440e44133287c3f86a0cae2fd08e1@codethink.com> User-Agent: Roundcube Webmail/1.1.5 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: =?utf-8?q?1597671512160670217?= X-GMAIL-MSGID: =?utf-8?q?1597745152098847474?= X-Mailing-List: linux-kernel@vger.kernel.org List-ID: On 2018-04-13 23:24, Ruslan Bilovol wrote: > Recently released USB Audio Class 3.0 specification > contains BADD (Basic Audio Device Definition) document > which describes pre-defined UAC3 configurations. > > BADD support is mandatory for UAC3 devices, it should be > implemented as a separate USB device configuration. > As per BADD document, class-specific descriptors > shall not be included in the Device’s Configuration > descriptor ("inferred"), but host can guess them > from BADD profile number, number of endpoints and > their max packed sizes. Right. I would have thought that, since BADD is a subset of UAC3, it may be simpler to fill the Class Specific descriptors buffer and let the UAC3 path intact as it would result in the same behavior (for UAC3 and BADD configs) without the need to add that much code to the mixer, which is already quite big. In the patch I proposed [1], the Class Specific buffer is filled once with the BADD descriptors, which are already UAC3 compliant, so the driver would handle the rest in the same way it would do with an UAC3 configuration. I will keep an eye on this as I'd need to do some work based on this instead. [1] https://www.spinics.net/lists/alsa-devel/msg71617.html Thanks, Jorge > > This patch adds support of all BADD profiles from the spec > > Signed-off-by: Ruslan Bilovol > --- > sound/usb/card.c | 14 +++ > sound/usb/clock.c | 9 +- > sound/usb/mixer.c | 313 > +++++++++++++++++++++++++++++++++++++++++++++++-- > sound/usb/mixer_maps.c | 65 ++++++++++ > sound/usb/stream.c | 83 +++++++++++-- > sound/usb/usbaudio.h | 2 + > 6 files changed, 466 insertions(+), 20 deletions(-) > > diff --git a/sound/usb/card.c b/sound/usb/card.c > index 4d866bd..47ebc50 100644 > --- a/sound/usb/card.c > +++ b/sound/usb/card.c > @@ -307,6 +307,20 @@ static int snd_usb_create_streams(struct > snd_usb_audio *chip, int ctrlif) > return -EINVAL; > } > > + if (protocol == UAC_VERSION_3) { > + int badd = assoc->bFunctionSubClass; > + > + if (badd != UAC3_FUNCTION_SUBCLASS_FULL_ADC_3_0 && > + (badd < UAC3_FUNCTION_SUBCLASS_GENERIC_IO || > + badd > UAC3_FUNCTION_SUBCLASS_SPEAKERPHONE)) { > + dev_err(&dev->dev, > + "Unsupported UAC3 BADD profile\n"); > + return -EINVAL; > + } > + > + chip->badd_profile = badd; > + } > + > for (i = 0; i < assoc->bInterfaceCount; i++) { > int intf = assoc->bFirstInterface + i; > > diff --git a/sound/usb/clock.c b/sound/usb/clock.c > index 0b030d8..17673f3 100644 > --- a/sound/usb/clock.c > +++ b/sound/usb/clock.c > @@ -587,8 +587,15 @@ int snd_usb_init_sample_rate(struct snd_usb_audio > *chip, int iface, > default: > return set_sample_rate_v1(chip, iface, alts, fmt, rate); > > - case UAC_VERSION_2: > case UAC_VERSION_3: > + if (chip->badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) { > + if (rate != UAC3_BADD_SAMPLING_RATE) > + return -ENXIO; > + else > + return 0; > + } > + /* fall through */ > + case UAC_VERSION_2: > return set_sample_rate_v2v3(chip, iface, alts, fmt, rate); > } > } > diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c > index 301ad61..e5c3b0d 100644 > --- a/sound/usb/mixer.c > +++ b/sound/usb/mixer.c > @@ -112,14 +112,12 @@ enum { > #include "mixer_maps.c" > > static const struct usbmix_name_map * > -find_map(struct mixer_build *state, int unitid, int control) > +find_map(const struct usbmix_name_map *p, int unitid, int control) > { > - const struct usbmix_name_map *p = state->map; > - > if (!p) > return NULL; > > - for (p = state->map; p->id; p++) { > + for (; p->id; p++) { > if (p->id == unitid && > (!control || !p->control || control == p->control)) > return p; > @@ -1333,6 +1331,76 @@ static struct usb_feature_control_info > *get_feature_control_info(int control) > return NULL; > } > > +static void build_feature_ctl_badd(struct usb_mixer_interface *mixer, > + unsigned int ctl_mask, int control, int unitid, > + const struct usbmix_name_map *badd_map) > +{ > + struct usb_feature_control_info *ctl_info; > + unsigned int len = 0; > + struct snd_kcontrol *kctl; > + struct usb_mixer_elem_info *cval; > + const struct usbmix_name_map *map; > + > + map = find_map(badd_map, unitid, control); > + if (!map) > + return; > + > + cval = kzalloc(sizeof(*cval), GFP_KERNEL); > + if (!cval) > + return; > + snd_usb_mixer_elem_init_std(&cval->head, mixer, unitid); > + cval->control = control; > + cval->cmask = ctl_mask; > + > + ctl_info = get_feature_control_info(control); > + if (!ctl_info) { > + kfree(cval); > + return; > + } > + cval->val_type = ctl_info->type; > + > + if (ctl_mask == 0) { > + cval->channels = 1; /* master channel */ > + } else { > + int i, c = 0; > + > + for (i = 0; i < 2; i++) > + if (ctl_mask & (1 << i)) > + c++; > + cval->channels = c; > + } > + > + kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval); > + > + if (!kctl) { > + usb_audio_err(mixer->chip, "cannot malloc kcontrol\n"); > + kfree(cval); > + return; > + } > + kctl->private_free = snd_usb_mixer_elem_free; > + len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); > + > + append_ctl_name(kctl, control == UAC_FU_MUTE ? " Switch" : " > Volume"); > + > + /* get min/max values */ > + get_min_max_with_quirks(cval, 0, kctl); > + > + if (control == UAC_FU_VOLUME) { > + check_mapped_dB(map, cval); > + if (cval->dBmin < cval->dBmax || !cval->initialized) { > + kctl->tlv.c = snd_usb_mixer_vol_tlv; > + kctl->vd[0].access |= > + SNDRV_CTL_ELEM_ACCESS_TLV_READ | > + SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; > + } > + } > + > + usb_audio_dbg(mixer->chip, "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", > + cval->head.id, kctl->id.name, cval->channels, > + cval->min, cval->max, cval->res); > + snd_usb_mixer_add_control(&cval->head, kctl); > +} > + > static void build_feature_ctl(struct mixer_build *state, void > *raw_desc, > unsigned int ctl_mask, int control, > struct usb_audio_term *iterm, int unitid, > @@ -1353,7 +1421,7 @@ static void build_feature_ctl(struct mixer_build > *state, void *raw_desc, > return; > } > > - map = find_map(state, unitid, control); > + map = find_map(state->map, unitid, control); > if (check_ignored_ctl(map)) > return; > > @@ -1806,7 +1874,7 @@ static void build_mixer_unit_ctl(struct > mixer_build *state, > struct snd_kcontrol *kctl; > const struct usbmix_name_map *map; > > - map = find_map(state, unitid, 0); > + map = find_map(state->map, unitid, 0); > if (check_ignored_ctl(map)) > return; > > @@ -2105,7 +2173,7 @@ static int build_audio_procunit(struct > mixer_build *state, int unitid, > > if (!(controls[valinfo->control / 8] & (1 << ((valinfo->control % 8) > - 1)))) > continue; > - map = find_map(state, unitid, valinfo->control); > + map = find_map(state->map, unitid, valinfo->control); > if (check_ignored_ctl(map)) > continue; > cval = kzalloc(sizeof(*cval), GFP_KERNEL); > @@ -2308,7 +2376,7 @@ static int parse_audio_selector_unit(struct > mixer_build *state, int unitid, > if (desc->bNrInPins == 1) /* only one ? nonsense! */ > return 0; > > - map = find_map(state, unitid, 0); > + map = find_map(state->map, unitid, 0); > if (check_ignored_ctl(map)) > return 0; > > @@ -2495,6 +2563,226 @@ static int snd_usb_mixer_dev_free(struct > snd_device *device) > } > > /* > + * create mixer controls for UAC3 BADD profiles > + * > + * UAC3 BADD device doesn't contain CS descriptors thus we will guess > everything > + * > + * BADD device may contain Mixer Unit, which doesn't have any > controls, skip it > + */ > +static int snd_usb_mixer_controls_badd(struct usb_mixer_interface > *mixer, > + int ctrlif) > +{ > + struct usb_device *dev = mixer->chip->dev; > + struct usb_interface_assoc_descriptor *assoc; > + int badd_profile = mixer->chip->badd_profile; > + const struct usbmix_ctl_map *map; > + int p_chmask = 0, c_chmask = 0, st_chmask = 0; > + int i; > + > + assoc = usb_ifnum_to_if(dev, ctrlif)->intf_assoc; > + > + /* Detect BADD capture/playback channels from AS EP descriptors */ > + for (i = 0; i < assoc->bInterfaceCount; i++) { > + int intf = assoc->bFirstInterface + i; > + > + if (intf != ctrlif) { > + struct usb_interface *iface; > + struct usb_host_interface *alts; > + struct usb_interface_descriptor *altsd; > + unsigned int maxpacksize; > + char dir_in; > + int chmask, num; > + > + iface = usb_ifnum_to_if(dev, intf); > + num = iface->num_altsetting; > + > + if (num < 2) > + return -EINVAL; > + > + /* > + * The number of Channels in an AudioStreaming interface > + * and the audio sample bit resolution (16 bits or 24 > + * bits) can be derived from the wMaxPacketSize field in > + * the Standard AS Audio Data Endpoint descriptor in > + * Alternate Setting 1 > + */ > + alts = &iface->altsetting[1]; > + altsd = get_iface_desc(alts); > + > + if (altsd->bNumEndpoints < 1) > + return -EINVAL; > + > + /* check direction */ > + dir_in = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN); > + maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); > + > + switch (maxpacksize) { > + default: > + usb_audio_err(mixer->chip, > + "incorrect wMaxPacketSize 0x%x for BADD profile\n", > + maxpacksize); > + return -EINVAL; > + case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16: > + case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16: > + case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24: > + case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24: > + chmask = 1; > + break; > + case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16: > + case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16: > + case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24: > + case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24: > + chmask = 3; > + break; > + } > + > + if (dir_in) > + c_chmask = chmask; > + else > + p_chmask = chmask; > + } > + } > + > + usb_audio_dbg(mixer->chip, > + "UAC3 BADD profile 0x%x: detected c_chmask=%d p_chmask=%d\n", > + badd_profile, c_chmask, p_chmask); > + > + /* check the mapping table */ > + for (map = uac3_badd_usbmix_ctl_maps; map->id; map++) { > + if (map->id == badd_profile) { > + mixer->ignore_ctl_error = map->ignore_ctl_error; > + break; > + } > + } > + > + if (!map->id) > + return -EINVAL; > + > + switch (badd_profile) { > + default: > + return -EINVAL; > + case UAC3_FUNCTION_SUBCLASS_GENERIC_IO: > + /* > + * BAIF, BAOF or combination of both > + * IN: Mono or Stereo cfg, Mono alt possible > + * OUT: Mono or Stereo cfg, Mono alt possible > + */ > + /* c_chmask := DYNAMIC */ > + /* p_chmask := DYNAMIC */ > + if (!c_chmask && !p_chmask) { > + usb_audio_err(mixer->chip, > + "BADD GENERIC_IO profile: no channels?\n"); > + return -EINVAL; > + } > + break; > + case UAC3_FUNCTION_SUBCLASS_HEADPHONE: > + /* BAOF; Stereo only cfg, Mono alt possible */ > + if (p_chmask != 3) > + usb_audio_warn(mixer->chip, > + "BADD HEADPHONE p_chmask mismatch: expected 3 actual %d\n", > + p_chmask); > + p_chmask = 3; > + break; > + case UAC3_FUNCTION_SUBCLASS_SPEAKER: > + /* BAOF; Mono or Stereo cfg, Mono alt possible */ > + /* p_chmask := DYNAMIC */ > + if (!p_chmask) { > + usb_audio_err(mixer->chip, > + "BADD SPEAKER profile: no playback channels?\n"); > + return -EINVAL; > + } > + break; > + case UAC3_FUNCTION_SUBCLASS_MICROPHONE: > + /* BAIF; Mono or Stereo cfg, Mono alt possible */ > + /* c_chmask := DYNAMIC */ > + if (!c_chmask) { > + usb_audio_err(mixer->chip, > + "BADD MICROPHONE profile: no capture channels?\n"); > + return -EINVAL; > + } > + break; > + case UAC3_FUNCTION_SUBCLASS_HEADSET: > + /* > + * BAIOF > + * IN: Mono only > + * OUT: Mono or Stereo cfg, Mono alt possible > + */ > + if (c_chmask != 1) > + usb_audio_warn(mixer->chip, > + "BADD HEADSET c_chmask mismatch: expected 1 actual %d\n", > + c_chmask); > + c_chmask = 1; > + st_chmask = 1; > + /* p_chmask := DYNAMIC */ > + if (!p_chmask) { > + usb_audio_err(mixer->chip, > + "BADD HEADSET profile: no playback channels?\n"); > + return -EINVAL; > + } > + break; > + case UAC3_FUNCTION_SUBCLASS_HEADSET_ADAPTER: > + /* BAIOF; IN: Mono only; OUT: Stereo only, Mono alt possible */ > + if (c_chmask != 1) > + usb_audio_warn(mixer->chip, > + "BADD HEADSET_ADAPTER c_chmask mismatch: expected 1 actual %d\n", > + c_chmask); > + if (p_chmask != 3) > + usb_audio_warn(mixer->chip, > + "BADD HEADSET_ADAPTER p_chmask mismatch: expected 3 actual %d\n", > + p_chmask); > + c_chmask = 1; > + st_chmask = 1; > + p_chmask = 3; > + break; > + case UAC3_FUNCTION_SUBCLASS_SPEAKERPHONE: > + /* BAIF + BAOF; IN: Mono only; OUT: Mono only */ > + if (c_chmask != 1) > + usb_audio_warn(mixer->chip, > + "BADD SPEAKERPHONE c_chmask mismatch: expected 1 actual %d\n", > + c_chmask); > + if (p_chmask != 1) > + usb_audio_warn(mixer->chip, > + "BADD SPEAKERPHONE p_chmask mismatch: expected 1 actual %d\n", > + p_chmask); > + c_chmask = 1; > + p_chmask = 1; > + break; > + } > + > + /* Playback */ > + if (p_chmask) { > + /* Master channel, always writable */ > + build_feature_ctl_badd(mixer, 0, UAC_FU_MUTE, > + UAC3_BADD_FU_ID2, map->map); > + /* Mono/Stereo volume channels, always writable */ > + build_feature_ctl_badd(mixer, p_chmask, UAC_FU_VOLUME, > + UAC3_BADD_FU_ID2, map->map); > + } > + > + /* Capture */ > + if (c_chmask) { > + /* Master channel, always writable */ > + build_feature_ctl_badd(mixer, 0, UAC_FU_MUTE, > + UAC3_BADD_FU_ID5, map->map); > + /* Mono/Stereo volume channels, always writable */ > + build_feature_ctl_badd(mixer, c_chmask, UAC_FU_VOLUME, > + UAC3_BADD_FU_ID5, map->map); > + } > + > + /* Side tone-mixing */ > + if (st_chmask) { > + /* Master channel, always writable */ > + build_feature_ctl_badd(mixer, 0, UAC_FU_MUTE, > + UAC3_BADD_FU_ID7, map->map); > + /* Mono volume channel, always writable */ > + build_feature_ctl_badd(mixer, 1, UAC_FU_VOLUME, > + UAC3_BADD_FU_ID7, map->map); > + } > + > + return 0; > +} > + > +/* > * create mixer controls > * > * walk through all UAC_OUTPUT_TERMINAL descriptors to search for > mixers > @@ -2838,9 +3126,14 @@ int snd_usb_create_mixer(struct snd_usb_audio > *chip, int ctrlif, > break; > } > > - if ((err = snd_usb_mixer_controls(mixer)) < 0 || > - (err = snd_usb_mixer_status_create(mixer)) < 0) > + if (mixer->protocol == UAC_VERSION_3 && > + chip->badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) { > + if ((err = snd_usb_mixer_controls_badd(mixer, ctrlif)) < 0) > + goto _error; > + } else if ((err = snd_usb_mixer_controls(mixer)) < 0 || > + (err = snd_usb_mixer_status_create(mixer)) < 0) { > goto _error; > + } > > snd_usb_mixer_apply_create_quirk(mixer); > > diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c > index 9038b2e..13f03c8 100644 > --- a/sound/usb/mixer_maps.c > +++ b/sound/usb/mixer_maps.c > @@ -482,3 +482,68 @@ struct usbmix_ctl_map { > { 0 } /* terminator */ > }; > > +/* > + * Control map entries for UAC3 BADD profiles > + */ > + > +static struct usbmix_name_map uac3_badd_generic_io_map[] = { > + { UAC3_BADD_FU_ID2, "Generic Out Playback" }, > + { UAC3_BADD_FU_ID5, "Generic In Capture" }, > + { 0 } /* terminator */ > +}; > +static struct usbmix_name_map uac3_badd_headphone_map[] = { > + { UAC3_BADD_FU_ID2, "Headphone Playback" }, > + { 0 } /* terminator */ > +}; > +static struct usbmix_name_map uac3_badd_speaker_map[] = { > + { UAC3_BADD_FU_ID2, "Speaker Playback" }, > + { 0 } /* terminator */ > +}; > +static struct usbmix_name_map uac3_badd_microphone_map[] = { > + { UAC3_BADD_FU_ID5, "Mic Capture" }, > + { 0 } /* terminator */ > +}; > +/* Covers also 'headset adapter' profile */ > +static struct usbmix_name_map uac3_badd_headset_map[] = { > + { UAC3_BADD_FU_ID2, "Headset Playback" }, > + { UAC3_BADD_FU_ID5, "Headset Capture" }, > + { UAC3_BADD_FU_ID7, "Side Tone Mixing" }, > + { 0 } /* terminator */ > +}; > +static struct usbmix_name_map uac3_badd_speakerphone_map[] = { > + { UAC3_BADD_FU_ID2, "Speaker Playback" }, > + { UAC3_BADD_FU_ID5, "Mic Capture" }, > + { 0 } /* terminator */ > +}; > + > +static struct usbmix_ctl_map uac3_badd_usbmix_ctl_maps[] = { > + { > + .id = UAC3_FUNCTION_SUBCLASS_GENERIC_IO, > + .map = uac3_badd_generic_io_map, > + }, > + { > + .id = UAC3_FUNCTION_SUBCLASS_HEADPHONE, > + .map = uac3_badd_headphone_map, > + }, > + { > + .id = UAC3_FUNCTION_SUBCLASS_SPEAKER, > + .map = uac3_badd_speaker_map, > + }, > + { > + .id = UAC3_FUNCTION_SUBCLASS_MICROPHONE, > + .map = uac3_badd_microphone_map, > + }, > + { > + .id = UAC3_FUNCTION_SUBCLASS_HEADSET, > + .map = uac3_badd_headset_map, > + }, > + { > + .id = UAC3_FUNCTION_SUBCLASS_HEADSET_ADAPTER, > + .map = uac3_badd_headset_map, > + }, > + { > + .id = UAC3_FUNCTION_SUBCLASS_SPEAKERPHONE, > + .map = uac3_badd_speakerphone_map, > + }, > + { 0 } /* terminator */ > +}; > diff --git a/sound/usb/stream.c b/sound/usb/stream.c > index 586d664..ea5a13e0 100644 > --- a/sound/usb/stream.c > +++ b/sound/usb/stream.c > @@ -798,15 +798,67 @@ static int parse_uac_endpoint_attributes(struct > snd_usb_audio *chip, > struct uac3_input_terminal_descriptor *input_term; > struct uac3_output_terminal_descriptor *output_term; > struct uac3_cluster_header_descriptor *cluster; > - struct uac3_as_header_descriptor *as; > + struct uac3_as_header_descriptor *as = NULL; > struct uac3_hc_descriptor_header hc_header; > struct snd_pcm_chmap_elem *chmap; > + unsigned char badd_profile; > + u64 badd_formats = 0; > unsigned int num_channels; > struct audioformat *fp; > u16 cluster_id, wLength; > int clock = 0; > int err; > > + badd_profile = chip->badd_profile; > + > + if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) { > + unsigned int maxpacksize = > + le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); > + > + switch (maxpacksize) { > + default: > + dev_err(&dev->dev, > + "%u:%d : incorrect wMaxPacketSize for BADD profile\n", > + iface_no, altno); > + return NULL; > + case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16: > + case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16: > + badd_formats = SNDRV_PCM_FMTBIT_S16_LE; > + num_channels = 1; > + break; > + case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24: > + case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24: > + badd_formats = SNDRV_PCM_FMTBIT_S24_3LE; > + num_channels = 1; > + break; > + case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16: > + case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16: > + badd_formats = SNDRV_PCM_FMTBIT_S16_LE; > + num_channels = 2; > + break; > + case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24: > + case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24: > + badd_formats = SNDRV_PCM_FMTBIT_S24_3LE; > + num_channels = 2; > + break; > + } > + > + chmap = kzalloc(sizeof(*chmap), GFP_KERNEL); > + if (!chmap) > + return ERR_PTR(-ENOMEM); > + > + if (num_channels == 1) { > + chmap->map[0] = SNDRV_CHMAP_MONO; > + } else { > + chmap->map[0] = SNDRV_CHMAP_FL; > + chmap->map[1] = SNDRV_CHMAP_FR; > + } > + > + chmap->channels = num_channels; > + clock = UAC3_BADD_CS_ID9; > + goto found_clock; > + } > + > as = snd_usb_find_csint_desc(alts->extra, alts->extralen, > NULL, UAC_AS_GENERAL); > if (!as) { > @@ -922,18 +974,31 @@ static int parse_uac_endpoint_attributes(struct > snd_usb_audio *chip, > if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) > fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) > * (fp->maxpacksize & 0x7ff); > - fp->attributes = parse_uac_endpoint_attributes(chip, alts, > - UAC_VERSION_3, > - iface_no); > fp->clock = clock; > fp->chmap = chmap; > INIT_LIST_HEAD(&fp->list); > > - /* ok, let's parse further... */ > - if (snd_usb_parse_audio_format_v3(chip, fp, as, stream) < 0) { > - kfree(fp->rate_table); > - kfree(fp); > - return NULL; > + if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) { > + fp->attributes = 0; /* No attributes */ > + > + fp->fmt_type = UAC_FORMAT_TYPE_I; > + fp->formats = badd_formats; > + > + fp->nr_rates = 0; /* SNDRV_PCM_RATE_CONTINUOUS */ > + fp->rate_min = UAC3_BADD_SAMPLING_RATE; > + fp->rate_max = UAC3_BADD_SAMPLING_RATE; > + fp->rates = SNDRV_PCM_RATE_CONTINUOUS; > + > + } else { > + fp->attributes = parse_uac_endpoint_attributes(chip, alts, > + UAC_VERSION_3, > + iface_no); > + /* ok, let's parse further... */ > + if (snd_usb_parse_audio_format_v3(chip, fp, as, stream) < 0) { > + kfree(fp->rate_table); > + kfree(fp); > + return NULL; > + } > } > > return fp; > diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h > index 4d5c89a..1bb5e2c 100644 > --- a/sound/usb/usbaudio.h > +++ b/sound/usb/usbaudio.h > @@ -49,6 +49,8 @@ struct snd_usb_audio { > int num_suspended_intf; > int sample_rate_read_error; > > + int badd_profile; /* UAC3 BADD profile */ > + > struct list_head pcm_list; /* list of pcm streams */ > struct list_head ep_list; /* list of audio-related endpoints */ > int pcm_devs; From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jorge Sanjuan Subject: Re: [PATCH 4/4] ALSA: usb: add UAC3 BADD profiles support Date: Sat, 14 Apr 2018 18:55:13 +0100 Message-ID: <298440e44133287c3f86a0cae2fd08e1@codethink.com> References: <1523658266-2259-1-git-send-email-ruslan.bilovol@gmail.com> <1523658266-2259-5-git-send-email-ruslan.bilovol@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8"; Format="flowed" Content-Transfer-Encoding: base64 Return-path: Received: from imap1.codethink.co.uk (imap1.codethink.co.uk [176.9.8.82]) by alsa0.perex.cz (Postfix) with ESMTP id 90F0E267235 for ; Sat, 14 Apr 2018 19:55:16 +0200 (CEST) In-Reply-To: <1523658266-2259-5-git-send-email-ruslan.bilovol@gmail.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org To: Ruslan Bilovol Cc: Greg Kroah-Hartman , alsa-devel@alsa-project.org, Takashi Iwai , linux-kernel@vger.kernel.org List-Id: alsa-devel@alsa-project.org CgpPbiAyMDE4LTA0LTEzIDIzOjI0LCBSdXNsYW4gQmlsb3ZvbCB3cm90ZToKPiBSZWNlbnRseSBy ZWxlYXNlZCBVU0IgQXVkaW8gQ2xhc3MgMy4wIHNwZWNpZmljYXRpb24KPiBjb250YWlucyBCQURE IChCYXNpYyBBdWRpbyBEZXZpY2UgRGVmaW5pdGlvbikgZG9jdW1lbnQKPiB3aGljaCBkZXNjcmli ZXMgcHJlLWRlZmluZWQgVUFDMyBjb25maWd1cmF0aW9ucy4KPiAKPiBCQUREIHN1cHBvcnQgaXMg bWFuZGF0b3J5IGZvciBVQUMzIGRldmljZXMsIGl0IHNob3VsZCBiZQo+IGltcGxlbWVudGVkIGFz IGEgc2VwYXJhdGUgVVNCIGRldmljZSBjb25maWd1cmF0aW9uLgo+IEFzIHBlciBCQUREIGRvY3Vt ZW50LCBjbGFzcy1zcGVjaWZpYyBkZXNjcmlwdG9ycwo+IHNoYWxsIG5vdCBiZSBpbmNsdWRlZCBp biB0aGUgRGV2aWNl4oCZcyBDb25maWd1cmF0aW9uCj4gZGVzY3JpcHRvciAoImluZmVycmVkIiks IGJ1dCBob3N0IGNhbiBndWVzcyB0aGVtCj4gZnJvbSBCQUREIHByb2ZpbGUgbnVtYmVyLCBudW1i ZXIgb2YgZW5kcG9pbnRzIGFuZAo+IHRoZWlyIG1heCBwYWNrZWQgc2l6ZXMuCgpSaWdodC4gSSB3 b3VsZCBoYXZlIHRob3VnaHQgdGhhdCwgc2luY2UgQkFERCBpcyBhIHN1YnNldCBvZiBVQUMzLCBp dCBtYXkgCmJlIHNpbXBsZXIgdG8gZmlsbCB0aGUgQ2xhc3MgU3BlY2lmaWMgZGVzY3JpcHRvcnMg YnVmZmVyIGFuZCBsZXQgdGhlIApVQUMzIHBhdGggaW50YWN0IGFzIGl0IHdvdWxkIHJlc3VsdCBp biB0aGUgc2FtZSBiZWhhdmlvciAoZm9yIFVBQzMgYW5kIApCQUREIGNvbmZpZ3MpIHdpdGhvdXQg dGhlIG5lZWQgdG8gYWRkIHRoYXQgbXVjaCBjb2RlIHRvIHRoZSBtaXhlciwgd2hpY2ggCmlzIGFs cmVhZHkgcXVpdGUgYmlnLgoKSW4gdGhlIHBhdGNoIEkgcHJvcG9zZWQgWzFdLCB0aGUgQ2xhc3Mg U3BlY2lmaWMgYnVmZmVyIGlzIGZpbGxlZCBvbmNlIAp3aXRoIHRoZSBCQUREIGRlc2NyaXB0b3Jz LCB3aGljaCBhcmUgYWxyZWFkeSBVQUMzIGNvbXBsaWFudCwgc28gdGhlIApkcml2ZXIgd291bGQg aGFuZGxlIHRoZSByZXN0IGluIHRoZSBzYW1lIHdheSBpdCB3b3VsZCBkbyB3aXRoIGFuIFVBQzMg CmNvbmZpZ3VyYXRpb24uCgpJIHdpbGwga2VlcCBhbiBleWUgb24gdGhpcyBhcyBJJ2QgbmVlZCB0 byBkbyBzb21lIHdvcmsgYmFzZWQgb24gdGhpcyAKaW5zdGVhZC4KClsxXSBodHRwczovL3d3dy5z cGluaWNzLm5ldC9saXN0cy9hbHNhLWRldmVsL21zZzcxNjE3Lmh0bWwKClRoYW5rcywKCkpvcmdl Cgo+IAo+IFRoaXMgcGF0Y2ggYWRkcyBzdXBwb3J0IG9mIGFsbCBCQUREIHByb2ZpbGVzIGZyb20g dGhlIHNwZWMKPiAKPiBTaWduZWQtb2ZmLWJ5OiBSdXNsYW4gQmlsb3ZvbCA8cnVzbGFuLmJpbG92 b2xAZ21haWwuY29tPgo+IC0tLQo+ICBzb3VuZC91c2IvY2FyZC5jICAgICAgIHwgIDE0ICsrKwo+ ICBzb3VuZC91c2IvY2xvY2suYyAgICAgIHwgICA5ICstCj4gIHNvdW5kL3VzYi9taXhlci5jICAg ICAgfCAzMTMgCj4gKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr KystLQo+ICBzb3VuZC91c2IvbWl4ZXJfbWFwcy5jIHwgIDY1ICsrKysrKysrKysKPiAgc291bmQv dXNiL3N0cmVhbS5jICAgICB8ICA4MyArKysrKysrKysrKy0tCj4gIHNvdW5kL3VzYi91c2JhdWRp by5oICAgfCAgIDIgKwo+ICA2IGZpbGVzIGNoYW5nZWQsIDQ2NiBpbnNlcnRpb25zKCspLCAyMCBk ZWxldGlvbnMoLSkKPiAKPiBkaWZmIC0tZ2l0IGEvc291bmQvdXNiL2NhcmQuYyBiL3NvdW5kL3Vz Yi9jYXJkLmMKPiBpbmRleCA0ZDg2NmJkLi40N2ViYzUwIDEwMDY0NAo+IC0tLSBhL3NvdW5kL3Vz Yi9jYXJkLmMKPiArKysgYi9zb3VuZC91c2IvY2FyZC5jCj4gQEAgLTMwNyw2ICszMDcsMjAgQEAg c3RhdGljIGludCBzbmRfdXNiX2NyZWF0ZV9zdHJlYW1zKHN0cnVjdAo+IHNuZF91c2JfYXVkaW8g KmNoaXAsIGludCBjdHJsaWYpCj4gIAkJCXJldHVybiAtRUlOVkFMOwo+ICAJCX0KPiAKPiArCQlp ZiAocHJvdG9jb2wgPT0gVUFDX1ZFUlNJT05fMykgewo+ICsJCQlpbnQgYmFkZCA9IGFzc29jLT5i RnVuY3Rpb25TdWJDbGFzczsKPiArCj4gKwkJCWlmIChiYWRkICE9IFVBQzNfRlVOQ1RJT05fU1VC Q0xBU1NfRlVMTF9BRENfM18wICYmCj4gKwkJCSAgICAoYmFkZCA8IFVBQzNfRlVOQ1RJT05fU1VC Q0xBU1NfR0VORVJJQ19JTyB8fAo+ICsJCQkgICAgIGJhZGQgPiBVQUMzX0ZVTkNUSU9OX1NVQkNM QVNTX1NQRUFLRVJQSE9ORSkpIHsKPiArCQkJCWRldl9lcnIoJmRldi0+ZGV2LAo+ICsJCQkJCSJV bnN1cHBvcnRlZCBVQUMzIEJBREQgcHJvZmlsZVxuIik7Cj4gKwkJCQlyZXR1cm4gLUVJTlZBTDsK PiArCQkJfQo+ICsKPiArCQkJY2hpcC0+YmFkZF9wcm9maWxlID0gYmFkZDsKPiArCQl9Cj4gKwo+ ICAJCWZvciAoaSA9IDA7IGkgPCBhc3NvYy0+YkludGVyZmFjZUNvdW50OyBpKyspIHsKPiAgCQkJ aW50IGludGYgPSBhc3NvYy0+YkZpcnN0SW50ZXJmYWNlICsgaTsKPiAKPiBkaWZmIC0tZ2l0IGEv c291bmQvdXNiL2Nsb2NrLmMgYi9zb3VuZC91c2IvY2xvY2suYwo+IGluZGV4IDBiMDMwZDguLjE3 NjczZjMgMTAwNjQ0Cj4gLS0tIGEvc291bmQvdXNiL2Nsb2NrLmMKPiArKysgYi9zb3VuZC91c2Iv Y2xvY2suYwo+IEBAIC01ODcsOCArNTg3LDE1IEBAIGludCBzbmRfdXNiX2luaXRfc2FtcGxlX3Jh dGUoc3RydWN0IHNuZF91c2JfYXVkaW8KPiAqY2hpcCwgaW50IGlmYWNlLAo+ICAJZGVmYXVsdDoK PiAgCQlyZXR1cm4gc2V0X3NhbXBsZV9yYXRlX3YxKGNoaXAsIGlmYWNlLCBhbHRzLCBmbXQsIHJh dGUpOwo+IAo+IC0JY2FzZSBVQUNfVkVSU0lPTl8yOgo+ICAJY2FzZSBVQUNfVkVSU0lPTl8zOgo+ ICsJCWlmIChjaGlwLT5iYWRkX3Byb2ZpbGUgPj0gVUFDM19GVU5DVElPTl9TVUJDTEFTU19HRU5F UklDX0lPKSB7Cj4gKwkJCWlmIChyYXRlICE9IFVBQzNfQkFERF9TQU1QTElOR19SQVRFKQo+ICsJ CQkJcmV0dXJuIC1FTlhJTzsKPiArCQkJZWxzZQo+ICsJCQkJcmV0dXJuIDA7Cj4gKwkJfQo+ICsJ LyogZmFsbCB0aHJvdWdoICovCj4gKwljYXNlIFVBQ19WRVJTSU9OXzI6Cj4gIAkJcmV0dXJuIHNl dF9zYW1wbGVfcmF0ZV92MnYzKGNoaXAsIGlmYWNlLCBhbHRzLCBmbXQsIHJhdGUpOwo+ICAJfQo+ ICB9Cj4gZGlmZiAtLWdpdCBhL3NvdW5kL3VzYi9taXhlci5jIGIvc291bmQvdXNiL21peGVyLmMK PiBpbmRleCAzMDFhZDYxLi5lNWMzYjBkIDEwMDY0NAo+IC0tLSBhL3NvdW5kL3VzYi9taXhlci5j Cj4gKysrIGIvc291bmQvdXNiL21peGVyLmMKPiBAQCAtMTEyLDE0ICsxMTIsMTIgQEAgZW51bSB7 Cj4gICNpbmNsdWRlICJtaXhlcl9tYXBzLmMiCj4gCj4gIHN0YXRpYyBjb25zdCBzdHJ1Y3QgdXNi bWl4X25hbWVfbWFwICoKPiAtZmluZF9tYXAoc3RydWN0IG1peGVyX2J1aWxkICpzdGF0ZSwgaW50 IHVuaXRpZCwgaW50IGNvbnRyb2wpCj4gK2ZpbmRfbWFwKGNvbnN0IHN0cnVjdCB1c2JtaXhfbmFt ZV9tYXAgKnAsIGludCB1bml0aWQsIGludCBjb250cm9sKQo+ICB7Cj4gLQljb25zdCBzdHJ1Y3Qg dXNibWl4X25hbWVfbWFwICpwID0gc3RhdGUtPm1hcDsKPiAtCj4gIAlpZiAoIXApCj4gIAkJcmV0 dXJuIE5VTEw7Cj4gCj4gLQlmb3IgKHAgPSBzdGF0ZS0+bWFwOyBwLT5pZDsgcCsrKSB7Cj4gKwlm b3IgKDsgcC0+aWQ7IHArKykgewo+ICAJCWlmIChwLT5pZCA9PSB1bml0aWQgJiYKPiAgCQkgICAg KCFjb250cm9sIHx8ICFwLT5jb250cm9sIHx8IGNvbnRyb2wgPT0gcC0+Y29udHJvbCkpCj4gIAkJ CXJldHVybiBwOwo+IEBAIC0xMzMzLDYgKzEzMzEsNzYgQEAgc3RhdGljIHN0cnVjdCB1c2JfZmVh dHVyZV9jb250cm9sX2luZm8KPiAqZ2V0X2ZlYXR1cmVfY29udHJvbF9pbmZvKGludCBjb250cm9s KQo+ICAJcmV0dXJuIE5VTEw7Cj4gIH0KPiAKPiArc3RhdGljIHZvaWQgYnVpbGRfZmVhdHVyZV9j dGxfYmFkZChzdHJ1Y3QgdXNiX21peGVyX2ludGVyZmFjZSAqbWl4ZXIsCj4gKwkJCSAgICAgIHVu c2lnbmVkIGludCBjdGxfbWFzaywgaW50IGNvbnRyb2wsIGludCB1bml0aWQsCj4gKwkJCSAgICAg IGNvbnN0IHN0cnVjdCB1c2JtaXhfbmFtZV9tYXAgKmJhZGRfbWFwKQo+ICt7Cj4gKwlzdHJ1Y3Qg dXNiX2ZlYXR1cmVfY29udHJvbF9pbmZvICpjdGxfaW5mbzsKPiArCXVuc2lnbmVkIGludCBsZW4g PSAwOwo+ICsJc3RydWN0IHNuZF9rY29udHJvbCAqa2N0bDsKPiArCXN0cnVjdCB1c2JfbWl4ZXJf ZWxlbV9pbmZvICpjdmFsOwo+ICsJY29uc3Qgc3RydWN0IHVzYm1peF9uYW1lX21hcCAqbWFwOwo+ ICsKPiArCW1hcCA9IGZpbmRfbWFwKGJhZGRfbWFwLCB1bml0aWQsIGNvbnRyb2wpOwo+ICsJaWYg KCFtYXApCj4gKwkJcmV0dXJuOwo+ICsKPiArCWN2YWwgPSBremFsbG9jKHNpemVvZigqY3ZhbCks IEdGUF9LRVJORUwpOwo+ICsJaWYgKCFjdmFsKQo+ICsJCXJldHVybjsKPiArCXNuZF91c2JfbWl4 ZXJfZWxlbV9pbml0X3N0ZCgmY3ZhbC0+aGVhZCwgbWl4ZXIsIHVuaXRpZCk7Cj4gKwljdmFsLT5j b250cm9sID0gY29udHJvbDsKPiArCWN2YWwtPmNtYXNrID0gY3RsX21hc2s7Cj4gKwo+ICsJY3Rs X2luZm8gPSBnZXRfZmVhdHVyZV9jb250cm9sX2luZm8oY29udHJvbCk7Cj4gKwlpZiAoIWN0bF9p bmZvKSB7Cj4gKwkJa2ZyZWUoY3ZhbCk7Cj4gKwkJcmV0dXJuOwo+ICsJfQo+ICsJY3ZhbC0+dmFs X3R5cGUgPSBjdGxfaW5mby0+dHlwZTsKPiArCj4gKwlpZiAoY3RsX21hc2sgPT0gMCkgewo+ICsJ CWN2YWwtPmNoYW5uZWxzID0gMTsJLyogbWFzdGVyIGNoYW5uZWwgKi8KPiArCX0gZWxzZSB7Cj4g KwkJaW50IGksIGMgPSAwOwo+ICsKPiArCQlmb3IgKGkgPSAwOyBpIDwgMjsgaSsrKQo+ICsJCQlp ZiAoY3RsX21hc2sgJiAoMSA8PCBpKSkKPiArCQkJCWMrKzsKPiArCQljdmFsLT5jaGFubmVscyA9 IGM7Cj4gKwl9Cj4gKwo+ICsJa2N0bCA9IHNuZF9jdGxfbmV3MSgmdXNiX2ZlYXR1cmVfdW5pdF9j dGwsIGN2YWwpOwo+ICsKPiArCWlmICgha2N0bCkgewo+ICsJCXVzYl9hdWRpb19lcnIobWl4ZXIt PmNoaXAsICJjYW5ub3QgbWFsbG9jIGtjb250cm9sXG4iKTsKPiArCQlrZnJlZShjdmFsKTsKPiAr CQlyZXR1cm47Cj4gKwl9Cj4gKwlrY3RsLT5wcml2YXRlX2ZyZWUgPSBzbmRfdXNiX21peGVyX2Vs ZW1fZnJlZTsKPiArCWxlbiA9IGNoZWNrX21hcHBlZF9uYW1lKG1hcCwga2N0bC0+aWQubmFtZSwg c2l6ZW9mKGtjdGwtPmlkLm5hbWUpKTsKPiArCj4gKwlhcHBlbmRfY3RsX25hbWUoa2N0bCwgY29u dHJvbCA9PSBVQUNfRlVfTVVURSA/ICIgU3dpdGNoIiA6ICIgCj4gVm9sdW1lIik7Cj4gKwo+ICsJ LyogZ2V0IG1pbi9tYXggdmFsdWVzICovCj4gKwlnZXRfbWluX21heF93aXRoX3F1aXJrcyhjdmFs LCAwLCBrY3RsKTsKPiArCj4gKwlpZiAoY29udHJvbCA9PSBVQUNfRlVfVk9MVU1FKSB7Cj4gKwkJ Y2hlY2tfbWFwcGVkX2RCKG1hcCwgY3ZhbCk7Cj4gKwkJaWYgKGN2YWwtPmRCbWluIDwgY3ZhbC0+ ZEJtYXggfHwgIWN2YWwtPmluaXRpYWxpemVkKSB7Cj4gKwkJCWtjdGwtPnRsdi5jID0gc25kX3Vz Yl9taXhlcl92b2xfdGx2Owo+ICsJCQlrY3RsLT52ZFswXS5hY2Nlc3MgfD0KPiArCQkJCVNORFJW X0NUTF9FTEVNX0FDQ0VTU19UTFZfUkVBRCB8Cj4gKwkJCQlTTkRSVl9DVExfRUxFTV9BQ0NFU1Nf VExWX0NBTExCQUNLOwo+ICsJCX0KPiArCX0KPiArCj4gKwl1c2JfYXVkaW9fZGJnKG1peGVyLT5j aGlwLCAiWyVkXSBGVSBbJXNdIGNoID0gJWQsIHZhbCA9ICVkLyVkLyVkXG4iLAo+ICsJCSAgICAg IGN2YWwtPmhlYWQuaWQsIGtjdGwtPmlkLm5hbWUsIGN2YWwtPmNoYW5uZWxzLAo+ICsJCSAgICAg IGN2YWwtPm1pbiwgY3ZhbC0+bWF4LCBjdmFsLT5yZXMpOwo+ICsJc25kX3VzYl9taXhlcl9hZGRf Y29udHJvbCgmY3ZhbC0+aGVhZCwga2N0bCk7Cj4gK30KPiArCj4gIHN0YXRpYyB2b2lkIGJ1aWxk X2ZlYXR1cmVfY3RsKHN0cnVjdCBtaXhlcl9idWlsZCAqc3RhdGUsIHZvaWQgCj4gKnJhd19kZXNj LAo+ICAJCQkgICAgICB1bnNpZ25lZCBpbnQgY3RsX21hc2ssIGludCBjb250cm9sLAo+ICAJCQkg ICAgICBzdHJ1Y3QgdXNiX2F1ZGlvX3Rlcm0gKml0ZXJtLCBpbnQgdW5pdGlkLAo+IEBAIC0xMzUz LDcgKzE0MjEsNyBAQCBzdGF0aWMgdm9pZCBidWlsZF9mZWF0dXJlX2N0bChzdHJ1Y3QgbWl4ZXJf YnVpbGQKPiAqc3RhdGUsIHZvaWQgKnJhd19kZXNjLAo+ICAJCXJldHVybjsKPiAgCX0KPiAKPiAt CW1hcCA9IGZpbmRfbWFwKHN0YXRlLCB1bml0aWQsIGNvbnRyb2wpOwo+ICsJbWFwID0gZmluZF9t YXAoc3RhdGUtPm1hcCwgdW5pdGlkLCBjb250cm9sKTsKPiAgCWlmIChjaGVja19pZ25vcmVkX2N0 bChtYXApKQo+ICAJCXJldHVybjsKPiAKPiBAQCAtMTgwNiw3ICsxODc0LDcgQEAgc3RhdGljIHZv aWQgYnVpbGRfbWl4ZXJfdW5pdF9jdGwoc3RydWN0Cj4gbWl4ZXJfYnVpbGQgKnN0YXRlLAo+ICAJ c3RydWN0IHNuZF9rY29udHJvbCAqa2N0bDsKPiAgCWNvbnN0IHN0cnVjdCB1c2JtaXhfbmFtZV9t YXAgKm1hcDsKPiAKPiAtCW1hcCA9IGZpbmRfbWFwKHN0YXRlLCB1bml0aWQsIDApOwo+ICsJbWFw ID0gZmluZF9tYXAoc3RhdGUtPm1hcCwgdW5pdGlkLCAwKTsKPiAgCWlmIChjaGVja19pZ25vcmVk X2N0bChtYXApKQo+ICAJCXJldHVybjsKPiAKPiBAQCAtMjEwNSw3ICsyMTczLDcgQEAgc3RhdGlj IGludCBidWlsZF9hdWRpb19wcm9jdW5pdChzdHJ1Y3QKPiBtaXhlcl9idWlsZCAqc3RhdGUsIGlu dCB1bml0aWQsCj4gCj4gIAkJaWYgKCEoY29udHJvbHNbdmFsaW5mby0+Y29udHJvbCAvIDhdICYg KDEgPDwgKCh2YWxpbmZvLT5jb250cm9sICUgOCkgCj4gLSAxKSkpKQo+ICAJCQljb250aW51ZTsK PiAtCQltYXAgPSBmaW5kX21hcChzdGF0ZSwgdW5pdGlkLCB2YWxpbmZvLT5jb250cm9sKTsKPiAr CQltYXAgPSBmaW5kX21hcChzdGF0ZS0+bWFwLCB1bml0aWQsIHZhbGluZm8tPmNvbnRyb2wpOwo+ ICAJCWlmIChjaGVja19pZ25vcmVkX2N0bChtYXApKQo+ICAJCQljb250aW51ZTsKPiAgCQljdmFs ID0ga3phbGxvYyhzaXplb2YoKmN2YWwpLCBHRlBfS0VSTkVMKTsKPiBAQCAtMjMwOCw3ICsyMzc2 LDcgQEAgc3RhdGljIGludCBwYXJzZV9hdWRpb19zZWxlY3Rvcl91bml0KHN0cnVjdAo+IG1peGVy X2J1aWxkICpzdGF0ZSwgaW50IHVuaXRpZCwKPiAgCWlmIChkZXNjLT5iTnJJblBpbnMgPT0gMSkg Lyogb25seSBvbmUgPyBub25zZW5zZSEgKi8KPiAgCQlyZXR1cm4gMDsKPiAKPiAtCW1hcCA9IGZp bmRfbWFwKHN0YXRlLCB1bml0aWQsIDApOwo+ICsJbWFwID0gZmluZF9tYXAoc3RhdGUtPm1hcCwg dW5pdGlkLCAwKTsKPiAgCWlmIChjaGVja19pZ25vcmVkX2N0bChtYXApKQo+ICAJCXJldHVybiAw Owo+IAo+IEBAIC0yNDk1LDYgKzI1NjMsMjI2IEBAIHN0YXRpYyBpbnQgc25kX3VzYl9taXhlcl9k ZXZfZnJlZShzdHJ1Y3QKPiBzbmRfZGV2aWNlICpkZXZpY2UpCj4gIH0KPiAKPiAgLyoKPiArICog Y3JlYXRlIG1peGVyIGNvbnRyb2xzIGZvciBVQUMzIEJBREQgcHJvZmlsZXMKPiArICoKPiArICog VUFDMyBCQUREIGRldmljZSBkb2Vzbid0IGNvbnRhaW4gQ1MgZGVzY3JpcHRvcnMgdGh1cyB3ZSB3 aWxsIGd1ZXNzCj4gZXZlcnl0aGluZwo+ICsgKgo+ICsgKiBCQUREIGRldmljZSBtYXkgY29udGFp biBNaXhlciBVbml0LCB3aGljaCBkb2Vzbid0IGhhdmUgYW55IAo+IGNvbnRyb2xzLCBza2lwIGl0 Cj4gKyAqLwo+ICtzdGF0aWMgaW50IHNuZF91c2JfbWl4ZXJfY29udHJvbHNfYmFkZChzdHJ1Y3Qg dXNiX21peGVyX2ludGVyZmFjZSAKPiAqbWl4ZXIsCj4gKwkJCQkgICAgICAgaW50IGN0cmxpZikK PiArewo+ICsJc3RydWN0IHVzYl9kZXZpY2UgKmRldiA9IG1peGVyLT5jaGlwLT5kZXY7Cj4gKwlz dHJ1Y3QgdXNiX2ludGVyZmFjZV9hc3NvY19kZXNjcmlwdG9yICphc3NvYzsKPiArCWludCBiYWRk X3Byb2ZpbGUgPSBtaXhlci0+Y2hpcC0+YmFkZF9wcm9maWxlOwo+ICsJY29uc3Qgc3RydWN0IHVz Ym1peF9jdGxfbWFwICptYXA7Cj4gKwlpbnQgcF9jaG1hc2sgPSAwLCBjX2NobWFzayA9IDAsIHN0 X2NobWFzayA9IDA7Cj4gKwlpbnQgaTsKPiArCj4gKwlhc3NvYyA9IHVzYl9pZm51bV90b19pZihk ZXYsIGN0cmxpZiktPmludGZfYXNzb2M7Cj4gKwo+ICsJLyogRGV0ZWN0IEJBREQgY2FwdHVyZS9w bGF5YmFjayBjaGFubmVscyBmcm9tIEFTIEVQIGRlc2NyaXB0b3JzICovCj4gKwlmb3IgKGkgPSAw OyBpIDwgYXNzb2MtPmJJbnRlcmZhY2VDb3VudDsgaSsrKSB7Cj4gKwkJaW50IGludGYgPSBhc3Nv Yy0+YkZpcnN0SW50ZXJmYWNlICsgaTsKPiArCj4gKwkJaWYgKGludGYgIT0gY3RybGlmKSB7Cj4g KwkJCXN0cnVjdCB1c2JfaW50ZXJmYWNlICppZmFjZTsKPiArCQkJc3RydWN0IHVzYl9ob3N0X2lu dGVyZmFjZSAqYWx0czsKPiArCQkJc3RydWN0IHVzYl9pbnRlcmZhY2VfZGVzY3JpcHRvciAqYWx0 c2Q7Cj4gKwkJCXVuc2lnbmVkIGludCBtYXhwYWNrc2l6ZTsKPiArCQkJY2hhciBkaXJfaW47Cj4g KwkJCWludCBjaG1hc2ssIG51bTsKPiArCj4gKwkJCWlmYWNlID0gdXNiX2lmbnVtX3RvX2lmKGRl diwgaW50Zik7Cj4gKwkJCW51bSA9IGlmYWNlLT5udW1fYWx0c2V0dGluZzsKPiArCj4gKwkJCWlm IChudW0gPCAyKQo+ICsJCQkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJCQkvKgo+ICsJCQkgKiBU aGUgbnVtYmVyIG9mIENoYW5uZWxzIGluIGFuIEF1ZGlvU3RyZWFtaW5nIGludGVyZmFjZQo+ICsJ CQkgKiBhbmQgdGhlIGF1ZGlvIHNhbXBsZSBiaXQgcmVzb2x1dGlvbiAoMTYgYml0cyBvciAyNAo+ ICsJCQkgKiBiaXRzKSBjYW4gYmUgZGVyaXZlZCBmcm9tIHRoZSB3TWF4UGFja2V0U2l6ZSBmaWVs ZCBpbgo+ICsJCQkgKiB0aGUgU3RhbmRhcmQgQVMgQXVkaW8gRGF0YSBFbmRwb2ludCBkZXNjcmlw dG9yIGluCj4gKwkJCSAqIEFsdGVybmF0ZSBTZXR0aW5nIDEKPiArCQkJICovCj4gKwkJCWFsdHMg PSAmaWZhY2UtPmFsdHNldHRpbmdbMV07Cj4gKwkJCWFsdHNkID0gZ2V0X2lmYWNlX2Rlc2MoYWx0 cyk7Cj4gKwo+ICsJCQlpZiAoYWx0c2QtPmJOdW1FbmRwb2ludHMgPCAxKQo+ICsJCQkJcmV0dXJu IC1FSU5WQUw7Cj4gKwo+ICsJCQkvKiBjaGVjayBkaXJlY3Rpb24gKi8KPiArCQkJZGlyX2luID0g KGdldF9lbmRwb2ludChhbHRzLCAwKS0+YkVuZHBvaW50QWRkcmVzcyAmIFVTQl9ESVJfSU4pOwo+ ICsJCQltYXhwYWNrc2l6ZSA9IGxlMTZfdG9fY3B1KGdldF9lbmRwb2ludChhbHRzLCAwKS0+d01h eFBhY2tldFNpemUpOwo+ICsKPiArCQkJc3dpdGNoIChtYXhwYWNrc2l6ZSkgewo+ICsJCQlkZWZh dWx0Ogo+ICsJCQkJdXNiX2F1ZGlvX2VycihtaXhlci0+Y2hpcCwKPiArCQkJCQkiaW5jb3JyZWN0 IHdNYXhQYWNrZXRTaXplIDB4JXggZm9yIEJBREQgcHJvZmlsZVxuIiwKPiArCQkJCQltYXhwYWNr c2l6ZSk7Cj4gKwkJCQlyZXR1cm4gLUVJTlZBTDsKPiArCQkJY2FzZSBVQUMzX0JBRERfRVBfTUFY UFNJWkVfU1lOQ19NT05PXzE2Ogo+ICsJCQljYXNlIFVBQzNfQkFERF9FUF9NQVhQU0laRV9BU1lO Q19NT05PXzE2Ogo+ICsJCQljYXNlIFVBQzNfQkFERF9FUF9NQVhQU0laRV9TWU5DX01PTk9fMjQ6 Cj4gKwkJCWNhc2UgVUFDM19CQUREX0VQX01BWFBTSVpFX0FTWU5DX01PTk9fMjQ6Cj4gKwkJCQlj aG1hc2sgPSAxOwo+ICsJCQkJYnJlYWs7Cj4gKwkJCWNhc2UgVUFDM19CQUREX0VQX01BWFBTSVpF X1NZTkNfU1RFUkVPXzE2Ogo+ICsJCQljYXNlIFVBQzNfQkFERF9FUF9NQVhQU0laRV9BU1lOQ19T VEVSRU9fMTY6Cj4gKwkJCWNhc2UgVUFDM19CQUREX0VQX01BWFBTSVpFX1NZTkNfU1RFUkVPXzI0 Ogo+ICsJCQljYXNlIFVBQzNfQkFERF9FUF9NQVhQU0laRV9BU1lOQ19TVEVSRU9fMjQ6Cj4gKwkJ CQljaG1hc2sgPSAzOwo+ICsJCQkJYnJlYWs7Cj4gKwkJCX0KPiArCj4gKwkJCWlmIChkaXJfaW4p Cj4gKwkJCQljX2NobWFzayA9IGNobWFzazsKPiArCQkJZWxzZQo+ICsJCQkJcF9jaG1hc2sgPSBj aG1hc2s7Cj4gKwkJfQo+ICsJfQo+ICsKPiArCXVzYl9hdWRpb19kYmcobWl4ZXItPmNoaXAsCj4g KwkJIlVBQzMgQkFERCBwcm9maWxlIDB4JXg6IGRldGVjdGVkIGNfY2htYXNrPSVkIHBfY2htYXNr PSVkXG4iLAo+ICsJCWJhZGRfcHJvZmlsZSwgY19jaG1hc2ssIHBfY2htYXNrKTsKPiArCj4gKwkv KiBjaGVjayB0aGUgbWFwcGluZyB0YWJsZSAqLwo+ICsJZm9yIChtYXAgPSB1YWMzX2JhZGRfdXNi bWl4X2N0bF9tYXBzOyBtYXAtPmlkOyBtYXArKykgewo+ICsJCWlmIChtYXAtPmlkID09IGJhZGRf cHJvZmlsZSkgewo+ICsJCQltaXhlci0+aWdub3JlX2N0bF9lcnJvciA9IG1hcC0+aWdub3JlX2N0 bF9lcnJvcjsKPiArCQkJYnJlYWs7Cj4gKwkJfQo+ICsJfQo+ICsKPiArCWlmICghbWFwLT5pZCkK PiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCj4gKwlzd2l0Y2ggKGJhZGRfcHJvZmlsZSkgewo+ICsJ ZGVmYXVsdDoKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCWNhc2UgVUFDM19GVU5DVElPTl9TVUJD TEFTU19HRU5FUklDX0lPOgo+ICsJCS8qCj4gKwkJICogQkFJRiwgQkFPRiBvciBjb21iaW5hdGlv biBvZiBib3RoCj4gKwkJICogSU46IE1vbm8gb3IgU3RlcmVvIGNmZywgTW9ubyBhbHQgcG9zc2li bGUKPiArCQkgKiBPVVQ6IE1vbm8gb3IgU3RlcmVvIGNmZywgTW9ubyBhbHQgcG9zc2libGUKPiAr CQkgKi8KPiArCQkvKiBjX2NobWFzayA6PSBEWU5BTUlDICovCj4gKwkJLyogcF9jaG1hc2sgOj0g RFlOQU1JQyAqLwo+ICsJCWlmICghY19jaG1hc2sgJiYgIXBfY2htYXNrKSB7Cj4gKwkJCXVzYl9h dWRpb19lcnIobWl4ZXItPmNoaXAsCj4gKwkJCQkiQkFERCBHRU5FUklDX0lPIHByb2ZpbGU6IG5v IGNoYW5uZWxzP1xuIik7Cj4gKwkJCXJldHVybiAtRUlOVkFMOwo+ICsJCX0KPiArCQlicmVhazsK PiArCWNhc2UgVUFDM19GVU5DVElPTl9TVUJDTEFTU19IRUFEUEhPTkU6Cj4gKwkJLyogQkFPRjsg U3RlcmVvIG9ubHkgY2ZnLCBNb25vIGFsdCBwb3NzaWJsZSAqLwo+ICsJCWlmIChwX2NobWFzayAh PSAzKQo+ICsJCQl1c2JfYXVkaW9fd2FybihtaXhlci0+Y2hpcCwKPiArCQkJCSJCQUREIEhFQURQ SE9ORSBwX2NobWFzayBtaXNtYXRjaDogZXhwZWN0ZWQgMyBhY3R1YWwgJWRcbiIsCj4gKwkJCQlw X2NobWFzayk7Cj4gKwkJcF9jaG1hc2sgPSAzOwo+ICsJCWJyZWFrOwo+ICsJY2FzZSBVQUMzX0ZV TkNUSU9OX1NVQkNMQVNTX1NQRUFLRVI6Cj4gKwkJLyogQkFPRjsgTW9ubyBvciBTdGVyZW8gY2Zn LCBNb25vIGFsdCBwb3NzaWJsZSAqLwo+ICsJCS8qIHBfY2htYXNrIDo9IERZTkFNSUMgKi8KPiAr CQlpZiAoIXBfY2htYXNrKSB7Cj4gKwkJCXVzYl9hdWRpb19lcnIobWl4ZXItPmNoaXAsCj4gKwkJ CQkiQkFERCBTUEVBS0VSIHByb2ZpbGU6IG5vIHBsYXliYWNrIGNoYW5uZWxzP1xuIik7Cj4gKwkJ CXJldHVybiAtRUlOVkFMOwo+ICsJCX0KPiArCQlicmVhazsKPiArCWNhc2UgVUFDM19GVU5DVElP Tl9TVUJDTEFTU19NSUNST1BIT05FOgo+ICsJCS8qIEJBSUY7IE1vbm8gb3IgU3RlcmVvIGNmZywg TW9ubyBhbHQgcG9zc2libGUgKi8KPiArCQkvKiBjX2NobWFzayA6PSBEWU5BTUlDICovCj4gKwkJ aWYgKCFjX2NobWFzaykgewo+ICsJCQl1c2JfYXVkaW9fZXJyKG1peGVyLT5jaGlwLAo+ICsJCQkJ IkJBREQgTUlDUk9QSE9ORSBwcm9maWxlOiBubyBjYXB0dXJlIGNoYW5uZWxzP1xuIik7Cj4gKwkJ CXJldHVybiAtRUlOVkFMOwo+ICsJCX0KPiArCQlicmVhazsKPiArCWNhc2UgVUFDM19GVU5DVElP Tl9TVUJDTEFTU19IRUFEU0VUOgo+ICsJCS8qCj4gKwkJICogQkFJT0YKPiArCQkgKiBJTjogTW9u byBvbmx5Cj4gKwkJICogT1VUOiBNb25vIG9yIFN0ZXJlbyBjZmcsIE1vbm8gYWx0IHBvc3NpYmxl Cj4gKwkJICovCj4gKwkJaWYgKGNfY2htYXNrICE9IDEpCj4gKwkJCXVzYl9hdWRpb193YXJuKG1p eGVyLT5jaGlwLAo+ICsJCQkJIkJBREQgSEVBRFNFVCBjX2NobWFzayBtaXNtYXRjaDogZXhwZWN0 ZWQgMSBhY3R1YWwgJWRcbiIsCj4gKwkJCQljX2NobWFzayk7Cj4gKwkJY19jaG1hc2sgPSAxOwo+ ICsJCXN0X2NobWFzayA9IDE7Cj4gKwkJLyogcF9jaG1hc2sgOj0gRFlOQU1JQyAqLwo+ICsJCWlm ICghcF9jaG1hc2spIHsKPiArCQkJdXNiX2F1ZGlvX2VycihtaXhlci0+Y2hpcCwKPiArCQkJCSJC QUREIEhFQURTRVQgcHJvZmlsZTogbm8gcGxheWJhY2sgY2hhbm5lbHM/XG4iKTsKPiArCQkJcmV0 dXJuIC1FSU5WQUw7Cj4gKwkJfQo+ICsJCWJyZWFrOwo+ICsJY2FzZSBVQUMzX0ZVTkNUSU9OX1NV QkNMQVNTX0hFQURTRVRfQURBUFRFUjoKPiArCQkvKiBCQUlPRjsgSU46IE1vbm8gb25seTsgT1VU OiBTdGVyZW8gb25seSwgTW9ubyBhbHQgcG9zc2libGUgKi8KPiArCQlpZiAoY19jaG1hc2sgIT0g MSkKPiArCQkJdXNiX2F1ZGlvX3dhcm4obWl4ZXItPmNoaXAsCj4gKwkJCQkiQkFERCBIRUFEU0VU X0FEQVBURVIgY19jaG1hc2sgbWlzbWF0Y2g6IGV4cGVjdGVkIDEgYWN0dWFsICVkXG4iLAo+ICsJ CQkJY19jaG1hc2spOwo+ICsJCWlmIChwX2NobWFzayAhPSAzKQo+ICsJCQl1c2JfYXVkaW9fd2Fy bihtaXhlci0+Y2hpcCwKPiArCQkJCSJCQUREIEhFQURTRVRfQURBUFRFUiBwX2NobWFzayBtaXNt YXRjaDogZXhwZWN0ZWQgMyBhY3R1YWwgJWRcbiIsCj4gKwkJCQlwX2NobWFzayk7Cj4gKwkJY19j aG1hc2sgPSAxOwo+ICsJCXN0X2NobWFzayA9IDE7Cj4gKwkJcF9jaG1hc2sgPSAzOwo+ICsJCWJy ZWFrOwo+ICsJY2FzZSBVQUMzX0ZVTkNUSU9OX1NVQkNMQVNTX1NQRUFLRVJQSE9ORToKPiArCQkv KiBCQUlGICsgQkFPRjsgSU46IE1vbm8gb25seTsgT1VUOiBNb25vIG9ubHkgKi8KPiArCQlpZiAo Y19jaG1hc2sgIT0gMSkKPiArCQkJdXNiX2F1ZGlvX3dhcm4obWl4ZXItPmNoaXAsCj4gKwkJCQki QkFERCBTUEVBS0VSUEhPTkUgY19jaG1hc2sgbWlzbWF0Y2g6IGV4cGVjdGVkIDEgYWN0dWFsICVk XG4iLAo+ICsJCQkJY19jaG1hc2spOwo+ICsJCWlmIChwX2NobWFzayAhPSAxKQo+ICsJCQl1c2Jf YXVkaW9fd2FybihtaXhlci0+Y2hpcCwKPiArCQkJCSJCQUREIFNQRUFLRVJQSE9ORSBwX2NobWFz ayBtaXNtYXRjaDogZXhwZWN0ZWQgMSBhY3R1YWwgJWRcbiIsCj4gKwkJCQlwX2NobWFzayk7Cj4g KwkJY19jaG1hc2sgPSAxOwo+ICsJCXBfY2htYXNrID0gMTsKPiArCQlicmVhazsKPiArCX0KPiAr Cj4gKwkvKiBQbGF5YmFjayAqLwo+ICsJaWYgKHBfY2htYXNrKSB7Cj4gKwkJLyogTWFzdGVyIGNo YW5uZWwsIGFsd2F5cyB3cml0YWJsZSAqLwo+ICsJCWJ1aWxkX2ZlYXR1cmVfY3RsX2JhZGQobWl4 ZXIsIDAsIFVBQ19GVV9NVVRFLAo+ICsJCQkJICAgICAgIFVBQzNfQkFERF9GVV9JRDIsIG1hcC0+ bWFwKTsKPiArCQkvKiBNb25vL1N0ZXJlbyB2b2x1bWUgY2hhbm5lbHMsIGFsd2F5cyB3cml0YWJs ZSAqLwo+ICsJCWJ1aWxkX2ZlYXR1cmVfY3RsX2JhZGQobWl4ZXIsIHBfY2htYXNrLCBVQUNfRlVf Vk9MVU1FLAo+ICsJCQkJICAgICAgIFVBQzNfQkFERF9GVV9JRDIsIG1hcC0+bWFwKTsKPiArCX0K PiArCj4gKwkvKiBDYXB0dXJlICovCj4gKwlpZiAoY19jaG1hc2spIHsKPiArCQkvKiBNYXN0ZXIg Y2hhbm5lbCwgYWx3YXlzIHdyaXRhYmxlICovCj4gKwkJYnVpbGRfZmVhdHVyZV9jdGxfYmFkZCht aXhlciwgMCwgVUFDX0ZVX01VVEUsCj4gKwkJCQkgICAgICAgVUFDM19CQUREX0ZVX0lENSwgbWFw LT5tYXApOwo+ICsJCS8qIE1vbm8vU3RlcmVvIHZvbHVtZSBjaGFubmVscywgYWx3YXlzIHdyaXRh YmxlICovCj4gKwkJYnVpbGRfZmVhdHVyZV9jdGxfYmFkZChtaXhlciwgY19jaG1hc2ssIFVBQ19G VV9WT0xVTUUsCj4gKwkJCQkgICAgICAgVUFDM19CQUREX0ZVX0lENSwgbWFwLT5tYXApOwo+ICsJ fQo+ICsKPiArCS8qIFNpZGUgdG9uZS1taXhpbmcgKi8KPiArCWlmIChzdF9jaG1hc2spIHsKPiAr CQkvKiBNYXN0ZXIgY2hhbm5lbCwgYWx3YXlzIHdyaXRhYmxlICovCj4gKwkJYnVpbGRfZmVhdHVy ZV9jdGxfYmFkZChtaXhlciwgMCwgVUFDX0ZVX01VVEUsCj4gKwkJCQkgICAgICAgVUFDM19CQURE X0ZVX0lENywgbWFwLT5tYXApOwo+ICsJCS8qIE1vbm8gdm9sdW1lIGNoYW5uZWwsIGFsd2F5cyB3 cml0YWJsZSAqLwo+ICsJCWJ1aWxkX2ZlYXR1cmVfY3RsX2JhZGQobWl4ZXIsIDEsIFVBQ19GVV9W T0xVTUUsCj4gKwkJCQkgICAgICAgVUFDM19CQUREX0ZVX0lENywgbWFwLT5tYXApOwo+ICsJfQo+ ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICsvKgo+ICAgKiBjcmVhdGUgbWl4ZXIgY29udHJv bHMKPiAgICoKPiAgICogd2FsayB0aHJvdWdoIGFsbCBVQUNfT1VUUFVUX1RFUk1JTkFMIGRlc2Ny aXB0b3JzIHRvIHNlYXJjaCBmb3IgCj4gbWl4ZXJzCj4gQEAgLTI4MzgsOSArMzEyNiwxNCBAQCBp bnQgc25kX3VzYl9jcmVhdGVfbWl4ZXIoc3RydWN0IHNuZF91c2JfYXVkaW8KPiAqY2hpcCwgaW50 IGN0cmxpZiwKPiAgCQlicmVhazsKPiAgCX0KPiAKPiAtCWlmICgoZXJyID0gc25kX3VzYl9taXhl cl9jb250cm9scyhtaXhlcikpIDwgMCB8fAo+IC0JICAgIChlcnIgPSBzbmRfdXNiX21peGVyX3N0 YXR1c19jcmVhdGUobWl4ZXIpKSA8IDApCj4gKwlpZiAobWl4ZXItPnByb3RvY29sID09IFVBQ19W RVJTSU9OXzMgJiYKPiArCQkJY2hpcC0+YmFkZF9wcm9maWxlID49IFVBQzNfRlVOQ1RJT05fU1VC Q0xBU1NfR0VORVJJQ19JTykgewo+ICsJCWlmICgoZXJyID0gc25kX3VzYl9taXhlcl9jb250cm9s c19iYWRkKG1peGVyLCBjdHJsaWYpKSA8IDApCj4gKwkJCWdvdG8gX2Vycm9yOwo+ICsJfSBlbHNl IGlmICgoZXJyID0gc25kX3VzYl9taXhlcl9jb250cm9scyhtaXhlcikpIDwgMCB8fAo+ICsJCQko ZXJyID0gc25kX3VzYl9taXhlcl9zdGF0dXNfY3JlYXRlKG1peGVyKSkgPCAwKSB7Cj4gIAkJZ290 byBfZXJyb3I7Cj4gKwl9Cj4gCj4gIAlzbmRfdXNiX21peGVyX2FwcGx5X2NyZWF0ZV9xdWlyayht aXhlcik7Cj4gCj4gZGlmZiAtLWdpdCBhL3NvdW5kL3VzYi9taXhlcl9tYXBzLmMgYi9zb3VuZC91 c2IvbWl4ZXJfbWFwcy5jCj4gaW5kZXggOTAzOGIyZS4uMTNmMDNjOCAxMDA2NDQKPiAtLS0gYS9z b3VuZC91c2IvbWl4ZXJfbWFwcy5jCj4gKysrIGIvc291bmQvdXNiL21peGVyX21hcHMuYwo+IEBA IC00ODIsMyArNDgyLDY4IEBAIHN0cnVjdCB1c2JtaXhfY3RsX21hcCB7Cj4gIAl7IDAgfSAvKiB0 ZXJtaW5hdG9yICovCj4gIH07Cj4gCj4gKy8qCj4gKyAqIENvbnRyb2wgbWFwIGVudHJpZXMgZm9y IFVBQzMgQkFERCBwcm9maWxlcwo+ICsgKi8KPiArCj4gK3N0YXRpYyBzdHJ1Y3QgdXNibWl4X25h bWVfbWFwIHVhYzNfYmFkZF9nZW5lcmljX2lvX21hcFtdID0gewo+ICsJeyBVQUMzX0JBRERfRlVf SUQyLCAiR2VuZXJpYyBPdXQgUGxheWJhY2siIH0sCj4gKwl7IFVBQzNfQkFERF9GVV9JRDUsICJH ZW5lcmljIEluIENhcHR1cmUiIH0sCj4gKwl7IDAgfQkJCQkJLyogdGVybWluYXRvciAqLwo+ICt9 Owo+ICtzdGF0aWMgc3RydWN0IHVzYm1peF9uYW1lX21hcCB1YWMzX2JhZGRfaGVhZHBob25lX21h cFtdID0gewo+ICsJeyBVQUMzX0JBRERfRlVfSUQyLCAiSGVhZHBob25lIFBsYXliYWNrIiB9LAo+ ICsJeyAwIH0JCQkJCS8qIHRlcm1pbmF0b3IgKi8KPiArfTsKPiArc3RhdGljIHN0cnVjdCB1c2Jt aXhfbmFtZV9tYXAgdWFjM19iYWRkX3NwZWFrZXJfbWFwW10gPSB7Cj4gKwl7IFVBQzNfQkFERF9G VV9JRDIsICJTcGVha2VyIFBsYXliYWNrIiB9LAo+ICsJeyAwIH0JCQkJCS8qIHRlcm1pbmF0b3Ig Ki8KPiArfTsKPiArc3RhdGljIHN0cnVjdCB1c2JtaXhfbmFtZV9tYXAgdWFjM19iYWRkX21pY3Jv cGhvbmVfbWFwW10gPSB7Cj4gKwl7IFVBQzNfQkFERF9GVV9JRDUsICJNaWMgQ2FwdHVyZSIgfSwK PiArCXsgMCB9CQkJCQkvKiB0ZXJtaW5hdG9yICovCj4gK307Cj4gKy8qIENvdmVycyBhbHNvICdo ZWFkc2V0IGFkYXB0ZXInIHByb2ZpbGUgKi8KPiArc3RhdGljIHN0cnVjdCB1c2JtaXhfbmFtZV9t YXAgdWFjM19iYWRkX2hlYWRzZXRfbWFwW10gPSB7Cj4gKwl7IFVBQzNfQkFERF9GVV9JRDIsICJI ZWFkc2V0IFBsYXliYWNrIiB9LAo+ICsJeyBVQUMzX0JBRERfRlVfSUQ1LCAiSGVhZHNldCBDYXB0 dXJlIiB9LAo+ICsJeyBVQUMzX0JBRERfRlVfSUQ3LCAiU2lkZSBUb25lIE1peGluZyIgfSwKPiAr CXsgMCB9CQkJCQkvKiB0ZXJtaW5hdG9yICovCj4gK307Cj4gK3N0YXRpYyBzdHJ1Y3QgdXNibWl4 X25hbWVfbWFwIHVhYzNfYmFkZF9zcGVha2VycGhvbmVfbWFwW10gPSB7Cj4gKwl7IFVBQzNfQkFE RF9GVV9JRDIsICJTcGVha2VyIFBsYXliYWNrIiB9LAo+ICsJeyBVQUMzX0JBRERfRlVfSUQ1LCAi TWljIENhcHR1cmUiIH0sCj4gKwl7IDAgfQkJCQkJLyogdGVybWluYXRvciAqLwo+ICt9Owo+ICsK PiArc3RhdGljIHN0cnVjdCB1c2JtaXhfY3RsX21hcCB1YWMzX2JhZGRfdXNibWl4X2N0bF9tYXBz W10gPSB7Cj4gKwl7Cj4gKwkJLmlkID0gVUFDM19GVU5DVElPTl9TVUJDTEFTU19HRU5FUklDX0lP LAo+ICsJCS5tYXAgPSB1YWMzX2JhZGRfZ2VuZXJpY19pb19tYXAsCj4gKwl9LAo+ICsJewo+ICsJ CS5pZCA9IFVBQzNfRlVOQ1RJT05fU1VCQ0xBU1NfSEVBRFBIT05FLAo+ICsJCS5tYXAgPSB1YWMz X2JhZGRfaGVhZHBob25lX21hcCwKPiArCX0sCj4gKwl7Cj4gKwkJLmlkID0gVUFDM19GVU5DVElP Tl9TVUJDTEFTU19TUEVBS0VSLAo+ICsJCS5tYXAgPSB1YWMzX2JhZGRfc3BlYWtlcl9tYXAsCj4g Kwl9LAo+ICsJewo+ICsJCS5pZCA9IFVBQzNfRlVOQ1RJT05fU1VCQ0xBU1NfTUlDUk9QSE9ORSwK PiArCQkubWFwID0gdWFjM19iYWRkX21pY3JvcGhvbmVfbWFwLAo+ICsJfSwKPiArCXsKPiArCQku aWQgPSBVQUMzX0ZVTkNUSU9OX1NVQkNMQVNTX0hFQURTRVQsCj4gKwkJLm1hcCA9IHVhYzNfYmFk ZF9oZWFkc2V0X21hcCwKPiArCX0sCj4gKwl7Cj4gKwkJLmlkID0gVUFDM19GVU5DVElPTl9TVUJD TEFTU19IRUFEU0VUX0FEQVBURVIsCj4gKwkJLm1hcCA9IHVhYzNfYmFkZF9oZWFkc2V0X21hcCwK PiArCX0sCj4gKwl7Cj4gKwkJLmlkID0gVUFDM19GVU5DVElPTl9TVUJDTEFTU19TUEVBS0VSUEhP TkUsCj4gKwkJLm1hcCA9IHVhYzNfYmFkZF9zcGVha2VycGhvbmVfbWFwLAo+ICsJfSwKPiArCXsg MCB9IC8qIHRlcm1pbmF0b3IgKi8KPiArfTsKPiBkaWZmIC0tZ2l0IGEvc291bmQvdXNiL3N0cmVh bS5jIGIvc291bmQvdXNiL3N0cmVhbS5jCj4gaW5kZXggNTg2ZDY2NC4uZWE1YTEzZTAgMTAwNjQ0 Cj4gLS0tIGEvc291bmQvdXNiL3N0cmVhbS5jCj4gKysrIGIvc291bmQvdXNiL3N0cmVhbS5jCj4g QEAgLTc5OCwxNSArNzk4LDY3IEBAIHN0YXRpYyBpbnQgcGFyc2VfdWFjX2VuZHBvaW50X2F0dHJp YnV0ZXMoc3RydWN0Cj4gc25kX3VzYl9hdWRpbyAqY2hpcCwKPiAgCXN0cnVjdCB1YWMzX2lucHV0 X3Rlcm1pbmFsX2Rlc2NyaXB0b3IgKmlucHV0X3Rlcm07Cj4gIAlzdHJ1Y3QgdWFjM19vdXRwdXRf dGVybWluYWxfZGVzY3JpcHRvciAqb3V0cHV0X3Rlcm07Cj4gIAlzdHJ1Y3QgdWFjM19jbHVzdGVy X2hlYWRlcl9kZXNjcmlwdG9yICpjbHVzdGVyOwo+IC0Jc3RydWN0IHVhYzNfYXNfaGVhZGVyX2Rl c2NyaXB0b3IgKmFzOwo+ICsJc3RydWN0IHVhYzNfYXNfaGVhZGVyX2Rlc2NyaXB0b3IgKmFzID0g TlVMTDsKPiAgCXN0cnVjdCB1YWMzX2hjX2Rlc2NyaXB0b3JfaGVhZGVyIGhjX2hlYWRlcjsKPiAg CXN0cnVjdCBzbmRfcGNtX2NobWFwX2VsZW0gKmNobWFwOwo+ICsJdW5zaWduZWQgY2hhciBiYWRk X3Byb2ZpbGU7Cj4gKwl1NjQgYmFkZF9mb3JtYXRzICA9IDA7Cj4gIAl1bnNpZ25lZCBpbnQgbnVt X2NoYW5uZWxzOwo+ICAJc3RydWN0IGF1ZGlvZm9ybWF0ICpmcDsKPiAgCXUxNiBjbHVzdGVyX2lk LCB3TGVuZ3RoOwo+ICAJaW50IGNsb2NrID0gMDsKPiAgCWludCBlcnI7Cj4gCj4gKwliYWRkX3By b2ZpbGUgPSBjaGlwLT5iYWRkX3Byb2ZpbGU7Cj4gKwo+ICsJaWYgKGJhZGRfcHJvZmlsZSA+PSBV QUMzX0ZVTkNUSU9OX1NVQkNMQVNTX0dFTkVSSUNfSU8pIHsKPiArCQl1bnNpZ25lZCBpbnQgbWF4 cGFja3NpemUgPQo+ICsJCQlsZTE2X3RvX2NwdShnZXRfZW5kcG9pbnQoYWx0cywgMCktPndNYXhQ YWNrZXRTaXplKTsKPiArCj4gKwkJc3dpdGNoIChtYXhwYWNrc2l6ZSkgewo+ICsJCWRlZmF1bHQ6 Cj4gKwkJCWRldl9lcnIoJmRldi0+ZGV2LAo+ICsJCQkJIiV1OiVkIDogaW5jb3JyZWN0IHdNYXhQ YWNrZXRTaXplIGZvciBCQUREIHByb2ZpbGVcbiIsCj4gKwkJCQlpZmFjZV9ubywgYWx0bm8pOwo+ ICsJCQlyZXR1cm4gTlVMTDsKPiArCQljYXNlIFVBQzNfQkFERF9FUF9NQVhQU0laRV9TWU5DX01P Tk9fMTY6Cj4gKwkJY2FzZSBVQUMzX0JBRERfRVBfTUFYUFNJWkVfQVNZTkNfTU9OT18xNjoKPiAr CQkJYmFkZF9mb3JtYXRzID0gU05EUlZfUENNX0ZNVEJJVF9TMTZfTEU7Cj4gKwkJCW51bV9jaGFu bmVscyA9IDE7Cj4gKwkJCWJyZWFrOwo+ICsJCWNhc2UgVUFDM19CQUREX0VQX01BWFBTSVpFX1NZ TkNfTU9OT18yNDoKPiArCQljYXNlIFVBQzNfQkFERF9FUF9NQVhQU0laRV9BU1lOQ19NT05PXzI0 Ogo+ICsJCQliYWRkX2Zvcm1hdHMgPSBTTkRSVl9QQ01fRk1UQklUX1MyNF8zTEU7Cj4gKwkJCW51 bV9jaGFubmVscyA9IDE7Cj4gKwkJCWJyZWFrOwo+ICsJCWNhc2UgVUFDM19CQUREX0VQX01BWFBT SVpFX1NZTkNfU1RFUkVPXzE2Ogo+ICsJCWNhc2UgVUFDM19CQUREX0VQX01BWFBTSVpFX0FTWU5D X1NURVJFT18xNjoKPiArCQkJYmFkZF9mb3JtYXRzID0gU05EUlZfUENNX0ZNVEJJVF9TMTZfTEU7 Cj4gKwkJCW51bV9jaGFubmVscyA9IDI7Cj4gKwkJCWJyZWFrOwo+ICsJCWNhc2UgVUFDM19CQURE X0VQX01BWFBTSVpFX1NZTkNfU1RFUkVPXzI0Ogo+ICsJCWNhc2UgVUFDM19CQUREX0VQX01BWFBT SVpFX0FTWU5DX1NURVJFT18yNDoKPiArCQkJYmFkZF9mb3JtYXRzID0gU05EUlZfUENNX0ZNVEJJ VF9TMjRfM0xFOwo+ICsJCQludW1fY2hhbm5lbHMgPSAyOwo+ICsJCQlicmVhazsKPiArCQl9Cj4g Kwo+ICsJCWNobWFwID0ga3phbGxvYyhzaXplb2YoKmNobWFwKSwgR0ZQX0tFUk5FTCk7Cj4gKwkJ aWYgKCFjaG1hcCkKPiArCQkJcmV0dXJuIEVSUl9QVFIoLUVOT01FTSk7Cj4gKwo+ICsJCWlmIChu dW1fY2hhbm5lbHMgPT0gMSkgewo+ICsJCQljaG1hcC0+bWFwWzBdID0gU05EUlZfQ0hNQVBfTU9O TzsKPiArCQl9IGVsc2Ugewo+ICsJCQljaG1hcC0+bWFwWzBdID0gU05EUlZfQ0hNQVBfRkw7Cj4g KwkJCWNobWFwLT5tYXBbMV0gPSBTTkRSVl9DSE1BUF9GUjsKPiArCQl9Cj4gKwo+ICsJCWNobWFw LT5jaGFubmVscyA9IG51bV9jaGFubmVsczsKPiArCQljbG9jayA9IFVBQzNfQkFERF9DU19JRDk7 Cj4gKwkJZ290byBmb3VuZF9jbG9jazsKPiArCX0KPiArCj4gIAlhcyA9IHNuZF91c2JfZmluZF9j c2ludF9kZXNjKGFsdHMtPmV4dHJhLCBhbHRzLT5leHRyYWxlbiwKPiAgCQkJCSAgICAgTlVMTCwg VUFDX0FTX0dFTkVSQUwpOwo+ICAJaWYgKCFhcykgewo+IEBAIC05MjIsMTggKzk3NCwzMSBAQCBz dGF0aWMgaW50IHBhcnNlX3VhY19lbmRwb2ludF9hdHRyaWJ1dGVzKHN0cnVjdAo+IHNuZF91c2Jf YXVkaW8gKmNoaXAsCj4gIAlpZiAoc25kX3VzYl9nZXRfc3BlZWQoZGV2KSA9PSBVU0JfU1BFRURf SElHSCkKPiAgCQlmcC0+bWF4cGFja3NpemUgPSAoKChmcC0+bWF4cGFja3NpemUgPj4gMTEpICYg MykgKyAxKQo+ICAJCQkJKiAoZnAtPm1heHBhY2tzaXplICYgMHg3ZmYpOwo+IC0JZnAtPmF0dHJp YnV0ZXMgPSBwYXJzZV91YWNfZW5kcG9pbnRfYXR0cmlidXRlcyhjaGlwLCBhbHRzLAo+IC0JCQkJ CQkgICAgICAgVUFDX1ZFUlNJT05fMywKPiAtCQkJCQkJICAgICAgIGlmYWNlX25vKTsKPiAgCWZw LT5jbG9jayA9IGNsb2NrOwo+ICAJZnAtPmNobWFwID0gY2htYXA7Cj4gIAlJTklUX0xJU1RfSEVB RCgmZnAtPmxpc3QpOwo+IAo+IC0JLyogb2ssIGxldCdzIHBhcnNlIGZ1cnRoZXIuLi4gKi8KPiAt CWlmIChzbmRfdXNiX3BhcnNlX2F1ZGlvX2Zvcm1hdF92MyhjaGlwLCBmcCwgYXMsIHN0cmVhbSkg PCAwKSB7Cj4gLQkJa2ZyZWUoZnAtPnJhdGVfdGFibGUpOwo+IC0JCWtmcmVlKGZwKTsKPiAtCQly ZXR1cm4gTlVMTDsKPiArCWlmIChiYWRkX3Byb2ZpbGUgPj0gVUFDM19GVU5DVElPTl9TVUJDTEFT U19HRU5FUklDX0lPKSB7Cj4gKwkJZnAtPmF0dHJpYnV0ZXMgPSAwOyAvKiBObyBhdHRyaWJ1dGVz ICovCj4gKwo+ICsJCWZwLT5mbXRfdHlwZSA9IFVBQ19GT1JNQVRfVFlQRV9JOwo+ICsJCWZwLT5m b3JtYXRzID0gYmFkZF9mb3JtYXRzOwo+ICsKPiArCQlmcC0+bnJfcmF0ZXMgPSAwOwkvKiBTTkRS Vl9QQ01fUkFURV9DT05USU5VT1VTICovCj4gKwkJZnAtPnJhdGVfbWluID0gVUFDM19CQUREX1NB TVBMSU5HX1JBVEU7Cj4gKwkJZnAtPnJhdGVfbWF4ID0gVUFDM19CQUREX1NBTVBMSU5HX1JBVEU7 Cj4gKwkJZnAtPnJhdGVzID0gU05EUlZfUENNX1JBVEVfQ09OVElOVU9VUzsKPiArCj4gKwl9IGVs c2Ugewo+ICsJCWZwLT5hdHRyaWJ1dGVzID0gcGFyc2VfdWFjX2VuZHBvaW50X2F0dHJpYnV0ZXMo Y2hpcCwgYWx0cywKPiArCQkJCQkJCSAgICAgICBVQUNfVkVSU0lPTl8zLAo+ICsJCQkJCQkJICAg ICAgIGlmYWNlX25vKTsKPiArCQkvKiBvaywgbGV0J3MgcGFyc2UgZnVydGhlci4uLiAqLwo+ICsJ CWlmIChzbmRfdXNiX3BhcnNlX2F1ZGlvX2Zvcm1hdF92MyhjaGlwLCBmcCwgYXMsIHN0cmVhbSkg PCAwKSB7Cj4gKwkJCWtmcmVlKGZwLT5yYXRlX3RhYmxlKTsKPiArCQkJa2ZyZWUoZnApOwo+ICsJ CQlyZXR1cm4gTlVMTDsKPiArCQl9Cj4gIAl9Cj4gCj4gIAlyZXR1cm4gZnA7Cj4gZGlmZiAtLWdp dCBhL3NvdW5kL3VzYi91c2JhdWRpby5oIGIvc291bmQvdXNiL3VzYmF1ZGlvLmgKPiBpbmRleCA0 ZDVjODlhLi4xYmI1ZTJjIDEwMDY0NAo+IC0tLSBhL3NvdW5kL3VzYi91c2JhdWRpby5oCj4gKysr IGIvc291bmQvdXNiL3VzYmF1ZGlvLmgKPiBAQCAtNDksNiArNDksOCBAQCBzdHJ1Y3Qgc25kX3Vz Yl9hdWRpbyB7Cj4gIAlpbnQgbnVtX3N1c3BlbmRlZF9pbnRmOwo+ICAJaW50IHNhbXBsZV9yYXRl X3JlYWRfZXJyb3I7Cj4gCj4gKwlpbnQgYmFkZF9wcm9maWxlOwkJLyogVUFDMyBCQUREIHByb2Zp bGUgKi8KPiArCj4gIAlzdHJ1Y3QgbGlzdF9oZWFkIHBjbV9saXN0OwkvKiBsaXN0IG9mIHBjbSBz dHJlYW1zICovCj4gIAlzdHJ1Y3QgbGlzdF9oZWFkIGVwX2xpc3Q7CS8qIGxpc3Qgb2YgYXVkaW8t cmVsYXRlZCBlbmRwb2ludHMgKi8KPiAgCWludCBwY21fZGV2czsKX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX18KQWxzYS1kZXZlbCBtYWlsaW5nIGxpc3QKQWxz YS1kZXZlbEBhbHNhLXByb2plY3Qub3JnCmh0dHA6Ly9tYWlsbWFuLmFsc2EtcHJvamVjdC5vcmcv bWFpbG1hbi9saXN0aW5mby9hbHNhLWRldmVsCg==