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