To LUGNET HomepageTo LUGNET News HomepageTo LUGNET Guide Homepage
 Help on Searching
 
Post new message to lugnet.robotics.rcx.legosOpen lugnet.robotics.rcx.legos in your NNTP NewsreaderTo LUGNET News Traffic PageSign In (Members)
 Robotics / RCX / legOS / 1320
1319  |  1321
Subject: 
Re: solaris + legOS
Newsgroups: 
lugnet.robotics.rcx.legos
Date: 
Fri, 28 Jul 2000 16:03:35 GMT
Viewed: 
1327 times
  
Hi,

Can you send me the full loader.c and any other changes that was done to
get it to compile under Solaris?  I am in the process of re-writing most
of dll to be easier to read (getting rid of a lot of the ifdefs,
renaming functions, etc), but still maintaining the cross-platform
compiling for both UNIX and Windows. Thanks

Ram

Ryan VanderBijl wrote:

YEAH! It works! And there was great rejoicing! :-)

This version sucsefully d/led the helloworld.lx, and it ran perfectly.
Thank you much!

I'm curious, what all did you change? I saw you did a cool thing to make
the getopt_long work...  (btw, it gave a small warning saying that
option_index
was unused in the main function.)
That should be applied to convert.c also, although you may have to do
something with optind to make it work.

Thanks again!

Ryan

... well.. i know that... i tried using that one before.  Like you said,
it
doesn't work.

Could you please try the appended version of loader.c?

Eddie C. Dost
ecd@skynet.be
--

/*! \file   loader.c
    \brief  legOS task downloading
    \author Markus L. Noga <markus@noga.de>
*/

/*
*  The contents of this file are subject to the Mozilla Public License
*  Version 1.0 (the "License"); you may not use this file except in
*  compliance with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/
*
*  Software distributed under the License is distributed on an "AS IS"
*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
*  License for the specific language governing rights and limitations
*  under the License.
*
*  The Original Code is legOS code, released October 2, 1999.
*
*  The Initial Developer of the Original Code is Markus L. Noga.
*  Portions created by Markus L. Noga are Copyright (C) 1999
*  Markus L. Noga. All Rights Reserved.
*
*  Contributor(s): everyone discussing LNP at LUGNET
*/

