⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ag_servicerecord.c

📁 bluetooth audio gateway
💻 C
字号:
#include "ag_private.h"
#include "ag.h"

#include <message.h>
#include <sdp_parse.h>
#include <stdlib.h>
#include <string.h>



/*
    This structure defines the service record for the Audio Gateway;
    it contains a blank space for the RFCOMM server channel since this
    will be filled in at run time.

    Note that attrIds are specified as being 16 bit ints.
*/
static const uint8 serviceRecord[] =
{
    /* Service class ID list */
    0x09,0x00,0x01, /* AttrID , ServiceClassIDList */
    0x35,0x06, /* 6 bytes in total DataElSeq */
    0x19,0x00,0x00,/* 2 byte UUID, Service class = Voice gateway */
    0x19,0x12,0x03,/* 2 byte UUID Service class = GenericAudio */
    
    /* protocol descriptor list */
    0x09,0x00,0x04,/* AttrId ProtocolDescriptorList */
    0x35,0x0c, /* 12 bytes in total DataElSeq */
    0x35,0x03, /*3 bytes in DataElSeq */
    0x19, 0x01,0x00,/* 2 byte UUID, Protocol = L2CAP */
    
    0x35,0x05, /* 5 bytes in DataElSeq */
    0x19, 0x00, 0x03,   /* 1 byte UUID Protocol = RFCOMM */
    0x08, 0x00, /* 1 byte UINT - server channel template value 0 - to be filled in by app */    
    
    /* profile descriptor list */
    0x09,0x00,0x09, /* AttrId, ProfileDescriptorList */
    0x35,0x08, /* 8 bytes in total DataElSeq */
    0x35,0x06, /* 6 bytes in total DataElSeq */
    0x19, 0x00,0x00, /* 2 byte UUID, Service class = Voice gateway */
    0x09, 0x01,0x00, /* 2 byte uint, version = 100 */
    
    /* service name */
    0x09, 0x01, 0x00, /* AttrId - Service Name */
    0x25, 0x0D, /* 13 byte string */
    'V','o','i','c','e',' ','G','a','t','e','w','a','y'            
};


static const uint8 handsFreeExtra[] =
{
    /* Network */
    0x09, 0x03, 0x01, /* AttrID - Network */
    0x08, 0x00,       /* 1 byte UINT - GSM like */

    /* Supported Features (init to profile defaults) */
    0x09, 0x03, 0x11,   /* AttrId - Supported Features */
    0x09, 0x00, 0x09    /* 2 byte UINT - Supported features */
                        /* 3 way calls              - 1 (LSB) */
                        /* EC and/or NR fn          - 0 */
                        /* Voice recognition fn     - 0 */
                        /* In-band ring tone        - 1 */
                        /* Attach phone num to tag  - 0 */
};


