From patchwork Mon Aug 16 16:06:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Henningsson X-Patchwork-Id: 12438801 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=-16.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,USER_AGENT_GIT 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 25ED4C4338F for ; Mon, 16 Aug 2021 16:08:54 +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 757E36056B for ; Mon, 16 Aug 2021 16:08:53 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 757E36056B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=diwic.se Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=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 DC5EE16B1; Mon, 16 Aug 2021 18:08:01 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz DC5EE16B1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1629130131; bh=Fx9FxJkSwNJS02kMs/A55CJl0xmX3UhqCJ4smScrKMs=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=sigMviA+C0LG+x4iNiyTxJi71grO5jYUY//OhUCn5KSdK/9s8TgPPscUnwz6uf9rB cF7cspuqsTWGQMGvgOEa22/jJkqIe3GLN3T5D5VM2L234uM94uXmIsLQa14Lm800B4 7F81E+O9gyHrsCLEneD2SX53XbZ1FOuUouviMWhI= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 737DCF804AC; Mon, 16 Aug 2021 18:07:11 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id F13E6F80246; Mon, 16 Aug 2021 18:07:09 +0200 (CEST) Received: from ns4.inleed.net (mailout4.inleed.net [IPv6:2a0b:dc80:cafe:104::1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id C7A6CF80246 for ; Mon, 16 Aug 2021 18:06:56 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz C7A6CF80246 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=diwic.se header.i=@diwic.se header.b="faTDXngY" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=diwic.se; s=x; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=ocw0dVp1ih8qx/IWobWqif/VNhclnsaC6xKq2xTchm4=; b=faTDXngYUNZie2puHgal0hF08k jpO3OVsTWVzSyBBOLhfmxhzqiURPmfLxoR1+PZVxR3D/5t0APq1uKe7P/QIXADK3IsTQ79mBbuS0P UxmZe0iqKBqNszTUnqPdicufOtwAxOcjVnKEOHLV+s84fl5nsWgvelHM8dvBsdv1NJAQUDCTPmc7Y mZoLg3iyZ9a0WluBjUTknNcA+rgN7Mong15y9cb5fuHgxcU8gPhHbM0yZxRJdbGexy1Gja4gjRZFs eRb0yn06ATTCuQwgiEIB9emYzucqElAif1fSCicElh4AqXr2PInjfvdWEm0CvzB3Xv11bdRr+Ohqm MOqlEMNw==; Received: from c83-254-143-147.bredband.tele2.se ([83.254.143.147] helo=localhost.localdomain) by ns4.inleed.net with esmtpsa (TLS1.2) tls TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1mFf8Y-0044Nq-05; Mon, 16 Aug 2021 18:06:54 +0200 From: David Henningsson To: tiwai@suse.de, perex@perex.cz, alsa-devel@alsa-project.org Subject: [PATCH 1/2] Add rawmidi framing API Date: Mon, 16 Aug 2021 18:06:24 +0200 Message-Id: <20210816160625.17796-2-coding@diwic.se> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210816160625.17796-1-coding@diwic.se> References: <20210816160625.17796-1-coding@diwic.se> MIME-Version: 1.0 X-Authenticated-Id: coding@diwic.se Cc: David Henningsson 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" Signed-off-by: David Henningsson --- include/rawmidi.h | 26 ++++++++++++ include/sound/uapi/asound.h | 30 +++++++++++++- src/rawmidi/rawmidi.c | 83 +++++++++++++++++++++++++++++++++++++ src/rawmidi/rawmidi_hw.c | 2 + src/rawmidi/rawmidi_local.h | 2 + 5 files changed, 141 insertions(+), 2 deletions(-) diff --git a/include/rawmidi.h b/include/rawmidi.h index d88c932c..2f27cb78 100644 --- a/include/rawmidi.h +++ b/include/rawmidi.h @@ -79,6 +79,27 @@ typedef enum _snd_rawmidi_type { SND_RAWMIDI_TYPE_VIRTUAL } snd_rawmidi_type_t; +#define SND_RAWMIDI_CLOCK_NONE (0<<3) +#define SND_RAWMIDI_CLOCK_REALTIME (1<<3) +#define SND_RAWMIDI_CLOCK_MONOTONIC (2<<3) +#define SND_RAWMIDI_CLOCK_MONOTONIC_RAW (3<<3) + +#define SND_RAWMIDI_FRAMING_DATA_LENGTH 16 + +/** Incoming RawMidi bytes is put inside this container if tstamp type framing is enabled. */ +typedef struct _snd_rawmidi_framing_tstamp { + /** + * For now, frame_type is always 0. Midi 2.0 is expected to add new + * types here. Applications are expected to skip unknown frame types. + */ + __u8 frame_type; + __u8 length; /* number of valid bytes in data field */ + __u8 reserved[2]; + __u32 tv_nsec; /* nanoseconds */ + __u64 tv_sec; /* seconds */ + __u8 data[SND_RAWMIDI_FRAMING_DATA_LENGTH]; +} snd_rawmidi_framing_tstamp_t; + int snd_rawmidi_open(snd_rawmidi_t **in_rmidi, snd_rawmidi_t **out_rmidi, const char *name, int mode); int snd_rawmidi_open_lconf(snd_rawmidi_t **in_rmidi, snd_rawmidi_t **out_rmidi, @@ -126,6 +147,11 @@ int snd_rawmidi_params_set_avail_min(snd_rawmidi_t *rmidi, snd_rawmidi_params_t size_t snd_rawmidi_params_get_avail_min(const snd_rawmidi_params_t *params); int snd_rawmidi_params_set_no_active_sensing(snd_rawmidi_t *rmidi, snd_rawmidi_params_t *params, int val); int snd_rawmidi_params_get_no_active_sensing(const snd_rawmidi_params_t *params); +int snd_rawmidi_params_set_framing_type(const snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, unsigned int val); +int snd_rawmidi_params_get_framing_type(const snd_rawmidi_params_t *params); +int snd_rawmidi_params_set_clock_type(const snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, unsigned int val); +int snd_rawmidi_params_get_clock_type(const snd_rawmidi_params_t *params); + int snd_rawmidi_params(snd_rawmidi_t *rmidi, snd_rawmidi_params_t * params); int snd_rawmidi_params_current(snd_rawmidi_t *rmidi, snd_rawmidi_params_t *params); size_t snd_rawmidi_status_sizeof(void); diff --git a/include/sound/uapi/asound.h b/include/sound/uapi/asound.h index ec610c27..9fe3943f 100644 --- a/include/sound/uapi/asound.h +++ b/include/sound/uapi/asound.h @@ -702,7 +702,7 @@ enum { * Raw MIDI section - /dev/snd/midi?? */ -#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 1) +#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 2) enum { SNDRV_RAWMIDI_STREAM_OUTPUT = 0, @@ -728,12 +728,38 @@ struct snd_rawmidi_info { unsigned char reserved[64]; /* reserved for future use */ }; +#define SNDRV_RAWMIDI_MODE_FRAMING_MASK (7<<0) +#define SNDRV_RAWMIDI_MODE_FRAMING_SHIFT 0 +#define SNDRV_RAWMIDI_MODE_FRAMING_NONE (0<<0) +#define SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP (1<<0) +#define SNDRV_RAWMIDI_MODE_CLOCK_MASK (7<<3) +#define SNDRV_RAWMIDI_MODE_CLOCK_SHIFT 3 +#define SNDRV_RAWMIDI_MODE_CLOCK_NONE (0<<3) +#define SNDRV_RAWMIDI_MODE_CLOCK_REALTIME (1<<3) +#define SNDRV_RAWMIDI_MODE_CLOCK_MONOTONIC (2<<3) +#define SNDRV_RAWMIDI_MODE_CLOCK_MONOTONIC_RAW (3<<3) + +#define SNDRV_RAWMIDI_FRAMING_DATA_LENGTH 16 + +struct snd_rawmidi_framing_tstamp { + /* For now, frame_type is always 0. Midi 2.0 is expected to add new + * types here. Applications are expected to skip unknown frame types. + */ + __u8 frame_type; + __u8 length; /* number of valid bytes in data field */ + __u8 reserved[2]; + __u32 tv_nsec; /* nanoseconds */ + __u64 tv_sec; /* seconds */ + __u8 data[SNDRV_RAWMIDI_FRAMING_DATA_LENGTH]; +} __packed; + 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 int mode; /* For input data only, frame incoming data */ + unsigned char reserved[12]; /* reserved for future use */ }; struct snd_rawmidi_status { diff --git a/src/rawmidi/rawmidi.c b/src/rawmidi/rawmidi.c index 55f44821..8ca7a8ac 100644 --- a/src/rawmidi/rawmidi.c +++ b/src/rawmidi/rawmidi.c @@ -118,6 +118,15 @@ hw:soundwave,1,2 hw:DEV=1,CARD=soundwave,SUBDEV=2 \endcode +\section rawmidi_framing Framing of rawmidi data + +Optionally, incoming rawmidi bytes can be put inside a frame of type snd_rawmidi_framing_tstamp_t. +The main current benefit is that can enable in-kernel timestamping of incoming bytes, and that +timestamp is likely to be more precise than what userspace can offer. + +Tstamp type framing requires a kernel >= 5.14 and a buffer size that is a multiple of +sizeof(snd_rawmidi_framing_tstamp_t). It is only available on input streams. + \section rawmidi_examples Examples The full featured examples with cross-links: @@ -154,6 +163,7 @@ static int snd_rawmidi_params_default(snd_rawmidi_t *rawmidi, snd_rawmidi_params params->buffer_size = page_size(); params->avail_min = 1; params->no_active_sensing = 1; + params->mode = 0; return 0; } @@ -811,6 +821,77 @@ int snd_rawmidi_params_get_no_active_sensing(const snd_rawmidi_params_t *params) return params->no_active_sensing; } +/** + * \brief enable or disable rawmidi framing + * \param rawmidi RawMidi handle + * \param params pointer to snd_rawmidi_params_t structure + * \param val (0 = no framing, 1 = tstamp type framing) + * \return 0 on success, otherwise a negative error code. + * + * Notable error codes: + * -EINVAL - "val" is invalid + * -ENOTSUP - Kernel is too old to support framing. + * + */ +int snd_rawmidi_params_set_framing_type(const snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, unsigned int val) +{ + assert(rawmidi && params); + if (val > SNDRV_RAWMIDI_MODE_FRAMING_MASK >> SNDRV_RAWMIDI_MODE_FRAMING_SHIFT) + return -EINVAL; + if (val != SNDRV_RAWMIDI_MODE_FRAMING_NONE && + (rawmidi->version < SNDRV_PROTOCOL_VERSION(2, 0, 2) || rawmidi->stream != SND_RAWMIDI_STREAM_INPUT)) + return -ENOTSUP; + params->mode = (params->mode & ~SNDRV_RAWMIDI_MODE_FRAMING_MASK) + (val << SNDRV_RAWMIDI_MODE_FRAMING_SHIFT); + return 0; +} + +/** + * \brief get current framing type + * \param params pointer to snd_rawmidi_params_t structure + * \return the current type (0 = no framing, 1 = tstamp type framing) + */ +int snd_rawmidi_params_get_framing_type(const snd_rawmidi_params_t *params) +{ + assert(params); + return (params->mode & SNDRV_RAWMIDI_MODE_FRAMING_MASK) >> SNDRV_RAWMIDI_MODE_FRAMING_SHIFT; +} + +/** + * \brief sets clock type for tstamp type framing + * \param rawmidi RawMidi handle + * \param params pointer to snd_rawmidi_params_t structure + * \param val one of the SND_RAWMIDI_CLOCK_* constants + * \return 0 on success, otherwise a negative error code. + * + * Notable error codes: + * -EINVAL - "val" is invalid + * -ENOTSUP - Kernel is too old to support framing. + * + */ +int snd_rawmidi_params_set_clock_type(const snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, unsigned int val) +{ + assert(rawmidi && params); + if (val > SNDRV_RAWMIDI_MODE_CLOCK_MASK >> SNDRV_RAWMIDI_MODE_CLOCK_SHIFT) + return -EINVAL; + if (val != SNDRV_RAWMIDI_MODE_CLOCK_NONE && + (rawmidi->version < SNDRV_PROTOCOL_VERSION(2, 0, 2) || rawmidi->stream != SND_RAWMIDI_STREAM_INPUT)) + return -ENOTSUP; + params->mode = (params->mode & ~SNDRV_RAWMIDI_MODE_CLOCK_MASK) + (val << SNDRV_RAWMIDI_MODE_CLOCK_SHIFT); + return 0; +} + +/** + * \brief get current clock type (for tstamp type framing) + * \param params pointer to snd_rawmidi_params_t structure + * \return the current clock type (one of the SND_RAWMIDI_CLOCK_* constants) + */ +int snd_rawmidi_params_get_clock_type(const snd_rawmidi_params_t *params) +{ + assert(params); + return (params->mode & SNDRV_RAWMIDI_MODE_CLOCK_MASK) >> SNDRV_RAWMIDI_MODE_CLOCK_SHIFT; +} + + /** * \brief set parameters about rawmidi stream * \param rawmidi RawMidi handle @@ -828,6 +909,7 @@ int snd_rawmidi_params(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t * params) rawmidi->buffer_size = params->buffer_size; rawmidi->avail_min = params->avail_min; rawmidi->no_active_sensing = params->no_active_sensing; + rawmidi->params_mode = rawmidi->version < SNDRV_PROTOCOL_VERSION(2, 0, 2) ? 0 : params->mode; return 0; } @@ -844,6 +926,7 @@ int snd_rawmidi_params_current(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *par params->buffer_size = rawmidi->buffer_size; params->avail_min = rawmidi->avail_min; params->no_active_sensing = rawmidi->no_active_sensing; + params->mode = rawmidi->params_mode; return 0; } diff --git a/src/rawmidi/rawmidi_hw.c b/src/rawmidi/rawmidi_hw.c index 99927d75..6bfbc1f3 100644 --- a/src/rawmidi/rawmidi_hw.c +++ b/src/rawmidi/rawmidi_hw.c @@ -285,6 +285,7 @@ int snd_rawmidi_hw_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp, rmidi->poll_fd = fd; rmidi->ops = &snd_rawmidi_hw_ops; rmidi->private_data = hw; + rmidi->version = ver; hw->open++; *inputp = rmidi; } @@ -300,6 +301,7 @@ int snd_rawmidi_hw_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp, rmidi->poll_fd = fd; rmidi->ops = &snd_rawmidi_hw_ops; rmidi->private_data = hw; + rmidi->version = ver; hw->open++; *outputp = rmidi; } diff --git a/src/rawmidi/rawmidi_local.h b/src/rawmidi/rawmidi_local.h index 721e1ec9..c4068d7c 100644 --- a/src/rawmidi/rawmidi_local.h +++ b/src/rawmidi/rawmidi_local.h @@ -42,12 +42,14 @@ struct _snd_rawmidi { snd_rawmidi_type_t type; snd_rawmidi_stream_t stream; int mode; + int version; int poll_fd; const snd_rawmidi_ops_t *ops; void *private_data; size_t buffer_size; size_t avail_min; unsigned int no_active_sensing: 1; + int params_mode; }; int snd_rawmidi_hw_open(snd_rawmidi_t **input, snd_rawmidi_t **output, From patchwork Mon Aug 16 16:06:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Henningsson X-Patchwork-Id: 12438799 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=-16.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,USER_AGENT_GIT 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 746FEC4338F for ; Mon, 16 Aug 2021 16:08:49 +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 B762A6056B for ; Mon, 16 Aug 2021 16:08:48 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org B762A6056B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=diwic.se Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=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 2D59D16B9; Mon, 16 Aug 2021 18:07:57 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 2D59D16B9 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1629130127; bh=HOHrwgvrUnWcG+GjHLteQdDPNtwLQmMUMzRrjAvuE20=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=lMrk5n6nG59J3aQwgRg5Va8dQca9wrzf7l/1okqVc3fehLqL7tJqyYtS0HkBGrmh1 +qNJHkNbWw/tRVPkzX+jqJSJLYX9ElhWtSOe5wHZyNBuc90N6xLpCgKhCHp/PVnMiB o9ppPKkLU9ZejBHjBZeqTVzE0XcsAKyhmEQF+0ZQ= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id B5C07F80259; Mon, 16 Aug 2021 18:07:09 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 2C58EF80425; Mon, 16 Aug 2021 18:07:08 +0200 (CEST) Received: from ns4.inleed.net (mailout4.inleed.net [IPv6:2a0b:dc80:cafe:104::1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id C8775F80154 for ; Mon, 16 Aug 2021 18:07:00 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz C8775F80154 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=diwic.se header.i=@diwic.se header.b="ROkbjOJW" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=diwic.se; s=x; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=RtV4avW87miuQJKhWG8x5vtWsvVLL2pYrQY0bf9KeuY=; b=ROkbjOJWk9yNOYFCJZMu2Jgptv HVDjxvZgh3P9IAhfcmjZ9MxgPY6iute1PNOURbA3jXU8Y+lWdlkyi+Kv3mOkT42PzZNCbR+Y7Ll7N axwjhfjJW4U4hMw3KILiQQxX5kf3MffLmhbz84eLHY5E7RLcq0oTnsFqU/4QrbJwki8HXNkv2Ww+3 F3dh/QO16oWUZ/hM5EFzpEMQ8yVgg8WQdyjmRu7puIR1WQCK4t+puNnR1bR0162rgBRjVCoJFgyPB em03GnRGyoR1aWFEhDEEv/oxaMONtgBZztCBbKAYazcnOiGF7a21cHMOSE2g01vqIjkNsmQ6mQeEG 0WNFne3A==; Received: from c83-254-143-147.bredband.tele2.se ([83.254.143.147] helo=localhost.localdomain) by ns4.inleed.net with esmtpsa (TLS1.2) tls TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1mFf8d-0044Nq-9G; Mon, 16 Aug 2021 18:06:59 +0200 From: David Henningsson To: tiwai@suse.de, perex@perex.cz, alsa-devel@alsa-project.org Subject: [PATCH 2/2] Add test for rawmidi framing API Date: Mon, 16 Aug 2021 18:06:25 +0200 Message-Id: <20210816160625.17796-3-coding@diwic.se> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210816160625.17796-1-coding@diwic.se> References: <20210816160625.17796-1-coding@diwic.se> MIME-Version: 1.0 X-Authenticated-Id: coding@diwic.se Cc: David Henningsson 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" Signed-off-by: David Henningsson --- test/rawmidi.c | 65 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/test/rawmidi.c b/test/rawmidi.c index 67f585b0..1090d44b 100644 --- a/test/rawmidi.c +++ b/test/rawmidi.c @@ -13,6 +13,7 @@ static void usage(void) fprintf(stderr, " -o device-id : test ALSA output device\n"); fprintf(stderr, " -I node : test input node\n"); fprintf(stderr, " -O node : test output node\n"); + fprintf(stderr, " -c clock : kernel clock type (0=none, 1=realtime, 2=monotonic, 3=monotonic raw)\n"); fprintf(stderr, " -t: test midi thru\n"); fprintf(stderr, " example:\n"); fprintf(stderr, " rawmidi -i hw:0,0 -O /dev/midi1\n"); @@ -37,7 +38,8 @@ int main(int argc,char** argv) char *device_out = NULL; char *node_in = NULL; char *node_out = NULL; - + int clock_type = -1; + int fd_in = -1,fd_out = -1; snd_rawmidi_t *handle_in = 0,*handle_out = 0; @@ -58,6 +60,10 @@ int main(int argc,char** argv) case 't': thru = 1; break; + case 'c': + if (i + 1 < argc) + clock_type = atoi(argv[++i]); + break; case 'i': if (i + 1 < argc) device_in = argv[++i]; @@ -133,20 +139,67 @@ int main(int argc,char** argv) } } - - if (!thru) { if (handle_in || fd_in!=-1) { + if (clock_type != -1) { + snd_rawmidi_params_t *params; + snd_rawmidi_params_malloc(¶ms); + if (!handle_in) { + fprintf(stderr, "-c only usable with -i"); + clock_type = -1; + } + if (clock_type != -1) { + fprintf(stderr, "Enable kernel clock type %d\n", clock_type); + snd_rawmidi_params_current(handle_in, params); + err = snd_rawmidi_params_set_framing_type(handle_in, params, 1); + if (err) { + fprintf(stderr,"snd_rawmidi_params_set_framing_type failed: %d\n", err); + clock_type = -1; + } + } + if (clock_type != -1) { + err = snd_rawmidi_params_set_clock_type(handle_in, params, clock_type); + if (err) { + fprintf(stderr, "snd_rawmidi_params_set_clock_type failed: %d\n", err); + clock_type = -1; + } + } + if (clock_type != -1) { + err = snd_rawmidi_params(handle_in, params); + if (err) { + fprintf(stderr, "snd_rawmidi_params failed: %d\n", err); + clock_type = -1; + } + } + snd_rawmidi_params_free(params); + } + fprintf(stderr,"Read midi in\n"); fprintf(stderr,"Press ctrl-c to stop\n"); } if (handle_in) { unsigned char ch; + snd_rawmidi_framing_tstamp_t frame; while (!stop) { - snd_rawmidi_read(handle_in,&ch,1); - if (verbose) { - fprintf(stderr,"read %02x\n",ch); + if (clock_type != -1) { + snd_rawmidi_read(handle_in, &frame, sizeof(frame)); + if (verbose) { + int i; + if (frame.frame_type) { + fprintf(stderr, "read unknown frame %d", frame.frame_type); + continue; + } + fprintf(stderr, "read [%lld:%09d]", frame.tv_sec, frame.tv_nsec); + for (i = 0; i < frame.length; i++) + fprintf(stderr, " %02x", frame.data[i]); + fprintf(stderr, "\n"); + } + } + else { + snd_rawmidi_read(handle_in,&ch,1); + if (verbose) + fprintf(stderr,"read %02x\n",ch); } } }