1// Copyright 2016 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <zircon/device/midi.h>
6#include <dirent.h>
7#include <fcntl.h>
8#include <stdbool.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <unistd.h>
13#include <zircon/types.h>
14
15#define DEV_MIDI   "/dev/class/midi"
16
17static bool open_devices(int* out_src_fd, int* out_dest_fd) {
18    int src_fd = -1;
19    int dest_fd = -1;
20
21    struct dirent* de;
22    DIR* dir = opendir(DEV_MIDI);
23    if (!dir) {
24        printf("Error opening %s\n", DEV_MIDI);
25        return -1;
26    }
27
28    while ((de = readdir(dir)) != NULL && (src_fd == -1 || dest_fd == -1)) {
29       char devname[128];
30
31        snprintf(devname, sizeof(devname), "%s/%s", DEV_MIDI, de->d_name);
32        int fd = open(devname, O_RDWR);
33        if (fd < 0) {
34            printf("Error opening %s\n", devname);
35            continue;
36        }
37
38        int device_type;
39        int ret = ioctl_midi_get_device_type(fd, &device_type);
40        if (ret != sizeof(device_type)) {
41            printf("ioctl_midi_get_device_type failed for %s\n", devname);
42            close(fd);
43            continue;
44        }
45        if (device_type == MIDI_TYPE_SOURCE) {
46            if (src_fd == -1) {
47                src_fd = fd;
48            } else {
49                close(fd);
50            }
51        } else if (device_type == MIDI_TYPE_SINK) {
52            if (dest_fd == -1) {
53                dest_fd = fd;
54            } else {
55                close(fd);
56            }
57        } else {
58            close(fd);
59        }
60    }
61
62    closedir(dir);
63    if (src_fd == -1) {
64        close(dest_fd);
65        return false;
66    }
67    if (dest_fd == -1) {
68        close(src_fd);
69        return false;
70    }
71
72    *out_src_fd = src_fd;
73    *out_dest_fd = dest_fd;
74    return true;
75}
76
77int main(int argc, char **argv)
78{
79    int src_fd = -1, dest_fd = -1;
80    if (!open_devices(&src_fd, &dest_fd)) {
81        printf("couldn't find a usable MIDI source and sink\n");
82        return -1;
83    }
84
85    while (1) {
86        uint8_t buffer[3];
87
88        int length = read(src_fd, buffer, sizeof(buffer));
89        if (length < 0) break;
90        printf("MIDI event:");
91        for (int i = 0; i < length; i++) {
92            printf(" %02X", buffer[i]);
93        }
94        printf("\n");
95        if (write(dest_fd, buffer, length) < 0) break;
96    }
97
98    close(src_fd);
99    close(dest_fd);
100
101    return 0;
102}
103