summaryrefslogtreecommitdiff
path: root/sys/src/cmd/nusb
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2022-10-08 10:38:14 +0000
committercinap_lenrek <cinap_lenrek@felloff.net>2022-10-08 10:38:14 +0000
commit166e8b3cf8d2e087258eb47fdba7e890d6a8432a (patch)
treeda16c7d2198956abacd36cb99a6137136503a11e /sys/src/cmd/nusb
parent2a29b497f215f91d05b6718a0e852e8a9b6ce6da (diff)
parentc6ae349e9d67ef24ce429f699c5232a9acdcb1ea (diff)
merge
Diffstat (limited to 'sys/src/cmd/nusb')
-rw-r--r--sys/src/cmd/nusb/disk/disk.c4
-rw-r--r--sys/src/cmd/nusb/kb/hid.h1
-rw-r--r--sys/src/cmd/nusb/kb/kb.c211
3 files changed, 169 insertions, 47 deletions
diff --git a/sys/src/cmd/nusb/disk/disk.c b/sys/src/cmd/nusb/disk/disk.c
index 196894cfe..2fb8fc324 100644
--- a/sys/src/cmd/nusb/disk/disk.c
+++ b/sys/src/cmd/nusb/disk/disk.c
@@ -155,10 +155,10 @@ ctlstring(Umsc *lun)
part = &lun->part[0];
fmtstrinit(&fmt);
- fmtprint(&fmt, "dev %s\n", dev->dir);
- fmtprint(&fmt, "lun %zd\n", lun - &ums->lun[0]);
if(lun->flags & Finqok)
fmtprint(&fmt, "inquiry %s\n", lun->inq);
+ fmtprint(&fmt, "dev %s\n", dev->dir);
+ fmtprint(&fmt, "lun %zd\n", lun - &ums->lun[0]);
if(lun->blocks > 0)
fmtprint(&fmt, "geometry %llud %ld\n", lun->blocks, lun->lbsize);
for (p = &part[Qdata+1]; p < &part[Qmax]; p++)
diff --git a/sys/src/cmd/nusb/kb/hid.h b/sys/src/cmd/nusb/kb/hid.h
index 10e614f4b..5c51250aa 100644
--- a/sys/src/cmd/nusb/kb/hid.h
+++ b/sys/src/cmd/nusb/kb/hid.h
@@ -4,6 +4,7 @@
enum {
Stack = 32 * 1024,
+ Nkey = 64,
/* HID class subclass protocol ids */
PtrCSP = 0x020103, /* mouse.boot.hid */
diff --git a/sys/src/cmd/nusb/kb/kb.c b/sys/src/cmd/nusb/kb/kb.c
index e748c9268..5a7b8ee5e 100644
--- a/sys/src/cmd/nusb/kb/kb.c
+++ b/sys/src/cmd/nusb/kb/kb.c
@@ -13,21 +13,21 @@
#include <u.h>
#include <libc.h>
+#include <ctype.h>
+#include <fcall.h>
#include <thread.h>
+#include <9p.h>
#include "usb.h"
#include "hid.h"
enum
{
- Awakemsg=0xdeaddead,
+ Awakemsg = 0xdeaddead,
Diemsg = 0xbeefbeef,
+ Rawon = 0x0defaced,
};
-enum
-{
- Kbdelay = 500,
- Kbrepeat = 100,
-};
+char user[] = "kb";
typedef struct Hiddev Hiddev;
struct Hiddev
@@ -78,7 +78,7 @@ struct Hidreport
Hidslot s[16];
int nk;
- uchar k[64];
+ ushort k[Nkey];
int o;
uchar *e;
@@ -92,6 +92,7 @@ enum {
/* Scan codes (see kbd.c) */
SCesc1 = 0xe0, /* first of a 2-character sequence */
SCesc2 = 0xe1,
+ Consumer = 0x100, /* the key is on consumer page */
Keyup = 0x80, /* flag bit */
Keymask = 0x7f, /* regular scan code bits */
};
@@ -101,12 +102,12 @@ enum {
*/
#define isext(sc) ((sc) >= 0x80)
+static char sctab[2*256] =
+{
/*
* key code to scan code; for the page table used by
* the logitech bluetooth keyboard.
*/
-static char sctab[256] =
-{
[0x00] 0x0, 0x0, 0x0, 0x0, 0x1e, 0x30, 0x2e, 0x20,
[0x08] 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26,
[0x10] 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1f, 0x14,
@@ -124,7 +125,7 @@ static char sctab[256] =
[0x70] 0xf8, 0xf9, 0xfa, 0xfb, 0x0, 0x0, 0x0, 0x0,
[0x78] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf1,
[0x80] 0xf3, 0xf2, 0x0, 0x0, 0x0, 0xfc, 0x0, 0x0,
-[0x88] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x88] 0x70, 0x0, 0x79, 0x7b, 0x0, 0x0, 0x0, 0x0,
[0x90] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
[0x98] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
[0xa0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
@@ -135,10 +136,43 @@ static char sctab[256] =
[0xc8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
[0xd0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
[0xd8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-[0xe0] 0x1d, 0x2a, 0x38, 0xdb, 0xe1, 0x36, 0xb8, 0xfe,
+[0xe0] 0x1d, 0x2a, 0x38, 0xdb, 0x9d, 0x36, 0xb8, 0xfe,
[0xe8] 0x0, 0x0, 0x0, 0x0, 0x0, 0xf3, 0xf2, 0xf1,
[0xf0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
[0xf8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+/* consumer page to scan code */
+[0x100] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x108] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x110] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x118] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x120] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x128] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x130] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x138] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x140] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x148] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x150] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x158] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x160] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x168] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9a,
+[0x170] 0x91, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x178] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x180] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x188] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x190] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x198] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x1a0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x1a8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x1b0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x99, 0x90, 0x0,
+[0x1b8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x1c0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x1c8] 0x0, 0x0, 0x0, 0x0, 0x0, 0xa2, 0x0, 0x0,
+[0x1d0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x1d8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x1e0] 0x0, 0x0, 0xa0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x1e8] 0x0, 0xb0, 0xae, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x1f0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+[0x1f8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
};
static uchar kbdbootrep[] = {
@@ -165,6 +199,9 @@ static uchar ptrbootrep[] = {
};
static int debug = 0;
+static int kbdelay = 500;
+static int kbrepeat = 100;
+static int havekbd;
static int
signext(int v, int bits)
@@ -377,12 +414,6 @@ setproto(Hiddev *f, Iface *iface)
return usbcmd(f->dev, Rh2d|Rclass|Riface, Setproto, proto, iface->id, nil, 0);
}
-static int
-setleds(Hiddev* f, int, uchar leds)
-{
- return usbcmd(f->dev, Rh2d|Rclass|Riface, Setreport, Reportout, 0, &leds, 1);
-}
-
static void
hdfree(Hiddev *f)
{
@@ -498,9 +529,9 @@ repeatproc(void* arg)
continue;
}
sc = l & 0xff;
- t = Kbdelay;
+ t = kbdelay;
if(alt(a) == 1){
- t = Kbrepeat;
+ t = kbrepeat;
while(alt(a) == 1)
putscan(f, sc, 0);
}
@@ -528,7 +559,7 @@ hidparse(int t, int f, int g[], int l[], int, void *a)
{
Hidreport *p = a;
Hidslot *s = &p->s[p->ns];
- int v, m;
+ int v, m, cp;
switch(t){
case Input:
@@ -571,11 +602,11 @@ hidparse(int t, int f, int g[], int l[], int, void *a)
if(debug > 1)
fprint(2, "hidparse: t=%x f=%x usage=%x v=%x\n", t, f, l[Usage], v);
- if((l[Usage]>>16) == 0x07){ /* keycode */
+ if((cp = ((l[Usage]>>16) == 0x0c)) || (l[Usage]>>16) == 0x07){ /* consumer/keycode */
if((f & (Fvar|Farray)) == Fvar)
if(v != 0) v = l[Usage] & 0xFF;
if(p->nk < nelem(p->k) && v != 0)
- p->k[p->nk++] = v;
+ p->k[p->nk++] = v | cp*Consumer;
return;
}
@@ -677,12 +708,23 @@ sethipri(void)
close(fd);
}
+static ushort *
+keykey(ushort *a, ushort k, int n)
+{
+ while(n > 0){
+ if(*a++ == k)
+ return a-1;
+ n--;
+ }
+ return nil;
+}
+
static void
readerproc(void* a)
{
char err[ERRMAX], mbuf[80];
- uchar lastk[64], uk, dk;
- int i, c, nerrs, bpress, lastb, nlastk;
+ ushort lastk[Nkey], uks[Nkey], dks[Nkey], nuks, ndks;
+ int i, c, nerrs, bpress, lastb, nlastk, stopped;
int abs, x, y, z, b;
Hidreport p;
Hidslot lasts[nelem(p.s)], *s, *l;
@@ -730,7 +772,7 @@ readerproc(void* a)
if(debug){
fprint(2, "kbd: ");
for(i = 0; i < p.nk; i++)
- fprint(2, "%#2.2ux ", p.k[i]);
+ fprint(2, "%#4.4ux ", p.k[i]);
fprint(2, "\n");
}
@@ -745,25 +787,36 @@ readerproc(void* a)
proccreate(repeatproc, f, Stack);
}
- dk = uk = 0;
- for(i=0; i<nlastk; i++){
- if(memchr(p.k, lastk[i], p.nk) == nil){
- uk = sctab[lastk[i]];
- putscan(f, uk, Keyup);
- }
+ /* collect key presses/releases */
+ for(i=nuks=0; i<nlastk; i++){
+ if(keykey(p.k, lastk[i], p.nk) == nil)
+ uks[nuks++] = sctab[lastk[i]];
}
- for(i=0; i<p.nk; i++){
- if(memchr(lastk, p.k[i], nlastk) == nil){
- dk = sctab[p.k[i]];
- putscan(f, dk, 0);
+ for(i=ndks=0; i<p.nk; i++){
+ if(keykey(lastk, p.k[i], nlastk) == nil)
+ dks[ndks++] = sctab[p.k[i]];
+ }
+
+ /*
+ * stop the repeats first to avoid race condition when
+ * the key is released but the repeat happens right after
+ */
+ for(stopped = i = 0; i < nuks; i++){
+ if(ndks == 0 || keykey(dks, uks[i], ndks) != nil){
+ stoprepeat(f);
+ stopped = 1;
+ break;
}
}
- if(uk != 0 && (dk == 0 || dk == uk))
- stoprepeat(f);
- else if(dk != 0)
- startrepeat(f, dk);
+ for(i = 0; i < nuks; i++)
+ putscan(f, uks[i], Keyup);
+ for(i = 0; i < ndks; i++)
+ putscan(f, dks[i], 0);
+
+ if(stopped == 0 && ndks > 0)
+ startrepeat(f, dks[ndks-1]);
- memmove(lastk, p.k, nlastk = p.nk);
+ memmove(lastk, p.k, (nlastk = p.nk)*sizeof(lastk[0]));
p.nk = 0;
}
@@ -871,7 +924,7 @@ quirks(Hiddev *f)
}
}
-static void
+static int
hdsetup(Dev *d, Ep *ep)
{
Hiddev *f;
@@ -896,12 +949,71 @@ hdsetup(Dev *d, Ep *ep)
}
quirks(f);
procrfork(readerproc, f, Stack, RFNOTEG);
- return;
+ return 0;
Err:
hdfree(f);
+ return -1;
+}
+
+static void
+fsread(Req *r)
+{
+ char msg[48], *s, *e;
+
+ s = msg;
+ e = msg+sizeof(msg);
+ *s = 0;
+ if(havekbd)
+ e = seprint(s, e, "repeat %d\ndelay %d\n", kbrepeat, kbdelay);
+ USED(e);
+ readstr(r, msg);
+ respond(r, nil);
}
static void
+fswrite(Req *r)
+{
+ char msg[256], *f[4];
+ void *data;
+ int nf, sz;
+ Dev *dev;
+
+ dev = r->fid->file->aux;
+ data = r->ifcall.data;
+ sz = r->ifcall.count;
+ if(r->fid->aux == (void*)Rawon){
+ if(sz == 6 && memcmp(data, "rawoff", 6) == 0)
+ r->fid->aux = nil;
+ else if(usbcmd(dev, Rh2d|Rclass|Riface, Setreport, Reportout, 0, data, sz) < 0){
+ responderror(r);
+ return;
+ }
+ }else{
+ snprint(msg, sizeof(msg), "%.*s", utfnlen(data, sz), data);
+ nf = tokenize(msg, f, nelem(f));
+ if(nf == 1 && strcmp(f[0], "rawon") == 0)
+ r->fid->aux = (void*)Rawon;
+ else if(nf == 2 && strcmp(f[0], "repeat") == 0)
+ kbrepeat = atoi(f[1]);
+ else if(nf == 2 && strcmp(f[0], "delay") == 0)
+ kbdelay = atoi(f[1]);
+ else if(nf == 2 && strcmp(f[0], "debug") == 0)
+ debug = atoi(f[1]);
+ else{
+ respond(r, "invalid ctl message");
+ return;
+ }
+ }
+ r->ofcall.count = sz;
+ respond(r, nil);
+}
+
+static Srv fs = {
+ .read = fsread,
+ .write = fswrite,
+};
+
+static void
usage(void)
{
fprint(2, "usage: %s [-d] devid\n", argv0);
@@ -911,10 +1023,11 @@ usage(void)
void
threadmain(int argc, char* argv[])
{
- int i;
+ int i, n;
Dev *d;
Ep *ep;
Usbdev *ud;
+ char buf[32];
ARGBEGIN{
case 'd':
@@ -929,20 +1042,28 @@ threadmain(int argc, char* argv[])
if(d == nil)
sysfatal("getdev: %r");
ud = d->usb;
- for(i = 0; i < nelem(ud->ep); i++){
+ for(i = n = 0; i < nelem(ud->ep); i++){
if((ep = ud->ep[i]) == nil)
continue;
if(ep->type != Eintr || ep->dir != Ein)
continue;
switch(ep->iface->csp){
case KbdCSP:
+ havekbd = 1;
case PtrCSP:
case PtrNonBootCSP:
case HidCSP:
- hdsetup(d, ep);
+ n += hdsetup(d, ep) == 0;
break;
}
}
closedev(d);
+ if(n > 0){
+ fs.tree = alloctree(user, "usb", DMDIR|0555, nil);
+ snprint(buf, sizeof buf, "hidU%sctl", d->hname);
+ createfile(fs.tree->root, buf, user, 0666, d);
+ snprint(buf, sizeof buf, "%s.hid", d->hname);
+ threadpostsharesrv(&fs, nil, "usb", buf);
+ }
threadexits(nil);
}