iPXE
usbhub.c File Reference

USB hub driver. More...

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <byteswap.h>
#include <ipxe/usb.h>
#include "usbhub.h"

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static void hub_refill (struct usb_hub_device *hubdev)
 Refill interrupt ring.
static void hub_complete (struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
 Complete interrupt transfer.
static int hub_open (struct usb_hub *hub)
 Open hub.
static void hub_close (struct usb_hub *hub)
 Close hub.
static int hub_enable (struct usb_hub *hub, struct usb_port *port)
 Enable port.
static int hub_disable (struct usb_hub *hub, struct usb_port *port)
 Disable port.
static int hub_clear_changes (struct usb_hub_device *hubdev, unsigned int port, uint16_t changed)
 Clear port status change bits.
static int hub_speed (struct usb_hub *hub, struct usb_port *port)
 Update port speed.
static int hub_clear_tt (struct usb_hub *hub, struct usb_port *port, struct usb_endpoint *ep)
 Clear transaction translator buffer.
static int hub_probe (struct usb_function *func, struct usb_configuration_descriptor *config)
 Probe USB hub.
static void hub_remove (struct usb_function *func)
 Remove USB hub.

Variables

static struct process_descriptor hub_refill_desc
 Refill process descriptor.
static struct usb_endpoint_driver_operations usb_hub_intr_operations
 Interrupt endpoint operations.
static struct usb_hub_driver_operations hub_operations
 USB hub operations.
static struct usb_device_id hub_ids []
 USB hub device IDs.
struct usb_driver usb_hub_driver __usb_driver
 USB hub driver.

Detailed Description

USB hub driver.

Definition in file usbhub.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ hub_refill()

void hub_refill ( struct usb_hub_device * hubdev)
static

Refill interrupt ring.

Parameters
hubdevHub device

Definition at line 47 of file usbhub.c.

47 {
48 int rc;
49
50 /* Refill interrupt endpoint */
51 if ( ( rc = usb_refill ( &hubdev->intr ) ) != 0 ) {
52 DBGC ( hubdev, "HUB %s could not refill interrupt: %s\n",
53 hubdev->name, strerror ( rc ) );
54 /* Continue attempting to refill */
55 return;
56 }
57
58 /* Stop refill process */
59 process_del ( &hubdev->refill );
60}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define DBGC(...)
Definition compiler.h:505
void process_del(struct process *process)
Remove process from process list.
Definition process.c:80
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
struct usb_endpoint intr
Interrupt endpoint.
Definition usbhub.h:265
struct process refill
Interrupt endpoint refill process.
Definition usbhub.h:267
const char * name
Name.
Definition usbhub.h:254
int usb_refill(struct usb_endpoint *ep)
Refill endpoint.
Definition usb.c:711

References DBGC, usb_hub_device::intr, usb_hub_device::name, process_del(), rc, usb_hub_device::refill, strerror(), and usb_refill().

Referenced by hub_open().

◆ hub_complete()

void hub_complete ( struct usb_endpoint * ep,
struct io_buffer * iobuf,
int rc )
static

Complete interrupt transfer.

Parameters
epUSB endpoint
iobufI/O buffer
rcCompletion status code

Definition at line 73 of file usbhub.c.

74 {
75 struct usb_hub_device *hubdev =
76 container_of ( ep, struct usb_hub_device, intr );
77 struct usb_hub *hub = hubdev->hub;
78 uint8_t *data = iobuf->data;
79 unsigned int bits = ( 8 * iob_len ( iobuf ) );
80 unsigned int i;
81
82 /* Ignore packets cancelled when the endpoint closes */
83 if ( ! ep->open )
84 goto done;
85
86 /* Ignore packets with errors */
87 if ( rc != 0 ) {
88 DBGC ( hubdev, "HUB %s interrupt failed: %s\n",
89 hubdev->name, strerror ( rc ) );
90 DBGC_HDA ( hubdev, 0, iobuf->data, iob_len ( iobuf ) );
91 goto done;
92 }
93
94 /* Report any port status changes */
95 for ( i = 1 ; i <= hub->ports ; i++ ) {
96
97 /* Sanity check */
98 if ( i > bits ) {
99 DBGC ( hubdev, "HUB %s underlength interrupt:\n",
100 hubdev->name );
101 DBGC_HDA ( hubdev, 0, iobuf->data, iob_len ( iobuf ) );
102 goto done;
103 }
104
105 /* Report port status change if applicable */
106 if ( data[ i / 8 ] & ( 1 << ( i % 8 ) ) ) {
107 DBGC2 ( hubdev, "HUB %s port %d status changed\n",
108 hubdev->name, i );
109 usb_port_changed ( usb_port ( hub, i ) );
110 }
111 }
112
113 done:
114
115 /* Recycle I/O buffer */
116 usb_recycle ( &hubdev->intr, iobuf );
117
118 /* Start refill process */
119 process_add ( &hubdev->refill );
120}
unsigned char uint8_t
Definition stdint.h:10
static volatile void * bits
Definition bitops.h:28
struct bofm_section_header done
Definition bofm_test.c:46
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint8_t intr
Interrupts enabled.
Definition ena.h:3
#define DBGC2(...)
Definition compiler.h:522
#define DBGC_HDA(...)
Definition compiler.h:506
static void usb_recycle(struct usb_endpoint *ep, struct io_buffer *iobuf)
Recycle I/O buffer.
Definition usb.h:633
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
void process_add(struct process *process)
Add process to process list.
Definition process.c:60
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
void * data
Start of data.
Definition iobuf.h:53
int open
Endpoint is open.
Definition usb.h:419
A USB hub device.
Definition usbhub.h:252
struct usb_hub * hub
USB hub.
Definition usbhub.h:258
A USB hub.
Definition usb.h:841
unsigned int ports
Number of ports.
Definition usb.h:851
A USB port.
Definition usb.h:813
void usb_port_changed(struct usb_port *port)
Report port status change.
Definition usb.c:1858

References bits, container_of, data, io_buffer::data, DBGC, DBGC2, DBGC_HDA, done, usb_hub_device::hub, intr, usb_hub_device::intr, iob_len(), usb_hub_device::name, usb_endpoint::open, usb_hub::ports, process_add(), rc, usb_hub_device::refill, strerror(), usb_port_changed(), and usb_recycle().

◆ hub_open()

int hub_open ( struct usb_hub * hub)
static

Open hub.

Parameters
hubUSB hub
Return values
rcReturn status code

Definition at line 133 of file usbhub.c.

133 {
134 struct usb_hub_device *hubdev = usb_hub_get_drvdata ( hub );
135 struct usb_device *usb = hubdev->usb;
136 unsigned int i;
137 int rc;
138
139 /* Ensure ports are powered */
140 for ( i = 1 ; i <= hub->ports ; i++ ) {
141 if ( ( rc = usb_hub_set_port_feature ( usb, i,
143 0 ) ) != 0 ) {
144 DBGC ( hubdev, "HUB %s port %d could not apply power: "
145 "%s\n", hubdev->name, i, strerror ( rc ) );
146 goto err_power;
147 }
148 }
149
150 /* Open interrupt endpoint */
151 if ( ( rc = usb_endpoint_open ( &hubdev->intr ) ) != 0 ) {
152 DBGC ( hubdev, "HUB %s could not register interrupt: %s\n",
153 hubdev->name, strerror ( rc ) );
154 goto err_open;
155 }
156
157 /* Start refill process */
158 process_add ( &hubdev->refill );
159
160 /* Refill interrupt ring */
161 hub_refill ( hubdev );
162
163 /* Delay to allow ports to stabilise on out-of-spec hubs */
164 if ( hubdev->flags & USB_HUB_SLOW_START )
166
167 return 0;
168
169 usb_endpoint_close ( &hubdev->intr );
170 err_open:
171 err_power:
172 return rc;
173}
static void * usb_hub_get_drvdata(struct usb_hub *hub)
Get USB hub driver private data.
Definition usb.h:948
A USB device.
Definition usb.h:723
unsigned int flags
Flags.
Definition usbhub.h:262
struct usb_device * usb
USB device.
Definition usbhub.h:256
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition timer.c:79
int usb_endpoint_open(struct usb_endpoint *ep)
Open USB endpoint.
Definition usb.c:294
void usb_endpoint_close(struct usb_endpoint *ep)
Close USB endpoint.
Definition usb.c:400
static void hub_refill(struct usb_hub_device *hubdev)
Refill interrupt ring.
Definition usbhub.c:47
static int usb_hub_set_port_feature(struct usb_device *usb, unsigned int port, unsigned int feature, unsigned int index)
Set port feature.
Definition usbhub.h:203
#define USB_HUB_PORT_POWER
Port power feature.
Definition usbhub.h:80
#define USB_HUB_SLOW_START_DELAY_MS
Additional setting delay for out-of-spec hubs.
Definition usbhub.h:274
#define USB_HUB_SLOW_START
Hub requires additional settling delay.
Definition usbhub.h:271

References DBGC, usb_hub_device::flags, usb_hub_device::hub, hub_refill(), usb_hub_device::intr, mdelay(), usb_hub_device::name, usb_hub::ports, process_add(), rc, usb_hub_device::refill, strerror(), usb_hub_device::usb, usb_endpoint_close(), usb_endpoint_open(), usb_hub_get_drvdata(), USB_HUB_PORT_POWER, usb_hub_set_port_feature(), USB_HUB_SLOW_START, and USB_HUB_SLOW_START_DELAY_MS.

◆ hub_close()

void hub_close ( struct usb_hub * hub)
static

Close hub.

Parameters
hubUSB hub

Definition at line 180 of file usbhub.c.

180 {
181 struct usb_hub_device *hubdev = usb_hub_get_drvdata ( hub );
182
183 /* Close interrupt endpoint */
184 usb_endpoint_close ( &hubdev->intr );
185
186 /* Stop refill process */
187 process_del ( &hubdev->refill );
188}

References usb_hub_device::hub, usb_hub_device::intr, process_del(), usb_hub_device::refill, usb_endpoint_close(), and usb_hub_get_drvdata().

◆ hub_enable()

int hub_enable ( struct usb_hub * hub,
struct usb_port * port )
static

Enable port.

Parameters
hubUSB hub
portUSB port
Return values
rcReturn status code

Definition at line 197 of file usbhub.c.

197 {
198 struct usb_hub_device *hubdev = usb_hub_get_drvdata ( hub );
199 struct usb_device *usb = hubdev->usb;
201 unsigned int current;
202 unsigned int i;
203 int rc;
204
205 /* Initiate reset if applicable */
206 if ( ( hub->protocol < USB_PROTO_3_0 ) &&
207 ( ( rc = usb_hub_set_port_feature ( usb, port->address,
208 USB_HUB_PORT_RESET, 0 ) )!=0)){
209 DBGC ( hubdev, "HUB %s port %d could not initiate reset: %s\n",
210 hubdev->name, port->address, strerror ( rc ) );
211 return rc;
212 }
213
214 /* Wait for port to become enabled */
215 for ( i = 0 ; i < USB_HUB_ENABLE_MAX_WAIT_MS ; i++ ) {
216
217 /* Check for port being enabled */
218 if ( ( rc = usb_hub_get_port_status ( usb, port->address,
219 &status ) ) != 0 ) {
220 DBGC ( hubdev, "HUB %s port %d could not get status: "
221 "%s\n", hubdev->name, port->address,
222 strerror ( rc ) );
223 return rc;
224 }
225 current = le16_to_cpu ( status.current );
226 if ( current & ( 1 << USB_HUB_PORT_ENABLE ) )
227 return 0;
228
229 /* Delay */
230 mdelay ( 1 );
231 }
232
233 DBGC ( hubdev, "HUB %s port %d timed out waiting for enable\n",
234 hubdev->name, port->address );
235 return -ETIMEDOUT;
236}
u8 port
Port number.
Definition CIB_PRM.h:3
uint8_t status
Status.
Definition ena.h:5
#define ETIMEDOUT
Connection timed out.
Definition errno.h:670
#define le16_to_cpu(value)
Definition byteswap.h:113
@ USB_PROTO_3_0
USB 3.0.
Definition usb.h:25
Port status.
Definition usbhub.h:63
uint16_t current
Current status.
Definition usbhub.h:65
unsigned int protocol
Hub protocol.
Definition usb.h:849
#define USB_HUB_PORT_RESET
Port reset feature.
Definition usbhub.h:77
#define USB_HUB_ENABLE_MAX_WAIT_MS
Maximum time to wait for port to become enabled.
Definition usbhub.h:286
static int usb_hub_get_port_status(struct usb_device *usb, unsigned int port, struct usb_hub_port_status *status)
Get port status.
Definition usbhub.h:169
#define USB_HUB_PORT_ENABLE
Port enabled/disabled feature.
Definition usbhub.h:74

References usb_hub_port_status::current, DBGC, ETIMEDOUT, usb_hub_device::hub, le16_to_cpu, mdelay(), usb_hub_device::name, port, usb_hub::protocol, rc, status, strerror(), usb_hub_device::usb, USB_HUB_ENABLE_MAX_WAIT_MS, usb_hub_get_drvdata(), usb_hub_get_port_status(), USB_HUB_PORT_ENABLE, USB_HUB_PORT_RESET, usb_hub_set_port_feature(), and USB_PROTO_3_0.

◆ hub_disable()

int hub_disable ( struct usb_hub * hub,
struct usb_port * port )
static

Disable port.

Parameters
hubUSB hub
portUSB port
Return values
rcReturn status code

Definition at line 245 of file usbhub.c.

245 {
246 struct usb_hub_device *hubdev = usb_hub_get_drvdata ( hub );
247 struct usb_device *usb = hubdev->usb;
248 int rc;
249
250 /* Disable port */
251 if ( ( hub->protocol < USB_PROTO_3_0 ) &&
252 ( ( rc = usb_hub_clear_port_feature ( usb, port->address,
254 0 ) ) != 0 ) ) {
255 DBGC ( hubdev, "HUB %s port %d could not disable: %s\n",
256 hubdev->name, port->address, strerror ( rc ) );
257 return rc;
258 }
259
260 return 0;
261}
static int usb_hub_clear_port_feature(struct usb_device *usb, unsigned int port, unsigned int feature, unsigned int index)
Clear port feature.
Definition usbhub.h:186

References DBGC, usb_hub_device::hub, usb_hub_device::name, port, usb_hub::protocol, rc, strerror(), usb_hub_device::usb, usb_hub_clear_port_feature(), usb_hub_get_drvdata(), USB_HUB_PORT_ENABLE, and USB_PROTO_3_0.

◆ hub_clear_changes()

int hub_clear_changes ( struct usb_hub_device * hubdev,
unsigned int port,
uint16_t changed )
static

Clear port status change bits.

Parameters
hubdevUSB hub device
portPort number
changedPort status change bits
Return values
rcReturn status code

Definition at line 271 of file usbhub.c.

272 {
273 struct usb_device *usb = hubdev->usb;
274 unsigned int bit;
275 unsigned int feature;
276 int rc;
277
278 /* Clear each set bit */
279 for ( bit = 0 ; bit < 16 ; bit++ ) {
280
281 /* Skip unset bits */
282 if ( ! ( changed & ( 1 << bit ) ) )
283 continue;
284
285 /* Skip unused features */
287 if ( ! ( hubdev->features & ( 1 << feature ) ) )
288 continue;
289
290 /* Clear bit */
291 if ( ( rc = usb_hub_clear_port_feature ( usb, port,
292 feature, 0 ) ) != 0 ) {
293 DBGC ( hubdev, "HUB %s port %d could not clear feature "
294 "%d: %s\n", hubdev->name, port, feature,
295 strerror ( rc ) );
296 return rc;
297 }
298 }
299
300 return 0;
301}
static unsigned int unsigned int bit
Definition bigint.h:392
A named feature.
Definition features.h:79
unsigned int features
Features.
Definition usbhub.h:260
#define USB_HUB_C_FEATURE(bit)
Calculate feature from change bit number.
Definition usbhub.h:110

References bit, DBGC, usb_hub_device::features, usb_hub_device::name, port, rc, strerror(), usb_hub_device::usb, USB_HUB_C_FEATURE, and usb_hub_clear_port_feature().

Referenced by hub_speed().

◆ hub_speed()

int hub_speed ( struct usb_hub * hub,
struct usb_port * port )
static

Update port speed.

Parameters
hubUSB hub
portUSB port
Return values
rcReturn status code

Definition at line 310 of file usbhub.c.

310 {
311 struct usb_hub_device *hubdev = usb_hub_get_drvdata ( hub );
312 struct usb_device *usb = hubdev->usb;
314 unsigned int current;
315 unsigned int changed;
316 int rc;
317
318 /* Get port status */
319 if ( ( rc = usb_hub_get_port_status ( usb, port->address,
320 &status ) ) != 0 ) {
321 DBGC ( hubdev, "HUB %s port %d could not get status: %s\n",
322 hubdev->name, port->address, strerror ( rc ) );
323 return rc;
324 }
325 current = le16_to_cpu ( status.current );
326 changed = le16_to_cpu ( status.changed );
327 DBGC2 ( hubdev, "HUB %s port %d status is %04x:%04x\n",
328 hubdev->name, port->address, changed, current );
329
330 /* Update port speed */
331 if ( current & ( 1 << USB_HUB_PORT_CONNECTION ) ) {
332 if ( hub->protocol >= USB_PROTO_3_0 ) {
333 port->speed = USB_SPEED_SUPER;
334 } else if ( current & ( 1 << USB_HUB_PORT_LOW_SPEED ) ) {
335 port->speed = USB_SPEED_LOW;
336 } else if ( current & ( 1 << USB_HUB_PORT_HIGH_SPEED ) ) {
337 port->speed = USB_SPEED_HIGH;
338 } else {
339 port->speed = USB_SPEED_FULL;
340 }
341 } else {
342 port->speed = USB_SPEED_NONE;
343 }
344
345 /* Record disconnections */
346 port->disconnected |= ( changed & ( 1 << USB_HUB_PORT_CONNECTION ) );
347
348 /* Clear port status change bits */
349 if ( ( rc = hub_clear_changes ( hubdev, port->address, changed ) ) != 0)
350 return rc;
351
352 return 0;
353}
@ USB_SPEED_LOW
Low speed (1.5Mbps)
Definition usb.h:49
@ USB_SPEED_FULL
Full speed (12Mbps)
Definition usb.h:51
@ USB_SPEED_HIGH
High speed (480Mbps)
Definition usb.h:53
@ USB_SPEED_NONE
Not connected.
Definition usb.h:47
@ USB_SPEED_SUPER
Super speed (5Gbps)
Definition usb.h:55
uint16_t changed
Changed status.
Definition usbhub.h:67
static int hub_clear_changes(struct usb_hub_device *hubdev, unsigned int port, uint16_t changed)
Clear port status change bits.
Definition usbhub.c:271
#define USB_HUB_PORT_HIGH_SPEED
High-speed device attached.
Definition usbhub.h:86
#define USB_HUB_PORT_LOW_SPEED
Low-speed device attached.
Definition usbhub.h:83
#define USB_HUB_PORT_CONNECTION
Current connect status feature.
Definition usbhub.h:71

References usb_hub_port_status::changed, usb_hub_port_status::current, DBGC, DBGC2, usb_hub_device::hub, hub_clear_changes(), le16_to_cpu, usb_hub_device::name, port, usb_hub::protocol, rc, status, strerror(), usb_hub_device::usb, usb_hub_get_drvdata(), usb_hub_get_port_status(), USB_HUB_PORT_CONNECTION, USB_HUB_PORT_HIGH_SPEED, USB_HUB_PORT_LOW_SPEED, USB_PROTO_3_0, USB_SPEED_FULL, USB_SPEED_HIGH, USB_SPEED_LOW, USB_SPEED_NONE, and USB_SPEED_SUPER.

◆ hub_clear_tt()

int hub_clear_tt ( struct usb_hub * hub,
struct usb_port * port,
struct usb_endpoint * ep )
static

Clear transaction translator buffer.

Parameters
hubUSB hub
portUSB port
epUSB endpoint
Return values
rcReturn status code

Definition at line 363 of file usbhub.c.

364 {
365 struct usb_hub_device *hubdev = usb_hub_get_drvdata ( hub );
366 struct usb_device *usb = hubdev->usb;
367 int rc;
368
369 /* Clear transaction translator buffer. All hubs must support
370 * single-TT operation; we simplify our code by supporting
371 * only this configuration.
372 */
373 if ( ( rc = usb_hub_clear_tt_buffer ( usb, ep->usb->address,
375 USB_HUB_TT_SINGLE ) ) != 0 ) {
376 DBGC ( hubdev, "HUB %s port %d could not clear TT buffer: %s\n",
377 hubdev->name, port->address, strerror ( rc ) );
378 return rc;
379 }
380
381 return 0;
382}
unsigned int address
Device address, if assigned.
Definition usb.h:733
struct usb_endpoint * ep[32]
Endpoint list.
Definition usb.h:745
struct usb_device * usb
USB device.
Definition usb.h:406
unsigned int attributes
Attributes.
Definition usb.h:410
unsigned int address
Endpoint address.
Definition usb.h:408
#define USB_HUB_TT_SINGLE
Transaction translator port value for single-TT hubs.
Definition usbhub.h:249
static int usb_hub_clear_tt_buffer(struct usb_device *usb, unsigned int device, unsigned int endpoint, unsigned int attributes, unsigned int tt_port)
Clear transaction translator buffer.
Definition usbhub.h:234

References usb_device::address, usb_endpoint::address, usb_endpoint::attributes, DBGC, usb_device::ep, usb_hub_device::hub, usb_hub_device::name, port, rc, strerror(), usb_endpoint::usb, usb_hub_device::usb, usb_hub_clear_tt_buffer(), usb_hub_get_drvdata(), and USB_HUB_TT_SINGLE.

◆ hub_probe()

int hub_probe ( struct usb_function * func,
struct usb_configuration_descriptor * config )
static

Probe USB hub.

Parameters
funcUSB function
configConfiguration descriptor
Return values
rcReturn status code

Definition at line 401 of file usbhub.c.

402 {
403 struct usb_device *usb = func->usb;
404 struct usb_bus *bus = usb->port->hub->bus;
405 struct usb_hub_device *hubdev;
408 unsigned int depth;
409 unsigned int ports;
410 int enhanced;
411 int rc;
412
413 /* Allocate and initialise structure */
414 hubdev = zalloc ( sizeof ( *hubdev ) );
415 if ( ! hubdev ) {
416 rc = -ENOMEM;
417 goto err_alloc;
418 }
419 enhanced = ( usb->port->protocol >= USB_PROTO_3_0 );
420 hubdev->name = func->name;
421 hubdev->usb = usb;
422 hubdev->features =
424 hubdev->flags = func->id->driver_data;
426 usb_refill_init ( &hubdev->intr, 0, 0, USB_HUB_INTR_FILL );
428
429 /* Locate hub interface descriptor */
430 interface = usb_interface_descriptor ( config, func->interface[0], 0 );
431 if ( ! interface ) {
432 DBGC ( hubdev, "HUB %s has no interface descriptor\n",
433 hubdev->name );
434 rc = -EINVAL;
435 goto err_interface;
436 }
437
438 /* Locate interrupt endpoint descriptor */
439 if ( ( rc = usb_endpoint_described ( &hubdev->intr, config, interface,
440 USB_INTERRUPT_IN, 0 ) ) != 0 ) {
441 DBGC ( hubdev, "HUB %s could not describe interrupt endpoint: "
442 "%s\n", hubdev->name, strerror ( rc ) );
443 goto err_endpoint;
444 }
445
446 /* Set hub depth */
447 depth = usb_depth ( usb );
448 if ( enhanced ) {
449 if ( ( rc = usb_hub_set_hub_depth ( usb, depth ) ) != 0 ) {
450 DBGC ( hubdev, "HUB %s could not set hub depth to %d: "
451 "%s\n", hubdev->name, depth, strerror ( rc ) );
452 goto err_set_hub_depth;
453 }
454 }
455
456 /* Get hub descriptor */
457 if ( ( rc = usb_hub_get_descriptor ( usb, enhanced, &desc ) ) != 0 ) {
458 DBGC ( hubdev, "HUB %s could not get hub descriptor: %s\n",
459 hubdev->name, strerror ( rc ) );
460 goto err_hub_descriptor;
461 }
462 ports = desc.basic.ports;
463 DBGC ( hubdev, "HUB %s has %d ports at depth %d%s\n", hubdev->name,
464 ports, depth, ( enhanced ? " (enhanced)" : "" ) );
465
466 /* Allocate hub */
467 hubdev->hub = alloc_usb_hub ( bus, usb, ports, &hub_operations );
468 if ( ! hubdev->hub ) {
469 rc = -ENOMEM;
470 goto err_alloc_hub;
471 }
472 usb_hub_set_drvdata ( hubdev->hub, hubdev );
473
474 /* Register hub */
475 if ( ( rc = register_usb_hub ( hubdev->hub ) ) != 0 ) {
476 DBGC ( hubdev, "HUB %s could not register: %s\n",
477 hubdev->name, strerror ( rc ) );
478 goto err_register_hub;
479 }
480
481 usb_func_set_drvdata ( func, hubdev );
482 return 0;
483
484 unregister_usb_hub ( hubdev->hub );
485 err_register_hub:
486 free_usb_hub ( hubdev->hub );
487 err_alloc_hub:
488 err_hub_descriptor:
489 err_set_hub_depth:
490 err_endpoint:
491 err_interface:
492 free ( hubdev );
493 err_alloc:
494 return rc;
495}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
uint8_t bus
Bus.
Definition edd.h:1
struct ena_llq_option desc
Descriptor counts.
Definition ena.h:9
#define EINVAL
Invalid argument.
Definition errno.h:429
#define ENOMEM
Not enough space.
Definition errno.h:535
static void usb_endpoint_init(struct usb_endpoint *ep, struct usb_device *usb, struct usb_endpoint_driver_operations *driver)
Initialise USB endpoint.
Definition usb.h:540
static void usb_refill_init(struct usb_endpoint *ep, size_t reserve, size_t len, unsigned int max)
Initialise USB endpoint refill.
Definition usb.h:617
static void usb_func_set_drvdata(struct usb_function *func, void *priv)
Set USB function driver private data.
Definition usb.h:707
static void usb_hub_set_drvdata(struct usb_hub *hub, void *priv)
Set USB hub driver private data.
Definition usb.h:937
static unsigned int usb_depth(struct usb_device *usb)
Get USB depth.
Definition usb.h:1269
#define USB_INTERRUPT_IN
Interrupt IN endpoint (internal) type.
Definition usb.h:302
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
static void process_init_stopped(struct process *process, struct process_descriptor *desc, struct refcnt *refcnt)
Initialise process without adding to process list.
Definition process.h:146
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
An object interface.
Definition interface.h:125
A USB bus.
Definition usb.h:966
unsigned long driver_data
Arbitrary driver data.
Definition usb.h:1369
struct usb_port * port
USB port.
Definition usb.h:727
struct usb_device * usb
USB device.
Definition usb.h:678
struct usb_device_id * id
Driver device ID.
Definition usb.h:691
const char * name
Name.
Definition usb.h:676
struct usb_bus * bus
USB bus.
Definition usb.h:845
A USB interface descriptor.
Definition usb.h:245
struct usb_hub * hub
USB hub.
Definition usb.h:815
unsigned int protocol
Port protocol.
Definition usb.h:819
A USB hub descriptor.
Definition usbhub.h:53
struct usb_hub_descriptor_enhanced enhanced
Enhanced hub descriptor.
Definition usbhub.h:59
int usb_endpoint_described(struct usb_endpoint *ep, struct usb_configuration_descriptor *config, struct usb_interface_descriptor *interface, unsigned int type, unsigned int index)
Describe USB endpoint from device configuration.
Definition usb.c:242
void free_usb_hub(struct usb_hub *hub)
Free USB hub.
Definition usb.c:2063
struct usb_hub * alloc_usb_hub(struct usb_bus *bus, struct usb_device *usb, unsigned int ports, struct usb_hub_driver_operations *driver)
Allocate USB hub.
Definition usb.c:1937
void unregister_usb_hub(struct usb_hub *hub)
Unregister USB hub.
Definition usb.c:2030
int register_usb_hub(struct usb_hub *hub)
Register USB hub.
Definition usb.c:1976
static struct usb_hub_driver_operations hub_operations
USB hub operations.
Definition usbhub.c:385
static struct process_descriptor hub_refill_desc
Refill process descriptor.
Definition usbhub.c:63
static struct usb_endpoint_driver_operations usb_hub_intr_operations
Interrupt endpoint operations.
Definition usbhub.c:123
#define USB_HUB_INTR_FILL
Interrupt ring fill level.
Definition usbhub.h:280
static int usb_hub_set_hub_depth(struct usb_device *usb, unsigned int depth)
Set hub depth.
Definition usbhub.h:218
static int usb_hub_get_descriptor(struct usb_device *usb, int enhanced, union usb_hub_descriptor *data)
Get hub descriptor.
Definition usbhub.h:147
#define USB_HUB_FEATURES_ENHANCED
USB features for enhanced hubs.
Definition usbhub.h:121
#define USB_HUB_FEATURES
USB features.
Definition usbhub.h:113

References alloc_usb_hub(), bus, usb_hub::bus, DBGC, desc, usb_device_id::driver_data, EINVAL, usb_hub_descriptor::enhanced, ENOMEM, usb_hub_device::features, usb_hub_device::flags, free, free_usb_hub(), usb_hub_device::hub, usb_port::hub, hub_operations, hub_refill_desc, usb_function::id, usb_hub_device::intr, usb_function::name, usb_hub_device::name, NULL, usb_device::port, process_init_stopped(), usb_port::protocol, rc, usb_hub_device::refill, register_usb_hub(), strerror(), unregister_usb_hub(), usb_function::usb, usb_hub_device::usb, usb_depth(), usb_endpoint_described(), usb_endpoint_init(), usb_func_set_drvdata(), USB_HUB_FEATURES, USB_HUB_FEATURES_ENHANCED, usb_hub_get_descriptor(), USB_HUB_INTR_FILL, usb_hub_intr_operations, usb_hub_set_drvdata(), usb_hub_set_hub_depth(), USB_INTERRUPT_IN, USB_PROTO_3_0, usb_refill_init(), and zalloc().

◆ hub_remove()

void hub_remove ( struct usb_function * func)
static

Remove USB hub.

Parameters
funcUSB function
Return values
rcReturn status code

Definition at line 503 of file usbhub.c.

503 {
504 struct usb_hub_device *hubdev = usb_func_get_drvdata ( func );
505 struct usb_hub *hub = hubdev->hub;
506 struct usb_device *usb = hubdev->usb;
507 struct usb_port *port;
508 unsigned int i;
509
510 /* If hub has been unplugged, mark all ports as unplugged */
511 if ( usb->port->disconnected ) {
512 for ( i = 1 ; i <= hub->ports ; i++ ) {
513 port = usb_port ( hub, i );
514 port->disconnected = 1;
515 port->speed = USB_SPEED_NONE;
516 }
517 }
518
519 /* Unregister hub */
520 unregister_usb_hub ( hubdev->hub );
521 assert ( ! process_running ( &hubdev->refill ) );
522
523 /* Free hub */
524 free_usb_hub ( hubdev->hub );
525
526 /* Free hub device */
527 free ( hubdev );
528}
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
static struct usb_port * usb_port(struct usb_hub *hub, unsigned int address)
Get USB port.
Definition usb.h:960
static void * usb_func_get_drvdata(struct usb_function *func)
Get USB function driver private data.
Definition usb.h:718
static int process_running(struct process *process)
Check if process is running.
Definition process.h:176
struct usb_device * usb
Currently attached device (if in use)
Definition usb.h:835
int disconnected
Port disconnection has been detected.
Definition usb.h:827

References assert, usb_port::disconnected, free, free_usb_hub(), usb_hub_device::hub, usb_port::hub, port, usb_device::port, usb_hub::ports, process_running(), usb_hub_device::refill, unregister_usb_hub(), usb_hub_device::usb, usb_port::usb, usb_func_get_drvdata(), usb_port(), and USB_SPEED_NONE.

Variable Documentation

◆ hub_refill_desc

struct process_descriptor hub_refill_desc
static
Initial value:
=
PROC_DESC ( struct usb_hub_device, refill, hub_refill )
#define PROC_DESC(object_type, process, _step)
Define a process descriptor.
Definition process.h:83

Refill process descriptor.

Definition at line 63 of file usbhub.c.

Referenced by hub_probe().

◆ usb_hub_intr_operations

struct usb_endpoint_driver_operations usb_hub_intr_operations
static
Initial value:
= {
.complete = hub_complete,
}
static void hub_complete(struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
Complete interrupt transfer.
Definition usbhub.c:73

Interrupt endpoint operations.

Definition at line 123 of file usbhub.c.

123 {
124 .complete = hub_complete,
125};

Referenced by hub_probe().

◆ hub_operations

struct usb_hub_driver_operations hub_operations
static
Initial value:
= {
.open = hub_open,
.close = hub_close,
.enable = hub_enable,
.disable = hub_disable,
.speed = hub_speed,
.clear_tt = hub_clear_tt,
}
static int hub_speed(struct usb_hub *hub, struct usb_port *port)
Update port speed.
Definition usbhub.c:310
static void hub_close(struct usb_hub *hub)
Close hub.
Definition usbhub.c:180
static int hub_open(struct usb_hub *hub)
Open hub.
Definition usbhub.c:133
static int hub_enable(struct usb_hub *hub, struct usb_port *port)
Enable port.
Definition usbhub.c:197
static int hub_disable(struct usb_hub *hub, struct usb_port *port)
Disable port.
Definition usbhub.c:245
static int hub_clear_tt(struct usb_hub *hub, struct usb_port *port, struct usb_endpoint *ep)
Clear transaction translator buffer.
Definition usbhub.c:363

USB hub operations.

Definition at line 385 of file usbhub.c.

385 {
386 .open = hub_open,
387 .close = hub_close,
388 .enable = hub_enable,
389 .disable = hub_disable,
390 .speed = hub_speed,
391 .clear_tt = hub_clear_tt,
392};

Referenced by hub_probe().

◆ hub_ids

struct usb_device_id hub_ids[]
static
Initial value:
= {
{
.name = "avocent-hub",
.vendor = 0x0624,
.product = 0x0248,
.driver_data = USB_HUB_SLOW_START,
},
{
.name = "hub",
.vendor = USB_ANY_ID,
.product = USB_ANY_ID,
},
}
#define USB_ANY_ID
Match-anything ID.
Definition usb.h:1373

USB hub device IDs.

Definition at line 531 of file usbhub.c.

531 {
532 {
533 .name = "avocent-hub",
534 .vendor = 0x0624,
535 .product = 0x0248,
536 .driver_data = USB_HUB_SLOW_START,
537 },
538 {
539 .name = "hub",
540 .vendor = USB_ANY_ID,
541 .product = USB_ANY_ID,
542 },
543};

◆ __usb_driver

struct usb_driver usb_hub_driver __usb_driver
Initial value:
= {
.ids = hub_ids,
.id_count = ( sizeof ( hub_ids ) / sizeof ( hub_ids[0] ) ),
.score = USB_SCORE_NORMAL,
.probe = hub_probe,
.remove = hub_remove,
}
#define USB_CLASS_ID(base, subclass, protocol)
Construct USB class ID.
Definition usb.h:1389
#define USB_CLASS_HUB
Class code for USB hubs.
Definition usb.h:170
@ USB_SCORE_NORMAL
Normal driver.
Definition usb.h:1453
static struct usb_device_id hub_ids[]
USB hub device IDs.
Definition usbhub.c:531
static int hub_probe(struct usb_function *func, struct usb_configuration_descriptor *config)
Probe USB hub.
Definition usbhub.c:401
static void hub_remove(struct usb_function *func)
Remove USB hub.
Definition usbhub.c:503

USB hub driver.

Definition at line 546 of file usbhub.c.

546 {
547 .ids = hub_ids,
548 .id_count = ( sizeof ( hub_ids ) / sizeof ( hub_ids[0] ) ),
549 .class = USB_CLASS_ID ( USB_CLASS_HUB, 0, USB_ANY_ID ),
550 .score = USB_SCORE_NORMAL,
551 .probe = hub_probe,
552 .remove = hub_remove,
553};