Snippets

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

You are viewing an old version of this snippet. View the current version.
Revised by 新妻浩光 a3546ad
#!/bin/sh

set -x

trans="/tmp/a.out"
#trans="echo"

start_trans () {
for i in 14 15 16 17 18 19 20 21 21 22 23
do
        evname="/dev/input/event"$i
        if [ -e $evname ]; then
                exe=$trans" "$evname
                $exe &
                sleep 1
                echo $sysfs
        fi

done



}

process_kill() {
        pkill -9 a.out
}
case "$1" in
"start")
  start_trans
  ;;
"stop")
  process_kill
  ;;
*)
  echo "Usage: $0 start|stop"
  ;;
esac
exit 0
#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 <unistd.h>
#include <dirent.h>
#include <sys/stat.h> 
#include <sys/types.h> 
#include <sys/ioctl.h>


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

void make_output(int fd,int ev) {

  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,"linkmeevent%d",ev-10);
  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));
}

///// Their code are copied from SYS_Joystick for touch raw structure data

struct SDL_joylist_item;

/* The private structure used to keep track of a joystick */
struct joystick_hwdata
{
    int fd;
    struct SDL_joylist_item *item;
    SDL_JoystickGUID guid;
    char *fname;                /* Used in haptic subsystem */

    /* The current Linux joystick driver maps hats to two axes */
    struct hwdata_hat
    {
        int axis[2];
    } *hats;
    /* The current Linux joystick driver maps balls to two axes */
    struct hwdata_ball
    {
        int axis[2];
    } *balls;

    /* Support for the Linux 2.4 unified input interface */
    Uint8 key_map[KEY_MAX];
    Uint8 abs_map[ABS_MAX];
    struct axis_correct
    {
        int used;
        int coef[3];
    } abs_correct[ABS_MAX];

    int fresh;

    /* Steam Controller support */
    SDL_bool m_bSteamController;
};
typedef struct _SDL_JoystickAxisInfo
{
    Sint16 initial_value;       /* Initial axis state */
    Sint16 value;               /* Current axis state */
    Sint16 zero;                /* Zero point on the axis (-32768 for triggers) */
    SDL_bool has_initial_value; /* Whether we've seen a value on the axis yet */
    SDL_bool sent_initial_value; /* Whether we've sent the initial axis value */
} SDL_JoystickAxisInfo;


struct _SDL_Joystick
{
    SDL_JoystickID instance_id; /* Device instance, monotonically increasing from 0 */
    char *name;                 /* Joystick name - system dependent */

    int naxes;                  /* Number of axis controls on the joystick */
    SDL_JoystickAxisInfo *axes;

    int nhats;                  /* Number of hats on the joystick */
    Uint8 *hats;                /* Current hat states */

    int nballs;                 /* Number of trackballs on the joystick */
    struct balldelta {
        int dx;
        int dy;
    } *balls;                   /* Current ball motion deltas */

    int nbuttons;               /* Number of buttons on the joystick */
    Uint8 *buttons;             /* Current button states */

    struct joystick_hwdata *hwdata;     /* Driver dependent information */

    int ref_count;              /* Reference count for multiple opens */

    SDL_bool is_game_controller;
};


int is_event_device(const struct dirent *dir)
{
	return strncmp("event", dir->d_name, 5) == 0;
}

