From: cinap_lenrek@felloff.net
To: 9front@9front.org
Subject: Re: [9front] Middle button on usb mice
Date: Fri, 30 Sep 2016 09:40:14 +0200 [thread overview]
Message-ID: <ee3e0caa29ff8d35bc19714482345463@felloff.net> (raw)
In-Reply-To: <3ed47344565c98254ffefc876b353e28@felloff.net>
[-- Attachment #1: Type: text/plain, Size: 33 bytes --]
screwed up attachment..
--
cinap
[-- Attachment #2: a.c --]
[-- Type: text/plain, Size: 5504 bytes --]
#include <u.h>
#include <libc.h>
#include <thread.h>
#include "usb.h"
#include "hid.h"
typedef struct Hidreport Hidreport;
struct Hidreport
{
int x;
int y;
int z;
int b;
int m;
int absx;
int absy;
int absz;
int nk;
uchar k[64];
int o;
uchar *e;
uchar p[128];
};
static int debug = 3;
static int
signext(int v, int bits)
{
int s;
s = sizeof(v)*8 - bits;
v <<= s;
v >>= s;
return v;
}
static int
getbits(uchar *p, uchar *e, int bits, int off)
{
int v, m;
p += off/8;
off %= 8;
v = 0;
m = 1;
if(p < e){
while(bits--){
if(*p & (1<<off))
v |= m;
if(++off == 8){
if(++p >= e)
break;
off = 0;
}
m <<= 1;
}
}
return v;
}
enum {
Ng = RepCnt+1,
UsgCnt = Delim+1, /* fake */
Nl = UsgCnt+1,
Nu = 256,
};
static uchar*
repparse1(uchar *d, uchar *e, int g[], int l[], int c,
void (*f)(int t, int v, int g[], int l[], int c, void *a), void *a)
{
int z, k, t, v, i;
while(d < e){
v = 0;
t = *d++;
z = t & 3, t >>= 2;
k = t & 3, t >>= 2;
switch(z){
case 3:
d += 4;
if(d > e) continue;
v = d[-4] | d[-3]<<8 | d[-2]<<16 | d[-1]<<24;
break;
case 2:
d += 2;
if(d > e) continue;
v = d[-2] | d[-1]<<8;
break;
case 1:
d++;
if(d > e) continue;
v = d[-1];
break;
}
switch(k){
case 0: /* main item*/
switch(t){
case Collection:
memset(l, 0, Nl*sizeof(l[0]));
d = repparse1(d, e, g, l, v, f, a);
continue;
case CollectionEnd:
return d;
case Input:
case Output:
case Feature:
if(l[UsgCnt] == 0 && l[UsagMin] != 0 && l[UsagMin] < l[UsagMax])
for(i=l[UsagMin]; i<=l[UsagMax] && l[UsgCnt] < Nu; i++)
l[Nl + l[UsgCnt]++] = i;
for(i=0; i<g[RepCnt]; i++){
l[Usage] = i < l[UsgCnt] ? l[Nl + i] : 0;
(*f)(t, v, g, l, c, a);
}
break;
}
memset(l, 0, Nl*sizeof(l[0]));
continue;
case 1: /* global item */
if(t == Push){
int w[Ng];
memmove(w, g, sizeof(w));
d = repparse1(d, e, w, l, c, f, a);
} else if(t == Pop){
return d;
} else if(t < Ng){
if(t == RepId)
v &= 0xFF;
else if(t == UsagPg)
v &= 0xFFFF;
else if(t != RepSize && t != RepCnt){
v = signext(v, (z == 3) ? 32 : 8*z);
}
g[t] = v;
}
continue;
case 2: /* local item */
if(l[Delim] != 0)
continue;
if(t == Delim){
l[Delim] = 1;
} else if(t < Delim){
if(z != 3 && (t == Usage || t == UsagMin || t == UsagMax))
v = (v & 0xFFFF) | (g[UsagPg] << 16);
l[t] = v;
if(t == Usage && l[UsgCnt] < Nu)
l[Nl + l[UsgCnt]++] = v;
}
continue;
case 3: /* long item */
if(t == 15)
d += v & 0xFF;
continue;
}
}
return d;
}
/*
* parse the report descriptor and call f for every (Input, Output
* and Feature) main item as often as it would appear in the report
* data packet.
*/
static void
repparse(uchar *d, uchar *e,
void (*f)(int t, int v, int g[], int l[], int c, void *a), void *a)
{
int l[Nl+Nu], g[Ng];
memset(l, 0, sizeof(l));
memset(g, 0, sizeof(g));
repparse1(d, e, g, l, 0, f, a);
}
static void
hidparse(int t, int f, int g[], int l[], int, void *a)
{
Hidreport *p = a;
int v, m;
if(t != Input)
return;
if(g[RepId] != 0){
if(p->p[0] != g[RepId]){
p->o = 0;
return;
}
if(p->o < 8)
p->o = 8; /* skip report id byte */
}
v = getbits(p->p, p->e, g[RepSize], p->o);
p->o += g[RepSize];
if((f & (Fconst|Fdata)) != Fdata)
return;
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((f & (Fvar|Farray)) == Fvar)
if(v != 0) v = l[Usage] & 0xFF;
if(p->nk < nelem(p->k) && v != 0)
p->k[p->nk++] = v;
return;
}
if(g[LogiMin] < 0)
v = signext(v, g[RepSize]);
if((f & (Fvar|Farray)) == Fvar && v >= g[LogiMin] && v <= g[LogiMax]){
/*
* we use logical units below, but need the
* sign to be correct for mouse deltas.
* so if physical unit is signed but logical
* is unsigned, convert to signed but in logical
* units.
*/
if((f & (Fabs|Frel)) == Frel
&& g[PhysMin] < 0 && g[PhysMax] > 0
&& g[LogiMin] >= 0 && g[LogiMin] < g[LogiMax])
v -= (g[PhysMax] * (g[LogiMax] - g[LogiMin])) / (g[PhysMax] - g[PhysMin]);
switch(l[Usage]){
case 0x090001:
case 0x090002:
case 0x090003:
case 0x090004:
case 0x090005:
case 0x090006:
case 0x090007:
case 0x090008:
m = 1<<(l[Usage] - 0x090001);
p->m |= m;
p->b &= ~m;
if(v != 0)
p->b |= m;
break;
case 0x010030:
if((f & (Fabs|Frel)) == Fabs){
p->x = (v - p->absx);
p->absx = v;
} else {
p->x = v;
p->absx += v;
}
break;
case 0x010031:
if((f & (Fabs|Frel)) == Fabs){
p->y = (v - p->absy);
p->absy = v;
} else {
p->y = v;
p->absy += v;
}
break;
case 0x010038:
if((f & (Fabs|Frel)) == Fabs){
p->z = (v - p->absz);
p->absz = v;
} else {
p->z = v;
p->absz += v;
}
break;
}
}
}
static void
usage(void)
{
fprint(2, "usage: %s [-d] devid\n", argv0);
threadexits("usage");
}
static uchar rep[] ={
0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x01,
0xa1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03,
0x15, 0x00, 0x25, 0x01, 0x95, 0x08, 0x75, 0x01,
0x81, 0x02, 0x05, 0x01, 0x09, 0x30, 0x09, 0x31,
0x09, 0x38, 0x15, 0x81, 0x25, 0x7f, 0x75, 0x08,
0x95, 0x03, 0x81, 0x06, 0xc0, 0xc0,
};
void
threadmain(int argc, char* argv[])
{
Hidreport p = {0};
p.o = 0;
p.e = p.p + 3;
p.p[0] = 1<<2;
repparse(rep, rep+sizeof(rep), hidparse, &p);
}
prev parent reply other threads:[~2016-09-30 7:40 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-09-24 3:26 lemon
2016-09-24 13:03 ` [9front] " cinap_lenrek
2016-09-26 23:13 ` lemon
2016-09-26 23:30 ` cinap_lenrek
2016-09-28 2:13 ` lemon
2016-09-28 13:27 ` cinap_lenrek
2016-09-28 14:20 ` cinap_lenrek
2016-09-30 3:47 ` lemon
2016-09-30 6:41 ` cinap_lenrek
2016-10-18 0:46 ` lemon
2016-09-30 7:37 ` cinap_lenrek
2016-09-30 7:40 ` cinap_lenrek [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ee3e0caa29ff8d35bc19714482345463@felloff.net \
--to=cinap_lenrek@felloff.net \
--cc=9front@9front.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).