/*  2000.05.01
*
*  Modifications to the original loader.c file for LegOS 0.2.2 include:
*
*  Paolo Masetti's patches to eliminate "Invalid Argument" error and
*  to get rid of several compiler warnings:
*     <paolo.masetti@itlug.org>
*     http://www.lugnet.com/robotics/rcx/legos/?n=619
*
*  Markus L. Noga's solution to Cygwin's failure to define the O_ASYNC
symbol:
*     <markus@noga.de>
*     http://www.lugnet.com/robotics/rcx/legos/?n=439
*
*  Paolo Masetti's adaptation for definitive porting to Win32. No more
errors in
*  serial communication and conditional compile for Winnt (cygnwin).
*  Several addition to dll option to better support user. Execute dll
without
*  arguments to get help.
*     <paolo.masetti@itlug.org>
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>

#if defined(_WIN32)
  #include <windows.h>
#endif

#include <sys/lnp.h>
#include <sys/lnp-logical.h>

#include "rcxtty.h"
#include "keepalive.h"
#include <lx.h>

#define MAX_DATA_CHUNK 0xf8     //!< maximum data bytes/packet for
boot protocol
#define XMIT_RETRIES   5        //!< number of packet transmit retries
#define REPLY_TIMEOUT  750000   //!< timeout for reply
#define BYTE_TIME      (1000*LNP_BYTE_TIME) //!< time to transmit a byte.

#define DEFAULT_DEST  0
#define DEFAULT_PROGRAM 0
#define DEFAULT_SRCPORT 0
#define DEFAULT_PRIORITY 10

typedef enum {
  CMDacknowledge,     //!< 1:
  CMDdelete,       //!< 1+ 1: b[nr]
  CMDcreate,       //!< 1+12: b[nr] s[textsize] s[datasize] s[bsssize] s[stacksize] s[start] b[prio]
  CMDoffsets,       //!< 1+ 7: b[nr] s[text] s[data] s[bss]
  CMDdata,         //!< 1+>3: b[nr] s[offset] array[data]
  CMDrun,           //!< 1+ 1: b[nr]
  CMDirmode, //!< 1+ 1: b[0=near/1=far]
  CMDlast           //!< ?
} packet_cmd_t;

#if defined(__sun__) && defined(__svr4__)
#define _SOLARIS 1
#endif

#if !defined(_SOLARIS)
#include <getopt.h>

static const struct option long_options[]={
  {"rcxaddr",required_argument,0,'r'},
  {"program",required_argument,0,'p'},
  {"srcport",required_argument,0,'s'},
  {"tty",    required_argument,0,'t'},
  {"irmode", required_argument,0,'i'},
  {"execute",no_argument      ,0,'e'},
  {"verbose",no_argument      ,0,'v'},
  {0        ,0                ,0,0  }
};

#else // _SOLARIS

#define getopt_long(ac, av, opt, lopt, lidx) (getopt((ac), (av), (opt)))

#endif // _SOLARIS

volatile int receivedAck=0;

volatile unsigned short relocate_to=0;

unsigned int  rcxaddr = DEFAULT_DEST,
              prog    = DEFAULT_PROGRAM,
              srcport = DEFAULT_SRCPORT,
  irmode  = -1;

int run_flag=0;
int verbose_flag=0;

void io_handler(void);

/*! blocking I/R write.
*! return number of bytes written, or negative for error.
*/
int lnp_logical_write(const void *data, size_t length) {

// With Win32 we are using Blocking Write by default
#if !defined(_WIN32)
  fd_set fds;

  // wait for transmission
  //
  do {
    FD_ZERO(&fds);
    FD_SET(rcxFD(),&fds);
  } while(select(rcxFD()+1,NULL,&fds,NULL,NULL)<1);
#endif

  // transmit
  //
  keepaliveRenew();

  return mywrite(rcxFD(), data, length)!=length;
}

//! send a LNP layer 0 packet of given length
/*! \return 0 on success.
*/
int lnp_assured_write(const unsigned char *data, unsigned char length,
                      unsigned char dest, unsigned char srcport) {
  int i;
  struct timeval timeout,now;
  unsigned long total,elapsed;

  for(i=0; i<XMIT_RETRIES; i++) {
    receivedAck=0;

    lnp_addressing_write(data,length,dest,srcport);

    gettimeofday(&timeout,0);
    total=REPLY_TIMEOUT+length*BYTE_TIME;
    elapsed=0;

    do {
#if defined(_WIN32)
      io_handler();
#else
      struct timeval tv;
      fd_set fds;

      FD_ZERO(&fds);
      FD_SET(rcxFD(), &fds);

      tv.tv_sec = (total - elapsed) / 1000000;
      tv.tv_usec = (total - elapsed) % 1000000;
      select(rcxFD() + 1, &fds, NULL, NULL, &tv);
      if (FD_ISSET(rcxFD(), &fds))
io_handler();
#endif

      gettimeofday(&now,0);
      elapsed=1000000*(now.tv_sec  - timeout.tv_sec ) +
              now.tv_usec - timeout.tv_usec;

    } while((!receivedAck) && (elapsed < total));

    if(i || !receivedAck)
      if(verbose_flag)
        fprintf(stderr,"try %d: ack:%d\n",i,receivedAck);

    if(receivedAck)
      return 0;
   }

  return -1;
}

void io_handler(void) {

    static struct timeval last={0,0};
    struct timeval now;
    unsigned long diff;

    unsigned char buffer[256];
#if defined(_WIN32)
    DWORD len;
    int i;
#else
    int len,i;
#endif

    gettimeofday(&now,0);
    diff= 1000000*now .tv_sec + now .tv_usec -
(1000000*last.tv_sec + last.tv_usec);

    if(diff> 10000*LNP_BYTE_TIMEOUT) {
      if(verbose_flag)
        fprintf(stderr,"\n#time %lu ",diff);
      lnp_integrity_reset();
    }
#if defined(_WIN32)
    ReadFile(rcxFD(), buffer, sizeof(buffer), &len, NULL);
#else
    len=read(rcxFD(),buffer,sizeof(buffer));
#endif
    for(i=0; i<len; i++) {
      if(verbose_flag)
        fprintf(stderr,"%02x ",buffer[i]);
      lnp_integrity_byte(buffer[i]);
    }
    gettimeofday(&last,0);
}

