//***************************************************************** /// <summary> /// Closes the USB device. /// </summary> /// <remarks> /// Calling this method will set the <see cref="PipeStreams"/> property /// to <b>null</b>, and the <see cref="IsOpen"/> property to <b>false</b>. /// </remarks> public void Close() { if (m_hWinUsb != INVALID_USB_HANDLE) { WinUsbApi.WinUsb_Free(m_hWinUsb); m_hWinUsb = INVALID_USB_HANDLE; } if (m_hDevice != null) { if (!m_hDevice.IsInvalid) { m_hDevice.Close(); } m_hDevice = null; } m_arPipeStreams = null; m_collPipeStreams = null; }
/// <summary> /// Open the USB device for I/O. /// </summary> /// <exception cref="IOException">The <see cref="IsAttached"/> /// property is <b>false</b>.</exception> /// <exception cref="Win32Exception">An error was reported by /// the operating system.</exception> /// <remarks> /// <para> /// If the open method succeeds, it will create the /// <see cref="PipeStreams"/> collection and populate it with /// <see cref="PipeStream"/> objects corresponding to the /// endpoints on the USB device. The initial value of /// the <see cref="PipeStream.ReadTimeout"/> property of each /// <see cref="PipeStream"/> will be set to /// <see cref="DefaultReadTimeout"/>.</para> /// <para> /// If the open fails, an exception will be thrown.</para> /// <para> /// USB devices are opened exclusively. That is, once a USB device /// has been opened and not yet closed, any additional attempt to /// open it (whether in the same or a different application) will fail /// with the <see cref="Win32Exception"/> <b>Access is denied</b>, /// <see cref="Win32Exception.NativeErrorCode"/> value 0x00000005.</para> /// </remarks> public void Open() { WinUsbApi.USB_INTERFACE_DESCRIPTOR descIface; WinUsbApi.WINUSB_PIPE_INFORMATION infoPipe; byte idPipe; PipeStream pipe; if (!IsAttached) { throw new IOException(ErrDeviceNotAttached); } try { m_hDevice = FileIO.CreateFile( m_strDeviceName, FileIO.GENERIC_WRITE | FileIO.GENERIC_READ, FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE, IntPtr.Zero, FileIO.OPEN_EXISTING, FileIO.FILE_ATTRIBUTE_NORMAL | FileIO.FILE_FLAG_OVERLAPPED, IntPtr.Zero); if (m_hDevice.IsInvalid) { throw new Win32Exception(); } if (!WinUsbApi.WinUsb_Initialize(m_hDevice, out m_hWinUsb)) { throw new Win32Exception(); } if (!WinUsbApi.WinUsb_QueryInterfaceSettings(m_hWinUsb, 0, out descIface)) { throw new Win32Exception(); } m_arPipeStreams = new PipeStream[16]; m_collPipeStreams = new PipeStreamCollection(m_arPipeStreams); // Enumerate the pipes for (byte i = 0; i < descIface.bNumEndpoints; i++) { if (!WinUsbApi.WinUsb_QueryPipe(m_hWinUsb, 0, i, out infoPipe)) { throw new Win32Exception(); } idPipe = (byte)(infoPipe.PipeId & WinUsbApi.PipeMask); if (idPipe > 15) { continue; // skip it } if (m_arPipeStreams[idPipe] == null) { m_arPipeStreams[idPipe] = new PipeStream(this, idPipe); } pipe = m_arPipeStreams[idPipe]; if ((infoPipe.PipeId & ~WinUsbApi.PipeMask) == WinUsbApi.ReadFlag) { pipe.m_fCanRead = true; pipe.m_cbReadMaxPacket = infoPipe.MaximumPacketSize; pipe.ReadTimeout = DefaultReadTimeout; } else { pipe.m_fCanWrite = true; pipe.m_cbWriteMaxPacket = infoPipe.MaximumPacketSize; } SetPipePolicyBool(infoPipe.PipeId, WinUsbApi.POLICY_TYPE.AUTO_CLEAR_STALL, true); } } catch { Close(); throw; } }