/*
+-------------------------------------------------------------------+
| PROJECT: MMI-Framework (8445)		$Workfile:: mfw_bt_dm.c			$|
| $Author:: NDH						$Revision::  1						$|
| CREATED: 22.04.04					$Modtime:: 22.04.04 11:07			$|
| STATE  : code														 |
+-------------------------------------------------------------------+


   MODULE  : MFW_BT_DM

   PURPOSE : This module contains the functions for MFW Bluetooth Device Manager Profile


*/

#define ENTITY_MFW

#include <string.h>

#if defined (NEW_FRAME)

#include "typedefs.h"
#include "vsi.h"
#include "pei.h"
#include "custom.h"
#include "gsm.h"

#else

#include "STDDEFS.H"
#include "custom.h"
#include "gsm.h"
#include "vsi.h"

#endif

#include "bta_riviera.h"
#include "mfw_bte.h"
#include "mfw_bt_dm.h"
#include "mfw_bt_geh.h"
#include "mfw_bt_flash.h"


T_MFW_BT_CB 			mfw_bt_cb;

/* file where is stored bd address of the device to connect */
#ifndef MFW_BT_BD_ADDR_FILE
#define MFW_BT_BD_ADDR_FILE "/bt/remote_bd"
#endif

static T_MFW_BT_STATUS mfw_bt_dm_trust_device(BOOLEAN is_trusted, BD_ADDR bd_addr);


/*******************************************************************************

 $Function:		mfw_bt_dm_set_visibility

 $Description:		set visibility of local BT device

 $Returns:		T_MFW_BT_STATUS. Success or fail.	

 $Arguments:		is_visible: new visibility setting. is_temp: define whether it is a temporary
 				modification ( TRUE ) or a permanent one ( FALSE ).

*******************************************************************************/
T_MFW_BT_STATUS mfw_bt_dm_set_visibility( BOOL is_visible, BOOL is_temp)
{
	/* other devices will be able to find this device during an inquiry */
	if( mfw_bt_cb.is_started == TRUE )
		BTA_DmSetVisibility( 	(is_visible)?BTA_DM_GENERAL_DISC:BTA_DM_NON_DISC, 
    								BTA_DM_CONN);	

	if( is_temp == TRUE)
		/* it looks like this is only a temporary change  => don't store that in flash! */
		return MFW_BT_SUCCESS;

	/* update to nvram and mfw_bt_cfg */
    	return mfw_bt_store_visibility( is_visible );
}

/*******************************************************************************

 $Function:		mfw_bt_dm_get_visibility

 $Description:		get visibility of local BT device

 $Returns:		TRUE if visible, FALSE if not.

 $Arguments:		none

*******************************************************************************/
BOOL mfw_bt_dm_get_visibility( void )
{
	return mfw_bt_read_visibility( );
}



/*******************************************************************************

 $Function:		mfw_bt_dm_get_local_name

 $Description:		read  local BT device name

 $Returns:		a pointer to a string. NULL if no name available. One should make a copy of
 				string if he wants to use it/modify it. 

 $Arguments:		none

*******************************************************************************/
UINT8 * mfw_bt_dm_get_local_name( void )
{
	return mfw_bt_read_local_name();
}




/*******************************************************************************

 $Function:		mfw_bt_dm_set_local_name

 $Description:		set local BT device name

 $Returns:		T_MFW_BT_STATUS	

 $Arguments:		new name. Pointer to a string. This string is copied locally. Buffer is not freed.

*******************************************************************************/
T_MFW_BT_STATUS mfw_bt_dm_set_local_name( INT8 *name )
{
	if( strlen((char*)name) == 0 )
	{
		/* BMI should never ever send back an empty string, except at start-up */
		if( mfw_bt_cb.is_name_requested == FALSE )
			return MFW_BT_FAIL;
		
		/* we are here, this means:
			- it's a start-up
			- apparently, the local name was never set. => it's the first start-up
			- the user don't really want to use BT as he cancelled the setting.
		=> this means we do want to stop BT... So go for it!  :o)  */
		mfw_bt_disable( );
		return MFW_BT_SUCCESS;
	}	

	if( mfw_bt_cb.is_name_requested == TRUE )
		mfw_bt_cb.is_name_requested = FALSE;

	if( strlen((char*)name) > MFW_BT_NAME_LENGTH )
		return MFW_BT_INVALID_DATA;
	
	if( mfw_bt_cb.is_started )
		BTA_DmSetDeviceName( (char*)name );
	/* update to nv memory and mfw_bt_cfg with new name */
	return mfw_bt_store_local_name( (char*) name );
}

/*******************************************************************************

 $Function:		mfw_bt_dm_get_bt_status

 $Description:		get the status of the local Bluetooth system. Used at start-up to decide whether
 				or not we want BT to be started by default.

 $Returns:		MFW_BT_SUCCESS is BT is started. 0 if OFF	

 $Arguments:		

*******************************************************************************/
BOOL mfw_bt_dm_get_bt_status( void )
{
	return mfw_bt_read_status( );

}





