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

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



From: Max Reitz <max@xxxxxxxxxx>

This version is slightly changed to fulfill the suggestions Kevin
made.

Signed-off-by: Max Reitz <max@xxxxxxxxxx>
---
 include/cdi-osdep.h       |    9 +
 include/cdi.h             |    2 +-
 include/cdi/usb-bus.h     |   98 ++++++
 include/cdi/usb-hc.h      |  268 +++++++++++++++++
 include/cdi/usb-structs.h |  159 ++++++++++
 include/cdi/usb.h         |  713 +++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 1248 insertions(+), 1 deletions(-)
 create mode 100644 include/cdi/usb-bus.h
 create mode 100644 include/cdi/usb-hc.h
 create mode 100644 include/cdi/usb-structs.h
 create mode 100644 include/cdi/usb.h

diff --git a/include/cdi-osdep.h b/include/cdi-osdep.h
index 279001a..c1778fd 100644
--- a/include/cdi-osdep.h
+++ b/include/cdi-osdep.h
@@ -67,4 +67,13 @@ typedef struct
 typedef struct {
 } cdi_mem_osdep;
 
+/**
+ * \if german
+ * Dient zur eindeutigen Identifizierung eines USB-Hostcontrollers.
+ * \elseif english
+ * Used for uniquely identifying a USB host controller.
+ * \endif
+ */
+typedef void* cdi_usb_hc_t;
+
 #endif
