Snippets

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

Updated by 新妻浩光

File 変換プログラムを動かすためのシェルスクリプト(udevから呼ぶのがいいと思う) Deleted

  • Ignore whitespace
  • Hide word diff
-#!/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

File 変換プログラム最新版のソースコード(ジョイスティックに中途半端に対応) Modified

  • Ignore whitespace
  • Hide word diff
   ioctl(fd, UI_SET_ABSBIT, ABS_Y);
   
 
-  snprintf(uidev.name, UINPUT_MAX_NAME_SIZE,"linkmeevent%d",ev-10);
+  snprintf(uidev.name, UINPUT_MAX_NAME_SIZE,"linkmeevent%d",ev);
   uidev.id.bustype = BUS_USB;
   uidev.id.vendor = 0x7777;
   uidev.id.product = 0x7777;
     /* Steam Controller support */
     SDL_bool m_bSteamController;
 };
+#if 1
 typedef struct _SDL_JoystickAxisInfo
 {
     Sint16 initial_value;       /* Initial axis state */
     SDL_bool sent_initial_value; /* Whether we've sent the initial axis value */
 } SDL_JoystickAxisInfo;
 
+#endif
+//strucct SDL_JoystickAxisInfo;
 
 struct _SDL_Joystick
 {
 	return NULL;
 }
 int handle_as_joystick(int output,SDL_Event e){
+	printf("event type=0x%x\n",e.type);
 	if( e.type==SDL_JOYAXISMOTION ){
 		int v=127;
 		if( e.caxis.value > 0 ) v=255;
 	}
 	return 0;
 }
