[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 %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, 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 %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, 0, 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, 0, 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 // 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 RtlCopyMemory(ConfigDescriptorBuffer, m_ConfigurationDescriptors[0].ConfigurationDescriptor, min(m_ConfigurationDescriptors[0].ConfigurationDescriptor->wTotalLength, BufferLength));
825 *OutBufferLength = m_ConfigurationDescriptors[0].ConfigurationDescriptor->wTotalLength;
826 }
827
828 //----------------------------------------------------------------------------------------
829 ULONG
830 CUSBDevice::GetConfigurationDescriptorsLength()
831 {
832 //
833 // FIXME: support multiple configurations
834 //
835 PC_ASSERT(m_DeviceDescriptor.bNumConfigurations == 1);
836
837 return m_ConfigurationDescriptors[0].ConfigurationDescriptor->wTotalLength;
838 }
839 //----------------------------------------------------------------------------------------
840 VOID
841 CUSBDevice::DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
842 {
843 DPRINT1("Dumping Device Descriptor %x\n", DeviceDescriptor);
844 DPRINT1("bLength %x\n", DeviceDescriptor->bLength);
845 DPRINT1("bDescriptorType %x\n", DeviceDescriptor->bDescriptorType);
846 DPRINT1("bcdUSB %x\n", DeviceDescriptor->bcdUSB);
847 DPRINT1("bDeviceClass %x\n", DeviceDescriptor->bDeviceClass);
848 DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor->bDeviceSubClass);
849 DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor->bDeviceProtocol);
850 DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor->bMaxPacketSize0);
851 DPRINT1("idVendor %x\n", DeviceDescriptor->idVendor);
852 DPRINT1("idProduct %x\n", DeviceDescriptor->idProduct);
853 DPRINT1("bcdDevice %x\n", DeviceDescriptor->bcdDevice);
854 DPRINT1("iManufacturer %x\n", DeviceDescriptor->iManufacturer);
855 DPRINT1("iProduct %x\n", DeviceDescriptor->iProduct);
856 DPRINT1("iSerialNumber %x\n", DeviceDescriptor->iSerialNumber);
857 DPRINT1("bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations);
858 }
859
860 //----------------------------------------------------------------------------------------
861 VOID
862 CUSBDevice::DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
863 {
864 DPRINT1("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor);
865 DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength);
866 DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
867 DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
868 DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
869 DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
870 DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
871 DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
872 DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
873 }
874 //----------------------------------------------------------------------------------------
875 NTSTATUS
876 CUSBDevice::SubmitSetupPacket(
877 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
878 IN OUT ULONG BufferLength,
879 OUT PVOID Buffer)
880 {
881 NTSTATUS Status;
882 PMDL Mdl = NULL;
883
884 if (BufferLength)
885 {
886 //
887 // allocate mdl
888 //
889 Mdl = IoAllocateMdl(Buffer, BufferLength, FALSE, FALSE, 0);
890 if (!Mdl)
891 {
892 //
893 // no memory
894 //
895 return STATUS_INSUFFICIENT_RESOURCES;
896 }
897
898 //
899 // HACK HACK HACK: assume the buffer is build from non paged pool
900 //
901 MmBuildMdlForNonPagedPool(Mdl);
902 }
903
904 //
905 // commit setup packet
906 //
907 Status = CommitSetupPacket(SetupPacket, 0, BufferLength, Mdl);
908
909 if (Mdl != NULL)
910 {
911 //
912 // free mdl
913 //
914 IoFreeMdl(Mdl);
915 }
916
917 //
918 // done
919 //
920 return Status;
921 }
922 //----------------------------------------------------------------------------------------
923 NTSTATUS
924 CUSBDevice::BuildInterfaceDescriptor(
925 IN ULONG ConfigurationIndex,
926 IN PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor,
927 OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo,
928 OUT PUSB_INTERFACE *OutUsbInterface)
929 {
930 PUSB_INTERFACE UsbInterface;
931 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
932 ULONG PipeIndex;
933
934 // allocate interface handle
935 UsbInterface = (PUSB_INTERFACE)ExAllocatePool(NonPagedPool, sizeof(USB_INTERFACE) + (InterfaceDescriptor->bNumEndpoints - 1) * sizeof(USB_ENDPOINT));
936 if (!UsbInterface)
937 {
938 // failed to allocate memory
939 return STATUS_INSUFFICIENT_RESOURCES;
940 }
941
942 // zero descriptor
943 RtlZeroMemory(UsbInterface, sizeof(USB_INTERFACE) + (InterfaceDescriptor->bNumEndpoints - 1) * sizeof(USB_ENDPOINT));
944
945 // store handle
946 InterfaceInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)UsbInterface;
947 InterfaceInfo->Class = InterfaceDescriptor->bInterfaceClass;
948 InterfaceInfo->SubClass = InterfaceDescriptor->bInterfaceSubClass;
949 InterfaceInfo->Protocol = InterfaceDescriptor->bInterfaceProtocol;
950 InterfaceInfo->Reserved = 0;
951
952
953 // init interface handle
954 UsbInterface->InterfaceDescriptor = InterfaceDescriptor;
955 InsertTailList(&m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList, &UsbInterface->ListEntry);
956
957 // grab first endpoint descriptor
958 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) (InterfaceDescriptor + 1);
959
960 // now copy all endpoint information
961 for(PipeIndex = 0; PipeIndex < InterfaceDescriptor->bNumEndpoints; PipeIndex++)
962 {
963 while(EndpointDescriptor->bDescriptorType != USB_ENDPOINT_DESCRIPTOR_TYPE)
964 {
965 // skip intermediate descriptors
966 if (EndpointDescriptor->bLength == 0 || EndpointDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
967 {
968 // bogus configuration descriptor
969 DPRINT1("[USBLIB] Bogus descriptor found in InterfaceNumber %x Alternate %x EndpointIndex %x bLength %x bDescriptorType %x\n", InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting, PipeIndex,
970 EndpointDescriptor->bLength, EndpointDescriptor->bDescriptorType);
971
972 // failed
973 return STATUS_UNSUCCESSFUL;
974 }
975
976 // move to next descriptor
977 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)EndpointDescriptor + EndpointDescriptor->bLength);
978 }
979
980 // store in interface info
981 RtlCopyMemory(&UsbInterface->EndPoints[PipeIndex].EndPointDescriptor, EndpointDescriptor, sizeof(USB_ENDPOINT_DESCRIPTOR));
982
983 DPRINT("Configuration Descriptor %p Length %lu\n", m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor, m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor->wTotalLength);
984 DPRINT("EndpointDescriptor %p DescriptorType %x bLength %x\n", EndpointDescriptor, EndpointDescriptor->bDescriptorType, EndpointDescriptor->bLength);
985 DPRINT("EndpointDescriptorHandle %p bAddress %x bmAttributes %x\n",&UsbInterface->EndPoints[PipeIndex], UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress,
986 UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bmAttributes);
987
988 // copy pipe info
989 InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize = UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.wMaxPacketSize;
990 InterfaceInfo->Pipes[PipeIndex].EndpointAddress = UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress;
991 InterfaceInfo->Pipes[PipeIndex].Interval = UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bInterval;
992 InterfaceInfo->Pipes[PipeIndex].PipeType = (USBD_PIPE_TYPE)UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bmAttributes;
993 InterfaceInfo->Pipes[PipeIndex].PipeHandle = (PVOID)&UsbInterface->EndPoints[PipeIndex];
994
995 // move to next descriptor
996 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)EndpointDescriptor + EndpointDescriptor->bLength);
997 }
998
999 if (OutUsbInterface)
1000 {
1001 // output result
1002 *OutUsbInterface = UsbInterface;
1003 }
1004 return STATUS_SUCCESS;
1005
1006 }
1007
1008
1009 //----------------------------------------------------------------------------------------
1010 NTSTATUS
1011 CUSBDevice::SelectConfiguration(
1012 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
1013 IN PUSBD_INTERFACE_INFORMATION InterfaceInfo,
1014 OUT USBD_CONFIGURATION_HANDLE *ConfigurationHandle)
1015 {
1016 ULONG InterfaceIndex;
1017 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1018 NTSTATUS Status;
1019 UCHAR bConfigurationValue = 0;
1020 ULONG ConfigurationIndex = 0, Index;
1021 UCHAR Found = FALSE;
1022 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
1023 PUSB_INTERFACE UsbInterface;
1024 PLIST_ENTRY Entry;
1025
1026 if (ConfigurationDescriptor)
1027 {
1028 // find configuration index
1029 for(Index = 0; Index < m_DeviceDescriptor.bNumConfigurations; Index++)
1030 {
1031 if (m_ConfigurationDescriptors[Index].ConfigurationDescriptor->bConfigurationValue == ConfigurationDescriptor->bConfigurationValue)
1032 {
1033 // found configuration index
1034 ConfigurationIndex = Index;
1035 Found = TRUE;
1036 }
1037 }
1038
1039 if (!Found)
1040 {
1041 DPRINT1("[USBLIB] invalid configuration value %lu\n", ConfigurationDescriptor->bConfigurationValue);
1042 return STATUS_INVALID_PARAMETER;
1043 }
1044
1045 // sanity check
1046 ASSERT(ConfigurationDescriptor->bNumInterfaces <= m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor->bNumInterfaces);
1047
1048 // get configuration value
1049 bConfigurationValue = ConfigurationDescriptor->bConfigurationValue;
1050 }
1051
1052 // now build setup packet
1053 RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1054 CtrlSetup.bRequest = USB_REQUEST_SET_CONFIGURATION;
1055 CtrlSetup.wValue.W = bConfigurationValue;
1056
1057 // select configuration
1058 Status = CommitSetupPacket(&CtrlSetup, 0, 0, 0);
1059
1060 if (!ConfigurationDescriptor)
1061 {
1062 // unconfigure request
1063 DPRINT1("CUSBDevice::SelectConfiguration Unconfigure Request Status %x\n", Status);
1064 m_ConfigurationIndex = 0;
1065 return Status;
1066 }
1067
1068 // informal debug print
1069 DPRINT1("CUSBDevice::SelectConfiguration New Configuration %x Old Configuration %x Result %x\n", ConfigurationIndex, m_ConfigurationIndex, Status);
1070 if (!NT_SUCCESS(Status))
1071 {
1072 //
1073 // failed
1074 //
1075 return Status;
1076 }
1077
1078 // destroy old interface info
1079 while(!IsListEmpty(&m_ConfigurationDescriptors[m_ConfigurationIndex].InterfaceList))
1080 {
1081 // remove entry
1082 Entry = RemoveHeadList(&m_ConfigurationDescriptors[m_ConfigurationIndex].InterfaceList);
1083
1084 // get interface info
1085 UsbInterface = (PUSB_INTERFACE)CONTAINING_RECORD(Entry, USB_INTERFACE, ListEntry);
1086
1087 // free interface info
1088 ExFreePool(UsbInterface);
1089 }
1090
1091 // sanity check
1092 ASSERT(IsListEmpty(&m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList));
1093
1094 // store new configuration device index
1095 m_ConfigurationIndex = ConfigurationIndex;
1096
1097 // store configuration handle
1098 *ConfigurationHandle = &m_ConfigurationDescriptors[ConfigurationIndex];
1099
1100 // copy interface info and pipe info
1101 for(InterfaceIndex = 0; InterfaceIndex < ConfigurationDescriptor->bNumInterfaces; InterfaceIndex++)
1102 {
1103 // interface info checks
1104 ASSERT(InterfaceInfo->Length != 0);
1105
1106 #ifdef _MSC_VER
1107 PC_ASSERT(InterfaceInfo->Length == FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes[InterfaceInfo->NumberOfPipes]));
1108 #endif
1109
1110 // find interface descriptor
1111 InterfaceDescriptor = USBD_ParseConfigurationDescriptor(m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor, InterfaceInfo->InterfaceNumber, InterfaceInfo->AlternateSetting);
1112
1113 // sanity checks
1114 ASSERT(InterfaceDescriptor != NULL);
1115
1116 // check if the number of pipes have been properly set
1117 ASSERT(InterfaceInfo->NumberOfPipes == InterfaceDescriptor->bNumEndpoints);
1118
1119 // copy interface info
1120 Status = BuildInterfaceDescriptor(ConfigurationIndex, InterfaceDescriptor, InterfaceInfo, NULL);
1121 if (!NT_SUCCESS(Status))
1122 {
1123 // failed
1124 break;
1125 }
1126
1127 // move offset
1128 InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)InterfaceInfo + InterfaceInfo->Length);
1129 }
1130
1131 //
1132 // done
1133 //
1134 return Status;
1135 }
1136
1137 //----------------------------------------------------------------------------------------
1138 NTSTATUS
1139 CUSBDevice::SelectInterface(
1140 IN USBD_CONFIGURATION_HANDLE ConfigurationHandle,
1141 IN OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo)
1142 {
1143 ULONG PipeIndex;
1144 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1145 NTSTATUS Status;
1146 ULONG Index, ConfigurationIndex = 0, Found = FALSE;
1147 PUSB_INTERFACE UsbInterface;
1148 PLIST_ENTRY Entry;
1149 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
1150
1151 // check if handle is valid
1152 for(Index = 0; Index < m_DeviceDescriptor.bNumConfigurations; Index++)
1153 {
1154 if (&m_ConfigurationDescriptors[Index] == ConfigurationHandle)
1155 {
1156 // found configuration index
1157 ConfigurationIndex = Index;
1158 Found = TRUE;
1159 }
1160 }
1161
1162 if (!Found)
1163 {
1164 // invalid handle passed
1165 DPRINT1("[USBLIB] Invalid configuration handle passed %p\n", ConfigurationHandle);
1166 return STATUS_INVALID_PARAMETER;
1167 }
1168
1169 // initialize setup packet
1170 RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1171 CtrlSetup.bRequest = USB_REQUEST_SET_INTERFACE;
1172 CtrlSetup.wValue.W = InterfaceInfo->AlternateSetting;
1173 CtrlSetup.wIndex.W = InterfaceInfo->InterfaceNumber;
1174 CtrlSetup.bmRequestType.B = 0x01;
1175
1176 // issue request
1177 Status = CommitSetupPacket(&CtrlSetup, 0, 0, 0);
1178
1179 // informal debug print
1180 DPRINT1("CUSBDevice::SelectInterface AlternateSetting %x InterfaceNumber %x Status %x\n", InterfaceInfo->AlternateSetting, InterfaceInfo->InterfaceNumber, Status);
1181 #if 0
1182 if (!NT_SUCCESS(Status))
1183 {
1184 // failed to select interface
1185 return Status;
1186 }
1187 #endif
1188
1189 Status = STATUS_SUCCESS;
1190
1191
1192 // find interface
1193 Found = FALSE;
1194 Entry = m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList.Flink;
1195 while(Entry != &m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList)
1196 {
1197 // grab interface descriptor
1198 UsbInterface = (PUSB_INTERFACE)CONTAINING_RECORD(Entry, USB_INTERFACE, ListEntry);
1199 if (UsbInterface->InterfaceDescriptor->bAlternateSetting == InterfaceInfo->AlternateSetting &&
1200 UsbInterface->InterfaceDescriptor->bInterfaceNumber == InterfaceInfo->InterfaceNumber)
1201 {
1202 // found interface
1203 Found = TRUE;
1204 break;
1205 }
1206
1207 // next entry
1208 Entry = Entry->Flink;
1209 }
1210
1211 if (!Found)
1212 {
1213 // find interface descriptor
1214 InterfaceDescriptor = USBD_ParseConfigurationDescriptor(m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor, InterfaceInfo->InterfaceNumber, InterfaceInfo->AlternateSetting);
1215 if (!InterfaceDescriptor)
1216 {
1217 DPRINT1("[LIBUSB] No such interface Alternate %x InterfaceNumber %x\n", InterfaceInfo->AlternateSetting, InterfaceInfo->InterfaceNumber);
1218 return STATUS_UNSUCCESSFUL;
1219 }
1220
1221 // build interface descriptor
1222 Status = BuildInterfaceDescriptor(ConfigurationIndex, InterfaceDescriptor, InterfaceInfo, &UsbInterface);
1223 if (!NT_SUCCESS(Status))
1224 {
1225 // failed
1226 DPRINT1("[LIBUSB] Failed to build interface descriptor Status %x\n", Status);
1227 return Status;
1228 }
1229 }
1230
1231 // assert on pipe length mismatch
1232 DPRINT1("NumberOfPipes %lu Endpoints %lu Length %lu\n", InterfaceInfo->NumberOfPipes, UsbInterface->InterfaceDescriptor->bNumEndpoints, InterfaceInfo->Length);
1233
1234 // sanity check
1235 ASSERT(GET_USBD_INTERFACE_SIZE(UsbInterface->InterfaceDescriptor->bNumEndpoints) == InterfaceInfo->Length);
1236
1237 // store number of pipes
1238 InterfaceInfo->NumberOfPipes = UsbInterface->InterfaceDescriptor->bNumEndpoints;
1239
1240 // copy pipe handles
1241 for(PipeIndex = 0; PipeIndex < UsbInterface->InterfaceDescriptor->bNumEndpoints; PipeIndex++)
1242 {
1243 // copy pipe handle
1244 DPRINT1("PipeIndex %lu\n", PipeIndex);
1245 DPRINT1("EndpointAddress %x\n", InterfaceInfo->Pipes[PipeIndex].EndpointAddress);
1246 DPRINT1("Interval %d\n", InterfaceInfo->Pipes[PipeIndex].Interval);
1247 DPRINT1("MaximumPacketSize %d\n", InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize);
1248 DPRINT1("MaximumTransferSize %d\n", InterfaceInfo->Pipes[PipeIndex].MaximumTransferSize);
1249 DPRINT1("PipeFlags %d\n", InterfaceInfo->Pipes[PipeIndex].PipeFlags);
1250 DPRINT1("PipeType %dd\n", InterfaceInfo->Pipes[PipeIndex].PipeType);
1251 DPRINT1("UsbEndPoint %x\n", InterfaceInfo->Pipes[PipeIndex].EndpointAddress);
1252
1253 // sanity checks
1254 ASSERT(InterfaceInfo->Pipes[PipeIndex].EndpointAddress == UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress);
1255 ASSERT(InterfaceInfo->Pipes[PipeIndex].Interval == UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bInterval);
1256
1257 // store pipe handle
1258 InterfaceInfo->Pipes[PipeIndex].PipeHandle = &UsbInterface->EndPoints[PipeIndex];
1259
1260 // data toggle is reset on select interface requests
1261 UsbInterface->EndPoints[PipeIndex].DataToggle = FALSE;
1262 }
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