From 73fba53895554e4b0e03749402e05b550ed1528f Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Fri, 2 Feb 2018 17:09:11 +0100 Subject: [PATCH] avrcp browsing controller: search --- src/classic/avrcp.h | 6 +++ src/classic/avrcp_browsing_controller.c | 68 ++++++++++++++++++++++++- src/classic/avrcp_browsing_controller.h | 11 ++++ src/classic/avrcp_controller.h | 1 - 4 files changed, 84 insertions(+), 2 deletions(-) diff --git a/src/classic/avrcp.h b/src/classic/avrcp.h index 0e1d819d4..5688ec4bf 100644 --- a/src/classic/avrcp.h +++ b/src/classic/avrcp.h @@ -131,6 +131,7 @@ typedef enum { AVRCP_PDU_ID_GET_FOLDER_ITEMS = 0x71, AVRCP_PDU_ID_CHANGE_PATH = 0x72, AVRCP_PDU_ID_PLAY_ITEM = 0x74, + AVRCP_PDU_ID_SEARCH = 0x80, AVRCP_PDU_ID_UNDEFINED = 0xFF } avrcp_pdu_id_t; @@ -324,6 +325,11 @@ typedef struct { uint16_t uid_counter; uint8_t folder_uid[8]; + // search str + uint16_t search_str_len; + uint8_t search_str[20]; + uint8_t search; + // fragmentation uint8_t fragmented; avrcp_pdu_id_t fragmented_pdu_id; diff --git a/src/classic/avrcp_browsing_controller.c b/src/classic/avrcp_browsing_controller.c index d9f435260..f01edddd3 100644 --- a/src/classic/avrcp_browsing_controller.c +++ b/src/classic/avrcp_browsing_controller.c @@ -318,6 +318,30 @@ static int avrcp_browsing_controller_send_change_path_cmd(uint16_t cid, avrcp_br return l2cap_send(cid, command, pos); } +static int avrcp_browsing_controller_send_search_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){ + uint8_t command[100]; + int pos = 0; + // transport header + // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier) + command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0; + // Profile IDentifier (PID) + command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8; + command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF; + command[pos++] = AVRCP_PDU_ID_SEARCH; + + big_endian_store_16(command, pos, 4 + connection->search_str_len); + pos += 2; + + big_endian_store_16(command, pos, 0x006A); + pos += 2; + big_endian_store_16(command, pos, connection->search_str_len); + pos += 2; + + memcpy(command+pos,connection->search_str, connection->search_str_len); + pos += connection->search_str_len; + return l2cap_send(cid, command, pos); +} + static int avrcp_browsing_controller_send_set_browsed_player_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){ uint8_t command[100]; int pos = 0; @@ -383,6 +407,12 @@ static void avrcp_browsing_controller_handle_can_send_now(avrcp_browsing_connect avrcp_browsing_controller_send_change_path_cmd(connection->l2cap_browsing_cid, connection); break; } + if (connection->search){ + connection->state = AVCTP_W2_RECEIVE_RESPONSE; + connection->search = 0; + avrcp_browsing_controller_send_search_cmd(connection->l2cap_browsing_cid, connection); + break; + } break; default: return; @@ -487,7 +517,7 @@ static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16 break; } case AVRCP_PDU_ID_GET_FOLDER_ITEMS:{ - printf("AVRCP_PDU_ID_GET_FOLDER_ITEMS \n"); + printf("AVRCP_PDU_ID_GET_FOLDER_ITEMS\n"); // send UID counter with done if (!browsing_connection->fragmented){ browsing_connection->num_items = big_endian_read_16(packet, pos); @@ -527,6 +557,11 @@ static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16 } break; } + case AVRCP_PDU_ID_SEARCH:{ + uint32_t num_items = big_endian_read_32(packet, pos); + printf("TODO: send as event, search found %d items\n", num_items); + break; + } default: break; } @@ -761,4 +796,35 @@ uint8_t avrcp_browsing_controller_go_up_one_level(uint16_t avrcp_browsing_cid){ uint8_t avrcp_browsing_controller_go_down_one_level(uint16_t avrcp_browsing_cid, uint8_t * folder_uid){ return avrcp_browsing_controller_change_path(avrcp_browsing_cid, 1, folder_uid); +} + +uint8_t avrcp_browsing_controller_search(uint16_t avrcp_browsing_cid, uint16_t search_str_len, char * search_str){ + avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context); + if (!avrcp_connection){ + log_error("avrcp_browsing_controller_change_path: could not find a connection."); + return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; + } + + avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection; + + if (!connection || connection->state != AVCTP_CONNECTION_OPENED){ + log_error("avrcp_browsing_controller_change_path: connection in wrong state."); + return ERROR_CODE_COMMAND_DISALLOWED; + } + + if (!connection->browsed_player_id){ + log_error("avrcp_browsing_controller_change_path: no browsed player set."); + return ERROR_CODE_COMMAND_DISALLOWED; + } + if (!search_str || search_str_len == 0){ + return AVRCP_BROWSING_ERROR_CODE_INVALID_COMMAND; + } + + connection->search = 1; + + connection->search_str_len = btstack_min(search_str_len, sizeof(connection->search_str)-1); + memset(connection->search_str, 0, sizeof(connection->search_str)); + memcpy(connection->search_str, search_str, connection->search_str_len); + avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid); + return ERROR_CODE_SUCCESS; } \ No newline at end of file diff --git a/src/classic/avrcp_browsing_controller.h b/src/classic/avrcp_browsing_controller.h index 20275cd8a..9c530502f 100644 --- a/src/classic/avrcp_browsing_controller.h +++ b/src/classic/avrcp_browsing_controller.h @@ -202,6 +202,17 @@ uint8_t avrcp_browsing_controller_set_addressed_player(uint16_t avrcp_browsing_c uint8_t avrcp_browsing_controller_change_path(uint16_t avrcp_browsing_cid, uint8_t direction, uint8_t * folder_uid); uint8_t avrcp_browsing_controller_go_up_one_level(uint16_t avrcp_browsing_cid); uint8_t avrcp_browsing_controller_go_down_one_level(uint16_t avrcp_browsing_cid, uint8_t * folder_uid); + + +/** + * @brief Searches are performed from the current folder in the Browsed Players virtual filesystem. The search applies to the current folder and all folders below that. + * @param avrcp_browsing_cid + * @param search_str_len + * @param search_str + * @return status + **/ +uint8_t avrcp_browsing_controller_search(uint16_t avrcp_browsing_cid, uint16_t search_str_len, char * search_str); + /* API_END */ #if defined __cplusplus diff --git a/src/classic/avrcp_controller.h b/src/classic/avrcp_controller.h index 8b68ee40b..166782ced 100644 --- a/src/classic/avrcp_controller.h +++ b/src/classic/avrcp_controller.h @@ -294,7 +294,6 @@ uint8_t avrcp_controller_set_repeat_mode(uint16_t avrcp_cid, avrcp_repeat_mode_t * @return status **/ uint8_t avrcp_controller_play_item(uint16_t avrcp_cid, avrcp_browsing_scope_t scope, uint8_t * uid, uint16_t uid_counter); - /* API_END */ // Used by AVRCP controller and AVRCP browsing controller