cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hdcp.c (18175B)


      1/*
      2 * Copyright 2019 Advanced Micro Devices, Inc.
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice shall be included in
     12 * all copies or substantial portions of the Software.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 * OTHER DEALINGS IN THE SOFTWARE.
     21 *
     22 * Authors: AMD
     23 *
     24 */
     25
     26#include "hdcp.h"
     27
     28static void push_error_status(struct mod_hdcp *hdcp,
     29		enum mod_hdcp_status status)
     30{
     31	struct mod_hdcp_trace *trace = &hdcp->connection.trace;
     32
     33	if (trace->error_count < MAX_NUM_OF_ERROR_TRACE) {
     34		trace->errors[trace->error_count].status = status;
     35		trace->errors[trace->error_count].state_id = hdcp->state.id;
     36		trace->error_count++;
     37		HDCP_ERROR_TRACE(hdcp, status);
     38	}
     39
     40	if (is_hdcp1(hdcp)) {
     41		hdcp->connection.hdcp1_retry_count++;
     42		if (hdcp->connection.hdcp1_retry_count == MAX_NUM_OF_ATTEMPTS)
     43			hdcp->connection.link.adjust.hdcp1.disable = 1;
     44	} else if (is_hdcp2(hdcp)) {
     45		hdcp->connection.hdcp2_retry_count++;
     46		if (hdcp->connection.hdcp2_retry_count == MAX_NUM_OF_ATTEMPTS)
     47			hdcp->connection.link.adjust.hdcp2.disable = 1;
     48	}
     49}
     50
     51static uint8_t is_cp_desired_hdcp1(struct mod_hdcp *hdcp)
     52{
     53	int i, is_auth_needed = 0;
     54
     55	/* if all displays on the link don't need authentication,
     56	 * hdcp is not desired
     57	 */
     58	for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) {
     59		if (hdcp->displays[i].state != MOD_HDCP_DISPLAY_INACTIVE &&
     60				hdcp->displays[i].adjust.disable != MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION) {
     61			is_auth_needed = 1;
     62			break;
     63		}
     64	}
     65
     66	return is_auth_needed &&
     67			!hdcp->connection.link.adjust.hdcp1.disable &&
     68			!hdcp->connection.is_hdcp1_revoked;
     69}
     70
     71static uint8_t is_cp_desired_hdcp2(struct mod_hdcp *hdcp)
     72{
     73	int i, is_auth_needed = 0;
     74
     75	/* if all displays on the link don't need authentication,
     76	 * hdcp is not desired
     77	 */
     78	for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) {
     79		if (hdcp->displays[i].state != MOD_HDCP_DISPLAY_INACTIVE &&
     80				hdcp->displays[i].adjust.disable != MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION) {
     81			is_auth_needed = 1;
     82			break;
     83		}
     84	}
     85
     86	return is_auth_needed &&
     87			!hdcp->connection.link.adjust.hdcp2.disable &&
     88			!hdcp->connection.is_hdcp2_revoked;
     89}
     90
     91static enum mod_hdcp_status execution(struct mod_hdcp *hdcp,
     92		struct mod_hdcp_event_context *event_ctx,
     93		union mod_hdcp_transition_input *input)
     94{
     95	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
     96
     97	if (is_in_initialized_state(hdcp)) {
     98		if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
     99			event_ctx->unexpected_event = 1;
    100			goto out;
    101		}
    102		/* initialize transition input */
    103		memset(input, 0, sizeof(union mod_hdcp_transition_input));
    104	} else if (is_in_cp_not_desired_state(hdcp)) {
    105		if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
    106			event_ctx->unexpected_event = 1;
    107			goto out;
    108		}
    109	} else if (is_in_hdcp1_states(hdcp)) {
    110		status = mod_hdcp_hdcp1_execution(hdcp, event_ctx, &input->hdcp1);
    111	} else if (is_in_hdcp1_dp_states(hdcp)) {
    112		status = mod_hdcp_hdcp1_dp_execution(hdcp,
    113				event_ctx, &input->hdcp1);
    114	} else if (is_in_hdcp2_states(hdcp)) {
    115		status = mod_hdcp_hdcp2_execution(hdcp, event_ctx, &input->hdcp2);
    116	} else if (is_in_hdcp2_dp_states(hdcp)) {
    117		status = mod_hdcp_hdcp2_dp_execution(hdcp,
    118				event_ctx, &input->hdcp2);
    119	} else {
    120		event_ctx->unexpected_event = 1;
    121		goto out;
    122	}
    123out:
    124	return status;
    125}
    126
    127static enum mod_hdcp_status transition(struct mod_hdcp *hdcp,
    128		struct mod_hdcp_event_context *event_ctx,
    129		union mod_hdcp_transition_input *input,
    130		struct mod_hdcp_output *output)
    131{
    132	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    133
    134	if (event_ctx->unexpected_event)
    135		goto out;
    136
    137	if (is_in_initialized_state(hdcp)) {
    138		if (is_dp_hdcp(hdcp))
    139			if (is_cp_desired_hdcp2(hdcp)) {
    140				callback_in_ms(0, output);
    141				set_state_id(hdcp, output, D2_A0_DETERMINE_RX_HDCP_CAPABLE);
    142			} else if (is_cp_desired_hdcp1(hdcp)) {
    143				callback_in_ms(0, output);
    144				set_state_id(hdcp, output, D1_A0_DETERMINE_RX_HDCP_CAPABLE);
    145			} else {
    146				callback_in_ms(0, output);
    147				set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED);
    148				set_auth_complete(hdcp, output);
    149			}
    150		else if (is_hdmi_dvi_sl_hdcp(hdcp))
    151			if (is_cp_desired_hdcp2(hdcp)) {
    152				callback_in_ms(0, output);
    153				set_state_id(hdcp, output, H2_A0_KNOWN_HDCP2_CAPABLE_RX);
    154			} else if (is_cp_desired_hdcp1(hdcp)) {
    155				callback_in_ms(0, output);
    156				set_state_id(hdcp, output, H1_A0_WAIT_FOR_ACTIVE_RX);
    157			} else {
    158				callback_in_ms(0, output);
    159				set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED);
    160				set_auth_complete(hdcp, output);
    161			}
    162		else {
    163			callback_in_ms(0, output);
    164			set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED);
    165			set_auth_complete(hdcp, output);
    166		}
    167	} else if (is_in_cp_not_desired_state(hdcp)) {
    168		increment_stay_counter(hdcp);
    169	} else if (is_in_hdcp1_states(hdcp)) {
    170		status = mod_hdcp_hdcp1_transition(hdcp,
    171				event_ctx, &input->hdcp1, output);
    172	} else if (is_in_hdcp1_dp_states(hdcp)) {
    173		status = mod_hdcp_hdcp1_dp_transition(hdcp,
    174				event_ctx, &input->hdcp1, output);
    175	} else if (is_in_hdcp2_states(hdcp)) {
    176		status = mod_hdcp_hdcp2_transition(hdcp,
    177				event_ctx, &input->hdcp2, output);
    178	} else if (is_in_hdcp2_dp_states(hdcp)) {
    179		status = mod_hdcp_hdcp2_dp_transition(hdcp,
    180				event_ctx, &input->hdcp2, output);
    181	} else {
    182		status = MOD_HDCP_STATUS_INVALID_STATE;
    183	}
    184out:
    185	return status;
    186}
    187
    188static enum mod_hdcp_status reset_authentication(struct mod_hdcp *hdcp,
    189		struct mod_hdcp_output *output)
    190{
    191	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    192
    193	if (is_hdcp1(hdcp)) {
    194		if (hdcp->auth.trans_input.hdcp1.create_session != UNKNOWN) {
    195			/* TODO - update psp to unify create session failure
    196			 * recovery between hdcp1 and 2.
    197			 */
    198			mod_hdcp_hdcp1_destroy_session(hdcp);
    199
    200		}
    201
    202		HDCP_TOP_RESET_AUTH_TRACE(hdcp);
    203		memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication));
    204		memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state));
    205		set_state_id(hdcp, output, HDCP_INITIALIZED);
    206	} else if (is_hdcp2(hdcp)) {
    207		if (hdcp->auth.trans_input.hdcp2.create_session == PASS) {
    208			status = mod_hdcp_hdcp2_destroy_session(hdcp);
    209			if (status != MOD_HDCP_STATUS_SUCCESS) {
    210				output->callback_needed = 0;
    211				output->watchdog_timer_needed = 0;
    212				goto out;
    213			}
    214		}
    215
    216		HDCP_TOP_RESET_AUTH_TRACE(hdcp);
    217		memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication));
    218		memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state));
    219		set_state_id(hdcp, output, HDCP_INITIALIZED);
    220	} else if (is_in_cp_not_desired_state(hdcp)) {
    221		HDCP_TOP_RESET_AUTH_TRACE(hdcp);
    222		memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication));
    223		memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state));
    224		set_state_id(hdcp, output, HDCP_INITIALIZED);
    225	}
    226
    227out:
    228	/* stop callback and watchdog requests from previous authentication*/
    229	output->watchdog_timer_stop = 1;
    230	output->callback_stop = 1;
    231	return status;
    232}
    233
    234static enum mod_hdcp_status reset_connection(struct mod_hdcp *hdcp,
    235		struct mod_hdcp_output *output)
    236{
    237	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    238
    239	memset(output, 0, sizeof(struct mod_hdcp_output));
    240
    241	status = reset_authentication(hdcp, output);
    242	if (status != MOD_HDCP_STATUS_SUCCESS)
    243		goto out;
    244
    245	if (current_state(hdcp) != HDCP_UNINITIALIZED) {
    246		HDCP_TOP_RESET_CONN_TRACE(hdcp);
    247		set_state_id(hdcp, output, HDCP_UNINITIALIZED);
    248	}
    249	memset(&hdcp->connection, 0, sizeof(hdcp->connection));
    250out:
    251	return status;
    252}
    253
    254static enum mod_hdcp_status update_display_adjustments(struct mod_hdcp *hdcp,
    255		struct mod_hdcp_display *display,
    256		struct mod_hdcp_display_adjustment *adj)
    257{
    258	enum mod_hdcp_status status = MOD_HDCP_STATUS_NOT_IMPLEMENTED;
    259
    260	if (is_in_authenticated_states(hdcp) &&
    261			is_dp_mst_hdcp(hdcp) &&
    262			display->adjust.disable == true &&
    263			adj->disable == false) {
    264		display->adjust.disable = false;
    265		if (is_hdcp1(hdcp))
    266			status = mod_hdcp_hdcp1_enable_dp_stream_encryption(hdcp);
    267		else if (is_hdcp2(hdcp))
    268			status = mod_hdcp_hdcp2_enable_dp_stream_encryption(hdcp);
    269
    270		if (status != MOD_HDCP_STATUS_SUCCESS)
    271			display->adjust.disable = true;
    272	}
    273
    274	if (status == MOD_HDCP_STATUS_SUCCESS &&
    275		memcmp(adj, &display->adjust,
    276		sizeof(struct mod_hdcp_display_adjustment)) != 0)
    277		status = MOD_HDCP_STATUS_NOT_IMPLEMENTED;
    278
    279	return status;
    280}
    281/*
    282 * Implementation of functions in mod_hdcp.h
    283 */
    284size_t mod_hdcp_get_memory_size(void)
    285{
    286	return sizeof(struct mod_hdcp);
    287}
    288
    289enum mod_hdcp_status mod_hdcp_setup(struct mod_hdcp *hdcp,
    290		struct mod_hdcp_config *config)
    291{
    292	struct mod_hdcp_output output;
    293	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    294
    295	memset(&output, 0, sizeof(output));
    296	hdcp->config = *config;
    297	HDCP_TOP_INTERFACE_TRACE(hdcp);
    298	status = reset_connection(hdcp, &output);
    299	if (status != MOD_HDCP_STATUS_SUCCESS)
    300		push_error_status(hdcp, status);
    301	return status;
    302}
    303
    304enum mod_hdcp_status mod_hdcp_teardown(struct mod_hdcp *hdcp)
    305{
    306	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    307	struct mod_hdcp_output output;
    308
    309	HDCP_TOP_INTERFACE_TRACE(hdcp);
    310	memset(&output, 0,  sizeof(output));
    311	status = reset_connection(hdcp, &output);
    312	if (status == MOD_HDCP_STATUS_SUCCESS)
    313		memset(hdcp, 0, sizeof(struct mod_hdcp));
    314	else
    315		push_error_status(hdcp, status);
    316	return status;
    317}
    318
    319enum mod_hdcp_status mod_hdcp_add_display(struct mod_hdcp *hdcp,
    320		struct mod_hdcp_link *link, struct mod_hdcp_display *display,
    321		struct mod_hdcp_output *output)
    322{
    323	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    324	struct mod_hdcp_display *display_container = NULL;
    325
    326	HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, display->index);
    327	memset(output, 0, sizeof(struct mod_hdcp_output));
    328
    329	/* skip inactive display */
    330	if (display->state != MOD_HDCP_DISPLAY_ACTIVE) {
    331		status = MOD_HDCP_STATUS_SUCCESS;
    332		goto out;
    333	}
    334
    335	/* check existing display container */
    336	if (get_active_display_at_index(hdcp, display->index)) {
    337		status = MOD_HDCP_STATUS_SUCCESS;
    338		goto out;
    339	}
    340
    341	/* find an empty display container */
    342	display_container = get_empty_display_container(hdcp);
    343	if (!display_container) {
    344		status = MOD_HDCP_STATUS_DISPLAY_OUT_OF_BOUND;
    345		goto out;
    346	}
    347
    348	/* reset existing authentication status */
    349	status = reset_authentication(hdcp, output);
    350	if (status != MOD_HDCP_STATUS_SUCCESS)
    351		goto out;
    352
    353	/* reset retry counters */
    354	reset_retry_counts(hdcp);
    355
    356	/* reset error trace */
    357	memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace));
    358
    359	/* add display to connection */
    360	hdcp->connection.link = *link;
    361	*display_container = *display;
    362	status = mod_hdcp_add_display_to_topology(hdcp, display_container);
    363
    364	if (status != MOD_HDCP_STATUS_SUCCESS)
    365		goto out;
    366
    367	/* request authentication */
    368	if (current_state(hdcp) != HDCP_INITIALIZED)
    369		set_state_id(hdcp, output, HDCP_INITIALIZED);
    370	callback_in_ms(hdcp->connection.link.adjust.auth_delay * 1000, output);
    371out:
    372	if (status != MOD_HDCP_STATUS_SUCCESS)
    373		push_error_status(hdcp, status);
    374
    375	return status;
    376}
    377
    378enum mod_hdcp_status mod_hdcp_remove_display(struct mod_hdcp *hdcp,
    379		uint8_t index, struct mod_hdcp_output *output)
    380{
    381	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    382	struct mod_hdcp_display *display = NULL;
    383
    384	HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, index);
    385	memset(output, 0, sizeof(struct mod_hdcp_output));
    386
    387	/* find display in connection */
    388	display = get_active_display_at_index(hdcp, index);
    389	if (!display) {
    390		status = MOD_HDCP_STATUS_SUCCESS;
    391		goto out;
    392	}
    393
    394	/* stop current authentication */
    395	status = reset_authentication(hdcp, output);
    396	if (status != MOD_HDCP_STATUS_SUCCESS)
    397		goto out;
    398
    399	/* clear retry counters */
    400	reset_retry_counts(hdcp);
    401
    402	/* reset error trace */
    403	memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace));
    404
    405	/* remove display */
    406	status = mod_hdcp_remove_display_from_topology(hdcp, index);
    407	if (status != MOD_HDCP_STATUS_SUCCESS)
    408		goto out;
    409	memset(display, 0, sizeof(struct mod_hdcp_display));
    410
    411	/* request authentication when connection is not reset */
    412	if (current_state(hdcp) != HDCP_UNINITIALIZED)
    413		callback_in_ms(hdcp->connection.link.adjust.auth_delay * 1000,
    414				output);
    415out:
    416	if (status != MOD_HDCP_STATUS_SUCCESS)
    417		push_error_status(hdcp, status);
    418	return status;
    419}
    420
    421enum mod_hdcp_status mod_hdcp_update_display(struct mod_hdcp *hdcp,
    422		uint8_t index,
    423		struct mod_hdcp_link_adjustment *link_adjust,
    424		struct mod_hdcp_display_adjustment *display_adjust,
    425		struct mod_hdcp_output *output)
    426{
    427	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    428	struct mod_hdcp_display *display = NULL;
    429
    430	HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, index);
    431	memset(output, 0, sizeof(struct mod_hdcp_output));
    432
    433	/* find display in connection */
    434	display = get_active_display_at_index(hdcp, index);
    435	if (!display) {
    436		status = MOD_HDCP_STATUS_DISPLAY_NOT_FOUND;
    437		goto out;
    438	}
    439
    440	/* skip if no changes */
    441	if (memcmp(link_adjust, &hdcp->connection.link.adjust,
    442			sizeof(struct mod_hdcp_link_adjustment)) == 0 &&
    443			memcmp(display_adjust, &display->adjust,
    444					sizeof(struct mod_hdcp_display_adjustment)) == 0) {
    445		status = MOD_HDCP_STATUS_SUCCESS;
    446		goto out;
    447	}
    448
    449	if (memcmp(link_adjust, &hdcp->connection.link.adjust,
    450			sizeof(struct mod_hdcp_link_adjustment)) == 0 &&
    451			memcmp(display_adjust, &display->adjust,
    452					sizeof(struct mod_hdcp_display_adjustment)) != 0) {
    453		status = update_display_adjustments(hdcp, display, display_adjust);
    454		if (status != MOD_HDCP_STATUS_NOT_IMPLEMENTED)
    455			goto out;
    456	}
    457
    458	/* stop current authentication */
    459	status = reset_authentication(hdcp, output);
    460	if (status != MOD_HDCP_STATUS_SUCCESS)
    461		goto out;
    462
    463	/* clear retry counters */
    464	reset_retry_counts(hdcp);
    465
    466	/* reset error trace */
    467	memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace));
    468
    469	/* set new adjustment */
    470	hdcp->connection.link.adjust = *link_adjust;
    471	display->adjust = *display_adjust;
    472
    473	/* request authentication when connection is not reset */
    474	if (current_state(hdcp) != HDCP_UNINITIALIZED)
    475		/* wait 100ms to debounce simultaneous updates for different indices */
    476		callback_in_ms(100, output);
    477
    478out:
    479	if (status != MOD_HDCP_STATUS_SUCCESS)
    480		push_error_status(hdcp, status);
    481	return status;
    482}
    483
    484enum mod_hdcp_status mod_hdcp_query_display(struct mod_hdcp *hdcp,
    485		uint8_t index, struct mod_hdcp_display_query *query)
    486{
    487	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    488	struct mod_hdcp_display *display = NULL;
    489
    490	/* find display in connection */
    491	display = get_active_display_at_index(hdcp, index);
    492	if (!display) {
    493		status = MOD_HDCP_STATUS_DISPLAY_NOT_FOUND;
    494		goto out;
    495	}
    496
    497	/* populate query */
    498	query->link = &hdcp->connection.link;
    499	query->display = display;
    500	query->trace = &hdcp->connection.trace;
    501	query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
    502
    503	if (is_display_encryption_enabled(display)) {
    504		if (is_hdcp1(hdcp)) {
    505			query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP1_ON;
    506		} else if (is_hdcp2(hdcp)) {
    507			if (query->link->adjust.hdcp2.force_type == MOD_HDCP_FORCE_TYPE_0)
    508				query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE0_ON;
    509			else if (query->link->adjust.hdcp2.force_type == MOD_HDCP_FORCE_TYPE_1)
    510				query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE1_ON;
    511			else
    512				query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP2_ON;
    513		}
    514	} else {
    515		query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
    516	}
    517
    518out:
    519	return status;
    520}
    521
    522enum mod_hdcp_status mod_hdcp_reset_connection(struct mod_hdcp *hdcp,
    523		struct mod_hdcp_output *output)
    524{
    525	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    526
    527	HDCP_TOP_INTERFACE_TRACE(hdcp);
    528	status = reset_connection(hdcp, output);
    529	if (status != MOD_HDCP_STATUS_SUCCESS)
    530		push_error_status(hdcp, status);
    531
    532	return status;
    533}
    534
    535enum mod_hdcp_status mod_hdcp_process_event(struct mod_hdcp *hdcp,
    536		enum mod_hdcp_event event, struct mod_hdcp_output *output)
    537{
    538	enum mod_hdcp_status exec_status, trans_status, reset_status, status;
    539	struct mod_hdcp_event_context event_ctx;
    540
    541	HDCP_EVENT_TRACE(hdcp, event);
    542	memset(output, 0, sizeof(struct mod_hdcp_output));
    543	memset(&event_ctx, 0, sizeof(struct mod_hdcp_event_context));
    544	event_ctx.event = event;
    545
    546	/* execute and transition */
    547	exec_status = execution(hdcp, &event_ctx, &hdcp->auth.trans_input);
    548	trans_status = transition(
    549			hdcp, &event_ctx, &hdcp->auth.trans_input, output);
    550	if (trans_status == MOD_HDCP_STATUS_SUCCESS) {
    551		status = MOD_HDCP_STATUS_SUCCESS;
    552	} else if (exec_status == MOD_HDCP_STATUS_SUCCESS) {
    553		status = MOD_HDCP_STATUS_INTERNAL_POLICY_FAILURE;
    554		push_error_status(hdcp, status);
    555	} else {
    556		status = exec_status;
    557		push_error_status(hdcp, status);
    558	}
    559
    560	/* reset authentication if needed */
    561	if (trans_status == MOD_HDCP_STATUS_RESET_NEEDED) {
    562		mod_hdcp_log_ddc_trace(hdcp);
    563		reset_status = reset_authentication(hdcp, output);
    564		if (reset_status != MOD_HDCP_STATUS_SUCCESS)
    565			push_error_status(hdcp, reset_status);
    566	}
    567
    568	/* Clear CP_IRQ status if needed */
    569	if (event_ctx.event == MOD_HDCP_EVENT_CPIRQ) {
    570		status = mod_hdcp_clear_cp_irq_status(hdcp);
    571		if (status != MOD_HDCP_STATUS_SUCCESS)
    572			push_error_status(hdcp, status);
    573	}
    574
    575	return status;
    576}
    577
    578enum mod_hdcp_operation_mode mod_hdcp_signal_type_to_operation_mode(
    579		enum signal_type signal)
    580{
    581	enum mod_hdcp_operation_mode mode = MOD_HDCP_MODE_OFF;
    582
    583	switch (signal) {
    584	case SIGNAL_TYPE_DVI_SINGLE_LINK:
    585	case SIGNAL_TYPE_HDMI_TYPE_A:
    586		mode = MOD_HDCP_MODE_DEFAULT;
    587		break;
    588	case SIGNAL_TYPE_EDP:
    589	case SIGNAL_TYPE_DISPLAY_PORT:
    590	case SIGNAL_TYPE_DISPLAY_PORT_MST:
    591		mode = MOD_HDCP_MODE_DP;
    592		break;
    593	default:
    594		break;
    595	}
    596
    597	return mode;
    598}