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

[cdi-devel] [PATCH] Correct DATA0/DATA1 treatment and packet size



From: Max Reitz <max@xxxxxxxxxx>

+ The decision about the usage of DATA0 or DATA1
  is now made by usb_do_packet(), that is more
  standard compliant.
* You cannot send 512 byte packets to 64 byte
  endpoints, you have to send them in small 64
  byte packets. Because of that, you also have
  to fetch the first eight byte of the device
  descriptor before to know the size of EP0
  before you can fetch the whole descriptor.

Signed-off-by: Max Reitz <max@xxxxxxxxxx>
---
 usb/include/msd.h  |    2 +-
 usb/include/uhci.h |    2 +-
 usb/include/usb.h  |   10 +++---
 usb/main.c         |   85 +++++++++++++++++++++++++++++++++++++--------------
 usb/msd.c          |   41 +++++++++----------------
 usb/uhci.c         |   14 ++++-----
 6 files changed, 89 insertions(+), 65 deletions(-)

diff --git a/usb/include/msd.h b/usb/include/msd.h
index 1af55f3..9f40469 100644
--- a/usb/include/msd.h
+++ b/usb/include/msd.h
@@ -95,4 +95,4 @@ struct part_table_entry {
 #define MSC_CMD_READ12   0xA8
 #define MSC_CMD_WRITE12  0xAA
 
-#endif
\ No newline at end of file
+#endif
diff --git a/usb/include/uhci.h b/usb/include/uhci.h
index edb98db..240619b 100644
--- a/usb/include/uhci.h
+++ b/usb/include/uhci.h
@@ -103,4 +103,4 @@ struct transfer {
     volatile int error;
 };
 
-#endif
\ No newline at end of file
+#endif
diff --git a/usb/include/usb.h b/usb/include/usb.h
index 584f31f..a7aecd4 100644
--- a/usb/include/usb.h
+++ b/usb/include/usb.h
@@ -245,6 +245,7 @@ struct usb_device {
     int id;
     int port;
     int low_speed;
+    struct endpoint_desc* ep0;
     struct device_desc* device;
     struct config_desc* config;
     struct interface_desc* interface;
@@ -252,6 +253,7 @@ struct usb_device {
     int stalled;
     int locked;
     int expects;
+    int data_toggle;
 };
 
 struct msclass_data {
@@ -264,14 +266,12 @@ struct msclass_data {
 struct usb_packet {
     /// Der Typ des Pakets (PACKET_IN, PACKET_OUT, PACKET_SETUP)
     enum usb_packet_type type;
-    /// Der gewuenschte Endpoint (0 bis 15)
-    int endpoint;
+    /// Der gewuenschte Endpoint
+    struct endpoint_desc* endpoint;
     /// Die physische Adresse des zu verwendenden Datenpuffers
     uintptr_t phys_data;
     /// Die Laenge des Puffers
     int length;
-    /// Gibt an, ob DATA0 (0) oder DATA1 (1) verwendet werden soll
-    int datatoggle;
     /// Typ der Daten (zur Sicherheit, damit es kein doofes STALL gibt)
     int type_of_data;
 };
@@ -290,4 +290,4 @@ void init_msc_driver(void);
 void register_msd(struct usb_device* usbdev);
 void uhci_init(struct cdi_device* cdi_hci);
 
-#endif
\ No newline at end of file
+#endif
diff --git a/usb/main.c b/usb/main.c
index 9eb20d8..f2e957e 100644
--- a/usb/main.c
+++ b/usb/main.c
@@ -104,6 +104,7 @@ int usb_do_packet(struct usb_device* device, struct usb_packet* packet)
 {
     int error = USB_NAK;
     int tod_short, tod = packet->type_of_data;
+    int i = 0, mps;
 
     if (!(device->expects & tod)) {
         dprintf("0x%04X erwartet, 0x%04X bekommen...?\n", device->expects, tod);
@@ -117,23 +118,41 @@ int usb_do_packet(struct usb_device* device, struct usb_packet* packet)
     }
     //dprintf("TOD: %s\n", tod_name[tod_short]);
     device->expects = next_data_type[tod_short];
-    packet->endpoint &= 0x07;
     packet->type &= 0xFF;
     if (device->stalled) {
         //TODO: Irgendwie entstallen, evtl.? oO
         dprintf("Zugriff auf stalled-Gerät verweigert.\n");
         return USB_STALLED;
     }
-    while (error == USB_NAK) {
-        error = device->hci->do_packet(device, packet);
-        if (error == USB_NAK) {
-            cdi_sleep_ms(5);
+
+    struct usb_packet send_packet = {
+        .type      = packet->type,
+        .endpoint  = packet->endpoint,
+        .phys_data = packet->phys_data
+    };
+    mps = packet->endpoint->max_packet_size;
+
+    for (i = 0; (i < packet->length) || (!i && !packet->length); i += mps) {
+        send_packet.length =
+            (packet->length - i > mps) ? mps : (packet->length - i);
+        error = USB_NAK;
+        while (error == USB_NAK) {
+            error = device->hci->do_packet(device, &send_packet);
+            if (error == USB_NAK) {
+                cdi_sleep_ms(5);
+            }
+        }
+        device->data_toggle ^= 1;
+        send_packet.phys_data += mps;
+        if (error == USB_STALLED) {
+            printf("[usb] ENDPOINT %i DES GERÃ?TS %i STALLED!\n",
+                packet->endpoint->endpoint_address,
+                device->id);
+            for (;;) {
+            }
+            device->stalled = 1;
+            break;
         }
-    }
-    if (error == USB_STALLED) {
-        printf("[usb] ENDPOINT %i DES GERÃ?TS %i STALLED!\n", packet->endpoint,
-            device->id);
-        device->stalled = 1;
     }
     return error;
 }
@@ -170,14 +189,12 @@ static void* do_control(struct usb_device* device, int direction, void* buffer,
 
     struct usb_packet setup_packet = {
         .type         = PACKET_SETUP,
-        .endpoint     = 0,
+        .endpoint     = device->ep0,
         .phys_data    = psetup,
         .length       = sizeof(*setup),
-        .datatoggle   = 0,
         .type_of_data = USB_TOD_SETUP,
     };
 
-
     if (usb_do_packet(device, &setup_packet)) {
         return NULL;
     }
@@ -188,10 +205,9 @@ static void* do_control(struct usb_device* device, int direction, void* buffer,
     } else {
         struct usb_packet data_packet = {
             .type         = (direction == DEV_TO_HOST ? PACKET_IN : PACKET_OUT),
-            .endpoint     = 0,
+            .endpoint     = device->ep0,
             .phys_data    = pbuf,
             .length       = length,
-            .datatoggle   = 1,
             .type_of_data =
                 (direction ==
                  DEV_TO_HOST ? USB_TOD_SETUP_DATA_IN : USB_TOD_SETUP_DATA_OUT),
@@ -202,11 +218,11 @@ static void* do_control(struct usb_device* device, int direction, void* buffer,
 
     if (rval == USB_NO_ERROR) {
         struct usb_packet ack_packet = {
-            .endpoint   = 0,
+            .endpoint   = device->ep0,
             .phys_data  = 0,
             .length     = 0,
-            .datatoggle = 1,
         };
+        device->data_toggle = 1;
 
         if (no_data || (direction == HOST_TO_DEV)) {
             ack_packet.type = PACKET_IN;
@@ -305,24 +321,45 @@ static void enum_device(struct usb_device* usbdev)
     void* position;
     int i, id;
 
+    //Gerät und EP0 initialisieren
     usbdev->stalled = 0;
     usbdev->locked = 0;
     usbdev->expects = USB_TOD_SETUP | USB_TOD_COMMAND;
+    usbdev->data_toggle = 0;
+    usbdev->ep0 = malloc(sizeof(*usbdev->ep0));
+    usbdev->ep0->length = sizeof(*usbdev->ep0);
+    usbdev->ep0->descriptor_type = DESC_ENDPOINT;
+    usbdev->ep0->endpoint_address = 0;
+    usbdev->ep0->attributes = 0;
+    usbdev->ep0->max_packet_size = 8;
+    usbdev->ep0->interval = 0;
+
+    //Erste acht Bytes des Device-Descriptors abrufen und die maximale Paketgrö�e von EP0 feststellen
     dev_desc =
-        do_control(usbdev, DEV_TO_HOST, NULL, sizeof(*dev_desc), STD_REQUEST,
-            REC_DEVICE, GET_DESCRIPTOR, DESC_DEVICE << 8,
+        do_control(usbdev, DEV_TO_HOST, NULL, 8, STD_REQUEST, REC_DEVICE,
+            GET_DESCRIPTOR,
+            DESC_DEVICE << 8,
             0);
     if (dev_desc == NULL) {
         return;
     }
-    usbdev->device = dev_desc;
-    dprintf("0x%04X:0x%04X (%i) -> ", dev_desc->vendor_id, dev_desc->device_id,
-        dev_desc->class_id);
+    usbdev->ep0->max_packet_size = dev_desc->max_packet_size0;
+
+    //USB-Adresse zuweisen
     do_control(usbdev, HOST_TO_DEV | NO_DATA, NULL, 0, STD_REQUEST, REC_DEVICE,
         SET_ADDRESS, (id = usb_dev_ids++),
         0);
     usbdev->id = id;
-    _dprintf("%i\n", id);
+
+    dev_desc =
+        do_control(usbdev, DEV_TO_HOST, NULL, sizeof(*dev_desc), STD_REQUEST,
+            REC_DEVICE, GET_DESCRIPTOR, DESC_DEVICE << 8,
+            0);
+    usbdev->device = dev_desc;
+    dprintf("0x%04X:0x%04X (%i) -> %i\n", dev_desc->vendor_id,
+        dev_desc->device_id, dev_desc->class_id,
+        id);
+
     if (dev_desc->iManufacturer) {
         name =
             do_control(usbdev, DEV_TO_HOST, NULL, 64, STD_REQUEST, REC_DEVICE,
@@ -389,7 +426,7 @@ static void enum_device(struct usb_device* usbdev)
     }
     position = conf_desc;
     position += sizeof(struct config_desc);
-    best_if = position;         //Standard-IF
+    best_if = position; //Standard-IF
     for (i = 0; i < conf_desc->num_interfaces; i++) {
         if_desc = position;
         //TODO: Mehr Klassencodes natürlich!
diff --git a/usb/msd.c b/usb/msd.c
index 471856a..fcfb0a3 100644
--- a/usb/msd.c
+++ b/usb/msd.c
@@ -228,10 +228,9 @@ static int write_cmd(struct usb_device* usbdev, uintptr_t src)
     struct msclass_data* msc = (struct msclass_data*) usbdev->classd;
     struct usb_packet cmd_packet = {
         .type         = PACKET_OUT,
-        .endpoint     = msc->bulk_ep_out->endpoint_address,
+        .endpoint     = msc->bulk_ep_out,
         .phys_data    = src,
         .length       = 0x1F,
-        .datatoggle   = 0,
         .type_of_data = USB_TOD_COMMAND,
     };
 
@@ -262,10 +261,9 @@ static int read_status(struct usb_device* usbdev, uint32_t expected_tag)
 
     struct usb_packet status_packet = {
         .type         = PACKET_IN,
-        .endpoint     = msc->bulk_ep_in->endpoint_address,
+        .endpoint     = msc->bulk_ep_in,
         .phys_data    = pcsw,
         .length       = 0x0D,
-        .datatoggle   = 0,
         .type_of_data = USB_TOD_STATUS,
     };
 
@@ -277,7 +275,8 @@ static int read_status(struct usb_device* usbdev, uint32_t expected_tag)
         (csw->csw_tag != expected_tag) || csw->csw_status)
     {
         dprintf("0x%08X %i==%i 0x%08X\n", csw->csw_signature, csw->csw_tag,
-            expected_tag, csw->csw_status);
+            expected_tag,
+            csw->csw_status);
         return USB_STATUS_ERROR;
     }
 
@@ -323,10 +322,9 @@ static int msd_get_capacity(struct usb_device* usbdev, uint32_t* block_size,
 
     struct usb_packet in_packet = {
         .type         = PACKET_IN,
-        .endpoint     = msc->bulk_ep_in->endpoint_address,
+        .endpoint     = msc->bulk_ep_in,
         .phys_data    = pcap,
         .length       = sizeof(*cap),
-        .datatoggle   = 0,
         .type_of_data = USB_TOD_DATA_IN,
     };
 
@@ -443,7 +441,7 @@ static uint32_t msd_read(struct usb_device* usbdev, uint32_t lba,
     struct command_block_wrapper* cbw;
     uintptr_t pcbw;
     uint32_t expected_tag;
-    int error, i, ep_size;
+    int error;
 
     if (cdi_alloc_phys_mem(sizeof(struct command_block_wrapper), (void**) &cbw,
             (void**) &pcbw) == -1)
@@ -477,22 +475,15 @@ static uint32_t msd_read(struct usb_device* usbdev, uint32_t lba,
 
     struct usb_packet in_packet = {
         .type         = PACKET_IN,
-        .endpoint     = msc->bulk_ep_in->endpoint_address,
+        .endpoint     = msc->bulk_ep_in,
         .phys_data    = phys_buffer,
-        .length       = 0,
-        .datatoggle   = 0,
+        .length       = length,
         .type_of_data = USB_TOD_DATA_IN,
     };
 
-    ep_size = msc->bulk_ep_in->max_packet_size;
-    for (i = 0; i < length; i += ep_size) {
-        in_packet.length = (length - i > ep_size) ? ep_size : length - i;
-        error = usb_do_packet(usbdev, &in_packet);
-        if (error != USB_NO_ERROR) {
-            return error;
-        }
-        in_packet.phys_data += ep_size;
-        in_packet.datatoggle ^= 1;
+    error = usb_do_packet(usbdev, &in_packet);
+    if (error != USB_NO_ERROR) {
+        return error;
     }
 
     error = read_status(usbdev, expected_tag);
@@ -592,14 +583,12 @@ static uint32_t msd_write(struct usb_device* usbdev, uint32_t lba,
 
     struct usb_packet out_packet = {
         .type         = PACKET_OUT,
-        .endpoint     = msc->bulk_ep_out->endpoint_address,
+        .endpoint     = msc->bulk_ep_out,
         .phys_data    = phys_buffer,
         .length       = 0,
-        .datatoggle   = 0,
         .type_of_data = USB_TOD_DATA_OUT,
     };
 
-    //Transaktionen eintragen
     ep_size = msc->bulk_ep_out->max_packet_size;
     for (i = 0; i < length; i += ep_size) {
         out_packet.length = (length - i > ep_size) ? ep_size : length - i;
@@ -608,7 +597,6 @@ static uint32_t msd_write(struct usb_device* usbdev, uint32_t lba,
             return error;
         }
         out_packet.phys_data += ep_size;
-        out_packet.datatoggle ^= 1;
     }
 
     error = read_status(usbdev, expected_tag);
@@ -638,7 +626,7 @@ static void get_partitions(struct cdi_storage_device* cdistrg)
     dprintf("Partitionen auf %s:", cdistrg->dev.name);
     for (i = 0; i < 4; i++) {
         if (partition[i].type && partition[i].size &&
-            (partition[i].start + partition[i].size < cdistrg->block_count))
+            (partition[i].start + partition[i].size <= cdistrg->block_count))
         {
             cdimsd = malloc(sizeof(struct cdi_msd));
             if (cdimsd == NULL) {
@@ -653,7 +641,8 @@ static void get_partitions(struct cdi_storage_device* cdistrg)
                 break;
             }
             sprintf((char*) cdimsd->cdi_device.dev.name, "%sp%i",
-                cdistrg->dev.name, j++);
+                cdistrg->dev.name,
+                j++);
             cdimsd->cdi_device.block_size = base_cdimsd->cdi_device.block_size;
             cdimsd->cdi_device.block_count = partition[i].size;
             _dprintf(" %s", cdimsd->cdi_device.dev.name);
diff --git a/usb/uhci.c b/usb/uhci.c
index f0087f4..e300eb3 100644
--- a/usb/uhci.c
+++ b/usb/uhci.c
@@ -53,8 +53,7 @@ static struct cdi_driver cdi_driver;
 static cdi_list_t active_transfers;
 
 static void uhci_handler(struct cdi_device* dev);
-static int uhci_do_packet(struct usb_device* usbdev,
-    struct usb_packet* packet);
+static int uhci_do_packet(struct usb_device* usbdev, struct usb_packet* packet);
 static cdi_list_t get_devices(struct hci* gen_hci);
 static void activate_device(struct hci* gen_hci, struct usb_device* device);
 static int get_current_frame(struct hci* gen_hci);
@@ -216,8 +215,7 @@ static inline int tsl(volatile int* variable)
 
 static volatile int locked = 0;
 
-static int uhci_do_packet(struct usb_device* usbdev,
-    struct usb_packet* packet)
+static int uhci_do_packet(struct usb_device* usbdev, struct usb_packet* packet)
 {
     struct uhci* uhci = (struct uhci*) usbdev->hci;
     struct uhci_td* td;
@@ -243,18 +241,18 @@ static int uhci_do_packet(struct usb_device* usbdev,
         __asm__ __volatile__ ("hlt");
 #endif
     }
-    qh->next = 1;               //Invalid
+    qh->next = 1; //Invalid
     qh->transfer = ptd;
     memset(td, 0, sizeof(struct uhci_td));
-    td->next = 1;               //Invalid
+    td->next = 1; //Invalid
     td->active = 1;
     td->ioc = 1;
-    td->data_toggle = packet->datatoggle;
+    td->data_toggle = usbdev->data_toggle;
     td->low_speed = usbdev->low_speed;
     td->errors = 1;
     td->pid = packet->type;
     td->device = usbdev->id;
-    td->endpoint = packet->endpoint;
+    td->endpoint = packet->endpoint->endpoint_address & 0x07;
     td->maxlen = packet->length ? packet->length - 1 : 0x7FF;
     td->buffer = packet->phys_data;
     addr = malloc(sizeof(struct transfer));
-- 
1.6.3.3