Browse Source

[usb] Add functions for manual device address assignment

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 years ago
parent
commit
838ab97ce3
2 changed files with 70 additions and 0 deletions
  1. 44
    0
      src/drivers/bus/usb.c
  2. 26
    0
      src/include/ipxe/usb.h

+ 44
- 0
src/drivers/bus/usb.c View File

@@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
26 26
 #include <stdlib.h>
27 27
 #include <stdio.h>
28 28
 #include <string.h>
29
+#include <strings.h>
29 30
 #include <unistd.h>
30 31
 #include <errno.h>
31 32
 #include <assert.h>
@@ -1849,6 +1850,49 @@ void free_usb_bus ( struct usb_bus *bus ) {
1849 1850
 	free ( bus );
1850 1851
 }
1851 1852
 
1853
+/******************************************************************************
1854
+ *
1855
+ * USB address assignment
1856
+ *
1857
+ ******************************************************************************
1858
+ */
1859
+
1860
+/**
1861
+ * Allocate device address
1862
+ *
1863
+ * @v bus		USB bus
1864
+ * @ret address		Device address, or negative error
1865
+ */
1866
+int usb_alloc_address ( struct usb_bus *bus ) {
1867
+	unsigned int address;
1868
+
1869
+	/* Find first free device address */
1870
+	address = ffsll ( ~bus->addresses );
1871
+	if ( ! address )
1872
+		return -ENOENT;
1873
+
1874
+	/* Mark address as used */
1875
+	bus->addresses |= ( 1ULL << ( address - 1 ) );
1876
+
1877
+	return address;
1878
+}
1879
+
1880
+/**
1881
+ * Free device address
1882
+ *
1883
+ * @v bus		USB bus
1884
+ * @v address		Device address
1885
+ */
1886
+void usb_free_address ( struct usb_bus *bus, unsigned int address ) {
1887
+
1888
+	/* Sanity check */
1889
+	assert ( address > 0 );
1890
+	assert ( bus->addresses & ( 1ULL << ( address - 1 ) ) );
1891
+
1892
+	/* Mark address as free */
1893
+	bus->addresses &= ~( 1ULL << ( address - 1 ) );
1894
+}
1895
+
1852 1896
 /******************************************************************************
1853 1897
  *
1854 1898
  * USB bus topology

+ 26
- 0
src/include/ipxe/usb.h View File

@@ -867,6 +867,17 @@ struct usb_bus {
867 867
 
868 868
 	/** Largest transfer allowed on the bus */
869 869
 	size_t mtu;
870
+	/** Address in-use mask
871
+	 *
872
+	 * This is used only by buses which perform manual address
873
+	 * assignment.  USB allows for addresses in the range [1,127].
874
+	 * We use a simple bitmask which restricts us to the range
875
+	 * [1,64]; this is unlikely to be a problem in practice.  For
876
+	 * comparison: controllers which perform autonomous address
877
+	 * assignment (such as xHCI) typically allow for only 32
878
+	 * devices per bus anyway.
879
+	 */
880
+	unsigned long long addresses;
870 881
 
871 882
 	/** Root hub */
872 883
 	struct usb_hub *hub;
@@ -1021,6 +1032,19 @@ usb_set_feature ( struct usb_device *usb, unsigned int type,
1021 1032
 			     feature, index, NULL, 0 );
1022 1033
 }
1023 1034
 
1035
+/**
1036
+ * Set address
1037
+ *
1038
+ * @v usb		USB device
1039
+ * @v address		Device address
1040
+ * @ret rc		Return status code
1041
+ */
1042
+static inline __attribute__ (( always_inline )) int
1043
+usb_set_address ( struct usb_device *usb, unsigned int address ) {
1044
+
1045
+	return usb_control ( usb, USB_SET_ADDRESS, address, 0, NULL, 0 );
1046
+}
1047
+
1024 1048
 /**
1025 1049
  * Get USB descriptor
1026 1050
  *
@@ -1148,6 +1172,8 @@ extern int register_usb_bus ( struct usb_bus *bus );
1148 1172
 extern void unregister_usb_bus ( struct usb_bus *bus );
1149 1173
 extern void free_usb_bus ( struct usb_bus *bus );
1150 1174
 
1175
+extern int usb_alloc_address ( struct usb_bus *bus );
1176
+extern void usb_free_address ( struct usb_bus *bus, unsigned int address );
1151 1177
 extern unsigned int usb_route_string ( struct usb_device *usb );
1152 1178
 extern unsigned int usb_depth ( struct usb_device *usb );
1153 1179
 extern struct usb_port * usb_root_hub_port ( struct usb_device *usb );

Loading…
Cancel
Save