avrcp_controller.c (1f94eaa583cb83b60ae97415c1dc9216d345c560) avrcp_controller.c (2ac1dc76c9f11326904f6859da1d08322744e245)
1/*
2 * Copyright (C) 2016 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright

--- 79 unchanged lines hidden (view full) ---

88 }
89}
90
91static int avrcp_controller_supports_browsing(uint16_t controller_supported_features){
92 return controller_supported_features & AVRCP_FEATURE_MASK_BROWSING;
93}
94
95static void avrcp_controller_emit_supported_events(avrcp_connection_t * connection){
1/*
2 * Copyright (C) 2016 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright

--- 79 unchanged lines hidden (view full) ---

88 }
89}
90
91static int avrcp_controller_supports_browsing(uint16_t controller_supported_features){
92 return controller_supported_features & AVRCP_FEATURE_MASK_BROWSING;
93}
94
95static void avrcp_controller_emit_supported_events(avrcp_connection_t * connection){
96 uint8_t event_id;
97 uint8_t offset;
98 uint8_t event[9];
99 uint8_t ctype = (uint8_t) AVRCP_CTYPE_RESPONSE_CHANGED_STABLE;
96 uint8_t ctype = (uint8_t) AVRCP_CTYPE_RESPONSE_CHANGED_STABLE;
97 uint8_t event_id;
100
101 for (event_id = (uint8_t) AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED; event_id < (uint8_t) AVRCP_NOTIFICATION_EVENT_MAX_VALUE; event_id++){
102 if ( (connection->remote_supported_notifications & (1<<event_id)) == 0){
103 continue;
104 }
98
99 for (event_id = (uint8_t) AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED; event_id < (uint8_t) AVRCP_NOTIFICATION_EVENT_MAX_VALUE; event_id++){
100 if ( (connection->remote_supported_notifications & (1<<event_id)) == 0){
101 continue;
102 }
105 offset = 0;
106 event[offset++] = HCI_EVENT_AVRCP_META;
107 event[offset++] = sizeof(event) - 2;
108 event[offset++] = AVRCP_SUBEVENT_GET_CAPABILITY_EVENT_ID;
109 little_endian_store_16(event, offset, connection->avrcp_cid);
110 offset += 2;
111 event[offset++] = ctype;
112 event[offset++] = 0;
113 event[offset++] = event_id;
114 (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, offset);
103 uint8_t event[8];
104 uint8_t pos = 0;
105 event[pos++] = HCI_EVENT_AVRCP_META;
106 event[pos++] = sizeof(event) - 2;
107 event[pos++] = AVRCP_SUBEVENT_GET_CAPABILITY_EVENT_ID;
108 little_endian_store_16(event, pos, connection->avrcp_cid);
109 pos += 2;
110 event[pos++] = ctype;
111 event[pos++] = 0;
112 event[pos++] = event_id;
113 UNUSED(pos);
114 (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
115 }
116
115 }
116
117 offset = 0;
118 event[offset++] = HCI_EVENT_AVRCP_META;
119 event[offset++] = sizeof(event) - 2;
120 event[offset++] = AVRCP_SUBEVENT_GET_CAPABILITY_EVENT_ID_DONE;
121 little_endian_store_16(event, offset, connection->avrcp_cid);
122 offset += 2;
123 event[offset++] = ctype;
124 event[offset++] = 0;
117 uint8_t event[7];
118 uint8_t pos = 0;
119 event[pos++] = HCI_EVENT_AVRCP_META;
120 event[pos++] = sizeof(event) - 2;
121 event[pos++] = AVRCP_SUBEVENT_GET_CAPABILITY_EVENT_ID_DONE;
122 little_endian_store_16(event, pos, connection->avrcp_cid);
123 pos += 2;
124 event[pos++] = ctype;
125 event[pos++] = 0;
126 UNUSED(pos);
125 (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
126}
127
128static void avrcp_controller_emit_notification_for_event_id(uint16_t avrcp_cid, avrcp_notification_event_id_t event_id,
129 avrcp_command_type_t ctype, const uint8_t *payload,
130 uint16_t size) {
131 switch (event_id){
132 case AVRCP_NOTIFICATION_EVENT_PLAYBACK_POS_CHANGED:{

--- 517 unchanged lines hidden (view full) ---

650 connection->cmd_operands[4] = 0;
651 big_endian_store_16(connection->cmd_operands, 5, 1); // parameter length
652 connection->cmd_operands[7] = capability_id; // capability ID
653 connection->cmd_operands_length = 8;
654 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
655}
656
657static uint8_t avrcp_controller_register_notification(avrcp_connection_t * connection, avrcp_notification_event_id_t event_id){
127 (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
128}
129
130static void avrcp_controller_emit_notification_for_event_id(uint16_t avrcp_cid, avrcp_notification_event_id_t event_id,
131 avrcp_command_type_t ctype, const uint8_t *payload,
132 uint16_t size) {
133 switch (event_id){
134 case AVRCP_NOTIFICATION_EVENT_PLAYBACK_POS_CHANGED:{

--- 517 unchanged lines hidden (view full) ---

652 connection->cmd_operands[4] = 0;
653 big_endian_store_16(connection->cmd_operands, 5, 1); // parameter length
654 connection->cmd_operands[7] = capability_id; // capability ID
655 connection->cmd_operands_length = 8;
656 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
657}
658
659static uint8_t avrcp_controller_register_notification(avrcp_connection_t * connection, avrcp_notification_event_id_t event_id){
658 if ( (connection->remote_supported_notifications & (1 << event_id)) == 0){
660 if (connection->remote_supported_notifications_queried && (connection->remote_supported_notifications & (1 << event_id)) == 0){
659 return ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE;
660 }
661 if ( (connection->notifications_to_deregister & (1 << event_id)) != 0){
662 return ERROR_CODE_COMMAND_DISALLOWED;
663 }
664 if ( (connection->notifications_enabled & (1 << event_id)) != 0){
665 return ERROR_CODE_SUCCESS;
666 }
667 if ( (connection->notifications_to_register & (1 << event_id)) != 0){
668 return ERROR_CODE_SUCCESS;
669 }
670
671 connection->notifications_to_register |= (1 << event_id);
661 return ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE;
662 }
663 if ( (connection->notifications_to_deregister & (1 << event_id)) != 0){
664 return ERROR_CODE_COMMAND_DISALLOWED;
665 }
666 if ( (connection->notifications_enabled & (1 << event_id)) != 0){
667 return ERROR_CODE_SUCCESS;
668 }
669 if ( (connection->notifications_to_register & (1 << event_id)) != 0){
670 return ERROR_CODE_SUCCESS;
671 }
672
673 connection->notifications_to_register |= (1 << event_id);
674
675 if (!connection->remote_supported_notifications_queried){
676 connection->remote_supported_notifications_suppress_emit_result = true;
677 avrcp_controller_get_capabilities_for_connection(connection, AVRCP_CAPABILITY_ID_EVENT);
678 return ERROR_CODE_SUCCESS;
679 }
672 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
673 return ERROR_CODE_SUCCESS;
674}
675
676static uint8_t avrcp_controller_request_abort_continuation(avrcp_connection_t * connection){
677 connection->state = AVCTP_W2_SEND_COMMAND;
678 connection->transaction_id = avrcp_controller_get_next_transaction_label(connection);
679 connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;

--- 315 unchanged lines hidden (view full) ---

995 (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, offset);
996 break;
997
998 case AVRCP_CAPABILITY_ID_EVENT:
999 for (i = 0; (i < capability_count) && ((size - pos) >= 1); i++){
1000 uint8_t event_id = packet[pos++];
1001 connection->remote_supported_notifications |= (1 << event_id);
1002 }
680 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
681 return ERROR_CODE_SUCCESS;
682}
683
684static uint8_t avrcp_controller_request_abort_continuation(avrcp_connection_t * connection){
685 connection->state = AVCTP_W2_SEND_COMMAND;
686 connection->transaction_id = avrcp_controller_get_next_transaction_label(connection);
687 connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;

--- 315 unchanged lines hidden (view full) ---

1003 (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, offset);
1004 break;
1005
1006 case AVRCP_CAPABILITY_ID_EVENT:
1007 for (i = 0; (i < capability_count) && ((size - pos) >= 1); i++){
1008 uint8_t event_id = packet[pos++];
1009 connection->remote_supported_notifications |= (1 << event_id);
1010 }
1011 if (connection->remote_supported_notifications_suppress_emit_result){
1012 connection->remote_supported_notifications_suppress_emit_result = false;
1013 break;
1014 }
1003 avrcp_controller_emit_supported_events(connection);
1004 break;
1005
1006 default:
1007 // ignore
1008 break;
1009 }
1010 break;

--- 384 unchanged lines hidden (view full) ---

1395 if (!connection){
1396 log_error("avrcp_get_capabilities: could not find a connection.");
1397 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
1398 }
1399 if (connection->state != AVCTP_CONNECTION_OPENED){
1400 return ERROR_CODE_COMMAND_DISALLOWED;
1401 }
1402
1015 avrcp_controller_emit_supported_events(connection);
1016 break;
1017
1018 default:
1019 // ignore
1020 break;
1021 }
1022 break;

--- 384 unchanged lines hidden (view full) ---

1407 if (!connection){
1408 log_error("avrcp_get_capabilities: could not find a connection.");
1409 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
1410 }
1411 if (connection->state != AVCTP_CONNECTION_OPENED){
1412 return ERROR_CODE_COMMAND_DISALLOWED;
1413 }
1414
1403 avrcp_controller_get_capabilities_for_connection(connection, AVRCP_CAPABILITY_ID_EVENT);
1415 if (!connection->remote_supported_notifications_queried){
1416 connection->remote_supported_notifications_queried = true;
1417 avrcp_controller_get_capabilities_for_connection(connection, AVRCP_CAPABILITY_ID_EVENT);
1418 return ERROR_CODE_SUCCESS;
1419 }
1420
1421 avrcp_controller_emit_supported_events(connection);
1404 return ERROR_CODE_SUCCESS;
1405}
1406
1407uint8_t avrcp_controller_get_play_status(uint16_t avrcp_cid){
1408 avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_CONTROLLER, avrcp_cid);
1409 if (!connection){
1410 log_error("avrcp_get_play_status: could not find a connection.");
1411 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;

--- 336 unchanged lines hidden ---
1422 return ERROR_CODE_SUCCESS;
1423}
1424
1425uint8_t avrcp_controller_get_play_status(uint16_t avrcp_cid){
1426 avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_CONTROLLER, avrcp_cid);
1427 if (!connection){
1428 log_error("avrcp_get_play_status: could not find a connection.");
1429 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;

--- 336 unchanged lines hidden ---