*/}}
Browse Source

evdev joystick and x56 thr mapping

YimingWu 3 months ago
parent
commit
c30ee6e413
5 changed files with 197 additions and 44 deletions
  1. 72 44
      la_controllers.c
  2. 13 0
      la_interface.h
  3. 23 0
      la_kernel.c
  4. 64 0
      la_util.c
  5. 25 0
      la_util.h

+ 72 - 44
la_controllers.c

@@ -22,22 +22,20 @@
 
 #ifdef __linux__
 #include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/ioctl.h>
+#include <sys/inotify.h>
 #include <linux/input.h>
 #include <linux/joystick.h>
+#include <fcntl.h>
+#include <unistd.h>
 #include <errno.h>
 #include <X11/extensions/XInput2.h>
 #endif
 
 extern LA MAIN;
 
-STRUCTURE(laJoystickEvent){
-  unsigned int time;
-  short value;
-  unsigned char type;
-  unsigned char number;
-};
-
 #define LA_JS_EVENT_BUTTON 0x01 // button pressed/released
 #define LA_JS_EVENT_AXIS   0x02 // joystick moved
 #define LA_JS_EVENT_INIT   0x80 // initial state of device
@@ -73,42 +71,72 @@ laController* la_FindControllerWithID(int id){
     for(laController* c=MAIN.Controllers.pFirst;c;c=c->Item.pNext){ if(c->UserAssignedID==id) return c; } return 0;
 }
 
