To LUGNET HomepageTo LUGNET News HomepageTo LUGNET Guide Homepage
 Help on Searching
 
Post new message to lugnet.roboticsOpen lugnet.robotics in your NNTP NewsreaderTo LUGNET News Traffic PageSign In (Members)
 Robotics / 19389
19388  |  19390
Subject: 
Linux USB-support for BrickOS.
Newsgroups: 
lugnet.robotics
Date: 
Sun, 3 Nov 2002 02:46:47 GMT
Original-From: 
P.C. Chan <pc.chan@alcatel.#stopspam#com>
Viewed: 
763 times
  
Dear Markus,

This probably already been done.  Here is one way of patching
brickos-0.2.6.08.newConf to work with usb tower under linux.

It involves patching firmdl.c, rcx_comm.c, loader.c and rcxtty.c

--- brickos-0.2.6.08.newConf/util/firmdl/firmdl.c       Fri Oct 11
23:22:26 2002
+++ brickos-0.2.6.08.newConf/util/firmdl/firmdl.c.patched       Sat Nov
2 21:03:11 2002
@@ -417,6 +417,14 @@
                fprintf(stderr, "Hary Mahesan - USB IR Tower Mode.\n");
        tty = "\\\\.\\legotower1"; // Set the correct usb tower if you
have more than one (unlikely).
     }
+#elif defined(LINUX) || defined(linux)
+   /* If the tty string contains "tower", e.g. /dev/tower0, we assume
it is */
+   /* an USB tower.  If you use something else, link it. */
+   if (strstr(tty,"tower") !=0) {
+       tty_usb=1;
+       if (__comm_debug)
+          fprintf(stderr, "USB IR Tower Mode for Linux.\n");
+   }
#endif

     if (use_fast && (tty_usb==0)) { //For now, run USB only at 2400bps
(slow mode).




--- brickos-0.2.6.08.newConf/util/firmdl/rcx_comm.c     Wed Aug 28
23:52:50 2002
+++ brickos-0.2.6.08.newConf/util/firmdl/rcx_comm.c.patched     Sat Nov
2 10:31:24 2002
@@ -46,6 +46,7 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>
+#include <errno.h>

#if defined(_WIN32)
   #include <windows.h>
@@ -167,6 +168,13 @@
        tv.tv_sec = timeout / 1000;
        tv.tv_usec = (timeout % 1000) * 1000;

+        /* For linux usb tower, I personally use mode 4, high power
with   */
+        /* 10ms urb interval, the original 50ms timeout is not good
enough */
+        /* in turnng around a multi-urb send. I'll give it at least 1
sec. */
+
+        if ((tty_usb == 1) && (tv.tv_sec < 1))
+           tv.tv_sec=1;
+
        if (select(fd+1, &fds, NULL, NULL, &tv) < 0) {
            perror("select");
            exit(1);
@@ -210,7 +218,31 @@
     WriteFile(fd, buf, len, &nBytesWritten, NULL);
     return nBytesWritten;
#else
-    return write(fd, buf, len);
+    /* For usb tower, the driver, legousbtower, uses interrupt  */
+    /* urb which can only carry up to 8 bytes at a time. To     */
+    /* transmit more we have to check and send the rest.  It is */
+    /* a good thing to check, so I'll make it general.          */
+
+    int actual = 0;
+    int rc;
+    char * cptr;
+    int retry = 1000;
+
+    if (len < 1) return len;
+    cptr = (char *) buf;
+    while (actual < len) {
+      rc = (long) write(fd, cptr+actual, len-actual);
+      if (rc == -1) {
+        if ((errno == EINTR) || (errno == EAGAIN))  {
+          rc = 0;
+          usleep(10);
+          retry --;
+        } else return -1;
+      }
+      actual += rc;
+      if (retry < 1) return actual;
+    }
+    return len;
#endif
}

@@ -269,29 +301,31 @@
        perror(tty);
        exit(1);
     }
-
-    if (!isatty(fd)) {
+
+    if (tty_usb == 0) {
+      if (!isatty(fd)) {
        close(fd);
        fprintf(stderr, "%s: not a tty\n", tty);
        exit(1);
-    }
+      }

-    memset(&ios, 0, sizeof(ios));
+      memset(&ios, 0, sizeof(ios));

-    if (is_fast) {
+      if (is_fast) {
        ios.c_cflag = CREAD | CLOCAL | CS8;
        cfsetispeed(&ios, B4800);
        cfsetospeed(&ios, B4800);
-    }
-    else {
+      }
+      else {
        ios.c_cflag = CREAD | CLOCAL | CS8 | PARENB | PARODD;
        cfsetispeed(&ios, B2400);
        cfsetospeed(&ios, B2400);
-    }
+      }

-    if (tcsetattr(fd, TCSANOW, &ios) == -1) {
+      if (tcsetattr(fd, TCSANOW, &ios) == -1) {
        perror("tcsetattr");
        exit(1);
+      }
     }
#endif

--- brickos-0.2.6.08.newConf/util/dll-src/loader.c      Wed Aug 28
23:52:50 2002
+++ brickos-0.2.6.08.newConf/util/dll-src/loader.c.patched      Sat Nov
2 11:14:37 2002
@@ -171,7 +171,10 @@

   // transmit
   //
-  keepaliveRenew();
+#if defined(LINUX) || defined(linux)
+  if (tty_usb == 0)
+#endif
+    keepaliveRenew();

   return mywrite(rcxFD(), data, length)!=length;
}
@@ -302,22 +305,31 @@
     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 ) +
