SET_INTERFACE
. The existence in nature of hubs that support the mode with different TT is not confirmed, as well as the benefits of this mode, so the hub driver does not even try to detect and enable it and simply uses the single TT mode, which is enabled by default.usb_hub_callbacks
structure containing pointers to the usb_hub_init
and usb_hub_disconnect
driver functions. The driver operation begins when the logic device level calls usb_hub_init
, and ends when the channel support level causes usb_hub_disconnect
in response to the device disconnecting.usb_hub_init
and continues in other functions as it usb_hub_init
responses from the device. usb_hub_init
opens a channel to the interrupt type endpoint, through which the hub will notify the driver about changes in the status of connected devices. Next, usb_hub_init
sends a GET_DESCRIPTOR
request to the hub handle .29h
;32h=50
corresponds to 100 ms;usb_hub_init
saves the endpoint packet size — it will be needed later — and requests 40 bytes of the hub descriptor, allowing a short response. After receiving the hub handle, usb_hub_got_config
allocates and fills enough memory to store interesting data, plus two variables for each port: a pointer to the connected device and the device connection time.SET_FEATURE(PORT_POWER)
. At the input, the command accepts a port number, counting from 1. Physically, the hub can support powering on and off for each port or be limited to two states “there is no power on all ports” and “power is on all ports” - the organization can be learned from the two lower bits of the attributes hub, 00 corresponds to the total power, 01 - separate, 10 and 11 are reserved. But in both cases, the hub maintains a separate logical state for each port and will not report events on ports with a power-off logic, so regardless of the physical organization, you need to turn on the power on each port. usb_hub_got_config
and usb_hub_port_powered
consistently usb_hub_port_powered
a power-on command for all ports.usb_hub_process_deferred
function. After the allotted interval usb_hub_process_deferred
, usb_hub_process_deferred
starts working with the hub.usb_hub_wait_change
, which requests data from the interrupt type endpoint. While there are no events requiring attention with the hub, the request waits without demanding CPU resources: the host controller periodically polls the endpoint without any intervention from the CPU to determine if there is any data. I remind you that the polling interval is encoded by the last byte of the endpoint descriptor and is set when the channel is opened. When the state of the hub has changed, the hub returns a bit mask indicating the ports whose state has changed, plus the low-order bit indicating whether the state of the hub itself has changed. If at the initialization of the hub some devices have already been connected to it, the first time the hub requests it, it will immediately return a change with respect to the “zero” state.usb_hub_init
saved it, not limited to transferring to the channel open function.GET_STATUS
, returning both the current status bits and the change bits, and CLEAR_FEATURE
, one way to use which is to reset the specified change bit. Due to the fact that these are two different teams, the following situation is possible:GET_STATUS
command and sees the device connection in the current state and in the state change,CLEAR_FEATURE
command, the hub clears the change bit,GET_STATUS
command, in GET_STATUS
to find out what happened, and the CLEAR_FEATURE
to clear the changes, you need to send the GET_STATUS
command GET_STATUS
to get the current status. It is possible that the second GET_STATUS
command GET_STATUS
again report changes in state after CLEAR_FEATURE
; although stopping processing at this point is correct - the next time the data is read from the end point of the interrupt type, the hub will immediately report a new change - more efficiently, since the host has learned about the change, update the host’s view of the world behind the hub and do a cycle: send a second CLEAR_FEATURE
command and the third GET_STATUS
and so on, until GET_STATUS
reports no new changes.usb_hub_changed
function. It looks at the state of which ports has changed, for each port it launches the above-described request-status-and-confirm-change cycle, accumulating incoming changes. The response to most changes is the corresponding debug print. It is necessary to process only device connection / disconnection notifications.usb_hub_changed
remembers the connection time, after which usb_hub_process_deferred
plans to wake up in 100 milliseconds. If within 100 milliseconds a signal arrives to disconnect a device on the same port, further actions are canceled. Unfortunately, the absence of such a signal does not mean that the device has been connected for all these 100 milliseconds - perhaps the polling interval is quite large and the signal has not reached yet. For reliability, after a 100 millisecond interval, usb_hub_process_deferred
sends an explicit GET_STATUS
request. If it shows that there was no change in the connection status, then further initialization is enabled. You cannot reset two devices on the same bus in parallel; if there is a reset of some other device connected to the same controller - not necessarily the same hub - then first the device is waiting for its turn to reset. The reset is activated by the SET_FEATURE(PORT_RESET)
command SET_FEATURE(PORT_RESET)
and is turned off by the hub automatically after 10 ms of the specified specification, which sets the reset status bit, which may or may not be noticed in time when reading the end point depending on the polling interval. Because of this uncertainty, usb_hub_process_deferred
sends usb_hub_process_deferred
independently after a set time and CLEAR_FEATURE
, and the change processing code, if it still sees a change in the reset state, simply ignores it. The end of the reset in the hub at the same time includes broadcast traffic to the device. After resetting according to the usb_hub_process_deferred
specification, another 10 milliseconds usb_hub_process_deferred
, during which the device can adapt, and then passes control to the host controllers support code by calling usb_hardware_func.NewDevice
. The device speed required for usb_hardware_func.NewDevice
determined by the hub during the reset process and returned along with the other state of the device in response to GET_STATUS
. A pointer to the connected device returned from usb_hardware_func.NewDevice
is stored in the structure of the hub.usb_hub_changed
device is disconnected, usb_hub_changed
calls the usb_device_disconnected
channel support function, passing the previously stored pointer from NewDevice
. If the device was in the process of initialization, the process is terminated.usb_hub_disconnected
handler, called when the hub is disconnected, calls usb_device_disconnected
for all connected devices, advances the queue of devices waiting to be reset — if the device was reset when one of the devices was disconnected and frees the allocated memory for the hub structure.Source: https://habr.com/ru/post/203918/
All Articles