Add more HSO implementation details
[connman] / plugins / hso.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2008  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <errno.h>
28 #include <string.h>
29
30 #include <glib.h>
31
32 #define CONNMAN_API_SUBJECT_TO_CHANGE
33 #include <connman/plugin.h>
34 #include <connman/device.h>
35 #include <connman/resolver.h>
36 #include <connman/log.h>
37
38 #include "modem.h"
39
40 struct hso_data {
41         int index;
42         GIOChannel *channel;
43         struct modem_data *modem;
44 };
45
46 static void owandata_callback(const char *buf, void *user_data)
47 {
48         //struct hso_data *data = user_data;
49         char *str, ip[16], nm[16], ns1[16], ns2[16], ns3[16], ns4[16], val[20];
50         int err, num;
51
52         str = g_strrstr(buf, "_OWANDATA");
53         if (str == NULL || strstr(buf, "ERROR") != NULL)
54                 return;
55
56         err = sscanf(str, "_OWANDATA: %d, %[^,], %[^,], "
57                                         "%[^,], %[^,], %[^,], %[^,], %s",
58                                 &num, ip, nm, ns1, ns2, ns3, ns4, val);
59
60         if (err != 8) {
61                 DBG("parsed %d arguments", err);
62                 return;
63         }
64
65         DBG("ip %s dns %s %s val %s", ip, ns1, ns2, val);
66
67         //connman_resolver_append(data->iface, NULL, ns1);
68         //connman_resolver_append(data->iface, NULL, ns2);
69 }
70
71 static void owancall_callback(const char *buf, void *user_data)
72 {
73         struct hso_data *data = user_data;
74
75         DBG("");
76
77         if (g_strrstr(buf, "_OWANCALL: 1, 3") != NULL) {
78                 DBG("%s", buf);
79                 //modem_command(modem, owancall_callback, data,
80                 //                      "_OWANCALL", "%d,%d,%d", 1, 1, 1);
81         }
82
83         if (g_strrstr(buf, "_OWANCALL: 1, 1") != NULL) {
84                 DBG("%s", buf);
85                 modem_command(data->modem, owandata_callback, data,
86                                                 "_OWANDATA", "%d", 1);
87         }
88
89         if (g_strrstr(buf, "\r\nOK\r\n") != NULL) {
90                 modem_command(data->modem, owandata_callback, data,
91                                                 "_OWANDATA", "%d", 1);
92         }
93 }
94
95 static int network_probe(struct connman_network *network)
96 {
97         DBG("network %p", network);
98
99         return 0;
100 }
101
102 static void network_remove(struct connman_network *network)
103 {
104         DBG("network %p", network);
105 }
106
107 static int network_connect(struct connman_network *network)
108 {
109         DBG("network %p", network);
110
111         return 0;
112 }
113
114 static int network_disconnect(struct connman_network *network)
115 {
116         DBG("network %p", network);
117
118         return 0;
119 }
120
121 static struct connman_network_driver network_driver = {
122         .name           = "hso-network",
123         .type           = CONNMAN_NETWORK_TYPE_HSO,
124         .probe          = network_probe,
125         .remove         = network_remove,
126         .connect        = network_connect,
127         .disconnect     = network_disconnect,
128 };
129
130 static int hso_probe(struct connman_device *device)
131 {
132         struct hso_data *data;
133
134         DBG("device %p", device);
135
136         data = g_try_new0(struct hso_data, 1);
137         if (data == NULL)
138                 return -ENOMEM;
139
140         data->index = connman_device_get_index(device);
141
142         data->modem = modem_create("/dev/ttyHS0");
143         if (data->modem == NULL) {
144                 g_free(data);
145                 return -EIO;
146         }
147
148         connman_device_set_data(device, data);
149
150         modem_add_callback(data->modem, "_OWANCALL",
151                                                 owancall_callback, data);
152
153         return 0;
154 }
155
156 static void hso_remove(struct connman_device *device)
157 {
158         struct hso_data *data = connman_device_get_data(device);
159
160         DBG("device %p", device);
161
162         connman_device_set_data(device, NULL);
163
164         modem_destroy(data->modem);
165
166         g_free(data);
167 }
168
169 static int hso_enable(struct connman_device *device)
170 {
171         struct hso_data *data = connman_device_get_data(device);
172         struct connman_network *network;
173         int err;
174
175         DBG("device %p", device);
176
177         err = modem_open(data->modem);
178         if (err < 0)
179                 return err;
180
181         connman_device_set_powered(device, TRUE);
182
183         modem_command(data->modem, NULL, NULL, "Z", NULL);
184         modem_command(data->modem, NULL, NULL, "I", NULL);
185
186         modem_command(data->modem, owancall_callback, data,
187                                         "_OWANCALL", "%d,%d,%d", 1, 1, 1);
188
189         network = connman_network_create("internet", CONNMAN_NETWORK_TYPE_HSO);
190         connman_device_add_network(device, network);
191
192         return 0;
193 }
194
195 static int hso_disable(struct connman_device *device)
196 {
197         struct hso_data *data = connman_device_get_data(device);
198         //const char *iface = connman_device_get_interface(device);
199
200         DBG("device %p", device);
201
202         //connman_resolver_remove_all(iface);
203
204         modem_command(data->modem, owancall_callback, data,
205                                         "_OWANCALL", "%d,%d,%d", 1, 0, 0);
206
207         connman_device_set_powered(device, FALSE);
208
209         modem_close(data->modem);
210
211         g_io_channel_shutdown(data->channel, TRUE, NULL);
212         g_io_channel_unref(data->channel);
213
214         return 0;
215 }
216
217 static struct connman_device_driver hso_driver = {
218         .name           = "hso-device",
219         .type           = CONNMAN_DEVICE_TYPE_HSO,
220         .probe          = hso_probe,
221         .remove         = hso_remove,
222         .enable         = hso_enable,
223         .disable        = hso_disable,
224 };
225
226 static int hso_init(void)
227 {
228         int err;
229
230         err = connman_network_driver_register(&network_driver);
231         if (err < 0)
232                 return err;
233
234         err = connman_device_driver_register(&hso_driver);
235         if (err < 0) {
236                 connman_network_driver_unregister(&network_driver);
237                 return err;
238         }
239
240         return 0;
241 }
242
243 static void hso_exit(void)
244 {
245         connman_device_driver_unregister(&hso_driver);
246         connman_network_driver_register(&network_driver);
247 }
248
249 CONNMAN_PLUGIN_DEFINE(hso, "Option HSO device plugin", VERSION,
250                                                 hso_init, hso_exit)