/*******************************************************************************

 $Function:		mfw_bt_dm_pin_code

 $Description:		used by BMI to send back a pin code

 $Returns:		T_MFW_BT_STATUS. 	MFW_BT_NOT_INITIALISED is BT is not started.

 $Arguments:		pin code and pin code length. This data is copied.

*******************************************************************************/
T_MFW_BT_STATUS mfw_bt_dm_pin_code(UINT8* pin_code, UINT8 pin_len)
{
	BOOLEAN accept = TRUE;

	if( mfw_bt_cb.is_started != TRUE )
		return MFW_BT_NOT_INITIALISED;
	
	if(pin_len == 0)
	    accept = FALSE;
	BTA_DmPinReply( 	mfw_bt_cb.peer_bdaddr, 
	                			accept,   
	                			pin_len, 
	                			pin_code);

	return MFW_BT_SUCCESS;
}



/*******************************************************************************

 $Function:		mfw_bt_dm_bond

 $Description:		used by BMI to send a pin code in order to establish a bonding with a 
 				remote device.

 $Returns:		T_MFW_BT_STATUS. MFW_BT_NOT_INITIALISED is BT is not started.
 				

 $Arguments:		BD_ADDR of the remote device, pin code and pin code length. Data is copied.

*******************************************************************************/
T_MFW_BT_STATUS mfw_bt_dm_bond(BD_ADDR bd_addr, UINT8* pin_code, UINT8 pin_len )
{
	if( mfw_bt_cb.is_started != TRUE )
		return MFW_BT_NOT_INITIALISED;
	

	MFW_BT_TRACE("try to bond with stored device");
	if(pin_len != 0)
	{
		/* now tell the BT stack */
		BTA_DmBond (	bd_addr,	pin_len,  pin_code );		
		return MFW_BT_SUCCESS;		
	}
	else
	{
		MFW_BT_TRACE("  [ mfw_bt dm bond]: no pin code entered!");
		return MFW_BT_FAIL;
	}

}


/*******************************************************************************

 $Function:		mfw_bt_dm_authorize_resp

 $Description:		used to answer to an authorization request

 $Returns:		T_MFW_BT_STATUS. SUCCESS/FAIL, but also:
 				MFW_BT_NOT_INITIALISED is BT is not started. 
 				MFW_BT_INVALID_DATA if auth value is not correct.
 				MFW_BT_UNKNOWN_DEVICE if BD_addr is not recognized.
 				MFW_BT_DATA_BASE_FULL if there are already too many devices in the DB.
 				

 $Arguments:		MFW_BT_AUTH_FAIL to refuse, 
 				MFW_BT_AUTH_ONCE to grant access temporarily,
 				MFW_BT_AUTH_ALWAYS to grant permanent access

*******************************************************************************/
T_MFW_BT_STATUS mfw_bt_dm_authorize_resp( T_MFW_BT_AUTHORIZE auth)
{
	T_MFW_BT_STATUS status;
	
	if( mfw_bt_cb.is_started != TRUE )
		return MFW_BT_NOT_INITIALISED;
	
	switch (auth)
	{
	case MFW_BT_AUTH_FAIL:
		/* reject */
		BTA_DmAuthorizeReply(	mfw_bt_cb.peer_bdaddr, 
								mfw_bt_cb.peer_service,
		                     			BTA_DM_NOT_AUTH);
		mfw_bt_dm_trust_device( FALSE, mfw_bt_cb.peer_bdaddr );
		break;
		
	case MFW_BT_AUTH_ALWAYS:
		/*
		** CQ22024 : Set the device as Trusted, and Authorise it for this an all subsequent connections
		**			If writing to the Flash fails, proceed with the authorisation anyway.
		*/
		status = mfw_bt_dm_trust_device( TRUE, mfw_bt_cb.peer_bdaddr );

		/*
		** Even if we fail to write the information to the FLASH, we should continue with the
		** Authorisation procedure. If the device is unknown, the device will remain Authorised as
		** long as the Handset is not powered down (Not ideal, but better than refusing Authorisation all together)
		*/
		BTA_DmAuthorizeReply(	mfw_bt_cb.peer_bdaddr, 
								mfw_bt_cb.peer_service,
								BTA_DM_AUTH_PERM);
		break;
		
	case MFW_BT_AUTH_ONCE:
		/* CQ22024 : tell the BT stack we authorize the device, but for this connection only */
		BTA_DmAuthorizeReply(	mfw_bt_cb.peer_bdaddr, 
								mfw_bt_cb.peer_service,
								BTA_DM_AUTH_TEMP);
		break;

	default:
		return MFW_BT_INVALID_DATA;
	}
	return MFW_BT_SUCCESS;
}


/*******************************************************************************

 $Function:		mfw_bt_dm_sig_strength

 $Description:		ask for the link quality

 $Returns:		T_MFW_BT_STATUS. MFW_BT_NOT_INITIALISED if BT is not started.

 $Arguments:		T_MFW_BT_DM_SIG_STRENGTH sig_strength,  UINT16 period, 	BOOLEAN is_on
				See BTA documentation for more details.
				
*******************************************************************************/
T_MFW_BT_STATUS	mfw_bt_dm_sig_strength (	T_MFW_BT_DM_SIG_STRENGTH sig_strength,
													UINT16 period,
													BOOLEAN is_on )
{
	if( mfw_bt_cb.is_started != TRUE )
		return MFW_BT_NOT_INITIALISED;
	BTA_DmSignalStrength((tBTA_SIG_STRENGTH_MASK) sig_strength,  period,  is_on);
	return MFW_BT_SUCCESS;
}


