1    /*
     2     * Copyright (c) 2012, Texas Instruments Incorporated
     3     * All rights reserved.
     4     *
     5     * Redistribution and use in source and binary forms, with or without
     6     * modification, are permitted provided that the following conditions
     7     * are met:
     8     *
     9     * *  Redistributions of source code must retain the above copyright
    10     *    notice, this list of conditions and the following disclaimer.
    11     *
    12     * *  Redistributions in binary form must reproduce the above copyright
    13     *    notice, this list of conditions and the following disclaimer in the
    14     *    documentation and/or other materials provided with the distribution.
    15     *
    16     * *  Neither the name of Texas Instruments Incorporated nor the names of
    17     *    its contributors may be used to endorse or promote products derived
    18     *    from this software without specific prior written permission.
    19     *
    20     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    21     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    22     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    23     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    24     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    25     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    26     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    27     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    28     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    29     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    30     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31     * */
    32    
    33    /*
    34     *  ======== ServiceMgr.xdc ========
    35     */
    36    
    37    import xdc.runtime.Assert;
    38    import xdc.rov.ViewInfo;
    39    
    40    /*!
    41     *  ======== ServiceMgr ========
    42     *  Module that manages UIA Services
    43     *
    44     *  The ServiceMgr module manages all the UIA Services. The ServiceMgr module
    45     *  itself can be plugged with different low level transport functions to
    46     *  support different methods for getting information between the target
    47     *  and instrumentation host. Some of these methods (e.g. File) only support
    48     *  sending information from the target to the host. They do not support
    49     *  sending information from the host to the target.
    50     *
    51     *  The ServiceMgr module also supports two different topologies.
    52     *  @p(blist)
    53     *      - Topology_SINGLECORE: Each core on the device communicates
    54     *        directly the instrumentation host.
    55     *      - Topology_MULTICORE: Only one core (i.e. master)
    56     *        communicates with the instrumentation host. Communication
    57     *        with other cores are routed to the via the master core.
    58     *        The master core is determined by the {@link #masterProcId}
    59     *        parameter. The routing is done via Ipc's MessageQ module.
    60     *        Note: ServiceMgr is a user of Ipc and depends on the
    61     *        application to configure and initialize Ipc.
    62     *  @p
    63     *
    64     *  There are two different uses of the ServiceMgr module:
    65     *  @p(blist)
    66     *      - Applications (configuration only)
    67     *      - Services
    68     *  @p
    69     *
    70     *  @p(html)
    71     *  <B>Applications</B>
    72     *  @p
    73     *  The ServiceMgr module contains the generic configuration.
    74     *  Many of these configuration values change
    75     *  depending on the device. The ServiceMgr module uses the
    76     *  ti.uia.family.Settings module to fill in values if they are not set by
    77     *  the application.
    78     *
    79     *  The ServiceMgr does expose many configuration parameters to allow users
    80     *  to modify the default behavior.
    81     *
    82     *  @p(blist)
    83     *      - Topology: UIA is shipped with support for two different topologies:
    84     *  @p(blist)
    85     *          - Topology_SINGLECORE: Each core on the device communicates
    86     *               directly the instrumentation host.
    87     *          - Topology_MULTICORE: Only one core (i.e. master)
    88     *               communicates with the instrumentation host. Communication
    89     *               with other cores are routed to the via the master core.
    90     *               The master core is determined by the {@link #masterProcId}
    91     *               parameter. The routing is done via Ipc's MessageQ module.
    92     *               Note: ServiceMgr is a user of Ipc and depends on the
    93     *               application to configure and initialize Ipc.
    94     *  @p
    95     *
    96     *      - Transport: The ServiceMgr has  pluggable transport functions. The
    97     *               determination of the transport is accomplished via the
    98     *               {@link #transportType} parameter. The parameter is defaulted
    99     *               based on the device is not explicitly set.
   100     *
   101     *      - Packets: UIA makes a distinction between event and messages packets.
   102     *                 Events packets are generally bigger to hold many event
   103     *                 records. The size and number of these packets are defaulted
   104     *                 by UIA based on the transport and device. However the number
   105     *                 of event packets might need to be increased on a multicore
   106     *                 device with heavy event record load.
   107     *                 {@link #numEventPacketBufs} can be increased in this case.
   108     *
   109     *      - Tasks: The ServiceMgr module might have up to two tasks:
   110     *               transfer agent task and receive task. The receive task only
   111     *               recieves control messages from the instrumentation host and
   112     *               forwards it on the the transfer agent task.
   113     *               The transfer agent task is responsible for everything else
   114     *               (e.g. period management, event collection, communicating with
   115     *               remote cores in a multicore configuration, sending UIA Packets
   116     *               to the instrumentation host, etc.).
   117     *
   118     *               The application can specify the stack sizes and placement of
   119     *               these task via the ServiceMgr.
   120     *
   121     *               If there is only one task needed, the parameters for the
   122     *               receive task is ignored.
   123     *  @p
   124     *
   125     *  @p(html)
   126     *  <B>Services</B>
   127     *  @p
   128     *  All services must register with the ServiceMgr module via the
   129     *  {@link #register} function. Each service
   130     *  must have a unique service id (the first 3 are reserved). The service id
   131     *  is obtained via the encoded type ServiceIdDesc.
   132     *
   133     *  From the service's standpoint, the ServiceMgr module manages all the
   134     *  buffers for sending and receive messages and events. The services need
   135     *  to obtain packets from the ServiceMgr via the {@link #getFreePacket}
   136     *  function. To send a packet, the service must call the
   137     *  {@link #sendPacket} function.
   138     *
   139     *  All data send and received by a service must be contained in a
   140     *  {@link UIAPacket} header. Refer to this module for more details.
   141     *
   142     *  From the service's standpoint, the ServiceMgr module also manages the
   143     *  the period of service. Each service can request the interval at which
   144     *  the ServiceMgr calls the service's {@link #ProcessCallback} to send out
   145     *  events. This interval can be set by the service via the {@link #register}
   146     *  function. If during runtime the service wants to change it period, it
   147     *  can call {@link #setPeriod}.
   148     */
   149    @CustomHeader
   150    module ServiceMgr
   151    {
   152        /*!
   153         *  @_nodoc
   154         *  ======== ModuleView ========
   155         */
   156        metaonly struct ModuleView {
   157            Int        periodInMs;
   158            Bool       supportControl;
   159            String     topology;
   160            Int        numServices;
   161            Int        masterProcId;
   162            Int        runCount;
   163            //string     masterRunning; //TODO SDOCM00077324
   164        }
   165    
   166        /*!
   167         *  @_nodoc
   168         *  ======== PacketView ========
   169         */
   170        metaonly struct PacketView {
   171            SizeT      maxEventPacketSize;
   172            Int        numEventPacketBufs;
   173            SizeT      maxCtrlPacketSize;
   174            Int        numOutgoingCtrlPacketBufs;
   175            Int        numIncomingCtrlPacketBufs;
   176        }
   177    
   178        /*!
   179         *  @_nodoc
   180         *  ======== TransportView ========
   181         */
   182        metaonly struct TransportView {
   183            String     initFxn;
   184            String     startFxn;
   185            String     recvFxn;
   186            String     sendFxn;
   187            String     stopFxn;
   188            String     exitFxn;
   189        }
   190    
   191        /*!
   192         *  @_nodoc
   193         *  ======== StatisticsView ========
   194         */
   195        metaonly struct StatisticsView {
   196            Int     numEventPacketsSent;
   197            Int     numEventPacketsFailed;
   198            Int     numMsgPacketsSent;
   199            Int     numMsgPacketsFailed;
   200        }
   201    
   202        /*!
   203         *  @_nodoc
   204         *  ======== rovViewInfo ========
   205         */
   206        @Facet
   207        metaonly config ViewInfo.Instance rovViewInfo =
   208            ViewInfo.create({
   209                viewMap: [
   210                    ['Module',
   211                        {
   212                            type: ViewInfo.MODULE,
   213                            viewInitFxn: 'viewInitModule',
   214                            structName: 'ModuleView'
   215                        }
   216                    ],
   217                    // SDOCM00077324
   218                    // ServiceMgr's ROV should obtain information from proxies
   219                    //['Statistics',
   220                    //    {
   221                    //        type: ViewInfo.MODULE,
   222                    //        viewInitFxn: 'viewInitStats',
   223                    //        structName: 'StatisticsView'
   224                    //    }
   225                    //],
   226                    ['Transport',
   227                        {
   228                            type: ViewInfo.MODULE,
   229                            viewInitFxn: 'viewInitTransport',
   230                            structName: 'TransportView'
   231                        }
   232                    ],
   233                    ['Packet',
   234                        {
   235                            type: ViewInfo.MODULE,
   236                            viewInitFxn: 'viewInitPacket',
   237                            structName: 'PacketView'
   238                        }
   239                    ],
   240                ]
   241            });
   242    
   243        /*!
   244         *  ======== Reason ========
   245         *  Used in the ProcessCallback to denote the reason
   246         *
   247         *  ServiceMgr_Reason_PERIODEXPIRED: the {@link #ProcessCallback} is being
   248         *  called because it is time to collect events and send them.
   249         *
   250         *  ServiceMgr_Reason_REQUESTENERGY: the {@link #ProcessCallback} is being
   251         *  called because the service requested energy to perform some action.
   252         *
   253         *  ServiceMgr_Reason_INCOMINGMSG: the {@link #ProcessCallback} is being
   254         *  called because there is an incoming message for the service.
   255         */
   256        enum Reason {
   257            Reason_PERIODEXPIRED,
   258            Reason_REQUESTENERGY,
   259            Reason_INCOMINGMSG
   260        };
   261    
   262        /*!
   263         *  ======== Topology ========
   264         *  Used to define UIA topology.
   265         *
   266         *  If UIA is configured for multicore, all events and messages are routed
   267         *  via the master core to the non-master cores. Choosing multicore requires
   268         *  setting the {@link #master} config.
   269         *
   270         *  If UIA is configured for Topology_SINGLECORE, each core on the device
   271         *  communicates with the instrumentation host directly.
   272         */
   273        enum Topology {
   274            Topology_SINGLECORE,
   275            Topology_MULTICORE
   276        };
   277    
   278        /*!
   279         *  ======== TransportType ========
   280         *  Used to specify the type of transport for UIA to use.
   281         *
   282         *  TransportType defines what the underlying transport will be used. In
   283         *  a multi-core topology, this parameter is only relevant for the
   284         *  {@link #masterProcId} core. The masterProcId core uses the TransportType
   285         *  to determine how to get the data off the target.
   286         *
   287         *  @p(blist)
   288         *  -TransportType_ETHERNET: Use the Ethernet transport. On a SYS/BIOS
   289         *      system, this uses the NDK. The application is responsible for
   290         *      adding the NDK into the application and initializing it.
   291         *  -TransportType_FILE: Use the File transport.
   292         *      On a SYS/BIOS system, this transport requires a JTAG connection.
   293         *  -TransportType_USER: This allows the application to specify their
   294         *      own transport functions.
   295         *  -TransportType_NULL: No transport functions are needed. This should
   296         *      only be used on the non-masterProcId cores.
   297         *  @p
   298         */
   299        metaonly enum TransportType {
   300            TransportType_ETHERNET,
   301            TransportType_FILE,
   302            TransportType_USER,
   303            TransportType_NULL
   304        };
   305    
   306        /*!
   307         *  ======== ProcessCallback ========
   308         *  Function prototype for the processMsg callback
   309         *
   310         *  A ProcessCallback function must be supplied by every service.
   311         *  The function is provided in the {@link #register} function.
   312         *
   313         *  For a description of the ServiceMgr_Reason parameter, please refer
   314         *  to {@link #Reason}.
   315         *
   316         *  The UIPacket_Hdr field is only used in the {@link #Reason_INCOMINGMSG}
   317         *  case. For any other reason, this value is NULL.
   318         */
   319        typedef Void (*ProcessCallback)(Reason, UIAPacket.Hdr *);
   320    
   321        /*!
   322         *  ======== WAIT_FOREVER ========
   323         *  Wait forever constant that can be used in ServiceMgr_getFreePacket.
   324         */
   325        const UInt WAIT_FOREVER = ~(0);
   326    
   327        /*! @_nodoc */
   328        metaonly struct ServiceIdDesc { Bits16 val; };
   329    
   330        /*!
   331         *  ======== ServiceId ========
   332         *  Used by services to generate a serviceId
   333         *
   334         *  Services needs to define a ServiceId in their xdc file.
   335         *  Then the ServiceMgr module will assign a unique value to it during
   336         *  build time.
   337         *
   338         *  For example in ti.uia.service.Rta.xdc there is the following line:
   339         *  @p(code)
   340         *  readonly config ServiceMgr.ServiceId SERVICEID;
   341         *  @p
   342         */
   343        @Encoded typedef ServiceIdDesc ServiceId;     /*! Control command type */
   344    
   345        /*!
   346         *  Assert raised when calling API with invalid ServiceId
   347         */
   348        config Assert.Id A_invalidServiceId  = {
   349            msg: "A_invalidServiceId: ServiceId out of range"
   350        };
   351    
   352        /*!
   353         *  Assert raised invalid processCallbackFxn is supplied
   354         */
   355        config Assert.Id A_invalidProcessCallbackFxn  = {
   356            msg: "A_invalidProcessCallbackFxn: Callback cannot be NULL"
   357        };
   358    
   359        /*!
   360         *  ======== customTransportType ========
   361         *  Custom transport used to send the records to an instrumentation host
   362         */
   363        metaonly config String customTransportType = null;
   364    
   365        /*!
   366         *  ======== transportFxns ========
   367         *  Transport functions used to communicate to the instrumentation host
   368         *
   369         *  These functions are setup by default based on the device.
   370         *  The user can explicitly set this parameter if the default is not
   371         *  appropriate.
   372         */
   373        config Transport.FxnSet transportFxns;
   374    
   375        /*!
   376         *  ======== topology ========
   377         *  Used to define UIA topology.
   378         *
   379         *  If `Topology_MULTICORE` is chosen, the ServiceMgr will use Ipc to
   380         *  discover the core configuration and to communicate between the cores.
   381         *  UIA will route the outbound packets from each core through the master
   382         *  core. UIA will also route messages received by the master core to
   383         *  their intended recipient.
   384         *
   385         *  If UIA is configured for Topology_SINGLECORE, each core on the device
   386         *  communicates with the instrumentation host directly.
   387         *
   388         *  The default is Topology_SINGLECORE.
   389         */
   390        config Topology topology = Topology_SINGLECORE;
   391    
   392        /*!
   393         *  ======== transportType ========
   394         *  Determines the transport that UIA will be configured for.
   395         *
   396         *  For a given transport type, UIA picks an appropriate transport
   397         *  implementation to use based on your device. This is specified by the
   398         *  ti.uia.family.Settings module. Refer to the examples for configuring
   399         *  the actual transport implementation.
   400         *
   401         *  If someone writes an new transport (e.g. RapidIO),
   402         *  they can be plugged in by setting the TransportType
   403         *  to `TransportType_USER` and then plugging
   404         *  the transportFxns manually. It must also set up the following parameters
   405         *  as directed by the new transport developer.
   406         *  @p(blist)
   407         *  -ServiceMgr.supportControl: does the transport support receiving
   408         *               messages from the host. For example TransportFile does not.
   409         *  -ServiceMgr.maxEventPacketSize: Max size of an outgoing event packet. For
   410         *               example TransportNdk uses 1472 (emac size minus headers)
   411         *  -ServiceMgr.maxCtrlPacketSize: Max size of the message packets. This can
   412         *               be zero if supportControl is false.
   413         *  @p
   414         *
   415         *  Here is an example of plugging the transport XYZ into the ServiceMgr:
   416         *  @p(code)
   417         *  var ServiceMgr = xdc.useModule('ti.uia.runtime.ServiceMgr');
   418         *  ServiceMgr.transportType = ServiceMgr.TransportType_USER;
   419         *  var xyzTransport = {
   420         *      initFxn: '&TransportXYZ_init',
   421         *      startFxn: '&TransportXYZ_start',
   422         *      recvFxn: '&TransportXYZ_recv',
   423         *      sendFxn: '&TransportXYZ_send',
   424         *      stopFxn: '&TransportXYZ_stop',
   425         *      exitFxn: '&TransportXYZ_exit'
   426         *  };
   427         *  ServiceMgr.transportFxns = xyzTransport;
   428         *
   429         *  ServiceMgr.maxEventPacketSize = 1024
   430         *  ServiceMgr.maxCtrlPacketSize  = 1024;
   431         *  ServiceMgr.supportControl     = true;
   432         *  @p
   433         */
   434        metaonly config TransportType transportType;
   435    
   436        /*!
   437         *  ======== periodInMs ========
   438         *  Period in miliseconds of ServiceMgr's transfer agent
   439         *
   440         *  The transfer agent runs at the configured period. It checks to see
   441         *  if a service's period has expired. If it has expired, the service's
   442         *  {@link #ProcessCallback} is called with the
   443         *  {@link #Reason_PERIODEXPIRED} reason.
   444         *
   445         *  A service should not set it's period to a value less than the ServiceMgr
   446         *  module'speriod. A service's period should be a multiple of the
   447         *  ServiceMgr module's period. If it is not, it will called at the rounded
   448         *  up period. For example, if ServiceMgr.periodInMs = 100 and a service
   449         *  sets its period to 250. That service will be called every 300
   450         *  milliseconds.
   451         *
   452         *  This value does not guarantee that the transfer agent will run at this
   453         *  rate. Even if the period has expired, the transfer agent will not run
   454         *  until the current running Task has yielded and there are no other higher
   455         *  priority Tasks ready.
   456         *
   457         *  Default is 100ms.
   458         */
   459        config Int periodInMs = 100;
   460    
   461        /*!
   462         *  ======== maxEventPacketSize  ========
   463         *  Size of Event packets in bytes
   464         *
   465         *  This size includes the UIAPacket header. This value's default
   466         *  depends on the device.
   467         */
   468        config SizeT maxEventPacketSize;
   469    
   470        /*!
   471         *  ======== numEventPacketBufs  ========
   472         *  Number of UIAPacket events on the processor
   473         */
   474        config Int numEventPacketBufs  = 2;
   475    
   476        /*!
   477         *  ======== maxCtrlPacketSize  ========
   478         *  Size of control message packets in bytes
   479         *
   480         *  This size includes the UIAPacket header. This value's default
   481         *  depends on the device.
   482         */
   483        config SizeT maxCtrlPacketSize;
   484    
   485        /*!
   486         *  ======== numOutgoingCtrlPacketBufs  ========
   487         *  Number of outgoing Ctrl buffers on the processor
   488         */
   489        config Int numOutgoingCtrlPacketBufs  = 2;
   490    
   491        /*!
   492         *  ======== numIncomingCtrlPacketBufs  ========
   493         *  Number of incoming Ctrl buffers on the master processor
   494         */
   495        config Int numIncomingCtrlPacketBufs  = 2;
   496    
   497        /*!
   498         *  ======== supportControl ========
   499         *  Configure whether control messages are supported.
   500         *
   501         *  Default is determined based on the device and transport type.
   502         *
   503         *  The application should only set this if {@link #transportType}
   504         *  is TransportType_USER and it is plugging in a new set
   505         *  of transport functions. The transport function package should
   506         *  specify how to set this parameter.
   507         */
   508        config Bool supportControl;
   509    
   510        /*!
   511         *  ======== transferAgentPriority ========
   512         *  Priority of the Transfer Agent Task.
   513         *
   514         *  Default is 1, the lowest priority.
   515         */
   516        config Int transferAgentPriority = 1;
   517    
   518        /*!
   519         *  ======== transferAgentStackSize ========
   520         *  Transfer Agent Task stack size in MAUs.
   521         *
   522         *  The recommended size is 2048 bytes.
   523         */
   524        config SizeT transferAgentStackSize = 2048;
   525    
   526        /*!
   527         *  ======== transferAgentStackSection ========
   528         *  Memory section for Transfer Agent Task's stack.
   529         *
   530         *  If this parameter is not set then the Task.defaultStackSection is used.
   531         *  See the Task module for instructions on creating a stack section in
   532         *  a different memory segment.
   533         */
   534        metaonly config String transferAgentStackSection = null;
   535    
   536        /*!
   537         *  ======== rxTaskPriority ========
   538         *  Priority of the Transfer Agent Task.
   539         *
   540         *  Default is 1, the lowest priority.
   541         */
   542        config Int rxTaskPriority = 1;
   543    
   544        /*!
   545         *  ======== rxTaskStackSize ========
   546         *  Transfer Agent Task stack size in MAUs.
   547         *
   548         *  The recommended size is 2048 bytes.
   549         */
   550        config SizeT rxTaskStackSize = 2048;
   551    
   552        /*!
   553         *  ======== rxTaskStackSection ========
   554         *  Memory section for Receiving Task's stack.
   555         *
   556         *  If this parameter is not set then the Task.defaultStackSection is used.
   557         *  See the Task module for instructions on creating a stack section in
   558         *  a different memory segment.
   559         */
   560        metaonly config String rxTaskStackSection = null;
   561    
   562        /*!
   563         *  @_nodoc
   564         *  ======== SupportProxy ========
   565         *  The implementation module of the low-level ServiceMgr functions
   566         */
   567        proxy SupportProxy inherits IServiceMgrSupport;
   568    
   569        /*!
   570         *  ======== masterProcId ========
   571         *  Processor that communicates to the instrumentation host
   572         *
   573         *  This value denotes which core in a multiple core topology is
   574         *  the master core. All routing of UIA data to the instrumentation
   575         *  host is done via this core.
   576         *
   577         *  The procId corresponds to Ipc's MultiProc value.
   578         *
   579         *  For single processor systems, or where there is no routing of
   580         *  data via an intermediate core, this value is ignored.
   581         */
   582        config UInt16 masterProcId = 0;
   583    
   584        /*!
   585         *  ======== freePacket ========
   586         *  Function to return an unused packet back to the ServiceMgr module
   587         *
   588         *  This function can be used to return an unused packet back to the
   589         *  ServiceMgr module. It must only return packets that were obtained via
   590         *  the {@link #getFreePacket} function.
   591         *
   592         *  @param(packet)  Pointer to a UIAPacket
   593         */
   594        Void freePacket(UIAPacket.Hdr *packet);
   595    
   596        /*!
   597         *  ======== getFreePacket ========
   598         *  Function to obtain a free UIA packet
   599         *
   600         *  The service can specify what type of packet it wants with the
   601         *  first parameter. Currently only UIAPacket_HdrType_Msg and
   602         *  UIAPacket_HdrType_EventPkt are supported.
   603         *
   604         *  The function fills in the HdrType field of the packet automatically
   605         *  for the service. All other fields are un-initialized.
   606         *
   607         *  @param(type)    Requested type of packet
   608         *  @param(timeout) Return after this many system time units
   609         *
   610         *  @b(returns)     Pointer to a packet if successful. NULL if timeout.
   611         */
   612        UIAPacket.Hdr *getFreePacket(UIAPacket.HdrType type, UInt timeout);
   613    
   614        /*!
   615         *  ======== getNumServices ========
   616         *  Returns the number of services present in the system
   617         *
   618         *  @b(returns)     Number of services
   619         */
   620        Int getNumServices();
   621    
   622        /*!
   623         *  @_nodoc
   624         *  ======== processCallback ========
   625         *  Callback function called by the support proxy
   626         *
   627         *  This function is called by the support proxy when it needs to
   628         *  call a service's ProcessCallback function.
   629         *
   630         *  This function should not be called by a service.
   631         *
   632         *  @param(id)      Service id of the service
   633         *  @param(reason)  Reason for calling the service's ProcessCallback
   634         *                  function
   635         *  @param(packet)  If the reason is {@link #Reason_INCOMINGMSG}, this
   636         *                  parameter points to the incoming msg. Otherwise it is
   637         *                  NULL. The service does not own this packet. It should
   638         *                  NOT re-use it. Internally the ServiceMgr module will
   639         *                  return it to an internal queue after the
   640         *                  processCallback returns.
   641         */
   642        Void processCallback(ServiceId id, Reason reason, UIAPacket.Hdr *packet);
   643    
   644        /*!
   645         *  ======== register ========
   646         *  Register a services with the ServiceMgr module
   647         *
   648         *  All service's must register with the ServiceMgr module statically.
   649         *
   650         *  Refer to {@link #periodInMs} for a description of the period parameter.
   651         *
   652         *  @param(id)      Service id of the service (refer to
   653         *                  {@link #ServiceId}).
   654         *
   655         *  @param(processCallbackFxn)  Service's callback function.
   656         *
   657         *  @param(periodInMs) Period of the service.
   658         */
   659        metaonly Int register(ServiceId id, ProcessCallback processCallbackFxn,
   660                              UInt32 periodInMs);
   661    
   662        /*!
   663         *  ======== requestEnergy ========
   664         *  Function to request energy for a service
   665         *
   666         *  Generally services do not maintain an active thread.
   667         *  They may request the ServiceMgr module to call the
   668         *  {@link #ProcessCallback} in the context of the transfer agent.
   669         *  This can be accomplished via this function.
   670         *
   671         *  @param(id)     Service id of the service
   672         */
   673        Void requestEnergy(ServiceId id);
   674    
   675        /*!
   676         *  ======== sendPacket ========
   677         *  Send a UIAPacket to the instrumentation host
   678         *
   679         *  All UIAPacket fields except for SenderAdrs must be filled in.
   680         *
   681         *  The caller loses ownership of the packet once it is successfully sent.
   682         *  If this function fails, the caller still owns the packet. It can re-use
   683         *  it or free it via the {@link #freePacket} function.
   684         *
   685         *  @param(packet)  UIAPacket to be sent
   686         *
   687         *  @b(returns)     TRUE denotes success and the packet is
   688         *                  no longer owned by the caller. FALSE denotes
   689         *                  failure and the packet is still owned by the caller.
   690         */
   691        Bool sendPacket(UIAPacket.Hdr *packet);
   692    
   693        /*!
   694         *  ======== setPeriod ========
   695         *  Allows services to set their event collection period
   696         *
   697         *  ServiceMgr's period should be a multiple of the ServiceMgr's period
   698         *  ({@link #periodInMs}). If it is not, they will called at the rounded
   699         *  up period. For example, if ServiceMgr.periodInMs = 100 and a service sets
   700         *  its period to 250. That service will be called every 300 milliseconds.
   701         *
   702         *  @param(id)         Service id of the service
   703         *
   704         *  @param(periodInMs) Requested period in milliseconds
   705         */
   706        Void setPeriod(ServiceId id, UInt32 periodInMs);
   707    
   708    internal:
   709    
   710        /*!
   711         *  ======== ServiceMgr Information ========
   712         *  The following arrays contain information about each service
   713         */
   714        config ProcessCallback processCallbackFxn[];
   715    
   716        struct Module_State {
   717            Int runCount;
   718            Int numServices;
   719        };
   720    }