/// <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); }
internal UInt16 getProductID() { return(Winusb.getProductID(deviceInstance)); }
internal UInt16 getVendorID() { return(Winusb.getVendorID(deviceInstance)); }
/// <summary> /// Disconnects from the device. This allows other programs to connect to the /// device and frees all the memory used by Winusb. After calling disconnect() /// you should not try to call any other functions on this object. /// /// Example usage: /// device.disconnect(); /// device = null; /// </summary> internal void disconnect() { Winusb.disconnect(this.handles); }