1 /* $Id$ */
2 /* Copyright (c) 2015 Pierre Pronchery <khorben@defora.org> */
3 /* This file is part of DeforaOS Desktop Phone */
4 /* This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, version 3 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16
17
18 #include <stdlib.h>
19 #ifdef DEBUG
20 # include <stdio.h>
21 #endif
22 #include <string.h>
23 #include "command.h"
24 #include "common.h"
25 #include "channel.h"
26
27
28 /* HayesChannel */
29 /* public */
30 /* functions */
31 /* hayeschannel_init */
hayeschannel_init(HayesChannel * channel,ModemPlugin * modem)32 void hayeschannel_init(HayesChannel * channel, ModemPlugin * modem)
33 {
34 size_t i;
35
36 channel->hayes = modem;
37 channel->mode = HAYESCHANNEL_MODE_INIT;
38 for(i = 0; i < sizeof(channel->events) / sizeof(*channel->events); i++)
39 channel->events[i].type = i;
40 channel->events[MODEM_EVENT_TYPE_REGISTRATION].registration.signal
41 = 0.0 / 0.0;
42 }
43
44
45 /* hayeschannel_destroy */
hayeschannel_destroy(HayesChannel * channel)46 void hayeschannel_destroy(HayesChannel * channel)
47 {
48 (void) channel;
49 }
50
51
52 /* accessors */
53 /* hayeschannel_has_quirks */
hayeschannel_has_quirks(HayesChannel * channel,unsigned int quirks)54 int hayeschannel_has_quirks(HayesChannel * channel, unsigned int quirks)
55 {
56 return ((channel->quirks & quirks) == quirks) ? 1 : 0;
57 }
58
59
60 /* hayeschannel_is_started */
hayeschannel_is_started(HayesChannel * channel)61 int hayeschannel_is_started(HayesChannel * channel)
62 {
63 return (channel->channel != NULL) ? 1 : 0;
64 }
65
66
67 /* hayeschannel_set_quirks */
hayeschannel_set_quirks(HayesChannel * channel,unsigned int quirks)68 void hayeschannel_set_quirks(HayesChannel * channel, unsigned int quirks)
69 {
70 channel->quirks = quirks;
71 }
72
73
74 /* useful */
75 /* queue management */
76 /* hayeschannel_queue_data */
hayeschannel_queue_data(HayesChannel * channel,char const * buf,size_t size)77 int hayeschannel_queue_data(HayesChannel * channel, char const * buf,
78 size_t size)
79 {
80 char * p;
81
82 if((p = realloc(channel->wr_buf, channel->wr_buf_cnt + size)) == NULL)
83 return -1;
84 channel->wr_buf = p;
85 memcpy(&channel->wr_buf[channel->wr_buf_cnt], buf, size);
86 channel->wr_buf_cnt += size;
87 return 0;
88 }
89
90
91 /* hayeschannel_queue_flush */
hayeschannel_queue_flush(HayesChannel * channel)92 void hayeschannel_queue_flush(HayesChannel * channel)
93 {
94 g_slist_foreach(channel->queue_timeout, (GFunc)hayes_command_delete,
95 NULL);
96 g_slist_free(channel->queue_timeout);
97 channel->queue_timeout = NULL;
98 g_slist_foreach(channel->queue, (GFunc)hayes_command_delete, NULL);
99 g_slist_free(channel->queue);
100 channel->queue = NULL;
101 free(channel->rd_buf);
102 channel->rd_buf = NULL;
103 channel->rd_buf_cnt = 0;
104 hayescommon_source_reset(&channel->rd_source);
105 free(channel->wr_buf);
106 channel->wr_buf = NULL;
107 channel->wr_buf_cnt = 0;
108 hayescommon_source_reset(&channel->wr_source);
109 hayescommon_source_reset(&channel->rd_ppp_source);
110 hayescommon_source_reset(&channel->wr_ppp_source);
111 channel->authenticate_count = 0;
112 hayescommon_source_reset(&channel->authenticate_source);
113 hayescommon_source_reset(&channel->timeout);
114 }
115
116
117 /* hayeschannel_queue_pop */
hayeschannel_queue_pop(HayesChannel * channel)118 int hayeschannel_queue_pop(HayesChannel * channel)
119 {
120 HayesCommand * command;
121
122 #ifdef DEBUG
123 fprintf(stderr, "DEBUG: %s()\n", __func__);
124 #endif
125 hayescommon_source_reset(&channel->timeout);
126 if(channel->queue == NULL) /* nothing to send */
127 return 0;
128 command = channel->queue->data; /* XXX assumes it's valid */
129 hayes_command_delete(command);
130 channel->queue = g_slist_remove(channel->queue, command);
131 return 0;
132 }
133
134
135 /* hayeschannel_stop */
136 static void _stop_giochannel(GIOChannel * channel);
137 static void _stop_string(char ** string);
138
hayeschannel_stop(HayesChannel * channel)139 void hayeschannel_stop(HayesChannel * channel)
140 {
141 size_t i;
142
143 /* close everything opened */
144 if(channel->fp != NULL)
145 fclose(channel->fp);
146 channel->fp = NULL;
147 hayeschannel_queue_flush(channel);
148 _stop_giochannel(channel->channel);
149 channel->channel = NULL;
150 _stop_giochannel(channel->rd_ppp_channel);
151 channel->rd_ppp_channel = NULL;
152 _stop_giochannel(channel->wr_ppp_channel);
153 channel->wr_ppp_channel = NULL;
154 /* remove internal data */
155 _stop_string(&channel->authentication_name);
156 _stop_string(&channel->authentication_error);
157 _stop_string(&channel->call_number);
158 _stop_string(&channel->contact_name);
159 _stop_string(&channel->contact_number);
160 _stop_string(&channel->gprs_username);
161 _stop_string(&channel->gprs_password);
162 _stop_string(&channel->message_number);
163 _stop_string(&channel->model_identity);
164 _stop_string(&channel->model_name);
165 _stop_string(&channel->model_serial);
166 _stop_string(&channel->model_vendor);
167 _stop_string(&channel->model_version);
168 _stop_string(&channel->registration_media);
169 _stop_string(&channel->registration_operator);
170 /* reset events */
171 memset(&channel->events, 0, sizeof(channel->events));
172 for(i = 0; i < sizeof(channel->events) / sizeof(*channel->events); i++)
173 channel->events[i].type = i;
174 /* reset mode */
175 channel->mode = HAYESCHANNEL_MODE_INIT;
176 }
177
_stop_giochannel(GIOChannel * channel)178 static void _stop_giochannel(GIOChannel * channel)
179 {
180 GError * error = NULL;
181
182 if(channel == NULL)
183 return;
184 /* XXX should the file descriptor also be closed? */
185 if(g_io_channel_shutdown(channel, TRUE, &error) == G_IO_STATUS_ERROR)
186 /* XXX report error */
187 g_error_free(error);
188 g_io_channel_unref(channel);
189 }
190
_stop_string(char ** string)191 static void _stop_string(char ** string)
192 {
193 free(*string);
194 *string = NULL;
195 }
196