Forum: PC-Programmierung FTDI USB device notification


von Patrick B. (p51d)


Lesenswert?

Hallo miteinander

Ich habe eine kleine Software die einen Daten-Stream mit einem MCU 
ermöglicht. Dabei werden Messwerte vom MCU an den PC gesendet. Der PC 
sendet ein paar Einstellungen an den MCU.

Alles läuft soweit so gut. Nun bin ich am Überarbeiten der Software, 
damit diese etwas stabiler läuft: Wenn z.B die Verbindung getrennt 
wurde, erkennt dies die Software noch nicht und versucht einfach weiter 
Daten zu senden.

Jetzt möchte ich dieses Problem beheben. Im gleichen Zug, könnte man ja 
noch eine "Auto-Connect" Funktion hinzufügen.

Bis jetzt habe ich etwas über die Windows Device Notification Events 
gelesen, aber dies ist sehr sehr "kompliziert". Über einen Timer wäre 
dies lösbar, aber nicht so elegant...

FTDI hat dafür eine App-Note herausgegeben, aber leider ist diese in C++ 
geschrieben und ich bräuchte diese in C#. Das wäre zwar nicht sonderlich 
schwer es umzuschreiben, wenn man es versteht...

Hat jemand da einen Tipp?
MFG
Patrick

von Christian R. (supachris)


Lesenswert?

Nimm lieber den sauberen Weg über die WinAPI. 
RegisterForDeviceNotification() ist doch total einfach, das sind doch 
nur 2 Zeilen, um sich das Event anhand der GUID des Treibers generieren 
zu lassen.

von Patrick B. (p51d)


Lesenswert?

Einfach? 2 Zeilen?

Hier sind etwas mehr als 2 Zeilen...
http://msdn.microsoft.com/en-us/library/aa363432%28v=VS.85%29.aspx

Aber eventuell hast du ja ein besseres Beispiel.
MFG

von Christian R. (supachris)


Lesenswert?

OK, 2 Zeilen sind nicht nur, aber viel mehr auch nicht. Ich programmiere 
mit der MFC, daher diese Lösung. Hab ich von hier: 
http://www.codeproject.com/KB/system/HwDetect.aspx
1
BEGIN_MESSAGE_MAP(..., CDialog)
2
  ...
3
  ON_MESSAGE(WM_DEVICECHANGE, OnMyDeviceChange)
4
  ...
5
END_MESSAGE_MAP()
6
7
8
BOOL Dialog::OnInitDialog()
9
{
10
  DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
11
  ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );
12
  NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
13
  NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
14
  
15
  NotificationFilter.dbcc_classguid = GUID;
16
  HDEVNOTIFY hDevNotify = RegisterDeviceNotification(this->GetSafeHwnd(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
17
18
  return TRUE;  // return TRUE  unless you set the focus to a control
19
}
20
21
LRESULT Dialog::OnMyDeviceChange(WPARAM wParam, LPARAM lParam)
22
{
23
    // for more information, see MSDN help of WM_DEVICECHANGE
24
25
    // this part should not be very difficult to understand
26
27
  if(wParam == DBT_DEVICEARRIVAL)
28
  {
29
30
  }
31
  
32
  if(wParam == DBT_DEVICEREMOVECOMPLETE)
33
  {
34
35
  }
36
  
37
    return 0;
38
}

Musst du natürlich bissl modifizieren und die Methoden deklarieren.

von Patrick B. (p51d)


Lesenswert?

Ich steh gerade etwas auf dem Schlauch:

Das ist die C++ Variante, oder? Geht das auch mit C#?
Weil alle anderen Beispiele haben nie eine Message_Map...

von Christian R. (supachris)


Lesenswert?

Achso. Ich habs falsch gelesen, ich dachte du brauchst C++ und hast nur 
ein C# Beispiel. Sicher geht das auch in C#, da hab ich aber kein 
eigenes Beispiel parat. Viel mehr kann es dort aber auch nicht sein, und 
die Eventhandler sind ja in C# noch einfacher zu handhaben...

von Patrick B. (p51d)


Lesenswert?

OK.

Das Abfangen der Meldung, ob ein USB Gerät angeschlossen oder entfernt 
wurde habe ich mitlerweile:
1
protected override void WndProc(ref Message m)
2
{
3
    if (m.Msg == WM_DEVICECHANGE)
4
    {
5
        switch (m.WParam.ToInt32())
6
        {
7
            case DBT_DEVICEARRIVAL:
8
                MessageBox.Show(m.LParam.ToString());
9
                break;
10
            
11
            case DBT_DEVICEREMOVECOMPLETE:
12
                MessageBox.Show(m.LParam.ToString());
13
                break;
14
        }
15
    }
16
    base.WndProc(ref m);
17
}

Jetzt ist einfach noch das Problem, dass der Event jedesmal kommt. Aber 
ich möchte ihn nur für ein Device. Die GUID habe ich...
Kann ich da irgendwas noch hinzufügen?

von Christian R. (supachris)


Lesenswert?

In C++ kommst du über den LParam an die Device-Infos ran:
1
if(wParam == DBT_DEVICEARRIVAL)
2
  {
3
    PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
4
    if(pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
5
    {
6
      PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;
7
      ...
8
    }
9
  }

An pDevInf hängt dann der Name, Gerätepfad, Class-GUID usw. da kannst du 
dir das passende raussuchen und nur was machen, wenn die GUID 
passt....ich vermute, das geht bei dir genau so.

von Patrick B. (p51d)


Lesenswert?

Klapt leider nicht.

Ich müsste die Events für ein ganz spezielles Device bekommen, da wenn 
z.B 2 FTDI Chips angeschlossen wurden und einer Entfernt wird, bekomme 
ich dann den selben Event...

Werde noch etwas Suchen, aber irgendwie habe ich das Gefühl das hierfür 
C# nicht unbedingt geeignet ist.

von Christian R. (supachris)


Lesenswert?

Hm, du musst doch auch in C# den Gerätepfad usw. mit dem Event 
mitbekommen. Da musst du dann halt nach deiner genauen Seriennummer oder 
was auch immer suchen. Mit der C++ Variante und 
RegisterForDeviceNotification() bekommst du auch für alle Geräte, die 
mit der gleichen Treiber GUID laufen das Event.

von Arc N. (arc)


Lesenswert?

Patrick B. schrieb:
> Klapt leider nicht.
>
> Ich müsste die Events für ein ganz spezielles Device bekommen, da wenn
> z.B 2 FTDI Chips angeschlossen wurden und einer Entfernt wird, bekomme
> ich dann den selben Event...
>
> Werde noch etwas Suchen, aber irgendwie habe ich das Gefühl das hierfür
> C# nicht unbedingt geeignet ist.

http://social.msdn.microsoft.com/Forums/eu/csharpgeneral/thread/c4b7445f-9e1d-4b3e-b4a1-320d1d8b1ef7

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.