hfp_ag.c (5fd6f36099526806c27882ae7a0e3cfa50950641) hfp_ag.c (aa10b9cbee75a92ba10686b7ba42c869ecdf5325)
1/*
2 * Copyright (C) 2014 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

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

2608 hfp_ag_run();
2609}
2610
2611static void hfp_ag_hci_event_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
2612 hfp_handle_hci_event(packet_type, channel, packet, size, HFP_ROLE_AG);
2613 hfp_ag_run();
2614}
2615
1/*
2 * Copyright (C) 2014 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

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

2608 hfp_ag_run();
2609}
2610
2611static void hfp_ag_hci_event_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
2612 hfp_handle_hci_event(packet_type, channel, packet, size, HFP_ROLE_AG);
2613 hfp_ag_run();
2614}
2615
2616void hfp_ag_init_codecs(int codecs_nr, const uint8_t * codecs){
2617 if (codecs_nr > HFP_MAX_NUM_CODECS){
2618 log_error("hfp_init: codecs_nr (%d) > HFP_MAX_NUM_CODECS (%d)", codecs_nr, HFP_MAX_NUM_CODECS);
2619 return;
2620 }
2621 int i;
2616void hfp_ag_init_codecs(uint8_t codecs_nr, const uint8_t * codecs){
2617 btstack_assert(codecs_nr <= HFP_MAX_NUM_CODECS);
2618
2622 hfp_ag_codecs_nr = codecs_nr;
2619 hfp_ag_codecs_nr = codecs_nr;
2620 uint8_t i;
2623 for (i=0; i < codecs_nr; i++){
2624 hfp_ag_codecs[i] = codecs[i];
2625 }
2626}
2627
2628void hfp_ag_init_supported_features(uint32_t supported_features){
2629 hfp_ag_supported_features = supported_features;
2630 hfp_ag_in_band_ring_tone_active = has_in_band_ring_tone();

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

3215 if (!hfp_connection->call_waiting_notification_enabled){
3216 return ERROR_CODE_COMMAND_DISALLOWED;
3217 }
3218
3219 hfp_connection->ag_notify_incoming_call_waiting = 1;
3220 hfp_ag_run_for_context(hfp_connection);
3221 return ERROR_CODE_SUCCESS;
3222}
2621 for (i=0; i < codecs_nr; i++){
2622 hfp_ag_codecs[i] = codecs[i];
2623 }
2624}
2625
2626void hfp_ag_init_supported_features(uint32_t supported_features){
2627 hfp_ag_supported_features = supported_features;
2628 hfp_ag_in_band_ring_tone_active = has_in_band_ring_tone();

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

3213 if (!hfp_connection->call_waiting_notification_enabled){
3214 return ERROR_CODE_COMMAND_DISALLOWED;
3215 }
3216
3217 hfp_connection->ag_notify_incoming_call_waiting = 1;
3218 hfp_ag_run_for_context(hfp_connection);
3219 return ERROR_CODE_SUCCESS;
3220}
3221void hfp_ag_create_sdp_record_with_codecs(uint8_t * service, uint32_t service_record_handle, int rfcomm_channel_nr,
3222 const char * name, uint8_t ability_to_reject_call, uint16_t supported_features,
3223 uint8_t codecs_nr, const uint8_t * codecs){
3224 if (!name){
3225 name = hfp_ag_default_service_name;
3226 }
3227 hfp_create_sdp_record(service, service_record_handle, BLUETOOTH_SERVICE_CLASS_HANDSFREE_AUDIO_GATEWAY, rfcomm_channel_nr, name);
3223
3228
3224void hfp_ag_create_sdp_record(uint8_t * service, uint32_t service_record_handle, int rfcomm_channel_nr, const char * name, uint8_t ability_to_reject_call, uint16_t supported_features, int wide_band_speech){
3225 if (!name){
3226 name = hfp_ag_default_service_name;
3227 }
3228 hfp_create_sdp_record(service, service_record_handle, BLUETOOTH_SERVICE_CLASS_HANDSFREE_AUDIO_GATEWAY, rfcomm_channel_nr, name);
3229 /*
3230 * 0x01 – Ability to reject a call
3231 * 0x00 – No ability to reject a call
3232 */
3233 de_add_number(service, DE_UINT, DE_SIZE_16, 0x0301); // Hands-Free Profile - Network
3234 de_add_number(service, DE_UINT, DE_SIZE_8, ability_to_reject_call);
3229
3235
3230 /*
3231 * 0x01 – Ability to reject a call
3232 * 0x00 – No ability to reject a call
3233 */
3234 de_add_number(service, DE_UINT, DE_SIZE_16, 0x0301); // Hands-Free Profile - Network
3235 de_add_number(service, DE_UINT, DE_SIZE_8, ability_to_reject_call);
3236 // Construct SupportedFeatures for SDP bitmap:
3237 //
3238 // "The values of the “SupportedFeatures” bitmap given in Table 5.4 shall be the same as the values
3239 // of the Bits 0 to 4 of the unsolicited result code +BRSF"
3240 //
3241 // Wide band speech (bit 5) and LC3-SWB (bit 8) require Codec negotiation
3242 //
3243 uint16_t sdp_features = supported_features & 0x1f;
3236
3244
3237 // Construct SupportedFeatures for SDP bitmap:
3238 //
3239 // "The values of the “SupportedFeatures” bitmap given in Table 5.4 shall be the same as the values
3240 // of the Bits 0 to 4 of the unsolicited result code +BRSF"
3241 //
3242 // Wide band speech (bit 5) requires Codec negotiation
3243 //
3244 uint16_t sdp_features = supported_features & 0x1f;
3245 if ( (wide_band_speech == 1) && (supported_features & (1 << HFP_AGSF_CODEC_NEGOTIATION))){
3246 sdp_features |= 1 << 5;
3247 }
3248
3249 if (supported_features & (1 << HFP_AGSF_ENHANCED_VOICE_RECOGNITION_STATUS)){
3250 sdp_features |= 1 << 6;
3251 }
3245 if (supported_features & (1 << HFP_AGSF_ENHANCED_VOICE_RECOGNITION_STATUS)){
3246 sdp_features |= 1 << 6;
3247 }
3252
3248
3253 if (supported_features & (1 << HFP_AGSF_VOICE_RECOGNITION_TEXT)){
3254 sdp_features |= 1 << 7;
3255 }
3249 if (supported_features & (1 << HFP_AGSF_VOICE_RECOGNITION_TEXT)){
3250 sdp_features |= 1 << 7;
3251 }
3256
3257 de_add_number(service, DE_UINT, DE_SIZE_16, 0x0311); // Hands-Free Profile - SupportedFeatures
3258 de_add_number(service, DE_UINT, DE_SIZE_16, sdp_features);
3252
3253 // codecs
3254 if ((supported_features & (1 << HFP_HFSF_CODEC_NEGOTIATION)) != 0){
3255 uint8_t i;
3256 for (i=0;i<codecs_nr;i++){
3257 switch (codecs[i]){
3258 case HFP_CODEC_MSBC:
3259 sdp_features |= 1 << 5;
3260 break;
3261 case HFP_CODEC_LC3_SWB:
3262 sdp_features |= 1 << 8;
3263 break;
3264 }
3265 }
3266 }
3267
3268 de_add_number(service, DE_UINT, DE_SIZE_16, 0x0311); // Hands-Free Profile - SupportedFeatures
3269 de_add_number(service, DE_UINT, DE_SIZE_16, sdp_features);
3259}
3260
3270}
3271
3272void hfp_ag_create_sdp_record(uint8_t * service, uint32_t service_record_handle, int rfcomm_channel_nr, const char * name,
3273 uint8_t ability_to_reject_call, uint16_t supported_features, int wide_band_speech){
3274 uint8_t codecs_nr;
3275 const uint8_t * codecs;
3276 const uint8_t wide_band_codecs[] = { HFP_CODEC_MSBC };
3277 if (wide_band_speech == 0){
3278 codecs_nr = 0;
3279 codecs = NULL;
3280 } else {
3281 codecs_nr = 1;
3282 codecs = wide_band_codecs;
3283 }
3284 hfp_ag_create_sdp_record_with_codecs(service, service_record_handle, rfcomm_channel_nr, name,
3285 ability_to_reject_call, supported_features, codecs_nr, codecs);
3286}
3287
3261void hfp_ag_register_packet_handler(btstack_packet_handler_t callback){
3262 btstack_assert(callback != NULL);
3263
3264 hfp_ag_callback = callback;
3265 hfp_set_ag_callback(callback);
3266}
3267
3268void hfp_ag_register_custom_call_sm_handler(bool (*handler)(hfp_ag_call_event_t event)){
3269 hfp_ag_custom_call_sm_handler = handler;
3270}
3271
3272void hfp_ag_register_custom_at_command(hfp_custom_at_command_t * custom_at_command){
3273 hfp_register_custom_ag_command(custom_at_command);
3274}
3288void hfp_ag_register_packet_handler(btstack_packet_handler_t callback){
3289 btstack_assert(callback != NULL);
3290
3291 hfp_ag_callback = callback;
3292 hfp_set_ag_callback(callback);
3293}
3294
3295void hfp_ag_register_custom_call_sm_handler(bool (*handler)(hfp_ag_call_event_t event)){
3296 hfp_ag_custom_call_sm_handler = handler;
3297}
3298
3299void hfp_ag_register_custom_at_command(hfp_custom_at_command_t * custom_at_command){
3300 hfp_register_custom_ag_command(custom_at_command);
3301}