Example #1
0
        /// <summary>
        /// Convert raw message to BabelMessage.
        /// Called by a port with an incoming raw message.
        /// Must return as soon as possible, so convert and put on incoming Q for later relay.
        /// Caller frees the underlying raw message.
        /// TODO: Process long message if necessary: start a long list.
        /// </summary>
        /// <param name="exchange"></param>
        /// <param name="mtx"></param>
        /// <returns></returns>
        public static byte ProcessIncomingRawMesssage(MessageExchange exchange, MessageTransaction mtx)
        {
            PacketBuffer g = mtx.MsgBuffer;
            BabelMessage m = new BabelMessage(exchange);

            m.Pid                = (byte)(g.flagsPid & ProtocolConstants.PID_MASK);
            m.Verified           = (m.Pid == ProtocolConstants.PID_GENERAL_V);
            m.Receiver           = ProtocolConstants.ADRS_LOCAL;
            m.FlagsRS            = g.flagsRS();
            m.IncomingNetIfIndex = mtx.ONetIfIndex;
            m.OutgoingNetIfIndex = ProtocolConstants.NETIF_UNSET;
            m.Cmd                = 0;
            switch (m.Pid)
            {
            case ProtocolConstants.PID_GENERAL:
            case ProtocolConstants.PID_GENERAL_V:
                m.IsGeneral   = true;
                m.IsHandshake = false;
                m.Receiver    = g.receiver();
                m.Cmd         = g.command();
                m.FlagsRS     = g.flagsRS();
                break;

            default:
                return(1);
            }
            m.Sender   = g.sender();
            m.SenderId = g.senderId();
            m.DataLen  = g.dataLength();
            m.DataAry  = mtx.CopyMessageData();
            // Now submit message to be relayed later.
            exchange.SubmitIncomingMessage(m);
            return(0);
        }
Example #2
0
        /// <summary>
        /// Handle a message sent to virtual port.
        /// This is a helper wrapper for CommandHandler.
        /// </summary>
        /// <param name="ioIndex"></param>
        /// <returns>Returns 0 if dealt with to completion and freed.
        /// Otherwise, returns error code, caller must free buffer.
        /// </returns>
        public override byte MessageCommandHandler(int ioIndex)
        {
            MessageTransaction bmc = new MessageTransaction(Manager);
            byte err = bmc.StartMessageTransaction(ioIndex);

            if (err != 0)
            {
                return(err);
            }
            err = CommandHandler(bmc);
            if (err != 0)
            {
                return(err);
            }
            bmc.FinishMessageTransaction();
            return(0);
        }
Example #3
0
 public virtual byte CommandHandler(MessageTransaction mtx)
 {
     return(0);
 }
