~oah-dev/oah/gst-plugins-bad

« back to all changes in this revision

Viewing changes to sys/dvb/camapplication.c

  • Committer: Haakon Sporsheim
  • Date: 2009-03-12 13:52:03 UTC
  • Revision ID: haakon.sporsheim@tandberg.com-20090312135203-i5k294hgkushb0mt
Initial import of git repository: git://anongit.freedesktop.org/gstreamer/gst-plugins-bad (tag: RELEASE-0_10_10)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * camapplication.c - GStreamer CAM (EN50221) Application Layer
 
3
 * Copyright (C) 2007 Alessandro Decina
 
4
 * 
 
5
 * Authors:
 
6
 *   Alessandro Decina <alessandro@nnva.org>
 
7
 *
 
8
 * This library is free software; you can redistribute it and/or
 
9
 * modify it under the terms of the GNU Library General Public
 
10
 * License as published by the Free Software Foundation; either
 
11
 * version 2 of the License, or (at your option) any later version.
 
12
 *
 
13
 * This library is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
 * Library General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU Library General Public
 
19
 * License along with this library; if not, write to the
 
20
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
21
 * Boston, MA 02111-1307, USA.
 
22
 */
 
23
 
 
24
#include "camapplication.h"
 
25
 
 
26
#define GST_CAT_DEFAULT cam_debug_cat
 
27
 
 
28
static CamReturn open_session_request_cb (CamSL * sl,
 
29
    CamSLSession * session, CamSLResourceStatus * status);
 
30
static CamReturn session_opened_cb (CamSL * sl, CamSLSession * session);
 
31
static CamReturn session_closed_cb (CamSL * sl, CamSLSession * session);
 
32
static CamReturn session_data_cb (CamSL * sl,
 
33
    CamSLSession * session, guint8 * data, guint length);
 
34
 
 
35
static guint
 
36
resource_id_hash (gconstpointer key)
 
37
{
 
38
  guint resource_id = GPOINTER_TO_UINT (key);
 
39
 
 
40
  if (!CAM_AL_RESOURCE_ID_IS_PUBLIC (resource_id)) {
 
41
    /* private identifier, leave it as is */
 
42
    return resource_id;
 
43
  }
 
44
 
 
45
  /* public identifier, mask out the version number */
 
46
  return resource_id >> 6;
 
47
}
 
48
 
 
49
CamAL *
 
50
cam_al_new (CamSL * sl)
 
51
{
 
52
  CamAL *al = g_new0 (CamAL, 1);
 
53
 
 
54
  al->sl = sl;
 
55
  al->applications = g_hash_table_new (resource_id_hash, g_direct_equal);
 
56
 
 
57
  sl->user_data = al;
 
58
  sl->open_session_request = open_session_request_cb;
 
59
  sl->session_opened = session_opened_cb;
 
60
  sl->session_closed = session_closed_cb;
 
61
  sl->session_data = session_data_cb;
 
62
 
 
63
  return al;
 
64
}
 
65
 
 
66
void
 
67
cam_al_destroy (CamAL * al)
 
68
{
 
69
  g_hash_table_destroy (al->applications);
 
70
  g_free (al);
 
71
}
 
72
 
 
73
gboolean
 
74
cam_al_install (CamAL * al, CamALApplication * application)
 
75
{
 
76
  if (g_hash_table_lookup (al->applications,
 
77
          GINT_TO_POINTER (application->resource_id)) != NULL)
 
78
    return FALSE;
 
79
 
 
80
  application->al = al;
 
81
 
 
82
  g_hash_table_insert (al->applications,
 
83
      GINT_TO_POINTER (application->resource_id), application);
 
84
 
 
85
  return TRUE;
 
86
}
 
87
 
 
88
gboolean
 
89
cam_al_uninstall (CamAL * al, CamALApplication * application)
 
