Create a branch for cmake bringup.
[reactos.git] / drivers / usb / nt4compat / usbdriver / usb.c
1 /**
2 * usb.c - USB driver stack project for Windows NT 4.0
3 *
4 * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com
5 *
6 * This program/include file is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program/include file is distributed in the hope that it will be
12 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program (in the main directory of the distribution, the file
18 * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #include "usbdriver.h"
23
24 LONG g_alloc_cnt = 0;
25 ULONG cpu_clock_freq = 0;
26
27 NTSTATUS usb_get_descriptor(PUSB_DEV pdev, PURB purb);
28 VOID usb_set_interface_completion(PURB purb, PVOID context);
29 NTSTATUS usb_set_interface(PURB purb);
30
31 PVOID
32 usb_alloc_mem(POOL_TYPE pool_type, LONG size)
33 {
34 PVOID ret;
35 g_alloc_cnt++;
36 ret = ExAllocatePool(pool_type, size);
37 usb_dbg_print(DBGLVL_ULTRA, ("usb_alloc_mem(): alloced=0x%x\n", g_alloc_cnt));
38 return ret;
39 }
40
41 VOID
42 usb_free_mem(PVOID pbuf)
43 {
44 g_alloc_cnt--;
45 usb_dbg_print(DBGLVL_ULTRA, ("usb_free_mem(): alloced=0x%x\n", g_alloc_cnt));
46 ExFreePool(pbuf);
47 }
48
49 VOID usb_config_dev_completion(PURB purb, PVOID context);
50
51 //shamelessly pasted from linux's usb.c
52 LONG
53 usb_calc_bus_time(LONG speed, LONG input_dir, LONG is_iso, LONG byte_count)
54 {
55 LONG tmp;
56
57 switch (speed & 0x3) /* no isoc. here */
58 {
59 case USB_SPEED_LOW:
60 {
61 if (input_dir)
62 {
63 tmp = (67667L * (31L + 10L * bit_time(byte_count))) / 1000L;
64 return (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);
65 }
66 else
67 {
68 tmp = (66700L * (31L + 10L * bit_time(byte_count))) / 1000L;
69 return (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);
70 }
71 break;
72 }
73 /* for full-speed: */
74 case USB_SPEED_FULL:
75 {
76 if (!is_iso) /* Input or Output */
77 {
78 tmp = (8354L * (31L + 10L * bit_time(byte_count))) / 1000L;
79 return (9107L + BW_HOST_DELAY + tmp);
80 } /* end not Isoc */
81
82 /* for isoc: */
83
84 tmp = (8354L * (31L + 10L * bit_time(byte_count))) / 1000L;
85 return (((input_dir) ? 7268L : 6265L) + BW_HOST_DELAY + tmp);
86 }
87 case USB_SPEED_HIGH:
88 {
89 if (!is_iso)
90 {
91 tmp = (999 + 926520 + 2083 * ((LONG) ((19 + 7 * 8 * byte_count) / 6))) / 1000;
92 }
93 else
94 {
95 tmp = (999 + 633232 + 2083 * ((LONG) ((19 + 7 * 8 * byte_count) / 6))) / 1000;
96 }
97 return tmp + USB2_HOST_DELAY;
98 }
99 default:
100 {
101 break;
102 }
103 }
104 return 125001;
105 }
106
107 //
108 // if the dev is not in the list, return value is not success and the pointer is nulled
109 // if the dev is in the list but zomb, return value is error code and the pointer is the dev( no ref_count guarded )
110 // if the dev is alive and in the list, return is success and the pointer is the dev.
111 // one must be aware of what his doing before he uses the ppdev
112 //
113 NTSTATUS
114 usb_query_and_lock_dev(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle, PUSB_DEV * ppdev)
115 {
116 int i;
117 PLIST_ENTRY pthis, pnext;
118 PUSB_DEV pdev = NULL;
119 BOOLEAN valid_dev;
120
121 USE_NON_PENDING_IRQL;
122
123 *ppdev = NULL;
124
125 if (dev_mgr == NULL || dev_handle == 0)
126 return STATUS_INVALID_PARAMETER;
127
128 i = dev_id_from_handle(dev_handle);
129
130 KeAcquireSpinLock(&dev_mgr->dev_list_lock, &old_irql);
131 ListFirst(&dev_mgr->dev_list, pthis);
132
133 while (pthis)
134 {
135 pdev = (PUSB_DEV) pthis;
136 if (pdev->dev_id != (ULONG) i)
137 {
138 ListNext(&dev_mgr->dev_list, pthis, pnext);
139 pthis = pnext;
140 continue;
141 }
142 else
143 break;
144 }
145 if (pthis == NULL)
146 {
147 //no such device
148 KeReleaseSpinLock(&dev_mgr->dev_list_lock, old_irql);
149 return STATUS_INVALID_PARAMETER;
150 }
151
152 valid_dev = TRUE;
153
154 lock_dev(pdev, TRUE);
155
156 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
157 {
158 valid_dev = FALSE;
159 }
160 else
161 pdev->ref_count++; //guard the dev by increasing the ref count
162
163 unlock_dev(pdev, TRUE);
164
165 KeReleaseSpinLock(&dev_mgr->dev_list_lock, old_irql);
166
167 *ppdev = pdev;
168
169 if (!valid_dev)
170 return STATUS_DEVICE_DOES_NOT_EXIST;
171
172 return STATUS_SUCCESS;
173
174 }
175
176 NTSTATUS
177 usb_unlock_dev(PUSB_DEV dev)
178 {
179 USE_BASIC_NON_PENDING_IRQL;
180
181 if (dev == NULL)
182 return STATUS_INVALID_PARAMETER;
183
184 lock_dev(dev, FALSE);
185 dev->ref_count--;
186 if (dev->ref_count < 0)
187 dev->ref_count = 0;
188 unlock_dev(dev, FALSE);
189 return STATUS_SUCCESS;
190 }
191
192 NTSTATUS
193 usb_reset_pipe_ex(PUSB_DEV_MANAGER dev_mgr,
194 DEV_HANDLE endp_handle, //endp handle to reset
195 PURBCOMPLETION reset_completion, //note: this reset completion has no right to delete the urb, that is only for reference
196 PVOID param)
197 {
198 NTSTATUS status;
199 PUSB_DEV pdev;
200 LONG if_idx, endp_idx;
201 PUSB_ENDPOINT pendp;
202 USE_BASIC_NON_PENDING_IRQL;
203
204 if (dev_mgr == NULL)
205 return STATUS_INVALID_PARAMETER;
206
207 status = usb_query_and_lock_dev(dev_mgr, (endp_handle & 0xffff0000), &pdev);
208 if (status != STATUS_SUCCESS)
209 return STATUS_UNSUCCESSFUL;
210
211 lock_dev(pdev, FALSE);
212 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
213 {
214 status = STATUS_UNSUCCESSFUL;
215 goto LBL_OUT;
216 }
217
218 if_idx = if_idx_from_handle(endp_handle);
219 endp_idx = endp_idx_from_handle(endp_handle);
220
221 if (default_endp_handle(endp_handle))
222 {
223 status = STATUS_UNSUCCESSFUL;
224 goto LBL_OUT;
225 }
226
227 if (dev_state(pdev) < USB_DEV_STATE_CONFIGURED)
228 {
229 status = STATUS_DEVICE_NOT_READY;
230 goto LBL_OUT;
231 }
232
233 pendp = &pdev->usb_config->interf[if_idx].endp[endp_idx];
234 unlock_dev(pdev, FALSE) status = usb_reset_pipe(pdev, pendp, reset_completion, param);
235 usb_unlock_dev(pdev);
236 return status;
237
238 LBL_OUT:
239 unlock_dev(pdev, FALSE);
240 usb_unlock_dev(pdev);
241
242 return status;
243 }
244
245 // caller must guarantee the pdev exist before the routine exit
246 NTSTATUS
247 usb_reset_pipe(PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURBCOMPLETION client_reset_pipe_completion, PVOID param)
248 {
249
250 PHCD hcd;
251 PURB purb;
252 BYTE endp_addr;
253 NTSTATUS status;
254 DEV_HANDLE dev_handle;
255
256 USE_BASIC_NON_PENDING_IRQL;
257
258 if (pdev == NULL || pendp == NULL)
259 return STATUS_INVALID_PARAMETER;
260
261 lock_dev(pdev, FALSE);
262 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
263 {
264 unlock_dev(pdev, FALSE);
265 return STATUS_DEVICE_DOES_NOT_EXIST;
266 }
267
268 hcd = pdev->hcd;
269 endp_addr = pendp->pusb_endp_desc->bEndpointAddress;
270 dev_handle = usb_make_handle(pdev->dev_id, 0, 0);
271 unlock_dev(pdev, FALSE);
272
273 purb = (PURB) usb_alloc_mem(NonPagedPool, sizeof(URB) + sizeof(PIRP));
274
275 if (purb == NULL)
276 return STATUS_NO_MEMORY;
277
278 UsbBuildResetPipeRequest(purb,
279 dev_handle,
280 endp_addr,
281 usb_reset_pipe_completion,
282 pendp,
283 (LONG)client_reset_pipe_completion);
284
285 *((PULONG)&purb[1]) = (ULONG)param;
286
287 if ((status = hcd->hcd_submit_urb(hcd, pdev, &pdev->default_endp, purb)) != STATUS_PENDING)
288 {
289 usb_free_mem(purb);
290 purb = NULL;
291 }
292 return status;
293 }
294
295 VOID
296 usb_reset_pipe_completion(PURB purb, PVOID context)
297 {
298 PUSB_DEV pdev;
299 PUSB_ENDPOINT pendp;
300
301 USE_BASIC_NON_PENDING_IRQL;
302
303 if (purb == NULL || context == NULL)
304 return;
305
306 pdev = purb->pdev;
307 pendp = (PUSB_ENDPOINT) context;
308
309 lock_dev(pdev, TRUE);
310 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
311 {
312 goto LBL_OUT;
313 }
314
315 if (usb_error(purb->status))
316 {
317 goto LBL_OUT;
318 }
319 //clear stall
320 pendp->flags &= ~USB_ENDP_FLAG_STAT_MASK;
321
322 //reset toggle endp_type
323 if ((pendp->pusb_endp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK ||
324 (pendp->pusb_endp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
325 {
326 pendp->flags &= ~USB_ENDP_FLAG_DATATOGGLE;
327 }
328
329 LBL_OUT:
330 unlock_dev(pdev, TRUE);
331
332 if (purb->reference)
333 ((PURBCOMPLETION) purb->reference) (purb, (PVOID) (*((PULONG) & purb[1])));
334
335 usb_free_mem(purb);
336 purb = NULL;
337 return;
338
339 }
340
341 void
342 usb_reset_pipe_from_dispatch_completion(PURB purb, PVOID param)
343 {
344 PURB pclient_urb;
345 if (purb == NULL || param == NULL)
346 TRAP();
347 pclient_urb = (PURB) param;
348 pclient_urb->status = purb->status;
349
350 if (pclient_urb->completion)
351 {
352 pclient_urb->completion(pclient_urb, pclient_urb->context);
353 }
354 // the urb can not be freed here because it is owned by the reset
355 // pipe completion
356 return;
357 }
358
359 //used to check descriptor validity
360 BOOLEAN
361 is_header_match(PUCHAR pbuf, ULONG type)
362 {
363 BOOLEAN ret;
364 PUSB_DESC_HEADER phdr;
365 phdr = (PUSB_DESC_HEADER) pbuf;
366
367 switch (type)
368 {
369 case USB_DT_DEVICE:
370 {
371 ret = (phdr->bLength == sizeof(USB_DEVICE_DESC) && phdr->bDescriptorType == USB_DT_DEVICE);
372 break;
373 }
374 case USB_DT_CONFIG:
375 {
376 ret = (phdr->bLength == sizeof(USB_CONFIGURATION_DESC) && phdr->bDescriptorType == USB_DT_CONFIG);
377 break;
378 }
379 case USB_DT_INTERFACE:
380 {
381 ret = (phdr->bLength == sizeof(USB_INTERFACE_DESC) && phdr->bDescriptorType == USB_DT_INTERFACE);
382 break;
383 }
384 case USB_DT_ENDPOINT:
385 {
386 ret = (phdr->bLength == sizeof(USB_ENDPOINT_DESC) && phdr->bDescriptorType == USB_DT_ENDPOINT);
387 break;
388 }
389 default:
390 ret = FALSE;
391 }
392 return ret;
393 }
394
395 BOOLEAN
396 usb_skip_endp_desc(PBYTE * pbUF, LONG n)
397 {
398 if (is_header_match(*pbUF, USB_DT_ENDPOINT))
399 {
400 (*pbUF) += sizeof(USB_ENDPOINT_DESC) * n;
401 return TRUE;
402 }
403 return FALSE;
404 }
405
406 BOOLEAN
407 usb_skip_if_desc(PBYTE * pBUF)
408 {
409 BOOLEAN ret;
410 PUSB_INTERFACE_DESC pif_desc = (PUSB_INTERFACE_DESC) * pBUF;
411 LONG endp_count;
412 ret = is_header_match((PBYTE) * pBUF, USB_DT_INTERFACE);
413 if (ret == TRUE)
414 {
415 endp_count = pif_desc->bNumEndpoints;
416 if (endp_count < MAX_ENDPS_PER_IF)
417 {
418 pif_desc++;
419 ret = usb_skip_endp_desc((PBYTE *) & pif_desc, endp_count);
420 if (ret)
421 *(pBUF) = (PBYTE) pif_desc;
422 }
423 else
424 ret = FALSE;
425 }
426 return ret;
427 }
428
429 BOOLEAN
430 usb_skip_if_and_altif(PUCHAR * pdesc_BUF)
431 {
432 BOOLEAN ret;
433 PUSB_INTERFACE_DESC pif_desc1 = (PUSB_INTERFACE_DESC) * pdesc_BUF;
434 ret = is_header_match(*pdesc_BUF, USB_DT_INTERFACE);
435 if (ret == TRUE)
436 {
437 if (pif_desc1->bAlternateSetting == 0)
438 ret = usb_skip_if_desc((PUCHAR *) & pif_desc1);
439 else
440 //no default interface
441 ret = FALSE;
442
443 while (ret && pif_desc1->bAlternateSetting != 0)
444 ret = usb_skip_if_desc((PUCHAR *) & pif_desc1);
445 }
446 if (ret)
447 *pdesc_BUF = (PUCHAR) pif_desc1;
448
449 return ret;
450 }
451
452 BOOLEAN
453 usb_skip_one_config(PUCHAR *pconfig_desc_BUF)
454 {
455 LONG if_count, i;
456 BOOLEAN ret;
457 PUSB_CONFIGURATION_DESC pcfg_DESC = (PUSB_CONFIGURATION_DESC) * pconfig_desc_BUF;
458 PUSB_INTERFACE_DESC pif_desc2 = (PUSB_INTERFACE_DESC) & pcfg_DESC[1];
459
460 ret = is_header_match((PUCHAR) pcfg_DESC, USB_DT_CONFIG);
461 if (ret)
462 *pconfig_desc_BUF = &((BYTE *) pcfg_DESC)[pcfg_DESC->wTotalLength];
463 return ret;
464
465 ret = is_header_match((PUCHAR) pcfg_DESC, USB_DT_CONFIG)
466 && is_header_match((PUCHAR) pif_desc2, USB_DT_INTERFACE);
467
468 if (ret)
469 {
470 if_count = pcfg_DESC->bNumInterfaces;
471 if (if_count < MAX_INTERFACES_PER_CONFIG)
472 {
473 for(i = 0; i < if_count; i++)
474 {
475 ret = usb_skip_if_and_altif((PUCHAR *) & pif_desc2);
476 if (ret == FALSE)
477 break;
478 }
479 if (ret)
480 *pconfig_desc_BUF = (PUCHAR) pif_desc2;
481 }
482 }
483 return ret;
484 }
485
486 PUSB_CONFIGURATION_DESC
487 usb_find_config_desc_by_idx(PUCHAR pbuf, LONG idx, LONG cfg_count)
488 {
489 LONG i;
490 BOOLEAN ret;
491 PUSB_CONFIGURATION_DESC pcfg_desc = (PUSB_CONFIGURATION_DESC) pbuf;
492 if (pcfg_desc == NULL)
493 return NULL;
494
495 if (cfg_count > MAX_CONFIGS_PER_DEV)
496 return NULL;
497
498 if (idx > cfg_count)
499 return NULL;
500
501 if (idx == 0)
502 return pcfg_desc;
503
504 for(i = 0; i < idx - 1; i++)
505 {
506 ret = usb_skip_one_config((PBYTE *) & pcfg_desc);
507 if (ret == FALSE)
508 return NULL;
509 }
510 return pcfg_desc;
511 }
512
513 PUSB_CONFIGURATION_DESC
514 usb_find_config_desc_by_val(PBYTE pbuf, LONG val, LONG cfg_count)
515 {
516 LONG i;
517 BOOLEAN ret;
518 PUSB_CONFIGURATION_DESC pcfg_desc = (PUSB_CONFIGURATION_DESC) pbuf;
519 if (pcfg_desc == NULL)
520 return NULL;
521
522 if (cfg_count > MAX_CONFIGS_PER_DEV)
523 return NULL;
524
525 for(i = 0; i < cfg_count; i++)
526 {
527 if (pcfg_desc->bConfigurationValue == val)
528 return pcfg_desc;
529
530 ret = usb_skip_one_config((PBYTE *) & pcfg_desc);
531 if (ret == FALSE)
532 return NULL;
533 }
534
535 return NULL;
536 }
537
538 #define if_from_handle( handle ) ( ( handle & 0xff00 ) >> 8 )
539
540 NTSTATUS
541 usb_submit_config_urb(PURB purb)
542 {
543 PUSB_DEV pdev;
544 PUSB_DEV_MANAGER dev_mgr;
545 PUSB_ENDPOINT pendp;
546 PURB purb1;
547 PUSB_CTRL_SETUP_PACKET psetup;
548 NTSTATUS status;
549 PHCD hcd;
550
551 USE_BASIC_NON_PENDING_IRQL;
552
553 if (purb == NULL)
554 return STATUS_INVALID_PARAMETER;
555
556 pdev = purb->pdev;
557 pendp = purb->pendp;
558
559 lock_dev(pdev, FALSE);
560
561 dev_mgr = dev_mgr_from_dev(pdev);
562 hcd = pdev->hcd;
563
564 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
565 {
566 status = STATUS_DEVICE_DOES_NOT_EXIST;
567 goto LBL_OUT;
568 }
569
570 if (dev_state(pdev) == USB_DEV_STATE_FIRST_CONFIG || dev_state(pdev) == USB_DEV_STATE_RECONFIG)
571 {
572 //outstanding request of set configuration exists in process
573 status = STATUS_UNSUCCESSFUL;
574 goto LBL_OUT;
575 }
576
577 psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
578
579 if (dev_state(pdev) == USB_DEV_STATE_CONFIGURED
580 && pdev->usb_config->pusb_config_desc->bConfigurationValue == (BYTE) psetup->wValue)
581 {
582 //already the current config
583 status = STATUS_SUCCESS;
584 goto LBL_OUT;
585 }
586
587
588 if (dev_state(pdev) == USB_DEV_STATE_CONFIGURED)
589 {
590 // not support re-configuration yet
591 status = STATUS_NOT_SUPPORTED;
592 goto LBL_OUT;
593 }
594
595 psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
596 purb1 = usb_alloc_mem(NonPagedPool, sizeof(URB));
597 if (purb1 == NULL)
598 {
599 status = STATUS_NO_MEMORY;
600 goto LBL_OUT;
601 }
602
603 UsbBuildSelectConfigurationRequest(purb1,
604 usb_make_handle(pdev->dev_id, 0, 0) | 0xffff,
605 psetup->wValue, usb_config_dev_completion, 0, ((ULONG) purb));
606 purb1->pdev = pdev;
607 purb1->pendp = pendp;
608
609 //change the dev state
610 pdev->flags &= ~USB_DEV_STATE_MASK;
611 pdev->flags |= USB_DEV_STATE_FIRST_CONFIG;
612
613 unlock_dev(pdev, FALSE);
614
615 status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb1);
616 if (status != STATUS_PENDING)
617 {
618 usb_free_mem(purb1);
619 purb1 = NULL;
620 }
621 return status;
622
623 LBL_OUT:
624 unlock_dev(pdev, FALSE);
625 return status;
626 }
627
628
629 NTSTATUS
630 usb_submit_urb(PUSB_DEV_MANAGER dev_mgr, PURB purb)
631 {
632 NTSTATUS status;
633 PUSB_DEV pdev;
634 LONG if_idx, endp_idx;
635 DEV_HANDLE endp_handle;
636 PUSB_CTRL_SETUP_PACKET psetup;
637 PUSB_ENDPOINT pendp;
638
639 PHCD hcd;
640 USE_BASIC_NON_PENDING_IRQL;
641
642 if (purb == NULL || dev_mgr == NULL)
643 return STATUS_INVALID_PARAMETER;
644
645 endp_handle = purb->endp_handle;
646
647 if (endp_handle == 0)
648 return STATUS_INVALID_PARAMETER;
649
650 status = usb_query_and_lock_dev(dev_mgr, endp_handle, &pdev);
651 if (status != STATUS_SUCCESS)
652 {
653 return status;
654 }
655
656 if_idx = if_idx_from_handle(endp_handle);
657 endp_idx = endp_idx_from_handle(endp_handle);
658
659 lock_dev(pdev, FALSE);
660 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
661 {
662 unlock_dev(pdev, FALSE);
663 status = STATUS_DEVICE_DOES_NOT_EXIST;
664 goto LBL_OUT;
665 }
666
667 if (dev_state(pdev) < USB_DEV_STATE_ADDRESSED)
668 {
669 unlock_dev(pdev, FALSE);
670 status = STATUS_DEVICE_NOT_READY;
671 goto LBL_OUT;
672 }
673
674 dev_mgr = dev_mgr_from_dev(pdev);
675 hcd = pdev->hcd;
676
677 if (default_endp_handle(endp_handle))
678 {
679 //default endp
680 pendp = &pdev->default_endp;
681 }
682 else if (if_idx >= MAX_INTERFACES_PER_CONFIG || endp_idx >= MAX_ENDPS_PER_IF)
683 {
684 status = STATUS_INVALID_PARAMETER;
685 unlock_dev(pdev, FALSE);
686 goto LBL_OUT;
687 }
688 else
689 {
690 if (dev_state(pdev) < USB_DEV_STATE_CONFIGURED)
691 {
692 status = STATUS_DEVICE_NOT_READY;
693 unlock_dev(pdev, FALSE);
694 goto LBL_OUT;
695 }
696 pendp = &pdev->usb_config->interf[if_idx].endp[endp_idx];
697
698 }
699
700 purb->pdev = pdev;
701 purb->pendp = pendp;
702
703 //for default endpoint we have some special process
704 if (default_endp_handle(endp_handle))
705 {
706 psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
707 if (psetup->bmRequestType == 0 && psetup->bRequest == USB_REQ_SET_CONFIGURATION)
708 {
709 unlock_dev(pdev, FALSE);
710 status = usb_submit_config_urb(purb);
711 goto LBL_OUT;
712 }
713 else if (psetup->bmRequestType == 1 && psetup->bRequest == USB_REQ_SET_INTERFACE)
714 {
715 unlock_dev(pdev, FALSE);
716 // status = STATUS_NOT_SUPPORTED;
717 status = usb_set_interface(purb);
718 goto LBL_OUT;
719 }
720 else if (psetup->bmRequestType == 0x80 && psetup->bRequest == USB_REQ_GET_DESCRIPTOR)
721 {
722 if ((psetup->wValue >> 8) == USB_DT_CONFIG || (psetup->wValue >> 8) == USB_DT_DEVICE)
723 {
724 unlock_dev(pdev, FALSE);
725 status = usb_get_descriptor(pdev, purb);
726 goto LBL_OUT;
727
728 //get the descriptor directly
729 //status = hcd->hcd_submit_urb( hcd, pdev, purb->pendp, purb );
730 //goto LBL_OUT;
731 }
732 }
733 else if (psetup->bmRequestType == 0x02 && psetup->bRequest == USB_REQ_CLEAR_FEATURE && psetup->wValue == 0) //reset pipe
734 {
735 ULONG endp_addr;
736 BOOLEAN found;
737 endp_addr = psetup->wIndex;
738 if ((endp_addr & 0xf) == 0)
739 {
740 unlock_dev(pdev, FALSE);
741 status = STATUS_INVALID_PARAMETER;
742 goto LBL_OUT;
743 }
744
745 // search for the endp by the endp addr in the wIndex
746 found = FALSE;
747 for(if_idx = 0; if_idx < pdev->usb_config->if_count; if_idx++)
748 {
749 for(endp_idx = 0; endp_idx < pdev->usb_config->interf[if_idx].endp_count; endp_idx++)
750 {
751 pendp = &pdev->usb_config->interf[if_idx].endp[endp_idx];
752 if (pendp->pusb_endp_desc->bEndpointAddress == endp_addr)
753 {
754 found = TRUE;
755 break;
756 }
757 }
758 if (found == TRUE)
759 break;
760 }
761 if (found)
762 endp_handle = usb_make_handle(pdev->dev_id, if_idx, endp_idx);
763 else
764 {
765 unlock_dev(pdev, FALSE);
766 status = STATUS_INVALID_PARAMETER;
767 goto LBL_OUT;
768 }
769 unlock_dev(pdev, FALSE);
770 status = usb_reset_pipe_ex(dev_mgr, endp_handle, usb_reset_pipe_from_dispatch_completion, purb);
771
772 goto LBL_OUT;
773 }
774 }
775
776 unlock_dev(pdev, FALSE);
777 status = hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb);
778
779 LBL_OUT:
780 usb_unlock_dev(pdev);
781 return status;
782 }
783
784 void
785 usb_config_dev_completion(PURB purb, PVOID context)
786 {
787 PURB puser_urb;
788 PUSB_DEV pdev;
789 PUSB_ENDPOINT pendp;
790 PUSB_CTRL_SETUP_PACKET psetup;
791 ULONG config_val;
792 NTSTATUS status;
793
794 USE_BASIC_NON_PENDING_IRQL;
795
796 UNREFERENCED_PARAMETER(context);
797
798 if (purb == NULL)
799 {
800 return;
801 }
802 pdev = purb->pdev;
803 pendp = purb->pendp;
804
805 if (pdev == NULL)
806 return;
807
808 if (purb->reference != 0)
809 puser_urb = (PURB) purb->reference;
810 else
811 puser_urb = NULL;
812
813 lock_dev(pdev, TRUE);
814
815 if (puser_urb)
816 puser_urb->status = purb->status;
817
818 if (purb->status != STATUS_SUCCESS)
819 {
820 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
821 {
822 goto LBL_OUT;
823 }
824
825 if (dev_state(pdev) == USB_DEV_STATE_FIRST_CONFIG)
826 {
827 pdev->flags &= ~USB_DEV_STATE_MASK;
828 pdev->flags |= USB_DEV_STATE_ADDRESSED;
829 }
830 else if (dev_state(pdev) == USB_DEV_STATE_RECONFIG)
831 {
832 pdev->flags &= ~USB_DEV_STATE_MASK;
833 pdev->flags |= USB_DEV_STATE_CONFIGURED;
834
835 }
836 goto LBL_OUT;
837 }
838 // now let's construct usb_config
839 if (!pdev->usb_config)
840 {
841 psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
842 config_val = psetup->wValue;
843 status = dev_mgr_build_usb_config(pdev,
844 &pdev->desc_buf[sizeof(USB_DEVICE_DESC)],
845 config_val, pdev->pusb_dev_desc->bNumConfigurations);
846 if (status != STATUS_SUCCESS)
847 {
848 pdev->flags &= ~USB_DEV_STATE_MASK;
849 pdev->flags |= USB_DEV_STATE_ADDRESSED;
850 goto LBL_OUT;
851 }
852 pdev->flags &= ~USB_DEV_STATE_MASK;
853 pdev->flags |= USB_DEV_STATE_CONFIGURED;
854 //this usb dev represents physical dev
855 if (pdev->pusb_dev_desc->bDeviceClass == USB_CLASS_HUB && pdev->pusb_dev_desc->bDeviceSubClass == 0)
856 {
857 pdev->flags &= ~USB_DEV_CLASS_MASK;
858 pdev->flags |= USB_DEV_CLASS_HUB;
859 }
860 else if (pdev->pusb_dev_desc->bDeviceClass == USB_CLASS_MASS_STORAGE
861 && pdev->pusb_dev_desc->bDeviceSubClass == 0)
862 {
863 pdev->flags &= ~USB_DEV_CLASS_MASK;
864 pdev->flags |= USB_DEV_CLASS_MASSSTOR;
865 }
866 else
867 {
868 pdev->flags &= ~USB_DEV_CLASS_MASK;
869 pdev->flags |= USB_DEV_CLASS_SCANNER;
870 }
871 }
872 else
873 {
874 //not supported
875 puser_urb->status = STATUS_NOT_SUPPORTED;
876 pdev->flags &= ~USB_DEV_STATE_MASK;
877 pdev->flags |= USB_DEV_STATE_CONFIGURED;
878 }
879
880 LBL_OUT:
881 unlock_dev(pdev, TRUE);
882 usb_free_mem(purb);
883 if (puser_urb && puser_urb->completion)
884 puser_urb->completion(puser_urb, puser_urb->context);
885
886 return;
887 }
888
889 NTSTATUS
890 usb_get_descriptor(PUSB_DEV pdev, PURB purb)
891 {
892 PUSB_CTRL_SETUP_PACKET psetup;
893 LONG idx, size, count, i;
894 PBYTE buf;
895 PUSB_CONFIGURATION_DESC pcfg_desc1;
896
897 USE_BASIC_NON_PENDING_IRQL;
898
899 if (pdev == NULL || purb == NULL)
900 return STATUS_INVALID_PARAMETER;
901
902 if (purb->data_buffer == NULL || purb->data_length == 0)
903 {
904 return purb->status = STATUS_INVALID_PARAMETER;
905 }
906
907 lock_dev(pdev, FALSE);
908 psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
909 if (pdev->desc_buf == NULL)
910 {
911 purb->status = STATUS_DEVICE_NOT_READY;
912 goto LBL_OUT;
913 }
914
915 if ((psetup->wValue >> 8) == USB_DT_CONFIG)
916 {
917 idx = (psetup->wValue & 0xff);
918
919 count = pdev->pusb_dev_desc->bNumConfigurations;
920
921 if (idx >= count)
922 {
923 purb->status = STATUS_INVALID_PARAMETER;
924 goto LBL_OUT;
925 }
926 buf = &pdev->desc_buf[sizeof(USB_DEVICE_DESC)];
927 pcfg_desc1 = usb_find_config_desc_by_idx(buf, idx, count);
928 if (pcfg_desc1 == NULL)
929 {
930 purb->status = STATUS_UNSUCCESSFUL;
931 goto LBL_OUT;
932 }
933
934 size = pcfg_desc1->wTotalLength;
935 size = size > purb->data_length ? purb->data_length : size;
936 for(i = 0; i < size; i++)
937 {
938 purb->data_buffer[i] = ((PBYTE) pcfg_desc1)[i];
939 }
940 purb->status = STATUS_SUCCESS;
941 goto LBL_OUT;
942
943 }
944 else if ((psetup->wValue >> 8) == USB_DT_DEVICE)
945 {
946 size = purb->data_length > sizeof(USB_DEVICE_DESC) ? sizeof(USB_DEVICE_DESC) : purb->data_length;
947
948 for(i = 0; i < size; i++)
949 {
950 purb->data_buffer[i] = ((PBYTE) pdev->pusb_dev_desc)[i];
951 }
952 purb->status = STATUS_SUCCESS;
953 }
954
955 LBL_OUT:
956 unlock_dev(pdev, FALSE);
957 return purb->status;
958 }
959
960 LONG
961 usb_count_list(PLIST_HEAD list_head)
962 {
963 LONG count;
964 PLIST_ENTRY pthis, pnext;
965
966 if (list_head == NULL)
967 return 0;
968
969 count = 0;
970 ListFirst(list_head, pthis);
971
972 while (pthis)
973 {
974 ListNext(list_head, pthis, pnext);
975 pthis = pnext;
976 count++;
977 }
978 return count;
979 }
980
981 // checks if processor supports Time Stamp Counter
982 __inline BOOLEAN
983 usb_query_clicks(PLARGE_INTEGER clicks)
984 {
985 BOOLEAN ret_val;
986 //so we have to use intel's cpu???
987 ret_val = FALSE;
988
989 #ifdef _MSC_VER
990 __asm
991 {
992 push ebx;
993 push eax;
994 mov eax, 1; //read version
995 cpuid;
996 test edx, 0x10; //timer stamp
997 jz LBL_OUT;
998 // cpuid //serialization
999 rdtsc;
1000 mov ebx, dword ptr[clicks];
1001 mov dword ptr[ebx], eax;
1002 mov dword ptr[ebx + 4], edx;
1003 mov dword ptr[ret_val], TRUE;
1004 LBL_OUT:
1005 pop eax;
1006 pop ebx;
1007 }
1008 #else
1009 ret_val = FALSE;
1010 #endif
1011 return ret_val;
1012 }
1013
1014 VOID
1015 usb_wait_ms_dpc(ULONG ms)
1016 {
1017 LARGE_INTEGER Interval;
1018 if (ms <= 0)
1019 return;
1020
1021 Interval.QuadPart = -ms * 10000;
1022 KeDelayExecutionThread(KernelMode, FALSE, &Interval);
1023 }
1024
1025
1026 VOID
1027 usb_wait_us_dpc(ULONG us)
1028 {
1029 LARGE_INTEGER Interval;
1030 if (us <= 0)
1031 return;
1032
1033 Interval.QuadPart = -us;
1034 KeDelayExecutionThread(KernelMode, FALSE, &Interval);
1035 }
1036
1037 VOID
1038 usb_cal_cpu_freq()
1039 {
1040 LARGE_INTEGER tick1, tick2;
1041 LONG i;
1042 // interval.QuadPart = -40 * 1000 * 1000;
1043
1044 if (cpu_clock_freq >= 100 * 1000 * 1000) // assume it is valid
1045 return;
1046
1047 if (usb_query_clicks(&tick1))
1048 {
1049 for(i = 0; i < 25; i++)
1050 {
1051 usb_query_clicks(&tick1);
1052 KeStallExecutionProcessor(40 * 1000);
1053 usb_query_clicks(&tick2);
1054 cpu_clock_freq += (ULONG) (tick2.QuadPart - tick1.QuadPart);
1055 }
1056 // cpu_clock_freq *= 1000;
1057 usb_dbg_print(DBGLVL_MAXIMUM, ("usb_cal_cpu_freq(): cpu frequency = %d Hz\n", cpu_clock_freq));
1058 }
1059 }
1060
1061 NTSTATUS
1062 usb_set_interface(PURB purb)
1063 {
1064 ULONG u;
1065 PURB purb1;
1066 PCTRL_REQ_STACK pstack;
1067 PUSB_DEV pdev;
1068 PUSB_CTRL_SETUP_PACKET psetup;
1069 PUSB_ENDPOINT pendp;
1070 NTSTATUS status;
1071
1072 PHCD hcd;
1073 USE_BASIC_NON_PENDING_IRQL;
1074
1075 purb1 = purb;
1076 pdev = purb->pdev;
1077 psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
1078
1079 lock_dev(pdev, FALSE);
1080 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
1081 {
1082 unlock_dev(pdev, FALSE);
1083 return STATUS_DEVICE_NOT_CONNECTED;
1084 }
1085 if (dev_state(pdev) < USB_DEV_STATE_CONFIGURED)
1086 {
1087 unlock_dev(pdev, FALSE);
1088 return STATUS_DEVICE_NOT_READY;
1089 }
1090
1091 hcd = pdev->hcd;
1092
1093 if (psetup->wIndex >= pdev->usb_config->if_count)
1094 {
1095 unlock_dev(pdev, FALSE);
1096 return STATUS_INVALID_PARAMETER;
1097 }
1098 if (psetup->wValue >= pdev->usb_config->interf[psetup->wIndex].altif_count + 1)
1099 {
1100 unlock_dev(pdev, FALSE);
1101 return STATUS_INVALID_PARAMETER;
1102 }
1103 if (pdev->usb_config->interf[psetup->wIndex].pusb_if_desc->bAlternateSetting == psetup->wValue)
1104 {
1105 // already the current interface
1106 unlock_dev(pdev, FALSE);
1107 return STATUS_SUCCESS;
1108 }
1109 // check to see if the endp is busy
1110 for(u = 0; u < pdev->usb_config->interf[psetup->wIndex].endp_count; u++)
1111 {
1112 // This check is not adquate. Since we do not have mechanism to block the new coming
1113 // request during this request. the caller must guarantee no active or pending
1114 // usb request on these endpoint.
1115 pendp = &pdev->usb_config->interf[psetup->wIndex].endp[u];
1116 if (usb_endp_busy_count(pendp))
1117 {
1118 // active urb on that endp
1119 unlock_dev(pdev, FALSE);
1120 return STATUS_DEVICE_NOT_READY;
1121 }
1122 if (IsListEmpty(&pendp->urb_list))
1123 {
1124 // pending urb on that endp
1125 unlock_dev(pdev, FALSE);
1126 return STATUS_DEVICE_NOT_READY;
1127 }
1128 }
1129 unlock_dev(pdev, FALSE);
1130
1131 if (purb1->ctrl_req_context.ctrl_stack_count == 0)
1132 {
1133 // ok, we have one stack cell for our use
1134 if (purb1->completion != NULL)
1135 {
1136 purb1->ctrl_req_context.ctrl_stack_count = 1;
1137 purb1->ctrl_req_context.ctrl_cur_stack = 0;
1138 }
1139 else
1140 {
1141 // use urb's completion and context
1142 purb1->completion = usb_set_interface_completion;
1143 purb1->context = pdev;
1144 }
1145 }
1146 else
1147 {
1148 if (purb->ctrl_req_context.ctrl_cur_stack + 1 >= purb->ctrl_req_context.ctrl_stack_count)
1149 {
1150 // stack full, let's allocate one new urb, we need stack size one
1151 purb1 = usb_alloc_mem(NonPagedPool, sizeof(URB));
1152 if (purb1 == NULL)
1153 return STATUS_NO_MEMORY;
1154
1155 RtlCopyMemory(purb1, purb, sizeof(URB));
1156
1157 // we do not use stack
1158 RtlZeroMemory(purb1->ctrl_req_stack, sizeof(CTRL_REQ_STACK));
1159 purb1->context = pdev;
1160 purb1->completion = usb_set_interface_completion;
1161 purb1->ctrl_parent_urb = purb;
1162 purb1->ctrl_req_context.ctrl_req_flags = CTRL_PARENT_URB_VALID;
1163
1164 goto LBL_SEND_URB;
1165 }
1166 else
1167 purb->ctrl_req_context.ctrl_cur_stack++;
1168 }
1169
1170 u = purb1->ctrl_req_context.ctrl_cur_stack;
1171 RtlZeroMemory(&purb1->ctrl_req_stack[u], sizeof(CTRL_REQ_STACK));
1172 pstack = &purb1->ctrl_req_stack[u];
1173 pstack->context = pdev;
1174 pstack->urb_completion = usb_set_interface_completion;
1175
1176 LBL_SEND_URB:
1177 if (hcd == NULL)
1178 return STATUS_INVALID_PARAMETER;
1179
1180 status = hcd->hcd_submit_urb(hcd, purb->pdev, purb->pendp, purb);
1181 return status;
1182 }
1183
1184 #define usb_complete_and_free_ctrl_urb( pURB ) \
1185 {\
1186 UCHAR i, j;\
1187 i = pURB->ctrl_req_context.ctrl_cur_stack;\
1188 j = pURB->ctrl_req_context.ctrl_stack_count;\
1189 usb_call_ctrl_completion( pURB );\
1190 if( i == 0xff || j == 0 )\
1191 usb_free_mem( pURB );\
1192 }
1193
1194 VOID
1195 usb_set_interface_completion(PURB purb, PVOID context)
1196 {
1197 PUSB_CTRL_SETUP_PACKET psetup;
1198 PUSB_INTERFACE pif, palt_if;
1199 USB_INTERFACE temp_if;
1200 UCHAR if_idx, if_alt_idx;
1201 PUSB_DEV pdev;
1202 PUSB_ENDPOINT pendp;
1203 ULONG i;
1204 PLIST_ENTRY pthis, pnext;
1205
1206 USE_BASIC_NON_PENDING_IRQL;
1207
1208 UNREFERENCED_PARAMETER(context);
1209
1210 if (purb == NULL)
1211 return;
1212
1213 if (purb->status == STATUS_SUCCESS)
1214 {
1215 psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
1216 if_idx = (UCHAR) psetup->wIndex;
1217 if_alt_idx = (UCHAR) psetup->wValue;
1218 pdev = purb->pdev;
1219 RtlZeroMemory(&temp_if, sizeof(USB_INTERFACE));
1220
1221 lock_dev(pdev, TRUE);
1222 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
1223 {
1224 unlock_dev(pdev, TRUE);
1225 purb->status = STATUS_DEVICE_NOT_CONNECTED;
1226 purb->data_length = 0;
1227 }
1228 else
1229 {
1230 // let's swap the interface
1231 pif = &pdev->usb_config->interf[if_idx];
1232 ListFirst(&pif->altif_list, pthis);
1233 pnext = pthis;
1234 do
1235 {
1236 palt_if = struct_ptr(pthis, USB_INTERFACE, altif_list);
1237 if (palt_if->pusb_if_desc->bAlternateSetting == if_alt_idx)
1238 {
1239 break;
1240 }
1241 palt_if = NULL;
1242 ListNext(&pif->altif_list, pthis, pnext);
1243 pthis = pnext;
1244
1245 } while (pthis);
1246
1247 if (palt_if != NULL)
1248 {
1249 RtlCopyMemory(&temp_if, palt_if, sizeof(USB_INTERFACE));
1250
1251 palt_if->endp_count = pif->endp_count;
1252 RtlCopyMemory(palt_if->endp, pif->endp, sizeof(pif->endp));
1253 palt_if->pif_drv = pif->pif_drv;
1254 palt_if->pusb_if_desc = pif->pusb_if_desc;
1255 for(i = 0; i < palt_if->endp_count; i++)
1256 {
1257 pendp = &palt_if->endp[i];
1258 InitializeListHead(&pendp->urb_list);
1259 pendp->flags = 0;
1260 }
1261
1262 RtlCopyMemory(pif->endp, temp_if.endp, sizeof(temp_if.endp));
1263 pif->endp_count = temp_if.endp_count;
1264 pif->pusb_if_desc = temp_if.pusb_if_desc;
1265 for(i = 0; i < pif->endp_count; i++)
1266 {
1267 pendp = &pif->endp[i];
1268 InitializeListHead(&pendp->urb_list);
1269 pendp->flags = 0;
1270 }
1271 }
1272 else
1273 {
1274 TRAP();
1275 purb->status = STATUS_UNSUCCESSFUL;
1276 }
1277 }
1278 unlock_dev(pdev, TRUE);
1279 }
1280
1281 // for recursive reason, we have to store the parameter ahead
1282 usb_complete_and_free_ctrl_urb(purb);
1283 }
1284
1285 // can only be called when current completion finished and called only in
1286 // urb completion. And this func may be called recursively, if this routine
1287 // is called, the urb must be treated as released.
1288 VOID
1289 usb_call_ctrl_completion(PURB purb)
1290 {
1291 PURB parent_urb;
1292 PCTRL_REQ_STACK pstack;
1293 ULONG i;
1294
1295
1296 if (purb == NULL)
1297 return;
1298
1299 if (purb->ctrl_req_context.ctrl_stack_count != 0)
1300 {
1301 i = purb->ctrl_req_context.ctrl_cur_stack;
1302 if (i > 0 && i < 0x10)
1303 {
1304 i--;
1305 purb->ctrl_req_context.ctrl_cur_stack = (UCHAR) i;
1306 pstack = &purb->ctrl_req_stack[i];
1307 if (pstack->urb_completion)
1308 {
1309 pstack->urb_completion(purb, pstack->context);
1310 }
1311 else
1312 TRAP();
1313 }
1314 else if (i == 0)
1315 {
1316 i = purb->ctrl_req_context.ctrl_cur_stack = 0xff;
1317 if (purb->completion)
1318 {
1319 purb->completion(purb, purb->context);
1320 }
1321 else
1322 TRAP();
1323 }
1324 else if (i == 0xff)
1325 {
1326 // only parent urb's completion, if parent urb exists, can be called
1327 if (purb->ctrl_req_context.ctrl_req_flags & CTRL_PARENT_URB_VALID)
1328 {
1329 parent_urb = purb->ctrl_parent_urb;
1330 if (parent_urb)
1331 {
1332 pstack = &parent_urb->ctrl_req_stack[parent_urb->ctrl_req_context.ctrl_cur_stack];
1333 pstack->urb_completion(parent_urb, pstack->context);
1334 }
1335 else
1336 TRAP();
1337 }
1338 }
1339 else
1340 TRAP();
1341 }
1342 else if (purb->ctrl_req_context.ctrl_req_flags & CTRL_PARENT_URB_VALID)
1343 {
1344 // this is the case when the child urb won't use the stack
1345 parent_urb = purb->ctrl_parent_urb;
1346 if (parent_urb)
1347 {
1348 // pstack = &parent_urb->ctrl_req_stack[ parent_urb->ctrl_req_context.ctrl_cur_stack ];
1349 // pstack->urb_completion( parent_urb, pstack->context );
1350 usb_call_ctrl_completion(parent_urb);
1351 }
1352 else
1353 TRAP();
1354 }
1355 else
1356 return;
1357 }