[CMAKE]
[reactos.git] / drivers / usb / usbehci / transfer.c
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbehci/transfer.c
5 * PURPOSE: Transfers to EHCI.
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 */
9
10 #include "transfer.h"
11 #include <debug.h>
12
13 VOID
14 BuildSetupPacketFromURB(PEHCI_HOST_CONTROLLER hcd, PURB Urb, PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup)
15 {
16 switch (Urb->UrbHeader.Function)
17 {
18 /* CLEAR FEATURE */
19 case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE:
20 case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE:
21 case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT:
22 DPRINT1("Not implemented!\n");
23 break;
24
25 /* GET CONFIG */
26 case URB_FUNCTION_GET_CONFIGURATION:
27 CtrlSetup->bRequest = USB_REQUEST_GET_CONFIGURATION;
28 CtrlSetup->bmRequestType.B = 0x80;
29 CtrlSetup->wLength = 1;
30 break;
31
32 /* GET DESCRIPTOR */
33 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
34 CtrlSetup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
35 CtrlSetup->wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
36 CtrlSetup->wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType;
37 CtrlSetup->wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
38 CtrlSetup->wLength = Urb->UrbControlDescriptorRequest.TransferBufferLength;
39 CtrlSetup->bmRequestType.B = 0x80;
40 break;
41
42 /* GET INTERFACE */
43 case URB_FUNCTION_GET_INTERFACE:
44 CtrlSetup->bRequest = USB_REQUEST_GET_CONFIGURATION;
45 CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
46 CtrlSetup->bmRequestType.B = 0x80;
47 CtrlSetup->wLength = 1;
48 break;
49
50 /* GET STATUS */
51 case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
52 CtrlSetup->bRequest = USB_REQUEST_GET_STATUS;
53 ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
54 CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
55 CtrlSetup->bmRequestType.B = 0x80;
56 CtrlSetup->wLength = 2;
57 break;
58
59 case URB_FUNCTION_GET_STATUS_FROM_INTERFACE:
60 CtrlSetup->bRequest = USB_REQUEST_GET_STATUS;
61 ASSERT(Urb->UrbControlGetStatusRequest.Index != 0);
62 CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
63 CtrlSetup->bmRequestType.B = 0x81;
64 CtrlSetup->wLength = 2;
65 break;
66
67 case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT:
68 CtrlSetup->bRequest = USB_REQUEST_GET_STATUS;
69 ASSERT(Urb->UrbControlGetStatusRequest.Index != 0);
70 CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
71 CtrlSetup->bmRequestType.B = 0x82;
72 CtrlSetup->wLength = 2;
73 break;
74
75 /* SET ADDRESS */
76
77 /* SET CONFIG */
78 case URB_FUNCTION_SELECT_CONFIGURATION:
79 CtrlSetup->bRequest = USB_REQUEST_SET_CONFIGURATION;
80 CtrlSetup->wValue.W = Urb->UrbSelectConfiguration.ConfigurationDescriptor->bConfigurationValue;
81 CtrlSetup->wIndex.W = 0;
82 CtrlSetup->wLength = 0;
83 CtrlSetup->bmRequestType.B = 0x00;
84 break;
85
86 /* SET DESCRIPTOR */
87 case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE:
88 case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE:
89 case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT:
90 DPRINT1("Not implemented\n");
91 break;
92
93 /* SET FEATURE */
94 case URB_FUNCTION_SET_FEATURE_TO_DEVICE:
95 CtrlSetup->bRequest = USB_REQUEST_SET_FEATURE;
96 ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
97 CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
98 CtrlSetup->bmRequestType.B = 0x80;
99 break;
100
101 case URB_FUNCTION_SET_FEATURE_TO_INTERFACE:
102 CtrlSetup->bRequest = USB_REQUEST_SET_FEATURE;
103 ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
104 CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
105 CtrlSetup->bmRequestType.B = 0x81;
106 break;
107
108 case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT:
109 CtrlSetup->bRequest = USB_REQUEST_SET_FEATURE;
110 ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
111 CtrlSetup->wIndex.W = Urb->UrbControlGetStatusRequest.Index;
112 CtrlSetup->bmRequestType.B = 0x82;
113 break;
114
115 /* SET INTERFACE*/
116 case URB_FUNCTION_SELECT_INTERFACE:
117 CtrlSetup->bRequest = USB_REQUEST_SET_INTERFACE;
118 CtrlSetup->wValue.W = Urb->UrbSelectInterface.Interface.AlternateSetting;
119 CtrlSetup->wIndex.W = Urb->UrbSelectInterface.Interface.InterfaceNumber;
120 CtrlSetup->wLength = 0;
121 CtrlSetup->bmRequestType.B = 0x01;
122 break;
123
124 /* SYNC FRAME */
125 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
126 DPRINT1("Not implemented\n");
127 break;
128 default:
129 DPRINT1("Unknown USB Request!\n");
130 break;
131 }
132 }
133
134 BOOLEAN
135 SubmitControlTransfer(PEHCI_HOST_CONTROLLER hcd,
136 PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup,
137 PVOID TransferBuffer,
138 ULONG TransferBufferLength,
139 PIRP IrpToComplete)
140 {
141 PQUEUE_HEAD QueueHead;
142 PQUEUE_TRANSFER_DESCRIPTOR Descriptor[3];
143 ULONG MdlPhysicalAddr;
144 PKEVENT Event = NULL;
145 PMDL pMdl = NULL;
146 PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetupVA, CtrlPhysicalPA;
147
148 CtrlSetupVA = (PUSB_DEFAULT_PIPE_SETUP_PACKET)AllocateMemory(hcd,
149 sizeof(USB_DEFAULT_PIPE_SETUP_PACKET),
150 (ULONG*)&CtrlPhysicalPA);
151
152 RtlCopyMemory(CtrlSetupVA, CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
153 /* If no Irp then wait on completion */
154 if (IrpToComplete == NULL)
155 {
156 Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
157 KeInitializeEvent(Event, NotificationEvent, FALSE);
158 }
159
160 if (TransferBuffer)
161 {
162 /* Allocate Mdl for Buffer */
163 pMdl = IoAllocateMdl(TransferBuffer,
164 TransferBufferLength,
165 FALSE,
166 FALSE,
167 NULL);
168
169 /* Lock Physical Pages */
170 MmBuildMdlForNonPagedPool(pMdl);
171 //MmProbeAndLockPages(pMdl, KernelMode, IoReadAccess);
172
173 MdlPhysicalAddr = MmGetPhysicalAddress((PVOID)TransferBuffer).LowPart;
174 }
175
176 QueueHead = CreateQueueHead(hcd);
177
178 Descriptor[0] = CreateDescriptor(hcd,
179 PID_CODE_SETUP_TOKEN,
180 sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
181
182 Descriptor[0]->Token.Bits.InterruptOnComplete = FALSE;
183 Descriptor[0]->Token.Bits.DataToggle = FALSE;
184
185 /* Save the first descriptor */
186 QueueHead->TransferDescriptor = Descriptor[0];
187
188 if (TransferBuffer)
189 {
190 Descriptor[1] = CreateDescriptor(hcd,
191 PID_CODE_IN_TOKEN,
192 TransferBufferLength);
193 }
194
195 Descriptor[2] = CreateDescriptor(hcd,
196 PID_CODE_OUT_TOKEN,
197 0);
198
199 Descriptor[1]->Token.Bits.InterruptOnComplete = FALSE;
200
201 /* Link the descriptors */
202
203 if (TransferBuffer)
204 {
205 Descriptor[0]->NextDescriptor = Descriptor[1];
206 Descriptor[1]->NextDescriptor = Descriptor[2];
207 Descriptor[1]->PreviousDescriptor = Descriptor[0];
208 Descriptor[2]->PreviousDescriptor = Descriptor[1];
209 }
210 else
211 {
212 Descriptor[0]->NextDescriptor = Descriptor[2];
213 Descriptor[2]->PreviousDescriptor = Descriptor[0];
214 }
215
216 /* Assign the descritors buffers */
217 Descriptor[0]->BufferPointer[0] = (ULONG)CtrlPhysicalPA;
218
219 if (TransferBuffer)
220 {
221 Descriptor[1]->BufferPointer[0] = MdlPhysicalAddr;
222 Descriptor[0]->NextPointer = Descriptor[1]->PhysicalAddr;
223 Descriptor[1]->NextPointer = Descriptor[2]->PhysicalAddr;
224 }
225 else
226 {
227 Descriptor[0]->NextPointer = Descriptor[2]->PhysicalAddr;
228 }
229
230 QueueHead->NextPointer = Descriptor[0]->PhysicalAddr;
231
232 QueueHead->IrpToComplete = IrpToComplete;
233 QueueHead->MdlToFree = pMdl;
234 QueueHead->Event = Event;
235
236 /* Link in the QueueHead */
237 LinkQueueHead(hcd, QueueHead);
238
239 if (IrpToComplete == NULL)
240 {
241 DPRINT1("Waiting For Completion %x!\n", Event);
242 KeWaitForSingleObject(Event, Suspended, KernelMode, FALSE, NULL);
243 ExFreePool(Event);
244 }
245
246 return TRUE;
247 }