/* * Copyright (C) ST-Ericsson SA 2011 * Author: Per Persson per.xb.persson@stericsson.com for * ST-Ericsson. * License terms: . */ #include /* Symbolic Constants */ #include /* Primitive System Data Types */ #include /* Errors */ #include #include /* Input/Output */ #include /* General Utilities */ #include /* String handling */ #include #include #include #include #include #include "../include/hdmi_service_api.h" #include "../include/hdmi_service_local.h" const __u8 hdcp_auth_start_val[] = {0x01, 0x00}; /* Start authentication */ const __u8 hdcp_encr_start_val[] = {0x03, 0x01}; /* Start encryption */ const __u8 hdcp_encr_stop_val[] = {0x00, 0x00}; /* Stop encryption */ const __u8 hdcp_even_val[] = {0x01}; /* Enable HDCP events */ static char *dbg_otp(int value) { switch (value) { case OTP_UNPROGGED: return "OTP IS NOT PROGRAMMED"; break; case OTP_PROGGED: return "OTP IS PROGRAMMED"; break; default: return "OTP status UNKNOWN"; break; } } static char *dbg_loadaes(int value) { switch (value) { case LOADAES_OK: return "LOAD AES OK\n"; break; case LOADAES_NOT_OK: return "LOAD AES FAILED\n"; break; case LOADAES_NOT_FUSED: return "LOAD AES FAILED NOT FUSED\n"; break; case LOADAES_CRC_MISMATCH: return "LOAD AES FAILED CRC MISMATCH\n"; break; default: return "LOAD AES result UNKNOWN\n"; break; } } static char *dbg_hdcpstate(int value) { switch (value) { case HDCP_STATE_NO_RECV: return "HDCP STATE NO_RECV"; break; case HDCP_STATE_RECV_CONN: return "HDCP STATE RECV_CONN"; break; case HDCP_STATE_NO_HDCP: return "HDCP STATE NO_HDCP"; break; case HDCP_STATE_NO_ENCR: return "HDCP STATE NO_ENCR"; break; case HDCP_STATE_AUTH_ONGOING: return "HDCP STATE AUTH_ONGOING"; break; case HDCP_STATE_AUTH_FAIL: return "HDCP STATE AUTH_FAIL"; break; case HDCP_STATE_AUTH_SUCCEDED: return "HDCP STATE AUTH_SUCCEDED"; break; case HDCP_STATE_ENCR_ONGOING: return "HDCP STATE ENCR_ONGOING"; break; default: return "HDCP STATE UNKNOWN"; break; } } /* Load aes keys and start hdcp encryption */ int hdcp_init(__u8 *aes) { int hdcpchkaesotp; int hdcploadaes; int hdcpauthencr; int hdcpeven; int res; int value = 0; char buf[128]; int result = HDCP_OK; int events; /* Check if OTP is fused */ hdcpchkaesotp = open(HDCPCHKAESOTP_FILE, O_RDONLY); if (hdcpchkaesotp < 0) { LOGHDMILIB("***** Failed to open %s *****", HDCPCHKAESOTP_FILE); result = SYSFS_FILE_FAILED; goto hdcp_end; } res = read(hdcpchkaesotp, buf, sizeof(buf)); close(hdcpchkaesotp); if (res != 1) { LOGHDMILIB("***** %s read error *****", HDCPCHKAESOTP_FILE); result = SYSFS_FILE_FAILED; goto hdcp_end; } value = *buf; LOGHDMILIB("%s", dbg_otp(value)); if (value == OTP_PROGGED) { /* Subscribe for hdcp events */ hdcpeven = open(HDCPEVEN_FILE, O_WRONLY); if (hdcpeven < 0) { LOGHDMILIB("***** Failed to open %s *****", HDCPEVEN_FILE); result = SYSFS_FILE_FAILED; goto hdcp_end; } write(hdcpeven, hdcp_even_val, sizeof(hdcp_even_val)); close(hdcpeven); /* Write aes keys */ hdcploadaes = open(HDCPLOADAES_FILE, O_WRONLY); if (hdcploadaes < 0) { LOGHDMILIB("***** Failed to open %s *****", HDCPLOADAES_FILE); result = SYSFS_FILE_FAILED; goto hdcp_end; } res = write(hdcploadaes, aes, AES_KEYS_SIZE); close(hdcploadaes); if (res != AES_KEYS_SIZE) { LOGHDMILIB("***** Failed to write hdcploadaes %d " "*****", res); result = SYSFS_FILE_FAILED; goto hdcp_end; } usleep(LOADAES_WAITTIME); /* Check result */ hdcploadaes = open(HDCPLOADAES_FILE, O_RDONLY); if (hdcploadaes < 0) { LOGHDMILIB("***** Failed to open %s *****", HDCPLOADAES_FILE); result = SYSFS_FILE_FAILED; goto hdcp_end; } res = read(hdcploadaes, buf, sizeof(buf)); close(hdcploadaes); if (res != 1) { LOGHDMILIB("***** %s read error *****", HDCPLOADAES_FILE); result = SYSFS_FILE_FAILED; goto hdcp_end; } value = *buf; LOGHDMILIB("%s", dbg_loadaes(value)); if (value == LOADAES_OK) { LOGHDMILIB("%s", "--- LOAD AES keys OK ---"); } else { result = AESKEYS_FAIL; goto hdcp_end; } usleep(LOADAES_WAITTIME); /* Start HDCP encryption */ hdcpauthencr = open(HDCPAUTH_FILE, O_WRONLY); if (hdcpauthencr < 0) { LOGHDMILIB("***** Failed to open %s *****", HDCPAUTH_FILE); result = HDCPAUTHENCR_FAIL; goto hdcp_end; } res = write(hdcpauthencr, hdcp_encr_start_val, sizeof(hdcp_encr_start_val)); close(hdcpauthencr); if (res != sizeof(hdcp_encr_start_val)) { LOGHDMILIB("***** Failed to write hdcpauthencr %d " "*****", res); result = HDCPAUTHENCR_FAIL; goto hdcp_end; } usleep(HDCPAUTH_WAITTIME); } else { printf("***** Missing aes file or HDCP AES OTP is not fused." " *****\n"); } hdcp_end: return result; } /* Get current hdcp state */ int hdcp_state(void) { int hdcpstateget; int result = HDCP_OK; int res; __u8 buf[128]; int val; __u32 cmd_id; cmd_id = get_new_cmd_id_ind(); /* Check hdcpstate */ hdcpstateget = open(HDCPSTATEGET_FILE, O_RDONLY); if (hdcpstateget < 0) { LOGHDMILIB("***** Failed to open %s *****", HDCPSTATEGET_FILE); result = SYSFS_FILE_FAILED; goto hdcp_state_end; } res = read(hdcpstateget, buf, sizeof(buf)); close(hdcpstateget); if (res != 1) { LOGHDMILIB("***** %s read error *****", HDCPSTATEGET_FILE); result = HDCPSTATE_FAIL; goto hdcp_state_end; } val = HDMI_HDCPSTATE; memcpy(&buf[CMD_OFFSET], &val, 4); memcpy(&buf[CMDID_OFFSET], &cmd_id, 4); val = 1; memcpy(&buf[CMDLEN_OFFSET], &val, 4); memcpy(&buf[CMDBUF_OFFSET], buf, val); /* Send on socket */ if (clientsocket_send(buf, CMDBUF_OFFSET + val) != 0) result = HDCPSTATE_FAIL; LOGHDMILIB("%s", dbg_hdcpstate(val)); hdcp_state_end: return result; }