コード例 #1
0
bool connectionAddTaskMap(conn_type type, map_id id, Task task, const profile_task_recipe *recipe)
{
	uint16 match_index;

	/* Check to see if we already have this entry if we do return false */
	if (findMatchInMap(type, id, &match_index))
    {
		return FALSE;
    }
	else
	{
		/* Create a new map array */
		conn_task_map new_map;
		new_map.type = type;        
		new_map.id = id;
        new_map.appTask = task;
        new_map.task_recipe = recipe;

		/* Allocate one more element in the array  - initially map_ptr should be null */
		map = (conn_task_map *) PanicNull(realloc(map, (sizeof(conn_task_map) * (mapSize+1))));

		/* Add new element */
		map[mapSize] = new_map;

		/* Don't forget to increment the size count */
		mapSize++;

		/* New element added successfully! */
		return TRUE;
	}
}
コード例 #2
0
static void deleteElement(uint16 match_index)
{
	conn_task_map *new_map;

	/* Reduce the size by one */
	mapSize--;

	/* Realocate the array with one fewer element */
	new_map = (conn_task_map *) PanicNull(malloc(sizeof(conn_task_map) * mapSize));

	/* Copy all the elements apart from the one being deleted */
	if (match_index == 0)
	{
		memmove(new_map, map+1, sizeof(conn_task_map)*mapSize);
	}
	else
	{
		/* Copy the elements before the one being remove */
		memmove(new_map, map, sizeof(conn_task_map)*match_index);

		/* Copy the elements after the one being removed if its not the last one */
		if ((mapSize-match_index) > 0)
			memmove(new_map+match_index, map+match_index+1, sizeof(conn_task_map)*(mapSize-match_index));
	}

	/* Free the old map array */
	free(map);

	/* Need to point to the new one */
	map = new_map;
}
コード例 #3
0
/*************************************************************************
NAME    
    gattHandleInternalExecuteWriteReq
    
DESCRIPTION
    This function is handler for GATT_INTERNAL_EXECUTE_WRITE_REQ internal
    message.
    
RETURNS
    
*/
void gattHandleInternalExecuteWriteReq(GATT_INTERNAL_EXECUTE_WRITE_REQ_T *m)
{
    cid_map_t *conn = PanicNull(gattFindConn(m->common.cid)); /* never NULL */
    
    gattSetConnState(conn, m->common.task, gatt_ms_execute_write);
    gatt_execute_write_req(m->common.cid, m->flags);
}
コード例 #4
0
static void send_pio_timed_message(PioState *pioState, const TimedMessage *p, int hold_repeat)
{
    const TimedMessage **m = (const TimedMessage **) PanicNull(malloc(sizeof(const TimedMessage *)));
    *m = p;
    if (hold_repeat)
        MessageSendLater(&pioState->task, internal_pio_timer_message, m, p->msecRepeat);
    else
        MessageSendLater(&pioState->task, internal_pio_timer_message, m, p->msec);
}
コード例 #5
0
/*************************************************************************
NAME    
    gattHandleInternalWriteReq
    
DESCRIPTION
    This function is handler for GATT_INTERNAL_WRITE_REQ internal message.
    
RETURNS
    
*/
void gattHandleInternalWriteReq(GATT_INTERNAL_WRITE_REQ_T *m)
{
    cid_map_t *conn = PanicNull(gattFindConn(m->common.cid)); /* never NULL */
    STASH(conn, stash, WRITE_CHARACTERISTIC_VALUE);
    uint16 flags;

    switch (m->id)
    {
#if (GATT_FEATURES & GATT_WRITE_COMMAND)        
        case gatt_ms_write_without_response:
            flags = ATT_WRITE_COMMAND;
            break;
#endif

#if (GATT_FEATURES & GATT_WRITE_SIGNED)
        case gatt_ms_signed_write_without_response:
            flags = ATT_WRITE_COMMAND | ATT_WRITE_SIGNED;
            break;
#endif
            
#if (GATT_FEATURES & GATT_WRITE)
        case gatt_ms_write_characteristic_value:
            flags = ATT_WRITE_REQUEST;
            break;
#endif

#if (GATT_FEATURES & GATT_WRITE_LONG)
        case gatt_ms_write_long_characteristic_value:
            handleInternalWriteReqLong(conn, m);
            return;
#endif
            
#if (GATT_FEATURES & GATT_WRITE_RELIABLE)
        case gatt_ms_prepare_write:
            handleInternalWriteReqPrepare(conn, m);
            return;
#endif
            
        default:
            /* horror error which can't happen, ever. */
            flags = 0;
            Panic();
            
    }
    
    gattSetConnState(conn, m->common.task, m->id);

    gatt_write_req(m->common.cid, m->handle, flags, m->size_value, m->value);

    /* Create the response message */
    MAKE_STASH(conn, stash, WRITE_CHARACTERISTIC_VALUE);

    stash->cid = m->common.cid;
    stash->handle = m->handle;    
}
コード例 #6
0
/****************************************************************************
NAME	
    inquiryAddEirData

PARAMS
    [IN/OUT] size_eir_data  Current size of the eir_data
    [OUT]    eir_data       Buffer into which the EIR data needs to be copied
    [IN]     size_data      Length of data to be copied
    [IN]     eir_data_part  Array from which the data needs to be copied from

DESCRIPTION
    Copy a block of data from an eir data part to the eir result.

RETURNS
    
*/
static uint8* inquiryAddEirData(uint8* size_eir_data, uint8* eir_data,
        uint8 size_data, const uint8* eir_data_part)
{
    /* Allocate space for the new data in result */
    uint8* result = PanicNull( realloc(eir_data, (*size_eir_data) + size_data) );
    /* Copy data from data part to result */
    memmove( (result + (*size_eir_data)), eir_data_part, size_data );
    /* Update size */
    *size_eir_data += size_data;
    
    return result;
}
コード例 #7
0
ファイル: gatt_init.c プロジェクト: stephen-kun/koovox_adk4.0
/****************************************************************************
NAME
    gattLockCid

DESCRIPTION
    Lock on CID for an active message scenario. New scenarios can't start 
    until the current one is complete and the CID unlocked.

RETURNS

*/
bool gattLockCid(uint16 cid,  gatt_msg_scen_t scenario)
{
    cid_map_t *ptr = (cid_map_t *)PanicNull(gattFindConn(cid));

    if (ptr->data.scenario)
    {
        return FALSE;   /* CID is already mapped to a scenario */
    }
    else
    {
        ptr->data.scenario = scenario;
    }
    return TRUE;
}
コード例 #8
0
/*************************************************************************
NAME    
    gattHandleInternalDiscoverAllDescriptorsReq
    
DESCRIPTION
    This function is handler for GATT_DISCOVER_ALL_DESCRIPTORS_REQ
    internal message.
    
RETURNS
    
*/
void gattHandleInternalDiscoverAllDescriptorsReq(
    GATT_INTERNAL_DISCOVER_ALL_DESCRIPTORS_REQ_T *m)
{
    cid_map_t *conn = PanicNull(gattFindConn(m->common.cid)); /* never NULL */
    
    gattSetConnState(conn, m->common.task, gatt_ms_discover_all_descriptors);

    conn->data.req.discover_all_descriptors.start = m->start;
    conn->data.req.discover_all_descriptors.end = m->end;
    
    gatt_find_info_req(m->common.cid,
                       conn->data.req.discover_all_descriptors.start,
                       conn->data.req.discover_all_descriptors.end);
}
コード例 #9
0
/****************************************************************************
NAME
    scanKickInquiryScan

DESCRIPTION
    Starts inquiry process.
    
*/
void scanKickInquiryScan (void)
{
    DEBUG_SCAN(("Kick inquiry scan\n"));
    the_app->remote_profiles = ProfileNone;
    if ( s_inquiry_scan_data == NULL )
    {
        s_inquiry_scan_data = (mvdInquiryScanData *)malloc( sizeof(mvdInquiryScanData) );
        PanicNull( s_inquiry_scan_data );
    }
    s_inquiry_scan_data->read_idx = 0;
    s_inquiry_scan_data->write_idx = 0;
    
    ConnectionInquire(&the_app->task, 0x9e8b33, INQUIRY_SCAN_BUFFER_SIZE, 4, (uint32)AV_MAJOR_DEVICE_CLASS);
}
コード例 #10
0
ファイル: swat_init.c プロジェクト: stephen-kun/csr8670
void SwatInit(Task clientTask, uint16 max_remote_devs, swat_role role, bool auto_handle, const uint8 *service_record, uint16 size_service_record, const sync_config_params * esco_config)
{
    /* Attempt to initialise the task data */
    if ( !swat )
    {
        swat = PanicUnlessNew(swatTaskData);
        memset( swat, 0, sizeof(swatTaskData) );
        
        SWAT_DEBUG(("[SWAT] Sizeof(swatTaskData) = %u\n", sizeof(swatTaskData)));
        
        /* Initialise the swat profile data */
        swat->l2cap_task.handler = swatL2capHandler;
        swat->profile_task.handler = swatProfileHandler;
        swat->command_task.handler = swatCommandHandler;
        swat->clientTask = clientTask;
        swat->auto_handle = auto_handle;
        swat->role = role;
        swat->max_remote_devs = max_remote_devs;

        /* Allocate memory to store remote device data depending on number of allowed devices */
        swat->remote_devs = (remoteDevice *)PanicNull(malloc(max_remote_devs * sizeof(remoteDevice)));
        memset(swat->remote_devs, 0, (max_remote_devs * sizeof(remoteDevice)));
        
        /* Use service record supplied by client */
        if (service_record)
        {
            ConnectionRegisterServiceRecord(&swat->l2cap_task, (sizeof(uint8) * size_service_record), service_record);
        }
        /* Use library default service record */
        else
        {
            ConnectionRegisterServiceRecord(&swat->l2cap_task, sizeof(swat_service_record), swat_service_record);
        }
        
        /* Use eSCO config supplied by client */
        if (esco_config)
        {
            swat->esco_config = esco_config;
        }
        else
        {
            swat->esco_config = NULL;
        }
    }
    else
    {
        swatSendInitCfmToClient(swat_init_failed);
    }
}
コード例 #11
0
ファイル: gatt_init.c プロジェクト: stephen-kun/koovox_adk4.0
/****************************************************************************
NAME
    gattUnlockCid

DESCRIPTION
    Clear data associated with a message scenario locking on a CID. 

RETURNS

*/
void gattUnlockCid(uint16 cid)
{
    cid_map_t *ptr = (cid_map_t *)PanicNull(gattFindConn(cid));

#if GATT_DEBUG_LIB
    if (!ptr->data.scenario)
    {
        printf("gattUnlockCid: No scenario associated with CID\n");
        Panic();
    }
#endif

    /* clear associated connection data. */
    free(ptr->data.stash);
    memset( &ptr->data, 0, sizeof(conn_data_t) );
}
コード例 #12
0
/*************************************************************************
NAME    
    gattHandleAttFindInfoCfm
    
DESCRIPTION
    This function handles Bluestack response for ATT_FIND_INFO_REQ.
    
RETURNS
    
*/
void gattHandleAttFindInfoCfm(ATT_FIND_INFO_CFM_T *m)
{
    cid_map_t *conn = PanicNull(gattFindConn(m->cid)); /* never NULL */
    STASH(conn, stash, DISCOVER_ALL_CHARACTERISTIC_DESCRIPTORS);
    bool more;
    bool send;

    if (!gatt_message_prepare(
            conn,
            &more, &send, m->result,
            m->handle >= conn->data.req.discover_all_descriptors.end,
            stash ? &stash->more_to_come : NULL,
            GATT_DISCOVER_ALL_CHARACTERISTIC_DESCRIPTORS_CFM))
    {
        return;
    }

    /* Create the message */
    MAKE_STASH(conn, stash, DISCOVER_ALL_CHARACTERISTIC_DESCRIPTORS);

    stash->cid = m->cid;
    stash->handle = m->handle;
    stash->uuid_type = m->uuid_type;
    memmove(stash->uuid, m->uuid, GATT_UUID_SIZE);
    stash->more_to_come = more;
    stash->status = gatt_message_status(m->result);
    
    /* schedule new round for getting more information */
    if (!send)
    {
        gatt_find_info_req(m->cid,
                           m->handle + 1,
                           conn->data.req.discover_all_descriptors.end);
    }
    
    /* only sent the message if we are not waiting for more information */
    else
    {
        gatt_message_send(conn,
                          GATT_DISCOVER_ALL_CHARACTERISTIC_DESCRIPTORS_CFM);

        if (!more)
        {
            gattSetConnState(conn, NULL, gatt_ms_none);
        }
    }
}
コード例 #13
0
/****************************************************************************
NAME	
	aghfpHandleSyncConnectInd

DESCRIPTION
	Incoming audio notification, accept if we recognise the sink reject
	otherwise.

RETURNS
	void
*/
void aghfpHandleSyncConnectInd(AGHFP *aghfp, const CL_DM_SYNC_CONNECT_IND_T *ind)
{
    uint16 i=0;
    uint16 my_audio = 0;
    uint16 num_sinks = 5;
    tp_bdaddr tp_addr = { {TYPED_BDADDR_PUBLIC, { 0, 0, 0 }}, TRANSPORT_BREDR_ACL};

    /* Sink array to store the sinks on the acl. */
    Sink *all_sinks = (Sink *)PanicNull(calloc(num_sinks, sizeof(Sink))); 

    tp_addr.taddr.addr = ind->bd_addr;

    if(StreamSinksFromBdAddr(&num_sinks, all_sinks, &tp_addr))
    {
        for (i=0; i<num_sinks; i++)
        {
            /* Make sure this profile instance owns the unlerlying sink */
            if (all_sinks[i] && all_sinks[i] == aghfp->rfcomm_sink)
            {
                my_audio = 1;
                break;
            }
        }
    }

    free(all_sinks);    

    /* If this is our audio connection then ask the app, otherwise reject outright */
    if (my_audio)
    {
        MAKE_AGHFP_MESSAGE(AGHFP_AUDIO_CONNECT_IND);
    	message->aghfp = aghfp;
		message->bd_addr = ind->bd_addr;
    	MessageSend(aghfp->client_task, AGHFP_AUDIO_CONNECT_IND, message);

        aghfp->audio_connection_state = aghfp_audio_accepting;
    }
    else
    {
        ConnectionSyncConnectResponse(&aghfp->task, &ind->bd_addr, FALSE, 0);
    }
}
コード例 #14
0
/****************************************************************************
NAME 
    powerManagerConfig

DESCRIPTION
    Initialise the power handling.
    
*/
bool powerManagerConfig(const power_config_type* config)
{
    bool success = TRUE;
          
    the_app->power = (power_type *)malloc(sizeof(power_type));
      
    PanicNull(the_app->power);
    
    if (config)
    {
        /* Store power configuration */
        the_app->power->config = *config;
    }
    else
    {
        success = FALSE;
    }

    return success;
}
コード例 #15
0
/*************************************************************************
NAME    
    gattHandleAttWriteCfm
    
DESCRIPTION
    This function handles Bluestack response for ATT_WRITE_REQ.
    
RETURNS
    
*/
void gattHandleAttWriteCfm(ATT_WRITE_CFM_T *m)
{
    cid_map_t *conn = PanicNull(gattFindConn(m->cid)); /* never NULL */
    STASH(conn, stash, WRITE_CHARACTERISTIC_VALUE);
    uint16 id;

    stash->status = gatt_message_status(m->result);

    switch (conn->data.scenario)
    {
#if (GATT_FEATURES & GATT_WRITE_COMMAND)
        case gatt_ms_write_without_response:
            id = GATT_WRITE_WITHOUT_RESPONSE_CFM;
            break;
#endif

#if (GATT_FEATURES & GATT_WRITE_SIGNED)
        case gatt_ms_signed_write_without_response:
            id = GATT_SIGNED_WRITE_WITHOUT_RESPONSE_CFM;
            break;
#endif

#if (GATT_FEATURES & GATT_WRITE)
        case gatt_ms_write_characteristic_value:
            id = GATT_WRITE_CHARACTERISTIC_VALUE_CFM;
            break;
#endif
            
        default:
            /* horror error which can't happen, ever. */
            id = 0;
            Panic();
    }
    
    gatt_message_send(conn, id);

    gattSetConnState(conn, NULL, gatt_ms_none);
}
コード例 #16
0
/*************************************************************************
NAME    
    gattHandleAttExecuteWriteCfm
    
DESCRIPTION
    This function handles Bluestack response for ATT_EXECUTE_WRITE_REQ.
    
RETURNS
    
*/
void gattHandleAttExecuteWriteCfm(ATT_EXECUTE_WRITE_CFM_T *m)
{
    cid_map_t *conn = PanicNull(gattFindConn(m->cid)); /* never NULL */

    switch (conn->data.scenario)
    {
#if (GATT_FEATURES & GATT_WRITE_LONG)
        case gatt_ms_write_long_characteristic_value:
            handleAttExecuteWriteCfmLong(conn, m);
            return;
#endif
            
#if (GATT_FEATURES & GATT_WRITE_RELIABLE)
        case gatt_ms_execute_write:
            handleAttExecuteWriteCfmExecute(conn, m);
            return;
#endif
            
        default:
            /* horror error which can't happen, ever. */
            Panic();            
    }
}
コード例 #17
0
/****************************************************************************
NAME    
    inquiryParseEir

DESCRIPTION
    Take the EIR data structure received from bluestack and concat the data 
	into a single block to send to the application

RETURNS
    A pointer to a single block containing the EIR data and the size of the 
	eir data
*/
static uint8* inquiryParseEir(uint8* size_eir_data, uint8 *inquiry_data[HCI_EIR_DATA_PACKET_PTRS], bool limit_data_size)
{
    /* Data Part */
    uint8 i = 0;                    /* Index into inquiry_data */
    uint8 size_data_part;           /* Size un-parsed data left in current part */
    uint8* eir_data_part;           /* Pointer to start of un-parsed data */
    uint8* eir_data_part_base;      /* Pointer to base of the current data part */
	
    /* Field Data */
    uint8 size_field;               /* Size of the field we're parsing */
    bool limit_exceeded;            /* If the field should be written */
	
    /* Result */
    uint8* eir_data = NULL;         /* Parsed EIR Data */
    *size_eir_data  = 0;            /* Size of Parsed Data */
	
    /* Return early if we have nothing to parse */
    if(inquiry_data[0] == NULL)
		{
        return eir_data;
    }
		
    /* Setup First Data Part */
    size_data_part = HCI_EIR_DATA_BYTES_PER_PTR;
    eir_data_part_base = VmGetPointerFromHandle(inquiry_data[i]);
    eir_data_part = eir_data_part_base;
	
    /* Get the size of the first field */
    size_field = (*eir_data_part) + 1;
    limit_exceeded = (((*size_eir_data) + size_field) > MAX_EIR_DATA_SIZE);
		
    /* Keep going until we reach NULL terminator */
    while(*eir_data_part != 0)
    {
        /* If the field is all in this part */
        if(size_field < size_data_part)
        {
            /* Copy to the end of field */
            if(!limit_data_size || !limit_exceeded)
                eir_data = inquiryAddEirData(size_eir_data, eir_data, size_field, eir_data_part);
            /* Move to the next field */
            size_data_part -= size_field;
            eir_data_part += size_field;
            size_field = (*eir_data_part) + 1;
            limit_exceeded = (((*size_eir_data) + size_field) > MAX_EIR_DATA_SIZE);
        }
        /* Field is split over multiple parts */
        else
        {
            /* Copy to the end of the data part */
            if(!limit_data_size || !limit_exceeded)
                eir_data = inquiryAddEirData(size_eir_data, eir_data, size_data_part, eir_data_part);
	
            /* Check if there's any more data parts to go */
            if(inquiry_data[++i] != NULL)
            {
                /* We're finished with this part so free it */
                free(eir_data_part_base);
	
                /* Move to the next data part */
                size_field -= size_data_part;
                size_data_part = HCI_EIR_DATA_BYTES_PER_PTR;
                eir_data_part_base = VmGetPointerFromHandle(inquiry_data[i]);
                eir_data_part = eir_data_part_base;
	
                /* Update field size if new field */
                if(size_field == 0)
                {
                    size_field = (*eir_data_part) + 1;
                    limit_exceeded = (((*size_eir_data) + size_field) > MAX_EIR_DATA_SIZE);
                }
            }
            /* Out of data */
            else
            {
                /* Data part will be freed below, just break */
                break;
            }
        }
	}
	
    /* Free the final data part */
    free(eir_data_part_base);
            
    /* NULL Terminate Data */
    (*size_eir_data)++;
    eir_data = PanicNull( realloc(eir_data, *size_eir_data) );
    *(eir_data + (*size_eir_data) - 1) = 0;
    
	return eir_data;
}
コード例 #18
0
ファイル: gatt_init.c プロジェクト: stephen-kun/koovox_adk4.0
/****************************************************************************
NAME
    gattGetCidMappedTask

DESCRIPTION
    Returns the the task associated with the cid, the task that created the
    connection.

RETURNS
    Task ptr
*/
Task gattGetCidMappedTask(uint16 cid)
{
    cid_map_t *ptr = (cid_map_t *)PanicNull(gattFindConn(cid));
    return ptr->task;
}
コード例 #19
0
ファイル: a2dp_init.c プロジェクト: stephen-kun/koovox_adk4.0
void A2dpInit(Task clientTask, uint16 role, service_record_type *service_records, uint16 size_seps, sep_data_type *seps, uint16 linkloss_timeout)
{
    /* Initialise the task data */
    if ( !a2dp )
    {
        uint8 device_id;
        
        a2dp = PanicUnlessNew(A2DP);
        memset( a2dp, 0, sizeof(A2DP) );
        for (device_id=0; device_id<A2DP_MAX_REMOTE_DEVICES_DEFAULT; device_id++)
        {
            a2dpInitialiseRemoteDevice(&a2dp->remote_conn[device_id],device_id);
        }
        
        PRINT(("sizeof(A2DP)=0x%u\n", sizeof(A2DP)));
        
        /* Set the handler function */
        a2dp->task.handler = a2dpProfileHandler;
        /* Set up the lib client */
        a2dp->clientTask = clientTask;
        a2dp->linkloss_timeout = linkloss_timeout;
        a2dp->max_remote_devs = A2DP_MAX_REMOTE_DEVICES_DEFAULT;
        a2dp->profile_role = role;
        
        blockInit();
        
        if ( seps && size_seps && validateSeps(seps, size_seps) )
        {
            for (device_id=0; device_id<A2DP_MAX_REMOTE_DEVICES; device_id++)
            {
                sep_data_type *sep_list = (sep_data_type *)PanicNull( blockAdd( device_id, data_block_sep_list, size_seps, sizeof(sep_data_type) ) );
                memmove( sep_list, (sep_data_type *)seps, size_seps*sizeof(sep_data_type) );
            }
        }
        else
        {
            a2dpSendInitCfmToClient(a2dp_invalid_parameters);
            return;
        }
    
    
        /* Used to count the number of SDP records registered.  Decremented again by a2dpHandleSdpRegisterCfm() and will 
           kick off a call to a2dpRegisterL2cap() when it hits zero - i.e. all CFM messages for SDP regsitering process
           have been received.                                                                                           */
        a2dp->sdp_register_outstanding = 0;
        
        if (service_records)
        {
            if (service_records->size_service_record_a && service_records->service_record_a)
            {
                /* Client has supplied their own record so register it without checking */
                ConnectionRegisterServiceRecord(&a2dp->task, service_records->size_service_record_a, service_records->service_record_a);
                a2dp->sdp_register_outstanding++;
            }
            if (service_records->size_service_record_b && service_records->service_record_b)
            {
                /* Client has supplied their own record so register it without checking */
                ConnectionRegisterServiceRecord(&a2dp->task, service_records->size_service_record_b, service_records->service_record_b);
                a2dp->sdp_register_outstanding++;
            }
        }
        else
        {
            /* Client using default library record */
            if (role & A2DP_INIT_ROLE_SINK)
            {
                ConnectionRegisterServiceRecord(&a2dp->task, sizeof(a2dp_sink_service_record), a2dp_sink_service_record);
                PRINT(("Register Sink Service Rec\n"));
                a2dp->sdp_register_outstanding++;
            }
            if (role & A2DP_INIT_ROLE_SOURCE)
            {
                ConnectionRegisterServiceRecord(&a2dp->task, sizeof(a2dp_source_service_record), a2dp_source_service_record);
                PRINT(("Register Source Service Rec\n"));
                a2dp->sdp_register_outstanding++;
            }
        }
    
        if ( a2dp->sdp_register_outstanding==0 )
        {
            /* Skip the service record registering if the user doesn't require any at this point. */
            a2dpRegisterL2cap();
        }
    }
}
コード例 #20
0
/*************************************************************************
NAME    
    gattHandleAttReadByTypeCfmCharacteristic
    
DESCRIPTION
    This function handles Bluestack response for ATT_READ_BY_TYPE_REQ
    during Relationship Discovery.
    
RETURNS
    
*/
void gattHandleAttReadByTypeCfmCharacteristic(ATT_READ_BY_TYPE_CFM_T *m)
{
    cid_map_t *conn = PanicNull(gattFindConn(m->cid)); /* never NULL */
    STASH(conn, stash, DISCOVER_ALL_CHARACTERISTICS);
    uint8 *data;
    uint8 *p;
    bool more;
    bool send;

    p = data = VmGetPointerFromHandle(m->value);

    if (!gatt_message_prepare(conn,
                              &more, &send, m->result,
                              m->handle >= conn->data.req.discover_all_characteristics.end,
                              stash ? &stash->more_to_come : NULL,
                              GATT_DISCOVER_ALL_CHARACTERISTICS_CFM))
    {
        free(data);
        return;
    }

    /* Create the message */
    MAKE_STASH(conn, stash, DISCOVER_ALL_CHARACTERISTICS);

    stash->cid = m->cid;
    stash->more_to_come = more;
    stash->status = gatt_message_status(m->result);
    stash->declaration = m->handle;

    /* read values from the response */
    if (stash->status == ATT_RESULT_SUCCESS)
    {
        stash->properties = gatt_read8(&p);
        stash->handle = gatt_read16(&p);

        gatt_get_att_uuid(stash->uuid, &stash->uuid_type,
                          m->size_value - 3, p);

    }
    
    /* schedule new round for getting more information */
    if (!send)
    {
        gatt_read_by_type_req(m->cid,
                              m->handle + 1,
                              conn->data.req.discover_all_characteristics.end,
                              ATT_UUID16, &uuid_characteristic);
    }
    
    /* only sent the message if we are not waiting for more information */
    else
    {
        gatt_message_send(conn, GATT_DISCOVER_ALL_CHARACTERISTICS_CFM);

        if (!more)
        {
            gattSetConnState(conn, NULL, gatt_ms_none);
        }
    }
    
    free(data);
}
コード例 #21
0
/****************************************************************************
NAME
    gattHandleAttConnectCfm

DESCRIPTION
    Handles the ATT_CONNECT_CFM from BlueStack. Pass on the INITIATING state
    so that the app can 'disconnect' the CID before the connection is
    established.


    Also, unless prepared, an ATT_CONNECT_CFM can be received for an ATT over
    BR/EDR slave connection and the GATT library won't know what to do with
    it. In that case Panic in debug and ignore in default lib version.

RETURNS

*/
void gattHandleAttConnectCfm(gattState *theGatt, ATT_CONNECT_CFM_T *cfm)
{

    /* PENDING is received for a master BR/EDR connection, after INITIALISING
     * has already been received, so just ignore it.
     */
    if (L2CA_CONNECT_PENDING != cfm->result)
    {
        cid_map_t *conn;
        gatt_status_t status;
        Task theAppTask = theGatt->conn_req_task;
        typed_bdaddr taddr;

        BdaddrConvertTypedBluestackToVm(&taddr, &cfm->addrt);

        switch (cfm->result)
        {
        /* INITIATING is received for any BLE connection. This is when the
         * CID for the connection is known and can be passed to the app.
         */
        case L2CA_CONNECT_INITIATING:
            if ( !gattCidIsValid(cfm->cid) )
                gattAddCid(cfm->cid, theGatt->conn_req_task);

            gattLockCid(cfm->cid, gatt_ms_connect_req);
            status = gatt_status_initialising;
            break;

        case L2CA_CONNECT_SUCCESS:
            /* By the time the SUCCESS is received, the cid & task should
             * already be registered with GATT.
             */
            conn = PanicNull(gattFindConn(cfm->cid));
            theAppTask = conn->task;

            /* Clear the connection scenario lock for this cid.  */
            gattUnlockCid(cfm->cid);

            status = gatt_status_success;
            conn->mtu = cfm->mtu;
            theGatt->conn_req_task = 0;

            if (L2CA_CONFLAG_IS_LE(cfm->flags))
                conn->bredr = FALSE;
            else
                conn->bredr = TRUE;

            break;


        default:
            if ( (conn = gattFindConn(cfm->cid)) )
                theAppTask = conn->task;

            /* If we are responding to a BR/EDR connect and it failed
             * Don't clear the con_req_task, as an LE connection could
             * still be coming in.
             */
            if (!conn || conn->data.scenario != gatt_ms_connect_rsp)
                theGatt->conn_req_task = 0;

            status = gattConvertL2capConnectStatus(cfm->result);
            gattDeleteCid(cfm->cid);

            GATT_DEBUG_INFO((
                                "gattHandleAttConnectCfm: result 0x%x\n",
                                cfm->result
                            ));
            break;
        }

        /* theAppTask can be 0, if max BLE connections have been made. Send
         * cfm to task that initialised GATT instead.
         */
        if (!theAppTask)
            theAppTask = gattGetAppTask();

        gattSendConnectionCfm(
            theAppTask,
            status,
            &taddr,
            cfm->flags,
            cfm->mtu,
            cfm->cid
        );
    }
}