/*******************************************************************************

 $Function:		mfw_bt_dm_get_known_devices

 $Description:		used by BMI to get the list of known devices for a specified condition: either a 
 				service mask, either a bd address ( union ). 
 				MFW will fill in the variables: pp_device => table of known devices
 				number_of_devices => number of devices.
 				MFW will allocate memory for each device found. It's up to BMI to free it!

 $Returns:		T_MFW_BT_STATUS. 
 				If BD_ADDR is specified, might return MFW_BT_UNKNOWN_DEVICE.
 				 The answers will be returned using BMI signals:
 				- E_BT_DM_INQ_CMPL with the number of devices
 				- E_BT_DM_DISC_RES for each device
 				- then E_BT_DM_DISC_CMPL when it's done.
 
 $Arguments:		BD_ADDR if looking for a particular device. services if looking for a 
 				category of device. If bd_addr is specified, ignore services. If services set
 				to 0, will return all the known devices.

*******************************************************************************/
void mfw_bt_dm_get_known_devices ( 	BD_ADDR bd_addr,
											T_MFW_BT_SERVICE_MASK services)
{
	T_MFW_BT_REM_DEVICE *ptr_db_device[MFW_BT_NUM_REM_DEVICE];
	UINT8 i, number_of_devices;
	T_MFW_BT_DM_INQ_CMPL inq_cmpl_res;
	T_MFW_BT_STATUS status;
	BD_ADDR null_bd_addr;
	
	number_of_devices = 0;
	memset(&null_bd_addr[0], 0x00, sizeof(BD_ADDR));
	
	/* we have a BT address, try to find the related data */
	/* CQ21834 : cannot treat bd_addr as a pointer, because it is passed by value. Use MemCmp */
	if( memcmp(&bd_addr[0], &null_bd_addr[0], sizeof(BD_ADDR)) != 0 )
	{
		ptr_db_device[0] = mfw_bt_get_device_info(bd_addr);
		
		if(ptr_db_device[0] != NULL)
		{
			if((ptr_db_device[0])->is_new == FALSE)
				number_of_devices = 1;
		}
	}
	else
	{
		/* Now we want to find all the devices which support the given services */
		mfw_bt_get_device_by_service(services, &ptr_db_device[0], &number_of_devices );
	}

	/* first send the number of found devices. this is important! BMI shouldn't do anything
	before he gets all the answer */
	inq_cmpl_res.num_resps = number_of_devices;
	mfw_bt_signal( E_BT_DM_INQ_CMPL, (void*)&inq_cmpl_res);
	
	if (number_of_devices > 0)
	{
		/*
		** CQ21834 : The incorrect structure was being used for the signal, so the data was never received by the BMI.
		*/
		T_MFW_BT_DM_DISC_RES disc_res;

		/* now for each device found, send a signal to BMI. This will copy the data! */	
		for( i=0; i<number_of_devices; i++ )
		{
			memcpy((void *)&disc_res, (void *)ptr_db_device[i], sizeof(disc_res));

			mfw_bt_signal( E_BT_DM_DISC_RES, (void *)&disc_res);
		}

		mfw_bt_signal( E_BT_DM_DISC_CMPL, NULL);
	}
	
	return;
	
}







/*******************************************************************************

 $Function:		mfw_bt_dm_trust_device

 $Description:		specify whether a remote device should or not be trusted ( => access granted )

 $Returns:		T_MFW_BT_STATUS	
 				success, failure, MFW_BT_UNKNOWN_DEVICE

 $Arguments:		BOOLEAN for the permission; BD address of the remote device

*******************************************************************************/
T_MFW_BT_STATUS mfw_bt_dm_trust_device(BOOLEAN is_trusted, BD_ADDR bd_addr)
{
	T_MFW_BT_REM_DEVICE * p_device;
	T_MFW_BT_STATUS status;
	
	/* check if we know this device*/
	if(( p_device = mfw_bt_get_device_info(bd_addr)) == NULL )
		/* unknown device... */
		return MFW_BT_UNKNOWN_DEVICE;
		
	p_device->is_trusted = is_trusted;
	if (( status = mfw_bt_flash_store_device(p_device)) != MFW_BT_SUCCESS )
		return status;

	/* update BTA with new settings */
	if( mfw_bt_cb.is_started )
	{
		if(p_device->link_key_present)
			BTA_DmAddDevice(bd_addr, p_device->link_key, BTA_ALL_SERVICE_MASK, is_trusted);
		else 
			BTA_DmAddDevice(bd_addr, NULL, BTA_ALL_SERVICE_MASK, is_trusted);
	}

	return MFW_BT_SUCCESS;
 }



/*******************************************************************************

 $Function:		mfw_bt_dm_delete_device

 $Description:		remove a device from the local DB
 
 $Returns:		T_MFW_BT_STATUS ( MFW_BT_SUCCESS, MFW_BT_FAIL, MFW_BT_UNKNOWN_DEVICE )	

 $Arguments:		BD address

*******************************************************************************/
T_MFW_BT_STATUS mfw_bt_dm_delete_device(BD_ADDR bd_addr)
{
	if( mfw_bt_cb.is_started )
		BTA_DmRemoveDevice (bd_addr);
	return mfw_bt_flash_delete_device(bd_addr);
}



