|
Antwort |
Registriert seit: 30. Dez 2002 Ort: Brandshagen 1.819 Beiträge Delphi 2007 Professional |
#1
Hi Leute!
Da ich nicht weis ob sowas überhaupt möglich ist möchte ich hier das Problem mal vorstellen. Kurz zur Erläuterung. Ich möchte einen Descriptor für ein USBDevice auslesen. Diesen bekomme ich als Zeiger auf ein ByteArray geliefert (mittels DLL Funktion) hier mal die Funktion:
Code:
Die Deskriptoren werden im Controller (PIC) wie folgt abgelegt:
DWORD (*MPUSBGetDeviceDescriptor)(HANDLE handle, // Input
PVOID pDevDsc, // Output DWORD dwLen, // Input PDWORD pLength); // Output DWORD (*MPUSBGetConfigurationDescriptor)(HANDLE handle, // Input UCHAR bIndex, // Input PVOID pDevDsc, // Output DWORD dwLen, // Input PDWORD pLength); // Output
Code:
Die ganze Sache ist so organisiert, dass jeder Configuration-Deskriptor mehrere Interface-Deskriptoren und jeder Interface-Deskribtor mehrere Endpoint-Deskriptoren haben kann. Dies ist in der Struktur wie folgt definiert:
/* Device Descriptor */
ROM USB_DEVICE_DESCRIPTOR device_dsc= { 0x12, // Size of this descriptor in bytes USB_DESCRIPTOR_DEVICE, // DEVICE descriptor type 0x0200, // USB Spec Release Number in BCD format 0x00, // Class Code 0x00, // Subclass code 0x00, // Protocol code USB_EP0_BUFF_SIZE, // Max packet size for EP0, see usb_config.h 0x04D8, // Vendor ID: 0x04D8 is Microchip's Vendor ID 0x000c, // Product ID: 0x0053 0x0000, // Device release number in BCD format 0x01, // Manufacturer string index 0x02, // Product string index 0x00, // Device serial number string index 0x01 // Number of possible configurations }; /* Configuration 1 Descriptor */ ROM BYTE configDescriptor1[]={ /* Configuration Descriptor */ 0x09,//sizeof(USB_CFG_DSC), // Size of this descriptor in bytes USB_DESCRIPTOR_CONFIGURATION, // CONFIGURATION descriptor type 0xD6,0x00, // Total length of data for this cfg changed on 14.12.2009 oki old Value 0x20, 0x00 1, // Number of interfaces in this cfg 1, // Index value of this configuration 0, // Configuration string index _DEFAULT | _SELF, // Attributes, see usb_device.h 50, // Max power consumption (2X mA) /* Interface Descriptor */ 0x09,//sizeof(USB_INTF_DSC), // Size of this descriptor in bytes USB_DESCRIPTOR_INTERFACE, // INTERFACE descriptor type 0, // Interface Number 0, // Alternate Setting Number 28, // Number of endpoints in this intf (alle IN und OUT ohne Endpoint 0) 0xFF, // Class code 0xFF, // Subclass code 0xFF, // Protocol code 0, // Interface string index /* Endpoint Descriptor */ 0x07, /*sizeof(USB_EP_DSC)*/ USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor _EP01_OUT, //EndpointAddress _BULK, //Attributes USBGEN_EP_SIZE,0x00, //size 4, //Interval 0x07, /*sizeof(USB_EP_DSC)*/ USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor _EP01_IN, //EndpointAddress _BULK, //Attributes USBGEN_EP_SIZE,0x00, //size 4, //Interval // Aditional Endpoints appanded on 14.12.2009 oki 0x07, //sizeof(USB_EP_DSC) USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor _EP02_OUT, //EndpointAddress _BULK, //Attributes USBGEN_EP_SIZE,0x00, //size 4, //Interval 0x07, //sizeof(USB_EP_DSC) USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor _EP02_IN, //EndpointAddress _BULK, //Attributes USBGEN_EP_SIZE,0x00, //size 4, //Interval ....
Code:
Blöd, ich wollte es so schön farbig machen, aber da stehen nur die Tags. Es geht um diese beiden Einträge:
/* Configuration Descriptor */
0x09,//sizeof(USB_CFG_DSC), // Size of this descriptor in bytes USB_DESCRIPTOR_CONFIGURATION, // CONFIGURATION descriptor type 0xD6,0x00, // Total length of data for this cfg changed on 14.12.2009 oki old Value 0x20, 0x00 [color=#ff003f]1, // Number of interfaces in this cfg[/color] 1, // Index value of this configuration 0, // Configuration string index _DEFAULT | _SELF, // Attributes, see usb_device.h 50, // Max power consumption (2X mA) /* Interface Descriptor */ 0x09,//sizeof(USB_INTF_DSC), // Size of this descriptor in bytes USB_DESCRIPTOR_INTERFACE, // INTERFACE descriptor type 0, // Interface Number 0, // Alternate Setting Number [color=#ff003f]28, // Number of endpoints in this intf (alle IN und OUT ohne Endpoint 0)[/color] 0xFF, // Class code 0xFF, // Subclass code 0xFF, // Protocol code 0, // Interface string index
Code:
Dort ist jeweils angegeben, wie viele Interfaces und jeweils wie viele Endpoints kommen.
1, // Number of interfaces in this cfg
... 28, // Number of endpoints in this intf (alle IN und OUT ohne Endpoint 0) Nun dachte ich mir, nichts leichter als dass, legst du dir die passenden Records an. Gedacht, getan:
Delphi-Quellcode:
Tja, böse Falle. Ihr seht schon meine auskommentierten Zeilen in den Records. Mir war dann eigentlich gleich klar, dass das so nicht geht, hab es aber mal da auskommentiert gelassen, damit ihr seht, wo mein Problem steckt.
TEndPointDescriptor = packed record
Length : Byte; // sollte 0x07 sein EndpointDescriptor : Byte; // Endpoint Deskriptor (Typangabe) EndpointAddress : Byte; // Endpoint Address (IN0-IN15 0x80 - 0x8F; OUT0-OUT15 0x00 - 0x0F) Attributes : TControlTransfer; // _BULK, _INT, _ISO, and _CTRL BufferSize : Word; // 8, 16, 32 Byte; as Byte Array "64,0" Intervall : Byte; // Polling Intervall end; TInterfaceDescriptor = packed record Length : Byte; // sollte 0x09 sein InterfaceDescriptor : Byte; // Interface Deskriptor (Typangabe) InterfaceNumber : Byte; // Interface Nummer AlternateSettingNumber : Byte; // Alternate Setting Number EndpointCount : Byte; // Number of Endpoints (exclude Endpoint 0) ClassCode : Byte; SubClassCode : Byte; ProtokollCode : Byte; InterfaceStringIndex: Byte; // EndPoints : Array[EndpointCount] of TEndPointDescriptor; end; TConfigurationDescriptor = packed record Lengt : Byte; // sollte 0x09 sein ConfigurationDescriptor : Byte; // Typangabe TotalLength : Word; // Gesamtlänge des Descriptors as Byte Array "xx,0" InterfaceCount : Byte; ConfigurationIndex : Byte; // Index of this Configuration ConfigurationStringIndex : Byte;// Configuration string index Attributes : Byte; // _DEFAULT, _SELF ... PowerConsumtion : Byte; // Max power consumption (2X mA) // IterfaceDescriptors : Array[InterfaceCount] of TInterfaceDescriptor; end; Hat jemand eine Idee wie ich das hinbekommen kann? Mein Ziel war es eigentlich einen Zeiger auf eine Recordvariable vom Typ TConfigurationDescriptor zu übergeben und dann schön sauber alles parat zu haben. Natürlich kann ich die auskommentierten Zeilen auch als dynamische Arrays anlegen und mittels Funktion das ByteArray scheibchenweise in die Records gießen und zur Laufzeit die Längen der Arrays setzen. Aber vielleicht gibt es ja auch eine richtig trickreiche Idee die mir nicht einfällt? Ich dank euch schon mal für die Mühe, Gruß oki [edit] Uppps, noch schnell hinten dran, aktuelle Projekt in Delphi 2010! [/edit]
42
|
Zitat |
Registriert seit: 7. Aug 2008 Ort: Brandenburg 1.477 Beiträge Delphi 12 Athens |
#2
Delphi-Quellcode:
type
PEndPointDescriptor = ^TEndPointDescriptor; TEndPointDescriptor = packed record Length : Byte; // sollte 0x07 sein EndpointDescriptor : Byte; // Endpoint Deskriptor (Typangabe) EndpointAddress : Byte; // Endpoint Address (IN0-IN15 0x80 - 0x8F; OUT0-OUT15 0x00 - 0x0F) Attributes : TControlTransfer; // _BULK, _INT, _ISO, and _CTRL BufferSize : Word; // 8, 16, 32 Byte; as Byte Array "64,0" Intervall : Byte; // Polling Intervall end; PInterfaceDescriptor = ^TInterfaceDescriptor; TInterfaceDescriptor = packed record Length : Byte; // sollte 0x09 sein InterfaceDescriptor : Byte; // Interface Deskriptor (Typangabe) InterfaceNumber : Byte; // Interface Nummer AlternateSettingNumber : Byte; // Alternate Setting Number EndpointCount : Byte; // Number of Endpoints (exclude Endpoint 0) ClassCode : Byte; SubClassCode : Byte; ProtokollCode : Byte; InterfaceStringIndex: Byte; private function GetItem(AIndex: Integer): PEndPointDescriptor; function GetEndPoint(AIndex: Integer): PEndPointDescriptor; public function GetSize: Integer; property EndPoints[AIndex: Integer]: PEndPointDescriptor read GetEndPoint; end; PConfigurationDescriptor = ^TConfigurationDescriptor; TConfigurationDescriptor = packed record Length : Byte; // sollte 0x09 sein ConfigurationDescriptor : Byte; // Typangabe TotalLength : Word; // Gesamtlänge des Descriptors as Byte Array "xx,0" InterfaceCount : Byte; ConfigurationIndex : Byte; // Index of this Configuration ConfigurationStringIndex : Byte;// Configuration string index Attributes : Byte; // _DEFAULT, _SELF ... PowerConsumtion : Byte; // Max power consumption (2X mA) private function GetItem(AIndex: Integer): PInterfaceDescriptor; function GetIterfaceDescriptor(AIndex: Integer): PInterfaceDescriptor; public function GetSize: Integer; property IterfaceDescriptors[AIndex: Integer]: PInterfaceDescriptor read GetIterfaceDescriptor; end; implementation { TConfigurationDescriptor } function TConfigurationDescriptor.GetItem(AIndex: Integer): PInterfaceDescriptor; var i: Integer; begin Result := @Self; Inc(LongWord(Result), Self.Length); for i := 0 to AIndex - 1 do Inc(LongWord(Result), Result^.GetSize); end; function TConfigurationDescriptor.GetIterfaceDescriptor( AIndex: Integer): PInterfaceDescriptor; begin if (AIndex >= 0) and (AIndex < InterfaceCount) then Result := GetItem(AIndex) else Result := nil; // oder Exception auslösen end; function TConfigurationDescriptor.GetSize: Integer; begin Result := LongWord(GetItem(InterfaceCount)) - LongWord(@Self); end; { TInterfaceDescriptor } function TInterfaceDescriptor.GetEndPoint(AIndex: Integer): PEndPointDescriptor; begin if (AIndex >= 0) and (AIndex < EndpointCount) then Result := GetItem(AIndex) else Result := nil; // oder Exception auslösen end; function TInterfaceDescriptor.GetItem(AIndex: Integer): PEndPointDescriptor; var i: Integer; begin Result := @Self; Inc(LongWord(Result), Self.Length); for i := 0 to AIndex - 1 do Inc(LongWord(Result), Result^.Length); end; function TInterfaceDescriptor.GetSize: Integer; begin Result := LongWord(GetItem(EndpointCount)) - LongWord(@Self); end; |
Zitat |
Registriert seit: 11. Okt 2003 Ort: Elbflorenz 44.184 Beiträge Delphi 12 Athens |
#3
EndPoints : Array[0..0] of TEndPointDescriptor;
ergibt ein statisches Array mit einem Fehld, aber ohne Bereichsprüfung.
Nun kann man also mit GetMem den Speicher für seinen Record reservieren und muß nur aufpassen, daß man genügend Speicher für sein Array reserviert.
$2B or not $2B
|
Zitat |
Registriert seit: 22. Okt 2006 772 Beiträge |
#4
Hallo,
ich würde eine Klasse konstruieren mit einem variablen array of byte für den record. Zuerst die ersten paar Bytes lesen und die Länge entnehmen, dann Array-Länge setzen und den ganzen Record lesen. Zum Zugriff arbeitet man am besten mit Pointern wie in C und schreibt eine Methode für jeden Typ Descriptor, die sich an den gegebenen Pointern entlanghangelt und einen Pointer auf den gewünschten Descriptor zurückliefert. Das funktioniert auch im allgemeinsten Fall: in TTF-Dateien z.B. können Details wie Namen oder Glyphen im Prinzip irgendwo stehen - es gibt nur eine Headertabelle mit Pointern dahin, und dort stehen dann oft Sub-Tabellen mit Pointern. Wenn man es braucht, kann man auch die ganzen Daten in eine Baumstruktur einlesen, aber das lohnt sich nicht, wenn man nur ein bestimmtes Detail braucht. Gruss Reinhard |
Zitat |
Registriert seit: 30. Dez 2002 Ort: Brandshagen 1.819 Beiträge Delphi 2007 Professional |
#5
Hallo,
erst mal herzlichen Dank für eure Antworten. Mir gefällt Blups Code-Beispiel eigentlich am Besten. Es macht auch einen eleganten Eindruck. Ich denke so werde ich es testen. @Himitsu: Auch wenn ich Blup's Variante nehmen werde habe ich mit deinem Hinweis zum Array mit den Grenzen [0..0] wieder was neues gelernt. Dank dafür. @Reinhard: Ja, so hätte ich es gemacht, wenn keiner geantwortet hätte. Ich denke Blup's Beispiel realisiert diese Idee elegant mit den neuen Mitteln der Records. Ich hatte schon so was geaht und deshalb auch extra vermerkt, dass ich das Problem unter D2010 löse. Nochmals herzlich Dank an alle, Gruß oki
42
|
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |