One of the things I've wanted to try is to convert midi into a controller. This gave me an idea: if I can read raw midi bytes from the linux /dev/midi1 device, it shouldn't be difficult at all to convert that to button presses.

A quick and dirty test:

Code
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/uinput.h>
#include <stdlib.h>

#define msleep(ms) usleep((ms)*1000)

// miditest3.c
// midi to uinput button test mapping notes to buttons, and mod/pitch/volume to axes
// by Golden Child
// just maps the low register of the keyboard into button pressess
// using examples from
//
// https://gist.github.com/matthewaveryusa/a721aad80ae89a5c69f7c964fa20fec1
// https://github.com/GrantEdwards/uinput-joystick-demo
// https://www.kernel.org/doc/html/v4.12/input/uinput.html
// https://blog.marekkraus.sk/c/linuxs-uinput-usage-tutorial-virtual-gamepad/


static void setup_abs(int fd, unsigned chan, int min, int max);  

int main(int argc, char* argv[])
{ 
  int midi_fd = open("/dev/midi1", O_RDONLY | O_NONBLOCK);
  
  if (midi_fd < 0)
    {
      perror("open /dev/midi1");
      return 1;
    }  
    
    
  //sleep(1); // wait for a second
  int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
  
  if (fd < 0)
    {
      perror("open /dev/uinput");
      return 1;
    }

  ioctl(fd, UI_SET_EVBIT, EV_KEY); // enable button/key handling

// event codes from linux/input-event-codes.h

int translatetable[] = { 
0xc, BTN_0,
0xd, BTN_1,
0xe, BTN_2,
0xf, BTN_3,
0x10, BTN_4,
0x11, BTN_5,
0x12, BTN_6,
0x13, BTN_7,
0x14, BTN_8,
0x15, BTN_9,
0x16, BTN_TRIGGER_HAPPY1,
0x17, BTN_TRIGGER_HAPPY2,
0x18, BTN_DPAD_UP,
0x19, BTN_DPAD_LEFT,
0x1a, BTN_DPAD_DOWN,
0x1b, BTN_DPAD_RIGHT,
0x1c, 0x2ff,
0x1d, 0x280, // 0x300 doesn't work
0x1e, 0x2F0,  // 2F0 seems to be undefined but works
0x1f, 0x2F1,
0x20, 0x224,  // 224 - 22f undefined
0x21, 0x22f,
0x22, 0x120,
0x23, 0x12f,
0x24, 0x130,
0x25, 0x13e };  // greater than 0x2ff key max doesn't show up as a button press

int translatetablelen = sizeof(translatetable) / sizeof (int);


// tell uinput which BTN events we will generate
for (int i=0;i<translatetablelen;i+=2)     ioctl(fd, UI_SET_KEYBIT, translatetable[i+1]);
for (int i=0;i<translatetablelen;i+=2)  printf("%d => %d\n",translatetable[i],translatetable[i+1]);


  ioctl(fd, UI_SET_EVBIT, EV_ABS); // enable analog absolute position handling
  
//  setup_abs(fd, ABS_X,  -512, 512);
//  setup_abs(fd, ABS_Y,  -512, 512);
//  setup_abs(fd, ABS_Z,  0, 32767);

  setup_abs(fd, ABS_X,  0, 127);
  setup_abs(fd, ABS_Y,  0, 127);
  setup_abs(fd, ABS_Z,  0, 127);
  
  struct uinput_setup setup =
    {
     .name = "Userspace Joystick",
     .id =
     {
      .bustype = BUS_USB,
      .vendor  = 0x3,
      .product = 0x3,
      .version = 2,
     }
    };

  if (ioctl(fd, UI_DEV_SETUP, &setup))
    {
      perror("UI_DEV_SETUP");
      return 1;
    }
  
  if (ioctl(fd, UI_DEV_CREATE))
    {
      perror("UI_DEV_CREATE");
      return 1;
    }

  printf("Press CTRL+C to exit or top key on keyboard to quit\n");

    
    struct input_event button_event;
    
unsigned char  buffer[256];
int doquit = 0;

while (1) {      
      int readval;
      
      if ( readval = read(midi_fd, &buffer, 3), readval != -1 ) {
      printf("read: %x %x %x\n",buffer[0],buffer[1],buffer[2]);
 
      if (buffer[0] == 0x90)  // note on/off convert to EV_KEY events
	      	{   if (buffer[1] == 0x3c) doquit = 1;
	      		for (int i=0;i<translatetablelen;i+=2) 
	       			if (buffer[1] == translatetable[i]) 
      					{
      										
						button_event.type = EV_KEY;
						button_event.code = translatetable[i+1];
						button_event.value = (buffer[2]!=0) ? 1 : 0;  // 1 for button down, 0 for button up
						
						  printf("readval=%d  ev type=%d  key in=%d  => button out=%d value=%d\n",
						  	readval,
						  	button_event.type,
						  	buffer[1],
							button_event.code,
							button_event.value);
		
					  if(write(fd, &button_event, sizeof button_event) < 0)
							{
							  perror("write");
							  return 1;
							}
						
						// send SYNC event
						
						button_event.type = EV_SYN;
						button_event.code = 0;
						button_event.value = 0;

	
					  if(write(fd, &button_event, sizeof button_event) < 0)
							{
							  perror("write");
							  return 1;
							}
					    }
			}
        else if (buffer[0]==0xb0) // convert midi controller message into EV_ABS events
      					{
      					button_event.type = EV_ABS;
						button_event.code = (buffer[1]==1) ? ABS_X : (buffer[1]==7) ? ABS_Y : 0;  // my midi keyboard has 1 for volume, 7 for modulation
						button_event.value = (buffer[2]);
						
						  printf("0xb0 readval=%d  ev type=%d  key in=%d  => button out=%d value=%d\n",
						  	readval,
						  	button_event.type,
						  	buffer[1],
							button_event.code,
							button_event.value);
		
					  if(write(fd, &button_event, sizeof button_event) < 0)
							{
							  perror("write");
							  return 1;
							}
						
						// send SYNC event
						
						button_event.type = EV_SYN;
						button_event.code = 0;
						button_event.value = 0;

					  if(write(fd, &button_event, sizeof button_event) < 0)
							{
							  perror("write");
							  return 1;
							}
			    }
			 else if (buffer[0]==0xe0)  // pitch bend wheel message to EV_ABS event
      					{
      					button_event.type = EV_ABS;
						button_event.code = ABS_Z;
						button_event.value = (buffer[2]);
						
						  printf("0xb0 readval=%d  ev type=%d  key in=%d  => button out=%d value=%d\n",
						  	readval,
						  	button_event.type,
						  	buffer[1],
							button_event.code,
							button_event.value);
		
					  if(write(fd, &button_event, sizeof button_event) < 0)
							{
							  perror("write");
							  return 1;
							}
						
						// send SYNC event
						
						button_event.type = EV_SYN;
						button_event.code = 0;
						button_event.value = 0;

	
					  if(write(fd, &button_event, sizeof button_event) < 0)
							{
							  perror("write");
							  return 1;
							}
			    }
			}
     	if (readval <=0) msleep(50); // sleep for a bit so we don't use all the cpu
     	if (doquit) break;
    }
 
    close(midi_fd);
      
  if(ioctl(fd, UI_DEV_DESTROY))
    {
      printf("UI_DEV_DESTROY");
      return 1;
    }

  close(fd);
    
  return 0;
}


// enable and configure an absolute "position" analog channel

static void setup_abs(int fd, unsigned chan, int min, int max)
{
  if (ioctl(fd, UI_SET_ABSBIT, chan))
    perror("UI_SET_ABSBIT");
  
  struct uinput_abs_setup s =
    {
     .code = chan,
     .absinfo = { .minimum = min,  .maximum = max },
    };

  if (ioctl(fd, UI_ABS_SETUP, &s))
    perror("UI_ABS_SETUP");
}


[Linked Image from i.imgur.com]

The usb keyboard protocol limits the keypresses to 6, but I can hold down a bunch of midi keys at once.