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

📄 app_device.c

📁 Bluetooth HID emulation
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
Copyright (C) Cambridge Silicon Radio Ltd. 2005-2006
Part of BlueLab 3.6.2-release

FILE NAME
    app_device.c        
DESCRIPTION
    This file contains the HID dongle device task.
NOTES

*/

/****************************************************************************
    Header files
*/
#include "app_private.h"
#include "app_device.h"
#include "app_usb.h"
#include "app_sdp.h"

#include <boot.h>
#include <usb.h>
#include <panic.h> 
#include <sink.h>
#include <source.h>
#include <stream.h>
#include <stdlib.h>
#include <message.h>
#include <connection.h>
#include <transform.h>
#include <bdaddr.h>
#include <ps.h>
#include <app/bluestack/types.h>
#include <app/bluestack/bluetooth.h>
#include <app/bluestack/l2cap_prim.h>

#define SNUT_PSM 13

#ifdef APP_DEBUG
#include <stdio.h>
#define MAIN_PRINT(x) printf x
#else
#define MAIN_PRINT(x)
#endif

/* Internal messages */
enum
{
	APP_DEVICE_INTERNAL_CONNECT_REQ,
    APP_DEVICE_INTERNAL_CONNECT_IND,
    APP_DEVICE_INTERNAL_UNPLUG_REQ,
    APP_DEVICE_INTERNAL_UNPLUG_TIMEOUT_IND
};

/* Internal connect request message */
typedef struct
{
	bdaddr bd_addr;
    bool initial;
} APP_DEVICE_INTERNAL_CONNECT_REQ_T;

/* Internal connect indication message */
typedef struct
{
    /* HID *hid; */
	uint16 connection_id;
	
} APP_DEVICE_INTERNAL_CONNECT_IND_T;

/* Virtual unplug timeout */
#define APP_UNPLUG_TIMEOUT  (5)

/* Macros for creating messages */
#define MAKE_DEVICE_MESSAGE(TYPE) \
	TYPE##_T *message = PanicUnlessNew(TYPE##_T);

/* Lower power table, we don't care, the devices have there own power tables  */
static const lp_power_table app_power_table[]=
{
	/* mode,    	min_interval, max_interval, attempt, timeout, duration */
	{lp_passive,	0,            0,			0,		 0,	      0},
};
	
/* HID connection configuration */
static const hid_connection_config app_connection_config = 
{
    sizeof(app_power_table) / sizeof(lp_power_table), app_power_table,  /* Power table */
    11250,                                                              /* Latency (11.25ms) */
    TRUE,
};

/* Service search pattern */
static const uint8 app_hid_service_search_pattern[] = {0x35,0x03,0x19,0x11,0x24};

/* Mandatory attribute search patterns */
static const uint8 app_hid_attribute_list_mandatory[] = 
{
    0x35, 0x0c,
    0x09, 0x02, 0x01, /* HIDParserVersion */
    0x09, 0x02, 0x04, /* HIDVirtualCable */
    0x09, 0x02, 0x05, /* HIDReconnectInitiate */
    0x09, 0x02, 0x0e, /* HIDBootDevice */
};

/* Optional attribute search patterns */
static const uint8 app_hid_attribute_list_optional[] = 
{
    0x35,0x03,0x09,0x02,0x0d, /* HIDNormallyConnectable */
};


l2cap_config_params l2cap_config;
		
	    

/*************************************************************************
NAME    
    appHandleDeferedAction
DESCRIPTION
    This function is called to check if there is a defered actions.
RETURNS
    void     
*/
static void appHandleDeferedAction(appDeviceTaskData *theDevice)
{
    /* Check if we have an unplug pending */
    if (theDevice->unplug_pending)
    {
        /* Clear flag */
        theDevice->unplug_pending = FALSE;

        /* Resend unplug message to ourselves */
        MessageSend(&theDevice->task, APP_DEVICE_INTERNAL_UNPLUG_REQ, 0);
    }
}

/*************************************************************************
NAME    
    appDevFreeEnter
DESCRIPTION
    This function is called on entry to the free state, it removes the
    device from the persistent store and the trusted device list.
RETURNS
    void
*/
static void appDevUnpluggedEnter(appDeviceTaskData *theDevice)
{
	MAIN_PRINT(("appDevUnpluggedEnter\n"));

    /* Clear unplug pending flag */
    theDevice->unplug_pending = FALSE;

    /* Delete device from trusted device list */
    ConnectionSmDeleteAuthDevice(&theDevice->dev_info.bd_addr);

    /* Delete persistent store */
    PsStore(theDevice->dev_num, NULL, 0);

    /* Send unplug indication to app */
    MessageSend(&theDevice->theApp->task, APP_DEVICE_UNPLUG_IND, 0);

    /* Cancel unplug timer */
    MessageCancelAll(&theDevice->task, APP_DEVICE_INTERNAL_UNPLUG_TIMEOUT_IND);
}