90
{
 
91
  gboolean ret;
 
92
 
 
93
  ret = g_hash_table_remove (al->applications,
 
94
      GINT_TO_POINTER (application->resource_id));
 
95
 
 
96
  return ret;
 
97
}
 
98
 
 
99
CamALApplication *
 
100
cam_al_get (CamAL * al, guint resource_id)
 
101
{
 
102
  return CAM_AL_APPLICATION (g_hash_table_lookup (al->applications,
 
103
          GINT_TO_POINTER (resource_id)));
 
104
}
 
105
 
 
106
void
 
107
_cam_al_application_init (CamALApplication * application)
 
108
{
 
109
  application->sessions = NULL;
 
110
}
 
111
 
 
112
void
 
113
_cam_al_application_destroy (CamALApplication * application)
 
114
{
 
115
  g_list_free (application->sessions);
 
116
}
 
117
 
 
118
static void
 
119
foreach_get_key (gpointer key, gpointer value, gpointer user_data)
 
120
{
 
121
  GList **lst = (GList **) user_data;
 
122
 
 
123
  *lst = g_list_append (*lst, key);
 
124
}
 
125
 
 
126
GList *
 
127
cam_al_get_resource_ids (CamAL * al)
 
128
{
 
129
  GList *resource_ids = NULL;
 
130
 
 
131
  g_hash_table_foreach (al->applications, foreach_get_key, &resource_ids);
 
132
 
 
133
  return resource_ids;
 
134
}
 
135
 
 
136
void
 
137
cam_al_calc_buffer_size (CamAL * al, guint body_length,
 
138
    guint * buffer_size, guint * offset)
 
139
{
 
140
  guint apdu_header_length;
 
141
  guint8 length_field_len;
 
142
 
 
143
  /* get the length of the lenght_field() */
 
144
  length_field_len = cam_calc_length_field_size (body_length);
 
145
 
 
146
  /* sum the APDU header */
 
147
  apdu_header_length = 3 + length_field_len;
 
148
 
 
149
  /* chain up to the session layer to get the size of the buffer that can
 
150
   * contain the whole APDU */
 
151
  cam_sl_calc_buffer_size (al->sl, apdu_header_length + body_length,
 
152
      buffer_size, offset);
 
153
 
 
154
  /* add the APDU header to the SPDU offset */
 
155
  *offset += apdu_header_length;
 
156
}
 
157
 
 
158
CamReturn
 
159
cam_al_application_write (CamALApplication * application,
 
160
    CamSLSession * session, guint tag, guint8 * buffer, guint buffer_size,
 
161
    guint body_length)
 
162
{
 
163
  guint length_field_len;
 
164
  guint apdu_header_length;
 
165
  guint8 *apdu;
 
166
 
 
167
  length_field_len = cam_calc_length_field_size (body_length);
 
168
  apdu_header_length = 3 + length_field_len;
 
169
  apdu = (buffer + buffer_size) - body_length - apdu_header_length;
 
170
  apdu[0] = tag >> 16;
 
171
  apdu[1] = (tag >> 8) & 0xFF;
 
172
  apdu[2] = tag & 0xFF;
 
173
 
 
174
  cam_write_length_field (&apdu[3], body_length);
 
175
 
 
176
  return cam_sl_session_write (session, buffer, buffer_size,
 
177
      apdu_header_length + body_length);
 
178
}
 
179
 
 
180
static CamReturn
 
181
open_session_request_cb (CamSL * sl, CamSLSession * session,
 
182
    CamSLResourceStatus * status)
 
