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