Found in "gnokii-working" directory, some November-patches version
[gnokii.git] / common / devices / unixirda.c
1 /*
2  * $Id$
3  *
4  *
5  * G N O K I I
6  *
7  * A Linux/Unix toolset and driver for Nokia mobile phones.
8  *
9  * Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml.
10  * Copyright (C) 2000-2001  Marcel Holtmann <marcel@holtmann.org>
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Library General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with this library; if not, write to the Free
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25  *
26  * $Log$
27  * Revision 1.1.1.3  2002/04/03 00:08:06  short
28  * Found in "gnokii-working" directory, some November-patches version
29  *
30  * Revision 1.7  2001/11/08 16:49:19  pkot
31  * Cleanups
32  *
33  * Revision 1.6  2001/08/17 00:18:12  pkot
34  * Removed recv() from IrDA initializing procedure (many people)
35  *
36  * Revision 1.5  2001/06/27 23:52:48  pkot
37  * 7110/6210 updates (Marian Jancar)
38  *
39  * Revision 1.4  2001/06/20 21:27:34  pkot
40  * IrDA patch (Marian Jancar)
41  *
42  * Revision 1.3  2001/02/21 19:57:04  chris
43  * More fiddling with the directory layout
44  *
45  * Revision 1.2  2001/02/20 21:55:10  pkot
46  * Small #include updates
47  *
48  * Revision 1.1  2001/02/16 14:29:52  chris
49  * Restructure of common/.  Fixed a problem in fbus-phonet.c
50  * Lots of dprintfs for Marcin
51  * Any size xpm can now be loaded (eg for 7110 startup logos)
52  * nk7110 code detects 7110/6210 and alters startup logo size to suit
53  * Moved Marcin's extended phonebook code into gnokii.c
54  *
55  * Revision 1.2  2001/02/06 21:15:35  chris
56  * Preliminary irda support for 7110 etc.  Not well tested!
57  *
58  * Revision 1.1  2001/02/03 23:56:17  chris
59  * Start of work on irda support (now we just need fbus-irda.c!)
60  * Proper unicode support in 7110 code (from pkot)
61  *
62  */
63
64 #include "devices/unixirda.h"
65
66 #ifndef AF_IRDA
67 #define AF_IRDA 23
68 #endif
69
70 #define INFO_LEN                22
71 #define DISCOVERY_TIMEOUT       60.0
72 #define DISCOVERY_SLEEP         0.4
73
74 static char *phone[] = {
75         "Nokia 7110", "Nokia 6210"
76 };
77
78 double d_time(void)
79 {
80         double          time;
81         struct timeval  tv;
82         
83         gettimeofday(&tv, NULL);
84         
85         time = tv.tv_sec + (((double)tv.tv_usec) / 1000000.0);
86         
87         return time;
88 }
89
90 double d_sleep(double s)
91 {
92         double          time;
93         struct timeval  tv1, tv2;
94         
95         gettimeofday(&tv1, NULL);
96         usleep(s * 1000000);
97         gettimeofday(&tv2, NULL);
98         
99         time = tv2.tv_sec - tv1.tv_sec + (((double)(tv2.tv_usec - tv1.tv_usec)) / 1000000.0);
100         
101         return time;
102 }
103
104 static int irda_discover_device(void)
105 {
106
107         struct irda_device_list *list;
108         struct irda_device_info *dev;
109         unsigned char           *buf;
110         int                     s, len, i, j, daddr = -1, fd;
111         double                  t1, t2;
112         int phones = sizeof(phone) / sizeof(*phone);
113         
114         fd = socket(AF_IRDA, SOCK_STREAM, 0);
115         
116         len = sizeof(*list) + sizeof(*dev) * 10;        // 10 = max devices in discover
117         buf = malloc(len);
118         list = (struct irda_device_list *)buf;
119         dev = list->dev;
120         
121         t1 = d_time();
122         
123         do {
124                 s = len;
125                 memset(buf, 0, s);
126                 
127                 if (getsockopt(fd, SOL_IRLMP, IRLMP_ENUMDEVICES, buf, &s) == 0) {
128                         for (i = 0; (i < list->len) && (daddr == -1); i++) {
129                                 for (j = 0; (j < phones) && (daddr == -1); j++) {
130                                         if (strncmp(dev[i].info, phone[j], INFO_LEN) == 0) {
131                                                 daddr = dev[i].daddr;
132                                                 dprintf("%s\t%x\n", dev[i].info, dev[i].daddr);
133                                         }
134                                 }
135                                 if (daddr == -1) {
136                                         dprintf("unknown: %s\t%x\n", dev[i].info, dev[i].daddr);
137                                 }
138                         }
139                 }
140                 
141                 if (daddr == -1) {
142                         d_sleep(DISCOVERY_SLEEP);
143                 }
144                 
145                 t2 = d_time();
146                 
147         } while ((t2 - t1 < DISCOVERY_TIMEOUT) && (daddr == -1));
148         
149         free(buf);
150         close(fd);
151         
152         return daddr;
153 }
154
155 int irda_open(void)
156 {
157         struct sockaddr_irda    peer;
158         int                     fd = -1, daddr;
159         
160         daddr = irda_discover_device();                 /* discover the devices */
161         
162         if (daddr != -1)  {
163                 fd = socket(AF_IRDA, SOCK_STREAM, 0);   /* Create socket */
164                 peer.sir_family = AF_IRDA;
165                 peer.sir_lsap_sel = LSAP_ANY;
166                 peer.sir_addr = daddr;
167                 strcpy(peer.sir_name, "Nokia:PhoNet");
168                 
169                 if (connect(fd, (struct sockaddr *)&peer, sizeof(peer))) {      /* Connect to service "Nokia:PhoNet" */
170                         perror("connect");
171                         close(fd);
172                         fd = -1;
173 /*              } else { FIXME: It does not work in most cases. Why? Or why it should work?
174                         recv(fd, NULL, 0, 0);            call recv first to make select work correctly */
175                 }
176         }
177         
178         return fd;
179 }
180
181 int irda_close(int fd)
182 {
183         shutdown(fd, 0);
184         return close(fd);
185 }
186
187 int irda_write(int __fd, __const __ptr_t __bytes, int __size)
188 {
189         return (send(__fd, __bytes, __size, 0));
190 }
191
192 int irda_read(int __fd, __ptr_t __bytes, int __size)
193 {
194         return (recv(__fd, __bytes, __size, 0));
195 }
196
197 int irda_select(int fd, struct timeval *timeout)
198 {
199         fd_set readfds;
200
201         FD_ZERO(&readfds);
202         FD_SET(fd, &readfds);
203
204         return (select(fd + 1, &readfds, NULL, NULL, timeout));
205 }