Snippets

新妻浩光 メガドライブミニにiBuffaloのアーケードスティックをつなぐ

You are viewing an old version of this snippet. View the current version.
Revised by 新妻浩光 2a4cc78
#include <SDL2/SDL.h>
#include <errno.h> 
#include <fcntl.h>
#include <linux/input.h> 
#include <linux/uinput.h>
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h>
#include <sys/stat.h> 
#include <sys/types.h> 
#include <unistd.h>


#define die(str)                                                               \
  do {                                                                         \
    perror(str);                                                               \
    exit(EXIT_FAILURE);                                                        \
  } while (0)
struct uinput_user_dev uidev = {0};

void make_output(int fd) {

  ioctl(fd, UI_SET_EVBIT, EV_KEY);
  ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER);
  ioctl(fd, UI_SET_KEYBIT, BTN_THUMB);
  ioctl(fd, UI_SET_KEYBIT, BTN_THUMB2);
  ioctl(fd, UI_SET_KEYBIT, BTN_TOP);
  ioctl(fd, UI_SET_KEYBIT, BTN_TOP2);
  ioctl(fd, UI_SET_KEYBIT, BTN_PINKIE);
  ioctl(fd, UI_SET_KEYBIT, BTN_BASE);
  ioctl(fd, UI_SET_KEYBIT, BTN_BASE2);
  ioctl(fd, UI_SET_KEYBIT, BTN_BASE3);
  ioctl(fd, UI_SET_KEYBIT, BTN_BASE4);

  ioctl(fd, UI_SET_KEYBIT, KEY_L);
  ioctl(fd, UI_SET_KEYBIT, KEY_R);


  ioctl(fd, UI_SET_EVBIT, EV_ABS);
  ioctl(fd, UI_SET_ABSBIT, ABS_X);
  ioctl(fd, UI_SET_ABSBIT, ABS_Y);
  


  snprintf(uidev.name, UINPUT_MAX_NAME_SIZE,"ev from sdl");
  uidev.id.bustype = BUS_USB;
  uidev.id.vendor = 0x7777;
  uidev.id.product = 0x7777;
  uidev.id.version = 1;

  uidev.absmin[ABS_X] = 0;
  uidev.absmax[ABS_X] = 255;
  uidev.absflat[ABS_X] = 15;

  uidev.absmin[ABS_Y] = 0;
  uidev.absmax[ABS_Y] = 255;
  uidev.absflat[ABS_Y] = 15;

  if (write(fd, &uidev, sizeof(uidev)) < 0)
    die("Fail to write uinput_user_dev");

  if (ioctl(fd, UI_DEV_CREATE) < 0)
    die("Fail to set UI_DEV_CREATE");
}

void emit(int output, int type, int code, int value) {
  struct input_event event = {.type = type, .code = code, .value = value};
  event.time.tv_sec = 0;
  event.time.tv_usec = 0;
  write(output, &event, sizeof(event));
}



int main(int argc, char* argv[])
{

  int output = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
  if (output == -1)
    die("Cannot open the output device");





    SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER );
	int i;
	const char *name;
	int ret;
	ret=SDL_GameControllerAddMapping("03000000a30c00002400000011010000,6B controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux,");
	if( ret < 0 ){
		printf("add mapping error. %s\n",SDL_GetError());
	}
	for (i = 0; i < SDL_NumJoysticks(); ++i) {
		printf("[%d] %s\n",i,SDL_JoystickNameForIndex(i));
		SDL_GameController *g=SDL_GameControllerOpen(i);
		if( g ){
			printf("game controller.\n");
			break;
		}else{
			printf("not game controller. %s\n",SDL_GetError());

		}
	}

  make_output(output);

	SDL_Event e;
	while(1){
	SDL_Delay(10);
		while(SDL_PollEvent(&e)){
			int code;
			if( e.type!= SDL_CONTROLLERBUTTONDOWN &&
				e.type!= SDL_CONTROLLERBUTTONUP &&
				e.type!= SDL_CONTROLLERAXISMOTION) continue;

			if( e.type==SDL_CONTROLLERAXISMOTION ){
				int v=127;
				if( e.caxis.value > 0 ) v=255;
				if( e.caxis.value < 0 ) v=0;

				printf("axis=%d value=%d\n",e.caxis.axis,e.caxis.value);
				switch(e.caxis.axis){
					case 0:
						emit(output, EV_ABS, ABS_X, v ); 
						break;
					case 1:
						emit(output, EV_ABS, ABS_Y, v ); 
						break;

				}
				emit(output, EV_SYN, SYN_REPORT, 0);
				continue;
			}
			printf("type=0x%x btn=%d state=%d\n",e.type,e.cbutton.button,e.cbutton.state);
			switch(e.cbutton.button){
				case SDL_CONTROLLER_BUTTON_A:
					code=BTN_THUMB2;
					break;
				case SDL_CONTROLLER_BUTTON_B:
					code=BTN_THUMB;
					break;
				case SDL_CONTROLLER_BUTTON_X:
					code=BTN_TOP;
					break;
				case SDL_CONTROLLER_BUTTON_Y:
					code=BTN_TRIGGER;
					break;
				
				case SDL_CONTROLLER_BUTTON_START:
					code=BTN_BASE4;
					break;
				case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
					code=BTN_TOP2;
					break;
				case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
					code=BTN_PINKIE;
					break;

				case SDL_CONTROLLER_BUTTON_BACK:
					code=BTN_BASE3;
					break;

				
			}
			emit(output,EV_KEY,code,e.cbutton.state==SDL_PRESSED?1:0);
			emit(output, EV_SYN, SYN_REPORT, 0);
			
		}
	}

    SDL_Quit();
    return 0;
}
#include <errno.h>
#include <fcntl.h>
#include <linux/input.h>
#include <linux/uinput.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>


