private void IoControl(IoCtrl ioControlCode, IntPtr inBuffer, int inBufferSize, IntPtr outBuffer, int outBufferSize, out int bytesReturned) { if (!_deviceAvailable) throw new InvalidOperationException("Device not available"); using (WaitHandle waitHandle = new ManualResetEvent(false)) { SafeHandle safeWaitHandle = waitHandle.SafeWaitHandle; bool success = false; safeWaitHandle.DangerousAddRef(ref success); if (!success) throw new InvalidOperationException("Failed to initialize safe wait handle"); try { int lastError; IntPtr dangerousWaitHandle = safeWaitHandle.DangerousGetHandle(); DeviceIoOverlapped overlapped = new DeviceIoOverlapped(); overlapped.ClearAndSetEvent(dangerousWaitHandle); bool deviceIoControl = DeviceIoControl(_eHomeHandle, ioControlCode, inBuffer, inBufferSize, outBuffer, outBufferSize, out bytesReturned, overlapped.Overlapped); lastError = Marshal.GetLastWin32Error(); if (!deviceIoControl) { // Now also handles Operation Aborted and Bad Command errors. switch (lastError) { case ErrorIoPending: waitHandle.WaitOne(); bool getOverlapped = GetOverlappedResult(_eHomeHandle, overlapped.Overlapped, out bytesReturned, false); lastError = Marshal.GetLastWin32Error(); if (!getOverlapped) { if (lastError == ErrorBadCommand) goto case ErrorBadCommand; if (lastError == ErrorOperationAborted) goto case ErrorOperationAborted; throw new Win32Exception(lastError); } break; case ErrorBadCommand: if (Thread.CurrentThread == _readThread) //Cause receive restart _deviceReceiveStarted = false; break; case ErrorOperationAborted: if (Thread.CurrentThread != _readThread) throw new Win32Exception(lastError); //Cause receive restart _deviceReceiveStarted = false; break; default: throw new Win32Exception(lastError); } } } catch { IrssUtils.IrssLog.Debug("IoControl: something went bad with StructToPtr or the other way around"); if (_eHomeHandle != null) CancelIo(_eHomeHandle); throw; } finally { safeWaitHandle.DangerousRelease(); } } //IrssUtils.IrssLog.Debug("IoControl: End of [{0}]", ioControlCode.ToString()); //IrssUtils.IrssLog.Close(); }
/// <summary> /// Device read thread method. /// </summary> private void ReadThread() { byte[] packetBytes; WaitHandle waitHandle = new ManualResetEvent(false); SafeHandle safeWaitHandle = waitHandle.SafeWaitHandle; WaitHandle[] waitHandles = new WaitHandle[] { waitHandle, _stopReadThread }; IntPtr deviceBufferPtr = IntPtr.Zero; bool success = false; safeWaitHandle.DangerousAddRef(ref success); if (!success) { throw new InvalidOperationException("Failed to initialize safe wait handle"); } try { IntPtr dangerousWaitHandle = safeWaitHandle.DangerousGetHandle(); DeviceIoOverlapped overlapped = new DeviceIoOverlapped(); overlapped.ClearAndSetEvent(dangerousWaitHandle); deviceBufferPtr = Marshal.AllocHGlobal(DeviceBufferSize); while (_readThreadMode != ReadThreadMode.Stop) { int lastError; int bytesRead; bool readDevice = ReadFile(_readHandle, deviceBufferPtr, DeviceBufferSize, out bytesRead, overlapped.Overlapped); lastError = Marshal.GetLastWin32Error(); if (!readDevice) { if (lastError != ErrorSuccess && lastError != ErrorIoPending) { throw new Win32Exception(lastError); } while (true) { int handle = WaitHandle.WaitAny(waitHandles, 2 * PacketTimeout, false); if (handle == ErrorWaitTimeout) { continue; } if (handle == 0) { break; } if (handle == 1) { throw new ThreadInterruptedException("Read thread stopping by request"); } throw new InvalidOperationException(String.Format("Invalid wait handle return: {0}", handle)); } bool getOverlapped = GetOverlappedResult(_readHandle, overlapped.Overlapped, out bytesRead, true); lastError = Marshal.GetLastWin32Error(); if (!getOverlapped && lastError != ErrorSuccess) { throw new Win32Exception(lastError); } } if (bytesRead == 0) { continue; } packetBytes = new byte[bytesRead]; Marshal.Copy(deviceBufferPtr, packetBytes, 0, bytesRead); DebugWrite("Received bytes ({0}): ", bytesRead); DebugDump(packetBytes); int[] timingData = null; if (_decodeCarry != 0 || packetBytes[0] >= 0x81 && packetBytes[0] <= 0x9E) { timingData = GetTimingDataFromPacket(packetBytes); } else { double firmware = 0.0; int indexOfFF = Array.IndexOf(packetBytes, (byte)0xFF); while (indexOfFF != -1) { if (packetBytes.Length > indexOfFF + 2 && packetBytes[indexOfFF + 1] == 0x0B) // FF 0B XY - Firmware X.Y00 { byte b1 = packetBytes[indexOfFF + 2]; firmware += (b1 >> 4) + (0.1 * (b1 & 0x0F)); DebugWriteLine("Firmware: {0}", firmware); } if (packetBytes.Length > indexOfFF + 2 && packetBytes[indexOfFF + 1] == 0x1B) // FF 1B XY - Firmware 0.0XY { byte b1 = packetBytes[indexOfFF + 2]; firmware += (0.01 * (b1 >> 4)) + (0.001 * (b1 & 0x0F)); DebugWriteLine("Firmware: {0}", firmware); } if (packetBytes.Length > indexOfFF + 1) { indexOfFF = Array.IndexOf(packetBytes, (byte)0xFF, indexOfFF + 1); } else { break; } } } switch (_readThreadMode) { case ReadThreadMode.Receiving: { IrDecoder.DecodeIR(timingData, _remoteCallback, _keyboardCallback, _mouseCallback); break; } case ReadThreadMode.Learning: { if (timingData == null) { if (_learningCode.TimingData.Length > 0) { _learningCode = null; _readThreadMode = ReadThreadMode.LearningFailed; } break; } if (_learningCode == null) { throw new InvalidOperationException("Learning not initialised correctly, _learningCode object is null"); } _learningCode.AddTimingData(timingData); // Example: 9F 01 02 9F 15 00 BE 80 int indexOf9F = Array.IndexOf(packetBytes, (byte)0x9F); while (indexOf9F != -1) { if (packetBytes.Length > indexOf9F + 3 && packetBytes[indexOf9F + 1] == 0x15) // 9F 15 XX XX { byte b1 = packetBytes[indexOf9F + 2]; byte b2 = packetBytes[indexOf9F + 3]; int onTime, onCount; GetIrCodeLengths(_learningCode, out onTime, out onCount); double carrierCount = (b1 * 256) + b2; if (carrierCount / onCount < 2.0) { _learningCode.Carrier = IrCode.CarrierFrequencyDCMode; } else { double carrier = 1000000 * carrierCount / onTime; // TODO: Double-Check this calculation. if (carrier > 32000) { _learningCode.Carrier = (int)(carrier + 0.05 * carrier - 0.666667); // was: _learningCode.Carrier = (int) (carrier + 0.05*carrier - 32000/48000); } else { _learningCode.Carrier = (int)carrier; } } _readThreadMode = ReadThreadMode.LearningDone; break; } if (packetBytes.Length > indexOf9F + 1) { indexOf9F = Array.IndexOf(packetBytes, (byte)0x9F, indexOf9F + 1); } else { _readThreadMode = ReadThreadMode.LearningFailed; break; } } break; } } } } catch (ThreadInterruptedException ex) { DebugWriteLine(ex.Message); if (_readHandle != null) { CancelIo(_readHandle); } } catch (Exception ex) { DebugWriteLine(ex.ToString()); if (_readHandle != null) { CancelIo(_readHandle); } } finally { if (deviceBufferPtr != IntPtr.Zero) { Marshal.FreeHGlobal(deviceBufferPtr); } safeWaitHandle.DangerousRelease(); waitHandle.Close(); } DebugWriteLine("Read Thread Ended"); }
/// <summary> /// Synchronously write a packet of bytes to the device. /// </summary> /// <param name="data">Packet to write to device.</param> private void WriteSync(byte[] data) { DebugWrite("WriteSync({0}): ", data.Length); DebugDump(data); if (!_deviceAvailable) throw new InvalidOperationException("Device not available"); WaitHandle waitHandle = new ManualResetEvent(false); SafeHandle safeWaitHandle = waitHandle.SafeWaitHandle; WaitHandle[] waitHandles = new WaitHandle[] {waitHandle}; try { int lastError; bool success = false; safeWaitHandle.DangerousAddRef(ref success); if (!success) throw new InvalidOperationException("Failed to initialize safe wait handle"); DeviceIoOverlapped overlapped = new DeviceIoOverlapped(); overlapped.ClearAndSetEvent(safeWaitHandle.DangerousGetHandle()); int bytesWritten; bool writeDevice = WriteFile(_writeHandle, data, data.Length, out bytesWritten, overlapped.Overlapped); lastError = Marshal.GetLastWin32Error(); if (writeDevice) return; if (lastError != ErrorSuccess && lastError != ErrorIoPending) throw new Win32Exception(lastError); int handle = WaitHandle.WaitAny(waitHandles, WriteSyncTimeout, false); if (handle == ErrorWaitTimeout) throw new TimeoutException("Timeout trying to write data to device"); if (handle != 0) throw new InvalidOperationException(String.Format("Invalid wait handle return: {0}", handle)); bool getOverlapped = GetOverlappedResult(_writeHandle, overlapped.Overlapped, out bytesWritten, true); lastError = Marshal.GetLastWin32Error(); if (!getOverlapped && lastError != ErrorSuccess) throw new Win32Exception(lastError); Thread.Sleep(PacketTimeout); } catch { if (_writeHandle != null) CancelIo(_writeHandle); throw; } finally { safeWaitHandle.DangerousRelease(); waitHandle.Close(); } }
/// <summary> /// Synchronously write a packet of bytes to the device. /// </summary> /// <param name="data">Packet to write to device.</param> private void WriteSync(byte[] data) { DebugWrite("WriteSync({0}): ", data.Length); DebugDump(data); if (!_deviceAvailable) { throw new InvalidOperationException("Device not available"); } WaitHandle waitHandle = new ManualResetEvent(false); SafeHandle safeWaitHandle = waitHandle.SafeWaitHandle; WaitHandle[] waitHandles = new WaitHandle[] { waitHandle }; try { int lastError; bool success = false; safeWaitHandle.DangerousAddRef(ref success); if (!success) { throw new InvalidOperationException("Failed to initialize safe wait handle"); } DeviceIoOverlapped overlapped = new DeviceIoOverlapped(); overlapped.ClearAndSetEvent(safeWaitHandle.DangerousGetHandle()); int bytesWritten; bool writeDevice = WriteFile(_writeHandle, data, data.Length, out bytesWritten, overlapped.Overlapped); lastError = Marshal.GetLastWin32Error(); if (writeDevice) { return; } if (lastError != ErrorSuccess && lastError != ErrorIoPending) { throw new Win32Exception(lastError); } int handle = WaitHandle.WaitAny(waitHandles, WriteSyncTimeout, false); if (handle == ErrorWaitTimeout) { throw new TimeoutException("Timeout trying to write data to device"); } if (handle != 0) { throw new InvalidOperationException(String.Format("Invalid wait handle return: {0}", handle)); } bool getOverlapped = GetOverlappedResult(_writeHandle, overlapped.Overlapped, out bytesWritten, true); lastError = Marshal.GetLastWin32Error(); if (!getOverlapped && lastError != ErrorSuccess) { throw new Win32Exception(lastError); } Thread.Sleep(PacketTimeout); } catch { if (_writeHandle != null) { CancelIo(_writeHandle); } throw; } finally { safeWaitHandle.DangerousRelease(); waitHandle.Close(); } }
/// <summary> /// Device read thread method. /// </summary> private void ReadThread() { byte[] packetBytes; WaitHandle waitHandle = new ManualResetEvent(false); SafeHandle safeWaitHandle = waitHandle.SafeWaitHandle; WaitHandle[] waitHandles = new WaitHandle[] {waitHandle, _stopReadThread}; IntPtr deviceBufferPtr = IntPtr.Zero; bool success = false; safeWaitHandle.DangerousAddRef(ref success); if (!success) throw new InvalidOperationException("Failed to initialize safe wait handle"); try { IntPtr dangerousWaitHandle = safeWaitHandle.DangerousGetHandle(); DeviceIoOverlapped overlapped = new DeviceIoOverlapped(); overlapped.ClearAndSetEvent(dangerousWaitHandle); deviceBufferPtr = Marshal.AllocHGlobal(DeviceBufferSize); while (_readThreadMode != ReadThreadMode.Stop) { int lastError; int bytesRead; bool readDevice = ReadFile(_readHandle, deviceBufferPtr, DeviceBufferSize, out bytesRead, overlapped.Overlapped); lastError = Marshal.GetLastWin32Error(); if (!readDevice) { if (lastError != ErrorSuccess && lastError != ErrorIoPending) throw new Win32Exception(lastError); while (true) { int handle = WaitHandle.WaitAny(waitHandles, 2 * PacketTimeout, false); if (handle == ErrorWaitTimeout) continue; if (handle == 0) break; if (handle == 1) throw new ThreadInterruptedException("Read thread stopping by request"); throw new InvalidOperationException(String.Format("Invalid wait handle return: {0}", handle)); } bool getOverlapped = GetOverlappedResult(_readHandle, overlapped.Overlapped, out bytesRead, true); lastError = Marshal.GetLastWin32Error(); if (!getOverlapped && lastError != ErrorSuccess) throw new Win32Exception(lastError); } if (bytesRead == 0) continue; packetBytes = new byte[bytesRead]; Marshal.Copy(deviceBufferPtr, packetBytes, 0, bytesRead); DebugWrite("Received bytes ({0}): ", bytesRead); DebugDump(packetBytes); int[] timingData = null; if (_decodeCarry != 0 || packetBytes[0] >= 0x81 && packetBytes[0] <= 0x9E) { timingData = GetTimingDataFromPacket(packetBytes); } else { double firmware = 0.0; int indexOfFF = Array.IndexOf(packetBytes, (byte) 0xFF); while (indexOfFF != -1) { if (packetBytes.Length > indexOfFF + 2 && packetBytes[indexOfFF + 1] == 0x0B) // FF 0B XY - Firmware X.Y00 { byte b1 = packetBytes[indexOfFF + 2]; firmware += (b1 >> 4) + (0.1 * (b1 & 0x0F)); DebugWriteLine("Firmware: {0}", firmware); } if (packetBytes.Length > indexOfFF + 2 && packetBytes[indexOfFF + 1] == 0x1B) // FF 1B XY - Firmware 0.0XY { byte b1 = packetBytes[indexOfFF + 2]; firmware += (0.01 * (b1 >> 4)) + (0.001 * (b1 & 0x0F)); DebugWriteLine("Firmware: {0}", firmware); } if (packetBytes.Length > indexOfFF + 1) indexOfFF = Array.IndexOf(packetBytes, (byte) 0xFF, indexOfFF + 1); else break; } } switch (_readThreadMode) { case ReadThreadMode.Receiving: { IrDecoder.DecodeIR(timingData, _remoteCallback, _keyboardCallback, _mouseCallback); break; } case ReadThreadMode.Learning: { if (timingData == null) { if (_learningCode.TimingData.Length > 0) { _learningCode = null; _readThreadMode = ReadThreadMode.LearningFailed; } break; } if (_learningCode == null) throw new InvalidOperationException("Learning not initialised correctly, _learningCode object is null"); _learningCode.AddTimingData(timingData); // Example: 9F 01 02 9F 15 00 BE 80 int indexOf9F = Array.IndexOf(packetBytes, (byte) 0x9F); while (indexOf9F != -1) { if (packetBytes.Length > indexOf9F + 3 && packetBytes[indexOf9F + 1] == 0x15) // 9F 15 XX XX { byte b1 = packetBytes[indexOf9F + 2]; byte b2 = packetBytes[indexOf9F + 3]; int onTime, onCount; GetIrCodeLengths(_learningCode, out onTime, out onCount); double carrierCount = (b1 * 256) + b2; if (carrierCount / onCount < 2.0) { _learningCode.Carrier = IrCode.CarrierFrequencyDCMode; } else { double carrier = 1000000 * carrierCount / onTime; // TODO: Double-Check this calculation. if (carrier > 32000) { _learningCode.Carrier = (int) (carrier + 0.05 * carrier - 0.666667); // was: _learningCode.Carrier = (int) (carrier + 0.05*carrier - 32000/48000); } else { _learningCode.Carrier = (int) carrier; } } _readThreadMode = ReadThreadMode.LearningDone; break; } if (packetBytes.Length > indexOf9F + 1) { indexOf9F = Array.IndexOf(packetBytes, (byte) 0x9F, indexOf9F + 1); } else { _readThreadMode = ReadThreadMode.LearningFailed; break; } } break; } } } } catch (ThreadInterruptedException ex) { DebugWriteLine(ex.Message); if (_readHandle != null) CancelIo(_readHandle); } catch (Exception ex) { DebugWriteLine(ex.ToString()); if (_readHandle != null) CancelIo(_readHandle); } finally { if (deviceBufferPtr != IntPtr.Zero) Marshal.FreeHGlobal(deviceBufferPtr); safeWaitHandle.DangerousRelease(); waitHandle.Close(); } DebugWriteLine("Read Thread Ended"); }