0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include "hdcp.h"
0027
0028 static void push_error_status(struct mod_hdcp *hdcp,
0029 enum mod_hdcp_status status)
0030 {
0031 struct mod_hdcp_trace *trace = &hdcp->connection.trace;
0032
0033 if (trace->error_count < MAX_NUM_OF_ERROR_TRACE) {
0034 trace->errors[trace->error_count].status = status;
0035 trace->errors[trace->error_count].state_id = hdcp->state.id;
0036 trace->error_count++;
0037 HDCP_ERROR_TRACE(hdcp, status);
0038 }
0039
0040 if (is_hdcp1(hdcp)) {
0041 hdcp->connection.hdcp1_retry_count++;
0042 if (hdcp->connection.hdcp1_retry_count == MAX_NUM_OF_ATTEMPTS)
0043 hdcp->connection.link.adjust.hdcp1.disable = 1;
0044 } else if (is_hdcp2(hdcp)) {
0045 hdcp->connection.hdcp2_retry_count++;
0046 if (hdcp->connection.hdcp2_retry_count == MAX_NUM_OF_ATTEMPTS)
0047 hdcp->connection.link.adjust.hdcp2.disable = 1;
0048 }
0049 }
0050
0051 static uint8_t is_cp_desired_hdcp1(struct mod_hdcp *hdcp)
0052 {
0053 int i, is_auth_needed = 0;
0054
0055
0056
0057
0058 for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) {
0059 if (hdcp->displays[i].state != MOD_HDCP_DISPLAY_INACTIVE &&
0060 hdcp->displays[i].adjust.disable != MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION) {
0061 is_auth_needed = 1;
0062 break;
0063 }
0064 }
0065
0066 return is_auth_needed &&
0067 !hdcp->connection.link.adjust.hdcp1.disable &&
0068 !hdcp->connection.is_hdcp1_revoked;
0069 }
0070
0071 static uint8_t is_cp_desired_hdcp2(struct mod_hdcp *hdcp)
0072 {
0073 int i, is_auth_needed = 0;
0074
0075
0076
0077
0078 for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) {
0079 if (hdcp->displays[i].state != MOD_HDCP_DISPLAY_INACTIVE &&
0080 hdcp->displays[i].adjust.disable != MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION) {
0081 is_auth_needed = 1;
0082 break;
0083 }
0084 }
0085
0086 return is_auth_needed &&
0087 !hdcp->connection.link.adjust.hdcp2.disable &&
0088 !hdcp->connection.is_hdcp2_revoked;
0089 }
0090
0091 static enum mod_hdcp_status execution(struct mod_hdcp *hdcp,
0092 struct mod_hdcp_event_context *event_ctx,
0093 union mod_hdcp_transition_input *input)
0094 {
0095 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
0096
0097 if (is_in_initialized_state(hdcp)) {
0098 if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
0099 event_ctx->unexpected_event = 1;
0100 goto out;
0101 }
0102
0103 memset(input, 0, sizeof(union mod_hdcp_transition_input));
0104 } else if (is_in_cp_not_desired_state(hdcp)) {
0105 if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
0106 event_ctx->unexpected_event = 1;
0107 goto out;
0108 }
0109 } else if (is_in_hdcp1_states(hdcp)) {
0110 status = mod_hdcp_hdcp1_execution(hdcp, event_ctx, &input->hdcp1);
0111 } else if (is_in_hdcp1_dp_states(hdcp)) {
0112 status = mod_hdcp_hdcp1_dp_execution(hdcp,
0113 event_ctx, &input->hdcp1);
0114 } else if (is_in_hdcp2_states(hdcp)) {
0115 status = mod_hdcp_hdcp2_execution(hdcp, event_ctx, &input->hdcp2);
0116 } else if (is_in_hdcp2_dp_states(hdcp)) {
0117 status = mod_hdcp_hdcp2_dp_execution(hdcp,
0118 event_ctx, &input->hdcp2);
0119 } else {
0120 event_ctx->unexpected_event = 1;
0121 goto out;
0122 }
0123 out:
0124 return status;
0125 }
0126
0127 static enum mod_hdcp_status transition(struct mod_hdcp *hdcp,
0128 struct mod_hdcp_event_context *event_ctx,
0129 union mod_hdcp_transition_input *input,
0130 struct mod_hdcp_output *output)
0131 {
0132 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
0133
0134 if (event_ctx->unexpected_event)
0135 goto out;
0136
0137 if (is_in_initialized_state(hdcp)) {
0138 if (is_dp_hdcp(hdcp))
0139 if (is_cp_desired_hdcp2(hdcp)) {
0140 callback_in_ms(0, output);
0141 set_state_id(hdcp, output, D2_A0_DETERMINE_RX_HDCP_CAPABLE);
0142 } else if (is_cp_desired_hdcp1(hdcp)) {
0143 callback_in_ms(0, output);
0144 set_state_id(hdcp, output, D1_A0_DETERMINE_RX_HDCP_CAPABLE);
0145 } else {
0146 callback_in_ms(0, output);
0147 set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED);
0148 set_auth_complete(hdcp, output);
0149 }
0150 else if (is_hdmi_dvi_sl_hdcp(hdcp))
0151 if (is_cp_desired_hdcp2(hdcp)) {
0152 callback_in_ms(0, output);
0153 set_state_id(hdcp, output, H2_A0_KNOWN_HDCP2_CAPABLE_RX);
0154 } else if (is_cp_desired_hdcp1(hdcp)) {
0155 callback_in_ms(0, output);
0156 set_state_id(hdcp, output, H1_A0_WAIT_FOR_ACTIVE_RX);
0157 } else {
0158 callback_in_ms(0, output);
0159 set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED);
0160 set_auth_complete(hdcp, output);
0161 }
0162 else {
0163 callback_in_ms(0, output);
0164 set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED);
0165 set_auth_complete(hdcp, output);
0166 }
0167 } else if (is_in_cp_not_desired_state(hdcp)) {
0168 increment_stay_counter(hdcp);
0169 } else if (is_in_hdcp1_states(hdcp)) {
0170 status = mod_hdcp_hdcp1_transition(hdcp,
0171 event_ctx, &input->hdcp1, output);
0172 } else if (is_in_hdcp1_dp_states(hdcp)) {
0173 status = mod_hdcp_hdcp1_dp_transition(hdcp,
0174 event_ctx, &input->hdcp1, output);
0175 } else if (is_in_hdcp2_states(hdcp)) {
0176 status = mod_hdcp_hdcp2_transition(hdcp,
0177 event_ctx, &input->hdcp2, output);
0178 } else if (is_in_hdcp2_dp_states(hdcp)) {
0179 status = mod_hdcp_hdcp2_dp_transition(hdcp,
0180 event_ctx, &input->hdcp2, output);
0181 } else {
0182 status = MOD_HDCP_STATUS_INVALID_STATE;
0183 }
0184 out:
0185 return status;
0186 }
0187
0188 static enum mod_hdcp_status reset_authentication(struct mod_hdcp *hdcp,
0189 struct mod_hdcp_output *output)
0190 {
0191 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
0192
0193 if (is_hdcp1(hdcp)) {
0194 if (hdcp->auth.trans_input.hdcp1.create_session != UNKNOWN) {
0195
0196
0197
0198 mod_hdcp_hdcp1_destroy_session(hdcp);
0199
0200 }
0201
0202 HDCP_TOP_RESET_AUTH_TRACE(hdcp);
0203 memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication));
0204 memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state));
0205 set_state_id(hdcp, output, HDCP_INITIALIZED);
0206 } else if (is_hdcp2(hdcp)) {
0207 if (hdcp->auth.trans_input.hdcp2.create_session == PASS) {
0208 status = mod_hdcp_hdcp2_destroy_session(hdcp);
0209 if (status != MOD_HDCP_STATUS_SUCCESS) {
0210 output->callback_needed = 0;
0211 output->watchdog_timer_needed = 0;
0212 goto out;
0213 }
0214 }
0215
0216 HDCP_TOP_RESET_AUTH_TRACE(hdcp);
0217 memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication));
0218 memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state));
0219 set_state_id(hdcp, output, HDCP_INITIALIZED);
0220 } else if (is_in_cp_not_desired_state(hdcp)) {
0221 HDCP_TOP_RESET_AUTH_TRACE(hdcp);
0222 memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication));
0223 memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state));
0224 set_state_id(hdcp, output, HDCP_INITIALIZED);
0225 }
0226
0227 out:
0228
0229 output->watchdog_timer_stop = 1;
0230 output->callback_stop = 1;
0231 return status;
0232 }
0233
0234 static enum mod_hdcp_status reset_connection(struct mod_hdcp *hdcp,
0235 struct mod_hdcp_output *output)
0236 {
0237 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
0238
0239 memset(output, 0, sizeof(struct mod_hdcp_output));
0240
0241 status = reset_authentication(hdcp, output);
0242 if (status != MOD_HDCP_STATUS_SUCCESS)
0243 goto out;
0244
0245 if (current_state(hdcp) != HDCP_UNINITIALIZED) {
0246 HDCP_TOP_RESET_CONN_TRACE(hdcp);
0247 set_state_id(hdcp, output, HDCP_UNINITIALIZED);
0248 }
0249 memset(&hdcp->connection, 0, sizeof(hdcp->connection));
0250 out:
0251 return status;
0252 }
0253
0254 static enum mod_hdcp_status update_display_adjustments(struct mod_hdcp *hdcp,
0255 struct mod_hdcp_display *display,
0256 struct mod_hdcp_display_adjustment *adj)
0257 {
0258 enum mod_hdcp_status status = MOD_HDCP_STATUS_NOT_IMPLEMENTED;
0259
0260 if (is_in_authenticated_states(hdcp) &&
0261 is_dp_mst_hdcp(hdcp) &&
0262 display->adjust.disable == true &&
0263 adj->disable == false) {
0264 display->adjust.disable = false;
0265 if (is_hdcp1(hdcp))
0266 status = mod_hdcp_hdcp1_enable_dp_stream_encryption(hdcp);
0267 else if (is_hdcp2(hdcp))
0268 status = mod_hdcp_hdcp2_enable_dp_stream_encryption(hdcp);
0269
0270 if (status != MOD_HDCP_STATUS_SUCCESS)
0271 display->adjust.disable = true;
0272 }
0273
0274 if (status == MOD_HDCP_STATUS_SUCCESS &&
0275 memcmp(adj, &display->adjust,
0276 sizeof(struct mod_hdcp_display_adjustment)) != 0)
0277 status = MOD_HDCP_STATUS_NOT_IMPLEMENTED;
0278
0279 return status;
0280 }
0281
0282
0283
0284 size_t mod_hdcp_get_memory_size(void)
0285 {
0286 return sizeof(struct mod_hdcp);
0287 }
0288
0289 enum mod_hdcp_status mod_hdcp_setup(struct mod_hdcp *hdcp,
0290 struct mod_hdcp_config *config)
0291 {
0292 struct mod_hdcp_output output;
0293 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
0294
0295 memset(&output, 0, sizeof(output));
0296 hdcp->config = *config;
0297 HDCP_TOP_INTERFACE_TRACE(hdcp);
0298 status = reset_connection(hdcp, &output);
0299 if (status != MOD_HDCP_STATUS_SUCCESS)
0300 push_error_status(hdcp, status);
0301 return status;
0302 }
0303
0304 enum mod_hdcp_status mod_hdcp_teardown(struct mod_hdcp *hdcp)
0305 {
0306 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
0307 struct mod_hdcp_output output;
0308
0309 HDCP_TOP_INTERFACE_TRACE(hdcp);
0310 memset(&output, 0, sizeof(output));
0311 status = reset_connection(hdcp, &output);
0312 if (status == MOD_HDCP_STATUS_SUCCESS)
0313 memset(hdcp, 0, sizeof(struct mod_hdcp));
0314 else
0315 push_error_status(hdcp, status);
0316 return status;
0317 }
0318
0319 enum mod_hdcp_status mod_hdcp_add_display(struct mod_hdcp *hdcp,
0320 struct mod_hdcp_link *link, struct mod_hdcp_display *display,
0321 struct mod_hdcp_output *output)
0322 {
0323 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
0324 struct mod_hdcp_display *display_container = NULL;
0325
0326 HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, display->index);
0327 memset(output, 0, sizeof(struct mod_hdcp_output));
0328
0329
0330 if (display->state != MOD_HDCP_DISPLAY_ACTIVE) {
0331 status = MOD_HDCP_STATUS_SUCCESS;
0332 goto out;
0333 }
0334
0335
0336 if (get_active_display_at_index(hdcp, display->index)) {
0337 status = MOD_HDCP_STATUS_SUCCESS;
0338 goto out;
0339 }
0340
0341
0342 display_container = get_empty_display_container(hdcp);
0343 if (!display_container) {
0344 status = MOD_HDCP_STATUS_DISPLAY_OUT_OF_BOUND;
0345 goto out;
0346 }
0347
0348
0349 status = reset_authentication(hdcp, output);
0350 if (status != MOD_HDCP_STATUS_SUCCESS)
0351 goto out;
0352
0353
0354 reset_retry_counts(hdcp);
0355
0356
0357 memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace));
0358
0359
0360 hdcp->connection.link = *link;
0361 *display_container = *display;
0362 status = mod_hdcp_add_display_to_topology(hdcp, display_container);
0363
0364 if (status != MOD_HDCP_STATUS_SUCCESS)
0365 goto out;
0366
0367
0368 if (current_state(hdcp) != HDCP_INITIALIZED)
0369 set_state_id(hdcp, output, HDCP_INITIALIZED);
0370 callback_in_ms(hdcp->connection.link.adjust.auth_delay * 1000, output);
0371 out:
0372 if (status != MOD_HDCP_STATUS_SUCCESS)
0373 push_error_status(hdcp, status);
0374
0375 return status;
0376 }
0377
0378 enum mod_hdcp_status mod_hdcp_remove_display(struct mod_hdcp *hdcp,
0379 uint8_t index, struct mod_hdcp_output *output)
0380 {
0381 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
0382 struct mod_hdcp_display *display = NULL;
0383
0384 HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, index);
0385 memset(output, 0, sizeof(struct mod_hdcp_output));
0386
0387
0388 display = get_active_display_at_index(hdcp, index);
0389 if (!display) {
0390 status = MOD_HDCP_STATUS_SUCCESS;
0391 goto out;
0392 }
0393
0394
0395 status = reset_authentication(hdcp, output);
0396 if (status != MOD_HDCP_STATUS_SUCCESS)
0397 goto out;
0398
0399
0400 reset_retry_counts(hdcp);
0401
0402
0403 memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace));
0404
0405
0406 status = mod_hdcp_remove_display_from_topology(hdcp, index);
0407 if (status != MOD_HDCP_STATUS_SUCCESS)
0408 goto out;
0409 memset(display, 0, sizeof(struct mod_hdcp_display));
0410
0411
0412 if (current_state(hdcp) != HDCP_UNINITIALIZED)
0413 callback_in_ms(hdcp->connection.link.adjust.auth_delay * 1000,
0414 output);
0415 out:
0416 if (status != MOD_HDCP_STATUS_SUCCESS)
0417 push_error_status(hdcp, status);
0418 return status;
0419 }
0420
0421 enum mod_hdcp_status mod_hdcp_update_display(struct mod_hdcp *hdcp,
0422 uint8_t index,
0423 struct mod_hdcp_link_adjustment *link_adjust,
0424 struct mod_hdcp_display_adjustment *display_adjust,
0425 struct mod_hdcp_output *output)
0426 {
0427 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
0428 struct mod_hdcp_display *display = NULL;
0429
0430 HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, index);
0431 memset(output, 0, sizeof(struct mod_hdcp_output));
0432
0433
0434 display = get_active_display_at_index(hdcp, index);
0435 if (!display) {
0436 status = MOD_HDCP_STATUS_DISPLAY_NOT_FOUND;
0437 goto out;
0438 }
0439
0440
0441 if (memcmp(link_adjust, &hdcp->connection.link.adjust,
0442 sizeof(struct mod_hdcp_link_adjustment)) == 0 &&
0443 memcmp(display_adjust, &display->adjust,
0444 sizeof(struct mod_hdcp_display_adjustment)) == 0) {
0445 status = MOD_HDCP_STATUS_SUCCESS;
0446 goto out;
0447 }
0448
0449 if (memcmp(link_adjust, &hdcp->connection.link.adjust,
0450 sizeof(struct mod_hdcp_link_adjustment)) == 0 &&
0451 memcmp(display_adjust, &display->adjust,
0452 sizeof(struct mod_hdcp_display_adjustment)) != 0) {
0453 status = update_display_adjustments(hdcp, display, display_adjust);
0454 if (status != MOD_HDCP_STATUS_NOT_IMPLEMENTED)
0455 goto out;
0456 }
0457
0458
0459 status = reset_authentication(hdcp, output);
0460 if (status != MOD_HDCP_STATUS_SUCCESS)
0461 goto out;
0462
0463
0464 reset_retry_counts(hdcp);
0465
0466
0467 memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace));
0468
0469
0470 hdcp->connection.link.adjust = *link_adjust;
0471 display->adjust = *display_adjust;
0472
0473
0474 if (current_state(hdcp) != HDCP_UNINITIALIZED)
0475
0476 callback_in_ms(100, output);
0477
0478 out:
0479 if (status != MOD_HDCP_STATUS_SUCCESS)
0480 push_error_status(hdcp, status);
0481 return status;
0482 }
0483
0484 enum mod_hdcp_status mod_hdcp_query_display(struct mod_hdcp *hdcp,
0485 uint8_t index, struct mod_hdcp_display_query *query)
0486 {
0487 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
0488 struct mod_hdcp_display *display = NULL;
0489
0490
0491 display = get_active_display_at_index(hdcp, index);
0492 if (!display) {
0493 status = MOD_HDCP_STATUS_DISPLAY_NOT_FOUND;
0494 goto out;
0495 }
0496
0497
0498 query->link = &hdcp->connection.link;
0499 query->display = display;
0500 query->trace = &hdcp->connection.trace;
0501 query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
0502
0503 if (is_display_encryption_enabled(display)) {
0504 if (is_hdcp1(hdcp)) {
0505 query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP1_ON;
0506 } else if (is_hdcp2(hdcp)) {
0507 if (query->link->adjust.hdcp2.force_type == MOD_HDCP_FORCE_TYPE_0)
0508 query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE0_ON;
0509 else if (query->link->adjust.hdcp2.force_type == MOD_HDCP_FORCE_TYPE_1)
0510 query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE1_ON;
0511 else
0512 query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP2_ON;
0513 }
0514 } else {
0515 query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
0516 }
0517
0518 out:
0519 return status;
0520 }
0521
0522 enum mod_hdcp_status mod_hdcp_reset_connection(struct mod_hdcp *hdcp,
0523 struct mod_hdcp_output *output)
0524 {
0525 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
0526
0527 HDCP_TOP_INTERFACE_TRACE(hdcp);
0528 status = reset_connection(hdcp, output);
0529 if (status != MOD_HDCP_STATUS_SUCCESS)
0530 push_error_status(hdcp, status);
0531
0532 return status;
0533 }
0534
0535 enum mod_hdcp_status mod_hdcp_process_event(struct mod_hdcp *hdcp,
0536 enum mod_hdcp_event event, struct mod_hdcp_output *output)
0537 {
0538 enum mod_hdcp_status exec_status, trans_status, reset_status, status;
0539 struct mod_hdcp_event_context event_ctx;
0540
0541 HDCP_EVENT_TRACE(hdcp, event);
0542 memset(output, 0, sizeof(struct mod_hdcp_output));
0543 memset(&event_ctx, 0, sizeof(struct mod_hdcp_event_context));
0544 event_ctx.event = event;
0545
0546
0547 exec_status = execution(hdcp, &event_ctx, &hdcp->auth.trans_input);
0548 trans_status = transition(
0549 hdcp, &event_ctx, &hdcp->auth.trans_input, output);
0550 if (trans_status == MOD_HDCP_STATUS_SUCCESS) {
0551 status = MOD_HDCP_STATUS_SUCCESS;
0552 } else if (exec_status == MOD_HDCP_STATUS_SUCCESS) {
0553 status = MOD_HDCP_STATUS_INTERNAL_POLICY_FAILURE;
0554 push_error_status(hdcp, status);
0555 } else {
0556 status = exec_status;
0557 push_error_status(hdcp, status);
0558 }
0559
0560
0561 if (trans_status == MOD_HDCP_STATUS_RESET_NEEDED) {
0562 mod_hdcp_log_ddc_trace(hdcp);
0563 reset_status = reset_authentication(hdcp, output);
0564 if (reset_status != MOD_HDCP_STATUS_SUCCESS)
0565 push_error_status(hdcp, reset_status);
0566 }
0567
0568
0569 if (event_ctx.event == MOD_HDCP_EVENT_CPIRQ) {
0570 status = mod_hdcp_clear_cp_irq_status(hdcp);
0571 if (status != MOD_HDCP_STATUS_SUCCESS)
0572 push_error_status(hdcp, status);
0573 }
0574
0575 return status;
0576 }
0577
0578 enum mod_hdcp_operation_mode mod_hdcp_signal_type_to_operation_mode(
0579 enum signal_type signal)
0580 {
0581 enum mod_hdcp_operation_mode mode = MOD_HDCP_MODE_OFF;
0582
0583 switch (signal) {
0584 case SIGNAL_TYPE_DVI_SINGLE_LINK:
0585 case SIGNAL_TYPE_HDMI_TYPE_A:
0586 mode = MOD_HDCP_MODE_DEFAULT;
0587 break;
0588 case SIGNAL_TYPE_EDP:
0589 case SIGNAL_TYPE_DISPLAY_PORT:
0590 case SIGNAL_TYPE_DISPLAY_PORT_MST:
0591 mode = MOD_HDCP_MODE_DP;
0592 break;
0593 default:
0594 break;
0595 }
0596
0597 return mode;
0598 }