xref: /utopia/UTPA2-700.0.x/modules/hdmi/hal/k6/hdmitx/halHDCPTx.c (revision 53ee8cc121a030b8d368113ac3e966b4705770ef)
1 //<MStar Software>
2 //******************************************************************************
3 // MStar Software
4 // Copyright (c) 2010 - 2012 MStar Semiconductor, Inc. All rights reserved.
5 // All software, firmware and related documentation herein ("MStar Software") are
6 // intellectual property of MStar Semiconductor, Inc. ("MStar") and protected by
7 // law, including, but not limited to, copyright law and international treaties.
8 // Any use, modification, reproduction, retransmission, or republication of all
9 // or part of MStar Software is expressly prohibited, unless prior written
10 // permission has been granted by MStar.
11 //
12 // By accessing, browsing and/or using MStar Software, you acknowledge that you
13 // have read, understood, and agree, to be bound by below terms ("Terms") and to
14 // comply with all applicable laws and regulations:
15 //
16 // 1. MStar shall retain any and all right, ownership and interest to MStar
17 //    Software and any modification/derivatives thereof.
18 //    No right, ownership, or interest to MStar Software and any
19 //    modification/derivatives thereof is transferred to you under Terms.
20 //
21 // 2. You understand that MStar Software might include, incorporate or be
22 //    supplied together with third party`s software and the use of MStar
23 //    Software may require additional licenses from third parties.
24 //    Therefore, you hereby agree it is your sole responsibility to separately
25 //    obtain any and all third party right and license necessary for your use of
26 //    such third party`s software.
27 //
28 // 3. MStar Software and any modification/derivatives thereof shall be deemed as
29 //    MStar`s confidential information and you agree to keep MStar`s
30 //    confidential information in strictest confidence and not disclose to any
31 //    third party.
32 //
33 // 4. MStar Software is provided on an "AS IS" basis without warranties of any
34 //    kind. Any warranties are hereby expressly disclaimed by MStar, including
35 //    without limitation, any warranties of merchantability, non-infringement of
36 //    intellectual property rights, fitness for a particular purpose, error free
37 //    and in conformity with any international standard.  You agree to waive any
38 //    claim against MStar for any loss, damage, cost or expense that you may
39 //    incur related to your use of MStar Software.
40 //    In no event shall MStar be liable for any direct, indirect, incidental or
41 //    consequential damages, including without limitation, lost of profit or
42 //    revenues, lost or damage of data, and unauthorized system use.
43 //    You agree that this Section 4 shall still apply without being affected
44 //    even if MStar Software has been modified by MStar in accordance with your
45 //    request or instruction for your use, except otherwise agreed by both
46 //    parties in writing.
47 //
48 // 5. If requested, MStar may from time to time provide technical supports or
49 //    services in relation with MStar Software to you for your use of
50 //    MStar Software in conjunction with your or your customer`s product
51 //    ("Services").
52 //    You understand and agree that, except otherwise agreed by both parties in
53 //    writing, Services are provided on an "AS IS" basis and the warranty
54 //    disclaimer set forth in Section 4 above shall apply.
55 //
56 // 6. Nothing contained herein shall be construed as by implication, estoppels
57 //    or otherwise:
58 //    (a) conferring any license or right to use MStar name, trademark, service
59 //        mark, symbol or any other identification;
60 //    (b) obligating MStar or any of its affiliates to furnish any person,
61 //        including without limitation, you and your customers, any assistance
62 //        of any kind whatsoever, or any information; or
63 //    (c) conferring any license or right under any intellectual property right.
64 //
65 // 7. These terms shall be governed by and construed in accordance with the laws
66 //    of Taiwan, R.O.C., excluding its conflict of law rules.
67 //    Any and all dispute arising out hereof or related hereto shall be finally
68 //    settled by arbitration referred to the Chinese Arbitration Association,
69 //    Taipei in accordance with the ROC Arbitration Law and the Arbitration
70 //    Rules of the Association by three (3) arbitrators appointed in accordance
71 //    with the said Rules.
72 //    The place of arbitration shall be in Taipei, Taiwan and the language shall
73 //    be English.
74 //    The arbitration award shall be final and binding to both parties.
75 //
76 //******************************************************************************
77 //<MStar Software>
78 ////////////////////////////////////////////////////////////////////////////////
79 //
80 // Copyright (c) 2006-2009 MStar Semiconductor, Inc.
81 // All rights reserved.
82 //
83 // Unless otherwise stipulated in writing, any and all information contained
84 // herein regardless in any format shall remain the sole proprietary of
85 // MStar Semiconductor Inc. and be kept in strict confidence
86 // (��MStar Confidential Information��) by the recipient.
87 // Any unauthorized act including without limitation unauthorized disclosure,
88 // copying, use, reproduction, sale, distribution, modification, disassembling,
89 // reverse engineering and compiling of the contents of MStar Confidential
90 // Information is unlawful and strictly prohibited. MStar hereby reserves the
91 // rights to any and all damages, losses, costs and expenses resulting therefrom.
92 //
93 ////////////////////////////////////////////////////////////////////////////////
94 
95 ///////////////////////////////////////////////////////////////////////////////////////////////////
96 ///
97 /// file    halHDCPTx.c
98 /// @author MStar Semiconductor Inc.
99 /// @brief  HDMITx HDCP HAL
100 ///////////////////////////////////////////////////////////////////////////////////////////////////
101 
102 
103 //-------------------------------------------------------------------------------------------------
104 //  Include Files
105 //-------------------------------------------------------------------------------------------------
106 #ifdef MSOS_TYPE_LINUX_KERNEL
107 #include <linux/string.h>
108 #else
109 #include <string.h>
110 #endif
111 #include "MsCommon.h"
112 #include "halHDMIUtilTx.h"
113 #include "regHDMITx.h"
114 #include "halHDCPTx.h"
115 
116 //-------------------------------------------------------------------------------------------------
117 //  Driver Compiler Options
118 //-------------------------------------------------------------------------------------------------
119 
120 
121 //-------------------------------------------------------------------------------------------------
122 //  Local Defines
123 //-------------------------------------------------------------------------------------------------
124 
125 #define HDCP_KEY_OFFSET         8U
126 
127 //-------------------------------------------------------------------------------------------------
128 //  Local Structures
129 //-------------------------------------------------------------------------------------------------
130 
131 //-------------------------------------------------------------------------------------------------
132 //  Global Variables
133 //-------------------------------------------------------------------------------------------------
134 
135 MS_BOOL bDebugHDCPFlag = FALSE;
136 MS_U8 HDCP_AKSV[5] = {0, 0, 0, 0, 0,};
137 MS_U8 HDCP_BKSV[5] = {0, 0, 0, 0, 0,};
138 
139 MS_U8 HDCP_KEY[304]=
140 {
141     0x47,0x7a,0x25,0x2f,0x1a,0xc1,0x54,0x00,0x93,0x23,0xbe,0x15,0x32,0x62,0x48,0xed,
142     0x8c,0xb8,0x80,0x61,0x06,0xc1,0x93,0x15,0xab,0xd9,0x3e,0x0f,0x5b,0xb5,0x76,0xcc,
143     0x25,0x01,0xbb,0x51,0xbc,0xbd,0x75,0x71,0x04,0x44,0x82,0xed,0x52,0xc6,0x68,0x11,
144     0x5f,0x24,0xff,0x48,0xac,0x6b,0x79,0xcb,0xf1,0xe8,0x2c,0xc4,0x3a,0x43,0xf0,0x27,
145     0x1d,0x15,0x9b,0x4e,0xa2,0x65,0x08,0x8d,0x69,0x69,0x35,0x1b,0x48,0xf0,0x79,0x57,
146     0x02,0xe5,0x69,0x58,0xa3,0x3e,0x0e,0x31,0xfe,0x8d,0x70,0x3e,0x30,0x21,0xdc,0x48,
147     0x9b,0x08,0xb5,0x2f,0x58,0xd2,0x21,0x67,0xe4,0x67,0x13,0x02,0x92,0x49,0x66,0x6f,
148     0xb6,0xe9,0x25,0x8c,0xa0,0x1f,0xd5,0xeb,0x25,0xbc,0xc6,0xa7,0x89,0x1a,0x33,0x8d,
149     0x50,0xf7,0x1d,0x88,0x18,0x7c,0xd3,0x26,0x80,0xa7,0x4c,0x40,0xae,0xb9,0x99,0x8a,
150     0x97,0x11,0x60,0xb5,0xbc,0x4a,0xce,0x14,0xa5,0x2d,0x86,0x73,0xd6,0xf2,0x45,0x19,
151     0x05,0xa3,0x81,0xa5,0xf3,0x8b,0x09,0xce,0x75,0x66,0xbe,0x17,0x04,0xf2,0x76,0xd9,
152     0x3e,0x53,0xbf,0x02,0x91,0xf7,0xbe,0x3b,0x05,0xfc,0x38,0xd2,0x80,0x7b,0x5a,0x0c,
153     0xb0,0xe8,0xb1,0x56,0x39,0xac,0x16,0x42,0xc2,0x1c,0x57,0x10,0xbd,0xd3,0x98,0x36,
154     0xd0,0x50,0x98,0x2d,0xbb,0x0b,0xd6,0x51,0xf0,0x31,0x0c,0x4f,0xfc,0x0c,0xb2,0xf6,
155     0x81,0x54,0xd4,0x39,0x0d,0xad,0xb8,0x73,0xf0,0x2d,0x47,0x5b,0xa0,0x01,0xe9,0x7f,
156     0x96,0xeb,0xbe,0xba,0xa2,0x82,0xee,0x3a,0x0b,0x11,0xee,0x39,0x93,0xab,0x91,0x63,
157     0xa9,0x25,0x63,0x24,0xcc,0x1f,0x80,0x45,0x56,0xbd,0xb3,0x82,0x7f,0xb3,0x7e,0xd9,
158     0xd1,0xcd,0xd7,0x89,0x0c,0x36,0x88,0x52,0x35,0xbf,0x6c,0xed,0xb3,0xca,0x9c,0x79,
159     0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
160 };
161 
162 //-------------------------------------------------------------------------------------------------
163 //  Local Variables
164 //-------------------------------------------------------------------------------------------------
165 
166 MSTHDMITX_REG_TYPE TxHdcpInitTbl[] =
167 {
168     {HDMITX_HDCP_REG_BASE, REG_HDCP_TX_MODE_01, 0x8000, 0x8000}, // Enable HDCP encryption
169     {HDMITX_HDCP_REG_BASE, REG_HDCP_TX_COMMAND_02, 0x001C, 0x0000}, //[4]: 1: km new mode; 0: km old mode
170 };
171 
172 MSTHDMITX_REG_TYPE TxHdcpEncryptOnTbl[] =
173 {
174     {HDMITX_HDCP_REG_BASE, REG_HDCP_TX_COMMAND_02, 0x0008, 0x0008},
175 };
176 
177 MSTHDMITX_REG_TYPE TxHdcpEncryptOffTbl[] =
178 {
179     {HDMITX_HDCP_REG_BASE, REG_HDCP_TX_COMMAND_02, 0x0008, 0x0000},
180 };
181 
182 MS_U8 TxHdcpAnTbl[] =
183 {
184     0x03, 0x04, 0x07, 0x0C, 0x13, 0x1C, 0x27, 0x34,
185 };
186 
187 MS_U32 sm_K160[4] =
188 {
189     0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6
190 };
191 
192 MS_U32 sm_H160[SHA160LENGTH] =
193 {
194     0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0
195 };
196 
197 
198 //-------------------------------------------------------------------------------------------------
199 //  Debug Functions
200 //-------------------------------------------------------------------------------------------------
201 
202 //-------------------------------------------------------------------------------------------------
203 //  Local Functions
204 //-------------------------------------------------------------------------------------------------
205 
206 extern MS_BOOL MDrv_EEPROM_Read(MS_U32 u32Addr, MS_U8 *pu8Buf, MS_U32 u32Size);
207 
Bytes2Word(MS_U8 const * pcBytes,MS_U32 * ruiWord)208 void Bytes2Word(MS_U8 const * pcBytes, MS_U32  * ruiWord)
209 {
210     *ruiWord = ((MS_U32) pcBytes[3])
211              | (((MS_U32) pcBytes[2]) << 8)
212              | (((MS_U32) pcBytes[1]) << 16)
213              | (((MS_U32) pcBytes[0]) << 24);
214 }
215 
216 //#define   Bytes2Word(pcBytes) (((MS_U32)pcBytes[3]) | (((MS_U32)pcBytes[2])<<8) |       (( (MS_U32)pcBytes[1] )<<16) | (( (MS_U32)pcBytes[0] )<<24))
217 
CircularShift(MS_U32 uiBits,MS_U32 uiWord)218 MS_U32 CircularShift(MS_U32 uiBits, MS_U32 uiWord)
219 {
220     return (uiWord << uiBits) | (uiWord >> (32 - uiBits));
221 }
222 
Word2Bytes1(MS_U32 const * ruiWord,MS_U8 * pcBytes)223 void Word2Bytes1(MS_U32 const * ruiWord, MS_U8* pcBytes)
224 {
225 	pcBytes += 3;
226 	*pcBytes = *ruiWord & 0xff;
227 	*--pcBytes = (*ruiWord >> 8) & 0xff;
228 	*--pcBytes = (*ruiWord >> 16) & 0xff;
229 	*--pcBytes = (*ruiWord >> 24) & 0xff;
230 }
231 
Word2Bytes(MS_U32 const * ruiWord,MS_U8 * pcBytes)232 void Word2Bytes(MS_U32 const * ruiWord, MS_U8* pcBytes)
233 {
234     pcBytes += 3;
235     *pcBytes = (*ruiWord>>24) & 0xff;
236     *--pcBytes = (*ruiWord >> 16) & 0xff;
237     *--pcBytes = (*ruiWord >> 8) & 0xff;
238     *--pcBytes = (*ruiWord) & 0xff;
239 }
240 
241 
MHal_HDMITx_HdcpDebugEnable(MS_BOOL benable)242 void MHal_HDMITx_HdcpDebugEnable(MS_BOOL benable)
243 {
244     bDebugHDCPFlag = benable;
245 }
246 
MHal_HDMITx_GetHdcpKey(MS_BOOL useinternalkey,MS_U8 * data)247 void MHal_HDMITx_GetHdcpKey(MS_BOOL useinternalkey, MS_U8 *data)
248 {
249     if(!useinternalkey)
250     {
251         memcpy(&HDCP_KEY[0], data, 304*sizeof(MS_U8));
252     	{
253             MS_U16 i;
254 
255             if(bDebugHDCPFlag)
256             {
257                 printf("HDCP key = \n");
258                 for(i=0;i<304;i++)
259                 {
260                     printf("0x%x, ", HDCP_KEY[i]);
261                     if ((i - ((i>>4)<<4) == 0) && (i != 0x00))//(i%16 == 15)
262                         printf("\n");
263                 }
264             }
265         }
266     }
267 }
268 
MHal_HDMITx_HdcpKeyInit(MS_BOOL useinternalkey)269 void MHal_HDMITx_HdcpKeyInit(MS_BOOL useinternalkey)
270 {
271     if(!useinternalkey)
272     {
273         MDrv_EEPROM_Read(0x00, HDCP_KEY, 304);
274     #if 1
275     	{
276             MS_U16 i;
277 
278             if(bDebugHDCPFlag)
279             {
280                 printf("HDCP key = \n");
281                 for(i=0;i<304;i++)
282                 {
283                     printf("0x%x, ", HDCP_KEY[i]);
284                     if ((i - ((i>>4)<<4) == 0) && (i != 0x00))//(i%16 == 15)
285                         printf("\n");
286                 }
287             }
288 
289 	}
290     #endif
291     }
292 }
293 
294 
295 //******************************************************************************
296 //
297 //  [Function Name]:
298 //      TxHdcpInit
299 //  [Description]:
300 //      This routine is the initialization for HDCP module.
301 //  [Arguments]:
302 //      arg1:   tx index
303 //  [Return]:
304 //      None
305 //
306 //*******************************************************************************
MHal_HDMITx_HdcpInit(void)307 void MHal_HDMITx_HdcpInit(void)
308 {
309     MS_U8 num;
310 
311     num = sizeof(TxHdcpInitTbl) / sizeof(MSTHDMITX_REG_TYPE);
312     MHal_HDMITx_RegsTbl_Write(TxHdcpInitTbl, num);
313 }
314 
315 
316 //******************************************************************************
317 //
318 //  [Function Name]:
319 //      TxHdcpRxActive
320 //  [Description]:
321 //      This routine check the HDCP Rx active or not
322 //  [Arguments]:
323 //      arg1:   tx index
324 //  [Return]:
325 //      FALSE:      no HDCP Rx
326 //      TRUE:       HDCP Rx active
327 //
328 //*******************************************************************************
MHal_HDMITx_HdcpRxActive(void)329 MS_BOOL MHal_HDMITx_HdcpRxActive(void)
330 {
331     MS_U8 regval;
332 
333     if (MHal_HDMITx_Rx74ReadByte(0x40, &regval) == TRUE)
334     {
335         if(regval != 0xFF)
336             return TRUE;
337     }
338     return FALSE;
339 }
340 
341 
342 //******************************************************************************
343 //
344 //  [Function Name]:
345 //      TxHdcpSetEncrypt
346 //  [Description]:
347 //      This routine set encryption for HDCP module.
348 //  [Arguments]:
349 //      arg1:   tx index
350 //      arg2:   0:disable 1:enable
351 //  [Return]:
352 //      None
353 //
354 //*******************************************************************************
MHal_HDMITx_HdcpSetEncrypt(MS_BOOL enable)355 void MHal_HDMITx_HdcpSetEncrypt(MS_BOOL enable)
356 {
357     switch (enable)
358     {
359         case 0:
360             MHal_HDMITx_RegsTbl_Write(TxHdcpEncryptOffTbl, 1);
361             break;
362         case 1:
363             MHal_HDMITx_RegsTbl_Write(TxHdcpEncryptOnTbl, 1);
364             break;
365         default:
366             break;
367     }
368 }
369 
370 
371 //******************************************************************************
372 //
373 //  [Function Name]:
374 //      TxHdcpCheckBksvLn
375 //  [Description]:
376 //      This routine check the HDCP Rx's BKSV and calculate the Key
377 //  [Arguments]:
378 //      arg1:   tx index
379 //  [Return]:
380 //      TRUE:   pass
381 //      FALSE:  fail
382 //
383 //*******************************************************************************
MHal_HDMITx_HdcpCheckBksvLn(void)384 MS_BOOL MHal_HDMITx_HdcpCheckBksvLn(void)
385 {
386     MS_U8 bksv[5] = {0}, Lm[7] = {0};
387     MS_U8 temp, carry_bit, seed;
388     MS_U8 i, j, k, t;
389     MS_U16 offset;
390 
391     if(bDebugHDCPFlag)
392         printf("TxHdcpCheckBksvLn()\r\n");
393     // Check BKSV 20 bit1 20 bit0
394     k = 0;
395     for (t = 0; t < 10; t++)
396     {
397         for (i = 0; i < 5; i++)
398         {
399             if(MHal_HDMITx_Rx74ReadByte(i, &bksv[i]) == FALSE)
400             {
401                 if(bDebugHDCPFlag)
402                     printf("Reading BKSV failed because I2C\r\n");
403                 return FALSE;
404             }
405             for (j = 0; j < 8; j++)
406                 k += (bksv[i] >> j) & 0x01;
407 
408 			HDCP_BKSV[i] = bksv[i];
409         }
410         if (k == 20)
411             break;
412         MsOS_DelayTask(20);
413         k=0;
414     }
415 
416     if(bDebugHDCPFlag)
417     {
418         printf("Bksv=");
419         for (i = 0; i < 5; i++)
420             printf("0x%x, ", bksv[i]);
421         printf("\r\n");
422     }
423 
424     if (k != 20)
425         return FALSE;
426     for (i = 0; i < 7; i++)
427         Lm[i] = 0;
428 
429 #if 0
430     for(i=0;i<18;i++)
431     {
432         for(j=0;j<16;j++)
433         {
434             if(HDCP_KEY[(i<<4)+j]!=MHal_HDMITx_Rx74ReadByte((i<<4)+j))
435             DBG_HDCP(printf("\r\nerror address=%x\r\n,",(i<<4)+j));
436         }
437     }
438 #endif
439 
440     // Generate cipher infomation from Key & BKSV
441     for (i = 0; i < 5; i++)
442         for (j = 0; j < 8; j++)
443         {
444             //if(RxBksvTbl[4-i] & (1<<j))
445             if (bksv[i] & (1 << j))
446             {
447                 carry_bit = 0;
448                 offset = (i * 8 + j) * 7 + HDCP_KEY_OFFSET;
449                 for (k = 0; k < 7; k++)
450                 {
451                     seed = (k + HDCP_KEY[7]) % 7;
452                     temp = HDCP_KEY[offset + k] ^ HDCP_KEY[seed];
453                     Lm[k] = Lm[k] + temp + carry_bit;
454                     if (((carry_bit == 0) && (Lm[k] >= temp)) || ((carry_bit == 1) && (Lm[k] > temp)))
455                         carry_bit = 0;
456                     else
457                         carry_bit = 1;
458                 }
459             }
460         }
461     temp = HDCP_KEY[288];
462 
463     if(bDebugHDCPFlag)
464         printf("Km= ");
465     for (i = 0; i < 7; i++)
466     {
467         if (i < 6)
468             Lm[i] = Lm[i] ^ temp;
469         else
470             Lm[i] = Lm[i] ^ (~temp);
471 
472         if(i%2)
473             MHal_HDMITx_Write(HDMITX_HDCP_REG_BASE, REG_HDCP_TX_LN_04+(i/2), (Lm[i]<<8) | Lm[i-1]);
474         if(bDebugHDCPFlag)
475             printf("0x%x, ", Lm[i]);
476     }
477     if(bDebugHDCPFlag)
478         printf("\n");
479     MHal_HDMITx_Write(HDMITX_HDCP_REG_BASE, REG_HDCP_TX_LN_SEED_07, (temp<<8) | Lm[6]);
480     if(bDebugHDCPFlag)
481         printf("Seed=0x%x\r\n", temp);
482 
483     return TRUE;
484 }
485 
486 
487 //******************************************************************************
488 //
489 //  [Function Name]:
490 //      TxHdcpWriteAn
491 //  [Description]:
492 //      This routine Write An to the HDCP Rx
493 //  [Arguments]:
494 //      arg1:   tx index
495 //      arg2:   use internal An or not
496 //  [Return]:
497 //      None
498 //
499 //*******************************************************************************
MHal_HDMITx_HdcpWriteAn(MS_U8 internal)500 MS_BOOL MHal_HDMITx_HdcpWriteAn(MS_U8 internal)
501 {
502     MS_U16 temp;
503     MS_U8 i;
504 
505     if (internal == 1)
506     {
507         MHal_HDMITx_Mask_Write(HDMITX_HDCP_REG_BASE, REG_HDCP_TX_MODE_01, 0x0100, 0x0100);
508         MHal_HDMITx_Mask_Write(HDMITX_HDCP_REG_BASE, REG_HDCP_TX_COMMAND_02, BIT1, BIT1);
509         MHal_HDMITx_Mask_Write(HDMITX_HDCP_REG_BASE, REG_HDCP_TX_COMMAND_02, BIT1, 0);
510 
511         //Waiting for HW An Auto Gen Ready
512         MsOS_DelayTask(1);
513 
514         if(bDebugHDCPFlag)
515             printf("Internal An=");
516         for (i = 0; i < 4; i++)
517         {
518             temp = MHal_HDMITx_Read(HDMITX_HDCP_REG_BASE, REG_HDCP_TX_AN_08+i);
519             if(MHal_HDMITx_Rx74WriteByte(0x18 + (i*2), (MS_U8)(temp & 0x00FF)) == FALSE)
520             {
521                 if(bDebugHDCPFlag)
522                     printf("Writing An failed because I2C\r\n");
523                 return FALSE;
524             }
525             if(MHal_HDMITx_Rx74WriteByte(0x18 + (i*2+1), (MS_U8)((temp & 0xFF00)>>8)) == FALSE)
526             {
527                 if(bDebugHDCPFlag)
528                     printf("Writing An failed because I2C\r\n");
529                 return FALSE;
530             }
531             if(bDebugHDCPFlag)
532             {
533                 printf("0x%x, ", temp & 0x00FF);
534                 printf("0x%x, ", (temp & 0xFF00)>>8);
535             }
536         }
537         if(bDebugHDCPFlag)
538             printf("\r\n");
539     }
540     else
541     {
542         MHal_HDMITx_Mask_Write(HDMITX_HDCP_REG_BASE, REG_HDCP_TX_MODE_01, 0x0100, 0x0000);
543         for(i = 0; i < 4; i++)
544             MHal_HDMITx_Write(HDMITX_HDCP_REG_BASE, REG_HDCP_TX_AN_08+i, (TxHdcpAnTbl[2*i+1] <<8) | (TxHdcpAnTbl[2*i]));
545         if(MHal_HDMITx_Rx74WriteBytes(0x18, 8, TxHdcpAnTbl) == FALSE)
546         {
547             if(bDebugHDCPFlag)
548                 printf("Writing An failed because I2C\r\n");
549             return FALSE;
550         }
551         if(bDebugHDCPFlag)
552         {
553              printf("External An=");
554              for (i = 0; i < 8; i++)
555                  printf("0x%x, ", TxHdcpAnTbl[i]);
556              printf("\r\n");
557         }
558     }
559     return TRUE;
560 }
561 
562 
563 //******************************************************************************
564 //
565 //  [Function Name]:
566 //      TxHdcpWriteAksv
567 //  [Description]:
568 //      This routine Write AKSV to the HDCP Rx
569 //  [Arguments]:
570 //      arg1:   tx index
571 //  [Return]:
572 //      None
573 //
574 //*******************************************************************************
MHal_HDMITx_HdcpWriteAksv(void)575 MS_BOOL MHal_HDMITx_HdcpWriteAksv(void)
576 {
577     MS_U8 temp;
578     MS_U8 i, k, j;
579 
580     if(bDebugHDCPFlag)
581         printf("Aksv=");
582     for (i = 0, k=0; i < 5; i++)
583     {
584         //temp = TxHdcpKeyTbl[i];
585         temp = HDCP_KEY[i];
586         HDCP_AKSV[i] = temp;
587         if(MHal_HDMITx_Rx74WriteByte(0x10 + i, temp) == FALSE)
588         {
589             if(bDebugHDCPFlag)
590                 printf("Writing Aksv failed because I2C\r\n");
591             return FALSE;
592         }
593         for (j = 0; j < 8; j++)
594             k += (temp >> j) & 0x01; // check AKSV whether is 20 zeros and 20 ones or not.
595         if(bDebugHDCPFlag)
596             printf("0x%x, ", temp);
597     }
598     if(bDebugHDCPFlag)
599         printf("\r\n");
600     if(k!=20)	return FALSE;
601     return TRUE;
602 }
603 
604 
605 //******************************************************************************
606 //
607 //  [Function Name]:
608 //      MHal_HDMITx_GET74
609 //  [Description]:
610 //      This routine get data from 74reg
611 //  [Arguments]:
612 //
613 //  [Return]:
614 //      None
615 //
616 //*******************************************************************************
MHal_HDMITx_GET74(MS_U8 udata,MS_U8 * pdata)617 void MHal_HDMITx_GET74(MS_U8 udata, MS_U8 *pdata)
618 {
619    if(udata == 0x00)
620        memcpy(pdata, &HDCP_BKSV, 5*sizeof(MS_U8));
621    else if(udata == 0x10)
622        memcpy(pdata, &HDCP_AKSV, 5*sizeof(MS_U8));
623 }
624 
625 
626 //******************************************************************************
627 //
628 //  [Function Name]:
629 //      TxHdcpStartCipher
630 //  [Description]:
631 //      This routine Start HDCP Tx Cipher
632 //  [Arguments]:
633 //      arg1:   tx index
634 //  [Return]:
635 //      None
636 //
637 //*******************************************************************************
MHal_HDMITx_HdcpStartCipher(void)638 void MHal_HDMITx_HdcpStartCipher(void)
639 {
640     MS_U8 count = 0xFF;
641 
642     MHal_HDMITx_Mask_Write(HDMITX_HDCP_REG_BASE, REG_HDCP_TX_COMMAND_02, 0x000F, 0);
643     MHal_HDMITx_Mask_Write(HDMITX_HDCP_REG_BASE, REG_HDCP_TX_COMMAND_02, 0x000F, BIT0);
644     MHal_HDMITx_Mask_Write(HDMITX_HDCP_REG_BASE, REG_HDCP_TX_COMMAND_02, 0x000F, 0);
645 
646     while (count-- && !(MHal_HDMITx_Read(HDMITX_HDCP_REG_BASE, REG_HDCP_TX_COMMAND_02) & BIT8));
647     if (count == 0)
648     {
649         if(bDebugHDCPFlag)
650             printf("Cipher not done!!!\r\n");
651     }
652 }
653 
654 
655 //******************************************************************************
656 //
657 //  [Function Name]:
658 //      TxHdcpAuthPass
659 //  [Description]:
660 //      This routine finish the authentication
661 //  [Arguments]:
662 //      arg1:   tx index
663 //  [Return]:
664 //      None
665 //
666 //*******************************************************************************
MHal_HDMITx_HdcpAuthPass(void)667 void MHal_HDMITx_HdcpAuthPass(void)
668 {
669     MHal_HDMITx_Mask_Write(HDMITX_HDCP_REG_BASE, REG_HDCP_TX_COMMAND_02, 0x000F, 0x000C);
670 }
671 
672 
MHal_HDMITx_HdcpSha1Init(SHA1_DATA * dig)673 void MHal_HDMITx_HdcpSha1Init(SHA1_DATA *dig)
674 {
675     MS_U8 i;
676 
677     for (i = 0; i < SHA160LENGTH; i++)
678         dig->m_auiBuf[i] = sm_H160[i];
679     dig->m_auiBits[0] = 0;
680     dig->m_auiBits[1] = 0;
681     memset(dig->m_aucIn, 0, BLOCKSIZE) ;  // 2006/1/18 3:31PM by Emily
682 }
683 
684 
685 //******************************************************************************
686 //
687 //  [Function Name]:
688 //      TxHdcpCheckRi
689 //  [Description]:
690 //      This routine check the hdcp Ri values
691 //  [Arguments]:
692 //      arg1:   tx index
693 //      arg2:   output Tx Ri value
694 //      arg3:   output Rx Ri value
695 //  [Return]:
696 //      None
697 //
698 //*******************************************************************************
MHal_HDMITx_HdcpCheckRi(MS_U16 * ptx_ri,MS_U16 * prx_ri)699 MS_BOOL MHal_HDMITx_HdcpCheckRi(MS_U16 *ptx_ri, MS_U16 *prx_ri)
700 {
701     *ptx_ri = MHal_HDMITx_Read(HDMITX_HDCP_REG_BASE, REG_HDCP_TX_RI_00);
702     if(MHal_HDMITx_Rx74ReadBytes(0x08, 2, (MS_U8 *)prx_ri) == TRUE)
703     {
704         if (*prx_ri == *ptx_ri)
705             return TRUE;
706     }
707     if(MHal_HDMITx_Rx74ReadBytes(0x08, 2, (MS_U8 *)prx_ri) == TRUE)
708     {
709         if (*prx_ri == *ptx_ri)
710             return TRUE;
711     }
712     *ptx_ri = MHal_HDMITx_Read(HDMITX_HDCP_REG_BASE, REG_HDCP_TX_RI_00);
713     if (*prx_ri == *ptx_ri)
714         return TRUE;
715     else
716         return FALSE;
717 }
718 
719 
_MHal_HDMITx_HdcpSha1Transform(SHA1_DATA * dig)720 void _MHal_HDMITx_HdcpSha1Transform(SHA1_DATA *dig)
721 {
722     MS_U8 * pucIn = dig->m_aucIn;
723     MS_U32 auiW[80];
724     MS_U8 i;
725     MS_U32 temp;
726     MS_U32 A, B, C, D, E;
727 
728     for (i = 0; i < 16; i++,pucIn += 4)
729         auiW[i] = ((MS_U32)pucIn[3]) | ((MS_U32)pucIn[2] << 8) |
730                   ((MS_U32)pucIn[1] << 16) | ((MS_U32)pucIn[0] << 24);
731     for (i = 16; i < 80; i++)
732         auiW[i] = ((auiW[i - 3] ^ auiW[i - 8] ^ auiW[i - 14] ^ auiW[i - 16]) << 1) |
733                   ((auiW[i - 3] ^ auiW[i - 8] ^ auiW[i - 14] ^ auiW[i - 16]) >> 31);
734 
735     A = dig->m_auiBuf[0];
736     B = dig->m_auiBuf[1];
737     C = dig->m_auiBuf[2];
738     D = dig->m_auiBuf[3];
739     E = dig->m_auiBuf[4];
740 
741     for (i = 0; i < 20; i++)
742     {
743         temp = ((A << 5) | (A >> 27)) + ((B & C) | ((~B) & D)) + E + auiW[i] + sm_K160[0];
744         E = D;
745         D = C;
746 		C = (B << 30) | (B >> 2);
747         B = A;
748         A = temp;
749     }
750     for (i = 20; i < 40; i++)
751     {
752         temp = ((A << 5) | (A >> 27)) + (B ^ C ^ D) + E + auiW[i] + sm_K160[1];
753         E = D;
754         D = C;
755 		C = (B << 30) | (B >> 2);
756         B = A;
757         A = temp;
758     }
759     for (i = 40; i < 60; i++)
760     {
761         temp = ((A << 5) | (A >> 27)) + ((B & C) | (B & D) | (C & D)) + E + auiW[i] + sm_K160[2];
762         E = D;
763         D = C;
764 		C = (B << 30) | (B >> 2);
765         B = A;
766         A = temp;
767     }
768     for (i = 60; i < 80; i++)
769     {
770         temp = ((A << 5) | (A >> 27)) + (B ^ C ^ D) + E + auiW[i] + sm_K160[3];
771         E = D;
772         D = C;
773 		C = (B << 30) | (B >> 2);
774         B = A;
775         A = temp;
776     }
777     dig->m_auiBuf[0] += A;
778     dig->m_auiBuf[1] += B;
779     dig->m_auiBuf[2] += C;
780     dig->m_auiBuf[3] += D;
781     dig->m_auiBuf[4] += E;
782 }
783 
784 
MHal_HDMITx_HdcpSha1AddData(SHA1_DATA * dig,MS_U8 const * pcData,MS_U16 iDataLength)785 void MHal_HDMITx_HdcpSha1AddData(SHA1_DATA *dig, MS_U8 const * pcData, MS_U16  iDataLength)
786 {
787     MS_U32  uiT;
788 
789     //Update bitcount
790     uiT = dig->m_auiBits[0];
791     if ((dig->m_auiBits[0] = uiT + ((MS_U32) iDataLength << 3)) < uiT)
792         dig->m_auiBits[1]++; //Carry from low to high
793     //dig->m_auiBits[1] += ((MS_U32) iDataLength) >> 29;  //Fix coverity impact : iDataLength >> 29 is 0
794     uiT = (uiT >> 3) & (BLOCKSIZE - 1); //Bytes already
795     //Handle any leading odd-sized chunks
796     if (uiT != 0)
797     {
798         MS_U8 * puc = (MS_U8 *) dig->m_aucIn + uiT;
799         uiT = BLOCKSIZE - uiT;
800         if (iDataLength < uiT)
801         {
802             memcpy(puc, pcData, iDataLength);
803             return;
804         }
805         memcpy(puc, pcData, uiT);
806         _MHal_HDMITx_HdcpSha1Transform(dig);
807         pcData += uiT;
808         iDataLength -= uiT;
809     }
810     //Process data in 64-byte chunks
811     while (iDataLength >= BLOCKSIZE)
812     {
813         memcpy(dig->m_aucIn, pcData, BLOCKSIZE);
814         _MHal_HDMITx_HdcpSha1Transform(dig);
815         pcData += BLOCKSIZE;
816         iDataLength -= BLOCKSIZE;
817     }
818     //Handle any remaining bytes of data
819     memcpy(dig->m_aucIn, pcData, iDataLength);
820 }
821 
822 
MHal_HDMITx_HdcpSha1FinalDigest(SHA1_DATA * dig,MS_U8 * pcDigest)823 void MHal_HDMITx_HdcpSha1FinalDigest(SHA1_DATA *dig, MS_U8* pcDigest)
824 {
825     MS_U16  uiCount;
826     MS_U8   *puc;
827     MS_U8   i;
828 
829     //Compute number of bytes mod 64
830     uiCount = (dig->m_auiBits[0] >> 3) & (BLOCKSIZE - 1);
831     //Set the first char of padding to 0x80. This is safe since there is
832     //always at least one byte free
833     puc = dig->m_aucIn + uiCount;
834     *puc++ = 0x80;
835     //Bytes of padding needed to make 64 bytes
836     uiCount = BLOCKSIZE - uiCount - 1;
837 
838     //Pad out to 56 mod 64
839     if (uiCount < 8)
840     {
841         //Two lots of padding: Pad the first block to 64 bytes
842         memset(puc, 0, uiCount);
843         _MHal_HDMITx_HdcpSha1Transform(dig);
844         //Now fill the next block with 56 bytes
845         memset(dig->m_aucIn, 0, BLOCKSIZE - 8);
846     }
847     else
848     {
849         //Pad block to 56 bytes
850         memset(puc, 0, uiCount - 8);
851     }
852 
853     //Append length in bits and transform
854     Word2Bytes1(&dig->m_auiBits[1], &dig->m_aucIn[BLOCKSIZE - 8]);
855     Word2Bytes1(&dig->m_auiBits[0], &dig->m_aucIn[BLOCKSIZE - 4]);
856     _MHal_HDMITx_HdcpSha1Transform(dig);
857 
858     for (i = 0; i < SHA160LENGTH; i++,pcDigest += 4)
859         Word2Bytes(&dig->m_auiBuf[i], pcDigest);
860 }
861 
862 
863 // *************  For customer NDS **************//
864 
MHal_HDMITx_HDCP_Get_BCaps(MS_U8 * u8bcaps)865 MS_BOOL MHal_HDMITx_HDCP_Get_BCaps(MS_U8 *u8bcaps)
866 {
867     return (MHal_HDMITx_Rx74ReadByte(0x40, u8bcaps));
868 }
869 
MHal_HDMITx_HDCP_Get_BStatus(MS_U16 * u16bstatus)870 MS_BOOL MHal_HDMITx_HDCP_Get_BStatus(MS_U16 *u16bstatus)
871 {
872     MS_U8 u8data1 = 0x0;
873 	MS_U8 u8data2 = 0x0;
874     MS_BOOL ret = TRUE;
875 
876     if(!MHal_HDMITx_Rx74ReadByte(0x42, &u8data2) || !MHal_HDMITx_Rx74ReadByte(0x41, &u8data1))
877         ret = FALSE;
878     *u16bstatus = ((MS_U16) u8data2<< 8) | u8data1;
879     return ret;
880 }
881 
MHal_HDMITx_HDCP_Get_BKSV(MS_U8 * u8bksv)882 MS_BOOL MHal_HDMITx_HDCP_Get_BKSV(MS_U8 *u8bksv)
883 {
884     MS_U8 i;
885     MS_BOOL ret = TRUE;
886 
887     for(i=0; i<5; i++)
888     {
889         if(!MHal_HDMITx_Rx74ReadByte(0x00+i, u8bksv+i))
890             ret = FALSE;
891     }
892     return ret;
893 }
894 
MHal_HDMITx_HDCP_SHA1_Transform(unsigned int * sha1,const MS_U8 * s)895 void MHal_HDMITx_HDCP_SHA1_Transform(unsigned int *sha1, const MS_U8 *s)
896 {
897     SHA1_DATA tdig;
898 
899     MHal_HDMITx_HdcpSha1Init(&tdig);
900     // MS_U32 M[2], w[16]
901     // w[0]=M[0];
902     // w[1]=M[1];
903     // w[2]=0x80000000;
904     // w[3]=0;w[4]=0;w[5]=0;w[6]=0;w[7]=0;w[8]=0;w[9]=0;w[10]=0;w[11]=0;w[12]=0;w[13]=0;
905     // w[14]=0;w[15]=0x00000040;
906     memcpy(&tdig.m_aucIn[0], s, 8*sizeof(MS_U8)); // The first 8 bytes are copy from message
907     tdig.m_aucIn[8] = 0x80; // append the bit "1" and K = 439 bits "0" to the message
908     memset(&tdig.m_aucIn[9], 0, 54*sizeof(MS_U8));
909     tdig.m_aucIn[63] = 0x40; // apppend length of message, 64 bytes
910 
911     _MHal_HDMITx_HdcpSha1Transform(&tdig);
912     memcpy(sha1, &tdig.m_auiBuf[0], 5*sizeof(MS_U32));
913     //printf("@@SRM - Trans Msg= %8x%8x%8x%8x%8x\r\n", tdig.m_auiBuf[0],tdig.m_auiBuf[1],tdig.m_auiBuf[2],tdig.m_auiBuf[3],tdig.m_auiBuf[4]);
914 }
915 
916 // *************  end  **************//
917 
918