#include #include #include #include #include #include #include #include #include #include #include #include #define LOG_TAG "HDCP" #include #include "Hdcp.h" #define RKNAND_GET_SN_SECTOR _IOW('d', 3, unsigned int) #define SN_SECTOR_OP_TAG 0x41444E53 // "SNDA" #define RKNAND_SYS_STORGAE_DATA_LEN 512 #define ERROR ALOGE typedef unsigned short uint16; typedef unsigned int uint32; typedef unsigned char uint8; typedef struct tagRKNAND_SYS_STORGAE { uint32 tag; uint32 len; uint8 data[RKNAND_SYS_STORGAE_DATA_LEN]; }RKNAND_SYS_STORGAE; #ifdef __cplusplus extern "C" { #endif extern int init_module(void *, unsigned long, const char *); extern int delete_module(const char *, unsigned int); #ifdef __cplusplus } #endif void rknand_print_hex_data(uint32 * buf,uint32 len) { uint32 i,j,count; for(i=0;i 42) { vrl_length -= 42; data = 0; fread(&data, 1, 1, fd); if(data*5 != vrl_length - 1) { ALOGE("[%s] invalid key number incorrect.\n", __FUNCTION__); goto invalid; } ALOGD("[%s] SRM next block invalid key number is %d", __FUNCTION__, data); fread(*buf, 1, data * 5, fd); invalid_key_size += data*5; fseek(fd, 40, SEEK_CUR); } temp = ftell(fd); } fclose(fd); *size = invalid_key_size; return 0; invalid: if(*buf) free(*buf); fclose(fd); failed: *buf = NULL; *size = 0; return -1; } static int hdcp_write_fireware(char *key, int keysize, char *srm, int srmsize) { FILE *fd = NULL; if(key == NULL || keysize == 0) return -1; fd = fopen(HDCP_FIRMWARE_DATA, "w"); if(fd == NULL) return -1; fwrite(key, 1, keysize, fd); if(srmsize && srm) { fwrite(srm, 1, srmsize, fd); } fclose(fd); return 0; } /* Load hdcp key and srm file to kernel. Key and SRM are combined with following mode: struct firmware { char key[keysize]; char srm[srmsize]; } */ static int hdcp_load_firmware(void) { char *key = NULL, *srm = NULL; int keysize = 0, srmsize, rc = -1, i; ALOGD("%s start\n", __FUNCTION__); hdcp_read_key(&key, &keysize); hdcp_read_srm(&srm, &srmsize); if(keysize) { rc = firmware_loading_enable(); if(!rc) { hdcp_write_fireware(key, keysize, srm, srmsize); rc = firmware_loading_disable(); } } if(key) free(key); if(srm) free(srm); return rc; } static void hdcp_set_trytimes(int times) { FILE *fd = NULL; char buf[5]; fd = fopen(HDCP_TRYTIMES, "w"); if(fd == NULL) return; memset(buf, 0, 5); sprintf(buf, "%d", times); fputs(buf, fd); fclose(fd); } void Hdcp_enable(void) { FILE *fd = NULL; if (!hdcp_enable) return; ALOGD("%s", __func__); fd = fopen(HDCP_ENABLE, "w"); if(fd == NULL) return; fputc('1', fd); fclose(fd); } static int insmod(const char *filename) { void *module = NULL; unsigned int size; int ret; struct utsname name; char filename_release[PATH_MAX]; ALOGD("insmod %s", filename); memset(&name, 0, sizeof(name)); ret = uname(&name); if (ret == 0 && name.release) { // try insmod filename.x.x.x strncat(filename_release, filename, sizeof(filename_release) - 1); strncat(filename_release, ".", sizeof(filename_release) - 1); strncat(filename_release, name.release, sizeof(filename_release) - 1); module = load_file(filename_release, &size); } if (!module) module = load_file(filename, &size); if (!module) return -1; ret = init_module(module, size, ""); free(module); return ret; } static int rmmod(const char *modname) { int ret = -1; int maxtry = 10; while (maxtry-- > 0) { ret = delete_module(modname, O_NONBLOCK | O_EXCL); if (ret < 0 && errno == EAGAIN) usleep(500000); else break; } if (ret != 0) SLOGE("Unable to unload driver module \"%s\": %s\n", modname, strerror(errno)); return ret; } static void hdcp2_init(void) { ALOGI("HDCP2 starting"); if (access(HDCP2_MODULE, R_OK) == 0 && access(HDCP2_FW_NAME, R_OK) == 0) { if (insmod(HDCP2_MODULE) == 0) usleep(150000); rk_hdmi_hdcp2_init(HDCP2_FW_NAME, NULL); } } void Hdcp_init() { ALOGI("HDCP starting"); hdcp_enable = 0; if (access(HDCP_ENABLE, W_OK) == 0) { if( (access(HDCP_FIRMWARE_LOADING, W_OK) == 0) && (access(HDCP_FIRMWARE_DATA, W_OK) == 0) ) { if (access("/drmboot.ko", R_OK) == 0) { insmod("/drmboot.ko"); usleep(150000); if (hdcp_load_firmware() == 0) { hdcp_set_trytimes(HDCP_AUTH_RETRY_TIMES); hdcp2_init(); hdcp_enable = 1; } else firmware_loading_cancel(); } else firmware_loading_cancel(); } else ALOGW("Device not support load HDCP firmware, just exit.\n"); } else ALOGW("Device not support HDCP, just exit.\n"); ALOGI("HDCP exiting"); }