# HG changeset patch # User Yoshiki Yazawa # Date 1252775493 -32400 # Node ID 41a5481db56f2d2db37606adaa16b6a00e1f122c # Parent db7af62da709e8756a6651b1939d10418a8bd685 rearrange arib25 directory diff -r db7af62da709 -r 41a5481db56f arib25/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arib25/Makefile Sun Sep 13 02:11:33 2009 +0900 @@ -0,0 +1,6 @@ +all: + cd src; make all + +clean: + cd src; make clean + diff -r db7af62da709 -r 41a5481db56f arib25/arib_std_b25.sln --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arib25/arib_std_b25.sln Sun Sep 13 02:11:33 2009 +0900 @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual C++ Express 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "arib_std_b25", "arib_std_b25.vcproj", "{6E77C1AC-A31A-49B9-9A52-9FE1E03B8FEC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6E77C1AC-A31A-49B9-9A52-9FE1E03B8FEC}.Debug|Win32.ActiveCfg = Debug|Win32 + {6E77C1AC-A31A-49B9-9A52-9FE1E03B8FEC}.Debug|Win32.Build.0 = Debug|Win32 + {6E77C1AC-A31A-49B9-9A52-9FE1E03B8FEC}.Release|Win32.ActiveCfg = Release|Win32 + {6E77C1AC-A31A-49B9-9A52-9FE1E03B8FEC}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff -r db7af62da709 -r 41a5481db56f arib25/arib_std_b25.vcproj --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arib25/arib_std_b25.vcproj Sun Sep 13 02:11:33 2009 +0900 @@ -0,0 +1,259 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r db7af62da709 -r 41a5481db56f arib25/readme.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arib25/readme.txt Sun Sep 13 02:11:33 2009 +0900 @@ -0,0 +1,351 @@ +y–¼Ìz + +@ARIB STD-B25 Žd—lŠm”FƒeƒXƒgƒvƒƒOƒ‰ƒ€ƒ\[ƒXƒR[ƒh + +yƒo[ƒWƒ‡ƒ“z + +@0.2.3 + +yìŽÒz + +@–Î–Ø ˜a—m (MOGI, Kazuhiro) +@kazhiro@marumo.ne.jp + +yˆêŽŸ”z•zŒ³z + +@http://www.marumo.ne.jp/db2008_c.htm#30 + +@‚ ‚é‚¢‚Í + +@http://www.marumo.ne.jp/junk/arib_std_b25-0.2.3.lzh + +y–Ú“Iz + +@ARIB STD-B25 ‚ÌŽd—l‚ð—‰ð‚·‚éˆ×‚ÌAŽQl—p‚ÌŽÀ‘•‚Æ‚µ‚ÄŒöŠJ + +y”wŒiz + +@2011 ”N 7 ŒŽ‚Ì’nãƒAƒiƒƒO•ú‘—’â”g‚ðT‚¦A—õ‰¿‚È’nãƒfƒWƒ^ƒ‹•ú‘— +@ŽóM‹@‚̔̔„‚ª‘Ò‚½‚ê‚Ä‚¢‚é + +@‚µ‚©‚µAARIB ‚Ì•W€•¶‘‚Í‚í‚´‚Æ”»‚è‚É‚­‚­‘‚¢‚ÄŠJ”­”ï‚ð‚©‚³‚Ü‚¹ +@‚悤‚Æ‚µ‚Ä‚¢‚é‚Æ‚µ‚©Žv‚¦‚È‚¢‚قǂɈӖ¡•s–¾—Ä‚È‹Lq‚É‚È‚Á‚Ä‚¨‚è +@‚±‚̂܂܂ł͒ቿŠiŽóM‹@‚ÌŠJ”­‚È‚Ç•s‰Â”\‚ÉŽv‚¦‚é + +@‚»‚±‚ÅAŽ©•ª‚È‚è‚É ARIB •W€•¶‘‚ð“Ç‚ÝA—‰ð‚µ‚½”͈͂ðƒ\[ƒX +@ƒR[ƒh‚ÌŒ`‚É‚Ü‚Æ‚ß‚ÄŒöŠJ‚·‚邱‚Æ‚É‚µ‚½ + +@‚±‚̃R[ƒh‚ªˆÀ‰¿‚ÈŽóM‹@‚ÌŠJ”­‚̈ꕂƂȂ邱‚Æ‚ðŠú‘Ò‚·‚é + +@‚È‚¨A‚ ‚­‚Ü‚Å‚àŽd—l—‰ð‚ð–Ú“I‚Æ‚µ‚½‚à‚Ì‚Å‚ ‚邽‚ßAƒrƒ‹ƒhÏ‚Ý +@ƒoƒCƒiƒŠƒtƒ@ƒCƒ‹‚Í”z•z‚µ‚È‚¢ + +yŽÀ‘•‚µ‚½”͈Íz + +@CA ƒVƒXƒeƒ€ (B-CAS ƒJ[ƒhŠÖ˜A) ‚ð’†S‚É ECM(table_id=0x82) ‚̈—‚Æ +@ƒXƒgƒŠ[ƒ€ˆÃ†‚Ì•œ†ˆ—AEMM(table_id=0x84) ‚̈—‚Ü‚Å‚ðŽÀ‘•‚µ‚½ + +@EMM ƒƒbƒZ[ƒW (table_id=0x85) ŠÖ˜A‚Í–¢ŽÀ‘•‚Æ‚È‚Á‚Ä‚¢‚é + +yƒvƒƒOƒ‰ƒ€‚Ì“®ìŠÂ‹«z + +@ISO 7816 ‘Ήž‚Ì IC ƒJ[ƒhƒŠ[ƒ_‚ªƒCƒ“ƒXƒg[ƒ‹‚³‚ꂽ Windows PC ‚ð +@‘z’è“®ìŠÂ‹«‚Æ‚·‚é + +@ISO 7816 ‘ΉžƒXƒ}[ƒgƒJ[ƒhƒŠ[ƒ_[‚͈ê”Ê‚É +@uZŠîƒJ[ƒh‘Ήž IC ƒJ[ƒhƒŠ[ƒ_vue-Tax ‘Ήž IC ƒJ[ƒhƒŠ[ƒ_v +@‚È‚Ç‚Æ‚µ‚Ä 4000 ‰~’ö“x‚Ŕ̔„‚³‚ê‚Ä‚¢‚é‚à‚Ì‚ª—˜—p‰Â”\‚Å‚ ‚é + +@“ú—§ƒ}ƒNƒZƒ‹»‚Ì HX-520UJJ ‚ųí‚É“®ì‚·‚邱‚Æ‚ðŠm”F‚µ‚Ä‚¢‚é + +yƒ\[ƒXƒR[ƒh‚̃‰ƒCƒZƒ“ƒX‚ɂ‚¢‚Äz + +@Eƒ\[ƒXƒR[ƒh‚ð—˜—p‚µ‚½‚±‚Æ‚É‚æ‚Á‚ÄA“Á‹–ã‚̃gƒ‰ƒuƒ‹‚ª”­¶‚µ‚Ä‚à +@@–Î–Ø ˜a—m‚ÍÓ”C‚𕉂í‚È‚¢ +@Eƒ\[ƒXƒR[ƒh‚ð—˜—p‚µ‚½‚±‚Æ‚É‚æ‚Á‚ÄAƒvƒƒOƒ‰ƒ€‚É–â‘肪”­¶‚µ‚Ä‚à +@@–Î–Ø ˜a—m‚ÍÓ”C‚𕉂í‚È‚¢ + +@ã‹L 2 ðŒ‚É“¯ˆÓ‚µ‚Ä쬂³‚ꂽ“ñŽŸ“I’˜ì•¨‚ɑ΂µ‚ÄA–Î–Ø ˜a—m‚Í +@Œ´’˜ìŽÒ‚É—^‚¦‚ç‚ê‚锌 —˜‚ðsŽg‚µ‚È‚¢ + +yƒvƒƒOƒ‰ƒ€‚Ì\¬z + +@Earib_std_b25.h/c + +@@ARIB STD-B25 ‹Lڂ̈—‚ðs‚¤‚½‚߂̃‚ƒWƒ…[ƒ‹ +@@MPEG-2 TS ‚Ì•ª—£ACA ƒVƒXƒeƒ€ (B-CAS ƒJ[ƒh) ‹@”\‚̌ĂÑo‚µA +@@MULTI2 •œ†‹@”\‚̌ĂÑo‚µ“™‚ð’S“–‚·‚é + +@Ets_section_parser.h/c + +@@MPEG-2 TS ‚̃ZƒNƒVƒ‡ƒ“Œ`Ž®ƒf[ƒ^‚Ì•ªŠ„ˆ—‚ð’S“–‚·‚é + +@Eb_cas_card.h/c + +@@CA ƒVƒXƒeƒ€ (B-CAS ƒJ[ƒh) ‚̃Šƒ\[ƒXŠÇ—‚¨‚æ‚Ñ’¼Ú‚̧Œä‚ð +@@’S“–‚·‚é + +@Emulti2.h/c + +@@MULTI2 ˆÃ†‚Ì•„†‰»‚Æ•œ†‚ð’S“–‚·‚é + +@Etd.c + +@@ƒeƒXƒgƒhƒ‰ƒCƒo +@@PAT/PMT/ECM ‚ðŠÜ‚Þ MPEG-2 TS ƒtƒ@ƒCƒ‹‚ð“Ç‚Ýž‚ÝA•œ†Œã‚Ì +@@MPEG-2 TS ƒtƒ@ƒCƒ‹‚ðo—Í‚·‚é + +@@ƒRƒ}ƒ“ƒhƒ‰ƒCƒ“ƒIƒvƒVƒ‡ƒ“‚Å MULTI2 ˆÃ†‚̃‰ƒEƒ“ƒh”‚ðŽw’è‰Â”\ +@@ƒ‰ƒEƒ“ƒh”‚ðŽw’肵‚È‚¢ê‡‚̉Šú’l‚Í 4 + +@@‚±‚̃‰ƒEƒ“ƒh” 4 ‚Í MULTI2 —pŒê‚Å‚Í 32 ‚É‘Š“–‚·‚é + +@@ARIB STD-B25 ‚Å‚Í MULTI2 ‚̃‰ƒEƒ“ƒh”‚Í”ñŒöŠJƒpƒ‰ƒ[ƒ^‚¾‚ª +@@‘“–‚½‚è‚ÅŽÀۂ̃‰ƒEƒ“ƒh”‚Í„’è‰Â”\‚Å‚ ‚é + +yˆ—‚Ì—¬‚êz + +@E‹N“®Žž + +@@1 ƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚Í B_CAS_CARD ƒ‚ƒWƒ…[ƒ‹‚̃Cƒ“ƒXƒ^ƒ“ƒX‚ð +@@@쬂µAB_CAS_CARD ƒ‚ƒWƒ…[ƒ‹‚ÉA‰Šú‰»‚ðˆË—Š‚·‚é + +@@1.a B_CAS_CARD ƒ‚ƒWƒ…[ƒ‹‚Í WIN32 API ‚̃Xƒ}[ƒgƒJ[ƒhŠÖ˜A +@@@@API ‚ðŒÄ‚Ño‚µACA ƒVƒXƒeƒ€‚ÉÚ‘±‚·‚é +@@1.b B_CAS_CARD ƒ‚ƒWƒ…[ƒ‹‚Í ARIB STD-B25 ‹LÚ‚Ìu‰ŠúðŒ +@@@@Ý’èƒRƒ}ƒ“ƒh‚ð CA ƒVƒXƒeƒ€‚É”­s‚µAƒVƒXƒeƒ€Œ® (64 byte) +@@@@‰Šú CBC ó‘Ô (8 byte) ‚ðŽó‚¯Žæ‚é + +@@2 ƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚Í ARIB_STD_B25 ƒ‚ƒWƒ…[ƒ‹‚̃Cƒ“ƒXƒ^ƒ“ƒX‚ð +@@@쬂µAB_CAS_CARD ƒ‚ƒWƒ…[ƒ‹‚ð ARIB_STD_B25 ƒ‚ƒWƒ…[ƒ‹‚É +@@@“o˜^‚·‚é + +@Eƒf[ƒ^ˆ—Žž + +@@1 ƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚Í ARIB_STD_B25 ƒ‚ƒWƒ…[ƒ‹‚ɇŽŸƒf[ƒ^‚ð +@@@’ñ‹Ÿ‚µAARIB_STD_B25 ƒ‚ƒWƒ…[ƒ‹‚©‚爗Š®—¹ƒf[ƒ^‚ðŽó‚¯ +@@@Žæ‚Á‚ătƒ@ƒCƒ‹‚Éo—Í‚µ‚Ä‚¢‚­ + +@@EARIB_STD_B25 ƒ‚ƒWƒ…[ƒ‹“à + +@@@1 TS ƒpƒPƒbƒg‚̃†ƒjƒbƒgƒTƒCƒY (188/192/204 ‚È‚Ç‚ªˆê”Ê“I) ‚ª +@@@@“Á’肳‚ê‚Ä‚¢‚È‚¢ê‡ 8K ‚Ü‚Å“ü—̓f[ƒ^‚ðƒoƒbƒtƒ@‚µ‚Ä‚©‚çA +@@@@ƒ†ƒjƒbƒgƒTƒCƒY‚ð“Á’è‚·‚é +@@@@ƒ†ƒjƒbƒgƒTƒCƒY‚ª“Á’è‚Å‚«‚È‚©‚Á‚½ê‡‚ÍAƒGƒ‰[I—¹‚·‚é + +@@@2 PAT ‚ª”­Œ©‚³‚ê‚Ä‚¢‚È‚¢ê‡APAT ‚ª”­Œ©‚Å‚«‚é‚Ü‚Å“ü—Í +@@@@ƒf[ƒ^‚ðƒoƒbƒtƒ@‚µ‘±‚¯‚é +@@@@PAT ‚ª”­Œ©‚Å‚«‚¸‚Ƀoƒbƒtƒ@ƒTƒCƒY‚ª 16M ‚𒴉߂µ‚½ê‡ +@@@@ƒGƒ‰[I—¹‚·‚é +@@@@PAT ‚ª”­Œ©‚Å‚«‚½ê‡AƒvƒƒOƒ‰ƒ€”z—ñ‚ð쬂µ PID ƒ}ƒbƒv +@@@@”z—ñ‚É“o˜^‚·‚é + +@@@3 PAT ‚É“o˜^‚³‚ê‚Ä‚¢‚½ PMT ‚·‚ׂĂª”­Œ©‚³‚ê‚é‚©A‚Ç‚ê‚© +@@@@‚Ð‚Æ‚Â‚Ì PMT ‚Å 2 ŒÂ–ڂ̃ZƒNƒVƒ‡ƒ“‚ª“ž’…‚·‚é‚Ü‚Å“ü—Í +@@@@ƒf[ƒ^‚ðƒoƒbƒtƒ@‚µ‘±‚¯‚é +@@@@ã‹LðŒ‚ð–ž‚½‚³‚¸‚Ƀoƒbƒtƒ@ƒTƒCƒY‚ª 32M ‚𒴉߂µ‚½ê‡ +@@@@ƒGƒ‰[I—¹‚·‚é +@@@@PMT ‚ª“ž’…‚·‚é–ˆ‚É ECM ‚Ì—L–³‚ðŠm”F‚µAECM ‚ª‘¶Ý‚·‚é +@@@@ꇂ̓fƒNƒŠƒvƒ^‚ð쬂µ‚ăvƒƒOƒ‰ƒ€‚ÉŠ‘®‚·‚éƒXƒgƒŠ[ƒ€ +@@@@‚Æ PID ƒ}ƒbƒvã‚ÅŠÖ˜A•t‚¯‚é + +@@@4 PMT ‚É“o˜^‚³‚ê‚Ä‚¢‚½ ECM ‚·‚ׂĂª”­Œ©‚³‚ê‚é‚©A‚Ç‚ê‚© +@@@@‚Ð‚Æ‚Â‚Ì ECM ‚Å 2 ŒÂ–ڂ̃ZƒNƒVƒ‡ƒ“‚ª“ž’…‚·‚é‚Ü‚Å“ü—Í +@@@@ƒf[ƒ^‚ðƒoƒbƒtƒ@‚µ‘±‚¯‚é +@@@@ã‹LðŒ‚ð–ž‚½‚³‚¸‚Ƀoƒbƒtƒ@ƒTƒCƒY‚ª 32M ‚𒴉߂µ‚½ê‡ +@@@@ƒGƒ‰[I—¹‚·‚é +@@@@Še ECM ‚ɑ΂µ‚ÄAʼn‚̃ZƒNƒVƒ‡ƒ“ƒf[ƒ^‚ª“ž’…‚µ‚½Žž“_‚Å +@@@@MULTI2 ƒ‚ƒWƒ…[ƒ‹‚̃Cƒ“ƒXƒ^ƒ“ƒX‚ðƒfƒNƒŠƒvƒ^ã‚É쬂·‚é +@@@@ECM ƒZƒNƒVƒ‡ƒ“ƒf[ƒ^‚Í B_CAS_CARD ƒ‚ƒWƒ…[ƒ‹‚É’ñ‹Ÿ‚µ‚Ä +@@@@ƒXƒNƒ‰ƒ“ƒuƒ‹Œ®‚ðŽó‚¯Žæ‚èAMULTI2 ƒ‚ƒWƒ…[ƒ‹‚ɃVƒXƒeƒ€Œ®A +@@@@‰Šú CBC ó‘ÔAƒXƒNƒ‰ƒ“ƒuƒ‹Œ®‚ð“n‚µAMULTI2 •œ†‚Ì€”õ‚ð +@@@@s‚¤ + +@@@5.a ˆÃ†‰»‚³‚ê‚Ä‚¢‚é TS ƒpƒPƒbƒg‚Å‚ ‚ê‚ÎAPID ‚©‚ç‘Ήž +@@@@@ECM ƒXƒgƒŠ[ƒ€‚ð“Á’肵AƒfƒNƒŠƒvƒ^‚Ì MULTI2 ƒ‚ƒWƒ…[ +@@@@@ƒ‹‚É•œ†‚³‚¹‚Äo—̓oƒbƒtƒ@‚ÉÏ‚Þ +@@@@ +@@@5.b ˆÃ†‰»‚³‚ê‚Ä‚¢‚È‚¢ TS ƒpƒPƒbƒg‚Å‚ ‚ê‚ÎA‚»‚Ì‚Ü‚Üo—Í +@@@@@ƒoƒbƒtƒ@‚ÉÏ‚Þ + +@@@5.c CAT ‚ðŒŸo‚µ‚½ê‡AEMM ‚Ì PID ‚ðŽæ“¾‚µ‚Ä EMM ‚̈— +@@@@@€”õ‚ðs‚¤ + +@@@5.d EMM ‚ðŽó‚¯Žæ‚Á‚½ê‡AB-CAS ƒJ[ƒh ID ‚Æ”äŠr‚µAŽ©•ª +@@@@@ˆ¶‚Ä‚Ì EMM ‚Å‚ ‚ê‚Î B-CAS ƒJ[ƒh‚Ɉø‚«“n‚µ‚Ĉ—‚³‚¹‚é +@@@@@# EMM ˆ—ƒIƒvƒVƒ‡ƒ“‚ªŽw’肳‚ê‚Ä‚¢‚éê‡ + +@@@6 ECM ‚ªXV‚³‚ꂽê‡AB_CAS_CARD ƒ‚ƒWƒ…[ƒ‹‚Ɉ—‚ð +@@@@ˆË—Š‚µAo—Í‚³‚ꂽƒXƒNƒ‰ƒ“ƒuƒ‹Œ®‚ð MULTI2 ƒ‚ƒWƒ…[ƒ‹‚É +@@@@“o˜^‚·‚é + +@@@7 PMT ‚ªXV‚³‚ꂽê‡AECM PID ‚ª•Ï‰»‚µ‚Ä‚¢‚ê‚ÎV‚½‚É +@@@@ƒfƒNƒŠƒvƒ^‚ð쬂µ‚Ä 4 ‚É–ß‚é + +@@@8 PAT ‚ªXV‚³‚ꂽê‡AƒvƒƒOƒ‰ƒ€”z—ñ‚ð”jŠü‚µ‚Ä +@@@@3 ‚É–ß‚é + +@EI—¹Žž + +@@1 Šeƒ‚ƒWƒ…[ƒ‹‚ªŠm•Û‚µ‚½ƒŠƒ\[ƒX‚ð‰ð•ú‚·‚é + +yXV—š—ðz + +@E2008, 12/30 - ver. 0.2.3 + +@@CA_descriptor ‚̉ðŽß‚ðs‚¤Û‚É CA_system_id ‚ª B-CAS ƒJ[ƒh +@@‚©‚çŽæ“¾‚µ‚½‚à‚̂ƈê’v‚·‚é‚©Šm”F‚ðs‚¤‚悤‚É•ÏX + +@@http://www.marumo.ne.jp/db2008_c.htm#30 –”‚Í +@@http://www.marumo.ne.jp/junk/arib_std_b25-0.2.3.lzh + +@E2008, 11/10 - ver. 0.2.2 + +@@C³ƒ†ƒŠƒEƒX“ú‚©‚ç”NŒŽ“ú‚Ö‚Ì•ÏŠ·ˆ—‚ð‚æ‚賊m‚È‚à‚Ì‚Ö•ÏX + +@@TS ƒpƒPƒbƒgƒTƒCƒY‚Ì“Á’è•û–@‚ð•ÏX + +@@http://www.marumo.ne.jp/db2008_b.htm#10 –”‚Í +@@http://www.marumo.ne.jp/junk/arib_std_b25-0.2.2.lzh + +@E2008, 4/9 - ver. 0.2.1 + +@@PAT XVŽž‚É•œ†˜R‚ꂪ”­¶‚µ‚Ä‚¢‚½ƒoƒO‚ðC³ +@@(ver. 0.2.0 ‚ł̃Gƒ“ƒoƒO) + +@@–ì—Ç PID (PMT ‚É‹LÚ‚³‚ê‚Ä‚¢‚È‚¢ƒXƒgƒŠ[ƒ€) ‚ª‘¶Ý‚µ‚½ê‡ +@@TS “à‚Ì ECM ‚ª‚ЂƂ‚¾‚¯‚È‚ç‚ÎA‚»‚Ì ECM ‚Å•œ†‚·‚éŒ`‚É•ÏX + +@@EMM ‚Ì B-CAS ƒJ[ƒh‚Ö‚Ì‘—M‚ðƒIƒvƒVƒ‡ƒ“‚Å‘I‘ð‰Â”\‚É•ÏX (-m) +@@i’»ó‹µ‚Ì•\Ž¦‚ðƒIƒvƒVƒ‡ƒ“‚Å‘I‘ð‰Â”\‚É•ÏX (-v) +@@’Ê“d§Œäî•ñ (EMMŽóM—p) ‚ð•\Ž¦‚·‚éƒIƒvƒVƒ‡ƒ“‚ð’ljÁ (-p) + +@@http://www.marumo.ne.jp/db2008_4.htm#9 –”‚Í +@@http://www.marumo.ne.jp/junk/arib_std_b25-0.2.1.lzh + +@E2008, 4/6 - ver. 0.2.0 + +@@EMM ‘Ήž +@@—˜—p’†‚Ì B-CAS ƒJ[ƒh ID Œü‚¯‚Ì EMM ‚ðŒŸo‚µ‚½ê‡AEMM ‚ð +@@B-CAS ƒJ[ƒh‚É“n‚·ˆ—‚ð’ljÁ + +@@ECM ˆ—‚ÌÛ‚É–¢Œ_–ñ‰ž“š‚ª•Ô‚³‚ꂽê‡Aˆ—•‰‰×ŒyŒ¸‚̈×A +@@ˆÈ~A‚»‚Ì PID ‚Ì ECM ‚ð B-CAS ƒJ[ƒh‚ň—‚µ‚È‚¢‚悤‚É•Ï +@@X (EMM ‚ðˆ—‚µ‚½ê‡‚ÍÄ‚Ñ ECM ‚ðˆ—‚·‚é‚悤‚É–ß‚·) + +@@i’»‚ð nn.nn% ‚Ì‘Ž®‚Å•W€ƒGƒ‰[o—Í‚É•\Ž¦‚·‚é‚悤‚É•ÏX +@@ +@@http://www.marumo.ne.jp/db2008_4.htm#6 –”‚Í +@@http://www.marumo.ne.jp/junk/arib_std_b25-0.2.0.lzh + +@E2008, 3/31 - ver. 0.1.9 + +@@MULTI2 ƒ‚ƒWƒ…[ƒ‹‚̃Cƒ“ƒXƒ^ƒ“ƒX‚ª–¢ì»‚Ì󋵂ÅAMULTI2 ‚Ì +@@‹@”\‚ðŒÄ‚Ño‚µ‚Ä—áŠO‚ð”­¶‚³‚¹‚邱‚Æ‚ª‚ ‚Á‚½ƒoƒO‚ðC³ + +@@# ƒpƒbƒ`‚ð’ñ‹Ÿ‚µ‚Ä‚­‚ꂽ•û‚ÉŠ´ŽÓ + +@@http://www.marumo.ne.jp/db2008_3.htm#31 –”‚Í +@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.9.lzh + +@E2008, 3/24 - ver. 0.1.8 + +@@-s ƒIƒvƒVƒ‡ƒ“ (NULL ƒpƒPƒbƒg‚Ìíœ) ‚ð’ljÁ +@@-s 1 ‚Å NULL ƒpƒPƒbƒg‚ðo—̓tƒ@ƒCƒ‹‚É‚Í•Û‘¶‚µ‚È‚­‚È‚é +@@ƒfƒtƒHƒ‹ƒg‚Í -s 0 ‚Ì NULL ƒpƒPƒbƒg•ÛŽ + +@@http://www.marumo.ne.jp/db2008_3.htm#24 –”‚Í +@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.8.lzh + +@E2008, 3/17 - ver. 0.1.7 + +@@arib_std_b25.h ‚Éuextern "C" {v‚ð•Â‚¶‚éƒR[ƒh‚ª‚È‚©‚Á‚½–â‘è +@@(C++ ƒR[ƒh‚©‚ç—˜—p‚·‚éꇂɃRƒ“ƒpƒCƒ‹ƒGƒ‰[‚ð”­¶‚³‚¹‚é) ‚ð +@@C³ + +@@TS ƒpƒPƒbƒg‚Ì’†“r‚ŃXƒgƒŠ[ƒ€‚ªØ‚è‘Ö‚í‚éƒP[ƒX‚Å–â‘肪”­¶‚µ +@@‚É‚­‚­‚È‚é‚悤‚ÉAarib_std_b25.c “à‚̃R[ƒh‚ðC³ + +@@http://www.marumo.ne.jp/db2008_3.htm#17 –”‚Í +@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.7.lzh + +@E2008, 3/16 - ver. 0.1.6 + +@@PMT XV‚ÌÛAECM ŠÖ˜A‚Ì󋵂ª•ÏX (ƒXƒNƒ‰ƒ“ƒuƒ‹ - ƒmƒ“ƒXƒN +@@ƒ‰ƒ“ƒuƒ‹‚ÌØ‚è‘Ö‚¦‚âAECM PID ‚Ì•ÏX“™) ‚ªs‚í‚ê‚Ä‚àA‚»‚ꂪ +@@”½‰f‚³‚ê‚Ä‚¢‚È‚©‚Á‚½–â‘è‚ðC³ + +@@http://www.marumo.ne.jp/db2008_3.htm#16 –”‚Í +@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.6.lzh + +@E2008, 2/14 + +@@readme.txt (‚±‚̃tƒ@ƒCƒ‹) ‚ðC³ +@@ƒ\[ƒXƒR[ƒh‚̃‰ƒCƒZƒ“ƒX‚ɂ‚¢‚Ä‚Ì‹Lq‚ð’ljÁ + +@E2008, 2/12 - ver. 0.1.5 + +@@PMT ‚ÌXV‚É”º‚¢A‚ǂ̃vƒƒOƒ‰ƒ€‚É‚àŠ‘®‚µ‚È‚­‚È‚Á‚½ PID (ƒXƒg +@@ƒŠ[ƒ€) ‚ŃpƒPƒbƒg‚ª‘—M‚³‚ꑱ‚¯‚½ê‡A‚»‚̃pƒPƒbƒg‚Ì•œ†‚ª +@@‚Å‚«‚È‚­‚È‚Á‚Ä‚¢‚½–â‘è‚ðC³ + +@@http://www.marumo.ne.jp/db2008_2.htm#12 –”‚Í +@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.5.lzh + +@E2008, 2/2 - ver. 0.1.4 + +@@ver. 0.1.3 ‚Å‚Ì PMT ˆ—•û–@•ÏX‚É–â‘肪‚ ‚èAPMT ‚ªXV‚³‚ꂽ +@@ê‡A‚»‚êˆÈ~‚ųí‚Ȉ—‚ªs‚¦‚È‚­‚È‚Á‚Ä‚¢‚½ƒoƒO‚ðC³ + +@@B-CAS ƒJ[ƒh‚Æ‚Ì’ÊM‚ŃGƒ‰[‚ª”­¶‚µ‚½ê‡‚̃Šƒgƒ‰ƒCˆ—‚ª‹@”\ +@@‚µ‚Ä‚¢‚È‚©‚Á‚½ƒoƒO‚ðC³ + +@@http://www.marumo.ne.jp/db2008_2.htm#2 –”‚Í +@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.4.lzh + +@E2008, 2/1 - ver. 0.1.3 + +@@—L—¿•ú‘—“™‚Å–¢Œ_–ñó‘Ô‚Ì B-CAS ƒJ[ƒh‚ðŽg‚Á‚½Û‚ÉAŒ®‚ªŽæ“¾‚Å +@@‚«‚Ä‚¢‚È‚¢‚É‚à‚©‚©‚í‚炸AŠÔˆá‚Á‚½Œ®‚Å•œ†‚ð‚µ‚Ä‚¢‚½–â‘è‚ɑΈ + +@@Œ®‚ªŽæ“¾‚Å‚«‚È‚©‚Á‚½ ECM ‚ÉŠÖ˜A•t‚¯‚ç‚ꂽƒXƒgƒŠ[ƒ€‚Å‚Í•œ†‚ð +@@s‚킸AƒXƒNƒ‰ƒ“ƒuƒ‹ƒtƒ‰ƒO‚ðŽc‚µ‚½‚Ü‚Ü“ü—Í‚ð‘f’Ê‚µ‚·‚éŒ`‚É•ÏX +@@Œ®‚ªŽæ“¾‚Å‚«‚È‚¢ ECM ‚ª‘¶Ý‚·‚éê‡AI—¹Žž‚Ƀ`ƒƒƒlƒ‹”Ô†‚Æ +@@B-CAS ƒJ[ƒh‚©‚çŽæ“¾‚Å‚«‚½ƒGƒ‰[”Ô†‚ðŒxƒƒbƒZ[ƒW‚Æ‚µ‚Ä•\Ž¦ +@@‚·‚éŒ`‚É•ÏX + +@@ˆÃ†‰»‚³‚ê‚Ä‚¢‚È‚¢ƒvƒƒOƒ‰ƒ€‚Å—áŠO‚ð”­¶‚³‚¹‚Ä‚¢‚½ƒoƒO‚ðC³ + +@@http://www.marumo.ne.jp/db2008_2.htm#1 –”‚Í +@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.3.lzh + +@E2008, 1/11 - ver. 0.1.2 + +@@ƒfƒWƒ^ƒ‹ BS •ú‘—“™‚ÅAPAT ‚É“o˜^‚³‚ê‚Ä‚¢‚é‚Ì‚ÉAƒXƒgƒŠ[ƒ€“à‚Å +@@PMT ‚ªˆêØoŒ»‚µ‚È‚¢‚±‚Æ‚ª‚ ‚éꇂɑΉž + +@@PMT “à‚Ì‹LqŽq—̈æ 2 ‚É CA_descriptor ‚ª‘¶Ý‚·‚éꇂɑΉž‚·‚é +@@‚½‚ß arib_std_b25.c “à•”‚ł̈—\‘¢‚ð•ÏX + +@@•ÊƒvƒƒOƒ‰ƒ€‚Æ“¯ŽžŽÀs‚·‚邽‚߂ɃXƒ}[ƒgƒJ[ƒh‚Ì”r‘¼§ŒäŽw’è‚ð +@@•ÏX + +@@http://www.marumo.ne.jp/db2008_1.htm#11 –”‚Í +@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.2.lzh + +@E2008, 1/7 - ver. 0.1.1 + +@@ƒZƒNƒVƒ‡ƒ“ (PAT/PMT/ECM “™) ‚ª•¡”‚Ì TS ƒpƒPƒbƒg‚É•ªŠ„‚³‚ê‚Ä‚¢‚é +@@ꇂÉA³í‚Ɉ—‚Å‚«‚È‚©‚Á‚½‚èA—áŠO‚ð”­¶‚ð‚³‚¹‚邱‚Æ‚ª‚ ‚é +@@ƒoƒO‚ðC³ + +@@http://www.marumo.ne.jp/db2008_1.htm#7 –”‚Í +@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.1.lzh + +@E2007, 11/25 - ver. 0.1.0 + +@@ŒöŠJ + +@@http://www.marumo.ne.jp/db2007_b.htm#25 –”‚Í +@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.0.lzh + diff -r db7af62da709 -r 41a5481db56f arib25/src/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arib25/src/Makefile Sun Sep 13 02:11:33 2009 +0900 @@ -0,0 +1,51 @@ +PREFIX = /usr/local +MAJOR = 0 +MINOR = 2 +REVISION = 3 +VER = $(MAJOR).$(MINOR).$(REVISION) + +DEST_HEADER = $(PREFIX)/include/arib25 + +CC = gcc +PCSC_CFLAGS ?= `pkg-config libpcsclite --cflags` +CPPFLAGS = -Wall $(PCSC_CFLAGS) -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 +CFLAGS = -O2 -g -fPIC + +PCSC_LIBS ?= `pkg-config libpcsclite --libs` +LIBS = $(PCSC_LIBS) -lm +LDFLAGS ?= + +OBJS = arib_std_b25.o b_cas_card.o multi2.o ts_section_parser.o +HEADERS = arib_std_b25.h b_cas_card.h portable.h +TARGET_APP = b25 +TARGET_LIB = libarib25.so +TARGETS = $(TARGET_APP) $(TARGET_LIB) +DEPEND = Makefile.dep +SONAME = $(TARGET_LIB).$(MAJOR) + +all: $(TARGETS) + +clean: + rm -f $(OBJS) td.o $(TARGETS) $(DEPEND) + +$(TARGET_APP): $(OBJS) td.o + $(CC) $(LDFLAGS) -o $(TARGET_APP) $(OBJS) td.o $(LIBS) + +$(TARGET_LIB): $(OBJS) + $(CC) $(LDFLAGS) -shared -o $(TARGET_LIB) $(OBJS) $(LIBS) -Wl,-soname,$(SONAME) + +$(DEPEND): + $(CC) -MM $(OBJS:.o=.c) $(CPPFLAGS) > $@ + +install: $(TARGET) install-headers + install -m755 b25 $(PREFIX)/bin + install -m755 $(TARGET_LIB) $(PREFIX)/lib/$(TARGET_LIB).$(VER) + ln -sf $(PREFIX)/lib/$(TARGET_LIB).$(VER) $(PREFIX)/lib/$(TARGET_LIB).$(MAJOR) + ln -sf $(PREFIX)/lib/$(TARGET_LIB).$(MAJOR) $(PREFIX)/lib/$(TARGET_LIB) + ldconfig + +install-headers: + mkdir -p $(DEST_HEADER) + install -m644 $(HEADERS) $(DEST_HEADER) + +-include Makefile.dep diff -r db7af62da709 -r 41a5481db56f arib25/src/arib_std_b25.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arib25/src/arib_std_b25.c Sun Sep 13 02:11:33 2009 +0900 @@ -0,0 +1,2566 @@ +#include +#include + +#include "arib_std_b25.h" +#include "arib_std_b25_error_code.h" +#include "multi2.h" +#include "ts_common_types.h" +#include "ts_section_parser.h" + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + inner structures + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +typedef struct { + int32_t pid; + int32_t type; + void *prev; + void *next; +} TS_STREAM_ELEM; + +typedef struct { + TS_STREAM_ELEM *head; + TS_STREAM_ELEM *tail; + int32_t count; +} TS_STREAM_LIST; + +typedef struct { + + uint8_t *pool; + uint8_t *head; + uint8_t *tail; + int32_t max; + +} TS_WORK_BUFFER; + +typedef struct { + + int32_t phase; + + int32_t program_number; + + int32_t pmt_pid; + TS_SECTION_PARSER *pmt; + + int32_t pcr_pid; + + TS_STREAM_LIST streams; + TS_STREAM_LIST old_strm; + +} TS_PROGRAM; + +typedef struct { + + int32_t ref; + int32_t phase; + + int32_t locked; + + int32_t ecm_pid; + TS_SECTION_PARSER *ecm; + + MULTI2 *m2; + + int32_t unpurchased; + int32_t last_error; + + void *prev; + void *next; + +} DECRYPTOR_ELEM; + +typedef struct { + DECRYPTOR_ELEM *head; + DECRYPTOR_ELEM *tail; + int32_t count; +} DECRYPTOR_LIST; + +typedef struct { + uint32_t ref; + uint32_t type; + int64_t normal_packet; + int64_t undecrypted; + void *target; +} PID_MAP; + +typedef struct { + + int32_t multi2_round; + int32_t strip; + int32_t emm_proc_on; + + int32_t unit_size; + + int32_t sbuf_offset; + + TS_SECTION_PARSER *pat; + TS_SECTION_PARSER *cat; + + TS_STREAM_LIST strm_pool; + + int32_t p_count; + TS_PROGRAM *program; + + DECRYPTOR_LIST decrypt; + + PID_MAP map[0x2000]; + + B_CAS_CARD *bcas; + B_CAS_ID casid; + int32_t ca_system_id; + + int32_t emm_pid; + TS_SECTION_PARSER *emm; + + TS_WORK_BUFFER sbuf; + TS_WORK_BUFFER dbuf; + +} ARIB_STD_B25_PRIVATE_DATA; + +typedef struct { + int64_t card_id; + int32_t associated_information_length; + int32_t protocol_number; + int32_t broadcaster_group_id; + int32_t update_number; + int32_t expiration_date; +} EMM_FIXED_PART; + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + constant values + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +enum TS_STREAM_TYPE { + TS_STREAM_TYPE_11172_2_VIDEO = 0x01, + TS_STREAM_TYPE_13818_2_VIDEO = 0x02, + TS_STREAM_TYPE_11172_3_AUDIO = 0x03, + TS_STREAM_TYPE_13818_3_AUDIO = 0x04, + TS_STREAM_TYPE_13818_1_PRIVATE_SECTIONS = 0x05, + TS_STREAM_TYPE_13818_1_PES_PRIVATE_DATA = 0x06, + TS_STREAM_TYPE_13522_MHEG = 0x07, + TS_STREAM_TYPE_13818_1_DSM_CC = 0x08, + TS_STREAM_TYPE_H_222_1 = 0x09, + TS_STREAM_TYPE_13818_6_TYPE_A = 0x0a, + TS_STREAM_TYPE_13818_6_TYPE_B = 0x0b, + TS_STREAM_TYPE_13818_6_TYPE_C = 0x0c, + TS_STREAM_TYPE_13818_6_TYPE_D = 0x0d, + TS_STREAM_TYPE_13818_1_AUX = 0x0e, + TS_STREAM_TYPE_13818_7_AUDIO_ADTS = 0x0f, + TS_STREAM_TYPE_14496_2_VISUAL = 0x10, + TS_STREAM_TYPE_14496_3_AUDIO_LATM = 0x11, + TS_STREAM_TYPE_14496_1_PES_SL_PACKET = 0x12, + TS_STREAM_TYPE_14496_1_SECTIONS_SL_PACKET = 0x13, + TS_STREAM_TYPE_13818_6_SYNC_DWLOAD_PROTCOL = 0x14, +}; + +enum TS_SECTION_ID { + TS_SECTION_ID_PROGRAM_ASSOCIATION = 0x00, + TS_SECTION_ID_CONDITIONAL_ACCESS = 0x01, + TS_SECTION_ID_PROGRAM_MAP = 0x02, + TS_SECTION_ID_DESCRIPTION = 0x03, + TS_SECTION_ID_14496_SCENE_DESCRIPTION = 0x04, + TS_SECTION_ID_14496_OBJECT_DESCRIPTION = 0x05, + + /* ARIB STD-B10 stuff */ + TS_SECTION_ID_DSM_CC_HEAD = 0x3a, + TS_SECTION_ID_DSM_CC_TAIL = 0x3f, + TS_SECTION_ID_NIT_ACTUAL = 0x40, + TS_SECTION_ID_NIT_OTHER = 0x41, + TS_SECTION_ID_SDT_ACTUAL = 0x42, + TS_SECTION_ID_SDT_OTHER = 0x46, + TS_SECTION_ID_BAT = 0x4a, + TS_SECTION_ID_EIT_ACTUAL_CURRENT = 0x4e, + TS_SECTION_ID_EIT_OTHER_CURRENT = 0x4f, + TS_SECTION_ID_EIT_ACTUAL_SCHEDULE_HEAD = 0x50, + TS_SECTION_ID_EIT_ACTUAL_SCHEDULE_TAIL = 0x5f, + TS_SECTION_ID_EIT_OTHER_SCHEDULE_HEAD = 0x60, + TS_SECTION_ID_EIT_OTHER_SCHEDULE_TAIL = 0x6f, + TS_SECTION_ID_TDT = 0x70, + TS_SECTION_ID_RST = 0x71, + TS_SECTION_ID_ST = 0x72, + TS_SECTION_ID_TOT = 0x73, + TS_SECTION_ID_AIT = 0x74, + TS_SECTION_ID_DIT = 0x7e, + TS_SECTION_ID_SIT = 0x7f, + TS_SECTION_ID_ECM_S = 0x82, + TS_SECTION_ID_ECM = 0x83, + TS_SECTION_ID_EMM_S = 0x84, + TS_SECTION_ID_EMM_MESSAGE = 0x85, + TS_SECTION_ID_DCT = 0xc0, + TS_SECTION_ID_DLT = 0xc1, + TS_SECTION_ID_PCAT = 0xc2, + TS_SECTION_ID_SDTT = 0xc3, + TS_SECTION_ID_BIT = 0xc4, + TS_SECTION_ID_NBIT_BODY = 0xc5, + TS_SECTION_ID_NBIT_REFERENCE = 0xc6, + TS_SECTION_ID_LDT = 0xc7, + TS_SECTION_ID_CDT = 0xc8, + TS_SECTION_ID_LIT = 0xd0, + TS_SECTION_ID_ERT = 0xd1, + TS_SECTION_ID_ITT = 0xd2, +}; + +enum TS_DESCRIPTOR_TAG { + TS_DESCRIPTOR_TAG_VIDEO_STREAM = 0x02, + TS_DESCRIPTOR_TAG_AUDIO_STREAM = 0x03, + TS_DESCRIPTOR_TAG_HIERARCHY = 0x04, + TS_DESCRIPTOR_TAG_REGISTRATION = 0x05, + TS_DESCRIPTOR_TAG_DATA_STREAM_ALIGNMENT = 0x06, + TS_DESCRIPTOR_TAG_TARGET_BACKGROUND_GRID = 0x07, + TS_DESCRIPTOR_TAG_VIDEO_WINDOW = 0x08, + TS_DESCRIPTOR_TAG_CA = 0x09, + TS_DESCRIPTOR_TAG_ISO_639_LANGUAGE = 0x0a, + TS_DESCRIPTOR_TAG_SYSTEM_CLOCK = 0x0b, + TS_DESCRIPTOR_TAG_MULTIPLEX_BUF_UTILIZ = 0x0c, + TS_DESCRIPTOR_TAG_COPYRIGHT = 0x0d, + TS_DESCRIPTOR_TAG_MAXIMUM_BITRATE = 0x0e, + TS_DESCRIPTOR_TAG_PRIVATE_DATA_INDICATOR = 0x0f, + TS_DESCRIPTOR_TAG_SMOOTHING_BUFFER = 0x10, + TS_DESCRIPTOR_TAG_STD = 0x11, + TS_DESCRIPTOR_TAG_IBP = 0x12, + TS_DESCRIPTOR_TAG_MPEG4_VIDEO = 0x1b, + TS_DESCRIPTOR_TAG_MPEG4_AUDIO = 0x1c, + TS_DESCRIPTOR_TAG_IOD = 0x1d, + TS_DESCRIPTOR_TAG_SL = 0x1e, + TS_DESCRIPTOR_TAG_FMC = 0x1f, + TS_DESCRIPTOR_TAG_EXTERNAL_ES_ID = 0x20, + TS_DESCRIPTOR_TAG_MUXCODE = 0x21, + TS_DESCRIPTOR_TAG_FMX_BUFFER_SIZE = 0x22, + TS_DESCRIPTOR_TAG_MULTIPLEX_BUFFER = 0x23, + TS_DESCRIPTOR_TAG_AVC_VIDEO = 0x28, + TS_DESCRIPTOR_TAG_AVC_TIMING_HRD = 0x2a, + + /* ARIB STD-B10 stuff */ + TS_DESCRIPTOR_TAG_NETWORK_NAME = 0x40, + TS_DESCRIPTOR_TAG_SERVICE_LIST = 0x41, + TS_DESCRIPTOR_TAG_STUFFING = 0x42, + TS_DESCRIPTOR_TAG_SATELLITE_DELIVERY_SYS = 0x43, + TS_DESCRIPTOR_TAG_CABLE_DISTRIBUTION = 0x44, + TS_DESCRIPTOR_TAG_BOUNQUET_NAME = 0x47, + TS_DESCRIPTOR_TAG_SERVICE = 0x48, + TS_DESCRIPTOR_TAG_COUNTRY_AVAILABILITY = 0x49, + TS_DESCRIPTOR_TAG_LINKAGE = 0x4a, + TS_DESCRIPTOR_TAG_NVOD_REFERENCE = 0x4b, + TS_DESCRIPTOR_TAG_TIME_SHIFTED_SERVICE = 0x4c, + TS_DESCRIPTOR_TAG_SHORT_EVENT = 0x4d, + TS_DESCRIPTOR_TAG_EXTENDED_EVENT = 0x4e, + TS_DESCRIPTOR_TAG_TIME_SHIFTED_EVENT = 0x4f, + TS_DESCRIPTOR_TAG_COMPONENT = 0x50, + TS_DESCRIPTOR_TAG_MOSAIC = 0x51, + TS_DESCRIPTOR_TAG_STREAM_IDENTIFIER = 0x52, + TS_DESCRIPTOR_TAG_CA_IDENTIFIER = 0x53, + TS_DESCRIPTOR_TAG_CONTENT = 0x54, + TS_DESCRIPTOR_TAG_PARENTAL_RATING = 0x55, + TS_DESCRIPTOR_TAG_LOCAL_TIME_OFFSET = 0x58, + TS_DESCRIPTOR_TAG_PARTIAL_TRANSPORT_STREAM = 0x63, + TS_DESCRIPTOR_TAG_HIERARCHICAL_TRANSMISSION = 0xc0, + TS_DESCRIPTOR_TAG_DIGITAL_COPY_CONTROL = 0xc1, + TS_DESCRIPTOR_TAG_NETWORK_IDENTIFICATION = 0xc2, + TS_DESCRIPTOR_TAG_PARTIAL_TRANSPORT_TIME = 0xc3, + TS_DESCRIPTOR_TAG_AUDIO_COMPONENT = 0xc4, + TS_DESCRIPTOR_TAG_HYPERLINK = 0xc5, + TS_DESCRIPTOR_TAG_TARGET_REGION = 0xc6, + TS_DESCRIPTOR_TAG_DATA_COTENT = 0xc7, + TS_DESCRIPTOR_TAG_VIDEO_DECODE_CONTROL = 0xc8, + TS_DESCRIPTOR_TAG_DOWNLOAD_CONTENT = 0xc9, + TS_DESCRIPTOR_TAG_CA_EMM_TS = 0xca, + TS_DESCRIPTOR_TAG_CA_CONTRACT_INFORMATION = 0xcb, + TS_DESCRIPTOR_TAG_CA_SERVICE = 0xcc, + TS_DESCRIPTOR_TAG_TS_INFORMATION = 0xcd, + TS_DESCRIPTOR_TAG_EXTENDED_BROADCASTER = 0xce, + TS_DESCRIPTOR_TAG_LOGO_TRANSMISSION = 0xcf, + TS_DESCRIPTOR_TAG_BASIC_LOCAL_EVENT = 0xd0, + TS_DESCRIPTOR_TAG_REFERENCE = 0xd1, + TS_DESCRIPTOR_TAG_NODE_RELATION = 0xd2, + TS_DESCRIPTOR_TAG_SHORT_NODE_INFORMATION = 0xd3, + TS_DESCRIPTOR_TAG_STC_REFERENCE = 0xd4, + TS_DESCRIPTOR_TAG_SERIES = 0xd5, + TS_DESCRIPTOR_TAG_EVENT_GROUP = 0xd6, + TS_DESCRIPTOR_TAG_SI_PARAMETER = 0xd7, + TS_DESCRIPTOR_TAG_BROADCASTER_NAME = 0xd8, + TS_DESCRIPTOR_TAG_COMPONENT_GROUP = 0xd9, + TS_DESCRIPTOR_TAG_SI_PRIME_TS = 0xda, + TS_DESCRIPTOR_TAG_BOARD_INFORMATION = 0xdb, + TS_DESCRIPTOR_TAG_LDT_LINKAGE = 0xdc, + TS_DESCRIPTOR_TAG_CONNECTED_TRANSMISSION = 0xdd, + TS_DESCRIPTOR_TAG_CONTENT_AVAILABILITY = 0xde, + TS_DESCRIPTOR_TAG_VALUE_EXTENSION = 0xdf, + TS_DESCRIPTOR_TAG_SERVICE_GROUP = 0xe0, + TS_DESCRIPTOR_TAG_CARUSEL_COMPOSITE = 0xf7, + TS_DESCRIPTOR_TAG_CONDITIONAL_PLAYBACK = 0xf8, + TS_DESCRIPTOR_TAG_CABLE_TS_DIVISSION = 0xf9, + TS_DESCRIPTOR_TAG_TERRESTRIAL_DELIVERY_SYS = 0xfa, + TS_DESCRIPTOR_TAG_PARTIAL_RECEPTION = 0xfb, + TS_DESCRIPTOR_TAG_EMERGENCY_INFOMATION = 0xfc, + TS_DESCRIPTOR_TAG_DATA_COMPONENT = 0xfd, + TS_DESCRIPTOR_TAG_SYSTEM_MANAGEMENT = 0xfe, +}; + +enum PID_MAP_TYPE { + PID_MAP_TYPE_UNKNOWN = 0x0000, + PID_MAP_TYPE_PAT = 0x0100, + PID_MAP_TYPE_PMT = 0x0200, + PID_MAP_TYPE_NIT = 0x0300, + PID_MAP_TYPE_PCR = 0x0400, + PID_MAP_TYPE_ECM = 0x0500, + PID_MAP_TYPE_EMM = 0x0600, + PID_MAP_TYPE_EIT = 0x0700, + PID_MAP_TYPE_CAT = 0x0800, + PID_MAP_TYPE_OTHER = 0xff00, +}; + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function prottypes (interface method) + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +static void release_arib_std_b25(void *std_b25); +static int set_multi2_round_arib_std_b25(void *std_b25, int32_t round); +static int set_strip_arib_std_b25(void *std_b25, int32_t strip); +static int set_emm_proc_arib_std_b25(void *std_b25, int32_t on); +static int set_b_cas_card_arib_std_b25(void *std_b25, B_CAS_CARD *bcas); +static int reset_arib_std_b25(void *std_b25); +static int flush_arib_std_b25(void *std_b25); +static int put_arib_std_b25(void *std_b25, ARIB_STD_B25_BUFFER *buf); +static int get_arib_std_b25(void *std_b25, ARIB_STD_B25_BUFFER *buf); +static int get_program_count_arib_std_b25(void *std_b25); +static int get_program_info_arib_std_b25(void *std_b25, ARIB_STD_B25_PROGRAM_INFO *info, int idx); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + global function implementation + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +ARIB_STD_B25 *create_arib_std_b25() +{ + int n; + + ARIB_STD_B25 *r; + ARIB_STD_B25_PRIVATE_DATA *prv; + + n = sizeof(ARIB_STD_B25_PRIVATE_DATA); + n += sizeof(ARIB_STD_B25); + + prv = (ARIB_STD_B25_PRIVATE_DATA *)calloc(1, n); + if(prv == NULL){ + return NULL; + } + + prv->multi2_round = 4; + + r = (ARIB_STD_B25 *)(prv+1); + r->private_data = prv; + + r->release = release_arib_std_b25; + r->set_multi2_round = set_multi2_round_arib_std_b25; + r->set_strip = set_strip_arib_std_b25; + r->set_emm_proc = set_emm_proc_arib_std_b25; + r->set_b_cas_card = set_b_cas_card_arib_std_b25; + r->reset = reset_arib_std_b25; + r->flush = flush_arib_std_b25; + r->put = put_arib_std_b25; + r->get = get_arib_std_b25; + r->get_program_count = get_program_count_arib_std_b25; + r->get_program_info = get_program_info_arib_std_b25; + + return r; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function prottypes (private method) + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +static ARIB_STD_B25_PRIVATE_DATA *private_data(void *std_b25); +static void teardown(ARIB_STD_B25_PRIVATE_DATA *prv); +static int select_unit_size(ARIB_STD_B25_PRIVATE_DATA *prv); +static int find_pat(ARIB_STD_B25_PRIVATE_DATA *prv); +static int proc_pat(ARIB_STD_B25_PRIVATE_DATA *prv); +static int check_pmt_complete(ARIB_STD_B25_PRIVATE_DATA *prv); +static int find_pmt(ARIB_STD_B25_PRIVATE_DATA *prv); +static int proc_pmt(ARIB_STD_B25_PRIVATE_DATA *prv, TS_PROGRAM *pgrm); +static int32_t find_ca_descriptor_pid(uint8_t *head, uint8_t *tail, int32_t ca_system_id); +static int32_t add_ecm_stream(ARIB_STD_B25_PRIVATE_DATA *prv, TS_STREAM_LIST *list, int32_t ecm_pid); +static int check_ecm_complete(ARIB_STD_B25_PRIVATE_DATA *prv); +static int find_ecm(ARIB_STD_B25_PRIVATE_DATA *prv); +static int proc_ecm(DECRYPTOR_ELEM *dec, B_CAS_CARD *bcas, int32_t multi2_round); +static int proc_arib_std_b25(ARIB_STD_B25_PRIVATE_DATA *prv); + +static int proc_cat(ARIB_STD_B25_PRIVATE_DATA *prv); +static int proc_emm(ARIB_STD_B25_PRIVATE_DATA *prv); + +static void release_program(ARIB_STD_B25_PRIVATE_DATA *prv, TS_PROGRAM *pgrm); + +static void unref_stream(ARIB_STD_B25_PRIVATE_DATA *prv, int32_t pid); + +static DECRYPTOR_ELEM *set_decryptor(ARIB_STD_B25_PRIVATE_DATA *prv, int32_t pid); +static void remove_decryptor(ARIB_STD_B25_PRIVATE_DATA *prv, DECRYPTOR_ELEM *dec); +static DECRYPTOR_ELEM *select_active_decryptor(DECRYPTOR_ELEM *a, DECRYPTOR_ELEM *b, int32_t pid); +static void bind_stream_decryptor(ARIB_STD_B25_PRIVATE_DATA *prv, int32_t pid, DECRYPTOR_ELEM *dec); +static void unlock_all_decryptor(ARIB_STD_B25_PRIVATE_DATA *prv); + +static TS_STREAM_ELEM *get_stream_list_head(TS_STREAM_LIST *list); +static TS_STREAM_ELEM *find_stream_list_elem(TS_STREAM_LIST *list, int32_t pid); +static TS_STREAM_ELEM *create_stream_elem(int32_t pid, int32_t type); +static void put_stream_list_tail(TS_STREAM_LIST *list, TS_STREAM_ELEM *elem); +static void clear_stream_list(TS_STREAM_LIST *list); + +static int reserve_work_buffer(TS_WORK_BUFFER *buf, int32_t size); +static int append_work_buffer(TS_WORK_BUFFER *buf, uint8_t *data, int32_t size); +static void reset_work_buffer(TS_WORK_BUFFER *buf); +static void release_work_buffer(TS_WORK_BUFFER *buf); + +static void extract_ts_header(TS_HEADER *dst, uint8_t *src); +static void extract_emm_fixed_part(EMM_FIXED_PART *dst, uint8_t *src); + +static uint8_t *resync(uint8_t *head, uint8_t *tail, int32_t unit); +static uint8_t *resync_force(uint8_t *head, uint8_t *tail, int32_t unit); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + interface method implementation + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +static void release_arib_std_b25(void *std_b25) +{ + ARIB_STD_B25_PRIVATE_DATA *prv; + + prv = private_data(std_b25); + if(prv == NULL){ + return; + } + + teardown(prv); + free(prv); +} + +static int set_multi2_round_arib_std_b25(void *std_b25, int32_t round) +{ + ARIB_STD_B25_PRIVATE_DATA *prv; + + prv = private_data(std_b25); + if(prv == NULL){ + return ARIB_STD_B25_ERROR_INVALID_PARAM; + } + + prv->multi2_round = round; + + return 0; +} + +static int set_strip_arib_std_b25(void *std_b25, int32_t strip) +{ + ARIB_STD_B25_PRIVATE_DATA *prv; + + prv = private_data(std_b25); + if(prv == NULL){ + return ARIB_STD_B25_ERROR_INVALID_PARAM; + } + + prv->strip = strip; + + return 0; +} + +static int set_emm_proc_arib_std_b25(void *std_b25, int32_t on) +{ + ARIB_STD_B25_PRIVATE_DATA *prv; + + prv = private_data(std_b25); + if(prv == NULL){ + return ARIB_STD_B25_ERROR_INVALID_PARAM; + } + + prv->emm_proc_on = on; + + return 0; +} + +static int set_b_cas_card_arib_std_b25(void *std_b25, B_CAS_CARD *bcas) +{ + int n; + B_CAS_INIT_STATUS is; + ARIB_STD_B25_PRIVATE_DATA *prv; + + prv = private_data(std_b25); + if(prv == NULL){ + return ARIB_STD_B25_ERROR_INVALID_PARAM; + } + + prv->bcas = bcas; + if(prv->bcas != NULL){ + n = prv->bcas->get_init_status(bcas, &is); + if(n < 0){ + return ARIB_STD_B25_ERROR_INVALID_B_CAS_STATUS; + } + prv->ca_system_id = is.ca_system_id; + n = prv->bcas->get_id(prv->bcas, &(prv->casid)); + if(n < 0){ + return ARIB_STD_B25_ERROR_INVALID_B_CAS_STATUS; + } + } + + return 0; +} + +static int reset_arib_std_b25(void *std_b25) +{ + ARIB_STD_B25_PRIVATE_DATA *prv; + + prv = private_data(std_b25); + if(prv == NULL){ + return ARIB_STD_B25_ERROR_INVALID_PARAM; + } + + teardown(prv); + + return 0; +} + +static int flush_arib_std_b25(void *std_b25) +{ + int r; + int m,n; + + int32_t crypt; + int32_t unit; + int32_t pid; + + uint8_t *p; + uint8_t *curr; + uint8_t *tail; + + TS_HEADER hdr; + DECRYPTOR_ELEM *dec; + TS_PROGRAM *pgrm; + + ARIB_STD_B25_PRIVATE_DATA *prv; + + prv = private_data(std_b25); + if(prv == NULL){ + return ARIB_STD_B25_ERROR_INVALID_PARAM; + } + + if(prv->unit_size < 188){ + r = select_unit_size(prv); + if(r < 0){ + return r; + } + } + + r = proc_arib_std_b25(prv); + if(r < 0){ + return r; + } + + unit = prv->unit_size; + curr = prv->sbuf.head; + tail = prv->sbuf.tail; + + m = prv->dbuf.tail - prv->dbuf.head; + n = tail - curr; + if(!reserve_work_buffer(&(prv->dbuf), m+n)){ + return ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; + } + + r = 0; + + while( (curr+188) <= tail ){ + + if(curr[0] != 0x47){ + p = resync_force(curr, tail, unit); + if(p == NULL){ + goto LAST; + } + curr = p; + } + + extract_ts_header(&hdr, curr); + crypt = hdr.transport_scrambling_control; + pid = hdr.pid; + + if( (pid == 0x1fff) && (prv->strip) ){ + goto NEXT; + } + + p = curr+4; + if(hdr.adaptation_field_control & 0x02){ + p += (p[0]+1); + } + n = 188 - (p-curr); + if( (n < 1) && ((n < 0) || (hdr.adaptation_field_control & 0x01)) ){ + /* broken packet */ + curr += 1; + continue; + } + + if( (crypt != 0) && + (hdr.adaptation_field_control & 0x01) ){ + + if(prv->map[pid].type == PID_MAP_TYPE_OTHER){ + dec = (DECRYPTOR_ELEM *)(prv->map[pid].target); + }else{ + dec = NULL; + } + + if( (dec != NULL) && (dec->m2 != NULL) ){ + m = dec->m2->decrypt(dec->m2, crypt, p, n); + if(m < 0){ + r = ARIB_STD_B25_ERROR_DECRYPT_FAILURE; + goto LAST; + } + curr[3] &= 0x3f; + prv->map[pid].normal_packet += 1; + }else{ + prv->map[pid].undecrypted += 1; + } + }else{ + prv->map[pid].normal_packet += 1; + } + + if(!append_work_buffer(&(prv->dbuf), curr, 188)){ + r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; + goto LAST; + } + + if(prv->map[pid].type == PID_MAP_TYPE_ECM){ + dec = (DECRYPTOR_ELEM *)(prv->map[pid].target); + if( (dec == NULL) || (dec->ecm == NULL) ){ + /* this code will never execute */ + r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; + goto LAST; + } + m = dec->ecm->put(dec->ecm, &hdr, p, n); + if(m < 0){ + r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; + goto LAST; + } + m = dec->ecm->get_count(dec->ecm); + if(m < 0){ + r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; + goto LAST; + } + if(m == 0){ + goto NEXT; + } + r = proc_ecm(dec, prv->bcas, prv->multi2_round); + if(r < 0){ + goto LAST; + } + }else if(prv->map[pid].type == PID_MAP_TYPE_PMT){ + pgrm = (TS_PROGRAM *)(prv->map[pid].target); + if( (pgrm == NULL) || (pgrm->pmt == NULL) ){ + /* this code will never execute */ + r = ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; + goto LAST; + } + m = pgrm->pmt->put(pgrm->pmt, &hdr, p, n); + if(m < 0){ + r = ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; + goto LAST; + } + m = pgrm->pmt->get_count(pgrm->pmt); + if(m < 0){ + r = ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; + goto LAST; + } + if(m == 0){ + goto NEXT; + } + r = proc_pmt(prv, pgrm); + if(r < 0){ + goto LAST; + } + }else if(prv->map[pid].type == PID_MAP_TYPE_EMM){ + if( prv->emm_proc_on == 0){ + goto NEXT; + } + if( prv->emm == NULL ){ + prv->emm = create_ts_section_parser(); + if(prv->emm == NULL){ + r = ARIB_STD_B25_ERROR_EMM_PARSE_FAILURE; + goto LAST; + } + } + m = prv->emm->put(prv->emm, &hdr, p, n); + if(m < 0){ + r = ARIB_STD_B25_ERROR_EMM_PARSE_FAILURE; + goto LAST; + } + m = prv->emm->get_count(prv->emm); + if(m < 0){ + r = ARIB_STD_B25_ERROR_EMM_PARSE_FAILURE; + goto LAST; + } + if(m == 0){ + goto NEXT; + } + r = proc_emm(prv); + if(r < 0){ + goto LAST; + } + }else if(pid == 0x0001){ + if( prv->cat == NULL ){ + prv->cat = create_ts_section_parser(); + if(prv->cat == NULL){ + r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; + goto LAST; + } + } + m = prv->cat->put(prv->cat, &hdr, p, n); + if(m < 0){ + r = ARIB_STD_B25_ERROR_CAT_PARSE_FAILURE; + goto LAST; + } + m = prv->cat->get_count(prv->cat); + if(m < 0){ + r = ARIB_STD_B25_ERROR_CAT_PARSE_FAILURE; + goto LAST; + } + if(m == 0){ + goto NEXT; + } + r = proc_cat(prv); + if(r < 0){ + goto LAST; + } + }else if(pid == 0x0000){ + if( prv->pat == NULL ){ + prv->pat = create_ts_section_parser(); + if(prv->pat == NULL){ + r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; + goto LAST; + } + } + m = prv->pat->put(prv->pat, &hdr, p, n); + if(m < 0){ + r = ARIB_STD_B25_ERROR_PAT_PARSE_FAILURE; + goto LAST; + } + m = prv->pat->get_count(prv->pat); + if(m < 0){ + r = ARIB_STD_B25_ERROR_PAT_PARSE_FAILURE; + goto LAST; + } + if(m == 0){ + goto NEXT; + } + r = proc_pat(prv); + if(r < 0){ + goto LAST; + } + } + + NEXT: + curr += unit; + } + +LAST: + + m = curr - prv->sbuf.head; + n = tail - curr; + if( (n < 1024) || (m > (prv->sbuf.max/2) ) ){ + p = prv->sbuf.pool; + memcpy(p, curr, n); + prv->sbuf.head = p; + prv->sbuf.tail = p+n; + }else{ + prv->sbuf.head = curr; + } + + return r; +} + +static int put_arib_std_b25(void *std_b25, ARIB_STD_B25_BUFFER *buf) +{ + int32_t n; + + ARIB_STD_B25_PRIVATE_DATA *prv; + + prv = private_data(std_b25); + if( (prv == NULL) || (buf == NULL) ){ + return ARIB_STD_B25_ERROR_INVALID_PARAM; + } + + if(!append_work_buffer(&(prv->sbuf), buf->data, buf->size)){ + return ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; + } + + if(prv->unit_size < 188){ + n = select_unit_size(prv); + if(n < 0){ + return n; + } + if(prv->unit_size < 188){ + /* need more data */ + return 0; + } + } + + if(prv->p_count < 1){ + n = find_pat(prv); + if(n < 0){ + return n; + } + if(prv->p_count < 1){ + if(prv->sbuf_offset < (16*1024*1024)){ + /* need more data */ + return 0; + }else{ + /* exceed sbuf limit */ + return ARIB_STD_B25_ERROR_NO_PAT_IN_HEAD_16M; + } + } + prv->sbuf_offset = 0; + } + + if(!check_pmt_complete(prv)){ + n = find_pmt(prv); + if(n < 0){ + return n; + } + if(!check_pmt_complete(prv)){ + if(prv->sbuf_offset < (32*1024*1024)){ + /* need more data */ + return 0; + }else{ + /* exceed sbuf limit */ + return ARIB_STD_B25_ERROR_NO_PMT_IN_HEAD_32M; + } + } + prv->sbuf_offset = 0; + } + + if(!check_ecm_complete(prv)){ + n = find_ecm(prv); + if(n < 0){ + return n; + } + if(!check_ecm_complete(prv)){ + if(prv->sbuf_offset < (32*1024*1024)){ + /* need more data */ + return 0; + }else{ + /* exceed sbuf limit */ + return ARIB_STD_B25_ERROR_NO_ECM_IN_HEAD_32M; + } + } + prv->sbuf_offset = 0; + } + + return proc_arib_std_b25(prv); +} + +static int get_arib_std_b25(void *std_b25, ARIB_STD_B25_BUFFER *buf) +{ + ARIB_STD_B25_PRIVATE_DATA *prv; + prv = private_data(std_b25); + if( (prv == NULL) || (buf == NULL) ){ + return ARIB_STD_B25_ERROR_INVALID_PARAM; + } + + buf->data = prv->dbuf.head; + buf->size = prv->dbuf.tail - prv->dbuf.head; + + reset_work_buffer(&(prv->dbuf)); + + return 0; +} + +static int get_program_count_arib_std_b25(void *std_b25) +{ + ARIB_STD_B25_PRIVATE_DATA *prv; + + prv = private_data(std_b25); + if(prv == NULL){ + return ARIB_STD_B25_ERROR_INVALID_PARAM; + } + + return prv->p_count; +} + +static int get_program_info_arib_std_b25(void *std_b25, ARIB_STD_B25_PROGRAM_INFO *info, int idx) +{ + ARIB_STD_B25_PRIVATE_DATA *prv; + + TS_PROGRAM *pgrm; + + TS_STREAM_ELEM *strm; + DECRYPTOR_ELEM *dec; + + int32_t pid; + + prv = private_data(std_b25); + if( (prv == NULL) || (info == NULL) || (idx < 0) || (idx >= prv->p_count) ){ + return ARIB_STD_B25_ERROR_INVALID_PARAM; + } + + pgrm = prv->program + idx; + + memset(info, 0, sizeof(ARIB_STD_B25_PROGRAM_INFO)); + + info->program_number = pgrm->program_number; + + pid = pgrm->pmt_pid; + info->total_packet_count += prv->map[pid].normal_packet; + info->total_packet_count += prv->map[pid].undecrypted; + info->undecrypted_packet_count += prv->map[pid].undecrypted; + + pid = pgrm->pcr_pid; + if( (pid != 0) && (pid != 0x1fff) ){ + info->total_packet_count += prv->map[pid].normal_packet; + info->total_packet_count += prv->map[pid].undecrypted; + info->undecrypted_packet_count += prv->map[pid].undecrypted; + } + + strm = pgrm->streams.head; + while(strm != NULL){ + pid = strm->pid; + if(prv->map[pid].type == PID_MAP_TYPE_ECM){ + dec = (DECRYPTOR_ELEM *)(prv->map[pid].target); + info->ecm_unpurchased_count += dec->unpurchased; + info->last_ecm_error_code = dec->last_error; + } + info->total_packet_count += prv->map[pid].normal_packet; + info->total_packet_count += prv->map[pid].undecrypted; + info->undecrypted_packet_count += prv->map[pid].undecrypted; + strm = (TS_STREAM_ELEM *)(strm->next); + } + + return 0; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + private method implementation + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +static ARIB_STD_B25_PRIVATE_DATA *private_data(void *std_b25) +{ + ARIB_STD_B25 *p; + ARIB_STD_B25_PRIVATE_DATA *r; + + p = (ARIB_STD_B25 *)std_b25; + if(p == NULL){ + return NULL; + } + + r = (ARIB_STD_B25_PRIVATE_DATA *)p->private_data; + if( ((void *)(r+1)) != ((void *)p) ){ + return NULL; + } + + return r; +} + +static void teardown(ARIB_STD_B25_PRIVATE_DATA *prv) +{ + int i; + + prv->unit_size = 0; + prv->sbuf_offset = 0; + + if(prv->pat != NULL){ + prv->pat->release(prv->pat); + prv->pat = NULL; + } + if(prv->cat != NULL){ + prv->cat->release(prv->cat); + prv->cat = NULL; + } + + if(prv->program != NULL){ + for(i=0;ip_count;i++){ + release_program(prv, prv->program+i); + } + free(prv->program); + prv->program = NULL; + } + prv->p_count = 0; + + clear_stream_list(&(prv->strm_pool)); + + while(prv->decrypt.head != NULL){ + remove_decryptor(prv, prv->decrypt.head); + } + + memset(prv->map, 0, sizeof(prv->map)); + + prv->emm_pid = 0; + if(prv->emm != NULL){ + prv->emm->release(prv->emm); + prv->emm = NULL; + } + + release_work_buffer(&(prv->sbuf)); + release_work_buffer(&(prv->dbuf)); +} + +static int select_unit_size(ARIB_STD_B25_PRIVATE_DATA *prv) +{ + int i; + int m,n,w; + int count[320-188]; + + unsigned char *head; + unsigned char *buf; + unsigned char *tail; + + head = prv->sbuf.head; + tail = prv->sbuf.tail; + + buf = head; + memset(count, 0, sizeof(count)); + + // 1st step, count up 0x47 interval + while( (buf+188) < tail ){ + if(buf[0] != 0x47){ + buf += 1; + continue; + } + m = 320; + if( buf+m > tail ){ + m = tail-buf; + } + for(i=188;iunit_size = n; + + return 0; +} + +static int find_pat(ARIB_STD_B25_PRIVATE_DATA *prv) +{ + int r; + int n,size; + + int32_t unit; + + uint8_t *p; + uint8_t *curr; + uint8_t *tail; + + TS_HEADER hdr; + + r = 0; + unit = prv->unit_size; + curr = prv->sbuf.head + prv->sbuf_offset; + tail = prv->sbuf.tail; + + while( (curr+unit) < tail ){ + if( (curr[0] != 0x47) || (curr[unit] != 0x47) ){ + p = resync(curr, tail, unit); + if(p == NULL){ + goto LAST; + } + curr = p; + } + extract_ts_header(&hdr, curr); + if(hdr.pid == 0x0000){ + + p = curr+4; + if(hdr.adaptation_field_control & 0x02){ + p += (p[0]+1); + } + size = 188 - (p-curr); + if(size < 1){ + goto NEXT; + } + + if(prv->pat == NULL){ + prv->pat = create_ts_section_parser(); + if(prv->pat == NULL){ + return ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; + } + } + + n = prv->pat->put(prv->pat, &hdr, p, size); + if(n < 0){ + r = ARIB_STD_B25_ERROR_PAT_PARSE_FAILURE; + curr += unit; + goto LAST; + } + n = prv->pat->get_count(prv->pat); + if(n < 0){ + r = ARIB_STD_B25_ERROR_PAT_PARSE_FAILURE; + curr += unit; + goto LAST; + } + if(n > 0){ + curr += unit; + goto LAST; + } + } + NEXT: + curr += unit; + } + +LAST: + prv->sbuf_offset = curr - prv->sbuf.head; + + if( (prv->pat != NULL) && (prv->pat->get_count(prv->pat) > 0) ){ + r = proc_pat(prv); + } + + return r; +} + +static int proc_pat(ARIB_STD_B25_PRIVATE_DATA *prv) +{ + int r; + int i,n; + int len; + int count; + + int32_t program_number; + int32_t pid; + + uint8_t *head; + uint8_t *tail; + + TS_PROGRAM *work; + TS_SECTION sect; + + r = 0; + memset(§, 0, sizeof(sect)); + + n = prv->pat->get(prv->pat, §); + if(n < 0){ + r = ARIB_STD_B25_ERROR_PAT_PARSE_FAILURE; + goto LAST; + } + + if(sect.hdr.table_id != TS_SECTION_ID_PROGRAM_ASSOCIATION){ + r = ARIB_STD_B25_WARN_TS_SECTION_ID_MISSMATCH; + goto LAST; + } + + len = (sect.tail - sect.data) - 4; + + count = len / 4; + work = (TS_PROGRAM *)calloc(count, sizeof(TS_PROGRAM)); + if(work == NULL){ + r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; + goto LAST; + } + + if(prv->program != NULL){ + for(i=0;ip_count;i++){ + release_program(prv, prv->program+i); + } + free(prv->program); + prv->program = NULL; + } + prv->p_count = 0; + memset(&(prv->map), 0, sizeof(prv->map)); + + head = sect.data; + tail = sect.tail-4; + + i = 0; + while( (head+4) <= tail ){ + program_number = ((head[0] << 8) | head[1]); + pid = ((head[2] << 8) | head[3]) & 0x1fff; + if(program_number != 0){ + work[i].program_number = program_number; + work[i].pmt_pid = pid; + work[i].pmt = create_ts_section_parser(); + if(work[i].pmt == NULL){ + r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; + break; + } + prv->map[pid].type = PID_MAP_TYPE_PMT; + prv->map[pid].target = work+i; + i += 1; + } + head += 4; + } + + prv->program = work; + prv->p_count = i; + + prv->map[0x0000].ref = 1; + prv->map[0x0000].type = PID_MAP_TYPE_PAT; + prv->map[0x0000].target = NULL; + +LAST: + if(sect.raw != NULL){ + n = prv->pat->ret(prv->pat, §); + if( (n < 0) && (r == 0) ){ + r = ARIB_STD_B25_ERROR_PAT_PARSE_FAILURE; + } + } + + return r; +} + +static int check_pmt_complete(ARIB_STD_B25_PRIVATE_DATA *prv) +{ + int i,n; + int num[3]; + + memset(num, 0, sizeof(num)); + + for(i=0;ip_count;i++){ + n = prv->program[i].phase; + if(n < 0){ + n = 0; + }else if(n > 2){ + n = 2; + } + num[n] += 1; + } + + if(num[2] > 0){ + return 1; + } + + if(num[0] > 0){ + return 0; + } + + return 1; +} + +static int find_pmt(ARIB_STD_B25_PRIVATE_DATA *prv) +{ + int r; + int n,size; + + int32_t unit; + + uint8_t *p; + uint8_t *curr; + uint8_t *tail; + + TS_HEADER hdr; + TS_PROGRAM *pgrm; + + r = 0; + unit = prv->unit_size; + curr = prv->sbuf.head + prv->sbuf_offset; + tail = prv->sbuf.tail; + + while( (curr+unit) < tail ){ + + if( (curr[0] != 0x47) || (curr[unit] != 0x47) ){ + p = resync(curr, tail, unit); + if(p == NULL){ + goto LAST; + } + curr = p; + } + + extract_ts_header(&hdr, curr); + + if(prv->map[hdr.pid].type != PID_MAP_TYPE_PMT){ + goto NEXT; + } + pgrm = (TS_PROGRAM *)(prv->map[hdr.pid].target); + if(pgrm == NULL){ + goto NEXT; + } + + if(pgrm->phase == 0){ + + p = curr + 4; + if(hdr.adaptation_field_control & 0x02){ + p += (p[0]+1); + } + size = 188 - (p-curr); + if(size < 1){ + goto NEXT; + } + + if(pgrm->pmt == NULL){ + /* this code will never execute */ + r = ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; + curr += unit; + goto LAST; + } + + n = pgrm->pmt->put(pgrm->pmt, &hdr, p, size); + if(n < 0){ + r = ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; + curr += unit; + goto LAST; + } + n = pgrm->pmt->get_count(pgrm->pmt); + if(n < 0){ + r =ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; + curr += unit; + goto LAST; + } + if(n == 0){ + goto NEXT; + } + r = proc_pmt(prv, pgrm); + if(r < 0){ + curr += unit; + goto LAST; + } + if(r > 0){ + /* broken or unexpected section data */ + goto NEXT; + } + pgrm->phase = 1; + if(check_pmt_complete(prv)){ + curr += unit; + goto LAST; + } + }else{ + pgrm->phase = 2; + curr += unit; + goto LAST; + } + + NEXT: + curr += unit; + } + +LAST: + prv->sbuf_offset = curr - prv->sbuf.head; + + return r; +} + +static int proc_pmt(ARIB_STD_B25_PRIVATE_DATA *prv, TS_PROGRAM *pgrm) +{ + int r; + + int n; + int length; + + uint8_t *head; + uint8_t *tail; + + int32_t ecm_pid; + int32_t pid; + int32_t type; + + TS_SECTION sect; + + DECRYPTOR_ELEM *dec[2]; + DECRYPTOR_ELEM *dw; + + TS_STREAM_ELEM *strm; + + r = 0; + dec[0] = NULL; + memset(§, 0, sizeof(sect)); + + n = pgrm->pmt->get(pgrm->pmt, §); + if(n < 0){ + r = ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; + goto LAST; + } + if(sect.hdr.table_id != TS_SECTION_ID_PROGRAM_MAP){ + r = ARIB_STD_B25_WARN_TS_SECTION_ID_MISSMATCH; + goto LAST; + } + + head = sect.data; + tail = sect.tail-4; + + pgrm->pcr_pid = ((head[0] << 8) | head[1]) & 0x1fff; + length = ((head[2] << 8) | head[3]) & 0x0fff; + head += 4; + if(head+length > tail){ + r = ARIB_STD_B25_WARN_BROKEN_TS_SECTION; + goto LAST; + } + + /* find major ecm_pid and regist decryptor */ + ecm_pid = find_ca_descriptor_pid(head, head+length, prv->ca_system_id); + if( (ecm_pid != 0) && (ecm_pid != 0x1fff) ){ + dec[0] = set_decryptor(prv, ecm_pid); + if(dec[0] == NULL){ + r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; + goto LAST; + } + dec[0]->ref += 1; + } + head += length; + + /* unref old stream entries */ + while( (strm = get_stream_list_head(&(pgrm->old_strm))) != NULL ){ + unref_stream(prv, strm->pid); + memset(strm, 0, sizeof(TS_STREAM_ELEM)); + put_stream_list_tail(&(prv->strm_pool), strm); + } + + /* save current streams */ + memcpy(&(pgrm->old_strm), &(pgrm->streams), sizeof(TS_STREAM_LIST)); + memset(&(pgrm->streams), 0, sizeof(TS_STREAM_LIST)); + + /* add current stream entries */ + if( (ecm_pid != 0) && (ecm_pid != 0x1fff) ){ + if(!add_ecm_stream(prv, &(pgrm->streams), ecm_pid)){ + r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; + goto LAST; + } + } + + while( head+4 < tail ){ + + type = head[0]; + pid = ((head[1] << 8) | head[2]) & 0x1fff; + length = ((head[3] << 8) | head[4]) & 0x0fff; + head += 5; + ecm_pid = find_ca_descriptor_pid(head, head+length, prv->ca_system_id); + head += length; + + if( (ecm_pid != 0) && (ecm_pid != 0x1fff) ){ + dec[1] = set_decryptor(prv, ecm_pid); + if(dec[1] == NULL){ + r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; + goto LAST; + } + if(!add_ecm_stream(prv, &(pgrm->streams), ecm_pid)){ + r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; + goto LAST; + } + }else{ + dec[1] = NULL; + } + + strm = get_stream_list_head(&(prv->strm_pool)); + if( strm == NULL ){ + strm = create_stream_elem(pid, type); + if(strm == NULL){ + r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; + goto LAST; + } + }else{ + strm->pid = pid; + strm->type = type; + } + + prv->map[pid].type = PID_MAP_TYPE_OTHER; + prv->map[pid].ref += 1; + + dw = select_active_decryptor(dec[0], dec[1], ecm_pid); + bind_stream_decryptor(prv, pid, dw); + + put_stream_list_tail(&(pgrm->streams), strm); + } + +LAST: + if( dec[0] != NULL ){ + dec[0]->ref -= 1; + if( dec[0]->ref < 1 ){ + remove_decryptor(prv, dec[0]); + dec[0] = NULL; + } + } + + if(sect.raw != NULL){ + n = pgrm->pmt->ret(pgrm->pmt, §); + if( (n < 0) && (r == 0) ){ + return ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; + } + } + + return 0; +} + +static int32_t find_ca_descriptor_pid(uint8_t *head, uint8_t *tail, int32_t ca_system_id) +{ + uint32_t ca_pid; + uint32_t ca_sys_id; + + uint32_t tag; + uint32_t len; + + while(head+1 < tail){ + tag = head[0]; + len = head[1]; + head += 2; + if( (tag == 0x09) && /* CA_descriptor */ + (len >= 4) && + (head+len <= tail) ){ + ca_sys_id = ((head[0] << 8) | head[1]); + ca_pid = ((head[2] << 8) | head[3]) & 0x1fff; + if(ca_sys_id == ca_system_id){ + return ca_pid; + } + } + head += len; + } + + return 0; +} + +static int add_ecm_stream(ARIB_STD_B25_PRIVATE_DATA *prv, TS_STREAM_LIST *list, int32_t ecm_pid) +{ + TS_STREAM_ELEM *strm; + + strm = find_stream_list_elem(list, ecm_pid); + if(strm != NULL){ + // ECM is already registered + return 1; + } + + strm = get_stream_list_head(&(prv->strm_pool)); + if(strm == NULL){ + strm = create_stream_elem(ecm_pid, PID_MAP_TYPE_ECM); + if(strm == NULL){ + return 0; + } + }else{ + strm->pid = ecm_pid; + strm->type = PID_MAP_TYPE_ECM; + } + + put_stream_list_tail(list, strm); + prv->map[ecm_pid].ref += 1; + + return 1; +} + +static int check_ecm_complete(ARIB_STD_B25_PRIVATE_DATA *prv) +{ + int n,num[3]; + DECRYPTOR_ELEM *e; + + memset(num, 0, sizeof(num)); + + e = prv->decrypt.head; + while( e != NULL ){ + n = e->phase; + if(n < 0){ + n = 0; + }else if(n > 2){ + n = 2; + } + num[n] += 1; + e = (DECRYPTOR_ELEM *)(e->next); + } + + if(num[2] > 0){ + return 1; + } + + if(num[0] > 0){ + return 0; + } + + return 1; +} + +static int find_ecm(ARIB_STD_B25_PRIVATE_DATA *prv) +{ + int r; + int n,size; + + int32_t unit; + + uint8_t *p; + uint8_t *curr; + uint8_t *tail; + + TS_HEADER hdr; + DECRYPTOR_ELEM *dec; + + r = 0; + unit = prv->unit_size; + curr = prv->sbuf.head + prv->sbuf_offset; + tail = prv->sbuf.tail; + + while( (curr+unit) < tail ){ + if( (curr[0] != 0x47) || (curr[unit] != 0x47) ){ + p = resync(curr, tail, unit); + if(p == NULL){ + goto LAST; + } + curr = p; + } + extract_ts_header(&hdr, curr); + if(prv->map[hdr.pid].type != PID_MAP_TYPE_ECM){ + goto NEXT; + } + dec = (DECRYPTOR_ELEM *)(prv->map[hdr.pid].target); + if(dec == NULL){ + goto NEXT; + } + + if(dec->phase == 0){ + + p = curr + 4; + if(hdr.adaptation_field_control & 0x02){ + p += (p[0]+1); + } + size = 188 - (p-curr); + if(size < 1){ + goto NEXT; + } + + if(dec->ecm == NULL){ + /* this code will never execute */ + r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; + curr += unit; + goto LAST; + } + + n = dec->ecm->put(dec->ecm, &hdr, p, size); + if(n < 0){ + r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; + curr += unit; + goto LAST; + } + n = dec->ecm->get_count(dec->ecm); + if(n < 0){ + r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; + curr += unit; + goto LAST; + } + if(n == 0){ + goto NEXT; + } + + r = proc_ecm(dec, prv->bcas, prv->multi2_round); + if(r < 0){ + curr += unit; + goto LAST; + } + if( (r > 0) && (r != ARIB_STD_B25_WARN_UNPURCHASED_ECM) ){ + /* broken or unexpected section data */ + goto NEXT; + } + + dec->phase = 1; + if(check_ecm_complete(prv)){ + curr += unit; + goto LAST; + } + + }else{ + dec->phase = 2; + curr += unit; + goto LAST; + } + + NEXT: + curr += unit; + } + +LAST: + prv->sbuf_offset = curr - prv->sbuf.head; + + return r; +} + +static int proc_ecm(DECRYPTOR_ELEM *dec, B_CAS_CARD *bcas, int32_t multi2_round) +{ + int r,n; + int length; + + uint8_t *p; + + B_CAS_INIT_STATUS is; + B_CAS_ECM_RESULT res; + + TS_SECTION sect; + + r = 0; + memset(§, 0, sizeof(sect)); + + if(bcas == NULL){ + r = ARIB_STD_B25_ERROR_EMPTY_B_CAS_CARD; + goto LAST; + } + + n = dec->ecm->get(dec->ecm, §); + if(n < 0){ + r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; + goto LAST; + } + if(sect.hdr.table_id != TS_SECTION_ID_ECM_S){ + r = ARIB_STD_B25_WARN_TS_SECTION_ID_MISSMATCH; + goto LAST; + } + + if(dec->locked){ + /* previous ECM has returned unpurchased + skip this pid for B-CAS card load reduction */ + dec->unpurchased += 1; + r = ARIB_STD_B25_WARN_UNPURCHASED_ECM; + goto LAST; + } + + length = (sect.tail - sect.data) - 4; + p = sect.data; + + r = bcas->proc_ecm(bcas, &res, p, length); + if(r < 0){ + if(dec->m2 != NULL){ + dec->m2->clear_scramble_key(dec->m2); + } + r = ARIB_STD_B25_ERROR_ECM_PROC_FAILURE; + goto LAST; + } + + if( (res.return_code != 0x0800) && + (res.return_code != 0x0400) && + (res.return_code != 0x0200) ){ + /* return_code is not equal "purchased" */ + if(dec->m2 != NULL){ + dec->m2->release(dec->m2); + dec->m2 = NULL; + } + dec->unpurchased += 1; + dec->last_error = res.return_code; + dec->locked += 1; + r = ARIB_STD_B25_WARN_UNPURCHASED_ECM; + goto LAST; + } + + if(dec->m2 == NULL){ + dec->m2 = create_multi2(); + if(dec->m2 == NULL){ + return ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; + } + r = bcas->get_init_status(bcas, &is); + if(r < 0){ + return ARIB_STD_B25_ERROR_INVALID_B_CAS_STATUS; + } + dec->m2->set_system_key(dec->m2, is.system_key); + dec->m2->set_init_cbc(dec->m2, is.init_cbc); + dec->m2->set_round(dec->m2, multi2_round); + } + + dec->m2->set_scramble_key(dec->m2, res.scramble_key); + +LAST: + if(sect.raw != NULL){ + n = dec->ecm->ret(dec->ecm, §); + if( (n < 0) && (r == 0) ){ + r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; + } + } + + return r; +} + +static int proc_arib_std_b25(ARIB_STD_B25_PRIVATE_DATA *prv) +{ + int r; + int m,n; + + int32_t crypt; + int32_t unit; + int32_t pid; + + uint8_t *p; + uint8_t *curr; + uint8_t *tail; + + TS_HEADER hdr; + DECRYPTOR_ELEM *dec; + TS_PROGRAM *pgrm; + + unit = prv->unit_size; + curr = prv->sbuf.head; + tail = prv->sbuf.tail; + + m = prv->dbuf.tail - prv->dbuf.head; + n = tail - curr; + if(!reserve_work_buffer(&(prv->dbuf), m+n)){ + return ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; + } + + r = 0; + + while( (curr+unit) < tail ){ + + if( (curr[0] != 0x47) || (curr[unit] != 0x47) ){ + p = resync(curr, tail, unit); + if(p == NULL){ + goto LAST; + } + curr = p; + } + + extract_ts_header(&hdr, curr); + crypt = hdr.transport_scrambling_control; + pid = hdr.pid; + + if( (pid == 0x1fff) && (prv->strip) ){ + /* strip null(padding) stream */ + goto NEXT; + } + + p = curr+4; + if(hdr.adaptation_field_control & 0x02){ + p += (p[0]+1); + } + n = 188 - (p-curr); + if( (n < 1) && ((n < 0) || (hdr.adaptation_field_control & 0x01)) ){ + /* broken packet */ + curr += 1; + continue; + } + + if( (crypt != 0) && + (hdr.adaptation_field_control & 0x01) ){ + + if(prv->map[pid].type == PID_MAP_TYPE_OTHER){ + dec = (DECRYPTOR_ELEM *)(prv->map[pid].target); + }else if( (prv->map[pid].type == 0) && + (prv->decrypt.count == 1) ){ + dec = prv->decrypt.head; + }else{ + dec = NULL; + } + + if( (dec != NULL) && (dec->m2 != NULL) ){ + m = dec->m2->decrypt(dec->m2, crypt, p, n); + if(m < 0){ + r = ARIB_STD_B25_ERROR_DECRYPT_FAILURE; + goto LAST; + } + curr[3] &= 0x3f; + prv->map[pid].normal_packet += 1; + }else{ + prv->map[pid].undecrypted += 1; + } + }else{ + prv->map[pid].normal_packet += 1; + } + + if(!append_work_buffer(&(prv->dbuf), curr, 188)){ + r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; + goto LAST; + } + + if(prv->map[pid].type == PID_MAP_TYPE_ECM){ + dec = (DECRYPTOR_ELEM *)(prv->map[pid].target); + if( (dec == NULL) || (dec->ecm == NULL) ){ + /* this code will never execute */ + r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; + goto LAST; + } + m = dec->ecm->put(dec->ecm, &hdr, p, n); + if(m < 0){ + r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; + goto LAST; + } + m = dec->ecm->get_count(dec->ecm); + if(m < 0){ + r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; + goto LAST; + } + if(m == 0){ + goto NEXT; + } + r = proc_ecm(dec, prv->bcas, prv->multi2_round); + if(r < 0){ + goto LAST; + } + }else if(prv->map[pid].type == PID_MAP_TYPE_PMT){ + pgrm = (TS_PROGRAM *)(prv->map[pid].target); + if( (pgrm == NULL) || (pgrm->pmt == NULL) ){ + /* this code will never execute */ + r = ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; + goto LAST; + } + m = pgrm->pmt->put(pgrm->pmt, &hdr, p, n); + if(m < 0){ + r = ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; + goto LAST; + } + m = pgrm->pmt->get_count(pgrm->pmt); + if(m < 0){ + r = ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; + goto LAST; + } + if(m == 0){ + goto NEXT; + } + r = proc_pmt(prv, pgrm); + if(r < 0){ + goto LAST; + } + }else if(prv->map[pid].type == PID_MAP_TYPE_EMM){ + if( prv->emm_proc_on == 0){ + goto NEXT; + } + if( prv->emm == NULL ){ + prv->emm = create_ts_section_parser(); + if(prv->emm == NULL){ + r = ARIB_STD_B25_ERROR_EMM_PARSE_FAILURE; + goto LAST; + } + } + m = prv->emm->put(prv->emm, &hdr, p, n); + if(m < 0){ + r = ARIB_STD_B25_ERROR_EMM_PARSE_FAILURE; + goto LAST; + } + m = prv->emm->get_count(prv->emm); + if(m < 0){ + r = ARIB_STD_B25_ERROR_EMM_PARSE_FAILURE; + goto LAST; + } + if(m == 0){ + goto NEXT; + } + r = proc_emm(prv); + if(r < 0){ + goto LAST; + } + }else if(pid == 0x0001){ + if( prv->cat == NULL ){ + prv->cat = create_ts_section_parser(); + if(prv->cat == NULL){ + r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; + goto LAST; + } + } + m = prv->cat->put(prv->cat, &hdr, p, n); + if(m < 0){ + r = ARIB_STD_B25_ERROR_CAT_PARSE_FAILURE; + goto LAST; + } + m = prv->cat->get_count(prv->cat); + if(m < 0){ + r = ARIB_STD_B25_ERROR_CAT_PARSE_FAILURE; + goto LAST; + } + if(m == 0){ + goto NEXT; + } + r = proc_cat(prv); + if(r < 0){ + goto LAST; + } + }else if(pid == 0x0000){ + if( prv->pat == NULL ){ + prv->pat = create_ts_section_parser(); + if(prv->pat == NULL){ + r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; + goto LAST; + } + } + m = prv->pat->put(prv->pat, &hdr, p, n); + if(m < 0){ + r = ARIB_STD_B25_ERROR_PAT_PARSE_FAILURE; + goto LAST; + } + m = prv->pat->get_count(prv->pat); + if(m < 0){ + r = ARIB_STD_B25_ERROR_PAT_PARSE_FAILURE; + goto LAST; + } + if(m == 0){ + goto NEXT; + } + r = proc_pat(prv); + goto LAST; + } + + NEXT: + curr += unit; + } + +LAST: + m = curr - prv->sbuf.head; + n = tail - curr; + if( (n < 1024) || (m > (prv->sbuf.max/2) ) ){ + p = prv->sbuf.pool; + memcpy(p, curr, n); + prv->sbuf.head = p; + prv->sbuf.tail = p+n; + }else{ + prv->sbuf.head = curr; + } + + return r; +} + +static int proc_cat(ARIB_STD_B25_PRIVATE_DATA *prv) +{ + int r; + int n; + int emm_pid; + + TS_SECTION sect; + + r = 0; + memset(§, 0, sizeof(sect)); + + n = prv->cat->get(prv->cat, §); + if(n < 0){ + r = ARIB_STD_B25_ERROR_CAT_PARSE_FAILURE; + goto LAST; + } + + if(sect.hdr.table_id != TS_SECTION_ID_CONDITIONAL_ACCESS){ + r = ARIB_STD_B25_WARN_TS_SECTION_ID_MISSMATCH; + goto LAST; + } + + emm_pid = find_ca_descriptor_pid(sect.data, sect.tail-4, prv->ca_system_id); + if( (emm_pid != 0x0000) && (emm_pid != 0x1fff) ){ + if( (prv->map[emm_pid].target != NULL) && + (prv->map[emm_pid].type == PID_MAP_TYPE_OTHER) ){ + DECRYPTOR_ELEM *dec; + dec = (DECRYPTOR_ELEM *)(prv->map[emm_pid].target); + dec->ref -= 1; + if(dec->ref < 1){ + remove_decryptor(prv, dec); + } + } + prv->emm_pid = emm_pid; + prv->map[emm_pid].ref = 1; + prv->map[emm_pid].type = PID_MAP_TYPE_EMM; + prv->map[emm_pid].target = NULL; + } + + prv->map[0x0001].ref = 1; + prv->map[0x0001].type = PID_MAP_TYPE_CAT; + prv->map[0x0001].target = NULL; + +LAST: + + if(sect.raw != NULL){ + n = prv->cat->ret(prv->cat, §); + if( (n < 0) && (r == 0) ){ + r = ARIB_STD_B25_ERROR_CAT_PARSE_FAILURE; + } + } + + return r; +} + +static int proc_emm(ARIB_STD_B25_PRIVATE_DATA *prv) +{ + int r; + int i,j,n; + + int len; + + uint8_t *head; + uint8_t *tail; + + TS_SECTION sect; + EMM_FIXED_PART emm_hdr; + + r = 0; + memset(§, 0, sizeof(sect)); + + if(prv->bcas == NULL){ + r = ARIB_STD_B25_ERROR_EMPTY_B_CAS_CARD; + goto LAST; + } + + while( (n = prv->emm->get_count(prv->emm)) > 0 ){ + + n = prv->emm->get(prv->emm, §); + if(n < 0){ + r = ARIB_STD_B25_ERROR_CAT_PARSE_FAILURE; + goto LAST; + } + + if(sect.hdr.table_id == TS_SECTION_ID_EMM_MESSAGE){ + /* EMM_MESSAGE is not supported */ + goto NEXT; + }else if(sect.hdr.table_id != TS_SECTION_ID_EMM_S){ + r = ARIB_STD_B25_WARN_TS_SECTION_ID_MISSMATCH; + goto LAST; + } + + head = sect.data; + tail = sect.tail - 4; + + i = 0; + while( (head+13) <= tail ){ + + extract_emm_fixed_part(&emm_hdr, head); + len = emm_hdr.associated_information_length+7; + if( (head+len) > tail ){ + /* broken EMM element */ + goto NEXT; + } + + for(j=0;jcasid.count;j++){ + if(prv->casid.data[j] == emm_hdr.card_id){ + n = prv->bcas->proc_emm(prv->bcas, head, len); + if(n < 0){ + r = ARIB_STD_B25_ERROR_EMM_PROC_FAILURE; + goto LAST; + } + unlock_all_decryptor(prv); + } + } + + head += len; + } + + NEXT: + if(sect.raw != NULL){ + n = prv->emm->ret(prv->emm, §); + if( (n < 0) && (r == 0) ){ + r = ARIB_STD_B25_ERROR_EMM_PARSE_FAILURE; + goto LAST; + } + memset(§, 0, sizeof(sect)); + } + } + +LAST: + if(sect.raw != NULL){ + n = prv->emm->ret(prv->emm, §); + if( (n < 0) && (r == 0) ){ + r = ARIB_STD_B25_ERROR_EMM_PARSE_FAILURE; + } + } + + return r; +} + +static void release_program(ARIB_STD_B25_PRIVATE_DATA *prv, TS_PROGRAM *pgrm) +{ + int32_t pid; + TS_STREAM_ELEM *strm; + + pid = pgrm->pmt_pid; + + if(pgrm->pmt != NULL){ + pgrm->pmt->release(pgrm->pmt); + pgrm->pmt = NULL; + } + + while( (strm = get_stream_list_head(&(pgrm->old_strm))) != NULL ){ + unref_stream(prv, strm->pid); + memset(strm, 0, sizeof(TS_STREAM_ELEM)); + put_stream_list_tail(&(prv->strm_pool), strm); + } + + while( (strm = get_stream_list_head(&(pgrm->streams))) != NULL ){ + unref_stream(prv, strm->pid); + memset(strm, 0, sizeof(TS_STREAM_ELEM)); + put_stream_list_tail(&(prv->strm_pool), strm); + } + + prv->map[pid].type = PID_MAP_TYPE_UNKNOWN; + prv->map[pid].ref = 0; + prv->map[pid].target = NULL; +} + +static void unref_stream(ARIB_STD_B25_PRIVATE_DATA *prv, int32_t pid) +{ + DECRYPTOR_ELEM *dec; + + prv->map[pid].ref -= 1; + if( prv->map[pid].ref < 1 ){ + if( (prv->map[pid].target != NULL) && + (prv->map[pid].type == PID_MAP_TYPE_OTHER) ){ + dec = (DECRYPTOR_ELEM *)(prv->map[pid].target); + dec->ref -= 1; + if(dec->ref < 1){ + remove_decryptor(prv, dec); + } + } + prv->map[pid].type = PID_MAP_TYPE_UNKNOWN; + prv->map[pid].ref = 0; + prv->map[pid].target = NULL; + } +} + +static DECRYPTOR_ELEM *set_decryptor(ARIB_STD_B25_PRIVATE_DATA *prv, int32_t pid) +{ + DECRYPTOR_ELEM *r; + + r = NULL; + if(prv->map[pid].type == PID_MAP_TYPE_ECM){ + r = (DECRYPTOR_ELEM *)(prv->map[pid].target); + if(r != NULL){ + return r; + } + } + r = (DECRYPTOR_ELEM *)calloc(1, sizeof(DECRYPTOR_ELEM)); + if(r == NULL){ + return NULL; + } + r->ecm_pid = pid; + r->ecm = create_ts_section_parser(); + if(r->ecm == NULL){ + free(r); + return NULL; + } + + if(prv->decrypt.tail != NULL){ + r->prev = prv->decrypt.tail; + r->next = NULL; + prv->decrypt.tail->next = r; + prv->decrypt.tail = r; + prv->decrypt.count += 1; + }else{ + r->prev = NULL; + r->next = NULL; + prv->decrypt.head = r; + prv->decrypt.tail = r; + prv->decrypt.count = 1; + } + + if( (prv->map[pid].type == PID_MAP_TYPE_OTHER) && + (prv->map[pid].target != NULL) ){ + DECRYPTOR_ELEM *dec; + dec = (DECRYPTOR_ELEM *)(prv->map[pid].target); + dec->ref -= 1; + if(dec->ref < 1){ + remove_decryptor(prv, dec); + } + } + + prv->map[pid].type = PID_MAP_TYPE_ECM; + prv->map[pid].target = r; + + return r; +} + +static void remove_decryptor(ARIB_STD_B25_PRIVATE_DATA *prv, DECRYPTOR_ELEM *dec) +{ + int32_t pid; + + DECRYPTOR_ELEM *prev; + DECRYPTOR_ELEM *next; + + pid = dec->ecm_pid; + if( (prv->map[pid].type == PID_MAP_TYPE_ECM) && + (prv->map[pid].target == ((void *)dec)) ){ + prv->map[pid].type = PID_MAP_TYPE_UNKNOWN; + prv->map[pid].target = NULL; + } + + prev = (DECRYPTOR_ELEM *)(dec->prev); + next = (DECRYPTOR_ELEM *)(dec->next); + if(prev != NULL){ + prev->next = next; + }else{ + prv->decrypt.head = next; + } + if(next != NULL){ + next->prev = prev; + }else{ + prv->decrypt.tail = prev; + } + prv->decrypt.count -= 1; + + if(dec->ecm != NULL){ + dec->ecm->release(dec->ecm); + dec->ecm = NULL; + } + + if(dec->m2 != NULL){ + dec->m2->release(dec->m2); + dec->m2 = NULL; + } + + free(dec); +} + +static DECRYPTOR_ELEM *select_active_decryptor(DECRYPTOR_ELEM *a, DECRYPTOR_ELEM *b, int32_t pid) +{ + if( b != NULL ){ + return b; + } + if( pid == 0x1fff ){ + return NULL; + } + return a; +} + +static void bind_stream_decryptor(ARIB_STD_B25_PRIVATE_DATA *prv, int32_t pid, DECRYPTOR_ELEM *dec) +{ + DECRYPTOR_ELEM *old; + + old = (DECRYPTOR_ELEM *)(prv->map[pid].target); + if(old == dec){ + /* already binded - do nothing */ + return; + } + + if(old != NULL){ + old->ref -= 1; + if(old->ref == 0){ + remove_decryptor(prv, old); + } + prv->map[pid].target = NULL; + } + + if(dec != NULL){ + prv->map[pid].target = dec; + dec->ref += 1; + } +} + +static void unlock_all_decryptor(ARIB_STD_B25_PRIVATE_DATA *prv) +{ + DECRYPTOR_ELEM *e; + + e = prv->decrypt.head; + while(e != NULL){ + e->locked = 0; + e = (DECRYPTOR_ELEM *)(e->next); + } +} + +static TS_STREAM_ELEM *get_stream_list_head(TS_STREAM_LIST *list) +{ + TS_STREAM_ELEM *r; + + r = list->head; + if(r == NULL){ + return NULL; + } + + list->head = (TS_STREAM_ELEM *)(r->next); + if(list->head == NULL){ + list->tail = NULL; + list->count = 0; + }else{ + list->head->prev = NULL; + list->count -= 1; + } + + r->prev = NULL; + r->next = NULL; + + return r; +} + +static TS_STREAM_ELEM *find_stream_list_elem(TS_STREAM_LIST *list, int32_t pid) +{ + TS_STREAM_ELEM *r; + + r = list->head; + while(r != NULL){ + if(r->pid == pid){ + break; + } + r = (TS_STREAM_ELEM *)(r->next); + } + + return r; +} + +static TS_STREAM_ELEM *create_stream_elem(int32_t pid, int32_t type) +{ + TS_STREAM_ELEM *r; + + r = (TS_STREAM_ELEM *)calloc(1, sizeof(TS_STREAM_ELEM)); + if(r == NULL){ + return NULL; + } + + r->pid = pid; + r->type = type; + + return r; +} + +static void put_stream_list_tail(TS_STREAM_LIST *list, TS_STREAM_ELEM *elem) +{ + if(list->tail != NULL){ + elem->prev = list->tail; + elem->next = NULL; + list->tail->next = elem; + list->tail = elem; + list->count += 1; + }else{ + elem->prev = NULL; + elem->next = NULL; + list->head = elem; + list->tail = elem; + list->count = 1; + } +} + +static void clear_stream_list(TS_STREAM_LIST *list) +{ + TS_STREAM_ELEM *p,*n; + + p = list->head; + while(p != NULL){ + n = (TS_STREAM_ELEM *)(p->next); + free(p); + p = n; + } + + list->head = NULL; + list->tail = NULL; + list->count = 0; +} + +static int reserve_work_buffer(TS_WORK_BUFFER *buf, int32_t size) +{ + int m,n; + uint8_t *p; + + if(buf->max >= size){ + return 1; + } + + if(buf->max < 512){ + n = 512; + }else{ + n = buf->max * 2; + } + + while(n < size){ + n += n; + } + + p = (uint8_t *)malloc(n); + if(p == NULL){ + return 0; + } + + m = 0; + if(buf->pool != NULL){ + m = buf->tail - buf->head; + if(m > 0){ + memcpy(p, buf->head, m); + } + free(buf->pool); + buf->pool = NULL; + } + + buf->pool = p; + buf->head = p; + buf->tail = p+m; + buf->max = n; + + return 1; +} + +static int append_work_buffer(TS_WORK_BUFFER *buf, uint8_t *data, int32_t size) +{ + int m; + + if(size < 1){ + /* ignore - do nothing */ + return 1; + } + + m = buf->tail - buf->pool; + + if( (m+size) > buf->max ){ + if(!reserve_work_buffer(buf, m+size)){ + return 0; + } + } + + memcpy(buf->tail, data, size); + buf->tail += size; + + return 1; +} + +static void reset_work_buffer(TS_WORK_BUFFER *buf) +{ + buf->head = buf->pool; + buf->tail = buf->pool; +} + +static void release_work_buffer(TS_WORK_BUFFER *buf) +{ + if(buf->pool != NULL){ + free(buf->pool); + } + buf->pool = NULL; + buf->head = NULL; + buf->tail = NULL; + buf->max = 0; +} + +static void extract_ts_header(TS_HEADER *dst, uint8_t *src) +{ + dst->sync = src[0]; + dst->transport_error_indicator = (src[1] >> 7) & 0x01; + dst->payload_unit_start_indicator = (src[1] >> 6) & 0x01; + dst->transport_priority = (src[1] >> 5) & 0x01; + dst->pid = ((src[1] & 0x1f) << 8) | src[2]; + dst->transport_scrambling_control = (src[3] >> 6) & 0x03; + dst->adaptation_field_control = (src[3] >> 4) & 0x03; + dst->continuity_counter = src[3] & 0x0f; +} + +static void extract_emm_fixed_part(EMM_FIXED_PART *dst, uint8_t *src) +{ + int i; + + dst->card_id = 0; + for(i=0;i<6;i++){ + dst->card_id = (dst->card_id << 8) | src[i]; + } + + dst->associated_information_length = src[ 6]; + dst->protocol_number = src[ 7]; + dst->broadcaster_group_id = src[ 8]; + dst->update_number = (src[ 9]<<8)|src[10]; + dst->expiration_date = (src[11]<<8)|src[12]; +} + +static uint8_t *resync(uint8_t *head, uint8_t *tail, int32_t unit_size) +{ + int i; + unsigned char *buf; + + buf = head; + tail -= unit_size * 8; + while( buf <= tail ){ + if(buf[0] == 0x47){ + for(i=1;i<8;i++){ + if(buf[unit_size*i] != 0x47){ + break; + } + } + if(i == 8){ + return buf; + } + } + buf += 1; + } + + return NULL; +} + +static uint8_t *resync_force(uint8_t *head, uint8_t *tail, int32_t unit_size) +{ + int i,n; + unsigned char *buf; + + buf = head; + while( buf <= (tail-188) ){ + if(buf[0] == 0x47){ + n = (tail - buf) / unit_size; + if(n == 0){ + return buf; + } + for(i=1;i +#include + +#include + +#if defined(WIN32) + #include +#endif +#include + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + inner structures + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +typedef struct { + + SCARDCONTEXT mng; + SCARDHANDLE card; + + uint8_t *pool; + char *reader; + + uint8_t *sbuf; + uint8_t *rbuf; + + B_CAS_INIT_STATUS stat; + + B_CAS_ID id; + int32_t id_max; + + B_CAS_PWR_ON_CTRL_INFO pwc; + int32_t pwc_max; + +} B_CAS_CARD_PRIVATE_DATA; + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + constant values + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +static const uint8_t INITIAL_SETTING_CONDITIONS_CMD[] = { + 0x90, 0x30, 0x00, 0x00, 0x00, +}; + +static const uint8_t CARD_ID_INFORMATION_ACQUIRE_CMD[] = { + 0x90, 0x32, 0x00, 0x00, 0x00, +}; + +static const uint8_t POWER_ON_CONTROL_INFORMATION_REQUEST_CMD[] = { + 0x90, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, +}; + +static const uint8_t ECM_RECEIVE_CMD_HEADER[] = { + 0x90, 0x34, 0x00, 0x00, +}; + +static const uint8_t EMM_RECEIVE_CMD_HEADER[] = { + 0x90, 0x36, 0x00, 0x00, +}; + +#define B_CAS_BUFFER_MAX (4*1024) + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function prottypes (interface method) + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +static void release_b_cas_card(void *bcas); +static int init_b_cas_card(void *bcas); +static int get_init_status_b_cas_card(void *bcas, B_CAS_INIT_STATUS *stat); +static int get_id_b_cas_card(void *bcas, B_CAS_ID *dst); +static int get_pwr_on_ctrl_b_cas_card(void *bcas, B_CAS_PWR_ON_CTRL_INFO *dst); +static int proc_ecm_b_cas_card(void *bcas, B_CAS_ECM_RESULT *dst, uint8_t *src, int len); +static int proc_emm_b_cas_card(void *bcas, uint8_t *src, int len); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + global function implementation + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +B_CAS_CARD *create_b_cas_card() +{ + int n; + + B_CAS_CARD *r; + B_CAS_CARD_PRIVATE_DATA *prv; + + n = sizeof(B_CAS_CARD) + sizeof(B_CAS_CARD_PRIVATE_DATA); + prv = (B_CAS_CARD_PRIVATE_DATA *)calloc(1, n); + if(prv == NULL){ + return NULL; + } + + r = (B_CAS_CARD *)(prv+1); + + r->private_data = prv; + + r->release = release_b_cas_card; + r->init = init_b_cas_card; + r->get_init_status = get_init_status_b_cas_card; + r->get_id = get_id_b_cas_card; + r->get_pwr_on_ctrl = get_pwr_on_ctrl_b_cas_card; + r->proc_ecm = proc_ecm_b_cas_card; + r->proc_emm = proc_emm_b_cas_card; + + return r; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function prottypes (private method) + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +static B_CAS_CARD_PRIVATE_DATA *private_data(void *bcas); +static void teardown(B_CAS_CARD_PRIVATE_DATA *prv); +static int change_id_max(B_CAS_CARD_PRIVATE_DATA *prv, int max); +static int change_pwc_max(B_CAS_CARD_PRIVATE_DATA *prv, int max); +static int connect_card(B_CAS_CARD_PRIVATE_DATA *prv, const char *reader_name); +static void extract_power_on_ctrl_response(B_CAS_PWR_ON_CTRL *dst, uint8_t *src); +static void extract_mjd(int *yy, int *mm, int *dd, int mjd); +static int setup_ecm_receive_command(uint8_t *dst, uint8_t *src, int len); +static int setup_emm_receive_command(uint8_t *dst, uint8_t *src, int len); +static int32_t load_be_uint16(uint8_t *p); +static int64_t load_be_uint48(uint8_t *p); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + interface method implementation + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +static void release_b_cas_card(void *bcas) +{ + B_CAS_CARD_PRIVATE_DATA *prv; + + prv = private_data(bcas); + if(prv == NULL){ + /* do nothing */ + return; + } + + teardown(prv); + free(prv); +} + +static int init_b_cas_card(void *bcas) +{ + int m; + LONG ret; + DWORD len; + + B_CAS_CARD_PRIVATE_DATA *prv; + + prv = private_data(bcas); + if(prv == NULL){ + return B_CAS_CARD_ERROR_INVALID_PARAMETER; + } + + teardown(prv); + + ret = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &(prv->mng)); + if(ret != SCARD_S_SUCCESS){ + return B_CAS_CARD_ERROR_NO_SMART_CARD_READER; + } + + ret = SCardListReaders(prv->mng, NULL, NULL, &len); + if(ret != SCARD_S_SUCCESS){ + return B_CAS_CARD_ERROR_NO_SMART_CARD_READER; + } + len += 256; + + m = len + (2*B_CAS_BUFFER_MAX) + (sizeof(int64_t)*16) + (sizeof(B_CAS_PWR_ON_CTRL)*16); + prv->pool = (uint8_t *)malloc(m); + if(prv->pool == NULL){ + return B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY; + } + + prv->reader = (char *)(prv->pool); + prv->sbuf = prv->pool + len; + prv->rbuf = prv->sbuf + B_CAS_BUFFER_MAX; + prv->id.data = (int64_t *)(prv->rbuf + B_CAS_BUFFER_MAX); + prv->id_max = 16; + prv->pwc.data = (B_CAS_PWR_ON_CTRL *)(prv->id.data + prv->id_max); + prv->pwc_max = 16; + + ret = SCardListReaders(prv->mng, NULL, prv->reader, &len); + if(ret != SCARD_S_SUCCESS){ + return B_CAS_CARD_ERROR_NO_SMART_CARD_READER; + } + + while( prv->reader[0] != 0 ){ + if(connect_card(prv, prv->reader)){ + break; + } + prv->reader += (strlen(prv->reader) + 1); + } + + if(prv->card == 0){ + return B_CAS_CARD_ERROR_ALL_READERS_CONNECTION_FAILED; + } + + return 0; +} + +static int get_init_status_b_cas_card(void *bcas, B_CAS_INIT_STATUS *stat) +{ + B_CAS_CARD_PRIVATE_DATA *prv; + + prv = private_data(bcas); + if( (prv == NULL) || (stat == NULL) ){ + return B_CAS_CARD_ERROR_INVALID_PARAMETER; + } + + if(prv->card == 0){ + return B_CAS_CARD_ERROR_NOT_INITIALIZED; + } + + memcpy(stat, &(prv->stat), sizeof(B_CAS_INIT_STATUS)); + + return 0; +} + +static int get_id_b_cas_card(void *bcas, B_CAS_ID *dst) +{ + LONG ret; + + DWORD slen; + DWORD rlen; + + int i,num; + + uint8_t *p; + uint8_t *tail; + + B_CAS_CARD_PRIVATE_DATA *prv; + SCARD_IO_REQUEST sir; + + prv = private_data(bcas); + if( (prv == NULL) || (dst == NULL) ){ + return B_CAS_CARD_ERROR_INVALID_PARAMETER; + } + + if(prv->card == 0){ + return B_CAS_CARD_ERROR_NOT_INITIALIZED; + } + + slen = sizeof(CARD_ID_INFORMATION_ACQUIRE_CMD); + memcpy(prv->sbuf, CARD_ID_INFORMATION_ACQUIRE_CMD, slen); + memcpy(&sir, SCARD_PCI_T1, sizeof(sir)); + rlen = B_CAS_BUFFER_MAX; + + ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen); + if( (ret != SCARD_S_SUCCESS) || (rlen < 19) ){ + return B_CAS_CARD_ERROR_TRANSMIT_FAILED; + } + + p = prv->rbuf + 6; + tail = prv->rbuf + rlen; + if( p+1 > tail ){ + return B_CAS_CARD_ERROR_TRANSMIT_FAILED; + } + + num = p[0]; + if(num > prv->id_max){ + if(change_id_max(prv, num+4) < 0){ + return B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY; + } + } + + p += 1; + for(i=0;i tail ){ + return B_CAS_CARD_ERROR_TRANSMIT_FAILED; + } + + { + int maker_id; + int version; + int check_code; + + maker_id = p[0]; + version = p[1]; + prv->id.data[i] = load_be_uint48(p+2); + check_code = load_be_uint16(p+8); + } + + p += 10; + } + + prv->id.count = num; + + memcpy(dst, &(prv->id), sizeof(B_CAS_ID)); + + return 0; +} + +static int get_pwr_on_ctrl_b_cas_card(void *bcas, B_CAS_PWR_ON_CTRL_INFO *dst) +{ + LONG ret; + + DWORD slen; + DWORD rlen; + + int i,num,code; + + B_CAS_CARD_PRIVATE_DATA *prv; + SCARD_IO_REQUEST sir; + + memset(dst, 0, sizeof(B_CAS_PWR_ON_CTRL_INFO)); + + prv = private_data(bcas); + if( (prv == NULL) || (dst == NULL) ){ + return B_CAS_CARD_ERROR_INVALID_PARAMETER; + } + + if(prv->card == 0){ + return B_CAS_CARD_ERROR_NOT_INITIALIZED; + } + + slen = sizeof(POWER_ON_CONTROL_INFORMATION_REQUEST_CMD); + memcpy(prv->sbuf, POWER_ON_CONTROL_INFORMATION_REQUEST_CMD, slen); + prv->sbuf[5] = 0; + memcpy(&sir, SCARD_PCI_T1, sizeof(sir)); + rlen = B_CAS_BUFFER_MAX; + + ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen); + if( (ret != SCARD_S_SUCCESS) || (rlen < 18) || (prv->rbuf[6] != 0) ){ + return B_CAS_CARD_ERROR_TRANSMIT_FAILED; + } + + code = load_be_uint16(prv->rbuf+4); + if(code == 0xa101){ + /* no data */ + return 0; + }else if(code != 0x2100){ + return B_CAS_CARD_ERROR_TRANSMIT_FAILED; + } + + num = (prv->rbuf[7] + 1); + if(prv->pwc_max < num){ + if(change_pwc_max(prv, num+4) < 0){ + return B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY; + } + } + + extract_power_on_ctrl_response(prv->pwc.data+0, prv->rbuf); + + for(i=1;isbuf[5] = i; + rlen = B_CAS_BUFFER_MAX; + + ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen); + if( (ret != SCARD_S_SUCCESS) || (rlen < 18) || (prv->rbuf[6] != i) ){ + return B_CAS_CARD_ERROR_TRANSMIT_FAILED; + } + + extract_power_on_ctrl_response(prv->pwc.data+i, prv->rbuf); + } + + prv->pwc.count = num; + + memcpy(dst, &(prv->pwc), sizeof(B_CAS_PWR_ON_CTRL_INFO)); + + return 0; +} + +static int proc_ecm_b_cas_card(void *bcas, B_CAS_ECM_RESULT *dst, uint8_t *src, int len) +{ + int retry_count; + + LONG ret; + DWORD slen; + DWORD rlen; + + B_CAS_CARD_PRIVATE_DATA *prv; + + SCARD_IO_REQUEST sir; + + prv = private_data(bcas); + if( (prv == NULL) || + (dst == NULL) || + (src == NULL) || + (len < 1) ){ + return B_CAS_CARD_ERROR_INVALID_PARAMETER; + } + + if(prv->card == 0){ + return B_CAS_CARD_ERROR_NOT_INITIALIZED; + } + + slen = setup_ecm_receive_command(prv->sbuf, src, len); + memcpy(&sir, SCARD_PCI_T1, sizeof(sir)); + rlen = B_CAS_BUFFER_MAX; + + retry_count = 0; + ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen); + while( ((ret != SCARD_S_SUCCESS) || (rlen < 25)) && (retry_count < 10) ){ + retry_count += 1; + if(!connect_card(prv, prv->reader)){ + continue; + } + slen = setup_ecm_receive_command(prv->sbuf, src, len); + memcpy(&sir, SCARD_PCI_T1, sizeof(sir)); + rlen = B_CAS_BUFFER_MAX; + + ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen); + } + + if( (ret != SCARD_S_SUCCESS) || (rlen < 25) ){ + return B_CAS_CARD_ERROR_TRANSMIT_FAILED; + } + + memcpy(dst->scramble_key, prv->rbuf+6, 16); + dst->return_code = load_be_uint16(prv->rbuf+4); + + return 0; +} + +static int proc_emm_b_cas_card(void *bcas, uint8_t *src, int len) +{ + int retry_count; + + LONG ret; + DWORD slen; + DWORD rlen; + + B_CAS_CARD_PRIVATE_DATA *prv; + + SCARD_IO_REQUEST sir; + + prv = private_data(bcas); + if( (prv == NULL) || + (src == NULL) || + (len < 1) ){ + return B_CAS_CARD_ERROR_INVALID_PARAMETER; + } + + if(prv->card == 0){ + return B_CAS_CARD_ERROR_NOT_INITIALIZED; + } + + slen = setup_emm_receive_command(prv->sbuf, src, len); + memcpy(&sir, SCARD_PCI_T1, sizeof(sir)); + rlen = B_CAS_BUFFER_MAX; + + retry_count = 0; + ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen); + while( ((ret != SCARD_S_SUCCESS) || (rlen < 6)) && (retry_count < 2) ){ + retry_count += 1; + if(!connect_card(prv, prv->reader)){ + continue; + } + slen = setup_emm_receive_command(prv->sbuf, src, len); + memcpy(&sir, SCARD_PCI_T1, sizeof(sir)); + rlen = B_CAS_BUFFER_MAX; + + ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen); + } + + if( (ret != SCARD_S_SUCCESS) || (rlen < 6) ){ + return B_CAS_CARD_ERROR_TRANSMIT_FAILED; + } + + return 0; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + private method implementation + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +static B_CAS_CARD_PRIVATE_DATA *private_data(void *bcas) +{ + B_CAS_CARD_PRIVATE_DATA *r; + B_CAS_CARD *p; + + p = (B_CAS_CARD *)bcas; + if(p == NULL){ + return NULL; + } + + r = (B_CAS_CARD_PRIVATE_DATA *)(p->private_data); + if( ((void *)(r+1)) != ((void *)p) ){ + return NULL; + } + + return r; +} + +static void teardown(B_CAS_CARD_PRIVATE_DATA *prv) +{ + if(prv->card != 0){ + SCardDisconnect(prv->card, SCARD_LEAVE_CARD); + prv->card = 0; + } + + if(prv->mng != 0){ + SCardReleaseContext(prv->mng); + prv->mng = 0; + } + + if(prv->pool != NULL){ + free(prv->pool); + prv->pool = NULL; + } + + prv->reader = NULL; + prv->sbuf = NULL; + prv->rbuf = NULL; + prv->id.data = NULL; + prv->id_max = 0; +} + +static int change_id_max(B_CAS_CARD_PRIVATE_DATA *prv, int max) +{ + int m; + int reader_size; + int pwctrl_size; + + uint8_t *p; + uint8_t *old_reader; + uint8_t *old_pwctrl; + + reader_size = prv->sbuf - prv->pool; + pwctrl_size = prv->pwc.count * sizeof(B_CAS_PWR_ON_CTRL); + + m = reader_size; + m += (2*B_CAS_BUFFER_MAX); + m += (max*sizeof(int64_t)); + m += (prv->pwc_max*sizeof(B_CAS_PWR_ON_CTRL)); + p = (uint8_t *)malloc(m); + if(p == NULL){ + return B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY; + } + + old_reader = (uint8_t *)(prv->reader); + old_pwctrl = (uint8_t *)(prv->pwc.data); + + prv->reader = (char *)p; + prv->sbuf = prv->pool + reader_size; + prv->rbuf = prv->sbuf + B_CAS_BUFFER_MAX; + prv->id.data = (int64_t *)(prv->rbuf + B_CAS_BUFFER_MAX); + prv->id_max = max; + prv->pwc.data = (B_CAS_PWR_ON_CTRL *)(prv->id.data + prv->id_max); + + memcpy(prv->reader, old_reader, reader_size); + memcpy(prv->pwc.data, old_pwctrl, pwctrl_size); + + free(prv->pool); + prv->pool = p; + + return 0; +} + +static int change_pwc_max(B_CAS_CARD_PRIVATE_DATA *prv, int max) +{ + int m; + int reader_size; + int cardid_size; + + uint8_t *p; + uint8_t *old_reader; + uint8_t *old_cardid; + + reader_size = prv->sbuf - prv->pool; + cardid_size = prv->id.count * sizeof(int64_t); + + m = reader_size; + m += (2*B_CAS_BUFFER_MAX); + m += (prv->id_max*sizeof(int64_t)); + m += (max*sizeof(B_CAS_PWR_ON_CTRL)); + p = (uint8_t *)malloc(m); + if(p == NULL){ + return B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY; + } + + old_reader = (uint8_t *)(prv->reader); + old_cardid = (uint8_t *)(prv->id.data); + + prv->reader = (char *)p; + prv->sbuf = prv->pool + reader_size; + prv->rbuf = prv->sbuf + B_CAS_BUFFER_MAX; + prv->id.data = (int64_t *)(prv->rbuf + B_CAS_BUFFER_MAX); + prv->pwc.data = (B_CAS_PWR_ON_CTRL *)(prv->id.data + prv->id_max); + prv->pwc_max = max; + + memcpy(prv->reader, old_reader, reader_size); + memcpy(prv->id.data, old_cardid, cardid_size); + + free(prv->pool); + prv->pool = p; + + return 0; +} + +static int connect_card(B_CAS_CARD_PRIVATE_DATA *prv, const char *reader_name) +{ + int m,n; + + LONG ret; + DWORD rlen,protocol; + + uint8_t *p; + + SCARD_IO_REQUEST sir; + + if(prv->card != 0){ + SCardDisconnect(prv->card, SCARD_RESET_CARD); + prv->card = 0; + } + + ret = SCardConnect(prv->mng, reader_name, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &(prv->card), &protocol); + if(ret != SCARD_S_SUCCESS){ + return 0; + } + + m = sizeof(INITIAL_SETTING_CONDITIONS_CMD); + memcpy(prv->sbuf, INITIAL_SETTING_CONDITIONS_CMD, m); + memcpy(&sir, SCARD_PCI_T1, sizeof(sir)); + rlen = B_CAS_BUFFER_MAX; + ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, m, &sir, prv->rbuf, &rlen); + if(ret != SCARD_S_SUCCESS){ + return 0; + } + + if(rlen < 57){ + return 0; + } + + p = prv->rbuf; + + n = load_be_uint16(p+4); + if(n != 0x2100){ // return code missmatch + return 0; + } + + memcpy(prv->stat.system_key, p+16, 32); + memcpy(prv->stat.init_cbc, p+48, 8); + prv->stat.bcas_card_id = load_be_uint48(p+8); + prv->stat.card_status = load_be_uint16(p+2); + prv->stat.ca_system_id = load_be_uint16(p+6); + + return 1; +} + +static void extract_power_on_ctrl_response(B_CAS_PWR_ON_CTRL *dst, uint8_t *src) +{ + int referrence; + int start; + int limit; + + + dst->broadcaster_group_id = src[8]; + referrence = (src[9]<<8)|src[10]; + start = referrence - src[11]; + limit = start + (src[12]-1); + + extract_mjd(&(dst->s_yy), &(dst->s_mm), &(dst->s_dd), start); + extract_mjd(&(dst->l_yy), &(dst->l_mm), &(dst->l_dd), limit); + + dst->hold_time = src[13]; + dst->network_id = (src[14]<<8)|src[15]; + dst->transport_id = (src[16]<<8)|src[17]; + +} + +static void extract_mjd(int *yy, int *mm, int *dd, int mjd) +{ + int a1,m1; + int a2,m2; + int a3,m3; + int a4,m4; + int mw; + int dw; + int yw; + + mjd -= 51604; // 2000,3/1 + if(mjd < 0){ + mjd += 0x10000; + } + + a1 = mjd / 146097; + m1 = mjd % 146097; + a2 = m1 / 36524; + m2 = m1 - (a2 * 36524); + a3 = m2 / 1461; + m3 = m2 - (a3 * 1461); + a4 = m3 / 365; + if(a4 > 3){ + a4 = 3; + } + m4 = m3 - (a4 * 365); + + mw = (1071*m4+450) >> 15; + dw = m4 - ((979*mw+16) >> 5); + + yw = a1*400 + a2*100 + a3*4 + a4 + 2000; + mw += 3; + if(mw > 12){ + mw -= 12; + yw += 1; + } + dw += 1; + + *yy = yw; + *mm = mw; + *dd = dw; +} + +static int setup_ecm_receive_command(uint8_t *dst, uint8_t *src, int len) +{ + int r; + + r = sizeof(ECM_RECEIVE_CMD_HEADER); + memcpy(dst+0, ECM_RECEIVE_CMD_HEADER, r); + dst[r] = (uint8_t)(len & 0xff); + r += 1; + memcpy(dst+r, src, len); + r += len; + dst[r] = 0; + r += 1; + + return r; +} + +static int setup_emm_receive_command(uint8_t *dst, uint8_t *src, int len) +{ + int r; + + r = sizeof(EMM_RECEIVE_CMD_HEADER); + memcpy(dst+0, EMM_RECEIVE_CMD_HEADER, r); + dst[r] = (uint8_t)(len & 0xff); + r += 1; + memcpy(dst+r, src, len); + r += len; + dst[r] = 0; + r += 1; + + return r; +} + +static int32_t load_be_uint16(uint8_t *p) +{ + return ((p[0]<<8)|p[1]); +} + +static int64_t load_be_uint48(uint8_t *p) +{ + int i; + int64_t r; + + r = p[0]; + for(i=1;i<6;i++){ + r <<= 8; + r |= p[i]; + } + + return r; +} + diff -r db7af62da709 -r 41a5481db56f arib25/src/b_cas_card.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arib25/src/b_cas_card.h Sun Sep 13 02:11:33 2009 +0900 @@ -0,0 +1,75 @@ +#ifndef B_CAS_CARD_H +#define B_CAS_CARD_H + +#include "portable.h" + +typedef struct { + uint8_t system_key[32]; + uint8_t init_cbc[8]; + int64_t bcas_card_id; + int32_t card_status; + int32_t ca_system_id; +} B_CAS_INIT_STATUS; + +typedef struct { + int64_t *data; + int32_t count; +} B_CAS_ID; + +typedef struct { + + int32_t s_yy; /* start date : year */ + int32_t s_mm; /* start date : month */ + int32_t s_dd; /* start date : day */ + + int32_t l_yy; /* limit date : year */ + int32_t l_mm; /* limit date : month */ + int32_t l_dd; /* limit date : day */ + + int32_t hold_time; /* in hour unit */ + + int32_t broadcaster_group_id; + + int32_t network_id; + int32_t transport_id; + +} B_CAS_PWR_ON_CTRL; + +typedef struct { + B_CAS_PWR_ON_CTRL *data; + int32_t count; +} B_CAS_PWR_ON_CTRL_INFO; + +typedef struct { + uint8_t scramble_key[16]; + uint32_t return_code; +} B_CAS_ECM_RESULT; + +typedef struct { + + void *private_data; + + void (* release)(void *bcas); + + int (* init)(void *bcas); + + int (* get_init_status)(void *bcas, B_CAS_INIT_STATUS *stat); + int (* get_id)(void *bcas, B_CAS_ID *dst); + int (* get_pwr_on_ctrl)(void *bcas, B_CAS_PWR_ON_CTRL_INFO *dst); + + int (* proc_ecm)(void *bcas, B_CAS_ECM_RESULT *dst, uint8_t *src, int len); + int (* proc_emm)(void *bcas, uint8_t *src, int len); + +} B_CAS_CARD; + +#ifdef __cplusplus +extern "C" { +#endif + +extern B_CAS_CARD *create_b_cas_card(); + +#ifdef __cplusplus +} +#endif + +#endif /* B_CAS_CARD_H */ diff -r db7af62da709 -r 41a5481db56f arib25/src/b_cas_card_error_code.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arib25/src/b_cas_card_error_code.h Sun Sep 13 02:11:33 2009 +0900 @@ -0,0 +1,11 @@ +#ifndef B_CAS_CARD_ERROR_CODE_H +#define B_CAS_CARD_ERROR_CODE_H + +#define B_CAS_CARD_ERROR_INVALID_PARAMETER -1 +#define B_CAS_CARD_ERROR_NOT_INITIALIZED -2 +#define B_CAS_CARD_ERROR_NO_SMART_CARD_READER -3 +#define B_CAS_CARD_ERROR_ALL_READERS_CONNECTION_FAILED -4 +#define B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY -5 +#define B_CAS_CARD_ERROR_TRANSMIT_FAILED -6 + +#endif /* B_CAS_CARD_ERROR_CODE_H */ diff -r db7af62da709 -r 41a5481db56f arib25/src/makefile.win --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arib25/src/makefile.win Sun Sep 13 02:11:33 2009 +0900 @@ -0,0 +1,33 @@ +CC = cl +CFLAG = /c /MT /W4 /O2 +LINK = link +LFLAG = /nologo +LIBS = winscard.lib + +ALL: b25.exe + +arib_std_b25.obj: arib_std_b25.c arib_std_b25.h portable.h b_cas_card.h arib_std_b25_error_code.h multi2.h ts_section_parser.h ts_common_types.h + $(CC) $(CFLAG) arib_std_b25.c + +b_cas_card.obj: b_cas_card.c b_cas_card.h portable.h b_cas_card_error_code.h + $(CC) $(CFLAG) b_cas_card.c + +multi2.obj: multi2.c multi2.h portable.h multi2_error_code.h + $(CC) $(CFLAG) multi2.c + +td.obj: td.c arib_std_b25.h portable.h b_cas_card.h + $(CC) $(CFLAG) td.c + +ts_section_parser.obj: ts_section_parser.c ts_section_parser.h ts_common_types.h portable.h ts_section_parser_error_code.h + $(CC) $(CFLAG) ts_section_parser.c + +OBJ = arib_std_b25.obj b_cas_card.obj multi2.obj td.obj ts_section_parser.obj + +b25.exe: $(OBJ) + $(LINK) $(LFLAG) $(LIBS) /OUT:b25.exe $(OBJ) + +clean: + DEL *.obj + DEL *.exe + + diff -r db7af62da709 -r 41a5481db56f arib25/src/multi2.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arib25/src/multi2.c Sun Sep 13 02:11:33 2009 +0900 @@ -0,0 +1,527 @@ +#include +#include + +#include "multi2.h" +#include "multi2_error_code.h" + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + inline functions + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +static __inline uint8_t *load_be_uint32(uint32_t *dst, uint8_t *src) +{ + *dst = ((src[0]<<24)|(src[1]<<16)|(src[2]<<8)|src[3]); + return src+4; +} + +static __inline uint8_t *save_be_uint32(uint8_t *dst, uint32_t src) +{ + dst[0] = (uint8_t)((src>>24) & 0xff); + dst[1] = (uint8_t)((src>>16) & 0xff); + dst[2] = (uint8_t)((src>> 8) & 0xff); + dst[3] = (uint8_t)( src & 0xff); + return dst+4; +} + +static __inline uint32_t left_rotate_uint32(uint32_t val, uint32_t count) +{ + return ((val << count) | (val >> (32-count))); +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + inner structures + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +typedef struct { + uint32_t key[8]; +} CORE_PARAM; + +typedef struct { + uint32_t l; + uint32_t r; +} CORE_DATA; + +typedef struct { + + int32_t ref_count; + + CORE_DATA cbc_init; + + CORE_PARAM sys; + CORE_DATA scr[2]; /* 0: odd, 1: even */ + CORE_PARAM wrk[2]; /* 0: odd, 1: even */ + + uint32_t round; + uint32_t state; + +} MULTI2_PRIVATE_DATA; + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + constant values + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +#define MULTI2_STATE_CBC_INIT_SET (0x0001) +#define MULTI2_STATE_SYSTEM_KEY_SET (0x0002) +#define MULTI2_STATE_SCRAMBLE_KEY_SET (0x0004) + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function prottypes (interface method) + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +static void release_multi2(void *m2); +static int add_ref_multi2(void *m2); +static int set_round_multi2(void *m2, int32_t val); +static int set_system_key_multi2(void *m2, uint8_t *val); +static int set_init_cbc_multi2(void *m2, uint8_t *val); +static int set_scramble_key_multi2(void *m2, uint8_t *val); +static int clear_scramble_key_multi2(void *m2); +static int encrypt_multi2(void *m2, int32_t type, uint8_t *buf, int32_t size); +static int decrypt_multi2(void *m2, int32_t type, uint8_t *buf, int32_t size); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + global function implementation + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +MULTI2 *create_multi2() +{ + int n; + + MULTI2 *r; + MULTI2_PRIVATE_DATA *prv; + + n = sizeof(MULTI2_PRIVATE_DATA); + n += sizeof(MULTI2); + + prv = (MULTI2_PRIVATE_DATA *)calloc(1, n); + if(prv == NULL){ + return NULL; + } + + r = (MULTI2 *)(prv+1); + r->private_data = prv; + + prv->ref_count = 1; + prv->round = 4; + + r->release = release_multi2; + r->add_ref = add_ref_multi2; + r->set_round = set_round_multi2; + r->set_system_key = set_system_key_multi2; + r->set_init_cbc = set_init_cbc_multi2; + r->set_scramble_key = set_scramble_key_multi2; + r->clear_scramble_key = clear_scramble_key_multi2; + r->encrypt = encrypt_multi2; + r->decrypt = decrypt_multi2; + + return r; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function prottypes (private method) + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +static MULTI2_PRIVATE_DATA *private_data(void *m2); + +static void core_schedule(CORE_PARAM *work, CORE_PARAM *skey, CORE_DATA *dkey); + +static void core_encrypt(CORE_DATA *dst, CORE_DATA *src, CORE_PARAM *w, int32_t round); +static void core_decrypt(CORE_DATA *dst, CORE_DATA *src, CORE_PARAM *w, int32_t round); + +static void core_pi1(CORE_DATA *dst, CORE_DATA *src); +static void core_pi2(CORE_DATA *dst, CORE_DATA *src, uint32_t a); +static void core_pi3(CORE_DATA *dst, CORE_DATA *src, uint32_t a, uint32_t b); +static void core_pi4(CORE_DATA *dst, CORE_DATA *src, uint32_t a); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + interface method implementation + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +static void release_multi2(void *m2) +{ + MULTI2_PRIVATE_DATA *prv; + + prv = private_data(m2); + if(prv == NULL){ + /* do nothing */ + return; + } + + prv->ref_count -= 1; + if(prv->ref_count == 0){ + free(prv); + } +} + +static int add_ref_multi2(void *m2) +{ + MULTI2_PRIVATE_DATA *prv; + + prv = private_data(m2); + if(prv == NULL){ + return MULTI2_ERROR_INVALID_PARAMETER; + } + + prv->ref_count += 1; + + return 0; +} + +static int set_round_multi2(void *m2, int32_t val) +{ + MULTI2_PRIVATE_DATA *prv; + + prv = private_data(m2); + if(prv == NULL){ + /* do nothing */ + return MULTI2_ERROR_INVALID_PARAMETER; + } + + prv->round = val; + + return 0; +} + +static int set_system_key_multi2(void *m2, uint8_t *val) +{ + int i; + uint8_t *p; + + MULTI2_PRIVATE_DATA *prv; + + prv = private_data(m2); + if( (prv == NULL) || (val == NULL) ){ + return MULTI2_ERROR_INVALID_PARAMETER; + } + + p = val; + for(i=0;i<8;i++){ + p = load_be_uint32(prv->sys.key+i, p); + } + + prv->state |= MULTI2_STATE_SYSTEM_KEY_SET; + + return 0; +} + +static int set_init_cbc_multi2(void *m2, uint8_t *val) +{ + uint8_t *p; + + MULTI2_PRIVATE_DATA *prv; + + prv = private_data(m2); + if( (prv == NULL) || (val == NULL) ){ + return MULTI2_ERROR_INVALID_PARAMETER; + } + + p = val; + + p = load_be_uint32(&(prv->cbc_init.l), p); + p = load_be_uint32(&(prv->cbc_init.r), p); + + prv->state |= MULTI2_STATE_CBC_INIT_SET; + + return 0; +} + +static int set_scramble_key_multi2(void *m2, uint8_t *val) +{ + uint8_t *p; + + MULTI2_PRIVATE_DATA *prv; + + prv = private_data(m2); + if( (prv == NULL) || (val == NULL) ){ + return MULTI2_ERROR_INVALID_PARAMETER; + } + + p = val; + + p = load_be_uint32(&(prv->scr[0].l), p); + p = load_be_uint32(&(prv->scr[0].r), p); + p = load_be_uint32(&(prv->scr[1].l), p); + p = load_be_uint32(&(prv->scr[1].r), p); + + core_schedule(prv->wrk+0, &(prv->sys), prv->scr+0); + core_schedule(prv->wrk+1, &(prv->sys), prv->scr+1); + + prv->state |= MULTI2_STATE_SCRAMBLE_KEY_SET; + + return 0; +} + +static int clear_scramble_key_multi2(void *m2) +{ + MULTI2_PRIVATE_DATA *prv; + + prv = private_data(m2); + if(prv == NULL){ + return MULTI2_ERROR_INVALID_PARAMETER; + } + + memset(prv->scr, 0, sizeof(prv->scr)); + memset(prv->wrk, 0, sizeof(prv->wrk)); + + prv->state &= (~MULTI2_STATE_SCRAMBLE_KEY_SET); + + return 0; +} + +static int encrypt_multi2(void *m2, int32_t type, uint8_t *buf, int32_t size) +{ + CORE_DATA src,dst; + CORE_PARAM *prm; + + uint8_t *p; + + MULTI2_PRIVATE_DATA *prv; + + prv = private_data(m2); + if( (prv == NULL) || (buf == NULL) || (size < 1) ){ + return MULTI2_ERROR_INVALID_PARAMETER; + } + + if(prv->state != (MULTI2_STATE_CBC_INIT_SET|MULTI2_STATE_SYSTEM_KEY_SET|MULTI2_STATE_SCRAMBLE_KEY_SET)){ + if( (prv->state & MULTI2_STATE_CBC_INIT_SET) == 0 ){ + return MULTI2_ERROR_UNSET_CBC_INIT; + } + if( (prv->state & MULTI2_STATE_SYSTEM_KEY_SET) == 0 ){ + return MULTI2_ERROR_UNSET_SYSTEM_KEY; + } + if( (prv->state & MULTI2_STATE_SCRAMBLE_KEY_SET) == 0 ){ + return MULTI2_ERROR_UNSET_SCRAMBLE_KEY; + } + } + + if(type == 0x02){ + prm = prv->wrk+1; + }else{ + prm = prv->wrk+0; + } + + dst.l = prv->cbc_init.l; + dst.r = prv->cbc_init.r; + + p = buf; + while(size >= 8){ + load_be_uint32(&(src.l), p+0); + load_be_uint32(&(src.r), p+4); + src.l = src.l ^ dst.l; + src.r = src.r ^ dst.r; + core_encrypt(&dst, &src, prm, prv->round); + p = save_be_uint32(p, dst.l); + p = save_be_uint32(p, dst.r); + size -= 8; + } + + if(size > 0){ + int i; + uint8_t tmp[8]; + + src.l = dst.l; + src.r = dst.r; + core_encrypt(&dst, &src, prm, prv->round); + save_be_uint32(tmp+0, dst.l); + save_be_uint32(tmp+4, dst.r); + + for(i=0;istate != (MULTI2_STATE_CBC_INIT_SET|MULTI2_STATE_SYSTEM_KEY_SET|MULTI2_STATE_SCRAMBLE_KEY_SET)){ + if( (prv->state & MULTI2_STATE_CBC_INIT_SET) == 0 ){ + return MULTI2_ERROR_UNSET_CBC_INIT; + } + if( (prv->state & MULTI2_STATE_SYSTEM_KEY_SET) == 0 ){ + return MULTI2_ERROR_UNSET_SYSTEM_KEY; + } + if( (prv->state & MULTI2_STATE_SCRAMBLE_KEY_SET) == 0 ){ + return MULTI2_ERROR_UNSET_SCRAMBLE_KEY; + } + } + + if(type == 0x02){ + prm = prv->wrk+1; + }else{ + prm = prv->wrk+0; + } + + cbc.l = prv->cbc_init.l; + cbc.r = prv->cbc_init.r; + + p = buf; + while(size >= 8){ + load_be_uint32(&(src.l), p+0); + load_be_uint32(&(src.r), p+4); + core_decrypt(&dst, &src, prm, prv->round); + dst.l = dst.l ^ cbc.l; + dst.r = dst.r ^ cbc.r; + cbc.l = src.l; + cbc.r = src.r; + p = save_be_uint32(p, dst.l); + p = save_be_uint32(p, dst.r); + size -= 8; + } + + if(size > 0){ + int i; + uint8_t tmp[8]; + + core_encrypt(&dst, &cbc, prm, prv->round); + save_be_uint32(tmp+0, dst.l); + save_be_uint32(tmp+4, dst.r); + + for(i=0;iprivate_data); + if( ((void *)(r+1)) != ((void *)p) ){ + return NULL; + } + + return r; +} + +static void core_schedule(CORE_PARAM *work, CORE_PARAM *skey, CORE_DATA *dkey) +{ + CORE_DATA b1,b2,b3,b4,b5,b6,b7,b8,b9; + + core_pi1(&b1, dkey); + + core_pi2(&b2, &b1, skey->key[0]); + work->key[0] = b2.l; + + core_pi3(&b3, &b2, skey->key[1], skey->key[2]); + work->key[1] = b3.r; + + core_pi4(&b4, &b3, skey->key[3]); + work->key[2] = b4.l; + + core_pi1(&b5, &b4); + work->key[3] = b5.r; + + core_pi2(&b6, &b5, skey->key[4]); + work->key[4] = b6.l; + + core_pi3(&b7, &b6, skey->key[5], skey->key[6]); + work->key[5] = b7.r; + + core_pi4(&b8, &b7, skey->key[7]); + work->key[6] = b8.l; + + core_pi1(&b9, &b8); + work->key[7] = b9.r; +} + +static void core_encrypt(CORE_DATA *dst, CORE_DATA *src, CORE_PARAM *w, int32_t round) +{ + int32_t i; + + CORE_DATA tmp; + + dst->l = src->l; + dst->r = src->r; + for(i=0;ikey[0]); + core_pi3(&tmp, dst, w->key[1], w->key[2]); + core_pi4( dst, &tmp, w->key[3]); + core_pi1(&tmp, dst); + core_pi2( dst, &tmp, w->key[4]); + core_pi3(&tmp, dst, w->key[5], w->key[6]); + core_pi4( dst, &tmp, w->key[7]); + } +} + +static void core_decrypt(CORE_DATA *dst, CORE_DATA *src, CORE_PARAM *w, int32_t round) +{ + int32_t i; + + CORE_DATA tmp; + + dst->l = src->l; + dst->r = src->r; + for(i=0;ikey[7]); + core_pi3( dst, &tmp, w->key[5], w->key[6]); + core_pi2(&tmp, dst, w->key[4]); + core_pi1( dst, &tmp); + core_pi4(&tmp, dst, w->key[3]); + core_pi3( dst, &tmp, w->key[1], w->key[2]); + core_pi2(&tmp, dst, w->key[0]); + core_pi1( dst, &tmp); + } +} + +static void core_pi1(CORE_DATA *dst, CORE_DATA *src) +{ + dst->l = src->l; + dst->r = src->r ^ src->l; +} + +static void core_pi2(CORE_DATA *dst, CORE_DATA *src, uint32_t a) +{ + uint32_t t0,t1,t2; + + t0 = src->r + a; + t1 = left_rotate_uint32(t0, 1) + t0 - 1; + t2 = left_rotate_uint32(t1, 4) ^ t1; + + dst->l = src->l ^ t2; + dst->r = src->r; +} + +static void core_pi3(CORE_DATA *dst, CORE_DATA *src, uint32_t a, uint32_t b) +{ + uint32_t t0,t1,t2,t3,t4,t5; + + t0 = src->l + a; + t1 = left_rotate_uint32(t0, 2) + t0 + 1; + t2 = left_rotate_uint32(t1, 8) ^ t1; + t3 = t2 + b; + t4 = left_rotate_uint32(t3, 1) - t3; + t5 = left_rotate_uint32(t4, 16) ^ (t4 | src->l); + + dst->l = src->l; + dst->r = src->r ^ t5; +} + +static void core_pi4(CORE_DATA *dst, CORE_DATA *src, uint32_t a) +{ + uint32_t t0,t1; + + t0 = src->r + a; + t1 = left_rotate_uint32(t0, 2) + t0 + 1; + + dst->l = src->l ^ t1; + dst->r = src->r; +} diff -r db7af62da709 -r 41a5481db56f arib25/src/multi2.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arib25/src/multi2.h Sun Sep 13 02:11:33 2009 +0900 @@ -0,0 +1,35 @@ +#ifndef MULTI2_H +#define MULTI2_H + +#include "portable.h" + +typedef struct { + + void *private_data; + + void (* release)(void *m2); + int (* add_ref)(void *m2); + + int (* set_round)(void *m2, int32_t val); + + int (* set_system_key)(void *m2, uint8_t *val); + int (* set_init_cbc)(void *m2, uint8_t *val); + int (* set_scramble_key)(void *m2, uint8_t *val); + int (* clear_scramble_key)(void *m2); + + int (* encrypt)(void *m2, int32_t type, uint8_t *buf, int32_t size); + int (* decrypt)(void *m2, int32_t type, uint8_t *buf, int32_t size); + +} MULTI2; + +#ifdef __cplusplus +extern "C" { +#endif + +extern MULTI2 *create_multi2(); + +#ifdef __cplusplus +} +#endif + +#endif /* MULTI2_H */ diff -r db7af62da709 -r 41a5481db56f arib25/src/multi2_error_code.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arib25/src/multi2_error_code.h Sun Sep 13 02:11:33 2009 +0900 @@ -0,0 +1,9 @@ +#ifndef MULTI2_ERROR_CODE_H +#define MULTI2_ERROR_CODE_H + +#define MULTI2_ERROR_INVALID_PARAMETER -1 +#define MULTI2_ERROR_UNSET_SYSTEM_KEY -2 +#define MULTI2_ERROR_UNSET_CBC_INIT -3 +#define MULTI2_ERROR_UNSET_SCRAMBLE_KEY -4 + +#endif /* MULTI2_ERROR_CODE_H */ diff -r db7af62da709 -r 41a5481db56f arib25/src/portable.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arib25/src/portable.h Sun Sep 13 02:11:33 2009 +0900 @@ -0,0 +1,38 @@ +#ifndef PORTABLE_H +#define PORTABLE_H + +#if (defined(WIN32) && MSC_VER < 1300) + +typedef unsigned char uint8_t; +typedef signed char int8_t; +typedef unsigned short uint16_t; +typedef signed short int16_t; +typedef unsigned int uint32_t; +typedef signed int int32_t; +typedef unsigned __int64 uint64_t; +typedef signed __int64 int64_t; + +#else + +#include + +#endif + +#if !defined(WIN32) + #define _open open + #define _close close + #define _read read + #define _write write + #define _lseeki64 lseek + #define _telli64(fd) (lseek(fd,0,SEEK_CUR)) + #define _O_BINARY (0) + #define _O_RDONLY (O_RDONLY) + #define _O_WRONLY (O_WRONLY) + #define _O_SEQUENTIAL (0) + #define _O_CREAT (O_CREAT) + #define _O_TRUNC (O_TRUNC) + #define _S_IREAD (S_IRUSR|S_IRGRP|S_IROTH) + #define _S_IWRITE (S_IWUSR|S_IWGRP|S_IWOTH) +#endif + +#endif /* PORTABLE_H */ diff -r db7af62da709 -r 41a5481db56f arib25/src/td.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arib25/src/td.c Sun Sep 13 02:11:33 2009 +0900 @@ -0,0 +1,381 @@ +#include +#include +#include + +#include +#include +#include + +#if defined(WIN32) + #include + #include + #include +#else + #define __STDC_FORMAT_MACROS + #include + #include +#endif + +#include "arib_std_b25.h" +#include "b_cas_card.h" + +typedef struct { + int32_t round; + int32_t strip; + int32_t emm; + int32_t verbose; + int32_t power_ctrl; +} OPTION; + +static void show_usage(); +static int parse_arg(OPTION *dst, int argc, char **argv); +static void test_arib_std_b25(const char *src, const char *dst, OPTION *opt); +static void show_bcas_power_on_control_info(B_CAS_CARD *bcas); + +int main(int argc, char **argv) +{ + int n; + OPTION opt; + + #if defined(WIN32) + _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT ); + _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT ); + _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT ); + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_DELAY_FREE_MEM_DF|_CRTDBG_CHECK_ALWAYS_DF|_CRTDBG_LEAK_CHECK_DF); + #endif + + n = parse_arg(&opt, argc, argv); + if(n+2 > argc){ + show_usage(); + exit(EXIT_FAILURE); + } + + test_arib_std_b25(argv[n+0], argv[n+1], &opt); + + #if defined(WIN32) + _CrtDumpMemoryLeaks(); + #endif + + return EXIT_SUCCESS; +} + +static void show_usage() +{ + fprintf(stderr, "b25 - ARIB STD-B25 test program ver. 0.2.3 (2008, 12/30)\n"); + fprintf(stderr, "usage: b25 [options] src.m2t dst.m2t\n"); + fprintf(stderr, "options:\n"); + fprintf(stderr, " -r round (integer, default=4)\n"); + fprintf(stderr, " -s strip\n"); + fprintf(stderr, " 0: keep null(padding) stream (default)\n"); + fprintf(stderr, " 1: strip null stream\n"); + fprintf(stderr, " -m EMM\n"); + fprintf(stderr, " 0: ignore EMM (default)\n"); + fprintf(stderr, " 1: send EMM to B-CAS card\n"); + fprintf(stderr, " -p power_on_control_info\n"); + fprintf(stderr, " 0: do nothing additionaly\n"); + fprintf(stderr, " 1: show B-CAS EMM receiving request (default)\n"); + fprintf(stderr, " -v verbose\n"); + fprintf(stderr, " 0: silent\n"); + fprintf(stderr, " 1: show processing status (default)\n"); + fprintf(stderr, "\n"); +} + +static int parse_arg(OPTION *dst, int argc, char **argv) +{ + int i; + + dst->round = 4; + dst->strip = 0; + dst->emm = 0; + dst->power_ctrl = 1; + dst->verbose = 1; + + for(i=1;iemm = atoi(argv[i]+2); + }else{ + dst->emm = atoi(argv[i+1]); + i += 1; + } + break; + case 'p': + if(argv[i][2]){ + dst->power_ctrl = atoi(argv[i]+2); + }else{ + dst->power_ctrl = atoi(argv[i+1]); + i += 1; + } + break; + case 'r': + if(argv[i][2]){ + dst->round = atoi(argv[i]+2); + }else{ + dst->round = atoi(argv[i+1]); + i += 1; + } + break; + case 's': + if(argv[i][2]){ + dst->strip = atoi(argv[i]+2); + }else{ + dst->strip = atoi(argv[i+1]); + i += 1; + } + break; + case 'v': + if(argv[i][2]){ + dst->verbose = atoi(argv[i]+2); + }else{ + dst->verbose = atoi(argv[i+1]); + i += 1; + } + break; + default: + fprintf(stderr, "error - unknown option '-%c'\n", argv[i][1]); + return argc; + } + } + + return i; +} + +static void test_arib_std_b25(const char *src, const char *dst, OPTION *opt) +{ + int code,i,n,m; + int sfd,dfd; + + int64_t total; + int64_t offset; + + ARIB_STD_B25 *b25; + B_CAS_CARD *bcas; + + ARIB_STD_B25_PROGRAM_INFO pgrm; + + uint8_t data[8*1024]; + + ARIB_STD_B25_BUFFER sbuf; + ARIB_STD_B25_BUFFER dbuf; + + sfd = -1; + dfd = -1; + b25 = NULL; + bcas = NULL; + + sfd = _open(src, _O_BINARY|_O_RDONLY|_O_SEQUENTIAL); + if(sfd < 0){ + fprintf(stderr, "error - failed on _open(%s) [src]\n", src); + goto LAST; + } + + _lseeki64(sfd, 0, SEEK_END); + total = _telli64(sfd); + _lseeki64(sfd, 0, SEEK_SET); + + b25 = create_arib_std_b25(); + if(b25 == NULL){ + fprintf(stderr, "error - failed on create_arib_std_b25()\n"); + goto LAST; + } + + code = b25->set_multi2_round(b25, opt->round); + if(code < 0){ + fprintf(stderr, "error - failed on ARIB_STD_B25::set_multi2_round() : code=%d\n", code); + goto LAST; + } + + code = b25->set_strip(b25, opt->strip); + if(code < 0){ + fprintf(stderr, "error - failed on ARIB_STD_B25::set_strip() : code=%d\n", code); + goto LAST; + } + + code = b25->set_emm_proc(b25, opt->emm); + if(code < 0){ + fprintf(stderr, "error - failed on ARIB_STD_B25::set_emm_proc() : code=%d\n", code); + goto LAST; + } + + bcas = create_b_cas_card(); + if(bcas == NULL){ + fprintf(stderr, "error - failed on create_b_cas_card()\n"); + goto LAST; + } + + code = bcas->init(bcas); + if(code < 0){ + fprintf(stderr, "error - failed on B_CAS_CARD::init() : code=%d\n", code); + goto LAST; + } + + code = b25->set_b_cas_card(b25, bcas); + if(code < 0){ + fprintf(stderr, "error - failed on ARIB_STD_B25::set_b_cas_card() : code=%d\n", code); + goto LAST; + } + + dfd = _open(dst, _O_BINARY|_O_WRONLY|_O_SEQUENTIAL|_O_CREAT|_O_TRUNC, _S_IREAD|_S_IWRITE); + if(dfd < 0){ + fprintf(stderr, "error - failed on _open(%s) [dst]\n", dst); + goto LAST; + } + + offset = 0; + while( (n = _read(sfd, data, sizeof(data))) > 0 ){ + sbuf.data = data; + sbuf.size = n; + + code = b25->put(b25, &sbuf); + if(code < 0){ + fprintf(stderr, "error - failed on ARIB_STD_B25::put() : code=%d\n", code); + goto LAST; + } + + code = b25->get(b25, &dbuf); + if(code < 0){ + fprintf(stderr, "error - failed on ARIB_STD_B25::get() : code=%d\n", code); + goto LAST; + } + + if(dbuf.size > 0){ + n = _write(dfd, dbuf.data, dbuf.size); + if(n != dbuf.size){ + fprintf(stderr, "error failed on _write(%d)\n", dbuf.size); + goto LAST; + } + } + + offset += sbuf.size; + if(opt->verbose != 0){ + m = (int)(10000*offset/total); + fprintf(stderr, "\rprocessing: %2d.%02d%% ", m/100, m%100); + } + } + + code = b25->flush(b25); + if(code < 0){ + fprintf(stderr, "error - failed on ARIB_STD_B25::flush() : code=%d\n", code); + goto LAST; + } + + code = b25->get(b25, &dbuf); + if(code < 0){ + fprintf(stderr, "error - failed on ARIB_STD_B25::get() : code=%d\n", code); + goto LAST; + } + + if(dbuf.size > 0){ + n = _write(dfd, dbuf.data, dbuf.size); + if(n != dbuf.size){ + fprintf(stderr, "error - failed on _write(%d)\n", dbuf.size); + goto LAST; + } + } + + if(opt->verbose != 0){ + fprintf(stderr, "\rprocessing: finish \n"); + fflush(stderr); + fflush(stdout); + } + + n = b25->get_program_count(b25); + if(n < 0){ + fprintf(stderr, "error - failed on ARIB_STD_B25::get_program_count() : code=%d\n", code); + goto LAST; + } + for(i=0;iget_program_info(b25, &pgrm, i); + if(code < 0){ + fprintf(stderr, "error - failed on ARIB_STD_B25::get_program_info(%d) : code=%d\n", i, code); + goto LAST; + } + if(pgrm.ecm_unpurchased_count > 0){ + fprintf(stderr, "warning - unpurchased ECM is detected\n"); + fprintf(stderr, " channel: %d\n", pgrm.program_number); + fprintf(stderr, " unpurchased ECM count: %d\n", pgrm.ecm_unpurchased_count); + fprintf(stderr, " last ECM error code: %04x\n", pgrm.last_ecm_error_code); + #if defined(WIN32) + fprintf(stderr, " undecrypted TS packet: %d\n", pgrm.undecrypted_packet_count); + fprintf(stderr, " total TS packet: %d\n", pgrm.total_packet_count); + #else + fprintf(stderr, " undecrypted TS packet: %"PRId64"\n", pgrm.undecrypted_packet_count); + fprintf(stderr, " total TS packet: %"PRId64"\n", pgrm.total_packet_count); + #endif + } + } + + if(opt->power_ctrl != 0){ + show_bcas_power_on_control_info(bcas); + } + +LAST: + + if(sfd >= 0){ + _close(sfd); + sfd = -1; + } + + if(dfd >= 0){ + _close(dfd); + dfd = -1; + } + + if(b25 != NULL){ + b25->release(b25); + b25 = NULL; + } + + if(bcas != NULL){ + bcas->release(bcas); + bcas = NULL; + } +} + +static void show_bcas_power_on_control_info(B_CAS_CARD *bcas) +{ + int code; + int i,w; + B_CAS_PWR_ON_CTRL_INFO pwc; + + code = bcas->get_pwr_on_ctrl(bcas, &pwc); + if(code < 0){ + fprintf(stderr, "error - failed on B_CAS_CARD::get_pwr_on_ctrl() : code=%d\n", code); + return; + } + + if(pwc.count == 0){ + fprintf(stdout, "no EMM receiving request\n"); + return; + } + + fprintf(stdout, "total %d EMM receiving request\n", pwc.count); + for(i=0;i> 4) & 0x1f), (w & 7)); + break; + case 6: + case 7: + w = pwc.data[i].transport_id; + fprintf(stdout, "ND-%d/TS-%d ", ((w >> 4) & 0x1f), (w & 7)); + break; + default: + fprintf(stdout, "unknown(b:0x%02x,n:0x%04x,t:0x%04x) ", pwc.data[i].broadcaster_group_id, pwc.data[i].network_id, pwc.data[i].transport_id); + break; + } + fprintf(stdout, "between %04d %02d/%02d ", pwc.data[i].s_yy, pwc.data[i].s_mm, pwc.data[i].s_dd); + fprintf(stdout, "to %04d %02d/%02d ", pwc.data[i].l_yy, pwc.data[i].l_mm, pwc.data[i].l_dd); + fprintf(stdout, "least %d hours\n", pwc.data[i].hold_time); + } +} + diff -r db7af62da709 -r 41a5481db56f arib25/src/ts_common_types.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arib25/src/ts_common_types.h Sun Sep 13 02:11:33 2009 +0900 @@ -0,0 +1,36 @@ +#ifndef TS_COMMON_TYPES_H +#define TS_COMMON_TYPES_H + +#include "portable.h" + +typedef struct { + int32_t sync; /* 0- 7 : 8 bits */ + int32_t transport_error_indicator; /* 8- 8 : 1 bit */ + int32_t payload_unit_start_indicator; /* 9- 9 : 1 bit */ + int32_t transport_priority; /* 10-10 : 1 bits */ + int32_t pid; /* 11-23 : 13 bits */ + int32_t transport_scrambling_control; /* 24-25 : 2 bits */ + int32_t adaptation_field_control; /* 26-27 : 2 bits */ + int32_t continuity_counter; /* 28-31 : 4 bits */ +} TS_HEADER; + +typedef struct { + int32_t table_id; /* 0- 7 : 8 bits */ + int32_t section_syntax_indicator; /* 8- 8 : 1 bit */ + int32_t private_indicator; /* 9- 9 : 1 bit */ + int32_t section_length; /* 12-23 : 12 bits */ + int32_t table_id_extension; /* 24-39 : 16 bits */ + int32_t version_number; /* 42-46 : 5 bits */ + int32_t current_next_indicator; /* 47-57 : 1 bit */ + int32_t section_number; /* 48-55 : 8 bits */ + int32_t last_section_number; /* 56-63 : 8 bits */ +} TS_SECTION_HEADER; + +typedef struct { + TS_SECTION_HEADER hdr; + uint8_t *raw; + uint8_t *data; + uint8_t *tail; +} TS_SECTION; + +#endif /* TS_COMMON_TYPES_H */ diff -r db7af62da709 -r 41a5481db56f arib25/src/ts_section_parser.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arib25/src/ts_section_parser.c Sun Sep 13 02:11:33 2009 +0900 @@ -0,0 +1,802 @@ +#include +#include + +#include "ts_section_parser.h" +#include "ts_section_parser_error_code.h" + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + inner structures + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +typedef struct { + void *prev; + void *next; + TS_SECTION sect; + int32_t ref; +} TS_SECTION_ELEM; + +typedef struct { + TS_SECTION_ELEM *head; + TS_SECTION_ELEM *tail; + int32_t count; +} TS_SECTION_LIST; + +typedef struct { + + int32_t pid; + + TS_SECTION_ELEM *work; + TS_SECTION_ELEM *last; + + TS_SECTION_LIST pool; + TS_SECTION_LIST buff; + + TS_SECTION_PARSER_STAT stat; + +} TS_SECTION_PARSER_PRIVATE_DATA; + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + constant values + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +#define MAX_RAW_SECTION_SIZE 4100 + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function prottypes (interface method) + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +static void release_ts_section_parser(void *parser); +static int reset_ts_section_parser(void *parser); +static int put_ts_section_parser(void *parser, TS_HEADER *hdr, uint8_t *data, int size); +static int get_ts_section_parser(void *parser, TS_SECTION *sect); +static int ret_ts_section_parser(void *parser, TS_SECTION *sect); +static int get_count_ts_section_parser(void *parser); +static int get_stat_ts_section_parser(void *parser, TS_SECTION_PARSER_STAT *stat); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + global function implementation (factory method) + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +TS_SECTION_PARSER *create_ts_section_parser() +{ + TS_SECTION_PARSER *r; + TS_SECTION_PARSER_PRIVATE_DATA *prv; + + int n; + + n = sizeof(TS_SECTION_PARSER_PRIVATE_DATA); + n += sizeof(TS_SECTION_PARSER); + + prv = (TS_SECTION_PARSER_PRIVATE_DATA *)calloc(1, n); + if(prv == NULL){ + /* failed on malloc() - no enough memory */ + return NULL; + } + + prv->pid = -1; + + r = (TS_SECTION_PARSER *)(prv+1); + r->private_data = prv; + + r->release = release_ts_section_parser; + r->reset = reset_ts_section_parser; + + r->put = put_ts_section_parser; + r->get = get_ts_section_parser; + r->ret = ret_ts_section_parser; + + r->get_count = get_count_ts_section_parser; + + r->get_stat = get_stat_ts_section_parser; + + return r; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function prottypes (private method) + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +static TS_SECTION_PARSER_PRIVATE_DATA *private_data(void *parser); +static void teardown(TS_SECTION_PARSER_PRIVATE_DATA *prv); + +static int put_exclude_section_start(TS_SECTION_PARSER_PRIVATE_DATA *prv, uint8_t *data, int size); +static int put_include_section_start(TS_SECTION_PARSER_PRIVATE_DATA *prv, uint8_t *data, int size); + +static void reset_section(TS_SECTION *sect); +static void append_section_data(TS_SECTION *sect, uint8_t *data, int size); +static int check_section_complete(TS_SECTION *sect); + +static int compare_elem_section(TS_SECTION_ELEM *a, TS_SECTION_ELEM *b); + +static void cancel_elem_empty(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem); +static void cancel_elem_error(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem); +static void cancel_elem_same(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem); +static void commit_elem_updated(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem); + +static TS_SECTION_ELEM *query_work_elem(TS_SECTION_PARSER_PRIVATE_DATA *prv); + +static void extract_ts_section_header(TS_SECTION *sect); + +static TS_SECTION_ELEM *create_ts_section_elem(); +static TS_SECTION_ELEM *get_ts_section_list_head(TS_SECTION_LIST *list); +static void put_ts_section_list_tail(TS_SECTION_LIST *list, TS_SECTION_ELEM *elem); +static void unlink_ts_section_list(TS_SECTION_LIST *list, TS_SECTION_ELEM *elem); +static void clear_ts_section_list(TS_SECTION_LIST *list); + +static uint32_t crc32(uint8_t *head, uint8_t *tail); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function implementation (interface method) + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +static void release_ts_section_parser(void *parser) +{ + TS_SECTION_PARSER_PRIVATE_DATA *prv; + + prv = private_data(parser); + if(prv == NULL){ + return; + } + + teardown(prv); + + memset(parser, 0, sizeof(TS_SECTION_PARSER)); + free(prv); +} + +static int reset_ts_section_parser(void *parser) +{ + TS_SECTION_PARSER_PRIVATE_DATA *prv; + + prv = private_data(parser); + if(prv == NULL){ + return TS_SECTION_PARSER_ERROR_INVALID_PARAM; + } + + teardown(prv); + + return 0; +} + +static int put_ts_section_parser(void *parser, TS_HEADER *hdr, uint8_t *data, int size) +{ + TS_SECTION_PARSER_PRIVATE_DATA *prv; + + prv = private_data(parser); + if( (prv == NULL) || (hdr == NULL) || (data == NULL) || (size < 1) ){ + return TS_SECTION_PARSER_ERROR_INVALID_PARAM; + } + + if( (prv->pid >= 0) && (prv->pid != hdr->pid) ){ + return TS_SECTION_PARSER_ERROR_INVALID_TS_PID; + } + + prv->pid = hdr->pid; + + if(hdr->payload_unit_start_indicator == 0){ + /* exclude section start */ + return put_exclude_section_start(prv, data, size); + }else{ + /* include section start */ + return put_include_section_start(prv, data, size); + } +} + +static int get_ts_section_parser(void *parser, TS_SECTION *sect) +{ + TS_SECTION_PARSER_PRIVATE_DATA *prv; + TS_SECTION_ELEM *w; + + prv = private_data(parser); + if( (prv == NULL) || (sect == NULL) ){ + return TS_SECTION_PARSER_ERROR_INVALID_PARAM; + } + + w = get_ts_section_list_head(&(prv->buff)); + if(w == NULL){ + memset(sect, 0, sizeof(TS_SECTION)); + return TS_SECTION_PARSER_ERROR_NO_SECTION_DATA; + } + + memcpy(sect, &(w->sect), sizeof(TS_SECTION)); + put_ts_section_list_tail(&(prv->pool), w); + + return 0; +} + +static int ret_ts_section_parser(void *parser, TS_SECTION *sect) +{ + TS_SECTION_PARSER_PRIVATE_DATA *prv; + TS_SECTION_ELEM *w; + + prv = private_data(parser); + if( (prv == NULL) || (sect == NULL) ){ + return TS_SECTION_PARSER_ERROR_INVALID_PARAM; + } + + w = prv->pool.tail; + while(w != NULL){ + if(w->sect.data == sect->data){ + break; + } + w = (TS_SECTION_ELEM *)(w->prev); + } + + if( (w != NULL) && (w->ref > 0) ){ + w->ref -= 1; + } + + return 0; +} + +static int get_count_ts_section_parser(void *parser) +{ + TS_SECTION_PARSER_PRIVATE_DATA *prv; + + prv = private_data(parser); + if(prv == NULL){ + return TS_SECTION_PARSER_ERROR_INVALID_PARAM; + } + + return prv->buff.count; +} + +static int get_stat_ts_section_parser(void *parser, TS_SECTION_PARSER_STAT *stat) +{ + TS_SECTION_PARSER_PRIVATE_DATA *prv; + + prv = private_data(parser); + if( (prv == NULL) || (stat == NULL) ){ + return TS_SECTION_PARSER_ERROR_INVALID_PARAM; + } + + memcpy(stat, &(prv->stat), sizeof(TS_SECTION_PARSER_STAT)); + + return 0; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function implementation (private method) + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +static TS_SECTION_PARSER_PRIVATE_DATA *private_data(void *parser) +{ + TS_SECTION_PARSER_PRIVATE_DATA *r; + TS_SECTION_PARSER *p; + + p = (TS_SECTION_PARSER *)parser; + if(p == NULL){ + return NULL; + } + + r = (TS_SECTION_PARSER_PRIVATE_DATA *)(p->private_data); + if( ((void *)(r+1)) != parser ){ + return NULL; + } + + return r; +} + +static void teardown(TS_SECTION_PARSER_PRIVATE_DATA *prv) +{ + prv->pid = -1; + + if(prv->work != NULL){ + free(prv->work); + prv->work = NULL; + } + + prv->last = NULL; + + clear_ts_section_list(&(prv->pool)); + clear_ts_section_list(&(prv->buff)); + + memset(&(prv->stat), 0, sizeof(TS_SECTION_PARSER_STAT)); +} + +static int put_exclude_section_start(TS_SECTION_PARSER_PRIVATE_DATA *prv, uint8_t *data, int size) +{ + TS_SECTION_ELEM *w; + + w = prv->work; + if( (w == NULL) || (w->sect.raw == w->sect.tail) ){ + /* no previous data */ + return 0; + } + + append_section_data(&(w->sect), data, size); + if(check_section_complete(&(w->sect)) == 0){ + /* need more data */ + return 0; + } + + prv->work = NULL; + + if( (w->sect.hdr.section_syntax_indicator != 0) && + (crc32(w->sect.raw, w->sect.tail) != 0) ){ + cancel_elem_error(prv, w); + return TS_SECTION_PARSER_WARN_CRC_MISSMATCH; + } + + if(compare_elem_section(w, prv->last) == 0){ + /* same section data */ + cancel_elem_same(prv, w); + return 0; + } + + commit_elem_updated(prv, w); + return 0; +} + +static int put_include_section_start(TS_SECTION_PARSER_PRIVATE_DATA *prv, uint8_t *data, int size) +{ + TS_SECTION_ELEM *w; + + int pointer_field; + + uint8_t *p; + uint8_t *tail; + + int r; + int length; + + p = data; + tail = p + size; + + r = 0; + + pointer_field = p[0]; + p += 1; + + if( (p+pointer_field) >= tail ){ + /* input data is probably broken */ + w = prv->work; + prv->work = NULL; + if(w != NULL) { + if(w->sect.raw != w->sect.tail){ + cancel_elem_error(prv, w); + return TS_SECTION_PARSER_WARN_LENGTH_MISSMATCH; + } + cancel_elem_empty(prv, w); + } + return 0; + } + + if(pointer_field > 0){ + r = put_exclude_section_start(prv, p, pointer_field); + if(r < 0){ + return r; + } + p += pointer_field; + } + + w = prv->work; + prv->work = NULL; + + if(w != NULL){ + if(w->sect.raw != w->sect.tail){ + cancel_elem_error(prv, w); + r = TS_SECTION_PARSER_WARN_LENGTH_MISSMATCH; + }else{ + cancel_elem_empty(prv, w); + } + w = NULL; + } + + do { + + w = query_work_elem(prv); + if(w == NULL){ + return TS_SECTION_PARSER_ERROR_NO_ENOUGH_MEMORY; + } + + append_section_data(&(w->sect), p, tail-p); + if(check_section_complete(&(w->sect)) == 0){ + /* need more data */ + prv->work = w; + return 0; + } + length = (w->sect.tail - w->sect.raw); + + if( (w->sect.hdr.section_syntax_indicator != 0) && + (crc32(w->sect.raw, w->sect.tail) != 0) ){ + cancel_elem_error(prv, w); + r = TS_SECTION_PARSER_WARN_CRC_MISSMATCH; + }else if(compare_elem_section(w, prv->last) == 0){ + cancel_elem_same(prv, w); + }else{ + commit_elem_updated(prv, w); + } + + p += length; + + } while ( (p < tail) && (p[0] != 0xff) ); + + return r; +} + +static void reset_section(TS_SECTION *sect) +{ + memset(&(sect->hdr), 0, sizeof(TS_SECTION_HEADER)); + sect->tail = sect->raw; + sect->data = NULL; +} + +static void append_section_data(TS_SECTION *sect, uint8_t *data, int size) +{ + int m,n; + + m = sect->tail - sect->raw; + n = MAX_RAW_SECTION_SIZE - m; + + if(size < n){ + n = size; + } + memcpy(sect->tail, data, n); + sect->tail += n; + m += n; + + if(sect->data == NULL){ + extract_ts_section_header(sect); + } + + if(sect->data == NULL){ + /* need more data */ + return; + } + + n = sect->hdr.section_length + 3; + if(m > n){ + sect->tail = sect->raw + n; + } + + return; +} + +static int check_section_complete(TS_SECTION *sect) +{ + int m,n; + + if(sect->data == NULL){ + return 0; + } + + m = sect->tail - sect->raw; + n = sect->hdr.section_length + 3; + + if(n > m){ + return 0; + } + + return 1; +} + +static int compare_elem_section(TS_SECTION_ELEM *a, TS_SECTION_ELEM *b) +{ + int m,n; + + if( (a == NULL) || (b == NULL) ){ + return 1; + } + + m = a->sect.tail - a->sect.raw; + n = b->sect.tail - b->sect.raw; + if( m != n ){ + return 1; + } + + if(memcmp(a->sect.raw, b->sect.raw, m) != 0){ + return 1; + } + + return 0; +} + +static void cancel_elem_empty(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem) +{ + reset_section(&(elem->sect)); + elem->ref = 0; + put_ts_section_list_tail(&(prv->pool), elem); +} + +static void cancel_elem_error(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem) +{ + reset_section(&(elem->sect)); + elem->ref = 0; + put_ts_section_list_tail(&(prv->pool), elem); + prv->stat.total += 1; + prv->stat.error += 1; +} + +static void cancel_elem_same(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem) +{ + reset_section(&(elem->sect)); + elem->ref = 0; + put_ts_section_list_tail(&(prv->pool), elem); + prv->stat.total +=1; +} + +static void commit_elem_updated(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem) +{ + if( (prv->last != NULL) && (prv->last->ref > 0) ){ + prv->last->ref -= 1; + } + + elem->ref = 2; + prv->last = elem; + put_ts_section_list_tail(&(prv->buff), elem); + prv->stat.total += 1; + prv->stat.unique += 1; +} + +static TS_SECTION_ELEM *query_work_elem(TS_SECTION_PARSER_PRIVATE_DATA *prv) +{ + TS_SECTION_ELEM *r; + + r = prv->pool.head; + while(r != NULL){ + if(r->ref < 1){ + break; + } + r = (TS_SECTION_ELEM *)(r->next); + } + + if(r != NULL){ + unlink_ts_section_list(&(prv->pool), r); + reset_section(&(r->sect)); + r->ref = 0; + return r; + } + + return create_ts_section_elem(); +} + +static void extract_ts_section_header(TS_SECTION *sect) +{ + int size; + uint8_t *p; + + sect->data = NULL; + + size = sect->tail - sect->raw; + if(size < 3){ + /* need more data */ + return; + } + + p = sect->raw; + + sect->hdr.table_id = p[0]; + sect->hdr.section_syntax_indicator = (p[1] >> 7) & 0x01; + sect->hdr.private_indicator = (p[1] >> 6) & 0x01; + sect->hdr.section_length =((p[1] << 8) | p[2]) & 0x0fff; + + if(sect->hdr.section_syntax_indicator == 0){ + /* short format section header */ + sect->data = p+3; + return; + } + + /* long format section header */ + + if(size < 8){ + /* need more data */ + return; + } + + sect->hdr.table_id_extension =((p[3] << 8) | p[4]); + sect->hdr.version_number = (p[5] >> 1) & 0x1f; + sect->hdr.current_next_indicator = p[5] & 0x01; + sect->hdr.section_number = p[6]; + sect->hdr.last_section_number = p[7]; + + sect->data = p+8; + + return; +} + +static TS_SECTION_ELEM *create_ts_section_elem() +{ + TS_SECTION_ELEM *r; + int n; + + n = sizeof(TS_SECTION_ELEM) + MAX_RAW_SECTION_SIZE; + r = (TS_SECTION_ELEM *)calloc(1, n); + if(r == NULL){ + /* failed on malloc() */ + return NULL; + } + + r->sect.raw = (uint8_t *)(r+1); + r->sect.tail = r->sect.raw; + + return r; +} + +static TS_SECTION_ELEM *get_ts_section_list_head(TS_SECTION_LIST *list) +{ + TS_SECTION_ELEM *r; + + if(list == NULL){/* invalid param */ + return NULL; + } + + r = list->head; + if(r == NULL){ + return NULL; + } + + list->head = (TS_SECTION_ELEM *)(r->next); + if(list->head != NULL){ + list->head->prev = NULL; + list->count -= 1; + }else{ + list->tail = NULL; + list->count = 0; + } + + r->next = NULL; + + return r; +} + +static void put_ts_section_list_tail(TS_SECTION_LIST *list, TS_SECTION_ELEM *elem) +{ + if( (list == NULL) || (elem == NULL) ){ + /* invalid param */ + return; + } + + if(list->tail != NULL){ + elem->prev = list->tail; + elem->next = NULL; + list->tail->next = elem; + list->tail = elem; + list->count += 1; + }else{ + elem->prev = NULL; + elem->next = NULL; + list->head = elem; + list->tail = elem; + list->count = 1; + } +} + +static void unlink_ts_section_list(TS_SECTION_LIST *list, TS_SECTION_ELEM *elem) +{ + TS_SECTION_ELEM *prev; + TS_SECTION_ELEM *next; + + if( (list == NULL) || (elem == NULL) ){ + /* invalid param */ + return; + } + + prev = (TS_SECTION_ELEM *)(elem->prev); + next = (TS_SECTION_ELEM *)(elem->next); + + if(prev != NULL){ + prev->next = next; + }else{ + list->head = next; + } + if(next != NULL){ + next->prev = prev; + }else{ + list->tail = prev; + } + list->count -= 1; +} + +static void clear_ts_section_list(TS_SECTION_LIST *list) +{ + TS_SECTION_ELEM *e; + TS_SECTION_ELEM *n; + + if(list == NULL){ /* invalid param */ + return; + } + + e = list->head; + while(e != NULL){ + n = (TS_SECTION_ELEM *)(e->next); + free(e); + e = n; + } + + list->head = NULL; + list->tail = NULL; + list->count = 0; +} + +static uint32_t crc32(uint8_t *head, uint8_t *tail) +{ + uint32_t crc; + uint8_t *p; + + static const uint32_t table[256] = { + 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, + 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, + 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, + 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, + + 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, + 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75, + 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, + 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD, + + 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, + 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, + 0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81, + 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D, + + 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, + 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95, + 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, + 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, + + 0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE, + 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072, + 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, + 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, + + 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, + 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, + 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066, + 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, + + 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, + 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692, + 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, + 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, + + 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, + 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, + 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, + 0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A, + + 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, + 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, + 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, + 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, + + 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, + 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B, + 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, + 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, + + 0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, + 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B, + 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, + 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3, + + 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, + 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, + 0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F, + 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3, + + 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, + 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, + 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, + 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, + + 0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30, + 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC, + 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, + 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, + + 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, + 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, + 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18, + 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, + + 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, + 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C, + 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, + 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4, + }; + + crc = 0xffffffff; + + p = head; + while(p < tail){ + crc = (crc << 8) ^ table[ ((crc >> 24) ^ p[0]) & 0xff ]; + p += 1; + } + + return crc; +} + diff -r db7af62da709 -r 41a5481db56f arib25/src/ts_section_parser.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arib25/src/ts_section_parser.h Sun Sep 13 02:11:33 2009 +0900 @@ -0,0 +1,40 @@ +#ifndef TS_SECTION_PARSER_H +#define TS_SECTION_PARSER_H + +#include "ts_common_types.h" + +typedef struct { + int64_t total; /* total received section count */ + int64_t unique; /* unique section count */ + int64_t error; /* crc and other error section count */ +} TS_SECTION_PARSER_STAT; + +typedef struct { + + void *private_data; + + void (* release)(void *parser); + + int (* reset)(void *parser); + + int (* put)(void *parser, TS_HEADER *hdr, uint8_t *data, int size); + int (* get)(void *parser, TS_SECTION *sect); + int (* ret)(void *parser, TS_SECTION *sect); + + int (* get_count)(void *parser); + + int (* get_stat)(void *parser, TS_SECTION_PARSER_STAT *stat); + +} TS_SECTION_PARSER; + +#ifdef __cplusplus +extern "C" { +#endif + +extern TS_SECTION_PARSER *create_ts_section_parser(); + +#ifdef __cplusplus +} +#endif + +#endif /* TS_SECTION_PARSER_H */ diff -r db7af62da709 -r 41a5481db56f arib25/src/ts_section_parser_error_code.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arib25/src/ts_section_parser_error_code.h Sun Sep 13 02:11:33 2009 +0900 @@ -0,0 +1,12 @@ +#ifndef TS_SECTION_PARSER_ERROR_CODE_H +#define TS_SECTION_PARESR_ERROR_CODE_H + +#define TS_SECTION_PARSER_ERROR_INVALID_PARAM -1 +#define TS_SECTION_PARSER_ERROR_NO_ENOUGH_MEMORY -2 +#define TS_SECTION_PARSER_ERROR_INVALID_TS_PID -3 +#define TS_SECTION_PARSER_ERROR_NO_SECTION_DATA -4 + +#define TS_SECTION_PARSER_WARN_CRC_MISSMATCH 1 +#define TS_SECTION_PARSER_WARN_LENGTH_MISSMATCH 2 + +#endif /* TS_SECTION_PARSER_ERROR_CODE_H */ diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/.cproject --- a/arib25v023/arib25/.cproject Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,218 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/.project --- a/arib25v023/arib25/.project Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ - - - arib25 - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - org.eclipse.cdt.make.core.fullBuildTarget - all - - - ?name? - - - - org.eclipse.cdt.make.core.enableAutoBuild - false - - - org.eclipse.cdt.make.core.buildLocation - ${workspace_loc:/arib25} - - - org.eclipse.cdt.make.core.enableFullBuild - true - - - org.eclipse.cdt.make.core.enableCleanBuild - true - - - org.eclipse.cdt.make.core.cleanBuildTarget - clean - - - org.eclipse.cdt.make.core.append_environment - true - - - org.eclipse.cdt.make.core.contents - org.eclipse.cdt.make.core.activeConfigSettings - - - org.eclipse.cdt.make.core.useDefaultBuildCmd - true - - - org.eclipse.cdt.make.core.buildArguments - - - - org.eclipse.cdt.make.core.buildCommand - make - - - org.eclipse.cdt.make.core.autoBuildTarget - all - - - org.eclipse.cdt.make.core.stopOnError - true - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - - diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/.settings/org.eclipse.core.resources.prefs --- a/arib25v023/arib25/.settings/org.eclipse.core.resources.prefs Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -#Wed Jan 23 22:50:22 JST 2008 -eclipse.preferences.version=1 -encoding/=Windows-31J diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/Makefile --- a/arib25v023/arib25/Makefile Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -all: - cd src; make all - -clean: - cd src; make clean - diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/arib_std_b25.sln --- a/arib25v023/arib25/arib_std_b25.sln Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual C++ Express 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "arib_std_b25", "arib_std_b25.vcproj", "{6E77C1AC-A31A-49B9-9A52-9FE1E03B8FEC}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6E77C1AC-A31A-49B9-9A52-9FE1E03B8FEC}.Debug|Win32.ActiveCfg = Debug|Win32 - {6E77C1AC-A31A-49B9-9A52-9FE1E03B8FEC}.Debug|Win32.Build.0 = Debug|Win32 - {6E77C1AC-A31A-49B9-9A52-9FE1E03B8FEC}.Release|Win32.ActiveCfg = Release|Win32 - {6E77C1AC-A31A-49B9-9A52-9FE1E03B8FEC}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/arib_std_b25.vcproj --- a/arib25v023/arib25/arib_std_b25.vcproj Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,259 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/readme.txt --- a/arib25v023/arib25/readme.txt Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,351 +0,0 @@ -y–¼Ìz - -@ARIB STD-B25 Žd—lŠm”FƒeƒXƒgƒvƒƒOƒ‰ƒ€ƒ\[ƒXƒR[ƒh - -yƒo[ƒWƒ‡ƒ“z - -@0.2.3 - -yìŽÒz - -@–Î–Ø ˜a—m (MOGI, Kazuhiro) -@kazhiro@marumo.ne.jp - -yˆêŽŸ”z•zŒ³z - -@http://www.marumo.ne.jp/db2008_c.htm#30 - -@‚ ‚é‚¢‚Í - -@http://www.marumo.ne.jp/junk/arib_std_b25-0.2.3.lzh - -y–Ú“Iz - -@ARIB STD-B25 ‚ÌŽd—l‚ð—‰ð‚·‚éˆ×‚ÌAŽQl—p‚ÌŽÀ‘•‚Æ‚µ‚ÄŒöŠJ - -y”wŒiz - -@2011 ”N 7 ŒŽ‚Ì’nãƒAƒiƒƒO•ú‘—’â”g‚ðT‚¦A—õ‰¿‚È’nãƒfƒWƒ^ƒ‹•ú‘— -@ŽóM‹@‚̔̔„‚ª‘Ò‚½‚ê‚Ä‚¢‚é - -@‚µ‚©‚µAARIB ‚Ì•W€•¶‘‚Í‚í‚´‚Æ”»‚è‚É‚­‚­‘‚¢‚ÄŠJ”­”ï‚ð‚©‚³‚Ü‚¹ -@‚悤‚Æ‚µ‚Ä‚¢‚é‚Æ‚µ‚©Žv‚¦‚È‚¢‚قǂɈӖ¡•s–¾—Ä‚È‹Lq‚É‚È‚Á‚Ä‚¨‚è -@‚±‚̂܂܂ł͒ቿŠiŽóM‹@‚ÌŠJ”­‚È‚Ç•s‰Â”\‚ÉŽv‚¦‚é - -@‚»‚±‚ÅAŽ©•ª‚È‚è‚É ARIB •W€•¶‘‚ð“Ç‚ÝA—‰ð‚µ‚½”͈͂ðƒ\[ƒX -@ƒR[ƒh‚ÌŒ`‚É‚Ü‚Æ‚ß‚ÄŒöŠJ‚·‚邱‚Æ‚É‚µ‚½ - -@‚±‚̃R[ƒh‚ªˆÀ‰¿‚ÈŽóM‹@‚ÌŠJ”­‚̈ꕂƂȂ邱‚Æ‚ðŠú‘Ò‚·‚é - -@‚È‚¨A‚ ‚­‚Ü‚Å‚àŽd—l—‰ð‚ð–Ú“I‚Æ‚µ‚½‚à‚Ì‚Å‚ ‚邽‚ßAƒrƒ‹ƒhÏ‚Ý -@ƒoƒCƒiƒŠƒtƒ@ƒCƒ‹‚Í”z•z‚µ‚È‚¢ - -yŽÀ‘•‚µ‚½”͈Íz - -@CA ƒVƒXƒeƒ€ (B-CAS ƒJ[ƒhŠÖ˜A) ‚ð’†S‚É ECM(table_id=0x82) ‚̈—‚Æ -@ƒXƒgƒŠ[ƒ€ˆÃ†‚Ì•œ†ˆ—AEMM(table_id=0x84) ‚̈—‚Ü‚Å‚ðŽÀ‘•‚µ‚½ - -@EMM ƒƒbƒZ[ƒW (table_id=0x85) ŠÖ˜A‚Í–¢ŽÀ‘•‚Æ‚È‚Á‚Ä‚¢‚é - -yƒvƒƒOƒ‰ƒ€‚Ì“®ìŠÂ‹«z - -@ISO 7816 ‘Ήž‚Ì IC ƒJ[ƒhƒŠ[ƒ_‚ªƒCƒ“ƒXƒg[ƒ‹‚³‚ꂽ Windows PC ‚ð -@‘z’è“®ìŠÂ‹«‚Æ‚·‚é - -@ISO 7816 ‘ΉžƒXƒ}[ƒgƒJ[ƒhƒŠ[ƒ_[‚͈ê”Ê‚É -@uZŠîƒJ[ƒh‘Ήž IC ƒJ[ƒhƒŠ[ƒ_vue-Tax ‘Ήž IC ƒJ[ƒhƒŠ[ƒ_v -@‚È‚Ç‚Æ‚µ‚Ä 4000 ‰~’ö“x‚Ŕ̔„‚³‚ê‚Ä‚¢‚é‚à‚Ì‚ª—˜—p‰Â”\‚Å‚ ‚é - -@“ú—§ƒ}ƒNƒZƒ‹»‚Ì HX-520UJJ ‚ųí‚É“®ì‚·‚邱‚Æ‚ðŠm”F‚µ‚Ä‚¢‚é - -yƒ\[ƒXƒR[ƒh‚̃‰ƒCƒZƒ“ƒX‚ɂ‚¢‚Äz - -@Eƒ\[ƒXƒR[ƒh‚ð—˜—p‚µ‚½‚±‚Æ‚É‚æ‚Á‚ÄA“Á‹–ã‚̃gƒ‰ƒuƒ‹‚ª”­¶‚µ‚Ä‚à -@@–Î–Ø ˜a—m‚ÍÓ”C‚𕉂í‚È‚¢ -@Eƒ\[ƒXƒR[ƒh‚ð—˜—p‚µ‚½‚±‚Æ‚É‚æ‚Á‚ÄAƒvƒƒOƒ‰ƒ€‚É–â‘肪”­¶‚µ‚Ä‚à -@@–Î–Ø ˜a—m‚ÍÓ”C‚𕉂í‚È‚¢ - -@ã‹L 2 ðŒ‚É“¯ˆÓ‚µ‚Ä쬂³‚ꂽ“ñŽŸ“I’˜ì•¨‚ɑ΂µ‚ÄA–Î–Ø ˜a—m‚Í -@Œ´’˜ìŽÒ‚É—^‚¦‚ç‚ê‚锌 —˜‚ðsŽg‚µ‚È‚¢ - -yƒvƒƒOƒ‰ƒ€‚Ì\¬z - -@Earib_std_b25.h/c - -@@ARIB STD-B25 ‹Lڂ̈—‚ðs‚¤‚½‚߂̃‚ƒWƒ…[ƒ‹ -@@MPEG-2 TS ‚Ì•ª—£ACA ƒVƒXƒeƒ€ (B-CAS ƒJ[ƒh) ‹@”\‚̌ĂÑo‚µA -@@MULTI2 •œ†‹@”\‚̌ĂÑo‚µ“™‚ð’S“–‚·‚é - -@Ets_section_parser.h/c - -@@MPEG-2 TS ‚̃ZƒNƒVƒ‡ƒ“Œ`Ž®ƒf[ƒ^‚Ì•ªŠ„ˆ—‚ð’S“–‚·‚é - -@Eb_cas_card.h/c - -@@CA ƒVƒXƒeƒ€ (B-CAS ƒJ[ƒh) ‚̃Šƒ\[ƒXŠÇ—‚¨‚æ‚Ñ’¼Ú‚̧Œä‚ð -@@’S“–‚·‚é - -@Emulti2.h/c - -@@MULTI2 ˆÃ†‚Ì•„†‰»‚Æ•œ†‚ð’S“–‚·‚é - -@Etd.c - -@@ƒeƒXƒgƒhƒ‰ƒCƒo -@@PAT/PMT/ECM ‚ðŠÜ‚Þ MPEG-2 TS ƒtƒ@ƒCƒ‹‚ð“Ç‚Ýž‚ÝA•œ†Œã‚Ì -@@MPEG-2 TS ƒtƒ@ƒCƒ‹‚ðo—Í‚·‚é - -@@ƒRƒ}ƒ“ƒhƒ‰ƒCƒ“ƒIƒvƒVƒ‡ƒ“‚Å MULTI2 ˆÃ†‚̃‰ƒEƒ“ƒh”‚ðŽw’è‰Â”\ -@@ƒ‰ƒEƒ“ƒh”‚ðŽw’肵‚È‚¢ê‡‚̉Šú’l‚Í 4 - -@@‚±‚̃‰ƒEƒ“ƒh” 4 ‚Í MULTI2 —pŒê‚Å‚Í 32 ‚É‘Š“–‚·‚é - -@@ARIB STD-B25 ‚Å‚Í MULTI2 ‚̃‰ƒEƒ“ƒh”‚Í”ñŒöŠJƒpƒ‰ƒ[ƒ^‚¾‚ª -@@‘“–‚½‚è‚ÅŽÀۂ̃‰ƒEƒ“ƒh”‚Í„’è‰Â”\‚Å‚ ‚é - -yˆ—‚Ì—¬‚êz - -@E‹N“®Žž - -@@1 ƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚Í B_CAS_CARD ƒ‚ƒWƒ…[ƒ‹‚̃Cƒ“ƒXƒ^ƒ“ƒX‚ð -@@@쬂µAB_CAS_CARD ƒ‚ƒWƒ…[ƒ‹‚ÉA‰Šú‰»‚ðˆË—Š‚·‚é - -@@1.a B_CAS_CARD ƒ‚ƒWƒ…[ƒ‹‚Í WIN32 API ‚̃Xƒ}[ƒgƒJ[ƒhŠÖ˜A -@@@@API ‚ðŒÄ‚Ño‚µACA ƒVƒXƒeƒ€‚ÉÚ‘±‚·‚é -@@1.b B_CAS_CARD ƒ‚ƒWƒ…[ƒ‹‚Í ARIB STD-B25 ‹LÚ‚Ìu‰ŠúðŒ -@@@@Ý’èƒRƒ}ƒ“ƒh‚ð CA ƒVƒXƒeƒ€‚É”­s‚µAƒVƒXƒeƒ€Œ® (64 byte) -@@@@‰Šú CBC ó‘Ô (8 byte) ‚ðŽó‚¯Žæ‚é - -@@2 ƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚Í ARIB_STD_B25 ƒ‚ƒWƒ…[ƒ‹‚̃Cƒ“ƒXƒ^ƒ“ƒX‚ð -@@@쬂µAB_CAS_CARD ƒ‚ƒWƒ…[ƒ‹‚ð ARIB_STD_B25 ƒ‚ƒWƒ…[ƒ‹‚É -@@@“o˜^‚·‚é - -@Eƒf[ƒ^ˆ—Žž - -@@1 ƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚Í ARIB_STD_B25 ƒ‚ƒWƒ…[ƒ‹‚ɇŽŸƒf[ƒ^‚ð -@@@’ñ‹Ÿ‚µAARIB_STD_B25 ƒ‚ƒWƒ…[ƒ‹‚©‚爗Š®—¹ƒf[ƒ^‚ðŽó‚¯ -@@@Žæ‚Á‚ătƒ@ƒCƒ‹‚Éo—Í‚µ‚Ä‚¢‚­ - -@@EARIB_STD_B25 ƒ‚ƒWƒ…[ƒ‹“à - -@@@1 TS ƒpƒPƒbƒg‚̃†ƒjƒbƒgƒTƒCƒY (188/192/204 ‚È‚Ç‚ªˆê”Ê“I) ‚ª -@@@@“Á’肳‚ê‚Ä‚¢‚È‚¢ê‡ 8K ‚Ü‚Å“ü—̓f[ƒ^‚ðƒoƒbƒtƒ@‚µ‚Ä‚©‚çA -@@@@ƒ†ƒjƒbƒgƒTƒCƒY‚ð“Á’è‚·‚é -@@@@ƒ†ƒjƒbƒgƒTƒCƒY‚ª“Á’è‚Å‚«‚È‚©‚Á‚½ê‡‚ÍAƒGƒ‰[I—¹‚·‚é - -@@@2 PAT ‚ª”­Œ©‚³‚ê‚Ä‚¢‚È‚¢ê‡APAT ‚ª”­Œ©‚Å‚«‚é‚Ü‚Å“ü—Í -@@@@ƒf[ƒ^‚ðƒoƒbƒtƒ@‚µ‘±‚¯‚é -@@@@PAT ‚ª”­Œ©‚Å‚«‚¸‚Ƀoƒbƒtƒ@ƒTƒCƒY‚ª 16M ‚𒴉߂µ‚½ê‡ -@@@@ƒGƒ‰[I—¹‚·‚é -@@@@PAT ‚ª”­Œ©‚Å‚«‚½ê‡AƒvƒƒOƒ‰ƒ€”z—ñ‚ð쬂µ PID ƒ}ƒbƒv -@@@@”z—ñ‚É“o˜^‚·‚é - -@@@3 PAT ‚É“o˜^‚³‚ê‚Ä‚¢‚½ PMT ‚·‚ׂĂª”­Œ©‚³‚ê‚é‚©A‚Ç‚ê‚© -@@@@‚Ð‚Æ‚Â‚Ì PMT ‚Å 2 ŒÂ–ڂ̃ZƒNƒVƒ‡ƒ“‚ª“ž’…‚·‚é‚Ü‚Å“ü—Í -@@@@ƒf[ƒ^‚ðƒoƒbƒtƒ@‚µ‘±‚¯‚é -@@@@ã‹LðŒ‚ð–ž‚½‚³‚¸‚Ƀoƒbƒtƒ@ƒTƒCƒY‚ª 32M ‚𒴉߂µ‚½ê‡ -@@@@ƒGƒ‰[I—¹‚·‚é -@@@@PMT ‚ª“ž’…‚·‚é–ˆ‚É ECM ‚Ì—L–³‚ðŠm”F‚µAECM ‚ª‘¶Ý‚·‚é -@@@@ꇂ̓fƒNƒŠƒvƒ^‚ð쬂µ‚ăvƒƒOƒ‰ƒ€‚ÉŠ‘®‚·‚éƒXƒgƒŠ[ƒ€ -@@@@‚Æ PID ƒ}ƒbƒvã‚ÅŠÖ˜A•t‚¯‚é - -@@@4 PMT ‚É“o˜^‚³‚ê‚Ä‚¢‚½ ECM ‚·‚ׂĂª”­Œ©‚³‚ê‚é‚©A‚Ç‚ê‚© -@@@@‚Ð‚Æ‚Â‚Ì ECM ‚Å 2 ŒÂ–ڂ̃ZƒNƒVƒ‡ƒ“‚ª“ž’…‚·‚é‚Ü‚Å“ü—Í -@@@@ƒf[ƒ^‚ðƒoƒbƒtƒ@‚µ‘±‚¯‚é -@@@@ã‹LðŒ‚ð–ž‚½‚³‚¸‚Ƀoƒbƒtƒ@ƒTƒCƒY‚ª 32M ‚𒴉߂µ‚½ê‡ -@@@@ƒGƒ‰[I—¹‚·‚é -@@@@Še ECM ‚ɑ΂µ‚ÄAʼn‚̃ZƒNƒVƒ‡ƒ“ƒf[ƒ^‚ª“ž’…‚µ‚½Žž“_‚Å -@@@@MULTI2 ƒ‚ƒWƒ…[ƒ‹‚̃Cƒ“ƒXƒ^ƒ“ƒX‚ðƒfƒNƒŠƒvƒ^ã‚É쬂·‚é -@@@@ECM ƒZƒNƒVƒ‡ƒ“ƒf[ƒ^‚Í B_CAS_CARD ƒ‚ƒWƒ…[ƒ‹‚É’ñ‹Ÿ‚µ‚Ä -@@@@ƒXƒNƒ‰ƒ“ƒuƒ‹Œ®‚ðŽó‚¯Žæ‚èAMULTI2 ƒ‚ƒWƒ…[ƒ‹‚ɃVƒXƒeƒ€Œ®A -@@@@‰Šú CBC ó‘ÔAƒXƒNƒ‰ƒ“ƒuƒ‹Œ®‚ð“n‚µAMULTI2 •œ†‚Ì€”õ‚ð -@@@@s‚¤ - -@@@5.a ˆÃ†‰»‚³‚ê‚Ä‚¢‚é TS ƒpƒPƒbƒg‚Å‚ ‚ê‚ÎAPID ‚©‚ç‘Ήž -@@@@@ECM ƒXƒgƒŠ[ƒ€‚ð“Á’肵AƒfƒNƒŠƒvƒ^‚Ì MULTI2 ƒ‚ƒWƒ…[ -@@@@@ƒ‹‚É•œ†‚³‚¹‚Äo—̓oƒbƒtƒ@‚ÉÏ‚Þ -@@@@ -@@@5.b ˆÃ†‰»‚³‚ê‚Ä‚¢‚È‚¢ TS ƒpƒPƒbƒg‚Å‚ ‚ê‚ÎA‚»‚Ì‚Ü‚Üo—Í -@@@@@ƒoƒbƒtƒ@‚ÉÏ‚Þ - -@@@5.c CAT ‚ðŒŸo‚µ‚½ê‡AEMM ‚Ì PID ‚ðŽæ“¾‚µ‚Ä EMM ‚̈— -@@@@@€”õ‚ðs‚¤ - -@@@5.d EMM ‚ðŽó‚¯Žæ‚Á‚½ê‡AB-CAS ƒJ[ƒh ID ‚Æ”äŠr‚µAŽ©•ª -@@@@@ˆ¶‚Ä‚Ì EMM ‚Å‚ ‚ê‚Î B-CAS ƒJ[ƒh‚Ɉø‚«“n‚µ‚Ĉ—‚³‚¹‚é -@@@@@# EMM ˆ—ƒIƒvƒVƒ‡ƒ“‚ªŽw’肳‚ê‚Ä‚¢‚éê‡ - -@@@6 ECM ‚ªXV‚³‚ꂽê‡AB_CAS_CARD ƒ‚ƒWƒ…[ƒ‹‚Ɉ—‚ð -@@@@ˆË—Š‚µAo—Í‚³‚ꂽƒXƒNƒ‰ƒ“ƒuƒ‹Œ®‚ð MULTI2 ƒ‚ƒWƒ…[ƒ‹‚É -@@@@“o˜^‚·‚é - -@@@7 PMT ‚ªXV‚³‚ꂽê‡AECM PID ‚ª•Ï‰»‚µ‚Ä‚¢‚ê‚ÎV‚½‚É -@@@@ƒfƒNƒŠƒvƒ^‚ð쬂µ‚Ä 4 ‚É–ß‚é - -@@@8 PAT ‚ªXV‚³‚ꂽê‡AƒvƒƒOƒ‰ƒ€”z—ñ‚ð”jŠü‚µ‚Ä -@@@@3 ‚É–ß‚é - -@EI—¹Žž - -@@1 Šeƒ‚ƒWƒ…[ƒ‹‚ªŠm•Û‚µ‚½ƒŠƒ\[ƒX‚ð‰ð•ú‚·‚é - -yXV—š—ðz - -@E2008, 12/30 - ver. 0.2.3 - -@@CA_descriptor ‚̉ðŽß‚ðs‚¤Û‚É CA_system_id ‚ª B-CAS ƒJ[ƒh -@@‚©‚çŽæ“¾‚µ‚½‚à‚̂ƈê’v‚·‚é‚©Šm”F‚ðs‚¤‚悤‚É•ÏX - -@@http://www.marumo.ne.jp/db2008_c.htm#30 –”‚Í -@@http://www.marumo.ne.jp/junk/arib_std_b25-0.2.3.lzh - -@E2008, 11/10 - ver. 0.2.2 - -@@C³ƒ†ƒŠƒEƒX“ú‚©‚ç”NŒŽ“ú‚Ö‚Ì•ÏŠ·ˆ—‚ð‚æ‚賊m‚È‚à‚Ì‚Ö•ÏX - -@@TS ƒpƒPƒbƒgƒTƒCƒY‚Ì“Á’è•û–@‚ð•ÏX - -@@http://www.marumo.ne.jp/db2008_b.htm#10 –”‚Í -@@http://www.marumo.ne.jp/junk/arib_std_b25-0.2.2.lzh - -@E2008, 4/9 - ver. 0.2.1 - -@@PAT XVŽž‚É•œ†˜R‚ꂪ”­¶‚µ‚Ä‚¢‚½ƒoƒO‚ðC³ -@@(ver. 0.2.0 ‚ł̃Gƒ“ƒoƒO) - -@@–ì—Ç PID (PMT ‚É‹LÚ‚³‚ê‚Ä‚¢‚È‚¢ƒXƒgƒŠ[ƒ€) ‚ª‘¶Ý‚µ‚½ê‡ -@@TS “à‚Ì ECM ‚ª‚ЂƂ‚¾‚¯‚È‚ç‚ÎA‚»‚Ì ECM ‚Å•œ†‚·‚éŒ`‚É•ÏX - -@@EMM ‚Ì B-CAS ƒJ[ƒh‚Ö‚Ì‘—M‚ðƒIƒvƒVƒ‡ƒ“‚Å‘I‘ð‰Â”\‚É•ÏX (-m) -@@i’»ó‹µ‚Ì•\Ž¦‚ðƒIƒvƒVƒ‡ƒ“‚Å‘I‘ð‰Â”\‚É•ÏX (-v) -@@’Ê“d§Œäî•ñ (EMMŽóM—p) ‚ð•\Ž¦‚·‚éƒIƒvƒVƒ‡ƒ“‚ð’ljÁ (-p) - -@@http://www.marumo.ne.jp/db2008_4.htm#9 –”‚Í -@@http://www.marumo.ne.jp/junk/arib_std_b25-0.2.1.lzh - -@E2008, 4/6 - ver. 0.2.0 - -@@EMM ‘Ήž -@@—˜—p’†‚Ì B-CAS ƒJ[ƒh ID Œü‚¯‚Ì EMM ‚ðŒŸo‚µ‚½ê‡AEMM ‚ð -@@B-CAS ƒJ[ƒh‚É“n‚·ˆ—‚ð’ljÁ - -@@ECM ˆ—‚ÌÛ‚É–¢Œ_–ñ‰ž“š‚ª•Ô‚³‚ꂽê‡Aˆ—•‰‰×ŒyŒ¸‚̈×A -@@ˆÈ~A‚»‚Ì PID ‚Ì ECM ‚ð B-CAS ƒJ[ƒh‚ň—‚µ‚È‚¢‚悤‚É•Ï -@@X (EMM ‚ðˆ—‚µ‚½ê‡‚ÍÄ‚Ñ ECM ‚ðˆ—‚·‚é‚悤‚É–ß‚·) - -@@i’»‚ð nn.nn% ‚Ì‘Ž®‚Å•W€ƒGƒ‰[o—Í‚É•\Ž¦‚·‚é‚悤‚É•ÏX -@@ -@@http://www.marumo.ne.jp/db2008_4.htm#6 –”‚Í -@@http://www.marumo.ne.jp/junk/arib_std_b25-0.2.0.lzh - -@E2008, 3/31 - ver. 0.1.9 - -@@MULTI2 ƒ‚ƒWƒ…[ƒ‹‚̃Cƒ“ƒXƒ^ƒ“ƒX‚ª–¢ì»‚Ì󋵂ÅAMULTI2 ‚Ì -@@‹@”\‚ðŒÄ‚Ño‚µ‚Ä—áŠO‚ð”­¶‚³‚¹‚邱‚Æ‚ª‚ ‚Á‚½ƒoƒO‚ðC³ - -@@# ƒpƒbƒ`‚ð’ñ‹Ÿ‚µ‚Ä‚­‚ꂽ•û‚ÉŠ´ŽÓ - -@@http://www.marumo.ne.jp/db2008_3.htm#31 –”‚Í -@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.9.lzh - -@E2008, 3/24 - ver. 0.1.8 - -@@-s ƒIƒvƒVƒ‡ƒ“ (NULL ƒpƒPƒbƒg‚Ìíœ) ‚ð’ljÁ -@@-s 1 ‚Å NULL ƒpƒPƒbƒg‚ðo—̓tƒ@ƒCƒ‹‚É‚Í•Û‘¶‚µ‚È‚­‚È‚é -@@ƒfƒtƒHƒ‹ƒg‚Í -s 0 ‚Ì NULL ƒpƒPƒbƒg•ÛŽ - -@@http://www.marumo.ne.jp/db2008_3.htm#24 –”‚Í -@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.8.lzh - -@E2008, 3/17 - ver. 0.1.7 - -@@arib_std_b25.h ‚Éuextern "C" {v‚ð•Â‚¶‚éƒR[ƒh‚ª‚È‚©‚Á‚½–â‘è -@@(C++ ƒR[ƒh‚©‚ç—˜—p‚·‚éꇂɃRƒ“ƒpƒCƒ‹ƒGƒ‰[‚ð”­¶‚³‚¹‚é) ‚ð -@@C³ - -@@TS ƒpƒPƒbƒg‚Ì’†“r‚ŃXƒgƒŠ[ƒ€‚ªØ‚è‘Ö‚í‚éƒP[ƒX‚Å–â‘肪”­¶‚µ -@@‚É‚­‚­‚È‚é‚悤‚ÉAarib_std_b25.c “à‚̃R[ƒh‚ðC³ - -@@http://www.marumo.ne.jp/db2008_3.htm#17 –”‚Í -@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.7.lzh - -@E2008, 3/16 - ver. 0.1.6 - -@@PMT XV‚ÌÛAECM ŠÖ˜A‚Ì󋵂ª•ÏX (ƒXƒNƒ‰ƒ“ƒuƒ‹ - ƒmƒ“ƒXƒN -@@ƒ‰ƒ“ƒuƒ‹‚ÌØ‚è‘Ö‚¦‚âAECM PID ‚Ì•ÏX“™) ‚ªs‚í‚ê‚Ä‚àA‚»‚ꂪ -@@”½‰f‚³‚ê‚Ä‚¢‚È‚©‚Á‚½–â‘è‚ðC³ - -@@http://www.marumo.ne.jp/db2008_3.htm#16 –”‚Í -@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.6.lzh - -@E2008, 2/14 - -@@readme.txt (‚±‚̃tƒ@ƒCƒ‹) ‚ðC³ -@@ƒ\[ƒXƒR[ƒh‚̃‰ƒCƒZƒ“ƒX‚ɂ‚¢‚Ä‚Ì‹Lq‚ð’ljÁ - -@E2008, 2/12 - ver. 0.1.5 - -@@PMT ‚ÌXV‚É”º‚¢A‚ǂ̃vƒƒOƒ‰ƒ€‚É‚àŠ‘®‚µ‚È‚­‚È‚Á‚½ PID (ƒXƒg -@@ƒŠ[ƒ€) ‚ŃpƒPƒbƒg‚ª‘—M‚³‚ꑱ‚¯‚½ê‡A‚»‚̃pƒPƒbƒg‚Ì•œ†‚ª -@@‚Å‚«‚È‚­‚È‚Á‚Ä‚¢‚½–â‘è‚ðC³ - -@@http://www.marumo.ne.jp/db2008_2.htm#12 –”‚Í -@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.5.lzh - -@E2008, 2/2 - ver. 0.1.4 - -@@ver. 0.1.3 ‚Å‚Ì PMT ˆ—•û–@•ÏX‚É–â‘肪‚ ‚èAPMT ‚ªXV‚³‚ꂽ -@@ê‡A‚»‚êˆÈ~‚ųí‚Ȉ—‚ªs‚¦‚È‚­‚È‚Á‚Ä‚¢‚½ƒoƒO‚ðC³ - -@@B-CAS ƒJ[ƒh‚Æ‚Ì’ÊM‚ŃGƒ‰[‚ª”­¶‚µ‚½ê‡‚̃Šƒgƒ‰ƒCˆ—‚ª‹@”\ -@@‚µ‚Ä‚¢‚È‚©‚Á‚½ƒoƒO‚ðC³ - -@@http://www.marumo.ne.jp/db2008_2.htm#2 –”‚Í -@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.4.lzh - -@E2008, 2/1 - ver. 0.1.3 - -@@—L—¿•ú‘—“™‚Å–¢Œ_–ñó‘Ô‚Ì B-CAS ƒJ[ƒh‚ðŽg‚Á‚½Û‚ÉAŒ®‚ªŽæ“¾‚Å -@@‚«‚Ä‚¢‚È‚¢‚É‚à‚©‚©‚í‚炸AŠÔˆá‚Á‚½Œ®‚Å•œ†‚ð‚µ‚Ä‚¢‚½–â‘è‚ɑΈ - -@@Œ®‚ªŽæ“¾‚Å‚«‚È‚©‚Á‚½ ECM ‚ÉŠÖ˜A•t‚¯‚ç‚ꂽƒXƒgƒŠ[ƒ€‚Å‚Í•œ†‚ð -@@s‚킸AƒXƒNƒ‰ƒ“ƒuƒ‹ƒtƒ‰ƒO‚ðŽc‚µ‚½‚Ü‚Ü“ü—Í‚ð‘f’Ê‚µ‚·‚éŒ`‚É•ÏX -@@Œ®‚ªŽæ“¾‚Å‚«‚È‚¢ ECM ‚ª‘¶Ý‚·‚éê‡AI—¹Žž‚Ƀ`ƒƒƒlƒ‹”Ô†‚Æ -@@B-CAS ƒJ[ƒh‚©‚çŽæ“¾‚Å‚«‚½ƒGƒ‰[”Ô†‚ðŒxƒƒbƒZ[ƒW‚Æ‚µ‚Ä•\Ž¦ -@@‚·‚éŒ`‚É•ÏX - -@@ˆÃ†‰»‚³‚ê‚Ä‚¢‚È‚¢ƒvƒƒOƒ‰ƒ€‚Å—áŠO‚ð”­¶‚³‚¹‚Ä‚¢‚½ƒoƒO‚ðC³ - -@@http://www.marumo.ne.jp/db2008_2.htm#1 –”‚Í -@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.3.lzh - -@E2008, 1/11 - ver. 0.1.2 - -@@ƒfƒWƒ^ƒ‹ BS •ú‘—“™‚ÅAPAT ‚É“o˜^‚³‚ê‚Ä‚¢‚é‚Ì‚ÉAƒXƒgƒŠ[ƒ€“à‚Å -@@PMT ‚ªˆêØoŒ»‚µ‚È‚¢‚±‚Æ‚ª‚ ‚éꇂɑΉž - -@@PMT “à‚Ì‹LqŽq—̈æ 2 ‚É CA_descriptor ‚ª‘¶Ý‚·‚éꇂɑΉž‚·‚é -@@‚½‚ß arib_std_b25.c “à•”‚ł̈—\‘¢‚ð•ÏX - -@@•ÊƒvƒƒOƒ‰ƒ€‚Æ“¯ŽžŽÀs‚·‚邽‚߂ɃXƒ}[ƒgƒJ[ƒh‚Ì”r‘¼§ŒäŽw’è‚ð -@@•ÏX - -@@http://www.marumo.ne.jp/db2008_1.htm#11 –”‚Í -@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.2.lzh - -@E2008, 1/7 - ver. 0.1.1 - -@@ƒZƒNƒVƒ‡ƒ“ (PAT/PMT/ECM “™) ‚ª•¡”‚Ì TS ƒpƒPƒbƒg‚É•ªŠ„‚³‚ê‚Ä‚¢‚é -@@ꇂÉA³í‚Ɉ—‚Å‚«‚È‚©‚Á‚½‚èA—áŠO‚ð”­¶‚ð‚³‚¹‚邱‚Æ‚ª‚ ‚é -@@ƒoƒO‚ðC³ - -@@http://www.marumo.ne.jp/db2008_1.htm#7 –”‚Í -@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.1.lzh - -@E2007, 11/25 - ver. 0.1.0 - -@@ŒöŠJ - -@@http://www.marumo.ne.jp/db2007_b.htm#25 –”‚Í -@@http://www.marumo.ne.jp/junk/arib_std_b25-0.1.0.lzh - diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/src/Makefile --- a/arib25v023/arib25/src/Makefile Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -PREFIX = /usr/local -MAJOR = 0 -MINOR = 2 -REVISION = 3 -VER = $(MAJOR).$(MINOR).$(REVISION) - -DEST_HEADER = $(PREFIX)/include/arib25 - -CC = gcc -PCSC_CFLAGS ?= `pkg-config libpcsclite --cflags` -CPPFLAGS = -Wall $(PCSC_CFLAGS) -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -CFLAGS = -O2 -g -fPIC - -PCSC_LIBS ?= `pkg-config libpcsclite --libs` -LIBS = $(PCSC_LIBS) -lm -LDFLAGS ?= - -OBJS = arib_std_b25.o b_cas_card.o multi2.o ts_section_parser.o -HEADERS = arib_std_b25.h b_cas_card.h portable.h -TARGET_APP = b25 -TARGET_LIB = libarib25.so -TARGETS = $(TARGET_APP) $(TARGET_LIB) -DEPEND = Makefile.dep -SONAME = $(TARGET_LIB).$(MAJOR) - -all: $(TARGETS) - -clean: - rm -f $(OBJS) td.o $(TARGETS) $(DEPEND) - -$(TARGET_APP): $(OBJS) td.o - $(CC) $(LDFLAGS) -o $(TARGET_APP) $(OBJS) td.o $(LIBS) - -$(TARGET_LIB): $(OBJS) - $(CC) $(LDFLAGS) -shared -o $(TARGET_LIB) $(OBJS) $(LIBS) -Wl,-soname,$(SONAME) - -$(DEPEND): - $(CC) -MM $(OBJS:.o=.c) $(CPPFLAGS) > $@ - -install: $(TARGET) install-headers - install -m755 b25 $(PREFIX)/bin - install -m755 $(TARGET_LIB) $(PREFIX)/lib/$(TARGET_LIB).$(VER) - ln -sf $(PREFIX)/lib/$(TARGET_LIB).$(VER) $(PREFIX)/lib/$(TARGET_LIB).$(MAJOR) - ln -sf $(PREFIX)/lib/$(TARGET_LIB).$(MAJOR) $(PREFIX)/lib/$(TARGET_LIB) - ldconfig - -install-headers: - mkdir -p $(DEST_HEADER) - install -m644 $(HEADERS) $(DEST_HEADER) - --include Makefile.dep diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/src/arib_std_b25.c --- a/arib25v023/arib25/src/arib_std_b25.c Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2566 +0,0 @@ -#include -#include - -#include "arib_std_b25.h" -#include "arib_std_b25_error_code.h" -#include "multi2.h" -#include "ts_common_types.h" -#include "ts_section_parser.h" - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - inner structures - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -typedef struct { - int32_t pid; - int32_t type; - void *prev; - void *next; -} TS_STREAM_ELEM; - -typedef struct { - TS_STREAM_ELEM *head; - TS_STREAM_ELEM *tail; - int32_t count; -} TS_STREAM_LIST; - -typedef struct { - - uint8_t *pool; - uint8_t *head; - uint8_t *tail; - int32_t max; - -} TS_WORK_BUFFER; - -typedef struct { - - int32_t phase; - - int32_t program_number; - - int32_t pmt_pid; - TS_SECTION_PARSER *pmt; - - int32_t pcr_pid; - - TS_STREAM_LIST streams; - TS_STREAM_LIST old_strm; - -} TS_PROGRAM; - -typedef struct { - - int32_t ref; - int32_t phase; - - int32_t locked; - - int32_t ecm_pid; - TS_SECTION_PARSER *ecm; - - MULTI2 *m2; - - int32_t unpurchased; - int32_t last_error; - - void *prev; - void *next; - -} DECRYPTOR_ELEM; - -typedef struct { - DECRYPTOR_ELEM *head; - DECRYPTOR_ELEM *tail; - int32_t count; -} DECRYPTOR_LIST; - -typedef struct { - uint32_t ref; - uint32_t type; - int64_t normal_packet; - int64_t undecrypted; - void *target; -} PID_MAP; - -typedef struct { - - int32_t multi2_round; - int32_t strip; - int32_t emm_proc_on; - - int32_t unit_size; - - int32_t sbuf_offset; - - TS_SECTION_PARSER *pat; - TS_SECTION_PARSER *cat; - - TS_STREAM_LIST strm_pool; - - int32_t p_count; - TS_PROGRAM *program; - - DECRYPTOR_LIST decrypt; - - PID_MAP map[0x2000]; - - B_CAS_CARD *bcas; - B_CAS_ID casid; - int32_t ca_system_id; - - int32_t emm_pid; - TS_SECTION_PARSER *emm; - - TS_WORK_BUFFER sbuf; - TS_WORK_BUFFER dbuf; - -} ARIB_STD_B25_PRIVATE_DATA; - -typedef struct { - int64_t card_id; - int32_t associated_information_length; - int32_t protocol_number; - int32_t broadcaster_group_id; - int32_t update_number; - int32_t expiration_date; -} EMM_FIXED_PART; - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - constant values - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -enum TS_STREAM_TYPE { - TS_STREAM_TYPE_11172_2_VIDEO = 0x01, - TS_STREAM_TYPE_13818_2_VIDEO = 0x02, - TS_STREAM_TYPE_11172_3_AUDIO = 0x03, - TS_STREAM_TYPE_13818_3_AUDIO = 0x04, - TS_STREAM_TYPE_13818_1_PRIVATE_SECTIONS = 0x05, - TS_STREAM_TYPE_13818_1_PES_PRIVATE_DATA = 0x06, - TS_STREAM_TYPE_13522_MHEG = 0x07, - TS_STREAM_TYPE_13818_1_DSM_CC = 0x08, - TS_STREAM_TYPE_H_222_1 = 0x09, - TS_STREAM_TYPE_13818_6_TYPE_A = 0x0a, - TS_STREAM_TYPE_13818_6_TYPE_B = 0x0b, - TS_STREAM_TYPE_13818_6_TYPE_C = 0x0c, - TS_STREAM_TYPE_13818_6_TYPE_D = 0x0d, - TS_STREAM_TYPE_13818_1_AUX = 0x0e, - TS_STREAM_TYPE_13818_7_AUDIO_ADTS = 0x0f, - TS_STREAM_TYPE_14496_2_VISUAL = 0x10, - TS_STREAM_TYPE_14496_3_AUDIO_LATM = 0x11, - TS_STREAM_TYPE_14496_1_PES_SL_PACKET = 0x12, - TS_STREAM_TYPE_14496_1_SECTIONS_SL_PACKET = 0x13, - TS_STREAM_TYPE_13818_6_SYNC_DWLOAD_PROTCOL = 0x14, -}; - -enum TS_SECTION_ID { - TS_SECTION_ID_PROGRAM_ASSOCIATION = 0x00, - TS_SECTION_ID_CONDITIONAL_ACCESS = 0x01, - TS_SECTION_ID_PROGRAM_MAP = 0x02, - TS_SECTION_ID_DESCRIPTION = 0x03, - TS_SECTION_ID_14496_SCENE_DESCRIPTION = 0x04, - TS_SECTION_ID_14496_OBJECT_DESCRIPTION = 0x05, - - /* ARIB STD-B10 stuff */ - TS_SECTION_ID_DSM_CC_HEAD = 0x3a, - TS_SECTION_ID_DSM_CC_TAIL = 0x3f, - TS_SECTION_ID_NIT_ACTUAL = 0x40, - TS_SECTION_ID_NIT_OTHER = 0x41, - TS_SECTION_ID_SDT_ACTUAL = 0x42, - TS_SECTION_ID_SDT_OTHER = 0x46, - TS_SECTION_ID_BAT = 0x4a, - TS_SECTION_ID_EIT_ACTUAL_CURRENT = 0x4e, - TS_SECTION_ID_EIT_OTHER_CURRENT = 0x4f, - TS_SECTION_ID_EIT_ACTUAL_SCHEDULE_HEAD = 0x50, - TS_SECTION_ID_EIT_ACTUAL_SCHEDULE_TAIL = 0x5f, - TS_SECTION_ID_EIT_OTHER_SCHEDULE_HEAD = 0x60, - TS_SECTION_ID_EIT_OTHER_SCHEDULE_TAIL = 0x6f, - TS_SECTION_ID_TDT = 0x70, - TS_SECTION_ID_RST = 0x71, - TS_SECTION_ID_ST = 0x72, - TS_SECTION_ID_TOT = 0x73, - TS_SECTION_ID_AIT = 0x74, - TS_SECTION_ID_DIT = 0x7e, - TS_SECTION_ID_SIT = 0x7f, - TS_SECTION_ID_ECM_S = 0x82, - TS_SECTION_ID_ECM = 0x83, - TS_SECTION_ID_EMM_S = 0x84, - TS_SECTION_ID_EMM_MESSAGE = 0x85, - TS_SECTION_ID_DCT = 0xc0, - TS_SECTION_ID_DLT = 0xc1, - TS_SECTION_ID_PCAT = 0xc2, - TS_SECTION_ID_SDTT = 0xc3, - TS_SECTION_ID_BIT = 0xc4, - TS_SECTION_ID_NBIT_BODY = 0xc5, - TS_SECTION_ID_NBIT_REFERENCE = 0xc6, - TS_SECTION_ID_LDT = 0xc7, - TS_SECTION_ID_CDT = 0xc8, - TS_SECTION_ID_LIT = 0xd0, - TS_SECTION_ID_ERT = 0xd1, - TS_SECTION_ID_ITT = 0xd2, -}; - -enum TS_DESCRIPTOR_TAG { - TS_DESCRIPTOR_TAG_VIDEO_STREAM = 0x02, - TS_DESCRIPTOR_TAG_AUDIO_STREAM = 0x03, - TS_DESCRIPTOR_TAG_HIERARCHY = 0x04, - TS_DESCRIPTOR_TAG_REGISTRATION = 0x05, - TS_DESCRIPTOR_TAG_DATA_STREAM_ALIGNMENT = 0x06, - TS_DESCRIPTOR_TAG_TARGET_BACKGROUND_GRID = 0x07, - TS_DESCRIPTOR_TAG_VIDEO_WINDOW = 0x08, - TS_DESCRIPTOR_TAG_CA = 0x09, - TS_DESCRIPTOR_TAG_ISO_639_LANGUAGE = 0x0a, - TS_DESCRIPTOR_TAG_SYSTEM_CLOCK = 0x0b, - TS_DESCRIPTOR_TAG_MULTIPLEX_BUF_UTILIZ = 0x0c, - TS_DESCRIPTOR_TAG_COPYRIGHT = 0x0d, - TS_DESCRIPTOR_TAG_MAXIMUM_BITRATE = 0x0e, - TS_DESCRIPTOR_TAG_PRIVATE_DATA_INDICATOR = 0x0f, - TS_DESCRIPTOR_TAG_SMOOTHING_BUFFER = 0x10, - TS_DESCRIPTOR_TAG_STD = 0x11, - TS_DESCRIPTOR_TAG_IBP = 0x12, - TS_DESCRIPTOR_TAG_MPEG4_VIDEO = 0x1b, - TS_DESCRIPTOR_TAG_MPEG4_AUDIO = 0x1c, - TS_DESCRIPTOR_TAG_IOD = 0x1d, - TS_DESCRIPTOR_TAG_SL = 0x1e, - TS_DESCRIPTOR_TAG_FMC = 0x1f, - TS_DESCRIPTOR_TAG_EXTERNAL_ES_ID = 0x20, - TS_DESCRIPTOR_TAG_MUXCODE = 0x21, - TS_DESCRIPTOR_TAG_FMX_BUFFER_SIZE = 0x22, - TS_DESCRIPTOR_TAG_MULTIPLEX_BUFFER = 0x23, - TS_DESCRIPTOR_TAG_AVC_VIDEO = 0x28, - TS_DESCRIPTOR_TAG_AVC_TIMING_HRD = 0x2a, - - /* ARIB STD-B10 stuff */ - TS_DESCRIPTOR_TAG_NETWORK_NAME = 0x40, - TS_DESCRIPTOR_TAG_SERVICE_LIST = 0x41, - TS_DESCRIPTOR_TAG_STUFFING = 0x42, - TS_DESCRIPTOR_TAG_SATELLITE_DELIVERY_SYS = 0x43, - TS_DESCRIPTOR_TAG_CABLE_DISTRIBUTION = 0x44, - TS_DESCRIPTOR_TAG_BOUNQUET_NAME = 0x47, - TS_DESCRIPTOR_TAG_SERVICE = 0x48, - TS_DESCRIPTOR_TAG_COUNTRY_AVAILABILITY = 0x49, - TS_DESCRIPTOR_TAG_LINKAGE = 0x4a, - TS_DESCRIPTOR_TAG_NVOD_REFERENCE = 0x4b, - TS_DESCRIPTOR_TAG_TIME_SHIFTED_SERVICE = 0x4c, - TS_DESCRIPTOR_TAG_SHORT_EVENT = 0x4d, - TS_DESCRIPTOR_TAG_EXTENDED_EVENT = 0x4e, - TS_DESCRIPTOR_TAG_TIME_SHIFTED_EVENT = 0x4f, - TS_DESCRIPTOR_TAG_COMPONENT = 0x50, - TS_DESCRIPTOR_TAG_MOSAIC = 0x51, - TS_DESCRIPTOR_TAG_STREAM_IDENTIFIER = 0x52, - TS_DESCRIPTOR_TAG_CA_IDENTIFIER = 0x53, - TS_DESCRIPTOR_TAG_CONTENT = 0x54, - TS_DESCRIPTOR_TAG_PARENTAL_RATING = 0x55, - TS_DESCRIPTOR_TAG_LOCAL_TIME_OFFSET = 0x58, - TS_DESCRIPTOR_TAG_PARTIAL_TRANSPORT_STREAM = 0x63, - TS_DESCRIPTOR_TAG_HIERARCHICAL_TRANSMISSION = 0xc0, - TS_DESCRIPTOR_TAG_DIGITAL_COPY_CONTROL = 0xc1, - TS_DESCRIPTOR_TAG_NETWORK_IDENTIFICATION = 0xc2, - TS_DESCRIPTOR_TAG_PARTIAL_TRANSPORT_TIME = 0xc3, - TS_DESCRIPTOR_TAG_AUDIO_COMPONENT = 0xc4, - TS_DESCRIPTOR_TAG_HYPERLINK = 0xc5, - TS_DESCRIPTOR_TAG_TARGET_REGION = 0xc6, - TS_DESCRIPTOR_TAG_DATA_COTENT = 0xc7, - TS_DESCRIPTOR_TAG_VIDEO_DECODE_CONTROL = 0xc8, - TS_DESCRIPTOR_TAG_DOWNLOAD_CONTENT = 0xc9, - TS_DESCRIPTOR_TAG_CA_EMM_TS = 0xca, - TS_DESCRIPTOR_TAG_CA_CONTRACT_INFORMATION = 0xcb, - TS_DESCRIPTOR_TAG_CA_SERVICE = 0xcc, - TS_DESCRIPTOR_TAG_TS_INFORMATION = 0xcd, - TS_DESCRIPTOR_TAG_EXTENDED_BROADCASTER = 0xce, - TS_DESCRIPTOR_TAG_LOGO_TRANSMISSION = 0xcf, - TS_DESCRIPTOR_TAG_BASIC_LOCAL_EVENT = 0xd0, - TS_DESCRIPTOR_TAG_REFERENCE = 0xd1, - TS_DESCRIPTOR_TAG_NODE_RELATION = 0xd2, - TS_DESCRIPTOR_TAG_SHORT_NODE_INFORMATION = 0xd3, - TS_DESCRIPTOR_TAG_STC_REFERENCE = 0xd4, - TS_DESCRIPTOR_TAG_SERIES = 0xd5, - TS_DESCRIPTOR_TAG_EVENT_GROUP = 0xd6, - TS_DESCRIPTOR_TAG_SI_PARAMETER = 0xd7, - TS_DESCRIPTOR_TAG_BROADCASTER_NAME = 0xd8, - TS_DESCRIPTOR_TAG_COMPONENT_GROUP = 0xd9, - TS_DESCRIPTOR_TAG_SI_PRIME_TS = 0xda, - TS_DESCRIPTOR_TAG_BOARD_INFORMATION = 0xdb, - TS_DESCRIPTOR_TAG_LDT_LINKAGE = 0xdc, - TS_DESCRIPTOR_TAG_CONNECTED_TRANSMISSION = 0xdd, - TS_DESCRIPTOR_TAG_CONTENT_AVAILABILITY = 0xde, - TS_DESCRIPTOR_TAG_VALUE_EXTENSION = 0xdf, - TS_DESCRIPTOR_TAG_SERVICE_GROUP = 0xe0, - TS_DESCRIPTOR_TAG_CARUSEL_COMPOSITE = 0xf7, - TS_DESCRIPTOR_TAG_CONDITIONAL_PLAYBACK = 0xf8, - TS_DESCRIPTOR_TAG_CABLE_TS_DIVISSION = 0xf9, - TS_DESCRIPTOR_TAG_TERRESTRIAL_DELIVERY_SYS = 0xfa, - TS_DESCRIPTOR_TAG_PARTIAL_RECEPTION = 0xfb, - TS_DESCRIPTOR_TAG_EMERGENCY_INFOMATION = 0xfc, - TS_DESCRIPTOR_TAG_DATA_COMPONENT = 0xfd, - TS_DESCRIPTOR_TAG_SYSTEM_MANAGEMENT = 0xfe, -}; - -enum PID_MAP_TYPE { - PID_MAP_TYPE_UNKNOWN = 0x0000, - PID_MAP_TYPE_PAT = 0x0100, - PID_MAP_TYPE_PMT = 0x0200, - PID_MAP_TYPE_NIT = 0x0300, - PID_MAP_TYPE_PCR = 0x0400, - PID_MAP_TYPE_ECM = 0x0500, - PID_MAP_TYPE_EMM = 0x0600, - PID_MAP_TYPE_EIT = 0x0700, - PID_MAP_TYPE_CAT = 0x0800, - PID_MAP_TYPE_OTHER = 0xff00, -}; - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - function prottypes (interface method) - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -static void release_arib_std_b25(void *std_b25); -static int set_multi2_round_arib_std_b25(void *std_b25, int32_t round); -static int set_strip_arib_std_b25(void *std_b25, int32_t strip); -static int set_emm_proc_arib_std_b25(void *std_b25, int32_t on); -static int set_b_cas_card_arib_std_b25(void *std_b25, B_CAS_CARD *bcas); -static int reset_arib_std_b25(void *std_b25); -static int flush_arib_std_b25(void *std_b25); -static int put_arib_std_b25(void *std_b25, ARIB_STD_B25_BUFFER *buf); -static int get_arib_std_b25(void *std_b25, ARIB_STD_B25_BUFFER *buf); -static int get_program_count_arib_std_b25(void *std_b25); -static int get_program_info_arib_std_b25(void *std_b25, ARIB_STD_B25_PROGRAM_INFO *info, int idx); - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - global function implementation - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -ARIB_STD_B25 *create_arib_std_b25() -{ - int n; - - ARIB_STD_B25 *r; - ARIB_STD_B25_PRIVATE_DATA *prv; - - n = sizeof(ARIB_STD_B25_PRIVATE_DATA); - n += sizeof(ARIB_STD_B25); - - prv = (ARIB_STD_B25_PRIVATE_DATA *)calloc(1, n); - if(prv == NULL){ - return NULL; - } - - prv->multi2_round = 4; - - r = (ARIB_STD_B25 *)(prv+1); - r->private_data = prv; - - r->release = release_arib_std_b25; - r->set_multi2_round = set_multi2_round_arib_std_b25; - r->set_strip = set_strip_arib_std_b25; - r->set_emm_proc = set_emm_proc_arib_std_b25; - r->set_b_cas_card = set_b_cas_card_arib_std_b25; - r->reset = reset_arib_std_b25; - r->flush = flush_arib_std_b25; - r->put = put_arib_std_b25; - r->get = get_arib_std_b25; - r->get_program_count = get_program_count_arib_std_b25; - r->get_program_info = get_program_info_arib_std_b25; - - return r; -} - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - function prottypes (private method) - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -static ARIB_STD_B25_PRIVATE_DATA *private_data(void *std_b25); -static void teardown(ARIB_STD_B25_PRIVATE_DATA *prv); -static int select_unit_size(ARIB_STD_B25_PRIVATE_DATA *prv); -static int find_pat(ARIB_STD_B25_PRIVATE_DATA *prv); -static int proc_pat(ARIB_STD_B25_PRIVATE_DATA *prv); -static int check_pmt_complete(ARIB_STD_B25_PRIVATE_DATA *prv); -static int find_pmt(ARIB_STD_B25_PRIVATE_DATA *prv); -static int proc_pmt(ARIB_STD_B25_PRIVATE_DATA *prv, TS_PROGRAM *pgrm); -static int32_t find_ca_descriptor_pid(uint8_t *head, uint8_t *tail, int32_t ca_system_id); -static int32_t add_ecm_stream(ARIB_STD_B25_PRIVATE_DATA *prv, TS_STREAM_LIST *list, int32_t ecm_pid); -static int check_ecm_complete(ARIB_STD_B25_PRIVATE_DATA *prv); -static int find_ecm(ARIB_STD_B25_PRIVATE_DATA *prv); -static int proc_ecm(DECRYPTOR_ELEM *dec, B_CAS_CARD *bcas, int32_t multi2_round); -static int proc_arib_std_b25(ARIB_STD_B25_PRIVATE_DATA *prv); - -static int proc_cat(ARIB_STD_B25_PRIVATE_DATA *prv); -static int proc_emm(ARIB_STD_B25_PRIVATE_DATA *prv); - -static void release_program(ARIB_STD_B25_PRIVATE_DATA *prv, TS_PROGRAM *pgrm); - -static void unref_stream(ARIB_STD_B25_PRIVATE_DATA *prv, int32_t pid); - -static DECRYPTOR_ELEM *set_decryptor(ARIB_STD_B25_PRIVATE_DATA *prv, int32_t pid); -static void remove_decryptor(ARIB_STD_B25_PRIVATE_DATA *prv, DECRYPTOR_ELEM *dec); -static DECRYPTOR_ELEM *select_active_decryptor(DECRYPTOR_ELEM *a, DECRYPTOR_ELEM *b, int32_t pid); -static void bind_stream_decryptor(ARIB_STD_B25_PRIVATE_DATA *prv, int32_t pid, DECRYPTOR_ELEM *dec); -static void unlock_all_decryptor(ARIB_STD_B25_PRIVATE_DATA *prv); - -static TS_STREAM_ELEM *get_stream_list_head(TS_STREAM_LIST *list); -static TS_STREAM_ELEM *find_stream_list_elem(TS_STREAM_LIST *list, int32_t pid); -static TS_STREAM_ELEM *create_stream_elem(int32_t pid, int32_t type); -static void put_stream_list_tail(TS_STREAM_LIST *list, TS_STREAM_ELEM *elem); -static void clear_stream_list(TS_STREAM_LIST *list); - -static int reserve_work_buffer(TS_WORK_BUFFER *buf, int32_t size); -static int append_work_buffer(TS_WORK_BUFFER *buf, uint8_t *data, int32_t size); -static void reset_work_buffer(TS_WORK_BUFFER *buf); -static void release_work_buffer(TS_WORK_BUFFER *buf); - -static void extract_ts_header(TS_HEADER *dst, uint8_t *src); -static void extract_emm_fixed_part(EMM_FIXED_PART *dst, uint8_t *src); - -static uint8_t *resync(uint8_t *head, uint8_t *tail, int32_t unit); -static uint8_t *resync_force(uint8_t *head, uint8_t *tail, int32_t unit); - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - interface method implementation - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -static void release_arib_std_b25(void *std_b25) -{ - ARIB_STD_B25_PRIVATE_DATA *prv; - - prv = private_data(std_b25); - if(prv == NULL){ - return; - } - - teardown(prv); - free(prv); -} - -static int set_multi2_round_arib_std_b25(void *std_b25, int32_t round) -{ - ARIB_STD_B25_PRIVATE_DATA *prv; - - prv = private_data(std_b25); - if(prv == NULL){ - return ARIB_STD_B25_ERROR_INVALID_PARAM; - } - - prv->multi2_round = round; - - return 0; -} - -static int set_strip_arib_std_b25(void *std_b25, int32_t strip) -{ - ARIB_STD_B25_PRIVATE_DATA *prv; - - prv = private_data(std_b25); - if(prv == NULL){ - return ARIB_STD_B25_ERROR_INVALID_PARAM; - } - - prv->strip = strip; - - return 0; -} - -static int set_emm_proc_arib_std_b25(void *std_b25, int32_t on) -{ - ARIB_STD_B25_PRIVATE_DATA *prv; - - prv = private_data(std_b25); - if(prv == NULL){ - return ARIB_STD_B25_ERROR_INVALID_PARAM; - } - - prv->emm_proc_on = on; - - return 0; -} - -static int set_b_cas_card_arib_std_b25(void *std_b25, B_CAS_CARD *bcas) -{ - int n; - B_CAS_INIT_STATUS is; - ARIB_STD_B25_PRIVATE_DATA *prv; - - prv = private_data(std_b25); - if(prv == NULL){ - return ARIB_STD_B25_ERROR_INVALID_PARAM; - } - - prv->bcas = bcas; - if(prv->bcas != NULL){ - n = prv->bcas->get_init_status(bcas, &is); - if(n < 0){ - return ARIB_STD_B25_ERROR_INVALID_B_CAS_STATUS; - } - prv->ca_system_id = is.ca_system_id; - n = prv->bcas->get_id(prv->bcas, &(prv->casid)); - if(n < 0){ - return ARIB_STD_B25_ERROR_INVALID_B_CAS_STATUS; - } - } - - return 0; -} - -static int reset_arib_std_b25(void *std_b25) -{ - ARIB_STD_B25_PRIVATE_DATA *prv; - - prv = private_data(std_b25); - if(prv == NULL){ - return ARIB_STD_B25_ERROR_INVALID_PARAM; - } - - teardown(prv); - - return 0; -} - -static int flush_arib_std_b25(void *std_b25) -{ - int r; - int m,n; - - int32_t crypt; - int32_t unit; - int32_t pid; - - uint8_t *p; - uint8_t *curr; - uint8_t *tail; - - TS_HEADER hdr; - DECRYPTOR_ELEM *dec; - TS_PROGRAM *pgrm; - - ARIB_STD_B25_PRIVATE_DATA *prv; - - prv = private_data(std_b25); - if(prv == NULL){ - return ARIB_STD_B25_ERROR_INVALID_PARAM; - } - - if(prv->unit_size < 188){ - r = select_unit_size(prv); - if(r < 0){ - return r; - } - } - - r = proc_arib_std_b25(prv); - if(r < 0){ - return r; - } - - unit = prv->unit_size; - curr = prv->sbuf.head; - tail = prv->sbuf.tail; - - m = prv->dbuf.tail - prv->dbuf.head; - n = tail - curr; - if(!reserve_work_buffer(&(prv->dbuf), m+n)){ - return ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; - } - - r = 0; - - while( (curr+188) <= tail ){ - - if(curr[0] != 0x47){ - p = resync_force(curr, tail, unit); - if(p == NULL){ - goto LAST; - } - curr = p; - } - - extract_ts_header(&hdr, curr); - crypt = hdr.transport_scrambling_control; - pid = hdr.pid; - - if( (pid == 0x1fff) && (prv->strip) ){ - goto NEXT; - } - - p = curr+4; - if(hdr.adaptation_field_control & 0x02){ - p += (p[0]+1); - } - n = 188 - (p-curr); - if( (n < 1) && ((n < 0) || (hdr.adaptation_field_control & 0x01)) ){ - /* broken packet */ - curr += 1; - continue; - } - - if( (crypt != 0) && - (hdr.adaptation_field_control & 0x01) ){ - - if(prv->map[pid].type == PID_MAP_TYPE_OTHER){ - dec = (DECRYPTOR_ELEM *)(prv->map[pid].target); - }else{ - dec = NULL; - } - - if( (dec != NULL) && (dec->m2 != NULL) ){ - m = dec->m2->decrypt(dec->m2, crypt, p, n); - if(m < 0){ - r = ARIB_STD_B25_ERROR_DECRYPT_FAILURE; - goto LAST; - } - curr[3] &= 0x3f; - prv->map[pid].normal_packet += 1; - }else{ - prv->map[pid].undecrypted += 1; - } - }else{ - prv->map[pid].normal_packet += 1; - } - - if(!append_work_buffer(&(prv->dbuf), curr, 188)){ - r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; - goto LAST; - } - - if(prv->map[pid].type == PID_MAP_TYPE_ECM){ - dec = (DECRYPTOR_ELEM *)(prv->map[pid].target); - if( (dec == NULL) || (dec->ecm == NULL) ){ - /* this code will never execute */ - r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; - goto LAST; - } - m = dec->ecm->put(dec->ecm, &hdr, p, n); - if(m < 0){ - r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; - goto LAST; - } - m = dec->ecm->get_count(dec->ecm); - if(m < 0){ - r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; - goto LAST; - } - if(m == 0){ - goto NEXT; - } - r = proc_ecm(dec, prv->bcas, prv->multi2_round); - if(r < 0){ - goto LAST; - } - }else if(prv->map[pid].type == PID_MAP_TYPE_PMT){ - pgrm = (TS_PROGRAM *)(prv->map[pid].target); - if( (pgrm == NULL) || (pgrm->pmt == NULL) ){ - /* this code will never execute */ - r = ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; - goto LAST; - } - m = pgrm->pmt->put(pgrm->pmt, &hdr, p, n); - if(m < 0){ - r = ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; - goto LAST; - } - m = pgrm->pmt->get_count(pgrm->pmt); - if(m < 0){ - r = ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; - goto LAST; - } - if(m == 0){ - goto NEXT; - } - r = proc_pmt(prv, pgrm); - if(r < 0){ - goto LAST; - } - }else if(prv->map[pid].type == PID_MAP_TYPE_EMM){ - if( prv->emm_proc_on == 0){ - goto NEXT; - } - if( prv->emm == NULL ){ - prv->emm = create_ts_section_parser(); - if(prv->emm == NULL){ - r = ARIB_STD_B25_ERROR_EMM_PARSE_FAILURE; - goto LAST; - } - } - m = prv->emm->put(prv->emm, &hdr, p, n); - if(m < 0){ - r = ARIB_STD_B25_ERROR_EMM_PARSE_FAILURE; - goto LAST; - } - m = prv->emm->get_count(prv->emm); - if(m < 0){ - r = ARIB_STD_B25_ERROR_EMM_PARSE_FAILURE; - goto LAST; - } - if(m == 0){ - goto NEXT; - } - r = proc_emm(prv); - if(r < 0){ - goto LAST; - } - }else if(pid == 0x0001){ - if( prv->cat == NULL ){ - prv->cat = create_ts_section_parser(); - if(prv->cat == NULL){ - r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; - goto LAST; - } - } - m = prv->cat->put(prv->cat, &hdr, p, n); - if(m < 0){ - r = ARIB_STD_B25_ERROR_CAT_PARSE_FAILURE; - goto LAST; - } - m = prv->cat->get_count(prv->cat); - if(m < 0){ - r = ARIB_STD_B25_ERROR_CAT_PARSE_FAILURE; - goto LAST; - } - if(m == 0){ - goto NEXT; - } - r = proc_cat(prv); - if(r < 0){ - goto LAST; - } - }else if(pid == 0x0000){ - if( prv->pat == NULL ){ - prv->pat = create_ts_section_parser(); - if(prv->pat == NULL){ - r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; - goto LAST; - } - } - m = prv->pat->put(prv->pat, &hdr, p, n); - if(m < 0){ - r = ARIB_STD_B25_ERROR_PAT_PARSE_FAILURE; - goto LAST; - } - m = prv->pat->get_count(prv->pat); - if(m < 0){ - r = ARIB_STD_B25_ERROR_PAT_PARSE_FAILURE; - goto LAST; - } - if(m == 0){ - goto NEXT; - } - r = proc_pat(prv); - if(r < 0){ - goto LAST; - } - } - - NEXT: - curr += unit; - } - -LAST: - - m = curr - prv->sbuf.head; - n = tail - curr; - if( (n < 1024) || (m > (prv->sbuf.max/2) ) ){ - p = prv->sbuf.pool; - memcpy(p, curr, n); - prv->sbuf.head = p; - prv->sbuf.tail = p+n; - }else{ - prv->sbuf.head = curr; - } - - return r; -} - -static int put_arib_std_b25(void *std_b25, ARIB_STD_B25_BUFFER *buf) -{ - int32_t n; - - ARIB_STD_B25_PRIVATE_DATA *prv; - - prv = private_data(std_b25); - if( (prv == NULL) || (buf == NULL) ){ - return ARIB_STD_B25_ERROR_INVALID_PARAM; - } - - if(!append_work_buffer(&(prv->sbuf), buf->data, buf->size)){ - return ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; - } - - if(prv->unit_size < 188){ - n = select_unit_size(prv); - if(n < 0){ - return n; - } - if(prv->unit_size < 188){ - /* need more data */ - return 0; - } - } - - if(prv->p_count < 1){ - n = find_pat(prv); - if(n < 0){ - return n; - } - if(prv->p_count < 1){ - if(prv->sbuf_offset < (16*1024*1024)){ - /* need more data */ - return 0; - }else{ - /* exceed sbuf limit */ - return ARIB_STD_B25_ERROR_NO_PAT_IN_HEAD_16M; - } - } - prv->sbuf_offset = 0; - } - - if(!check_pmt_complete(prv)){ - n = find_pmt(prv); - if(n < 0){ - return n; - } - if(!check_pmt_complete(prv)){ - if(prv->sbuf_offset < (32*1024*1024)){ - /* need more data */ - return 0; - }else{ - /* exceed sbuf limit */ - return ARIB_STD_B25_ERROR_NO_PMT_IN_HEAD_32M; - } - } - prv->sbuf_offset = 0; - } - - if(!check_ecm_complete(prv)){ - n = find_ecm(prv); - if(n < 0){ - return n; - } - if(!check_ecm_complete(prv)){ - if(prv->sbuf_offset < (32*1024*1024)){ - /* need more data */ - return 0; - }else{ - /* exceed sbuf limit */ - return ARIB_STD_B25_ERROR_NO_ECM_IN_HEAD_32M; - } - } - prv->sbuf_offset = 0; - } - - return proc_arib_std_b25(prv); -} - -static int get_arib_std_b25(void *std_b25, ARIB_STD_B25_BUFFER *buf) -{ - ARIB_STD_B25_PRIVATE_DATA *prv; - prv = private_data(std_b25); - if( (prv == NULL) || (buf == NULL) ){ - return ARIB_STD_B25_ERROR_INVALID_PARAM; - } - - buf->data = prv->dbuf.head; - buf->size = prv->dbuf.tail - prv->dbuf.head; - - reset_work_buffer(&(prv->dbuf)); - - return 0; -} - -static int get_program_count_arib_std_b25(void *std_b25) -{ - ARIB_STD_B25_PRIVATE_DATA *prv; - - prv = private_data(std_b25); - if(prv == NULL){ - return ARIB_STD_B25_ERROR_INVALID_PARAM; - } - - return prv->p_count; -} - -static int get_program_info_arib_std_b25(void *std_b25, ARIB_STD_B25_PROGRAM_INFO *info, int idx) -{ - ARIB_STD_B25_PRIVATE_DATA *prv; - - TS_PROGRAM *pgrm; - - TS_STREAM_ELEM *strm; - DECRYPTOR_ELEM *dec; - - int32_t pid; - - prv = private_data(std_b25); - if( (prv == NULL) || (info == NULL) || (idx < 0) || (idx >= prv->p_count) ){ - return ARIB_STD_B25_ERROR_INVALID_PARAM; - } - - pgrm = prv->program + idx; - - memset(info, 0, sizeof(ARIB_STD_B25_PROGRAM_INFO)); - - info->program_number = pgrm->program_number; - - pid = pgrm->pmt_pid; - info->total_packet_count += prv->map[pid].normal_packet; - info->total_packet_count += prv->map[pid].undecrypted; - info->undecrypted_packet_count += prv->map[pid].undecrypted; - - pid = pgrm->pcr_pid; - if( (pid != 0) && (pid != 0x1fff) ){ - info->total_packet_count += prv->map[pid].normal_packet; - info->total_packet_count += prv->map[pid].undecrypted; - info->undecrypted_packet_count += prv->map[pid].undecrypted; - } - - strm = pgrm->streams.head; - while(strm != NULL){ - pid = strm->pid; - if(prv->map[pid].type == PID_MAP_TYPE_ECM){ - dec = (DECRYPTOR_ELEM *)(prv->map[pid].target); - info->ecm_unpurchased_count += dec->unpurchased; - info->last_ecm_error_code = dec->last_error; - } - info->total_packet_count += prv->map[pid].normal_packet; - info->total_packet_count += prv->map[pid].undecrypted; - info->undecrypted_packet_count += prv->map[pid].undecrypted; - strm = (TS_STREAM_ELEM *)(strm->next); - } - - return 0; -} - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - private method implementation - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -static ARIB_STD_B25_PRIVATE_DATA *private_data(void *std_b25) -{ - ARIB_STD_B25 *p; - ARIB_STD_B25_PRIVATE_DATA *r; - - p = (ARIB_STD_B25 *)std_b25; - if(p == NULL){ - return NULL; - } - - r = (ARIB_STD_B25_PRIVATE_DATA *)p->private_data; - if( ((void *)(r+1)) != ((void *)p) ){ - return NULL; - } - - return r; -} - -static void teardown(ARIB_STD_B25_PRIVATE_DATA *prv) -{ - int i; - - prv->unit_size = 0; - prv->sbuf_offset = 0; - - if(prv->pat != NULL){ - prv->pat->release(prv->pat); - prv->pat = NULL; - } - if(prv->cat != NULL){ - prv->cat->release(prv->cat); - prv->cat = NULL; - } - - if(prv->program != NULL){ - for(i=0;ip_count;i++){ - release_program(prv, prv->program+i); - } - free(prv->program); - prv->program = NULL; - } - prv->p_count = 0; - - clear_stream_list(&(prv->strm_pool)); - - while(prv->decrypt.head != NULL){ - remove_decryptor(prv, prv->decrypt.head); - } - - memset(prv->map, 0, sizeof(prv->map)); - - prv->emm_pid = 0; - if(prv->emm != NULL){ - prv->emm->release(prv->emm); - prv->emm = NULL; - } - - release_work_buffer(&(prv->sbuf)); - release_work_buffer(&(prv->dbuf)); -} - -static int select_unit_size(ARIB_STD_B25_PRIVATE_DATA *prv) -{ - int i; - int m,n,w; - int count[320-188]; - - unsigned char *head; - unsigned char *buf; - unsigned char *tail; - - head = prv->sbuf.head; - tail = prv->sbuf.tail; - - buf = head; - memset(count, 0, sizeof(count)); - - // 1st step, count up 0x47 interval - while( (buf+188) < tail ){ - if(buf[0] != 0x47){ - buf += 1; - continue; - } - m = 320; - if( buf+m > tail ){ - m = tail-buf; - } - for(i=188;iunit_size = n; - - return 0; -} - -static int find_pat(ARIB_STD_B25_PRIVATE_DATA *prv) -{ - int r; - int n,size; - - int32_t unit; - - uint8_t *p; - uint8_t *curr; - uint8_t *tail; - - TS_HEADER hdr; - - r = 0; - unit = prv->unit_size; - curr = prv->sbuf.head + prv->sbuf_offset; - tail = prv->sbuf.tail; - - while( (curr+unit) < tail ){ - if( (curr[0] != 0x47) || (curr[unit] != 0x47) ){ - p = resync(curr, tail, unit); - if(p == NULL){ - goto LAST; - } - curr = p; - } - extract_ts_header(&hdr, curr); - if(hdr.pid == 0x0000){ - - p = curr+4; - if(hdr.adaptation_field_control & 0x02){ - p += (p[0]+1); - } - size = 188 - (p-curr); - if(size < 1){ - goto NEXT; - } - - if(prv->pat == NULL){ - prv->pat = create_ts_section_parser(); - if(prv->pat == NULL){ - return ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; - } - } - - n = prv->pat->put(prv->pat, &hdr, p, size); - if(n < 0){ - r = ARIB_STD_B25_ERROR_PAT_PARSE_FAILURE; - curr += unit; - goto LAST; - } - n = prv->pat->get_count(prv->pat); - if(n < 0){ - r = ARIB_STD_B25_ERROR_PAT_PARSE_FAILURE; - curr += unit; - goto LAST; - } - if(n > 0){ - curr += unit; - goto LAST; - } - } - NEXT: - curr += unit; - } - -LAST: - prv->sbuf_offset = curr - prv->sbuf.head; - - if( (prv->pat != NULL) && (prv->pat->get_count(prv->pat) > 0) ){ - r = proc_pat(prv); - } - - return r; -} - -static int proc_pat(ARIB_STD_B25_PRIVATE_DATA *prv) -{ - int r; - int i,n; - int len; - int count; - - int32_t program_number; - int32_t pid; - - uint8_t *head; - uint8_t *tail; - - TS_PROGRAM *work; - TS_SECTION sect; - - r = 0; - memset(§, 0, sizeof(sect)); - - n = prv->pat->get(prv->pat, §); - if(n < 0){ - r = ARIB_STD_B25_ERROR_PAT_PARSE_FAILURE; - goto LAST; - } - - if(sect.hdr.table_id != TS_SECTION_ID_PROGRAM_ASSOCIATION){ - r = ARIB_STD_B25_WARN_TS_SECTION_ID_MISSMATCH; - goto LAST; - } - - len = (sect.tail - sect.data) - 4; - - count = len / 4; - work = (TS_PROGRAM *)calloc(count, sizeof(TS_PROGRAM)); - if(work == NULL){ - r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; - goto LAST; - } - - if(prv->program != NULL){ - for(i=0;ip_count;i++){ - release_program(prv, prv->program+i); - } - free(prv->program); - prv->program = NULL; - } - prv->p_count = 0; - memset(&(prv->map), 0, sizeof(prv->map)); - - head = sect.data; - tail = sect.tail-4; - - i = 0; - while( (head+4) <= tail ){ - program_number = ((head[0] << 8) | head[1]); - pid = ((head[2] << 8) | head[3]) & 0x1fff; - if(program_number != 0){ - work[i].program_number = program_number; - work[i].pmt_pid = pid; - work[i].pmt = create_ts_section_parser(); - if(work[i].pmt == NULL){ - r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; - break; - } - prv->map[pid].type = PID_MAP_TYPE_PMT; - prv->map[pid].target = work+i; - i += 1; - } - head += 4; - } - - prv->program = work; - prv->p_count = i; - - prv->map[0x0000].ref = 1; - prv->map[0x0000].type = PID_MAP_TYPE_PAT; - prv->map[0x0000].target = NULL; - -LAST: - if(sect.raw != NULL){ - n = prv->pat->ret(prv->pat, §); - if( (n < 0) && (r == 0) ){ - r = ARIB_STD_B25_ERROR_PAT_PARSE_FAILURE; - } - } - - return r; -} - -static int check_pmt_complete(ARIB_STD_B25_PRIVATE_DATA *prv) -{ - int i,n; - int num[3]; - - memset(num, 0, sizeof(num)); - - for(i=0;ip_count;i++){ - n = prv->program[i].phase; - if(n < 0){ - n = 0; - }else if(n > 2){ - n = 2; - } - num[n] += 1; - } - - if(num[2] > 0){ - return 1; - } - - if(num[0] > 0){ - return 0; - } - - return 1; -} - -static int find_pmt(ARIB_STD_B25_PRIVATE_DATA *prv) -{ - int r; - int n,size; - - int32_t unit; - - uint8_t *p; - uint8_t *curr; - uint8_t *tail; - - TS_HEADER hdr; - TS_PROGRAM *pgrm; - - r = 0; - unit = prv->unit_size; - curr = prv->sbuf.head + prv->sbuf_offset; - tail = prv->sbuf.tail; - - while( (curr+unit) < tail ){ - - if( (curr[0] != 0x47) || (curr[unit] != 0x47) ){ - p = resync(curr, tail, unit); - if(p == NULL){ - goto LAST; - } - curr = p; - } - - extract_ts_header(&hdr, curr); - - if(prv->map[hdr.pid].type != PID_MAP_TYPE_PMT){ - goto NEXT; - } - pgrm = (TS_PROGRAM *)(prv->map[hdr.pid].target); - if(pgrm == NULL){ - goto NEXT; - } - - if(pgrm->phase == 0){ - - p = curr + 4; - if(hdr.adaptation_field_control & 0x02){ - p += (p[0]+1); - } - size = 188 - (p-curr); - if(size < 1){ - goto NEXT; - } - - if(pgrm->pmt == NULL){ - /* this code will never execute */ - r = ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; - curr += unit; - goto LAST; - } - - n = pgrm->pmt->put(pgrm->pmt, &hdr, p, size); - if(n < 0){ - r = ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; - curr += unit; - goto LAST; - } - n = pgrm->pmt->get_count(pgrm->pmt); - if(n < 0){ - r =ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; - curr += unit; - goto LAST; - } - if(n == 0){ - goto NEXT; - } - r = proc_pmt(prv, pgrm); - if(r < 0){ - curr += unit; - goto LAST; - } - if(r > 0){ - /* broken or unexpected section data */ - goto NEXT; - } - pgrm->phase = 1; - if(check_pmt_complete(prv)){ - curr += unit; - goto LAST; - } - }else{ - pgrm->phase = 2; - curr += unit; - goto LAST; - } - - NEXT: - curr += unit; - } - -LAST: - prv->sbuf_offset = curr - prv->sbuf.head; - - return r; -} - -static int proc_pmt(ARIB_STD_B25_PRIVATE_DATA *prv, TS_PROGRAM *pgrm) -{ - int r; - - int n; - int length; - - uint8_t *head; - uint8_t *tail; - - int32_t ecm_pid; - int32_t pid; - int32_t type; - - TS_SECTION sect; - - DECRYPTOR_ELEM *dec[2]; - DECRYPTOR_ELEM *dw; - - TS_STREAM_ELEM *strm; - - r = 0; - dec[0] = NULL; - memset(§, 0, sizeof(sect)); - - n = pgrm->pmt->get(pgrm->pmt, §); - if(n < 0){ - r = ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; - goto LAST; - } - if(sect.hdr.table_id != TS_SECTION_ID_PROGRAM_MAP){ - r = ARIB_STD_B25_WARN_TS_SECTION_ID_MISSMATCH; - goto LAST; - } - - head = sect.data; - tail = sect.tail-4; - - pgrm->pcr_pid = ((head[0] << 8) | head[1]) & 0x1fff; - length = ((head[2] << 8) | head[3]) & 0x0fff; - head += 4; - if(head+length > tail){ - r = ARIB_STD_B25_WARN_BROKEN_TS_SECTION; - goto LAST; - } - - /* find major ecm_pid and regist decryptor */ - ecm_pid = find_ca_descriptor_pid(head, head+length, prv->ca_system_id); - if( (ecm_pid != 0) && (ecm_pid != 0x1fff) ){ - dec[0] = set_decryptor(prv, ecm_pid); - if(dec[0] == NULL){ - r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; - goto LAST; - } - dec[0]->ref += 1; - } - head += length; - - /* unref old stream entries */ - while( (strm = get_stream_list_head(&(pgrm->old_strm))) != NULL ){ - unref_stream(prv, strm->pid); - memset(strm, 0, sizeof(TS_STREAM_ELEM)); - put_stream_list_tail(&(prv->strm_pool), strm); - } - - /* save current streams */ - memcpy(&(pgrm->old_strm), &(pgrm->streams), sizeof(TS_STREAM_LIST)); - memset(&(pgrm->streams), 0, sizeof(TS_STREAM_LIST)); - - /* add current stream entries */ - if( (ecm_pid != 0) && (ecm_pid != 0x1fff) ){ - if(!add_ecm_stream(prv, &(pgrm->streams), ecm_pid)){ - r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; - goto LAST; - } - } - - while( head+4 < tail ){ - - type = head[0]; - pid = ((head[1] << 8) | head[2]) & 0x1fff; - length = ((head[3] << 8) | head[4]) & 0x0fff; - head += 5; - ecm_pid = find_ca_descriptor_pid(head, head+length, prv->ca_system_id); - head += length; - - if( (ecm_pid != 0) && (ecm_pid != 0x1fff) ){ - dec[1] = set_decryptor(prv, ecm_pid); - if(dec[1] == NULL){ - r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; - goto LAST; - } - if(!add_ecm_stream(prv, &(pgrm->streams), ecm_pid)){ - r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; - goto LAST; - } - }else{ - dec[1] = NULL; - } - - strm = get_stream_list_head(&(prv->strm_pool)); - if( strm == NULL ){ - strm = create_stream_elem(pid, type); - if(strm == NULL){ - r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; - goto LAST; - } - }else{ - strm->pid = pid; - strm->type = type; - } - - prv->map[pid].type = PID_MAP_TYPE_OTHER; - prv->map[pid].ref += 1; - - dw = select_active_decryptor(dec[0], dec[1], ecm_pid); - bind_stream_decryptor(prv, pid, dw); - - put_stream_list_tail(&(pgrm->streams), strm); - } - -LAST: - if( dec[0] != NULL ){ - dec[0]->ref -= 1; - if( dec[0]->ref < 1 ){ - remove_decryptor(prv, dec[0]); - dec[0] = NULL; - } - } - - if(sect.raw != NULL){ - n = pgrm->pmt->ret(pgrm->pmt, §); - if( (n < 0) && (r == 0) ){ - return ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; - } - } - - return 0; -} - -static int32_t find_ca_descriptor_pid(uint8_t *head, uint8_t *tail, int32_t ca_system_id) -{ - uint32_t ca_pid; - uint32_t ca_sys_id; - - uint32_t tag; - uint32_t len; - - while(head+1 < tail){ - tag = head[0]; - len = head[1]; - head += 2; - if( (tag == 0x09) && /* CA_descriptor */ - (len >= 4) && - (head+len <= tail) ){ - ca_sys_id = ((head[0] << 8) | head[1]); - ca_pid = ((head[2] << 8) | head[3]) & 0x1fff; - if(ca_sys_id == ca_system_id){ - return ca_pid; - } - } - head += len; - } - - return 0; -} - -static int add_ecm_stream(ARIB_STD_B25_PRIVATE_DATA *prv, TS_STREAM_LIST *list, int32_t ecm_pid) -{ - TS_STREAM_ELEM *strm; - - strm = find_stream_list_elem(list, ecm_pid); - if(strm != NULL){ - // ECM is already registered - return 1; - } - - strm = get_stream_list_head(&(prv->strm_pool)); - if(strm == NULL){ - strm = create_stream_elem(ecm_pid, PID_MAP_TYPE_ECM); - if(strm == NULL){ - return 0; - } - }else{ - strm->pid = ecm_pid; - strm->type = PID_MAP_TYPE_ECM; - } - - put_stream_list_tail(list, strm); - prv->map[ecm_pid].ref += 1; - - return 1; -} - -static int check_ecm_complete(ARIB_STD_B25_PRIVATE_DATA *prv) -{ - int n,num[3]; - DECRYPTOR_ELEM *e; - - memset(num, 0, sizeof(num)); - - e = prv->decrypt.head; - while( e != NULL ){ - n = e->phase; - if(n < 0){ - n = 0; - }else if(n > 2){ - n = 2; - } - num[n] += 1; - e = (DECRYPTOR_ELEM *)(e->next); - } - - if(num[2] > 0){ - return 1; - } - - if(num[0] > 0){ - return 0; - } - - return 1; -} - -static int find_ecm(ARIB_STD_B25_PRIVATE_DATA *prv) -{ - int r; - int n,size; - - int32_t unit; - - uint8_t *p; - uint8_t *curr; - uint8_t *tail; - - TS_HEADER hdr; - DECRYPTOR_ELEM *dec; - - r = 0; - unit = prv->unit_size; - curr = prv->sbuf.head + prv->sbuf_offset; - tail = prv->sbuf.tail; - - while( (curr+unit) < tail ){ - if( (curr[0] != 0x47) || (curr[unit] != 0x47) ){ - p = resync(curr, tail, unit); - if(p == NULL){ - goto LAST; - } - curr = p; - } - extract_ts_header(&hdr, curr); - if(prv->map[hdr.pid].type != PID_MAP_TYPE_ECM){ - goto NEXT; - } - dec = (DECRYPTOR_ELEM *)(prv->map[hdr.pid].target); - if(dec == NULL){ - goto NEXT; - } - - if(dec->phase == 0){ - - p = curr + 4; - if(hdr.adaptation_field_control & 0x02){ - p += (p[0]+1); - } - size = 188 - (p-curr); - if(size < 1){ - goto NEXT; - } - - if(dec->ecm == NULL){ - /* this code will never execute */ - r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; - curr += unit; - goto LAST; - } - - n = dec->ecm->put(dec->ecm, &hdr, p, size); - if(n < 0){ - r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; - curr += unit; - goto LAST; - } - n = dec->ecm->get_count(dec->ecm); - if(n < 0){ - r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; - curr += unit; - goto LAST; - } - if(n == 0){ - goto NEXT; - } - - r = proc_ecm(dec, prv->bcas, prv->multi2_round); - if(r < 0){ - curr += unit; - goto LAST; - } - if( (r > 0) && (r != ARIB_STD_B25_WARN_UNPURCHASED_ECM) ){ - /* broken or unexpected section data */ - goto NEXT; - } - - dec->phase = 1; - if(check_ecm_complete(prv)){ - curr += unit; - goto LAST; - } - - }else{ - dec->phase = 2; - curr += unit; - goto LAST; - } - - NEXT: - curr += unit; - } - -LAST: - prv->sbuf_offset = curr - prv->sbuf.head; - - return r; -} - -static int proc_ecm(DECRYPTOR_ELEM *dec, B_CAS_CARD *bcas, int32_t multi2_round) -{ - int r,n; - int length; - - uint8_t *p; - - B_CAS_INIT_STATUS is; - B_CAS_ECM_RESULT res; - - TS_SECTION sect; - - r = 0; - memset(§, 0, sizeof(sect)); - - if(bcas == NULL){ - r = ARIB_STD_B25_ERROR_EMPTY_B_CAS_CARD; - goto LAST; - } - - n = dec->ecm->get(dec->ecm, §); - if(n < 0){ - r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; - goto LAST; - } - if(sect.hdr.table_id != TS_SECTION_ID_ECM_S){ - r = ARIB_STD_B25_WARN_TS_SECTION_ID_MISSMATCH; - goto LAST; - } - - if(dec->locked){ - /* previous ECM has returned unpurchased - skip this pid for B-CAS card load reduction */ - dec->unpurchased += 1; - r = ARIB_STD_B25_WARN_UNPURCHASED_ECM; - goto LAST; - } - - length = (sect.tail - sect.data) - 4; - p = sect.data; - - r = bcas->proc_ecm(bcas, &res, p, length); - if(r < 0){ - if(dec->m2 != NULL){ - dec->m2->clear_scramble_key(dec->m2); - } - r = ARIB_STD_B25_ERROR_ECM_PROC_FAILURE; - goto LAST; - } - - if( (res.return_code != 0x0800) && - (res.return_code != 0x0400) && - (res.return_code != 0x0200) ){ - /* return_code is not equal "purchased" */ - if(dec->m2 != NULL){ - dec->m2->release(dec->m2); - dec->m2 = NULL; - } - dec->unpurchased += 1; - dec->last_error = res.return_code; - dec->locked += 1; - r = ARIB_STD_B25_WARN_UNPURCHASED_ECM; - goto LAST; - } - - if(dec->m2 == NULL){ - dec->m2 = create_multi2(); - if(dec->m2 == NULL){ - return ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; - } - r = bcas->get_init_status(bcas, &is); - if(r < 0){ - return ARIB_STD_B25_ERROR_INVALID_B_CAS_STATUS; - } - dec->m2->set_system_key(dec->m2, is.system_key); - dec->m2->set_init_cbc(dec->m2, is.init_cbc); - dec->m2->set_round(dec->m2, multi2_round); - } - - dec->m2->set_scramble_key(dec->m2, res.scramble_key); - -LAST: - if(sect.raw != NULL){ - n = dec->ecm->ret(dec->ecm, §); - if( (n < 0) && (r == 0) ){ - r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; - } - } - - return r; -} - -static int proc_arib_std_b25(ARIB_STD_B25_PRIVATE_DATA *prv) -{ - int r; - int m,n; - - int32_t crypt; - int32_t unit; - int32_t pid; - - uint8_t *p; - uint8_t *curr; - uint8_t *tail; - - TS_HEADER hdr; - DECRYPTOR_ELEM *dec; - TS_PROGRAM *pgrm; - - unit = prv->unit_size; - curr = prv->sbuf.head; - tail = prv->sbuf.tail; - - m = prv->dbuf.tail - prv->dbuf.head; - n = tail - curr; - if(!reserve_work_buffer(&(prv->dbuf), m+n)){ - return ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; - } - - r = 0; - - while( (curr+unit) < tail ){ - - if( (curr[0] != 0x47) || (curr[unit] != 0x47) ){ - p = resync(curr, tail, unit); - if(p == NULL){ - goto LAST; - } - curr = p; - } - - extract_ts_header(&hdr, curr); - crypt = hdr.transport_scrambling_control; - pid = hdr.pid; - - if( (pid == 0x1fff) && (prv->strip) ){ - /* strip null(padding) stream */ - goto NEXT; - } - - p = curr+4; - if(hdr.adaptation_field_control & 0x02){ - p += (p[0]+1); - } - n = 188 - (p-curr); - if( (n < 1) && ((n < 0) || (hdr.adaptation_field_control & 0x01)) ){ - /* broken packet */ - curr += 1; - continue; - } - - if( (crypt != 0) && - (hdr.adaptation_field_control & 0x01) ){ - - if(prv->map[pid].type == PID_MAP_TYPE_OTHER){ - dec = (DECRYPTOR_ELEM *)(prv->map[pid].target); - }else if( (prv->map[pid].type == 0) && - (prv->decrypt.count == 1) ){ - dec = prv->decrypt.head; - }else{ - dec = NULL; - } - - if( (dec != NULL) && (dec->m2 != NULL) ){ - m = dec->m2->decrypt(dec->m2, crypt, p, n); - if(m < 0){ - r = ARIB_STD_B25_ERROR_DECRYPT_FAILURE; - goto LAST; - } - curr[3] &= 0x3f; - prv->map[pid].normal_packet += 1; - }else{ - prv->map[pid].undecrypted += 1; - } - }else{ - prv->map[pid].normal_packet += 1; - } - - if(!append_work_buffer(&(prv->dbuf), curr, 188)){ - r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; - goto LAST; - } - - if(prv->map[pid].type == PID_MAP_TYPE_ECM){ - dec = (DECRYPTOR_ELEM *)(prv->map[pid].target); - if( (dec == NULL) || (dec->ecm == NULL) ){ - /* this code will never execute */ - r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; - goto LAST; - } - m = dec->ecm->put(dec->ecm, &hdr, p, n); - if(m < 0){ - r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; - goto LAST; - } - m = dec->ecm->get_count(dec->ecm); - if(m < 0){ - r = ARIB_STD_B25_ERROR_ECM_PARSE_FAILURE; - goto LAST; - } - if(m == 0){ - goto NEXT; - } - r = proc_ecm(dec, prv->bcas, prv->multi2_round); - if(r < 0){ - goto LAST; - } - }else if(prv->map[pid].type == PID_MAP_TYPE_PMT){ - pgrm = (TS_PROGRAM *)(prv->map[pid].target); - if( (pgrm == NULL) || (pgrm->pmt == NULL) ){ - /* this code will never execute */ - r = ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; - goto LAST; - } - m = pgrm->pmt->put(pgrm->pmt, &hdr, p, n); - if(m < 0){ - r = ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; - goto LAST; - } - m = pgrm->pmt->get_count(pgrm->pmt); - if(m < 0){ - r = ARIB_STD_B25_ERROR_PMT_PARSE_FAILURE; - goto LAST; - } - if(m == 0){ - goto NEXT; - } - r = proc_pmt(prv, pgrm); - if(r < 0){ - goto LAST; - } - }else if(prv->map[pid].type == PID_MAP_TYPE_EMM){ - if( prv->emm_proc_on == 0){ - goto NEXT; - } - if( prv->emm == NULL ){ - prv->emm = create_ts_section_parser(); - if(prv->emm == NULL){ - r = ARIB_STD_B25_ERROR_EMM_PARSE_FAILURE; - goto LAST; - } - } - m = prv->emm->put(prv->emm, &hdr, p, n); - if(m < 0){ - r = ARIB_STD_B25_ERROR_EMM_PARSE_FAILURE; - goto LAST; - } - m = prv->emm->get_count(prv->emm); - if(m < 0){ - r = ARIB_STD_B25_ERROR_EMM_PARSE_FAILURE; - goto LAST; - } - if(m == 0){ - goto NEXT; - } - r = proc_emm(prv); - if(r < 0){ - goto LAST; - } - }else if(pid == 0x0001){ - if( prv->cat == NULL ){ - prv->cat = create_ts_section_parser(); - if(prv->cat == NULL){ - r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; - goto LAST; - } - } - m = prv->cat->put(prv->cat, &hdr, p, n); - if(m < 0){ - r = ARIB_STD_B25_ERROR_CAT_PARSE_FAILURE; - goto LAST; - } - m = prv->cat->get_count(prv->cat); - if(m < 0){ - r = ARIB_STD_B25_ERROR_CAT_PARSE_FAILURE; - goto LAST; - } - if(m == 0){ - goto NEXT; - } - r = proc_cat(prv); - if(r < 0){ - goto LAST; - } - }else if(pid == 0x0000){ - if( prv->pat == NULL ){ - prv->pat = create_ts_section_parser(); - if(prv->pat == NULL){ - r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY; - goto LAST; - } - } - m = prv->pat->put(prv->pat, &hdr, p, n); - if(m < 0){ - r = ARIB_STD_B25_ERROR_PAT_PARSE_FAILURE; - goto LAST; - } - m = prv->pat->get_count(prv->pat); - if(m < 0){ - r = ARIB_STD_B25_ERROR_PAT_PARSE_FAILURE; - goto LAST; - } - if(m == 0){ - goto NEXT; - } - r = proc_pat(prv); - goto LAST; - } - - NEXT: - curr += unit; - } - -LAST: - m = curr - prv->sbuf.head; - n = tail - curr; - if( (n < 1024) || (m > (prv->sbuf.max/2) ) ){ - p = prv->sbuf.pool; - memcpy(p, curr, n); - prv->sbuf.head = p; - prv->sbuf.tail = p+n; - }else{ - prv->sbuf.head = curr; - } - - return r; -} - -static int proc_cat(ARIB_STD_B25_PRIVATE_DATA *prv) -{ - int r; - int n; - int emm_pid; - - TS_SECTION sect; - - r = 0; - memset(§, 0, sizeof(sect)); - - n = prv->cat->get(prv->cat, §); - if(n < 0){ - r = ARIB_STD_B25_ERROR_CAT_PARSE_FAILURE; - goto LAST; - } - - if(sect.hdr.table_id != TS_SECTION_ID_CONDITIONAL_ACCESS){ - r = ARIB_STD_B25_WARN_TS_SECTION_ID_MISSMATCH; - goto LAST; - } - - emm_pid = find_ca_descriptor_pid(sect.data, sect.tail-4, prv->ca_system_id); - if( (emm_pid != 0x0000) && (emm_pid != 0x1fff) ){ - if( (prv->map[emm_pid].target != NULL) && - (prv->map[emm_pid].type == PID_MAP_TYPE_OTHER) ){ - DECRYPTOR_ELEM *dec; - dec = (DECRYPTOR_ELEM *)(prv->map[emm_pid].target); - dec->ref -= 1; - if(dec->ref < 1){ - remove_decryptor(prv, dec); - } - } - prv->emm_pid = emm_pid; - prv->map[emm_pid].ref = 1; - prv->map[emm_pid].type = PID_MAP_TYPE_EMM; - prv->map[emm_pid].target = NULL; - } - - prv->map[0x0001].ref = 1; - prv->map[0x0001].type = PID_MAP_TYPE_CAT; - prv->map[0x0001].target = NULL; - -LAST: - - if(sect.raw != NULL){ - n = prv->cat->ret(prv->cat, §); - if( (n < 0) && (r == 0) ){ - r = ARIB_STD_B25_ERROR_CAT_PARSE_FAILURE; - } - } - - return r; -} - -static int proc_emm(ARIB_STD_B25_PRIVATE_DATA *prv) -{ - int r; - int i,j,n; - - int len; - - uint8_t *head; - uint8_t *tail; - - TS_SECTION sect; - EMM_FIXED_PART emm_hdr; - - r = 0; - memset(§, 0, sizeof(sect)); - - if(prv->bcas == NULL){ - r = ARIB_STD_B25_ERROR_EMPTY_B_CAS_CARD; - goto LAST; - } - - while( (n = prv->emm->get_count(prv->emm)) > 0 ){ - - n = prv->emm->get(prv->emm, §); - if(n < 0){ - r = ARIB_STD_B25_ERROR_CAT_PARSE_FAILURE; - goto LAST; - } - - if(sect.hdr.table_id == TS_SECTION_ID_EMM_MESSAGE){ - /* EMM_MESSAGE is not supported */ - goto NEXT; - }else if(sect.hdr.table_id != TS_SECTION_ID_EMM_S){ - r = ARIB_STD_B25_WARN_TS_SECTION_ID_MISSMATCH; - goto LAST; - } - - head = sect.data; - tail = sect.tail - 4; - - i = 0; - while( (head+13) <= tail ){ - - extract_emm_fixed_part(&emm_hdr, head); - len = emm_hdr.associated_information_length+7; - if( (head+len) > tail ){ - /* broken EMM element */ - goto NEXT; - } - - for(j=0;jcasid.count;j++){ - if(prv->casid.data[j] == emm_hdr.card_id){ - n = prv->bcas->proc_emm(prv->bcas, head, len); - if(n < 0){ - r = ARIB_STD_B25_ERROR_EMM_PROC_FAILURE; - goto LAST; - } - unlock_all_decryptor(prv); - } - } - - head += len; - } - - NEXT: - if(sect.raw != NULL){ - n = prv->emm->ret(prv->emm, §); - if( (n < 0) && (r == 0) ){ - r = ARIB_STD_B25_ERROR_EMM_PARSE_FAILURE; - goto LAST; - } - memset(§, 0, sizeof(sect)); - } - } - -LAST: - if(sect.raw != NULL){ - n = prv->emm->ret(prv->emm, §); - if( (n < 0) && (r == 0) ){ - r = ARIB_STD_B25_ERROR_EMM_PARSE_FAILURE; - } - } - - return r; -} - -static void release_program(ARIB_STD_B25_PRIVATE_DATA *prv, TS_PROGRAM *pgrm) -{ - int32_t pid; - TS_STREAM_ELEM *strm; - - pid = pgrm->pmt_pid; - - if(pgrm->pmt != NULL){ - pgrm->pmt->release(pgrm->pmt); - pgrm->pmt = NULL; - } - - while( (strm = get_stream_list_head(&(pgrm->old_strm))) != NULL ){ - unref_stream(prv, strm->pid); - memset(strm, 0, sizeof(TS_STREAM_ELEM)); - put_stream_list_tail(&(prv->strm_pool), strm); - } - - while( (strm = get_stream_list_head(&(pgrm->streams))) != NULL ){ - unref_stream(prv, strm->pid); - memset(strm, 0, sizeof(TS_STREAM_ELEM)); - put_stream_list_tail(&(prv->strm_pool), strm); - } - - prv->map[pid].type = PID_MAP_TYPE_UNKNOWN; - prv->map[pid].ref = 0; - prv->map[pid].target = NULL; -} - -static void unref_stream(ARIB_STD_B25_PRIVATE_DATA *prv, int32_t pid) -{ - DECRYPTOR_ELEM *dec; - - prv->map[pid].ref -= 1; - if( prv->map[pid].ref < 1 ){ - if( (prv->map[pid].target != NULL) && - (prv->map[pid].type == PID_MAP_TYPE_OTHER) ){ - dec = (DECRYPTOR_ELEM *)(prv->map[pid].target); - dec->ref -= 1; - if(dec->ref < 1){ - remove_decryptor(prv, dec); - } - } - prv->map[pid].type = PID_MAP_TYPE_UNKNOWN; - prv->map[pid].ref = 0; - prv->map[pid].target = NULL; - } -} - -static DECRYPTOR_ELEM *set_decryptor(ARIB_STD_B25_PRIVATE_DATA *prv, int32_t pid) -{ - DECRYPTOR_ELEM *r; - - r = NULL; - if(prv->map[pid].type == PID_MAP_TYPE_ECM){ - r = (DECRYPTOR_ELEM *)(prv->map[pid].target); - if(r != NULL){ - return r; - } - } - r = (DECRYPTOR_ELEM *)calloc(1, sizeof(DECRYPTOR_ELEM)); - if(r == NULL){ - return NULL; - } - r->ecm_pid = pid; - r->ecm = create_ts_section_parser(); - if(r->ecm == NULL){ - free(r); - return NULL; - } - - if(prv->decrypt.tail != NULL){ - r->prev = prv->decrypt.tail; - r->next = NULL; - prv->decrypt.tail->next = r; - prv->decrypt.tail = r; - prv->decrypt.count += 1; - }else{ - r->prev = NULL; - r->next = NULL; - prv->decrypt.head = r; - prv->decrypt.tail = r; - prv->decrypt.count = 1; - } - - if( (prv->map[pid].type == PID_MAP_TYPE_OTHER) && - (prv->map[pid].target != NULL) ){ - DECRYPTOR_ELEM *dec; - dec = (DECRYPTOR_ELEM *)(prv->map[pid].target); - dec->ref -= 1; - if(dec->ref < 1){ - remove_decryptor(prv, dec); - } - } - - prv->map[pid].type = PID_MAP_TYPE_ECM; - prv->map[pid].target = r; - - return r; -} - -static void remove_decryptor(ARIB_STD_B25_PRIVATE_DATA *prv, DECRYPTOR_ELEM *dec) -{ - int32_t pid; - - DECRYPTOR_ELEM *prev; - DECRYPTOR_ELEM *next; - - pid = dec->ecm_pid; - if( (prv->map[pid].type == PID_MAP_TYPE_ECM) && - (prv->map[pid].target == ((void *)dec)) ){ - prv->map[pid].type = PID_MAP_TYPE_UNKNOWN; - prv->map[pid].target = NULL; - } - - prev = (DECRYPTOR_ELEM *)(dec->prev); - next = (DECRYPTOR_ELEM *)(dec->next); - if(prev != NULL){ - prev->next = next; - }else{ - prv->decrypt.head = next; - } - if(next != NULL){ - next->prev = prev; - }else{ - prv->decrypt.tail = prev; - } - prv->decrypt.count -= 1; - - if(dec->ecm != NULL){ - dec->ecm->release(dec->ecm); - dec->ecm = NULL; - } - - if(dec->m2 != NULL){ - dec->m2->release(dec->m2); - dec->m2 = NULL; - } - - free(dec); -} - -static DECRYPTOR_ELEM *select_active_decryptor(DECRYPTOR_ELEM *a, DECRYPTOR_ELEM *b, int32_t pid) -{ - if( b != NULL ){ - return b; - } - if( pid == 0x1fff ){ - return NULL; - } - return a; -} - -static void bind_stream_decryptor(ARIB_STD_B25_PRIVATE_DATA *prv, int32_t pid, DECRYPTOR_ELEM *dec) -{ - DECRYPTOR_ELEM *old; - - old = (DECRYPTOR_ELEM *)(prv->map[pid].target); - if(old == dec){ - /* already binded - do nothing */ - return; - } - - if(old != NULL){ - old->ref -= 1; - if(old->ref == 0){ - remove_decryptor(prv, old); - } - prv->map[pid].target = NULL; - } - - if(dec != NULL){ - prv->map[pid].target = dec; - dec->ref += 1; - } -} - -static void unlock_all_decryptor(ARIB_STD_B25_PRIVATE_DATA *prv) -{ - DECRYPTOR_ELEM *e; - - e = prv->decrypt.head; - while(e != NULL){ - e->locked = 0; - e = (DECRYPTOR_ELEM *)(e->next); - } -} - -static TS_STREAM_ELEM *get_stream_list_head(TS_STREAM_LIST *list) -{ - TS_STREAM_ELEM *r; - - r = list->head; - if(r == NULL){ - return NULL; - } - - list->head = (TS_STREAM_ELEM *)(r->next); - if(list->head == NULL){ - list->tail = NULL; - list->count = 0; - }else{ - list->head->prev = NULL; - list->count -= 1; - } - - r->prev = NULL; - r->next = NULL; - - return r; -} - -static TS_STREAM_ELEM *find_stream_list_elem(TS_STREAM_LIST *list, int32_t pid) -{ - TS_STREAM_ELEM *r; - - r = list->head; - while(r != NULL){ - if(r->pid == pid){ - break; - } - r = (TS_STREAM_ELEM *)(r->next); - } - - return r; -} - -static TS_STREAM_ELEM *create_stream_elem(int32_t pid, int32_t type) -{ - TS_STREAM_ELEM *r; - - r = (TS_STREAM_ELEM *)calloc(1, sizeof(TS_STREAM_ELEM)); - if(r == NULL){ - return NULL; - } - - r->pid = pid; - r->type = type; - - return r; -} - -static void put_stream_list_tail(TS_STREAM_LIST *list, TS_STREAM_ELEM *elem) -{ - if(list->tail != NULL){ - elem->prev = list->tail; - elem->next = NULL; - list->tail->next = elem; - list->tail = elem; - list->count += 1; - }else{ - elem->prev = NULL; - elem->next = NULL; - list->head = elem; - list->tail = elem; - list->count = 1; - } -} - -static void clear_stream_list(TS_STREAM_LIST *list) -{ - TS_STREAM_ELEM *p,*n; - - p = list->head; - while(p != NULL){ - n = (TS_STREAM_ELEM *)(p->next); - free(p); - p = n; - } - - list->head = NULL; - list->tail = NULL; - list->count = 0; -} - -static int reserve_work_buffer(TS_WORK_BUFFER *buf, int32_t size) -{ - int m,n; - uint8_t *p; - - if(buf->max >= size){ - return 1; - } - - if(buf->max < 512){ - n = 512; - }else{ - n = buf->max * 2; - } - - while(n < size){ - n += n; - } - - p = (uint8_t *)malloc(n); - if(p == NULL){ - return 0; - } - - m = 0; - if(buf->pool != NULL){ - m = buf->tail - buf->head; - if(m > 0){ - memcpy(p, buf->head, m); - } - free(buf->pool); - buf->pool = NULL; - } - - buf->pool = p; - buf->head = p; - buf->tail = p+m; - buf->max = n; - - return 1; -} - -static int append_work_buffer(TS_WORK_BUFFER *buf, uint8_t *data, int32_t size) -{ - int m; - - if(size < 1){ - /* ignore - do nothing */ - return 1; - } - - m = buf->tail - buf->pool; - - if( (m+size) > buf->max ){ - if(!reserve_work_buffer(buf, m+size)){ - return 0; - } - } - - memcpy(buf->tail, data, size); - buf->tail += size; - - return 1; -} - -static void reset_work_buffer(TS_WORK_BUFFER *buf) -{ - buf->head = buf->pool; - buf->tail = buf->pool; -} - -static void release_work_buffer(TS_WORK_BUFFER *buf) -{ - if(buf->pool != NULL){ - free(buf->pool); - } - buf->pool = NULL; - buf->head = NULL; - buf->tail = NULL; - buf->max = 0; -} - -static void extract_ts_header(TS_HEADER *dst, uint8_t *src) -{ - dst->sync = src[0]; - dst->transport_error_indicator = (src[1] >> 7) & 0x01; - dst->payload_unit_start_indicator = (src[1] >> 6) & 0x01; - dst->transport_priority = (src[1] >> 5) & 0x01; - dst->pid = ((src[1] & 0x1f) << 8) | src[2]; - dst->transport_scrambling_control = (src[3] >> 6) & 0x03; - dst->adaptation_field_control = (src[3] >> 4) & 0x03; - dst->continuity_counter = src[3] & 0x0f; -} - -static void extract_emm_fixed_part(EMM_FIXED_PART *dst, uint8_t *src) -{ - int i; - - dst->card_id = 0; - for(i=0;i<6;i++){ - dst->card_id = (dst->card_id << 8) | src[i]; - } - - dst->associated_information_length = src[ 6]; - dst->protocol_number = src[ 7]; - dst->broadcaster_group_id = src[ 8]; - dst->update_number = (src[ 9]<<8)|src[10]; - dst->expiration_date = (src[11]<<8)|src[12]; -} - -static uint8_t *resync(uint8_t *head, uint8_t *tail, int32_t unit_size) -{ - int i; - unsigned char *buf; - - buf = head; - tail -= unit_size * 8; - while( buf <= tail ){ - if(buf[0] == 0x47){ - for(i=1;i<8;i++){ - if(buf[unit_size*i] != 0x47){ - break; - } - } - if(i == 8){ - return buf; - } - } - buf += 1; - } - - return NULL; -} - -static uint8_t *resync_force(uint8_t *head, uint8_t *tail, int32_t unit_size) -{ - int i,n; - unsigned char *buf; - - buf = head; - while( buf <= (tail-188) ){ - if(buf[0] == 0x47){ - n = (tail - buf) / unit_size; - if(n == 0){ - return buf; - } - for(i=1;i -#include - -#include - -#if defined(WIN32) - #include -#endif -#include - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - inner structures - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -typedef struct { - - SCARDCONTEXT mng; - SCARDHANDLE card; - - uint8_t *pool; - char *reader; - - uint8_t *sbuf; - uint8_t *rbuf; - - B_CAS_INIT_STATUS stat; - - B_CAS_ID id; - int32_t id_max; - - B_CAS_PWR_ON_CTRL_INFO pwc; - int32_t pwc_max; - -} B_CAS_CARD_PRIVATE_DATA; - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - constant values - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -static const uint8_t INITIAL_SETTING_CONDITIONS_CMD[] = { - 0x90, 0x30, 0x00, 0x00, 0x00, -}; - -static const uint8_t CARD_ID_INFORMATION_ACQUIRE_CMD[] = { - 0x90, 0x32, 0x00, 0x00, 0x00, -}; - -static const uint8_t POWER_ON_CONTROL_INFORMATION_REQUEST_CMD[] = { - 0x90, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, -}; - -static const uint8_t ECM_RECEIVE_CMD_HEADER[] = { - 0x90, 0x34, 0x00, 0x00, -}; - -static const uint8_t EMM_RECEIVE_CMD_HEADER[] = { - 0x90, 0x36, 0x00, 0x00, -}; - -#define B_CAS_BUFFER_MAX (4*1024) - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - function prottypes (interface method) - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -static void release_b_cas_card(void *bcas); -static int init_b_cas_card(void *bcas); -static int get_init_status_b_cas_card(void *bcas, B_CAS_INIT_STATUS *stat); -static int get_id_b_cas_card(void *bcas, B_CAS_ID *dst); -static int get_pwr_on_ctrl_b_cas_card(void *bcas, B_CAS_PWR_ON_CTRL_INFO *dst); -static int proc_ecm_b_cas_card(void *bcas, B_CAS_ECM_RESULT *dst, uint8_t *src, int len); -static int proc_emm_b_cas_card(void *bcas, uint8_t *src, int len); - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - global function implementation - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -B_CAS_CARD *create_b_cas_card() -{ - int n; - - B_CAS_CARD *r; - B_CAS_CARD_PRIVATE_DATA *prv; - - n = sizeof(B_CAS_CARD) + sizeof(B_CAS_CARD_PRIVATE_DATA); - prv = (B_CAS_CARD_PRIVATE_DATA *)calloc(1, n); - if(prv == NULL){ - return NULL; - } - - r = (B_CAS_CARD *)(prv+1); - - r->private_data = prv; - - r->release = release_b_cas_card; - r->init = init_b_cas_card; - r->get_init_status = get_init_status_b_cas_card; - r->get_id = get_id_b_cas_card; - r->get_pwr_on_ctrl = get_pwr_on_ctrl_b_cas_card; - r->proc_ecm = proc_ecm_b_cas_card; - r->proc_emm = proc_emm_b_cas_card; - - return r; -} - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - function prottypes (private method) - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -static B_CAS_CARD_PRIVATE_DATA *private_data(void *bcas); -static void teardown(B_CAS_CARD_PRIVATE_DATA *prv); -static int change_id_max(B_CAS_CARD_PRIVATE_DATA *prv, int max); -static int change_pwc_max(B_CAS_CARD_PRIVATE_DATA *prv, int max); -static int connect_card(B_CAS_CARD_PRIVATE_DATA *prv, const char *reader_name); -static void extract_power_on_ctrl_response(B_CAS_PWR_ON_CTRL *dst, uint8_t *src); -static void extract_mjd(int *yy, int *mm, int *dd, int mjd); -static int setup_ecm_receive_command(uint8_t *dst, uint8_t *src, int len); -static int setup_emm_receive_command(uint8_t *dst, uint8_t *src, int len); -static int32_t load_be_uint16(uint8_t *p); -static int64_t load_be_uint48(uint8_t *p); - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - interface method implementation - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -static void release_b_cas_card(void *bcas) -{ - B_CAS_CARD_PRIVATE_DATA *prv; - - prv = private_data(bcas); - if(prv == NULL){ - /* do nothing */ - return; - } - - teardown(prv); - free(prv); -} - -static int init_b_cas_card(void *bcas) -{ - int m; - LONG ret; - DWORD len; - - B_CAS_CARD_PRIVATE_DATA *prv; - - prv = private_data(bcas); - if(prv == NULL){ - return B_CAS_CARD_ERROR_INVALID_PARAMETER; - } - - teardown(prv); - - ret = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &(prv->mng)); - if(ret != SCARD_S_SUCCESS){ - return B_CAS_CARD_ERROR_NO_SMART_CARD_READER; - } - - ret = SCardListReaders(prv->mng, NULL, NULL, &len); - if(ret != SCARD_S_SUCCESS){ - return B_CAS_CARD_ERROR_NO_SMART_CARD_READER; - } - len += 256; - - m = len + (2*B_CAS_BUFFER_MAX) + (sizeof(int64_t)*16) + (sizeof(B_CAS_PWR_ON_CTRL)*16); - prv->pool = (uint8_t *)malloc(m); - if(prv->pool == NULL){ - return B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY; - } - - prv->reader = (char *)(prv->pool); - prv->sbuf = prv->pool + len; - prv->rbuf = prv->sbuf + B_CAS_BUFFER_MAX; - prv->id.data = (int64_t *)(prv->rbuf + B_CAS_BUFFER_MAX); - prv->id_max = 16; - prv->pwc.data = (B_CAS_PWR_ON_CTRL *)(prv->id.data + prv->id_max); - prv->pwc_max = 16; - - ret = SCardListReaders(prv->mng, NULL, prv->reader, &len); - if(ret != SCARD_S_SUCCESS){ - return B_CAS_CARD_ERROR_NO_SMART_CARD_READER; - } - - while( prv->reader[0] != 0 ){ - if(connect_card(prv, prv->reader)){ - break; - } - prv->reader += (strlen(prv->reader) + 1); - } - - if(prv->card == 0){ - return B_CAS_CARD_ERROR_ALL_READERS_CONNECTION_FAILED; - } - - return 0; -} - -static int get_init_status_b_cas_card(void *bcas, B_CAS_INIT_STATUS *stat) -{ - B_CAS_CARD_PRIVATE_DATA *prv; - - prv = private_data(bcas); - if( (prv == NULL) || (stat == NULL) ){ - return B_CAS_CARD_ERROR_INVALID_PARAMETER; - } - - if(prv->card == 0){ - return B_CAS_CARD_ERROR_NOT_INITIALIZED; - } - - memcpy(stat, &(prv->stat), sizeof(B_CAS_INIT_STATUS)); - - return 0; -} - -static int get_id_b_cas_card(void *bcas, B_CAS_ID *dst) -{ - LONG ret; - - DWORD slen; - DWORD rlen; - - int i,num; - - uint8_t *p; - uint8_t *tail; - - B_CAS_CARD_PRIVATE_DATA *prv; - SCARD_IO_REQUEST sir; - - prv = private_data(bcas); - if( (prv == NULL) || (dst == NULL) ){ - return B_CAS_CARD_ERROR_INVALID_PARAMETER; - } - - if(prv->card == 0){ - return B_CAS_CARD_ERROR_NOT_INITIALIZED; - } - - slen = sizeof(CARD_ID_INFORMATION_ACQUIRE_CMD); - memcpy(prv->sbuf, CARD_ID_INFORMATION_ACQUIRE_CMD, slen); - memcpy(&sir, SCARD_PCI_T1, sizeof(sir)); - rlen = B_CAS_BUFFER_MAX; - - ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen); - if( (ret != SCARD_S_SUCCESS) || (rlen < 19) ){ - return B_CAS_CARD_ERROR_TRANSMIT_FAILED; - } - - p = prv->rbuf + 6; - tail = prv->rbuf + rlen; - if( p+1 > tail ){ - return B_CAS_CARD_ERROR_TRANSMIT_FAILED; - } - - num = p[0]; - if(num > prv->id_max){ - if(change_id_max(prv, num+4) < 0){ - return B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY; - } - } - - p += 1; - for(i=0;i tail ){ - return B_CAS_CARD_ERROR_TRANSMIT_FAILED; - } - - { - int maker_id; - int version; - int check_code; - - maker_id = p[0]; - version = p[1]; - prv->id.data[i] = load_be_uint48(p+2); - check_code = load_be_uint16(p+8); - } - - p += 10; - } - - prv->id.count = num; - - memcpy(dst, &(prv->id), sizeof(B_CAS_ID)); - - return 0; -} - -static int get_pwr_on_ctrl_b_cas_card(void *bcas, B_CAS_PWR_ON_CTRL_INFO *dst) -{ - LONG ret; - - DWORD slen; - DWORD rlen; - - int i,num,code; - - B_CAS_CARD_PRIVATE_DATA *prv; - SCARD_IO_REQUEST sir; - - memset(dst, 0, sizeof(B_CAS_PWR_ON_CTRL_INFO)); - - prv = private_data(bcas); - if( (prv == NULL) || (dst == NULL) ){ - return B_CAS_CARD_ERROR_INVALID_PARAMETER; - } - - if(prv->card == 0){ - return B_CAS_CARD_ERROR_NOT_INITIALIZED; - } - - slen = sizeof(POWER_ON_CONTROL_INFORMATION_REQUEST_CMD); - memcpy(prv->sbuf, POWER_ON_CONTROL_INFORMATION_REQUEST_CMD, slen); - prv->sbuf[5] = 0; - memcpy(&sir, SCARD_PCI_T1, sizeof(sir)); - rlen = B_CAS_BUFFER_MAX; - - ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen); - if( (ret != SCARD_S_SUCCESS) || (rlen < 18) || (prv->rbuf[6] != 0) ){ - return B_CAS_CARD_ERROR_TRANSMIT_FAILED; - } - - code = load_be_uint16(prv->rbuf+4); - if(code == 0xa101){ - /* no data */ - return 0; - }else if(code != 0x2100){ - return B_CAS_CARD_ERROR_TRANSMIT_FAILED; - } - - num = (prv->rbuf[7] + 1); - if(prv->pwc_max < num){ - if(change_pwc_max(prv, num+4) < 0){ - return B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY; - } - } - - extract_power_on_ctrl_response(prv->pwc.data+0, prv->rbuf); - - for(i=1;isbuf[5] = i; - rlen = B_CAS_BUFFER_MAX; - - ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen); - if( (ret != SCARD_S_SUCCESS) || (rlen < 18) || (prv->rbuf[6] != i) ){ - return B_CAS_CARD_ERROR_TRANSMIT_FAILED; - } - - extract_power_on_ctrl_response(prv->pwc.data+i, prv->rbuf); - } - - prv->pwc.count = num; - - memcpy(dst, &(prv->pwc), sizeof(B_CAS_PWR_ON_CTRL_INFO)); - - return 0; -} - -static int proc_ecm_b_cas_card(void *bcas, B_CAS_ECM_RESULT *dst, uint8_t *src, int len) -{ - int retry_count; - - LONG ret; - DWORD slen; - DWORD rlen; - - B_CAS_CARD_PRIVATE_DATA *prv; - - SCARD_IO_REQUEST sir; - - prv = private_data(bcas); - if( (prv == NULL) || - (dst == NULL) || - (src == NULL) || - (len < 1) ){ - return B_CAS_CARD_ERROR_INVALID_PARAMETER; - } - - if(prv->card == 0){ - return B_CAS_CARD_ERROR_NOT_INITIALIZED; - } - - slen = setup_ecm_receive_command(prv->sbuf, src, len); - memcpy(&sir, SCARD_PCI_T1, sizeof(sir)); - rlen = B_CAS_BUFFER_MAX; - - retry_count = 0; - ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen); - while( ((ret != SCARD_S_SUCCESS) || (rlen < 25)) && (retry_count < 10) ){ - retry_count += 1; - if(!connect_card(prv, prv->reader)){ - continue; - } - slen = setup_ecm_receive_command(prv->sbuf, src, len); - memcpy(&sir, SCARD_PCI_T1, sizeof(sir)); - rlen = B_CAS_BUFFER_MAX; - - ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen); - } - - if( (ret != SCARD_S_SUCCESS) || (rlen < 25) ){ - return B_CAS_CARD_ERROR_TRANSMIT_FAILED; - } - - memcpy(dst->scramble_key, prv->rbuf+6, 16); - dst->return_code = load_be_uint16(prv->rbuf+4); - - return 0; -} - -static int proc_emm_b_cas_card(void *bcas, uint8_t *src, int len) -{ - int retry_count; - - LONG ret; - DWORD slen; - DWORD rlen; - - B_CAS_CARD_PRIVATE_DATA *prv; - - SCARD_IO_REQUEST sir; - - prv = private_data(bcas); - if( (prv == NULL) || - (src == NULL) || - (len < 1) ){ - return B_CAS_CARD_ERROR_INVALID_PARAMETER; - } - - if(prv->card == 0){ - return B_CAS_CARD_ERROR_NOT_INITIALIZED; - } - - slen = setup_emm_receive_command(prv->sbuf, src, len); - memcpy(&sir, SCARD_PCI_T1, sizeof(sir)); - rlen = B_CAS_BUFFER_MAX; - - retry_count = 0; - ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen); - while( ((ret != SCARD_S_SUCCESS) || (rlen < 6)) && (retry_count < 2) ){ - retry_count += 1; - if(!connect_card(prv, prv->reader)){ - continue; - } - slen = setup_emm_receive_command(prv->sbuf, src, len); - memcpy(&sir, SCARD_PCI_T1, sizeof(sir)); - rlen = B_CAS_BUFFER_MAX; - - ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen); - } - - if( (ret != SCARD_S_SUCCESS) || (rlen < 6) ){ - return B_CAS_CARD_ERROR_TRANSMIT_FAILED; - } - - return 0; -} - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - private method implementation - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -static B_CAS_CARD_PRIVATE_DATA *private_data(void *bcas) -{ - B_CAS_CARD_PRIVATE_DATA *r; - B_CAS_CARD *p; - - p = (B_CAS_CARD *)bcas; - if(p == NULL){ - return NULL; - } - - r = (B_CAS_CARD_PRIVATE_DATA *)(p->private_data); - if( ((void *)(r+1)) != ((void *)p) ){ - return NULL; - } - - return r; -} - -static void teardown(B_CAS_CARD_PRIVATE_DATA *prv) -{ - if(prv->card != 0){ - SCardDisconnect(prv->card, SCARD_LEAVE_CARD); - prv->card = 0; - } - - if(prv->mng != 0){ - SCardReleaseContext(prv->mng); - prv->mng = 0; - } - - if(prv->pool != NULL){ - free(prv->pool); - prv->pool = NULL; - } - - prv->reader = NULL; - prv->sbuf = NULL; - prv->rbuf = NULL; - prv->id.data = NULL; - prv->id_max = 0; -} - -static int change_id_max(B_CAS_CARD_PRIVATE_DATA *prv, int max) -{ - int m; - int reader_size; - int pwctrl_size; - - uint8_t *p; - uint8_t *old_reader; - uint8_t *old_pwctrl; - - reader_size = prv->sbuf - prv->pool; - pwctrl_size = prv->pwc.count * sizeof(B_CAS_PWR_ON_CTRL); - - m = reader_size; - m += (2*B_CAS_BUFFER_MAX); - m += (max*sizeof(int64_t)); - m += (prv->pwc_max*sizeof(B_CAS_PWR_ON_CTRL)); - p = (uint8_t *)malloc(m); - if(p == NULL){ - return B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY; - } - - old_reader = (uint8_t *)(prv->reader); - old_pwctrl = (uint8_t *)(prv->pwc.data); - - prv->reader = (char *)p; - prv->sbuf = prv->pool + reader_size; - prv->rbuf = prv->sbuf + B_CAS_BUFFER_MAX; - prv->id.data = (int64_t *)(prv->rbuf + B_CAS_BUFFER_MAX); - prv->id_max = max; - prv->pwc.data = (B_CAS_PWR_ON_CTRL *)(prv->id.data + prv->id_max); - - memcpy(prv->reader, old_reader, reader_size); - memcpy(prv->pwc.data, old_pwctrl, pwctrl_size); - - free(prv->pool); - prv->pool = p; - - return 0; -} - -static int change_pwc_max(B_CAS_CARD_PRIVATE_DATA *prv, int max) -{ - int m; - int reader_size; - int cardid_size; - - uint8_t *p; - uint8_t *old_reader; - uint8_t *old_cardid; - - reader_size = prv->sbuf - prv->pool; - cardid_size = prv->id.count * sizeof(int64_t); - - m = reader_size; - m += (2*B_CAS_BUFFER_MAX); - m += (prv->id_max*sizeof(int64_t)); - m += (max*sizeof(B_CAS_PWR_ON_CTRL)); - p = (uint8_t *)malloc(m); - if(p == NULL){ - return B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY; - } - - old_reader = (uint8_t *)(prv->reader); - old_cardid = (uint8_t *)(prv->id.data); - - prv->reader = (char *)p; - prv->sbuf = prv->pool + reader_size; - prv->rbuf = prv->sbuf + B_CAS_BUFFER_MAX; - prv->id.data = (int64_t *)(prv->rbuf + B_CAS_BUFFER_MAX); - prv->pwc.data = (B_CAS_PWR_ON_CTRL *)(prv->id.data + prv->id_max); - prv->pwc_max = max; - - memcpy(prv->reader, old_reader, reader_size); - memcpy(prv->id.data, old_cardid, cardid_size); - - free(prv->pool); - prv->pool = p; - - return 0; -} - -static int connect_card(B_CAS_CARD_PRIVATE_DATA *prv, const char *reader_name) -{ - int m,n; - - LONG ret; - DWORD rlen,protocol; - - uint8_t *p; - - SCARD_IO_REQUEST sir; - - if(prv->card != 0){ - SCardDisconnect(prv->card, SCARD_RESET_CARD); - prv->card = 0; - } - - ret = SCardConnect(prv->mng, reader_name, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &(prv->card), &protocol); - if(ret != SCARD_S_SUCCESS){ - return 0; - } - - m = sizeof(INITIAL_SETTING_CONDITIONS_CMD); - memcpy(prv->sbuf, INITIAL_SETTING_CONDITIONS_CMD, m); - memcpy(&sir, SCARD_PCI_T1, sizeof(sir)); - rlen = B_CAS_BUFFER_MAX; - ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, m, &sir, prv->rbuf, &rlen); - if(ret != SCARD_S_SUCCESS){ - return 0; - } - - if(rlen < 57){ - return 0; - } - - p = prv->rbuf; - - n = load_be_uint16(p+4); - if(n != 0x2100){ // return code missmatch - return 0; - } - - memcpy(prv->stat.system_key, p+16, 32); - memcpy(prv->stat.init_cbc, p+48, 8); - prv->stat.bcas_card_id = load_be_uint48(p+8); - prv->stat.card_status = load_be_uint16(p+2); - prv->stat.ca_system_id = load_be_uint16(p+6); - - return 1; -} - -static void extract_power_on_ctrl_response(B_CAS_PWR_ON_CTRL *dst, uint8_t *src) -{ - int referrence; - int start; - int limit; - - - dst->broadcaster_group_id = src[8]; - referrence = (src[9]<<8)|src[10]; - start = referrence - src[11]; - limit = start + (src[12]-1); - - extract_mjd(&(dst->s_yy), &(dst->s_mm), &(dst->s_dd), start); - extract_mjd(&(dst->l_yy), &(dst->l_mm), &(dst->l_dd), limit); - - dst->hold_time = src[13]; - dst->network_id = (src[14]<<8)|src[15]; - dst->transport_id = (src[16]<<8)|src[17]; - -} - -static void extract_mjd(int *yy, int *mm, int *dd, int mjd) -{ - int a1,m1; - int a2,m2; - int a3,m3; - int a4,m4; - int mw; - int dw; - int yw; - - mjd -= 51604; // 2000,3/1 - if(mjd < 0){ - mjd += 0x10000; - } - - a1 = mjd / 146097; - m1 = mjd % 146097; - a2 = m1 / 36524; - m2 = m1 - (a2 * 36524); - a3 = m2 / 1461; - m3 = m2 - (a3 * 1461); - a4 = m3 / 365; - if(a4 > 3){ - a4 = 3; - } - m4 = m3 - (a4 * 365); - - mw = (1071*m4+450) >> 15; - dw = m4 - ((979*mw+16) >> 5); - - yw = a1*400 + a2*100 + a3*4 + a4 + 2000; - mw += 3; - if(mw > 12){ - mw -= 12; - yw += 1; - } - dw += 1; - - *yy = yw; - *mm = mw; - *dd = dw; -} - -static int setup_ecm_receive_command(uint8_t *dst, uint8_t *src, int len) -{ - int r; - - r = sizeof(ECM_RECEIVE_CMD_HEADER); - memcpy(dst+0, ECM_RECEIVE_CMD_HEADER, r); - dst[r] = (uint8_t)(len & 0xff); - r += 1; - memcpy(dst+r, src, len); - r += len; - dst[r] = 0; - r += 1; - - return r; -} - -static int setup_emm_receive_command(uint8_t *dst, uint8_t *src, int len) -{ - int r; - - r = sizeof(EMM_RECEIVE_CMD_HEADER); - memcpy(dst+0, EMM_RECEIVE_CMD_HEADER, r); - dst[r] = (uint8_t)(len & 0xff); - r += 1; - memcpy(dst+r, src, len); - r += len; - dst[r] = 0; - r += 1; - - return r; -} - -static int32_t load_be_uint16(uint8_t *p) -{ - return ((p[0]<<8)|p[1]); -} - -static int64_t load_be_uint48(uint8_t *p) -{ - int i; - int64_t r; - - r = p[0]; - for(i=1;i<6;i++){ - r <<= 8; - r |= p[i]; - } - - return r; -} - diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/src/b_cas_card.h --- a/arib25v023/arib25/src/b_cas_card.h Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -#ifndef B_CAS_CARD_H -#define B_CAS_CARD_H - -#include "portable.h" - -typedef struct { - uint8_t system_key[32]; - uint8_t init_cbc[8]; - int64_t bcas_card_id; - int32_t card_status; - int32_t ca_system_id; -} B_CAS_INIT_STATUS; - -typedef struct { - int64_t *data; - int32_t count; -} B_CAS_ID; - -typedef struct { - - int32_t s_yy; /* start date : year */ - int32_t s_mm; /* start date : month */ - int32_t s_dd; /* start date : day */ - - int32_t l_yy; /* limit date : year */ - int32_t l_mm; /* limit date : month */ - int32_t l_dd; /* limit date : day */ - - int32_t hold_time; /* in hour unit */ - - int32_t broadcaster_group_id; - - int32_t network_id; - int32_t transport_id; - -} B_CAS_PWR_ON_CTRL; - -typedef struct { - B_CAS_PWR_ON_CTRL *data; - int32_t count; -} B_CAS_PWR_ON_CTRL_INFO; - -typedef struct { - uint8_t scramble_key[16]; - uint32_t return_code; -} B_CAS_ECM_RESULT; - -typedef struct { - - void *private_data; - - void (* release)(void *bcas); - - int (* init)(void *bcas); - - int (* get_init_status)(void *bcas, B_CAS_INIT_STATUS *stat); - int (* get_id)(void *bcas, B_CAS_ID *dst); - int (* get_pwr_on_ctrl)(void *bcas, B_CAS_PWR_ON_CTRL_INFO *dst); - - int (* proc_ecm)(void *bcas, B_CAS_ECM_RESULT *dst, uint8_t *src, int len); - int (* proc_emm)(void *bcas, uint8_t *src, int len); - -} B_CAS_CARD; - -#ifdef __cplusplus -extern "C" { -#endif - -extern B_CAS_CARD *create_b_cas_card(); - -#ifdef __cplusplus -} -#endif - -#endif /* B_CAS_CARD_H */ diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/src/b_cas_card_error_code.h --- a/arib25v023/arib25/src/b_cas_card_error_code.h Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -#ifndef B_CAS_CARD_ERROR_CODE_H -#define B_CAS_CARD_ERROR_CODE_H - -#define B_CAS_CARD_ERROR_INVALID_PARAMETER -1 -#define B_CAS_CARD_ERROR_NOT_INITIALIZED -2 -#define B_CAS_CARD_ERROR_NO_SMART_CARD_READER -3 -#define B_CAS_CARD_ERROR_ALL_READERS_CONNECTION_FAILED -4 -#define B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY -5 -#define B_CAS_CARD_ERROR_TRANSMIT_FAILED -6 - -#endif /* B_CAS_CARD_ERROR_CODE_H */ diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/src/makefile.win --- a/arib25v023/arib25/src/makefile.win Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -CC = cl -CFLAG = /c /MT /W4 /O2 -LINK = link -LFLAG = /nologo -LIBS = winscard.lib - -ALL: b25.exe - -arib_std_b25.obj: arib_std_b25.c arib_std_b25.h portable.h b_cas_card.h arib_std_b25_error_code.h multi2.h ts_section_parser.h ts_common_types.h - $(CC) $(CFLAG) arib_std_b25.c - -b_cas_card.obj: b_cas_card.c b_cas_card.h portable.h b_cas_card_error_code.h - $(CC) $(CFLAG) b_cas_card.c - -multi2.obj: multi2.c multi2.h portable.h multi2_error_code.h - $(CC) $(CFLAG) multi2.c - -td.obj: td.c arib_std_b25.h portable.h b_cas_card.h - $(CC) $(CFLAG) td.c - -ts_section_parser.obj: ts_section_parser.c ts_section_parser.h ts_common_types.h portable.h ts_section_parser_error_code.h - $(CC) $(CFLAG) ts_section_parser.c - -OBJ = arib_std_b25.obj b_cas_card.obj multi2.obj td.obj ts_section_parser.obj - -b25.exe: $(OBJ) - $(LINK) $(LFLAG) $(LIBS) /OUT:b25.exe $(OBJ) - -clean: - DEL *.obj - DEL *.exe - - diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/src/multi2.c --- a/arib25v023/arib25/src/multi2.c Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,527 +0,0 @@ -#include -#include - -#include "multi2.h" -#include "multi2_error_code.h" - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - inline functions - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -static __inline uint8_t *load_be_uint32(uint32_t *dst, uint8_t *src) -{ - *dst = ((src[0]<<24)|(src[1]<<16)|(src[2]<<8)|src[3]); - return src+4; -} - -static __inline uint8_t *save_be_uint32(uint8_t *dst, uint32_t src) -{ - dst[0] = (uint8_t)((src>>24) & 0xff); - dst[1] = (uint8_t)((src>>16) & 0xff); - dst[2] = (uint8_t)((src>> 8) & 0xff); - dst[3] = (uint8_t)( src & 0xff); - return dst+4; -} - -static __inline uint32_t left_rotate_uint32(uint32_t val, uint32_t count) -{ - return ((val << count) | (val >> (32-count))); -} - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - inner structures - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -typedef struct { - uint32_t key[8]; -} CORE_PARAM; - -typedef struct { - uint32_t l; - uint32_t r; -} CORE_DATA; - -typedef struct { - - int32_t ref_count; - - CORE_DATA cbc_init; - - CORE_PARAM sys; - CORE_DATA scr[2]; /* 0: odd, 1: even */ - CORE_PARAM wrk[2]; /* 0: odd, 1: even */ - - uint32_t round; - uint32_t state; - -} MULTI2_PRIVATE_DATA; - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - constant values - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -#define MULTI2_STATE_CBC_INIT_SET (0x0001) -#define MULTI2_STATE_SYSTEM_KEY_SET (0x0002) -#define MULTI2_STATE_SCRAMBLE_KEY_SET (0x0004) - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - function prottypes (interface method) - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -static void release_multi2(void *m2); -static int add_ref_multi2(void *m2); -static int set_round_multi2(void *m2, int32_t val); -static int set_system_key_multi2(void *m2, uint8_t *val); -static int set_init_cbc_multi2(void *m2, uint8_t *val); -static int set_scramble_key_multi2(void *m2, uint8_t *val); -static int clear_scramble_key_multi2(void *m2); -static int encrypt_multi2(void *m2, int32_t type, uint8_t *buf, int32_t size); -static int decrypt_multi2(void *m2, int32_t type, uint8_t *buf, int32_t size); - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - global function implementation - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -MULTI2 *create_multi2() -{ - int n; - - MULTI2 *r; - MULTI2_PRIVATE_DATA *prv; - - n = sizeof(MULTI2_PRIVATE_DATA); - n += sizeof(MULTI2); - - prv = (MULTI2_PRIVATE_DATA *)calloc(1, n); - if(prv == NULL){ - return NULL; - } - - r = (MULTI2 *)(prv+1); - r->private_data = prv; - - prv->ref_count = 1; - prv->round = 4; - - r->release = release_multi2; - r->add_ref = add_ref_multi2; - r->set_round = set_round_multi2; - r->set_system_key = set_system_key_multi2; - r->set_init_cbc = set_init_cbc_multi2; - r->set_scramble_key = set_scramble_key_multi2; - r->clear_scramble_key = clear_scramble_key_multi2; - r->encrypt = encrypt_multi2; - r->decrypt = decrypt_multi2; - - return r; -} - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - function prottypes (private method) - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -static MULTI2_PRIVATE_DATA *private_data(void *m2); - -static void core_schedule(CORE_PARAM *work, CORE_PARAM *skey, CORE_DATA *dkey); - -static void core_encrypt(CORE_DATA *dst, CORE_DATA *src, CORE_PARAM *w, int32_t round); -static void core_decrypt(CORE_DATA *dst, CORE_DATA *src, CORE_PARAM *w, int32_t round); - -static void core_pi1(CORE_DATA *dst, CORE_DATA *src); -static void core_pi2(CORE_DATA *dst, CORE_DATA *src, uint32_t a); -static void core_pi3(CORE_DATA *dst, CORE_DATA *src, uint32_t a, uint32_t b); -static void core_pi4(CORE_DATA *dst, CORE_DATA *src, uint32_t a); - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - interface method implementation - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -static void release_multi2(void *m2) -{ - MULTI2_PRIVATE_DATA *prv; - - prv = private_data(m2); - if(prv == NULL){ - /* do nothing */ - return; - } - - prv->ref_count -= 1; - if(prv->ref_count == 0){ - free(prv); - } -} - -static int add_ref_multi2(void *m2) -{ - MULTI2_PRIVATE_DATA *prv; - - prv = private_data(m2); - if(prv == NULL){ - return MULTI2_ERROR_INVALID_PARAMETER; - } - - prv->ref_count += 1; - - return 0; -} - -static int set_round_multi2(void *m2, int32_t val) -{ - MULTI2_PRIVATE_DATA *prv; - - prv = private_data(m2); - if(prv == NULL){ - /* do nothing */ - return MULTI2_ERROR_INVALID_PARAMETER; - } - - prv->round = val; - - return 0; -} - -static int set_system_key_multi2(void *m2, uint8_t *val) -{ - int i; - uint8_t *p; - - MULTI2_PRIVATE_DATA *prv; - - prv = private_data(m2); - if( (prv == NULL) || (val == NULL) ){ - return MULTI2_ERROR_INVALID_PARAMETER; - } - - p = val; - for(i=0;i<8;i++){ - p = load_be_uint32(prv->sys.key+i, p); - } - - prv->state |= MULTI2_STATE_SYSTEM_KEY_SET; - - return 0; -} - -static int set_init_cbc_multi2(void *m2, uint8_t *val) -{ - uint8_t *p; - - MULTI2_PRIVATE_DATA *prv; - - prv = private_data(m2); - if( (prv == NULL) || (val == NULL) ){ - return MULTI2_ERROR_INVALID_PARAMETER; - } - - p = val; - - p = load_be_uint32(&(prv->cbc_init.l), p); - p = load_be_uint32(&(prv->cbc_init.r), p); - - prv->state |= MULTI2_STATE_CBC_INIT_SET; - - return 0; -} - -static int set_scramble_key_multi2(void *m2, uint8_t *val) -{ - uint8_t *p; - - MULTI2_PRIVATE_DATA *prv; - - prv = private_data(m2); - if( (prv == NULL) || (val == NULL) ){ - return MULTI2_ERROR_INVALID_PARAMETER; - } - - p = val; - - p = load_be_uint32(&(prv->scr[0].l), p); - p = load_be_uint32(&(prv->scr[0].r), p); - p = load_be_uint32(&(prv->scr[1].l), p); - p = load_be_uint32(&(prv->scr[1].r), p); - - core_schedule(prv->wrk+0, &(prv->sys), prv->scr+0); - core_schedule(prv->wrk+1, &(prv->sys), prv->scr+1); - - prv->state |= MULTI2_STATE_SCRAMBLE_KEY_SET; - - return 0; -} - -static int clear_scramble_key_multi2(void *m2) -{ - MULTI2_PRIVATE_DATA *prv; - - prv = private_data(m2); - if(prv == NULL){ - return MULTI2_ERROR_INVALID_PARAMETER; - } - - memset(prv->scr, 0, sizeof(prv->scr)); - memset(prv->wrk, 0, sizeof(prv->wrk)); - - prv->state &= (~MULTI2_STATE_SCRAMBLE_KEY_SET); - - return 0; -} - -static int encrypt_multi2(void *m2, int32_t type, uint8_t *buf, int32_t size) -{ - CORE_DATA src,dst; - CORE_PARAM *prm; - - uint8_t *p; - - MULTI2_PRIVATE_DATA *prv; - - prv = private_data(m2); - if( (prv == NULL) || (buf == NULL) || (size < 1) ){ - return MULTI2_ERROR_INVALID_PARAMETER; - } - - if(prv->state != (MULTI2_STATE_CBC_INIT_SET|MULTI2_STATE_SYSTEM_KEY_SET|MULTI2_STATE_SCRAMBLE_KEY_SET)){ - if( (prv->state & MULTI2_STATE_CBC_INIT_SET) == 0 ){ - return MULTI2_ERROR_UNSET_CBC_INIT; - } - if( (prv->state & MULTI2_STATE_SYSTEM_KEY_SET) == 0 ){ - return MULTI2_ERROR_UNSET_SYSTEM_KEY; - } - if( (prv->state & MULTI2_STATE_SCRAMBLE_KEY_SET) == 0 ){ - return MULTI2_ERROR_UNSET_SCRAMBLE_KEY; - } - } - - if(type == 0x02){ - prm = prv->wrk+1; - }else{ - prm = prv->wrk+0; - } - - dst.l = prv->cbc_init.l; - dst.r = prv->cbc_init.r; - - p = buf; - while(size >= 8){ - load_be_uint32(&(src.l), p+0); - load_be_uint32(&(src.r), p+4); - src.l = src.l ^ dst.l; - src.r = src.r ^ dst.r; - core_encrypt(&dst, &src, prm, prv->round); - p = save_be_uint32(p, dst.l); - p = save_be_uint32(p, dst.r); - size -= 8; - } - - if(size > 0){ - int i; - uint8_t tmp[8]; - - src.l = dst.l; - src.r = dst.r; - core_encrypt(&dst, &src, prm, prv->round); - save_be_uint32(tmp+0, dst.l); - save_be_uint32(tmp+4, dst.r); - - for(i=0;istate != (MULTI2_STATE_CBC_INIT_SET|MULTI2_STATE_SYSTEM_KEY_SET|MULTI2_STATE_SCRAMBLE_KEY_SET)){ - if( (prv->state & MULTI2_STATE_CBC_INIT_SET) == 0 ){ - return MULTI2_ERROR_UNSET_CBC_INIT; - } - if( (prv->state & MULTI2_STATE_SYSTEM_KEY_SET) == 0 ){ - return MULTI2_ERROR_UNSET_SYSTEM_KEY; - } - if( (prv->state & MULTI2_STATE_SCRAMBLE_KEY_SET) == 0 ){ - return MULTI2_ERROR_UNSET_SCRAMBLE_KEY; - } - } - - if(type == 0x02){ - prm = prv->wrk+1; - }else{ - prm = prv->wrk+0; - } - - cbc.l = prv->cbc_init.l; - cbc.r = prv->cbc_init.r; - - p = buf; - while(size >= 8){ - load_be_uint32(&(src.l), p+0); - load_be_uint32(&(src.r), p+4); - core_decrypt(&dst, &src, prm, prv->round); - dst.l = dst.l ^ cbc.l; - dst.r = dst.r ^ cbc.r; - cbc.l = src.l; - cbc.r = src.r; - p = save_be_uint32(p, dst.l); - p = save_be_uint32(p, dst.r); - size -= 8; - } - - if(size > 0){ - int i; - uint8_t tmp[8]; - - core_encrypt(&dst, &cbc, prm, prv->round); - save_be_uint32(tmp+0, dst.l); - save_be_uint32(tmp+4, dst.r); - - for(i=0;iprivate_data); - if( ((void *)(r+1)) != ((void *)p) ){ - return NULL; - } - - return r; -} - -static void core_schedule(CORE_PARAM *work, CORE_PARAM *skey, CORE_DATA *dkey) -{ - CORE_DATA b1,b2,b3,b4,b5,b6,b7,b8,b9; - - core_pi1(&b1, dkey); - - core_pi2(&b2, &b1, skey->key[0]); - work->key[0] = b2.l; - - core_pi3(&b3, &b2, skey->key[1], skey->key[2]); - work->key[1] = b3.r; - - core_pi4(&b4, &b3, skey->key[3]); - work->key[2] = b4.l; - - core_pi1(&b5, &b4); - work->key[3] = b5.r; - - core_pi2(&b6, &b5, skey->key[4]); - work->key[4] = b6.l; - - core_pi3(&b7, &b6, skey->key[5], skey->key[6]); - work->key[5] = b7.r; - - core_pi4(&b8, &b7, skey->key[7]); - work->key[6] = b8.l; - - core_pi1(&b9, &b8); - work->key[7] = b9.r; -} - -static void core_encrypt(CORE_DATA *dst, CORE_DATA *src, CORE_PARAM *w, int32_t round) -{ - int32_t i; - - CORE_DATA tmp; - - dst->l = src->l; - dst->r = src->r; - for(i=0;ikey[0]); - core_pi3(&tmp, dst, w->key[1], w->key[2]); - core_pi4( dst, &tmp, w->key[3]); - core_pi1(&tmp, dst); - core_pi2( dst, &tmp, w->key[4]); - core_pi3(&tmp, dst, w->key[5], w->key[6]); - core_pi4( dst, &tmp, w->key[7]); - } -} - -static void core_decrypt(CORE_DATA *dst, CORE_DATA *src, CORE_PARAM *w, int32_t round) -{ - int32_t i; - - CORE_DATA tmp; - - dst->l = src->l; - dst->r = src->r; - for(i=0;ikey[7]); - core_pi3( dst, &tmp, w->key[5], w->key[6]); - core_pi2(&tmp, dst, w->key[4]); - core_pi1( dst, &tmp); - core_pi4(&tmp, dst, w->key[3]); - core_pi3( dst, &tmp, w->key[1], w->key[2]); - core_pi2(&tmp, dst, w->key[0]); - core_pi1( dst, &tmp); - } -} - -static void core_pi1(CORE_DATA *dst, CORE_DATA *src) -{ - dst->l = src->l; - dst->r = src->r ^ src->l; -} - -static void core_pi2(CORE_DATA *dst, CORE_DATA *src, uint32_t a) -{ - uint32_t t0,t1,t2; - - t0 = src->r + a; - t1 = left_rotate_uint32(t0, 1) + t0 - 1; - t2 = left_rotate_uint32(t1, 4) ^ t1; - - dst->l = src->l ^ t2; - dst->r = src->r; -} - -static void core_pi3(CORE_DATA *dst, CORE_DATA *src, uint32_t a, uint32_t b) -{ - uint32_t t0,t1,t2,t3,t4,t5; - - t0 = src->l + a; - t1 = left_rotate_uint32(t0, 2) + t0 + 1; - t2 = left_rotate_uint32(t1, 8) ^ t1; - t3 = t2 + b; - t4 = left_rotate_uint32(t3, 1) - t3; - t5 = left_rotate_uint32(t4, 16) ^ (t4 | src->l); - - dst->l = src->l; - dst->r = src->r ^ t5; -} - -static void core_pi4(CORE_DATA *dst, CORE_DATA *src, uint32_t a) -{ - uint32_t t0,t1; - - t0 = src->r + a; - t1 = left_rotate_uint32(t0, 2) + t0 + 1; - - dst->l = src->l ^ t1; - dst->r = src->r; -} diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/src/multi2.h --- a/arib25v023/arib25/src/multi2.h Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -#ifndef MULTI2_H -#define MULTI2_H - -#include "portable.h" - -typedef struct { - - void *private_data; - - void (* release)(void *m2); - int (* add_ref)(void *m2); - - int (* set_round)(void *m2, int32_t val); - - int (* set_system_key)(void *m2, uint8_t *val); - int (* set_init_cbc)(void *m2, uint8_t *val); - int (* set_scramble_key)(void *m2, uint8_t *val); - int (* clear_scramble_key)(void *m2); - - int (* encrypt)(void *m2, int32_t type, uint8_t *buf, int32_t size); - int (* decrypt)(void *m2, int32_t type, uint8_t *buf, int32_t size); - -} MULTI2; - -#ifdef __cplusplus -extern "C" { -#endif - -extern MULTI2 *create_multi2(); - -#ifdef __cplusplus -} -#endif - -#endif /* MULTI2_H */ diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/src/multi2_error_code.h --- a/arib25v023/arib25/src/multi2_error_code.h Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -#ifndef MULTI2_ERROR_CODE_H -#define MULTI2_ERROR_CODE_H - -#define MULTI2_ERROR_INVALID_PARAMETER -1 -#define MULTI2_ERROR_UNSET_SYSTEM_KEY -2 -#define MULTI2_ERROR_UNSET_CBC_INIT -3 -#define MULTI2_ERROR_UNSET_SCRAMBLE_KEY -4 - -#endif /* MULTI2_ERROR_CODE_H */ diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/src/portable.h --- a/arib25v023/arib25/src/portable.h Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -#ifndef PORTABLE_H -#define PORTABLE_H - -#if (defined(WIN32) && MSC_VER < 1300) - -typedef unsigned char uint8_t; -typedef signed char int8_t; -typedef unsigned short uint16_t; -typedef signed short int16_t; -typedef unsigned int uint32_t; -typedef signed int int32_t; -typedef unsigned __int64 uint64_t; -typedef signed __int64 int64_t; - -#else - -#include - -#endif - -#if !defined(WIN32) - #define _open open - #define _close close - #define _read read - #define _write write - #define _lseeki64 lseek - #define _telli64(fd) (lseek(fd,0,SEEK_CUR)) - #define _O_BINARY (0) - #define _O_RDONLY (O_RDONLY) - #define _O_WRONLY (O_WRONLY) - #define _O_SEQUENTIAL (0) - #define _O_CREAT (O_CREAT) - #define _O_TRUNC (O_TRUNC) - #define _S_IREAD (S_IRUSR|S_IRGRP|S_IROTH) - #define _S_IWRITE (S_IWUSR|S_IWGRP|S_IWOTH) -#endif - -#endif /* PORTABLE_H */ diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/src/td.c --- a/arib25v023/arib25/src/td.c Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,381 +0,0 @@ -#include -#include -#include - -#include -#include -#include - -#if defined(WIN32) - #include - #include - #include -#else - #define __STDC_FORMAT_MACROS - #include - #include -#endif - -#include "arib_std_b25.h" -#include "b_cas_card.h" - -typedef struct { - int32_t round; - int32_t strip; - int32_t emm; - int32_t verbose; - int32_t power_ctrl; -} OPTION; - -static void show_usage(); -static int parse_arg(OPTION *dst, int argc, char **argv); -static void test_arib_std_b25(const char *src, const char *dst, OPTION *opt); -static void show_bcas_power_on_control_info(B_CAS_CARD *bcas); - -int main(int argc, char **argv) -{ - int n; - OPTION opt; - - #if defined(WIN32) - _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); - _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT ); - _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ); - _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT ); - _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); - _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT ); - _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_DELAY_FREE_MEM_DF|_CRTDBG_CHECK_ALWAYS_DF|_CRTDBG_LEAK_CHECK_DF); - #endif - - n = parse_arg(&opt, argc, argv); - if(n+2 > argc){ - show_usage(); - exit(EXIT_FAILURE); - } - - test_arib_std_b25(argv[n+0], argv[n+1], &opt); - - #if defined(WIN32) - _CrtDumpMemoryLeaks(); - #endif - - return EXIT_SUCCESS; -} - -static void show_usage() -{ - fprintf(stderr, "b25 - ARIB STD-B25 test program ver. 0.2.3 (2008, 12/30)\n"); - fprintf(stderr, "usage: b25 [options] src.m2t dst.m2t\n"); - fprintf(stderr, "options:\n"); - fprintf(stderr, " -r round (integer, default=4)\n"); - fprintf(stderr, " -s strip\n"); - fprintf(stderr, " 0: keep null(padding) stream (default)\n"); - fprintf(stderr, " 1: strip null stream\n"); - fprintf(stderr, " -m EMM\n"); - fprintf(stderr, " 0: ignore EMM (default)\n"); - fprintf(stderr, " 1: send EMM to B-CAS card\n"); - fprintf(stderr, " -p power_on_control_info\n"); - fprintf(stderr, " 0: do nothing additionaly\n"); - fprintf(stderr, " 1: show B-CAS EMM receiving request (default)\n"); - fprintf(stderr, " -v verbose\n"); - fprintf(stderr, " 0: silent\n"); - fprintf(stderr, " 1: show processing status (default)\n"); - fprintf(stderr, "\n"); -} - -static int parse_arg(OPTION *dst, int argc, char **argv) -{ - int i; - - dst->round = 4; - dst->strip = 0; - dst->emm = 0; - dst->power_ctrl = 1; - dst->verbose = 1; - - for(i=1;iemm = atoi(argv[i]+2); - }else{ - dst->emm = atoi(argv[i+1]); - i += 1; - } - break; - case 'p': - if(argv[i][2]){ - dst->power_ctrl = atoi(argv[i]+2); - }else{ - dst->power_ctrl = atoi(argv[i+1]); - i += 1; - } - break; - case 'r': - if(argv[i][2]){ - dst->round = atoi(argv[i]+2); - }else{ - dst->round = atoi(argv[i+1]); - i += 1; - } - break; - case 's': - if(argv[i][2]){ - dst->strip = atoi(argv[i]+2); - }else{ - dst->strip = atoi(argv[i+1]); - i += 1; - } - break; - case 'v': - if(argv[i][2]){ - dst->verbose = atoi(argv[i]+2); - }else{ - dst->verbose = atoi(argv[i+1]); - i += 1; - } - break; - default: - fprintf(stderr, "error - unknown option '-%c'\n", argv[i][1]); - return argc; - } - } - - return i; -} - -static void test_arib_std_b25(const char *src, const char *dst, OPTION *opt) -{ - int code,i,n,m; - int sfd,dfd; - - int64_t total; - int64_t offset; - - ARIB_STD_B25 *b25; - B_CAS_CARD *bcas; - - ARIB_STD_B25_PROGRAM_INFO pgrm; - - uint8_t data[8*1024]; - - ARIB_STD_B25_BUFFER sbuf; - ARIB_STD_B25_BUFFER dbuf; - - sfd = -1; - dfd = -1; - b25 = NULL; - bcas = NULL; - - sfd = _open(src, _O_BINARY|_O_RDONLY|_O_SEQUENTIAL); - if(sfd < 0){ - fprintf(stderr, "error - failed on _open(%s) [src]\n", src); - goto LAST; - } - - _lseeki64(sfd, 0, SEEK_END); - total = _telli64(sfd); - _lseeki64(sfd, 0, SEEK_SET); - - b25 = create_arib_std_b25(); - if(b25 == NULL){ - fprintf(stderr, "error - failed on create_arib_std_b25()\n"); - goto LAST; - } - - code = b25->set_multi2_round(b25, opt->round); - if(code < 0){ - fprintf(stderr, "error - failed on ARIB_STD_B25::set_multi2_round() : code=%d\n", code); - goto LAST; - } - - code = b25->set_strip(b25, opt->strip); - if(code < 0){ - fprintf(stderr, "error - failed on ARIB_STD_B25::set_strip() : code=%d\n", code); - goto LAST; - } - - code = b25->set_emm_proc(b25, opt->emm); - if(code < 0){ - fprintf(stderr, "error - failed on ARIB_STD_B25::set_emm_proc() : code=%d\n", code); - goto LAST; - } - - bcas = create_b_cas_card(); - if(bcas == NULL){ - fprintf(stderr, "error - failed on create_b_cas_card()\n"); - goto LAST; - } - - code = bcas->init(bcas); - if(code < 0){ - fprintf(stderr, "error - failed on B_CAS_CARD::init() : code=%d\n", code); - goto LAST; - } - - code = b25->set_b_cas_card(b25, bcas); - if(code < 0){ - fprintf(stderr, "error - failed on ARIB_STD_B25::set_b_cas_card() : code=%d\n", code); - goto LAST; - } - - dfd = _open(dst, _O_BINARY|_O_WRONLY|_O_SEQUENTIAL|_O_CREAT|_O_TRUNC, _S_IREAD|_S_IWRITE); - if(dfd < 0){ - fprintf(stderr, "error - failed on _open(%s) [dst]\n", dst); - goto LAST; - } - - offset = 0; - while( (n = _read(sfd, data, sizeof(data))) > 0 ){ - sbuf.data = data; - sbuf.size = n; - - code = b25->put(b25, &sbuf); - if(code < 0){ - fprintf(stderr, "error - failed on ARIB_STD_B25::put() : code=%d\n", code); - goto LAST; - } - - code = b25->get(b25, &dbuf); - if(code < 0){ - fprintf(stderr, "error - failed on ARIB_STD_B25::get() : code=%d\n", code); - goto LAST; - } - - if(dbuf.size > 0){ - n = _write(dfd, dbuf.data, dbuf.size); - if(n != dbuf.size){ - fprintf(stderr, "error failed on _write(%d)\n", dbuf.size); - goto LAST; - } - } - - offset += sbuf.size; - if(opt->verbose != 0){ - m = (int)(10000*offset/total); - fprintf(stderr, "\rprocessing: %2d.%02d%% ", m/100, m%100); - } - } - - code = b25->flush(b25); - if(code < 0){ - fprintf(stderr, "error - failed on ARIB_STD_B25::flush() : code=%d\n", code); - goto LAST; - } - - code = b25->get(b25, &dbuf); - if(code < 0){ - fprintf(stderr, "error - failed on ARIB_STD_B25::get() : code=%d\n", code); - goto LAST; - } - - if(dbuf.size > 0){ - n = _write(dfd, dbuf.data, dbuf.size); - if(n != dbuf.size){ - fprintf(stderr, "error - failed on _write(%d)\n", dbuf.size); - goto LAST; - } - } - - if(opt->verbose != 0){ - fprintf(stderr, "\rprocessing: finish \n"); - fflush(stderr); - fflush(stdout); - } - - n = b25->get_program_count(b25); - if(n < 0){ - fprintf(stderr, "error - failed on ARIB_STD_B25::get_program_count() : code=%d\n", code); - goto LAST; - } - for(i=0;iget_program_info(b25, &pgrm, i); - if(code < 0){ - fprintf(stderr, "error - failed on ARIB_STD_B25::get_program_info(%d) : code=%d\n", i, code); - goto LAST; - } - if(pgrm.ecm_unpurchased_count > 0){ - fprintf(stderr, "warning - unpurchased ECM is detected\n"); - fprintf(stderr, " channel: %d\n", pgrm.program_number); - fprintf(stderr, " unpurchased ECM count: %d\n", pgrm.ecm_unpurchased_count); - fprintf(stderr, " last ECM error code: %04x\n", pgrm.last_ecm_error_code); - #if defined(WIN32) - fprintf(stderr, " undecrypted TS packet: %d\n", pgrm.undecrypted_packet_count); - fprintf(stderr, " total TS packet: %d\n", pgrm.total_packet_count); - #else - fprintf(stderr, " undecrypted TS packet: %"PRId64"\n", pgrm.undecrypted_packet_count); - fprintf(stderr, " total TS packet: %"PRId64"\n", pgrm.total_packet_count); - #endif - } - } - - if(opt->power_ctrl != 0){ - show_bcas_power_on_control_info(bcas); - } - -LAST: - - if(sfd >= 0){ - _close(sfd); - sfd = -1; - } - - if(dfd >= 0){ - _close(dfd); - dfd = -1; - } - - if(b25 != NULL){ - b25->release(b25); - b25 = NULL; - } - - if(bcas != NULL){ - bcas->release(bcas); - bcas = NULL; - } -} - -static void show_bcas_power_on_control_info(B_CAS_CARD *bcas) -{ - int code; - int i,w; - B_CAS_PWR_ON_CTRL_INFO pwc; - - code = bcas->get_pwr_on_ctrl(bcas, &pwc); - if(code < 0){ - fprintf(stderr, "error - failed on B_CAS_CARD::get_pwr_on_ctrl() : code=%d\n", code); - return; - } - - if(pwc.count == 0){ - fprintf(stdout, "no EMM receiving request\n"); - return; - } - - fprintf(stdout, "total %d EMM receiving request\n", pwc.count); - for(i=0;i> 4) & 0x1f), (w & 7)); - break; - case 6: - case 7: - w = pwc.data[i].transport_id; - fprintf(stdout, "ND-%d/TS-%d ", ((w >> 4) & 0x1f), (w & 7)); - break; - default: - fprintf(stdout, "unknown(b:0x%02x,n:0x%04x,t:0x%04x) ", pwc.data[i].broadcaster_group_id, pwc.data[i].network_id, pwc.data[i].transport_id); - break; - } - fprintf(stdout, "between %04d %02d/%02d ", pwc.data[i].s_yy, pwc.data[i].s_mm, pwc.data[i].s_dd); - fprintf(stdout, "to %04d %02d/%02d ", pwc.data[i].l_yy, pwc.data[i].l_mm, pwc.data[i].l_dd); - fprintf(stdout, "least %d hours\n", pwc.data[i].hold_time); - } -} - diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/src/ts_common_types.h --- a/arib25v023/arib25/src/ts_common_types.h Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -#ifndef TS_COMMON_TYPES_H -#define TS_COMMON_TYPES_H - -#include "portable.h" - -typedef struct { - int32_t sync; /* 0- 7 : 8 bits */ - int32_t transport_error_indicator; /* 8- 8 : 1 bit */ - int32_t payload_unit_start_indicator; /* 9- 9 : 1 bit */ - int32_t transport_priority; /* 10-10 : 1 bits */ - int32_t pid; /* 11-23 : 13 bits */ - int32_t transport_scrambling_control; /* 24-25 : 2 bits */ - int32_t adaptation_field_control; /* 26-27 : 2 bits */ - int32_t continuity_counter; /* 28-31 : 4 bits */ -} TS_HEADER; - -typedef struct { - int32_t table_id; /* 0- 7 : 8 bits */ - int32_t section_syntax_indicator; /* 8- 8 : 1 bit */ - int32_t private_indicator; /* 9- 9 : 1 bit */ - int32_t section_length; /* 12-23 : 12 bits */ - int32_t table_id_extension; /* 24-39 : 16 bits */ - int32_t version_number; /* 42-46 : 5 bits */ - int32_t current_next_indicator; /* 47-57 : 1 bit */ - int32_t section_number; /* 48-55 : 8 bits */ - int32_t last_section_number; /* 56-63 : 8 bits */ -} TS_SECTION_HEADER; - -typedef struct { - TS_SECTION_HEADER hdr; - uint8_t *raw; - uint8_t *data; - uint8_t *tail; -} TS_SECTION; - -#endif /* TS_COMMON_TYPES_H */ diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/src/ts_section_parser.c --- a/arib25v023/arib25/src/ts_section_parser.c Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,802 +0,0 @@ -#include -#include - -#include "ts_section_parser.h" -#include "ts_section_parser_error_code.h" - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - inner structures - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -typedef struct { - void *prev; - void *next; - TS_SECTION sect; - int32_t ref; -} TS_SECTION_ELEM; - -typedef struct { - TS_SECTION_ELEM *head; - TS_SECTION_ELEM *tail; - int32_t count; -} TS_SECTION_LIST; - -typedef struct { - - int32_t pid; - - TS_SECTION_ELEM *work; - TS_SECTION_ELEM *last; - - TS_SECTION_LIST pool; - TS_SECTION_LIST buff; - - TS_SECTION_PARSER_STAT stat; - -} TS_SECTION_PARSER_PRIVATE_DATA; - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - constant values - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -#define MAX_RAW_SECTION_SIZE 4100 - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - function prottypes (interface method) - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -static void release_ts_section_parser(void *parser); -static int reset_ts_section_parser(void *parser); -static int put_ts_section_parser(void *parser, TS_HEADER *hdr, uint8_t *data, int size); -static int get_ts_section_parser(void *parser, TS_SECTION *sect); -static int ret_ts_section_parser(void *parser, TS_SECTION *sect); -static int get_count_ts_section_parser(void *parser); -static int get_stat_ts_section_parser(void *parser, TS_SECTION_PARSER_STAT *stat); - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - global function implementation (factory method) - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -TS_SECTION_PARSER *create_ts_section_parser() -{ - TS_SECTION_PARSER *r; - TS_SECTION_PARSER_PRIVATE_DATA *prv; - - int n; - - n = sizeof(TS_SECTION_PARSER_PRIVATE_DATA); - n += sizeof(TS_SECTION_PARSER); - - prv = (TS_SECTION_PARSER_PRIVATE_DATA *)calloc(1, n); - if(prv == NULL){ - /* failed on malloc() - no enough memory */ - return NULL; - } - - prv->pid = -1; - - r = (TS_SECTION_PARSER *)(prv+1); - r->private_data = prv; - - r->release = release_ts_section_parser; - r->reset = reset_ts_section_parser; - - r->put = put_ts_section_parser; - r->get = get_ts_section_parser; - r->ret = ret_ts_section_parser; - - r->get_count = get_count_ts_section_parser; - - r->get_stat = get_stat_ts_section_parser; - - return r; -} - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - function prottypes (private method) - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -static TS_SECTION_PARSER_PRIVATE_DATA *private_data(void *parser); -static void teardown(TS_SECTION_PARSER_PRIVATE_DATA *prv); - -static int put_exclude_section_start(TS_SECTION_PARSER_PRIVATE_DATA *prv, uint8_t *data, int size); -static int put_include_section_start(TS_SECTION_PARSER_PRIVATE_DATA *prv, uint8_t *data, int size); - -static void reset_section(TS_SECTION *sect); -static void append_section_data(TS_SECTION *sect, uint8_t *data, int size); -static int check_section_complete(TS_SECTION *sect); - -static int compare_elem_section(TS_SECTION_ELEM *a, TS_SECTION_ELEM *b); - -static void cancel_elem_empty(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem); -static void cancel_elem_error(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem); -static void cancel_elem_same(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem); -static void commit_elem_updated(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem); - -static TS_SECTION_ELEM *query_work_elem(TS_SECTION_PARSER_PRIVATE_DATA *prv); - -static void extract_ts_section_header(TS_SECTION *sect); - -static TS_SECTION_ELEM *create_ts_section_elem(); -static TS_SECTION_ELEM *get_ts_section_list_head(TS_SECTION_LIST *list); -static void put_ts_section_list_tail(TS_SECTION_LIST *list, TS_SECTION_ELEM *elem); -static void unlink_ts_section_list(TS_SECTION_LIST *list, TS_SECTION_ELEM *elem); -static void clear_ts_section_list(TS_SECTION_LIST *list); - -static uint32_t crc32(uint8_t *head, uint8_t *tail); - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - function implementation (interface method) - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -static void release_ts_section_parser(void *parser) -{ - TS_SECTION_PARSER_PRIVATE_DATA *prv; - - prv = private_data(parser); - if(prv == NULL){ - return; - } - - teardown(prv); - - memset(parser, 0, sizeof(TS_SECTION_PARSER)); - free(prv); -} - -static int reset_ts_section_parser(void *parser) -{ - TS_SECTION_PARSER_PRIVATE_DATA *prv; - - prv = private_data(parser); - if(prv == NULL){ - return TS_SECTION_PARSER_ERROR_INVALID_PARAM; - } - - teardown(prv); - - return 0; -} - -static int put_ts_section_parser(void *parser, TS_HEADER *hdr, uint8_t *data, int size) -{ - TS_SECTION_PARSER_PRIVATE_DATA *prv; - - prv = private_data(parser); - if( (prv == NULL) || (hdr == NULL) || (data == NULL) || (size < 1) ){ - return TS_SECTION_PARSER_ERROR_INVALID_PARAM; - } - - if( (prv->pid >= 0) && (prv->pid != hdr->pid) ){ - return TS_SECTION_PARSER_ERROR_INVALID_TS_PID; - } - - prv->pid = hdr->pid; - - if(hdr->payload_unit_start_indicator == 0){ - /* exclude section start */ - return put_exclude_section_start(prv, data, size); - }else{ - /* include section start */ - return put_include_section_start(prv, data, size); - } -} - -static int get_ts_section_parser(void *parser, TS_SECTION *sect) -{ - TS_SECTION_PARSER_PRIVATE_DATA *prv; - TS_SECTION_ELEM *w; - - prv = private_data(parser); - if( (prv == NULL) || (sect == NULL) ){ - return TS_SECTION_PARSER_ERROR_INVALID_PARAM; - } - - w = get_ts_section_list_head(&(prv->buff)); - if(w == NULL){ - memset(sect, 0, sizeof(TS_SECTION)); - return TS_SECTION_PARSER_ERROR_NO_SECTION_DATA; - } - - memcpy(sect, &(w->sect), sizeof(TS_SECTION)); - put_ts_section_list_tail(&(prv->pool), w); - - return 0; -} - -static int ret_ts_section_parser(void *parser, TS_SECTION *sect) -{ - TS_SECTION_PARSER_PRIVATE_DATA *prv; - TS_SECTION_ELEM *w; - - prv = private_data(parser); - if( (prv == NULL) || (sect == NULL) ){ - return TS_SECTION_PARSER_ERROR_INVALID_PARAM; - } - - w = prv->pool.tail; - while(w != NULL){ - if(w->sect.data == sect->data){ - break; - } - w = (TS_SECTION_ELEM *)(w->prev); - } - - if( (w != NULL) && (w->ref > 0) ){ - w->ref -= 1; - } - - return 0; -} - -static int get_count_ts_section_parser(void *parser) -{ - TS_SECTION_PARSER_PRIVATE_DATA *prv; - - prv = private_data(parser); - if(prv == NULL){ - return TS_SECTION_PARSER_ERROR_INVALID_PARAM; - } - - return prv->buff.count; -} - -static int get_stat_ts_section_parser(void *parser, TS_SECTION_PARSER_STAT *stat) -{ - TS_SECTION_PARSER_PRIVATE_DATA *prv; - - prv = private_data(parser); - if( (prv == NULL) || (stat == NULL) ){ - return TS_SECTION_PARSER_ERROR_INVALID_PARAM; - } - - memcpy(stat, &(prv->stat), sizeof(TS_SECTION_PARSER_STAT)); - - return 0; -} - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - function implementation (private method) - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -static TS_SECTION_PARSER_PRIVATE_DATA *private_data(void *parser) -{ - TS_SECTION_PARSER_PRIVATE_DATA *r; - TS_SECTION_PARSER *p; - - p = (TS_SECTION_PARSER *)parser; - if(p == NULL){ - return NULL; - } - - r = (TS_SECTION_PARSER_PRIVATE_DATA *)(p->private_data); - if( ((void *)(r+1)) != parser ){ - return NULL; - } - - return r; -} - -static void teardown(TS_SECTION_PARSER_PRIVATE_DATA *prv) -{ - prv->pid = -1; - - if(prv->work != NULL){ - free(prv->work); - prv->work = NULL; - } - - prv->last = NULL; - - clear_ts_section_list(&(prv->pool)); - clear_ts_section_list(&(prv->buff)); - - memset(&(prv->stat), 0, sizeof(TS_SECTION_PARSER_STAT)); -} - -static int put_exclude_section_start(TS_SECTION_PARSER_PRIVATE_DATA *prv, uint8_t *data, int size) -{ - TS_SECTION_ELEM *w; - - w = prv->work; - if( (w == NULL) || (w->sect.raw == w->sect.tail) ){ - /* no previous data */ - return 0; - } - - append_section_data(&(w->sect), data, size); - if(check_section_complete(&(w->sect)) == 0){ - /* need more data */ - return 0; - } - - prv->work = NULL; - - if( (w->sect.hdr.section_syntax_indicator != 0) && - (crc32(w->sect.raw, w->sect.tail) != 0) ){ - cancel_elem_error(prv, w); - return TS_SECTION_PARSER_WARN_CRC_MISSMATCH; - } - - if(compare_elem_section(w, prv->last) == 0){ - /* same section data */ - cancel_elem_same(prv, w); - return 0; - } - - commit_elem_updated(prv, w); - return 0; -} - -static int put_include_section_start(TS_SECTION_PARSER_PRIVATE_DATA *prv, uint8_t *data, int size) -{ - TS_SECTION_ELEM *w; - - int pointer_field; - - uint8_t *p; - uint8_t *tail; - - int r; - int length; - - p = data; - tail = p + size; - - r = 0; - - pointer_field = p[0]; - p += 1; - - if( (p+pointer_field) >= tail ){ - /* input data is probably broken */ - w = prv->work; - prv->work = NULL; - if(w != NULL) { - if(w->sect.raw != w->sect.tail){ - cancel_elem_error(prv, w); - return TS_SECTION_PARSER_WARN_LENGTH_MISSMATCH; - } - cancel_elem_empty(prv, w); - } - return 0; - } - - if(pointer_field > 0){ - r = put_exclude_section_start(prv, p, pointer_field); - if(r < 0){ - return r; - } - p += pointer_field; - } - - w = prv->work; - prv->work = NULL; - - if(w != NULL){ - if(w->sect.raw != w->sect.tail){ - cancel_elem_error(prv, w); - r = TS_SECTION_PARSER_WARN_LENGTH_MISSMATCH; - }else{ - cancel_elem_empty(prv, w); - } - w = NULL; - } - - do { - - w = query_work_elem(prv); - if(w == NULL){ - return TS_SECTION_PARSER_ERROR_NO_ENOUGH_MEMORY; - } - - append_section_data(&(w->sect), p, tail-p); - if(check_section_complete(&(w->sect)) == 0){ - /* need more data */ - prv->work = w; - return 0; - } - length = (w->sect.tail - w->sect.raw); - - if( (w->sect.hdr.section_syntax_indicator != 0) && - (crc32(w->sect.raw, w->sect.tail) != 0) ){ - cancel_elem_error(prv, w); - r = TS_SECTION_PARSER_WARN_CRC_MISSMATCH; - }else if(compare_elem_section(w, prv->last) == 0){ - cancel_elem_same(prv, w); - }else{ - commit_elem_updated(prv, w); - } - - p += length; - - } while ( (p < tail) && (p[0] != 0xff) ); - - return r; -} - -static void reset_section(TS_SECTION *sect) -{ - memset(&(sect->hdr), 0, sizeof(TS_SECTION_HEADER)); - sect->tail = sect->raw; - sect->data = NULL; -} - -static void append_section_data(TS_SECTION *sect, uint8_t *data, int size) -{ - int m,n; - - m = sect->tail - sect->raw; - n = MAX_RAW_SECTION_SIZE - m; - - if(size < n){ - n = size; - } - memcpy(sect->tail, data, n); - sect->tail += n; - m += n; - - if(sect->data == NULL){ - extract_ts_section_header(sect); - } - - if(sect->data == NULL){ - /* need more data */ - return; - } - - n = sect->hdr.section_length + 3; - if(m > n){ - sect->tail = sect->raw + n; - } - - return; -} - -static int check_section_complete(TS_SECTION *sect) -{ - int m,n; - - if(sect->data == NULL){ - return 0; - } - - m = sect->tail - sect->raw; - n = sect->hdr.section_length + 3; - - if(n > m){ - return 0; - } - - return 1; -} - -static int compare_elem_section(TS_SECTION_ELEM *a, TS_SECTION_ELEM *b) -{ - int m,n; - - if( (a == NULL) || (b == NULL) ){ - return 1; - } - - m = a->sect.tail - a->sect.raw; - n = b->sect.tail - b->sect.raw; - if( m != n ){ - return 1; - } - - if(memcmp(a->sect.raw, b->sect.raw, m) != 0){ - return 1; - } - - return 0; -} - -static void cancel_elem_empty(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem) -{ - reset_section(&(elem->sect)); - elem->ref = 0; - put_ts_section_list_tail(&(prv->pool), elem); -} - -static void cancel_elem_error(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem) -{ - reset_section(&(elem->sect)); - elem->ref = 0; - put_ts_section_list_tail(&(prv->pool), elem); - prv->stat.total += 1; - prv->stat.error += 1; -} - -static void cancel_elem_same(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem) -{ - reset_section(&(elem->sect)); - elem->ref = 0; - put_ts_section_list_tail(&(prv->pool), elem); - prv->stat.total +=1; -} - -static void commit_elem_updated(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem) -{ - if( (prv->last != NULL) && (prv->last->ref > 0) ){ - prv->last->ref -= 1; - } - - elem->ref = 2; - prv->last = elem; - put_ts_section_list_tail(&(prv->buff), elem); - prv->stat.total += 1; - prv->stat.unique += 1; -} - -static TS_SECTION_ELEM *query_work_elem(TS_SECTION_PARSER_PRIVATE_DATA *prv) -{ - TS_SECTION_ELEM *r; - - r = prv->pool.head; - while(r != NULL){ - if(r->ref < 1){ - break; - } - r = (TS_SECTION_ELEM *)(r->next); - } - - if(r != NULL){ - unlink_ts_section_list(&(prv->pool), r); - reset_section(&(r->sect)); - r->ref = 0; - return r; - } - - return create_ts_section_elem(); -} - -static void extract_ts_section_header(TS_SECTION *sect) -{ - int size; - uint8_t *p; - - sect->data = NULL; - - size = sect->tail - sect->raw; - if(size < 3){ - /* need more data */ - return; - } - - p = sect->raw; - - sect->hdr.table_id = p[0]; - sect->hdr.section_syntax_indicator = (p[1] >> 7) & 0x01; - sect->hdr.private_indicator = (p[1] >> 6) & 0x01; - sect->hdr.section_length =((p[1] << 8) | p[2]) & 0x0fff; - - if(sect->hdr.section_syntax_indicator == 0){ - /* short format section header */ - sect->data = p+3; - return; - } - - /* long format section header */ - - if(size < 8){ - /* need more data */ - return; - } - - sect->hdr.table_id_extension =((p[3] << 8) | p[4]); - sect->hdr.version_number = (p[5] >> 1) & 0x1f; - sect->hdr.current_next_indicator = p[5] & 0x01; - sect->hdr.section_number = p[6]; - sect->hdr.last_section_number = p[7]; - - sect->data = p+8; - - return; -} - -static TS_SECTION_ELEM *create_ts_section_elem() -{ - TS_SECTION_ELEM *r; - int n; - - n = sizeof(TS_SECTION_ELEM) + MAX_RAW_SECTION_SIZE; - r = (TS_SECTION_ELEM *)calloc(1, n); - if(r == NULL){ - /* failed on malloc() */ - return NULL; - } - - r->sect.raw = (uint8_t *)(r+1); - r->sect.tail = r->sect.raw; - - return r; -} - -static TS_SECTION_ELEM *get_ts_section_list_head(TS_SECTION_LIST *list) -{ - TS_SECTION_ELEM *r; - - if(list == NULL){/* invalid param */ - return NULL; - } - - r = list->head; - if(r == NULL){ - return NULL; - } - - list->head = (TS_SECTION_ELEM *)(r->next); - if(list->head != NULL){ - list->head->prev = NULL; - list->count -= 1; - }else{ - list->tail = NULL; - list->count = 0; - } - - r->next = NULL; - - return r; -} - -static void put_ts_section_list_tail(TS_SECTION_LIST *list, TS_SECTION_ELEM *elem) -{ - if( (list == NULL) || (elem == NULL) ){ - /* invalid param */ - return; - } - - if(list->tail != NULL){ - elem->prev = list->tail; - elem->next = NULL; - list->tail->next = elem; - list->tail = elem; - list->count += 1; - }else{ - elem->prev = NULL; - elem->next = NULL; - list->head = elem; - list->tail = elem; - list->count = 1; - } -} - -static void unlink_ts_section_list(TS_SECTION_LIST *list, TS_SECTION_ELEM *elem) -{ - TS_SECTION_ELEM *prev; - TS_SECTION_ELEM *next; - - if( (list == NULL) || (elem == NULL) ){ - /* invalid param */ - return; - } - - prev = (TS_SECTION_ELEM *)(elem->prev); - next = (TS_SECTION_ELEM *)(elem->next); - - if(prev != NULL){ - prev->next = next; - }else{ - list->head = next; - } - if(next != NULL){ - next->prev = prev; - }else{ - list->tail = prev; - } - list->count -= 1; -} - -static void clear_ts_section_list(TS_SECTION_LIST *list) -{ - TS_SECTION_ELEM *e; - TS_SECTION_ELEM *n; - - if(list == NULL){ /* invalid param */ - return; - } - - e = list->head; - while(e != NULL){ - n = (TS_SECTION_ELEM *)(e->next); - free(e); - e = n; - } - - list->head = NULL; - list->tail = NULL; - list->count = 0; -} - -static uint32_t crc32(uint8_t *head, uint8_t *tail) -{ - uint32_t crc; - uint8_t *p; - - static const uint32_t table[256] = { - 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, - 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, - 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, - 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, - - 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, - 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75, - 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, - 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD, - - 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, - 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, - 0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81, - 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D, - - 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, - 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95, - 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, - 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, - - 0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE, - 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072, - 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, - 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, - - 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, - 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, - 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066, - 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, - - 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, - 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692, - 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, - 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, - - 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, - 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, - 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, - 0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A, - - 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, - 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, - 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, - 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, - - 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, - 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B, - 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, - 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, - - 0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, - 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B, - 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, - 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3, - - 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, - 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, - 0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F, - 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3, - - 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, - 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, - 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, - 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, - - 0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30, - 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC, - 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, - 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, - - 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, - 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, - 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18, - 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, - - 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, - 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C, - 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, - 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4, - }; - - crc = 0xffffffff; - - p = head; - while(p < tail){ - crc = (crc << 8) ^ table[ ((crc >> 24) ^ p[0]) & 0xff ]; - p += 1; - } - - return crc; -} - diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/src/ts_section_parser.h --- a/arib25v023/arib25/src/ts_section_parser.h Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -#ifndef TS_SECTION_PARSER_H -#define TS_SECTION_PARSER_H - -#include "ts_common_types.h" - -typedef struct { - int64_t total; /* total received section count */ - int64_t unique; /* unique section count */ - int64_t error; /* crc and other error section count */ -} TS_SECTION_PARSER_STAT; - -typedef struct { - - void *private_data; - - void (* release)(void *parser); - - int (* reset)(void *parser); - - int (* put)(void *parser, TS_HEADER *hdr, uint8_t *data, int size); - int (* get)(void *parser, TS_SECTION *sect); - int (* ret)(void *parser, TS_SECTION *sect); - - int (* get_count)(void *parser); - - int (* get_stat)(void *parser, TS_SECTION_PARSER_STAT *stat); - -} TS_SECTION_PARSER; - -#ifdef __cplusplus -extern "C" { -#endif - -extern TS_SECTION_PARSER *create_ts_section_parser(); - -#ifdef __cplusplus -} -#endif - -#endif /* TS_SECTION_PARSER_H */ diff -r db7af62da709 -r 41a5481db56f arib25v023/arib25/src/ts_section_parser_error_code.h --- a/arib25v023/arib25/src/ts_section_parser_error_code.h Sat Aug 29 05:36:06 2009 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -#ifndef TS_SECTION_PARSER_ERROR_CODE_H -#define TS_SECTION_PARESR_ERROR_CODE_H - -#define TS_SECTION_PARSER_ERROR_INVALID_PARAM -1 -#define TS_SECTION_PARSER_ERROR_NO_ENOUGH_MEMORY -2 -#define TS_SECTION_PARSER_ERROR_INVALID_TS_PID -3 -#define TS_SECTION_PARSER_ERROR_NO_SECTION_DATA -4 - -#define TS_SECTION_PARSER_WARN_CRC_MISSMATCH 1 -#define TS_SECTION_PARSER_WARN_LENGTH_MISSMATCH 2 - -#endif /* TS_SECTION_PARSER_ERROR_CODE_H */