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
;
147 if (dev_mgr
== NULL
|| irp
== NULL
)
149 EXIT_DISPATCH(STATUS_INVALID_PARAMETER
, irp
);
152 status
= STATUS_SUCCESS
;
153 irp_stack
= IoGetCurrentIrpStackLocation(irp
);
154 ctrl_code
= irp_stack
->Parameters
.DeviceIoControl
.IoControlCode
;
156 switch (irp_stack
->MajorFunction
)
160 InterlockedIncrement(&dev_mgr
->open_count
);
161 EXIT_DISPATCH(STATUS_SUCCESS
, irp
);
165 InterlockedDecrement(&dev_mgr
->open_count
);
166 EXIT_DISPATCH(STATUS_SUCCESS
, irp
);
168 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
169 case IRP_MJ_DEVICE_CONTROL
:
173 case IOCTL_GET_DEV_COUNT
:
177 irp
->IoStatus
.Information
= 0;
178 if (irp_stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(LONG
))
180 EXIT_DISPATCH(STATUS_INVALID_PARAMETER
, irp
);
183 KeAcquireSpinLock(&dev_mgr
->dev_list_lock
, &old_irql
);
184 dev_count
= usb_count_list(&dev_mgr
->dev_list
);
185 KeReleaseSpinLock(&dev_mgr
->dev_list_lock
, old_irql
);
187 *((PLONG
) irp
->AssociatedIrp
.SystemBuffer
) = dev_count
;
188 irp
->IoStatus
.Information
= sizeof(LONG
);
189 EXIT_DISPATCH(STATUS_SUCCESS
, irp
);
191 case IOCTL_ENUM_DEVICES
:
193 PLIST_ENTRY pthis
, pnext
;
194 LONG dev_count
, array_size
, i
, j
= 0;
196 PENUM_DEV_ARRAY peda
;
198 irp
->IoStatus
.Information
= 0;
199 if (irp_stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(LONG
))
201 EXIT_DISPATCH(STATUS_INVALID_PARAMETER
, irp
);
203 if (irp_stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(ENUM_DEV_ARRAY
))
205 EXIT_DISPATCH(STATUS_INVALID_PARAMETER
, irp
);
207 array_size
= *((PULONG
) irp
->AssociatedIrp
.SystemBuffer
);
209 KeAcquireSpinLock(&dev_mgr
->dev_list_lock
, &old_irql
);
210 dev_count
= usb_count_list(&dev_mgr
->dev_list
);
211 dev_count
= dev_count
> array_size
? array_size
: dev_count
;
212 peda
= (PENUM_DEV_ARRAY
) irp
->AssociatedIrp
.SystemBuffer
;
213 RtlZeroMemory(peda
, sizeof(ENUM_DEV_ARRAY
) + (dev_count
- 1) * sizeof(ENUM_DEV_ELEMENT
));
217 ListFirst(&dev_mgr
->dev_list
, pthis
);
218 for(i
= 0, j
= 0; i
< dev_count
; i
++)
220 pdev
= struct_ptr(pthis
, USB_DEV
, dev_link
);
221 ListNext(&dev_mgr
->dev_list
, pthis
, pnext
);
224 lock_dev(pdev
, FALSE
);
225 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
227 unlock_dev(pdev
, FALSE
);
231 if (dev_state(pdev
) < USB_DEV_STATE_ADDRESSED
)
233 unlock_dev(pdev
, FALSE
);
237 peda
->dev_arr
[i
].dev_handle
= (pdev
->dev_id
<< 16);
238 //may not get the desc yet
239 if (pdev
->pusb_dev_desc
)
241 peda
->dev_arr
[i
].product_id
= pdev
->pusb_dev_desc
->idProduct
;
242 peda
->dev_arr
[i
].vendor_id
= pdev
->pusb_dev_desc
->idVendor
;
246 peda
->dev_arr
[i
].product_id
= 0xffff;
247 peda
->dev_arr
[i
].vendor_id
= 0xffff;
249 peda
->dev_arr
[i
].dev_addr
= pdev
->dev_addr
;
250 unlock_dev(pdev
, FALSE
);
254 peda
->dev_count
= dev_count
? j
: 0;
255 KeReleaseSpinLock(&dev_mgr
->dev_list_lock
, old_irql
);
257 irp
->IoStatus
.Information
=
258 sizeof(ENUM_DEV_ARRAY
) + (dev_count
- 1) * sizeof(ENUM_DEV_ELEMENT
);
259 EXIT_DISPATCH(STATUS_SUCCESS
, irp
);
261 case IOCTL_GET_DEV_DESC
:
263 GET_DEV_DESC_REQ gddr
;
264 PUSB_DESC_HEADER pusb_desc_header
;
268 if (irp_stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(GET_DEV_DESC_REQ
))
270 EXIT_DISPATCH(STATUS_INVALID_PARAMETER
, irp
);
273 if (irp_stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< 8)
275 EXIT_DISPATCH(STATUS_INVALID_PARAMETER
, irp
);
278 status
= STATUS_SUCCESS
;
279 buf_size
= irp_stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
280 RtlCopyMemory(&gddr
, irp
->AssociatedIrp
.SystemBuffer
, sizeof(GET_DEV_DESC_REQ
));
281 pusb_desc_header
= irp
->AssociatedIrp
.SystemBuffer
;
283 if (gddr
.desc_type
!= USB_DT_CONFIG
&& gddr
.desc_type
!= USB_DT_DEVICE
)
285 EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST
, irp
);
288 if (usb_query_and_lock_dev(dev_mgr
, gddr
.dev_handle
, &pdev
) != STATUS_SUCCESS
)
290 EXIT_DISPATCH(STATUS_IO_DEVICE_ERROR
, irp
);
293 lock_dev(pdev
, FALSE
);
294 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
296 status
= STATUS_INVALID_DEVICE_STATE
;
299 if (dev_state(pdev
) != USB_DEV_STATE_ADDRESSED
&&
300 dev_state(pdev
) != USB_DEV_STATE_CONFIGURED
)
302 status
= STATUS_DEVICE_NOT_READY
;
306 if (pdev
->pusb_dev_desc
== NULL
)
308 status
= STATUS_DEVICE_NOT_READY
;
312 if (gddr
.desc_type
== USB_DT_DEVICE
)
314 RtlCopyMemory(pusb_desc_header
,
316 buf_size
> sizeof(USB_DEVICE_DESC
)
317 ? sizeof(USB_DEVICE_DESC
) : buf_size
);
319 irp
->IoStatus
.Information
=
320 buf_size
>= sizeof(USB_DEVICE_DESC
) ? sizeof(USB_DEVICE_DESC
) : buf_size
;
322 else if (gddr
.desc_type
== USB_DT_CONFIG
)
324 PUSB_CONFIGURATION_DESC pusb_config_desc
;
325 if (pdev
->pusb_dev_desc
->bNumConfigurations
<= gddr
.desc_idx
)
327 status
= STATUS_INVALID_PARAMETER
;
331 pusb_config_desc
= usb_find_config_desc_by_idx((PUCHAR
) & pdev
->pusb_dev_desc
[1],
333 pdev
->pusb_dev_desc
->
336 if (pusb_config_desc
== NULL
)
338 status
= STATUS_DEVICE_NOT_READY
;
342 RtlCopyMemory(pusb_desc_header
,
344 buf_size
>= pusb_config_desc
->wTotalLength
345 ? pusb_config_desc
->wTotalLength
: buf_size
);
347 irp
->IoStatus
.Information
=
348 buf_size
>= pusb_config_desc
->wTotalLength
349 ? pusb_config_desc
->wTotalLength
: buf_size
;
352 unlock_dev(pdev
, FALSE
);
353 usb_unlock_dev(pdev
);
354 EXIT_DISPATCH(status
, irp
);
356 case IOCTL_SUBMIT_URB_RD
:
357 case IOCTL_SUBMIT_URB_WR
:
358 case IOCTL_SUBMIT_URB_NOIO
:
361 ULONG endp_idx
, if_idx
, user_buffer_length
= 0;
362 PUCHAR user_buffer
= NULL
;
364 DEV_HANDLE endp_handle
;
367 if (irp_stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(URB
))
369 EXIT_DISPATCH(STATUS_INVALID_PARAMETER
, irp
);
372 purb
= (PURB
) irp
->AssociatedIrp
.SystemBuffer
;
373 endp_handle
= purb
->endp_handle
;
375 if (ctrl_code
== IOCTL_SUBMIT_URB_RD
|| ctrl_code
== IOCTL_SUBMIT_URB_WR
)
377 if (irp_stack
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
)
379 user_buffer_length
= irp_stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
380 if (user_buffer_length
== 0)
381 EXIT_DISPATCH(STATUS_INVALID_PARAMETER
, irp
);
382 user_buffer
= MmGetSystemAddressForMdl(irp
->MdlAddress
);
386 if (purb
->data_buffer
== NULL
|| purb
->data_length
== 0)
387 EXIT_DISPATCH(STATUS_INVALID_PARAMETER
, irp
);
388 user_buffer_length
= purb
->data_length
;
389 user_buffer
= purb
->data_buffer
;
393 if (usb_query_and_lock_dev(dev_mgr
, endp_handle
& ~0xffff, &pdev
) != STATUS_SUCCESS
)
395 EXIT_DISPATCH(STATUS_IO_DEVICE_ERROR
, irp
);
399 lock_dev(pdev
, FALSE
);
400 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
|| (dev_state(pdev
) < USB_DEV_STATE_ADDRESSED
))
403 status
= STATUS_INVALID_DEVICE_STATE
;
407 if (dev_state(pdev
) == USB_DEV_STATE_ADDRESSED
&& !default_endp_handle(endp_handle
))
409 status
= STATUS_DEVICE_NOT_READY
;
413 if_idx
= if_idx_from_handle(endp_handle
);
414 endp_idx
= endp_idx_from_handle(endp_handle
);
416 //if_idx exceeds the upper limit
417 if (pdev
->usb_config
)
419 if (if_idx
>= pdev
->usb_config
->if_count
420 || endp_idx
>= pdev
->usb_config
->interf
[if_idx
].endp_count
)
422 if (!default_endp_handle(endp_handle
))
424 status
= STATUS_INVALID_DEVICE_STATE
;
430 endp_from_handle(pdev
, endp_handle
, pendp
);
431 // FIXME: don't know what evil will let loose
432 if (endp_type(pendp
) != USB_ENDPOINT_XFER_CONTROL
)
434 if (user_buffer_length
> 0x100000)
436 status
= STATUS_INVALID_PARAMETER
;
442 purb
->context
= dev_mgr
;
443 purb
->reference
= ctrl_code
;
445 if (ctrl_code
== IOCTL_SUBMIT_URB_RD
|| ctrl_code
== IOCTL_SUBMIT_URB_WR
)
447 if (ctrl_code
== IOCTL_SUBMIT_URB_RD
)
448 KeFlushIoBuffers(irp
->MdlAddress
, TRUE
, TRUE
);
450 KeFlushIoBuffers(irp
->MdlAddress
, FALSE
, TRUE
);
452 purb
->data_buffer
= user_buffer
;
453 purb
->data_length
= user_buffer_length
;
454 purb
->completion
= disp_urb_completion
;
458 purb
->completion
= disp_noio_urb_completion
;
461 unlock_dev(pdev
, FALSE
);
463 // we have to mark irp before the urb is scheduled to
464 // avoid race condition
465 IoMarkIrpPending(irp
);
466 ASSERT(dev_mgr_register_irp(dev_mgr
, irp
, purb
));
467 status
= usb_submit_urb(dev_mgr
, purb
);
468 if (status
!= STATUS_PENDING
)
470 IoGetCurrentIrpStackLocation((irp
))->Control
&= ~SL_PENDING_RETURNED
;
471 dev_mgr_remove_irp(dev_mgr
, irp
);
473 usb_unlock_dev(pdev
);
474 if (status
!= STATUS_PENDING
)
476 irp
->IoStatus
.Status
= status
;
477 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
481 unlock_dev(pdev
, FALSE
);
482 usb_unlock_dev(pdev
);
483 irp
->IoStatus
.Information
= 0;
484 EXIT_DISPATCH(status
, irp
);
488 irp
->IoStatus
.Information
= 0;
489 EXIT_DISPATCH(STATUS_NOT_IMPLEMENTED
, irp
);
495 irp
->IoStatus
.Information
= 0;
499 EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST
, irp
);
502 /*#define IOCTL_GET_DEV_COUNT CTL_CODE( FILE_HCD_DEV_TYPE, 4093, METHOD_BUFFERED, FILE_ANY_ACCESS )
503 //input_buffer and input_buffer_length is zero, output_buffer is to receive a dword value of the
504 //dev count, output_buffer_length must be no less than sizeof( long ).
506 #define IOCTL_ENUM_DEVICES CTL_CODE( FILE_HCD_DEV_TYPE, 4094, METHOD_BUFFERED, FILE_ANY_ACCESS )
507 //input_buffer is a dword value to indicate the count of elements in the array
508 //input_buffer_length is sizeof( long ), output_buffer is to receive a
509 //structure ENUM_DEV_ARRAY where dev_count is the elements hold in this array.
511 #define IOCTL_GET_DEV_DESC CTL_CODE( FILE_HCD_DEV_TYPE, 4095, METHOD_BUFFERED, FILE_ANY_ACCESS )
512 //input_buffer is a structure GET_DEV_DESC_REQ, and the input_buffer_length is
513 //no less than sizeof( input_buffer ), output_buffer is a buffer to receive the
514 //requested dev's desc, and output_buffer_length specifies the length of the
517 #define IOCTL_SUBMIT_URB_RD CTL_CODE( FILE_HCD_DEV_TYPE, 4096, METHOD_IN_DIRECT, FILE_ANY_ACCESS )
518 #define IOCTL_SUBMIT_URB_WR CTL_CODE( FILE_HCD_DEV_TYPE, 4097, METHOD_OUT_DIRECT, FILE_ANY_ACCESS )
519 // input_buffer is a URB, and input_buffer_length is equal to or greater than
520 // sizeof( URB ); the output_buffer is a buffer to receive data from or send data
521 // to device. only the following urb fields can be accessed, others must be zeroed.
522 // DEV_HANDLE endp_handle;
523 // UCHAR setup_packet[8]; //for control pipe
524 // the choosing of IOCTL_SUBMIT_URB_RD or IOCTL_SUBMIT_URB_WR should be determined
525 // by the current URB, for example, a request string from device will use XXX_RD,
526 // and a write to the bulk endpoint will use XXX_WR
528 #define IOCTL_SUBMIT_URB_NOIO CTL_CODE( FILE_HCD_DEV_TYPE, 4098, METHOD_BUFFERED, FILE_ANY_ACCESS )
529 // input_buffer is a URB, and input_buffer_length is equal to or greater than
530 // sizeof( URB ); the output_buffer is null and no output_buffer_length,
531 // only the following fields in urb can be accessed, others must be zeroed.
532 // DEV_HANDLE endp_handle;
533 // UCHAR setup_packet[8]; //for control pipe