Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1521 lines
53 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. usb.c
  5. Author:
  6. ervinp
  7. Environment:
  8. Kernel mode
  9. Revision History:
  10. --*/
  11. #include <wdm.h>
  12. #include <usbdi.h>
  13. #include <usbdlib.h>
  14. #include <usbioctl.h>
  15. #include "usb8023.h"
  16. #include "debug.h"
  17. /*
  18. * USB- and WDM- specific prototypes (won't compile in common header)
  19. */
  20. NTSTATUS SubmitUrb(PDEVICE_OBJECT pdo, PURB urb, BOOLEAN synchronous, PVOID completionRoutine, PVOID completionContext);
  21. NTSTATUS SubmitUrbIrp(PDEVICE_OBJECT pdo, PIRP irp, PURB urb, BOOLEAN synchronous, PVOID completionRoutine, PVOID completionContext);
  22. NTSTATUS CallDriverSync(PDEVICE_OBJECT devObj, PIRP irp);
  23. NTSTATUS CallDriverSyncCompletion(IN PDEVICE_OBJECT devObjOrNULL, IN PIRP irp, IN PVOID context);
  24. NTSTATUS ReadPipeCompletion(IN PDEVICE_OBJECT devObj, IN PIRP irp, IN PVOID context);
  25. NTSTATUS WritePipeCompletion(IN PDEVICE_OBJECT devObj, IN PIRP irp, IN PVOID context);
  26. NTSTATUS NotificationCompletion(IN PDEVICE_OBJECT devObj, IN PIRP irp, IN PVOID context);
  27. NTSTATUS ControlPipeWriteCompletion(IN PDEVICE_OBJECT devObj, IN PIRP irp, IN PVOID context);
  28. NTSTATUS ControlPipeReadCompletion(IN PDEVICE_OBJECT devObj, IN PIRP irp, IN PVOID context);
  29. BOOLEAN InitUSB(ADAPTEREXT *adapter)
  30. /*++
  31. Routine Description:
  32. Intialize USB-related data
  33. Arguments:
  34. adapter - adapter context
  35. Return Value:
  36. TRUE iff successful
  37. --*/
  38. {
  39. NTSTATUS status;
  40. BOOLEAN result = FALSE;
  41. status = GetDeviceDescriptor(adapter);
  42. if (NT_SUCCESS(status)){
  43. PUSB_DEVICE_DESCRIPTOR deviceDesc = adapter->deviceDesc;
  44. if (deviceDesc->bDeviceClass == USB_DEVICE_CLASS_CDC){
  45. status = GetConfigDescriptor(adapter);
  46. if (NT_SUCCESS(status)){
  47. status = SelectConfiguration(adapter);
  48. if (NT_SUCCESS(status)){
  49. /*
  50. * Find the read and write pipe handles.
  51. */
  52. status = FindUSBPipeHandles(adapter);
  53. if (NT_SUCCESS(status)){
  54. /*
  55. * Now that we know the notify length,
  56. * initialize structures for reading the notify pipe.
  57. * Add some buffer space for a guard word.
  58. */
  59. adapter->notifyBuffer = AllocPool(adapter->notifyPipeLength+sizeof(ULONG));
  60. adapter->notifyIrpPtr = IoAllocateIrp(adapter->nextDevObj->StackSize, FALSE);
  61. adapter->notifyUrbPtr = AllocPool(sizeof(URB));
  62. if (adapter->notifyBuffer && adapter->notifyIrpPtr && adapter->notifyUrbPtr){
  63. KeInitializeEvent(&adapter->notifyCancelEvent, NotificationEvent, FALSE);
  64. adapter->cancellingNotify = FALSE;
  65. }
  66. else {
  67. /*
  68. * Alloc failure. Memory will be cleaned up by FreeAdapter().
  69. */
  70. status = STATUS_INSUFFICIENT_RESOURCES;
  71. }
  72. if (NT_SUCCESS(status)){
  73. result = TRUE;
  74. }
  75. else {
  76. /*
  77. * Alloc failure. Memory will be cleaned up by FreeAdapter().
  78. */
  79. DBGERR(("Couldn't allocate notify structs"));
  80. }
  81. }
  82. }
  83. }
  84. }
  85. else {
  86. DBGERR(("InitUSB: device descriptor has wrong bDeviceClass==%xh.", (ULONG)deviceDesc->bDeviceClass));
  87. status = STATUS_DEVICE_DATA_ERROR;
  88. }
  89. }
  90. return result;
  91. }
  92. VOID StartUSBReadLoop(ADAPTEREXT *adapter)
  93. {
  94. ULONG i;
  95. for (i = 0; i < NUM_READ_PACKETS; i++){
  96. TryReadUSB(adapter);
  97. }
  98. }
  99. VOID TryReadUSB(ADAPTEREXT *adapter)
  100. {
  101. KIRQL oldIrql;
  102. /*
  103. * ReadPipeCompletion re-issues a read irp directly via this function.
  104. * Ordinarily the hardware can't keep up fast enough to
  105. * make us loop, but this check forces an unwind in extenuating circumstances.
  106. */
  107. if (InterlockedIncrement(&adapter->readReentrancyCount) > 3){
  108. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  109. adapter->readDeficit++;
  110. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  111. QueueAdapterWorkItem(adapter);
  112. DBGWARN(("TryReadUSB: reentered %d times, aborting to prevent stack overflow", adapter->readReentrancyCount));
  113. }
  114. else {
  115. USBPACKET *packet = DequeueFreePacket(adapter);
  116. if (packet){
  117. NTSTATUS status;
  118. EnqueuePendingReadPacket(packet);
  119. status = SubmitUSBReadPacket(packet);
  120. }
  121. else {
  122. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  123. adapter->readDeficit++;
  124. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  125. QueueAdapterWorkItem(adapter);
  126. }
  127. }
  128. InterlockedDecrement(&adapter->readReentrancyCount);
  129. }
  130. NTSTATUS GetDeviceDescriptor(ADAPTEREXT *adapter)
  131. /*++
  132. Routine Description:
  133. Function retrieves the device descriptor from the device
  134. Arguments:
  135. adapter - adapter context
  136. Return Value:
  137. NT status code
  138. --*/
  139. {
  140. URB urb;
  141. NTSTATUS status;
  142. UsbBuildGetDescriptorRequest(&urb,
  143. (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  144. USB_DEVICE_DESCRIPTOR_TYPE,
  145. 0,
  146. 0,
  147. adapter->deviceDesc,
  148. NULL,
  149. sizeof(USB_DEVICE_DESCRIPTOR),
  150. NULL);
  151. status = SubmitUrb(adapter->nextDevObj, &urb, TRUE, NULL, NULL);
  152. if (NT_SUCCESS(status)){
  153. ASSERT(urb.UrbControlDescriptorRequest.TransferBufferLength == sizeof(USB_DEVICE_DESCRIPTOR));
  154. DBGVERBOSE(("Got device desc @ %ph.", (PVOID)&adapter->deviceDesc));
  155. }
  156. ASSERT(NT_SUCCESS(status));
  157. return status;
  158. }
  159. NTSTATUS GetConfigDescriptor(ADAPTEREXT *adapter)
  160. /*++
  161. Routine Description:
  162. Function retrieves the configuration descriptor from the device
  163. Arguments:
  164. adapter - adapter context
  165. Return Value:
  166. NT status code
  167. --*/
  168. {
  169. URB urb = { 0 };
  170. NTSTATUS status;
  171. USB_CONFIGURATION_DESCRIPTOR tmpConfigDesc = { 0 };
  172. /*
  173. * First get the initial part of the config descriptor
  174. * to find out how long the entire descriptor is.
  175. */
  176. UsbBuildGetDescriptorRequest(&urb,
  177. (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  178. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  179. 0,
  180. 0,
  181. (PVOID)&tmpConfigDesc,
  182. NULL,
  183. sizeof(USB_CONFIGURATION_DESCRIPTOR),
  184. NULL);
  185. status = SubmitUrb(adapter->nextDevObj, &urb, TRUE, NULL, NULL);
  186. if (NT_SUCCESS(status)){
  187. ASSERT(urb.UrbControlDescriptorRequest.TransferBufferLength == sizeof(USB_CONFIGURATION_DESCRIPTOR));
  188. ASSERT(tmpConfigDesc.wTotalLength > sizeof(USB_CONFIGURATION_DESCRIPTOR));
  189. adapter->configDesc = AllocPool((ULONG)tmpConfigDesc.wTotalLength);
  190. if (adapter->configDesc){
  191. RtlZeroMemory(adapter->configDesc, (ULONG)tmpConfigDesc.wTotalLength);
  192. UsbBuildGetDescriptorRequest(&urb,
  193. (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  194. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  195. 0,
  196. 0,
  197. adapter->configDesc,
  198. NULL,
  199. tmpConfigDesc.wTotalLength,
  200. NULL);
  201. status = SubmitUrb(adapter->nextDevObj, &urb, TRUE, NULL, NULL);
  202. if (NT_SUCCESS(status)){
  203. ASSERT(((PUSB_CONFIGURATION_DESCRIPTOR)adapter->configDesc)->wTotalLength == tmpConfigDesc.wTotalLength);
  204. ASSERT(urb.UrbControlDescriptorRequest.TransferBufferLength == (ULONG)tmpConfigDesc.wTotalLength);
  205. DBGVERBOSE(("Got config desc @ %ph, len=%xh.", adapter->configDesc, urb.UrbControlDescriptorRequest.TransferBufferLength));
  206. }
  207. else {
  208. ASSERT(NT_SUCCESS(status));
  209. FreePool(adapter->configDesc);
  210. adapter->configDesc = NULL;
  211. }
  212. }
  213. else {
  214. status = STATUS_INSUFFICIENT_RESOURCES;
  215. }
  216. }
  217. ASSERT(NT_SUCCESS(status));
  218. return status;
  219. }
  220. /*
  221. * SelectConfiguration
  222. *
  223. *
  224. */
  225. NTSTATUS SelectConfiguration(ADAPTEREXT *adapter)
  226. {
  227. PUSB_CONFIGURATION_DESCRIPTOR configDesc = (PUSB_CONFIGURATION_DESCRIPTOR)adapter->configDesc;
  228. NTSTATUS status;
  229. PURB urb = NULL;
  230. ULONG i;
  231. ASSERT(configDesc->bNumInterfaces > 0);
  232. #if SPECIAL_WIN98SE_BUILD
  233. /*
  234. * Hack to load on Win98 gold
  235. */
  236. {
  237. USHORT dummySize = 0;
  238. ASSERT(configDesc->bNumInterfaces >= 2);
  239. urb = USBD_CreateConfigurationRequest(configDesc, &dummySize);
  240. }
  241. #else
  242. if (configDesc->bNumInterfaces >= 2){
  243. PUSBD_INTERFACE_LIST_ENTRY interfaceList;
  244. interfaceList = AllocPool((configDesc->bNumInterfaces+1)*sizeof(USBD_INTERFACE_LIST_ENTRY));
  245. if (interfaceList){
  246. for (i = 0; i < configDesc->bNumInterfaces; i++){
  247. /*
  248. * Note: try to use USBD_ParseConfigurationDescriptor instead of
  249. * USBD_ParseConfigurationDescriptorEx so that we work
  250. * on Win98 gold.
  251. */
  252. interfaceList[i].InterfaceDescriptor = USBD_ParseConfigurationDescriptor(
  253. configDesc,
  254. (UCHAR)i,
  255. (UCHAR)0);
  256. if (!interfaceList[i].InterfaceDescriptor){
  257. break;
  258. }
  259. }
  260. interfaceList[i].InterfaceDescriptor = NULL;
  261. ASSERT(i == configDesc->bNumInterfaces);
  262. urb = USBD_CreateConfigurationRequestEx(configDesc, interfaceList);
  263. FreePool(interfaceList);
  264. }
  265. }
  266. else {
  267. ASSERT(configDesc->bNumInterfaces >= 2);
  268. }
  269. #endif
  270. if (urb){
  271. PUSBD_INTERFACE_INFORMATION interfaceInfo;
  272. /*
  273. * Fill in the interfaceInfo Class fields,
  274. * since USBD_CreateConfigurationRequestEx doesn't do that.
  275. */
  276. interfaceInfo = &urb->UrbSelectConfiguration.Interface;
  277. for (i = 0; i < configDesc->bNumInterfaces; i++){
  278. PUSB_INTERFACE_DESCRIPTOR ifaceDesc;
  279. ifaceDesc = USBD_ParseConfigurationDescriptor(configDesc, (UCHAR)i, (UCHAR)0);
  280. interfaceInfo->Class = ifaceDesc->bInterfaceClass;
  281. interfaceInfo = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)interfaceInfo+interfaceInfo->Length);
  282. }
  283. /*
  284. * Increase the transfer size for all data endpoints up to the maximum.
  285. * The data interface follows the master interface.
  286. */
  287. interfaceInfo = &urb->UrbSelectConfiguration.Interface;
  288. if (interfaceInfo->Class != USB_DEVICE_CLASS_DATA){
  289. interfaceInfo = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)interfaceInfo+interfaceInfo->Length);
  290. }
  291. if (interfaceInfo->Class == USB_DEVICE_CLASS_DATA){
  292. for (i = 0; i < interfaceInfo->NumberOfPipes; i++){
  293. interfaceInfo->Pipes[i].MaximumTransferSize = PACKET_BUFFER_SIZE;
  294. }
  295. status = SubmitUrb(adapter->nextDevObj, urb, TRUE, NULL, NULL);
  296. }
  297. else {
  298. ASSERT(interfaceInfo->Class == USB_DEVICE_CLASS_DATA);
  299. status = STATUS_DEVICE_DATA_ERROR;
  300. }
  301. if (NT_SUCCESS(status)){
  302. PUSBD_INTERFACE_INFORMATION interfaceInfo2;
  303. adapter->configHandle = (PVOID)urb->UrbSelectConfiguration.ConfigurationHandle;
  304. /*
  305. * A USB RNDIS device has two interfaces:
  306. * - a 'master' CDC class interface with one interrupt endpoint for notification
  307. * - a Data class interface with two bulk endpoints
  308. *
  309. * They may be in either order, so check class fields to assign
  310. * pointers correctly.
  311. */
  312. interfaceInfo = &urb->UrbSelectConfiguration.Interface;
  313. interfaceInfo2 = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)interfaceInfo+interfaceInfo->Length);
  314. if ((interfaceInfo->Class == USB_DEVICE_CLASS_CDC) &&
  315. (interfaceInfo2->Class == USB_DEVICE_CLASS_DATA)){
  316. adapter->interfaceInfoMaster = MemDup(interfaceInfo, interfaceInfo->Length);
  317. adapter->interfaceInfo = MemDup(interfaceInfo2, interfaceInfo2->Length);
  318. }
  319. else if ((interfaceInfo->Class == USB_DEVICE_CLASS_DATA) &&
  320. (interfaceInfo2->Class == USB_DEVICE_CLASS_CDC)){
  321. DBGWARN(("COVERAGE - Data interface precedes master CDC interface"));
  322. adapter->interfaceInfo = MemDup(interfaceInfo, interfaceInfo->Length);
  323. adapter->interfaceInfoMaster = MemDup(interfaceInfo2, interfaceInfo2->Length);
  324. }
  325. else {
  326. DBGERR(("improper interface classes"));
  327. adapter->interfaceInfo = NULL;
  328. adapter->interfaceInfoMaster = NULL;
  329. }
  330. if (adapter->interfaceInfo && adapter->interfaceInfoMaster){
  331. DBGVERBOSE(("SelectConfiguration: interfaceInfo @ %ph, interfaceInfoMaster @ %ph.", adapter->interfaceInfo, adapter->interfaceInfoMaster));
  332. }
  333. else {
  334. if (adapter->interfaceInfoMaster) FreePool(adapter->interfaceInfoMaster);
  335. if (adapter->interfaceInfo) FreePool(adapter->interfaceInfo);
  336. status = STATUS_INSUFFICIENT_RESOURCES;
  337. }
  338. }
  339. else {
  340. DBGERR(("SelectConfiguration: selectConfig URB failed w/ %xh.", status));
  341. }
  342. ExFreePool(urb);
  343. }
  344. else {
  345. status = STATUS_INSUFFICIENT_RESOURCES;
  346. }
  347. ASSERT(NT_SUCCESS(status));
  348. return status;
  349. }
  350. NTSTATUS FindUSBPipeHandles(ADAPTEREXT *adapter)
  351. {
  352. /*
  353. * Algorithm for identifying the endpoints:
  354. * The longest interrupt or bulk IN endpoint on the data interface
  355. * is the read endpoint;
  356. * The longest interrupt or bulk OUT endpoint on the data interface
  357. * is the write endpoint;
  358. * The first interrupt IN endpoint on the master interface
  359. * is the notification endpoint.
  360. */
  361. PUSBD_INTERFACE_INFORMATION interfaceInfo = adapter->interfaceInfo;
  362. PUSBD_INTERFACE_INFORMATION notifyInterfaceInfo = adapter->interfaceInfoMaster;
  363. LONG pipeIndex;
  364. LONG longestInputPipeIndex = -1, longestOutputPipeIndex = -1, notifyPipeIndex = -1;
  365. ULONG longestInputPipeLength = 0, longestOutputPipeLength = 0, notifyPipeLength;
  366. NTSTATUS status;
  367. /*
  368. * Find the IN and OUT endpoints.
  369. */
  370. for (pipeIndex = 0; pipeIndex < (LONG)interfaceInfo->NumberOfPipes; pipeIndex++){
  371. PUSBD_PIPE_INFORMATION pipeInfo = &interfaceInfo->Pipes[pipeIndex];
  372. if ((pipeInfo->PipeType == UsbdPipeTypeInterrupt) ||
  373. (pipeInfo->PipeType == UsbdPipeTypeBulk)){
  374. if (pipeInfo->EndpointAddress & USB_ENDPOINT_DIRECTION_MASK){
  375. if (pipeInfo->MaximumPacketSize > longestInputPipeLength){
  376. longestInputPipeIndex = pipeIndex;
  377. longestInputPipeLength = pipeInfo->MaximumPacketSize;
  378. }
  379. }
  380. else {
  381. if (pipeInfo->MaximumPacketSize > longestOutputPipeLength){
  382. longestOutputPipeIndex = pipeIndex;
  383. longestOutputPipeLength = pipeInfo->MaximumPacketSize;
  384. }
  385. }
  386. }
  387. }
  388. /*
  389. * Find the Notify endpoint.
  390. */
  391. for (pipeIndex = 0; pipeIndex < (LONG)notifyInterfaceInfo->NumberOfPipes; pipeIndex++){
  392. PUSBD_PIPE_INFORMATION pipeInfo = &notifyInterfaceInfo->Pipes[pipeIndex];
  393. if ((pipeInfo->PipeType == UsbdPipeTypeInterrupt) &&
  394. (pipeInfo->EndpointAddress & USB_ENDPOINT_DIRECTION_MASK) &&
  395. ((notifyInterfaceInfo != interfaceInfo) ||
  396. (pipeIndex != longestInputPipeIndex))){
  397. notifyPipeIndex = pipeIndex;
  398. notifyPipeLength = pipeInfo->MaximumPacketSize;
  399. break;
  400. }
  401. }
  402. if ((longestInputPipeIndex >= 0) &&
  403. (longestOutputPipeIndex >= 0) &&
  404. (notifyPipeIndex >= 0)){
  405. adapter->readPipeHandle = interfaceInfo->Pipes[longestInputPipeIndex].PipeHandle;
  406. adapter->writePipeHandle = interfaceInfo->Pipes[longestOutputPipeIndex].PipeHandle;
  407. adapter->notifyPipeHandle = notifyInterfaceInfo->Pipes[notifyPipeIndex].PipeHandle;
  408. adapter->readPipeLength = longestInputPipeLength;
  409. adapter->writePipeLength = longestOutputPipeLength;
  410. adapter->notifyPipeLength = notifyPipeLength;
  411. adapter->readPipeEndpointAddr = interfaceInfo->Pipes[longestInputPipeIndex].EndpointAddress;
  412. adapter->writePipeEndpointAddr = interfaceInfo->Pipes[longestOutputPipeIndex].EndpointAddress;
  413. adapter->notifyPipeEndpointAddr = notifyInterfaceInfo->Pipes[notifyPipeIndex].EndpointAddress;
  414. DBGVERBOSE(("FindUSBPipeHandles: got readPipe %ph,len=%xh; writePipe %ph,len=%xh; notifyPipe %ph,len=%xh.",
  415. adapter->readPipeHandle, adapter->readPipeLength, adapter->writePipeHandle, adapter->writePipeLength, adapter->notifyPipeHandle, adapter->notifyPipeLength));
  416. status = STATUS_SUCCESS;
  417. }
  418. else {
  419. DBGERR(("FindUSBPipeHandles: couldn't find right set of pipe handles (indices: %xh,%xh,%xh).", longestInputPipeIndex, longestOutputPipeIndex, notifyPipeIndex));
  420. status = STATUS_DEVICE_DATA_ERROR;
  421. }
  422. return status;
  423. }
  424. NTSTATUS SubmitUrb( PDEVICE_OBJECT pdo,
  425. PURB urb,
  426. BOOLEAN synchronous,
  427. PVOID completionRoutine,
  428. PVOID completionContext)
  429. /*++
  430. Routine Description:
  431. Send the URB to the USB device.
  432. If synchronous is TRUE, ignore the completion info and synchonize the IRP;
  433. otherwise, don't synchronize and set the provided completion routine for the IRP.
  434. Arguments:
  435. Return Value:
  436. NT status code
  437. --*/
  438. {
  439. NTSTATUS status;
  440. PIRP irp;
  441. /*
  442. * Allocate the IRP to send the buffer down the USB stack.
  443. *
  444. * Don't use IoBuildDeviceIoControlRequest (because it queues
  445. * the IRP on the current thread's irp list and may
  446. * cause the calling process to hang if the IopCompleteRequest APC
  447. * does not fire and dequeue the IRP).
  448. */
  449. irp = IoAllocateIrp(pdo->StackSize, FALSE);
  450. if (irp){
  451. PIO_STACK_LOCATION nextSp;
  452. DBGVERBOSE(("SubmitUrb: submitting URB %ph on IRP %ph (sync=%d)", urb, irp, synchronous));
  453. nextSp = IoGetNextIrpStackLocation(irp);
  454. nextSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  455. nextSp->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
  456. /*
  457. * Attach the URB to this IRP.
  458. */
  459. nextSp->Parameters.Others.Argument1 = urb;
  460. if (synchronous){
  461. status = CallDriverSync(pdo, irp);
  462. IoFreeIrp(irp);
  463. }
  464. else {
  465. /*
  466. * Caller's completion routine will free the irp
  467. * when it completes.
  468. */
  469. ASSERT(completionRoutine);
  470. ASSERT(completionContext);
  471. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  472. IoSetCompletionRoutine( irp,
  473. completionRoutine,
  474. completionContext,
  475. TRUE, TRUE, TRUE);
  476. status = IoCallDriver(pdo, irp);
  477. }
  478. }
  479. else {
  480. status = STATUS_INSUFFICIENT_RESOURCES;
  481. }
  482. return status;
  483. }
  484. NTSTATUS SubmitUrbIrp( PDEVICE_OBJECT pdo,
  485. PIRP irp,
  486. PURB urb,
  487. BOOLEAN synchronous,
  488. PVOID completionRoutine,
  489. PVOID completionContext)
  490. /*++
  491. Routine Description:
  492. Send the URB to the USB device.
  493. If synchronous is TRUE, ignore the completion info and synchonize the IRP;
  494. otherwise, don't synchronize and set the provided completion routine for the IRP.
  495. Arguments:
  496. Return Value:
  497. NT status code
  498. --*/
  499. {
  500. NTSTATUS status;
  501. PIO_STACK_LOCATION nextSp;
  502. DBGVERBOSE(("SubmitUrb: submitting URB %ph on IRP %ph (sync=%d)", urb, irp, synchronous));
  503. nextSp = IoGetNextIrpStackLocation(irp);
  504. nextSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  505. nextSp->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
  506. irp->Cancel = FALSE;
  507. /*
  508. * Attach the URB to this IRP.
  509. */
  510. nextSp->Parameters.Others.Argument1 = urb;
  511. if (synchronous){
  512. status = CallDriverSync(pdo, irp);
  513. ASSERT(!irp->CancelRoutine);
  514. }
  515. else {
  516. ASSERT(completionRoutine);
  517. ASSERT(completionContext);
  518. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  519. IoSetCompletionRoutine( irp,
  520. completionRoutine,
  521. completionContext,
  522. TRUE, TRUE, TRUE);
  523. status = IoCallDriver(pdo, irp);
  524. }
  525. return status;
  526. }
  527. NTSTATUS SubmitUSBReadPacket(USBPACKET *packet)
  528. {
  529. NTSTATUS status;
  530. PURB urb = packet->urbPtr;
  531. PIRP irp = packet->irpPtr;
  532. ULONG readLength;
  533. readLength = packet->dataBufferMaxLength;
  534. DBGVERBOSE(("SubmitUSBReadPacket: read %xh bytes, packet # %xh.", readLength, packet->packetId));
  535. urb->UrbBulkOrInterruptTransfer.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
  536. urb->UrbBulkOrInterruptTransfer.Hdr.Length = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
  537. urb->UrbBulkOrInterruptTransfer.PipeHandle = packet->adapter->readPipeHandle;
  538. urb->UrbBulkOrInterruptTransfer.TransferBufferLength = readLength;
  539. urb->UrbBulkOrInterruptTransfer.TransferBufferMDL = NULL;
  540. urb->UrbBulkOrInterruptTransfer.TransferBuffer = packet->dataBuffer;
  541. urb->UrbBulkOrInterruptTransfer.TransferFlags = USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_IN;
  542. urb->UrbBulkOrInterruptTransfer.UrbLink = NULL;
  543. status = SubmitUrbIrp( packet->adapter->nextDevObj,
  544. irp,
  545. urb,
  546. FALSE, // asynchronous
  547. ReadPipeCompletion, // completion routine
  548. packet // completion context
  549. );
  550. return status;
  551. }
  552. NTSTATUS ReadPipeCompletion(IN PDEVICE_OBJECT devObj, IN PIRP irp, IN PVOID context)
  553. {
  554. USBPACKET *packet = (USBPACKET *)context;
  555. ADAPTEREXT *adapter = packet->adapter;
  556. NTSTATUS status = irp->IoStatus.Status;
  557. ASSERT(packet->sig == DRIVER_SIG);
  558. ASSERT(adapter->sig == DRIVER_SIG);
  559. ASSERT(packet->irpPtr == irp);
  560. ASSERT(!irp->CancelRoutine);
  561. ASSERT(status != STATUS_PENDING); // saw UHCD doing this ?
  562. /*
  563. * Dequeue the packet from the usbPendingReadPackets queue
  564. * BEFORE checking if it was cancelled to avoid race with CancelAllPendingPackets.
  565. */
  566. DequeuePendingReadPacket(packet);
  567. if (packet->cancelled){
  568. /*
  569. * This packet was cancelled because of a halt or reset.
  570. * Get the packet is back in the free list first, then
  571. * set the event so CancelAllPendingPackets can proceed.
  572. */
  573. DBGVERBOSE((" ... read packet #%xh cancelled.", packet->packetId));
  574. packet->cancelled = FALSE;
  575. EnqueueFreePacket(packet);
  576. KeSetEvent(&packet->cancelEvent, 0, FALSE);
  577. }
  578. else if (adapter->halting){
  579. EnqueueFreePacket(packet);
  580. }
  581. else {
  582. PURB urb = packet->urbPtr;
  583. if (NT_SUCCESS(status)){
  584. BOOLEAN ethernetPacketComplete;
  585. adapter->numConsecutiveReadFailures = 0;
  586. /*
  587. * Fix the packet's dataBufferCurrentLength to indicate the actual length
  588. * of the returned data.
  589. * Note: the KLSI device rounds this up to a multiple of the endpoint
  590. * packet size, so the returned length may actually be larger than
  591. * the actual data.
  592. */
  593. packet->dataBufferCurrentLength = urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
  594. ASSERT(packet->dataBufferCurrentLength);
  595. ASSERT(packet->dataBufferCurrentLength <= packet->dataBufferMaxLength);
  596. DBGVERBOSE(("ReadPipeCompletion: %xh bytes, packet # %xh.", packet->dataBufferCurrentLength, packet->packetId));
  597. ethernetPacketComplete = (packet->dataBufferCurrentLength >= MINIMUM_ETHERNET_PACKET_SIZE);
  598. if (ethernetPacketComplete){
  599. /*
  600. * A complete ethernet packet has been received.
  601. * The entire ethernet packet is now in the current (final) USB packet.
  602. * Put our USB packet on the completed list and indicate it to RNDIS.
  603. */
  604. DBGSHOWBYTES("ReadPipeCompletion (COMPLETE packet)", packet->dataBuffer, packet->dataBufferCurrentLength);
  605. EnqueueCompletedReadPacket(packet);
  606. status = IndicateRndisMessage(packet, TRUE);
  607. if (status != STATUS_PENDING){
  608. DequeueCompletedReadPacket(packet);
  609. EnqueueFreePacket(packet);
  610. }
  611. }
  612. else {
  613. DBGWARN(("Device returned %xh-length packet @ %ph.", packet->dataBufferCurrentLength, packet->dataBuffer));
  614. DBGSHOWBYTES("ReadPipeCompletion (partial packet)", packet->dataBuffer, packet->dataBufferCurrentLength);
  615. EnqueueFreePacket(packet);
  616. }
  617. TryReadUSB(adapter);
  618. }
  619. else {
  620. KIRQL oldIrql;
  621. /*
  622. * The read failed. Put the packet back in the free list.
  623. */
  624. DBGWARN(("ReadPipeCompletion: read failed with status %xh on adapter %xh (urb status = %xh).", status, adapter, urb->UrbHeader.Status));
  625. #if DO_FULL_RESET
  626. switch (USBD_STATUS(urb->UrbBulkOrInterruptTransfer.Hdr.Status)){
  627. case USBD_STATUS(USBD_STATUS_STALL_PID):
  628. case USBD_STATUS(USBD_STATUS_DEV_NOT_RESPONDING):
  629. case USBD_STATUS(USBD_STATUS_ENDPOINT_HALTED):
  630. /*
  631. * Set a flag so we do a full reset in the workItem
  632. * (QueueAdapterWorkItem is called below)
  633. */
  634. adapter->needFullReset = TRUE;
  635. break;
  636. }
  637. #endif
  638. EnqueueFreePacket(packet);
  639. /*
  640. * We're probably halting or resetting.
  641. * Don't reissue a read synchronously here because it will probably
  642. * keep failing on the same thread and cause us to blow the stack.
  643. */
  644. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  645. adapter->numConsecutiveReadFailures++;
  646. adapter->readDeficit++;
  647. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  648. QueueAdapterWorkItem(adapter);
  649. }
  650. }
  651. return STATUS_MORE_PROCESSING_REQUIRED;
  652. }
  653. NTSTATUS SubmitUSBWritePacket(USBPACKET *packet)
  654. {
  655. NTSTATUS status;
  656. ADAPTEREXT *adapter = packet->adapter;
  657. PURB urb = packet->urbPtr;
  658. PIRP irp = packet->irpPtr;
  659. /*
  660. * Some device USB controllers cannot detect the end of a transfer unless there
  661. * is a short packet at the end. So if the transfer is a multiple of the
  662. * endpoint's wMaxPacketSize, add a byte to force a short packet at the end.
  663. */
  664. if ((packet->dataBufferCurrentLength % adapter->writePipeLength) == 0){
  665. packet->dataBuffer[packet->dataBufferCurrentLength++] = 0x00;
  666. }
  667. ASSERT(packet->dataBufferCurrentLength <= PACKET_BUFFER_SIZE);
  668. DBGVERBOSE(("SubmitUSBWritePacket: %xh bytes, packet # %xh.", packet->dataBufferCurrentLength, packet->packetId));
  669. DBGSHOWBYTES("SubmitUSBWritePacket", packet->dataBuffer, packet->dataBufferCurrentLength);
  670. urb->UrbBulkOrInterruptTransfer.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
  671. urb->UrbBulkOrInterruptTransfer.Hdr.Length = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
  672. urb->UrbBulkOrInterruptTransfer.PipeHandle = adapter->writePipeHandle;
  673. urb->UrbBulkOrInterruptTransfer.TransferBufferLength = packet->dataBufferCurrentLength;
  674. urb->UrbBulkOrInterruptTransfer.TransferBufferMDL = NULL;
  675. urb->UrbBulkOrInterruptTransfer.TransferBuffer = packet->dataBuffer;
  676. urb->UrbBulkOrInterruptTransfer.TransferFlags = USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_OUT;
  677. urb->UrbBulkOrInterruptTransfer.UrbLink = NULL;
  678. status = SubmitUrbIrp( adapter->nextDevObj,
  679. irp,
  680. urb,
  681. FALSE, // asynchronous
  682. WritePipeCompletion, // completion routine
  683. packet // completion context
  684. );
  685. if (!NT_SUCCESS(status)){
  686. DBGERR(("SubmitUSBWritePacket: packet @ %ph status %xh.", packet, status));
  687. }
  688. return status;
  689. }
  690. NTSTATUS WritePipeCompletion(IN PDEVICE_OBJECT devObj, IN PIRP irp, IN PVOID context)
  691. {
  692. USBPACKET *packet = (USBPACKET *)context;
  693. ADAPTEREXT *adapter = packet->adapter;
  694. NTSTATUS status = irp->IoStatus.Status;
  695. KIRQL oldIrql;
  696. ASSERT(packet->sig == DRIVER_SIG);
  697. ASSERT(adapter->sig == DRIVER_SIG);
  698. ASSERT(packet->irpPtr == irp);
  699. ASSERT(!irp->CancelRoutine);
  700. ASSERT(status != STATUS_PENDING); // saw UHCD doing this ?
  701. if (NT_SUCCESS(status)){
  702. DBGVERBOSE(("WritePipeCompletion: packet # %xh completed.", packet->packetId));
  703. }
  704. else {
  705. DBGWARN(("WritePipeCompletion: packet # %xh failed with status %xh on adapter %xh.", packet->packetId, status, adapter));
  706. }
  707. IndicateSendStatusToRNdis(packet, status);
  708. /*
  709. * Dequeue the packet from the usbPendingWritePackets queue
  710. * BEFORE checking if it was cancelled to avoid race with CancelAllPendingPackets.
  711. */
  712. DequeuePendingWritePacket(packet);
  713. if (packet->cancelled){
  714. /*
  715. * This packet was cancelled because of a halt or reset.
  716. * Put the packet back in the free list first, then
  717. * set the event so CancelAllPendingPackets can proceed.
  718. */
  719. DBGVERBOSE((" ... write packet #%xh cancelled.", packet->packetId));
  720. packet->cancelled = FALSE;
  721. EnqueueFreePacket(packet);
  722. KeSetEvent(&packet->cancelEvent, 0, FALSE);
  723. }
  724. else {
  725. EnqueueFreePacket(packet);
  726. }
  727. return STATUS_MORE_PROCESSING_REQUIRED;
  728. }
  729. NTSTATUS SubmitNotificationRead(ADAPTEREXT *adapter, BOOLEAN synchronous)
  730. {
  731. NTSTATUS status;
  732. PURB urb = adapter->notifyUrbPtr;
  733. PIRP irp = adapter->notifyIrpPtr;
  734. ULONG guardWord = GUARD_WORD;
  735. KIRQL oldIrql;
  736. ASSERT(adapter->notifyPipeHandle);
  737. DBGVERBOSE(("SubmitNotificationRead: read %xh bytes.", adapter->notifyPipeLength));
  738. /*
  739. * Fill the notify buffer with invalid data just in case a device replies with
  740. * no data at all. A previously received valid message may still be there.
  741. * Apparently it won't be overwritten by the USB stack unless the device
  742. * supplies data.
  743. */
  744. RtlFillMemory(adapter->notifyBuffer, adapter->notifyPipeLength, 0xfe);
  745. /*
  746. * Place a guard word at the end of the notify buffer
  747. * to catch overwrites by the host controller (which we've seen).
  748. * Use RtlCopyMemory in case pointer is unaligned.
  749. */
  750. RtlCopyMemory(adapter->notifyBuffer+adapter->notifyPipeLength, &guardWord, sizeof(ULONG));
  751. /*
  752. * The notify pipe actually fills out a buffer with the fields given
  753. * in the spec as URB fields. Read the notify pipe like any interrupt pipe.
  754. */
  755. urb->UrbBulkOrInterruptTransfer.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
  756. urb->UrbBulkOrInterruptTransfer.Hdr.Length = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
  757. urb->UrbBulkOrInterruptTransfer.PipeHandle = adapter->notifyPipeHandle;
  758. urb->UrbBulkOrInterruptTransfer.TransferBufferLength = adapter->notifyPipeLength;
  759. urb->UrbBulkOrInterruptTransfer.TransferBufferMDL = NULL;
  760. urb->UrbBulkOrInterruptTransfer.TransferBuffer = adapter->notifyBuffer;
  761. urb->UrbBulkOrInterruptTransfer.TransferFlags = USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_IN;
  762. urb->UrbBulkOrInterruptTransfer.UrbLink = NULL;
  763. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  764. adapter->notifyBufferCurrentLength = 0;
  765. adapter->notifyStopped = FALSE;
  766. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  767. if (synchronous){
  768. status = SubmitUrbIrp(adapter->nextDevObj, irp, urb, TRUE, NULL, NULL);
  769. }
  770. else {
  771. status = SubmitUrbIrp( adapter->nextDevObj,
  772. irp,
  773. urb,
  774. FALSE, // asynchronous
  775. NotificationCompletion, // completion routine
  776. adapter // completion context
  777. );
  778. }
  779. return status;
  780. }
  781. NTSTATUS NotificationCompletion(IN PDEVICE_OBJECT devObj, IN PIRP irp, IN PVOID context)
  782. {
  783. ADAPTEREXT *adapter = context;
  784. PURB urb = adapter->notifyUrbPtr;
  785. NTSTATUS status = irp->IoStatus.Status;
  786. BOOLEAN notifyStopped = FALSE;
  787. BOOLEAN setCancelEvent = FALSE;
  788. ULONG guardWord;
  789. KIRQL oldIrql;
  790. ASSERT(adapter->sig == DRIVER_SIG);
  791. ASSERT(irp == adapter->notifyIrpPtr);
  792. ASSERT(!irp->CancelRoutine);
  793. ASSERT(status != STATUS_PENDING); // saw UHCD doing this ?
  794. /*
  795. * Check the guard word at the end of the notify buffer
  796. * to catch overwrites by the host controller
  797. * (we've seen this on VIA host controllers).
  798. * Use RtlCopyMemory in case pointer is unaligned.
  799. */
  800. RtlCopyMemory(&guardWord, adapter->notifyBuffer+adapter->notifyPipeLength, sizeof(ULONG));
  801. if (guardWord != GUARD_WORD){
  802. ASSERT(guardWord == GUARD_WORD);
  803. DBGERR(("NotificationCompletion: adapter %p, bad guard word 0x%x\n",
  804. adapter, guardWord));
  805. #if DBG
  806. DbgBreakPoint();
  807. #endif // DBG
  808. }
  809. /*
  810. * In order to synchronize with CancelAllPendingPackets,
  811. * we need to either send the irp down again, mark the notifyIrp as stopped,
  812. * or set the notifyCancelEvent.
  813. */
  814. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  815. if (adapter->cancellingNotify){
  816. /*
  817. * This irp was cancelled by CancelAllPendingPackets.
  818. * After dropping the spinlock, we'll set the cancel event
  819. * so that CancelAllPendingPackets stops waiting.
  820. */
  821. notifyStopped = TRUE;
  822. setCancelEvent = TRUE;
  823. }
  824. else if (!NT_SUCCESS(status)){
  825. /*
  826. * The notify irp can get failed on an unplug BEFORE we get the halted.
  827. * Since we're not going to send the notify IRP down again, we need to
  828. * make sure that we don't wait for it forever in CancelAllPendingPackets.
  829. * We do this by synchronously setting notifyStopped
  830. * as an indication that this irp doesn't need to be cancelled.
  831. */
  832. DBGWARN(("NotificationCompletion: read failed with status %xh on adapter %xh (urb status = %xh).", status, adapter, urb->UrbHeader.Status));
  833. notifyStopped = adapter->notifyStopped = TRUE;
  834. }
  835. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  836. if (!notifyStopped){
  837. ULONG notifyLen = urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
  838. ASSERT(notifyLen <= adapter->notifyPipeLength);
  839. adapter->notifyBufferCurrentLength = MIN(notifyLen, adapter->notifyPipeLength);
  840. RNDISProcessNotification(adapter);
  841. SubmitNotificationRead(adapter, FALSE);
  842. }
  843. if (setCancelEvent){
  844. DBGVERBOSE((" ... notify read packet cancelled."));
  845. KeSetEvent(&adapter->notifyCancelEvent, 0, FALSE);
  846. }
  847. return STATUS_MORE_PROCESSING_REQUIRED;
  848. }
  849. NTSTATUS SubmitPacketToControlPipe( USBPACKET *packet,
  850. BOOLEAN synchronous,
  851. BOOLEAN simulated)
  852. {
  853. NTSTATUS status;
  854. ADAPTEREXT *adapter = packet->adapter;
  855. PURB urb = packet->urbPtr;
  856. PIRP irp = packet->irpPtr;
  857. PUSBD_INTERFACE_INFORMATION interfaceInfoControl;
  858. DBGVERBOSE(("SubmitPacketToControlPipe: packet # %xh.", packet->packetId));
  859. DBGSHOWBYTES("SubmitPacketToControlPipe", packet->dataBuffer, packet->dataBufferCurrentLength);
  860. ASSERT(adapter->interfaceInfoMaster);
  861. interfaceInfoControl = adapter->interfaceInfoMaster;
  862. urb->UrbHeader.Length = (USHORT) sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
  863. urb->UrbHeader.Function = URB_FUNCTION_CLASS_INTERFACE;
  864. urb->UrbControlVendorClassRequest.Reserved = 0;
  865. urb->UrbControlVendorClassRequest.TransferFlags = USBD_TRANSFER_DIRECTION_OUT;
  866. urb->UrbControlVendorClassRequest.TransferBufferLength = packet->dataBufferCurrentLength;
  867. urb->UrbControlVendorClassRequest.TransferBuffer = packet->dataBuffer;
  868. urb->UrbControlVendorClassRequest.TransferBufferMDL = NULL;
  869. urb->UrbControlVendorClassRequest.UrbLink = NULL;
  870. urb->UrbControlVendorClassRequest.RequestTypeReservedBits = 0;
  871. urb->UrbControlVendorClassRequest.Request = NATIVE_RNDIS_SEND_ENCAPSULATED_COMMAND;
  872. urb->UrbControlVendorClassRequest.Value = 0;
  873. urb->UrbControlVendorClassRequest.Index = interfaceInfoControl->InterfaceNumber;
  874. urb->UrbControlVendorClassRequest.Reserved1 = 0;
  875. if (synchronous){
  876. /*
  877. * Send the URB down synchronously,
  878. * then call the completion routine to clean up ourselves.
  879. */
  880. status = SubmitUrbIrp(adapter->nextDevObj, irp, urb, TRUE, NULL, NULL);
  881. if (!simulated){
  882. ControlPipeWriteCompletion(adapter->nextDevObj, irp, packet);
  883. }
  884. }
  885. else {
  886. status = SubmitUrbIrp( adapter->nextDevObj,
  887. irp,
  888. urb,
  889. FALSE, // asynchronous
  890. ControlPipeWriteCompletion, // completion routine
  891. packet // completion context
  892. );
  893. }
  894. return status;
  895. }
  896. NTSTATUS ControlPipeWriteCompletion(IN PDEVICE_OBJECT devObj, IN PIRP irp, IN PVOID context)
  897. {
  898. USBPACKET *packet = (USBPACKET *)context;
  899. ADAPTEREXT *adapter = packet->adapter;
  900. NTSTATUS status = irp->IoStatus.Status;
  901. KIRQL oldIrql;
  902. ASSERT(packet->sig == DRIVER_SIG);
  903. ASSERT(adapter->sig == DRIVER_SIG);
  904. ASSERT(packet->irpPtr == irp);
  905. ASSERT(!irp->CancelRoutine);
  906. ASSERT(status != STATUS_PENDING); // saw UHCD doing this ?
  907. if (NT_SUCCESS(status)){
  908. DBGVERBOSE(("ControlPipeWriteCompletion: packet # %xh completed.", packet->packetId));
  909. }
  910. else {
  911. DBGWARN(("ControlPipeWriteCompletion: packet # %xh failed with status %xh on adapter %xh.", packet->packetId, status, adapter));
  912. }
  913. IndicateSendStatusToRNdis(packet, status);
  914. /*
  915. * Dequeue the packet from the usbPendingWritePackets queue
  916. * BEFORE checking if it was cancelled to avoid race with CancelAllPendingPackets.
  917. */
  918. DequeuePendingWritePacket(packet);
  919. if (packet->cancelled){
  920. /*
  921. * This packet was cancelled because of a halt or reset.
  922. * Put the packet back in the free list first, then
  923. * set the event so CancelAllPendingPackets can proceed.
  924. */
  925. DBGVERBOSE((" ... write packet #%xh cancelled.", packet->packetId));
  926. packet->cancelled = FALSE;
  927. EnqueueFreePacket(packet);
  928. KeSetEvent(&packet->cancelEvent, 0, FALSE);
  929. }
  930. else {
  931. EnqueueFreePacket(packet);
  932. }
  933. if (NT_SUCCESS(status)){
  934. }
  935. else {
  936. #if DO_FULL_RESET
  937. adapter->needFullReset = TRUE;
  938. QueueAdapterWorkItem(adapter);
  939. #endif
  940. }
  941. return STATUS_MORE_PROCESSING_REQUIRED;
  942. }
  943. NTSTATUS ReadPacketFromControlPipe(USBPACKET *packet, BOOLEAN synchronous)
  944. {
  945. NTSTATUS status;
  946. ADAPTEREXT *adapter = packet->adapter;
  947. PURB urb = packet->urbPtr;
  948. PIRP irp = packet->irpPtr;
  949. PUSBD_INTERFACE_INFORMATION interfaceInfoControl;
  950. ULONG bytesToRead = MAXIMUM_DEVICE_MESSAGE_SIZE+1;
  951. DBGVERBOSE(("ReadPacketFromControlPipe: read %xh bytes, packet #%xh.", bytesToRead, packet->packetId));
  952. ASSERT(adapter->interfaceInfoMaster);
  953. interfaceInfoControl = adapter->interfaceInfoMaster;
  954. urb->UrbHeader.Length = (USHORT) sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
  955. urb->UrbHeader.Function = URB_FUNCTION_CLASS_INTERFACE;
  956. urb->UrbControlVendorClassRequest.Reserved = 0;
  957. urb->UrbControlVendorClassRequest.TransferFlags = USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_IN;
  958. urb->UrbControlVendorClassRequest.TransferBufferLength = bytesToRead;
  959. urb->UrbControlVendorClassRequest.TransferBuffer = packet->dataBuffer;
  960. urb->UrbControlVendorClassRequest.TransferBufferMDL = NULL;
  961. urb->UrbControlVendorClassRequest.UrbLink = NULL;
  962. urb->UrbControlVendorClassRequest.RequestTypeReservedBits = 0;
  963. urb->UrbControlVendorClassRequest.Request = NATIVE_RNDIS_GET_ENCAPSULATED_RESPONSE;
  964. urb->UrbControlVendorClassRequest.Value = 0;
  965. urb->UrbControlVendorClassRequest.Index = interfaceInfoControl->InterfaceNumber;
  966. urb->UrbControlVendorClassRequest.Reserved1 = 0;
  967. if (synchronous){
  968. status = SubmitUrbIrp(adapter->nextDevObj, irp, urb, TRUE, NULL, NULL);
  969. }
  970. else {
  971. status = SubmitUrbIrp( adapter->nextDevObj,
  972. irp,
  973. urb,
  974. FALSE, // asynchronous
  975. ControlPipeReadCompletion, // completion routine
  976. packet // completion context
  977. );
  978. }
  979. ASSERT(NT_SUCCESS(status));
  980. return status;
  981. }
  982. NTSTATUS ControlPipeReadCompletion(IN PDEVICE_OBJECT devObj, IN PIRP irp, IN PVOID context)
  983. {
  984. USBPACKET *packet = (USBPACKET *)context;
  985. ADAPTEREXT *adapter = packet->adapter;
  986. NTSTATUS status = irp->IoStatus.Status;
  987. KIRQL oldIrql;
  988. ASSERT(packet->sig == DRIVER_SIG);
  989. ASSERT(adapter->sig == DRIVER_SIG);
  990. ASSERT(packet->irpPtr == irp);
  991. ASSERT(!irp->CancelRoutine);
  992. ASSERT(status != STATUS_PENDING); // saw UHCD doing this ?
  993. /*
  994. * Dequeue the packet from the usbPendingReadPackets queue
  995. * BEFORE checking if it was cancelled to avoid race with CancelAllPendingPackets.
  996. */
  997. DequeuePendingReadPacket(packet);
  998. if (packet->cancelled){
  999. /*
  1000. * This packet was cancelled because of a halt or reset.
  1001. * Get the packet is back in the free list first, then
  1002. * set the event so CancelAllPendingPackets can proceed.
  1003. */
  1004. DBGVERBOSE((" ... read packet #%xh cancelled.", packet->packetId));
  1005. packet->cancelled = FALSE;
  1006. EnqueueFreePacket(packet);
  1007. KeSetEvent(&packet->cancelEvent, 0, FALSE);
  1008. }
  1009. else if (adapter->halting){
  1010. EnqueueFreePacket(packet);
  1011. }
  1012. else {
  1013. if (NT_SUCCESS(status)){
  1014. PURB urb = packet->urbPtr;
  1015. /*
  1016. * Fix the packet's dataBufferCurrentLength to indicate the actual length
  1017. * of the returned data.
  1018. * Note: the KLSI device rounds this up to a multiple of the endpoint
  1019. * packet size, so the returned length may actually be larger than
  1020. * the actual data.
  1021. */
  1022. packet->dataBufferCurrentLength = urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
  1023. ASSERT(packet->dataBufferCurrentLength);
  1024. ASSERT(packet->dataBufferCurrentLength <= packet->dataBufferMaxLength);
  1025. DBGVERBOSE(("ControlPipeReadCompletion: packet # %xh.", packet->packetId));
  1026. DBGSHOWBYTES("ControlPipeReadCompletion", packet->dataBuffer, packet->dataBufferCurrentLength);
  1027. EnqueueCompletedReadPacket(packet);
  1028. status = IndicateRndisMessage(packet, FALSE);
  1029. if (status != STATUS_PENDING){
  1030. DequeueCompletedReadPacket(packet);
  1031. EnqueueFreePacket(packet);
  1032. }
  1033. }
  1034. else {
  1035. /*
  1036. * The read failed. Put the packet back in the free list.
  1037. */
  1038. DBGWARN(("ControlPipeReadCompletion: read failed with status %xh on adapter %xh.", status, adapter));
  1039. EnqueueFreePacket(packet);
  1040. #if DO_FULL_RESET
  1041. adapter->needFullReset = TRUE;
  1042. QueueAdapterWorkItem(adapter);
  1043. #endif
  1044. }
  1045. }
  1046. return STATUS_MORE_PROCESSING_REQUIRED;
  1047. }
  1048. NTSTATUS CallDriverSync(PDEVICE_OBJECT devObj, PIRP irp)
  1049. /*++
  1050. Routine Description:
  1051. Call IoCallDriver to send the irp to the device object;
  1052. then, synchronize with the completion routine.
  1053. When CallDriverSync returns, the action has completed
  1054. and the irp again belongs to the current driver.
  1055. NOTE: In order to keep the device object from getting freed
  1056. while this IRP is pending, you should call
  1057. IncrementPendingActionCount() and
  1058. DecrementPendingActionCount()
  1059. around the CallDriverSync call.
  1060. Arguments:
  1061. devObj - targetted device object
  1062. irp - Io Request Packet
  1063. Return Value:
  1064. NT status code, indicates result returned by lower driver for this IRP.
  1065. --*/
  1066. {
  1067. KEVENT event;
  1068. NTSTATUS status;
  1069. ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
  1070. KeInitializeEvent(&event, NotificationEvent, FALSE);
  1071. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  1072. IoSetCompletionRoutine( irp,
  1073. CallDriverSyncCompletion,
  1074. &event, // context
  1075. TRUE, TRUE, TRUE);
  1076. status = IoCallDriver(devObj, irp);
  1077. KeWaitForSingleObject( &event,
  1078. Executive, // wait reason
  1079. KernelMode,
  1080. FALSE, // not alertable
  1081. NULL ); // no timeout
  1082. status = irp->IoStatus.Status;
  1083. ASSERT(status != STATUS_PENDING);
  1084. if (!NT_SUCCESS(status)){
  1085. DBGWARN(("CallDriverSync: irp failed w/ status %xh.", status));
  1086. }
  1087. return status;
  1088. }
  1089. NTSTATUS CallDriverSyncCompletion(IN PDEVICE_OBJECT devObjOrNULL, IN PIRP irp, IN PVOID context)
  1090. /*++
  1091. Routine Description:
  1092. Completion routine for CallDriverSync.
  1093. Arguments:
  1094. devObjOrNULL -
  1095. Usually, this is this driver's device object.
  1096. However, if this driver created the IRP,
  1097. there is no stack location in the IRP for this driver;
  1098. so the kernel has no place to store the device object;
  1099. ** so devObj will be NULL in this case **.
  1100. irp - completed Io Request Packet
  1101. context - context passed to IoSetCompletionRoutine by CallDriverSync.
  1102. Return Value:
  1103. NT status code, indicates result returned by lower driver for this IRP.
  1104. --*/
  1105. {
  1106. PKEVENT event = context;
  1107. ASSERT(!irp->CancelRoutine);
  1108. if (!NT_SUCCESS(irp->IoStatus.Status)){
  1109. DBGWARN(("CallDriverSyncCompletion: irp failed w/ status %xh.", irp->IoStatus.Status));
  1110. }
  1111. KeSetEvent(event, 0, FALSE);
  1112. return STATUS_MORE_PROCESSING_REQUIRED;
  1113. }
  1114. #if 0
  1115. NTSTATUS GetStringDescriptor( ADAPTEREXT *adapter,
  1116. UCHAR stringIndex,
  1117. PUCHAR buffer,
  1118. ULONG bufferLen)
  1119. /*++
  1120. Routine Description:
  1121. Function retrieves a string descriptor from the device
  1122. Arguments:
  1123. adapter - adapter context
  1124. Return Value:
  1125. NT status code
  1126. --*/
  1127. {
  1128. URB urb;
  1129. NTSTATUS status;
  1130. UsbBuildGetDescriptorRequest(&urb,
  1131. (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  1132. USB_STRING_DESCRIPTOR_TYPE,
  1133. stringIndex,
  1134. 0x0409, // language = US English
  1135. buffer,
  1136. NULL,
  1137. bufferLen,
  1138. NULL);
  1139. status = SubmitUrb(adapter->nextDevObj, &urb, TRUE, NULL, NULL);
  1140. if (NT_SUCCESS(status)){
  1141. DBGVERBOSE(("Got string desc (index %xh) @ %ph, len = %xh.", (ULONG)stringIndex, buffer, urb.UrbControlDescriptorRequest.TransferBufferLength));
  1142. ASSERT(urb.UrbControlDescriptorRequest.TransferBufferLength <= bufferLen);
  1143. }
  1144. else {
  1145. DBGERR(("GetStringDescriptor: failed to get string (index %xh) with status %xh on adapter %xh.", (ULONG)stringIndex, status, adapter));
  1146. }
  1147. ASSERT(NT_SUCCESS(status));
  1148. return status;
  1149. }
  1150. /*
  1151. * CreateSingleInterfaceConfigDesc
  1152. *
  1153. * Allocate a configuration descriptor that excludes all interfaces
  1154. * but the given interface
  1155. * (e.g. for multiple-interface devices like the Intel cable modem,
  1156. * for which we don't load on top of the generic parent).
  1157. *
  1158. * Note: interfaceDesc must point inside configDesc.
  1159. *
  1160. */
  1161. PUSB_CONFIGURATION_DESCRIPTOR CreateSingleInterfaceConfigDesc(
  1162. PUSB_CONFIGURATION_DESCRIPTOR configDesc,
  1163. PUSB_INTERFACE_DESCRIPTOR interfaceDesc)
  1164. {
  1165. PUSB_CONFIGURATION_DESCRIPTOR ifaceConfigDesc;
  1166. ASSERT(interfaceDesc);
  1167. ASSERT((PVOID)interfaceDesc > (PVOID)configDesc);
  1168. ASSERT((PUCHAR)interfaceDesc - (PUCHAR)configDesc < configDesc->wTotalLength);
  1169. ifaceConfigDesc = AllocPool(configDesc->wTotalLength);
  1170. if (ifaceConfigDesc){
  1171. PUSB_COMMON_DESCRIPTOR srcDesc, newDesc;
  1172. USHORT totalLen;
  1173. /*
  1174. * Copy the configuration descriptor itself.
  1175. */
  1176. RtlCopyMemory(ifaceConfigDesc, configDesc, configDesc->bLength);
  1177. totalLen = configDesc->bLength;
  1178. /*
  1179. * Copy the given interface descriptor.
  1180. */
  1181. srcDesc = (PUSB_COMMON_DESCRIPTOR)interfaceDesc;
  1182. newDesc = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)ifaceConfigDesc + ifaceConfigDesc->bLength);
  1183. RtlCopyMemory(newDesc, srcDesc, srcDesc->bLength);
  1184. totalLen += srcDesc->bLength;
  1185. srcDesc = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)srcDesc + srcDesc->bLength);
  1186. newDesc = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)newDesc + newDesc->bLength);
  1187. /*
  1188. * Copy the given interface descriptors and all following descriptors
  1189. * up to either the next interface descriptor or the end of the original
  1190. * configuration descriptor.
  1191. */
  1192. while ((PUCHAR)srcDesc - (PUCHAR)configDesc < configDesc->wTotalLength){
  1193. if (srcDesc->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE){
  1194. break;
  1195. }
  1196. else {
  1197. RtlCopyMemory(newDesc, srcDesc, srcDesc->bLength);
  1198. totalLen += srcDesc->bLength;
  1199. srcDesc = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)srcDesc + srcDesc->bLength);
  1200. newDesc = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)newDesc + newDesc->bLength);
  1201. }
  1202. }
  1203. ifaceConfigDesc->bNumInterfaces = 1;
  1204. ifaceConfigDesc->wTotalLength = totalLen;
  1205. DBGVERBOSE(("CreateSingleInterfaceConfigDesc: build partial configDesc @ %ph, len=%xh.", ifaceConfigDesc, ifaceConfigDesc->wTotalLength));
  1206. }
  1207. return ifaceConfigDesc;
  1208. }
  1209. #endif