xref: /third_party/alsa-lib/src/rawmidi/rawmidi.c (revision d5ac70f0)
1/**
2 * \file rawmidi/rawmidi.c
3 * \brief RawMidi Interface
4 * \author Jaroslav Kysela <perex@perex.cz>
5 * \author Abramo Bagnara <abramo@alsa-project.org>
6 * \date 2000-2001
7 *
8 * See the \ref rawmidi page for more details.
9 */
10/*
11 *
12 *   This library is free software; you can redistribute it and/or modify
13 *   it under the terms of the GNU Lesser General Public License as
14 *   published by the Free Software Foundation; either version 2.1 of
15 *   the License, or (at your option) any later version.
16 *
17 *   This program is distributed in the hope that it will be useful,
18 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
19 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 *   GNU Lesser General Public License for more details.
21 *
22 *   You should have received a copy of the GNU Lesser General Public
23 *   License along with this library; if not, write to the Free Software
24 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
25 *
26 */
27
28/*! \page rawmidi RawMidi interface
29
30<P>RawMidi Interface is designed to write or read raw (unchanged) MIDI
31data over the MIDI line without any timestamps defined in interface. MIDI
32stands Musical Instrument Digital Interface and more information about
33this standard can be found at http://www.midi.org.
34
35\section rawmidi_general_overview General overview
36
37The rawmidi implementation uses ring buffers to store outgoing and incoming
38MIDI stream. The buffer size is tunable and drivers report underruns for incoming
39stream as well.
40
41\section rawmidi_open Open handling
42
43RawMidi devices are opened exclusively for a selected direction.
44While more than one process may not open a given MIDI device in the same
45direction simultaneously, separate processes may open a single MIDI device
46in different directions (i.e. process one opens a MIDI device in write
47direction and process two opens the same device in read direction).
48
49\subsection rawmidi_open_nonblock Nonblocking open (flag)
50
51Using #SND_RAWMIDI_NONBLOCK flag for snd_rawmidi_open() or snd_rawmidi_open_lconf()
52instruct device driver to return the -EBUSY error when device is already occupied
53with another application. This flag also changes behaviour of snd_rawmidi_write()
54and snd_rawmidi_read() returning -EAGAIN when no more bytes can be processed.
55
56Note: In opposite (default) behaviour, application is blocked until device resources
57are free.
58
59\subsection rawmidi_open_append Append open (flag)
60
61Using #SND_RAWMIDI_APPEND flag (output only) instruct device driver to append
62contents of written buffer - passed by snd_rawmidi_write() - atomically
63to output ring buffer in the kernel space. This flag also means that device
64is not opened exclusively, so more applications can share given rawmidi device.
65Note that applications must send the whole MIDI message including the running status,
66because another writing application might break the MIDI message in the output
67buffer.
68
69\subsection rawmidi_open_sync Sync open (flag)
70
71Using #SND_RAWMIDI_SYNC flag (output only) assures that the contents of output
72buffer specified using snd_rawmidi_write() is always drained before the function
73exits. This behaviour is same like 'snd_rawmidi_write() followed by
74snd_rawmidi_drain() immediately'.
75
76\subsection rawmidi_io I/O handling
77
78There is only standard read/write access to device internal ring buffer. Use
79snd_rawmidi_read() and snd_rawmidi_write() functions to obtain / write MIDI bytes.
80
81\subsection rawmidi_dev_names RawMidi naming conventions
82
83The ALSA library uses a generic string representation for names of devices.
84The devices might be virtual, physical or a mix of both. The generic string
85is passed to \link ::snd_rawmidi_open() \endlink or \link ::snd_rawmidi_open_lconf() \endlink.
86It contains two parts: device name and arguments. Devices and arguments are described
87in configuration files. The usual place for default definitions is at /usr/share/alsa/alsa.conf.
88
89\subsection rawmidi_dev_names_default
90
91The default device is equal to hw device. The defaults are used:
92
93defaults.rawmidi.card 0
94defaults.rawmidi.device 0
95defaults.rawmidi.subdevice -1
96
97These defaults can be freely overwritten in local configuration files.
98
99Example:
100
101\code
102default
103\endcode
104
105\subsection rawmidi_dev_names_hw HW device
106
107The hw device description uses the hw plugin. The three arguments (in order: CARD,DEV,SUBDEV)
108specify card number or identifier, device number and subdevice number (-1 means any).
109
110Example:
111
112\code
113hw
114hw:0
115hw:0,0
116hw:supersonic,1
117hw:soundwave,1,2
118hw:DEV=1,CARD=soundwave,SUBDEV=2
119\endcode
120
121\section read_mode Read mode
122
123Optionally, incoming rawmidi bytes can be marked with timestamps. The library hides
124the kernel implementation (linux kernel 5.14+) and exports
125the \link ::snd_rawmidi_tread() \endlink  function which returns the
126midi bytes marked with the identical timestamp in one iteration.
127
128The timestamping is available only on input streams.
129
130\section rawmidi_examples Examples
131
132The full featured examples with cross-links:
133
134\par Simple input/output test program
135\link example_test_rawmidi example code \endlink
136\par
137This example shows open and read/write rawmidi operations.
138
139*/
140
141/**
142 * \example ../test/rawmidi.c
143 * \anchor example_test_rawmidi
144 * Shows open and read/write rawmidi operations.
145 */
146
147#include "rawmidi_local.h"
148#include <stdio.h>
149#include <stdlib.h>
150#include <stdarg.h>
151#include <unistd.h>
152#include <string.h>
153
154/**
155 * \brief setup the default parameters
156 * \param rawmidi RawMidi handle
157 * \param params pointer to a snd_rawmidi_params_t structure
158 * \return 0 on success otherwise a negative error code
159 */
160static int snd_rawmidi_params_default(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params)
161{
162	assert(rawmidi);
163	assert(params);
164	params->buffer_size = page_size();
165	params->avail_min = 1;
166	params->no_active_sensing = 1;
167	params->mode = 0;
168	memset(params->reserved, 0, sizeof(params->reserved));
169	return 0;
170}
171
172static int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
173				 const char *name, snd_config_t *rawmidi_root,
174				 snd_config_t *rawmidi_conf, int mode)
175{
176	const char *str;
177	char buf[256];
178	int err;
179	snd_config_t *conf, *type_conf = NULL;
180	snd_config_iterator_t i, next;
181	snd_rawmidi_params_t params;
182	const char *id;
183	const char *lib = NULL, *open_name = NULL;
184	int (*open_func)(snd_rawmidi_t **, snd_rawmidi_t **,
185			 const char *, snd_config_t *, snd_config_t *, int) = NULL;
186#ifndef PIC
187	extern void *snd_rawmidi_open_symbols(void);
188#endif
189	if (snd_config_get_type(rawmidi_conf) != SND_CONFIG_TYPE_COMPOUND) {
190		if (name)
191			SNDERR("Invalid type for RAWMIDI %s definition", name);
192		else
193			SNDERR("Invalid type for RAWMIDI definition");
194		return -EINVAL;
195	}
196	err = snd_config_search(rawmidi_conf, "type", &conf);
197	if (err < 0) {
198		SNDERR("type is not defined");
199		return err;
200	}
201	err = snd_config_get_id(conf, &id);
202	if (err < 0) {
203		SNDERR("unable to get id");
204		return err;
205	}
206	err = snd_config_get_string(conf, &str);
207	if (err < 0) {
208		SNDERR("Invalid type for %s", id);
209		return err;
210	}
211	err = snd_config_search_definition(rawmidi_root, "rawmidi_type", str, &type_conf);
212	if (err >= 0) {
213		if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) {
214			SNDERR("Invalid type for RAWMIDI type %s definition", str);
215			err = -EINVAL;
216			goto _err;
217		}
218		snd_config_for_each(i, next, type_conf) {
219			snd_config_t *n = snd_config_iterator_entry(i);
220			const char *id;
221			if (snd_config_get_id(n, &id) < 0)
222				continue;
223			if (strcmp(id, "comment") == 0)
224				continue;
225			if (strcmp(id, "lib") == 0) {
226				err = snd_config_get_string(n, &lib);
227				if (err < 0) {
228					SNDERR("Invalid type for %s", id);
229					goto _err;
230				}
231				continue;
232			}
233			if (strcmp(id, "open") == 0) {
234				err = snd_config_get_string(n, &open_name);
235				if (err < 0) {
236					SNDERR("Invalid type for %s", id);
237					goto _err;
238				}
239				continue;
240			}
241			SNDERR("Unknown field %s", id);
242			err = -EINVAL;
243			goto _err;
244		}
245	}
246	if (!open_name) {
247		open_name = buf;
248		snprintf(buf, sizeof(buf), "_snd_rawmidi_%s_open", str);
249	}
250#ifndef PIC
251	snd_rawmidi_open_symbols();
252#endif
253	open_func = snd_dlobj_cache_get2(lib, open_name,
254			SND_DLSYM_VERSION(SND_RAWMIDI_DLSYM_VERSION), 1);
255	if (!open_func) {
256		err = -ENXIO;
257		goto _err;
258	}
259	if (type_conf)
260		snd_config_delete(type_conf);
261	err = open_func(inputp, outputp, name, rawmidi_root, rawmidi_conf, mode);
262	if (err < 0)
263		goto _err;
264	if (inputp) {
265		(*inputp)->open_func = open_func;
266		snd_rawmidi_params_default(*inputp, &params);
267		err = snd_rawmidi_params(*inputp, &params);
268		assert(err >= 0);
269	}
270	if (outputp) {
271		(*outputp)->open_func = open_func;
272		snd_rawmidi_params_default(*outputp, &params);
273		err = snd_rawmidi_params(*outputp, &params);
274		assert(err >= 0);
275	}
276	return 0;
277
278       _err:
279	if (open_func)
280		snd_dlobj_cache_put(open_func);
281	if (type_conf)
282		snd_config_delete(type_conf);
283	return err;
284}
285
286static int snd_rawmidi_open_noupdate(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
287				     snd_config_t *root, const char *name, int mode)
288{
289	int err;
290	snd_config_t *rawmidi_conf;
291	err = snd_config_search_definition(root, "rawmidi", name, &rawmidi_conf);
292	if (err < 0) {
293		SNDERR("Unknown RawMidi %s", name);
294		return err;
295	}
296	err = snd_rawmidi_open_conf(inputp, outputp, name, root, rawmidi_conf, mode);
297	snd_config_delete(rawmidi_conf);
298	return err;
299}
300
301/**
302 * \brief Opens a new connection to the RawMidi interface.
303 * \param inputp Returned input handle (NULL if not wanted)
304 * \param outputp Returned output handle (NULL if not wanted)
305 * \param name ASCII identifier of the RawMidi handle
306 * \param mode Open mode
307 * \return 0 on success otherwise a negative error code
308 *
309 * Opens a new connection to the RawMidi interface specified with
310 * an ASCII identifier and mode.
311 */
312int snd_rawmidi_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
313		     const char *name, int mode)
314{
315	snd_config_t *top;
316	int err;
317
318	assert((inputp || outputp) && name);
319	if (_snd_is_ucm_device(name)) {
320		name = uc_mgr_alibcfg_by_device(&top, name);
321		if (name == NULL)
322			return -ENODEV;
323	} else {
324		err = snd_config_update_ref(&top);
325		if (err < 0)
326			return err;
327	}
328	err = snd_rawmidi_open_noupdate(inputp, outputp, top, name, mode);
329	snd_config_unref(top);
330	return err;
331}
332
333/**
334 * \brief Opens a new connection to the RawMidi interface using local configuration
335 * \param inputp Returned input handle (NULL if not wanted)
336 * \param outputp Returned output handle (NULL if not wanted)
337 * \param name ASCII identifier of the RawMidi handle
338 * \param mode Open mode
339 * \param lconf Local configuration
340 * \return 0 on success otherwise a negative error code
341 *
342 * Opens a new connection to the RawMidi interface specified with
343 * an ASCII identifier and mode.
344 */
345int snd_rawmidi_open_lconf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
346			   const char *name, int mode, snd_config_t *lconf)
347{
348	assert((inputp || outputp) && name && lconf);
349	return snd_rawmidi_open_noupdate(inputp, outputp, lconf, name, mode);
350}
351
352/**
353 * \brief close RawMidi handle
354 * \param rawmidi RawMidi handle
355 * \return 0 on success otherwise a negative error code
356 *
357 * Closes the specified RawMidi handle and frees all associated
358 * resources.
359 */
360int snd_rawmidi_close(snd_rawmidi_t *rawmidi)
361{
362	int err;
363  	assert(rawmidi);
364	err = rawmidi->ops->close(rawmidi);
365	free(rawmidi->name);
366	if (rawmidi->open_func)
367		snd_dlobj_cache_put(rawmidi->open_func);
368	free(rawmidi);
369	return err;
370}
371
372/**
373 * \brief get identifier of RawMidi handle
374 * \param rawmidi a RawMidi handle
375 * \return ascii identifier of RawMidi handle
376 *
377 * Returns the ASCII identifier of given RawMidi handle. It's the same
378 * identifier specified in snd_rawmidi_open().
379 */
380const char *snd_rawmidi_name(snd_rawmidi_t *rawmidi)
381{
382	assert(rawmidi);
383	return rawmidi->name;
384}
385
386/**
387 * \brief get type of RawMidi handle
388 * \param rawmidi a RawMidi handle
389 * \return type of RawMidi handle
390 *
391 * Returns the type #snd_rawmidi_type_t of given RawMidi handle.
392 */
393snd_rawmidi_type_t snd_rawmidi_type(snd_rawmidi_t *rawmidi)
394{
395	assert(rawmidi);
396	return rawmidi->type;
397}
398
399/**
400 * \brief get stream (direction) of RawMidi handle
401 * \param rawmidi a RawMidi handle
402 * \return stream of RawMidi handle
403 *
404 * Returns the stream #snd_rawmidi_stream_t of given RawMidi handle.
405 */
406snd_rawmidi_stream_t snd_rawmidi_stream(snd_rawmidi_t *rawmidi)
407{
408	assert(rawmidi);
409	return rawmidi->stream;
410}
411
412/**
413 * \brief get count of poll descriptors for RawMidi handle
414 * \param rawmidi RawMidi handle
415 * \return count of poll descriptors
416 */
417int snd_rawmidi_poll_descriptors_count(snd_rawmidi_t *rawmidi)
418{
419	assert(rawmidi);
420	return 1;
421}
422
423/**
424 * \brief get poll descriptors
425 * \param rawmidi RawMidi handle
426 * \param pfds array of poll descriptors
427 * \param space space in the poll descriptor array
428 * \return count of filled descriptors
429 */
430int snd_rawmidi_poll_descriptors(snd_rawmidi_t *rawmidi, struct pollfd *pfds, unsigned int space)
431{
432	assert(rawmidi);
433	if (space >= 1) {
434		pfds->fd = rawmidi->poll_fd;
435		pfds->events = rawmidi->stream == SND_RAWMIDI_STREAM_OUTPUT ? (POLLOUT|POLLERR|POLLNVAL) : (POLLIN|POLLERR|POLLNVAL);
436		return 1;
437	}
438	return 0;
439}
440
441/**
442 * \brief get returned events from poll descriptors
443 * \param rawmidi rawmidi RawMidi handle
444 * \param pfds array of poll descriptors
445 * \param nfds count of poll descriptors
446 * \param revents returned events
447 * \return zero if success, otherwise a negative error code
448 */
449int snd_rawmidi_poll_descriptors_revents(snd_rawmidi_t *rawmidi, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
450{
451        assert(rawmidi && pfds && revents);
452        if (nfds == 1) {
453                *revents = pfds->revents;
454                return 0;
455        }
456        return -EINVAL;
457}
458
459/**
460 * \brief set nonblock mode
461 * \param rawmidi RawMidi handle
462 * \param nonblock 0 = block, 1 = nonblock mode
463 * \return 0 on success otherwise a negative error code
464 *
465 * The nonblock mode cannot be used when the stream is in
466 * #SND_RAWMIDI_APPEND state.
467 */
468int snd_rawmidi_nonblock(snd_rawmidi_t *rawmidi, int nonblock)
469{
470	int err;
471	assert(rawmidi);
472	assert(!(rawmidi->mode & SND_RAWMIDI_APPEND));
473	if ((err = rawmidi->ops->nonblock(rawmidi, nonblock)) < 0)
474		return err;
475	if (nonblock)
476		rawmidi->mode |= SND_RAWMIDI_NONBLOCK;
477	else
478		rawmidi->mode &= ~SND_RAWMIDI_NONBLOCK;
479	return 0;
480}
481
482/**
483 * \brief get size of the snd_rawmidi_info_t structure in bytes
484 * \return size of the snd_rawmidi_info_t structure in bytes
485 */
486size_t snd_rawmidi_info_sizeof()
487{
488	return sizeof(snd_rawmidi_info_t);
489}
490
491/**
492 * \brief allocate a new snd_rawmidi_info_t structure
493 * \param info returned pointer
494 * \return 0 on success otherwise a negative error code if fails
495 *
496 * Allocates a new snd_rawmidi_params_t structure using the standard
497 * malloc C library function.
498 */
499int snd_rawmidi_info_malloc(snd_rawmidi_info_t **info)
500{
501	assert(info);
502	*info = calloc(1, sizeof(snd_rawmidi_info_t));
503	if (!*info)
504		return -ENOMEM;
505	return 0;
506}
507
508/**
509 * \brief frees the snd_rawmidi_info_t structure
510 * \param info pointer to the snd_rawmidi_info_t structure to free
511 *
512 * Frees the given snd_rawmidi_params_t structure using the standard
513 * free C library function.
514 */
515void snd_rawmidi_info_free(snd_rawmidi_info_t *info)
516{
517	assert(info);
518	free(info);
519}
520
521/**
522 * \brief copy one snd_rawmidi_info_t structure to another
523 * \param dst destination snd_rawmidi_info_t structure
524 * \param src source snd_rawmidi_info_t structure
525 */
526void snd_rawmidi_info_copy(snd_rawmidi_info_t *dst, const snd_rawmidi_info_t *src)
527{
528	assert(dst && src);
529	*dst = *src;
530}
531
532/**
533 * \brief get rawmidi device number
534 * \param info pointer to a snd_rawmidi_info_t structure
535 * \return rawmidi device number
536 */
537unsigned int snd_rawmidi_info_get_device(const snd_rawmidi_info_t *info)
538{
539	assert(info);
540	return info->device;
541}
542
543/**
544 * \brief get rawmidi subdevice number
545 * \param info pointer to a snd_rawmidi_info_t structure
546 * \return rawmidi subdevice number
547 */
548unsigned int snd_rawmidi_info_get_subdevice(const snd_rawmidi_info_t *info)
549{
550	assert(info);
551	return info->subdevice;
552}
553
554/**
555 * \brief get rawmidi stream identification
556 * \param info pointer to a snd_rawmidi_info_t structure
557 * \return rawmidi stream identification
558 */
559snd_rawmidi_stream_t snd_rawmidi_info_get_stream(const snd_rawmidi_info_t *info)
560{
561	assert(info);
562	return info->stream;
563}
564
565/**
566 * \brief get rawmidi card number
567 * \param info pointer to a snd_rawmidi_info_t structure
568 * \return rawmidi card number
569 */
570int snd_rawmidi_info_get_card(const snd_rawmidi_info_t *info)
571{
572	assert(info);
573	return info->card;
574}
575
576/**
577 * \brief get rawmidi flags
578 * \param info pointer to a snd_rawmidi_info_t structure
579 * \return rawmidi flags
580 */
581unsigned int snd_rawmidi_info_get_flags(const snd_rawmidi_info_t *info)
582{
583	assert(info);
584	return info->flags;
585}
586
587/**
588 * \brief get rawmidi hardware driver identifier
589 * \param info pointer to a snd_rawmidi_info_t structure
590 * \return rawmidi hardware driver identifier
591 */
592const char *snd_rawmidi_info_get_id(const snd_rawmidi_info_t *info)
593{
594	assert(info);
595	return (const char *)info->id;
596}
597
598/**
599 * \brief get rawmidi hardware driver name
600 * \param info pointer to a snd_rawmidi_info_t structure
601 * \return rawmidi hardware driver name
602 */
603const char *snd_rawmidi_info_get_name(const snd_rawmidi_info_t *info)
604{
605	assert(info);
606	return (const char *)info->name;
607}
608
609/**
610 * \brief get rawmidi subdevice name
611 * \param info pointer to a snd_rawmidi_info_t structure
612 * \return rawmidi subdevice name
613 */
614const char *snd_rawmidi_info_get_subdevice_name(const snd_rawmidi_info_t *info)
615{
616	assert(info);
617	return (const char *)info->subname;
618}
619
620/**
621 * \brief get rawmidi count of subdevices
622 * \param info pointer to a snd_rawmidi_info_t structure
623 * \return rawmidi count of subdevices
624 */
625unsigned int snd_rawmidi_info_get_subdevices_count(const snd_rawmidi_info_t *info)
626{
627	assert(info);
628	return info->subdevices_count;
629}
630
631/**
632 * \brief get rawmidi available count of subdevices
633 * \param info pointer to a snd_rawmidi_info_t structure
634 * \return rawmidi available count of subdevices
635 */
636unsigned int snd_rawmidi_info_get_subdevices_avail(const snd_rawmidi_info_t *info)
637{
638	assert(info);
639	return info->subdevices_avail;
640}
641
642/**
643 * \brief set rawmidi device number
644 * \param info pointer to a snd_rawmidi_info_t structure
645 * \param val device number
646 */
647void snd_rawmidi_info_set_device(snd_rawmidi_info_t *info, unsigned int val)
648{
649	assert(info);
650	info->device = val;
651}
652
653/**
654 * \brief set rawmidi subdevice number
655 * \param info pointer to a snd_rawmidi_info_t structure
656 * \param val subdevice number
657 */
658void snd_rawmidi_info_set_subdevice(snd_rawmidi_info_t *info, unsigned int val)
659{
660	assert(info);
661	info->subdevice = val;
662}
663
664/**
665 * \brief set rawmidi stream identifier
666 * \param info pointer to a snd_rawmidi_info_t structure
667 * \param val rawmidi stream identifier
668 */
669void snd_rawmidi_info_set_stream(snd_rawmidi_info_t *info, snd_rawmidi_stream_t val)
670{
671	assert(info);
672	info->stream = val;
673}
674
675/**
676 * \brief get information about RawMidi handle
677 * \param rawmidi RawMidi handle
678 * \param info pointer to a snd_rawmidi_info_t structure to be filled
679 * \return 0 on success otherwise a negative error code
680 */
681int snd_rawmidi_info(snd_rawmidi_t *rawmidi, snd_rawmidi_info_t * info)
682{
683	assert(rawmidi);
684	assert(info);
685	return rawmidi->ops->info(rawmidi, info);
686}
687
688/**
689 * \brief get size of the snd_rawmidi_params_t structure in bytes
690 * \return size of the snd_rawmidi_params_t structure in bytes
691 */
692size_t snd_rawmidi_params_sizeof()
693{
694	return sizeof(snd_rawmidi_params_t);
695}
696
697/**
698 * \brief allocate the snd_rawmidi_params_t structure
699 * \param params returned pointer
700 * \return 0 on success otherwise a negative error code if fails
701 *
702 * Allocates a new snd_rawmidi_params_t structure using the standard
703 * malloc C library function.
704 */
705int snd_rawmidi_params_malloc(snd_rawmidi_params_t **params)
706{
707	assert(params);
708	*params = calloc(1, sizeof(snd_rawmidi_params_t));
709	if (!*params)
710		return -ENOMEM;
711	return 0;
712}
713
714/**
715 * \brief frees the snd_rawmidi_params_t structure
716 * \param params pointer to the #snd_rawmidi_params_t structure to free
717 *
718 * Frees the given snd_rawmidi_params_t structure using the standard
719 * free C library function.
720 */
721void snd_rawmidi_params_free(snd_rawmidi_params_t *params)
722{
723	assert(params);
724	free(params);
725}
726
727/**
728 * \brief copy one snd_rawmidi_params_t structure to another
729 * \param dst destination snd_rawmidi_params_t structure
730 * \param src source snd_rawmidi_params_t structure
731 */
732void snd_rawmidi_params_copy(snd_rawmidi_params_t *dst, const snd_rawmidi_params_t *src)
733{
734	assert(dst && src);
735	*dst = *src;
736}
737
738/**
739 * \brief set rawmidi I/O ring buffer size
740 * \param rawmidi RawMidi handle
741 * \param params pointer to a snd_rawmidi_params_t structure
742 * \param val size in bytes
743 * \return 0 on success otherwise a negative error code
744 */
745#ifndef DOXYGEN
746int snd_rawmidi_params_set_buffer_size(snd_rawmidi_t *rawmidi ATTRIBUTE_UNUSED, snd_rawmidi_params_t *params, size_t val)
747#else
748int snd_rawmidi_params_set_buffer_size(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, size_t val)
749#endif
750{
751	assert(rawmidi && params);
752	assert(val > params->avail_min);
753	params->buffer_size = val;
754	return 0;
755}
756
757/**
758 * \brief get rawmidi I/O ring buffer size
759 * \param params pointer to a snd_rawmidi_params_t structure
760 * \return size of rawmidi I/O ring buffer in bytes
761 */
762size_t snd_rawmidi_params_get_buffer_size(const snd_rawmidi_params_t *params)
763{
764	assert(params);
765	return params->buffer_size;
766}
767
768/**
769 * \brief set minimum available bytes in rawmidi I/O ring buffer for wakeup
770 * \param rawmidi RawMidi handle
771 * \param params pointer to a snd_rawmidi_params_t structure
772 * \param val desired value
773 */
774#ifndef DOXYGEN
775int snd_rawmidi_params_set_avail_min(snd_rawmidi_t *rawmidi ATTRIBUTE_UNUSED, snd_rawmidi_params_t *params, size_t val)
776#else
777int snd_rawmidi_params_set_avail_min(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, size_t val)
778#endif
779{
780	assert(rawmidi && params);
781	assert(val < params->buffer_size);
782	params->avail_min = val;
783	return 0;
784}
785
786/**
787 * \brief get minimum available bytes in rawmidi I/O ring buffer for wakeup
788 * \param params pointer to snd_rawmidi_params_t structure
789 * \return minimum available bytes
790 */
791size_t snd_rawmidi_params_get_avail_min(const snd_rawmidi_params_t *params)
792{
793	assert(params);
794	return params->avail_min;
795}
796
797/**
798 * \brief set no-active-sensing action on snd_rawmidi_close()
799 * \param rawmidi RawMidi handle
800 * \param params pointer to snd_rawmidi_params_t structure
801 * \param val value: 0 = enable to send the active sensing message, 1 = disable
802 * \return 0 on success otherwise a negative error code
803 */
804#ifndef DOXYGEN
805int snd_rawmidi_params_set_no_active_sensing(snd_rawmidi_t *rawmidi ATTRIBUTE_UNUSED, snd_rawmidi_params_t *params, int val)
806#else
807int snd_rawmidi_params_set_no_active_sensing(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, int val)
808#endif
809{
810	assert(rawmidi && params);
811	params->no_active_sensing = val;
812	return 0;
813}
814
815/**
816 * \brief get no-active-sensing action status
817 * \param params pointer to snd_rawmidi_params_t structure
818 * \return the current status (0 = enable, 1 = disable the active sensing message)
819 */
820int snd_rawmidi_params_get_no_active_sensing(const snd_rawmidi_params_t *params)
821{
822	assert(params);
823	return params->no_active_sensing;
824}
825
826/**
827 * \brief set read mode
828 * \param rawmidi RawMidi handle
829 * \param params pointer to snd_rawmidi_params_t structure
830 * \param val type of read_mode
831 * \return 0 on success, otherwise a negative error code.
832 *
833 * Notable error codes:
834 * -EINVAL - "val" is invalid
835 * -ENOTSUP - mode is not supported
836 *
837 */
838int snd_rawmidi_params_set_read_mode(const snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, snd_rawmidi_read_mode_t val)
839{
840	unsigned int framing;
841	assert(rawmidi && params);
842
843	switch (val) {
844	case SND_RAWMIDI_READ_STANDARD:
845		framing = SNDRV_RAWMIDI_MODE_FRAMING_NONE;
846		break;
847	case SND_RAWMIDI_READ_TSTAMP:
848		if (rawmidi->ops->tread == NULL)
849			return -ENOTSUP;
850		framing = SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP;
851		break;
852	default:
853		return -EINVAL;
854	}
855
856	if (framing != SNDRV_RAWMIDI_MODE_FRAMING_NONE &&
857		(rawmidi->version < SNDRV_PROTOCOL_VERSION(2, 0, 2) || rawmidi->stream != SND_RAWMIDI_STREAM_INPUT))
858		return -ENOTSUP;
859	params->mode = (params->mode & ~SNDRV_RAWMIDI_MODE_FRAMING_MASK) | framing;
860	return 0;
861}
862
863/**
864 * \brief get current read mode
865 * \param params pointer to snd_rawmidi_params_t structure
866 * \return the current read mode (see enum)
867 */
868snd_rawmidi_read_mode_t snd_rawmidi_params_get_read_mode(const snd_rawmidi_params_t *params)
869{
870	unsigned int framing;
871
872	assert(params);
873	framing = params->mode & SNDRV_RAWMIDI_MODE_FRAMING_MASK;
874	if (framing == SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP)
875		return SND_RAWMIDI_READ_TSTAMP;
876	return SND_RAWMIDI_READ_STANDARD;
877}
878
879/**
880 * \brief sets clock type for tstamp type framing
881 * \param rawmidi RawMidi handle
882 * \param params pointer to snd_rawmidi_params_t structure
883 * \param val one of the SND_RAWMIDI_CLOCK_* constants
884 * \return 0 on success, otherwise a negative error code.
885 *
886 * Notable error codes:
887 * -EINVAL - "val" is invalid
888 * -ENOTSUP - Kernel is too old to support framing.
889 *
890 */
891int snd_rawmidi_params_set_clock_type(const snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, snd_rawmidi_clock_t val)
892{
893	assert(rawmidi && params);
894	if (val > SNDRV_RAWMIDI_MODE_CLOCK_MASK >> SNDRV_RAWMIDI_MODE_CLOCK_SHIFT)
895		return -EINVAL;
896	if (val != SNDRV_RAWMIDI_MODE_CLOCK_NONE &&
897		(rawmidi->version < SNDRV_PROTOCOL_VERSION(2, 0, 2) || rawmidi->stream != SND_RAWMIDI_STREAM_INPUT))
898		return -ENOTSUP;
899	params->mode = (params->mode & ~SNDRV_RAWMIDI_MODE_CLOCK_MASK) + (val << SNDRV_RAWMIDI_MODE_CLOCK_SHIFT);
900	return 0;
901}
902
903/**
904 * \brief get current clock type (for tstamp type framing)
905 * \param params pointer to snd_rawmidi_params_t structure
906 * \return the current clock type (one of the SND_RAWMIDI_CLOCK_* constants)
907 */
908snd_rawmidi_clock_t snd_rawmidi_params_get_clock_type(const snd_rawmidi_params_t *params)
909{
910	assert(params);
911	return (params->mode & SNDRV_RAWMIDI_MODE_CLOCK_MASK) >> SNDRV_RAWMIDI_MODE_CLOCK_SHIFT;
912}
913
914
915/**
916 * \brief set parameters about rawmidi stream
917 * \param rawmidi RawMidi handle
918 * \param params pointer to a snd_rawmidi_params_t structure to be filled
919 * \return 0 on success otherwise a negative error code
920 */
921int snd_rawmidi_params(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t * params)
922{
923	int err;
924	assert(rawmidi);
925	assert(params);
926	err = rawmidi->ops->params(rawmidi, params);
927	if (err < 0)
928		return err;
929	rawmidi->buffer_size = params->buffer_size;
930	rawmidi->avail_min = params->avail_min;
931	rawmidi->no_active_sensing = params->no_active_sensing;
932	rawmidi->params_mode = rawmidi->version < SNDRV_PROTOCOL_VERSION(2, 0, 2) ? 0 : params->mode;
933	return 0;
934}
935
936/**
937 * \brief get current parameters about rawmidi stream
938 * \param rawmidi RawMidi handle
939 * \param params pointer to a snd_rawmidi_params_t structure to be filled
940 * \return 0 on success otherwise a negative error code
941 */
942int snd_rawmidi_params_current(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params)
943{
944	assert(rawmidi);
945	assert(params);
946	params->buffer_size = rawmidi->buffer_size;
947	params->avail_min = rawmidi->avail_min;
948	params->no_active_sensing = rawmidi->no_active_sensing;
949	params->mode = rawmidi->params_mode;
950	return 0;
951}
952
953/**
954 * \brief get size of the snd_rawmidi_status_t structure in bytes
955 * \return size of the snd_rawmidi_status_t structure in bytes
956 */
957size_t snd_rawmidi_status_sizeof()
958{
959	return sizeof(snd_rawmidi_status_t);
960}
961
962/**
963 * \brief allocate the snd_rawmidi_status_t structure
964 * \param ptr returned pointer
965 * \return 0 on success otherwise a negative error code if fails
966 *
967 * Allocates a new snd_rawmidi_status_t structure using the standard
968 * malloc C library function.
969 */
970int snd_rawmidi_status_malloc(snd_rawmidi_status_t **ptr)
971{
972	assert(ptr);
973	*ptr = calloc(1, sizeof(snd_rawmidi_status_t));
974	if (!*ptr)
975		return -ENOMEM;
976	return 0;
977}
978
979/**
980 * \brief frees the snd_rawmidi_status_t structure
981 * \param status pointer to the snd_rawmidi_status_t structure to free
982 *
983 * Frees the given snd_rawmidi_status_t structure using the standard
984 * free C library function.
985 */
986void snd_rawmidi_status_free(snd_rawmidi_status_t *status)
987{
988	assert(status);
989	free(status);
990}
991
992/**
993 * \brief copy one snd_rawmidi_status_t structure to another
994 * \param dst destination snd_rawmidi_status_t structure
995 * \param src source snd_rawmidi_status_t structure
996 */
997void snd_rawmidi_status_copy(snd_rawmidi_status_t *dst, const snd_rawmidi_status_t *src)
998{
999	assert(dst && src);
1000	*dst = *src;
1001}
1002
1003/**
1004 * \brief get the start timestamp
1005 * \param status pointer to a snd_rawmidi_status_t structure
1006 * \param tstamp returned timestamp value
1007 */
1008void snd_rawmidi_status_get_tstamp(const snd_rawmidi_status_t *status, snd_htimestamp_t *tstamp)
1009{
1010	assert(status && tstamp);
1011	*tstamp = status->tstamp;
1012}
1013
1014/**
1015 * \brief get current available bytes in the rawmidi I/O ring buffer
1016 * \param status pointer to a snd_rawmidi_status_t structure
1017 * \return current available bytes in the rawmidi I/O ring buffer
1018 */
1019size_t snd_rawmidi_status_get_avail(const snd_rawmidi_status_t *status)
1020{
1021	assert(status);
1022	return status->avail;
1023}
1024
1025/**
1026 * \brief get count of xruns
1027 * \param status pointer to a snd_rawmidi_status_t structure
1028 * \return count of xruns
1029 */
1030size_t snd_rawmidi_status_get_xruns(const snd_rawmidi_status_t *status)
1031{
1032	assert(status);
1033	return status->xruns;
1034}
1035
1036/**
1037 * \brief get status of rawmidi stream
1038 * \param rawmidi RawMidi handle
1039 * \param status pointer to a snd_rawmidi_status_t structure to be filled
1040 * \return 0 on success otherwise a negative error code
1041 */
1042int snd_rawmidi_status(snd_rawmidi_t *rawmidi, snd_rawmidi_status_t * status)
1043{
1044	assert(rawmidi);
1045	assert(status);
1046	return rawmidi->ops->status(rawmidi, status);
1047}
1048
1049/**
1050 * \brief drop all bytes in the rawmidi I/O ring buffer immediately
1051 * \param rawmidi RawMidi handle
1052 * \return 0 on success otherwise a negative error code
1053 */
1054int snd_rawmidi_drop(snd_rawmidi_t *rawmidi)
1055{
1056	assert(rawmidi);
1057	return rawmidi->ops->drop(rawmidi);
1058}
1059
1060/**
1061 * \brief drain all bytes in the rawmidi I/O ring buffer
1062 * \param rawmidi RawMidi handle
1063 * \return 0 on success otherwise a negative error code
1064 *
1065 * Waits until all MIDI bytes are not drained (sent) to the
1066 * hardware device.
1067 */
1068int snd_rawmidi_drain(snd_rawmidi_t *rawmidi)
1069{
1070	assert(rawmidi);
1071	return rawmidi->ops->drain(rawmidi);
1072}
1073
1074/**
1075 * \brief write MIDI bytes to MIDI stream
1076 * \param rawmidi RawMidi handle
1077 * \param buffer buffer containing MIDI bytes
1078 * \param size output buffer size in bytes
1079 */
1080ssize_t snd_rawmidi_write(snd_rawmidi_t *rawmidi, const void *buffer, size_t size)
1081{
1082	assert(rawmidi);
1083	assert(rawmidi->stream == SND_RAWMIDI_STREAM_OUTPUT);
1084	assert(buffer || size == 0);
1085	return rawmidi->ops->write(rawmidi, buffer, size);
1086}
1087
1088/**
1089 * \brief read MIDI bytes from MIDI stream
1090 * \param rawmidi RawMidi handle
1091 * \param buffer buffer to store the input MIDI bytes
1092 * \param size input buffer size in bytes
1093 * \retval count of MIDI bytes otherwise a negative error code
1094 */
1095ssize_t snd_rawmidi_read(snd_rawmidi_t *rawmidi, void *buffer, size_t size)
1096{
1097	assert(rawmidi);
1098	assert(rawmidi->stream == SND_RAWMIDI_STREAM_INPUT);
1099	if ((rawmidi->params_mode & SNDRV_RAWMIDI_MODE_FRAMING_MASK) == SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP)
1100		size &= ~(sizeof(struct snd_rawmidi_framing_tstamp) - 1);
1101	assert(buffer || size == 0);
1102	return (rawmidi->ops->read)(rawmidi, buffer, size);
1103}
1104
1105/**
1106 * \brief read MIDI bytes from MIDI stream with timestamp
1107 * \param rawmidi RawMidi handle
1108 * \param[out] tstamp timestamp for the returned MIDI bytes
1109 * \param buffer buffer to store the input MIDI bytes
1110 * \param size input buffer size in bytes
1111 * \retval count of MIDI bytes otherwise a negative error code
1112 */
1113ssize_t snd_rawmidi_tread(snd_rawmidi_t *rawmidi, struct timespec *tstamp, void *buffer, size_t size)
1114{
1115	assert(rawmidi);
1116	assert(rawmidi->stream == SND_RAWMIDI_STREAM_INPUT);
1117	assert(buffer || size == 0);
1118	if ((rawmidi->params_mode & SNDRV_RAWMIDI_MODE_FRAMING_MASK) != SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP)
1119		return -EINVAL;
1120	if (rawmidi->ops->tread == NULL)
1121		return -ENOTSUP;
1122	return (rawmidi->ops->tread)(rawmidi, tstamp, buffer, size);
1123}
1124
1125#ifndef DOXYGEN
1126/*
1127 * internal API functions for obtaining UMP info from rawmidi instance
1128 */
1129int _snd_rawmidi_ump_endpoint_info(snd_rawmidi_t *rmidi, void *info)
1130{
1131	if (!rmidi->ops->ump_endpoint_info)
1132		return -ENXIO;
1133	return rmidi->ops->ump_endpoint_info(rmidi, info);
1134}
1135
1136int _snd_rawmidi_ump_block_info(snd_rawmidi_t *rmidi, void *info)
1137{
1138	if (!rmidi->ops->ump_block_info)
1139		return -ENXIO;
1140	return rmidi->ops->ump_block_info(rmidi, info);
1141}
1142#endif /* DOXYGEN */
1143