Plan 9 from Bell Labs’s /usr/web/sources/patch/applied/mice/hid.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <thread.h>
#include "usb.h"
#include "hid.h"

/*
 * Rough hid descriptor parsing and interpretation for mice
 *
 * Chain and its operations build the infrastructure needed
 * to manipulate non-aligned fields which do appear (sigh!).
 */

/* Get, at most, 8 bits*/
static uchar
get8bits(Chain *ch, int nbits)
{
	int b, nbyb, nbib, nlb;
	uchar low, high, res;

	b = ch->b+nbits-1;
	nbib = ch->b % 8;
	nbyb = ch->b / 8;
	nlb = 8 - nbib;
	if(nlb > nbits)
		nlb = nbits;

	low = MSK(nlb) & (ch->buf[nbyb] >> nbib);
	if(IsCut(ch->b, b))
		high = (ch->buf[nbyb + 1] & MSK(nbib)) << nlb;
	else
		high = 0;
	res = high | low;
	ch->b += nbits;
	return res;
}

static void
getbits(void *p, Chain *ch, int nbits)
{
	int nby, nbi, i;
	uchar *vp;

	assert(ch->e >= ch->b);
	nby = nbits / 8;
	nbi = nbits % 8;

	vp = p;
	for(i = 0; i < nby; i++)
		*vp++ = get8bits(ch, 8);
	
	if(nbi != 0)
		*vp = get8bits(ch, nbi);
}

/* TODO check report id, when it does appear (not all devices) */
int
parsereportdesc(HidRepTempl *temp, uchar *repdesc, int repsz)
{
	int i, j, l, n, isptr, hasxy, hasbut, nk;
	int ks[MaxVals];
	HidInterface *ifs;

	ifs = temp->ifcs;
	isptr = 0;
	hasxy = hasbut = 0;
	n = 0;
	nk = 0;
	memset(ifs, 0, sizeof(*ifs)*MaxIfc);
	for(i = 0; i < repsz/2; i+=2){
		if(n == MaxIfc)
			break;
		if(repdesc[i] == HidEnd)
			break;

		switch(repdesc[i]){
		default:
			break;
		case HidTypeUsg:	
			switch(repdesc[i+1]){
			default:
				break;
			case HidX:
				hasxy++;
				ks[nk++] = KindX;
				break;
			case HidY:
				hasxy++;
				ks[nk++] = KindY;
			break;
			case HidWheel:
				ks[nk++] = KindWheel;
				break;
			case HidPtr:
				isptr++;
				break;
					
			}
			break;
		case HidTypeUsgPg:	
			switch(repdesc[i+1]){
			default:
				break;
			case HidPgButts:
				hasbut++;
				ks[nk++] = KindButtons;
				break;
			}
			break;
		case HidTypeRepSz:
			ifs[n].nbits = repdesc[i+1];
			break;
		case HidTypeCnt:
			ifs[n].count = repdesc[i+1];
			break;
		case HidInput:
			for(j = 0; j <nk; j++)
				ifs[n].kind[j] = ks[j];
			if(nk < ifs[n].count)
				for(l = j; l <ifs[n].count; l++)
					ifs[n].kind[l] = ks[j-1];
			n++;
			nk = 0;
			break;
			
		}
	}
	temp->nifcs = n;
	if(isptr && hasxy && hasbut)
		return 0;
	else
		fprint(2, "bad report: isptr %d, hasxy %d, hasbut %d\n",
				isptr, hasxy, hasbut);

	return -1;
}

int
parsereport(HidRepTempl *templ, Chain *rep)
{
	int i, j, k, ifssz;
	ulong u;
	uchar *p;
	HidInterface *ifs;
	
	ifssz = templ->nifcs;
	ifs = templ->ifcs;
	for(i = 0; i < ifssz; i++){
		for(j = 0; j < ifs[i].count; j++){
			if(ifs[i].nbits > 8*sizeof(ifs[i].v[0])){
				fprint(2, "ptr: bad bits in parsereport");
				return -1;
			}
			u =0;
			getbits(&u, rep, ifs[i].nbits);
			p = (uchar *)&u;
			ifs[i].v[j] = (p[3]<<24)|(p[2]<<16)|(p[1]<<8)|(p[0]<<0);	/* le to host */
			k = ifs[i].kind[j];
			if(k == KindX || k == KindY || k == KindWheel){
				if(ifs[i].v[j] & 1<<ifs[i].nbits -1)
					ifs[i].v[j] |= ~MSK(ifs[i].nbits);			/* propagate sign */
			}
		}
	}
	return 0;
}

/* TODO: fmt representation */
void
dumpreport(HidRepTempl *templ)
{
	int i, j, ifssz;
	HidInterface *ifs;
	
	ifssz = templ->nifcs;
	ifs = templ->ifcs;
	for(i = 0; i < ifssz; i++){
		fprint(2, "\tcount %#ux", ifs[i].count);
		fprint(2, " nbits %d ", ifs[i].nbits);
		fprint(2, "\n");
		for(j = 0; j < ifs[i].count; j++){
			fprint(2, "\t\tkind %#ux ", ifs[i].kind[j]);
			fprint(2, "v %#lux\n", ifs[i].v[j]);
		}
		fprint(2, "\n");	
	}
	fprint(2, "\n");
}


/* could cache indexes after parsing the descriptor */
int
hidifcval(HidRepTempl *templ, int kind, int n)
{
	int i, j, ifssz;
	HidInterface *ifs;
	
	ifssz = templ->nifcs;
	ifs = templ->ifcs;
	assert(n <= nelem(ifs[i].v));
	for(i = 0; i < ifssz; i++){
		for(j = 0; j < ifs[i].count; j++)
			if(ifs[i].kind[j] == kind && n-- == 0){
				return (int)ifs[i].v[j];
			}
	}
	return 0;	/* least damage (no buttons, no movement) */
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.