Created
February 22, 2026 00:45
-
-
Save saper-2/e94b64253ba223302dea6c257263ddd0 to your computer and use it in GitHub Desktop.
cp2112-cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Runtime.InteropServices; | |
| using System.Text; | |
| namespace SLABCP2112; | |
| /// <summary> | |
| /// Główna klasa importująca funkcje z SLABHIDtoSMBus.dll | |
| /// Używa LibraryImport dla .NET 9 (source generator) | |
| /// </summary> | |
| internal static partial class HidSmbus | |
| { | |
| // ========================================================================= | |
| // Funkcje zarządzania urządzeniem i enumeracji | |
| // ========================================================================= | |
| [DllImport("SLABHIDtoSMBus.dll", CallingConvention = CallingConvention.StdCall)] | |
| private static extern int HidSmbus_Open( | |
| out IntPtr device, | |
| uint deviceNum, // const DWORD deviceNum | |
| ushort vid, // const WORD vid | |
| ushort pid); // const WORD pid | |
| [DllImport("SLABHIDtoSMBus.dll", CallingConvention = CallingConvention.StdCall)] | |
| private static extern int HidSmbus_GetNumDevices( | |
| out uint numDevices, // const DWORD deviceNum - UWAGA! może być uint | |
| ushort vid, // const WORD vid | |
| ushort pid); // const WORD pid | |
| [DllImport("SLABHIDtoSMBus.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)] | |
| private static extern int HidSmbus_OpenBySerial( | |
| out IntPtr device, | |
| ushort vid, | |
| ushort pid, | |
| string serial); | |
| [DllImport("SLABHIDtoSMBus.dll", CallingConvention = CallingConvention.StdCall)] | |
| private static extern int HidSmbus_Close(IntPtr device); | |
| /*[LibraryImport("SLABHIDtoSMBus.dll")] | |
| private static partial int HidSmbus_IsOpened( | |
| IntPtr device, | |
| out bool opened);*/ | |
| [DllImport("SLABHIDtoSMBus.dll", CallingConvention = CallingConvention.StdCall)] | |
| private static extern int HidSmbus_IsOpened( | |
| IntPtr device, | |
| out byte opened); | |
| [DllImport("SLABHIDtoSMBus.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)] | |
| private static extern int HidSmbus_GetString( | |
| uint deviceNum, // const DWORD deviceNum | |
| ushort vid, // const WORD vid | |
| ushort pid, // const WORD pid | |
| byte[] deviceString, // char* deviceString | |
| int options); // const HID_SMBUS_GETSTRING options | |
| /// <summary> | |
| /// h: HidSmbus_GetOpenedString(_In_ _Pre_defensive_ const HID_SMBUS_DEVICE device, char* deviceString, _In_ _Pre_defensive_ const HID_SMBUS_GETSTRING options); | |
| /// </summary> | |
| /// <param name="device"></param> | |
| /// <param name="deviceString"></param> | |
| /// <param name="getStringOption"></param> | |
| /// <returns></returns> | |
| [DllImport("SLABHIDtoSMBus.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)] | |
| private static extern int HidSmbus_GetOpenedString( | |
| IntPtr device, | |
| byte[] deviceString, | |
| int getStringOption); | |
| // ========================================================================= | |
| // Funkcje konfiguracyjne SMBus | |
| // ========================================================================= | |
| [DllImport("SLABHIDtoSMBus.dll", CallingConvention = CallingConvention.StdCall)] | |
| private static extern int HidSmbus_GetSmbusConfig( | |
| IntPtr device, | |
| out int bitRate, | |
| out int address, | |
| out int autoReadRespond, | |
| out int writeTimeout, | |
| out int readTimeout, | |
| out byte sclLowTimeout, | |
| out byte transferRetries); | |
| [DllImport("SLABHIDtoSMBus.dll", CallingConvention = CallingConvention.StdCall)] | |
| private static extern int HidSmbus_SetSmbusConfig( | |
| IntPtr device, | |
| int bitRate, | |
| int address, | |
| int autoReadRespond, | |
| int writeTimeout, | |
| int readTimeout, | |
| byte sclLowTimeout, | |
| byte transferRetries); | |
| // ========================================================================= | |
| // Funkcje transferu danych SMBus | |
| // ========================================================================= | |
| [DllImport("SLABHIDtoSMBus.dll", CallingConvention = CallingConvention.StdCall)] | |
| private static extern int HidSmbus_WriteRequest( | |
| IntPtr device, | |
| byte targetAddress, | |
| byte[] data, | |
| int numBytesToWrite); | |
| [DllImport("SLABHIDtoSMBus.dll", CallingConvention = CallingConvention.StdCall)] | |
| private static extern int HidSmbus_ReadRequest( | |
| IntPtr device, | |
| byte targetAddress, | |
| int numBytesToRead); | |
| [DllImport("SLABHIDtoSMBus.dll", CallingConvention = CallingConvention.StdCall)] | |
| private static extern int HidSmbus_TransferStatusRequest( | |
| IntPtr device, | |
| out byte status, | |
| out byte detail); | |
| [DllImport("SLABHIDtoSMBus.dll", CallingConvention = CallingConvention.StdCall)] | |
| private static extern int HidSmbus_ReadResponse( | |
| IntPtr device, | |
| byte[] buffer, | |
| out int numBytesRead); | |
| [DllImport("SLABHIDtoSMBus.dll", CallingConvention = CallingConvention.StdCall)] | |
| private static extern int HidSmbus_TransferAbort( | |
| IntPtr device); | |
| [DllImport("SLABHIDtoSMBus.dll", CallingConvention = CallingConvention.StdCall)] | |
| private static extern int HidSmbus_Reset( | |
| IntPtr device); | |
| // ========================================================================= | |
| // Funkcje do zarządzania GPIO | |
| // ========================================================================= | |
| [DllImport("SLABHIDtoSMBus.dll", CallingConvention = CallingConvention.StdCall)] | |
| private static extern int HidSmbus_GetGpioConfig( | |
| IntPtr device, | |
| out byte direction, | |
| out byte mode, | |
| out byte function, | |
| out byte clkDivider); | |
| [DllImport("SLABHIDtoSMBus.dll", CallingConvention = CallingConvention.StdCall)] | |
| private static extern int HidSmbus_SetGpioConfig( | |
| IntPtr device, | |
| byte direction, | |
| byte mode, | |
| byte function, | |
| byte clkDivider); | |
| [DllImport("SLABHIDtoSMBus.dll", CallingConvention = CallingConvention.StdCall)] | |
| private static extern int HidSmbus_GetGpio( | |
| IntPtr device, | |
| out byte gpioValue); | |
| [DllImport("SLABHIDtoSMBus.dll", CallingConvention = CallingConvention.StdCall)] | |
| private static extern int HidSmbus_SetGpio( | |
| IntPtr device, | |
| byte gpioValue); | |
| // ========================================================================= | |
| // Publiczne metody wrappera - one wywołują prywatne importy | |
| // ========================================================================= | |
| public static int GetNumDevices(out int numDevices, int vid, int pid) | |
| { | |
| uint devices = 0; | |
| int result = HidSmbus_GetNumDevices(out devices, (ushort)vid, (ushort)pid); | |
| numDevices = (int)devices; | |
| return result; | |
| } | |
| public static int Open(out IntPtr device, int vid, int pid, int deviceIndex) | |
| { | |
| // POPRAWNA KOLEJNOŚĆ: deviceNum, vid, pid | |
| return HidSmbus_Open(out device, (uint)deviceIndex, (ushort)vid, (ushort)pid); | |
| } | |
| public static int OpenBySerial(out IntPtr device, int vid, int pid, string serial) | |
| { | |
| return HidSmbus_OpenBySerial(out device, (ushort)vid, (ushort)pid, serial); | |
| } | |
| public static int Close(IntPtr device) | |
| { | |
| return HidSmbus_Close(device); | |
| } | |
| public static int GetString(int deviceNum, int vid, int pid, byte[] deviceString, int options) | |
| { | |
| return HidSmbus_GetString((uint)deviceNum, (ushort)vid, (ushort)pid, deviceString, options); | |
| } | |
| public static int GetOpenedString(IntPtr device, byte[] deviceString, int options) | |
| { | |
| return HidSmbus_GetOpenedString(device, deviceString, options); | |
| } | |
| /*public static int IsOpened(IntPtr device, out bool opened) | |
| { | |
| return HidSmbus_IsOpened(device, out opened); | |
| }*/ | |
| public static int IsOpened(IntPtr device, out bool opened) | |
| { | |
| int result = HidSmbus_IsOpened(device, out byte openedByte); | |
| opened = openedByte != 0; | |
| return result; | |
| } | |
| public static int GetSmbusConfig(IntPtr device, out int bitRate, out int address, out int autoReadRespond, | |
| out int writeTimeout, out int readTimeout, out byte sclLowTimeout, out byte transferRetries) | |
| { | |
| return HidSmbus_GetSmbusConfig(device, out bitRate, out address, out autoReadRespond, | |
| out writeTimeout, out readTimeout, out sclLowTimeout, out transferRetries); | |
| } | |
| public static int SetSmbusConfig(IntPtr device, int bitRate, int address, int autoReadRespond, | |
| int writeTimeout, int readTimeout, byte sclLowTimeout, byte transferRetries) | |
| { | |
| return HidSmbus_SetSmbusConfig(device, bitRate, address, autoReadRespond, | |
| writeTimeout, readTimeout, sclLowTimeout, transferRetries); | |
| } | |
| public static int WriteRequest(IntPtr device, byte targetAddress, byte[] data, int numBytesToWrite) | |
| { | |
| return HidSmbus_WriteRequest(device, targetAddress, data, numBytesToWrite); | |
| } | |
| public static int ReadRequest(IntPtr device, byte targetAddress, int numBytesToRead) | |
| { | |
| return HidSmbus_ReadRequest(device, targetAddress, numBytesToRead); | |
| } | |
| public static int TransferStatusRequest(IntPtr device, out byte status, out byte detail) | |
| { | |
| return HidSmbus_TransferStatusRequest(device, out status, out detail); | |
| } | |
| public static int ReadResponse(IntPtr device, byte[] buffer, out int numBytesRead) | |
| { | |
| return HidSmbus_ReadResponse(device, buffer, out numBytesRead); | |
| } | |
| public static int TransferAbort(IntPtr device) | |
| { | |
| return HidSmbus_TransferAbort(device); | |
| } | |
| public static int Reset(IntPtr device) | |
| { | |
| return HidSmbus_Reset(device); | |
| } | |
| public static int GetGpioConfig(IntPtr device, out byte direction, out byte mode, out byte function, out byte clkDivider) | |
| { | |
| return HidSmbus_GetGpioConfig(device, out direction, out mode, out function, out clkDivider); | |
| } | |
| public static int SetGpioConfig(IntPtr device, byte direction, byte mode, byte function, byte clkDivider) | |
| { | |
| return HidSmbus_SetGpioConfig(device, direction, mode, function, clkDivider); | |
| } | |
| public static int GetGpio(IntPtr device, out byte gpioValue) | |
| { | |
| return HidSmbus_GetGpio(device, out gpioValue); | |
| } | |
| public static int SetGpio(IntPtr device, byte gpioValue) | |
| { | |
| return HidSmbus_SetGpio(device, gpioValue); | |
| } | |
| } | |
| /// <summary> | |
| /// Wrapper dla urządzenia CP2112 - uproszczenie użycia | |
| /// </summary> | |
| public class Cp2112Device : IDisposable | |
| { | |
| private IntPtr _deviceHandle; | |
| private bool _disposed; | |
| public const int HID_SMBUS_GET_VID_STR = 0x01; | |
| public const int HID_SMBUS_GET_PID_STR = 0x02; | |
| public const int HID_SMBUS_GET_PATH_STR = 0x03; | |
| public const int HID_SMBUS_GET_SERIAL_STR = 0x04; | |
| public const int HID_SMBUS_GET_MANUFACTURER_STR = 0x05; | |
| public const int HID_SMBUS_GET_PRODUCT_STR = 0x06; | |
| public const byte HID_SMBUS_S0_IDLE = 0x00; | |
| public const byte HID_SMBUS_S0_BUSY = 0x01; | |
| public const byte HID_SMBUS_S0_COMPLETE = 0x02; | |
| public const byte HID_SMBUS_S0_ERROR = 0x03; | |
| public const int SILICON_LABS_VID = 0x10C4; | |
| public const int CP2112_PID = 0xEA90; | |
| public IntPtr GetHandle() => _deviceHandle; | |
| public static Cp2112Device? OpenFirst(int vid = SILICON_LABS_VID, int pid = CP2112_PID) | |
| { | |
| var result = HidSmbus.GetNumDevices(out int numDevices, vid, pid); | |
| if (result != 0 || numDevices == 0) | |
| return null; | |
| var device = new Cp2112Device(); | |
| result = HidSmbus.Open(out device._deviceHandle, vid, pid, 0); | |
| return result == 0 ? device : null; | |
| } | |
| // Dodatkowa metoda do testowania | |
| /*public static void ListAllDevices() | |
| { | |
| //Console.WriteLine("=== LISTA WSZYSTKICH URZĄDZEŃ CP2112 ===\n"); | |
| int result = HidSmbus.GetNumDevices(out int numDevices, SILICON_LABS_VID, CP2112_PID); | |
| if (result != 0 || numDevices == 0) | |
| { | |
| //Console.WriteLine("Nie znaleziono żadnych urządzeń CP2112."); | |
| return; | |
| } | |
| //Console.WriteLine($"Znaleziono {numDevices} urządzeń CP2112:\n"); | |
| for (int i = 0; i < numDevices; i++) | |
| { | |
| //Console.WriteLine($"--- URZĄDZENIE #{i} ---"); | |
| using var device = OpenByIndex(i, SILICON_LABS_VID, CP2112_PID); | |
| if (device != null) | |
| { | |
| //Console.WriteLine($" Handle: {device.GetHandle()}"); | |
| //Console.WriteLine($" Serial: {device.GetSerialString()}"); | |
| //Console.WriteLine($" Manufacturer: {device.GetString(HID_SMBUS_GET_MANUFACTURER_STR)}"); | |
| //Console.WriteLine($" Product: {device.GetString(HID_SMBUS_GET_PRODUCT_STR)}"); | |
| //Console.WriteLine(); | |
| } | |
| else | |
| { | |
| //Console.WriteLine($" Nie można otworzyć urządzenia #{i}"); | |
| } | |
| } | |
| }*/ | |
| public static Cp2112Device? OpenBySerial(string serial, int vid = SILICON_LABS_VID, int pid = CP2112_PID) | |
| { | |
| var device = new Cp2112Device(); | |
| var result = HidSmbus.OpenBySerial(out device._deviceHandle, vid, pid, serial); | |
| return result == 0 ? device : null; | |
| } | |
| /// <summary> | |
| /// Otwiera urządzenie o podanym indeksie | |
| /// </summary> | |
| public static Cp2112Device? OpenByIndex(int index, int vid = SILICON_LABS_VID, int pid = CP2112_PID) | |
| { | |
| var device = new Cp2112Device(); | |
| int result = HidSmbus.Open(out device._deviceHandle, vid, pid, index); | |
| return result == 0 ? device : null; | |
| } | |
| public string? GetSerialString() | |
| { | |
| return GetString(HID_SMBUS_GET_SERIAL_STR); | |
| } | |
| public string? GetString(int stringType) | |
| { | |
| byte[] buffer = new byte[260]; | |
| var result = HidSmbus.GetOpenedString(_deviceHandle, buffer, stringType); | |
| if (result != 0) return null; | |
| int length = Array.IndexOf(buffer, (byte)0); | |
| return System.Text.Encoding.UTF8.GetString(buffer, 0, length >= 0 ? length : buffer.Length); | |
| } | |
| public int ConfigureSmbus(int bitRate, int address, int writeTimeoutMs, int readTimeoutMs, byte retries = 0) | |
| { | |
| return HidSmbus.SetSmbusConfig( | |
| _deviceHandle, | |
| bitRate, | |
| address, | |
| 1, // autoReadRespond = true | |
| writeTimeoutMs, | |
| readTimeoutMs, | |
| 1, // sclLowTimeout = true | |
| retries); | |
| } | |
| public int Write(byte targetAddress, byte[] data) | |
| { | |
| return HidSmbus.WriteRequest(_deviceHandle, targetAddress, data, data.Length); | |
| } | |
| public int Read(byte targetAddress, int bytesToRead, out byte[] data) | |
| { | |
| data = Array.Empty<byte>(); | |
| var result = HidSmbus.ReadRequest(_deviceHandle, targetAddress, bytesToRead); | |
| if (result != 0) return result; | |
| byte status, detail; | |
| do | |
| { | |
| Thread.Sleep(1); | |
| result = HidSmbus.TransferStatusRequest(_deviceHandle, out status, out detail); | |
| if (result != 0) return result; | |
| } while (status == HID_SMBUS_S0_BUSY); | |
| if (status != HID_SMBUS_S0_COMPLETE) | |
| return -1; | |
| data = new byte[61]; | |
| result = HidSmbus.ReadResponse(_deviceHandle, data, out int bytesRead); | |
| if (bytesRead < data.Length) | |
| Array.Resize(ref data, bytesRead); | |
| return result; | |
| } | |
| public int SetGpio(byte gpioValue) | |
| { | |
| return HidSmbus.SetGpio(_deviceHandle, gpioValue); | |
| } | |
| public int GetGpio(out byte gpioValue) | |
| { | |
| return HidSmbus.GetGpio(_deviceHandle, out gpioValue); | |
| } | |
| public int Reset() | |
| { | |
| return HidSmbus.Reset(_deviceHandle); | |
| } | |
| public void Dispose() | |
| { | |
| if (!_disposed && _deviceHandle != IntPtr.Zero) | |
| { | |
| HidSmbus.Close(_deviceHandle); | |
| _deviceHandle = IntPtr.Zero; | |
| } | |
| _disposed = true; | |
| GC.SuppressFinalize(this); | |
| } | |
| /// <summary> | |
| /// Zwraca listę wszystkich podłączonych urządzeń CP2112 bez ich otwierania | |
| /// </summary> | |
| public static List<Cp2112DeviceInfo> EnumerateAll(int vid = SILICON_LABS_VID, int pid = CP2112_PID) | |
| { | |
| var devices = new List<Cp2112DeviceInfo>(); | |
| // Sprawdź liczbę urządzeń | |
| int result = HidSmbus.GetNumDevices(out int numDevices, vid, pid); | |
| if (result != 0 || numDevices == 0) | |
| return devices; | |
| // Dla każdego urządzenia pobierz podstawowe informacje | |
| for (int i = 0; i < numDevices; i++) | |
| { | |
| var deviceInfo = new Cp2112DeviceInfo | |
| { | |
| DeviceIndex = i, | |
| Vid = vid, | |
| Pid = pid | |
| }; | |
| // Próba otwarcia urządzenia (tymczasowo) | |
| IntPtr tempHandle = IntPtr.Zero; | |
| try | |
| { | |
| result = HidSmbus.Open(out tempHandle, vid, pid, i); | |
| if (result == 0 && tempHandle != IntPtr.Zero) | |
| { | |
| // Pobierz stringi | |
| deviceInfo.ManufacturerString = GetStringFromDevice(tempHandle, HID_SMBUS_GET_MANUFACTURER_STR); | |
| deviceInfo.ProductString = GetStringFromDevice(tempHandle, HID_SMBUS_GET_PRODUCT_STR); | |
| deviceInfo.SerialString = GetStringFromDevice(tempHandle, HID_SMBUS_GET_SERIAL_STR); | |
| deviceInfo.Path = GetStringFromDevice(tempHandle, HID_SMBUS_GET_PATH_STR); | |
| } | |
| } | |
| catch | |
| { | |
| // Ignoruj błędy przy pojedynczym urządzeniu | |
| } | |
| finally | |
| { | |
| if (tempHandle != IntPtr.Zero) | |
| HidSmbus.Close(tempHandle); | |
| } | |
| devices.Add(deviceInfo); | |
| } | |
| return devices; | |
| } | |
| /// <summary> | |
| /// Pomocnicza metoda do pobierania stringów z urządzenia | |
| /// </summary> | |
| private static string? GetStringFromDevice(IntPtr deviceHandle, int stringType) | |
| { | |
| byte[] buffer = new byte[260]; | |
| int result = HidSmbus.GetOpenedString(deviceHandle, buffer, stringType); | |
| if (result != 0) return null; | |
| int length = Array.IndexOf(buffer, (byte)0); | |
| if (length <= 0) return null; | |
| return Encoding.UTF8.GetString(buffer, 0, length); | |
| } | |
| /// <summary> | |
| /// Skanuje magistralę I2C w poszukiwaniu urządzeń slave. | |
| /// </summary> | |
| /// <param name="startAddress">Początkowy adres (domyślnie 0x02)</param> | |
| /// <param name="endAddress">Końcowy adres (domyślnie 0x7F)</param> | |
| /// <param name="timeoutMs">Timeout dla każdej próby w ms</param> | |
| /// <returns>Lista znalezionych adresów</returns> | |
| public List<byte> ScanI2CBus(byte startAddress = 0x02, byte endAddress = 0x7F, int timeoutMs = 10) | |
| { | |
| var foundDevices = new List<byte>(); | |
| if (_deviceHandle == IntPtr.Zero) | |
| throw new InvalidOperationException("Urządzenie nie jest otwarte"); | |
| // Zapisz oryginalną konfigurację | |
| HidSmbus.GetSmbusConfig(_deviceHandle, | |
| out int originalBitRate, | |
| out int originalAddress, | |
| out int originalAutoRespond, | |
| out int originalWriteTimeout, | |
| out int originalReadTimeout, | |
| out byte originalSclTimeout, | |
| out byte originalRetries); | |
| try | |
| { | |
| // Optymalizacja dla skanowania: ustaw małą liczbę retransmisji i krótki timeout | |
| // Ustawienie transferRetries=1 oznacza tylko jedną próbę, bez ponowień przy błędzie [citation:1] | |
| HidSmbus.SetSmbusConfig( | |
| _deviceHandle, | |
| originalBitRate, | |
| originalAddress, | |
| 0, // autoReadRespond = false (ważne dla skanowania) | |
| timeoutMs, | |
| timeoutMs, | |
| 1, // sclLowTimeout = true | |
| 1 // transferRetries = 1 (tylko jedna próba) | |
| ); | |
| //Console.WriteLine($"Skanowanie adresów od 0x{startAddress:X2} do 0x{endAddress:X2}..."); | |
| // Przeskanuj wszystkie adresy | |
| for (byte address = startAddress; address <= endAddress; address++) | |
| { | |
| // Pomijamy adresy nieparzyste? Dla SMBus adresy są parzyste (7-bitowe) | |
| // CP2112 obsługuje adresy od 0x02 do 0xFE z krokiem 2 [citation:1] | |
| // Próba zapisu 1 bajtu (lub odczytu) bez faktycznego przesyłania danych | |
| byte[] dummyData = { 0x00 }; // Jeden bajt dummy data | |
| // Opcja 1: Próba zapisu (nie zmienia stanu urządzenia jeśli wyślemy 0x00) | |
| int result = HidSmbus.WriteRequest(_deviceHandle, address, dummyData, 1); | |
| // Opcja 2: Alternatywnie możesz użyć ReadRequest (bezpieczniejsze, nie modyfikuje) | |
| // int result = HidSmbus.ReadRequest(_deviceHandle, address, 1); | |
| if (result == 0) // HID_SMBUS_SUCCESS | |
| { | |
| // Sprawdź status transferu | |
| byte status, detail; | |
| Thread.Sleep(1); // Krótkie opóźnienie | |
| result = HidSmbus.TransferStatusRequest(_deviceHandle, out status, out detail); | |
| if (result == 0) | |
| { | |
| // Jeśli status COMPLETE - urządzenie odpowiedziało ACK | |
| if (status == HID_SMBUS_S0_COMPLETE) | |
| { | |
| //Console.WriteLine($" Znaleziono urządzenie na adresie 0x{address:X2}"); | |
| foundDevices.Add(address); | |
| } | |
| } | |
| } | |
| // Krótkie opóźnienie między skanowaniem | |
| Thread.Sleep(1); | |
| } | |
| } | |
| finally | |
| { | |
| // Przywróć oryginalną konfigurację | |
| HidSmbus.SetSmbusConfig( | |
| _deviceHandle, | |
| originalBitRate, | |
| originalAddress, | |
| originalAutoRespond, | |
| originalWriteTimeout, | |
| originalReadTimeout, | |
| originalSclTimeout, | |
| originalRetries); | |
| } | |
| return foundDevices; | |
| } | |
| /// <summary> | |
| /// Skanuje magistralę I2C używając ReadRequest (nie modyfikuje urządzeń) | |
| /// </summary> | |
| public List<byte> ScanI2CBusSafe(byte startAddress = 0x02, byte endAddress = 0x7F, int timeoutMs = 10) | |
| { | |
| var foundDevices = new List<byte>(); | |
| if (_deviceHandle == IntPtr.Zero) | |
| throw new InvalidOperationException("Urządzenie nie jest otwarte"); | |
| // Zapisz oryginalną konfigurację | |
| HidSmbus.GetSmbusConfig(_deviceHandle, | |
| out int originalBitRate, | |
| out int originalAddress, | |
| out int originalAutoRespond, | |
| out int originalWriteTimeout, | |
| out int originalReadTimeout, | |
| out byte originalSclTimeout, | |
| out byte originalRetries); | |
| try | |
| { | |
| // Konfiguracja dla skanowania | |
| HidSmbus.SetSmbusConfig( | |
| _deviceHandle, | |
| originalBitRate, | |
| originalAddress, | |
| 0, // autoReadRespond = false | |
| timeoutMs, | |
| timeoutMs, | |
| 1, | |
| 1); | |
| //Console.WriteLine($"Skanowanie adresów od 0x{startAddress:X2} do 0x{endAddress:X2}..."); | |
| //Console.WriteLine("Oczekiwanie na stabilizację magistrali..."); | |
| Thread.Sleep(100); | |
| for (byte address = startAddress; address <= endAddress; address++) | |
| { | |
| // Użyj ReadRequest zamiast WriteRequest - to bezpieczniejsze | |
| // Nie wysyłamy żadnych danych, tylko sprawdzamy czy slave odpowiada | |
| int result = HidSmbus.ReadRequest(_deviceHandle, address, 1); | |
| if (result == 0) | |
| { | |
| // Daj czas na odpowiedź | |
| Thread.Sleep(2); | |
| // Sprawdź status transferu | |
| byte status, detail; | |
| result = HidSmbus.TransferStatusRequest(_deviceHandle, out status, out detail); | |
| if (result == 0) | |
| { | |
| if (status == HID_SMBUS_S0_COMPLETE) | |
| { | |
| //Console.WriteLine($" [OK] Adres 0x{address:X2} - odpowiedź ACK"); | |
| foundDevices.Add(address); | |
| } | |
| else if (status == HID_SMBUS_S0_ERROR) | |
| { | |
| // Brak urządzenia - NACK, ignorujemy | |
| // Console.WriteLine($" Adres 0x{address:X2} - NACK"); | |
| } | |
| } | |
| } | |
| // Małe opóźnienie między próbami | |
| Thread.Sleep(1); | |
| } | |
| } | |
| finally | |
| { | |
| // Przywróć oryginalną konfigurację | |
| HidSmbus.SetSmbusConfig( | |
| _deviceHandle, | |
| originalBitRate, | |
| originalAddress, | |
| originalAutoRespond, | |
| originalWriteTimeout, | |
| originalReadTimeout, | |
| originalSclTimeout, | |
| originalRetries); | |
| } | |
| //Console.WriteLine($"Skanowanie zakończone. Znaleziono {foundDevices.Count} urządzeń."); | |
| return foundDevices; | |
| } | |
| } | |
| public class I2CScanResult | |
| { | |
| public byte Address { get; set; } | |
| public bool HasDevice { get; set; } | |
| public string? DeviceType { get; set; } | |
| public int ResponseTimeMs { get; set; } | |
| public override string ToString() | |
| { | |
| return $"0x{Address:X2} ({(Address % 2 == 0 ? "even" : "odd")}): {(HasDevice ? "OK" : "---")}"; | |
| } | |
| } | |
| /// <summary> | |
| /// Klasa reprezentująca informacje o urządzeniu bez otwierania go | |
| /// </summary> | |
| public class Cp2112DeviceInfo | |
| { | |
| public int DeviceIndex { get; set; } | |
| public int Vid { get; set; } | |
| public int Pid { get; set; } | |
| public string? ManufacturerString { get; set; } | |
| public string? ProductString { get; set; } | |
| public string? SerialString { get; set; } | |
| public string? Path { get; set; } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment