/// <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. }
/// <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); }
protected internal WinUsbDevice(WinUsbDeviceHandles handles) { this.handles.winusbHandle = handles.winusbHandle; this.handles.deviceHandle = handles.deviceHandle; this.handles.deviceInstance = handles.deviceInstance; }