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