📄 bthid.cxx
字号:
//
// Hid parser interface
//
//
// Parser interface
//
int HidDevice::SetIdle(unsigned char bIdle) {
// Initialize the packets
BTHHIDPacket requestPacket;
requestPacket.SetHeader(BTHID_SET_IDLE << 4);
requestPacket.SetPayload(&bIdle, sizeof(bIdle));
return WriteControlPacket (this, &requestPacket, BTH_WIRE_TIMEOUT, NULL);
}
int HidDevice::SetProtocol(E_BTHID_PROTOCOLS protocol) {
// Initialize the packets
BTHHIDPacket requestPacket;
BTHID_Header_Parameter param;
// Initialize the packets
param.bRawHeader = 0;
param.setprotocol_p.bProtocol = protocol;
requestPacket.SetHeader((BTHID_SET_PROTOCOL << 4) | param.bRawHeader);
return WriteControlPacket (this, &requestPacket, BTH_WIRE_TIMEOUT, NULL);
}
int HidDevice::SetReport(E_BTHID_REPORT_TYPES type, PCHAR pBuffer, int cbBuffer, int iTimeout) {
// Initialize the packets
BTHHIDPacket requestPacket;
BTHID_Header_Parameter SetReport_param;
// Initialize the packets
SetReport_param.bRawHeader = 0;
SetReport_param.setreport_p.bReportType = type;
// Start by sending BTHIDSetReport_Request down the pipe.
requestPacket.SetHeader((BTHID_SET_REPORT << 4) | SetReport_param.bRawHeader);
requestPacket.SetPayload((PBYTE) pBuffer, cbBuffer);
return WriteControlPacket (this, &requestPacket, iTimeout, NULL);
}
int HidDevice::GetReport(int iReportID, E_BTHID_REPORT_TYPES type, PCHAR pBuffer, int cbBuffer, PDWORD pcbTransfered, int iTimeout) {
// Initialize the packets
BTHHIDPacket requestPacket;
BTHID_Header_Parameter GetReport_param;
// Initialize the packets
GetReport_param.bRawHeader = 0;
GetReport_param.getreport_p.bReportType = type;
GetReport_param.getreport_p.bSize = 0;
// Start by sending BTHIDGetReport_Request down the pipe.
requestPacket.SetHeader((BTHID_GET_REPORT << 4) | GetReport_param.bRawHeader);
BTHHIDPacket *pPacket = NULL;
int iErr = WriteControlPacket (this, &requestPacket, iTimeout, &pPacket);
if (iErr == ERROR_SUCCESS) {
// Check if the request succeeded
BYTE bHeader = pPacket->GetHeader();
if ((bHeader >> 4) == BTHID_DATA) {
// Request succeeded, get the payload to the caller
BYTE *pPacketPayload;
int cbPacketPayload;
pPacket->GetPayload(&pPacketPayload, &cbPacketPayload);
if (cbBuffer >= cbPacketPayload) {
memcpy(pBuffer, pPacketPayload, cbPacketPayload);
*pcbTransfered = cbPacketPayload;
} else
iErr = ERROR_INSUFFICIENT_BUFFER;
} else
iErr = ERROR_INVALID_DATA;
pPacket->ReleasePayload ();
delete pPacket;
}
return iErr;
}
//
// Main API section
//
static int HIDConnect (BT_ADDR *pbt) {
BD_ADDR *pba = (BD_ADDR *)pbt;
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
HidDevice *pDev = FindDevice (pba);
if (! pDev)
pDev = MakeNewDevice (pba, FALSE);
if (pDev && pDev->ckDeviceTimeout) {
gpState->pSchedule->UnScheduleEvent (pDev->ckDeviceTimeout);
pDev->ckDeviceTimeout = 0;
}
gpState->Unlock ();
if (! pDev)
return ERROR_CONNECTION_REFUSED;
unsigned short cidControl = 0;
int iRes = HIDConnect_Int (pba, BTH_PSM_CONTROL, &cidControl);
if (iRes != ERROR_SUCCESS)
return iRes;
unsigned short cidInterrupt = 0;
iRes = HIDConnect_Int (pba, BTH_PSM_INTERRUPT, &cidInterrupt);
if (iRes != ERROR_SUCCESS) {
HIDCloseCID_Int (cidControl);
return iRes;
}
return ERROR_SUCCESS;
}
static int HIDVerify (unsigned char *ucSDP, unsigned int cSDP) {
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
BTHHIDSdpParser sdpParser;
int iErr = sdpParser.Start (ucSDP, cSDP);
BOOL bb = FALSE;
if (iErr == ERROR_SUCCESS)
iErr = sdpParser.GetHIDReconnectInitiate(&bb);
if (iErr == ERROR_SUCCESS)
iErr = sdpParser.GetHIDNormallyConnectable(&bb);
if (iErr == ERROR_SUCCESS)
iErr = sdpParser.GetHIDVirtualCable(&bb);
// Pass in an empty structure to retrieve the size of the blob
BLOB blobReportDescriptor = {0, NULL};
if (iErr == ERROR_SUCCESS)
iErr = sdpParser.GetHIDReportDescriptor(&blobReportDescriptor);
if (iErr == ERROR_SUCCESS) {
// Now we have the size. Allocate and requery.
SVSUTIL_ASSERT(blobReportDescriptor.cbSize > 0);
blobReportDescriptor.pBlobData = (unsigned char *)g_funcAlloc (blobReportDescriptor.cbSize, g_pvAllocData);
iErr = sdpParser.GetHIDReportDescriptor(&blobReportDescriptor);
if (iErr == ERROR_SUCCESS)
g_funcFree (blobReportDescriptor.pBlobData, g_pvFreeData);
}
sdpParser.End ();
if (iErr != ERROR_SUCCESS) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: HIDVerify - parsing SDP record failed\n"));
} else {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: HIDVerify - successfully parsed SDP record\n"));
}
gpState->Unlock ();
return iErr;
}
//
// Marshaling code
//
#define TASK_CONNECT 1
#define TASK_VERIFY 2
struct Task {
unsigned int what;
union {
struct {
BT_ADDR b;
} Connect;
struct {
unsigned int cSDP;
unsigned char ucSDP[1];
} Verify;
};
};
static DWORD WINAPI ExecThread (LPVOID lpTask) {
Task *pTask = (Task *)lpTask;
DWORD dwError = ERROR_CALL_NOT_IMPLEMENTED;
if (pTask->what == TASK_CONNECT)
dwError = HIDConnect (&pTask->Connect.b);
else if (pTask->what == TASK_VERIFY)
dwError = HIDVerify (pTask->Verify.ucSDP, pTask->Verify.cSDP);
return dwError;
}
static int Exec (Task *pTask) {
HANDLE hThread = CreateThread (NULL, 0, ExecThread, pTask, 0, NULL);
if (! hThread)
return GetLastError ();
WaitForSingleObject (hThread, INFINITE);
DWORD dwCode;
if (! GetExitCodeThread (hThread, &dwCode))
dwCode = GetLastError ();
CloseHandle (hThread);
return dwCode;
}
#if defined (UNDER_CE)
//
// Driver service funcs...
//
extern "C" BOOL WINAPI DllMain( HANDLE hInstDll, DWORD fdwReason, LPVOID lpvReserved) {
switch(fdwReason) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls ((HMODULE)hInstDll);
svsutil_Initialize ();
break;
case DLL_PROCESS_DETACH:
svsutil_DeInitialize ();
break;
}
return TRUE;
}
#if defined (SDK_BUILD)
HANDLE OpenEvent (DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName) {
return CreateEvent (NULL, TRUE, FALSE, lpName);
}
#endif
static DWORD WINAPI StackInitialize (LPVOID lpUnused) {
for (int i = 0 ; i < 100 ; ++i) {
HANDLE hBthStackInited = OpenEvent (EVENT_ALL_ACCESS, FALSE, BTH_NAMEDEVENT_STACK_INITED);
if (hBthStackInited) {
DWORD dwRes = WaitForSingleObject (hBthStackInited, INFINITE);
CloseHandle (hBthStackInited);
if (WAIT_OBJECT_0 == dwRes)
return hiddev_CreateDriverInstance ();
}
Sleep (1000);
}
return ERROR_TIMEOUT;
}
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// EXECUTION THREAD: Client-application!
// These functions are only executed on the caller's thread
// i.e. the thread belongs to the client application
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// @func PVOID | BHI_Init | Device initialization routine
// @parm DWORD | dwInfo | Info passed to RegisterDevice
// @rdesc Returns a DWORD which will be passed to Open & Deinit or NULL if
// unable to initialize the device.
// @remark Routine exported by a device driver. "PRF" is the string passed
// in as lpszType in RegisterDevice
extern "C" DWORD BHI_Init (DWORD Index) {
DebugInit();
HANDLE hBthStackInited = OpenEvent (EVENT_ALL_ACCESS, FALSE, BTH_NAMEDEVENT_STACK_INITED);
if (hBthStackInited) {
DWORD dwRes = WaitForSingleObject (hBthStackInited, 0);
CloseHandle (hBthStackInited);
if (WAIT_OBJECT_0 == dwRes)
return (DWORD)(hiddev_CreateDriverInstance () == ERROR_SUCCESS);
}
CloseHandle (CreateThread (NULL, 0, StackInitialize, NULL, 0, NULL));
return TRUE;
}
// @func PVOID | BHI_Deinit | Device deinitialization routine
// @parm DWORD | dwData | value returned from BHI_Init call
// @rdesc Returns TRUE for success, FALSE for failure.
// @remark Routine exported by a device driver. "PRF" is the string
// passed in as lpszType in RegisterDevice
extern "C" BOOL BHI_Deinit(DWORD dwData) {
hiddev_CloseDriverInstance ();
DebugDeInit();
return TRUE;
}
// @func PVOID | BHI_Open | Device open routine
// @parm DWORD | dwData | value returned from BHI_Init call
// @parm DWORD | dwAccess | requested access (combination of GENERIC_READ
// and GENERIC_WRITE)
// @parm DWORD | dwShareMode | requested share mode (combination of
// FILE_SHARE_READ and FILE_SHARE_WRITE)
// @rdesc Returns a DWORD which will be passed to Read, Write, etc or NULL if
// unable to open device.
// @remark Routine exported by a device driver. "PRF" is the string passed
// in as lpszType in RegisterDevice
extern "C" DWORD BHI_Open (DWORD dwData, DWORD dwAccess, DWORD dwShareMode) {
HANDLE *ph = (HANDLE *)g_funcAlloc (sizeof(HANDLE), g_pvAllocData);
ph[0] = NULL;
return (DWORD)ph;
}
// @func BOOL | BHI_Close | Device close routine
// @parm DWORD | dwOpenData | value returned from BHI_Open call
// @rdesc Returns TRUE for success, FALSE for failure
// @remark Routine exported by a device driver. "PRF" is the string passed
// in as lpszType in RegisterDevice
extern "C" BOOL BHI_Close (DWORD dwData) {
HANDLE *ph = (HANDLE *)dwData;
if (ph && ph[0])
ProcessExited (ph[0]);
if (ph)
g_funcFree (ph, g_pvFreeData);
return TRUE;
}
// @func DWORD | BHI_Write | Device write routine
// @parm DWORD | dwOpenData | value returned from BHI_Open call
// @parm LPCVOID | pBuf | buffer containing data
// @parm DWORD | len | maximum length to write [IN BYTES, NOT WORDS!!!]
// @rdesc Returns -1 for error, otherwise the number of bytes written. The
// length returned is guaranteed to be the length requested unless an
// error condition occurs.
// @remark Routine exported by a device driver. "PRF" is the string passed
// in as lpszType in RegisterDevice
//
extern "C" DWORD BHI_Write (DWORD dwData, LPCVOID pInBuf, DWORD dwInLen) {
return -1;
}
// @func DWORD | BHI_Read | Device read routine
// @parm DWORD | dwOpenData | value returned from BHI_Open call
// @parm LPVOID | pBuf | buffer to receive data
// @parm DWORD | len | maximum length to read [IN BYTES, not WORDS!!]
// @rdesc Returns 0 for end of file, -1 for error, otherwise the number of
// bytes read. The length returned is guaranteed to be the length
// requested unless end of file or an error condition occurs.
// @remark Routine exported by a device driver. "PRF" is the string passed
// in as lpszType in RegisterDevice
//
extern "C" DWORD BHI_Read (DWORD dwData, LPVOID pBuf, DWORD Len) {
return -1;
}
// @func DWORD | BHI_Seek | Device seek routine
// @parm DWORD | dwOpenData | value returned from BHI_Open call
// @parm long | pos | position to seek to (relative to type)
// @parm DWORD | type | FILE_BEGIN, FILE_CURRENT, or FILE_END
// @rdesc Returns current position relative to start of file, or -1 on error
// @remark Routine exported by a device driver. "PRF" is the string passed
// in as lpszType in RegisterDevice
extern "C" DWORD BHI_Seek (DWORD dwData, long pos, DWORD type) {
return (DWORD)-1;
}
// @func void | BHI_PowerUp | Device powerup routine
// @comm Called to restore device from suspend mode. You cannot call any
// routines aside from those in your dll in this call.
extern "C" void BHI_PowerUp (void) {
return;
}
// @func void | BHI_PowerDown | Device powerdown routine
// @comm Called to suspend device. You cannot call any routines aside from
// those in your dll in this call.
extern "C" void BHI_PowerDown (void) {
return;
}
// @func BOOL | BHI_IOControl | Device IO control routine
// @parm DWORD | dwOpenData | value returned from BHI_Open call
// @parm DWORD | dwCode | io control code to be performed
// @parm PBYTE | pBufIn | input data to the device
// @parm DWORD | dwLenIn | number of bytes being passed in
// @parm PBYTE | pBufOut | output data from the device
// @parm DWORD | dwLenOut |maximum number of bytes to receive from device
// @parm PDWORD | pdwActualOut | actual number of bytes received from device
// @rdesc Returns TRUE for success, FALSE for failure
// @remark Routine exported by a device driver. "PRF" is the string passed
// in as lpszType in RegisterDevice
extern "C" BOOL BHI_IOControl(DWORD dwData, DWORD dwCode, PBYTE pBufIn,
DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut,
PDWORD pdwActualOut)
{
#if ! defined (SDK_BUILD)
if (dwCode == IOCTL_PSL_NOTIFY) {
PDEVICE_PSL_NOTIFY pPslPacket = (PDEVICE_PSL_NOTIFY)pBufIn;
if ((pPslPacket->dwSize == sizeof(DEVICE_PSL_NOTIFY)) && (pPslPacket->dwFlags == DLL_PROCESS_EXITING)){
SVSUTIL_ASSERT (*(HANDLE *)dwData == pPslPacket->hProc);
ProcessExited ((HANDLE)pPslPacket->hProc);
}
return TRUE;
}
#endif
HANDLE *ph = (HANDLE *)dwData;
SVSUTIL_ASSERT (ph);
if (! ph[0])
ph[0] = GetCallerProcess ();
SVSUTIL_ASSERT (ph[0] == GetCallerProcess());
int iError = ERROR_SUCCESS;
switch (dwCode) {
case BTHHID_IOCTL_HIDConnect:
if (dwLenIn == sizeof(BT_ADDR)) {
Task *pTask = (Task *)LocalAlloc (LMEM_FIXED, sizeof(Task));
if (pTask) {
pTask->what = TASK_CONNECT;
memcpy (&pTask->Connect.b, pBufIn, sizeof(pTask->Connect.b));
iError = Exec(pTask);
LocalFree (pTask);
} else
iError = ERROR_OUTOFMEMORY;
} else
iError = ERROR_INVALID_PARAMETER;
break;
case BTHHID_IOCTL_HIDVerify:
if (dwLenIn > 0) {
Task *pTask = (Task *)LocalAlloc (LMEM_FIXED, sizeof(Task) + dwLenIn);
if (pTask) {
pTask->what = TASK_VERIFY;
memcpy (pTask->Verify.ucSDP, pBufIn, dwLenIn);
pTask->Verify.cSDP = dwLenIn;
iError = Exec(pTask);
LocalFree (pTask);
} else
iError = ERROR_OUTOFMEMORY;
} else
iError = ERROR_INVALID_PARAMETER;
break;
default:
IFDBG(DebugOut (DEBUG_WARN, L"Unknown control code %d\n", dwCode));
iError = ERROR_CALL_NOT_IMPLEMENTED;
}
if (iError != ERROR_SUCCESS) {
SetLastError(iError);
return FALSE;
}
return TRUE;
}
#if defined(UNDER_CE) && CE_MAJOR_VER < 0x0003
extern "C" int _isctype(int c, int mask) {
if ((c < 0) || (c > 0xff))
return 0;
return iswctype((wchar_t)c,(wctype_t)mask);
}
#endif //defined(UNDER_CE) && CE_MAJOR_VER < 0x0003
#endif // UNDER_CE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -