Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adapt USB stack to work on ia32 #34

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions libusb/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,33 @@ static struct {
} usbdrv_common;


static void usb_hostLookup(oid_t *oid)
{
int ret;

for (;;) {
ret = lookup("devfs/usb", NULL, oid);
if (ret >= 0) {
break;
}

ret = lookup("/dev/usb", NULL, oid);
if (ret >= 0) {
break;
}

usleep(1000000);
}
}


int usb_connect(const usb_device_id_t *filters, int nfilters, unsigned drvport)
{
msg_t msg = { 0 };
usb_msg_t *umsg = (usb_msg_t *)&msg.i.raw;
oid_t oid;

while (lookup("/dev/usb", NULL, &oid) < 0)
usleep(1000000);
usb_hostLookup(&oid);

msg.type = mtDevCtl;
msg.i.size = sizeof(*filters) * nfilters;
Expand Down
1 change: 1 addition & 0 deletions libusb/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
#define CLASS_REQ_SET_CONTROL_LINE_STATE 0x22

/* class codes */
#define USB_CLASS_HID 0x3
#define USB_CLASS_MASS_STORAGE 0x8
#define USB_CLASS_HUB 0x9

Expand Down
86 changes: 68 additions & 18 deletions usb/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,6 @@ static int usb_getConfiguration(usb_dev_t *dev)

/* Get first nine bytes to get to know configuration len */
if (usb_getDescriptor(dev, USB_DESC_CONFIG, 0, (char *)&pre, sizeof(pre)) < 0) {
USB_LOG("usb: Fail to get configuration descriptor\n");
return -1;
}

Expand All @@ -224,7 +223,6 @@ static int usb_getConfiguration(usb_dev_t *dev)

/* TODO: Handle multiple configuration devices */
if (usb_getDescriptor(dev, USB_DESC_CONFIG, 0, (char *)conf, pre.wTotalLength) < 0) {
USB_LOG("usb: Fail to get configuration descriptor\n");
free(conf);
return -1;
}
Expand Down Expand Up @@ -374,14 +372,61 @@ static int usb_getStringDesc(usb_dev_t *dev, char **buf, int index)
}


static void usb_fallbackProductString(usb_dev_t *dev)
{
switch (dev->desc.bDeviceClass) {
case USB_CLASS_HID:
dev->product = "USB HID";
break;
case USB_CLASS_HUB:
switch (dev->desc.bDeviceProtocol) {
case USB_HUB_PROTO_ROOT:
dev->product = "USB Root Hub";
break;
case USB_HUB_PROTO_SINGLE_TT:
dev->product = "USB Single TT Hub";
break;
default:
dev->product = "USB Hub";
break;
}
break;
case USB_CLASS_MASS_STORAGE:
dev->product = "USB Mass Storage";
break;
default:
dev->product = "Unknown USB Device";
break;
}
}


static void usb_fallbackManufacturerString(usb_dev_t *dev)
{
dev->manufacturer = "Generic";
}


static void usb_fallbackSerialNumberString(usb_dev_t *dev)
{
dev->serialNumber = "Unknown";
}


static int usb_getAllStringDescs(usb_dev_t *dev)
{
usb_string_desc_t desc = { 0 };
int i;
int i, ret;

/* Get an array of language ids */
/* String descriptors are optional. If a device omits all string descriptors,
* it must not return this array, so the following call is allowed to fail in
* that case */
if (usb_getDescriptor(dev, USB_DESC_STRING, 0, (char *)&desc, sizeof(desc)) < 0) {
USB_LOG("usb: Fail to get configuration descriptor\n");
return -1;
usb_fallbackManufacturerString(dev);
usb_fallbackProductString(dev);
usb_fallbackSerialNumberString(dev);
return -ENOTSUP;
}

if (desc.bLength < 4)
Expand All @@ -391,18 +436,24 @@ static int usb_getAllStringDescs(usb_dev_t *dev)
dev->langId = desc.wData[0] | ((uint16_t)desc.wData[1] << 8);

if (dev->desc.iManufacturer != 0) {
if (usb_getStringDesc(dev, &dev->manufacturer, dev->desc.iManufacturer) != 0)
return -ENOMEM;
ret = usb_getStringDesc(dev, &dev->manufacturer, dev->desc.iManufacturer);
}
if (dev->desc.iManufacturer == 0 || ret != 0) {
usb_fallbackManufacturerString(dev);
}

if (dev->desc.iProduct != 0) {
if (usb_getStringDesc(dev, &dev->product, dev->desc.iProduct) != 0)
return -ENOMEM;
ret = usb_getStringDesc(dev, &dev->product, dev->desc.iProduct);
}
if (dev->desc.iProduct == 0 || ret != 0) {
usb_fallbackProductString(dev);
}

if (dev->desc.iSerialNumber != 0) {
if (usb_getStringDesc(dev, &dev->serialNumber, dev->desc.iSerialNumber) != 0)
return -ENOMEM;
ret = usb_getStringDesc(dev, &dev->serialNumber, dev->desc.iSerialNumber);
}
if (dev->desc.iSerialNumber == 0 || ret != 0) {
usb_fallbackSerialNumberString(dev);
}

for (i = 0; i < dev->nifs; i++) {
Expand Down Expand Up @@ -455,16 +506,13 @@ int usb_devEnumerate(usb_dev_t *dev)
return -1;
}

if (usb_getAllStringDescs(dev) < 0) {
USB_LOG("usb: Fail to get string descriptors\n");
return -1;
}
(void)usb_getAllStringDescs(dev);

if (!usb_isRoothub(dev))
usb_devSetChild(dev->hub, dev->port, dev);

USB_LOG("usb: New device addr: %d locationID: %08x %s, %s\n", dev->address, dev->locationID,
dev->manufacturer, dev->product);
dev->manufacturer, dev->product);

