ReactOS  0.4.14-dev-583-g2a1ba2c
usb_request.cpp
Go to the documentation of this file.
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/usbohci/usb_request.cpp
5  * PURPOSE: USB OHCI device driver.
6  * PROGRAMMERS:
7  * Michael Martin (michael.martin@reactos.org)
8  * Johannes Anderwald (johannes.anderwald@reactos.org)
9  */
10 
11 #include "usbohci.h"
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 class CUSBRequest : public IOHCIRequest
17 {
18 public:
20 
22  {
24  return m_Ref;
25  }
27  {
29 
30  if (!m_Ref)
31  {
32  delete this;
33  return 0;
34  }
35  return m_Ref;
36  }
37 
38  // IUSBRequest interface functions
41 
42  // local functions
57  VOID CheckError(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor);
59  NTSTATUS BuildTransferDescriptorChain(IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode, OUT POHCI_GENERAL_TD * OutFirstDescriptor, OUT POHCI_GENERAL_TD * OutLastDescriptor, OUT PULONG OutTransferBufferOffset);
60  VOID InitDescriptor(IN POHCI_GENERAL_TD CurrentDescriptor, IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode);
61 
62  // constructor / destructor
63  CUSBRequest(IUnknown *OuterUnknown);
64  virtual ~CUSBRequest();
65 
66 protected:
67  LONG m_Ref;
68 
69  //
70  // memory manager for allocating setup packet / queue head / transfer descriptors
71  //
73 
74  //
75  // caller provided irp packet containing URB request
76  //
77  PIRP m_Irp;
78 
79  //
80  // transfer buffer length
81  //
83 
84  //
85  // current transfer length
86  //
88 
89  //
90  // Total Transfer Length
91  //
93 
94  //
95  // transfer buffer MDL
96  //
98 
99  //
100  // caller provided setup packet
101  //
103 
104  //
105  // completion event for callers who initialized request with setup packet
106  //
108 
109  //
110  // device address for callers who initialized it with device address
111  //
113 
114  //
115  // store endpoint descriptor
116  //
118 
119  //
120  // allocated setup packet from the DMA pool
121  //
124 
125  //
126  // stores the result of the operation
127  //
130 
131  //
132  // device speed
133  //
135 
136  //
137  // store urb
138  //
140 
141  //
142  // base buffer
143  //
144  PVOID m_Base;
145 };
146 
147 //----------------------------------------------------------------------------------------
148 CUSBRequest::CUSBRequest(IUnknown *OuterUnknown) :
149  m_CompletionEvent(NULL)
150 {
151  UNREFERENCED_PARAMETER(OuterUnknown);
152 }
153 
154 //----------------------------------------------------------------------------------------
156 {
157  if (m_CompletionEvent != NULL)
158  {
160  }
161 }
162 
163 //----------------------------------------------------------------------------------------
164 NTSTATUS
167  IN REFIID refiid,
168  OUT PVOID* Output)
169 {
170  return STATUS_UNSUCCESSFUL;
171 }
172 
173 //----------------------------------------------------------------------------------------
174 NTSTATUS
176 CUSBRequest::InitializeWithSetupPacket(
177  IN PDMAMEMORYMANAGER DmaManager,
180  IN OPTIONAL struct _USB_ENDPOINT* EndpointDescriptor,
181  IN OUT ULONG TransferBufferLength,
182  IN OUT PMDL TransferBuffer)
183 {
184  //
185  // sanity checks
186  //
187  PC_ASSERT(DmaManager);
188  PC_ASSERT(SetupPacket);
189 
190  //
191  // initialize packet
192  //
193  m_DmaManager = DmaManager;
194  m_SetupPacket = SetupPacket;
195  m_TransferBufferLength = TransferBufferLength;
196  m_TransferBufferMDL = TransferBuffer;
197  m_DeviceAddress = Device->GetDeviceAddress();
198  m_EndpointDescriptor = EndpointDescriptor;
200  m_DeviceSpeed = Device->GetSpeed();
201 
202  //
203  // Set Length Completed to 0
204  //
206 
207  //
208  // allocate completion event
209  //
211  if (!m_CompletionEvent)
212  {
213  //
214  // failed to allocate completion event
215  //
217  }
218 
219  //
220  // initialize completion event
221  //
223 
224  //
225  // done
226  //
227  return STATUS_SUCCESS;
228 }
229 //----------------------------------------------------------------------------------------
230 NTSTATUS
232 CUSBRequest::InitializeWithIrp(
233  IN PDMAMEMORYMANAGER DmaManager,
234  IN struct IUSBDevice* Device,
235  IN OUT PIRP Irp)
236 {
237  PIO_STACK_LOCATION IoStack;
238 
239  //
240  // sanity checks
241  //
242  PC_ASSERT(DmaManager);
243  PC_ASSERT(Irp);
244 
245  m_DmaManager = DmaManager;
247 
248  //
249  // get current irp stack location
250  //
252 
253  //
254  // sanity check
255  //
257  PC_ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB);
258  PC_ASSERT(IoStack->Parameters.Others.Argument1 != 0);
259 
260  //
261  // get urb
262  //
263  m_Urb = (PURB)IoStack->Parameters.Others.Argument1;
264 
265  //
266  // store irp
267  //
268  m_Irp = Irp;
269 
270  //
271  // store speed
272  //
273  m_DeviceSpeed = Device->GetSpeed();
274 
275  //
276  // check function type
277  //
278  switch (m_Urb->UrbHeader.Function)
279  {
281  {
282  //
283  // there must be at least one packet
284  //
285  ASSERT(m_Urb->UrbIsochronousTransfer.NumberOfPackets);
286 
287  //
288  // is there data to be transferred
289  //
290  if (m_Urb->UrbIsochronousTransfer.TransferBufferLength)
291  {
292  //
293  // Check if there is a MDL
294  //
295  if (!m_Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
296  {
297  //
298  // sanity check
299  //
300  PC_ASSERT(m_Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
301 
302  //
303  // Create one using TransferBuffer
304  //
305  DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", m_Urb->UrbBulkOrInterruptTransfer.TransferBuffer, m_Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
307  m_Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
308  FALSE,
309  FALSE,
310  NULL);
311 
312  if (!m_TransferBufferMDL)
313  {
314  //
315  // failed to allocate mdl
316  //
318  }
319 
320  //
321  // build mdl for non paged pool
322  // FIXME: Does hub driver already do this when passing MDL?
323  //
325  }
326  else
327  {
328  //
329  // use provided mdl
330  //
331  m_TransferBufferMDL = m_Urb->UrbIsochronousTransfer.TransferBufferMDL;
332  }
333  }
334 
335  //
336  // save buffer length
337  //
338  m_TransferBufferLength = m_Urb->UrbIsochronousTransfer.TransferBufferLength;
339 
340  //
341  // Set Length Completed to 0
342  //
344 
345  //
346  // get endpoint descriptor
347  //
349 
350  //
351  // completed initialization
352  //
353  break;
354  }
355  //
356  // luckily those request have the same structure layout
357  //
361  {
362  //
363  // bulk interrupt transfer
364  //
365  if (m_Urb->UrbBulkOrInterruptTransfer.TransferBufferLength)
366  {
367  //
368  // Check if there is a MDL
369  //
370  if (!m_Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
371  {
372  //
373  // sanity check
374  //
375  PC_ASSERT(m_Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
376 
377  //
378  // Create one using TransferBuffer
379  //
380  DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", m_Urb->UrbBulkOrInterruptTransfer.TransferBuffer, m_Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
382  m_Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
383  FALSE,
384  FALSE,
385  NULL);
386 
387  if (!m_TransferBufferMDL)
388  {
389  //
390  // failed to allocate mdl
391  //
393  }
394 
395  //
396  // build mdl for non paged pool
397  // FIXME: Does hub driver already do this when passing MDL?
398  //
400 
401  //
402  // Keep that ehci created the MDL and needs to free it.
403  //
404  }
405  else
406  {
408  }
409 
410  //
411  // save buffer length
412  //
414 
415  //
416  // Set Length Completed to 0
417  //
419 
420  //
421  // get endpoint descriptor
422  //
424 
425  }
426  break;
427  }
428  default:
429  DPRINT1("URB Function: not supported %x\n", m_Urb->UrbHeader.Function);
430  PC_ASSERT(FALSE);
431  }
432 
433  //
434  // done
435  //
436  return STATUS_SUCCESS;
437 
438 }
439 
440 //----------------------------------------------------------------------------------------
441 BOOLEAN
443 CUSBRequest::IsRequestComplete()
444 {
445  //
446  // FIXME: check if request was split
447  //
448 
449  //
450  // Check if the transfer was completed, only valid for Bulk Transfers
451  //
453  && (GetTransferType() == USB_ENDPOINT_TYPE_BULK))
454  {
455  //
456  // Transfer not completed
457  //
458  return FALSE;
459  }
460  return TRUE;
461 }
462 //----------------------------------------------------------------------------------------
463 ULONG
465 CUSBRequest::GetTransferType()
466 {
467  //
468  // call internal implementation
469  //
470  return InternalGetTransferType();
471 }
472 
473 USHORT
475 {
477  {
478  if (m_DeviceSpeed == UsbLowSpeed)
479  {
480  //
481  // control pipes use 8 bytes packets
482  //
483  return 8;
484  }
485  else
486  {
487  //
488  // must be full speed
489  //
491  return 64;
492  }
493  }
494 
495  ASSERT(m_Irp);
497 
498  //
499  // return max packet size
500  //
502 }
503 
504 UCHAR
506 CUSBRequest::GetInterval()
507 {
510 
511  //
512  // return interrupt interval
513  //
515 }
516 
517 UCHAR
519 {
521  {
522  //
523  // control request
524  //
525  return 0;
526  }
527 
528  ASSERT(m_Irp);
530 
531  //
532  // endpoint number is between 1-15
533  //
535 }
536 
537 //----------------------------------------------------------------------------------------
538 ULONG
540 {
541  ULONG TransferType;
542 
543  //
544  // check if an irp is provided
545  //
546  if (m_Irp)
547  {
549 
550  //
551  // end point is defined in the low byte of bmAttributes
552  //
554  }
555  else
556  {
557  //
558  // initialized with setup packet, must be a control transfer
559  //
560  TransferType = USB_ENDPOINT_TYPE_CONTROL;
561  }
562 
563  //
564  // done
565  //
566  return TransferType;
567 }
568 
569 UCHAR
571 {
573  {
574  //
575  // end point direction is highest bit in bEndpointAddress
576  //
578  }
579  else
580  {
581  //
582  // request arrives on the control pipe, extract direction from setup packet
583  //
585  return (m_SetupPacket->bmRequestType.B >> 7);
586  }
587 }
588 
589 //----------------------------------------------------------------------------------------
590 UCHAR
593 {
594  PIO_STACK_LOCATION IoStack;
595  PURB Urb;
596  PUSBDEVICE UsbDevice;
597 
598  //
599  // check if there is an irp provided
600  //
601  if (!m_Irp)
602  {
603  //
604  // used provided address
605  //
606  return m_DeviceAddress;
607  }
608 
609  //
610  // get current stack location
611  //
613 
614  //
615  // get contained urb
616  //
617  Urb = (PURB)IoStack->Parameters.Others.Argument1;
618 
619  //
620  // check if there is a pipe handle provided
621  //
622  if (Urb->UrbHeader.UsbdDeviceHandle)
623  {
624  //
625  // there is a device handle provided
626  //
627  UsbDevice = (PUSBDEVICE)Urb->UrbHeader.UsbdDeviceHandle;
628 
629  //
630  // return device address
631  //
632  return UsbDevice->GetDeviceAddress();
633  }
634 
635  //
636  // no device handle provided, it is the host root bus
637  //
638  return 0;
639 }
640 
641 VOID
644 {
645  if (Descriptor->BufferSize)
646  {
647  //
648  // free buffer
649  //
650  m_DmaManager->Release(Descriptor->BufferLogical, Descriptor->BufferSize);
651  }
652 
653  //
654  // release descriptor
655  //
656  m_DmaManager->Release(Descriptor, sizeof(OHCI_GENERAL_TD));
657 
658 }
659 
660 //----------------------------------------------------------------------------------------
661 NTSTATUS
663  POHCI_ISO_TD* OutDescriptor,
664  ULONG FrameCount)
665 {
667  PHYSICAL_ADDRESS DescriptorAddress;
669 
670  //
671  // allocate transfer descriptor
672  //
673  Status = m_DmaManager->Allocate(sizeof(OHCI_ISO_TD), (PVOID*)&Descriptor, &DescriptorAddress);
674  if (!NT_SUCCESS(Status))
675  {
676  //
677  // no memory
678  //
679  return Status;
680  }
681 
682  //
683  // initialize descriptor, hardware part
684  //
685  Descriptor->Flags = OHCI_ITD_SET_FRAME_COUNT(FrameCount) | OHCI_ITD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE);// | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED);
686  Descriptor->BufferPhysical = 0;
687  Descriptor->NextPhysicalDescriptor = 0;
688  Descriptor->LastPhysicalByteAddress = 0;
689 
690  //
691  // software part
692  //
693  Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart;
694  Descriptor->NextLogicalDescriptor = 0;
695 
696  //
697  // store result
698  //
699  *OutDescriptor = Descriptor;
700 
701  //
702  // done
703  //
704  return STATUS_SUCCESS;
705 }
706 
707 NTSTATUS
709  POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
710 {
711  POHCI_ISO_TD FirstDescriptor = NULL, PreviousDescriptor = NULL, CurrentDescriptor = NULL;
712  POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
713  ULONG Index = 0, SubIndex, NumberOfPackets, PageOffset, Page;
715  PVOID Buffer;
716  PIO_STACK_LOCATION IoStack;
717  PURB Urb;
719 
720  //
721  // get current irp stack location
722  //
724 
725  //
726  // sanity check
727  //
729  PC_ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB);
730  PC_ASSERT(IoStack->Parameters.Others.Argument1 != 0);
731 
732  //
733  // get urb
734  //
735  Urb = (PURB)IoStack->Parameters.Others.Argument1;
736  ASSERT(Urb);
737 
738  //
739  // allocate endpoint descriptor
740  //
741  Status = AllocateEndpointDescriptor(&EndpointDescriptor);
742  if (!NT_SUCCESS(Status))
743  {
744  //
745  // failed to create setup descriptor
746  //
747  ASSERT(FALSE);
748  return Status;
749  }
750 
751  //
752  // get buffer
753  //
755  ASSERT(Buffer);
756 
757  //
758  // FIXME: support requests which spans several pages
759  //
761 
764 
765 
766  while(Index < Urb->UrbIsochronousTransfer.NumberOfPackets)
767  {
768  //
769  // get number of packets remaining
770  //
772  //
773  // allocate iso descriptor
774  //
776  if (!NT_SUCCESS(Status))
777  {
778  //
779  // FIXME: cleanup
780  // failed to allocate descriptor
781  //
782  ASSERT(FALSE);
783  return Status;
784  }
785 
786  //
787  // get physical page (HACK)
788  //
789  *(volatile char *)Buffer;
791 
792  //
793  // get page offset
794  //
795  PageOffset = BYTE_OFFSET(Page);
796 
797  //
798  // initialize descriptor
799  //
800  CurrentDescriptor->BufferPhysical = Page - PageOffset;
801 
802  for(SubIndex = 0; SubIndex < NumberOfPackets; SubIndex++)
803  {
804  //
805  // store buffer offset
806  //
807  CurrentDescriptor->Offset[SubIndex] = Urb->UrbIsochronousTransfer.IsoPacket[Index+SubIndex].Offset + PageOffset;
808  DPRINT("Index %lu PacketOffset %lu FinalOffset %lu\n", SubIndex+Index, Urb->UrbIsochronousTransfer.IsoPacket[Index+SubIndex].Offset, CurrentDescriptor->Offset[SubIndex]);
809  }
810 
811  //
812  // increment packet offset
813  //
815 
816  //
817  // check if this is the last descriptor
818  //
819  if (Index == Urb->UrbIsochronousTransfer.NumberOfPackets)
820  {
821  //
822  // end of transfer
823  //
824  CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + PageOffset + m_TransferBufferLength - 1;
825  }
826  else
827  {
828  //
829  // use start address of next packet - 1
830  //
831  CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + PageOffset + Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset - 1;
832  }
833 
834  //
835  // is there a previous descriptor
836  //
837  if (PreviousDescriptor)
838  {
839  //
840  // link descriptors
841  //
842  PreviousDescriptor->NextLogicalDescriptor = CurrentDescriptor;
843  PreviousDescriptor->NextPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart;
844  }
845  else
846  {
847  //
848  // first descriptor
849  //
850  FirstDescriptor = CurrentDescriptor;
851  }
852 
853  //
854  // store as previous descriptor
855  //
856  PreviousDescriptor = CurrentDescriptor;
857  DPRINT("Current Descriptor %p Logical %lx StartAddress %x EndAddress %x\n", CurrentDescriptor, CurrentDescriptor->PhysicalAddress.LowPart, CurrentDescriptor->BufferPhysical, CurrentDescriptor->LastPhysicalByteAddress);
858 
859  //
860  // fire interrupt as soon transfer is finished
861  //
862  CurrentDescriptor->Flags |= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
863  }
864 
865  //
866  // clear interrupt mask for last transfer descriptor
867  //
868  CurrentDescriptor->Flags &= ~OHCI_TD_INTERRUPT_MASK;
869 
870  //
871  // fire interrupt as soon transfer is finished
872  //
873  CurrentDescriptor->Flags |= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
874 
875  //
876  // set isochronous type
877  //
878  EndpointDescriptor->Flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
879 
880  //
881  // now link descriptor to endpoint
882  //
883  EndpointDescriptor->HeadPhysicalDescriptor = FirstDescriptor->PhysicalAddress.LowPart;
884  EndpointDescriptor->TailPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart;
885  EndpointDescriptor->HeadLogicalDescriptor = FirstDescriptor;
886 
887  //
888  // store result
889  //
890  *OutEndpointDescriptor = EndpointDescriptor;
891 
892  //
893  // done
894  //
895  return STATUS_SUCCESS;
896 }
897 
898 //----------------------------------------------------------------------------------------
899 NTSTATUS
901  POHCI_GENERAL_TD* OutDescriptor,
903 {
905  PHYSICAL_ADDRESS DescriptorAddress;
907 
908  //
909  // allocate transfer descriptor
910  //
911  Status = m_DmaManager->Allocate(sizeof(OHCI_GENERAL_TD), (PVOID*)&Descriptor, &DescriptorAddress);
912  if (!NT_SUCCESS(Status))
913  {
914  //
915  // no memory
916  //
917  return Status;
918  }
919 
920  //
921  // initialize descriptor, hardware part
922  //
923  Descriptor->Flags = 0;
924  Descriptor->BufferPhysical = 0;
925  Descriptor->NextPhysicalDescriptor = 0;
926  Descriptor->LastPhysicalByteAddress = 0;
927 
928  //
929  // software part
930  //
931  Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart;
932  Descriptor->BufferSize = BufferSize;
933 
934  if (BufferSize > 0)
935  {
936  //
937  // allocate buffer from dma
938  //
939  Status = m_DmaManager->Allocate(BufferSize, &Descriptor->BufferLogical, &DescriptorAddress);
940  if (!NT_SUCCESS(Status))
941  {
942  //
943  // no memory
944  //
945  m_DmaManager->Release(Descriptor, sizeof(OHCI_GENERAL_TD));
946  return Status;
947  }
948 
949  //
950  // set physical address of buffer
951  //
952  Descriptor->BufferPhysical = DescriptorAddress.LowPart;
953  Descriptor->LastPhysicalByteAddress = Descriptor->BufferPhysical + BufferSize - 1;
954  }
955 
956  //
957  // store result
958  //
959  *OutDescriptor = Descriptor;
960 
961  //
962  // done
963  //
964  return STATUS_SUCCESS;
965 }
966 
967 NTSTATUS
969  OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor)
970 {
972  PHYSICAL_ADDRESS DescriptorAddress;
974 
975  //
976  // allocate descriptor
977  //
978  Status = m_DmaManager->Allocate(sizeof(OHCI_ENDPOINT_DESCRIPTOR), (PVOID*)&Descriptor, &DescriptorAddress);
979  if (!NT_SUCCESS(Status))
980  {
981  //
982  // failed to allocate descriptor
983  //
984  return Status;
985  }
986 
987  //
988  // initialize descriptor
989  //
991 
992  //
993  // append device address and endpoint number
994  //
998 
999  DPRINT("Flags %x DeviceAddress %x EndpointAddress %x PacketSize %lu\n", Descriptor->Flags, GetDeviceAddress(), GetEndpointAddress(), GetMaxPacketSize());
1000 
1001  //
1002  // is there an endpoint descriptor
1003  //
1005  {
1006  //
1007  // check direction
1008  //
1010  {
1011  //
1012  // direction out
1013  //
1015  }
1016  else
1017  {
1018  //
1019  // direction in
1020  //
1022  }
1023  }
1024  else
1025  {
1026  //
1027  // get it from transfer descriptor
1028  //
1030  }
1031 
1032  //
1033  // set type
1034  //
1035  if (m_DeviceSpeed == UsbFullSpeed)
1036  {
1037  //
1038  // device is full speed
1039  //
1041  }
1042  else if (m_DeviceSpeed == UsbLowSpeed)
1043  {
1044  //
1045  // device is full speed
1046  //
1048  }
1049  else
1050  {
1051  //
1052  // error
1053  //
1054  ASSERT(FALSE);
1055  }
1056 
1057  Descriptor->HeadPhysicalDescriptor = 0;
1058  Descriptor->NextPhysicalEndpoint = 0;
1059  Descriptor->TailPhysicalDescriptor = 0;
1060  Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart;
1061 
1062  //
1063  // store result
1064  //
1065  *OutDescriptor = Descriptor;
1066 
1067  //
1068  // done
1069  //
1070  return STATUS_SUCCESS;
1071 }
1072 
1073 VOID
1075  IN POHCI_GENERAL_TD CurrentDescriptor,
1076  IN PVOID TransferBuffer,
1077  IN ULONG TransferBufferLength,
1078  IN UCHAR PidDirection)
1079 {
1080  ULONG Direction;
1081 
1082  if (PidDirection)
1083  {
1084  //
1085  // input direction
1086  //
1088  }
1089  else
1090  {
1091  //
1092  // output direction
1093  //
1095  }
1096 
1097 
1098  //
1099  // initialize descriptor
1100  //
1102 
1103  //
1104  // store physical address of buffer
1105  //
1106  CurrentDescriptor->BufferPhysical = MmGetPhysicalAddress(TransferBuffer).LowPart;
1107  CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + TransferBufferLength - 1;
1108 
1109  DPRINT("CurrentDescriptor %p Addr %x TransferBufferLength %lu\n", CurrentDescriptor, CurrentDescriptor->PhysicalAddress.LowPart, TransferBufferLength);
1110 }
1111 
1112 NTSTATUS
1114  IN PVOID TransferBuffer,
1115  IN ULONG TransferBufferLength,
1116  IN UCHAR PidDirection,
1117  OUT POHCI_GENERAL_TD * OutFirstDescriptor,
1118  OUT POHCI_GENERAL_TD * OutLastDescriptor,
1119  OUT PULONG OutTransferBufferOffset)
1120 {
1121  POHCI_GENERAL_TD FirstDescriptor = NULL, CurrentDescriptor, LastDescriptor = NULL;
1122  NTSTATUS Status;
1123  ULONG MaxLengthInPage, TransferBufferOffset = 0;
1124  ULONG MaxPacketSize = 0, TransferSize, CurrentSize;
1125 
1126  //
1127  // for now use one page as maximum size
1128  //
1129  MaxPacketSize = PAGE_SIZE;
1130 
1131  do
1132  {
1133  //
1134  // allocate transfer descriptor
1135  //
1136  Status = CreateGeneralTransferDescriptor(&CurrentDescriptor, 0);
1137  if (!NT_SUCCESS(Status))
1138  {
1139  //
1140  // failed to allocate transfer descriptor
1141  //
1143  }
1144 
1145  if (MaxPacketSize)
1146  {
1147  //
1148  // transfer size is minimum available buffer or endpoint size
1149  //
1150  TransferSize = min(TransferBufferLength - TransferBufferOffset, MaxPacketSize);
1151  }
1152  else
1153  {
1154  //
1155  // use available buffer
1156  //
1157  TransferSize = TransferBufferLength - TransferBufferOffset;
1158  }
1159 
1160  //
1161  // get page offset
1162  //
1163  MaxLengthInPage = PAGE_SIZE - BYTE_OFFSET(TransferBuffer);
1164 
1165  //
1166  // get minimum from current page size
1167  //
1168  CurrentSize = min(TransferSize, MaxLengthInPage);
1169  ASSERT(CurrentSize);
1170 
1171  //
1172  // now init the descriptor
1173  //
1174  InitDescriptor(CurrentDescriptor,
1175  (PVOID)((ULONG_PTR)TransferBuffer + TransferBufferOffset),
1176  CurrentSize,
1177  PidDirection);
1178 
1179  //
1180  // adjust offset
1181  //
1182  TransferBufferOffset += CurrentSize;
1183 
1184  //
1185  // is there a previous descriptor
1186  //
1187  if (LastDescriptor)
1188  {
1189  //
1190  // link descriptors
1191  //
1192  LastDescriptor->NextLogicalDescriptor = (PVOID)CurrentDescriptor;
1193  LastDescriptor->NextPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart;
1194  }
1195  else
1196  {
1197  //
1198  // it is the first descriptor
1199  //
1200  FirstDescriptor = CurrentDescriptor;
1201  }
1202 
1203  if(TransferBufferLength == TransferBufferOffset)
1204  {
1205  //
1206  // end reached
1207  //
1208  break;
1209  }
1210 
1211  }while(TRUE);
1212 
1213  if (OutFirstDescriptor)
1214  {
1215  //
1216  // store first descriptor
1217  //
1218  *OutFirstDescriptor = FirstDescriptor;
1219  }
1220 
1221  if (OutLastDescriptor)
1222  {
1223  //
1224  // store last descriptor
1225  //
1226  *OutLastDescriptor = CurrentDescriptor;
1227  }
1228 
1229  if (OutTransferBufferOffset)
1230  {
1231  //
1232  // store offset
1233  //
1234  *OutTransferBufferOffset = TransferBufferOffset;
1235  }
1236 
1237  //
1238  // done
1239  //
1240  return STATUS_SUCCESS;
1241 }
1242 
1243 
1244 NTSTATUS
1246  POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
1247 {
1248  POHCI_GENERAL_TD FirstDescriptor, LastDescriptor;
1249  POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
1250  NTSTATUS Status;
1251  PVOID Base;
1252  ULONG ChainDescriptorLength;
1253 
1254  //
1255  // sanity check
1256  //
1258 
1259  //
1260  // allocate endpoint descriptor
1261  //
1262  Status = AllocateEndpointDescriptor(&EndpointDescriptor);
1263  if (!NT_SUCCESS(Status))
1264  {
1265  //
1266  // failed to create setup descriptor
1267  //
1268  return Status;
1269  }
1270 
1272 
1273  if (m_Base == NULL)
1274  {
1275  //
1276  // get buffer
1277  //
1279  }
1280 
1281  //
1282  // Increase the size of last transfer, 0 in case this is the first
1283  //
1285 
1286  //
1287  // sanity checks
1288  //
1290  ASSERT(Base);
1291 
1292  //
1293  // use 2 * PAGE_SIZE at max for each new request
1294  //
1296  DPRINT("m_TransferBufferLength %lu m_TransferBufferLengthCompleted %lu DataToggle %x\n", m_TransferBufferLength, m_TransferBufferLengthCompleted, m_EndpointDescriptor->DataToggle);
1297 
1298  //
1299  // build bulk transfer descriptor chain
1300  //
1302  MaxTransferLength,
1304  &FirstDescriptor,
1305  &LastDescriptor,
1306  &ChainDescriptorLength);
1307  if (!NT_SUCCESS(Status))
1308  {
1309  //
1310  // failed to build transfer descriptor chain
1311  //
1312  m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1313  return Status;
1314  }
1315 
1316  //
1317  // move to next offset
1318  //
1319  m_TransferBufferLengthCompleted += ChainDescriptorLength;
1320 
1321  //
1322  // first descriptor has no carry bit
1323  //
1324  FirstDescriptor->Flags &= ~OHCI_TD_TOGGLE_CARRY;
1325 
1326  //
1327  // apply data toggle
1328  //
1330 
1331  //
1332  // clear interrupt mask for last transfer descriptor
1333  //
1334  LastDescriptor->Flags &= ~OHCI_TD_INTERRUPT_MASK;
1335 
1336 
1337  //
1338  // fire interrupt as soon transfer is finished
1339  //
1341 
1342  //
1343  // now link descriptor to endpoint
1344  //
1345  EndpointDescriptor->HeadPhysicalDescriptor = FirstDescriptor->PhysicalAddress.LowPart;
1346  EndpointDescriptor->TailPhysicalDescriptor = (FirstDescriptor == LastDescriptor ? 0 : LastDescriptor->PhysicalAddress.LowPart);
1347  EndpointDescriptor->HeadLogicalDescriptor = FirstDescriptor;
1348 
1349  //
1350  // dump descriptor list
1351  //
1352  //DumpEndpointDescriptor(EndpointDescriptor);
1353 
1354  //
1355  // store result
1356  //
1357  *OutEndpointDescriptor = EndpointDescriptor;
1358 
1359  //
1360  // done
1361  //
1362  return STATUS_SUCCESS;
1363 }
1364 
1365 VOID
1368 {
1369  ULONG Count = 0;
1370  POHCI_GENERAL_TD GeneralDescriptor;
1371 
1372  DPRINT1("EndpointDescriptor %p Addr %x\n", Descriptor, Descriptor->PhysicalAddress.LowPart);
1373  DPRINT1("EndpointDescriptor HeadPhysicalDescriptor %x HeadLogicalDescriptor %p\n", Descriptor->HeadPhysicalDescriptor, Descriptor->HeadLogicalDescriptor);
1374  DPRINT1("EndpointDescriptor TailPhysicalDescriptor %x\n", Descriptor->TailPhysicalDescriptor);
1375  DPRINT1("EndpointDescriptor NextDescriptor %p\n", Descriptor->NextDescriptor);
1376  DPRINT1("EndpointDescriptor NextPhysicalEndpoint %x\n", Descriptor->NextPhysicalEndpoint);
1377  DPRINT1("EndpointDescriptor Flags %x\n", Descriptor->Flags);
1378 
1379 
1380  GeneralDescriptor = (POHCI_GENERAL_TD)Descriptor->HeadLogicalDescriptor;
1381  while(GeneralDescriptor)
1382  {
1383  DPRINT1("Descriptor %lu Address %p Addr %x\n", Count, GeneralDescriptor, GeneralDescriptor->PhysicalAddress);
1384  DPRINT1("Descriptor %lu BufferLogical %p BufferPhysical %x\n", Count, GeneralDescriptor->BufferLogical, GeneralDescriptor->BufferPhysical);
1385  DPRINT1("Descriptor %lu BufferSize %lu\n", Count, GeneralDescriptor->BufferSize);
1386  DPRINT1("Descriptor %lu LastPhysicalByteAddress %x\n", Count, GeneralDescriptor->LastPhysicalByteAddress);
1387  DPRINT1("Descriptor %lu Flags %x\n", Count, GeneralDescriptor->Flags);
1388  DPRINT1("Descriptor %lu NextLogicalDescriptor %p NextPhysicalDescriptor %x\n", Count, GeneralDescriptor->NextLogicalDescriptor, GeneralDescriptor->NextPhysicalDescriptor);
1389 
1390  Count++;
1391  GeneralDescriptor = (POHCI_GENERAL_TD)GeneralDescriptor->NextLogicalDescriptor;
1392  }
1393 }
1394 
1395 NTSTATUS
1397  POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
1398 {
1399  POHCI_GENERAL_TD SetupDescriptor, StatusDescriptor, DataDescriptor = NULL, LastDescriptor;
1400  POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
1401  NTSTATUS Status;
1402 
1403  //
1404  // allocate endpoint descriptor
1405  //
1406  Status = AllocateEndpointDescriptor(&EndpointDescriptor);
1407  if (!NT_SUCCESS(Status))
1408  {
1409  //
1410  // failed to create setup descriptor
1411  //
1412  return Status;
1413  }
1414 
1415  //
1416  // first allocate setup descriptor
1417  //
1419  if (!NT_SUCCESS(Status))
1420  {
1421  //
1422  // failed to create setup descriptor
1423  //
1424  m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1425  return Status;
1426  }
1427 
1428  //
1429  // now create the status descriptor
1430  //
1431  Status = CreateGeneralTransferDescriptor(&StatusDescriptor, 0);
1432  if (!NT_SUCCESS(Status))
1433  {
1434  //
1435  // failed to create status descriptor
1436  //
1437  FreeDescriptor(SetupDescriptor);
1438  m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1439  return Status;
1440  }
1441 
1442  //
1443  // finally create the last descriptor
1444  //
1445  Status = CreateGeneralTransferDescriptor(&LastDescriptor, 0);
1446  if (!NT_SUCCESS(Status))
1447  {
1448  //
1449  // failed to create status descriptor
1450  //
1451  FreeDescriptor(SetupDescriptor);
1452  FreeDescriptor(StatusDescriptor);
1453  m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1454  return Status;
1455  }
1456 
1457  //
1458  // initialize setup descriptor
1459  //
1461 
1462  //
1463  // initialize status descriptor
1464  //
1466 
1467  if (m_SetupPacket)
1468  {
1469  //
1470  // copy setup packet
1471  //
1473  }
1474  else
1475  {
1476  //
1477  // generate setup packet from urb
1478  //
1479  ASSERT(FALSE);
1480  }
1481 
1483  {
1484  //
1485  // FIXME: support more than one data descriptor
1486  //
1488 
1489  //
1490  // now create the data descriptor
1491  //
1492  Status = CreateGeneralTransferDescriptor(&DataDescriptor, 0);
1493  if (!NT_SUCCESS(Status))
1494  {
1495  //
1496  // failed to create status descriptor
1497  //
1498  m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1499  FreeDescriptor(SetupDescriptor);
1500  FreeDescriptor(StatusDescriptor);
1501  return Status;
1502  }
1503 
1504  //
1505  // initialize data descriptor
1506  //
1508 
1509  //
1510  // setup pid direction
1511  //
1513 
1514  //
1515  // use short packets
1516  //
1517  DataDescriptor->Flags |= OHCI_TD_BUFFER_ROUNDING;
1518 
1519  //
1520  // store physical address of buffer
1521  //
1523  DataDescriptor->LastPhysicalByteAddress = DataDescriptor->BufferPhysical + m_TransferBufferLength - 1;
1524 
1525  //
1526  // flip status pid direction
1527  //
1529 
1530  //
1531  // link setup descriptor to data descriptor
1532  //
1533  SetupDescriptor->NextPhysicalDescriptor = DataDescriptor->PhysicalAddress.LowPart;
1534  SetupDescriptor->NextLogicalDescriptor = DataDescriptor;
1535 
1536  //
1537  // link data descriptor to status descriptor
1538  // FIXME: check if there are more data descriptors
1539  //
1540  DataDescriptor->NextPhysicalDescriptor = StatusDescriptor->PhysicalAddress.LowPart;
1541  DataDescriptor->NextLogicalDescriptor = StatusDescriptor;
1542 
1543  //
1544  // link status descriptor to last descriptor
1545  //
1546  StatusDescriptor->NextPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart;
1547  StatusDescriptor->NextLogicalDescriptor = LastDescriptor;
1548  }
1549  else
1550  {
1551  //
1552  // status descriptor is always in
1553  //
1554  StatusDescriptor->Flags |= OHCI_TD_DIRECTION_PID_IN;
1555 
1556  //
1557  // link setup descriptor to status descriptor
1558  //
1559  SetupDescriptor->NextPhysicalDescriptor = StatusDescriptor->PhysicalAddress.LowPart;
1560  SetupDescriptor->NextLogicalDescriptor = StatusDescriptor;
1561  //
1562  // link status descriptor to last descriptor
1563  //
1564  StatusDescriptor->NextPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart;
1565  StatusDescriptor->NextLogicalDescriptor = LastDescriptor;
1566  }
1567 
1568  //
1569  // now link descriptor to endpoint
1570  //
1571  EndpointDescriptor->HeadPhysicalDescriptor = SetupDescriptor->PhysicalAddress.LowPart;
1572  EndpointDescriptor->TailPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart;
1573  EndpointDescriptor->HeadLogicalDescriptor = SetupDescriptor;
1574 
1575  //
1576  // store result
1577  //
1578  *OutEndpointDescriptor = EndpointDescriptor;
1579 
1580  //
1581  // dump descriptor
1582  //
1583  //DumpEndpointDescriptor(EndpointDescriptor);
1584 
1585  //
1586  // done
1587  //
1588  return STATUS_SUCCESS;
1589 }
1590 
1591 //----------------------------------------------------------------------------------------
1592 NTSTATUS
1594 CUSBRequest::GetEndpointDescriptor(
1595  struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor)
1596 {
1597  ULONG TransferType;
1598  NTSTATUS Status;
1599 
1600 
1601  //
1602  // get transfer type
1603  //
1604  TransferType = InternalGetTransferType();
1605 
1606  //
1607  // build request depending on type
1608  //
1609  switch(TransferType)
1610  {
1613  break;
1616  Status = BuildBulkInterruptEndpoint(OutDescriptor);
1617  break;
1620  break;
1621  default:
1622  PC_ASSERT(FALSE);
1624  break;
1625  }
1626 
1627 
1628 
1629  if (NT_SUCCESS(Status))
1630  {
1631  //
1632  // store queue head
1633  //
1634  //m_QueueHead = *OutDescriptor;
1635 
1636  //
1637  // store request object
1638  //
1639  (*OutDescriptor)->Request = PVOID(this);
1640  }
1641 
1642  //
1643  // done
1644  //
1645  return Status;
1646 }
1647 
1648 //----------------------------------------------------------------------------------------
1649 VOID
1651 CUSBRequest::GetResultStatus(
1652  OUT OPTIONAL NTSTATUS * NtStatusCode,
1653  OUT OPTIONAL PULONG UrbStatusCode)
1654 {
1655  //
1656  // sanity check
1657  //
1659 
1660  //
1661  // wait for the operation to complete
1662  //
1664 
1665  //
1666  // copy status
1667  //
1668  if (NtStatusCode)
1669  {
1670  *NtStatusCode = m_NtStatusCode;
1671  }
1672 
1673  //
1674  // copy urb status
1675  //
1676  if (UrbStatusCode)
1677  {
1678  *UrbStatusCode = m_UrbStatusCode;
1679  }
1680 
1681 }
1682 
1683 VOID
1685 CUSBRequest::FreeEndpointDescriptor(
1686  struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
1687 {
1688  POHCI_GENERAL_TD TransferDescriptor, NextTransferDescriptor;
1689  POHCI_ISO_TD IsoTransferDescriptor, IsoNextTransferDescriptor;
1690  ULONG Index, PacketCount;
1691 
1692  DPRINT("CUSBRequest::FreeEndpointDescriptor EndpointDescriptor %p Logical %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart);
1693 
1694  //
1695  // check for errors
1696  //
1697  CheckError(OutDescriptor);
1698 
1699 
1700  if (OutDescriptor->Flags & OHCI_ENDPOINT_ISOCHRONOUS_FORMAT)
1701  {
1702  //
1703  // get first iso transfer descriptor
1704  //
1705  IsoTransferDescriptor = (POHCI_ISO_TD)OutDescriptor->HeadLogicalDescriptor;
1706 
1707  //
1708  // release endpoint descriptor
1709  //
1710  m_DmaManager->Release(OutDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1711 
1712  while(IsoTransferDescriptor)
1713  {
1714  //
1715  // get next
1716  //
1717  IsoNextTransferDescriptor = IsoTransferDescriptor->NextLogicalDescriptor;
1718 
1719  //
1720  // get packet count
1721  //
1722  PacketCount = OHCI_ITD_GET_FRAME_COUNT(IsoTransferDescriptor->Flags);
1723 
1724  DPRINT("CUSBRequest::FreeEndpointDescriptor Descriptor %p Logical %x Buffer Physical %x EndAddress %x PacketCount %lu\n", IsoTransferDescriptor, IsoTransferDescriptor->PhysicalAddress.LowPart, IsoTransferDescriptor->BufferPhysical, IsoTransferDescriptor->LastPhysicalByteAddress, PacketCount);
1725 
1726  for(Index = 0; Index < PacketCount; Index++)
1727  {
1728  DPRINT("PSW Index %lu Value %x\n", Index, IsoTransferDescriptor->Offset[Index]);
1729  }
1730 
1731  //
1732  // release descriptor
1733  //
1734  m_DmaManager->Release(IsoTransferDescriptor, sizeof(OHCI_ISO_TD));
1735 
1736  //
1737  // move to next
1738  //
1739  IsoTransferDescriptor = IsoNextTransferDescriptor;
1740  }
1741  }
1742  else
1743  {
1744  //
1745  // get first general transfer descriptor
1746  //
1747  TransferDescriptor = (POHCI_GENERAL_TD)OutDescriptor->HeadLogicalDescriptor;
1748 
1749  //
1750  // release endpoint descriptor
1751  //
1752  m_DmaManager->Release(OutDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
1753 
1754  while(TransferDescriptor)
1755  {
1756  //
1757  // get next
1758  //
1759  NextTransferDescriptor = (POHCI_GENERAL_TD)TransferDescriptor->NextLogicalDescriptor;
1760 
1761  //
1762  // is there a buffer associated
1763  //
1764  if (TransferDescriptor->BufferSize)
1765  {
1766  //
1767  // release buffer
1768  //
1769  m_DmaManager->Release(TransferDescriptor->BufferLogical, TransferDescriptor->BufferSize);
1770  }
1771 
1772  DPRINT("CUSBRequest::FreeEndpointDescriptor Descriptor %p Logical %x Buffer Physical %x EndAddress %x\n", TransferDescriptor, TransferDescriptor->PhysicalAddress.LowPart, TransferDescriptor->BufferPhysical, TransferDescriptor->LastPhysicalByteAddress);
1773 
1774  //
1775  // release descriptor
1776  //
1777  m_DmaManager->Release(TransferDescriptor, sizeof(OHCI_GENERAL_TD));
1778 
1779  //
1780  // move to next
1781  //
1782  TransferDescriptor = NextTransferDescriptor;
1783  }
1784  }
1785 
1786 }
1787 
1788 VOID
1790  struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
1791 {
1792  POHCI_GENERAL_TD TransferDescriptor;
1793  ULONG ConditionCode;
1794  PURB Urb;
1795  PIO_STACK_LOCATION IoStack;
1796 
1797 
1798  //
1799  // set status code
1800  //
1803 
1804 
1805  if (OutDescriptor->Flags & OHCI_ENDPOINT_ISOCHRONOUS_FORMAT)
1806  {
1807  //
1808  // FIXME: handle isochronous support
1809  //
1810  ASSERT(FALSE);
1811  }
1812  else
1813  {
1814  //
1815  // get first general transfer descriptor
1816  //
1817  TransferDescriptor = (POHCI_GENERAL_TD)OutDescriptor->HeadLogicalDescriptor;
1818 
1820  {
1821  //
1822  // update data toggle
1823  //
1825  }
1826 
1827  while(TransferDescriptor)
1828  {
1829  //
1830  // get condition code
1831  //
1832  ConditionCode = OHCI_TD_GET_CONDITION_CODE(TransferDescriptor->Flags);
1833  if (ConditionCode != OHCI_TD_CONDITION_NO_ERROR)
1834  {
1835  //
1836  // FIXME status code
1837  //
1839 
1840  switch(ConditionCode)
1841  {
1843  DPRINT1("OHCI_TD_CONDITION_CRC_ERROR detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
1845  break;
1847  DPRINT1("OHCI_TD_CONDITION_BIT_STUFFING detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
1849  break;
1851  DPRINT1("OHCI_TD_CONDITION_TOGGLE_MISMATCH detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
1853  break;
1855  DPRINT1("OHCI_TD_CONDITION_STALL detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
1857  break;
1859  DPRINT1("OHCI_TD_CONDITION_NO_RESPONSE detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
1861  break;
1863  DPRINT1("OHCI_TD_CONDITION_PID_CHECK_FAILURE detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
1865  break;
1867  DPRINT1("OHCI_TD_CONDITION_UNEXPECTED_PID detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
1869  break;
1871  DPRINT1("OHCI_TD_CONDITION_DATA_OVERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
1873  break;
1875  if (m_Irp)
1876  {
1877  //
1878  // get current irp stack location
1879  //
1881 
1882  //
1883  // get urb
1884  //
1885  Urb = (PURB)IoStack->Parameters.Others.Argument1;
1886 
1887  if(Urb->UrbBulkOrInterruptTransfer.TransferFlags & USBD_SHORT_TRANSFER_OK)
1888  {
1889  //
1890  // short packets are ok
1891  //
1894  break;
1895  }
1896  }
1897  DPRINT1("OHCI_TD_CONDITION_DATA_UNDERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
1899  break;
1901  DPRINT1("OHCI_TD_CONDITION_BUFFER_OVERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
1903  break;
1905  DPRINT1("OHCI_TD_CONDITION_BUFFER_UNDERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
1907  break;
1908  }
1909  }
1910 
1911  //
1912  // get next
1913  //
1914  TransferDescriptor = (POHCI_GENERAL_TD)TransferDescriptor->NextLogicalDescriptor;
1915  }
1916  }
1917 }
1918 
1919 VOID
1922 {
1923  PIO_STACK_LOCATION IoStack;
1924  PURB Urb;
1925 
1926  DPRINT("CUSBRequest::CompletionCallback\n");
1927 
1928  if (m_Irp)
1929  {
1930  //
1931  // set irp completion status
1932  //
1933  m_Irp->IoStatus.Status = m_NtStatusCode;
1934 
1935  //
1936  // get current irp stack location
1937  //
1939 
1940  //
1941  // get urb
1942  //
1943  Urb = (PURB)IoStack->Parameters.Others.Argument1;
1944 
1945  //
1946  // store urb status
1947  //
1948  Urb->UrbHeader.Status = m_UrbStatusCode;
1949 
1950  //
1951  // Check if the MDL was created
1952  //
1953  if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
1954  {
1955  //
1956  // Free Mdl
1957  //
1959  }
1960 
1961  //
1962  // FIXME calculate length
1963  //
1964 
1965  //
1966  // complete request
1967  //
1969  }
1970  else
1971  {
1972  //
1973  // signal completion event
1974  //
1977  }
1978 }
1979 
1980 //-----------------------------------------------------------------------------------------
1981 NTSTATUS
1982 NTAPI
1984  PUSBREQUEST *OutRequest)
1985 {
1986  PUSBREQUEST This;
1987 
1988  //
1989  // allocate requests
1990  //
1992  if (!This)
1993  {
1994  //
1995  // failed to allocate
1996  //
1998  }
1999 
2000  //
2001  // add reference count
2002  //
2003  This->AddRef();
2004 
2005  //
2006  // return result
2007  //
2008  *OutRequest = (PUSBREQUEST)This;
2009 
2010  //
2011  // done
2012  //
2013  return STATUS_SUCCESS;
2014 }
_In_ PPNDIS_PACKET _In_ UINT NumberOfPackets
Definition: ndis.h:5120
ULONG m_TransferBufferLength
Definition: usb_request.cpp:78
PUSB_ENDPOINT m_EndpointDescriptor
ULONG m_TransferBufferLengthCompleted
Definition: usb_request.cpp:83
IMP_IUSBREQUEST IMP_IEHCIREQUEST ULONG InternalGetTransferType()
NTSTATUS BuildSetupPacketFromURB()
#define OHCI_TD_CONDITION_BUFFER_OVERRUN
Definition: hardware.h:305
#define IN
Definition: typedefs.h:38
#define USBD_STATUS_PID_CHECK_FAILURE
Definition: usb.h:177
STDMETHODIMP_(ULONG) AddRef()
Definition: usb_request.cpp:21
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
struct _KEVENT * PKEVENT
PVOID BufferLogical
Definition: hardware.h:271
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define OHCI_ITD_NOFFSET
Definition: hardware.h:313
#define OHCI_TD_DIRECTION_PID_SETUP
Definition: hardware.h:277
ULONG BufferPhysical
Definition: hardware.h:320
#define PC_ASSERT(exp)
Definition: usbehci.h:17
PVOID NextLogicalDescriptor
Definition: hardware.h:269
_In_ PIRP _In_ PDEVICE_OBJECT Device
Definition: fatprocs.h:2020
#define IOCTL_INTERNAL_USB_SUBMIT_URB
Definition: usbioctl.h:32
_In_ BOOLEAN Release
Definition: classpnp.h:929
NTSTATUS STDMETHODCALLTYPE BuildTransferDescriptorChain(IN PQUEUE_HEAD QueueHead, IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode, IN UCHAR InitialDataToggle, OUT PQUEUE_TRANSFER_DESCRIPTOR *OutFirstDescriptor, OUT PQUEUE_TRANSFER_DESCRIPTOR *OutLastDescriptor, OUT PUCHAR OutDataToggle, OUT PULONG OutTransferBufferOffset)
#define OHCI_ITD_GET_FRAME_COUNT(x)
Definition: hardware.h:344
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
#define MmGetMdlVirtualAddress(_Mdl)
#define OHCI_ENDPOINT_DIRECTION_IN
Definition: hardware.h:239
VOID STDMETHODCALLTYPE InitDescriptor(IN PQUEUE_TRANSFER_DESCRIPTOR CurrentDescriptor, IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode, IN UCHAR DataToggle, OUT PULONG OutDescriptorLength)
NTSTATUS CreateIsochronousTransferDescriptor(OUT POHCI_ISO_TD *OutDescriptor, ULONG FrameCount)
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
USB_ENDPOINT_DESCRIPTOR EndPointDescriptor
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:428
LONG NTSTATUS
Definition: precomp.h:26
struct _OHCI_ISO_TD_ * POHCI_ISO_TD
VOID CheckError(struct _OHCI_ENDPOINT_DESCRIPTOR *OutDescriptor)
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2343
#define OHCI_ENDPOINT_DIRECTION_DESCRIPTOR
Definition: hardware.h:245
NTSTATUS BuildSetupPacket()
ULONG BufferSize
Definition: hardware.h:270
UCHAR STDMETHODCALLTYPE GetDeviceAddress()
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
#define USBD_STATUS_DATA_UNDERRUN
Definition: usb.h:180
#define USB_ENDPOINT_TYPE_CONTROL
Definition: usb100.h:62
#define OHCI_TD_SET_DELAY_INTERRUPT(x)
Definition: hardware.h:281
#define OHCI_TD_CONDITION_DATA_UNDERRUN
Definition: hardware.h:304
NTSTATUS BuildIsochronousEndpoint(POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor)
#define OHCI_TD_INTERRUPT_IMMEDIATE
Definition: hardware.h:292
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
#define USB_ENDPOINT_DIRECTION_MASK
Definition: usb100.h:73
#define OHCI_ENDPOINT_DIRECTION_OUT
Definition: hardware.h:238
VOID DumpEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR *Descriptor)
uint32_t ULONG_PTR
Definition: typedefs.h:63
struct OHCI_GENERAL_TD * POHCI_GENERAL_TD
PHYSICAL_ADDRESS PhysicalAddress
Definition: hardware.h:268
IUSBDevice * PUSBDEVICE
#define OHCI_TD_DIRECTION_PID_IN
Definition: hardware.h:279
#define IMP_IUSBREQUEST
USB_DEVICE_SPEED m_DeviceSpeed
#define USBD_STATUS_CRC
Definition: usb.h:172
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
long LONG
Definition: pedump.c:60
CUSBRequest(IUnknown *OuterUnknown)
#define OHCI_TD_CONDITION_TOGGLE_MISMATCH
Definition: hardware.h:298
PKEVENT m_CompletionEvent
NTSTATUS BuildControlTransferDescriptor(POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor)
#define STDMETHODIMP
Definition: basetyps.h:43
#define OHCI_TD_INTERRUPT_MASK
Definition: hardware.h:282
#define OHCI_TD_CONDITION_NO_ERROR
Definition: hardware.h:295
unsigned char BOOLEAN
#define OHCI_TD_SET_CONDITION_CODE(x)
Definition: hardware.h:289
PHYSICAL_ADDRESS m_DescriptorSetupPacket
smooth NULL
Definition: ftsmooth.c:416
static WCHAR Address[46]
Definition: ping.c:68
#define IoCompleteRequest
Definition: irp.c:1240
UCHAR InternalGetPidDirection()
void DPRINT(...)
Definition: polytest.cpp:61
#define USBD_STATUS_BUFFER_UNDERRUN
Definition: usb.h:184
#define USBD_STATUS_DATA_TOGGLE_MISMATCH
Definition: usb.h:174
Definition: bufpool.h:45
#define OHCI_TD_INTERRUPT_NONE
Definition: hardware.h:293
void * PVOID
Definition: retypes.h:9
PDMAMEMORYMANAGER m_DmaManager
Definition: usb_request.cpp:68
ULONG BufferPhysical
Definition: hardware.h:264
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)
#define USBD_STATUS_BUFFER_OVERRUN
Definition: usb.h:183
#define OHCI_TD_CONDITION_STALL
Definition: hardware.h:299
enum _USB_DEVICE_SPEED USB_DEVICE_SPEED
STDMETHODIMP QueryInterface(REFIID InterfaceId, PVOID *Interface)
#define USB_ENDPOINT_TYPE_MASK
Definition: usb100.h:61
PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket
struct _URB_HEADER UrbHeader
Definition: usb.h:531
IN PVOID IN PVOID IN USHORT IN USHORT IN PINTERFACE Interface
Definition: pci.h:359
struct _USB_ENDPOINT * PUSB_ENDPOINT
#define OHCI_TD_GET_CONDITION_CODE(x)
Definition: hardware.h:288
ULONG Flags
Definition: hardware.h:319
#define TAG_USBOHCI
Definition: usbohci.h:26
#define OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(s)
Definition: hardware.h:235
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define OHCI_ENDPOINT_SKIP
Definition: hardware.h:229
#define OHCI_ENDPOINT_LOW_SPEED
Definition: hardware.h:236
_Inout_ PSIZE_T _In_opt_ PMDLX _In_ MM_ROTATE_DIRECTION Direction
Definition: mmfuncs.h:773
static const UCHAR Index[8]
Definition: usbohci.c:18
#define STDMETHODCALLTYPE
Definition: bdasup.h:9
#define BufferSize
Definition: classpnp.h:419
#define OHCI_TD_CONDITION_CRC_ERROR
Definition: hardware.h:296
#define IRP_MJ_INTERNAL_DEVICE_CONTROL
VOID FreeDescriptor(POHCI_GENERAL_TD Descriptor)
#define OHCI_TD_CONDITION_DATA_OVERRUN
Definition: hardware.h:303
#define OHCI_ITD_SET_FRAME_COUNT(x)
Definition: hardware.h:345
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
#define USB_ENDPOINT_TYPE_ISOCHRONOUS
Definition: usb100.h:63
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
PUSB_DEFAULT_PIPE_SETUP_PACKET m_SetupPacket
Definition: usb_request.cpp:98
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define USBD_STATUS_SUCCESS
Definition: usb.h:170
#define OHCI_TD_TOGGLE_1
Definition: hardware.h:285
unsigned char UCHAR
Definition: xmlstorage.h:181
#define OHCI_ITD_SET_DELAY_INTERRUPT(x)
Definition: hardware.h:342
#define InterlockedDecrement
Definition: armddk.h:52
Definition: arc.h:85
ULONG LowPart
Definition: typedefs.h:104
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
Definition: usb.h:97
#define USB_ENDPOINT_TYPE_BULK
Definition: usb100.h:64
#define OHCI_TD_CONDITION_BIT_STUFFING
Definition: hardware.h:297
#define USBD_STATUS_STALL_PID
Definition: usb.h:175
struct _URB * PURB
PMDL m_TransferBufferMDL
Definition: usb_request.cpp:93
#define USBD_STATUS_DEV_NOT_RESPONDING
Definition: usb.h:176
Status
Definition: gdiplustypes.h:24
#define OHCI_TD_DIRECTION_PID_OUT
Definition: hardware.h:278
UCHAR m_DeviceAddress
PMDL NTAPI IoAllocateMdl(IN PVOID VirtualAddress, IN ULONG Length, IN BOOLEAN SecondaryBuffer, IN BOOLEAN ChargeQuota, IN PIRP Irp)
Definition: iomdl.c:22
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
#define USBD_SHORT_TRANSFER_OK
Definition: usb.h:154
#define OHCI_TD_TOGGLE_CARRY
Definition: hardware.h:283
struct _URB_ISOCH_TRANSFER UrbIsochronousTransfer
Definition: usb.h:544
#define OHCI_TD_CONDITION_BUFFER_UNDERRUN
Definition: hardware.h:306
#define USBD_STATUS_UNEXPECTED_PID
Definition: usb.h:178
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define InterlockedIncrement
Definition: armddk.h:53
Definition: usb.h:529
#define URB_FUNCTION_ISOCH_TRANSFER
Definition: usb.h:96
unsigned short USHORT
Definition: pedump.c:61
ULONG LastPhysicalByteAddress
Definition: hardware.h:322
ULONG LastPhysicalByteAddress
Definition: hardware.h:266
IUSBRequest * PUSBREQUEST
#define URB_FUNCTION_CLASS_INTERFACE
Definition: usb.h:113
#define OHCI_ENDPOINT_ISOCHRONOUS_FORMAT
Definition: hardware.h:241
STDMETHODIMP_(ULONG) Release()
Definition: usb_request.cpp:26
#define MmGetMdlByteCount(_Mdl)
ULONG m_TotalBytesTransferred
Definition: usb_request.cpp:88
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
#define OHCI_ENDPOINT_TOGGLE_CARRY
Definition: hardware.h:244
IDMAMemoryManager * PDMAMEMORYMANAGER
UCHAR GetEndpointAddress()
static ULONG WINAPI AddRef(IStream *iface)
Definition: clist.c:90
#define OHCI_ENDPOINT_SET_DEVICE_ADDRESS(s)
Definition: hardware.h:230
#define OHCI_TD_TOGGLE_0
Definition: hardware.h:284
#define DPRINT1
Definition: precomp.h:8
PHYSICAL_ADDRESS PhysicalAddress
Definition: hardware.h:221
virtual ~CUSBRequest()
NTSTATUS NTAPI InternalCreateUSBRequest(PUSBREQUEST *OutRequest)
USHORT Offset[OHCI_ITD_NOFFSET]
Definition: hardware.h:323
#define OUT
Definition: typedefs.h:39
NTSTATUS BuildBulkInterruptEndpoint(POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor)
NTSTATUS m_NtStatusCode
#define OHCI_TD_CONDITION_NOT_ACCESSED
Definition: hardware.h:307
#define OHCI_TD_CONDITION_PID_CHECK_FAILURE
Definition: hardware.h:301
struct _URB_BULK_OR_INTERRUPT_TRANSFER UrbBulkOrInterruptTransfer
Definition: usb.h:543
#define OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(s)
Definition: hardware.h:233
struct _OHCI_ISO_TD_ * NextLogicalDescriptor
Definition: hardware.h:327
#define OHCI_TD_BUFFER_ROUNDING
Definition: hardware.h:275
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:566
#define USBD_STATUS_DATA_OVERRUN
Definition: usb.h:179
PHYSICAL_ADDRESS NTAPI MmGetPhysicalAddress(IN PVOID Address)
Definition: stubs.c:682
#define OHCI_TD_CONDITION_UNEXPECTED_PID
Definition: hardware.h:302
NTSTATUS CreateGeneralTransferDescriptor(POHCI_GENERAL_TD *OutDescriptor, ULONG BufferSize)
#define USB_ENDPOINT_DIRECTION_OUT(x)
Definition: usb100.h:75
#define IMP_IOHCIREQUEST
Definition: interfaces.h:90
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define OHCI_ENDPOINT_FULL_SPEED
Definition: hardware.h:237
const TCHAR * CompletionCallback(unsigned __int64 &rnIndex, const BOOL *pblnForward, const TCHAR *pszContext, const TCHAR *pszBegin)
Definition: Completion.cpp:439
ULONG NextPhysicalDescriptor
Definition: hardware.h:265
USHORT GetMaxPacketSize()
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
return STATUS_SUCCESS
Definition: btrfs.c:2938
BM_REQUEST_TYPE bmRequestType
Definition: usb200.h:72
ULONG m_UrbStatusCode
#define OHCI_TD_CONDITION_NO_RESPONSE
Definition: hardware.h:300
PHYSICAL_ADDRESS PhysicalAddress
Definition: hardware.h:326
#define BYTE_OFFSET(Va)
NTSTATUS AllocateEndpointDescriptor(OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor)
#define URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
Definition: usb.h:95
LONGLONG QuadPart
Definition: typedefs.h:112
#define USBD_STATUS_BTSTUFF
Definition: usb.h:173
#define USB_ENDPOINT_TYPE_INTERRUPT
Definition: usb100.h:65
_In_ PSTORAGE_PROPERTY_ID _Outptr_ PSTORAGE_DESCRIPTOR_HEADER * Descriptor
Definition: classpnp.h:966
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68