12 #include <linux/dvb/ca.h>
14 #include <netinet/in.h>
18 #include <sys/ioctl.h>
36 #define dbgprotocol(a...) do { if (DebugProtocol) fprintf(stderr, a); } while (0)
40 #define SIZE_INDICATOR 0x80
42 static const uint8_t *
GetLength(
const uint8_t *Data,
int &Length)
51 for (
int i = 0; i < l; i++)
52 Length = (Length << 8) | *Data++;
57 static uint8_t *
SetLength(uint8_t *Data,
int Length)
65 int n =
sizeof(Length);
66 for (
int i = n - 1; i >= 0; i--) {
67 int b = (Length >> (8 * i)) & 0xFF;
81 char *s =
MALLOC(
char, Length + 1);
96 static char *
GetString(
int &Length,
const uint8_t **Data)
101 if (Length > 0 && Data && *Data) {
105 Length -= d - *Data + l;
123 #define CAT_MAXPACKETS 6
188 const uchar *p = NULL;
191 length = (int(Data[6] & 0x0F) << 8) | Data[7];
193 int v = (Data[10] & 0x3E) >> 1;
195 if (Data[11] == 0 && Data[12] == 0) {
199 memcpy(
buffer, Data + 5, n);
212 dsyslog(
"multi table CAT section - unhandled!");
215 else if (MtdCamSlot) {
225 memcpy(
bufp, Data + 4, n);
236 esyslog(
"ERROR: buffer overflow in cCaPidReceiver::Receive()");
244 for (
int i = 8; i <
length - 4; i++) {
246 int CaId = int(p[i + 2] << 8) | p[i + 3];
247 int EmmPid =
Peek13(p + i + 4);
252 case 0x01:
for (
int j = i + 7; j < i + p[i + 1] + 2; j += 4) {
260 i += p[i + 1] + 2 - 1;
283 esyslog(
"ERROR: wrong checksum in CAT");
304 #define UNSCRAMBLE_TIME 5
305 #define TS_PACKET_FACTOR 1024
335 time_t Now = time(NULL);
345 s->CancelActivation();
356 #define CRA_DISCARD -1
357 #define CRA_CONFIRM -2
358 #define CRA_SELECT -3
368 bool Parse(
const char *s);
369 int Matches(
int CamNumber,
const char *Text)
const;
401 char *t =
const_cast<char *
>(s);
403 bool InQuotes =
false;
413 else if (*t ==
'\\') {
419 memmove(t, t + 1, strlen(t));
421 else if (*t ==
' ') {
430 text = strndup(s, t - s);
450 if (strcmp(
text, Text) == 0)
460 int GetMatch(
int CamNumber,
const char *Text)
const;
466 int Action = cr->Matches(CamNumber, Text);
468 dsyslog(
"CAM %d: auto response %4d to '%s'\n", CamNumber, Action, Text);
484 #define MAX_TPDU_SIZE 4096
485 #define MAX_TPDU_DATA (MAX_TPDU_SIZE - 4)
487 #define DATA_INDICATOR 0x80
491 #define T_CREATE_TC 0x82
492 #define T_CTC_REPLY 0x83
493 #define T_DELETE_TC 0x84
494 #define T_DTC_REPLY 0x85
495 #define T_REQUEST_TC 0x86
496 #define T_NEW_TC 0x87
497 #define T_TC_ERROR 0x88
498 #define T_DATA_LAST 0xA0
499 #define T_DATA_MORE 0xA1
505 const uint8_t *
GetData(
const uint8_t *
Data,
int &Length);
518 void Dump(
int SlotNumber,
bool Outgoing);
521 cTPDU::cTPDU(uint8_t Slot, uint8_t Tcid, uint8_t Tag,
int Length,
const uint8_t *Data)
547 esyslog(
"ERROR: invalid data length for TPDU tag 0x%02X: %d (%d/%d)",
Tag, Length,
Slot,
Tcid);
556 memcpy(p,
Data, Length);
560 esyslog(
"ERROR: invalid data length for TPDU tag 0x%02X: %d (%d/%d)",
Tag, Length,
Slot,
Tcid);
571 fprintf(stderr,
" %d: %s ", SlotNumber, Outgoing ?
"-->" :
"<--");
573 fprintf(stderr,
"%02X ",
buffer[i]);
576 fprintf(stderr,
" ");
578 fprintf(stderr,
"%2c ", isprint(
buffer[i]) ?
buffer[i] :
'.');
605 #define MAX_SESSIONS_PER_TC 16
621 void SendTPDU(uint8_t Tag,
int Length = 0,
const uint8_t *Data = NULL);
622 void SendTag(uint8_t Tag, uint16_t SessionId, uint32_t ResourceId = 0,
int Status = -1);
641 void SendData(
int Length,
const uint8_t *Data);
650 #define ST_SESSION_NUMBER 0x90
651 #define ST_OPEN_SESSION_REQUEST 0x91
652 #define ST_OPEN_SESSION_RESPONSE 0x92
653 #define ST_CREATE_SESSION 0x93
654 #define ST_CREATE_SESSION_RESPONSE 0x94
655 #define ST_CLOSE_SESSION_REQUEST 0x95
656 #define ST_CLOSE_SESSION_RESPONSE 0x96
661 #define SS_NOT_ALLOCATED 0xF0
665 #define RI_RESOURCE_MANAGER 0x00010041
666 #define RI_APPLICATION_INFORMATION 0x00020041
667 #define RI_CONDITIONAL_ACCESS_SUPPORT 0x00030041
668 #define RI_HOST_CONTROL 0x00200041
669 #define RI_DATE_TIME 0x00240041
670 #define RI_MMI 0x00400041
674 #define AOT_NONE 0x000000
675 #define AOT_PROFILE_ENQ 0x9F8010
676 #define AOT_PROFILE 0x9F8011
677 #define AOT_PROFILE_CHANGE 0x9F8012
678 #define AOT_APPLICATION_INFO_ENQ 0x9F8020
679 #define AOT_APPLICATION_INFO 0x9F8021
680 #define AOT_ENTER_MENU 0x9F8022
681 #define AOT_CA_INFO_ENQ 0x9F8030
682 #define AOT_CA_INFO 0x9F8031
683 #define AOT_CA_PMT 0x9F8032
684 #define AOT_CA_PMT_REPLY 0x9F8033
685 #define AOT_TUNE 0x9F8400
686 #define AOT_REPLACE 0x9F8401
687 #define AOT_CLEAR_REPLACE 0x9F8402
688 #define AOT_ASK_RELEASE 0x9F8403
689 #define AOT_DATE_TIME_ENQ 0x9F8440
690 #define AOT_DATE_TIME 0x9F8441
691 #define AOT_CLOSE_MMI 0x9F8800
692 #define AOT_DISPLAY_CONTROL 0x9F8801
693 #define AOT_DISPLAY_REPLY 0x9F8802
694 #define AOT_TEXT_LAST 0x9F8803
695 #define AOT_TEXT_MORE 0x9F8804
696 #define AOT_KEYPAD_CONTROL 0x9F8805
697 #define AOT_KEYPRESS 0x9F8806
698 #define AOT_ENQ 0x9F8807
699 #define AOT_ANSW 0x9F8808
700 #define AOT_MENU_LAST 0x9F8809
701 #define AOT_MENU_MORE 0x9F880A
702 #define AOT_MENU_ANSW 0x9F880B
703 #define AOT_LIST_LAST 0x9F880C
704 #define AOT_LIST_MORE 0x9F880D
705 #define AOT_SUBTITLE_SEGMENT_LAST 0x9F880E
706 #define AOT_SUBTITLE_SEGMENT_MORE 0x9F880F
707 #define AOT_DISPLAY_MESSAGE 0x9F8810
708 #define AOT_SCENE_END_MARK 0x9F8811
709 #define AOT_SCENE_DONE 0x9F8812
710 #define AOT_SCENE_CONTROL 0x9F8813
711 #define AOT_SUBTITLE_DOWNLOAD_LAST 0x9F8814
712 #define AOT_SUBTITLE_DOWNLOAD_MORE 0x9F8815
713 #define AOT_FLUSH_DOWNLOAD 0x9F8816
714 #define AOT_DOWNLOAD_REPLY 0x9F8817
715 #define AOT_COMMS_CMD 0x9F8C00
716 #define AOT_CONNECTION_DESCRIPTOR 0x9F8C01
717 #define AOT_COMMS_REPLY 0x9F8C02
718 #define AOT_COMMS_SEND_LAST 0x9F8C03
719 #define AOT_COMMS_SEND_MORE 0x9F8C04
720 #define AOT_COMMS_RCV_LAST 0x9F8C05
721 #define AOT_COMMS_RCV_MORE 0x9F8C06
723 #define RESOURCE_CLASS_MASK 0xFFFF0000
751 if (Length >= 3 && Data && *Data) {
753 for (
int i = 0; i < 3; i++)
754 t = (t << 8) | *(*Data)++;
764 return Length ? Data : NULL;
775 *p++ = (Tag >> 16) & 0xFF;
776 *p++ = (Tag >> 8) & 0xFF;
779 if (p - buffer + Length <
int(
sizeof(buffer))) {
781 memcpy(p, Data, Length);
786 esyslog(
"ERROR: CAM %d: data length (%d) exceeds buffer size",
CamSlot()->SlotNumber(), Length);
805 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
818 int Tag =
GetTag(Length, &Data);
831 const uint8_t *d =
GetData(Data, l);
833 esyslog(
"ERROR: CAM %d: resource manager: unexpected data",
CamSlot()->SlotNumber());
839 esyslog(
"ERROR: CAM %d: resource manager: unexpected tag %06X in state %d",
CamSlot()->SlotNumber(), Tag,
state);
843 default:
esyslog(
"ERROR: CAM %d: resource manager: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
846 else if (
state == 0) {
871 int Tag =
GetTag(Length, &Data);
876 const uint8_t *d =
GetData(Data, l);
877 if ((l -= 1) < 0)
break;
879 if ((l -= 2) < 0)
break;
882 if ((l -= 2) < 0)
break;
891 default:
esyslog(
"ERROR: CAM %d: application information: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
894 else if (
state == 0) {
913 #define MAXCASYSTEMIDS 64
917 #define CPLM_MORE 0x00
918 #define CPLM_FIRST 0x01
919 #define CPLM_LAST 0x02
920 #define CPLM_ONLY 0x03
921 #define CPLM_ADD 0x04
922 #define CPLM_UPDATE 0x05
926 #define CPCI_OK_DESCRAMBLING 0x01
927 #define CPCI_OK_MMI 0x02
928 #define CPCI_QUERY 0x03
929 #define CPCI_NOT_SELECTED 0x04
944 cCiCaPmt(uint8_t
CmdId,
int Source,
int Transponder,
int ProgramNumber,
const int *CaSystemIds);
948 void AddPid(
int Pid, uint8_t StreamType);
952 cCiCaPmt::cCiCaPmt(uint8_t CmdId,
int Source,
int Transponder,
int ProgramNumber,
const int *CaSystemIds)
960 for (; CaSystemIds[i]; i++)
1007 esyslog(
"ERROR: adding CA descriptor without Pid!");
1020 esyslog(
"ERROR: wrong length (%d) in MtdMapCaDescriptor()", l);
1023 esyslog(
"ERROR: wrong tag (%d) in MtdMapCaDescriptor()", *p);
1029 int Length = p[0] * 256 + p[1];
1092 #define CAEI_POSSIBLE 0x01
1093 #define CAEI_POSSIBLE_COND_PURCHASE 0x02
1094 #define CAEI_POSSIBLE_COND_TECHNICAL 0x03
1095 #define CAEI_NOT_POSSIBLE_ENTITLEMENT 0x71
1096 #define CAEI_NOT_POSSIBLE_TECHNICAL 0x73
1098 #define CA_ENABLE_FLAG 0x80
1100 #define CA_ENABLE(x) (((x) & CA_ENABLE_FLAG) ? (x) & ~CA_ENABLE_FLAG : 0)
1102 #define QUERY_WAIT_TIME 500
1103 #define QUERY_REPLY_TIMEOUT 2000
1104 #define QUERY_RETRIES 6
1116 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
1138 int Tag =
GetTag(Length, &Data);
1145 const uint8_t *d =
GetData(Data, l);
1147 uint16_t
id = ((uint16_t)(*d) << 8) | *(d + 1);
1155 esyslog(
"ERROR: CAM %d: too many CA system IDs!",
CamSlot()->SlotNumber());
1166 dsyslog(
"CAM %d: system ids:%s",
CamSlot()->SlotNumber(), *Ids ? *Ids :
" none");
1172 if (
CamSlot()->IsMasterSlot())
1173 dsyslog(
"CAM %d: replies to QUERY - multi channel decryption (MCD) possible",
CamSlot()->SlotNumber());
1175 if (
CamSlot()->MtdAvailable()) {
1176 if (
CamSlot()->IsMasterSlot())
1177 dsyslog(
"CAM %d: supports multi transponder decryption (MTD)",
CamSlot()->SlotNumber());
1183 const uint8_t *d =
GetData(Data, l);
1185 uint16_t pnr = ((uint16_t)(*d) << 8) | *(d + 1);
1194 if (l % 3 == 0 && l > 1) {
1200 uint16_t len = ((uint16_t)(*d) << 8) | *(d + 1);
1206 unsigned char caepl = *d;
1214 uint16_t pid = ((uint16_t)(*d) << 8) | *(d + 1);
1215 unsigned char caees = *(d + 2);
1230 default:
esyslog(
"ERROR: CAM %d: conditional access support: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
1233 else if (
state == 0) {
1246 dsyslog(
"CAM %d: doesn't reply to QUERY - only a single channel can be decrypted",
CamSlot()->SlotNumber());
1255 if (CaPmt &&
state >= 2) {
1267 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
1279 int Tag =
GetTag(Length, &Data);
1290 default:
esyslog(
"ERROR: CAM %d: Host Control: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
1304 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
1317 time_t t = time(NULL);
1320 if (gmtime_r(&t, &tm_gmt) && localtime_r(&t, &tm_loc)) {
1321 int Y = tm_gmt.tm_year;
1322 int M = tm_gmt.tm_mon + 1;
1323 int D = tm_gmt.tm_mday;
1324 int L = (M == 1 || M == 2) ? 1 : 0;
1325 int MJD = 14956 + D + int((Y - L) * 365.25) + int((M + 1 + L * 12) * 30.6001);
1326 #define DEC2BCD(d) uint8_t(((d / 10) << 4) + (d % 10))
1328 struct tTime { uint16_t mjd; uint8_t h, m, s;
short offset; };
1330 tTime T = { mjd : htons(MJD), h :
DEC2BCD(tm_gmt.tm_hour), m :
DEC2BCD(tm_gmt.tm_min), s :
DEC2BCD(tm_gmt.tm_sec), offset : short(htons(tm_loc.tm_gmtoff / 60)) };
1343 int Tag =
GetTag(Length, &Data);
1348 const uint8_t *d =
GetData(Data, l);
1356 default:
esyslog(
"ERROR: CAM %d: date time: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
1369 #define DCC_SET_MMI_MODE 0x01
1370 #define DCC_DISPLAY_CHARACTER_TABLE_LIST 0x02
1371 #define DCC_INPUT_CHARACTER_TABLE_LIST 0x03
1372 #define DCC_OVERLAY_GRAPHICS_CHARACTERISTICS 0x04
1373 #define DCC_FULL_SCREEN_GRAPHICS_CHARACTERISTICS 0x05
1377 #define MM_HIGH_LEVEL 0x01
1378 #define MM_LOW_LEVEL_OVERLAY_GRAPHICS 0x02
1379 #define MM_LOW_LEVEL_FULL_SCREEN_GRAPHICS 0x03
1383 #define DRI_MMI_MODE_ACK 0x01
1384 #define DRI_LIST_DISPLAY_CHARACTER_TABLES 0x02
1385 #define DRI_LIST_INPUT_CHARACTER_TABLES 0x03
1386 #define DRI_LIST_GRAPHIC_OVERLAY_CHARACTERISTICS 0x04
1387 #define DRI_LIST_FULL_SCREEN_GRAPHIC_CHARACTERISTICS 0x05
1388 #define DRI_UNKNOWN_DISPLAY_CONTROL_CMD 0xF0
1389 #define DRI_UNKNOWN_MMI_MODE 0xF1
1390 #define DRI_UNKNOWN_CHARACTER_TABLE 0xF2
1394 #define EF_BLIND 0x01
1398 #define AI_CANCEL 0x00
1399 #define AI_ANSWER 0x01
1403 char *
GetText(
int &Length,
const uint8_t **Data);
1409 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
1445 int Tag =
GetTag(Length, Data);
1452 esyslog(
"ERROR: CAM %d: MMI: unexpected text tag: %06X",
CamSlot()->SlotNumber(), Tag);
1459 int Tag =
GetTag(Length, &Data);
1464 const uint8_t *d =
GetData(Data, l);
1469 struct tDisplayReply { uint8_t id; uint8_t mode; };
1475 default:
esyslog(
"ERROR: CAM %d: MMI: unsupported display control command %02X",
CamSlot()->SlotNumber(), *d);
1486 const uint8_t *d =
GetData(Data, l);
1526 dsyslog(
"CAM %d: SELECT %d",
CamSlot()->SlotNumber(), Select + 1);
1537 const uint8_t *d =
GetData(Data, l);
1539 uint8_t blind = *d++;
1550 snprintf(s,
sizeof(s),
"%d", Action);
1567 const uint8_t *d =
GetData(Data, l);
1576 default:
esyslog(
"ERROR: CAM %d: MMI: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
1612 struct tAnswer { uint8_t id;
char text[256]; };
1617 len =
min(
sizeof(answer.text), strlen(Text));
1618 memcpy(answer.text, Text, len);
1746 static uint32_t Ids[] = {
1760 switch (ResourceId) {
1767 default:
return NULL;
1782 if (ResourceHandler) {
1783 Add(ResourceHandler);
1784 if (
const uint32_t *r = ResourceHandler->
ResourceIds()) {
1796 if (
cCiSession *CiSession = r->GetNewCiSession(ResourceId, SessionId, Tc))
1804 #define TC_POLL_TIMEOUT 300
1805 #define TC_ALIVE_TIMEOUT 2000
1844 return cas && cas->
Ready();
1870 uint8_t *p = buffer;
1881 buffer[1] = p - buffer - 2;
1910 if (s->ResourceId() == ResourceId)
1921 if (Length == 6 && *(Data + 1) == 0x04) {
1946 if (Session &&
sessions[SessionId] == Session) {
1960 const uint8_t *Data = TPDU->
Data(Length);
1961 if (Data && Length > 1) {
1964 uint16_t SessionId = ntohs(
get_unaligned((uint16_t *)&Data[2]));
1967 Session->
Process(Length - 4, Data + 4);
2019 switch (TPDU->
Tag()) {
2046 esyslog(
"ERROR: unknown TPDU tag: 0x%02X (%s)", TPDU->
Tag(), __FUNCTION__);
2067 esyslog(
"ERROR: unknown state: %d (%s)",
state, __FUNCTION__);
2135 esyslog(
"ERROR: no free CAM slot in CI adapter");
2171 #define MODULE_CHECK_INTERVAL 500
2172 #define MODULE_RESET_TIMEOUT 2
2223 int OldDeviceNumber = 0;
2265 return DeviceNumbers.
Size() > 0;
2294 int n = TPDU->
Tcid();
2339 esyslog(
"ERROR: unknown module status %d (%s)", ms, __FUNCTION__);
2403 dsyslog(
"CAM %d: activating on device %d with channel %d (%s)",
SlotNumber(), d->DeviceNumber() + 1, Channel->Number(), Channel->Name());
2505 cCiCaPmt *p =
new cCiCaPmt(CmdId, Source, Transponder, ProgramNumber, CaSystemIds);
2528 if (CaSystemIds && *CaSystemIds) {
2532 bool Active = p->Active();
2536 CaPmt->
AddPid(q->pid, q->streamType);
2553 p->modified =
false;
2558 CaPmtList.
Add(CmdId, 0, 0, 0, NULL);
2565 int *pCaPids = CaPids;
2576 int *pCaPids2 = CaPids2;
2580 if (*pCaPids == *pCaPids2) {
2583 *pCaPids = CaPids[numPids - 1];
2585 CaPids[numPids] = 0;
2604 for (
int i = 0; i < CaPmtList.
caPmts.
Size(); i++)
2665 for (
const int *ids = cas->
GetCaSystemIds(); ids && *ids; ids++) {
2666 for (
const int *
id = CaSystemIds; *id;
id++) {
2680 if (p->programNumber == ProgramNumber) {
2700 if (q->pid == Pid) {
2701 if (q->active != Active) {
2712 #define STREAM_TYPE_VIDEO 0x02
2713 #define STREAM_TYPE_AUDIO 0x04
2714 #define STREAM_TYPE_PRIVATE 0x06
2725 for (
const int *Apid = Channel->
Apids(); *Apid; Apid++)
2727 for (
const int *Dpid = Channel->
Dpids(); *Dpid; Dpid++)
2729 for (
const int *Spid = Channel->
Spids(); *Spid; Spid++)
2734 #define QUERY_REPLY_WAIT 100
2748 for (
const int *Apid = Channel->
Apids(); *Apid; Apid++)
2750 for (
const int *Dpid = Channel->
Dpids(); *Dpid; Dpid++)
2752 for (
const int *Spid = Channel->
Spids(); *Spid; Spid++)
2840 if (CamSlot->IsMasterSlot() && CamSlot->ModuleStatus() ==
msReady)
2849 for (time_t t0 = time(NULL); time(NULL) - t0 < Timeout; ) {
2852 if (!CamSlot->Ready()) {
2861 dsyslog(
"CAM %d: %sready, %s", CamSlot->SlotNumber(), CamSlot->Ready() ?
"" :
"not ", CamSlot->IsMasterSlot() ? *
cString::sprintf(
"master (%s)", CamSlot->GetCamName() ? CamSlot->GetCamName() :
"empty") : *
cString::sprintf(
"slave of CAM %d", CamSlot->MasterSlotNumber()));
2867 #define CAM_CHECKED_TIMEOUT 15
2940 #define MAX_CAM_NUMBER 32
2941 #define CHANNEL_CAM_RELATIONS_CLEANUP_INTERVAL 3600
2969 if (ccr->ChannelID() == ChannelID)
2988 ccr->ClrChecked(CamSlotNumber);
2989 ccr->ClrDecrypt(CamSlotNumber);
2997 return ccr ? ccr->
CamChecked(CamSlotNumber) :
false;
3004 return ccr ? ccr->
CamDecrypt(CamSlotNumber) :
false;
3045 if (FILE *f = fopen(
fileName,
"r")) {
3048 while ((s = ReadLine.
Read(f)) != NULL) {
3049 if (
char *p = strchr(s,
' ')) {
3053 if (ChannelID.
Valid()) {
3056 while ((q = strtok_r(p,
" ", &strtok_next)) != NULL) {
3057 int CamSlotNumber = atoi(q);
3080 if ((st.st_mode & S_IWUSR) == 0) {
3089 if (ccr->ChannelID().Valid()) {
3092 if (ccr->CamDecrypt(i))
3096 fprintf(f,
"%s %s\n", *ccr->ChannelID().ToString(), *s);
#define LOCK_CHANNELS_READ
static bool DumpTPDUDataTransfer
#define ST_CREATE_SESSION_RESPONSE
#define AOT_PROFILE_CHANGE
#define AOT_APPLICATION_INFO_ENQ
cChannelCamRelations ChannelCamRelations
#define ST_OPEN_SESSION_REQUEST
#define QUERY_REPLY_TIMEOUT
static const uint8_t * GetLength(const uint8_t *Data, int &Length)
#define AOT_APPLICATION_INFO
cCiResourceHandlers CiResourceHandlers
static int MtdMapCaDescriptors(uchar *p, cMtdMapper *MtdMapper)
#define ST_CLOSE_SESSION_REQUEST
#define MODULE_RESET_TIMEOUT
#define CPCI_OK_DESCRAMBLING
#define STREAM_TYPE_VIDEO
#define ST_CLOSE_SESSION_RESPONSE
#define CPCI_NOT_SELECTED
#define STREAM_TYPE_AUDIO
#define RI_RESOURCE_MANAGER
static uint8_t * SetLength(uint8_t *Data, int Length)
#define RI_CONDITIONAL_ACCESS_SUPPORT
#define CHANNEL_CAM_RELATIONS_CLEANUP_INTERVAL
static bool DebugProtocol
static char * GetString(int &Length, const uint8_t **Data)
#define CAM_CHECKED_TIMEOUT
#define RI_APPLICATION_INFORMATION
static int MtdMapStreams(uchar *p, cMtdMapper *MtdMapper, int Length)
static int MtdMapCaDescriptor(uchar *p, cMtdMapper *MtdMapper)
#define ST_OPEN_SESSION_RESPONSE
#define AOT_DISPLAY_CONTROL
#define RESOURCE_CLASS_MASK
cCamResponses CamResponses
#define STREAM_TYPE_PRIVATE
#define dbgprotocol(a...)
#define AOT_CLEAR_REPLACE
#define AOT_DATE_TIME_ENQ
static char * CopyString(int Length, const uint8_t *Data)
#define MAX_SESSIONS_PER_TC
static int MtdMapStream(uchar *p, cMtdMapper *MtdMapper)
bool CamResponsesLoad(const char *FileName, bool AllowComments, bool MustExist)
#define MODULE_CHECK_INTERVAL
#define AOT_DISPLAY_REPLY
#define ST_SESSION_NUMBER
#define MAX_CAM_SLOTS_PER_ADAPTER
#define MAX_CONNECTIONS_PER_CAM_SLOT
static u_int32_t crc32(const char *d, int len, u_int32_t CRCvalue)
virtual void Receive(const uchar *Data, int Length)
This function is called from the cDevice we are attached to, and delivers one TS packet from the set ...
virtual ~cCaActivationReceiver()
cCaActivationReceiver(const cChannel *Channel, cCamSlot *CamSlot)
uchar mtdCatBuffer[CAT_MAXPACKETS][TS_SIZE]
virtual ~cCaPidReceiver()
bool HandlingPid(void)
The cCaPidReceiver adds/deletes PIDs to/from the base class cReceiver, which in turn does the same on...
virtual void Receive(const uchar *Data, int Length)
This function is called from the cDevice we are attached to, and delivers one TS packet from the set ...
bool HasCaPids(void) const
bool Parse(const char *s)
int Matches(int CamNumber, const char *Text) const
int GetMatch(int CamNumber, const char *Text) const
bool Devices(cVector< int > &DeviceNumbers)
Adds the numbers of any devices that currently use this CAM to the given DeviceNumbers.
virtual bool RepliesToQuery(void)
Returns true if the CAM in this slot replies to queries and thus supports MCD ("Multi Channel Decrypt...
virtual bool IsDecrypting(void)
Returns true if the CAM in this slot is currently used for decrypting.
virtual bool Ready(void)
Returns 'true' if the CAM in this slot is ready to decrypt.
virtual void InjectEit(int Sid)
Injects a generated EIT with a "present event" for the given Sid into the TS data stream sent to the ...
int Priority(void)
Returns the priority of the device this slot is currently assigned to, or IDLEPRIORITY if it is not a...
virtual const char * GetCamName(void)
Returns the name of the CAM in this slot, or NULL if there is no ready CAM in this slot.
void DeleteAllConnections(void)
friend class cCiTransportConnection
cCiSession * GetSessionByResourceId(uint32_t ResourceId)
virtual bool CanDecrypt(const cChannel *Channel, cMtdMapper *MtdMapper=NULL)
Returns true if there is a CAM in this slot that is able to decrypt the given Channel (or at least cl...
void KeepSharedCaPids(int ProgramNumber, const int *CaSystemIds, int *CaPids)
virtual bool Inject(uchar *Data, int Count)
Sends all Count bytes of the given Data to the CAM, and returns true if this was possible.
void MtdEnable(void)
Enables MTD support for this CAM.
bool McdAvailable(void)
Returns true if this CAM supports MCD ("Multi Channel Decyption").
virtual bool EnterMenu(void)
Requests the CAM in this slot to start its menu.
virtual uchar * Decrypt(uchar *Data, int &Count)
If this is a CAM slot that can be freely assigned to any device, but will not be directly inserted in...
virtual void AddPid(int ProgramNumber, int Pid, int StreamType)
Adds the given PID information to the list of PIDs.
int MasterSlotNumber(void)
Returns the number of this CAM's master slot within the whole system.
virtual cCiEnquiry * GetEnquiry(void)
Gets a pending enquiry, or NULL if there is no enquiry.
void Process(cTPDU *TPDU=NULL)
cCaActivationReceiver * caActivationReceiver
virtual eModuleStatus ModuleStatus(void)
Returns the status of the CAM in this slot.
void MtdActivate(bool On)
Activates (On == true) or deactivates (On == false) MTD.
eModuleStatus lastModuleStatus
cCaPidReceiver * caPidReceiver
virtual void AddChannel(const cChannel *Channel)
Adds all PIDs of the given Channel to the current list of PIDs.
virtual bool HasUserIO(void)
Returns true if there is a pending user interaction, which shall be retrieved via GetMenu() or GetEnq...
virtual const int * GetCaSystemIds(void)
bool WantsTsData(void) const
Returns true if this CAM slot wants to receive the TS data through its Decrypt() function.
virtual bool Assign(cDevice *Device, bool Query=false)
Assigns this CAM slot to the given Device, if this is possible.
virtual cCiMenu * GetMenu(void)
Gets a pending menu, or NULL if there is no menu.
virtual void SendCaPmt(uint8_t CmdId)
virtual bool Reset(void)
Resets the CAM in this slot.
virtual void SetPid(int Pid, bool Active)
Sets the given Pid (which has previously been added through a call to AddPid()) to Active.
virtual void StartActivation(void)
Puts the CAM in this slot into a mode where an inserted smart card can be activated.
virtual void StartDecrypting(void)
Sends all CA_PMT entries to the CAM that have been modified since the last call to this function.
virtual bool IsActivating(void)
Returns true if this CAM slot is currently activating a smart card.
bool MtdAvailable(void)
Returns true if this CAM supports MTD ("Multi Transponder Decryption").
cCiTransportConnection * tc[MAX_CONNECTIONS_PER_CAM_SLOT+1]
virtual bool TsPostProcess(uchar *Data)
If there is a cCiSession that needs to do additional processing on TS packets (after the CAM has done...
int MtdPutData(uchar *Data, int Count)
Sends at most Count bytes of the given Data to the individual MTD CAM slots that are using this CAM.
int SlotIndex(void)
Returns the index of this CAM slot within its CI adapter.
cList< cCiCaProgramData > caProgramList
virtual void StopDecrypting(void)
Clears the list of CA_PMT entries and tells the CAM to stop decrypting.
void SendCaPmts(cCiCaPmtList &CaPmtList)
Sends the given list of CA_PMTs to the CAM.
virtual bool HasMMI(void)
Returns 'true' if the CAM in this slot has an active MMI.
virtual bool CanActivate(void)
Returns true if there is a CAM in this slot that can be put into activation mode.
cCamSlot(cCiAdapter *CiAdapter, bool WantsTsData=false, cCamSlot *MasterSlot=NULL)
Creates a new CAM slot for the given CiAdapter.
cDevice * Device(void)
Returns the device this CAM slot is currently assigned to.
cCamSlot * MtdSpawn(void)
If this CAM slot can do MTD ("Multi Transponder Decryption"), a call to this function returns a cMtdC...
void BuildCaPmts(uint8_t CmdId, cCiCaPmtList &CaPmtList, cMtdMapper *MtdMapper=NULL)
Generates all CA_PMTs with the given CmdId and stores them in the given CaPmtList.
cCamSlot * MasterSlot(void)
Returns this CAM slot's master slot, or a pointer to itself if it is a master slot.
int SlotNumber(void)
Returns the number of this CAM slot within the whole system.
virtual void CancelActivation(void)
Cancels a previously started activation (if any).
virtual bool ProvidesCa(const int *CaSystemIds)
Returns true if the CAM in this slot provides one of the given CaSystemIds.
bool WaitForAllCamSlotsReady(int Timeout=0)
Waits until all CAM slots have become ready, or the given Timeout (seconds) has expired.
int NumReadyMasterSlots(void)
Returns the number of master CAM slots in the system that are ready to decrypt.
bool CamChecked(int CamSlotNumber)
void ClrChecked(int CamSlotNumber)
tChannelID ChannelID(void)
void SetChecked(int CamSlotNumber)
cChannelCamRelation(tChannelID ChannelID)
void SetDecrypt(int CamSlotNumber)
bool CamDecrypt(int CamSlotNumber)
void ClrDecrypt(int CamSlotNumber)
void ClrDecrypt(tChannelID ChannelID, int CamSlotNumber)
void Load(const char *FileName)
void SetChecked(tChannelID ChannelID, int CamSlotNumber)
bool CamDecrypt(tChannelID ChannelID, int CamSlotNumber)
cChannelCamRelations(void)
bool CamChecked(tChannelID ChannelID, int CamSlotNumber)
cChannelCamRelation * GetEntry(tChannelID ChannelID)
cChannelCamRelation * AddEntry(tChannelID ChannelID)
void SetDecrypt(tChannelID ChannelID, int CamSlotNumber)
void ClrChecked(tChannelID ChannelID, int CamSlotNumber)
void Reset(int CamSlotNumber)
const int * Dpids(void) const
int Ca(int Index=0) const
const int * Spids(void) const
int Transponder(void) const
Returns the transponder frequency in MHz, plus the polarization in case of sat.
const int * Apids(void) const
virtual void Action(void)
Handles the attached CAM slots in a separate thread.
cCamSlot * camSlots[MAX_CAM_SLOTS_PER_ADAPTER]
virtual bool Reset(int Slot)
Resets the CAM in the given Slot.
virtual eModuleStatus ModuleStatus(int Slot)
Returns the status of the CAM in the given Slot.
cCamSlot * ItCamSlot(int &Iter)
Iterates over all added CAM slots of this adapter.
virtual bool Assign(cDevice *Device, bool Query=false)
Assigns this adapter to the given Device, if this is possible.
virtual ~cCiAdapter()
The derived class must call Cancel(3) in its destructor.
void AddCamSlot(cCamSlot *CamSlot)
Adds the given CamSlot to this CI adapter.
virtual void Write(const uint8_t *Buffer, int Length)
Writes Length bytes of the given Buffer.
virtual int Read(uint8_t *Buffer, int MaxLength)
Reads one chunk of data into the given Buffer, up to MaxLength bytes.
cCiCaPidData(int Pid, int StreamType)
int caSystemIds[MAXCASYSTEMIDS+1]
cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds)
void AddPid(int Pid, uint8_t StreamType)
void SetListManagement(uint8_t ListManagement)
cDynamicBuffer caDescriptors
void MtdMapPids(cMtdMapper *MtdMapper)
void AddCaDescriptors(int Length, const uint8_t *Data)
uint8_t ListManagement(void)
cList< cCiCaPidData > pidList
cCiCaProgramData(int ProgramNumber)
bool RepliesToQuery(void)
int caSystemIds[MAXCASYSTEMIDS+1]
cCiConditionalAccessSupport(uint16_t SessionId, cCiTransportConnection *Tc)
const int * GetCaSystemIds(void)
virtual void Process(int Length=0, const uint8_t *Data=NULL)
void SendPMT(cCiCaPmt *CaPmt)
virtual void Process(int Length=0, const uint8_t *Data=NULL)
cCiDateTime(uint16_t SessionId, cCiTransportConnection *Tc)
virtual cCiSession * GetNewCiSession(uint32_t ResourceId, uint16_t SessionId, cCiTransportConnection *Tc)
Returns a new cCiSession, according to the given ResourceId.
virtual const uint32_t * ResourceIds(void) const
Returns a pointer to an array of resource identifiers, where the last value is zero.
void Reply(const char *s)
cCiHostControl(uint16_t SessionId, cCiTransportConnection *Tc)
virtual void Process(int Length=0, const uint8_t *Data=NULL)
cCiEnquiry * Enquiry(bool Clear=false)
cCiMenu * Menu(bool Clear=false)
virtual void Process(int Length=0, const uint8_t *Data=NULL)
virtual bool HasUserIO(void)
cCiMMI(uint16_t SessionId, cCiTransportConnection *Tc)
cCiEnquiry * fetchedEnquiry
bool SendAnswer(const char *Text)
char * GetText(int &Length, const uint8_t **Data)
void SendMenuAnswer(uint8_t Selection)
virtual const uint32_t * ResourceIds(void) const =0
Returns a pointer to an array of resource identifiers, where the last value is zero.
cCiResourceHandler(void)
Creates a new resource handler, through which the available resources can be provides.
virtual ~cCiResourceHandler()
const uint32_t * Ids(void)
cCiResourceHandlers(void)
Creates the default list of resourceIds.
cVector< uint32_t > resourceIds
void Register(cCiResourceHandler *ResourceHandler)
Adds the given ResourceHandler to the list of resource handlers and appends its ResourceIds to the gl...
cCiSession * GetNewCiSession(uint32_t ResourceId, uint16_t SessionId, cCiTransportConnection *Tc)
cCiResourceManager(uint16_t SessionId, cCiTransportConnection *Tc)
virtual void Process(int Length=0, const uint8_t *Data=NULL)
int GetTag(int &Length, const uint8_t **Data)
void SendData(int Tag, int Length=0, const uint8_t *Data=NULL)
cCiTransportConnection * tc
cCiSession(uint16_t SessionId, uint32_t ResourceId, cCiTransportConnection *Tc)
void SetResourceId(uint32_t Id)
If this is a class that has been derived from an existing cCiSession class, but implements a differen...
uint32_t ResourceId(void)
virtual bool TsPostProcess(uint8_t *TsPacket)
If this cCiSession needs to do additional processing on TS packets (after the CAM has done the decryp...
const uint8_t * GetData(const uint8_t *Data, int &Length)
void SetTsPostProcessor(void)
If this cCiSession implements the TsPostProcess() function, it shall call SetTsPostProcessor() to reg...
cCiTransportConnection * Tc(void)
virtual void Process(int Length=0, const uint8_t *Data=NULL)
virtual ~cCiTransportConnection()
cCiSession * GetSessionBySessionId(uint16_t SessionId)
void CreateConnection(void)
bool TsPostProcess(uint8_t *TsPacket)
void OpenSession(int Length, const uint8_t *Data)
bool createConnectionRequested
cCiSession * sessions[MAX_SESSIONS_PER_TC+1]
cCiSession * tsPostProcessor
void SetTsPostProcessor(cCiSession *CiSession)
const char * GetCamName(void)
void SendTag(uint8_t Tag, uint16_t SessionId, uint32_t ResourceId=0, int Status=-1)
cCiTransportConnection(cCamSlot *CamSlot, uint8_t Tcid)
void DeleteConnection(void)
void SendTPDU(uint8_t Tag, int Length=0, const uint8_t *Data=NULL)
void CloseSession(uint16_t SessionId)
void SendData(int Length, const uint8_t *Data)
uint32_t ResourceIdToInt(const uint8_t *Data)
bool deleteConnectionRequested
void HandleSessions(cTPDU *TPDU)
bool Process(cTPDU *TPDU=NULL)
cCiSession * GetSessionByResourceId(uint32_t ResourceId)
bool TimedWait(cMutex &Mutex, int TimeoutMs)
static void SleepMs(int TimeoutMs)
Creates a cCondWait object and uses it to sleep for TimeoutMs milliseconds, immediately giving up the...
bool Load(const char *FileName=NULL, bool AllowComments=false, bool MustExist=false)
void SetCamSlot(cCamSlot *CamSlot)
Sets the given CamSlot to be used with this device.
int DeviceNumber(void) const
Returns the number of this device (0 ... numDevices - 1).
bool AttachReceiver(cReceiver *Receiver)
Attaches the given receiver to this device.
static int CurrentChannel(void)
Returns the number of the current channel on the primary device.
void Detach(cFilter *Filter)
Detaches the given filter from this device.
int Priority(void) const
Returns the priority of the current receiving session (-MAXPRIORITY..MAXPRIORITY),...
cCamSlot * CamSlot(void) const
Returns the CAM slot that is currently used with this device, or NULL if no CAM slot is in use.
void Set(int Index, uchar Data)
void Append(const uchar *Data, int Length)
void Del(cListObject *Object, bool DeleteObject=true)
void Add(cListObject *Object, cListObject *After=NULL)
cListObject * Next(void) const
const T * Next(const T *Object) const
< Returns the element immediately before Object in this list, or NULL if Object is the first element ...
const cCiResourceHandler * Last(void) const
Returns the last element in this list, or NULL if the list is empty.
const T * First(void) const
Returns the first element in this list, or NULL if the list is empty.
const cCiResourceHandler * Prev(const cCiResourceHandler *Object) const
int PutCat(const uchar *Data, int Count)
cMtdMapper * MtdMapper(void)
int Put(const uchar *Data, int Count)
Puts at most Count bytes of Data into the CAM slot which's index is derived from the PID of the TS pa...
bool IsActivating(void)
Returns true if any of the active MTD CAM slots is currently activating.
void StartDecrypting(void)
Tells all active MTD CAM slots to start decrypting.
bool IsDecrypting(void)
Returns true if any of the active MTD CAM slots is currently decrypting.
void CancelActivation(void)
Tells all active MTD CAM slots to cancel activation.
cMtdCamSlot * GetMtdCamSlot(cCamSlot *MasterSlot)
Creates a new MTD CAM slot, or reuses an existing one that is currently unused.
void StopDecrypting(void)
Tells all active MTD CAM slots to stop decrypting.
int Priority(void)
Returns the maximum priority of any of the active MTD CAM slots.
void UnAssignAll(void)
Unassigns all MTD CAM slots from their devices.
bool Devices(cVector< int > &DeviceNumbers)
Adds the numbers of the devices of any active MTD CAM slots to the given DeviceNumbers.
bool AddPids(const int *Pids)
Adds the given zero terminated list of Pids to the list of PIDs of this receiver.
bool AddPid(int Pid)
Adds the given Pid to the list of PIDs of this receiver.
void DelPids(const int *Pids)
Deletes the given zero terminated list of Pids from the list of PIDs of this receiver.
void DelPid(int Pid)
Deletes the given Pid from the list of PIDs of this receiver.
int QueueMessage(eMessageType Type, const char *s, int Seconds=0, int Timeout=0)
Like Message(), but this function may be called from a background thread.
static cString sprintf(const char *fmt,...) __attribute__((format(printf
void Dump(int SlotNumber, bool Outgoing)
const uint8_t * Data(int &Length)
uint8_t buffer[MAX_TPDU_SIZE]
const uint8_t * GetData(const uint8_t *Data, int &Length)
bool Running(void)
Returns false if a derived cThread object shall leave its Action() function.
void Cancel(int WaitSeconds=0)
Cancels the thread by first setting 'running' to false, so that the Action() loop can finish in an or...
void Set(int Ms=0)
Sets the timer.
bool TimedOut(void) const
virtual void Append(T Data)
bool RemoveElement(const T &Data)
void MtdMapPid(uchar *p, cMtdMapper *MtdMapper)
void MtdMapSid(uchar *p, cMtdMapper *MtdMapper)
int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids)
Gets all CA pids for a given channel.
void GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, cDynamicBuffer &Buffer, int EsPid)
Gets all CA descriptors for a given channel.
int TsPid(const uchar *p)
bool TsIsScrambled(const uchar *p)
bool TsPayloadStart(const uchar *p)
void Del(cCiCaPmt *CaPmt)
cVector< cCiCaPmt * > caPmts
cCiCaPmt * Add(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds)
static tChannelID FromString(const char *s)