summaryrefslogtreecommitdiffstats
path: root/src/tools/sdpscanner/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/sdpscanner/main.cpp')
-rw-r--r--src/tools/sdpscanner/main.cpp106
1 files changed, 90 insertions, 16 deletions
diff --git a/src/tools/sdpscanner/main.cpp b/src/tools/sdpscanner/main.cpp
index bf978c0d..edca8fa3 100644
--- a/src/tools/sdpscanner/main.cpp
+++ b/src/tools/sdpscanner/main.cpp
@@ -40,6 +40,7 @@
#include <QtCore/QByteArray>
#include <QtCore/QDebug>
#include <stdio.h>
+#include <string>
#include <bluetooth/bluetooth.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
@@ -52,11 +53,14 @@
void usage()
{
fprintf(stderr, "Usage:\n");
- fprintf(stderr, "\tsdpscanner <remote bdaddr> <local bdaddr> [Options]\n\n");
+ fprintf(stderr, "\tsdpscanner <remote bdaddr> <local bdaddr> [Options] ({uuids})\n\n");
fprintf(stderr, "Performs an SDP scan on remote device, using the SDP server\n"
"represented by the local Bluetooth device.\n\n"
"Options:\n"
- " -p Show scan results in human-readable form\n");
+ " -p Show scan results in human-readable form\n"
+ " -u [list of uuids] List of uuids which should be scanned for.\n"
+ " Each uuid must be enclosed in {}.\n"
+ " If the list is empty PUBLIC_BROWSE_GROUP scan is used.\n");
}
#define BUFFER_SIZE 1024
@@ -275,6 +279,7 @@ int main(int argc, char **argv)
}
bool showHumanReadable = false;
+ std::vector<std::string> targetServices;
for (int i = 3; i < argc; i++) {
if (argv[i][0] != '-') {
@@ -287,12 +292,56 @@ int main(int argc, char **argv)
case 'p':
showHumanReadable = true;
break;
+ case 'u':
+ i++;
+
+ for ( ; i < argc && argv[i][0] == '{'; i++)
+ targetServices.push_back(argv[i]);
+
+ i--; // outer loop increments again
+ break;
default:
fprintf(stderr, "Wrong argument: %s\n", argv[i]);
usage();
return RETURN_USAGE;
+ }
+ }
+ std::vector<uuid_t> uuids;
+ for (std::vector<std::string>::const_iterator iter = targetServices.cbegin();
+ iter != targetServices.cend(); ++iter) {
+
+ uint128_t temp128;
+ uint16_t field1, field2, field3, field5;
+ uint32_t field0, field4;
+
+ fprintf(stderr, "Target scan for %s\n", (*iter).c_str());
+ if (sscanf((*iter).c_str(), "{%08x-%04hx-%04hx-%04hx-%08x%04hx}", &field0,
+ &field1, &field2, &field3, &field4, &field5) != 6) {
+ fprintf(stderr, "Skipping invalid uuid: %s\n", ((*iter).c_str()));
+ continue;
}
+
+ // we need uuid_t conversion based on
+ // http://www.spinics.net/lists/linux-bluetooth/msg20356.html
+ field0 = htonl(field0);
+ field4 = htonl(field4);
+ field1 = htons(field1);
+ field2 = htons(field2);
+ field3 = htons(field3);
+ field5 = htons(field5);
+
+ uint8_t* temp = (uint8_t*) &temp128;
+ memcpy(&temp[0], &field0, 4);
+ memcpy(&temp[4], &field1, 2);
+ memcpy(&temp[6], &field2, 2);
+ memcpy(&temp[8], &field3, 2);
+ memcpy(&temp[10], &field4, 4);
+ memcpy(&temp[14], &field5, 2);
+
+ uuid_t sdpUuid;
+ sdp_uuid128_create(&sdpUuid, &temp128);
+ uuids.push_back(sdpUuid);
}
sdp_session_t *session = sdp_connect( &local, &remote, SDP_RETRY_IF_BUSY);
@@ -307,27 +356,52 @@ int main(int argc, char **argv)
}
// set the filter for service matches
- uuid_t publicBrowseGroupUuid;
- sdp_uuid16_create(&publicBrowseGroupUuid, PUBLIC_BROWSE_GROUP);
- sdp_list_t *serviceFilter;
- serviceFilter = sdp_list_append(0, &publicBrowseGroupUuid);
+ if (uuids.empty()) {
+ fprintf(stderr, "Using PUBLIC_BROWSE_GROUP for SDP search\n");
+ uuid_t publicBrowseGroupUuid;
+ sdp_uuid16_create(&publicBrowseGroupUuid, PUBLIC_BROWSE_GROUP);
+ uuids.push_back(publicBrowseGroupUuid);
+ }
uint32_t attributeRange = 0x0000ffff; //all attributes
sdp_list_t *attributes;
attributes = sdp_list_append(0, &attributeRange);
- sdp_list_t *sdpResults, *previous;
- result = sdp_service_search_attr_req(session, serviceFilter,
+ sdp_list_t *sdpResults, *sdpIter;
+ sdp_list_t *totalResults = NULL;
+ sdp_list_t* serviceFilter;
+
+ for (uint i = 0; i < uuids.size(); ++i) {
+ serviceFilter = sdp_list_append(0, &uuids[i]);
+ result = sdp_service_search_attr_req(session, serviceFilter,
SDP_ATTR_REQ_RANGE,
attributes, &sdpResults);
- sdp_list_free(attributes, 0);
- sdp_list_free(serviceFilter, 0);
+ sdp_list_free(serviceFilter, 0);
+ if (result != 0) {
+ fprintf(stderr, "sdp_service_search_attr_req failed\n");
+ sdp_list_free(attributes, 0);
+ sdp_close(session);
+ return RETURN_SDP_ERROR;
+ }
- if (result != 0) {
- fprintf(stderr, "sdp_service_search_attr_req failed\n");
- sdp_close(session);
- return RETURN_SDP_ERROR;
+ if (!sdpResults)
+ continue;
+
+ if (!totalResults) {
+ totalResults = sdpResults;
+ sdpIter = totalResults;
+ } else {
+ // attach each new result list to the end of totalResults
+ sdpIter->next = sdpResults;
+ }
+
+ while (sdpIter->next) // skip to end of list
+ sdpIter = sdpIter->next;
}
+ sdp_list_free(attributes, 0);
+
+ // start XML generation from the front
+ sdpResults = totalResults;
QByteArray total;
while (sdpResults) {
@@ -336,9 +410,9 @@ int main(int argc, char **argv)
const QByteArray xml = parseSdpRecord(record);
total += xml;
- previous = sdpResults;
+ sdpIter = sdpResults;
sdpResults = sdpResults->next;
- free(previous);
+ free(sdpIter);
sdp_record_free(record);
}