public static extern ReturnCode DsmWinNew( [In, Out] TWIdentity origin, [In, Out] TWIdentity destination, DataGroups dg, DataArgumentType dat, Message msg, [In, Out] TWPendingXfers data);
public static ReturnCode DsmEntry( TWIdentity origin, TWIdentity destination, Message msg, TWPendingXfers data) { if (PlatformInfo.Current.IsWindows) { if (PlatformInfo.Current.UseNewWinDSM) { return(NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.PendingXfers, msg, data)); } else { return(NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.PendingXfers, msg, data)); } } else if (PlatformInfo.Current.IsLinux) { return(NativeMethods.DsmLinux(origin, destination, DataGroups.Control, DataArgumentType.PendingXfers, msg, data)); } throw new PlatformNotSupportedException(); }
/// <summary> /// If CapAutoScan is TRUE, this command will stop the operation of the scanner’s automatic /// feeder. No other action is taken. /// </summary> /// <param name="pendingXfers">The pending xfers.</param> /// <returns></returns> public ReturnCode StopFeeder(TWPendingXfers pendingXfers) { Session.VerifyState(6, 6, DataGroups.Control, DataArgumentType.PendingXfers, Message.StopFeeder); return(Dsm.DsmEntry(Session.AppId, Session.CurrentSource.Identity, Message.StopFeeder, pendingXfers)); }
/// <summary> /// Sets the number of pending transfers in the Source to zero. /// </summary> /// <param name="pendingXfers">The pending xfers.</param> /// <returns></returns> internal ReturnCode Reset(TWPendingXfers pendingXfers) { Session.VerifyState(6, 6, DataGroups.Control, DataArgumentType.PendingXfers, Message.Reset); return(Dsm.DsmEntry(Session.AppId, Session.CurrentSource.Identity, Message.Reset, pendingXfers)); }
/// <summary> /// Forces the stepping down of an opened source when things gets out of control. /// Used when session state and source state become out of sync. /// </summary> /// <param name="targetState">State of the target.</param> public void ForceStepDown(int targetState) { PlatformInfo.Current.Log.Debug("Thread {0}: ForceStepDown.", Thread.CurrentThread.ManagedThreadId); bool origFlag = EnforceState; EnforceState = false; // From the twain spec // Stepping Back Down the States // DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER → state 7 to 6 // DG_CONTROL / DAT_PENDINGXFERS / MSG_RESET → state 6 to 5 // DG_CONTROL / DAT_USERINTERFACE / MSG_DISABLEDS → state 5 to 4 // DG_CONTROL / DAT_IDENTITY / MSG_CLOSEDS → state 4 to 3 // Ignore the status returns from the calls prior to the one yielding the desired state. For instance, if a // call during scanning returns TWCC_SEQERROR and the desire is to return to state 5, then use the // following commands. // DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER → state 7 to 6 // DG_CONTROL / DAT_PENDINGXFERS / MSG_RESET → state 6 to 5 // Being sure to confirm that DG_CONTROL / DAT_PENDINGXFERS / MSG_RESET returned // success, the return status from DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER may // be ignored. _msgLoopHook?.Invoke(() => { if (targetState < 7 && CurrentSource != null) { // not sure if really necessary but can't hurt to pin it var pending = new TWPendingXfers(); var handle = GCHandle.Alloc(pending, GCHandleType.Pinned); try { ((ITwainSessionInternal)this).DGControl.PendingXfers.EndXfer(pending); } finally { handle.Free(); } } if (targetState < 6 && CurrentSource != null) { var pending = new TWPendingXfers(); var handle = GCHandle.Alloc(pending, GCHandleType.Pinned); try { ((ITwainSessionInternal)this).DGControl.PendingXfers.Reset(pending); } finally { handle.Free(); } } if (targetState < 5 && CurrentSource != null) { ((ITwainSessionInternal)this).DisableSource(); } if (targetState < 4 && CurrentSource != null) { CurrentSource.Close(); } if (targetState < 3) { Close(); } }); EnforceState = origFlag; }
/// <summary> /// Performs the TWAIN transfer routine at state 6. /// </summary> public static void DoTransferRoutine(ITwainSessionInternal session) { #region get xfer types bool xferImage = true; // default to always xfer image bool xferAudio = false; DataGroups xferGroup = DataGroups.None; XferMech imgXferMech = XferMech.Native; XferMech audXferMech = XferMech.Native; if (session.DGControl.XferGroup.Get(ref xferGroup) == ReturnCode.Success) { xferAudio = (xferGroup & DataGroups.Audio) == DataGroups.Audio; // check for Plustek OpticSlim 2680H, this scanner returns wrong xferGroup after first scanning if (session.CurrentSource.Identity.ProductName.IndexOf("Plustek", StringComparison.OrdinalIgnoreCase) > -1 && session.CurrentSource.Identity.ProductName.IndexOf("OpticSlim", StringComparison.OrdinalIgnoreCase) > -1 && session.CurrentSource.Identity.ProductName.IndexOf("2680H", StringComparison.OrdinalIgnoreCase) > -1) { xferImage = true; } else { xferImage = xferGroup == DataGroups.None || (xferGroup & DataGroups.Image) == DataGroups.Image; } } // some DS end up getting none but we will assume it's image if (xferImage) { imgXferMech = session.CurrentSource.Capabilities.ICapXferMech.GetCurrent(); } if (xferAudio) { var mech = session.CurrentSource.Capabilities.ACapXferMech.GetCurrent(); } #endregion var pending = new TWPendingXfers(); var rc = session.DGControl.PendingXfers.Get(pending); if (rc == ReturnCode.Success) { do { #region raise xfer ready var preXferArgs = new TransferReadyEventArgs(session.CurrentSource, pending.Count, pending.EndOfJob);; session.SafeSyncableRaiseEvent(preXferArgs); #endregion #region actually handle xfer if (preXferArgs.CancelAll || session.CloseDSRequested) { rc = session.DGControl.PendingXfers.Reset(pending); } else { if (!preXferArgs.CancelCurrent) { if (xferImage) { switch (imgXferMech) { case XferMech.Memory: rc = DoImageMemoryXfer(session); break; case XferMech.File: rc = DoImageFileXfer(session); break; case XferMech.MemFile: rc = DoImageMemoryFileXfer(session); break; case XferMech.Native: default: // always assume native rc = DoImageNativeXfer(session); break; } } if (xferAudio) { switch (audXferMech) { case XferMech.File: rc = DoAudioFileXfer(session); break; case XferMech.Native: default: // always assume native rc = DoAudioNativeXfer(session); break; } } } if (rc != ReturnCode.Success && session.StopOnTransferError) { // end xfer without setting rc to exit (good/bad?) session.DGControl.PendingXfers.Reset(pending); } else { rc = session.DGControl.PendingXfers.EndXfer(pending); } } #endregion } while (rc == ReturnCode.Success && pending.Count != 0 && !session.CloseDSRequested); } else { HandleReturnCode(session, rc); } // some poorly written scanner drivers return failure on EndXfer so also check for pending count now. // this may break with other sources but we'll see if (//pending.Count == 0 && session.State > 5) { session.ChangeState(5, true); session.DisableSource(); } }