0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include <linux/dev_printk.h>
0023 #include <linux/ratelimit.h>
0024 #include <linux/slab.h>
0025 #include <linux/types.h>
0026
0027 #include "vidtv_channel.h"
0028 #include "vidtv_common.h"
0029 #include "vidtv_encoder.h"
0030 #include "vidtv_mux.h"
0031 #include "vidtv_psi.h"
0032 #include "vidtv_s302m.h"
0033
0034 static void vidtv_channel_encoder_destroy(struct vidtv_encoder *e)
0035 {
0036 struct vidtv_encoder *tmp = NULL;
0037 struct vidtv_encoder *curr = e;
0038
0039 while (curr) {
0040
0041 tmp = curr;
0042 curr = curr->next;
0043 tmp->destroy(tmp);
0044 }
0045 }
0046
0047 #define ENCODING_ISO8859_15 "\x0b"
0048 #define TS_NIT_PID 0x10
0049
0050
0051
0052
0053 struct vidtv_channel
0054 *vidtv_channel_s302m_init(struct vidtv_channel *head, u16 transport_stream_id)
0055 {
0056 const __be32 s302m_fid = cpu_to_be32(VIDTV_S302M_FORMAT_IDENTIFIER);
0057 char *event_text = ENCODING_ISO8859_15 "Bagatelle No. 25 in A minor for solo piano, also known as F\xfcr Elise, composed by Ludwig van Beethoven";
0058 char *event_name = ENCODING_ISO8859_15 "Ludwig van Beethoven: F\xfcr Elise";
0059 struct vidtv_s302m_encoder_init_args encoder_args = {};
0060 char *iso_language_code = ENCODING_ISO8859_15 "eng";
0061 char *provider = ENCODING_ISO8859_15 "LinuxTV.org";
0062 char *name = ENCODING_ISO8859_15 "Beethoven";
0063 const u16 s302m_es_pid = 0x111;
0064 const u16 s302m_program_pid = 0x101;
0065 const u16 s302m_service_id = 0x880;
0066 const u16 s302m_program_num = 0x880;
0067 const u16 s302m_beethoven_event_id = 1;
0068 struct vidtv_channel *s302m;
0069
0070 s302m = kzalloc(sizeof(*s302m), GFP_KERNEL);
0071 if (!s302m)
0072 return NULL;
0073
0074 s302m->name = kstrdup(name, GFP_KERNEL);
0075 if (!s302m->name)
0076 goto free_s302m;
0077
0078 s302m->service = vidtv_psi_sdt_service_init(NULL, s302m_service_id, false, true);
0079 if (!s302m->service)
0080 goto free_name;
0081
0082 s302m->service->descriptor = (struct vidtv_psi_desc *)
0083 vidtv_psi_service_desc_init(NULL,
0084 DIGITAL_RADIO_SOUND_SERVICE,
0085 name,
0086 provider);
0087 if (!s302m->service->descriptor)
0088 goto free_service;
0089
0090 s302m->transport_stream_id = transport_stream_id;
0091
0092 s302m->program = vidtv_psi_pat_program_init(NULL,
0093 s302m_service_id,
0094 s302m_program_pid);
0095 if (!s302m->program)
0096 goto free_service;
0097
0098 s302m->program_num = s302m_program_num;
0099
0100 s302m->streams = vidtv_psi_pmt_stream_init(NULL,
0101 STREAM_PRIVATE_DATA,
0102 s302m_es_pid);
0103 if (!s302m->streams)
0104 goto free_program;
0105
0106 s302m->streams->descriptor = (struct vidtv_psi_desc *)
0107 vidtv_psi_registration_desc_init(NULL,
0108 s302m_fid,
0109 NULL,
0110 0);
0111 if (!s302m->streams->descriptor)
0112 goto free_streams;
0113
0114 encoder_args.es_pid = s302m_es_pid;
0115
0116 s302m->encoders = vidtv_s302m_encoder_init(encoder_args);
0117 if (!s302m->encoders)
0118 goto free_streams;
0119
0120 s302m->events = vidtv_psi_eit_event_init(NULL, s302m_beethoven_event_id);
0121 if (!s302m->events)
0122 goto free_encoders;
0123 s302m->events->descriptor = (struct vidtv_psi_desc *)
0124 vidtv_psi_short_event_desc_init(NULL,
0125 iso_language_code,
0126 event_name,
0127 event_text);
0128 if (!s302m->events->descriptor)
0129 goto free_events;
0130
0131 if (head) {
0132 while (head->next)
0133 head = head->next;
0134
0135 head->next = s302m;
0136 }
0137
0138 return s302m;
0139
0140 free_events:
0141 vidtv_psi_eit_event_destroy(s302m->events);
0142 free_encoders:
0143 vidtv_s302m_encoder_destroy(s302m->encoders);
0144 free_streams:
0145 vidtv_psi_pmt_stream_destroy(s302m->streams);
0146 free_program:
0147 vidtv_psi_pat_program_destroy(s302m->program);
0148 free_service:
0149 vidtv_psi_sdt_service_destroy(s302m->service);
0150 free_name:
0151 kfree(s302m->name);
0152 free_s302m:
0153 kfree(s302m);
0154
0155 return NULL;
0156 }
0157
0158 static struct vidtv_psi_table_eit_event
0159 *vidtv_channel_eit_event_cat_into_new(struct vidtv_mux *m)
0160 {
0161
0162 const struct vidtv_channel *cur_chnl = m->channels;
0163 struct vidtv_psi_table_eit_event *curr = NULL;
0164 struct vidtv_psi_table_eit_event *head = NULL;
0165 struct vidtv_psi_table_eit_event *tail = NULL;
0166 struct vidtv_psi_desc *desc = NULL;
0167 u16 event_id;
0168
0169 if (!cur_chnl)
0170 return NULL;
0171
0172 while (cur_chnl) {
0173 curr = cur_chnl->events;
0174
0175 if (!curr)
0176 dev_warn_ratelimited(m->dev,
0177 "No events found for channel %s\n",
0178 cur_chnl->name);
0179
0180 while (curr) {
0181 event_id = be16_to_cpu(curr->event_id);
0182 tail = vidtv_psi_eit_event_init(tail, event_id);
0183 if (!tail) {
0184 vidtv_psi_eit_event_destroy(head);
0185 return NULL;
0186 }
0187
0188 desc = vidtv_psi_desc_clone(curr->descriptor);
0189 vidtv_psi_desc_assign(&tail->descriptor, desc);
0190
0191 if (!head)
0192 head = tail;
0193
0194 curr = curr->next;
0195 }
0196
0197 cur_chnl = cur_chnl->next;
0198 }
0199
0200 return head;
0201 }
0202
0203 static struct vidtv_psi_table_sdt_service
0204 *vidtv_channel_sdt_serv_cat_into_new(struct vidtv_mux *m)
0205 {
0206
0207 const struct vidtv_channel *cur_chnl = m->channels;
0208
0209 struct vidtv_psi_table_sdt_service *curr = NULL;
0210 struct vidtv_psi_table_sdt_service *head = NULL;
0211 struct vidtv_psi_table_sdt_service *tail = NULL;
0212
0213 struct vidtv_psi_desc *desc = NULL;
0214 u16 service_id;
0215
0216 if (!cur_chnl)
0217 return NULL;
0218
0219 while (cur_chnl) {
0220 curr = cur_chnl->service;
0221
0222 if (!curr)
0223 dev_warn_ratelimited(m->dev,
0224 "No services found for channel %s\n",
0225 cur_chnl->name);
0226
0227 while (curr) {
0228 service_id = be16_to_cpu(curr->service_id);
0229 tail = vidtv_psi_sdt_service_init(tail,
0230 service_id,
0231 curr->EIT_schedule,
0232 curr->EIT_present_following);
0233 if (!tail)
0234 goto free;
0235
0236 desc = vidtv_psi_desc_clone(curr->descriptor);
0237 if (!desc)
0238 goto free_tail;
0239 vidtv_psi_desc_assign(&tail->descriptor, desc);
0240
0241 if (!head)
0242 head = tail;
0243
0244 curr = curr->next;
0245 }
0246
0247 cur_chnl = cur_chnl->next;
0248 }
0249
0250 return head;
0251
0252 free_tail:
0253 vidtv_psi_sdt_service_destroy(tail);
0254 free:
0255 vidtv_psi_sdt_service_destroy(head);
0256 return NULL;
0257 }
0258
0259 static struct vidtv_psi_table_pat_program*
0260 vidtv_channel_pat_prog_cat_into_new(struct vidtv_mux *m)
0261 {
0262
0263 const struct vidtv_channel *cur_chnl = m->channels;
0264 struct vidtv_psi_table_pat_program *curr = NULL;
0265 struct vidtv_psi_table_pat_program *head = NULL;
0266 struct vidtv_psi_table_pat_program *tail = NULL;
0267 u16 serv_id;
0268 u16 pid;
0269
0270 if (!cur_chnl)
0271 return NULL;
0272
0273 while (cur_chnl) {
0274 curr = cur_chnl->program;
0275
0276 if (!curr)
0277 dev_warn_ratelimited(m->dev,
0278 "No programs found for channel %s\n",
0279 cur_chnl->name);
0280
0281 while (curr) {
0282 serv_id = be16_to_cpu(curr->service_id);
0283 pid = vidtv_psi_get_pat_program_pid(curr);
0284 tail = vidtv_psi_pat_program_init(tail,
0285 serv_id,
0286 pid);
0287 if (!tail) {
0288 vidtv_psi_pat_program_destroy(head);
0289 return NULL;
0290 }
0291
0292 if (!head)
0293 head = tail;
0294
0295 curr = curr->next;
0296 }
0297
0298 cur_chnl = cur_chnl->next;
0299 }
0300
0301 vidtv_psi_pat_program_init(tail, 0, TS_NIT_PID);
0302
0303 return head;
0304 }
0305
0306
0307
0308
0309
0310 static void
0311 vidtv_channel_pmt_match_sections(struct vidtv_channel *channels,
0312 struct vidtv_psi_table_pmt **sections,
0313 u32 nsections)
0314 {
0315 struct vidtv_psi_table_pmt *curr_section = NULL;
0316 struct vidtv_psi_table_pmt_stream *head = NULL;
0317 struct vidtv_psi_table_pmt_stream *tail = NULL;
0318 struct vidtv_psi_table_pmt_stream *s = NULL;
0319 struct vidtv_channel *cur_chnl = channels;
0320 struct vidtv_psi_desc *desc = NULL;
0321 u16 e_pid;
0322 u16 curr_id;
0323 u32 j;
0324
0325 while (cur_chnl) {
0326 for (j = 0; j < nsections; ++j) {
0327 curr_section = sections[j];
0328
0329 if (!curr_section)
0330 continue;
0331
0332 curr_id = be16_to_cpu(curr_section->header.id);
0333
0334
0335 if (curr_id == cur_chnl->program_num) {
0336 s = cur_chnl->streams;
0337
0338
0339 while (s) {
0340 e_pid = vidtv_psi_pmt_stream_get_elem_pid(s);
0341 tail = vidtv_psi_pmt_stream_init(tail,
0342 s->type,
0343 e_pid);
0344
0345 if (!head)
0346 head = tail;
0347
0348 desc = vidtv_psi_desc_clone(s->descriptor);
0349 vidtv_psi_desc_assign(&tail->descriptor,
0350 desc);
0351
0352 s = s->next;
0353 }
0354
0355 vidtv_psi_pmt_stream_assign(curr_section, head);
0356 break;
0357 }
0358 }
0359
0360 cur_chnl = cur_chnl->next;
0361 }
0362 }
0363
0364 static void
0365 vidtv_channel_destroy_service_list(struct vidtv_psi_desc_service_list_entry *e)
0366 {
0367 struct vidtv_psi_desc_service_list_entry *tmp;
0368
0369 while (e) {
0370 tmp = e;
0371 e = e->next;
0372 kfree(tmp);
0373 }
0374 }
0375
0376 static struct vidtv_psi_desc_service_list_entry
0377 *vidtv_channel_build_service_list(struct vidtv_psi_table_sdt_service *s)
0378 {
0379 struct vidtv_psi_desc_service_list_entry *curr_e = NULL;
0380 struct vidtv_psi_desc_service_list_entry *head_e = NULL;
0381 struct vidtv_psi_desc_service_list_entry *prev_e = NULL;
0382 struct vidtv_psi_desc *desc = s->descriptor;
0383 struct vidtv_psi_desc_service *s_desc;
0384
0385 while (s) {
0386 while (desc) {
0387 if (s->descriptor->type != SERVICE_DESCRIPTOR)
0388 goto next_desc;
0389
0390 s_desc = (struct vidtv_psi_desc_service *)desc;
0391
0392 curr_e = kzalloc(sizeof(*curr_e), GFP_KERNEL);
0393 if (!curr_e) {
0394 vidtv_channel_destroy_service_list(head_e);
0395 return NULL;
0396 }
0397
0398 curr_e->service_id = s->service_id;
0399 curr_e->service_type = s_desc->service_type;
0400
0401 if (!head_e)
0402 head_e = curr_e;
0403 if (prev_e)
0404 prev_e->next = curr_e;
0405
0406 prev_e = curr_e;
0407
0408 next_desc:
0409 desc = desc->next;
0410 }
0411 s = s->next;
0412 }
0413 return head_e;
0414 }
0415
0416 int vidtv_channel_si_init(struct vidtv_mux *m)
0417 {
0418 struct vidtv_psi_desc_service_list_entry *service_list = NULL;
0419 struct vidtv_psi_table_pat_program *programs = NULL;
0420 struct vidtv_psi_table_sdt_service *services = NULL;
0421 struct vidtv_psi_table_eit_event *events = NULL;
0422
0423 m->si.pat = vidtv_psi_pat_table_init(m->transport_stream_id);
0424 if (!m->si.pat)
0425 return -ENOMEM;
0426
0427 m->si.sdt = vidtv_psi_sdt_table_init(m->network_id,
0428 m->transport_stream_id);
0429 if (!m->si.sdt)
0430 goto free_pat;
0431
0432 programs = vidtv_channel_pat_prog_cat_into_new(m);
0433 if (!programs)
0434 goto free_sdt;
0435 services = vidtv_channel_sdt_serv_cat_into_new(m);
0436 if (!services)
0437 goto free_programs;
0438
0439 events = vidtv_channel_eit_event_cat_into_new(m);
0440 if (!events)
0441 goto free_services;
0442
0443
0444 service_list = vidtv_channel_build_service_list(services);
0445 if (!service_list)
0446 goto free_events;
0447
0448
0449 m->si.nit = vidtv_psi_nit_table_init(m->network_id,
0450 m->transport_stream_id,
0451 m->network_name,
0452 service_list);
0453 if (!m->si.nit)
0454 goto free_service_list;
0455
0456 m->si.eit = vidtv_psi_eit_table_init(m->network_id,
0457 m->transport_stream_id,
0458 programs->service_id);
0459 if (!m->si.eit)
0460 goto free_nit;
0461
0462
0463 vidtv_psi_pat_program_assign(m->si.pat, programs);
0464
0465
0466 vidtv_psi_sdt_service_assign(m->si.sdt, services);
0467
0468
0469 vidtv_psi_eit_event_assign(m->si.eit, events);
0470
0471 m->si.pmt_secs = vidtv_psi_pmt_create_sec_for_each_pat_entry(m->si.pat,
0472 m->pcr_pid);
0473 if (!m->si.pmt_secs)
0474 goto free_eit;
0475
0476 vidtv_channel_pmt_match_sections(m->channels,
0477 m->si.pmt_secs,
0478 m->si.pat->num_pmt);
0479
0480 vidtv_channel_destroy_service_list(service_list);
0481
0482 return 0;
0483
0484 free_eit:
0485 vidtv_psi_eit_table_destroy(m->si.eit);
0486 free_nit:
0487 vidtv_psi_nit_table_destroy(m->si.nit);
0488 free_service_list:
0489 vidtv_channel_destroy_service_list(service_list);
0490 free_events:
0491 vidtv_psi_eit_event_destroy(events);
0492 free_services:
0493 vidtv_psi_sdt_service_destroy(services);
0494 free_programs:
0495 vidtv_psi_pat_program_destroy(programs);
0496 free_sdt:
0497 vidtv_psi_sdt_table_destroy(m->si.sdt);
0498 free_pat:
0499 vidtv_psi_pat_table_destroy(m->si.pat);
0500 return 0;
0501 }
0502
0503 void vidtv_channel_si_destroy(struct vidtv_mux *m)
0504 {
0505 u32 i;
0506
0507 for (i = 0; i < m->si.pat->num_pmt; ++i)
0508 vidtv_psi_pmt_table_destroy(m->si.pmt_secs[i]);
0509
0510 vidtv_psi_pat_table_destroy(m->si.pat);
0511
0512 kfree(m->si.pmt_secs);
0513 vidtv_psi_sdt_table_destroy(m->si.sdt);
0514 vidtv_psi_nit_table_destroy(m->si.nit);
0515 vidtv_psi_eit_table_destroy(m->si.eit);
0516 }
0517
0518 int vidtv_channels_init(struct vidtv_mux *m)
0519 {
0520
0521 m->channels = vidtv_channel_s302m_init(NULL, m->transport_stream_id);
0522
0523 if (!m->channels)
0524 return -ENOMEM;
0525
0526 return 0;
0527 }
0528
0529 void vidtv_channels_destroy(struct vidtv_mux *m)
0530 {
0531 struct vidtv_channel *curr = m->channels;
0532 struct vidtv_channel *tmp = NULL;
0533
0534 while (curr) {
0535 kfree(curr->name);
0536 vidtv_psi_sdt_service_destroy(curr->service);
0537 vidtv_psi_pat_program_destroy(curr->program);
0538 vidtv_psi_pmt_stream_destroy(curr->streams);
0539 vidtv_channel_encoder_destroy(curr->encoders);
0540 vidtv_psi_eit_event_destroy(curr->events);
0541
0542 tmp = curr;
0543 curr = curr->next;
0544 kfree(tmp);
0545 }
0546 }