xref: /third_party/alsa-lib/src/rawmidi/ump.c (revision d5ac70f0)
1d5ac70f0Sopenharmony_ci/* SPDX-License-Identifier: LGPL-2.1+ */
2d5ac70f0Sopenharmony_ci/**
3d5ac70f0Sopenharmony_ci * \file rawmidi/ump.c
4d5ac70f0Sopenharmony_ci * \brief Universal MIDI Protocol (UMP) Interface
5d5ac70f0Sopenharmony_ci */
6d5ac70f0Sopenharmony_ci
7d5ac70f0Sopenharmony_ci#include "rawmidi_local.h"
8d5ac70f0Sopenharmony_ci#include "ump_local.h"
9d5ac70f0Sopenharmony_ci
10d5ac70f0Sopenharmony_cistatic int get_rawmidi_flags(snd_ump_t *ump)
11d5ac70f0Sopenharmony_ci{
12d5ac70f0Sopenharmony_ci	snd_rawmidi_info_t info;
13d5ac70f0Sopenharmony_ci	int err;
14d5ac70f0Sopenharmony_ci
15d5ac70f0Sopenharmony_ci	err = snd_rawmidi_info(ump->rawmidi, &info);
16d5ac70f0Sopenharmony_ci	if (err < 0)
17d5ac70f0Sopenharmony_ci		return err;
18d5ac70f0Sopenharmony_ci	if (!(info.flags & SNDRV_RAWMIDI_INFO_UMP))
19d5ac70f0Sopenharmony_ci		return -EINVAL;
20d5ac70f0Sopenharmony_ci	ump->flags = info.flags;
21d5ac70f0Sopenharmony_ci	return 0;
22d5ac70f0Sopenharmony_ci}
23d5ac70f0Sopenharmony_ci
24d5ac70f0Sopenharmony_ci/**
25d5ac70f0Sopenharmony_ci * \brief Opens a new connection to the UMP interface.
26d5ac70f0Sopenharmony_ci * \param inputp Returned input handle (NULL if not wanted)
27d5ac70f0Sopenharmony_ci * \param outputp Returned output handle (NULL if not wanted)
28d5ac70f0Sopenharmony_ci * \param name ASCII identifier of the UMP handle
29d5ac70f0Sopenharmony_ci * \param mode Open mode
30d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code
31d5ac70f0Sopenharmony_ci *
32d5ac70f0Sopenharmony_ci * Opens a new connection to the UMP interface specified with
33d5ac70f0Sopenharmony_ci * an ASCII identifier and mode.
34d5ac70f0Sopenharmony_ci */
35d5ac70f0Sopenharmony_ciint snd_ump_open(snd_ump_t **inputp, snd_ump_t **outputp, const char *name,
36d5ac70f0Sopenharmony_ci		 int mode)
37d5ac70f0Sopenharmony_ci{
38d5ac70f0Sopenharmony_ci	snd_ump_t *input = NULL, *output = NULL;
39d5ac70f0Sopenharmony_ci	int err;
40d5ac70f0Sopenharmony_ci
41d5ac70f0Sopenharmony_ci	if (inputp)
42d5ac70f0Sopenharmony_ci		*inputp = NULL;
43d5ac70f0Sopenharmony_ci	if (outputp)
44d5ac70f0Sopenharmony_ci		*outputp = NULL;
45d5ac70f0Sopenharmony_ci	if (!inputp && !outputp)
46d5ac70f0Sopenharmony_ci		return -EINVAL;
47d5ac70f0Sopenharmony_ci
48d5ac70f0Sopenharmony_ci	err = -ENOMEM;
49d5ac70f0Sopenharmony_ci	if (inputp) {
50d5ac70f0Sopenharmony_ci		input = calloc(1, sizeof(*input));
51d5ac70f0Sopenharmony_ci		if (!input)
52d5ac70f0Sopenharmony_ci			goto error;
53d5ac70f0Sopenharmony_ci		input->is_input = 1;
54d5ac70f0Sopenharmony_ci	}
55d5ac70f0Sopenharmony_ci	if (outputp) {
56d5ac70f0Sopenharmony_ci		output = calloc(1, sizeof(*output));
57d5ac70f0Sopenharmony_ci		if (!output)
58d5ac70f0Sopenharmony_ci			goto error;
59d5ac70f0Sopenharmony_ci	}
60d5ac70f0Sopenharmony_ci
61d5ac70f0Sopenharmony_ci	err = snd_rawmidi_open(input ? &input->rawmidi : NULL,
62d5ac70f0Sopenharmony_ci			       output ? &output->rawmidi : NULL,
63d5ac70f0Sopenharmony_ci			       name, mode | _SND_RAWMIDI_OPEN_UMP);
64d5ac70f0Sopenharmony_ci	if (err < 0)
65d5ac70f0Sopenharmony_ci		goto error;
66d5ac70f0Sopenharmony_ci
67d5ac70f0Sopenharmony_ci	if (input) {
68d5ac70f0Sopenharmony_ci		err = get_rawmidi_flags(input);
69d5ac70f0Sopenharmony_ci		if (err < 0)
70d5ac70f0Sopenharmony_ci			goto error;
71d5ac70f0Sopenharmony_ci	}
72d5ac70f0Sopenharmony_ci	if (output) {
73d5ac70f0Sopenharmony_ci		err = get_rawmidi_flags(output);
74d5ac70f0Sopenharmony_ci		if (err < 0)
75d5ac70f0Sopenharmony_ci			goto error;
76d5ac70f0Sopenharmony_ci	}
77d5ac70f0Sopenharmony_ci
78d5ac70f0Sopenharmony_ci	if (inputp)
79d5ac70f0Sopenharmony_ci		*inputp = input;
80d5ac70f0Sopenharmony_ci	if (outputp)
81d5ac70f0Sopenharmony_ci		*outputp = output;
82d5ac70f0Sopenharmony_ci
83d5ac70f0Sopenharmony_ci	return 0;
84d5ac70f0Sopenharmony_ci
85d5ac70f0Sopenharmony_ci error:
86d5ac70f0Sopenharmony_ci	if (input) {
87d5ac70f0Sopenharmony_ci		if (input->rawmidi)
88d5ac70f0Sopenharmony_ci			snd_rawmidi_close(input->rawmidi);
89d5ac70f0Sopenharmony_ci		free(input);
90d5ac70f0Sopenharmony_ci	}
91d5ac70f0Sopenharmony_ci	if (output) {
92d5ac70f0Sopenharmony_ci		if (output->rawmidi)
93d5ac70f0Sopenharmony_ci			snd_rawmidi_close(output->rawmidi);
94d5ac70f0Sopenharmony_ci		free(output);
95d5ac70f0Sopenharmony_ci	}
96d5ac70f0Sopenharmony_ci	return err;
97d5ac70f0Sopenharmony_ci}
98d5ac70f0Sopenharmony_ci
99d5ac70f0Sopenharmony_ci/**
100d5ac70f0Sopenharmony_ci * \brief close UMP handle
101d5ac70f0Sopenharmony_ci * \param ump UMP handle
102d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code
103d5ac70f0Sopenharmony_ci *
104d5ac70f0Sopenharmony_ci * Closes the specified UMP handle and frees all associated
105d5ac70f0Sopenharmony_ci * resources.
106d5ac70f0Sopenharmony_ci */
107d5ac70f0Sopenharmony_ciint snd_ump_close(snd_ump_t *ump)
108d5ac70f0Sopenharmony_ci{
109d5ac70f0Sopenharmony_ci	int err;
110d5ac70f0Sopenharmony_ci
111d5ac70f0Sopenharmony_ci	err = snd_rawmidi_close(ump->rawmidi);
112d5ac70f0Sopenharmony_ci	free(ump);
113d5ac70f0Sopenharmony_ci	return err;
114d5ac70f0Sopenharmony_ci}
115d5ac70f0Sopenharmony_ci
116d5ac70f0Sopenharmony_ci/**
117d5ac70f0Sopenharmony_ci * \brief get RawMidi instance associated with the UMP handle
118d5ac70f0Sopenharmony_ci * \param ump UMP handle
119d5ac70f0Sopenharmony_ci * \return the associated RawMidi handle
120d5ac70f0Sopenharmony_ci *
121d5ac70f0Sopenharmony_ci * Returns the associated RawMidi instance with the given UMP handle
122d5ac70f0Sopenharmony_ci */
123d5ac70f0Sopenharmony_cisnd_rawmidi_t *snd_ump_rawmidi(snd_ump_t *ump)
124d5ac70f0Sopenharmony_ci{
125d5ac70f0Sopenharmony_ci	return ump->rawmidi;
126d5ac70f0Sopenharmony_ci}
127d5ac70f0Sopenharmony_ci
128d5ac70f0Sopenharmony_ci/**
129d5ac70f0Sopenharmony_ci * \brief get identifier of UMP handle
130d5ac70f0Sopenharmony_ci * \param ump UMP handle
131d5ac70f0Sopenharmony_ci * \return ascii identifier of UMP handle
132d5ac70f0Sopenharmony_ci *
133d5ac70f0Sopenharmony_ci * Returns the ASCII identifier of given UMP handle. It's the same
134d5ac70f0Sopenharmony_ci * identifier specified in snd_ump_open().
135d5ac70f0Sopenharmony_ci */
136d5ac70f0Sopenharmony_ciconst char *snd_ump_name(snd_ump_t *ump)
137d5ac70f0Sopenharmony_ci{
138d5ac70f0Sopenharmony_ci	return snd_rawmidi_name(ump->rawmidi);
139d5ac70f0Sopenharmony_ci}
140d5ac70f0Sopenharmony_ci
141d5ac70f0Sopenharmony_ci/**
142d5ac70f0Sopenharmony_ci * \brief get count of poll descriptors for UMP handle
143d5ac70f0Sopenharmony_ci * \param ump UMP handle
144d5ac70f0Sopenharmony_ci * \return count of poll descriptors
145d5ac70f0Sopenharmony_ci */
146d5ac70f0Sopenharmony_ciint snd_ump_poll_descriptors_count(snd_ump_t *ump)
147d5ac70f0Sopenharmony_ci{
148d5ac70f0Sopenharmony_ci	return snd_rawmidi_poll_descriptors_count(ump->rawmidi);
149d5ac70f0Sopenharmony_ci}
150d5ac70f0Sopenharmony_ci
151d5ac70f0Sopenharmony_ci/**
152d5ac70f0Sopenharmony_ci * \brief get poll descriptors
153d5ac70f0Sopenharmony_ci * \param ump UMP handle
154d5ac70f0Sopenharmony_ci * \param pfds array of poll descriptors
155d5ac70f0Sopenharmony_ci * \param space space in the poll descriptor array
156d5ac70f0Sopenharmony_ci * \return count of filled descriptors
157d5ac70f0Sopenharmony_ci */
158d5ac70f0Sopenharmony_ciint snd_ump_poll_descriptors(snd_ump_t *ump, struct pollfd *pfds,
159d5ac70f0Sopenharmony_ci			     unsigned int space)
160d5ac70f0Sopenharmony_ci{
161d5ac70f0Sopenharmony_ci	return snd_rawmidi_poll_descriptors(ump->rawmidi, pfds, space);
162d5ac70f0Sopenharmony_ci}
163d5ac70f0Sopenharmony_ci
164d5ac70f0Sopenharmony_ci/**
165d5ac70f0Sopenharmony_ci * \brief get returned events from poll descriptors
166d5ac70f0Sopenharmony_ci * \param ump UMP handle
167d5ac70f0Sopenharmony_ci * \param pfds array of poll descriptors
168d5ac70f0Sopenharmony_ci * \param nfds count of poll descriptors
169d5ac70f0Sopenharmony_ci * \param revents returned events
170d5ac70f0Sopenharmony_ci * \return zero if success, otherwise a negative error code
171d5ac70f0Sopenharmony_ci */
172d5ac70f0Sopenharmony_ciint snd_ump_poll_descriptors_revents(snd_ump_t *ump, struct pollfd *pfds,
173d5ac70f0Sopenharmony_ci				     unsigned int nfds, unsigned short *revents)
174d5ac70f0Sopenharmony_ci{
175d5ac70f0Sopenharmony_ci	return snd_rawmidi_poll_descriptors_revents(ump->rawmidi, pfds, nfds,
176d5ac70f0Sopenharmony_ci						    revents);
177d5ac70f0Sopenharmony_ci}
178d5ac70f0Sopenharmony_ci
179d5ac70f0Sopenharmony_ci/**
180d5ac70f0Sopenharmony_ci * \brief set nonblock mode
181d5ac70f0Sopenharmony_ci * \param ump UMP handle
182d5ac70f0Sopenharmony_ci * \param nonblock 0 = block, 1 = nonblock mode
183d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code
184d5ac70f0Sopenharmony_ci *
185d5ac70f0Sopenharmony_ci * The nonblock mode cannot be used when the stream is in
186d5ac70f0Sopenharmony_ci * #SND_RAWMIDI_APPEND state.
187d5ac70f0Sopenharmony_ci */
188d5ac70f0Sopenharmony_ciint snd_ump_nonblock(snd_ump_t *ump, int nonblock)
189d5ac70f0Sopenharmony_ci{
190d5ac70f0Sopenharmony_ci	return snd_rawmidi_nonblock(ump->rawmidi, nonblock);
191d5ac70f0Sopenharmony_ci}
192d5ac70f0Sopenharmony_ci
193d5ac70f0Sopenharmony_ci/**
194d5ac70f0Sopenharmony_ci * \brief get information about associated RawMidi handle
195d5ac70f0Sopenharmony_ci * \param ump UMP handle
196d5ac70f0Sopenharmony_ci * \param info pointer to a snd_rawmidi_info_t structure to be filled
197d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code
198d5ac70f0Sopenharmony_ci */
199d5ac70f0Sopenharmony_ciint snd_ump_rawmidi_info(snd_ump_t *ump, snd_rawmidi_info_t *info)
200d5ac70f0Sopenharmony_ci{
201d5ac70f0Sopenharmony_ci	return snd_rawmidi_info(ump->rawmidi, info);
202d5ac70f0Sopenharmony_ci}
203d5ac70f0Sopenharmony_ci
204d5ac70f0Sopenharmony_ci/**
205d5ac70f0Sopenharmony_ci * \brief set parameters about associated RawMidi stream
206d5ac70f0Sopenharmony_ci * \param ump UMP handle
207d5ac70f0Sopenharmony_ci * \param params pointer to a snd_rawmidi_params_t structure to be filled
208d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code
209d5ac70f0Sopenharmony_ci */
210d5ac70f0Sopenharmony_ciint snd_ump_rawmidi_params(snd_ump_t *ump, snd_rawmidi_params_t *params)
211d5ac70f0Sopenharmony_ci{
212d5ac70f0Sopenharmony_ci	return snd_rawmidi_params(ump->rawmidi, params);
213d5ac70f0Sopenharmony_ci}
214d5ac70f0Sopenharmony_ci
215d5ac70f0Sopenharmony_ci/**
216d5ac70f0Sopenharmony_ci * \brief get current parameters about associated RawMidi stream
217d5ac70f0Sopenharmony_ci * \param ump UMP handle
218d5ac70f0Sopenharmony_ci * \param params pointer to a snd_rawmidi_params_t structure to be filled
219d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code
220d5ac70f0Sopenharmony_ci */
221d5ac70f0Sopenharmony_ciint snd_ump_rawmidi_params_current(snd_ump_t *ump, snd_rawmidi_params_t *params)
222d5ac70f0Sopenharmony_ci{
223d5ac70f0Sopenharmony_ci	return snd_rawmidi_params_current(ump->rawmidi, params);
224d5ac70f0Sopenharmony_ci}
225d5ac70f0Sopenharmony_ci
226d5ac70f0Sopenharmony_ci/**
227d5ac70f0Sopenharmony_ci * \brief get status of associated RawMidi stream
228d5ac70f0Sopenharmony_ci * \param ump UMP handle
229d5ac70f0Sopenharmony_ci * \param status pointer to a snd_rawmidi_status_t structure to be filled
230d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code
231d5ac70f0Sopenharmony_ci */
232d5ac70f0Sopenharmony_ciint snd_ump_rawmidi_status(snd_ump_t *ump, snd_rawmidi_status_t *status)
233d5ac70f0Sopenharmony_ci{
234d5ac70f0Sopenharmony_ci	return snd_rawmidi_status(ump->rawmidi, status);
235d5ac70f0Sopenharmony_ci}
236d5ac70f0Sopenharmony_ci
237d5ac70f0Sopenharmony_ci/**
238d5ac70f0Sopenharmony_ci * \brief drop all packets in the rawmidi I/O ring buffer immediately
239d5ac70f0Sopenharmony_ci * \param ump UMP handle
240d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code
241d5ac70f0Sopenharmony_ci */
242d5ac70f0Sopenharmony_ciint snd_ump_drop(snd_ump_t *ump)
243d5ac70f0Sopenharmony_ci{
244d5ac70f0Sopenharmony_ci	return snd_rawmidi_drop(ump->rawmidi);
245d5ac70f0Sopenharmony_ci}
246d5ac70f0Sopenharmony_ci
247d5ac70f0Sopenharmony_ci/**
248d5ac70f0Sopenharmony_ci * \brief drain all packets in the UMP I/O ring buffer
249d5ac70f0Sopenharmony_ci * \param ump UMP handle
250d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code
251d5ac70f0Sopenharmony_ci *
252d5ac70f0Sopenharmony_ci * Waits until all MIDI packets are not drained (sent) to the
253d5ac70f0Sopenharmony_ci * hardware device.
254d5ac70f0Sopenharmony_ci */
255d5ac70f0Sopenharmony_ciint snd_ump_drain(snd_ump_t *ump)
256d5ac70f0Sopenharmony_ci{
257d5ac70f0Sopenharmony_ci	return snd_rawmidi_drain(ump->rawmidi);
258d5ac70f0Sopenharmony_ci}
259d5ac70f0Sopenharmony_ci
260d5ac70f0Sopenharmony_ci/**
261d5ac70f0Sopenharmony_ci * \brief write UMP packets to UMP stream
262d5ac70f0Sopenharmony_ci * \param ump UMP handle
263d5ac70f0Sopenharmony_ci * \param buffer buffer containing UMP packets
264d5ac70f0Sopenharmony_ci * \param size output buffer size in bytes
265d5ac70f0Sopenharmony_ci */
266d5ac70f0Sopenharmony_cissize_t snd_ump_write(snd_ump_t *ump, const void *buffer, size_t size)
267d5ac70f0Sopenharmony_ci{
268d5ac70f0Sopenharmony_ci	if (ump->is_input)
269d5ac70f0Sopenharmony_ci		return -EINVAL;
270d5ac70f0Sopenharmony_ci	return snd_rawmidi_write(ump->rawmidi, buffer, size);
271d5ac70f0Sopenharmony_ci}
272d5ac70f0Sopenharmony_ci
273d5ac70f0Sopenharmony_ci/**
274d5ac70f0Sopenharmony_ci * \brief read UMP packets from UMP stream
275d5ac70f0Sopenharmony_ci * \param ump UMP handle
276d5ac70f0Sopenharmony_ci * \param buffer buffer to store the input MIDI bytes
277d5ac70f0Sopenharmony_ci * \param size input buffer size in bytes
278d5ac70f0Sopenharmony_ci * \retval count of UMP packet in bytes otherwise a negative error code
279d5ac70f0Sopenharmony_ci */
280d5ac70f0Sopenharmony_cissize_t snd_ump_read(snd_ump_t *ump, void *buffer, size_t size)
281d5ac70f0Sopenharmony_ci{
282d5ac70f0Sopenharmony_ci	if (!ump->is_input)
283d5ac70f0Sopenharmony_ci		return -EINVAL;
284d5ac70f0Sopenharmony_ci	return snd_rawmidi_read(ump->rawmidi, buffer, size);
285d5ac70f0Sopenharmony_ci}
286d5ac70f0Sopenharmony_ci
287d5ac70f0Sopenharmony_ci/**
288d5ac70f0Sopenharmony_ci * \brief read UMP packets from UMP stream with timestamp
289d5ac70f0Sopenharmony_ci * \param ump UMP handle
290d5ac70f0Sopenharmony_ci * \param[out] tstamp timestamp for the returned UMP packets
291d5ac70f0Sopenharmony_ci * \param buffer buffer to store the input UMP packets
292d5ac70f0Sopenharmony_ci * \param size input buffer size in bytes
293d5ac70f0Sopenharmony_ci * \retval count of UMP packet in bytes otherwise a negative error code
294d5ac70f0Sopenharmony_ci */
295d5ac70f0Sopenharmony_cissize_t snd_ump_tread(snd_ump_t *ump, struct timespec *tstamp, void *buffer,
296d5ac70f0Sopenharmony_ci		      size_t size)
297d5ac70f0Sopenharmony_ci{
298d5ac70f0Sopenharmony_ci	if (!ump->is_input)
299d5ac70f0Sopenharmony_ci		return -EINVAL;
300d5ac70f0Sopenharmony_ci	return snd_rawmidi_tread(ump->rawmidi, tstamp, buffer, size);
301d5ac70f0Sopenharmony_ci}
302d5ac70f0Sopenharmony_ci
303d5ac70f0Sopenharmony_ci/**
304d5ac70f0Sopenharmony_ci * \brief get size of the snd_ump_endpoint_info_t structure in bytes
305d5ac70f0Sopenharmony_ci * \return size of the snd_ump_endpoint_info_t structure in bytes
306d5ac70f0Sopenharmony_ci */
307d5ac70f0Sopenharmony_cisize_t snd_ump_endpoint_info_sizeof(void)
308d5ac70f0Sopenharmony_ci{
309d5ac70f0Sopenharmony_ci	return sizeof(snd_ump_endpoint_info_t);
310d5ac70f0Sopenharmony_ci}
311d5ac70f0Sopenharmony_ci
312d5ac70f0Sopenharmony_ci/**
313d5ac70f0Sopenharmony_ci * \brief allocate the snd_ump_endpoint_info_t structure
314d5ac70f0Sopenharmony_ci * \param info returned pointer
315d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code if fails
316d5ac70f0Sopenharmony_ci *
317d5ac70f0Sopenharmony_ci * Allocates a new snd_rawmidi_status_t structure using the standard
318d5ac70f0Sopenharmony_ci * malloc C library function.
319d5ac70f0Sopenharmony_ci */
320d5ac70f0Sopenharmony_ciint snd_ump_endpoint_info_malloc(snd_ump_endpoint_info_t **info)
321d5ac70f0Sopenharmony_ci{
322d5ac70f0Sopenharmony_ci	*info = calloc(1, sizeof(snd_ump_endpoint_info_t));
323d5ac70f0Sopenharmony_ci	if (!*info)
324d5ac70f0Sopenharmony_ci		return -ENOMEM;
325d5ac70f0Sopenharmony_ci	return 0;
326d5ac70f0Sopenharmony_ci}
327d5ac70f0Sopenharmony_ci
328d5ac70f0Sopenharmony_ci/**
329d5ac70f0Sopenharmony_ci * \brief frees the snd_ump_endpoint_info_t structure
330d5ac70f0Sopenharmony_ci * \param info pointer to the snd_ump_endpoint_info_t structure to free
331d5ac70f0Sopenharmony_ci *
332d5ac70f0Sopenharmony_ci * Frees the given snd_ump_endpoint_info_t structure using the standard
333d5ac70f0Sopenharmony_ci * free C library function.
334d5ac70f0Sopenharmony_ci */
335d5ac70f0Sopenharmony_civoid snd_ump_endpoint_info_free(snd_ump_endpoint_info_t *info)
336d5ac70f0Sopenharmony_ci{
337d5ac70f0Sopenharmony_ci	free(info);
338d5ac70f0Sopenharmony_ci}
339d5ac70f0Sopenharmony_ci
340d5ac70f0Sopenharmony_ci/**
341d5ac70f0Sopenharmony_ci * \brief copy one snd_ump_endpoint_info_t structure to another
342d5ac70f0Sopenharmony_ci * \param dst destination snd_ump_endpoint_info_t structure
343d5ac70f0Sopenharmony_ci * \param src source snd_ump_endpoint_info_t structure
344d5ac70f0Sopenharmony_ci */
345d5ac70f0Sopenharmony_civoid snd_ump_endpoint_info_copy(snd_ump_endpoint_info_t *dst,
346d5ac70f0Sopenharmony_ci				const snd_ump_endpoint_info_t *src)
347d5ac70f0Sopenharmony_ci{
348d5ac70f0Sopenharmony_ci	*dst = *src;
349d5ac70f0Sopenharmony_ci}
350d5ac70f0Sopenharmony_ci
351d5ac70f0Sopenharmony_ci/**
352d5ac70f0Sopenharmony_ci * \brief get card number of UMP endpoint
353d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_endpoint_info_t structure
354d5ac70f0Sopenharmony_ci * \return the card number of the given UMP endpoint
355d5ac70f0Sopenharmony_ci */
356d5ac70f0Sopenharmony_ciint snd_ump_endpoint_info_get_card(const snd_ump_endpoint_info_t *info)
357d5ac70f0Sopenharmony_ci{
358d5ac70f0Sopenharmony_ci	return info->card;
359d5ac70f0Sopenharmony_ci}
360d5ac70f0Sopenharmony_ci
361d5ac70f0Sopenharmony_ci/**
362d5ac70f0Sopenharmony_ci * \brief get device number of UMP endpoint
363d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_endpoint_info_t structure
364d5ac70f0Sopenharmony_ci * \return the device number of the given UMP endpoint
365d5ac70f0Sopenharmony_ci */
366d5ac70f0Sopenharmony_ciint snd_ump_endpoint_info_get_device(const snd_ump_endpoint_info_t *info)
367d5ac70f0Sopenharmony_ci{
368d5ac70f0Sopenharmony_ci	return info->device;
369d5ac70f0Sopenharmony_ci}
370d5ac70f0Sopenharmony_ci
371d5ac70f0Sopenharmony_ci/**
372d5ac70f0Sopenharmony_ci * \brief get UMP endpoint info flags
373d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_endpoint_info_t structure
374d5ac70f0Sopenharmony_ci * \return UMP endpoint flag bits
375d5ac70f0Sopenharmony_ci */
376d5ac70f0Sopenharmony_ciunsigned int snd_ump_endpoint_info_get_flags(const snd_ump_endpoint_info_t *info)
377d5ac70f0Sopenharmony_ci{
378d5ac70f0Sopenharmony_ci	return info->flags;
379d5ac70f0Sopenharmony_ci}
380d5ac70f0Sopenharmony_ci
381d5ac70f0Sopenharmony_ci/**
382d5ac70f0Sopenharmony_ci * \brief get UMP endpoint protocol capability bits
383d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_endpoint_info_t structure
384d5ac70f0Sopenharmony_ci * \return UMP endpoint protocol capability bits
385d5ac70f0Sopenharmony_ci */
386d5ac70f0Sopenharmony_ciunsigned int snd_ump_endpoint_info_get_protocol_caps(const snd_ump_endpoint_info_t *info)
387d5ac70f0Sopenharmony_ci{
388d5ac70f0Sopenharmony_ci	return info->protocol_caps;
389d5ac70f0Sopenharmony_ci}
390d5ac70f0Sopenharmony_ci
391d5ac70f0Sopenharmony_ci/**
392d5ac70f0Sopenharmony_ci * \brief get the current UMP endpoint protocol
393d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_endpoint_info_t structure
394d5ac70f0Sopenharmony_ci * \return UMP endpoint protocol bits
395d5ac70f0Sopenharmony_ci */
396d5ac70f0Sopenharmony_ciunsigned int snd_ump_endpoint_info_get_protocol(const snd_ump_endpoint_info_t *info)
397d5ac70f0Sopenharmony_ci{
398d5ac70f0Sopenharmony_ci	return info->protocol;
399d5ac70f0Sopenharmony_ci}
400d5ac70f0Sopenharmony_ci
401d5ac70f0Sopenharmony_ci/**
402d5ac70f0Sopenharmony_ci * \brief get the number of UMP blocks belonging to the endpoint
403d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_endpoint_info_t structure
404d5ac70f0Sopenharmony_ci * \return number of UMP blocks
405d5ac70f0Sopenharmony_ci */
406d5ac70f0Sopenharmony_ciunsigned int snd_ump_endpoint_info_get_num_blocks(const snd_ump_endpoint_info_t *info)
407d5ac70f0Sopenharmony_ci{
408d5ac70f0Sopenharmony_ci	return info->num_blocks;
409d5ac70f0Sopenharmony_ci}
410d5ac70f0Sopenharmony_ci
411d5ac70f0Sopenharmony_ci/**
412d5ac70f0Sopenharmony_ci * \brief get UMP version number
413d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_endpoint_info_t structure
414d5ac70f0Sopenharmony_ci * \return UMP version number
415d5ac70f0Sopenharmony_ci */
416d5ac70f0Sopenharmony_ciunsigned int snd_ump_endpoint_info_get_version(const snd_ump_endpoint_info_t *info)
417d5ac70f0Sopenharmony_ci{
418d5ac70f0Sopenharmony_ci	return info->version;
419d5ac70f0Sopenharmony_ci}
420d5ac70f0Sopenharmony_ci
421d5ac70f0Sopenharmony_ci/**
422d5ac70f0Sopenharmony_ci * \brief get UMP manufacturer ID
423d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_endpoint_info_t structure
424d5ac70f0Sopenharmony_ci * \return UMP manufacturer ID
425d5ac70f0Sopenharmony_ci */
426d5ac70f0Sopenharmony_ciunsigned int snd_ump_endpoint_info_get_manufacturer_id(const snd_ump_endpoint_info_t *info)
427d5ac70f0Sopenharmony_ci{
428d5ac70f0Sopenharmony_ci	return info->manufacturer_id;
429d5ac70f0Sopenharmony_ci}
430d5ac70f0Sopenharmony_ci
431d5ac70f0Sopenharmony_ci/**
432d5ac70f0Sopenharmony_ci * \brief get UMP family ID
433d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_endpoint_info_t structure
434d5ac70f0Sopenharmony_ci * \return UMP family ID
435d5ac70f0Sopenharmony_ci */
436d5ac70f0Sopenharmony_ciunsigned int snd_ump_endpoint_info_get_family_id(const snd_ump_endpoint_info_t *info)
437d5ac70f0Sopenharmony_ci{
438d5ac70f0Sopenharmony_ci	return info->family_id;
439d5ac70f0Sopenharmony_ci}
440d5ac70f0Sopenharmony_ci
441d5ac70f0Sopenharmony_ci/**
442d5ac70f0Sopenharmony_ci * \brief get UMP model ID
443d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_endpoint_info_t structure
444d5ac70f0Sopenharmony_ci * \return UMP model ID
445d5ac70f0Sopenharmony_ci */
446d5ac70f0Sopenharmony_ciunsigned int snd_ump_endpoint_info_get_model_id(const snd_ump_endpoint_info_t *info)
447d5ac70f0Sopenharmony_ci{
448d5ac70f0Sopenharmony_ci	return info->model_id;
449d5ac70f0Sopenharmony_ci}
450d5ac70f0Sopenharmony_ci
451d5ac70f0Sopenharmony_ci/**
452d5ac70f0Sopenharmony_ci * \brief get UMP software revision
453d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_endpoint_info_t structure
454d5ac70f0Sopenharmony_ci * \return UMP software revision
455d5ac70f0Sopenharmony_ci */
456d5ac70f0Sopenharmony_ciconst unsigned char *snd_ump_endpoint_info_get_sw_revision(const snd_ump_endpoint_info_t *info)
457d5ac70f0Sopenharmony_ci{
458d5ac70f0Sopenharmony_ci	return info->sw_revision;
459d5ac70f0Sopenharmony_ci}
460d5ac70f0Sopenharmony_ci
461d5ac70f0Sopenharmony_ci/**
462d5ac70f0Sopenharmony_ci * \brief get UMP endpoint name string
463d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_endpoint_info_t structure
464d5ac70f0Sopenharmony_ci * \return UMP endpoint name string
465d5ac70f0Sopenharmony_ci */
466d5ac70f0Sopenharmony_ciconst char *snd_ump_endpoint_info_get_name(const snd_ump_endpoint_info_t *info)
467d5ac70f0Sopenharmony_ci{
468d5ac70f0Sopenharmony_ci	return (const char *)info->name;
469d5ac70f0Sopenharmony_ci}
470d5ac70f0Sopenharmony_ci
471d5ac70f0Sopenharmony_ci/**
472d5ac70f0Sopenharmony_ci * \brief get UMP endpoint product ID string
473d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_endpoint_info_t structure
474d5ac70f0Sopenharmony_ci * \return UMP endpoint product ID string
475d5ac70f0Sopenharmony_ci */
476d5ac70f0Sopenharmony_ciconst char *snd_ump_endpoint_info_get_product_id(const snd_ump_endpoint_info_t *info)
477d5ac70f0Sopenharmony_ci{
478d5ac70f0Sopenharmony_ci	return (const char *)info->product_id;
479d5ac70f0Sopenharmony_ci}
480d5ac70f0Sopenharmony_ci
481d5ac70f0Sopenharmony_ci/**
482d5ac70f0Sopenharmony_ci * \brief get endpoint information about UMP handle
483d5ac70f0Sopenharmony_ci * \param ump UMP handle
484d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_endpoint_info_t structure to be filled
485d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code
486d5ac70f0Sopenharmony_ci */
487d5ac70f0Sopenharmony_ciint snd_ump_endpoint_info(snd_ump_t *ump, snd_ump_endpoint_info_t *info)
488d5ac70f0Sopenharmony_ci{
489d5ac70f0Sopenharmony_ci	return _snd_rawmidi_ump_endpoint_info(ump->rawmidi, info);
490d5ac70f0Sopenharmony_ci}
491d5ac70f0Sopenharmony_ci
492d5ac70f0Sopenharmony_ci/**
493d5ac70f0Sopenharmony_ci * \brief get size of the snd_ump_block_info_t structure in bytes
494d5ac70f0Sopenharmony_ci * \return size of the snd_ump_block_info_t structure in bytes
495d5ac70f0Sopenharmony_ci */
496d5ac70f0Sopenharmony_cisize_t snd_ump_block_info_sizeof(void)
497d5ac70f0Sopenharmony_ci{
498d5ac70f0Sopenharmony_ci	return sizeof(snd_ump_block_info_t);
499d5ac70f0Sopenharmony_ci}
500d5ac70f0Sopenharmony_ci
501d5ac70f0Sopenharmony_ci/**
502d5ac70f0Sopenharmony_ci * \brief allocate the snd_ump_block_info_t structure
503d5ac70f0Sopenharmony_ci * \param info returned pointer
504d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code if fails
505d5ac70f0Sopenharmony_ci *
506d5ac70f0Sopenharmony_ci * Allocates a new snd_ump_block_info_t structure using the standard
507d5ac70f0Sopenharmony_ci * malloc C library function.
508d5ac70f0Sopenharmony_ci */
509d5ac70f0Sopenharmony_ciint snd_ump_block_info_malloc(snd_ump_block_info_t **info)
510d5ac70f0Sopenharmony_ci{
511d5ac70f0Sopenharmony_ci	*info = calloc(1, sizeof(snd_ump_block_info_t));
512d5ac70f0Sopenharmony_ci	if (!*info)
513d5ac70f0Sopenharmony_ci		return -ENOMEM;
514d5ac70f0Sopenharmony_ci	return 0;
515d5ac70f0Sopenharmony_ci}
516d5ac70f0Sopenharmony_ci
517d5ac70f0Sopenharmony_ci/**
518d5ac70f0Sopenharmony_ci * \brief frees the snd_ump_block_info_t structure
519d5ac70f0Sopenharmony_ci * \param info pointer to the snd_ump_block_info_t structure to free
520d5ac70f0Sopenharmony_ci *
521d5ac70f0Sopenharmony_ci * Frees the given snd_ump_block_info_t structure using the standard
522d5ac70f0Sopenharmony_ci * free C library function.
523d5ac70f0Sopenharmony_ci */
524d5ac70f0Sopenharmony_civoid snd_ump_block_info_free(snd_ump_block_info_t *info)
525d5ac70f0Sopenharmony_ci{
526d5ac70f0Sopenharmony_ci	free(info);
527d5ac70f0Sopenharmony_ci}
528d5ac70f0Sopenharmony_ci
529d5ac70f0Sopenharmony_ci/**
530d5ac70f0Sopenharmony_ci * \brief copy one snd_ump_block_info_t structure to another
531d5ac70f0Sopenharmony_ci * \param dst destination snd_ump_block_info_t structure
532d5ac70f0Sopenharmony_ci * \param src source snd_ump_block_info_t structure
533d5ac70f0Sopenharmony_ci */
534d5ac70f0Sopenharmony_civoid snd_ump_block_info_copy(snd_ump_block_info_t *dst,
535d5ac70f0Sopenharmony_ci			     const snd_ump_block_info_t *src)
536d5ac70f0Sopenharmony_ci{
537d5ac70f0Sopenharmony_ci	*dst = *src;
538d5ac70f0Sopenharmony_ci}
539d5ac70f0Sopenharmony_ci
540d5ac70f0Sopenharmony_ci/**
541d5ac70f0Sopenharmony_ci * \brief get card number of UMP block
542d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_block_info_t structure
543d5ac70f0Sopenharmony_ci * \return the card number of the given UMP block
544d5ac70f0Sopenharmony_ci */
545d5ac70f0Sopenharmony_ciint snd_ump_block_info_get_card(const snd_ump_block_info_t *info)
546d5ac70f0Sopenharmony_ci{
547d5ac70f0Sopenharmony_ci	return info->card;
548d5ac70f0Sopenharmony_ci}
549d5ac70f0Sopenharmony_ci
550d5ac70f0Sopenharmony_ci/**
551d5ac70f0Sopenharmony_ci * \brief get device number of UMP block
552d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_block_info_t structure
553d5ac70f0Sopenharmony_ci * \return the device number of the given UMP block
554d5ac70f0Sopenharmony_ci */
555d5ac70f0Sopenharmony_ciint snd_ump_block_info_get_device(const snd_ump_block_info_t *info)
556d5ac70f0Sopenharmony_ci{
557d5ac70f0Sopenharmony_ci	return info->device;
558d5ac70f0Sopenharmony_ci}
559d5ac70f0Sopenharmony_ci
560d5ac70f0Sopenharmony_ci/**
561d5ac70f0Sopenharmony_ci * \brief get UMP block ID
562d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_block_info_t structure
563d5ac70f0Sopenharmony_ci * \return ID number of the given UMP block
564d5ac70f0Sopenharmony_ci */
565d5ac70f0Sopenharmony_ciunsigned int snd_ump_block_info_get_block_id(const snd_ump_block_info_t *info)
566d5ac70f0Sopenharmony_ci{
567d5ac70f0Sopenharmony_ci	return info->block_id;
568d5ac70f0Sopenharmony_ci}
569d5ac70f0Sopenharmony_ci
570d5ac70f0Sopenharmony_ci/**
571d5ac70f0Sopenharmony_ci * \brief set UMP block ID for query
572d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_block_info_t structure
573d5ac70f0Sopenharmony_ci * \param id the ID number for query
574d5ac70f0Sopenharmony_ci */
575d5ac70f0Sopenharmony_civoid snd_ump_block_info_set_block_id(snd_ump_block_info_t *info,
576d5ac70f0Sopenharmony_ci				     unsigned int id)
577d5ac70f0Sopenharmony_ci{
578d5ac70f0Sopenharmony_ci	info->block_id = id;
579d5ac70f0Sopenharmony_ci}
580d5ac70f0Sopenharmony_ci
581d5ac70f0Sopenharmony_ci/**
582d5ac70f0Sopenharmony_ci * \brief get UMP block activeness
583d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_block_info_t structure
584d5ac70f0Sopenharmony_ci * \return 1 if the block is active or 0 if inactive
585d5ac70f0Sopenharmony_ci */
586d5ac70f0Sopenharmony_ciunsigned int snd_ump_block_info_get_active(const snd_ump_block_info_t *info)
587d5ac70f0Sopenharmony_ci{
588d5ac70f0Sopenharmony_ci	return info->active;
589d5ac70f0Sopenharmony_ci}
590d5ac70f0Sopenharmony_ci
591d5ac70f0Sopenharmony_ci/**
592d5ac70f0Sopenharmony_ci * \brief get UMP block information flags
593d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_block_info_t structure
594d5ac70f0Sopenharmony_ci * \return info flag bits for the given UMP block
595d5ac70f0Sopenharmony_ci */
596d5ac70f0Sopenharmony_ciunsigned int snd_ump_block_info_get_flags(const snd_ump_block_info_t *info)
597d5ac70f0Sopenharmony_ci{
598d5ac70f0Sopenharmony_ci	return info->flags;
599d5ac70f0Sopenharmony_ci}
600d5ac70f0Sopenharmony_ci
601d5ac70f0Sopenharmony_ci/**
602d5ac70f0Sopenharmony_ci * \brief get UMP block direction
603d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_block_info_t structure
604d5ac70f0Sopenharmony_ci * \return direction of UMP block (input,output,bidirectional)
605d5ac70f0Sopenharmony_ci */
606d5ac70f0Sopenharmony_ciunsigned int snd_ump_block_info_get_direction(const snd_ump_block_info_t *info)
607d5ac70f0Sopenharmony_ci{
608d5ac70f0Sopenharmony_ci	return info->direction;
609d5ac70f0Sopenharmony_ci}
610d5ac70f0Sopenharmony_ci
611d5ac70f0Sopenharmony_ci/**
612d5ac70f0Sopenharmony_ci * \brief get first UMP group ID belonging to the block
613d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_block_info_t structure
614d5ac70f0Sopenharmony_ci * \return the first UMP group ID belonging to the block
615d5ac70f0Sopenharmony_ci */
616d5ac70f0Sopenharmony_ciunsigned int snd_ump_block_info_get_first_group(const snd_ump_block_info_t *info)
617d5ac70f0Sopenharmony_ci{
618d5ac70f0Sopenharmony_ci	return info->first_group;
619d5ac70f0Sopenharmony_ci}
620d5ac70f0Sopenharmony_ci
621d5ac70f0Sopenharmony_ci/**
622d5ac70f0Sopenharmony_ci * \brief get number of UMP groups belonging to the block
623d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_block_info_t structure
624d5ac70f0Sopenharmony_ci * \return the number of UMP groups belonging to the block
625d5ac70f0Sopenharmony_ci */
626d5ac70f0Sopenharmony_ciunsigned int snd_ump_block_info_get_num_groups(const snd_ump_block_info_t *info)
627d5ac70f0Sopenharmony_ci{
628d5ac70f0Sopenharmony_ci	return info->num_groups;
629d5ac70f0Sopenharmony_ci}
630d5ac70f0Sopenharmony_ci
631d5ac70f0Sopenharmony_ci/**
632d5ac70f0Sopenharmony_ci * \brief get MIDI-CI version number
633d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_block_info_t structure
634d5ac70f0Sopenharmony_ci * \return MIDI-CI version number
635d5ac70f0Sopenharmony_ci */
636d5ac70f0Sopenharmony_ciunsigned int snd_ump_block_info_get_midi_ci_version(const snd_ump_block_info_t *info)
637d5ac70f0Sopenharmony_ci{
638d5ac70f0Sopenharmony_ci	return info->midi_ci_version;
639d5ac70f0Sopenharmony_ci}
640d5ac70f0Sopenharmony_ci
641d5ac70f0Sopenharmony_ci/**
642d5ac70f0Sopenharmony_ci * \brief get number of supported SysEx8 streams
643d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_block_info_t structure
644d5ac70f0Sopenharmony_ci * \return number of supported SysEx8 streams
645d5ac70f0Sopenharmony_ci */
646d5ac70f0Sopenharmony_ciunsigned int snd_ump_block_info_get_sysex8_streams(const snd_ump_block_info_t *info)
647d5ac70f0Sopenharmony_ci{
648d5ac70f0Sopenharmony_ci	return info->sysex8_streams;
649d5ac70f0Sopenharmony_ci}
650d5ac70f0Sopenharmony_ci
651d5ac70f0Sopenharmony_ci/**
652d5ac70f0Sopenharmony_ci * \brief get UI hint of the given UMP block
653d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_block_info_t structure
654d5ac70f0Sopenharmony_ci * \return the hint bits
655d5ac70f0Sopenharmony_ci */
656d5ac70f0Sopenharmony_ciunsigned int snd_ump_block_info_get_ui_hint(const snd_ump_block_info_t *info)
657d5ac70f0Sopenharmony_ci{
658d5ac70f0Sopenharmony_ci	return info->ui_hint;
659d5ac70f0Sopenharmony_ci}
660d5ac70f0Sopenharmony_ci
661d5ac70f0Sopenharmony_ci/**
662d5ac70f0Sopenharmony_ci * \brief get the name string of UMP block
663d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_block_info_t structure
664d5ac70f0Sopenharmony_ci * \return the name string of UMP block
665d5ac70f0Sopenharmony_ci */
666d5ac70f0Sopenharmony_ciconst char *snd_ump_block_info_get_name(const snd_ump_block_info_t *info)
667d5ac70f0Sopenharmony_ci{
668d5ac70f0Sopenharmony_ci	return (const char *)info->name;
669d5ac70f0Sopenharmony_ci}
670d5ac70f0Sopenharmony_ci
671d5ac70f0Sopenharmony_ci/**
672d5ac70f0Sopenharmony_ci * \brief get UMP block information
673d5ac70f0Sopenharmony_ci * \param ump UMP handle
674d5ac70f0Sopenharmony_ci * \param info pointer to a snd_ump_block_info_t structure
675d5ac70f0Sopenharmony_ci * \return 0 on success otherwise a negative error code
676d5ac70f0Sopenharmony_ci *
677d5ac70f0Sopenharmony_ci * The caller should fill the block ID to query at first via
678d5ac70f0Sopenharmony_ci * snd_ump_block_info_set_block_id().
679d5ac70f0Sopenharmony_ci */
680d5ac70f0Sopenharmony_ciint snd_ump_block_info(snd_ump_t *ump, snd_ump_block_info_t *info)
681d5ac70f0Sopenharmony_ci{
682d5ac70f0Sopenharmony_ci	return _snd_rawmidi_ump_block_info(ump->rawmidi, info);
683d5ac70f0Sopenharmony_ci}
684d5ac70f0Sopenharmony_ci
685d5ac70f0Sopenharmony_ci/*
686d5ac70f0Sopenharmony_ci * UMP sysex helpers
687d5ac70f0Sopenharmony_ci */
688d5ac70f0Sopenharmony_cistatic int expand_sysex_data(const uint32_t *data, uint8_t *buf,
689d5ac70f0Sopenharmony_ci			     size_t maxlen, unsigned char bytes, int offset)
690d5ac70f0Sopenharmony_ci{
691d5ac70f0Sopenharmony_ci	int size = 0;
692d5ac70f0Sopenharmony_ci
693d5ac70f0Sopenharmony_ci	for (; bytes; bytes--, size++) {
694d5ac70f0Sopenharmony_ci		if (!maxlen)
695d5ac70f0Sopenharmony_ci			break;
696d5ac70f0Sopenharmony_ci		buf[size] = (*data >> offset) & 0x7f;
697d5ac70f0Sopenharmony_ci		if (!offset) {
698d5ac70f0Sopenharmony_ci			offset = 24;
699d5ac70f0Sopenharmony_ci			data++;
700d5ac70f0Sopenharmony_ci		} else {
701d5ac70f0Sopenharmony_ci			offset -= 8;
702d5ac70f0Sopenharmony_ci		}
703d5ac70f0Sopenharmony_ci	}
704d5ac70f0Sopenharmony_ci
705d5ac70f0Sopenharmony_ci	return size;
706d5ac70f0Sopenharmony_ci}
707d5ac70f0Sopenharmony_ci
708d5ac70f0Sopenharmony_cistatic int expand_sysex7(const uint32_t *ump, uint8_t *buf, size_t maxlen,
709d5ac70f0Sopenharmony_ci			 size_t *filled)
710d5ac70f0Sopenharmony_ci{
711d5ac70f0Sopenharmony_ci	unsigned char status;
712d5ac70f0Sopenharmony_ci	unsigned char bytes;
713d5ac70f0Sopenharmony_ci
714d5ac70f0Sopenharmony_ci	*filled = 0;
715d5ac70f0Sopenharmony_ci	if (!maxlen)
716d5ac70f0Sopenharmony_ci		return 0;
717d5ac70f0Sopenharmony_ci
718d5ac70f0Sopenharmony_ci	status = snd_ump_sysex_msg_status(ump);
719d5ac70f0Sopenharmony_ci	bytes = snd_ump_sysex_msg_length(ump);
720d5ac70f0Sopenharmony_ci	if (bytes > 6)
721d5ac70f0Sopenharmony_ci		return 0; // invalid - skip
722d5ac70f0Sopenharmony_ci
723d5ac70f0Sopenharmony_ci	*filled = expand_sysex_data(ump, buf, maxlen, bytes, 8);
724d5ac70f0Sopenharmony_ci	return (status == SND_UMP_SYSEX_STATUS_SINGLE ||
725d5ac70f0Sopenharmony_ci		status == SND_UMP_SYSEX_STATUS_END);
726d5ac70f0Sopenharmony_ci}
727d5ac70f0Sopenharmony_ci
728d5ac70f0Sopenharmony_cistatic int expand_sysex8(const uint32_t *ump, uint8_t *buf, size_t maxlen,
729d5ac70f0Sopenharmony_ci			  size_t *filled)
730d5ac70f0Sopenharmony_ci{
731d5ac70f0Sopenharmony_ci	unsigned char status;
732d5ac70f0Sopenharmony_ci	unsigned char bytes;
733d5ac70f0Sopenharmony_ci
734d5ac70f0Sopenharmony_ci	*filled = 0;
735d5ac70f0Sopenharmony_ci	if (!maxlen)
736d5ac70f0Sopenharmony_ci		return 0;
737d5ac70f0Sopenharmony_ci
738d5ac70f0Sopenharmony_ci	status = snd_ump_sysex_msg_status(ump);
739d5ac70f0Sopenharmony_ci	if (status > SND_UMP_SYSEX_STATUS_END)
740d5ac70f0Sopenharmony_ci		return 0; // unsupported, skip
741d5ac70f0Sopenharmony_ci	bytes = snd_ump_sysex_msg_length(ump);
742d5ac70f0Sopenharmony_ci	if (!bytes || bytes > 14)
743d5ac70f0Sopenharmony_ci		return 0; // skip
744d5ac70f0Sopenharmony_ci
745d5ac70f0Sopenharmony_ci	*filled = expand_sysex_data(ump, buf, maxlen, bytes - 1, 0);
746d5ac70f0Sopenharmony_ci	return (status == SND_UMP_SYSEX_STATUS_SINGLE ||
747d5ac70f0Sopenharmony_ci		status == SND_UMP_SYSEX_STATUS_END);
748d5ac70f0Sopenharmony_ci}
749d5ac70f0Sopenharmony_ci
750d5ac70f0Sopenharmony_ci/**
751d5ac70f0Sopenharmony_ci * \brief fill sysex byte from a UMP packet
752d5ac70f0Sopenharmony_ci * \param ump UMP packet pointer
753d5ac70f0Sopenharmony_ci * \param buf buffer point to fill sysex bytes
754d5ac70f0Sopenharmony_ci * \param maxlen max buffer size in bytes
755d5ac70f0Sopenharmony_ci * \param filled the size of filled sysex bytes on the buffer
756d5ac70f0Sopenharmony_ci * \return 1 if the sysex finished, otherwise 0
757d5ac70f0Sopenharmony_ci */
758d5ac70f0Sopenharmony_ciint snd_ump_msg_sysex_expand(const uint32_t *ump, uint8_t *buf, size_t maxlen,
759d5ac70f0Sopenharmony_ci			     size_t *filled)
760d5ac70f0Sopenharmony_ci{
761d5ac70f0Sopenharmony_ci	switch (snd_ump_msg_type(ump)) {
762d5ac70f0Sopenharmony_ci	case SND_UMP_MSG_TYPE_DATA:
763d5ac70f0Sopenharmony_ci		return expand_sysex7(ump, buf, maxlen, filled);
764d5ac70f0Sopenharmony_ci	case SND_UMP_MSG_TYPE_EXTENDED_DATA:
765d5ac70f0Sopenharmony_ci		return expand_sysex8(ump, buf, maxlen, filled);
766d5ac70f0Sopenharmony_ci	default:
767d5ac70f0Sopenharmony_ci		return -EINVAL;
768d5ac70f0Sopenharmony_ci	}
769d5ac70f0Sopenharmony_ci}
770