Bytes an USB-Port senden

  • VB.NET

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von Mad Andy.

    Bytes an USB-Port senden

    Hallo,
    ich habe mir einen X-Box-Controller an den USB-Anschluss angeschlossen (Gelötet). Über XBCD (Treiber) kann ich den Controller vibrieren lassen (Rumble), und habe herausgefunden, dass dabei der wert 'FF FF' an den Controller geschickt wird, und zum stoppen der Wert '00 00'. Gibt es jetz eine möglichkeit, diese Werte auch in Visual Basic 2008 an den Controller am USB-Anschluss zu senden?
    Wär schön, wenn einer ne Lösung hätte, Danke im Vorraus.

    Leseratte
    Hi

    Es wird vermutlich mehr als nur FFFF und 0000 an den Controller gesendet. Das wird vermutlich nur die Stärke sein, mit dem der Controller vibriert. Das HID-Protokoll ist erfahrungsgemäß doch etwas komplizierter ;)

    Ich sehe generell 2 Möglichkeiten: 1. du verwendest eine Schnittstelle, die der Treiber bietet (siehe z.B. Quelltext von der Settings-App, den du, iirc, optional mitinstallieren kannst) oder 2. du schreibst dir deinen eigenen Treiber, was wohl eher mehr aufwand ist
    Aber in dem Treiber, wo ich den Rumblen lassen kann, wurde mir gezeigt, dass vom Controller sehr viele Bytes zum PC gesendet werden (Achsenzustände, Knöpfe), aber zum PC halt nur die Beiden Werte, die auf 00 00 stehen, wenn nicht rumbled, und auf FF FF, wenn der Controller stark rumbled. Ich schau aber mal, ob ich den Sourcecode finde.

    EDIT: Source-Code gefunden, Code als zip. Ich habe da nix für Visual Basic gefunden, könnte das irgendwer von Visual C nach Visual Basic 'übersetzen'?
    Ich hab keine Ahnung von C. Danke.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Leseratte“ () aus folgendem Grund: Anhang hinzugefügt

    Die Werte, die Übertragen werden: FF FF bzw. 00 00 sind nur die Vibrationsstärke (Links: 100%, Rechts: 100% bzw. Links: 0%, Rechts: 0%), es fehlt vom Prinzip her noch der Rest, wobei das meiste der USB/HID-Treiber übernimmt.

    Okay, ich habe mich in der Tat geirrt. Es wird nicht via DirectX oder irgrendeinem Treiber-Aufruf das Rumble aktiviert bzw. deaktiviert, sondern das Config-Programm schickt die Werte direkt via HID-Report.
    Der Quelltext, der dich interessieren sollte ist aber übrigens in Delphi/Pascal geschrieben: /XBCDSU/Main.pas. Die Procedure, die relevant ist, ist WriteReport.

    Brainfuck-Quellcode

    1. //--WriteReport-------------------------------------
    2. procedure WriteReport;
    3. var
    4. NumberOfBytesWritten: DWORD;
    5. SendBuffer: array [0..2] of Byte;
    6. begin
    7. //Send data to the device.
    8. //******************************************************************************
    9. //WriteFile
    10. //Sends a report to the device.
    11. //Returns: success or failure.
    12. //Requires: the handle returned by CreateFile and
    13. //The output report byte length returned by HidP_GetCaps
    14. //******************************************************************************
    15. //The first byte is the Report ID
    16. SendBuffer[0] := 2;
    17. SendBuffer[1] := trkRumble[0].Position;
    18. SendBuffer[2] := trkRumble[1].Position;
    19. NumberOfBytesWritten := 0;
    20. WriteFile(HIDHandle, SendBuffer, sizeof(SendBuffer), NumberOfBytesWritten, nil);
    21. If frmMain.chkRawData.Checked = True Then
    22. begin
    23. frmMain.txtBytesSent.Text := IntToHex(SendBuffer[1], 2) + ' ' + IntToHex(SendBuffer[2], 2);
    24. end
    25. Else
    26. frmMain.txtBytesSent.Text := '';
    27. end;
    28. //--WriteReport-------------------------------------

    Was da passiert ist nicht so kompliziert: Der HID-Report PC->Controller hat nur 2 Datenbytes. Es wird ein Buffer mit 3 Bytes angelegt, in's erste Byte eine 2 (passende HID Report ID, siehe HID Report Descriptor) geschrieben, in die anderen beiden die Werte für's "rumblen".
    Nacher wird der Report an den HID-Treiber weitergeschick, der das ganze dann zum Gerät umleitet. WriteFile ist dabei ein Windows API Aufruf.

    Zusätzlich musst du hald erstmal das HIDHandle bekommen/öffnen:

    Quellcode

    1. HIDHandle := CreateFile(PChar(strDevicePath[frmMain.cmbDevices.ItemIndex]),
    2. GENERIC_WRITE,
    3. FILE_SHARE_READ Or FILE_SHARE_WRITE,
    4. nil,//Addr(Security),
    5. OPEN_EXISTING,
    6. 0,
    7. 0);


    Wobei du den DevicePath (erster Parameter beim CreateFile-Aufruf) über XBCDEnumerate(Callback, True) bekommst. XBCDEnumerate ist eine Procedure, die offensichtlich in xbcdif.dll (Teil vom Treiber) enthalten ist.

    Quellcode

    1. function EnumCallback(EnumDevice: PXBCD_Device): Integer;
    2. // ...
    3. strUSBDevicePath[intUSBCount] := EnumDevice.USBPath;
    4. strDevicePath[intUSBCount] := EnumDevice.HIDPath;
    5. // ...
    6. Result := 0;
    7. end;
    Das Enum (dt. "aufzählen") bzw. die Path-Arrays sind notwendig, damit man mehrere Controller anstecken und den aussuchen kann, den man ansprechen will.

    PXBCD_Device ist ein Pointer zu einer "normalen" Struct

    Quellcode

    1. Type
    2. PXBCD_Device = ^TXBCD_Device;
    3. TXBCD_Device = packed record
    4. Index: Integer;
    5. HIDPath: PChar;
    6. USBPath: PChar;
    7. end;


    Wie man am besten klassische C-Strings (Char Pointer) in .net bekommt, weiß ich grad garnicht. Sollte mit etwas Google aber zu lösen sein, hoffe ich :)

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Mad Andy“ ()

    Einen Teil habe ich schon übersetzt, aber der hat nochn paar Fehler.

    VB.NET-Quellcode

    1. Public Class Form1
    2. '--WriteReport-------------------------------------
    3. Private Declare Function WriteFile Lib "kernel32" ( _
    4. ByVal hFile As Long, ByVal lpBuffer As String, _
    5. ByVal nNumberOfBytesToWrite As Long, _
    6. ByVal lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long) As Long
    7. Private Function WriteReport()
    8. Dim NumberOfBytesWritten As Integer
    9. Dim SendBuffer(2) As Byte
    10. 'Send data to the device.
    11. '******************************************************************************
    12. 'WriteFile
    13. 'Sends a report to the device.
    14. 'Returns: success or failure.
    15. 'Requires: the handle returned by CreateFile and
    16. 'The output report byte length returned by HidP_GetCaps
    17. '******************************************************************************
    18. 'The first byte is the Report ID
    19. SendBuffer(0) = 2
    20. SendBuffer(1) = 255
    21. SendBuffer(2) = 255
    22. NumberOfBytesWritten = 0
    23. WriteFile(HIDHandle, SendBuffer, Len(SendBuffer), NumberOfBytesWritten, 0)'In diesem Teil will VB HIDhandle deklariert haben
    24. '--WriteReport-------------------------------------
    25. End Function
    26. End Class

    Ich bräuchte noch einen, der mir die restlichen Teile übersetzt, das bekomm ich überhaupt nicht auf die Reihe. Wie könnte ich das denn jetzt deklarieren?

    EDIT: Also das HIDHandle-Problem löst sich in Luft auf, wenn ich (oder ein andrer) den code davor übersetzt bekommt. Und das NIL ist das selbe wie "0".

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Leseratte“ ()

    NIL ist ein Nullpointer, also im weitesten Sinne eine 0.

    Das CreateFile ist ebenfalls ein Private/Public Declare Function .... Die Enum-Funktion ist ebenfalls so zu Deklarieren, jedoch weiß ich nicht, wie man das mit der Callback-Funktion macht.