📄 ms_cardea.c
字号:
/* * * Copyright (c) Sigma Designs, Inc. 2005. All rights reserved. * */#define ALLOW_OS_CODE 1#include "rmdef/rmdef.h"#include "rmcore/include/rmcore.h"#include "rmcci/include/output_cci.h"#include "../include/ms_cardea_types.h"#include "wmdrmndcoreapi.h"#include "../include/ms_cardea.h"#include "../../rmlibwmdrmndupnp/include/ms_upnp.h"#if 0#define CARDEADBG ENABLE#else#define CARDEADBG DISABLE#endif#if 0#define PACKETDBG ENABLE#else#define PACKETDBG DISABLE#endif/* For testing create a fake device for any url in init_carde *//* #define TEST_FAKE_DEVICE */#ifdef TEST_FAKE_DEVICEextern wmdrmnet_context * init_wmdrmnet_context_fake(RMuint8 *content_key);/* Harcoded key for test purpose*/static RMuint8 content_key[] = { /* 16 bytes */ 0x58, 0xfa, 0x13, 0x0e, 0xef, 0x29, 0x19, 0xfe, 0x26, 0x7f, 0xb6, 0xe1, 0xc8, 0x9d, 0x21, 0x66 };#endif/** All the knwon ms_device, keep track of them, also used by ms_cardea.h, so not static */struct ms_upnp_extension_s *ms_device[MAX_MS_DEVICE]; #if (EM86XX_CHIP==EM86XX_CHIPID_TANGO2)//// Note: The macrovision guid in the M$ docs is {C3FD11C6-F8B7-4d20-B008-1DB17D61F2DA}// The macrovision guid in the license is {C611FDC3-B7F8-204d-B008-1DB17D61F2DA}// It appears that the guid a mixture of varying width fields with differing endiannessstatic RMuint8 MacroVision_ACP_GUID1[] = { 0xc6,0x11,0xfd,0xc3, 0xb7,0xf8, 0x20,0x4d, 0xb0,0x08, 0x1d,0xb1,0x7d,0x61,0xf2,0xda };// Component Output constraint {811C5110-46C8-4C6E-8163-c0482A15D47E}static RMuint8 ComponentOut_Constraint_GUID[] = { 0x10,0x51,0x1c,0x81, 0xc8,0x46, 0x6e,0x4c, 0x81,0x63, 0xc0,0x48,0x2a,0x15,0xd4,0x7e };#endif// http://cr.yp.to/cdb/cdb.txtstatic RMuint32 cdb_hash(RMuint8 *string, RMint32 length){ RMuint32 h = 5381; for (; length >= 0;length--) h = ((h<<5) + h) ^ string[length]; h = h % 256; RMDBGLOG((ENABLE, "hashed to id: 0x%08x vs 0x%08x\n", h, h ^ 0x0000000)); return h;}/** * Initialize CARDEA for a given URL * * This function tries to get the CARDEA session associated with the URL. If no * session is opened for this URL, returns NULL. * * @param url - url for which a session header is required * @return NULL if no session header is available */RMint32 init_cardea(const RMascii *url){ RMuint32 i; RMstatus status; for (i=0;i<MAX_MS_DEVICE;i++){ RMDBGLOG((ENABLE,"Inspecting device: %d\n", i)); if (ms_device[i] != NULL ) { RMDBGLOG((ENABLE,"Inspecting device: %d\n", i)); /* Initialize CARDEA core */ status = init_cardea_core((wmdrmnet_context*)ms_device[i]->drm_context); if (RMFAILED(status)) { RMDBGLOG((ENABLE,"Cannot initialize CARDEA core\n")); return -1; } return 0; } } RMDBGLOG((ENABLE,"Cannot initialize CARDEA core\n")); return -1;}void * init_cardea_url(struct ms_upnp_extension_s *ms_upnp, RMascii *url, RMascii *session_header){ RMint32 i; struct ms_url_context_s *new_ctx = NULL; if ( url == NULL ) { RMDBGLOG((ENABLE, "passed URL is NULL!\n")); return NULL; } RMDBGLOG((ENABLE, "Inserting url in device: 0x%08x\n", ms_upnp)); for (i=0; (i <= MAX_URL_CTX) && (ms_upnp->urls[i] != NULL); i++) {} RMDBGLOG((ENABLE, "Searched through %d structs\n", i)); if ((i == MAX_URL_CTX)) { i=0; // we searched through the whole list, but there is a // allocated context at slot 0, which means we have no // free slots if (ms_upnp->urls[0] != NULL) { RMDBGLOG((ENABLE, "All slots appear to be full.. sorry!\n", i)); return NULL; } } RMDBGLOG((ENABLE, "Inserting new URL ctx at position: %d\n", i)); new_ctx = (struct ms_url_context_s *)RMMalloc(sizeof(struct ms_url_context_s)); ms_upnp->urls[i] = new_ctx; new_ctx->url = RMMallocAndDuplicateAscii(url); new_ctx->url_hash = cdb_hash((RMuint8*)url, RMasciiLength(url)); new_ctx->license_present = FALSE; new_ctx->server = ms_upnp; new_ctx->server->use_count++;// printf("new_ctx->server->use_count = %d\n",new_ctx->server->use_count); if ( session_header == NULL ) { RMDBGLOG((ENABLE, "pass NULL session header\n")); new_ctx->session_header = NULL; } else new_ctx->session_header = RMMallocAndDuplicateAscii(session_header); /* Clear MS stream context */ RMMemset(new_ctx->ms_stream_decryption_context, 0, sizeof(new_ctx->ms_stream_decryption_context)); RMDBGLOG((ENABLE, "New url ctx at 0x%08x\n", ms_upnp->urls[i])); return new_ctx;}RMstatus destroy_url_context(void *ctx){ struct ms_url_context_s *url_ctx = (struct ms_url_context_s *)ctx; RMuint32 i = 0; if( url_ctx == NULL ) { RMDBGLOG((ENABLE, "passed a null pointer... not erasing\n")); return RM_ERROR; } if(url_ctx->server != NULL) { //printf("destroy_url_context url_ctx->server=%x\n",url_ctx->server); } for (i=0; (i < MAX_URL_CTX) && (url_ctx->server->urls[i] != url_ctx);i++) {} if ( i == MAX_URL_CTX ) { RMDBGLOG((ENABLE, "Unable to find URL in this server, corrupted pointer ?\n")); return RM_ERROR; } RMDBGLOG((ENABLE, "Destroying url ctx at: 0x%08x\n", ctx)); if ( url_ctx->session_header != NULL ) { RMFree(url_ctx->session_header); url_ctx->session_header = NULL; } if ( url_ctx->url != NULL ) { RMFree(url_ctx->url); url_ctx->url = NULL; } url_ctx->server->use_count--; if(url_ctx->server->use_count == 0) { RMDBGLOG((ENABLE,"calling release_cardea from destroy_url_context \n")); release_cardea(url_ctx); } url_ctx->server->urls[i] = NULL; url_ctx->server = NULL; RMFree(url_ctx); return RM_OK;}/** * Release CARDEA session * * Releases a session previously allocated via init_cardea() * * @param cardea_context - value returned by init_cardea() * @return RM_OK on success * RM_ERROR otherwise */RMstatus release_cardea(void *cardea_context) { int i,j; RMstatus status = RM_OK; struct ms_url_context_s *url_ctx = ( struct ms_url_context_s *) cardea_context; struct ms_upnp_extension_s *ms_context; RMbool found = FALSE; for (i=0;i<MAX_MS_DEVICE;i++){ for ( j=0; j < MAX_URL_CTX; j++) { if((ms_device[i] != NULL ) && (ms_device[i]->urls[j] == cardea_context)) { found = TRUE; break; } } if(found == TRUE) break; } if( !found ) { RMDBGLOG((ENABLE, "Unable to find url context 0x%08x, not destroying...\n", cardea_context)); return RM_ERROR; } ms_context = url_ctx->server; for (i=0;i<MAX_MS_DEVICE;i++){ if ( ms_device[i] == ms_context ) { if ( ms_device[i]->use_count == 0 ) { destroy_ms_device( ms_context ); } status = RM_OK; break; } } return status;}/** * Terminate CARDEA * * This function handles the termination of all cardea services * * @return RM_OK on success */RMstatus term_cardea(){ /* Terminate CARDEA core */ return term_cardea_core();}static void *find_url(struct ms_upnp_extension_s *ms_upnp, RMascii *url){ RMint32 i; struct ms_url_context_s *current_url; if ( url == NULL ) { RMDBGLOG((ENABLE, "Attempting to pass NULL for search!\n")); return NULL; } for (i=0; (i < MAX_URL_CTX) /*&& (ms_upnp->urls[i] != NULL)*/;i++) { if(ms_upnp->urls[i] != NULL) { current_url = ms_upnp->urls[i]; RMDBGLOG((ENABLE, "Searching for url: 0x%08x\n", current_url->url)); if ( (current_url->url != NULL) && (RMCompareAscii(current_url->url, url)) ) { RMDBGLOG((ENABLE, "found url context... 0x%08x\n", current_url)); return current_url; } } } RMDBGLOG((ENABLE, "Did not find any matching urls!!!\n")); return NULL;}void * find_cardea_url(RMascii *url){ RMint32 i; void *ctx; if ( url == NULL ) { RMDBGLOG((ENABLE, "Attempting to pass NULL for search!\n")); return NULL; } for (i=0;i<MAX_MS_DEVICE;i++){ if ( ms_device[i] != NULL ) { if( (ctx = find_url(ms_device[i], url)) != NULL ) { RMDBGLOG((ENABLE, "Found matching device for url: 0x%08x\n", ms_device[i])); return ctx; } } } return NULL;}void * find_cardea_device(RMascii *url){ RMint32 i; void *ctx; for (i=0;i<MAX_MS_DEVICE;i++){ if ( ms_device[i] != NULL ) { if( (ctx = find_url(ms_device[i], url)) != NULL ) { RMDBGLOG((ENABLE, "Found matching device for url: 0x%08x\n", ms_device[i])); return ms_device[i]; } } } return NULL;}RMbool should_decrypt(void *cardea_ctx){ struct ms_url_context_s *url_ctx = (struct ms_url_context_s *)cardea_ctx; if (url_ctx == NULL) { RMDBGLOG((ENABLE, "passed NULL pointer... \n")); return FALSE; } RMDBGLOG((ENABLE, "current ctx: 0x%08x\n", url_ctx )); RMDBGLOG((ENABLE, "URL has license ? %s\n", url_ctx->license_present ? "Yes" : "No")); return url_ctx->license_present;}/** * Update the sample ID for a particuler stream and media object * * @param cardea_context - the context to update * @param stream_index - current stream index * @param media_object_number - current media object number * @param sample_id - pointer to the sample ID data * @param sample_id_size - size of the sample id (should be 8) */void update_cardea_sample_id( void * cardea_playback_url, RMuint16 stream_index, RMuint32 media_object_number, RMuint8 *sample_id, RMuint32 sample_id_size){ struct ms_url_context_s *url_ctx = (struct ms_url_context_s *) cardea_playback_url; struct ms_upnp_extension_s *ms_context = (struct ms_upnp_extension_s *) url_ctx->server; if (ms_context == NULL){ RMDBGLOG((ENABLE,"** Error ** NULL context\n")); return; } if ( url_ctx == NULL ) { RMDBGLOG((ENABLE,"** Error ** NULL url context\n")); return; } RMDBGLOG((ENABLE,"url_ctx: 0x%08x , key id: %d\n", url_ctx, url_ctx->url_hash)); if (stream_index == 0 || stream_index > 127){ RMDBGLOG((ENABLE,"** Error ** stream index value is invalid : %ld\n", stream_index)); return; } if (sample_id_size != 8) RMDBGLOG((ENABLE,"** Warning ** sample Id size is not 8 (%ld)\n", sample_id_size)); if (url_ctx->ms_stream_decryption_context[stream_index].media_object_number != media_object_number){ url_ctx->ms_stream_decryption_context[stream_index].media_object_number = media_object_number; RMMemset(url_ctx->ms_stream_decryption_context[stream_index].sample_id, 0, 8); RMMemcpy(url_ctx->ms_stream_decryption_context[stream_index].sample_id, sample_id, sample_id_size); /* Reset the byte count since we change media object */ url_ctx->ms_stream_decryption_context[stream_index].byte_count = 0; RMDBGLOG((CARDEADBG,"ST:%02d,MON:%04lu,SID:0x%08lx%08lx\n", stream_index, media_object_number, RMbeBufToUint32(url_ctx->ms_stream_decryption_context[stream_index].sample_id), RMbeBufToUint32(url_ctx->ms_stream_decryption_context[stream_index].sample_id+4))); } /* If we are here, it means the url associated with the CARDEA context * has been or is currently being retrieved, so the license is not * valid anymore, reset the URL and session header fields */ //if (url_ctx->url != NULL){ // RMFree(url_ctx->url); // url_ctx->url = NULL; //} if (url_ctx->session_header != NULL){ RMFree(url_ctx->session_header); url_ctx->session_header = NULL; }}/** * Decrypt cardea encrypted data (in place) * * @param cardea_context - the current cardea context * @param stream_index - current stream index * @param media_object_number - current media object number * @param buf - pointer to the data to decrypt * @param size - size of the data to decrypt * @return RM_OK on success
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -