avrcp: use l2cap cid instead of handle

This commit is contained in:
Milanka Ringwald 2017-06-07 22:50:10 +02:00
parent 8a2c6c7c4b
commit b193c45e22
5 changed files with 285 additions and 278 deletions

View File

@ -1453,26 +1453,26 @@ typedef uint8_t sm_key_t[16];
/** AVRCP Subevent */ /** AVRCP Subevent */
/** /**
* @format 1H12B * @format 11BH2
* @param subevent_code * @param subevent_code
* @param con_handle
* @param status 0 == OK * @param status 0 == OK
* @param local_cid
* @param bd_addr * @param bd_addr
* @param con_handle
* @param avrcp_cid
*/ */
#define AVRCP_SUBEVENT_CONNECTION_ESTABLISHED 0x01 #define AVRCP_SUBEVENT_CONNECTION_ESTABLISHED 0x01
/** /**
* @format 1H * @format 12
* @param subevent_code * @param subevent_code
* @param con_handle * @param avrcp_cid
*/ */
#define AVRCP_SUBEVENT_CONNECTION_RELEASED 0x02 #define AVRCP_SUBEVENT_CONNECTION_RELEASED 0x02
/** /**
* @format 1H1114JVJVJVJV * @format 121114JVJVJVJV
* @param subevent_code * @param subevent_code
* @param con_handle * @param avrcp_cid
* @param status * @param status
* @param track * @param track
* @param total_tracks * @param total_tracks
@ -1489,9 +1489,9 @@ typedef uint8_t sm_key_t[16];
#define AVRCP_SUBEVENT_NOW_PLAYING_INFO 0x03 #define AVRCP_SUBEVENT_NOW_PLAYING_INFO 0x03
/** /**
* @format 1H111 * @format 12111
* @param subevent_code * @param subevent_code
* @param con_handle * @param avrcp_cid
* @param status * @param status
* @param repeat_mode * @param repeat_mode
* @param shuffle_mode * @param shuffle_mode
@ -1499,9 +1499,9 @@ typedef uint8_t sm_key_t[16];
#define AVRCP_SUBEVENT_SHUFFLE_AND_REPEAT_MODE 0x04 #define AVRCP_SUBEVENT_SHUFFLE_AND_REPEAT_MODE 0x04
/** /**
* @format 1H1441 * @format 121441
* @param subevent_code * @param subevent_code
* @param con_handle * @param avrcp_cid
* @param status * @param status
* @param song_length * @param song_length
* @param song_position * @param song_position
@ -1510,88 +1510,88 @@ typedef uint8_t sm_key_t[16];
#define AVRCP_SUBEVENT_PLAY_STATUS 0x05 #define AVRCP_SUBEVENT_PLAY_STATUS 0x05
/** /**
* @format 1H11 * @format 1211
* @param subevent_code * @param subevent_code
* @param con_handle * @param avrcp_cid
* @param status * @param status
* @param playback_status * @param playback_status
*/ */
#define AVRCP_SUBEVENT_NOTIFICATION_PLAYBACK_STATUS_CHANGED 0x06 #define AVRCP_SUBEVENT_NOTIFICATION_PLAYBACK_STATUS_CHANGED 0x06
/** /**
* @format 1H11 * @format 1211
* @param subevent_code * @param subevent_code
* @param con_handle * @param avrcp_cid
* @param status * @param status
* @param track_status * @param track_status
*/ */
#define AVRCP_SUBEVENT_NOTIFICATION_TRACK_CHANGED 0x07 #define AVRCP_SUBEVENT_NOTIFICATION_TRACK_CHANGED 0x07
/** /**
* @format 1H1 * @format 121
* @param subevent_code * @param subevent_code
* @param con_handle * @param avrcp_cid
* @param status * @param status
*/ */
#define AVRCP_SUBEVENT_NOTIFICATION_NOW_PLAYING_CONTENT_CHANGED 0x08 #define AVRCP_SUBEVENT_NOTIFICATION_NOW_PLAYING_CONTENT_CHANGED 0x08
/** /**
* @format 1H1 * @format 121
* @param subevent_code * @param subevent_code
* @param con_handle * @param avrcp_cid
* @param status * @param status
*/ */
#define AVRCP_SUBEVENT_NOTIFICATION_AVAILABLE_PLAYERS_CHANGED 0x09 #define AVRCP_SUBEVENT_NOTIFICATION_AVAILABLE_PLAYERS_CHANGED 0x09
/** /**
* @format 1H11 * @format 1211
* @param subevent_code * @param subevent_code
* @param con_handle * @param avrcp_cid
* @param status * @param status
* @param absolute_volume * @param absolute_volume
*/ */
#define AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED 0x0A #define AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED 0x0A
/** /**
* @format 1H11 * @format 1211
* @param subevent_code * @param subevent_code
* @param con_handle * @param avrcp_cid
* @param status * @param status
* @param absolute_volume * @param absolute_volume
*/ */
#define AVRCP_SUBEVENT_SET_ABSOLUTE_VOLUME_RESPONSE 0x0B #define AVRCP_SUBEVENT_SET_ABSOLUTE_VOLUME_RESPONSE 0x0B
/** /**
* @format 1H11 * @format 1211
* @param subevent_code * @param subevent_code
* @param con_handle * @param avrcp_cid
* @param status * @param status
* @param notification_id * @param notification_id
*/ */
#define AVRCP_SUBEVENT_ENABLE_NOTIFICATION_COMPLETE 0x0C #define AVRCP_SUBEVENT_ENABLE_NOTIFICATION_COMPLETE 0x0C
/** /**
* @format 1H11 * @format 1211
* @param subevent_code * @param subevent_code
* @param con_handle * @param avrcp_cid
* @param status * @param status
* @param operation_id * @param operation_id
*/ */
#define AVRCP_SUBEVENT_OPERATION_START 0x0D #define AVRCP_SUBEVENT_OPERATION_START 0x0D
/** /**
* @format 1H11 * @format 1211
* @param subevent_code * @param subevent_code
* @param con_handle * @param avrcp_cid
* @param status * @param status
* @param operation_id * @param operation_id
*/ */
#define AVRCP_SUBEVENT_OPERATION_COMPLETE 0x0E #define AVRCP_SUBEVENT_OPERATION_COMPLETE 0x0E
/** /**
* @format 1H1 * @format 121
* @param subevent_code * @param subevent_code
* @param con_handle * @param avrcp_cid
* @param status * @param status
*/ */
#define AVRCP_SUBEVENT_PLAYER_APPLICATION_VALUE_RESPONSE 0x0F #define AVRCP_SUBEVENT_PLAYER_APPLICATION_VALUE_RESPONSE 0x0F

View File