/*******************************************************************************

 $Function:		mfw_bt_dm_add_device

 $Description:		This will store permanently a device in Flash.

 $Returns:		T_MFW_BT_STATUS
 				errors: MFW_BT_UNKNOWN_DEVICE, MFW_BT_DATA_BASE_FULL, 
 				

 $Arguments:		new BD address

*******************************************************************************/
 T_MFW_BT_STATUS mfw_bt_dm_add_device(BD_ADDR bd_addr)
{
	T_MFW_BT_REM_DEVICE *p_device;
	T_MFW_BT_STATUS status;
	
	MFW_BT_TRACE("mfw_bt_dm_add_device()");

	/* get the info about this device */
	if( ( p_device = mfw_bt_get_device_info( bd_addr)) == NULL)
		return MFW_BT_UNKNOWN_DEVICE;
	
	if( p_device->is_new == TRUE )
	{
		/*
		** CQ21834 : Ensure that the is_new value is set before writing the data to Flash, so that it will be
		**			set correctly when  the handset is restarted.
		*/
		p_device->is_new = FALSE;
		if((status = mfw_bt_flash_store_device(p_device))!=MFW_BT_SUCCESS)
			return status;
	}
	
	/* update BTA device database */
	if( mfw_bt_cb.is_started )
	{
		if(p_device->link_key_present)
			BTA_DmAddDevice(p_device->bd_addr, p_device->link_key,
		                    p_device->trusted_services, p_device->is_trusted);
		else 
		    	BTA_DmAddDevice(p_device->bd_addr, NULL,
		                    p_device->trusted_services, p_device->is_trusted);
	}
	return MFW_BT_SUCCESS;

}



/*******************************************************************************

 $Function:		mfw_bt_dm_rename_device

 $Description:		modify the friendly name of a known ( already stored ) remote device

 $Returns:		T_MFW_BT_STATUS.
 				MFW_BT_UNKNOWN_DEVICE, DATA_BASE_FULL, MFW_BT_INVALID_DATA...

 $Arguments:		bd address of the remote device and the new name associated

*******************************************************************************/
T_MFW_BT_STATUS mfw_bt_dm_rename_device(BD_ADDR bd_addr, UINT8* new_name)
{
	T_MFW_BT_REM_DEVICE *p_device;

	if( ( p_device = mfw_bt_get_device_info( bd_addr)) == NULL )
		return MFW_BT_UNKNOWN_DEVICE;
	/* if this device is new ( == in the inq DB ), we don't want to do anything */
	if( p_device->is_new == TRUE )
		return MFW_BT_FAIL;
	/* verify the string is OK */
	if( strlen( (char*)new_name ) > MFW_BT_NAME_LENGTH )
		return MFW_BT_INVALID_DATA;
	strcpy(p_device->friendly_name, (char*)new_name );
	return mfw_bt_flash_store_device(p_device);
	
}






/*
**  Functions used to interact with the BT "search engine"
*/


/*******************************************************************************

 $Function:		mfw_bt_dm_discover_device

 $Description:		Discovers services on a device

 $Returns:		T_MFW_BT_STATUS. MFW_BT_NOT_INITIALISED if BT not started.	

 $Arguments:		bd address of the remote device to discover

*******************************************************************************/
T_MFW_BT_STATUS mfw_bt_dm_discover_device(BD_ADDR bd_addr)
{

    	T_MFW_BT_SERVICE_MASK client_services;

	if( mfw_bt_cb.is_started != TRUE )
		return MFW_BT_NOT_INITIALISED;

	/* remember it's an inquiry */
	mfw_bt_cb.is_discovery = TRUE;
	
	/* we need to find only services for which we can be in client role, plus HS/HF */
	client_services = ((BTA_SUPPORTED_CLIENT_SERVICES & \
	                                ~( BTA_DUN_SERVICE_MASK | BTA_FAX_SERVICE_MASK )) \
	                                | BTA_HSP_SERVICE_MASK | BTA_HFP_SERVICE_MASK );

	BTA_DmDiscover(bd_addr, BTA_ALL_SERVICE_MASK, (tBTA_DM_SEARCH_CBACK*)mfw_bt_dm_search_cb);

	return MFW_BT_SUCCESS;
}


/*******************************************************************************

 $Function:		mfw_bt_dm_is_discover

 $Description:	Checks if we are in discovering services process

 $Returns:		

 $Arguments:	None

*******************************************************************************/
UINT8 mfw_bt_dm_is_discover(void)
{
	return mfw_bt_cb.is_discovery;
}



/*******************************************************************************

 $Function:		mfw_bt_dm_cancel_search

 $Description:		cancel an ongoing search

 $Returns:		MFW_BT_NOT_INITIALISED if BT not started.	

 $Arguments:		

*******************************************************************************/
T_MFW_BT_STATUS mfw_bt_dm_cancel_search( void )
{
	if( mfw_bt_cb.is_started != TRUE )
		return MFW_BT_NOT_INITIALISED;
    	BTA_DmSearchCancel();
	return MFW_BT_SUCCESS;		
}