Example #4
0
        // Process Port commands.
        // Returns zero on success.
        public override byte CommandHandler(MessageTransaction mtx)
        {
            PacketBuffer g       = mtx.MsgBuffer;
            Boolean      isReply = ((g.flagsRS() & ProtocolConstants.MESSAGE_FLAGS_IS_REPLY) != 0);

            if (((!isReply) && (g.command() < ProtocolConstants.MEDIATOR_CONTROL_CMD_BASE)) ||
                (isReply && (g.senderId() == ProtocolConstants.IDENT_MEDIATOR)))
            {
                byte   dataIndex = ProtocolConstants.GENERAL_DATA_ARRAY_OFFSET;
                byte[] tmp;
                switch (g.command())
                {
                // Standard device commands.
                case ProtocolConstants.MEDIATOR_DEVICE_RESET:     // Reset the module.
                    Manager.AppBabelDeviceReset();
                    break;

                case ProtocolConstants.MEDIATOR_DEVICE_STATUS:     // Get device status.
                    if (isReply)
                    {
                        return(1);
                    }
                    g.dataLength(Diagnostics.GetDeviceStatus(Manager, g.buffer));
                    mtx.ChangeDir = true;
                    mtx.Finish    = MessageTransaction.FinishAction.Normal;
                    break;

                case ProtocolConstants.MEDIATOR_DEVICE_TICKER:     // Get device ticker count.
                    if (isReply)
                    {
                        return(1);             // We've been sent a ticker count.
                    }
                    // Sender wants to know ticker count.
                    tmp = Primitives.UIntToByteArray(Primitives.GetBabelMilliTicker());
                    return(mtx.StoreMessageValue(tmp, (byte)(tmp.Length)));

                case ProtocolConstants.MEDIATOR_DEVICE_ERASE:     // TODO: erase eeprom and restart.
                    return(2);

                case ProtocolConstants.MEDIATOR_DEVICE_READVAR:
                    return((MediatorReadCommand(mtx) == 0) ? (byte)1 : (byte)0);

                case ProtocolConstants.MEDIATOR_DEVICE_WRITEVAR:
                    return((MediatorWriteCommand(mtx) == 0) ? (byte)1 : (byte)0);

                case ProtocolConstants.MEDIATOR_DEVICE_ISOVAR:
                    return((MediatorIsoCommand(mtx) == 0) ? (byte)1 : (byte)0);

                case ProtocolConstants.MEDIATOR_DEVICE_ISOMONVAR:
                    return((MediatorIsoCommand(mtx) == 0) ? (byte)1 : (byte)0);

                case ProtocolConstants.MEDIATOR_DEVICE_ISOMSG:
                    return((MediatorIsoCommand(mtx) == 0) ? (byte)1 : (byte)0);

                case ProtocolConstants.MEDIATOR_DEVICE_LOG:
                    if (!isReply)
                    {
                        if (Settings.LogOn)
                        {
                            uint   ticks = (uint)Primitives.GetArrayValueU(g.buffer, dataIndex, 4);
                            string s;
                            byte   logType = g.buffer[dataIndex + 4];
                            if (Settings.LogBinary || logType == 'B')
                            {
                                int start = dataIndex + 5;
                                int last  = dataIndex + g.dataLength();
                                s = "(";
                                for (int k = start; k < last; k++)
                                {
                                    s = s + g.buffer[k].ToString("X2") + " ";
                                }
                                s += ")";
                            }
                            else
                            {
                                s = Primitives.GetArrayStringValue(g.buffer, dataIndex + 5, g.dataLength() - 5);
                            }
                            Log.d("MediatorNetIf:" + Exchange.Id, ":" + ticks + ":" + s);
                        }
                    }
                    return(1);

                // Connection specific commands.
                case ProtocolConstants.MEDIATOR_DEVICE_GETSN: // Get SN of receiver device at end of link.
                    if (isReply)                              // We've been sent an SN for SPort.
                    {
                        g.buffer[dataIndex + g.dataLength()] = 0;
                        Manager.SerialNumberManager.UpdateSerialNumbers(g.buffer, dataIndex, g.dataLength(), g.iNetIf, g.sender());
                        if (mtx.MsgBuffer.iNetIf != ProtocolConstants.NETIF_USER_BASE)       // Notify master of SN via connection attach command.
                        {
                            SendLinkMediatorCommand(this, true, ProtocolConstants.MEDIATOR_CONNECT_ATTACH, g.dataLength(), g.buffer, dataIndex);
                        }
                        break;
                    }
                    // Sender wants to know SN of master.
                    g.dataLength(Manager.SerialNumberManager.CopyMasterSerialNumber(g.buffer, dataIndex, g.iNetIf));
                    mtx.ChangeDir = true;
                    mtx.Finish    = MessageTransaction.FinishAction.Normal;
                    break;

                case ProtocolConstants.MEDIATOR_CONNECT_ATTACH:     // TODO: Report attach and SN of device.
                case ProtocolConstants.MEDIATOR_CONNECT_DETACH:     // TODO: Report detach of device.
                case ProtocolConstants.MEDIATOR_CONNECT_GATEWAY:    // TODO: Register as a gateway.
                    return(10);

                default:
                    // TODO: try handling via NETIF_MEDIATOR_PORT.
                    return(11);
                }
                return(0);
            }
            return(BabelMessage.ProcessIncomingRawMesssage(Exchange, mtx));
        }
