12 #include <linux/dvb/ca.h> 14 #include <netinet/in.h> 18 #include <sys/ioctl.h> 36 #define dbgprotocol(a...) if (DebugProtocol) fprintf(stderr, a) 40 #define SIZE_INDICATOR 0x80 42 static const uint8_t *
GetLength(
const uint8_t *Data,
int &Length)
49 int l = Length & ~SIZE_INDICATOR;
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;
274 #define UNSCRAMBLE_TIME 5 // seconds of receiving purely unscrambled data before considering the smart card "activated" 275 #define TS_PACKET_FACTOR 1024 // only process every TS_PACKET_FACTORth packet to keep the load down 305 time_t Now = time(NULL);
315 s->CancelActivation();
326 #define CRA_DISCARD -1 327 #define CRA_CONFIRM -2 328 #define CRA_SELECT -3 338 bool Parse(
const char *s);
339 int Matches(
int CamNumber,
const char *Text)
const;
364 camNumber = strtol(s, &e, 10);
365 if (e == s || camNumber <= 0)
371 char *t =
const_cast<char *
>(s);
373 bool InQuotes =
false;
383 else if (*t ==
'\\') {
389 memmove(t, t + 1, strlen(t));
391 else if (*t ==
' ') {
400 text = strndup(s, t - s);
408 if (strcasecmp(s,
"DISCARD") == 0) action =
CRA_DISCARD;
409 else if (strcasecmp(s,
"CONFIRM") == 0) action =
CRA_CONFIRM;
410 else if (strcasecmp(s,
"SELECT") == 0) action =
CRA_SELECT;
411 else if (
isnumber(s)) action = atoi(s);
419 if (!camNumber || camNumber == CamNumber) {
420 if (strcmp(text, Text) == 0)
430 int GetMatch(
int CamNumber,
const char *Text)
const;
435 for (
const cCamResponse *cr = First(); cr; cr = Next(cr)) {
436 int Action = cr->Matches(CamNumber, Text);
438 dsyslog(
"CAM %d: auto response %4d to '%s'\n", CamNumber, Action, Text);
449 return CamResponses.
Load(FileName, AllowComments, MustExist);
454 #define MAX_TPDU_SIZE 4096 455 #define MAX_TPDU_DATA (MAX_TPDU_SIZE - 4) 457 #define DATA_INDICATOR 0x80 461 #define T_CREATE_TC 0x82 462 #define T_CTC_REPLY 0x83 463 #define T_DELETE_TC 0x84 464 #define T_DTC_REPLY 0x85 465 #define T_REQUEST_TC 0x86 466 #define T_NEW_TC 0x87 467 #define T_TC_ERROR 0x88 468 #define T_DATA_LAST 0xA0 469 #define T_DATA_MORE 0xA1 475 const uint8_t *GetData(
const uint8_t *Data,
int &Length);
478 cTPDU(uint8_t Slot, uint8_t Tcid, uint8_t Tag,
int Length = 0,
const uint8_t *Data = NULL);
479 uint8_t
Slot(
void) {
return buffer[0]; }
480 uint8_t
Tcid(
void) {
return buffer[1]; }
481 uint8_t
Tag(
void) {
return buffer[2]; }
482 const uint8_t *
Data(
int &Length) {
return GetData(buffer + 3, Length); }
483 uint8_t Status(
void);
485 int Size(
void) {
return size; }
488 void Dump(
int SlotNumber,
bool Outgoing);
491 cTPDU::cTPDU(uint8_t Slot, uint8_t Tcid, uint8_t Tag,
int Length,
const uint8_t *Data)
517 esyslog(
"ERROR: invalid data length for TPDU tag 0x%02X: %d (%d/%d)", Tag, Length, Slot, Tcid);
522 uint8_t *p = buffer + 3;
526 memcpy(p, Data, Length);
527 size = Length + (p - buffer);
530 esyslog(
"ERROR: invalid data length for TPDU tag 0x%02X: %d (%d/%d)", Tag, Length, Slot, Tcid);
533 esyslog(
"ERROR: unknown TPDU tag: 0x%02X (%d/%d)", Tag, Slot, Tcid);
541 fprintf(stderr,
" %d: %s ", SlotNumber, Outgoing ?
"-->" :
"<--");
542 for (
int i = 0; i < size && i <
MAX_DUMP; i++)
543 fprintf(stderr,
"%02X ", buffer[i]);
544 fprintf(stderr,
"%s\n", size >= MAX_DUMP ?
"..." :
"");
546 fprintf(stderr,
" ");
547 for (
int i = 0; i < size && i <
MAX_DUMP; i++)
548 fprintf(stderr,
"%2c ", isprint(buffer[i]) ? buffer[i] :
'.');
549 fprintf(stderr,
"%s\n", size >= MAX_DUMP ?
"..." :
"");
568 if (size >= 4 && buffer[size - 4] ==
T_SB && buffer[size - 3] == 2)
569 return buffer[size - 1];
575 #define MAX_SESSIONS_PER_TC 16 590 void SendTPDU(uint8_t Tag,
int Length = 0,
const uint8_t *Data = NULL);
591 void SendTag(uint8_t Tag, uint16_t SessionId, uint32_t ResourceId = 0,
int Status = -1);
593 uint32_t ResourceIdToInt(
const uint8_t *Data);
594 cCiSession *GetSessionBySessionId(uint16_t SessionId);
595 void OpenSession(
int Length,
const uint8_t *Data);
596 void CloseSession(uint16_t SessionId);
597 void HandleSessions(
cTPDU *TPDU);
601 void SetTsPostProcessor(
cCiSession *CiSession);
602 bool TsPostProcess(uint8_t *TsPacket);
604 uint8_t
Tcid(
void)
const {
return tcid; }
607 const char *GetCamName(
void);
610 void SendData(
int Length,
const uint8_t *Data);
611 bool Process(
cTPDU *TPDU = NULL);
612 cCiSession *GetSessionByResourceId(uint32_t ResourceId);
619 #define ST_SESSION_NUMBER 0x90 620 #define ST_OPEN_SESSION_REQUEST 0x91 621 #define ST_OPEN_SESSION_RESPONSE 0x92 622 #define ST_CREATE_SESSION 0x93 623 #define ST_CREATE_SESSION_RESPONSE 0x94 624 #define ST_CLOSE_SESSION_REQUEST 0x95 625 #define ST_CLOSE_SESSION_RESPONSE 0x96 630 #define SS_NOT_ALLOCATED 0xF0 634 #define RI_RESOURCE_MANAGER 0x00010041 635 #define RI_APPLICATION_INFORMATION 0x00020041 636 #define RI_CONDITIONAL_ACCESS_SUPPORT 0x00030041 637 #define RI_HOST_CONTROL 0x00200041 638 #define RI_DATE_TIME 0x00240041 639 #define RI_MMI 0x00400041 643 #define AOT_NONE 0x000000 644 #define AOT_PROFILE_ENQ 0x9F8010 645 #define AOT_PROFILE 0x9F8011 646 #define AOT_PROFILE_CHANGE 0x9F8012 647 #define AOT_APPLICATION_INFO_ENQ 0x9F8020 648 #define AOT_APPLICATION_INFO 0x9F8021 649 #define AOT_ENTER_MENU 0x9F8022 650 #define AOT_CA_INFO_ENQ 0x9F8030 651 #define AOT_CA_INFO 0x9F8031 652 #define AOT_CA_PMT 0x9F8032 653 #define AOT_CA_PMT_REPLY 0x9F8033 654 #define AOT_TUNE 0x9F8400 655 #define AOT_REPLACE 0x9F8401 656 #define AOT_CLEAR_REPLACE 0x9F8402 657 #define AOT_ASK_RELEASE 0x9F8403 658 #define AOT_DATE_TIME_ENQ 0x9F8440 659 #define AOT_DATE_TIME 0x9F8441 660 #define AOT_CLOSE_MMI 0x9F8800 661 #define AOT_DISPLAY_CONTROL 0x9F8801 662 #define AOT_DISPLAY_REPLY 0x9F8802 663 #define AOT_TEXT_LAST 0x9F8803 664 #define AOT_TEXT_MORE 0x9F8804 665 #define AOT_KEYPAD_CONTROL 0x9F8805 666 #define AOT_KEYPRESS 0x9F8806 667 #define AOT_ENQ 0x9F8807 668 #define AOT_ANSW 0x9F8808 669 #define AOT_MENU_LAST 0x9F8809 670 #define AOT_MENU_MORE 0x9F880A 671 #define AOT_MENU_ANSW 0x9F880B 672 #define AOT_LIST_LAST 0x9F880C 673 #define AOT_LIST_MORE 0x9F880D 674 #define AOT_SUBTITLE_SEGMENT_LAST 0x9F880E 675 #define AOT_SUBTITLE_SEGMENT_MORE 0x9F880F 676 #define AOT_DISPLAY_MESSAGE 0x9F8810 677 #define AOT_SCENE_END_MARK 0x9F8811 678 #define AOT_SCENE_DONE 0x9F8812 679 #define AOT_SCENE_CONTROL 0x9F8813 680 #define AOT_SUBTITLE_DOWNLOAD_LAST 0x9F8814 681 #define AOT_SUBTITLE_DOWNLOAD_MORE 0x9F8815 682 #define AOT_FLUSH_DOWNLOAD 0x9F8816 683 #define AOT_DOWNLOAD_REPLY 0x9F8817 684 #define AOT_COMMS_CMD 0x9F8C00 685 #define AOT_CONNECTION_DESCRIPTOR 0x9F8C01 686 #define AOT_COMMS_REPLY 0x9F8C02 687 #define AOT_COMMS_SEND_LAST 0x9F8C03 688 #define AOT_COMMS_SEND_MORE 0x9F8C04 689 #define AOT_COMMS_RCV_LAST 0x9F8C05 690 #define AOT_COMMS_RCV_MORE 0x9F8C06 692 #define RESOURCE_CLASS_MASK 0xFFFF0000 696 sessionId = SessionId;
697 resourceId = ResourceId;
712 tc->SetTsPostProcessor(
this);
720 if (Length >= 3 && Data && *Data) {
722 for (
int i = 0; i < 3; i++)
723 t = (t << 8) | *(*Data)++;
733 return Length ? Data : NULL;
742 *p++ = (sessionId >> 8) & 0xFF;
743 *p++ = sessionId & 0xFF;
744 *p++ = (Tag >> 16) & 0xFF;
745 *p++ = (Tag >> 8) & 0xFF;
748 if (p - buffer + Length <
int(
sizeof(buffer))) {
750 memcpy(p, Data, Length);
752 tc->SendData(p - buffer, buffer);
755 esyslog(
"ERROR: CAM %d: data length (%d) exceeds buffer size", CamSlot()->SlotNumber(), Length);
760 return Tc()->CamSlot();
774 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
780 dbgprotocol(
"Slot %d: new Resource Manager (session id %d)\n",
CamSlot()->SlotNumber(), SessionId);
787 int Tag =
GetTag(Length, &Data);
800 const uint8_t *d =
GetData(Data, l);
802 esyslog(
"ERROR: CAM %d: resource manager: unexpected data",
CamSlot()->SlotNumber());
808 esyslog(
"ERROR: CAM %d: resource manager: unexpected tag %06X in state %d",
CamSlot()->SlotNumber(), Tag,
state);
812 default:
esyslog(
"ERROR: CAM %d: resource manager: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
815 else if (
state == 0) {
827 dbgprotocol(
"Slot %d: new Application Information (session id %d)\n",
CamSlot()->SlotNumber(), SessionId);
840 int Tag =
GetTag(Length, &Data);
845 const uint8_t *d =
GetData(Data, l);
846 if ((l -= 1) < 0)
break;
848 if ((l -= 2) < 0)
break;
851 if ((l -= 2) < 0)
break;
860 default:
esyslog(
"ERROR: CAM %d: application information: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
863 else if (
state == 0) {
882 #define MAXCASYSTEMIDS 64 886 #define CPLM_MORE 0x00 887 #define CPLM_FIRST 0x01 888 #define CPLM_LAST 0x02 889 #define CPLM_ONLY 0x03 890 #define CPLM_ADD 0x04 891 #define CPLM_UPDATE 0x05 895 #define CPCI_OK_DESCRAMBLING 0x01 896 #define CPCI_OK_MMI 0x02 897 #define CPCI_QUERY 0x03 898 #define CPCI_NOT_SELECTED 0x04 911 void AddCaDescriptors(
int Length,
const uint8_t *Data);
913 cCiCaPmt(uint8_t CmdId,
int Source,
int Transponder,
int ProgramNumber,
const int *CaSystemIds);
914 uint8_t
CmdId(
void) {
return cmdId; }
915 void SetListManagement(uint8_t ListManagement);
917 void AddPid(
int Pid, uint8_t StreamType);
921 cCiCaPmt::cCiCaPmt(uint8_t CmdId,
int Source,
int Transponder,
int ProgramNumber,
const int *CaSystemIds)
925 transponder = Transponder;
926 programNumber = ProgramNumber;
929 for (; CaSystemIds[i]; i++)
935 capmt.Append((ProgramNumber >> 8) & 0xFF);
936 capmt.Append( ProgramNumber & 0xFF);
938 esInfoLengthPos = capmt.Length();
941 AddCaDescriptors(caDescriptors.Length(), caDescriptors.Data());
946 capmt.Set(0, ListManagement);
953 capmt.Append(StreamType);
954 capmt.Append((Pid >> 8) & 0xFF);
955 capmt.Append( Pid & 0xFF);
956 esInfoLengthPos = capmt.Length();
959 AddCaDescriptors(caDescriptors.Length(), caDescriptors.Data());
965 if (esInfoLengthPos) {
968 capmt.Append(Data, Length);
969 int l = capmt.Length() - esInfoLengthPos - 2;
970 capmt.Set(esInfoLengthPos, (l >> 8) & 0xFF);
971 capmt.Set(esInfoLengthPos + 1, l & 0xFF);
976 esyslog(
"ERROR: adding CA descriptor without Pid!");
989 esyslog(
"ERROR: wrong length (%d) in MtdMapCaDescriptor()", l);
992 esyslog(
"ERROR: wrong tag (%d) in MtdMapCaDescriptor()", *p);
998 int Length = p[0] * 256 + p[1];
1040 uchar *p = capmt.Data();
1041 int m = capmt.Length();
1061 #define CAEI_POSSIBLE 0x01 1062 #define CAEI_POSSIBLE_COND_PURCHASE 0x02 1063 #define CAEI_POSSIBLE_COND_TECHNICAL 0x03 1064 #define CAEI_NOT_POSSIBLE_ENTITLEMENT 0x71 1065 #define CAEI_NOT_POSSIBLE_TECHNICAL 0x73 1067 #define CA_ENABLE_FLAG 0x80 1069 #define CA_ENABLE(x) (((x) & CA_ENABLE_FLAG) ? (x) & ~CA_ENABLE_FLAG : 0) 1071 #define QUERY_WAIT_TIME 500 // ms to wait before sending a query 1072 #define QUERY_REPLY_TIMEOUT 2000 // ms to wait for a reply to a query 1073 #define QUERY_RETRIES 6 // max. number of retries to check if there is a reply to a query 1085 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
1097 dbgprotocol(
"Slot %d: new Conditional Access Support (session id %d)\n",
CamSlot()->SlotNumber(), SessionId);
1107 int Tag =
GetTag(Length, &Data);
1114 const uint8_t *d =
GetData(Data, l);
1116 uint16_t
id = ((uint16_t)(*d) << 8) | *(d + 1);
1124 esyslog(
"ERROR: CAM %d: too many CA system IDs!",
CamSlot()->SlotNumber());
1135 dsyslog(
"CAM %d: system ids:%s",
CamSlot()->SlotNumber(), *Ids ? *Ids :
" none");
1141 if (
CamSlot()->IsMasterSlot())
1142 dsyslog(
"CAM %d: replies to QUERY - multi channel decryption (MCD) possible",
CamSlot()->SlotNumber());
1144 if (
CamSlot()->MtdAvailable()) {
1145 if (
CamSlot()->IsMasterSlot())
1146 dsyslog(
"CAM %d: supports multi transponder decryption (MTD)",
CamSlot()->SlotNumber());
1152 const uint8_t *d =
GetData(Data, l);
1154 uint16_t pnr = ((uint16_t)(*d) << 8) | *(d + 1);
1163 if (l % 3 == 0 && l > 1) {
1169 uint16_t len = ((uint16_t)(*d) << 8) | *(d + 1);
1175 unsigned char caepl = *d;
1183 uint16_t pid = ((uint16_t)(*d) << 8) | *(d + 1);
1184 unsigned char caees = *(d + 2);
1199 default:
esyslog(
"ERROR: CAM %d: conditional access support: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
1202 else if (
state == 0) {
1215 dsyslog(
"CAM %d: doesn't reply to QUERY - only a single channel can be decrypted",
CamSlot()->SlotNumber());
1224 if (CaPmt &&
state >= 2) {
1236 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
1242 dbgprotocol(
"Slot %d: new Host Control (session id %d)\n",
CamSlot()->SlotNumber(), SessionId);
1248 int Tag =
GetTag(Length, &Data);
1259 default:
esyslog(
"ERROR: CAM %d: Host Control: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
1270 void SendDateTime(
void);
1273 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
1281 dbgprotocol(
"Slot %d: new Date Time (session id %d)\n",
CamSlot()->SlotNumber(), SessionId);
1286 time_t t = time(NULL);
1289 if (gmtime_r(&t, &tm_gmt) && localtime_r(&t, &tm_loc)) {
1290 int Y = tm_gmt.tm_year;
1291 int M = tm_gmt.tm_mon + 1;
1292 int D = tm_gmt.tm_mday;
1293 int L = (M == 1 || M == 2) ? 1 : 0;
1294 int MJD = 14956 + D + int((Y - L) * 365.25) + int((M + 1 + L * 12) * 30.6001);
1295 #define DEC2BCD(d) uint8_t(((d / 10) << 4) + (d % 10)) 1297 struct tTime { uint16_t mjd; uint8_t h, m, s;
short offset; };
1299 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)) };
1312 int Tag =
GetTag(Length, &Data);
1317 const uint8_t *d =
GetData(Data, l);
1325 default:
esyslog(
"ERROR: CAM %d: date time: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
1338 #define DCC_SET_MMI_MODE 0x01 1339 #define DCC_DISPLAY_CHARACTER_TABLE_LIST 0x02 1340 #define DCC_INPUT_CHARACTER_TABLE_LIST 0x03 1341 #define DCC_OVERLAY_GRAPHICS_CHARACTERISTICS 0x04 1342 #define DCC_FULL_SCREEN_GRAPHICS_CHARACTERISTICS 0x05 1346 #define MM_HIGH_LEVEL 0x01 1347 #define MM_LOW_LEVEL_OVERLAY_GRAPHICS 0x02 1348 #define MM_LOW_LEVEL_FULL_SCREEN_GRAPHICS 0x03 1352 #define DRI_MMI_MODE_ACK 0x01 1353 #define DRI_LIST_DISPLAY_CHARACTER_TABLES 0x02 1354 #define DRI_LIST_INPUT_CHARACTER_TABLES 0x03 1355 #define DRI_LIST_GRAPHIC_OVERLAY_CHARACTERISTICS 0x04 1356 #define DRI_LIST_FULL_SCREEN_GRAPHIC_CHARACTERISTICS 0x05 1357 #define DRI_UNKNOWN_DISPLAY_CONTROL_CMD 0xF0 1358 #define DRI_UNKNOWN_MMI_MODE 0xF1 1359 #define DRI_UNKNOWN_CHARACTER_TABLE 0xF2 1363 #define EF_BLIND 0x01 1367 #define AI_CANCEL 0x00 1368 #define AI_ANSWER 0x01 1372 char *GetText(
int &Length,
const uint8_t **Data);
1378 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
1380 cCiMenu *Menu(
bool Clear =
false);
1382 void SendMenuAnswer(uint8_t Selection);
1383 bool SendAnswer(
const char *Text);
1384 bool SendCloseMMI(
void);
1390 dbgprotocol(
"Slot %d: new MMI (session id %d)\n",
CamSlot()->SlotNumber(), SessionId);
1414 int Tag =
GetTag(Length, Data);
1421 esyslog(
"ERROR: CAM %d: MMI: unexpected text tag: %06X",
CamSlot()->SlotNumber(), Tag);
1428 int Tag =
GetTag(Length, &Data);
1433 const uint8_t *d =
GetData(Data, l);
1438 struct tDisplayReply { uint8_t id; uint8_t mode; };
1444 default:
esyslog(
"ERROR: CAM %d: MMI: unsupported display control command %02X",
CamSlot()->SlotNumber(), *d);
1455 const uint8_t *d =
GetData(Data, l);
1495 dsyslog(
"CAM %d: SELECT %d",
CamSlot()->SlotNumber(), Select + 1);
1506 const uint8_t *d =
GetData(Data, l);
1508 uint8_t blind = *d++;
1519 snprintf(s,
sizeof(s),
"%d", Action);
1536 const uint8_t *d =
GetData(Data, l);
1545 default:
esyslog(
"ERROR: CAM %d: MMI: unknown tag %06X",
CamSlot()->SlotNumber(), Tag);
1581 struct tAnswer { uint8_t id;
char text[256]; };
1585 strncpy(answer.text, Text,
sizeof(answer.text));
1603 selectable = Selectable;
1604 titleText = subTitleText = bottomText = NULL;
1616 for (
int i = 0; i < numEntries; i++)
1622 if (numEntries < MAX_CIMENU_ENTRIES) {
1623 entries[numEntries++] = s;
1632 return !mmi || mmi->HasUserIO();
1638 if (mmi && -1 <= Index && Index < numEntries)
1639 mmi->SendMenuAnswer(Index + 1);
1651 mmi->SendCloseMMI();
1689 mmi->SendCloseMMI();
1706 virtual const uint32_t *ResourceIds(
void)
const;
1712 static uint32_t Ids[] = {
1726 switch (ResourceId) {
1733 default:
return NULL;
1748 if (ResourceHandler) {
1749 Add(ResourceHandler);
1750 if (
const uint32_t *r = ResourceHandler->
ResourceIds()) {
1752 resourceIds.Append(htonl(*r));
1762 if (
cCiSession *CiSession = r->GetNewCiSession(ResourceId, SessionId, Tc))
1770 #define TC_POLL_TIMEOUT 300 // ms WORKAROUND: TC_POLL_TIMEOUT < 300ms doesn't work with DragonCAM 1771 #define TC_ALIVE_TIMEOUT 2000 // ms after which a transport connection is assumed dead 1779 createConnectionRequested =
false;
1780 deleteConnectionRequested =
false;
1785 tsPostProcessor = NULL;
1796 tsPostProcessor = CiSession;
1801 if (tsPostProcessor)
1802 return tsPostProcessor->TsPostProcess(TsPacket);
1809 return cas && cas->
Ready();
1820 cTPDU TPDU(camSlot->SlotIndex(), tcid, Tag, Length, Data);
1821 camSlot->Write(&TPDU);
1828 if (state == stACTIVE && Length > 0)
1835 uint8_t *p = buffer;
1846 buffer[1] = p - buffer - 2;
1855 dbgprotocol(
"Slot %d: ==> Poll\n", camSlot->SlotNumber());
1886 if (Length == 6 && *(Data + 1) == 0x04) {
1887 uint32_t
ResourceId = ResourceIdToInt(Data + 2);
1889 if (!GetSessionByResourceId(ResourceId)) {
1892 sessions[i] = CiResourceHandlers.
GetNewCiSession(ResourceId, i,
this);
1896 esyslog(
"ERROR: CAM %d: unknown resource identifier: %08X (%d/%d)", camSlot->SlotNumber(),
ResourceId, camSlot->SlotIndex(), tcid);
1900 esyslog(
"ERROR: CAM %d: no free session slot for resource identifier %08X (%d/%d)", camSlot->SlotNumber(),
ResourceId, camSlot->SlotIndex(), tcid);
1903 esyslog(
"ERROR: CAM %d: session for resource identifier %08X already exists (%d/%d)", camSlot->SlotNumber(),
ResourceId, camSlot->SlotIndex(), tcid);
1910 cCiSession *Session = GetSessionBySessionId(SessionId);
1911 if (Session && sessions[SessionId] == Session) {
1917 esyslog(
"ERROR: CAM %d: unknown session id: %d (%d/%d)", camSlot->SlotNumber(),
SessionId, camSlot->SlotIndex(), tcid);
1925 const uint8_t *Data = TPDU->
Data(Length);
1926 if (Data && Length > 1) {
1930 cCiSession *Session = GetSessionBySessionId(SessionId);
1932 Session->
Process(Length - 4, Data + 4);
1934 esyslog(
"ERROR: CAM %d: unknown session id: %d (%d/%d)", camSlot->SlotNumber(),
SessionId, camSlot->SlotIndex(), tcid);
1944 default:
esyslog(
"ERROR: CAM %d: unknown session tag: %02X (%d/%d)", camSlot->SlotNumber(), *Data, camSlot->SlotIndex(), tcid);
1953 else if (alive.TimedOut())
1957 if (createConnectionRequested) {
1958 dbgprotocol(
"Slot %d: create connection %d/%d\n", camSlot->SlotNumber(), camSlot->SlotIndex(), tcid);
1959 createConnectionRequested =
false;
1966 dbgprotocol(
"Slot %d: connection created %d/%d\n", camSlot->SlotNumber(), camSlot->SlotIndex(), tcid);
1970 else if (timer.TimedOut()) {
1971 dbgprotocol(
"Slot %d: timeout while creating connection %d/%d\n", camSlot->SlotNumber(), camSlot->SlotIndex(), tcid);
1976 if (deleteConnectionRequested) {
1977 dbgprotocol(
"Slot %d: delete connection requested %d/%d\n", camSlot->SlotNumber(), camSlot->SlotIndex(), tcid);
1978 deleteConnectionRequested =
false;
1984 switch (TPDU->
Tag()) {
1986 esyslog(
"ERROR: CAM %d: T_REQUEST_TC not implemented (%d/%d)", camSlot->SlotNumber(), camSlot->SlotIndex(), tcid);
1990 HandleSessions(TPDU);
1994 dbgprotocol(
"Slot %d: receive data %d/%d\n", camSlot->SlotNumber(), camSlot->SlotIndex(), tcid);
1999 dbgprotocol(
"Slot %d: delete connection %d/%d\n", camSlot->SlotNumber(), camSlot->SlotIndex(), tcid);
2011 esyslog(
"ERROR: unknown TPDU tag: 0x%02X (%s)", TPDU->
Tag(), __FUNCTION__);
2014 else if (timer.TimedOut())
2019 sessions[i]->Process();
2027 dbgprotocol(
"Slot %d: connection deleted %d/%d\n", camSlot->SlotNumber(), camSlot->SlotIndex(), tcid);
2032 esyslog(
"ERROR: unknown state: %d (%s)", state, __FUNCTION__);
2048 streamType = StreamType;
2061 programNumber = ProgramNumber;
2100 esyslog(
"ERROR: no free CAM slot in CI adapter");
2136 #define MODULE_CHECK_INTERVAL 500 // ms 2137 #define MODULE_RESET_TIMEOUT 2 // s 2141 ciAdapter = CiAdapter;
2142 masterSlot = MasterSlot;
2143 assignedDevice = NULL;
2145 caActivationReceiver = NULL;
2147 mtdAvailable =
false;
2158 slotNumber = Index() + 1;
2159 ciAdapter->AddCamSlot(
this);
2167 delete caPidReceiver;
2168 delete caActivationReceiver;
2170 DeleteAllConnections();
2178 return mtdHandler->GetMtdCamSlot(
this);
2185 if (Device == assignedDevice)
2188 int OldDeviceNumber = 0;
2189 if (assignedDevice && !Query) {
2190 OldDeviceNumber = assignedDevice->DeviceNumber() + 1;
2192 assignedDevice->Detach(caPidReceiver);
2193 assignedDevice->SetCamSlot(NULL);
2194 assignedDevice = NULL;
2196 if (ciAdapter->Assign(Device,
true)) {
2199 if (ciAdapter->Assign(Device)) {
2202 assignedDevice = Device;
2203 if (caPidReceiver) {
2204 caPidReceiver->Reset();
2211 dsyslog(
"CAM %d: unassigned from device %d", MasterSlotNumber(), OldDeviceNumber);
2227 return mtdHandler->Devices(CardIndexes);
2229 CardIndexes.
Append(assignedDevice->CardIndex());
2230 return CardIndexes.
Size() > 0;
2239 tc[i]->CreateConnection();
2243 esyslog(
"ERROR: CAM %d: can't create new transport connection!", slotNumber);
2259 int n = TPDU->
Tcid();
2262 tc[n]->Process(TPDU);
2267 if (!tc[i]->Process()) {
2273 if (moduleCheckTimer.TimedOut()) {
2275 if (ms != lastModuleStatus) {
2278 dbgprotocol(
"Slot %d: no module present\n", slotNumber);
2279 isyslog(
"CAM %d: no module present", slotNumber);
2281 DeleteAllConnections();
2284 mtdHandler->UnAssignAll();
2289 dbgprotocol(
"Slot %d: module reset\n", slotNumber);
2290 isyslog(
"CAM %d: module reset", slotNumber);
2291 DeleteAllConnections();
2294 dbgprotocol(
"Slot %d: module present\n", slotNumber);
2295 isyslog(
"CAM %d: module present", slotNumber);
2298 dbgprotocol(
"Slot %d: module ready\n", slotNumber);
2299 isyslog(
"CAM %d: module ready", slotNumber);
2304 esyslog(
"ERROR: unknown module status %d (%s)", ms, __FUNCTION__);
2306 lastModuleStatus = ms;
2310 if (resendPmt && Ready()) {
2312 mtdHandler->StartDecrypting();
2315 else if (caProgramList.Count())
2318 processed.Broadcast();
2324 return tc[1] ? tc[1]->GetSessionByResourceId(ResourceId) : NULL;
2330 if (ciAdapter && TPDU->
Size()) {
2331 TPDU->
Dump(SlotNumber(),
true);
2332 ciAdapter->Write(TPDU->
Buffer(), TPDU->
Size());
2340 DeleteAllConnections();
2343 if (ciAdapter->Reset(slotIndex)) {
2344 resetTime = time(NULL);
2362 if (!caActivationReceiver) {
2367 d->AttachReceiver(caActivationReceiver);
2368 dsyslog(
"CAM %d: activating on device %d with channel %d (%s)", SlotNumber(), d->DeviceNumber() + 1, Channel->Number(), Channel->Name());
2378 mtdHandler->CancelActivation();
2380 delete caActivationReceiver;
2381 caActivationReceiver = NULL;
2388 return mtdHandler->IsActivating();
2389 return caActivationReceiver;
2409 return tc[1] ? tc[1]->GetCamName() : NULL;
2420 return GetSessionByResourceId(
RI_MMI);
2426 return tc[1] && tc[1]->HasUserIO();
2464 for (
int i = 0; i < caPmts.Size(); i++)
2470 cCiCaPmt *p =
new cCiCaPmt(CmdId, Source, Transponder, ProgramNumber, CaSystemIds);
2477 if (caPmts.RemoveElement(CaPmt))
2492 const int *CaSystemIds = GetCaSystemIds();
2493 if (CaSystemIds && *CaSystemIds) {
2494 if (caProgramList.Count()) {
2496 if (p->modified || resendPmt) {
2497 bool Active = p->Active();
2501 CaPmt->
AddPid(q->pid, q->streamType);
2503 if (caPidReceiver) {
2507 caPidReceiver->AddPids(CaPids);
2509 caPidReceiver->DelPids(CaPids);
2512 if (RepliesToQuery())
2516 p->modified =
false;
2521 CaPmtList.
Add(CmdId, 0, 0, 0, NULL);
2530 for (
int i = 0; i < CaPmtList.
caPmts.
Size(); i++)
2540 BuildCaPmts(CmdId, CaPmtList);
2541 SendCaPmts(CaPmtList);
2546 mtdAvailable =
true;
2551 if (McdAvailable() && MtdAvailable()) {
2554 dsyslog(
"CAM %d: activating MTD support", SlotNumber());
2558 else if (mtdHandler) {
2559 dsyslog(
"CAM %d: deactivating MTD support", SlotNumber());
2568 return mtdHandler->Put(Data, Count);
2581 return mtdHandler->Priority();
2591 for (
const int *ids = cas->
GetCaSystemIds(); ids && *ids; ids++) {
2592 for (
const int *
id = CaSystemIds; *id;
id++) {
2606 if (p->programNumber == ProgramNumber) {
2621 if (caPidReceiver && caPidReceiver->HandlingPid())
2626 if (q->pid == Pid) {
2627 if (q->active != Active) {
2638 #define STREAM_TYPE_VIDEO 0x02 2639 #define STREAM_TYPE_AUDIO 0x04 2640 #define STREAM_TYPE_PRIVATE 0x06 2647 source = Channel->
Source();
2651 for (
const int *Apid = Channel->
Apids(); *Apid; Apid++)
2653 for (
const int *Dpid = Channel->
Dpids(); *Dpid; Dpid++)
2655 for (
const int *Spid = Channel->
Spids(); *Spid; Spid++)
2660 #define QUERY_REPLY_WAIT 100 // ms to wait between checks for a reply 2666 if (!IsDecrypting())
2674 for (
const int *Apid = Channel->
Apids(); *Apid; Apid++)
2676 for (
const int *Dpid = Channel->
Dpids(); *Dpid; Dpid++)
2678 for (
const int *Spid = Channel->
Spids(); *Spid; Spid++)
2681 CaPmt.MtdMapPids(MtdMapper);
2693 dsyslog(
"CAM %d: didn't reply to QUERY", SlotNumber());
2706 if (caProgramList.Count()) {
2707 caProgramList.Clear();
2708 if (!dynamic_cast<cMtdCamSlot *>(
this))
2717 return mtdHandler->IsDecrypting();
2718 if (caProgramList.Count()) {
2740 return tc[1] ? tc[1]->TsPostProcess(Data) :
false;
2761 for (
cCamSlot *CamSlot = CamSlots.
First(); CamSlot; CamSlot = CamSlots.
Next(CamSlot)) {
2762 if (CamSlot->IsMasterSlot() && CamSlot->ModuleStatus() ==
msReady)
2771 for (time_t t0 = time(NULL); time(NULL) - t0 < Timeout; ) {
2773 for (
cCamSlot *CamSlot = CamSlots.
First(); CamSlot; CamSlot = CamSlots.
Next(CamSlot)) {
2774 if (!CamSlot->Ready()) {
2782 for (
cCamSlot *CamSlot = CamSlots.
First(); CamSlot; CamSlot = CamSlots.
Next(CamSlot))
2783 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()));
2789 #define CAM_CHECKED_TIMEOUT 15 // seconds before a CAM that has been checked for a particular channel will be checked again 2799 bool TimedOut(
void);
2801 bool CamChecked(
int CamSlotNumber);
2802 bool CamDecrypt(
int CamSlotNumber);
2803 void SetChecked(
int CamSlotNumber);
2804 void SetDecrypt(
int CamSlotNumber);
2805 void ClrChecked(
int CamSlotNumber);
2806 void ClrDecrypt(
int CamSlotNumber);
2811 channelID = ChannelID;
2812 camSlotsChecked = 0;
2813 camSlotsDecrypt = 0;
2826 camSlotsChecked = 0;
2828 return camSlotsChecked & (1 << (CamSlotNumber - 1));
2833 return camSlotsDecrypt & (1 << (CamSlotNumber - 1));
2838 camSlotsChecked |= (1 << (CamSlotNumber - 1));
2839 lastChecked = time(NULL);
2840 ClrDecrypt(CamSlotNumber);
2845 camSlotsDecrypt |= (1 << (CamSlotNumber - 1));
2846 ClrChecked(CamSlotNumber);
2851 camSlotsChecked &= ~(1 << (CamSlotNumber - 1));
2857 camSlotsDecrypt &= ~(1 << (CamSlotNumber - 1));
2862 #define MAX_CAM_NUMBER 32 2863 #define CHANNEL_CAM_RELATIONS_CLEANUP_INTERVAL 3600 // seconds between cleanups 2869 lastCleanup = time(NULL);
2882 lastCleanup = time(NULL);
2891 if (ccr->ChannelID() == ChannelID)
2910 ccr->ClrChecked(CamSlotNumber);
2911 ccr->ClrDecrypt(CamSlotNumber);
2919 return ccr ? ccr->
CamChecked(CamSlotNumber) :
false;
2926 return ccr ? ccr->
CamDecrypt(CamSlotNumber) :
false;
2964 fileName = FileName;
2965 if (access(fileName, R_OK) == 0) {
2966 dsyslog(
"loading %s", *fileName);
2967 if (FILE *f = fopen(fileName,
"r")) {
2970 while ((s = ReadLine.
Read(f)) != NULL) {
2971 if (
char *p = strchr(s,
' ')) {
2975 if (ChannelID.
Valid()) {
2978 while ((q = strtok_r(p,
" ", &strtok_next)) != NULL) {
2979 int CamSlotNumber = atoi(q);
2981 SetDecrypt(ChannelID, CamSlotNumber);
3001 if (stat(fileName, &st) == 0) {
3002 if ((st.st_mode & S_IWUSR) == 0) {
3003 dsyslog(
"not saving %s (file is read-only)", *fileName);
3007 dsyslog(
"saving %s", *fileName);
3011 if (ccr->ChannelID().Valid()) {
3014 if (ccr->CamDecrypt(i))
3018 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
int DeviceNumber(void) const
Returns the number of this device (0 ... numDevices - 1).
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...
const int * Dpids(void) const
bool Devices(cVector< int > &CardIndexes)
Adds the card indexes of any devices that currently use this CAM to the given CardIndexes.
bool Process(cTPDU *TPDU=NULL)
static tChannelID FromString(const char *s)
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.
cCiSession(uint16_t SessionId, uint32_t ResourceId, cCiTransportConnection *Tc)
cList< cCiCaPidData > pidList
virtual void AddPid(int ProgramNumber, int Pid, int StreamType)
Adds the given PID information to the list of PIDs.
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 ...
int Ca(int Index=0) const
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
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)
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
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)
#define STREAM_TYPE_VIDEO
virtual ~cCaPidReceiver()
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 Transponder(void) const
Returns the transponder frequency in MHz, plus the polarization in case of sat.
#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 const uint32_t * ResourceIds(void) const =0
Returns a pointer to an array of resource identifiers, where the last value is zero.
virtual eModuleStatus ModuleStatus(void)
Returns the status of the CAM in this slot.
void AddPid(int Pid, uint8_t StreamType)
virtual void AddChannel(const cChannel *Channel)
Adds all PIDs of the given Channel to the current list of PIDs.
uint32_t ResourceId(void)
void SetListManagement(uint8_t ListManagement)
#define RI_CONDITIONAL_ACCESS_SUPPORT
int TsPid(const uchar *p)
virtual void SendCaPmt(uint8_t CmdId)
virtual bool Reset(int Slot)
Resets the CAM in the given Slot.
void CreateConnection(void)
void SendTag(uint8_t Tag, uint16_t SessionId, uint32_t ResourceId=0, int Status=-1)
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...
void MtdMapPid(uchar *p, cMtdMapper *MtdMapper)
#define MODULE_RESET_TIMEOUT
int GetMatch(int CamNumber, const char *Text) const
static int CurrentChannel(void)
Returns the number of the current channel on the primary device.
#define ST_CLOSE_SESSION_REQUEST
cCiSession * GetSessionByResourceId(uint32_t ResourceId)
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)
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)
int Matches(int CamNumber, const char *Text) const
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)
cListObject * Next(void) const
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)
#define LOCK_CHANNELS_READ
cCiConditionalAccessSupport(uint16_t SessionId, cCiTransportConnection *Tc)
bool TimedOut(void) const
#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...
#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)
#define AOT_DISPLAY_REPLY
void ClrChecked(int CamSlotNumber)
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
#define STREAM_TYPE_PRIVATE
const T * Next(const T *Object) const
< Returns the element immediately before Object in this list, or NULL if Object is the first element ...
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.
cCiTransportConnection * Tc(void)
bool HandlingPid(void)
The cCaPidReceiver adds/deletes PIDs to/from the base class cReceiver, which in turn does the same on...
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.
int PutCat(const uchar *Data, int Count)
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)
int Priority(void) const
Returns the priority of the current receiving session (-MAXPRIORITY..MAXPRIORITY), or IDLEPRIORITY if no receiver is currently active.
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...
cCamSlot * camSlots[MAX_CAM_SLOTS_PER_ADAPTER]
const int * Apids(void) const
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
virtual void Process(int Length=0, const uint8_t *Data=NULL)
void SendPMT(cCiCaPmt *CaPmt)
void Reply(const char *s)
void MtdMapSid(uchar *p, cMtdMapper *MtdMapper)
cCiMenu * Menu(bool Clear=false)
bool Active(void)
Checks whether the thread is still alive.
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
virtual bool Ready(void)
Returns 'true' if the CAM in this slot is ready to decrypt.
void DeleteConnection(void)
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 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)
const int * Spids(void) const
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...
const T * First(void) const
Returns the first element in this list, or NULL if the list is empty.
#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)
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.
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 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)
static int MtdMapStreams(uchar *p, cMtdMapper *MtdMapper, int Length)
int SlotNumber(void)
Returns the number of this CAM slot within the whole system.
uchar mtdCatBuffer[TS_SIZE]
bool HasCaPids(void) const
virtual const uint32_t * ResourceIds(void) const
Returns a pointer to an array of resource identifiers, where the last value is zero.
static bool DebugProtocol
cCiResourceManager(uint16_t SessionId, cCiTransportConnection *Tc)
virtual bool RepliesToQuery(void)
Returns true if the CAM in this slot replies to queries and thus supports MCD ("Multi Channel Decrypt...
void SetDecrypt(int CamSlotNumber)