/*******************************************************************************

 $Function:		mfw_bt_dm_search

 $Description:		Searches for devices supporting the services specified. If services = 0, will 
 				return all the found devices regardless of their functionalities.

 $Returns:		MFW_BT_NOT_INITIALISED if BT not started.	

 $Arguments:		services. If

*******************************************************************************/
T_MFW_BT_STATUS mfw_bt_dm_search(T_MFW_BT_SERVICE_MASK services)
{
	tBTA_DM_INQ inq_params;
	UINT8 inq_index;

	if( mfw_bt_cb.is_started != TRUE )
		return MFW_BT_NOT_INITIALISED;
	mfw_bt_cb.is_discovery = FALSE;
	inq_params.mode = 0;
	inq_params.duration = MFW_BT_DEFAULT_INQ_DURATION;
	inq_params.max_resps = MFW_BT_NUM_REM_DEVICE;
	inq_params.filter_type = BTA_DM_INQ_CLR;

	/* "initialize" the inquiry data base */
	mfw_bt_clean_inq_db( );
	/* store the services we are looking for, so that we can filter the results */
	mfw_bt_cb.search_services = services;
	/* find nearby devices */
	BTA_DmSearch(&inq_params, services, mfw_bt_dm_search_cb );
	return MFW_BT_SUCCESS;		
	
}




/*
** MFW Bluetooth Device Manager Signal Handler Function Definitions
*/
/*******************************************************************************

 $Function:		mfw_bt_dm_security_hndlr

 $Description:		This function recieves the BTA DM Security events from the Generic Event Handler
 				and either processes them in their entirety or passes them to the MMI for further
 				processing.

 $Returns:		MFW_BT_SUCCESS	: The signal was handled successfully

 $Arguments:		event	: Event Id returned from the Bluetooth Module
 				data		: pointer to the relevant data returned from the Mluetooth Module

*******************************************************************************/
T_MFW_BT_STATUS	mfw_bt_dm_security_hndlr (T_MFW_BT_DM_SEC_EVT event, T_MFW_BT_DM_SEC_SIG_DATA *data)
{
	T_MFW_BT_STATUS retVal = MFW_BT_SUCCESS;
	
	MFW_BT_TRACE("mfw_bt_dm_security_hndlr");

	switch (event)
	{
		case BTA_DM_SYS_START_EVT:
		{
			MFW_BT_TRACE("mfw_bt_dm_security_hndlr > BTA_DM_SYS_START_EVT event received");
			/* now enable bluetooth functionalities before calling other BTA API */
			BTA_EnableBluetooth(&mfw_bt_dm_security_cb);  
		}
		break;			
			
		case BTA_DM_ENABLE_EVT:
		{
			MFW_BT_TRACE("mfw_bt_dm_security_hndlr > BTA_DM_ENABLE_EVT event received");
			/* call the enable call-back */
			mfw_bt_enable_cb( );
		}
		break;

		case BTA_DM_DISABLE_EVT:
		{
			MFW_BT_TRACE("mfw_bt_dm_security_hndlr > BTA_DM_DISABLE_EVT event received");

			/* stop the BT chipset */
			BTA_SysStop();

			/* we won't use BT anymore => free the event handler */
			mfw_bt_ge_disable();
			
			/* store the new settings */
			mfw_bt_store_status(FALSE);
			mfw_bt_cb.is_started = FALSE;
			
			/* and tell BMI */
			mfw_bt_signal(E_BT_DISABLE_CMPL, (void *)0);
		}
		break;

		case BTA_DM_PIN_REQ_EVT:
		{
			/* store the BD ADDR of the remote device */
			bdcpy(mfw_bt_cb.peer_bdaddr, data->pin_req.bd_addr);
			/* and forward the signal to BMI */
			mfw_bt_signal(E_BT_DM_PIN_REQ, data);
			MFW_BT_TRACE("mfw_bt_dm_security_hndlr > BTA_DM_PIN_REQ_EVT event received");
		}
		break;

		case BTA_DM_AUTH_CMPL_EVT:
		{	
			T_MFW_BT_DM_AUTH_CMPL data_auth;
			T_MFW_BT_REM_DEVICE device;
			T_MFW_BT_REM_DEVICE *p_device;

			MFW_BT_TRACE("mfw_bt_dm_security_hndlr > BTA_DM_AUTH_CMPL_EVT event received");
			/* first, give some feedback to BMI */
			/* => copy data */
			memcpy(data_auth.bd_addr, data->auth_cmpl.bd_addr, BD_ADDR_LEN); 
			if( strlen((char*)data->auth_cmpl.bd_name) != 0 )
				mfwStrncpy((char*)data_auth.bd_name, (const char*)data->auth_cmpl.bd_name, MFW_BT_NAME_LENGTH);
			data_auth.is_success = data->auth_cmpl.success;
			/* and forward it */
			mfw_bt_signal(E_BT_DM_AUTH_CMPL, (void*)&data_auth);

			/* now see if we have to update our data base */
			p_device = mfw_bt_get_device_info(data->auth_cmpl.bd_addr);
			if( p_device == NULL )
			{	
				/* we don't know this device ... */ 
				if ( data->auth_cmpl.success == FALSE )
					/* ... and auth has been rejected: get away from here... */
					break;			
				
				/* ... but it's trusted. So add it to our DB. This means we have to create a 
				real T_MFW_BT_REM_DEVICE entity, which will be copied */
				p_device = &device;
				memset(&device, 0, sizeof( T_MFW_BT_REM_DEVICE ) );
			}
				
			/* ok, now  update our local DB: get the info we received */
			memcpy(p_device->bd_addr, data->auth_cmpl.bd_addr, BD_ADDR_LEN); 
			if( strlen((char*)data->auth_cmpl.bd_name) != 0 )
				mfwStrncpy((char*)p_device->name, (const char*)data->auth_cmpl.bd_name, MFW_BT_NAME_LENGTH);
			memcpy(p_device->link_key, data->auth_cmpl.key, LINK_KEY_LEN );
			p_device->link_key_present = data->auth_cmpl.key_present;

			/* we don't modify the other fields => either the already stored ones will be used, 
			either for a new device they will be set to zero. */
			
			mfw_bt_flash_store_device( p_device );			
		}
		break;

		case BTA_DM_AUTHORIZE_EVT:
		{
			/* keep a trace of the information??? */
			bdcpy(mfw_bt_cb.peer_bdaddr, data->authorize.bd_addr);
			strncpy((char*)mfw_bt_cb.peer_name, (char*)data->authorize.bd_name, MFW_BT_NAME_LENGTH);
			mfw_bt_cb.peer_service = data->authorize.service;
			/*and forward it to BMI */
			mfw_bt_signal(E_BT_DM_AUTHORIZE_REQ, data );
			MFW_BT_TRACE("mfw_bt_dm_security_hndlr > BTA_DM_AUTHORIZE_EVT event received");
		}
		break;

		case BTA_DM_LINK_UP_EVT:
		{	
			/* this is only a "HW" connection, so no service or name needed. Just show BT is busy */
			MFW_BT_TRACE("mfw_bt_dm_security_hndlr > BTA_DM_LINK_UP_EVT event received");
			mfw_bt_signal(E_BT_DM_LINK_UP, data );
		}
		break;

		case BTA_DM_LINK_DOWN_EVT:
		{	
			/* just to know BT is idle again */
			MFW_BT_TRACE("mfw_bt_dm_security_hndlr > BTA_DM_LINK_DOWN_EVT event received");
			mfw_bt_signal(E_BT_DM_LINK_DOWN, data );
		}
		break;

		case BTA_DM_SIG_STRENGTH_EVT:
		{	
			/* ok, we receive a signal strength indication. Great. */
			MFW_BT_TRACE("mfw_bt_dm_security_hndlr > BTA_DM_SIG_STRENGTH_EVT event received");
			mfw_bt_signal(E_BT_DM_SIG_STRENGTH_IND, data );
		}	
		break;

		default:
		{
			/*
			** Unexpected Event, set the data sized to -1 to exit with no further action
			*/
			MFW_BT_TRACE_P1("mfw_bt_dm_security_b > Unexpected Event %d", event);
			retVal = MFW_BT_INVALID_EVENT;
		}
		break;
			
	}

	return retVal;
}




