1 /*
2     en50221 encoder An implementation for libdvb
3     an implementation for the en50221 transport layer
4 
5     Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
6     Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
7     Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
8 
9     This library is free software; you can redistribute it and/or modify
10     it under the terms of the GNU Lesser General Public License as
11     published by the Free Software Foundation; either version 2.1 of
12     the License, or (at your option) any later version.
13 
14     This program is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU Lesser General Public License for more details.
18 
19     You should have received a copy of the GNU Lesser General Public
20     License along with this library; if not, write to the Free Software
21     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
22 */
23 
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <pthread.h>
28 #include <fcntl.h>
29 #include <sys/ioctl.h>
30 #include <sys/poll.h>
31 #include <time.h>
32 #include <libdvbmisc/dvbmisc.h>
33 #include <libdvbapi/dvbca.h>
34 #include "en50221_errno.h"
35 #include "en50221_transport.h"
36 #include "asn_1.h"
37 
38 // these are the Transport Tags, like
39 // described in EN50221, Annex A.4.1.13 (pg70)
40 #define T_SB                0x80	// sb                           primitive   h<--m
41 #define T_RCV               0x81	// receive                      primitive   h-->m
42 #define T_CREATE_T_C        0x82	// create transport connection  primitive   h-->m
43 #define T_C_T_C_REPLY       0x83	// ctc reply                    primitive   h<--m
44 #define T_DELETE_T_C        0x84	// delete tc                    primitive   h<->m
45 #define T_D_T_C_REPLY       0x85	// dtc reply                    primitive   h<->m
46 #define T_REQUEST_T_C       0x86	// request transport connection primitive   h<--m
47 #define T_NEW_T_C           0x87	// new tc / reply to t_request  primitive   h-->m
48 #define T_T_C_ERROR         0x77	// error creating tc            primitive   h-->m
49 #define T_DATA_LAST         0xA0	// convey data from higher      constructed h<->m
50 				 // layers
51 #define T_DATA_MORE         0xA1	// convey data from higher      constructed h<->m
52 				 // layers
53 
54 struct en50221_message {
55 	struct en50221_message *next;
56 	uint32_t length;
57 	uint8_t data[0];
58 };
59 
60 struct en50221_connection {
61 	uint32_t state;		// the current state: idle/in_delete/in_create/active
62 	struct timeval tx_time;	// time last request was sent from host->module, or 0 if ok
63 	struct timeval last_poll_time;	// time of last poll transmission
64 	uint8_t *chain_buffer;	// used to save parts of chained packets
65 	uint32_t buffer_length;
66 
67 	struct en50221_message *send_queue;
68 	struct en50221_message *send_queue_tail;
69 };
70 
71 struct en50221_slot {
72 	int ca_hndl;
73 	uint8_t slot;		// CAM slot
74 	struct en50221_connection *connections;
75 
76 	pthread_mutex_t slot_lock;
77 
78 	uint32_t response_timeout;
79 	uint32_t poll_delay;
80 };
81 
82 struct en50221_transport_layer {
83 	uint8_t max_slots;
84 	uint8_t max_connections_per_slot;
85 	struct en50221_slot *slots;
86 	struct pollfd *slot_pollfds;
87 	int slots_changed;
88 
89 	pthread_mutex_t global_lock;
90 	pthread_mutex_t setcallback_lock;
91 
92 	int error;
93 	int error_slot;
94 
95 	en50221_tl_callback callback;
96 	void *callback_arg;
97 };
98 
99 static int en50221_tl_process_data(struct en50221_transport_layer *tl,
100 				   uint8_t slot_id, uint8_t * data,
101 				   uint32_t data_length);
102 static int en50221_tl_poll_tc(struct en50221_transport_layer *tl,
103 			      uint8_t slot_id, uint8_t connection_id);
104 static int en50221_tl_alloc_new_tc(struct en50221_transport_layer *tl,
105 				   uint8_t slot_id);
106 static void queue_message(struct en50221_transport_layer *tl,
107 			  uint8_t slot_id, uint8_t connection_id,
108 			  struct en50221_message *msg);
109 static int en50221_tl_handle_create_tc_reply(struct en50221_transport_layer
110 					     *tl, uint8_t slot_id,
111 					     uint8_t connection_id);
112 static int en50221_tl_handle_delete_tc(struct en50221_transport_layer *tl,
113 				       uint8_t slot_id,
114 				       uint8_t connection_id);
115 static int en50221_tl_handle_delete_tc_reply(struct en50221_transport_layer
116 					     *tl, uint8_t slot_id,
117 					     uint8_t connection_id);
118 static int en50221_tl_handle_request_tc(struct en50221_transport_layer *tl,
119 					uint8_t slot_id,
120 					uint8_t connection_id);
121 static int en50221_tl_handle_data_more(struct en50221_transport_layer *tl,
122 				       uint8_t slot_id,
123 				       uint8_t connection_id,
124 				       uint8_t * data,
125 				       uint32_t data_length);
126 static int en50221_tl_handle_data_last(struct en50221_transport_layer *tl,
127 				       uint8_t slot_id,
128 				       uint8_t connection_id,
129 				       uint8_t * data,
130 				       uint32_t data_length);
131 static int en50221_tl_handle_sb(struct en50221_transport_layer *tl,
132 				uint8_t slot_id, uint8_t connection_id,
133 				uint8_t * data, uint32_t data_length);
134 
135 
en50221_tl_create(uint8_t max_slots,uint8_t max_connections_per_slot)136 struct en50221_transport_layer *en50221_tl_create(uint8_t max_slots,
137 						  uint8_t
138 						  max_connections_per_slot)
139 {
140 	struct en50221_transport_layer *tl = NULL;
141 	int i;
142 	int j;
143 
144 	// setup structure
145 	tl = (struct en50221_transport_layer *)
146 		malloc(sizeof(struct en50221_transport_layer));
147 	if (tl == NULL)
148 		goto error_exit;
149 	tl->max_slots = max_slots;
150 	tl->max_connections_per_slot = max_connections_per_slot;
151 	tl->slots = NULL;
152 	tl->slot_pollfds = NULL;
153 	tl->slots_changed = 1;
154 	tl->callback = NULL;
155 	tl->callback_arg = NULL;
156 	tl->error_slot = 0;
157 	tl->error = 0;
158 	pthread_mutex_init(&tl->global_lock, NULL);
159 	pthread_mutex_init(&tl->setcallback_lock, NULL);
160 
161 	// create the slots
162 	tl->slots = malloc(sizeof(struct en50221_slot) * max_slots);
163 	if (tl->slots == NULL)
164 		goto error_exit;
165 
166 	// set them up
167 	for (i = 0; i < max_slots; i++) {
168 		tl->slots[i].ca_hndl = -1;
169 
170 		// create the connections for this slot
171 		tl->slots[i].connections =
172 		    malloc(sizeof(struct en50221_connection) * max_connections_per_slot);
173 		if (tl->slots[i].connections == NULL)
174 			goto error_exit;
175 
176 		// create a mutex for the slot
177 		pthread_mutex_init(&tl->slots[i].slot_lock, NULL);
178 
179 		// set them up
180 		for (j = 0; j < max_connections_per_slot; j++) {
181 			tl->slots[i].connections[j].state = T_STATE_IDLE;
182 			tl->slots[i].connections[j].tx_time.tv_sec = 0;
183 			tl->slots[i].connections[j].last_poll_time.tv_sec = 0;
184 			tl->slots[i].connections[j].last_poll_time.tv_usec = 0;
185 			tl->slots[i].connections[j].chain_buffer = NULL;
186 			tl->slots[i].connections[j].buffer_length = 0;
187 			tl->slots[i].connections[j].send_queue = NULL;
188 			tl->slots[i].connections[j].send_queue_tail = NULL;
189 		}
190 	}
191 
192 	// create the pollfds
193 	tl->slot_pollfds = malloc(sizeof(struct pollfd) * max_slots);
194 	if (tl->slot_pollfds == NULL) {
195 		goto error_exit;
196 	}
197 	memset(tl->slot_pollfds, 0, sizeof(struct pollfd) * max_slots);
198 
199 	return tl;
200 
201       error_exit:
202 	en50221_tl_destroy(tl);
203 	return NULL;
204 }
205 
206 // Destroy an instance of the transport layer
en50221_tl_destroy(struct en50221_transport_layer * tl)207 void en50221_tl_destroy(struct en50221_transport_layer *tl)
208 {
209 	int i, j;
210 
211 	if (tl) {
212 		if (tl->slots) {
213 			for (i = 0; i < tl->max_slots; i++) {
214 				if (tl->slots[i].connections) {
215 					for (j = 0; j < tl->max_connections_per_slot; j++) {
216 						if (tl->slots[i].connections[j].chain_buffer) {
217 							free(tl->slots[i].connections[j].chain_buffer);
218 						}
219 
220 						struct en50221_message *cur_msg =
221 							tl->slots[i].connections[j].send_queue;
222 						while (cur_msg) {
223 							struct en50221_message *next_msg = cur_msg->next;
224 							free(cur_msg);
225 							cur_msg = next_msg;
226 						}
227 						tl->slots[i].connections[j].send_queue = NULL;
228 						tl->slots[i].connections[j].send_queue_tail = NULL;
229 					}
230 					free(tl->slots[i].connections);
231 					pthread_mutex_destroy(&tl->slots[i].slot_lock);
232 				}
233 			}
234 			free(tl->slots);
235 		}
236 		if (tl->slot_pollfds) {
237 			free(tl->slot_pollfds);
238 		}
239 		pthread_mutex_destroy(&tl->setcallback_lock);
240 		pthread_mutex_destroy(&tl->global_lock);
241 		free(tl);
242 	}
243 }
244 
245 // this can be called from the user-space app to
246 // register new slots that we should work with
en50221_tl_register_slot(struct en50221_transport_layer * tl,int ca_hndl,uint8_t slot,uint32_t response_timeout,uint32_t poll_delay)247 int en50221_tl_register_slot(struct en50221_transport_layer *tl,
248 			     int ca_hndl, uint8_t slot,
249 			     uint32_t response_timeout,
250 			     uint32_t poll_delay)
251 {
252 	// lock
253 	pthread_mutex_lock(&tl->global_lock);
254 
255 	// we browse through the array of slots
256 	// to look for the first unused one
257 	int i;
258 	int16_t slot_id = -1;
259 	for (i = 0; i < tl->max_slots; i++) {
260 		if (tl->slots[i].ca_hndl == -1) {
261 			slot_id = i;
262 			break;
263 		}
264 	}
265 	if (slot_id == -1) {
266 		tl->error = EN50221ERR_OUTOFSLOTS;
267 		pthread_mutex_unlock(&tl->global_lock);
268 		return -1;
269 	}
270 	// set up the slot struct
271 	pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
272 	tl->slots[slot_id].ca_hndl = ca_hndl;
273 	tl->slots[slot_id].slot = slot;
274 	tl->slots[slot_id].response_timeout = response_timeout;
275 	tl->slots[slot_id].poll_delay = poll_delay;
276 	pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
277 
278 	tl->slots_changed = 1;
279 	pthread_mutex_unlock(&tl->global_lock);
280 	return slot_id;
281 }
282 
en50221_tl_destroy_slot(struct en50221_transport_layer * tl,uint8_t slot_id)283 void en50221_tl_destroy_slot(struct en50221_transport_layer *tl,
284 			     uint8_t slot_id)
285 {
286 	int i;
287 
288 	if (slot_id >= tl->max_slots)
289 		return;
290 
291 	// lock
292 	pthread_mutex_lock(&tl->global_lock);
293 
294 	// clear the slot
295 	pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
296 	tl->slots[slot_id].ca_hndl = -1;
297 	for (i = 0; i < tl->max_connections_per_slot; i++) {
298 		tl->slots[slot_id].connections[i].state = T_STATE_IDLE;
299 		tl->slots[slot_id].connections[i].tx_time.tv_sec = 0;
300 		tl->slots[slot_id].connections[i].last_poll_time.tv_sec = 0;
301 		tl->slots[slot_id].connections[i].last_poll_time.tv_usec = 0;
302 		if (tl->slots[slot_id].connections[i].chain_buffer) {
303 			free(tl->slots[slot_id].connections[i].
304 			     chain_buffer);
305 		}
306 		tl->slots[slot_id].connections[i].chain_buffer = NULL;
307 		tl->slots[slot_id].connections[i].buffer_length = 0;
308 
309 		struct en50221_message *cur_msg =
310 		    tl->slots[slot_id].connections[i].send_queue;
311 		while (cur_msg) {
312 			struct en50221_message *next_msg = cur_msg->next;
313 			free(cur_msg);
314 			cur_msg = next_msg;
315 		}
316 		tl->slots[slot_id].connections[i].send_queue = NULL;
317 		tl->slots[slot_id].connections[i].send_queue_tail = NULL;
318 	}
319 	pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
320 
321 	// tell upper layers
322 	pthread_mutex_lock(&tl->setcallback_lock);
323 	en50221_tl_callback cb = tl->callback;
324 	void *cb_arg = tl->callback_arg;
325 	pthread_mutex_unlock(&tl->setcallback_lock);
326 	if (cb)
327 		cb(cb_arg, T_CALLBACK_REASON_SLOTCLOSE, NULL, 0, slot_id, 0);
328 
329 	tl->slots_changed = 1;
330 	pthread_mutex_unlock(&tl->global_lock);
331 }
332 
en50221_tl_poll(struct en50221_transport_layer * tl)333 int en50221_tl_poll(struct en50221_transport_layer *tl)
334 {
335 	uint8_t data[4096];
336 	int slot_id;
337 	int j;
338 
339 	// make up pollfds if the slots have changed
340 	pthread_mutex_lock(&tl->global_lock);
341 	if (tl->slots_changed) {
342 		for (slot_id = 0; slot_id < tl->max_slots; slot_id++) {
343 			if (tl->slots[slot_id].ca_hndl != -1) {
344 				tl->slot_pollfds[slot_id].fd = tl->slots[slot_id].ca_hndl;
345 				tl->slot_pollfds[slot_id].events = POLLIN | POLLPRI | POLLERR;
346 				tl->slot_pollfds[slot_id].revents = 0;
347 			} else {
348 				tl->slot_pollfds[slot_id].fd = 0;
349 				tl->slot_pollfds[slot_id].events = 0;
350 				tl->slot_pollfds[slot_id].revents = 0;
351 			}
352 		}
353 		tl->slots_changed = 0;
354 	}
355 	pthread_mutex_unlock(&tl->global_lock);
356 
357 	// anything happened?
358 	if (poll(tl->slot_pollfds, tl->max_slots, 10) < 0) {
359 		tl->error_slot = -1;
360 		tl->error = EN50221ERR_CAREAD;
361 		return -1;
362 	}
363 	// go through all slots (even though poll may not have reported any events
364 	for (slot_id = 0; slot_id < tl->max_slots; slot_id++) {
365 
366 		// check if this slot is still used and get its handle
367 		pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
368 		if (tl->slots[slot_id].ca_hndl == -1) {
369 			pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
370 			continue;
371 		}
372 		int ca_hndl = tl->slots[slot_id].ca_hndl;
373 
374 		if (tl->slot_pollfds[slot_id].revents & (POLLPRI | POLLIN)) {
375 			// read data
376 			uint8_t r_slot_id;
377 			uint8_t connection_id;
378 			int readcnt = dvbca_link_read(ca_hndl, &r_slot_id,
379 						      &connection_id,
380 						      data, sizeof(data));
381 			if (readcnt < 0) {
382 				tl->error_slot = slot_id;
383 				tl->error = EN50221ERR_CAREAD;
384 				pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
385 				return -1;
386 			}
387 			// process it if we got some
388 			if (readcnt > 0) {
389 				if (tl->slots[slot_id].slot != r_slot_id) {
390 					// this message is for an other CAM of the same CA
391 					int new_slot_id;
392 					for (new_slot_id = 0; new_slot_id < tl->max_slots; new_slot_id++) {
393 						if ((tl->slots[new_slot_id].ca_hndl == ca_hndl) &&
394 						    (tl->slots[new_slot_id].slot == r_slot_id))
395 							break;
396 					}
397 					if (new_slot_id != tl->max_slots) {
398 						// we found the requested CAM
399 						pthread_mutex_lock(&tl->slots[new_slot_id].slot_lock);
400 						if (en50221_tl_process_data(tl, new_slot_id, data, readcnt)) {
401 							pthread_mutex_unlock(&tl->slots[new_slot_id].slot_lock);
402 							pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
403 							return -1;
404 						}
405 						pthread_mutex_unlock(&tl->slots[new_slot_id].slot_lock);
406 					} else {
407 						tl->error = EN50221ERR_BADSLOTID;
408 						pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
409 						return -1;
410 					}
411 				} else
412 				    if (en50221_tl_process_data(tl, slot_id, data, readcnt)) {
413 					pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
414 					return -1;
415 				}
416 			}
417 		} else if (tl->slot_pollfds[slot_id].revents & POLLERR) {
418 			// an error was reported
419 			tl->error_slot = slot_id;
420 			tl->error = EN50221ERR_CAREAD;
421 			pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
422 			return -1;
423 		}
424 		// poll the connections on this slot + check for timeouts
425 		for (j = 0; j < tl->max_connections_per_slot; j++) {
426 			// ignore connection if idle
427 			if (tl->slots[slot_id].connections[j].state == T_STATE_IDLE) {
428 				continue;
429 			}
430 			// send queued data
431 			if (tl->slots[slot_id].connections[j].state &
432 				(T_STATE_IN_CREATION | T_STATE_ACTIVE | T_STATE_ACTIVE_DELETEQUEUED)) {
433 				// send data if there is some to go and we're not waiting for a response already
434 				if (tl->slots[slot_id].connections[j].send_queue &&
435 				    (tl->slots[slot_id].connections[j].tx_time.tv_sec == 0)) {
436 
437 					// get the message
438 					struct en50221_message *msg =
439 						tl->slots[slot_id].connections[j].send_queue;
440 					if (msg->next != NULL) {
441 						tl->slots[slot_id].connections[j].send_queue = msg->next;
442 					} else {
443 						tl->slots[slot_id].connections[j].send_queue = NULL;
444 						tl->slots[slot_id].connections[j].send_queue_tail = NULL;
445 					}
446 
447 					// send the message
448 					if (dvbca_link_write(tl->slots[slot_id].ca_hndl,
449 					    		     tl->slots[slot_id].slot,
450 							     j,
451 							     msg->data, msg->length) < 0) {
452 						free(msg);
453 						pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
454 						tl->error_slot = slot_id;
455 						tl->error = EN50221ERR_CAWRITE;
456 						print(LOG_LEVEL, ERROR, 1, "CAWrite failed");
457 						return -1;
458 					}
459 					gettimeofday(&tl->slots[slot_id].connections[j].tx_time, 0);
460 
461 					// fixup connection state for T_DELETE_T_C
462 					if (msg->length && (msg->data[0] == T_DELETE_T_C)) {
463 						tl->slots[slot_id].connections[j].state = T_STATE_IN_DELETION;
464 						if (tl->slots[slot_id].connections[j].chain_buffer) {
465 							free(tl->slots[slot_id].connections[j].chain_buffer);
466 						}
467 						tl->slots[slot_id].connections[j].chain_buffer = NULL;
468 						tl->slots[slot_id].connections[j].buffer_length = 0;
469 					}
470 
471 					free(msg);
472 				}
473 			}
474 			// poll it if we're not expecting a reponse and the poll time has elapsed
475 			if (tl->slots[slot_id].connections[j].state & T_STATE_ACTIVE) {
476 				if ((tl->slots[slot_id].connections[j].tx_time.tv_sec == 0) &&
477 				    (time_after(tl->slots[slot_id].connections[j].last_poll_time,
478 				     		tl->slots[slot_id].poll_delay))) {
479 
480 					gettimeofday(&tl->slots[slot_id].connections[j].last_poll_time, 0);
481 					if (en50221_tl_poll_tc(tl, slot_id, j)) {
482 						pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
483 						return -1;
484 					}
485 				}
486 			}
487 
488 			// check for timeouts - in any state
489 			if (tl->slots[slot_id].connections[j].tx_time.tv_sec &&
490 			    (time_after(tl->slots[slot_id].connections[j].tx_time,
491 			     		tl->slots[slot_id].response_timeout))) {
492 
493 				if (tl->slots[slot_id].connections[j].state &
494 				    (T_STATE_IN_CREATION |T_STATE_IN_DELETION)) {
495 					tl->slots[slot_id].connections[j].state = T_STATE_IDLE;
496 				} else if (tl->slots[slot_id].connections[j].state &
497 					   (T_STATE_ACTIVE | T_STATE_ACTIVE_DELETEQUEUED)) {
498 					tl->error_slot = slot_id;
499 					tl->error = EN50221ERR_TIMEOUT;
500 					pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
501 					return -1;
502 				}
503 			}
504 		}
505 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
506 	}
507 
508 	return 0;
509 }
510 
en50221_tl_register_callback(struct en50221_transport_layer * tl,en50221_tl_callback callback,void * arg)511 void en50221_tl_register_callback(struct en50221_transport_layer *tl,
512 				  en50221_tl_callback callback, void *arg)
513 {
514 	pthread_mutex_lock(&tl->setcallback_lock);
515 	tl->callback = callback;
516 	tl->callback_arg = arg;
517 	pthread_mutex_unlock(&tl->setcallback_lock);
518 }
519 
en50221_tl_get_error_slot(struct en50221_transport_layer * tl)520 int en50221_tl_get_error_slot(struct en50221_transport_layer *tl)
521 {
522 	return tl->error_slot;
523 }
524 
en50221_tl_get_error(struct en50221_transport_layer * tl)525 int en50221_tl_get_error(struct en50221_transport_layer *tl)
526 {
527 	return tl->error;
528 }
529 
en50221_tl_send_data(struct en50221_transport_layer * tl,uint8_t slot_id,uint8_t connection_id,uint8_t * data,uint32_t data_size)530 int en50221_tl_send_data(struct en50221_transport_layer *tl,
531 			 uint8_t slot_id, uint8_t connection_id,
532 			 uint8_t * data, uint32_t data_size)
533 {
534 #ifdef DEBUG_TXDATA
535 	printf("[[[[[[[[[[[[[[[[[[[[\n");
536 	uint32_t ii = 0;
537 	for (ii = 0; ii < data_size; ii++) {
538 		printf("%02x: %02x\n", ii, data[ii]);
539 	}
540 	printf("]]]]]]]]]]]]]]]]]]]]\n");
541 #endif
542 
543 	if (slot_id >= tl->max_slots) {
544 		tl->error = EN50221ERR_BADSLOTID;
545 		return -1;
546 	}
547 
548 	pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
549 	if (tl->slots[slot_id].ca_hndl == -1) {
550 		tl->error = EN50221ERR_BADSLOTID;
551 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
552 		return -1;
553 	}
554 	if (connection_id >= tl->max_connections_per_slot) {
555 		tl->error_slot = slot_id;
556 		tl->error = EN50221ERR_BADCONNECTIONID;
557 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
558 		return -1;
559 	}
560 	if (tl->slots[slot_id].connections[connection_id].state != T_STATE_ACTIVE) {
561 		tl->error = EN50221ERR_BADCONNECTIONID;
562 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
563 		return -1;
564 	}
565 	// allocate msg structure
566 	struct en50221_message *msg =
567 	    malloc(sizeof(struct en50221_message) + data_size + 10);
568 	if (msg == NULL) {
569 		tl->error_slot = slot_id;
570 		tl->error = EN50221ERR_OUTOFMEMORY;
571 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
572 		return -1;
573 	}
574 	// make up data to send
575 	int length_field_len;
576 	msg->data[0] = T_DATA_LAST;
577 	if ((length_field_len = asn_1_encode(data_size + 1, msg->data + 1, 3)) < 0) {
578 		free(msg);
579 		tl->error_slot = slot_id;
580 		tl->error = EN50221ERR_ASNENCODE;
581 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
582 		return -1;
583 	}
584 	msg->data[1 + length_field_len] = connection_id;
585 	memcpy(msg->data + 1 + length_field_len + 1, data, data_size);
586 	msg->length = 1 + length_field_len + 1 + data_size;
587 
588 	// queue it for transmission
589 	queue_message(tl, slot_id, connection_id, msg);
590 
591 	pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
592 	return 0;
593 }
594 
en50221_tl_send_datav(struct en50221_transport_layer * tl,uint8_t slot_id,uint8_t connection_id,struct iovec * vector,int iov_count)595 int en50221_tl_send_datav(struct en50221_transport_layer *tl,
596 			  uint8_t slot_id, uint8_t connection_id,
597 			  struct iovec *vector, int iov_count)
598 {
599 #ifdef DEBUG_TXDATA
600 	printf("[[[[[[[[[[[[[[[[[[[[\n");
601 	uint32_t ii = 0;
602 	uint32_t iipos = 0;
603 	for (ii = 0; ii < (uint32_t) iov_count; ii++) {
604 		uint32_t jj;
605 		for (jj = 0; jj < vector[ii].iov_len; jj++) {
606 			printf("%02x: %02x\n", jj + iipos,
607 			       *((uint8_t *) (vector[ii].iov_base) + jj));
608 		}
609 		iipos += vector[ii].iov_len;
610 	}
611 	printf("]]]]]]]]]]]]]]]]]]]]\n");
612 #endif
613 
614 	if (slot_id >= tl->max_slots) {
615 		tl->error = EN50221ERR_BADSLOTID;
616 		return -1;
617 	}
618 
619 	pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
620 	if (tl->slots[slot_id].ca_hndl == -1) {
621 		tl->error = EN50221ERR_BADSLOTID;
622 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
623 		return -1;
624 	}
625 	if (connection_id >= tl->max_connections_per_slot) {
626 		tl->error_slot = slot_id;
627 		tl->error = EN50221ERR_BADCONNECTIONID;
628 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
629 		return -1;
630 	}
631 	if (tl->slots[slot_id].connections[connection_id].state != T_STATE_ACTIVE) {
632 		tl->error = EN50221ERR_BADCONNECTIONID;
633 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
634 		return -1;
635 	}
636 	// calculate the total length of the data to send
637 	uint32_t data_size = 0;
638 	int i;
639 	for (i = 0; i < iov_count; i++) {
640 		data_size += vector[i].iov_len;
641 	}
642 
643 	// allocate msg structure
644 	struct en50221_message *msg =
645 	    malloc(sizeof(struct en50221_message) + data_size + 10);
646 	if (msg == NULL) {
647 		tl->error_slot = slot_id;
648 		tl->error = EN50221ERR_OUTOFMEMORY;
649 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
650 		return -1;
651 	}
652 	// make up data to send
653 	int length_field_len;
654 	msg->data[0] = T_DATA_LAST;
655 	if ((length_field_len = asn_1_encode(data_size + 1, msg->data + 1, 3)) < 0) {
656 		free(msg);
657 		tl->error_slot = slot_id;
658 		tl->error = EN50221ERR_ASNENCODE;
659 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
660 		return -1;
661 	}
662 	msg->data[1 + length_field_len] = connection_id;
663 	msg->length = 1 + length_field_len + 1 + data_size;
664 	msg->next = NULL;
665 
666 	// merge the iovecs
667 	uint32_t pos = 1 + length_field_len + 1;
668 	for (i = 0; i < iov_count; i++) {
669 		memcpy(msg->data + pos, vector[i].iov_base,
670 		       vector[i].iov_len);
671 		pos += vector[i].iov_len;
672 	}
673 
674 	// queue it for transmission
675 	queue_message(tl, slot_id, connection_id, msg);
676 
677 	pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
678 	return 0;
679 }
680 
en50221_tl_new_tc(struct en50221_transport_layer * tl,uint8_t slot_id)681 int en50221_tl_new_tc(struct en50221_transport_layer *tl, uint8_t slot_id)
682 {
683 	// check
684 	if (slot_id >= tl->max_slots) {
685 		tl->error = EN50221ERR_BADSLOTID;
686 		return -1;
687 	}
688 
689 	pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
690 	if (tl->slots[slot_id].ca_hndl == -1) {
691 		tl->error = EN50221ERR_BADSLOTID;
692 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
693 		return -1;
694 	}
695 	// allocate a new connection if possible
696 	int conid = en50221_tl_alloc_new_tc(tl, slot_id);
697 	if (conid == -1) {
698 		tl->error_slot = slot_id;
699 		tl->error = EN50221ERR_OUTOFCONNECTIONS;
700 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
701 		return -1;
702 	}
703 	// allocate msg structure
704 	struct en50221_message *msg =
705 	    malloc(sizeof(struct en50221_message) + 3);
706 	if (msg == NULL) {
707 		tl->error_slot = slot_id;
708 		tl->error = EN50221ERR_OUTOFMEMORY;
709 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
710 		return -1;
711 	}
712 	// make up the data to send
713 	msg->data[0] = T_CREATE_T_C;
714 	msg->data[1] = 1;
715 	msg->data[2] = conid;
716 	msg->length = 3;
717 	msg->next = NULL;
718 
719 	// queue it for transmission
720 	queue_message(tl, slot_id, conid, msg);
721 
722 	// done
723 	pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
724 	return conid;
725 }
726 
en50221_tl_del_tc(struct en50221_transport_layer * tl,uint8_t slot_id,uint8_t connection_id)727 int en50221_tl_del_tc(struct en50221_transport_layer *tl, uint8_t slot_id,
728 		      uint8_t connection_id)
729 {
730 	// check
731 	if (slot_id >= tl->max_slots) {
732 		tl->error = EN50221ERR_BADSLOTID;
733 		return -1;
734 	}
735 
736 	pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
737 	if (tl->slots[slot_id].ca_hndl == -1) {
738 		tl->error = EN50221ERR_BADSLOTID;
739 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
740 		return -1;
741 	}
742 	if (connection_id >= tl->max_connections_per_slot) {
743 		tl->error_slot = slot_id;
744 		tl->error = EN50221ERR_BADCONNECTIONID;
745 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
746 		return -1;
747 	}
748 	if (!(tl->slots[slot_id].connections[connection_id].state &
749 	      (T_STATE_ACTIVE | T_STATE_IN_DELETION))) {
750 		tl->error_slot = slot_id;
751 		tl->error = EN50221ERR_BADSTATE;
752 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
753 		return -1;
754 	}
755 	// allocate msg structure
756 	struct en50221_message *msg =
757 	    malloc(sizeof(struct en50221_message) + 3);
758 	if (msg == NULL) {
759 		tl->error_slot = slot_id;
760 		tl->error = EN50221ERR_OUTOFMEMORY;
761 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
762 		return -1;
763 	}
764 	// make up the data to send
765 	msg->data[0] = T_DELETE_T_C;
766 	msg->data[1] = 1;
767 	msg->data[2] = connection_id;
768 	msg->length = 3;
769 	msg->next = NULL;
770 
771 	// queue it for transmission
772 	queue_message(tl, slot_id, connection_id, msg);
773 	tl->slots[slot_id].connections[connection_id].state =
774 	    T_STATE_ACTIVE_DELETEQUEUED;
775 
776 	pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
777 	return 0;
778 }
779 
en50221_tl_get_connection_state(struct en50221_transport_layer * tl,uint8_t slot_id,uint8_t connection_id)780 int en50221_tl_get_connection_state(struct en50221_transport_layer *tl,
781 				    uint8_t slot_id, uint8_t connection_id)
782 {
783 	if (slot_id >= tl->max_slots) {
784 		tl->error = EN50221ERR_BADSLOTID;
785 		return -1;
786 	}
787 
788 	pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
789 	if (tl->slots[slot_id].ca_hndl == -1) {
790 		tl->error = EN50221ERR_BADSLOTID;
791 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
792 		return -1;
793 	}
794 	if (connection_id >= tl->max_connections_per_slot) {
795 		tl->error_slot = slot_id;
796 		tl->error = EN50221ERR_BADCONNECTIONID;
797 		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
798 		return -1;
799 	}
800 	int state = tl->slots[slot_id].connections[connection_id].state;
801 	pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
802 
803 	return state;
804 }
805 
806 
807 
808 
809 // ask the module for new data
en50221_tl_poll_tc(struct en50221_transport_layer * tl,uint8_t slot_id,uint8_t connection_id)810 static int en50221_tl_poll_tc(struct en50221_transport_layer *tl,
811 			      uint8_t slot_id, uint8_t connection_id)
812 {
813 	gettimeofday(&tl->slots[slot_id].connections[connection_id].
814 		     tx_time, 0);
815 
816 	// send command
817 	uint8_t hdr[3];
818 	hdr[0] = T_DATA_LAST;
819 	hdr[1] = 1;
820 	hdr[2] = connection_id;
821 	if (dvbca_link_write(tl->slots[slot_id].ca_hndl,
822 	    		     tl->slots[slot_id].slot,
823 			     connection_id, hdr, 3) < 0) {
824 		tl->error_slot = slot_id;
825 		tl->error = EN50221ERR_CAWRITE;
826 		return -1;
827 	}
828 	return 0;
829 }
830 
831 // handle incoming data
en50221_tl_process_data(struct en50221_transport_layer * tl,uint8_t slot_id,uint8_t * data,uint32_t data_length)832 static int en50221_tl_process_data(struct en50221_transport_layer *tl,
833 				   uint8_t slot_id, uint8_t * data,
834 				   uint32_t data_length)
835 {
836 	int result;
837 
838 #ifdef DEBUG_RXDATA
839 	printf("-------------------\n");
840 	uint32_t ii = 0;
841 	for (ii = 0; ii < data_length; ii++) {
842 		printf("%02x: %02x\n", ii, data[ii]);
843 	}
844 	printf("+++++++++++++++++++\n");
845 #endif
846 
847 	// process the received data
848 	while (data_length) {
849 		// parse the header
850 		uint8_t tpdu_tag = data[0];
851 		uint16_t asn_data_length;
852 		int length_field_len;
853 		if ((length_field_len = asn_1_decode(&asn_data_length, data + 1, data_length - 1)) < 0) {
854 			print(LOG_LEVEL, ERROR, 1,
855 			      "Received data with invalid asn from module on slot %02x\n",
856 			      slot_id);
857 			tl->error_slot = slot_id;
858 			tl->error = EN50221ERR_BADCAMDATA;
859 			return -1;
860 		}
861 		if ((asn_data_length < 1) ||
862 		    (asn_data_length > (data_length - (1 + length_field_len)))) {
863 			print(LOG_LEVEL, ERROR, 1,
864 			      "Received data with invalid length from module on slot %02x\n",
865 			      slot_id);
866 			tl->error_slot = slot_id;
867 			tl->error = EN50221ERR_BADCAMDATA;
868 			return -1;
869 		}
870 		uint8_t connection_id = data[1 + length_field_len];
871 		data += 1 + length_field_len + 1;
872 		data_length -= (1 + length_field_len + 1);
873 		asn_data_length--;
874 
875 		// check the connection_id
876 		if (connection_id >= tl->max_connections_per_slot) {
877 			print(LOG_LEVEL, ERROR, 1,
878 			      "Received bad connection id %02x from module on slot %02x\n",
879 			      connection_id, slot_id);
880 			tl->error_slot = slot_id;
881 			tl->error = EN50221ERR_BADCONNECTIONID;
882 			return -1;
883 		}
884 		// process the TPDUs
885 		switch (tpdu_tag) {
886 		case T_C_T_C_REPLY:
887 			if ((result = en50221_tl_handle_create_tc_reply(tl, slot_id, connection_id)) < 0) {
888 				return -1;
889 			}
890 			break;
891 		case T_DELETE_T_C:
892 			if ((result = en50221_tl_handle_delete_tc(tl, slot_id, connection_id)) < 0) {
893 				return -1;
894 			}
895 			break;
896 		case T_D_T_C_REPLY:
897 			if ((result = en50221_tl_handle_delete_tc_reply(tl, slot_id, connection_id)) < 0) {
898 				return -1;
899 			}
900 			break;
901 		case T_REQUEST_T_C:
902 			if ((result = en50221_tl_handle_request_tc(tl, slot_id, connection_id)) < 0) {
903 				return -1;
904 			}
905 			break;
906 		case T_DATA_MORE:
907 			if ((result = en50221_tl_handle_data_more(tl, slot_id,
908 			     					  connection_id,
909 								  data,
910 								  asn_data_length)) < 0) {
911 				return -1;
912 			}
913 			break;
914 		case T_DATA_LAST:
915 			if ((result = en50221_tl_handle_data_last(tl, slot_id,
916 			     					  connection_id,
917 								  data,
918 								  asn_data_length)) < 0) {
919 				return -1;
920 			}
921 			break;
922 		case T_SB:
923 			if ((result = en50221_tl_handle_sb(tl, slot_id,
924 			     				   connection_id,
925 							   data,
926 							   asn_data_length)) < 0) {
927 				return -1;
928 			}
929 			break;
930 		default:
931 			print(LOG_LEVEL, ERROR, 1,
932 			      "Recieved unexpected TPDU tag %02x from module on slot %02x\n",
933 			      tpdu_tag, slot_id);
934 			tl->error_slot = slot_id;
935 			tl->error = EN50221ERR_BADCAMDATA;
936 			return -1;
937 		}
938 
939 		// skip over the consumed data
940 		data += asn_data_length;
941 		data_length -= asn_data_length;
942 	}
943 
944 	return 0;
945 }
946 
en50221_tl_handle_create_tc_reply(struct en50221_transport_layer * tl,uint8_t slot_id,uint8_t connection_id)947 static int en50221_tl_handle_create_tc_reply(struct en50221_transport_layer
948 					     *tl, uint8_t slot_id,
949 					     uint8_t connection_id)
950 {
951 	// set this connection to state active
952 	if (tl->slots[slot_id].connections[connection_id].state == T_STATE_IN_CREATION) {
953 		tl->slots[slot_id].connections[connection_id].state = T_STATE_ACTIVE;
954 		tl->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0;
955 
956 		// tell upper layers
957 		pthread_mutex_lock(&tl->setcallback_lock);
958 		en50221_tl_callback cb = tl->callback;
959 		void *cb_arg = tl->callback_arg;
960 		pthread_mutex_unlock(&tl->setcallback_lock);
961 		if (cb)
962 			cb(cb_arg, T_CALLBACK_REASON_CONNECTIONOPEN, NULL, 0, slot_id, connection_id);
963 	} else {
964 		print(LOG_LEVEL, ERROR, 1,
965 		      "Received T_C_T_C_REPLY for connection not in "
966 		      "T_STATE_IN_CREATION from module on slot %02x\n",
967 		      slot_id);
968 		tl->error_slot = slot_id;
969 		tl->error = EN50221ERR_BADCAMDATA;
970 		return -1;
971 	}
972 
973 	return 0;
974 }
975 
en50221_tl_handle_delete_tc(struct en50221_transport_layer * tl,uint8_t slot_id,uint8_t connection_id)976 static int en50221_tl_handle_delete_tc(struct en50221_transport_layer *tl,
977 				       uint8_t slot_id,
978 				       uint8_t connection_id)
979 {
980 	// immediately delete this connection and send D_T_C_REPLY
981 	if (tl->slots[slot_id].connections[connection_id].state &
982 	    (T_STATE_ACTIVE | T_STATE_IN_DELETION)) {
983 		// clear down the slot
984 		tl->slots[slot_id].connections[connection_id].state = T_STATE_IDLE;
985 		if (tl->slots[slot_id].connections[connection_id].chain_buffer) {
986 			free(tl->slots[slot_id].connections[connection_id].chain_buffer);
987 		}
988 		tl->slots[slot_id].connections[connection_id].chain_buffer = NULL;
989 		tl->slots[slot_id].connections[connection_id].buffer_length = 0;
990 
991 		// send the reply
992 		uint8_t hdr[3];
993 		hdr[0] = T_D_T_C_REPLY;
994 		hdr[1] = 1;
995 		hdr[2] = connection_id;
996 		if (dvbca_link_write(tl->slots[slot_id].ca_hndl,
997 		    		     tl->slots[slot_id].slot,
998 				     connection_id, hdr, 3) < 0) {
999 			tl->error_slot = slot_id;
1000 			tl->error = EN50221ERR_CAWRITE;
1001 			return -1;
1002 		}
1003 		// tell upper layers
1004 		pthread_mutex_lock(&tl->setcallback_lock);
1005 		en50221_tl_callback cb = tl->callback;
1006 		void *cb_arg = tl->callback_arg;
1007 		pthread_mutex_unlock(&tl->setcallback_lock);
1008 		if (cb)
1009 			cb(cb_arg, T_CALLBACK_REASON_CONNECTIONCLOSE, NULL, 0, slot_id, connection_id);
1010 	} else {
1011 		print(LOG_LEVEL, ERROR, 1,
1012 		      "Received T_DELETE_T_C for inactive connection from module on slot %02x\n",
1013 		      slot_id);
1014 		tl->error_slot = slot_id;
1015 		tl->error = EN50221ERR_BADCAMDATA;
1016 		return -1;
1017 	}
1018 
1019 	return 0;
1020 }
1021 
en50221_tl_handle_delete_tc_reply(struct en50221_transport_layer * tl,uint8_t slot_id,uint8_t connection_id)1022 static int en50221_tl_handle_delete_tc_reply(struct en50221_transport_layer
1023 					     *tl, uint8_t slot_id,
1024 					     uint8_t connection_id)
1025 {
1026 	// delete this connection, should be in T_STATE_IN_DELETION already
1027 	if (tl->slots[slot_id].connections[connection_id].state == T_STATE_IN_DELETION) {
1028 		tl->slots[slot_id].connections[connection_id].state = T_STATE_IDLE;
1029 	} else {
1030 		print(LOG_LEVEL, ERROR, 1,
1031 		      "Received T_D_T_C_REPLY received for connection not in "
1032 		      "T_STATE_IN_DELETION from module on slot %02x\n",
1033 		      slot_id);
1034 		tl->error_slot = slot_id;
1035 		tl->error = EN50221ERR_BADCAMDATA;
1036 		return -1;
1037 	}
1038 
1039 	return 0;
1040 }
1041 
en50221_tl_handle_request_tc(struct en50221_transport_layer * tl,uint8_t slot_id,uint8_t connection_id)1042 static int en50221_tl_handle_request_tc(struct en50221_transport_layer *tl,
1043 					uint8_t slot_id,
1044 					uint8_t connection_id)
1045 {
1046 	// allocate a new connection if possible
1047 	int conid = en50221_tl_alloc_new_tc(tl, slot_id);
1048 	int ca_hndl = tl->slots[slot_id].ca_hndl;
1049 	if (conid == -1) {
1050 		print(LOG_LEVEL, ERROR, 1,
1051 		      "Too many connections requested by module on slot %02x\n",
1052 		      slot_id);
1053 
1054 		// send the error
1055 		uint8_t hdr[4];
1056 		hdr[0] = T_T_C_ERROR;
1057 		hdr[1] = 2;
1058 		hdr[2] = connection_id;
1059 		hdr[3] = 1;
1060 		if (dvbca_link_write(ca_hndl, tl->slots[slot_id].slot, connection_id, hdr, 4) < 0) {
1061 			tl->error_slot = slot_id;
1062 			tl->error = EN50221ERR_CAWRITE;
1063 			return -1;
1064 		}
1065 		tl->slots[slot_id].connections[connection_id].tx_time.
1066 		    tv_sec = 0;
1067 	} else {
1068 		// send the NEW_T_C on the connection we received it on
1069 		uint8_t hdr[4];
1070 		hdr[0] = T_NEW_T_C;
1071 		hdr[1] = 2;
1072 		hdr[2] = connection_id;
1073 		hdr[3] = conid;
1074 		if (dvbca_link_write(ca_hndl, tl->slots[slot_id].slot, connection_id, hdr, 4) < 0) {
1075 			tl->slots[slot_id].connections[conid].state = T_STATE_IDLE;
1076 			tl->error_slot = slot_id;
1077 			tl->error = EN50221ERR_CAWRITE;
1078 			return -1;
1079 		}
1080 		tl->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0;
1081 
1082 		// send the CREATE_T_C on the new connnection
1083 		hdr[0] = T_CREATE_T_C;
1084 		hdr[1] = 1;
1085 		hdr[2] = conid;
1086 		if (dvbca_link_write(ca_hndl, tl->slots[slot_id].slot, conid, hdr, 3) < 0) {
1087 			tl->slots[slot_id].connections[conid].state = T_STATE_IDLE;
1088 			tl->error_slot = slot_id;
1089 			tl->error = EN50221ERR_CAWRITE;
1090 			return -1;
1091 		}
1092 		gettimeofday(&tl->slots[slot_id].connections[conid].tx_time, 0);
1093 
1094 		// tell upper layers
1095 		pthread_mutex_lock(&tl->setcallback_lock);
1096 		en50221_tl_callback cb = tl->callback;
1097 		void *cb_arg = tl->callback_arg;
1098 		pthread_mutex_unlock(&tl->setcallback_lock);
1099 		if (cb)
1100 			cb(cb_arg, T_CALLBACK_REASON_CAMCONNECTIONOPEN, NULL, 0, slot_id, conid);
1101 	}
1102 
1103 	return 0;
1104 }
1105 
en50221_tl_handle_data_more(struct en50221_transport_layer * tl,uint8_t slot_id,uint8_t connection_id,uint8_t * data,uint32_t data_length)1106 static int en50221_tl_handle_data_more(struct en50221_transport_layer *tl,
1107 				       uint8_t slot_id,
1108 				       uint8_t connection_id,
1109 				       uint8_t * data,
1110 				       uint32_t data_length)
1111 {
1112 	// connection in correct state?
1113 	if (tl->slots[slot_id].connections[connection_id].state != T_STATE_ACTIVE) {
1114 		print(LOG_LEVEL, ERROR, 1,
1115 		      "Received T_DATA_MORE for connection not in "
1116 		      "T_STATE_ACTIVE from module on slot %02x\n",
1117 		      slot_id);
1118 		tl->error_slot = slot_id;
1119 		tl->error = EN50221ERR_BADCAMDATA;
1120 		return -1;
1121 	}
1122 	// a chained data packet is coming in, save
1123 	// it to the buffer and wait for more
1124 	tl->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0;
1125 	int new_data_length =
1126 	    tl->slots[slot_id].connections[connection_id].buffer_length + data_length;
1127 	uint8_t *new_data_buffer =
1128 	    realloc(tl->slots[slot_id].connections[connection_id].chain_buffer, new_data_length);
1129 	if (new_data_buffer == NULL) {
1130 		tl->error_slot = slot_id;
1131 		tl->error = EN50221ERR_OUTOFMEMORY;
1132 		return -1;
1133 	}
1134 	tl->slots[slot_id].connections[connection_id].chain_buffer = new_data_buffer;
1135 
1136 	memcpy(tl->slots[slot_id].connections[connection_id].chain_buffer +
1137 	       tl->slots[slot_id].connections[connection_id].buffer_length,
1138 	       data, data_length);
1139 	tl->slots[slot_id].connections[connection_id].buffer_length = new_data_length;
1140 
1141 	return 0;
1142 }
1143 
en50221_tl_handle_data_last(struct en50221_transport_layer * tl,uint8_t slot_id,uint8_t connection_id,uint8_t * data,uint32_t data_length)1144 static int en50221_tl_handle_data_last(struct en50221_transport_layer *tl,
1145 				       uint8_t slot_id,
1146 				       uint8_t connection_id,
1147 				       uint8_t * data,
1148 				       uint32_t data_length)
1149 {
1150 	// connection in correct state?
1151 	if (tl->slots[slot_id].connections[connection_id].state != T_STATE_ACTIVE) {
1152 		print(LOG_LEVEL, ERROR, 1,
1153 		      "Received T_DATA_LAST received for connection not in "
1154 		      "T_STATE_ACTIVE from module on slot %02x\n",
1155 		      slot_id);
1156 		tl->error_slot = slot_id;
1157 		tl->error = EN50221ERR_BADCAMDATA;
1158 		return -1;
1159 	}
1160 	// last package of a chain or single package comes in
1161 	tl->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0;
1162 	if (tl->slots[slot_id].connections[connection_id].chain_buffer == NULL) {
1163 		// single package => dispatch immediately
1164 		pthread_mutex_lock(&tl->setcallback_lock);
1165 		en50221_tl_callback cb = tl->callback;
1166 		void *cb_arg = tl->callback_arg;
1167 		pthread_mutex_unlock(&tl->setcallback_lock);
1168 
1169 		if (cb && data_length) {
1170 			pthread_mutex_unlock(&tl->slots[slot_id].
1171 					     slot_lock);
1172 			cb(cb_arg, T_CALLBACK_REASON_DATA, data, data_length, slot_id, connection_id);
1173 			pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
1174 		}
1175 	} else {
1176 		int new_data_length =
1177 		    tl->slots[slot_id].connections[connection_id].buffer_length + data_length;
1178 		uint8_t *new_data_buffer =
1179 		    realloc(tl->slots[slot_id].connections[connection_id].chain_buffer, new_data_length);
1180 		if (new_data_buffer == NULL) {
1181 			tl->error_slot = slot_id;
1182 			tl->error = EN50221ERR_OUTOFMEMORY;
1183 			return -1;
1184 		}
1185 
1186 		memcpy(new_data_buffer +
1187 		       tl->slots[slot_id].connections[connection_id].
1188 		       buffer_length, data, data_length);
1189 
1190 		// clean the buffer position
1191 		tl->slots[slot_id].connections[connection_id].chain_buffer = NULL;
1192 		tl->slots[slot_id].connections[connection_id].buffer_length = 0;
1193 
1194 		// tell the upper layers
1195 		pthread_mutex_lock(&tl->setcallback_lock);
1196 		en50221_tl_callback cb = tl->callback;
1197 		void *cb_arg = tl->callback_arg;
1198 		pthread_mutex_unlock(&tl->setcallback_lock);
1199 		if (cb && data_length) {
1200 			pthread_mutex_unlock(&tl->slots[slot_id].
1201 					     slot_lock);
1202 			cb(cb_arg, T_CALLBACK_REASON_DATA, new_data_buffer,
1203 			   new_data_length, slot_id, connection_id);
1204 			pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
1205 		}
1206 
1207 		free(new_data_buffer);
1208 	}
1209 
1210 	return 0;
1211 }
1212 
en50221_tl_handle_sb(struct en50221_transport_layer * tl,uint8_t slot_id,uint8_t connection_id,uint8_t * data,uint32_t data_length)1213 static int en50221_tl_handle_sb(struct en50221_transport_layer *tl,
1214 				uint8_t slot_id, uint8_t connection_id,
1215 				uint8_t * data, uint32_t data_length)
1216 {
1217 	// is the connection id ok?
1218 	if (tl->slots[slot_id].connections[connection_id].state != T_STATE_ACTIVE) {
1219 		print(LOG_LEVEL, ERROR, 1,
1220 		      "Received T_SB for connection not in T_STATE_ACTIVE from module on slot %02x\n",
1221 		      slot_id);
1222 		tl->error_slot = slot_id;
1223 		tl->error = EN50221ERR_BADCAMDATA;
1224 		return -1;
1225 	}
1226 	// did we get enough data in the T_SB?
1227 	if (data_length != 1) {
1228 		print(LOG_LEVEL, ERROR, 1,
1229 		      "Recieved T_SB with invalid length from module on slot %02x\n",
1230 		      slot_id);
1231 		tl->error_slot = slot_id;
1232 		tl->error = EN50221ERR_BADCAMDATA;
1233 		return -1;
1234 	}
1235 	// tell it to send the data if it says there is some
1236 	if (data[0] & 0x80) {
1237 		int ca_hndl = tl->slots[slot_id].ca_hndl;
1238 
1239 		// send the RCV
1240 		uint8_t hdr[3];
1241 		hdr[0] = T_RCV;
1242 		hdr[1] = 1;
1243 		hdr[2] = connection_id;
1244 		if (dvbca_link_write(ca_hndl, tl->slots[slot_id].slot, connection_id, hdr, 3) < 0) {
1245 			tl->error_slot = slot_id;
1246 			tl->error = EN50221ERR_CAWRITE;
1247 			return -1;
1248 		}
1249 		gettimeofday(&tl->slots[slot_id].connections[connection_id].tx_time, 0);
1250 
1251 	} else {
1252 		// no data - indicate not waiting for anything now
1253 		tl->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0;
1254 	}
1255 
1256 	return 0;
1257 }
1258 
en50221_tl_alloc_new_tc(struct en50221_transport_layer * tl,uint8_t slot_id)1259 static int en50221_tl_alloc_new_tc(struct en50221_transport_layer *tl,
1260 				   uint8_t slot_id)
1261 {
1262 	// we browse through the array of connection
1263 	// types, to look for the first unused one
1264 	int i, conid = -1;
1265 	for (i = 1; i < tl->max_connections_per_slot; i++) {
1266 		if (tl->slots[slot_id].connections[i].state == T_STATE_IDLE) {
1267 			conid = i;
1268 			break;
1269 		}
1270 	}
1271 	if (conid == -1) {
1272 		print(LOG_LEVEL, ERROR, 1,
1273 		      "CREATE_T_C failed: no more connections available\n");
1274 		return -1;
1275 	}
1276 	// set up the connection struct
1277 	tl->slots[slot_id].connections[conid].state = T_STATE_IN_CREATION;
1278 	tl->slots[slot_id].connections[conid].chain_buffer = NULL;
1279 	tl->slots[slot_id].connections[conid].buffer_length = 0;
1280 
1281 	return conid;
1282 }
1283 
queue_message(struct en50221_transport_layer * tl,uint8_t slot_id,uint8_t connection_id,struct en50221_message * msg)1284 static void queue_message(struct en50221_transport_layer *tl,
1285 			  uint8_t slot_id, uint8_t connection_id,
1286 			  struct en50221_message *msg)
1287 {
1288 	msg->next = NULL;
1289 	if (tl->slots[slot_id].connections[connection_id].send_queue_tail) {
1290 		tl->slots[slot_id].connections[connection_id].send_queue_tail->next = msg;
1291 		tl->slots[slot_id].connections[connection_id].send_queue_tail = msg;
1292 	} else {
1293 		tl->slots[slot_id].connections[connection_id].send_queue = msg;
1294 		tl->slots[slot_id].connections[connection_id].send_queue_tail = msg;
1295 	}
1296 }
1297