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

📄 bthsco.cxx

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 CXX
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/**
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.


Abstract:
    Windows CE Bluetooth SCO layer 

**/
#include <windows.h>

#if defined (SDK_BUILD)
#undef CP_UTF8
#endif

#include <pkfuncs.h>
#include <bt_hcip.h>

#include "bthsco.h"

DECLARE_DEBUG_VARS();

#define DEBUG_SCO_TRACE         DEBUG_HCI_TRACE //0x4
#define DEBUG_DATA_PACKET_UP    DEBUG_HCI_TRACE
#define DEBUG_DATA_PACKET_DOWN  DEBUG_HCI_TRACE

//
// Need typedefs for HCI_EstablishDeviceContext and HCI_CloseDeviceContext because
// we do LoadLibrary on btd.dll to invoke those functions.
//

typedef int (*HCI_EstablishDeviceContext_t)
(
void                    *pUserContext,      /* IN */
unsigned int            uiControl,          /* IN */
BD_ADDR                 *pba,               /* IN */
unsigned int            class_of_device,    /* IN */
unsigned char           link_type,          /* IN */
HCI_EVENT_INDICATION    *pInd,              /* IN */
HCI_CALLBACKS           *pCall,             /* IN */
HCI_INTERFACE           *pInt,              /* OUT */
int                     *pcDataHeaders,     /* OUT */
int                     *pcDataTrailers,    /* OUT */
HANDLE                  *phDeviceContext    /* OUT */
);

typedef int (*HCI_CloseDeviceContext_t)
(
HANDLE                  hDeviceContext      /* IN */
);



#define BT_ROLE_SWITCH      0
#define BT_NO_ROLE_SWITCH   1

// SCO baseband packet types
#define BT_PACKET_TYPE_HV1  0x0020
#define BT_PACKET_TYPE_HV2  0x0040
#define BT_PACKET_TYPE_HV3  0x0080

#define SCO_PACKET_HEADER_LEN 3

//
// Call definitions
//

// values for fCallType
#define CALL_TYPE_CONNECT                       1
#define CALL_TYPE_DISCONNECT                    2
#define CALL_TYPE_READ_VOICE_SETTING            3
#define CALL_TYPE_WRITE_VOICE_SETTING           4
#define CALL_TYPE_WAIT_FOR_INCOMING_CONNECTION  5
#define CALL_TYPE_ACCEPT_INCOMING_CONNECTION    6
#define CALL_TYPE_WRITE_PACKET                  7
#define CALL_TYPE_DATA_PACKET_DOWN              8
#define CALL_TYPE_WRITE_SCO_FLOW_CONTROL        9
#define CALL_TYPE_READ_SCO_FLOW_CONTROL         10

struct Call {
    Call            *pNext;
    Call            *pPrev;

    HANDLE          hEvent;
    int             iResult;

    //
    // each fCallType has a struct (although it can be empty)
    // place stuff there that needs to be passed around from anywhere
    // from initial HCI function call to callback to event handler to 
    // user return data
    //
    unsigned char   fCallType;
    union {

        // CALL_TYPE_CONNECT
        struct {
            USHORT hAclConnection;
            USHORT hScoConnection;
        } Connect;

        // CALL_TYPE_DISCONNECT
        struct {
        } Disconnect;

        // CALL_TYPE_READ_VOICE_SETTING
        struct {
            VOICE_SETTING Setting;
        } ReadVoiceSetting;

        // CALL_TYPE_WRITE_VOICE_SETTING
        struct {
        } WriteVoiceSetting;

        // CALL_TYPE_WAIT_FOR_INCOMING_CONNECTION
        struct {
            BOOL    bAllAddresses;
            BD_ADDR Address;
        } WaitIncomingConnection;

        // CALL_TYPE_ACCEPT_INCOMING_CONNECTION
        struct {
            BD_ADDR Address;
            USHORT  hScoConnection;
        } AcceptIncomingConnection;

        // CALL_TYPE_WRITE_PACKET
        struct {
        } WritePacket;

        // CALL_TYPE_DATA_PACKET_DOWN
        struct {
            USHORT  hConnection;
            void    *pPacketUserContext;
        } DataPacketDown;

        // CALL_TYPE_WRITE_SCO_FLOW_CONTROL
        struct {
        } WriteScoFlowControl;

        // CALL_TYPE_READ_SCO_FLOW_CONTROL
        struct {
            BOOL    bEnabled;
        } ReadScoFlowControl;

    } uParameters;

    SCO_USER_CALL       *pUserCall;

    // a call that is on the queue, is either waiting to be sent to HCI 
    // or currently being processed by HCI.
    unsigned char       fInvokedHCI : 1;

