|
@@ -321,6 +321,37 @@ int usb_endpoint_open ( struct usb_endpoint *ep ) {
|
321
|
321
|
return rc;
|
322
|
322
|
}
|
323
|
323
|
|
|
324
|
+/**
|
|
325
|
+ * Clear transaction translator (if applicable)
|
|
326
|
+ *
|
|
327
|
+ * @v ep USB endpoint
|
|
328
|
+ * @ret rc Return status code
|
|
329
|
+ */
|
|
330
|
+static int usb_endpoint_clear_tt ( struct usb_endpoint *ep ) {
|
|
331
|
+ struct usb_device *usb = ep->usb;
|
|
332
|
+ struct usb_port *tt;
|
|
333
|
+ int rc;
|
|
334
|
+
|
|
335
|
+ /* Do nothing if this is a periodic endpoint */
|
|
336
|
+ if ( ep->attributes & USB_ENDPOINT_ATTR_PERIODIC )
|
|
337
|
+ return 0;
|
|
338
|
+
|
|
339
|
+ /* Do nothing if this endpoint is not behind a transaction translator */
|
|
340
|
+ tt = usb_transaction_translator ( usb );
|
|
341
|
+ if ( ! tt )
|
|
342
|
+ return 0;
|
|
343
|
+
|
|
344
|
+ /* Clear transaction translator buffer */
|
|
345
|
+ if ( ( rc = tt->hub->driver->clear_tt ( tt->hub, tt, ep ) ) != 0 ) {
|
|
346
|
+ DBGC ( usb, "USB %s %s could not clear transaction translator: "
|
|
347
|
+ "%s\n", usb->name, usb_endpoint_name ( ep->address ),
|
|
348
|
+ strerror ( rc ) );
|
|
349
|
+ return rc;
|
|
350
|
+ }
|
|
351
|
+
|
|
352
|
+ return 0;
|
|
353
|
+}
|
|
354
|
+
|
324
|
355
|
/**
|
325
|
356
|
* Close USB endpoint
|
326
|
357
|
*
|
|
@@ -345,6 +376,9 @@ void usb_endpoint_close ( struct usb_endpoint *ep ) {
|
345
|
376
|
/* Discard any recycled buffers, if applicable */
|
346
|
377
|
if ( ep->max )
|
347
|
378
|
usb_flush ( ep );
|
|
379
|
+
|
|
380
|
+ /* Clear transaction translator, if applicable */
|
|
381
|
+ usb_endpoint_clear_tt ( ep );
|
348
|
382
|
}
|
349
|
383
|
|
350
|
384
|
/**
|
|
@@ -369,6 +403,10 @@ static int usb_endpoint_reset ( struct usb_endpoint *ep ) {
|
369
|
403
|
return rc;
|
370
|
404
|
}
|
371
|
405
|
|
|
406
|
+ /* Clear transaction translator, if applicable */
|
|
407
|
+ if ( ( rc = usb_endpoint_clear_tt ( ep ) ) != 0 )
|
|
408
|
+ return rc;
|
|
409
|
+
|
372
|
410
|
/* Clear endpoint halt, if applicable */
|
373
|
411
|
type = ( ep->attributes & USB_ENDPOINT_ATTR_TYPE_MASK );
|
374
|
412
|
if ( ( type != USB_ENDPOINT_ATTR_CONTROL ) &&
|
|
@@ -1949,14 +1987,16 @@ void usb_free_address ( struct usb_bus *bus, unsigned int address ) {
|
1949
|
1987
|
* @ret route USB route string
|
1950
|
1988
|
*/
|
1951
|
1989
|
unsigned int usb_route_string ( struct usb_device *usb ) {
|
|
1990
|
+ struct usb_device *parent;
|
1952
|
1991
|
unsigned int route;
|
1953
|
1992
|
|
1954
|
1993
|
/* Navigate up to root hub, constructing route string as we go */
|
1955
|
|
- for ( route = 0 ; usb->port->hub->usb ; usb = usb->port->hub->usb ) {
|
|
1994
|
+ for ( route = 0 ; ( parent = usb->port->hub->usb ) ; usb = parent ) {
|
1956
|
1995
|
route <<= 4;
|
1957
|
1996
|
route |= ( ( usb->port->address > 0xf ) ?
|
1958
|
1997
|
0xf : usb->port->address );
|
1959
|
1998
|
}
|
|
1999
|
+
|
1960
|
2000
|
return route;
|
1961
|
2001
|
}
|
1962
|
2002
|
|
|
@@ -1967,10 +2007,11 @@ unsigned int usb_route_string ( struct usb_device *usb ) {
|
1967
|
2007
|
* @ret depth Hub depth
|
1968
|
2008
|
*/
|
1969
|
2009
|
unsigned int usb_depth ( struct usb_device *usb ) {
|
|
2010
|
+ struct usb_device *parent;
|
1970
|
2011
|
unsigned int depth;
|
1971
|
2012
|
|
1972
|
2013
|
/* Navigate up to root hub, constructing depth as we go */
|
1973
|
|
- for ( depth = 0 ; usb->port->hub->usb ; usb = usb->port->hub->usb )
|
|
2014
|
+ for ( depth = 0 ; ( parent = usb->port->hub->usb ) ; usb = parent )
|
1974
|
2015
|
depth++;
|
1975
|
2016
|
|
1976
|
2017
|
return depth;
|
|
@@ -1983,14 +2024,37 @@ unsigned int usb_depth ( struct usb_device *usb ) {
|
1983
|
2024
|
* @ret port Root hub port
|
1984
|
2025
|
*/
|
1985
|
2026
|
struct usb_port * usb_root_hub_port ( struct usb_device *usb ) {
|
|
2027
|
+ struct usb_device *parent;
|
1986
|
2028
|
|
1987
|
2029
|
/* Navigate up to root hub */
|
1988
|
|
- while ( usb->port->hub->usb )
|
1989
|
|
- usb = usb->port->hub->usb;
|
|
2030
|
+ while ( ( parent = usb->port->hub->usb ) )
|
|
2031
|
+ usb = parent;
|
1990
|
2032
|
|
1991
|
2033
|
return usb->port;
|
1992
|
2034
|
}
|
1993
|
2035
|
|
|
2036
|
+/**
|
|
2037
|
+ * Get USB transaction translator
|
|
2038
|
+ *
|
|
2039
|
+ * @v usb USB device
|
|
2040
|
+ * @ret port Transaction translator port, or NULL
|
|
2041
|
+ */
|
|
2042
|
+struct usb_port * usb_transaction_translator ( struct usb_device *usb ) {
|
|
2043
|
+ struct usb_device *parent;
|
|
2044
|
+
|
|
2045
|
+ /* Navigate up to root hub. If we find a low-speed or
|
|
2046
|
+ * full-speed port with a higher-speed parent device, then
|
|
2047
|
+ * that port is the transaction translator.
|
|
2048
|
+ */
|
|
2049
|
+ for ( ; ( parent = usb->port->hub->usb ) ; usb = parent ) {
|
|
2050
|
+ if ( ( usb->port->speed <= USB_SPEED_FULL ) &&
|
|
2051
|
+ ( parent->port->speed > USB_SPEED_FULL ) )
|
|
2052
|
+ return usb->port;
|
|
2053
|
+ }
|
|
2054
|
+
|
|
2055
|
+ return NULL;
|
|
2056
|
+}
|
|
2057
|
+
|
1994
|
2058
|
/* Drag in objects via register_usb_bus() */
|
1995
|
2059
|
REQUIRING_SYMBOL ( register_usb_bus );
|
1996
|
2060
|
|