usbdi_util.c revision 1.3 1 /* $NetBSD: usbdi_util.c,v 1.3 1998/07/29 20:50:12 augustss Exp $ */
2
3 /*
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Author: Lennart Augustsson <augustss (at) carlstedt.se>
8 * Carlstedt Research & Technology
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/device.h>
44 #include <sys/proc.h>
45 #include <sys/select.h>
46
47 #include <dev/usb/usb.h>
48 #include <dev/usb/usbhid.h>
49
50 #include <dev/usb/usbdi.h>
51 #include <dev/usb/usbdi_util.h>
52
53 #include "opt_usbverbose.h"
54
55 #ifdef USB_DEBUG
56 #define DPRINTF(x) if (usbdebug) printf x
57 #define DPRINTFN(n,x) if (usbdebug>(n)) printf x
58 extern int usbdebug;
59 #else
60 #define DPRINTF(x)
61 #define DPRINTFN(n,x)
62 #endif
63
64 usbd_status
65 usbd_get_desc(dev, type, index, len, desc)
66 usbd_device_handle dev;
67 int type, index;
68 int len;
69 void *desc;
70 {
71 usb_device_request_t req;
72
73 req.bmRequestType = UT_READ_DEVICE;
74 req.bRequest = UR_GET_DESCRIPTOR;
75 USETW2(req.wValue, type, index);
76 USETW(req.wIndex, 0);
77 USETW(req.wLength, len);
78 return (usbd_do_request(dev, &req, desc));
79 }
80
81 usbd_status
82 usbd_get_config_desc(dev, conf, d)
83 usbd_device_handle dev;
84 int conf;
85 usb_config_descriptor_t *d;
86 {
87 DPRINTFN(3,("usbd_get_config_desc: conf=%d\n", conf));
88 return (usbd_get_desc(dev, UDESC_CONFIG,
89 conf, USB_CONFIG_DESCRIPTOR_SIZE, d));
90 }
91
92 usbd_status
93 usbd_get_device_desc(dev, d)
94 usbd_device_handle dev;
95 usb_device_descriptor_t *d;
96 {
97 DPRINTFN(3,("usbd_get_device_desc:\n"));
98 return (usbd_get_desc(dev, UDESC_DEVICE,
99 0, USB_DEVICE_DESCRIPTOR_SIZE, d));
100 }
101
102 usbd_status
103 usbd_get_device_status(dev, st)
104 usbd_device_handle dev;
105 usb_status_t *st;
106 {
107 usb_device_request_t req;
108
109 req.bmRequestType = UT_READ_DEVICE;
110 req.bRequest = UR_GET_STATUS;
111 USETW(req.wValue, 0);
112 USETW(req.wIndex, 0);
113 USETW(req.wLength, sizeof(usb_status_t));
114 return (usbd_do_request(dev, &req, st));
115 }
116
117 usbd_status
118 usbd_get_hub_status(dev, st)
119 usbd_device_handle dev;
120 usb_hub_status_t *st;
121 {
122 usb_device_request_t req;
123
124 req.bmRequestType = UT_READ_CLASS_DEVICE;
125 req.bRequest = UR_GET_STATUS;
126 USETW(req.wValue, 0);
127 USETW(req.wIndex, 0);
128 USETW(req.wLength, sizeof(usb_hub_status_t));
129 return (usbd_do_request(dev, &req, st));
130 }
131
132 usbd_status
133 usbd_set_address(dev, addr)
134 usbd_device_handle dev;
135 int addr;
136 {
137 usb_device_request_t req;
138
139 req.bmRequestType = UT_WRITE_DEVICE;
140 req.bRequest = UR_SET_ADDRESS;
141 USETW(req.wValue, addr);
142 USETW(req.wIndex, 0);
143 USETW(req.wLength, 0);
144 return usbd_do_request(dev, &req, 0);
145 }
146
147 usbd_status
148 usbd_set_config(dev, conf)
149 usbd_device_handle dev;
150 int conf;
151 {
152 usb_device_request_t req;
153
154 req.bmRequestType = UT_WRITE_DEVICE;
155 req.bRequest = UR_SET_CONFIG;
156 USETW(req.wValue, conf);
157 USETW(req.wIndex, 0);
158 USETW(req.wLength, 0);
159 return (usbd_do_request(dev, &req, 0));
160 }
161
162 usbd_status
163 usbd_get_port_status(dev, port, ps)
164 usbd_device_handle dev;
165 int port;
166 usb_port_status_t *ps;
167 {
168 usb_device_request_t req;
169
170 req.bmRequestType = UT_READ_CLASS_OTHER;
171 req.bRequest = UR_GET_STATUS;
172 USETW(req.wValue, 0);
173 USETW(req.wIndex, port);
174 USETW(req.wLength, sizeof *ps);
175 return (usbd_do_request(dev, &req, ps));
176 }
177
178 usbd_status
179 usbd_clear_port_feature(dev, port, sel)
180 usbd_device_handle dev;
181 int port, sel;
182 {
183 usb_device_request_t req;
184
185 req.bmRequestType = UT_WRITE_CLASS_OTHER;
186 req.bRequest = UR_CLEAR_FEATURE;
187 USETW(req.wValue, sel);
188 USETW(req.wIndex, port);
189 USETW(req.wLength, 0);
190 return (usbd_do_request(dev, &req, 0));
191 }
192
193 usbd_status
194 usbd_set_port_feature(dev, port, sel)
195 usbd_device_handle dev;
196 int port, sel;
197 {
198 usb_device_request_t req;
199
200 req.bmRequestType = UT_WRITE_CLASS_OTHER;
201 req.bRequest = UR_SET_FEATURE;
202 USETW(req.wValue, sel);
203 USETW(req.wIndex, port);
204 USETW(req.wLength, 0);
205 return (usbd_do_request(dev, &req, 0));
206 }
207
208
209 usbd_status
210 usbd_set_protocol(iface, report)
211 usbd_interface_handle iface;
212 int report;
213 {
214 usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface);
215 usbd_device_handle dev;
216 usb_device_request_t req;
217 usbd_status r;
218
219 DPRINTFN(4, ("usbd_set_protocol: iface=%p, report=%d, endpt=%d\n",
220 iface, report, id->bInterfaceNumber));
221 r = usbd_interface2device_handle(iface, &dev);
222 if (r != USBD_NORMAL_COMPLETION)
223 return (r);
224 if (!id)
225 return (USBD_INVAL);
226 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
227 req.bRequest = UR_SET_PROTOCOL;
228 USETW(req.wValue, report);
229 USETW(req.wIndex, id->bInterfaceNumber);
230 USETW(req.wLength, 0);
231 return (usbd_do_request(dev, &req, 0));
232 }
233
234 usbd_status
235 usbd_set_report(iface, type, id, data, len)
236 usbd_interface_handle iface;
237 int type;
238 int id;
239 void *data;
240 int len;
241 {
242 usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
243 usbd_device_handle dev;
244 usb_device_request_t req;
245 usbd_status r;
246
247 DPRINTFN(4, ("usbd_set_report: len=%d\n", len));
248 r = usbd_interface2device_handle(iface, &dev);
249 if (r != USBD_NORMAL_COMPLETION)
250 return (r);
251 if (!ifd)
252 return (USBD_INVAL);
253 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
254 req.bRequest = UR_SET_REPORT;
255 USETW2(req.wValue, type, id);
256 USETW(req.wIndex, ifd->bInterfaceNumber);
257 USETW(req.wLength, len);
258 return (usbd_do_request(dev, &req, data));
259 }
260
261 usbd_status
262 usbd_set_report_async(iface, type, id, data, len)
263 usbd_interface_handle iface;
264 int type;
265 int id;
266 void *data;
267 int len;
268 {
269 usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
270 usbd_device_handle dev;
271 usb_device_request_t req;
272 usbd_status r;
273
274 DPRINTFN(4, ("usbd_set_report_async: len=%d\n", len));
275 r = usbd_interface2device_handle(iface, &dev);
276 if (r != USBD_NORMAL_COMPLETION)
277 return (r);
278 if (!ifd)
279 return (USBD_INVAL);
280 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
281 req.bRequest = UR_SET_REPORT;
282 USETW2(req.wValue, type, id);
283 USETW(req.wIndex, ifd->bInterfaceNumber);
284 USETW(req.wLength, len);
285 return (usbd_do_request_async(dev, &req, data));
286 }
287
288 usbd_status
289 usbd_get_report(iface, type, id, data, len)
290 usbd_interface_handle iface;
291 int type;
292 int id;
293 void *data;
294 int len;
295 {
296 usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
297 usbd_device_handle dev;
298 usb_device_request_t req;
299 usbd_status r;
300
301 DPRINTFN(4, ("usbd_set_report: len=%d\n", len));
302 r = usbd_interface2device_handle(iface, &dev);
303 if (r != USBD_NORMAL_COMPLETION)
304 return (r);
305 if (!ifd)
306 return (USBD_INVAL);
307 req.bmRequestType = UT_READ_CLASS_INTERFACE;
308 req.bRequest = UR_GET_REPORT;
309 USETW2(req.wValue, type, id);
310 USETW(req.wIndex, ifd->bInterfaceNumber);
311 USETW(req.wLength, len);
312 return (usbd_do_request(dev, &req, data));
313 }
314
315 usbd_status
316 usbd_set_idle(iface, duration, id)
317 usbd_interface_handle iface;
318 int duration;
319 int id;
320 {
321 usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
322 usbd_device_handle dev;
323 usb_device_request_t req;
324 usbd_status r;
325
326 DPRINTFN(4, ("usbd_set_idle: %d %d\n", duration, id));
327 r = usbd_interface2device_handle(iface, &dev);
328 if (r != USBD_NORMAL_COMPLETION)
329 return (r);
330 if (!ifd)
331 return (USBD_INVAL);
332 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
333 req.bRequest = UR_SET_IDLE;
334 USETW2(req.wValue, duration, id);
335 USETW(req.wIndex, ifd->bInterfaceNumber);
336 USETW(req.wLength, 0);
337 return (usbd_do_request(dev, &req, 0));
338 }
339
340 usbd_status
341 usbd_get_report_descriptor(dev, i, size, d)
342 usbd_device_handle dev;
343 int i;
344 int size;
345 void *d;
346 {
347 usb_device_request_t req;
348
349 req.bmRequestType = UT_READ_INTERFACE;
350 req.bRequest = UR_GET_DESCRIPTOR;
351 USETW2(req.wValue, UDESC_REPORT, 0);
352 USETW(req.wIndex, i);
353 USETW(req.wLength, size);
354 return (usbd_do_request(dev, &req, d));
355 }
356
357 usb_hid_descriptor_t *
358 usbd_get_hid_descriptor(ifc)
359 usbd_interface_handle ifc;
360 {
361 usb_interface_descriptor_t *idesc = usbd_get_interface_descriptor(ifc);
362 usbd_device_handle dev;
363 usb_config_descriptor_t *cdesc;
364 usb_hid_descriptor_t *hd;
365 char *p, *end;
366 usbd_status r;
367
368 r = usbd_interface2device_handle(ifc, &dev);
369 if (r != USBD_NORMAL_COMPLETION)
370 return (0);
371 cdesc = usbd_get_config_descriptor(dev);
372
373 p = (char *)idesc + idesc->bLength;
374 end = (char *)cdesc + UGETW(cdesc->wTotalLength);
375
376 for (; p < end; p += hd->bLength) {
377 hd = (usb_hid_descriptor_t *)p;
378 if (p + hd->bLength <= end && hd->bDescriptorType == UDESC_HID)
379 return (hd);
380 if (hd->bDescriptorType == UDESC_INTERFACE)
381 break;
382 }
383 return (0);
384 }
385
386 usbd_status
387 usbd_alloc_report_desc(ifc, descp, sizep, mem)
388 usbd_interface_handle ifc;
389 void **descp;
390 int *sizep;
391 int mem;
392 {
393 usb_hid_descriptor_t *hid;
394 usbd_device_handle dev;
395 usbd_status r;
396
397 r = usbd_interface2device_handle(ifc, &dev);
398 if (r != USBD_NORMAL_COMPLETION)
399 return (r);
400 hid = usbd_get_hid_descriptor(ifc);
401 if (!hid)
402 return (USBD_IOERROR);
403 *sizep = UGETW(hid->descrs[0].wDescriptorLength);
404 *descp = malloc(*sizep, mem, M_NOWAIT);
405 if (!*descp)
406 return (USBD_NOMEM);
407 r = usbd_get_report_descriptor(dev, 0, *sizep, *descp);
408 if (r != USBD_NORMAL_COMPLETION) {
409 free(*descp, mem);
410 return (r);
411 }
412 return (USBD_NORMAL_COMPLETION);
413 }
414