/// <summary>
        /// Split and compress the complete virtual channel data into chunk data.
        /// </summary>
        /// <param name="completeData">The compete virtual channel data. This argument can be null.</param>
        /// <returns>The splitted chunk data.</returns>
        internal ChannelChunk[] SplitToChunks(byte[] completeData, int maxBit  =16)
        {
            if (completeData == null || completeData.Length <= 0)
            {
                return null;
            }

            // calculate the number of the chunks
            int chunkNum = (int)(completeData.Length / maxChunkSize);
            if ((completeData.Length % maxChunkSize) != 0)
            {
                chunkNum++;
            }

            ChannelChunk[] chunks = new ChannelChunk[chunkNum];

            uint chunkSize = maxChunkSize;

            // fill the chunks except the last one
            for (int i = 0; i < chunkNum; i++)
            {
                if (i == chunkNum - 1)   // the last chunk
                {
                    chunkSize = (uint)(completeData.Length - maxChunkSize * i);
                }

                byte[] chunkData = new byte[chunkSize];
                Array.Copy(completeData, maxChunkSize * i, chunkData, 0, chunkSize);
                chunks[i].channelPduHeader.length = (uint)completeData.Length;
                if (mppcCompressor != null && channelOptions == Channel_Options.COMPRESS)   // has compression
                {
                    CompressMode flag;
                    chunks[i].chunkData = mppcCompressor.Compress(chunkData, out flag);

                    if ((flag & CompressMode.Compressed) == CompressMode.Compressed)
                    {
                        chunks[i].channelPduHeader.flags |= CHANNEL_PDU_HEADER_flags_Values.CHANNEL_PACKET_COMPRESSED;
                    }

                    if ((flag & CompressMode.Flush) == CompressMode.Flush)
                    {
                        chunks[i].channelPduHeader.flags |= CHANNEL_PDU_HEADER_flags_Values.CHANNEL_PACKET_FLUSHED;
                    }

                    if ((flag & CompressMode.SetToFront) == CompressMode.SetToFront)
                    {
                        chunks[i].channelPduHeader.flags |= CHANNEL_PDU_HEADER_flags_Values.CHANNEL_PACKET_AT_FRONT;
                    }
                }
                else                          // no compression
                {
                    chunks[i].chunkData = chunkData;
                }
            }

            // set the first chunk CHANNEL_FLAG_FIRST
            chunks[0].channelPduHeader.flags |= CHANNEL_PDU_HEADER_flags_Values.CHANNEL_FLAG_FIRST;
            // the last chunk
            chunks[chunkNum - 1].channelPduHeader.flags |= CHANNEL_PDU_HEADER_flags_Values.CHANNEL_FLAG_LAST;

            return chunks;
        }