Project

General

Profile

Bug #434 » dvb_support.c

i clean printf functions - bigtarget bigtarget, 2011-05-12 16:46

 
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
  if(srclen < 1) {
88
    *dst = 0;
89
    return 0;
90
  }
91
    
92
  switch(src[0]) {
93
  case 0:
94
    return -1;
95

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

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

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

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

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

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

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

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

    
144

    
145
  /* Escape control codes */
146

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

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

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

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

    
182
  len = dstlen - outlen - 1;
183
  dst[len] = 0;
184
  return 0;
185
}
186

    
187

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

    
194
  if(l + 1 > buflen)
195
    return -1;
196

    
197
  if(dvb_get_string(dst, dstlen, buf + 1, l, dvb_default_charset))
198
    return -1;
199

    
200
  return l + 1;
201
}
202

    
203

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

    
212
  for(i = 0; i < len; i++) {
213
    c = (src[i * 2 + 0] << 8) | src[i * 2 + 1];
214

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

    
224

    
225

    
226

    
227

    
228
/*
229
 * DVB time and date functions
230
 */
231

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

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

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

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

    
282

    
283
int
284
dvb_str_to_adaptertype(const char *str)
285
{
286
  return str2val(str, adaptertype);
287
}
288

    
289
const char *
290
dvb_adaptertype_to_str(int type)
291
{
292
  return val2str(type, adaptertype) ?: "invalid";
293
}
294

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

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

    
319

    
320
th_dvb_adapter_t *
321
dvb_adapter_find_by_identifier(const char *identifier)
322
{
323
  th_dvb_adapter_t *tda;
324

    
325
  TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link)
326
    if(!strcmp(identifier, tda->tda_identifier))
327
      return tda;
328
  return NULL;
329
}
330

    
331

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

    
352

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

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

    
371

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

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

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

    
(4-4/7)