cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hdcp_ddc.c (20766B)


      1/*
      2 * Copyright 2019 Advanced Micro Devices, Inc.
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice shall be included in
     12 * all copies or substantial portions of the Software.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 * OTHER DEALINGS IN THE SOFTWARE.
     21 *
     22 * Authors: AMD
     23 *
     24 */
     25
     26#include "hdcp.h"
     27
     28#define MIN(a, b) ((a) < (b) ? (a) : (b))
     29#define HDCP_I2C_ADDR 0x3a	/* 0x74 >> 1*/
     30#define KSV_READ_SIZE 0xf	/* 0x6803b - 0x6802c */
     31#define HDCP_MAX_AUX_TRANSACTION_SIZE 16
     32
     33#define DP_CP_IRQ (1 << 2)
     34
     35enum mod_hdcp_ddc_message_id {
     36	MOD_HDCP_MESSAGE_ID_INVALID = -1,
     37
     38	/* HDCP 1.4 */
     39
     40	MOD_HDCP_MESSAGE_ID_READ_BKSV = 0,
     41	MOD_HDCP_MESSAGE_ID_READ_RI_R0,
     42	MOD_HDCP_MESSAGE_ID_WRITE_AKSV,
     43	MOD_HDCP_MESSAGE_ID_WRITE_AINFO,
     44	MOD_HDCP_MESSAGE_ID_WRITE_AN,
     45	MOD_HDCP_MESSAGE_ID_READ_VH_X,
     46	MOD_HDCP_MESSAGE_ID_READ_VH_0,
     47	MOD_HDCP_MESSAGE_ID_READ_VH_1,
     48	MOD_HDCP_MESSAGE_ID_READ_VH_2,
     49	MOD_HDCP_MESSAGE_ID_READ_VH_3,
     50	MOD_HDCP_MESSAGE_ID_READ_VH_4,
     51	MOD_HDCP_MESSAGE_ID_READ_BCAPS,
     52	MOD_HDCP_MESSAGE_ID_READ_BSTATUS,
     53	MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO,
     54	MOD_HDCP_MESSAGE_ID_READ_BINFO,
     55
     56	/* HDCP 2.2 */
     57
     58	MOD_HDCP_MESSAGE_ID_HDCP2VERSION,
     59	MOD_HDCP_MESSAGE_ID_RX_CAPS,
     60	MOD_HDCP_MESSAGE_ID_WRITE_AKE_INIT,
     61	MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT,
     62	MOD_HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM,
     63	MOD_HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM,
     64	MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME,
     65	MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO,
     66	MOD_HDCP_MESSAGE_ID_WRITE_LC_INIT,
     67	MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME,
     68	MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS,
     69	MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST,
     70	MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST_PART2,
     71	MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK,
     72	MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE,
     73	MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY,
     74	MOD_HDCP_MESSAGE_ID_READ_RXSTATUS,
     75	MOD_HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE,
     76
     77	MOD_HDCP_MESSAGE_ID_MAX
     78};
     79
     80static const uint8_t hdcp_i2c_offsets[] = {
     81	[MOD_HDCP_MESSAGE_ID_READ_BKSV] = 0x0,
     82	[MOD_HDCP_MESSAGE_ID_READ_RI_R0] = 0x8,
     83	[MOD_HDCP_MESSAGE_ID_WRITE_AKSV] = 0x10,
     84	[MOD_HDCP_MESSAGE_ID_WRITE_AINFO] = 0x15,
     85	[MOD_HDCP_MESSAGE_ID_WRITE_AN] = 0x18,
     86	[MOD_HDCP_MESSAGE_ID_READ_VH_X] = 0x20,
     87	[MOD_HDCP_MESSAGE_ID_READ_VH_0] = 0x20,
     88	[MOD_HDCP_MESSAGE_ID_READ_VH_1] = 0x24,
     89	[MOD_HDCP_MESSAGE_ID_READ_VH_2] = 0x28,
     90	[MOD_HDCP_MESSAGE_ID_READ_VH_3] = 0x2C,
     91	[MOD_HDCP_MESSAGE_ID_READ_VH_4] = 0x30,
     92	[MOD_HDCP_MESSAGE_ID_READ_BCAPS] = 0x40,
     93	[MOD_HDCP_MESSAGE_ID_READ_BSTATUS] = 0x41,
     94	[MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x43,
     95	[MOD_HDCP_MESSAGE_ID_READ_BINFO] = 0xFF,
     96	[MOD_HDCP_MESSAGE_ID_HDCP2VERSION] = 0x50,
     97	[MOD_HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x60,
     98	[MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x80,
     99	[MOD_HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x60,
    100	[MOD_HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x60,
    101	[MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x80,
    102	[MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x80,
    103	[MOD_HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x60,
    104	[MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x80,
    105	[MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x60,
    106	[MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x80,
    107	[MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST_PART2] = 0x80,
    108	[MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x60,
    109	[MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x60,
    110	[MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x80,
    111	[MOD_HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x70,
    112	[MOD_HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = 0x0
    113};
    114
    115static const uint32_t hdcp_dpcd_addrs[] = {
    116	[MOD_HDCP_MESSAGE_ID_READ_BKSV] = 0x68000,
    117	[MOD_HDCP_MESSAGE_ID_READ_RI_R0] = 0x68005,
    118	[MOD_HDCP_MESSAGE_ID_WRITE_AKSV] = 0x68007,
    119	[MOD_HDCP_MESSAGE_ID_WRITE_AINFO] = 0x6803B,
    120	[MOD_HDCP_MESSAGE_ID_WRITE_AN] = 0x6800c,
    121	[MOD_HDCP_MESSAGE_ID_READ_VH_X] = 0x68014,
    122	[MOD_HDCP_MESSAGE_ID_READ_VH_0] = 0x68014,
    123	[MOD_HDCP_MESSAGE_ID_READ_VH_1] = 0x68018,
    124	[MOD_HDCP_MESSAGE_ID_READ_VH_2] = 0x6801c,
    125	[MOD_HDCP_MESSAGE_ID_READ_VH_3] = 0x68020,
    126	[MOD_HDCP_MESSAGE_ID_READ_VH_4] = 0x68024,
    127	[MOD_HDCP_MESSAGE_ID_READ_BCAPS] = 0x68028,
    128	[MOD_HDCP_MESSAGE_ID_READ_BSTATUS] = 0x68029,
    129	[MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x6802c,
    130	[MOD_HDCP_MESSAGE_ID_READ_BINFO] = 0x6802a,
    131	[MOD_HDCP_MESSAGE_ID_RX_CAPS] = 0x6921d,
    132	[MOD_HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x69000,
    133	[MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x6900b,
    134	[MOD_HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x69220,
    135	[MOD_HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x692a0,
    136	[MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x692c0,
    137	[MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x692e0,
    138	[MOD_HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x692f0,
    139	[MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x692f8,
    140	[MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x69318,
    141	[MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x69330,
    142	[MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST_PART2] = 0x69340,
    143	[MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x693e0,
    144	[MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x693f0,
    145	[MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x69473,
    146	[MOD_HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x69493,
    147	[MOD_HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = 0x69494
    148};
    149
    150static enum mod_hdcp_status read(struct mod_hdcp *hdcp,
    151		enum mod_hdcp_ddc_message_id msg_id,
    152		uint8_t *buf,
    153		uint32_t buf_len)
    154{
    155	bool success = true;
    156	uint32_t cur_size = 0;
    157	uint32_t data_offset = 0;
    158
    159	if (is_dp_hdcp(hdcp)) {
    160		while (buf_len > 0) {
    161			cur_size = MIN(buf_len, HDCP_MAX_AUX_TRANSACTION_SIZE);
    162			success = hdcp->config.ddc.funcs.read_dpcd(hdcp->config.ddc.handle,
    163					hdcp_dpcd_addrs[msg_id] + data_offset,
    164					buf + data_offset,
    165					cur_size);
    166
    167			if (!success)
    168				break;
    169
    170			buf_len -= cur_size;
    171			data_offset += cur_size;
    172		}
    173	} else {
    174		success = hdcp->config.ddc.funcs.read_i2c(
    175				hdcp->config.ddc.handle,
    176				HDCP_I2C_ADDR,
    177				hdcp_i2c_offsets[msg_id],
    178				buf,
    179				(uint32_t)buf_len);
    180	}
    181
    182	return success ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE;
    183}
    184
    185static enum mod_hdcp_status read_repeatedly(struct mod_hdcp *hdcp,
    186		enum mod_hdcp_ddc_message_id msg_id,
    187		uint8_t *buf,
    188		uint32_t buf_len,
    189		uint8_t read_size)
    190{
    191	enum mod_hdcp_status status = MOD_HDCP_STATUS_DDC_FAILURE;
    192	uint32_t cur_size = 0;
    193	uint32_t data_offset = 0;
    194
    195	while (buf_len > 0) {
    196		cur_size = MIN(buf_len, read_size);
    197		status = read(hdcp, msg_id, buf + data_offset, cur_size);
    198
    199		if (status != MOD_HDCP_STATUS_SUCCESS)
    200			break;
    201
    202		buf_len -= cur_size;
    203		data_offset += cur_size;
    204	}
    205
    206	return status;
    207}
    208
    209static enum mod_hdcp_status write(struct mod_hdcp *hdcp,
    210		enum mod_hdcp_ddc_message_id msg_id,
    211		uint8_t *buf,
    212		uint32_t buf_len)
    213{
    214	bool success = true;
    215	uint32_t cur_size = 0;
    216	uint32_t data_offset = 0;
    217
    218	if (is_dp_hdcp(hdcp)) {
    219		while (buf_len > 0) {
    220			cur_size = MIN(buf_len, HDCP_MAX_AUX_TRANSACTION_SIZE);
    221			success = hdcp->config.ddc.funcs.write_dpcd(
    222					hdcp->config.ddc.handle,
    223					hdcp_dpcd_addrs[msg_id] + data_offset,
    224					buf + data_offset,
    225					cur_size);
    226
    227			if (!success)
    228				break;
    229
    230			buf_len -= cur_size;
    231			data_offset += cur_size;
    232		}
    233	} else {
    234		hdcp->buf[0] = hdcp_i2c_offsets[msg_id];
    235		memmove(&hdcp->buf[1], buf, buf_len);
    236		success = hdcp->config.ddc.funcs.write_i2c(
    237				hdcp->config.ddc.handle,
    238				HDCP_I2C_ADDR,
    239				hdcp->buf,
    240				(uint32_t)(buf_len+1));
    241	}
    242
    243	return success ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE;
    244}
    245
    246enum mod_hdcp_status mod_hdcp_read_bksv(struct mod_hdcp *hdcp)
    247{
    248	return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BKSV,
    249			hdcp->auth.msg.hdcp1.bksv,
    250			sizeof(hdcp->auth.msg.hdcp1.bksv));
    251}
    252
    253enum mod_hdcp_status mod_hdcp_read_bcaps(struct mod_hdcp *hdcp)
    254{
    255	return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BCAPS,
    256			&hdcp->auth.msg.hdcp1.bcaps,
    257			sizeof(hdcp->auth.msg.hdcp1.bcaps));
    258}
    259
    260enum mod_hdcp_status mod_hdcp_read_bstatus(struct mod_hdcp *hdcp)
    261{
    262	enum mod_hdcp_status status;
    263
    264	if (is_dp_hdcp(hdcp))
    265		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BSTATUS,
    266					(uint8_t *)&hdcp->auth.msg.hdcp1.bstatus,
    267					1);
    268	else
    269		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BSTATUS,
    270				(uint8_t *)&hdcp->auth.msg.hdcp1.bstatus,
    271				sizeof(hdcp->auth.msg.hdcp1.bstatus));
    272	return status;
    273}
    274
    275enum mod_hdcp_status mod_hdcp_read_r0p(struct mod_hdcp *hdcp)
    276{
    277	return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_RI_R0,
    278			(uint8_t *)&hdcp->auth.msg.hdcp1.r0p,
    279			sizeof(hdcp->auth.msg.hdcp1.r0p));
    280}
    281
    282/* special case, reading repeatedly at the same address, don't use read() */
    283enum mod_hdcp_status mod_hdcp_read_ksvlist(struct mod_hdcp *hdcp)
    284{
    285	enum mod_hdcp_status status;
    286
    287	if (is_dp_hdcp(hdcp))
    288		status = read_repeatedly(hdcp, MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO,
    289				hdcp->auth.msg.hdcp1.ksvlist,
    290				hdcp->auth.msg.hdcp1.ksvlist_size,
    291				KSV_READ_SIZE);
    292	else
    293		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO,
    294				(uint8_t *)&hdcp->auth.msg.hdcp1.ksvlist,
    295				hdcp->auth.msg.hdcp1.ksvlist_size);
    296	return status;
    297}
    298
    299enum mod_hdcp_status mod_hdcp_read_vp(struct mod_hdcp *hdcp)
    300{
    301	enum mod_hdcp_status status;
    302
    303	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_0,
    304			&hdcp->auth.msg.hdcp1.vp[0], 4);
    305	if (status != MOD_HDCP_STATUS_SUCCESS)
    306		goto out;
    307
    308	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_1,
    309			&hdcp->auth.msg.hdcp1.vp[4], 4);
    310	if (status != MOD_HDCP_STATUS_SUCCESS)
    311		goto out;
    312
    313	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_2,
    314			&hdcp->auth.msg.hdcp1.vp[8], 4);
    315	if (status != MOD_HDCP_STATUS_SUCCESS)
    316		goto out;
    317
    318	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_3,
    319			&hdcp->auth.msg.hdcp1.vp[12], 4);
    320	if (status != MOD_HDCP_STATUS_SUCCESS)
    321		goto out;
    322
    323	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_4,
    324			&hdcp->auth.msg.hdcp1.vp[16], 4);
    325out:
    326	return status;
    327}
    328
    329enum mod_hdcp_status mod_hdcp_read_binfo(struct mod_hdcp *hdcp)
    330{
    331	enum mod_hdcp_status status;
    332
    333	if (is_dp_hdcp(hdcp))
    334		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BINFO,
    335				(uint8_t *)&hdcp->auth.msg.hdcp1.binfo_dp,
    336				sizeof(hdcp->auth.msg.hdcp1.binfo_dp));
    337	else
    338		status = MOD_HDCP_STATUS_INVALID_OPERATION;
    339
    340	return status;
    341}
    342
    343enum mod_hdcp_status mod_hdcp_write_aksv(struct mod_hdcp *hdcp)
    344{
    345	return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKSV,
    346			hdcp->auth.msg.hdcp1.aksv,
    347			sizeof(hdcp->auth.msg.hdcp1.aksv));
    348}
    349
    350enum mod_hdcp_status mod_hdcp_write_ainfo(struct mod_hdcp *hdcp)
    351{
    352	return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AINFO,
    353			&hdcp->auth.msg.hdcp1.ainfo,
    354			sizeof(hdcp->auth.msg.hdcp1.ainfo));
    355}
    356
    357enum mod_hdcp_status mod_hdcp_write_an(struct mod_hdcp *hdcp)
    358{
    359	return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AN,
    360			hdcp->auth.msg.hdcp1.an,
    361			sizeof(hdcp->auth.msg.hdcp1.an));
    362}
    363
    364enum mod_hdcp_status mod_hdcp_read_hdcp2version(struct mod_hdcp *hdcp)
    365{
    366	enum mod_hdcp_status status;
    367
    368	if (is_dp_hdcp(hdcp))
    369		status = MOD_HDCP_STATUS_INVALID_OPERATION;
    370	else
    371		status = read(hdcp, MOD_HDCP_MESSAGE_ID_HDCP2VERSION,
    372				&hdcp->auth.msg.hdcp2.hdcp2version_hdmi,
    373				sizeof(hdcp->auth.msg.hdcp2.hdcp2version_hdmi));
    374
    375	return status;
    376}
    377
    378enum mod_hdcp_status mod_hdcp_read_rxcaps(struct mod_hdcp *hdcp)
    379{
    380	enum mod_hdcp_status status;
    381
    382	if (!is_dp_hdcp(hdcp))
    383		status = MOD_HDCP_STATUS_INVALID_OPERATION;
    384	else
    385		status = read(hdcp, MOD_HDCP_MESSAGE_ID_RX_CAPS,
    386				hdcp->auth.msg.hdcp2.rxcaps_dp,
    387				sizeof(hdcp->auth.msg.hdcp2.rxcaps_dp));
    388
    389	return status;
    390}
    391
    392enum mod_hdcp_status mod_hdcp_read_rxstatus(struct mod_hdcp *hdcp)
    393{
    394	enum mod_hdcp_status status;
    395
    396	if (is_dp_hdcp(hdcp)) {
    397		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_RXSTATUS,
    398				&hdcp->auth.msg.hdcp2.rxstatus_dp,
    399				1);
    400	} else {
    401		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_RXSTATUS,
    402					(uint8_t *)&hdcp->auth.msg.hdcp2.rxstatus,
    403					sizeof(hdcp->auth.msg.hdcp2.rxstatus));
    404	}
    405	return status;
    406}
    407
    408enum mod_hdcp_status mod_hdcp_read_ake_cert(struct mod_hdcp *hdcp)
    409{
    410	enum mod_hdcp_status status;
    411
    412	if (is_dp_hdcp(hdcp)) {
    413		hdcp->auth.msg.hdcp2.ake_cert[0] = HDCP_2_2_AKE_SEND_CERT;
    414		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT,
    415				hdcp->auth.msg.hdcp2.ake_cert+1,
    416				sizeof(hdcp->auth.msg.hdcp2.ake_cert)-1);
    417
    418	} else {
    419		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT,
    420					hdcp->auth.msg.hdcp2.ake_cert,
    421					sizeof(hdcp->auth.msg.hdcp2.ake_cert));
    422	}
    423	return status;
    424}
    425
    426enum mod_hdcp_status mod_hdcp_read_h_prime(struct mod_hdcp *hdcp)
    427{
    428	enum mod_hdcp_status status;
    429
    430	if (is_dp_hdcp(hdcp)) {
    431		hdcp->auth.msg.hdcp2.ake_h_prime[0] = HDCP_2_2_AKE_SEND_HPRIME;
    432		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME,
    433				hdcp->auth.msg.hdcp2.ake_h_prime+1,
    434				sizeof(hdcp->auth.msg.hdcp2.ake_h_prime)-1);
    435
    436	} else {
    437		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME,
    438				hdcp->auth.msg.hdcp2.ake_h_prime,
    439				sizeof(hdcp->auth.msg.hdcp2.ake_h_prime));
    440	}
    441	return status;
    442}
    443
    444enum mod_hdcp_status mod_hdcp_read_pairing_info(struct mod_hdcp *hdcp)
    445{
    446	enum mod_hdcp_status status;
    447
    448	if (is_dp_hdcp(hdcp)) {
    449		hdcp->auth.msg.hdcp2.ake_pairing_info[0] = HDCP_2_2_AKE_SEND_PAIRING_INFO;
    450		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO,
    451				hdcp->auth.msg.hdcp2.ake_pairing_info+1,
    452				sizeof(hdcp->auth.msg.hdcp2.ake_pairing_info)-1);
    453
    454	} else {
    455		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO,
    456				hdcp->auth.msg.hdcp2.ake_pairing_info,
    457				sizeof(hdcp->auth.msg.hdcp2.ake_pairing_info));
    458	}
    459	return status;
    460}
    461
    462enum mod_hdcp_status mod_hdcp_read_l_prime(struct mod_hdcp *hdcp)
    463{
    464	enum mod_hdcp_status status;
    465
    466	if (is_dp_hdcp(hdcp)) {
    467		hdcp->auth.msg.hdcp2.lc_l_prime[0] = HDCP_2_2_LC_SEND_LPRIME;
    468		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME,
    469				hdcp->auth.msg.hdcp2.lc_l_prime+1,
    470				sizeof(hdcp->auth.msg.hdcp2.lc_l_prime)-1);
    471
    472	} else {
    473		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME,
    474				hdcp->auth.msg.hdcp2.lc_l_prime,
    475				sizeof(hdcp->auth.msg.hdcp2.lc_l_prime));
    476	}
    477	return status;
    478}
    479
    480enum mod_hdcp_status mod_hdcp_read_rx_id_list(struct mod_hdcp *hdcp)
    481{
    482	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    483
    484	if (is_dp_hdcp(hdcp)) {
    485		uint32_t device_count = 0;
    486		uint32_t rx_id_list_size = 0;
    487		uint32_t bytes_read = 0;
    488
    489		hdcp->auth.msg.hdcp2.rx_id_list[0] = HDCP_2_2_REP_SEND_RECVID_LIST;
    490		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST,
    491						hdcp->auth.msg.hdcp2.rx_id_list+1,
    492						HDCP_MAX_AUX_TRANSACTION_SIZE);
    493		if (status == MOD_HDCP_STATUS_SUCCESS) {
    494			bytes_read = HDCP_MAX_AUX_TRANSACTION_SIZE;
    495			device_count = HDCP_2_2_DEV_COUNT_LO(hdcp->auth.msg.hdcp2.rx_id_list[2]) +
    496					(HDCP_2_2_DEV_COUNT_HI(hdcp->auth.msg.hdcp2.rx_id_list[1]) << 4);
    497			rx_id_list_size = MIN((21 + 5 * device_count),
    498					(sizeof(hdcp->auth.msg.hdcp2.rx_id_list) - 1));
    499			status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST_PART2,
    500					hdcp->auth.msg.hdcp2.rx_id_list + 1 + bytes_read,
    501					(rx_id_list_size - 1) / HDCP_MAX_AUX_TRANSACTION_SIZE * HDCP_MAX_AUX_TRANSACTION_SIZE);
    502		}
    503	} else {
    504		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST,
    505				hdcp->auth.msg.hdcp2.rx_id_list,
    506				hdcp->auth.msg.hdcp2.rx_id_list_size);
    507	}
    508	return status;
    509}
    510
    511enum mod_hdcp_status mod_hdcp_read_stream_ready(struct mod_hdcp *hdcp)
    512{
    513	enum mod_hdcp_status status;
    514
    515	if (is_dp_hdcp(hdcp)) {
    516		hdcp->auth.msg.hdcp2.repeater_auth_stream_ready[0] = HDCP_2_2_REP_STREAM_READY;
    517		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY,
    518				hdcp->auth.msg.hdcp2.repeater_auth_stream_ready+1,
    519				sizeof(hdcp->auth.msg.hdcp2.repeater_auth_stream_ready)-1);
    520
    521	} else {
    522		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY,
    523				hdcp->auth.msg.hdcp2.repeater_auth_stream_ready,
    524				sizeof(hdcp->auth.msg.hdcp2.repeater_auth_stream_ready));
    525	}
    526	return status;
    527}
    528
    529enum mod_hdcp_status mod_hdcp_write_ake_init(struct mod_hdcp *hdcp)
    530{
    531	enum mod_hdcp_status status;
    532
    533	if (is_dp_hdcp(hdcp))
    534		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_INIT,
    535				hdcp->auth.msg.hdcp2.ake_init+1,
    536				sizeof(hdcp->auth.msg.hdcp2.ake_init)-1);
    537	else
    538		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_INIT,
    539					hdcp->auth.msg.hdcp2.ake_init,
    540					sizeof(hdcp->auth.msg.hdcp2.ake_init));
    541	return status;
    542}
    543
    544enum mod_hdcp_status mod_hdcp_write_no_stored_km(struct mod_hdcp *hdcp)
    545{
    546	enum mod_hdcp_status status;
    547
    548	if (is_dp_hdcp(hdcp))
    549		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM,
    550				hdcp->auth.msg.hdcp2.ake_no_stored_km+1,
    551				sizeof(hdcp->auth.msg.hdcp2.ake_no_stored_km)-1);
    552	else
    553		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM,
    554			hdcp->auth.msg.hdcp2.ake_no_stored_km,
    555			sizeof(hdcp->auth.msg.hdcp2.ake_no_stored_km));
    556	return status;
    557}
    558
    559enum mod_hdcp_status mod_hdcp_write_stored_km(struct mod_hdcp *hdcp)
    560{
    561	enum mod_hdcp_status status;
    562
    563	if (is_dp_hdcp(hdcp))
    564		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM,
    565				hdcp->auth.msg.hdcp2.ake_stored_km+1,
    566				sizeof(hdcp->auth.msg.hdcp2.ake_stored_km)-1);
    567	else
    568		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM,
    569				hdcp->auth.msg.hdcp2.ake_stored_km,
    570				sizeof(hdcp->auth.msg.hdcp2.ake_stored_km));
    571	return status;
    572}
    573
    574enum mod_hdcp_status mod_hdcp_write_lc_init(struct mod_hdcp *hdcp)
    575{
    576	enum mod_hdcp_status status;
    577
    578	if (is_dp_hdcp(hdcp))
    579		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_LC_INIT,
    580				hdcp->auth.msg.hdcp2.lc_init+1,
    581				sizeof(hdcp->auth.msg.hdcp2.lc_init)-1);
    582	else
    583		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_LC_INIT,
    584				hdcp->auth.msg.hdcp2.lc_init,
    585				sizeof(hdcp->auth.msg.hdcp2.lc_init));
    586	return status;
    587}
    588
    589enum mod_hdcp_status mod_hdcp_write_eks(struct mod_hdcp *hdcp)
    590{
    591	enum mod_hdcp_status status;
    592
    593	if (is_dp_hdcp(hdcp))
    594		status = write(hdcp,
    595				MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS,
    596				hdcp->auth.msg.hdcp2.ske_eks+1,
    597				sizeof(hdcp->auth.msg.hdcp2.ske_eks)-1);
    598	else
    599		status = write(hdcp,
    600			MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS,
    601			hdcp->auth.msg.hdcp2.ske_eks,
    602			sizeof(hdcp->auth.msg.hdcp2.ske_eks));
    603	return status;
    604}
    605
    606enum mod_hdcp_status mod_hdcp_write_repeater_auth_ack(struct mod_hdcp *hdcp)
    607{
    608	enum mod_hdcp_status status;
    609
    610	if (is_dp_hdcp(hdcp))
    611		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK,
    612				hdcp->auth.msg.hdcp2.repeater_auth_ack+1,
    613				sizeof(hdcp->auth.msg.hdcp2.repeater_auth_ack)-1);
    614	else
    615		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK,
    616				hdcp->auth.msg.hdcp2.repeater_auth_ack,
    617				sizeof(hdcp->auth.msg.hdcp2.repeater_auth_ack));
    618	return status;
    619}
    620
    621enum mod_hdcp_status mod_hdcp_write_stream_manage(struct mod_hdcp *hdcp)
    622{
    623	enum mod_hdcp_status status;
    624
    625	if (is_dp_hdcp(hdcp))
    626		status = write(hdcp,
    627				MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE,
    628				hdcp->auth.msg.hdcp2.repeater_auth_stream_manage+1,
    629				hdcp->auth.msg.hdcp2.stream_manage_size-1);
    630	else
    631		status = write(hdcp,
    632				MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE,
    633				hdcp->auth.msg.hdcp2.repeater_auth_stream_manage,
    634				hdcp->auth.msg.hdcp2.stream_manage_size);
    635	return status;
    636}
    637
    638enum mod_hdcp_status mod_hdcp_write_content_type(struct mod_hdcp *hdcp)
    639{
    640	enum mod_hdcp_status status;
    641
    642	if (is_dp_hdcp(hdcp))
    643		status = write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE,
    644				hdcp->auth.msg.hdcp2.content_stream_type_dp+1,
    645				sizeof(hdcp->auth.msg.hdcp2.content_stream_type_dp)-1);
    646	else
    647		status = MOD_HDCP_STATUS_INVALID_OPERATION;
    648	return status;
    649}
    650
    651enum mod_hdcp_status mod_hdcp_clear_cp_irq_status(struct mod_hdcp *hdcp)
    652{
    653	uint8_t clear_cp_irq_bit = DP_CP_IRQ;
    654	uint32_t size = 1;
    655
    656	if (is_dp_hdcp(hdcp)) {
    657		uint32_t cp_irq_addrs = (hdcp->connection.link.dp.rev >= 0x14)
    658				? DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0:DP_DEVICE_SERVICE_IRQ_VECTOR;
    659		return hdcp->config.ddc.funcs.write_dpcd(hdcp->config.ddc.handle, cp_irq_addrs,
    660				&clear_cp_irq_bit, size) ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE;
    661	}
    662
    663	return MOD_HDCP_STATUS_INVALID_OPERATION;
    664}