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