internal FruDevice ReadFru(int deviceId, bool maxLenght = false)
        {
            byte countToRead = 8; //FRU common header size

            GetFruDataResponse fruResponse =
                IpmiSendReceive <GetFruDataResponse>(new GetFruDataRequest(0, 0, countToRead)
            {
                DeviceId = (byte)deviceId
            });

            if (fruResponse.CompletionCode == 0x00)
            {
                FruCommonHeader commonHeader = new FruCommonHeader(fruResponse.DataReturned);

                ushort areaOffset;

                byte[] chassisInfo     = null;
                byte[] boardInfo       = null;
                byte[] productInfo     = null;
                byte[] multiRecordInfo = null;
                byte   completionCode  = fruResponse.CompletionCode;

                areaOffset = commonHeader.ChassisInfoStartingOffset;
                if (areaOffset != 0)
                {
                    chassisInfo = ReadFruAreaBytes(deviceId, areaOffset, maxLenght, out completionCode);
                }

                areaOffset = commonHeader.BoardAreaStartingOffset;
                if (areaOffset != 0)
                {
                    boardInfo = ReadFruAreaBytes(deviceId, areaOffset, maxLenght, out completionCode);
                }

                areaOffset = commonHeader.ProductAreaStartingOffset;
                if (areaOffset != 0)
                {
                    productInfo = ReadFruAreaBytes(deviceId, areaOffset, maxLenght, out completionCode);
                }

                areaOffset = commonHeader.MultiRecordAreaStartingOffset;
                if (areaOffset != 0)
                {
                    multiRecordInfo = ReadFruAreaBytes(deviceId, areaOffset, maxLenght, out completionCode);
                }


                return(new FruDevice(deviceId,
                                     commonHeader,
                                     chassisInfo,
                                     boardInfo,
                                     productInfo,
                                     multiRecordInfo,
                                     completionCode));
            }
            else
            {
                return(new FruDevice(fruResponse.CompletionCode));
            }
        }
        /// <summary>
        /// Reads raw fru data, and returns a byte array.
        /// </summary>
        public virtual byte[] ReadFruDevice(int deviceId, ushort offset, byte readCount)
        {
            byte loOffset;
            byte hiOffset;

            // split address into hi and lo bytes.
            IpmiSharedFunc.SplitWord(offset, out loOffset, out hiOffset);

            GetFruDataResponse fruResponse =
                this.IpmiSendReceive <GetFruDataResponse>(new GetFruDataRequest(loOffset, hiOffset, readCount)
            {
                DeviceId = (byte)deviceId
            });

            return(fruResponse.DataReturned);
        }
        /// <summary>
        /// Returns a byte array with all bytes from a specific area of the fru: Chassis, Baseboard, Product
        /// </summary>
        private byte[] ReadFruAreaBytes(int deviceId, ushort offset, bool maxLenght, out byte completionCode)
        {
            byte countToRead = 0x10;
            byte loOffset;
            byte hiOffset;

            List <byte> areaBytes = new List <byte>();

            IpmiSharedFunc.SplitWord(offset, out loOffset, out hiOffset);

            ushort            totalDataRead = countToRead;
            GetFruDataRequest fruRequest    =
                new GetFruDataRequest(loOffset, hiOffset, countToRead)
            {
                DeviceId = (byte)deviceId
            };

            GetFruDataResponse fruResponse = IpmiSendReceive <GetFruDataResponse>(fruRequest);

            completionCode = fruResponse.CompletionCode;

            if (completionCode == 0x00)
            {
                ushort dataSize = FruArea.AreaLength(fruResponse.DataReturned);
                totalDataRead = Math.Min(countToRead, dataSize);
                IpmiSharedFunc.AppendArrayToList(fruResponse.DataReturned, areaBytes, totalDataRead);
                offset += totalDataRead;
                int pass = 0;

                while (dataSize > totalDataRead || pass > 12)
                {
                    IpmiSharedFunc.SplitWord(offset, out loOffset, out hiOffset);

                    if (!maxLenght)
                    {
                        countToRead = (byte)Math.Min(countToRead, dataSize - totalDataRead);
                    }
                    else
                    {
                        countToRead = (byte)Math.Min(byte.MaxValue, dataSize - totalDataRead);
                    }

                    fruRequest = new GetFruDataRequest(loOffset, hiOffset, countToRead)
                    {
                        DeviceId = (byte)deviceId
                    };
                    // send request for more data
                    fruResponse    = IpmiSendReceive <GetFruDataResponse>(fruRequest);
                    totalDataRead += countToRead;
                    offset        += countToRead;

                    completionCode = fruResponse.CompletionCode;

                    if (completionCode == 0x00)
                    {
                        IpmiSharedFunc.AppendArrayToList(fruResponse.DataReturned, areaBytes, countToRead);
                    }
                    else
                    {
                        break;
                    }

                    pass++;
                }

                if (pass > 12)
                {
                    completionCode = 0xEF;
                }
            }

            return(areaBytes.ToArray());
        }