From patchwork Fri Jun 23 07:55:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 695295 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id B7750EB64DD for ; Fri, 23 Jun 2023 07:57:11 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 91C34843; Fri, 23 Jun 2023 09:56:17 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 91C34843 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1687507027; bh=74A3ePod+MVJV5XObYYrqUOb3EDgqIpmcAhXK8yrAJM=; h=From:To:Subject:Date:List-Id:List-Archive:List-Help:List-Owner: List-Post:List-Subscribe:List-Unsubscribe:From; b=PClG1PWhrp8ic1zaGv+mqL6t7Dwckojv7jkVZnV5C4C11kziJPMwECbQHnL+tGFRE xBtvqxN0EhfuPT2eI9nmDEkN41MWolKOteoQU5zKo5dGsgJqHQW+5NOO0W4OlNCnCw FU0L/9eRuI4Tst4YQOcpUCbhCK+1UryQzQfwbJyU= Received: by alsa1.perex.cz (Postfix, from userid 50401) id 48D2EF80544; Fri, 23 Jun 2023 09:55:52 +0200 (CEST) Received: from mailman-core.alsa-project.org (mailman-core.alsa-project.org [10.254.200.10]) by alsa1.perex.cz (Postfix) with ESMTP id B9114F80141; Fri, 23 Jun 2023 09:55:51 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id E15A1F80141; Fri, 23 Jun 2023 09:55:42 +0200 (CEST) Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.220.28]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id E4056F80093 for ; Fri, 23 Jun 2023 09:55:33 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz E4056F80093 Authentication-Results: alsa1.perex.cz; dkim=pass (1024-bit key, unprotected) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=dARWo7Yj; dkim=pass header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=/TsSz1O/ Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 3E96621901; Fri, 23 Jun 2023 07:55:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1687506933; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=3CYxtSygKPI3g8/xzqkbOFX8CAsBETnJ1/EnWn39SUc=; b=dARWo7Yj1KU6bZEhhU28xILoLUKDstYRSrBaEwAwn9X5WJp392YfYH2OvZ7ZJ4KWPiAXwD xmphb8+CgELjoROznr4s3+vRbpEV0v32NyWPl4/hVV4nK2vNk2sfUNC0WSkCttGmFAjrAc Abho2QF+XmH6Svicn3rhha3Jgi2rAHI= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1687506933; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=3CYxtSygKPI3g8/xzqkbOFX8CAsBETnJ1/EnWn39SUc=; b=/TsSz1O/vwuBulrrnBxOiHdj5uhWfc4bcbOaSrR6RCX9O1zj2KkbxgaQoI2v837Xydeg7J 4lJOuLM7XY5M8HDw== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 10C0C139F7; Fri, 23 Jun 2023 07:55:33 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id i6f4AvVPlWRFQQAAMHmgww (envelope-from ); Fri, 23 Jun 2023 07:55:33 +0000 From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH] ALSA: ump: Export MIDI1 / UMP conversion helpers Date: Fri, 23 Jun 2023 09:55:30 +0200 Message-Id: <20230623075530.10976-1-tiwai@suse.de> X-Mailer: git-send-email 2.35.3 MIME-Version: 1.0 Message-ID-Hash: BQXNXRKQJ4VOG4BE2NFT27VARDDMTXPJ X-Message-ID-Hash: BQXNXRKQJ4VOG4BE2NFT27VARDDMTXPJ X-MailFrom: tiwai@suse.de X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-alsa-devel.alsa-project.org-0; header-match-alsa-devel.alsa-project.org-1; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.8 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Yet more preliminary work for the upcoming USB gadget support. Now export the helpers to convert between legacy MIDI1 and UMP data for handling the MIDI 1.0 USB interface. The header file is moved to include/sound. The API functions are slightly changed, so that they can be used without the direct access to snd_ump object. The allocation is done in ump.c itself as it's a simple kcalloc(). Signed-off-by: Takashi Iwai --- include/sound/ump_convert.h | 46 +++++++++++++++++++++ sound/core/ump.c | 18 ++++----- sound/core/ump_convert.c | 80 ++++++++++++++++--------------------- sound/core/ump_convert.h | 43 -------------------- 4 files changed, 89 insertions(+), 98 deletions(-) create mode 100644 include/sound/ump_convert.h delete mode 100644 sound/core/ump_convert.h diff --git a/include/sound/ump_convert.h b/include/sound/ump_convert.h new file mode 100644 index 000000000000..28c364c63245 --- /dev/null +++ b/include/sound/ump_convert.h @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#ifndef __SOUND_UMP_CONVERT_H +#define __SOUND_UMP_CONVERT_H + +#include + +/* context for converting from legacy control messages to UMP packet */ +struct ump_cvt_to_ump_bank { + bool rpn_set; + bool nrpn_set; + bool bank_set; + unsigned char cc_rpn_msb, cc_rpn_lsb; + unsigned char cc_nrpn_msb, cc_nrpn_lsb; + unsigned char cc_data_msb, cc_data_lsb; + unsigned char cc_bank_msb, cc_bank_lsb; +}; + +/* context for converting from MIDI1 byte stream to UMP packet */ +struct ump_cvt_to_ump { + /* MIDI1 intermediate buffer */ + unsigned char buf[4]; + int len; + int cmd_bytes; + + /* UMP output packet */ + u32 ump[4]; + int ump_bytes; + + /* various status */ + unsigned int in_sysex; + struct ump_cvt_to_ump_bank bank[16]; /* per channel */ +}; + +int snd_ump_convert_from_ump(const u32 *data, unsigned char *dst, + unsigned char *group_ret); +void snd_ump_convert_to_ump(struct ump_cvt_to_ump *cvt, unsigned char group, + unsigned int protocol, unsigned char c); + +/* reset the converter context, called at each open to ump */ +static inline void snd_ump_convert_reset(struct ump_cvt_to_ump *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + +} + +#endif /* __SOUND_UMP_CONVERT_H */ diff --git a/sound/core/ump.c b/sound/core/ump.c index 5e17351ca984..246348766ec1 100644 --- a/sound/core/ump.c +++ b/sound/core/ump.c @@ -11,7 +11,7 @@ #include #include #include -#include "ump_convert.h" +#include #define ump_err(ump, fmt, args...) dev_err(&(ump)->core.dev, fmt, ##args) #define ump_warn(ump, fmt, args...) dev_warn(&(ump)->core.dev, fmt, ##args) @@ -87,7 +87,7 @@ static void snd_ump_endpoint_free(struct snd_rawmidi *rmidi) ump->private_free(ump); #if IS_ENABLED(CONFIG_SND_UMP_LEGACY_RAWMIDI) - snd_ump_convert_free(ump); + kfree(ump->out_cvts); #endif } @@ -1002,7 +1002,7 @@ static int snd_ump_legacy_open(struct snd_rawmidi_substream *substream) goto unlock; } ump->legacy_out_opens++; - snd_ump_reset_convert_to_ump(ump, group); + snd_ump_convert_reset(&ump->out_cvts[group]); } spin_lock_irq(&ump->legacy_locks[dir]); ump->legacy_substreams[dir][group] = substream; @@ -1091,7 +1091,7 @@ static int process_legacy_output(struct snd_ump_endpoint *ump, ctx = &ump->out_cvts[group]; while (!ctx->ump_bytes && snd_rawmidi_transmit(substream, &c, 1) > 0) - snd_ump_convert_to_ump(ump, group, c); + snd_ump_convert_to_ump(ctx, group, ump->info.protocol, c); if (ctx->ump_bytes && ctx->ump_bytes <= count) { size = ctx->ump_bytes; memcpy(buffer, ctx->ump, size); @@ -1113,7 +1113,7 @@ static void process_legacy_input(struct snd_ump_endpoint *ump, const u32 *src, const int dir = SNDRV_RAWMIDI_STREAM_INPUT; int size; - size = snd_ump_convert_from_ump(ump, src, buf, &group); + size = snd_ump_convert_from_ump(src, buf, &group); if (size <= 0) return; spin_lock_irqsave(&ump->legacy_locks[dir], flags); @@ -1130,9 +1130,9 @@ int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump, bool input, output; int err; - err = snd_ump_convert_init(ump); - if (err < 0) - return err; + ump->out_cvts = kcalloc(16, sizeof(*ump->out_cvts), GFP_KERNEL); + if (!ump->out_cvts) + return -ENOMEM; input = ump->core.info_flags & SNDRV_RAWMIDI_INFO_INPUT; output = ump->core.info_flags & SNDRV_RAWMIDI_INFO_OUTPUT; @@ -1140,7 +1140,7 @@ int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump, output ? 16 : 0, input ? 16 : 0, &rmidi); if (err < 0) { - snd_ump_convert_free(ump); + kfree(ump->out_cvts); return err; } diff --git a/sound/core/ump_convert.c b/sound/core/ump_convert.c index 48ab3e1bd62e..fb61df424a87 100644 --- a/sound/core/ump_convert.c +++ b/sound/core/ump_convert.c @@ -8,7 +8,7 @@ #include #include #include -#include "ump_convert.h" +#include /* * Upgrade / downgrade value bits @@ -205,12 +205,18 @@ static int cvt_ump_sysex7_to_legacy(const u32 *data, unsigned char *buf) return size; } -/* convert from a UMP packet @data to MIDI 1.0 bytes at @buf; - * the target group is stored at @group_ret, - * returns the number of bytes of MIDI 1.0 stream +/** + * snd_ump_convert_from_ump - convert from UMP to legacy MIDI + * @data: UMP packet + * @buf: buffer to store legacy MIDI data + * @group_ret: pointer to store the target group + * + * Convert from a UMP packet @data to MIDI 1.0 bytes at @buf. + * The target group is stored at @group_ret. + * + * The function returns the number of bytes of MIDI 1.0 stream. */ -int snd_ump_convert_from_ump(struct snd_ump_endpoint *ump, - const u32 *data, +int snd_ump_convert_from_ump(const u32 *data, unsigned char *buf, unsigned char *group_ret) { @@ -230,6 +236,7 @@ int snd_ump_convert_from_ump(struct snd_ump_endpoint *ump, return 0; } +EXPORT_SYMBOL_GPL(snd_ump_convert_from_ump); /* * MIDI 1 byte stream -> UMP conversion @@ -302,10 +309,10 @@ static void fill_rpn(struct ump_cvt_to_ump_bank *cc, } /* convert to a MIDI 1.0 Channel Voice message */ -static int cvt_legacy_cmd_to_ump(struct snd_ump_endpoint *ump, - struct ump_cvt_to_ump *cvt, - unsigned char group, u32 *data, - unsigned char bytes) +static int cvt_legacy_cmd_to_ump(struct ump_cvt_to_ump *cvt, + unsigned char group, + unsigned int protocol, + u32 *data, unsigned char bytes) { const unsigned char *buf = cvt->buf; struct ump_cvt_to_ump_bank *cc; @@ -316,7 +323,7 @@ static int cvt_legacy_cmd_to_ump(struct snd_ump_endpoint *ump, BUILD_BUG_ON(sizeof(union snd_ump_midi2_msg) != 8); /* for MIDI 1.0 UMP, it's easy, just pack it into UMP */ - if (ump->info.protocol & SNDRV_UMP_EP_INFO_PROTO_MIDI1) { + if (protocol & SNDRV_UMP_EP_INFO_PROTO_MIDI1) { data[0] = ump_compose(UMP_MSG_TYPE_MIDI1_CHANNEL_VOICE, group, 0, buf[0]); data[0] |= buf[1] << 8; @@ -413,8 +420,8 @@ static int cvt_legacy_cmd_to_ump(struct snd_ump_endpoint *ump, return 8; } -static int do_convert_to_ump(struct snd_ump_endpoint *ump, - unsigned char group, unsigned char c, u32 *data) +static int do_convert_to_ump(struct ump_cvt_to_ump *cvt, unsigned char group, + unsigned int protocol, unsigned char c, u32 *data) { /* bytes for 0x80-0xf0 */ static unsigned char cmd_bytes[8] = { @@ -424,7 +431,6 @@ static int do_convert_to_ump(struct snd_ump_endpoint *ump, static unsigned char system_bytes[16] = { 0, 2, 3, 2, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1 }; - struct ump_cvt_to_ump *cvt = &ump->out_cvts[group]; unsigned char bytes; if (c == UMP_MIDI1_MSG_SYSEX_START) { @@ -478,40 +484,22 @@ static int do_convert_to_ump(struct snd_ump_endpoint *ump, cvt->len = 1; if ((cvt->buf[0] & 0xf0) == UMP_MIDI1_MSG_REALTIME) return cvt_legacy_system_to_ump(cvt, group, data); - return cvt_legacy_cmd_to_ump(ump, cvt, group, data, cvt->cmd_bytes); + return cvt_legacy_cmd_to_ump(cvt, group, protocol, data, cvt->cmd_bytes); } -/* feed a MIDI 1.0 byte @c and convert to a UMP packet; - * the target group is @group, - * the result is stored in out_cvts[group].ump[] and out_cvts[group].ump_bytes +/** + * snd_ump_convert_to_ump - convert legacy MIDI byte to UMP packet + * @cvt: converter context + * @group: target UMP group + * @protocol: target UMP protocol + * @c: MIDI 1.0 byte data + * + * Feed a MIDI 1.0 byte @c and convert to a UMP packet if completed. + * The result is stored in the buffer in @cvt. */ -void snd_ump_convert_to_ump(struct snd_ump_endpoint *ump, - unsigned char group, unsigned char c) +void snd_ump_convert_to_ump(struct ump_cvt_to_ump *cvt, unsigned char group, + unsigned int protocol, unsigned char c) { - struct ump_cvt_to_ump *cvt = &ump->out_cvts[group]; - - cvt->ump_bytes = do_convert_to_ump(ump, group, c, cvt->ump); -} - -/* reset the converter context, called at each open */ -void snd_ump_reset_convert_to_ump(struct snd_ump_endpoint *ump, - unsigned char group) -{ - memset(&ump->out_cvts[group], 0, sizeof(*ump->out_cvts)); -} - -/* initialize converters */ -int snd_ump_convert_init(struct snd_ump_endpoint *ump) -{ - ump->out_cvts = kcalloc(16, sizeof(*ump->out_cvts), GFP_KERNEL); - if (!ump->out_cvts) - return -ENOMEM; - return 0; -} - -/* release resources */ -void snd_ump_convert_free(struct snd_ump_endpoint *ump) -{ - kfree(ump->out_cvts); - ump->out_cvts = NULL; + cvt->ump_bytes = do_convert_to_ump(cvt, group, protocol, c, cvt->ump); } +EXPORT_SYMBOL_GPL(snd_ump_convert_to_ump); diff --git a/sound/core/ump_convert.h b/sound/core/ump_convert.h deleted file mode 100644 index bbfe96084779..000000000000 --- a/sound/core/ump_convert.h +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -#ifndef __UMP_CONVERT_H -#define __UMP_CONVERT_H - -#include - -/* context for converting from legacy control messages to UMP packet */ -struct ump_cvt_to_ump_bank { - bool rpn_set; - bool nrpn_set; - bool bank_set; - unsigned char cc_rpn_msb, cc_rpn_lsb; - unsigned char cc_nrpn_msb, cc_nrpn_lsb; - unsigned char cc_data_msb, cc_data_lsb; - unsigned char cc_bank_msb, cc_bank_lsb; -}; - -/* context for converting from MIDI1 byte stream to UMP packet */ -struct ump_cvt_to_ump { - /* MIDI1 intermediate buffer */ - unsigned char buf[4]; - int len; - int cmd_bytes; - - /* UMP output packet */ - u32 ump[4]; - int ump_bytes; - - /* various status */ - unsigned int in_sysex; - struct ump_cvt_to_ump_bank bank[16]; /* per channel */ -}; - -int snd_ump_convert_init(struct snd_ump_endpoint *ump); -void snd_ump_convert_free(struct snd_ump_endpoint *ump); -int snd_ump_convert_from_ump(struct snd_ump_endpoint *ump, - const u32 *data, unsigned char *dst, - unsigned char *group_ret); -void snd_ump_convert_to_ump(struct snd_ump_endpoint *ump, - unsigned char group, unsigned char c); -void snd_ump_reset_convert_to_ump(struct snd_ump_endpoint *ump, - unsigned char group); -#endif /* __UMP_CONVERT_H */