char *find_device(char *p)
{
	struct dirent **namelist;
	int i, ndev;

	ndev = scandir("/dev/input", &namelist, is_event_device, alphasort);
	if (ndev <= 0)
		return 0;

	for (i = 0; i < ndev; i++) {
		char fname[64];
		int fd = -1;
		char name[256] = "";
		char phys[256] = "";
		char uniq[256] = "";
		char prop[256] = "";

		snprintf(fname, sizeof(fname), "/dev/input/%s",
				namelist[i]->d_name);
		fd = open(fname, O_RDONLY);
		if (fd < 0)
			continue;

		ioctl(fd, EVIOCGNAME(sizeof(name)), name);
		ioctl(fd, EVIOCGPHYS(sizeof(phys)), phys);
		ioctl(fd, EVIOCGUNIQ(sizeof(uniq)), uniq);
		ioctl(fd, EVIOCGPROP(sizeof(prop)), prop);
#if 0
		printf("%s:\n", fname);
		printf("\tname: %s\n", name);
		printf("\tphys: %s\n", phys);
		printf("\tuniq: %s\n", uniq);
		printf("\tprop: %s\n", prop);
#endif
		close(fd);
		if( strcmp(p,name)==0 ){
			return strdup(fname);
		}
		free(namelist[i]);
	}
	return NULL;
}
int handle_as_joystick(int output,SDL_Event e){
	if( e.type==SDL_JOYAXISMOTION ){
		int v=127;
		if( e.caxis.value > 0 ) v=255;
		if( e.caxis.value < 0 ) v=0;

		printf("axis=%d value=%d\n",e.jaxis.axis,e.jaxis.value);
		switch(e.jaxis.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);
	}

	if (e.type==SDL_JOYBUTTONDOWN || e.type==SDL_JOYBUTTONUP) {
		printf("type=0x%x btn=%d state=%d\n",e.type,e.cbutton.button,e.cbutton.state);

	}

	return 0;
}
int handle_as_controller(int output,SDL_Event e){

	switch(e.type)
	{
		case 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);
		}
			break;
		case SDL_CONTROLLERBUTTONDOWN:
		case SDL_CONTROLLERBUTTONUP:
		{
			int code=0;
			// buttons
			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_RIGHTSHOULDER:
					code=BTN_PINKIE;
					break;


				case SDL_CONTROLLER_BUTTON_X:
					code=BTN_TOP;
					break;
				case SDL_CONTROLLER_BUTTON_Y:
					code=BTN_TRIGGER;
					break;
				
				case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
					code=BTN_TOP2;
					break;

				case SDL_CONTROLLER_BUTTON_START:
					code=BTN_BASE4;
					break;

				case SDL_CONTROLLER_BUTTON_BACK:
					code=BTN_BASE3;
					break;
			}
			if( code > 0){
				emit(output,EV_KEY,code,e.cbutton.state==SDL_PRESSED?1:0);
				emit(output, EV_SYN, SYN_REPORT, 0);
			}
		}
		break;
	}
	return 0;
}
int main(int argc, char* argv[])
{
	int joysticktype=-1;	// not opened
	int i;
	int n_event_input;
	int ret;

	if( argc < 2 ){
		fprintf(stderr,"%s : </dev/input/eventx>\n",argv[0]);
		exit(-1);
	}

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

	// Initialize SDL
    SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER );

	// MD Mini 6B pad mapping
	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,");
	printf("add mapping returns<%d>, %s\n",ret,SDL_GetError());

	// get /dev/input/event[number]


	// open joystick or mapped pad
	SDL_Joystick *j=NULL;
	for (i = 0; i < SDL_NumJoysticks(); ++i) {
		printf("[%d] %s ",i,SDL_JoystickNameForIndex(i));
		SDL_GameController *g=SDL_GameControllerOpen(i);
		if( g ){		
			printf("is game controller.\n");

			j=SDL_GameControllerGetJoystick(g);

			// check joystick is target event 
			if( strcmp(j->hwdata->fname,argv[1])==0 ){
				// yes
				joysticktype=0;
				break;
			}else{
				// no

				SDL_GameControllerClose(g);
				// next input
			}
		}else{
			printf("is not game controller. treat as simple joystick.%s\n",SDL_GetError());
			joysticktype=1;

			j=SDL_JoystickOpen(i);

			// check joystick is target event 
			if( strcmp(j->hwdata->fname,argv[1])==0 ){
				// yes
				joysticktype=1;
				break;
			}else{
				SDL_JoystickClose(j);
				//next input
			}
		}
	}

	if( joysticktype < 0 ){
		fprintf(stderr,"could not found js on %s\n",argv[1]);
		die("fatal error.");
	}
	
	n_event_input=atoi(j->hwdata->fname+strlen("/dev/input/event"));

	// make virtual input event with "linkmeevent[4-13]"
	make_output(output,n_event_input);
	
	// find new virtual/input and link to event4-13
	char target[255];
	sprintf(target,"linkmeevent%d",n_event_input-10);

	char *dev=find_device(target);		
	if( dev ){
		char cmdline[255];
		sprintf(cmdline,"ln -s %s /dev/input/event%d",dev,n_event_input-10);
		puts(cmdline);
~		system(cmdline);
	}else{
		die("fatal error. linkmeevent device not found.");
	}

	
	while(1){
		SDL_Event e;
		SDL_Delay(10);
		while(SDL_PollEvent(&e)){

			switch(joysticktype){
				case 0:
					handle_as_controller(output,e);
					break;
				case 1:
					handle_as_joystick(output,e);
					break;
			}
		}

	}

    SDL_Quit();
    return 0;
}
HTTPS SSH

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