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