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;
185 const uchar *p = NULL;
188 length = (int(Data[6] & 0x03) << 8) | Data[7];
190 int v = (Data[10] & 0x3E) >> 1;
192 if (Data[11] == 0 && Data[12] == 0) {
195 esyslog(
"ERROR: need to implement multi packet CAT handling for MTD!");
197 memcpy(
buffer, Data + 13, n);
207 dsyslog(
"multi table CAT section - unhandled!");
218 memcpy(
bufp, Data + 4, n);
227 esyslog(
"ERROR: buffer overflow in cCaPidReceiver::Receive()");
234 for (
int i = 0; i <
length - 4; i++) {
236 int CaId = int(p[i + 2] << 8) | p[i + 3];
237 int EmmPid =
Peek13(p + i + 4);
242 case 0x01:
for (
int j = i + 7; j < p[i + 1] + 2; j += 4) {
250 i += p[i + 1] + 2 - 1;
284 #define UNSCRAMBLE_TIME 5 // seconds of receiving purely unscrambled data before considering the smart card "activated" 285 #define TS_PACKET_FACTOR 1024 // only process every TS_PACKET_FACTORth packet to keep the load down 315 time_t Now = time(NULL);
325 s->CancelActivation();
336 #define CRA_DISCARD -1 337 #define CRA_CONFIRM -2 338 #define CRA_SELECT -3 348 bool Parse(
const char *s);
349 int Matches(
int CamNumber,
const char *Text)
const;
381 char *t =
const_cast<char *
>(s);
383 bool InQuotes =
false;
393 else if (*t ==
'\\') {
399 memmove(t, t + 1, strlen(t));
401 else if (*t ==
' ') {
410 text = strndup(s, t - s);
430 if (strcmp(
text, Text) == 0)
440 int GetMatch(
int CamNumber,
const char *Text)
const;
446 int Action = cr->Matches(CamNumber, Text);
448 dsyslog(
"CAM %d: auto response %4d to '%s'\n", CamNumber, Action, Text);
464 #define MAX_TPDU_SIZE 4096 465 #define MAX_TPDU_DATA (MAX_TPDU_SIZE - 4) 467 #define DATA_INDICATOR 0x80 471 #define T_CREATE_TC 0x82 472 #define T_CTC_REPLY 0x83 473 #define T_DELETE_TC 0x84 474 #define T_DTC_REPLY 0x85 475 #define T_REQUEST_TC 0x86 476 #define T_NEW_TC 0x87 477 #define T_TC_ERROR 0x88 478 #define T_DATA_LAST 0xA0 479 #define T_DATA_MORE 0xA1 485 const uint8_t *
GetData(
const uint8_t *
Data,
int &Length);
498 void Dump(
int SlotNumber,
bool Outgoing);
501 cTPDU::cTPDU(uint8_t Slot, uint8_t Tcid, uint8_t Tag,
int Length,
const uint8_t *Data)
527 esyslog(
"ERROR: invalid data length for TPDU tag 0x%02X: %d (%d/%d)",
Tag, Length,
Slot,
Tcid);
536 memcpy(p,
Data, Length);
540 esyslog(
"ERROR: invalid data length for TPDU tag 0x%02X: %d (%d/%d)",
Tag, Length,
Slot,
Tcid);
551 fprintf(stderr,
" %d: %s ", SlotNumber, Outgoing ?
"-->" :
"<--");
553 fprintf(stderr,
"%02X ",
buffer[i]);
556 fprintf(stderr,
" ");
558 fprintf(stderr,
"%2c ", isprint(
buffer[i]) ?
buffer[i] :
'.');
585 #define MAX_SESSIONS_PER_TC 16 600 void SendTPDU(uint8_t Tag,
int Length = 0,
const uint8_t *Data = NULL);
601 void SendTag(uint8_t Tag, uint16_t SessionId, uint32_t ResourceId = 0,
int Status = -1);
620 void SendData(
int Length,
const uint8_t *Data);
629 #define ST_SESSION_NUMBER 0x90 630 #define ST_OPEN_SESSION_REQUEST 0x91 631 #define ST_OPEN_SESSION_RESPONSE 0x92 632 #define ST_CREATE_SESSION 0x93 633 #define ST_CREATE_SESSION_RESPONSE 0x94 634 #define ST_CLOSE_SESSION_REQUEST 0x95 635 #define ST_CLOSE_SESSION_RESPONSE 0x96 640 #define SS_NOT_ALLOCATED 0xF0 644 #define RI_RESOURCE_MANAGER 0x00010041 645 #define RI_APPLICATION_INFORMATION 0x00020041 646 #define RI_CONDITIONAL_ACCESS_SUPPORT 0x00030041 647 #define RI_HOST_CONTROL 0x00200041 648 #define RI_DATE_TIME 0x00240041 649 #define RI_MMI 0x00400041 653 #define AOT_NONE 0x000000 654 #define AOT_PROFILE_ENQ 0x9F8010 655 #define AOT_PROFILE 0x9F8011 656 #define AOT_PROFILE_CHANGE 0x9F8012 657 #define AOT_APPLICATION_INFO_ENQ 0x9F8020 658 #define AOT_APPLICATION_INFO 0x9F8021 659 #define AOT_ENTER_MENU 0x9F8022 660 #define AOT_CA_INFO_ENQ 0x9F8030 661 #define AOT_CA_INFO 0x9F8031 662 #define AOT_CA_PMT 0x9F8032 663 #define AOT_CA_PMT_REPLY 0x9F8033 664 #define AOT_TUNE 0x9F8400 665 #define AOT_REPLACE 0x9F8401 666 #define AOT_CLEAR_REPLACE 0x9F8402 667 #define AOT_ASK_RELEASE 0x9F8403 668 #define AOT_DATE_TIME_ENQ 0x9F8440 669 #define AOT_DATE_TIME 0x9F8441 670 #define AOT_CLOSE_MMI 0x9F8800 671 #define AOT_DISPLAY_CONTROL 0x9F8801 672 #define AOT_DISPLAY_REPLY 0x9F8802 673 #define AOT_TEXT_LAST 0x9F8803 674 #define AOT_TEXT_MORE 0x9F8804 675 #define AOT_KEYPAD_CONTROL 0x9F8805 676 #define AOT_KEYPRESS 0x9F8806 677 #define AOT_ENQ 0x9F8807 678 #define AOT_ANSW 0x9F8808 679 #define AOT_MENU_LAST 0x9F8809 680 #define AOT_MENU_MORE 0x9F880A 681 #define AOT_MENU_ANSW 0x9F880B 682 #define AOT_LIST_LAST 0x9F880C 683 #define AOT_LIST_MORE 0x9F880D 684 #define AOT_SUBTITLE_SEGMENT_LAST 0x9F880E 685 #define AOT_SUBTITLE_SEGMENT_MORE 0x9F880F 686 #define AOT_DISPLAY_MESSAGE 0x9F8810 687 #define AOT_SCENE_END_MARK 0x9F8811 688 #define AOT_SCENE_DONE 0x9F8812 689 #define AOT_SCENE_CONTROL 0x9F8813 690 #define AOT_SUBTITLE_DOWNLOAD_LAST 0x9F8814 691 #define AOT_SUBTITLE_DOWNLOAD_MORE 0x9F8815 692 #define AOT_FLUSH_DOWNLOAD 0x9F8816 693 #define AOT_DOWNLOAD_REPLY 0x9F8817 694 #define AOT_COMMS_CMD 0x9F8C00 695 #define AOT_CONNECTION_DESCRIPTOR 0x9F8C01 696 #define AOT_COMMS_REPLY 0x9F8C02 697 #define AOT_COMMS_SEND_LAST 0x9F8C03 698 #define AOT_COMMS_SEND_MORE 0x9F8C04 699 #define AOT_COMMS_RCV_LAST 0x9F8C05 700 #define AOT_COMMS_RCV_MORE 0x9F8C06 702 #define RESOURCE_CLASS_MASK 0xFFFF0000 730 if (Length >= 3 && Data && *Data) {
732 for (
int i = 0; i < 3; i++)
733 t = (t << 8) | *(*Data)++;
743 return Length ? Data : NULL;
754 *p++ = (Tag >> 16) & 0xFF;
755 *p++ = (Tag >> 8) & 0xFF;
758 if (p - buffer + Length <
int(
sizeof(buffer))) {
760 memcpy(p, Data, Length);
765 esyslog(
"ERROR: CAM %d: data length (%d) exceeds buffer size",
CamSlot()->SlotNumber(), Length);
784 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
797 int Tag =
GetTag(Length, &Data);
810 const uint8_t *d =
GetData(Data, l);
812 esyslog(
"ERROR: CAM %d: resource manager: unexpected data",
CamSlot()->SlotNumber());
818 esyslog(
"ERROR: CAM %d: resource manager: unexpected tag %06X in state %d",
CamSlot()->SlotNumber(), Tag,
state);
822 default:
esyslog(
"ERROR: CAM %d: resource manager: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
825 else if (
state == 0) {
850 int Tag =
GetTag(Length, &Data);
855 const uint8_t *d =
GetData(Data, l);
856 if ((l -= 1) < 0)
break;
858 if ((l -= 2) < 0)
break;
861 if ((l -= 2) < 0)
break;
870 default:
esyslog(
"ERROR: CAM %d: application information: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
873 else if (
state == 0) {
892 #define MAXCASYSTEMIDS 64 896 #define CPLM_MORE 0x00 897 #define CPLM_FIRST 0x01 898 #define CPLM_LAST 0x02 899 #define CPLM_ONLY 0x03 900 #define CPLM_ADD 0x04 901 #define CPLM_UPDATE 0x05 905 #define CPCI_OK_DESCRAMBLING 0x01 906 #define CPCI_OK_MMI 0x02 907 #define CPCI_QUERY 0x03 908 #define CPCI_NOT_SELECTED 0x04 923 cCiCaPmt(uint8_t
CmdId,
int Source,
int Transponder,
int ProgramNumber,
const int *CaSystemIds);
927 void AddPid(
int Pid, uint8_t StreamType);
931 cCiCaPmt::cCiCaPmt(uint8_t CmdId,
int Source,
int Transponder,
int ProgramNumber,
const int *CaSystemIds)
939 for (; CaSystemIds[i]; i++)
986 esyslog(
"ERROR: adding CA descriptor without Pid!");
999 esyslog(
"ERROR: wrong length (%d) in MtdMapCaDescriptor()", l);
1002 esyslog(
"ERROR: wrong tag (%d) in MtdMapCaDescriptor()", *p);
1008 int Length = p[0] * 256 + p[1];
1071 #define CAEI_POSSIBLE 0x01 1072 #define CAEI_POSSIBLE_COND_PURCHASE 0x02 1073 #define CAEI_POSSIBLE_COND_TECHNICAL 0x03 1074 #define CAEI_NOT_POSSIBLE_ENTITLEMENT 0x71 1075 #define CAEI_NOT_POSSIBLE_TECHNICAL 0x73 1077 #define CA_ENABLE_FLAG 0x80 1079 #define CA_ENABLE(x) (((x) & CA_ENABLE_FLAG) ? (x) & ~CA_ENABLE_FLAG : 0) 1081 #define QUERY_WAIT_TIME 500 // ms to wait before sending a query 1082 #define QUERY_REPLY_TIMEOUT 2000 // ms to wait for a reply to a query 1083 #define QUERY_RETRIES 6 // max. number of retries to check if there is a reply to a query 1095 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
1117 int Tag =
GetTag(Length, &Data);
1124 const uint8_t *d =
GetData(Data, l);
1126 uint16_t
id = ((uint16_t)(*d) << 8) | *(d + 1);
1134 esyslog(
"ERROR: CAM %d: too many CA system IDs!",
CamSlot()->SlotNumber());
1145 dsyslog(
"CAM %d: system ids:%s",
CamSlot()->SlotNumber(), *Ids ? *Ids :
" none");
1151 if (
CamSlot()->IsMasterSlot())
1152 dsyslog(
"CAM %d: replies to QUERY - multi channel decryption (MCD) possible",
CamSlot()->SlotNumber());
1154 if (
CamSlot()->MtdAvailable()) {
1155 if (
CamSlot()->IsMasterSlot())
1156 dsyslog(
"CAM %d: supports multi transponder decryption (MTD)",
CamSlot()->SlotNumber());
1162 const uint8_t *d =
GetData(Data, l);
1164 uint16_t pnr = ((uint16_t)(*d) << 8) | *(d + 1);
1173 if (l % 3 == 0 && l > 1) {
1179 uint16_t len = ((uint16_t)(*d) << 8) | *(d + 1);
1185 unsigned char caepl = *d;
1193 uint16_t pid = ((uint16_t)(*d) << 8) | *(d + 1);
1194 unsigned char caees = *(d + 2);
1209 default:
esyslog(
"ERROR: CAM %d: conditional access support: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
1212 else if (
state == 0) {
1225 dsyslog(
"CAM %d: doesn't reply to QUERY - only a single channel can be decrypted",
CamSlot()->SlotNumber());
1234 if (CaPmt &&
state >= 2) {
1246 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
1258 int Tag =
GetTag(Length, &Data);
1269 default:
esyslog(
"ERROR: CAM %d: Host Control: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
1283 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
1296 time_t t = time(NULL);
1299 if (gmtime_r(&t, &tm_gmt) && localtime_r(&t, &tm_loc)) {
1300 int Y = tm_gmt.tm_year;
1301 int M = tm_gmt.tm_mon + 1;
1302 int D = tm_gmt.tm_mday;
1303 int L = (M == 1 || M == 2) ? 1 : 0;
1304 int MJD = 14956 + D + int((Y - L) * 365.25) + int((M + 1 + L * 12) * 30.6001);
1305 #define DEC2BCD(d) uint8_t(((d / 10) << 4) + (d % 10)) 1307 struct tTime { uint16_t mjd; uint8_t h, m, s;
short offset; };
1309 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)) };
1322 int Tag =
GetTag(Length, &Data);
1327 const uint8_t *d =
GetData(Data, l);
1335 default:
esyslog(
"ERROR: CAM %d: date time: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
1348 #define DCC_SET_MMI_MODE 0x01 1349 #define DCC_DISPLAY_CHARACTER_TABLE_LIST 0x02 1350 #define DCC_INPUT_CHARACTER_TABLE_LIST 0x03 1351 #define DCC_OVERLAY_GRAPHICS_CHARACTERISTICS 0x04 1352 #define DCC_FULL_SCREEN_GRAPHICS_CHARACTERISTICS 0x05 1356 #define MM_HIGH_LEVEL 0x01 1357 #define MM_LOW_LEVEL_OVERLAY_GRAPHICS 0x02 1358 #define MM_LOW_LEVEL_FULL_SCREEN_GRAPHICS 0x03 1362 #define DRI_MMI_MODE_ACK 0x01 1363 #define DRI_LIST_DISPLAY_CHARACTER_TABLES 0x02 1364 #define DRI_LIST_INPUT_CHARACTER_TABLES 0x03 1365 #define DRI_LIST_GRAPHIC_OVERLAY_CHARACTERISTICS 0x04 1366 #define DRI_LIST_FULL_SCREEN_GRAPHIC_CHARACTERISTICS 0x05 1367 #define DRI_UNKNOWN_DISPLAY_CONTROL_CMD 0xF0 1368 #define DRI_UNKNOWN_MMI_MODE 0xF1 1369 #define DRI_UNKNOWN_CHARACTER_TABLE 0xF2 1373 #define EF_BLIND 0x01 1377 #define AI_CANCEL 0x00 1378 #define AI_ANSWER 0x01 1382 char *
GetText(
int &Length,
const uint8_t **Data);
1388 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
1424 int Tag =
GetTag(Length, Data);
1431 esyslog(
"ERROR: CAM %d: MMI: unexpected text tag: %06X",
CamSlot()->SlotNumber(), Tag);
1438 int Tag =
GetTag(Length, &Data);
1443 const uint8_t *d =
GetData(Data, l);
1448 struct tDisplayReply { uint8_t id; uint8_t mode; };
1454 default:
esyslog(
"ERROR: CAM %d: MMI: unsupported display control command %02X",
CamSlot()->SlotNumber(), *d);
1465 const uint8_t *d =
GetData(Data, l);
1505 dsyslog(
"CAM %d: SELECT %d",
CamSlot()->SlotNumber(), Select + 1);
1516 const uint8_t *d =
GetData(Data, l);
1518 uint8_t blind = *d++;
1529 snprintf(s,
sizeof(s),
"%d", Action);
1546 const uint8_t *d =
GetData(Data, l);
1555 default:
esyslog(
"ERROR: CAM %d: MMI: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
1591 struct tAnswer { uint8_t id;
char text[256]; };
1596 len =
min(
sizeof(answer.text), strlen(Text));
1597 memcpy(answer.text, Text, len);
1725 static uint32_t Ids[] = {
1739 switch (ResourceId) {
1746 default:
return NULL;
1761 if (ResourceHandler) {
1762 Add(ResourceHandler);
1763 if (
const uint32_t *r = ResourceHandler->
ResourceIds()) {
1775 if (
cCiSession *CiSession = r->GetNewCiSession(ResourceId, SessionId, Tc))
1783 #define TC_POLL_TIMEOUT 300 // ms WORKAROUND: TC_POLL_TIMEOUT < 300ms doesn't work with DragonCAM 1784 #define TC_ALIVE_TIMEOUT 2000 // ms after which a transport connection is assumed dead 1822 return cas && cas->
Ready();
1848 uint8_t *p = buffer;
1859 buffer[1] = p - buffer - 2;
1888 if (s->ResourceId() == ResourceId)
1899 if (Length == 6 && *(Data + 1) == 0x04) {
1924 if (Session &&
sessions[SessionId] == Session) {
1938 const uint8_t *Data = TPDU->
Data(Length);
1939 if (Data && Length > 1) {
1942 uint16_t SessionId = ntohs(
get_unaligned((uint16_t *)&Data[2]));
1945 Session->
Process(Length - 4, Data + 4);
1997 switch (TPDU->
Tag()) {
2024 esyslog(
"ERROR: unknown TPDU tag: 0x%02X (%s)", TPDU->
Tag(), __FUNCTION__);
2045 esyslog(
"ERROR: unknown state: %d (%s)",
state, __FUNCTION__);
2113 esyslog(
"ERROR: no free CAM slot in CI adapter");
2149 #define MODULE_CHECK_INTERVAL 500 // ms 2150 #define MODULE_RESET_TIMEOUT 2 // s 2201 int OldDeviceNumber = 0;
2243 return DeviceNumbers.
Size() > 0;
2272 int n = TPDU->
Tcid();
2317 esyslog(
"ERROR: unknown module status %d (%s)", ms, __FUNCTION__);
2381 dsyslog(
"CAM %d: activating on device %d with channel %d (%s)",
SlotNumber(), d->DeviceNumber() + 1, Channel->Number(), Channel->Name());
2483 cCiCaPmt *p =
new cCiCaPmt(CmdId, Source, Transponder, ProgramNumber, CaSystemIds);
2506 if (CaSystemIds && *CaSystemIds) {
2510 bool Active = p->Active();
2514 CaPmt->
AddPid(q->pid, q->streamType);
2531 p->modified =
false;
2536 CaPmtList.
Add(CmdId, 0, 0, 0, NULL);
2543 int *pCaPids = CaPids;
2552 if (p->programNumber != ProgramNumber) {
2554 int *pCaPids2 = CaPids2;
2558 if (*pCaPids == *pCaPids2) {
2561 *pCaPids = CaPids[numPids - 1];
2563 CaPids[numPids] = 0;
2582 for (
int i = 0; i < CaPmtList.
caPmts.
Size(); i++)
2643 for (
const int *ids = cas->
GetCaSystemIds(); ids && *ids; ids++) {
2644 for (
const int *
id = CaSystemIds; *id;
id++) {
2658 if (p->programNumber == ProgramNumber) {
2678 if (q->pid == Pid) {
2679 if (q->active != Active) {
2690 #define STREAM_TYPE_VIDEO 0x02 2691 #define STREAM_TYPE_AUDIO 0x04 2692 #define STREAM_TYPE_PRIVATE 0x06 2703 for (
const int *Apid = Channel->
Apids(); *Apid; Apid++)
2705 for (
const int *Dpid = Channel->
Dpids(); *Dpid; Dpid++)
2707 for (
const int *Spid = Channel->
Spids(); *Spid; Spid++)
2712 #define QUERY_REPLY_WAIT 100 // ms to wait between checks for a reply 2726 for (
const int *Apid = Channel->
Apids(); *Apid; Apid++)
2728 for (
const int *Dpid = Channel->
Dpids(); *Dpid; Dpid++)
2730 for (
const int *Spid = Channel->
Spids(); *Spid; Spid++)
2733 CaPmt.MtdMapPids(MtdMapper);
2760 if (!dynamic_cast<cMtdCamSlot *>(
this))
2814 if (CamSlot->IsMasterSlot() && CamSlot->ModuleStatus() ==
msReady)
2823 for (time_t t0 = time(NULL); time(NULL) - t0 < Timeout; ) {
2826 if (!CamSlot->Ready()) {
2835 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()));
2841 #define CAM_CHECKED_TIMEOUT 15 // seconds before a CAM that has been checked for a particular channel will be checked again 2914 #define MAX_CAM_NUMBER 32 2915 #define CHANNEL_CAM_RELATIONS_CLEANUP_INTERVAL 3600 // seconds between cleanups 2943 if (ccr->ChannelID() == ChannelID)
2962 ccr->ClrChecked(CamSlotNumber);
2963 ccr->ClrDecrypt(CamSlotNumber);
2971 return ccr ? ccr->
CamChecked(CamSlotNumber) :
false;
2978 return ccr ? ccr->
CamDecrypt(CamSlotNumber) :
false;
3019 if (FILE *f = fopen(
fileName,
"r")) {
3022 while ((s = ReadLine.
Read(f)) != NULL) {
3023 if (
char *p = strchr(s,
' ')) {
3027 if (ChannelID.
Valid()) {
3030 while ((q = strtok_r(p,
" ", &strtok_next)) != NULL) {
3031 int CamSlotNumber = atoi(q);
3054 if ((st.st_mode & S_IWUSR) == 0) {
3063 if (ccr->ChannelID().Valid()) {
3066 if (ccr->CamDecrypt(i))
3070 fprintf(f,
"%s %s\n", *ccr->ChannelID().ToString(), *s);
cCiHostControl(uint16_t SessionId, cCiTransportConnection *Tc)
virtual void Process(int Length=0, const uint8_t *Data=NULL)
cCiCaProgramData(int ProgramNumber)
#define AOT_DISPLAY_CONTROL
static int MtdMapStream(uchar *p, cMtdMapper *MtdMapper)
virtual void Action(void)
Handles the attached CAM slots in a separate thread.
cCamSlot * MtdSpawn(void)
If this CAM slot can do MTD ("Multi Transponder Decryption"), a call to this function returns a cMtdC...
bool Process(cTPDU *TPDU=NULL)
static tChannelID FromString(const char *s)
cCamSlot * CamSlot(void) const
Returns the CAM slot that is currently used with this device, or NULL if no CAM slot is in use...
cCiCaPidData(int Pid, int StreamType)
cVector< cCiCaPmt * > caPmts
int MasterSlotNumber(void)
Returns the number of this CAM's master slot within the whole system.
virtual bool ProvidesCa(const int *CaSystemIds)
Returns true if the CAM in this slot provides one of the given CaSystemIds.
static char * CopyString(int Length, const uint8_t *Data)
virtual ~cCiAdapter()
The derived class must call Cancel(3) in its destructor.
virtual bool HasUserIO(void)
const uint32_t * Ids(void)
virtual void StartActivation(void)
Puts the CAM in this slot into a mode where an inserted smart card can be activated.
cCamSlot * ItCamSlot(int &Iter)
Iterates over all added CAM slots of this adapter.
bool RemoveElement(const T &Data)
cCiSession(uint16_t SessionId, uint32_t ResourceId, cCiTransportConnection *Tc)
bool Devices(cVector< int > &DeviceNumbers)
Adds the numbers of the devices of any active MTD CAM slots to the given DeviceNumbers.
cList< cCiCaPidData > pidList
virtual void AddPid(int ProgramNumber, int Pid, int StreamType)
Adds the given PID information to the list of PIDs.
virtual void Write(const uint8_t *Buffer, int Length)
Writes Length bytes of the given Buffer.
void Add(cListObject *Object, cListObject *After=NULL)
#define AOT_PROFILE_CHANGE
bool CamChecked(int CamSlotNumber)
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 ...
virtual void StartDecrypting(void)
Sends all CA_PMT entries to the CAM that have been modified since the last call to this function...
int caSystemIds[MAXCASYSTEMIDS+1]
bool TsPayloadStart(const uchar *p)
#define MAX_CONNECTIONS_PER_CAM_SLOT
static char * GetString(int &Length, const uint8_t **Data)
static int MtdMapCaDescriptors(uchar *p, cMtdMapper *MtdMapper)
void MtdActivate(bool On)
Activates (On == true) or deactivates (On == false) MTD.
#define MAX_CAM_SLOTS_PER_ADAPTER
#define AOT_APPLICATION_INFO_ENQ
cCiResourceHandlers CiResourceHandlers
virtual bool TsPostProcess(uchar *Data)
If there is a cCiSession that needs to do additional processing on TS packets (after the CAM has done...
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 ...
static cString sprintf(const char *fmt,...) __attribute__((format(printf
bool MtdAvailable(void)
Returns true if this CAM supports MTD ("Multi Transponder Decryption").
cCamResponses CamResponses
#define CHANNEL_CAM_RELATIONS_CLEANUP_INTERVAL
virtual void Append(T Data)
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.
virtual void Process(int Length=0, const uint8_t *Data=NULL)
int NumReadyMasterSlots(void)
Returns the number of master CAM slots in the system that are ready to decrypt.
void SetCamSlot(cCamSlot *CamSlot)
Sets the given CamSlot to be used with this device.
#define RESOURCE_CLASS_MASK
#define dbgprotocol(a...)
#define ST_CLOSE_SESSION_RESPONSE
virtual void Process(int Length=0, const uint8_t *Data=NULL)
void Detach(cFilter *Filter)
Detaches the given filter from this device.
static u_int32_t crc32(const char *d, int len, u_int32_t CRCvalue)
bool AttachReceiver(cReceiver *Receiver)
Attaches the given receiver to this device.
void MtdEnable(void)
Enables MTD support for this CAM.
virtual bool CanActivate(void)
Returns true if there is a CAM in this slot that can be put into activation mode. ...
static bool DumpTPDUDataTransfer
bool AddPids(const int *Pids)
Adds the given zero terminated list of Pids to the list of PIDs of this receiver. ...
uint8_t ListManagement(void)
bool Load(const char *FileName=NULL, bool AllowComments=false, bool MustExist=false)
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.
bool Parse(const char *s)
int GetTag(int &Length, const uint8_t **Data)
#define CPCI_NOT_SELECTED
virtual void Process(int Length=0, const uint8_t *Data=NULL)
#define AOT_APPLICATION_INFO
const int * GetCaSystemIds(void)
const int * Spids(void) const
#define STREAM_TYPE_VIDEO
friend class cCiTransportConnection
virtual ~cCaPidReceiver()
void Set(int Index, uchar Data)
cCiSession * GetSessionByResourceId(uint32_t ResourceId)
char * GetText(int &Length, const uint8_t **Data)
int SlotIndex(void)
Returns the index of this CAM slot within its CI adapter.
cCiSession * GetNewCiSession(uint32_t ResourceId, uint16_t SessionId, cCiTransportConnection *Tc)
int Ca(int Index=0) const
#define ST_SESSION_NUMBER
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...
bool CamDecrypt(int CamSlotNumber)
virtual eModuleStatus ModuleStatus(void)
Returns the status of the CAM in this slot.
void AddPid(int Pid, uint8_t StreamType)
cCiSession * sessions[MAX_SESSIONS_PER_TC+1]
virtual void AddChannel(const cChannel *Channel)
Adds all PIDs of the given Channel to the current list of PIDs.
uint32_t ResourceId(void)
const int * Apids(void) const
void SetListManagement(uint8_t ListManagement)
#define RI_CONDITIONAL_ACCESS_SUPPORT
int TsPid(const uchar *p)
virtual void SendCaPmt(uint8_t CmdId)
bool McdAvailable(void)
Returns true if this CAM supports MCD ("Multi Channel Decyption").
virtual bool Reset(int Slot)
Resets the CAM in the given Slot.
cCiTransportConnection * tc[MAX_CONNECTIONS_PER_CAM_SLOT+1]
void KeepSharedCaPids(int ProgramNumber, const int *CaSystemIds, int *CaPids)
void CreateConnection(void)
int GetMatch(int CamNumber, const char *Text) const
cCaActivationReceiver * caActivationReceiver
void SendTag(uint8_t Tag, uint16_t SessionId, uint32_t ResourceId=0, int Status=-1)
static int MtdMapCaDescriptor(uchar *p, cMtdMapper *MtdMapper)
void CancelActivation(void)
Tells all active MTD CAM slots to cancel activation.
void MtdMapPid(uchar *p, cMtdMapper *MtdMapper)
int Transponder(void) const
Returns the transponder frequency in MHz, plus the polarization in case of sat.
#define MODULE_RESET_TIMEOUT
static int CurrentChannel(void)
Returns the number of the current channel on the primary device.
void DelPids(const int *Pids)
Deletes the given zero terminated list of Pids from the list of PIDs of this receiver.
#define ST_CLOSE_SESSION_REQUEST
cCiTransportConnection * tc
cCiSession * GetSessionByResourceId(uint32_t ResourceId)
int caSystemIds[MAXCASYSTEMIDS+1]
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 void Process(int Length=0, const uint8_t *Data=NULL)
const int * Dpids(void) const
cChannelCamRelation(tChannelID ChannelID)
virtual cCiSession * GetNewCiSession(uint32_t ResourceId, uint16_t SessionId, cCiTransportConnection *Tc)
Returns a new cCiSession, according to the given ResourceId.
uint32_t ResourceIdToInt(const uint8_t *Data)
void HandleSessions(cTPDU *TPDU)
void Process(cTPDU *TPDU=NULL)
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...
virtual ~cCiResourceHandler()
void GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, cDynamicBuffer &Buffer, int EsPid)
Gets all CA descriptors for a given channel.
virtual bool HasUserIO(void)
Returns true if there is a pending user interaction, which shall be retrieved via GetMenu() or GetEnq...
void SetDecrypt(tChannelID ChannelID, int CamSlotNumber)
void SendData(int Tag, int Length=0, const uint8_t *Data=NULL)
cCiSession * GetSessionBySessionId(uint16_t SessionId)
virtual cCiMenu * GetMenu(void)
Gets a pending menu, or NULL if there is no menu.
bool SendAnswer(const char *Text)
void StartDecrypting(void)
Tells all active MTD CAM slots to start decrypting.
#define LOCK_CHANNELS_READ
cCiConditionalAccessSupport(uint16_t SessionId, cCiTransportConnection *Tc)
#define ST_OPEN_SESSION_RESPONSE
static void SleepMs(int TimeoutMs)
Creates a cCondWait object and uses it to sleep for TimeoutMs milliseconds, immediately giving up the...
cList< cCiCaProgramData > caProgramList
#define STREAM_TYPE_AUDIO
cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds)
#define ST_OPEN_SESSION_REQUEST
cDynamicBuffer caDescriptors
void MtdMapPids(cMtdMapper *MtdMapper)
virtual ~cCiTransportConnection()
cCiEnquiry * Enquiry(bool Clear=false)
int Matches(int CamNumber, const char *Text) const
bool WantsTsData(void) const
Returns true if this CAM slot wants to receive the TS data through its Decrypt() function.
cMtdCamSlot * GetMtdCamSlot(cCamSlot *MasterSlot)
Creates a new MTD CAM slot, or reuses an existing one that is currently unused.
#define AOT_DISPLAY_REPLY
void ClrChecked(int CamSlotNumber)
cVector< uint32_t > resourceIds
bool CamDecrypt(tChannelID ChannelID, int CamSlotNumber)
virtual int Read(uint8_t *Buffer, int MaxLength)
Reads one chunk of data into the given Buffer, up to MaxLength bytes.
void Load(const char *FileName)
#define MAX_SESSIONS_PER_TC
eModuleStatus lastModuleStatus
#define STREAM_TYPE_PRIVATE
void AddCamSlot(cCamSlot *CamSlot)
Adds the given CamSlot to this CI adapter.
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.
bool Running(void)
Returns false if a derived cThread object shall leave its Action() function.
const cCiResourceHandler * Last(void) const
Returns the last element in this list, or NULL if the list is empty.
cCiTransportConnection * Tc(void)
bool Devices(cVector< int > &DeviceNumbers)
Adds the numbers of any devices that currently use this CAM to the given DeviceNumbers.
bool HandlingPid(void)
The cCaPidReceiver adds/deletes PIDs to/from the base class cReceiver, which in turn does the same on...
bool TimedWait(cMutex &Mutex, int TimeoutMs)
cCiSession * tsPostProcessor
void OpenSession(int Length, const uint8_t *Data)
#define AOT_CLEAR_REPLACE
virtual const int * GetCaSystemIds(void)
void SetChecked(int CamSlotNumber)
#define CPCI_OK_DESCRAMBLING
void Dump(int SlotNumber, bool Outgoing)
cCiResourceHandlers(void)
Creates the default list of resourceIds.
bool AddPid(int Pid)
Adds the given Pid to the list of PIDs of this receiver.
const cCiResourceHandler * Prev(const cCiResourceHandler *Object) const
cCamSlot * MasterSlot(void)
Returns this CAM slot's master slot, or a pointer to itself if it is a master slot.
int PutCat(const uchar *Data, int Count)
const cCamResponse * First(void) const
Returns the first element in this list, or NULL if the list is empty.
static uint8_t * SetLength(uint8_t *Data, int Length)
virtual bool Reset(void)
Resets the CAM in this slot.
void SendCaPmts(cCiCaPmtList &CaPmtList)
Sends the given list of CA_PMTs to the CAM.
bool CamResponsesLoad(const char *FileName, bool AllowComments, bool MustExist)
virtual bool IsDecrypting(void)
Returns true if the CAM in this slot is currently used for decrypting.
bool createConnectionRequested
cCiMMI(uint16_t SessionId, cCiTransportConnection *Tc)
void SendMenuAnswer(uint8_t Selection)
void SendData(int Length, const uint8_t *Data)
const char * GetCamName(void)
void DelPid(int Pid)
Deletes the given Pid from the list of PIDs of this receiver.
void ClrDecrypt(tChannelID ChannelID, int CamSlotNumber)
void Del(cCiCaPmt *CaPmt)
virtual void SetPid(int Pid, bool Active)
Sets the given Pid (which has previously been added through a call to AddPid()) to Active...
bool HasCaPids(void) const
cCamSlot * camSlots[MAX_CAM_SLOTS_PER_ADAPTER]
virtual cCiEnquiry * GetEnquiry(void)
Gets a pending enquiry, or NULL if there is no enquiry.
cChannelCamRelation * AddEntry(tChannelID ChannelID)
cCiDateTime(uint16_t SessionId, cCiTransportConnection *Tc)
void SetTsPostProcessor(cCiSession *CiSession)
#define AOT_DATE_TIME_ENQ
bool WaitForAllCamSlotsReady(int Timeout=0)
Waits until all CAM slots have become ready, or the given Timeout (seconds) has expired.
#define CAM_CHECKED_TIMEOUT
void Del(cListObject *Object, bool DeleteObject=true)
bool TsPostProcess(uint8_t *TsPacket)
#define RI_RESOURCE_MANAGER
int DeviceNumber(void) const
Returns the number of this device (0 ... numDevices - 1).
bool IsDecrypting(void)
Returns true if any of the active MTD CAM slots is currently decrypting.
virtual void Process(int Length=0, const uint8_t *Data=NULL)
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...
void SendPMT(cCiCaPmt *CaPmt)
void Reply(const char *s)
void MtdMapSid(uchar *p, cMtdMapper *MtdMapper)
cCiMenu * Menu(bool Clear=false)
virtual eModuleStatus ModuleStatus(int Slot)
Returns the status of the CAM in the given Slot.
virtual bool HasMMI(void)
Returns 'true' if the CAM in this slot has an active MMI.
virtual ~cCaActivationReceiver()
cCaActivationReceiver(const cChannel *Channel, cCamSlot *CamSlot)
#define MODULE_CHECK_INTERVAL
tChannelID ChannelID(void)
void SetChecked(tChannelID ChannelID, int CamSlotNumber)
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...
cCiEnquiry * fetchedEnquiry
void ClrDecrypt(int CamSlotNumber)
cCiResourceHandler(void)
Creates a new resource handler, through which the available resources can be provides.
bool TsIsScrambled(const uchar *p)
cChannelCamRelations ChannelCamRelations
cListObject * Next(void) const
virtual bool Ready(void)
Returns 'true' if the CAM in this slot is ready to decrypt.
void DeleteConnection(void)
cCaPidReceiver * caPidReceiver
virtual void CancelActivation(void)
Cancels a previously started activation (if any).
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 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...
int Priority(void)
Returns the priority of the device this slot is currently assigned to, or IDLEPRIORITY if it is not a...
bool CamChecked(tChannelID ChannelID, int CamSlotNumber)
virtual void StopDecrypting(void)
Clears the list of CA_PMT entries and tells the CAM to stop decrypting.
void Append(const uchar *Data, int Length)
virtual bool TsPostProcess(uint8_t *TsPacket)
If this cCiSession needs to do additional processing on TS packets (after the CAM has done the decryp...
void ClrChecked(tChannelID ChannelID, int CamSlotNumber)
void AddCaDescriptors(int Length, const uint8_t *Data)
const uint8_t * GetData(const uint8_t *Data, int &Length)
void Reset(int CamSlotNumber)
cCiTransportConnection(cCamSlot *CamSlot, uint8_t Tcid)
virtual bool EnterMenu(void)
Requests the CAM in this slot to start its menu.
int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids)
Gets all CA pids for a given channel.
void Register(cCiResourceHandler *ResourceHandler)
Adds the given ResourceHandler to the list of resource handlers and appends its ResourceIds to the gl...
#define ST_CREATE_SESSION_RESPONSE
#define QUERY_REPLY_TIMEOUT
cCamSlot(cCiAdapter *CiAdapter, bool WantsTsData=false, cCamSlot *MasterSlot=NULL)
Creates a new CAM slot for the given CiAdapter.
static const uint8_t * GetLength(const uint8_t *Data, int &Length)
void UnAssignAll(void)
Unassigns all MTD CAM slots from their devices.
bool deleteConnectionRequested
void CloseSession(uint16_t SessionId)
virtual bool Assign(cDevice *Device, bool Query=false)
Assigns this adapter to the given Device, if this is possible.
uint8_t buffer[MAX_TPDU_SIZE]
cChannelCamRelation * GetEntry(tChannelID ChannelID)
#define RI_APPLICATION_INFORMATION
virtual bool Assign(cDevice *Device, bool Query=false)
Assigns this CAM slot to the given Device, if this is possible.
virtual const uint32_t * ResourceIds(void) const
Returns a pointer to an array of resource identifiers, where the last value is zero.
bool IsActivating(void)
Returns true if any of the active MTD CAM slots is currently activating.
virtual bool IsActivating(void)
Returns true if this CAM slot is currently activating a smart card.
void SendTPDU(uint8_t Tag, 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...
cMtdMapper * MtdMapper(void)
cCiCaPmt * Add(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds)
cChannelCamRelations(void)
void DeleteAllConnections(void)
void SetResourceId(uint32_t Id)
If this is a class that has been derived from an existing cCiSession class, but implements a differen...
bool RepliesToQuery(void)
const uint8_t * Data(int &Length)
int Priority(void)
Returns the maximum priority of any of the active MTD CAM slots.
static int MtdMapStreams(uchar *p, cMtdMapper *MtdMapper, int Length)
int Priority(void) const
Returns the priority of the current receiving session (-MAXPRIORITY..MAXPRIORITY), or IDLEPRIORITY if no receiver is currently active.
int SlotNumber(void)
Returns the number of this CAM slot within the whole system.
uchar mtdCatBuffer[TS_SIZE]
static bool DebugProtocol
cCiResourceManager(uint16_t SessionId, cCiTransportConnection *Tc)
virtual const uint32_t * ResourceIds(void) const =0
Returns a pointer to an array of resource identifiers, where the last value is zero.
cDevice * Device(void)
Returns the device this CAM slot is currently assigned to.
bool TimedOut(void) const
virtual bool RepliesToQuery(void)
Returns true if the CAM in this slot replies to queries and thus supports MCD ("Multi Channel Decrypt...
const cCamResponse * Next(const cCamResponse *Object) const
< Returns the element immediately before Object in this list, or NULL if Object is the first element ...
void SetDecrypt(int CamSlotNumber)