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