    Call (void) {
        memset (this, 0, sizeof(*this));
    }
};

//
// Link definitions
//

struct Link {
    Link            *pNext;
    BD_ADDR         b;
    unsigned short  hScoConnection;
    unsigned short  hAclConnection;
};

class SCO : public SVSSynch, public SVSRefObj {
public:
    Call            *pCalls;
    Link            *pLinks;

    unsigned int    fIsRunning : 1; // whether SCO is successfully connected to HCI (via HCI_EstablishedDeviceContext)
    unsigned int    fConnected : 1; // whether entire stack is up or down (BTH_STACK_DOWN,BTH_STACK_UP,BTH_STACK_DISCONNECT)
    unsigned int    fIsBinded  : 1; // whether SoundDriver has invoked sco_Bind

    HANDLE          hHCI;
    HANDLE			hClosingEvent;
    HCI_INTERFACE   hci_if;

    void            *pUserData;
    SCO_CALLBACKS   sco_callbacks;

    int             cHciHeaders;
    int             cHciTrailers;

    void Zero ()
    {
        pLinks = NULL;
        pCalls = NULL;
        hHCI = NULL;
        hClosingEvent = NULL;

        fIsRunning = FALSE;
        fConnected = FALSE;
        fIsBinded  = FALSE;

        memset (&hci_if, 0, sizeof (hci_if));

        pUserData = NULL;
        memset (&sco_callbacks, 0, sizeof (sco_callbacks));

        cHciHeaders = 0;
        cHciTrailers = 0;
    }

    SCO (void) 
    {
        Zero();
    }

    ~SCO (void) 
    {
    	if (hClosingEvent) {
    		CloseHandle(hClosingEvent);
    		hClosingEvent = NULL;
    	}
    }
};

//
// init/deinit functions
//
int sco_InitializeOnce      (void);
int sco_UninitializeOnce    (void);
int sco_CreateDriverInstance(void);
int sco_CloseDriverInstance (void);

//
// stack notification/init routines
//
static int          StackInitDevice ();
static int          StackNotifyUser (int iEvent);
static DWORD WINAPI StackDisconnect (LPVOID lpVoid);
static DWORD WINAPI StackDown       (LPVOID lpVoid);
static DWORD WINAPI StackUp         (LPVOID lpVoid);


//
// event handlers
//
static int sco_ConnectionComplete_Event         (void *pUserContext, void *pCallContext, unsigned char status, unsigned short connection_handle, BD_ADDR *pba, unsigned char link_type, unsigned char encryption_mode);
static int sco_ConnectionRequest_Event          (void *pUserContext, void *pCallContext, BD_ADDR *pba, unsigned int class_of_device, unsigned char link_type);
static int sco_DisconnectionComplete_Event      (void *pUserContext, void *pCallContext, unsigned char status, unsigned short connection_handle, unsigned char reason);
static int sco_Stack_Event                      (void *pUserContext, int iEvent, void *pEventContext);
static int sco_NumberOfCompletedPackets_Event   (void *pUserContext, void *pCallContext, unsigned short connection_handle, unsigned short num_of_completed_packets);
static int sco_DataPacketUp_Event               (void *pUserContext, unsigned short connection_handle,  BD_BUFFER *pBuffer);

//
// callbacks
//
static int sco_CallAborted_Out              (void *pCallContext, int iError);
static int sco_DataPacketDown_Out           (void *pCallContext, int iError);
static int sco_AddSCOConnection_Out         (void *pCallContext, unsigned char status);
static int sco_Disconnect_Out               (void *pCallContext, unsigned char status);
static int sco_AcceptConnectionRequest_Out  (void *pCallContext, unsigned char status);
static int sco_WriteVoiceSetting_Out        (void *pCallContext, unsigned char status);
static int sco_ReadVoiceSetting_Out         (void *pCallContext, unsigned char status, unsigned short voice_channel_setting);
static int sco_WriteSCOFlowControlEnable_Out(void *pCallContext, unsigned char status);
static int sco_ReadSCOFlowControlEnable_Out (void *pCallContext, unsigned char status, unsigned char SCO_flow_control_enable);


//
// interface
//
static int sco_Call_In              (SCO_USER_CALL* pUserCall);
static int sco_AbortUserCall_In     (SCO_USER_CALL* pUserCall);
static int sco_DataPacketDown_In    (void* pPacketUserContext, USHORT hConnection, PUCHAR pBuffer, DWORD dwBufferLen);

