Я думаю, ты моя последняя надежда. У меня есть Bluetooth-устройство (точнее, датчик), к которому я хочу подключиться и считывать данные. Устройство предлагает SPP (профиль последовательного порта). Чтобы избежать проблемы надежного сопоставления с адресами Bluetooth и виртуальными последовательными портами (COM-портами), я собираюсь использовать сокеты.
К сожалению, приложение всегда вылетает, прежде чем вернуться из функции WinAPI. connect (...) с: 0xC0000005: Место чтения нарушения доступа 0x00000004 , поэтому я получаю без кода ошибки .
НО, и это странно, когда я щелкаю правой кнопкой мыши на значке в системном трее Bluetooth, чтобы показать доступные устройства, мое устройство обнаруживает аутентификацию и подключение. Этот список, конечно, был пуст до ,
Моя ОС - Windows 7 64-разрядная, IDE - Visual Studio 2010, стек Microsoft Bluetooth. Код для поиска и подключения к моему единственному устройству:
#include <iostream>
#include <string>
#include <algorithm>
#include <cassert>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <BluetoothAPIs.h>
#include <Winsock2.h>
#include <Ws2bth.h>
BOOL auth_callback_ex(LPVOID pvParam, PBLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS authParams)
{
BLUETOOTH_AUTHENTICATE_RESPONSE response;
response.bthAddressRemote = authParams->deviceInfo.Address;
response.authMethod = authParams->authenticationMethod; // == BLUETOOTH_AUTHENTICATION_METHOD_LEGACY
UCHAR pin[] = "1234";
std::copy(pin, pin+sizeof(pin), response.pinInfo.pin);
response.pinInfo.pinLength = sizeof(pin)-1; //excluding '\0'
response.negativeResponse = false;
HRESULT err = BluetoothSendAuthenticationResponseEx(NULL, &response);
if (err)
{
std::cout << "BluetoothSendAuthenticationResponseEx error = " << err << std::endl;
}
return true;
}
int main()
{
BLUETOOTH_DEVICE_SEARCH_PARAMS btSearchParams;
btSearchParams.dwSize = sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS);
btSearchParams.cTimeoutMultiplier = 5; //5*1.28s search timeout
btSearchParams.fIssueInquiry = true; //new inquiry
//return all known and unknown devices
btSearchParams.fReturnAuthenticated = true;
btSearchParams.fReturnConnected = true;
btSearchParams.fReturnRemembered = true;
btSearchParams.fReturnUnknown = true;
btSearchParams.hRadio = NULL; //search on all local radios
BLUETOOTH_DEVICE_INFO btDeviceInfo;
ZeroMemory(&btDeviceInfo, sizeof(BLUETOOTH_DEVICE_INFO)); //"initialize"
btDeviceInfo.dwSize = sizeof(BLUETOOTH_DEVICE_INFO);
HBLUETOOTH_DEVICE_FIND btDeviceFindHandle = NULL;
btDeviceFindHandle = BluetoothFindFirstDevice(&btSearchParams, &btDeviceInfo);
if(btDeviceFindHandle)
{
HBLUETOOTH_AUTHENTICATION_REGISTRATION authCallbackHandle = NULL;
DWORD err = BluetoothRegisterForAuthenticationEx(&btDeviceInfo, &authCallbackHandle, &auth_callback_ex, NULL);
if (err != ERROR_SUCCESS)
{
DWORD err = GetLastError();
std::cout << "BluetoothRegisterForAuthentication Error" << err << std::endl;
}
/////////////// Socket
WSADATA wsaData;
err = WSAStartup(MAKEWORD(2,2), &wsaData);
if (err)
{
std::cout << "WSAStartup error = " << err << std::endl;
}
// create BT socket
SOCKET s = socket (AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
assert(s != INVALID_SOCKET); //WSAGetLastError //throw // runtime check release?
SOCKADDR_BTH btSockAddr;
btSockAddr.addressFamily = AF_BTH;
btSockAddr.btAddr = btDeviceInfo.Address.ullLong;
btSockAddr.serviceClassId = RFCOMM_PROTOCOL_UUID; //SerialPortServiceClass_UUID (no difference)
btSockAddr.port = BT_PORT_ANY;
err = connect(s, reinterpret_cast<SOCKADDR*>(&btSockAddr), sizeof(SOCKADDR_BTH));
/* <--- never got so far --> */
if (err)
{
DWORD wsaErr = WSAGetLastError();
std::cout << "connect error = " << wsaErr << std::endl;
}
else
{
//err = shutdown(s, SD_BOTH);
err = closesocket(s);
if (err)
{
std::cout << "closesocket error = " << err << std::endl;
}
}
WSACleanup();
///////////////Socket
BOOL ok = BluetoothUnregisterAuthentication(authCallbackHandle);
if (!ok)
{
DWORD err = GetLastError();
std::cout << "BluetoothUnregisterAuthentication Error" << err << std::endl;
}
ok = BluetoothFindDeviceClose(btDeviceFindHandle);
if (!ok)
{
DWORD err = GetLastError();
std::cout << "BluetoothDeviceClose Error" << err << std::endl;
}
}
else
{
DWORD err = GetLastError();
std::cout << "BluetoothFindFirstDevice Error" << err << std::endl;
}
std::cin.get();
}
Я сделал еще несколько замечаний:
- Обратный вызов аутентификации и функция BluetoothSendAuthenticationResponseEx работают нормально, ошибки не возвращаются.
- Если я не устанавливаю обратный вызов аутентификации ( BluetoothRegisterForAuthenticationEx ) и, следовательно, должен вручную вводить PIN-код (пользовательский интерфейс отображается автоматически при попытке подключения), функция connect возвращается правильно и все тоже отлично работает. Я даже получил данные (часть recv в этом фрагменте опущена).
- Если я ищу и выполняю сопряжение полностью вручную (иконка в трее Bluetooth -> Добавить устройство), все тоже хорошо. Служба и виртуальный последовательный порт установлены. Данные поступают через замазку.
Итак, где-то между вызовом аутентификации и завершением функции connect что-то идет не так. Может быть, при попытке получить определенную структуру данных через указатель, который не должен быть NULL плюс смещение.
Или я что-то не так делаю? Чего-то не хватает?
Спасибо ...