/*******************************************************************************

 $Function:		mfw_bt_dm_search_hndlr

 $Description:		This function recieves the BTA DM Search events from the Generic Event Handler
 				and either processes them in their entirety or passes them to the MMI for further
 				processing.

 $Returns:		MFW_BT_SUCCESS	: The signal was handled successfully

 $Arguments:		event	: Event Id returned from the Bluetooth Module
 				data		: pointer to the relevant data returned from the Mluetooth Module

*******************************************************************************/
T_MFW_BT_STATUS	mfw_bt_dm_search_hndlr (T_MFW_BT_DM_SRCH_EVT event, T_MFW_BT_DM_SRCH_SIG_DATA *data)
{
	T_MFW_BT_STATUS retVal = MFW_BT_SUCCESS;
	
	MFW_BT_TRACE("mfw_bt_dm_search_hndlr");

	/*
	** Set the expected data size according to the received event
	*/
	switch (event)
	{
		case BTA_DM_INQ_RES_EVT:
			{
				MFW_BT_TRACE("mfw_bt_dm_search_hndlr > BTA_DM_INQ_RES_EVT event received");
				/* we just received a BD address... Don't even forward this to BMI */
			    	MFW_BT_TRACE_P6("DB_ADDR: msg_str%02x:%02x:%02x:%02x:%02x:%02x\n",
									data->inq_res.bd_addr[0], data->inq_res.bd_addr[1],
							              data->inq_res.bd_addr[2], data->inq_res.bd_addr[3],
							              data->inq_res.bd_addr[4], data->inq_res.bd_addr[5]);
				mfw_bt_add_inq_device( &(data->inq_res) );
			}
			break;

		case BTA_DM_INQ_CMPL_EVT:
			mfw_bt_signal( E_BT_DM_INQ_CMPL, (void*)&data->inq_cmpl);
			MFW_BT_TRACE("mfw_bt_dm_search_hndlr > BTA_DM_INQ_CMPL_EVT event received");
			break;

		case BTA_DM_DISC_RES_EVT:
		{
			T_MFW_BT_DM_DISC_RES disc_res_data;
			T_MFW_BT_REM_DEVICE *p_device_rec = NULL;	/*CQ21834 : Not Just needed for discovery, but search also */

			/*
			** Do some preliminary initialisation, so that if nothing changes we send the right information
			*/
			memset(&disc_res_data, 0x00, sizeof(T_MFW_BT_DM_DISC_RES));
			
			memcpy(disc_res_data.bd_addr, data->disc_res.bd_addr, sizeof(BD_ADDR));
			memcpy(disc_res_data.name, data->disc_res.bd_name, MFW_BT_NAME_LENGTH);
			disc_res_data.services = data->disc_res.services;	
			disc_res_data.is_new = TRUE;

			/* if we are doing a discovery on a device */
			if(mfw_bt_cb.is_discovery == TRUE)
			{
				if(data->disc_res.services == 0 )
				{
				    MFW_BT_TRACE("No service found");
				}
				else
				{
		                	p_device_rec = mfw_bt_get_device_info(data->disc_res.bd_addr );
		                	if(p_device_rec)
			              {
			              	/* we really should find our device! */ 
						p_device_rec->services = data->disc_res.services;
							
			              	if( p_device_rec->is_new)
							mfw_bt_add_disc_device((T_MFW_BT_DM_DISC_RES*) p_device_rec);
						else
							mfw_bt_flash_store_device(p_device_rec);
						/* forward the info to BMI */

						/*
						** Reset the information for the signal from the known or already discovered database
						*/
						memcpy(&disc_res_data, p_device_rec, sizeof(T_MFW_BT_DM_DISC_RES));
			              }
		            	}
		        }
		        /* we are doing device search. We receive the information about all the found devices. 
				Let's verify if we specified services to look for => if yes, filter the results */
		        else if( mfw_bt_cb.search_services == 0 ||  
					(mfw_bt_cb.search_services & data->disc_res.services))
		        {		
			/*
			** CQ21834 : Check to determine whether the device is already known, if so get (and update)
			** 			the information in th eKnown Devices Database
			*/
	                p_device_rec = mfw_bt_get_device_info(data->disc_res.bd_addr );

			/*
			** p_device_rec should not be NULL because the device was added to the inquiry database when the inq result
			** was recieved if it was not already in the known device database.
			*/
	                if (p_device_rec->is_new == FALSE)
		          {
		            MFW_BT_TRACE("BTA_DM_DISC_RES_EVT > This device is known");
				
		            if (strncmp(p_device_rec->name, (char *)&data->disc_res.bd_name, MFW_BT_NAME_LENGTH) != 0)
	              	{
	              		mfwStrncpy(p_device_rec->name, (char *)&data->disc_res.bd_name, MFW_BT_NAME_LENGTH);
	              	}

		            /* Update the device details! */ 
		                    p_device_rec->services |= data->disc_res.services;
				mfw_bt_flash_store_device(p_device_rec);

		            memcpy(&disc_res_data, p_device_rec, sizeof(T_MFW_BT_DM_DISC_RES));
	                }

		        /*
			** CQ21834: update our database whether the device is known or not, so that if the user removes it from the
			** known device database, we will still have the details available.
			*/
		        	mfw_bt_add_disc_device( (T_MFW_BT_DM_DISC_RES*) &disc_res_data);
		       }
		       
			MFW_BT_TRACE("mfw_bt_dm_search_hndlr > BTA_DM_DISC_RES_EVT event received");
			/* and forward the event to BMI */
			mfw_bt_signal( E_BT_DM_DISC_RES, (void*)&disc_res_data);			
		}
		break;

		case BTA_DM_DISC_CMPL_EVT:
			mfw_bt_signal( E_BT_DM_DISC_CMPL, NULL );
			MFW_BT_TRACE("mfw_bt_dm_search_hndlr > BTA_DM_DISC_CMPL_EVT event received");
			break;

		case BTA_DM_SEARCH_CANCEL_CMPL_EVT:
			/* currently, we don't do anything when a search is cancelled. Should we? */
			MFW_BT_TRACE("mfw_bt_dm_search_hndlr > BTA_DM_SEARCH_CANCEL_CMPL_EVT event received");
			break;

		default:
			/*
			** Unexpected Event, setthe data sized to -1 to exit with no further action
			*/
			MFW_BT_TRACE_P1("mfw_bt_dm_search_hndlr > Unexpected Event %d", event);
			retVal = MFW_BT_INVALID_EVENT;
			
	}

	return retVal;
}





