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