/*
    customizeServiceRecord

    Fill in the profile specific fields in the service record
*/
static uint16 customizeServiceRecord(uint16 *len, uint8 **s_ptr, ag_profile_role_t dev_type)
{
    uint8_t *ptr;
    uint8_t *endptr;
    
    /* Set the ptrs for sdp_parse function calls */
    ptr = *s_ptr;
    endptr = ptr + *len;
    
    /* start by looking for the first UUID as this is the service class */
    ptr = SdpFindElement(SDP_TYPE_UUID, ptr, endptr);
        
    /* Check for null ptr access and return 0 to indicate something is wrong */
    if (!ptr)            
        return 0;    

    /* write the service class and move on from that element */
    if (dev_type == agHeadsetProfile)
    {
        SdpSetData(ptr, (uint32_t) 0x1112);
    }
    else if (dev_type == agHandsFreeProfile)
    {
        /* device must be hands free or we wouldn't get this far */
        SdpSetData(ptr, (uint32_t) 0x111F);
    }
	else
	{
		return 0;
	}
    
    /* Skip the next UUIDs until we reach the one we're interested in */
    for(;;)
    {     
        /* Find the next UUID */
        ptr = SdpFindElement(SDP_TYPE_UUID, ptr, endptr);
        
        if (!ptr)
            return 0;
        
            /* 
            We're looking for the UUID after the RFCOMM UUID but unfortunately
            it hasn't been set yet so we can't look for it directly
        */
        if (SdpGetData(ptr) == SDP_UUID_RFCOMM)
        {            
            ptr = SdpSkipElement(ptr);
            ptr = SdpFindElement(SDP_TYPE_UUID, ptr, endptr);
            if (ptr)
            {
                if (dev_type == agHeadsetProfile)                 
                {
                    SdpSetData(ptr, (uint32_t) 0x1108);                        
                }
                else if (dev_type == agHandsFreeProfile)                    
                {
                    SdpSetData(ptr, (uint32_t) 0x111E);                        
                    
                    /* 
                    For hands free profile also need to insert the supported features
                    the external driver passed in 
                    */    
                    ptr = SdpFindElement(SDP_TYPE_STR, ptr, endptr);
                    ptr = SdpSkipElement(ptr);
                    ptr = SdpFindElement(SDP_TYPE_UINT, ptr, endptr);
                    ptr = SdpSkipElement(ptr);
                    
                    if (!ptr)
                        return 0;
                    
                    /* Set the network type */
                    SdpSetData(ptr, (uint32_t) (AGState.hfAgSupportedFeatures>>8));        
                    
                    /* Skip along */
                    ptr = SdpSkipElement(ptr);
                    
                    /* Find the next uint that contains the supported features */
                    ptr = SdpFindElement(SDP_TYPE_UINT, ptr, endptr);          
                    ptr = SdpSkipElement(ptr);
                    
                    if (!ptr)
                        return 0;
                    
                    /* Only the 5 LSBs of the LSW are valid so mask the rest off */
                    SdpSetData(ptr, (uint32_t) (AGState.hfAgSupportedFeatures & 0x001f));
                }
                else                
                {
                    return 0;
                }
                
                break ;
            }
        }
        else
        {
            /* Skip to the next element and try our luck there */
            ptr = SdpSkipElement(ptr);
        }
    }           

    return 1;
}


/*
    agCreateServiceRecord 

    Create a copy of the service record; the Connection Manager will
    fill in the RFCOMM channel for us since it knows about such things
    we need to supply the length of the record also.
*/
uint8 *agCreateServiceRecord(uint16 *len, ag_profile_role_t dev_type)
{
    uint8 *sr_ptr = 0;
    uint16 sr_len=0;
    uint16 return_flag = 1;

    /* 
        Copy the relevant service record. Note that the hands free one record
        has a number of extra fields so needs to be handled separately 
    */
    if (dev_type == agHeadsetProfile)
    {
        sr_len = sizeof(serviceRecord);
        sr_ptr = (uint8 *)agAlloc(sr_len);
        memcpy(sr_ptr,(void*) serviceRecord, sr_len);
        *len = sr_len;        

        /* Fill in the headset specific fields into the service record */
        if (!customizeServiceRecord(len, &sr_ptr, agHeadsetProfile))
            return_flag = 0;        
    }
    else if (dev_type == agHandsFreeProfile)
    {
        sr_len = sizeof(serviceRecord) + sizeof(handsFreeExtra);
        sr_ptr = (uint8 *)agAlloc(sr_len);
        memcpy(sr_ptr, (void*) serviceRecord, sizeof(serviceRecord));
        memcpy(sr_ptr+sizeof(serviceRecord), (void*) handsFreeExtra, sizeof(handsFreeExtra));
        *len = sr_len;

        /* Fill in the hands free specific fields into the service record */
        if (!customizeServiceRecord(len, &sr_ptr, agHandsFreeProfile))
            return_flag = 0;
    }
    else
    {
        /* Unknown ervice type requested */        
        return_flag = 0;
    }
        
    if (!return_flag)
    {
        /* Failed to create the service record */
        *len = 0;
        free(sr_ptr);
        return 0;
    }
    
    return sr_ptr;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -