Laden...

Win8.1 - Probleme bei HID Kommunikation wegen Power Management

Erstellt von moelski vor 10 Jahren Letzter Beitrag vor 10 Jahren 730 Views
M
moelski Themenstarter:in
183 Beiträge seit 2011
vor 10 Jahren
Win8.1 - Probleme bei HID Kommunikation wegen Power Management

Moin !

Wir haben unter Windows 8.1 ein Problem mit der HID kommunikation. Nach ersten Tests liegt das an den neuen Power Management Funktionen von Windows 8.1. Nicht genutzte Geräte werden sehr schnell in einen Sleep Modus gesetzt.
Im Netz gibt es dazu auch zahlreiche Fragen und auch einen Workaround:
After installing Windows 8.1, my USB device doesn't charge or it disconnects and reconnects frequently...

Ich habe nun mal ein paar Tests gemacht und bin zwar zu einer Lösung gekommen, die finde ich allerdings eher unbauchbar.

            SafeHandle handle = DsKernel.CreateFile(
                this.DevicePath,
                FileAccess.ReadWrite,
                FileShare.ReadWrite,
                IntPtr.Zero,
                FileMode.Open,
                DsKernel.FileAttributes.Overlapped,
                IntPtr.Zero);

            success = DsHidApi.HidD_GetAttributes(handle.DangerousGetHandle(), ref DeviceAttributes); 

            if (success)
            {
                this.Vid = DeviceAttributes.VendorID.ToString("X4");
                this.Pid = DeviceAttributes.ProductID.ToString("X4");
                this.Version = DeviceAttributes.VersionNumber;
                
                success = DsHidApi.HidD_GetPreparsedData(handle.DangerousGetHandle(), ref preparsedData); 
                
                DsHidApi.HIDP_CAPS Capabilities = new DsHidApi.HIDP_CAPS(); 
                Int32 result = 0;
                result = DsHidApi.HidP_GetCaps(preparsedData, ref Capabilities);

                int bufferLength = 126;
                byte[] buffer = new byte[bufferLength];

               ############## Thread.sleep(200);

                // Bei Api Call Problemem mit DsLog.ResultOfApiCall("HidD_GetManufacturerString"); abfragen
                if (DsHidApi.HidD_GetManufacturerString(handle.DangerousGetHandle(), buffer, bufferLength))
                {
                    this.Manufacturer = Encoding.Unicode.GetString(buffer).Replace("\0", string.Empty);
                }

Das ist ein Stück aus der HID Enumeration. Es geht u.a. um das Auslesen von Manufacturer, Serial Number und Product String.

Wenn ich den Code ohne das Sleep laufen lasse bekomme ich > Fehlermeldung:

Fehler 31: A device attached to the system is not functioning.

Mit dem Sleep läuft die Kommunikation sauber durch und die Erkennung klappt auch.

Nun ist ein Sleep aber sicher keine Lösung. Drum meine Frage ob jemand eine saubere Lösung für dieses problem kennt. Gibt es evtl. einen Api Call um das Gerät aus dem Sleep Mode zu "befreien" oder kann ich ein Flag so lange abfragen bis das Gerät bereit für eine Kommunikation ist?

Greetz Dominik

16.842 Beiträge seit 2008
vor 10 Jahren

Hast auch schon WMI probiert? Einige Daten sind hier im Gegensatz zur Win32 API gecached, sodass es egal wäre, wenn das Gerät im Sleep Modus ist.
Geändert werden die Werte IIRC bei Connected, Disconnect und Failure.
Bin mir aber nicht sicher, ob WMI HID-fähige Geräte so ansprechen kann; oder nur einen generischen Namen liefert.

Ansonsten gäbe es noch das WDK, mit dem das gehen sollte.

M
moelski Themenstarter:in
183 Beiträge seit 2011
vor 10 Jahren

Moin Abt,

WMI möchte ich vermeiden. Meine bisherigen Versuche waren da ncht wirklich zielführend und es ist auch im Vergleich zur API eher träge bei der Abfrage.
WDK würde sicher gehen, aber dann muss ich alles umschreiben.

Die Kommunikation an sich klappt ja sobald das Gerät wach ist. Also der Grundlegende Code passt. Es fehlt im Moment eben nur dieses eine Stückchen Code um ein Device aufzuwecken.

Greetz Dominik

16.842 Beiträge seit 2008
vor 10 Jahren

Naja gut.. wenn man mit "das möcht ich nicht" und "da muss ich ja was machen" argumentiert, dann kann mans gleich lassen 😉

Thread.Sleep ist jetzt zwar unsauber; gibt aber genug Konstellationen, wo es einfach nur funktioniert, da es nichts anderes gibt - und darum gehts hier doch. Ich will Thread.Sleep gewiss nicht gut heißen, aber gerade bei solchen Sachen ist Thread.Sleep nicht unbedingt ein schmutziges Mittel.
Kannst jetzt auch ein Timer machen, der nach 200ms einfach eine Methode ausführt; oder eine Schleife, die periodisch abfragt kommt quasi fast aufs gleiche hinaus.

Bei USB werden ja nicht die Geräte selbst, sondern das USB Interface schlafen gelegt. Meist ist das so, dass der ganze Hub im Sleep-Mode ist und nicht nur ein Port.
Ergo hast Du bei Deiner jetzigen Situation ohnehin nicht das korrekte Handle... umbauen musst also so oder so; sofern Du den WakeUp des Interfaces mitbekommst.