if (dev->desc.bDeviceClass == USB_CLASS_HUB) {
if (hub_conf(dev) != 0)
Expand Down Expand Up @@ -525,9 +573,11 @@ usb_dev_t *usb_devFind(usb_dev_t *hub, int locationID)
}


void usb_devDisconnected(usb_dev_t *dev)
void usb_devDisconnected(usb_dev_t *dev, bool silent)
{
printf("usb: Device disconnected addr %d locationID: %08x\n", dev->address, dev->locationID);
if (!silent) {
printf("usb: Device disconnected addr %d locationID: %08x\n", dev->address, dev->locationID);
}
usb_devSetChild(dev->hub, dev->port, NULL);
usb_devUnbind(dev);
usb_devDestroy(dev);
Expand Down
5 changes: 4 additions & 1 deletion usb/dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define _USB_DEV_H_

#include <usb.h>
#include <stdbool.h>

#include "usbhost.h"

Expand All @@ -33,6 +34,8 @@ typedef struct {


typedef struct _usb_dev {
struct _usb_dev *next, *prev;

enum usb_speed speed;
usb_device_desc_t desc;
usb_configuration_desc_t *conf;
Expand Down Expand Up @@ -71,7 +74,7 @@ usb_dev_t *usb_devAlloc(void);
int usb_devEnumerate(usb_dev_t *dev);


void usb_devDisconnected(usb_dev_t *dev);
void usb_devDisconnected(usb_dev_t *dev, bool silent);


int usb_devInit(void);
Expand Down
29 changes: 23 additions & 6 deletions usb/drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
struct {
handle_t lock;
usb_drv_t *drvs;
handle_t drvAddedCond;
} usbdrv_common;


Expand Down Expand Up @@ -251,11 +252,10 @@ static usb_drv_t *usb_drvMatchIface(usb_dev_t *dev, usb_iface_t *iface)
int i, match, bestmatch = 0;

mutexLock(usbdrv_common.lock);
drv = usbdrv_common.drvs;
if (drv == NULL) {
mutexUnlock(usbdrv_common.lock);
return NULL;
while (usbdrv_common.drvs == NULL) {
condWait(usbdrv_common.drvAddedCond, usbdrv_common.lock, 0);
}
drv = usbdrv_common.drvs;

do {
for (i = 0; i < drv->nfilters; i++) {
Expand Down Expand Up @@ -363,16 +363,22 @@ int usb_drvBind(usb_dev_t *dev)
umsg->insertion.descriptor = dev->desc;
umsg->insertion.locationID = dev->locationID;

/* FIXME: drvAdd races with drvMatchIface in multi-driver scenario.
* Devices may become orphaned forever if they get added by hcd before the driver
* is connected */
for (i = 0; i < dev->nifs; i++) {
if ((drv = usb_drvMatchIface(dev, &dev->ifs[i])) != NULL) {
dev->ifs[i].driver = drv;
umsg->insertion.interface = i;
msgSend(drv->port, &msg);
if (msg.o.err == 0) {
return 0;
}
}
/* TODO: Make a device orphaned */
}

return 0;
return -1;
}


Expand Down Expand Up @@ -414,6 +420,7 @@ void usb_drvAdd(usb_drv_t *drv)
idtree_init(&drv->pipes);
idtree_init(&drv->urbs);
LIST_ADD(&usbdrv_common.drvs, drv);
condSignal(usbdrv_common.drvAddedCond);
mutexUnlock(usbdrv_common.lock);
}

Expand Down Expand Up @@ -561,6 +568,7 @@ static int _usb_handleUrb(msg_t *msg, unsigned int port, unsigned long rid)

t->port = drv->port;
t->pipeid = urb->pipe;
t->msg = *msg;

/* For async urbs only allocate resources. The transfer would be executed,
* upon receiving usb_submit_t msg later */
Expand Down Expand Up @@ -613,10 +621,19 @@ void usb_drvPipeFree(usb_drv_t *drv, usb_pipe_t *pipe)

int usb_drvInit(void)
{
if (mutexCreate(&usbdrv_common.lock) != 0) {
int ret;

ret = mutexCreate(&usbdrv_common.lock);
if (ret != 0) {
USB_LOG("usbdrv: Can't create mutex!\n");
return -ENOMEM;
}

ret = condCreate(&usbdrv_common.drvAddedCond);
if (ret != 0) {
USB_LOG("usbdrv: Can't create cond!\n");
return -ENOMEM;
}

return 0;
}
14 changes: 12 additions & 2 deletions usb/hcd.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,19 @@
typedef struct {
char type[HCD_TYPE_LEN];
uintptr_t hcdaddr;
uintptr_t phyaddr;
int irq;
int clk;
union {
struct {
uintptr_t addr;
int clk;
} phy;

struct {
unsigned char bus;
unsigned char dev;
unsigned char func;
} pci_devId;
};
} hcd_info_t;

typedef struct hcd_ops {
Expand Down
Loading
Loading