1*6747b1a8SChristos Margiolis /*
2*6747b1a8SChristos Margiolis * SPDX-License-Identifier: BSD-2-Clause
3*6747b1a8SChristos Margiolis *
4*6747b1a8SChristos Margiolis * Copyright (c) 2022 Goran Mekić
5*6747b1a8SChristos Margiolis * Copyright (c) 2024 The FreeBSD Foundation
6*6747b1a8SChristos Margiolis *
7*6747b1a8SChristos Margiolis * Portions of this software were developed by Christos Margiolis
8*6747b1a8SChristos Margiolis * <christos@FreeBSD.org> under sponsorship from the FreeBSD Foundation.
9*6747b1a8SChristos Margiolis *
10*6747b1a8SChristos Margiolis * Redistribution and use in source and binary forms, with or without
11*6747b1a8SChristos Margiolis * modification, are permitted provided that the following conditions
12*6747b1a8SChristos Margiolis * are met:
13*6747b1a8SChristos Margiolis * 1. Redistributions of source code must retain the above copyright
14*6747b1a8SChristos Margiolis * notice, this list of conditions and the following disclaimer.
15*6747b1a8SChristos Margiolis * 2. Redistributions in binary form must reproduce the above copyright
16*6747b1a8SChristos Margiolis * notice, this list of conditions and the following disclaimer in the
17*6747b1a8SChristos Margiolis * documentation and/or other materials provided with the distribution.
18*6747b1a8SChristos Margiolis *
19*6747b1a8SChristos Margiolis * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20*6747b1a8SChristos Margiolis * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*6747b1a8SChristos Margiolis * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*6747b1a8SChristos Margiolis * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23*6747b1a8SChristos Margiolis * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*6747b1a8SChristos Margiolis * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*6747b1a8SChristos Margiolis * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*6747b1a8SChristos Margiolis * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*6747b1a8SChristos Margiolis * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*6747b1a8SChristos Margiolis * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*6747b1a8SChristos Margiolis * SUCH DAMAGE.
30*6747b1a8SChristos Margiolis */
31*6747b1a8SChristos Margiolis
32*6747b1a8SChristos Margiolis #include <err.h>
33*6747b1a8SChristos Margiolis #include <fcntl.h>
34*6747b1a8SChristos Margiolis #include <stdio.h>
35*6747b1a8SChristos Margiolis #include <stdlib.h>
36*6747b1a8SChristos Margiolis #include <unistd.h>
37*6747b1a8SChristos Margiolis
38*6747b1a8SChristos Margiolis #define CMD_MASK 0xF0
39*6747b1a8SChristos Margiolis #define CHANNEL_MASK 0x0F
40*6747b1a8SChristos Margiolis #define NOTE_ON 0x90
41*6747b1a8SChristos Margiolis #define NOTE_OFF 0x80
42*6747b1a8SChristos Margiolis #define CTL_CHANGE 0xB0
43*6747b1a8SChristos Margiolis
44*6747b1a8SChristos Margiolis int
main(int argc,char * argv[])45*6747b1a8SChristos Margiolis main(int argc, char *argv[])
46*6747b1a8SChristos Margiolis {
47*6747b1a8SChristos Margiolis int fd;
48*6747b1a8SChristos Margiolis unsigned char raw, type, channel, b1, b2;
49*6747b1a8SChristos Margiolis
50*6747b1a8SChristos Margiolis if ((fd = open("/dev/umidi0.0", O_RDWR)) < 0)
51*6747b1a8SChristos Margiolis err(1, "Error opening MIDI device");
52*6747b1a8SChristos Margiolis
53*6747b1a8SChristos Margiolis for (;;) {
54*6747b1a8SChristos Margiolis if (read(fd, &raw, sizeof(raw)) < sizeof(raw))
55*6747b1a8SChristos Margiolis err(1, "Error reading command byte");
56*6747b1a8SChristos Margiolis if (!(raw & 0x80))
57*6747b1a8SChristos Margiolis continue;
58*6747b1a8SChristos Margiolis
59*6747b1a8SChristos Margiolis type = raw & CMD_MASK;
60*6747b1a8SChristos Margiolis channel = raw & CHANNEL_MASK;
61*6747b1a8SChristos Margiolis
62*6747b1a8SChristos Margiolis if (read(fd, &b1, sizeof(b1)) < sizeof(b1))
63*6747b1a8SChristos Margiolis err(1, "Error reading byte 1");
64*6747b1a8SChristos Margiolis if (read(fd, &b2, sizeof(b2)) < sizeof(b2))
65*6747b1a8SChristos Margiolis err(1, "Error reading byte 2");
66*6747b1a8SChristos Margiolis
67*6747b1a8SChristos Margiolis switch (type) {
68*6747b1a8SChristos Margiolis case NOTE_ON:
69*6747b1a8SChristos Margiolis printf("Channel %d, note on %d, velocity %d\n",
70*6747b1a8SChristos Margiolis channel, b1, b2);
71*6747b1a8SChristos Margiolis break;
72*6747b1a8SChristos Margiolis case NOTE_OFF:
73*6747b1a8SChristos Margiolis printf("Channel %d, note off %d, velocity %d\n",
74*6747b1a8SChristos Margiolis channel, b1, b2);
75*6747b1a8SChristos Margiolis break;
76*6747b1a8SChristos Margiolis case CTL_CHANGE:
77*6747b1a8SChristos Margiolis printf("Channel %d, controller change %d, value %d\n",
78*6747b1a8SChristos Margiolis channel, b1, b2);
79*6747b1a8SChristos Margiolis break;
80*6747b1a8SChristos Margiolis default:
81*6747b1a8SChristos Margiolis printf("Unknown event type %d\n", type);
82*6747b1a8SChristos Margiolis break;
83*6747b1a8SChristos Margiolis }
84*6747b1a8SChristos Margiolis }
85*6747b1a8SChristos Margiolis
86*6747b1a8SChristos Margiolis close(fd);
87*6747b1a8SChristos Margiolis
88*6747b1a8SChristos Margiolis return (0);
89*6747b1a8SChristos Margiolis }
90