/*
+-------------------------------------------------------------------+
| PROJECT: MMI-Framework (8445)		$Workfile:: mfw_bt.c				$|
| $Author:: NDH						$Revision::  1						$|
| CREATED: 17.04.04					$Modtime:: 17.04.04 17:21			$|
| STATE  : code														 |
+-------------------------------------------------------------------+


   MODULE  : MFW_BT

   PURPOSE : This module contains the functions for MFW Bluetooth Management


*/

#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"
#include "prim.h"

#else

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

#endif

#include "bta_riviera.h"

#include "bta_api.h"
#include "mfw_bt_geh.h"
#include "mfw_bte.h"
#include "mfw_bt_dm.h"
#include "mfw_bt_dg.h"
#include "mfw_bt_ag.h"
#include "mfw_bt_op.h"
#include "mfw_bt_ft.h"
#include "mfw_bt_flash.h"

#include "mfw_utils.h"

/*
** Define Module wide variables
*/
static SHORT Mfw_Bt_Ge_Sigbuf_Id = -1;
static BOOLEAN Mfw_Bt_Ge_InProgress;

static T_MFW_STARTUP_VISIBILITY startup_visibility;

/*
** Local Function Prototypes
*/
static void mfw_bt_send_cb_notify_ind (void);

/*
** Define External variables and references
*/
EXTERN MfwHdr * current_mfw_elem;
/*
** Module Function Definitoins
*/



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

 $Function:		mfw_bt_enable

 $Description:		This function will start the whole process of enabling Bluetooth.

 $Returns:		MFW_BT_FAIL if the chip is not stopped or if the generic event handler
 				doesn't start correctly.

 $Arguments:		startup_visibility. Visibility set by the BMI. MFW_BT_DEFAULT_VIS if 
 				using the settings stored in flash. 

*******************************************************************************/
T_MFW_BT_STATUS mfw_bt_enable(T_MFW_STARTUP_VISIBILITY startup_visibility )
{
	UINT8 delay_counter = 0;
	T_RV_RET bt_start_status = 0;
	T_MFW_BT_STATUS status;
//	static tBTA_SYS_START_CBACK *fp;
//	fp= (tBTA_SYS_START_CBACK *)&mfw_bt_dm_security_cb;
	
	/* first, enable the event handler */
	status = mfw_bt_ge_enable();
	if( status != MFW_BT_SUCCESS ) 
		return status;
	
	/* start the system */
	if( BTA_SysStart((tBTA_SYS_START_CBACK *)(&mfw_bt_dm_security_cb) ) != RV_OK )
//	if( BTA_SysStart(fp) != RV_OK )
	{	
		MFW_BT_TRACE( "[mfw_bt]: failed to start BT chipset" );
		return MFW_BT_FAIL;	
	}
	/* the start-up procedure has been started. We will receive an 
	event when it is done */		
	MFW_BT_TRACE( "[mfw_bt]: BT is starting" );
	return MFW_BT_SUCCESS;

}




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

 $Function:		mfw_bt_enable_cb

 $Description:		mfw_bt_enable will cause a BTA_DM_SYS_START_EVT to be sent. At this 
 				moment we call BTA_EnableBluetooth. When we receive 
 				BTA_DM_ENABLE_EVT, we call this function.
 				
 $Returns:		Will send a BMI signal if there is no default name. If the user cancels the 
 				input, BT will then be stopped.
 				Will send a E_BT_ENABLE_CMPL event when the initialization is done. 

 $Arguments:		none 

