[英]How to use WSASetService to advertise bluetooth service using WSAQUERYSET structure on Windows devices
我從https://docs.microsoft.com/en-us/windows/win32/bluetooth/bluetooth-and-wsasetservice讀到有兩種方法可以向本地 SDP 服務器提交服務:
應用程序可以讓系統公布一個簡單的藍牙 SDP 服務記錄,該記錄由 WSAQUERYSET 結構中的標准成員構建。
應用程序可以讓系統通過在 WSAQUERYSET 結構的 lpBlob 成員中傳遞 BTH_SET_SERVICE 結構來通告他們自己的藍牙 SDP 記錄。 這是一種更復雜的方法。
對我來說,第一個是首選,但我現在可以找到的所有代碼示例都使用第二個。 我認為這可能涉及到設置有關服務的信息,例如 WSAQUERYSET 成員中的地址、端口、服務 uuid:
//Service Information
int port = 4;
BTH_ADDR address = xxx;
GUID serviceUuid = {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx};
char* serviceName = "xxx";
//....
//Putting service information into WSAQUERYSET
WSAQUERYSET Service;
memset( &Service, 0, sizeof( Service ) );
Service.dwSize = sizeof( Service );
//Service.xxx = xxx
//...
Service.dwNameSpace = NS_BTH;
if ( WSASetService( &Service, RNRSERVICE_REGISTER, 0 ) == SOCKET_ERROR ) {
return WSAGetLastError();
}
else {
return 0;
}
目前,我在猜測如何設置這些屬性,但不知何故,我無法成功宣傳可以檢測到的服務。 我真的希望有一些可行的代碼示例。
一開始你不需要硬編碼port = 4;
但使用bind
獲取動態空閑端口,使用getsockname
獲取端口號。 例如(沒有錯誤檢查)
SOCKADDR_BTH asi = { AF_BTH, 0, {}, BT_PORT_ANY };
SOCKET s = WSASocket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM,
0, 0, WSA_FLAG_NO_HANDLE_INHERIT|WSA_FLAG_OVERLAPPED);
bind(s, (PSOCKADDR)&asi, sizeof(asi));
int len = sizeof(asi);
getsockname(s, (PSOCKADDR)&asi, &len);
那么您需要調用 WSASetService,如Bluetooth 和 WSAQUERYSET for Set Service中所述。 這里描述了WSAQUERYSET
中使用的所有參數。 只有一個例外 - lpszServiceInstanceName描述為
可選,但推薦。
但如果不使用它 - 我們得到了一個無效的參數被提供。 所以這是強制參數。
ULONG BthRegisterService(LPCGUID lpServiceClassId, PCWSTR ServiceName, PSOCKADDR_BTH asi)
{
CSADDR_INFO csa = {
{ (PSOCKADDR)asi, sizeof(SOCKADDR_BTH) }, {}, SOCK_STREAM, BTHPROTO_RFCOMM
};
WSAQUERYSET wqs = { sizeof(wqs) };
wqs.lpszServiceInstanceName = const_cast<PWSTR>(ServiceName);
wqs.lpServiceClassId = const_cast<PGUID>(lpServiceClassId);
wqs.dwNameSpace = NS_BTH;
wqs.dwNumberOfCsAddrs = 1;
wqs.lpcsaBuffer = &csa;
return WSASetService(&wqs, RNRSERVICE_REGISTER, 0) ? WSAGetLastError() : NOERROR;
}
這種方式的缺點 - 我們無法取回我們注冊的記錄的HANDLE
,對於帶有RNRSERVICE_DELETE
的后期調用WSASetService
- 為此需要使用指向BTH_SET_SERVICE
的BLOB
。 為此,我們需要通過自己的原始 SDP 記錄 stream 進行格式化。
所以調用BthRegisterService
我們可以這樣:
struct __declspec(uuid("00112233-4455-6677-8899-aabbccddeeff")) MyServiceClass;
BthRegisterService(&__uuidof(MyServiceClass), L"*", &asi);
但是,如果我們可以格式化 SDP 記錄,我們也可以直接使用IOCTL_BTH_SDP_SUBMIT_RECORD
進行注冊,然后使用IOCTL_BTH_SDP_REMOVE_RECORD
進行注銷
對於打開的藍牙設備,需要使用帶有CM_Get_Device_Interface_ListW
的GUID_BTHPORT_DEVICE_INTERFACE
由 NspSetService 格式化的 SDP 記錄看起來像
UCHAR SdpRecordTmplt[] = {
// [//////////////////////////////////////////////////////////////////////////////////////////////////////////
0x35, 0x33, //
//
// UINT16:SDP_ATTRIB_CLASS_ID_LIST //
0x09, 0x00, 0x01, //
// [///////////////////////////////////////////////////////////////////////////////////////////////// //
0x35, 0x11, // //
// UUID128:{guid} // //
0x1c, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, // //
// ]///////////////////////////////////////////////////////////////////////////////////////////////// //
//
// UINT16:SDP_ATTRIB_PROTOCOL_DESCRIPTOR_LIST //
0x09, 0x00, 0x04, //
// [///////////////////////////////// //
0x35, 0x0f, // //
// (L2CAP, PSM=PSM_RFCOMM) // //
// [///////////////////////// // //
0x35, 0x06, // // //
// UUID16:L2CAP_PROTOCOL_UUID16 // // //
0x19, 0x01, 0x00, // // //
// UINT16:PSM_RFCOMM // // //
0x09, 0x00, 0x03, // // //
// ]///////////////////////// // //
// (RFCOMM, CN=Port) // //
// [///////////////////////// // //
0x35, 0x05, // // //
// UUID16:RFCOMM_PROTOCOL_UUID16 // // //
0x19, 0x00, 0x03, // // //
// UINT8:CN // // //
0x08, 0x**, // // //
// ]///////////////////////// // //
// ]///////////////////////////////// //
//
// UINT16:SDP_ATTRIB_SERVICE_NAME //
0x09, 0x01, 0x00, //
// STR:4 "ABCD" //
0x25, 0x04, 0x41, 0x42, 0x43, 0x44 //
// ]//////////////////////////////////////////////////////////////////////////////////////////////////////////
};
這里只有 UUID128 ( ServiceClassId ),rfcomm 端口號和名稱被更改
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.