Source code of Windows XP (NT5)
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.

1537 lines
52 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. #ifndef SPECIAL_WIN98SE_BUILD
  804. {
  805. /*
  806. * Raise an exception so we catch this in retail builds.
  807. */
  808. EXCEPTION_RECORD exceptionRec;
  809. exceptionRec.ExceptionCode = STATUS_ADAPTER_HARDWARE_ERROR;
  810. exceptionRec.ExceptionFlags = EXCEPTION_NONCONTINUABLE_EXCEPTION;
  811. exceptionRec.ExceptionRecord = NULL;
  812. exceptionRec.ExceptionAddress = (PVOID)NotificationCompletion; // actual fault is in bus-mastering hardware
  813. exceptionRec.NumberParameters = 0;
  814. // ExRaiseException(&exceptionRec);
  815. // Changed to KeBugCheckEx since ExRaiseException is not a WDM call.
  816. // We want to be loadable on WinMe.
  817. KeBugCheckEx(FATAL_UNHANDLED_HARD_ERROR,
  818. STATUS_ADAPTER_HARDWARE_ERROR,
  819. (ULONG_PTR)adapter,
  820. (ULONG_PTR)guardWord,
  821. (ULONG_PTR)NULL);
  822. }
  823. #endif
  824. }
  825. /*
  826. * In order to synchronize with CancelAllPendingPackets,
  827. * we need to either send the irp down again, mark the notifyIrp as stopped,
  828. * or set the notifyCancelEvent.
  829. */
  830. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  831. if (adapter->cancellingNotify){
  832. /*
  833. * This irp was cancelled by CancelAllPendingPackets.
  834. * After dropping the spinlock, we'll set the cancel event
  835. * so that CancelAllPendingPackets stops waiting.
  836. */
  837. notifyStopped = TRUE;
  838. setCancelEvent = TRUE;
  839. }
  840. else if (!NT_SUCCESS(status)){
  841. /*
  842. * The notify irp can get failed on an unplug BEFORE we get the halted.
  843. * Since we're not going to send the notify IRP down again, we need to
  844. * make sure that we don't wait for it forever in CancelAllPendingPackets.
  845. * We do this by synchronously setting notifyStopped
  846. * as an indication that this irp doesn't need to be cancelled.
  847. */
  848. DBGWARN(("NotificationCompletion: read failed with status %xh on adapter %xh (urb status = %xh).", status, adapter, urb->UrbHeader.Status));
  849. notifyStopped = adapter->notifyStopped = TRUE;
  850. }
  851. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  852. if (!notifyStopped){
  853. ULONG notifyLen = urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
  854. ASSERT(notifyLen <= adapter->notifyPipeLength);
  855. adapter->notifyBufferCurrentLength = MIN(notifyLen, adapter->notifyPipeLength);
  856. RNDISProcessNotification(adapter);
  857. SubmitNotificationRead(adapter, FALSE);
  858. }
  859. if (setCancelEvent){
  860. DBGVERBOSE((" ... notify read packet cancelled."));
  861. KeSetEvent(&adapter->notifyCancelEvent, 0, FALSE);
  862. }
  863. return STATUS_MORE_PROCESSING_REQUIRED;
  864. }
  865. NTSTATUS SubmitPacketToControlPipe( USBPACKET *packet,
  866. BOOLEAN synchronous,
  867. BOOLEAN simulated)
  868. {
  869. NTSTATUS status;
  870. ADAPTEREXT *adapter = packet->adapter;
  871. PURB urb = packet->urbPtr;
  872. PIRP irp = packet->irpPtr;
  873. PUSBD_INTERFACE_INFORMATION interfaceInfoControl;
  874. DBGVERBOSE(("SubmitPacketToControlPipe: packet # %xh.", packet->packetId));
  875. DBGSHOWBYTES("SubmitPacketToControlPipe", packet->dataBuffer, packet->dataBufferCurrentLength);
  876. ASSERT(adapter->interfaceInfoMaster);
  877. interfaceInfoControl = adapter->interfaceInfoMaster;
  878. urb->UrbHeader.Length = (USHORT) sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
  879. urb->UrbHeader.Function = URB_FUNCTION_CLASS_INTERFACE;
  880. urb->UrbControlVendorClassRequest.Reserved = 0;
  881. urb->UrbControlVendorClassRequest.TransferFlags = USBD_TRANSFER_DIRECTION_OUT;
  882. urb->UrbControlVendorClassRequest.TransferBufferLength = packet->dataBufferCurrentLength;
  883. urb->UrbControlVendorClassRequest.TransferBuffer = packet->dataBuffer;
  884. urb->UrbControlVendorClassRequest.TransferBufferMDL = NULL;
  885. urb->UrbControlVendorClassRequest.UrbLink = NULL;
  886. urb->UrbControlVendorClassRequest.RequestTypeReservedBits = 0;
  887. urb->UrbControlVendorClassRequest.Request = NATIVE_RNDIS_SEND_ENCAPSULATED_COMMAND;
  888. urb->UrbControlVendorClassRequest.Value = 0;
  889. urb->UrbControlVendorClassRequest.Index = interfaceInfoControl->InterfaceNumber;
  890. urb->UrbControlVendorClassRequest.Reserved1 = 0;
  891. if (synchronous){
  892. /*
  893. * Send the URB down synchronously,
  894. * then call the completion routine to clean up ourselves.
  895. */
  896. status = SubmitUrbIrp(adapter->nextDevObj, irp, urb, TRUE, NULL, NULL);
  897. if (!simulated){
  898. ControlPipeWriteCompletion(adapter->nextDevObj, irp, packet);
  899. }
  900. }
  901. else {
  902. status = SubmitUrbIrp( adapter->nextDevObj,
  903. irp,
  904. urb,
  905. FALSE, // asynchronous
  906. ControlPipeWriteCompletion, // completion routine
  907. packet // completion context
  908. );
  909. }
  910. return status;
  911. }
  912. NTSTATUS ControlPipeWriteCompletion(IN PDEVICE_OBJECT devObj, IN PIRP irp, IN PVOID context)
  913. {
  914. USBPACKET *packet = (USBPACKET *)context;
  915. ADAPTEREXT *adapter = packet->adapter;
  916. NTSTATUS status = irp->IoStatus.Status;
  917. KIRQL oldIrql;
  918. ASSERT(packet->sig == DRIVER_SIG);
  919. ASSERT(adapter->sig == DRIVER_SIG);
  920. ASSERT(packet->irpPtr == irp);
  921. ASSERT(!irp->CancelRoutine);
  922. ASSERT(status != STATUS_PENDING); // saw UHCD doing this ?
  923. if (NT_SUCCESS(status)){
  924. DBGVERBOSE(("ControlPipeWriteCompletion: packet # %xh completed.", packet->packetId));
  925. }
  926. else {
  927. DBGWARN(("ControlPipeWriteCompletion: packet # %xh failed with status %xh on adapter %xh.", packet->packetId, status, adapter));
  928. }
  929. IndicateSendStatusToRNdis(packet, status);
  930. /*
  931. * Dequeue the packet from the usbPendingWritePackets queue
  932. * BEFORE checking if it was cancelled to avoid race with CancelAllPendingPackets.
  933. */
  934. DequeuePendingWritePacket(packet);
  935. if (packet->cancelled){
  936. /*
  937. * This packet was cancelled because of a halt or reset.
  938. * Put the packet back in the free list first, then
  939. * set the event so CancelAllPendingPackets can proceed.
  940. */
  941. DBGVERBOSE((" ... write packet #%xh cancelled.", packet->packetId));
  942. packet->cancelled = FALSE;
  943. EnqueueFreePacket(packet);
  944. KeSetEvent(&packet->cancelEvent, 0, FALSE);
  945. }
  946. else {
  947. EnqueueFreePacket(packet);
  948. }
  949. if (NT_SUCCESS(status)){
  950. }
  951. else {
  952. #if DO_FULL_RESET
  953. adapter->needFullReset = TRUE;
  954. QueueAdapterWorkItem(adapter);
  955. #endif
  956. }
  957. return STATUS_MORE_PROCESSING_REQUIRED;
  958. }
  959. NTSTATUS ReadPacketFromControlPipe(USBPACKET *packet, BOOLEAN synchronous)
  960. {
  961. NTSTATUS status;
  962. ADAPTEREXT *adapter = packet->adapter;
  963. PURB urb = packet->urbPtr;
  964. PIRP irp = packet->irpPtr;
  965. PUSBD_INTERFACE_INFORMATION interfaceInfoControl;
  966. ULONG bytesToRead = MAXIMUM_DEVICE_MESSAGE_SIZE+1;
  967. DBGVERBOSE(("ReadPacketFromControlPipe: read %xh bytes, packet #%xh.", bytesToRead, packet->packetId));
  968. ASSERT(adapter->interfaceInfoMaster);
  969. interfaceInfoControl = adapter->interfaceInfoMaster;
  970. urb->UrbHeader.Length = (USHORT) sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
  971. urb->UrbHeader.Function = URB_FUNCTION_CLASS_INTERFACE;
  972. urb->UrbControlVendorClassRequest.Reserved = 0;
  973. urb->UrbControlVendorClassRequest.TransferFlags = USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_IN;
  974. urb->UrbControlVendorClassRequest.TransferBufferLength = bytesToRead;
  975. urb->UrbControlVendorClassRequest.TransferBuffer = packet->dataBuffer;
  976. urb->UrbControlVendorClassRequest.TransferBufferMDL = NULL;
  977. urb->UrbControlVendorClassRequest.UrbLink = NULL;
  978. urb->UrbControlVendorClassRequest.RequestTypeReservedBits = 0;
  979. urb->UrbControlVendorClassRequest.Request = NATIVE_RNDIS_GET_ENCAPSULATED_RESPONSE;
  980. urb->UrbControlVendorClassRequest.Value = 0;
  981. urb->UrbControlVendorClassRequest.Index = interfaceInfoControl->InterfaceNumber;
  982. urb->UrbControlVendorClassRequest.Reserved1 = 0;
  983. if (synchronous){
  984. status = SubmitUrbIrp(adapter->nextDevObj, irp, urb, TRUE, NULL, NULL);
  985. }
  986. else {
  987. status = SubmitUrbIrp( adapter->nextDevObj,
  988. irp,
  989. urb,
  990. FALSE, // asynchronous
  991. ControlPipeReadCompletion, // completion routine
  992. packet // completion context
  993. );
  994. }
  995. ASSERT(NT_SUCCESS(status));
  996. return status;
  997. }
  998. NTSTATUS ControlPipeReadCompletion(IN PDEVICE_OBJECT devObj, IN PIRP irp, IN PVOID context)
  999. {
  1000. USBPACKET *packet = (USBPACKET *)context;
  1001. ADAPTEREXT *adapter = packet->adapter;
  1002. NTSTATUS status = irp->IoStatus.Status;
  1003. KIRQL oldIrql;
  1004. ASSERT(packet->sig == DRIVER_SIG);
  1005. ASSERT(adapter->sig == DRIVER_SIG);
  1006. ASSERT(packet->irpPtr == irp);
  1007. ASSERT(!irp->CancelRoutine);
  1008. ASSERT(status != STATUS_PENDING); // saw UHCD doing this ?
  1009. /*
  1010. * Dequeue the packet from the usbPendingReadPackets queue
  1011. * BEFORE checking if it was cancelled to avoid race with CancelAllPendingPackets.
  1012. */
  1013. DequeuePendingReadPacket(packet);
  1014. if (packet->cancelled){
  1015. /*
  1016. * This packet was cancelled because of a halt or reset.
  1017. * Get the packet is back in the free list first, then
  1018. * set the event so CancelAllPendingPackets can proceed.
  1019. */
  1020. DBGVERBOSE((" ... read packet #%xh cancelled.", packet->packetId));
  1021. packet->cancelled = FALSE;
  1022. EnqueueFreePacket(packet);
  1023. KeSetEvent(&packet->cancelEvent, 0, FALSE);
  1024. }
  1025. else if (adapter->halting){
  1026. EnqueueFreePacket(packet);
  1027. }
  1028. else {
  1029. if (NT_SUCCESS(status)){
  1030. PURB urb = packet->urbPtr;
  1031. /*
  1032. * Fix the packet's dataBufferCurrentLength to indicate the actual length
  1033. * of the returned data.
  1034. * Note: the KLSI device rounds this up to a multiple of the endpoint
  1035. * packet size, so the returned length may actually be larger than
  1036. * the actual data.
  1037. */
  1038. packet->dataBufferCurrentLength = urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
  1039. ASSERT(packet->dataBufferCurrentLength);
  1040. ASSERT(packet->dataBufferCurrentLength <= packet->dataBufferMaxLength);
  1041. DBGVERBOSE(("ControlPipeReadCompletion: packet # %xh.", packet->packetId));
  1042. DBGSHOWBYTES("ControlPipeReadCompletion", packet->dataBuffer, packet->dataBufferCurrentLength);
  1043. EnqueueCompletedReadPacket(packet);
  1044. status = IndicateRndisMessage(packet, FALSE);
  1045. if (status != STATUS_PENDING){
  1046. DequeueCompletedReadPacket(packet);
  1047. EnqueueFreePacket(packet);
  1048. }
  1049. }
  1050. else {
  1051. /*
  1052. * The read failed. Put the packet back in the free list.
  1053. */
  1054. DBGWARN(("ControlPipeReadCompletion: read failed with status %xh on adapter %xh.", status, adapter));
  1055. EnqueueFreePacket(packet);
  1056. #if DO_FULL_RESET
  1057. adapter->needFullReset = TRUE;
  1058. QueueAdapterWorkItem(adapter);
  1059. #endif
  1060. }
  1061. }
  1062. return STATUS_MORE_PROCESSING_REQUIRED;
  1063. }
  1064. NTSTATUS CallDriverSync(PDEVICE_OBJECT devObj, PIRP irp)
  1065. /*++
  1066. Routine Description:
  1067. Call IoCallDriver to send the irp to the device object;
  1068. then, synchronize with the completion routine.
  1069. When CallDriverSync returns, the action has completed
  1070. and the irp again belongs to the current driver.
  1071. NOTE: In order to keep the device object from getting freed
  1072. while this IRP is pending, you should call
  1073. IncrementPendingActionCount() and
  1074. DecrementPendingActionCount()
  1075. around the CallDriverSync call.
  1076. Arguments:
  1077. devObj - targetted device object
  1078. irp - Io Request Packet
  1079. Return Value:
  1080. NT status code, indicates result returned by lower driver for this IRP.
  1081. --*/
  1082. {
  1083. KEVENT event;
  1084. NTSTATUS status;
  1085. ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
  1086. KeInitializeEvent(&event, NotificationEvent, FALSE);
  1087. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  1088. IoSetCompletionRoutine( irp,
  1089. CallDriverSyncCompletion,
  1090. &event, // context
  1091. TRUE, TRUE, TRUE);
  1092. status = IoCallDriver(devObj, irp);
  1093. KeWaitForSingleObject( &event,
  1094. Executive, // wait reason
  1095. KernelMode,
  1096. FALSE, // not alertable
  1097. NULL ); // no timeout
  1098. status = irp->IoStatus.Status;
  1099. ASSERT(status != STATUS_PENDING);
  1100. if (!NT_SUCCESS(status)){
  1101. DBGWARN(("CallDriverSync: irp failed w/ status %xh.", status));
  1102. }
  1103. return status;
  1104. }
  1105. NTSTATUS CallDriverSyncCompletion(IN PDEVICE_OBJECT devObjOrNULL, IN PIRP irp, IN PVOID context)
  1106. /*++
  1107. Routine Description:
  1108. Completion routine for CallDriverSync.
  1109. Arguments:
  1110. devObjOrNULL -
  1111. Usually, this is this driver's device object.
  1112. However, if this driver created the IRP,
  1113. there is no stack location in the IRP for this driver;
  1114. so the kernel has no place to store the device object;
  1115. ** so devObj will be NULL in this case **.
  1116. irp - completed Io Request Packet
  1117. context - context passed to IoSetCompletionRoutine by CallDriverSync.
  1118. Return Value:
  1119. NT status code, indicates result returned by lower driver for this IRP.
  1120. --*/
  1121. {
  1122. PKEVENT event = context;
  1123. ASSERT(!irp->CancelRoutine);
  1124. if (!NT_SUCCESS(irp->IoStatus.Status)){
  1125. DBGWARN(("CallDriverSyncCompletion: irp failed w/ status %xh.", irp->IoStatus.Status));
  1126. }
  1127. KeSetEvent(event, 0, FALSE);
  1128. return STATUS_MORE_PROCESSING_REQUIRED;
  1129. }
  1130. #if 0
  1131. NTSTATUS GetStringDescriptor( ADAPTEREXT *adapter,
  1132. UCHAR stringIndex,
  1133. PUCHAR buffer,
  1134. ULONG bufferLen)
  1135. /*++
  1136. Routine Description:
  1137. Function retrieves a string descriptor from the device
  1138. Arguments:
  1139. adapter - adapter context
  1140. Return Value:
  1141. NT status code
  1142. --*/
  1143. {
  1144. URB urb;
  1145. NTSTATUS status;
  1146. UsbBuildGetDescriptorRequest(&urb,
  1147. (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  1148. USB_STRING_DESCRIPTOR_TYPE,
  1149. stringIndex,
  1150. 0x0409, // language = US English
  1151. buffer,
  1152. NULL,
  1153. bufferLen,
  1154. NULL);
  1155. status = SubmitUrb(adapter->nextDevObj, &urb, TRUE, NULL, NULL);
  1156. if (NT_SUCCESS(status)){
  1157. DBGVERBOSE(("Got string desc (index %xh) @ %ph, len = %xh.", (ULONG)stringIndex, buffer, urb.UrbControlDescriptorRequest.TransferBufferLength));
  1158. ASSERT(urb.UrbControlDescriptorRequest.TransferBufferLength <= bufferLen);
  1159. }
  1160. else {
  1161. DBGERR(("GetStringDescriptor: failed to get string (index %xh) with status %xh on adapter %xh.", (ULONG)stringIndex, status, adapter));
  1162. }
  1163. ASSERT(NT_SUCCESS(status));
  1164. return status;
  1165. }
  1166. /*
  1167. * CreateSingleInterfaceConfigDesc
  1168. *
  1169. * Allocate a configuration descriptor that excludes all interfaces
  1170. * but the given interface
  1171. * (e.g. for multiple-interface devices like the Intel cable modem,
  1172. * for which we don't load on top of the generic parent).
  1173. *
  1174. * Note: interfaceDesc must point inside configDesc.
  1175. *
  1176. */
  1177. PUSB_CONFIGURATION_DESCRIPTOR CreateSingleInterfaceConfigDesc(
  1178. PUSB_CONFIGURATION_DESCRIPTOR configDesc,
  1179. PUSB_INTERFACE_DESCRIPTOR interfaceDesc)
  1180. {
  1181. PUSB_CONFIGURATION_DESCRIPTOR ifaceConfigDesc;
  1182. ASSERT(interfaceDesc);
  1183. ASSERT((PVOID)interfaceDesc > (PVOID)configDesc);
  1184. ASSERT((PUCHAR)interfaceDesc - (PUCHAR)configDesc < configDesc->wTotalLength);
  1185. ifaceConfigDesc = AllocPool(configDesc->wTotalLength);
  1186. if (ifaceConfigDesc){
  1187. PUSB_COMMON_DESCRIPTOR srcDesc, newDesc;
  1188. USHORT totalLen;
  1189. /*
  1190. * Copy the configuration descriptor itself.
  1191. */
  1192. RtlCopyMemory(ifaceConfigDesc, configDesc, configDesc->bLength);
  1193. totalLen = configDesc->bLength;
  1194. /*
  1195. * Copy the given interface descriptor.
  1196. */
  1197. srcDesc = (PUSB_COMMON_DESCRIPTOR)interfaceDesc;
  1198. newDesc = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)ifaceConfigDesc + ifaceConfigDesc->bLength);
  1199. RtlCopyMemory(newDesc, srcDesc, srcDesc->bLength);
  1200. totalLen += srcDesc->bLength;
  1201. srcDesc = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)srcDesc + srcDesc->bLength);
  1202. newDesc = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)newDesc + newDesc->bLength);
  1203. /*
  1204. * Copy the given interface descriptors and all following descriptors
  1205. * up to either the next interface descriptor or the end of the original
  1206. * configuration descriptor.
  1207. */
  1208. while ((PUCHAR)srcDesc - (PUCHAR)configDesc < configDesc->wTotalLength){
  1209. if (srcDesc->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE){
  1210. break;
  1211. }
  1212. else {
  1213. RtlCopyMemory(newDesc, srcDesc, srcDesc->bLength);
  1214. totalLen += srcDesc->bLength;
  1215. srcDesc = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)srcDesc + srcDesc->bLength);
  1216. newDesc = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)newDesc + newDesc->bLength);
  1217. }
  1218. }
  1219. ifaceConfigDesc->bNumInterfaces = 1;
  1220. ifaceConfigDesc->wTotalLength = totalLen;
  1221. DBGVERBOSE(("CreateSingleInterfaceConfigDesc: build partial configDesc @ %ph, len=%xh.", ifaceConfigDesc, ifaceConfigDesc->wTotalLength));
  1222. }
  1223. return ifaceConfigDesc;
  1224. }
  1225. #endif