[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[cdi-devel] [PATCH v2] CDI.usb, CDI.usb-hcd



From: Max Reitz <max@xxxxxxxxxx>

+ Added proposals for CDI.usb (USB drivers (bus drivers)) and
  CDI.usb-hcd (USB host controller drivers)

Signed-off-by: Max Reitz <max@xxxxxxxxxx>
---
 include/cdi/usb-hcd.h |   60 ++++++++++
 include/cdi/usb.h     |  311 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 371 insertions(+), 0 deletions(-)
 create mode 100644 include/cdi/usb-hcd.h
 create mode 100644 include/cdi/usb.h

diff --git a/include/cdi/usb-hcd.h b/include/cdi/usb-hcd.h
new file mode 100644
index 0000000..a5fcc51
--- /dev/null
+++ b/include/cdi/usb-hcd.h
@@ -0,0 +1,60 @@
+#ifndef _CDI_USB_HCD_H_
+#define _CDI_USB_HCD_H_
+
+#include "cdi/misc.h"
+#include "cdi/usb.h"
+
+struct cdi_usb_hc {
+    struct cdi_device dev;
+
+    ///USB-Geschwindigkeit
+    cdi_usb_speed_t speed;
+};
+
+struct cdi_usb_hcd {
+    struct cdi_driver drv;
+
+    /**
+     * Listet alle Geraete auf, die an den Rootports haengen und ruft ggf.
+     * cdi_usb_device_init auf
+     *
+     * @param device Der Hostcontroller
+     */
+    void (*find_devices)(struct cdi_usb_hc* device);
+
+    /**
+     * Aktiviert den zum angegebenen Geraet gehoerigen Rootport
+     *
+     * @param usb_device Das USB-Geraet (muss an einem Rootport haengen)
+     */
+    void (*activate_device)(struct cdi_usb_device* usb_device);
+
+    /**
+     * Verarbeitet USB-Pakete
+     *
+     * @param packets Array zu sendender Pakete
+     * @param num_packets Anzahl der Pakete
+     *
+     * @return Gibt den Status an (z. B. USB_NO_ERROR fuer keinen Fehler)
+     */
+    cdi_usb_status_t (*send_packets)(struct cdi_usb_packet* packets,
+        size_t num_packets);
+
+    /**
+     * Erstellt eine neue Pipe
+     *
+     * @param pipe Die Pipe
+     */
+    void (*add_pipe)(struct cdi_usb_pipe* pipe);
+};
+
+/// Initialisiert einen HCD
+void cdi_usb_hcd_init(struct cdi_usb_hcd* driver);
+
+/// Gibt einen HCD frei
+void cdi_usb_hcd_destroy(struct cdi_usb_hcd* driver);
+
+/// Registriert einen HCD
+void cdi_usb_hcd_register(struct cdi_usb_hcd* driver);
+
+#endif
diff --git a/include/cdi/usb.h b/include/cdi/usb.h
new file mode 100644
index 0000000..df695fa
--- /dev/null
+++ b/include/cdi/usb.h
@@ -0,0 +1,311 @@
+#ifndef _CDI_USB_H_
+#define _CDI_USB_H_
+
+#include "stddef.h"
+#include "stdint.h"
+
+typedef enum {
+    /// Low-Speed (1,5 Mbit/s)
+    CDI_USB_LOW_SPEED   = 0x01,
+    /// Full-Speed (12 Mbit/s)
+    CDI_USB_FULL_SPEED  = 0x02,
+    /// High-Speed (480 Mbit/s)
+    CDI_USB_HIGH_SPEED  = 0x04,
+    /// SuperSpeed (5 Gbit/s)
+    CDI_USB_SUPER_SPEED = 0x08,
+} cdi_usb_speed_t;
+
+typedef enum {
+    /// SETUP-Paket
+    CDI_USB_PACKET_SETUP = 0x2D,
+    /// Daten vom Geraet zum Host
+    CDI_USB_PACKET_IN    = 0x69,
+    /// Daten vom Host zum Geraet
+    CDI_USB_PACKET_OUT   = 0xE1,
+} cdi_usb_packet_type_t;
+
+typedef enum {
+    /// Kein Fehler
+    CDI_USB_NO_ERROR      = 0x0000,
+    /// Stalled
+    CDI_USB_STALLED       = 0x0001,
+    /// Bufferfehler (Overflow, underrun, ...)
+    CDI_USB_BUFFER_ERROR  = 0x0002,
+    /// Babble (Geraet hat zu viele Daten gesendet)
+    CDI_USB_BABBLE        = 0x0004,
+    /// NAK (Daten sind erneut zu senden)
+    CDI_USB_NAK           = 0x0008,
+    /// CRC-Fehler
+    CDI_USB_CRC           = 0x0010,
+    /// Timeout
+    CDI_USB_TIMEOUT       = 0x0020,
+    /// Bitstuff/-destuff-Fehler
+    CDI_USB_BITSTUFF      = 0x0040,
+    /// Reservieren von Speicher fehlgeschlagen, ...
+    CDI_USB_TRIVIAL_ERROR = 0x0080,
+} cdi_usb_status_t;
+
+struct cdi_usb_hc;
+struct cdi_usb_pipe;
+struct cdi_usb_interface;
+struct cdi_usb_driver;
+
+struct cdi_usb_device {
+    /// Der USB-Bustreiber
+    struct cdi_usb_driver* drv;
+    /// Der Hostcontroller, an dem das Geraet im Endeffekt haengt
+    struct cdi_usb_hc* hc;
+    /**
+     * Haengt das Geraet an einem Hub, dann ist dieses Feld ein Pointer auf
+     * das entsprechende USB-Geraet, haengt es an einem Rootport, dann ist
+     * dieses Feld NULL.
+     */
+    struct cdi_usb_device* hub;
+    /// Geschwindigkeit(-en) dieses Geraets
+    cdi_usb_speed_t speed;
+    /// ID
+    int id;
+    /// Entweder der Rootport oder der Port des Hubs, an dem das Geraet haengt
+    int port;
+    /// Hier darf der Geraetetreiber seine Daten unterbringen
+    void* driver_data;
+
+    /**
+     * Felder, die so auch bei PCI existieren: Vendor-, Device-, Class-,
+     * Subclass- und Protocol-ID
+     */
+    int vendor_id;
+    int device_id;
+    int class_id;
+    int subclass_id;
+    int protocol_id;
+
+    /**
+     * Setzt das USB-Geraet zurueck (kann sowohl vom HCD als auch vom Hub
+     * driver ausgefuehrt werden)
+     *
+     * @param usb_device Das Geraet
+     */
+    void (*reset)(struct cdi_usb_device* usb_device);
+
+    /// Ziemlich lowlevelig. Gehoert das hier wirklich rein?
+    /// Im einzelnen sind das: Pipe fuer Endpoint 0
+    struct cdi_usb_pipe* ep0;
+    /// Device descriptor
+    void* device_desc;
+    /// Configuration descriptor
+    void* config_desc;
+    /// Interface descriptor
+    struct cdi_usb_interface* interface_desc;
+    /// Class descriptor
+    void* class_desc;
+};
+
+enum cdi_usb_toggle {
+    /// Das Toggle nehmen, das jetzt dran ist
+    TOGGLE_UNSPECIFIC = 0,
+    /// Geloeschtes Togglebit erzwingen
+    TOGGLE_0 = 1,
+    /// Gesetztes Togglebit erzwingen
+    TOGGLE_1 = 2
+};
+
+struct cdi_usb_endpoint {
+    /// sizeof(struct cdi_usb_endpoint)
+    uint8_t length;
+    /// 5
+    uint8_t descriptor_type;
+    /// Nummer des Endpoints
+    uint8_t endpoint_address;
+    /// Eigenschaften (IN/OUT, Bulk/Interrupt/..., ...)
+    uint8_t attributes;
+    /// Maximale Paketgroesse in Bytes
+    uint16_t max_packet_size;
+    /// ???
+    uint8_t interval;
+} __attribute__((packed));
+
+struct cdi_usb_interface {
+    /// sizeof(struct cdi_usb_interface)
+    uint8_t length;
+    /// 4
+    uint8_t descriptor_type;
+    /// Nummer des Interfaces
+    uint8_t interface_number;
+    /// ???
+    uint8_t alternate_setting;
+    /// Anzahl der Endpoints fuer dieses Interface
+    uint8_t num_endpoints;
+    /// Class-ID (bei Composite Devices)
+    uint8_t interface_class;
+    /// Subclass-ID
+    uint8_t interface_subclass;
+    /// Protocol-ID
+    uint8_t interface_protocol;
+    /// String-Index, der das Interface beschreibt
+    uint8_t iInterface;
+} __attribute__((packed));
+
+/// Beschreibt eine Pipe
+struct cdi_usb_pipe {
+    /// Ziel
+    struct cdi_usb_device* device;
+    /// Ein Pointer auf eine den Endpoint beschreibende Struktur
+    /// TODO Das ist eigentlich auch sehr lowlevelig.
+    struct cdi_usb_endpoint* endpoint;
+    /// Data-Toggle
+    int data_toggle;
+};
+
+/** Beschreibt ein USB-Paket */
+struct cdi_usb_packet {
+    /// Die gewuenschte Pipe
+    struct cdi_usb_pipe* pipe;
+    /// Der Typ des Pakets (PACKET_IN, PACKET_OUT, PACKET_SETUP)
+    cdi_usb_packet_type_t type;
+    /// Zeiger auf den Datenpuffer
+    void* data;
+    /// Die Laenge des Puffers
+    size_t length;
+    /// Fehlertyp (oder USB_NO_ERROR)
+    cdi_usb_status_t condition;
+    /// Bestimmtes Data-Toggle benuten
+    enum cdi_usb_toggle use_toggle;
+};
+
+typedef enum {
+    /// Host -> Geraet
+    CDI_USB_CONTROL_OUT = 0x00,
+    /// Geraet -> Host
+    CDI_USB_CONTROL_IN = 0x80
+} cdi_usb_control_direction_t;
+
+typedef enum {
+    /// Standard-Request
+    CDI_USB_CONTROL_RQ_STANDARD = 0x00,
+    /// Klassenspezifischer Request
+    CDI_USB_CONTROL_RQ_CLASS = 0x20,
+    /// Herstellerspezifischer Request
+    CDI_USB_CONTROL_RQ_VENDOR = 0x40
+} cdi_usb_control_request_type_t;
+
+typedef enum {
+    /// Empfaenger: Geraet
+    CDI_USB_CONTROL_REC_DEVICE = 0x00,
+    /// Empfaenger: Interface
+    CDI_USB_CONTROL_REC_INTERFACE = 0x01,
+    /// Empfaenger: Endpoint
+    CDI_USB_CONTROL_REC_ENDPOINT = 0x02,
+    /// Empfaenger ist jemand anderes
+    CDI_USB_CONTROL_REC_OTHER = 0x03
+} cdi_usb_control_recipient_t;
+
+struct cdi_usb_control_transfer {
+    /// Wenn Daten zum Geraet gesendet werden sollen, dann ist hier der
+    /// Speicherbereich anzugeben
+    void *buffer;
+    /// Laenge der erwarteten bzw. zu sendenden Daten
+    size_t length;
+    /// Richtung
+    cdi_usb_control_direction_t direction;
+    /// Art des Requests (Standardrequest, klassenspezifisch,
+    /// herstellerspezifisch)
+    cdi_usb_control_request_type_t rtype;
+    /// Ziel (Device, Interface, Endpoint, anderes)
+    cdi_usb_control_recipient_t recipient;
+    /// Requestcode (Je nach rtype und recipient)
+    int request;
+    /// Ein zu sendender Wert
+    int value;
+    /// Ein zu sendender Index
+    int index;
+};
+
+#include "cdi/usb-hcd.h"
+
+struct cdi_usb_driver {
+    struct cdi_driver drv;
+
+    /// Unterstuetzte Geschwindigkeiten
+    cdi_usb_speed_t speeds;
+
+    /**
+     * Enumeriert ein USB-Geraet
+     *
+     * @param device Das zu enumerierende Geraet
+     */
+    void (*enumerate_device)(struct cdi_usb_device* device);
+
+    /**
+     * Sendet USB-Pakete
+     *
+     * @param packets Array zu sendender Pakete
+     * @param num_packets Anzahl der Pakete
+     *
+     * @return Gibt den Status an (z. B. USB_NO_ERROR fuer keinen Fehler)
+     */
+    cdi_usb_status_t (*send_packets)(struct cdi_usb_packet* packets,
+        size_t num_packets);
+
+    /**
+     * Fuehrt einen Control-Transfer durch
+     *
+     * @param device Das Zielgeraet
+     * @param transfer Eine den Transfer beschreibende Struktur
+     *
+     * @return Gibt einen Puffer zurueck, der die ausgetauschen Daten enthaelt,
+     *         im Fehlerfall hingegen NULL, gab es keine Daten, dann
+     *         (void *)0xFFFFFFFF.
+     */
+    void* (*do_control)(struct cdi_usb_device* device,
+        struct cdi_usb_control_transfer* transfer);
+};
+
+/**
+ * Ein USB-Geraetetreiber uebergibt dem Betriebssystem eine solche Struktur,
+ * damit ein bestimmter Handler beim Auffinden solcher Geraete aufgerufen wird.
+ * Jedes Feld enthaelt entweder eine Zahl, die mit der des Geraetes
+ * uebereinstimmen muss oder -1, dann wird dieses Feld ignoriert.
+ */
+struct cdi_usb_device_pattern {
+    int vendor_id;
+    int device_id;
+    int class_id;
+    int subclass_id;
+    int protocol_id;
+
+    /**
+     * Ueberprueft das angegebene USB-Geraet
+     *
+     * @param device Das Geraet
+     *
+     * @return 0, wenn dieses Geraet nicht vom Treiber verarbeitet werden kann,
+     *         sonst 1
+     */
+    int (*take_usb_device)(struct cdi_usb_device* device);
+};
+
+void cdi_usb_driver_destroy(struct cdi_usb_driver* driver);
+
+/**
+ * Initialisiert und registriert einen USB-Bustreiber beim System
+ *
+ * @param driver Der Treiber
+ */
+void cdi_usb_driver_init_and_register(struct cdi_usb_driver* driver);
+
+/**
+ * Registriert ein gefundenes USB-Geraet beim Betriebssystem
+ *
+ * @param device Das zu registrierende Geraet
+ */
+void cdi_usb_device_init(struct cdi_usb_device* device);
+
+/**
+ * Registriert ein Geraetemuster
+ *
+ * @param pattern Das Muster
+ */
+void cdi_usb_register_device_pattern(struct cdi_usb_device_pattern* pattern);
+
+#endif
-- 
1.6.4.2