+void eDVBCAService::registerChannelCallback(eDVBResourceManager *res_mgr)
+{
+ res_mgr->connectChannelAdded(slot(&DVBChannelAdded), m_chanAddedConn);
+}
+
+void eDVBCAService::DVBChannelAdded(eDVBChannel *chan)
+{
+ if ( chan )
+ {
+ eDebug("[eDVBCAService] new channel %p!", chan);
+ channel_data *data = new channel_data();
+ data->m_channel = chan;
+ data->m_prevChannelState = -1;
+ data->m_dataDemux = -1;
+ exist_channels[chan] = data;
+ chan->connectStateChange(slot(&DVBChannelStateChanged), data->m_stateChangedConn);
+ }
+}
+
+void eDVBCAService::DVBChannelStateChanged(iDVBChannel *chan)
+{
+ ChannelMap::iterator it =
+ exist_channels.find(chan);
+ if ( it != exist_channels.end() )
+ {
+ int state=0;
+ chan->getState(state);
+ if ( it->second->m_prevChannelState != state )
+ {
+ switch (state)
+ {
+ case iDVBChannel::state_ok:
+ {
+ eDebug("[eDVBCAService] channel %p running", chan);
+ break;
+ }
+ case iDVBChannel::state_release:
+ {
+ eDebug("[eDVBCAService] remove channel %p", chan);
+ unsigned char msg[8] = { 0x9f,0x80,0x3f,0x04,0x83,0x02,0x00,0x00 };
+ msg[7] = it->second->m_dataDemux & 0xFF;
+ int sock, clilen;
+ struct sockaddr_un servaddr;
+ memset(&servaddr, 0, sizeof(struct sockaddr_un));
+ servaddr.sun_family = AF_UNIX;
+ strcpy(servaddr.sun_path, "/tmp/camd.socket");
+ clilen = sizeof(servaddr.sun_family) + strlen(servaddr.sun_path);
+ sock = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (sock > -1)
+ {
+ connect(sock, (struct sockaddr *) &servaddr, clilen);
+ fcntl(sock, F_SETFL, O_NONBLOCK);
+ int val=1;
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, 4);
+ if (write(sock, msg, 8) != 8)
+ eDebug("[eDVBCAService] write leave transponder failed!!");
+ close(sock);
+ }
+ exist_channels.erase(it);
+ delete it->second;
+ it->second=0;
+ break;
+ }
+ default: // ignore all other events
+ return;
+ }
+ if (it->second)
+ it->second->m_prevChannelState = state;
+ }
+ }
+}
+
+channel_data *eDVBCAService::getChannelData(eDVBChannelID &chid)
+{
+ for (ChannelMap::iterator it(exist_channels.begin()); it != exist_channels.end(); ++it)
+ {
+ if (chid == it->second->m_channel->getChannelID())
+ return it->second;
+ }
+ return 0;
+}
+// end static methods
+
+#define CA_REPLY_DEBUG
+#define MAX_LENGTH_BYTES 4
+#define MIN_LENGTH_BYTES 1
+
+void eDVBCAService::socketCB(int what)
+{
+ if (what & (eSocketNotifier::Read | eSocketNotifier::Priority))
+ {
+ char msgbuffer[4096];
+ ssize_t length = read(m_sock, msgbuffer, sizeof(msgbuffer));
+ if (length == -1)
+ {
+ if (errno != EAGAIN && errno != EINTR && errno != EBUSY)
+ {
+ eDebug("[eSocketMMIHandler] read (%m)");
+ what |= eSocketNotifier::Error;
+ }
+ } else if (length == 0)
+ {
+ what |= eSocketNotifier::Hungup;
+ } else
+ {
+ int len = length;
+ unsigned char *data = (unsigned char*)msgbuffer;
+ int clear = 1;
+ // If a new message starts, then the previous message
+ // should already have been processed. Otherwise the
+ // previous message was incomplete and should therefore
+ // be deleted.
+ if ((len >= 1) && ((data[0] & 0xFF) != 0x9f))
+ clear = 0;
+ if ((len >= 2) && ((data[1] & 0x80) != 0x80))
+ clear = 0;
+ if ((len >= 3) && ((data[2] & 0x80) != 0x00))
+ clear = 0;
+ if (clear)
+ {
+ m_buffer.clear();
+#ifdef CA_REPLY_DEBUG
+ eDebug("clear buffer");
+#endif
+ }
+#ifdef CA_REPLY_DEBUG
+ eDebug("Put to buffer:");
+ for (int i=0; i < len; ++i)
+ eDebugNoNewLine("%02x ", data[i]);
+ eDebug("\n--------");
+#endif
+ m_buffer.write( data, len );
+
+ while ( m_buffer.size() >= (3 + MIN_LENGTH_BYTES) )
+ {
+ unsigned char tmp[3+MAX_LENGTH_BYTES];
+ m_buffer.peek(tmp, 3+MIN_LENGTH_BYTES);
+ if (((tmp[0] & 0xFF) != 0x9f) || ((tmp[1] & 0x80) != 0x80) || ((tmp[2] & 0x80) != 0x00))
+ {
+ m_buffer.skip(1);
+#ifdef CA_REPLY_DEBUG
+ eDebug("skip %02x", tmp[0]);
+#endif
+ continue;
+ }
+ if (tmp[3] & 0x80)
+ {
+ int peekLength = (tmp[3] & 0x7f) + 4;
+ if (m_buffer.size() < peekLength)
+ continue;
+ m_buffer.peek(tmp, peekLength);
+ }
+ int size=0;
+ int LengthBytes=eDVBCISession::parseLengthField(tmp+3, size);
+ int messageLength = 3+LengthBytes+size;
+ if ( m_buffer.size() >= messageLength )
+ {
+ unsigned char dest[messageLength];
+ m_buffer.read(dest, messageLength);
+#ifdef CA_REPLY_DEBUG
+ eDebug("dump ca reply:");
+ for (int i=0; i < messageLength; ++i)
+ eDebugNoNewLine("%02x ", dest[i]);
+ eDebug("\n--------");
+#endif
+// /*emit*/ mmi_progress(0, dest, (const void*)(dest+3+LengthBytes), messageLength-3-LengthBytes);
+ }
+ }
+ }
+ }
+ if (what & eSocketNotifier::Hungup) {
+ /*eDebug("[eDVBCAService] connection closed")*/;
+ m_sendstate=1;
+ sendCAPMT();
+ }
+ if (what & eSocketNotifier::Error)
+ eDebug("[eDVBCAService] connection error");
+}
+