[USBEHCI]
[reactos.git] / drivers / usb / usbehci / usb_device.cpp
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbehci/usb_device.cpp
5 * PURPOSE: USB EHCI device driver.
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
9 */
10
11 #define INITGUID
12 #include "usbehci.h"
13
14 class CUSBDevice : public IUSBDevice
15 {
16 public:
17 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
18
19 STDMETHODIMP_(ULONG) AddRef()
20 {
21 InterlockedIncrement(&m_Ref);
22 return m_Ref;
23 }
24 STDMETHODIMP_(ULONG) Release()
25 {
26 InterlockedDecrement(&m_Ref);
27
28 if (!m_Ref)
29 {
30 delete this;
31 return 0;
32 }
33 return m_Ref;
34 }
35
36 // IUSBDevice interface functions
37 virtual NTSTATUS Initialize(IN PHUBCONTROLLER HubController, IN PUSBHARDWAREDEVICE Device, IN PVOID Parent, IN ULONG Port, IN ULONG PortStatus);
38 virtual BOOLEAN IsHub();
39 virtual NTSTATUS GetParent(PVOID * Parent);
40 virtual UCHAR GetDeviceAddress();
41 virtual ULONG GetPort();
42 virtual USB_DEVICE_SPEED GetSpeed();
43 virtual USB_DEVICE_TYPE GetType();
44 virtual ULONG GetState();
45 virtual void SetDeviceHandleData(PVOID Data);
46 virtual NTSTATUS SetDeviceAddress(UCHAR DeviceAddress);
47 virtual void GetDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor);
48 virtual UCHAR GetConfigurationValue();
49 virtual NTSTATUS SubmitIrp(PIRP Irp);
50 virtual VOID GetConfigurationDescriptors(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer, IN ULONG BufferLength, OUT PULONG OutBufferLength);
51 virtual ULONG GetConfigurationDescriptorsLength();
52 virtual NTSTATUS SubmitSetupPacket(IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, OUT ULONG BufferLength, OUT PVOID Buffer);
53 virtual NTSTATUS SelectConfiguration(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, IN PUSBD_INTERFACE_INFORMATION Interface, OUT USBD_CONFIGURATION_HANDLE *ConfigurationHandle);
54 virtual NTSTATUS SelectInterface(IN USBD_CONFIGURATION_HANDLE ConfigurationHandle, IN OUT PUSBD_INTERFACE_INFORMATION Interface);
55 virtual NTSTATUS AbortPipe(IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor);
56
57
58 // local function
59 virtual NTSTATUS CommitIrp(PIRP Irp);
60 virtual NTSTATUS CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor, IN ULONG BufferLength, IN OUT PMDL Mdl);
61 virtual NTSTATUS CreateConfigurationDescriptor(UCHAR ConfigurationIndex);
62 virtual NTSTATUS CreateDeviceDescriptor();
63 virtual VOID DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor);
64 virtual VOID DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor);
65
66 // constructor / destructor
67 CUSBDevice(IUnknown *OuterUnknown){}
68 virtual ~CUSBDevice(){}
69
70 protected:
71 LONG m_Ref;
72 PHUBCONTROLLER m_HubController;
73 PUSBHARDWAREDEVICE m_Device;
74 PVOID m_Parent;
75 ULONG m_Port;
76 UCHAR m_DeviceAddress;
77 PVOID m_Data;
78 UCHAR m_ConfigurationIndex;
79 KSPIN_LOCK m_Lock;
80 USB_DEVICE_DESCRIPTOR m_DeviceDescriptor;
81 ULONG m_PortStatus;
82 PUSBQUEUE m_Queue;
83 PDMAMEMORYMANAGER m_DmaManager;
84
85 PUSB_CONFIGURATION m_ConfigurationDescriptors;
86 };
87
88 //----------------------------------------------------------------------------------------
89 NTSTATUS
90 STDMETHODCALLTYPE
91 CUSBDevice::QueryInterface(
92 IN REFIID refiid,
93 OUT PVOID* Output)
94 {
95 return STATUS_UNSUCCESSFUL;
96 }
97
98 //----------------------------------------------------------------------------------------
99 NTSTATUS
100 CUSBDevice::Initialize(
101 IN PHUBCONTROLLER HubController,
102 IN PUSBHARDWAREDEVICE Device,
103 IN PVOID Parent,
104 IN ULONG Port,
105 IN ULONG PortStatus)
106 {
107 NTSTATUS Status;
108
109 //
110 // initialize members
111 //
112 m_HubController = HubController;
113 m_Device = Device;
114 m_Parent = Parent;
115 m_Port = Port;
116 m_PortStatus = PortStatus;
117
118 //
119 // initialize device lock
120 //
121 KeInitializeSpinLock(&m_Lock);
122
123 //
124 // no device address has been set yet
125 //
126 m_DeviceAddress = 0;
127
128 //
129 // get usb request queue
130 //
131 Status = m_Device->GetUSBQueue(&m_Queue);
132 if (!NT_SUCCESS(Status))
133 {
134 //
135 // failed to get usb queue
136 //
137 DPRINT1("CUSBDevice::Initialize GetUsbQueue failed with %x\n", Status);
138 return Status;
139 }
140
141 //
142 // get dma manager
143 //
144 Status = m_Device->GetDMA(&m_DmaManager);
145 if (!NT_SUCCESS(Status))
146 {
147 //
148 // failed to get dma manager
149 //
150 DPRINT1("CUSBDevice::Initialize GetDMA failed with %x\n", Status);
151 return Status;
152 }
153
154 //
155 // sanity check
156 //
157 PC_ASSERT(m_DmaManager);
158
159 //
160 // get device descriptor
161 //
162 Status = CreateDeviceDescriptor();
163 if (!NT_SUCCESS(Status))
164 {
165 //
166 // failed to get device descriptor
167 //
168 DPRINT1("CUSBDevice::Initialize Failed to get device descriptor with %x\n", Status);
169 return Status;
170 }
171
172 //
173 // done
174 //
175 return Status;
176 }
177
178 //----------------------------------------------------------------------------------------
179 BOOLEAN
180 CUSBDevice::IsHub()
181 {
182 //
183 // USB Standard Device Class see http://www.usb.org/developers/defined_class/#BaseClass09h
184 // for details
185 //
186 return (m_DeviceDescriptor.bDeviceClass == 0x09 && m_DeviceDescriptor.bDeviceSubClass == 0x00);
187 }
188
189 //----------------------------------------------------------------------------------------
190 NTSTATUS
191 CUSBDevice::GetParent(
192 PVOID * Parent)
193 {
194 //
195 // returns parent
196 //
197 *Parent = m_Parent;
198
199 //
200 // done
201 //
202 return STATUS_SUCCESS;
203 }
204
205 //----------------------------------------------------------------------------------------
206 UCHAR
207 CUSBDevice::GetDeviceAddress()
208 {
209 //
210 // get device address
211 //
212 return m_DeviceAddress;
213 }
214
215 //----------------------------------------------------------------------------------------
216 ULONG
217 CUSBDevice::GetPort()
218 {
219 //
220 // get port to which this device is connected to
221 //
222 return m_Port;
223 }
224
225 //----------------------------------------------------------------------------------------
226 USB_DEVICE_SPEED
227 CUSBDevice::GetSpeed()
228 {
229 if (m_PortStatus & USB_PORT_STATUS_LOW_SPEED)
230 {
231 //
232 // low speed device
233 //
234 return UsbLowSpeed;
235 }
236 else if (m_PortStatus & USB_PORT_STATUS_HIGH_SPEED)
237 {
238 //
239 // high speed device
240 //
241 return UsbHighSpeed;
242 }
243
244 //
245 // default to full speed
246 //
247 return UsbFullSpeed;
248 }
249
250 //----------------------------------------------------------------------------------------
251 USB_DEVICE_TYPE
252 CUSBDevice::GetType()
253 {
254 //
255 // device is encoded into bcdUSB
256 //
257 if (m_DeviceDescriptor.bcdUSB == 0x110)
258 {
259 //
260 // USB 1.1 device
261 //
262 return Usb11Device;
263 }
264 else if (m_DeviceDescriptor.bcdUSB == 0x200)
265 {
266 //
267 // USB 2.0 device
268 //
269 return Usb20Device;
270 }
271
272 DPRINT1("CUSBDevice::GetType Unknown bcdUSB Type %x\n", m_DeviceDescriptor.bcdUSB);
273 PC_ASSERT(FALSE);
274
275 return Usb11Device;
276 }
277
278 //----------------------------------------------------------------------------------------
279 ULONG
280 CUSBDevice::GetState()
281 {
282 UNIMPLEMENTED
283 return FALSE;
284 }
285
286 //----------------------------------------------------------------------------------------
287 void
288 CUSBDevice::SetDeviceHandleData(
289 PVOID Data)
290 {
291 //
292 // set device data, for debugging issues
293 //
294 m_Data = Data;
295 }
296
297 //----------------------------------------------------------------------------------------
298 NTSTATUS
299 CUSBDevice::SetDeviceAddress(
300 UCHAR DeviceAddress)
301 {
302 PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
303 NTSTATUS Status;
304 UCHAR OldAddress;
305 UCHAR Index;
306
307 DPRINT1("CUSBDevice::SetDeviceAddress Address %d\n", DeviceAddress);
308
309 CtrlSetup = (PUSB_DEFAULT_PIPE_SETUP_PACKET)ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET), TAG_USBEHCI);
310 if (!CtrlSetup)
311 return STATUS_INSUFFICIENT_RESOURCES;
312
313 //
314 // zero request
315 //
316 RtlZeroMemory(CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
317
318 //
319 // initialize request
320 //
321 CtrlSetup->bRequest = USB_REQUEST_SET_ADDRESS;
322 CtrlSetup->wValue.W = (USHORT)DeviceAddress;
323
324 //
325 // set device address
326 //
327 Status = CommitSetupPacket(CtrlSetup, 0, 0, 0);
328
329 //
330 // free setup packet
331 //
332 ExFreePoolWithTag(CtrlSetup, TAG_USBEHCI);
333
334 //
335 // check for success
336 //
337 if (!NT_SUCCESS(Status))
338 {
339 //
340 // failed to set device address
341 //
342 DPRINT1("CUSBDevice::SetDeviceAddress> failed to set device address with %x Address %x\n", Status, DeviceAddress);
343 return Status;
344 }
345
346 //
347 // lets have a short nap
348 //
349 KeStallExecutionProcessor(300);
350
351 //
352 // back up old address
353 //
354 OldAddress = m_DeviceAddress;
355
356 //
357 // store new device address
358 //
359 m_DeviceAddress = DeviceAddress;
360
361 //
362 // check that setting device address succeeded by retrieving the device descriptor
363 //
364 Status = CreateDeviceDescriptor();
365 if (!NT_SUCCESS(Status))
366 {
367 //
368 // failed to retrieve device descriptor
369 //
370 DPRINT1("CUSBbDevice::SetDeviceAddress> failed to retrieve device descriptor with device address set Error %x\n", Status);
371 m_DeviceAddress = OldAddress;
372
373 //
374 // return error status
375 //
376 return Status;
377 }
378
379 //
380 // sanity checks
381 //
382 PC_ASSERT(m_DeviceDescriptor.bNumConfigurations);
383
384 //
385 // allocate configuration descriptor
386 //
387 m_ConfigurationDescriptors = (PUSB_CONFIGURATION) ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_CONFIGURATION) * m_DeviceDescriptor.bNumConfigurations, TAG_USBEHCI);
388
389 //
390 // zero configuration descriptor
391 //
392 RtlZeroMemory(m_ConfigurationDescriptors, sizeof(USB_CONFIGURATION) * m_DeviceDescriptor.bNumConfigurations);
393
394 //
395 // retrieve the configuration descriptors
396 //
397 for(Index = 0; Index < m_DeviceDescriptor.bNumConfigurations; Index++)
398 {
399 //
400 // retrieve configuration descriptors from device
401 //
402 Status = CreateConfigurationDescriptor(Index);
403 if (!NT_SUCCESS(Status))
404 {
405 DPRINT1("CUSBDevice::SetDeviceAddress> failed to retrieve configuration %lu\n", Index);
406 break;
407 }
408 }
409
410 //
411 // done
412 //
413 return Status;
414
415 }
416
417 //----------------------------------------------------------------------------------------
418 void
419 CUSBDevice::GetDeviceDescriptor(
420 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
421 {
422 RtlMoveMemory(DeviceDescriptor, &m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
423 }
424
425 //----------------------------------------------------------------------------------------
426 UCHAR
427 CUSBDevice::GetConfigurationValue()
428 {
429 //
430 // return configuration index
431 //
432 return m_ConfigurationIndex;
433 }
434
435 //----------------------------------------------------------------------------------------
436 NTSTATUS
437 CUSBDevice::CommitIrp(
438 PIRP Irp)
439 {
440 NTSTATUS Status;
441 PUSBREQUEST Request;
442
443 if (!m_Queue || !m_DmaManager)
444 {
445 //
446 // no queue, wtf?
447 //
448 DPRINT1("CUSBDevice::CommitUrb> no queue / dma !!!\n");
449 return STATUS_UNSUCCESSFUL;
450 }
451
452 //
453 // build usb request
454 //
455 Status = m_Queue->CreateUSBRequest(&Request);
456 if (!NT_SUCCESS(Status))
457 {
458 //
459 // failed to build request
460 //
461 DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with %x\n", Status);
462 return Status;
463 }
464
465 //
466 // initialize request
467 //
468 Status = Request->InitializeWithIrp(m_DmaManager, Irp);
469
470 //
471 // mark irp as pending
472 //
473 IoMarkIrpPending(Irp);
474
475 //
476 // now add the request
477 //
478 Status = m_Queue->AddUSBRequest(Request);
479 if (!NT_SUCCESS(Status))
480 {
481 //
482 // failed to add request
483 //
484 DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with %x\n", Status);
485 Request->Release();
486 return Status;
487 }
488
489 //
490 // done
491 //
492 return STATUS_PENDING;
493 }
494
495 //----------------------------------------------------------------------------------------
496 NTSTATUS
497 CUSBDevice::SubmitIrp(
498 PIRP Irp)
499 {
500 KIRQL OldLevel;
501 NTSTATUS Status;
502
503 //
504 // acquire device lock
505 //
506 KeAcquireSpinLock(&m_Lock, &OldLevel);
507
508 //
509 // commit urb
510 //
511 Status = CommitIrp(Irp);
512
513 //
514 // release lock
515 //
516 KeReleaseSpinLock(&m_Lock, OldLevel);
517
518 return Status;
519 }
520 //----------------------------------------------------------------------------------------
521 NTSTATUS
522 CUSBDevice::CommitSetupPacket(
523 IN PUSB_DEFAULT_PIPE_SETUP_PACKET Packet,
524 IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor,
525 IN ULONG BufferLength,
526 IN OUT PMDL Mdl)
527 {
528 NTSTATUS Status;
529 PUSBREQUEST Request;
530
531 if (!m_Queue)
532 {
533 //
534 // no queue, wtf?
535 //
536 DPRINT1("CUSBDevice::CommitSetupPacket> no queue!!!\n");
537 return STATUS_UNSUCCESSFUL;
538 }
539
540 //
541 // build usb request
542 //
543 Status = m_Queue->CreateUSBRequest(&Request);
544 if (!NT_SUCCESS(Status))
545 {
546 //
547 // failed to build request
548 //
549 DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with %x\n", Status);
550 return Status;
551 }
552
553 //
554 // initialize request
555 //
556 Status = Request->InitializeWithSetupPacket(m_DmaManager, Packet, m_DeviceAddress, EndpointDescriptor, BufferLength, Mdl);
557 if (!NT_SUCCESS(Status))
558 {
559 //
560 // failed to initialize request
561 //
562 DPRINT1("CUSBDevice::CommitSetupPacket> failed to initialize usb request with %x\n", Status);
563 Request->Release();
564 return Status;
565 }
566
567 //
568 // now add the request
569 //
570 Status = m_Queue->AddUSBRequest(Request);
571 if (!NT_SUCCESS(Status))
572 {
573 //
574 // failed to add request
575 //
576 DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with %x\n", Status);
577 Request->Release();
578 return Status;
579 }
580
581 //
582 // get the result code when the operation has been finished
583 //
584 Request->GetResultStatus(&Status, NULL);
585
586 //
587 // release request
588 //
589 Request->Release();
590
591 //
592 // done
593 //
594 return Status;
595 }
596
597 //----------------------------------------------------------------------------------------
598 NTSTATUS
599 CUSBDevice::CreateDeviceDescriptor()
600 {
601 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
602 PMDL Mdl;
603 NTSTATUS Status;
604 PVOID Buffer;
605
606 //
607 // zero descriptor
608 //
609 RtlZeroMemory(&m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
610 RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
611
612 //
613 // setup request
614 //
615 CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
616 CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
617 CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR);
618 CtrlSetup.bmRequestType.B = 0x80;
619
620 //
621 // allocate buffer
622 //
623 Buffer = ExAllocatePool(NonPagedPool, PAGE_SIZE);
624 if (!Buffer)
625 {
626 //
627 // failed to allocate
628 //
629 return STATUS_INSUFFICIENT_RESOURCES;
630 }
631
632 //
633 // zero buffer
634 //
635 RtlZeroMemory(Buffer, PAGE_SIZE);
636
637 //
638 // allocate mdl describing the device descriptor
639 //
640 Mdl = IoAllocateMdl(Buffer, sizeof(USB_DEVICE_DESCRIPTOR), FALSE, FALSE, 0);
641 if (!Mdl)
642 {
643 //
644 // failed to allocate mdl
645 //
646 return STATUS_INSUFFICIENT_RESOURCES;
647 }
648
649 //
650 // build mdl for non paged pool
651 //
652 MmBuildMdlForNonPagedPool(Mdl);
653
654 //
655 // commit setup packet
656 //
657 Status = CommitSetupPacket(&CtrlSetup, 0, sizeof(USB_DEVICE_DESCRIPTOR), Mdl);
658
659 //
660 // now free the mdl
661 //
662 IoFreeMdl(Mdl);
663
664 if (NT_SUCCESS(Status))
665 {
666 //
667 // informal dbg print
668 //
669 RtlCopyMemory(&m_DeviceDescriptor, Buffer, sizeof(USB_DEVICE_DESCRIPTOR));
670 DumpDeviceDescriptor(&m_DeviceDescriptor);
671 }
672
673 //
674 // free buffer
675 //
676 ExFreePool(Buffer);
677
678 //
679 // done
680 //
681 return Status;
682
683 }
684
685 //----------------------------------------------------------------------------------------
686 NTSTATUS
687 CUSBDevice::CreateConfigurationDescriptor(
688 UCHAR Index)
689 {
690 PVOID Buffer;
691 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
692 NTSTATUS Status;
693 PMDL Mdl;
694 ULONG InterfaceIndex, EndPointIndex;
695 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
696 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
697 PUSB_ENDPOINT_DESCRIPTOR EndPointDescriptor;
698
699
700 //
701 // sanity checks
702 //
703 PC_ASSERT(m_ConfigurationDescriptors);
704
705 //
706 // first allocate a buffer which should be enough to store all different interfaces and endpoints
707 //
708 Buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, TAG_USBEHCI);
709 if (!Buffer)
710 {
711 //
712 // failed to allocate buffer
713 //
714 return STATUS_INSUFFICIENT_RESOURCES;
715 }
716
717 //
718 // build setup packet
719 //
720 CtrlSetup.bmRequestType._BM.Recipient = BMREQUEST_TO_DEVICE;
721 CtrlSetup.bmRequestType._BM.Type = BMREQUEST_STANDARD;
722 CtrlSetup.bmRequestType._BM.Reserved = 0;
723 CtrlSetup.bmRequestType._BM.Dir = BMREQUEST_DEVICE_TO_HOST;
724 CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
725 CtrlSetup.wValue.LowByte = Index;
726 CtrlSetup.wValue.HiByte = USB_CONFIGURATION_DESCRIPTOR_TYPE;
727 CtrlSetup.wIndex.W = 0;
728 CtrlSetup.wLength = PAGE_SIZE;
729
730 //
731 // now build MDL describing the buffer
732 //
733 Mdl = IoAllocateMdl(Buffer, PAGE_SIZE, FALSE, FALSE, 0);
734 if (!Mdl)
735 {
736 //
737 // failed to allocate mdl
738 //
739 ExFreePoolWithTag(Buffer, TAG_USBEHCI);
740 return STATUS_INSUFFICIENT_RESOURCES;
741 }
742
743 //
744 // build mdl for non paged pool
745 //
746 MmBuildMdlForNonPagedPool(Mdl);
747
748 //
749 // commit packet
750 //
751 Status = CommitSetupPacket(&CtrlSetup, 0, PAGE_SIZE, Mdl);
752 if (!NT_SUCCESS(Status))
753 {
754 //
755 // failed to issue request, cleanup
756 //
757 IoFreeMdl(Mdl);
758 ExFreePool(Buffer);
759 return Status;
760 }
761
762 //
763 // now free the mdl
764 //
765 IoFreeMdl(Mdl);
766
767 //
768 // get configuration descriptor
769 //
770 ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)Buffer;
771
772 //
773 // informal debug print
774 //
775 DumpConfigurationDescriptor(ConfigurationDescriptor);
776
777 //
778 // sanity check
779 //
780 PC_ASSERT(ConfigurationDescriptor->bLength == sizeof(USB_CONFIGURATION_DESCRIPTOR));
781 PC_ASSERT(ConfigurationDescriptor->wTotalLength <= PAGE_SIZE);
782 PC_ASSERT(ConfigurationDescriptor->bNumInterfaces);
783
784 //
785 // request is complete, initialize configuration descriptor
786 //
787 RtlCopyMemory(&m_ConfigurationDescriptors[Index].ConfigurationDescriptor, ConfigurationDescriptor, ConfigurationDescriptor->bLength);
788
789 //
790 // now allocate interface descriptors
791 //
792 m_ConfigurationDescriptors[Index].Interfaces = (PUSB_INTERFACE)ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_INTERFACE) * ConfigurationDescriptor->bNumInterfaces, TAG_USBEHCI);
793 if (!m_ConfigurationDescriptors[Index].Interfaces)
794 {
795 //
796 // failed to allocate interface descriptors
797 //
798 ExFreePool(Buffer);
799 return STATUS_INSUFFICIENT_RESOURCES;
800 }
801
802 //
803 // zero interface descriptor
804 //
805 RtlZeroMemory(m_ConfigurationDescriptors[Index].Interfaces, sizeof(USB_INTERFACE) * ConfigurationDescriptor->bNumInterfaces);
806
807 //
808 // get first interface descriptor
809 //
810 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)(ConfigurationDescriptor + 1);
811
812 //
813 // setup interface descriptors
814 //
815 for(InterfaceIndex = 0; InterfaceIndex < ConfigurationDescriptor->bNumInterfaces; InterfaceIndex++)
816 {
817 //
818 // sanity check
819 //
820 PC_ASSERT(InterfaceDescriptor->bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
821 PC_ASSERT(InterfaceDescriptor->bNumEndpoints);
822
823 //
824 // copy current interface descriptor
825 //
826 RtlCopyMemory(&m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].InterfaceDescriptor, InterfaceDescriptor, InterfaceDescriptor->bLength);
827
828 //
829 // allocate end point descriptors
830 //
831 m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].EndPoints = (PUSB_ENDPOINT)ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_ENDPOINT) * InterfaceDescriptor->bNumEndpoints, TAG_USBEHCI);
832 if (!m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].EndPoints)
833 {
834 //
835 // failed to allocate endpoint
836 //
837 Status = STATUS_INSUFFICIENT_RESOURCES;
838 break;
839 }
840
841 //
842 // zero memory
843 //
844 RtlZeroMemory(m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].EndPoints, sizeof(USB_ENDPOINT) * InterfaceDescriptor->bNumEndpoints);
845
846 //
847 // initialize end point descriptors
848 //
849 EndPointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)(InterfaceDescriptor + 1);
850
851 for(EndPointIndex = 0; EndPointIndex < InterfaceDescriptor->bNumEndpoints; EndPointIndex++)
852 {
853 //
854 // sanity check
855 //
856 PC_ASSERT(EndPointDescriptor->bLength == sizeof(USB_ENDPOINT_DESCRIPTOR));
857
858 //
859 // copy endpoint descriptor
860 //
861 RtlCopyMemory(&m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].EndPoints[EndPointIndex].EndPointDescriptor, EndPointDescriptor, EndPointDescriptor->bLength);
862
863 //
864 // move to next offset
865 //
866 EndPointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)EndPointDescriptor + EndPointDescriptor->bLength);
867 }
868
869 //
870 // update interface descriptor offset
871 //
872 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)EndPointDescriptor;
873 }
874
875 //
876 // free buffer
877 //
878 ExFreePoolWithTag(Buffer, TAG_USBEHCI);
879
880 //
881 // done
882 //
883 return Status;
884 }
885 //----------------------------------------------------------------------------------------
886 VOID
887 CUSBDevice::GetConfigurationDescriptors(
888 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer,
889 IN ULONG BufferLength,
890 OUT PULONG OutBufferLength)
891 {
892 PVOID Buffer;
893 ULONG InterfaceIndex, EndpointIndex;
894
895 //
896 // sanity check
897 //
898 PC_ASSERT(BufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
899 PC_ASSERT(ConfigDescriptorBuffer);
900 PC_ASSERT(OutBufferLength);
901
902 //
903 // reset copied length
904 //
905 *OutBufferLength = 0;
906
907 //
908 // FIXME: support multiple configurations
909 //
910 PC_ASSERT(m_DeviceDescriptor.bNumConfigurations == 1);
911
912 //
913 // copy first configuration descriptor
914 //
915 RtlCopyMemory(ConfigDescriptorBuffer, &m_ConfigurationDescriptors[0].ConfigurationDescriptor, sizeof(USB_CONFIGURATION_DESCRIPTOR));
916
917 //
918 // subtract length
919 //
920 BufferLength -= sizeof(USB_CONFIGURATION_DESCRIPTOR);
921 *OutBufferLength += sizeof(USB_CONFIGURATION_DESCRIPTOR);
922
923 //
924 // increment offset
925 //
926 Buffer = (PVOID)(ConfigDescriptorBuffer + 1);
927
928 for(InterfaceIndex = 0; InterfaceIndex < m_ConfigurationDescriptors[0].ConfigurationDescriptor.bNumInterfaces; InterfaceIndex++)
929 {
930 if (BufferLength < sizeof(USB_INTERFACE_DESCRIPTOR))
931 {
932 //
933 // no more room in buffer
934 //
935 return;
936 }
937
938 //
939 // copy interface descriptor
940 //
941 RtlCopyMemory(Buffer, &m_ConfigurationDescriptors[0].Interfaces[InterfaceIndex].InterfaceDescriptor, sizeof(USB_INTERFACE_DESCRIPTOR));
942
943 //
944 // increment offset
945 //
946 Buffer = (PVOID)((ULONG_PTR)Buffer + sizeof(USB_INTERFACE_DESCRIPTOR));
947 BufferLength -= sizeof(USB_INTERFACE_DESCRIPTOR);
948 *OutBufferLength += sizeof(USB_INTERFACE_DESCRIPTOR);
949
950 //
951 // does the interface have endpoints
952 //
953 if (m_ConfigurationDescriptors[0].Interfaces[InterfaceIndex].InterfaceDescriptor.bNumEndpoints)
954 {
955 //
956 // is enough space available
957 //
958 if (BufferLength < sizeof(USB_ENDPOINT_DESCRIPTOR) * m_ConfigurationDescriptors[0].Interfaces[InterfaceIndex].InterfaceDescriptor.bNumEndpoints)
959 {
960 //
961 // no buffer
962 //
963 return;
964 }
965
966 //
967 // copy end points
968 //
969 for(EndpointIndex = 0; EndpointIndex < m_ConfigurationDescriptors[0].Interfaces[InterfaceIndex].InterfaceDescriptor.bNumEndpoints; EndpointIndex++)
970 {
971 //
972 // copy endpoint
973 //
974 RtlCopyMemory(Buffer, &m_ConfigurationDescriptors[0].Interfaces[InterfaceIndex].EndPoints[EndpointIndex].EndPointDescriptor, sizeof(USB_ENDPOINT_DESCRIPTOR));
975
976 //
977 // increment buffer offset
978 //
979 Buffer = (PVOID)((ULONG_PTR)Buffer + sizeof(USB_ENDPOINT_DESCRIPTOR));
980 BufferLength -= sizeof(USB_ENDPOINT_DESCRIPTOR);
981 *OutBufferLength += sizeof(USB_ENDPOINT_DESCRIPTOR);
982 }
983 }
984 }
985 }
986
987 //----------------------------------------------------------------------------------------
988 ULONG
989 CUSBDevice::GetConfigurationDescriptorsLength()
990 {
991 //
992 // FIXME: support multiple configurations
993 //
994 PC_ASSERT(m_DeviceDescriptor.bNumConfigurations == 1);
995
996 return m_ConfigurationDescriptors[0].ConfigurationDescriptor.wTotalLength;
997 }
998 //----------------------------------------------------------------------------------------
999 VOID
1000 CUSBDevice::DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
1001 {
1002 DPRINT1("Dumping Device Descriptor %x\n", DeviceDescriptor);
1003 DPRINT1("bLength %x\n", DeviceDescriptor->bLength);
1004 DPRINT1("bDescriptorType %x\n", DeviceDescriptor->bDescriptorType);
1005 DPRINT1("bcdUSB %x\n", DeviceDescriptor->bcdUSB);
1006 DPRINT1("bDeviceClass %x\n", DeviceDescriptor->bDeviceClass);
1007 DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor->bDeviceSubClass);
1008 DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor->bDeviceProtocol);
1009 DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor->bMaxPacketSize0);
1010 DPRINT1("idVendor %x\n", DeviceDescriptor->idVendor);
1011 DPRINT1("idProduct %x\n", DeviceDescriptor->idProduct);
1012 DPRINT1("bcdDevice %x\n", DeviceDescriptor->bcdDevice);
1013 DPRINT1("iManufacturer %x\n", DeviceDescriptor->iManufacturer);
1014 DPRINT1("iProduct %x\n", DeviceDescriptor->iProduct);
1015 DPRINT1("iSerialNumber %x\n", DeviceDescriptor->iSerialNumber);
1016 DPRINT1("bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations);
1017 }
1018
1019 //----------------------------------------------------------------------------------------
1020 VOID
1021 CUSBDevice::DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
1022 {
1023 DPRINT1("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor);
1024 DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength);
1025 DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
1026 DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
1027 DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
1028 DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
1029 DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
1030 DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
1031 DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
1032 }
1033 //----------------------------------------------------------------------------------------
1034 NTSTATUS
1035 CUSBDevice::SubmitSetupPacket(
1036 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
1037 IN OUT ULONG BufferLength,
1038 OUT PVOID Buffer)
1039 {
1040 NTSTATUS Status;
1041 PMDL Mdl = NULL;
1042
1043 if (BufferLength)
1044 {
1045 //
1046 // allocate mdl
1047 //
1048 Mdl = IoAllocateMdl(Buffer, BufferLength, FALSE, FALSE, 0);
1049 if (!Mdl)
1050 {
1051 //
1052 // no memory
1053 //
1054 return STATUS_INSUFFICIENT_RESOURCES;
1055 }
1056
1057 //
1058 // HACK HACK HACK: assume the buffer is build from non paged pool
1059 //
1060 MmBuildMdlForNonPagedPool(Mdl);
1061 }
1062
1063 //
1064 // commit setup packet
1065 //
1066 Status = CommitSetupPacket(SetupPacket, 0, BufferLength, Mdl);
1067
1068 if (Mdl != NULL)
1069 {
1070 //
1071 // free mdl
1072 //
1073 IoFreeMdl(Mdl);
1074 }
1075
1076 //
1077 // done
1078 //
1079 return Status;
1080 }
1081
1082 //----------------------------------------------------------------------------------------
1083 NTSTATUS
1084 CUSBDevice::SelectConfiguration(
1085 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
1086 IN PUSBD_INTERFACE_INFORMATION InterfaceInfo,
1087 OUT USBD_CONFIGURATION_HANDLE *ConfigurationHandle)
1088 {
1089 ULONG InterfaceIndex, PipeIndex;
1090 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1091 NTSTATUS Status;
1092
1093 //
1094 // sanity checks
1095 //
1096 ASSERT(ConfigurationDescriptor->iConfiguration < m_DeviceDescriptor.bNumConfigurations);
1097 ASSERT(ConfigurationDescriptor->iConfiguration == m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].ConfigurationDescriptor.iConfiguration);
1098
1099 //
1100 // sanity check
1101 //
1102 ASSERT(ConfigurationDescriptor->bNumInterfaces <= m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].ConfigurationDescriptor.bNumInterfaces);
1103
1104 //
1105 // now build setup packet
1106 //
1107 RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1108 CtrlSetup.bRequest = USB_REQUEST_SET_CONFIGURATION;
1109 CtrlSetup.wValue.W = ConfigurationDescriptor->bConfigurationValue;
1110
1111 //
1112 // select configuration
1113 //
1114 Status = CommitSetupPacket(&CtrlSetup, 0, 0, 0);
1115
1116 //
1117 // informal debug print
1118 //
1119 DPRINT1("CUsbDevice::SelectConfiguration New Configuration %x Old Configuration %x Result %x\n", ConfigurationDescriptor->iConfiguration, m_ConfigurationIndex, Status);
1120 if (!NT_SUCCESS(Status))
1121 {
1122 //
1123 // failed
1124 //
1125 return Status;
1126 }
1127
1128 //
1129 // store configuration device index
1130 //
1131 m_ConfigurationIndex = ConfigurationDescriptor->iConfiguration;
1132
1133 //
1134 // store configuration handle
1135 //
1136 *ConfigurationHandle = &m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration];
1137
1138 //
1139 // copy interface info and pipe info
1140 //
1141 for(InterfaceIndex = 0; InterfaceIndex < ConfigurationDescriptor->bNumInterfaces; InterfaceIndex++)
1142 {
1143 //
1144 // sanity check: is the info pre-layed out
1145 //
1146 PC_ASSERT(InterfaceInfo->NumberOfPipes == m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].InterfaceDescriptor.bNumEndpoints);
1147 PC_ASSERT(InterfaceInfo->Length != 0);
1148 #ifdef _MSC_VER
1149 PC_ASSERT(InterfaceInfo->Length == FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes[InterfaceInfo->NumberOfPipes]));
1150 #endif
1151
1152 //
1153 // copy interface info
1154 //
1155 InterfaceInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)&m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex];
1156 InterfaceInfo->Class = m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].InterfaceDescriptor.bInterfaceClass;
1157 InterfaceInfo->SubClass = m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].InterfaceDescriptor.bInterfaceSubClass;
1158 InterfaceInfo->Protocol = m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].InterfaceDescriptor.bInterfaceProtocol;
1159 InterfaceInfo->Reserved = 0;
1160
1161 //
1162 // copy endpoint info
1163 //
1164 for(PipeIndex = 0; PipeIndex < InterfaceInfo->NumberOfPipes; PipeIndex++)
1165 {
1166 //
1167 // copy pipe info
1168 //
1169 InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize = m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].EndPoints[PipeIndex].EndPointDescriptor.wMaxPacketSize;
1170 InterfaceInfo->Pipes[PipeIndex].EndpointAddress = m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress;
1171 InterfaceInfo->Pipes[PipeIndex].Interval = m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].EndPoints[PipeIndex].EndPointDescriptor.bInterval;
1172 InterfaceInfo->Pipes[PipeIndex].PipeType = (USBD_PIPE_TYPE)m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].EndPoints[PipeIndex].EndPointDescriptor.bmAttributes;
1173 InterfaceInfo->Pipes[PipeIndex].PipeHandle = (PVOID)&m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].EndPoints[PipeIndex].EndPointDescriptor;
1174
1175 //
1176 // data toggle is reset on configuration requests
1177 //
1178 m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].EndPoints[PipeIndex].DataToggle = FALSE;
1179 }
1180
1181 //
1182 // move offset
1183 //
1184 InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)PtrToUlong(InterfaceInfo) + InterfaceInfo->Length);
1185 }
1186
1187 //
1188 // done
1189 //
1190 return Status;
1191 }
1192
1193 //----------------------------------------------------------------------------------------
1194 NTSTATUS
1195 CUSBDevice::SelectInterface(
1196 IN USBD_CONFIGURATION_HANDLE ConfigurationHandle,
1197 IN OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo)
1198 {
1199 PUSB_CONFIGURATION Configuration;
1200 ULONG PipeIndex;
1201 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1202 NTSTATUS Status;
1203
1204 //
1205 // get configuration struct
1206 //
1207 Configuration = (PUSB_CONFIGURATION)ConfigurationHandle;
1208
1209 //
1210 // sanity check
1211 //
1212 ASSERT(Configuration->ConfigurationDescriptor.bDescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE);
1213 ASSERT(Configuration->ConfigurationDescriptor.bLength == sizeof(USB_CONFIGURATION_DESCRIPTOR));
1214 ASSERT(Configuration->ConfigurationDescriptor.iConfiguration < m_DeviceDescriptor.bNumConfigurations);
1215 ASSERT(&m_ConfigurationDescriptors[Configuration->ConfigurationDescriptor.iConfiguration] == Configuration);
1216
1217 //
1218 // initialize setup packet
1219 //
1220 RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1221 CtrlSetup.bRequest = USB_REQUEST_SET_INTERFACE;
1222 CtrlSetup.wValue.W = Configuration->Interfaces[InterfaceInfo->InterfaceNumber].InterfaceDescriptor.bAlternateSetting;
1223 CtrlSetup.wIndex.W = Configuration->Interfaces[InterfaceInfo->InterfaceNumber].InterfaceDescriptor.bInterfaceNumber;
1224 CtrlSetup.bmRequestType.B = 0x01;
1225
1226 //
1227 // issue request
1228 //
1229 Status = CommitSetupPacket(&CtrlSetup, 0, 0, 0);
1230
1231 //
1232 // informal debug print
1233 //
1234 DPRINT1("CUSBDevice::SelectInterface AlternateSetting %x InterfaceNumber %x Status %x\n", InterfaceInfo->AlternateSetting, InterfaceInfo->InterfaceNumber, Status);
1235 if (!NT_SUCCESS(Status))
1236 {
1237 //
1238 // failed to select interface
1239 //
1240 return Status;
1241 }
1242
1243
1244 //
1245 // sanity checks
1246 //
1247 PC_ASSERT(Configuration->ConfigurationDescriptor.bNumInterfaces > InterfaceInfo->InterfaceNumber);
1248 PC_ASSERT(Configuration->Interfaces[InterfaceInfo->InterfaceNumber].InterfaceDescriptor.bNumEndpoints == InterfaceInfo->NumberOfPipes);
1249 #ifdef _MSC_VER
1250 PC_ASSERT(InterfaceInfo->Length == FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes[InterfaceInfo->NumberOfPipes]));
1251 #endif
1252
1253 //
1254 // copy pipe handles
1255 //
1256 for(PipeIndex = 0; PipeIndex < InterfaceInfo->NumberOfPipes; PipeIndex++)
1257 {
1258 //
1259 // copy pipe handle
1260 //
1261 DPRINT1("PipeIndex %lu\n", PipeIndex);
1262 DPRINT1("EndpointAddress %x\n", InterfaceInfo->Pipes[PipeIndex].EndpointAddress);
1263 DPRINT1("Interval %d\n", InterfaceInfo->Pipes[PipeIndex].Interval);
1264 DPRINT1("MaximumPacketSize %d\n", InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize);
1265 DPRINT1("MaximumTransferSize %d\n", InterfaceInfo->Pipes[PipeIndex].MaximumTransferSize);
1266 DPRINT1("PipeFlags %d\n", InterfaceInfo->Pipes[PipeIndex].PipeFlags);
1267 DPRINT1("PipeType %dd\n", InterfaceInfo->Pipes[PipeIndex].PipeType);
1268 DPRINT1("UsbEndPoint %x\n", Configuration->Interfaces[InterfaceInfo->InterfaceNumber].EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress);
1269 PC_ASSERT(Configuration->Interfaces[InterfaceInfo->InterfaceNumber].EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress == InterfaceInfo->Pipes[PipeIndex].EndpointAddress);
1270
1271 InterfaceInfo->Pipes[PipeIndex].PipeHandle = &Configuration->Interfaces[InterfaceInfo->InterfaceNumber].EndPoints[PipeIndex].EndPointDescriptor;
1272
1273 //
1274 // data toggle is reset on select interface requests
1275 //
1276 m_ConfigurationDescriptors[Configuration->ConfigurationDescriptor.iConfiguration].Interfaces[InterfaceInfo->InterfaceNumber].EndPoints[PipeIndex].DataToggle = FALSE;
1277
1278 if (Configuration->Interfaces[InterfaceInfo->InterfaceNumber].EndPoints[PipeIndex].EndPointDescriptor.bmAttributes & (USB_ENDPOINT_TYPE_ISOCHRONOUS | USB_ENDPOINT_TYPE_INTERRUPT))
1279 {
1280 //
1281 // FIXME: check if enough bandwidth is available
1282 //
1283 }
1284 }
1285
1286
1287 //
1288 // done
1289 //
1290 return Status;
1291 }
1292
1293 NTSTATUS
1294 CUSBDevice::AbortPipe(
1295 IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor)
1296 {
1297 //
1298 // let it handle usb queue
1299 //
1300 ASSERT(m_Queue);
1301 ASSERT(m_DeviceAddress);
1302
1303 //
1304 // done
1305 //
1306 return m_Queue->AbortDevicePipe(m_DeviceAddress, EndpointDescriptor);
1307 }
1308
1309
1310 //----------------------------------------------------------------------------------------
1311 NTSTATUS
1312 CreateUSBDevice(
1313 PUSBDEVICE *OutDevice)
1314 {
1315 CUSBDevice * This;
1316
1317 //
1318 // allocate controller
1319 //
1320 This = new(NonPagedPool, TAG_USBEHCI) CUSBDevice(0);
1321 if (!This)
1322 {
1323 //
1324 // failed to allocate
1325 //
1326 return STATUS_INSUFFICIENT_RESOURCES;
1327 }
1328
1329 //
1330 // add reference count
1331 //
1332 This->AddRef();
1333
1334 //
1335 // return result
1336 //
1337 *OutDevice = (PUSBDEVICE)This;
1338
1339 //
1340 // done
1341 //
1342 return STATUS_SUCCESS;
1343 }
1344