1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxUsbPipeAPI.cpp
8 
9 Abstract:
10 
11 
12 Author:
13 
14 Environment:
15 
16     Both kernel and user mode
17 
18 Revision History:
19 
20 --*/
21 
22 #include "fxusbpch.hpp"
23 
24 extern "C" {
25 #include "FxUsbPipeAPI.tmh"
26 }
27 
28 //
29 // extern "C" the whole file since we are exporting the APIs by name
30 //
31 extern "C" {
32 
33 __drv_maxIRQL(DISPATCH_LEVEL)
34 VOID
35 WDFAPI
36 WDFEXPORT(WdfUsbTargetPipeGetInformation)(
37     __in
38     PWDF_DRIVER_GLOBALS DriverGlobals,
39     __in
40     WDFUSBPIPE Pipe,
41     __out
42     PWDF_USB_PIPE_INFORMATION PipeInformation
43     )
44 {
45     DDI_ENTRY();
46 
47     PFX_DRIVER_GLOBALS pFxDriverGlobals;
48     FxUsbPipe* pUsbPipe;
49 
50     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
51                                    Pipe,
52                                    FX_TYPE_IO_TARGET_USB_PIPE,
53                                    (PVOID*) &pUsbPipe,
54                                    &pFxDriverGlobals);
55 
56     FxPointerNotNull(pFxDriverGlobals, PipeInformation);
57 
58     pUsbPipe->GetInformation(PipeInformation);
59 }
60 
61 __drv_maxIRQL(DISPATCH_LEVEL)
62 BOOLEAN
63 WDFAPI
64 WDFEXPORT(WdfUsbTargetPipeIsInEndpoint)(
65     __in
66     PWDF_DRIVER_GLOBALS DriverGlobals,
67     __in
68     WDFUSBPIPE Pipe
69     )
70 {
71     DDI_ENTRY();
72 
73     FxUsbPipe* pUsbPipe;
74 
75     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
76                          Pipe,
77                          FX_TYPE_IO_TARGET_USB_PIPE,
78                          (PVOID*) &pUsbPipe);
79 
80     return pUsbPipe->IsInEndpoint();
81 }
82 
83 __drv_maxIRQL(DISPATCH_LEVEL)
84 BOOLEAN
85 WDFAPI
86 WDFEXPORT(WdfUsbTargetPipeIsOutEndpoint)(
87     __in
88     PWDF_DRIVER_GLOBALS DriverGlobals,
89     __in
90     WDFUSBPIPE Pipe
91     )
92 {
93     DDI_ENTRY();
94 
95     FxUsbPipe* pUsbPipe;
96 
97     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
98                          Pipe,
99                          FX_TYPE_IO_TARGET_USB_PIPE,
100                          (PVOID*) &pUsbPipe);
101 
102     return pUsbPipe->IsOutEndpoint();
103 }
104 
105 __drv_maxIRQL(DISPATCH_LEVEL)
106 WDF_USB_PIPE_TYPE
107 WDFAPI
108 WDFEXPORT(WdfUsbTargetPipeGetType)(
109     __in
110     PWDF_DRIVER_GLOBALS DriverGlobals,
111     __in
112     WDFUSBPIPE Pipe
113     )
114 {
115     DDI_ENTRY();
116 
117     FxUsbPipe* pUsbPipe;
118 
119     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
120                          Pipe,
121                          FX_TYPE_IO_TARGET_USB_PIPE,
122                          (PVOID*) &pUsbPipe);
123 
124     return pUsbPipe->GetType();
125 }
126 
127 __drv_maxIRQL(DISPATCH_LEVEL)
128 VOID
129 WDFAPI
130 WDFEXPORT(WdfUsbTargetPipeSetNoMaximumPacketSizeCheck)(
131     __in
132     PWDF_DRIVER_GLOBALS DriverGlobals,
133     __in
134     WDFUSBPIPE Pipe
135     )
136 {
137     DDI_ENTRY();
138 
139     PFX_DRIVER_GLOBALS pFxDriverGlobals;
140     FxUsbPipe* pUsbPipe;
141 
142     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
143                                    Pipe,
144                                    FX_TYPE_IO_TARGET_USB_PIPE,
145                                    (PVOID*) &pUsbPipe,
146                                    &pFxDriverGlobals);
147 
148     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
149                         "WDFUSBPIPE %p", Pipe);
150 
151     pUsbPipe->SetNoCheckPacketSize();
152 }
153 
154 _Must_inspect_result_
155 __drv_maxIRQL(PASSIVE_LEVEL)
156 NTSTATUS
157 WDFAPI
158 WDFEXPORT(WdfUsbTargetPipeWriteSynchronously)(
159     __in
160     PWDF_DRIVER_GLOBALS DriverGlobals,
161     __in
162     WDFUSBPIPE Pipe,
163     __in_opt
164     WDFREQUEST Request,
165     __in_opt
166     PWDF_REQUEST_SEND_OPTIONS RequestOptions,
167     __in_opt
168     PWDF_MEMORY_DESCRIPTOR MemoryDescriptor,
169     __out_opt
170     PULONG BytesWritten
171     )
172 {
173     DDI_ENTRY();
174 
175     DoTraceLevelMessage(
176         GetFxDriverGlobals(DriverGlobals), TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
177         "WDFUSBPIPE %p", Pipe);
178 
179     return FxUsbPipe::_SendTransfer(GetFxDriverGlobals(DriverGlobals),
180                                     Pipe,
181                                     Request,
182                                     RequestOptions,
183                                     MemoryDescriptor,
184                                     BytesWritten,
185                                     0);
186 }
187 
188 _Must_inspect_result_
189 __drv_maxIRQL(DISPATCH_LEVEL)
190 NTSTATUS
191 WDFAPI
192 WDFEXPORT(WdfUsbTargetPipeFormatRequestForWrite)(
193     __in
194     PWDF_DRIVER_GLOBALS DriverGlobals,
195     __in
196     WDFUSBPIPE Pipe,
197     __in
198     WDFREQUEST Request,
199     __in_opt
200     WDFMEMORY WriteMemory,
201     __in_opt
202     PWDFMEMORY_OFFSET WriteOffsets
203     )
204 {
205     DDI_ENTRY();
206 
207     DoTraceLevelMessage(GetFxDriverGlobals(DriverGlobals), TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
208                         "WDFUSBPIPE %p, WDFREQUEST %p, WDFMEMORY %p",
209                         Pipe, Request, WriteMemory);
210 
211     return FxUsbPipe::_FormatTransfer(GetFxDriverGlobals(DriverGlobals),
212                                       Pipe,
213                                       Request,
214                                       WriteMemory,
215                                       WriteOffsets,
216                                       0);
217 }
218 
219 _Must_inspect_result_
220 __drv_maxIRQL(PASSIVE_LEVEL)
221 NTSTATUS
222 WDFAPI
223 WDFEXPORT(WdfUsbTargetPipeReadSynchronously)(
224     __in
225     PWDF_DRIVER_GLOBALS DriverGlobals,
226     __in
227     WDFUSBPIPE Pipe,
228     __in_opt
229     WDFREQUEST Request,
230     __in_opt
231     PWDF_REQUEST_SEND_OPTIONS RequestOptions,
232     __in_opt
233     PWDF_MEMORY_DESCRIPTOR MemoryDescriptor,
234     __out_opt
235     PULONG BytesRead
236     )
237 {
238     DDI_ENTRY();
239 
240     DoTraceLevelMessage(GetFxDriverGlobals(DriverGlobals), TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
241                         "WDFUSBPIPE %p", Pipe);
242 
243     return FxUsbPipe::_SendTransfer(
244         GetFxDriverGlobals(DriverGlobals),
245         Pipe,
246         Request,
247         RequestOptions,
248         MemoryDescriptor,
249         BytesRead,
250         USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK
251         );
252 }
253 
254 _Must_inspect_result_
255 __drv_maxIRQL(DISPATCH_LEVEL)
256 NTSTATUS
257 WDFAPI
258 WDFEXPORT(WdfUsbTargetPipeFormatRequestForRead)(
259     __in
260     PWDF_DRIVER_GLOBALS DriverGlobals,
261     __in
262     WDFUSBPIPE Pipe,
263     __in
264     WDFREQUEST Request,
265     __in_opt
266     WDFMEMORY ReadMemory,
267     __in_opt
268     PWDFMEMORY_OFFSET ReadOffsets
269     )
270 {
271     DDI_ENTRY();
272 
273     DoTraceLevelMessage(
274         GetFxDriverGlobals(DriverGlobals), TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
275         "WDFUSBPIPE %p, WDFREQUEST %p, WDFMEMORY %p",
276         Pipe, Request, ReadMemory);
277 
278     return FxUsbPipe::_FormatTransfer(
279         GetFxDriverGlobals(DriverGlobals),
280         Pipe,
281         Request,
282         ReadMemory,
283         ReadOffsets,
284         USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK
285         );
286 }
287 
288 _Must_inspect_result_
289 __drv_maxIRQL(DISPATCH_LEVEL)
290 NTSTATUS
291 WDFAPI
292 WDFEXPORT(WdfUsbTargetPipeConfigContinuousReader)(
293     __in
294     PWDF_DRIVER_GLOBALS DriverGlobals,
295     __in
296     WDFUSBPIPE Pipe,
297     __in
298     PWDF_USB_CONTINUOUS_READER_CONFIG Config
299     )
300 {
301     DDI_ENTRY();
302 
303     PFX_DRIVER_GLOBALS pFxDriverGlobals;
304     FxUsbPipe* pUsbPipe;
305     NTSTATUS status;
306     size_t total;
307 
308     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
309                                    Pipe,
310                                    FX_TYPE_IO_TARGET_USB_PIPE,
311                                    (PVOID*) &pUsbPipe,
312                                    &pFxDriverGlobals);
313 
314     FxPointerNotNull(pFxDriverGlobals, Config);
315 
316     if (Config->Size != sizeof(WDF_USB_CONTINUOUS_READER_CONFIG)) {
317         status = STATUS_INFO_LENGTH_MISMATCH;
318 
319         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
320                             "Config %p incorrect size %d, expected %d %!STATUS!",
321                             Config, Config->Size, sizeof(WDF_USB_CONTINUOUS_READER_CONFIG),
322                             status);
323 
324         return status;
325     }
326 
327     if (Config->EvtUsbTargetPipeReadComplete == NULL) {
328         status = STATUS_INVALID_PARAMETER;
329         DoTraceLevelMessage(
330             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
331             "NULL EvtUsbTargetPipeReadComplete not allowed %!STATUS!", status);
332         return status;
333     }
334 
335     if (Config->TransferLength == 0) {
336         status = STATUS_INVALID_PARAMETER;
337         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
338                             "TransferLength of 0 not allowed %!STATUS!", status);
339         return status;
340     }
341 
342     status = RtlSizeTAdd(Config->HeaderLength,
343                          Config->TransferLength,
344                          &total);
345 
346     if (!NT_SUCCESS(status)) {
347         DoTraceLevelMessage(
348             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
349             "HeaderLength + TransferLength overflow %!STATUS!", status);
350         return status;
351     }
352 
353     status = RtlSizeTAdd(total,
354                          Config->TrailerLength,
355                          &total);
356 
357     if (!NT_SUCCESS(status)) {
358         DoTraceLevelMessage(
359             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
360             "HeaderLength + TransferLength + TrailerLength overflow %!STATUS!",
361             status);
362         return status;
363     }
364 
365     //
366     // Internally WDF will assign a parent to the memory, so do not allow the driver
367     // to do so.
368     //
369     status = FxValidateObjectAttributes(pFxDriverGlobals,
370                                         Config->BufferAttributes,
371                                         FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED);
372     if (!NT_SUCCESS(status)) {
373         return status;
374     }
375 
376     //
377     // Only bulk or interrrupt is allowed for a continous reader
378     //
379     if ((pUsbPipe->IsType(WdfUsbPipeTypeBulk) ||
380          pUsbPipe->IsType(WdfUsbPipeTypeInterrupt)) == FALSE) {
381         status = STATUS_INVALID_DEVICE_REQUEST;
382 
383         DoTraceLevelMessage(
384             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
385             "WDFUSBPIPE %p type %!WDF_USB_PIPE_TYPE!, only bulk or interrupt "
386             "pipes can be configured for continous readers, %!STATUS!",
387             Pipe, pUsbPipe->GetType(), status);
388 
389         return status;
390     }
391 
392     if (pUsbPipe->IsOutEndpoint()) {
393         status = STATUS_INVALID_DEVICE_REQUEST;
394 
395         DoTraceLevelMessage(
396             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
397             "WDFUSBPIPE %p, wrong direction for continuous reader, %!STATUS!",
398             Pipe, status);
399 
400         return status;
401     }
402 
403     status = pUsbPipe->ValidateTransferLength(Config->TransferLength);
404     if (!NT_SUCCESS(status)) {
405         DoTraceLevelMessage(
406             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
407             "TransferLength %I64d not a valid transer length (not integral of max "
408             "packet size %d) %!STATUS!", Config->TransferLength,
409             pUsbPipe->GetMaxPacketSize(), status);
410         return status;
411     }
412 
413     status = pUsbPipe->InitContinuousReader(Config, total);
414 
415     return status;
416 }
417 
418 _Must_inspect_result_
419 __drv_maxIRQL(PASSIVE_LEVEL)
420 NTSTATUS
421 WDFAPI
422 WDFEXPORT(WdfUsbTargetPipeAbortSynchronously)(
423     __in
424     PWDF_DRIVER_GLOBALS DriverGlobals,
425     __in
426     WDFUSBPIPE Pipe,
427     __in_opt
428     WDFREQUEST Request,
429     __in_opt
430     PWDF_REQUEST_SEND_OPTIONS RequestOptions
431     )
432 {
433     DDI_ENTRY();
434 
435     PFX_DRIVER_GLOBALS pFxDriverGlobals;
436     FxUsbPipe* pUsbPipe;
437     NTSTATUS status;
438 
439     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
440                                    Pipe,
441                                    FX_TYPE_IO_TARGET_USB_PIPE,
442                                    (PVOID*) &pUsbPipe,
443                                    &pFxDriverGlobals);
444 
445     FxUsbPipeRequestContext context(FxUrbTypeLegacy);
446 
447     FxSyncRequest request(pFxDriverGlobals, &context, Request);
448 
449     //
450     // FxSyncRequest always succeesds for KM but can fail for UM.
451     //
452     status = request.Initialize();
453     if (!NT_SUCCESS(status)) {
454         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
455                             "Failed to initialize FxSyncRequest");
456         return status;
457     }
458 
459     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
460                         "Pipe %p", Pipe);
461 
462     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
463     if (!NT_SUCCESS(status)) {
464         return status;
465     }
466 
467     status = FxValidateRequestOptions(pFxDriverGlobals, RequestOptions);
468     if (!NT_SUCCESS(status)) {
469         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
470                             "Invalid request options");
471         return status;
472     }
473 
474     status = pUsbPipe->FormatAbortRequest(request.m_TrueRequest);
475     if (NT_SUCCESS(status)) {
476         DoTraceLevelMessage(
477             pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
478             "WDFUSBPIPE %p, WDFREQUEST %p being submitted",
479             Pipe, request.m_TrueRequest->GetTraceObjectHandle());
480 
481         status = pUsbPipe->SubmitSync(request.m_TrueRequest, RequestOptions);
482     }
483 
484     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
485                         "WDFUSBPIPE %p, %!STATUS!", Pipe, status);
486 
487     return status;
488 }
489 
490 _Must_inspect_result_
491 __drv_maxIRQL(DISPATCH_LEVEL)
492 NTSTATUS
493 WDFAPI
494 WDFEXPORT(WdfUsbTargetPipeFormatRequestForAbort)(
495     __in
496     PWDF_DRIVER_GLOBALS DriverGlobals,
497     __in
498     WDFUSBPIPE Pipe,
499     __in
500     WDFREQUEST Request
501     )
502 {
503     DDI_ENTRY();
504 
505     PFX_DRIVER_GLOBALS pFxDriverGlobals;
506     FxRequest* pRequest;
507     FxUsbPipe* pUsbPipe;
508     NTSTATUS status;
509 
510     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
511                                    Pipe,
512                                    FX_TYPE_IO_TARGET_USB_PIPE,
513                                    (PVOID*) &pUsbPipe,
514                                    &pFxDriverGlobals);
515 
516     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
517                         "Pipe %p, Request %p", Pipe, Request);
518 
519     FxObjectHandleGetPtr(pFxDriverGlobals,
520                          Request,
521                          FX_TYPE_REQUEST,
522                          (PVOID*) &pRequest);
523 
524     status = pUsbPipe->FormatAbortRequest(pRequest);
525 
526     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
527                         "Pipe %p, Request %p, status %!STATUS!",
528                         Pipe, Request, status);
529 
530     return status;
531 }
532 
533 _Must_inspect_result_
534 __drv_maxIRQL(PASSIVE_LEVEL)
535 NTSTATUS
536 WDFAPI
537 WDFEXPORT(WdfUsbTargetPipeResetSynchronously)(
538     __in
539     PWDF_DRIVER_GLOBALS DriverGlobals,
540     __in
541     WDFUSBPIPE Pipe,
542     __in_opt
543     WDFREQUEST Request,
544     __in_opt
545     PWDF_REQUEST_SEND_OPTIONS RequestOptions
546     )
547 {
548     DDI_ENTRY();
549 
550     PFX_DRIVER_GLOBALS pFxDriverGlobals;
551     FxUsbPipe* pUsbPipe;
552     NTSTATUS status;
553 
554     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
555                                    Pipe,
556                                    FX_TYPE_IO_TARGET_USB_PIPE,
557                                    (PVOID*) &pUsbPipe,
558                                    &pFxDriverGlobals);
559 
560     FxUsbPipeRequestContext context(FxUrbTypeLegacy);
561 
562     FxSyncRequest request(pFxDriverGlobals, &context, Request);
563 
564     //
565     // FxSyncRequest always succeesds for KM but can fail for UM.
566     //
567     status = request.Initialize();
568     if (!NT_SUCCESS(status)) {
569         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
570                             "Failed to initialize FxSyncRequest");
571         return status;
572     }
573 
574     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
575                         "WDFUSBPIPE %p reset", Pipe);
576 
577     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
578     if (!NT_SUCCESS(status)) {
579         return status;
580     }
581 
582     status = FxValidateRequestOptions(pFxDriverGlobals, RequestOptions);
583     if (!NT_SUCCESS(status)) {
584         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
585                             "Invalid request options");
586         return status;
587     }
588 
589     status = pUsbPipe->FormatResetRequest(request.m_TrueRequest);
590 
591     if (NT_SUCCESS(status)) {
592         DoTraceLevelMessage(
593             pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
594             "WDFUSBPIPE %p, WDFREQUEST %p being submitted",
595             Pipe,  request.m_TrueRequest->GetTraceObjectHandle());
596 
597         pUsbPipe->CancelSentIo();
598 
599         //
600         // Even if the previous state of the target was stopped let this IO go through by
601         // ignoring target state.
602         //
603         status = pUsbPipe->SubmitSyncRequestIgnoreTargetState(request.m_TrueRequest, RequestOptions);
604     }
605 
606     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
607                         "WDFUSBPIPE %p reset, %!STATUS!", Pipe, status);
608 
609     return status;
610 }
611 
612 _Must_inspect_result_
613 __drv_maxIRQL(DISPATCH_LEVEL)
614 NTSTATUS
615 WDFAPI
616 WDFEXPORT(WdfUsbTargetPipeFormatRequestForReset)(
617     __in
618     PWDF_DRIVER_GLOBALS DriverGlobals,
619     __in
620     WDFUSBPIPE Pipe,
621     __in
622     WDFREQUEST Request
623     )
624 {
625     DDI_ENTRY();
626 
627     PFX_DRIVER_GLOBALS pFxDriverGlobals;
628     FxRequest* pRequest;
629     FxUsbPipe* pUsbPipe;
630     NTSTATUS status;
631 
632     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
633                                    Pipe,
634                                    FX_TYPE_IO_TARGET_USB_PIPE,
635                                    (PVOID*) &pUsbPipe,
636                                    &pFxDriverGlobals);
637 
638     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
639                         "Pipe %p, Request %p", Pipe, Request);
640 
641     FxObjectHandleGetPtr(pFxDriverGlobals,
642                          Request,
643                          FX_TYPE_REQUEST,
644                          (PVOID*) &pRequest);
645 
646     status = pUsbPipe->FormatResetRequest(pRequest);
647 
648     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
649                         "Pipe %p, Request %p = 0x%x",
650                         Pipe, Request, status);
651 
652     return status;
653 }
654 
655 _Must_inspect_result_
656 __drv_maxIRQL(PASSIVE_LEVEL)
657 NTSTATUS
658 WDFAPI
659 WDFEXPORT(WdfUsbTargetPipeSendUrbSynchronously)(
660     __in
661     PWDF_DRIVER_GLOBALS DriverGlobals,
662     __in
663     WDFUSBPIPE Pipe,
664     __in_opt
665     WDFREQUEST Request,
666     __in_opt
667     PWDF_REQUEST_SEND_OPTIONS RequestOptions,
668     __in_xcount("union bug in SAL")
669     PURB Urb
670     )
671 {
672     DDI_ENTRY();
673 
674     FxRequestBuffer buf;
675     PFX_DRIVER_GLOBALS pFxDriverGlobals;
676     FxUsbPipe* pUsbPipe;
677     NTSTATUS status;
678 
679     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
680                                    Pipe,
681                                    FX_TYPE_IO_TARGET_USB_PIPE,
682                                    (PVOID*) &pUsbPipe,
683                                    &pFxDriverGlobals);
684 
685     FxUsbUrbContext context;
686     FxSyncRequest request(pFxDriverGlobals, &context, Request);
687 
688     //
689     // FxSyncRequest always succeesds for KM but can fail for UM.
690     //
691     status = request.Initialize();
692     if (!NT_SUCCESS(status)) {
693         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
694                             "Failed to initialize FxSyncRequest");
695         return status;
696     }
697 
698     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
699                         "WDFUSBPIPE %p, Urb %p", Pipe, Urb);
700 
701     FxPointerNotNull(pFxDriverGlobals, Urb);
702 
703     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
704     if (!NT_SUCCESS(status)) {
705         return status;
706     }
707 
708     status = FxValidateRequestOptions(pFxDriverGlobals, RequestOptions);
709     if (!NT_SUCCESS(status)) {
710         return status;
711     }
712 
713     buf.SetBuffer(Urb, 0);
714 
715     status = FxFormatUrbRequest(pFxDriverGlobals,
716                                 pUsbPipe,
717                                 request.m_TrueRequest,
718                                 &buf,
719                                 pUsbPipe->GetUrbType(),
720                                 pUsbPipe->GetUSBDHandle());
721 
722     if (NT_SUCCESS(status)) {
723         DoTraceLevelMessage(
724             pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
725             "WDFUSBPIPE %p, WDFREQUEST %p being submitted",
726             Pipe,  request.m_TrueRequest->GetTraceObjectHandle());
727 
728         status = pUsbPipe->SubmitSync(request.m_TrueRequest, RequestOptions);
729     }
730 
731     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
732                         "WDFUSBPIPE %p, Urb %p, %!STATUS!",
733                         Pipe, Urb, status);
734 
735     return status;
736 }
737 
738 _Must_inspect_result_
739 __drv_maxIRQL(DISPATCH_LEVEL)
740 NTSTATUS
741 WDFAPI
742 WDFEXPORT(WdfUsbTargetPipeFormatRequestForUrb)(
743     __in
744     PWDF_DRIVER_GLOBALS DriverGlobals,
745     __in
746     WDFUSBPIPE Pipe,
747     __in
748     WDFREQUEST Request,
749     __in
750     WDFMEMORY UrbMemory,
751     __in_opt
752     PWDFMEMORY_OFFSET UrbOffsets
753     )
754 {
755     DDI_ENTRY();
756 
757     PFX_DRIVER_GLOBALS pFxDriverGlobals;
758     IFxMemory* pMemory;
759     FxUsbPipe* pUsbPipe;
760     FxRequest* pRequest;
761     FxRequestBuffer buf;
762     NTSTATUS status;
763     size_t bufferSize;
764 
765     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
766                                    Pipe,
767                                    FX_TYPE_IO_TARGET_USB_PIPE,
768                                    (PVOID*) &pUsbPipe,
769                                    &pFxDriverGlobals);
770 
771     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
772                         "Pipe %p, Request %p, Memory %p",
773                         Pipe, Request, UrbMemory);
774 
775     FxObjectHandleGetPtr(pFxDriverGlobals,
776                          UrbMemory,
777                          IFX_TYPE_MEMORY,
778                          (PVOID*) &pMemory);
779 
780     FxObjectHandleGetPtr(pFxDriverGlobals,
781                          Request,
782                          FX_TYPE_REQUEST,
783                          (PVOID*) &pRequest);
784 
785     status = pMemory->ValidateMemoryOffsets(UrbOffsets);
786     if (!NT_SUCCESS(status)) {
787         return status;
788     }
789 
790     bufferSize = pMemory->GetBufferSize();
791     if (UrbOffsets != NULL && UrbOffsets->BufferOffset > 0) {
792         bufferSize -= UrbOffsets->BufferOffset;
793     }
794 
795     if (bufferSize < sizeof(_URB_HEADER)) {
796         status = STATUS_INVALID_PARAMETER;
797         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
798                             "UrbMemory %p buffer size, %I64d, smaller then "
799                             "_URB_HEADER, %!STATUS!", UrbMemory,
800                             pMemory->GetBufferSize(), status);
801         return status;
802     }
803 
804     buf.SetMemory(pMemory, UrbOffsets);
805 
806     status = FxFormatUrbRequest(pFxDriverGlobals,
807                                 pUsbPipe,
808                                 pRequest,
809                                 &buf,
810                                 pUsbPipe->GetUrbType(),
811                                 pUsbPipe->GetUSBDHandle());
812 
813     if (NT_SUCCESS(status)) {
814         FxUsbUrbContext* pContext;
815         pContext = (FxUsbUrbContext*) pRequest->GetContext();
816 
817         pContext->SetUsbType(WdfUsbRequestTypePipeUrb);
818         pContext->m_UsbParameters.Parameters.PipeUrb.Buffer = UrbMemory;
819     }
820 
821     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
822                         "Pipe %p, Request %p, Memory %p, status %!STATUS!",
823                         Pipe, Request, UrbMemory, status);
824 
825     return status;
826 }
827 
828 __drv_maxIRQL(DISPATCH_LEVEL)
829 USBD_PIPE_HANDLE
830 WDFAPI
831 WDFEXPORT(WdfUsbTargetPipeWdmGetPipeHandle)(
832     __in
833     PWDF_DRIVER_GLOBALS DriverGlobals,
834     __in
835     WDFUSBPIPE UsbPipe
836     )
837 /*++
838 
839 Routine Description:
840     Returns the underlying WDM USBD pipe handle
841 
842 Arguments:
843     UsbPipe - the WDF pipe whose WDM handle will be returned
844 
845 Return Value:
846     valid handle value or NULL on error
847 
848   --*/
849 {
850     DDI_ENTRY();
851 
852     FxUsbPipe* pUsbPipe;
853 
854     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
855                          UsbPipe,
856                          FX_TYPE_IO_TARGET_USB_PIPE,
857                          (PVOID*) &pUsbPipe);
858 
859     return pUsbPipe->WdmGetPipeHandle();
860 }
861 
862 } // extern "C"
863