/*************************************************************************
NAME
    appDevConnectingInitialEnter    
DESCRIPTION
    This function is called when entering the connection initial state,
    it initiates a SDP service and attribute search.
RETURNS
    void
*/
static void appDevConnectingInitialEnter(appDeviceTaskData *theDevice)
{
	MAIN_PRINT(("appDevConnectingInitialEnter\n"));
        
    /* Set SDP state */
    theDevice->sdp_state = appSdpMandatory;

    /* Disable outgoing SDP security */
    ConnectionSmSetSdpSecurityOut(TRUE, &theDevice->dev_info.bd_addr);

    /* Start SDP service and attribute search */
    ConnectionSdpServiceSearchAttributeRequest(&theDevice->task, &theDevice->dev_info.bd_addr, 20,
                                               sizeof(app_hid_service_search_pattern), app_hid_service_search_pattern,
                                               sizeof(app_hid_attribute_list_mandatory), app_hid_attribute_list_mandatory);
}

/*************************************************************************
NAME    
    appDevConnectingLocalEnter
DESCRIPTION
    This function is called on entry to the connecting local state.
    It initiates the HID connection.
RETURNS
    void
*/
static void appDevConnectingLocalEnter(appDeviceTaskData *theDevice)
{
	MAIN_PRINT(("appDevConnectingLocalEnter\n"));

    /* Start HID connection */
	/*
   	HidConnect(theDevice->theApp->hid_lib, &theDevice->task, &theDevice->dev_info.bd_addr, &app_connection_config);
	*/
	
	l2cap_config.mtu_local = MINIMUM_MTU; /*HID_L2CAP_MTU; */
    l2cap_config.mtu_remote_min = MINIMUM_MTU;
    l2cap_config.flush_timeout = DEFAULT_FLUSH_TO;
    l2cap_config.accept_non_default_flush = 1;
	l2cap_config.qos.service_type = DEFAULT_SERVICE_TYPE; /*(psm == HID_PSM_CONTROL) ? DEFAULT_SERVICE_TYPE : ((hid->config->qos_guaranteed) ? SERVICE_GUARANTEED : DEFAULT_SERVICE_TYPE);*/
    l2cap_config.qos.token_rate = DEFAULT_TOKEN_RATE;
    l2cap_config.qos.token_bucket = DEFAULT_TOKEN_BUCKET;
    l2cap_config.qos.peak_bw = DEFAULT_PEAK_BW;
	l2cap_config.qos.latency = 1110 ;/*(psm == HID_PSM_CONTROL) ? DEFAULT_LATENCY : hid->config->latency; */
   	l2cap_config.qos.delay_var = DEFAULT_DELAY_VAR;
    l2cap_config.accept_qos_settings = 1;
    l2cap_config.timeout = 5; /* sec, HID_L2CAP_TIMEOUT; */

	ConnectionL2capConnectRequest(&theDevice->task, &theDevice->dev_info.bd_addr, 
								  SNUT_PSM, SNUT_PSM, &l2cap_config);
}

