[LIBUSB][USBCCGP][USBEHCI]
[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 %x\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, NULL, 0, NULL);
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 %lx 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("CUSBDevice::SetDeviceAddress> failed to retrieve device descriptor with device address set Error %lx\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("CUSBDevice::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::CommitIrp> 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::CommitIrp> CreateUSBRequest failed with %lx\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::CommitIrp> failed add request to queue with %lx\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 //----------------------------------------------------------------------------------------
507 NTSTATUS
508 CUSBDevice::CommitSetupPacket(
509 IN PUSB_DEFAULT_PIPE_SETUP_PACKET Packet,
510 IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor,
511 IN ULONG BufferLength,
512 IN OUT PMDL Mdl)
513 {
514 NTSTATUS Status;
515 PUSBREQUEST Request;
516
517 if (!m_Queue)
518 {
519 //
520 // no queue, wtf?
521 //
522 DPRINT1("CUSBDevice::CommitSetupPacket> no queue!!!\n");
523 return STATUS_UNSUCCESSFUL;
524 }
525
526 //
527 // build usb request
528 //
529 Status = m_Queue->CreateUSBRequest(&Request);
530 if (!NT_SUCCESS(Status))
531 {
532 //
533 // failed to build request
534 //
535 DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with %x\n", Status);
536 return Status;
537 }
538
539 //
540 // initialize request
541 //
542 Status = Request->InitializeWithSetupPacket(m_DmaManager, Packet, PUSBDEVICE(this), EndpointDescriptor, BufferLength, Mdl);
543 if (!NT_SUCCESS(Status))
544 {
545 //
546 // failed to initialize request
547 //
548 DPRINT1("CUSBDevice::CommitSetupPacket> failed to initialize usb request with %x\n", Status);
549 Request->Release();
550 return Status;
551 }
552
553 //
554 // now add the request
555 //
556 Status = m_Queue->AddUSBRequest(Request);
557 if (!NT_SUCCESS(Status))
558 {
559 //
560 // failed to add request
561 //
562 DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with %x\n", Status);
563 Request->Release();
564 return Status;
565 }
566
567 //
568 // get the result code when the operation has been finished
569 //
570 Request->GetResultStatus(&Status, NULL);
571
572 //
573 // release request
574 //
575 Request->Release();
576
577 //
578 // done
579 //
580 return Status;
581 }
582
583 //----------------------------------------------------------------------------------------
584 NTSTATUS
585 CUSBDevice::CreateDeviceDescriptor()
586 {
587 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
588 PMDL Mdl;
589 NTSTATUS Status;
590 PVOID Buffer;
591
592 //
593 // zero descriptor
594 //
595 RtlZeroMemory(&m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
596 RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
597
598 //
599 // setup request
600 //
601 CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
602 CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
603 CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR);
604 CtrlSetup.bmRequestType.B = 0x80;
605
606 //
607 // allocate buffer
608 //
609 Buffer = ExAllocatePool(NonPagedPool, PAGE_SIZE);
610 if (!Buffer)
611 {
612 //
613 // failed to allocate
614 //
615 return STATUS_INSUFFICIENT_RESOURCES;
616 }
617
618 //
619 // zero buffer
620 //
621 RtlZeroMemory(Buffer, PAGE_SIZE);
622
623 //
624 // allocate mdl describing the device descriptor
625 //
626 Mdl = IoAllocateMdl(Buffer, sizeof(USB_DEVICE_DESCRIPTOR), FALSE, FALSE, 0);
627 if (!Mdl)
628 {
629 //
630 // failed to allocate mdl
631 //
632 return STATUS_INSUFFICIENT_RESOURCES;
633 }
634
635 //
636 // build mdl for non paged pool
637 //
638 MmBuildMdlForNonPagedPool(Mdl);
639
640 //
641 // commit setup packet
642 //
643 Status = CommitSetupPacket(&CtrlSetup, NULL, sizeof(USB_DEVICE_DESCRIPTOR), Mdl);
644
645 //
646 // now free the mdl
647 //
648 IoFreeMdl(Mdl);
649
650 if (NT_SUCCESS(Status))
651 {
652 //
653 // copy device descriptor
654 //
655 RtlCopyMemory(&m_DeviceDescriptor, Buffer, sizeof(USB_DEVICE_DESCRIPTOR));
656 }
657
658 //
659 // free buffer
660 //
661 ExFreePool(Buffer);
662
663 //
664 // done
665 //
666 return Status;
667
668 }
669
670 //----------------------------------------------------------------------------------------
671 NTSTATUS
672 CUSBDevice::GetConfigurationDescriptor(
673 IN UCHAR ConfigurationIndex,
674 IN USHORT BufferSize,
675 IN PVOID Buffer)
676 {
677 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
678 NTSTATUS Status;
679 PMDL Mdl;
680
681
682 //
683 // now build MDL describing the buffer
684 //
685 Mdl = IoAllocateMdl(Buffer, BufferSize, FALSE, FALSE, 0);
686 if (!Mdl)
687 {
688 //
689 // failed to allocate mdl
690 //
691 return STATUS_INSUFFICIENT_RESOURCES;
692 }
693
694 //
695 // build mdl for non paged pool
696 //
697 MmBuildMdlForNonPagedPool(Mdl);
698
699
700 //
701 // build setup packet
702 //
703 CtrlSetup.bmRequestType._BM.Recipient = BMREQUEST_TO_DEVICE;
704 CtrlSetup.bmRequestType._BM.Type = BMREQUEST_STANDARD;
705 CtrlSetup.bmRequestType._BM.Reserved = 0;
706 CtrlSetup.bmRequestType._BM.Dir = BMREQUEST_DEVICE_TO_HOST;
707 CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
708 CtrlSetup.wValue.LowByte = ConfigurationIndex;
709 CtrlSetup.wValue.HiByte = USB_CONFIGURATION_DESCRIPTOR_TYPE;
710 CtrlSetup.wIndex.W = 0;
711 CtrlSetup.wLength = BufferSize;
712
713 //
714 // commit packet
715 //
716 Status = CommitSetupPacket(&CtrlSetup, NULL, BufferSize, Mdl);
717
718 //
719 // free mdl
720 //
721 IoFreeMdl(Mdl);
722
723 //
724 // done
725 //
726 return Status;
727 }
728
729 //----------------------------------------------------------------------------------------
730 NTSTATUS
731 CUSBDevice::CreateConfigurationDescriptor(
732 UCHAR Index)
733 {
734 NTSTATUS Status;
735 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
736
737 //
738 // sanity checks
739 //
740 PC_ASSERT(m_ConfigurationDescriptors);
741
742 //
743 // first allocate a buffer which should be enough to store all different interfaces and endpoints
744 //
745 ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, TAG_USBLIB);
746 if (!ConfigurationDescriptor)
747 {
748 //
749 // failed to allocate buffer
750 //
751 return STATUS_INSUFFICIENT_RESOURCES;
752 }
753
754 //
755 // get partial configuration descriptor
756 //
757 Status = GetConfigurationDescriptor(Index, sizeof(USB_CONFIGURATION_DESCRIPTOR), ConfigurationDescriptor);
758 if (!NT_SUCCESS(Status))
759 {
760 //
761 // failed to get partial configuration descriptor
762 //
763 DPRINT1("[USBLIB] Failed to get partial configuration descriptor Status %x Index %x\n", Status, Index);
764 ExFreePoolWithTag(ConfigurationDescriptor, TAG_USBLIB);
765 return Status;
766 }
767
768 //
769 // now get full descriptor
770 //
771 Status = GetConfigurationDescriptor(Index, ConfigurationDescriptor->wTotalLength, ConfigurationDescriptor);
772 if (!NT_SUCCESS(Status))
773 {
774 //
775 // failed to get full configuration descriptor
776 //
777 DPRINT1("[USBLIB] Failed to get full configuration descriptor Status %x Index %x\n", Status, Index);
778 ExFreePoolWithTag(ConfigurationDescriptor, TAG_USBLIB);
779 return Status;
780 }
781
782 //
783 // informal debug print
784 //
785 DumpConfigurationDescriptor(ConfigurationDescriptor);
786
787 //
788 // sanity check
789 //
790 PC_ASSERT(ConfigurationDescriptor->bLength == sizeof(USB_CONFIGURATION_DESCRIPTOR));
791 PC_ASSERT(ConfigurationDescriptor->wTotalLength <= PAGE_SIZE);
792 PC_ASSERT(ConfigurationDescriptor->bNumInterfaces);
793
794 //
795 // request is complete, initialize configuration descriptor
796 //
797 m_ConfigurationDescriptors[Index].ConfigurationDescriptor = ConfigurationDescriptor;
798 InitializeListHead(&m_ConfigurationDescriptors[Index].InterfaceList);
799
800 //
801 // done
802 //
803 return Status;
804 }
805 //----------------------------------------------------------------------------------------
806 VOID
807 CUSBDevice::GetConfigurationDescriptors(
808 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer,
809 IN ULONG BufferLength,
810 OUT PULONG OutBufferLength)
811 {
812 ULONG Length;
813
814 // sanity check
815 ASSERT(BufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
816 ASSERT(ConfigDescriptorBuffer);
817 ASSERT(OutBufferLength);
818
819 // reset copied length
820 *OutBufferLength = 0;
821
822 // FIXME: support multiple configurations
823 PC_ASSERT(m_DeviceDescriptor.bNumConfigurations == 1);
824
825 // copy configuration descriptor
826 Length = min(m_ConfigurationDescriptors[0].ConfigurationDescriptor->wTotalLength, BufferLength);
827 RtlCopyMemory(ConfigDescriptorBuffer, m_ConfigurationDescriptors[0].ConfigurationDescriptor, Length);
828 *OutBufferLength = Length;
829 }
830
831 //----------------------------------------------------------------------------------------
832 ULONG
833 CUSBDevice::GetConfigurationDescriptorsLength()
834 {
835 //
836 // FIXME: support multiple configurations
837 //
838 PC_ASSERT(m_DeviceDescriptor.bNumConfigurations == 1);
839
840 return m_ConfigurationDescriptors[0].ConfigurationDescriptor->wTotalLength;
841 }
842 //----------------------------------------------------------------------------------------
843 VOID
844 CUSBDevice::DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
845 {
846 DPRINT1("Dumping Device Descriptor %x\n", DeviceDescriptor);
847 DPRINT1("bLength %x\n", DeviceDescriptor->bLength);
848 DPRINT1("bDescriptorType %x\n", DeviceDescriptor->bDescriptorType);
849 DPRINT1("bcdUSB %x\n", DeviceDescriptor->bcdUSB);
850 DPRINT1("bDeviceClass %x\n", DeviceDescriptor->bDeviceClass);
851 DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor->bDeviceSubClass);
852 DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor->bDeviceProtocol);
853 DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor->bMaxPacketSize0);
854 DPRINT1("idVendor %x\n", DeviceDescriptor->idVendor);
855 DPRINT1("idProduct %x\n", DeviceDescriptor->idProduct);
856 DPRINT1("bcdDevice %x\n", DeviceDescriptor->bcdDevice);
857 DPRINT1("iManufacturer %x\n", DeviceDescriptor->iManufacturer);
858 DPRINT1("iProduct %x\n", DeviceDescriptor->iProduct);
859 DPRINT1("iSerialNumber %x\n", DeviceDescriptor->iSerialNumber);
860 DPRINT1("bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations);
861 }
862
863 //----------------------------------------------------------------------------------------
864 VOID
865 CUSBDevice::DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
866 {
867 DPRINT1("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor);
868 DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength);
869 DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
870 DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
871 DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
872 DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
873 DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
874 DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
875 DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
876 }
877 //----------------------------------------------------------------------------------------
878 NTSTATUS
879 CUSBDevice::SubmitSetupPacket(
880 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
881 IN OUT ULONG BufferLength,
882 OUT PVOID Buffer)
883 {
884 NTSTATUS Status;
885 PMDL Mdl = NULL;
886
887 if (BufferLength)
888 {
889 //
890 // allocate mdl
891 //
892 Mdl = IoAllocateMdl(Buffer, BufferLength, FALSE, FALSE, 0);
893 if (!Mdl)
894 {
895 //
896 // no memory
897 //
898 return STATUS_INSUFFICIENT_RESOURCES;
899 }
900
901 //
902 // HACK HACK HACK: assume the buffer is build from non paged pool
903 //
904 MmBuildMdlForNonPagedPool(Mdl);
905 }
906
907 //
908 // commit setup packet
909 //
910 Status = CommitSetupPacket(SetupPacket, NULL, BufferLength, Mdl);
911
912 if (Mdl != NULL)
913 {
914 //
915 // free mdl
916 //
917 IoFreeMdl(Mdl);
918 }
919
920 //
921 // done
922 //
923 return Status;
924 }
925 //----------------------------------------------------------------------------------------
926 NTSTATUS
927 CUSBDevice::BuildInterfaceDescriptor(
928 IN ULONG ConfigurationIndex,
929 IN PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor,
930 OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo,
931 OUT PUSB_INTERFACE *OutUsbInterface)
932 {
933 PUSB_INTERFACE UsbInterface;
934 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
935 ULONG PipeIndex;
936
937 // allocate interface handle
938 UsbInterface = (PUSB_INTERFACE)ExAllocatePool(NonPagedPool, sizeof(USB_INTERFACE) + (InterfaceDescriptor->bNumEndpoints - 1) * sizeof(USB_ENDPOINT));
939 if (!UsbInterface)
940 {
941 // failed to allocate memory
942 return STATUS_INSUFFICIENT_RESOURCES;
943 }
944
945 // zero descriptor
946 RtlZeroMemory(UsbInterface, sizeof(USB_INTERFACE) + (InterfaceDescriptor->bNumEndpoints - 1) * sizeof(USB_ENDPOINT));
947
948 // store handle
949 InterfaceInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)UsbInterface;
950 InterfaceInfo->Class = InterfaceDescriptor->bInterfaceClass;
951 InterfaceInfo->SubClass = InterfaceDescriptor->bInterfaceSubClass;
952 InterfaceInfo->Protocol = InterfaceDescriptor->bInterfaceProtocol;
953 InterfaceInfo->Reserved = 0;
954
955
956 // init interface handle
957 UsbInterface->InterfaceDescriptor = InterfaceDescriptor;
958 InsertTailList(&m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList, &UsbInterface->ListEntry);
959
960 // grab first endpoint descriptor
961 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) (InterfaceDescriptor + 1);
962
963 // now copy all endpoint information
964 for(PipeIndex = 0; PipeIndex < InterfaceDescriptor->bNumEndpoints; PipeIndex++)
965 {
966 while(EndpointDescriptor->bDescriptorType != USB_ENDPOINT_DESCRIPTOR_TYPE)
967 {
968 // skip intermediate descriptors
969 if (EndpointDescriptor->bLength == 0 || EndpointDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
970 {
971 // bogus configuration descriptor
972 DPRINT1("[USBLIB] Bogus descriptor found in InterfaceNumber %x Alternate %x EndpointIndex %x bLength %x bDescriptorType %x\n", InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting, PipeIndex,
973 EndpointDescriptor->bLength, EndpointDescriptor->bDescriptorType);
974
975 // failed
976 return STATUS_UNSUCCESSFUL;
977 }
978
979 // move to next descriptor
980 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)EndpointDescriptor + EndpointDescriptor->bLength);
981 }
982
983 // store in interface info
984 RtlCopyMemory(&UsbInterface->EndPoints[PipeIndex].EndPointDescriptor, EndpointDescriptor, sizeof(USB_ENDPOINT_DESCRIPTOR));
985
986 DPRINT("Configuration Descriptor %p Length %lu\n", m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor, m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor->wTotalLength);
987 DPRINT("EndpointDescriptor %p DescriptorType %x bLength %x\n", EndpointDescriptor, EndpointDescriptor->bDescriptorType, EndpointDescriptor->bLength);
988 DPRINT("EndpointDescriptorHandle %p bAddress %x bmAttributes %x\n",&UsbInterface->EndPoints[PipeIndex], UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress,
989 UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bmAttributes);
990
991 // copy pipe info
992 InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize = UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.wMaxPacketSize;
993 InterfaceInfo->Pipes[PipeIndex].EndpointAddress = UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress;
994 InterfaceInfo->Pipes[PipeIndex].Interval = UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bInterval;
995 InterfaceInfo->Pipes[PipeIndex].PipeType = (USBD_PIPE_TYPE)UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bmAttributes;
996 InterfaceInfo->Pipes[PipeIndex].PipeHandle = (PVOID)&UsbInterface->EndPoints[PipeIndex];
997
998 // move to next descriptor
999 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)EndpointDescriptor + EndpointDescriptor->bLength);
1000 }
1001
1002 if (OutUsbInterface)
1003 {
1004 // output result
1005 *OutUsbInterface = UsbInterface;
1006 }
1007 return STATUS_SUCCESS;
1008
1009 }
1010
1011
1012 //----------------------------------------------------------------------------------------
1013 NTSTATUS
1014 CUSBDevice::SelectConfiguration(
1015 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
1016 IN PUSBD_INTERFACE_INFORMATION InterfaceInfo,
1017 OUT USBD_CONFIGURATION_HANDLE *ConfigurationHandle)
1018 {
1019 ULONG InterfaceIndex;
1020 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1021 NTSTATUS Status;
1022 UCHAR bConfigurationValue = 0;
1023 ULONG ConfigurationIndex = 0, Index;
1024 UCHAR Found = FALSE;
1025 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
1026 PUSB_INTERFACE UsbInterface;
1027 PLIST_ENTRY Entry;
1028
1029 if (ConfigurationDescriptor)
1030 {
1031 // find configuration index
1032 for(Index = 0; Index < m_DeviceDescriptor.bNumConfigurations; Index++)
1033 {
1034 if (m_ConfigurationDescriptors[Index].ConfigurationDescriptor->bConfigurationValue == ConfigurationDescriptor->bConfigurationValue)
1035 {
1036 // found configuration index
1037 ConfigurationIndex = Index;
1038 Found = TRUE;
1039 }
1040 }
1041
1042 if (!Found)
1043 {
1044 DPRINT1("[USBLIB] invalid configuration value %lu\n", ConfigurationDescriptor->bConfigurationValue);
1045 return STATUS_INVALID_PARAMETER;
1046 }
1047
1048 // sanity check
1049 ASSERT(ConfigurationDescriptor->bNumInterfaces <= m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor->bNumInterfaces);
1050
1051 // get configuration value
1052 bConfigurationValue = ConfigurationDescriptor->bConfigurationValue;
1053 }
1054
1055 // now build setup packet
1056 RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1057 CtrlSetup.bRequest = USB_REQUEST_SET_CONFIGURATION;
1058 CtrlSetup.wValue.W = bConfigurationValue;
1059
1060 // select configuration
1061 Status = CommitSetupPacket(&CtrlSetup, NULL, 0, NULL);
1062
1063 if (!ConfigurationDescriptor)
1064 {
1065 // unconfigure request
1066 DPRINT1("CUSBDevice::SelectConfiguration Unconfigure Request Status %x\n", Status);
1067 m_ConfigurationIndex = 0;
1068 return Status;
1069 }
1070
1071 // informal debug print
1072 DPRINT1("CUSBDevice::SelectConfiguration New Configuration %x Old Configuration %x Result %x\n", ConfigurationIndex, m_ConfigurationIndex, Status);
1073 if (!NT_SUCCESS(Status))
1074 {
1075 //
1076 // failed
1077 //
1078 return Status;
1079 }
1080
1081 // destroy old interface info
1082 while(!IsListEmpty(&m_ConfigurationDescriptors[m_ConfigurationIndex].InterfaceList))
1083 {
1084 // remove entry
1085 Entry = RemoveHeadList(&m_ConfigurationDescriptors[m_ConfigurationIndex].InterfaceList);
1086
1087 // get interface info
1088 UsbInterface = (PUSB_INTERFACE)CONTAINING_RECORD(Entry, USB_INTERFACE, ListEntry);
1089
1090 // free interface info
1091 ExFreePool(UsbInterface);
1092 }
1093
1094 // sanity check
1095 ASSERT(IsListEmpty(&m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList));
1096
1097 // store new configuration device index
1098 m_ConfigurationIndex = ConfigurationIndex;
1099
1100 // store configuration handle
1101 *ConfigurationHandle = &m_ConfigurationDescriptors[ConfigurationIndex];
1102
1103 // copy interface info and pipe info
1104 for(InterfaceIndex = 0; InterfaceIndex < ConfigurationDescriptor->bNumInterfaces; InterfaceIndex++)
1105 {
1106 // interface info checks
1107 ASSERT(InterfaceInfo->Length != 0);
1108
1109 #ifdef _MSC_VER
1110 PC_ASSERT(InterfaceInfo->Length == FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes[InterfaceInfo->NumberOfPipes]));
1111 #endif
1112
1113 // find interface descriptor
1114 InterfaceDescriptor = USBD_ParseConfigurationDescriptor(m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor, InterfaceInfo->InterfaceNumber, InterfaceInfo->AlternateSetting);
1115
1116 // sanity checks
1117 ASSERT(InterfaceDescriptor != NULL);
1118
1119 // check if the number of pipes have been properly set
1120 ASSERT(InterfaceInfo->NumberOfPipes == InterfaceDescriptor->bNumEndpoints);
1121
1122 // copy interface info
1123 Status = BuildInterfaceDescriptor(ConfigurationIndex, InterfaceDescriptor, InterfaceInfo, NULL);
1124 if (!NT_SUCCESS(Status))
1125 {
1126 // failed
1127 break;
1128 }
1129
1130 // move offset
1131 InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)InterfaceInfo + InterfaceInfo->Length);
1132 }
1133
1134 //
1135 // done
1136 //
1137 return Status;
1138 }
1139
1140 //----------------------------------------------------------------------------------------
1141 NTSTATUS
1142 CUSBDevice::SelectInterface(
1143 IN USBD_CONFIGURATION_HANDLE ConfigurationHandle,
1144 IN OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo)
1145 {
1146 ULONG PipeIndex;
1147 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1148 NTSTATUS Status;
1149 ULONG Index, ConfigurationIndex = 0, Found = FALSE;
1150 PUSB_INTERFACE UsbInterface;
1151 PLIST_ENTRY Entry;
1152 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
1153
1154 // check if handle is valid
1155 for(Index = 0; Index < m_DeviceDescriptor.bNumConfigurations; Index++)
1156 {
1157 if (&m_ConfigurationDescriptors[Index] == ConfigurationHandle)
1158 {
1159 // found configuration index
1160 ConfigurationIndex = Index;
1161 Found = TRUE;
1162 }
1163 }
1164
1165 if (!Found)
1166 {
1167 // invalid handle passed
1168 DPRINT1("[USBLIB] Invalid configuration handle passed %p\n", ConfigurationHandle);
1169 return STATUS_INVALID_PARAMETER;
1170 }
1171
1172 // initialize setup packet
1173 RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1174 CtrlSetup.bRequest = USB_REQUEST_SET_INTERFACE;
1175 CtrlSetup.wValue.W = InterfaceInfo->AlternateSetting;
1176 CtrlSetup.wIndex.W = InterfaceInfo->InterfaceNumber;
1177 CtrlSetup.bmRequestType.B = 0x01;
1178
1179 // issue request
1180 Status = CommitSetupPacket(&CtrlSetup, NULL, 0, NULL);
1181
1182 // informal debug print
1183 DPRINT1("CUSBDevice::SelectInterface AlternateSetting %x InterfaceNumber %x Status %x\n", InterfaceInfo->AlternateSetting, InterfaceInfo->InterfaceNumber, Status);
1184 #if 0
1185 if (!NT_SUCCESS(Status))
1186 {
1187 // failed to select interface
1188 return Status;
1189 }
1190 #endif
1191
1192 Status = STATUS_SUCCESS;
1193
1194
1195 // find interface
1196 Found = FALSE;
1197 Entry = m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList.Flink;
1198 while(Entry != &m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList)
1199 {
1200 // grab interface descriptor
1201 UsbInterface = (PUSB_INTERFACE)CONTAINING_RECORD(Entry, USB_INTERFACE, ListEntry);
1202 if (UsbInterface->InterfaceDescriptor->bAlternateSetting == InterfaceInfo->AlternateSetting &&
1203 UsbInterface->InterfaceDescriptor->bInterfaceNumber == InterfaceInfo->InterfaceNumber)
1204 {
1205 // found interface
1206 Found = TRUE;
1207 break;
1208 }
1209
1210 // next entry
1211 Entry = Entry->Flink;
1212 }
1213
1214 if (!Found)
1215 {
1216 // find interface descriptor
1217 InterfaceDescriptor = USBD_ParseConfigurationDescriptor(m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor, InterfaceInfo->InterfaceNumber, InterfaceInfo->AlternateSetting);
1218 if (!InterfaceDescriptor)
1219 {
1220 DPRINT1("[LIBUSB] No such interface Alternate %x InterfaceNumber %x\n", InterfaceInfo->AlternateSetting, InterfaceInfo->InterfaceNumber);
1221 return STATUS_UNSUCCESSFUL;
1222 }
1223
1224 // build interface descriptor
1225 Status = BuildInterfaceDescriptor(ConfigurationIndex, InterfaceDescriptor, InterfaceInfo, &UsbInterface);
1226 if (!NT_SUCCESS(Status))
1227 {
1228 // failed
1229 DPRINT1("[LIBUSB] Failed to build interface descriptor Status %x\n", Status);
1230 return Status;
1231 }
1232 }
1233
1234 // assert on pipe length mismatch
1235 DPRINT1("NumberOfPipes %lu Endpoints %lu Length %lu\n", InterfaceInfo->NumberOfPipes, UsbInterface->InterfaceDescriptor->bNumEndpoints, InterfaceInfo->Length);
1236
1237 // sanity check
1238 ASSERT(GET_USBD_INTERFACE_SIZE(UsbInterface->InterfaceDescriptor->bNumEndpoints) == InterfaceInfo->Length);
1239
1240 // store number of pipes
1241 InterfaceInfo->NumberOfPipes = UsbInterface->InterfaceDescriptor->bNumEndpoints;
1242
1243 // copy pipe handles
1244 for(PipeIndex = 0; PipeIndex < UsbInterface->InterfaceDescriptor->bNumEndpoints; PipeIndex++)
1245 {
1246 // copy pipe handle
1247 DPRINT1("PipeIndex %lu\n", PipeIndex);
1248 DPRINT1("EndpointAddress %x\n", InterfaceInfo->Pipes[PipeIndex].EndpointAddress);
1249 DPRINT1("Interval %d\n", InterfaceInfo->Pipes[PipeIndex].Interval);
1250 DPRINT1("MaximumPacketSize %d\n", InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize);
1251 DPRINT1("MaximumTransferSize %d\n", InterfaceInfo->Pipes[PipeIndex].MaximumTransferSize);
1252 DPRINT1("PipeFlags %d\n", InterfaceInfo->Pipes[PipeIndex].PipeFlags);
1253 DPRINT1("PipeType %dd\n", InterfaceInfo->Pipes[PipeIndex].PipeType);
1254 DPRINT1("UsbEndPoint %x\n", InterfaceInfo->Pipes[PipeIndex].EndpointAddress);
1255
1256 // sanity checks
1257 ASSERT(InterfaceInfo->Pipes[PipeIndex].EndpointAddress == UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress);
1258 ASSERT(InterfaceInfo->Pipes[PipeIndex].Interval == UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bInterval);
1259
1260 // store pipe handle
1261 InterfaceInfo->Pipes[PipeIndex].PipeHandle = &UsbInterface->EndPoints[PipeIndex];
1262
1263 // data toggle is reset on select interface requests
1264 UsbInterface->EndPoints[PipeIndex].DataToggle = FALSE;
1265 }
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