+typedef struct _map_event_uevent_links{
+	int out_fd;	// uinput handle
+	int joystick_id;
+	int controller_id;
+
+	int instance_id;
+	void *ptr;
+} eventlink;
+
+eventlink EvLink[10];	// mapped 4-13 to 0-9
+
+int make_output_devices(){
+	int ev;
+
+	for(ev=4;ev<=5;ev++){
+		int output = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
+		if (output == -1)
+			die("Cannot open the output device");
+		// make virtual input event with "linkmeevent[4-13]"
+		make_output(output,ev);
+		
+		// find new virtual/input and link to event4-13
+		char target[255];
+		sprintf(target,"linkmeevent%d",ev);
+
+		char *dev=find_device(target);		
+		if( dev ){
+			char cmdline[255];
+			sprintf(cmdline,"unlink /dev/input/event%d",ev);
+			puts(cmdline);
+			system(cmdline);
+
+
+			sprintf(cmdline,"ln -s %s /dev/input/event%d",dev,ev);
+			puts(cmdline);
+			system(cmdline);
+			EvLink[ev-4].out_fd=output;
+		}else{
+			die("fatal error. linkmeevent device not found.");
+		}
+	}
+	return 0;
+}
+#define INVALID -1
+int joystick_add_callback(int jsindex){
+
+	printf("add index [%d] name : %s \n",jsindex,SDL_JoystickNameForIndex(jsindex));
+
+	SDL_Joystick *j=SDL_JoystickOpen(jsindex);
+	int n_event_input=atoi(j->hwdata->fname+strlen("/dev/input/event"));
+	SDL_JoystickClose(j);
+
+	if(n_event_input>=14 && n_event_input<=23){
+
+		if( SDL_IsGameController(jsindex)){
+			SDL_GameController *g=SDL_GameControllerOpen(jsindex);
+			if( g ){		
+
+				j=SDL_GameControllerGetJoystick(g);
+
+				printf("is game controller. Handle it\n");
+				EvLink[n_event_input-14].joystick_id=INVALID;
+				EvLink[n_event_input-14].controller_id=jsindex;
+				EvLink[n_event_input-14].instance_id=SDL_JoystickInstanceID(j);
+				EvLink[n_event_input-14].ptr=g;
+			}else{
+				printf("fatal error on open gamecontroller\n");
+			}
+		}else{
+			SDL_Joystick *j=SDL_JoystickOpen(jsindex);
+			printf("is not game controller. treat as simple joystick.%s\n",SDL_GetError());
+			EvLink[n_event_input-14].joystick_id=jsindex;
+			EvLink[n_event_input-14].controller_id=INVALID;
+			EvLink[n_event_input-14].instance_id=SDL_JoystickInstanceID(j);
+				EvLink[n_event_input-14].ptr=j;
+
+		}
+			
+	}else{
+		printf("It's not target.\n");
+		return 0;
+	}
+
+	return 0;
+}
+int joystick_remove_callback(int jsinstance){
+
+	printf("joystick_remove_callback(%d)\n",jsinstance);
+	int ec;
+	for(ec=0;ec<10;ec++){
+		if( EvLink[ec].instance_id==jsinstance){
+			if( EvLink[ec].joystick_id!=-1 ){
+				SDL_Joystick* j=(SDL_Joystick*)EvLink[ec].ptr;
+				SDL_JoystickClose(j);
+			}else{
+				SDL_GameController* g=(SDL_GameController*)EvLink[ec].ptr;
+				SDL_GameControllerClose(g);
+			}
+			EvLink[ec].joystick_id=INVALID;
+			EvLink[ec].controller_id=INVALID;
+			EvLink[ec].instance_id=INVALID;
+			EvLink[ec].ptr=NULL;
+		}
+	}
+	return 0;
+}
+int get_output_device(int jsinstance){
+	printf("get_output_device(%d)\n",jsinstance);
+	int ec;
+	for(ec=0;ec<10;ec++){
+		if( EvLink[ec].instance_id==jsinstance){
+			int output=EvLink[ec].out_fd;
+			printf(" return <%d>\n",output);
+			return output;
+		}
+	}
+	return -1;
+}
+int get_is_gamecontroller(int jsinstance){
+	printf("get_is_gamecontroller(%d)\n",jsinstance);
+	int ec;
+	for(ec=0;ec<10;ec++){
+		if( EvLink[ec].instance_id==jsinstance){
+			return (EvLink[ec].controller_id==-1)?0:1;
+		}
+	}
+	return 0;
+}
+
+int emit_abs_xy(int output,int xy,int value){
+	emit(output, EV_ABS, xy, value ); 
+	emit(output, EV_SYN, SYN_REPORT, 0);
+	return 0;
+}
+
+int joystick_axis_handle(SDL_Event e){
+	if( get_is_gamecontroller(e.jaxis.which )) return;
+
+	int output=get_output_device(e.jaxis.which);
+	if( output == -1) return -1;
+	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);
+	emit_abs_xy(output,e.jaxis.axis,v);
+
+	return 0;
+}
+int controller_asix_handle(SDL_Event e){
+	int output=get_output_device(e.caxis.which);
+	if( output == -1) return -1;
+
+	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);
+	emit_abs_xy(output,e.caxis.axis,v);
+
+	return 0;
+
+}
+int joystick_button_handle(SDL_Event e){
+	if( get_is_gamecontroller(e.jbutton.which)) return;
+
+	int output=get_output_device(e.jbutton.which);
+	if( output == -1) return -1;
+	printf("Button=%d\n",e.jbutton.button);
+	int code=0;
+	switch(e.jbutton.button){
+		case 0:
+			code=BTN_TOP;
+			break;
+		case 1:
+			code=BTN_THUMB2;
+			break;
+		case 2:
+			code=BTN_THUMB;
+			break;
+		case 3:
+			code=BTN_TRIGGER;
+			break;
+		case 4:
+			break;
+		case 5:
+			code=BTN_TOP2;
+			break;
+		case 7:
+			code=BTN_PINKIE;
+			break;
+		case 8:
+			code=BTN_BASE4;
+			break;
+		case 9:
+			code=BTN_BASE3;
+			break;
+		
+	}
+	if( code > 0){
+		emit(output,EV_KEY,code,e.jbutton.state==SDL_PRESSED?1:0);
+		emit(output, EV_SYN, SYN_REPORT, 0);
+	}
+	return 0;
+}
+
+int controller_button_handle(SDL_Event e){
+	int output=get_output_device(e.caxis.which);
+	if( output == -1) return -1;
+
+	int code=0;
+	
+	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);
+	}
+	return 0;
+}
+
 int main(int argc, char* argv[])
 {
 	int joysticktype=-1;	// not opened
 	int i;
 	int n_event_input;
 	int ret;
-
+#if 0
 	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");
-
+#endif
+	int ec;
+	for(ec=0;ec<10;ec++){
+		EvLink[ec].joystick_id=INVALID;
+		EvLink[ec].controller_id=INVALID;
+		EvLink[ec].instance_id=INVALID;
+		EvLink[ec].out_fd=INVALID;
+		EvLink[ec].ptr=NULL;
+	}
 	// Initialize SDL
     SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER );
 
 
 	// get /dev/input/event[number]
 
-
+//	gets(buf);
+//	exit(1);
 	// 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;
+	make_output_devices();
 
-			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"));
+	char buf[255];
 
 	// make virtual input event with "linkmeevent[4-13]"
-	make_output(output,n_event_input);
+	//make_output(output,n_event_input);
 	
 	// find new virtual/input and link to event4-13
