[USBPORT] Continue implementation USBPORT_AllocateBandwidthUSB2().
[reactos.git] / drivers / usb / usbehci / 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/usbehci/usb_request.cpp
5 * PURPOSE: USB EHCI device driver.
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
9 */
10
11 #include "usbehci.h"
12
13 #define NDEBUG
14 #include <debug.h>
15
16 class CUSBRequest : public IEHCIRequest
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 IMP_IUSBREQUEST
40 // IEHCI Request interface functions
41 IMP_IEHCIREQUEST
42
43 // local functions
44 ULONG InternalGetTransferType();
45 UCHAR InternalGetPidDirection();
46 NTSTATUS BuildControlTransferQueueHead(PQUEUE_HEAD * OutHead);
47 NTSTATUS BuildBulkInterruptTransferQueueHead(PQUEUE_HEAD * OutHead);
48 NTSTATUS STDMETHODCALLTYPE CreateDescriptor(PQUEUE_TRANSFER_DESCRIPTOR *OutDescriptor);
49 NTSTATUS CreateQueueHead(PQUEUE_HEAD *OutQueueHead);
50 UCHAR STDMETHODCALLTYPE GetDeviceAddress();
51 NTSTATUS BuildSetupPacket();
52 NTSTATUS BuildSetupPacketFromURB();
53 ULONG InternalCalculateTransferLength();
54 NTSTATUS STDMETHODCALLTYPE BuildTransferDescriptorChain(IN PQUEUE_HEAD QueueHead, IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode, IN UCHAR InitialDataToggle, OUT PQUEUE_TRANSFER_DESCRIPTOR * OutFirstDescriptor, OUT PQUEUE_TRANSFER_DESCRIPTOR * OutLastDescriptor, OUT PUCHAR OutDataToggle, OUT PULONG OutTransferBufferOffset);
55 VOID STDMETHODCALLTYPE InitDescriptor(IN PQUEUE_TRANSFER_DESCRIPTOR CurrentDescriptor, IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode, IN UCHAR DataToggle, OUT PULONG OutDescriptorLength);
56 VOID DumpQueueHead(IN PQUEUE_HEAD QueueHead);
57
58 // constructor / destructor
59 CUSBRequest(IUnknown *OuterUnknown);
60 virtual ~CUSBRequest();
61
62 protected:
63 LONG m_Ref;
64
65 //
66 // memory manager for allocating setup packet / queue head / transfer descriptors
67 //
68 PDMAMEMORYMANAGER m_DmaManager;
69
70 //
71 // caller provided irp packet containing URB request
72 //
73 PIRP m_Irp;
74
75 //
76 // transfer buffer length
77 //
78 ULONG m_TransferBufferLength;
79
80 //
81 // current transfer length
82 //
83 ULONG m_TransferBufferLengthCompleted;
84
85 //
86 // Total Transfer Length
87 //
88 ULONG m_TotalBytesTransferred;
89
90 //
91 // transfer buffer MDL
92 //
93 PMDL m_TransferBufferMDL;
94
95 //
96 // caller provided setup packet
97 //
98 PUSB_DEFAULT_PIPE_SETUP_PACKET m_SetupPacket;
99
100 //
101 // completion event for callers who initialized request with setup packet
102 //
103 PKEVENT m_CompletionEvent;
104
105 //
106 // device address for callers who initialized it with device address
107 //
108 UCHAR m_DeviceAddress;
109
110 //
111 // store end point address
112 //
113 PUSB_ENDPOINT m_EndpointDescriptor;
114
115 //
116 // DMA queue head
117 //
118 PQUEUE_HEAD m_QueueHead;
119
120 //
121 // allocated setup packet from the DMA pool
122 //
123 PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket;
124 PHYSICAL_ADDRESS m_DescriptorSetupPacket;
125
126 //
127 // stores the result of the operation
128 //
129 NTSTATUS m_NtStatusCode;
130 ULONG m_UrbStatusCode;
131
132 // buffer base address
133 PVOID m_Base;
134
135 // device speed
136 USB_DEVICE_SPEED m_Speed;
137
138 };
139
140 //----------------------------------------------------------------------------------------
141 CUSBRequest::CUSBRequest(IUnknown *OuterUnknown) :
142 m_CompletionEvent(NULL)
143 {
144 UNREFERENCED_PARAMETER(OuterUnknown);
145 }
146
147 //----------------------------------------------------------------------------------------
148 CUSBRequest::~CUSBRequest()
149 {
150 if (m_CompletionEvent != NULL)
151 {
152 ExFreePoolWithTag(m_CompletionEvent, TAG_USBEHCI);
153 }
154 }
155
156 //----------------------------------------------------------------------------------------
157 NTSTATUS
158 STDMETHODCALLTYPE
159 CUSBRequest::QueryInterface(
160 IN REFIID refiid,
161 OUT PVOID* Output)
162 {
163 return STATUS_UNSUCCESSFUL;
164 }
165
166 //----------------------------------------------------------------------------------------
167 NTSTATUS
168 STDMETHODCALLTYPE
169 CUSBRequest::InitializeWithSetupPacket(
170 IN PDMAMEMORYMANAGER DmaManager,
171 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
172 IN PUSBDEVICE Device,
173 IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor,
174 IN OUT ULONG TransferBufferLength,
175 IN OUT PMDL TransferBuffer)
176 {
177 //
178 // sanity checks
179 //
180 PC_ASSERT(DmaManager);
181 PC_ASSERT(SetupPacket);
182
183 //
184 // initialize packet
185 //
186 m_DmaManager = DmaManager;
187 m_SetupPacket = SetupPacket;
188 m_TransferBufferLength = TransferBufferLength;
189 m_TransferBufferMDL = TransferBuffer;
190 m_DeviceAddress = Device->GetDeviceAddress();
191 m_Speed = Device->GetSpeed();
192 m_EndpointDescriptor = EndpointDescriptor;
193 m_TotalBytesTransferred = 0;
194
195 //
196 // Set Length Completed to 0
197 //
198 m_TransferBufferLengthCompleted = 0;
199
200 //
201 // allocate completion event
202 //
203 m_CompletionEvent = (PKEVENT)ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_USBEHCI);
204 if (!m_CompletionEvent)
205 {
206 //
207 // failed to allocate completion event
208 //
209 return STATUS_INSUFFICIENT_RESOURCES;
210 }
211
212 //
213 // initialize completion event
214 //
215 KeInitializeEvent(m_CompletionEvent, NotificationEvent, FALSE);
216
217 //
218 // done
219 //
220 return STATUS_SUCCESS;
221 }
222 //----------------------------------------------------------------------------------------
223 NTSTATUS
224 STDMETHODCALLTYPE
225 CUSBRequest::InitializeWithIrp(
226 IN PDMAMEMORYMANAGER DmaManager,
227 IN PUSBDEVICE Device,
228 IN OUT PIRP Irp)
229 {
230 PIO_STACK_LOCATION IoStack;
231 PURB Urb;
232
233 //
234 // sanity checks
235 //
236 PC_ASSERT(DmaManager);
237 PC_ASSERT(Irp);
238
239 m_DmaManager = DmaManager;
240 m_TotalBytesTransferred = 0;
241 m_Speed = Device->GetSpeed();
242
243 //
244 // get current irp stack location
245 //
246 IoStack = IoGetCurrentIrpStackLocation(Irp);
247
248 //
249 // sanity check
250 //
251 PC_ASSERT(IoStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL);
252 PC_ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB);
253 PC_ASSERT(IoStack->Parameters.Others.Argument1 != 0);
254
255 //
256 // get urb
257 //
258 Urb = (PURB)IoStack->Parameters.Others.Argument1;
259
260 //
261 // store irp
262 //
263 m_Irp = Irp;
264
265 //
266 // check function type
267 //
268 switch (Urb->UrbHeader.Function)
269 {
270 //
271 // luckily those request have the same structure layout
272 //
273 case URB_FUNCTION_CLASS_INTERFACE:
274 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
275 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
276 {
277 //
278 // bulk interrupt transfer
279 //
280 if (Urb->UrbBulkOrInterruptTransfer.TransferBufferLength)
281 {
282 //
283 // Check if there is a MDL
284 //
285 if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
286 {
287 //
288 // sanity check
289 //
290 PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
291
292 //
293 // Create one using TransferBuffer
294 //
295 DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
296 m_TransferBufferMDL = IoAllocateMdl(Urb->UrbBulkOrInterruptTransfer.TransferBuffer,
297 Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
298 FALSE,
299 FALSE,
300 NULL);
301
302 if (!m_TransferBufferMDL)
303 {
304 //
305 // failed to allocate mdl
306 //
307 return STATUS_INSUFFICIENT_RESOURCES;
308 }
309
310 //
311 // build mdl for non paged pool
312 // FIXME: Does hub driver already do this when passing MDL?
313 //
314 MmBuildMdlForNonPagedPool(m_TransferBufferMDL);
315
316 //
317 // Keep that ehci created the MDL and needs to free it.
318 //
319 }
320 else
321 {
322 m_TransferBufferMDL = Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL;
323 }
324
325 //
326 // save buffer length
327 //
328 m_TransferBufferLength = Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
329
330 //
331 // Set Length Completed to 0
332 //
333 m_TransferBufferLengthCompleted = 0;
334
335 //
336 // get endpoint descriptor
337 //
338 m_EndpointDescriptor = (PUSB_ENDPOINT)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
339
340 }
341 break;
342 }
343 default:
344 DPRINT1("URB Function: not supported %x\n", Urb->UrbHeader.Function);
345 //ASSERT(FALSE);
346 }
347
348 //
349 // done
350 //
351 return STATUS_SUCCESS;
352
353 }
354
355 //----------------------------------------------------------------------------------------
356 VOID
357 STDMETHODCALLTYPE
358 CUSBRequest::CompletionCallback(
359 IN NTSTATUS NtStatusCode,
360 IN ULONG UrbStatusCode,
361 IN struct _QUEUE_HEAD *QueueHead)
362 {
363 PIO_STACK_LOCATION IoStack;
364 PURB Urb;
365
366 //
367 // FIXME: support linked queue heads
368 //
369
370 //
371 // store completion code
372 //
373 m_NtStatusCode = NtStatusCode;
374 m_UrbStatusCode = UrbStatusCode;
375
376 if (m_Irp)
377 {
378 //
379 // set irp completion status
380 //
381 m_Irp->IoStatus.Status = NtStatusCode;
382
383 //
384 // get current irp stack location
385 //
386 IoStack = IoGetCurrentIrpStackLocation(m_Irp);
387
388 //
389 // get urb
390 //
391 Urb = (PURB)IoStack->Parameters.Others.Argument1;
392
393 //
394 // store urb status
395 //
396 Urb->UrbHeader.Status = UrbStatusCode;
397
398 //
399 // Check if the MDL was created
400 //
401 if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
402 {
403 //
404 // Free Mdl
405 //
406 IoFreeMdl(m_TransferBufferMDL);
407 }
408
409 //
410 // check if the request was successful
411 //
412 if (!NT_SUCCESS(NtStatusCode))
413 {
414 //
415 // set returned length to zero in case of error
416 //
417 Urb->UrbHeader.Length = 0;
418 }
419 else
420 {
421 //
422 // calculate transfer length
423 //
424 Urb->UrbBulkOrInterruptTransfer.TransferBufferLength = InternalCalculateTransferLength();
425 }
426
427 DPRINT("Request %p Completing Irp %p NtStatusCode %x UrbStatusCode %x Transferred Length %lu\n", this, m_Irp, NtStatusCode, UrbStatusCode, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
428
429 //
430 // FIXME: check if the transfer was split
431 // if yes dont complete irp yet
432 //
433 IoCompleteRequest(m_Irp, IO_NO_INCREMENT);
434 }
435 else
436 {
437 //
438 // signal completion event
439 //
440 PC_ASSERT(m_CompletionEvent);
441 KeSetEvent(m_CompletionEvent, 0, FALSE);
442 }
443 }
444
445 //----------------------------------------------------------------------------------------
446 NTSTATUS
447 STDMETHODCALLTYPE
448 CUSBRequest::GetQueueHead(
449 struct _QUEUE_HEAD ** OutHead)
450 {
451 ULONG TransferType;
452 NTSTATUS Status;
453
454 //
455 // first get transfer type
456 //
457 TransferType = InternalGetTransferType();
458
459 //
460 // build request depending on type
461 //
462 switch(TransferType)
463 {
464 case USB_ENDPOINT_TYPE_CONTROL:
465 Status = BuildControlTransferQueueHead(OutHead);
466 break;
467 case USB_ENDPOINT_TYPE_INTERRUPT:
468 case USB_ENDPOINT_TYPE_BULK:
469 Status = BuildBulkInterruptTransferQueueHead(OutHead);
470 break;
471 case USB_ENDPOINT_TYPE_ISOCHRONOUS:
472 DPRINT1("USB_ENDPOINT_TYPE_ISOCHRONOUS not implemented\n");
473 Status = STATUS_NOT_IMPLEMENTED;
474 break;
475 default:
476 PC_ASSERT(FALSE);
477 Status = STATUS_NOT_IMPLEMENTED;
478 break;
479 }
480
481 if (NT_SUCCESS(Status))
482 {
483 //
484 // store queue head
485 //
486 m_QueueHead = *OutHead;
487
488 //
489 // store request object
490 //
491 (*OutHead)->Request = PVOID(this);
492 }
493
494 //
495 // done
496 //
497 return Status;
498 }
499
500 //----------------------------------------------------------------------------------------
501 BOOLEAN
502 STDMETHODCALLTYPE
503 CUSBRequest::IsRequestComplete()
504 {
505 //
506 // FIXME: check if request was split
507 //
508
509 //
510 // Check if the transfer was completed, only valid for Bulk Transfers
511 //
512 if ((m_TransferBufferLengthCompleted < m_TransferBufferLength)
513 && (GetTransferType() == USB_ENDPOINT_TYPE_BULK))
514 {
515 //
516 // Transfer not completed
517 //
518 return FALSE;
519 }
520 return TRUE;
521 }
522 //----------------------------------------------------------------------------------------
523 ULONG
524 STDMETHODCALLTYPE
525 CUSBRequest::GetTransferType()
526 {
527 //
528 // call internal implementation
529 //
530 return InternalGetTransferType();
531 }
532
533 //----------------------------------------------------------------------------------------
534 ULONG
535 CUSBRequest::InternalGetTransferType()
536 {
537 ULONG TransferType;
538
539 //
540 // check if an irp is provided
541 //
542 if (m_Irp)
543 {
544 ASSERT(m_EndpointDescriptor);
545
546 //
547 // end point is defined in the low byte of bmAttributes
548 //
549 TransferType = (m_EndpointDescriptor->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK);
550 }
551 else
552 {
553 //
554 // initialized with setup packet, must be a control transfer
555 //
556 TransferType = USB_ENDPOINT_TYPE_CONTROL;
557 ASSERT(m_EndpointDescriptor == NULL);
558 }
559
560 //
561 // done
562 //
563 return TransferType;
564 }
565
566 UCHAR
567 CUSBRequest::InternalGetPidDirection()
568 {
569 if (m_EndpointDescriptor)
570 {
571 //
572 // end point direction is highest bit in bEndpointAddress
573 //
574 return (m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) >> 7;
575 }
576 else
577 {
578 //
579 // request arrives on the control pipe, extract direction from setup packet
580 //
581 ASSERT(m_DescriptorPacket);
582 return (m_DescriptorPacket->bmRequestType.B >> 7);
583 }
584 }
585
586 VOID
587 STDMETHODCALLTYPE
588 CUSBRequest::InitDescriptor(
589 IN PQUEUE_TRANSFER_DESCRIPTOR CurrentDescriptor,
590 IN PVOID TransferBuffer,
591 IN ULONG TransferBufferLength,
592 IN UCHAR PidCode,
593 IN UCHAR DataToggle,
594 OUT PULONG OutDescriptorLength)
595 {
596 ULONG Index, Length = 0, PageOffset, BufferLength;
597 PHYSICAL_ADDRESS Address;
598
599 //
600 // init transfer descriptor
601 //
602 CurrentDescriptor->Token.Bits.PIDCode = PidCode;
603 CurrentDescriptor->Token.Bits.TotalBytesToTransfer = 0;
604 CurrentDescriptor->Token.Bits.DataToggle = DataToggle;
605
606 //
607 // sanity check
608 //
609 ASSERT(TransferBufferLength);
610
611 //
612 // store buffers
613 //
614 Index = 0;
615 do
616 {
617 //
618 // get address (HACK)
619 //
620 *(volatile char *)TransferBuffer;
621 Address = MmGetPhysicalAddress(TransferBuffer);
622
623 //
624 // use physical address
625 //
626 CurrentDescriptor->BufferPointer[Index] = Address.LowPart;
627 CurrentDescriptor->ExtendedBufferPointer[Index] = Address.HighPart;
628
629 //
630 // Get the offset from page size
631 //
632 PageOffset = BYTE_OFFSET(CurrentDescriptor->BufferPointer[Index]);
633 if (PageOffset != 0)
634 {
635 //
636 // move to next page
637 //
638 TransferBuffer = (PVOID)ROUND_TO_PAGES(TransferBuffer);
639 }
640 else
641 {
642 //
643 // move to next page
644 //
645 TransferBuffer = (PVOID)((ULONG_PTR)TransferBuffer + PAGE_SIZE);
646 }
647
648 //
649 // calculate buffer length
650 //
651 BufferLength = min(TransferBufferLength, PAGE_SIZE - PageOffset);
652
653 //
654 // increment transfer bytes
655 //
656 CurrentDescriptor->Token.Bits.TotalBytesToTransfer += BufferLength;
657 CurrentDescriptor->TotalBytesToTransfer += BufferLength;
658 Length += BufferLength;
659 DPRINT("Index %lu TransferBufferLength %lu PageOffset %x BufferLength %lu Buffer Phy %p TransferBuffer %p\n", Index, TransferBufferLength, PageOffset, BufferLength, CurrentDescriptor->BufferPointer[Index], TransferBuffer);
660
661 //
662 // decrement available byte count
663 //
664 TransferBufferLength -= BufferLength;
665 if (TransferBufferLength == 0)
666 {
667 //
668 // end reached
669 //
670 break;
671 }
672
673 //
674 // sanity check
675 //
676 if (Index > 1)
677 {
678 //
679 // no equal buffers
680 //
681 ASSERT(CurrentDescriptor->BufferPointer[Index] != CurrentDescriptor->BufferPointer[Index-1]);
682 }
683
684 //
685 // next descriptor index
686 //
687 Index++;
688 }while(Index < 5);
689
690 //
691 // store result
692 //
693 *OutDescriptorLength = Length;
694 }
695
696 NTSTATUS
697 STDMETHODCALLTYPE
698 CUSBRequest::BuildTransferDescriptorChain(
699 IN PQUEUE_HEAD QueueHead,
700 IN PVOID TransferBuffer,
701 IN ULONG TransferBufferLength,
702 IN UCHAR PidCode,
703 IN UCHAR InitialDataToggle,
704 OUT PQUEUE_TRANSFER_DESCRIPTOR * OutFirstDescriptor,
705 OUT PQUEUE_TRANSFER_DESCRIPTOR * OutLastDescriptor,
706 OUT PUCHAR OutDataToggle,
707 OUT PULONG OutTransferBufferOffset)
708 {
709 PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor = NULL, CurrentDescriptor, LastDescriptor = NULL;
710 NTSTATUS Status;
711 ULONG DescriptorLength, TransferBufferOffset = 0;
712 ULONG MaxPacketSize = 0, TransferSize;
713
714 //
715 // is there an endpoint descriptor
716 //
717 if (m_EndpointDescriptor)
718 {
719 //
720 // use endpoint packet size
721 //
722 MaxPacketSize = m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize;
723 }
724
725 do
726 {
727 //
728 // allocate transfer descriptor
729 //
730 Status = CreateDescriptor(&CurrentDescriptor);
731 if (!NT_SUCCESS(Status))
732 {
733 //
734 // failed to allocate transfer descriptor
735 //
736 return STATUS_INSUFFICIENT_RESOURCES;
737 }
738
739 if (MaxPacketSize)
740 {
741 //
742 // transfer size is minimum available buffer or endpoint size
743 //
744 TransferSize = min(TransferBufferLength - TransferBufferOffset, MaxPacketSize);
745 }
746 else
747 {
748 //
749 // use available buffer
750 //
751 TransferSize = TransferBufferLength - TransferBufferOffset;
752 }
753
754 //
755 // now init the descriptor
756 //
757 InitDescriptor(CurrentDescriptor,
758 (PVOID)((ULONG_PTR)TransferBuffer + TransferBufferOffset),
759 TransferSize,
760 PidCode,
761 InitialDataToggle,
762 &DescriptorLength);
763
764 //
765 // insert into queue head
766 //
767 InsertTailList(&QueueHead->TransferDescriptorListHead, &CurrentDescriptor->DescriptorEntry);
768
769 //
770 // adjust offset
771 //
772 TransferBufferOffset += DescriptorLength;
773
774 if (LastDescriptor)
775 {
776 //
777 // link to current descriptor
778 //
779 LastDescriptor->NextPointer = CurrentDescriptor->PhysicalAddr;
780 LastDescriptor = CurrentDescriptor;
781 }
782 else
783 {
784 //
785 // first descriptor in chain
786 //
787 LastDescriptor = FirstDescriptor = CurrentDescriptor;
788 }
789
790 //
791 // flip data toggle
792 //
793 InitialDataToggle = !InitialDataToggle;
794
795 if(TransferBufferLength == TransferBufferOffset)
796 {
797 //
798 // end reached
799 //
800 break;
801 }
802
803 }while(TRUE);
804
805 if (OutFirstDescriptor)
806 {
807 //
808 // store first descriptor
809 //
810 *OutFirstDescriptor = FirstDescriptor;
811 }
812
813 if (OutLastDescriptor)
814 {
815 //
816 // store last descriptor
817 //
818 *OutLastDescriptor = CurrentDescriptor;
819 }
820
821 if (OutDataToggle)
822 {
823 //
824 // store result data toggle
825 //
826 *OutDataToggle = InitialDataToggle;
827 }
828
829 if (OutTransferBufferOffset)
830 {
831 //
832 // store offset
833 //
834 *OutTransferBufferOffset = TransferBufferOffset;
835 }
836
837 //
838 // done
839 //
840 return STATUS_SUCCESS;
841 }
842
843 //----------------------------------------------------------------------------------------
844 NTSTATUS
845 CUSBRequest::BuildControlTransferQueueHead(
846 PQUEUE_HEAD * OutHead)
847 {
848 NTSTATUS Status;
849 ULONG DescriptorChainLength;
850 PQUEUE_HEAD QueueHead;
851 PQUEUE_TRANSFER_DESCRIPTOR SetupDescriptor, StatusDescriptor, FirstDescriptor, LastDescriptor;
852
853 //
854 // first allocate the queue head
855 //
856 Status = CreateQueueHead(&QueueHead);
857 if (!NT_SUCCESS(Status))
858 {
859 //
860 // failed to allocate queue head
861 //
862 DPRINT1("[EHCI] Failed to create queue head\n");
863 return Status;
864 }
865
866 //
867 // sanity check
868 //
869 PC_ASSERT(QueueHead);
870
871 //
872 // create setup packet
873 //
874 Status = BuildSetupPacket();
875 if (!NT_SUCCESS(Status))
876 {
877 // failed to create setup packet
878 DPRINT1("[EHCI] Failed to create setup packet\n");
879
880 // release queue head
881 m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
882 return Status;
883 }
884
885 //
886 // create setup descriptor
887 //
888 Status = CreateDescriptor(&SetupDescriptor);
889 if (!NT_SUCCESS(Status))
890 {
891 // failed to create setup transfer descriptor
892 DPRINT1("[EHCI] Failed to create setup descriptor\n");
893
894 if (m_DescriptorPacket)
895 {
896 // release packet descriptor
897 m_DmaManager->Release(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
898 }
899
900 // release queue head
901 m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
902 return Status;
903 }
904
905 //
906 // create status descriptor
907 //
908 Status = CreateDescriptor(&StatusDescriptor);
909 if (!NT_SUCCESS(Status))
910 {
911 // failed to create status transfer descriptor
912 DPRINT1("[EHCI] Failed to create status descriptor\n");
913
914 // release setup transfer descriptor
915 m_DmaManager->Release(SetupDescriptor, sizeof(QUEUE_TRANSFER_DESCRIPTOR));
916
917 if (m_DescriptorPacket)
918 {
919 // release packet descriptor
920 m_DmaManager->Release(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
921 }
922
923 // release queue head
924 m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
925 return Status;
926 }
927
928 //
929 // now initialize the queue head
930 //
931 QueueHead->EndPointCharacteristics.DeviceAddress = GetDeviceAddress();
932
933 ASSERT(m_EndpointDescriptor == NULL);
934
935 //
936 // init setup descriptor
937 //
938 SetupDescriptor->Token.Bits.PIDCode = PID_CODE_SETUP_TOKEN;
939 SetupDescriptor->Token.Bits.TotalBytesToTransfer = sizeof(USB_DEFAULT_PIPE_SETUP_PACKET);
940 SetupDescriptor->Token.Bits.DataToggle = FALSE;
941 SetupDescriptor->BufferPointer[0] = m_DescriptorSetupPacket.LowPart;
942 SetupDescriptor->ExtendedBufferPointer[0] = m_DescriptorSetupPacket.HighPart;
943 InsertTailList(&QueueHead->TransferDescriptorListHead, &SetupDescriptor->DescriptorEntry);
944
945
946 //
947 // init status descriptor
948 //
949 StatusDescriptor->Token.Bits.TotalBytesToTransfer = 0;
950 StatusDescriptor->Token.Bits.DataToggle = TRUE;
951 StatusDescriptor->Token.Bits.InterruptOnComplete = TRUE;
952
953 //
954 // is there data
955 //
956 if (m_TransferBufferLength)
957 {
958 Status = BuildTransferDescriptorChain(QueueHead,
959 MmGetMdlVirtualAddress(m_TransferBufferMDL),
960 m_TransferBufferLength,
961 InternalGetPidDirection(),
962 TRUE,
963 &FirstDescriptor,
964 &LastDescriptor,
965 NULL,
966 &DescriptorChainLength);
967 if (!NT_SUCCESS(Status))
968 {
969 // failed to create descriptor chain
970 DPRINT1("[EHCI] Failed to create descriptor chain\n");
971
972 // release status transfer descriptor
973 m_DmaManager->Release(StatusDescriptor, sizeof(QUEUE_TRANSFER_DESCRIPTOR));
974
975 // release setup transfer descriptor
976 m_DmaManager->Release(SetupDescriptor, sizeof(QUEUE_TRANSFER_DESCRIPTOR));
977
978 if (m_DescriptorPacket)
979 {
980 // release packet descriptor
981 m_DmaManager->Release(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
982 }
983
984 // release queue head
985 m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
986 return Status;
987 }
988
989 if (m_TransferBufferLength != DescriptorChainLength)
990 {
991 DPRINT1("DescriptorChainLength %x\n", DescriptorChainLength);
992 DPRINT1("m_TransferBufferLength %x\n", m_TransferBufferLength);
993 ASSERT(FALSE);
994 }
995
996 //
997 // now link the descriptors
998 //
999 SetupDescriptor->NextPointer = FirstDescriptor->PhysicalAddr;
1000 SetupDescriptor->AlternateNextPointer = FirstDescriptor->PhysicalAddr;
1001 LastDescriptor->NextPointer = StatusDescriptor->PhysicalAddr;
1002 LastDescriptor->AlternateNextPointer = StatusDescriptor->PhysicalAddr;
1003
1004
1005 //
1006 // pid code is flipped for ops with data stage
1007 //
1008 StatusDescriptor->Token.Bits.PIDCode = !InternalGetPidDirection();
1009 }
1010 else
1011 {
1012 //
1013 // direct link
1014 //
1015 SetupDescriptor->NextPointer = StatusDescriptor->PhysicalAddr;
1016 SetupDescriptor->AlternateNextPointer = StatusDescriptor->PhysicalAddr;
1017
1018 //
1019 // retrieve result of operation
1020 //
1021 StatusDescriptor->Token.Bits.PIDCode = PID_CODE_IN_TOKEN;
1022 }
1023
1024 //
1025 // insert status descriptor
1026 //
1027 InsertTailList(&QueueHead->TransferDescriptorListHead, &StatusDescriptor->DescriptorEntry);
1028
1029
1030 //
1031 // link transfer descriptors to queue head
1032 //
1033 QueueHead->NextPointer = SetupDescriptor->PhysicalAddr;
1034
1035 //
1036 // store result
1037 //
1038 *OutHead = QueueHead;
1039
1040 //
1041 // displays the current request
1042 //
1043 //DumpQueueHead(QueueHead);
1044
1045 DPRINT("BuildControlTransferQueueHead done\n");
1046 //
1047 // done
1048 //
1049 return STATUS_SUCCESS;
1050 }
1051
1052 VOID
1053 CUSBRequest::DumpQueueHead(
1054 IN PQUEUE_HEAD QueueHead)
1055 {
1056 PLIST_ENTRY Entry;
1057 PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
1058 ULONG Index = 0;
1059
1060 DPRINT1("QueueHead %p Addr %x\n", QueueHead, QueueHead->PhysicalAddr);
1061 DPRINT1("QueueHead AlternateNextPointer %x\n", QueueHead->AlternateNextPointer);
1062 DPRINT1("QueueHead NextPointer %x\n", QueueHead->NextPointer);
1063
1064 DPRINT1("QueueHead HubAddr %x\n", QueueHead->EndPointCharacteristics.ControlEndPointFlag);
1065 DPRINT1("QueueHead DeviceAddress %x\n", QueueHead->EndPointCharacteristics.DeviceAddress);
1066 DPRINT1("QueueHead EndPointNumber %x\n", QueueHead->EndPointCharacteristics.EndPointNumber);
1067 DPRINT1("QueueHead EndPointSpeed %x\n", QueueHead->EndPointCharacteristics.EndPointSpeed);
1068 DPRINT1("QueueHead HeadOfReclamation %x\n", QueueHead->EndPointCharacteristics.HeadOfReclamation);
1069 DPRINT1("QueueHead InactiveOnNextTransaction %x\n", QueueHead->EndPointCharacteristics.InactiveOnNextTransaction);
1070 DPRINT1("QueueHead MaximumPacketLength %x\n", QueueHead->EndPointCharacteristics.MaximumPacketLength);
1071 DPRINT1("QueueHead NakCountReload %x\n", QueueHead->EndPointCharacteristics.NakCountReload);
1072 DPRINT1("QueueHead QEDTDataToggleControl %x\n", QueueHead->EndPointCharacteristics.QEDTDataToggleControl);
1073 DPRINT1("QueueHead HubAddr %x\n", QueueHead->EndPointCapabilities.HubAddr);
1074 DPRINT1("QueueHead InterruptScheduleMask %x\n", QueueHead->EndPointCapabilities.InterruptScheduleMask);
1075 DPRINT1("QueueHead NumberOfTransactionPerFrame %x\n", QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame);
1076 DPRINT1("QueueHead PortNumber %x\n", QueueHead->EndPointCapabilities.PortNumber);
1077 DPRINT1("QueueHead SplitCompletionMask %x\n", QueueHead->EndPointCapabilities.SplitCompletionMask);
1078
1079 Entry = QueueHead->TransferDescriptorListHead.Flink;
1080 while(Entry != &QueueHead->TransferDescriptorListHead)
1081 {
1082 //
1083 // get transfer descriptor
1084 //
1085 Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry);
1086
1087 DPRINT1("TransferDescriptor %lu Addr %x\n", Index, Descriptor->PhysicalAddr);
1088 DPRINT1("TransferDescriptor %lu Next %x\n", Index, Descriptor->NextPointer);
1089 DPRINT1("TransferDescriptor %lu AlternateNextPointer %x\n", Index, Descriptor->AlternateNextPointer);
1090 DPRINT1("TransferDescriptor %lu Active %lu\n", Index, Descriptor->Token.Bits.Active);
1091 DPRINT1("TransferDescriptor %lu BabbleDetected %lu\n", Index, Descriptor->Token.Bits.BabbleDetected);
1092 DPRINT1("TransferDescriptor %lu CurrentPage %lu\n", Index, Descriptor->Token.Bits.CurrentPage);
1093 DPRINT1("TransferDescriptor %lu DataBufferError %lu\n", Index, Descriptor->Token.Bits.DataBufferError);
1094 DPRINT1("TransferDescriptor %lu DataToggle %lu\n", Index, Descriptor->Token.Bits.DataToggle);
1095 DPRINT1("TransferDescriptor %lu ErrorCounter %lu\n", Index, Descriptor->Token.Bits.ErrorCounter);
1096 DPRINT1("TransferDescriptor %lu Halted %lu\n", Index, Descriptor->Token.Bits.Halted);
1097 DPRINT1("TransferDescriptor %lu InterruptOnComplete %x\n", Index, Descriptor->Token.Bits.InterruptOnComplete);
1098 DPRINT1("TransferDescriptor %lu MissedMicroFrame %lu\n", Index, Descriptor->Token.Bits.MissedMicroFrame);
1099 DPRINT1("TransferDescriptor %lu PIDCode %lu\n", Index, Descriptor->Token.Bits.PIDCode);
1100 DPRINT1("TransferDescriptor %lu PingState %lu\n", Index, Descriptor->Token.Bits.PingState);
1101 DPRINT1("TransferDescriptor %lu SplitTransactionState %lu\n", Index, Descriptor->Token.Bits.SplitTransactionState);
1102 DPRINT1("TransferDescriptor %lu TotalBytesToTransfer %lu\n", Index, Descriptor->Token.Bits.TotalBytesToTransfer);
1103 DPRINT1("TransferDescriptor %lu TransactionError %lu\n", Index, Descriptor->Token.Bits.TransactionError);
1104
1105 DPRINT1("TransferDescriptor %lu Buffer Pointer 0 %x\n", Index, Descriptor->BufferPointer[0]);
1106 DPRINT1("TransferDescriptor %lu Buffer Pointer 1 %x\n", Index, Descriptor->BufferPointer[1]);
1107 DPRINT1("TransferDescriptor %lu Buffer Pointer 2 %x\n", Index, Descriptor->BufferPointer[2]);
1108 DPRINT1("TransferDescriptor %lu Buffer Pointer 3 %x\n", Index, Descriptor->BufferPointer[3]);
1109 DPRINT1("TransferDescriptor %lu Buffer Pointer 4 %x\n", Index, Descriptor->BufferPointer[4]);
1110 Entry = Entry->Flink;
1111 Index++;
1112 }
1113 }
1114
1115
1116 //----------------------------------------------------------------------------------------
1117 NTSTATUS
1118 CUSBRequest::BuildBulkInterruptTransferQueueHead(
1119 PQUEUE_HEAD * OutHead)
1120 {
1121 NTSTATUS Status;
1122 PQUEUE_HEAD QueueHead;
1123 PVOID Base;
1124 ULONG ChainDescriptorLength;
1125 PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor, LastDescriptor;
1126
1127 //
1128 // Allocate the queue head
1129 //
1130 Status = CreateQueueHead(&QueueHead);
1131 if (!NT_SUCCESS(Status))
1132 {
1133 //
1134 // failed to allocate queue head
1135 //
1136 DPRINT1("[EHCI] Failed to create queue head\n");
1137 return Status;
1138 }
1139
1140 //
1141 // sanity checks
1142 //
1143 PC_ASSERT(QueueHead);
1144 PC_ASSERT(m_TransferBufferLength);
1145
1146 if (!m_Base)
1147 {
1148 //
1149 // get virtual base of mdl
1150 //
1151 m_Base = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority);
1152 }
1153
1154 //
1155 // Increase the size of last transfer, 0 in case this is the first
1156 //
1157 Base = (PVOID)((ULONG_PTR)m_Base + m_TransferBufferLengthCompleted);
1158
1159 PC_ASSERT(m_EndpointDescriptor);
1160 PC_ASSERT(Base);
1161
1162 //
1163 // sanity check
1164 //
1165 ASSERT(m_EndpointDescriptor);
1166
1167 //
1168 // use 4 * PAGE_SIZE at max for each new request
1169 //
1170 ULONG MaxTransferLength = min(4 * PAGE_SIZE, m_TransferBufferLength - m_TransferBufferLengthCompleted);
1171
1172 //
1173 // build bulk transfer descriptor chain
1174 //
1175 Status = BuildTransferDescriptorChain(QueueHead,
1176 Base,
1177 MaxTransferLength,
1178 InternalGetPidDirection(),
1179 m_EndpointDescriptor->DataToggle,
1180 &FirstDescriptor,
1181 &LastDescriptor,
1182 &m_EndpointDescriptor->DataToggle,
1183 &ChainDescriptorLength);
1184 if (!NT_SUCCESS(Status))
1185 {
1186 //
1187 // failed to build transfer descriptor chain
1188 //
1189 DPRINT1("[EHCI] Failed to create descriptor chain\n");
1190 m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
1191 return Status;
1192 }
1193
1194 //
1195 // move to next offset
1196 //
1197 m_TransferBufferLengthCompleted += ChainDescriptorLength;
1198
1199 //
1200 // init queue head
1201 //
1202 QueueHead->EndPointCharacteristics.DeviceAddress = GetDeviceAddress();
1203 QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & 0x0F;
1204 QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize;
1205 QueueHead->NextPointer = FirstDescriptor->PhysicalAddr;
1206 QueueHead->CurrentLinkPointer = FirstDescriptor->PhysicalAddr;
1207 QueueHead->AlternateNextPointer = TERMINATE_POINTER;
1208
1209 ASSERT(QueueHead->EndPointCharacteristics.DeviceAddress);
1210 ASSERT(QueueHead->EndPointCharacteristics.EndPointNumber);
1211 ASSERT(QueueHead->EndPointCharacteristics.MaximumPacketLength);
1212 ASSERT(QueueHead->NextPointer);
1213
1214 //
1215 // interrupt on last descriptor
1216 //
1217 LastDescriptor->Token.Bits.InterruptOnComplete = TRUE;
1218
1219 //
1220 // store result
1221 //
1222 *OutHead = QueueHead;
1223
1224 //
1225 // dump status
1226 //
1227 //DumpQueueHead(QueueHead);
1228
1229 //
1230 // done
1231 //
1232 return STATUS_SUCCESS;
1233 }
1234
1235 //----------------------------------------------------------------------------------------
1236 NTSTATUS
1237 STDMETHODCALLTYPE
1238 CUSBRequest::CreateDescriptor(
1239 PQUEUE_TRANSFER_DESCRIPTOR *OutDescriptor)
1240 {
1241 PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
1242 NTSTATUS Status;
1243 PHYSICAL_ADDRESS TransferDescriptorPhysicalAddress;
1244
1245 //
1246 // allocate descriptor
1247 //
1248 Status = m_DmaManager->Allocate(sizeof(QUEUE_TRANSFER_DESCRIPTOR), (PVOID*)&Descriptor, &TransferDescriptorPhysicalAddress);
1249 if (!NT_SUCCESS(Status))
1250 {
1251 //
1252 // failed to allocate transfer descriptor
1253 //
1254 return STATUS_INSUFFICIENT_RESOURCES;
1255 }
1256
1257 //
1258 // initialize transfer descriptor
1259 //
1260 Descriptor->NextPointer = TERMINATE_POINTER;
1261 Descriptor->AlternateNextPointer = TERMINATE_POINTER;
1262 Descriptor->Token.Bits.DataToggle = TRUE;
1263 Descriptor->Token.Bits.ErrorCounter = 0x03;
1264 Descriptor->Token.Bits.Active = TRUE;
1265 Descriptor->PhysicalAddr = TransferDescriptorPhysicalAddress.LowPart;
1266
1267 //
1268 // store result
1269 //
1270 *OutDescriptor = Descriptor;
1271
1272 //
1273 // done
1274 //
1275 return Status;
1276 }
1277
1278 //----------------------------------------------------------------------------------------
1279 NTSTATUS
1280 CUSBRequest::CreateQueueHead(
1281 PQUEUE_HEAD *OutQueueHead)
1282 {
1283 PQUEUE_HEAD QueueHead;
1284 PHYSICAL_ADDRESS QueueHeadPhysicalAddress;
1285 NTSTATUS Status;
1286
1287 //
1288 // allocate queue head
1289 //
1290 Status = m_DmaManager->Allocate(sizeof(QUEUE_HEAD), (PVOID*)&QueueHead, &QueueHeadPhysicalAddress);
1291 if (!NT_SUCCESS(Status))
1292 {
1293 //
1294 // failed to allocate queue head
1295 //
1296 return STATUS_INSUFFICIENT_RESOURCES;
1297 }
1298
1299 //
1300 // initialize queue head
1301 //
1302 QueueHead->HorizontalLinkPointer = TERMINATE_POINTER;
1303 QueueHead->AlternateNextPointer = TERMINATE_POINTER;
1304 QueueHead->NextPointer = TERMINATE_POINTER;
1305 InitializeListHead(&QueueHead->TransferDescriptorListHead);
1306
1307 //
1308 // 1 for non high speed, 0 for high speed device
1309 //
1310 QueueHead->EndPointCharacteristics.ControlEndPointFlag = 0;
1311 QueueHead->EndPointCharacteristics.HeadOfReclamation = FALSE;
1312 QueueHead->EndPointCharacteristics.MaximumPacketLength = 64;
1313
1314 //
1315 // Set NakCountReload to max value possible
1316 //
1317 QueueHead->EndPointCharacteristics.NakCountReload = 0x3;
1318
1319 //
1320 // Get the Initial Data Toggle from the QEDT
1321 //
1322 QueueHead->EndPointCharacteristics.QEDTDataToggleControl = TRUE;
1323
1324 //
1325 // FIXME: check if High Speed Device
1326 //
1327 QueueHead->EndPointCharacteristics.EndPointSpeed = QH_ENDPOINT_HIGHSPEED;
1328 QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = 0x01;
1329 QueueHead->Token.DWord = 0;
1330 QueueHead->Token.Bits.InterruptOnComplete = FALSE;
1331
1332 //
1333 // store address
1334 //
1335 QueueHead->PhysicalAddr = QueueHeadPhysicalAddress.LowPart;
1336
1337 //
1338 // output queue head
1339 //
1340 *OutQueueHead = QueueHead;
1341
1342 //
1343 // done
1344 //
1345 return STATUS_SUCCESS;
1346 }
1347
1348 //----------------------------------------------------------------------------------------
1349 UCHAR
1350 STDMETHODCALLTYPE
1351 CUSBRequest::GetDeviceAddress()
1352 {
1353 PIO_STACK_LOCATION IoStack;
1354 PURB Urb;
1355 PUSBDEVICE UsbDevice;
1356
1357 //
1358 // check if there is an irp provided
1359 //
1360 if (!m_Irp)
1361 {
1362 //
1363 // used provided address
1364 //
1365 return m_DeviceAddress;
1366 }
1367
1368 //
1369 // get current stack location
1370 //
1371 IoStack = IoGetCurrentIrpStackLocation(m_Irp);
1372
1373 //
1374 // get contained urb
1375 //
1376 Urb = (PURB)IoStack->Parameters.Others.Argument1;
1377
1378 //
1379 // check if there is a pipe handle provided
1380 //
1381 if (Urb->UrbHeader.UsbdDeviceHandle)
1382 {
1383 //
1384 // there is a device handle provided
1385 //
1386 UsbDevice = (PUSBDEVICE)Urb->UrbHeader.UsbdDeviceHandle;
1387
1388 //
1389 // return device address
1390 //
1391 return UsbDevice->GetDeviceAddress();
1392 }
1393
1394 //
1395 // no device handle provided, it is the host root bus
1396 //
1397 return 0;
1398 }
1399
1400 //----------------------------------------------------------------------------------------
1401 NTSTATUS
1402 CUSBRequest::BuildSetupPacket()
1403 {
1404 NTSTATUS Status;
1405
1406 //
1407 // allocate common buffer setup packet
1408 //
1409 Status = m_DmaManager->Allocate(sizeof(USB_DEFAULT_PIPE_SETUP_PACKET), (PVOID*)&m_DescriptorPacket, &m_DescriptorSetupPacket);
1410 if (!NT_SUCCESS(Status))
1411 {
1412 //
1413 // no memory
1414 //
1415 return Status;
1416 }
1417
1418 if (m_SetupPacket)
1419 {
1420 //
1421 // copy setup packet
1422 //
1423 RtlCopyMemory(m_DescriptorPacket, m_SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1424 }
1425 else
1426 {
1427 //
1428 // build setup packet from urb
1429 //
1430 Status = BuildSetupPacketFromURB();
1431 }
1432
1433 //
1434 // done
1435 //
1436 return Status;
1437 }
1438
1439
1440 NTSTATUS
1441 CUSBRequest::BuildSetupPacketFromURB()
1442 {
1443 PIO_STACK_LOCATION IoStack;
1444 PURB Urb;
1445 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
1446
1447 //
1448 // sanity checks
1449 //
1450 PC_ASSERT(m_Irp);
1451 PC_ASSERT(m_DescriptorPacket);
1452
1453 //
1454 // get stack location
1455 //
1456 IoStack = IoGetCurrentIrpStackLocation(m_Irp);
1457
1458 //
1459 // get urb
1460 //
1461 Urb = (PURB)IoStack->Parameters.Others.Argument1;
1462
1463 //
1464 // zero descriptor packet
1465 //
1466 RtlZeroMemory(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1467
1468
1469 switch (Urb->UrbHeader.Function)
1470 {
1471 /* CLEAR FEATURE */
1472 case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE:
1473 case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE:
1474 case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT:
1475 UNIMPLEMENTED;
1476 break;
1477
1478 /* GET CONFIG */
1479 case URB_FUNCTION_GET_CONFIGURATION:
1480 m_DescriptorPacket->bRequest = USB_REQUEST_GET_CONFIGURATION;
1481 m_DescriptorPacket->bmRequestType.B = 0x80;
1482 m_DescriptorPacket->wLength = 1;
1483 break;
1484
1485 /* GET DESCRIPTOR */
1486 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
1487 m_DescriptorPacket->bRequest = USB_REQUEST_GET_DESCRIPTOR;
1488 m_DescriptorPacket->wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
1489 m_DescriptorPacket->wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType;
1490 m_DescriptorPacket->wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
1491 m_DescriptorPacket->wLength = (USHORT)Urb->UrbControlDescriptorRequest.TransferBufferLength;
1492 m_DescriptorPacket->bmRequestType.B = 0x80;
1493 break;
1494
1495 /* GET INTERFACE */
1496 case URB_FUNCTION_GET_INTERFACE:
1497 m_DescriptorPacket->bRequest = USB_REQUEST_GET_CONFIGURATION;
1498 m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
1499 m_DescriptorPacket->bmRequestType.B = 0x80;
1500 m_DescriptorPacket->wLength = 1;
1501 break;
1502
1503 /* GET STATUS */
1504 case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
1505 m_DescriptorPacket->bRequest = USB_REQUEST_GET_STATUS;
1506 ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
1507 m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
1508 m_DescriptorPacket->bmRequestType.B = 0x80;
1509 m_DescriptorPacket->wLength = 2;
1510 break;
1511
1512 case URB_FUNCTION_GET_STATUS_FROM_INTERFACE:
1513 m_DescriptorPacket->bRequest = USB_REQUEST_GET_STATUS;
1514 ASSERT(Urb->UrbControlGetStatusRequest.Index != 0);
1515 m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
1516 m_DescriptorPacket->bmRequestType.B = 0x81;
1517 m_DescriptorPacket->wLength = 2;
1518 break;
1519
1520 case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT:
1521 m_DescriptorPacket->bRequest = USB_REQUEST_GET_STATUS;
1522 ASSERT(Urb->UrbControlGetStatusRequest.Index != 0);
1523 m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
1524 m_DescriptorPacket->bmRequestType.B = 0x82;
1525 m_DescriptorPacket->wLength = 2;
1526 break;
1527
1528 /* SET ADDRESS */
1529
1530 /* SET CONFIG */
1531 case URB_FUNCTION_SELECT_CONFIGURATION:
1532 m_DescriptorPacket->bRequest = USB_REQUEST_SET_CONFIGURATION;
1533 m_DescriptorPacket->wValue.W = Urb->UrbSelectConfiguration.ConfigurationDescriptor->bConfigurationValue;
1534 m_DescriptorPacket->wIndex.W = 0;
1535 m_DescriptorPacket->wLength = 0;
1536 m_DescriptorPacket->bmRequestType.B = 0x00;
1537 break;
1538
1539 /* SET DESCRIPTOR */
1540 case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE:
1541 case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE:
1542 case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT:
1543 UNIMPLEMENTED;
1544 break;
1545
1546 /* SET FEATURE */
1547 case URB_FUNCTION_SET_FEATURE_TO_DEVICE:
1548 m_DescriptorPacket->bRequest = USB_REQUEST_SET_FEATURE;
1549 ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
1550 m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
1551 m_DescriptorPacket->bmRequestType.B = 0x80;
1552 break;
1553
1554 case URB_FUNCTION_SET_FEATURE_TO_INTERFACE:
1555 m_DescriptorPacket->bRequest = USB_REQUEST_SET_FEATURE;
1556 ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
1557 m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
1558 m_DescriptorPacket->bmRequestType.B = 0x81;
1559 break;
1560
1561 case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT:
1562 m_DescriptorPacket->bRequest = USB_REQUEST_SET_FEATURE;
1563 ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
1564 m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
1565 m_DescriptorPacket->bmRequestType.B = 0x82;
1566 break;
1567
1568 /* SET INTERFACE*/
1569 case URB_FUNCTION_SELECT_INTERFACE:
1570 m_DescriptorPacket->bRequest = USB_REQUEST_SET_INTERFACE;
1571 m_DescriptorPacket->wValue.W = Urb->UrbSelectInterface.Interface.AlternateSetting;
1572 m_DescriptorPacket->wIndex.W = Urb->UrbSelectInterface.Interface.InterfaceNumber;
1573 m_DescriptorPacket->wLength = 0;
1574 m_DescriptorPacket->bmRequestType.B = 0x01;
1575 break;
1576
1577 /* SYNC FRAME */
1578 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
1579 UNIMPLEMENTED;
1580 break;
1581 default:
1582 UNIMPLEMENTED;
1583 break;
1584 }
1585
1586 return Status;
1587 }
1588
1589 //----------------------------------------------------------------------------------------
1590 VOID
1591 STDMETHODCALLTYPE
1592 CUSBRequest::GetResultStatus(
1593 OUT OPTIONAL NTSTATUS * NtStatusCode,
1594 OUT OPTIONAL PULONG UrbStatusCode)
1595 {
1596 //
1597 // sanity check
1598 //
1599 PC_ASSERT(m_CompletionEvent);
1600
1601 //
1602 // wait for the operation to complete
1603 //
1604 KeWaitForSingleObject(m_CompletionEvent, Executive, KernelMode, FALSE, NULL);
1605
1606 //
1607 // copy status
1608 //
1609 if (NtStatusCode)
1610 {
1611 *NtStatusCode = m_NtStatusCode;
1612 }
1613
1614 //
1615 // copy urb status
1616 //
1617 if (UrbStatusCode)
1618 {
1619 *UrbStatusCode = m_UrbStatusCode;
1620 }
1621
1622 }
1623
1624 //-----------------------------------------------------------------------------------------
1625 BOOLEAN
1626 STDMETHODCALLTYPE
1627 CUSBRequest::ShouldReleaseRequestAfterCompletion()
1628 {
1629 if (m_Irp)
1630 {
1631 //
1632 // the request is completed, release it
1633 //
1634 return TRUE;
1635 }
1636 else
1637 {
1638 //
1639 // created with an setup packet, don't release
1640 //
1641 return FALSE;
1642 }
1643 }
1644
1645 //-----------------------------------------------------------------------------------------
1646 VOID
1647 STDMETHODCALLTYPE
1648 CUSBRequest::FreeQueueHead(
1649 IN struct _QUEUE_HEAD * QueueHead)
1650 {
1651 PLIST_ENTRY Entry;
1652 PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
1653
1654 //
1655 // sanity checks
1656 //
1657 ASSERT(m_DmaManager);
1658 ASSERT(QueueHead);
1659 ASSERT(!IsListEmpty(&QueueHead->TransferDescriptorListHead));
1660
1661 do
1662 {
1663 //
1664 // get transfer descriptors
1665 //
1666 Entry = RemoveHeadList(&QueueHead->TransferDescriptorListHead);
1667 ASSERT(Entry);
1668
1669 //
1670 // obtain descriptor from entry
1671 //
1672 Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry);
1673 ASSERT(Descriptor);
1674
1675 //
1676 // add transfer count
1677 //
1678 m_TotalBytesTransferred += (Descriptor->TotalBytesToTransfer - Descriptor->Token.Bits.TotalBytesToTransfer);
1679 DPRINT("TotalBytes Transferred in Descriptor %p Phys Addr %x TotalBytesSoftware %lu Length %lu\n", Descriptor, Descriptor->PhysicalAddr, Descriptor->TotalBytesToTransfer, Descriptor->TotalBytesToTransfer - Descriptor->Token.Bits.TotalBytesToTransfer);
1680
1681 //
1682 // release transfer descriptors
1683 //
1684 m_DmaManager->Release(Descriptor, sizeof(QUEUE_TRANSFER_DESCRIPTOR));
1685
1686 }while(!IsListEmpty(&QueueHead->TransferDescriptorListHead));
1687
1688 if (m_DescriptorPacket)
1689 {
1690 //
1691 // release packet descriptor
1692 //
1693 m_DmaManager->Release(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1694 }
1695
1696 //
1697 // release queue head
1698 //
1699 m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
1700
1701 //
1702 // nullify pointers
1703 //
1704 m_QueueHead = 0;
1705 m_DescriptorPacket = 0;
1706 }
1707
1708 //-----------------------------------------------------------------------------------------
1709 BOOLEAN
1710 STDMETHODCALLTYPE
1711 CUSBRequest::IsQueueHeadComplete(
1712 struct _QUEUE_HEAD * QueueHead)
1713 {
1714 PLIST_ENTRY Entry;
1715 PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
1716
1717 //
1718 // first check - is the queue head currently active
1719 //
1720 if (QueueHead->Token.Bits.Active)
1721 {
1722 //
1723 // queue head is active (currently processed)
1724 //
1725 return FALSE;
1726 }
1727
1728 if (QueueHead->Token.Bits.Halted)
1729 {
1730 //
1731 // error occured
1732 //
1733 DPRINT1("Found halted queue head %p\n", QueueHead);
1734 DumpQueueHead(QueueHead);
1735 //ASSERT(FALSE);
1736 return TRUE;
1737 }
1738
1739 //
1740 // loop list and see if there are any active descriptors
1741 //
1742 Entry = QueueHead->TransferDescriptorListHead.Flink;
1743 while(Entry != &QueueHead->TransferDescriptorListHead)
1744 {
1745 //
1746 // obtain descriptor from entry
1747 //
1748 Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry);
1749 ASSERT(Descriptor);
1750 if (Descriptor->Token.Bits.Active)
1751 {
1752 //
1753 // descriptor is still active
1754 //
1755 return FALSE;
1756 }
1757
1758 //
1759 // move to next entry
1760 //
1761 Entry = Entry->Flink;
1762 }
1763
1764 DPRINT("QueueHead %p Addr %x is complete\n", QueueHead, QueueHead->PhysicalAddr);
1765
1766 //
1767 // no active descriptors found, queue head is finished
1768 //
1769 return TRUE;
1770 }
1771
1772 //-----------------------------------------------------------------------------------------
1773 ULONG
1774 CUSBRequest::InternalCalculateTransferLength()
1775 {
1776 if (!m_Irp)
1777 {
1778 //
1779 // FIXME: get length for control request
1780 //
1781 return m_TransferBufferLength;
1782 }
1783
1784 //
1785 // sanity check
1786 //
1787 ASSERT(m_EndpointDescriptor);
1788 if (USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress))
1789 {
1790 //
1791 // bulk in request
1792 // HACK: Properly determine transfer length
1793 //
1794 return m_TransferBufferLength;//m_TotalBytesTransferred;
1795 }
1796
1797 //
1798 // bulk out transfer
1799 //
1800 return m_TransferBufferLength;
1801 }
1802
1803 USB_DEVICE_SPEED
1804 CUSBRequest::GetSpeed()
1805 {
1806 return m_Speed;
1807 }
1808
1809 UCHAR
1810 CUSBRequest::GetInterval()
1811 {
1812 if (!m_EndpointDescriptor)
1813 return 0;
1814
1815 return m_EndpointDescriptor->EndPointDescriptor.bInterval;
1816 }
1817
1818 //-----------------------------------------------------------------------------------------
1819 NTSTATUS
1820 NTAPI
1821 InternalCreateUSBRequest(
1822 PUSBREQUEST *OutRequest)
1823 {
1824 PUSBREQUEST This;
1825
1826 //
1827 // allocate requests
1828 //
1829 This = new(NonPagedPool, TAG_USBEHCI) CUSBRequest(0);
1830 if (!This)
1831 {
1832 //
1833 // failed to allocate
1834 //
1835 return STATUS_INSUFFICIENT_RESOURCES;
1836 }
1837
1838 //
1839 // add reference count
1840 //
1841 This->AddRef();
1842
1843 //
1844 // return result
1845 //
1846 *OutRequest = (PUSBREQUEST)This;
1847
1848 //
1849 // done
1850 //
1851 return STATUS_SUCCESS;
1852 }