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 | |
35 | enum 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 | |
80 | static 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 | |
115 | static 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 | |
150 | static 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 | |
185 | static 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: buf + data_offset, buf_len: 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 | |
209 | static 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 | |
246 | enum mod_hdcp_status mod_hdcp_read_bksv(struct mod_hdcp *hdcp) |
247 | { |
248 | return read(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_READ_BKSV, |
249 | buf: hdcp->auth.msg.hdcp1.bksv, |
250 | buf_len: sizeof(hdcp->auth.msg.hdcp1.bksv)); |
251 | } |
252 | |
253 | enum mod_hdcp_status mod_hdcp_read_bcaps(struct mod_hdcp *hdcp) |
254 | { |
255 | return read(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_READ_BCAPS, |
256 | buf: &hdcp->auth.msg.hdcp1.bcaps, |
257 | buf_len: sizeof(hdcp->auth.msg.hdcp1.bcaps)); |
258 | } |
259 | |
260 | enum 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, msg_id: MOD_HDCP_MESSAGE_ID_READ_BSTATUS, |
266 | buf: (uint8_t *)&hdcp->auth.msg.hdcp1.bstatus, |
267 | buf_len: 1); |
268 | else |
269 | status = read(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_READ_BSTATUS, |
270 | buf: (uint8_t *)&hdcp->auth.msg.hdcp1.bstatus, |
271 | buf_len: sizeof(hdcp->auth.msg.hdcp1.bstatus)); |
272 | return status; |
273 | } |
274 | |
275 | enum mod_hdcp_status mod_hdcp_read_r0p(struct mod_hdcp *hdcp) |
276 | { |
277 | return read(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_READ_RI_R0, |
278 | buf: (uint8_t *)&hdcp->auth.msg.hdcp1.r0p, |
279 | buf_len: sizeof(hdcp->auth.msg.hdcp1.r0p)); |
280 | } |
281 | |
282 | /* special case, reading repeatedly at the same address, don't use read() */ |
283 | enum 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, msg_id: MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO, |
289 | buf: hdcp->auth.msg.hdcp1.ksvlist, |
290 | buf_len: hdcp->auth.msg.hdcp1.ksvlist_size, |
291 | KSV_READ_SIZE); |
292 | else |
293 | status = read(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO, |
294 | buf: (uint8_t *)&hdcp->auth.msg.hdcp1.ksvlist, |
295 | buf_len: hdcp->auth.msg.hdcp1.ksvlist_size); |
296 | return status; |
297 | } |
298 | |
299 | enum mod_hdcp_status mod_hdcp_read_vp(struct mod_hdcp *hdcp) |
300 | { |
301 | enum mod_hdcp_status status; |
302 | |
303 | status = read(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_READ_VH_0, |
304 | buf: &hdcp->auth.msg.hdcp1.vp[0], buf_len: 4); |
305 | if (status != MOD_HDCP_STATUS_SUCCESS) |
306 | goto out; |
307 | |
308 | status = read(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_READ_VH_1, |
309 | buf: &hdcp->auth.msg.hdcp1.vp[4], buf_len: 4); |
310 | if (status != MOD_HDCP_STATUS_SUCCESS) |
311 | goto out; |
312 | |
313 | status = read(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_READ_VH_2, |
314 | buf: &hdcp->auth.msg.hdcp1.vp[8], buf_len: 4); |
315 | if (status != MOD_HDCP_STATUS_SUCCESS) |
316 | goto out; |
317 | |
318 | status = read(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_READ_VH_3, |
319 | buf: &hdcp->auth.msg.hdcp1.vp[12], buf_len: 4); |
320 | if (status != MOD_HDCP_STATUS_SUCCESS) |
321 | goto out; |
322 | |
323 | status = read(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_READ_VH_4, |
324 | buf: &hdcp->auth.msg.hdcp1.vp[16], buf_len: 4); |
325 | out: |
326 | return status; |
327 | } |
328 | |
329 | enum 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, msg_id: MOD_HDCP_MESSAGE_ID_READ_BINFO, |
335 | buf: (uint8_t *)&hdcp->auth.msg.hdcp1.binfo_dp, |
336 | buf_len: sizeof(hdcp->auth.msg.hdcp1.binfo_dp)); |
337 | else |
338 | status = MOD_HDCP_STATUS_INVALID_OPERATION; |
339 | |
340 | return status; |
341 | } |
342 | |
343 | enum mod_hdcp_status mod_hdcp_write_aksv(struct mod_hdcp *hdcp) |
344 | { |
345 | return write(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_WRITE_AKSV, |
346 | buf: hdcp->auth.msg.hdcp1.aksv, |
347 | buf_len: sizeof(hdcp->auth.msg.hdcp1.aksv)); |
348 | } |
349 | |
350 | enum mod_hdcp_status mod_hdcp_write_ainfo(struct mod_hdcp *hdcp) |
351 | { |
352 | return write(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_WRITE_AINFO, |
353 | buf: &hdcp->auth.msg.hdcp1.ainfo, |
354 | buf_len: sizeof(hdcp->auth.msg.hdcp1.ainfo)); |
355 | } |
356 | |
357 | enum mod_hdcp_status mod_hdcp_write_an(struct mod_hdcp *hdcp) |
358 | { |
359 | return write(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_WRITE_AN, |
360 | buf: hdcp->auth.msg.hdcp1.an, |
361 | buf_len: sizeof(hdcp->auth.msg.hdcp1.an)); |
362 | } |
363 | |
364 | enum 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, msg_id: MOD_HDCP_MESSAGE_ID_HDCP2VERSION, |
372 | buf: &hdcp->auth.msg.hdcp2.hdcp2version_hdmi, |
373 | buf_len: sizeof(hdcp->auth.msg.hdcp2.hdcp2version_hdmi)); |
374 | |
375 | return status; |
376 | } |
377 | |
378 | enum 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, msg_id: MOD_HDCP_MESSAGE_ID_RX_CAPS, |
386 | buf: hdcp->auth.msg.hdcp2.rxcaps_dp, |
387 | buf_len: sizeof(hdcp->auth.msg.hdcp2.rxcaps_dp)); |
388 | |
389 | return status; |
390 | } |
391 | |
392 | enum 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, msg_id: MOD_HDCP_MESSAGE_ID_READ_RXSTATUS, |
398 | buf: &hdcp->auth.msg.hdcp2.rxstatus_dp, |
399 | buf_len: 1); |
400 | } else { |
401 | status = read(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_READ_RXSTATUS, |
402 | buf: (uint8_t *)&hdcp->auth.msg.hdcp2.rxstatus, |
403 | buf_len: sizeof(hdcp->auth.msg.hdcp2.rxstatus)); |
404 | } |
405 | return status; |
406 | } |
407 | |
408 | enum 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, msg_id: MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT, |
415 | buf: hdcp->auth.msg.hdcp2.ake_cert+1, |
416 | buf_len: sizeof(hdcp->auth.msg.hdcp2.ake_cert)-1); |
417 | |
418 | } else { |
419 | status = read(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_CERT, |
420 | buf: hdcp->auth.msg.hdcp2.ake_cert, |
421 | buf_len: sizeof(hdcp->auth.msg.hdcp2.ake_cert)); |
422 | } |
423 | return status; |
424 | } |
425 | |
426 | enum 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, msg_id: MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME, |
433 | buf: hdcp->auth.msg.hdcp2.ake_h_prime+1, |
434 | buf_len: sizeof(hdcp->auth.msg.hdcp2.ake_h_prime)-1); |
435 | |
436 | } else { |
437 | status = read(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME, |
438 | buf: hdcp->auth.msg.hdcp2.ake_h_prime, |
439 | buf_len: sizeof(hdcp->auth.msg.hdcp2.ake_h_prime)); |
440 | } |
441 | return status; |
442 | } |
443 | |
444 | enum 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, msg_id: MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO, |
451 | buf: hdcp->auth.msg.hdcp2.ake_pairing_info+1, |
452 | buf_len: sizeof(hdcp->auth.msg.hdcp2.ake_pairing_info)-1); |
453 | |
454 | } else { |
455 | status = read(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO, |
456 | buf: hdcp->auth.msg.hdcp2.ake_pairing_info, |
457 | buf_len: sizeof(hdcp->auth.msg.hdcp2.ake_pairing_info)); |
458 | } |
459 | return status; |
460 | } |
461 | |
462 | enum 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, msg_id: MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME, |
469 | buf: hdcp->auth.msg.hdcp2.lc_l_prime+1, |
470 | buf_len: sizeof(hdcp->auth.msg.hdcp2.lc_l_prime)-1); |
471 | |
472 | } else { |
473 | status = read(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME, |
474 | buf: hdcp->auth.msg.hdcp2.lc_l_prime, |
475 | buf_len: sizeof(hdcp->auth.msg.hdcp2.lc_l_prime)); |
476 | } |
477 | return status; |
478 | } |
479 | |
480 | enum 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, msg_id: MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST, |
491 | buf: 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, msg_id: MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST_PART2, |
500 | buf: hdcp->auth.msg.hdcp2.rx_id_list + 1 + bytes_read, |
501 | buf_len: (rx_id_list_size - 1) / HDCP_MAX_AUX_TRANSACTION_SIZE * HDCP_MAX_AUX_TRANSACTION_SIZE); |
502 | } |
503 | } else { |
504 | status = read(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST, |
505 | buf: hdcp->auth.msg.hdcp2.rx_id_list, |
506 | buf_len: hdcp->auth.msg.hdcp2.rx_id_list_size); |
507 | } |
508 | return status; |
509 | } |
510 | |
511 | enum 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, msg_id: MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY, |
518 | buf: hdcp->auth.msg.hdcp2.repeater_auth_stream_ready+1, |
519 | buf_len: sizeof(hdcp->auth.msg.hdcp2.repeater_auth_stream_ready)-1); |
520 | |
521 | } else { |
522 | status = read(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY, |
523 | buf: hdcp->auth.msg.hdcp2.repeater_auth_stream_ready, |
524 | buf_len: sizeof(hdcp->auth.msg.hdcp2.repeater_auth_stream_ready)); |
525 | } |
526 | return status; |
527 | } |
528 | |
529 | enum 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, msg_id: MOD_HDCP_MESSAGE_ID_WRITE_AKE_INIT, |
535 | buf: hdcp->auth.msg.hdcp2.ake_init+1, |
536 | buf_len: sizeof(hdcp->auth.msg.hdcp2.ake_init)-1); |
537 | else |
538 | status = write(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_WRITE_AKE_INIT, |
539 | buf: hdcp->auth.msg.hdcp2.ake_init, |
540 | buf_len: sizeof(hdcp->auth.msg.hdcp2.ake_init)); |
541 | return status; |
542 | } |
543 | |
544 | enum 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, msg_id: MOD_HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM, |
550 | buf: hdcp->auth.msg.hdcp2.ake_no_stored_km+1, |
551 | buf_len: sizeof(hdcp->auth.msg.hdcp2.ake_no_stored_km)-1); |
552 | else |
553 | status = write(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM, |
554 | buf: hdcp->auth.msg.hdcp2.ake_no_stored_km, |
555 | buf_len: sizeof(hdcp->auth.msg.hdcp2.ake_no_stored_km)); |
556 | return status; |
557 | } |
558 | |
559 | enum 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, msg_id: MOD_HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM, |
565 | buf: hdcp->auth.msg.hdcp2.ake_stored_km+1, |
566 | buf_len: sizeof(hdcp->auth.msg.hdcp2.ake_stored_km)-1); |
567 | else |
568 | status = write(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM, |
569 | buf: hdcp->auth.msg.hdcp2.ake_stored_km, |
570 | buf_len: sizeof(hdcp->auth.msg.hdcp2.ake_stored_km)); |
571 | return status; |
572 | } |
573 | |
574 | enum 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, msg_id: MOD_HDCP_MESSAGE_ID_WRITE_LC_INIT, |
580 | buf: hdcp->auth.msg.hdcp2.lc_init+1, |
581 | buf_len: sizeof(hdcp->auth.msg.hdcp2.lc_init)-1); |
582 | else |
583 | status = write(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_WRITE_LC_INIT, |
584 | buf: hdcp->auth.msg.hdcp2.lc_init, |
585 | buf_len: sizeof(hdcp->auth.msg.hdcp2.lc_init)); |
586 | return status; |
587 | } |
588 | |
589 | enum 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 | msg_id: MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS, |
596 | buf: hdcp->auth.msg.hdcp2.ske_eks+1, |
597 | buf_len: sizeof(hdcp->auth.msg.hdcp2.ske_eks)-1); |
598 | else |
599 | status = write(hdcp, |
600 | msg_id: MOD_HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS, |
601 | buf: hdcp->auth.msg.hdcp2.ske_eks, |
602 | buf_len: sizeof(hdcp->auth.msg.hdcp2.ske_eks)); |
603 | return status; |
604 | } |
605 | |
606 | enum 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, msg_id: MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK, |
612 | buf: hdcp->auth.msg.hdcp2.repeater_auth_ack+1, |
613 | buf_len: sizeof(hdcp->auth.msg.hdcp2.repeater_auth_ack)-1); |
614 | else |
615 | status = write(hdcp, msg_id: MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK, |
616 | buf: hdcp->auth.msg.hdcp2.repeater_auth_ack, |
617 | buf_len: sizeof(hdcp->auth.msg.hdcp2.repeater_auth_ack)); |
618 | return status; |
619 | } |
620 | |
621 | enum 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 | msg_id: MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE, |
628 | buf: hdcp->auth.msg.hdcp2.repeater_auth_stream_manage+1, |
629 | buf_len: hdcp->auth.msg.hdcp2.stream_manage_size-1); |
630 | else |
631 | status = write(hdcp, |
632 | msg_id: MOD_HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE, |
633 | buf: hdcp->auth.msg.hdcp2.repeater_auth_stream_manage, |
634 | buf_len: hdcp->auth.msg.hdcp2.stream_manage_size); |
635 | return status; |
636 | } |
637 | |
638 | enum 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, msg_id: MOD_HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE, |
644 | buf: hdcp->auth.msg.hdcp2.content_stream_type_dp+1, |
645 | buf_len: sizeof(hdcp->auth.msg.hdcp2.content_stream_type_dp)-1); |
646 | else |
647 | status = MOD_HDCP_STATUS_INVALID_OPERATION; |
648 | return status; |
649 | } |
650 | |
651 | enum 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 | } |
665 | |