Reorganized HCD for multiple URB scheduling
. HCD URB scheduler stub . Added USB hub - HCD message passing . Fixed invalid paths related to USB drivers Change-Id: I878f4521d5a7b25eb97fd8b377f3fdfd7ee4f28b
This commit is contained in:
parent
75d3188723
commit
d2032a25e2
|
|
@ -174,6 +174,7 @@
|
|||
./service/sched minix-sys
|
||||
./service/tty minix-sys
|
||||
./service/uds minix-sys
|
||||
./service/usb_hub minix-sys
|
||||
./service/usb_storage minix-sys
|
||||
./service/vfs minix-sys
|
||||
./service/vm minix-sys
|
||||
|
|
@ -5169,8 +5170,8 @@
|
|||
./usr/sbin/rdate minix-sys
|
||||
./usr/sbin/traceroute minix-sys
|
||||
./usr/sbin/unlink minix-sys
|
||||
./usr/sbin/usb_hub minix-sys
|
||||
./usr/sbin/usb_storage minix-sys
|
||||
./usr/sbin/usb_hub minix-sys obsolete
|
||||
./usr/sbin/usb_storage minix-sys obsolete
|
||||
./usr/sbin/user minix-sys
|
||||
./usr/sbin/useradd minix-sys
|
||||
./usr/sbin/userdel minix-sys
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
usb_driver usb_hub
|
||||
{
|
||||
binary = /usr/sbin/usb_hub;
|
||||
binary = /service/usb_hub;
|
||||
id {
|
||||
bInterfaceClass = 0x09;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
usb_driver usb_storage
|
||||
{
|
||||
binary = /usr/sbin/usb_storage;
|
||||
binary = /service/usb_storage;
|
||||
id {
|
||||
bInterfaceClass = 0x08;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,4 @@ LDADD+=-lddekit_usb_client -lddekit -lusb -lsys -lminlib
|
|||
#LDADD+=-Wl,-Ttext=0x800000
|
||||
#CPPFLAGS+=-DHUB_DEBUG
|
||||
|
||||
MAN=
|
||||
|
||||
BINDIR?= /usr/sbin
|
||||
|
||||
.include <minix.service.mk>
|
||||
|
|
|
|||
|
|
@ -479,6 +479,11 @@ hub_task(void * UNUSED(arg))
|
|||
}
|
||||
/* Block this port forever */
|
||||
s->conn[port] = HUB_PORT_ERROR;
|
||||
|
||||
HUB_MSG("Port%d status ERROR", port);
|
||||
HUB_MSG("Port%d will be blocked, until "
|
||||
"hub is detached", port);
|
||||
|
||||
break;
|
||||
|
||||
case HUB_CHANGE_COM_ERR:
|
||||
|
|
@ -827,7 +832,8 @@ hub_handle_connection(int port_num)
|
|||
|
||||
HUB_MSG("Device connected to port %d", port_num);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
return ddekit_usb_info(driver_state.dev, (long)DDEKIT_HUB_PORT_CONN,
|
||||
(long)port_num);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -841,5 +847,6 @@ hub_handle_disconnection(int port_num)
|
|||
|
||||
HUB_MSG("Device disconnected from port %d", port_num);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
return ddekit_usb_info(driver_state.dev, (long)DDEKIT_HUB_PORT_DISCONN,
|
||||
(long)port_num);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Makefile for the EARM USBD
|
||||
|
||||
PROG= usbd
|
||||
SRCS= usbd.c usbd_earm.c hcd.c hcd_common.c hcd_ddekit.c musb_am335x.c musb_core.c
|
||||
SRCS= usbd.c usbd_earm.c hcd.c hcd_common.c hcd_ddekit.c hcd_schedule.c musb_am335x.c musb_core.c
|
||||
MAN=
|
||||
BINDIR= /service
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <usbd/usbd_common.h>
|
||||
#include <usbd/usbd_interface.h>
|
||||
#include <usbd/usbd_schedule.h>
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
@ -129,8 +130,17 @@ usbd_start(void)
|
|||
|
||||
/* After spawning, allow server thread to work */
|
||||
if (NULL != usbd_th) {
|
||||
/* This will lock current thread until DDEKit exits */
|
||||
ddekit_minix_wait_exit();
|
||||
|
||||
/* Allow URB scheduling */
|
||||
if (usbd_init_scheduler()) {
|
||||
USB_MSG("Failed to start URB scheduler");
|
||||
} else {
|
||||
/* This will lock current thread until DDEKit exits */
|
||||
ddekit_minix_wait_exit();
|
||||
}
|
||||
|
||||
/* Disallow URB scheduling */
|
||||
usbd_deinit_scheduler();
|
||||
|
||||
/* Cleanup */
|
||||
ddekit_thread_terminate(usbd_th);
|
||||
|
|
|
|||
|
|
@ -21,13 +21,16 @@ static void hcd_device_thread(void *);
|
|||
/* Procedure that locks device thread forever in case of error/completion */
|
||||
static void hcd_device_finish(hcd_device_state *, const char *);
|
||||
|
||||
/* Procedure that finds device, waiting for given EP interrupt */
|
||||
static hcd_device_state * hcd_get_child_for_ep(hcd_device_state *, hcd_reg1);
|
||||
|
||||
/* Typical USD device communication procedures */
|
||||
static int hcd_enumerate(hcd_device_state *);
|
||||
static int hcd_get_device_descriptor(hcd_device_state *);
|
||||
static int hcd_set_address(hcd_device_state *, hcd_reg1);
|
||||
static int hcd_get_descriptor_tree(hcd_device_state *);
|
||||
static int hcd_set_configuration(hcd_device_state *, hcd_reg1);
|
||||
static int hcd_handle_urb(hcd_device_state *, hcd_urb *);
|
||||
static void hcd_handle_urb(hcd_device_state *, hcd_urb *);
|
||||
static int hcd_control_urb(hcd_device_state *, hcd_urb *);
|
||||
static int hcd_non_control_urb(hcd_device_state *, hcd_urb *);
|
||||
|
||||
|
|
@ -40,11 +43,8 @@ static int hcd_data_transfer(hcd_device_state *, hcd_datarequest *);
|
|||
/*===========================================================================*
|
||||
* Local definitions *
|
||||
*===========================================================================*/
|
||||
/* TODO: Only one device at a time
|
||||
* If ever HUB functionality is added, one must remember that disconnecting
|
||||
* HUB, means disconnecting every device attached to it, so data structure may
|
||||
* have to be altered to allow that */
|
||||
static hcd_device_state hcd_device[1];
|
||||
/* Array of available devices */
|
||||
static hcd_device_state hcd_device[HCD_NUM_MAX_DEVICES];
|
||||
|
||||
/* TODO: This was added for compatibility with DDELinux drivers that
|
||||
* allow receiving less data than expected in URB, without error */
|
||||
|
|
@ -55,69 +55,152 @@ static hcd_device_state hcd_device[1];
|
|||
* hcd_handle_event *
|
||||
*===========================================================================*/
|
||||
void
|
||||
hcd_handle_event(hcd_driver_state * driver)
|
||||
hcd_handle_event(hcd_device_state * device, hcd_event event, hcd_reg1 val)
|
||||
{
|
||||
hcd_device_state * this_device;
|
||||
|
||||
DEBUG_DUMP;
|
||||
|
||||
/* TODO: Finding which hcd_device is in use should be performed here */
|
||||
this_device = &(hcd_device[0]);
|
||||
|
||||
/* Sometimes interrupts occur in a weird order (EP after disconnect)
|
||||
* This helps finding ordering errors in DEBUG */
|
||||
USB_DBG("Event: 0x%02X, state: 0x%02X",
|
||||
driver->current_event, this_device->state);
|
||||
|
||||
/* Set what was received for device thread to use */
|
||||
this_device->driver = driver;
|
||||
/* No device may be supplied */
|
||||
if (NULL == device) {
|
||||
USB_MSG("No device available for event: 0x%02X, value: 0x%02X",
|
||||
event, val);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Handle event and forward control to device thread when required */
|
||||
switch (driver->current_event) {
|
||||
switch (event) {
|
||||
case HCD_EVENT_CONNECTED:
|
||||
if (HCD_STATE_DISCONNECTED == this_device->state) {
|
||||
if (EXIT_SUCCESS != hcd_connect_device(
|
||||
this_device,
|
||||
hcd_device_thread))
|
||||
USB_MSG("Device creation failed");
|
||||
} else
|
||||
USB_MSG("Device not marked as 'disconnected' "
|
||||
"for 'connection' event");
|
||||
USB_ASSERT((HCD_STATE_DISCONNECTED == device->state),
|
||||
"Device not marked as 'disconnected' "
|
||||
"for 'connection' event");
|
||||
|
||||
/* Mark as 'plugged in' first */
|
||||
device->state = HCD_STATE_CONNECTION_PENDING;
|
||||
|
||||
/* Try creating new thread for device */
|
||||
if (hcd_connect_device(device, hcd_device_thread))
|
||||
USB_MSG("Device creation failed, nothing more "
|
||||
"will happen until disconnected");
|
||||
|
||||
break;
|
||||
|
||||
case HCD_EVENT_DISCONNECTED:
|
||||
if (HCD_STATE_DISCONNECTED != this_device->state) {
|
||||
/* If connect callback was used before, call
|
||||
* it's equivalent to signal disconnection */
|
||||
if (HCD_STATE_CONNECTED == this_device->state)
|
||||
hcd_disconnect_cb(this_device);
|
||||
hcd_disconnect_device(this_device);
|
||||
this_device->state = HCD_STATE_DISCONNECTED;
|
||||
USB_ASSERT((HCD_STATE_DISCONNECTED != device->state),
|
||||
"Device is marked as 'disconnected' "
|
||||
"for 'disconnection' event");
|
||||
|
||||
/* Finally, zero everything to allow
|
||||
* further connections with this object */
|
||||
memset(this_device, 0x00, sizeof(*this_device));
|
||||
} else
|
||||
USB_MSG("Device is marked as 'disconnected' "
|
||||
"for 'disconnection' event");
|
||||
/* If connect callback was used before, call
|
||||
* it's equivalent to signal disconnection */
|
||||
if (HCD_STATE_CONNECTED == device->state)
|
||||
hcd_disconnect_cb(device);
|
||||
|
||||
hcd_disconnect_device(device);
|
||||
device->state = HCD_STATE_DISCONNECTED;
|
||||
|
||||
/* Finally, zero everything to allow
|
||||
* further connections with this object */
|
||||
memset(device, 0x00, sizeof(*device));
|
||||
|
||||
break;
|
||||
|
||||
case HCD_EVENT_PORT_CONNECTED:
|
||||
/* TODO: Actual port handling */
|
||||
USB_MSG("Device connected to hub's port");
|
||||
break;
|
||||
|
||||
case HCD_EVENT_PORT_DISCONNECTED:
|
||||
/* TODO: Actual port handling */
|
||||
USB_MSG("Device disconnected from hub's port");
|
||||
break;
|
||||
|
||||
case HCD_EVENT_ENDPOINT:
|
||||
case HCD_EVENT_URB:
|
||||
/* Allow device thread to continue with it's logic */
|
||||
if (HCD_STATE_DISCONNECTED != this_device->state)
|
||||
hcd_device_continue(this_device);
|
||||
USB_ASSERT((HCD_STATE_DISCONNECTED != device->state),
|
||||
"Parent device is marked as 'disconnected' "
|
||||
"for 'endpoint' event");
|
||||
|
||||
/* Alters 'device' when endpoint is allocated to
|
||||
* child rather than parent (hub), which allows
|
||||
* proper thread to continue */
|
||||
device = hcd_get_child_for_ep(device, val);
|
||||
|
||||
/* Check if anything at all, waits for such endpoint */
|
||||
if (device)
|
||||
/* Allow device thread, waiting for endpoint
|
||||
* event, to continue with its logic */
|
||||
hcd_device_continue(device, event, val);
|
||||
else
|
||||
USB_MSG("Device is marked as 'disconnected' "
|
||||
"for 'EP' event");
|
||||
USB_MSG("No device waits for endpoint %u", val);
|
||||
|
||||
break;
|
||||
|
||||
case HCD_EVENT_URB:
|
||||
USB_ASSERT((HCD_STATE_DISCONNECTED != device->state),
|
||||
"Device is marked as 'disconnected' "
|
||||
"for 'URB' event");
|
||||
|
||||
/* Allow device thread to continue with it's logic */
|
||||
hcd_device_continue(device, event, val);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
USB_ASSERT(0, "Illegal HCD event");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* hcd_update_port *
|
||||
*===========================================================================*/
|
||||
void
|
||||
hcd_update_port(hcd_driver_state * driver, hcd_event event)
|
||||
{
|
||||
hcd_device_state * d;
|
||||
int devnum;
|
||||
|
||||
const int maxdevs = (sizeof(hcd_device) / sizeof(hcd_device[0]));
|
||||
|
||||
DEBUG_DUMP;
|
||||
|
||||
switch (event) {
|
||||
case HCD_EVENT_CONNECTED:
|
||||
/* Check if already assigned */
|
||||
USB_ASSERT(NULL == driver->port_device,
|
||||
"Device was already connected before "
|
||||
"receiving 'connection' event");
|
||||
|
||||
/* For short */
|
||||
d = hcd_device;
|
||||
|
||||
/* Find first unused device */
|
||||
for (devnum = 0; devnum < maxdevs; devnum++) {
|
||||
if (HCD_STATE_DISCONNECTED == d[devnum].state) {
|
||||
/* Assign free device */
|
||||
driver->port_device = &(d[devnum]);
|
||||
/* Associate this device with driver */
|
||||
driver->port_device->driver = driver;
|
||||
/* Device found, exit */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Nothing found */
|
||||
USB_MSG("Device limit reached, no more "
|
||||
"free device structures to use");
|
||||
|
||||
break;
|
||||
|
||||
case HCD_EVENT_DISCONNECTED:
|
||||
/* Check if already released */
|
||||
USB_ASSERT(NULL != driver->port_device,
|
||||
"Device was already disconnected before "
|
||||
"receiving 'disconnection' event");
|
||||
|
||||
/* Clear port device */
|
||||
driver->port_device = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
USB_ASSERT(0, "Illegal port update event");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -135,9 +218,6 @@ hcd_device_thread(void * thread_args)
|
|||
/* Retrieve structures from generic data */
|
||||
this_device = (hcd_device_state *)thread_args;
|
||||
|
||||
/* Plugged in */
|
||||
this_device->state = HCD_STATE_CONNECTION_PENDING;
|
||||
|
||||
/* Enumeration sequence */
|
||||
if (EXIT_SUCCESS != hcd_enumerate(this_device))
|
||||
hcd_device_finish(this_device, "USB device enumeration failed");
|
||||
|
|
@ -153,11 +233,8 @@ hcd_device_thread(void * thread_args)
|
|||
/* Start handling URB's */
|
||||
for(;;) {
|
||||
/* Block and wait for something like 'submit URB' */
|
||||
hcd_device_wait(this_device, HCD_EVENT_URB, HCD_ANY_EP);
|
||||
|
||||
if (EXIT_SUCCESS != hcd_handle_urb(this_device,
|
||||
&(this_device->urb)))
|
||||
hcd_device_finish(this_device, "URB handling failed");
|
||||
hcd_device_wait(this_device, HCD_EVENT_URB, HCD_UNUSED_VAL);
|
||||
hcd_handle_urb(this_device, this_device->urb);
|
||||
}
|
||||
|
||||
/* Finish device handling to avoid leaving thread */
|
||||
|
|
@ -177,12 +254,28 @@ hcd_device_finish(hcd_device_state * this_device, const char * finish_msg)
|
|||
|
||||
/* Lock forever */
|
||||
for (;;) {
|
||||
hcd_device_wait(this_device, HCD_EVENT_URB, HCD_ANY_EP);
|
||||
hcd_device_wait(this_device, HCD_EVENT_URB, HCD_UNUSED_VAL);
|
||||
USB_MSG("Failed attempt to continue finished thread");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* hcd_get_child_for_ep *
|
||||
*===========================================================================*/
|
||||
static hcd_device_state *
|
||||
hcd_get_child_for_ep(hcd_device_state * device, hcd_reg1 ep)
|
||||
{
|
||||
DEBUG_DUMP;
|
||||
|
||||
/* TODO: When device has multiple children (hub),
|
||||
* this will allow routing interrupt login downstream */
|
||||
((void)ep);
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* hcd_enumerate *
|
||||
*===========================================================================*/
|
||||
|
|
@ -462,15 +555,13 @@ hcd_set_configuration(hcd_device_state * this_device, hcd_reg1 configuration)
|
|||
/*===========================================================================*
|
||||
* hcd_handle_urb *
|
||||
*===========================================================================*/
|
||||
static int
|
||||
static void
|
||||
hcd_handle_urb(hcd_device_state * this_device, hcd_urb * urb)
|
||||
{
|
||||
int transfer_status;
|
||||
|
||||
DEBUG_DUMP;
|
||||
|
||||
/* TODO: One device only */
|
||||
USB_ASSERT(NULL != urb, "NULL URB given");
|
||||
USB_ASSERT(this_device == urb->target_device, "Unknown device for URB");
|
||||
|
||||
/* Only if URB parsing was completed... */
|
||||
|
|
@ -491,13 +582,8 @@ hcd_handle_urb(hcd_device_state * this_device, hcd_urb * urb)
|
|||
this_device, urb);
|
||||
break;
|
||||
|
||||
case HCD_TRANSFER_ISOCHRONOUS:
|
||||
/* TODO: ISO transfer */
|
||||
USB_MSG("ISO transfer not supported");
|
||||
break;
|
||||
|
||||
default:
|
||||
USB_MSG("Invalid transfer type 0x%02X",
|
||||
USB_MSG("Unsupported transfer type 0x%02X",
|
||||
(int)urb->type);
|
||||
break;
|
||||
}
|
||||
|
|
@ -509,13 +595,8 @@ hcd_handle_urb(hcd_device_state * this_device, hcd_urb * urb)
|
|||
} else
|
||||
USB_MSG("Invalid URB supplied");
|
||||
|
||||
/* Call completion regardless of status */
|
||||
hcd_completion_cb(urb);
|
||||
|
||||
/* TODO: Only critical failures should ever yield EXIT_FAILURE, so
|
||||
* return is not bound to transfer_status for now, to let device
|
||||
* driver act accordingly */
|
||||
return EXIT_SUCCESS;
|
||||
/* Signal scheduler that URB was handled */
|
||||
urb->handled();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -235,20 +235,16 @@ hcd_disconnect_device(hcd_device_state * this_device)
|
|||
* hcd_device_wait *
|
||||
*===========================================================================*/
|
||||
void
|
||||
hcd_device_wait(hcd_device_state * this_device, hcd_event event, hcd_reg1 ep)
|
||||
hcd_device_wait(hcd_device_state * device, hcd_event event, hcd_reg1 ep)
|
||||
{
|
||||
hcd_driver_state * drv;
|
||||
|
||||
DEBUG_DUMP;
|
||||
|
||||
drv = (hcd_driver_state *)this_device->driver;
|
||||
USB_DBG("Device 0x%08X wait (0x%02X, 0x%02X)", device, event, ep);
|
||||
|
||||
drv->expected_event = event;
|
||||
drv->expected_endpoint = ep;
|
||||
device->wait_event = event;
|
||||
device->wait_ep = ep;
|
||||
|
||||
USB_DBG("Waiting for: ev=0x%X, ep=0x%X", (int)event, ep);
|
||||
|
||||
ddekit_sem_down(this_device->lock);
|
||||
ddekit_sem_down(device->lock);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -256,25 +252,16 @@ hcd_device_wait(hcd_device_state * this_device, hcd_event event, hcd_reg1 ep)
|
|||
* hcd_device_continue *
|
||||
*===========================================================================*/
|
||||
void
|
||||
hcd_device_continue(hcd_device_state * this_device)
|
||||
hcd_device_continue(hcd_device_state * device, hcd_event event, hcd_reg1 ep)
|
||||
{
|
||||
hcd_driver_state * drv;
|
||||
|
||||
DEBUG_DUMP;
|
||||
|
||||
drv = (hcd_driver_state *)this_device->driver;
|
||||
USB_DBG("Device 0x%08X continue (0x%02X, 0x%02X)", device, event, ep);
|
||||
|
||||
/* We need to get what was expected... */
|
||||
USB_ASSERT(drv->current_event == drv->expected_event,
|
||||
"Unexpected event occurred");
|
||||
USB_ASSERT(device->wait_event == event, "Unexpected event");
|
||||
USB_ASSERT(device->wait_ep == ep, "Unexpected endpoint");
|
||||
|
||||
/* ...including endpoint interrupts */
|
||||
if (HCD_EVENT_ENDPOINT == drv->current_event) {
|
||||
USB_ASSERT(drv->current_endpoint == drv->expected_endpoint,
|
||||
"Unexpected endpoint interrupt");
|
||||
}
|
||||
|
||||
ddekit_sem_up(this_device->lock);
|
||||
ddekit_sem_up(device->lock);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <usbd/hcd_ddekit.h>
|
||||
#include <usbd/hcd_interface.h>
|
||||
#include <usbd/hcd_schedule.h>
|
||||
#include <usbd/usbd_common.h>
|
||||
|
||||
|
||||
|
|
@ -16,7 +17,7 @@
|
|||
*===========================================================================*/
|
||||
/*
|
||||
* In this file "struct ddekit_usb_dev" equals "hcd_device_state"
|
||||
* */
|
||||
*/
|
||||
struct ddekit_usb_device_id;
|
||||
struct ddekit_usb_urb;
|
||||
struct ddekit_usb_dev;
|
||||
|
|
@ -25,6 +26,13 @@ struct ddekit_usb_dev;
|
|||
static void hcd_decode_urb(hcd_urb *, struct ddekit_usb_urb *);
|
||||
static void hcd_encode_urb(hcd_urb *, struct ddekit_usb_urb *);
|
||||
|
||||
/* HCD's URB create/destroy */
|
||||
static hcd_urb * hcd_new_urb(void);
|
||||
static void hcd_free_urb(hcd_urb *);
|
||||
|
||||
/* Decodes event from received info */
|
||||
static void hcd_decode_info(long, long, hcd_event *, hcd_reg1 *);
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* Global definitions *
|
||||
|
|
@ -177,35 +185,22 @@ int
|
|||
ddekit_usb_submit_urb(struct ddekit_usb_urb * d_urb)
|
||||
{
|
||||
hcd_device_state * dev;
|
||||
hcd_driver_state * drv;
|
||||
hcd_urb * urb;
|
||||
|
||||
DEBUG_DUMP;
|
||||
|
||||
/* Retrieve info on device/driver state from DDEKit's USB */
|
||||
/* Retrieve info on device state from DDEKit's URB */
|
||||
dev = (hcd_device_state *)(d_urb->dev);
|
||||
drv = (hcd_driver_state *)(dev->driver);
|
||||
|
||||
/* Check for latest URB completion */
|
||||
if (NULL == dev->urb.original_urb) {
|
||||
/* Get new URB */
|
||||
urb = hcd_new_urb();
|
||||
|
||||
/* Remember original URB */
|
||||
dev->urb.original_urb = (void *)d_urb;
|
||||
/* Turn DDEKit URB format to one that is easier to
|
||||
* handle by HCD, also check if URB is valid */
|
||||
hcd_decode_urb(urb, d_urb);
|
||||
|
||||
/* TODO: If multiple URB's have to be queued, this code
|
||||
* or DDEKit's must be altered accordingly */
|
||||
/* Turn DDEKit URB format to one that is easier to
|
||||
* handle by HCD, also check if URB is valid */
|
||||
hcd_decode_urb(&(dev->urb), d_urb);
|
||||
|
||||
/* Start handling URB event */
|
||||
drv->current_event = HCD_EVENT_URB;
|
||||
hcd_handle_event(drv);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* Last URB must not have been completed */
|
||||
return EXIT_FAILURE;
|
||||
/* Add URB to scheduler */
|
||||
return hcd_schedule_urb(urb);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -222,6 +217,31 @@ ddekit_usb_cancle_urb(struct ddekit_usb_urb * d_urb)
|
|||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* ddekit_usb_info *
|
||||
*===========================================================================*/
|
||||
long
|
||||
ddekit_usb_info(struct ddekit_usb_dev * dev, long type, long value)
|
||||
{
|
||||
hcd_event event;
|
||||
hcd_reg1 val;
|
||||
|
||||
DEBUG_DUMP;
|
||||
|
||||
/* Decode event */
|
||||
hcd_decode_info(type, value, &event, &val);
|
||||
|
||||
if (HCD_EVENT_INVALID == event) {
|
||||
USB_MSG("Invalid info message received");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
/* Let HCD handle info message */
|
||||
hcd_handle_event((hcd_device_state *)dev, event, val);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* ddekit_usb_init *
|
||||
*===========================================================================*/
|
||||
|
|
@ -290,13 +310,16 @@ hcd_completion_cb(hcd_urb * urb)
|
|||
/* Recollect original URB */
|
||||
d_urb = (struct ddekit_usb_urb *)urb->original_urb;
|
||||
|
||||
/* This URB will be scheduled no more */
|
||||
hcd_unschedule_urb(urb);
|
||||
|
||||
/* Turn HCD URB format to one handled by DDEKit */
|
||||
hcd_encode_urb(urb, d_urb);
|
||||
|
||||
completion_cb(d_urb->priv);
|
||||
/* No need for this URB anymore */
|
||||
hcd_free_urb(urb);
|
||||
|
||||
/* URB was handled, forget about it */
|
||||
urb->original_urb = NULL;
|
||||
completion_cb(d_urb->priv);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -308,6 +331,9 @@ hcd_decode_urb(hcd_urb * urb, struct ddekit_usb_urb * dde_urb)
|
|||
{
|
||||
DEBUG_DUMP;
|
||||
|
||||
/* Remember original */
|
||||
urb->original_urb = (void *)dde_urb;
|
||||
|
||||
/* No UBR error initially */
|
||||
urb->inout_status = EXIT_SUCCESS;
|
||||
|
||||
|
|
@ -397,7 +423,57 @@ hcd_encode_urb(hcd_urb * urb, struct ddekit_usb_urb * dde_urb)
|
|||
{
|
||||
DEBUG_DUMP;
|
||||
|
||||
/* Data buffers are the same, no need to copy */
|
||||
/* Rewrite output for DDEKit part */
|
||||
dde_urb->actual_length = urb->out_size;
|
||||
dde_urb->status = urb->inout_status;
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* hcd_new_urb *
|
||||
*===========================================================================*/
|
||||
static hcd_urb *
|
||||
hcd_new_urb(void)
|
||||
{
|
||||
DEBUG_DUMP;
|
||||
return malloc(sizeof(hcd_urb));
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* hcd_free_urb *
|
||||
*===========================================================================*/
|
||||
static void
|
||||
hcd_free_urb(hcd_urb * urb)
|
||||
{
|
||||
DEBUG_DUMP;
|
||||
free(urb);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* hcd_decode_info *
|
||||
*===========================================================================*/
|
||||
static void
|
||||
hcd_decode_info(long type, long invalue, hcd_event * event, hcd_reg1 * outvalue)
|
||||
{
|
||||
DEBUG_DUMP;
|
||||
|
||||
USB_ASSERT((invalue >= 0) && (invalue <= 0xFF),
|
||||
"Illegal USB info value received");
|
||||
|
||||
switch ((ddekit_msg_type_t)type) {
|
||||
case DDEKIT_HUB_PORT_CONN:
|
||||
*event = HCD_EVENT_PORT_CONNECTED;
|
||||
break;
|
||||
case DDEKIT_HUB_PORT_DISCONN:
|
||||
*event = HCD_EVENT_PORT_DISCONNECTED;
|
||||
break;
|
||||
default:
|
||||
*event = HCD_EVENT_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
*outvalue = (hcd_reg1)invalue;
|
||||
}
|
||||
|
|
|
|||
143
minix/drivers/usb/usbd/hcd/hcd_schedule.c
Normal file
143
minix/drivers/usb/usbd/hcd/hcd_schedule.c
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Implementation of HCD URB scheduler
|
||||
*/
|
||||
|
||||
#include <usbd/hcd_common.h>
|
||||
#include <usbd/hcd_ddekit.h>
|
||||
#include <usbd/hcd_interface.h>
|
||||
#include <usbd/hcd_schedule.h>
|
||||
#include <usbd/usbd_common.h>
|
||||
#include <usbd/usbd_schedule.h>
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* Required for scheduling *
|
||||
*===========================================================================*/
|
||||
/* Scheduler thread */
|
||||
static hcd_thread * urb_thread;
|
||||
|
||||
/* TODO: This will soon become URB list */
|
||||
static hcd_urb * current_urb;
|
||||
|
||||
/* This allows waiting for completion */
|
||||
static hcd_lock * handled_lock;
|
||||
|
||||
/* Scheduler task */
|
||||
static void hcd_urb_scheduler_task(void *);
|
||||
|
||||
/* Completion callback */
|
||||
static void hcd_urb_handled(void);
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* usbd_init_scheduler *
|
||||
*===========================================================================*/
|
||||
int
|
||||
usbd_init_scheduler(void)
|
||||
{
|
||||
DEBUG_DUMP;
|
||||
|
||||
urb_thread = ddekit_thread_create(hcd_urb_scheduler_task, NULL, "URB");
|
||||
if (NULL == urb_thread)
|
||||
goto ERR1;
|
||||
|
||||
handled_lock = ddekit_sem_init(0);
|
||||
if (NULL == handled_lock)
|
||||
goto ERR2;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
ERR2:
|
||||
ddekit_thread_terminate(urb_thread);
|
||||
ERR1:
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* usbd_deinit_scheduler *
|
||||
*===========================================================================*/
|
||||
void
|
||||
usbd_deinit_scheduler(void)
|
||||
{
|
||||
DEBUG_DUMP;
|
||||
|
||||
ddekit_sem_deinit(handled_lock);
|
||||
|
||||
ddekit_thread_terminate(urb_thread);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* hcd_schedule_urb *
|
||||
*===========================================================================*/
|
||||
int
|
||||
hcd_schedule_urb(hcd_urb * urb)
|
||||
{
|
||||
DEBUG_DUMP;
|
||||
|
||||
/* Tell URB what to call on completion */
|
||||
urb->handled = hcd_urb_handled;
|
||||
|
||||
/* TODO: Proper list handling */
|
||||
current_urb = urb;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* hcd_unschedule_urb *
|
||||
*===========================================================================*/
|
||||
void
|
||||
hcd_unschedule_urb(hcd_urb * urb)
|
||||
{
|
||||
DEBUG_DUMP;
|
||||
|
||||
/* TODO: Proper list handling */
|
||||
((void)urb);
|
||||
current_urb = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* hcd_urb_scheduler_task *
|
||||
*===========================================================================*/
|
||||
static void
|
||||
hcd_urb_scheduler_task(void * UNUSED(arg))
|
||||
{
|
||||
DEBUG_DUMP;
|
||||
|
||||
for (;;) {
|
||||
if (NULL != current_urb) {
|
||||
/* Tell device that this is it's URB */
|
||||
current_urb->target_device->urb = current_urb;
|
||||
|
||||
/* Start handling URB event */
|
||||
hcd_handle_event(current_urb->target_device,
|
||||
HCD_EVENT_URB, HCD_UNUSED_VAL);
|
||||
|
||||
/* Wait for completion */
|
||||
ddekit_sem_down(handled_lock);
|
||||
|
||||
/* Call completion regardless of status */
|
||||
hcd_completion_cb(current_urb);
|
||||
}
|
||||
|
||||
/* TODO: Temporary, poor scheduling with forced sleep */
|
||||
ddekit_thread_msleep(50);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* hcd_urb_handled *
|
||||
*===========================================================================*/
|
||||
static void
|
||||
hcd_urb_handled(void)
|
||||
{
|
||||
DEBUG_DUMP;
|
||||
|
||||
/* Handling completed */
|
||||
ddekit_sem_up(handled_lock);
|
||||
}
|
||||
|
|
@ -348,6 +348,7 @@ musb_am335x_init(void)
|
|||
ctrl->driver.out_status_stage = musb_out_status_stage;
|
||||
ctrl->driver.read_data = musb_read_data;
|
||||
ctrl->driver.check_error = musb_check_error;
|
||||
ctrl->driver.port_device = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -388,6 +389,7 @@ musb_am335x_init(void)
|
|||
ctrl->driver.out_status_stage = musb_out_status_stage;
|
||||
ctrl->driver.read_data = musb_read_data;
|
||||
ctrl->driver.check_error = musb_check_error;
|
||||
ctrl->driver.port_device = NULL;
|
||||
}
|
||||
|
||||
return musb_am335x_internal_init();
|
||||
|
|
@ -563,25 +565,26 @@ musb_am335x_usbx_isr(void * data)
|
|||
if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_CONNECTED) {
|
||||
USB_DBG("Device connected");
|
||||
CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_CONNECTED);
|
||||
driver->current_event = HCD_EVENT_CONNECTED;
|
||||
hcd_handle_event(driver);
|
||||
hcd_update_port(driver, HCD_EVENT_CONNECTED);
|
||||
hcd_handle_event(driver->port_device, HCD_EVENT_CONNECTED,
|
||||
HCD_UNUSED_VAL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_DISCONNECTED) {
|
||||
USB_DBG("Device disconnected");
|
||||
CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_DISCONNECTED);
|
||||
driver->current_event = HCD_EVENT_DISCONNECTED;
|
||||
hcd_handle_event(driver);
|
||||
hcd_handle_event(driver->port_device, HCD_EVENT_DISCONNECTED,
|
||||
HCD_UNUSED_VAL);
|
||||
hcd_update_port(driver, HCD_EVENT_DISCONNECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 != irqstat0) {
|
||||
USB_DBG("EP interrupt");
|
||||
CLEAR_IRQ0(irqstat0);
|
||||
driver->current_event = HCD_EVENT_ENDPOINT;
|
||||
driver->current_endpoint = musb_am335x_irqstat0_to_ep(irqstat0);
|
||||
hcd_handle_event(driver);
|
||||
hcd_handle_event(driver->port_device, HCD_EVENT_ENDPOINT,
|
||||
musb_am335x_irqstat0_to_ep(irqstat0));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -124,10 +124,13 @@ hcd_direction;
|
|||
/* Possible asynchronous HCD events */
|
||||
typedef enum {
|
||||
|
||||
HCD_EVENT_CONNECTED,
|
||||
HCD_EVENT_CONNECTED = 0,
|
||||
HCD_EVENT_DISCONNECTED,
|
||||
HCD_EVENT_PORT_CONNECTED,
|
||||
HCD_EVENT_PORT_DISCONNECTED,
|
||||
HCD_EVENT_ENDPOINT,
|
||||
HCD_EVENT_URB
|
||||
HCD_EVENT_URB,
|
||||
HCD_EVENT_INVALID = 0xFF
|
||||
}
|
||||
hcd_event;
|
||||
|
||||
|
|
@ -189,6 +192,7 @@ struct hcd_urb {
|
|||
/* Basic */
|
||||
void * original_urb;
|
||||
hcd_device_state * target_device;
|
||||
void (*handled)(void); /* URB handled callback */
|
||||
|
||||
/* Transfer (in/out signifies what may be overwritten by HCD) */
|
||||
hcd_ctrlrequest * in_setup;
|
||||
|
|
@ -207,12 +211,15 @@ struct hcd_urb {
|
|||
/* Current state of attached device */
|
||||
struct hcd_device_state {
|
||||
|
||||
hcd_driver_state * driver; /* Specific HCD driver object */
|
||||
hcd_device_state * parent; /* In case of hub attachment */
|
||||
hcd_driver_state * driver; /* Specific HCD driver object */
|
||||
hcd_thread * thread;
|
||||
hcd_lock * lock;
|
||||
void * data;
|
||||
|
||||
hcd_urb urb;
|
||||
hcd_urb * urb; /* URB to be used by device */
|
||||
hcd_event wait_event; /* Expected event */
|
||||
hcd_reg1 wait_ep; /* Expected event's endpoint */
|
||||
hcd_device_descriptor device_desc;
|
||||
hcd_configuration config_tree;
|
||||
hcd_reg1 max_packet_size;
|
||||
|
|
@ -250,12 +257,15 @@ struct hcd_device_state {
|
|||
#define HCD_LAST_ADDR 0x7Fu
|
||||
#define HCD_LAST_EP 0x0Fu
|
||||
#define HCD_TOTAL_EP 0x10u
|
||||
#define HCD_ANY_EP 0xFFu
|
||||
#define HCD_UNUSED_VAL 0xFFu /* When number not needed */
|
||||
|
||||
/* Legal interval values */
|
||||
#define HCD_LOWEST_INTERVAL 0x00u
|
||||
#define HCD_HIGHEST_INTERVAL 0xFFu
|
||||
|
||||
/* Max number of supported devices */
|
||||
#define HCD_NUM_MAX_DEVICES 0x08u
|
||||
|
||||
/* TODO: One device only */
|
||||
#define HCD_ATTACHED_ADDR 0x01u
|
||||
|
||||
|
|
@ -313,7 +323,7 @@ void hcd_disconnect_device(hcd_device_state *);
|
|||
void hcd_device_wait(hcd_device_state *, hcd_event, hcd_reg1);
|
||||
|
||||
/* Unlocks device thread halted by 'hcd_device_wait' */
|
||||
void hcd_device_continue(hcd_device_state *);
|
||||
void hcd_device_continue(hcd_device_state *, hcd_event, hcd_reg1);
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
* Interface for HCD
|
||||
*
|
||||
* This file holds prototypes that must be implemented by HCD
|
||||
* and event call that should be called when interrupt occurred
|
||||
* and call that should be used for asynchronous events
|
||||
* (interrupts, UBR submits, hub events, ...)
|
||||
*/
|
||||
|
||||
#ifndef _HCD_INTERFACE_H_
|
||||
|
|
@ -39,20 +40,20 @@ struct hcd_driver_state {
|
|||
/* Controller's private data (like mapped registers) */
|
||||
void * private_data;
|
||||
|
||||
/* Current state to be handled by driver */
|
||||
hcd_event current_event;
|
||||
hcd_reg1 current_endpoint;
|
||||
hcd_event expected_event;
|
||||
hcd_reg1 expected_endpoint;
|
||||
/* TODO: Only one port for each driver */
|
||||
/* Represents device attached to USB port handled by this driver */
|
||||
hcd_device_state * port_device;
|
||||
};
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* HCD event handling routine *
|
||||
*===========================================================================*/
|
||||
/* Handle asynchronous event
|
||||
* This must be called in case of specific HCD interrupts listed above */
|
||||
void hcd_handle_event(hcd_driver_state *);
|
||||
/* Handle asynchronous event */
|
||||
void hcd_handle_event(hcd_device_state *, hcd_event, hcd_reg1);
|
||||
|
||||
/* This resolves port's device structure for given driver and event */
|
||||
void hcd_update_port(hcd_driver_state *, hcd_event);
|
||||
|
||||
|
||||
#endif /* !_HCD_INTERFACE_H_ */
|
||||
|
|
|
|||
16
minix/drivers/usb/usbd/include/usbd/hcd_schedule.h
Normal file
16
minix/drivers/usb/usbd/include/usbd/hcd_schedule.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* HCD URB scheduler interface
|
||||
*/
|
||||
|
||||
#ifndef _HCD_SCHEDULE_H_
|
||||
#define _HCD_SCHEDULE_H_
|
||||
|
||||
#include <usbd/hcd_common.h>
|
||||
|
||||
/* Makes URB schedule enabled */
|
||||
int hcd_schedule_urb(hcd_urb *);
|
||||
|
||||
/* Makes URB schedule disabled */
|
||||
void hcd_unschedule_urb(hcd_urb *);
|
||||
|
||||
#endif /* !_HCD_SCHEDULE_H_ */
|
||||
12
minix/drivers/usb/usbd/include/usbd/usbd_schedule.h
Normal file
12
minix/drivers/usb/usbd/include/usbd/usbd_schedule.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* USBD URB scheduler interface
|
||||
*/
|
||||
|
||||
#ifndef _USBD_SCHEDULE_H_
|
||||
#define _USBD_SCHEDULE_H_
|
||||
|
||||
/* Should be used to create/destroy URB scheduler in base code */
|
||||
int usbd_init_scheduler(void);
|
||||
void usbd_deinit_scheduler(void);
|
||||
|
||||
#endif /* !_USBD_SCHEDULE_H_ */
|
||||
|
|
@ -78,12 +78,21 @@ struct ddekit_usb_urb {
|
|||
void *ddekit_priv;
|
||||
};
|
||||
|
||||
/* USB message types */
|
||||
typedef enum {
|
||||
|
||||
DDEKIT_HUB_PORT_CONN,
|
||||
DDEKIT_HUB_PORT_DISCONN
|
||||
}
|
||||
ddekit_msg_type_t;
|
||||
|
||||
int ddekit_usb_dev_set_data(struct ddekit_usb_dev *dev, void *data);
|
||||
void *ddekit_usb_dev_get_data(struct ddekit_usb_dev *dev);
|
||||
void ddekit_usb_get_device_id(struct ddekit_usb_dev *dev, struct
|
||||
ddekit_usb_device_id *id);
|
||||
int ddekit_usb_submit_urb(struct ddekit_usb_urb *d_urb);
|
||||
int ddekit_usb_cancle_urb(struct ddekit_usb_urb *d_urb);
|
||||
long ddekit_usb_info(struct ddekit_usb_dev *, long, long);
|
||||
|
||||
/*
|
||||
* This one is only implemented for the client side. For the server side is
|
||||
|
|
|
|||
|
|
@ -775,7 +775,8 @@
|
|||
#define USB_RQ_DEINIT (USB_BASE + 1) /* Quit the session */
|
||||
#define USB_RQ_SEND_URB (USB_BASE + 2) /* Send URB */
|
||||
#define USB_RQ_CANCEL_URB (USB_BASE + 3) /* Cancel URB */
|
||||
#define USB_REPLY (USB_BASE + 4)
|
||||
#define USB_RQ_SEND_INFO (USB_BASE + 4) /* Sends various information */
|
||||
#define USB_REPLY (USB_BASE + 5)
|
||||
|
||||
|
||||
/* those are from USBD to driver */
|
||||
|
|
@ -793,6 +794,9 @@
|
|||
# define USB_INTERFACES m4_l3
|
||||
# define USB_RB_INIT_NAME m3_ca1
|
||||
|
||||
# define USB_INFO_TYPE m4_l1
|
||||
# define USB_INFO_VALUE m4_l2
|
||||
|
||||
/*===========================================================================*
|
||||
* Messages for DeviceManager (s/t like SysFS) *
|
||||
*===========================================================================*/
|
||||
|
|
|
|||
|
|
@ -152,4 +152,7 @@ int usb_init(char *name);
|
|||
/** This functions handles a message from the HCD */
|
||||
int usb_handle_msg(struct usb_driver *ubd, message *msg);
|
||||
|
||||
/** Lets device driver send HCD various information */
|
||||
int usb_send_info(long, long);
|
||||
|
||||
#endif /* _MINIX_USB_H */
|
||||
|
|
|
|||
|
|
@ -186,6 +186,17 @@ int ddekit_usb_cancle_urb(struct ddekit_usb_urb *d_urb)
|
|||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* ddekit_usb_info *
|
||||
*****************************************************************************/
|
||||
long
|
||||
ddekit_usb_info(struct ddekit_usb_dev * UNUSED(dev), long type, long value)
|
||||
{
|
||||
return usb_send_info(type, value);
|
||||
}
|
||||
|
||||
|
||||
static void _ddekit_usb_thread()
|
||||
{
|
||||
struct ddekit_minix_msg_q *mq = ddekit_minix_create_msg_q(USB_BASE,
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ static struct ddekit_usb_urb *ddekit_usb_urb_from_mx_urb(struct usb_urb
|
|||
*mx_urb);
|
||||
static void submit_urb(message *msg);
|
||||
static void cancle_urb(message *msg);
|
||||
static void get_info(message *msg);
|
||||
static void completion_callback(void *priv);
|
||||
|
||||
static void prepare_devman_usbdev(struct ddekit_usb_dev * dev, int
|
||||
|
|
@ -441,6 +442,39 @@ static void cancle_urb(message *msg)
|
|||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* get_info *
|
||||
*****************************************************************************/
|
||||
static void
|
||||
get_info(message * msg)
|
||||
{
|
||||
struct minix_usb_driver * drv;
|
||||
endpoint_t ep;
|
||||
long info_type;
|
||||
long info_value;
|
||||
|
||||
/* Read */
|
||||
ep = msg->m_source;
|
||||
info_type = msg->USB_INFO_TYPE;
|
||||
info_value = msg->USB_INFO_VALUE;
|
||||
|
||||
/* Reuse as reply */
|
||||
msg->m_type = USB_REPLY;
|
||||
msg->USB_RESULT = -1;
|
||||
|
||||
/* Try and find driver first */
|
||||
if (NULL == (drv = find_driver(ep)))
|
||||
ddekit_printf("Non-registered driver tries to send info");
|
||||
else
|
||||
/* Route info to device */
|
||||
msg->USB_RESULT = ddekit_usb_info(_devices[drv->dev].dev,
|
||||
info_type, info_value);
|
||||
|
||||
/* Reply */
|
||||
ipc_send(ep, msg);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* completion_callback *
|
||||
****************************************************************************/
|
||||
|
|
@ -713,6 +747,9 @@ static int handle_msg(message *msg)
|
|||
case USB_RQ_CANCEL_URB:
|
||||
cancle_urb(msg);
|
||||
return 1;
|
||||
case USB_RQ_SEND_INFO:
|
||||
get_info(msg);
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -223,3 +223,32 @@ int usb_handle_msg(struct usb_driver *ud, message *msg)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* usb_send_info *
|
||||
*****************************************************************************/
|
||||
int
|
||||
usb_send_info(long info_type, long info_value)
|
||||
{
|
||||
int res;
|
||||
message msg;
|
||||
|
||||
/* Prepare message */
|
||||
msg.m_type = USB_RQ_SEND_INFO;
|
||||
msg.USB_INFO_TYPE = info_type;
|
||||
msg.USB_INFO_VALUE = info_value;
|
||||
|
||||
/* Send/receive message */
|
||||
res = ipc_sendrec(hcd_ep, &msg);
|
||||
|
||||
if (res != 0)
|
||||
panic("usb_send_info: could not talk to HCD: %d", res);
|
||||
|
||||
if (msg.m_type != USB_REPLY)
|
||||
panic("usb_send_info: got illegal response from HCD: %d", msg.m_type);
|
||||
|
||||
if (msg.USB_RESULT != 0)
|
||||
panic("usb_send_info: got illegal response from HCD: %d", msg.m_type);
|
||||
|
||||
return msg.USB_RESULT;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user