*******************************************************************************/
void mfw_bt_enable_cb(void)
{
	UINT8* device_name;
	T_MFW_BT_REM_DEVICE *ptr_device_array[MFW_BT_NUM_REM_DEVICE];
	UINT8 number_of_devices;
	T_MFW_BT_ENABLE_CMPL enable_evt_data;

	
	mfw_bt_cb.is_started = TRUE;
	
	/* set device name */
	device_name = mfw_bt_read_local_name( );
	if( *device_name == NULL )
	{
		/* no name yet. Use default one, and ask the user to specify a new one */
		BTA_DmSetDeviceName((char*)MFW_BT_DEVICE_NAME);
		mfw_bt_cb.is_name_requested = TRUE;
		mfw_bt_signal(E_BT_DM_DEV_NAME_REQ, NULL);
	}
	else
		BTA_DmSetDeviceName( (char*)device_name );

	/* set visibility and connectability */
	if( startup_visibility == MFW_BT_DEFAULT_VIS )
	{
		if( mfw_bt_read_visibility( ) == TRUE )
		{
			BTA_DmSetVisibility( BTA_DM_GENERAL_DISC, BTA_DM_CONN);
		}
		else
		{
			BTA_DmSetVisibility( BTA_DM_NON_DISC, BTA_DM_NON_CONN);
		}
	}
	else
	{
		BTA_DmSetVisibility( startup_visibility, BTA_DM_NON_CONN);
	}
	
	
    	/* Update BTA with peer device information stored in NVRAM  */
		/* first, get all the devices */
	mfw_bt_get_device_by_service(0, 
       							    &ptr_device_array[0],
       							    &number_of_devices);

		/* then add these devices to BTA database. */
	for ( ; number_of_devices>0 ; number_of_devices-- )
	{
		if(ptr_device_array[number_of_devices]->link_key_present)
		{
			BTA_DmAddDevice(ptr_device_array[number_of_devices]->bd_addr, 
							    ptr_device_array[number_of_devices]->link_key, 
							    ptr_device_array[number_of_devices]->trusted_services, 
							    ptr_device_array[number_of_devices]->is_trusted);
		}
		else if (ptr_device_array[number_of_devices]->is_trusted)
		{
			BTA_DmAddDevice(ptr_device_array[number_of_devices]->bd_addr, 
							    NULL,
							    ptr_device_array[number_of_devices]->trusted_services,
							    ptr_device_array[number_of_devices]->is_trusted);
		}
	}

	/* initialize all the sub-parts => BT profiles. THIS CODE IS ABSOLUTELY NOT DYNAMIC... Does it
	need to be??? */
	mfw_bt_ag_init();
	mfw_bt_dg_init();
	mfw_bt_op_init();
	mfw_bt_ft_init();
	
	/* finally platform-specific initialization */
	//nothing to do for the time being. 

	/* store the new settings. this stores base conf file */
	mfw_bt_store_status(TRUE);

	enable_evt_data.Success = TRUE;
	mfw_bt_signal(E_BT_ENABLE_CMPL, (void*)&enable_evt_data );
	
	return;

}

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

 $Function:		mfw_bt_disable

 $Description:		This function stops the BT system.

 $Returns:		None

 $Arguments:		None

*******************************************************************************/
void mfw_bt_disable(void)
{
	/* disable BT. DM handler will then receive an DISABLE event => will stop the chipset
	and kill the generic event handler. */
	BTA_DisableBluetooth( );

	return;
}



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

 $Function:		mfw_bt_init

 $Description:		This function initialises the Mfw Bluetooth Persistent Data on Power Up. 

 $Returns:		None

 $Arguments:		None

*******************************************************************************/
void mfw_bt_init(void)
{

	/*
	** Read the Known Devices from FFS
	*/
	mfw_bt_flash_init( );
	
	/*
	** The rest is down to you Thomas
	*/

	return;
}

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

 $Function:		mfw_bt_exit

 $Description:		This function will tidy up any resources used by the Mfw Bluetooth Module
 				on Power Down

 $Returns:		None

 $Arguments:		None

*******************************************************************************/
void mfw_bt_exit(void)
{
	/* nothing to do here... RAM will be automatically cleaned, and the flash wasn't modified */

	return;
}

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

 $Function:		mfw_bt_create

 $Description:		This function  initialises an Mfw Bluetooth entity and adds it to the Window Stack

 $Returns:		T_MFW_HND	: A handle for the entity

 $Arguments:		T_MFW_HND		: Parent Window Handle
 				T_MFW_EVENT	: Event Mask of the events to be handled
 				T_MFW_CB		: Callback function to handle the events

*******************************************************************************/
T_MFW_HND mfw_bt_create(T_MFW_HND hWin, T_MFW_EVENT event, T_MFW_CB cbfunc)
{
	T_MFW_HDR *hdr;
	T_MFW_BT  *bt_para;

	MFW_BT_TRACE("mfw_bt_create");

	hdr = (T_MFW_HDR *) mfwAlloc(sizeof (T_MFW_HDR));
	bt_para = (T_MFW_BT *) mfwAlloc(sizeof (T_MFW_BT));

	if (!hdr OR !bt_para)
		return FALSE;

	/*
	* initialisation of the handler
	*/
	bt_para->emask   = event;
	bt_para->handler = cbfunc;

	hdr->data = bt_para;		/* store parameter in node	*/
	hdr->type = MfwTypBt;		/* store type of event handler */

	/*
	* installation of the handler
	*/
	return mfwInsert((T_MFW_HDR *)hWin, hdr);
}

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

 $Function:		mfw_bt_delete

 $Description:		This function clears down an Mfw Bluetooth entity and removes it from the
 				Window Stack

 $Returns:		T_MFW_RES	: The result of the function

 $Arguments:		T_MFW_HND	: The Handle of the entity to be removed

