[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[cdi-devel] [PATCH] Double reset on enum, no toggle change on error
From: Max Reitz <max@xxxxxxxxxx>
* Reset is needed two times on device enumeration (before reading the
first eight bytes of the device descriptor and afterwards).
* DATA0/DATA1 toggle bit may not be changed if an error occured.
Signed-off-by: Max Reitz <max@xxxxxxxxxx>
---
usb/include/usb.h | 2 +
usb/main.c | 37 ++++++++++++++++++++---------
usb/msd.c | 66 +++++++++++++++++++++++++---------------------------
usb/uhci.c | 17 ++++++++++++-
4 files changed, 74 insertions(+), 48 deletions(-)
diff --git a/usb/include/usb.h b/usb/include/usb.h
index 0fc6567..9a94b2e 100644
--- a/usb/include/usb.h
+++ b/usb/include/usb.h
@@ -242,6 +242,7 @@ struct class_data {
struct usb_device {
struct hci* hci;
+ struct usb_device* hub;
int id;
int port;
int low_speed;
@@ -254,6 +255,7 @@ struct usb_device {
int locked;
int expects;
int data_toggle;
+ void (* reset)(struct usb_device* device);
};
struct msclass_data {
diff --git a/usb/main.c b/usb/main.c
index abfb936..7250092 100644
--- a/usb/main.c
+++ b/usb/main.c
@@ -142,8 +142,12 @@ int usb_do_packet(struct usb_device* device, struct usb_packet* packet)
cdi_sleep_ms(5);
}
}
- device->data_toggle ^= 1;
- send_packet.data += mps;
+ if (error != USB_NO_ERROR) {
+ i -= mps;
+ } else {
+ device->data_toggle ^= 1;
+ send_packet.data += mps;
+ }
if (error == USB_STALLED) {
printf("[usb] ENDPOINT %i DES GERÃ?TS %i STALLED!\n",
packet->endpoint->endpoint_address,
@@ -167,11 +171,9 @@ static void* do_control(struct usb_device* device, int direction, void* buffer,
no_data = direction & NO_DATA;
direction &= 0x80;
-
if ((direction != HOST_TO_DEV) || !length || (buffer == NULL)) {
buffer = malloc(length);
}
-
setup->request_type = direction | (rtype & 0x60) | (recipient & 0x1F);
setup->request = request;
setup->value = value;
@@ -192,7 +194,7 @@ static void* do_control(struct usb_device* device, int direction, void* buffer,
if (no_data) {
rval = USB_NO_ERROR;
- buffer = (void*) 0xFFFFFFFF; //Kein Fehler, aber auch keine Daten
+ buffer = (void*) 0xFFFFFFFF; //Kein Fehler, aber auch keine Daten
} else {
struct usb_packet data_packet = {
.type = (direction == DEV_TO_HOST ? PACKET_IN : PACKET_OUT),
@@ -225,7 +227,7 @@ static void* do_control(struct usb_device* device, int direction, void* buffer,
rval = usb_do_packet(device, &ack_packet);
}
- return (rval == USB_NO_ERROR) ? buffer: NULL;
+ return (rval == USB_NO_ERROR) ? buffer : NULL;
}
static void usb_init(void)
@@ -325,6 +327,9 @@ static void enum_device(struct usb_device* usbdev)
usbdev->ep0->max_packet_size = 8;
usbdev->ep0->interval = 0;
+ //Resetten
+ usbdev->reset(usbdev);
+
//Erste acht Bytes des Device-Descriptors abrufen und die maximale Paketgrö�e von EP0 feststellen
dev_desc =
do_control(usbdev, DEV_TO_HOST, NULL, 8, STD_REQUEST, REC_DEVICE,
@@ -336,12 +341,16 @@ static void enum_device(struct usb_device* usbdev)
}
usbdev->ep0->max_packet_size = dev_desc->max_packet_size0;
+ //Nochmals resetten
+ usbdev->reset(usbdev);
+
//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;
+ //Den ganzen Device-Descriptor einlesen
dev_desc =
do_control(usbdev, DEV_TO_HOST, NULL, sizeof(*dev_desc), STD_REQUEST,
REC_DEVICE, GET_DESCRIPTOR, DESC_DEVICE << 8,
@@ -454,6 +463,14 @@ static void enum_device(struct usb_device* usbdev)
}
}
+static void reset_hub_device(struct usb_device* usbdev)
+{
+ do_control(usbdev->hub, HOST_TO_DEV, NULL, 0, CLS_REQUEST, REC_OTHER,
+ SET_FEATURE, PORTF_RESET,
+ usbdev->port + 1);
+ cdi_sleep_ms(20);
+}
+
static void enumerate_hub(struct usb_device* usbdev)
{
struct hub_desc* hub_desc;
@@ -481,17 +498,13 @@ static void enumerate_hub(struct usb_device* usbdev)
SET_FEATURE, PORTF_POWER,
i + 1);
cdi_sleep_ms(hub_desc->pwron2pwrgood * 2);
- //Resetten
- do_control(usbdev, HOST_TO_DEV, NULL, 0, CLS_REQUEST, REC_OTHER,
- SET_FEATURE, PORTF_RESET,
- i + 1);
- //Reset sollte jetzt eigtl. schon beendet sein
- //(do_control wartet ja 50 ms)
down = malloc(sizeof(struct usb_device));
down->hci = usbdev->hci;
+ down->hub = usbdev;
down->id = 0;
down->port = i;
down->low_speed = (port_status[0] & PORT_LOWSPEED) && 1;
+ down->reset = &reset_hub_device;
enum_device(down);
}
}
diff --git a/usb/msd.c b/usb/msd.c
index 9d843bf..6fb8a42 100644
--- a/usb/msd.c
+++ b/usb/msd.c
@@ -367,10 +367,12 @@ static inline int tsl(volatile int* variable)
}
static uint32_t msd_read(struct usb_device* usbdev, uint32_t lba,
- uint16_t sectors, void* buffer, size_t length);
+ uint16_t sectors, void* buffer,
+ size_t length);
static int msd_cdi_read(struct cdi_storage_device* strgdev, uint64_t start,
- uint64_t count, void* buffer)
+ uint64_t count,
+ void* buffer)
{
int bs = strgdev->block_size, error;
#ifdef WAIT_FOR_MSD_READY
@@ -394,7 +396,6 @@ static int msd_cdi_read(struct cdi_storage_device* strgdev, uint64_t start,
for (i = 0; !msd_ready(usbdev) && (i < 10); i++) {
cdi_sleep_ms(20);
}
-
#endif
error = msd_read(usbdev, start, count, buffer, count * bs);
if (error != USB_NO_ERROR) {
@@ -407,7 +408,8 @@ static int msd_cdi_read(struct cdi_storage_device* strgdev, uint64_t start,
}
static uint32_t msd_read(struct usb_device* usbdev, uint32_t lba,
- uint16_t sectors, void* buffer, size_t length)
+ uint16_t sectors, void* buffer,
+ size_t length)
{
struct msclass_data* msc;
struct command_block_wrapper _cbw;
@@ -415,10 +417,9 @@ static uint32_t msd_read(struct usb_device* usbdev, uint32_t lba,
uint32_t expected_tag;
int error;
- if (!buffer || !length) {
+ if ((buffer == NULL) || !length) {
return USB_TRIVIAL_ERROR;
}
-
msc = (struct msclass_data*) usbdev->classd;
memset(cbw, 0, 0x1F);
cbw->cbw_signature = CBW_SIGNATURE;
@@ -463,57 +464,59 @@ static uint32_t msd_read(struct usb_device* usbdev, uint32_t lba,
}
static uint32_t msd_write(struct usb_device* usbdev, uint32_t lba,
- uint16_t sectors, void* buffer, size_t length);
+ uint16_t sectors, void* buffer,
+ size_t length);
static int msd_cdi_write(struct cdi_storage_device* strgdev, uint64_t start,
- uint64_t count, void* buffer)
+ uint64_t count,
+ void* buffer)
{
int bs = strgdev->block_size, error;
#ifdef WAIT_FOR_MSD_READY
- int j;
+ int i;
#endif
- uint32_t i;
struct usb_device* usbdev = ((struct cdi_msd*) strgdev)->usb_device;
fdprintf("write(%i, %i)\n", (int) start, (int) count);
start += ((struct cdi_msd*) strgdev)->offset;
+ if (!count) {
+ dprintf("Leere Schreibanfrage.\n");
+ return 0;
+ }
while (tsl(&usbdev->locked)) {
#ifndef CDI_STANDALONE
__asm__ __volatile__ ("hlt");
#endif
}
- for (i = 0; i < count; i++) {
#ifdef WAIT_FOR_MSD_READY
- for (j = 0; !msd_ready(usbdev) && (j < 10); j++) {
- cdi_sleep_ms(20);
- }
-
+ for (i = 0; !msd_ready(usbdev) && (i < 10); i++) {
+ cdi_sleep_ms(20);
+ }
#endif
- error = msd_write(usbdev, start + i, 1, buffer + i * bs, bs);
- if (error != USB_NO_ERROR) {
- dprintf("Schreibfehler 0x%X bei Block %i.\n", error, i);
- usbdev->locked = 0;
- return -1;
- }
+ error = msd_write(usbdev, start, count, buffer, count * bs);
+ if (error != USB_NO_ERROR) {
+ dprintf("Schreibfehler 0x%X bei Block %i.\n", error, start);
+ usbdev->locked = 0;
+ return -1;
}
usbdev->locked = 0;
return 0;
}
static uint32_t msd_write(struct usb_device* usbdev, uint32_t lba,
- uint16_t sectors, void* buffer, size_t length)
+ uint16_t sectors, void* buffer,
+ size_t length)
{
struct msclass_data* msc;
struct command_block_wrapper _cbw;
struct command_block_wrapper* cbw = &_cbw;
uint32_t expected_tag;
- int error, i, ep_size;
+ int error;
- if (!buffer || !length) {
+ if ((buffer == NULL) || !length) {
return USB_TRIVIAL_ERROR;
}
-
msc = (struct msclass_data*) usbdev->classd;
memset(cbw, 0, 0x1F);
cbw->cbw_signature = CBW_SIGNATURE;
@@ -540,18 +543,13 @@ static uint32_t msd_write(struct usb_device* usbdev, uint32_t lba,
.type = PACKET_OUT,
.endpoint = msc->bulk_ep_out,
.data = buffer,
- .length = 0,
+ .length = length,
.type_of_data = USB_TOD_DATA_OUT,
};
- 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;
- error = usb_do_packet(usbdev, &out_packet);
- if (error != USB_NO_ERROR) {
- return error;
- }
- out_packet.data += ep_size;
+ error = usb_do_packet(usbdev, &out_packet);
+ if (error != USB_NO_ERROR) {
+ return error;
}
error = read_status(usbdev, expected_tag);
diff --git a/usb/uhci.c b/usb/uhci.c
index 03ad4c6..d302364 100644
--- a/usb/uhci.c
+++ b/usb/uhci.c
@@ -59,6 +59,7 @@ static void activate_device(struct hci* gen_hci, struct usb_device* device);
static int get_current_frame(struct hci* gen_hci);
static void uhci_deinit(struct cdi_device* cdi_hci);
static void uhci_kill(struct cdi_driver* cdi_hcd);
+static void uhci_reset_device(struct usb_device* device);
struct cdi_driver* init_uhcd()
@@ -184,19 +185,29 @@ static cdi_list_t get_devices(struct hci* gen_hci)
dev->port = i;
dev->low_speed =
(cdi_inw(uhci->pbase + UHCI_RPORTS + 2 * i) & RPORT_LOSPD) && 1;
+ dev->reset = &uhci_reset_device;
cdi_list_push(dlist, dev);
}
_dprintf("\n");
return dlist;
}
+static void uhci_reset_device(struct usb_device* device)
+{
+ struct uhci* uhci = (struct uhci*) device->hci;
+
+ cdi_outw(uhci->pbase + UHCI_RPORTS + 2 * device->port,
+ RPORT_ENABLE | RPORT_RESET | RPORT_CSC);
+ cdi_sleep_ms(20);
+}
+
static void activate_device(struct hci* gen_hci, struct usb_device* device)
{
struct uhci* uhci = (struct uhci*) gen_hci;
dprintf("Gerät an Port %i wird aktiviert.\n", device->port);
cdi_outw(uhci->pbase + UHCI_RPORTS + 2 * device->port,
- RPORT_RESET | RPORT_ENABLE | RPORT_CSC);
+ RPORT_ENABLE | RPORT_CSC);
cdi_sleep_ms(20);
}
@@ -243,7 +254,9 @@ static int uhci_do_packet(struct usb_device* usbdev, struct usb_packet* packet)
data = NULL;
phys_data = 0;
} else {
- if (cdi_alloc_phys_mem(packet->length, &data, (void**) &phys_data) == -1) {
+ if (cdi_alloc_phys_mem(packet->length, &data,
+ (void**) &phys_data) == -1)
+ {
return USB_TRIVIAL_ERROR;
}
if (packet->type != PACKET_IN) {
--
1.6.3.3