1 #include "../helper/locales.h"
2 
3 #include <gammu.h>
4 #include <string.h>
5 #include <stdarg.h>
6 
7 #ifdef HAVE_PTHREAD
8 #  include <pthread.h>
9 #  include <sys/types.h>
10 #  include <sys/stat.h>
11 #  include <fcntl.h>
12 #  define THREAD_RETURN void *
13 #  define THREAD_RETURN_VAL NULL
14 #elif defined(WIN32)
15 #  define HAVE_WIN32_THREADS
16 #  define WIN32_LEAN_AND_MEAN
17 #  include <windows.h>
18 #  define THREAD_RETURN DWORD
19 #  define THREAD_RETURN_VAL 0
20 #endif
21 
22 #include "search.h"
23 #include "common.h"
24 
25 #include "../helper/formats.h"
26 #include "../libgammu/misc/string.h"
27 
28 #if defined(HAVE_WIN32_THREADS) || defined(HAVE_PTHREAD)
29 /**
30  * Structure to hold information about connection for searching.
31  */
32 typedef struct {
33 	/**
34 	 * Connection name.
35 	 */
36 	unsigned char Connection[50];
37 } OneConnectionInfo;
38 
39 /**
40  * Structure to hold device information for phone searching.
41  */
42 typedef struct {
43 	/**
44 	 * Device name
45 	 */
46 	unsigned char Device[50];
47 	/**
48 	 * List of connections to try
49 	 */
50 	OneConnectionInfo Connections[5];
51 } OneDeviceInfo;
52 
53 gboolean SearchOutput;
54 
55 /**
56  * Like printf, but only when output from searching is enabled.
57  */
58 PRINTF_STYLE(1, 2)
SearchPrintf(const char * format,...)59 int SearchPrintf(const char *format, ...)
60 {
61 	va_list ap;
62 	int ret;
63 
64 	if (!SearchOutput)
65 		return 0;
66 
67 	va_start(ap, format);
68 	ret = vprintf(format, ap);
69 	va_end(ap);
70 
71 	return ret;
72 }
73 
SearchPrintPhoneInfo(GSM_StateMachine * sm)74 void SearchPrintPhoneInfo(GSM_StateMachine * sm)
75 {
76 	GSM_Error error;
77 	char buffer[GSM_MAX_INFO_LENGTH];
78 
79 	/* Try to get phone manufacturer */
80 	error = GSM_GetManufacturer(sm, buffer);
81 
82 	/* Bail out if we failed */
83 	if (error != ERR_NONE) {
84 		SearchPrintf("\t%s\n", GSM_ErrorString(error));
85 		return;
86 	}
87 
88 	/* Print basic information */
89 	printf("\t" LISTFORMAT "%s\n", _("Manufacturer"), buffer);
90 
91 	/* Try to get phone model */
92 	error = GSM_GetModel(sm, buffer);
93 
94 	/* Bail out if we failed */
95 	if (error != ERR_NONE) {
96 		SearchPrintf("\t%s\n", GSM_ErrorString(error));
97 		return;
98 	}
99 
100 	/* Print model information */
101 	printf("\t" LISTFORMAT "%s (%s)\n", _("Model"),
102 	       GSM_GetModelInfo(sm)->model, buffer);
103 }
104 
SearchPhoneThread(void * arg)105 THREAD_RETURN SearchPhoneThread(void * arg)
106 {
107 	int j;
108 	OneDeviceInfo *Info = arg;
109 	GSM_Error error;
110 	GSM_StateMachine *search_gsm;
111 	GSM_Config *smcfg;
112 	GSM_Config *globalcfg;
113 
114 	/* Iterate over all connections */
115 	for (j = 0; strlen(Info->Connections[j].Connection) != 0; j++) {
116 
117 		/* Allocate state machine */
118 		search_gsm = GSM_AllocStateMachine();
119 		if (search_gsm == NULL)
120 			return THREAD_RETURN_VAL;
121 
122 		/* Get configuration pointers */
123 		smcfg = GSM_GetConfig(search_gsm, 0);
124 		globalcfg = GSM_GetConfig(gsm, 0);
125 
126 		/* We share some configuration with global one */
127 		smcfg->UseGlobalDebugFile = globalcfg->UseGlobalDebugFile;
128 		smcfg->DebugFile = strdup(globalcfg->DebugFile);
129 		strcpy(smcfg->DebugLevel, globalcfg->DebugLevel);
130 
131 		/* Configure the tested state machine */
132 		smcfg->Device = strdup(Info->Device);
133 		smcfg->Connection = strdup(Info->Connections[j].Connection);
134 		smcfg->SyncTime = FALSE;
135 		smcfg->Model[0] = 0;
136 		smcfg->LockDevice = FALSE;
137 		smcfg->StartInfo = FALSE;
138 
139 		/* We have only one configured connection */
140 		GSM_SetConfigNum(search_gsm, 1);
141 
142 		/* Let's connect */
143 		error = GSM_InitConnection(search_gsm, 1);
144 
145 		printf(_("Connection \"%s\" on device \"%s\"\n"),
146 		       Info->Connections[j].Connection, Info->Device);
147 
148 		/* Did we succeed? Show info */
149 		if (error == ERR_NONE) {
150 			SearchPrintPhoneInfo(search_gsm);
151 		} else {
152 			SearchPrintf("\t%s\n", GSM_ErrorString(error));
153 		}
154 
155 		if (error != ERR_DEVICEOPENERROR) {
156 			GSM_TerminateConnection(search_gsm);
157 		}
158 
159 		if (error == ERR_DEVICEOPENERROR)
160 			break;
161 
162 		/* Free allocated buffer */
163 		GSM_FreeStateMachine(search_gsm);
164 	}
165 	return THREAD_RETURN_VAL;
166 }
167 
168 #ifdef HAVE_PTHREAD
169 pthread_t Threads[100];
170 #else
171 HANDLE Threads[100];
172 #endif
173 
174 OneDeviceInfo SearchDevices[60];
175 
MakeSearchThread(int i)176 void MakeSearchThread(int i)
177 {
178 #ifdef HAVE_PTHREAD
179 	if (pthread_create
180 	    (&Threads[i], NULL, SearchPhoneThread,
181 	     &SearchDevices[i]) != 0) {
182 		fprintf(stderr, "%s", _("Error creating thread\n"));
183 	}
184 #else
185 	Threads[i] = CreateThread((LPSECURITY_ATTRIBUTES) NULL, 0,
186 			 (LPTHREAD_START_ROUTINE) SearchPhoneThread,
187 			 &SearchDevices[i], 0, NULL);
188 	if (Threads[i] 	== NULL) {
189 		fprintf(stderr, "%s", _("Error creating thread\n"));
190 	}
191 #endif
192 }
193 
SearchPhone(int argc,char * argv[])194 void SearchPhone(int argc, char *argv[])
195 {
196 	int i, dev = 0;
197 #ifdef HAVE_PTHREAD
198 	int fd;
199 	void *ret;
200 #endif
201 
202 
203 	SearchOutput = FALSE;
204 	if (argc == 3 && strcasecmp(argv[2], "-debug") == 0)
205 		SearchOutput = TRUE;
206 
207 #ifdef HAVE_WIN32_THREADS
208 	SearchDevices[dev].Device[0] = 0;
209 	sprintf(SearchDevices[dev].Connections[0].Connection, "irdaphonet");
210 	sprintf(SearchDevices[dev].Connections[1].Connection, "irdaat");
211 	SearchDevices[dev].Connections[2].Connection[0] = 0;
212 	dev++;
213 	for (i = 0; i < 20; i++) {
214 		sprintf(SearchDevices[dev].Device, "com%i:", i + 1);
215 		sprintf(SearchDevices[dev].Connections[0].Connection,
216 			"fbusdlr3");
217 		sprintf(SearchDevices[dev].Connections[1].Connection, "fbus");
218 		sprintf(SearchDevices[dev].Connections[2].Connection,
219 			"at19200");
220 		sprintf(SearchDevices[dev].Connections[3].Connection, "mbus");
221 		SearchDevices[dev].Connections[4].Connection[0] = 0;
222 		dev++;
223 	}
224 #else
225 	for (i = 0; i < 6; i++) {
226 		sprintf(SearchDevices[dev].Device, "/dev/ircomm%i", i);
227 		fd = open(SearchDevices[dev].Device, O_RDWR);
228 		if (fd < 0) continue;
229 		close(fd);
230 		sprintf(SearchDevices[dev].Connections[0].Connection,
231 			"irdaphonet");
232 		sprintf(SearchDevices[dev].Connections[1].Connection,
233 			"at19200");
234 		SearchDevices[dev].Connections[2].Connection[0] = 0;
235 		dev++;
236 	}
237 	for (i = 0; i < 10; i++) {
238 		sprintf(SearchDevices[dev].Device, "/dev/ttyS%i", i);
239 		fd = open(SearchDevices[dev].Device, O_RDWR);
240 		if (fd < 0) continue;
241 		close(fd);
242 		sprintf(SearchDevices[dev].Connections[0].Connection,
243 			"fbusdlr3");
244 		sprintf(SearchDevices[dev].Connections[1].Connection, "fbus");
245 		sprintf(SearchDevices[dev].Connections[2].Connection,
246 			"at19200");
247 		sprintf(SearchDevices[dev].Connections[3].Connection, "mbus");
248 		SearchDevices[dev].Connections[4].Connection[0] = 0;
249 		dev++;
250 	}
251 	for (i = 0; i < 8; i++) {
252 		sprintf(SearchDevices[dev].Device, "/dev/ttyD00%i", i);
253 		fd = open(SearchDevices[dev].Device, O_RDWR);
254 		if (fd < 0) continue;
255 		close(fd);
256 		sprintf(SearchDevices[dev].Connections[0].Connection,
257 			"fbusdlr3");
258 		sprintf(SearchDevices[dev].Connections[1].Connection, "fbus");
259 		sprintf(SearchDevices[dev].Connections[2].Connection,
260 			"at19200");
261 		sprintf(SearchDevices[dev].Connections[3].Connection, "mbus");
262 		SearchDevices[dev].Connections[4].Connection[0] = 0;
263 		dev++;
264 	}
265 	for (i = 0; i < 4; i++) {
266 		sprintf(SearchDevices[dev].Device, "/dev/usb/tts/%i", i);
267 		fd = open(SearchDevices[dev].Device, O_RDWR);
268 		if (fd < 0) continue;
269 		close(fd);
270 		sprintf(SearchDevices[dev].Connections[0].Connection,
271 			"fbusdlr3");
272 		sprintf(SearchDevices[dev].Connections[1].Connection, "fbus");
273 		sprintf(SearchDevices[dev].Connections[2].Connection,
274 			"at19200");
275 		sprintf(SearchDevices[dev].Connections[3].Connection, "mbus");
276 		SearchDevices[dev].Connections[4].Connection[0] = 0;
277 		dev++;
278 	}
279 #endif
280 	for (i = 0; i < dev; i++)
281 		MakeSearchThread(i);
282 #ifdef HAVE_WIN32_THREADS
283 	WaitForMultipleObjects(dev, Threads, TRUE, INFINITE);
284 #else
285 	for (i = 0; i < dev; i++)
286 		pthread_join(Threads[i], &ret);
287 #endif
288 }
289 #endif				/*Support for threads */
290 
291 /* How should editor hadle tabs in this file? Add editor commands here.
292  * vim: noexpandtab sw=8 ts=8 sts=8:
293  */
294