The real, definitive, Visual C++ support branch. Accept no substitutes
[reactos.git] / drivers / usb / nt4compat / usbdriver / devmgr.c
1 /**
2 * devmgr.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 #define realloc_buf( pdEV, puRB ) \
25 {\
26 PBYTE data_buf;\
27 int i;\
28 data_buf = usb_alloc_mem( NonPagedPool, ( pdEV )->desc_buf_size += 1024 );\
29 RtlZeroMemory( data_buf, ( pdEV )->desc_buf_size );\
30 for( i = 0; i < ( LONG )( puRB )->context; i++ )\
31 {\
32 data_buf[ i ] = ( pdEV )->desc_buf[ i ];\
33 }\
34 usb_free_mem( ( pdEV )->desc_buf );\
35 ( pdEV )->desc_buf = data_buf;\
36 ( pdEV )->pusb_dev_desc = ( PUSB_DEVICE_DESC )( pdEV )->desc_buf;\
37 ( puRB )->data_buffer = &data_buf[ ( LONG ) ( puRB )->context ];\
38 }
39
40
41 //----------------------------------------------------------
42
43 USB_DRIVER g_driver_list[DEVMGR_MAX_DRIVERS];
44 USB_DEV_MANAGER g_dev_mgr;
45
46
47 //----------------------------------------------------------
48 BOOLEAN
49 dev_mgr_set_if_driver(PUSB_DEV_MANAGER dev_mgr,
50 DEV_HANDLE if_handle,
51 PUSB_DRIVER pdriver,
52 PUSB_DEV pdev //if pdev != NULL, we use pdev instead if_handle, and must have dev_lock acquired.
53 )
54 {
55 ULONG i;
56 USE_BASIC_NON_PENDING_IRQL;
57
58 if (dev_mgr == NULL || if_handle == 0 || pdriver == NULL)
59 return FALSE;
60
61 i = if_idx_from_handle(if_handle);
62 if (pdev != NULL)
63 {
64 if (dev_state(pdev) < USB_DEV_STATE_BEFORE_ZOMB)
65 {
66 pdev->usb_config->interf[i].pif_drv = pdriver;
67 return TRUE;
68 }
69 return FALSE;
70 }
71
72 if (usb_query_and_lock_dev(dev_mgr, if_handle, &pdev) != STATUS_SUCCESS)
73 return FALSE;
74
75 lock_dev(pdev, TRUE);
76 if (dev_state(pdev) != USB_DEV_STATE_ZOMB)
77 {
78 pdev->usb_config->interf[i].pif_drv = pdriver;
79 }
80 unlock_dev(pdev, TRUE);
81 usb_unlock_dev(pdev);
82 return TRUE;
83 }
84
85 BOOLEAN
86 dev_mgr_set_driver(PUSB_DEV_MANAGER dev_mgr,
87 DEV_HANDLE dev_handle,
88 PUSB_DRIVER pdriver,
89 PUSB_DEV pdev //if pdev != NULL, we use pdev instead if_handle
90 )
91 {
92 USE_BASIC_NON_PENDING_IRQL;
93
94 if (dev_mgr == NULL || dev_handle == 0 || pdriver == NULL)
95 return FALSE;
96
97 if (pdev != NULL)
98 {
99 if (dev_state(pdev) < USB_DEV_STATE_BEFORE_ZOMB)
100 {
101 pdev->dev_driver = pdriver;
102 return TRUE;
103 }
104 return FALSE;
105 }
106
107 if (usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev) != STATUS_SUCCESS)
108 return FALSE;
109
110 lock_dev(pdev, FALSE);
111 if (dev_state(pdev) < USB_DEV_STATE_BEFORE_ZOMB)
112 {
113 pdev->dev_driver = pdriver;
114 }
115 unlock_dev(pdev, FALSE);
116 usb_unlock_dev(pdev);
117
118 return TRUE;
119 }
120
121 BOOLEAN
122 dev_mgr_post_event(PUSB_DEV_MANAGER dev_mgr, PUSB_EVENT event)
123 {
124 KIRQL old_irql;
125
126 if (dev_mgr == NULL || event == NULL)
127 return FALSE;
128
129 KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql);
130 InsertTailList(&dev_mgr->event_list, &event->event_link);
131 KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
132
133 KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE);
134 return TRUE;
135 }
136
137 VOID
138 dev_mgr_driver_entry_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdrvr)
139 {
140 // Device Info
141
142 RtlZeroMemory(pdrvr, sizeof(USB_DRIVER) * DEVMGR_MAX_DRIVERS);
143
144 pdrvr[RH_DRIVER_IDX].driver_init = rh_driver_init; // in fact, this routine will init the rh device rather that the driver struct.
145 pdrvr[RH_DRIVER_IDX].driver_destroy = rh_driver_destroy; // we do not need rh to destroy currently, since that may means fatal hardware failure
146
147 pdrvr[HUB_DRIVER_IDX].driver_init = hub_driver_init; //no need, since dev_mgr is also a hub driver
148 pdrvr[HUB_DRIVER_IDX].driver_destroy = hub_driver_destroy;
149
150 pdrvr[UMSS_DRIVER_IDX].driver_init = umss_if_driver_init;
151 pdrvr[UMSS_DRIVER_IDX].driver_destroy = umss_if_driver_destroy;
152
153 pdrvr[COMP_DRIVER_IDX].driver_init = compdev_driver_init;
154 pdrvr[COMP_DRIVER_IDX].driver_destroy = compdev_driver_destroy;
155
156 pdrvr[GEN_DRIVER_IDX].driver_init = gendrv_driver_init;
157 pdrvr[GEN_DRIVER_IDX].driver_destroy = gendrv_driver_destroy;
158
159 pdrvr[GEN_IF_DRIVER_IDX].driver_init = gendrv_if_driver_init;
160 pdrvr[GEN_IF_DRIVER_IDX].driver_destroy = gendrv_if_driver_destroy;
161
162 pdrvr[MOUSE_DRIVER_IDX].driver_init = mouse_driver_init;
163 pdrvr[MOUSE_DRIVER_IDX].driver_destroy = mouse_driver_destroy;
164
165 //pdrvr[KEYBOARD_DRIVER_IDX].driver_init = gendrv_if_driver_init;
166 //pdrvr[KEYBOARD_DRIVER_IDX].driver_destroy = gendrv_if_driver_destroy;
167 }
168
169 BOOLEAN
170 dev_mgr_strobe(PUSB_DEV_MANAGER dev_mgr)
171 {
172 PUSB_EVENT pevent;
173 HANDLE thread_handle;
174
175 if (dev_mgr == NULL)
176 return FALSE;
177 if (dev_mgr->hcd_count == 0)
178 return FALSE;
179
180 dev_mgr->term_flag = FALSE;
181
182 if (dev_mgr->hcd_count == 0)
183 return FALSE;
184
185 KeInitializeSpinLock(&dev_mgr->event_list_lock);
186 InitializeListHead(&dev_mgr->event_list);
187 init_event_pool(&dev_mgr->event_pool);
188
189 pevent = alloc_event(&dev_mgr->event_pool, 1);
190 if (pevent == NULL)
191 {
192 destroy_event_pool(&dev_mgr->event_pool);
193 return FALSE;
194 }
195
196 pevent->flags = USB_EVENT_FLAG_ACTIVE;
197 pevent->event = USB_EVENT_INIT_DEV_MGR;
198
199 pevent->process_queue = event_list_default_process_queue;
200 pevent->process_event = (PROCESS_EVENT)dev_mgr_event_init;
201
202 pevent->context = (ULONG) dev_mgr;
203
204 KeInitializeEvent(&dev_mgr->wake_up_event, SynchronizationEvent, FALSE);
205
206 InsertTailList(&dev_mgr->event_list, &pevent->event_link);
207
208 if (PsCreateSystemThread(&thread_handle, 0, NULL, NULL, NULL, dev_mgr_thread, dev_mgr) != STATUS_SUCCESS)
209 {
210 destroy_event_pool(&dev_mgr->event_pool);
211 return FALSE;
212 }
213
214 ObReferenceObjectByHandle(thread_handle,
215 THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID *) & dev_mgr->pthread, NULL);
216
217 ZwClose(thread_handle);
218
219 return TRUE;
220 }
221
222 BOOLEAN
223 dev_mgr_event_init(PUSB_DEV pdev, //always null. we do not use this param
224 ULONG event, ULONG context, ULONG param)
225 {
226 LARGE_INTEGER due_time;
227 PUSB_DEV_MANAGER dev_mgr;
228 LONG i;
229
230 usb_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_event_init(): dev_mgr=0x%x, event=0x%x\n", context, event));
231 dev_mgr = (PUSB_DEV_MANAGER) context;
232 if (dev_mgr == NULL)
233 return FALSE;
234
235 if (event != USB_EVENT_INIT_DEV_MGR)
236 return FALSE;
237
238 //dev_mgr->root_hub = NULL;
239 KeInitializeTimer(&dev_mgr->dev_mgr_timer);
240
241 KeInitializeDpc(&dev_mgr->dev_mgr_timer_dpc, dev_mgr_timer_dpc_callback, (PVOID) dev_mgr);
242
243 KeInitializeSpinLock(&dev_mgr->timer_svc_list_lock);
244 InitializeListHead(&dev_mgr->timer_svc_list);
245 init_timer_svc_pool(&dev_mgr->timer_svc_pool);
246 dev_mgr->timer_click = 0;
247
248 init_irp_list(&dev_mgr->irp_list);
249
250 KeInitializeSpinLock(&dev_mgr->dev_list_lock);
251 InitializeListHead(&dev_mgr->dev_list);
252
253 dev_mgr->hub_count = 0;
254 InitializeListHead(&dev_mgr->hub_list);
255
256 dev_mgr->conn_count = 0;
257 dev_mgr->driver_list = g_driver_list;
258
259 dev_mgr_driver_entry_init(dev_mgr, dev_mgr->driver_list);
260
261 for(i = 0; i < DEVMGR_MAX_DRIVERS; i++)
262 {
263 if (dev_mgr->driver_list[i].driver_init == NULL)
264 continue;
265
266 if (dev_mgr->driver_list[i].driver_init(dev_mgr, &dev_mgr->driver_list[i]) == FALSE)
267 break;
268 }
269 if (i == DEVMGR_MAX_DRIVERS)
270 {
271 due_time.QuadPart = -(DEV_MGR_TIMER_INTERVAL_NS - 10);
272
273 KeSetTimerEx(&dev_mgr->dev_mgr_timer,
274 due_time, DEV_MGR_TIMER_INTERVAL_MS, &dev_mgr->dev_mgr_timer_dpc);
275
276 return TRUE;
277 }
278
279 i--;
280
281 for(; i >= 0; i--)
282 {
283 if (dev_mgr->driver_list[i].driver_destroy)
284 dev_mgr->driver_list[i].driver_destroy(dev_mgr, &dev_mgr->driver_list[i]);
285 }
286
287 KeCancelTimer(&dev_mgr->dev_mgr_timer);
288 KeRemoveQueueDpc(&dev_mgr->dev_mgr_timer_dpc);
289 return FALSE;
290
291 }
292
293 VOID
294 dev_mgr_destroy(PUSB_DEV_MANAGER dev_mgr)
295 {
296 LONG i;
297 // oops...
298 KeCancelTimer(&dev_mgr->dev_mgr_timer);
299 KeRemoveQueueDpc(&dev_mgr->dev_mgr_timer_dpc);
300
301 for(i = DEVMGR_MAX_DRIVERS - 1; i >= 0; i--)
302 dev_mgr->driver_list[i].driver_destroy(dev_mgr, &dev_mgr->driver_list[i]);
303
304 destroy_irp_list(&dev_mgr->irp_list);
305 destroy_timer_svc_pool(&dev_mgr->timer_svc_pool);
306 destroy_event_pool(&dev_mgr->event_pool);
307
308 }
309
310 VOID
311 NTAPI
312 dev_mgr_thread(PVOID context)
313 {
314 PUSB_DEV_MANAGER dev_mgr;
315 PUSB_EVENT pevent;
316 PLIST_ENTRY pthis, pnext;
317 USB_EVENT usb_event;
318 LARGE_INTEGER time_out;
319 NTSTATUS status;
320 BOOLEAN dev_mgr_inited;
321 KIRQL old_irql;
322 LONG i;
323
324 dev_mgr = (PUSB_DEV_MANAGER) context;
325 dev_mgr_inited = FALSE;
326 usb_cal_cpu_freq();
327 time_out.u.LowPart = (10 * 1000 * 1000) * 100 - 1; //1 minutes
328 time_out.u.HighPart = 0;
329 time_out.QuadPart = -time_out.QuadPart;
330
331 //usb_dbg_print( DBGLVL_MAXIMUM + 1, ( "dev_mgr_thread(): current uhci status=0x%x\n", uhci_status( dev_mgr->pdev_ext->uhci ) ) );
332
333 while (dev_mgr->term_flag == FALSE)
334 {
335 KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql);
336 if (IsListEmpty(&dev_mgr->event_list) == TRUE)
337 {
338 KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
339 status = KeWaitForSingleObject(&dev_mgr->wake_up_event, Executive, KernelMode, TRUE, &time_out);
340 continue;
341 }
342
343 /*
344 usb_dbg_print( DBGLVL_MAXIMUM, ( "dev_mgr_thread(): current element in event list is 0x%x\n", \
345 dbg_count_list( &dev_mgr->event_list ) ) ); */
346
347 dev_mgr_inited = TRUE; //since we have post one event, if this statement is executed, dev_mgr_event_init must be called sometime later or earlier
348
349 ListFirst(&dev_mgr->event_list, pthis);
350 pevent = struct_ptr(pthis, USB_EVENT, event_link);
351
352 while (pevent && ((pevent->flags & USB_EVENT_FLAG_ACTIVE) == 0))
353 {
354 //skip inactive ones
355 ListNext(&dev_mgr->event_list, &pevent->event_link, pnext);
356 pevent = struct_ptr(pnext, USB_EVENT, event_link);
357 }
358
359 if (pevent != NULL)
360 {
361 if (pevent->process_queue == NULL)
362 pevent->process_queue = event_list_default_process_queue;
363
364 pevent->process_queue(&dev_mgr->event_list, &dev_mgr->event_pool, pevent, &usb_event);
365 }
366 else
367 {
368 //no active event
369 KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
370 status = KeWaitForSingleObject(&dev_mgr->wake_up_event, Executive, KernelMode, TRUE, &time_out // 10 minutes
371 );
372
373 usb_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_thread(): wake up, reason=0x%x\n", status));
374 continue;
375 }
376
377 KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
378
379 if (usb_event.process_event)
380 {
381 usb_event.process_event(usb_event.pdev, usb_event.event, usb_event.context, usb_event.param);
382 }
383 else
384 {
385 event_list_default_process_event(usb_event.pdev,
386 usb_event.event, usb_event.context, usb_event.param);
387 }
388 }
389
390 if (dev_mgr_inited)
391 {
392 for(i = 0; i < dev_mgr->hcd_count; i++)
393 dev_mgr_disconnect_dev(dev_mgr->hcd_array[i]->hcd_get_root_hub(dev_mgr->hcd_array[i]));
394 dev_mgr_destroy(dev_mgr);
395 }
396 PsTerminateSystemThread(0);
397 }
398
399 VOID
400 NTAPI
401 dev_mgr_timer_dpc_callback(PKDPC Dpc, PVOID context, PVOID SystemArgument1, PVOID SystemArgument2)
402 {
403 PUSB_DEV_MANAGER dev_mgr;
404 LIST_HEAD templist;
405 PLIST_ENTRY pthis, pnext;
406 static ULONG ticks = 0;
407
408 ticks++;
409 dev_mgr = (PUSB_DEV_MANAGER) context;
410 if (dev_mgr == NULL)
411 return;
412
413 dev_mgr->timer_click++;
414 InitializeListHead(&templist);
415
416 KeAcquireSpinLockAtDpcLevel(&dev_mgr->timer_svc_list_lock);
417 if (IsListEmpty(&dev_mgr->timer_svc_list) == TRUE)
418 {
419 KeReleaseSpinLockFromDpcLevel(&dev_mgr->timer_svc_list_lock);
420 return;
421 }
422
423 ListFirst(&dev_mgr->timer_svc_list, pthis);
424 while (pthis)
425 {
426 ((PTIMER_SVC) pthis)->counter++;
427 ListNext(&dev_mgr->timer_svc_list, pthis, pnext);
428 if (((PTIMER_SVC) pthis)->counter >= ((PTIMER_SVC) pthis)->threshold)
429 {
430 RemoveEntryList(pthis);
431 InsertTailList(&templist, pthis);
432 }
433 pthis = pnext;
434 }
435
436 KeReleaseSpinLockFromDpcLevel(&dev_mgr->timer_svc_list_lock);
437
438
439 while (IsListEmpty(&templist) == FALSE)
440 {
441 pthis = RemoveHeadList(&templist);
442 ((PTIMER_SVC) pthis)->func(((PTIMER_SVC) pthis)->pdev, (PVOID) ((PTIMER_SVC) pthis)->context);
443 KeAcquireSpinLockAtDpcLevel(&dev_mgr->timer_svc_list_lock);
444 free_timer_svc(&dev_mgr->timer_svc_pool, (PTIMER_SVC) pthis);
445 KeReleaseSpinLockFromDpcLevel(&dev_mgr->timer_svc_list_lock);
446 }
447
448 }
449
450 BOOLEAN
451 dev_mgr_request_timer_svc(PUSB_DEV_MANAGER dev_mgr,
452 PUSB_DEV pdev, ULONG context, ULONG due_time, TIMER_SVC_HANDLER handler)
453 {
454 PTIMER_SVC timer_svc;
455 KIRQL old_irql;
456
457 if (dev_mgr == NULL || pdev == NULL || due_time == 0 || handler == NULL)
458 return FALSE;
459
460 KeAcquireSpinLock(&dev_mgr->timer_svc_list_lock, &old_irql);
461 timer_svc = alloc_timer_svc(&dev_mgr->timer_svc_pool, 1);
462 if (timer_svc == NULL)
463 {
464 KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql);
465 return FALSE;
466 }
467 timer_svc->pdev = pdev;
468 timer_svc->threshold = due_time;
469 timer_svc->func = handler;
470 timer_svc->counter = 0;
471
472 InsertTailList(&dev_mgr->timer_svc_list, &timer_svc->timer_svc_link);
473 KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql);
474 return TRUE;
475 }
476
477 BYTE
478 dev_mgr_alloc_addr(PUSB_DEV_MANAGER dev_mgr, PHCD hcd)
479 {
480 // alloc a usb addr for the device within 1-128
481 if (dev_mgr == NULL || hcd == NULL)
482 return 0xff;
483
484 return hcd->hcd_alloc_addr(hcd);
485 }
486
487 BOOLEAN
488 dev_mgr_free_addr(PUSB_DEV_MANAGER dev_mgr, PUSB_DEV pdev, BYTE addr)
489 {
490 PHCD hcd;
491 if (addr & 0x80)
492 return FALSE;
493
494 if (dev_mgr == NULL || pdev == NULL)
495 return FALSE;
496
497 hcd = pdev->hcd;
498 if (hcd == NULL)
499 return FALSE;
500 hcd->hcd_free_addr(hcd, addr);
501 return TRUE;
502 }
503
504 PUSB_DEV
505 dev_mgr_alloc_device(PUSB_DEV_MANAGER dev_mgr, PHCD hcd)
506 {
507 BYTE addr;
508 PUSB_DEV pdev;
509
510 if ((addr = dev_mgr_alloc_addr(dev_mgr, hcd)) == 0xff)
511 return NULL;
512
513 pdev = usb_alloc_mem(NonPagedPool, sizeof(USB_DEV));
514 if (pdev == NULL)
515 return NULL;
516
517 RtlZeroMemory(pdev, sizeof(USB_DEV));
518
519 KeInitializeSpinLock(&pdev->dev_lock);
520 dev_mgr->conn_count++;
521
522 pdev->flags = USB_DEV_STATE_RESET; //class | cur_state | low speed
523 pdev->ref_count = 0;
524 pdev->dev_addr = addr;
525
526 pdev->hcd = hcd;
527
528 pdev->dev_id = dev_mgr->conn_count; //will be used to compose dev_handle
529
530 InitializeListHead(&pdev->default_endp.urb_list);
531 pdev->default_endp.pusb_if = (PUSB_INTERFACE) pdev;
532 pdev->default_endp.flags = USB_ENDP_FLAG_DEFAULT_ENDP; //toggle | busy-count | stall | default-endp
533
534 return pdev;
535 }
536
537 VOID
538 dev_mgr_free_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DEV pdev)
539 {
540 if (pdev == NULL || dev_mgr == NULL)
541 return;
542
543 dev_mgr_free_addr(dev_mgr, pdev, pdev->dev_addr);
544 if (pdev->usb_config && pdev != pdev->hcd->hcd_get_root_hub(pdev->hcd))
545 {
546 //root hub has its config and desc buf allocated together,
547 //so no usb_config allocated seperately
548 dev_mgr_destroy_usb_config(pdev->usb_config);
549 pdev->usb_config = NULL;
550 }
551 if (pdev->desc_buf)
552 {
553 usb_free_mem(pdev->desc_buf);
554 pdev->desc_buf = NULL;
555 }
556 usb_free_mem(pdev);
557 pdev = NULL;
558 return;
559 }
560
561 //called when a disconnect is detected on the port
562 VOID
563 dev_mgr_disconnect_dev(PUSB_DEV pdev)
564 {
565 PLIST_ENTRY pthis, pnext;
566 PHUB2_EXTENSION phub_ext = NULL;
567 PUSB_CONFIGURATION pconfig;
568 PUSB_DEV_MANAGER dev_mgr;
569 PHCD hcd;
570 BOOLEAN is_hub, found;
571 ULONG dev_id;
572 int i;
573
574 USE_NON_PENDING_IRQL;
575
576 if (pdev == NULL)
577 return;
578
579 found = FALSE;
580
581 usb_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_disconnect_dev(): entering, pdev=0x%x\n", pdev));
582 lock_dev(pdev, FALSE);
583 pdev->flags &= ~USB_DEV_STATE_MASK;
584 pdev->flags |= USB_DEV_STATE_BEFORE_ZOMB;
585 dev_mgr = dev_mgr_from_dev(pdev);
586 unlock_dev(pdev, FALSE);
587
588 // notify dev_driver that the dev stops function before any operations
589 if (pdev->dev_driver && pdev->dev_driver->disp_tbl.dev_stop)
590 pdev->dev_driver->disp_tbl.dev_stop(dev_mgr, dev_handle_from_dev(pdev));
591
592 //safe to use the dev pointer in this function.
593 lock_dev(pdev, FALSE);
594 pdev->flags &= ~USB_DEV_STATE_MASK;
595 pdev->flags |= USB_DEV_STATE_ZOMB;
596 hcd = pdev->hcd;
597 dev_id = pdev->dev_id;
598 unlock_dev(pdev, FALSE);
599
600 if (dev_mgr == NULL)
601 return;
602
603 hcd->hcd_remove_device(hcd, pdev);
604
605 //disconnect its children
606 if ((pdev->flags & USB_DEV_CLASS_MASK) == USB_DEV_CLASS_HUB ||
607 (pdev->flags & USB_DEV_CLASS_MASK) == USB_DEV_CLASS_ROOT_HUB)
608 {
609 phub_ext = hub_ext_from_dev(pdev);
610 if (phub_ext)
611 {
612 for(i = 1; i <= phub_ext->port_count; i++)
613 {
614 if (phub_ext->child_dev[i])
615 {
616 dev_mgr_disconnect_dev(phub_ext->child_dev[i]);
617 phub_ext->child_dev[i] = NULL;
618 }
619 }
620 }
621 }
622
623 pconfig = pdev->usb_config;
624
625 //remove event belong to the dev
626 is_hub = ((pdev->flags & USB_DEV_CLASS_MASK) == USB_DEV_CLASS_HUB);
627
628 if (phub_ext && is_hub)
629 {
630 for(i = 1; i <= phub_ext->port_count; i++)
631 {
632 found = hub_remove_reset_event(pdev, i, FALSE);
633 if (found)
634 break;
635 }
636 }
637
638 //free event of the dev from the event list
639 KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql);
640 ListFirst(&dev_mgr->event_list, pthis);
641 while (pthis)
642 {
643 ListNext(&dev_mgr->event_list, pthis, pnext);
644 if (((PUSB_EVENT) pthis)->pdev == pdev)
645 {
646 PLIST_ENTRY p1;
647 RemoveEntryList(pthis);
648 if ((((PUSB_EVENT) pthis)->flags & USB_EVENT_FLAG_QUE_TYPE) != USB_EVENT_FLAG_NOQUE)
649 {
650 //has a queue, re-insert the queue
651 if ((p1 = (PLIST_ENTRY) ((PUSB_EVENT) pthis)->pnext))
652 {
653 InsertHeadList(&dev_mgr->event_list, p1);
654 free_event(&dev_mgr->event_pool, struct_ptr(pthis, USB_EVENT, event_link));
655 pthis = p1;
656 //note: this queue will be examined again in the next loop
657 //to find the matched dev in the queue
658 continue;
659 }
660 }
661 free_event(&dev_mgr->event_pool, struct_ptr(pthis, USB_EVENT, event_link));
662 }
663 else if (((((PUSB_EVENT) pthis)->flags & USB_EVENT_FLAG_QUE_TYPE)
664 != USB_EVENT_FLAG_NOQUE) && ((PUSB_EVENT) pthis)->pnext)
665 {
666 //has a queue, examine the queue
667 PUSB_EVENT p1, p2;
668 p1 = (PUSB_EVENT) pthis;
669 p2 = p1->pnext;
670 while (p2)
671 {
672 if (p2->pdev == pdev)
673 {
674 p1->pnext = p2->pnext;
675 p2->pnext = NULL;
676 free_event(&dev_mgr->event_pool, p2);
677 p2 = p1->pnext;
678 }
679 else
680 {
681 p1 = p2;
682 p2 = p2->pnext;
683 }
684 }
685 }
686 pthis = pnext;
687 }
688 KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql);
689
690 // found indicates the reset event on one of the dev's port in process
691 if (found)
692 hub_start_next_reset_port(dev_mgr_from_dev(pdev), FALSE);
693
694 // remove timer-svc belonging to the dev
695 KeAcquireSpinLock(&dev_mgr->timer_svc_list_lock, &old_irql);
696 ListFirst(&dev_mgr->timer_svc_list, pthis);
697 i = 0;
698 while (pthis)
699 {
700 ListNext(&dev_mgr->timer_svc_list, pthis, pnext);
701 if (((PUSB_EVENT) pthis)->pdev == pdev)
702 {
703 RemoveEntryList(pthis);
704 free_timer_svc(&dev_mgr->timer_svc_pool, struct_ptr(pthis, TIMER_SVC, timer_svc_link));
705 i++;
706 }
707 pthis = pnext;
708 }
709 KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql);
710
711 // release the refcount
712 if (i)
713 {
714 lock_dev(pdev, FALSE);
715 pdev->ref_count -= i;
716 unlock_dev(pdev, FALSE);
717 }
718
719 // wait for all the reference count be released
720 for(;;)
721 {
722 LARGE_INTEGER interval;
723
724 lock_dev(pdev, FALSE);
725 if (pdev->ref_count == 0)
726 {
727 unlock_dev(pdev, FALSE);
728 break;
729 }
730 unlock_dev(pdev, FALSE);
731 // Wait two ms.
732 interval.QuadPart = -20000;
733 KeDelayExecutionThread(KernelMode, FALSE, &interval);
734 }
735
736 if (pdev->dev_driver && pdev->dev_driver->disp_tbl.dev_disconnect)
737 pdev->dev_driver->disp_tbl.dev_disconnect(dev_mgr, dev_handle_from_dev(pdev));
738
739 // we put it here to let handle valid before disconnect
740 KeAcquireSpinLock(&dev_mgr->dev_list_lock, &old_irql);
741 ListFirst(&dev_mgr->dev_list, pthis);
742 while (pthis)
743 {
744 if (((PUSB_DEV) pthis) == pdev)
745 {
746 RemoveEntryList(pthis);
747 break;
748 }
749 ListNext(&dev_mgr->dev_list, pthis, pnext);
750 pthis = pnext;
751 }
752 KeReleaseSpinLock(&dev_mgr->dev_list_lock, old_irql);
753
754
755 if (pdev != pdev->hcd->hcd_get_root_hub(pdev->hcd))
756 {
757 dev_mgr_free_device(dev_mgr, pdev);
758 }
759 else
760 {
761 //rh_destroy( pdev );
762 //TRAP();
763 //destroy it in dev_mgr_destroy
764 }
765
766 return;
767 }
768
769 //called in hub_set_address_completion
770 BOOLEAN
771 dev_mgr_start_config_dev(PUSB_DEV pdev)
772 {
773 PBYTE data_buf;
774 PUSB_CTRL_SETUP_PACKET psetup;
775 PURB purb;
776 PHCD hcd;
777 USE_BASIC_NON_PENDING_IRQL;
778
779 hcd_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_start_config_dev: pdev=%p\n", pdev));
780
781 if (pdev == NULL)
782 return FALSE;
783
784 lock_dev(pdev, TRUE);
785 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
786 {
787 unlock_dev(pdev, TRUE);
788 return FALSE;
789 }
790
791 hcd = pdev->hcd;
792
793 //first, get device descriptor
794 purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
795 data_buf = usb_alloc_mem(NonPagedPool, 512);
796 if (purb == NULL)
797 {
798 unlock_dev(pdev, TRUE);
799 return FALSE;
800 }
801
802 RtlZeroMemory(purb, sizeof(URB));
803 RtlZeroMemory(data_buf, 512);
804
805 psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
806
807 purb->data_buffer = data_buf; // user data
808 purb->data_length = 8; // get partial desc
809
810 pdev->desc_buf = data_buf;
811 pdev->desc_buf_size = 512;
812
813 purb->pdev = pdev;
814 purb->pendp = &pdev->default_endp; //pipe for current transfer
815
816 purb->completion = dev_mgr_get_desc_completion;
817 purb->reference = 0;
818
819 InitializeListHead(&purb->trasac_list);
820
821 psetup->bmRequestType = 0x80;
822 psetup->bRequest = USB_REQ_GET_DESCRIPTOR;
823 psetup->wValue = (USB_DT_DEVICE << 8) | 0;
824 psetup->wIndex = 0;
825 psetup->wLength = 8; //sizeof( USB_DEVICE_DESC );
826 unlock_dev(pdev, TRUE);
827
828 if (hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb) != STATUS_PENDING)
829 {
830 usb_free_mem(purb);
831 usb_free_mem(data_buf);
832 return FALSE;
833 }
834 return TRUE;
835 }
836
837 VOID
838 dev_mgr_get_desc_completion(PURB purb, PVOID context)
839 {
840 PUSB_DEV pdev;
841 PUSB_CONFIGURATION_DESC pconfig_desc;
842 PUSB_ENDPOINT pendp;
843 PUSB_DEV_MANAGER dev_mgr;
844 NTSTATUS status;
845 PUSB_CTRL_SETUP_PACKET psetup;
846 PHCD hcd;
847
848 USE_BASIC_NON_PENDING_IRQL;;
849
850 if (purb == NULL)
851 return;
852
853 hcd_dbg_print(DBGLVL_MAXIMUM,
854 ("dev_mgr_get_desc_completion: purb->reference=%d\n", purb->reference));
855
856 pdev = purb->pdev;
857 pendp = purb->pendp;
858
859 if (pdev == NULL || pendp == NULL)
860 {
861 usb_free_mem(purb);
862 purb = NULL;
863 return;
864 }
865
866 lock_dev(pdev, TRUE);
867 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
868 {
869 unlock_dev(pdev, TRUE);
870 goto LBL_OUT;
871 }
872
873 pendp = &pdev->default_endp;
874 dev_mgr = dev_mgr_from_dev(pdev);
875 hcd = pdev->hcd;
876 psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
877
878 if (usb_error(purb->status))
879 {
880 unlock_dev(pdev, TRUE);
881 hcd_dbg_print(DBGLVL_MAXIMUM,
882 ("dev_mgr_get_desc_completion: can not get dev desc ref=0x%x, status=0x%x\n",
883 purb->reference, purb->status));
884 goto LBL_OUT;
885 }
886
887 switch (purb->reference)
888 {
889 case 0:
890 {
891 //only partial dev_desc
892 //enable the dev specific default endp maxpacketsize
893 pdev->pusb_dev_desc = (PUSB_DEVICE_DESC) purb->data_buffer;
894
895 psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
896 psetup->wLength = sizeof(USB_DEVICE_DESC);
897
898 //get the complete dev_desc
899 purb->reference = 1;
900 purb->status = 0;
901 purb->data_length = sizeof(USB_DEVICE_DESC);
902
903 unlock_dev(pdev, TRUE);
904
905 status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb);
906 if (status != STATUS_PENDING)
907 {
908 goto LBL_OUT;
909 }
910 return;
911 }
912 case 1:
913 {
914 //let's begin to get config descriptors.
915 if (pdev->pusb_dev_desc->bNumConfigurations == 0)
916 {
917 unlock_dev(pdev, TRUE);
918 goto LBL_OUT;
919 }
920
921 purb->data_buffer += sizeof(USB_DEVICE_DESC);
922 purb->data_length = 8;
923 purb->reference++;
924 purb->context = (PVOID) sizeof(USB_DEVICE_DESC);
925 purb->status = 0;
926
927 psetup->wValue = (USB_DT_CONFIG << 8) | 0;
928 psetup->wLength = 8;
929 unlock_dev(pdev, TRUE);
930
931 status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb);
932
933 if (status != STATUS_PENDING)
934 {
935 goto LBL_OUT;
936 }
937 return;
938 }
939 default:
940 {
941 LONG config_idx;
942 config_idx = (purb->reference >> 1) - 1;
943 if ((purb->reference & 1) == 0)
944 {
945 //partial config desc is obtained.
946 pconfig_desc = (PUSB_CONFIGURATION_DESC) purb->data_buffer;
947 if (pconfig_desc->wTotalLength >= 1024)
948 {
949 //treat as an error
950 unlock_dev(pdev, TRUE);
951 goto LBL_OUT;
952
953 }
954
955 if (pconfig_desc->wTotalLength > (USHORT) (pdev->desc_buf_size - (LONG) purb->context))
956 {
957 //rewind the 8-byte hdr
958 *((PULONG) & context) -= 8;
959 realloc_buf(pdev, purb);
960 }
961 purb->data_length = pconfig_desc->wTotalLength;
962 psetup->wLength = pconfig_desc->wTotalLength;
963 purb->reference++;
964 unlock_dev(pdev, TRUE);
965 status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb);
966 if (status != STATUS_PENDING)
967 goto LBL_OUT;
968
969 }
970 else
971 {
972 //complete desc is returned.
973 if (config_idx + 1 < pdev->pusb_dev_desc->bNumConfigurations)
974 {
975 //still have configurations left
976 *((PULONG) & context) += psetup->wLength;
977 purb->data_buffer = &pdev->desc_buf[(LONG) context];
978 purb->data_length = 8;
979 psetup->wLength = 8;
980 psetup->wValue = (((USB_DT_CONFIG) << 8) | (config_idx + 1));
981 purb->reference++;
982 purb->context = context;
983
984 if (((LONG) context) + 8 > pdev->desc_buf_size)
985 realloc_buf(pdev, purb);
986
987 purb->status = 0;
988 unlock_dev(pdev, TRUE);
989 status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb);
990 if (status != STATUS_PENDING)
991 goto LBL_OUT;
992 }
993 else
994 {
995 //config descriptors have all been fetched
996 unlock_dev(pdev, TRUE);
997 usb_free_mem(purb);
998 purb = NULL;
999
1000 // load driver for the device
1001 dev_mgr_start_select_driver(pdev);
1002 }
1003 }
1004 return;
1005 }
1006 }
1007
1008 LBL_OUT:
1009 usb_free_mem(purb);
1010 purb = NULL;
1011
1012 lock_dev(pdev, TRUE);
1013 if (dev_state(pdev) != USB_DEV_STATE_ZOMB)
1014 {
1015 if (pdev->desc_buf)
1016 {
1017 usb_free_mem(pdev->desc_buf);
1018 pdev->desc_buf_size = 0;
1019 pdev->desc_buf = NULL;
1020 pdev->pusb_dev_desc = NULL;
1021 pdev->usb_config = NULL;
1022 }
1023 }
1024 unlock_dev(pdev, TRUE);
1025
1026 return;
1027 }
1028
1029 BOOLEAN
1030 dev_mgr_start_select_driver(PUSB_DEV pdev)
1031 {
1032 PUSB_DEV_MANAGER dev_mgr;
1033 PUSB_EVENT pevent;
1034 BOOLEAN bret;
1035
1036 USE_BASIC_NON_PENDING_IRQL;;
1037
1038 if (pdev == NULL)
1039 return FALSE;
1040
1041 dev_mgr = dev_mgr_from_dev(pdev);
1042 KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock);
1043 lock_dev(pdev, TRUE);
1044
1045 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
1046 {
1047 bret = FALSE;
1048 goto LBL_OUT;
1049 }
1050
1051 pevent = alloc_event(&dev_mgr->event_pool, 1);
1052 if (pevent == NULL)
1053 {
1054 bret = FALSE;
1055 goto LBL_OUT;
1056 }
1057 pevent->flags = USB_EVENT_FLAG_ACTIVE;
1058 pevent->event = USB_EVENT_DEFAULT;
1059 pevent->pdev = pdev;
1060 pevent->context = 0;
1061 pevent->param = 0;
1062 pevent->pnext = 0; //vertical queue for serialized operation
1063 pevent->process_event = dev_mgr_event_select_driver;
1064 pevent->process_queue = event_list_default_process_queue;
1065
1066 InsertTailList(&dev_mgr->event_list, &pevent->event_link);
1067 KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE);
1068 bret = TRUE;
1069
1070 LBL_OUT:
1071 unlock_dev(pdev, TRUE);
1072 KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
1073 return bret;
1074 }
1075
1076 BOOLEAN
1077 dev_mgr_connect_to_dev(PVOID Parameter)
1078 {
1079 PUSB_DEV pdev;
1080 DEV_HANDLE dev_handle;
1081 NTSTATUS status;
1082 PUSB_DRIVER pdriver;
1083 PDEV_CONNECT_DATA pcd = (PDEV_CONNECT_DATA) Parameter;
1084 PUSB_DEV_MANAGER dev_mgr;
1085 DEV_CONNECT_DATA param;
1086
1087 if (pcd == NULL)
1088 return FALSE;
1089 dev_handle = pcd->dev_handle;
1090 pdriver = pcd->pdriver;
1091 dev_mgr = pcd->dev_mgr;
1092
1093 param.dev_mgr = dev_mgr;
1094 param.pdriver = pdriver;
1095 param.dev_handle = 0; //not used
1096
1097 status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
1098 if (status != STATUS_SUCCESS)
1099 return FALSE;
1100
1101 usb_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_connect_to_dev(): about to call driver's dev_connect\n"));
1102 status = pdriver->disp_tbl.dev_connect(&param, dev_handle);
1103 usb_unlock_dev(pdev);
1104 return status;
1105 }
1106
1107 VOID
1108 dev_mgr_event_select_driver(PUSB_DEV pdev, ULONG event, ULONG context, ULONG param)
1109 {
1110 PUSB_DEV_MANAGER dev_mgr;
1111 PUSB_DRIVER pdriver, pcand;
1112 LONG credit, match, i;
1113 DEV_HANDLE handle = 0;
1114 DEV_CONNECT_DATA cd;
1115
1116 USE_BASIC_NON_PENDING_IRQL;
1117
1118 UNREFERENCED_PARAMETER(param);
1119 UNREFERENCED_PARAMETER(context);
1120
1121 usb_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_event_select_driver(): pdev=%p event=0x%x\n", pdev, event));
1122
1123 if (pdev == NULL)
1124 return;
1125
1126 lock_dev(pdev, FALSE);
1127 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
1128 {
1129 unlock_dev(pdev, FALSE);
1130 return;
1131 }
1132 dev_mgr = dev_mgr_from_dev(pdev);
1133
1134 pcand = NULL;
1135 match = 0;
1136 for(i = HUB_DRIVER_IDX; i < DEVMGR_MAX_DRIVERS; i++)
1137 {
1138 //bypass root-hub driver with idx zero
1139 pdriver = (PUSB_DRIVER) & dev_mgr->driver_list[i];
1140
1141 if (pdriver->driver_desc.flags & USB_DRIVER_FLAG_DEV_CAPABLE)
1142 credit = dev_mgr_score_driver_for_dev(dev_mgr, pdriver, pdev->pusb_dev_desc);
1143 else
1144 {
1145 continue;
1146 }
1147 if (credit > match)
1148 pcand = pdriver, match = credit;
1149
1150 }
1151
1152 if (match)
1153 {
1154 // we set class driver here
1155 // pdev->dev_driver = pcand;
1156 handle = usb_make_handle(pdev->dev_id, 0, 0);
1157 }
1158 unlock_dev(pdev, FALSE);
1159
1160 if (match)
1161 {
1162
1163 cd.dev_handle = handle;
1164 cd.pdriver = pcand;
1165 cd.dev_mgr = dev_mgr;
1166
1167 if (dev_mgr_connect_to_dev(&cd))
1168 return;
1169
1170 // ExInitializeWorkItem( pwork_item, dev_mgr_connect_to_dev, ( PVOID )pcd );
1171 // ExQueueWorkItem( pwork_item, DelayedWorkQueue );
1172 }
1173 cd.dev_handle = handle;
1174 cd.pdriver = &dev_mgr->driver_list[GEN_DRIVER_IDX];
1175 cd.dev_mgr = dev_mgr;
1176 dev_mgr_connect_to_dev(&cd);
1177 return;
1178 }
1179
1180 BOOLEAN
1181 dev_mgr_build_usb_endp(PUSB_INTERFACE pif, PUSB_ENDPOINT pendp, PUSB_ENDPOINT_DESC pendp_desc)
1182 {
1183 if (pendp == NULL || pif == NULL || pendp_desc == NULL)
1184 return FALSE;
1185
1186 pendp->flags = 0;
1187 InitializeListHead(&pendp->urb_list); //pending urb queue
1188 pendp->pusb_if = pif;
1189 pendp->pusb_endp_desc = pendp_desc;
1190 return TRUE;
1191 }
1192
1193 BOOLEAN
1194 dev_mgr_build_usb_if(PUSB_CONFIGURATION pcfg, PUSB_INTERFACE pif, PUSB_INTERFACE_DESC pif_desc, BOOLEAN alt_if)
1195 {
1196 LONG i;
1197 PUSB_ENDPOINT_DESC pendp_desc;
1198
1199 if (pcfg == NULL || pif == NULL || pif_desc == NULL)
1200 return FALSE;
1201
1202 if (alt_if == FALSE)
1203 {
1204 pif->endp_count = pif_desc->bNumEndpoints > MAX_ENDPS_PER_IF
1205 ? MAX_ENDPS_PER_IF : pif_desc->bNumEndpoints;
1206
1207 pif->pif_drv = NULL;
1208 pif->pusb_config = pcfg;
1209 pif->pusb_if_desc = pif_desc;
1210 pif->if_ext_size = 0;
1211 pif->if_ext = NULL;
1212
1213 InitializeListHead(&pif->altif_list);
1214 pif->altif_count = 0;
1215
1216 pendp_desc = (PUSB_ENDPOINT_DESC) (&((PBYTE) pif_desc)[sizeof(USB_INTERFACE_DESC)]);
1217
1218 for(i = 0; i < pif->endp_count; i++, pendp_desc++)
1219 {
1220 dev_mgr_build_usb_endp(pif, &pif->endp[i], pendp_desc);
1221 }
1222 }
1223 else
1224 {
1225 PUSB_INTERFACE paltif;
1226 PLIST_ENTRY pthis, pnext;
1227
1228 pif->altif_count++;
1229 paltif = usb_alloc_mem(NonPagedPool, sizeof(USB_INTERFACE));
1230 RtlZeroMemory(paltif, sizeof(USB_INTERFACE));
1231 InsertTailList(&pif->altif_list, &paltif->altif_list);
1232 paltif->pif_drv = NULL;
1233 paltif->pusb_config = pcfg;
1234 paltif->pusb_if_desc = pif_desc;
1235 paltif->if_ext_size = 0;
1236 paltif->if_ext = NULL;
1237 paltif->endp_count = pif_desc->bNumEndpoints > MAX_ENDPS_PER_IF
1238 ? MAX_ENDPS_PER_IF : pif_desc->bNumEndpoints;
1239
1240 ListFirst(&pif->altif_list, pthis);
1241
1242 while (pthis)
1243 {
1244 //synchronize the altif_count;
1245 PUSB_INTERFACE pthis_if;
1246 pthis_if = (PUSB_INTERFACE) (((PBYTE) pthis) - offsetof(USB_INTERFACE, altif_list));
1247 pthis_if->altif_count = pif->altif_count;
1248 ListNext(&pif->altif_list, pthis, pnext);
1249 }
1250
1251 }
1252 return TRUE;
1253 }
1254
1255 NTSTATUS
1256 dev_mgr_build_usb_config(PUSB_DEV pdev, PBYTE pbuf, ULONG config_val, LONG config_count)
1257 {
1258 PUSB_CONFIGURATION pcfg;
1259 PUSB_INTERFACE_DESC pif_desc;
1260 PUSB_INTERFACE pif;
1261 int i;
1262 LONG if_count;
1263
1264 if (pdev == NULL || pbuf == NULL)
1265 return STATUS_INVALID_PARAMETER;
1266
1267
1268 pdev->usb_config = usb_alloc_mem(NonPagedPool, sizeof(USB_CONFIGURATION));
1269 pcfg = pdev->usb_config;
1270
1271 if (pdev->usb_config == NULL)
1272 return STATUS_NO_MEMORY;
1273
1274 RtlZeroMemory(pcfg, sizeof(USB_CONFIGURATION));
1275 pcfg->pusb_config_desc = usb_find_config_desc_by_val(pbuf, config_val, config_count);
1276
1277 if (pcfg->pusb_config_desc == NULL)
1278 {
1279 usb_free_mem(pcfg);
1280 pdev->usb_config = NULL;
1281 return STATUS_UNSUCCESSFUL;
1282 }
1283 pcfg->if_count = pcfg->pusb_config_desc->bNumInterfaces;
1284 pcfg->pusb_dev = pdev;
1285 pif_desc = (PUSB_INTERFACE_DESC) & ((PBYTE) pcfg->pusb_config_desc)[sizeof(USB_CONFIGURATION_DESC)];
1286 if_count = pcfg->if_count;
1287
1288 for(i = 0; i < if_count; i++, pif_desc++)
1289 {
1290 if (pif_desc->bAlternateSetting == 0)
1291 {
1292 dev_mgr_build_usb_if(pcfg, &pcfg->interf[i], pif_desc, FALSE);
1293 }
1294 else
1295 {
1296 i--;
1297 pif = &pcfg->interf[i];
1298 dev_mgr_build_usb_if(pcfg, pif, pif_desc, TRUE);
1299 }
1300 }
1301 return STATUS_SUCCESS;
1302 }
1303
1304 NTSTATUS
1305 dev_mgr_destroy_usb_config(PUSB_CONFIGURATION pcfg)
1306 {
1307 long i;
1308 PLIST_ENTRY pthis;
1309 PUSB_INTERFACE pif;
1310
1311 if (pcfg == NULL)
1312 return FALSE;
1313
1314 for(i = 0; i < pcfg->if_count; i++)
1315 {
1316 pif = &pcfg->interf[i];
1317
1318 if (pif->altif_count)
1319 {
1320 ListFirst(&pif->altif_list, pthis);
1321 while (pthis)
1322 {
1323 PUSB_INTERFACE pthis_if;
1324 pthis_if = (PUSB_INTERFACE) (((PBYTE) pthis) - offsetof(USB_INTERFACE, altif_list));
1325 RemoveEntryList(pthis);
1326 usb_free_mem(pthis_if);
1327 if (IsListEmpty(&pif->altif_list) == TRUE)
1328 break;
1329
1330 ListFirst(&pif->altif_list, pthis);
1331 }
1332 }
1333 }
1334 usb_free_mem(pcfg);
1335 return TRUE;
1336 }
1337
1338 #define is_dev_product_match( pdriVER, pdev_DESC ) \
1339 ( ( pdriVER )->driver_desc.vendor_id == ( pdev_DESC )->idVendor \
1340 && ( pdriVER )->driver_desc.product_id == ( pdev_DESC )->idProduct )
1341
1342 LONG
1343 dev_mgr_score_driver_for_dev(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver, PUSB_DEVICE_DESC pdev_desc)
1344 {
1345 LONG credit = 0;
1346
1347 UNREFERENCED_PARAMETER(dev_mgr);
1348
1349 //assume supports all the sub_class are supported if sub_class is zero
1350 if (pdriver->driver_desc.dev_class == pdev_desc->bDeviceClass)
1351 {
1352 if (pdriver->driver_desc.dev_sub_class == 0 && pdriver->driver_desc.dev_protocol == 0)
1353 credit = 3;
1354 else if (pdriver->driver_desc.dev_sub_class == pdev_desc->bDeviceSubClass)
1355 {
1356 if (pdriver->driver_desc.dev_protocol == 0)
1357 credit = 6;
1358 else if (pdriver->driver_desc.dev_protocol == pdev_desc->bDeviceProtocol)
1359 credit = 9;
1360 }
1361 }
1362
1363 if (is_dev_product_match(pdriver, pdev_desc))
1364 credit += 20;
1365
1366 return credit;
1367 }
1368
1369 LONG
1370 dev_mgr_score_driver_for_if(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver, PUSB_INTERFACE_DESC pif_desc)
1371 {
1372 LONG credit;
1373
1374 if (pdriver == NULL
1375 || !(pdriver->driver_desc.flags & USB_DRIVER_FLAG_IF_CAPABLE) || pif_desc == NULL || dev_mgr == NULL)
1376 return 0;
1377
1378 if (is_header_match((PBYTE) pif_desc, USB_DT_INTERFACE) == FALSE)
1379 {
1380 return 0;
1381 }
1382
1383 credit = 0;
1384 if ((pdriver->driver_desc.if_class == pif_desc->bInterfaceClass))
1385 {
1386 if (pdriver->driver_desc.if_sub_class == 0 && pdriver->driver_desc.if_protocol == 0)
1387 credit = 2;
1388 if (pdriver->driver_desc.if_sub_class == pif_desc->bInterfaceSubClass)
1389 {
1390 if (pdriver->driver_desc.if_protocol == 0)
1391 credit = 4;
1392 if (pdriver->driver_desc.if_protocol == pif_desc->bInterfaceProtocol)
1393 credit = 6;
1394 }
1395 }
1396 else
1397 credit = 1;
1398
1399 return credit;
1400 }
1401
1402 #define is_equal_driver( pd1, pd2, ret ) \
1403 {\
1404 int i;\
1405 ret = TRUE;\
1406 PUSB_DRIVER pdr1, pdr2;\
1407 pdr1 = ( PUSB_DRIVER )( pd1 );\
1408 pdr2 = ( PUSB_DRIVER ) ( pd2 );\
1409 for( i = 0; i < 16; i++ )\
1410 {\
1411 if( pdr1->driver_name[ i ] != pdr2->driver_name[ i ] )\
1412 {\
1413 ret = FALSE;\
1414 break;\
1415 }\
1416 }\
1417 }
1418
1419 //return value is the hcd id
1420 UCHAR
1421 dev_mgr_register_hcd(PUSB_DEV_MANAGER dev_mgr, PHCD hcd)
1422 {
1423 if (dev_mgr == NULL || hcd == NULL)
1424 return 0xff;
1425
1426 if (dev_mgr->hcd_count >= MAX_HCDS)
1427 return 0xff;
1428
1429 dev_mgr->hcd_array[dev_mgr->hcd_count++] = hcd;
1430 return dev_mgr->hcd_count - 1;
1431 }
1432
1433 BOOLEAN
1434 dev_mgr_register_irp(PUSB_DEV_MANAGER dev_mgr, PIRP pirp, PURB purb)
1435 {
1436 if (dev_mgr == NULL)
1437 return FALSE;
1438
1439 if (add_irp_to_list(&dev_mgr->irp_list, pirp, purb))
1440 {
1441 return TRUE;
1442 }
1443 TRAP();
1444 return FALSE;
1445 }
1446
1447 //caller must guarantee that when this func is called,
1448 //the urb associated must exist.
1449 PURB
1450 dev_mgr_remove_irp(PUSB_DEV_MANAGER dev_mgr, PIRP pirp)
1451 {
1452 PURB purb;
1453 if (dev_mgr == NULL)
1454 return NULL;
1455
1456 purb = remove_irp_from_list(&dev_mgr->irp_list, pirp, NULL);
1457 return purb;
1458 }
1459
1460 VOID
1461 dev_mgr_cancel_irp(PDEVICE_OBJECT dev_obj, PIRP pirp)
1462 {
1463 PUSB_DEV_MANAGER dev_mgr;
1464 PDEVEXT_HEADER pdev_ext_hdr;
1465
1466 pdev_ext_hdr = (PDEVEXT_HEADER) dev_obj->DeviceExtension;
1467 dev_mgr = pdev_ext_hdr->dev_mgr;
1468
1469 if (dev_obj->CurrentIrp == pirp)
1470 {
1471 IoReleaseCancelSpinLock(pirp->CancelIrql);
1472 // we did not IoStartNextPacket, leave it for the urb completion
1473 }
1474 else
1475 {
1476 KeRemoveEntryDeviceQueue(&dev_obj->DeviceQueue, &pirp->Tail.Overlay.DeviceQueueEntry);
1477 IoReleaseCancelSpinLock(pirp->CancelIrql);
1478
1479 pirp->IoStatus.Information = 0;
1480 pirp->IoStatus.Status = STATUS_CANCELLED;
1481 IoCompleteRequest(pirp, IO_NO_INCREMENT);
1482 // the device queue is moved on, no need to call IoStartNextPacket
1483 return;
1484 }
1485
1486 //
1487 // remove the irp and call the dev_mgr_cancel_irp
1488 // the completion will be done in urb completion
1489 //
1490 remove_irp_from_list(&dev_mgr->irp_list, pirp, dev_mgr);
1491 return;
1492
1493 }
1494
1495 // release the hcd
1496 VOID
1497 dev_mgr_release_hcd(PUSB_DEV_MANAGER dev_mgr)
1498 {
1499 LONG i;
1500 PHCD hcd;
1501 for(i = 0; i < dev_mgr->hcd_count; i++)
1502 {
1503 hcd = dev_mgr->hcd_array[i];
1504 hcd->hcd_release(hcd);
1505 dev_mgr->hcd_array[i] = 0;
1506 }
1507 dev_mgr->hcd_count = 0;
1508 return;
1509 }
1510
1511 VOID
1512 dev_mgr_start_hcd(PUSB_DEV_MANAGER dev_mgr)
1513 {
1514 LONG i;
1515 PHCD hcd;
1516 for(i = 0; i < dev_mgr->hcd_count; i++)
1517 {
1518 hcd = dev_mgr->hcd_array[i];
1519 hcd->hcd_start(hcd);
1520 }
1521 return;
1522 }