Commit df117e56 authored by Sam Hurst's avatar Sam Hurst Committed by Anas Nashif
Browse files

usb_c: Add super state to handle Sender Response Timer



Any Power Delivery message state that expects a reply must
start a sender response timer. This change addes a super
state that implements the Sender Response Timer
functionality, from which Power Deleiver messages states
can inherit from.

Signed-off-by: default avatarSam Hurst <sbh1187@gmail.com>
parent 2b4a6e52
Loading
Loading
Loading
Loading
+88 −83
Original line number Diff line number Diff line
@@ -654,6 +654,7 @@ static void pe_drs_send_swap_entry(void *obj)

/**
 * @brief PE_DRS_Send_Swap Run state
 *	  NOTE: Sender Response Timer is handled in super state.
 */
static void pe_drs_send_swap_run(void *obj)
{
@@ -663,11 +664,6 @@ static void pe_drs_send_swap_run(void *obj)
	struct protocol_layer_rx_t *prl_rx = data->prl_rx;
	union pd_header header;

	if (atomic_test_and_clear_bit(pe->flags, PE_FLAGS_TX_COMPLETE)) {
		/* Start Sender Response Timer */
		usbc_timer_start(&pe->pd_t_sender_response);
	}

	if (atomic_test_and_clear_bit(pe->flags, PE_FLAGS_MSG_RECEIVED)) {
		header = prl_rx->emsg.header;
		if (received_control_message(dev, header, PD_CTRL_REJECT)) {
@@ -715,22 +711,16 @@ static void pe_drs_send_swap_run(void *obj)
		pe_set_state(dev, PE_SNK_READY);
		return;
	}

	/* Transition to PE_SNK_READY on SenderResponseTimer timeout */
	if (usbc_timer_expired(&pe->pd_t_sender_response)) {
		pe_set_state(dev, PE_SNK_READY);
	}
}

/**
 * @brief PE_DRS_Send_Swap Exit state
 */
static void pe_drs_send_swap_exit(void *obj)
static void pe_suspend_entry(void *obj)
{
	struct policy_engine *pe = (struct policy_engine *)obj;
	LOG_INF("PE_SUSPEND");
}

	/* Stop Sender Response Timer */
	usbc_timer_stop(&pe->pd_t_sender_response);
static void pe_suspend_run(void *obj)
{
	/* DO NOTHING */
}

/**
@@ -745,7 +735,7 @@ enum pe_soft_reset_submachine_states {
};

/**
 * @brief 8.3.3.4.2.1 PE_SNK_Send_Soft_Reset State
 * @brief 8.3.3.4.2.2 PE_SNK_Soft_Reset State
 */
static void pe_soft_reset_entry(void *obj)
{
@@ -772,8 +762,6 @@ static void pe_soft_reset_run(void *obj)
	case PE_SOFT_RESET_RUN_SEND_ACCEPT_MSG:
		/* Send Accept message to SOP */
		pe_send_ctrl_msg(dev, PD_PACKET_SOP, PD_CTRL_ACCEPT);
		/* Start Sender Response Timer */
		usbc_timer_start(&pe->pd_t_sender_response);
		/* Move to next substate */
		pe->submachine = PE_SOFT_RESET_RUN_SEND_ACCEPT_MSG_COMPLETE;
		break;
@@ -785,13 +773,11 @@ static void pe_soft_reset_run(void *obj)
		 */
		if (atomic_test_and_clear_bit(pe->flags, PE_FLAGS_TX_COMPLETE)) {
			pe_set_state(dev, PE_SNK_WAIT_FOR_CAPABILITIES);
		} else if (usbc_timer_expired(&pe->pd_t_sender_response) ||
			   atomic_test_and_clear_bit(pe->flags, PE_FLAGS_PROTOCOL_ERROR)) {
		} else if (atomic_test_and_clear_bit(pe->flags, PE_FLAGS_PROTOCOL_ERROR)) {
			/*
			 * The Policy Engine Shall transition to the
			 * PE_SRC_Hard_Reset state when:
			 *      1: A SenderResponseTimer timeout occurs.
			 *      2: OR the Protocol Layer indicates that a
			 *      1: Protocol Layer indicates that a
			 *         transmission error has occurred.
			 */
			pe_set_state(dev, PE_SNK_HARD_RESET);
@@ -800,16 +786,9 @@ static void pe_soft_reset_run(void *obj)
	}
}

static void pe_soft_reset_exit(void *obj)
{
	struct policy_engine *pe = (struct policy_engine *)obj;

	/* Stop Sender Response Timer */
	usbc_timer_stop(&pe->pd_t_sender_response);
}

/**
 * @brief PE_Send_Soft_Reset Entry State
 *	  NOTE: Sender Response Timer is handled in super state.
 */
static void pe_send_soft_reset_entry(void *obj)
{
@@ -848,46 +827,27 @@ static void pe_send_soft_reset_run(void *obj)
		/* Inform Device Policy Manager that the message was discarded */
		policy_notify(dev, MSG_DISCARDED);
		pe_set_state(dev, PE_SNK_READY);
	} else if (atomic_test_and_clear_bit(pe->flags, PE_FLAGS_TX_COMPLETE)) {
		/* Start SenderResponse timer */
		usbc_timer_start(&pe->pd_t_sender_response);
	}
	} else if (atomic_test_and_clear_bit(pe->flags, PE_FLAGS_MSG_RECEIVED)) {
		/*
		 * The Policy Engine Shall transition to the PE_SNK_Wait_for_Capabilities
		 * state when:
		 *      1: An Accept Message has been received on SOP
		 */
	else if (atomic_test_and_clear_bit(pe->flags, PE_FLAGS_MSG_RECEIVED)) {
		header = prl_rx->emsg.header;

		if (received_control_message(dev, header, PD_CTRL_ACCEPT)) {
			pe_set_state(dev, PE_SNK_WAIT_FOR_CAPABILITIES);
		}
	}
	} else if (atomic_test_and_clear_bit(pe->flags, PE_FLAGS_PROTOCOL_ERROR)) {
		/*
		 * The Policy Engine Shall transition to the PE_SNK_Hard_Reset state when:
	 *      1: A SenderResponseTimer timeout occurs (Handled in pe_report_error function)
		 *      1: A SenderResponseTimer timeout occurs (Handled in Super State)
		 *      2: Or the Protocol Layer indicates that a transmission error has occurred
		 */
	else if (usbc_timer_expired(&pe->pd_t_sender_response) ||
		 atomic_test_and_clear_bit(pe->flags, PE_FLAGS_PROTOCOL_ERROR)) {
		pe_set_state(dev, PE_SNK_HARD_RESET);
	}
}

