Project

General

Profile

Bug #434 » dvb_support.c

bigtarget bigtarget, 2011-05-12 15:07

 
1
/*
2
 *  TV Input - DVB - Support functions
3
 *  Copyright (C) 2007 Andreas ?man
4
 *
5
 *  This program is free software: you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
7
 *  the Free Software Foundation, either version 3 of the License, or
8
 *  (at your option) any later version.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18

    
19
#include <pthread.h>
20

    
21
#include <sys/types.h>
22
#include <sys/stat.h>
23
#include <sys/ioctl.h>
24
#include <errno.h>
25
#include <iconv.h>
26

    
27
#include <stdio.h>
28
#include <unistd.h>
29
#include <stdlib.h>
30
#include <string.h>
31

    
32
#include <linux/dvb/frontend.h>
33

    
34
#include "tvheadend.h"
35
#include "dvb_support.h"
36
#include "dvb.h"
37

    
38
/**
39
 *
40
 */
41
static iconv_t convert_iso_8859[16];
42
static iconv_t convert_utf8;
43
static iconv_t convert_latin1;
44

    
45

    
46
static iconv_t
47
dvb_iconv_open(const char *srcencoding)
48
{
49
  iconv_t ic;
50
  ic = iconv_open("UTF8", srcencoding);
51
  return ic;
52
}
53

    
54
void
55
dvb_conversion_init(void)
56
{
57
  char buf[50];
58
  int i;
59
 
60
  for(i = 1; i <= 15; i++) {
61
    snprintf(buf, sizeof(buf), "ISO_8859-%d", i);
62
    convert_iso_8859[i] = dvb_iconv_open(buf);
63
  }
64

    
65
  convert_utf8   = dvb_iconv_open("UTF8");
66
  convert_latin1 = dvb_iconv_open("ISO6937");
67
}
68

    
69

    
70

    
71
/*
72
 * DVB String conversion according to EN 300 468, Annex A
73
 * Not all character sets are supported, but it should cover most of them
74
 */
75

    
76
int
77
dvb_get_string(char *dst, size_t dstlen, const uint8_t *src, size_t srclen, char *dvb_default_charset)
78
{
79
  iconv_t ic;
80
  int len;
81
  char *in, *out;
82
  size_t inlen, outlen;
83
  int utf8 = 0;
84
  int i;
85
  unsigned char *tmp;
86
  int r;
87
  printf("%s \n",dvb_default_charset);
88
  if(srclen < 1) {
89
    *dst = 0;
90
    return 0;
91
  }
92
    
93
  switch(src[0]) {
94
  case 0:
95
    return -1;
96

    
97
  case 0x01 ... 0x0b:
98
    ic = convert_iso_8859[src[0] + 4];
99
    src++; srclen--;
100
    break;
101

    
102
  case 0x0c ... 0x0f:
103
    return -1;
104

    
105
  case 0x10: /* Table A.4 */
106
    if(srclen < 3 || src[1] != 0 || src[2] == 0 || src[2] > 0x0f)
107
      return -1;
108

    
109
    ic = convert_iso_8859[src[2]];
110
    src+=3; srclen-=3;
111
    break;
112
    
113
  case 0x11 ... 0x14:
114
    return -1;
115

    
116
  case 0x15:
117
    ic = convert_utf8;
118
    utf8 = 1;
119
    break;
120
  case 0x16 ... 0x1f:
121
    return -1;
122

    
123
  default:
124
    if (dvb_default_charset != NULL && sscanf(dvb_default_charset, "ISO8859-%d", &i) > 0) {
125
      if (i > 0 && i < 16) {
126
        ic = convert_iso_8859[i];
127
      } else {
128
        ic = convert_latin1;
129
      }
130
    } else {
131
      ic = convert_latin1;
132
    }
133
    break;
134
  }
135

    
136
  if(srclen < 1) {
137
    *dst = 0;
138
    return 0;
139
  }
140

    
141
  tmp = alloca(srclen + 1);
142
  memcpy(tmp, src, srclen);
143
  tmp[srclen] = 0;
144

    
145

    
146
  /* Escape control codes */
147

    
148
  if(!utf8) {
149
    for(i = 0; i < srclen; i++) {
150
      if(tmp[i] >= 0x80 && tmp[i] <= 0x9f)
151
	tmp[i] = ' ';
152
    }
153
  }
154

    
155
  if(ic == (iconv_t) -1)
156
    return -1;
157

    
158
  inlen = srclen;
159
  outlen = dstlen - 1;
160

    
161
  out = dst;
162
  in = (char *)tmp;
163
  if (dvb_default_charset != NULL ) {
164
      if (sscanf(dvb_default_charset, "ISO8859-%d", &i) > 0 && i > 0 && i < 16) {
165
        ic = convert_iso_8859[i];
166
      } else {
167
        ic = convert_latin1;
168
      }
169
    }
170
  while(inlen > 0) {
171
    printf("%s \n",in);
172
    r = iconv(ic, &in, &inlen, &out, &outlen);
173
    printf("%s \n",out);
174
    if(r == (size_t) -1) {
175
      if(errno == EILSEQ) {
176
	in++;
177
	inlen--;
178
	continue;
179
      } else {
180
	return -1;
181
      }
182
    }
183
  }
184

    
185
  len = dstlen - outlen - 1;
186
  dst[len] = 0;
187
  return 0;
188
}
189

    
190

    
191
int
192
dvb_get_string_with_len(char *dst, size_t dstlen, 
193
			const uint8_t *buf, size_t buflen, char *dvb_default_charset)
