Ejemplo n.º 1
0
        private unsafe void PipeIOCallback(uint errorCode, uint numBytes, NativeOverlapped *pOverlapped)
        {
            try
            {
                Exception error = null;
                if (errorCode != 0)
                {
                    error = APIException.Win32("Asynchronous operation on WinUSB device failed.", (int)errorCode);
                }
                Overlapped     overlapped = Overlapped.Unpack(pOverlapped);
                USBAsyncResult result     = (USBAsyncResult)overlapped.AsyncResult;
                Overlapped.Free(pOverlapped);
                pOverlapped = null;

                result.OnCompletion(false, error, (int)numBytes, true);
            }
            finally
            {
                if (pOverlapped != null)
                {
                    Overlapped.Unpack(pOverlapped);
                    Overlapped.Free(pOverlapped);
                }
            }
        }
Ejemplo n.º 2
0
        public void GetInterfaceInfo(int interfaceIndex, out USB_INTERFACE_DESCRIPTOR descriptor, out WINUSB_PIPE_INFORMATION[] pipes)
        {
            var  pipeList = new List <WINUSB_PIPE_INFORMATION>();
            bool success  = WinUsb_QueryInterfaceSettings(InterfaceHandle(interfaceIndex), 0, out descriptor);

            if (!success)
            {
                throw APIException.Win32("Failed to get WinUSB device interface descriptor.");
            }

            IntPtr interfaceHandle = InterfaceHandle(interfaceIndex);

            for (byte pipeIdx = 0; pipeIdx < descriptor.bNumEndpoints; pipeIdx++)
            {
                WINUSB_PIPE_INFORMATION pipeInfo;
                success = WinUsb_QueryPipe(interfaceHandle, 0, pipeIdx, out pipeInfo);

                pipeList.Add(pipeInfo);
                if (!success)
                {
                    throw APIException.Win32("Failed to get WinUSB device pipe information.");
                }
            }
            pipes = pipeList.ToArray();
        }
