Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <thread.h>
4
#include "usb.h"
5
#include "hid.h"
6
 
7
/*
8
 * Rough hid descriptor parsing and interpretation for mice
9
 *
10
 * Chain and its operations build the infrastructure needed
11
 * to manipulate non-aligned fields, which do appear (sigh!).
12
 */
13
 
14
/* Get, at most, 8 bits*/
15
static uchar
16
get8bits(Chain *ch, int nbits)
17
{
18
	int b, nbyb, nbib, nlb;
19
	uchar low, high;
20
 
21
	b = ch->b + nbits - 1;
22
	nbib = ch->b % 8;
23
	nbyb = ch->b / 8;
24
	nlb = 8 - nbib;
25
	if(nlb > nbits)
26
		nlb = nbits;
27
 
28
	low = MSK(nlb) & (ch->buf[nbyb] >> nbib);
29
	if(IsCut(ch->b, b))
30
		high = (ch->buf[nbyb + 1] & MSK(nbib)) << nlb;
31
	else
32
		high = 0;
33
	ch->b += nbits;
34
	return MSK(nbits)&(high | low);
35
}
36
 
37
static void
38
getbits(void *p, Chain *ch, int nbits)
39
{
40
	int nby, nbi, i;
41
	uchar *vp;
42
 
43
	assert(ch->e >= ch->b);
44
	nby = nbits / 8;
45
	nbi = nbits % 8;
46
 
47
	vp = p;
48
	for(i = 0; i < nby; i++)
49
		*vp++ = get8bits(ch, 8);
50
 
51
	if(nbi != 0)
52
		*vp = get8bits(ch, nbi);
53
}
54
 
55
int
56
parsereportdesc(HidRepTempl *temp, uchar *repdesc, int repsz)
57
{
58
	int i, j, l, n, isptr, hasxy, hasbut, nk, ncoll, dsize;
59
	uchar ks[MaxVals+1];
60
	HidInterface *ifs;
61
 
62
	ifs = temp->ifcs;
63
	isptr = 0;
64
	hasxy = hasbut = 0;
65
	ncoll = 0;
66
	n = 0;
67
	nk = 0;
68
	memset(ifs, 0, sizeof *ifs * MaxIfc);
69
	for(i = 0; i < repsz; i += dsize+1){
70
		dsize = (1 << (repdesc[i] & 03)) >> 1;
71
		if(nk > MaxVals){
72
			fprint(2, "bad report: too many input types\n");
73
			return -1;
74
		}
75
		if(n == MaxIfc)
76
			break;
77
		if(repdesc[i] == HidEnd){
78
			ncoll--;
79
			if(ncoll == 0)
80
				break;
81
		}
82
 
83
		switch(repdesc[i]){
84
		case HidReportId:
85
			switch(repdesc[i+1]){
86
			case HidReportIdPtr:
87
				temp->id = repdesc[i+1];
88
				break;
89
			default:
90
				fprint(2, "report type %#ux bad\n",
91
					repdesc[i+1]);
92
				return -1;
93
			}
94
			break;
95
		case HidTypeUsg:
96
			switch(repdesc[i+1]){
97
			case HidX:
98
				hasxy++;
99
				ks[nk++] = KindX;
100
				break;
101
			case HidY:
102
				hasxy++;
103
				ks[nk++] = KindY;
104
				break;
105
			case HidZ:
106
				ks[nk++] = KindPad;
107
				break;
108
			case HidWheel:
109
				ks[nk++] = KindWheel;
110
				break;
111
			case HidPtr:
112
				isptr++;
113
				break;
114
			}
115
			break;
116
		case HidTypeUsgPg:
117
			switch(repdesc[i+1]){
118
			case HidPgButts:
119
				hasbut++;
120
				ks[nk++] = KindButtons;
121
				break;
122
			}
123
			break;
124
		case HidTypeRepSz:
125
			ifs[n].nbits = repdesc[i+1];
126
			break;
127
		case HidTypeCnt:
128
			ifs[n].count = repdesc[i+1];
129
			break;
130
		case HidInput:
131
			if(ifs[n].count > MaxVals){
132
				fprint(2, "bad report: input count too big\n");
133
				return -1;
134
			}
135
			for(j = 0; j <nk; j++)
136
				ifs[n].kind[j] = ks[j];
137
			if(nk != 0 && nk < ifs[n].count)
138
				for(l = j; l <ifs[n].count; l++)
139
					ifs[n].kind[l] = ks[j-1];
140
			n++;
141
			if(n < MaxIfc){
142
				ifs[n].count = ifs[n-1].count;	/* inherit values */
143
				ifs[n].nbits = ifs[n-1].nbits;
144
				if(ifs[n].nbits == 0)
145
					ifs[n].nbits = 1;
146
			}
147
			nk = 0;
148
			break;
149
		case HidCollection:
150
			ncoll++;
151
			break;
152
		}
153
	}
154
	temp->nifcs = n;
155
	for(i = 0; i < n; i++)
156
		temp->sz += temp->ifcs[i].nbits * temp->ifcs[i].count;
157
	temp->sz = (temp->sz + 7) / 8;
158
 
159
	if(isptr && hasxy && hasbut)
160
		return 0;
161
	fprint(2, "bad report: isptr %d, hasxy %d, hasbut %d\n",
162
		isptr, hasxy, hasbut);
163
	return -1;
164
}
165
 
