📄 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>
#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;
} 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 */
};
/*************************************************************************
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);
}
/*************************************************************************
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)));
}
/* USB does not have the concept of Combo Boot devices. We therefore default
to present just the keyboard functionality which is the most useful. */
if (theDevice->dev_class & HID_MINOR_KEYBOARD)
{
MAIN_PRINT(("Starting keyboard transform\n"));
/* We are a keyboard, create the transform and configure the current idle rate. */
theDevice->transform = TransformHidKeyboard(StreamSourceFromSink(theDevice->hid_sink), StreamUsbEndPointSink(KEYBOARD_ENDPOINT_ADDRESS));
/* Set idle to last requested value */
TransformConfigure(theDevice->transform, VM_TRANSFORM_HID_KEYBOARD_IDLE_RATE, theDevice->settings.keyboard.idle_rate);
/* Enable the transform to let data flow */
TransformStart(theDevice->transform);
}
else if (theDevice->dev_class & HID_MINOR_MOUSE)
{
MAIN_PRINT(("Starting mouse transform\n"));
/* 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 */
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -