📄 app_device.c
字号:
/****************************************************************************
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 + -