/// <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);
        }
Beispiel #3
0
        //*****************************************************************

        /// <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));
        }
Beispiel #5
0
 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();
            }
        }
Beispiel #7
0
        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);
        }
Beispiel #8
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;
        }
Beispiel #9
0
        //*****************************************************************

        /// <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);
        }
Beispiel #10
0
        /// <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;
            }
        }