www.pudn.com > bluecove-1.2.1-src.zip > intelbth.cpp, change:2007-01-07,size:29036b
/*
Copyright 2004 Intel Corporation
This file is part of Blue Cove.
Blue Cove is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
Blue Cove is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Blue Cove; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "stdafx.h"
// Old school way of debug
#ifdef DEBUG
void debug(char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
{
vprintf(fmt, ap);
}
va_end(ap);
fflush(stdout);
}
#else
#define debug(x)
#endif
#define INQUIRY_COMPLETED 0
#define INQUIRY_TERMINATED 5
#define INQUIRY_ERROR 7
#define SERVICE_SEARCH_COMPLETED 1
#define SERVICE_SEARCH_TERMINATED 2
#define SERVICE_SEARCH_ERROR 3
#define SERVICE_SEARCH_NO_RECORDS 4
#define SERVICE_SEARCH_DEVICE_NOT_REACHABLE 6
static BOOL started;
static HANDLE hLookup;
static CRITICAL_SECTION csLookup;
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch(ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
{
WSADATA data;
if (WSAStartup(MAKEWORD(2, 2), &data)) {
started = FALSE;
return FALSE;
} else
started = TRUE;
hLookup = NULL;
InitializeCriticalSection(&csLookup);
break;
}
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
if (started)
WSACleanup();
DeleteCriticalSection(&csLookup);
break;
}
return TRUE;
}
void throwException(JNIEnv *env, const char *name, const char *msg)
{
debug("c Throw Exception %s %s\n", name, msg);
jclass cls = env->FindClass(name);
/* if cls is NULL, an exception has already been thrown */
if (cls != NULL) {
env->ThrowNew(cls, msg);
} else {
env->FatalError("illegal Exception name");
}
/* free the local ref */
env->DeleteLocalRef(cls);
}
void throwIOException(JNIEnv *env, const char *msg)
{
throwException(env, "java/io/IOException", msg);
}
/*
* Class: com_intel_bluetooth_BluetoothPeer
* Method: doInquiry
* Signature: (ILjavax/bluetooth/DiscoveryListener;)I
*/
JNIEXPORT jint JNICALL Java_com_intel_bluetooth_BluetoothPeer_doInquiry(JNIEnv *env, jobject peer, jint accessCode, jobject listener)
{
jclass cls;
// build device query
#ifndef _WIN32_WCE
BTH_QUERY_DEVICE query;
query.LAP = 0;
#else
BTHNS_INQUIRYBLOB query;
query.LAP = accessCode;
query.num_responses = 10;
#endif
query.length = 10;
// build BLOB pointing to device query
BLOB blob;
blob.cbSize = sizeof(query);
blob.pBlobData = (BYTE *)&query;
// build query
WSAQUERYSET queryset;
memset(&queryset, 0, sizeof(WSAQUERYSET));
queryset.dwSize = sizeof(WSAQUERYSET);
queryset.dwNameSpace = NS_BTH;
queryset.lpBlob = &blob;
#ifndef _WIN32_WCE
queryset.lpBlob = &blob;
#endif
// begin query
EnterCriticalSection(&csLookup);
if (hLookup != NULL) {
LeaveCriticalSection(&csLookup);
return INQUIRY_ERROR;
}
#ifdef _WIN32_WCE
if (WSALookupServiceBegin(&queryset, LUP_CONTAINERS, &hLookup)) {
#else
if (WSALookupServiceBegin(&queryset, LUP_FLUSHCACHE|LUP_CONTAINERS, &hLookup)) {
#endif
hLookup = NULL;
LeaveCriticalSection(&csLookup);
return INQUIRY_ERROR;
}
LeaveCriticalSection(&csLookup);
// fetch results
while(true) {
union {
CHAR buf[4096];
SOCKADDR_BTH __unused;
};
memset(buf, 0, sizeof(buf));
LPWSAQUERYSET pwsaResults = (LPWSAQUERYSET) buf;
pwsaResults->dwSize = sizeof(WSAQUERYSET);
pwsaResults->dwNameSpace = NS_BTH;
DWORD size = sizeof(buf);
EnterCriticalSection(&csLookup);
if (hLookup == NULL) {
LeaveCriticalSection(&csLookup);
return INQUIRY_TERMINATED;
}
if (WSALookupServiceNext(hLookup, LUP_RETURN_NAME|LUP_RETURN_ADDR|LUP_RETURN_BLOB, &size, (WSAQUERYSET *)buf)) {
WSALookupServiceEnd(hLookup);
hLookup = NULL;
LeaveCriticalSection(&csLookup);
switch(WSAGetLastError()) {
case WSAENOMORE:
case WSA_E_NO_MORE:
return INQUIRY_COMPLETED;
default:
return INQUIRY_ERROR;
}
}
LeaveCriticalSection(&csLookup);
#ifdef _WIN32_WCE
BthInquiryResult *p_inqRes = (BthInquiryResult *)pwsaResults->lpBlob->pBlobData;
#else
BTH_DEVICE_INFO *p_inqRes = (BTH_DEVICE_INFO *)pwsaResults->lpBlob->pBlobData;
#endif
// get device name
WCHAR name[256];
BOOL bHaveName = pwsaResults->lpszServiceInstanceName && *(pwsaResults->lpszServiceInstanceName);
StringCchPrintf(name, sizeof(name),L"%s",bHaveName ? pwsaResults->lpszServiceInstanceName : L"");
// create remote device
cls = env->FindClass("javax/bluetooth/RemoteDevice");
jobject dev = env->NewObject(cls, env->GetMethodID(cls, "<init>", "(Ljava/lang/String;J)V"), env->NewString((jchar*)name, (jsize)wcslen(name)), ((SOCKADDR_BTH *)pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr)->btAddr);
// create device class
cls = env->FindClass("javax/bluetooth/DeviceClass");
#ifdef _WIN32_WCE
int classOfDev = p_inqRes->cod;
#else
int classOfDev = p_inqRes->classOfDevice;
#endif
jobject cod = env->NewObject(cls, env->GetMethodID(cls, "<init>", "(I)V"), classOfDev);
// notify listener
env->CallVoidMethod(listener, env->GetMethodID(env->GetObjectClass(listener), "deviceDiscovered", "(Ljavax/bluetooth/RemoteDevice;Ljavax/bluetooth/DeviceClass;)V"), dev, cod);
}
}
/*
* Class: com_intel_bluetooth_BluetoothPeer
* Method: cancelInquiry
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_com_intel_bluetooth_BluetoothPeer_cancelInquiry(JNIEnv *env, jobject peer)
{
EnterCriticalSection(&csLookup);
if (hLookup == NULL) {
LeaveCriticalSection(&csLookup);
return JNI_FALSE;
}
WSALookupServiceEnd(hLookup);
hLookup = NULL;
LeaveCriticalSection(&csLookup);
return JNI_TRUE;
}
static void convertBytesToUUID(jbyte *bytes, GUID *uuid)
{
uuid->Data1 = bytes[0]<<24&0xff000000|bytes[1]<<16&0x00ff0000|bytes[2]<<8&0x0000ff00|bytes[3]&0x000000ff;
uuid->Data2 = bytes[4]<<8&0xff00|bytes[5]&0x00ff;
uuid->Data3 = bytes[6]<<8&0xff00|bytes[7]&0x00ff;
for(int i = 0; i 8; i++)
uuid->Data4[i] = bytes[i+8];
}
JNIEXPORT jintArray JNICALL Java_com_intel_bluetooth_BluetoothPeer_getServiceHandles(JNIEnv *env, jobject peer, jobjectArray uuidSet, jlong address)
{
// check if we can handle the number of UUIDs supplied
if (env->GetArrayLength(uuidSet) > MAX_UUIDS_IN_QUERY)
return NULL;
#ifndef _WIN32_WCE
// generate a Bluetooth address string (WSAAddressToString doesn't work on WinCE)
WCHAR addressString[20];
swprintf_s(addressString, _T("(%02x:%02x:%02x:%02x:%02x:%02x)"), (int)(address>>40&0xff), (int)(address>>32&0xff), (int)(address>>24&0xff), (int)(address>>16&0xff), (int)(address>>8&0xff), (int)(address&0xff));
// build service query
BTH_QUERY_SERVICE queryservice;
#else
BTHNS_RESTRICTIONBLOB queryservice;
#endif
memset(&queryservice, 0, sizeof(queryservice));
queryservice.type = SDP_SERVICE_SEARCH_REQUEST;
GUID guid;
for(int i = 0; i env->GetArrayLength(uuidSet); i++) {
jbyteArray uuidValue = (jbyteArray)env->GetObjectField(env->GetObjectArrayElement(uuidSet, i), env->GetFieldID(env->FindClass("javax/bluetooth/UUID"), "uuidValue", "[B"));
// pin array
jbyte *bytes = env->GetByteArrayElements(uuidValue, 0);
// build UUID
convertBytesToUUID(bytes, &guid);
//UUID is full 128 bits
queryservice.uuids[i].uuidType = SDP_ST_UUID128;
memcpy(&queryservice.uuids[i].u.uuid128, &guid, sizeof(guid));
// unpin array
env->ReleaseByteArrayElements(uuidValue, bytes, 0);
}
// build BLOB pointing to service query
BLOB blob;
blob.cbSize = sizeof(queryservice);
blob.pBlobData = (BYTE *)&queryservice;
// build query
WSAQUERYSET queryset;
memset(&queryset, 0, sizeof(WSAQUERYSET));
queryset.dwSize = sizeof(WSAQUERYSET);
queryset.dwNameSpace = NS_BTH;
queryset.lpBlob = &blob;
#ifdef _WIN32_WCE
// Build address
SOCKADDR_BTH sa;
memset (&sa, 0, sizeof(sa));
sa.addressFamily = AF_BT;
sa.btAddr = address;
CSADDR_INFO csai;
memset (&csai, 0, sizeof(csai));
csai.RemoteAddr.lpSockaddr = (sockaddr *)&sa;
csai.RemoteAddr.iSockaddrLength = sizeof(sa);
queryset.lpcsaBuffer = &csai;
#else
queryset.lpszContext = addressString;
#endif
HANDLE hLookup;
// begin query
#ifdef _WIN32_WCE
if (WSALookupServiceBegin(&queryset, 0, &hLookup))
return NULL;
#else
if (WSALookupServiceBegin(&queryset, LUP_FLUSHCACHE, &hLookup))
return NULL;
#endif
// fetch results
char buf[4096];
memset(buf, 0, sizeof(buf));
LPWSAQUERYSET pwsaResults = (LPWSAQUERYSET) buf;
pwsaResults->dwSize = sizeof(WSAQUERYSET);
pwsaResults->dwNameSpace = NS_BTH;
pwsaResults->lpBlob = NULL;
DWORD size = sizeof(buf);
#ifdef _WIN32_WCE
if (WSALookupServiceNext(hLookup, 0, &size, pwsaResults)) {
#else
if (WSALookupServiceNext(hLookup, LUP_RETURN_BLOB, &size, pwsaResults)) {
#endif
switch(WSAGetLastError()) {
case WSANO_DATA:
return env->NewIntArray(0);
default:
WSALookupServiceEnd(hLookup);
return NULL;
}
}
WSALookupServiceEnd(hLookup);
// construct int array to hold handles
jintArray result = env->NewIntArray(pwsaResults->lpBlob->cbSize/sizeof(ULONG));
jint *ints = env->GetIntArrayElements(result, 0);
memcpy(ints, pwsaResults->lpBlob->pBlobData, pwsaResults->lpBlob->cbSize);
env->ReleaseIntArrayElements(result, ints, 0);
return result;
}
JNIEXPORT jbyteArray JNICALL Java_com_intel_bluetooth_BluetoothPeer_getServiceAttributes(JNIEnv *env, jobject peer, jintArray attrIDs, jlong address, jint handle)
{
#ifdef _WIN32_WCE
BTHNS_RESTRICTIONBLOB *queryservice = (BTHNS_RESTRICTIONBLOB *)malloc(sizeof(BTHNS_RESTRICTIONBLOB)+sizeof(SdpAttributeRange)*(1));
queryservice->type = SDP_SERVICE_ATTRIBUTE_REQUEST;
queryservice->serviceHandle = handle;
queryservice->numRange = 1;
// set attribute ranges
jint *ints = env->GetIntArrayElements(attrIDs, 0);
queryservice->pRange[0].minAttribute = (USHORT)ints[0];
queryservice->pRange[0].maxAttribute = (USHORT)ints[env->GetArrayLength(attrIDs)-1];
env->ReleaseIntArrayElements(attrIDs, ints, 0);
#else
// generate a Bluetooth address string (WSAAddressToString doesn't work on WinCE)
WCHAR addressString[20];
swprintf_s(addressString, _T("(%02x:%02x:%02x:%02x:%02x:%02x)"), (int)(address>>40&0xff), (int)(address>>32&0xff), (int)(address>>24&0xff), (int)(address>>16&0xff), (int)(address>>8&0xff), (int)(address&0xff));
// build attribute query
BTH_QUERY_SERVICE *queryservice = (BTH_QUERY_SERVICE *)malloc(sizeof(BTH_QUERY_SERVICE)+sizeof(SdpAttributeRange)*(env->GetArrayLength(attrIDs)-1));
memset(queryservice, 0, sizeof(BTH_QUERY_SERVICE)-sizeof(SdpAttributeRange));
queryservice->type = SDP_SERVICE_ATTRIBUTE_REQUEST;
queryservice->serviceHandle = handle;
queryservice->numRange = env->GetArrayLength(attrIDs);
// set attribute ranges
jint *ints = env->GetIntArrayElements(attrIDs, 0);
for(int i = 0; i env->GetArrayLength(attrIDs); i++) {
queryservice->pRange[i].minAttribute = (USHORT)ints[i];
queryservice->pRange[i].maxAttribute = (USHORT)ints[i];
}
env->ReleaseIntArrayElements(attrIDs, ints, 0);
#endif
// build BLOB pointing to attribute query
BLOB blob;
#ifdef _WIN32_WCE
blob.cbSize = sizeof(BTHNS_RESTRICTIONBLOB);
#else
blob.cbSize = sizeof(BTH_QUERY_SERVICE);
#endif
blob.pBlobData = (BYTE *)queryservice;
// build query
WSAQUERYSET queryset;
memset(&queryset, 0, sizeof(WSAQUERYSET));
queryset.dwSize = sizeof(WSAQUERYSET);
queryset.dwNameSpace = NS_BTH;
#ifdef _WIN32_WCE
// Build address
SOCKADDR_BTH sa;
memset (&sa, 0, sizeof(sa));
sa.addressFamily = AF_BT;
sa.btAddr = address;
CSADDR_INFO csai;
memset (&csai, 0, sizeof(csai));
csai.RemoteAddr.lpSockaddr = (sockaddr *)&sa;
csai.RemoteAddr.iSockaddrLength = sizeof(sa);
queryset.lpcsaBuffer = &csai;
#else
queryset.lpszContext = addressString;
#endif
queryset.lpBlob = &blob;
HANDLE hLookup;
// begin query
#ifdef _WIN32_WCE
if (WSALookupServiceBegin(&queryset, 0, &hLookup)) {
#else
if (WSALookupServiceBegin(&queryset, LUP_FLUSHCACHE, &hLookup)) {
#endif
free(queryservice);
//env->ThrowNew(env->FindClass("java/io/IOException"), "Failed to begin attribute query");
throwIOException(env, "Failed to begin attribute query");
return NULL;
}
free(queryservice);
// fetch results
char buf[4096];
memset(buf, 0, sizeof(buf));
LPWSAQUERYSET pwsaResults = (LPWSAQUERYSET) buf;
pwsaResults->dwSize = sizeof(WSAQUERYSET);
pwsaResults->dwNameSpace = NS_BTH;
pwsaResults->lpBlob = NULL;
DWORD size = sizeof(buf);
#ifdef _WIN32_WCE
if (WSALookupServiceNext(hLookup, 0, &size, pwsaResults)) {
#else
if (WSALookupServiceNext(hLookup, LUP_RETURN_BLOB, &size, (WSAQUERYSET *)buf)) {
#endif
WSALookupServiceEnd(hLookup);
//env->ThrowNew(env->FindClass("java/io/IOException"), "Failed to perform attribute query");
throwIOException(env, "Failed to perform attribute query");
return NULL;
}
WSALookupServiceEnd(hLookup);
// construct byte array to hold blob
jbyteArray result = env->NewByteArray(pwsaResults->lpBlob->cbSize);
jbyte *bytes = env->GetByteArrayElements(result, 0);
memcpy(bytes, pwsaResults->lpBlob->pBlobData, pwsaResults->lpBlob->cbSize);
env->ReleaseByteArrayElements(result, bytes, 0);
return result;
}
/*
* Class: com_intel_bluetooth_BluetoothPeer
* Method: registerService
* Signature: ([B)I
*/
JNIEXPORT jint JNICALL Java_com_intel_bluetooth_BluetoothPeer_registerService(JNIEnv *env, jobject peer, jbyteArray record)
{
int length = env->GetArrayLength(record);
HANDLE handle = NULL;
// build service set
ULONG version = BTH_SDP_VERSION;
#ifdef _WIN32_WCE
BTHNS_SETBLOB *setservice = (BTHNS_SETBLOB*)malloc(sizeof(BTHNS_SETBLOB)+length-1);
memset(setservice, 0, sizeof(BTHNS_SETBLOB)-1);
setservice->pRecordHandle = (ULONG*)&handle;
#else
BTH_SET_SERVICE *setservice = (BTH_SET_SERVICE *)malloc(sizeof(BTH_SET_SERVICE)+length-1);
memset(setservice, 0, sizeof(BTH_SET_SERVICE)-1);
setservice->pRecordHandle = &handle;
#endif
setservice->pSdpVersion = &version;
setservice->ulRecordLength = length;
jbyte *bytes = env->GetByteArrayElements(record, 0);
memcpy(setservice->pRecord, bytes, length);
env->ReleaseByteArrayElements(record, bytes, 0);
// build BLOB pointing to service set
BLOB blob;
#ifdef _WIN32_WCE
blob.cbSize = sizeof(BTHNS_SETBLOB);
#else
blob.cbSize = sizeof(BTH_SET_SERVICE);
#endif
blob.pBlobData = (BYTE *)setservice;
// build set
WSAQUERYSET queryset;
memset(&queryset, 0, sizeof(WSAQUERYSET));
queryset.dwSize = sizeof(WSAQUERYSET);
queryset.dwNameSpace = NS_BTH;
queryset.lpBlob = &blob;
// perform set
if (WSASetService(&queryset, RNRSERVICE_REGISTER, 0)) {
free(setservice);
//env->ThrowNew(env->FindClass("java/io/IOException"), "Failed to register service");
throwIOException(env, "Failed to register service");
return 0;
}
free(setservice);
return (jint)handle;
}
/*
* Class: com_intel_bluetooth_BluetoothPeer
* Method: unregisterService
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_intel_bluetooth_BluetoothPeer_unregisterService(JNIEnv *env, jobject peer, jint handle)
{
// build service set
ULONG version = BTH_SDP_VERSION;
#ifdef _WIN32_WCE
BTHNS_SETBLOB setservice;
memset(&setservice, 0, sizeof(BTHNS_SETBLOB));
setservice.pRecordHandle = (ULONG *)&handle;
#else
BTH_SET_SERVICE setservice;
memset(&setservice, 0, sizeof(BTH_SET_SERVICE));
setservice.pRecordHandle = (HANDLE *)&handle;
#endif
setservice.pSdpVersion = &version;
// build BLOB pointing to service set
BLOB blob;
#ifdef _WIN32_WCE
blob.cbSize = sizeof(BTHNS_SETBLOB);
#else
blob.cbSize = sizeof(BTH_SET_SERVICE);
#endif
blob.pBlobData = (BYTE *)&setservice;
// build set
WSAQUERYSET queryset;
memset(&queryset, 0, sizeof(WSAQUERYSET));
queryset.dwSize = sizeof(WSAQUERYSET);
queryset.dwNameSpace = NS_BTH;
queryset.lpBlob = &blob;
// perform set
if (WSASetService(&queryset, RNRSERVICE_DELETE, 0)) {
//env->ThrowNew(env->FindClass("java/io/IOException"), "Failed to unregister service");
throwIOException(env, "Failed to unregister service");
}
}
/*
* Class: com_intel_bluetooth_BluetoothPeer
* Method: socket
* Signature: (ZZ)I
*/
JNIEXPORT jint JNICALL Java_com_intel_bluetooth_BluetoothPeer_socket(JNIEnv *env, jobject peer, jboolean authenticate, jboolean encrypt)
{
// create socket
SOCKET s = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
if (s == INVALID_SOCKET) {
//env->ThrowNew(env->FindClass("java/io/IOException"), "Failed to create socket");
throwIOException(env, "Failed to create socket");
return 0;
}
// set socket options
if (authenticate) {
ULONG ul = TRUE;
if (setsockopt(s, SOL_RFCOMM, SO_BTH_AUTHENTICATE, (char *)&ul, sizeof(ULONG))) {
closesocket(s);
//env->ThrowNew(env->FindClass("java/io/IOException"), "Failed to set authentication option");
throwIOException(env, "Failed to set authentication option");
return 0;
}
}
if (encrypt) {
#ifdef _WIN32_WCE
int ul = TRUE;
#else
ULONG ul = TRUE;
#endif
if (setsockopt(s, SOL_RFCOMM, SO_BTH_ENCRYPT, (char *)&ul, sizeof(ul))) {
closesocket(s);
//env->ThrowNew(env->FindClass("java/io/IOException"), "Failed to set encryption option");
throwIOException(env, "Failed to set encryption option");
return 0;
}
}
#ifndef _WIN32_WINCE
// bind socket
// This will not work for WIN32_WCE. Ideally bind should be before listen
/*
SOCKADDR_BTH addr;
memset(&addr, 0, sizeof(SOCKADDR_BTH));
addr.addressFamily = AF_BTH;
addr.port = BT_PORT_ANY;
if (bind(s, (sockaddr*)&addr, sizeof(SOCKADDR_BTH))) {
closesocket(s);
//env->ThrowNew(env->FindClass("java/io/IOException"), "Failed to bind socket");
throwIOException(env, "Failed to bind socket");
return 0;
}
*/
#endif
return (jint)s;
}
/*
* Class: com_intel_bluetooth_BluetoothPeer
* Method: getsockaddress
* Signature: (I)J
*/
JNIEXPORT jlong JNICALL Java_com_intel_bluetooth_BluetoothPeer_getsockaddress(JNIEnv *env, jobject peer, jint socket)
{
// get socket name
SOCKADDR_BTH addr;
int size = sizeof(SOCKADDR_BTH);
if (getsockname(socket, (sockaddr *)&addr, &size)) {
//env->ThrowNew(env->FindClass("java/io/IOException"), "Failed to get socket name");
throwIOException(env, "Failed to get socket name");
return 0;
}
return addr.btAddr;
}
/*
* Class: com_intel_bluetooth_BluetoothPeer
* Method: getsockchannel
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_intel_bluetooth_BluetoothPeer_getsockchannel(JNIEnv *env, jobject peer, jint socket)
{
// get socket name
SOCKADDR_BTH addr;
int size = sizeof(SOCKADDR_BTH);
if (getsockname(socket, (sockaddr *)&addr, &size)) {
//env->ThrowNew(env->FindClass("java/io/IOException"), "Failed to get socket name");
throwIOException(env, "Failed to get socket name");
return 0;
}
return addr.port;
}
/*
* Class: com_intel_bluetooth_BluetoothPeer
* Method: connect
* Signature: (IJI)V
*/
JNIEXPORT void JNICALL Java_com_intel_bluetooth_BluetoothPeer_connect(JNIEnv *env, jobject peer, jint socket, jlong address, jint channel)
{
// connect
SOCKADDR_BTH addr;
memset(&addr, 0, sizeof(SOCKADDR_BTH));
addr.addressFamily = AF_BTH;
addr.btAddr = address;
addr.port = channel;
if (connect((SOCKET)socket, (sockaddr *)&addr, sizeof(SOCKADDR_BTH))) {
// env->ThrowNew(env->FindClass("java/io/IOException"), "Failed to connect socket");
throwIOException(env, "Failed to connect socket");
}
}
/*
* Class: com_intel_bluetooth_BluetoothPeer
* Method: listen
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_intel_bluetooth_BluetoothPeer_listen(JNIEnv *env, jobject peer, jint socket)
{
// bind socket
SOCKADDR_BTH addr;
memset(&addr, 0, sizeof(addr));
addr.addressFamily = AF_BTH;
#ifdef _WIN32_WCE
addr.port = 0;
#else
addr.port = BT_PORT_ANY;
#endif
if (bind(socket, (SOCKADDR *)&addr, sizeof(addr))) {
closesocket(socket);
char errmsg[512];
sprintf_s(errmsg,"Failed to bind socket; error = %d", WSAGetLastError());
//env->ThrowNew(env->FindClass("java/io/IOException"), errmsg);
throwIOException(env, errmsg);
return;
}
// listen
if (listen((SOCKET)socket, 10)) {
//env->ThrowNew(env->FindClass("java/io/IOException"), "Failed to listen socket");
throwIOException(env, "Failed to listen socket");
}
}
/*
* Class: com_intel_bluetooth_BluetoothPeer
* Method: accept
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_intel_bluetooth_BluetoothPeer_accept(JNIEnv *env, jobject peer, jint socket)
{
SOCKADDR_BTH addr;
int size = sizeof(SOCKADDR_BTH);
SOCKET s = accept((SOCKET)socket, (sockaddr *)&addr, &size);
if (s == INVALID_SOCKET) {
//env->ThrowNew(env->FindClass("java/io/IOException"), "Failed to listen socket");
throwIOException(env, "Failed to listen socket");
return 0;
}
return (jint)s;
}
/*
* Class: com_intel_bluetooth_BluetoothPeer
* Method: recv
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_intel_bluetooth_BluetoothPeer_recv__I(JNIEnv *env, jobject peer, jint socket)
{
unsigned char c;
if (recv((SOCKET)socket, (char *)&c, 1, 0) != 1) {
//env->ThrowNew(env->FindClass("java/io/IOException"), "Failed to read");
throwIOException(env, "Failed to read");
return 0;
}
return (int)c;
}
/*
* Class: com_intel_bluetooth_BluetoothPeer
* Method: recv
* Signature: (I[BII)I
*/
JNIEXPORT jint JNICALL Java_com_intel_bluetooth_BluetoothPeer_recv__I_3BII(JNIEnv *env, jobject peer, jint socket, jbyteArray b, jint off, jint len)
{
jbyte *bytes = env->GetByteArrayElements(b, 0);
int done = 0;
while(done len) {
int count = recv((SOCKET)socket, (char *)(bytes+off+done), len-done, 0);
if (count = 0) {
env->ReleaseByteArrayElements(b, bytes, 0);
if (done == 0) {
//env->ThrowNew(env->FindClass("java/io/IOException"), "Failed to write");
throwIOException(env, "Failed to write");
return 0;
} else
return done;
}
done += count;
}
env->ReleaseByteArrayElements(b, bytes, 0);
return done;
}
/*
* Class: com_intel_bluetooth_BluetoothPeer
* Method: send
* Signature: (II)V
*/
JNIEXPORT void JNICALL Java_com_intel_bluetooth_BluetoothPeer_send__II(JNIEnv *env, jobject peer, jint socket, jint b)
{
char c = (char)b;
if (send((SOCKET)socket, &c, 1, 0) != 1) {
//env->ThrowNew(env->FindClass("java/io/IOException"), "Failed to write");
throwIOException(env, "Failed to write");
}
}
/*
* Class: com_intel_bluetooth_BluetoothPeer
* Method: send
* Signature: (I[BII)V
*/
JNIEXPORT void JNICALL Java_com_intel_bluetooth_BluetoothPeer_send__I_3BII(JNIEnv *env, jobject peer, jint socket, jbyteArray b, jint off, jint len)
{
jbyte *bytes = env->GetByteArrayElements(b, 0);
int done = 0;
while(done len) {
int count = send((SOCKET)socket, (char *)(bytes+off+done), len-done, 0);
if (count = 0) {
env->ReleaseByteArrayElements(b, bytes, 0);
//env->ThrowNew(env->FindClass("java/io/IOException"), "Failed to write");
throwIOException(env, "Failed to write");
return;
}
done += count;
}
env->ReleaseByteArrayElements(b, bytes, 0);
}
/*
* Class: com_intel_bluetooth_BluetoothPeer
* Method: close
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_intel_bluetooth_BluetoothPeer_close(JNIEnv *env, jobject peer, jint socket)
{
if (closesocket((SOCKET)socket)) {
//env->ThrowNew(env->FindClass("java/io/IOException"), "Failed to close socket");
throwIOException(env, "Failed to close socket");
}
}
WCHAR *GetWSAErrorMessage(DWORD last_error)
{
static WCHAR errmsg[512];
if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
0,
last_error,
0,
errmsg,
511,
NULL))
{
// if we fail, call ourself to find out why and return that error
return (GetWSAErrorMessage(GetLastError()));
}
return errmsg;
}
/*
* Class: com_intel_bluetooth_BluetoothPeer
* Method: getsockname
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_intel_bluetooth_BluetoothPeer_getpeername(JNIEnv *env, jobject peer, jlong addr)
{
#ifdef _WIN32_WCE
/*
* For the moment just return an empty string on Windows Mobile
* The next device scan will return a name anyway...
* To be modified later
*/
return env->NewStringUTF((char*)"");
#else
debug("c getpeername\n");
WSAQUERYSET querySet;
memset(&querySet, 0, sizeof(querySet));
querySet.dwSize = sizeof(querySet);
querySet.dwNameSpace = NS_BTH;
DWORD flags = LUP_RETURN_NAME |LUP_RETURN_ADDR | LUP_CONTAINERS;
EnterCriticalSection(&csLookup);
if (hLookup != NULL) {
LeaveCriticalSection(&csLookup);
throwIOException(env, "Another inquiry already running");
return NULL;
//env->ThrowNew(env->FindClass("java/io/IOException"), "Another inquiry already running");
}
if (WSALookupServiceBegin(&querySet, flags, &hLookup)) {
hLookup = NULL;
LeaveCriticalSection(&csLookup);
throwIOException(env, (char*)GetWSAErrorMessage(GetLastError()));
return NULL;
//env->ThrowNew(env->FindClass("java/io/IOException"), (char*)GetWSAErrorMessage(GetLastError()));
}
LeaveCriticalSection(&csLookup);
while (true) {
BYTE buffer[1000];
DWORD bufferLength = sizeof(buffer);
WSAQUERYSET *pResults = (WSAQUERYSET*)&buffer;
EnterCriticalSection(&csLookup);
if (WSALookupServiceNext(hLookup, flags, &bufferLength, pResults)) {
WSALookupServiceEnd(hLookup);
hLookup = NULL;
LeaveCriticalSection(&csLookup);
int err = GetLastError();
switch(err) {
case WSAENOMORE:
case WSA_E_NO_MORE:
break;
default:
throwIOException(env, (char*)GetWSAErrorMessage(GetLastError()));
return NULL;
//env->ThrowNew(env->FindClass("java/io/IOException"), (char*)GetWSAErrorMessage(GetLastError()));
}
}
LeaveCriticalSection(&csLookup);
if (((SOCKADDR_BTH *)((CSADDR_INFO *)pResults->lpcsaBuffer)->RemoteAddr.lpSockaddr)->btAddr == addr) {
EnterCriticalSection(&csLookup);
WSALookupServiceEnd(hLookup);
hLookup = NULL;
LeaveCriticalSection(&csLookup);
WCHAR *name = pResults->lpszServiceInstanceName;
debug("c return %s\n", name);
return env->NewString((jchar*)name, wcslen(name));
}
} // while(true)
//env->ThrowNew(env->FindClass("java/IO/IOException", "No name found"));
debug("c return empty\n");
return env->NewStringUTF((char*)"");
#endif
}
JNIEXPORT jlong JNICALL Java_com_intel_bluetooth_BluetoothPeer_getpeeraddress(JNIEnv *env, jobject peer, jint socket)
{
SOCKADDR_BTH addr;
int size = sizeof(addr);
if (getpeername((SOCKET) socket, (sockaddr*)&addr, &size)) {
//env->ThrowNew(env->FindClass("java/io/IOException"), (char*)GetWSAErrorMessage(GetLastError()));
throwIOException(env, (char*)GetWSAErrorMessage(GetLastError()));
return 0;
}
return addr.btAddr;
}
JNIEXPORT jstring JNICALL Java_com_intel_bluetooth_BluetoothPeer_getradioname(JNIEnv *env, jobject peer, jlong address)
{
// Unsupported for _WIN32_WCE for the moment...
#ifndef _WIN32_WCE
HANDLE hRadio;
BLUETOOTH_FIND_RADIO_PARAMS btfrp = { sizeof(btfrp) };
HBLUETOOTH_RADIO_FIND hFind = BluetoothFindFirstRadio( &btfrp, &hRadio );
if ( NULL != hFind )
{
do
{
BLUETOOTH_RADIO_INFO radioInfo;
radioInfo.dwSize = sizeof(radioInfo);
if (ERROR_SUCCESS == BluetoothGetRadioInfo(hRadio, &radioInfo))
{
if (radioInfo.address.ullLong == address) {
BluetoothFindRadioClose(hFind);
return env->NewString((jchar*)radioInfo.szName, (jsize) wcslen(radioInfo.szName));
}
}
} while( BluetoothFindNextRadio( hFind, &hRadio ) );
BluetoothFindRadioClose( hFind );
}
#endif
return NULL;
}