*******************************************************************************/
T_MFW_RES mfw_bt_delete(T_MFW_HND hnd)
{
	MFW_BT_TRACE("mfw_bt_delete");

	if (!hnd OR !((T_MFW_HDR *)hnd)->data)
		return MFW_RES_ILL_HND;

	if (!mfwRemove((T_MFW_HDR *)hnd))
		return MFW_RES_ILL_HND;

	mfwFree((U8 *)(((T_MFW_HDR *) hnd)->data),sizeof(T_MFW_BT));
	mfwFree((U8 *)hnd,sizeof(T_MFW_HDR));

	return MFW_RES_OK;
}

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

 $Function:		mfw_bt_signal

 $Description:		This function sends the Mfw Bluetooth events from the Mfw to the BMI.

 $Returns:		None

 $Arguments:		T_MFW_EVENT	: The event to be sent to the BMI
 				void *			: Pointer to the Event data

*******************************************************************************/
void mfw_bt_signal(T_MFW_EVENT event, void *para)
{
	UBYTE temp;

	temp = dspl_Enable(0);


	if (mfwSignallingMethod EQ 0)
	{
		/*
		* focus is on a window
		*/
		if (mfwFocus)
		{
			/*
			* send event to sim management
			* handler if available
			*/
			if (mfw_bt_sign_exec (mfwFocus, event, para))
			{
				dspl_Enable(temp);
				return;
			}
		}

		/*
		* actual focussed window is not available
		* or has no network management registration
		* handler, then search all nodes from the root.
		*/
		if (mfwRoot)
			mfw_bt_sign_exec (mfwRoot, event, para);
	}
	else
	{
		MfwHdr * h = 0;

		/*
		* Focus set, then start here
		*/
		if (mfwFocus)
			h = mfwFocus;

		/*
		* Focus not set, then start root
		*/
		if (!h)
			h = mfwRoot;

		/*
		* No elements available, return
		*/
		while (h)
		{
			/*
			* Signal consumed, then return
			*/
			if (mfw_bt_sign_exec (h, event, para))
			{
				dspl_Enable(temp);
				return;
			}

			/*
			* All windows tried inclusive root
			*/
			if (h == mfwRoot)
			{
				dspl_Enable(temp);
				return;
			}

			/*
			* get parent window
			*/
			h = mfwParent(mfwParent(h));

			if (h)
				h = ((MfwWin * )(h->data))->elems;
		}
		
		mfw_bt_sign_exec (mfwRoot, event, para);
		
	}
	
	dspl_Enable(temp);

	return;
}

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

 $Function:		mfw_bt_sign_exec

 $Description:		This function sends the Mfw Bluetooth events from the Mfw to the BMI.

 $Returns:		None

 $Arguments:		None

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

