Du bist nicht angemeldet.

Leseratte

Registrierter Benutzer

  • »Leseratte« ist der Autor dieses Themas

Beiträge: 141

Dabei seit: 10. April 2010

Wohnort: Welt://Europa/Deutschland/NRW/Ich.Mensch

Hilfreich-Bewertungen: 4

  • Private Nachricht senden

1

Samstag, 10. April 2010, 14:34

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

Mad Andy

Registrierter Benutzer

  • »Mad Andy« ist männlich

Beiträge: 4 451

Dabei seit: 2. August 2004

Wohnort: Österreich / Wien

Hilfreich-Bewertungen: 13

  • Private Nachricht senden

2

Sonntag, 11. April 2010, 04:30

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

Leseratte

Registrierter Benutzer

  • »Leseratte« ist der Autor dieses Themas

Beiträge: 141

Dabei seit: 10. April 2010

Wohnort: Welt://Europa/Deutschland/NRW/Ich.Mensch

Hilfreich-Bewertungen: 4

  • Private Nachricht senden

3

Sonntag, 11. April 2010, 06:59

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« (11. April 2010, 07:07) aus folgendem Grund: Anhang hinzugefügt


Mad Andy

Registrierter Benutzer

  • »Mad Andy« ist männlich

Beiträge: 4 451

Dabei seit: 2. August 2004

Wohnort: Österreich / Wien

Hilfreich-Bewertungen: 13

  • Private Nachricht senden

4

Sonntag, 11. April 2010, 18:26

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.

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//--WriteReport-------------------------------------
procedure WriteReport;
var
   NumberOfBytesWritten: DWORD;
   SendBuffer: array [0..2] of Byte;
begin
     //Send data to the device.
    
    //******************************************************************************
    //WriteFile
    //Sends a report to the device.
    //Returns: success or failure.
    //Requires: the handle returned by CreateFile and
    //The output report byte length returned by HidP_GetCaps
    //******************************************************************************

    //The first byte is the Report ID
    SendBuffer[0] := 2;

    SendBuffer[1] := trkRumble[0].Position;
    SendBuffer[2] := trkRumble[1].Position;
    
    NumberOfBytesWritten := 0;

    WriteFile(HIDHandle, SendBuffer, sizeof(SendBuffer), NumberOfBytesWritten, nil);

    If frmMain.chkRawData.Checked = True Then
    begin
        frmMain.txtBytesSent.Text := IntToHex(SendBuffer[1], 2) + '         ' + IntToHex(SendBuffer[2], 2);
    end
    Else
        frmMain.txtBytesSent.Text := '';
    
end;
//--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
2
3
4
5
6
7
              HIDHandle := CreateFile(PChar(strDevicePath[frmMain.cmbDevices.ItemIndex]),
                                              GENERIC_WRITE,
                                              FILE_SHARE_READ Or FILE_SHARE_WRITE,
                                              nil,//Addr(Security),
                                              OPEN_EXISTING,
                                              0,
                                              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
2
3
4
5
6
7
function EnumCallback(EnumDevice: PXBCD_Device): Integer;
     // ...
     strUSBDevicePath[intUSBCount] := EnumDevice.USBPath;
     strDevicePath[intUSBCount] := EnumDevice.HIDPath;
     // ...
     Result := 0;
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
2
3
4
5
6
7
Type
  PXBCD_Device = ^TXBCD_Device;
  TXBCD_Device = packed record
    Index: Integer;
    HIDPath: PChar;
    USBPath: PChar;
  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« (11. April 2010, 18:33)


Leseratte

Registrierter Benutzer

  • »Leseratte« ist der Autor dieses Themas

Beiträge: 141

Dabei seit: 10. April 2010

Wohnort: Welt://Europa/Deutschland/NRW/Ich.Mensch

Hilfreich-Bewertungen: 4

  • Private Nachricht senden

5

Sonntag, 11. April 2010, 19:24

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

Visual Basic Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Public Class Form1
	'--WriteReport-------------------------------------
	Private Declare Function WriteFile Lib "kernel32" ( _
       	ByVal hFile As Long, ByVal lpBuffer As String, _
       	ByVal nNumberOfBytesToWrite As Long, _
       	ByVal lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long) As Long
	Private Function WriteReport()
    	Dim NumberOfBytesWritten As Integer
    	Dim SendBuffer(2) As Byte
    	'Send data to the device.

    	'******************************************************************************
    	'WriteFile
    	'Sends a report to the device.
    	'Returns: success or failure.
    	'Requires: the handle returned by CreateFile and
    	'The output report byte length returned by HidP_GetCaps
    	'******************************************************************************

    	'The first byte is the Report ID
    	SendBuffer(0) = 2

    	SendBuffer(1) = 255
    	SendBuffer(2) = 255

    	NumberOfBytesWritten = 0

    	WriteFile(HIDHandle, SendBuffer, Len(SendBuffer), NumberOfBytesWritten, 0)'In diesem Teil will VB HIDhandle deklariert haben
    	'--WriteReport-------------------------------------
	End Function
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« (11. April 2010, 20:05)


Mad Andy

Registrierter Benutzer

  • »Mad Andy« ist männlich

Beiträge: 4 451

Dabei seit: 2. August 2004

Wohnort: Österreich / Wien

Hilfreich-Bewertungen: 13

  • Private Nachricht senden

6

Montag, 12. April 2010, 01:57

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.

Leseratte

Registrierter Benutzer

  • »Leseratte« ist der Autor dieses Themas

Beiträge: 141

Dabei seit: 10. April 2010

Wohnort: Welt://Europa/Deutschland/NRW/Ich.Mensch

Hilfreich-Bewertungen: 4

  • Private Nachricht senden

7

Montag, 12. April 2010, 07:01

WriteFile/createFile ist ja schon deklariert, ich hoffe wir haben hier im Forum noch einen der das HID handle übersetzen könnte.

Mad Andy

Registrierter Benutzer

  • »Mad Andy« ist männlich

Beiträge: 4 451

Dabei seit: 2. August 2004

Wohnort: Österreich / Wien

Hilfreich-Bewertungen: 13

  • Private Nachricht senden

8

Dienstag, 13. April 2010, 09:06

Hier mal ein Sample, wie man das mit dem Callback macht:
http://stackoverflow.com/questions/55409…d-dll-in-vb-net

Zusätzlich brauchst du noch die Struct und der Rest ist nichts besonderes, wenn's wahr ist :D