Ejemplo n.º 3
0
 public void OpenDevice(string devicePathName)
 {
     try
     {
         _deviceHandle = FileIO.CreateFile(devicePathName,
                                           (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,
                                           0);
         if (_deviceHandle.IsInvalid)
         {
             throw APIException.Win32("Failed to open WinUSB device handle.");
         }
         InitializeDevice();
     }
     catch (Exception)
     {
         if (_deviceHandle != null)
         {
             _deviceHandle.Dispose();
             _deviceHandle = null;
         }
         FreeWinUSB();
         throw;
     }
 }
Ejemplo n.º 4
0
 public static void StopDeviceDeviceNotifications(IntPtr deviceNotificationHandle)
 {
     if (!DeviceManagement.UnregisterDeviceNotification(deviceNotificationHandle))
     {
         throw APIException.Win32("Failed to unregister device notification");
     }
 }
Ejemplo n.º 5
0
        public void SetPipePolicy(int ifaceIndex, byte pipeID, POLICY_TYPE policyType, uint value)
        {
            bool success = WinUsb_SetPipePolicy(InterfaceHandle(ifaceIndex), pipeID, (uint)policyType, 4, ref value);

            if (!success)
            {
                throw APIException.Win32("Failed to set WinUSB pipe policy.");
            }
        }
Ejemplo n.º 6
0
        public void FlushPipe(int ifaceIndex, byte pipeID)
        {
            bool success = WinUsb_FlushPipe(InterfaceHandle(ifaceIndex), pipeID);

            if (!success)
            {
                throw APIException.Win32("Failed to flush pipe on WinUSB device.");
            }
        }
Ejemplo n.º 7
0
        public void SetPipePolicy(int ifaceIndex, byte pipeID, POLICY_TYPE policyType, bool value)
        {
            byte byteVal = (byte)(value ? 1 : 0);
            bool success = WinUsb_SetPipePolicy(InterfaceHandle(ifaceIndex), pipeID, (uint)policyType, 1, ref byteVal);

            if (!success)
            {
                throw APIException.Win32("Failed to set WinUSB pipe policy.");
            }
        }
Ejemplo n.º 8
0
        public uint GetPipePolicyUInt(int ifaceIndex, byte pipeID, POLICY_TYPE policyType)
        {
            uint result;
            uint length  = 4;
            bool success = WinUsb_GetPipePolicy(InterfaceHandle(ifaceIndex), pipeID, (uint)policyType, ref length, out result);

            if (!success || length != 4)
            {
                throw APIException.Win32("Failed to get WinUSB pipe policy.");
            }
            return(result);
        }
Ejemplo n.º 9
0
        private void InitializeDevice()
        {
            bool success;

            success = WinUsb_Initialize(_deviceHandle, ref _winUsbHandle);

            if (!success)
            {
                throw APIException.Win32("Failed to initialize WinUSB handle. Device might not be connected.");
            }

            List <IntPtr> interfaces       = new List <IntPtr>();
            byte          numAddInterfaces = 0;
            byte          idx = 0;

            try
            {
                while (true)
                {
                    IntPtr ifaceHandle = IntPtr.Zero;
                    success = WinUsb_GetAssociatedInterface(_winUsbHandle, idx, out ifaceHandle);
                    if (!success)
                    {
                        if (Marshal.GetLastWin32Error() == ERROR_NO_MORE_ITEMS)
                        {
                            break;
                        }

                        throw APIException.Win32("Failed to enumerate interfaces for WinUSB device.");
                    }
                    interfaces.Add(ifaceHandle);
                    idx++;
                    numAddInterfaces++;
                }
            }
            finally
            {
                // Save interface handles (will be cleaned by Dispose)
                // also in case of exception (which is why it is in finally block),
                // because some handles might have already been opened and need
                // to be disposed.
                _addInterfaces = interfaces.ToArray();
            }

            // Bind handle (needed for overlapped I/O thread pool)
            ThreadPool.BindHandle(_deviceHandle);
            // TODO: bind interface handles as well? doesn't seem to be necessary
        }
Ejemplo n.º 10
0
        public void WritePipe(int ifaceIndex, byte pipeID, byte[] buffer, int offset, int length)
        {
            uint bytesWritten;
            bool success;

            unsafe
            {
                fixed(byte *pBuffer = buffer)
                {
                    success = WinUsb_WritePipe(InterfaceHandle(ifaceIndex), pipeID, pBuffer + offset, (uint)length,
                                               out bytesWritten, IntPtr.Zero);
                }
            }
            if (!success || (bytesWritten != length))
            {
                throw APIException.Win32("Failed to write pipe on WinUSB device.");
            }
        }
Ejemplo n.º 11
0
        public void ControlTransfer(byte requestType, byte request, ushort value, ushort index, ushort length, byte[] data)
        {
            uint bytesReturned = 0;
            WINUSB_SETUP_PACKET setupPacket;

            setupPacket.RequestType = requestType;
            setupPacket.Request     = request;
            setupPacket.Value       = value;
            setupPacket.Index       = index;
            setupPacket.Length      = length;

            bool success = WinUsb_ControlTransfer(_winUsbHandle, setupPacket, data, length, ref bytesReturned, IntPtr.Zero);

            if (!success) // todo check bytes returned?
            {
                throw APIException.Win32("Control transfer on WinUSB device failed.");
            }
        }
Ejemplo n.º 12
0
        public USB_DEVICE_DESCRIPTOR GetDeviceDescriptor()
        {
            USB_DEVICE_DESCRIPTOR deviceDesc;
            uint transfered;
            uint size    = (uint)Marshal.SizeOf(typeof(USB_DEVICE_DESCRIPTOR));
            bool success = WinUsb_GetDescriptor(_winUsbHandle, USB_DEVICE_DESCRIPTOR_TYPE,
                                                0, 0, out deviceDesc, size, out transfered);

            if (!success)
            {
                throw APIException.Win32("Failed to get USB device descriptor.");
            }

            if (transfered != size)
            {
                throw APIException.Win32("Incomplete USB device descriptor.");
            }

            return(deviceDesc);
        }
Ejemplo n.º 13
0
        public string GetStringDescriptor(byte index)
        {
            byte[] buffer = new byte[256];
            uint   transfered;
            bool   success = WinUsb_GetDescriptor(_winUsbHandle, USB_STRING_DESCRIPTOR_TYPE,
                                                  index, 0, buffer, (uint)buffer.Length, out transfered);

            if (!success)
            {
                throw APIException.Win32("Failed to get USB string descriptor (" + index + ").");
            }

            int length = buffer[0] - 2;

            if (length <= 0)
            {
                return(null);
            }
            char[] chars = System.Text.Encoding.Unicode.GetChars(buffer, 2, length);
            return(new string(chars));
        }
Ejemplo n.º 14
0
        private unsafe void HandleOverlappedAPI(bool success, string errorMessage, NativeOverlapped *pOverlapped, USBAsyncResult result, int bytesTransfered)
        {
            if (!success)
            {
                if (Marshal.GetLastWin32Error() != FileIO.ERROR_IO_PENDING)
                {
                    Overlapped.Unpack(pOverlapped);
                    Overlapped.Free(pOverlapped);
                    throw APIException.Win32(errorMessage);
                }
            }
            else
            {
                // Immediate success!
                Overlapped.Unpack(pOverlapped);
                Overlapped.Free(pOverlapped);

                result.OnCompletion(true, null, bytesTransfered, false);
                // is the callback still called in this case?? todo
            }
        }
Ejemplo n.º 15
0
        private static byte[] GetProperty(IntPtr deviceInfoSet, SP_DEVINFO_DATA deviceInfoData, SPDRP property, out int regType)
        {
            uint requiredSize;

            if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, ref deviceInfoData, property, IntPtr.Zero, IntPtr.Zero, 0, out requiredSize))
            {
                if (Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER)
                {
                    throw APIException.Win32("Failed to get buffer size for device registry property.");
                }
            }

            byte[] buffer = new byte[requiredSize];

            if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, ref deviceInfoData, property, out regType, buffer, (uint)buffer.Length, out requiredSize))
            {
                throw APIException.Win32("Failed to get device registry property.");
            }

            return(buffer);
        }