Example #5
0
        // Read parameter values from RAM or EEPROM.
        // Command syntax: data[]={ readId, cmdFlags, page, <numRead:>numToRead, {parameterIndexes}+ }
        //						<[{[VarKind[,StoreFlgs,ArgsFlgs,value data]}*]>.
        // Or: data[]={ readId, cmdFlags, page, name} when BX_MEDIATOR_DEVICE_RWV_FLAGS_BY_NAME cmdFlag set.
        // In reply to a BY_NAME: strips out request name and sets NAME flag to reply in std form.
        // Returns number of values read / changed depending on readFlags:
        // BX_MEDIATOR_DEVICE_MONITORVAR = Iso compare and return true if parameters have changed.
        // For each parameter, replies with:
        //  {DSK [,DSF, [ ramValue,] [ eepromValue,] [defaultValue]
        //       [dataSize, minValue, maxValue] [name + '\0'] ]}.
        public byte MediatorReadCommand(MessageTransaction mtx)
        {
            DeviceParameterTable pt = Exchange.ParameterTable;
            DeviceParameter      d;
            PacketBuffer         g = mtx.MsgBuffer;

            byte[] pAry;
            int    numReadIndex, dataIndex;
            bool   addMeta, addKindOnly;
            byte   n, j, k, byteCount, numToRead;
            byte   readId, cmdFlags, pageNum, parameterVarKind, parameterFlags, parameterSize, metaSize;
            byte   c = 0, maxData = (byte)(Exchange.Manager.MaxPacketSize - ProtocolConstants.GENERAL_OVERHEADS_SIZE);

            byte[] paramIndexes = new byte[8];
            n = g.dataLength();
            if (n < 5)
            {
                return(0);
            }
            numReadIndex = -1;
            dataIndex    = ProtocolConstants.GENERAL_DATA_ARRAY_OFFSET;
            pAry         = g.buffer;
            readId       = pAry[dataIndex++];
            cmdFlags     = pAry[dataIndex++];
            pageNum      = pAry[dataIndex++];
            n           -= 3;
            // TODO: table page selection.
            addKindOnly = (cmdFlags & ProtocolConstants.MEDIATOR_DEVICE_RWV_FLAGS_PACK_KIND) != 0;
            addMeta     = addKindOnly || (cmdFlags & ProtocolConstants.MEDIATOR_DEVICE_RWV_FLAGS_PACK) == 0;
            if ((cmdFlags & ProtocolConstants.MEDIATOR_DEVICE_RWV_FLAGS_BY_NAME) != 0)
            {
                pAry[dataIndex + n] = 0;
                string name = Primitives.GetArrayStringValue(pAry, dataIndex, n);
                // Search for name in table.
                d = pt.Find(name);
                if (d == null)
                {
                    pAry[dataIndex - 1] = cmdFlags;
                    dataIndex          += n;
                    numToRead           = 0;
                }
                else
                {
                    // If found, fall through and add meta data.
                    cmdFlags       |= ProtocolConstants.MEDIATOR_DEVICE_RWV_FLAGS_NAME;
                    numToRead       = 1;
                    paramIndexes[0] = (byte)d.ParamIndex;
                }
            }
            else
            {
                --n;
                numToRead = (byte)(pAry[dataIndex++] & 0xf);
                if (numToRead > n)
                {
                    numToRead = n;
                }
                j = numToRead;
                if (numToRead > 8)
                {
                    numToRead = 8;
                }
                for (k = 0; k < numToRead; k++)
                {
                    paramIndexes[k] = pAry[dataIndex + k];
                }
            }
            if (numToRead > 0)
            {
                dataIndex         = ProtocolConstants.GENERAL_DATA_ARRAY_OFFSET;
                pAry              = g.buffer;
                pAry[dataIndex++] = readId;
                pAry[dataIndex++] = cmdFlags; // Restore parameters.
                pAry[dataIndex++] = pageNum;
                numReadIndex      = dataIndex;
                pAry[dataIndex++] = 0;
                for (k = 0; k < numToRead; k++)
                {
                    pAry[dataIndex++] = paramIndexes[k];
                }
            }
            byteCount = (byte)dataIndex;
            g.dataLength(byteCount);
            k = 0;
            while (k < numToRead)
            {
                byte paramIndex = paramIndexes[k];
                if (paramIndex > pt.GetLastEntryIndex())
                {
                    break;
                }
                d = pt.Find(paramIndex);
                if (d == null)
                {
                    d = DeviceParameterTable.NullParameter;
                }
                n = 0;
                parameterVarKind = (byte)d.ParamVarKind;
                if (addMeta)
                {
                    // Write out representation kind.
                    metaSize = 1;
                    if ((byteCount + metaSize) >= maxData)
                    {
                        break;
                    }
                    pAry[dataIndex + n++] = parameterVarKind;
                }
                else
                {
                    metaSize = 0;
                }
                if (parameterVarKind != (byte)VariableKind.VK_None)
                {
                    VariableValue p; byte[] b;
                    byte          argsFlags, argsIndex = 0;
                    parameterSize  = (byte)d.ParamSize;
                    parameterFlags = (byte)d.ParamStorageFlags;
                    if (addMeta && !addKindOnly)
                    {
                        // Write out parameter flags & space for argsFlags.
                        metaSize += 2;
                        if ((byteCount + metaSize) >= maxData)
                        {
                            break;
                        }
                        pAry[dataIndex + n++] = parameterFlags;
                        argsIndex             = n++;
                    }
                    argsFlags = 0;
                    // Now write out parameter details depending on cmd flags.
                    if (((cmdFlags & ProtocolConstants.MEDIATOR_DEVICE_RWV_FLAGS_RAM) != 0) &&
                        ((parameterFlags & (byte)StorageFlags.SF_RAM) != 0))
                    {
                        p = d.RamValue;
                        if (p != null)
                        {
                            if (parameterVarKind == (byte)VariableKind.VK_String) // Get size of string.
                            {
                                byte maxSize = (byte)d.MaxValue.ValueLong;
                                int  s       = p.ValueString.Length;
                                if (s > maxSize)
                                {
                                    s = maxSize;
                                }
                                parameterSize = (byte)(1 + s); // Allow one for len byte.
                            }
                            if ((byteCount + metaSize + parameterSize) < maxData)
                            {
                                argsFlags |= ProtocolConstants.MEDIATOR_DEVICE_RWV_FLAGS_RAM;
                                metaSize  += parameterSize;
                                if (parameterVarKind == (byte)VariableKind.VK_String) // Prefix a len byte.
                                {
                                    --parameterSize;
                                    pAry[dataIndex + n++] = parameterSize;
                                    b = Primitives.StringToByteArray(p.ValueString);
                                    for (j = 0; j < parameterSize; j++)
                                    {
                                        pAry[dataIndex + n++] = b[j];
                                    }
                                }
                                else
                                {
                                    if ((mtx.TaskCmd != ProtocolConstants.MEDIATOR_DEVICE_ISOMONVAR) || (c != 0) || (paramIndex == ProtocolConstants.PARAMETER_TABLE_INDEX_TICKER))
                                    {
                                        Array.Copy(p.GetBytes(), 0, pAry, dataIndex + n, parameterSize);
                                    }
                                    else
                                    {
                                        int h = parameterSize;
                                        b = p.GetBytes();
                                        if (h > b.Length)
                                        {
                                            h = b.Length;
                                        }
                                        for (j = 0; j < parameterSize; j++)
                                        {
                                            int i = dataIndex + n + j;
                                            if ((c == 0) && pAry[i] != b[j])
                                            {
                                                c = 1;
                                            }
                                            pAry[i] = b[j];
                                        }
                                    }
                                    n += parameterSize;
                                }
                            }
                        }
                    }
                    if (((cmdFlags & ProtocolConstants.MEDIATOR_DEVICE_RWV_FLAGS_EEPROM) != 0) &&
                        ((parameterFlags & (byte)StorageFlags.SF_EEPROM) != 0))
                    {
                        p = d.EEPromValue;
                        if (p != null)
                        {
                            if (parameterVarKind == (byte)VariableKind.VK_String)   // Get size of string.
                            {
                                byte maxSize = (byte)d.MaxValue.ValueLong;
                                int  s       = p.ValueString.Length;
                                if (s > maxSize)
                                {
                                    s = maxSize;
                                }
                                parameterSize = (byte)(1 + s); // Allow one for len byte.
                            }
                            if ((byteCount + metaSize + parameterSize) < maxData)
                            {
                                argsFlags |= ProtocolConstants.MEDIATOR_DEVICE_RWV_FLAGS_EEPROM;
                                metaSize  += parameterSize;
                                if (parameterVarKind == (byte)VariableKind.VK_String)   // Prefix a len byte.
                                {
                                    --parameterSize;
                                    pAry[dataIndex + n++] = parameterSize;
                                    b = p.GetBytes();
                                    for (j = 0; j < parameterSize; j++)
                                    {
                                        pAry[dataIndex + n++] = b[j];
                                    }
                                }
                                else
                                {
                                    Array.Copy(p.GetBytes(), 0, pAry, dataIndex + n, parameterSize);
                                    n += parameterSize;
                                }
                            }
                        }
                    }
                    if (parameterVarKind == (byte)VariableKind.VK_String)
                    {
                        parameterSize = 1;
                    }
                    else
                    {
                        if ((cmdFlags & ProtocolConstants.MEDIATOR_DEVICE_RWV_FLAGS_DEFAULT) != 0)
                        {
                            if ((byteCount + metaSize + parameterSize) < maxData)
                            {
                                argsFlags |= ProtocolConstants.MEDIATOR_DEVICE_RWV_FLAGS_DEFAULT;
                                metaSize  += parameterSize;
                                Array.Copy(d.DefaultValue.GetBytes(), 0, pAry, dataIndex + n, parameterSize);
                                n += parameterSize;
                            }
                        }
                    }
                    if ((cmdFlags & ProtocolConstants.MEDIATOR_DEVICE_RWV_FLAGS_RANGE) != 0)
                    {
                        byte rangeSize = (byte)(2 + parameterSize * 2);
                        if ((byteCount + metaSize + rangeSize) < maxData)
                        {
                            argsFlags            |= ProtocolConstants.MEDIATOR_DEVICE_RWV_FLAGS_RANGE;
                            metaSize             += rangeSize;
                            pAry[dataIndex + n++] = parameterSize;
                            pAry[dataIndex + n++] = (byte)d.ParamCategory;
                            Array.Copy(d.MinValue.GetBytes(), 0, pAry, dataIndex + n, parameterSize);
                            n += parameterSize;
                            Array.Copy(d.MaxValue.GetBytes(), 0, pAry, dataIndex + n, parameterSize);
                            n += parameterSize;
                        }
                    }
                    if ((cmdFlags & ProtocolConstants.MEDIATOR_DEVICE_RWV_FLAGS_NAME) != 0)
                    {
                        // Get size of string.
                        parameterSize = 0;
                        string s = d.ParamName;
                        if (s != null)
                        {
                            parameterSize = (byte)s.Length;
                        }
                        if (parameterSize > ProtocolConstants.MAX_PARAMETER_NAME_SIZE)
                        {
                            parameterSize = ProtocolConstants.MAX_PARAMETER_NAME_SIZE;
                        }
                        if ((byteCount + metaSize + 1 + parameterSize) < maxData)
                        {
                            argsFlags            |= ProtocolConstants.MEDIATOR_DEVICE_RWV_FLAGS_NAME;
                            metaSize             += (byte)(1 + parameterSize);
                            pAry[dataIndex + n++] = parameterSize;
                            b = Primitives.StringToByteArray(s);
                            for (j = 0; j < parameterSize; j++)
                            {
                                pAry[dataIndex + n++] = b[j];
                            }
                        }
                    }
                    if (addMeta && !addKindOnly)
                    {
                        pAry[dataIndex + argsIndex] = argsFlags;
                    }
                }
                byteCount += metaSize;
                dataIndex += metaSize;
                g.dataLength((byte)(g.dataLength() + metaSize));
                ++k;
            }
            if (numReadIndex >= 0)
            {
                g.buffer[numReadIndex] = (byte)((k << 4) + numToRead);
            }
            mtx.ChangeDir = true;
            mtx.Finish    = MessageTransaction.FinishAction.Normal;
            if (mtx.TaskCmd == ProtocolConstants.MEDIATOR_DEVICE_ISOMONVAR)
            {
                return(c);
            }
            return(k);
        }