#define die(str)                                                               \
  do {                                                                         \
    perror(str);                                                               \
    exit(EXIT_FAILURE);                                                        \
  } while (0)
struct uinput_user_dev uidev = {0};

void make_output(int fd) {

  ioctl(fd, UI_SET_EVBIT, EV_KEY);
  ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER);
  ioctl(fd, UI_SET_KEYBIT, BTN_THUMB);
  ioctl(fd, UI_SET_KEYBIT, BTN_THUMB2);
  ioctl(fd, UI_SET_KEYBIT, BTN_TOP);
  ioctl(fd, UI_SET_KEYBIT, BTN_TOP2);
  ioctl(fd, UI_SET_KEYBIT, BTN_PINKIE);
  ioctl(fd, UI_SET_KEYBIT, BTN_BASE);
  ioctl(fd, UI_SET_KEYBIT, BTN_BASE2);
  ioctl(fd, UI_SET_KEYBIT, BTN_BASE3);
  ioctl(fd, UI_SET_KEYBIT, BTN_BASE4);

  ioctl(fd, UI_SET_KEYBIT, KEY_L);
  ioctl(fd, UI_SET_KEYBIT, KEY_R);


  ioctl(fd, UI_SET_EVBIT, EV_ABS);
  ioctl(fd, UI_SET_ABSBIT, ABS_X);
  ioctl(fd, UI_SET_ABSBIT, ABS_Y);
  


  snprintf(uidev.name, UINPUT_MAX_NAME_SIZE,"evfrom23");
  uidev.id.bustype = BUS_USB;
  uidev.id.vendor = 0x7777;
  uidev.id.product = 0x7777;
  uidev.id.version = 1;

  uidev.absmin[ABS_X] = 0;
  uidev.absmax[ABS_X] = 255;
  uidev.absflat[ABS_X] = 15;

  uidev.absmin[ABS_Y] = 0;
  uidev.absmax[ABS_Y] = 255;
  uidev.absflat[ABS_Y] = 15;

  if (write(fd, &uidev, sizeof(uidev)) < 0)
    die("Fail to write uinput_user_dev");

  if (ioctl(fd, UI_DEV_CREATE) < 0)
    die("Fail to set UI_DEV_CREATE");
}

void emit(int output, int type, int code, int value) {
  struct input_event event = {.type = type, .code = code, .value = value};
  event.time.tv_sec = 0;
  event.time.tv_usec = 0;
  write(output, &event, sizeof(event));
}

#define NAME_ELEMENT(element) [element] = #element
static const char * const absval[6] = { "Value", "Min  ", "Max  ", "Fuzz ", "Flat ", "Resolution "};

int abs_max[10];
int abs_min[10];
static void print_absdata(int fd, int axis)
{
	int abs[6] = {0};
	int k;

	ioctl(fd, EVIOCGABS(axis), abs);
	for (k = 0; k < 6; k++){
		if ((k < 3) || abs[k]){
			printf("      %s %6d\n", absval[k], abs[k]);
    }
  }
  if( axis == ABS_X) {

  }
  abs_min[axis]=abs[1];
  abs_max[axis]=abs[2];

}
#define BITS_PER_LONG (sizeof(long) * 8)
#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
#define OFF(x)  ((x)%BITS_PER_LONG)
#define BIT(x)  (1UL<<OFF(x))
#define LONG(x) ((x)/BITS_PER_LONG)
#define test_bit(bit, array)	((array[LONG(bit)] >> OFF(bit)) & 1)

