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