mirror of https://github.com/ipxe/ipxe.git
[usb] Add functions for manual device address assignment
Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/35/head
parent
74f57016dc
commit
838ab97ce3
|
@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -1849,6 +1850,49 @@ void free_usb_bus ( struct usb_bus *bus ) {
|
||||||
free ( 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
|
* USB bus topology
|
||||||
|
|
|
@ -867,6 +867,17 @@ struct usb_bus {
|
||||||
|
|
||||||
/** Largest transfer allowed on the bus */
|
/** Largest transfer allowed on the bus */
|
||||||
size_t mtu;
|
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 */
|
/** Root hub */
|
||||||
struct usb_hub *hub;
|
struct usb_hub *hub;
|
||||||
|
@ -1021,6 +1032,19 @@ usb_set_feature ( struct usb_device *usb, unsigned int type,
|
||||||
feature, index, NULL, 0 );
|
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
|
* Get USB descriptor
|
||||||
*
|
*
|
||||||
|
@ -1148,6 +1172,8 @@ extern int register_usb_bus ( struct usb_bus *bus );
|
||||||
extern void unregister_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 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_route_string ( struct usb_device *usb );
|
||||||
extern unsigned int usb_depth ( 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 );
|
extern struct usb_port * usb_root_hub_port ( struct usb_device *usb );
|
||||||
|
|
Loading…
Reference in New Issue