[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