This source file includes following definitions.
- usbf_match
- usbf_attach
- usbf_add_task
- usbf_rem_task
- usbf_create_thread
- usbf_task_thread
- usbf_host_reset
- usbf_get_descriptor
- usbf_set_address
- usbf_set_config
- usbf_do_request
- usb_enum_string
- usbf_request_code_string
- usbf_request_type_string
- usbf_request_desc_string
- usbf_dump_request
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 #include <sys/param.h>
54 #include <sys/device.h>
55 #include <sys/kthread.h>
56 #include <sys/malloc.h>
57 #include <sys/systm.h>
58
59 #include <machine/bus.h>
60
61 #include <dev/usb/usb.h>
62 #include <dev/usb/usbdi.h>
63 #include <dev/usb/usbdivar.h>
64 #include <dev/usb/usbf.h>
65 #include <dev/usb/usbfvar.h>
66
67 #ifndef USBF_DEBUG
68 #define DPRINTF(l, x) do {} while (0)
69 #else
70 int usbfdebug = 0;
71 #define DPRINTF(l, x) if ((l) <= usbfdebug) printf x; else {}
72 #endif
73
74 struct usbf_softc {
75 struct device sc_dev;
76 usbf_bus_handle sc_bus;
77 struct usbf_port sc_port;
78 struct proc *sc_proc;
79 TAILQ_HEAD(,usbf_task) sc_tskq;
80 int sc_dying;
81 };
82
83 #define DEVNAME(sc) ((sc)->sc_dev.dv_xname)
84
85 int usbf_match(struct device *, void *, void *);
86 void usbf_attach(struct device *, struct device *, void *);
87 void usbf_create_thread(void *);
88 void usbf_task_thread(void *);
89
90 usbf_status usbf_get_descriptor(usbf_device_handle, usb_device_request_t *,
91 void **);
92 void usbf_set_address(usbf_device_handle, u_int8_t);
93 usbf_status usbf_set_config(usbf_device_handle, u_int8_t);
94
95 #ifdef USBF_DEBUG
96 void usbf_dump_request(usbf_device_handle, usb_device_request_t *);
97 #endif
98
99 struct cfattach usbf_ca = {
100 sizeof(struct usbf_softc), usbf_match, usbf_attach
101 };
102
103 struct cfdriver usbf_cd = {
104 NULL, "usbf", DV_DULL
105 };
106
107 static const char * const usbrev_str[] = USBREV_STR;
108
109 int
110 usbf_match(struct device *parent, void *match, void *aux)
111 {
112 return UMATCH_GENERIC;
113 }
114
115 void
116 usbf_attach(struct device *parent, struct device *self, void *aux)
117 {
118 struct usbf_softc *sc = (struct usbf_softc *)self;
119 int usbrev;
120 int speed;
121 usbf_status err;
122
123
124 sc->sc_bus = aux;
125 sc->sc_bus->usbfctl = sc;
126
127 usbrev = sc->sc_bus->usbrev;
128 printf(": USB revision %s", usbrev_str[usbrev]);
129 switch (usbrev) {
130 case USBREV_2_0:
131 speed = USB_SPEED_HIGH;
132 break;
133 case USBREV_1_1:
134 case USBREV_1_0:
135 speed = USB_SPEED_FULL;
136 break;
137 default:
138 printf(", not supported\n");
139 sc->sc_dying = 1;
140 return;
141 }
142 printf("\n");
143
144
145 TAILQ_INIT(&sc->sc_tskq);
146
147
148 if (usbf_softintr_establish(sc->sc_bus)) {
149 printf("%s: can't establish softintr\n", DEVNAME(sc));
150 sc->sc_dying = 1;
151 return;
152 }
153
154
155 err = usbf_new_device(self, sc->sc_bus, 0, speed, 0, &sc->sc_port);
156 if (err) {
157 printf("%s: usbf_new_device failed, %s\n", DEVNAME(sc),
158 usbf_errstr(err));
159 sc->sc_dying = 1;
160 return;
161 }
162
163
164 config_pending_incr();
165 kthread_create_deferred(usbf_create_thread, sc);
166 }
167
168
169
170
171
172
173
174
175
176
177 void
178 usbf_add_task(usbf_device_handle dev, struct usbf_task *task)
179 {
180 struct usbf_softc *sc = dev->bus->usbfctl;
181 int s;
182
183 s = splusb();
184 if (!task->onqueue) {
185 DPRINTF(1,("usbf_add_task: task=%p, proc=%s\n",
186 task, sc->sc_bus->intr_context ? "(null)" :
187 curproc->p_comm));
188 TAILQ_INSERT_TAIL(&sc->sc_tskq, task, next);
189 task->onqueue = 1;
190 } else {
191 DPRINTF(0,("usbf_add_task: task=%p on q, proc=%s\n",
192 task, sc->sc_bus->intr_context ? "(null)" :
193 curproc->p_comm));
194 }
195 wakeup(&sc->sc_tskq);
196 splx(s);
197 }
198
199 void
200 usbf_rem_task(usbf_device_handle dev, struct usbf_task *task)
201 {
202 struct usbf_softc *sc = dev->bus->usbfctl;
203 int s;
204
205 s = splusb();
206 if (task->onqueue) {
207 DPRINTF(1,("usbf_rem_task: task=%p\n", task));
208 TAILQ_REMOVE(&sc->sc_tskq, task, next);
209 task->onqueue = 0;
210
211 } else {
212 DPRINTF(0,("usbf_rem_task: task=%p not on q", task));
213 }
214 splx(s);
215 }
216
217
218
219
220 void
221 usbf_create_thread(void *arg)
222 {
223 struct usbf_softc *sc = arg;
224
225 if (kthread_create(usbf_task_thread, sc, &sc->sc_proc, "%s",
226 DEVNAME(sc)) != 0) {
227 printf("%s: can't create task thread\n", DEVNAME(sc));
228 return;
229 }
230 config_pending_decr();
231 }
232
233
234
235
236 void
237 usbf_task_thread(void *arg)
238 {
239 struct usbf_softc *sc = arg;
240 struct usbf_task *task;
241 int s;
242
243 DPRINTF(0,("usbf_task_thread: start (pid %d)\n", curproc->p_pid));
244
245 s = splusb();
246 while (!sc->sc_dying) {
247 task = TAILQ_FIRST(&sc->sc_tskq);
248 if (task == NULL) {
249 tsleep(&sc->sc_tskq, PWAIT, "usbtsk", 0);
250 task = TAILQ_FIRST(&sc->sc_tskq);
251 }
252 DPRINTF(1,("usbf_task_thread: woke up task=%p\n", task));
253 if (task != NULL) {
254 TAILQ_REMOVE(&sc->sc_tskq, task, next);
255 task->onqueue = 0;
256 splx(s);
257 task->fun(task->arg);
258 s = splusb();
259 DPRINTF(1,("usbf_task_thread: done task=%p\n", task));
260 }
261 }
262 splx(s);
263
264 DPRINTF(0,("usbf_task_thread: exit\n"));
265 kthread_exit(0);
266 }
267
268
269
270
271
272 void
273 usbf_host_reset(usbf_bus_handle bus)
274 {
275 usbf_device_handle dev = bus->usbfctl->sc_port.device;
276
277 DPRINTF(0,("usbf_host_reset\n"));
278
279
280 (void)usbf_set_config(dev, USB_UNCONFIG_NO);
281 dev->address = 0;
282 }
283
284
285
286
287
288
289 static u_int8_t hs_config[65536];
290
291 usbf_status
292 usbf_get_descriptor(usbf_device_handle dev, usb_device_request_t *req,
293 void **data)
294 {
295 u_int8_t type = UGETW(req->wValue) >> 8;
296 u_int8_t index = UGETW(req->wValue) & 0xff;
297 usb_device_descriptor_t *dd;
298 usb_config_descriptor_t *cd;
299 usb_string_descriptor_t *sd;
300
301 switch (type) {
302 case UDESC_DEVICE:
303 dd = usbf_device_descriptor(dev);
304 *data = dd;
305 USETW(req->wLength, MIN(UGETW(req->wLength), dd->bLength));;
306 return USBF_NORMAL_COMPLETION;
307
308 case UDESC_DEVICE_QUALIFIER: {
309 static usb_device_qualifier_t dq;
310
311 dd = usbf_device_descriptor(dev);
312 bzero(&dq, sizeof dq);
313 dq.bLength = USB_DEVICE_QUALIFIER_SIZE;
314 dq.bDescriptorType = UDESC_DEVICE_QUALIFIER;
315 USETW(dq.bcdUSB, 0x0200);
316 dq.bDeviceClass = dd->bDeviceClass;
317 dq.bDeviceSubClass = dd->bDeviceSubClass;
318 dq.bDeviceProtocol = dd->bDeviceProtocol;
319 dq.bMaxPacketSize0 = dd->bMaxPacketSize;
320 dq.bNumConfigurations = dd->bNumConfigurations;
321 *data = &dq;
322 USETW(req->wLength, MIN(UGETW(req->wLength), dq.bLength));;
323 return USBF_NORMAL_COMPLETION;
324 }
325
326 case UDESC_CONFIG:
327 cd = usbf_config_descriptor(dev, index);
328 if (cd == NULL)
329 return USBF_INVAL;
330 *data = cd;
331 USETW(req->wLength, MIN(UGETW(req->wLength),
332 UGETW(cd->wTotalLength)));
333 return USBF_NORMAL_COMPLETION;
334
335
336 case UDESC_OTHER_SPEED_CONFIGURATION:
337 cd = usbf_config_descriptor(dev, index);
338 if (cd == NULL)
339 return USBF_INVAL;
340 bcopy(cd, &hs_config, UGETW(cd->wTotalLength));
341 *data = &hs_config;
342 ((usb_config_descriptor_t *)&hs_config)->bDescriptorType =
343 UDESC_OTHER_SPEED_CONFIGURATION;
344 USETW(req->wLength, MIN(UGETW(req->wLength),
345 UGETW(cd->wTotalLength)));
346 return USBF_NORMAL_COMPLETION;
347
348 case UDESC_STRING:
349 sd = usbf_string_descriptor(dev, index);
350 if (sd == NULL)
351 return USBF_INVAL;
352 *data = sd;
353 USETW(req->wLength, MIN(UGETW(req->wLength), sd->bLength));
354 return USBF_NORMAL_COMPLETION;
355
356 default:
357 DPRINTF(0,("usbf_get_descriptor: unknown descriptor type=%u\n",
358 type));
359 return USBF_INVAL;
360 }
361 }
362
363
364
365
366
367 void
368 usbf_set_address(usbf_device_handle dev, u_int8_t address)
369 {
370 DPRINTF(0,("usbf_set_address: dev=%p, %u -> %u\n", dev,
371 dev->address, address));
372 dev->address = address;
373 }
374
375
376
377
378
379 usbf_status
380 usbf_set_config(usbf_device_handle dev, u_int8_t new)
381 {
382 usbf_config_handle cfg = dev->config;
383 usbf_function_handle fun = dev->function;
384 usbf_status err = USBF_NORMAL_COMPLETION;
385 u_int8_t old = cfg ? cfg->uc_cdesc->bConfigurationValue :
386 USB_UNCONFIG_NO;
387
388 if (old == new)
389 return USBF_NORMAL_COMPLETION;
390
391 DPRINTF(0,("usbf_set_config: dev=%p, %u -> %u\n", dev, old, new));
392
393
394
395
396
397 if (new == USB_UNCONFIG_NO) {
398 if (dev->function->methods->set_config)
399 err = fun->methods->set_config(fun, NULL);
400 if (err) {
401 DPRINTF(0,("usbf_set_config: %s\n", usbf_errstr(err)));
402 }
403 dev->config = NULL;
404 return USBF_NORMAL_COMPLETION;
405 }
406
407
408
409
410
411 SIMPLEQ_FOREACH(cfg, &dev->configs, next) {
412 if (cfg->uc_cdesc->bConfigurationValue == new) {
413 if (dev->function->methods->set_config)
414 err = fun->methods->set_config(fun, cfg);
415 if (!err)
416 dev->config = cfg;
417 return err;
418 }
419 }
420 return USBF_INVAL;
421 }
422
423
424
425
426 void
427 usbf_do_request(usbf_xfer_handle xfer, usbf_private_handle priv,
428 usbf_status err)
429 {
430 usbf_device_handle dev = xfer->pipe->device;
431 usb_device_request_t *req = xfer->buffer;
432 usbf_config_handle cfg;
433 void *data = NULL;
434 u_int16_t value;
435 u_int16_t index;
436
437 if (err) {
438 DPRINTF(0,("usbf_do_request: receive failed, %s\n",
439 usbf_errstr(err)));
440 return;
441 }
442
443 #ifdef USBF_DEBUG
444 if (usbfdebug >= 0)
445 usbf_dump_request(dev, req);
446 #endif
447
448 #define C(x,y) ((x) | ((y) << 8))
449 switch (C(req->bRequest, req->bmRequestType)) {
450
451 case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
452
453 usbf_set_address(dev, UGETW(req->wValue));
454 break;
455
456 case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
457
458 printf("set config activated\n");
459 err = usbf_set_config(dev, UGETW(req->wValue) & 0xff);
460 break;
461
462 case C(UR_GET_CONFIG, UT_READ_DEVICE):
463 {
464 if ((cfg = dev->config) == NULL) {
465 static u_int8_t zero = 0;
466 data = &zero;
467 } else
468 data = &cfg->uc_cdesc->bConfigurationValue;
469 USETW(req->wLength, MIN(UGETW(req->wLength), 1));;
470 }
471 break;
472
473 case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
474 err = usbf_get_descriptor(dev, req, &data);
475 break;
476
477 case C(UR_GET_STATUS, UT_READ_DEVICE):
478 DPRINTF(1,("usbf_do_request: UR_GET_STATUS %d\n",
479 UGETW(req->wLength)));
480 data = &dev->status;
481 USETW(req->wLength, MIN(UGETW(req->wLength),
482 sizeof dev->status));
483 break;
484
485 case C(UR_GET_STATUS, UT_READ_ENDPOINT): {
486
487 static u_int16_t status = 0;
488
489 data = &status;
490 USETW(req->wLength, MIN(UGETW(req->wLength), sizeof status));
491 break;
492 }
493
494 case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
495 value = UGETW(req->wValue);
496 index = UGETW(req->wIndex);
497 if ((cfg = dev->config) == NULL)
498 err = USBF_STALLED;
499 else
500 err = usbf_set_endpoint_feature(cfg, index, value);
501 break;
502
503 case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
504 value = UGETW(req->wValue);
505 index = UGETW(req->wIndex);
506 if ((cfg = dev->config) == NULL)
507 err = USBF_STALLED;
508 else
509 err = usbf_clear_endpoint_feature(cfg, index, value);
510 break;
511
512
513 case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
514 if (UGETW(req->wValue) != 0)
515 err = USBF_STALLED;
516 break;
517 case C(UR_GET_INTERFACE, UT_READ_INTERFACE): {
518 static u_int8_t zero = 0;
519 data = &zero;
520 USETW(req->wLength, MIN(UGETW(req->wLength), 1));
521 break;
522 }
523
524 default: {
525 usbf_function_handle fun = dev->function;
526
527 if (fun == NULL)
528 err = USBF_STALLED;
529 else
530
531
532 err = fun->methods->do_request(fun, req, &data);
533 }
534 }
535
536 if (err) {
537 DPRINTF(0,("usbf_do_request: request=%#x, type=%#x "
538 "failed, %s\n", req->bRequest, req->bmRequestType,
539 usbf_errstr(err)));
540 usbf_stall_pipe(dev->default_pipe);
541 } else if (UGETW(req->wLength) > 0) {
542 if (data == NULL) {
543 DPRINTF(0,("usbf_do_request: no data, "
544 "sending ZLP\n"));
545 USETW(req->wLength, 0);
546 }
547
548 usbf_setup_xfer(dev->data_xfer, dev->default_pipe,
549 NULL, data, UGETW(req->wLength), 0, 0, NULL);
550 err = usbf_transfer(dev->data_xfer);
551 if (err && err != USBF_IN_PROGRESS) {
552 DPRINTF(0,("usbf_do_request: data xfer=%p, %s\n",
553 xfer, usbf_errstr(err)));
554 }
555 }
556
557
558 usbf_setup_default_xfer(dev->default_xfer, dev->default_pipe,
559 NULL, &dev->def_req, 0, 0, usbf_do_request);
560 err = usbf_transfer(dev->default_xfer);
561 if (err && err != USBF_IN_PROGRESS) {
562 DPRINTF(0,("usbf_do_request: ctrl xfer=%p, %s\n", xfer,
563 usbf_errstr(err)));
564 }
565 }
566
567 #ifdef USBF_DEBUG
568 struct usb_enum_str {
569 int code;
570 const char * const str;
571 };
572
573 static const struct usb_enum_str usb_request_str[] = {
574 { UR_GET_STATUS, "GET STATUS" },
575 { UR_CLEAR_FEATURE, "CLEAR FEATURE" },
576 { UR_SET_FEATURE, "SET FEATURE" },
577 { UR_SET_ADDRESS, "SET ADDRESS" },
578 { UR_GET_DESCRIPTOR, "GET DESCRIPTOR" },
579 { UR_SET_DESCRIPTOR, "SET DESCRIPTOR" },
580 { UR_GET_CONFIG, "GET CONFIG" },
581 { UR_SET_CONFIG, "SET CONFIG" },
582 { UR_GET_INTERFACE, "GET INTERFACE" },
583 { UR_SET_INTERFACE, "SET INTERFACE" },
584 { UR_SYNCH_FRAME, "SYNCH FRAME" },
585 { 0, NULL }
586 };
587
588 static const struct usb_enum_str usb_request_type_str[] = {
589 { UT_READ_DEVICE, "Read Device" },
590 { UT_READ_INTERFACE, "Read Interface" },
591 { UT_READ_ENDPOINT, "Read Endpoint" },
592 { UT_WRITE_DEVICE, "Write Device" },
593 { UT_WRITE_INTERFACE, "Write Interface" },
594 { UT_WRITE_ENDPOINT, "Write Endpoint" },
595 { UT_READ_CLASS_DEVICE, "Read Class Device" },
596 { UT_READ_CLASS_INTERFACE, "Read Class Interface" },
597 { UT_READ_CLASS_OTHER, "Read Class Other" },
598 { UT_READ_CLASS_ENDPOINT, "Read Class Endpoint" },
599 { UT_WRITE_CLASS_DEVICE, "Write Class Device" },
600 { UT_WRITE_CLASS_INTERFACE, "Write Class Interface" },
601 { UT_WRITE_CLASS_OTHER, "Write Class Other" },
602 { UT_WRITE_CLASS_ENDPOINT, "Write Class Endpoint" },
603 { UT_READ_VENDOR_DEVICE, "Read Vendor Device" },
604 { UT_READ_VENDOR_INTERFACE, "Read Vendor Interface" },
605 { UT_READ_VENDOR_OTHER, "Read Vendor Other" },
606 { UT_READ_VENDOR_ENDPOINT, "Read Vendor Endpoint" },
607 { UT_WRITE_VENDOR_DEVICE, "Write Vendor Device" },
608 { UT_WRITE_VENDOR_INTERFACE, "Write Vendor Interface" },
609 { UT_WRITE_VENDOR_OTHER, "Write Vendor Other" },
610 { UT_WRITE_VENDOR_ENDPOINT, "Write Vendor Endpoint" },
611 { 0, NULL }
612 };
613
614 static const struct usb_enum_str usb_request_desc_str[] = {
615 { UDESC_DEVICE, "Device" },
616 { UDESC_CONFIG, "Configuration" },
617 { UDESC_STRING, "String" },
618 { UDESC_INTERFACE, "Interface" },
619 { UDESC_ENDPOINT, "Endpoint" },
620 { UDESC_DEVICE_QUALIFIER, "Device Qualifier" },
621 { UDESC_OTHER_SPEED_CONFIGURATION, "Other Speed Configuration" },
622 { UDESC_INTERFACE_POWER, "Interface Power" },
623 { UDESC_OTG, "OTG" },
624 { UDESC_CS_DEVICE, "Class-specific Device" },
625 { UDESC_CS_CONFIG, "Class-specific Configuration" },
626 { UDESC_CS_STRING, "Class-specific String" },
627 { UDESC_CS_INTERFACE, "Class-specific Interface" },
628 { UDESC_CS_ENDPOINT, "Class-specific Endpoint" },
629 { UDESC_HUB, "Hub" },
630 { 0, NULL }
631 };
632
633 static const char *
634 usb_enum_string(const struct usb_enum_str *tab, int code)
635 {
636 static char buf[16];
637
638 while (tab->str != NULL) {
639 if (tab->code == code)
640 return tab->str;
641 tab++;
642 }
643
644 (void)snprintf(buf, sizeof buf, "0x%02x", code);
645 return buf;
646 }
647
648 static const char *
649 usbf_request_code_string(usb_device_request_t *req)
650 {
651 static char buf[32];
652
653 (void)snprintf(buf, sizeof buf, "%s",
654 usb_enum_string(usb_request_str, req->bRequest));
655 return buf;
656 }
657
658 static const char *
659 usbf_request_type_string(usb_device_request_t *req)
660 {
661 static char buf[32];
662
663 (void)snprintf(buf, sizeof buf, "%s",
664 usb_enum_string(usb_request_type_str, req->bmRequestType));
665 return buf;
666 }
667
668 static const char *
669 usbf_request_desc_string(usb_device_request_t *req)
670 {
671 static char buf[32];
672 u_int8_t type = UGETW(req->wValue) >> 8;
673 u_int8_t index = UGETW(req->wValue) & 0xff;
674
675 (void)snprintf(buf, sizeof buf, "%s/%u",
676 usb_enum_string(usb_request_desc_str, type), index);
677 return buf;
678 }
679
680 void
681 usbf_dump_request(usbf_device_handle dev, usb_device_request_t *req)
682 {
683 struct usbf_softc *sc = dev->bus->usbfctl;
684
685 printf("%s: %s request %s\n",
686 DEVNAME(sc), usbf_request_type_string(req),
687 usbf_request_code_string(req));
688
689 if (req->bRequest == UR_GET_DESCRIPTOR)
690 printf("%s: VALUE: 0x%04x (%s)\n", DEVNAME(sc),
691 UGETW(req->wValue), usbf_request_desc_string(req));
692 else
693 printf("%s: VALUE: 0x%04x\n", DEVNAME(sc),
694 UGETW(req->wValue));
695
696 printf("%s: INDEX: 0x%04x\n", DEVNAME(sc), UGETW(req->wIndex));
697 printf("%s: LENGTH: 0x%04x\n", DEVNAME(sc), UGETW(req->wLength));
698 }
699 #endif