[USBEHCI][USBOHCI][USBUHCI]
[reactos.git] / reactos / 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
619 //
620 Address = MmGetPhysicalAddress(TransferBuffer);
621
622 //
623 // use physical address
624 //
625 CurrentDescriptor->BufferPointer[Index] = Address.LowPart;
626 CurrentDescriptor->ExtendedBufferPointer[Index] = Address.HighPart;
627
628 //
629 // Get the offset from page size
630 //
631 PageOffset = BYTE_OFFSET(CurrentDescriptor->BufferPointer[Index]);
632 if (PageOffset != 0)
633 {
634 //
635 // move to next page
636 //
637 TransferBuffer = (PVOID)ROUND_TO_PAGES(TransferBuffer);
638 }
639 else
640 {
641 //
642 // move to next page
643 //
644 TransferBuffer = (PVOID)((ULONG_PTR)TransferBuffer + PAGE_SIZE);
645 }
646
647 //
648 // calculate buffer length
649 //
650 BufferLength = min(TransferBufferLength, PAGE_SIZE - PageOffset);
651
652 //
653 // increment transfer bytes
654 //
655 CurrentDescriptor->Token.Bits.TotalBytesToTransfer += BufferLength;
656 CurrentDescriptor->TotalBytesToTransfer += BufferLength;
657 Length += BufferLength;
658 DPRINT("Index %lu TransferBufferLength %lu PageOffset %x BufferLength %lu Buffer Phy %p TransferBuffer %p\n", Index, TransferBufferLength, PageOffset, BufferLength, CurrentDescriptor->BufferPointer[Index], TransferBuffer);
659
660 //
661 // decrement available byte count
662 //
663 TransferBufferLength -= BufferLength;
664 if (TransferBufferLength == 0)
665 {
666 //
667 // end reached
668 //
669 break;
670 }
671
672 //
673 // sanity check
674 //
675 if (Index > 1)
676 {
677 //
678 // no equal buffers
679 //
680 ASSERT(CurrentDescriptor->BufferPointer[Index] != CurrentDescriptor->BufferPointer[Index-1]);
681 }
682
683 //
684 // next descriptor index
685 //
686 Index++;
687 }while(Index < 5);
688
689 //
690 // store result
691 //
692 *OutDescriptorLength = Length;
693 }
694
695 NTSTATUS
696 STDMETHODCALLTYPE
697 CUSBRequest::BuildTransferDescriptorChain(
698 IN PQUEUE_HEAD QueueHead,
699 IN PVOID TransferBuffer,
700 IN ULONG TransferBufferLength,
701 IN UCHAR PidCode,
702 IN UCHAR InitialDataToggle,
703 OUT PQUEUE_TRANSFER_DESCRIPTOR * OutFirstDescriptor,
704 OUT PQUEUE_TRANSFER_DESCRIPTOR * OutLastDescriptor,
705 OUT PUCHAR OutDataToggle,
706 OUT PULONG OutTransferBufferOffset)
707 {
708 PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor = NULL, CurrentDescriptor, LastDescriptor = NULL;
709 NTSTATUS Status;
710 ULONG DescriptorLength, TransferBufferOffset = 0;
711 ULONG MaxPacketSize = 0, TransferSize;
712
713 //
714 // is there an endpoint descriptor
715 //
716 if (m_EndpointDescriptor)
717 {
718 //
719 // use endpoint packet size
720 //
721 MaxPacketSize = m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize;
722 }
723
724 do
725 {
726 //
727 // allocate transfer descriptor
728 //
729 Status = CreateDescriptor(&CurrentDescriptor);
730 if (!NT_SUCCESS(Status))
731 {
732 //
733 // failed to allocate transfer descriptor
734 //
735 return STATUS_INSUFFICIENT_RESOURCES;
736 }
737
738 if (MaxPacketSize)
739 {
740 //
741 // transfer size is minimum available buffer or endpoint size
742 //
743 TransferSize = min(TransferBufferLength - TransferBufferOffset, MaxPacketSize);
744 }
745 else
746 {
747 //
748 // use available buffer
749 //
750 TransferSize = TransferBufferLength - TransferBufferOffset;
751 }
752
753 //
754 // now init the descriptor
755 //
756 InitDescriptor(CurrentDescriptor,
757 (PVOID)((ULONG_PTR)TransferBuffer + TransferBufferOffset),
758 TransferSize,
759 PidCode,
760 InitialDataToggle,
761 &DescriptorLength);
762
763 //
764 // insert into queue head
765 //
766 InsertTailList(&QueueHead->TransferDescriptorListHead, &CurrentDescriptor->DescriptorEntry);
767
768 //
769 // adjust offset
770 //
771 TransferBufferOffset += DescriptorLength;
772
773 if (LastDescriptor)
774 {
775 //
776 // link to current descriptor
777 //
778 LastDescriptor->NextPointer = CurrentDescriptor->PhysicalAddr;
779 LastDescriptor = CurrentDescriptor;
780 }
781 else
782 {
783 //
784 // first descriptor in chain
785 //
786 LastDescriptor = FirstDescriptor = CurrentDescriptor;
787 }
788
789 //
790 // flip data toggle
791 //
792 InitialDataToggle = !InitialDataToggle;
793
794 if(TransferBufferLength == TransferBufferOffset)
795 {
796 //
797 // end reached
798 //
799 break;
800 }
801
802 }while(TRUE);
803
804 if (OutFirstDescriptor)
805 {
806 //
807 // store first descriptor
808 //
809 *OutFirstDescriptor = FirstDescriptor;
810 }
811
812 if (OutLastDescriptor)
813 {
814 //
815 // store last descriptor
816 //
817 *OutLastDescriptor = CurrentDescriptor;
818 }
819
820 if (OutDataToggle)
821 {
822 //
823 // store result data toggle
824 //
825 *OutDataToggle = InitialDataToggle;
826 }
827
828 if (OutTransferBufferOffset)
829 {
830 //
831 // store offset
832 //
833 *OutTransferBufferOffset = TransferBufferOffset;
834 }
835
836 //
837 // done
838 //
839 return STATUS_SUCCESS;
840 }
841
842 //----------------------------------------------------------------------------------------
843 NTSTATUS
844 CUSBRequest::BuildControlTransferQueueHead(
845 PQUEUE_HEAD * OutHead)
846 {
847 NTSTATUS Status;
848 ULONG DescriptorChainLength;
849 PQUEUE_HEAD QueueHead;
850 PQUEUE_TRANSFER_DESCRIPTOR SetupDescriptor, StatusDescriptor, FirstDescriptor, LastDescriptor;
851
852 //
853 // first allocate the queue head
854 //
855 Status = CreateQueueHead(&QueueHead);
856 if (!NT_SUCCESS(Status))
857 {
858 //
859 // failed to allocate queue head
860 //
861 DPRINT1("[EHCI] Failed to create queue head\n");
862 return Status;
863 }
864
865 //
866 // sanity check
867 //
868 PC_ASSERT(QueueHead);
869
870 //
871 // create setup packet
872 //
873 Status = BuildSetupPacket();
874 if (!NT_SUCCESS(Status))
875 {
876 // failed to create setup packet
877 DPRINT1("[EHCI] Failed to create setup packet\n");
878
879 // release queue head
880 m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
881 return Status;
882 }
883
884 //
885 // create setup descriptor
886 //
887 Status = CreateDescriptor(&SetupDescriptor);
888 if (!NT_SUCCESS(Status))
889 {
890 // failed to create setup transfer descriptor
891 DPRINT1("[EHCI] Failed to create setup descriptor\n");
892
893 if (m_DescriptorPacket)
894 {
895 // release packet descriptor
896 m_DmaManager->Release(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
897 }
898
899 // release queue head
900 m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
901 return Status;
902 }
903
904 //
905 // create status descriptor
906 //
907 Status = CreateDescriptor(&StatusDescriptor);
908 if (!NT_SUCCESS(Status))
909 {
910 // failed to create status transfer descriptor
911 DPRINT1("[EHCI] Failed to create status descriptor\n");
912
913 // release setup transfer descriptor
914 m_DmaManager->Release(SetupDescriptor, sizeof(QUEUE_TRANSFER_DESCRIPTOR));
915
916 if (m_DescriptorPacket)
917 {
918 // release packet descriptor
919 m_DmaManager->Release(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
920 }
921
922 // release queue head
923 m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
924 return Status;
925 }
926
927 //
928 // now initialize the queue head
929 //
930 QueueHead->EndPointCharacteristics.DeviceAddress = GetDeviceAddress();
931
932 ASSERT(m_EndpointDescriptor == NULL);
933
934 //
935 // init setup descriptor
936 //
937 SetupDescriptor->Token.Bits.PIDCode = PID_CODE_SETUP_TOKEN;
938 SetupDescriptor->Token.Bits.TotalBytesToTransfer = sizeof(USB_DEFAULT_PIPE_SETUP_PACKET);
939 SetupDescriptor->Token.Bits.DataToggle = FALSE;
940 SetupDescriptor->BufferPointer[0] = m_DescriptorSetupPacket.LowPart;
941 SetupDescriptor->ExtendedBufferPointer[0] = m_DescriptorSetupPacket.HighPart;
942 InsertTailList(&QueueHead->TransferDescriptorListHead, &SetupDescriptor->DescriptorEntry);
943
944
945 //
946 // init status descriptor
947 //
948 StatusDescriptor->Token.Bits.TotalBytesToTransfer = 0;
949 StatusDescriptor->Token.Bits.DataToggle = TRUE;
950 StatusDescriptor->Token.Bits.InterruptOnComplete = TRUE;
951
952 //
953 // is there data
954 //
955 if (m_TransferBufferLength)
956 {
957 Status = BuildTransferDescriptorChain(QueueHead,
958 MmGetMdlVirtualAddress(m_TransferBufferMDL),
959 m_TransferBufferLength,
960 InternalGetPidDirection(),
961 TRUE,
962 &FirstDescriptor,
963 &LastDescriptor,
964 NULL,
965 &DescriptorChainLength);
966 if (!NT_SUCCESS(Status))
967 {
968 // failed to create descriptor chain
969 DPRINT1("[EHCI] Failed to create descriptor chain\n");
970
971 // release status transfer descriptor
972 m_DmaManager->Release(StatusDescriptor, sizeof(QUEUE_TRANSFER_DESCRIPTOR));
973
974 // release setup transfer descriptor
975 m_DmaManager->Release(SetupDescriptor, sizeof(QUEUE_TRANSFER_DESCRIPTOR));
976
977 if (m_DescriptorPacket)
978 {
979 // release packet descriptor
980 m_DmaManager->Release(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
981 }
982
983 // release queue head
984 m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
985 return Status;
986 }
987
988 if (m_TransferBufferLength != DescriptorChainLength)
989 {
990 DPRINT1("DescriptorChainLength %x\n", DescriptorChainLength);
991 DPRINT1("m_TransferBufferLength %x\n", m_TransferBufferLength);
992 ASSERT(FALSE);
993 }
994
995 //
996 // now link the descriptors
997 //
998 SetupDescriptor->NextPointer = FirstDescriptor->PhysicalAddr;
999 SetupDescriptor->AlternateNextPointer = FirstDescriptor->PhysicalAddr;
1000 LastDescriptor->NextPointer = StatusDescriptor->PhysicalAddr;
1001 LastDescriptor->AlternateNextPointer = StatusDescriptor->PhysicalAddr;
1002
1003
1004 //
1005 // pid code is flipped for ops with data stage
1006 //
1007 StatusDescriptor->Token.Bits.PIDCode = !InternalGetPidDirection();
1008 }
1009 else
1010 {
1011 //
1012 // direct link
1013 //
1014 SetupDescriptor->NextPointer = StatusDescriptor->PhysicalAddr;
1015 SetupDescriptor->AlternateNextPointer = StatusDescriptor->PhysicalAddr;
1016
1017 //
1018 // retrieve result of operation
1019 //
1020 StatusDescriptor->Token.Bits.PIDCode = PID_CODE_IN_TOKEN;
1021 }
1022
1023 //
1024 // insert status descriptor
1025 //
1026 InsertTailList(&QueueHead->TransferDescriptorListHead, &StatusDescriptor->DescriptorEntry);
1027
1028
1029 //
1030 // link transfer descriptors to queue head
1031 //
1032 QueueHead->NextPointer = SetupDescriptor->PhysicalAddr;
1033
1034 //
1035 // store result
1036 //
1037 *OutHead = QueueHead;
1038
1039 //
1040 // displays the current request
1041 //
1042 //DumpQueueHead(QueueHead);
1043
1044 DPRINT("BuildControlTransferQueueHead done\n");
1045 //
1046 // done
1047 //
1048 return STATUS_SUCCESS;
1049 }
1050
1051 VOID
1052 CUSBRequest::DumpQueueHead(
1053 IN PQUEUE_HEAD QueueHead)
1054 {
1055 PLIST_ENTRY Entry;
1056 PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
1057 ULONG Index = 0;
1058
1059 DPRINT1("QueueHead %p Addr %x\n", QueueHead, QueueHead->PhysicalAddr);
1060 DPRINT1("QueueHead AlternateNextPointer %x\n", QueueHead->AlternateNextPointer);
1061 DPRINT1("QueueHead NextPointer %x\n", QueueHead->NextPointer);
1062
1063 DPRINT1("QueueHead HubAddr %x\n", QueueHead->EndPointCharacteristics.ControlEndPointFlag);
1064 DPRINT1("QueueHead DeviceAddress %x\n", QueueHead->EndPointCharacteristics.DeviceAddress);
1065 DPRINT1("QueueHead EndPointNumber %x\n", QueueHead->EndPointCharacteristics.EndPointNumber);
1066 DPRINT1("QueueHead EndPointSpeed %x\n", QueueHead->EndPointCharacteristics.EndPointSpeed);
1067 DPRINT1("QueueHead HeadOfReclamation %x\n", QueueHead->EndPointCharacteristics.HeadOfReclamation);
1068 DPRINT1("QueueHead InactiveOnNextTransaction %x\n", QueueHead->EndPointCharacteristics.InactiveOnNextTransaction);
1069 DPRINT1("QueueHead MaximumPacketLength %x\n", QueueHead->EndPointCharacteristics.MaximumPacketLength);
1070 DPRINT1("QueueHead NakCountReload %x\n", QueueHead->EndPointCharacteristics.NakCountReload);
1071 DPRINT1("QueueHead QEDTDataToggleControl %x\n", QueueHead->EndPointCharacteristics.QEDTDataToggleControl);
1072 DPRINT1("QueueHead HubAddr %x\n", QueueHead->EndPointCapabilities.HubAddr);
1073 DPRINT1("QueueHead InterruptScheduleMask %x\n", QueueHead->EndPointCapabilities.InterruptScheduleMask);
1074 DPRINT1("QueueHead NumberOfTransactionPerFrame %x\n", QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame);
1075 DPRINT1("QueueHead PortNumber %x\n", QueueHead->EndPointCapabilities.PortNumber);
1076 DPRINT1("QueueHead SplitCompletionMask %x\n", QueueHead->EndPointCapabilities.SplitCompletionMask);
1077
1078 Entry = QueueHead->TransferDescriptorListHead.Flink;
1079 while(Entry != &QueueHead->TransferDescriptorListHead)
1080 {
1081 //
1082 // get transfer descriptor
1083 //
1084 Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry);
1085
1086 DPRINT1("TransferDescriptor %lu Addr %x\n", Index, Descriptor->PhysicalAddr);
1087 DPRINT1("TransferDescriptor %lu Next %x\n", Index, Descriptor->NextPointer);
1088 DPRINT1("TransferDescriptor %lu AlternateNextPointer %x\n", Index, Descriptor->AlternateNextPointer);
1089 DPRINT1("TransferDescriptor %lu Active %lu\n", Index, Descriptor->Token.Bits.Active);
1090 DPRINT1("TransferDescriptor %lu BabbleDetected %lu\n", Index, Descriptor->Token.Bits.BabbleDetected);
1091 DPRINT1("TransferDescriptor %lu CurrentPage %lu\n", Index, Descriptor->Token.Bits.CurrentPage);
1092 DPRINT1("TransferDescriptor %lu DataBufferError %lu\n", Index, Descriptor->Token.Bits.DataBufferError);
1093 DPRINT1("TransferDescriptor %lu DataToggle %lu\n", Index, Descriptor->Token.Bits.DataToggle);
1094 DPRINT1("TransferDescriptor %lu ErrorCounter %lu\n", Index, Descriptor->Token.Bits.ErrorCounter);
1095 DPRINT1("TransferDescriptor %lu Halted %lu\n", Index, Descriptor->Token.Bits.Halted);
1096 DPRINT1("TransferDescriptor %lu InterruptOnComplete %x\n", Index, Descriptor->Token.Bits.InterruptOnComplete);
1097 DPRINT1("TransferDescriptor %lu MissedMicroFrame %lu\n", Index, Descriptor->Token.Bits.MissedMicroFrame);
1098 DPRINT1("TransferDescriptor %lu PIDCode %lu\n", Index, Descriptor->Token.Bits.PIDCode);
1099 DPRINT1("TransferDescriptor %lu PingState %lu\n", Index, Descriptor->Token.Bits.PingState);
1100 DPRINT1("TransferDescriptor %lu SplitTransactionState %lu\n", Index, Descriptor->Token.Bits.SplitTransactionState);
1101 DPRINT1("TransferDescriptor %lu TotalBytesToTransfer %lu\n", Index, Descriptor->Token.Bits.TotalBytesToTransfer);
1102 DPRINT1("TransferDescriptor %lu TransactionError %lu\n", Index, Descriptor->Token.Bits.TransactionError);
1103
1104 DPRINT1("TransferDescriptor %lu Buffer Pointer 0 %x\n", Index, Descriptor->BufferPointer[0]);
1105 DPRINT1("TransferDescriptor %lu Buffer Pointer 1 %x\n", Index, Descriptor->BufferPointer[1]);
1106 DPRINT1("TransferDescriptor %lu Buffer Pointer 2 %x\n", Index, Descriptor->BufferPointer[2]);
1107 DPRINT1("TransferDescriptor %lu Buffer Pointer 3 %x\n", Index, Descriptor->BufferPointer[3]);
1108 DPRINT1("TransferDescriptor %lu Buffer Pointer 4 %x\n", Index, Descriptor->BufferPointer[4]);
1109 Entry = Entry->Flink;
1110 Index++;
1111 }
1112 }
1113
1114
1115 //----------------------------------------------------------------------------------------
1116 NTSTATUS
1117 CUSBRequest::BuildBulkInterruptTransferQueueHead(
1118 PQUEUE_HEAD * OutHead)
1119 {
1120 NTSTATUS Status;
1121 PQUEUE_HEAD QueueHead;
1122 PVOID Base;
1123 ULONG ChainDescriptorLength;
1124 PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor, LastDescriptor;
1125
1126 //
1127 // Allocate the queue head
1128 //
1129 Status = CreateQueueHead(&QueueHead);
1130 if (!NT_SUCCESS(Status))
1131 {
1132 //
1133 // failed to allocate queue head
1134 //
1135 DPRINT1("[EHCI] Failed to create queue head\n");
1136 return Status;
1137 }
1138
1139 //
1140 // sanity checks
1141 //
1142 PC_ASSERT(QueueHead);
1143 PC_ASSERT(m_TransferBufferLength);
1144
1145 if (!m_Base)
1146 {
1147 //
1148 // get virtual base of mdl
1149 //
1150 m_Base = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority);
1151 }
1152
1153 //
1154 // Increase the size of last transfer, 0 in case this is the first
1155 //
1156 Base = (PVOID)((ULONG_PTR)m_Base + m_TransferBufferLengthCompleted);
1157
1158 PC_ASSERT(m_EndpointDescriptor);
1159 PC_ASSERT(Base);
1160
1161 //
1162 // sanity check
1163 //
1164 ASSERT(m_EndpointDescriptor);
1165
1166 //
1167 // use 4 * PAGE_SIZE at max for each new request
1168 //
1169 ULONG MaxTransferLength = min(4 * PAGE_SIZE, m_TransferBufferLength - m_TransferBufferLengthCompleted);
1170
1171 //
1172 // build bulk transfer descriptor chain
1173 //
1174 Status = BuildTransferDescriptorChain(QueueHead,
1175 Base,
1176 MaxTransferLength,
1177 InternalGetPidDirection(),
1178 m_EndpointDescriptor->DataToggle,
1179 &FirstDescriptor,
1180 &LastDescriptor,
1181 &m_EndpointDescriptor->DataToggle,
1182 &ChainDescriptorLength);
1183 if (!NT_SUCCESS(Status))
1184 {
1185 //
1186 // failed to build transfer descriptor chain
1187 //
1188 DPRINT1("[EHCI] Failed to create descriptor chain\n");
1189 m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
1190 return Status;
1191 }
1192
1193 //
1194 // move to next offset
1195 //
1196 m_TransferBufferLengthCompleted += ChainDescriptorLength;
1197
1198 //
1199 // init queue head
1200 //
1201 QueueHead->EndPointCharacteristics.DeviceAddress = GetDeviceAddress();
1202 QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & 0x0F;
1203 QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize;
1204 QueueHead->NextPointer = FirstDescriptor->PhysicalAddr;
1205 QueueHead->CurrentLinkPointer = FirstDescriptor->PhysicalAddr;
1206 QueueHead->AlternateNextPointer = TERMINATE_POINTER;
1207
1208 ASSERT(QueueHead->EndPointCharacteristics.DeviceAddress);
1209 ASSERT(QueueHead->EndPointCharacteristics.EndPointNumber);
1210 ASSERT(QueueHead->EndPointCharacteristics.MaximumPacketLength);
1211 ASSERT(QueueHead->NextPointer);
1212
1213 //
1214 // interrupt on last descriptor
1215 //
1216 LastDescriptor->Token.Bits.InterruptOnComplete = TRUE;
1217
1218 //
1219 // store result
1220 //
1221 *OutHead = QueueHead;
1222
1223 //
1224 // dump status
1225 //
1226 //DumpQueueHead(QueueHead);
1227
1228 //
1229 // done
1230 //
1231 return STATUS_SUCCESS;
1232 }
1233
1234 //----------------------------------------------------------------------------------------
1235 NTSTATUS
1236 STDMETHODCALLTYPE
1237 CUSBRequest::CreateDescriptor(
1238 PQUEUE_TRANSFER_DESCRIPTOR *OutDescriptor)
1239 {
1240 PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
1241 NTSTATUS Status;
1242 PHYSICAL_ADDRESS TransferDescriptorPhysicalAddress;
1243
1244 //
1245 // allocate descriptor
1246 //
1247 Status = m_DmaManager->Allocate(sizeof(QUEUE_TRANSFER_DESCRIPTOR), (PVOID*)&Descriptor, &TransferDescriptorPhysicalAddress);
1248 if (!NT_SUCCESS(Status))
1249 {
1250 //
1251 // failed to allocate transfer descriptor
1252 //
1253 return STATUS_INSUFFICIENT_RESOURCES;
1254 }
1255
1256 //
1257 // initialize transfer descriptor
1258 //
1259 Descriptor->NextPointer = TERMINATE_POINTER;
1260 Descriptor->AlternateNextPointer = TERMINATE_POINTER;
1261 Descriptor->Token.Bits.DataToggle = TRUE;
1262 Descriptor->Token.Bits.ErrorCounter = 0x03;
1263 Descriptor->Token.Bits.Active = TRUE;
1264 Descriptor->PhysicalAddr = TransferDescriptorPhysicalAddress.LowPart;
1265
1266 //
1267 // store result
1268 //
1269 *OutDescriptor = Descriptor;
1270
1271 //
1272 // done
1273 //
1274 return Status;
1275 }
1276
1277 //----------------------------------------------------------------------------------------
1278 NTSTATUS
1279 CUSBRequest::CreateQueueHead(
1280 PQUEUE_HEAD *OutQueueHead)
1281 {
1282 PQUEUE_HEAD QueueHead;
1283 PHYSICAL_ADDRESS QueueHeadPhysicalAddress;
1284 NTSTATUS Status;
1285
1286 //
1287 // allocate queue head
1288 //
1289 Status = m_DmaManager->Allocate(sizeof(QUEUE_HEAD), (PVOID*)&QueueHead, &QueueHeadPhysicalAddress);
1290 if (!NT_SUCCESS(Status))
1291 {
1292 //
1293 // failed to allocate queue head
1294 //
1295 return STATUS_INSUFFICIENT_RESOURCES;
1296 }
1297
1298 //
1299 // initialize queue head
1300 //
1301 QueueHead->HorizontalLinkPointer = TERMINATE_POINTER;
1302 QueueHead->AlternateNextPointer = TERMINATE_POINTER;
1303 QueueHead->NextPointer = TERMINATE_POINTER;
1304 InitializeListHead(&QueueHead->TransferDescriptorListHead);
1305
1306 //
1307 // 1 for non high speed, 0 for high speed device
1308 //
1309 QueueHead->EndPointCharacteristics.ControlEndPointFlag = 0;
1310 QueueHead->EndPointCharacteristics.HeadOfReclamation = FALSE;
1311 QueueHead->EndPointCharacteristics.MaximumPacketLength = 64;
1312
1313 //
1314 // Set NakCountReload to max value possible
1315 //
1316 QueueHead->EndPointCharacteristics.NakCountReload = 0x3;
1317
1318 //
1319 // Get the Initial Data Toggle from the QEDT
1320 //
1321 QueueHead->EndPointCharacteristics.QEDTDataToggleControl = TRUE;
1322
1323 //
1324 // FIXME: check if High Speed Device
1325 //
1326 QueueHead->EndPointCharacteristics.EndPointSpeed = QH_ENDPOINT_HIGHSPEED;
1327 QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = 0x01;
1328 QueueHead->Token.DWord = 0;
1329 QueueHead->Token.Bits.InterruptOnComplete = FALSE;
1330
1331 //
1332 // store address
1333 //
1334 QueueHead->PhysicalAddr = QueueHeadPhysicalAddress.LowPart;
1335
1336 //
1337 // output queue head
1338 //
1339 *OutQueueHead = QueueHead;
1340
1341 //
1342 // done
1343 //
1344 return STATUS_SUCCESS;
1345 }
1346
1347 //----------------------------------------------------------------------------------------
1348 UCHAR
1349 STDMETHODCALLTYPE
1350 CUSBRequest::GetDeviceAddress()
1351 {
1352 PIO_STACK_LOCATION IoStack;
1353 PURB Urb;
1354 PUSBDEVICE UsbDevice;
1355
1356 //
1357 // check if there is an irp provided
1358 //
1359 if (!m_Irp)
1360 {
1361 //
1362 // used provided address
1363 //
1364 return m_DeviceAddress;
1365 }
1366
1367 //
1368 // get current stack location
1369 //
1370 IoStack = IoGetCurrentIrpStackLocation(m_Irp);
1371
1372 //
1373 // get contained urb
1374 //
1375 Urb = (PURB)IoStack->Parameters.Others.Argument1;
1376
1377 //
1378 // check if there is a pipe handle provided
1379 //
1380 if (Urb->UrbHeader.UsbdDeviceHandle)
1381 {
1382 //
1383 // there is a device handle provided
1384 //
1385 UsbDevice = (PUSBDEVICE)Urb->UrbHeader.UsbdDeviceHandle;
1386
1387 //
1388 // return device address
1389 //
1390 return UsbDevice->GetDeviceAddress();
1391 }
1392
1393 //
1394 // no device handle provided, it is the host root bus
1395 //
1396 return 0;
1397 }
1398
1399 //----------------------------------------------------------------------------------------
1400 NTSTATUS
1401 CUSBRequest::BuildSetupPacket()
1402 {
1403 NTSTATUS Status;
1404
1405 //
1406 // allocate common buffer setup packet
1407 //
1408 Status = m_DmaManager->Allocate(sizeof(USB_DEFAULT_PIPE_SETUP_PACKET), (PVOID*)&m_DescriptorPacket, &m_DescriptorSetupPacket);
1409 if (!NT_SUCCESS(Status))
1410 {
1411 //
1412 // no memory
1413 //
1414 return Status;
1415 }
1416
1417 if (m_SetupPacket)
1418 {
1419 //
1420 // copy setup packet
1421 //
1422 RtlCopyMemory(m_DescriptorPacket, m_SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1423 }
1424 else
1425 {
1426 //
1427 // build setup packet from urb
1428 //
1429 Status = BuildSetupPacketFromURB();
1430 }
1431
1432 //
1433 // done
1434 //
1435 return Status;
1436 }
1437
1438
1439 NTSTATUS
1440 CUSBRequest::BuildSetupPacketFromURB()
1441 {
1442 PIO_STACK_LOCATION IoStack;
1443 PURB Urb;
1444 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
1445
1446 //
1447 // sanity checks
1448 //
1449 PC_ASSERT(m_Irp);
1450 PC_ASSERT(m_DescriptorPacket);
1451
1452 //
1453 // get stack location
1454 //
1455 IoStack = IoGetCurrentIrpStackLocation(m_Irp);
1456
1457 //
1458 // get urb
1459 //
1460 Urb = (PURB)IoStack->Parameters.Others.Argument1;
1461
1462 //
1463 // zero descriptor packet
1464 //
1465 RtlZeroMemory(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1466
1467
1468 switch (Urb->UrbHeader.Function)
1469 {
1470 /* CLEAR FEATURE */
1471 case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE:
1472 case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE:
1473 case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT:
1474 UNIMPLEMENTED;
1475 break;
1476
1477 /* GET CONFIG */
1478 case URB_FUNCTION_GET_CONFIGURATION:
1479 m_DescriptorPacket->bRequest = USB_REQUEST_GET_CONFIGURATION;
1480 m_DescriptorPacket->bmRequestType.B = 0x80;
1481 m_DescriptorPacket->wLength = 1;
1482 break;
1483
1484 /* GET DESCRIPTOR */
1485 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
1486 m_DescriptorPacket->bRequest = USB_REQUEST_GET_DESCRIPTOR;
1487 m_DescriptorPacket->wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
1488 m_DescriptorPacket->wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType;
1489 m_DescriptorPacket->wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
1490 m_DescriptorPacket->wLength = (USHORT)Urb->UrbControlDescriptorRequest.TransferBufferLength;
1491 m_DescriptorPacket->bmRequestType.B = 0x80;
1492 break;
1493
1494 /* GET INTERFACE */
1495 case URB_FUNCTION_GET_INTERFACE:
1496 m_DescriptorPacket->bRequest = USB_REQUEST_GET_CONFIGURATION;
1497 m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
1498 m_DescriptorPacket->bmRequestType.B = 0x80;
1499 m_DescriptorPacket->wLength = 1;
1500 break;
1501
1502 /* GET STATUS */
1503 case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
1504 m_DescriptorPacket->bRequest = USB_REQUEST_GET_STATUS;
1505 ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
1506 m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
1507 m_DescriptorPacket->bmRequestType.B = 0x80;
1508 m_DescriptorPacket->wLength = 2;
1509 break;
1510
1511 case URB_FUNCTION_GET_STATUS_FROM_INTERFACE:
1512 m_DescriptorPacket->bRequest = USB_REQUEST_GET_STATUS;
1513 ASSERT(Urb->UrbControlGetStatusRequest.Index != 0);
1514 m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
1515 m_DescriptorPacket->bmRequestType.B = 0x81;
1516 m_DescriptorPacket->wLength = 2;
1517 break;
1518
1519 case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT:
1520 m_DescriptorPacket->bRequest = USB_REQUEST_GET_STATUS;
1521 ASSERT(Urb->UrbControlGetStatusRequest.Index != 0);
1522 m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
1523 m_DescriptorPacket->bmRequestType.B = 0x82;
1524 m_DescriptorPacket->wLength = 2;
1525 break;
1526
1527 /* SET ADDRESS */
1528
1529 /* SET CONFIG */
1530 case URB_FUNCTION_SELECT_CONFIGURATION:
1531 m_DescriptorPacket->bRequest = USB_REQUEST_SET_CONFIGURATION;
1532 m_DescriptorPacket->wValue.W = Urb->UrbSelectConfiguration.ConfigurationDescriptor->bConfigurationValue;
1533 m_DescriptorPacket->wIndex.W = 0;
1534 m_DescriptorPacket->wLength = 0;
1535 m_DescriptorPacket->bmRequestType.B = 0x00;
1536 break;
1537
1538 /* SET DESCRIPTOR */
1539 case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE:
1540 case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE:
1541 case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT:
1542 UNIMPLEMENTED;
1543 break;
1544
1545 /* SET FEATURE */
1546 case URB_FUNCTION_SET_FEATURE_TO_DEVICE:
1547 m_DescriptorPacket->bRequest = USB_REQUEST_SET_FEATURE;
1548 ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
1549 m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
1550 m_DescriptorPacket->bmRequestType.B = 0x80;
1551 break;
1552
1553 case URB_FUNCTION_SET_FEATURE_TO_INTERFACE:
1554 m_DescriptorPacket->bRequest = USB_REQUEST_SET_FEATURE;
1555 ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
1556 m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
1557 m_DescriptorPacket->bmRequestType.B = 0x81;
1558 break;
1559
1560 case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT:
1561 m_DescriptorPacket->bRequest = USB_REQUEST_SET_FEATURE;
1562 ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
1563 m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
1564 m_DescriptorPacket->bmRequestType.B = 0x82;
1565 break;
1566
1567 /* SET INTERFACE*/
1568 case URB_FUNCTION_SELECT_INTERFACE:
1569 m_DescriptorPacket->bRequest = USB_REQUEST_SET_INTERFACE;
1570 m_DescriptorPacket->wValue.W = Urb->UrbSelectInterface.Interface.AlternateSetting;
1571 m_DescriptorPacket->wIndex.W = Urb->UrbSelectInterface.Interface.InterfaceNumber;
1572 m_DescriptorPacket->wLength = 0;
1573 m_DescriptorPacket->bmRequestType.B = 0x01;
1574 break;
1575
1576 /* SYNC FRAME */
1577 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
1578 UNIMPLEMENTED;
1579 break;
1580 default:
1581 UNIMPLEMENTED;
1582 break;
1583 }
1584
1585 return Status;
1586 }
1587
1588 //----------------------------------------------------------------------------------------
1589 VOID
1590 STDMETHODCALLTYPE
1591 CUSBRequest::GetResultStatus(
1592 OUT OPTIONAL NTSTATUS * NtStatusCode,
1593 OUT OPTIONAL PULONG UrbStatusCode)
1594 {
1595 //
1596 // sanity check
1597 //
1598 PC_ASSERT(m_CompletionEvent);
1599
1600 //
1601 // wait for the operation to complete
1602 //
1603 KeWaitForSingleObject(m_CompletionEvent, Executive, KernelMode, FALSE, NULL);
1604
1605 //
1606 // copy status
1607 //
1608 if (NtStatusCode)
1609 {
1610 *NtStatusCode = m_NtStatusCode;
1611 }
1612
1613 //
1614 // copy urb status
1615 //
1616 if (UrbStatusCode)
1617 {
1618 *UrbStatusCode = m_UrbStatusCode;
1619 }
1620
1621 }
1622
1623 //-----------------------------------------------------------------------------------------
1624 BOOLEAN
1625 STDMETHODCALLTYPE
1626 CUSBRequest::ShouldReleaseRequestAfterCompletion()
1627 {
1628 if (m_Irp)
1629 {
1630 //
1631 // the request is completed, release it
1632 //
1633 return TRUE;
1634 }
1635 else
1636 {
1637 //
1638 // created with an setup packet, don't release
1639 //
1640 return FALSE;
1641 }
1642 }
1643
1644 //-----------------------------------------------------------------------------------------
1645 VOID
1646 STDMETHODCALLTYPE
1647 CUSBRequest::FreeQueueHead(
1648 IN struct _QUEUE_HEAD * QueueHead)
1649 {
1650 PLIST_ENTRY Entry;
1651 PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
1652
1653 //
1654 // sanity checks
1655 //
1656 ASSERT(m_DmaManager);
1657 ASSERT(QueueHead);
1658 ASSERT(!IsListEmpty(&QueueHead->TransferDescriptorListHead));
1659
1660 do
1661 {
1662 //
1663 // get transfer descriptors
1664 //
1665 Entry = RemoveHeadList(&QueueHead->TransferDescriptorListHead);
1666 ASSERT(Entry);
1667
1668 //
1669 // obtain descriptor from entry
1670 //
1671 Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry);
1672 ASSERT(Descriptor);
1673
1674 //
1675 // add transfer count
1676 //
1677 m_TotalBytesTransferred += (Descriptor->TotalBytesToTransfer - Descriptor->Token.Bits.TotalBytesToTransfer);
1678 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);
1679
1680 //
1681 // release transfer descriptors
1682 //
1683 m_DmaManager->Release(Descriptor, sizeof(QUEUE_TRANSFER_DESCRIPTOR));
1684
1685 }while(!IsListEmpty(&QueueHead->TransferDescriptorListHead));
1686
1687 if (m_DescriptorPacket)
1688 {
1689 //
1690 // release packet descriptor
1691 //
1692 m_DmaManager->Release(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1693 }
1694
1695 //
1696 // release queue head
1697 //
1698 m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
1699
1700 //
1701 // nullify pointers
1702 //
1703 m_QueueHead = 0;
1704 m_DescriptorPacket = 0;
1705 }
1706
1707 //-----------------------------------------------------------------------------------------
1708 BOOLEAN
1709 STDMETHODCALLTYPE
1710 CUSBRequest::IsQueueHeadComplete(
1711 struct _QUEUE_HEAD * QueueHead)
1712 {
1713 PLIST_ENTRY Entry;
1714 PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
1715
1716 //
1717 // first check - is the queue head currently active
1718 //
1719 if (QueueHead->Token.Bits.Active)
1720 {
1721 //
1722 // queue head is active (currently processed)
1723 //
1724 return FALSE;
1725 }
1726
1727 if (QueueHead->Token.Bits.Halted)
1728 {
1729 //
1730 // error occured
1731 //
1732 DPRINT1("Found halted queue head %p\n", QueueHead);
1733 DumpQueueHead(QueueHead);
1734 //ASSERT(FALSE);
1735 return TRUE;
1736 }
1737
1738 //
1739 // loop list and see if there are any active descriptors
1740 //
1741 Entry = QueueHead->TransferDescriptorListHead.Flink;
1742 while(Entry != &QueueHead->TransferDescriptorListHead)
1743 {
1744 //
1745 // obtain descriptor from entry
1746 //
1747 Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry);
1748 ASSERT(Descriptor);
1749 if (Descriptor->Token.Bits.Active)
1750 {
1751 //
1752 // descriptor is still active
1753 //
1754 return FALSE;
1755 }
1756
1757 //
1758 // move to next entry
1759 //
1760 Entry = Entry->Flink;
1761 }
1762
1763 DPRINT("QueueHead %p Addr %x is complete\n", QueueHead, QueueHead->PhysicalAddr);
1764
1765 //
1766 // no active descriptors found, queue head is finished
1767 //
1768 return TRUE;
1769 }
1770
1771 //-----------------------------------------------------------------------------------------
1772 ULONG
1773 CUSBRequest::InternalCalculateTransferLength()
1774 {
1775 if (!m_Irp)
1776 {
1777 //
1778 // FIXME: get length for control request
1779 //
1780 return m_TransferBufferLength;
1781 }
1782
1783 //
1784 // sanity check
1785 //
1786 ASSERT(m_EndpointDescriptor);
1787 if (USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress))
1788 {
1789 //
1790 // bulk in request
1791 // HACK: Properly determine transfer length
1792 //
1793 return m_TransferBufferLength;//m_TotalBytesTransferred;
1794 }
1795
1796 //
1797 // bulk out transfer
1798 //
1799 return m_TransferBufferLength;
1800 }
1801
1802 USB_DEVICE_SPEED
1803 CUSBRequest::GetSpeed()
1804 {
1805 return m_Speed;
1806 }
1807
1808 UCHAR
1809 CUSBRequest::GetInterval()
1810 {
1811 if (!m_EndpointDescriptor)
1812 return 0;
1813
1814 return m_EndpointDescriptor->EndPointDescriptor.bInterval;
1815 }
1816
1817 //-----------------------------------------------------------------------------------------
1818 NTSTATUS
1819 NTAPI
1820 InternalCreateUSBRequest(
1821 PUSBREQUEST *OutRequest)
1822 {
1823 PUSBREQUEST This;
1824
1825 //
1826 // allocate requests
1827 //
1828 This = new(NonPagedPool, TAG_USBEHCI) CUSBRequest(0);
1829 if (!This)
1830 {
1831 //
1832 // failed to allocate
1833 //
1834 return STATUS_INSUFFICIENT_RESOURCES;
1835 }
1836
1837 //
1838 // add reference count
1839 //
1840 This->AddRef();
1841
1842 //
1843 // return result
1844 //
1845 *OutRequest = (PUSBREQUEST)This;
1846
1847 //
1848 // done
1849 //
1850 return STATUS_SUCCESS;
1851 }