chiark / gitweb /
hostside: wip test programs etc. for Joytech Neo S gamepad
authorIan Jackson <ian@liberator.relativity.greenend.org.uk>
Wed, 19 Jan 2011 18:07:11 +0000 (18:07 +0000)
committerIan Jackson <ian@liberator.relativity.greenend.org.uk>
Sun, 30 Jan 2011 19:22:05 +0000 (19:22 +0000)
hostside/.gitignore
hostside/Makefile
hostside/hiddev-ioctl.c [new file with mode: 0644]
hostside/hidraw-ioctl.c [new file with mode: 0644]
hostside/hidraw.h [new file with mode: 0644]
hostside/kdled-ioctl.c [new file with mode: 0644]
neo-s.pl [new file with mode: 0755]

index 7238cd84eba1a8cc48ef170f668976c1e90c8170..b47722d0d0f4ca5c7f731b0b3270023bdbc599ed 100644 (file)
@@ -28,3 +28,6 @@ record-y.[ch]
 evdev-manip
 input-codes.h
 +dump.*
+hiddev-ioctl
+hidraw-ioctl
+kdled-ioctl
index 9bf760957f054dfdbd571ba5f07e2ff927395760..9cdce76a03160300762a14a8a41c63ac3a3bbf11 100644 (file)
@@ -39,6 +39,8 @@ topology-dump:        topology-dump.o utils.o $(LAYOUT_DATA).o
 
 evdev-manip:   evdev-manip.o utils.o $(LIBOOP_OBJS)
 
+hid%-ioctl:    $@.o utils.o
+
 gui-plan-bot: gui-plan-%:  gui-plan.o utils.o parseutils.o obc.o       \
                        ../layout/ours.dgram-%.plandata.o               \
                        $(LAYOUT_DATA).o $(LIBOOP_OBJS)