166
int
167
parsereport(HidRepTempl *templ, Chain *rep)
168
{
169
	int i, j, k, ifssz;
170
	ulong u;
171
	uchar *p;
172
	HidInterface *ifs;
173
 
174
	ifssz = templ->nifcs;
175
	ifs = templ->ifcs;
176
	for(i = 0; i < ifssz; i++)
177
		for(j = 0; j < ifs[i].count; j++){
178
			if(ifs[i].nbits > 8 * sizeof ifs[i].v[0]){
179
				fprint(2, "ptr: bad bits in parsereport");
180
				return -1;
181
			}
182
			u =0;
183
			getbits(&u, rep, ifs[i].nbits);
184
			p = (uchar *)&u;
185
			/* le to host */
186
			ifs[i].v[j] = p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0]<<0;
187
			k = ifs[i].kind[j];
188
			if(k == KindX || k == KindY || k == KindWheel){
189
				/* propagate sign */
190
				if(ifs[i].v[j] & (1 << (ifs[i].nbits - 1)))
191
					ifs[i].v[j] |= ~MSK(ifs[i].nbits);
192
			}
193
		}
194
	return 0;
195
}
196
 
197
/* TODO: fmt representation */
198
void
199
dumpreport(HidRepTempl *templ)
200
{
201
	int i, j, ifssz;
202
	HidInterface *ifs;
203
 
204
	ifssz = templ->nifcs;
205
	ifs = templ->ifcs;
206
	for(i = 0; i < ifssz; i++){
207
		fprint(2, "\tcount %#ux", ifs[i].count);
208
		fprint(2, " nbits %d ", ifs[i].nbits);
209
		fprint(2, "\n");
210
		for(j = 0; j < ifs[i].count; j++){
211
			fprint(2, "\t\tkind %#ux ", ifs[i].kind[j]);
212
			fprint(2, "v %#lux\n", ifs[i].v[j]);
213
		}
214
		fprint(2, "\n");
215
	}
216
	fprint(2, "\n");
217
}
218
 
219
/* could precalculate indices after parsing the descriptor */
220
int
221
hidifcval(HidRepTempl *templ, int kind, int n)
222
{
223
	int i, j, ifssz;
224
	HidInterface *ifs;
225
 
226
	ifssz = templ->nifcs;
227
	ifs = templ->ifcs;
228
	assert(n <= nelem(ifs[i].v));
229
	for(i = 0; i < ifssz; i++)
230
		for(j = 0; j < ifs[i].count; j++)
231
			if(ifs[i].kind[j] == kind && n-- == 0)
232
				return (int)ifs[i].v[j];
233
	return 0;		/* least damage (no buttons, no movement) */
234
}