Ejemplo n.º 16
0
        public static void RegisterForDeviceNotifications(IntPtr controlHandle, Guid classGuid, ref IntPtr deviceNotificationHandle)
        {
            DEV_BROADCAST_DEVICEINTERFACE devBroadcastDeviceInterface = new DEV_BROADCAST_DEVICEINTERFACE();
            IntPtr devBroadcastDeviceInterfaceBuffer = IntPtr.Zero;

            try
            {
                int size = Marshal.SizeOf(devBroadcastDeviceInterface);
                devBroadcastDeviceInterface.dbcc_size = size;

                devBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
                devBroadcastDeviceInterface.dbcc_reserved   = 0;
                devBroadcastDeviceInterface.dbcc_classguid  = classGuid;
                devBroadcastDeviceInterfaceBuffer           = Marshal.AllocHGlobal(size);

                // Copy the DEV_BROADCAST_DEVICEINTERFACE structure to the buffer.
                // Set fDeleteOld True to prevent memory leaks.
                Marshal.StructureToPtr(devBroadcastDeviceInterface, devBroadcastDeviceInterfaceBuffer, true);

                deviceNotificationHandle = RegisterDeviceNotification(controlHandle, devBroadcastDeviceInterfaceBuffer, DEVICE_NOTIFY_WINDOW_HANDLE);
                if (deviceNotificationHandle == IntPtr.Zero)
                {
                    throw APIException.Win32("Failed to register device notification");
                }

                // Marshal data from the unmanaged block devBroadcastDeviceInterfaceBuffer to
                // the managed object devBroadcastDeviceInterface
                Marshal.PtrToStructure(devBroadcastDeviceInterfaceBuffer, devBroadcastDeviceInterface);
            }
            finally
            {
                // Free the memory allocated previously by AllocHGlobal.
                if (devBroadcastDeviceInterfaceBuffer != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(devBroadcastDeviceInterfaceBuffer);
                }
            }
        }
Ejemplo n.º 17
0
 public static APIException Win32(string message)
 {
     return(APIException.Win32(message, Marshal.GetLastWin32Error()));
 }