/**
 * @brief PE_Send_Soft_Reset Exit State
 */
static void pe_send_soft_reset_exit(void *obj)
{
	struct policy_engine *pe = (struct policy_engine *)obj;

	/* Stop Sender Response Timer */
	usbc_timer_stop(&pe->pd_t_sender_response);
}



/**
 * @brief 8.3.3.6.2.1 PE_SNK_Send_Not_Supported State
 */
@@ -956,23 +916,73 @@ static void pe_chunk_received_run(void *obj)
	}
}

/**
 * @brief Suspend State
/*
 * @brief Super State for any message that requires
 *	  Sender Response Timer functionality
 */
static void pe_suspend_entry(void *obj)
static void pe_sender_response_run(void *obj)
{
	LOG_INF("PE_SUSPEND");
	struct policy_engine *pe = (struct policy_engine *)obj;
	const struct device *dev = pe->dev;
	enum usbc_pe_state current_state = pe_get_state(dev);

	/* Start the Sender Response Timer after the message is sent */
	if (atomic_test_and_clear_bit(pe->flags, PE_FLAGS_TX_COMPLETE)) {
		/* Start Sender Response Timer */
		usbc_timer_start(&pe->pd_t_sender_response);
	}

static void pe_suspend_run(void *obj)
	/* Check if the Sender Response Timer has expired */
	if (usbc_timer_expired(&pe->pd_t_sender_response)) {
		/*
		 * Handle Sender Response Timeouts
		 */
		switch (current_state) {
		/* Sink states */
		case PE_SNK_SELECT_CAPABILITY:
			pe_set_state(dev, PE_SNK_HARD_RESET);
			break;
		case PE_SNK_GET_SOURCE_CAP:
			pe_set_state(dev, PE_SNK_READY);
			break;

		/*
		 * Common states:
		 * Could transition to a Sink or Source states,
		 * depending on the current Data Role
		 */
		case PE_SEND_SOFT_RESET:
			pe_set_state(dev, PE_SNK_HARD_RESET);
			break;
		case PE_DRS_SEND_SWAP:
			pe_set_state(dev, PE_SNK_READY);
			break;

		/* This should not happen. Implementation error */
		default:
			LOG_INF("Unhandled Sender Response Timeout State!");
		}
	}
}

