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