Project

General

Profile

Feature #159 » tvheadend-irdeto-seca-emm.patch

Same patch with seca support and aligned coding conventions - sbi -, 2010-03-21 11:56

View differences:

src/cwc.c (working copy)
49 49
#define CWS_NETMSGSIZE 256
50 50
#define CWS_FIRSTCMDNO 0xe0
51 51

  
52
/**
53
 * cards for which emm updates are handled
54
 */
52 55
typedef enum {
56
  CARD_IRDETO,
57
  CARD_CONAX,
58
  CARD_SECA,
59
  CARD_UNKNOWN
60
} card_type_t;
61

  
62
typedef enum {
53 63
  MSG_CLIENT_2_SERVER_LOGIN = CWS_FIRSTCMDNO,
54 64
  MSG_CLIENT_2_SERVER_LOGIN_ACK,
55 65
  MSG_CLIENT_2_SERVER_LOGIN_NAK,
......
195 205
  /* Emm forwarding */
196 206
  int cwc_forward_emm;
197 207

  
208
  /* Card type */
209
  card_type_t cwc_card_type;
210
  
198 211
  /* From configuration */
199 212

  
200 213
  uint8_t cwc_confedkey[14];
......
221 234

  
222 235
static void cwc_transport_destroy(th_descrambler_t *td);
223 236
extern char *cwc_krypt(const char *key, const char *salt);
237
static void cwc_detect_card_type(cwc_t *cwc);
238
void cwc_emm_conax(cwc_t *cwc, uint8_t *data, int len);
239
void cwc_emm_irdeto(cwc_t *cwc, uint8_t *data, int len);
240
void cwc_emm_seca(cwc_t *cwc, uint8_t *data, int len);
224 241

  
225

  
226 242
/**
227 243
 *
228 244
 */
......
516 532
	 cwc->cwc_ua[0], cwc->cwc_ua[1], cwc->cwc_ua[2], cwc->cwc_ua[3], cwc->cwc_ua[4], cwc->cwc_ua[5], cwc->cwc_ua[6], cwc->cwc_ua[7],
517 533
	 nprov);
518 534

  
535
  cwc_detect_card_type(cwc);
536

  
519 537
  msg  += 15;
520 538
  plen -= 12;
521 539

  
......
557 575
    if (!emm_allowed)
558 576
      tvhlog(LOG_INFO, "cwc", "%s: Will not forward EMMs (not allowed by server)",
559 577
	     cwc->cwc_hostname);
560
    else if ((cwc->cwc_caid>>8) != 0x0b)
561
      tvhlog(LOG_INFO, "cwc", "%s: Will not forward EMMs (unsupported ca system)",
562
	     cwc->cwc_hostname);
563
    else {
578
    else if (cwc->cwc_card_type != CARD_UNKNOWN) {
564 579
      tvhlog(LOG_INFO, "cwc", "%s: Will forward EMMs",
565 580
	     cwc->cwc_hostname);
566 581
      cwc->cwc_forward_emm = 1;
567
    }
582
    } else
583
      tvhlog(LOG_INFO, "cwc", "%s: Will not forward EMMs (unsupported ca system)",
584
         cwc->cwc_hostname);
568 585
  }
569 586

  
570 587
  return 0;
571 588
}
572 589

  
590
/**
591
 * Detects the cam card type
592
 * If you want to add another card, have a look at
593
 * http://www.dvbservices.com/identifiers/ca_system_id?page=3
594
 * 
595
 * based on the equivalent in sasc-ng
596
 */