BOOL mfw_bt_sign_exec (T_MFW_HDR * cur_elem, T_MFW_EVENT event, T_MFW_BT_PARA * para)
{
	MFW_BT_TRACE("mfw_bt_sign_exec");

	while (cur_elem)
	{
		/*
		* event handler is available
		*/
		if (cur_elem->type EQ MfwTypBt)
		{
			T_MFW_BT * bt_data;
			/*
			* handler is CM management handler
			*/
			bt_data = (T_MFW_BT *)cur_elem->data;
			if (bt_data->emask & event)
			{
				/*
				* event is expected by the call back function
				*/
				bt_data->event = event;
				switch (event)
				{
					/*
					** Generic Events
					*/
					case E_BT_ENABLE_CMPL:
						memcpy (&bt_data->para, para, sizeof (T_MFW_BT_ENABLE_CMPL));
						break;

					case E_BT_DISABLE_CMPL:
						memset(&bt_data->para, 0x00, sizeof(T_MFW_BT_PARA));
						break;

					/*
					** Device Manager Events
					*/
					case E_BT_DM_LINK_UP:
						memcpy (&bt_data->para, para, sizeof (T_MFW_BT_DM_LINK_UP));
						break;

					case E_BT_DM_LINK_DOWN:
						memcpy (&bt_data->para, para, sizeof (T_MFW_BT_DM_LINK_DOWN));
						break;

					case E_BT_DM_INQ_RES:
						memcpy (&bt_data->para, para, sizeof (T_MFW_BT_DM_INQ_RES));
						break;

					case E_BT_DM_INQ_CMPL:
						memcpy (&bt_data->para, para, sizeof (T_MFW_BT_DM_INQ_CMPL));
						break;

					case E_BT_DM_DISC_RES:
						memcpy (&bt_data->para, para, sizeof (T_MFW_BT_DM_DISC_RES));
						break;

					case E_BT_DM_DISC_CMPL:
						memset(&bt_data->para, 0x00, sizeof(T_MFW_BT_PARA));
						break;

					case E_BT_DM_PIN_REQ:
						memcpy (&bt_data->para, para, sizeof (T_MFW_BT_DM_PIN_REQ));
						break;

					case E_BT_DM_AUTH_CMPL:
						memcpy (&bt_data->para, para, sizeof (T_MFW_BT_DM_AUTH_CMPL));
						break;

					case E_BT_DM_AUTHORIZE_REQ:
						memcpy (&bt_data->para, para, sizeof (T_MFW_BT_DM_AUTHORIZE_REQ));
						break;

					case E_BT_DM_DEV_NAME_REQ:
						memset(&bt_data->para, 0x00, sizeof(T_MFW_BT_PARA));
						break;

					case E_BT_DM_SIG_STRENGTH_IND:
						memcpy (&bt_data->para, para, sizeof (T_MFW_BT_DM_SIG_STRENGTH_IND));
						break;

				}

				/*
				* if call back defined, call it
				*/
				if (bt_data->handler)
				{
					// store current mfw elem
					current_mfw_elem = cur_elem;

					if ((*(bt_data->handler)) (bt_data->event, (void *)&bt_data->para))
						return TRUE;
				}
			}
		}
		cur_elem = cur_elem->next;
	}
	return FALSE;
}


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

 $Function:		mfw_bt_ge_enable

 $Description:		This function initialises the Generic Event Handler, it should be active only
 				when bluetooth is enabled.

 $Returns:		MFW_BT_UNABLE_TO_CREATE_EVT_BUF	: Failed to start - memory problems
 				MFW_BT_SUCCESS					: Started OK, and Ready

 $Arguments:		None

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

T_MFW_BT_STATUS mfw_bt_ge_enable (void)
{
	SHORT cbufRetVal;

	MFW_BT_TRACE("mfw_bt_ge_enable");

	/*
	** Try to create the Circular Event Buffer
	*/
	cbufRetVal = mfw_cbuf_create(MFW_BT_MAX_SIG_Q_ENTRIES,		/* Max Entires */
								sizeof(T_MFW_BT_SIGNALS),		/* Item Size */
								FALSE,							/* Don't Overwrite */
								0xFF,							/* Null Character */
								FALSE,							/* Dynamic Buffer */
								(void *)0);						/* Buffer pointer not required */

	if (cbufRetVal == MFW_CBUF_MEM_ALLOC_FAILURE)
	{

		MFW_BT_TRACE("mfw_bt_ge_enable > Buffer Creation Failed with Mem Constraints");

		/*
		** Failed due to memory constraints, try again with half the number of entries
		*/
		cbufRetVal = mfw_cbuf_create(MFW_BT_MAX_SIG_Q_ENTRIES/2,	/* Max Entires */
									sizeof(T_MFW_BT_SIGNALS),		/* Item Size */
									FALSE,							/* Don't Overwrite */
									0xFF,							/* Null Character */
									FALSE,							/* Dynamic Buffer */
									(void *)0);						/* Buffer pointer not required */
		/*
		** All MFW_CBUF error codes are negative, 0 or a positive value from mfw_cbuf_create is a valid buffer Id
		*/
		if (cbufRetVal < 0)
		{

			MFW_BT_TRACE_P1("mfw_bt_ge_enable > Unable to Create Buffer : Error %d", cbufRetVal);

			/*
			** Failed to allocate buffer, return an error
			*/
			return MFW_BT_UNABLE_TO_CREATE_EVT_BUF;
		}
		
	}
	else if (cbufRetVal < 0)
	{

		MFW_BT_TRACE_P1("mfw_bt_ge_enable > Unable to Create Buffer : Error %d", cbufRetVal);

		/*
		** Failed to allocate buffer, return an error
		*/
		return MFW_BT_UNABLE_TO_CREATE_EVT_BUF;
	}


	MFW_BT_TRACE_P1("mfw_bt_ge_enable > Buffer created successfully with Id %d", cbufRetVal);

	/*
	** A buffer has been created, store the Id for future use.
	*/
	Mfw_Bt_Ge_Sigbuf_Id = cbufRetVal;

	return MFW_BT_SUCCESS;

}


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

 $Function:		mfw_bt_ge_disable

 $Description:		Disbales the Generic Event Handler, and releases the Dynamic Event Buffer

 $Returns:		None

 $Arguments:		None

