* [9front] [patch] nusb/ joy: xbox360 controller support and improved hid parsing
@ 2024-10-19 12:44 Arne Meyer
2024-10-19 12:59 ` qwx
2024-11-09 13:32 ` Arne Meyer
0 siblings, 2 replies; 3+ messages in thread
From: Arne Meyer @ 2024-10-19 12:44 UTC (permalink / raw)
To: 9front
[-- Attachment #1: Type: text/plain, Size: 304 bytes --]
Hello,
this patch adds some improvements to nusb/joy.
Support for xbox360 controllers.
Up to six axes are now supported for analog input.
The DPad gets mapped to buttons 16-19.
Added a simple deadband filter for analog axes.
Thanks qwx for feedback and help with the man page changes!
Greetings,
Arne
[-- Attachment #2: nusbjoy.patch --]
[-- Type: application/octet-stream, Size: 5600 bytes --]
diff 0c4e4cb9e92e372dc0cb3df182790dc0b1c757ad uncommitted
--- a/sys/man/4/nusb
+++ b/sys/man/4/nusb
@@ -44,6 +44,9 @@
.B nusb/joy
[
.B -d
+] [
+.B -b
+.I deadband
]
.I devid
.PP
@@ -190,7 +193,7 @@
any changes in the device's axes or buttons.
Buttons are identified via an integer id.
.PP
-Directional buttons are reported as axes
+Directional buttons are reported either as buttons or axes
with 3 positions:
.IR 0 ,
.IR 128 ,
@@ -198,6 +201,12 @@
.I 255
for left (or up), center and right (or down) respectively.
Messages are in the form \fIaxis id position\fR.
+.PP
+A deadband in the range of
+.RI [ 0.0 , 1.0 ]
+can be set with the
+.B \-b
+option to filter out input below a threshold on all analog axes.
.PP
On/off buttons are reported as either
.I down
--- a/sys/src/cmd/nusb/joy/hid.h
+++ b/sys/src/cmd/nusb/joy/hid.h
@@ -7,8 +7,9 @@
/* HID class subclass protocol ids */
JoyCSP = 0x000003,
+ Xbox360CSP = 0x015dff,
- Maxaxes = 3,
+ Maxaxes = 6,
/* Requests */
Getreport = 0x01,
@@ -74,4 +75,88 @@
Flinear = 0<<4, Fnonlin = 1<<4,
Fpref = 0<<5, Fnopref = 1<<5,
Fnonull = 0<<6, Fnullst = 1<<6,
+};
+
+uchar xbox360desc[] = {
+ 0x05, 0x01,
+ 0x09, 0x05,
+ 0xa1, 0x01,
+ 0x75, 0x08,
+ 0x95, 0x01,
+ 0x81, 0x01,
+ 0x75, 0x08,
+ 0x95, 0x01,
+ 0x05, 0x01,
+ 0x09, 0x3b,
+ 0x81, 0x01,
+ 0x05, 0x01,
+ 0x09, 0x01,
+ 0xa1, 0x00,
+ 0x75, 0x01,
+ 0x15, 0x00,
+ 0x25, 0x01,
+ 0x35, 0x00,
+ 0x45, 0x01,
+ 0x95, 0x04,
+ 0x05, 0x01,
+ 0x09, 0x90,
+ 0x09, 0x91,
+ 0x09, 0x93,
+ 0x09, 0x92,
+ 0x81, 0x02,
+ 0xc0,
+ 0x75, 0x01,
+ 0x15, 0x00,
+ 0x25, 0x01,
+ 0x35, 0x00,
+ 0x45, 0x01,
+ 0x95, 0x07,
+ 0x05, 0x09,
+ 0x09, 0x08,
+ 0x09, 0x07,
+ 0x09, 0x09,
+ 0x09, 0x0a,
+ 0x09, 0x05,
+ 0x09, 0x06,
+ 0x09, 0x0b,
+ 0x81, 0x02,
+ 0x75, 0x01,
+ 0x95, 0x01,
+ 0x81, 0x01,
+ 0x75, 0x01,
+ 0x15, 0x00,
+ 0x25, 0x01,
+ 0x35, 0x00,
+ 0x45, 0x01,
+ 0x95, 0x04,
+ 0x05, 0x09,
+ 0x19, 0x01,
+ 0x29, 0x04,
+ 0x81, 0x02,
+ 0x75, 0x08,
+ 0x15, 0x00,
+ 0x26, 0xff, 0x00,
+ 0x35, 0x00,
+ 0x46, 0xff, 0x00,
+ 0x95, 0x02,
+ 0x05, 0x01,
+ 0x09, 0x32,
+ 0x09, 0x35,
+ 0x81, 0x02,
+ 0x75, 0x10,
+ 0x16, 0x00, 0x80,
+ 0x26, 0xff, 0x7f,
+ 0x36, 0x00, 0x80,
+ 0x46, 0xff, 0x7f,
+ 0x95, 0x04,
+ 0x05, 0x01,
+ 0x09, 0x30,
+ 0x09, 0x31,
+ 0x09, 0x33,
+ 0x09, 0x34,
+ 0x81, 0x02,
+ 0x75, 0x30,
+ 0x95, 0x01,
+ 0x81, 0x01,
+ 0xc0,
};
--- a/sys/src/cmd/nusb/joy/joy.c
+++ b/sys/src/cmd/nusb/joy/joy.c
@@ -47,6 +47,7 @@
}
static int debug, kbd;
+static double deadband;
static int
signext(int v, int bits)
@@ -219,8 +220,7 @@
fprint(2, "\n");
}
proto = Reportproto;
- }else
- kbfatal(f, "no report");
+ }
/*
* if a HID's subclass code is 1 (boot mode), it will support
@@ -283,15 +283,28 @@
case 0x010030:
case 0x010031:
case 0x010032:
+ case 0x010033:
+ case 0x010034:
+ case 0x010035:
i = l[Usage] - 0x010030;
if((f & (Fabs|Frel)) == Fabs)
- p->axes[i] = v;
+ p->axes[i] = (abs(v)<(g[LogiMax]*deadband))?0:v;
else
- p->axes[i] += v;
+ p->axes[i] += (abs(v)<(g[LogiMax]*deadband))?0:v;
break;
+
+ case 0x010090:
+ case 0x010091:
+ case 0x010092:
+ case 0x010093:
+ m = 1ULL << (l[Usage] & 0x1f);
+ p->btns &= ~m;
+ if(v != 0)
+ p->btns |= m;
+ break;
}
if((l[Usage] >> 16) == 0x09){
- m = 1ULL << (l[Usage] & 0xff);
+ m = 1ULL << (l[Usage] & 0x0f);
p->btns &= ~m;
if(v != 0)
p->btns |= m;
@@ -365,11 +378,15 @@
/* apply quirks for special devices */
static void
-quirks(Dev *d)
+quirks(KDev *kd)
{
int ret;
+ Dev *d;
uchar buf[17];
+ static uchar xbox360ledcmd[] = {1,3,0};
+ d = kd->dev;
+
/* sony dualshock 3 (ps3) controller requires special enable command */
if(d->usb->vid == 0x054c && d->usb->did == 0x0268){
ret = usbcmd(d, Rd2h|Rclass|Riface, Getreport, (0x3<<8) | 0xF2, 0, buf, sizeof(buf));
@@ -376,6 +393,15 @@
if(ret < 0)
sysfatal("failed to enable ps3 controller: %r");
}
+
+ /* XBox360 controller returns no HID descriptor, so we provide one */
+ if(d->usb->vid == 0x045e && d->usb->did == 0x028e
+ || d->usb->vid == 0x1bad && d->usb->did == 0xf03a){
+ memcpy(kd->rep, xbox360desc, sizeof(xbox360desc));
+ kd->nrep = sizeof(xbox360desc);
+ /* no blinken lights */
+ usbcmd(d, Rh2d|Rclass|Riface, Setreport, Reportout, 0, xbox360ledcmd, 3);
+ }
}
static void
@@ -399,7 +425,9 @@
fprint(2, "%s: %s: opendevdata: %r\n", argv0, kd->ep->dir);
goto Err;
}
- quirks(kd->dev);
+ quirks(kd);
+ if(kd->nrep == 0) kbfatal(kd, "no report");
+
f(kd);
return;
Err:
@@ -409,7 +437,7 @@
static void
usage(void)
{
- fprint(2, "usage: %s [-d] devid\n", argv0);
+ fprint(2, "usage: %s [-d] [-b deadband] devid\n", argv0);
threadexits("usage");
}
@@ -420,11 +448,16 @@
Dev *d;
Ep *ep;
Usbdev *ud;
+ char *b;
ARGBEGIN{
case 'd':
debug++;
break;
+ case 'b':
+ b = EARGF(usage());
+ deadband = atof(b);
+ if(deadband > 0.0 && deadband < 1.0) break;
default:
usage();
}ARGEND;
@@ -438,8 +471,10 @@
for(i = 0; i < nelem(ud->ep); i++){
if((ep = ud->ep[i]) == nil)
continue;
- if(ep->type == Eintr && ep->dir == Ein && ep->iface->csp == JoyCSP)
- break;
+ if(ep->type != Eintr || (ep->dir == Eout))
+ continue;
+ if(ep->iface->csp == JoyCSP) break;
+ if(ep->iface->csp == Xbox360CSP) break;
}
if(ep == nil)
sysfatal("no suitable endpoint found");
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [9front] [patch] nusb/ joy: xbox360 controller support and improved hid parsing
2024-10-19 12:44 [9front] [patch] nusb/ joy: xbox360 controller support and improved hid parsing Arne Meyer
@ 2024-10-19 12:59 ` qwx
2024-11-09 13:32 ` Arne Meyer
1 sibling, 0 replies; 3+ messages in thread
From: qwx @ 2024-10-19 12:59 UTC (permalink / raw)
To: 9front
On Sat Oct 19 14:44:48 +0200 2024, meyer.arne83@netcologne.de wrote:
> Hello,
>
> this patch adds some improvements to nusb/joy.
>
> Support for xbox360 controllers.
> Up to six axes are now supported for analog input.
> The DPad gets mapped to buttons 16-19.
> Added a simple deadband filter for analog axes.
>
> Thanks qwx for feedback and help with the man page changes!
>
> Greetings,
> Arne
I should add that this also enables support for xbox360-compatible
fight sticks, and that the changes allow the 8Bitdo SN30 Pro to work
flawlessly, in xinput mode. I imagine that other such controllers
might now work as well. The deadband control was added because the
xbox360 controller is overly sensitive, spamming messages for all axes
any time anything moves; with a 5-10% deadband, it's perfect.
Thanks!
qwx
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [9front] [patch] nusb/ joy: xbox360 controller support and improved hid parsing
2024-10-19 12:44 [9front] [patch] nusb/ joy: xbox360 controller support and improved hid parsing Arne Meyer
2024-10-19 12:59 ` qwx
@ 2024-11-09 13:32 ` Arne Meyer
1 sibling, 0 replies; 3+ messages in thread
From: Arne Meyer @ 2024-11-09 13:32 UTC (permalink / raw)
To: 9front
[-- Attachment #1: Type: text/plain, Size: 539 bytes --]
new version. I fixed some style issues and the dpad buttons of the controller now get mapped to regular buttons.
ok?
> Arne Meyer <meyer.arne83@netcologne.de> hat am 19.10.2024 14:44 CEST geschrieben:
>
>
> Hello,
>
> this patch adds some improvements to nusb/joy.
>
> Support for xbox360 controllers.
> Up to six axes are now supported for analog input.
> The DPad gets mapped to buttons 16-19.
> Added a simple deadband filter for analog axes.
>
> Thanks qwx for feedback and help with the man page changes!
>
> Greetings,
> Arne
[-- Attachment #2: xbox360.diff --]
[-- Type: application/octet-stream, Size: 5238 bytes --]
diff c51566faa77810a457a543ffcf5707db9579c27a uncommitted
--- a/sys/man/4/nusb
+++ b/sys/man/4/nusb
@@ -44,6 +44,9 @@
.B nusb/joy
[
.B -d
+] [
+.B -b
+.I deadband
]
.I devid
.PP
@@ -190,7 +193,7 @@
any changes in the device's axes or buttons.
Buttons are identified via an integer id.
.PP
-Directional buttons are reported as axes
+Directional buttons are reported either as buttons or axes
with 3 positions:
.IR 0 ,
.IR 128 ,
@@ -198,6 +201,12 @@
.I 255
for left (or up), center and right (or down) respectively.
Messages are in the form \fIaxis id position\fR.
+.PP
+A deadband in the range of
+.RI [ 0.0 , 1.0 ]
+can be set with the
+.B \-b
+option to filter out input below a threshold on all analog axes.
.PP
On/off buttons are reported as either
.I down
--- a/sys/src/cmd/nusb/joy/hid.h
+++ b/sys/src/cmd/nusb/joy/hid.h
@@ -7,8 +7,9 @@
/* HID class subclass protocol ids */
JoyCSP = 0x000003,
+ Xbox360CSP = 0x015dff,
- Maxaxes = 3,
+ Maxaxes = 6,
/* Requests */
Getreport = 0x01,
--- a/sys/src/cmd/nusb/joy/joy.c
+++ b/sys/src/cmd/nusb/joy/joy.c
@@ -47,6 +47,7 @@
}
static int debug, kbd;
+static double deadband;
static int
signext(int v, int bits)
@@ -219,8 +220,7 @@
fprint(2, "\n");
}
proto = Reportproto;
- }else
- kbfatal(f, "no report");
+ }
/*
* if a HID's subclass code is 1 (boot mode), it will support
@@ -283,15 +283,18 @@
case 0x010030:
case 0x010031:
case 0x010032:
+ case 0x010033:
+ case 0x010034:
+ case 0x010035:
i = l[Usage] - 0x010030;
if((f & (Fabs|Frel)) == Fabs)
- p->axes[i] = v;
+ p->axes[i] = (abs(v)<(g[LogiMax]*deadband))?0:v;
else
- p->axes[i] += v;
+ p->axes[i] += (abs(v)<(g[LogiMax]*deadband))?0:v;
break;
}
if((l[Usage] >> 16) == 0x09){
- m = 1ULL << (l[Usage] & 0xff);
+ m = 1ULL << (l[Usage] & 0x3f);
p->btns &= ~m;
if(v != 0)
p->btns |= m;
@@ -363,13 +366,112 @@
}
}
+static void
+xbox360(KDev *kd)
+{
+ static uchar descr[] = {
+ 0x05, 0x01,
+ 0x09, 0x05,
+ 0xa1, 0x01,
+ 0x75, 0x08,
+ 0x95, 0x01,
+ 0x81, 0x01,
+ 0x75, 0x08,
+ 0x95, 0x01,
+ 0x05, 0x01,
+ 0x09, 0x3b,
+ 0x81, 0x01,
+ 0x05, 0x01,
+ 0x09, 0x01,
+ 0xa1, 0x00,
+ 0x75, 0x01,
+ 0x15, 0x00,
+ 0x25, 0x01,
+ 0x35, 0x00,
+ 0x45, 0x01,
+ 0x95, 0x04,
+ 0x05, 0x09,
+ 0x09, 0x0c,
+ 0x09, 0x0d,
+ 0x09, 0x0e,
+ 0x09, 0x0f,
+ 0x81, 0x02,
+ 0xc0,
+ 0x75, 0x01,
+ 0x15, 0x00,
+ 0x25, 0x01,
+ 0x35, 0x00,
+ 0x45, 0x01,
+ 0x95, 0x07,
+ 0x05, 0x09,
+ 0x09, 0x08,
+ 0x09, 0x07,
+ 0x09, 0x09,
+ 0x09, 0x0a,
+ 0x09, 0x05,
+ 0x09, 0x06,
+ 0x09, 0x0b,
+ 0x81, 0x02,
+ 0x75, 0x01,
+ 0x95, 0x01,
+ 0x81, 0x01,
+ 0x75, 0x01,
+ 0x15, 0x00,
+ 0x25, 0x01,
+ 0x35, 0x00,
+ 0x45, 0x01,
+ 0x95, 0x04,
+ 0x05, 0x09,
+ 0x19, 0x01,
+ 0x29, 0x04,
+ 0x81, 0x02,
+ 0x75, 0x08,
+ 0x15, 0x00,
+ 0x26, 0xff, 0x00,
+ 0x35, 0x00,
+ 0x46, 0xff, 0x00,
+ 0x95, 0x02,
+ 0x05, 0x01,
+ 0x09, 0x32,
+ 0x09, 0x35,
+ 0x81, 0x02,
+ 0x75, 0x10,
+ 0x16, 0x00, 0x80,
+ 0x26, 0xff, 0x7f,
+ 0x36, 0x00, 0x80,
+ 0x46, 0xff, 0x7f,
+ 0x95, 0x04,
+ 0x05, 0x01,
+ 0x09, 0x30,
+ 0x09, 0x31,
+ 0x09, 0x33,
+ 0x09, 0x34,
+ 0x81, 0x02,
+ 0x75, 0x30,
+ 0x95, 0x01,
+ 0x81, 0x01,
+ 0xc0,
+ };
+ static uchar ledcmd[] = {1,3,0};
+ Dev *d = kd->dev;
+
+ memcpy(kd->rep, descr, kd->nrep = sizeof(descr));
+ /* no blinken lights */
+ usbcmd(d, Rh2d|Rclass|Riface, Setreport, Reportout, 0, ledcmd, 3);
+}
+
+
/* apply quirks for special devices */
static void
-quirks(Dev *d)
+quirks(KDev *kd)
{
int ret;
+ Dev *d;
uchar buf[17];
+ static uchar xbox360ledcmd[] = {1,3,0};
+ d = kd->dev;
+
/* sony dualshock 3 (ps3) controller requires special enable command */
if(d->usb->vid == 0x054c && d->usb->did == 0x0268){
ret = usbcmd(d, Rd2h|Rclass|Riface, Getreport, (0x3<<8) | 0xF2, 0, buf, sizeof(buf));
@@ -376,6 +478,12 @@
if(ret < 0)
sysfatal("failed to enable ps3 controller: %r");
}
+
+ /* XBox360 controller and compatible return no HID descriptor, so we provide one */
+ if(d->usb->vid == 0x045e && d->usb->did == 0x028e
+ || d->usb->vid == 0x1bad && d->usb->did == 0xf03a){
+ xbox360(kd);
+ }
}
static void
@@ -399,7 +507,10 @@
fprint(2, "%s: %s: opendevdata: %r\n", argv0, kd->ep->dir);
goto Err;
}
- quirks(kd->dev);
+ quirks(kd);
+ if(kd->nrep == 0)
+ kbfatal(kd, "no report");
+
f(kd);
return;
Err:
@@ -409,7 +520,7 @@
static void
usage(void)
{
- fprint(2, "usage: %s [-d] devid\n", argv0);
+ fprint(2, "usage: %s [-d] [-b deadband] devid\n", argv0);
threadexits("usage");
}
@@ -420,11 +531,17 @@
Dev *d;
Ep *ep;
Usbdev *ud;
+ char *b;
ARGBEGIN{
case 'd':
debug++;
break;
+ case 'b':
+ b = EARGF(usage());
+ deadband = atof(b);
+ if(deadband > 0.0 && deadband < 1.0)
+ break;
default:
usage();
}ARGEND;
@@ -438,8 +555,13 @@
for(i = 0; i < nelem(ud->ep); i++){
if((ep = ud->ep[i]) == nil)
continue;
- if(ep->type == Eintr && ep->dir == Ein && ep->iface->csp == JoyCSP)
+ if(ep->type != Eintr || (ep->dir == Eout))
+ continue;
+ if(ep->iface->csp == JoyCSP)
break;
+ if(ep->iface->csp == Xbox360CSP)
+ break;
+
}
if(ep == nil)
sysfatal("no suitable endpoint found");
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2024-11-09 13:33 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-10-19 12:44 [9front] [patch] nusb/ joy: xbox360 controller support and improved hid parsing Arne Meyer
2024-10-19 12:59 ` qwx
2024-11-09 13:32 ` Arne Meyer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).