597
static void
598
cwc_detect_card_type(cwc_t *cwc)
599
{
600
  uint8_t c_sys = cwc->cwc_caid >> 8;
601
		
602
  switch (c_sys) {
603
  case 0x17:
604
  case 0x06: 
605
    cwc->cwc_card_type = CARD_IRDETO;
606
      tvhlog(LOG_INFO, "cwc", "%s: irdeto card",
607
        cwc->cwc_hostname);
608
      break;
609
  case 0x01:
610
    cwc->cwc_card_type = CARD_SECA;
611
    tvhlog(LOG_INFO, "cwc", "%s: seca card",
612
      cwc->cwc_hostname);
613
    break;
614
  case 0x0b:
615
    cwc->cwc_card_type = CARD_CONAX;
616
    tvhlog(LOG_INFO, "cwc", "%s: conax card",
617
      cwc->cwc_hostname);
618
    break;
619
  default:
620
    cwc->cwc_card_type = CARD_UNKNOWN;
621
    tvhlog(LOG_INFO, "cwc", "%s: unknown card",
622
      cwc->cwc_hostname);
623
  }
624
}
573 625

  
574 626
/**
575 627
 * Login command
......
1036 1088

  
1037 1089
  lock_assert(&global_lock);
1038 1090

  
1039
  TAILQ_FOREACH(cwc, &cwcs, cwc_link)
1040
    if(cwc->cwc_forward_emm && cwc->cwc_writer_running &&
1041
       data[0] == 0x82 /* Conax */ ) {
1042
      int i;
1043
      for (i=0; i < cwc->cwc_num_providers; i++)
1044
	if (memcmp(&data[3], &cwc->cwc_providers[i].sa[1], 7) == 0) {
1045
	  cwc_send_msg(cwc, data, len, 0, 1);
1046
	  break;
1047
	}
1091
  TAILQ_FOREACH(cwc, &cwcs, cwc_link) {
1092
    if(cwc->cwc_forward_emm && cwc->cwc_writer_running) {
1093
      switch (cwc->cwc_card_type) {
1094
      case CARD_CONAX:
1095
        cwc_emm_conax(cwc, data, len);
1096
        break;
1097
      case CARD_IRDETO:
1098
        cwc_emm_irdeto(cwc, data, len);
1099
        break;
1100
      case CARD_SECA:
1101
        cwc_emm_seca(cwc, data, len);
1102
        break;
1103
      case CARD_UNKNOWN:
1104
        break;
1105
      }
1048 1106
    }
1107
  }
1049 1108
}
1050 1109

  
1051 1110

  
1052 1111
/**
1112
 * conax emm handler
1113
 */
1114
void
1115
cwc_emm_conax(cwc_t *cwc, uint8_t *data, int len)
1116
{
1117
  if (data[0] == 0x82) {
1118
    int i;
1119
    for (i=0; i < cwc->cwc_num_providers; i++) {
1120
      if (memcmp(&data[3], &cwc->cwc_providers[i].sa[1], 7) == 0) {
1121
        cwc_send_msg(cwc, data, len, 0, 1);
1122
        break;
1123
      }
1124
    }
1125
  }
1126
}
1127

  
1128

  
1129
/**
1130
 * irdeto emm handler
1131
 * inspired by opensasc-ng, https://opensvn.csie.org/traccgi/opensascng/
1132
 */
1133
void
1134
cwc_emm_irdeto(cwc_t *cwc, uint8_t *data, int len)
1135
{
1136
  int emm_mode = data[3] >> 3;
1137
  int emm_len = data[3] & 0x07;
1138
  int match = 0;
1139
  
1140
  if (emm_mode & 0x10) {
1141
    // try to match card
1142
    match = (emm_mode == cwc->cwc_ua[4] && 
1143
      (!emm_len || // zero length
1144
      !memcmp(&data[4], &cwc->cwc_ua[5], emm_len))); // exact match
1145
  }
1146
  else {
1147
    // try to match provider
1148
    int i;
1149
    for(i=0; i < cwc->cwc_num_providers; i++) {
1150
      match = (emm_mode == cwc->cwc_providers[i].sa[4] && 
1151
        (!emm_len || // zero length
1152
        !memcmp(&data[4], &cwc->cwc_providers[i].sa[5], emm_len))); // exact match
1153
      if (match) break;
1154
    }
1155
  }
1156
  
1157
  if (match)
1158
    cwc_send_msg(cwc, data, len, 0, 1);
1159
}
1160

  
1161

  
1162
/**
1163
 * seca emm handler
1164
 * inspired by opensasc-ng, https://opensvn.csie.org/traccgi/opensascng/
1165
 */
1166
void
1167
cwc_emm_seca(cwc_t *cwc, uint8_t *data, int len)
1168
{
1169
  int match = 0;
1170

  
1171
  if (data[0] == 0x82) {
1172
    if (memcmp(&data[3], &cwc->cwc_ua[2], 6) == 0) {
1173
      match = 1;
1174
    }
1175
  } 
1176
  else if (data[0] == 0x84) {
1177
    /* XXX this part is untested */
1178
    int i;
1179
    for (i=0; i < cwc->cwc_num_providers; i++) {
1180
      if (memcmp(&data[5], &cwc->cwc_providers[i].sa[5], 3) == 0) {
1181
        match = 1;
1182
        break;
1183
      }
1184
    }
1185
  }
1186

  
1187
  if (match)
1188
    cwc_send_msg(cwc, data, len, 0, 1);
1189
}
1190

  
1191

  
1192
/**
1053 1193
 *
1054 1194
 */
1055 1195
static void
(3-3/3)