*******************************************************************************/
void mfw_bt_ge_disable (void)
{

	MFW_BT_TRACE("mfw_bt_ge_disable");


	/*
	** Ensure the MFW Bluetooth Event handler is initialised
	*/
	if (Mfw_Bt_Ge_Sigbuf_Id < 0)
	{
		MFW_BT_TRACE("mfw_bt_ge_disable > Bluetooth Module Not Initialised");
	}
	else
	{
		mfw_cbuf_delete(Mfw_Bt_Ge_Sigbuf_Id);

		Mfw_Bt_Ge_Sigbuf_Id = -1;
	}
}


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

 $Function:		mfw_bt_ge_post_event

 $Description:		This function stores the incoming event in the event buffer, and if required,
 				notifies the MMI Task

 $Returns:		MFW_BT_NOT_INITIALISED	: Fn mfw_bt_ge_enable not called or failed
 				MFW_BT_INVALID_ORIG	: Invalid Originator Id received
 				MFW_BT_INVALID_EVENT	: Invalid Event Id received
 				MFW_BT_INVALID_DATA	: Mismatch between the data pointer and datalen values
 				MFW_BT_FAILED_TO_STORE_EVENT	: Event Buffer Full (check trace)
 				MFW_BT_SUCCESS		: Event Stored successfuly

 $Arguments:		originator		: Identifier for the originating profile that caused the event
 				eventId		: Event Identifier (See BTA Specification)
 				data			: pointer to the event data
 				dataLen		: length of the event data in bytes (must be 0 if data is (void *)0)

