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