void LNPinit(const char *tty) {
  struct timeval timeout,now;
  long diff;

#if !defined(_WIN32)
  unsigned char buffer[256];
#endif

  // initialize RCX communications
  //
  if (verbose_flag) fputs("opening tty...\n", stderr);
#ifdef LNP_FAST
  rcxInit(tty, 1);
#else
  rcxInit(tty, 0);
#endif

  if (rcxFD() == BADFILE) {
    myperror("opening tty");
    exit(1);
  }
  keepaliveInit();

  // wait for IR to settle
  //
  gettimeofday(&timeout,0);
  do {
    usleep(100000);
    gettimeofday(&now,0);
    diff=1000000*(now.tv_sec  - timeout.tv_sec ) +
           now.tv_usec - timeout.tv_usec;

  } while(diff < 100000);
#if defined(_WIN32)
  PurgeComm(rcxFD(), PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
#else
  read(rcxFD(),buffer,256);
#endif
}

void ahandler(const unsigned char *data,unsigned char len,unsigned char src)
{
  if(*data==CMDacknowledge) {
    receivedAck=1;
    if(len==8) {
      // offset packet
      //
      relocate_to=(data[2]<<8)|data[3];
    }
  }
}

void lnp_download(const lx_t *lx) {
  unsigned char buffer[256+3];

  size_t i,chunkSize,totalSize=lx->text_size+lx->data_size;

  if(verbose_flag)
    fputs("\ndata ",stderr);

  buffer[0]=CMDdata;
  buffer[1]=prog;

  for(i=0; i<totalSize; i+=chunkSize) {
    chunkSize=totalSize-i;
    if(chunkSize>MAX_DATA_CHUNK)
      chunkSize=MAX_DATA_CHUNK;

    buffer[2]= i >> 8;
    buffer[3]= i &  0xff;
    memcpy(buffer+4,lx->text + i,chunkSize);
    if(lnp_assured_write(buffer,chunkSize+4,rcxaddr,srcport)) {
      fputs("error downloading program\n",stderr);
      exit(-1);
    }
  }
}

int main(int argc, char **argv) {
  lx_t lx;        // the legOS executable
  char *filename;
  int opt,option_index;

  unsigned char buffer[256+3]="";
  char *tty=NULL;

  while((opt=getopt_long(argc, argv, "r:p:s:t:i:ev",
                        (struct option *)long_options, &option_index) )!=-1)
                        {
    switch(opt) {
      case 'e':
  run_flag=1;
        break;
      case 'r':
  sscanf(optarg,"%x",&rcxaddr);
        break;
      case 'p':
  sscanf(optarg,"%x",&prog);
        break;
      case 's':
  sscanf(optarg,"%x",&srcport);
        break;
      case 't':
  sscanf(optarg,"%s",buffer);
        break;
      case 'i':
  sscanf(optarg,"%x",&irmode);
        break;
      case 'v':
  verbose_flag=1;
  break;
    }
  }

  // load executable
  //
  if(argc-optind<1) {
    char *usage_string =
"  -p<prognum>  , --program=<prognum>   set destination program to <prognum>\n"
"  -r<rcxadress>, --rcxaddr=<rcxadress> set RCX address to <rcxaddress>\n"
"  -s<srcadress>, --srcport=<srcadress> set RCX sourceport to
<srcaddress>\n"
"  -t<comport>  , --tty=<comport>       set IR Tower com port <comport>\n"
"  -i<0/1>      , --irmode=<0/1>        set IR mode near(0)/far(1) on
RCX\n"
"  -e           , --execute             execute program after download\n"
"  -v           , --verbose             verbose mode\n"
"\n"
"Default com port can be set using environment variable RCXTTY.\n"
"Eg:\tset RCXTTY=COM2\n"
"\n"
;

fprintf(stderr, "usage: %s [options] file.lx\n", argv[0]);
fprintf(stderr, usage_string);

    return -1;
  }
  filename=argv[optind++];
  if(lx_read(&lx,filename)) {
    fprintf(stderr,"unable to load legOS executable from %s.\n",filename);
    return -1;
  }

  // Moved tty device setting for a new option on command line
  if (buffer[0]) tty=buffer;
  if (!tty) tty = getenv(TTY_VARIABLE);
  if (!tty) tty = DEFAULTTTY;

  LNPinit(tty);

  if (verbose_flag)
    fputs("\nLNP Initialized...\n",stderr);

  lnp_addressing_set_handler(0,ahandler);

  if(verbose_flag)
    fprintf(stderr,"loader hostaddr=%02x hostmask=%02x portmask=%02x\n",
            LNP_HOSTADDR & 0x00ff,LNP_HOSTMASK & 0x00ff, LNP_PORTMASK &
            0x00ff);

  // Set IR mode
  if (irmode != -1) {
    buffer[0]=CMDirmode;
    buffer[1]=irmode;
    if(lnp_assured_write(buffer,2,rcxaddr,srcport)) {
      fputs("error setting IR mode to far\n",stderr);
      return -1;
    }
  }

  if(verbose_flag)
    fputs("\ndelete",stderr);
  buffer[0]=CMDdelete;
  buffer[1]=prog; //       prog 0
  if(lnp_assured_write(buffer,2,rcxaddr,srcport)) {
    fputs("error deleting program\n",stderr);
    return -1;
  }

  if(verbose_flag)
    fputs("\ncreate ",stderr);
  buffer[ 0]=CMDcreate;
  buffer[ 1]=prog; //       prog 0
  buffer[ 2]=lx.text_size>>8;
  buffer[ 3]=lx.text_size & 0xff;
  buffer[ 4]=lx.data_size>>8;
  buffer[ 5]=lx.data_size & 0xff;
  buffer[ 6]=lx.bss_size>>8;
  buffer[ 7]=lx.bss_size & 0xff;
  buffer[ 8]=lx.stack_size>>8;
  buffer[ 9]=lx.stack_size & 0xff;
  buffer[10]=lx.offset >> 8;  // start offset from text segment
  buffer[11]=lx.offset & 0xff;
  buffer[12]=DEFAULT_PRIORITY;
  if(lnp_assured_write(buffer,13,rcxaddr,srcport)) {
    fputs("error creating program\n",stderr);
    return -1;
  }

  // relocation target address in relocate_to
  //
  lx_relocate(&lx,relocate_to);

  lnp_download(&lx);

  if (run_flag) {
    if(verbose_flag)
      fputs("\nrun ",stderr);
    buffer[0]=CMDrun;
    buffer[1]=prog; //       prog 0
    if(lnp_assured_write(buffer,2,rcxaddr,srcport)) {
      fputs("error running program\n",stderr);
      return -1;
    }
  }

  return 0;
}


--
Ryan VanderBijl                        http://www.calvin.edu/~rvbijl39

(Frodo:) "I don't want to answer a string of questions while I am
eating. I want to think!" "Good heavens!" said Pippin. "At breakfast?"





Message has 1 Reply:
  Re: solaris + legOS
 
(...) Actually you should refer to CVS files that are available from (URL) tree contains the Solaris patch too. Bye, Paolo. --- Gambling: The sure way of getting nothing for something. (24 years ago, 1-Aug-00, to lugnet.robotics.rcx.legos)

Message is in Reply To:
  Re: solaris + legOS
 
YEAH! It works! And there was great rejoicing! :-) This version sucsefully d/led the helloworld.lx, and it ran perfectly. Thank you much! I'm curious, what all did you change? I saw you did a cool thing to make the getopt_long work... (btw, it gave (...) (24 years ago, 28-Jul-00, to lugnet.robotics.rcx.legos)

3 Messages in This Thread:

Entire Thread on One Page:
Nested:  All | Brief | Compact | Dots
Linear:  All | Brief | Compact

This Message and its Replies on One Page:
Nested:  All | Brief | Compact | Dots
Linear:  All | Brief | Compact
    

Custom Search

©2005 LUGNET. All rights reserved. - hosted by steinbruch.info GbR