*******************************************************************************/
T_MFW_BT_STATUS mfw_bt_ge_post_event (T_MFW_BT_ORIGINATORS originator,
										ULONG eventId,
										void * data,
										int dataLen)
{
	T_MFW_BT_SIGNALS	sigBuffer;
	USHORT				numElements;
	SHORT				cbufRetVal;

	MFW_BT_TRACE("mfw_bt_ge_post_event");

	/*
	** Ensure the MFW Bluetooth Event handler is initialised
	*/
	if (Mfw_Bt_Ge_Sigbuf_Id < 0)
	{
		MFW_BT_TRACE("mfw_bt_ge_post_event > Bluetooth Module Not Initialised");
		return MFW_BT_NOT_INITIALISED;
	}

	/*
	** Validate the incoming Parameters
	*/

	if ((originator >= MFW_BT_MAX_ORIGINATOR) ||
	     ((originator & (ULONG)0xFFFF) != 0))
	{
		MFW_BT_TRACE_P1("mfw_bt_ge_post_event > Originator Invalid : 0x%lx", originator);
		return MFW_BT_INVALID_ORIG;
	}

	if (eventId > (ULONG)0xFFFF)
	{
		MFW_BT_TRACE_P1("mfw_bt_ge_post_event > Event Id  Invalid : 0x%lx", eventId);
		return MFW_BT_INVALID_EVENT;
	}

	if ((dataLen < 0) ||
	     ((data == (void *)0) && (dataLen != 0)) ||
	     ((data != (void *)0) && (dataLen == 0)))
	{
		MFW_BT_TRACE_P2("mfw_bt_ge_post_event > Data, DataLen combination Invalid : data 0x%lx, dataLen %d", data, dataLen);
	     return MFW_BT_INVALID_DATA;
	}

	/*
	** Create the Event for storage, which is combined from the OriginatorId and the EventId
	*/
	sigBuffer.event = originator | eventId;

	/*
	** Copy the Signal Data for storage
	*/
	memcpy((void *)&sigBuffer.data, data, dataLen);

	/*
	** Get the existing number of elements in the Event Buffer
	*/
	numElements = mfw_cbuf_num_elements (Mfw_Bt_Ge_Sigbuf_Id);

	/*
	** Post the event to the buffer
	*/
	cbufRetVal = mfw_cbuf_put(Mfw_Bt_Ge_Sigbuf_Id, (void *)&sigBuffer);
	
	if (cbufRetVal != MFW_CBUF_OK)
	{
		/*
		** Unable to store the data
		*/
		MFW_BT_TRACE_P1("mfw_bt_ge_post_event > Unable to store the event : Error %d", cbufRetVal);

		return MFW_BT_FAILED_TO_STORE_EVENT;
	}

	MFW_BT_TRACE("mfw_bt_ge_post_event > Event Successfully Stored");

	/*
	** If required, Post the MMI_BT_CB_NOTIFY_RXD_IND Primitive
	*/
	if ((numElements == 0) &&
	     (Mfw_Bt_Ge_InProgress == FALSE))
	{
		/*
		** Sending Primitive to MMI TASK
		*/
		MFW_BT_TRACE("mfw_bt_ge_post_event > Sending Primitive to MMI TASK");
		mfw_bt_send_cb_notify_ind();
	}
#ifdef MFW_BT_DEBUG
	else
	{
		/*
		** Sending Primitive to MMI TASK
		*/
		MFW_BT_TRACE("mfw_bt_ge_post_event > No need to send Primitive to MMI TASK");
	}
#endif

	return MFW_BT_SUCCESS;
}


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

 $Function:		mfw_bt_cb_notify_rxd

 $Description:		This function is called on receipt of the MMI_BT_CB_NOTIFY_IND primitive, it reads
 				the events from the event buffer and passes the details to the appropriate Profile
 				Handler. It will process a Maximum of MFW_BT_MAX_CONSEC_SIG_PROC events
 				before reposting the primitive to the MMI Queue and relinquishing control.

 $Returns:		None

 $Arguments:		None

