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