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

[tyndur-devel] [PATCH 1/3] CDI.usb, CDI.usb-hcd, mempool



From: Max Reitz <max@xxxxxxxxxx>

+ CDI.usb-Lib (nur tauglich, wenn alle die Lib nutzenden Treiber
  in einer Binary sind)
+ CDI.usb-hcd-Lib (ebenso)
+ Mempool-Lib für CDI-Treiber

Signed-off-by: Max Reitz <max@xxxxxxxxxx>
---
 src/modules/cdi/include/cdi/mempool.h |   35 ++
 src/modules/cdi/include/cdi/usb-hcd.h |  184 +++++++
 src/modules/cdi/include/cdi/usb.h     |  880 +++++++++++++++++++++++++++++++++
 src/modules/cdi/lib/cdi.c             |    5 +
 src/modules/cdi/lib/mempool.c         |  109 ++++
 src/modules/cdi/lib/usb-hcd.c         |   55 ++
 src/modules/cdi/lib/usb.c             |  425 ++++++++++++++++
 7 files changed, 1693 insertions(+), 0 deletions(-)
 create mode 100644 src/modules/cdi/include/cdi/mempool.h
 create mode 100644 src/modules/cdi/include/cdi/usb-hcd.h
 create mode 100644 src/modules/cdi/include/cdi/usb.h
 create mode 100644 src/modules/cdi/lib/mempool.c
 create mode 100644 src/modules/cdi/lib/usb-hcd.c
 create mode 100644 src/modules/cdi/lib/usb.c