/*
** MFW Bluetooth Device Manager Callback Function Definitions
*/
/*******************************************************************************

 $Function:		mfw_bt_dm_security_b

 $Description:		This is the Device Manager Security Callback function, a pointer to it is passed
 				to the Bluetooth Module in the BTA DM Enable function and it is used to return
 				information from the Bluetooth Module

 $Returns:		None

 $Arguments:		event	: Event Id returned from the Bluetooth Module
 				data		: pointer to the relevant data returned from the Mluetooth Module

*******************************************************************************/
void	mfw_bt_dm_security_cb(T_MFW_BT_DM_SEC_EVT event, T_MFW_BT_DM_SEC_SIG_DATA *data)
{
	int dataLen;
	T_MFW_BT_STATUS	geRetVal = MFW_BT_SUCCESS;

	MFW_BT_TRACE("mfw_bt_dm_security_b");

	/*
	** Set the expected data size according to the received event
	*/
	switch (event)
	{
		case BTA_DM_SYS_START_EVT:
			dataLen = 0;
			break;
		case BTA_DM_ENABLE_EVT:
			dataLen = sizeof(tBTA_DM_ENABLE);
			break;

		case BTA_DM_DISABLE_EVT:
			dataLen = 0;
			break;

		case BTA_DM_PIN_REQ_EVT:
			dataLen = sizeof(tBTA_DM_PIN_REQ);
			break;

		case BTA_DM_AUTH_CMPL_EVT:
			dataLen = sizeof(tBTA_DM_AUTH_CMPL);
			break;

		case BTA_DM_AUTHORIZE_EVT:
			dataLen = sizeof(tBTA_DM_AUTHORIZE);
			break;

		case BTA_DM_LINK_UP_EVT:
			dataLen = sizeof(tBTA_DM_LINK_UP);
			break;

		case BTA_DM_LINK_DOWN_EVT:
			dataLen = sizeof(tBTA_DM_LINK_DOWN);
			break;

		case BTA_DM_SIG_STRENGTH_EVT:
			dataLen = sizeof(tBTA_DM_SIG_STRENGTH);
			break;

		default:
			/*
			** Unexpected Event, setthe data sized to -1 to exit with no further action
			*/
			MFW_BT_TRACE_P1("mfw_bt_dm_security_b > Unexpected Event %d", event);
			dataLen = -1;
			
	}


	if (dataLen > 0)
	{
		/*
		** Data is expected with the received signal
		*/
		if ((void *)data == (void *)0)
		{
			/*
			** The data pointer is NULL, report the error
			*/
			MFW_BT_TRACE_P1("mfw_bt_dm_security_b > Event : %d, Data Pointer is NULL, but data is expected", event);
		}
		else
		{
			/*
			** Post the event and data to the Generic event handler
			*/
			geRetVal = mfw_bt_ge_post_event(MFW_BT_DM_SECURITY, (ULONG)event, (void *)data, dataLen);
		}
	}
	else if (dataLen == 0)
	{
		/*
		** There is no expected data with the received signal, post the event to the Generic event handler
		*/
		geRetVal = mfw_bt_ge_post_event(MFW_BT_DM_SECURITY, (ULONG)event, (void *)0, 0);
	}

	if (geRetVal != MFW_BT_SUCCESS)
	{
		/*
		** There is an error, but there is nothing that can be done other than to report it.
		*/
		MFW_BT_TRACE_P1("mfw_bt_dm_security_b > Failed to post the event. Error %d", geRetVal);
	}

	return;
}