static int sco_Connect              (SCO_USER_CALL* pUserCall);
static int sco_Disconnect           (SCO_USER_CALL* pUserCall);
static int sco_WriteVoiceSetting    (SCO_USER_CALL* pUserCall);
static int sco_ReadVoiceSetting     (SCO_USER_CALL* pUserCall);
static int sco_RecvConnection       (SCO_USER_CALL* pUserCall);
static int sco_WritePacket          (SCO_USER_CALL* pUserCall);
static int sco_ioctl                (SCO_USER_CALL* pUserCall);

static int sco_AbortCall            (Call *pCall, BOOL bHciAbort);

// Call functions
static Call*    CallCreateNew       (unsigned char fCallType, BOOL bCreateCallEvent, SCO_USER_CALL *pUserCall);
static void     CallDelete          (Call* pCall);
static Call*    CallVerify          (Call* pCall, unsigned char fCallType);
static void     CallInsert          (Call* pCall);
static void     CallRemove          (Call* pCall);
static void     CallSetUserData     (SCO_USER_CALL *pUserCall, Call *pCall);
static void     CallSignal          (Call *pCall, int iResult);
static Call*    CallFindByUserCall  (SCO_USER_CALL *pUserCall);

//
// global variables
//
static SCO*                         gpLayerState                  = NULL;
static HMODULE                      ghModBtd                      = NULL;
static HCI_EstablishDeviceContext_t gpfHCI_EstablishDeviceContext = NULL;
static HCI_CloseDeviceContext_t     gpfHCI_CloseDeviceContext     = NULL;


static int StatusToError (unsigned char status, int iGeneric) 
{
    switch (status) 
    {
        case BT_ERROR_SUCCESS:
            return ERROR_SUCCESS;

        case BT_ERROR_COMMAND_DISALLOWED:
        case BT_ERROR_UNKNOWN_HCI_COMMAND:
        case BT_ERROR_UNSUPPORTED_FEATURE_OR_PARAMETER:
        case BT_ERROR_INVALID_HCI_PARAMETER:
        case BT_ERROR_UNSUPPORTED_REMOTE_FEATURE:
            return ERROR_CALL_NOT_IMPLEMENTED;

        case BT_ERROR_NO_CONNECTION:
            return ERROR_DEVICE_NOT_CONNECTED;

        case BT_ERROR_HARDWARE_FAILURE:
        case BT_ERROR_UNSPECIFIED_ERROR:
            return ERROR_ADAP_HDW_ERR;

        case BT_ERROR_PAGE_TIMEOUT:
        case BT_ERROR_CONNECTION_TIMEOUT:
        case BT_ERROR_HOST_TIMEOUT:
            return ERROR_TIMEOUT;

        case BT_ERROR_AUTHENTICATION_FAILURE:
            return ERROR_NOT_AUTHENTICATED;

        case BT_ERROR_KEY_MISSING:
            return ERROR_NO_USER_SESSION_KEY;

        case BT_ERROR_MEMORY_FULL:
            return ERROR_OUTOFMEMORY;

        case BT_ERROR_MAX_NUMBER_OF_CONNECTIONS:
        case BT_ERROR_MAX_NUMBER_OF_SCO_CONNECTIONS:
        case BT_ERROR_MAX_NUMBER_OF_ACL_CONNECTIONS:
            return ERROR_NO_SYSTEM_RESOURCES;

        case BT_ERROR_HOST_REJECTED_LIMITED_RESOURCES:
        case BT_ERROR_HOST_REJECTED_SECURITY_REASONS:
        case BT_ERROR_HOST_REJECTED_PERSONAL_DEVICE:
        case BT_ERROR_PAIRING_NOT_ALLOWED:
            return ERROR_CONNECTION_REFUSED;

        case BT_ERROR_OETC_USER_ENDED:
        case BT_ERROR_OETC_LOW_RESOURCES:
        case BT_ERROR_OETC_POWERING_OFF:
            return ERROR_GRACEFUL_DISCONNECT;

        case BT_ERROR_CONNECTION_TERMINATED_BY_LOCAL_HOST:
            return ERROR_CONNECTION_ABORTED;

        case BT_ERROR_REPEATED_ATTEMPTS:
            return ERROR_CONNECTION_COUNT_LIMIT;
    }

    return iGeneric;
}

///////////////////////////////////////////////////
// Call functions
///////////////////////////////////////////////////

static Call* CallCreateNew(unsigned char fCallType, BOOL bCreateCallEvent, SCO_USER_CALL *pUserCall)
{
    Call *pCall = new Call;
    if (!pCall) {
        return NULL;
    }

    if (bCreateCallEvent) {
        pCall->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (!pCall->hEvent) {
            delete pCall;
            return NULL;
        }
    }

    pCall->fCallType  = fCallType;
    pCall->pUserCall  = pUserCall;

    return pCall;
}

static void CallDelete(Call* pCall)

⌨️ 快捷键说明

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