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 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