brintos

brintos / linux-shallow public Read only

0
0
Text · 10.4 KiB · 7f01119 Raw
323 lines · c
1/*2 * Copyright 2019 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25 26#include "hdcp.h"27 28enum mod_hdcp_status mod_hdcp_hdcp1_transition(struct mod_hdcp *hdcp,29		struct mod_hdcp_event_context *event_ctx,30		struct mod_hdcp_transition_input_hdcp1 *input,31		struct mod_hdcp_output *output)32{33	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;34	struct mod_hdcp_connection *conn = &hdcp->connection;35	struct mod_hdcp_link_adjustment *adjust = &hdcp->connection.link.adjust;36 37	switch (current_state(hdcp)) {38	case H1_A0_WAIT_FOR_ACTIVE_RX:39		if (input->bksv_read != PASS || input->bcaps_read != PASS) {40			/* 1A-04: repeatedly attempts on port access failure */41			callback_in_ms(500, output);42			increment_stay_counter(hdcp);43			break;44		}45		callback_in_ms(0, output);46		set_state_id(hdcp, output, H1_A1_EXCHANGE_KSVS);47		break;48	case H1_A1_EXCHANGE_KSVS:49		if (input->create_session != PASS) {50			/* out of sync with psp state */51			adjust->hdcp1.disable = 1;52			fail_and_restart_in_ms(0, &status, output);53			break;54		} else if (input->an_write != PASS ||55				input->aksv_write != PASS ||56				input->bksv_read != PASS ||57				input->bksv_validation != PASS ||58				input->ainfo_write == FAIL) {59			/* 1A-05: consider invalid bksv a failure */60			fail_and_restart_in_ms(0, &status, output);61			break;62		}63		callback_in_ms(300, output);64		set_state_id(hdcp, output,65			H1_A2_COMPUTATIONS_A3_VALIDATE_RX_A6_TEST_FOR_REPEATER);66		break;67	case H1_A2_COMPUTATIONS_A3_VALIDATE_RX_A6_TEST_FOR_REPEATER:68		if (input->bcaps_read != PASS ||69				input->r0p_read != PASS) {70			fail_and_restart_in_ms(0, &status, output);71			break;72		} else if (input->rx_validation != PASS) {73			/* 1A-06: consider invalid r0' a failure */74			/* 1A-08: consider bksv listed in SRM a failure */75			/*76			 * some slow RX will fail rx validation when it is77			 * not ready. give it more time to react before retry.78			 */79			fail_and_restart_in_ms(1000, &status, output);80			break;81		} else if (!conn->is_repeater && input->encryption != PASS) {82			fail_and_restart_in_ms(0, &status, output);83			break;84		}85		if (conn->is_repeater) {86			callback_in_ms(0, output);87			set_watchdog_in_ms(hdcp, 5000, output);88			set_state_id(hdcp, output, H1_A8_WAIT_FOR_READY);89		} else {90			callback_in_ms(0, output);91			set_state_id(hdcp, output, H1_A45_AUTHENTICATED);92			set_auth_complete(hdcp, output);93		}94		break;95	case H1_A45_AUTHENTICATED:96		if (input->link_maintenance == FAIL) {97			/* 1A-07: consider invalid ri' a failure */98			/* 1A-07a: consider read ri' not returned a failure */99			fail_and_restart_in_ms(0, &status, output);100			break;101		}102		callback_in_ms(500, output);103		increment_stay_counter(hdcp);104		break;105	case H1_A8_WAIT_FOR_READY:106		if (input->ready_check != PASS) {107			if (event_ctx->event ==108					MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {109				/* 1B-03: fail hdcp on ksv list READY timeout */110				/* prevent black screen in next attempt */111				adjust->hdcp1.postpone_encryption = 1;112				fail_and_restart_in_ms(0, &status, output);113			} else {114				/* continue ksv list READY polling*/115				callback_in_ms(500, output);116				increment_stay_counter(hdcp);117			}118			break;119		}120		callback_in_ms(0, output);121		set_state_id(hdcp, output, H1_A9_READ_KSV_LIST);122		break;123	case H1_A9_READ_KSV_LIST:124		if (input->bstatus_read != PASS ||125				input->max_cascade_check != PASS ||126				input->max_devs_check != PASS ||127				input->device_count_check != PASS ||128				input->ksvlist_read != PASS ||129				input->vp_read != PASS ||130				input->ksvlist_vp_validation != PASS ||131				input->encryption != PASS) {132			/* 1B-06: consider MAX_CASCADE_EXCEEDED a failure */133			/* 1B-05: consider MAX_DEVS_EXCEEDED a failure */134			/* 1B-04: consider invalid v' a failure */135			fail_and_restart_in_ms(0, &status, output);136			break;137		}138		callback_in_ms(0, output);139		set_state_id(hdcp, output, H1_A45_AUTHENTICATED);140		set_auth_complete(hdcp, output);141		break;142	default:143		status = MOD_HDCP_STATUS_INVALID_STATE;144		fail_and_restart_in_ms(0, &status, output);145		break;146	}147 148	return status;149}150 151enum mod_hdcp_status mod_hdcp_hdcp1_dp_transition(struct mod_hdcp *hdcp,152		struct mod_hdcp_event_context *event_ctx,153		struct mod_hdcp_transition_input_hdcp1 *input,154		struct mod_hdcp_output *output)155{156	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;157	struct mod_hdcp_connection *conn = &hdcp->connection;158	struct mod_hdcp_link_adjustment *adjust = &hdcp->connection.link.adjust;159 160	switch (current_state(hdcp)) {161	case D1_A0_DETERMINE_RX_HDCP_CAPABLE:162		if (input->bcaps_read != PASS) {163			/* 1A-04: no authentication on bcaps read failure */164			fail_and_restart_in_ms(0, &status, output);165			break;166		} else if (input->hdcp_capable_dp != PASS) {167			adjust->hdcp1.disable = 1;168			fail_and_restart_in_ms(0, &status, output);169			break;170		}171		callback_in_ms(0, output);172		set_state_id(hdcp, output, D1_A1_EXCHANGE_KSVS);173		break;174	case D1_A1_EXCHANGE_KSVS:175		if (input->create_session != PASS) {176			/* out of sync with psp state */177			adjust->hdcp1.disable = 1;178			fail_and_restart_in_ms(0, &status, output);179			break;180		} else if (input->an_write != PASS ||181				input->aksv_write != PASS ||182				input->bksv_read != PASS ||183				input->bksv_validation != PASS ||184				input->ainfo_write == FAIL) {185			/* 1A-05: consider invalid bksv a failure */186			fail_and_restart_in_ms(0, &status, output);187			break;188		}189		set_watchdog_in_ms(hdcp, 100, output);190		set_state_id(hdcp, output, D1_A23_WAIT_FOR_R0_PRIME);191		break;192	case D1_A23_WAIT_FOR_R0_PRIME:193		if (input->bstatus_read != PASS) {194			fail_and_restart_in_ms(0, &status, output);195			break;196		} else if (input->r0p_available_dp != PASS) {197			if (event_ctx->event == MOD_HDCP_EVENT_WATCHDOG_TIMEOUT)198				fail_and_restart_in_ms(0, &status, output);199			else200				increment_stay_counter(hdcp);201			break;202		}203		callback_in_ms(0, output);204		set_state_id(hdcp, output, D1_A2_COMPUTATIONS_A3_VALIDATE_RX_A5_TEST_FOR_REPEATER);205		break;206	case D1_A2_COMPUTATIONS_A3_VALIDATE_RX_A5_TEST_FOR_REPEATER:207		if (input->r0p_read != PASS) {208			fail_and_restart_in_ms(0, &status, output);209			break;210		} else if (input->rx_validation != PASS) {211			if (hdcp->state.stay_count < 2 &&212					!hdcp->connection.is_hdcp1_revoked) {213				/* allow 2 additional retries */214				callback_in_ms(0, output);215				increment_stay_counter(hdcp);216			} else {217				/*218				 * 1A-06: consider invalid r0' a failure219				 * after 3 attempts.220				 * 1A-08: consider bksv listed in SRM a failure221				 */222				/*223				 * some slow RX will fail rx validation when it is224				 * not ready. give it more time to react before retry.225				 */226				fail_and_restart_in_ms(1000, &status, output);227			}228			break;229		} else if ((!conn->is_repeater && input->encryption != PASS) ||230				(!conn->is_repeater && is_dp_mst_hdcp(hdcp) && input->stream_encryption_dp != PASS)) {231			fail_and_restart_in_ms(0, &status, output);232			break;233		} else if (conn->hdcp1_retry_count < conn->link.adjust.hdcp1.min_auth_retries_wa) {234			fail_and_restart_in_ms(200, &status, output);235			break;236		}237		if (conn->is_repeater) {238			set_watchdog_in_ms(hdcp, 5000, output);239			set_state_id(hdcp, output, D1_A6_WAIT_FOR_READY);240		} else {241			set_state_id(hdcp, output, D1_A4_AUTHENTICATED);242			set_auth_complete(hdcp, output);243		}244		break;245	case D1_A4_AUTHENTICATED:246		if (input->link_integrity_check == FAIL ||247				input->reauth_request_check == FAIL) {248			/* 1A-07: restart hdcp on a link integrity failure */249			fail_and_restart_in_ms(0, &status, output);250			break;251		}252		break;253	case D1_A6_WAIT_FOR_READY:254		if (input->link_integrity_check == FAIL ||255				input->reauth_request_check == FAIL) {256			fail_and_restart_in_ms(0, &status, output);257			break;258		} else if (input->ready_check != PASS) {259			if (event_ctx->event ==260					MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {261				/* 1B-04: fail hdcp on ksv list READY timeout */262				/* prevent black screen in next attempt */263				adjust->hdcp1.postpone_encryption = 1;264				fail_and_restart_in_ms(0, &status, output);265			} else {266				increment_stay_counter(hdcp);267			}268			break;269		}270		callback_in_ms(0, output);271		set_state_id(hdcp, output, D1_A7_READ_KSV_LIST);272		break;273	case D1_A7_READ_KSV_LIST:274		if (input->binfo_read_dp != PASS ||275				input->max_cascade_check != PASS ||276				input->max_devs_check != PASS) {277			/* 1B-06: consider MAX_DEVS_EXCEEDED a failure */278			/* 1B-07: consider MAX_CASCADE_EXCEEDED a failure */279			fail_and_restart_in_ms(0, &status, output);280			break;281		} else if (input->device_count_check != PASS) {282			/*283			 * some slow dongle doesn't update284			 * device count as soon as downstream is connected.285			 * give it more time to react.286			 */287			adjust->hdcp1.postpone_encryption = 1;288			fail_and_restart_in_ms(1000, &status, output);289			break;290		} else if (input->ksvlist_read != PASS ||291				input->vp_read != PASS) {292			fail_and_restart_in_ms(0, &status, output);293			break;294		} else if (input->ksvlist_vp_validation != PASS) {295			if (hdcp->state.stay_count < 2 &&296					!hdcp->connection.is_hdcp1_revoked) {297				/* allow 2 additional retries */298				callback_in_ms(0, output);299				increment_stay_counter(hdcp);300			} else {301				/*302				 * 1B-05: consider invalid v' a failure303				 * after 3 attempts.304				 */305				fail_and_restart_in_ms(0, &status, output);306			}307			break;308		} else if (input->encryption != PASS ||309				(is_dp_mst_hdcp(hdcp) && input->stream_encryption_dp != PASS)) {310			fail_and_restart_in_ms(0, &status, output);311			break;312		}313		set_state_id(hdcp, output, D1_A4_AUTHENTICATED);314		set_auth_complete(hdcp, output);315		break;316	default:317		fail_and_restart_in_ms(0, &status, output);318		break;319	}320 321	return status;322}323