2
en50221 encoder An implementation for libdvb
3
an implementation for the en50221 transport layer
5
Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU Lesser General Public License as
9
published by the Free Software Foundation; either version 2.1 of
10
the License, or (at your option) any later version.
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU Lesser General Public License for more details.
17
You should have received a copy of the GNU Lesser General Public
18
License along with this library; if not, write to the Free Software
19
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
#include <libdvbapi/dvbca.h>
28
#include "en50221_app_utils.h"
29
#include "en50221_app_tags.h"
30
#include "en50221_stdcam.h"
33
struct en50221_stdcam_hlci {
34
struct en50221_stdcam stdcam;
39
struct en50221_app_send_functions sendfuncs;
42
static void en50221_stdcam_hlci_destroy(struct en50221_stdcam *stdcam, int closefd);
43
static enum en50221_stdcam_status en50221_stdcam_hlci_poll(struct en50221_stdcam *stdcam);
44
static int hlci_cam_added(struct en50221_stdcam_hlci *hlci);
45
static int hlci_send_data(void *arg, uint16_t session_number,
46
uint8_t * data, uint16_t data_length);
47
static int hlci_send_datav(void *arg, uint16_t session_number,
48
struct iovec *vector, int iov_count);
53
struct en50221_stdcam *en50221_stdcam_hlci_create(int cafd, int slotnum)
55
// try and allocate space for the HLCI stdcam
56
struct en50221_stdcam_hlci *hlci =
57
malloc(sizeof(struct en50221_stdcam_hlci));
61
memset(hlci, 0, sizeof(struct en50221_stdcam_hlci));
63
// create the sendfuncs
64
hlci->sendfuncs.arg = hlci;
65
hlci->sendfuncs.send_data = hlci_send_data;
66
hlci->sendfuncs.send_datav = hlci_send_datav;
68
// create the resources (NOTE: we just use fake session numbers here)
69
hlci->stdcam.ai_resource = en50221_app_ai_create(&hlci->sendfuncs);
70
hlci->stdcam.ai_session_number = 0;
71
hlci->stdcam.ca_resource = en50221_app_ca_create(&hlci->sendfuncs);
72
hlci->stdcam.ca_session_number = 1;
73
// hlci->stdcam.mmi_resource = en50221_app_mmi_create(&hlci->sendfuncs);
74
hlci->stdcam.mmi_session_number = -1;
77
hlci->stdcam.destroy = en50221_stdcam_hlci_destroy;
78
hlci->stdcam.poll = en50221_stdcam_hlci_poll;
79
hlci->slotnum = slotnum;
84
static void en50221_stdcam_hlci_destroy(struct en50221_stdcam *stdcam, int closefd)
86
struct en50221_stdcam_hlci *hlci = (struct en50221_stdcam_hlci *) stdcam;
88
if (hlci->stdcam.ai_resource)
89
en50221_app_ai_destroy(hlci->stdcam.ai_resource);
90
if (hlci->stdcam.ca_resource)
91
en50221_app_ca_destroy(hlci->stdcam.ca_resource);
92
if (hlci->stdcam.mmi_resource)
93
en50221_app_mmi_destroy(hlci->stdcam.mmi_resource);
101
static enum en50221_stdcam_status en50221_stdcam_hlci_poll(struct en50221_stdcam *stdcam)
103
struct en50221_stdcam_hlci *hlci = (struct en50221_stdcam_hlci *) stdcam;
105
switch(dvbca_get_cam_state(hlci->cafd, hlci->slotnum)) {
106
case DVBCA_CAMSTATE_MISSING:
107
hlci->initialised = 0;
110
case DVBCA_CAMSTATE_READY:
111
case DVBCA_CAMSTATE_INITIALISING:
112
if (!hlci->initialised)
113
hlci_cam_added(hlci);
117
// delay to prevent busy loop
120
if (!hlci->initialised) {
121
return EN50221_STDCAM_CAM_NONE;
123
return EN50221_STDCAM_CAM_OK;
128
static int hlci_cam_added(struct en50221_stdcam_hlci *hlci)
133
// get application information
134
if (en50221_app_ai_enquiry(hlci->stdcam.ai_resource, 0)) {
137
if ((size = dvbca_hlci_read(hlci->cafd, TAG_APP_INFO, buf, sizeof(buf))) < 0) {
140
if (en50221_app_ai_message(hlci->stdcam.ai_resource, 0, 0, EN50221_APP_AI_RESOURCEID, buf, size)) {
144
// we forge a fake CA_INFO here so the main app works - since it will expect a CA_INFO
145
// this will be replaced with a proper call (below) when the driver support is there
146
buf[0] = TAG_CA_INFO >> 16;
147
buf[1] = (uint8_t) (TAG_CA_INFO >> 8);
148
buf[2] = (uint8_t) TAG_CA_INFO;
150
if (en50221_app_ca_message(hlci->stdcam.ca_resource, 0, 0, EN50221_APP_CA_RESOURCEID, buf, 4)) {
155
// get CA information
156
if (en50221_app_ca_info_enq(ca_resource, 0)) {
157
fprintf(stderr, "Failed to send CA INFO enquiry\n");
161
if ((size = dvbca_hlci_read(cafd, TAG_CA_INFO, buf, sizeof(buf))) < 0) {
162
fprintf(stderr, "Failed to read CA INFO\n");
166
if (en50221_app_ca_message(ca_resource, 0, 0, EN50221_APP_CA_RESOURCEID, buf, size)) {
167
fprintf(stderr, "Failed to parse CA INFO\n");
174
hlci->initialised = 1;
178
static int hlci_send_data(void *arg, uint16_t session_number,
179
uint8_t * data, uint16_t data_length)
181
(void) session_number;
182
struct en50221_stdcam_hlci *hlci = arg;
184
return dvbca_hlci_write(hlci->cafd, data, data_length);
187
static int hlci_send_datav(void *arg, uint16_t session_number,
188
struct iovec *vector, int iov_count)
190
(void) session_number;
191
struct en50221_stdcam_hlci *hlci = arg;
193
// calculate the total length of the data to send
194
uint32_t data_size = 0;
196
for (i = 0; i < iov_count; i++) {
197
data_size += vector[i].iov_len;
200
// allocate memory for it
201
uint8_t *buf = malloc(data_size);
207
for (i = 0; i < iov_count; i++) {
208
memcpy(buf + pos, vector[i].iov_base, vector[i].iov_len);
209
pos += vector[i].iov_len;
212
// sendit and cleanup
213
int status = dvbca_hlci_write(hlci->cafd, buf, data_size);