42b04789c748c65cea691ba6a7eb2339850c13c0
[reactos.git] / drivers / usb / usbohci / usb_request.cpp
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbohci/usb_request.cpp
5 * PURPOSE: USB OHCI device driver.
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
9 */
10
11 #define INITGUID
12
13 #include "usbohci.h"
14 #include "hardware.h"
15
16 class CUSBRequest : public IUSBRequest
17 {
18 public:
19 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
20
21 STDMETHODIMP_(ULONG) AddRef()
22 {
23 InterlockedIncrement(&m_Ref);
24 return m_Ref;
25 }
26 STDMETHODIMP_(ULONG) Release()
27 {
28 InterlockedDecrement(&m_Ref);
29
30 if (!m_Ref)
31 {
32 delete this;
33 return 0;
34 }
35 return m_Ref;
36 }
37
38 // IUSBRequest interface functions
39 virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN UCHAR DeviceAddress, IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN OUT ULONG TransferBufferLength, IN OUT PMDL TransferBuffer);
40 virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager, IN OUT PIRP Irp);
41 virtual BOOLEAN IsRequestComplete();
42 virtual ULONG GetTransferType();
43 virtual NTSTATUS GetEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutEndpointDescriptor);
44 virtual VOID GetResultStatus(OUT OPTIONAL NTSTATUS *NtStatusCode, OUT OPTIONAL PULONG UrbStatusCode);
45 virtual BOOLEAN IsRequestInitialized();
46 virtual BOOLEAN IsQueueHeadComplete(struct _QUEUE_HEAD * QueueHead);
47
48
49 // local functions
50 ULONG InternalGetTransferType();
51 UCHAR InternalGetPidDirection();
52 UCHAR GetDeviceAddress();
53 NTSTATUS BuildSetupPacket();
54 NTSTATUS BuildSetupPacketFromURB();
55 NTSTATUS BuildControlTransferDescriptor(POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor);
56 NTSTATUS CreateGeneralTransferDescriptor(POHCI_GENERAL_TD* OutDescriptor, ULONG BufferSize);
57 VOID FreeDescriptor(POHCI_GENERAL_TD Descriptor);
58 NTSTATUS AllocateEndpointDescriptor(OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor);
59 UCHAR GetEndpointAddress();
60 USHORT GetMaxPacketSize();
61
62 // constructor / destructor
63 CUSBRequest(IUnknown *OuterUnknown){}
64 virtual ~CUSBRequest(){}
65
66 protected:
67 LONG m_Ref;
68
69 //
70 // memory manager for allocating setup packet / queue head / transfer descriptors
71 //
72 PDMAMEMORYMANAGER m_DmaManager;
73
74 //
75 // caller provided irp packet containing URB request
76 //
77 PIRP m_Irp;
78
79 //
80 // transfer buffer length
81 //
82 ULONG m_TransferBufferLength;
83
84 //
85 // current transfer length
86 //
87 ULONG m_TransferBufferLengthCompleted;
88
89 //
90 // Total Transfer Length
91 //
92 ULONG m_TotalBytesTransferred;
93
94 //
95 // transfer buffer MDL
96 //
97 PMDL m_TransferBufferMDL;
98
99 //
100 // caller provided setup packet
101 //
102 PUSB_DEFAULT_PIPE_SETUP_PACKET m_SetupPacket;
103
104 //
105 // completion event for callers who initialized request with setup packet
106 //
107 PKEVENT m_CompletionEvent;
108
109 //
110 // device address for callers who initialized it with device address
111 //
112 UCHAR m_DeviceAddress;
113
114 //
115 // store end point address
116 //
117 PUSB_ENDPOINT_DESCRIPTOR m_EndpointDescriptor;
118
119 //
120 // allocated setup packet from the DMA pool
121 //
122 PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket;
123 PHYSICAL_ADDRESS m_DescriptorSetupPacket;
124
125 //
126 // stores the result of the operation
127 //
128 NTSTATUS m_NtStatusCode;
129 ULONG m_UrbStatusCode;
130
131 };
132
133 //----------------------------------------------------------------------------------------
134 NTSTATUS
135 STDMETHODCALLTYPE
136 CUSBRequest::QueryInterface(
137 IN REFIID refiid,
138 OUT PVOID* Output)
139 {
140 return STATUS_UNSUCCESSFUL;
141 }
142
143 //----------------------------------------------------------------------------------------
144 NTSTATUS
145 CUSBRequest::InitializeWithSetupPacket(
146 IN PDMAMEMORYMANAGER DmaManager,
147 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
148 IN UCHAR DeviceAddress,
149 IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor,
150 IN OUT ULONG TransferBufferLength,
151 IN OUT PMDL TransferBuffer)
152 {
153 //
154 // sanity checks
155 //
156 PC_ASSERT(DmaManager);
157 PC_ASSERT(SetupPacket);
158
159 //
160 // initialize packet
161 //
162 m_DmaManager = DmaManager;
163 m_SetupPacket = SetupPacket;
164 m_TransferBufferLength = TransferBufferLength;
165 m_TransferBufferMDL = TransferBuffer;
166 m_DeviceAddress = DeviceAddress;
167 m_EndpointDescriptor = EndpointDescriptor;
168 m_TotalBytesTransferred = 0;
169
170 //
171 // Set Length Completed to 0
172 //
173 m_TransferBufferLengthCompleted = 0;
174
175 //
176 // allocate completion event
177 //
178 m_CompletionEvent = (PKEVENT)ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_USBOHCI);
179 if (!m_CompletionEvent)
180 {
181 //
182 // failed to allocate completion event
183 //
184 return STATUS_INSUFFICIENT_RESOURCES;
185 }
186
187 //
188 // initialize completion event
189 //
190 KeInitializeEvent(m_CompletionEvent, NotificationEvent, FALSE);
191
192 //
193 // done
194 //
195 return STATUS_SUCCESS;
196 }
197 //----------------------------------------------------------------------------------------
198 NTSTATUS
199 CUSBRequest::InitializeWithIrp(
200 IN PDMAMEMORYMANAGER DmaManager,
201 IN OUT PIRP Irp)
202 {
203 PIO_STACK_LOCATION IoStack;
204 PURB Urb;
205
206 //
207 // sanity checks
208 //
209 PC_ASSERT(DmaManager);
210 PC_ASSERT(Irp);
211
212 m_DmaManager = DmaManager;
213 m_TotalBytesTransferred = 0;
214
215 //
216 // get current irp stack location
217 //
218 IoStack = IoGetCurrentIrpStackLocation(Irp);
219
220 //
221 // sanity check
222 //
223 PC_ASSERT(IoStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL);
224 PC_ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB);
225 PC_ASSERT(IoStack->Parameters.Others.Argument1 != 0);
226
227 //
228 // get urb
229 //
230 Urb = (PURB)IoStack->Parameters.Others.Argument1;
231
232 //
233 // store irp
234 //
235 m_Irp = Irp;
236
237 //
238 // check function type
239 //
240 switch (Urb->UrbHeader.Function)
241 {
242 //
243 // luckily those request have the same structure layout
244 //
245 case URB_FUNCTION_CLASS_INTERFACE:
246 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
247 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
248 {
249 //
250 // bulk interrupt transfer
251 //
252 if (Urb->UrbBulkOrInterruptTransfer.TransferBufferLength)
253 {
254 //
255 // Check if there is a MDL
256 //
257 if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
258 {
259 //
260 // sanity check
261 //
262 PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
263
264 //
265 // Create one using TransferBuffer
266 //
267 DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
268 m_TransferBufferMDL = IoAllocateMdl(Urb->UrbBulkOrInterruptTransfer.TransferBuffer,
269 Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
270 FALSE,
271 FALSE,
272 NULL);
273
274 if (!m_TransferBufferMDL)
275 {
276 //
277 // failed to allocate mdl
278 //
279 return STATUS_INSUFFICIENT_RESOURCES;
280 }
281
282 //
283 // build mdl for non paged pool
284 // FIXME: Does hub driver already do this when passing MDL?
285 //
286 MmBuildMdlForNonPagedPool(m_TransferBufferMDL);
287
288 //
289 // Keep that ehci created the MDL and needs to free it.
290 //
291 }
292 else
293 {
294 m_TransferBufferMDL = Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL;
295 }
296
297 //
298 // save buffer length
299 //
300 m_TransferBufferLength = Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
301
302 //
303 // Set Length Completed to 0
304 //
305 m_TransferBufferLengthCompleted = 0;
306
307 //
308 // get endpoint descriptor
309 //
310 m_EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
311
312 }
313 break;
314 }
315 default:
316 DPRINT1("URB Function: not supported %x\n", Urb->UrbHeader.Function);
317 PC_ASSERT(FALSE);
318 }
319
320 //
321 // done
322 //
323 return STATUS_SUCCESS;
324
325 }
326
327 //----------------------------------------------------------------------------------------
328 BOOLEAN
329 CUSBRequest::IsRequestComplete()
330 {
331 //
332 // FIXME: check if request was split
333 //
334
335 //
336 // Check if the transfer was completed, only valid for Bulk Transfers
337 //
338 if ((m_TransferBufferLengthCompleted < m_TransferBufferLength)
339 && (GetTransferType() == USB_ENDPOINT_TYPE_BULK))
340 {
341 //
342 // Transfer not completed
343 //
344 return FALSE;
345 }
346 return TRUE;
347 }
348 //----------------------------------------------------------------------------------------
349 ULONG
350 CUSBRequest::GetTransferType()
351 {
352 //
353 // call internal implementation
354 //
355 return InternalGetTransferType();
356 }
357
358 USHORT
359 CUSBRequest::GetMaxPacketSize()
360 {
361 if (!m_EndpointDescriptor)
362 {
363 //
364 // control request
365 //
366 return 0;
367 }
368
369 ASSERT(m_Irp);
370 ASSERT(m_EndpointDescriptor);
371
372 //
373 // return max packet size
374 //
375 return m_EndpointDescriptor->wMaxPacketSize;
376 }
377
378 UCHAR
379 CUSBRequest::GetEndpointAddress()
380 {
381 if (!m_EndpointDescriptor)
382 {
383 //
384 // control request
385 //
386 return 0;
387 }
388
389 ASSERT(m_Irp);
390 ASSERT(m_EndpointDescriptor);
391
392 //
393 // endpoint number is between 1-15
394 //
395 return (m_EndpointDescriptor->bEndpointAddress & 0xF);
396 }
397
398 //----------------------------------------------------------------------------------------
399 ULONG
400 CUSBRequest::InternalGetTransferType()
401 {
402 ULONG TransferType;
403
404 //
405 // check if an irp is provided
406 //
407 if (m_Irp)
408 {
409 ASSERT(m_EndpointDescriptor);
410
411 //
412 // end point is defined in the low byte of bmAttributes
413 //
414 TransferType = (m_EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK);
415 }
416 else
417 {
418 //
419 // initialized with setup packet, must be a control transfer
420 //
421 TransferType = USB_ENDPOINT_TYPE_CONTROL;
422 }
423
424 //
425 // done
426 //
427 return TransferType;
428 }
429
430 UCHAR
431 CUSBRequest::InternalGetPidDirection()
432 {
433 ASSERT(m_Irp);
434 ASSERT(m_EndpointDescriptor);
435
436 //
437 // end point is defined in the low byte of bEndpointAddress
438 //
439 return (m_EndpointDescriptor->bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) >> 7;
440 }
441
442
443 //----------------------------------------------------------------------------------------
444 UCHAR
445 CUSBRequest::GetDeviceAddress()
446 {
447 PIO_STACK_LOCATION IoStack;
448 PURB Urb;
449 PUSBDEVICE UsbDevice;
450
451 //
452 // check if there is an irp provided
453 //
454 if (!m_Irp)
455 {
456 //
457 // used provided address
458 //
459 return m_DeviceAddress;
460 }
461
462 //
463 // get current stack location
464 //
465 IoStack = IoGetCurrentIrpStackLocation(m_Irp);
466
467 //
468 // get contained urb
469 //
470 Urb = (PURB)IoStack->Parameters.Others.Argument1;
471
472 //
473 // check if there is a pipe handle provided
474 //
475 if (Urb->UrbHeader.UsbdDeviceHandle)
476 {
477 //
478 // there is a device handle provided
479 //
480 UsbDevice = (PUSBDEVICE)Urb->UrbHeader.UsbdDeviceHandle;
481
482 //
483 // return device address
484 //
485 return UsbDevice->GetDeviceAddress();
486 }
487
488 //
489 // no device handle provided, it is the host root bus
490 //
491 return 0;
492 }
493
494 VOID
495 CUSBRequest::FreeDescriptor(
496 POHCI_GENERAL_TD Descriptor)
497 {
498 if (Descriptor->BufferSize)
499 {
500 //
501 // free buffer
502 //
503 m_DmaManager->Release(Descriptor->BufferLogical, Descriptor->BufferSize);
504 }
505
506 //
507 // release descriptor
508 //
509 m_DmaManager->Release(Descriptor, sizeof(OHCI_GENERAL_TD));
510
511 }
512 //----------------------------------------------------------------------------------------
513 NTSTATUS
514 CUSBRequest::CreateGeneralTransferDescriptor(
515 POHCI_GENERAL_TD* OutDescriptor,
516 ULONG BufferSize)
517 {
518 POHCI_GENERAL_TD Descriptor;
519 PHYSICAL_ADDRESS DescriptorAddress;
520 NTSTATUS Status;
521
522 //
523 // allocate transfer descriptor
524 //
525 Status = m_DmaManager->Allocate(sizeof(OHCI_GENERAL_TD), (PVOID*)&Descriptor, &DescriptorAddress);
526 if (!NT_SUCCESS(Status))
527 {
528 //
529 // no memory
530 //
531 return Status;
532 }
533
534 //
535 // initialize descriptor, hardware part
536 //
537 Descriptor->Flags = 0;
538 Descriptor->BufferPhysical = 0;
539 Descriptor->NextPhysicalDescriptor = 0;
540 Descriptor->LastPhysicalByteAddress = 0;
541
542 //
543 // software part
544 //
545 Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart;
546 Descriptor->BufferSize = BufferSize;
547
548 if (BufferSize > 0)
549 {
550 //
551 // allocate buffer from dma
552 //
553 Status = m_DmaManager->Allocate(BufferSize, &Descriptor->BufferLogical, &DescriptorAddress);
554 if (!NT_SUCCESS(Status))
555 {
556 //
557 // no memory
558 //
559 m_DmaManager->Release(Descriptor, sizeof(OHCI_GENERAL_TD));
560 return Status;
561 }
562
563 //
564 // set physical address of buffer
565 //
566 Descriptor->BufferPhysical = DescriptorAddress.LowPart;
567 Descriptor->LastPhysicalByteAddress = Descriptor->BufferPhysical + BufferSize - 1;
568 }
569
570 //
571 // store result
572 //
573 *OutDescriptor = Descriptor;
574
575 //
576 // done
577 //
578 return STATUS_SUCCESS;
579 }
580
581 NTSTATUS
582 CUSBRequest::AllocateEndpointDescriptor(
583 OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor)
584 {
585 POHCI_ENDPOINT_DESCRIPTOR Descriptor;
586 PHYSICAL_ADDRESS DescriptorAddress;
587 NTSTATUS Status;
588
589 //
590 // allocate descriptor
591 //
592 Status = m_DmaManager->Allocate(sizeof(OHCI_ENDPOINT_DESCRIPTOR), (PVOID*)&Descriptor, &DescriptorAddress);
593 if (!NT_SUCCESS(Status))
594 {
595 //
596 // failed to allocate descriptor
597 //
598 return Status;
599 }
600
601 //
602 // intialize descriptor
603 //
604 Descriptor->Flags = OHCI_ENDPOINT_SKIP;
605
606 //
607 // append device address and endpoint number
608 //
609 Descriptor->Flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(m_DeviceAddress);
610 Descriptor->Flags |= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress());
611 Descriptor->Flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize());
612
613 //
614 // FIXME: detect type
615 //
616 Descriptor->Flags |= OHCI_ENDPOINT_FULL_SPEED;
617
618 Descriptor->HeadPhysicalDescriptor = 0;
619 Descriptor->NextPhysicalEndpoint = 0;
620 Descriptor->TailPhysicalDescriptor = 0;
621 Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart;
622
623 //
624 // store result
625 //
626 *OutDescriptor = Descriptor;
627
628 //
629 // done
630 //
631 return STATUS_SUCCESS;
632 }
633
634 NTSTATUS
635 CUSBRequest::BuildControlTransferDescriptor(
636 POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
637 {
638 POHCI_GENERAL_TD SetupDescriptor, StatusDescriptor, DataDescriptor = NULL;
639 POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
640 NTSTATUS Status;
641
642 DPRINT1("CUSBRequest::BuildControlTransferDescriptor\n");
643
644 //
645 // allocate endpoint descriptor
646 //
647 Status = AllocateEndpointDescriptor(&EndpointDescriptor);
648 if (!NT_SUCCESS(Status))
649 {
650 //
651 // failed to create setup descriptor
652 //
653 return Status;
654 }
655
656 //
657 // first allocate setup descriptor
658 //
659 Status = CreateGeneralTransferDescriptor(&SetupDescriptor, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
660 if (!NT_SUCCESS(Status))
661 {
662 //
663 // failed to create setup descriptor
664 //
665 m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
666 return Status;
667 }
668
669 //
670 // now create the status descriptor
671 //
672 Status = CreateGeneralTransferDescriptor(&StatusDescriptor, 0);
673 if (!NT_SUCCESS(Status))
674 {
675 //
676 // failed to create status descriptor
677 //
678 FreeDescriptor(SetupDescriptor);
679 m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
680 return Status;
681 }
682
683 if (m_TransferBufferLength)
684 {
685 //
686 // FIXME: support more than one data descriptor
687 //
688 ASSERT(m_TransferBufferLength < 8192);
689
690 //
691 // now create the data descriptor
692 //
693 Status = CreateGeneralTransferDescriptor(&DataDescriptor, 0);
694 if (!NT_SUCCESS(Status))
695 {
696 //
697 // failed to create status descriptor
698 //
699 m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
700 FreeDescriptor(SetupDescriptor);
701 FreeDescriptor(StatusDescriptor);
702 return Status;
703 }
704
705 //
706 // initialize data descriptor
707 //
708 DataDescriptor->Flags = OHCI_TD_BUFFER_ROUNDING| OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE) | OHCI_TD_TOGGLE_CARRY | OHCI_TD_DIRECTION_PID_IN;
709
710 //
711 // store physical address of buffer
712 //
713 DataDescriptor->BufferPhysical = MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL)).LowPart;
714 DataDescriptor->LastPhysicalByteAddress = DataDescriptor->BufferPhysical + m_TransferBufferLength - 1;
715 }
716
717 //
718 // initialize setup descriptor
719 //
720 SetupDescriptor->Flags = OHCI_TD_DIRECTION_PID_SETUP | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_TOGGLE_0 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE);
721
722 if (m_SetupPacket)
723 {
724 //
725 // copy setup packet
726 //
727 RtlCopyMemory(SetupDescriptor->BufferLogical, m_SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
728 }
729 else
730 {
731 //
732 // generate setup packet from urb
733 //
734 ASSERT(FALSE);
735 }
736
737 //
738 // initialize status descriptor
739 //
740 StatusDescriptor->Flags = OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
741 if (m_TransferBufferLength == 0)
742 {
743 //
744 // input direction is flipped for the status descriptor
745 //
746 StatusDescriptor->Flags |= OHCI_TD_DIRECTION_PID_IN;
747 }
748 else
749 {
750 //
751 // output direction is flipped for the status descriptor
752 //
753 StatusDescriptor->Flags |= OHCI_TD_DIRECTION_PID_OUT;
754 }
755
756 //
757 // now link the descriptors
758 //
759 if (m_TransferBufferLength)
760 {
761 //
762 // link setup descriptor to data descriptor
763 //
764 SetupDescriptor->NextPhysicalDescriptor = DataDescriptor->PhysicalAddress.LowPart;
765
766 //
767 // FIXME: should link to last data descriptor to status descriptor
768 //
769 DataDescriptor->NextPhysicalDescriptor = StatusDescriptor->PhysicalAddress.LowPart;
770 }
771 else
772 {
773 //
774 // link setup descriptor to status descriptor
775 //
776 SetupDescriptor->NextPhysicalDescriptor = StatusDescriptor->PhysicalAddress.LowPart;
777 }
778
779 //
780 // now link descriptor to endpoint
781 //
782 EndpointDescriptor->HeadPhysicalDescriptor = SetupDescriptor->PhysicalAddress.LowPart;
783 EndpointDescriptor->TailPhysicalDescriptor = SetupDescriptor->PhysicalAddress.LowPart;
784 DPRINT1("CUSBRequest::BuildControlTransferDescriptor done\n");
785
786 //
787 // store result
788 //
789 *OutEndpointDescriptor = EndpointDescriptor;
790
791 //
792 // done
793 //
794 return STATUS_SUCCESS;
795 }
796
797 //----------------------------------------------------------------------------------------
798 NTSTATUS
799 CUSBRequest::GetEndpointDescriptor(
800 struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor)
801 {
802 ULONG TransferType;
803 NTSTATUS Status;
804
805 //
806 // get transfer type
807 //
808 TransferType = InternalGetTransferType();
809
810 //
811 // build request depending on type
812 //
813 switch(TransferType)
814 {
815 case USB_ENDPOINT_TYPE_CONTROL:
816 Status = BuildControlTransferDescriptor((POHCI_ENDPOINT_DESCRIPTOR*)OutDescriptor);
817 break;
818 case USB_ENDPOINT_TYPE_BULK:
819 DPRINT1("USB_ENDPOINT_TYPE_BULK not implemented\n");
820 Status = STATUS_NOT_IMPLEMENTED; //BuildBulkTransferQueueHead(OutDescriptor);
821 break;
822 case USB_ENDPOINT_TYPE_INTERRUPT:
823 DPRINT1("USB_ENDPOINT_TYPE_INTERRUPT not implemented\n");
824 Status = STATUS_NOT_IMPLEMENTED;
825 break;
826 case USB_ENDPOINT_TYPE_ISOCHRONOUS:
827 DPRINT1("USB_ENDPOINT_TYPE_ISOCHRONOUS not implemented\n");
828 Status = STATUS_NOT_IMPLEMENTED;
829 break;
830 default:
831 PC_ASSERT(FALSE);
832 Status = STATUS_NOT_IMPLEMENTED;
833 break;
834 }
835
836 if (NT_SUCCESS(Status))
837 {
838 //
839 // store queue head
840 //
841 //m_QueueHead = *OutDescriptor;
842
843 //
844 // store request object
845 //
846 (*OutDescriptor)->Request = PVOID(this);
847 }
848
849 //
850 // done
851 //
852 return Status;
853 }
854
855 //----------------------------------------------------------------------------------------
856 VOID
857 CUSBRequest::GetResultStatus(
858 OUT OPTIONAL NTSTATUS * NtStatusCode,
859 OUT OPTIONAL PULONG UrbStatusCode)
860 {
861 //
862 // sanity check
863 //
864 PC_ASSERT(m_CompletionEvent);
865
866 //
867 // wait for the operation to complete
868 //
869 KeWaitForSingleObject(m_CompletionEvent, Executive, KernelMode, FALSE, NULL);
870
871 //
872 // copy status
873 //
874 if (NtStatusCode)
875 {
876 *NtStatusCode = m_NtStatusCode;
877 }
878
879 //
880 // copy urb status
881 //
882 if (UrbStatusCode)
883 {
884 *UrbStatusCode = m_UrbStatusCode;
885 }
886
887 }
888
889
890 //-----------------------------------------------------------------------------------------
891 BOOLEAN
892 CUSBRequest::IsRequestInitialized()
893 {
894 if (m_Irp || m_SetupPacket)
895 {
896 //
897 // request is initialized
898 //
899 return TRUE;
900 }
901
902 //
903 // request is not initialized
904 //
905 return FALSE;
906 }
907
908 //-----------------------------------------------------------------------------------------
909 BOOLEAN
910 CUSBRequest::IsQueueHeadComplete(
911 struct _QUEUE_HEAD * QueueHead)
912 {
913 UNIMPLEMENTED
914 return TRUE;
915 }
916
917
918
919 //-----------------------------------------------------------------------------------------
920 NTSTATUS
921 InternalCreateUSBRequest(
922 PUSBREQUEST *OutRequest)
923 {
924 PUSBREQUEST This;
925
926 //
927 // allocate requests
928 //
929 This = new(NonPagedPool, TAG_USBOHCI) CUSBRequest(0);
930 if (!This)
931 {
932 //
933 // failed to allocate
934 //
935 return STATUS_INSUFFICIENT_RESOURCES;
936 }
937
938 //
939 // add reference count
940 //
941 This->AddRef();
942
943 //
944 // return result
945 //
946 *OutRequest = (PUSBREQUEST)This;
947
948 //
949 // done
950 //
951 return STATUS_SUCCESS;
952 }