diff --git a/include/cdi.h b/include/cdi.h
index 851bb6a..9e15b8c 100644
--- a/include/cdi.h
+++ b/include/cdi.h
@@ -292,7 +292,7 @@ void cdi_driver_register(struct cdi_driver* driver);
 
 /**
  * \german
- * Informiert dass Betriebssystem, dass ein neues Geraet angeschlossen wurde.
+ * Informiert das Betriebssystem, dass ein neues Geraet angeschlossen wurde.
  *
  * Der Zweck dieser Funktion ist es, Bustreibern zu ermöglichen, die Geräte
  * auf ihrem Bus anderen Treibern zur Verfügung zu stellen, die über den
diff --git a/include/cdi/usb-bus.h b/include/cdi/usb-bus.h
new file mode 100644
index 0000000..b01cd35
--- /dev/null
+++ b/include/cdi/usb-bus.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2010 Max Reitz
+ *
+ * This program is free software. It comes without any warranty, to
+ * the extent permitted by applicable law. You can redistribute it
+ * and/or modify it under the terms of the Do What The Fuck You Want
+ * To Public License, Version 2, as published by Sam Hocevar. See
+ * http://sam.zoy.org/projects/COPYING.WTFPL for more details.
+ */
+
+/**
+ * \if german
+ * Definitionen für USB-Bustreiber.
+ * \elseif english
+ * Definitions for USB bus drivers.
+ * \endif
+ */
+/*\@{*/
+
+#ifndef _CDI_USB_BUS_H_
+#define _CDI_USB_BUS_H_
+
+#include <cdi.h>
+#include <cdi/usb.h>
+#include <cdi/usb-hc.h>
+
+struct cdi_usb_bus_driver {
+    struct cdi_driver drv;
+    /**
+     * \if german
+     *
+     * Wird aufgerufen, wenn ein neuer Hostcontroller gefunden wurde.
+     *
+     * @param hc Gefundener Hostcontroller
+     *
+     * \elseif english
+     *
+     * Is called when a new host controller has been found.
+     *
+     * @param hc Found host controller
+     *
+     * \endif
+     */
+    void (*found_hc)(cdi_usb_hc_t hc);
+    /**
+     * \if german
+     * s. cdi_usb_connect()
+     * \elseif english
+     * see cdi_usb_connect()
+     * \endif
+     */
+    cdi_usb_pipe_t (*create_pipe)(cdi_usb_endpoint_t endpoint);
+    /**
+     * \if german
+     * s. cdi_usb_disconnect()
+     * \elseif english
+     * see cdi_usb_disconnect()
+     * \endif
+     */
+    void (*destroy_pipe)(cdi_usb_pipe_t pipe);
+    /**
+     * \if german
+     * s. cdi_usb_initiate_transaction()
+     * \elseif english
+     * see cdi_usb_initiate_transaction()
+     * \endif
+     */
+    int (*initiate_transaction)(struct cdi_usb_transaction* transaction);
+    /**
+     * \if german
+     * s. cdi_get_usb_endpoint()
+     * \elseif english
+     * see cdi_get_usb_endpoint()
+     * \endif
+     */
+    int (*get_endpoint)(struct cdi_usb_endpoint* endpoint, cdi_usb_endpoint_t id);
+    /**
+     * \if german
+     * s. cdi_get_usb_interface()
+     * \elseif english
+     * see cdi_get_usb_interface()
+     * \endif
+     */
+    int (*get_interface)(struct cdi_usb_interface* interface);
+    /**
+     * \if german
+     * s. cdi_usb_get_pipe_information()
+     * \elseif english
+     * see cdi_usb_get_pipe_information()
+     * \endif
+     */
+    int (*get_pipe_info)(cdi_usb_pipe_t pipe, int* device_addr,
+        struct cdi_usb_endpoint* endpoint);
+};
+
+#endif
+/*\@}*/
+
diff --git a/include/cdi/usb-hc.h b/include/cdi/usb-hc.h
new file mode 100644
index 0000000..fcb0658
--- /dev/null
+++ b/include/cdi/usb-hc.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2010 Max Reitz
+ *
+ * This program is free software. It comes without any warranty, to
+ * the extent permitted by applicable law. You can redistribute it
+ * and/or modify it under the terms of the Do What The Fuck You Want
+ * To Public License, Version 2, as published by Sam Hocevar. See
+ * http://sam.zoy.org/projects/COPYING.WTFPL for more details.
+ */
+
+/**
+ * \if german
+ * USB-Hostcontroller-Definitionen
+ * \elseif english
+ * USB host controller definitions
+ * \endif
+ */
+/*\@{*/
+
+#ifndef _CDI_USB_HC_H_
+#define _CDI_USB_HC_H_
+
+#include <cdi.h>
+#include <cdi-osdep.h>
+#include <cdi/usb.h>
+
+struct cdi_usb_hc {
+    struct cdi_device dev;
+    /**
+     * \if german
+     * Anzahl der Rootports.
+     * \elseif english
+     * Root port count.
+     * \endif
+     */
+    int ports;
+};
+
+struct cdi_usb_hcd {
+    struct cdi_driver drv;
+    /**
+     * \if german
+     * Geschwindigkeit(en), die dieser Hostcontrollertreiber unterstützt.
+     * \elseif english
+     * Speed(s) supported by this host controller driver.
+     * \endif
+     */
+    cdi_usb_speed_t speed;
+    /**
+     * \if german
+     * Ist dieses Flag gesetzt, so muss die entsprechende Funktion für jeden
+     * registrierten Hostcontroller mit diesem Treiber ständig aufgerufen
+     * werden, damit z. B. der Status von angeschlossenen und nicht
+     * angeschlossenen Geräte aktualisiert werden kann.
+     * \elseif english
+     * If this flag is set, the according function has to be called for every
+     * registered host controller with this driver periodically, thus the driver
+     * can refresh the status of connected and disconnected devices, for
+     * example.
+     * \endif
+     */
+    int needs_periodic_call;
+    /**
+     * \if german
+     *
+     * Callback, das vom OS ständig aufgerufen werden muss, wenn das gerade
+     * beschriebene Flag gesetzt ist.
+     *
+     * @param hc Hostcontroller (Funktion muss mit allen Hostcontrollern
+     *           nacheinander aufgerufen werden)
+     *
+     * \elseif english
+     *
+     * Callback which is periodically called by the OS if the flag just
+     * described is set.
+     *
+     * @param hc Host controller (function has to be called with all host
+     *           controllers consecutively)
+     *
+     * \endif
+     */
+    void (*periodic_callback)(struct cdi_usb_hc* hc);
+    /**
+     * \if german
+     *
+     * Untersucht einen Rootport auf ein angeschlossenes Gerät.
+     *
+     * @param hc Hostcontroller
+     * @param dev Die Funktion muss diese Struktur mit Informationen füllen,
+     *            wenn ein Gerät angeschlossen ist (nur speed-Feld).
+     * @param port Index des Ports (von 0 beginnend)
+     *
+     * @return 0, wenn ein Gerät angeschlossen ist, sonst -1.
+     *
+     * \elseif english
+     *
+     * Determines if a device is plugged into a root port.
+     *
+     * @param Host controller
+     * @param dev The function has to store information about the device (if
+     *            available) here (speed field has to be set).
+     * @param port Port's index (starting from 0)
+     *
+     * @return 0 if there's a device, -1 else.
+     *
+     * \endif
+     */
+    int (*scan_port)(struct cdi_usb_hc* hc, struct cdi_usb_device* dev,
+        int port);
+    /**
+     * \if german
+     *
+     * Aktiviert einen Rootport (treibt also ggf. Resume) und treibt
+     * anschlieÃ?end 50 ms lang ein Resetsignal.
+     *
+     * @param hc Hostcontroller
+     * @param port Der zu aktivierende Port.
+     *
+     * \elseif english
+     *
+     * Activates a root port (drives resume if necessary) and drives a 50 ms
+     * reset signal afterwards.
+     *
+     * @param hc Host controller
+     * @param port Port to be activated.
+     *
+     * \endif
+     */
+    void (*reset_and_enable)(struct cdi_usb_hc* hc, int port);
+    /**
+     * \if german
+     *
+     * Deaktiviert einen Rootport.
+     *
+     * @param hc Hostcontroller
+     * @param port Zu deaktivierender Port
+     *
+     * \elseif english
+     *
+     * Disables a root port.
+     *
+     * @param hc Host controller
+     * @param port Port to be disabled
+     *
+     * \endif
+     */
+    void (*disable)(struct cdi_usb_hc* hc, int port);
+    /**
+     * \if german
+     *
+     * Erstellt eine Pipe zum angegebenen Endpunkt.
+     *
+     * @param hc Hostcontroller
+     * @param device_addr USB-Adresse des Zielgeräts
+     * @param endpoint Informationen zum Endpunkt
+     *
+     * \elseif english
+     *
+     * Creates a pipe to the given endpoint.
+     *
+     * @param hc Host controller
+     * @param device_addr Target device's USB address
+     * @param endpoint Information about the endpoint
+     *
+     * \endif
+     */
+    void (*create_pipe)(struct cdi_usb_hc* hc, int device_addr,
+        struct cdi_usb_endpoint* endpoint);
+    /**
+     * \if german
+     *
+     * Entfernt alle Pipes zum angegebenen Endpunkt (und mit ihnen alle
+     * entsprechenden Ã?bertragungen).
+     *
+     * @param hc Hostcontroller
+     * @param device_addr USB-Adresse des Zielgeräts
+     * @param endpoint Informationen zum Endpunkt
+     *
+     * \elseif english
+     *
+     * Removes all pipes to the given endpoint (and all according transactions,
+     * too).
+     *
+     * @param hc Host controller
+     * @param device_addr Target device's USB address
+     * @param endpoint Information about the endpoint
+     *
+     * \endif
+     */
+    void (*destroy_pipe)(struct cdi_usb_hc* hc, int device_addr,
+        struct cdi_usb_endpoint* endpoint);
+    /**
+     * \if german
+     *
+     * Leitet eine USB-Transaktion ein.
+     *
+     * @param hc Hostcontroller
+     * @param transaction Beschreibung der Ã?bertragung
+     *
+     * \elseif english
+     *
+     * Initiates a USB transaction.
+     *
+     * @param hc Host controller
+     * @param transaction Transaction's description
+     *
+     * \endif
+     */
+    void (*initiate_transaction)(struct cdi_usb_hc* hc,
+        struct cdi_usb_transaction* transaction);
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \if german
+ *
+ * Am angegebenen Rootport trat ein CSC (connect status change) auf, es wurde
+ * also ein Gerät angesteckt oder entfernt. Diese Funktion wird vom HCD
+ * aufgerufen, um dem OS diese Veränderung mitzuteilen, damit es alle
+ * Informationen zu diesem Port aktualisieren kann.
+ *
+ * @param hc Hostcontroller
+ * @param port Rootport, an dem der CSC aufgetreten ist
+ *
+ * \elseif english
+ *
+ * A CSC (connect status change) occured at the given root port, i.e., a device
+ * has been removed or plugged in. This function is called by the HCD to tell
+ * the OS about that change, thus it can refresh all information about this
+ * port.
+ *
+ * @param hc Host controller
+ * @param port Root port where the CSC occured
+ *
+ * \endif
+ */
+void cdi_usb_csc(struct cdi_usb_hc* hc, int port);
+
+/**
+ * \if german
+ * Die folgendenen Funktionen verhalten sich genau so wie die dazugehörigen
+ * Funktion in struct cdi_usb_hcd.
+ * \elseif english
+ * The following functions behave exactly like the according functions in
+ * struct cdi_usb_hcd.
+ * \endif
+ */
+
+int cdi_usb_hc_scan_port(cdi_usb_hc_t hc, struct cdi_usb_device* dev, int port);
+void cdi_usb_hc_reset_and_enable(cdi_usb_hc_t hc, int port);
+void cdi_usb_hc_disable(cdi_usb_hc_t hc, int port);
+void cdi_usb_hc_create_pipe(cdi_usb_hc_t hc, int device_addr,
+    struct cdi_usb_endpoint* endpoint);
+void cdi_usb_hc_destroy_pipe(cdi_usb_hc_t hc, int device_addr,
+    struct cdi_usb_endpoint* endpoint);
+void cdi_usb_hc_initiate_transaction(cdi_usb_hc_t hc,
+    struct cdi_usb_transaction* transaction);
+
+#ifdef __cplusplus
+}; // extern "C"
+#endif
+
+#endif
+/*\@}*/
+
diff --git a/include/cdi/usb-structs.h b/include/cdi/usb-structs.h
new file mode 100644
index 0000000..316165e
--- /dev/null
+++ b/include/cdi/usb-structs.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2010 Max Reitz
+ *
+ * This program is free software. It comes without any warranty, to
+ * the extent permitted by applicable law. You can redistribute it
+ * and/or modify it under the terms of the Do What The Fuck You Want
+ * To Public License, Version 2, as published by Sam Hocevar. See
+ * http://sam.zoy.org/projects/COPYING.WTFPL for more details.
+ */
+
+/**
+ * \if german
+ * Allgemeine USB-Strukturen
+ * \elseif english
+ * General USB structures
+ * \endif
+ */
+/*\@{*/
+
+#ifndef _CDI_USB_STRUCTS_H_
+#define _CDI_USB_STRUCTS_H_
+
+#include <stdint.h>
+
+#define CDI_USB_SETUP_OUT     (0 << 7)
+#define CDI_USB_SETUP_IN      (1 << 7)
+#define CDI_USB_SETUP_REQ_STD (0 << 5)
+#define CDI_USB_SETUP_REQ_CLS (1 << 5)
+#define CDI_USB_SETUP_REQ_VDR (2 << 5)
+#define CDI_USB_SETUP_REC_DEV 0
+#define CDI_USB_SETUP_REC_IF  1
+#define CDI_USB_SETUP_REC_EP  2
+#define CDI_USB_SETUP_REC_OTH 3
+
+enum cdi_usb_setup_requst {
+    CDI_USB_GET_STATUS = 0,
+    CDI_USB_CLEAR_FEATURE = 1,
+    CDI_USB_SET_FEATURE = 3,
+    CDI_USB_SET_ADDRESS = 5,
+    CDI_USB_GET_DESCRIPTOR = 6,
+    CDI_USB_SET_DESCRIPTOR = 7,
+    CDI_USB_GET_CONFIGURATION = 8,
+    CDI_USB_SET_CONFIGURATION = 9,
+    CDI_USB_GET_INTERFACE = 10,
+    CDI_USB_SET_INTERFACE = 11,
+    CDI_USB_SYNC_FRAME = 12
+};
+
+enum cdi_usb_setup_descriptor {
+    CDI_USB_DESC_DEVICE = 1 << 8,
+    CDI_USB_DESC_CONFIGURATION = 2 << 8,
+    CDI_USB_DESC_STRING = 3 << 8,
+    CDI_USB_DESC_INTERFACE = 4 << 8,
+    CDI_USB_DESC_ENDPOINT = 5 << 8,
+    CDI_USB_DESC_DEVICE_QUALIFIER = 6 << 8,
+    CDI_USB_DESC_OTHER_SPEED_CONFIGURATION = 7 << 8,
+    CDI_USB_DESC_INTERFACE_POWER = 8 << 8,
+
+    CDI_USB_DESC_HUB = 41 << 8
+};
+
+struct cdi_usb_setup_packet {
+    uint8_t type;
+    uint8_t request;
+    uint16_t value;
+    uint16_t index;
+    uint16_t length;
+} __attribute__((packed));
+
+struct cdi_usb_descriptor {
+    uint8_t length;
+    uint8_t desc_type;
+} __attribute__((packed));
+
+struct cdi_usb_device_descriptor {
+    struct cdi_usb_descriptor desc;
+    uint16_t bcd_usb;
+    uint8_t class, subclass, protocol;
+    uint8_t mps0;
+    uint16_t vendor_id, device_id;
+    uint16_t bcd_device;
+    uint8_t i_manufacturer, i_product, i_serial;
+    uint8_t num_configurations;
+} __attribute__((packed));
+
+struct cdi_usb_config_descriptor {
+    struct cdi_usb_descriptor desc;
+    uint16_t total_length;
+    uint8_t num_interfaces;
+    uint8_t configuration_value;
+    uint8_t i_configuration;
+    unsigned rsvd0         : 5;
+    unsigned remote_wakeup : 1;
+    unsigned self_powered  : 1;
+    unsigned rsvd1         : 1;
+    uint8_t max_power;
+} __attribute__((packed));
+
+struct cdi_usb_interface_descriptor {
+    struct cdi_usb_descriptor desc;
+    uint8_t interface_number;
+    uint8_t alternate_setting;
+    uint8_t num_endpoints;
+    uint8_t class, subclass, protocol;
+    uint8_t i_interface;
+} __attribute__((packed));
+
+#define CDI_USB_EP_CONTROL     0
+#define CDI_USB_EP_ISOCHRONOUS 1
+#define CDI_USB_EP_BULK        2
+#define CDI_USB_EP_INTERRUPT   3
+
+struct cdi_usb_endpoint_descriptor {
+    struct cdi_usb_descriptor desc;
+    unsigned number    : 4;
+    unsigned rsvd1     : 3;
+    unsigned direction : 1;
+    unsigned type  : 2;
+    unsigned sync  : 2;
+    unsigned usage : 2;
+    unsigned rsvd2 : 2;
+    unsigned mps       : 11;
+    unsigned trans_opp : 2;
+    unsigned rsvd3     : 3;
+    uint8_t interval;
+} __attribute__((packed));
+
+struct cdi_usb_device_qualifier {
+    struct cdi_usb_descriptor desc;
+    uint16_t bcd_usb;
+    uint8_t class, subclass, protocol;
+    uint8_t mps0;
+    uint8_t num_configurations;
+    uint8_t rsvd;
+} __attribute__((packed));
+
+struct cdi_usb_hub_descriptor {
+    struct cdi_usb_descriptor desc;
+    uint8_t nbr_ports;
+    unsigned power_mode : 2;
+    unsigned compound   : 1;
+    unsigned oc_protect : 2;
+    unsigned tt         : 2;
+    unsigned pindicator : 1;
+    uint8_t rsvd;
+    uint8_t pwr_on_2_pwr_good;
+    uint8_t hub_contr_current;
+    /**
+     * \if german
+     * Die folgenden Felder haben eine variable Grö�e.
+     * \elseif english
+     * The following fields are not constant in size.
+     * \endif
+     */
+} __attribute__((packed));
+
+#endif
+/*\@}*/
+
diff --git a/include/cdi/usb.h b/include/cdi/usb.h
new file mode 100644
index 0000000..b784327
--- /dev/null
+++ b/include/cdi/usb.h
@@ -0,0 +1,713 @@
+/*
+ * Copyright (c) 2010 Max Reitz
+ *
+ * This program is free software. It comes without any warranty, to
+ * the extent permitted by applicable law. You can redistribute it
+ * and/or modify it under the terms of the Do What The Fuck You Want
+ * To Public License, Version 2, as published by Sam Hocevar. See
+ * http://sam.zoy.org/projects/COPYING.WTFPL for more details.
+ */
+
+/**
+ * \if german
+ * USB beinhaltet mehrere Interfaces: Es gibt ein Interface, mit dem sich
+ * Hostcontrollertreiber beim System anmelden können, eines, mit dem USB-
+ * Bustreiber arbeiten (es sollte eigentlich nur einen Bustreiber geben) und
+ * eines, mit dem sich USB-Gerätetreiber beim System registrieren können,
+ * sodass sie aufgerufen werden, wenn ein entsprechendes Gerät gefunden wird.
+ *
+ * \section usb_dev Ein USB-Gerät
+ * Bei CDI.usb gibt es zwei verschiedene Typen von USB-Geräten:
+ *
+ * - Echte (physische) USB-Geräte: Dies ist z. B. ein USB-Stick oder eine
+ *   Tastatur, also das, was auch der Normalbürger als Gerät bezeichnen würde.
+ * - Logische Geräte: Ein echtes USB-Gerät kann mehrere logische enthalten,
+ *   so ist eine Webcam gleichzeitig Video- und Audiogerät. Diese Teilung wird
+ *   über Interfaces erreicht. Ein logisches Gerät kann also entweder ein
+ *   Interface (meistens so, auch wenn nur ein logisches Gerät im echten
+ *   enthalten ist) oder ein echtes Gerät sein (z. B. bei Diagnosegeräten).
+ *   Logische Geräte werden (hier) auch USB-Einheiten genannt.
+ *
+ * Jedem logischen Gerät wird ein Treiber zugewiesen (bzw. es wird zumindest
+ * versucht). So kann ein echtes Gerät von mehreren Treibern gleichzeitig
+ * gesteuert werden.
+ *
+ * \section usb_hc Hostcontroller
+ * Der Hostcontrollertreiber übernimmt zwei Aufgaben:
+ *
+ * - Er leitet USB-Transaktionen ein und muss dabei z. B. selbst darauf achten,
+ *   dass die MPS des verwendeten Endpunkts nicht überschritten wird (also die
+ *   Ã?bertragungen selbst aufteilen).
+ * - Er steuert den Roothub, muss also erkennen, wenn neue Geräte angeschlossen
+ *   werden und dem OS die Möglichkeit bieten, Informationen darüber zu
+ *   erhalten, sie zurückzusetzen, und so weiter.
+ *
+ * \section usb_bus_drv USB-Bustreiber
+ * Der Bustreiber ist für die Steuerung der USB-Topologie zuständig.
+ *
+ * - Er muss Geräte enumerieren und so dem OS über neu angeschlossene Bericht
+ *   erstatten.
+ * - Er muss die Steuerung aller Hubs (au�er Roothubs) übernehmen, ist also
+ *   gleichzeitig auch Hubtreiber.
+ * - Der Bustreiber muss Konfiguration und alternative Einstellungen für
+ *   Interfaces selbstständig auswählen. In jedem Fall müssen betroffene
+ *   Interfaces zunächst deinitialisiert und anschlie�end wieder neu
+ *   registriert werden.
+ * - Au�erdem muss er �bertragungsanforderungen von den Gerätetreibern an den
+ *   Hostcontroller durchreichen und den Status aller Pipes festhalten (z. B.
+ *   Toggle-Bit). Bei Ã?bertragungsfehlern muss entsprechend reagiert werden
+ *   (z. B. ein ClearFeature(ENDPOINT_STALL) bei einem STALL).
+ *
+ * \section usb_dev_drv USB-Gerätetreiber
+ * Ein USB-Gerätetreiber steuert ein logisches USB-Gerät. Zunächst muss er sich
+ * beim System anmelden und mitteilen, welche Geräte er unterstützt. Wird solch
+ * eines gefunden, so wird der Treiber aufgerufen, welcher daraufhin die
+ * Initialisierung (nicht die Enumeration) ausführt.
+ * \elseif english
+ * USB contains multiple interfaces: There is an interface for host controller
+ * drivers to register themselves at the OS, one for USB bus drivers (but there
+ * should be only one bus driver) and one for USB device drivers to register
+ * themselves at the OS, so they are called when an appropriate device has been
+ * found.
+ *
+ * \section usb_dev A USB device
+ * There are two different types of USB devices when using CDI.usb:
+ *
+ * - Physical USB devices: This is for example a USB pen drive or a keyboard,
+ *   i.e., those devices a normal user would call device.
+ * - Logical devices: A physical device may contain several logical ones, e.g.
+ *   a webcam is both video and audio device. This seperation is done via
+ *   interfaces. Hence, a logical device may be either an interface (in most
+ *   cases) or a physical device (e.g., diagnosis devices). Logical devices
+ *   are (as for here) also referred to as USB units.
+ *
+ * Every logical device is handled by one driver (i.e., one tries to do so).
+ * Thus, a physical device may be handled by several drivers simultanously.
+ *
+ * \section usb_hc Host controller
+ * The host controller has two tasks:
+ *
+ * - It initiates USB transactions and has to take care (for example) that the
+ *   MPS of the used endpoint will not be exceeded (so it has to split
+ *   transactions on its own, if necessary).
+ * - It controls the root hub, thus is responsible for discovering new devices
+ *   and the OS must be able to obtain information about them, reset them, and
+ *   so on.
+ *
+ * \section usb_bus_drv USB bus driver
+ * The bus driver is responsible for controling the USB topology.
+ *
+ * - It has to enumerate newly connected devices and tell the OS about them.
+ * - It is responsible for handling all hubs (except the root hub), i.e., is
+ *   also a hub driver.
+ * - The bus driver has to select configurations and alternate interfaces on
+ *   its own. Everytime an interface is changed, it has to be de-initialised
+ *   and registered again.
+ * - Furthermore, it has to send transaction requests from the device drivers
+ *   to the host controller and it needs know every pipe's status (e.g., the
+ *   toggle bit). When detecting errors, it has to react properly (e.g.,
+ *   sending a ClearFeature(ENDPOINT_STALL) after a STALL).
+ *
+ * \section usb_dev_drv USB device driver
+ * A USB device driver controls a USB unit. First, it has to register itself at
+ * the OS and tell it about the devices it supports. If such a device is being
+ * found, the OS calls the driver which will afterwards initialise (not
+ * enumerate) the device.
+ * \endif
+ *
+ * \defgroup usb
+ */
+/*\@{*/
+
+#ifndef _CDI_USB_H_
+#define _CDI_USB_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <cdi.h>
+#include <cdi/mem.h>
+#include <cdi/lists.h>
+
+/**
+ * \if german
+ * Unterscheidet bei USB-Einheiten zwischen Geräten und Interfaces.
+ * \elseif english
+ * Differentiates between devices and interfaces on USB units.
+ * \endif
+ */
+typedef enum {
+    CDI_USB_DEVICE,
+    CDI_USB_INTERFACE
+} cdi_usb_unit_type_t;
+
+/**
+ * \if german
+ * Typ eines Endpunkts oder einer Pipe
+ * \elseif english
+ * Endpoint's or pipe's type
+ * \endif
+ */
+typedef enum {
+    CDI_USB_EP_CONTROL,
+    CDI_USB_EP_BULK,
+    CDI_USB_EP_INTERRUPT,
+    CDI_USB_EP_ISOCHRONOUS
+} cdi_usb_endpoint_type_t;
+
+/**
+ * \if german
+ * Richtung eines Endpunkts oder Transfertyp
+ * \elseif english
+ * Endpoint's direction or transfer type
+ * \endif
+ */
+typedef enum {
+    CDI_USB_DIR_IN,
+    CDI_USB_DIR_OUT,
+    /**
+     * \if german
+     * Setuptransfers oder unbestimmte Richtung
+     * \elseif english
+     * Setup transfers or undefined direction
+     * \endif
+     */
+    CDI_USB_DIR_SETUP
+} cdi_usb_direction_t;
+
+/**
+ * \if german
+ * Geschwindigkeit eines Geräts, eines Hostcontrollers, usw..
+ * \elseif english
+ * Speed of a device, a host controller, etc..
+ * \endif
+ */
+typedef enum {
+    CDI_USB_LOW_SPEED = (1 << 0),
+    CDI_USB_FULL_SPEED = (1 << 1),
+    CDI_USB_HIGH_SPEED = (1 << 2),
+    CDI_USB_SUPERSPEED = (1 << 3)
+} cdi_usb_speed_t;
+
+/**
+ * \if german
+ * Kann eine USB-Geräteadresse aufnehmen (0 â?? 127)
+ * \elseif english
+ * Capable of holding a USB device address (0â??127)
+ * \endif
+ */
+typedef int8_t cdi_usb_dev_id_t;
+
+/**
+ * \if german
+ * Dient zur eindeutigen Identifizierung eines Interfaces innerhalb eines
+ * Geräts
+ * \elseif english
+ * Used to uniquely identify an interface on one device
+ * \endif
+ */
+typedef int cdi_usb_interface_t;
+
+/**
+ * \if german
+ * Dient zur global eindeutigen Identifizierung eines Endpunkts
+ * \elseif english
+ * Used to uniquely identify an endpoint (globally)
+ * \endif
+ */
+typedef int cdi_usb_endpoint_t;
+
+/**
+ * \if german
+ * Repräsentiert eine USB-Pipe.
+ * \elseif english
+ * Represents a USB pipe.
+ * \endif
+ */
+typedef void* cdi_usb_pipe_t;
+
+struct cdi_usb_transaction;
+/**
+ * \if german
+ *
+ * Callback für periodische Transfers.
+ *
+ * @param transaction Transaktion, die den Aufruf ausgelöst hat
+ *
+ * \elseif english
+ *
+ * Callback for periodic transfers.
+ *
+ * @param transaction Transaction which caused the call
+ *
+ * \endif
+ */
+typedef void (*cdi_usb_callback_periodic_t)(struct cdi_usb_transaction* transaction);
+
+/**
+ * \if german
+ * Eine USB-Einheit ist ein logisches USB-Gerät. Jede Einheit wird von einem
+ * (oder keinem) USB-Gerätetreiber behandelt.
+ * Solch eine Einheit kann entweder ein echtes USB-Gerät oder (häufiger) ein
+ * Interface sein.
+ * \elseif english
+ * A USB unit is a logical USB device. Each unit is handled by one (or none)
+ * USB device driver.
+ * Such a unit may be either a physical USB device or (more often) an interface.
+ * \endif
+ */
+struct cdi_usb_unit {
+    /**
+     * \if german
+     * Typ der Einheit (echtes Gerät oder Interface)
+     * \elseif english
+     * Unit type (physical device or interface)
+     * \endif
+     */
+    cdi_usb_unit_type_t type;
+    /**
+     * \if german
+     * USB-Geräteadresse des echten USB-Geräts, zu dem dieses logische
+     * gehört.
+     * \elseif english
+     * USB device address of the physical USB device this logical one belongs
+     * to.
+     * \endif
+     */
+    cdi_usb_dev_id_t device_id;
+    /**
+     * \if german
+     * Interface-ID, wenn es sich um ein Interface handelt; bei echten USB-
+     * Geräten muss dies entweder die ID des ersten Interfaces sein, oder eine
+     * ungültige ID, sodass beim Aufruf von cdi_get_usb_interface die Daten
+     * des ersten Interfaces zurückgegeben werden.
+     * \elseif english
+     * Interface ID if this is an interface; if this unit is a physical USB
+     * device, this ID is either the first interface's ID or an invalid one,
+     * thus calling cdi_get_usb_interface returns the first interface's data.
+     * \endif
+     */
+    cdi_usb_interface_t interface_id;
+    /**
+     * \if german
+     * Klasse, Unterklasse und Protokoll dieser USB-Einheit.
+     * \elseif english
+     * Class, subclass and protocol of this USB unit.
+     * \endif
+     */
+    int class, subclass, protocol;
+    /**
+     * \if german
+     * Hersteller- und Produkt-ID des echten USB-Geräts.
+     * \elseif english
+     * Vendor and product ID of the physical USB device.
+     * \endif
+     */
+    int vendor_id, product_id;
+};
+
+/**
+ * \if german
+ * Echtes USB-Gerät.
+ * \elseif english
+ * Physical USB device.
+ * \endif
+ */
+struct cdi_usb_device {
+    struct cdi_usb_unit usb_unit;
+
+    /**
+     * \if german
+     * Geschwindigkeit des Geräts.
+     * \elseif english
+     * Device's speed.
+     * \endif
+     */
+    cdi_usb_speed_t speed;
+};
+
+/**
+ * \if german
+ * USB-Geräteinterface.
+ * \elseif english
+ * USB device interface.
+ * \endif
+ */
+struct cdi_usb_interface {
+    struct cdi_usb_unit usb_unit;
+
+    /**
+     * \if german
+     * Enthält Elemente vom Typ cdi_usb_endpoint_t.
+     * \elseif english
+     * Contains elements of type cdi_usb_endpoint_t.
+     * \endif
+     */
+    cdi_list_t endpoints;
+};
+
+/**
+ * \if german
+ * Beschreibt eine gefundene USB-Einheit.
+ * \elseif english
+ * Describtes a found USB unit.
+ * \endif
+ */
+struct cdi_usb_bus_data {
+    struct cdi_bus_data generic;
+    struct cdi_usb_unit* unit;
+};
+
+/**
+ * \if german
+ * Informationen zu einem USB-Endpunkt.
+ * \elseif english
+ * Information about a USB endpoint.
+ * \endif
+ */
+struct cdi_usb_endpoint {
+    /**
+     * \if german
+     * Typ des Endpunkts (Control, Bulk, Interrupt, Isochronous)
+     * \elseif english
+     * Endpoint's type (control, bulk, interrupt, isochronous)
+     * \endif
+     */
+    cdi_usb_endpoint_type_t type;
+    /**
+     * \if german
+     * Richtung des Endpunkts (IN, OUT, undefiniert)
+     * \elseif english
+     * Endpoint's direction (IN, OUT, undefined)
+     * \endif
+     */
+    cdi_usb_direction_t direction;
+    /**
+     * \if german
+     * Nummer des Endpunkts in der aktuellen Konfiguration.
+     * \elseif english
+     * Endpoint's number in the current configuration.
+     * \endif
+     */
+    int number;
+    /**
+     * \if german
+     * Maximale Paketgrö�e des Endpunkts.
+     * \elseif english
+     * Maximum packet size of this endpoint.
+     * \endif
+     */
+    int mps;
+    /**
+     * \if german
+     * Aktuelles Datatoggle. Ist hier, damit Hostcontroller- und Bustreiber
+     * synchronisiert bleiben (jeder kann seine eigene Pipestruktur haben, aber
+     * die Endpunktstruktur ist identisch).
+     * \elseif english
+     * Current data toggle. Is here to allow host controller and bus driver to
+     * stay synchronised (both may use their own pipe structure, but the
+     * endpoint structure is identical).
+     * \endif
+     */
+    int toggle;
+};
+
+/**
+ * \if german
+ * Beschreibt eine USB-Transaktion.
+ * \elseif english
+ * Describes a USB transaction.
+ * \endif
+ */
+struct cdi_usb_transaction {
+    /**
+     * \if german
+     * Typ der Transaktion
+     * \elseif english
+     * Transaction type
+     * \endif
+     */
+    cdi_usb_endpoint_type_t type;
+    /**
+     * \if german
+     * Pipe, über die die �bertragung ablaufen soll.
+     * \elseif english
+     * Pipe to be used by the transaction.
+     * \endif
+     */
+    cdi_usb_pipe_t pipe;
+    /**
+     * \if german
+     * Zu verwendender Datenpuffer (je nach Ã?bertragungstyp).
+     * \elseif english
+     * Buffer to be used (depends on the transaction type).
+     * \endif
+     */
+    struct cdi_mem_area* buffer;
+};
+
+/**
+ * \if german
+ * Beschreibt einen Controltransfer.
+ * \elseif english
+ * Describes a control transfer.
+ * \endif
+ */
+struct cdi_usb_control_transaction {
+    struct cdi_usb_transaction transaction;
+    /**
+     * \if german
+     * Daten, die während der Setupstage gesendet werden sollen (der Puffer
+     * muss acht Byte lang sein).
+     * \elseif english
+     * Data to be sent during setup stage (buffer has to contain eight bytes).
+     * \endif
+     */
+    void* setup_packet;
+};
+
+/**
+ * \if german
+ * Beschreibt einen Bulktransfer.
+ * \elseif english
+ * Describes a bulk transfer.
+ * \endif
+ */
+struct cdi_usb_bulk_transaction {
+    struct cdi_usb_transaction transaction;
+    /**
+     * \if german
+     * Nachdem die Ã?bertragung abgeschlossen ist, wird dieses Feld entweder auf
+     * 0 (erfolgreich) oder -1 (Fehler) gesetzt.
+     * \elseif english
+     * After the transaction has been done this value is either set to 0
+     * (success) or -1 (error).
+     * \endif
+     */
+    volatile int status;
+};
+
+/**
+ * \if german
+ * Beschreibt einen Interrupttransfer.
+ * \elseif english
+ * Descripes an interrupt transfer.
+ * \endif
+ */
+struct cdi_usb_interrupt_transaction {
+    struct cdi_usb_transaction transaction;
+    /**
+     * \if german
+     * Callback, der bei jedem Empfangen von Daten aufgerufen wird.
+     * \elseif english
+     * Callback being called upon receiving data.
+     * \endif
+     */
+    cdi_usb_callback_periodic_t callback;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \if german
+ *
+ * Speichert Informationen zum angegebenen Interface in der Struktur, auf die
+ * der Pointer zeigt.
+ *
+ * @param interface Hier wird die Information gespeichert, die Felder
+ *                  usb_unit.device_id und usb_unit.interface_id geben das zu
+ *                  untersuchende Interface an. Ist der Wert für interface_id
+ *                  ungültig (also z. B. negativ; wenn ein Interface einfach
+ *                  nicht existiert, der Wert an sich aber gültig ist, dann
+ *                  gilt dies nicht), so muss das erste Interface des Geräts
+ *                  genutzt werden.
+ *
+ * @return 0 im Erfolgsfall, -1, wenn ein Fehler aufgetreten ist.
+ *
+ * \elseif english
+ *
+ * Stores information about the given interface in the structure the pointer is
+ * pointing to.
+ *
+ * @param interface Information is stored here, usb_unit.device_id and
+ *                  usb_unit.interface_id select the interface to be examined.
+ *                  If the value of interface_id is invalid (e.g., negative; if
+ *                  an interface simply not exist but the value itself is valid,
+ *                  then the following is not applicable), then the device's
+ *                  first interface has to be used.
+ *
+ * @return 0 in case of success, -1 in case of error.
+ *
+ * \endif
+ */
+int cdi_get_usb_interface(struct cdi_usb_interface* interface);
+
+/**
+ * \if german
+ *
+ * Speichert Informationen zum angegebenen Endpunkt in der Struktur, auf die der
+ * Pointer zeigt.
+ *
+ * @param endpoint Die Daten werden hier gespeichert
+ * @param id ID des Endpunkts
+ *
+ * @return 0 bei Erfolg, sonst -1.
+ *
+ * \elseif english
+ *
+ * Stores information about the given endpoint in the structure the pointer is
+ * pointing to.
+ *
+ * @param endpoint Data is stored here
+ * @param id Endpoint's ID
+ *
+ * @return 0 on success, -1 else.
+ *
+ * \endif
+ */
+int cdi_get_usb_endpoint(struct cdi_usb_endpoint* endpoint,
+    cdi_usb_endpoint_t id);
+
+/**
+ * \if german
+ *
+ * Erstellt eine USB-Pipe zum angegebenen Endpunkt (oder gibt die ID einer
+ * bestehenden zurück, wenn sie bereits existiert).
+ *
+ * @param endpoint ID des Endpunkts
+ *
+ * @return ID der Pipe bei Erfolg, sonst (cdi_usb_pipe_t)-1.
+ *
+ * \elseif english
+ *
+ * Creates a USB pipe to the given endpoint (or returns an existing one's if
+ * there is one).
+ *
+ * @param endpoint Endpoint's ID
+ *
+ * @return Pipe's ID on success, else (cdi_usb_pipe_t)-1.
+ *
+ * \endif
+ */
+cdi_usb_pipe_t cdi_usb_connect(cdi_usb_endpoint_t endpoint);
+
+/**
+ * \if german
+ *
+ * Entfernt eine existierende Pipe.
+ *
+ * @param pipe Zu entfernende Pipe
+ *
+ * \elseif english
+ *
+ * Removes an existing pipe.
+ *
+ * @param pipe Pipe to be removed
+ *
+ * \endif
+ */
+void cdi_usb_disconnect(cdi_usb_pipe_t pipe);
+
+/**
+ * \if german
+ *
+ * Leitet eine USB-Ã?bertragung ein.
+ *
+ * @param transaction Informationen zur Transaktion
+ *
+ * @return 0, wenn die Ã?bertragung erfolgreich gestartet werden konnte, -1 im
+ *         Fehlerfall (bei synchronen Ã?bertragungen wird so auch der Status
+ *         der gesamten Ã?bertragung angezeigt)
+ *
+ * \elseif english
+ *
+ * Initiates a USB transaction.
+ *
+ * @param transaction Information about the transaction
+ *
+ * @return 0 if the transaction has been enqueued successfully, -1 in case of
+ *         an error (indicates also the status of the whole transaction for
+ *         synchronous ones)
+ *
+ * \endif
+ */
+int cdi_usb_initiate_transaction(struct cdi_usb_transaction* transaction);
+
+/**
+ * \if german
+ *
+ * Gibt Informationen zu einer Pipe zurück.
+ *
+ * @param pipe Zu untersuchende Pipe
+ * @param device_addr Hier wird die USB-Adresse des Zielgeräts gespeichert
+ * @param endpoint Hier werden Informationen zum Zielendpunkt gespeichert
+ *
+ * @return 0 bei Erfolg, sonst -1 (z. B. Pipe existiert nicht)
+ *
+ * \elseif english
+ *
+ * Returns information about a pipe.
+ *
+ * @param pipe Pipe to be examined
+ * @param device_addr USB address of the target device is stored here
+ * @param endpoint Information about the target endpoint is stored here
+ *
+ * @return 0 on success, -1 else (e.g., pipe doesn't exist)
+ *
+ * \endif
+ */
+int cdi_usb_get_pipe_information(cdi_usb_pipe_t pipe, int* device_addr,
+    struct cdi_usb_endpoint* endpoint);
+
+/**
+ * \if german
+ *
+ * Registriert einen USB-Gerätetreiber für einen bestimmten Typ von USB-
+ * Geräten. Ist einem Treiber ein Feld egal, so muss er dort -1 übergeben
+ * (möchte er z. B. alle Geräte eines bestimmten Klassen- und
+ * Unterklassencodes behandeln, so müssen protocol, vendor_id und product_id
+ * -1 sein).
+ * Das Betriebssystem muss dafür Sorge tragen, dass beim Auffinden eines
+ * USB-Geräts nur der am besten passende Callback aufgerufen wird (z. B. sind
+ * Hersteller- und Produkt-ID eindeutiger als die Klassencodes).
+ *
+ * @param drv Treiberstruktur (Pointer init_device und remove_device werden
+ *            jeweils verwendet, wenn ein Gerät gefunden oder entfernt wurde)
+ * @param class Klassencode
+ * @param subclass Unterklassencode
+ * @param protocol Protokolltyp
+ * @param vendor_id Hersteller-ID
+ * @param product_id Produkt-ID
+ *
+ * \elseif english
+ *
+ * Registers a USB device driver for a specific type of USB device. If the
+ * driver does not care about a field, it must be set to -1 (e.g., if it wants
+ * to handle all devices with a specific class and subclass code, then protocol,
+ * vendor_id and product_id must be set to -1).
+ * The OS has to make sure that upon finding a USB device just the best fitting
+ * callback is called (e.g., vendor and product ID are less ambiguous than the
+ * class codes).
+ *
+ * @param drv Driver structure (pointers init_device and remove_device will be
+ *            used when a device has been found or removed, respectively)
+ * @param class Class code
+ * @param subclass Subclass code
+ * @param protocol Protocol type
+ * @param vendor_id Vendor ID
+ * @param product_id Product ID
+ *
+ * \endif
+ */
+void cdi_usb_register_device_driver(struct cdi_driver* drv, int class,
+    int subclass, int protocol, int vendor_id, int product_id);
+
+#ifdef __cplusplus
+}; // extern "C"
+#endif
+
+#endif
+/*\@}*/
+
-- 
1.6.4.2