194
{
195
  int l = buf[0];
196

    
197
  if(l + 1 > buflen)
198
    return -1;
199

    
200
  if(dvb_get_string(dst, dstlen, buf + 1, l, dvb_default_charset))
201
    return -1;
202

    
203
  return l + 1;
204
}
205

    
206

    
207
/**
208
 *
209
 */
210
void
211
atsc_utf16_to_utf8(uint8_t *src, int len, char *buf, int buflen)
212
{
213
  int i, c, r;
214

    
215
  for(i = 0; i < len; i++) {
216
    c = (src[i * 2 + 0] << 8) | src[i * 2 + 1];
217

    
218
    if(buflen >= 7) {
219
      r = put_utf8(buf, c);
220
      buf += r;
221
      buflen -= r;
222
    }
223
  }
224
  *buf = 0;
225
}
226

    
227

    
228

    
229

    
230

    
231
/*
232
 * DVB time and date functions
233
 */
234

    
235
time_t
236
dvb_convert_date(uint8_t *dvb_buf)
237
{
238
  int i;
239
  int year, month, day, hour, min, sec;
240
  long int mjd;
241
  struct tm dvb_time;
242

    
243
  mjd = (dvb_buf[0] & 0xff) << 8;
244
  mjd += (dvb_buf[1] & 0xff);
245
  hour = bcdtoint(dvb_buf[2] & 0xff);
246
  min = bcdtoint(dvb_buf[3] & 0xff);
247
  sec = bcdtoint(dvb_buf[4] & 0xff);
248
  /*
249
   * Use the routine specified in ETSI EN 300 468 V1.4.1,
250
   * "Specification for Service Information in Digital Video Broadcasting"
251
   * to convert from Modified Julian Date to Year, Month, Day.
252
   */
253
  year = (int) ((mjd - 15078.2) / 365.25);
254
  month = (int) ((mjd - 14956.1 - (int) (year * 365.25)) / 30.6001);
255
  day = mjd - 14956 - (int) (year * 365.25) - (int) (month * 30.6001);
256
  if (month == 14 || month == 15)
257
    i = 1;
258
  else
259
    i = 0;
260
  year += i;
261
  month = month - 1 - i * 12;
262

    
263
  dvb_time.tm_sec = sec;
264
  dvb_time.tm_min = min;
265
  dvb_time.tm_hour = hour;
266
  dvb_time.tm_mday = day;
267
  dvb_time.tm_mon = month - 1;
268
  dvb_time.tm_year = year;
269
  dvb_time.tm_isdst = -1;
270
  dvb_time.tm_wday = 0;
271
  dvb_time.tm_yday = 0;
272
  return (timegm(&dvb_time));
273
}
274

    
275
/**
276
 *
277
 */
