2 * gendrv.c - USB driver stack project for Windows NT 4.0
4 * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com
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.
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.
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
22 //this driver is part of the dev manager responsible to manage non-driver device
23 #include "usbdriver.h"
26 #define if_dev( dev_obj ) \
27 ( ( ( ( PGENDRV_DEVICE_EXTENSION)dev_obj->DeviceExtension )->pdriver->driver_desc.flags & USB_DRIVER_FLAG_IF_CAPABLE ) != 0 )
29 #define GENDRV_EXIT_DISPATCH( dev_OBJ, staTUS, iRp ) \
31 iRp->IoStatus.Status = staTUS;\
32 if( staTUS != STATUS_PENDING)\
34 IoCompleteRequest( iRp, IO_NO_INCREMENT);\
37 IoMarkIrpPending( iRp );\
38 IoStartPacket( dev_OBJ, iRp, NULL, gendrv_cancel_queued_irp ); \
39 return STATUS_PENDING;\
42 #define GENDRV_COMPLETE_START_IO( dev_OBJ, staTUS, iRP ) \
44 iRP->IoStatus.Status = staTUS;\
45 if( staTUS != STATUS_PENDING )\
47 IoStartNextPacket( dev_OBJ, TRUE );\
48 IoCompleteRequest( iRP, IO_NO_INCREMENT );\
53 extern POBJECT_TYPE NTSYSAPI IoDriverObjectType
;
55 extern VOID
disp_urb_completion(PURB purb
, PVOID context
);
58 VOID
disp_noio_urb_completion(PURB purb
, PVOID context
);
60 NTSYSAPI NTSTATUS NTAPI
ZwLoadDriver(IN PUNICODE_STRING DriverServiceName
);
62 NTSYSAPI NTSTATUS NTAPI
ZwClose(IN HANDLE Handle
);
67 ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes
,
68 IN POBJECT_TYPE ObjectType OPTIONAL
,
69 IN KPROCESSOR_MODE AccessMode
,
70 IN OUT PACCESS_STATE AccessState OPTIONAL
,
71 IN ACCESS_MASK DesiredAccess OPTIONAL
,
72 IN OUT PVOID ParseContext OPTIONAL
, OUT PHANDLE Handle
);
74 BOOLEAN
gendrv_if_driver_destroy(PUSB_DEV_MANAGER dev_mgr
, PUSB_DRIVER pdriver
);
76 VOID
gendrv_set_cfg_completion(PURB purb
, PVOID context
);
78 BOOLEAN
gendrv_connect(PDEV_CONNECT_DATA param
, DEV_HANDLE dev_handle
);
80 BOOLEAN
gendrv_stop(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE dev_handle
);
82 BOOLEAN
gendrv_disconnect(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE dev_handle
);
84 VOID
gendrv_startio(IN PDEVICE_OBJECT dev_obj
, IN PIRP irp
);
86 VOID NTAPI
gendrv_cancel_queued_irp(PDEVICE_OBJECT pdev_obj
, PIRP pirp
);
88 VOID
gendrv_release_ext_drvr_entry(PGENDRV_DRVR_EXTENSION pdrvr_ext
, PGENDRV_EXT_DRVR_ENTRY pentry
);
90 VOID
gendrv_clean_up_queued_irps(PDEVICE_OBJECT dev_obj
);
92 PGENDRV_EXT_DRVR_ENTRY
gendrv_alloc_ext_drvr_entry(PGENDRV_DRVR_EXTENSION pdrvr_ext
);
94 PDRIVER_OBJECT
gendrv_open_ext_driver(PUNICODE_STRING unicode_string
);
97 gendrv_get_key_value(IN HANDLE KeyHandle
, IN PWSTR ValueName
, OUT PKEY_VALUE_FULL_INFORMATION
* Information
);
100 gendrv_open_reg_key(OUT PHANDLE handle
,
101 IN HANDLE base_handle OPTIONAL
,
102 IN PUNICODE_STRING keyname
, IN ACCESS_MASK desired_access
, IN BOOLEAN create
);
104 BOOLEAN
gendrv_do_disconnect(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE if_handle
, BOOLEAN is_if
);
106 BOOLEAN
gendrv_do_stop(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE dev_handle
, BOOLEAN is_if
);
108 NTSTATUS
gendrv_send_pnp_msg(ULONG msg
, PDEVICE_OBJECT pdev_obj
, PVOID pctx
);
110 BOOLEAN
gendrv_delete_device(PUSB_DEV_MANAGER dev_mgr
, PDEVICE_OBJECT dev_obj
);
112 PDEVICE_OBJECT
gendrv_create_device(PUSB_DEV_MANAGER dev_mgr
, PUSB_DRIVER gen_drvr
, DEV_HANDLE dev_handle
);
114 PDRIVER_OBJECT
gendrv_load_ext_drvr(PGENDRV_DRVR_EXTENSION pdrvr_ext
, PUSB_DESC_HEADER pdesc
);
116 PDRIVER_OBJECT
gendrv_find_drvr_by_key(PGENDRV_DRVR_EXTENSION pdrvr_ext
, ULONG key
);
118 ULONG
gendrv_make_key(PUSB_DESC_HEADER pdesc
);
121 gendrv_driver_init(PUSB_DEV_MANAGER dev_mgr
, PUSB_DRIVER pdriver
)
123 PGENDRV_DRVR_EXTENSION pdrvr_ext
;
125 if (dev_mgr
== NULL
|| pdriver
== NULL
)
128 pdriver
->driver_desc
.flags
= USB_DRIVER_FLAG_DEV_CAPABLE
;
129 pdriver
->driver_desc
.vendor_id
= 0xffff; // USB Vendor ID
130 pdriver
->driver_desc
.product_id
= 0xffff; // USB Product ID.
131 pdriver
->driver_desc
.release_num
= 0x100; // Release Number of Device
133 pdriver
->driver_desc
.config_val
= 0; // Configuration Value
134 pdriver
->driver_desc
.if_num
= 0; // Interface Number
135 pdriver
->driver_desc
.if_class
= 0xff; // Interface Class
136 pdriver
->driver_desc
.if_sub_class
= 0xff; // Interface SubClass
137 pdriver
->driver_desc
.if_protocol
= 0xff; // Interface Protocol
139 pdriver
->driver_desc
.driver_name
= "USB generic dev driver"; // Driver name for Name Registry
140 pdriver
->driver_desc
.dev_class
= USB_CLASS_VENDOR_SPEC
;
141 pdriver
->driver_desc
.dev_sub_class
= 0; // Device Subclass
142 pdriver
->driver_desc
.dev_protocol
= 0; // Protocol Info.
144 pdriver
->driver_ext
= usb_alloc_mem(NonPagedPool
, sizeof(GENDRV_DRVR_EXTENSION
));
145 if (!pdriver
->driver_ext
)
147 usb_dbg_print(DBGLVL_MAXIMUM
, ("gendrv_driver_init(): memory allocation failed!\n"));
151 pdriver
->driver_ext_size
= sizeof(GENDRV_DRVR_EXTENSION
);
153 RtlZeroMemory(pdriver
->driver_ext
, pdriver
->driver_ext_size
);
154 pdrvr_ext
= (PGENDRV_DRVR_EXTENSION
) pdriver
->driver_ext
;
156 // InitializeListHead( &pdrvr_ext->dev_list );
157 InitializeListHead(&pdrvr_ext
->ext_drvr_list
);
158 pdrvr_ext
->ext_drvr_count
= 0;
159 ExInitializeFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
161 pdriver
->disp_tbl
.version
= 1;
162 pdriver
->disp_tbl
.dev_connect
= gendrv_connect
;
163 pdriver
->disp_tbl
.dev_disconnect
= gendrv_disconnect
;
164 pdriver
->disp_tbl
.dev_stop
= gendrv_stop
;
165 pdriver
->disp_tbl
.dev_reserved
= NULL
;
171 gendrv_driver_destroy(PUSB_DEV_MANAGER dev_mgr
, PUSB_DRIVER pdriver
)
173 return gendrv_if_driver_destroy(dev_mgr
, pdriver
);
177 gendrv_connect(PDEV_CONNECT_DATA param
, DEV_HANDLE dev_handle
)
180 PUSB_CTRL_SETUP_PACKET psetup
;
184 PUSB_CONFIGURATION_DESC pconfig_desc
;
185 PUSB_DEV_MANAGER dev_mgr
;
187 if (param
== NULL
|| dev_handle
== 0)
190 dev_mgr
= param
->dev_mgr
;
192 // let's set the configuration
193 purb
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
197 buf
= usb_alloc_mem(NonPagedPool
, 512);
200 usb_dbg_print(DBGLVL_MAXIMUM
, ("gendrv_connect(): can not alloc buf\n"));
205 // before we set the configuration, let's search to find if there
206 // exist interfaces we supported
207 psetup
= (PUSB_CTRL_SETUP_PACKET
) (purb
)->setup_packet
;
209 purb
->endp_handle
= dev_handle
| 0xffff;
210 purb
->data_buffer
= buf
;
211 purb
->data_length
= 512;
212 purb
->completion
= NULL
; // this is an immediate request, no completion required
213 purb
->context
= NULL
;
215 psetup
->bmRequestType
= 0x80;
216 psetup
->bRequest
= USB_REQ_GET_DESCRIPTOR
;
217 psetup
->wValue
= USB_DT_CONFIG
<< 8;
219 psetup
->wLength
= 512;
221 status
= usb_submit_urb(dev_mgr
, purb
);
222 if (status
== STATUS_PENDING
)
230 // check the config desc valid
231 pconfig_desc
= (PUSB_CONFIGURATION_DESC
) buf
;
232 if (pconfig_desc
->wTotalLength
> 512)
236 usb_dbg_print(DBGLVL_MAXIMUM
, ("gendrv_connect(): error, bad configuration desc\n"));
240 i
= pconfig_desc
->bConfigurationValue
;
244 //set the configuration
246 purb
->endp_handle
= dev_handle
| 0xffff;
247 purb
->data_buffer
= NULL
;
248 purb
->data_length
= 0;
249 purb
->completion
= gendrv_set_cfg_completion
;
250 purb
->context
= dev_mgr
;
251 purb
->reference
= (ULONG
) param
->pdriver
;
252 psetup
->bmRequestType
= 0;
253 psetup
->bRequest
= USB_REQ_SET_CONFIGURATION
;
254 psetup
->wValue
= (USHORT
) i
;
258 usb_dbg_print(DBGLVL_MAXIMUM
, ("gendrv_connect(): start config the device, cfgval=%d\n", i
));
259 status
= usb_submit_urb(dev_mgr
, purb
);
261 if (status
!= STATUS_PENDING
)
265 if (status
== STATUS_SUCCESS
)
275 gendrv_event_select_driver(PUSB_DEV pdev
, //always null. we do not use this param
276 ULONG event
, ULONG context
, ULONG param
)
279 // try to search the registry to find one driver.
280 // if found, create the PDO, load the driver.
281 // and call its AddDevice.
285 PGENDRV_DRVR_EXTENSION pdrvr_ext
;
286 PGENDRV_EXT_DRVR_ENTRY pentry
;
287 PGENDRV_DEVICE_EXTENSION pdev_ext
;
288 PUSB_CONFIGURATION_DESC pconfig_desc
;
289 PUSB_DEV_MANAGER dev_mgr
;
291 PDEVICE_OBJECT pdev_obj
;
292 PDRIVER_OBJECT pdrvr_obj
;
293 PLIST_ENTRY pthis
, pnext
;
295 USE_BASIC_NON_PENDING_IRQL
;
297 UNREFERENCED_PARAMETER(context
);
298 UNREFERENCED_PARAMETER(event
);
303 usb_dbg_print(DBGLVL_MAXIMUM
, ("gendrv_event_select_driver(): entering...\n"));
305 pdrvr
= (PUSB_DRIVER
) param
;
306 //original code: pconfig_desc = (PUSB_CONFIGURATION_DESC) pdev->desc_buf[sizeof(USB_DEVICE_DESC)];
307 pconfig_desc
= (PUSB_CONFIGURATION_DESC
) &pdev
->desc_buf
[sizeof(USB_DEVICE_DESC
)];
308 pdrvr_ext
= (PGENDRV_DRVR_EXTENSION
) pdrvr
->driver_ext
;
311 // well, let's do the hard work to see if there is a class driver
313 // in the event routine, we have no need to check if the device is zomb or
314 // not, it must be alive there.
316 i
= gendrv_make_key((PUSB_DESC_HEADER
) pdev
->pusb_dev_desc
);
322 pdrvr_obj
= gendrv_find_drvr_by_key(pdrvr_ext
, (ULONG
) i
);
325 if ((pdrvr_obj
= gendrv_load_ext_drvr(pdrvr_ext
, (PUSB_DESC_HEADER
) pdev
->pusb_dev_desc
)) == NULL
)
329 dev_mgr
= dev_mgr_from_dev(pdev
);
330 pdev_obj
= gendrv_create_device(dev_mgr
, pdrvr
, usb_make_handle(pdev
->dev_id
, 0, 0));
331 if (pdev_obj
== NULL
)
336 lock_dev(pdev
, FALSE
);
337 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
||
338 dev_mgr_set_driver(dev_mgr
, usb_make_handle(pdev
->dev_id
, 0, 0), pdrvr
, pdev
) == FALSE
)
340 unlock_dev(pdev
, FALSE
);
341 gendrv_delete_device(dev_mgr
, pdev_obj
);
345 if (pdev
->usb_config
)
347 pdev
->dev_obj
= pdev_obj
;
350 unlock_dev(pdev
, FALSE
);
352 pdev_ext
= (PGENDRV_DEVICE_EXTENSION
) pdev_obj
->DeviceExtension
;
353 pdev_ext
->desc_buf
= usb_alloc_mem(NonPagedPool
, 512);
354 if (!pdev_ext
->desc_buf
)
356 usb_dbg_print(DBGLVL_MAXIMUM
, ("gendrv_event_select_driver(): memory allocation failed!\n"));
360 RtlCopyMemory(pdev_ext
->desc_buf
, pconfig_desc
, 512);
362 // insert the device to the dev_list
363 ExAcquireFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
364 ListFirst(&pdrvr_ext
->ext_drvr_list
, pthis
);
368 pentry
= (PGENDRV_EXT_DRVR_ENTRY
) pthis
;
369 if (pentry
->pext_drvr
== pdrvr_obj
)
371 ListNext(&pdrvr_ext
->ext_drvr_list
, pthis
, pnext
);
376 InsertTailList(&pentry
->dev_list
, &pdev_ext
->dev_obj_link
);
377 pdev_ext
->ext_drvr_entry
= pentry
;
379 ExReleaseFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
381 // notify the class driver, some device comes
382 gendrv_send_pnp_msg(GENDRV_MSG_ADDDEVICE
, pdev_obj
, pdrvr_obj
);
383 usb_unlock_dev(pdev
);
388 usb_unlock_dev(pdev
);
393 gendrv_set_cfg_completion(PURB purb
, PVOID context
)
395 DEV_HANDLE dev_handle
;
396 PUSB_DEV_MANAGER dev_mgr
;
401 USE_BASIC_NON_PENDING_IRQL
;
403 if (purb
== NULL
|| context
== NULL
)
406 dev_handle
= purb
->endp_handle
& ~0xffff;
407 dev_mgr
= (PUSB_DEV_MANAGER
) context
;
408 pdriver
= (PUSB_DRIVER
) purb
->reference
;
410 if (purb
->status
!= STATUS_SUCCESS
)
420 status
= usb_query_and_lock_dev(dev_mgr
, dev_handle
, &pdev
);
421 if (status
!= STATUS_SUCCESS
)
423 usb_unlock_dev(pdev
);
426 usb_unlock_dev(pdev
); // safe to release the pdev ref since we are in urb completion
429 KeAcquireSpinLockAtDpcLevel(&dev_mgr
->event_list_lock
);
430 lock_dev(pdev
, TRUE
);
432 if (dev_state(pdev
) >= USB_DEV_STATE_BEFORE_ZOMB
)
434 unlock_dev(pdev
, TRUE
);
435 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->event_list_lock
);
439 if (dev_mgr_set_driver(dev_mgr
, dev_handle
, pdriver
, pdev
) == FALSE
)
441 unlock_dev(pdev
, TRUE
);
442 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->event_list_lock
);
446 //transit the state to configured
447 pdev
->flags
&= ~USB_DEV_STATE_MASK
;
448 pdev
->flags
|= USB_DEV_STATE_CONFIGURED
;
450 pevent
= alloc_event(&dev_mgr
->event_pool
, 1);
453 unlock_dev(pdev
, TRUE
);
454 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->event_list_lock
);
458 pevent
->flags
= USB_EVENT_FLAG_ACTIVE
;
459 pevent
->event
= USB_EVENT_DEFAULT
;
462 pevent
->param
= (ULONG
) pdriver
;
463 pevent
->pnext
= 0; //vertical queue for serialized operation
464 pevent
->process_event
= (PROCESS_EVENT
) gendrv_event_select_driver
;
465 pevent
->process_queue
= event_list_default_process_queue
;
467 InsertTailList(&dev_mgr
->event_list
, &pevent
->event_link
);
468 KeSetEvent(&dev_mgr
->wake_up_event
, 0, FALSE
);
469 unlock_dev(pdev
, TRUE
);
470 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->event_list_lock
);
477 gendrv_stop(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE dev_handle
)
481 return gendrv_do_stop(dev_mgr
, dev_handle
, FALSE
);
485 gendrv_disconnect(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE dev_handle
)
489 return gendrv_do_disconnect(dev_mgr
, dev_handle
, FALSE
);
493 gendrv_build_reg_string(PUSB_DESC_HEADER pdesc
, PUNICODE_STRING pus
)
499 if (pdesc
== NULL
|| pus
== NULL
)
502 if (pdesc
->bDescriptorType
== USB_DT_DEVICE
)
504 PUSB_DEVICE_DESC pdev_desc
;
505 pdev_desc
= (PUSB_DEVICE_DESC
) pdesc
;
506 sprintf(desc_str
, "%sv_%04x&p_%04x",
507 "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\ehci\\device\\",
508 pdev_desc
->idVendor
, pdev_desc
->idProduct
);
510 else if (pdesc
->bDescriptorType
== USB_DT_INTERFACE
)
512 PUSB_INTERFACE_DESC pif_desc
;
513 pif_desc
= (PUSB_INTERFACE_DESC
) pdesc
;
514 sprintf(desc_str
, "%sc_%04x&s_%04x&p_%04x",
515 "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\ehci\\interface\\",
516 pif_desc
->bInterfaceClass
, pif_desc
->bInterfaceSubClass
, pif_desc
->bInterfaceProtocol
);
521 RtlInitString(&atemp
, desc_str
);
522 RtlAnsiStringToUnicodeString(pus
, &atemp
, TRUE
);
527 gendrv_make_key(PUSB_DESC_HEADER pdesc
)
529 PUSB_DEVICE_DESC pdev_desc
;
530 PUSB_INTERFACE_DESC pif_desc
;
534 if (pdesc
->bDescriptorType
== USB_DT_DEVICE
)
536 pdev_desc
= (PUSB_DEVICE_DESC
) pdesc
;
537 return ((((ULONG
) pdev_desc
->idVendor
) << 16) | pdev_desc
->idProduct
);
539 else if (pdesc
->bDescriptorType
== USB_DT_INTERFACE
)
541 pif_desc
= (PUSB_INTERFACE_DESC
) pdesc
;
542 return ((((ULONG
) pif_desc
->bInterfaceClass
) << 16) |
543 (((ULONG
) pif_desc
->bInterfaceSubClass
) << 8) | ((ULONG
) pif_desc
->bInterfaceProtocol
));
549 gendrv_find_drvr_by_key(PGENDRV_DRVR_EXTENSION pdrvr_ext
, ULONG key
)
551 PGENDRV_EXT_DRVR_ENTRY pentry
;
552 PLIST_ENTRY pthis
, pnext
;
553 if (pdrvr_ext
== NULL
|| key
== (ULONG
) - 1)
556 ExAcquireFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
557 ListFirst(&pdrvr_ext
->ext_drvr_list
, pthis
);
560 pentry
= (PGENDRV_EXT_DRVR_ENTRY
) pthis
;
561 if (pentry
->drvr_key
== key
)
563 ExReleaseFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
564 return pentry
->pext_drvr
;
566 ListNext(&pdrvr_ext
->ext_drvr_list
, pthis
, pnext
);
569 ExReleaseFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
575 gendrv_load_ext_drvr(PGENDRV_DRVR_EXTENSION pdrvr_ext
, PUSB_DESC_HEADER pdesc
)
577 PDRIVER_OBJECT pdrvr_obj
;
578 PGENDRV_EXT_DRVR_ENTRY pentry
;
579 UNICODE_STRING usz
, svc_name
, svc_key
, utemp
;
580 PKEY_VALUE_FULL_INFORMATION val_info
;
585 if (pdrvr_ext
== NULL
|| pdesc
== NULL
)
588 // try to search and load driver from outside
590 RtlZeroMemory(&svc_key
, sizeof(svc_key
));
592 RtlInitUnicodeString(&usz
, L
"");
593 gendrv_build_reg_string(pdesc
, &usz
);
594 DbgPrint("UHCI: Trying to load driver %wZ\n", &usz
);
595 if (gendrv_open_reg_key(&handle
, NULL
, &usz
, KEY_READ
, FALSE
) != STATUS_SUCCESS
)
599 if (gendrv_get_key_value(handle
, L
"service", &val_info
) != STATUS_SUCCESS
)
604 if (val_info
->DataLength
> 32)
607 val_buf
= (PWCHAR
) (((PBYTE
) val_info
) + val_info
->DataOffset
);
608 svc_key
.Length
= 0, svc_key
.MaximumLength
= 255;
609 svc_key
.Buffer
= usb_alloc_mem(NonPagedPool
, 256);
611 RtlInitUnicodeString(&utemp
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
612 RtlAppendUnicodeStringToString(&svc_key
, &utemp
);
613 RtlInitUnicodeString(&svc_name
, val_buf
);
614 RtlAppendUnicodeStringToString(&svc_key
, &svc_name
);
616 status
= ZwLoadDriver(&svc_key
);
617 if (status
!= STATUS_SUCCESS
)
621 RtlZeroMemory(svc_key
.Buffer
, 128);
622 RtlInitUnicodeString(&svc_key
, L
"\\Driver\\");
623 RtlAppendUnicodeStringToString(&svc_key
, &svc_name
);
624 pdrvr_obj
= gendrv_open_ext_driver(&svc_key
);
625 if (pdrvr_obj
== NULL
)
628 ExAcquireFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
630 // insert the driver to the drvr list
631 pentry
= gendrv_alloc_ext_drvr_entry(pdrvr_ext
);
634 ExReleaseFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
635 ObDereferenceObject(pdrvr_obj
);
638 pentry
->pext_drvr
= pdrvr_obj
;
639 InsertTailList(&pdrvr_ext
->ext_drvr_list
, &pentry
->drvr_link
);
640 pdrvr_ext
->ext_drvr_count
++;
641 ExReleaseFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
646 RtlFreeUnicodeString(&usz
);
647 if (val_info
!= NULL
)
649 usb_free_mem(val_info
);
653 usb_free_mem(svc_key
.Buffer
);
662 gendrv_release_drvr(PGENDRV_DRVR_EXTENSION pdrvr_ext
, PDRIVER_OBJECT pdrvr_obj
)
664 PLIST_ENTRY pthis
, pnext
;
665 PGENDRV_EXT_DRVR_ENTRY pentry
;
667 if (pdrvr_ext
== NULL
|| pdrvr_obj
== NULL
)
669 ExAcquireFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
670 ListFirst(&pdrvr_ext
->ext_drvr_list
, pthis
);
673 pentry
= (PGENDRV_EXT_DRVR_ENTRY
) pthis
;
674 if (pentry
->pext_drvr
== pdrvr_obj
)
676 ASSERT(pentry
->ref_count
);
677 ExReleaseFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
680 ListNext(&pdrvr_ext
->ext_drvr_list
, pthis
, pnext
);
683 ExReleaseFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
687 gendrv_send_pnp_msg(ULONG msg
, PDEVICE_OBJECT pdev_obj
, PVOID pctx
)
689 if (pdev_obj
== NULL
)
690 return STATUS_INVALID_PARAMETER
;
694 case GENDRV_MSG_ADDDEVICE
:
696 PDRIVER_OBJECT pdrvr_obj
;
698 return STATUS_INVALID_PARAMETER
;
699 pdrvr_obj
= (PDRIVER_OBJECT
) pctx
;
700 if (pdrvr_obj
->DriverExtension
)
702 return pdrvr_obj
->DriverExtension
->AddDevice(pdrvr_obj
, pdev_obj
);
704 return STATUS_IO_DEVICE_ERROR
;
706 case GENDRV_MSG_STOPDEVICE
:
707 case GENDRV_MSG_DISCDEVICE
:
710 IO_STACK_LOCATION
*irpstack
;
713 irp
= IoAllocateIrp(2, FALSE
);
715 return STATUS_NO_MEMORY
;
717 irpstack
= IoGetNextIrpStackLocation(irp
);
718 irpstack
->MajorFunction
= IRP_MJ_PNP_POWER
;
719 irpstack
->MinorFunction
=
720 (msg
== GENDRV_MSG_STOPDEVICE
) ? IRP_MN_STOP_DEVICE
: IRP_MN_REMOVE_DEVICE
;
721 status
= IoCallDriver(pdev_obj
, irp
);
722 ASSERT(status
!= STATUS_PENDING
);
723 status
= irp
->IoStatus
.Status
;
725 return STATUS_MORE_PROCESSING_REQUIRED
;
728 return STATUS_INVALID_PARAMETER
;
733 gendrv_if_connect(PDEV_CONNECT_DATA params
, DEV_HANDLE if_handle
)
736 // try to search the registry to find one driver.
737 // if found, create the PDO, load the driver.
738 // and call its AddDevice.
744 PUSB_INTERFACE_DESC pif_desc
;
745 PGENDRV_DEVICE_EXTENSION pdev_ext
;
746 PUSB_CONFIGURATION_DESC pconfig_desc
;
747 PUSB_DEV_MANAGER dev_mgr
;
748 PGENDRV_DRVR_EXTENSION pdrvr_ext
;
749 PGENDRV_EXT_DRVR_ENTRY pentry
;
751 PDEVICE_OBJECT pdev_obj
;
752 PDRIVER_OBJECT pdrvr_obj
;
753 PLIST_ENTRY pthis
, pnext
;
754 USE_BASIC_NON_PENDING_IRQL
;
757 usb_dbg_print(DBGLVL_MAXIMUM
, ("gendrv_if_connect(): entering...\n"));
762 dev_mgr
= params
->dev_mgr
;
763 pdrvr
= params
->pdriver
;
764 pdrvr_ext
= (PGENDRV_DRVR_EXTENSION
) pdrvr
->driver_ext
;
766 status
= usb_query_and_lock_dev(dev_mgr
, if_handle
, &pdev
);
767 if (status
!= STATUS_SUCCESS
)
771 // obtain the pointer to the config desc, the dev won't go away in this routine
772 pconfig_desc
= pdev
->usb_config
->pusb_config_desc
; //
773 usb_unlock_dev(pdev
);
776 if_idx
= if_idx_from_handle(if_handle
);
777 pif_desc
= (PUSB_INTERFACE_DESC
) (&pconfig_desc
[1]);
779 for(i
= 0; i
< if_idx
; i
++)
782 if (usb_skip_if_and_altif((PUCHAR
*) & pif_desc
) == FALSE
)
785 if (pif_desc
== NULL
)
789 // well, let's do the hard work to see if there is a class driver
792 i
= gendrv_make_key((PUSB_DESC_HEADER
) pif_desc
);
798 pdrvr_obj
= gendrv_find_drvr_by_key(pdrvr_ext
, (ULONG
) i
);
801 if ((pdrvr_obj
= gendrv_load_ext_drvr(pdrvr_ext
, (PUSB_DESC_HEADER
) pif_desc
)) == NULL
)
806 pdev_obj
= gendrv_create_device(dev_mgr
, pdrvr
, if_handle
);
807 if (pdev_obj
== NULL
)
812 lock_dev(pdev
, FALSE
);
813 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
||
814 dev_mgr_set_if_driver(dev_mgr
, if_handle
, pdrvr
, pdev
) == FALSE
)
816 unlock_dev(pdev
, FALSE
);
817 gendrv_delete_device(dev_mgr
, pdev_obj
);
821 if (pdev
->usb_config
)
823 pdev
->usb_config
->interf
[if_idx
].if_ext
= pdev_obj
;
824 pdev
->usb_config
->interf
[if_idx
].if_ext_size
= 0;
827 unlock_dev(pdev
, FALSE
);
829 pdev_ext
= (PGENDRV_DEVICE_EXTENSION
) pdev_obj
->DeviceExtension
;
830 pdev_ext
->desc_buf
= usb_alloc_mem(NonPagedPool
, 512);
831 if (!pdev_ext
->desc_buf
)
833 usb_dbg_print(DBGLVL_MAXIMUM
, ("gendrv_if_connect(): memory allocation failed!\n"));
837 RtlCopyMemory(pdev_ext
->desc_buf
, pconfig_desc
, 512);
838 pdev_ext
->if_ctx
.pif_desc
=
839 (PUSB_INTERFACE_DESC
) & pdev_ext
->desc_buf
[(PBYTE
) pif_desc
- (PBYTE
) pconfig_desc
];
841 // insert the device to the dev_list
842 ExAcquireFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
843 ListFirst(&pdrvr_ext
->ext_drvr_list
, pthis
);
847 pentry
= (PGENDRV_EXT_DRVR_ENTRY
) pthis
;
848 if (pentry
->pext_drvr
== pdrvr_obj
)
850 ListNext(&pdrvr_ext
->ext_drvr_list
, pthis
, pnext
);
855 InsertTailList(&pentry
->dev_list
, &pdev_ext
->dev_obj_link
);
856 pdev_ext
->ext_drvr_entry
= pentry
;
858 ExReleaseFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
860 // notify the class driver, some device comes
861 gendrv_send_pnp_msg(GENDRV_MSG_ADDDEVICE
, pdev_obj
, pdrvr_obj
);
862 usb_unlock_dev(pdev
);
867 usb_unlock_dev(pdev
);
872 gendrv_do_stop(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE dev_handle
, BOOLEAN is_if
)
875 PDEVICE_OBJECT pdev_obj
;
882 if_idx
= if_idx_from_handle(dev_handle
);
883 if (usb_query_and_lock_dev(dev_mgr
, dev_handle
, &pdev
) != STATUS_SUCCESS
)
887 if (is_if
&& pdev
->usb_config
)
888 pdev_obj
= (PDEVICE_OBJECT
) pdev
->usb_config
->interf
[if_idx
].if_ext
;
890 pdev_obj
= pdev
->dev_obj
;
892 gendrv_clean_up_queued_irps(pdev_obj
);
893 usb_unlock_dev(pdev
);
895 // send message to class drivers.
896 gendrv_send_pnp_msg(GENDRV_MSG_STOPDEVICE
, pdev_obj
, NULL
);
902 gendrv_if_stop(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE dev_handle
)
907 return gendrv_do_stop(dev_mgr
, dev_handle
, TRUE
);
911 gendrv_do_disconnect(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE if_handle
, BOOLEAN is_if
)
914 PDEVICE_OBJECT dev_obj
= NULL
;
917 PGENDRV_DRVR_EXTENSION pdrvr_ext
= NULL
;
918 PGENDRV_DEVICE_EXTENSION pdev_ext
= NULL
;
921 status
= usb_query_and_lock_dev(dev_mgr
, if_handle
, &pdev
);
926 if (status
== STATUS_SUCCESS
)
931 if_idx
= if_idx_from_handle(if_handle
);
932 if (pdev
->usb_config
)
936 pdrvr
= pdev
->usb_config
->interf
[if_idx
].pif_drv
;
937 dev_obj
= (PDEVICE_OBJECT
) pdev
->usb_config
->interf
[if_idx
].if_ext
;
941 pdrvr
= pdev
->dev_driver
;
942 dev_obj
= pdev
->dev_obj
;
947 // it means no driver was found for the device and thus no device object created
948 // we just do nothing here
952 pdrvr_ext
= (PGENDRV_DRVR_EXTENSION
) pdrvr
->driver_ext
;
953 pdev_ext
= (PGENDRV_DEVICE_EXTENSION
) dev_obj
->DeviceExtension
;
959 // remove the device from the list
960 ExAcquireFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
961 RemoveEntryList(&pdev_ext
->dev_obj_link
);
962 pdev_ext
->ext_drvr_entry
->ref_count
--;
963 ExReleaseFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
965 // send message to class driver
966 gendrv_send_pnp_msg(GENDRV_MSG_DISCDEVICE
, dev_obj
, NULL
);
967 // delete the device object
968 gendrv_delete_device(dev_mgr
, dev_obj
);
973 gendrv_if_disconnect(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE if_handle
)
975 return gendrv_do_disconnect(dev_mgr
, if_handle
, TRUE
);
979 gendrv_if_driver_init(PUSB_DEV_MANAGER dev_mgr
, PUSB_DRIVER pdriver
)
981 PGENDRV_DRVR_EXTENSION pdrvr_ext
;
982 if (dev_mgr
== NULL
|| pdriver
== NULL
)
985 pdriver
->driver_desc
.flags
= USB_DRIVER_FLAG_IF_CAPABLE
;
986 pdriver
->driver_desc
.vendor_id
= 0x0000; // USB Vendor ID
987 pdriver
->driver_desc
.product_id
= 0x0000; // USB Product ID.
988 pdriver
->driver_desc
.release_num
= 0x100; // Release Number of Device
990 pdriver
->driver_desc
.config_val
= 0; // Configuration Value
991 pdriver
->driver_desc
.if_num
= 0; // Interface Number
992 pdriver
->driver_desc
.if_class
= 0x0; // Interface Class
993 pdriver
->driver_desc
.if_sub_class
= 0x0; // Interface SubClass
994 pdriver
->driver_desc
.if_protocol
= 0x0; // Interface Protocol
996 pdriver
->driver_desc
.driver_name
= "USB generic interface driver"; // Driver name for Name Registry
997 pdriver
->driver_desc
.dev_class
= 0;
998 pdriver
->driver_desc
.dev_sub_class
= 0; // Device Subclass
999 pdriver
->driver_desc
.dev_protocol
= 0; // Protocol Info.
1001 //we have no extra data sturcture currently
1003 pdriver
->disp_tbl
.version
= 1;
1004 pdriver
->disp_tbl
.dev_connect
= gendrv_if_connect
;
1005 pdriver
->disp_tbl
.dev_disconnect
= gendrv_if_disconnect
;
1006 pdriver
->disp_tbl
.dev_stop
= gendrv_if_stop
;
1007 pdriver
->disp_tbl
.dev_reserved
= NULL
;
1009 pdriver
->driver_ext
= usb_alloc_mem(NonPagedPool
, sizeof(GENDRV_DRVR_EXTENSION
));
1010 if (!pdriver
->driver_ext
) return FALSE
;
1012 pdriver
->driver_ext_size
= sizeof(GENDRV_DRVR_EXTENSION
);
1014 RtlZeroMemory(pdriver
->driver_ext
, pdriver
->driver_ext_size
);
1015 pdrvr_ext
= (PGENDRV_DRVR_EXTENSION
) pdriver
->driver_ext
;
1017 // InitializeListHead( &pdrvr_ext->dev_list );
1018 InitializeListHead(&pdrvr_ext
->ext_drvr_list
);
1019 pdrvr_ext
->ext_drvr_count
= 0;
1020 ExInitializeFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
1026 gendrv_if_driver_destroy(PUSB_DEV_MANAGER dev_mgr
, PUSB_DRIVER pdriver
)
1028 PGENDRV_DRVR_EXTENSION pdrvr_ext
;
1030 PGENDRV_EXT_DRVR_ENTRY pentry
;
1031 if (dev_mgr
== NULL
|| pdriver
== NULL
)
1034 if (pdriver
->driver_ext
)
1036 // should we lock it?
1037 // ExAcquireFastMutex( &pdrvr_ext->drvr_ext_mutex );
1038 pdrvr_ext
= (PGENDRV_DRVR_EXTENSION
) pdriver
->driver_ext
;
1039 if (pdrvr_ext
->ext_drvr_count
)
1041 while (IsListEmpty(&pdrvr_ext
->ext_drvr_list
))
1043 pthis
= RemoveHeadList(&pdrvr_ext
->ext_drvr_list
);
1044 pentry
= (PGENDRV_EXT_DRVR_ENTRY
) pthis
;
1045 if (pentry
->pext_drvr
)
1047 if (pentry
->ref_count
)
1049 // FIXME: really fail?
1052 ObDereferenceObject(pentry
->pext_drvr
);
1053 gendrv_release_ext_drvr_entry(pdrvr_ext
, pentry
);
1056 pdrvr_ext
->ext_drvr_count
= 0;
1059 usb_free_mem(pdriver
->driver_ext
);
1060 pdriver
->driver_ext
= NULL
;
1061 pdriver
->driver_ext_size
= 0;
1067 gendrv_open_ext_driver(PUNICODE_STRING unicode_string
)
1070 OBJECT_ATTRIBUTES oa
;
1072 UNICODE_STRING oname
;
1073 PDRIVER_OBJECT pdrvr
= NULL
;
1075 RtlZeroMemory(&oa
, sizeof(oa
));
1076 oa
.Length
= sizeof(oa
);
1077 oa
.ObjectName
= &oname
;
1078 oa
.Attributes
= OBJ_CASE_INSENSITIVE
;
1079 RtlInitUnicodeString(&oname
, L
"");
1080 RtlAppendUnicodeStringToString(&oname
, unicode_string
);
1082 status
= ObOpenObjectByName(&oa
, IoDriverObjectType
, // object type
1083 KernelMode
, // access mode
1084 NULL
, // access state
1085 FILE_READ_DATA
, // STANDARD_RIGHTS_READ, access right
1089 if (status
!= STATUS_SUCCESS
)
1093 ObReferenceObjectByHandle(drvr_handle
,
1098 NULL
); // OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL
1100 ZwClose(drvr_handle
);
1105 gendrv_close_ext_driver(PDRIVER_OBJECT pdrvr
)
1109 ObDereferenceObject(pdrvr
);
1114 gendrv_dispatch(PDEVICE_OBJECT dev_obj
, PIRP irp
)
1116 IO_STACK_LOCATION
*irpstack
;
1117 PUSB_DEV_MANAGER dev_mgr
;
1118 PDEVEXT_HEADER ext_hdr
;
1121 if (dev_obj
== NULL
|| irp
== NULL
)
1122 return STATUS_INVALID_PARAMETER
;
1124 ext_hdr
= dev_obj
->DeviceExtension
;
1125 dev_mgr
= ext_hdr
->dev_mgr
;
1127 irpstack
= IoGetNextIrpStackLocation(irp
);
1128 switch (irpstack
->MajorFunction
)
1130 case IRP_MJ_PNP_POWER
:
1132 irp
->IoStatus
.Information
= 0;
1133 GENDRV_EXIT_DISPATCH(dev_obj
, STATUS_SUCCESS
, irp
);
1135 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
1137 status
= STATUS_NOT_SUPPORTED
;
1138 if (irpstack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_SUBMIT_URB_RD
||
1139 irpstack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_SUBMIT_URB_WR
||
1140 irpstack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_SUBMIT_URB_NOIO
)
1143 DEV_HANDLE endp_handle
;
1144 PGENDRV_DEVICE_EXTENSION pdev_ext
;
1146 pdev_ext
= dev_obj
->DeviceExtension
;
1147 if (irpstack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(URB
))
1149 GENDRV_EXIT_DISPATCH(dev_obj
, STATUS_INVALID_PARAMETER
, irp
);
1152 purb
= (PURB
) irp
->AssociatedIrp
.SystemBuffer
;
1153 endp_handle
= purb
->endp_handle
;
1154 if (purb
->data_buffer
== NULL
|| purb
->data_length
== 0)
1156 if (irpstack
->Parameters
.DeviceIoControl
.IoControlCode
!= IOCTL_SUBMIT_URB_NOIO
)
1158 GENDRV_EXIT_DISPATCH(dev_obj
, STATUS_INVALID_PARAMETER
, irp
);
1161 if (!default_endp_handle(endp_handle
))
1163 //no permit to other interface if interface dev
1164 if (if_dev(dev_obj
) && if_idx_from_handle(endp_handle
) != pdev_ext
->if_ctx
.if_idx
)
1165 GENDRV_EXIT_DISPATCH(dev_obj
, STATUS_INVALID_PARAMETER
, irp
);
1168 GENDRV_EXIT_DISPATCH(dev_obj
, STATUS_PENDING
, irp
);
1170 else if (irpstack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_GET_DEV_DESC
)
1172 // this is a synchronous call, route to dev_mgr_dispatch
1173 return dev_mgr_dispatch(dev_mgr
, irp
);
1175 else if (irpstack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_GET_DEV_HANDLE
)
1177 PGENDRV_DEVICE_EXTENSION pdev_ext
;
1178 pdev_ext
= dev_obj
->DeviceExtension
;
1179 if (irpstack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(LONG
))
1180 GENDRV_EXIT_DISPATCH(dev_obj
, STATUS_INVALID_PARAMETER
, irp
);
1182 *((PLONG
) irp
->AssociatedIrp
.SystemBuffer
) = pdev_ext
->dev_handle
;
1183 irp
->IoStatus
.Information
= sizeof(LONG
);
1184 GENDRV_EXIT_DISPATCH(dev_obj
, STATUS_SUCCESS
, irp
);
1186 GENDRV_EXIT_DISPATCH(dev_obj
, STATUS_NOT_SUPPORTED
, irp
);
1188 case IRP_MJ_DEVICE_CONTROL
:
1190 status
= STATUS_NOT_SUPPORTED
;
1191 if (irpstack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_SUBMIT_URB_RD
||
1192 irpstack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_SUBMIT_URB_WR
||
1193 irpstack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_SUBMIT_URB_NOIO
)
1196 DEV_HANDLE endp_handle
;
1197 PGENDRV_DEVICE_EXTENSION pdev_ext
;
1199 pdev_ext
= dev_obj
->DeviceExtension
;
1200 if (irpstack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(URB
))
1202 GENDRV_EXIT_DISPATCH(dev_obj
, STATUS_INVALID_PARAMETER
, irp
);
1205 purb
= (PURB
) irp
->AssociatedIrp
.SystemBuffer
;
1206 endp_handle
= purb
->endp_handle
;
1207 if (!default_endp_handle(endp_handle
))
1209 //no permit to other interface if interface dev
1210 if (if_dev(dev_obj
) && if_idx_from_handle(endp_handle
) != pdev_ext
->if_ctx
.if_idx
)
1211 GENDRV_EXIT_DISPATCH(dev_obj
, STATUS_INVALID_PARAMETER
, irp
);
1214 GENDRV_EXIT_DISPATCH(dev_obj
, STATUS_PENDING
, irp
);
1216 else if (irpstack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_GET_DEV_DESC
)
1218 // this is a synchronous call, route to dev_mgr_dispatch
1219 return dev_mgr_dispatch(dev_mgr
, irp
);
1221 else if (irpstack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_GET_DEV_HANDLE
)
1223 PGENDRV_DEVICE_EXTENSION pdev_ext
;
1224 pdev_ext
= dev_obj
->DeviceExtension
;
1225 if (irpstack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(LONG
))
1226 GENDRV_EXIT_DISPATCH(dev_obj
, STATUS_INVALID_PARAMETER
, irp
);
1228 *((PLONG
) irp
->AssociatedIrp
.SystemBuffer
) = pdev_ext
->dev_handle
;
1229 irp
->IoStatus
.Information
= sizeof(LONG
);
1230 GENDRV_EXIT_DISPATCH(dev_obj
, STATUS_SUCCESS
, irp
);
1232 GENDRV_EXIT_DISPATCH(dev_obj
, STATUS_NOT_SUPPORTED
, irp
);
1235 irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
1236 irp
->IoStatus
.Information
= 0;
1237 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
1239 return STATUS_NOT_SUPPORTED
;
1243 gendrv_init_dev_ext_hdr(PDEVICE_OBJECT dev_obj
, PUSB_DEV_MANAGER dev_mgr
)
1245 PDEVEXT_HEADER dev_hdr
= NULL
;
1246 if (dev_obj
== NULL
|| dev_mgr
== NULL
)
1249 dev_hdr
= (PDEVEXT_HEADER
) dev_obj
->DeviceExtension
;
1250 dev_hdr
->type
= NTDEV_TYPE_CLIENT_DEV
;
1251 dev_hdr
->dispatch
= gendrv_dispatch
;
1252 dev_hdr
->start_io
= (PDRIVER_STARTIO
) gendrv_startio
;
1257 gendrv_create_device(PUSB_DEV_MANAGER dev_mgr
, PUSB_DRIVER gen_drvr
, DEV_HANDLE dev_handle
)
1260 PDEVICE_OBJECT pdev
;
1261 PGENDRV_DEVICE_EXTENSION pdev_ext
;
1263 PGENDRV_DRVR_EXTENSION pdrvr_ext
;
1266 UNICODE_STRING name_string
, symb_link
;
1269 if (dev_mgr
== NULL
|| gen_drvr
== NULL
|| dev_handle
== 0)
1272 is_if
= (gen_drvr
->driver_desc
.flags
& USB_DRIVER_FLAG_IF_CAPABLE
) ? 1 : 0;
1273 usb_dbg_print(DBGLVL_MAXIMUM
, ("gendrv_create_device(): entering...\n"));
1274 pdrvr_ext
= (PGENDRV_DRVR_EXTENSION
) gen_drvr
->driver_ext
;
1275 dev_id
= (UCHAR
) dev_id_from_handle(dev_handle
);
1278 sprintf(dev_name
, "\\Device\\gendev_%d", (int)dev_id
);
1280 sprintf(dev_name
, "\\Device\\genifdev_%d", (int)dev_id
);
1282 RtlInitString(&string
, dev_name
);
1283 RtlAnsiStringToUnicodeString(&name_string
, &string
, TRUE
);
1286 status
= IoCreateDevice(dev_mgr
->usb_driver_obj
,
1287 sizeof(GENDRV_DEVICE_EXTENSION
), &name_string
, FILE_USB_DEV_TYPE
, 0, TRUE
, &pdev
);
1289 if (status
== STATUS_SUCCESS
)
1294 pdev
->Flags
|= DO_DIRECT_IO
;
1296 pdev
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1297 pdev
->StackSize
= 2; //one for fdo, one for file device obj
1299 pdev_ext
= (PGENDRV_DEVICE_EXTENSION
) pdev
->DeviceExtension
;
1301 //may be accessed by other thread
1303 gendrv_init_dev_ext_hdr(pdev
, dev_mgr
);
1305 pdev_ext
->dev_id
= (UCHAR
) dev_id
;
1306 pdev_ext
->pdo
= pdev
;
1307 pdev_ext
->dev_handle
= dev_handle
;
1308 pdev_ext
->dev_mgr
= dev_mgr
;
1309 pdev_ext
->pdriver
= gen_drvr
;
1312 sprintf(dev_name
, "\\DosDevices\\gendev%d", (int)dev_id
);
1314 sprintf(dev_name
, "\\DosDevices\\genifdev%d", (int)dev_id
);
1316 RtlInitString(&string
, dev_name
);
1317 RtlAnsiStringToUnicodeString(&symb_link
, &string
, TRUE
);
1318 IoCreateSymbolicLink(&symb_link
, &name_string
);
1319 RtlFreeUnicodeString(&symb_link
);
1320 KeInitializeEvent(&pdev_ext
->sync_event
, SynchronizationEvent
, FALSE
);
1321 KeInitializeSpinLock(&pdev_ext
->dev_lock
);
1324 RtlFreeUnicodeString(&name_string
);
1331 gendrv_deferred_delete_device(PVOID context
)
1333 PDEVICE_OBJECT dev_obj
;
1334 PGENDRV_DEVICE_EXTENSION pdev_ext
;
1335 PGENDRV_DRVR_EXTENSION pdrvr_ext
;
1336 LARGE_INTEGER interval
;
1338 if (context
== NULL
)
1341 dev_obj
= (PDEVICE_OBJECT
) context
;
1342 pdev_ext
= dev_obj
->DeviceExtension
;
1343 pdrvr_ext
= (PGENDRV_DRVR_EXTENSION
) pdev_ext
->pdriver
->driver_ext
;
1345 interval
.QuadPart
= -20000; //two ms
1349 if (dev_obj
->ReferenceCount
)
1350 KeDelayExecutionThread(KernelMode
, TRUE
, &interval
);
1353 KeDelayExecutionThread(KernelMode
, TRUE
, &interval
);
1354 if (dev_obj
->ReferenceCount
== 0)
1358 usb_dbg_print(DBGLVL_MAXIMUM
, ("gendrv_deferred_delete_device(): delete device, 0x%x\n", dev_obj
));
1360 ExAcquireFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
1361 RemoveEntryList(&pdev_ext
->dev_obj_link
);
1362 pdev_ext
->ext_drvr_entry
->ref_count
--;
1363 ExReleaseFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
1365 IoDeleteDevice(dev_obj
);
1370 gendrv_delete_device(PUSB_DEV_MANAGER dev_mgr
, PDEVICE_OBJECT dev_obj
)
1374 PGENDRV_DEVICE_EXTENSION pdev_ext
;
1377 UNICODE_STRING symb_link
;
1378 PGENDRV_DRVR_EXTENSION pdrvr_ext
;
1380 if (dev_mgr
== NULL
|| dev_obj
== 0)
1383 pdev_ext
= (PGENDRV_DEVICE_EXTENSION
) dev_obj
->DeviceExtension
;
1384 pdrvr
= pdev_ext
->pdriver
;
1385 pdrvr_ext
= (PGENDRV_DRVR_EXTENSION
) pdrvr
->driver_ext
;
1386 is_if
= (BOOLEAN
) if_dev(dev_obj
);
1388 sprintf(dev_name
, "\\DosDevices\\gendev%d", (int)pdev_ext
->dev_id
);
1390 sprintf(dev_name
, "\\DosDevices\\genifdev%d", (int)pdev_ext
->dev_id
);
1392 RtlInitString(&string
, dev_name
);
1393 RtlAnsiStringToUnicodeString(&symb_link
, &string
, TRUE
);
1394 IoDeleteSymbolicLink(&symb_link
);
1395 RtlFreeUnicodeString(&symb_link
);
1397 if (pdev_ext
->desc_buf
)
1399 usb_dbg_print(DBGLVL_MAXIMUM
, ("gendrv_delete_device(): delete desc_buf\n"));
1400 usb_free_mem(pdev_ext
->desc_buf
);
1401 pdev_ext
->desc_buf
= NULL
;
1405 if (dev_obj
->ReferenceCount
== 0)
1407 ExAcquireFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
1408 RemoveEntryList(&pdev_ext
->dev_obj_link
);
1409 pdev_ext
->ext_drvr_entry
->ref_count
--; //the ext_drvr_entry is actually in pdrvr_ext, so lock it.
1410 ExReleaseFastMutex(&pdrvr_ext
->drvr_ext_mutex
);
1412 IoDeleteDevice(dev_obj
);
1416 // borrow from umss's work routine
1417 return umss_schedule_workitem(dev_obj
, gendrv_deferred_delete_device
, NULL
, 0);
1420 // must have the drvr_ext_mutex acquired.
1421 PGENDRV_EXT_DRVR_ENTRY
1422 gendrv_alloc_ext_drvr_entry(PGENDRV_DRVR_EXTENSION pdrvr_ext
)
1425 if (pdrvr_ext
== NULL
)
1427 if (pdrvr_ext
->ext_drvr_count
== GENDRV_MAX_EXT_DRVR
)
1429 for(i
= 0; i
< GENDRV_MAX_EXT_DRVR
; i
++)
1431 if (pdrvr_ext
->ext_drvr_array
[i
].drvr_link
.Flink
== NULL
&&
1432 pdrvr_ext
->ext_drvr_array
[i
].drvr_link
.Blink
== NULL
)
1434 return &pdrvr_ext
->ext_drvr_array
[i
];
1440 // must have the drvr_ext_mutex acquired.
1442 gendrv_release_ext_drvr_entry(PGENDRV_DRVR_EXTENSION pdrvr_ext
, PGENDRV_EXT_DRVR_ENTRY pentry
)
1444 if (pdrvr_ext
== NULL
|| pentry
== NULL
)
1446 RtlZeroMemory(pentry
, sizeof(GENDRV_EXT_DRVR_ENTRY
));
1447 InitializeListHead(&pentry
->dev_list
);
1452 gendrv_open_reg_key(OUT PHANDLE handle
,
1453 IN HANDLE base_handle OPTIONAL
,
1454 IN PUNICODE_STRING keyname
, IN ACCESS_MASK desired_access
, IN BOOLEAN create
)
1457 Routine Description:
1459 Opens or creates a VOLATILE registry key using the name passed in based
1460 at the BaseHandle node.
1464 Handle - Pointer to the handle which will contain the registry key that
1467 BaseHandle - Handle to the base path from which the key must be opened.
1469 KeyName - Name of the Key that must be opened/created.
1471 DesiredAccess - Specifies the desired access that the caller needs to
1474 Create - Determines if the key is to be created if it does not exist.
1478 The function value is the final status of the operation.
1482 OBJECT_ATTRIBUTES object_attr
;
1486 // Initialize the object for the key.
1489 InitializeObjectAttributes(&object_attr
,
1490 keyname
, OBJ_CASE_INSENSITIVE
, base_handle
, (PSECURITY_DESCRIPTOR
) NULL
);
1493 // Create the key or open it, as appropriate based on the caller's
1499 return ZwCreateKey(handle
,
1501 &object_attr
, 0, (PUNICODE_STRING
) NULL
, REG_OPTION_VOLATILE
, &disposition
);
1505 return ZwOpenKey(handle
, desired_access
, &object_attr
);
1507 return STATUS_INVALID_PARAMETER
;
1511 gendrv_get_key_value(IN HANDLE KeyHandle
, IN PWSTR ValueName
, OUT PKEY_VALUE_FULL_INFORMATION
* Information
)
1514 Routine Description:
1516 This routine is invoked to retrieve the data for a registry key's value.
1517 This is done by querying the value of the key with a zero-length buffer
1518 to determine the size of the value, and then allocating a buffer and
1519 actually querying the value into the buffer.
1521 It is the responsibility of the caller to free the buffer.
1525 KeyHandle - Supplies the key handle whose value is to be queried
1527 ValueName - Supplies the null-terminated Unicode name of the value.
1529 Information - Returns a pointer to the allocated data buffer.
1533 The function value is the final status of the query operation.
1537 UNICODE_STRING unicodeString
;
1539 PKEY_VALUE_FULL_INFORMATION infoBuffer
;
1540 ULONG keyValueLength
;
1544 RtlInitUnicodeString(&unicodeString
, ValueName
);
1547 // Figure out how big the data value is so that a buffer of the
1548 // appropriate size can be allocated.
1551 status
= ZwQueryValueKey(KeyHandle
,
1552 &unicodeString
, KeyValueFullInformation
, (PVOID
) NULL
, 0, &keyValueLength
);
1553 if (status
!= STATUS_BUFFER_OVERFLOW
&& status
!= STATUS_BUFFER_TOO_SMALL
)
1559 // Allocate a buffer large enough to contain the entire key data value.
1562 infoBuffer
= usb_alloc_mem(NonPagedPool
, keyValueLength
);
1565 return STATUS_INSUFFICIENT_RESOURCES
;
1569 // Query the data for the key value.
1572 status
= ZwQueryValueKey(KeyHandle
,
1574 KeyValueFullInformation
, infoBuffer
, keyValueLength
, &keyValueLength
);
1575 if (!NT_SUCCESS(status
))
1577 usb_free_mem(infoBuffer
);
1582 // Everything worked, so simply return the address of the allocated
1583 // buffer to the caller, who is now responsible for freeing it.
1586 *Information
= infoBuffer
;
1587 return STATUS_SUCCESS
;
1591 gendrv_startio(IN PDEVICE_OBJECT dev_obj
, IN PIRP irp
)
1593 PIO_STACK_LOCATION irp_stack
;
1595 PUSB_DEV_MANAGER dev_mgr
;
1596 USE_NON_PENDING_IRQL
;
1598 if (dev_obj
== NULL
|| irp
== NULL
)
1601 // standard process from walter oney
1602 IoAcquireCancelSpinLock(&old_irql
);
1603 if (irp
!= dev_obj
->CurrentIrp
|| irp
->Cancel
)
1605 // already move on to other irp
1606 IoReleaseCancelSpinLock(old_irql
);
1611 (void)IoSetCancelRoutine(irp
, NULL
);
1613 IoReleaseCancelSpinLock(old_irql
);
1615 irp
->IoStatus
.Information
= 0;
1617 irp_stack
= IoGetCurrentIrpStackLocation(irp
);
1618 ctrl_code
= irp_stack
->Parameters
.DeviceIoControl
.IoControlCode
;
1619 dev_mgr
= ((PDEVEXT_HEADER
) dev_obj
->DeviceExtension
)->dev_mgr
;
1621 if (irp_stack
->MajorFunction
!= IRP_MJ_DEVICE_CONTROL
&&
1622 irp_stack
->MajorFunction
!= IRP_MJ_INTERNAL_DEVICE_CONTROL
)
1624 GENDRV_COMPLETE_START_IO(dev_obj
, STATUS_INVALID_DEVICE_REQUEST
, irp
);
1629 case IOCTL_SUBMIT_URB_RD
:
1630 case IOCTL_SUBMIT_URB_NOIO
:
1631 case IOCTL_SUBMIT_URB_WR
:
1634 ULONG endp_idx
, if_idx
, user_buffer_length
= 0;
1635 PUCHAR user_buffer
= NULL
;
1637 DEV_HANDLE endp_handle
;
1638 PUSB_ENDPOINT pendp
;
1642 if (irp_stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(URB
))
1644 GENDRV_COMPLETE_START_IO(dev_obj
, STATUS_INVALID_PARAMETER
, irp
);
1647 purb
= (PURB
) irp
->AssociatedIrp
.SystemBuffer
;
1648 if (ctrl_code
== IOCTL_SUBMIT_URB_RD
|| ctrl_code
== IOCTL_SUBMIT_URB_WR
)
1650 if (irp_stack
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
)
1652 user_buffer
= MmGetSystemAddressForMdl(irp
->MdlAddress
);
1653 user_buffer_length
= irp_stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
1654 if (user_buffer_length
== 0)
1655 GENDRV_COMPLETE_START_IO(dev_obj
, STATUS_INVALID_PARAMETER
, irp
);
1659 if (purb
->data_buffer
== NULL
|| purb
->data_length
== 0)
1660 GENDRV_COMPLETE_START_IO(dev_obj
, STATUS_INVALID_PARAMETER
, irp
);
1661 user_buffer
= purb
->data_buffer
;
1662 user_buffer_length
= purb
->data_length
;
1666 purb
->reference
= 0;
1667 endp_handle
= purb
->endp_handle
;
1669 if (usb_query_and_lock_dev(dev_mgr
, endp_handle
& ~0xffff, &pdev
) != STATUS_SUCCESS
)
1671 GENDRV_COMPLETE_START_IO(dev_obj
, STATUS_IO_DEVICE_ERROR
, irp
);
1674 lock_dev(pdev
, FALSE
);
1675 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
|| (dev_state(pdev
) < USB_DEV_STATE_ADDRESSED
))
1678 status
= STATUS_INVALID_DEVICE_STATE
;
1682 if (dev_state(pdev
) == USB_DEV_STATE_ADDRESSED
&& !default_endp_handle(endp_handle
))
1684 status
= STATUS_DEVICE_NOT_READY
;
1688 if_idx
= if_idx_from_handle(endp_handle
);
1689 endp_idx
= endp_idx_from_handle(endp_handle
);
1691 //if_idx exceeds the upper limit
1692 if (pdev
->usb_config
)
1694 if (if_idx
>= pdev
->usb_config
->if_count
1695 || endp_idx
>= pdev
->usb_config
->interf
[if_idx
].endp_count
)
1697 if (!default_endp_handle(endp_handle
))
1699 status
= STATUS_INVALID_DEVICE_STATE
;
1705 endp_from_handle(pdev
, endp_handle
, pendp
);
1707 // FIXME: don't know what evil will let loose
1708 if (endp_type(pendp
) != USB_ENDPOINT_XFER_CONTROL
)
1710 if (user_buffer_length
> 16)
1712 status
= STATUS_INVALID_PARAMETER
;
1718 purb
->context
= dev_mgr
;
1719 purb
->reference
= ctrl_code
;
1721 if (ctrl_code
== IOCTL_SUBMIT_URB_RD
|| ctrl_code
== IOCTL_SUBMIT_URB_WR
)
1723 purb
->data_buffer
= user_buffer
;
1724 purb
->data_length
= user_buffer_length
;
1725 purb
->completion
= disp_urb_completion
;
1729 purb
->completion
= disp_noio_urb_completion
;
1732 unlock_dev(pdev
, FALSE
);
1735 // we have to register irp before the urb is scheduled to
1736 // avoid race condition.
1738 ASSERT(dev_mgr_register_irp(dev_mgr
, irp
, purb
));
1740 // the irp can not be canceled at this point, since it is
1741 // now the current irp and not in any urb queue. dev_mgr_cancel_irp
1742 // can not find it and simply return.
1744 // FIXME: there is a time window that the irp is registered and
1745 // the urb is not queued. In the meantime, the cancel
1746 // request may come and cause the irp removed from the irp
1747 // queue while fail to cancel due to urb not in any urb queue .
1748 // Thus from that point on, the irp can not be canceled till it
1749 // is completed or hanging there forever.
1751 status
= usb_submit_urb(dev_mgr
, purb
);
1752 if (status
!= STATUS_PENDING
)
1754 // unmark the pending bit
1755 IoGetCurrentIrpStackLocation((irp
))->Control
&= ~SL_PENDING_RETURNED
;
1756 dev_mgr_remove_irp(dev_mgr
, irp
);
1758 usb_unlock_dev(pdev
);
1759 if (status
!= STATUS_PENDING
)
1761 irp
->IoStatus
.Status
= status
;
1762 GENDRV_COMPLETE_START_IO(dev_obj
, status
, irp
);
1767 unlock_dev(pdev
, FALSE
);
1768 usb_unlock_dev(pdev
);
1769 irp
->IoStatus
.Information
= 0;
1770 GENDRV_COMPLETE_START_IO(dev_obj
, status
, irp
);
1773 GENDRV_COMPLETE_START_IO(dev_obj
, STATUS_INVALID_DEVICE_REQUEST
, irp
);
1777 gendrv_clean_up_queued_irps(PDEVICE_OBJECT dev_obj
)
1779 // called when device may not function or about to be removed, need cleanup
1782 PKDEVICE_QUEUE_ENTRY packet
;
1783 LIST_ENTRY cancel_irps
, *pthis
;
1786 // cancel all the irps in the queue
1788 if (dev_obj
== NULL
)
1791 InitializeListHead(&cancel_irps
);
1793 // remove the irps from device queue
1794 IoAcquireCancelSpinLock(&cancelIrql
);
1795 cur_irp
= dev_obj
->CurrentIrp
;
1796 while ((packet
= KeRemoveDeviceQueue(&dev_obj
->DeviceQueue
)))
1798 irp
= struct_ptr(packet
, IRP
, Tail
.Overlay
.DeviceQueueEntry
);
1799 InsertTailList(&cancel_irps
, &irp
->Tail
.Overlay
.DeviceQueueEntry
.DeviceListEntry
);
1801 IoReleaseCancelSpinLock(cancelIrql
);
1803 // cancel the irps in process
1804 // we did not cancel the current irp, it will be done by hcd when
1805 // disconnect is detected.
1806 // remove_irp_from_list( &dev_mgr->irp_list, cur_irp, dev_mgr );
1808 while (IsListEmpty(&cancel_irps
) == FALSE
)
1810 pthis
= RemoveHeadList(&cancel_irps
);
1811 irp
= struct_ptr(pthis
, IRP
, Tail
.Overlay
.DeviceQueueEntry
.DeviceListEntry
);
1812 irp
->IoStatus
.Information
= 0;
1813 irp
->IoStatus
.Status
= STATUS_CANCELLED
;
1814 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
1821 gendrv_cancel_queued_irp(PDEVICE_OBJECT dev_obj
, PIRP pirp
)
1823 // cancel routine for irps queued in the device queue
1824 PUSB_DEV_MANAGER dev_mgr
;
1825 PDEVEXT_HEADER pdev_ext_hdr
;
1827 pdev_ext_hdr
= (PDEVEXT_HEADER
) dev_obj
->DeviceExtension
;
1828 dev_mgr
= pdev_ext_hdr
->dev_mgr
;
1830 if (dev_obj
->CurrentIrp
== pirp
)
1832 // just before start_io set the cancel routine to null
1833 IoReleaseCancelSpinLock(pirp
->CancelIrql
);
1834 // we did not IoStartNextPacket, leave it for dev_mgr_cancel_irp, that
1835 // is user have to call CancelIo again.
1839 KeRemoveEntryDeviceQueue(&dev_obj
->DeviceQueue
, &pirp
->Tail
.Overlay
.DeviceQueueEntry
);
1840 IoReleaseCancelSpinLock(pirp
->CancelIrql
);
1842 pirp
->IoStatus
.Information
= 0;
1843 pirp
->IoStatus
.Status
= STATUS_CANCELLED
;
1844 IoCompleteRequest(pirp
, IO_NO_INCREMENT
);
1845 // the device queue is moved on, no need to call IoStartNextPacket