[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[cdi-devel] [PATCH] usb: struct usb_packet
Als ersten Schritt zu einem netteren Interface nimmt usb_do_packet jetzt
statt einer endlosen Kette von Parametern jetzt eine struct, die ein
Paket beschreibt.
Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
---
usb/include/usb.h | 27 ++++++++++--
usb/main.c | 85 +++++++++++++++++++++++++--------------
usb/msd.c | 114 +++++++++++++++++++++++++++++++++++++++++-----------
3 files changed, 167 insertions(+), 59 deletions(-)
diff --git a/usb/include/usb.h b/usb/include/usb.h
index 2c435d8..cca698a 100644
--- a/usb/include/usb.h
+++ b/usb/include/usb.h
@@ -28,10 +28,11 @@
#include "cdi/misc.h"
#include "cdi/pci.h"
-
-#define PACKET_SETUP 0x2D
-#define PACKET_IN 0x69
-#define PACKET_OUT 0xE1
+enum usb_packet_type {
+ PACKET_SETUP = 0x2D,
+ PACKET_IN = 0x69,
+ PACKET_OUT = 0xE1,
+};
#define NO_DATA 0x01
#define DEV_TO_HOST 0x80
@@ -270,6 +271,22 @@ struct msclass_data
struct endpoint_desc *bulk_ep_out;
};
+/** Beschreibt ein USB-Paket */
+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;
+ /// 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;
+};
+
#include "uhci.h"
@@ -277,7 +294,7 @@ struct msclass_data
#define HCI_STRUCT_SIZE sizeof(struct uhci)
-int do_packet(struct usb_device *device, int type, int endpoint, uintptr_t phys_data, int length, int datatoggle, int type_of_data);
+int usb_do_packet(struct usb_device *device, struct usb_packet* packet);
void enumerate_hci(struct hci *);
struct cdi_driver *init_uhcd(void);
void init_msc_driver(void);
diff --git a/usb/main.c b/usb/main.c
index c06f15d..92a7096 100644
--- a/usb/main.c
+++ b/usb/main.c
@@ -97,44 +97,41 @@ static const int next_data_type[9] = {
* Verarbeitet ein USB-Paket.
*
* @param device Das USB-Gerät
-* @param type Der Typ des Pakets (PACKET_IN, PACKET_OUT, PACKET_SETUP)
-* @param endpoint Der gewünschte Endpoint (0 bis 15)
-* @param phys_data Die physische Adresse des zu verwendenden Datenpuffers
-* @param length Die Länge des Puffers
-* @param datatoggle Gibt an, ob DATA0 (0) oder DATA1 (1) verwendet werden soll
-* @param type_of_data Typ der Daten (zur Sicherheit, damit es kein doofes STALL gibt)
*/
-int do_packet(struct usb_device *device, int type, int endpoint, uintptr_t phys_data, int length, int datatoggle, int type_of_data)
+int usb_do_packet(struct usb_device *device, struct usb_packet* packet)
{
int error;
int tod_short;
- if (!(device->expects & type_of_data)) {
- dprintf("Expected 0x%04X, got 0x%04X...?\n", device->expects, type_of_data);
+ if (!(device->expects & packet->type_of_data)) {
+ dprintf("Expected 0x%04X, got 0x%04X...?\n", device->expects,
+ packet->type_of_data);
+ // FIXME Das ist keine elegante Loesung des Problems
for (;;);
}
- type_of_data >>= 1;
- for (tod_short = 0; type_of_data; tod_short++) {
- type_of_data >>= 1;
+ packet->type_of_data >>= 1;
+ for (tod_short = 0; packet->type_of_data; tod_short++) {
+ packet->type_of_data >>= 1;
}
//dprintf("TOD: %s\n", tod_name[tod_short]);
device->expects = next_data_type[tod_short];
- endpoint &= 0x07;
- type &= 0xFF;
+ 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;
}
error = device->hci->do_packet(device->hci,
- (device->hci->get_frame(device->hci) + 3) & 0x3FF,
- type, device->id, endpoint,
- device->low_speed, phys_data, length,
- datatoggle);
+ (device->hci->get_frame(device->hci) + 3) & 0x3FF,
+ packet->type, device->id, packet->endpoint,
+ device->low_speed, packet->phys_data, packet->length,
+ packet->datatoggle);
if (error == USB_STALLED)
{
- printf("[usb] ENDPOINT %i DES GERÃ?TS %i STALLED!\n", endpoint, device->id);
+ printf("[usb] ENDPOINT %i DES GERÃ?TS %i STALLED!\n",
+ packet->endpoint, device->id);
device->stalled = 1;
}
return error;
@@ -164,10 +161,21 @@ static void *do_control(struct usb_device *device, int direction, void *buffer,
setup->value = value;
setup->index = index;
setup->length = length;
- if (do_packet(device, PACKET_SETUP, 0, psetup, sizeof(struct setup_packet),
- 0, USB_TOD_SETUP) != USB_NO_ERROR) {
+
+ struct usb_packet setup_packet = {
+ .type = PACKET_SETUP,
+ .endpoint = 0,
+ .phys_data = psetup,
+ .length = sizeof(*setup),
+ .datatoggle = 0,
+ .type_of_data = USB_TOD_SETUP,
+ };
+
+
+ if (usb_do_packet(device, &setup_packet)) {
return NULL;
}
+
cdi_sleep_ms(20);
if (no_data)
{
@@ -176,22 +184,39 @@ static void *do_control(struct usb_device *device, int direction, void *buffer,
}
else
{
- if (direction == DEV_TO_HOST) {
- rval = do_packet(device, PACKET_IN, 0, pbuf, length, 1,
- USB_TOD_SETUP_DATA_IN);
- } else {
- rval = do_packet(device, PACKET_OUT, 0, pbuf, length, 1,
- USB_TOD_SETUP_DATA_OUT);
- }
+ struct usb_packet data_packet = {
+ .type = PACKET_IN,
+ .endpoint = 0,
+ .phys_data = pbuf,
+ .length = length,
+ .datatoggle = 1,
+ .type_of_data = (direction == DEV_TO_HOST ?
+ USB_TOD_SETUP_DATA_IN : USB_TOD_SETUP_DATA_OUT),
+ };
+
+ rval = usb_do_packet(device, &data_packet);
}
+
if (rval == USB_NO_ERROR)
{
+ struct usb_packet ack_packet = {
+ .endpoint = 0,
+ .phys_data = 0,
+ .length = 0,
+ .datatoggle = 1,
+ };
+
cdi_sleep_ms(20);
+
if (no_data || (direction == HOST_TO_DEV)) {
- rval = do_packet(device, PACKET_IN, 0, 0, 0, 1, USB_TOD_SETUP_ACK_IN);
+ ack_packet.type = PACKET_IN;
+ ack_packet.type_of_data = USB_TOD_SETUP_ACK_IN;
} else {
- rval = do_packet(device, PACKET_OUT, 0, 0, 0, 1, USB_TOD_SETUP_ACK_OUT);
+ ack_packet.type = PACKET_OUT;
+ ack_packet.type_of_data = USB_TOD_SETUP_ACK_OUT;
}
+
+ rval = usb_do_packet(device, &ack_packet);
}
return (rval == USB_NO_ERROR) ? rbuf : NULL;
}
diff --git a/usb/msd.c b/usb/msd.c
index 11fbd6a..0f9b79e 100644
--- a/usb/msd.c
+++ b/usb/msd.c
@@ -187,7 +187,7 @@ void register_msd(struct usb_device *usbdev)
strgdev->block_count = bc;
size = bs;
size *= bc;
- dprintf("%s: %i * %i B (ca. %i MB).\n", strgdev->dev.name, bc, bs, size >> 20);
+ dprintf("%s: %i * %i B (ca. %lld MB).\n", strgdev->dev.name, bc, bs, size >> 20);
}
cdi_storage_device_init(strgdev);
cdi_list_push(cdi_driver.drv.devices, strgdev);
@@ -210,6 +210,36 @@ static void deinit_msd(struct cdi_device *cdi_msd)
//TODO: Und gerade hier...
}
+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,
+ .phys_data = src,
+ .length = 0x1F,
+ .datatoggle = 0,
+ .type_of_data = USB_TOD_COMMAND,
+ };
+
+ return usb_do_packet(usbdev, &cmd_packet);
+}
+
+static int read_status(struct usb_device* usbdev, uintptr_t dest)
+{
+ struct msclass_data *msc = (struct msclass_data*) usbdev->classd;
+ struct usb_packet status_packet = {
+ .type = PACKET_IN,
+ .endpoint = msc->bulk_ep_in->endpoint_address,
+ .phys_data = dest,
+ .length = 0x0D,
+ .datatoggle = 0,
+ .type_of_data = USB_TOD_STATUS,
+ };
+
+ return usb_do_packet(usbdev, &status_packet);
+}
+
static int msd_get_capacity(struct usb_device *usbdev, uint32_t *block_size, uint32_t *block_count)
{
struct msclass_data *msc;
@@ -244,29 +274,43 @@ static int msd_get_capacity(struct usb_device *usbdev, uint32_t *block_size, uin
cbw->cbw_cb_length = 12;
cbw->cbw_cb[0] = MSC_CMD_CAPACITY;
cbw->cbw_cb[1] = 0; //LUN: 0
- if (do_packet(usbdev, PACKET_OUT, msc->bulk_ep_out->endpoint_address, pcbw,
- 0x1F, 0, USB_TOD_COMMAND) != USB_NO_ERROR) {
+
+ if (write_cmd(usbdev, pcbw) != USB_NO_ERROR) {
return 0;
}
+
cdi_sleep_ms(20);
- if (do_packet(usbdev, PACKET_IN, msc->bulk_ep_in->endpoint_address, pcap,
- sizeof(struct msd_capacity), 0, USB_TOD_DATA_IN)
- != USB_NO_ERROR) {
+
+ struct usb_packet in_packet = {
+ .type = PACKET_IN,
+ .endpoint = msc->bulk_ep_in->endpoint_address,
+ .phys_data = pcap,
+ .length = sizeof(*cap),
+ .datatoggle = 0,
+ .type_of_data = USB_TOD_DATA_IN,
+ };
+
+ if (usb_do_packet(usbdev, &in_packet) != USB_NO_ERROR) {
return 0;
}
+
cdi_sleep_ms(5);
- if (do_packet(usbdev, PACKET_IN, msc->bulk_ep_in->endpoint_address, pcsw,
- 0x0D, 0, USB_TOD_STATUS) != USB_NO_ERROR) {
+
+ if (read_status(usbdev, pcsw) != USB_NO_ERROR) {
return 0;
}
+
cdi_sleep_ms(5);
+
if ((csw->csw_signature != CSW_SIGNATURE) ||
(csw->csw_tag != expected_tag) ||
csw->csw_status) {
return 0;
}
+
*block_size = BE2CPU(cap->block_length);
*block_count = BE2CPU(cap->last_lba) + 1;
+
return 1;
}
@@ -295,21 +339,23 @@ static int msd_ready(struct usb_device *usbdev)
cbw->cbw_flags = 0x80; //IN
cbw->cbw_lun = 0; //Was weiÃ? ich, wie viele LUNs datt Dingens hat?
cbw->cbw_cb_length = 12; //Alles null, also "Test unit ready"
- if (do_packet(usbdev, PACKET_OUT, msc->bulk_ep_out->endpoint_address, pcbw,
- 0x1F, 0, USB_TOD_COMMAND) != USB_NO_ERROR) {
+
+ if (write_cmd(usbdev, pcbw) != USB_NO_ERROR) {
return 0;
}
+
cdi_sleep_ms(7);
- if (do_packet(usbdev, PACKET_IN, msc->bulk_ep_in->endpoint_address, pcsw,
- 0x0D, 0, USB_TOD_STATUS) != USB_NO_ERROR) {
+ if (read_status(usbdev, pcsw) != USB_NO_ERROR) {
return 0;
}
+
cdi_sleep_ms(4);
if ((csw->csw_signature != CSW_SIGNATURE) ||
(csw->csw_tag != expected_tag) ||
csw->csw_status) {
return 0;
}
+
return 1;
}
#endif
@@ -409,23 +455,33 @@ static uint32_t msd_read(struct usb_device *usbdev, uint32_t lba, uint16_t secto
cbw->cbw_cb[5] = lba & 0x000000FF;
cbw->cbw_cb[7] = (sectors & 0x0000FF00) >> 8;
cbw->cbw_cb[8] = sectors & 0x000000FF;
- error = do_packet(usbdev, PACKET_OUT, msc->bulk_ep_out->endpoint_address,
- pcbw, 0x1F, 0, USB_TOD_COMMAND);
+
+ error = write_cmd(usbdev, pcbw);
if (error != USB_NO_ERROR) {
return error;
}
cdi_sleep_ms(20);
- error = do_packet(usbdev, PACKET_IN, msc->bulk_ep_in->endpoint_address,
- phys_buffer, length, 0, USB_TOD_DATA_IN);
+
+ struct usb_packet in_packet = {
+ .type = PACKET_IN,
+ .endpoint = msc->bulk_ep_in->endpoint_address,
+ .phys_data = phys_buffer,
+ .length = length,
+ .datatoggle = 0,
+ .type_of_data = USB_TOD_DATA_IN,
+ };
+
+ error = usb_do_packet(usbdev, &in_packet);
if (error != USB_NO_ERROR) {
return error;
}
cdi_sleep_ms(5);
- error = do_packet(usbdev, PACKET_IN, msc->bulk_ep_in->endpoint_address,
- pcsw, 0x0D, 0, USB_TOD_STATUS);
+
+ error = read_status(usbdev, pcsw);
if (error != USB_NO_ERROR) {
return error;
}
+
cdi_sleep_ms(4);
if ((csw->csw_signature != CSW_SIGNATURE) ||
(csw->csw_tag != expected_tag) ||
@@ -522,23 +578,33 @@ static uint32_t msd_write(struct usb_device *usbdev, uint32_t lba, uint16_t sect
cbw->cbw_cb[5] = lba & 0x000000FF;
cbw->cbw_cb[7] = (sectors & 0x0000FF00) >> 8;
cbw->cbw_cb[8] = sectors & 0x000000FF;
- error = do_packet(usbdev, PACKET_OUT, msc->bulk_ep_out->endpoint_address,
- pcbw, 0x1F, 0, USB_TOD_COMMAND);
+
+ error = write_cmd(usbdev, pcbw);
if (error != USB_NO_ERROR) {
return error;
}
cdi_sleep_ms(20);
- error = do_packet(usbdev, PACKET_OUT, msc->bulk_ep_out->endpoint_address,
- phys_buffer, length, 0, USB_TOD_DATA_OUT);
+
+ struct usb_packet out_packet = {
+ .type = PACKET_OUT,
+ .endpoint = msc->bulk_ep_out->endpoint_address,
+ .phys_data = phys_buffer,
+ .length = length,
+ .datatoggle = 0,
+ .type_of_data = USB_TOD_DATA_OUT,
+ };
+
+ error = usb_do_packet(usbdev, &out_packet);
if (error != USB_NO_ERROR) {
return error;
}
+
cdi_sleep_ms(5);
- error = do_packet(usbdev, PACKET_IN, msc->bulk_ep_in->endpoint_address,
- pcsw, 0x0D, 0, USB_TOD_STATUS);
+ error = read_status(usbdev, pcsw);
if (error != USB_NO_ERROR) {
return error;
}
+
cdi_sleep_ms(4);
if ((csw->csw_signature != CSW_SIGNATURE) ||
(csw->csw_tag != expected_tag) ||
--
1.6.0.2