From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 17CB3C433DB for ; Wed, 24 Mar 2021 10:04:59 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CE12661A02 for ; Wed, 24 Mar 2021 10:04:57 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CE12661A02 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 3F7971669; Wed, 24 Mar 2021 11:04:06 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 3F7971669 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1616580296; bh=iU8ENTHiuHkHXDhjTQziiqYURwIrxKiz+I45m49o5tk=; h=Date:From:To:Subject:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=sGtV2c4gzh0YF7MVNNWE5a1oXF5OFurAu+z4g/E/Ps6z8FAvE1I9FXub6aSyw+1Nq k3IYmp9wR0gTpYckQYQqc95YDhPCK7aI/ZscniZ8hG1QaPdfX55STv8LmNPr4t/vjj Xy+y65vTcvh6g/EwnVsFzGBMfSW7AiygwSAiS2eo= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id A50D5F80156; Wed, 24 Mar 2021 11:04:05 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 1AC1EF8016B; Wed, 24 Mar 2021 11:04:04 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 021DAF8012B for ; Wed, 24 Mar 2021 11:03:55 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 021DAF8012B X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 3A7E2AB9B; Wed, 24 Mar 2021 10:03:55 +0000 (UTC) Date: Wed, 24 Mar 2021 11:03:55 +0100 Message-ID: From: Takashi Iwai To: David Henningsson Subject: Re: [PATCH v2] sound: rawmidi: Add framing mode In-Reply-To: <20210324054253.34642-1-coding@diwic.se> References: <20210324054253.34642-1-coding@diwic.se> User-Agent: Wanderlust/2.15.9 (Almost Unreal) SEMI/1.14.6 (Maruoka) FLIM/1.14.9 (=?UTF-8?B?R29qxY0=?=) APEL/10.8 Emacs/25.3 (x86_64-suse-linux-gnu) MULE/6.0 (HANACHIRUSATO) MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset=US-ASCII Cc: alsa-devel@alsa-project.org X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" On Wed, 24 Mar 2021 06:42:53 +0100, David Henningsson wrote: > > This commit adds a new framing mode that frames all MIDI data into > 16-byte frames with a timestamp from the monotonic_raw clock. > > The main benefit is that we can get accurate timestamps even if > userspace wakeup and processing is not immediate. > > Signed-off-by: David Henningsson Thanks for the patch! I seem to have overlooked your previous post, sorry. This looks like a good middle ground solution, while we still need to address the sequencer timestamp (basically we should be able to send an event with the timestamp prepared from the rawmidi side). The implementation itself looks good to me. But this needs to bump the SNDRV_RAWMIDI_VERSION for indicating the new API. Takashi > --- > > v2: Fixed checkpatch errors. > > include/sound/rawmidi.h | 1 + > include/uapi/sound/asound.h | 18 ++++++++++++++- > sound/core/rawmidi.c | 45 ++++++++++++++++++++++++++++++++++++- > 3 files changed, 62 insertions(+), 2 deletions(-) > > diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h > index 334842daa904..4ba5d2deec18 100644 > --- a/include/sound/rawmidi.h > +++ b/include/sound/rawmidi.h > @@ -81,6 +81,7 @@ struct snd_rawmidi_substream { > bool opened; /* open flag */ > bool append; /* append flag (merge more streams) */ > bool active_sensing; /* send active sensing when close */ > + u8 framing; /* whether to frame data (for input) */ > int use_count; /* use counter (for output) */ > size_t bytes; > struct snd_rawmidi *rmidi; > diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h > index 535a7229e1d9..f33076755025 100644 > --- a/include/uapi/sound/asound.h > +++ b/include/uapi/sound/asound.h > @@ -736,12 +736,28 @@ struct snd_rawmidi_info { > unsigned char reserved[64]; /* reserved for future use */ > }; > > +enum { > + SNDRV_RAWMIDI_FRAMING_NONE = 0, > + SNDRV_RAWMIDI_FRAMING_TSTAMP_MONOTONIC_RAW, > + SNDRV_RAWMIDI_FRAMING_LAST = SNDRV_RAWMIDI_FRAMING_TSTAMP_MONOTONIC_RAW, > +}; > + > +#define SND_RAWMIDI_FRAMING_DATA_LENGTH 7 > + > +struct snd_rawmidi_framing_tstamp { > + unsigned int tv_sec; /* seconds */ > + unsigned int tv_nsec; /* nanoseconds */ > + unsigned char length; > + unsigned char data[SND_RAWMIDI_FRAMING_DATA_LENGTH]; > +}; > + > struct snd_rawmidi_params { > int stream; > size_t buffer_size; /* queue size in bytes */ > size_t avail_min; /* minimum avail bytes for wakeup */ > unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */ > - unsigned char reserved[16]; /* reserved for future use */ > + unsigned char framing; /* For input data only, frame incoming data */ > + unsigned char reserved[15]; /* reserved for future use */ > }; > > #ifndef __KERNEL__ > diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c > index aca00af93afe..cd927ba178a6 100644 > --- a/sound/core/rawmidi.c > +++ b/sound/core/rawmidi.c > @@ -721,6 +721,7 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, > struct snd_rawmidi_params *params) > { > snd_rawmidi_drain_input(substream); > + substream->framing = params->framing; > return resize_runtime_buffer(substream->runtime, params, true); > } > EXPORT_SYMBOL(snd_rawmidi_input_params); > @@ -963,6 +964,44 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card, > return -ENOIOCTLCMD; > } > > +static int receive_with_tstamp_framing(struct snd_rawmidi_substream *substream, > + const unsigned char *buffer, int src_count, struct timespec64 *tstamp) > +{ > + struct snd_rawmidi_runtime *runtime = substream->runtime; > + struct snd_rawmidi_framing_tstamp frame; > + struct snd_rawmidi_framing_tstamp *dest_ptr; > + int dest_frames = 0; > + int frame_size = sizeof(struct snd_rawmidi_framing_tstamp); > + > + frame.tv_sec = tstamp->tv_sec; > + frame.tv_nsec = tstamp->tv_nsec; > + if (snd_BUG_ON(runtime->hw_ptr & 15 || runtime->buffer_size & 15 || frame_size != 16)) > + return -EINVAL; > + > + while (src_count > 0) { > + if ((int)(runtime->buffer_size - runtime->avail) < frame_size) { > + runtime->xruns += src_count; > + return dest_frames * frame_size; > + } > + if (src_count >= SND_RAWMIDI_FRAMING_DATA_LENGTH) > + frame.length = SND_RAWMIDI_FRAMING_DATA_LENGTH; > + else { > + frame.length = src_count; > + memset(frame.data, 0, SND_RAWMIDI_FRAMING_DATA_LENGTH); > + } > + memcpy(frame.data, buffer, frame.length); > + buffer += frame.length; > + src_count -= frame.length; > + dest_ptr = (struct snd_rawmidi_framing_tstamp *) (runtime->buffer + runtime->hw_ptr); > + *dest_ptr = frame; > + runtime->avail += frame_size; > + runtime->hw_ptr += frame_size; > + runtime->hw_ptr %= runtime->buffer_size; > + dest_frames++; > + } > + return dest_frames * frame_size; > +} > + > /** > * snd_rawmidi_receive - receive the input data from the device > * @substream: the rawmidi substream > @@ -977,6 +1016,7 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream, > const unsigned char *buffer, int count) > { > unsigned long flags; > + struct timespec64 ts64; > int result = 0, count1; > struct snd_rawmidi_runtime *runtime = substream->runtime; > > @@ -988,7 +1028,10 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream, > return -EINVAL; > } > spin_lock_irqsave(&runtime->lock, flags); > - if (count == 1) { /* special case, faster code */ > + if (substream->framing == SNDRV_RAWMIDI_FRAMING_TSTAMP_MONOTONIC_RAW) { > + ktime_get_raw_ts64(&ts64); > + result = receive_with_tstamp_framing(substream, buffer, count, &ts64); > + } else if (count == 1) { /* special case, faster code */ > substream->bytes++; > if (runtime->avail < runtime->buffer_size) { > runtime->buffer[runtime->hw_ptr++] = buffer[0]; > -- > 2.25.1 >