Skip to content

Commit

Permalink
[usb] Add functions for manual device address assignment
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed Mar 16, 2015
1 parent 74f5701 commit 838ab97
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 0 deletions.
44 changes: 44 additions & 0 deletions src/drivers/bus/usb.c
Expand Up @@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
Expand Down Expand Up @@ -1849,6 +1850,49 @@ void free_usb_bus ( struct usb_bus *bus ) {
free ( bus );
}

/******************************************************************************
*
* USB address assignment
*
******************************************************************************
*/

/**
* Allocate device address
*
* @v bus USB bus
* @ret address Device address, or negative error
*/
int usb_alloc_address ( struct usb_bus *bus ) {
unsigned int address;

/* Find first free device address */
address = ffsll ( ~bus->addresses );
if ( ! address )
return -ENOENT;

/* Mark address as used */
bus->addresses |= ( 1ULL << ( address - 1 ) );

return address;
}

/**
* Free device address
*
* @v bus USB bus
* @v address Device address
*/
void usb_free_address ( struct usb_bus *bus, unsigned int address ) {

/* Sanity check */
assert ( address > 0 );
assert ( bus->addresses & ( 1ULL << ( address - 1 ) ) );

/* Mark address as free */
bus->addresses &= ~( 1ULL << ( address - 1 ) );
}

/******************************************************************************
*
* USB bus topology
Expand Down
26 changes: 26 additions & 0 deletions src/include/ipxe/usb.h
Expand Up @@ -867,6 +867,17 @@ struct usb_bus {

/** Largest transfer allowed on the bus */
size_t mtu;
/** Address in-use mask
*
* This is used only by buses which perform manual address
* assignment. USB allows for addresses in the range [1,127].
* We use a simple bitmask which restricts us to the range
* [1,64]; this is unlikely to be a problem in practice. For
* comparison: controllers which perform autonomous address
* assignment (such as xHCI) typically allow for only 32
* devices per bus anyway.
*/
unsigned long long addresses;

/** Root hub */
struct usb_hub *hub;
Expand Down Expand Up @@ -1021,6 +1032,19 @@ usb_set_feature ( struct usb_device *usb, unsigned int type,
feature, index, NULL, 0 );
}

/**
* Set address
*
* @v usb USB device
* @v address Device address
* @ret rc Return status code
*/
static inline __attribute__ (( always_inline )) int
usb_set_address ( struct usb_device *usb, unsigned int address ) {

return usb_control ( usb, USB_SET_ADDRESS, address, 0, NULL, 0 );
}

/**
* Get USB descriptor
*
Expand Down Expand Up @@ -1148,6 +1172,8 @@ extern int register_usb_bus ( struct usb_bus *bus );
extern void unregister_usb_bus ( struct usb_bus *bus );
extern void free_usb_bus ( struct usb_bus *bus );

extern int usb_alloc_address ( struct usb_bus *bus );
extern void usb_free_address ( struct usb_bus *bus, unsigned int address );
extern unsigned int usb_route_string ( struct usb_device *usb );
extern unsigned int usb_depth ( struct usb_device *usb );
extern struct usb_port * usb_root_hub_port ( struct usb_device *usb );
Expand Down

0 comments on commit 838ab97

Please sign in to comment.