static void pe_sender_response_exit(void *obj)
{
	/* DO NOTHING */
	struct policy_engine *pe = (struct policy_engine *)obj;

	/* Stop Sender Response Timer */
	usbc_timer_stop(&pe->pd_t_sender_response);
}

/**
 * @brief Policy engine State table
 */
static const struct smf_state pe_states[] = {
	/* PE Super States */
	[PE_SENDER_RESPONSE_PARENT] = SMF_CREATE_STATE(
		NULL,
		pe_sender_response_run,
		pe_sender_response_exit,
		NULL),
	[PE_SNK_STARTUP] = SMF_CREATE_STATE(
		pe_snk_startup_entry,
		pe_snk_startup_run,
@@ -996,8 +1006,8 @@ static const struct smf_state pe_states[] = {
	[PE_SNK_SELECT_CAPABILITY] = SMF_CREATE_STATE(
		pe_snk_select_capability_entry,
		pe_snk_select_capability_run,
		pe_snk_select_capability_exit,
		NULL),
		NULL,
		&pe_states[PE_SENDER_RESPONSE_PARENT]),
	[PE_SNK_READY] = SMF_CREATE_STATE(
		pe_snk_ready_entry,
		pe_snk_ready_run,
@@ -1021,27 +1031,22 @@ static const struct smf_state pe_states[] = {
	[PE_SNK_GET_SOURCE_CAP] = SMF_CREATE_STATE(
		pe_snk_get_source_cap_entry,
		pe_snk_get_source_cap_run,
		pe_snk_get_source_cap_exit,
		NULL),
		NULL,
		&pe_states[PE_SENDER_RESPONSE_PARENT]),
	[PE_SNK_TRANSITION_SINK] = SMF_CREATE_STATE(
		pe_snk_transition_sink_entry,
		pe_snk_transition_sink_run,
		pe_snk_transition_sink_exit,
		NULL),
	[PE_SNK_GET_SOURCE_CAP] = SMF_CREATE_STATE(
		pe_snk_get_source_cap_entry,
		pe_snk_get_source_cap_run,
		pe_snk_get_source_cap_exit,
		NULL),
	[PE_SEND_SOFT_RESET] = SMF_CREATE_STATE(
		pe_send_soft_reset_entry,
		pe_send_soft_reset_run,
		pe_send_soft_reset_exit,
		NULL),
		NULL,
		&pe_states[PE_SENDER_RESPONSE_PARENT]),
	[PE_SOFT_RESET] = SMF_CREATE_STATE(
		pe_soft_reset_entry,
		pe_soft_reset_run,
		pe_soft_reset_exit,
		NULL,
		NULL),
	[PE_SEND_NOT_SUPPORTED] = SMF_CREATE_STATE(
		pe_send_not_supported_entry,
@@ -1056,8 +1061,8 @@ static const struct smf_state pe_states[] = {
	[PE_DRS_SEND_SWAP] = SMF_CREATE_STATE(
		pe_drs_send_swap_entry,
		pe_drs_send_swap_run,
		pe_drs_send_swap_exit,
		NULL),
		NULL,
		&pe_states[PE_SENDER_RESPONSE_PARENT]),
	[PE_CHUNK_RECEIVED] = SMF_CREATE_STATE(
		pe_chunk_received_entry,
		pe_chunk_received_run,
+8 −0
Original line number Diff line number Diff line
@@ -64,6 +64,14 @@ enum usbc_pe_state {
	/** PE_Suspend. Not part of the PD specification. */
	PE_SUSPEND,

	/**
	 * NOTE: The states below should not be called directly. They're used
	 * internally by the state machine.
	 */

	/** PE_SENDER_RESPONSE_PARENT. Not part of the PD specification. */
	PE_SENDER_RESPONSE_PARENT,

	/** Number of PE States */
	PE_STATE_COUNT
};
+4 −42
Original line number Diff line number Diff line
@@ -237,6 +237,7 @@ void pe_snk_select_capability_entry(void *obj)

/**
 * @brief PE_SNK_Select_Capability Run State
 *	  NOTE: Sender Response Timer is handled in super state.
 */
void pe_snk_select_capability_run(void *obj)
{
@@ -259,9 +260,6 @@ void pe_snk_select_capability_run(void *obj)
		} else {
			pe_set_state(dev, PE_SNK_READY);
		}
	} else if (atomic_test_and_clear_bit(pe->flags, PE_FLAGS_TX_COMPLETE)) {
		/* Start the SenderResponseTimer */
		usbc_timer_start(&pe->pd_t_sender_response);
	}

	if (atomic_test_and_clear_bit(pe->flags, PE_FLAGS_MSG_RECEIVED)) {
@@ -321,23 +319,6 @@ void pe_snk_select_capability_run(void *obj)
		}
		return;
	}

	/* When the SenderResponseTimer times out, perform a Hard Reset. */
	if (usbc_timer_expired(&pe->pd_t_sender_response)) {
		policy_notify(dev, PORT_PARTNER_NOT_RESPONSIVE);
		pe_set_state(dev, PE_SNK_HARD_RESET);
	}
}

/**
 * @brief PE_SNK_Select_Capability Exit State
 */
void pe_snk_select_capability_exit(void *obj)
{
	struct policy_engine *pe = (struct policy_engine *)obj;

	/* Stop SenderResponse Timer */
	usbc_timer_stop(&pe->pd_t_sender_response);
}

/**
@@ -617,6 +598,7 @@ void pe_snk_transition_to_default_run(void *obj)

/**
 * @brief PE_SNK_Get_Source_Cap Entry State
 *
 */
void pe_snk_get_source_cap_entry(void *obj)
{
@@ -636,6 +618,7 @@ void pe_snk_get_source_cap_entry(void *obj)

/**
 * @brief PE_SNK_Get_Source_Cap Run State
 *	  NOTE: Sender Response Timer is handled in super state.
 */
void pe_snk_get_source_cap_run(void *obj)
{
@@ -646,10 +629,7 @@ void pe_snk_get_source_cap_run(void *obj)
	union pd_header header;

	/* Wait until message is sent or dropped */
	if (atomic_test_and_clear_bit(pe->flags, PE_FLAGS_TX_COMPLETE)) {
		/* The Policy Engine Shall then start the SenderResponseTimer. */
		usbc_timer_start(&pe->pd_t_sender_response);
	} else if (atomic_test_and_clear_bit(pe->flags, PE_FLAGS_MSG_RECEIVED)) {
	if (atomic_test_and_clear_bit(pe->flags, PE_FLAGS_MSG_RECEIVED)) {
		/*
		 * The Policy Engine Shall transition to the PE_SNK_Evaluate_Capability
		 * State when:
@@ -661,25 +641,7 @@ void pe_snk_get_source_cap_run(void *obj)
		if (received_control_message(dev, header, PD_DATA_SOURCE_CAP)) {
			pe_set_state(dev, PE_SNK_EVALUATE_CAPABILITY);
		}
	} else if (usbc_timer_expired(&pe->pd_t_sender_response)) {
		/*
		 * The Policy Engine Shall transition to the PE_SNK_Ready state when:
		 *	1: The SenderResponseTimer times out.
		 */
		pe_set_state(dev, PE_SNK_READY);
		/* Inform the DPM of the sender response timeout */
		policy_notify(dev, SENDER_RESPONSE_TIMEOUT);
	}
	}

/**
 * @brief PE_SNK_Get_Source_Cap Exit State
 */
void pe_snk_get_source_cap_exit(void *obj)
{
	struct policy_engine *pe = (struct policy_engine *)obj;

	usbc_timer_stop(&pe->pd_t_sender_response);
}

/**