Example #6
0
        // Setup an isochronous task.
        // Format:
        // for ISO[MON]VAR: as per standard ReadCommand,
        // but CmdFlags preceded by: ISODetails={IsoId,IsoIntLo,IsoIntHi,RepeatLo,RepeatHi},
        // for ISOMSG: <cmd=ISOMSG> ISODetails {msgCmd,...},
        // where: IsoInt is the millisecond interval between reads, 0=remove,
        // Repeat is the number of times to send data, 0=forever.
        // Id for deleting task is SenderParams.
        int MediatorIsoCommand(MessageTransaction mtx)
        {
            PacketBuffer g = mtx.MsgBuffer;
            IsoTask      t;

            byte[] pAry;
            int    dataIndex;
            int    pIndex;
            uint   msInterval, repeatCount;
            byte   n, k, isoId;
            bool   isIsoMsg;

            n = g.dataLength();
            if (n < 3)
            {
                return(0);
            }
            pAry        = g.buffer;
            pIndex      = dataIndex = ProtocolConstants.GENERAL_DATA_ARRAY_OFFSET;
            isoId       = pAry[dataIndex++];
            msInterval  = pAry[dataIndex++];
            msInterval += (uint)(pAry[dataIndex++] << 8);
            // First check if this is a cancel or update request.
            // Find isoTask, if it exists, using isoId + senderParams as id.
            for (k = 0; k < NumTasks; k++)
            {
                do
                {
                    byte j;
                    t = IsoTasks[IsoTaskQueue[k]];
                    if (t.isoId == isoId &&
                        t.addressParams.Sender == g.sender() &&
                        t.addressParams.SenderId == g.senderId() &&
                        t.addressParams.flagsRS == (g.flagsRS() & ProtocolConstants.MESSAGE_PORTS_MASK))
                    {
                        // Free message buffer.
                        Manager.IoBuffersFreeHeap.Release(t.ioIndex);
                        t.ioIndex = -1;
                        // Remove from task queue.
                        for (j = k; j < (NumTasks - 1); j++)
                        {
                            IsoTaskQueue[j] = IsoTaskQueue[j + 1];
                        }
                        --NumTasks;
                        if (k < NumTasks)
                        {
                            continue;
                        }
                    }
                    break;
                } while (true);
            }
            if (msInterval == 0)
            {
                return(0);
            }
            isIsoMsg = (g.command() == ProtocolConstants.MEDIATOR_DEVICE_ISOMSG);
            if (isIsoMsg)
            {
                if (n < 6)
                {
                    return(0);       // Must be at least 5 iso parameters + 1 cmd byte.
                }
            }
            else if (n < 8)
            {
                return(0);           // Must be at least 5 iso parameter bytes + 3 read bytes.
            }
            // Set up a new isoTask.
            // First check if a task slot is free.
            if (NumTasks == IsoTaskSize)
            {
                return(0);
            }
            t = null;
            for (k = 0; k < IsoTaskSize; k++)
            {
                if (IsoTasks[k].ioIndex == -1)
                {
                    t = IsoTasks[k];
                    break;
                }
            }
            if (t == null)
            {
                return(0);
            }
            // Second, get iso params.
            repeatCount           = pAry[dataIndex++];
            repeatCount          += (uint)(pAry[dataIndex++] << 8);
            t.isoId               = isoId;
            t.repeatCount         = repeatCount;
            t.msTicksRelativeToGo = 0;     // Schedule for immediate execution because inserted at head of Q.
            t.msInterval          = msInterval;
            t.ioIndex             = mtx.IoIndex;
            t.state               = 0;
            t.cmd                    = g.command();                                                                      // Original msg iso cmd.
            t.ownerDriver            = (isIsoMsg ? Manager.GetLinkDriver(ProtocolConstants.NETIF_MEDIATOR_PORT) : this); // For IsoMsg, needs to be MediatorNetIf.
            t.addressParams.SenderId = g.senderId();
            t.addressParams.Sender   = g.sender();
            t.addressParams.flagsRS  = (byte)(g.flagsRS() & ProtocolConstants.MESSAGE_PORTS_MASK);
            // Now convert iso to a regular read message.
            // For ISOMSG cmd, g->command needs to be pulled from next dataAry byte.
            if (isIsoMsg)
            {
                g.command(pAry[dataIndex++]);
                --n;
            }
            else
            {
                g.command(ProtocolConstants.MEDIATOR_DEVICE_READVAR);
            }
            n -= 5;
            g.dataLength(n);
            while (n-- > 0)
            {
                pAry[pIndex++] = pAry[dataIndex++];
            }
            mtx.Finish = MessageTransaction.FinishAction.Keep;   // Keep iobuffer.
            // Finally insert task at head of queue.
            for (n = (byte)NumTasks; n > 0; n--)
            {
                IsoTaskQueue[n] = IsoTaskQueue[n - 1];
            }
            IsoTaskQueue[0] = k;
            ++NumTasks;
            return(1);
        }
