Gammu internals  1.38.0
devfunc.c
Go to the documentation of this file.
1 /* Some source from Gnokii (www.gnokii.org)
2  * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
3  * GNU GPL version 2 or later
4  */
5 /* Due to a problem in the source code management, the names of some of
6  * the authors have unfortunately been lost. We do not mean to belittle
7  * their efforts and hope they will contact us to see their names
8  * properly added to the Copyright notice above.
9  * Having published their contributions under the terms of the GNU
10  * General Public License (GPL) [version 2], the Copyright of these
11  * authors will remain respected by adhering to the license they chose
12  * to publish their code under.
13  */
14 
15 #include <string.h>
16 #include <fcntl.h>
17 #include <stdlib.h>
18 #ifdef WIN32
19 # include <winsock2.h>
20 # include <io.h>
21 #else
22 # include <errno.h>
23 # include <ctype.h>
24 # include <signal.h>
25 # include <sys/socket.h>
26 # include <sys/stat.h>
27 #endif
28 
29 #include "devfunc.h"
30 #include "../gsmstate.h"
31 
32 #ifdef GSM_ENABLE_BLUETOOTHDEVICE
33 #ifdef BLUETOOTH_RF_SEARCHING
34 
35 int bluetooth_checkservicename(GSM_StateMachine *s, const char *name)
36 {
37  /* Phonet */
38  if (s->ConnectionType == GCT_BLUEPHONET) {
39  if (strstr(name, "Nokia PC Suite") != NULL) return 1;
40 
41  /* Series 60 remote */
42  } else if (s->ConnectionType == GCT_BLUES60) {
43  if (strstr(name, "pys60_remote") != NULL) return 1;
44 
45  /* OBEX */
46  } else if (s->ConnectionType == GCT_BLUEOBEX) {
47  /* Prefer this on Nokia as this gives better access to filesystem */
48  if (strstr(name, "Nokia OBEX PC Suite Services") != NULL) {
49  if (strcmp(s->CurrentConfig->Model, "obex") == 0) {
50  return 5;
51  }
52  return 3;
53  }
54  /* For filesystem, we prefer file transfer */
55  if (strstr(name, "OBEX File Transfer") != NULL || strstr(name, "OBEX file transfer") != NULL) {
56  if (strcmp(s->CurrentConfig->Model, "obex") == 0 ||
57  strcmp(s->CurrentConfig->Model, "obexfs") == 0) {
58  return 4;
59  }
60  return 3;
61  }
62  /* Ususally this name also contains OBEX, prefered for irmc */
63  if (strstr(name, "IrMC Sync") != NULL || strstr(name, "OBEX Synchronisation")) {
64  if (strcmp(s->CurrentConfig->Model, "obexirmc") == 0 ||
65  strcmp(s->CurrentConfig->Model, "seobex") == 0) {
66  return 4;
67  }
68  return 3;
69  }
70  /* Simple send of files should work here */
71  if (strstr(name, "OBEX Object Push") != NULL) {
72  if (strcmp(s->CurrentConfig->Model, "obexnone") == 0) {
73  return 3;
74  }
75  return 2;
76  }
77 #if 0
78  /* Not supported currently */
79  /* Phone Book Access */
80  if (strstr(name, "PSE") != NULL) {
81  if (strcmp(s->CurrentConfig->Model, "obexirmc") == 0) {
82  return 3;
83  }
84  return 2;
85  }
86  /* Phone Book Access Profile */
87  if (strstr(name, "PBAP") != NULL) {
88  if (strcmp(s->CurrentConfig->Model, "obexirmc") == 0) {
89  return 3;
90  }
91  return 2;
92  }
93 #endif
94  /* Object Push Profile */
95  if (strstr(name, "OPP") != NULL) {
96  if (strcmp(s->CurrentConfig->Model, "obexnone") == 0) {
97  return 3;
98  }
99  return 2;
100  }
101  /* Anything matching OBEX has lowest priority */
102  if (strstr(name, "OBEX") != NULL) return 1;
103 
104  /* AT */
105  } else if (s->ConnectionType == GCT_BLUEAT) {
106  /* Nokia */
107  if (strstr(name, "Dial-Up Networking") != NULL) return 2;
108  /* Sony-Ericsson */
109  if (strstr(name, "Serial Port 1") != NULL) return 3;
110  if (strstr(name, "Serial Port") != NULL) return 2;
111  /* Motorola */
112  if (strstr(name, "Dial-up networking Gateway") != NULL) return 3;
113  if (strstr(name, "Serial port") != NULL) return 2;
114  /* Samsung */
115  if (strstr(name, "Dial-up Networking") != NULL) return 3;
116  if (strstr(name, "Dial-Up Networking Gateway") != NULL) return 3;
117  if (strstr(name, "Dialup Networking") != NULL) return 3;
118  if (strstr(name, "Serial Server") != NULL) return 3;
119  /* Siemens, Thomas Eitzenberger */
120  if (strstr(name, "SerialPort1") != NULL) return 3;
121  if (strstr(name, "SerialPort") != NULL) return 2;
122 
123  /* MyPhoneExplorer client on Android */
124  if (strstr(name, "MyPhoneExplorer") != NULL) return 1;
125 
126  if (strstr(name, "COM1") != NULL) return 3;
127  if (strstr(name, "COM") != NULL) return 1;
128  }
129 
130  return 0;
131 }
132 
133 #endif
134 #endif
135 
136 #if defined (GSM_ENABLE_BLUETOOTHDEVICE) || defined (GSM_ENABLE_IRDADEVICE)
137 
138 /* Windows do not have this, but we don't seem to need it there */
139 #ifndef MSG_DONTWAIT
140 #define MSG_DONTWAIT 0
141 #endif
142 
143 int socket_read(GSM_StateMachine *s UNUSED, void *buf, size_t nbytes, socket_type hPhone)
144 {
145  fd_set readfds;
146  int result = 0;
147  struct timeval timer;
148 
149  FD_ZERO(&readfds);
150  FD_SET(hPhone, &readfds);
151 
152  timer.tv_sec = 0;
153  timer.tv_usec = 0;
154 
155  if (select(hPhone + 1, &readfds, NULL, NULL, &timer) > 0) {
156  result = recv(hPhone, buf, nbytes, MSG_DONTWAIT);
157 #ifndef WIN32
158  if (result < 0 && errno != EINTR) {
159  return 0;
160  }
161 #endif
162  }
163 
164  return result;
165 }
166 
167 int socket_write(GSM_StateMachine *s, unsigned const char *buf, size_t nbytes, socket_type hPhone)
168 {
169  int ret;
170  size_t actual = 0;
171 
172  do {
173  ret = send(hPhone, buf, nbytes - actual, 0);
174  if (ret < 0) {
175  if (actual != nbytes) {
176  GSM_OSErrorInfo(s,"socket_write");
177 #ifndef WIN32
178  if (errno != EINTR) {
179  return 0;
180  }
181 #endif
182  }
183  return actual;
184  }
185  actual += ret;
186  buf += ret;
187  } while (actual < nbytes);
188 
189  return actual;
190 }
191 
192 GSM_Error socket_close(GSM_StateMachine *s UNUSED, socket_type hPhone)
193 {
194  shutdown(hPhone, 0);
195 #ifdef WIN32
196  closesocket(hPhone); /*FIXME: error checking */
197 #else
198  close(hPhone); /*FIXME: error checking */
199 #endif
200  return ERR_NONE;
201 }
202 
203 #endif
204 
205 #define max_buf_len 128
206 #define lock_path "/var/lock/LCK.."
207 
208 /* Lock the device. Allocated string with a lock name is returned
209  * in lock_device
210  */
211 #if !defined(WIN32) && !defined(DJGPP)
212 GSM_Error lock_device(GSM_StateMachine *s, const char* port, char **lock_name)
213 {
214  char *lock_file = NULL;
215  char buffer[max_buf_len];
216  const char *aux;
217  int fd = -1, len;
218  GSM_Error error = ERR_NONE;
219  size_t wrotebytes;
220  char buf[max_buf_len];
221  int pid, n = 0;
222 
223 
224  smprintf(s, "Locking device\n");
225 
226  aux = strrchr(port, '/');
227  /* Remove leading '/' */
228  if (aux) {
229  aux++;
230  } else {
231  /* No / in port */
232  aux = port;
233  }
234  len = strlen(aux) + strlen(lock_path);
235 
236  memset(buffer, 0, sizeof(buffer));
237  lock_file = calloc(len + 1, 1);
238  if (!lock_file) {
239  smprintf(s, "Out of memory error while locking device\n");
240  return ERR_MOREMEMORY;
241  }
242  /* I think we don't need to use strncpy, as we should have enough
243  * buffer due to strlen results
244  */
245  strcpy(lock_file, lock_path);
246  strcat(lock_file, aux);
247 
248  /* Check for the stale lockfile.
249  * The code taken from minicom by Miquel van Smoorenburg */
250  if ((fd = open(lock_file, O_RDONLY)) >= 0) {
251  n = read(fd, buf, sizeof(buf) - 1);
252  if (n <= 0) {
253  goto failread;
254  }
255  if (n == 4 && 4 == sizeof(int) &&
256  ! (
257  isdigit((int)buf[0]) &&
258  isdigit((int)buf[1]) &&
259  isdigit((int)buf[2]) &&
260  isdigit((int)buf[3])
261  )) {
262  /* Rewind */
263  lseek(fd, 0, SEEK_SET);
264  /* Read PID */
265  /* We could make it from buf, but we would have to care about endians. */
266  n = read(fd, &pid, sizeof(int));
267  if (n != 4) {
268  smprintf(s, "Reading lock for second time failed\n");
269  goto failread;
270 
271  }
272  } else {
273  /* Ascii lockfile. */
274  buf[n] = 0;
275  sscanf(buf, "%d", &pid);
276  }
277  close(fd);
278  fd = -1;
279 
280 
281  if (pid > 0 && kill((pid_t)pid, 0) < 0 && errno == ESRCH) {
282  smprintf(s, "Lockfile %s is stale. Overriding it..\n", lock_file);
283  if (unlink(lock_file) != 0) {
284  smprintf(s, "Overriding failed, please check the permissions\n");
285  smprintf(s, "Cannot lock device\n");
286  error = ERR_DEVICENOPERMISSION;
287  goto failed;
288  }
289  } else {
290  smprintf(s, "Device already locked by PID %d.\n", pid);
291  error = ERR_DEVICELOCKED;
292  goto failed;
293  }
294  }
295 
296  /* Try to create a new file, with 0644 mode */
297  fd = open(lock_file, O_CREAT | O_EXCL | O_WRONLY, 0644);
298  if (fd == -1) {
299  if (errno == EEXIST) {
300  smprintf(s, "Device seems to be locked by unknown process\n");
301  error = ERR_DEVICEOPENERROR;
302  } else if (errno == EACCES) {
303  smprintf(s, "Please check permission on lock directory\n");
304  error = ERR_DEVICENOPERMISSION;
305  } else if (errno == ENOENT) {
306  smprintf(s, "Cannot create lockfile %s. Please check for existence of path\n", lock_file);
307  error = ERR_UNKNOWN;
308  } else {
309  smprintf(s, "Unknown error with creating lockfile %s\n", lock_file);
310  error = ERR_UNKNOWN;
311  }
312  goto failed;
313  }
314  sprintf(buffer, "%10ld gammu\n", (long)getpid());
315  wrotebytes = write(fd, buffer, strlen(buffer));
316  close(fd);
317  fd = -1;
318  if (wrotebytes != strlen(buffer)) {
319  error = ERR_WRITING_FILE;
320  goto failed;
321  }
322  *lock_name = lock_file;
323  return ERR_NONE;
324 failread:
325  smprintf(s, "Unable to read lockfile %s.\n", lock_file);
326  smprintf(s, "Please check for reason and remove the lockfile by hand.\n");
327  smprintf(s, "Cannot lock device\n");
328  error = ERR_UNKNOWN;
329 failed:
330  if (fd != -1) {
331  close(fd);
332  }
333  free(lock_file);
334  *lock_name = NULL;
335  return error;
336 }
337 #else
338 GSM_Error lock_device(GSM_StateMachine *s UNUSED, const char* port UNUSED, char **lock_name)
339 {
340  *lock_name = NULL;
341  return ERR_NONE;
342 }
343 #endif
344 
345 /* Removes lock and frees memory */
346 #if !defined(WIN32) && !defined(DJGPP)
348 {
349  int err;
350 
351  if (lock_file == NULL || *lock_file == NULL) {
352  smprintf(s, "Cannot unlock device\n");
353  return FALSE;
354  }
355  err = unlink(*lock_file);
356  free(*lock_file);
357  *lock_file = NULL;
358  return (err + 1);
359 }
360 #else
361 gboolean unlock_device(GSM_StateMachine *s UNUSED, char **lock_file UNUSED)
362 {
363  return TRUE;
364 }
365 #endif
366 
367 int FindSerialSpeed(const char *buffer)
368 {
369  switch (atoi(buffer)) {
370  case 50 : return 50;
371  case 75 : return 75;
372  case 110 : return 110;
373  case 134 : return 134;
374  case 150 : return 150;
375  case 200 : return 200;
376  case 300 : return 300;
377  case 600 : return 600;
378  case 1200 : return 1200;
379  case 1800 : return 1800;
380  case 2400 : return 2400;
381  case 3600 : return 3600;
382  case 4800 : return 4800;
383  case 7200 : return 7200;
384  case 9600 : return 9600;
385  case 14400 : return 14400;
386  case 19200 : return 19200;
387  case 28800 : return 28800;
388  case 38400 : return 38400;
389  case 57600 : return 57600;
390  case 115200 : return 115200;
391  case 230400 : return 230400;
392  case 460800 : return 460800;
393  case 614400 : return 614400;
394  case 921600 : return 921600;
395  case 1228800 : return 1228800;
396  case 2457600 : return 2457600;
397  case 3000000 : return 3000000;
398  case 6000000 : return 6000000;
399  default : return 0;
400  }
401 }
402 
403 /* How should editor hadle tabs in this file? Add editor commands here.
404  * vim: noexpandtab sw=8 ts=8 sts=8:
405  */
GSM_Config * CurrentConfig
Definition: gsmstate.h:1415
GSM_ConnectionType ConnectionType
Definition: gsmstate.h:1402
int FindSerialSpeed(const char *buffer)
Definition: devfunc.c:367
int socket_type
Definition: misc.h:114
GSM_Error
Definition: gammu-error.h:23
#define lock_path
Definition: devfunc.c:206
gboolean unlock_device(GSM_StateMachine *s, char **lock_file)
Definition: devfunc.c:347
#define max_buf_len
Definition: devfunc.c:205
int gboolean
Definition: gammu-types.h:23
#define FALSE
Definition: gammu-types.h:25
void GSM_OSErrorInfo(GSM_StateMachine *s, const char *description)
Definition: gsmstate.c:1593
#define TRUE
Definition: gammu-types.h:28
#define UNUSED
Definition: gammu-misc.h:105
int smprintf(GSM_StateMachine *s, const char *format,...)
Definition: debug.c:261
GSM_Error lock_device(GSM_StateMachine *s, const char *port, char **lock_name)
Definition: devfunc.c:212