@ -4699,15 +4699,6 @@ static inline uint8_t a2dp_subevent_stream_released_get_local_seid(const uint8_t
return event[5]; return event[5];
} }
/**
* @brief Get field con_handle from event AVRCP_SUBEVENT_CONNECTION_ESTABLISHED
* @param event packet
* @return con_handle
* @note: btstack_type H
*/
static inline hci_con_handle_t avrcp_subevent_connection_established_get_con_handle(const uint8_t * event){
return little_endian_read_16(event, 3);
}
/** /**
* @brief Get field status from event AVRCP_SUBEVENT_CONNECTION_ESTABLISHED * @brief Get field status from event AVRCP_SUBEVENT_CONNECTION_ESTABLISHED
* @param event packet * @param event packet
@ -4715,16 +4706,7 @@ static inline hci_con_handle_t avrcp_subevent_connection_established_get_con_han
* @note: btstack_type 1 * @note: btstack_type 1
*/ */
static inline uint8_t avrcp_subevent_connection_established_get_status(const uint8_t * event){ static inline uint8_t avrcp_subevent_connection_established_get_status(const uint8_t * event){
return event[5]; return event[3];
}
/**
* @brief Get field local_cid from event AVRCP_SUBEVENT_CONNECTION_ESTABLISHED
* @param event packet
* @return local_cid
* @note: btstack_type 2
*/
static inline uint16_t avrcp_subevent_connection_established_get_local_cid(const uint8_t * event){
return little_endian_read_16(event, 6);
} }
/** /**
* @brief Get field bd_addr from event AVRCP_SUBEVENT_CONNECTION_ESTABLISHED * @brief Get field bd_addr from event AVRCP_SUBEVENT_CONNECTION_ESTABLISHED
@ -4733,26 +4715,44 @@ static inline uint16_t avrcp_subevent_connection_established_get_local_cid(const
* @note: btstack_type B * @note: btstack_type B
*/ */
static inline void avrcp_subevent_connection_established_get_bd_addr(const uint8_t * event, bd_addr_t bd_addr){ static inline void avrcp_subevent_connection_established_get_bd_addr(const uint8_t * event, bd_addr_t bd_addr){
reverse_bd_addr(&event[8], bd_addr); reverse_bd_addr(&event[4], bd_addr);
} }
/** /**
* @brief Get field con_handle from event AVRCP_SUBEVENT_CONNECTION_RELEASED * @brief Get field con_handle from event AVRCP_SUBEVENT_CONNECTION_ESTABLISHED
* @param event packet * @param event packet
* @return con_handle * @return con_handle
* @note: btstack_type H * @note: btstack_type H
*/ */
static inline hci_con_handle_t avrcp_subevent_connection_released_get_con_handle(const uint8_t * event){ static inline hci_con_handle_t avrcp_subevent_connection_established_get_con_handle(const uint8_t * event){
return little_endian_read_16(event, 10);
}
/**
* @brief Get field avrcp_cid from event AVRCP_SUBEVENT_CONNECTION_ESTABLISHED
* @param event packet
* @return avrcp_cid
* @note: btstack_type 2
*/
static inline uint16_t avrcp_subevent_connection_established_get_avrcp_cid(const uint8_t * event){
return little_endian_read_16(event, 12);
}
/**
* @brief Get field avrcp_cid from event AVRCP_SUBEVENT_CONNECTION_RELEASED
* @param event packet
* @return avrcp_cid
* @note: btstack_type 2
*/
static inline uint16_t avrcp_subevent_connection_released_get_avrcp_cid(const uint8_t * event){
return little_endian_read_16(event, 3); return little_endian_read_16(event, 3);
} }
/** /**
* @brief Get field con_handle from event AVRCP_SUBEVENT_NOW_PLAYING_INFO * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_NOW_PLAYING_INFO
* @param event packet * @param event packet
* @return con_handle * @return avrcp_cid
* @note: btstack_type H * @note: btstack_type 2
*/ */
static inline hci_con_handle_t avrcp_subevent_now_playing_info_get_con_handle(const uint8_t * event){ static inline uint16_t avrcp_subevent_now_playing_info_get_avrcp_cid(const uint8_t * event){
return little_endian_read_16(event, 3); return little_endian_read_16(event, 3);
} }
/** /**
@ -4865,12 +4865,12 @@ static inline const uint8_t * avrcp_subevent_now_playing_info_get_genre(const ui
} }
/** /**
* @brief Get field con_handle from event AVRCP_SUBEVENT_SHUFFLE_AND_REPEAT_MODE * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_SHUFFLE_AND_REPEAT_MODE
* @param event packet * @param event packet
* @return con_handle * @return avrcp_cid
* @note: btstack_type H * @note: btstack_type 2
*/ */
static inline hci_con_handle_t avrcp_subevent_shuffle_and_repeat_mode_get_con_handle(const uint8_t * event){ static inline uint16_t avrcp_subevent_shuffle_and_repeat_mode_get_avrcp_cid(const uint8_t * event){
return little_endian_read_16(event, 3); return little_endian_read_16(event, 3);
} }
/** /**
@ -4902,12 +4902,12 @@ static inline uint8_t avrcp_subevent_shuffle_and_repeat_mode_get_shuffle_mode(co
} }
/** /**
* @brief Get field con_handle from event AVRCP_SUBEVENT_PLAY_STATUS * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_PLAY_STATUS
* @param event packet * @param event packet
* @return con_handle * @return avrcp_cid
* @note: btstack_type H * @note: btstack_type 2
*/ */
static inline hci_con_handle_t avrcp_subevent_play_status_get_con_handle(const uint8_t * event){ static inline uint16_t avrcp_subevent_play_status_get_avrcp_cid(const uint8_t * event){
return little_endian_read_16(event, 3); return little_endian_read_16(event, 3);
} }
/** /**
@ -4948,12 +4948,12 @@ static inline uint8_t avrcp_subevent_play_status_get_play_status(const uint8_t *
} }
/** /**
* @brief Get field con_handle from event AVRCP_SUBEVENT_NOTIFICATION_PLAYBACK_STATUS_CHANGED * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_NOTIFICATION_PLAYBACK_STATUS_CHANGED
* @param event packet * @param event packet
* @return con_handle * @return avrcp_cid
* @note: btstack_type H * @note: btstack_type 2
*/ */
static inline hci_con_handle_t avrcp_subevent_notification_playback_status_changed_get_con_handle(const uint8_t * event){ static inline uint16_t avrcp_subevent_notification_playback_status_changed_get_avrcp_cid(const uint8_t * event){
return little_endian_read_16(event, 3); return little_endian_read_16(event, 3);
} }
/** /**
@ -4976,12 +4976,12 @@ static inline uint8_t avrcp_subevent_notification_playback_status_changed_get_pl
} }
/** /**
* @brief Get field con_handle from event AVRCP_SUBEVENT_NOTIFICATION_TRACK_CHANGED * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_NOTIFICATION_TRACK_CHANGED
* @param event packet * @param event packet
* @return con_handle * @return avrcp_cid
* @note: btstack_type H * @note: btstack_type 2
*/ */
static inline hci_con_handle_t avrcp_subevent_notification_track_changed_get_con_handle(const uint8_t * event){ static inline uint16_t avrcp_subevent_notification_track_changed_get_avrcp_cid(const uint8_t * event){
return little_endian_read_16(event, 3); return little_endian_read_16(event, 3);
} }
/** /**
@ -5004,12 +5004,12 @@ static inline uint8_t avrcp_subevent_notification_track_changed_get_track_status
} }
/** /**
* @brief Get field con_handle from event AVRCP_SUBEVENT_NOTIFICATION_NOW_PLAYING_CONTENT_CHANGED * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_NOTIFICATION_NOW_PLAYING_CONTENT_CHANGED
* @param event packet * @param event packet
* @return con_handle * @return avrcp_cid
* @note: btstack_type H * @note: btstack_type 2
*/ */
static inline hci_con_handle_t avrcp_subevent_notification_now_playing_content_changed_get_con_handle(const uint8_t * event){ static inline uint16_t avrcp_subevent_notification_now_playing_content_changed_get_avrcp_cid(const uint8_t * event){
return little_endian_read_16(event, 3); return little_endian_read_16(event, 3);
} }
/** /**
@ -5023,12 +5023,12 @@ static inline uint8_t avrcp_subevent_notification_now_playing_content_changed_ge
} }
/** /**
* @brief Get field con_handle from event AVRCP_SUBEVENT_NOTIFICATION_AVAILABLE_PLAYERS_CHANGED * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_NOTIFICATION_AVAILABLE_PLAYERS_CHANGED
* @param event packet * @param event packet
* @return con_handle * @return avrcp_cid
* @note: btstack_type H * @note: btstack_type 2
*/ */
static inline hci_con_handle_t avrcp_subevent_notification_available_players_changed_get_con_handle(const uint8_t * event){ static inline uint16_t avrcp_subevent_notification_available_players_changed_get_avrcp_cid(const uint8_t * event){
return little_endian_read_16(event, 3); return little_endian_read_16(event, 3);
} }
/** /**
@ -5042,12 +5042,12 @@ static inline uint8_t avrcp_subevent_notification_available_players_changed_get_
} }
/** /**
* @brief Get field con_handle from event AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED
* @param event packet * @param event packet
* @return con_handle * @return avrcp_cid
* @note: btstack_type H * @note: btstack_type 2
*/ */
static inline hci_con_handle_t avrcp_subevent_notification_volume_changed_get_con_handle(const uint8_t * event){ static inline uint16_t avrcp_subevent_notification_volume_changed_get_avrcp_cid(const uint8_t * event){
return little_endian_read_16(event, 3); return little_endian_read_16(event, 3);
} }
/** /**
@ -5070,12 +5070,12 @@ static inline uint8_t avrcp_subevent_notification_volume_changed_get_absolute_vo
} }
/** /**
* @brief Get field con_handle from event AVRCP_SUBEVENT_SET_ABSOLUTE_VOLUME_RESPONSE * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_SET_ABSOLUTE_VOLUME_RESPONSE
* @param event packet * @param event packet
* @return con_handle * @return avrcp_cid
* @note: btstack_type H * @note: btstack_type 2
*/ */
static inline hci_con_handle_t avrcp_subevent_set_absolute_volume_response_get_con_handle(const uint8_t * event){ static inline uint16_t avrcp_subevent_set_absolute_volume_response_get_avrcp_cid(const uint8_t * event){
return little_endian_read_16(event, 3); return little_endian_read_16(event, 3);
} }
/** /**
@ -5098,12 +5098,12 @@ static inline uint8_t avrcp_subevent_set_absolute_volume_response_get_absolute_v
} }
/** /**
* @brief Get field con_handle from event AVRCP_SUBEVENT_ENABLE_NOTIFICATION_COMPLETE * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_ENABLE_NOTIFICATION_COMPLETE
* @param event packet * @param event packet
* @return con_handle * @return avrcp_cid
* @note: btstack_type H * @note: btstack_type 2
*/ */
static inline hci_con_handle_t avrcp_subevent_enable_notification_complete_get_con_handle(const uint8_t * event){ static inline uint16_t avrcp_subevent_enable_notification_complete_get_avrcp_cid(const uint8_t * event){
return little_endian_read_16(event, 3); return little_endian_read_16(event, 3);
} }
/** /**
@ -5126,12 +5126,12 @@ static inline uint8_t avrcp_subevent_enable_notification_complete_get_notificati
} }
/** /**
* @brief Get field con_handle from event AVRCP_SUBEVENT_OPERATION_START * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_OPERATION_START
* @param event packet * @param event packet
* @return con_handle * @return avrcp_cid
* @note: btstack_type H * @note: btstack_type 2
*/ */
static inline hci_con_handle_t avrcp_subevent_operation_start_get_con_handle(const uint8_t * event){ static inline uint16_t avrcp_subevent_operation_start_get_avrcp_cid(const uint8_t * event){
return little_endian_read_16(event, 3); return little_endian_read_16(event, 3);
} }
/** /**
@ -5154,12 +5154,12 @@ static inline uint8_t avrcp_subevent_operation_start_get_operation_id(const uint
} }
/** /**
* @brief Get field con_handle from event AVRCP_SUBEVENT_OPERATION_COMPLETE * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_OPERATION_COMPLETE
* @param event packet * @param event packet
* @return con_handle * @return avrcp_cid
* @note: btstack_type H * @note: btstack_type 2
*/ */
static inline hci_con_handle_t avrcp_subevent_operation_complete_get_con_handle(const uint8_t * event){ static inline uint16_t avrcp_subevent_operation_complete_get_avrcp_cid(const uint8_t * event){
return little_endian_read_16(event, 3); return little_endian_read_16(event, 3);
} }
/** /**
@ -5182,12 +5182,12 @@ static inline uint8_t avrcp_subevent_operation_complete_get_operation_id(const u
} }
/** /**
* @brief Get field con_handle from event AVRCP_SUBEVENT_PLAYER_APPLICATION_VALUE_RESPONSE * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_PLAYER_APPLICATION_VALUE_RESPONSE
* @param event packet * @param event packet
* @return con_handle * @return avrcp_cid
* @note: btstack_type H * @note: btstack_type 2
*/ */
static inline hci_con_handle_t avrcp_subevent_player_application_value_response_get_con_handle(const uint8_t * event){ static inline uint16_t avrcp_subevent_player_application_value_response_get_avrcp_cid(const uint8_t * event){
return little_endian_read_16(event, 3); return little_endian_read_16(event, 3);
} }
/** /**

View File

@ -327,14 +327,31 @@ void avrcp_target_create_sdp_record(uint8_t * service, uint32_t service_record_h
avrcp_create_sdp_record(0, service, service_record_handle, browsing, supported_features, service_name, service_provider_name); avrcp_create_sdp_record(0, service, service_record_handle, browsing, supported_features, service_name, service_provider_name);
} }
static void avrcp_emit_repeat_and_shuffle_mode(btstack_packet_handler_t callback, uint16_t con_handle, uint8_t status, avrcp_repeat_mode_t repeat_mode, avrcp_shuffle_mode_t shuffle_mode){ static void avrcp_emit_connection_established(btstack_packet_handler_t callback, uint8_t status, bd_addr_t addr, uint16_t con_handle, uint16_t avrcp_cid){
if (!callback) return;
uint8_t event[14];
int pos = 0;
event[pos++] = HCI_EVENT_AVRCP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = AVRCP_SUBEVENT_CONNECTION_ESTABLISHED;
event[pos++] = status;
reverse_bd_addr(addr,&event[pos]);
pos += 6;
little_endian_store_16(event, pos, con_handle);
pos += 2;
little_endian_store_16(event, pos, avrcp_cid);
pos += 2;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
static void avrcp_emit_repeat_and_shuffle_mode(btstack_packet_handler_t callback, uint16_t avrcp_cid, uint8_t status, avrcp_repeat_mode_t repeat_mode, avrcp_shuffle_mode_t shuffle_mode){
if (!callback) return; if (!callback) return;
uint8_t event[8]; uint8_t event[8];
int pos = 0; int pos = 0;
event[pos++] = HCI_EVENT_AVRCP_META; event[pos++] = HCI_EVENT_AVRCP_META;
event[pos++] = sizeof(event) - 2; event[pos++] = sizeof(event) - 2;
event[pos++] = AVRCP_SUBEVENT_SHUFFLE_AND_REPEAT_MODE; event[pos++] = AVRCP_SUBEVENT_SHUFFLE_AND_REPEAT_MODE;
little_endian_store_16(event, pos, con_handle); little_endian_store_16(event, pos, avrcp_cid);
pos += 2; pos += 2;
event[pos++] = status; event[pos++] = status;
event[pos++] = repeat_mode; event[pos++] = repeat_mode;
@ -342,45 +359,28 @@ static void avrcp_emit_repeat_and_shuffle_mode(btstack_packet_handler_t callback
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
} }
static void avrcp_emit_connection_established(btstack_packet_handler_t callback, uint16_t con_handle, uint8_t status, uint16_t local_cid, bd_addr_t addr){ static void avrcp_emit_operation_status(btstack_packet_handler_t callback, uint8_t subevent, uint16_t avrcp_cid, uint8_t status, uint8_t operation_id){
if (!callback) return;
uint8_t event[14];
int pos = 0;
event[pos++] = HCI_EVENT_AVRCP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = AVRCP_SUBEVENT_CONNECTION_ESTABLISHED;
little_endian_store_16(event, pos, con_handle);
pos += 2;
event[pos++] = status;
little_endian_store_16(event, pos, local_cid);
pos += 2;
reverse_bd_addr(addr,&event[pos]);
pos += 6;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
static void avrcp_emit_operation_status(btstack_packet_handler_t callback, uint8_t subevent, uint16_t con_handle, uint8_t status, uint8_t operation_id){
if (!callback) return; if (!callback) return;
uint8_t event[7]; uint8_t event[7];
int pos = 0; int pos = 0;
event[pos++] = HCI_EVENT_AVRCP_META; event[pos++] = HCI_EVENT_AVRCP_META;
event[pos++] = sizeof(event) - 2; event[pos++] = sizeof(event) - 2;
event[pos++] = subevent; event[pos++] = subevent;
little_endian_store_16(event, pos, con_handle); little_endian_store_16(event, pos, avrcp_cid);
pos += 2; pos += 2;
event[pos++] = status; event[pos++] = status;
event[pos++] = operation_id; event[pos++] = operation_id;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
} }
static void avrcp_emit_connection_closed(btstack_packet_handler_t callback, uint16_t con_handle){ static void avrcp_emit_connection_closed(btstack_packet_handler_t callback, uint16_t avrcp_cid){
if (!callback) return; if (!callback) return;
uint8_t event[5]; uint8_t event[5];
int pos = 0; int pos = 0;
event[pos++] = HCI_EVENT_AVRCP_META; event[pos++] = HCI_EVENT_AVRCP_META;
event[pos++] = sizeof(event) - 2; event[pos++] = sizeof(event) - 2;
event[pos++] = AVRCP_SUBEVENT_CONNECTION_RELEASED; event[pos++] = AVRCP_SUBEVENT_CONNECTION_RELEASED;
little_endian_store_16(event, pos, con_handle); little_endian_store_16(event, pos, avrcp_cid);
pos += 2; pos += 2;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
} }
@ -396,17 +396,6 @@ static avrcp_connection_t * get_avrcp_connection_for_bd_addr(bd_addr_t addr){
return NULL; return NULL;
} }
static avrcp_connection_t * get_avrcp_connection_for_con_handle(hci_con_handle_t con_handle){
btstack_linked_list_iterator_t it;
btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &avrcp_connections);
while (btstack_linked_list_iterator_has_next(&it)){
avrcp_connection_t * connection = (avrcp_connection_t *)btstack_linked_list_iterator_next(&it);
if (connection->con_handle != con_handle) continue;
return connection;
}
return NULL;
}
static avrcp_connection_t * get_avrcp_connection_for_l2cap_signaling_cid(uint16_t l2cap_cid){ static avrcp_connection_t * get_avrcp_connection_for_l2cap_signaling_cid(uint16_t l2cap_cid){
btstack_linked_list_iterator_t it; btstack_linked_list_iterator_t it;
btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &avrcp_connections); btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &avrcp_connections);
@ -459,8 +448,8 @@ static void request_pass_through_release_control_cmd(avrcp_connection_t * connec
avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
} }
static void request_pass_through_press_control_cmd(uint16_t con_handle, avrcp_operation_id_t opid, uint16_t playback_speed){ static void request_pass_through_press_control_cmd(uint16_t avrcp_cid, avrcp_operation_id_t opid, uint16_t playback_speed){
avrcp_connection_t * connection = get_avrcp_connection_for_con_handle(con_handle); avrcp_connection_t * connection = get_avrcp_connection_for_l2cap_signaling_cid(avrcp_cid);
if (!connection){ if (!connection){
log_error("avrcp: could not find a connection."); log_error("avrcp: could not find a connection.");
return; return;
@ -999,10 +988,12 @@ static void avrcp_handle_can_send_now(avrcp_connection_t * connection){
switch (connection->state){ switch (connection->state){
case AVCTP_W2_SEND_PRESS_COMMAND: case AVCTP_W2_SEND_PRESS_COMMAND:
connection->state = AVCTP_W2_RECEIVE_PRESS_RESPONSE; connection->state = AVCTP_W2_RECEIVE_PRESS_RESPONSE;
avrcp_send_cmd(connection->l2cap_signaling_cid, connection);
break; break;
case AVCTP_W2_SEND_COMMAND: case AVCTP_W2_SEND_COMMAND:
case AVCTP_W2_SEND_RELEASE_COMMAND: case AVCTP_W2_SEND_RELEASE_COMMAND:
connection->state = AVCTP_W2_RECEIVE_RESPONSE; connection->state = AVCTP_W2_RECEIVE_RESPONSE;
avrcp_send_cmd(connection->l2cap_signaling_cid, connection);
break; break;
case AVCTP_CONNECTION_OPENED: case AVCTP_CONNECTION_OPENED:
if (connection->disconnect){ if (connection->disconnect){
@ -1027,7 +1018,6 @@ static void avrcp_handle_can_send_now(avrcp_connection_t * connection){
default: default:
return; return;
} }
avrcp_send_cmd(connection->l2cap_signaling_cid, connection);
} }
static avrcp_connection_t * avrcp_create_connection(bd_addr_t remote_addr){ static avrcp_connection_t * avrcp_create_connection(bd_addr_t remote_addr){
@ -1079,7 +1069,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
} }
psm = l2cap_event_channel_opened_get_psm(packet); psm = l2cap_event_channel_opened_get_psm(packet);
if (psm != BLUETOOTH_PROTOCOL_AVCTP){ if (psm != BLUETOOTH_PROTOCOL_AVCTP){
log_error("unexpected PSM - Not implemented yet: L2CAP_EVENT_CHANNEL_OPENED"); log_error("L2CAP_EVENT_CHANNEL_OPENED avrcp: unexpected PSM");
return; return;
} }
@ -1088,13 +1078,20 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
con_handle = l2cap_event_channel_opened_get_handle(packet); con_handle = l2cap_event_channel_opened_get_handle(packet);
local_cid = l2cap_event_channel_opened_get_local_cid(packet); local_cid = l2cap_event_channel_opened_get_local_cid(packet);
if (connection->l2cap_signaling_cid != local_cid) {
log_info("Connection is not established, expected 0x%02X l2cap cid, received 0x%02X\n", connection->l2cap_signaling_cid, local_cid);
break;
}
// printf("L2CAP_EVENT_CHANNEL_OPENED: Channel successfully opened: %s, handle 0x%02x, psm 0x%02x, local cid 0x%02x, remote cid 0x%02x\n", // printf("L2CAP_EVENT_CHANNEL_OPENED: Channel successfully opened: %s, handle 0x%02x, psm 0x%02x, local cid 0x%02x, remote cid 0x%02x\n",
// bd_addr_to_str(event_addr), con_handle, psm, local_cid, l2cap_event_channel_opened_get_remote_cid(packet)); // bd_addr_to_str(event_addr), con_handle, psm, local_cid, l2cap_event_channel_opened_get_remote_cid(packet));
if (connection->l2cap_signaling_cid == 0) {
if (connection->con_handle == 0) {
connection->l2cap_signaling_cid = local_cid; connection->l2cap_signaling_cid = local_cid;
connection->con_handle = con_handle; connection->con_handle = con_handle;
connection->state = AVCTP_CONNECTION_OPENED; connection->state = AVCTP_CONNECTION_OPENED;
avrcp_emit_connection_established(avrcp_callback, con_handle, 0, local_cid, event_addr); avrcp_emit_connection_established(avrcp_callback, 0, event_addr, con_handle, local_cid);
break; break;
} }
break; break;
@ -1137,7 +1134,7 @@ void avrcp_register_packet_handler(btstack_packet_handler_t callback){
avrcp_callback = callback; avrcp_callback = callback;
} }
uint8_t avrcp_connect(bd_addr_t bd_addr){ uint8_t avrcp_connect(bd_addr_t bd_addr, uint16_t * avrcp_cid){
avrcp_connection_t * connection = get_avrcp_connection_for_bd_addr(bd_addr); avrcp_connection_t * connection = get_avrcp_connection_for_bd_addr(bd_addr);
if (connection){ if (connection){
return ERROR_CODE_COMMAND_DISALLOWED; return ERROR_CODE_COMMAND_DISALLOWED;
@ -1150,12 +1147,15 @@ uint8_t avrcp_connect(bd_addr_t bd_addr){
} }
connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED; connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
l2cap_create_channel(packet_handler, connection->remote_addr, BLUETOOTH_PROTOCOL_AVCTP, 0xffff, NULL); l2cap_create_channel(packet_handler, connection->remote_addr, BLUETOOTH_PROTOCOL_AVCTP, 0xffff, &connection->l2cap_signaling_cid);
if (avrcp_cid) {
*avrcp_cid = connection->l2cap_signaling_cid;
}
return ERROR_CODE_SUCCESS; return ERROR_CODE_SUCCESS;
} }
void avrcp_unit_info(uint16_t con_handle){ void avrcp_unit_info(uint16_t avrcp_cid){
avrcp_connection_t * connection = get_avrcp_connection_for_con_handle(con_handle); avrcp_connection_t * connection = get_avrcp_connection_for_l2cap_signaling_cid(avrcp_cid);
if (!connection){ if (!connection){
log_error("avrcp_unit_info: could not find a connection."); log_error("avrcp_unit_info: could not find a connection.");
return; return;
@ -1173,8 +1173,8 @@ void avrcp_unit_info(uint16_t con_handle){
avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
} }
static void avrcp_get_capabilities(uint16_t con_handle, uint8_t capability_id){ static void avrcp_get_capabilities(uint16_t avrcp_cid, uint8_t capability_id){
avrcp_connection_t * connection = get_avrcp_connection_for_con_handle(con_handle); avrcp_connection_t * connection = get_avrcp_connection_for_l2cap_signaling_cid(avrcp_cid);
if (!connection){ if (!connection){
log_error("avrcp_get_capabilities: could not find a connection."); log_error("avrcp_get_capabilities: could not find a connection.");
return; return;
@ -1196,57 +1196,57 @@ static void avrcp_get_capabilities(uint16_t con_handle, uint8_t capability_id){
avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
} }
void avrcp_get_supported_company_ids(uint16_t con_handle){ void avrcp_get_supported_company_ids(uint16_t avrcp_cid){
avrcp_get_capabilities(con_handle, AVRCP_CAPABILITY_ID_COMPANY); avrcp_get_capabilities(avrcp_cid, AVRCP_CAPABILITY_ID_COMPANY);
} }
void avrcp_get_supported_events(uint16_t con_handle){ void avrcp_get_supported_events(uint16_t avrcp_cid){
avrcp_get_capabilities(con_handle, AVRCP_CAPABILITY_ID_EVENT); avrcp_get_capabilities(avrcp_cid, AVRCP_CAPABILITY_ID_EVENT);
} }
void avrcp_play(uint16_t con_handle){ void avrcp_play(uint16_t avrcp_cid){
request_pass_through_press_control_cmd(con_handle, AVRCP_OPERATION_ID_PLAY, 0); request_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_PLAY, 0);
} }
void avrcp_stop(uint16_t con_handle){ void avrcp_stop(uint16_t avrcp_cid){
request_pass_through_press_control_cmd(con_handle, AVRCP_OPERATION_ID_STOP, 0); request_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_STOP, 0);
} }
void avrcp_pause(uint16_t con_handle){ void avrcp_pause(uint16_t avrcp_cid){
request_pass_through_press_control_cmd(con_handle, AVRCP_OPERATION_ID_PAUSE, 0); request_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_PAUSE, 0);
} }
void avrcp_forward(uint16_t con_handle){ void avrcp_forward(uint16_t avrcp_cid){
request_pass_through_press_control_cmd(con_handle, AVRCP_OPERATION_ID_FORWARD, 0); request_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_FORWARD, 0);
} }
void avrcp_backward(uint16_t con_handle){ void avrcp_backward(uint16_t avrcp_cid){
request_pass_through_press_control_cmd(con_handle, AVRCP_OPERATION_ID_BACKWARD, 0); request_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_BACKWARD, 0);
} }
void avrcp_start_rewind(uint16_t con_handle){ void avrcp_start_rewind(uint16_t avrcp_cid){
request_pass_through_press_control_cmd(con_handle, AVRCP_OPERATION_ID_REWIND, 0); request_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_REWIND, 0);
} }
void avrcp_volume_up(uint16_t con_handle){ void avrcp_volume_up(uint16_t avrcp_cid){
request_pass_through_press_control_cmd(con_handle, AVRCP_OPERATION_ID_VOLUME_UP, 0); request_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_VOLUME_UP, 0);
} }
void avrcp_volume_down(uint16_t con_handle){ void avrcp_volume_down(uint16_t avrcp_cid){
request_pass_through_press_control_cmd(con_handle, AVRCP_OPERATION_ID_VOLUME_DOWN, 0); request_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_VOLUME_DOWN, 0);
} }
void avrcp_mute(uint16_t con_handle){ void avrcp_mute(uint16_t avrcp_cid){
request_pass_through_press_control_cmd(con_handle, AVRCP_OPERATION_ID_MUTE, 0); request_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_MUTE, 0);
} }
void avrcp_skip(uint16_t con_handle){ void avrcp_skip(uint16_t avrcp_cid){
request_pass_through_press_control_cmd(con_handle, AVRCP_OPERATION_ID_SKIP, 0); request_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_SKIP, 0);
} }
void avrcp_stop_rewind(uint16_t con_handle){ void avrcp_stop_rewind(uint16_t avrcp_cid){
avrcp_connection_t * connection = get_avrcp_connection_for_con_handle(con_handle); avrcp_connection_t * connection = get_avrcp_connection_for_l2cap_signaling_cid(avrcp_cid);
if (!connection){ if (!connection){
log_error("avrcp_stop_rewind: could not find a connection."); log_error("avrcp_stop_rewind: could not find a connection.");
return; return;
@ -1255,12 +1255,12 @@ void avrcp_stop_rewind(uint16_t con_handle){
request_pass_through_release_control_cmd(connection); request_pass_through_release_control_cmd(connection);
} }
void avrcp_start_fast_forward(uint16_t con_handle){ void avrcp_start_fast_forward(uint16_t avrcp_cid){
request_pass_through_press_control_cmd(con_handle, AVRCP_OPERATION_ID_FAST_FORWARD, 0); request_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_FAST_FORWARD, 0);
} }
void avrcp_stop_fast_forward(uint16_t con_handle){ void avrcp_stop_fast_forward(uint16_t avrcp_cid){
avrcp_connection_t * connection = get_avrcp_connection_for_con_handle(con_handle); avrcp_connection_t * connection = get_avrcp_connection_for_l2cap_signaling_cid(avrcp_cid);
if (!connection){ if (!connection){
log_error("avrcp_stop_fast_forward: could not find a connection."); log_error("avrcp_stop_fast_forward: could not find a connection.");
return; return;
@ -1269,8 +1269,8 @@ void avrcp_stop_fast_forward(uint16_t con_handle){
request_pass_through_release_control_cmd(connection); request_pass_through_release_control_cmd(connection);
} }
void avrcp_get_play_status(uint16_t con_handle){ void avrcp_get_play_status(uint16_t avrcp_cid){
avrcp_connection_t * connection = get_avrcp_connection_for_con_handle(con_handle); avrcp_connection_t * connection = get_avrcp_connection_for_l2cap_signaling_cid(avrcp_cid);
if (!connection){ if (!connection){
log_error("avrcp_get_play_status: could not find a connection."); log_error("avrcp_get_play_status: could not find a connection.");
return; return;
@ -1291,8 +1291,8 @@ void avrcp_get_play_status(uint16_t con_handle){
avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
} }
void avrcp_enable_notification(uint16_t con_handle, avrcp_notification_event_id_t event_id){ void avrcp_enable_notification(uint16_t avrcp_cid, avrcp_notification_event_id_t event_id){
avrcp_connection_t * connection = get_avrcp_connection_for_con_handle(con_handle); avrcp_connection_t * connection = get_avrcp_connection_for_l2cap_signaling_cid(avrcp_cid);
if (!connection){ if (!connection){
log_error("avrcp_get_play_status: could not find a connection."); log_error("avrcp_get_play_status: could not find a connection.");
return; return;
@ -1300,8 +1300,8 @@ void avrcp_enable_notification(uint16_t con_handle, avrcp_notification_event_id_
avrcp_register_notification(connection, event_id); avrcp_register_notification(connection, event_id);
} }
void avrcp_disable_notification(uint16_t con_handle, avrcp_notification_event_id_t event_id){ void avrcp_disable_notification(uint16_t avrcp_cid, avrcp_notification_event_id_t event_id){
avrcp_connection_t * connection = get_avrcp_connection_for_con_handle(con_handle); avrcp_connection_t * connection = get_avrcp_connection_for_l2cap_signaling_cid(avrcp_cid);
if (!connection){ if (!connection){
log_error("avrcp_get_play_status: could not find a connection."); log_error("avrcp_get_play_status: could not find a connection.");
return; return;
@ -1309,8 +1309,8 @@ void avrcp_disable_notification(uint16_t con_handle, avrcp_notification_event_id
connection->notifications_to_deregister |= (1 << event_id); connection->notifications_to_deregister |= (1 << event_id);
} }
void avrcp_get_now_playing_info(uint16_t con_handle){ void avrcp_get_now_playing_info(uint16_t avrcp_cid){
avrcp_connection_t * connection = get_avrcp_connection_for_con_handle(con_handle); avrcp_connection_t * connection = get_avrcp_connection_for_l2cap_signaling_cid(avrcp_cid);
if (!connection){ if (!connection){
log_error("avrcp_get_capabilities: could not find a connection."); log_error("avrcp_get_capabilities: could not find a connection.");
return; return;
@ -1345,8 +1345,8 @@ void avrcp_get_now_playing_info(uint16_t con_handle){
} }
void avrcp_set_absolute_volume(uint16_t con_handle, uint8_t volume){ void avrcp_set_absolute_volume(uint16_t avrcp_cid, uint8_t volume){
avrcp_connection_t * connection = get_avrcp_connection_for_con_handle(con_handle); avrcp_connection_t * connection = get_avrcp_connection_for_l2cap_signaling_cid(avrcp_cid);
if (!connection){ if (!connection){
log_error("avrcp_get_capabilities: could not find a connection."); log_error("avrcp_get_capabilities: could not find a connection.");
return; return;
@ -1374,8 +1374,8 @@ void avrcp_set_absolute_volume(uint16_t con_handle, uint8_t volume){
avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
} }
void avrcp_query_shuffle_and_repeat_modes(uint16_t con_handle){ void avrcp_query_shuffle_and_repeat_modes(uint16_t avrcp_cid){
avrcp_connection_t * connection = get_avrcp_connection_for_con_handle(con_handle); avrcp_connection_t * connection = get_avrcp_connection_for_l2cap_signaling_cid(avrcp_cid);
if (!connection){ if (!connection){
log_error("avrcp_get_capabilities: could not find a connection."); log_error("avrcp_get_capabilities: could not find a connection.");
return; return;
@ -1403,8 +1403,8 @@ void avrcp_query_shuffle_and_repeat_modes(uint16_t con_handle){
} }
static void avrcp_set_current_player_application_setting_value(uint16_t con_handle, uint8_t attribute_id, uint8_t attribute_value){ static void avrcp_set_current_player_application_setting_value(uint16_t avrcp_cid, uint8_t attribute_id, uint8_t attribute_value){
avrcp_connection_t * connection = get_avrcp_connection_for_con_handle(con_handle); avrcp_connection_t * connection = get_avrcp_connection_for_l2cap_signaling_cid(avrcp_cid);
if (!connection){ if (!connection){
log_error("avrcp_get_capabilities: could not find a connection."); log_error("avrcp_get_capabilities: could not find a connection.");
return; return;
@ -1433,18 +1433,18 @@ static void avrcp_set_current_player_application_setting_value(uint16_t con_hand
avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
} }
void avrcp_set_shuffle_mode(uint16_t con_handle, avrcp_shuffle_mode_t mode){ void avrcp_set_shuffle_mode(uint16_t avrcp_cid, avrcp_shuffle_mode_t mode){
if (mode < AVRCP_SHUFFLE_MODE_OFF || mode > AVRCP_SHUFFLE_MODE_GROUP) return; if (mode < AVRCP_SHUFFLE_MODE_OFF || mode > AVRCP_SHUFFLE_MODE_GROUP) return;
avrcp_set_current_player_application_setting_value(con_handle, 0x03, mode); avrcp_set_current_player_application_setting_value(avrcp_cid, 0x03, mode);
} }
void avrcp_set_repeat_mode(uint16_t con_handle, avrcp_repeat_mode_t mode){ void avrcp_set_repeat_mode(uint16_t avrcp_cid, avrcp_repeat_mode_t mode){
if (mode < AVRCP_REPEAT_MODE_OFF || mode > AVRCP_REPEAT_MODE_GROUP) return; if (mode < AVRCP_REPEAT_MODE_OFF || mode > AVRCP_REPEAT_MODE_GROUP) return;
avrcp_set_current_player_application_setting_value(con_handle, 0x02, mode); avrcp_set_current_player_application_setting_value(avrcp_cid, 0x02, mode);
} }
void avrcp_disconnect(uint16_t con_handle){ void avrcp_disconnect(uint16_t avrcp_cid){
avrcp_connection_t * connection = get_avrcp_connection_for_con_handle(con_handle); avrcp_connection_t * connection = get_avrcp_connection_for_l2cap_signaling_cid(avrcp_cid);
if (!connection){ if (!connection){
log_error("avrcp_get_capabilities: could not find a connection."); log_error("avrcp_get_capabilities: could not find a connection.");
return; return;

View File

@ -189,7 +189,7 @@ typedef struct {
bd_addr_t remote_addr; bd_addr_t remote_addr;
hci_con_handle_t con_handle; hci_con_handle_t con_handle;
uint16_t l2cap_signaling_cid; uint16_t l2cap_signaling_cid;
avctp_connection_state_t state; avctp_connection_state_t state;
uint8_t wait_to_send; uint8_t wait_to_send;
@ -269,136 +269,138 @@ void avrcp_register_packet_handler(btstack_packet_handler_t callback);
/** /**
* @brief Connect to device with a bluetooth address. * @brief Connect to device with a bluetooth address.
* @param bd_addr * @param bd_addr
* @param avrcp_cid
*/ */
uint8_t avrcp_connect(bd_addr_t bd_addr); uint8_t avrcp_connect(bd_addr_t bd_addr, uint16_t * avrcp_cid);
void avrcp_disconnect(uint16_t con_handle);
void avrcp_disconnect(uint16_t avrcp_cid);
/** /**
* @brief Unit info. * @brief Unit info.
* @param con_handle * @param avrcp_cid
*/ */
void avrcp_unit_info(uint16_t con_handle); void avrcp_unit_info(uint16_t avrcp_cid);
/** /**
* @brief Get capabilities. * @brief Get capabilities.
* @param con_handle * @param avrcp_cid
*/ */
void avrcp_get_supported_company_ids(uint16_t con_handle); void avrcp_get_supported_company_ids(uint16_t avrcp_cid);
void avrcp_get_supported_events(uint16_t con_handle); void avrcp_get_supported_events(uint16_t avrcp_cid);
/** /**
* @brief Play. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status. * @brief Play. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status.
* @param con_handle * @param avrcp_cid
*/ */
void avrcp_play(uint16_t con_handle); void avrcp_play(uint16_t avrcp_cid);
/** /**
* @brief Stop. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status. * @brief Stop. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status.
* @param con_handle * @param avrcp_cid
*/ */
void avrcp_stop(uint16_t con_handle); void avrcp_stop(uint16_t avrcp_cid);
/** /**
* @brief Pause. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status. * @brief Pause. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status.
* @param con_handle * @param avrcp_cid
*/ */
void avrcp_pause(uint16_t con_handle); void avrcp_pause(uint16_t avrcp_cid);
/** /**
* @brief Fast forward. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status. * @brief Fast forward. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status.
* @param con_handle * @param avrcp_cid
*/ */
void avrcp_start_fast_forward(uint16_t con_handle); void avrcp_start_fast_forward(uint16_t avrcp_cid);
void avrcp_stop_fast_forward(uint16_t con_handle); void avrcp_stop_fast_forward(uint16_t avrcp_cid);
/** /**
* @brief Rewind. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status. * @brief Rewind. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status.
* @param con_handle * @param avrcp_cid
*/ */
void avrcp_start_rewind(uint16_t con_handle); void avrcp_start_rewind(uint16_t avrcp_cid);
void avrcp_stop_rewind(uint16_t con_handle); void avrcp_stop_rewind(uint16_t avrcp_cid);
/** /**
* @brief Forward. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status. * @brief Forward. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status.
* @param con_handle * @param avrcp_cid
*/ */
void avrcp_forward(uint16_t con_handle); void avrcp_forward(uint16_t avrcp_cid);
/** /**
* @brief Backward. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status. * @brief Backward. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status.
* @param con_handle * @param avrcp_cid
*/ */
void avrcp_backward(uint16_t con_handle); void avrcp_backward(uint16_t avrcp_cid);
/** /**
* @brief Get play status. Returns event of type AVRCP_SUBEVENT_PLAY_STATUS (length, position, play_status). * @brief Get play status. Returns event of type AVRCP_SUBEVENT_PLAY_STATUS (length, position, play_status).
* If TG does not support SongLength And SongPosition on TG, then TG shall return 0xFFFFFFFF. * If TG does not support SongLength And SongPosition on TG, then TG shall return 0xFFFFFFFF.
* @param con_handle * @param avrcp_cid
*/ */
void avrcp_get_play_status(uint16_t con_handle); void avrcp_get_play_status(uint16_t avrcp_cid);
/** /**
* @brief Register notification. Response via AVRCP_SUBEVENT_ENABLE_NOTIFICATION_COMPLETE. * @brief Register notification. Response via AVRCP_SUBEVENT_ENABLE_NOTIFICATION_COMPLETE.
* @param con_handle * @param avrcp_cid
* @param event_id * @param event_id
*/ */
void avrcp_enable_notification(uint16_t con_handle, avrcp_notification_event_id_t event_id); void avrcp_enable_notification(uint16_t avrcp_cid, avrcp_notification_event_id_t event_id);
void avrcp_disable_notification(uint16_t con_handle, avrcp_notification_event_id_t event_id); void avrcp_disable_notification(uint16_t avrcp_cid, avrcp_notification_event_id_t event_id);
/** /**
* @brief Get info on now playing media. * @brief Get info on now playing media.
* @param con_handle * @param avrcp_cid
*/ */
void avrcp_get_now_playing_info(uint16_t con_handle); void avrcp_get_now_playing_info(uint16_t avrcp_cid);
/** /**
* @brief Set absolute volume 0-127 (corresponds to 0-100%). Response via AVRCP_SUBEVENT_SET_ABSOLUTE_VOLUME_RESPONSE * @brief Set absolute volume 0-127 (corresponds to 0-100%). Response via AVRCP_SUBEVENT_SET_ABSOLUTE_VOLUME_RESPONSE
* @param con_handle * @param avrcp_cid
*/ */
void avrcp_set_absolute_volume(uint16_t con_handle, uint8_t volume); void avrcp_set_absolute_volume(uint16_t avrcp_cid, uint8_t volume);
/** /**
* @brief Turns the volume to high. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status. * @brief Turns the volume to high. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status.
* @param con_handle * @param avrcp_cid
*/ */
void avrcp_volume_up(uint16_t con_handle); void avrcp_volume_up(uint16_t avrcp_cid);
/** /**
* @brief Turns the volume to low. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status. * @brief Turns the volume to low. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status.
* @param con_handle * @param avrcp_cid
*/ */
void avrcp_volume_down(uint16_t con_handle); void avrcp_volume_down(uint16_t avrcp_cid);
/** /**
* @brief Puts the sound out. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status. * @brief Puts the sound out. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status.
* @param con_handle * @param avrcp_cid
*/ */
void avrcp_mute(uint16_t con_handle); void avrcp_mute(uint16_t avrcp_cid);
/** /**
* @brief Skip to next playing media. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status. * @brief Skip to next playing media. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status.
* @param con_handle * @param avrcp_cid
*/ */
void avrcp_skip(uint16_t con_handle); void avrcp_skip(uint16_t avrcp_cid);
/** /**
* @brief Query repeat and shuffle mode. Response via AVRCP_SUBEVENT_SHUFFLE_AND_REPEAT_MODE. * @brief Query repeat and shuffle mode. Response via AVRCP_SUBEVENT_SHUFFLE_AND_REPEAT_MODE.
* @param con_handle * @param avrcp_cid
*/ */
void avrcp_query_shuffle_and_repeat_modes(uint16_t con_handle); void avrcp_query_shuffle_and_repeat_modes(uint16_t avrcp_cid);
/** /**
* @brief Set shuffle mode. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status. * @brief Set shuffle mode. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status.
* @param con_handle * @param avrcp_cid
*/ */
void avrcp_set_shuffle_mode(uint16_t con_handle, avrcp_shuffle_mode_t mode); void avrcp_set_shuffle_mode(uint16_t avrcp_cid, avrcp_shuffle_mode_t mode);
/** /**
* @brief Set repeat mode. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status. * @brief Set repeat mode. Event AVRCP_SUBEVENT_OPERATION_COMPLETE returns operation id and status.
* @param con_handle * @param avrcp_cid
*/ */
void avrcp_set_repeat_mode(uint16_t con_handle, avrcp_repeat_mode_t mode); void avrcp_set_repeat_mode(uint16_t avrcp_cid, avrcp_repeat_mode_t mode);
const char * avrcp_subunit2str(uint16_t index); const char * avrcp_subunit2str(uint16_t index);
const char * avrcp_event2str(uint16_t index); const char * avrcp_event2str(uint16_t index);

