/// <summary> /// Writes one byte to the USB device. /// </summary> /// <param name="value">The byte to write.</param> /// <exception cref="NotSupportedException">The <see cref="PipeStream"/> /// does not support writing.</exception> /// <exception cref="Win32Exception">An error was reported by /// the operating system.</exception> /// <exception cref="IOException">The <see cref="UsbDevice"/> is not open, /// or the transfer did not complete.</exception> /// <remarks> /// Data sent to the USB device is not buffered, so this method will /// always send a 1-byte packet. /// </remarks> /// <seealso cref="ReadByte">ReadByte</seealso> /// <seealso cref="Write">Write</seealso> public override void WriteByte(byte value) { uint cbWritten; bool retval; if (!m_fCanWrite) { throw new NotSupportedException(); } retval = WinUsbApi.WinUsb_WritePipeByte( m_Device.UsbHandle, (byte)(m_idPipe | WinUsbApi.WriteFlag), ref value, 1, out cbWritten, IntPtr.Zero); if (!retval) { throw new Win32Exception(); } if (cbWritten != 1) { throw new IOException(); } }
/// <summary> /// Attempts to read one byte from the USB device. /// </summary> /// <returns> /// <para>The unsigned byte cast to an Int32, or -1 if a short packet is received and the /// <see cref="ReadUseShortPacket"/> property is set to <b>true</b>.</para> /// </returns> /// <exception cref="IOException">The <see cref="UsbDevice"/> is not open.</exception> /// <exception cref="NotSupportedException">The <see cref="PipeStream"/> /// does not support reading.</exception> /// <exception cref="Win32Exception">An error was reported by /// the operating system. If <see cref="Win32Exception.NativeErrorCode"/> is 0x00000079, /// the operation timed out.</exception> /// <remarks> /// If the USB device returns more data than requested, the excess /// data will be stored in an internal buffer. Future calls to /// <see cref="Read">Read</see> or <see cref="ReadByte">ReadByte</see> /// will read from the internal buffer until it is exhausted. /// </remarks> /// <seealso cref="Read"/> /// <seealso cref="WriteByte"/> public override int ReadByte() { byte bData; uint cbRead; bool retval; if (!m_fCanRead) { throw new NotSupportedException(); } retval = WinUsbApi.WinUsb_ReadPipeByte( m_Device.UsbHandle, (byte)(m_idPipe | WinUsbApi.ReadFlag), out bData, 1, out cbRead, IntPtr.Zero); if (!retval) { throw new Win32Exception(); } if (cbRead == 0) { return(-1); } return(bData); }
//***************************************************************** /// <summary> /// Initiates a USB control transfer with optional data sent to the USB device. /// </summary> /// <param name="bmRequestType">The USB <i>bmRequestType</i>field.</param> /// <param name="bRequest">The USB <i>bRequest</i>field.</param> /// <param name="wValue">The USB <i>wValue</i>field.</param> /// <param name="wIndex">The USB <i>wIndex</i>field.</param> /// <param name="buffer">An array of bytes with the data to write to the /// USB device. May be <b>null</b>.</param> /// <exception cref="IOException">The <see cref="UsbDevice"/> is not open, /// or the transfer did not complete.</exception> /// <exception cref="Win32Exception">An error was reported by /// the operating system.</exception> /// <remarks> /// <para> /// The first four arguments of this method correspond precisely with the /// like-named fields of a USB Setup packet. See the USB specification /// for the meaning and use of these parameters.</para> /// <para> /// The <i>wLength</i> field of the USB Setup packet is set to the /// length of <paramref name="buffer"/>, or zero if <paramref name="buffer"/> /// is <b>null</b>. /// </para> /// </remarks> public void ControlWrite(byte bmRequestType, byte bRequest, ushort wValue, ushort wIndex, byte[] buffer) { bool retval; uint cbWritten; WinUsbApi.WINUSB_SETUP_PACKET packet; packet.RequestType = (byte)(bmRequestType & WinUsbApi.PipeMask); // ensure OUT transfer packet.Request = bRequest; packet.Value = wValue; packet.Index = wIndex; if (buffer == null) { buffer = new byte[0]; } packet.Length = (ushort)buffer.Length; retval = WinUsbApi.WinUsb_ControlTransfer( UsbHandle, packet, buffer, (uint)buffer.Length, out cbWritten, IntPtr.Zero); if (!retval) { throw new Win32Exception(); } if (cbWritten != buffer.Length) { throw new IOException(); } }
/// <summary> /// Clears the read buffer for the <see cref="PipeStream"/>. /// </summary> /// <exception cref="IOException">The <see cref="UsbDevice"/> is not open.</exception> /// <exception cref="NotSupportedException">The <see cref="PipeStream"/> /// does not support reading. /// </exception> /// <remarks> /// Data received from the USB device that has not yet been read with /// the <see cref="Read">Read</see> or <see cref="ReadByte">ReadByte</see> /// methods is stored in an internal buffer. The <b>ClearReadBuffer</b> method /// clears the buffer, discarding any unread data. /// </remarks> public void ClearReadBuffer() { if (!m_fCanRead) { throw new NotSupportedException(); } WinUsbApi.WinUsb_FlushPipe(m_Device.UsbHandle, (byte)(m_idPipe | WinUsbApi.ReadFlag)); }
internal void SetPipePolicyBool(int idPipe, WinUsbApi.POLICY_TYPE type, bool value) { WinUsbApi.WinUsb_SetPipePolicyBool( UsbHandle, (byte)idPipe, (uint)type, sizeof(byte), ref value); }
/// <summary> /// Writes a specified number of bytes to the USB device. /// </summary> /// <param name="buffer">An array of bytes containing the data to /// write to the USB device.</param> /// <param name="offset">The zero-based offset in the <paramref name="buffer"/> /// at which to begin sending data to the USB device.</param> /// <param name="count">The number of bytes to write to the /// USB device.</param> /// <exception cref="NotSupportedException">The <see cref="PipeStream"/> /// does not support writing.</exception> /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is <b>null</b>. /// </exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="offset"/> or /// <paramref name="count"/> is negative.</exception> /// <exception cref="ArgumentException">The sum of <paramref name="offset"/> and /// <paramref name="count"/> is larger than the buffer length.</exception> /// <exception cref="Win32Exception">An error was reported by /// the operating system.</exception> /// <exception cref="IOException">The <see cref="UsbDevice"/> is not open, /// or the transfer did not complete.</exception> /// <remarks> /// If the number of bytes written to the USB device is /// a multiple of the maximum packet size, and the <see cref="WriteUseShortPacket"/> /// property is set to <b>true</b>, then a zero-length packet will be /// sent after the data. /// </remarks> /// <seealso cref="Read">Read</seealso> /// <seealso cref="WriteByte">WriteByte</seealso> public override void Write(byte[] buffer, int offset, int count) { GCHandle gch; uint cbWritten; bool retval; IntPtr pBuf; if (!m_fCanWrite) { throw new NotSupportedException(); } if (buffer == null) { throw new ArgumentNullException("buffer"); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset"); } if (count < 0) { throw new ArgumentOutOfRangeException("count"); } if (offset + count > buffer.Length) { throw new ArgumentException(); } gch = GCHandle.Alloc(buffer, GCHandleType.Pinned); pBuf = gch.AddrOfPinnedObject(); pBuf = (IntPtr)(pBuf.ToInt64() + offset); retval = WinUsbApi.WinUsb_WritePipe( m_Device.UsbHandle, (byte)(m_idPipe | WinUsbApi.WriteFlag), pBuf, (uint)count, out cbWritten, IntPtr.Zero); gch.Free(); if (!retval) { throw new Win32Exception(); } if (cbWritten != count) { throw new IOException(); } }
internal bool GetPipePolicyBool(int idPipe, WinUsbApi.POLICY_TYPE type) { byte value; uint len; len = sizeof(byte); WinUsbApi.WinUsb_GetPipePolicyByte( UsbHandle, (byte)idPipe, (uint)type, ref len, out value); return(value != 0); }
//***************************************************************** /// <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> /// Initiates a USB control transfer that reads data from the USB device. /// </summary> /// <param name="bmRequestType">The USB <i>bmRequestType</i>field.</param> /// <param name="bRequest">The USB <i>bRequest</i>field.</param> /// <param name="wValue">The USB <i>wValue</i>field.</param> /// <param name="wIndex">The USB <i>wIndex</i>field.</param> /// <param name="wLength">The USB <i>wLength</i>field.</param> /// <returns> /// <para>A byte array containing the bytes read from the USB device.</para> /// </returns> /// <exception cref="IOException">The <see cref="UsbDevice"/> is not open.</exception> /// <exception cref="Win32Exception">An error was reported by /// the operating system.</exception> /// <remarks> /// <para> /// The arguments of this method correspond precisely with the /// like-named fields of a USB Setup packet. See the USB specification /// for the meaning and use of these parameters.</para> /// <para> /// The <paramref name="wLength"/> parameter is the maximum number of /// bytes to read from the USB device, and the USB device may send less. /// The length of the returned byte array is the actual number of /// bytes received.</para> /// </remarks> public byte[] ControlRead(byte bmRequestType, byte bRequest, ushort wValue, ushort wIndex, ushort wLength) { byte[] arbBuf; byte[] arbData; uint cbRead; bool retval; WinUsbApi.WINUSB_SETUP_PACKET packet; packet.RequestType = (byte)(bmRequestType | WinUsbApi.ReadFlag); // ensure IN transfer packet.Request = bRequest; packet.Value = wValue; packet.Index = wIndex; packet.Length = wLength; arbBuf = new byte[wLength]; retval = WinUsbApi.WinUsb_ControlTransfer( UsbHandle, packet, arbBuf, (uint)arbBuf.Length, out cbRead, IntPtr.Zero); if (!retval) { throw new Win32Exception(); } if (cbRead == arbBuf.Length) { return(arbBuf); } arbData = new byte[cbRead]; Array.Copy(arbBuf, arbData, cbRead); return(arbData); }
/// <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; } }