static bool DataPoll()

in src/cdi/adapter.c [232:331]


static bool DataPoll(AdapterConnectionState* adapter_con_state_ptr)
{
    bool all_idle = true;

    // Set this thread to use the connection's log. Can now use CDI_LOG_THREAD() for logging within this thread.
    CdiLoggerThreadLogSet(adapter_con_state_ptr->log_handle);

    assert(kEndpointDirectionBidirectional != adapter_con_state_ptr->direction); // Not supported

    EndpointManagerHandle mgr_handle = EndpointManagerConnectionToEndpointManager(
                                          adapter_con_state_ptr->data_state.cdi_connection_handle);

    if (kPollStart == adapter_con_state_ptr->poll_state) {
        // Register this thread with the Endpoint Manager as being part of this connection. Since this is a polling
        // thread, we use the non-blocking EndpointManagerPoll() function instead of the blocking
        // EndpointManagerThreadWait() function.
        EndpointManagerThreadRegister(mgr_handle,
                                      CdiOsThreadGetName(adapter_con_state_ptr->poll_thread_state_ptr->thread_id));
        adapter_con_state_ptr->poll_state = kPollRunning;
    } else if (kPollStopping == adapter_con_state_ptr->poll_state) {
        if (EndpointManagerPollThreadExit(mgr_handle)) {
            adapter_con_state_ptr->poll_state = kPollStopped;
        }
        return all_idle;
    }

    // The Endpoint Manager is used here to control suspend, restart and shutdown sequences.
    if (!CdiOsSignalReadState(adapter_con_state_ptr->shutdown_signal) &&
        !EndpointManagerIsConnectionShuttingDown(mgr_handle)) {
        // Walk through each endpoint that is part of this connection.
        CdiEndpointHandle cdi_endpoint_handle = EndpointManagerGetFirstEndpoint(mgr_handle);

        if (cdi_endpoint_handle) {
            // Account for poll thread sleeping (idle time).
            AdapterEndpointState* adapter_endpoint_ptr = EndpointManagerEndpointToAdapterEndpoint(cdi_endpoint_handle);
            UpdateThreadUtilizationStats(adapter_endpoint_ptr->endpoint_stats_ptr, true,
                                         &adapter_con_state_ptr->load_state);
        }

        while (cdi_endpoint_handle) {
            adapter_con_state_ptr->load_state.top_time = CdiOsGetMicroseconds();
            bool idle = true;
            AdapterEndpointState* adapter_endpoint_ptr = EndpointManagerEndpointToAdapterEndpoint(cdi_endpoint_handle);
            // Get Endpoint Manager notification signal.
            if (EndpointManagerPoll(&cdi_endpoint_handle) && adapter_endpoint_ptr) {
                if (adapter_con_state_ptr->can_transmit) {
                    Packet* packet_ptr = NULL;
                    bool last_packet = false;
                    EndpointTransmitQueueLevel queue_level = CdiAdapterGetTransmitQueueLevel(adapter_endpoint_ptr);
                    bool got_packet = (kEndpointTransmitQueueFull != queue_level) &&
                        (NULL != (packet_ptr = GetNextPacket(adapter_endpoint_ptr, 0, NULL, &last_packet)));
                    if (got_packet) {
                        idle = false;
                        // Use the adapter to send the packet.
                        adapter_con_state_ptr->adapter_state_ptr->functions_ptr->Send(adapter_endpoint_ptr, packet_ptr,
                                                                                      last_packet);
                        // NOTE: No need to generate any error or warnings here since, the Send() will normally fail if
                        // the receiver is not connected (ie. during probe).
                    }
                    if (kEndpointTransmitQueueEmpty != CdiAdapterGetTransmitQueueLevel(adapter_endpoint_ptr)) {
                        // Packets are in flight (have not received ACKs back), so don't want this poll thread to sleep.
                        all_idle = false;
                    }
                } else {
                    if (RxPollProcess(adapter_endpoint_ptr)) {
                        idle = false;
                        all_idle = false;
                    }
                }

                // Perform adapter specific poll mode processing.
                if (kCdiStatusOk == CdiAdapterPollEndpoint(adapter_endpoint_ptr)) {
                    idle = false;
                }

                // Check if busy/idle state is different this time compared to last.
                UpdateThreadUtilizationStats(adapter_endpoint_ptr->endpoint_stats_ptr, idle,
                                             &adapter_con_state_ptr->load_state);
            }
        }
        // Set top time to account for poll thread idle time performed outside of this function (ie. mostly sleep time).
        adapter_con_state_ptr->load_state.top_time = CdiOsGetMicroseconds();
    } else {
        // Connection is shutting down. If a receiver, ensure receiver poll processing is performed for all endpoints
        // related to this connection to flush Rx queues.
        if (!adapter_con_state_ptr->can_transmit) {
            CdiEndpointHandle cdi_endpoint_handle = EndpointManagerGetFirstEndpoint(mgr_handle);
            while (cdi_endpoint_handle) {
                AdapterEndpointState* adapter_endpoint_ptr = EndpointManagerEndpointToAdapterEndpoint(cdi_endpoint_handle);
                RxPollProcess(adapter_endpoint_ptr);
                cdi_endpoint_handle = EndpointManagerGetNextEndpoint(cdi_endpoint_handle);
            }
        }
        if (kPollRunning == adapter_con_state_ptr->poll_state) {
            adapter_con_state_ptr->poll_state = kPollStopping;
        }
    }

    return all_idle;
}