+#if 0
 	char target[255];
 	sprintf(target,"linkmeevent%d",n_event_input-10);
 
 		char cmdline[255];
 		sprintf(cmdline,"ln -s %s /dev/input/event%d",dev,n_event_input-10);
 		puts(cmdline);
-~		system(cmdline);
+		system(cmdline);
 	}else{
 		die("fatal error. linkmeevent device not found.");
 	}
+#endif
 
-	
 	while(1){
 		SDL_Event e;
 		SDL_Delay(10);
 		while(SDL_PollEvent(&e)){
+			printf("e.type=0x%x\n",e.type);
+
+			switch(e.type){
+				case SDL_QUIT:
+					goto end;
+				case SDL_CONTROLLERAXISMOTION:
+					printf("Controller Axis motion.\n");
+					controller_asix_handle(e);
+					break;
+				case SDL_CONTROLLERBUTTONDOWN:
+				case SDL_CONTROLLERBUTTONUP:
+					printf("Controller Button Up/Down\n");
+					controller_button_handle(e);
+					break;
+				case SDL_CONTROLLERDEVICEADDED:
+					printf("Controller Device Added  id=%d\n",e.cdevice.which);
+					break;
+				case SDL_CONTROLLERDEVICEREMOVED:
+					printf("Controller Device Removed instance id=%d\n",e.cdevice.which);
+					break;
+				case SDL_CONTROLLERDEVICEREMAPPED:
+					printf("Controller Device Remapped device id=%d\n",e.cdevice.which);
+					break;
 
-			switch(joysticktype){
-				case 0:
-					handle_as_controller(output,e);
+				case SDL_JOYAXISMOTION: /**< Joystick axis motion */
+					printf("Joystick Axis motion.\n");
+					joystick_axis_handle(e);
 					break;
-				case 1:
-					handle_as_joystick(output,e);
+				case SDL_JOYBALLMOTION:          /**< Joystick trackball motion */
+					printf("Joystick trackball motion..\n");
+					break;
+				case SDL_JOYHATMOTION:           /**< Joystick hat position change */
+					printf("Joystick hat position change..\n");
+					break;
+				case SDL_JOYBUTTONDOWN:          /**< Joystick button pressed */
+				case SDL_JOYBUTTONUP:           /**< Joystick button released */
+					printf("Joystick Button Up/Down.\n");
+					joystick_button_handle(e);
+					break;
+				case SDL_JOYDEVICEADDED:         /**< A new joystick has been inserted into the system */
+					printf("Joystick Device Added js index=%d.\n",e.jdevice.which);
+					joystick_add_callback(e.jdevice.which);
+					for(ec=0;ec<10;ec++){
+						if( EvLink[ec].out_fd >= 0){
+							printf("-----------\n");
+							printf("event[%d] is linked to event[%d]\n",ec+4,ec+14);
+							printf("\t joystick_id=%d\n",EvLink[ec].joystick_id);
+							printf("\t controller_id=%d\n",EvLink[ec].controller_id);
+							printf("\t instance id=%d\n",EvLink[ec].instance_id);
+							printf("\t out_fd=%d\n",EvLink[ec].out_fd);
+							printf("-----------\n");
+						}
+					}
+
+					break;
+				case SDL_JOYDEVICEREMOVED:       /**< An opened joystick has been removed */
+					printf("Joystick Device Removed js instance id=%d.\n",e.jdevice.which);
+					joystick_remove_callback(e.jdevice.which);
 					break;
+
 			}
+
 		}
 
 	}
 
     SDL_Quit();
+	end:;
     return 0;
 }
Updated by 新妻浩光

File SDL2対応版 Deleted

  • Ignore whitespace
  • Hide word diff
-#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;
-}

File snippet.txt Deleted

  • Ignore whitespace
  • Hide word diff
-#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);
-}

File 変換プログラムを動かすためのシェルスクリプト(udevから呼ぶのがいいと思う) Modified

  • Ignore whitespace
  • Hide word diff
+#!/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
Updated by 新妻浩光

File 変換プログラムを動かすためのシェルスクリプト(udevから呼ぶのがいいと思う) Added

  • Ignore whitespace
  • Hide word diff
Empty file added.

File 変換プログラム最新版のソースコード(ジョイスティックに中途半端に対応) Added

  • Ignore whitespace
  • Hide word diff
+#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;
+}
Updated by 新妻浩光

File SDL2対応版 Added

  • Ignore whitespace
  • Hide word diff
+#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;
+}
Created by 新妻浩光

File snippet.txt Added

  • Ignore whitespace
  • Hide word diff
+#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.