Example #7
0
        public override void ServiceTasks(uint curTicks, LinkTaskKind taskAction)
        {
            IsoTask t, s;
            int     h, j, k, ioIndex;
            byte    r;
            bool    checkSchedule = false, checkRemove = false;
            uint    elapsedTicks;

            if (NumTasks == 0)
            {
                return;
            }
            if (taskAction == LinkTaskKind.Reset)
            {
                ResetLinkTasks();
                return;
            }
            elapsedTicks       = curTicks - LastIsoUpdateTicks;
            LastIsoUpdateTicks = curTicks;
            for (k = 0; k < NumTasks; k++)
            {
                t = IsoTasks[IsoTaskQueue[k]];
                if (elapsedTicks >= t.msTicksRelativeToGo)        // Perform this task.
                {
                    do
                    {
                        bool isIsoMsg = (t.cmd == ProtocolConstants.MEDIATOR_DEVICE_ISOMSG);
                        if (isIsoMsg)
                        {
                            ioIndex = CopyMessage(t.ioIndex, 0);
                            if (ioIndex == -1)
                            {
                                break;
                            }
                        }
                        else
                        {
                            ioIndex = t.ioIndex;
                        }
                        MessageTransaction bmc = new MessageTransaction(Manager);
                        j = bmc.StartMessageTransaction(t.ioIndex);
                        if (j != 0)
                        {
                            break;
                        }
                        bmc.TaskCmd = (byte)t.cmd;
                        j           = t.ownerDriver.CommandHandler(bmc);
                        if (j != 0)
                        {
                            break;
                        }
                        // Make a copy before its finalised.
                        if (!isIsoMsg)
                        {
                            byte pktLen = (byte)(ProtocolConstants.GENERAL_OVERHEADS_SIZE + bmc.MsgBuffer.dataLength());
                            ioIndex = CopyMessage(t.ioIndex, pktLen);
                            if (ioIndex == -1)
                            {
                                break;
                            }
                            t.ioIndex     = ioIndex;
                            bmc.ReturnCmd = bmc.TaskCmd;
                        }
                        bmc.FinishMessageTransaction();
                    } while(false);
                    // Check if task to be removed.
                    if (t.repeatCount > 0)
                    {
                        if (--t.repeatCount == 0)
                        {
                            // Free message buffer.
                            Manager.IoBuffersFreeHeap.Release(t.ioIndex);
                            t.ioIndex = -1;
                            // Mark task for later removal.
                            t.state     = IsoRemove;
                            checkRemove = true;
                        }
                    }
                    if ((t.state & IsoRemove) == 0)
                    {
                        // Mark task as requiring rescheduling.
                        t.state      |= IsoReschedule;
                        checkSchedule = true;
                    }
                    // Update elapsedTicks:
                    elapsedTicks -= t.msTicksRelativeToGo;
                }
                else
                {
                    t.msTicksRelativeToGo -= elapsedTicks;
                    break;
                }
            }
            if (checkRemove)
            {
                r = 0;
                for (k = 0; k < NumTasks; k++)
                {
                    j = IsoTaskQueue[k];
                    if (IsoTasks[j].ioIndex != -1)
                    {
                        IsoTaskQueue[r++] = j;
                    }
                }
                NumTasks = r;
            }
            if (checkSchedule)                 // Reschedule tasks.
            {
                for (j = 0; j < NumTasks; j++) // Find first task that doesn't require rescheduling.
                {
                    if ((IsoTasks[IsoTaskQueue[j]].state & IsoReschedule) == 0)
                    {
                        break;
                    }
                }
                for (k = j - 1; k >= 0; k--)
                {
                    t       = IsoTasks[IsoTaskQueue[k]];
                    t.state = 0;
                    t.msTicksRelativeToGo = t.msInterval - 1; // Note, minus one because 1 tick used during scheduling.
                    r = (byte)k;
                    do                                        // Ripple current task down Q until position found.
                    {
                        if ((r + 1) == NumTasks)              // Check next not past end.
                        {
                            break;
                        }
                        s = IsoTasks[IsoTaskQueue[r + 1]];
                        if (t.msTicksRelativeToGo < s.msTicksRelativeToGo)   // '<' for fairness.
                        {
                            s.msTicksRelativeToGo -= t.msTicksRelativeToGo;
                            break;
                        }
                        // Find location deeper in schedule.
                        t.msTicksRelativeToGo -= s.msTicksRelativeToGo;
                        // Swap over tasks in Q.
                        h = IsoTaskQueue[r];
                        IsoTaskQueue[r]     = IsoTaskQueue[r + 1];
                        IsoTaskQueue[r + 1] = h;
                        ++r;
                    } while(r < NumTasks);
                    if (k == 0)
                    {
                        break;
                    }
                }
            }
        }