183
{
 
184
  CamAL *al = CAM_AL (sl->user_data);
 
185
  CamALApplication *application;
 
186
  guint resource_id = session->resource_id;
 
187
  CamReturn ret;
 
188
 
 
189
  application = g_hash_table_lookup (al->applications,
 
190
      GINT_TO_POINTER (resource_id));
 
191
  if (application == NULL) {
 
192
    *status = CAM_SL_RESOURCE_STATUS_NOT_FOUND;
 
193
 
 
194
    return CAM_RETURN_OK;
 
195
  }
 
196
 
 
197
  if (CAM_AL_RESOURCE_ID_VERSION (application->resource_id)
 
198
      < CAM_AL_RESOURCE_ID_VERSION (resource_id)) {
 
199
    *status = CAM_SL_RESOURCE_STATUS_INVALID_VERSION;
 
200
 
 
201
    return CAM_RETURN_OK;
 
202
  }
 
203
 
 
204
  ret = application->session_request (application, session, status);
 
205
  if (CAM_FAILED (ret)) {
 
206
    *status = CAM_SL_RESOURCE_STATUS_NOT_FOUND;
 
207
 
 
208
    return ret;
 
209
  }
 
210
 
 
211
  if (*status == CAM_SL_RESOURCE_STATUS_OPEN) {
 
212
    session->user_data = application;
 
213
    application->sessions = g_list_append (application->sessions, session);
 
214
  }
 
215
 
 
216
  return CAM_RETURN_OK;
 
217
}
 
218
 
 
219
static CamReturn
 
220
session_opened_cb (CamSL * sl, CamSLSession * session)
 
221
{
 
222
  CamALApplication *application;
 
223
 
 
224
  application = CAM_AL_APPLICATION (session->user_data);
 
225
  if (application == NULL) {
 
226
    GST_ERROR ("session is established but has no application");
 
227
    return CAM_RETURN_APPLICATION_ERROR;
 
228
  }
 
229
 
 
230
  return application->open (application, session);
 
231
}
 
232
 
 
233
static CamReturn
 
234
session_closed_cb (CamSL * sl, CamSLSession * session)
 
235
{
 
236
  CamALApplication *application;
 
237
  CamReturn ret;
 
238
  GList *walk;
 
239
 
 
240
  application = CAM_AL_APPLICATION (session->user_data);
 
241
  if (application == NULL) {
 
242
    GST_ERROR ("session is established but has no application");
 
243
    return CAM_RETURN_APPLICATION_ERROR;
 
244
  }
 
245
 
 
246
  ret = application->close (application, session);
 
247
  for (walk = application->sessions; walk; walk = g_list_next (walk)) {
 
248
    CamSLSession *s = CAM_SL_SESSION (walk->data);
 
249
 
 
250
    if (s->session_nb == session->session_nb) {
 
251
      application->sessions = g_list_delete_link (application->sessions, walk);
 
252
      break;
 
253
    }
 
254
  }
 
255
 
 
256
  return ret;
 
257
}
 
258
 
 
259
static CamReturn
 
260
session_data_cb (CamSL * sl, CamSLSession * session, guint8 * data, guint size)
 
261
{
 
262
  CamALApplication *application;
 
263
  guint tag = 0;
 
264
  guint8 length_field_len;
 
265
  guint length;
 
266
  guint i;
 
267
 
 
268
  application = CAM_AL_APPLICATION (session->user_data);
 
269
  if (application == NULL) {
 
270
    GST_ERROR ("session is established but has no application");
 
271
    return CAM_RETURN_APPLICATION_ERROR;
 
272
  }
 
273
 
 
274
  if (size < 4) {
 
275
    GST_ERROR ("invalid APDU length %d", size);
 
276
    return CAM_RETURN_APPLICATION_ERROR;
 
277
  }
 
278
 
 
279
  for (i = 0; i < 3; ++i)
 
280
    tag = (tag << 8) | data[i];
 
281
 
 
282
  length_field_len = cam_read_length_field (&data[3], &length);
 
283
 
 
284
  if (length != size - 4) {
 
285
    GST_ERROR ("unexpected APDU length %d expected %d", length, size);
 
286
 
 
287
    return CAM_RETURN_APPLICATION_ERROR;
 
288
  }
 
289
 
 
290
  return application->data (application, session,
 
291
      tag, data + 3 + length_field_len, length);
 
292
}