View File

@ -64,6 +64,7 @@ static btstack_packet_callback_registration_t hci_event_callback_registration;
static bd_addr_t device_addr; static bd_addr_t device_addr;
static uint16_t avrcp_cid = 0;
// iPhone SE // iPhone SE
// static const char * device_addr_string = "BC:EC:5D:E6:15:03"; // static const char * device_addr_string = "BC:EC:5D:E6:15:03";
@ -90,19 +91,24 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
case HCI_EVENT_AVRCP_META: case HCI_EVENT_AVRCP_META:
switch (packet[2]){ switch (packet[2]){
case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: {
local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet);
if (avrcp_cid != local_cid) {
printf("Connection is not established, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid);
break;
}
status = avrcp_subevent_connection_established_get_status(packet); status = avrcp_subevent_connection_established_get_status(packet);
avrcp_con_handle = avrcp_subevent_connection_established_get_con_handle(packet); avrcp_con_handle = avrcp_subevent_connection_established_get_con_handle(packet);
local_cid = avrcp_subevent_connection_established_get_local_cid(packet);
avrcp_subevent_connection_established_get_bd_addr(packet, event_addr); avrcp_subevent_connection_established_get_bd_addr(packet, event_addr);
printf("Channel successfully opened: %s, handle 0x%02x, local cid 0x%02x\n", bd_addr_to_str(event_addr), avrcp_con_handle, local_cid); printf("Channel successfully opened: %s, handle 0x%02x, local cid 0x%02x\n", bd_addr_to_str(event_addr), avrcp_con_handle, local_cid);
// automatically enable notifications // automatically enable notifications
avrcp_enable_notification(avrcp_con_handle, AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED); avrcp_enable_notification(avrcp_con_handle, AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED);
//avrcp_enable_notification(avrcp_con_handle, AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED); avrcp_enable_notification(avrcp_con_handle, AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED);
return; return;
} }
case AVRCP_SUBEVENT_CONNECTION_RELEASED: case AVRCP_SUBEVENT_CONNECTION_RELEASED:
printf("Channel released: con_handle 0x%02x\n", avrcp_subevent_connection_released_get_con_handle(packet)); printf("Channel released: avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet));
avrcp_con_handle = 0; avrcp_cid = 0;
return; return;
default: default:
break; break;
@ -233,99 +239,99 @@ static void stdin_process(char cmd){
switch (cmd){ switch (cmd){
case 'c': case 'c':
printf(" - Create AVRCP connection to addr %s.\n", bd_addr_to_str(device_addr)); printf(" - Create AVRCP connection to addr %s.\n", bd_addr_to_str(device_addr));
avrcp_connect(device_addr); avrcp_connect(device_addr, &avrcp_cid);
break; break;
case 'D': case 'D':
printf(" - Disconnect\n"); printf(" - Disconnect\n");
avrcp_disconnect(avrcp_con_handle); avrcp_disconnect(avrcp_cid);
break; break;
case 'i': case 'i':
printf(" - get play status\n"); printf(" - get play status\n");
avrcp_get_play_status(avrcp_con_handle); avrcp_get_play_status(avrcp_cid);
break; break;
case 'j': case 'j':
printf(" - get now playing info\n"); printf(" - get now playing info\n");
avrcp_get_now_playing_info(avrcp_con_handle); avrcp_get_now_playing_info(avrcp_cid);
break; break;
case 'k': case 'k':
printf(" - play\n"); printf(" - play\n");
avrcp_play(avrcp_con_handle); avrcp_play(avrcp_cid);
break; break;
case 'K': case 'K':
printf(" - stop\n"); printf(" - stop\n");
avrcp_stop(avrcp_con_handle); avrcp_stop(avrcp_cid);
break; break;
case 'L': case 'L':
printf(" - pause\n"); printf(" - pause\n");
avrcp_pause(avrcp_con_handle); avrcp_pause(avrcp_cid);
break; break;
case 'm': case 'm':
printf(" - start fast forward\n"); printf(" - start fast forward\n");
avrcp_start_fast_forward(avrcp_con_handle); avrcp_start_fast_forward(avrcp_cid);
break; break;
case 'M': case 'M':
printf(" - stop fast forward\n"); printf(" - stop fast forward\n");
avrcp_stop_fast_forward(avrcp_con_handle); avrcp_stop_fast_forward(avrcp_cid);
break; break;
case 'n': case 'n':
printf(" - start rewind\n"); printf(" - start rewind\n");
avrcp_start_rewind(avrcp_con_handle); avrcp_start_rewind(avrcp_cid);
break; break;
case 'N': case 'N':
printf(" - stop rewind\n"); printf(" - stop rewind\n");
avrcp_stop_rewind(avrcp_con_handle); avrcp_stop_rewind(avrcp_cid);
break; break;
case 'o': case 'o':
printf(" - forward\n"); printf(" - forward\n");
avrcp_forward(avrcp_con_handle); avrcp_forward(avrcp_cid);
break; break;
case 'O': case 'O':
printf(" - backward\n"); printf(" - backward\n");
avrcp_backward(avrcp_con_handle); avrcp_backward(avrcp_cid);
break; break;
case 'p': case 'p':
printf(" - volume up\n"); printf(" - volume up\n");
avrcp_volume_up(avrcp_con_handle); avrcp_volume_up(avrcp_cid);
break; break;
case 'P': case 'P':
printf(" - volume down\n"); printf(" - volume down\n");
avrcp_volume_down(avrcp_con_handle); avrcp_volume_down(avrcp_cid);
break; break;
case 'r': case 'r':
printf(" - absolute volume of 50 percent\n"); printf(" - absolute volume of 50 percent\n");
avrcp_set_absolute_volume(avrcp_con_handle, 50); avrcp_set_absolute_volume(avrcp_cid, 50);
break; break;
case 's': case 's':
printf(" - mute\n"); printf(" - mute\n");
avrcp_mute(avrcp_con_handle); avrcp_mute(avrcp_cid);
break; break;
case 't': case 't':
printf(" - skip\n"); printf(" - skip\n");
avrcp_skip(avrcp_con_handle); avrcp_skip(avrcp_cid);
break; break;
case 'u': case 'u':
printf(" - query repeat and shuffle mode\n"); printf(" - query repeat and shuffle mode\n");
avrcp_query_shuffle_and_repeat_modes(avrcp_con_handle); avrcp_query_shuffle_and_repeat_modes(avrcp_cid);
break; break;
case 'v': case 'v':
printf(" - repeat single track\n"); printf(" - repeat single track\n");
avrcp_set_repeat_mode(avrcp_con_handle, AVRCP_REPEAT_MODE_SINGLE_TRACK); avrcp_set_repeat_mode(avrcp_cid, AVRCP_REPEAT_MODE_SINGLE_TRACK);
break; break;
case 'x': case 'x':
printf(" - repeat all tracks\n"); printf(" - repeat all tracks\n");
avrcp_set_repeat_mode(avrcp_con_handle, AVRCP_REPEAT_MODE_ALL_TRACKS); avrcp_set_repeat_mode(avrcp_cid, AVRCP_REPEAT_MODE_ALL_TRACKS);
break; break;
case 'X': case 'X':
printf(" - disable repeat mode\n"); printf(" - disable repeat mode\n");
avrcp_set_repeat_mode(avrcp_con_handle, AVRCP_REPEAT_MODE_OFF); avrcp_set_repeat_mode(avrcp_cid, AVRCP_REPEAT_MODE_OFF);
break; break;
case 'z': case 'z':
printf(" - shuffle all tracks\n"); printf(" - shuffle all tracks\n");
avrcp_set_shuffle_mode(avrcp_con_handle, AVRCP_SHUFFLE_MODE_ALL_TRACKS); avrcp_set_shuffle_mode(avrcp_cid, AVRCP_SHUFFLE_MODE_ALL_TRACKS);
break; break;
case 'Z': case 'Z':
printf(" - disable shuffle mode\n"); printf(" - disable shuffle mode\n");
avrcp_set_shuffle_mode(avrcp_con_handle, AVRCP_SHUFFLE_MODE_OFF); avrcp_set_shuffle_mode(avrcp_cid, AVRCP_SHUFFLE_MODE_OFF);
break; break;
default: default:
show_usage(); show_usage();
@ -337,7 +343,6 @@ int btstack_main(int argc, const char * argv[]);
int btstack_main(int argc, const char * argv[]){ int btstack_main(int argc, const char * argv[]){
UNUSED(argc); UNUSED(argc);
(void)argv; (void)argv;
avrcp_con_handle = 0;
/* Register for HCI events */ /* Register for HCI events */
hci_event_callback_registration.callback = &packet_handler; hci_event_callback_registration.callback = &packet_handler;
hci_add_event_handler(&hci_event_callback_registration); hci_add_event_handler(&hci_event_callback_registration);