diff --git a/src/modules/cdi/include/cdi/mempool.h b/src/modules/cdi/include/cdi/mempool.h
new file mode 100644
index 0000000..83d2ab2
--- /dev/null
+++ b/src/modules/cdi/include/cdi/mempool.h
@@ -0,0 +1,35 @@
+/******************************************************************************
+* Copyright (c) 2009 Kevin Wolf                                              *
+*                                                                            *
+* Permission is hereby granted,  free of charge,  to any  person obtaining a *
+* copy of this software and associated documentation files (the "Software"), *
+* to deal in the Software without restriction,  including without limitation *
+* the rights to use,  copy, modify, merge, publish,  distribute, sublicense, *
+* and/or sell copies  of the  Software,  and to permit  persons to whom  the *
+* Software is furnished to do so, subject to the following conditions:       *
+*                                                                            *
+* The above copyright notice and this permission notice shall be included in *
+* all copies or substantial portions of the Software.                        *
+*                                                                            *
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
+* IMPLIED, INCLUDING  BUT NOT  LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
+* FITNESS FOR A PARTICULAR  PURPOSE AND  NONINFRINGEMENT.  IN NO EVENT SHALL *
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
+* LIABILITY,  WHETHER IN AN ACTION OF CONTRACT,  TORT OR OTHERWISE,  ARISING *
+* FROM,  OUT OF  OR IN CONNECTION  WITH THE  SOFTWARE  OR THE  USE OR  OTHER *
+* DEALINGS IN THE SOFTWARE.                                                  *
+*****************************************************************************/
+
+#ifndef MEMPOOL_H
+#define MEMPOOL_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+struct mempool;
+
+struct mempool* mempool_create(size_t pool_size, size_t object_size);
+int mempool_get(struct mempool* pool, void** obj, uintptr_t* phys_obj);
+int mempool_put(struct mempool* pool, void* obj);
+
+#endif
diff --git a/src/modules/cdi/include/cdi/usb-hcd.h b/src/modules/cdi/include/cdi/usb-hcd.h
new file mode 100644
index 0000000..246bda4
--- /dev/null
+++ b/src/modules/cdi/include/cdi/usb-hcd.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2009 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-Hostcontrollertreiber
+ * \elseif english
+ * USB host controller drivers
+ * \endif
+ * \defgroup USBHCD
+ */
+/*\@{*/
+
+#ifndef _CDI_USB_HCD_H_
+#define _CDI_USB_HCD_H_
+
+#include "cdi/misc.h"
+#include "cdi/usb.h"
+#include "sys/types.h"
+
+struct cdi_usb_hc {
+    struct cdi_device dev;
+
+    /**
+      * \if german
+      * USB-Geschwindigkeit
+      * \elseif english
+      * USB speed
+      * \endif
+      */
+    cdi_usb_speed_t speed;
+};
+
+struct cdi_usb_hcd {
+    struct cdi_driver drv;
+
+    /**
+      * \if german
+      *
+      * Listet alle Geraete auf, die an den Rootports haengen und ruft ggf.
+      * cdi_usb_device_init auf
+      *
+      * @param device Der Hostcontroller
+      *
+      * \elseif english
+      *
+      * Lists all devices hanging at the root ports and calls (if necessary)
+      * cdi_usb_device_init
+      *
+      * @param device The host controller
+      *
+      * \endif
+      */
+    void (*find_devices)(struct cdi_usb_hc* device);
+
+    /**
+      * \if german
+      *
+      * Aktiviert den zum angegebenen Geraet gehoerigen Rootport
+      *
+      * @param usb_device Das USB-Geraet (muss an einem Rootport haengen)
+      *
+      * \elseif english
+      *
+      * Activates the root port corresponding to the device
+      *
+      * @param usb_device The USB device (must be located at a root port)
+      *
+      * \endif
+      */
+    void (*activate_device)(struct cdi_usb_device* usb_device);
+
+    /**
+      * \if german
+      *
+      * 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)
+      *
+      * \elseif english
+      *
+      * Sends USB packets
+      *
+      * @param packets Array of packages to be sent
+      * @param num_packages Number of packages
+      *
+      * \endif
+      */
+    cdi_usb_status_t (*send_packets)(struct cdi_usb_packet* packets,
+        size_t num_packets);
+
+    /**
+      * \if german
+      *
+      * Erstellt eine neue Pipe
+      *
+      * @param pipe Die Pipe
+      *
+      * \elseif english
+      *
+      * Creates a new pipe
+      *
+      * @param pipe The pipe
+      *
+      * \endif
+      */
+    void (*add_pipe)(struct cdi_usb_pipe* pipe);
+
+    /*
+    // tyndurspezifisch
+    pid_t pid;
+    uintptr_t real_add_pipe;*/
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+  * \if german
+  *
+  * Initialisiert einen HCD
+  *
+  * @param driver Der HCD
+  *
+  * \elseif english
+  *
+  * Initializes an HCD
+  *
+  * @param driver The HCD
+  *
+  * \endif
+  */
+void cdi_usb_hcd_init(struct cdi_usb_hcd* driver);
+
+/**
+  * \if german
+  *
+  * Gibt einen HCD frei
+  *
+  * @param driver Freizugebender HCD
+  *
+  * \elseif english
+  *
+  * Removes an HCD
+  *
+  * @param driver HCD to be removed
+  *
+  * \endif
+  */
+void cdi_usb_hcd_destroy(struct cdi_usb_hcd* driver);
+
+/**
+ * \if german
+ *
+ * Registriert einen HCD
+ *
+ * @param driver Zu registrierender HCD
+ *
+ * \elseif english
+ *
+ * Registers an HCD
+ *
+ * @param driver HCD to be registered
+ *
+ * \endif
+ */
+//void cdi_usb_hcd_register(struct cdi_usb_hcd* driver);
+
+#ifdef __cplusplus
+} //extern "C"
+#endif
+
+#endif
diff --git a/src/modules/cdi/include/cdi/usb.h b/src/modules/cdi/include/cdi/usb.h
new file mode 100644
index 0000000..ccfe6c1
--- /dev/null
+++ b/src/modules/cdi/include/cdi/usb.h
@@ -0,0 +1,880 @@
+/*
+ * Copyright (c) 2009 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-Bustreiber
+ * \elseif english
+ * USB bus drivers
+ * \endif
+ * \defgroup USB
+ */
+/*\@{*/
+
+#ifndef _CDI_USB_H_
+#define _CDI_USB_H_
+
+#include "stddef.h"
+#include "stdint.h"
+#include "sys/types.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 {
+    /**
+      * \if german
+      * SETUP-Paket
+      * \elseif english
+      * SETUP packet
+      * \endif
+      */
+    CDI_USB_PACKET_SETUP = 0x2D,
+
+    /**
+      * \if german
+      * Daten vom Geraet zum Host
+      * \elseif english
+      * Data from the device to the host
+      * \endif
+      */
+    CDI_USB_PACKET_IN    = 0x69,
+
+    /**
+      * \if german
+      * Daten vom Host zum Geraet
+      * \elseif english
+      * Data from the host to the device
+      * \endif
+      */
+    CDI_USB_PACKET_OUT   = 0xE1,
+} cdi_usb_packet_type_t;
+
+typedef enum {
+    /**
+      * \if german
+      * Kein Fehler
+      * \elseif english
+      * No error
+      * \endif
+      */
+    CDI_USB_NO_ERROR      = 0x0000,
+
+    /// Stalled
+    CDI_USB_STALLED       = 0x0001,
+
+    /**
+      * \if german
+      * Bufferfehler (Overflow, underrun, ...)
+      * \elseif english
+      * Buffer error (overflow, underrun, ...)
+      * \endif
+      */
+    CDI_USB_BUFFER_ERROR  = 0x0002,
+
+    /**
+      * \if german
+      * Babble (Geraet hat zu viele Daten gesendet)
+      * \elseif english
+      * Babble (device has sent more data than expected)
+      * \endif
+      */
+    CDI_USB_BABBLE        = 0x0004,
+
+    /**
+      * \if german
+      * NAK (Daten sind erneut zu senden)
+      * \elseif english
+      * NAK (data has to be sent again)
+      * \endif
+      */
+    CDI_USB_NAK           = 0x0008,
+
+    /**
+      * \if german
+      * CRC-Fehler
+      * \elseif english
+      * CRC error
+      * \endif
+      */
+    CDI_USB_CRC           = 0x0010,
+
+    /// Timeout
+    CDI_USB_TIMEOUT       = 0x0020,
+
+    /**
+      * \if german
+      * Bitstuff/-destuff-Fehler
+      * \elseif english
+      * bitstuff/-destuff error
+      * \endif
+      */
+    CDI_USB_BITSTUFF      = 0x0040,
+
+    /**
+      * \if german
+      * Reservieren von Speicher fehlgeschlagen, ...
+      * \elseif english
+      * Allocating of memory failed, ...
+      * \endif
+      */
+    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 {
+    /**
+      * \if german
+      * Der USB-Bustreiber
+      * \elseif english
+      * The USB bus driver
+      * \endif
+      */
+    struct cdi_usb_driver* drv;
+
+    /**
+      * \if german
+      * Der Hostcontroller, an dem das Geraet im Endeffekt haengt
+      * \elseif english
+      * The host controller where the device is eventually located
+      * \endif
+      */
+    struct cdi_usb_hc* hc;
+
+    /**
+      * \if german
+      * 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.
+      * \elseif english
+      * If the device is located at a hub, then this field contains a pointer to
+      * the corresponding USB device, if it's located at a root port, then this
+      * field is set to NULL.
+      * \endif
+      */
+    struct cdi_usb_device* hub;
+
+    /**
+      * \if german
+      * Geschwindigkeit(-en) dieses Geraets
+      * \elseif english
+      * Speed(-s) supported by this device
+      * \endif
+      */
+    cdi_usb_speed_t speed;
+
+    /// ID
+    int id;
+
+    /**
+      * \if german
+      * Entweder der Rootport oder der Port des Hubs, an dem das Geraet haengt
+      * \elseif english
+      * Either the root port or the port hub's port where the device is located
+      * \endif
+      */
+    int port;
+
+    /**
+      * \if german
+      * Hier darf der Geraetetreiber seine Daten unterbringen
+      * \elseif english
+      * The device driver may store its data here
+      * \endif
+      */
+    void* driver_data;
+
+    /**
+      * \if german
+      * Felder, die so auch bei PCI existieren: Vendor-, Device-, Class-,
+      * Subclass- und Protocol-ID
+      * \elseif english
+      * Fields existing at PCI, too: vendor, device, class, subclass and
+      * protocol ID.
+      * \endif
+      */
+    int vendor_id;
+    int device_id;
+    int class_id;
+    int subclass_id;
+    int protocol_id;
+
+    /**
+      * \if german
+      *
+      * Setzt das USB-Geraet zurueck (kann sowohl vom HCD als auch vom Hub
+      * driver ausgefuehrt werden)
+      *
+      * @param usb_device Das Geraet
+      *
+      * \elseif english
+      *
+      * Resets the USB device (may be executed either by the HCD or the hub
+      * driver)
+      *
+      * @param usb_device The device
+      *
+      * \endif
+      */
+    void (*reset)(struct cdi_usb_device* usb_device);
+
+    /**
+      * \if german
+      * Ziemlich lowlevelig. Gehoert das hier wirklich rein?
+      * \elseif english
+      * Very low level. Does it really fit in here?
+      * \endif
+      */
+
+    /**
+      * \if german
+      * Im einzelnen sind das: Pipe fuer Endpoint 0
+      * \elseif english
+      * In particular these things are: Pipe for endpoint 0
+      * \endif
+      */
+    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;
+
+    /*
+    // tyndurspezifisch
+    uintptr_t real_reset;
+    pid_t ppid;*/
+};
+
+enum cdi_usb_toggle {
+    /**
+      * \if german
+      * Das Toggle nehmen, das jetzt dran ist
+      * \elseif english
+      * Use the toggle to be used right now
+      * \endif
+      */
+    TOGGLE_UNSPECIFIC = 0,
+
+    /**
+      * \if german
+      * Geloeschtes Togglebit erzwingen
+      * \elseif english
+      * Force unset toggle bit
+      * \endif
+      */
+    TOGGLE_0 = 1,
+
+    /**
+      * \if german
+      * Gesetztes Togglebit erzwingen
+      * \elseif english
+      * Force set toggle bit
+      * \endif
+      */
+    TOGGLE_1 = 2
+};
+
+struct cdi_usb_endpoint {
+    /// sizeof(struct cdi_usb_endpoint)
+    uint8_t length;
+
+    /// 5
+    uint8_t descriptor_type;
+
+    /**
+      * \if german
+      * Nummer des Endpoints
+      * \elseif english
+      * Endpoint's number
+      * \endif
+      */
+    uint8_t endpoint_address;
+
+    /**
+      * \if german
+      * Eigenschaften (IN/OUT, Bulk/Interrupt/..., ...)
+      * \elseif english
+      * Attributes (IN/OUT, bulk/interrupt/..., ...)
+      * \endif
+      */
+    uint8_t attributes;
+
+    /**
+      * \if german
+      * Maximale Paketgroesse in Bytes
+      * \elseif english
+      * Maximum packet size in bytes
+      * \endif
+      */
+    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;
+
+    /**
+      * \if german
+      * Nummer des Interface
+      * \elseif english
+      * Interface's number
+      * \endif
+      */
+    uint8_t interface_number;
+
+    /// ???
+    uint8_t alternate_setting;
+
+    /**
+      * \if german
+      * Anzahl der Endpoints fuer dieses Interface
+      * \elseif english
+      * Number of endpoints for this interface
+      * \endif
+      */
+    uint8_t num_endpoints;
+
+    /**
+      * \if german
+      * Class-ID (bei Composite Devices)
+      * \elseif english
+      * Class ID (used with composite devices)
+      * \endif
+      */
+    uint8_t interface_class;
+
+    /// Subclass-ID
+    uint8_t interface_subclass;
+
+    /// Protocol-ID
+    uint8_t interface_protocol;
+
+    /**
+      * \if german
+      * String-Index, der das Interface beschreibt
+      * \elseif english
+      * String index describing the interface
+      * \endif
+      */
+    uint8_t iInterface;
+} __attribute__((packed));
+
+/**
+  * \if german
+  * Beschreibt eine Pipe
+  * \elseif english
+  * Describes a pipe
+  * \endif
+  */
+struct cdi_usb_pipe {
+    /**
+      * \if german
+      * Ziel
+      * \elseif english
+      * Destination
+      * \endif
+      */
+    struct cdi_usb_device* device;
+
+    /**
+      * \if german
+      * Ein Pointer auf eine den Endpoint beschreibende Struktur
+      * TODO Das ist eigentlich auch sehr lowlevelig.
+      * \elseif english
+      * A pointer to a structure describing the endpoint
+      * TODO This is on a very low level, too.
+      */
+    struct cdi_usb_endpoint* endpoint;
+
+    /// Data-Toggle
+    int data_toggle;
+};
+
+/**
+  * \if german
+  * Beschreibt ein USB-Paket
+  * \elseif english
+  * Describes a USB packet
+  * \endif
+  */
+struct cdi_usb_packet {
+    /**
+      * \if german
+      * Die gewuenschte Pipe
+      * \elseif english
+      * The desired pipe
+      * \endif
+      */
+    struct cdi_usb_pipe* pipe;
+
+    /**
+      * \if german
+      * Der Typ des Pakets (PACKET_IN, PACKET_OUT, PACKET_SETUP)
+      * \elseif english
+      * Type of packet (PACKET_IN, PACKET_OUT, PACKET_SETUP)
+      * \endif
+      */
+    cdi_usb_packet_type_t type;
+
+    /**
+      * \if german
+      * Zeiger auf den Datenpuffer
+      * \elseif english
+      * Pointer to the data buffer
+      * \endif
+      */
+    void* data;
+
+    /**
+      * \if german
+      * Die Laenge des Puffers
+      * \elseif english
+      * The buffer's length
+      * \endif
+      */
+    size_t length;
+
+    /**
+      * \if german
+      * Fehlertyp (oder CDI_USB_NO_ERROR)
+      * \elseif english
+      * Error type (or CDI_USB_NO_ERROR)
+      * \endif
+      */
+    cdi_usb_status_t condition;
+
+    /**
+      * \if german
+      * Bestimmtes Data-Toggle benuten
+      * \elseif english
+      * Use specific data toggle
+      * \endif
+      */
+    enum cdi_usb_toggle use_toggle;
+};
+
+typedef enum {
+    /**
+      * \if german
+      * Host -> Geraet
+      * \elseif english
+      * Host -> device
+      * \endif
+      */
+    CDI_USB_CONTROL_OUT = 0x00,
+
+    /**
+      * \if german
+      * Geraet -> Host
+      * \elseif english
+      * Device -> host
+      * \endif
+      */
+    CDI_USB_CONTROL_IN = 0x80
+} cdi_usb_control_direction_t;
+
+typedef enum {
+    /**
+      * \if german
+      * Standard-Request
+      * \elseif english
+      * Standard request
+      * \endif
+      */
+    CDI_USB_CONTROL_RQ_STANDARD = 0x00,
+
+    /**
+      * \if german
+      * Klassenspezifischer Request
+      * \elseif english
+      * Class specific request
+      * \endif
+      */
+    CDI_USB_CONTROL_RQ_CLASS = 0x20,
+
+    /**
+      * \if german
+      * Herstellerspezifischer Request
+      * \elseif english
+      * Vendor specific request
+      * \endif
+      */
+    CDI_USB_CONTROL_RQ_VENDOR = 0x40
+} cdi_usb_control_request_type_t;
+
+typedef enum {
+    /**
+      * \if german
+      * Empfaenger: Geraet
+      * \elseif english
+      * Recipient: device
+      * \endif
+      */
+    CDI_USB_CONTROL_REC_DEVICE = 0x00,
+
+    /**
+      * \if german
+      * Empfaenger: Interface
+      * \elseif english
+      * Recipient: interface
+      * \endif
+      */
+    CDI_USB_CONTROL_REC_INTERFACE = 0x01,
+
+    /**
+      * \if german
+      * Empfaenger: Endpoint
+      * \elseif english
+      * Recipient: endpoint
+      * \endif
+      */
+    CDI_USB_CONTROL_REC_ENDPOINT = 0x02,
+
+    /**
+      * \if german
+      * Empfaenger ist jemand anderes
+      * \elseif english
+      * Recipient is another one
+      * \endif
+      */
+    CDI_USB_CONTROL_REC_OTHER = 0x03
+} cdi_usb_control_recipient_t;
+
+struct cdi_usb_control_transfer {
+    /**
+      * \if german
+      * Wenn Daten zum Geraet gesendet werden sollen, dann ist hier der
+      * Speicherbereich anzugeben
+      * \elseif english
+      * If data has to be sent to the device, then the memory buffer has to be
+      * given here
+      * \endif
+      */
+    void* buffer;
+
+    /**
+      * \if german
+      * Laenge der erwarteten bzw. zu sendenden Daten
+      * \elseif english
+      * Length of the expected data respectively the data to be sent
+      * \endif
+      */
+    size_t length;
+
+    /**
+      * \if german
+      * Richtung
+      * \elseif english
+      * Direction
+      * \endif
+      */
+    cdi_usb_control_direction_t direction;
+
+    /**
+      * \if german
+      * Art des Requests (Standardrequest, klassenspezifisch,
+      * herstellerspezifisch)
+      * \elseif english
+      * Request type (standard request, class specific, vendor specific)
+      * \endif
+      */
+    cdi_usb_control_request_type_t rtype;
+
+    /**
+      * \if german
+      * Ziel (Device, Interface, Endpoint, anderes)
+      * \elseif english
+      * Recipient (device, interface, endpoint, other)
+      * \endif
+      */
+    cdi_usb_control_recipient_t recipient;
+
+    /**
+      * \if german
+      * Requestcode (Je nach rtype und recipient)
+      * \elseif english
+      * Request code (specific to rtype and recipient)
+      * \endif
+      */
+    int request;
+
+    /**
+      * \if german
+      * Ein zu sendender Wert
+      * \elseif english
+      * A value to be sent
+      * \endif
+      */
+    int value;
+
+    /**
+      * \if german
+      * Ein zu sendender Index
+      * \elseif english
+      * An index to be sent
+      * \endif
+      */
+    int index;
+};
+
+#include "cdi/usb-hcd.h"
+
+struct cdi_usb_driver {
+    struct cdi_driver drv;
+
+    /**
+      * \if german
+      * Unterstuetzte Geschwindigkeiten
+      * \elseif english
+      * Supported speeds
+      * \endif
+      */
+    cdi_usb_speed_t speeds;
+
+    /**
+      * \if german
+      *
+      * Enumeriert ein USB-Geraet
+      *
+      * @param device Das zu enumerierende Geraet
+      *
+      * \elseif english
+      *
+      * Enumerates a USB device
+      *
+      * @param device The device to be enumerated
+      *
+      * \endif
+      */
+    void (*enumerate_device)(struct cdi_usb_device* device);
+
+    /**
+      * \if german
+      *
+      * 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)
+      *
+      * \elseif english
+      *
+      * Sends USB packets
+      *
+      * @param packets Array of packets to be sent
+      * @param num_packets Number of packets
+      *
+      * @return Returns the status (i. e. USB_NO_ERROR to indicate no error)
+      *
+      * \endif
+      */
+    cdi_usb_status_t (*send_packets)(struct cdi_usb_packet* packets,
+        size_t num_packets);
+
+    /**
+      * \if german
+      *
+      * 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.
+      *
+      * \elseif english
+      *
+      * Performs a control transfer
+      *
+      * @param device The destination device
+      * @param transfer A structure describing this transfer
+      *
+      * @return Returns a buffer containing the transferred data, in case of an
+      *         error the value is NULL and if there was no data, it returns
+      *         (void *)0xFFFFFFFF.
+      *
+      * \endif
+      */
+    void* (*do_control)(struct cdi_usb_device* device,
+        struct cdi_usb_control_transfer* transfer);
+
+    /*
+    // tyndurspezifisch
+    uintptr_t pointer_base;
+    uintptr_t real_enum_device;
+    pid_t pid;*/
+};
+
+/**
+  * \if german
+  * 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.
+  * \elseif english
+  * A USB device driver passes this structure to the OS so that a specific
+  * handler is called upon the detection of such a device. Each field either
+  * contains a number that has to be equal to that of the driver or -1, so that
+  * the field will be ignored.
+  * \endif
+  */
+struct cdi_usb_device_pattern {
+    int vendor_id;
+    int device_id;
+    int class_id;
+    int subclass_id;
+    int protocol_id;
+
+    /**
+      * \if german
+      *
+      * Ueberprueft das angegebene USB-Geraet
+      *
+      * @param device Das Geraet
+      *
+      * @return 0, wenn dieses Geraet nicht vom Treiber verarbeitet werden kann,
+      *         sonst 1
+      *
+      * \elseif english
+      *
+      * Checks the given USB device
+      *
+      * @param device The device
+      *
+      * @return 0 if the driver is unable to handle this device, else 1
+      *
+      * \endif
+      */
+    int (*take_usb_device)(struct cdi_usb_device* device);
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \if german
+ *
+ * Entfernt einen USB-Bustreiber
+ *
+ * @param driver Der Treiber
+ *
+ * \elseif english
+ *
+ * Removes a USB bus driver
+ *
+ * @param driver The driver
+ *
+ * \endif
+ */
+void cdi_usb_driver_destroy(struct cdi_usb_driver* driver);
+
+/**
+  * \if german
+  *
+  * Initialisiert einen USB-Bustreiber
+  *
+  * @param driver Der Treiber
+  *
+  * \elseif english
+  *
+  * Initializes a USB bus driver
+  *
+  * @param driver The driver
+  *
+  * \endif
+  */
+void cdi_usb_driver_init(struct cdi_usb_driver* driver);
+
+/**
+  * \if german
+  *
+  * Registriert einen USB-Bustreiber beim System
+  *
+  * @param driver Der Treiber
+  *
+  * \elseif english
+  *
+  * Registers a USB bus driver at the OS
+  *
+  * @param driver The driver
+  *
+  * \endif
+  */
+void cdi_usb_driver_register(struct cdi_usb_driver* driver);
+
+/**
+  * \if german
+  *
+  * Registriert ein gefundenes USB-Geraet beim Betriebssystem - diese Funktion
+  * wird z. B. vom Host-Controller-Treiber nach einem Aufruf von find_devices
+  * fuer jedes gefundene Geraet aufgerufen
+  *
+  * @param device Das zu registrierende Geraet
+  *
+  * \elseif english
+  *
+  * Registers a detected USB device at the OS - this function is called i. e. by
+  * the host controller driver after a find_devices call for every device found
+  *
+  * @param device The device to be registered
+  */
+void cdi_usb_device_init(struct cdi_usb_device* device);
+
+/**
+  * \if german
+  *
+  * Registriert ein Geraetemuster
+  *
+  * @param pattern Das Muster
+  *
+  * \elseif english
+  *
+  * Registers a device pattern
+  *
+  * @param pattern The pattern
+  *
+  * \endif
+  */
+void cdi_usb_register_device_pattern(struct cdi_usb_device_pattern* pattern);
+
+#ifdef __cplusplus
+} //extern "C"
+#endif
+
+#endif
diff --git a/src/modules/cdi/lib/cdi.c b/src/modules/cdi/lib/cdi.c
index b650a79..e3b10cc 100644
--- a/src/modules/cdi/lib/cdi.c
+++ b/src/modules/cdi/lib/cdi.c
@@ -21,6 +21,7 @@
 static list_t* drivers = NULL;
 
 static void cdi_destroy(void);
+void _init_usb_hcd(struct cdi_driver* drv);
 
 /**
  * Caches Synchronisieren
@@ -98,6 +99,10 @@ void cdi_run_drivers(void)
             }
         }
 
+        if (driver->type == CDI_USB_HCD) {
+            _init_usb_hcd(driver);
+        }
+
         if (driver->type != CDI_NETWORK) {
             init_service_register((char*) driver->name);
         }
diff --git a/src/modules/cdi/lib/mempool.c b/src/modules/cdi/lib/mempool.c
new file mode 100644
index 0000000..8a165db
--- /dev/null
+++ b/src/modules/cdi/lib/mempool.c
@@ -0,0 +1,109 @@
+/******************************************************************************
+* Copyright (c) 2009 Kevin Wolf                                              *
+*                                                                            *
+* Permission is hereby granted,  free of charge,  to any  person obtaining a *
+* copy of this software and associated documentation files (the "Software"), *
+* to deal in the Software without restriction,  including without limitation *
+* the rights to use,  copy, modify, merge, publish,  distribute, sublicense, *
+* and/or sell copies  of the  Software,  and to permit  persons to whom  the *
+* Software is furnished to do so, subject to the following conditions:       *
+*                                                                            *
+* The above copyright notice and this permission notice shall be included in *
+* all copies or substantial portions of the Software.                        *
+*                                                                            *
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
+* IMPLIED, INCLUDING  BUT NOT  LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
+* FITNESS FOR A PARTICULAR  PURPOSE AND  NONINFRINGEMENT.  IN NO EVENT SHALL *
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
+* LIABILITY,  WHETHER IN AN ACTION OF CONTRACT,  TORT OR OTHERWISE,  ARISING *
+* FROM,  OUT OF  OR IN CONNECTION  WITH THE  SOFTWARE  OR THE  USE OR  OTHER *
+* DEALINGS IN THE SOFTWARE.                                                  *
+*****************************************************************************/
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "cdi/mempool.h"
+#include "cdi/misc.h"
+
+struct free_object {
+    struct free_object* next;
+};
+
+struct mempool {
+    size_t pool_size;
+    size_t object_size;
+    size_t num_objects;
+
+    void* objects;
+    void* phys_objects;
+
+    struct free_object* first_free;
+};
+
+struct mempool* mempool_create(size_t pool_size, size_t object_size)
+{
+    struct mempool* pool = malloc(sizeof(*pool));
+    uintptr_t cur;
+    int i;
+    struct free_object** p;
+
+    pool->pool_size = pool_size;
+    pool->object_size = object_size;
+    pool->num_objects = pool_size / object_size;
+
+    // Wir brauchen auf jeden Fall Platz fuer die Freispeicherliste
+    if (object_size < sizeof(struct free_object)) {
+        goto fail;
+    }
+
+
+    // Speicher reservieren
+    // FIXME Das ist alles zusammenhaengend
+    if (cdi_alloc_phys_mem(pool_size, &pool->objects, &pool->phys_objects)) {
+        goto fail;
+    }
+
+    // Freie Objekte eintragen
+    cur = (uintptr_t) pool->objects;
+    p = &pool->first_free;
+    for (i = 0; i < (int)pool->num_objects; i++) {
+        *p = (struct free_object*) cur;
+        p = &((struct free_object*) cur)->next;
+        cur += object_size;
+    }
+    *p = NULL;
+
+    return pool;
+
+fail:
+        free(pool);
+    return NULL;
+}
+
+int mempool_get(struct mempool* pool, void** obj, uintptr_t* phys_obj)
+{
+    struct free_object* free = pool->first_free;
+
+    if (free == NULL) {
+        return -1;
+    }
+
+    pool->first_free = free->next;
+
+    *obj = free;
+    *phys_obj = (uintptr_t) pool->phys_objects +
+            (uintptr_t) free - (uintptr_t) pool->objects;
+
+    return 0;
+}
+
+int mempool_put(struct mempool* pool, void* obj)
+{
+    struct free_object* free = obj;
+
+    free->next = pool->first_free;
+    pool->first_free = free;
+
+    return 0;
+}
diff --git a/src/modules/cdi/lib/usb-hcd.c b/src/modules/cdi/lib/usb-hcd.c
new file mode 100644
index 0000000..cb8c5a6
--- /dev/null
+++ b/src/modules/cdi/lib/usb-hcd.c
@@ -0,0 +1,55 @@
+//#include "rpc.h"
+#include "stdio.h"
+//#include "unistd.h"
+
+#include "cdi/lists.h"
+#include "cdi/misc.h"
+#include "cdi/usb-hcd.h"
+
+//static int has_handler = 0;
+
+void register_usb_devices(cdi_list_t devices);
+
+void cdi_usb_hcd_init(struct cdi_usb_hcd* driver)
+{
+    driver->drv.type = CDI_USB_HCD;
+    cdi_driver_init((struct cdi_driver*) driver);
+}
+
+void cdi_usb_hcd_destroy(struct cdi_usb_hcd* driver)
+{
+    cdi_driver_destroy((struct cdi_driver*) driver);
+}
+
+/*static void rpc_pipe(pid_t pid, dword correlation_id, size_t data_size,
+    void* data)
+{
+    struct {
+        void (*call_address)(struct cdi_usb_device*);
+        struct cdi_usb_device dev_data;
+        struct cdi_usb_hc hc_data;
+        struct cdi_usb_endpoint ep0;
+    }* drv_dev = data;
+    struct cdi_usb_pipe ep0_pipe = {
+        .device = &drv_dev->dev_data,
+        .endpoint = &drv_dev->ep0,
+        .data_toggle = 0
+    };
+
+    drv_dev->dev_data.hc = &drv_dev->hc_data;
+    drv_dev->dev_data.ep0 = &ep0_pipe;
+    drv_dev->call_address(&drv_dev->dev_data);
+
+    rpc_send_dword_response(pid, correlation_id, 0);
+}*/
+
+void _init_usb_hcd(struct cdi_driver* drv)
+{
+    struct cdi_usb_hcd* driver = (struct cdi_usb_hcd*) drv;
+    struct cdi_usb_hc* hc;
+    int i;
+
+    for (i = 0; (hc = cdi_list_get(drv->devices, i)) != NULL; i++) {
+        driver->find_devices(hc);
+    }
+}
diff --git a/src/modules/cdi/lib/usb.c b/src/modules/cdi/lib/usb.c
new file mode 100644
index 0000000..a9f42e0
--- /dev/null
+++ b/src/modules/cdi/lib/usb.c
@@ -0,0 +1,425 @@
+//#include "init.h"
+//#include "rpc.h"
+#include "stdio.h"
+#include "stdlib.h"
+#include "string.h"
+//#include "syscall.h"
+//#include "unistd.h"
+
+#include "cdi/lists.h"
+#include "cdi/usb.h"
+
+static cdi_list_t queued_usb_devices = NULL;
+static cdi_list_t possible_usb_drivers = NULL;
+static cdi_list_t usb_bus_drivers = NULL;
+/*static struct cdi_usb_driver* bus_drivers = NULL;
+
+static pid_t service_usb = (pid_t)-1;
+static dword bus_drivers_shm_id = 0;
+static int has_handler = 0;
+static int has_parent_handler = 0;*/
+
+static char *class_name[] =
+{
+    "TSNH", //"This should never happen" - Von Composite Devices sollte einer
+            //der Interface-Class-Codes geliefert werden
+    "Audiogeraet",
+    "Kommunikationsgeraet",
+    "HID",
+    "???", //Hm, ja. Undefiniert.
+    "PID",
+    "Bildgeraet",
+    "Drucker",
+    "Massenspeicher",
+    "Hub",
+    "CDC-Datengeraet",
+    "Chipkarte",
+    "Sicherheitsgeraet",
+    "Videogeraet",
+    "Healthcare-Geraet"
+};
+
+/*static void dev_reset(struct cdi_usb_device* device)
+{
+    struct {
+        void (*call_address)(struct cdi_usb_device*);
+        struct cdi_usb_device dev_data;
+        int driver_index;
+    } drv_dev;
+
+    drv_dev.call_address = (void*) device->real_reset;
+    memcpy(&drv_dev.dev_data, device, sizeof(*device));
+    drv_dev.driver_index = ((uintptr_t)device->drv - (uintptr_t)bus_drivers) /
+        sizeof(struct cdi_usb_driver);
+
+    rpc_get_dword(device->ppid, "RESET", sizeof(drv_dev),
+        (char*) &drv_dev);
+}
+
+static void _add_pipe(struct cdi_usb_pipe* pipe)
+{
+    struct cdi_usb_hcd* hcd;
+    struct {
+        void (*call_address)(struct cdi_usb_device*);
+        struct cdi_usb_device dev_data;
+        struct cdi_usb_hc hc_data;
+        struct cdi_usb_endpoint ep0;
+    } drv_dev;
+
+    hcd = (struct cdi_usb_hcd*) pipe->device->hc->dev.driver;
+    drv_dev.call_address = (void*) hcd->real_add_pipe;
+    memcpy(&drv_dev.dev_data, pipe->device, sizeof(drv_dev.dev_data));
+    memcpy(&drv_dev.hc_data, pipe->device->hc, sizeof(drv_dev.hc_data));
+    memcpy(&drv_dev.ep0, pipe->endpoint, sizeof(drv_dev.ep0));
+
+    rpc_get_dword(hcd->pid, "ADD_PIPE", sizeof(drv_dev),
+        (char*) &drv_dev);
+}
+
+static void rpc_reset(pid_t pid, dword correlation_id, size_t data_size,
+    void* data)
+{
+    struct {
+        void (*call_address)(struct cdi_usb_device*);
+        struct cdi_usb_device dev_data;
+        int driver_index;
+    }* drv_dev = data;
+
+    drv_dev->dev_data.drv = &bus_drivers[drv_dev->driver_index];
+
+    drv_dev->call_address(&drv_dev->dev_data);
+
+    rpc_send_dword_response(pid, correlation_id, 0);
+}
+
+static void rpc_enum(pid_t pid, dword correlation_id, size_t data_size,
+    void* data)
+{
+    struct {
+        void (*call_address)(struct cdi_usb_device*);
+        struct cdi_usb_device dev_data;
+        struct cdi_usb_hc hc_data;
+        int driver_index;
+    }* drv_dev = data;
+
+    drv_dev->dev_data.drv = &bus_drivers[drv_dev->driver_index];
+    drv_dev->dev_data.hc = &drv_dev->hc_data;
+    drv_dev->dev_data.real_reset = (uintptr_t)drv_dev->dev_data.reset;
+    drv_dev->dev_data.reset = &dev_reset;
+
+    drv_dev->call_address(&drv_dev->dev_data);
+
+    rpc_send_dword_response(pid, correlation_id, 0);
+}*/
+
+void cdi_usb_driver_destroy(struct cdi_usb_driver* driver)
+{
+    cdi_driver_destroy((struct cdi_driver*) driver);
+}
+
+void cdi_usb_driver_init(struct cdi_usb_driver* driver)
+{
+    if (driver == NULL) {
+        return;
+    }
+
+    driver->drv.type = CDI_USB;
+    cdi_driver_init((struct cdi_driver*) driver);
+}
+
+void cdi_usb_driver_register(struct cdi_usb_driver* driver)
+{
+    /*int len = strlen(driver->drv.name) + 1, i;
+    int* heap, off;
+
+    if (service_usb == (pid_t)-1) {
+        service_usb = init_service_get("usb");
+    }
+
+    driver->pid = getpid();
+    if (!has_handler) {
+        register_message_handler("ENUM", &rpc_enum);
+        has_handler = 1;
+    }
+
+    if (!bus_drivers_shm_id) {
+        bus_drivers_shm_id = rpc_get_dword(service_usb, "USB_BUS_DRIVERS", 0,
+            NULL);
+        bus_drivers = open_shared_memory(bus_drivers_shm_id);
+    }
+
+    heap = (int*) ((uintptr_t)bus_drivers + 32768);
+    off = *heap;
+    *heap += len;
+    memcpy((void*) ((uintptr_t)bus_drivers + 32772 + off), driver->drv.name,
+        len);
+    driver->drv.name = (const char*) ((uintptr_t)bus_drivers + 32772 + off);
+    driver->pointer_base = (uintptr_t)bus_drivers;
+
+    for (i = 0; bus_drivers[i].drv.type; i++);
+
+    memcpy(&bus_drivers[i], driver, sizeof(*driver));*/
+
+    if (usb_bus_drivers == NULL) {
+        usb_bus_drivers = cdi_list_create();
+    }
+    cdi_list_push(usb_bus_drivers, driver);
+
+    cdi_driver_register((struct cdi_driver*) driver);
+}
+
+/*static void _enumerate(struct cdi_usb_device* device)
+{
+    struct {
+        uintptr_t call_address;
+        struct cdi_usb_device dev_data;
+        struct cdi_usb_hc hc_data;
+        int driver_index;
+    } drv_dev;
+
+    drv_dev.call_address = device->drv->real_enum_device;
+    drv_dev.driver_index = ((uintptr_t)device->drv - (uintptr_t)bus_drivers) /
+        sizeof(struct cdi_usb_driver);
+    memcpy(&drv_dev.dev_data, device, sizeof(*device));
+    memcpy(&drv_dev.hc_data, device->hc, sizeof(*device->hc));
+    rpc_get_dword(device->drv->pid, "ENUM", sizeof(drv_dev),
+        (char *)&drv_dev);
+}*/
+
+void cdi_usb_device_init(struct cdi_usb_device* device)
+{
+    size_t i;
+    struct cdi_usb_driver* drv;
+    struct cdi_usb_device_pattern* pos_drv;
+    struct cdi_usb_device_pattern* best_drv = NULL;
+    enum {
+        MATCH_NOTHING = 0,
+        MATCH_CLASS = 1,
+        MATCH_CLASS_VENDOR = 2,
+        MATCH_CLASS_SUBCLASS = 3,
+        MATCH_CLASS_SUBCLASS_VENDOR = 4,
+        MATCH_CLASS_SUBCLASS_PROTOCOL = 5,
+        MATCH_CLASS_SUBCLASS_PROTOCOL_VENDOR = 6,
+        MATCH_VENDOR_DEVICE = 7
+    } best_match;
+
+    if (queued_usb_devices == NULL) {
+        queued_usb_devices = cdi_list_create();
+    }
+
+    /*if (!has_parent_handler) {
+        register_message_handler("RESET", &rpc_reset);
+        has_parent_handler = 1;
+    }*/
+
+    printf("[cdi.usb] ");
+    switch (device->speed) {
+        case CDI_USB_LOW_SPEED:
+            printf("Low");
+            break;
+        case CDI_USB_FULL_SPEED:
+            printf("Full");
+            break;
+        case CDI_USB_HIGH_SPEED:
+            printf("High");
+            break;
+        case CDI_USB_SUPER_SPEED:
+            printf("Super");
+            break;
+    }
+//    device->ppid = getpid();
+    printf("-Speed-Geraet am Port %i (", device->port);
+    if (device->hub != NULL) {
+        printf("Hub %i) ", device->hub->id);
+    } else {
+        printf("HC %s) ", device->hc->dev.name);
+    }
+
+    /*
+    //if (service_usb == (pid_t)-1) {
+        service_usb = init_service_get("usb");
+    //}
+
+    if (!bus_drivers_shm_id) {
+        bus_drivers_shm_id = rpc_get_dword(service_usb, "USB_BUS_DRIVERS", 0,
+            NULL);
+        bus_drivers = open_shared_memory(bus_drivers_shm_id);
+    }
+    */
+
+    //for (i = 0; (drv = &bus_drivers[i])->drv.type; i++) {
+    for (i = 0; (drv = cdi_list_get(usb_bus_drivers, i)) != NULL; i++) {
+/*        drv->real_enum_device = (uintptr_t)drv->enumerate_device;
+        drv->enumerate_device = &_enumerate;*/
+
+        if (drv->speeds & device->speed) {
+            device->drv = drv;
+            /*printf("-> %s\n", (char*) ((uintptr_t)bus_drivers +
+                (uintptr_t)drv->drv.name - drv->pointer_base));*/
+            printf("-> %s\n", drv->drv.name);
+
+            drv->enumerate_device(device);
+
+            printf("[cdi.usb] ");
+            if (device->class_id < 0x10) {
+                printf("%s", class_name[device->class_id]);
+            } else {
+                switch (device->class_id) {
+                    case 0xDC:
+                        printf("Diagnosegeraet");
+                        break;
+                    case 0xE0:
+                        printf("Drahtloscontroller");
+                        break;
+                    case 0xEF:
+                        printf("Unbestimmtes Geraet");
+                        break;
+                    case 0xFE:
+                        printf("Softwarespezifisch");
+                        break;
+                    case 0xFF:
+                        printf("Herstellerspezifisch");
+                        break;
+                    default:
+                        printf("Unbekanntes Geraet");
+                }
+            }
+
+            printf(" %i@", device->id);
+            if (device->hub != NULL)
+                printf("%i", device->hub->id);
+            else
+                printf("%s:", device->hc->dev.name);
+            printf("/%i (%04X:%04X) - %02X/%02X/%02X\n", device->port,
+                device->vendor_id, device->device_id, device->class_id,
+                device->subclass_id, device->protocol_id);
+
+            best_match = MATCH_NOTHING;
+            if (possible_usb_drivers != NULL) {
+                for (i = 0; (pos_drv = cdi_list_get(possible_usb_drivers, i))
+                    != NULL; i++)
+                {
+                    if (pos_drv->vendor_id == device->vendor_id) {
+                        if (pos_drv->device_id == device->device_id) {
+                            best_match = MATCH_VENDOR_DEVICE;
+                            best_drv = pos_drv;
+                            break;
+                        } else if (pos_drv->device_id != -1) {
+                            continue;
+                        } else if (pos_drv->class_id == device->class_id) {
+                            if (pos_drv->subclass_id == device->subclass_id) {
+                                if (pos_drv->protocol_id ==
+                                    device->protocol_id)
+                                {
+                                    best_match =
+                                        MATCH_CLASS_SUBCLASS_PROTOCOL_VENDOR;
+                                    best_drv = pos_drv;
+                                    continue;
+                                } else if (pos_drv->protocol_id != -1) {
+                                    continue;
+                                }
+                                if (best_match < MATCH_CLASS_SUBCLASS_VENDOR) {
+                                    best_match = MATCH_CLASS_SUBCLASS_VENDOR;
+                                    best_drv = pos_drv;
+                                }
+                                continue;
+                            } else if (pos_drv->subclass_id != -1) {
+                                continue;
+                            }
+                            if (best_match < MATCH_CLASS_VENDOR) {
+                                best_match = MATCH_CLASS_VENDOR;
+                                best_drv = pos_drv;
+                            }
+                            continue;
+                        }
+                    } else if (pos_drv->vendor_id != -1) {
+                        continue;
+                    }
+                    if (pos_drv->class_id == device->class_id) {
+                        if (pos_drv->subclass_id == device->subclass_id) {
+                            if (pos_drv->protocol_id == device->protocol_id) {
+                                if (best_match < MATCH_CLASS_SUBCLASS_PROTOCOL)
+                                {
+                                    best_match = MATCH_CLASS_SUBCLASS_PROTOCOL;
+                                    best_drv = pos_drv;
+                                }
+                                continue;
+                            } else if (pos_drv->protocol_id != -1) {
+                                continue;
+                            }
+                            if (best_match < MATCH_CLASS_SUBCLASS) {
+                                best_match = MATCH_CLASS_SUBCLASS;
+                                best_drv = pos_drv;
+                            }
+                            continue;
+                        } else if (pos_drv->subclass_id != -1) {
+                            continue;
+                        }
+                        if (best_match < MATCH_CLASS) {
+                            best_match = MATCH_CLASS;
+                            best_drv = pos_drv;
+                        }
+                        continue;
+                    }
+                }
+            }
+
+            if ((best_match == MATCH_NOTHING) ||
+                !best_drv->take_usb_device(device))
+            {
+                printf("[cdi.usb] Derzeit kein passender USB-Geraetetreiber"
+                    "vorhanden...\n");
+                cdi_list_push(queued_usb_devices, device);
+            }
+
+            return;
+        }
+    }
+
+    printf("-> kein passender USB-Bustreiber.\n");
+}
+
+void cdi_usb_register_device_pattern(struct cdi_usb_device_pattern* pattern)
+{
+    struct cdi_usb_device* dev;
+    int i;
+
+    if (pattern == NULL) {
+        return;
+    }
+
+    if (possible_usb_drivers == NULL) {
+        possible_usb_drivers = cdi_list_create();
+    }
+
+    cdi_list_push(possible_usb_drivers, pattern);
+
+    for (i = 0; (dev = cdi_list_get(queued_usb_devices, i)) != NULL; i++) {
+        if ((pattern->vendor_id != dev->vendor_id) &&
+            (pattern->vendor_id != -1))
+        {
+            continue;
+        }
+        if ((pattern->device_id != dev->device_id) &&
+            (pattern->device_id != -1))
+        {
+            continue;
+        }
+        if ((pattern->class_id != dev->class_id) && (pattern->class_id != -1)) {
+            continue;
+        }
+        if ((pattern->subclass_id != dev->subclass_id) &&
+            (pattern->subclass_id != -1))
+        {
+            continue;
+        }
+        if ((pattern->protocol_id != dev->protocol_id) &&
+            (pattern->protocol_id != -1))
+        {
+            continue;
+        }
+        if (pattern->take_usb_device(dev)) {
+            cdi_list_remove(queued_usb_devices, i);
+        }
+    }
+}
-- 
1.6.4.2