]> rtime.felk.cvut.cz Git - ert_linux.git/blob - ert_linux/ext_svr.c
Suppress warning about thread return value.
[ert_linux.git] / ert_linux / ext_svr.c
1 /*
2  * Copyright 1994-2012 The MathWorks, Inc.
3  *
4  * File: ext_svr.c     
5  *
6  * Abstract:
7  *  External mode server interface (TCPIP example).  Provides functions
8  *  that get called by main routine (model-name.c):
9  *    o ExtParseArgsAndInitUD:  parse args and create UserData
10  *    o ExtWaitForStartPkt:     return true if waiting for host to start
11  *    o rt_ExtModeInit:         external mode initialization
12  *    o rt_ExtModeSleep:        pause the process
13  *    o rt_PktServerWork:       server for setting/getting packets from host
14  *    o rt_PktServer:           server dispatcher - for multi-tasking targets
15  *    o rt_UploadServerWork:    server for setting data upload packets on host
16  *    o rt_UploadServer:        server dispatcher - for multi-tasking targets
17  *    o rt_ExtModeShutdown:     external mode termination
18  *
19  *  Parameter downloading and data uploading supported for single and
20  *  multi-tasking targets.
21  */
22
23 /*****************
24  * Include files *
25  *****************/
26
27 /*ANSI C headers*/
28 #ifndef EXTMODE_DISABLEPRINTF  
29 #include <stdio.h>
30 #endif
31
32 #include <stdlib.h>
33 #include <string.h>
34
35 #if defined(VXWORKS)
36  /*VxWorks headers*/
37 # include <selectLib.h>
38 # include <sockLib.h>
39 # include <inetLib.h>
40 # include <ioLib.h>
41 # include <taskLib.h>
42 #endif
43
44 /*Real Time Workshop headers*/
45 #include "rtwtypes.h"
46 #include "rtw_extmode.h"
47
48 #include "ext_types.h"
49 #include "ext_share.h"
50 #include "ext_test.h"
51 #include "ext_svr_transport.h"
52 #include "updown.h"
53 #include "updown_util.h"
54 #include "dt_info.h"
55
56 /*Uncomment to test 4 byte reals*/
57 /*#define real_T float*/
58
59 /**********************
60  * External Variables *
61  **********************/
62 extern int_T           volatile startModel;
63 extern TargetSimStatus volatile modelStatus;
64 #ifdef VXWORKS
65 extern SEM_ID uploadSem;
66 extern SEM_ID pktSem;
67 #endif
68 extern boolean_T host_upstatus_is_uploading;
69
70 /********************
71  * Global Variables *
72  ********************/
73
74 /*
75  * Flags.
76  */
77 PRIVATE boolean_T   connected       = FALSE;
78 PRIVATE boolean_T   commInitialized = FALSE;
79
80 /*
81  * Pointer to opaque user data (defined by ext_svr_transport.c).
82  */
83 PRIVATE ExtUserData *extUD          = NULL;
84
85 /*
86  * Buffer used to receive packets.
87  */
88 PRIVATE int_T pktBufSize = 0;
89 PRIVATE char  *pktBuf    = NULL;
90
91
92 #ifndef EXTMODE_DISABLESIGNALMONITORING
93 #ifndef EXTMODE_DISABLEPRINTF 
94 PRIVATE char ERRMSG_PROCESSSELECTSIGNAL[] = 
95             "\nError in UploadLogInfoInit(). Most likely a memory\n"
96             "allocation error or an attempt to re-initialize the\n"
97             "signal selection during the data logging process\n"
98             "(i.e., multiple EXT_SELECT_SIGNAL packets were received\n"
99             "before the logging session terminated or an\n"
100             "EXT_CANCEL_LOGGING packet was received)\n";
101
102 PRIVATE char ERRMSG_PROCESSSELECTTRIGGER[] = 
103             "\nError in UploadInitTrigger(). Most likely a memory\n"
104             "allocation error or an attempt to re-initialize the\n"
105             "trigger selection during the data logging process\n"
106             "(i.e., multiple EXT_SELECT_TRIGGER packets were received\n"
107             "before the logging session terminated or an\n"
108             "EXT_CANCEL_LOGGING packet was received)\n";
109 #else
110 PRIVATE char ERRMSG_PROCESSSELECTSIGNAL[] = "";
111 PRIVATE char ERRMSG_PROCESSSELECTTRIGGER[] = "";
112 #endif
113 #endif
114
115 /*******************
116  * Local Functions *
117  *******************/
118
119 /* Function: GrowRecvBufIfNeeded ===============================================
120  * Abstract:
121  *  Allocate or increase the size of buffer for receiving packets from target.
122  */
123 PRIVATE boolean_T GrowRecvBufIfNeeded(const int pktSize)
124 {
125     if (pktSize > pktBufSize) {
126         if (pktBuf != NULL) {
127             free(pktBuf);
128             pktBufSize = 0;
129         }
130
131         pktBuf = (char *)malloc(pktSize);
132         if (pktBuf == NULL) return(EXT_ERROR);
133
134         pktBufSize = pktSize;
135     }
136     return(EXT_NO_ERROR);
137 } /* end GrowRecvBufIfNeeded */
138
139
140 /* Function: GetPktHdr =========================================================
141  * Abstract:
142  *  Attempts to retrieve a packet header from the host.  If a header is in 
143  *  fact retrieved, the reference arg, 'hdrAvail' will be returned as true.
144  *
145  *  EXT_NO_ERROR is returned on success, EXT_ERROR is returned on failure.
146  *
147  * NOTES:
148  *  o It is not necessarily an error for 'hdrAvail' to be returned as false.
149  *    It typically means that we were polling for packets and none were
150  *    available.
151  */
152 PRIVATE boolean_T GetPktHdr(PktHeader *pktHdr, boolean_T *hdrAvail)
153 {
154     int_T     nGot      = 0; /* assume */
155     int_T     nGotTotal = 0;
156     int_T     pktSize   = sizeof(PktHeader);
157     boolean_T error     = EXT_NO_ERROR;
158     
159     /* Get the header. */
160     while(nGotTotal < pktSize) {
161         error = ExtGetHostPkt(extUD,
162             pktSize - nGotTotal, &nGot, (char_T *)((char_T *)pktHdr + nGotTotal));
163         if (error) goto EXIT_POINT;
164
165         nGotTotal += nGot;
166
167         if (nGotTotal == 0) break;
168     }
169     assert((nGot == 0) || (nGotTotal == pktSize));
170
171 EXIT_POINT:
172     *hdrAvail = (boolean_T)(nGot > 0);
173     return(error);
174 } /* end GetPktHdr */
175
176
177 /* Function: ClearPkt ==========================================================
178  * Abstract:
179  *  Remove the data from the communication line one byte at a time.  This
180  *  function is called when there was not enough memory to receive an entire
181  *  packet.  Since the data was never received, it must be discarded so that
182  *  other packets can be sent.
183  */
184 PRIVATE void ClearPkt(const int pktSize)
185 {
186     int_T     nGot;
187     boolean_T error     = EXT_NO_ERROR;
188     int_T     nGotTotal = 0;
189     static    char buffer;
190
191     /* Get and discard the data one char at a time. */
192     while(nGotTotal < pktSize) {
193         error = ExtGetHostPkt(extUD, 1, &nGot, (char_T *)&buffer);
194         if (error) {
195 #ifndef EXTMODE_DISABLEPRINTF            
196             fprintf(stderr,"ExtGetHostPkt() failed.\n");
197 #endif
198             goto EXIT_POINT;
199         }
200
201         nGotTotal += nGot;
202     }
203
204 EXIT_POINT:
205     return;
206
207 } /* end ClearPkt */
208
209
210 /* Function: GetPkt ============================================================
211  * Abstract:
212  *  Receive nBytes from the host.  Return a buffer containing the bytes or
213  *  NULL if an error occurs.  Note that the pointer returned is that of the
214  *  global pktBuf.  If the buf needs to be grown to accommodate the package,
215  *  it is realloc'd.  This function will try to get the requested number
216  *  of bytes indefinitely - it is assumed that the data is either already there,
217  *  or will show up in a "reasonable" amount of time.
218  */
219 PRIVATE const char *GetPkt(const int pktSize)
220 {
221     int_T     nGot;
222     boolean_T error     = EXT_NO_ERROR;
223     int_T     nGotTotal = 0;
224
225     error = GrowRecvBufIfNeeded(pktSize);
226     if (error != EXT_NO_ERROR) {
227 #ifndef EXTMODE_DISABLEPRINTF            
228         fprintf(stderr,"Previous pkt from host thrown away due to lack of memory.\n");
229 #endif
230         ClearPkt(pktSize);
231         goto EXIT_POINT;
232     }
233     
234     /* Get the data. */
235     while(nGotTotal < pktSize) {
236         error = ExtGetHostPkt(extUD,
237             pktSize - nGotTotal, &nGot, (char_T *)(pktBuf + nGotTotal));
238         if (error) {
239 #ifndef EXTMODE_DISABLEPRINTF                
240             fprintf(stderr,"ExtGetHostPkt() failed.\n");
241 #endif
242             goto EXIT_POINT;
243         }
244
245         nGotTotal += nGot;
246     }
247
248 EXIT_POINT:
249     return((error == EXT_NO_ERROR) ? pktBuf : NULL);
250 } /* end GetPkt */
251
252
253 #ifndef EXTMODE_DISABLESIGNALMONITORING
254 /* Forward declaration */
255 void UploadServerWork(int32_T, int_T numSampTimes);
256 #endif
257
258 /* Function: DisconnectFromHost ================================================
259  * Abstract:
260  *  Disconnect from the host.
261  */
262 PRIVATE void DisconnectFromHost(int_T numSampTimes)
263 {
264     int i;
265
266     for (i=0; i<NUM_UPINFOS; i++) {
267         UploadPrepareForFinalFlush(i);
268
269 #if defined(VXWORKS)
270         /*
271          * UploadPrepareForFinalFlush() has already called semGive(uploadSem)
272          * two times.  Now the server thread will wait until the upload thread
273          * has processed all of the data in the buffers for the final upload
274          * and exhausted the uploadSem semaphores.  If the server thread
275          * attempts to call UploadServerWork() while the upload thread is in
276          * the middle of processing the buffers, the target code may crash
277          * with a NULL pointer exception (the buffers are destroyed after
278          * calling UploadLogInfoTerm).
279          */
280         while(semTake(uploadSem, NO_WAIT) != ERROR) {
281             semGive(uploadSem);
282             taskDelay(1000);
283         }
284 #else
285 #ifndef EXTMODE_DISABLESIGNALMONITORING
286         if (host_upstatus_is_uploading) {
287             UploadServerWork(i, numSampTimes);
288         }
289 #endif
290 #endif
291
292         UploadLogInfoTerm(i, numSampTimes);
293     }
294     
295     connected       = FALSE;
296     commInitialized = FALSE;
297     
298     ExtCloseConnection(extUD);
299 } /* end DisconnectFromHost */
300
301
302 /* Function: ForceDisconnectFromHost ===========================================
303  * Abstract:
304  *  Force a disconnect from the host.  This is not a graceful shutdown and
305  *  should only be used when the integrity of the external mode connection
306  *  is in question.  To shutdown the connection gracefully, use
307  *  DisconnectFromHost().
308  */
309 PRIVATE void ForceDisconnectFromHost(int_T numSampTimes)
310 {
311     int i;
312     connected       = FALSE;
313     commInitialized = FALSE;
314
315     for (i=0; i<NUM_UPINFOS; i++) {
316         UploadEndLoggingSession(i, numSampTimes);
317     }
318
319     ExtForceDisconnect(extUD);
320 } /* end ForceDisconnectFromHost */
321
322
323 /* Function: ProcessConnectPkt =================================================
324  * Abstract:
325  *  Process the EXT_CONNECT packet and send response to host.
326  */
327 PRIVATE boolean_T ProcessConnectPkt(RTWExtModeInfo *ei)
328 {
329     int_T                   nSet;
330     PktHeader               pktHdr;
331     int_T                   tmpBufSize;
332     uint32_T                *tmpBuf = NULL;
333     boolean_T               error   = EXT_NO_ERROR;
334     
335     const DataTypeTransInfo *dtInfo    = rteiGetModelMappingInfo(ei);
336     uint_T                  *dtSizes   = dtGetDataTypeSizes(dtInfo);
337     int_T                   nDataTypes = dtGetNumDataTypes(dtInfo);
338
339     assert(connected);
340     assert(!comminitialized);
341
342     /*
343      * Send the 1st of two EXT_CONNECT_RESPONSE packets to the host. 
344      * The packet consists purely of the pktHeader.  In this special
345      * case the pktSize actually contains the number of bits per byte
346      * (not always 8 - see TI compiler for C30 and C40).
347      */
348     pktHdr.type = (uint32_T)EXT_CONNECT_RESPONSE;
349     pktHdr.size = (uint32_T)8; /* 8 bits per byte */
350
351     error = ExtSetHostPkt(extUD,sizeof(pktHdr),(char_T *)&pktHdr,&nSet);
352     if (error || (nSet != sizeof(pktHdr))) {
353 #ifndef EXTMODE_DISABLEPRINTF            
354         fprintf(stderr,
355             "ExtSetHostPkt() failed for 1st EXT_CONNECT_RESPONSE.\n");
356 #endif
357         goto EXIT_POINT;
358     }
359
360     /* Send 2nd EXT_CONNECT_RESPONSE packet containing the following 
361      * fields:
362      *
363      * CS1 - checksum 1 (uint32_T)
364      * CS2 - checksum 2 (uint32_T)
365      * CS3 - checksum 3 (uint32_T)
366      * CS4 - checksum 4 (uint32_T)
367      *
368      * intCodeOnly   - flag indicating if target is integer only (uint32_T)
369      * 
370      * MWChunkSize   - multiword data type chunk size on target (uint32_T)
371      * 
372      * targetStatus  - the status of the target (uint32_T)
373      *
374      * nDataTypes    - # of data types        (uint32_T)
375      * dataTypeSizes - 1 per nDataTypes       (uint32_T[])
376      */
377
378     {
379         int nPktEls    = 4 +                        /* checkSums       */
380                          1 +                        /* intCodeOnly     */
381                          1 +                        /* MW chunk size   */
382                          1 +                        /* targetStatus    */
383                          1 +                        /* nDataTypes      */
384                          dtGetNumDataTypes(dtInfo); /* data type sizes */
385
386         tmpBufSize = nPktEls * sizeof(uint32_T);
387         tmpBuf     = (uint32_T *)malloc(tmpBufSize);
388         if (tmpBuf == NULL) {
389             error = EXT_ERROR; goto EXIT_POINT;
390         }
391     }
392     
393     /* Send packet header. */
394     pktHdr.type = EXT_CONNECT_RESPONSE;
395     pktHdr.size = tmpBufSize;
396
397     error = ExtSetHostPkt(extUD,sizeof(pktHdr),(char_T *)&pktHdr,&nSet);
398     if (error || (nSet != sizeof(pktHdr))) {
399 #ifndef EXTMODE_DISABLEPRINTF            
400         fprintf(stderr,
401             "ExtSetHostPkt() failed for 2nd EXT_CONNECT_RESPONSE.\n");
402 #endif
403         goto EXIT_POINT;
404     }
405    
406     /* Checksums, target status & SL_DOUBLESize. */
407     tmpBuf[0] = rteiGetChecksum0(ei);
408     tmpBuf[1] = rteiGetChecksum1(ei);
409     tmpBuf[2] = rteiGetChecksum2(ei);
410     tmpBuf[3] = rteiGetChecksum3(ei);
411
412 #if INTEGER_CODE == 0
413     tmpBuf[4] = (uint32_T)0;
414 #else
415     tmpBuf[4] = (uint32_T)1;
416 #endif
417
418     tmpBuf[5] = (uint32_T)sizeof(uchunk_T);
419     
420     tmpBuf[6] = (uint32_T)modelStatus;
421
422     /* nDataTypes and dataTypeSizes */
423     {        
424         int i;
425         tmpBuf[7] = (uint32_T)nDataTypes;
426         for (i=0; i<nDataTypes; i++) {
427             tmpBuf[8+i] = (uint32_T)dtSizes[i];
428         }
429     }
430     
431     /* Send the packet. */
432     error = ExtSetHostPkt(extUD,tmpBufSize,(char_T *)tmpBuf,&nSet);
433     if (error || (nSet != tmpBufSize)) {
434 #ifndef EXTMODE_DISABLEPRINTF            
435         fprintf(stderr,
436             "ExtSetHostPkt() failed.\n");
437 #endif
438         goto EXIT_POINT;
439     }
440
441     commInitialized = TRUE;
442
443 EXIT_POINT:
444     free(tmpBuf);
445     return(error);
446 } /* end ProcessConnectPkt */
447
448
449 /* Function: SendPktHdrToHost ==================================================
450  * Abstract:
451  *  Send a packet header to the host.
452  */
453 PRIVATE boolean_T SendPktHdrToHost(
454     const ExtModeAction action,
455     const int           size)  /* # of bytes to follow pkt header */
456 {
457     int_T     nSet;
458     PktHeader pktHdr;
459     boolean_T error = EXT_NO_ERROR;
460
461     pktHdr.type = (uint32_T)action;
462     pktHdr.size = size;
463
464     error = ExtSetHostPkt(extUD,sizeof(pktHdr),(char_T *)&pktHdr,&nSet);
465     if (error || (nSet != sizeof(pktHdr))) {
466         error = EXT_ERROR;
467 #ifndef EXTMODE_DISABLEPRINTF            
468         fprintf(stderr,"ExtSetHostPkt() failed.\n");
469 #endif
470         goto EXIT_POINT;
471     }
472
473 EXIT_POINT:
474     return(error);
475 } /* end SendPktHdrToHost */
476
477
478 /* Function: SendPktDataToHost =================================================
479  * Abstract:
480  *  Send packet data to host. You are responsible for sending a header
481  *  prior to sending the header.
482  */
483 PRIVATE boolean_T SendPktDataToHost(const char *data, const int size)
484 {
485     int_T     nSet;
486     boolean_T error = EXT_NO_ERROR;
487
488     error = ExtSetHostPkt(extUD,size,data,&nSet);
489     if (error || (nSet != size)) {
490         error = EXT_ERROR;
491 #ifndef EXTMODE_DISABLEPRINTF            
492         fprintf(stderr,"ExtSetHostPkt() failed.\n");
493 #endif
494         goto EXIT_POINT;
495     }
496
497 EXIT_POINT:
498     return(error);
499 } /* end SendPktDataToHost */
500
501
502 /* Function: SendPktToHost =====================================================
503  * Abstract:
504  *  Send a packet to the host.  Packets can be of two forms:
505  *      o packet header only
506  *          the type is used as a flag to notify Simulink of an event
507  *          that has taken place on the target (event == action == type)
508  *      o pkt header, followed by data
509  */
510 PUBLIC boolean_T SendPktToHost(
511     const ExtModeAction action,
512     const int           size,  /* # of bytes to follow pkt header */
513     const char          *data)
514 {
515     boolean_T error = EXT_NO_ERROR;
516     
517 #ifdef VXWORKS
518     semTake(pktSem, WAIT_FOREVER);
519 #endif
520
521     error = SendPktHdrToHost(action,size);
522     if (error != EXT_NO_ERROR) goto EXIT_POINT;
523
524     if (data != NULL) {
525         error = SendPktDataToHost(data, size);
526         if (error != EXT_NO_ERROR) goto EXIT_POINT;
527     } else {
528         assert(size == 0);
529     }
530
531 EXIT_POINT:
532 #ifdef VXWORKS
533     semGive(pktSem);
534 #endif
535     return(error);
536 } /* end SendPktToHost */
537
538
539 /* Function:  SendResponseStatus ===============================================
540  *  
541  */
542 PRIVATE boolean_T SendResponseStatus(const ExtModeAction  response,
543                                      const ResponseStatus status,
544                                      int32_T upInfoIdx)
545 {
546     int32_T   msg[2];
547     boolean_T error = EXT_NO_ERROR;
548
549     msg[0] = (int32_T)status;
550     msg[1] = upInfoIdx;
551
552     error = SendPktToHost(response,2*sizeof(int32_T),(char_T *)&msg);
553     return(error);
554
555 } /* end SendResponseStatus */
556
557
558 #ifndef EXTMODE_DISABLEPARAMETERTUNING
559 /* Function: ProcessSetParamPkt ================================================
560  * Receive and process the EXT_SETPARAM packet.
561  */
562 PRIVATE boolean_T ProcessSetParamPkt(RTWExtModeInfo *ei,
563                                      const int pktSize)
564 {
565     int32_T    msg;
566     const char *pkt;
567     boolean_T  error = EXT_NO_ERROR;
568
569     /*
570      * Receive packet and set parameters.
571      */
572     pkt = GetPkt(pktSize);
573     if (pkt == NULL) {
574         msg = (int32_T)NOT_ENOUGH_MEMORY;
575         SendPktToHost(EXT_SETPARAM_RESPONSE,sizeof(int32_T),(char_T *)&msg);
576         error = EXT_ERROR;
577         goto EXIT_POINT;
578     }
579     SetParam(ei, pkt);
580
581     msg = (int32_T)STATUS_OK;
582     error = SendPktToHost(EXT_SETPARAM_RESPONSE,sizeof(int32_T),(char_T *)&msg);
583     if (error != EXT_NO_ERROR) goto EXIT_POINT;
584
585 EXIT_POINT:
586     return(error);
587 } /* end ProcessSetParamPkt */
588 #endif /* ifndef EXTMODE_DISABLEPARAMETERTUNING */
589
590 #ifndef EXTMODE_DISABLEPARAMETERTUNING 
591 /* Function: ProcessGetParamsPkt ===============================================
592  *  Respond to the hosts request for the parameters by gathering up all the
593  *  params and sending them to the host.
594  */
595 PRIVATE boolean_T ProcessGetParamsPkt(RTWExtModeInfo *ei)
596 {
597     int_T                         i;
598     int_T                         nBytesTotal;
599     boolean_T                     error    = EXT_NO_ERROR;
600     const DataTypeTransInfo       *dtInfo  = rteiGetModelMappingInfo(ei);
601     const DataTypeTransitionTable *dtTable = dtGetParamDataTypeTrans(dtInfo);
602
603     if (dtTable != NULL) {
604         /*
605          * We've got some params in the model.  Send their values to the
606          * host.
607          */
608         int_T        nTrans   = dtGetNumTransitions(dtTable);
609         const uint_T *dtSizes = dtGetDataTypeSizes(dtInfo);
610
611  #ifdef VERBOSE
612     #ifndef EXTMODE_DISABLEPRINTF             
613         printf("\nUploading initial parameters....\n");
614  #endif
615 #endif 
616
617         /*
618          * Take pass 1 through the transitions to figure out how many
619          * bytes we're going to send.
620          */
621         nBytesTotal = 0;
622         for (i=0; i<nTrans; i++) {
623             int_T dt     = dtTransGetDataType(dtTable, i);
624             int_T dtSize = dtSizes[dt];
625             int_T nEls   = dtTransNEls(dtTable, i); /* complexity accounted for in trans tbl num of els */
626             int_T nBytes = dtSize * nEls;
627
628             nBytesTotal += nBytes;
629         }
630
631         /*
632          * Send the packet header.
633          */
634         error = SendPktHdrToHost(EXT_GETPARAMS_RESPONSE,nBytesTotal);
635         if (error != EXT_NO_ERROR) goto EXIT_POINT;
636
637         /*
638          * Take pass 2 through the transitions and send the parameters.
639          */
640         for (i=0; i<nTrans; i++) {
641             char_T *tranAddress  = dtTransGetAddress(dtTable, i);
642             int_T  dt            = dtTransGetDataType(dtTable, i);
643             int_T  dtSize        = dtSizes[dt];
644             int_T  nEls          = dtTransNEls(dtTable, i); /* complexity accounted for in trans tbl num of els */
645             int_T  nBytes        = dtSize * nEls;
646
647             error = SendPktDataToHost(tranAddress, nBytes);
648             if (error != EXT_NO_ERROR) goto EXIT_POINT;
649         }
650     } else {
651         /*
652          * We've got no params in the model.
653          */
654         error = SendPktHdrToHost(EXT_GETPARAMS_RESPONSE,0);
655         if (error != EXT_NO_ERROR) goto EXIT_POINT;
656     }
657
658 EXIT_POINT:
659     return(error);
660 } /* end ProcessGetParamsPkt */
661 #endif /* ifndef EXTMODE_DISABLEPARAMETERTUNING */
662
663
664 #ifndef EXTMODE_DISABLESIGNALMONITORING
665 /* Function: ProcessSelectTriggerSignalPkt ===========================================
666  * Receive and process the EXT_SELECT_TRIGGER or EXT_SELECT_SIGNALS packet.
667  */
668 PRIVATE boolean_T ProcessSelectTriggerSignalPkt(const ExtModeAction ACTION_ID, 
669                                                 RTWExtModeInfo *ei,
670                                                 const int pktSize,
671                                                 int_T numSampTimes,
672                                                 char* errMsg)
673 {
674     const char *pkt;
675     int32_T    upInfoIdx;
676     boolean_T  error = EXT_NO_ERROR;
677
678     pkt = GetPkt(pktSize);
679     if (pkt == NULL) {
680         SendResponseStatus(ACTION_ID, NOT_ENOUGH_MEMORY, -1);
681         return(EXT_ERROR);
682     }
683
684     (void)memcpy(&upInfoIdx, pkt, sizeof(int32_T)); /* Extract upInfoIdx */
685     switch(ACTION_ID) {
686     case EXT_SELECT_TRIGGER_RESPONSE:
687 #ifndef EXTMODE_DISABLEPRINTF  
688         PRINT_VERBOSE(
689                     ("got EXT_SELECT_TRIGGER packet for upInfoIdx : %d\n", upInfoIdx));
690 #endif
691         error = UploadInitTrigger(ei, pkt+sizeof(int32_T), upInfoIdx);
692         break;
693     case EXT_SELECT_SIGNALS_RESPONSE:
694 #ifndef EXTMODE_DISABLEPRINTF  
695         PRINT_VERBOSE(
696                     ("got EXT_SELECT_SIGNALS packet for upInfoIdx : %d\n", upInfoIdx));
697 #endif
698         error = UploadLogInfoInit(ei, numSampTimes, pkt+sizeof(int32_T), upInfoIdx);
699         break;
700     default:
701         break;
702     }
703
704     if (error != EXT_NO_ERROR) {
705         SendResponseStatus(ACTION_ID, NOT_ENOUGH_MEMORY, upInfoIdx);
706 #ifndef EXTMODE_DISABLEPRINTF            
707         printf("%s\n", errMsg);
708 #endif
709         return(error);
710     }
711
712     error = SendResponseStatus(ACTION_ID, STATUS_OK, upInfoIdx);
713     return(error); /* Can be EXT_NO_ERROR */
714 } /* end ProcessSelectTriggerSignalPkt */
715 #endif /* ifndef EXTMODE_DISABLESIGNALMONITORING */
716
717
718 #ifndef EXTMODE_DISABLESIGNALMONITORING
719 /* Function: ProcessCancelLoggingArmTriggerPkt ===========================================
720  * Receive and process the EXT_CANCEL_LOGGING or EXT_ARM_TRIGGER packet.
721  */
722 PRIVATE boolean_T ProcessCancelLoggingArmTriggerPkt(const ExtModeAction ACTION_ID, 
723                                                 const int pktSize, 
724                                                 int_T numSampTimes)
725 {
726     const char *pkt;
727     int32_T    upInfoIdx;
728     boolean_T  error = EXT_NO_ERROR;
729
730     pkt = GetPkt(pktSize);
731     if (pkt == NULL) {
732         SendResponseStatus(ACTION_ID, NOT_ENOUGH_MEMORY, -1);
733         return(EXT_ERROR);
734     }
735             
736     (void)memcpy(&upInfoIdx, pkt, sizeof(int32_T)); /* Extract upInfoIdx */
737         
738     switch(ACTION_ID) {
739     case EXT_CANCEL_LOGGING_RESPONSE:
740 #ifndef EXTMODE_DISABLEPRINTF   
741         PRINT_VERBOSE(
742                 ("got EXT_CANCEL_LOGGING packet for upInfoIdx : %d\n", upInfoIdx));
743 #endif
744         UploadCancelLogging(upInfoIdx);
745         break;
746     case EXT_ARM_TRIGGER_RESPONSE:
747 #ifndef EXTMODE_DISABLEPRINTF
748         PRINT_VERBOSE(
749                 ("got EXT_ARM_TRIGGER packet for upInfoIdx : %d\n", upInfoIdx));
750 #endif
751         UploadArmTrigger(upInfoIdx, numSampTimes);
752         break;
753     default:
754         break;
755     }
756
757     error = SendResponseStatus(ACTION_ID, STATUS_OK, upInfoIdx);
758     return(error); /* Can be EXT_NO_ERROR */
759 } /* end ProcessCancelLoggingArmTriggerPkt */
760 #endif /* ifndef EXTMODE_DISABLESIGNALMONITORING */
761
762
763 #ifdef EXTMODE_DISABLEPARAMETERTUNING
764 PRIVATE boolean_T AcknowledgeSetParamPkt(const int pktSize)
765 {
766     int32_T    msg;
767     const char *pkt;
768     boolean_T  error = EXT_NO_ERROR;
769
770     pkt = GetPkt(pktSize);
771     msg = (int32_T)STATUS_OK;
772     error = SendPktToHost(EXT_SETPARAM_RESPONSE, sizeof(int32_T), (char_T *)&msg);
773     return(error);
774 }
775 #endif /* ifdef EXTMODE_DISABLEPARAMETERTUNING */
776
777 #ifdef EXTMODE_DISABLESIGNALMONITORING
778 PRIVATE boolean_T AcknowledgeSignalActionPkt(const int pktSize, const ExtModeAction ACTION_ID)
779 {
780     const char *pkt;
781     int32_T    upInfoIdx;
782     boolean_T  error = EXT_NO_ERROR;
783
784     pkt = GetPkt(pktSize);
785     (void)memcpy(&upInfoIdx, pkt, sizeof(int32_T));
786     error = SendResponseStatus(ACTION_ID, STATUS_OK, upInfoIdx);
787     return(error);
788
789 #endif /* ifdef EXTMODE_DISABLESIGNALMONITORING */
790
791 /*********************
792  * Visible Functions *
793  *********************/
794
795
796 /* Function: ExtParseArgsAndInitUD =============================================
797  * Abstract:
798  *  Pass remaining arguments (main program should have NULL'ed out any args
799  *  that it processed) to external mode.
800  *  
801  *  The actual, transport-specific parsing routine (implemented in
802  *  ext_svr_transport.c) MUST NULL out all entries of argv that it processes.
803  *  The main program depends on this in order to determine if any unhandled
804  *  command line options were specified (i.e., if the main program detects
805  *  any non-null fields after the parse, it throws an error).
806  *
807  *  Returns an error string on failure, NULL on success.
808  *
809  * NOTES:
810  *  The external mode UserData is created here so that the specified command-
811  *  line options can be stored.
812  */
813 PUBLIC const char_T *ExtParseArgsAndInitUD(const int_T  argc,
814                                            const char_T *argv[])
815 {
816     const char_T *error = NULL;
817     
818     /*
819      * Create the user data.
820      */
821     extUD = ExtUserDataCreate();
822     if (extUD == NULL) {
823         error = "Could not create external mode user data.  Out of memory.\n";
824         goto EXIT_POINT;
825     }
826
827     /*
828      * Parse the transport-specific args.
829      */
830     error = ExtProcessArgs(extUD,argc,argv);
831     if (error != NULL) goto EXIT_POINT;
832         
833 EXIT_POINT:
834     if (error != NULL) {
835         ExtUserDataDestroy(extUD);
836         extUD = NULL;
837     }
838     return(error);
839 } /* end ExtParseArgsAndInitUD */
840
841
842 /* Function: ExtWaitForStartPkt ================================================
843  * Abstract:
844  *  Return true if waiting for host to tell us when to start.
845  */
846 PUBLIC boolean_T ExtWaitForStartPkt(void)
847 {
848     return(ExtWaitForStartPktFromHost(extUD));
849 } /* end ExtWaitForStartPkt */
850
851
852 #ifndef EXTMODE_DISABLESIGNALMONITORING
853 /* Function: UploadServerWork =================================================
854  * Abstract:
855  *  Upload model signals to host for a single upInfo.
856  */
857 void UploadServerWork(int32_T upInfoIdx, int_T numSampTimes)
858 {
859     int_T         i;
860     ExtBufMemList upList;
861     boolean_T     error = EXT_NO_ERROR;
862
863 #ifdef VXWORKS
864     /*
865      * Don't spin the CPU unless we've got data to upload.
866      * The upload.c/UploadBufAddTimePoint function gives the sem
867      * each time that data is added.
868      */
869 taskUnsafe();
870     semTake(uploadSem, WAIT_FOREVER);
871 taskSafe();
872 #endif
873
874     if (!connected) goto EXIT_POINT;
875     
876     UploadBufGetData(&upList, upInfoIdx, numSampTimes);
877     while(upList.nActiveBufs > 0) {
878         for (i=0; i<upList.nActiveBufs; i++) {
879             const BufMem *bufMem = &upList.bufs[i];
880
881             /*
882              * We call SendPktDataToHost() instead of SendPktToHost() because
883              * the packet header is combined with packet payload.  We do this
884              * to avoid the overhead of making two calls for each upload
885              * packet - one for the head and one for the payload.
886              */
887             error = SendPktDataToHost(
888                 bufMem->section1,
889                 bufMem->nBytes1);
890             if (error != EXT_NO_ERROR) {
891 #ifndef EXTMODE_DISABLEPRINTF                    
892                 fprintf(stderr,"SendPktDataToHost() failed on data upload.\n");
893 #endif
894                 goto EXIT_POINT;
895             }
896             
897             if (bufMem->nBytes2 > 0) {
898
899                 error = SendPktDataToHost(
900                     bufMem->section2,
901                     bufMem->nBytes2);
902                 if (error != EXT_NO_ERROR) {
903 #ifndef EXTMODE_DISABLEPRINTF                        
904                     fprintf(stderr,"SendPktDataToHost() failed on data upload.\n");
905 #endif
906                     goto EXIT_POINT;
907                 }
908             }
909             /* confirm that the data was sent */
910             UploadBufDataSent(upList.tids[i], upInfoIdx);
911         }
912         UploadBufGetData(&upList, upInfoIdx, numSampTimes);
913     }
914     
915 EXIT_POINT:
916     if (error != EXT_NO_ERROR) {
917         /* An error in this function is caused by a physical failure in the
918          * external mode connection.  We assume this failure caused the host
919          * to disconnect.  The target must be disconnected and returned to a
920          * state where it is running and can be re-connected to by the host.
921          */
922         ForceDisconnectFromHost(numSampTimes);
923     }
924 }
925 /* end UploadServerWork */
926 #endif /* ifndef EXTMODE_DISABLESIGNALMONITORING */
927
928 #ifndef EXTMODE_DISABLESIGNALMONITORING
929 /* Function: rt_UploadServerWork ===============================================
930  * Abstract:
931  *  Wrapper function that calls UploadServerWork once for each upInfo
932  */
933 PUBLIC void rt_UploadServerWork(int_T numSampTimes)
934 {
935     int i;
936     
937     for (i=0; i<NUM_UPINFOS; i++) {
938         UploadServerWork(i, numSampTimes);
939     }
940 } /* end rt_UploadServerWork */
941 #endif /* ifndef EXTMODE_DISABLESIGNALMONITORING */
942
943 /* Function: rt_ExtModeInit ====================================================
944  * Abstract:
945  *  Called once at program startup to do any initialization related to external
946  *  mode. 
947  */
948 PUBLIC boolean_T rt_ExtModeInit(void)
949 {
950     int i;
951     boolean_T error = EXT_NO_ERROR;
952
953 #ifdef TMW_EXTMODE_TESTING_REQ
954 #  ifndef TMW_EXTMODE_TESTING
955 #ifndef EXTMODE_DISABLEPRINTF 
956     fprintf(stderr,"Error: External mode tests should use the external mode test harness.\n");
957 #endif
958     error = EXT_ERROR;
959 #  endif
960 #endif
961     if (error != EXT_NO_ERROR) goto EXIT_POINT;
962
963     error = ExtInit(extUD);
964     if (error != EXT_NO_ERROR) goto EXIT_POINT;
965
966     for (i=0; i<NUM_UPINFOS; i++) {
967         UploadLogInfoReset(i);
968     }
969
970     rtExtModeTestingInit();
971
972 EXIT_POINT:
973     return(error);
974 } /* end rt_ExtModeInit */
975
976
977 /* Function: rt_ExtModeSleep ===================================================
978  * Abstract:
979  *  Called by grt_main, ert_main, and grt_malloc_main  to "pause".  It attempts
980  *  to do this in a way that does not hog the processor.
981  */
982 #ifndef VXWORKS
983 PUBLIC void rt_ExtModeSleep(
984     long sec,  /* number of seconds to wait       */
985     long usec) /* number of micro seconds to wait */
986 {
987     ExtModeSleep(extUD,sec,usec);
988 } /* end rt_ExtModeSleep */
989 #endif
990
991
992 /* Function: rt_PktServerWork ==================================================
993  * Abstract:
994  *  If not connected, establish communication of the packet line and the
995  *  data upload line.  If connected, send/receive packets and parameters
996  *  on the packet line.
997  */
998 PUBLIC void rt_PktServerWork(RTWExtModeInfo *ei,
999                              int_T          numSampTimes,
1000                              boolean_T      *stopReq)
1001 {
1002     PktHeader  pktHdr;
1003     boolean_T  hdrAvail;
1004     boolean_T  error             = EXT_NO_ERROR;
1005     boolean_T  disconnectOnError = FALSE;
1006     
1007     /*
1008      * If not connected, attempt to make connection to host.
1009      */
1010     if (!connected) {
1011         rtExtModeTestingKillIfOrphaned(FALSE);
1012
1013         error = ExtOpenConnection(extUD,&connected);
1014         if (error != EXT_NO_ERROR) goto EXIT_POINT;
1015     }
1016
1017     /*
1018      * If ExtOpenConnection is not blocking and there are no pending
1019      * requests to open a connection, we'll still be unconnected.
1020      */
1021     if (!connected) goto EXIT_POINT; /* nothing to do */
1022     
1023     /*
1024      * Process packets.
1025      */
1026
1027     /* Wait for a packet. */
1028     error = GetPktHdr(&pktHdr, &hdrAvail);
1029     if (error != EXT_NO_ERROR) {
1030 #ifndef EXTMODE_DISABLEPRINTF            
1031         fprintf(stderr, "\nError occurred getting packet header.\n");
1032 #endif
1033         disconnectOnError = TRUE;
1034         goto EXIT_POINT;
1035     }
1036     rtExtModeTestingKillIfOrphaned(hdrAvail);
1037     
1038     if (!hdrAvail) goto EXIT_POINT; /* nothing to do */
1039
1040     /*
1041      * This is the first packet.  Should contain the string:
1042      * 'ext-mode'.  Its contents are not important to us.
1043      * It is used as a flag to start the handshaking process.
1044      */
1045     if (!commInitialized) {
1046         pktHdr.type = EXT_CONNECT;
1047     }
1048
1049     /* 
1050      * At this point we know that we have a packet: process it.
1051      */
1052 #ifdef VXWORKS
1053     taskSafe();
1054 #endif
1055     switch(pktHdr.type) {
1056
1057     case EXT_GET_TIME:
1058     {
1059         /* Skip verbosity print out - we get too many of these */
1060         PRINT_VERBOSE(("got EXT_GET_TIME packet.\n"));
1061         time_T t = rteiGetT(ei);
1062         
1063         error = SendPktToHost(
1064             EXT_GET_TIME_RESPONSE,sizeof(time_T),
1065             (char_T *)&t);
1066         if (error != EXT_NO_ERROR) goto EXIT_POINT;
1067         break;
1068     }
1069
1070     case EXT_ARM_TRIGGER:
1071     {
1072 #ifndef EXTMODE_DISABLESIGNALMONITORING
1073         error = ProcessCancelLoggingArmTriggerPkt(EXT_ARM_TRIGGER_RESPONSE, pktHdr.size, numSampTimes);
1074         if (error != EXT_NO_ERROR) goto EXIT_POINT;
1075 #else
1076         error = AcknowledgeSignalActionPkt(pktHdr.size, EXT_ARM_TRIGGER_RESPONSE);
1077         if (error != EXT_NO_ERROR) goto EXIT_POINT;
1078 #endif
1079         break;
1080     }
1081
1082     case EXT_SELECT_SIGNALS:
1083     {
1084 #ifndef EXTMODE_DISABLESIGNALMONITORING
1085         error = ProcessSelectTriggerSignalPkt(EXT_SELECT_SIGNALS_RESPONSE, ei, pktHdr.size, numSampTimes, ERRMSG_PROCESSSELECTSIGNAL);
1086         if (error != EXT_NO_ERROR) goto EXIT_POINT;
1087 #else
1088         error = AcknowledgeSignalActionPkt(pktHdr.size, EXT_SELECT_SIGNALS_RESPONSE);
1089         if (error != EXT_NO_ERROR) goto EXIT_POINT;
1090 #endif
1091         break;
1092     }
1093
1094     case EXT_SELECT_TRIGGER: 
1095     {
1096 #ifndef EXTMODE_DISABLESIGNALMONITORING
1097         error = ProcessSelectTriggerSignalPkt(EXT_SELECT_TRIGGER_RESPONSE, ei, pktHdr.size, -1, ERRMSG_PROCESSSELECTTRIGGER);
1098         if (error != EXT_NO_ERROR) goto EXIT_POINT;
1099 #else
1100         error = AcknowledgeSignalActionPkt(pktHdr.size, EXT_SELECT_TRIGGER_RESPONSE);
1101         if (error != EXT_NO_ERROR) goto EXIT_POINT;
1102 #endif
1103         break;
1104     }
1105
1106     case EXT_CONNECT:
1107     {
1108         PRINT_VERBOSE(("got EXT_CONNECT packet.\n"));
1109         error = ProcessConnectPkt(ei);
1110         if (error != EXT_NO_ERROR) goto EXIT_POINT;
1111         break;
1112     }
1113
1114     case EXT_SETPARAM:
1115     {
1116 #ifndef EXTMODE_DISABLEPARAMETERTUNING
1117         PRINT_VERBOSE(("got EXT_SETPARAM packet.\n"));
1118         error = ProcessSetParamPkt(ei, pktHdr.size);
1119         if (error != EXT_NO_ERROR) goto EXIT_POINT;
1120 #else
1121         PRINT_VERBOSE(("discard EXT_SETPARAM packet.\n"));
1122         error = AcknowledgeSetParamPkt(pktHdr.size);
1123         if (error != EXT_NO_ERROR) goto EXIT_POINT;
1124 #endif
1125         break;
1126     }
1127
1128     case EXT_GETPARAMS:
1129     {
1130 #ifndef EXTMODE_DISABLEPARAMETERTUNING
1131         PRINT_VERBOSE(("got EXT_GETPARAMS packet.\n"));
1132         error = ProcessGetParamsPkt(ei);
1133         if (error != EXT_NO_ERROR) goto EXIT_POINT;
1134 #endif
1135         break;
1136     }
1137
1138     case EXT_DISCONNECT_REQUEST:
1139     {
1140         PRINT_VERBOSE(("got EXT_DISCONNECT_REQUEST packet.\n"));
1141         
1142         /*
1143          * Note that from the target's point of view this is
1144          * more a "notify" than a "request".  The host needs to
1145          * have this acknowledged before it can begin closing
1146          * the connection.
1147          */
1148         error = SendPktToHost(EXT_DISCONNECT_REQUEST_RESPONSE, 0, NULL);
1149         if (error != EXT_NO_ERROR) goto EXIT_POINT;
1150
1151         DisconnectFromHost(numSampTimes);
1152
1153         break;
1154     }
1155
1156     case EXT_DISCONNECT_REQUEST_NO_FINAL_UPLOAD:
1157     {
1158         PRINT_VERBOSE(("got EXT_DISCONNECT_REQUEST_NO_FINAL_UPLOAD packet.\n"));
1159         
1160         /*
1161          * The target receives this packet when the host is
1162          * immediately terminating the extmode communication due
1163          * to some error.  The target should not send back a
1164          * response or a final upload of data because the host is
1165          * expecting neither.  The target must be disconnected and
1166          * returned to a state where it is running and can be
1167          * re-connected to by the host.
1168          */
1169         ForceDisconnectFromHost(numSampTimes);
1170
1171         break;
1172     }
1173
1174     case EXT_MODEL_START:
1175         PRINT_VERBOSE(("got EXT_MODEL_START packet.\n"));
1176 #ifdef VXWORKS
1177         {
1178             extern SEM_ID startStopSem;
1179             semGive(startStopSem);
1180         }
1181 #endif
1182         startModel = TRUE;
1183         error = SendPktToHost(EXT_MODEL_START_RESPONSE, 0, NULL);
1184         if (error != EXT_NO_ERROR) goto EXIT_POINT;
1185         break;
1186
1187     case EXT_MODEL_STOP:
1188         PRINT_VERBOSE(("got EXT_MODEL_STOP packet.\n"));
1189         *stopReq = TRUE;
1190         break;
1191 #ifndef EXTMODE_DISABLETESTING
1192     case EXT_MODEL_PAUSE:
1193         PRINT_VERBOSE(("got EXT_MODEL_PAUSE packet.\n"));
1194         modelStatus = TARGET_STATUS_PAUSED;
1195         startModel  = FALSE;
1196
1197         error = SendPktToHost(EXT_MODEL_PAUSE_RESPONSE, 0, NULL);
1198         if (error != EXT_NO_ERROR) goto EXIT_POINT;
1199         break;
1200     case EXT_MODEL_STEP:
1201         PRINT_VERBOSE(("got EXT_MODEL_STEP packet.\n"));
1202         if ((modelStatus == TARGET_STATUS_PAUSED) && !startModel) {
1203             startModel = TRUE;
1204         }
1205         
1206         error = SendPktToHost(EXT_MODEL_STEP_RESPONSE, 0, NULL);
1207         if (error != EXT_NO_ERROR) goto EXIT_POINT;
1208         break;
1209     case EXT_MODEL_CONTINUE:
1210         PRINT_VERBOSE(("got EXT_MODEL_CONTINUE packet.\n"));
1211         if (modelStatus == TARGET_STATUS_PAUSED) {
1212             modelStatus = TARGET_STATUS_RUNNING;
1213             startModel  = FALSE;
1214         }
1215         
1216         error = SendPktToHost(EXT_MODEL_CONTINUE_RESPONSE, 0, NULL);
1217         if (error != EXT_NO_ERROR) goto EXIT_POINT;
1218 #endif
1219         break;
1220
1221     case EXT_CANCEL_LOGGING:
1222     {
1223 #ifndef EXTMODE_DISABLESIGNALMONITORING
1224         error = ProcessCancelLoggingArmTriggerPkt(EXT_CANCEL_LOGGING_RESPONSE, pktHdr.size, numSampTimes);
1225         if (error != EXT_NO_ERROR) goto EXIT_POINT;
1226 #else
1227         error = AcknowledgeSignalActionPkt(pktHdr.size, EXT_CANCEL_LOGGING_RESPONSE);
1228         if (error != EXT_NO_ERROR) goto EXIT_POINT;
1229 #endif
1230         break;
1231     }
1232
1233     default:
1234 #ifndef EXTMODE_DISABLEPRINTF            
1235         fprintf(stderr,"received invalid packet.\n");
1236 #endif
1237         break;
1238     } /* end switch */
1239
1240 EXIT_POINT:
1241     if (error != EXT_NO_ERROR) {
1242         if (disconnectOnError) {
1243 #ifndef EXTMODE_DISABLEPRINTF                
1244             fprintf(stderr,
1245                 "Error occurred in rt_PktServerWork.\n"
1246                 "Disconnecting from host!\n");
1247 #endif
1248             /* An error in this function which causes disconnectOnError to be
1249              * set to true is caused by a physical failure in the external mode
1250              * connection.  We assume this failure caused the host to disconnect.
1251              * The target must be disconnected and returned to a state
1252              * where it is running and can be re-connected to by the host.
1253              */
1254             ForceDisconnectFromHost(numSampTimes);
1255         }
1256     }
1257 #ifdef VXWORKS
1258     taskUnsafe();
1259 #endif
1260 } /* end rt_PktServerWork */
1261
1262
1263 /* Function: rt_PktServer ======================================================
1264  * Abstract:
1265  *  Call rt_PktServerWork forever.   Used only for RTOS (e.g., Tornado/VxWorks
1266  *  when running as a low priority task.
1267  */
1268 #ifdef VXWORKS
1269 PUBLIC void rt_PktServer(RTWExtModeInfo *ei,
1270                          int_T          numSampTimes,
1271                          boolean_T      *stopReq)
1272 {
1273     for(;;) {
1274         rt_PktServerWork(ei,numSampTimes,stopReq); 
1275     }
1276 }
1277 #endif
1278
1279
1280 /* Function: rt_UploadServer ===================================================
1281  * Abstract:
1282  *  Call rt_UploadServerWork forever.   Used only for RTOS (e.g.,
1283  *  Tornado/VxWorks when running as a low priority task.
1284  */
1285 #ifdef VXWORKS
1286 #ifndef EXTMODE_DISABLESIGNALMONITORING
1287 PUBLIC void rt_UploadServer(int_T numSampTimes)
1288 {
1289     for(;;) {
1290         rt_UploadServerWork(numSampTimes);
1291     }
1292 } /* end rt_UploadServer */
1293 #endif /* ifndef EXTMODE_DISABLESIGNALMONITORING */
1294 #endif
1295
1296
1297 /* Function: rt_SetPortInExtUD =================================================
1298  * Abstract:
1299  *  Set the port in the external mode user data structure.
1300  */
1301 #ifdef VXWORKS
1302 PUBLIC void rt_SetPortInExtUD(const int_T port)
1303 {
1304     ExtUserDataSetPort(extUD, port);
1305 } /* end rt_SetPortInExtUD */
1306 #endif
1307
1308 /* Function: ExtModeShutdown ==================================================
1309  * Abstract:
1310  *  Called when target program terminates to enable cleanup of external 
1311  *  mode for a given upInfo.
1312  */
1313 PRIVATE void ExtModeShutdown(int32_T upInfoIdx, int_T numSampTimes)
1314 {
1315     /*
1316      * Make sure buffers are flushed so that the final points get to
1317      * host (this is important for the case of the target reaching tfinal
1318      * while data uploading is in progress).
1319      */
1320     UploadPrepareForFinalFlush(upInfoIdx);
1321 #ifndef EXTMODE_DISABLESIGNALMONITORING
1322     UploadServerWork(upInfoIdx, numSampTimes);
1323 #endif
1324
1325     UploadLogInfoTerm(upInfoIdx, numSampTimes);
1326
1327     if (pktBuf != NULL) {
1328         free(pktBuf);
1329         pktBuf = NULL;
1330     }
1331
1332 } /* end ExtModeShutdown */
1333
1334 /* Function: rt_ExtModeShutdown ================================================
1335  * Abstract:
1336  *  Called when target program terminates to enable cleanup of external 
1337  *  mode.
1338  */
1339 PUBLIC boolean_T rt_ExtModeShutdown(int_T numSampTimes)
1340 {
1341     int i;
1342     boolean_T error = EXT_NO_ERROR;
1343
1344     for (i=0; i<NUM_UPINFOS; i++) {
1345         ExtModeShutdown(i, numSampTimes);
1346     }
1347
1348     if (commInitialized) {
1349         error = SendPktToHost(EXT_MODEL_SHUTDOWN, 0, NULL);
1350         if (error != EXT_NO_ERROR) {
1351 #ifndef EXTMODE_DISABLEPRINTF                
1352             fprintf(stderr,
1353                 "\nError sending EXT_MODEL_SHUTDOWN packet to host.\n");
1354 #endif
1355         }
1356         commInitialized = FALSE;
1357     }
1358     if (connected) {
1359         connected = FALSE;
1360         modelStatus = TARGET_STATUS_WAITING_TO_START;        
1361     }
1362
1363     ExtShutDown(extUD);
1364     ExtUserDataDestroy(extUD);
1365     
1366     rtExtModeTestingRemoveBatMarker();
1367     
1368     return(error);
1369 } /* end rt_ExtModeShutdown */
1370
1371 #ifndef EXTMODE_DISABLESIGNALMONITORING
1372 /* Function: rt_UploadCheckTrigger =============================================
1373  * Abstract:
1374  *  Wrapper function that calls UploadCheckTrigger once for each upInfo
1375  */
1376 PUBLIC void rt_UploadCheckTrigger(int_T numSampTimes)
1377 {
1378     int i;
1379     for (i=0; i<NUM_UPINFOS; i++) {
1380         UploadCheckTrigger(i, numSampTimes);
1381     }
1382 } /* end rt_UploadCheckTrigger */
1383
1384 /* Function: rt_UploadCheckEndTrigger ==========================================
1385  * Abstract:
1386  *  Wrapper function that calls UploadCheckTrigger once for each upInfo
1387  */
1388 PUBLIC void rt_UploadCheckEndTrigger(void)
1389 {
1390     int i;
1391     
1392     for (i=0; i<NUM_UPINFOS; i++) {
1393         UploadCheckEndTrigger(i);
1394     }
1395 } /* end rt_UploadCheckEndTrigger */
1396
1397 /* Function: rt_UploadBufAddTimePoint ==========================================
1398  * Abstract:
1399  *  Wrapper function that calls UploadBufAddTimePoint once for each upInfo
1400  */
1401 PUBLIC void rt_UploadBufAddTimePoint(int_T tid, real_T taskTime)
1402 {
1403     int i;
1404     
1405     for (i=0; i<NUM_UPINFOS; i++) {
1406         UploadBufAddTimePoint(tid, taskTime, i);
1407     }
1408 } /* end rt_UploadBufAddTimePoint */
1409 #endif /* ifndef EXTMODE_DISABLESIGNALMONITORING */
1410
1411 /* [EOF] ext_svr.c */