Пример #1
0
 /// <summary>
 ///     Frees the handles so that the device can be used by other
 ///     programs, or by this program later.
 /// </summary>
 /// <param name="handles">
 ///     Handles returned by some other WinUsbHelper function.
 /// </param>
 internal static void disconnect(WinUsbDeviceHandles handles)
 {
     WinUsb_Free(handles.winusbHandle);
     handles.deviceHandle.Close();
     // Device Instance does not need to be freed, its existence does
     // not imply a lock.
 }
Пример #2
0
        /// <summary>
        ///   Connects to the specified device in the list.
        /// </summary>
        /// <param name="listHandle">
        ///   The handle of the list created with listCreate.
        /// </param>
        /// <param name="index">
        ///   The zero-based index of the device in the list to connect to.
        /// </param>
        /// <param name="deviceInterfaceGuid">GUID from the INF file.</param>
        /// <returns>Handles needed to communicate with the device.</returns>
        internal static unsafe WinUsbDeviceHandles listConnect(IntPtr listHandle, Byte index, Guid deviceInterfaceGuid)
        {
            WinUsbDeviceHandles handles = new WinUsbDeviceHandles();

            /* Get the device instance ****************************************/
            handles.deviceInstance = listGetDeviceInstance(listHandle, index);

            /* Get the DeviceInterfaceData struct *****************************/

            // DeviceInterfaceData is some info about the device in the list.
            SP_DEVICE_INTERFACE_DATA DeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();

            // Necessary according to http://msdn.microsoft.com/en-us/library/ms791242.aspx
            DeviceInterfaceData.cbSize = (UInt32)Marshal.SizeOf(DeviceInterfaceData);

            Boolean result = SetupDiEnumDeviceInterfaces(listHandle, IntPtr.Zero,
                                                         ref deviceInterfaceGuid, index, ref DeviceInterfaceData);

            if (!result)
            {
                throw new Win32Exception("Unable to get the device interface data.");
            }

            /* Get the DeviceInterfaceDetailData struct ***********************/

            // RequiredSize is the size in bytes of the
            // DeviceInterfaceDetailData struct we want to get for the device.
            UInt32 RequiredSize = 0;

            result = SetupDiGetDeviceInterfaceDetail(listHandle, ref DeviceInterfaceData,
                                                     IntPtr.Zero, 0, ref RequiredSize, IntPtr.Zero);
            if (!result && Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER)
            {
                throw new Win32Exception("Unable to get the size of the device interface detail.");
            }

            // Now that we know the size of the DeviceInterfaceDetailData struct,
            // we can allocate memory for it.
            IntPtr pDeviceInterfaceDetailData = Marshal.AllocHGlobal((Int32)RequiredSize);

            // Get the DeviceInterfaceDetailData.

            /* According to the MSDN, we must set cbSize (the first 4 bytes of
             * the array) to sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA).  On 32-bit
             * machines, this is 6, and on 64-bit machines, this is 8.  I'm not
             * sure why.
             */

            bool sixtyFourBit = (sizeof(IntPtr) == 8);

            Marshal.WriteInt32(pDeviceInterfaceDetailData, sixtyFourBit ? 8 : 6);

            result = SetupDiGetDeviceInterfaceDetail(listHandle, ref DeviceInterfaceData,
                                                     pDeviceInterfaceDetailData, RequiredSize, ref RequiredSize, IntPtr.Zero);
            if (!result)
            {
                Marshal.FreeHGlobal(pDeviceInterfaceDetailData);
                throw new Win32Exception("Unable to get the device interface detail.");
            }

            /* Get the device handle ******************************************/

            // Get the address of the PDeviceInterfaceDetaildata->DevicePath.
            IntPtr pDevicePath = new IntPtr(pDeviceInterfaceDetailData.ToInt64() + 4);

            // Get a string object with the device path.
            // This is what a typical DevicePath looks like:
            // \\?\usb#vid_04d8&pid_da01#5&226425fa&0&2#{fe187157-e4cb-4c53-a1d6-e6040ff6896f}
            String devicePath = Marshal.PtrToStringAuto(pDevicePath);

            // Use the DevicePath to open a file handle.
            handles.deviceHandle = CreateFile(devicePath,
                                              GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
                                              IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, IntPtr.Zero);

            Marshal.FreeHGlobal(pDeviceInterfaceDetailData);

            if (handles.deviceHandle.IsInvalid)
            {
                Int32 error = Marshal.GetLastWin32Error();
                if (error == 5) // ERROR_ACCESS_DENIED
                {
                    throw new Win32Exception("Access denied when trying to open device.  Try closing all other programs that are using the device.");
                }
                else
                {
                    throw new Win32Exception(error, "Unable to create a handle for the device (" + devicePath + ").");
                }
            }

            // Use DeviceHandle to make a Winusb Interface Handle.
            result = WinUsb_Initialize(handles.deviceHandle, ref handles.winusbHandle);
            if (!result)
            {
                Int32 error = Marshal.GetLastWin32Error();
                handles.deviceHandle.Close();
                throw new Win32Exception(error, "Unable to initialize WinUSB.");
            }

            // Set the timeout for control transfers to 350 ms.
            // It needs to be that long to support the control transfer that erases the entire script
            // on the Mini Maestros.
            // TODO: test to make sure this timeout is actually being applied correctly
            UInt32 timeout = 350;

            result = WinUsb_SetPipePolicy(handles.winusbHandle, 0, PIPE_TRANSFER_TIMEOUT, 4, &timeout);
            if (!result)
            {
                Int32 error = Marshal.GetLastWin32Error();
                Winusb.disconnect(handles);
                throw new Win32Exception(error, "Unable to set control transfer timeout.");
            }

            return(handles);
        }
Пример #3
0
 protected internal WinUsbDevice(WinUsbDeviceHandles handles)
 {
     this.handles.winusbHandle   = handles.winusbHandle;
     this.handles.deviceHandle   = handles.deviceHandle;
     this.handles.deviceInstance = handles.deviceInstance;
 }