Go to the documentation of this file.
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 // 6 * 184 = 1104 bytes for CAT table
188 const uchar *p = NULL;
195 length = (int(Data[6] & 0x0F) << 8) | Data[7];
197 int v = (Data[10] & 0x3E) >> 1;
199 if (Data[11] == 0 && Data[12] == 0) {
203 memcpy(
buffer, Data + 5, n);
216 dsyslog(
"multi table CAT section - unhandled!");
219 else if (MtdCamSlot) {
229 memcpy(
bufp, Data + 4, n);
240 esyslog(
"ERROR: buffer overflow in cCaPidReceiver::Receive()");
248 for (
int i = 8; i <
length - 4; i++) {
250 int CaId = int(p[i + 2] << 8) | p[i + 3];
251 int EmmPid =
Peek13(p + i + 4);
256 case 0x01:
for (
int j = i + 7; j < i + p[i + 1] + 2; j += 4) {
264 i += p[i + 1] + 2 - 1;
287 esyslog(
"ERROR: wrong checksum in CAT");
308 #define UNSCRAMBLE_TIME 5 // seconds of receiving purely unscrambled data before considering the smart card "activated"
309 #define TS_PACKET_FACTOR 1024 // only process every TS_PACKET_FACTORth packet to keep the load down
339 time_t Now = time(NULL);
349 s->CancelActivation();
360 #define CRA_DISCARD -1
361 #define CRA_CONFIRM -2
362 #define CRA_SELECT -3
372 bool Parse(
const char *s);
373 int Matches(
int CamNumber,
const char *Text)
const;
405 char *t =
const_cast<char *
>(s);
407 bool InQuotes =
false;
417 else if (*t ==
'\\') {
423 memmove(t, t + 1, strlen(t));
425 else if (*t ==
' ') {
434 text = strndup(s, t - s);
454 if (strcmp(
text, Text) == 0)
464 int GetMatch(
int CamNumber,
const char *Text)
const;
470 int Action = cr->Matches(CamNumber, Text);
472 dsyslog(
"CAM %d: auto response %4d to '%s'\n", CamNumber, Action, Text);
488 #define MAX_TPDU_SIZE 4096
489 #define MAX_TPDU_DATA (MAX_TPDU_SIZE - 4)
491 #define DATA_INDICATOR 0x80
495 #define T_CREATE_TC 0x82
496 #define T_CTC_REPLY 0x83
497 #define T_DELETE_TC 0x84
498 #define T_DTC_REPLY 0x85
499 #define T_REQUEST_TC 0x86
500 #define T_NEW_TC 0x87
501 #define T_TC_ERROR 0x88
502 #define T_DATA_LAST 0xA0
503 #define T_DATA_MORE 0xA1
509 const uint8_t *
GetData(
const uint8_t *
Data,
int &Length);
522 void Dump(
int SlotNumber,
bool Outgoing);
525 cTPDU::cTPDU(uint8_t Slot, uint8_t Tcid, uint8_t Tag,
int Length,
const uint8_t *Data)
551 esyslog(
"ERROR: invalid data length for TPDU tag 0x%02X: %d (%d/%d)",
Tag, Length,
Slot,
Tcid);
560 memcpy(p,
Data, Length);
564 esyslog(
"ERROR: invalid data length for TPDU tag 0x%02X: %d (%d/%d)",
Tag, Length,
Slot,
Tcid);
575 fprintf(stderr,
" %d: %s ", SlotNumber, Outgoing ?
"-->" :
"<--");
577 fprintf(stderr,
"%02X ",
buffer[i]);
580 fprintf(stderr,
" ");
582 fprintf(stderr,
"%2c ", isprint(
buffer[i]) ?
buffer[i] :
'.');
609 #define MAX_SESSIONS_PER_TC 16
625 void SendTPDU(uint8_t Tag,
int Length = 0,
const uint8_t *Data = NULL);
626 void SendTag(uint8_t Tag, uint16_t SessionId, uint32_t ResourceId = 0,
int Status = -1);
645 void SendData(
int Length,
const uint8_t *Data);
654 #define ST_SESSION_NUMBER 0x90
655 #define ST_OPEN_SESSION_REQUEST 0x91
656 #define ST_OPEN_SESSION_RESPONSE 0x92
657 #define ST_CREATE_SESSION 0x93
658 #define ST_CREATE_SESSION_RESPONSE 0x94
659 #define ST_CLOSE_SESSION_REQUEST 0x95
660 #define ST_CLOSE_SESSION_RESPONSE 0x96
665 #define SS_NOT_ALLOCATED 0xF0
669 #define RI_RESOURCE_MANAGER 0x00010041
670 #define RI_APPLICATION_INFORMATION 0x00020041
671 #define RI_CONDITIONAL_ACCESS_SUPPORT 0x00030041
672 #define RI_HOST_CONTROL 0x00200041
673 #define RI_DATE_TIME 0x00240041
674 #define RI_MMI 0x00400041
678 #define AOT_NONE 0x000000
679 #define AOT_PROFILE_ENQ 0x9F8010
680 #define AOT_PROFILE 0x9F8011
681 #define AOT_PROFILE_CHANGE 0x9F8012
682 #define AOT_APPLICATION_INFO_ENQ 0x9F8020
683 #define AOT_APPLICATION_INFO 0x9F8021
684 #define AOT_ENTER_MENU 0x9F8022
685 #define AOT_CA_INFO_ENQ 0x9F8030
686 #define AOT_CA_INFO 0x9F8031
687 #define AOT_CA_PMT 0x9F8032
688 #define AOT_CA_PMT_REPLY 0x9F8033
689 #define AOT_TUNE 0x9F8400
690 #define AOT_REPLACE 0x9F8401
691 #define AOT_CLEAR_REPLACE 0x9F8402
692 #define AOT_ASK_RELEASE 0x9F8403
693 #define AOT_DATE_TIME_ENQ 0x9F8440
694 #define AOT_DATE_TIME 0x9F8441
695 #define AOT_CLOSE_MMI 0x9F8800
696 #define AOT_DISPLAY_CONTROL 0x9F8801
697 #define AOT_DISPLAY_REPLY 0x9F8802
698 #define AOT_TEXT_LAST 0x9F8803
699 #define AOT_TEXT_MORE 0x9F8804
700 #define AOT_KEYPAD_CONTROL 0x9F8805
701 #define AOT_KEYPRESS 0x9F8806
702 #define AOT_ENQ 0x9F8807
703 #define AOT_ANSW 0x9F8808
704 #define AOT_MENU_LAST 0x9F8809
705 #define AOT_MENU_MORE 0x9F880A
706 #define AOT_MENU_ANSW 0x9F880B
707 #define AOT_LIST_LAST 0x9F880C
708 #define AOT_LIST_MORE 0x9F880D
709 #define AOT_SUBTITLE_SEGMENT_LAST 0x9F880E
710 #define AOT_SUBTITLE_SEGMENT_MORE 0x9F880F
711 #define AOT_DISPLAY_MESSAGE 0x9F8810
712 #define AOT_SCENE_END_MARK 0x9F8811
713 #define AOT_SCENE_DONE 0x9F8812
714 #define AOT_SCENE_CONTROL 0x9F8813
715 #define AOT_SUBTITLE_DOWNLOAD_LAST 0x9F8814
716 #define AOT_SUBTITLE_DOWNLOAD_MORE 0x9F8815
717 #define AOT_FLUSH_DOWNLOAD 0x9F8816
718 #define AOT_DOWNLOAD_REPLY 0x9F8817
719 #define AOT_COMMS_CMD 0x9F8C00
720 #define AOT_CONNECTION_DESCRIPTOR 0x9F8C01
721 #define AOT_COMMS_REPLY 0x9F8C02
722 #define AOT_COMMS_SEND_LAST 0x9F8C03
723 #define AOT_COMMS_SEND_MORE 0x9F8C04
724 #define AOT_COMMS_RCV_LAST 0x9F8C05
725 #define AOT_COMMS_RCV_MORE 0x9F8C06
727 #define RESOURCE_CLASS_MASK 0xFFFF0000
755 if (Length >= 3 && Data && *Data) {
757 for (
int i = 0; i < 3; i++)
758 t = (t << 8) | *(*Data)++;
768 return Length ? Data : NULL;
779 *p++ = (Tag >> 16) & 0xFF;
780 *p++ = (Tag >> 8) & 0xFF;
783 if (p - buffer + Length <
int(
sizeof(buffer))) {
785 memcpy(p, Data, Length);
790 esyslog(
"ERROR: CAM %d: data length (%d) exceeds buffer size",
CamSlot()->SlotNumber(), Length);
809 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
822 int Tag =
GetTag(Length, &Data);
835 const uint8_t *d =
GetData(Data, l);
837 esyslog(
"ERROR: CAM %d: resource manager: unexpected data",
CamSlot()->SlotNumber());
843 esyslog(
"ERROR: CAM %d: resource manager: unexpected tag %06X in state %d",
CamSlot()->SlotNumber(), Tag,
state);
847 default:
esyslog(
"ERROR: CAM %d: resource manager: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
850 else if (
state == 0) {
875 int Tag =
GetTag(Length, &Data);
880 const uint8_t *d =
GetData(Data, l);
881 if ((l -= 1) < 0)
break;
883 if ((l -= 2) < 0)
break;
886 if ((l -= 2) < 0)
break;
895 default:
esyslog(
"ERROR: CAM %d: application information: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
898 else if (
state == 0) {
917 #define MAXCASYSTEMIDS 64
921 #define CPLM_MORE 0x00
922 #define CPLM_FIRST 0x01
923 #define CPLM_LAST 0x02
924 #define CPLM_ONLY 0x03
925 #define CPLM_ADD 0x04
926 #define CPLM_UPDATE 0x05
930 #define CPCI_OK_DESCRAMBLING 0x01
931 #define CPCI_OK_MMI 0x02
932 #define CPCI_QUERY 0x03
933 #define CPCI_NOT_SELECTED 0x04
948 cCiCaPmt(uint8_t
CmdId,
int Source,
int Transponder,
int ProgramNumber,
const int *CaSystemIds);
952 void AddPid(
int Pid, uint8_t StreamType);
956 cCiCaPmt::cCiCaPmt(uint8_t CmdId,
int Source,
int Transponder,
int ProgramNumber,
const int *CaSystemIds)
964 for (; CaSystemIds[i]; i++)
1011 esyslog(
"ERROR: adding CA descriptor without Pid!");
1024 esyslog(
"ERROR: wrong length (%d) in MtdMapCaDescriptor()", l);
1027 esyslog(
"ERROR: wrong tag (%d) in MtdMapCaDescriptor()", *p);
1033 int Length = p[0] * 256 + p[1];
1096 #define CAEI_POSSIBLE 0x01
1097 #define CAEI_POSSIBLE_COND_PURCHASE 0x02
1098 #define CAEI_POSSIBLE_COND_TECHNICAL 0x03
1099 #define CAEI_NOT_POSSIBLE_ENTITLEMENT 0x71
1100 #define CAEI_NOT_POSSIBLE_TECHNICAL 0x73
1102 #define CA_ENABLE_FLAG 0x80
1104 #define CA_ENABLE(x) (((x) & CA_ENABLE_FLAG) ? (x) & ~CA_ENABLE_FLAG : 0)
1106 #define QUERY_WAIT_TIME 500 // ms to wait before sending a query
1107 #define QUERY_REPLY_TIMEOUT 2000 // ms to wait for a reply to a query
1108 #define QUERY_RETRIES 6 // max. number of retries to check if there is a reply to a query
1120 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
1142 int Tag =
GetTag(Length, &Data);
1149 const uint8_t *d =
GetData(Data, l);
1151 uint16_t
id = ((uint16_t)(*d) << 8) | *(d + 1);
1159 esyslog(
"ERROR: CAM %d: too many CA system IDs!",
CamSlot()->SlotNumber());
1170 dsyslog(
"CAM %d: system ids:%s",
CamSlot()->SlotNumber(), *Ids ? *Ids :
" none");
1176 if (
CamSlot()->IsMasterSlot())
1177 dsyslog(
"CAM %d: replies to QUERY - multi channel decryption (MCD) possible",
CamSlot()->SlotNumber());
1179 if (
CamSlot()->MtdAvailable()) {
1180 if (
CamSlot()->IsMasterSlot())
1181 dsyslog(
"CAM %d: supports multi transponder decryption (MTD)",
CamSlot()->SlotNumber());
1187 const uint8_t *d =
GetData(Data, l);
1189 uint16_t pnr = ((uint16_t)(*d) << 8) | *(d + 1);
1198 if (l % 3 == 0 && l > 1) {
1204 uint16_t len = ((uint16_t)(*d) << 8) | *(d + 1);
1210 unsigned char caepl = *d;
1218 uint16_t pid = ((uint16_t)(*d) << 8) | *(d + 1);
1219 unsigned char caees = *(d + 2);
1234 default:
esyslog(
"ERROR: CAM %d: conditional access support: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
1237 else if (
state == 0) {
1250 dsyslog(
"CAM %d: doesn't reply to QUERY - only a single channel can be decrypted",
CamSlot()->SlotNumber());
1259 if (CaPmt &&
state >= 2) {
1271 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
1283 int Tag =
GetTag(Length, &Data);
1294 default:
esyslog(
"ERROR: CAM %d: Host Control: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
1308 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
1321 time_t t = time(NULL);
1324 if (gmtime_r(&t, &tm_gmt) && localtime_r(&t, &tm_loc)) {
1325 int Y = tm_gmt.tm_year;
1326 int M = tm_gmt.tm_mon + 1;
1327 int D = tm_gmt.tm_mday;
1328 int L = (M == 1 || M == 2) ? 1 : 0;
1329 int MJD = 14956 + D + int((Y - L) * 365.25) + int((M + 1 + L * 12) * 30.6001);
1330 #define DEC2BCD(d) uint8_t(((d / 10) << 4) + (d % 10))
1332 struct tTime { uint16_t mjd; uint8_t h, m, s;
short offset; };
1334 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)) };
1347 int Tag =
GetTag(Length, &Data);
1352 const uint8_t *d =
GetData(Data, l);
1360 default:
esyslog(
"ERROR: CAM %d: date time: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
1373 #define DCC_SET_MMI_MODE 0x01
1374 #define DCC_DISPLAY_CHARACTER_TABLE_LIST 0x02
1375 #define DCC_INPUT_CHARACTER_TABLE_LIST 0x03
1376 #define DCC_OVERLAY_GRAPHICS_CHARACTERISTICS 0x04
1377 #define DCC_FULL_SCREEN_GRAPHICS_CHARACTERISTICS 0x05
1381 #define MM_HIGH_LEVEL 0x01
1382 #define MM_LOW_LEVEL_OVERLAY_GRAPHICS 0x02
1383 #define MM_LOW_LEVEL_FULL_SCREEN_GRAPHICS 0x03
1387 #define DRI_MMI_MODE_ACK 0x01
1388 #define DRI_LIST_DISPLAY_CHARACTER_TABLES 0x02
1389 #define DRI_LIST_INPUT_CHARACTER_TABLES 0x03
1390 #define DRI_LIST_GRAPHIC_OVERLAY_CHARACTERISTICS 0x04
1391 #define DRI_LIST_FULL_SCREEN_GRAPHIC_CHARACTERISTICS 0x05
1392 #define DRI_UNKNOWN_DISPLAY_CONTROL_CMD 0xF0
1393 #define DRI_UNKNOWN_MMI_MODE 0xF1
1394 #define DRI_UNKNOWN_CHARACTER_TABLE 0xF2
1398 #define EF_BLIND 0x01
1402 #define AI_CANCEL 0x00
1403 #define AI_ANSWER 0x01
1407 char *
GetText(
int &Length,
const uint8_t **Data);
1413 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
1449 int Tag =
GetTag(Length, Data);
1456 esyslog(
"ERROR: CAM %d: MMI: unexpected text tag: %06X",
CamSlot()->SlotNumber(), Tag);
1463 int Tag =
GetTag(Length, &Data);
1468 const uint8_t *d =
GetData(Data, l);
1473 struct tDisplayReply { uint8_t id; uint8_t mode; };
1479 default:
esyslog(
"ERROR: CAM %d: MMI: unsupported display control command %02X",
CamSlot()->SlotNumber(), *d);
1490 const uint8_t *d =
GetData(Data, l);
1530 dsyslog(
"CAM %d: SELECT %d",
CamSlot()->SlotNumber(), Select + 1);
1541 const uint8_t *d =
GetData(Data, l);
1543 uint8_t blind = *d++;
1554 snprintf(s,
sizeof(s),
"%d", Action);
1571 const uint8_t *d =
GetData(Data, l);
1580 default:
esyslog(
"ERROR: CAM %d: MMI: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
1616 struct tAnswer { uint8_t id;
char text[256]; };
1621 len =
min(
sizeof(answer.text), strlen(Text));
1622 memcpy(answer.text, Text, len);
1750 static uint32_t Ids[] = {
1764 switch (ResourceId) {
1771 default:
return NULL;
1786 if (ResourceHandler) {
1787 Add(ResourceHandler);
1788 if (
const uint32_t *r = ResourceHandler->
ResourceIds()) {
1800 if (
cCiSession *CiSession = r->GetNewCiSession(ResourceId, SessionId, Tc))
1808 #define TC_POLL_TIMEOUT 300 // ms WORKAROUND: TC_POLL_TIMEOUT < 300ms doesn't work with DragonCAM
1809 #define TC_ALIVE_TIMEOUT 2000 // ms after which a transport connection is assumed dead
1848 return cas && cas->
Ready();
1874 uint8_t *p = buffer;
1885 buffer[1] = p - buffer - 2;
1914 if (s->ResourceId() == ResourceId)
1925 if (Length == 6 && *(Data + 1) == 0x04) {
1950 if (Session &&
sessions[SessionId] == Session) {
1964 const uint8_t *Data = TPDU->
Data(Length);
1965 if (Data && Length > 1) {
1968 uint16_t SessionId = ntohs(
get_unaligned((uint16_t *)&Data[2]));
1971 Session->
Process(Length - 4, Data + 4);
2023 switch (TPDU->
Tag()) {
2050 esyslog(
"ERROR: unknown TPDU tag: 0x%02X (%s)", TPDU->
Tag(), __FUNCTION__);
2071 esyslog(
"ERROR: unknown state: %d (%s)",
state, __FUNCTION__);
2139 esyslog(
"ERROR: no free CAM slot in CI adapter");
2175 #define MODULE_CHECK_INTERVAL 500 // ms
2176 #define MODULE_RESET_TIMEOUT 2 // s
2227 int OldDeviceNumber = 0;
2269 return DeviceNumbers.
Size() > 0;
2298 int n = TPDU->
Tcid();
2343 esyslog(
"ERROR: unknown module status %d (%s)", ms, __FUNCTION__);
2407 dsyslog(
"CAM %d: activating on device %d with channel %d (%s)",
SlotNumber(), d->DeviceNumber() + 1, Channel->Number(), Channel->Name());
2509 cCiCaPmt *p =
new cCiCaPmt(CmdId, Source, Transponder, ProgramNumber, CaSystemIds);
2532 if (CaSystemIds && *CaSystemIds) {
2536 bool Active = p->Active();
2540 CaPmt->
AddPid(q->pid, q->streamType);
2557 p->modified =
false;
2562 CaPmtList.
Add(CmdId, 0, 0, 0, NULL);
2569 int *pCaPids = CaPids;
2580 int *pCaPids2 = CaPids2;
2584 if (*pCaPids == *pCaPids2) {
2587 *pCaPids = CaPids[numPids - 1];
2589 CaPids[numPids] = 0;
2608 for (
int i = 0; i < CaPmtList.
caPmts.
Size(); i++)
2669 for (
const int *ids = cas->
GetCaSystemIds(); ids && *ids; ids++) {
2670 for (
const int *
id = CaSystemIds; *id;
id++) {
2684 if (p->programNumber == ProgramNumber) {
2704 if (q->pid == Pid) {
2705 if (q->active != Active) {
2716 #define STREAM_TYPE_VIDEO 0x02
2717 #define STREAM_TYPE_AUDIO 0x04
2718 #define STREAM_TYPE_PRIVATE 0x06
2729 for (
const int *Apid = Channel->
Apids(); *Apid; Apid++)
2731 for (
const int *Dpid = Channel->
Dpids(); *Dpid; Dpid++)
2733 for (
const int *Spid = Channel->
Spids(); *Spid; Spid++)
2738 #define QUERY_REPLY_WAIT 100 // ms to wait between checks for a reply
2752 for (
const int *Apid = Channel->
Apids(); *Apid; Apid++)
2754 for (
const int *Dpid = Channel->
Dpids(); *Dpid; Dpid++)
2756 for (
const int *Spid = Channel->
Spids(); *Spid; Spid++)
2844 if (CamSlot->IsMasterSlot() && CamSlot->ModuleStatus() ==
msReady)
2853 for (time_t t0 = time(NULL); time(NULL) - t0 < Timeout; ) {
2856 if (!CamSlot->Ready()) {
2865 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()));
2871 #define CAM_CHECKED_TIMEOUT 15 // seconds before a CAM that has been checked for a particular channel will be checked again
2944 #define MAX_CAM_NUMBER 32
2945 #define CHANNEL_CAM_RELATIONS_CLEANUP_INTERVAL 3600 // seconds between cleanups
2973 if (ccr->ChannelID() == ChannelID)
2992 ccr->ClrChecked(CamSlotNumber);
2993 ccr->ClrDecrypt(CamSlotNumber);
3001 return ccr ? ccr->
CamChecked(CamSlotNumber) :
false;
3008 return ccr ? ccr->
CamDecrypt(CamSlotNumber) :
false;
3049 if (FILE *f = fopen(
fileName,
"r")) {
3052 while ((s = ReadLine.
Read(f)) != NULL) {
3053 if (
char *p = strchr(s,
' ')) {
3057 if (ChannelID.
Valid()) {
3060 while ((q = strtok_r(p,
" ", &strtok_next)) != NULL) {
3061 int CamSlotNumber = atoi(q);
3084 if ((st.st_mode & S_IWUSR) == 0) {
3093 if (ccr->ChannelID().Valid()) {
3096 if (ccr->CamDecrypt(i))
3100 fprintf(f,
"%s %s\n", *ccr->ChannelID().ToString(), *s);
virtual bool Reset(int Slot)
Resets the CAM in the given Slot.
bool Devices(cVector< int > &DeviceNumbers)
Adds the numbers of any devices that currently use this CAM to the given DeviceNumbers.
#define dbgprotocol(a...)
static int MtdMapCaDescriptors(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.
#define ST_CLOSE_SESSION_RESPONSE
cCaPidReceiver * caPidReceiver
#define ST_CREATE_SESSION_RESPONSE
static const uint8_t * GetLength(const uint8_t *Data, int &Length)
void AddCamSlot(cCamSlot *CamSlot)
Adds the given CamSlot to this CI adapter.
cCiTransportConnection * Tc(void)
#define CPCI_OK_DESCRAMBLING
bool CamDecrypt(tChannelID ChannelID, int CamSlotNumber)
static cString sprintf(const char *fmt,...) __attribute__((format(printf
void KeepSharedCaPids(int ProgramNumber, const int *CaSystemIds, int *CaPids)
cCiCaPidData(int Pid, int StreamType)
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.
static int CurrentChannel(void)
Returns the number of the current channel on the primary device.
cCiSession * tsPostProcessor
virtual void Process(int Length=0, const uint8_t *Data=NULL)
void OpenSession(int Length, const uint8_t *Data)
void MtdMapSid(uchar *p, cMtdMapper *MtdMapper)
static uint8_t * SetLength(uint8_t *Data, int Length)
bool HandlingPid(void)
The cCaPidReceiver adds/deletes PIDs to/from the base class cReceiver, which in turn does the same on...
cCiTransportConnection * tc
cCaActivationReceiver * caActivationReceiver
#define ST_OPEN_SESSION_RESPONSE
virtual ~cCiTransportConnection()
uint32_t ResourceId(void)
static u_int32_t crc32(const char *d, int len, u_int32_t CRCvalue)
void MtdMapPids(cMtdMapper *MtdMapper)
int GetTag(int &Length, const uint8_t **Data)
uchar mtdCatBuffer[CAT_MAXPACKETS][TS_SIZE]
uint8_t ListManagement(void)
void DelPids(const int *Pids)
Deletes the given zero terminated list of Pids from the list of PIDs of this receiver.
cCiCaPmt * Add(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds)
void Load(const char *FileName)
bool createConnectionRequested
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 cCiMenu * GetMenu(void)
Gets a pending menu, or NULL if there is no menu.
bool Parse(const char *s)
void SendData(int Length, const uint8_t *Data)
void SendData(int Tag, int Length=0, const uint8_t *Data=NULL)
const char * GetCamName(void)
#define LOCK_CHANNELS_READ
virtual bool HasMMI(void)
Returns 'true' if the CAM in this slot has an active MMI.
bool AddPids(const int *Pids)
Adds the given zero terminated list of Pids to the list of PIDs of this receiver.
cCamSlot * camSlots[MAX_CAM_SLOTS_PER_ADAPTER]
virtual void SendCaPmt(uint8_t CmdId)
bool WaitForAllCamSlotsReady(int Timeout=0)
Waits until all CAM slots have become ready, or the given Timeout (seconds) has expired.
#define ST_SESSION_NUMBER
void ClrChecked(int CamSlotNumber)
void ClrChecked(tChannelID ChannelID, int CamSlotNumber)
eModuleStatus lastModuleStatus
void SendCaPmts(cCiCaPmtList &CaPmtList)
Sends the given list of CA_PMTs to the CAM.
bool TsPostProcess(uint8_t *TsPacket)
virtual eModuleStatus ModuleStatus(int Slot)
Returns the status of the CAM in the given Slot.
int SlotIndex(void)
Returns the index of this CAM slot within its CI adapter.
cCamSlot(cCiAdapter *CiAdapter, bool WantsTsData=false, cCamSlot *MasterSlot=NULL)
Creates a new CAM slot for the given CiAdapter.
virtual void AddPid(int ProgramNumber, int Pid, int StreamType)
Adds the given PID information to the list of PIDs.
bool RepliesToQuery(void)
cCiSession * GetNewCiSession(uint32_t ResourceId, uint16_t SessionId, cCiTransportConnection *Tc)
int caSystemIds[MAXCASYSTEMIDS+1]
int Priority(void) const
Returns the priority of the current receiving session (-MAXPRIORITY..MAXPRIORITY),...
void SetResourceId(uint32_t Id)
If this is a class that has been derived from an existing cCiSession class, but implements a differen...
cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds)
virtual void StartDecrypting(void)
Sends all CA_PMT entries to the CAM that have been modified since the last call to this function.
#define ST_CLOSE_SESSION_REQUEST
bool CamResponsesLoad(const char *FileName, bool AllowComments, bool MustExist)
virtual bool EnterMenu(void)
Requests the CAM in this slot to start its menu.
void DeleteConnection(void)
#define CAM_CHECKED_TIMEOUT
void SetDecrypt(tChannelID ChannelID, int CamSlotNumber)
void SetTsPostProcessor(cCiSession *CiSession)
virtual cCiEnquiry * GetEnquiry(void)
Gets a pending enquiry, or NULL if there is no enquiry.
void Add(cListObject *Object, cListObject *After=NULL)
virtual ~cCiResourceHandler()
virtual const int * GetCaSystemIds(void)
virtual bool Assign(cDevice *Device, bool Query=false)
Assigns this adapter to the given Device, if this is possible.
void SetChecked(tChannelID ChannelID, int CamSlotNumber)
const uint8_t * GetData(const uint8_t *Data, int &Length)
#define MODULE_CHECK_INTERVAL
virtual void CancelActivation(void)
Cancels a previously started activation (if any).
virtual void Process(int Length=0, const uint8_t *Data=NULL)
void Cancel(int WaitSeconds=0)
Cancels the thread by first setting 'running' to false, so that the Action() loop can finish in an or...
cCiSession(uint16_t SessionId, uint32_t ResourceId, cCiTransportConnection *Tc)
#define AOT_PROFILE_CHANGE
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.
void Del(cCiCaPmt *CaPmt)
cCiMenu * Menu(bool Clear=false)
virtual bool Reset(void)
Resets the CAM in this slot.
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.
bool CamChecked(tChannelID ChannelID, int CamSlotNumber)
bool WantsTsData(void) const
Returns true if this CAM slot wants to receive the TS data through its Decrypt() function.
#define ST_OPEN_SESSION_REQUEST
void Set(int Ms=0)
Sets the timer.
#define MAX_CAM_SLOTS_PER_ADAPTER
void StartDecrypting(void)
Tells all active MTD CAM slots to start decrypting.
void MtdMapPid(uchar *p, cMtdMapper *MtdMapper)
int Transponder(void) const
Returns the transponder frequency in MHz, plus the polarization in case of sat.
void CancelActivation(void)
Tells all active MTD CAM slots to cancel activation.
virtual void SetPid(int Pid, bool Active)
Sets the given Pid (which has previously been added through a call to AddPid()) to Active.
virtual bool Assign(cDevice *Device, bool Query=false)
Assigns this CAM slot to the given Device, if this is possible.
void SetCamSlot(cCamSlot *CamSlot)
Sets the given CamSlot to be used with this device.
void Reply(const char *s)
cList< cCiCaProgramData > caProgramList
void SetChecked(int CamSlotNumber)
virtual void Process(int Length=0, const uint8_t *Data=NULL)
cCiTransportConnection * tc[MAX_CONNECTIONS_PER_CAM_SLOT+1]
int TsPid(const uchar *p)
static int MtdMapStreams(uchar *p, cMtdMapper *MtdMapper, int Length)
void Detach(cFilter *Filter)
Detaches the given filter from this device.
#define RI_APPLICATION_INFORMATION
void Del(cListObject *Object, bool DeleteObject=true)
const int * Dpids(void) const
cDynamicBuffer caDescriptors
bool Running(void)
Returns false if a derived cThread object shall leave its Action() function.
void Set(int Index, uchar Data)
cChannelCamRelation(tChannelID ChannelID)
virtual eModuleStatus ModuleStatus(void)
Returns the status of the CAM in this slot.
cCiTransportConnection(cCamSlot *CamSlot, uint8_t Tcid)
#define CPCI_NOT_SELECTED
virtual const uint32_t * ResourceIds(void) const =0
Returns a pointer to an array of resource identifiers, where the last value is zero.
bool SendAnswer(const char *Text)
void SetDecrypt(int CamSlotNumber)
cCiEnquiry * Enquiry(bool Clear=false)
virtual void Process(int Length=0, const uint8_t *Data=NULL)
bool RemoveElement(const T &Data)
cCiHostControl(uint16_t SessionId, cCiTransportConnection *Tc)
bool deleteConnectionRequested
const cCiResourceHandler * Last(void) const
Returns the last element in this list, or NULL if the list is empty.
virtual ~cCiAdapter()
The derived class must call Cancel(3) in its destructor.
friend class cCiTransportConnection
#define AOT_CLEAR_REPLACE
static bool DumpTPDUDataTransfer
#define QUERY_REPLY_TIMEOUT
void CloseSession(uint16_t SessionId)
virtual void Write(const uint8_t *Buffer, int Length)
Writes Length bytes of the given Buffer.
cCiCaProgramData(int ProgramNumber)
const uint8_t * GetData(const uint8_t *Data, int &Length)
void SendTPDU(uint8_t Tag, int Length=0, const uint8_t *Data=NULL)
int PutCat(const uchar *Data, int Count)
virtual bool IsActivating(void)
Returns true if this CAM slot is currently activating a smart card.
int MasterSlotNumber(void)
Returns the number of this CAM's master slot within the whole system.
virtual void Process(int Length=0, const uint8_t *Data=NULL)
cMtdCamSlot * GetMtdCamSlot(cCamSlot *MasterSlot)
Creates a new MTD CAM slot, or reuses an existing one that is currently unused.
bool AddPid(int Pid)
Adds the given Pid to the list of PIDs of this receiver.
virtual bool ProvidesCa(const int *CaSystemIds)
Returns true if the CAM in this slot provides one of the given CaSystemIds.
virtual void Action(void)
Handles the attached CAM slots in a separate thread.
bool TsIsScrambled(const uchar *p)
bool Load(const char *FileName=NULL, bool AllowComments=false, bool MustExist=false)
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 GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, cDynamicBuffer &Buffer, int EsPid)
Gets all CA descriptors for a given channel.
static int MtdMapCaDescriptor(uchar *p, cMtdMapper *MtdMapper)
cCamSlot * CamSlot(void) const
Returns the CAM slot that is currently used with this device, or NULL if no CAM slot is in use.
virtual bool HasUserIO(void)
Returns true if there is a pending user interaction, which shall be retrieved via GetMenu() or GetEnq...
#define RI_RESOURCE_MANAGER
bool IsDecrypting(void)
Returns true if any of the active MTD CAM slots is currently decrypting.
#define MODULE_RESET_TIMEOUT
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 caSystemIds[MAXCASYSTEMIDS+1]
virtual bool TsPostProcess(uint8_t *TsPacket)
If this cCiSession needs to do additional processing on TS packets (after the CAM has done the decryp...
bool HasCaPids(void) const
cList< cCiCaPidData > pidList
bool AttachReceiver(cReceiver *Receiver)
Attaches the given receiver to this device.
const cCamResponse * First(void) const
Returns the first element in this list, or NULL if the list is empty.
virtual cCiSession * GetNewCiSession(uint32_t ResourceId, uint16_t SessionId, cCiTransportConnection *Tc)
Returns a new cCiSession, according to the given ResourceId.
cCiMMI(uint16_t SessionId, cCiTransportConnection *Tc)
void SendMenuAnswer(uint8_t Selection)
virtual bool RepliesToQuery(void)
Returns true if the CAM in this slot replies to queries and thus supports MCD ("Multi Channel Decrypt...
bool TsPayloadStart(const uchar *p)
void Process(cTPDU *TPDU=NULL)
void AddPid(int Pid, uint8_t StreamType)
bool Process(cTPDU *TPDU=NULL)
cCamSlot * MtdSpawn(void)
If this CAM slot can do MTD ("Multi Transponder Decryption"), a call to this function returns a cMtdC...
cChannelCamRelations ChannelCamRelations
cCamResponses CamResponses
bool CamDecrypt(int CamSlotNumber)
cVector< uint32_t > resourceIds
int NumReadyMasterSlots(void)
Returns the number of master CAM slots in the system that are ready to decrypt.
bool McdAvailable(void)
Returns true if this CAM supports MCD ("Multi Channel Decyption").
void ClrDecrypt(int CamSlotNumber)
cCamSlot * ItCamSlot(int &Iter)
Iterates over all added CAM slots of this adapter.
cCiResourceHandlers CiResourceHandlers
cCamSlot * MasterSlot(void)
Returns this CAM slot's master slot, or a pointer to itself if it is a master slot.
#define STREAM_TYPE_AUDIO
const cCiResourceHandler * Prev(const cCiResourceHandler *Object) const
cCaActivationReceiver(const cChannel *Channel, cCamSlot *CamSlot)
virtual void Process(int Length=0, const uint8_t *Data=NULL)
virtual void AddChannel(const cChannel *Channel)
Adds all PIDs of the given Channel to the current list of PIDs.
#define AOT_APPLICATION_INFO_ENQ
cCiResourceHandlers(void)
Creates the default list of resourceIds.
#define AOT_APPLICATION_INFO
#define CHANNEL_CAM_RELATIONS_CLEANUP_INTERVAL
void Reset(int CamSlotNumber)
#define AOT_DISPLAY_REPLY
virtual void StartActivation(void)
Puts the CAM in this slot into a mode where an inserted smart card can be activated.
tChannelID ChannelID(void)
virtual bool IsDecrypting(void)
Returns true if the CAM in this slot is currently used for decrypting.
const int * GetCaSystemIds(void)
#define RESOURCE_CLASS_MASK
cListObject * Next(void) const
cCiResourceManager(uint16_t SessionId, cCiTransportConnection *Tc)
static void SleepMs(int TimeoutMs)
Creates a cCondWait object and uses it to sleep for TimeoutMs milliseconds, immediately giving up the...
#define STREAM_TYPE_VIDEO
int Ca(int Index=0) const
virtual const uint32_t * ResourceIds(void) const
Returns a pointer to an array of resource identifiers, where the last value is zero.
void Dump(int SlotNumber, bool Outgoing)
void Register(cCiResourceHandler *ResourceHandler)
Adds the given ResourceHandler to the list of resource handlers and appends its ResourceIds to the gl...
void AddCaDescriptors(int Length, const uint8_t *Data)
#define MAX_SESSIONS_PER_TC
cChannelCamRelation * GetEntry(tChannelID ChannelID)
char * GetText(int &Length, const uint8_t **Data)
cMtdMapper * MtdMapper(void)
bool TimedOut(void) const
void StopDecrypting(void)
Tells all active MTD CAM slots to stop decrypting.
void DelPid(int Pid)
Deletes the given Pid from the list of PIDs of this receiver.
virtual bool CanActivate(void)
Returns true if there is a CAM in this slot that can be put into activation mode.
void DeleteAllConnections(void)
const uint8_t * Data(int &Length)
cCiSession * sessions[MAX_SESSIONS_PER_TC+1]
virtual ~cCaActivationReceiver()
#define AOT_DISPLAY_CONTROL
bool TimedWait(cMutex &Mutex, int TimeoutMs)
void MtdEnable(void)
Enables MTD support for this CAM.
int DeviceNumber(void) const
Returns the number of this device (0 ... numDevices - 1).
static bool DebugProtocol
static int MtdMapStream(uchar *p, cMtdMapper *MtdMapper)
const int * Spids(void) const
cVector< cCiCaPmt * > caPmts
cCiSession * GetSessionByResourceId(uint32_t ResourceId)
#define RI_CONDITIONAL_ACCESS_SUPPORT
bool MtdAvailable(void)
Returns true if this CAM supports MTD ("Multi Transponder Decryption").
const cCamResponse * Next(const cCamResponse *Object) const
< Returns the element immediately before Object in this list, or NULL if Object is the first element ...
cCiDateTime(uint16_t SessionId, cCiTransportConnection *Tc)
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 MtdActivate(bool On)
Activates (On == true) or deactivates (On == false) MTD.
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 ...
uint8_t buffer[MAX_TPDU_SIZE]
int Matches(int CamNumber, const char *Text) const
virtual void Append(T Data)
bool IsActivating(void)
Returns true if any of the active MTD CAM slots is currently activating.
cDevice * Device(void)
Returns the device this CAM slot is currently assigned to.
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 SetTsPostProcessor(void)
If this cCiSession implements the TsPostProcess() function, it shall call SetTsPostProcessor() to reg...
int SlotNumber(void)
Returns the number of this CAM slot within the whole system.
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...
static char * CopyString(int Length, const uint8_t *Data)
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...
cCiEnquiry * fetchedEnquiry
int GetMatch(int CamNumber, const char *Text) const
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 ~cCaPidReceiver()
#define AOT_DATE_TIME_ENQ
void SendPMT(cCiCaPmt *CaPmt)
cChannelCamRelations(void)
cCiSession * GetSessionByResourceId(uint32_t ResourceId)
void ClrDecrypt(tChannelID ChannelID, int CamSlotNumber)
cCiConditionalAccessSupport(uint16_t SessionId, cCiTransportConnection *Tc)
static tChannelID FromString(const char *s)
cCiResourceHandler(void)
Creates a new resource handler, through which the available resources can be provides.
cCiSession * GetSessionBySessionId(uint16_t SessionId)
void CreateConnection(void)
virtual int Read(uint8_t *Buffer, int MaxLength)
Reads one chunk of data into the given Buffer, up to MaxLength bytes.
void SendTag(uint8_t Tag, uint16_t SessionId, uint32_t ResourceId=0, int Status=-1)
void UnAssignAll(void)
Unassigns all MTD CAM slots from their devices.
cChannelCamRelation * AddEntry(tChannelID ChannelID)
void Append(const uchar *Data, int Length)
int Priority(void)
Returns the priority of the device this slot is currently assigned to, or IDLEPRIORITY if it is not a...
virtual bool Ready(void)
Returns 'true' if the CAM in this slot is ready to decrypt.
#define MAX_CONNECTIONS_PER_CAM_SLOT
bool Devices(cVector< int > &DeviceNumbers)
Adds the numbers of the devices of any active MTD CAM slots to the given DeviceNumbers.
static char * GetString(int &Length, const uint8_t **Data)
virtual bool HasUserIO(void)
void SetListManagement(uint8_t ListManagement)
bool CamChecked(int CamSlotNumber)
virtual void StopDecrypting(void)
Clears the list of CA_PMT entries and tells the CAM to stop decrypting.
uint32_t ResourceIdToInt(const uint8_t *Data)
const int * Apids(void) const
void HandleSessions(cTPDU *TPDU)
const uint32_t * Ids(void)
#define STREAM_TYPE_PRIVATE
int Priority(void)
Returns the maximum priority of any of the active MTD CAM slots.