Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2019 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 #include "hdcp.h"
0027 
0028 enum mod_hdcp_status mod_hdcp_hdcp1_transition(struct mod_hdcp *hdcp,
0029         struct mod_hdcp_event_context *event_ctx,
0030         struct mod_hdcp_transition_input_hdcp1 *input,
0031         struct mod_hdcp_output *output)
0032 {
0033     enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
0034     struct mod_hdcp_connection *conn = &hdcp->connection;
0035     struct mod_hdcp_link_adjustment *adjust = &hdcp->connection.link.adjust;
0036 
0037     switch (current_state(hdcp)) {
0038     case H1_A0_WAIT_FOR_ACTIVE_RX:
0039         if (input->bksv_read != PASS || input->bcaps_read != PASS) {
0040             /* 1A-04: repeatedly attempts on port access failure */
0041             callback_in_ms(500, output);
0042             increment_stay_counter(hdcp);
0043             break;
0044         }
0045         callback_in_ms(0, output);
0046         set_state_id(hdcp, output, H1_A1_EXCHANGE_KSVS);
0047         break;
0048     case H1_A1_EXCHANGE_KSVS:
0049         if (input->create_session != PASS) {
0050             /* out of sync with psp state */
0051             adjust->hdcp1.disable = 1;
0052             fail_and_restart_in_ms(0, &status, output);
0053             break;
0054         } else if (input->an_write != PASS ||
0055                 input->aksv_write != PASS ||
0056                 input->bksv_read != PASS ||
0057                 input->bksv_validation != PASS ||
0058                 input->ainfo_write == FAIL) {
0059             /* 1A-05: consider invalid bksv a failure */
0060             fail_and_restart_in_ms(0, &status, output);
0061             break;
0062         }
0063         callback_in_ms(300, output);
0064         set_state_id(hdcp, output,
0065             H1_A2_COMPUTATIONS_A3_VALIDATE_RX_A6_TEST_FOR_REPEATER);
0066         break;
0067     case H1_A2_COMPUTATIONS_A3_VALIDATE_RX_A6_TEST_FOR_REPEATER:
0068         if (input->bcaps_read != PASS ||
0069                 input->r0p_read != PASS) {
0070             fail_and_restart_in_ms(0, &status, output);
0071             break;
0072         } else if (input->rx_validation != PASS) {
0073             /* 1A-06: consider invalid r0' a failure */
0074             /* 1A-08: consider bksv listed in SRM a failure */
0075             /*
0076              * some slow RX will fail rx validation when it is
0077              * not ready. give it more time to react before retry.
0078              */
0079             fail_and_restart_in_ms(1000, &status, output);
0080             break;
0081         } else if (!conn->is_repeater && input->encryption != PASS) {
0082             fail_and_restart_in_ms(0, &status, output);
0083             break;
0084         }
0085         if (conn->is_repeater) {
0086             callback_in_ms(0, output);
0087             set_watchdog_in_ms(hdcp, 5000, output);
0088             set_state_id(hdcp, output, H1_A8_WAIT_FOR_READY);
0089         } else {
0090             callback_in_ms(0, output);
0091             set_state_id(hdcp, output, H1_A45_AUTHENTICATED);
0092             set_auth_complete(hdcp, output);
0093         }
0094         break;
0095     case H1_A45_AUTHENTICATED:
0096         if (input->link_maintenance == FAIL) {
0097             /* 1A-07: consider invalid ri' a failure */
0098             /* 1A-07a: consider read ri' not returned a failure */
0099             fail_and_restart_in_ms(0, &status, output);
0100             break;
0101         }
0102         callback_in_ms(500, output);
0103         increment_stay_counter(hdcp);
0104         break;
0105     case H1_A8_WAIT_FOR_READY:
0106         if (input->ready_check != PASS) {
0107             if (event_ctx->event ==
0108                     MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
0109                 /* 1B-03: fail hdcp on ksv list READY timeout */
0110                 /* prevent black screen in next attempt */
0111                 adjust->hdcp1.postpone_encryption = 1;
0112                 fail_and_restart_in_ms(0, &status, output);
0113             } else {
0114                 /* continue ksv list READY polling*/
0115                 callback_in_ms(500, output);
0116                 increment_stay_counter(hdcp);
0117             }
0118             break;
0119         }
0120         callback_in_ms(0, output);
0121         set_state_id(hdcp, output, H1_A9_READ_KSV_LIST);
0122         break;
0123     case H1_A9_READ_KSV_LIST:
0124         if (input->bstatus_read != PASS ||
0125                 input->max_cascade_check != PASS ||
0126                 input->max_devs_check != PASS ||
0127                 input->device_count_check != PASS ||
0128                 input->ksvlist_read != PASS ||
0129                 input->vp_read != PASS ||
0130                 input->ksvlist_vp_validation != PASS ||
0131                 input->encryption != PASS) {
0132             /* 1B-06: consider MAX_CASCADE_EXCEEDED a failure */
0133             /* 1B-05: consider MAX_DEVS_EXCEEDED a failure */
0134             /* 1B-04: consider invalid v' a failure */
0135             fail_and_restart_in_ms(0, &status, output);
0136             break;
0137         }
0138         callback_in_ms(0, output);
0139         set_state_id(hdcp, output, H1_A45_AUTHENTICATED);
0140         set_auth_complete(hdcp, output);
0141         break;
0142     default:
0143         status = MOD_HDCP_STATUS_INVALID_STATE;
0144         fail_and_restart_in_ms(0, &status, output);
0145         break;
0146     }
0147 
0148     return status;
0149 }
0150 
0151 enum mod_hdcp_status mod_hdcp_hdcp1_dp_transition(struct mod_hdcp *hdcp,
0152         struct mod_hdcp_event_context *event_ctx,
0153         struct mod_hdcp_transition_input_hdcp1 *input,
0154         struct mod_hdcp_output *output)
0155 {
0156     enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
0157     struct mod_hdcp_connection *conn = &hdcp->connection;
0158     struct mod_hdcp_link_adjustment *adjust = &hdcp->connection.link.adjust;
0159 
0160     switch (current_state(hdcp)) {
0161     case D1_A0_DETERMINE_RX_HDCP_CAPABLE:
0162         if (input->bcaps_read != PASS) {
0163             /* 1A-04: no authentication on bcaps read failure */
0164             fail_and_restart_in_ms(0, &status, output);
0165             break;
0166         } else if (input->hdcp_capable_dp != PASS) {
0167             adjust->hdcp1.disable = 1;
0168             fail_and_restart_in_ms(0, &status, output);
0169             break;
0170         }
0171         callback_in_ms(0, output);
0172         set_state_id(hdcp, output, D1_A1_EXCHANGE_KSVS);
0173         break;
0174     case D1_A1_EXCHANGE_KSVS:
0175         if (input->create_session != PASS) {
0176             /* out of sync with psp state */
0177             adjust->hdcp1.disable = 1;
0178             fail_and_restart_in_ms(0, &status, output);
0179             break;
0180         } else if (input->an_write != PASS ||
0181                 input->aksv_write != PASS ||
0182                 input->bksv_read != PASS ||
0183                 input->bksv_validation != PASS ||
0184                 input->ainfo_write == FAIL) {
0185             /* 1A-05: consider invalid bksv a failure */
0186             fail_and_restart_in_ms(0, &status, output);
0187             break;
0188         }
0189         set_watchdog_in_ms(hdcp, 100, output);
0190         set_state_id(hdcp, output, D1_A23_WAIT_FOR_R0_PRIME);
0191         break;
0192     case D1_A23_WAIT_FOR_R0_PRIME:
0193         if (input->bstatus_read != PASS) {
0194             fail_and_restart_in_ms(0, &status, output);
0195             break;
0196         } else if (input->r0p_available_dp != PASS) {
0197             if (event_ctx->event == MOD_HDCP_EVENT_WATCHDOG_TIMEOUT)
0198                 fail_and_restart_in_ms(0, &status, output);
0199             else
0200                 increment_stay_counter(hdcp);
0201             break;
0202         }
0203         callback_in_ms(0, output);
0204         set_state_id(hdcp, output, D1_A2_COMPUTATIONS_A3_VALIDATE_RX_A5_TEST_FOR_REPEATER);
0205         break;
0206     case D1_A2_COMPUTATIONS_A3_VALIDATE_RX_A5_TEST_FOR_REPEATER:
0207         if (input->r0p_read != PASS) {
0208             fail_and_restart_in_ms(0, &status, output);
0209             break;
0210         } else if (input->rx_validation != PASS) {
0211             if (hdcp->state.stay_count < 2 &&
0212                     !hdcp->connection.is_hdcp1_revoked) {
0213                 /* allow 2 additional retries */
0214                 callback_in_ms(0, output);
0215                 increment_stay_counter(hdcp);
0216             } else {
0217                 /*
0218                  * 1A-06: consider invalid r0' a failure
0219                  * after 3 attempts.
0220                  * 1A-08: consider bksv listed in SRM a failure
0221                  */
0222                 /*
0223                  * some slow RX will fail rx validation when it is
0224                  * not ready. give it more time to react before retry.
0225                  */
0226                 fail_and_restart_in_ms(1000, &status, output);
0227             }
0228             break;
0229         } else if ((!conn->is_repeater && input->encryption != PASS) ||
0230                 (!conn->is_repeater && is_dp_mst_hdcp(hdcp) && input->stream_encryption_dp != PASS)) {
0231             fail_and_restart_in_ms(0, &status, output);
0232             break;
0233         } else if (conn->hdcp1_retry_count < conn->link.adjust.hdcp1.min_auth_retries_wa) {
0234             fail_and_restart_in_ms(200, &status, output);
0235             break;
0236         }
0237         if (conn->is_repeater) {
0238             set_watchdog_in_ms(hdcp, 5000, output);
0239             set_state_id(hdcp, output, D1_A6_WAIT_FOR_READY);
0240         } else {
0241             set_state_id(hdcp, output, D1_A4_AUTHENTICATED);
0242             set_auth_complete(hdcp, output);
0243         }
0244         break;
0245     case D1_A4_AUTHENTICATED:
0246         if (input->link_integrity_check == FAIL ||
0247                 input->reauth_request_check == FAIL) {
0248             /* 1A-07: restart hdcp on a link integrity failure */
0249             fail_and_restart_in_ms(0, &status, output);
0250             break;
0251         }
0252         break;
0253     case D1_A6_WAIT_FOR_READY:
0254         if (input->link_integrity_check == FAIL ||
0255                 input->reauth_request_check == FAIL) {
0256             fail_and_restart_in_ms(0, &status, output);
0257             break;
0258         } else if (input->ready_check != PASS) {
0259             if (event_ctx->event ==
0260                     MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
0261                 /* 1B-04: fail hdcp on ksv list READY timeout */
0262                 /* prevent black screen in next attempt */
0263                 adjust->hdcp1.postpone_encryption = 1;
0264                 fail_and_restart_in_ms(0, &status, output);
0265             } else {
0266                 increment_stay_counter(hdcp);
0267             }
0268             break;
0269         }
0270         callback_in_ms(0, output);
0271         set_state_id(hdcp, output, D1_A7_READ_KSV_LIST);
0272         break;
0273     case D1_A7_READ_KSV_LIST:
0274         if (input->binfo_read_dp != PASS ||
0275                 input->max_cascade_check != PASS ||
0276                 input->max_devs_check != PASS) {
0277             /* 1B-06: consider MAX_DEVS_EXCEEDED a failure */
0278             /* 1B-07: consider MAX_CASCADE_EXCEEDED a failure */
0279             fail_and_restart_in_ms(0, &status, output);
0280             break;
0281         } else if (input->device_count_check != PASS) {
0282             /*
0283              * some slow dongle doesn't update
0284              * device count as soon as downstream is connected.
0285              * give it more time to react.
0286              */
0287             adjust->hdcp1.postpone_encryption = 1;
0288             fail_and_restart_in_ms(1000, &status, output);
0289             break;
0290         } else if (input->ksvlist_read != PASS ||
0291                 input->vp_read != PASS) {
0292             fail_and_restart_in_ms(0, &status, output);
0293             break;
0294         } else if (input->ksvlist_vp_validation != PASS) {
0295             if (hdcp->state.stay_count < 2 &&
0296                     !hdcp->connection.is_hdcp1_revoked) {
0297                 /* allow 2 additional retries */
0298                 callback_in_ms(0, output);
0299                 increment_stay_counter(hdcp);
0300             } else {
0301                 /*
0302                  * 1B-05: consider invalid v' a failure
0303                  * after 3 attempts.
0304                  */
0305                 fail_and_restart_in_ms(0, &status, output);
0306             }
0307             break;
0308         } else if (input->encryption != PASS ||
0309                 (is_dp_mst_hdcp(hdcp) && input->stream_encryption_dp != PASS)) {
0310             fail_and_restart_in_ms(0, &status, output);
0311             break;
0312         }
0313         set_state_id(hdcp, output, D1_A4_AUTHENTICATED);
0314         set_auth_complete(hdcp, output);
0315         break;
0316     default:
0317         fail_and_restart_in_ms(0, &status, output);
0318         break;
0319     }
0320 
0321     return status;
0322 }