Ejemplo n.º 18
0
        public static DeviceDetails[] FindDevicesFromGuid(Guid guid)
        {
            IntPtr deviceInfoSet            = IntPtr.Zero;
            List <DeviceDetails> deviceList = new List <DeviceDetails>();

            try
            {
                deviceInfoSet = SetupDiGetClassDevs(ref guid, IntPtr.Zero, IntPtr.Zero,
                                                    DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
                if (deviceInfoSet == FileIO.INVALID_HANDLE_VALUE)
                {
                    throw APIException.Win32("Failed to enumerate devices.");
                }
                int memberIndex = 0;
                while (true)
                {
                    // Begin with 0 and increment through the device information set until
                    // no more devices are available.
                    SP_DEVICE_INTERFACE_DATA deviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();

                    // The cbSize element of the deviceInterfaceData structure must be set to
                    // the structure's size in bytes.
                    // The size is 28 bytes for 32-bit code and 32 bytes for 64-bit code.
                    deviceInterfaceData.cbSize = Marshal.SizeOf(deviceInterfaceData);

                    bool success;

                    success = SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref guid, memberIndex, ref deviceInterfaceData);

                    // Find out if a device information set was retrieved.
                    if (!success)
                    {
                        int lastError = Marshal.GetLastWin32Error();
                        if (lastError == ERROR_NO_MORE_ITEMS)
                        {
                            break;
                        }

                        throw APIException.Win32("Failed to get device interface.");
                    }
                    // A device is present.

                    int bufferSize = 0;

                    success = SetupDiGetDeviceInterfaceDetail
                                  (deviceInfoSet,
                                  ref deviceInterfaceData,
                                  IntPtr.Zero,
                                  0,
                                  ref bufferSize,
                                  IntPtr.Zero);

                    if (!success)
                    {
                        if (Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER)
                        {
                            throw APIException.Win32("Failed to get interface details buffer size.");
                        }
                    }

                    IntPtr detailDataBuffer = IntPtr.Zero;
                    try
                    {
                        // Allocate memory for the SP_DEVICE_INTERFACE_DETAIL_DATA structure using the returned buffer size.
                        detailDataBuffer = Marshal.AllocHGlobal(bufferSize);

                        // Store cbSize in the first bytes of the array. The number of bytes varies with 32- and 64-bit systems.

                        Marshal.WriteInt32(detailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);

                        // Call SetupDiGetDeviceInterfaceDetail again.
                        // This time, pass a pointer to DetailDataBuffer
                        // and the returned required buffer size.

                        // build a DevInfo Data structure
                        SP_DEVINFO_DATA da = new SP_DEVINFO_DATA();
                        da.cbSize = Marshal.SizeOf(da);


                        success = SetupDiGetDeviceInterfaceDetail
                                      (deviceInfoSet,
                                      ref deviceInterfaceData,
                                      detailDataBuffer,
                                      bufferSize,
                                      ref bufferSize,
                                      ref da);

                        if (!success)
                        {
                            throw APIException.Win32("Failed to get device interface details.");
                        }


                        // Skip over cbsize (4 bytes) to get the address of the devicePathName.

                        IntPtr pDevicePathName = new IntPtr(detailDataBuffer.ToInt64() + 4);
                        string pathName        = Marshal.PtrToStringUni(pDevicePathName);

                        // Get the String containing the devicePathName.

                        DeviceDetails details = GetDeviceDetails(pathName, deviceInfoSet, da);


                        deviceList.Add(details);
                    }
                    finally
                    {
                        if (detailDataBuffer != IntPtr.Zero)
                        {
                            Marshal.FreeHGlobal(detailDataBuffer);
                            detailDataBuffer = IntPtr.Zero;
                        }
                    }
                    memberIndex++;
                }
            }
            finally
            {
                if (deviceInfoSet != IntPtr.Zero && deviceInfoSet != FileIO.INVALID_HANDLE_VALUE)
                {
                    SetupDiDestroyDeviceInfoList(deviceInfoSet);
                }
            }
            return(deviceList.ToArray());
        }