diff --git a/userspace/busenum.c b/userspace/busenum.c index c91d6b1a..da37fbbd 100755 --- a/userspace/busenum.c +++ b/userspace/busenum.c @@ -352,7 +352,7 @@ int process_write_irp(PPDO_DEVICE_DATA pdodata, PIRP irp) struct _URB_ISOCH_TRANSFER *urb; struct usbip_iso_packet_descriptor * ip_desc; NTSTATUS ioctl_status = STATUS_INVALID_PARAMETER; - int found=0, iso_len=0, in_len=0; + int found=0, iso_len=0, in_len=0, send; struct urb_req * urb_r; irpstack = IoGetCurrentIrpStackLocation (irp); @@ -368,9 +368,12 @@ int process_write_irp(PPDO_DEVICE_DATA pdodata, PIRP irp) le = le->Flink) { urb_r = CONTAINING_RECORD (le, struct urb_req, list); if(urb_r->seq_num == h->base.seqnum){ - found=1; - RemoveEntryList (le); ioctl_irp = urb_r->irp; + if(IoSetCancelRoutine(ioctl_irp, NULL)){ + found=1; + RemoveEntryList (le); + send = urb_r->send; + } break; } } @@ -379,14 +382,14 @@ int process_write_irp(PPDO_DEVICE_DATA pdodata, PIRP irp) KdPrint(("can't found %d\n", h->base.seqnum)); return STATUS_INVALID_PARAMETER; } + ExFreeToNPagedLookasideList(&g_lookaside, urb_r); irp->IoStatus.Information = len; irpstack = IoGetCurrentIrpStackLocation(ioctl_irp); - if(!urb_r->send){ + if(!send){ KdPrint(("Warning, recv not send")); ioctl_status = STATUS_INVALID_PARAMETER; goto end; } - ExFreeToNPagedLookasideList(&g_lookaside, urb_r); switch ( irpstack->Parameters.DeviceIoControl.IoControlCode ){ case IOCTL_INTERNAL_USB_SUBMIT_URB: break; @@ -1074,37 +1077,21 @@ int process_read_irp(PPDO_DEVICE_DATA pdodata, PIRP read_irp) IoMarkIrpPending(read_irp); pdodata->pending_read_irp = read_irp; } + KeReleaseSpinLock(&pdodata->q_lock, oldirql); + return status; } - KeReleaseSpinLock(&pdodata->q_lock, oldirql); - if(NULL==ioctl_irp) - return status; if(old_seq_num) KdPrint(("Error, why old_seq_num %d\n", old_seq_num)); KdPrint(("get a ioctl_irp %p %d\n", ioctl_irp, seq_num)); status = set_read_irp_data(read_irp, ioctl_irp, seq_num, pdodata->devid); - if(status == STATUS_SUCCESS) + if(status == STATUS_SUCCESS||!IoSetCancelRoutine(ioctl_irp, NULL)){ + KeReleaseSpinLock(&pdodata->q_lock, oldirql); return status; - /* set_read_irp failed, we must complete ioctl_irp */ - found=0; - KeAcquireSpinLock(&pdodata->q_lock, &oldirql); - for (le = pdodata->ioctl_q.Flink; - le !=&pdodata->ioctl_q; - le = le->Flink) { - urb_r = CONTAINING_RECORD(le, struct urb_req, list); - if(urb_r->seq_num == seq_num){ - found = 1; - RemoveEntryList(le); - break; - } } + /* set_read_irp failed, we must complete ioctl_irp */ + RemoveEntryList (le); KeReleaseSpinLock(&pdodata->q_lock, oldirql); - if(!found){ /* perhaps it complete by other */ - KdPrint(("Warning, we can't found irp we should release")); - return status; - } ExFreeToNPagedLookasideList(&g_lookaside, urb_r); - if(urb_r->send!=1||urb_r->irp!=ioctl_irp) - KdPrint(("Warning, why it change")); ioctl_irp->IoStatus.Status = STATUS_INVALID_PARAMETER; IoCompleteRequest (ioctl_irp, IO_NO_INCREMENT); return status; @@ -1625,6 +1612,38 @@ int proc_urb(PPDO_DEVICE_DATA pdodata, void *arg) return STATUS_INVALID_PARAMETER; } +void cancel_irp(PDEVICE_OBJECT pdo, PIRP Irp) +{ + PLIST_ENTRY le = NULL; + int found=0; + struct urb_req * urb_r; + PPDO_DEVICE_DATA pdodata; + KIRQL oldirql = Irp->CancelIrql; + + pdodata = (PPDO_DEVICE_DATA) pdo->DeviceExtension; + IoReleaseCancelSpinLock(DISPATCH_LEVEL); + KdPrint(("Cancle Irp %p called", Irp)); + KeAcquireSpinLockAtDpcLevel(&pdodata->q_lock); + for (le = pdodata->ioctl_q.Flink; + le != &pdodata->ioctl_q; + le = le->Flink) { + urb_r = CONTAINING_RECORD (le, struct urb_req, list); + if(urb_r->irp == Irp){ + found=1; + RemoveEntryList (le); + break; + } + } + KeReleaseSpinLock(&pdodata->q_lock, oldirql); + if(found){ + ExFreeToNPagedLookasideList(&g_lookaside, urb_r); + } else { + KdPrint(("Warning, why we can't found it?")); + } + Irp->IoStatus.Status = STATUS_CANCELLED; + IoCompleteRequest(Irp, IO_NO_INCREMENT); +} + int try_addq(PPDO_DEVICE_DATA pdodata, PIRP Irp) { KIRQL oldirql; @@ -1642,9 +1661,15 @@ int try_addq(PPDO_DEVICE_DATA pdodata, PIRP Irp) read_irp = pdodata->pending_read_irp; pdodata->pending_read_irp=NULL; if(NULL==read_irp){ - IoMarkIrpPending(Irp); - IoSetCancelRoutine(Irp, NULL); - InsertTailList(&pdodata->ioctl_q, &urb_r->list); + IoSetCancelRoutine(Irp, cancel_irp); + if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL)) { + KeReleaseSpinLock(&pdodata->q_lock, oldirql); + ExFreeToNPagedLookasideList(&g_lookaside, urb_r); + return STATUS_CANCELLED; + } else { + IoMarkIrpPending(Irp); + InsertTailList(&pdodata->ioctl_q, &urb_r->list); + } } else seq_num = ++(pdodata->seq_num); KeReleaseSpinLock(&pdodata->q_lock, oldirql); @@ -1654,12 +1679,18 @@ int try_addq(PPDO_DEVICE_DATA pdodata, PIRP Irp) pdodata->devid); if(read_irp->IoStatus.Status == STATUS_SUCCESS){ KeAcquireSpinLock(&pdodata->q_lock, &oldirql); - IoMarkIrpPending(Irp); urb_r->send = 1; urb_r->seq_num = seq_num; - IoSetCancelRoutine(Irp, NULL); - InsertTailList(&pdodata->ioctl_q, &urb_r->list); - KeReleaseSpinLock(&pdodata->q_lock, oldirql); + IoSetCancelRoutine(Irp, cancel_irp); + if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL)) { + KeReleaseSpinLock(&pdodata->q_lock, oldirql); + ExFreeToNPagedLookasideList(&g_lookaside, urb_r); + status = STATUS_CANCELLED; + } else { + IoMarkIrpPending(Irp); + InsertTailList(&pdodata->ioctl_q, &urb_r->list); + KeReleaseSpinLock(&pdodata->q_lock, oldirql); + } } else { ExFreeToNPagedLookasideList(&g_lookaside, urb_r); status = STATUS_INVALID_PARAMETER; @@ -1695,15 +1726,13 @@ Bus_Internal_IoCtl ( } pdoData = (PPDO_DEVICE_DATA) DeviceObject->DeviceExtension; - #if 0 if (pdoData->Present==FALSE) { - Irp->IoStatus.Status = status = STATUS_DEVICE_OFF_LINE; + Irp->IoStatus.Status = status = STATUS_DEVICE_NOT_CONNECTED; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } #endif - buffer = Irp->AssociatedIrp.SystemBuffer; inlen = irpStack->Parameters.DeviceIoControl.InputBufferLength; diff --git a/userspace/pnp.c b/userspace/pnp.c index fa34bfc7..742e045a 100755 --- a/userspace/pnp.c +++ b/userspace/pnp.c @@ -1018,23 +1018,26 @@ void complete_pending_read_irp(PPDO_DEVICE_DATA pdodata) KeReleaseSpinLock(&pdodata->q_lock, oldirql); if(NULL==irp) return; - irp->IoStatus.Status = STATUS_DEVICE_OFF_LINE; + irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED; IoCompleteRequest (irp, IO_NO_INCREMENT); return; } void complete_pending_irp(PPDO_DEVICE_DATA pdodata) { - KIRQL oldirql; PIRP irp; struct urb_req * urb_r; PLIST_ENTRY le; + KIRQL oldirql; + int count=0; //FIXME + KdPrint(("finish pending irp")); + KeRaiseIrql(DISPATCH_LEVEL, &oldirql); do { irp=NULL; le=NULL; - KeAcquireSpinLock(&pdodata->q_lock, &oldirql); + KeAcquireSpinLockAtDpcLevel(&pdodata->q_lock); if (!IsListEmpty(&pdodata->ioctl_q)) le = RemoveHeadList(&pdodata->ioctl_q); if(le){ @@ -1042,42 +1045,25 @@ void complete_pending_irp(PPDO_DEVICE_DATA pdodata) /* FIMXE event */ irp = urb_r->irp; } - if(NULL==irp){ - irp=pdodata->pending_read_irp; - pdodata->pending_read_irp=NULL; - } - KeReleaseSpinLock(&pdodata->q_lock, oldirql); - if(le) - ExFreeToNPagedLookasideList(&g_lookaside, urb_r); - if(NULL==irp) + if(irp==NULL){ + KeReleaseSpinLock(&pdodata->q_lock, oldirql); break; - irp->IoStatus.Status = STATUS_DEVICE_OFF_LINE; - if(le) + } + if(count>2){ + KeReleaseSpinLock(&pdodata->q_lock, oldirql); + KdPrint(("sleep 50ms, let pnp manager send irp")); + KeDelayExecutionThread(KernelMode, FALSE, -500000); KeRaiseIrql(DISPATCH_LEVEL, &oldirql); + } else { + KeReleaseSpinLock(&pdodata->q_lock, DISPATCH_LEVEL); + } + ExFreeToNPagedLookasideList(&g_lookaside, urb_r); + irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED; IoCompleteRequest (irp, IO_NO_INCREMENT); - if(le) - KeLowerIrql(oldirql); + count++; }while(1); } - -VOID DpcRoutine(PKDPC dpc, PVOID context, PVOID junk1, PVOID junk2) -{ - PPDO_DEVICE_DATA pdodata = context; - complete_pending_irp(pdodata); - return; -} - -void sched_complete_irp(PPDO_DEVICE_DATA pdodata) -{ - LARGE_INTEGER duetime; - duetime.QuadPart=-50000000; - - KeInitializeTimer(&pdodata->timer); - KeInitializeDpc(&pdodata->dpc, DpcRoutine, pdodata); - KeSetTimer(&pdodata->timer, duetime, &pdodata->dpc); -} - NTSTATUS Bus_DestroyPdo ( PDEVICE_OBJECT Device, @@ -1406,8 +1392,7 @@ bus_unplug_dev ( Bus_KdPrint (fdodata, BUS_DBG_IOCTL_INFO, ("Plugged out %d\n", pdodata->SerialNo)); pdodata->Present = FALSE; - complete_pending_read_irp(pdodata); - sched_complete_irp(pdodata); + complete_pending_read_irp(pdodata); found = 1; if (!all) { break; @@ -1419,11 +1404,25 @@ bus_unplug_dev ( if (found) { IoInvalidateDeviceRelations (fdodata->UnderlyingPDO, BusRelations); - return STATUS_SUCCESS; - } + ExAcquireFastMutex (&fdodata->Mutex); + + for (entry = fdodata->ListOfPDOs.Flink; + entry != &fdodata->ListOfPDOs; + entry = entry->Flink) { + + pdodata = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); + + if( pdodata->Present ==FALSE){ + complete_pending_irp(pdodata); + } + } + ExReleaseFastMutex (&fdodata->Mutex); Bus_KdPrint (fdodata, BUS_DBG_IOCTL_ERROR, ("Device %d is not present\n", addr)); + return STATUS_SUCCESS; + } + return STATUS_INVALID_PARAMETER; }