Beispiel #1
0
 /// <summary>
 /// Callback from driver, returning CI menu headers
 /// </summary>
 /// <param name="slot">Slot</param>
 /// <param name="lpszTitle">Title</param>
 /// <param name="lpszSubTitle">Subtitle</param>
 /// <param name="lpszBottom">Bottom text</param>
 /// <param name="nNumChoices">Number of choices</param>
 /// <param name="pParam">Context pointer</param>
 public void OnCiMenu(byte slot, String lpszTitle, String lpszSubTitle, String lpszBottom, uint nNumChoices,
                      IntPtr pParam)
 {
     try
     {
         lock (this)
         {
             Log.Log.Debug("OnKncCiMenu slot:       {0}", slot);
             Log.Log.Debug("OnKncCiMenu title:      {0}", lpszTitle);
             Log.Log.Debug("OnKncCiMenu subtitle:   {0}", lpszSubTitle);
             Log.Log.Debug("OnKncCiMenu bottom:     {0}", lpszSubTitle);
             Log.Log.Debug("OnKncCiMenu lpszBottom: {0}", lpszBottom);
             Log.Log.Debug("OnKncCiMenu nNumChoices:{0}", nNumChoices);
             if (m_ciMenuCallback != null)
             {
                 m_ciMenuCallback.OnCiMenu(lpszTitle.ToString(), lpszSubTitle.ToString(), lpszBottom.ToString(),
                                           (int)nNumChoices);
             }
         }
     }
     catch (Exception ex)
     {
         Log.Log.Debug("OnKncCiMenu exception: {0}", ex.ToString());
     }
 }
        /// <summary>
        /// Process the MMI and do callbacks.
        /// </summary>
        /// <param name="CiMenu"></param>
        /// <returns></returns>
        private bool ProcessCamMenu(DD_CAM_MENU_DATA CiMenu)
        {
            Log.Log.Debug("Menu received (ID {0} Type {1} Choices {2})", CiMenu.Id, CiMenu.Type, CiMenu.NumChoices);
            //Log.Log.Debug(" Menu Id      = {0}", CiMenu.Id);
            //Log.Log.Debug(" Menu Type    = {0}", CiMenu.Type);
            //Log.Log.Debug(" Menu Choices = {0}", CiMenu.NumChoices);
            //Log.Log.Debug(" Menu Length  = {0}", CiMenu.Length);

            if (ciMenuCallbacks == null)
            {
                return(false);
            }

            switch (CiMenu.Type)
            {
            case 1:
            case 2:
                ciMenuCallbacks.OnCiMenu(CiMenu.Title, CiMenu.SubTitle, CiMenu.BottomText, CiMenu.NumChoices);
                int n = 0;
                foreach (String choice in CiMenu.Choices)
                {
                    ciMenuCallbacks.OnCiMenuChoice(n++, choice);
                }
                break;

            case 3:
            case 4:
                ciMenuCallbacks.OnCiRequest(false, (uint)CiMenu.NumChoices, CiMenu.Title);
                break;

            default:
                Log.Log.Debug("Unknown MMI Type {0}", CiMenu.Type);
                break;
            }
            return(true);
        }
Beispiel #3
0
        /// <summary>
        /// Thread that checks for CI menu
        /// </summary>
        private void CiMenuHandler()
        {
            Log.Log.Debug("TwinHan: CI handler thread start polling status");
            try
            {
                while (!StopThread)
                {
                    uint CIState;
                    uint MMIState;
                    GetCAMStatus(out CIState, out MMIState, true);
                    switch (MMIState)
                    {
                    case 3: // TODO: find proper MMIState codings
                        MMIInfoStruct MMI = ReadMMI();
                        if (MMI != null)
                        {
                            Log.Log.Debug("TwinHan MMI:");
                            Log.Log.Debug("Type        :{0}", MMI.Type);
                            Log.Log.Debug("Header:      {0}", MMI.Header);
                            Log.Log.Debug("SubHeader:   {0}", MMI.SubHeader);
                            Log.Log.Debug("ButtomLine:  {0}", MMI.BottomLine);
                            Log.Log.Debug("ItemCount:   {0}", MMI.ItemCount);
                            Log.Log.Debug("EnqFlag:     {0}", MMI.EnqFlag);
                            Log.Log.Debug("Prompt:      {0}", MMI.Prompt);
                            Log.Log.Debug("AnswerLength:{0}", MMI.Answer_Text_Length);
                            Log.Log.Debug("Blind_Answer:{0}", MMI.Blind_Answer);

                            // which types do we get???
                            switch (MMI.Type)
                            {
                            case 0:
                                m_ciMenuCallback.OnCiCloseDisplay(0);
                                break;

                            case 1:
                                if (m_ciMenuCallback != null)
                                {
                                    m_ciMenuCallback.OnCiMenu(MMI.Header, MMI.SubHeader, MMI.BottomLine, MMI.ItemCount);
                                    for (int m = 0; m < MMI.ItemCount; m++)
                                    {
                                        // choice number start with 0
                                        m_ciMenuCallback.OnCiMenuChoice(m, MMI.MenuItems[m].MenuItem);
                                    }
                                }
                                break;

                            case 3:
                                if (MMI.EnqFlag != 0)
                                {
                                    if (m_ciMenuCallback != null)
                                    {
                                        m_ciMenuCallback.OnCiRequest((MMI.Blind_Answer == 1), (uint)MMI.Answer_Text_Length, MMI.Prompt);
                                    }
                                }
                                break;
                            }
                        }
                        break;

                    default:
                        Log.Log.Write("MMI State {0}", (CIState)MMIState);
                        break;
                    }
                    Thread.Sleep(500);
                }
            }
            catch (ThreadAbortException) {}
            catch (Exception ex)
            {
                Log.Log.Debug("TwinHan: error in CiMenuHandler thread\r\n{0}", ex.ToString());
                return;
            }
        }
