2 * roothub.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"
24 //----------------------------------------------------------
27 rh_driver_destroy(PUSB_DEV_MANAGER dev_mgr
, PUSB_DRIVER pdriver
)
35 for(i
= 0; i
< dev_mgr
->hcd_count
; i
++)
37 hcd
= dev_mgr
->hcd_array
[i
];
38 // if( hcd->hcd_get_type( hcd ) != HCD_TYPE_UHCI )
40 rh_destroy(hcd
->hcd_get_root_hub(hcd
));
46 rh_driver_init(PUSB_DEV_MANAGER dev_mgr
, PUSB_DRIVER pdriver
)
50 PUSB_CONFIGURATION_DESC pconfig_desc
;
51 PUSB_INTERFACE_DESC pif_desc
;
52 PUSB_ENDPOINT_DESC pendp_desc
;
53 PUSB_CONFIGURATION pconfig
;
56 PHUB2_EXTENSION phub_ext
;
61 if (dev_mgr
== NULL
|| pdriver
== NULL
)
64 //init driver structure, no PNP table functions
65 pdriver
->driver_desc
.flags
= USB_DRIVER_FLAG_DEV_CAPABLE
;
66 pdriver
->driver_desc
.vendor_id
= 0xffff; // USB Vendor ID
67 pdriver
->driver_desc
.product_id
= 0xffff; // USB Product ID.
68 pdriver
->driver_desc
.release_num
= 0xffff; // Release Number of Device
70 pdriver
->driver_desc
.config_val
= 0; // Configuration Value
71 pdriver
->driver_desc
.if_num
= 0; // Interface Number
72 pdriver
->driver_desc
.if_class
= USB_CLASS_HUB
; // Interface Class
73 pdriver
->driver_desc
.if_sub_class
= 0; // Interface SubClass
74 pdriver
->driver_desc
.if_protocol
= 0; // Interface Protocol
76 pdriver
->driver_desc
.driver_name
= "USB root hub"; // Driver name for Name Registry
77 pdriver
->driver_desc
.dev_class
= USB_CLASS_HUB
;
78 pdriver
->driver_desc
.dev_sub_class
= 0; // Device Subclass
79 pdriver
->driver_desc
.dev_protocol
= 0; // Protocol Info.
81 //pdriver->driver_init = rh_driver_init; // initialized in dev_mgr_init_driver
82 //pdriver->driver_destroy = rh_driver_destroy;
83 pdriver
->disp_tbl
.version
= 1; // other fields of the dispatch table is not used since rh needs no pnp
85 pdriver
->driver_ext
= 0;
86 pdriver
->driver_ext_size
= 0;
88 for(i
= 0; i
< dev_mgr
->hcd_count
; i
++)
90 hcd
= dev_mgr
->hcd_array
[i
];
91 //if( hcd->hcd_get_type( hcd ) != HCD_TYPE_UHCI )
94 if ((rh
= dev_mgr_alloc_device(dev_mgr
, hcd
)) == NULL
)
97 rh
->parent_dev
= NULL
;
100 rh
->flags
= USB_DEV_CLASS_ROOT_HUB
| USB_DEV_STATE_CONFIGURED
;
103 rh
->flags
|= USB_DEV_FLAG_HIGH_SPEED
;
105 rh
->dev_driver
= pdriver
;
107 rh
->desc_buf_size
= sizeof(USB_DEVICE_DESC
)
108 + sizeof(USB_CONFIGURATION_DESC
)
109 + sizeof(USB_INTERFACE_DESC
)
110 + sizeof(USB_ENDPOINT_DESC
) + sizeof(USB_CONFIGURATION
) + sizeof(HUB2_EXTENSION
);
112 rh
->desc_buf
= usb_alloc_mem(NonPagedPool
, rh
->desc_buf_size
);
114 if (rh
->desc_buf
== NULL
)
119 RtlZeroMemory(rh
->desc_buf
, rh
->desc_buf_size
);
121 rh
->pusb_dev_desc
= (PUSB_DEVICE_DESC
) rh
->desc_buf
;
123 rh
->pusb_dev_desc
->bLength
= sizeof(USB_DEVICE_DESC
);
124 rh
->pusb_dev_desc
->bDescriptorType
= USB_DT_DEVICE
;
125 rh
->pusb_dev_desc
->bcdUSB
= 0x110;
127 rh
->pusb_dev_desc
->bcdUSB
= 0x200;
128 rh
->pusb_dev_desc
->bDeviceClass
= USB_CLASS_HUB
;
129 rh
->pusb_dev_desc
->bDeviceSubClass
= 0;
130 rh
->pusb_dev_desc
->bDeviceProtocol
= 0;
131 rh
->pusb_dev_desc
->bMaxPacketSize0
= 8;
134 rh
->pusb_dev_desc
->bDeviceProtocol
= 1;
135 rh
->pusb_dev_desc
->bMaxPacketSize0
= 64;
137 rh
->pusb_dev_desc
->idVendor
= 0;
138 rh
->pusb_dev_desc
->idProduct
= 0;
139 rh
->pusb_dev_desc
->bcdDevice
= 0x100;
140 rh
->pusb_dev_desc
->iManufacturer
= 0;
141 rh
->pusb_dev_desc
->iProduct
= 0;
142 rh
->pusb_dev_desc
->iSerialNumber
= 0;
143 rh
->pusb_dev_desc
->bNumConfigurations
= 1;
145 pconfig_desc
= (PUSB_CONFIGURATION_DESC
) & rh
->desc_buf
[sizeof(USB_DEVICE_DESC
)];
146 pif_desc
= (PUSB_INTERFACE_DESC
) & pconfig_desc
[1];
147 pendp_desc
= (PUSB_ENDPOINT_DESC
) & pif_desc
[1];
149 pconfig_desc
->bLength
= sizeof(USB_CONFIGURATION_DESC
);
150 pconfig_desc
->bDescriptorType
= USB_DT_CONFIG
;
152 pconfig_desc
->wTotalLength
= sizeof(USB_CONFIGURATION_DESC
)
153 + sizeof(USB_INTERFACE_DESC
) + sizeof(USB_ENDPOINT_DESC
);
155 pconfig_desc
->bNumInterfaces
= 1;
156 pconfig_desc
->bConfigurationValue
= 1;
157 pconfig_desc
->iConfiguration
= 0;
158 pconfig_desc
->bmAttributes
= 0Xe0; //self-powered and support remoke wakeup
159 pconfig_desc
->MaxPower
= 0;
161 pif_desc
->bLength
= sizeof(USB_INTERFACE_DESC
);
162 pif_desc
->bDescriptorType
= USB_DT_INTERFACE
;
163 pif_desc
->bInterfaceNumber
= 0;
164 pif_desc
->bAlternateSetting
= 0;
165 pif_desc
->bNumEndpoints
= 1;
166 pif_desc
->bInterfaceClass
= USB_CLASS_HUB
;
167 pif_desc
->bInterfaceSubClass
= 0;
168 pif_desc
->bInterfaceProtocol
= 0;
169 pif_desc
->iInterface
= 0;
171 pendp_desc
->bLength
= sizeof(USB_ENDPOINT_DESC
);
172 pendp_desc
->bDescriptorType
= USB_DT_ENDPOINT
;
173 pendp_desc
->bEndpointAddress
= 0x81;
174 pendp_desc
->bmAttributes
= 0x03;
175 pendp_desc
->wMaxPacketSize
= 8;
176 pendp_desc
->bInterval
= USB_HUB_INTERVAL
;
178 pendp_desc
->bInterval
= 0x0c;
180 pconfig
= rh
->usb_config
= (PUSB_CONFIGURATION
) & pendp_desc
[1];
181 rh
->active_config_idx
= 0;
182 pconfig
->pusb_config_desc
= pconfig_desc
;
183 pconfig
->if_count
= 1;
184 pconfig
->pusb_dev
= rh
;
185 pif
= &pconfig
->interf
[0];
188 pendp
= &pif
->endp
[0];
189 pif
->pusb_config
= pconfig
;
190 pif
->pusb_if_desc
= pif_desc
;
192 pif
->if_ext_size
= 0;
195 phub_ext
= (PHUB2_EXTENSION
) & pconfig
[1];
196 phub_ext
->port_count
= 2;
200 // port count is configurable in usb2
201 hcd
->hcd_dispatch(hcd
, HCD_DISP_READ_PORT_COUNT
, &phub_ext
->port_count
);
206 for(j
= 0; j
< phub_ext
->port_count
; j
++)
208 psq_init(&phub_ext
->port_status_queue
[j
]);
209 phub_ext
->child_dev
[j
] = NULL
;
210 usb_dbg_print(DBGLVL_MAXIMUM
, ("rh_driver_init(): port[ %d ].flag=0x%x\n",
211 j
, phub_ext
->port_status_queue
[j
].port_flags
));
216 phub_ext
->hub_desc
.bLength
= sizeof(USB_HUB_DESCRIPTOR
);
217 phub_ext
->hub_desc
.bDescriptorType
= USB_DT_HUB
;
218 phub_ext
->hub_desc
.bNbrPorts
= (UCHAR
) phub_ext
->port_count
;
219 phub_ext
->hub_desc
.wHubCharacteristics
= 0;
220 phub_ext
->hub_desc
.bPwrOn2PwrGood
= 0;
221 phub_ext
->hub_desc
.bHubContrCurrent
= 50;
223 rh
->dev_ext
= (PBYTE
) phub_ext
;
224 rh
->dev_ext_size
= sizeof(HUB2_EXTENSION
);
226 rh
->default_endp
.flags
= USB_ENDP_FLAG_DEFAULT_ENDP
;
227 InitializeListHead(&rh
->default_endp
.urb_list
);
228 rh
->default_endp
.pusb_if
= (PUSB_INTERFACE
) rh
;
229 rh
->default_endp
.pusb_endp_desc
= NULL
; //???
230 rh
->time_out_count
= 0;
233 InitializeListHead(&pendp
->urb_list
);
235 pendp
->pusb_endp_desc
= pendp_desc
;
236 pendp
->pusb_if
= pif
;
239 InsertTailList(&dev_mgr
->dev_list
, &rh
->dev_link
);
240 hcd
->hcd_set_root_hub(hcd
, rh
);
241 status
= hub_start_int_request(rh
);
242 pdriver
->driver_ext
= 0;
247 //to be the reverse of what init does, we assume that the timer is now killed
248 //int is disconnected and the hub thread will not process event anymore
250 rh_destroy(PUSB_DEV pdev
)
253 PUSB_DEV_MANAGER dev_mgr
;
258 dev_mgr
= dev_mgr_from_dev(pdev
);
261 rh
= pdev
->hcd
->hcd_get_root_hub(pdev
->hcd
);
265 dev_mgr_free_device(dev_mgr
, rh
);
266 //dev_mgr->root_hub = NULL;
273 rh_timer_svc_int_completion(PUSB_DEV pdev
, PVOID context
)
277 USE_BASIC_NON_PENDING_IRQL
;
279 if (pdev
== NULL
|| context
== NULL
)
282 purb
= (PURB
) context
;
284 lock_dev(pdev
, TRUE
);
286 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
288 pdev
->ref_count
-= 2; // one for timer_svc and one for urb, for those rh requests
289 unlock_dev(pdev
, TRUE
);
291 usb_dbg_print(DBGLVL_MAXIMUM
, ("rh_timer_svc_int_completion(): the dev is zomb, 0x%x\n", pdev
));
296 if (purb
->data_length
< 1)
298 purb
->status
= STATUS_INVALID_PARAMETER
;
299 unlock_dev(pdev
, TRUE
);
303 pdev
->hcd
->hcd_dispatch(pdev
->hcd
, HCD_DISP_READ_RH_DEV_CHANGE
, purb
->data_buffer
);
304 purb
->status
= STATUS_SUCCESS
;
305 unlock_dev(pdev
, TRUE
);
308 hcd
->hcd_generic_urb_completion(purb
, purb
->context
);
310 lock_dev(pdev
, TRUE
);
311 pdev
->ref_count
-= 2;
312 // one for timer_svc and one for urb, for those rh requests
313 // that completed immediately, the ref_count of the dev for
314 // that urb won't increment and for normal hub request
315 // completion, hcd_generic_urb_completion will be called
316 // by the xhci_dpc_callback, and the ref_count for the urb
317 // is maintained there. So only rh's timer-svc cares refcount
318 // when hcd_generic_urb_completion is called.
319 usb_dbg_print(DBGLVL_ULTRA
, ("rh_timer_svc_int_completion(): rh's ref_count=0x%x\n", pdev
->ref_count
));
320 unlock_dev(pdev
, TRUE
);
321 usb_dbg_print(DBGLVL_ULTRA
, ("rh_timer_svc_int_completion(): exitiing...\n"));
326 rh_timer_svc_reset_port_completion(PUSB_DEV pdev
, PVOID context
)
330 PHUB2_EXTENSION hub_ext
;
331 PLIST_ENTRY pthis
, pnext
;
332 PUSB_DEV_MANAGER dev_mgr
;
333 PUSB_CTRL_SETUP_PACKET psetup
;
335 USE_BASIC_NON_PENDING_IRQL
;
337 if (pdev
== NULL
|| context
== NULL
)
340 dev_mgr
= dev_mgr_from_dev(pdev
); //readonly and hold ref_count
342 //block the rh polling
343 KeAcquireSpinLockAtDpcLevel(&dev_mgr
->timer_svc_list_lock
);
344 if (IsListEmpty(&dev_mgr
->timer_svc_list
) == FALSE
)
346 ListFirst(&dev_mgr
->timer_svc_list
, pthis
);
349 if (((PTIMER_SVC
) pthis
)->pdev
== pdev
&& ((PTIMER_SVC
) pthis
)->threshold
== RH_INTERVAL
)
351 ((PTIMER_SVC
) pthis
)->threshold
= RH_INTERVAL
+ 0x800000;
355 ListNext(&dev_mgr
->timer_svc_list
, pthis
, pnext
);
359 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->timer_svc_list_lock
);
361 purb
= (PURB
) context
;
362 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
364 lock_dev(pdev
, TRUE
);
365 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
367 //purb->status = STATUS_ERROR;
368 //pdev->hcd->hcd_generic_urb_completion( purb, purb->context );
370 pdev
->ref_count
-= 2;
371 unlock_dev(pdev
, TRUE
);
376 i
= pdev
->hcd
->hcd_rh_reset_port(pdev
->hcd
, (UCHAR
) psetup
->wIndex
);
378 hub_ext
= hub_ext_from_dev(pdev
);
383 if (psetup
->wIndex
< 16)
385 temp
= 1 << psetup
->wIndex
;
386 pbuf
= (PUCHAR
) & temp
;
389 hub_ext
->int_data_buf
[psetup
->wIndex
/ 8] |= *pbuf
;
391 hub_ext
->rh_port_status
[psetup
->wIndex
].wPortChange
|= USB_PORT_STAT_C_RESET
;
392 else // notify that is not a high speed device, will lost definitely
393 hub_ext
->rh_port_status
[psetup
->wIndex
].wPortChange
|= USB_PORT_STAT_C_CONNECTION
;
397 //???how to construct port status map
398 // decrease the timer_svc ref-count
400 unlock_dev(pdev
, TRUE
);
402 purb
->status
= STATUS_SUCCESS
;
403 //we delegate the completion to the rh_timer_svc_int_completion.
404 //this function is equivalent to hub_start_reset_port_completion
408 //expire the rh polling timer
409 KeAcquireSpinLockAtDpcLevel(&dev_mgr
->timer_svc_list_lock
);
410 if (IsListEmpty(&dev_mgr
->timer_svc_list
) == FALSE
)
412 ListFirst(&dev_mgr
->timer_svc_list
, pthis
);
415 if (((PTIMER_SVC
) pthis
)->pdev
== pdev
&&
416 ((PTIMER_SVC
) pthis
)->threshold
== RH_INTERVAL
+ 0x800000)
418 ((PTIMER_SVC
) pthis
)->counter
= RH_INTERVAL
;
419 ((PTIMER_SVC
) pthis
)->threshold
= RH_INTERVAL
;
423 ListNext(&dev_mgr
->timer_svc_list
, pthis
, pnext
);
427 KeReleaseSpinLockFromDpcLevel(&dev_mgr
->timer_svc_list_lock
);
429 lock_dev(pdev
, TRUE
);
431 unlock_dev(pdev
, TRUE
);