*******************************************************************************/
void mfw_bt_cb_notify_rxd(void)
{
	T_MFW_BT_SIGNALS sigBuffer;
	T_MFW_BT_ORIGINATORS originatorId;
	T_MFW_BT_STATUS hndlrRetVal;
	ULONG eventId;
	UBYTE numSigsProcessed;
	SHORT cbufRetVal;

	MFW_BT_TRACE("mfw_bt_cb_notify_rxd");

	if (Mfw_Bt_Ge_Sigbuf_Id < 0)
	{
		MFW_BT_TRACE("Mfw_Bt_cb_notify_rxd > Bluetooth Module Not Initialised");
		return;
	}

	/*
	** Initialise Local and Module variables as required.
	*/
	Mfw_Bt_Ge_InProgress = TRUE;
	numSigsProcessed = 0;

	/*
	** While there are events in the Buffer, and the maximum number of signals have not
	** been processed ...
	*/
	while ((numSigsProcessed < MFW_BT_MAX_CONSEC_SIG_PROC) && (mfw_cbuf_num_elements(Mfw_Bt_Ge_Sigbuf_Id) > 0))
	{
		numSigsProcessed++;

		/*
		** Read the event details from the buffer
		*/
		cbufRetVal = mfw_cbuf_get(Mfw_Bt_Ge_Sigbuf_Id, (void *)&sigBuffer);

		if (cbufRetVal != MFW_CBUF_OK)
		{
			Mfw_Bt_Ge_InProgress = FALSE;
			(void)mfw_cbuf_reset(Mfw_Bt_Ge_Sigbuf_Id);
			MFW_BT_TRACE_P1("Mfw_Bt_cb_notify_rxd > Unable to read events from Buffer : Error %d", cbufRetVal);
			return;
		}

		/*
		** Seperate the Originator and Event Id values
		*/
		originatorId = sigBuffer.event & (ULONG)0xFFFF0000;
		eventId = sigBuffer.event & (ULONG)0x0000FFFF;

		/*
		** switch on the originator Id
		*/
		switch (originatorId)
		{
			case MFW_BT_DM_SECURITY:
				hndlrRetVal = mfw_bt_dm_security_hndlr((T_MFW_BT_DM_SEC_EVT)eventId,
													    (T_MFW_BT_DM_SEC_SIG_DATA *)&sigBuffer.data.dmSecSignals);
				break;

			case MFW_BT_DM_SEARCH:
				hndlrRetVal = mfw_bt_dm_search_hndlr((T_MFW_BT_DM_SRCH_EVT)eventId,
													  (T_MFW_BT_DM_SRCH_SIG_DATA *)&sigBuffer.data.dmSrchSignals);
				break;

			case MFW_BT_DG:
				hndlrRetVal = mfw_bt_dg_hndlr((T_MFW_BT_DG_EVT)eventId,
											 (T_MFW_BT_DG_SIG_DATA *)&sigBuffer.data.dgSignals);
				break;

			case MFW_BT_AG:
				hndlrRetVal = mfw_bt_ag_hndlr((T_MFW_BT_AG_EVT)eventId,
											  (T_MFW_BT_AG_SIG_DATA *)&sigBuffer.data.agSignals);
				break;

			case MFW_BT_OPC:
				hndlrRetVal = mfw_bt_opc_hndlr((T_MFW_BT_OPC_EVT)eventId,
											   (T_MFW_BT_OPC_SIG_DATA *)&sigBuffer.data.opcSignals);
				break;

			case MFW_BT_OPS:
				hndlrRetVal = mfw_bt_ops_hndlr((T_MFW_BT_OPS_EVT)eventId,
											   (T_MFW_BT_OPS_SIG_DATA *)&sigBuffer.data.opsSignals);
				break;

			case MFW_BT_FTC:
				hndlrRetVal = mfw_bt_ftc_hndlr((T_MFW_BT_FTC_EVT)eventId,
											  (T_MFW_BT_FTC_SIG_DATA *)&sigBuffer.data.ftcSignals);
				break;

			case MFW_BT_FTS:
				hndlrRetVal = mfw_bt_fts_hndlr((T_MFW_BT_FTS_EVT)eventId,
											  (T_MFW_BT_FTS_SIG_DATA *)&sigBuffer.data.ftsSignals);
				break;

			default:
				MFW_BT_TRACE_P1("mfw_bt_cb_notify_rxd > Invalid Originator 0x%lx", originatorId);
				hndlrRetVal = MFW_BT_SUCCESS;		/* Set the return value to success because an error has already been reported */
				
		}

		if (hndlrRetVal <= 0)
		{
			/* Error reported by the handler, not a lot can be done, expect report it */
			MFW_BT_TRACE_P2("mfw_bt_cb_notify_rxd > Error %d returned from Event handler for Originator 0x%lx", hndlrRetVal, originatorId);
		}
	}

	Mfw_Bt_Ge_InProgress = FALSE;

	/*
	** If there are still signals in the buffer, send another MMI_BT_CB_NOTIFY_RXD_IND primitive
	*/
	if (mfw_cbuf_num_elements(Mfw_Bt_Ge_Sigbuf_Id) > 0)
	{
		MFW_BT_TRACE("Mfw_Bt_cb_notify_rxd > Send the MMI_BT_CB_NOTIFY_IND signal");
		mfw_bt_send_cb_notify_ind();
	}

	return;
}


/**************************************************************************************************
**
** Local Function Definitions
**
**************************************************************************************************/

#define hCommACI _ENTITY_PREFIXED(hCommACI)


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

 $Function:		mfw_bt_send_cb_notify_ind

 $Description:		This function posts the MMI_BT_CB_NOTIFY_IND primitive to the MMI Queue

 $Returns:		None

 $Arguments:		None

*******************************************************************************/
static void mfw_bt_send_cb_notify_ind (void)
{
#if defined (NEW_FRAME)
	EXTERN T_HANDLE hCommACI;


	ULONG signal_raw;
#else
	EXTERN T_VSI_CHANDLE hCommACI;
#endif

	PALLOC(bt_cb_notify_ind,MMI_BT_CB_NOTIFY_IND);

	MFW_BT_TRACE("mfw_bt_send_cb_notify_ind");

#if defined (NEW_FRAME)
	PSENDX(ACI,bt_cb_notify_ind);
#else
#if defined (_TMS470)
	vsi_c_send("",hCommACI,D2P(bt_cb_notify_ind),
	        sizeof(T_PRIM_HEADER)+sizeof(T_MMI_BT_CB_NOTIFY_IND));
#else
	PSEND(ACI,bt_cb_notify_ind);
#endif
#endif

	return;

}
