Gammu internals  1.38.0
blue_w32.c
Go to the documentation of this file.
1 /* (c) 2003-2004 by Marcin Wiacek and Intra */
2 
3 /* To define GUID and not only declare */
4 #define INITGUID
5 #include "../../gsmstate.h"
6 
7 #ifdef GSM_ENABLE_BLUETOOTHDEVICE
8 #ifdef WIN32
9 
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <fcntl.h>
13 #include <errno.h>
14 #include <string.h>
15 #define WIN32_LEAN_AND_MEAN
16 #include <windows.h>
17 #include <winsock2.h>
18 #include <ole2.h>
19 #include <io.h>
20 
21 #include "../../misc/coding/coding.h"
22 #include "../../gsmcomon.h"
23 #include "../devfunc.h"
24 #include "bluetooth.h"
25 #include "blue_w32.h"
26 
27 GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device)
28 {
29  GSM_Device_BlueToothData *d = &s->Device.Data.BlueTooth;
30  WSADATA wsaData;
31  SOCKADDR_BTH sab;
32  DWORD err;
33  const char *ch;
34 
35  smprintf(s, "Connecting to RF channel %i\n",port);
36 
37  /* BCC comes with broken MAKEWORD, which emmits warnings */
38 #ifdef __BORLANDC__
39 # pragma warn -8084
40 #endif
41  WSAStartup(MAKEWORD(1,1), &wsaData);
42 #ifdef __BORLANDC__
43 # pragma warn +8084
44 #endif
45 
46  d->hPhone = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
47  if (d->hPhone == INVALID_SOCKET) {
48  err = GetLastError();
49  GSM_OSErrorInfo(s, "Socket in bluetooth_open");
50  if (err == WSAEPROTOTYPE)
51  return ERR_DEVICENODRIVER;/* unknown socket type */
52  return ERR_UNKNOWN;
53  }
54 
55  memset (&sab, 0, sizeof(sab));
56  sab.port = port;
57  sab.addressFamily = AF_BTH;
58  sab.btAddr = 0;
59  for (ch = device; *ch != '\0'; ch++){
60  if (*ch >='0' && *ch <='9') {
61  sab.btAddr = sab.btAddr * 16;
62  sab.btAddr = sab.btAddr + (*ch-'0');
63  } else if (*ch >='a' && *ch <='f') {
64  sab.btAddr = sab.btAddr * 16;
65  sab.btAddr = sab.btAddr + (*ch-'a'+10);
66  } else if (*ch >='A' && *ch <='F') {
67  sab.btAddr = sab.btAddr * 16;
68  sab.btAddr = sab.btAddr + (*ch-'A'+10);
69  }
70  }
71 
72  smprintf(s, "Remote Bluetooth device is %02x:%02x:%02x:%02x:%02x:%02x\n",
73  GET_BYTE(sab.btAddr, 5),
74  GET_BYTE(sab.btAddr, 4),
75  GET_BYTE(sab.btAddr, 3),
76  GET_BYTE(sab.btAddr, 2),
77  GET_BYTE(sab.btAddr, 1),
78  GET_BYTE(sab.btAddr, 0));
79 
80  if (connect (d->hPhone, (struct sockaddr *)&sab, sizeof(sab)) != 0) {
81  err = GetLastError();
82  GSM_OSErrorInfo(s, "Connect in bluetooth_open");
83 
84  /* Close the handle */
85  closesocket(d->hPhone);
86 
87  switch (err) {
88  case WSAETIMEDOUT:
89  smprintf(s, "The I/O timed out at the Bluetooth radio level (PAGE_TIMEOUT).\n");
90  return ERR_TIMEOUT;
91  case WSAEDISCON:
92  smprintf(s, "The RFCOMM channel disconnected by remote peer.\n");
93  return ERR_DEVICEOPENERROR;
94  case WSAEHOSTDOWN:
95  smprintf(s, "The RFCOMM received DM response.\n");
96  return ERR_DEVICEOPENERROR;
97  case WSAENETDOWN:
98  smprintf(s, "Unexpected network error.\n");
99  return ERR_DEVICENOTWORK;
100  case WSAESHUTDOWN:
101  smprintf(s, "The L2CAP channel disconnected by remote peer.\n");
102  return ERR_DEVICEOPENERROR;
103  case WSAENETUNREACH:
104  smprintf(s, "Error other than time-out at L2CAP or Bluetooth radio level.\n");
105  return ERR_DEVICENOTWORK;
106  }
107  return ERR_UNKNOWN;
108  }
109 
110  return ERR_NONE;
111 }
112 
113 #ifdef BLUETOOTH_RF_SEARCHING
114 
115 DEFINE_GUID(L2CAP_PROTOCOL_UUID, 0x00000100, 0x0000, 0x1000, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB);
116 
117 #ifndef __GNUC__
118 #pragma comment(lib, "ws2_32.lib")
119 #endif
120 
121 static GSM_Error bluetooth_checkdevice(GSM_StateMachine *s, char *address, WSAPROTOCOL_INFO *protocolInfo)
122 {
123  int found = -1;
124  int score, bestscore = 0;
125  WSAQUERYSET querySet;
126  DWORD flags;
127  GUID protocol;
128  int i, result;
129  BYTE buffer[2000];
130  char addressAsString[1000];
131  DWORD bufferLength, addressSize;
132  WSAQUERYSET *pResults = (WSAQUERYSET*)&buffer;
133  HANDLE handle;
134 
135  memset(&querySet, 0, sizeof(querySet));
136  querySet.dwSize = sizeof(querySet);
137  protocol = L2CAP_PROTOCOL_UUID;
138  querySet.lpServiceClassId = &protocol;
139  querySet.dwNameSpace = NS_BTH;
140  querySet.lpszContext = address;
141 
142  flags = LUP_FLUSHCACHE | LUP_RETURN_NAME |
143  LUP_RETURN_TYPE | LUP_RETURN_ADDR |
144  LUP_RETURN_BLOB | LUP_RETURN_COMMENT;
145 
146  result = WSALookupServiceBegin(&querySet, flags, &handle);
147  if (result != 0) return ERR_UNKNOWN;
148 
149  bufferLength = sizeof(buffer);
150  while (1) {
151  result = WSALookupServiceNext(handle, flags, &bufferLength, pResults);
152  if (result != 0) break;
153  addressSize = sizeof(addressAsString);
154  addressAsString[0] = 0;
155  if (WSAAddressToString(pResults->lpcsaBuffer->RemoteAddr.lpSockaddr,
156  pResults->lpcsaBuffer->RemoteAddr.iSockaddrLength, protocolInfo,
157  addressAsString,&addressSize)==0) {
158  smprintf(s, "%s - ", addressAsString);
159  }
160  score = bluetooth_checkservicename(s, pResults->lpszServiceInstanceName);
161  smprintf(s, "\"%s\" (score=%d)\n", pResults->lpszServiceInstanceName, score);
162  if (addressAsString[0] != 0) {
163  for (i=strlen(addressAsString)-1;i>0;i--) {
164  if (addressAsString[i] == ':') break;
165  }
166  if (score > bestscore) {
167  found = atoi(addressAsString+i+1);
168  bestscore = score;
169  }
170  }
171  }
172  result = WSALookupServiceEnd(handle);
173  if (found != -1) {
174  return bluetooth_connect(s,found,address+1);
175  }
176  return ERR_NOTSUPPORTED;
177 }
178 
180 {
181  GSM_Device_BlueToothData *d = &s->Device.Data.BlueTooth;
182  WSADATA wsaData;
183  int protocolInfoSize, result;
184  WSAPROTOCOL_INFO protocolInfo;
185  HANDLE handle;
186  DWORD flags;
187  WSAQUERYSET querySet;
188  BYTE buffer[2000];
189  char addressAsString[1000];
190  DWORD bufferLength, addressSize;
191  WSAQUERYSET *pResults = (WSAQUERYSET*)&buffer;
192  GSM_Error error;
193  DWORD err;
194 
195  /* BCC comes with broken MAKEWORD, which emmits warnings */
196 #ifdef __BORLANDC__
197 # pragma warn -8084
198 #endif
199  if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0x00) return ERR_DEVICENODRIVER;
200 #ifdef __BORLANDC__
201 # pragma warn +8084
202 #endif
203 
204  d->hPhone = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
205  if (d->hPhone == INVALID_SOCKET) {
206  err = GetLastError();
207  GSM_OSErrorInfo(s, "Socket in bluetooth_open");
208  if (err == WSAEPROTOTYPE)
209  return ERR_DEVICENODRIVER;/* unknown socket type */
210  smprintf(s, "Failed to socket in bluetooth_open\n");
211  return ERR_UNKNOWN;
212  }
213 
214  protocolInfoSize = sizeof(protocolInfo);
215  if (getsockopt(d->hPhone, SOL_SOCKET, SO_PROTOCOL_INFO,
216  (char*)&protocolInfo, &protocolInfoSize) != 0)
217  {
218  GSM_OSErrorInfo(s, "getsockopt in bluetooth_open");
219  closesocket(d->hPhone);
220  smprintf(s, "Failed to getsockopt in bluetooth_open\n");
221  return ERR_UNKNOWN;
222  }
223  closesocket(d->hPhone);
224 
225  if (!strcmp(s->CurrentConfig->Device,"com2:")) {
226  bufferLength = sizeof(buffer);
227 
228  flags = LUP_RETURN_NAME | LUP_CONTAINERS |
229  LUP_RETURN_ADDR | LUP_FLUSHCACHE |
230  LUP_RETURN_TYPE | LUP_RETURN_BLOB | LUP_RES_SERVICE;
231 
232  memset(&querySet, 0, sizeof(querySet));
233  querySet.dwSize = sizeof(querySet);
234  querySet.dwNameSpace = NS_BTH;
235 
236  result = WSALookupServiceBegin(&querySet, flags, &handle);
237  GSM_OSErrorInfo(s, "WSALookupServiceBegin in bluetooth_open");
238  if (result != 0) {
239  smprintf(s, "Failed to WSALookupServiceBegin in bluetooth_open\n");
240  return ERR_UNKNOWN;
241  }
242 
243  while (1) {
244  result = WSALookupServiceNext(handle, flags, &bufferLength, pResults);
245  if (result != 0) break;
246 
247  smprintf(s, "\"%s\"", pResults->lpszServiceInstanceName);
248 
249  addressSize = sizeof(addressAsString);
250  addressAsString[0] = 0;
251  if (WSAAddressToString(pResults->lpcsaBuffer->RemoteAddr.lpSockaddr,
252  pResults->lpcsaBuffer->RemoteAddr.iSockaddrLength, &protocolInfo,
253  addressAsString,&addressSize)==0) {
254  smprintf(s, " - %s\n", addressAsString);
255  error = bluetooth_checkdevice(s, addressAsString,&protocolInfo);
256  if (error == ERR_NONE) {
257  free(s->CurrentConfig->Device);
258  s->CurrentConfig->Device = strdup(addressAsString);
259  if (s->CurrentConfig->Device == NULL) {
260  return ERR_MOREMEMORY;
261  }
262  result = WSALookupServiceEnd(handle);
263  return error;
264  }
265  } else smprintf(s, "\n");
266  }
267 
268  result = WSALookupServiceEnd(handle);
269  return ERR_NOTSUPPORTED;
270  } else {
271  return bluetooth_checkdevice(s, s->CurrentConfig->Device,&protocolInfo);
272  }
273 }
274 
275 #endif
276 #endif
277 #endif
278 
279 /* How should editor hadle tabs in this file? Add editor commands here.
280  * vim: noexpandtab sw=8 ts=8 sts=8:
281  */
GSM_Config * CurrentConfig
Definition: gsmstate.h:1415
ULONG port
Definition: blue_w32.h:37
union GSM_Device::@0 Data
#define AF_BTH
Definition: blue_w32.h:30
#define BTHPROTO_RFCOMM
Definition: blue_w32.h:40
GSM_Error
Definition: gammu-error.h:23
GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device)
BTH_ADDR btAddr
Definition: blue_w32.h:35
socket_type hPhone
Definition: bluetooth.h:7
void GSM_OSErrorInfo(GSM_StateMachine *s, const char *description)
Definition: gsmstate.c:1593
USHORT addressFamily
Definition: blue_w32.h:34
GSM_Error bluetooth_findchannel(GSM_StateMachine *s)
#define GET_BYTE(num, byte)
Definition: blue_w32.h:13
GSM_Device Device
Definition: gsmstate.h:1429
int smprintf(GSM_StateMachine *s, const char *format,...)
Definition: debug.c:261