static const char * const events[EV_MAX + 1] = {
	[0 ... EV_MAX] = NULL,
	NAME_ELEMENT(EV_SYN),			NAME_ELEMENT(EV_KEY),
	NAME_ELEMENT(EV_REL),			NAME_ELEMENT(EV_ABS),
	NAME_ELEMENT(EV_MSC),			NAME_ELEMENT(EV_LED),
	NAME_ELEMENT(EV_SND),			NAME_ELEMENT(EV_REP),
	NAME_ELEMENT(EV_FF),			NAME_ELEMENT(EV_PWR),
	NAME_ELEMENT(EV_FF_STATUS),		NAME_ELEMENT(EV_SW),
};

static inline const char* typename(unsigned int type)
{
	return (type <= EV_MAX && events[type]) ? events[type] : "?";
}


int main(int argc,char **argv) {

	unsigned int type, code;
	int version;
	unsigned short id[4];
	char name[256] = "Unknown";
	unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
  char INPUT_DEVICE[255];
  int x;
  int replace_code;
  for(x=0;x<argc;x++){
    printf("argv[%d]=%s\n",x,argv[x]);
  }
  if( argc > 1 ){
    strcpy(INPUT_DEVICE,argv[1]);
  }

  int input = open(INPUT_DEVICE, O_RDWR);
  if (input == -1)
    die("Cannot open the input device");

  int fd=input;

	ioctl(fd, EVIOCGNAME(sizeof(name)), name);
	printf("Input device name: \"%s\"\n", name);

	memset(bit, 0, sizeof(bit));
	ioctl(fd, EVIOCGBIT(0, EV_MAX), bit[0]);
	printf("Supported events:\n");

	for (type = 0; type < EV_MAX; type++) {
		if (test_bit(type, bit[0]) && type != EV_REP) {
			printf("  Event type %d (%s)\n", type, typename(type));
			if (type == EV_SYN) continue;
			ioctl(fd, EVIOCGBIT(type, KEY_MAX), bit[type]);
			for (code = 0; code < KEY_MAX; code++)
				if (test_bit(code, bit[type])) {
					printf("    Event code %d\n", code);
					if (type == EV_ABS){
						print_absdata(fd, code);
          }
				}
		}
	}

  int output = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
  if (output == -1)
    die("Cannot open the output device");

  make_output(output);

  emit(output, EV_ABS, ABS_X, 127);
  emit(output, EV_ABS, ABS_Y, 127);

  // Disable the input device
  // ioctl(input, EVIOCGRAB, 1);
  printf("abs_x [%d - %d] abs_y [%d - %d] \n",abs_min[ABS_X],abs_max[ABS_X],abs_min[ABS_Y],abs_max[ABS_Y]);
  while (1) {
    struct input_event event;

    ssize_t result = read(input, &event, sizeof(event));
    if (result == -1) {
      perror("Stopping");
      return 0;
    } else if (result != sizeof(event)) {
      die("Inconsistent event size");
    }
    printf("tv_sec: %lu, type: %04x, code: %04x, value: %08x\n", event.time.tv_sec, event.type, event.code, event.value);
    fflush(stdout);
    
    switch (event.type) {
    case EV_ABS:
      if( event.code==ABS_X ){
        printf("ABS X : value=%d\n",event.value);
      }
      if( event.code==ABS_Y ){
        printf("ABS Y : value=%d\n",event.value);
      }

      if( event.value == abs_max[event.code]) {
        emit(output, EV_ABS, event.code, 255);

      }else if( event.value== abs_min[event.code]){
        emit(output, EV_ABS, event.code, 0);
      }else{
        emit(output, EV_ABS, event.code, 127);
      }
      emit(output, EV_SYN, SYN_REPORT, 0);


    case EV_KEY:
      switch(event.code){
        case BTN_B: // 1
          replace_code=BTN_THUMB2;  // MD A
          break;
        case BTN_C: // 2
          replace_code=BTN_THUMB;   // MD B
          break;
        case BTN_TR: // 3
          replace_code=BTN_PINKIE;  // MD C
          break;

        case BTN_TL:  // 4
          break;  // MD no use

        case BTN_A:  // 5
          replace_code=BTN_TOP;   // MD X
          break;
        case BTN_X:  // 6
          replace_code=BTN_TOP;   // MD Y
          break;
        case BTN_Z:  // 7
          replace_code=BTN_TOP;   // MD Z
          break;

        case BTN_Y: // 8
          break;  // MD no use



        case BTN_SELECT: // L3
          replace_code=BTN_BASE3;
          break;
        case BTN_START: // R3
          replace_code=BTN_BASE4;
          break;
      }
      emit(output, event.type, replace_code, event.value);
      emit(output, EV_SYN, SYN_REPORT, 0);
    }
  }

  // Never reach here...
  // Enable the mouse
  ioctl(input, EVIOCGRAB, 0);
  close(input);
  close(output);
  return (EXIT_SUCCESS);
}
HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.