+#if defined(LINUX) || defined(linux)
+  if (tty_usb == 0) {
+#endif
+    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);
+    } while(diff < 100000);
+#if defined(LINUX) || defined(linux)
+  }
+#endif
#if defined(_WIN32)
   PurgeComm(rcxFD(), PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR |
PURGE_RXCLEAR);
#else
-  read(rcxFD(),buffer,256);
+  #if defined(LINUX) || defined(linux)
+    if (tty_usb == 0)
+  #endif
+       read(rcxFD(),buffer,256);
#endif
}

@@ -476,6 +488,14 @@
                fputs("\n\n Hary Mahesan - LEGO USB IR Tower
Mode\n\n",stderr);
        tty="\\\\.\\legotower1"; // Set the correct usb tower if you
have more than one (unlikely).
   }
+#elif defined(LINUX) || defined(linux)
+   /* If the tty string contains "tower", e.g. /dev/tower0, we assume
it is */
+   /* an USB tower.  If you use something else, link it. */
+   if (strstr(tty,"tower") !=0) {
+       tty_usb=1;
+       if (verbose_flag)
+          fputs("\nUSB IR Tower Mode for Linux.\n",stderr);
+   }
#endif

   LNPinit(tty);
--- brickos-0.2.6.08.newConf/util/dll-src/rcxtty.c      Mon Aug 19
23:04:29 2002
+++ brickos-0.2.6.08.newConf/util/dll-src/rcxtty.c.patched      Sat Nov
2 11:24:03 2002
@@ -41,6 +41,7 @@
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
+#include <errno.h>

#if defined(_WIN32)
   #include <windows.h>
@@ -77,7 +78,31 @@
     else
       return -1;
#else
-    return write(fd, buf, len);
+    /* For usb tower, the driver, legousbtower, uses interrupt  */
+    /* urb which can only carry up to 8 bytes at a time. To     */
+    /* transmit more we have to check and send the rest.  It is */
+    /* a good thing to check, so I'll make it general.          */
+
+    int actual = 0;
+    int rc;
+    char * cptr;
+    int retry = 1000;
+
+    if (len < 1) return len;
+    cptr = (char *) buf;
+    while (actual < len) {
+      rc = (long) write(fd, cptr+actual, len-actual);
+      if (rc == -1) {
+        if ((errno == EINTR) || (errno == EAGAIN))  {
+          rc = 0;
+          usleep(10);
+          retry --;
+        } else return -1;
+      }
+      actual += rc;
+      if (retry < 1) return actual;
+    }
+    return len;
#endif
}

@@ -124,7 +149,7 @@
   }

#if !defined(_WIN32)
-  if (!isatty(fd)) {
+  if ((tty_usb ==0) && (!isatty(fd))) {
     close(fd);
     fprintf(stderr, "%s: not a tty\n", tty);
     return -1;
@@ -172,15 +197,17 @@
   }
   rcxFd=fd;
#else
-  memset(&ios, 0, sizeof(ios));
-  ios.c_cflag = CREAD | CLOCAL | CS8 | (highspeed ? 0 : PARENB | PARODD);
-
-  cfsetispeed(&ios, highspeed ? B4800 : B2400);
-  cfsetospeed(&ios, highspeed ? B4800 : B2400);
-
-  if (tcsetattr(fd, TCSANOW, &ios) == -1) {
-    perror("tcsetattr");
-    exit(1);
+  if (tty_usb == 0) {
+    memset(&ios, 0, sizeof(ios));
+    ios.c_cflag = CREAD | CLOCAL | CS8 | (highspeed ? 0 : PARENB | PARODD);
+
+    cfsetispeed(&ios, highspeed ? B4800 : B2400);
+    cfsetospeed(&ios, highspeed ? B4800 : B2400);
+
+    if (tcsetattr(fd, TCSANOW, &ios) == -1) {
+      perror("tcsetattr");
+      exit(1);
+    }
   }
   rcxFd=fd;
#endif

To specify USB tower,  export the tower device name in RCXTTY.  The name
must contain "tower", e.g. export RCXTTY=/dev/tower0.
If the name does not contain "tower" just link to something does.

I am using the usb tower driver from legousbtower project at
sourceforge.net with patches.   Please read my mails in the mailing list
for details of the patches we need on top of the source code posted on
the site.  After the patches legousbtower would support the open, close,
read, write and poll operations on the tower.

With the combination,  I am able to walk through the brickos demo's
using an usb tower on linux.

There would be options not  supported on this combination.

I myself hard coded the legoustower driver in mode 4 (high power and 10
ms urb interval, in original legousbtower driver we use mode 1 i.e low
power, 1ms urb interval.)  Hence the power mode would no longer be set
through dll.   I haven't tried speed change, it is probably dictated by
the urb interval which is already hardcoded in my case.)   To make this
user controllerable, we first have to standardize on the IOCTL on
controling the usb mode.   There has not been enough stream to drive it yet.

I am not sure how to use the source port in dll.  Hence I cannot verify
if it works.   Sorry, this is the first time I use brickos.

If we have enough need for brickos to work with usb tower under linux,
please feel free to incorporate the patches.

Thanks,
P.C.



1 Message in This Thread:

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

Custom Search

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