+void la_ReadControllerAxisLimit(laController* c, int i, int Min, int Max){
+    c->AxisMins[i] = Min;
+    c->AxisMaxes[i] = Max;
+}
 void la_InitControllers(){
 #ifdef __linux__
     char path[32]="/dev/input/js";
     char name[128]={0};
     int numpos=strlen(path);
-    for(int i=0;i<16;i++){
-        int fd;
-        int version; uint8_t axes, buttons;
-        int btnmapok = 1;
-        sprintf(&path[numpos],"%d",i);
-        if ((fd=open(path, O_RDONLY|O_NONBLOCK))<0) { continue; }
-
-        ioctl(fd, JSIOCGVERSION, &version);
-        ioctl(fd, JSIOCGAXES, &axes);
-        ioctl(fd, JSIOCGBUTTONS, &buttons);
-        ioctl(fd, JSIOCGNAME(128), name);
-
-        laController* c=la_NewController(name, path, fd, axes, buttons);
-    }
+
+    char fileName[32];
+	for (int i=0; i<32; ++i) {
+		sprintf(fileName, "/dev/input/event%d", i);
+		int file = open(fileName, O_RDWR | O_NONBLOCK);
+		if (file != -1){
+			// Get name
+			ioctl(file, EVIOCGNAME(128), name);
+            printf("%s ",name);
+
+            barray_t *abs_barray = barray_init(ABS_CNT);
+            ioctl(file, EVIOCGBIT(EV_ABS, ABS_CNT), barray_data(abs_barray));
+            size_t abs_count = barray_count_set(abs_barray);
+
+            barray_t *key_barray = barray_init(KEY_CNT);
+            ioctl(file, EVIOCGBIT(EV_KEY, KEY_CNT), barray_data(key_barray));
+            size_t key_count = barray_count_set(key_barray);
+
+            if(!abs_count && !key_count){ close(file); continue; }
+
+            laController* c=la_NewController(name, fileName, file, abs_count, key_count);
+
+			for (unsigned int j=0; j<abs_count; j++){ struct input_absinfo axisInfo;
+				if (ioctl(file, EVIOCGABS(j), &axisInfo) != -1){
+                    la_ReadControllerAxisLimit(c,j,axisInfo.minimum,axisInfo.maximum);
+				}
+			}
+
+            barray_free(abs_barray);
+            barray_free(key_barray);
+		}
+	}
 #endif
 }
 
 void la_UpdateControllerStatus(){
 #ifdef __linux__
-    laJoystickEvent event; int HasEvent=0;
+    struct input_event event; int HasEvent=0;
     for(laController* c=MAIN.Controllers.pFirst;c;c=c->Item.pNext){ if(c->Error) continue;
-        int bytes; while((bytes=read(c->fd, &event, sizeof(laJoystickEvent)))>0){
-            if(event.type&LA_JS_EVENT_BUTTON){
-                if(event.number>=c->NumButtons) continue;
-                c->ButtonValues[event.number]=event.value; HasEvent=1;
-                //printf("b %d %d\n", event.number, event.value);
+        int bytes; while((bytes=read(c->fd, &event, sizeof(struct input_event)))>0){
+            if(event.type == EV_KEY){
+                printf("b %d %d", event.code, event.value);
+                if(event.code>=BTN_JOYSTICK && event.code<=BTN_THUMBR){
+                    event.code -= BTN_JOYSTICK;
+                }elif(event.code>=BTN_TRIGGER_HAPPY && event.code<=BTN_TRIGGER_HAPPY40){
+                    event.code=event.code-BTN_TRIGGER_HAPPY+BTN_THUMBR-BTN_JOYSTICK+1;
+                }
+                printf(" %d \n", event.code, event.value);
+                //if(event.code>=c->NumButtons+BTN_THUMBR) continue;
+                c->ButtonValues[event.code]=event.value; HasEvent=1;
             }
-            if(event.type&LA_JS_EVENT_AXIS){
-                if(event.number>=c->NumAxes) continue;
-                c->AxisValues[event.number]=event.value; HasEvent=1;
-                //printf("a %d %d\n", event.number, event.value);
+            else if(event.type == EV_ABS){
+                if(event.code>=c->NumAxes+ABS_X) continue;
+                int axis=event.code-ABS_X;
+                c->AxisValues[axis]=rint(tnsLinearItp(-32768.0f,32767.0f,((real)event.value/(c->AxisMaxes[axis]-c->AxisMins[axis]))));
+                HasEvent=1;
+                //printf("a %d %d\n", event.code, event.value);
             }
         }
         if(bytes<=0){ struct stat buffer; if(stat(c->Path->Ptr,&buffer)<0){ c->Error=1; HasEvent=1; } }
@@ -143,7 +171,7 @@ void la_AddButtonProp(laPropContainer* pc, char* id, char* name, char* desc, int
 }
 void la_AddAxisProp(laPropContainer* pc, char* id, char* name, char* desc, int i, int array_len, char* array_prefix){
     laProp* p=laAddIntProperty(pc,id,name,desc,array_len>1?LA_WIDGET_VALUE_METER_2D:LA_WIDGET_VALUE_METER,
-        array_prefix,0,32768,-32767,1,0,0,offsetof(laController, AxisValues[i]),0,0,array_len,0,0,0,0,0,0,0,LA_READ_ONLY);
+        array_prefix,0,32767,-32768,1,0,0,offsetof(laController, AxisValues[i]),0,0,array_len,0,0,0,0,0,0,0,LA_READ_ONLY);
 }
 void la_AddGenericButtonProps(laPropContainer* pc){
     for(int i=0;i<LA_JS_MAX_BUTTONS;i++){ char* name=LA_JS_BTN_NAMES[i]; la_AddButtonProp(pc,name,name,name,i,0,0); }
@@ -211,18 +239,18 @@ void la_RegisterControllerProps(){
     la_AddButtonProp(pc,"t2_up","T2+","Toggle 2+", 13,0,0);
     la_AddButtonProp(pc,"t2_dn","T2-","Toggle 2-", 14,0,0);
     la_AddButtonProp(pc,"t3_up","T3+","Toggle 3+", 15,0,0);
-    la_AddButtonProp(pc,"t3_dn","T3-","Toggle 3-", 16,0,0);
-    la_AddButtonProp(pc,"t4_up","T4+","Toggle 4+", 17,0,0);
-    la_AddButtonProp(pc,"t4_dn","T4-","Toggle 4-", 18,0,0);
-    la_AddButtonProp(pc,"h3","H3","Hat 3 (Upper round hat)", 19,4,"N,E,S,W");
-    la_AddButtonProp(pc,"h4","H4","Hat 4 (lower jagged hat)", 23,4,"N,E,S,W");
-    la_AddButtonProp(pc,"pinky_up","P+","Pinky up", 27,0,0);
-    la_AddButtonProp(pc,"pinky_dn","P-","Pinky down", 28,0,0);
-    la_AddButtonProp(pc,"dial_fwd","D+","Dial forward", 29,0,0);
-    la_AddButtonProp(pc,"dial_back","D-","Dial backward", 30,0,0);
-    la_AddButtonProp(pc,"bball","BP","Ball push", 31,0,0);
-    la_AddButtonProp(pc,"slider","SLD","Slider", 32,0,0);
-    la_AddButtonProp(pc,"mode","Mode","Mode switch", 33,3,"M1,M2,S1");
+    la_AddButtonProp(pc,"t3_dn","T3-","Toggle 3-", 31,0,0);
+    la_AddButtonProp(pc,"t4_up","T4+","Toggle 4+", 32,0,0);
+    la_AddButtonProp(pc,"t4_dn","T4-","Toggle 4-", 33,0,0);
+    la_AddButtonProp(pc,"h3","H3","Hat 3 (Upper round hat)", 34,4,"N,E,S,W");
+    la_AddButtonProp(pc,"h4","H4","Hat 4 (lower jagged hat)", 38,4,"N,E,S,W");
+    la_AddButtonProp(pc,"pinky_up","P+","Pinky up", 42,0,0);
+    la_AddButtonProp(pc,"pinky_dn","P-","Pinky down", 43,0,0);
+    la_AddButtonProp(pc,"dial_fwd","D+","Dial forward", 44,0,0);
+    la_AddButtonProp(pc,"dial_back","D-","Dial backward", 45,0,0);
+    la_AddButtonProp(pc,"bball","BP","Ball push", 46,0,0);
+    la_AddButtonProp(pc,"slider","SLD","Slider", 47,0,0);
+    la_AddButtonProp(pc,"mode","Mode","Mode switch", 48,3,"M1,M2,S1");
 
 
     pc=laAddPropertyContainer("la_controller_x56_stick", "X56 Stick", "X56 Stick", 0,laui_X56Stick,sizeof(laController),0,0,1);

+ 13 - 0
la_interface.h

@@ -1029,6 +1029,12 @@ STRUCTURE(laUiTemplate){
     laKeyMapper KeyMap;
 };
 
+STRUCTURE(laCompoundPP){
+    laListItem Item;
+    int Slot;
+    laPropPack PP;
+};
+
 STRUCTURE(laUiItem){
     laListItem Item;
 
@@ -1045,6 +1051,7 @@ STRUCTURE(laUiItem){
     short Expand;
     short SymbolID;
     laPropPack PP;
+    laListHandle CompoundPPs;
     laSafeString *Display;
     laSafeString *ExtraInstructions;
 
@@ -1410,6 +1417,12 @@ STRUCTURE(laController){
     int NumButtons; int NumAxes; int UserAssignedID; int Error;
     int InternalType; // used to identify models and use specific props.
     int AxisValues[LA_JS_MAX_AXES];
+    int AxisMaxes[LA_JS_MAX_AXES]; // original max scaled to 32767;
+    int AxisMins[LA_JS_MAX_AXES];
+    int AxisLimitMaxes[LA_JS_MAX_AXES]; // calibrated max;
+    int AxisLimitMins[LA_JS_MAX_AXES];
+    int AxisCenterMaxes[LA_JS_MAX_AXES]; // calibrated center;
+    int AxisCenterMins[LA_JS_MAX_AXES];
     char ButtonValues[LA_JS_MAX_BUTTONS];
 };
 

+ 23 - 0
la_kernel.c

@@ -4226,6 +4226,20 @@ laUiItem *laShowSymbol(laUiList *uil, laColumn *c, int SymbolID, int Height){
 
     return ui;
 }
+laPropPack* laShowCompoundValue(laUiItem* ui, int slot, laPropPack *Base, const char *Path){
+    laPropPack PP={0}; int result;
+    if (Path){
+        result = la_GetPropFromPath(&PP, Base, Path, 0);
+        if (!result){ return 0; }
+        if (Base){ PP.RawThis = Base; }
+    }else if (Base){
+        PP.LastPs = Base->LastPs; PP.RawThis = Base; //HACK! Not Unified For Prop Access!!!<<<----------??????????
+    }
+    laCompoundPP* CPP = memAcquire(sizeof(laCompoundPP));
+    CPP->Slot = slot; memcpy(&CPP->PP, &PP, sizeof(laPropPack));
+    lstAppendItem(&ui->CompoundPPs,CPP);
+    return &CPP->PP;
+}
 
 laUiItem *laBeginRow(laUiList *uil, laColumn *c, int Expand, int Even){
     laUiItem *ui = memAcquireSimple(sizeof(laUiItem));
@@ -4881,6 +4895,10 @@ void la_DestroyUiItem(laUiItem *ui, int RemoveUsers){
     //    { /*la_StopUsingPropPack(&ui->PP);*/ }
         //laStopUsingDataBlock(ui->PP.LastPs->UseInstance,ui->PP.LastPs->p,MAIN.PropMatcherContextP);
     la_FreePropStepCache(ui->PP.Go); //-------[Up Here], instance already been freed.XXXXXXXXXXXX!!!!!!!!!!1
+
+    if (ui->CompoundPPs.pFirst){laCompoundPP* CPP;
+        while(CPP = lstPopItem(&ui->CompoundPPs)){ la_FreePropStepCache(CPP->PP.Go); memFree(CPP); }
+    }
     if (ui->Type->Destroy) ui->Type->Destroy(ui);
     memFree(ui);
 }
@@ -5204,6 +5222,11 @@ int la_UpdateUiListRecursive(laUiList *uil, int U, int L, int R, int B, int Fast
 
         if (ui->PP.LastPs){ la_StepPropPack(&ui->PP); }
         la_UsePropPack(&ui->PP, 0);
+        if (ui->CompoundPPs.pFirst){
+            for(laCompoundPP* CPP=ui->CompoundPPs.pFirst;CPP;CPP=CPP->Item.pNext){
+                la_StepPropPack(&CPP->PP); la_UsePropPack(&CPP->PP, 0);
+            }
+        }
 
         if(ui->Type==&_LA_UI_INVISIBLE){ ui=ui->Item.pNext; continue; }
 

+ 64 - 0
la_util.c

@@ -151,6 +151,70 @@ int nutSameAddress(void *l, void *r){
     return (l == r);
 }
 
+barray_t *barray_init(size_t num_bits)
+{
+    size_t num_longs = BITS_TO_LONGS(num_bits);
+    barray_t *barray = malloc(sizeof(unsigned long) * num_longs + sizeof(barray_t));
+    barray->num_bits = num_bits;
+    barray->num_longs = num_longs;
+    return barray;
+}
+void barray_free(barray_t *barray)
+{
+    free(barray);
+}
+unsigned long *barray_data(barray_t *barray)
+{
+    return barray->data;
+}
+size_t barray_count_set(barray_t *barray)
+{
+    size_t count = 0;
+    for (int i = 0; i < barray->num_longs; i++)
+        count += __builtin_popcountl(barray->data[i]);
+    return count;
+}
+void barray_set(barray_t *barray, bit_t bit)
+{
+    if (bit >= barray->num_bits)
+        return;
+
+    int index = bit / BITS_PER_LONG;
+    int shift = bit % BITS_PER_LONG;
+
+    barray->data[index] |= (1 << shift);
+}
+void barray_clear(barray_t *barray, bit_t bit)
+{
+    if (bit >= barray->num_bits)
+        return;
+
+    int index = bit / BITS_PER_LONG;
+    int shift = bit % BITS_PER_LONG;
+
+    barray->data[index] &= ~(1 << shift);
+}
+bool barray_is_set(barray_t *barray, bit_t bit)
+{
+    if (bit >= barray->num_bits)
+        return false;
+
+    int index = bit / BITS_PER_LONG;
+    int shift = bit % BITS_PER_LONG;
+    return (barray->data[index] & (1 << shift)) != 0;
+}
+void barray_foreach_set(barray_t *barray, barray_callback_t callback, void *arg)
+{
+    for (int i = 0; i < barray->num_longs; i++)
+    {
+        unsigned long bits = barray->data[i];
+        while (bits != 0)
+        {
+            callback(i * BITS_PER_LONG + __builtin_ctzl(bits), arg);
+            bits ^= (bits & -bits);
+        }
+    }    
+}
 //===================================================================[list]
 
 void* arrElement(void* head, int i, int size){

+ 25 - 0
la_util.h

@@ -739,6 +739,31 @@ char * transLate(char * Target);
 void transState(void* UNUSED, int val);
 void transInitTranslation_zh_cn();
 
+#include <stdlib.h>
+#include <stdbool.h>
+
+typedef struct barray barray_t;
+typedef unsigned bit_t;
+
+barray_t *barray_init(size_t num_bits);
+void barray_free(barray_t *barray);
+unsigned long *barray_data(barray_t *barray);
+size_t barray_count_set(barray_t *barray);
+void barray_set(barray_t *barray, bit_t bit);
+void barray_clear(barray_t *barray, bit_t bit);
+bool barray_is_set(barray_t *barray, bit_t bit);
+typedef void (*barray_callback_t)(bit_t bit, void *arg);
+void barray_foreach_set(barray_t *barray, barray_callback_t callback, void *arg);
+
+#define BITS_PER_LONG        (sizeof(unsigned long) * 8)
+#define BITS_TO_LONGS(n)     (((n) + BITS_PER_LONG - 1) / BITS_PER_LONG)
+
+struct barray
+{
+    size_t num_bits;
+    size_t num_longs;
+    unsigned long data[0];
+};
 
 void laOpenInternetLink(char* url);