diff --git a/hostside/hiddev-ioctl.c b/hostside/hiddev-ioctl.c
new file mode 100644 (file)
index 0000000..d6fd11c
--- /dev/null
@@ -0,0 +1,119 @@
+/**/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include <linux/types.h>
+#include <linux/hiddev.h>
+
+#include "common.h"
+
+#if 0
+static void dump(const void *pu, int l) {
+  const uint8_t *p= pu;
+  while (l>0) {
+    printf("%02x",*p++);
+    l--;
+  }
+  putchar(' ');
+}
+#endif
+
+static void report_scan(const char *which, int type) {
+  struct hiddev_report_info rinfo;
+  int r, i, j;
+  int fd=0;
+
+  rinfo.report_type = type;
+  rinfo.report_id = HID_REPORT_ID_FIRST;
+
+  for (;;) {
+    r = ioctl(fd, HIDIOCGREPORTINFO, &rinfo);
+    if (r && errno==EINVAL) break;
+    if (r) diee("HIDIOCGREPORTINFO");
+
+    printf("%s type=%08"PRIx32" id=%08"PRIx32" num_fields=%08"PRIx32"\n",
+          which, rinfo.report_type, rinfo.report_id, rinfo.num_fields);
+    for (i=0; i < rinfo.num_fields; i++) {
+      struct hiddev_field_info finfo;
+      finfo.report_type= rinfo.report_type;
+      finfo.report_id= rinfo.report_id;
+      finfo.field_index= i;
+      r= ioctl(fd, HIDIOCGFIELDINFO, &finfo);
+      if (r) diee("HIDIOCGFIELDINFO");
+      printf("%s type=%08"PRIx32" id=%08"PRIx32" fi=%08"PRIx32
+            " maxusage=%08"PRIx32" flags=%08"PRIx32
+            " phys=%08"PRIx32"/log=%08"PRIx32"/app=%08"PRIx32
+            " log=%08"PRIx32"..%08"PRIx32
+            " phys=%08"PRIx32"..%08"PRIx32
+            "\n",
+            which, finfo.report_type, finfo.report_id, finfo.field_index,
+            finfo.maxusage, finfo.flags,
+            finfo.physical, finfo.logical, finfo.application,
+            finfo.logical_minimum, finfo.logical_maximum,
+            finfo.physical_minimum, finfo.physical_maximum
+            );
+      for (j=0; j < finfo.maxusage; j++) {
+       struct hiddev_usage_ref uref;
+       uref.report_type= finfo.report_type;
+       uref.report_id= finfo.report_id;
+       uref.field_index= i;
+       uref.usage_index= j;
+       r= ioctl(fd, HIDIOCGUCODE, &uref);
+//dump(&uref,sizeof(uref));
+       r= ioctl(fd, HIDIOCGUSAGE, &uref);
+//dump(&uref,sizeof(uref));
+       printf("%s type=%08"PRIx32" id=%08"PRIx32" fi=%08"PRIx32
+              " ui=%08"PRIx32" uc=%08"PRIx32" val=%08"PRIx32"\n",
+              which, uref.report_type, uref.report_id, uref.field_index,
+              uref.usage_index, uref.usage_code, uref.value);
+      }
+    }
+    rinfo.report_id |= HID_REPORT_ID_NEXT;
+  }
+}
+
+void die_vprintf_hook(const char *fmt, va_list al) { }
+void die_hook(void) { }
+const char *progname= "hiddev-ioctl";
+
+int main(int argc, char **argv) {
+  int r;
+  if (!argv[0] || !argv[1]) badusage("too few args");
+  const char *act= *++argv;
+  if (!strcmp(act, "scan")) {
+    report_scan("input", HID_REPORT_TYPE_INPUT);
+    report_scan("output", HID_REPORT_TYPE_OUTPUT);
+  } else if (!strcmp(act, "send")) {
+    /* type id field val */
+    if (!argv[1] || !argv[2] || !argv[3] || !argv[4]
+        || !argv[5] || !argv[6] || argv[7])
+      badusage("wrong # args");
+    struct hiddev_usage_ref uref;
+    struct hiddev_report_info rinfo;
+    uref.report_type= strtoul(argv[1],0,0);
+    uref.report_id=   strtoul(argv[2],0,0);
+    uref.field_index= strtoul(argv[3],0,0);
+    uref.usage_index= strtoul(argv[4],0,0);
+    uref.usage_code=  strtoul(argv[5],0,0);
+    uref.value=        strtol(argv[6],0,0);
+    rinfo.report_type= uref.report_type;
+    rinfo.report_id=   uref.report_id;
+    rinfo.num_fields=  0;
+//    r= ioctl(0, HIDIOCGREPORT, &rinfo);    if (r) diee("HIDIOCGREPORT");
+//    r= ioctl(0, HIDIOCGUSAGE, &uref);    if (r) diee("HIDIOCGUSAGE");
+//dump(&uref,sizeof(uref));
+//    printf("%08"PRIx32"...",uref.value);
+    r= ioctl(0, HIDIOCSUSAGE, &uref);    if (r) diee("HIDIOCSUSAGE");
+    r= ioctl(0, HIDIOCSREPORT, &rinfo);  if (r) diee("HIDIOCSREPORT");
+  } else {
+    badusage("unknown action");
+  }
+  return 0;
+}
diff --git a/hostside/hidraw-ioctl.c b/hostside/hidraw-ioctl.c
new file mode 100644 (file)
index 0000000..e5ac44a
--- /dev/null
@@ -0,0 +1,64 @@
+/**/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include <linux/types.h>
+
+#include "hidraw.h"
+
+#include "common.h"
+
+static void dump(const void *pu, int l) {
+  const uint8_t *p= pu;
+  while (l>0) {
+    printf("%02x",*p++);
+    l--;
+  }
+  putchar(' ');
+}
+
+int main(int argc, char **argv) {
+  int r, descsz;
+
+  r= ioctl(0, HIDIOCGRDESCSIZE, &descsz);
+  if (r) {
+    perror("HIDIOCGRDESCSIZE");
+  } else {
+    printf("%d\n",descsz);
+    struct {
+      struct hidraw_report_descriptor d;
+      unsigned char buf[descsz];
+    } d;
+    d.d.size = descsz;
+    r= ioctl(0, HIDIOCGRDESC, &d);
+    if (r) perror("HIDIOCGRDESC");
+    else { dump(d.d.value, d.d.size); putchar('\n'); }
+  }
+
+  struct hidraw_devinfo di;
+  r= ioctl(0, HIDIOCGRAWINFO, &di);
+  if (r) perror("HIDIOCGRAWINFO");
+  else {
+    printf("%08"PRIx32" %04"PRIx16" %04"PRIx16"\n",
+          di.bustype, di.vendor, di.product);
+  }
+
+  unsigned char buf[PATH_MAX];
+
+  r= ioctl(0, HIDIOCGRAWNAME(PATH_MAX), buf);
+  if (r<0) perror("HIDIOCGRAWNAME");
+  else printf("%d %.*s\n", r, r,buf);
+
+  r= ioctl(0, HIDIOCGRAWPHYS(PATH_MAX), buf);
+  if (r<0) perror("HIDIOCGRAWPHYS");
+  else printf("%d %.*s\n", r, r,buf);
+
+  return 0;
+}
diff --git a/hostside/hidraw.h b/hostside/hidraw.h
new file mode 100644 (file)
index 0000000..dd8d692
--- /dev/null
@@ -0,0 +1,89 @@
+#ifndef _HIDRAW_H
+#define _HIDRAW_H
+
+/*
+ *  Copyright (c) 2007 Jiri Kosina
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/hid.h>
+#include <linux/types.h>
+
+struct hidraw_report_descriptor {
+       __u32 size;
+       __u8 value[HID_MAX_DESCRIPTOR_SIZE];
+};
+
+struct hidraw_devinfo {
+       __u32 bustype;
+       __s16 vendor;
+       __s16 product;
+};
+
+/* ioctl interface */
+#define HIDIOCGRDESCSIZE       _IOR('H', 0x01, int)
+#define HIDIOCGRDESC           _IOR('H', 0x02, struct hidraw_report_descriptor)
+#define HIDIOCGRAWINFO         _IOR('H', 0x03, struct hidraw_devinfo)
+#define HIDIOCGRAWNAME(len)     _IOC(_IOC_READ, 'H', 0x04, len)
+#define HIDIOCGRAWPHYS(len)     _IOC(_IOC_READ, 'H', 0x05, len)
+
+#define HIDRAW_FIRST_MINOR 0
+#define HIDRAW_MAX_DEVICES 64
+/* number of reports to buffer */
+#define HIDRAW_BUFFER_SIZE 64
+
+
+/* kernel-only API declarations */
+#ifdef __KERNEL__
+
+struct hidraw {
+       unsigned int minor;
+       int exist;
+       int open;
+       wait_queue_head_t wait;
+       struct hid_device *hid;
+       struct device *dev;
+       struct list_head list;
+};
+
+struct hidraw_report {
+       __u8 *value;
+       int len;
+};
+
+struct hidraw_list {
+       struct hidraw_report buffer[HIDRAW_BUFFER_SIZE];
+       int head;
+       int tail;
+       struct fasync_struct *fasync;
+       struct hidraw *hidraw;
+       struct list_head node;
+       struct mutex read_mutex;
+};
+
+#ifdef CONFIG_HIDRAW
+int hidraw_init(void);
+void hidraw_exit(void);
+void hidraw_report_event(struct hid_device *, u8 *, int);
+int hidraw_connect(struct hid_device *);
+void hidraw_disconnect(struct hid_device *);
+#else
+static inline int hidraw_init(void) { return 0; }
+static inline void hidraw_exit(void) { }
+static inline void hidraw_report_event(struct hid_device *hid, u8 *data, int len) { }
+static inline int hidraw_connect(struct hid_device *hid) { return -1; }
+static inline void hidraw_disconnect(struct hid_device *hid) { }
+#endif
+
+#endif
+
+#endif
diff --git a/hostside/kdled-ioctl.c b/hostside/kdled-ioctl.c
new file mode 100644 (file)
index 0000000..c55d5a9
--- /dev/null
@@ -0,0 +1,18 @@
+/**/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <linux/kd.h>
+
+int main(int argc, char **argv) {
+  uint8_t l;
+  int r;
+  r= ioctl(0, KDGETLED, &l);
+  if (r<0) { perror("KDGETLED"); exit(-1); }
+  printf("%02x\n", l);
+  return 0;
+}
diff --git a/neo-s.pl b/neo-s.pl
new file mode 100755 (executable)
index 0000000..f8f0c37
--- /dev/null
+++ b/neo-s.pl
@@ -0,0 +1,20 @@
+#!/usr/bin/perl
+$|=1;
+for ($a=0x43; $a<=0x53; $a+=0x10) {
+    next if $a eq 0x46;
+#for ($b=90; $b<=95; $b++) {
+    $b=0xff;
+printf STDERR "%02x %02x\n", $b, $a;
+#next if $a eq 0x46;
+    print pack("c*", 0xff, $b,$a) or die $!;
+#}
+printf STDERR "---\n";
+#sleep 1;# if !($a & 0x0f);
+}    
+
+__END__
+
+speed,0x00,0x46 rumble
+ ??,0x00,0x43   ?? is something to do with mouse acceleration; with ??=0
+                  no mice visible
+0xff,0x00,0x53  swaps things round