Example #8
0
        // Write parameter values to RAM or EEPROM.
        // Writes default value if no value given.
        // Command syntax: data[]={writeId, cmdFlags, page, <numWritten:>numToWrite, {parameterIndex}+[data].
        // Returns number written along with parameter Index's.
        byte MediatorWriteCommand(MessageTransaction mtx)
        {
            DeviceParameterTable pt = Exchange.ParameterTable;
            DeviceParameter      d;
            PacketBuffer         g = mtx.MsgBuffer;

            byte[]        pAry;
            int           dataIndex;
            VariableValue val = null;
            byte          n, h, k, j, writeId, cmdFlags, pageNum, retArgsLen, maxSize = 0;
            VariableKind  parameterVarKind;
            StorageFlags  parameterFlags;
            byte          parameterSize, numToWrite;
            int           paramIndexes, numWrittenIndex;

            n = g.dataLength();
            if (n < 5)
            {
                return(0);
            }
            dataIndex       = ProtocolConstants.GENERAL_DATA_ARRAY_OFFSET;
            pAry            = g.buffer;
            writeId         = pAry[dataIndex++];
            cmdFlags        = pAry[dataIndex++];
            pageNum         = pAry[dataIndex++];
            numWrittenIndex = dataIndex;
            numToWrite      = (byte)(pAry[dataIndex++] & 0xf);
            n -= 4;
            if (numToWrite > n)
            {
                numToWrite = n;
            }
            j = numToWrite;
            if (numToWrite > 8)
            {
                numToWrite = 8;
            }
            paramIndexes = dataIndex;
            retArgsLen   = (byte)(dataIndex + numToWrite);
            g.dataLength((byte)(g.dataLength() - (4 + j))); //3=(wId, cmdFlags, page, nW:nTW), j= num original idx's.
            dataIndex += j;
            h          = 0; k = 0;
            while (k < numToWrite)
            {
                int paramIndex = pAry[paramIndexes + k];
                if (paramIndex > pt.GetLastEntryIndex())
                {
                    break;
                }
                d = pt.Find(paramIndex);
                if (d == null)
                {
                    d = DeviceParameterTable.NullParameter;
                }
                parameterSize = (byte)d.ParamSize;
                if (parameterSize != 0)
                {
                    int valPtrIndex = 0;
                    parameterVarKind = (VariableKind)d.ParamVarKind;
                    parameterFlags   = (StorageFlags)d.ParamStorageFlags;
                    if (parameterVarKind == VariableKind.VK_String) // Note: only one string allowed per message.
                    {
                        parameterSize = 0;
                        if (n > 0) // Strings must be at least 1 byte long: len byte.
                        {
                            byte lenAdj;
                            maxSize       = (byte)d.MaxValue.ValueLong;
                            parameterSize = pAry[dataIndex++];
                            lenAdj        = parameterSize;
                            n--;
                            if (parameterSize > maxSize)
                            {
                                parameterSize = maxSize;
                            }
                            if (n < parameterSize)
                            {
                                parameterSize = n;
                                lenAdj        = parameterSize;
                            }
                            valPtrIndex = dataIndex;
                            n          -= lenAdj;
                            dataIndex  += lenAdj;
                        }
                    }
                    else
                    {
                        if (n >= parameterSize)
                        {
                            val         = new VariableValue(parameterVarKind, pAry, dataIndex, (int)parameterSize);
                            valPtrIndex = dataIndex;
                            n          -= parameterSize;
                            dataIndex  += parameterSize;
                        }
                        else
                        {
                            val         = d.DefaultValue;
                            valPtrIndex = -1;
                        }
                        val.CheckInRange(d.MinValue, d.MaxValue);
                    }
                    if (parameterSize > 0)
                    {
                        if ((parameterFlags & StorageFlags.SF_ReadOnly) == 0)
                        {
                            if (((cmdFlags & ProtocolConstants.MEDIATOR_DEVICE_RWV_FLAGS_EEPROM) != 0) &&
                                ((parameterFlags & StorageFlags.SF_EEPROM) != 0))
                            {
                                if (parameterVarKind == VariableKind.VK_String)
                                {
                                    if (valPtrIndex >= 0)
                                    {
                                        d.EEPromValue = new VariableValue(parameterVarKind, pAry, valPtrIndex, (int)parameterSize);
                                    }
                                    else
                                    {
                                        d.EEPromValue = new VariableValue(parameterVarKind, pAry, 0, (int)0);
                                    }
                                }
                                else
                                {
                                    d.EEPromValue = val;
                                }
                            }
                            if ((cmdFlags & ProtocolConstants.MEDIATOR_DEVICE_RWV_FLAGS_RAM) != 0)
                            {
                                if (parameterVarKind == VariableKind.VK_String)
                                {
                                    if (valPtrIndex >= 0)
                                    {
                                        d.RamValue = new VariableValue(parameterVarKind, pAry, valPtrIndex, (int)parameterSize);
                                    }
                                    else
                                    {
                                        d.RamValue = new VariableValue(parameterVarKind, pAry, 0, (int)0);
                                    }
                                }
                                else
                                {
                                    d.RamValue = val;
                                }
                            }
                        }
                    }
                    ++h;
                }
                ++k;
                ++paramIndex;
            }
            if (numWrittenIndex >= 0)
            {
                pAry[numWrittenIndex] = h; // Reply to caller with number of parameters written.
            }
            g.dataLength(retArgsLen);
            mtx.ChangeDir = true;
            mtx.Finish    = ((g.flagsRS() & ProtocolConstants.MESSAGE_FLAGS_ACK) != 0)
                ? MessageTransaction.FinishAction.Normal : MessageTransaction.FinishAction.Free;
            return(h);
        }