278
static struct strtab adaptertype[] = {
279
  { "DVB-S",  FE_QPSK },
280
  { "DVB-C",  FE_QAM },
281
  { "DVB-T",  FE_OFDM },
282
  { "ATSC",   FE_ATSC },
283
};
284

    
285

    
286
int
287
dvb_str_to_adaptertype(const char *str)
288
{
289
  return str2val(str, adaptertype);
290
}
291

    
292
const char *
293
dvb_adaptertype_to_str(int type)
294
{
295
  return val2str(type, adaptertype) ?: "invalid";
296
}
297

    
298
const char *
299
dvb_polarisation_to_str(int pol)
300
{
301
  switch(pol) {
302
  case POLARISATION_VERTICAL:       return "V";
303
  case POLARISATION_HORIZONTAL:     return "H";
304
  case POLARISATION_CIRCULAR_LEFT:  return "L";
305
  case POLARISATION_CIRCULAR_RIGHT: return "R";
306
  default:                          return "X";
307
  }
308
}
309

    
310
const char *
311
dvb_polarisation_to_str_long(int pol)
312
{
313
  switch(pol) {
314
  case POLARISATION_VERTICAL:        return "Vertical";
315
  case POLARISATION_HORIZONTAL:      return "Horizontal";
316
  case POLARISATION_CIRCULAR_LEFT:   return "Left";
317
  case POLARISATION_CIRCULAR_RIGHT:  return "Right";
318
  default:                           return "??";
319
  }
320
}
321

    
322

    
323
th_dvb_adapter_t *
324
dvb_adapter_find_by_identifier(const char *identifier)
325
{
326
  th_dvb_adapter_t *tda;
327

    
328
  TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link)
329
    if(!strcmp(identifier, tda->tda_identifier))
330
      return tda;
331
  return NULL;
332
}
333

    
334

    
335
/**
336
 *
337
 */
338
static const char *
339
nicenum(char *x, size_t siz, unsigned int v)
340
{
341
  if(v < 1000)
342
    snprintf(x, siz, "%d", v);
343
  else if(v < 1000000)
344
    snprintf(x, siz, "%d,%03d", v / 1000, v % 1000);
345
  else if(v < 1000000000)
346
    snprintf(x, siz, "%d,%03d,%03d", 
347
	     v / 1000000, (v % 1000000) / 1000, v % 1000);
348
  else 
349
    snprintf(x, siz, "%d,%03d,%03d,%03d", 
350
	     v / 1000000000, (v % 1000000000) / 1000000,
351
	     (v % 1000000) / 1000, v % 1000);
352
  return x;
353
}
354

    
355

    
356
/**
357
 * 
358
 */
359
void
360
dvb_mux_nicefreq(char *buf, size_t size, th_dvb_mux_instance_t *tdmi)
361
{
362
  char freq[50];
363

    
364
  if(tdmi->tdmi_adapter->tda_type == FE_QPSK) {
365
    nicenum(freq, sizeof(freq), tdmi->tdmi_conf.dmc_fe_params.frequency);
366
    snprintf(buf, size, "%s kHz", freq);
367
  } else {
368
    nicenum(freq, sizeof(freq), 
369
	    tdmi->tdmi_conf.dmc_fe_params.frequency / 1000);
370
    snprintf(buf, size, "%s kHz", freq);
371
  }
372
}
373

    
374

    
375
/**
376
 * 
377
 */
378
void
379
dvb_mux_nicename(char *buf, size_t size, th_dvb_mux_instance_t *tdmi)
380
{
381
  char freq[50];
382
  const char *n = tdmi->tdmi_network;
383

    
384
  if(tdmi->tdmi_adapter->tda_type == FE_QPSK) {
385
    nicenum(freq, sizeof(freq), tdmi->tdmi_conf.dmc_fe_params.frequency);
386
    snprintf(buf, size, "%s%s%s kHz %s (%s)", 
387
	     n?:"", n ? ": ":"", freq,
388
	     dvb_polarisation_to_str_long(tdmi->tdmi_conf.dmc_polarisation),
389
	     tdmi->tdmi_conf.dmc_satconf ? tdmi->tdmi_conf.dmc_satconf->sc_name : "No satconf");
390

    
391
  } else {
392
    nicenum(freq, sizeof(freq), tdmi->tdmi_conf.dmc_fe_params.frequency / 1000);
393
    snprintf(buf, size, "%s%s%s kHz", n?:"", n ? ": ":"", freq);
394
  }
395
}
396

    
(3-3/7)