1 /*++ 2 3 Copyright (c) Microsoft Corporation 4 5 Module Name: 6 7 FxUsbDeviceAPI.cpp 8 9 Abstract: 10 11 12 Author: 13 14 Environment: 15 16 kernel mode only 17 18 Revision History: 19 20 --*/ 21 22 #include "fxusbpch.hpp" 23 24 extern "C" { 25 #include "FxUsbDeviceApiKm.tmh" 26 } 27 28 // 29 // Extern "C" all APIs 30 // 31 extern "C" { 32 33 _Must_inspect_result_ 34 __drv_maxIRQL(DISPATCH_LEVEL) 35 NTSTATUS 36 WDFAPI 37 WDFEXPORT(WdfUsbTargetDeviceRetrieveCurrentFrameNumber)( 38 __in 39 PWDF_DRIVER_GLOBALS DriverGlobals, 40 __in 41 WDFUSBDEVICE UsbDevice, 42 __out 43 PULONG CurrentFrameNumber 44 ) 45 { 46 DDI_ENTRY(); 47 48 PFX_DRIVER_GLOBALS pFxDriverGlobals; 49 FxUsbDevice* pUsbDevice; 50 51 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 52 UsbDevice, 53 FX_TYPE_IO_TARGET_USB_DEVICE, 54 (PVOID*) &pUsbDevice, 55 &pFxDriverGlobals); 56 57 FxPointerNotNull(pFxDriverGlobals, CurrentFrameNumber); 58 59 return pUsbDevice->GetCurrentFrameNumber(CurrentFrameNumber); 60 } 61 62 _Must_inspect_result_ 63 __drv_maxIRQL(PASSIVE_LEVEL) 64 NTSTATUS 65 WDFAPI 66 WDFEXPORT(WdfUsbTargetDeviceSendUrbSynchronously)( 67 __in 68 PWDF_DRIVER_GLOBALS DriverGlobals, 69 __in 70 WDFUSBDEVICE UsbDevice, 71 __in_opt 72 WDFREQUEST Request, 73 __in_opt 74 PWDF_REQUEST_SEND_OPTIONS RequestOptions, 75 __in_xcount("union bug in SAL") 76 PURB Urb 77 ) 78 { 79 PFX_DRIVER_GLOBALS pFxDriverGlobals; 80 FxRequestBuffer buf; 81 NTSTATUS status; 82 FxUsbDevice* pUsbDevice; 83 84 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 85 UsbDevice, 86 FX_TYPE_IO_TARGET_USB_DEVICE, 87 (PVOID*) &pUsbDevice, 88 &pFxDriverGlobals); 89 90 FxUsbUrbContext context; 91 FxSyncRequest request(pFxDriverGlobals, &context, Request); 92 93 // 94 // FxSyncRequest always succeesds for KM but can fail for UM. 95 // 96 status = request.Initialize(); 97 if (!NT_SUCCESS(status)) { 98 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, 99 "Failed to initialize FxSyncRequest"); 100 return status; 101 } 102 103 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET, 104 "WDFUSBDEVICE %p, Urb %p", UsbDevice, Urb); 105 106 FxPointerNotNull(pFxDriverGlobals, Urb); 107 108 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 109 if (!NT_SUCCESS(status)) { 110 return status; 111 } 112 113 status = FxValidateRequestOptions(pFxDriverGlobals, RequestOptions); 114 if (!NT_SUCCESS(status)) { 115 return status; 116 } 117 118 buf.SetBuffer(Urb, 0); 119 120 status = FxFormatUrbRequest(pFxDriverGlobals, 121 pUsbDevice, 122 request.m_TrueRequest, 123 &buf, 124 pUsbDevice->GetUrbType(), 125 pUsbDevice->GetUSBDHandle()); 126 127 if (NT_SUCCESS(status)) { 128 DoTraceLevelMessage( 129 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET, 130 "WDFUSBDEVICE %p, WDFREQUEST %p being submitted", 131 UsbDevice, request.m_TrueRequest->GetTraceObjectHandle()); 132 133 status = pUsbDevice->SubmitSync(request.m_TrueRequest, RequestOptions); 134 } 135 136 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET, 137 "Device %p, Urb %p, %!STATUS!", 138 UsbDevice, Urb, status); 139 140 return status; 141 } 142 143 _Must_inspect_result_ 144 __drv_maxIRQL(DISPATCH_LEVEL) 145 NTSTATUS 146 WDFAPI 147 WDFEXPORT(WdfUsbTargetDeviceFormatRequestForUrb)( 148 __in 149 PWDF_DRIVER_GLOBALS DriverGlobals, 150 __in 151 WDFUSBDEVICE UsbDevice, 152 __in 153 WDFREQUEST Request, 154 __in 155 WDFMEMORY UrbMemory, 156 __in_opt 157 PWDFMEMORY_OFFSET UrbOffsets 158 ) 159 { 160 DDI_ENTRY(); 161 162 PFX_DRIVER_GLOBALS pFxDriverGlobals; 163 IFxMemory* pMemory; 164 FxUsbDevice* pUsbDevice; 165 FxRequestBuffer buf; 166 FxRequest* pRequest; 167 NTSTATUS status; 168 size_t bufferSize; 169 170 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 171 UsbDevice, 172 FX_TYPE_IO_TARGET_USB_DEVICE, 173 (PVOID*) &pUsbDevice, 174 &pFxDriverGlobals); 175 176 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET, 177 "WDFUSBDEVICE %p, Request %p, Memory %p", 178 UsbDevice, Request, UrbMemory); 179 180 FxPointerNotNull(pFxDriverGlobals, UrbMemory); 181 182 FxObjectHandleGetPtr(pFxDriverGlobals, 183 UrbMemory, 184 IFX_TYPE_MEMORY, 185 (PVOID*) &pMemory); 186 187 FxObjectHandleGetPtr(pFxDriverGlobals, 188 Request, 189 FX_TYPE_REQUEST, 190 (PVOID*) &pRequest); 191 192 status = pMemory->ValidateMemoryOffsets(UrbOffsets); 193 if (!NT_SUCCESS(status)) { 194 return status; 195 } 196 197 bufferSize = pMemory->GetBufferSize(); 198 if (UrbOffsets != NULL && UrbOffsets->BufferOffset > 0) { 199 bufferSize -= UrbOffsets->BufferOffset; 200 } 201 202 if (bufferSize < sizeof(_URB_HEADER)) { 203 status = STATUS_INVALID_PARAMETER; 204 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, 205 "UrbMemory %p buffer size, %I64d, smaller then" 206 "_URB_HEADER, %!STATUS!", 207 UrbMemory, pMemory->GetBufferSize(), status); 208 return status; 209 } 210 211 buf.SetMemory(pMemory, UrbOffsets); 212 213 status = FxFormatUrbRequest(pFxDriverGlobals, 214 pUsbDevice, 215 pRequest, 216 &buf, 217 pUsbDevice->GetUrbType(), 218 pUsbDevice->GetUSBDHandle()); 219 220 if (NT_SUCCESS(status)) { 221 FxUsbUrbContext* pContext; 222 pContext = (FxUsbUrbContext*) pRequest->GetContext(); 223 224 pContext->SetUsbType(WdfUsbRequestTypeDeviceUrb); 225 pContext->m_UsbParameters.Parameters.DeviceUrb.Buffer = UrbMemory; 226 } 227 228 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET, 229 "WDFUSBDEVICE %p, Request %p, Memory %p, %!STATUS!", 230 UsbDevice, Request, UrbMemory, status); 231 232 return status; 233 } 234 235 _Must_inspect_result_ 236 __drv_maxIRQL(PASSIVE_LEVEL) 237 NTSTATUS 238 WDFAPI 239 WDFEXPORT(WdfUsbTargetDeviceIsConnectedSynchronous)( 240 __in 241 PWDF_DRIVER_GLOBALS DriverGlobals, 242 __in 243 WDFUSBDEVICE UsbDevice 244 ) 245 { 246 DDI_ENTRY(); 247 248 PFX_DRIVER_GLOBALS pFxDriverGlobals; 249 FxUsbDevice* pUsbDevice; 250 NTSTATUS status; 251 252 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 253 UsbDevice, 254 FX_TYPE_IO_TARGET_USB_DEVICE, 255 (PVOID*) &pUsbDevice, 256 &pFxDriverGlobals); 257 258 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 259 if (!NT_SUCCESS(status)) { 260 return status; 261 } 262 263 status = pUsbDevice->IsConnected(); 264 265 return status; 266 } 267 268 _Must_inspect_result_ 269 __drv_maxIRQL(PASSIVE_LEVEL) 270 NTSTATUS 271 WDFEXPORT(WdfUsbTargetDeviceCyclePortSynchronously)( 272 __in 273 PWDF_DRIVER_GLOBALS DriverGlobals, 274 __in 275 WDFUSBDEVICE UsbDevice 276 ) 277 /*++ 278 279 Routine Description: 280 Synchronously cycles a device on a USB port. This will cause the device 281 to be surprise removed and reenumerated. Very similar to the reenumerate 282 interface we use in the pnp state machine. Usually a driver will do this 283 after it has downloaded firmware and wants to be reenumerated as a new 284 device. 285 286 287 288 289 Arguments: 290 UsbDevice - the IOTARGET representing the device 291 292 Return Value: 293 NTSTATUS 294 295 --*/ 296 { 297 DDI_ENTRY(); 298 299 PFX_DRIVER_GLOBALS pFxDriverGlobals; 300 FxUsbDevice* pUsbDevice; 301 NTSTATUS status; 302 303 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 304 UsbDevice, 305 FX_TYPE_IO_TARGET_USB_DEVICE, 306 (PVOID*) &pUsbDevice, 307 &pFxDriverGlobals); 308 309 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 310 if (!NT_SUCCESS(status)) { 311 return status; 312 } 313 314 status = pUsbDevice->CyclePort(); 315 316 return status; 317 } 318 319 _Must_inspect_result_ 320 __drv_maxIRQL(DISPATCH_LEVEL) 321 NTSTATUS 322 WDFEXPORT(WdfUsbTargetDeviceFormatRequestForCyclePort)( 323 __in 324 PWDF_DRIVER_GLOBALS DriverGlobals, 325 __in 326 WDFUSBDEVICE UsbDevice, 327 __in 328 WDFREQUEST Request 329 ) 330 /*++ 331 332 Routine Description: 333 Formats a WDFREQUEST so that it will cycle the port and reenumerate the 334 device when sent. 335 336 Arguments: 337 UsbDevice - the IOTARGET representing the device that will be reenumerated 338 339 Request - the request which will be formatted 340 341 Return Value: 342 NTSTATUS 343 344 --*/ 345 { 346 DDI_ENTRY(); 347 348 PFX_DRIVER_GLOBALS pFxDriverGlobals; 349 FxUsbDevice* pUsbDevice; 350 FxRequest* pRequest; 351 NTSTATUS status; 352 353 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 354 UsbDevice, 355 FX_TYPE_IO_TARGET_USB_DEVICE, 356 (PVOID*) &pUsbDevice, 357 &pFxDriverGlobals); 358 359 FxObjectHandleGetPtr(pFxDriverGlobals, 360 Request, 361 FX_TYPE_REQUEST, 362 (PVOID*) &pRequest); 363 364 status = pUsbDevice->FormatCycleRequest(pRequest); 365 366 return status; 367 } 368 369 __checkReturn 370 __drv_maxIRQL(DISPATCH_LEVEL) 371 NTSTATUS 372 WDFAPI 373 WDFEXPORT(WdfUsbTargetDeviceCreateUrb)( 374 __in 375 PWDF_DRIVER_GLOBALS DriverGlobals, 376 __in 377 WDFUSBDEVICE UsbDevice, 378 __in_opt 379 PWDF_OBJECT_ATTRIBUTES Attributes, 380 __out 381 WDFMEMORY* UrbMemory, 382 __deref_opt_out_bcount(sizeof(URB)) 383 PURB* Urb 384 ) 385 /*++ 386 387 Routine Description: 388 Creates a WDFUSBDEVICE handle for the client. 389 390 Arguments: 391 Attributes - Attributes associated with this object 392 393 UrbMemory - The returned handle to the caller for the allocated Urb 394 395 Urb - (opt) Pointer to the associated urb buffer. 396 397 Return Value: 398 STATUS_INVALID_PARAMETER - any required parameters are not present/invalid 399 400 STATUS_INVALID_DEVICE_STATE - If the client did not specify a client contract verion while 401 creating the WDFUSBDEVICE 402 403 STATUS_INSUFFICIENT_RESOURCES - could not allocated the object that backs 404 the handle 405 406 STATUS_SUCCESS - success 407 408 ... 409 410 --*/ 411 { 412 DDI_ENTRY(); 413 414 PFX_DRIVER_GLOBALS pFxDriverGlobals; 415 FxUsbDevice* pUsbDevice; 416 NTSTATUS status; 417 418 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 419 UsbDevice, 420 FX_TYPE_IO_TARGET_USB_DEVICE, 421 (PVOID*) &pUsbDevice, 422 &pFxDriverGlobals); 423 424 // 425 // Basic parameter validation 426 // 427 FxPointerNotNull(pFxDriverGlobals, UrbMemory); 428 429 if (pUsbDevice->GetUSBDHandle() == NULL) { 430 status = STATUS_INVALID_DEVICE_STATE; 431 432 DoTraceLevelMessage( 433 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, 434 "USBDEVICE Must have been created with Client Contract Verion Info, %!STATUS!", 435 status); 436 437 return status; 438 } 439 440 status = pUsbDevice->CreateUrb(Attributes, UrbMemory, Urb); 441 442 return status; 443 } 444 445 } // extern "C" 446