/*******************************************************************************

 $Function:		mfw_bt_Dm_Search_Cb

 $Description:		This is the Device Manager Search Callback function, a pointer to it is passed
 				to the Bluetooth Module in the BTA DM Search and Discover functions and it is
 				used to return information from the Bluetooth Module

 $Returns:		None

 $Arguments:		event	: Event Id returned from the Bluetooth Module
 				data		: pointer to the relevant data returned from the Mluetooth Module

*******************************************************************************/
void	mfw_bt_dm_search_cb(T_MFW_BT_DM_SRCH_EVT event, T_MFW_BT_DM_SRCH_SIG_DATA *data)
{
	int dataLen;
	T_MFW_BT_STATUS	geRetVal = MFW_BT_SUCCESS;

	MFW_BT_TRACE("mfw_bt_Dm_Search_Cb");

	/*
	** Set the expected data size according to the received event
	*/
	switch (event)
	{
		case BTA_DM_INQ_RES_EVT:
			dataLen = sizeof(tBTA_DM_INQ_RES);
			break;

		case BTA_DM_INQ_CMPL_EVT:
			dataLen = sizeof(tBTA_DM_INQ_CMPL);
			break;

		case BTA_DM_DISC_RES_EVT:
			dataLen = sizeof(tBTA_DM_DISC_RES);
			break;

		case BTA_DM_DISC_CMPL_EVT:
			dataLen = 0;
			break;

		case BTA_DM_SEARCH_CANCEL_CMPL_EVT:
			dataLen = 0;
			break;


		default:
			/*
			** Unexpected Event, setthe data sized to -1 to exit with no further action
			*/
			MFW_BT_TRACE_P1("mfw_bt_Dm_Search_Cb > Unexpected Event %d", event);
			dataLen = -1;
			
	}


	if (dataLen > 0)
	{
		/*
		** Data is expected with the received signal
		*/
		if ((void *)data == (void *)0)
		{
			/*
			** The data pointer is NULL, report the error
			*/
			MFW_BT_TRACE_P1("mfw_bt_Dm_Search_Cb > Event : %d, Data Pointer is NULL, but data is expected", event);
		}
		else
		{
			/*
			** Post the event and data to the Generic event handler
			*/
			geRetVal = mfw_bt_ge_post_event(MFW_BT_DM_SEARCH, (ULONG)event, (void *)data, dataLen);
		}
	}
	else if (dataLen == 0)
	{
		/*
		** There is no expected data with the received signal, post the event to the Generic event handler
		*/
		geRetVal = mfw_bt_ge_post_event(MFW_BT_DM_SEARCH, (ULONG)event, (void *)0, 0);
	}

	if (geRetVal != MFW_BT_SUCCESS)
	{
		/*
		** There is an error, but there is nothing that can be done other than to report it.
		*/
		MFW_BT_TRACE_P1("mfw_bt_Dm_Search_Cb > Failed to post the event. Error %d", geRetVal);
	}

	return;
}


