ReactOS  0.4.13-dev-39-g8b6696f
usb_queue.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_queue.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 CUSBQueue : public IOHCIQueue
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  // com
41 
42  // local functions
43  BOOLEAN IsTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress);
44  BOOLEAN IsTransferDescriptorInIsoEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress);
45  NTSTATUS FindTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor);
46  NTSTATUS FindTransferDescriptorInInterruptHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor);
47  NTSTATUS FindTransferDescriptorInIsochronousHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor);
48 
49  VOID CleanupEndpointDescriptor(POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor);
52  VOID LinkEndpoint(POHCI_ENDPOINT_DESCRIPTOR HeadEndpointDescriptor, POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor);
54 
55 
56  // constructor / destructor
57  CUSBQueue(IUnknown *OuterUnknown){}
58  virtual ~CUSBQueue(){}
59 
60 protected:
61  LONG m_Ref; // reference count
62  KSPIN_LOCK m_Lock; // list lock
68  LIST_ENTRY m_PendingRequestList; // pending request list
69 };
70 
71 //=================================================================================================
72 // COM
73 //
77  IN REFIID refiid,
78  OUT PVOID* Output)
79 {
80  if (IsEqualGUIDAligned(refiid, IID_IUnknown))
81  {
82  *Output = PVOID(PUNKNOWN(this));
83  PUNKNOWN(*Output)->AddRef();
84  return STATUS_SUCCESS;
85  }
86 
87  return STATUS_UNSUCCESSFUL;
88 }
89 
93  IN PUSBHARDWAREDEVICE Hardware,
94  IN PDMA_ADAPTER AdapterObject,
95  IN PDMAMEMORYMANAGER MemManager,
97 {
98  if (!Hardware)
99  {
100  // WTF
101  DPRINT1("[USBOHCI] Failed to initialize queue\n");
102  return STATUS_UNSUCCESSFUL;
103  }
104 
105  //
106  // store hardware
107  //
108  m_Hardware = POHCIHARDWAREDEVICE(Hardware);
110 
111  //
112  // get bulk endpoint descriptor
113  //
114  m_Hardware->GetBulkHeadEndpointDescriptor(&m_BulkHeadEndpointDescriptor);
115 
116  //
117  // get control endpoint descriptor
118  //
119  m_Hardware->GetControlHeadEndpointDescriptor(&m_ControlHeadEndpointDescriptor);
120 
121  //
122  // get isochronous endpoint
123  //
124  m_Hardware->GetIsochronousHeadEndpointDescriptor(&m_IsoHeadEndpointDescriptor);
125 
126  //
127  // get interrupt endpoints
128  //
129  m_Hardware->GetInterruptEndpointDescriptors(&m_InterruptEndpoints);
130 
131  //
132  // initialize spinlock
133  //
135 
136  //
137  // init list
138  //
140 
141  return STATUS_SUCCESS;
142 }
143 
144 VOID
146  POHCI_ENDPOINT_DESCRIPTOR HeadEndpointDescriptor,
147  POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor)
148 {
149  POHCI_ENDPOINT_DESCRIPTOR CurrentEndpointDescriptor = HeadEndpointDescriptor;
150 
151  //
152  // get last descriptor in queue
153  //
154  while(CurrentEndpointDescriptor->NextDescriptor)
155  {
156  //
157  // move to last descriptor
158  //
159  CurrentEndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)CurrentEndpointDescriptor->NextDescriptor;
160  }
161 
162  //
163  // link endpoints
164  //
165  CurrentEndpointDescriptor->NextPhysicalEndpoint = EndpointDescriptor->PhysicalAddress.LowPart;
166  CurrentEndpointDescriptor->NextDescriptor = EndpointDescriptor;
167 
168 }
169 
170 VOID
173 {
174  IOHCIRequest *Request;
175  ULONG Type;
176  POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor;
177  POHCI_ISO_TD CurrentDescriptor;
178  ULONG FrameNumber;
179  USHORT Frame;
180 
181 
182  //
183  // sanity check
184  //
185  ASSERT(Descriptor->Request);
186  Request = (IOHCIRequest*)Descriptor->Request;
187 
188  //
189  // get request type
190  //
191  Type = Request->GetTransferType();
192 
193  //
194  // check type
195  //
197  {
198  //
199  // get head descriptor
200  //
201  HeadDescriptor = m_BulkHeadEndpointDescriptor;
202  }
203  else if (Type == USB_ENDPOINT_TYPE_CONTROL)
204  {
205  //
206  // get head descriptor
207  //
208  HeadDescriptor = m_ControlHeadEndpointDescriptor;
209  }
210  else if (Type == USB_ENDPOINT_TYPE_INTERRUPT)
211  {
212  //
213  // get head descriptor
214  //
215  HeadDescriptor = FindInterruptEndpointDescriptor(Request->GetInterval());
216  ASSERT(HeadDescriptor);
217  }
219  {
220  //
221  // get head descriptor
222  //
223  HeadDescriptor = m_IsoHeadEndpointDescriptor;
224 
225  //
226  // get current frame number
227  //
228  m_Hardware->GetCurrentFrameNumber(&FrameNumber);
229 
230  //
231  // FIXME: increment frame number
232  //
233  FrameNumber += 300;
234 
235  //
236  // apply frame number to iso transfer descriptors
237  //
238  CurrentDescriptor = (POHCI_ISO_TD)Descriptor->HeadLogicalDescriptor;
239 
240  DPRINT("ISO: NextFrameNumber %x\n", FrameNumber);
241  Frame = (FrameNumber & 0xFFFF);
242 
243  while(CurrentDescriptor)
244  {
245  //
246  // set current frame number
247  //
248  CurrentDescriptor->Flags |= OHCI_ITD_SET_STARTING_FRAME(Frame);
249 
250  //
251  // move to next frame number
252  //
253  Frame += OHCI_ITD_GET_FRAME_COUNT(CurrentDescriptor->Flags);
254 
255  //
256  // move to next descriptor
257  //
258  CurrentDescriptor = CurrentDescriptor->NextLogicalDescriptor;
259  }
260 
261  //
262  // get current frame number
263  //
264  m_Hardware->GetCurrentFrameNumber(&FrameNumber);
265 
266  DPRINT("Hardware 1ms %p Iso %p\n",m_InterruptEndpoints[0], m_IsoHeadEndpointDescriptor);
268 
270  }
271  else
272  {
273  //
274  // bad request type
275  //
276  ASSERT(FALSE);
277  return;
278  }
279 
280  //
281  // set descriptor active
282  //
283  Descriptor->Flags &= ~OHCI_ENDPOINT_SKIP;
284 
285  //
286  // insert endpoint at end
287  //
288  LinkEndpoint(HeadDescriptor, Descriptor);
289 
291  {
292  //
293  // notify hardware of our request
294  //
295  m_Hardware->HeadEndpointDescriptorModified(Type);
296  }
297 }
298 
299 
300 NTSTATUS
302 CUSBQueue::AddUSBRequest(
303  IUSBRequest * Req)
304 {
308 
309  DPRINT("CUSBQueue::AddUSBRequest\n");
310 
311  // get request
312  Request = POHCIREQUEST(Req);
313 
314 
315  //
316  // sanity check
317  //
318  ASSERT(Request != NULL);
319 
320  //
321  // add extra reference which is released when the request is completed
322  //
323  Request->AddRef();
324 
325  //
326  // get transfer descriptors
327  //
328  Status = Request->GetEndpointDescriptor(&Descriptor);
329  if (!NT_SUCCESS(Status))
330  {
331  //
332  // failed to get transfer descriptor
333  //
334  DPRINT1("CUSBQueue::AddUSBRequest GetEndpointDescriptor failed with %x\n", Status);
335 
336  //
337  // release reference
338  //
339  Request->Release();
340  return Status;
341  }
342 
343  //
344  // add the request
345  //
347  return STATUS_SUCCESS;
348 }
349 
350 NTSTATUS
352 CUSBQueue::CreateUSBRequest(
353  IUSBRequest **OutRequest)
354 {
355  PUSBREQUEST UsbRequest;
357 
358  *OutRequest = NULL;
359  Status = InternalCreateUSBRequest(&UsbRequest);
360 
361  if (NT_SUCCESS(Status))
362  {
363  *OutRequest = UsbRequest;
364  }
365 
366  return Status;
367 }
368 
369 NTSTATUS
371  IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor,
372  IN ULONG TransferDescriptorLogicalAddress,
373  OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor,
374  OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor)
375 {
376  POHCI_ENDPOINT_DESCRIPTOR LastDescriptor = EndpointDescriptor;
377 
378 
379  //
380  // skip first endpoint head
381  //
382  EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)EndpointDescriptor->NextDescriptor;
383 
384  while(EndpointDescriptor)
385  {
386  //
387  // check if the transfer descriptor is inside the list
388  //
389  if ((EndpointDescriptor->HeadPhysicalDescriptor & OHCI_ENDPOINT_HEAD_MASK) == EndpointDescriptor->TailPhysicalDescriptor || (EndpointDescriptor->HeadPhysicalDescriptor & OHCI_ENDPOINT_HALTED))
390  {
391  //
392  // found endpoint
393  //
394  *OutEndpointDescriptor = EndpointDescriptor;
395  *OutPreviousEndpointDescriptor = LastDescriptor;
396 
397  //
398  // done
399  //
400  return STATUS_SUCCESS;
401  }
402 
403  //
404  // store last endpoint
405  //
406  LastDescriptor = EndpointDescriptor;
407 
408  //
409  // move to next
410  //
411  EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)EndpointDescriptor->NextDescriptor;
412  }
413 
414  //
415  // failed to endpoint
416  //
417  return STATUS_NOT_FOUND;
418 }
419 
420 NTSTATUS
421 CUSBQueue::FindTransferDescriptorInInterruptHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor)
422 {
423  ULONG Index;
425 
426  //
427  // search descriptor in endpoint list
428  //
430  {
431  //
432  // is it in current endpoint
433  //
434  Status = FindTransferDescriptorInEndpoint(m_InterruptEndpoints[Index], TransferDescriptorLogicalAddress, OutEndpointDescriptor, OutPreviousEndpointDescriptor);
435  if (NT_SUCCESS(Status))
436  {
437  //
438  // found transfer descriptor
439  //
440  return STATUS_SUCCESS;
441  }
442  }
443 
444  //
445  // not found
446  //
447  return STATUS_NOT_FOUND;
448 }
449 
450 NTSTATUS
452  IN ULONG TransferDescriptorLogicalAddress,
453  OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor,
454  OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor)
455 {
456  POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
458 
459 
460  //
461  // skip first endpoint head
462  //
464 
465  while(EndpointDescriptor)
466  {
467  //
468  // check if the transfer descriptor is inside the list
469  //
470  if (IsTransferDescriptorInIsoEndpoint(EndpointDescriptor, TransferDescriptorLogicalAddress))
471  {
472  //
473  // found endpoint
474  //
475  *OutEndpointDescriptor = EndpointDescriptor;
476  *OutPreviousEndpointDescriptor = LastDescriptor;
477 
478  //
479  // done
480  //
481  return STATUS_SUCCESS;
482  }
483 
484  //
485  // store last endpoint
486  //
487  LastDescriptor = EndpointDescriptor;
488 
489  //
490  // move to next
491  //
492  EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)EndpointDescriptor->NextDescriptor;
493  }
494 
495  //
496  // failed to endpoint
497  //
498  return STATUS_NOT_FOUND;
499 }
500 
501 BOOLEAN
503  IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor,
504  IN ULONG TransferDescriptorLogicalAddress)
505 {
507 
508  //
509  // get first general transfer descriptor
510  //
511  Descriptor = (POHCI_ISO_TD)EndpointDescriptor->HeadLogicalDescriptor;
512 
513  //
514  // sanity check
515  //
517 
518  do
519  {
520  if (Descriptor->PhysicalAddress.LowPart == TransferDescriptorLogicalAddress)
521  {
522  //
523  // found descriptor
524  //
525  return TRUE;
526  }
527 
528  //
529  // move to next
530  //
531  Descriptor = (POHCI_ISO_TD)Descriptor->NextLogicalDescriptor;
532  }while(Descriptor);
533 
534  //
535  // no descriptor found
536  //
537  return FALSE;
538 }
539 
540 
541 BOOLEAN
543  IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor,
544  IN ULONG TransferDescriptorLogicalAddress)
545 {
547 
548  //
549  // get first general transfer descriptor
550  //
551  Descriptor = (POHCI_GENERAL_TD)EndpointDescriptor->HeadLogicalDescriptor;
552 
553  //
554  // sanity check
555  //
557 
558  do
559  {
560  if (Descriptor->PhysicalAddress.LowPart == TransferDescriptorLogicalAddress)
561  {
562  //
563  // found descriptor
564  //
565  return TRUE;
566  }
567 
568  //
569  // move to next
570  //
571  Descriptor = (POHCI_GENERAL_TD)Descriptor->NextLogicalDescriptor;
572  }while(Descriptor);
573 
574 
575  //
576  // no descriptor found
577  //
578  return FALSE;
579 }
580 
581 VOID
583  POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor,
584  POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor)
585 {
587  POHCI_ENDPOINT_DESCRIPTOR NewEndpointDescriptor;
588  USBD_STATUS UrbStatus;
589  KIRQL OldLevel;
590 
591  //
592  // FIXME: verify unlinking process
593  //
594  PreviousEndpointDescriptor->NextDescriptor = EndpointDescriptor->NextDescriptor;
595  PreviousEndpointDescriptor->NextPhysicalEndpoint = EndpointDescriptor->NextPhysicalEndpoint;
596 
597  //
598  // get corresponding request
599  //
600  Request = POHCIREQUEST(EndpointDescriptor->Request);
601  ASSERT(Request);
602 
603  //
604  // check for errors
605  //
606  if (EndpointDescriptor->HeadPhysicalDescriptor & OHCI_ENDPOINT_HALTED)
607  {
608  //
609  // the real error will processed by IUSBRequest
610  //
611  UrbStatus = USBD_STATUS_STALL_PID;
612  }
613  else
614  {
615  //
616  // well done ;)
617  //
618  UrbStatus = USBD_STATUS_SUCCESS;
619  }
620 
621  //
622  // Check if the transfer was completed and if UrbStatus is ok
623  //
624  if ((Request->IsRequestComplete() == FALSE) && (UrbStatus == USBD_STATUS_SUCCESS))
625  {
626  //
627  // request is incomplete, get new queue head
628  //
629  if (Request->GetEndpointDescriptor(&NewEndpointDescriptor) == STATUS_SUCCESS)
630  {
631  //
632  // notify of completion
633  //
634  Request->FreeEndpointDescriptor(EndpointDescriptor);
635 
636  //
637  // first acquire request lock
638  //
639  KeAcquireSpinLock(&m_Lock, &OldLevel);
640 
641  //
642  // add to pending list
643  //
644  InsertTailList(&m_PendingRequestList, &NewEndpointDescriptor->DescriptorListEntry);
645 
646  //
647  // release queue head
648  //
649  KeReleaseSpinLock(&m_Lock, OldLevel);
650 
651  //
652  // Done for now
653  //
654  return;
655  }
656  DPRINT1("Unable to create a new QueueHead\n");
657  //ASSERT(FALSE);
658 
659  //
660  // Else there was a problem
661  // FIXME: Find better return
663  }
664 
665  if (UrbStatus != USBD_STATUS_SUCCESS)
666  {
667  DPRINT1("URB failed with status 0x%x\n", UrbStatus);
668  //PC_ASSERT(FALSE);
669  }
670 
671  //
672  // free endpoint descriptor
673  //
674  Request->FreeEndpointDescriptor(EndpointDescriptor);
675 
676  //
677  // notify of completion
678  //
679  Request->CompletionCallback();
680 
681 
682  //
683  // release request
684  //
685  Request->Release();
686 }
687 
688 VOID
690  POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor)
691 {
692  DPRINT1("CUSBQueue::PrintEndpointList HeadEndpoint %p Logical %x\n", EndpointDescriptor, EndpointDescriptor->PhysicalAddress.LowPart);
693 
694  //
695  // get first general transfer descriptor
696  //
697  EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)EndpointDescriptor->NextDescriptor;
698 
699  while(EndpointDescriptor)
700  {
701  DPRINT1(" CUSBQueue::PrintEndpointList Endpoint %p Logical %x\n", EndpointDescriptor, EndpointDescriptor->PhysicalAddress.LowPart);
702 
703  //
704  // move to next
705  //
706  EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)EndpointDescriptor->NextDescriptor;
707  }
708 }
709 
710 VOID
712 CUSBQueue::TransferDescriptorCompletionCallback(
713  ULONG TransferDescriptorLogicalAddress)
714 {
715  POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, PreviousEndpointDescriptor;
718 
719  DPRINT("CUSBQueue::TransferDescriptorCompletionCallback transfer descriptor %x\n", TransferDescriptorLogicalAddress);
720 
721  do
722  {
723  //
724  // find transfer descriptor in control list
725  //
726  Status = FindTransferDescriptorInEndpoint(m_ControlHeadEndpointDescriptor, TransferDescriptorLogicalAddress, &EndpointDescriptor, &PreviousEndpointDescriptor);
727  if (NT_SUCCESS(Status))
728  {
729  //
730  // cleanup endpoint
731  //
732  CleanupEndpointDescriptor(EndpointDescriptor, PreviousEndpointDescriptor);
733 
734  //
735  // done
736  //
737  continue;
738  }
739 
740  //
741  // find transfer descriptor in bulk list
742  //
743  Status = FindTransferDescriptorInEndpoint(m_BulkHeadEndpointDescriptor, TransferDescriptorLogicalAddress, &EndpointDescriptor, &PreviousEndpointDescriptor);
744  if (NT_SUCCESS(Status))
745  {
746  //
747  // cleanup endpoint
748  //
749  CleanupEndpointDescriptor(EndpointDescriptor, PreviousEndpointDescriptor);
750 
751  //
752  // done
753  //
754  continue;
755  }
756 
757  //
758  // find transfer descriptor in interrupt list
759  //
760  Status = FindTransferDescriptorInInterruptHeadEndpoints(TransferDescriptorLogicalAddress, &EndpointDescriptor, &PreviousEndpointDescriptor);
761  if (NT_SUCCESS(Status))
762  {
763  //
764  // cleanup endpoint
765  //
766  CleanupEndpointDescriptor(EndpointDescriptor, PreviousEndpointDescriptor);
767 
768  //
769  // done
770  //
771  continue;
772  }
773 
774  //
775  // last try: find the descriptor in isochronous list
776  //
777  Status = FindTransferDescriptorInIsochronousHeadEndpoints(TransferDescriptorLogicalAddress, &EndpointDescriptor, &PreviousEndpointDescriptor);
778  if (NT_SUCCESS(Status))
779  {
780  //
781  // cleanup endpoint
782  //
783  DPRINT("ISO endpoint complete\n");
784  //ASSERT(FALSE);
785  CleanupEndpointDescriptor(EndpointDescriptor, PreviousEndpointDescriptor);
786 
787  //
788  // done
789  //
790  continue;
791  }
792 
793  //
794  // no more completed descriptors found
795  //
796  break;
797 
798  }while(TRUE);
799 
800 
801  //
802  // acquire spin lock
803  //
805 
806  //
807  // is there a pending list item
808  //
810  {
811  //
812  // get list entry
813  //
815 
816  //
817  // get entry
818  //
819  EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)CONTAINING_RECORD(Entry, OHCI_ENDPOINT_DESCRIPTOR, DescriptorListEntry);
820 
821  //
822  // add entry
823  //
824  AddEndpointDescriptor(EndpointDescriptor);
825  }
826 
827  //
828  // release lock
829  //
831 }
832 
835  UCHAR InterruptInterval)
836 {
837  ULONG Index = 0;
838  ULONG Power = 1;
839 
840  //
841  // sanity check
842  //
843  ASSERT(InterruptInterval <= OHCI_BIGGEST_INTERVAL);
844 
845  //
846  // find interrupt index
847  //
848  while (Power <= OHCI_BIGGEST_INTERVAL / 2)
849  {
850  //
851  // is current interval greater
852  //
853  if (Power * 2 > InterruptInterval)
854  break;
855 
856  //
857  // increment power
858  //
859  Power *= 2;
860 
861  //
862  // move to next interrupt
863  //
864  Index++;
865  }
866 
867  DPRINT("InterruptInterval %lu Selected InterruptIndex %lu Chosen Interval %lu\n", InterruptInterval, Index, Power);
868 
869  //
870  // return endpoint
871  //
872  return m_InterruptEndpoints[Index];
873 }
874 
875 NTSTATUS
877 CUSBQueue::AbortDevicePipe(
879  IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor)
880 {
881  POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor, CurrentDescriptor, PreviousDescriptor, TempDescriptor;
882  ULONG Type;
883  POHCI_GENERAL_TD TransferDescriptor;
884 
885  //
886  // get type
887  //
888  Type = (EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK);
889 
890  //
891  // check type
892  //
894  {
895  //
896  // get head descriptor
897  //
898  HeadDescriptor = m_BulkHeadEndpointDescriptor;
899  }
900  else if (Type == USB_ENDPOINT_TYPE_CONTROL)
901  {
902  //
903  // get head descriptor
904  //
905  HeadDescriptor = m_ControlHeadEndpointDescriptor;
906  }
907  else if (Type == USB_ENDPOINT_TYPE_INTERRUPT)
908  {
909  //
910  // get head descriptor
911  //
912  HeadDescriptor = FindInterruptEndpointDescriptor(EndpointDescriptor->bInterval);
913  ASSERT(HeadDescriptor);
914  }
915  else
916  {
917  //
918  // IMPLEMENT me
919  //
922  return STATUS_NOT_IMPLEMENTED;
923  }
924 
925  //
926  // FIXME should disable list processing
927  //
928 
929  //
930  // now remove all endpoints
931  //
932  ASSERT(HeadDescriptor);
933  CurrentDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)HeadDescriptor->NextDescriptor;
934  PreviousDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)HeadDescriptor;
935 
936  while(CurrentDescriptor)
937  {
938  if ((CurrentDescriptor->HeadPhysicalDescriptor & OHCI_ENDPOINT_HEAD_MASK) == CurrentDescriptor->TailPhysicalDescriptor || (CurrentDescriptor->HeadPhysicalDescriptor & OHCI_ENDPOINT_HALTED))
939  {
940  //
941  // cleanup endpoint
942  //
943  TempDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)CurrentDescriptor->NextDescriptor;
944  CleanupEndpointDescriptor(CurrentDescriptor, PreviousDescriptor);
945 
946  //
947  // use next descriptor
948  //
949  CurrentDescriptor = TempDescriptor;
950  }
951 
952  if (!CurrentDescriptor)
953  break;
954 
955  if (CurrentDescriptor->HeadPhysicalDescriptor)
956  {
957  TransferDescriptor = (POHCI_GENERAL_TD)CurrentDescriptor->HeadLogicalDescriptor;
958  ASSERT(TransferDescriptor);
959 
960  if ((OHCI_ENDPOINT_GET_ENDPOINT_NUMBER(TransferDescriptor->Flags) == (EndpointDescriptor->bEndpointAddress & 0xF)) &&
961  (OHCI_ENDPOINT_GET_DEVICE_ADDRESS(TransferDescriptor->Flags) == DeviceAddress))
962  {
963  //
964  // cleanup endpoint
965  //
966  TempDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)CurrentDescriptor->NextDescriptor;
967  CleanupEndpointDescriptor(CurrentDescriptor, PreviousDescriptor);
968  //
969  // use next descriptor
970  //
971  CurrentDescriptor = TempDescriptor;
972  }
973  }
974 
975  if (!CurrentDescriptor)
976  break;
977 
978  PreviousDescriptor = CurrentDescriptor;
979  CurrentDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)CurrentDescriptor->NextDescriptor;
980  }
981 
982  //
983  // done
984  //
985  return STATUS_SUCCESS;
986 }
987 
988 
989 NTSTATUS
990 NTAPI
992  PUSBQUEUE *OutUsbQueue)
993 {
994  PUSBQUEUE This;
995 
996  //
997  // allocate controller
998  //
1000  if (!This)
1001  {
1002  //
1003  // failed to allocate
1004  //
1006  }
1007 
1008  //
1009  // add reference count
1010  //
1011  This->AddRef();
1012 
1013  //
1014  // return result
1015  //
1016  *OutUsbQueue = (PUSBQUEUE)This;
1017 
1018  //
1019  // done
1020  //
1021  return STATUS_SUCCESS;
1022 }
#define OHCI_ENDPOINT_GET_ENDPOINT_NUMBER(s)
Definition: hardware.h:232
#define OHCI_STATIC_ENDPOINT_COUNT
Definition: hardware.h:193
#define IN
Definition: typedefs.h:38
KSPIN_LOCK m_Lock
Definition: usb_queue.cpp:62
#define REFIID
Definition: guiddef.h:113
#define TRUE
Definition: types.h:120
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
Type
Definition: Type.h:6
IUSBHardwareDevice * PUSBHARDWAREDEVICE
struct _Entry Entry
Definition: kefuncs.h:640
_In_ BOOLEAN Release
Definition: classpnp.h:929
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
#define OHCI_ITD_GET_FRAME_COUNT(x)
Definition: hardware.h:344
#define OHCI_ENDPOINT_HEAD_MASK
Definition: hardware.h:242
STDMETHODIMP_(ULONG) Release()
Definition: usb_queue.cpp:26
IUnknown * PUNKNOWN
Definition: com_apitest.h:45
VOID NTAPI KeAcquireSpinLockAtDpcLevel(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:192
LONG NTSTATUS
Definition: precomp.h:26
struct _OHCI_ISO_TD_ * POHCI_ISO_TD
LIST_ENTRY DescriptorListEntry
Definition: hardware.h:225
POHCI_ENDPOINT_DESCRIPTOR m_ControlHeadEndpointDescriptor
Definition: usb_queue.cpp:65
KSPIN_LOCK * PKSPIN_LOCK
Definition: env_spec_w32.h:73
#define USB_ENDPOINT_TYPE_CONTROL
Definition: usb100.h:62
POHCI_ENDPOINT_DESCRIPTOR FindInterruptEndpointDescriptor(UCHAR InterruptInterval)
Definition: usb_queue.cpp:834
VOID PrintEndpointList(POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor)
Definition: usb_queue.cpp:689
#define InsertTailList(ListHead, Entry)
NTSTATUS FindTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor)
Definition: usb_queue.cpp:370
POHCI_ENDPOINT_DESCRIPTOR m_IsoHeadEndpointDescriptor
Definition: usb_queue.cpp:66
#define OHCI_ENDPOINT_GET_DEVICE_ADDRESS(s)
Definition: hardware.h:231
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
virtual ~CUSBQueue()
Definition: usb_queue.cpp:58
#define IsEqualGUIDAligned(guid1, guid2)
Definition: wdm.template.h:233
LIST_ENTRY m_PendingRequestList
Definition: usb_queue.cpp:68
struct OHCI_GENERAL_TD * POHCI_GENERAL_TD
#define USBD_STATUS_INSUFFICIENT_RESOURCES
Definition: usb.h:204
_In_ NDIS_HANDLE _In_ PNDIS_REQUEST Request
Definition: ndis.h:5155
UCHAR KIRQL
Definition: env_spec_w32.h:591
POHCIHARDWAREDEVICE m_Hardware
Definition: usb_queue.cpp:63
#define OHCI_ENDPOINT_HALTED
Definition: hardware.h:243
POHCI_ENDPOINT_DESCRIPTOR * m_InterruptEndpoints
Definition: usb_queue.cpp:67
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
_In_ PUSB_DEVICE_HANDLE _Out_ PUSHORT DeviceAddress
Definition: hubbusif.h:359
long LONG
Definition: pedump.c:60
PEHCIHARDWAREDEVICE m_Hardware
Definition: usb_queue.cpp:52
NTSTATUS FindTransferDescriptorInIsochronousHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor)
Definition: usb_queue.cpp:451
#define STDMETHODIMP
Definition: basetyps.h:43
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:251
#define OHCI_BIGGEST_INTERVAL
Definition: hardware.h:194
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
void DPRINT(...)
Definition: polytest.cpp:61
void * PVOID
Definition: retypes.h:9
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
NTSTATUS NTAPI CreateUSBQueue(PUSBQUEUE *OutUsbQueue)
Definition: usb_queue.cpp:1204
STDMETHODIMP QueryInterface(REFIID InterfaceId, PVOID *Interface)
#define OHCI_ITD_SET_STARTING_FRAME(x)
Definition: hardware.h:340
#define USB_ENDPOINT_TYPE_MASK
Definition: usb100.h:61
VOID LinkEndpoint(POHCI_ENDPOINT_DESCRIPTOR HeadEndpointDescriptor, POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor)
Definition: usb_queue.cpp:145
STDMETHODIMP_(ULONG) AddRef()
Definition: usb_queue.cpp:21
IN PVOID IN PVOID IN USHORT IN USHORT IN PINTERFACE Interface
Definition: pci.h:359
#define STATUS_NOT_FOUND
Definition: shellext.h:67
IOHCIRequest * POHCIREQUEST
Definition: interfaces.h:106
ULONG Flags
Definition: hardware.h:319
#define TAG_USBOHCI
Definition: usbohci.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define OHCI_ENDPOINT_SKIP
Definition: hardware.h:229
const GUID IID_IUnknown
VOID NTAPI KeReleaseSpinLockFromDpcLevel(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:215
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
static const UCHAR Index[8]
Definition: usbohci.c:18
#define STDMETHODCALLTYPE
Definition: bdasup.h:9
LONG m_Ref
Definition: usb_queue.cpp:49
nsrefcnt Release()
ULONG AddRef()
CUSBQueue(IUnknown *OuterUnknown)
Definition: usb_queue.cpp:57
#define USB_ENDPOINT_TYPE_ISOCHRONOUS
Definition: usb100.h:63
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define USBD_STATUS_SUCCESS
Definition: usb.h:170
BOOLEAN IsTransferDescriptorInIsoEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress)
Definition: usb_queue.cpp:502
unsigned char UCHAR
Definition: xmlstorage.h:181
#define IMP_IUSBOHCIQUEUE
Definition: interfaces.h:121
#define InterlockedDecrement
Definition: armddk.h:52
LONG USBD_STATUS
Definition: usb.h:165
Definition: arc.h:85
ULONG LowPart
Definition: typedefs.h:104
Definition: typedefs.h:117
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG IN OUT PLONG IN LONG Increment IN PNDIS_RW_LOCK Lock
Definition: CrNtStubs.h:75
#define USB_ENDPOINT_TYPE_BULK
Definition: usb100.h:64
#define USBD_STATUS_STALL_PID
Definition: usb.h:175
NTSTATUS FindTransferDescriptorInInterruptHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor)
Definition: usb_queue.cpp:421
VOID CleanupEndpointDescriptor(POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor)
Definition: usb_queue.cpp:582
Status
Definition: gdiplustypes.h:24
#define InterlockedIncrement
Definition: armddk.h:53
IUSBQueue * PUSBQUEUE
unsigned short USHORT
Definition: pedump.c:61
struct _OHCI_ENDPOINT_DESCRIPTOR * POHCI_ENDPOINT_DESCRIPTOR
IMP_IUSBQUEUE IMP_IUSBOHCIQUEUE BOOLEAN IsTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress)
Definition: usb_queue.cpp:542
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
IUSBRequest * PUSBREQUEST
POHCI_ENDPOINT_DESCRIPTOR m_BulkHeadEndpointDescriptor
Definition: usb_queue.cpp:64
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
BOOL Initialize(HINSTANCE hInstance)
Definition: msconfig.c:341
IOHCIHardwareDevice * POHCIHARDWAREDEVICE
Definition: interfaces.h:59
IDMAMemoryManager * PDMAMEMORYMANAGER
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
static ULONG WINAPI AddRef(IStream *iface)
Definition: clist.c:90
#define DPRINT1
Definition: precomp.h:8
PHYSICAL_ADDRESS PhysicalAddress
Definition: hardware.h:221
NTSTATUS NTAPI InternalCreateUSBRequest(PUSBREQUEST *OutRequest)
#define OUT
Definition: typedefs.h:39
struct _OHCI_ISO_TD_ * NextLogicalDescriptor
Definition: hardware.h:327
unsigned int ULONG
Definition: retypes.h:1
#define UNIMPLEMENTED
Definition: debug.h:114
#define IMP_IUSBQUEUE
VOID AddEndpointDescriptor(IN POHCI_ENDPOINT_DESCRIPTOR Descriptor)
Definition: usb_queue.cpp:171
return STATUS_SUCCESS
Definition: btrfs.c:2725
nsrefcnt AddRef()
base of all file and directory entries
Definition: entries.h:82
#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