Gammu internals  1.38.0
blue_bsd.c
Go to the documentation of this file.
1 /*-
2  * Copyright (c) 2009 Iain Hibbert
3  * All rights reserved.
4  *
5  * Licensend under GNU GPL 2 or later.
6  */
7 
8 #include "../../gsmstate.h"
9 
10 #ifdef GSM_ENABLE_BLUETOOTHDEVICE
11 #ifdef BSD_BLUE_FOUND
12 
13 #include <sys/socket.h>
14 #include <sys/time.h>
15 
16 #include <bluetooth.h>
17 #include <errno.h>
18 #include <netdb.h>
19 #include <sdp.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 
25 #include "../../gsmcomon.h"
26 #include "../devfunc.h"
27 #include "bluetooth.h"
28 
29 /*
30  * Handle FreeBSD compatibility
31  */
32 #ifndef BTPROTO_RFCOMM
33 #define BTPROTO_RFCOMM BLUETOOTH_PROTO_RFCOMM
34 #define BDADDR_ANY NG_HCI_BDADDR_ANY
35 #define sockaddr_bt sockaddr_rfcomm
36 #define bt_len rfcomm_len
37 #define bt_family rfcomm_family
38 #define bt_channel rfcomm_channel
39 #define bt_bdaddr rfcomm_bdaddr
40 #define bdaddr_copy(d, s) memcpy((d), (s), sizeof(bdaddr_t))
41 #endif
42 
43 static GSM_Error bluetooth_open(GSM_StateMachine *s, bdaddr_t *bdaddr, int channel)
44 {
45  GSM_Device_BlueToothData *d = &s->Device.Data.BlueTooth;
46  struct sockaddr_bt sa;
47  int fd;
48 
49  memset(&sa, 0, sizeof(sa));
50  sa.bt_len = sizeof(sa);
51  sa.bt_family = AF_BLUETOOTH;
52 
53  smprintf(s, "Connecting to RF channel %i\n", channel);
54 
55  fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
56  if (fd < 0) {
57  smprintf(s, "Can't create socket\n");
58  return ERR_DEVICENODRIVER;
59  }
60 
61  bdaddr_copy(&sa.bt_bdaddr, BDADDR_ANY);
62 
63  if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
64  smprintf(s, "Can't bind socket: %s\n", strerror(errno));
65  close(fd);
66  return ERR_DEVICEOPENERROR;
67  }
68 
69  sa.bt_channel = channel;
70  bdaddr_copy(&sa.bt_bdaddr, bdaddr);
71 
72  if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
73  smprintf(s, "Can't connect to %s: %s\n", bt_ntoa(bdaddr, NULL), strerror(errno));
74  close(fd);
75  return ERR_DEVICEOPENERROR;
76  }
77 
78  d->hPhone = fd;
79  return ERR_NONE;
80 }
81 
82 GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device)
83 {
84  bdaddr_t bdaddr;
85  struct hostent *he = NULL;
86 
87  if (!bt_aton(device, &bdaddr)) {
88  if ((he = bt_gethostbyname(device)) == NULL) {
89  smprintf(s, "%s: %s\n", device, hstrerror(h_errno));
90  return ERR_UNKNOWN;
91  }
92 
93  bdaddr_copy(&bdaddr, (bdaddr_t *)he->h_addr);
94  }
95 
96  return bluetooth_open(s, &bdaddr, port);
97 }
98 
99 #ifdef BLUETOOTH_RF_SEARCHING
100 
101 static int bluetooth_channel(sdp_data_t *value)
102 {
103  sdp_data_t pdl, seq;
104  uintmax_t channel;
105 
106  sdp_get_alt(value, value); /* strip any alt container */
107 
108  while (sdp_get_seq(value, &pdl)) {
109  if (sdp_get_seq(&pdl, &seq)
110  && sdp_match_uuid16(&seq, SDP_UUID_PROTOCOL_L2CAP)
111  && sdp_get_seq(&pdl, &seq)
112  && sdp_match_uuid16(&seq, SDP_UUID_PROTOCOL_RFCOMM)
113  && sdp_get_uint(&seq, &channel)
114  && channel >= 1 && channel <= 30)
115  return channel;
116  }
117 
118  return -1;
119 }
120 
121 static char *bluetooth_service(sdp_data_t *value)
122 {
123  char *str;
124  size_t len;
125 
126  if (!sdp_get_str(value, &str, &len))
127  return NULL;
128 
129  return strndup(str, len);
130 }
131 
132 static GSM_Error bluetooth_search(GSM_StateMachine *s, bdaddr_t *bdaddr)
133 {
134  sdp_data_t rec, rsp, ssp, value;
135  uint8_t buf[3];
136  uint16_t attr;
137  sdp_session_t ss;
138  int ch, channel, sc, score;
139  char *sv;
140 
141  smprintf(s, "Searching for services on %s\n", bt_ntoa(bdaddr, NULL));
142 
143  ss = sdp_open(NULL, bdaddr);
144  if (ss == NULL) {
145  smprintf(s, "SDP Connection failed: %s\n", strerror(errno));
146  return ERR_TIMEOUT;
147  }
148 
149  ssp.next = buf;
150  ssp.end = buf + sizeof(buf);
151  sdp_put_uuid16(&ssp, SDP_UUID_PROTOCOL_RFCOMM);
152  ssp.end = ssp.next;
153  ssp.next = buf;
154 
155  if (!sdp_service_search_attribute(ss, &ssp, NULL, &rsp)) {
156  smprintf(s, "SDP Service Search Attribute failed: %s\n", strerror(errno));
157  sdp_close(ss);
158  return ERR_UNKNOWN;
159  }
160 
161  channel = -1;
162  score = 0;
163 
164  while (sdp_get_seq(&rsp, &rec)) {
165  ch = -1;
166  sv = NULL;
167 
168  while (sdp_get_attr(&rec, &attr, &value)) {
169  switch (attr) {
170  case SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST:
171  ch = bluetooth_channel(&value);
172  break;
173 
174  case SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET:
175  sv = bluetooth_service(&value);
176  break;
177 
178  default:
179  break;
180  }
181  }
182 
183  if (ch != -1) {
184  smprintf(s, " Channel %i", ch);
185  if (sv != NULL) {
186  sc = bluetooth_checkservicename(s, sv);
187  smprintf(s, " - \"%s\" (score=%d)", sv, sc);
188  if (sc > score) {
189  score = sc;
190  channel = ch;
191  }
192  }
193  smprintf(s, "\n");
194  }
195  free(sv);
196  sv=NULL;
197  }
198 
199  sdp_close(ss);
200 
201  if (channel == -1) {
202  smprintf(s, "No suitable service found!\n");
203  return ERR_NOTSUPPORTED;
204  }
205 
206  return bluetooth_open(s, bdaddr, channel);
207 }
208 
210 {
211  char *device = s->CurrentConfig->Device;
212  bdaddr_t bdaddr;
213  struct hostent *he;
214  struct bt_devinquiry *ii;
215  int count, n;
216 
217  if (bt_aton(device, &bdaddr))
218  return bluetooth_search(s, &bdaddr);
219 
220  if ((he = bt_gethostbyname(device)) != NULL)
221  return bluetooth_search(s, (bdaddr_t *)he->h_addr);
222 
223  smprintf(s, "Device \"%s\" unknown. Starting inquiry..\n", device);
224 
225  if ((count = bt_devinquiry(NULL, 10, 20, &ii)) == -1) {
226  smprintf(s, "Inquiry failed: %s\n", strerror(errno));
227  return ERR_UNKNOWN;
228  }
229 
230  smprintf(s, "Found %d device%s.\n", count, (count == 1 ? "" : "s"));
231 
232  for (n = 0; n < count; n++) {
233  if (bluetooth_search(s, &ii[n].bdaddr) == ERR_NONE) {
234  free(ii);
235  ii=NULL;
236  free(s->CurrentConfig->Device);
237  s->CurrentConfig->Device = (char *)malloc(18);
238  if (s->CurrentConfig->Device == NULL) {
239  return ERR_MOREMEMORY;
240  }
241  bt_ntoa(&ii[0].bdaddr, s->CurrentConfig->Device);
242  return ERR_NONE;
243  }
244  }
245 
246  free(ii);
247  ii=NULL;
248  return ERR_UNKNOWN;
249 }
250 
251 #endif
252 #endif
253 #endif
254 
255 /* How should editor hadle tabs in this file? Add editor commands here.
256  * vim: noexpandtab sw=8 ts=8 sts=8:
257  */
GSM_Config * CurrentConfig
Definition: gsmstate.h:1415
union GSM_Device::@0 Data
GSM_Error
Definition: gammu-error.h:23
GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device)
socket_type hPhone
Definition: bluetooth.h:7
GSM_Error bluetooth_findchannel(GSM_StateMachine *s)
GSM_Device Device
Definition: gsmstate.h:1429
int smprintf(GSM_StateMachine *s, const char *format,...)
Definition: debug.c:261