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