Beispiel #4
0
        /// <summary>
        /// Handles APDU (MMI) objects and perform callbacks
        /// </summary>
        /// <param name="MMI">MMI byte[]</param>
        /// <param name="MMI_length">length</param>
        public void HandleMMI(byte[] MMI, int MMI_length)
        {
            // parse starting 3 bytes == tag
            DVB_MMI.MMI_TAGS uMMITag = DVB_MMI.ToMMITag(MMI, 0);

            // dumping binary APDU
#if DEBUG
            DVB_MMI.DumpBinary(MMI, 0, MMI_length);
#endif

            // calculate length and offset
            int countLengthBytes;
            int mmiLength = DVB_MMI.GetLength(MMI, 3 /* bytes for mmi_tag */, out countLengthBytes);
            int mmiOffset = 3 + countLengthBytes; // 3 bytes mmi tag + 1 byte length field ?

#if DEBUG
            Log.Log.Debug("{0}: MMITag:{1}, MMIObjectLength: {2} ({2:X2}), mmiOffset: {3}", m_cardName, uMMITag, mmiLength,
                          mmiOffset);
#endif
            int offset = 0; // starting with 0; reading whole struct from start
            if (uMMITag == DVB_MMI.MMI_TAGS.CLOSE)
            {
                // Close menu
                byte nDelay   = 0;
                byte CloseCmd = MMI[mmiOffset + 0];
                if (CloseCmd != 0)
                {
                    nDelay = MMI[mmiOffset + 1];
                }
                if (m_ciMenuCallback != null)
                {
                    Log.Log.Debug("{0}: OnCiClose()", m_cardName);
                    m_ciMenuCallback.OnCiCloseDisplay(nDelay);
                }
                else
                {
                    Log.Log.Debug("{0}: OnCiCloseDisplay: cannot do callback!", m_cardName);
                }
            }
            if (uMMITag == DVB_MMI.MMI_TAGS.ENQUIRY)
            {
                // request input
                bool   bPasswordMode      = false;
                byte   answer_text_length = MMI[mmiOffset + 1];
                string strText            = "";

                if ((MMI[mmiOffset + 0] & 0x01) != 0)
                {
                    bPasswordMode = true;
                }

                // mmioffset +4 because there a 2 other bytes before text starts
                // length is these 2 bytes shorter
                strText = DVB_MMI.BytesToString(MMI, mmiOffset + 4, mmiLength - mmiOffset - 2);
                if (m_ciMenuCallback != null)
                {
                    Log.Log.Debug("{0}: OnCiRequest: bPasswordMode:{1}, answer_text_length:{2}, strText:{3}", m_cardName,
                                  bPasswordMode, answer_text_length, strText);
                    m_ciMenuCallback.OnCiRequest(bPasswordMode, answer_text_length, strText);
                }
                else
                {
                    Log.Log.Debug("{0}: OnCiRequest: cannot do callback!", m_cardName);
                }
            }
            if (uMMITag == DVB_MMI.MMI_TAGS.LIST_LAST || uMMITag == DVB_MMI.MMI_TAGS.MENU_LAST ||
                uMMITag == DVB_MMI.MMI_TAGS.MENU_MORE || uMMITag == DVB_MMI.MMI_TAGS.LIST_MORE)
            {
                // step forward; begin with offset+1; stop when 0x9F reached
                // should be modified to offset + mmioffset+1 ?
                offset++;
                while (MMI[offset] != (byte)0x9F)
                {
                    //Log.Log.Debug("Skip to offset {0} value {1:X2}", offset, MMI[offset]);
                    offset++;
                }
                uMMITag = DVB_MMI.ToMMITag(MMI, offset); // get next MMI tag
                Log.Log.Debug("{0}: MMI Parse: Got MENU_LAST, skipped to next block on index: {1}; new Tag {2}", m_cardName,
                              offset, uMMITag);

                int           nChoices = 0;
                List <string> Choices  = new List <string>();
                // Always three line with menu info (DVB Standard)
                // Title Text
                offset += DVB_MMI.GetCIText(MMI, offset, ref Choices);
                // Subtitle Text
                offset += DVB_MMI.GetCIText(MMI, offset, ref Choices);
                // Bottom Text
                offset += DVB_MMI.GetCIText(MMI, offset, ref Choices);

                // first step through the choices, to get info and count them
                int max = 20;
                while (max-- > 0)
                {
                    // if the offset gets to mmi object length then end here
                    if (offset >= mmiLength - 1)
                    {
                        break;
                    }

                    offset += DVB_MMI.GetCIText(MMI, offset, ref Choices);
                    nChoices++;
                }
                // when title and choices are ready now, send to client
#if DEBUG
                for (int c = 0; c < Choices.Count; c++)
                {
                    Log.Log.Debug("{0}: {1} : {2}", m_cardName, c, Choices[c]);
                }
#endif
                if (m_ciMenuCallback != null)
                {
                    m_ciMenuCallback.OnCiMenu(Choices[0], Choices[1], Choices[2], nChoices);
                    for (int c = 3; c < Choices.Count; c++)
                    {
                        m_ciMenuCallback.OnCiMenuChoice(c - 3, Choices[c]);
                    }
                }
                else
                {
                    Log.Log.Debug("{0}: OnCiMenu: cannot do callback!", m_cardName);
                }
            }
        }