avrcp_controller.c (b28a301e4cb410ef409cc073c79f2d0b866d3387) avrcp_controller.c (8b631c133ad1de27895b59950abcd1500898b447)
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

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

1251
1252 // trigger pending notification reqistrations
1253 if ((connection->state == AVCTP_CONNECTION_OPENED) && connection->controller_notifications_to_register){
1254 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
1255 }
1256}
1257
1258static void avrcp_controller_handle_can_send_now(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

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

1251
1252 // trigger pending notification reqistrations
1253 if ((connection->state == AVCTP_CONNECTION_OPENED) && connection->controller_notifications_to_register){
1254 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
1255 }
1256}
1257
1258static void avrcp_controller_handle_can_send_now(avrcp_connection_t * connection){
1259 // identifier (9) + num attributes (1) + attributes (4 * num attributes)
1260 uint8_t get_element_attributes_command[9+8*((AVRCP_MEDIA_ATTR_RESERVED-AVRCP_MEDIA_ATTR_TITLE) + 1)];
1261 uint16_t pos;
1262 uint16_t num_attributes_index;
1263 uint8_t i;
1264
1259 switch (connection->state){
1260 case AVCTP_W2_SEND_PRESS_COMMAND:
1261 avrcp_send_cmd_with_avctp_fragmentation(connection);
1262 connection->state = AVCTP_W2_RECEIVE_PRESS_RESPONSE;
1263 return;
1264
1265 case AVCTP_W2_SEND_RELEASE_COMMAND:
1266 avrcp_send_cmd_with_avctp_fragmentation(connection);

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

1271 avrcp_send_cmd_with_avctp_fragmentation(connection);
1272 if (connection->data_offset < connection->data_len){
1273 // continue AVCTP fragmentation
1274 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
1275 return;
1276 }
1277 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
1278 return;
1265 switch (connection->state){
1266 case AVCTP_W2_SEND_PRESS_COMMAND:
1267 avrcp_send_cmd_with_avctp_fragmentation(connection);
1268 connection->state = AVCTP_W2_RECEIVE_PRESS_RESPONSE;
1269 return;
1270
1271 case AVCTP_W2_SEND_RELEASE_COMMAND:
1272 avrcp_send_cmd_with_avctp_fragmentation(connection);

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

1277 avrcp_send_cmd_with_avctp_fragmentation(connection);
1278 if (connection->data_offset < connection->data_len){
1279 // continue AVCTP fragmentation
1280 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
1281 return;
1282 }
1283 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
1284 return;
1285 case AVCTP_W2_SEND_GET_ELEMENT_ATTRIBUTES_REQUEST:
1286 // build command in local buffer
1287 pos = 0;
1288 connection->data = get_element_attributes_command;
1289 // write identifier
1290 memset(connection->data, 0, 8);
1291 pos += 8;
1292 num_attributes_index = pos;
1293 // If num_attributes is set to zero, all attribute information shall be returned,
1294 // and the AttributeID field is omitted
1295 connection->data[num_attributes_index] = 0;
1296 pos++;
1297 for (i = 0; i < AVRCP_MEDIA_ATTR_RESERVED-AVRCP_MEDIA_ATTR_TITLE; i++){
1298 if ((connection->controller_element_attributes & (1<<i)) != 0){
1299 // every attribute is 4 bytes long
1300 big_endian_store_32(connection->data, pos, AVRCP_MEDIA_ATTR_TITLE + i);
1301 pos += 4;
1302 connection->data[num_attributes_index]++;
1303 }
1304 }
1305
1306 // Parameter Length
1307 connection->data_len = pos;
1308
1309 log_info("AVCTP_W2_SEND_GET_ELEMENT_ATTRIBUTES_REQUEST, len %u", connection->data_len);
1310
1311 // send data - assume it will fit into one packet
1312 avrcp_send_cmd_with_avctp_fragmentation(connection);
1313 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
1314 return;
1279 default:
1280 break;
1281 }
1282
1283 // send register notification if queued,
1284 // avrcp_handle_l2cap_data_packet_for_signaling_connection will trigger next one
1285 if (connection->controller_notifications_to_register != 0){
1286 uint8_t event_id;

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

1590 }
1591
1592 if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
1593
1594 if (num_attributes >= AVRCP_MEDIA_ATTR_RESERVED) {
1595 return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
1596 }
1597
1315 default:
1316 break;
1317 }
1318
1319 // send register notification if queued,
1320 // avrcp_handle_l2cap_data_packet_for_signaling_connection will trigger next one
1321 if (connection->controller_notifications_to_register != 0){
1322 uint8_t event_id;

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

1626 }
1627
1628 if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
1629
1630 if (num_attributes >= AVRCP_MEDIA_ATTR_RESERVED) {
1631 return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
1632 }
1633
1598 connection->state = AVCTP_W2_SEND_COMMAND;
1634 connection->state = AVCTP_W2_SEND_GET_ELEMENT_ATTRIBUTES_REQUEST;
1599 avrcp_controller_vendor_dependent_command_data_init(connection, AVRCP_CTYPE_STATUS, AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES, true);
1600
1635 avrcp_controller_vendor_dependent_command_data_init(connection, AVRCP_CTYPE_STATUS, AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES, true);
1636
1601 uint8_t pos = 0;
1602 // write 8 bytes value
1603 memset(connection->data, pos, 8); // identifier: PLAYING
1604 pos += 8;
1605
1606 uint8_t num_attributes_index = pos;
1607 pos++;
1608
1609 // If num_attributes is set to zero, all attribute information shall be returned,
1610 // and the AttributeID field is omitted
1611 connection->data[num_attributes_index] = 0;
1637 // collect element attributes
1612 uint8_t i;
1638 uint8_t i;
1639 uint16_t attributes_set = 0;
1613 for (i = 0; i < num_attributes; i++){
1614 // ignore invalid attribute ID and "get all attributes"
1615 if (AVRCP_MEDIA_ATTR_ALL < attributes[i] && attributes[i] < AVRCP_MEDIA_ATTR_RESERVED){
1640 for (i = 0; i < num_attributes; i++){
1641 // ignore invalid attribute ID and "get all attributes"
1642 if (AVRCP_MEDIA_ATTR_ALL < attributes[i] && attributes[i] < AVRCP_MEDIA_ATTR_RESERVED){
1616 // every attribute is 4 bytes long
1617 big_endian_store_32(connection->data, pos, attributes[i]);
1618 pos += 4;
1619 connection->data[num_attributes_index]++;
1643 attributes_set |= 1 << (attributes[i] - AVRCP_MEDIA_ATTR_TITLE);
1620 }
1621 }
1644 }
1645 }
1646 connection->controller_element_attributes = attributes_set;
1622
1647
1623 // Parameter Length
1624 connection->data_len = pos;
1625
1626 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
1627 return ERROR_CODE_SUCCESS;
1628}
1629
1630uint8_t avrcp_controller_get_now_playing_info(uint16_t avrcp_cid){
1631 return avrcp_controller_get_element_attributes(avrcp_cid, 0, NULL);
1632}
1633

--- 200 unchanged lines hidden ---
1648 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
1649 return ERROR_CODE_SUCCESS;
1650}
1651
1652uint8_t avrcp_controller_get_now_playing_info(uint16_t avrcp_cid){
1653 return avrcp_controller_get_element_attributes(avrcp_cid, 0, NULL);
1654}
1655

--- 200 unchanged lines hidden ---