summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/device/bluetoth
Side-by-side diff
Diffstat (limited to 'gammu/emb/common/device/bluetoth') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/device/bluetoth/affix.c44
-rw-r--r--gammu/emb/common/device/bluetoth/affix.h3
-rw-r--r--gammu/emb/common/device/bluetoth/blue_w32.c216
-rw-r--r--gammu/emb/common/device/bluetoth/blue_w32.h188
-rw-r--r--gammu/emb/common/device/bluetoth/bluetoth.c85
-rw-r--r--gammu/emb/common/device/bluetoth/bluetoth.h15
-rw-r--r--gammu/emb/common/device/bluetoth/bluez.c207
-rw-r--r--gammu/emb/common/device/bluetoth/bluez.h3
8 files changed, 761 insertions, 0 deletions
diff --git a/gammu/emb/common/device/bluetoth/affix.c b/gammu/emb/common/device/bluetoth/affix.c
new file mode 100644
index 0000000..30a917b
--- a/dev/null
+++ b/gammu/emb/common/device/bluetoth/affix.c
@@ -0,0 +1,44 @@
+/* (c) 2004 by Marcin Wiacek */
+
+#include "../../gsmstate.h"
+
+#ifdef GSM_ENABLE_BLUETOOTHDEVICE
+#ifdef GSM_ENABLE_AFFIX
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "../../gsmcomon.h"
+#include "../devfunc.h"
+#include "bluetoth.h"
+
+GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device)
+{
+ d->hPhone = fd;
+ return ERR_NONE;
+}
+
+#ifdef BLUETOOTH_RF_SEARCHING
+
+static GSM_Error bluetooth_checkdevice(GSM_StateMachine *s, bdaddr_t *bdaddr, struct search_context *context)
+{
+}
+
+GSM_Error bluetooth_findchannel(GSM_StateMachine *s)
+{
+ return error;
+}
+
+#endif
+#endif
+#endif
+
+/* How should editor hadle tabs in this file? Add editor commands here.
+ * vim: noexpandtab sw=8 ts=8 sts=8:
+ */
diff --git a/gammu/emb/common/device/bluetoth/affix.h b/gammu/emb/common/device/bluetoth/affix.h
new file mode 100644
index 0000000..896ecbe
--- a/dev/null
+++ b/gammu/emb/common/device/bluetoth/affix.h
@@ -0,0 +1,3 @@
+
+GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device);
+GSM_Error bluetooth_findchannel(GSM_StateMachine *s);
diff --git a/gammu/emb/common/device/bluetoth/blue_w32.c b/gammu/emb/common/device/bluetoth/blue_w32.c
new file mode 100644
index 0000000..a631c9f
--- a/dev/null
+++ b/gammu/emb/common/device/bluetoth/blue_w32.c
@@ -0,0 +1,216 @@
+/* (c) 2003-2004 by Marcin Wiacek and Intra */
+
+#include "../../gsmstate.h"
+
+#ifdef GSM_ENABLE_BLUETOOTHDEVICE
+#ifdef WIN32
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <windows.h>
+#include <io.h>
+
+#include "../../misc/coding/coding.h"
+#include "../../gsmcomon.h"
+#include "../devfunc.h"
+#include "bluetoth.h"
+#include "blue_w32.h"
+
+GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device)
+{
+ GSM_Device_BlueToothData *d = &s->Device.Data.BlueTooth;
+ WSADATA wsaData;
+ SOCKADDR_BTH sab;
+ int i;
+
+ smprintf(s, "Connecting to RF channel %i\n",port);
+
+ WSAStartup(MAKEWORD(1,1), &wsaData);
+
+ d->hPhone = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
+ if (d->hPhone == INVALID_SOCKET) {
+ i = GetLastError();
+ GSM_OSErrorInfo(s, "Socket in bluetooth_open");
+ if (i == 10041) return ERR_DEVICENODRIVER;//unknown socket type
+ return ERR_UNKNOWN;
+ }
+
+ memset (&sab, 0, sizeof(sab));
+ sab.port = port;
+ sab.addressFamily = AF_BTH;
+ sab.btAddr = 0;
+ for (i=0;i<(int)strlen(device);i++) {
+ if (device[i] >='0' && device[i] <='9') {
+ sab.btAddr = sab.btAddr * 16;
+ sab.btAddr = sab.btAddr + (device[i]-'0');
+ }
+ if (device[i] >='a' && device[i] <='f') {
+ sab.btAddr = sab.btAddr * 16;
+ sab.btAddr = sab.btAddr + (device[i]-'a'+10);
+ }
+ if (device[i] >='A' && device[i] <='F') {
+ sab.btAddr = sab.btAddr * 16;
+ sab.btAddr = sab.btAddr + (device[i]-'A'+10);
+ }
+ }
+ dbgprintf("Remote Bluetooth device is %04x%08x\n",
+ GET_NAP(sab.btAddr), GET_SAP(sab.btAddr));
+
+ if (connect (d->hPhone, (struct sockaddr *)&sab, sizeof(sab)) != 0) {
+ i = GetLastError();
+ GSM_OSErrorInfo(s, "Connect in bluetooth_open");
+ if (i == 10060) return ERR_TIMEOUT; //remote device failed to respond
+ if (i == 10050) return ERR_DEVICENOTWORK; //socket operation connected with dead network
+ //noauth
+ close(d->hPhone);
+ return ERR_UNKNOWN;
+ }
+
+ return ERR_NONE;
+}
+
+#ifdef BLUETOOTH_RF_SEARCHING
+
+#pragma comment(lib, "irprops.lib")
+#pragma comment(lib, "ws2_32.lib")
+
+static GSM_Error bluetooth_checkdevice(GSM_StateMachine *s, char *address, WSAPROTOCOL_INFO *protocolInfo)
+{
+ GSM_Device_BlueToothData *d = &s->Device.Data.BlueTooth;
+ WSAQUERYSET querySet;
+ DWORD flags;
+ GUID protocol;
+ int i, result;
+ BYTE buffer[2000];
+ char addressAsString[1000];
+ DWORD bufferLength, addressSize;
+ WSAQUERYSET *pResults = (WSAQUERYSET*)&buffer;
+ HANDLE handle;
+ GSM_Error error;
+
+ memset(&querySet, 0, sizeof(querySet));
+ querySet.dwSize = sizeof(querySet);
+ protocol = L2CAP_PROTOCOL_UUID;
+ querySet.lpServiceClassId = &protocol;
+ querySet.dwNameSpace = NS_BTH;
+ querySet.lpszContext = address;
+
+ flags = LUP_FLUSHCACHE | LUP_RETURN_NAME |
+ LUP_RETURN_TYPE | LUP_RETURN_ADDR |
+ LUP_RETURN_BLOB | LUP_RETURN_COMMENT;
+
+ result = WSALookupServiceBegin(&querySet, flags, &handle);
+ if (result != 0) return ERR_UNKNOWN;
+
+ bufferLength = sizeof(buffer);
+ while (1) {
+ result = WSALookupServiceNext(handle, flags, &bufferLength, pResults);
+ if (result != 0) break;
+ addressSize = sizeof(addressAsString);
+ addressAsString[0] = 0;
+ if (WSAAddressToString(pResults->lpcsaBuffer->RemoteAddr.lpSockaddr,
+ pResults->lpcsaBuffer->RemoteAddr.iSockaddrLength, protocolInfo,
+ addressAsString,&addressSize)==0) {
+ smprintf(s, "%s - ", addressAsString);
+ }
+ smprintf(s, "\"%s\"\n", pResults->lpszServiceInstanceName);
+ if (addressAsString[0] != 0) {
+ for (i=strlen(addressAsString)-1;i>0;i--) {
+ if (addressAsString[i] == ':') break;
+ }
+ if (bluetooth_checkservicename(s, pResults->lpszServiceInstanceName) == ERR_NONE) {
+ error = bluetooth_connect(s,atoi(addressAsString+i+1),address+1);
+ result = WSALookupServiceEnd(handle);
+ return error;
+ }
+ }
+ }
+ result = WSALookupServiceEnd(handle);
+ return ERR_NOTSUPPORTED;
+}
+
+GSM_Error bluetooth_findchannel(GSM_StateMachine *s)
+{
+ GSM_Device_BlueToothData *d = &s->Device.Data.BlueTooth;
+ WSADATA wsaData;
+ int i, protocolInfoSize, result;
+ WSAPROTOCOL_INFO protocolInfo;
+ HANDLE handle;
+ DWORD flags;
+ WSAQUERYSET querySet;
+ BYTE buffer[2000];
+ char addressAsString[1000];
+ DWORD bufferLength, addressSize;
+ WSAQUERYSET *pResults = (WSAQUERYSET*)&buffer;
+ GSM_Error error;
+
+ if (WSAStartup(MAKEWORD(2,2), &wsaData)!=0x00) return ERR_DEVICENODRIVER;
+
+ d->hPhone = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
+ if (d->hPhone == INVALID_SOCKET) {
+ i = GetLastError();
+ GSM_OSErrorInfo(s, "Socket in bluetooth_open");
+ if (i == 10041) return ERR_DEVICENODRIVER;//unknown socket type
+ return ERR_UNKNOWN;
+ }
+
+ protocolInfoSize = sizeof(protocolInfo);
+ if (getsockopt(d->hPhone, SOL_SOCKET, SO_PROTOCOL_INFO,
+ (char*)&protocolInfo, &protocolInfoSize) != 0)
+ {
+ close(d->hPhone);
+ return ERR_UNKNOWN;
+ }
+ close(d->hPhone);
+
+ if (!strcmp(s->CurrentConfig->Device,"com2:")) {
+ bufferLength = sizeof(buffer);
+
+ flags = LUP_RETURN_NAME | LUP_CONTAINERS |
+ LUP_RETURN_ADDR | LUP_FLUSHCACHE |
+ LUP_RETURN_TYPE | LUP_RETURN_BLOB | LUP_RES_SERVICE;
+
+ memset(&querySet, 0, sizeof(querySet));
+ querySet.dwSize = sizeof(querySet);
+ querySet.dwNameSpace = NS_BTH;
+
+ result = WSALookupServiceBegin(&querySet, flags, &handle);
+ if (result != 0) return ERR_UNKNOWN;
+
+ while (1) {
+ result = WSALookupServiceNext(handle, flags, &bufferLength, pResults);
+ if (result != 0) break;
+
+ smprintf(s, "\"%s\"", pResults->lpszServiceInstanceName);
+
+ addressSize = sizeof(addressAsString);
+ addressAsString[0] = 0;
+ if (WSAAddressToString(pResults->lpcsaBuffer->RemoteAddr.lpSockaddr,
+ pResults->lpcsaBuffer->RemoteAddr.iSockaddrLength, &protocolInfo,
+ addressAsString,&addressSize)==0) {
+ smprintf(s, " - %s\n", addressAsString);
+ error = bluetooth_checkdevice(s, addressAsString,&protocolInfo);
+ if (error == ERR_NONE) {
+ result = WSALookupServiceEnd(handle);
+ return error;
+ }
+ } else smprintf(s, "\n");
+ }
+
+ result = WSALookupServiceEnd(handle);
+ return ERR_NOTSUPPORTED;
+ } else {
+ return bluetooth_checkdevice(s, s->CurrentConfig->Device,&protocolInfo);
+ }
+}
+
+#endif
+#endif
+#endif
+
+/* How should editor hadle tabs in this file? Add editor commands here.
+ * vim: noexpandtab sw=8 ts=8 sts=8:
+ */
diff --git a/gammu/emb/common/device/bluetoth/blue_w32.h b/gammu/emb/common/device/bluetoth/blue_w32.h
new file mode 100644
index 0000000..e457c92
--- a/dev/null
+++ b/gammu/emb/common/device/bluetoth/blue_w32.h
@@ -0,0 +1,188 @@
+
+GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device);
+GSM_Error bluetooth_findchannel(GSM_StateMachine *s);
+
+/* MS Platform SDK */
+
+#ifndef __blue_w32_h
+#define __blue_w32_h
+
+#include <pshpack1.h> // Without it compiled code hangs up BT stack
+
+typedef ULONGLONG BTH_ADDR, *PBTH_ADDR;
+
+#define NAP_MASK ((ULONGLONG) 0xFFFF00000000)
+#define SAP_MASK ((ULONGLONG) 0x0000FFFFFFFF)
+
+#define NAP_BIT_OFFSET (8 * 4)
+#define SAP_BIT_OFFSET (0)
+
+#define GET_NAP(_bth_addr) ((USHORT) (((_bth_addr) & NAP_MASK) >> NAP_BIT_OFFSET))
+#define GET_SAP(_bth_addr) ((ULONG) (((_bth_addr) & SAP_MASK) >> SAP_BIT_OFFSET))
+
+#ifndef AF_BTH
+#define AF_BTH 32
+#endif
+
+typedef struct _SOCKADDR_BTH {
+ USHORT addressFamily; // Always AF_BTH
+ BTH_ADDR btAddr; // Bluetooth device address
+ GUID serviceClassId; // [OPTIONAL] system will query SDP for port
+ ULONG port; // RFCOMM channel or L2CAP PSM
+} SOCKADDR_BTH, *PSOCKADDR_BTH;
+
+#define BTHPROTO_RFCOMM 0x0003
+
+#ifdef BLUETOOTH_RF_SEARCHING
+
+typedef struct _SOCKET_ADDRESS {
+ LPSOCKADDR lpSockaddr ;
+ INT iSockaddrLength ;
+} SOCKET_ADDRESS, *PSOCKET_ADDRESS, FAR * LPSOCKET_ADDRESS ;
+
+typedef struct _CSADDR_INFO {
+ SOCKET_ADDRESS LocalAddr ;
+ SOCKET_ADDRESS RemoteAddr ;
+ INT iSocketType ;
+ INT iProtocol ;
+} CSADDR_INFO, *PCSADDR_INFO, FAR * LPCSADDR_INFO ;
+
+typedef struct _AFPROTOCOLS {
+ INT iAddressFamily;
+ INT iProtocol;
+} AFPROTOCOLS, *PAFPROTOCOLS, *LPAFPROTOCOLS;
+
+typedef enum _WSAEcomparator
+{
+ COMP_EQUAL = 0,
+ COMP_NOTLESS
+} WSAECOMPARATOR, *PWSAECOMPARATOR, *LPWSAECOMPARATOR;
+
+typedef struct _WSAVersion
+{
+ DWORD dwVersion;
+ WSAECOMPARATOR ecHow;
+}WSAVERSION, *PWSAVERSION, *LPWSAVERSION;
+
+typedef struct _WSAQuerySetA
+{
+ DWORD dwSize;
+ LPSTR lpszServiceInstanceName;
+ LPGUID lpServiceClassId;
+ LPWSAVERSION lpVersion;
+ LPSTR lpszComment;
+ DWORD dwNameSpace;
+ LPGUID lpNSProviderId;
+ LPSTR lpszContext;
+ DWORD dwNumberOfProtocols;
+ LPAFPROTOCOLS lpafpProtocols;
+ LPSTR lpszQueryString;
+ DWORD dwNumberOfCsAddrs;
+ LPCSADDR_INFO lpcsaBuffer;
+ DWORD dwOutputFlags;
+ LPBLOB lpBlob;
+} WSAQUERYSET, WSAQUERYSETA, *PWSAQUERYSETA, *LPWSAQUERYSETA;
+
+DEFINE_GUID(L2CAP_PROTOCOL_UUID, 0x00000100, 0x0000, 0x1000, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB);
+
+#ifndef NS_BTH
+# define NS_BTH 16
+#endif
+
+#define LUP_CONTAINERS 0x0002
+#define LUP_RETURN_NAME 0x0010
+#define LUP_RETURN_TYPE 0x0020
+#define LUP_RETURN_COMMENT 0x0080
+#define LUP_RETURN_ADDR 0x0100
+#define LUP_RETURN_BLOB 0x0200
+#define LUP_FLUSHCACHE 0x1000
+#define LUP_RES_SERVICE 0x8000
+
+#define WSAAPI FAR PASCAL
+
+#ifndef WINSOCK_API_LINKAGE
+#ifdef DECLSPEC_IMPORT
+#define WINSOCK_API_LINKAGE DECLSPEC_IMPORT
+#else
+#define WINSOCK_API_LINKAGE
+#endif
+#endif
+
+WINSOCK_API_LINKAGE INT WSAAPI
+WSALookupServiceBeginA(
+ IN LPWSAQUERYSETA lpqsRestrictions,
+ IN DWORD dwControlFlags,
+ OUT LPHANDLE lphLookup
+ );
+
+#define WSALookupServiceBegin WSALookupServiceBeginA
+
+WINSOCK_API_LINKAGE INT WSAAPI
+WSALookupServiceNextA(
+ IN HANDLE hLookup,
+ IN DWORD dwControlFlags,
+ IN OUT LPDWORD lpdwBufferLength,
+ OUT LPWSAQUERYSETA lpqsResults
+ );
+
+#define WSALookupServiceNext WSALookupServiceNextA
+
+WINSOCK_API_LINKAGE INT WSAAPI WSALookupServiceEnd(IN HANDLE hLookup);
+
+#define MAX_PROTOCOL_CHAIN 7
+
+typedef struct _WSAPROTOCOLCHAIN {
+ int ChainLen; /* the length of the chain, */
+ /* length = 0 means layered protocol, */
+ /* length = 1 means base protocol, */
+ /* length > 1 means protocol chain */
+ DWORD ChainEntries[MAX_PROTOCOL_CHAIN]; /* a list of dwCatalogEntryIds */
+} WSAPROTOCOLCHAIN, FAR * LPWSAPROTOCOLCHAIN;
+
+#define WSAPROTOCOL_LEN 255
+
+typedef struct _WSAPROTOCOL_INFOA {
+ DWORD dwServiceFlags1;
+ DWORD dwServiceFlags2;
+ DWORD dwServiceFlags3;
+ DWORD dwServiceFlags4;
+ DWORD dwProviderFlags;
+ GUID ProviderId;
+ DWORD dwCatalogEntryId;
+ WSAPROTOCOLCHAIN ProtocolChain;
+ int iVersion;
+ int iAddressFamily;
+ int iMaxSockAddr;
+ int iMinSockAddr;
+ int iSocketType;
+ int iProtocol;
+ int iProtocolMaxOffset;
+ int iNetworkByteOrder;
+ int iSecurityScheme;
+ DWORD dwMessageSize;
+ DWORD dwProviderReserved;
+ CHAR szProtocol[WSAPROTOCOL_LEN+1];
+} WSAPROTOCOL_INFOA, FAR * LPWSAPROTOCOL_INFOA;
+
+typedef WSAPROTOCOL_INFOA WSAPROTOCOL_INFO;
+
+#define SO_PROTOCOL_INFOA 0x2004 /* WSAPROTOCOL_INFOA structure */
+#define SO_PROTOCOL_INFO SO_PROTOCOL_INFOA
+
+WINSOCK_API_LINKAGE INT WSAAPI
+WSAAddressToStringA(
+ IN LPSOCKADDR lpsaAddress,
+ IN DWORD dwAddressLength,
+ IN LPWSAPROTOCOL_INFOA lpProtocolInfo,
+ IN OUT LPSTR lpszAddressString,
+ IN OUT LPDWORD lpdwAddressStringLength
+ );
+
+#define WSAAddressToString WSAAddressToStringA
+
+#endif
+#endif
+
+/* How should editor hadle tabs in this file? Add editor commands here.
+ * vim: noexpandtab sw=8 ts=8 sts=8:
+ */
diff --git a/gammu/emb/common/device/bluetoth/bluetoth.c b/gammu/emb/common/device/bluetoth/bluetoth.c
new file mode 100644
index 0000000..c20e04b
--- a/dev/null
+++ b/gammu/emb/common/device/bluetoth/bluetoth.c
@@ -0,0 +1,85 @@
+/* (c) 2003-2004 by Marcin Wiacek and Marcel Holtmann and others */
+
+#include "../../gsmstate.h"
+
+#ifdef GSM_ENABLE_BLUETOOTHDEVICE
+#ifndef DJGPP
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+#include "../../misc/coding/coding.h"
+#include "../../gsmcomon.h"
+#include "../devfunc.h"
+#include "bluetoth.h"
+
+#ifdef GSM_ENABLE_BLUEZ
+# include "bluez.h"
+#endif
+#ifdef GSM_ENABLE_AFFIX
+# include "affix.h"
+#endif
+#ifdef WIN32
+# include "blue_w32.h"
+#endif
+
+GSM_Error bluetooth_findrfchannel(GSM_StateMachine *s)
+{
+ GSM_Error error;
+
+#ifdef BLUETOOTH_RF_SEARCHING
+ if (!mystrncasecmp(s->CurrentConfig->Connection, "bluerf", 6)) return bluetooth_findchannel(s);
+#endif
+
+ switch (s->ConnectionType) {
+ case GCT_BLUEAT:
+ return bluetooth_connect(s,1,s->CurrentConfig->Device);
+ case GCT_BLUEOBEX:
+ return bluetooth_connect(s,9,s->CurrentConfig->Device);
+ case GCT_BLUEPHONET:
+ error = bluetooth_connect(s,14,s->CurrentConfig->Device); //older Series 40 - 8910, 6310
+ if (error == ERR_NONE) return error;
+ return bluetooth_connect(s,15,s->CurrentConfig->Device); //new Series 40 - 6310i, 6230
+ default:
+ return ERR_UNKNOWN;
+ }
+}
+
+static int bluetooth_read(GSM_StateMachine *s, void *buf, size_t nbytes)
+{
+ return socket_read(s, buf, nbytes, s->Device.Data.BlueTooth.hPhone);
+}
+
+#ifdef WIN32
+static int bluetooth_write(GSM_StateMachine *s, unsigned char *buf, size_t nbytes)
+#else
+static int bluetooth_write(GSM_StateMachine *s, void *buf, size_t nbytes)
+#endif
+{
+ return socket_write(s, buf, nbytes, s->Device.Data.BlueTooth.hPhone);
+}
+
+static GSM_Error bluetooth_close(GSM_StateMachine *s)
+{
+ return socket_close(s, s->Device.Data.BlueTooth.hPhone);
+}
+
+GSM_Device_Functions BlueToothDevice = {
+ bluetooth_findrfchannel,
+ bluetooth_close,
+ NONEFUNCTION,
+ NONEFUNCTION,
+ NONEFUNCTION,
+ bluetooth_read,
+ bluetooth_write
+};
+
+#endif
+#endif
+
+/* How should editor hadle tabs in this file? Add editor commands here.
+ * vim: noexpandtab sw=8 ts=8 sts=8:
+ */
diff --git a/gammu/emb/common/device/bluetoth/bluetoth.h b/gammu/emb/common/device/bluetoth/bluetoth.h
new file mode 100644
index 0000000..8a7fdf4
--- a/dev/null
+++ b/gammu/emb/common/device/bluetoth/bluetoth.h
@@ -0,0 +1,15 @@
+
+#ifndef DJGPP
+#ifndef unixbluetooth_h
+#define unixbluetooth_h
+
+typedef struct {
+ int hPhone;
+} GSM_Device_BlueToothData;
+
+#endif
+#endif
+
+/* How should editor hadle tabs in this file? Add editor commands here.
+ * vim: noexpandtab sw=8 ts=8 sts=8:
+ */
diff --git a/gammu/emb/common/device/bluetoth/bluez.c b/gammu/emb/common/device/bluetoth/bluez.c
new file mode 100644
index 0000000..8a4807e
--- a/dev/null
+++ b/gammu/emb/common/device/bluetoth/bluez.c
@@ -0,0 +1,207 @@
+/* Based on work by Marcel Holtmann and other authors of Bluez */
+
+#include "../../gsmstate.h"
+
+#ifdef GSM_ENABLE_BLUETOOTHDEVICE
+#ifdef GSM_ENABLE_BLUEZ
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/rfcomm.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+#include "../../gsmcomon.h"
+#include "../devfunc.h"
+#include "bluetoth.h"
+
+GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device)
+{
+ GSM_Device_BlueToothData *d = &s->Device.Data.BlueTooth;
+ struct sockaddr_rc laddr, raddr;
+ bdaddr_t bdaddr;
+ int fd;
+
+ smprintf(s, "Connecting to RF channel %i\n",port);
+
+ fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+ if (fd < 0) {
+ dbgprintf("Can't create socket\n");
+ return ERR_DEVICENODRIVER;
+ }
+
+ bacpy(&laddr.rc_bdaddr, BDADDR_ANY);
+ laddr.rc_family = AF_BLUETOOTH;
+ laddr.rc_channel = 0;
+
+ if (bind(fd, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) {
+ dbgprintf("Can't bind socket\n");
+ close(fd);
+ return ERR_DEVICEOPENERROR;
+ }
+
+ str2ba(device, &bdaddr);
+ bacpy(&raddr.rc_bdaddr, &bdaddr);
+ raddr.rc_family = AF_BLUETOOTH;
+ raddr.rc_channel = port;
+
+ if (connect(fd, (struct sockaddr *)&raddr, sizeof(raddr)) < 0) {
+ dbgprintf("Can't connect\n");
+ close(fd);
+ return ERR_DEVICEOPENERROR;
+ }
+
+ d->hPhone = fd;
+ return ERR_NONE;
+}
+
+#ifdef BLUETOOTH_RF_SEARCHING
+
+struct search_context {
+ char *svc;
+ uuid_t group;
+ int tree;
+ uint32_t handle;
+};
+
+static void print_service_desc(void *value, void *user)
+{
+ sdp_data_t *p = (sdp_data_t *)value;
+ int i = 0, proto = 0, *channel = (int *)user;
+
+ for (; p; p = p->next, i++) {
+ switch (p->dtd) {
+ case SDP_UUID16:
+ case SDP_UUID32:
+ case SDP_UUID128:
+ proto = 1;//sdp_uuid_to_proto(&p->val.uuid);
+ break;
+ case SDP_UINT8:
+ if (proto == RFCOMM_UUID) {
+ (*channel) = p->val.uint8;
+ return;
+ }
+ break;
+ }
+ }
+}
+
+void print_access_protos(value, user)
+{
+ sdp_list_t *protDescSeq = (sdp_list_t *)value;
+ int *channel = (int *)user;
+
+ sdp_list_foreach(protDescSeq,print_service_desc,channel);
+}
+
+static GSM_Error bluetooth_checkdevice(GSM_StateMachine *s, bdaddr_t *bdaddr, struct search_context *context)
+{
+ sdp_session_t *sess;
+ sdp_list_t *attrid, *search, *seq, *next, *proto = 0;
+ uint32_t range = 0x0000ffff;
+ char str[20];
+ sdp_record_t *rec;
+ sdp_data_t *d;
+ bdaddr_t interface;
+ struct search_context subcontext;
+ int channel,channel2;
+
+ bacpy(&interface,BDADDR_ANY);
+
+ ba2str(bdaddr, str);
+ smprintf(s,"%s\n", str);
+
+ sess = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY);
+ if (!sess) {
+ dbgprintf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno));
+ return ERR_UNKNOWN;
+ }
+
+ attrid = sdp_list_append(0, &range);
+ search = sdp_list_append(0, &context->group);
+ if (sdp_service_search_attr_req(sess, search, SDP_ATTR_REQ_RANGE, attrid, &seq)) {
+ dbgprintf("Service Search failed: %s\n", strerror(errno));
+ sdp_close(sess);
+ return ERR_UNKNOWN;
+ }
+ sdp_list_free(attrid, 0);
+ sdp_list_free(search, 0);
+
+ channel2 = -1;
+ for (; seq; seq = next) {
+ rec = (sdp_record_t *) seq->data;
+
+ if (channel2 == -1) {
+ if (!context->tree) {
+ d = sdp_data_get(rec,SDP_ATTR_SVCNAME_PRIMARY);
+
+ if (false) {
+ channel = -1;
+ sdp_list_foreach(proto,print_access_protos,&channel);
+ //sdp_list_free(proto,(sdp_free_func_t)sdp_data_free);
+ }
+ smprintf(s,"Channel %i",channel);
+ if (d) smprintf(s," - \"%s\"",d->val.str);
+ smprintf(s,"\n");
+ if (channel2 == -1 && bluetooth_checkservicename(s, d->val.str) == ERR_NONE) {
+ channel2 = channel;
+ }
+ }
+ if (sdp_get_group_id(rec,&subcontext.group) != -1) {
+ memcpy(&subcontext, context, sizeof(struct search_context));
+ if (subcontext.group.value.uuid16 != context->group.value.uuid16) bluetooth_checkdevice(s,bdaddr,&subcontext);
+ }
+ }
+
+ next = seq->next;
+ free(seq);
+ //sdp_record_free(rec);
+ }
+ sdp_close(sess);
+
+ if (channel2 != -1) return bluetooth_connect(s, channel2, str);
+
+ return ERR_UNKNOWN;
+}
+
+GSM_Error bluetooth_findchannel(GSM_StateMachine *s)
+{
+ inquiry_info ii[20];
+ uint8_t count = 0;
+ int i;
+ struct search_context context;
+ GSM_Error error = ERR_NOTSUPPORTED;
+
+ memset(&context, '\0', sizeof(struct search_context));
+ //sdp_uuid16_create(&(context.group),PUBLIC_BROWSE_GROUP);
+
+ if (!strcmp(s->CurrentConfig->Device,"/dev/ttyS1")) {
+ dbgprintf("Searching for devices\n");
+ if (sdp_general_inquiry(ii, 20, 8, &count) < 0) {
+ return ERR_UNKNOWN;
+ }
+ } else {
+ count = 1;
+ str2ba(s->CurrentConfig->Device,&ii[0].bdaddr);
+ }
+ for (i=0;i<count;i++) {
+ error = bluetooth_checkdevice(s,&ii[i].bdaddr,&context);
+ if (error == ERR_NONE) return error;
+ }
+ return error;
+}
+
+#endif
+#endif
+#endif
+
+/* How should editor hadle tabs in this file? Add editor commands here.
+ * vim: noexpandtab sw=8 ts=8 sts=8:
+ */
diff --git a/gammu/emb/common/device/bluetoth/bluez.h b/gammu/emb/common/device/bluetoth/bluez.h
new file mode 100644
index 0000000..896ecbe
--- a/dev/null
+++ b/gammu/emb/common/device/bluetoth/bluez.h
@@ -0,0 +1,3 @@
+
+GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device);
+GSM_Error bluetooth_findchannel(GSM_StateMachine *s);