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