2 * dmgrdisp.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 #include "usbdriver.h"
25 disp_urb_completion(PURB purb
, PVOID context
)
27 PUSB_DEV_MANAGER dev_mgr
;
30 PDEVEXT_HEADER dev_hdr
;
32 UNREFERENCED_PARAMETER(context
);
37 ctrl_code
= (ULONG
) purb
->reference
;
38 dev_mgr
= (PUSB_DEV_MANAGER
) purb
->context
;
40 // at this stage, the irp can not be canceled since the urb
41 // won't be found in any queue and the irp is not in any queue.
42 // see line 4685 in hub.c
43 // Sometimes, it may be very fast to enter this routine before
44 // the dev_mgr_register_irp to be called in dispatch routine in
45 // usb2.0 environment as
46 // we did in usb1.1 driver. We can not simply add a loop to wait
47 // for the dispatch thread to add the irp to the list, because
48 // here we are at DPC level higher than the dispatch thread
49 // running level. And the solution is to register the irp
50 // before the urb is scheduled instead of registering it after
54 PIO_STACK_LOCATION irp_stack
;
55 dev_mgr_remove_irp(dev_mgr
, purb
->pirp
);
57 status
= purb
->status
;
58 irp_stack
= IoGetCurrentIrpStackLocation(purb
->pirp
);
60 if (purb
->status
!= STATUS_SUCCESS
)
62 purb
->pirp
->IoStatus
.Information
= 0;
66 // currently only IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL
67 // are allowed. And we do not need to set information
68 // for IRP_MJ_INTERNAL_DEVICE_CONTROL
69 if (irp_stack
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
)
70 purb
->pirp
->IoStatus
.Information
= purb
->data_length
;
72 purb
->pirp
->IoStatus
.Status
= status
;
75 dev_hdr
= irp_stack
->DeviceObject
->DeviceExtension
;
76 if (dev_hdr
->start_io
)
78 IoStartNextPacket(irp_stack
->DeviceObject
, TRUE
);
81 IoCompleteRequest(purb
->pirp
, IO_NO_INCREMENT
);
87 disp_noio_urb_completion(PURB purb
, PVOID context
)
89 PUSB_CTRL_SETUP_PACKET psetup
;
91 PUSB_DEV_MANAGER dev_mgr
;
92 NTSTATUS status
= STATUS_SUCCESS
;
93 PIO_STACK_LOCATION irp_stack
;
94 PDEVEXT_HEADER dev_hdr
;
99 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
101 if ((psetup
->bmRequestType
== 0x2) &&
102 (psetup
->bRequest
== USB_REQ_CLEAR_FEATURE
) &&
103 (psetup
->wIndex
== 0)) //reset pipe
105 purb2
= (PURB
) context
;
112 if (purb2
->pirp
== NULL
)
115 dev_mgr
= (PUSB_DEV_MANAGER
) purb2
->context
;
117 dev_mgr_remove_irp(dev_mgr
, purb2
->pirp
);
119 if (purb
->status
!= STATUS_SUCCESS
)
120 status
= STATUS_IO_DEVICE_ERROR
;
122 purb2
->pirp
->IoStatus
.Information
= 0;
123 purb2
->pirp
->IoStatus
.Status
= status
;
124 irp_stack
= IoGetCurrentIrpStackLocation(purb
->pirp
);
127 dev_hdr
= irp_stack
->DeviceObject
->DeviceExtension
;
128 if (dev_hdr
->start_io
)
130 IoStartNextPacket(irp_stack
->DeviceObject
, TRUE
);
133 IoCompleteRequest(purb2
->pirp
, IO_NO_INCREMENT
);
137 //this function is called by the hcd's
138 //dispatch when they have done their job.
140 dev_mgr_dispatch(IN PUSB_DEV_MANAGER dev_mgr
, IN PIRP irp
)
142 PIO_STACK_LOCATION irp_stack
;
145 USE_NON_PENDING_IRQL
;
150 EXIT_DISPATCH(STATUS_INVALID_PARAMETER
, irp
);
153 status
= STATUS_SUCCESS
;
154 irp_stack
= IoGetCurrentIrpStackLocation(irp
);
155 ctrl_code
= irp_stack
->Parameters
.DeviceIoControl
.IoControlCode
;
157 switch (irp_stack
->MajorFunction
)
161 InterlockedIncrement(&dev_mgr
->open_count
);
162 EXIT_DISPATCH(STATUS_SUCCESS
, irp
);
166 InterlockedDecrement(&dev_mgr
->open_count
);
167 EXIT_DISPATCH(STATUS_SUCCESS
, irp
);
169 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
170 case IRP_MJ_DEVICE_CONTROL
:
174 case IOCTL_GET_DEV_COUNT
:
178 irp
->IoStatus
.Information
= 0;
179 if (irp_stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(LONG
))
181 EXIT_DISPATCH(STATUS_INVALID_PARAMETER
, irp
);
184 KeAcquireSpinLock(&dev_mgr
->dev_list_lock
, &old_irql
);
185 dev_count
= usb_count_list(&dev_mgr
->dev_list
);
186 KeReleaseSpinLock(&dev_mgr
->dev_list_lock
, old_irql
);
188 *((PLONG
) irp
->AssociatedIrp
.SystemBuffer
) = dev_count
;
189 irp
->IoStatus
.Information
= sizeof(LONG
);
190 EXIT_DISPATCH(STATUS_SUCCESS
, irp
);
192 case IOCTL_ENUM_DEVICES
:
194 PLIST_ENTRY pthis
, pnext
;
195 LONG dev_count
, array_size
, i
, j
= 0;
197 PENUM_DEV_ARRAY peda
;
199 irp
->IoStatus
.Information
= 0;
200 if (irp_stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(LONG
))
202 EXIT_DISPATCH(STATUS_INVALID_PARAMETER
, irp
);
204 if (irp_stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(ENUM_DEV_ARRAY
))
206 EXIT_DISPATCH(STATUS_INVALID_PARAMETER
, irp
);
208 array_size
= *((PULONG
) irp
->AssociatedIrp
.SystemBuffer
);
210 KeAcquireSpinLock(&dev_mgr
->dev_list_lock
, &old_irql
);
211 dev_count
= usb_count_list(&dev_mgr
->dev_list
);
212 dev_count
= dev_count
> array_size
? array_size
: dev_count
;
213 peda
= (PENUM_DEV_ARRAY
) irp
->AssociatedIrp
.SystemBuffer
;
214 RtlZeroMemory(peda
, sizeof(ENUM_DEV_ARRAY
) + (dev_count
- 1) * sizeof(ENUM_DEV_ELEMENT
));
218 ListFirst(&dev_mgr
->dev_list
, pthis
);
219 for(i
= 0, j
= 0; i
< dev_count
; i
++)
221 pdev
= struct_ptr(pthis
, USB_DEV
, dev_link
);
222 ListNext(&dev_mgr
->dev_list
, pthis
, pnext
);
225 lock_dev(pdev
, FALSE
);
226 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
228 unlock_dev(pdev
, FALSE
);
232 if (dev_state(pdev
) < USB_DEV_STATE_ADDRESSED
)
234 unlock_dev(pdev
, FALSE
);
238 peda
->dev_arr
[i
].dev_handle
= (pdev
->dev_id
<< 16);
239 //may not get the desc yet
240 if (pdev
->pusb_dev_desc
)
242 peda
->dev_arr
[i
].product_id
= pdev
->pusb_dev_desc
->idProduct
;
243 peda
->dev_arr
[i
].vendor_id
= pdev
->pusb_dev_desc
->idVendor
;
247 peda
->dev_arr
[i
].product_id
= 0xffff;
248 peda
->dev_arr
[i
].vendor_id
= 0xffff;
250 peda
->dev_arr
[i
].dev_addr
= pdev
->dev_addr
;
251 unlock_dev(pdev
, FALSE
);
255 peda
->dev_count
= dev_count
? j
: 0;
256 KeReleaseSpinLock(&dev_mgr
->dev_list_lock
, old_irql
);
258 irp
->IoStatus
.Information
=
259 sizeof(ENUM_DEV_ARRAY
) + (dev_count
- 1) * sizeof(ENUM_DEV_ELEMENT
);
260 EXIT_DISPATCH(STATUS_SUCCESS
, irp
);
262 case IOCTL_GET_DEV_DESC
:
264 GET_DEV_DESC_REQ gddr
;
265 PUSB_DESC_HEADER pusb_desc_header
;
269 if (irp_stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(GET_DEV_DESC_REQ
))
271 EXIT_DISPATCH(STATUS_INVALID_PARAMETER
, irp
);
274 if (irp_stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< 8)
276 EXIT_DISPATCH(STATUS_INVALID_PARAMETER
, irp
);
279 status
= STATUS_SUCCESS
;
280 buf_size
= irp_stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
281 RtlCopyMemory(&gddr
, irp
->AssociatedIrp
.SystemBuffer
, sizeof(GET_DEV_DESC_REQ
));
282 pusb_desc_header
= irp
->AssociatedIrp
.SystemBuffer
;
284 if (gddr
.desc_type
!= USB_DT_CONFIG
&& gddr
.desc_type
!= USB_DT_DEVICE
)
286 EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST
, irp
);
289 if (usb_query_and_lock_dev(dev_mgr
, gddr
.dev_handle
, &pdev
) != STATUS_SUCCESS
)
291 EXIT_DISPATCH(STATUS_IO_DEVICE_ERROR
, irp
);
294 lock_dev(pdev
, FALSE
);
295 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
297 status
= STATUS_INVALID_DEVICE_STATE
;
300 if (dev_state(pdev
) != USB_DEV_STATE_ADDRESSED
&&
301 dev_state(pdev
) != USB_DEV_STATE_CONFIGURED
)
303 status
= STATUS_DEVICE_NOT_READY
;
307 if (pdev
->pusb_dev_desc
== NULL
)
309 status
= STATUS_DEVICE_NOT_READY
;
313 if (gddr
.desc_type
== USB_DT_DEVICE
)
315 RtlCopyMemory(pusb_desc_header
,
317 buf_size
> sizeof(USB_DEVICE_DESC
)
318 ? sizeof(USB_DEVICE_DESC
) : buf_size
);
320 irp
->IoStatus
.Information
=
321 buf_size
>= sizeof(USB_DEVICE_DESC
) ? sizeof(USB_DEVICE_DESC
) : buf_size
;
323 else if (gddr
.desc_type
== USB_DT_CONFIG
)
325 PUSB_CONFIGURATION_DESC pusb_config_desc
;
326 if (pdev
->pusb_dev_desc
->bNumConfigurations
<= gddr
.desc_idx
)
328 status
= STATUS_INVALID_PARAMETER
;
332 pusb_config_desc
= usb_find_config_desc_by_idx((PUCHAR
) & pdev
->pusb_dev_desc
[1],
334 pdev
->pusb_dev_desc
->
337 if (pusb_config_desc
== NULL
)
339 status
= STATUS_DEVICE_NOT_READY
;
343 RtlCopyMemory(pusb_desc_header
,
345 buf_size
>= pusb_config_desc
->wTotalLength
346 ? pusb_config_desc
->wTotalLength
: buf_size
);
348 irp
->IoStatus
.Information
=
349 buf_size
>= pusb_config_desc
->wTotalLength
350 ? pusb_config_desc
->wTotalLength
: buf_size
;
353 unlock_dev(pdev
, FALSE
);
354 usb_unlock_dev(pdev
);
355 EXIT_DISPATCH(status
, irp
);
357 case IOCTL_SUBMIT_URB_RD
:
358 case IOCTL_SUBMIT_URB_WR
:
359 case IOCTL_SUBMIT_URB_NOIO
:
362 ULONG endp_idx
, if_idx
, user_buffer_length
= 0;
363 PUCHAR user_buffer
= NULL
;
365 DEV_HANDLE endp_handle
;
368 if (irp_stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(URB
))
370 EXIT_DISPATCH(STATUS_INVALID_PARAMETER
, irp
);
373 purb
= (PURB
) irp
->AssociatedIrp
.SystemBuffer
;
374 endp_handle
= purb
->endp_handle
;
376 if (ctrl_code
== IOCTL_SUBMIT_URB_RD
|| ctrl_code
== IOCTL_SUBMIT_URB_WR
)
378 if (irp_stack
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
)
380 user_buffer_length
= irp_stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
381 if (user_buffer_length
== 0)
382 EXIT_DISPATCH(STATUS_INVALID_PARAMETER
, irp
);
383 user_buffer
= MmGetSystemAddressForMdl(irp
->MdlAddress
);
387 if (purb
->data_buffer
== NULL
|| purb
->data_length
== 0)
388 EXIT_DISPATCH(STATUS_INVALID_PARAMETER
, irp
);
389 user_buffer_length
= purb
->data_length
;
390 user_buffer
= purb
->data_buffer
;
394 if (usb_query_and_lock_dev(dev_mgr
, endp_handle
& ~0xffff, &pdev
) != STATUS_SUCCESS
)
396 EXIT_DISPATCH(STATUS_IO_DEVICE_ERROR
, irp
);
400 lock_dev(pdev
, FALSE
);
401 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
|| (dev_state(pdev
) < USB_DEV_STATE_ADDRESSED
))
404 status
= STATUS_INVALID_DEVICE_STATE
;
408 if (dev_state(pdev
) == USB_DEV_STATE_ADDRESSED
&& !default_endp_handle(endp_handle
))
410 status
= STATUS_DEVICE_NOT_READY
;
414 if_idx
= if_idx_from_handle(endp_handle
);
415 endp_idx
= endp_idx_from_handle(endp_handle
);
417 //if_idx exceeds the upper limit
418 if (pdev
->usb_config
)
420 if (if_idx
>= pdev
->usb_config
->if_count
421 || endp_idx
>= pdev
->usb_config
->interf
[if_idx
].endp_count
)
423 if (!default_endp_handle(endp_handle
))
425 status
= STATUS_INVALID_DEVICE_STATE
;
431 endp_from_handle(pdev
, endp_handle
, pendp
);
432 // FIXME: don't know what evil will let loose
433 if (endp_type(pendp
) != USB_ENDPOINT_XFER_CONTROL
)
435 if (user_buffer_length
> 0x100000)
437 status
= STATUS_INVALID_PARAMETER
;
443 purb
->context
= dev_mgr
;
444 purb
->reference
= ctrl_code
;
446 if (ctrl_code
== IOCTL_SUBMIT_URB_RD
|| ctrl_code
== IOCTL_SUBMIT_URB_WR
)
448 if (ctrl_code
== IOCTL_SUBMIT_URB_RD
)
449 KeFlushIoBuffers(irp
->MdlAddress
, TRUE
, TRUE
);
451 KeFlushIoBuffers(irp
->MdlAddress
, FALSE
, TRUE
);
453 purb
->data_buffer
= user_buffer
;
454 purb
->data_length
= user_buffer_length
;
455 purb
->completion
= disp_urb_completion
;
459 purb
->completion
= disp_noio_urb_completion
;
462 unlock_dev(pdev
, FALSE
);
464 // we have to mark irp before the urb is scheduled to
465 // avoid race condition
466 IoMarkIrpPending(irp
);
467 ASSERT(dev_mgr_register_irp(dev_mgr
, irp
, purb
));
468 status
= usb_submit_urb(dev_mgr
, purb
);
469 if (status
!= STATUS_PENDING
)
471 IoGetCurrentIrpStackLocation((irp
))->Control
&= ~SL_PENDING_RETURNED
;
472 dev_mgr_remove_irp(dev_mgr
, irp
);
474 usb_unlock_dev(pdev
);
475 if (status
!= STATUS_PENDING
)
477 irp
->IoStatus
.Status
= status
;
478 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
482 unlock_dev(pdev
, FALSE
);
483 usb_unlock_dev(pdev
);
484 irp
->IoStatus
.Information
= 0;
485 EXIT_DISPATCH(status
, irp
);
489 irp
->IoStatus
.Information
= 0;
490 EXIT_DISPATCH(STATUS_NOT_IMPLEMENTED
, irp
);
496 irp
->IoStatus
.Information
= 0;
500 EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST
, irp
);
503 /*#define IOCTL_GET_DEV_COUNT CTL_CODE( FILE_HCD_DEV_TYPE, 4093, METHOD_BUFFERED, FILE_ANY_ACCESS )
504 //input_buffer and input_buffer_length is zero, output_buffer is to receive a dword value of the
505 //dev count, output_buffer_length must be no less than sizeof( long ).
507 #define IOCTL_ENUM_DEVICES CTL_CODE( FILE_HCD_DEV_TYPE, 4094, METHOD_BUFFERED, FILE_ANY_ACCESS )
508 //input_buffer is a dword value to indicate the count of elements in the array
509 //input_buffer_length is sizeof( long ), output_buffer is to receive a
510 //structure ENUM_DEV_ARRAY where dev_count is the elements hold in this array.
512 #define IOCTL_GET_DEV_DESC CTL_CODE( FILE_HCD_DEV_TYPE, 4095, METHOD_BUFFERED, FILE_ANY_ACCESS )
513 //input_buffer is a structure GET_DEV_DESC_REQ, and the input_buffer_length is
514 //no less than sizeof( input_buffer ), output_buffer is a buffer to receive the
515 //requested dev's desc, and output_buffer_length specifies the length of the
518 #define IOCTL_SUBMIT_URB_RD CTL_CODE( FILE_HCD_DEV_TYPE, 4096, METHOD_IN_DIRECT, FILE_ANY_ACCESS )
519 #define IOCTL_SUBMIT_URB_WR CTL_CODE( FILE_HCD_DEV_TYPE, 4097, METHOD_OUT_DIRECT, FILE_ANY_ACCESS )
520 // input_buffer is a URB, and input_buffer_length is equal to or greater than
521 // sizeof( URB ); the output_buffer is a buffer to receive data from or send data
522 // to device. only the following urb fields can be accessed, others must be zeroed.
523 // DEV_HANDLE endp_handle;
524 // UCHAR setup_packet[8]; //for control pipe
525 // the choosing of IOCTL_SUBMIT_URB_RD or IOCTL_SUBMIT_URB_WR should be determined
526 // by the current URB, for example, a request string from device will use XXX_RD,
527 // and a write to the bulk endpoint will use XXX_WR
529 #define IOCTL_SUBMIT_URB_NOIO CTL_CODE( FILE_HCD_DEV_TYPE, 4098, METHOD_BUFFERED, FILE_ANY_ACCESS )
530 // input_buffer is a URB, and input_buffer_length is equal to or greater than
531 // sizeof( URB ); the output_buffer is null and no output_buffer_length,
532 // only the following fields in urb can be accessed, others must be zeroed.
533 // DEV_HANDLE endp_handle;
534 // UCHAR setup_packet[8]; //for control pipe