e02cd03a65200e2ca2aaf6e8b33ed82a3b66233e
[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 break;
391 }
392 }
393
394 //
395 // done
396 //
397 return Status;
398
399 }
400
401 //----------------------------------------------------------------------------------------
402 void
403 CUSBDevice::GetDeviceDescriptor(
404 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
405 {
406 RtlMoveMemory(DeviceDescriptor, &m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
407 }
408
409 //----------------------------------------------------------------------------------------
410 UCHAR
411 CUSBDevice::GetConfigurationValue()
412 {
413 //
414 // return configuration index
415 //
416 return m_ConfigurationIndex;
417 }
418
419 //----------------------------------------------------------------------------------------
420 NTSTATUS
421 CUSBDevice::CommitIrp(
422 PIRP Irp)
423 {
424 NTSTATUS Status;
425 PUSBREQUEST Request;
426
427 if (!m_Queue || !m_DmaManager)
428 {
429 //
430 // no queue, wtf?
431 //
432 DPRINT1("CUSBDevice::CommitIrp> no queue / dma !!!\n");
433 return STATUS_UNSUCCESSFUL;
434 }
435
436 //
437 // build usb request
438 //
439 Status = m_Queue->CreateUSBRequest(&Request);
440 if (!NT_SUCCESS(Status))
441 {
442 //
443 // failed to build request
444 //
445 DPRINT1("CUSBDevice::CommitIrp> CreateUSBRequest failed with %lx\n", Status);
446 return Status;
447 }
448
449 //
450 // initialize request
451 //
452 Status = Request->InitializeWithIrp(m_DmaManager, PUSBDEVICE(this), Irp);
453
454 //
455 // mark irp as pending
456 //
457 IoMarkIrpPending(Irp);
458
459 //
460 // now add the request
461 //
462 Status = m_Queue->AddUSBRequest(Request);
463 if (!NT_SUCCESS(Status))
464 {
465 //
466 // failed to add request
467 //
468 DPRINT1("CUSBDevice::CommitIrp> failed add request to queue with %lx\n", Status);
469 Request->Release();
470 return Status;
471 }
472
473 //
474 // done
475 //
476 return STATUS_PENDING;
477 }
478
479 //----------------------------------------------------------------------------------------
480 NTSTATUS
481 CUSBDevice::SubmitIrp(
482 PIRP Irp)
483 {
484 KIRQL OldLevel;
485 NTSTATUS Status;
486
487 //
488 // acquire device lock
489 //
490 KeAcquireSpinLock(&m_Lock, &OldLevel);
491
492 //
493 // commit urb
494 //
495 Status = CommitIrp(Irp);
496
497 //
498 // release lock
499 //
500 KeReleaseSpinLock(&m_Lock, OldLevel);
501
502 return Status;
503 }
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, NULL, 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, NULL, 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 ULONG Length;
812
813 // sanity check
814 ASSERT(BufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
815 ASSERT(ConfigDescriptorBuffer);
816 ASSERT(OutBufferLength);
817
818 // reset copied length
819 *OutBufferLength = 0;
820
821 // FIXME: support multiple configurations
822 PC_ASSERT(m_DeviceDescriptor.bNumConfigurations == 1);
823
824 // copy configuration descriptor
825 Length = min(m_ConfigurationDescriptors[0].ConfigurationDescriptor->wTotalLength, BufferLength);
826 RtlCopyMemory(ConfigDescriptorBuffer, m_ConfigurationDescriptors[0].ConfigurationDescriptor, Length);
827 *OutBufferLength = Length;
828 }
829
830 //----------------------------------------------------------------------------------------
831 ULONG
832 CUSBDevice::GetConfigurationDescriptorsLength()
833 {
834 //
835 // FIXME: support multiple configurations
836 //
837 PC_ASSERT(m_DeviceDescriptor.bNumConfigurations == 1);
838
839 return m_ConfigurationDescriptors[0].ConfigurationDescriptor->wTotalLength;
840 }
841 //----------------------------------------------------------------------------------------
842 VOID
843 CUSBDevice::DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
844 {
845 DPRINT1("Dumping Device Descriptor %x\n", DeviceDescriptor);
846 DPRINT1("bLength %x\n", DeviceDescriptor->bLength);
847 DPRINT1("bDescriptorType %x\n", DeviceDescriptor->bDescriptorType);
848 DPRINT1("bcdUSB %x\n", DeviceDescriptor->bcdUSB);
849 DPRINT1("bDeviceClass %x\n", DeviceDescriptor->bDeviceClass);
850 DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor->bDeviceSubClass);
851 DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor->bDeviceProtocol);
852 DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor->bMaxPacketSize0);
853 DPRINT1("idVendor %x\n", DeviceDescriptor->idVendor);
854 DPRINT1("idProduct %x\n", DeviceDescriptor->idProduct);
855 DPRINT1("bcdDevice %x\n", DeviceDescriptor->bcdDevice);
856 DPRINT1("iManufacturer %x\n", DeviceDescriptor->iManufacturer);
857 DPRINT1("iProduct %x\n", DeviceDescriptor->iProduct);
858 DPRINT1("iSerialNumber %x\n", DeviceDescriptor->iSerialNumber);
859 DPRINT1("bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations);
860 }
861
862 //----------------------------------------------------------------------------------------
863 VOID
864 CUSBDevice::DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
865 {
866 DPRINT1("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor);
867 DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength);
868 DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
869 DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
870 DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
871 DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
872 DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
873 DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
874 DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
875 }
876 //----------------------------------------------------------------------------------------
877 NTSTATUS
878 CUSBDevice::SubmitSetupPacket(
879 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
880 IN OUT ULONG BufferLength,
881 OUT PVOID Buffer)
882 {
883 NTSTATUS Status;
884 PMDL Mdl = NULL;
885
886 if (BufferLength)
887 {
888 //
889 // allocate mdl
890 //
891 Mdl = IoAllocateMdl(Buffer, BufferLength, FALSE, FALSE, 0);
892 if (!Mdl)
893 {
894 //
895 // no memory
896 //
897 return STATUS_INSUFFICIENT_RESOURCES;
898 }
899
900 //
901 // HACK HACK HACK: assume the buffer is build from non paged pool
902 //
903 MmBuildMdlForNonPagedPool(Mdl);
904 }
905
906 //
907 // commit setup packet
908 //
909 Status = CommitSetupPacket(SetupPacket, NULL, BufferLength, Mdl);
910
911 if (Mdl != NULL)
912 {
913 //
914 // free mdl
915 //
916 IoFreeMdl(Mdl);
917 }
918
919 //
920 // done
921 //
922 return Status;
923 }
924 //----------------------------------------------------------------------------------------
925 NTSTATUS
926 CUSBDevice::BuildInterfaceDescriptor(
927 IN ULONG ConfigurationIndex,
928 IN PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor,
929 OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo,
930 OUT PUSB_INTERFACE *OutUsbInterface)
931 {
932 PUSB_INTERFACE UsbInterface;
933 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
934 ULONG PipeIndex;
935
936 // allocate interface handle
937 UsbInterface = (PUSB_INTERFACE)ExAllocatePool(NonPagedPool, sizeof(USB_INTERFACE) + (InterfaceDescriptor->bNumEndpoints - 1) * sizeof(USB_ENDPOINT));
938 if (!UsbInterface)
939 {
940 // failed to allocate memory
941 return STATUS_INSUFFICIENT_RESOURCES;
942 }
943
944 // zero descriptor
945 RtlZeroMemory(UsbInterface, sizeof(USB_INTERFACE) + (InterfaceDescriptor->bNumEndpoints - 1) * sizeof(USB_ENDPOINT));
946
947 // store handle
948 InterfaceInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)UsbInterface;
949 InterfaceInfo->Class = InterfaceDescriptor->bInterfaceClass;
950 InterfaceInfo->SubClass = InterfaceDescriptor->bInterfaceSubClass;
951 InterfaceInfo->Protocol = InterfaceDescriptor->bInterfaceProtocol;
952 InterfaceInfo->Reserved = 0;
953
954
955 // init interface handle
956 UsbInterface->InterfaceDescriptor = InterfaceDescriptor;
957 InsertTailList(&m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList, &UsbInterface->ListEntry);
958
959 // grab first endpoint descriptor
960 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) (InterfaceDescriptor + 1);
961
962 // now copy all endpoint information
963 for(PipeIndex = 0; PipeIndex < InterfaceDescriptor->bNumEndpoints; PipeIndex++)
964 {
965 while(EndpointDescriptor->bDescriptorType != USB_ENDPOINT_DESCRIPTOR_TYPE)
966 {
967 // skip intermediate descriptors
968 if (EndpointDescriptor->bLength == 0 || EndpointDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
969 {
970 // bogus configuration descriptor
971 DPRINT1("[USBLIB] Bogus descriptor found in InterfaceNumber %x Alternate %x EndpointIndex %x bLength %x bDescriptorType %x\n", InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting, PipeIndex,
972 EndpointDescriptor->bLength, EndpointDescriptor->bDescriptorType);
973
974 // failed
975 return STATUS_UNSUCCESSFUL;
976 }
977
978 // move to next descriptor
979 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)EndpointDescriptor + EndpointDescriptor->bLength);
980 }
981
982 // store in interface info
983 RtlCopyMemory(&UsbInterface->EndPoints[PipeIndex].EndPointDescriptor, EndpointDescriptor, sizeof(USB_ENDPOINT_DESCRIPTOR));
984
985 DPRINT("Configuration Descriptor %p Length %lu\n", m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor, m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor->wTotalLength);
986 DPRINT("EndpointDescriptor %p DescriptorType %x bLength %x\n", EndpointDescriptor, EndpointDescriptor->bDescriptorType, EndpointDescriptor->bLength);
987 DPRINT("EndpointDescriptorHandle %p bAddress %x bmAttributes %x\n",&UsbInterface->EndPoints[PipeIndex], UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress,
988 UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bmAttributes);
989
990 // copy pipe info
991 InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize = UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.wMaxPacketSize;
992 InterfaceInfo->Pipes[PipeIndex].EndpointAddress = UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress;
993 InterfaceInfo->Pipes[PipeIndex].Interval = UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bInterval;
994 InterfaceInfo->Pipes[PipeIndex].PipeType = (USBD_PIPE_TYPE)UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bmAttributes;
995 InterfaceInfo->Pipes[PipeIndex].PipeHandle = (PVOID)&UsbInterface->EndPoints[PipeIndex];
996
997 // move to next descriptor
998 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)EndpointDescriptor + EndpointDescriptor->bLength);
999 }
1000
1001 if (OutUsbInterface)
1002 {
1003 // output result
1004 *OutUsbInterface = UsbInterface;
1005 }
1006 return STATUS_SUCCESS;
1007
1008 }
1009
1010
1011 //----------------------------------------------------------------------------------------
1012 NTSTATUS
1013 CUSBDevice::SelectConfiguration(
1014 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
1015 IN PUSBD_INTERFACE_INFORMATION InterfaceInfo,
1016 OUT USBD_CONFIGURATION_HANDLE *ConfigurationHandle)
1017 {
1018 ULONG InterfaceIndex;
1019 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1020 NTSTATUS Status;
1021 UCHAR bConfigurationValue = 0;
1022 ULONG ConfigurationIndex = 0, Index;
1023 UCHAR Found = FALSE;
1024 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
1025 PUSB_INTERFACE UsbInterface;
1026 PLIST_ENTRY Entry;
1027
1028 if (ConfigurationDescriptor)
1029 {
1030 // find configuration index
1031 for (Index = 0; Index < m_DeviceDescriptor.bNumConfigurations; Index++)
1032 {
1033 if (m_ConfigurationDescriptors[Index].ConfigurationDescriptor->bConfigurationValue == ConfigurationDescriptor->bConfigurationValue)
1034 {
1035 // found configuration index
1036 ConfigurationIndex = Index;
1037 Found = TRUE;
1038 }
1039 }
1040
1041 if (!Found)
1042 {
1043 DPRINT1("[USBLIB] invalid configuration value %u\n", ConfigurationDescriptor->bConfigurationValue);
1044 return STATUS_INVALID_PARAMETER;
1045 }
1046
1047 // sanity check
1048 ASSERT(ConfigurationDescriptor->bNumInterfaces <= m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor->bNumInterfaces);
1049
1050 // get configuration value
1051 bConfigurationValue = ConfigurationDescriptor->bConfigurationValue;
1052 }
1053
1054 // now build setup packet
1055 RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1056 CtrlSetup.bRequest = USB_REQUEST_SET_CONFIGURATION;
1057 CtrlSetup.wValue.W = bConfigurationValue;
1058
1059 // select configuration
1060 Status = CommitSetupPacket(&CtrlSetup, NULL, 0, NULL);
1061
1062 if (!ConfigurationDescriptor)
1063 {
1064 // unconfigure request
1065 DPRINT1("CUSBDevice::SelectConfiguration Unconfigure Request Status %lx\n", Status);
1066 m_ConfigurationIndex = 0;
1067 return Status;
1068 }
1069
1070 // informal debug print
1071 DPRINT1("CUSBDevice::SelectConfiguration New Configuration %x Old Configuration %x Result %lx\n", ConfigurationIndex, m_ConfigurationIndex, Status);
1072 if (!NT_SUCCESS(Status))
1073 {
1074 //
1075 // failed
1076 //
1077 return Status;
1078 }
1079
1080 // destroy old interface info
1081 while (!IsListEmpty(&m_ConfigurationDescriptors[m_ConfigurationIndex].InterfaceList))
1082 {
1083 // remove entry
1084 Entry = RemoveHeadList(&m_ConfigurationDescriptors[m_ConfigurationIndex].InterfaceList);
1085
1086 // get interface info
1087 UsbInterface = (PUSB_INTERFACE)CONTAINING_RECORD(Entry, USB_INTERFACE, ListEntry);
1088
1089 // free interface info
1090 ExFreePool(UsbInterface);
1091 }
1092
1093 // sanity check
1094 ASSERT(IsListEmpty(&m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList));
1095
1096 // store new configuration device index
1097 m_ConfigurationIndex = ConfigurationIndex;
1098
1099 // store configuration handle
1100 *ConfigurationHandle = &m_ConfigurationDescriptors[ConfigurationIndex];
1101
1102 // copy interface info and pipe info
1103 for(InterfaceIndex = 0; InterfaceIndex < ConfigurationDescriptor->bNumInterfaces; InterfaceIndex++)
1104 {
1105 // interface info checks
1106 ASSERT(InterfaceInfo->Length != 0);
1107
1108 #ifdef _MSC_VER
1109 PC_ASSERT(InterfaceInfo->Length == FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes[InterfaceInfo->NumberOfPipes]));
1110 #endif
1111
1112 // find interface descriptor
1113 InterfaceDescriptor = USBD_ParseConfigurationDescriptor(m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor, InterfaceInfo->InterfaceNumber, InterfaceInfo->AlternateSetting);
1114
1115 // sanity checks
1116 ASSERT(InterfaceDescriptor != NULL);
1117
1118 // check if the number of pipes have been properly set
1119 ASSERT(InterfaceInfo->NumberOfPipes == InterfaceDescriptor->bNumEndpoints);
1120
1121 // copy interface info
1122 Status = BuildInterfaceDescriptor(ConfigurationIndex, InterfaceDescriptor, InterfaceInfo, NULL);
1123 if (!NT_SUCCESS(Status))
1124 {
1125 // failed
1126 DPRINT1("[LIBUSB] Failed to copy interface descriptor Index %lu InterfaceDescriptor %p InterfaceInfo %p\n", ConfigurationIndex, InterfaceDescriptor, InterfaceInfo);
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 %lx\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 // find interface
1195 Found = FALSE;
1196 Entry = m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList.Flink;
1197 while (Entry != &m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList)
1198 {
1199 // grab interface descriptor
1200 UsbInterface = (PUSB_INTERFACE)CONTAINING_RECORD(Entry, USB_INTERFACE, ListEntry);
1201 if (UsbInterface->InterfaceDescriptor->bAlternateSetting == InterfaceInfo->AlternateSetting &&
1202 UsbInterface->InterfaceDescriptor->bInterfaceNumber == InterfaceInfo->InterfaceNumber)
1203 {
1204 // found interface
1205 Found = TRUE;
1206 break;
1207 }
1208
1209 // next entry
1210 Entry = Entry->Flink;
1211 }
1212
1213 if (!Found)
1214 {
1215 // find interface descriptor
1216 InterfaceDescriptor = USBD_ParseConfigurationDescriptor(m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor, InterfaceInfo->InterfaceNumber, InterfaceInfo->AlternateSetting);
1217 if (!InterfaceDescriptor)
1218 {
1219 DPRINT1("[LIBUSB] No such interface Alternate %x InterfaceNumber %x\n", InterfaceInfo->AlternateSetting, InterfaceInfo->InterfaceNumber);
1220 return STATUS_UNSUCCESSFUL;
1221 }
1222
1223 // build interface descriptor
1224 Status = BuildInterfaceDescriptor(ConfigurationIndex, InterfaceDescriptor, InterfaceInfo, &UsbInterface);
1225 if (!NT_SUCCESS(Status))
1226 {
1227 // failed
1228 DPRINT1("[LIBUSB] Failed to build interface descriptor Status %x\n", Status);
1229 return Status;
1230 }
1231 }
1232
1233 // assert on pipe length mismatch
1234 DPRINT1("NumberOfPipes %lu Endpoints %lu Length %lu\n", InterfaceInfo->NumberOfPipes, UsbInterface->InterfaceDescriptor->bNumEndpoints, InterfaceInfo->Length);
1235
1236 // sanity check
1237 ASSERT(GET_USBD_INTERFACE_SIZE(UsbInterface->InterfaceDescriptor->bNumEndpoints) == InterfaceInfo->Length);
1238
1239 // store number of pipes
1240 InterfaceInfo->NumberOfPipes = UsbInterface->InterfaceDescriptor->bNumEndpoints;
1241
1242 // copy pipe handles
1243 for (PipeIndex = 0; PipeIndex < UsbInterface->InterfaceDescriptor->bNumEndpoints; PipeIndex++)
1244 {
1245 // copy pipe handle
1246 DPRINT1("PipeIndex %lu\n", PipeIndex);
1247 DPRINT1("EndpointAddress %x\n", InterfaceInfo->Pipes[PipeIndex].EndpointAddress);
1248 DPRINT1("Interval %d\n", InterfaceInfo->Pipes[PipeIndex].Interval);
1249 DPRINT1("MaximumPacketSize %d\n", InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize);
1250 DPRINT1("MaximumTransferSize %d\n", InterfaceInfo->Pipes[PipeIndex].MaximumTransferSize);
1251 DPRINT1("PipeFlags %d\n", InterfaceInfo->Pipes[PipeIndex].PipeFlags);
1252 DPRINT1("PipeType %d\n", InterfaceInfo->Pipes[PipeIndex].PipeType);
1253 DPRINT1("UsbEndPoint %x\n", InterfaceInfo->Pipes[PipeIndex].EndpointAddress);
1254
1255 // sanity checks
1256 ASSERT(InterfaceInfo->Pipes[PipeIndex].EndpointAddress == UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress);
1257 ASSERT(InterfaceInfo->Pipes[PipeIndex].Interval == UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bInterval);
1258
1259 // store pipe handle
1260 InterfaceInfo->Pipes[PipeIndex].PipeHandle = &UsbInterface->EndPoints[PipeIndex];
1261
1262 // data toggle is reset on select interface requests
1263 UsbInterface->EndPoints[PipeIndex].DataToggle = FALSE;
1264 }
1265
1266 //
1267 // done
1268 //
1269 return Status;
1270 }
1271
1272 NTSTATUS
1273 CUSBDevice::AbortPipe(
1274 IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor)
1275 {
1276 //
1277 // let it handle usb queue
1278 //
1279 ASSERT(m_Queue);
1280 ASSERT(m_DeviceAddress);
1281
1282 //
1283 // done
1284 //
1285 return m_Queue->AbortDevicePipe(m_DeviceAddress, EndpointDescriptor);
1286 }
1287
1288 UCHAR
1289 CUSBDevice::GetMaxPacketSize()
1290 {
1291 return m_DeviceDescriptor.bMaxPacketSize0;
1292 }
1293
1294
1295 //----------------------------------------------------------------------------------------
1296 NTSTATUS
1297 NTAPI
1298 CreateUSBDevice(
1299 PUSBDEVICE *OutDevice)
1300 {
1301 CUSBDevice * This;
1302
1303 //
1304 // allocate controller
1305 //
1306 This = new(NonPagedPool, TAG_USBLIB) CUSBDevice(0);
1307 if (!This)
1308 {
1309 //
1310 // failed to allocate
1311 //
1312 return STATUS_INSUFFICIENT_RESOURCES;
1313 }
1314
1315 //
1316 // add reference count
1317 //
1318 This->AddRef();
1319
1320 //
1321 // return result
1322 //
1323 *OutDevice = (PUSBDEVICE)This;
1324
1325 //
1326 // done
1327 //
1328 return STATUS_SUCCESS;
1329 }
1330