/*************************************************************************
NAME    
    appDevConnectedEnter
DESCRIPTION
    This function is called on entry to the connected state.
    Is stores the device information in the persistent store and attempts
    to set the device into boot protocol mode.
RETURNS
    void
*/
static void appDevConnectedEnter(appDeviceTaskData *theDevice)
{
   	MAIN_PRINT(("appDevConnectedEnter, storing device information, nap=%d, uap=%d, lap=%ld\n",
                theDevice->dev_info.bd_addr.nap,
                theDevice->dev_info.bd_addr.uap,
                theDevice->dev_info.bd_addr.lap));
     
    /* Check if virtual cabled */        
   	if (theDevice->dev_info.hid_virtual_cable)
    {
        /* Store info in persistent store */
        PanicFalse(PsStore(theDevice->dev_num, &theDevice->dev_info, sizeof(theDevice->dev_info)));
    }

	if (theDevice->dev_class & HID_MINOR_MOUSE)
	{
    	MAIN_PRINT(("Starting mouse transform\n"));
        
		/* 酒付档 BT HID INTERRUPT 盲澄肺 坷绰 单捞磐甫 弊措肺 PASS窍绰 巴栏肺 焊烙 */
		/* Header 殿阑 绢骂 贸府 且瘤 葛福百栏唱, 鞘夸窍搁, L2CAP 惑困俊 Header 嘿捞绰 内靛甫 眠啊窍咯 傈价窍搁 瞪巴捞扼绊 抗惑窃 */
		
		/* We are a mouse, so just create and start it. */
		theDevice->transform = TransformHidMouse(StreamSourceFromSink(theDevice->hid_sink), StreamUsbEndPointSink(MOUSE_ENDPOINT_ADDRESS));
        
#ifdef HID_MOUSE_SEND_WHEEL
        TransformConfigure(theDevice->transform, VM_TRANSFORM_HID_MOUSE_ENABLE_SCROLL_DATA, TRUE);
#else
        TransformConfigure(theDevice->transform, VM_TRANSFORM_HID_MOUSE_ENABLE_SCROLL_DATA, FALSE);
#endif
		TransformStart(theDevice->transform);
	}
	else
	{
    	MAIN_PRINT(("Unknown device\n"));
        
		/* Unknown device, throw away any incoming Bluetooth data to prevent
		   buffer overflow. */
		StreamConnectDispose(StreamSourceFromSink(theDevice->hid_sink));
	}

    /* Send HID_SET_PROTOCOL(BOOT) to device */
	/* 泅犁 PC俊辑 盔窍绰 Protocol阑 傈崔窃 */
    /* HidSetProtocol(theDevice->hid, hid_protocol_boot); */

    /* Send connect indication to app */
    MessageSend(&theDevice->theApp->task, APP_DEVICE_CONNECT_IND, 0);
}


/*************************************************************************
NAME   
    appDevConnectedExit 
DESCRIPTION
    This function is called on exit from the connected state, it
    disconnects the interrupt channel from the host transport.
RETURNS
    void
*/
static void appDevConnectedExit(appDeviceTaskData *theDevice)
{
	MAIN_PRINT(("appDevConnectedExit\n"));
    
	/* Disconnect the device's interrupt channel from the host transport */
	StreamDisconnect(StreamSourceFromSink(theDevice->hid_sink), 0);
	StreamDisconnect(0, theDevice->hid_sink);

	/* Throw away any data arriving from the device
	   while we are disconnecting. */
	StreamConnectDispose(StreamSourceFromSink(theDevice->hid_sink));

    /* Send disconnect indication to app */
    MessageSend(&theDevice->theApp->task, APP_DEVICE_DISCONNECT_IND, 0);
}

/*************************************************************************
NAME    
    appDevDisconnectLocalEnter
DESCRIPTION
    Called on entry to the local disconnecting state. Initialise
    disconnecting HID connection.
RETURNS
    void
*/
static void  appDevDisconnectingLocalEnter(appDeviceTaskData *theDevice)
{
    MAIN_PRINT(("appDevDisconnectingLocalEnter\n"));

    /* Start HID disconnecting */
    HidDisconnect(theDevice->hid);
}

/*************************************************************************
NAME    
    appDevGetState
DESCRIPTION
    Returns current device state.
RETURNS
    appDevState - The current device state.
*/
static appDevState appDevGetState(appDeviceTaskData *theDevice)
{
	return theDevice->state;
}
 
/*************************************************************************
NAME    
    appDevSetState
DESCRIPTION
    This function sets the new device state, it handles calling any exit
    function for the old state and any entry function for the new state.
RETURNS
    void
*/
static void appDevSetState(appDeviceTaskData *theDevice, appDevState state)
{
    if (theDevice->state != state)
    {
        /* Handle exiting old state */
        switch (theDevice->state)
        {
            case appDevConnected:
                appDevConnectedExit(theDevice);
                break;
            default:
                break;
        }
    
        /* Set new state */
    	theDevice->state = state;
        
        /* Handle entering new state */
        switch (theDevice->state)
        {
            case appDevUnplugged:
                appDevUnpluggedEnter(theDevice);
                break;
            case appDevConnectingInitial:
                appDevConnectingInitialEnter(theDevice);
                break;
            case appDevConnectingLocal:
                appDevConnectingLocalEnter(theDevice);
                break;
            case appDevConnected:
                appDevConnectedEnter(theDevice);
                break;
            case appDevDisconnectingLocal:
                appDevDisconnectingLocalEnter(theDevice);
                break;
            default:
                break;
        }
    }

    appHandleDeferedAction(theDevice);
}

/*************************************************************************
NAME    
    appDevHandleUnexpected
DESCRIPTION
    Called when a unexpected message is received, in debug mode it
    will display the message id and state.
RETURNS
    void
*/
static void appDevHandleUnexpected(appDeviceTaskData *theDevice, MessageId id)
{
	MAIN_PRINT(("appDevHandleUnexpected, state %d, id%x\n", theDevice->state, id));
}

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

⌨️ 快捷键说明

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