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

hdcp2_transition.c (22174B)


      1/*
      2 * Copyright 2018 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
     28enum mod_hdcp_status mod_hdcp_hdcp2_transition(struct mod_hdcp *hdcp,
     29		struct mod_hdcp_event_context *event_ctx,
     30		struct mod_hdcp_transition_input_hdcp2 *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 H2_A0_KNOWN_HDCP2_CAPABLE_RX:
     39		if (input->hdcp2version_read != PASS ||
     40				input->hdcp2_capable_check != PASS) {
     41			adjust->hdcp2.disable = 1;
     42			callback_in_ms(0, output);
     43			set_state_id(hdcp, output, HDCP_INITIALIZED);
     44		} else {
     45			callback_in_ms(0, output);
     46			set_state_id(hdcp, output, H2_A1_SEND_AKE_INIT);
     47		}
     48		break;
     49	case H2_A1_SEND_AKE_INIT:
     50		if (input->create_session != PASS ||
     51				input->ake_init_prepare != PASS) {
     52			/* out of sync with psp state */
     53			adjust->hdcp2.disable = 1;
     54			fail_and_restart_in_ms(0, &status, output);
     55			break;
     56		} else if (input->ake_init_write != PASS) {
     57			fail_and_restart_in_ms(0, &status, output);
     58			break;
     59		}
     60		set_watchdog_in_ms(hdcp, 100, output);
     61		callback_in_ms(0, output);
     62		set_state_id(hdcp, output, H2_A1_VALIDATE_AKE_CERT);
     63		break;
     64	case H2_A1_VALIDATE_AKE_CERT:
     65		if (input->ake_cert_available != PASS) {
     66			if (event_ctx->event ==
     67					MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
     68				/* 1A-08: consider ake timeout a failure */
     69				/* some hdmi receivers are not ready for HDCP
     70				 * immediately after video becomes active,
     71				 * delay 1s before retry on first HDCP message
     72				 * timeout.
     73				 */
     74				fail_and_restart_in_ms(1000, &status, output);
     75			} else {
     76				/* continue ake cert polling*/
     77				callback_in_ms(10, output);
     78				increment_stay_counter(hdcp);
     79			}
     80			break;
     81		} else if (input->ake_cert_read != PASS ||
     82				input->ake_cert_validation != PASS) {
     83			/*
     84			 * 1A-09: consider invalid ake cert a failure
     85			 * 1A-10: consider receiver id listed in SRM a failure
     86			 */
     87			fail_and_restart_in_ms(0, &status, output);
     88			break;
     89		}
     90		if (conn->is_km_stored &&
     91				!adjust->hdcp2.force_no_stored_km) {
     92			callback_in_ms(0, output);
     93			set_state_id(hdcp, output, H2_A1_SEND_STORED_KM);
     94		} else {
     95			callback_in_ms(0, output);
     96			set_state_id(hdcp, output, H2_A1_SEND_NO_STORED_KM);
     97		}
     98		break;
     99	case H2_A1_SEND_NO_STORED_KM:
    100		if (input->no_stored_km_write != PASS) {
    101			fail_and_restart_in_ms(0, &status, output);
    102			break;
    103		}
    104		if (adjust->hdcp2.increase_h_prime_timeout)
    105			set_watchdog_in_ms(hdcp, 2000, output);
    106		else
    107			set_watchdog_in_ms(hdcp, 1000, output);
    108		callback_in_ms(0, output);
    109		set_state_id(hdcp, output, H2_A1_READ_H_PRIME);
    110		break;
    111	case H2_A1_READ_H_PRIME:
    112		if (input->h_prime_available != PASS) {
    113			if (event_ctx->event ==
    114					MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
    115				/* 1A-11-3: consider h' timeout a failure */
    116				fail_and_restart_in_ms(1000, &status, output);
    117			} else {
    118				/* continue h' polling */
    119				callback_in_ms(100, output);
    120				increment_stay_counter(hdcp);
    121			}
    122			break;
    123		} else if (input->h_prime_read != PASS) {
    124			fail_and_restart_in_ms(0, &status, output);
    125			break;
    126		}
    127		set_watchdog_in_ms(hdcp, 200, output);
    128		callback_in_ms(0, output);
    129		set_state_id(hdcp, output, H2_A1_READ_PAIRING_INFO_AND_VALIDATE_H_PRIME);
    130		break;
    131	case H2_A1_READ_PAIRING_INFO_AND_VALIDATE_H_PRIME:
    132		if (input->pairing_available != PASS) {
    133			if (event_ctx->event ==
    134					MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
    135				/* 1A-12: consider pairing info timeout
    136				 * a failure
    137				 */
    138				fail_and_restart_in_ms(0, &status, output);
    139			} else {
    140				/* continue pairing info polling */
    141				callback_in_ms(20, output);
    142				increment_stay_counter(hdcp);
    143			}
    144			break;
    145		} else if (input->pairing_info_read != PASS ||
    146				input->h_prime_validation != PASS) {
    147			/* 1A-11-1: consider invalid h' a failure */
    148			fail_and_restart_in_ms(0, &status, output);
    149			break;
    150		}
    151		callback_in_ms(0, output);
    152		set_state_id(hdcp, output, H2_A2_LOCALITY_CHECK);
    153		break;
    154	case H2_A1_SEND_STORED_KM:
    155		if (input->stored_km_write != PASS) {
    156			fail_and_restart_in_ms(0, &status, output);
    157			break;
    158		}
    159		set_watchdog_in_ms(hdcp, 200, output);
    160		callback_in_ms(0, output);
    161		set_state_id(hdcp, output, H2_A1_VALIDATE_H_PRIME);
    162		break;
    163	case H2_A1_VALIDATE_H_PRIME:
    164		if (input->h_prime_available != PASS) {
    165			if (event_ctx->event ==
    166					MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
    167				/* 1A-11-2: consider h' timeout a failure */
    168				fail_and_restart_in_ms(1000, &status, output);
    169			} else {
    170				/* continue h' polling */
    171				callback_in_ms(20, output);
    172				increment_stay_counter(hdcp);
    173			}
    174			break;
    175		} else if (input->h_prime_read != PASS) {
    176			fail_and_restart_in_ms(0, &status, output);
    177			break;
    178		} else if (input->h_prime_validation != PASS) {
    179			/* 1A-11-1: consider invalid h' a failure */
    180			adjust->hdcp2.force_no_stored_km = 1;
    181			fail_and_restart_in_ms(0, &status, output);
    182			break;
    183		}
    184		callback_in_ms(0, output);
    185		set_state_id(hdcp, output, H2_A2_LOCALITY_CHECK);
    186		break;
    187	case H2_A2_LOCALITY_CHECK:
    188		if (hdcp->state.stay_count > 10 ||
    189				input->lc_init_prepare != PASS ||
    190				input->lc_init_write != PASS ||
    191				input->l_prime_available_poll != PASS ||
    192				input->l_prime_read != PASS) {
    193			/*
    194			 * 1A-05: consider disconnection after LC init a failure
    195			 * 1A-13-1: consider invalid l' a failure
    196			 * 1A-13-2: consider l' timeout a failure
    197			 */
    198			fail_and_restart_in_ms(0, &status, output);
    199			break;
    200		} else if (input->l_prime_validation != PASS) {
    201			callback_in_ms(0, output);
    202			increment_stay_counter(hdcp);
    203			break;
    204		}
    205		callback_in_ms(0, output);
    206		set_state_id(hdcp, output, H2_A3_EXCHANGE_KS_AND_TEST_FOR_REPEATER);
    207		break;
    208	case H2_A3_EXCHANGE_KS_AND_TEST_FOR_REPEATER:
    209		if (input->eks_prepare != PASS ||
    210				input->eks_write != PASS) {
    211			fail_and_restart_in_ms(0, &status, output);
    212			break;
    213		}
    214		if (conn->is_repeater) {
    215			set_watchdog_in_ms(hdcp, 3000, output);
    216			callback_in_ms(0, output);
    217			set_state_id(hdcp, output, H2_A6_WAIT_FOR_RX_ID_LIST);
    218		} else {
    219			/* some CTS equipment requires a delay GREATER than
    220			 * 200 ms, so delay 210 ms instead of 200 ms
    221			 */
    222			callback_in_ms(210, output);
    223			set_state_id(hdcp, output, H2_ENABLE_ENCRYPTION);
    224		}
    225		break;
    226	case H2_ENABLE_ENCRYPTION:
    227		if (input->rxstatus_read != PASS ||
    228				input->reauth_request_check != PASS) {
    229			/*
    230			 * 1A-07: restart hdcp on REAUTH_REQ
    231			 * 1B-08: restart hdcp on REAUTH_REQ
    232			 */
    233			fail_and_restart_in_ms(0, &status, output);
    234			break;
    235		} else if (event_ctx->rx_id_list_ready && conn->is_repeater) {
    236			callback_in_ms(0, output);
    237			set_state_id(hdcp, output, H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
    238			break;
    239		} else if (input->enable_encryption != PASS) {
    240			fail_and_restart_in_ms(0, &status, output);
    241			break;
    242		}
    243		callback_in_ms(0, output);
    244		set_state_id(hdcp, output, H2_A5_AUTHENTICATED);
    245		set_auth_complete(hdcp, output);
    246		break;
    247	case H2_A5_AUTHENTICATED:
    248		if (input->rxstatus_read == FAIL ||
    249				input->reauth_request_check == FAIL) {
    250			fail_and_restart_in_ms(0, &status, output);
    251			break;
    252		} else if (event_ctx->rx_id_list_ready && conn->is_repeater) {
    253			callback_in_ms(0, output);
    254			set_state_id(hdcp, output, H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
    255			break;
    256		}
    257		callback_in_ms(500, output);
    258		increment_stay_counter(hdcp);
    259		break;
    260	case H2_A6_WAIT_FOR_RX_ID_LIST:
    261		if (input->rxstatus_read != PASS ||
    262				input->reauth_request_check != PASS) {
    263			fail_and_restart_in_ms(0, &status, output);
    264			break;
    265		} else if (!event_ctx->rx_id_list_ready) {
    266			if (event_ctx->event == MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
    267				/* 1B-02: consider rx id list timeout a failure */
    268				/* some CTS equipment's actual timeout
    269				 * measurement is slightly greater than 3000 ms.
    270				 * Delay 100 ms to ensure it is fully timeout
    271				 * before re-authentication.
    272				 */
    273				fail_and_restart_in_ms(100, &status, output);
    274			} else {
    275				callback_in_ms(300, output);
    276				increment_stay_counter(hdcp);
    277			}
    278			break;
    279		}
    280		callback_in_ms(0, output);
    281		set_state_id(hdcp, output, H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
    282		break;
    283	case H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK:
    284		if (input->rxstatus_read != PASS ||
    285				input->reauth_request_check != PASS ||
    286				input->rx_id_list_read != PASS ||
    287				input->device_count_check != PASS ||
    288				input->rx_id_list_validation != PASS ||
    289				input->repeater_auth_ack_write != PASS) {
    290			/* 1B-03: consider invalid v' a failure
    291			 * 1B-04: consider MAX_DEVS_EXCEEDED a failure
    292			 * 1B-05: consider MAX_CASCADE_EXCEEDED a failure
    293			 * 1B-06: consider invalid seq_num_V a failure
    294			 * 1B-09: consider seq_num_V rollover a failure
    295			 */
    296			fail_and_restart_in_ms(0, &status, output);
    297			break;
    298		}
    299		callback_in_ms(0, output);
    300		set_state_id(hdcp, output, H2_A9_SEND_STREAM_MANAGEMENT);
    301		break;
    302	case H2_A9_SEND_STREAM_MANAGEMENT:
    303		if (input->rxstatus_read != PASS ||
    304				input->reauth_request_check != PASS) {
    305			fail_and_restart_in_ms(0, &status, output);
    306			break;
    307		} else if (event_ctx->rx_id_list_ready && conn->is_repeater) {
    308			callback_in_ms(0, output);
    309			set_state_id(hdcp, output, H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
    310			break;
    311		} else if (input->prepare_stream_manage != PASS ||
    312				input->stream_manage_write != PASS) {
    313			fail_and_restart_in_ms(0, &status, output);
    314			break;
    315		}
    316		set_watchdog_in_ms(hdcp, 100, output);
    317		callback_in_ms(0, output);
    318		set_state_id(hdcp, output, H2_A9_VALIDATE_STREAM_READY);
    319		break;
    320	case H2_A9_VALIDATE_STREAM_READY:
    321		if (input->rxstatus_read != PASS ||
    322				input->reauth_request_check != PASS) {
    323			fail_and_restart_in_ms(0, &status, output);
    324			break;
    325		} else if (event_ctx->rx_id_list_ready && conn->is_repeater) {
    326			callback_in_ms(0, output);
    327			set_state_id(hdcp, output, H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
    328			break;
    329		} else if (input->stream_ready_available != PASS) {
    330			if (event_ctx->event == MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
    331				/* 1B-10-2: restart content stream management on
    332				 * stream ready timeout
    333				 */
    334				hdcp->auth.count.stream_management_retry_count++;
    335				callback_in_ms(0, output);
    336				set_state_id(hdcp, output, H2_A9_SEND_STREAM_MANAGEMENT);
    337			} else {
    338				callback_in_ms(10, output);
    339				increment_stay_counter(hdcp);
    340			}
    341			break;
    342		} else if (input->stream_ready_read != PASS ||
    343				input->stream_ready_validation != PASS) {
    344			/*
    345			 * 1B-10-1: restart content stream management
    346			 * on invalid M'
    347			 */
    348			if (hdcp->auth.count.stream_management_retry_count > 10) {
    349				fail_and_restart_in_ms(0, &status, output);
    350			} else {
    351				hdcp->auth.count.stream_management_retry_count++;
    352				callback_in_ms(0, output);
    353				set_state_id(hdcp, output, H2_A9_SEND_STREAM_MANAGEMENT);
    354			}
    355			break;
    356		}
    357		callback_in_ms(200, output);
    358		set_state_id(hdcp, output, H2_ENABLE_ENCRYPTION);
    359		break;
    360	default:
    361		status = MOD_HDCP_STATUS_INVALID_STATE;
    362		fail_and_restart_in_ms(0, &status, output);
    363		break;
    364	}
    365
    366	return status;
    367}
    368
    369enum mod_hdcp_status mod_hdcp_hdcp2_dp_transition(struct mod_hdcp *hdcp,
    370		struct mod_hdcp_event_context *event_ctx,
    371		struct mod_hdcp_transition_input_hdcp2 *input,
    372		struct mod_hdcp_output *output)
    373{
    374	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    375	struct mod_hdcp_connection *conn = &hdcp->connection;
    376	struct mod_hdcp_link_adjustment *adjust = &hdcp->connection.link.adjust;
    377
    378	switch (current_state(hdcp)) {
    379	case D2_A0_DETERMINE_RX_HDCP_CAPABLE:
    380		if (input->rx_caps_read_dp != PASS ||
    381				input->hdcp2_capable_check != PASS) {
    382			adjust->hdcp2.disable = 1;
    383			callback_in_ms(0, output);
    384			set_state_id(hdcp, output, HDCP_INITIALIZED);
    385		} else {
    386			callback_in_ms(0, output);
    387			set_state_id(hdcp, output, D2_A1_SEND_AKE_INIT);
    388		}
    389		break;
    390	case D2_A1_SEND_AKE_INIT:
    391		if (input->create_session != PASS ||
    392				input->ake_init_prepare != PASS) {
    393			/* out of sync with psp state */
    394			adjust->hdcp2.disable = 1;
    395			fail_and_restart_in_ms(0, &status, output);
    396			break;
    397		} else if (input->ake_init_write != PASS) {
    398			/* possibly display not ready */
    399			fail_and_restart_in_ms(0, &status, output);
    400			break;
    401		}
    402		callback_in_ms(100, output);
    403		set_state_id(hdcp, output, D2_A1_VALIDATE_AKE_CERT);
    404		break;
    405	case D2_A1_VALIDATE_AKE_CERT:
    406		if (input->ake_cert_read != PASS ||
    407				input->ake_cert_validation != PASS) {
    408			/*
    409			 * 1A-08: consider invalid ake cert a failure
    410			 * 1A-09: consider receiver id listed in SRM a failure
    411			 */
    412			fail_and_restart_in_ms(0, &status, output);
    413			break;
    414		}
    415		if (conn->is_km_stored &&
    416				!adjust->hdcp2.force_no_stored_km) {
    417			callback_in_ms(0, output);
    418			set_state_id(hdcp, output, D2_A1_SEND_STORED_KM);
    419		} else {
    420			callback_in_ms(0, output);
    421			set_state_id(hdcp, output, D2_A1_SEND_NO_STORED_KM);
    422		}
    423		break;
    424	case D2_A1_SEND_NO_STORED_KM:
    425		if (input->no_stored_km_write != PASS) {
    426			fail_and_restart_in_ms(0, &status, output);
    427			break;
    428		}
    429		if (adjust->hdcp2.increase_h_prime_timeout)
    430			set_watchdog_in_ms(hdcp, 2000, output);
    431		else
    432			set_watchdog_in_ms(hdcp, 1000, output);
    433		set_state_id(hdcp, output, D2_A1_READ_H_PRIME);
    434		break;
    435	case D2_A1_READ_H_PRIME:
    436		if (input->h_prime_available != PASS) {
    437			if (event_ctx->event ==
    438					MOD_HDCP_EVENT_WATCHDOG_TIMEOUT)
    439				/* 1A-10-3: consider h' timeout a failure */
    440				fail_and_restart_in_ms(1000, &status, output);
    441			else
    442				increment_stay_counter(hdcp);
    443			break;
    444		} else if (input->h_prime_read != PASS) {
    445			fail_and_restart_in_ms(0, &status, output);
    446			break;
    447		}
    448		set_watchdog_in_ms(hdcp, 200, output);
    449		set_state_id(hdcp, output, D2_A1_READ_PAIRING_INFO_AND_VALIDATE_H_PRIME);
    450		break;
    451	case D2_A1_READ_PAIRING_INFO_AND_VALIDATE_H_PRIME:
    452		if (input->pairing_available != PASS) {
    453			if (event_ctx->event ==
    454					MOD_HDCP_EVENT_WATCHDOG_TIMEOUT)
    455				/*
    456				 * 1A-11: consider pairing info timeout
    457				 * a failure
    458				 */
    459				fail_and_restart_in_ms(0, &status, output);
    460			else
    461				increment_stay_counter(hdcp);
    462			break;
    463		} else if (input->pairing_info_read != PASS ||
    464				input->h_prime_validation != PASS) {
    465			/* 1A-10-1: consider invalid h' a failure */
    466			fail_and_restart_in_ms(0, &status, output);
    467			break;
    468		}
    469		callback_in_ms(0, output);
    470		set_state_id(hdcp, output, D2_A2_LOCALITY_CHECK);
    471		break;
    472	case D2_A1_SEND_STORED_KM:
    473		if (input->stored_km_write != PASS) {
    474			fail_and_restart_in_ms(0, &status, output);
    475			break;
    476		}
    477		set_watchdog_in_ms(hdcp, 200, output);
    478		set_state_id(hdcp, output, D2_A1_VALIDATE_H_PRIME);
    479		break;
    480	case D2_A1_VALIDATE_H_PRIME:
    481		if (input->h_prime_available != PASS) {
    482			if (event_ctx->event ==
    483					MOD_HDCP_EVENT_WATCHDOG_TIMEOUT)
    484				/* 1A-10-2: consider h' timeout a failure */
    485				fail_and_restart_in_ms(1000, &status, output);
    486			else
    487				increment_stay_counter(hdcp);
    488			break;
    489		} else if (input->h_prime_read != PASS) {
    490			fail_and_restart_in_ms(0, &status, output);
    491			break;
    492		} else if (input->h_prime_validation != PASS) {
    493			/* 1A-10-1: consider invalid h' a failure */
    494			adjust->hdcp2.force_no_stored_km = 1;
    495			fail_and_restart_in_ms(0, &status, output);
    496			break;
    497		}
    498		callback_in_ms(0, output);
    499		set_state_id(hdcp, output, D2_A2_LOCALITY_CHECK);
    500		break;
    501	case D2_A2_LOCALITY_CHECK:
    502		if (hdcp->state.stay_count > 10 ||
    503				input->lc_init_prepare != PASS ||
    504				input->lc_init_write != PASS ||
    505				input->l_prime_read != PASS) {
    506			/* 1A-12: consider invalid l' a failure */
    507			fail_and_restart_in_ms(0, &status, output);
    508			break;
    509		} else if (input->l_prime_validation != PASS) {
    510			callback_in_ms(0, output);
    511			increment_stay_counter(hdcp);
    512			break;
    513		}
    514		callback_in_ms(0, output);
    515		set_state_id(hdcp, output, D2_A34_EXCHANGE_KS_AND_TEST_FOR_REPEATER);
    516		break;
    517	case D2_A34_EXCHANGE_KS_AND_TEST_FOR_REPEATER:
    518		if (input->eks_prepare != PASS ||
    519				input->eks_write != PASS) {
    520			fail_and_restart_in_ms(0, &status, output);
    521			break;
    522		}
    523		if (conn->is_repeater) {
    524			set_watchdog_in_ms(hdcp, 3000, output);
    525			set_state_id(hdcp, output, D2_A6_WAIT_FOR_RX_ID_LIST);
    526		} else {
    527			callback_in_ms(0, output);
    528			set_state_id(hdcp, output, D2_SEND_CONTENT_STREAM_TYPE);
    529		}
    530		break;
    531	case D2_SEND_CONTENT_STREAM_TYPE:
    532		if (input->rxstatus_read != PASS ||
    533				input->reauth_request_check != PASS ||
    534				input->link_integrity_check_dp != PASS ||
    535				input->content_stream_type_write != PASS) {
    536			fail_and_restart_in_ms(0, &status, output);
    537			break;
    538		}
    539		callback_in_ms(210, output);
    540		set_state_id(hdcp, output, D2_ENABLE_ENCRYPTION);
    541		break;
    542	case D2_ENABLE_ENCRYPTION:
    543		if (input->rxstatus_read != PASS ||
    544				input->reauth_request_check != PASS ||
    545				input->link_integrity_check_dp != PASS) {
    546			/*
    547			 * 1A-07: restart hdcp on REAUTH_REQ
    548			 * 1B-08: restart hdcp on REAUTH_REQ
    549			 */
    550			fail_and_restart_in_ms(0, &status, output);
    551			break;
    552		} else if (event_ctx->rx_id_list_ready && conn->is_repeater) {
    553			callback_in_ms(0, output);
    554			set_state_id(hdcp, output, D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
    555			break;
    556		} else if (input->enable_encryption != PASS ||
    557				(is_dp_mst_hdcp(hdcp) && input->stream_encryption_dp != PASS)) {
    558			fail_and_restart_in_ms(0, &status, output);
    559			break;
    560		}
    561		set_state_id(hdcp, output, D2_A5_AUTHENTICATED);
    562		set_auth_complete(hdcp, output);
    563		break;
    564	case D2_A5_AUTHENTICATED:
    565		if (input->rxstatus_read == FAIL ||
    566				input->reauth_request_check == FAIL) {
    567			fail_and_restart_in_ms(100, &status, output);
    568			break;
    569		} else if (input->link_integrity_check_dp == FAIL) {
    570			if (hdcp->connection.hdcp2_retry_count >= 1)
    571				adjust->hdcp2.force_type = MOD_HDCP_FORCE_TYPE_0;
    572			fail_and_restart_in_ms(0, &status, output);
    573			break;
    574		} else if (event_ctx->rx_id_list_ready && conn->is_repeater) {
    575			callback_in_ms(0, output);
    576			set_state_id(hdcp, output, D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
    577			break;
    578		}
    579		increment_stay_counter(hdcp);
    580		break;
    581	case D2_A6_WAIT_FOR_RX_ID_LIST:
    582		if (input->rxstatus_read != PASS ||
    583				input->reauth_request_check != PASS ||
    584				input->link_integrity_check_dp != PASS) {
    585			fail_and_restart_in_ms(0, &status, output);
    586			break;
    587		} else if (!event_ctx->rx_id_list_ready) {
    588			if (event_ctx->event == MOD_HDCP_EVENT_WATCHDOG_TIMEOUT)
    589				/* 1B-02: consider rx id list timeout a failure */
    590				fail_and_restart_in_ms(0, &status, output);
    591			else
    592				increment_stay_counter(hdcp);
    593			break;
    594		}
    595		callback_in_ms(0, output);
    596		set_state_id(hdcp, output, D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
    597		break;
    598	case D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK:
    599		if (input->rxstatus_read != PASS ||
    600				input->reauth_request_check != PASS ||
    601				input->link_integrity_check_dp != PASS ||
    602				input->rx_id_list_read != PASS ||
    603				input->device_count_check != PASS ||
    604				input->rx_id_list_validation != PASS ||
    605				input->repeater_auth_ack_write != PASS) {
    606			/*
    607			 * 1B-03: consider invalid v' a failure
    608			 * 1B-04: consider MAX_DEVS_EXCEEDED a failure
    609			 * 1B-05: consider MAX_CASCADE_EXCEEDED a failure
    610			 * 1B-06: consider invalid seq_num_V a failure
    611			 * 1B-09: consider seq_num_V rollover a failure
    612			 */
    613			fail_and_restart_in_ms(0, &status, output);
    614			break;
    615		}
    616		callback_in_ms(0, output);
    617		set_state_id(hdcp, output, D2_A9_SEND_STREAM_MANAGEMENT);
    618		break;
    619	case D2_A9_SEND_STREAM_MANAGEMENT:
    620		if (input->rxstatus_read != PASS ||
    621				input->reauth_request_check != PASS ||
    622				input->link_integrity_check_dp != PASS) {
    623			fail_and_restart_in_ms(0, &status, output);
    624			break;
    625		} else if (event_ctx->rx_id_list_ready) {
    626			callback_in_ms(0, output);
    627			set_state_id(hdcp, output, D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
    628			break;
    629		} else if (input->prepare_stream_manage != PASS ||
    630				input->stream_manage_write != PASS) {
    631			if (event_ctx->event == MOD_HDCP_EVENT_CALLBACK)
    632				fail_and_restart_in_ms(0, &status, output);
    633			else
    634				increment_stay_counter(hdcp);
    635			break;
    636		}
    637		callback_in_ms(100, output);
    638		set_state_id(hdcp, output, D2_A9_VALIDATE_STREAM_READY);
    639		break;
    640	case D2_A9_VALIDATE_STREAM_READY:
    641		if (input->rxstatus_read != PASS ||
    642				input->reauth_request_check != PASS ||
    643				input->link_integrity_check_dp != PASS) {
    644			fail_and_restart_in_ms(0, &status, output);
    645			break;
    646		} else if (event_ctx->rx_id_list_ready) {
    647			callback_in_ms(0, output);
    648			set_state_id(hdcp, output, D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK);
    649			break;
    650		} else if (input->stream_ready_read != PASS ||
    651				input->stream_ready_validation != PASS) {
    652			/*
    653			 * 1B-10-1: restart content stream management
    654			 * on invalid M'
    655			 * 1B-10-2: consider stream ready timeout a failure
    656			 */
    657			if (hdcp->auth.count.stream_management_retry_count > 10) {
    658				fail_and_restart_in_ms(0, &status, output);
    659			} else if (event_ctx->event == MOD_HDCP_EVENT_CALLBACK) {
    660				hdcp->auth.count.stream_management_retry_count++;
    661				callback_in_ms(0, output);
    662				set_state_id(hdcp, output, D2_A9_SEND_STREAM_MANAGEMENT);
    663			} else {
    664				increment_stay_counter(hdcp);
    665			}
    666			break;
    667		}
    668		callback_in_ms(200, output);
    669		set_state_id(hdcp, output, D2_ENABLE_ENCRYPTION);
    670		break;
    671	default:
    672		status = MOD_HDCP_STATUS_INVALID_STATE;
    673		fail_and_restart_in_ms(0, &status, output);
    674		break;
    675	}
    676	return status;
    677}