baseline working thinkpad nipple driver master
authorThomas Balzer <niebieskitrociny@gmail.com>
Mon, 7 Sep 2020 11:28:49 +0000 (07:28 -0400)
committerThomas Balzer <niebieskitrociny@gmail.com>
Mon, 7 Sep 2020 11:28:49 +0000 (07:28 -0400)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
tlb.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..140f8cf
--- /dev/null
@@ -0,0 +1 @@
+*.so
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..b161e19
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,5 @@
+all:tlb.c
+       gcc -I/usr/local/include/pixman-1 tlb.c -fPIC --shared -o tlb_drv.so
+
+install:
+       cp tlb_drv.so /usr/local/lib/xorg/modules/input
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..3d734f7
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+test x11 driver???
\ No newline at end of file
diff --git a/tlb.c b/tlb.c
new file mode 100644 (file)
index 0000000..5ce6351
--- /dev/null
+++ b/tlb.c
@@ -0,0 +1,377 @@
+/* test driver to make sure i can do things... */
+
+/* _X_EXPORT defined in /usr/local/include/X11/Xfuncproto.h,
+            included by /usr/local/include/xorg/xf86.h */
+#include <xorg/xf86.h>
+
+/* so the version macros exist */
+#include <xorg/xorg-server.h>
+
+/* XF86ModuleData is defined in /usr/local/include/xorg/xf86Module.h */
+/* #include <xorg/xf86Module.h> */
+/*  NOTE: this is done by xf86Xinput.h */
+#include <xorg/xf86Xinput.h>
+
+#include <xorg/xserver-properties.h>
+#include <xorg/exevents.h>
+
+#include <errno.h>
+#include <fcntl.h>                             /* open, creat */
+#include <unistd.h>                            /* close */
+#include <linux/input.h>
+
+enum codes { 
+  TP_STICK_HORI  = 0,
+  TP_STICK_VERT  = 1,
+  TP_LEFT   = 272, 
+  TP_RIGHT  = 273, 
+  TP_MIDDLE = 274, 
+};
+
+enum type {
+  TP_NOP    = 0,
+  TP_BUTTON = 1,
+  TP_STICK  = 2,
+};
+
+enum button {
+  TP_BUTTON_UP   = 0,
+  TP_BUTTON_DOWN = 1,
+};
+
+struct tlb_device_private_data {
+  int fd;
+  ValuatorMask *valuators;
+  unsigned char btnmap[4];             /* left/right/middle */
+};
+
+/* lifted from libinput */
+static void tlb_ptr_ctl(DeviceIntPtr dev, PtrCtrl *ctl)
+{
+  InputInfoPtr pInfo = dev->public.devicePrivate;
+  xf86IDrvMsg(pInfo, X_ERROR, "tlb_ptr_ctl NOT IMPLEMENTED\n");  
+}
+
+static int tlb_device_init(DeviceIntPtr dev)
+{
+  InputInfoPtr pInfo = dev->public.devicePrivate;
+  xf86IDrvMsg(pInfo, X_INFO, "tlb_device_control (DEVICE_INIT) \n");
+  
+  struct tlb_device_private_data *priv = pInfo->private;
+  char *device = xf86CheckStrOption(pInfo->options, "Device", NULL);
+  xf86IDrvMsg(pInfo, X_INFO, "attempting to open device '%s'.\n", device);
+  
+  priv->fd = open(device, O_RDONLY);
+  if(-1 == priv->fd){
+       xf86IDrvMsg(pInfo, X_ERROR, "FAILED TO OPEN '%s'. (errno=%d).\n", device, errno);       
+       return BadValue;
+  }
+  
+  xf86IDrvMsg(pInfo, X_INFO, "Opened '%s' successfully.\n", device);
+  
+  /* lifted from libinput driver */
+  Atom btnlabels[3];
+  btnlabels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
+  btnlabels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
+  btnlabels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
+  
+  Atom axislabels[2];
+  axislabels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
+  axislabels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
+  /* labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL); */
+  /* labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_VSCROLL); */
+  
+  priv->btnmap[1] = 1;
+  priv->btnmap[2] = 2;
+  priv->btnmap[3] = 3;
+  InitPointerDeviceStruct((DevicePtr)dev,
+                                                 priv->btnmap,
+                                                 3,
+                                                 btnlabels,
+                                                 tlb_ptr_ctl, /* why can't be null */
+                                                 GetMotionHistorySize(), /* ??? */
+                                                 2,
+                                                 axislabels);
+  
+  /* ???? */
+  int min, max, res;
+  min = -1;
+  max = -1;
+  res = 0;
+  
+  xf86InitValuatorAxisStruct(dev, 0,
+                                                        XIGetKnownProperty(AXIS_LABEL_PROP_REL_X),
+                                                        min, max, res * 1000, 0, res * 1000, Relative);
+  xf86InitValuatorDefaults(dev, 0);
+  xf86InitValuatorAxisStruct(dev, 1,
+                                                        XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y),
+                                                        -1, -1, 1, 0, 1, Relative);
+  xf86InitValuatorDefaults(dev, 1);
+  
+  /* TODO */
+  /* axis def??? x,y,vscroll,hscroll */
+  return Success;
+}
+
+static int tlb_device_on(DeviceIntPtr dev)
+{
+  InputInfoPtr pInfo = dev->public.devicePrivate;
+  xf86IDrvMsg(pInfo, X_INFO, "tlb_device_control (DEVICE_ON) Partially implemented\n"); 
+  
+  /* start up pthread polling or something? */
+  struct tlb_device_private_data *priv = pInfo->private;  
+  pInfo->fd = priv->fd;
+  xf86AddEnabledDevice(pInfo);
+
+  /* TODO: implement */
+  return Success;
+}
+
+static int tlb_device_off(DeviceIntPtr dev)
+{
+  InputInfoPtr pInfo = dev->public.devicePrivate;
+  xf86IDrvMsg(pInfo, X_INFO, "tlb_device_control (DEVICE_OFF) Partially implemented\n");
+  
+  /* shutdown polling pthread or something? */
+  xf86RemoveEnabledDevice(pInfo);
+  
+  /* TODO: implement */
+  return Success;
+}
+
+static int tlb_device_close(DeviceIntPtr dev)
+{
+  InputInfoPtr pInfo = dev->public.devicePrivate;
+  xf86IDrvMsg(pInfo, X_INFO, "tlb_device_control (DEVICE_CLOSE) Partially implemented\n");
+  
+  struct tlb_device_private_data *priv = pInfo->private;
+  char *device = xf86CheckStrOption(pInfo->options, "Device", NULL);
+  
+  if(-1 != priv->fd){
+       if(-1 == close(priv->fd)){
+         xf86IDrvMsg(pInfo, X_ERROR, "FAILED TO CLOSE '%s'. (errno=%d).\n", device, errno);    
+         return BadValue;
+       }
+       
+       priv->fd = -1;
+       xf86IDrvMsg(pInfo, X_INFO, "Closed '%s' successfully.\n", device);
+  }
+  
+  return Success;
+}
+
+static int tlb_device_abort(DeviceIntPtr dev)
+{
+  InputInfoPtr pInfo = dev->public.devicePrivate;
+  xf86IDrvMsg(pInfo, X_ERROR, "tlb_device_control (DEVICE_ABORT) NOT IMPLEMENTED\n");
+  return BadValue;
+}
+
+static int tlb_device_control(DeviceIntPtr dev, int mode)
+{
+  int retval = BadValue;
+  /* TODO: implement */
+  switch(mode){
+       /* defined in /usr/local/include/xorg/input.h */
+  case DEVICE_INIT:
+       retval = tlb_device_init(dev);
+       break;
+  case DEVICE_ON:
+       retval = tlb_device_on(dev);
+       break;
+  case DEVICE_OFF:
+       retval = tlb_device_off(dev);
+       break;
+  case DEVICE_CLOSE:
+       retval = tlb_device_close(dev);
+       break;
+  case DEVICE_ABORT:
+       retval = tlb_device_abort(dev);
+       break;
+  };
+  return retval;
+}
+
+static void tlb_read_input(InputInfoPtr pInfo)
+{
+  /* TODO: implement */
+  /* xf86IDrvMsg(pInfo, X_ERROR, "tlb_read_input NOT IMPLEMENTED\n"); */
+  DeviceIntPtr dev = pInfo->dev;
+  struct tlb_device_private_data *priv = pInfo->private;
+  
+    /* 48, 72 bytes. seems like 100 is fine. */
+#define BUF_SIZ 1000
+  static unsigned char buf[BUF_SIZ] = {};
+  ssize_t cnt = 0;
+  /* do one at a time, xorg server will call use when we have more events */
+  if(0 < (cnt = read(pInfo->fd, buf, BUF_SIZ))){
+       /* we are _always_ supposed to get a whole number of events on a read. */
+       unsigned char *cur = buf;
+       int x = 0, y = 0;
+       char hasx = 0, hasy = 0;
+       while(cnt != 0){
+         char isx = 0, isy = 0;
+         struct input_event *ev = (struct input_event *)cur;     
+         cnt -= sizeof(struct input_event);
+         cur += sizeof(struct input_event);
+         
+         /* dump the event we got i guess */
+         char *code_str, *type_str, *button_str;
+         switch(ev->type){
+         case TP_BUTTON: { code_str = " BUTT"; break; }
+         case TP_STICK:  { code_str = "STICK"; break; }
+         case TP_NOP:
+         default:{
+               /* skip entirely */
+               continue;                               /* while loop */
+         }
+         }
+         
+         switch(ev->code){
+         case TP_STICK_HORI:{
+               hasx = 1;
+               isx = 1;
+               if(ev->value > 0)
+                 type_str = "RIGHT";
+               else
+                 type_str = " LEFT";
+               break;
+         }
+         case TP_STICK_VERT:{
+               hasy = 1;
+               isy = 1;
+               if(ev->value > 0)
+                 type_str = " DOWN";
+               else
+                 type_str = "   UP";
+               break;
+         }
+         case TP_LEFT:  { 
+               type_str = " LEFT"; 
+               xf86PostButtonEvent(dev, 0, 1, ev->value, 0, 0);
+               break; 
+         }
+         case TP_RIGHT: { 
+               type_str = "RIGHT"; 
+               xf86PostButtonEvent(dev, 0, 3, ev->value, 0, 0);
+               break; 
+         }
+         case TP_MIDDLE:{ 
+               type_str = "  MID";
+               xf86PostButtonEvent(dev, 0, 2, ev->value, 0, 0);
+               break;
+         }
+         }
+         
+         char output_msg[200];
+         
+         int offset = sprintf(output_msg,
+                                                  "%d.%09d: %s %s ", 
+                                                  ev->input_event_sec, ev->input_event_usec,
+                                                  type_str, code_str);
+         
+         if(ev->type == TP_BUTTON){
+               switch(ev->value){
+               case TP_BUTTON_UP:  { sprintf(output_msg + offset, "  UP\n"); break; }
+               case TP_BUTTON_DOWN:{ sprintf(output_msg + offset, "DOWN\n"); break; }
+               }
+         }else{
+               sprintf(output_msg + offset, "%d\n", ev->value);
+               if(isx){
+                 x = ev->value;
+               }
+               if(isy){
+                 y = ev->value;
+               }
+         }
+         
+         xf86IDrvMsg(pInfo, X_INFO, output_msg);
+       }
+       
+       ValuatorMask *mask = priv->valuators;
+       valuator_mask_zero(mask);
+       
+       if(hasx){
+         valuator_mask_set_double(mask, 0, x);
+       }
+       if(hasy){
+         valuator_mask_set_double(mask, 1, y);
+       }
+       if(hasx || hasy){
+         /* xf86PostMotionEventM(dev, Relative, mask); */
+         /* xf86IDrvMsg(pInfo, X_INFO, "Posting motion with x=%d, y=%d\n"); */
+         xf86PostMotionEvent(dev, 0, 0, 2, x, y);
+       }
+  }
+}
+
+static int tlb_pre_init(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
+{  
+  /* TODO: have to __actually__ make a driver, it turns out */
+  pInfo->type_name = 0;
+  pInfo->device_control = tlb_device_control;
+  pInfo->read_input = tlb_read_input;
+  pInfo->control_proc = NULL;
+  pInfo->switch_mode = NULL;
+  
+  /* my own data i guess */
+  pInfo->private = malloc(sizeof(struct tlb_device_private_data));
+  ((struct tlb_device_private_data *)pInfo->private)->fd = -1;
+  ((struct tlb_device_private_data *)pInfo->private)->valuators = valuator_mask_new(6);
+  
+  /* TODO: init driver data... i guess */
+  
+  xf86IDrvMsg(pInfo, X_INFO, "init for driver 'tlb' SUCCEEDED.\n");
+  
+  pInfo->type_name = XI_MOUSE;
+  return Success;
+}
+
+static void tlb_uninit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
+{
+  if(NULL != pInfo->private){
+       /* this seg faults it seems.... */
+       /* free(pInfo->private); */
+       valuator_mask_free(&((struct tlb_device_private_data *)pInfo->private)->valuators);
+  }
+  
+  /* TODO: things */
+  xf86DeleteInput(pInfo, flags);
+}
+
+InputDriverRec tlb_driver = {
+  .driverVersion   = 1,
+  .driverName      = "tlb",
+  .PreInit         = tlb_pre_init,
+  .UnInit          = tlb_uninit,
+  .module          = NULL,
+  .default_options = NULL,
+};
+
+static pointer tlb_setup_proc(pointer module, pointer options, int *errmaj, int *errmin)
+{
+  xf86AddInputDriver(&tlb_driver, module, 0);
+  return module;
+}
+
+/* This structure is expected to be returned by the initfunc */
+static XF86ModuleVersionInfo tlb_mod_version = {
+  .modname = "tlb-track",        /* name of module, e.g. "foo" */
+  .vendor  = MODULEVENDORSTRING,         /* vendor specific string */
+  ._modinfo1_ = MODINFOSTRING1,          /* constant MODINFOSTRING1/2 to find */
+  ._modinfo2_ = MODINFOSTRING2,          /* infoarea with a binary editor or sign tool */
+  .xf86version = XORG_VERSION_CURRENT,
+  .majorversion = 0,         /* module-specific major version */
+  .minorversion = 0,         /* module-specific minor version */
+  .patchlevel = 2,          /* module-specific patch level */
+  .abiclass = ABI_CLASS_XINPUT,       /* ABI class that the module uses */
+  .abiversion =ABI_XINPUT_VERSION,          /* ABI version */
+  .moduleclass = MOD_CLASS_XINPUT,    /* module class description */
+  .checksum = { 0, 0, 0, 0 },         /* contains a digital signature of the */
+};
+
+_X_EXPORT XF86ModuleData tlbModuleData = {
+  .vers     = &tlb_mod_version,
+  .setup    = tlb_setup_proc,
+  .teardown = NULL,
+};