Index: trunk/code/projects/colonet/lib/colonet_wireless/colonet_wireless_test.cpp
===================================================================
--- trunk/code/projects/colonet/lib/colonet_wireless/colonet_wireless_test.cpp	(nonexistent)
+++ trunk/code/projects/colonet/lib/colonet_wireless/colonet_wireless_test.cpp	(revision 11)
@@ -0,0 +1,85 @@
+/* Eugene Marinelli
+ * 11/2/06
+ *
+ * colonet_wireless_test - tests the colonet_wireless library
+ */
+
+#include <iostream>
+#include <signal.h>
+
+#include "colonet_wireless.h"
+
+int msg_handler(ColonetPacket* pkt)
+{
+  printf("Handler!\n");
+
+  fprintf(stderr, 
+          "token_src:%d\n"
+          "token_dest:%d\n"
+          "msg_dest:%d\n"
+          "msg_type:%d\n"
+          "msg_code:%d\n"
+          "num_robots:%d\n",
+          pkt->token_src, pkt->token_dest, pkt->msg_dest, pkt->msg_type,
+          pkt->msg_code, pkt->num_robots);
+  
+  printf("data: ");
+
+  for(int i = 0; i < PACKET_DATA_LEN; i++){
+    printf("%d ", pkt->data[i]);
+  }
+  
+  printf("\n\n");
+
+  return 0;
+}
+
+int main()
+{
+  ColonetWireless* cw = new ColonetWireless(SERIAL_PORT, msg_handler, NULL, 
+                                            true, false);
+
+  /*
+  unsigned char orbdata[3] = {0xFF, 0xFF, 0xFF};
+  unsigned char motordata[4] = {0, 1, 0, 0xFF};
+  unsigned char motordata2[4] = {0, 0, 0, 0xFF};
+  unsigned char buzzerdata[5] = {0x01};
+  */
+
+  unsigned char data[10];
+  unsigned char msgcode;
+
+  //cw->send(GLOBAL_DEST, 0, 0, "eugene");
+
+  //cw->send(GLOBAL_DEST, COLONET_COMMAND, ORB_SET, orbdata);
+  //cw->send(GLOBAL_DEST, COLONET_COMMAND, MOTOR1_SET, motordata);
+
+  //cw->send(GLOBAL_DEST, COLONET_COMMAND, BUZZER_INIT, (unsigned char*)"");
+  //cw->send(GLOBAL_DEST, COLONET_COMMAND, BUZZER_SET_VAL, buzzerdata);
+
+  cw->run_listener_thread();
+
+  printf("spawned thread\n");
+
+  while(1){
+    printf("Code: ");
+    scanf("%x", (int*)&msgcode);
+
+    for (int i = 0; i < 5; i++) {
+      printf("Byte %d: ", i);
+      scanf("%x", (int*)&(data[i]));
+    }
+
+    cw->send(GLOBAL_DEST, COLONET_COMMAND, msgcode, data);
+
+    /*
+    cw->send(GLOBAL_DEST, COLONET_COMMAND, ORB_SET, orbdata);
+    cw->send(GLOBAL_DEST, COLONET_COMMAND, MOTOR1_SET, motordata);
+    cw->send(GLOBAL_DEST, COLONET_COMMAND, MOTOR2_SET, motordata2);
+
+    sleep(3);
+    */
+  }
+
+  return 0;
+}
Index: trunk/code/projects/colonet/lib/colonet_wireless/colonet_wireless.cpp
===================================================================
--- trunk/code/projects/colonet/lib/colonet_wireless/colonet_wireless.cpp	(nonexistent)
+++ trunk/code/projects/colonet/lib/colonet_wireless/colonet_wireless.cpp	(revision 11)
@@ -0,0 +1,626 @@
+/** @file colonet_wireless.cpp 
+ *
+ * @brief Implementation of server-side colonet wireless library
+ *
+ * @author Eugene Marinelli
+ *
+ * @bug Only reads when gtkterm is open
+ * @bug Fails to tokenize
+ * @bug Deconstructor not implemented
+ * @bug Nonsense initializations in constructor
+ */
+
+/********************************* Includes **********************************/
+#include <string>
+#include <pthread.h>
+#include <iostream>
+#include <fstream>
+#include <unistd.h>
+#include <fcntl.h>
+#include "colonet_wireless.h"
+
+/******************************* Definitions *********************************/
+#define TIMEOUT_MAX 100
+#define WL_SEND_DELAY 5 //microseconds
+
+//for debug printouts
+#define DEBUG 1
+
+#ifdef DEBUG
+#define dbg_printf(...) printf(__VA_ARGS__)
+#define dbg_fprintf(...) fprintf(__VA_ARGS__)
+#else
+#define dbg_printf(...)
+#define dbg_fprintf(...)
+#endif
+
+typedef struct {
+  MsgHandlerFunction handler;
+  ColonetWireless* cw;
+} ListenerArgs;
+
+/************************* Internal prototypes *******************************/
+static void* listen(void* args);
+
+/**************************** Public functions *******************************/
+ColonetWireless::ColonetWireless(char* wl_port, 
+                                 MsgHandlerFunction message_handler_, 
+                                 char* log_filename_, bool join_token_ring_,
+                                 bool ignore_token_)
+{
+  have_token = false;
+  first_packet_sent = false;
+
+  //FIX THESE INITIALIZATIONS
+  token_src = 255;
+  token_dest = 255;
+  num_robots = 0;
+  connected = false;
+  ignore_token = ignore_token_;
+
+  sprintf(wireless_port, wl_port);
+
+  if (log_filename) {
+    logging_enabled = true;
+    sprintf(log_filename, log_filename_);
+  }
+
+  join_token_ring = join_token_ring_;
+
+  message_handler = message_handler_;
+}
+
+ColonetWireless::~ColonetWireless()
+{
+  //kill listener thread
+  
+
+  //free packets in queues
+  
+}
+
+int ColonetWireless::handle_packet(ColonetPacket* pkt)
+{
+  if (logging_enabled) {
+    /* Log the packet */
+    log_packet(pkt);
+  }
+
+  /* Update what we know about the network based on the packet */
+  update_network_props(pkt);
+
+  /* Received a message */
+  if (message_handler(pkt) < 0) {
+    fprintf(stderr, "%s: message_handler failed\n", __FUNCTION__);
+    return -1;
+  }
+  
+  if ((unsigned char) pkt->token_dest == WL_ERROR_DEST) {
+    /* token_dest is an error - handle it */
+    if (handle_error(pkt) < 0) {
+      fprintf(stderr, "%s: handle_error failed\n", __FUNCTION__);
+      return -1;
+    }
+  } else if(join_token_ring && !connected) {
+    /* We want to join the token ring but we are not connected - join robot 
+     * network */
+    dbg_printf("%s: Trying to join robot network...\n", __FUNCTION__);
+
+    if (join_network(pkt) < 0) {
+      dbg_fprintf(stderr, "%s: join_network failed\n", __FUNCTION__);
+      return -1;
+    }
+  } else {
+
+    if (pkt->token_dest == token_src && join_token_ring && !ignore_token) {
+      /* Received the token - send queued message(s) */
+      dbg_printf("%s: token received\n", __FUNCTION__);
+
+      have_token = true;
+    
+      if (transmit_queued_message() < 0) {
+        fprintf(stderr, "%s: transmit_queued_message failed\n", __FUNCTION__);
+        return -1;
+      } else {
+        if (!first_packet_sent) {
+          dbg_printf("First packet sent.\n");
+          first_packet_sent = true;
+        }
+      }
+    }
+  }
+
+  return 0;
+}
+
+pthread_t* ColonetWireless::run_listener_thread()
+{
+  // pthread_t listener_thread;
+
+  pthread_t* listener_thread = (pthread_t*)malloc(sizeof(pthread_t));
+
+  dbg_printf("Spawning listener thread...\n");
+
+  ListenerArgs* args = new ListenerArgs;
+  args->cw = this;
+
+  if (pthread_create(listener_thread, NULL, listen, args) != 0) {
+    perror("pthread_create");
+    return NULL;
+  }
+
+  return listener_thread;
+}
+
+int ColonetWireless::send(unsigned char msg_dest, unsigned char msg_type, 
+                          unsigned char msg_code, unsigned char* data)
+{
+  /* Create a new packet it and queue it to be sent */
+  ColonetPacket* newpkt = create_packet(token_src, token_dest, msg_dest, 
+                                        msg_type, msg_code, data, num_robots);
+
+  if(newpkt == NULL){
+    fprintf(stderr, "Error: %s - create_packet failed\n", __FUNCTION__);
+    return -1;
+  }
+
+  if (ignore_token) {
+    send_packet(newpkt);
+  } else {
+    outbox.push(newpkt);                
+  }
+
+  return 0;
+}
+
+void ColonetWireless::clear_message_queue(void)
+{
+  while (!outbox.empty()) {
+    outbox.pop();
+  }
+}
+
+/**************************** Private functions ******************************/
+
+/** @brief Analogous to the "SIGNAL" or "ISR" function on the robots.
+ * Listens for bytes on the wireless port and constructs packets based on them.
+ * Not part of the ColonetWireless class since a function pointer must be
+ * passed in starting the thread that runs it (tricky or impossible if it's 
+ * a class function).
+ *
+ * @param args Pointer to arguments.  Can be safely casted to ListenerArgs type
+ * @return NULL
+ */
+static void* listen(void* args)
+{
+  int read_len;
+  int portfd;
+  unsigned char inbuf[128];
+  int no_packet_timeout_count = 0;
+  ColonetPacket* in_pkt;
+
+  /* Extract arguments from args */
+
+  ColonetWireless* cw = ((ListenerArgs*)args)->cw;
+
+  /* Open connection to wireless port */
+  if((portfd = open(cw->wireless_port, O_RDWR)) < 0){
+    perror("open");
+    pthread_exit(NULL);
+  }
+
+  /* loop waiting for messages */
+  while(1){
+    /* Read in some bytes (blocks until bytes are read) */
+    read_len = read(portfd, inbuf, 3);
+
+    if(read_len > 0){
+      /* Read in some bytes - this will always be true if portfd is blocking */
+      /* parse the packet or part of packet */
+      in_pkt = cw->build_packet(inbuf, read_len);
+      
+      if(in_pkt == NULL){
+        /* Packet is not ready yet - go back and read some more bytes */
+        continue;
+      }else{
+        /* Packet is complete */
+        /* close fd so that we can safely write to it in the handler */
+        close(portfd);
+
+        if (cw->handle_packet(in_pkt)) {
+          fprintf(stderr, "%s: Error - handle_packet failed\n", __FUNCTION__);
+        }
+
+        /* reopen wireless port */
+        if(!(portfd = open(cw->wireless_port, O_RDWR))){
+          perror("open");
+          pthread_exit(NULL);
+        }
+      }
+    }else if(read_len == 0){
+      // Note - this won't actually happen if read blocks
+      if(no_packet_timeout_count++ > TIMEOUT_MAX){
+        //Nothing received for a while - try to start a new token ring
+        dbg_printf("Attempting to start a token ring...\n");
+
+        cw->token_src = 0;
+        cw->token_dest = 1;
+        cw->num_robots = 0;
+  
+        ColonetPacket* tmp_pkt = cw->create_packet(cw->token_src, 
+                                                   cw->token_dest, 0, 0, 0, 
+                                                   (unsigned char*) "",
+                                                   cw->num_robots);
+        cw->send_packet(tmp_pkt);
+        free(tmp_pkt);
+      }
+    }else{ //(read_len < 0)
+      //Error
+      perror("read");
+    }
+  }
+
+  pthread_exit(NULL);
+
+  return NULL;
+}
+
+/** @brief Takes some number of bytes and tries to build a packet with them
+ * State of the function is saved between callings, so parts of packets 
+ * can be provided as available
+ *
+ * @param buf Data buffer 
+ * @param len Number of bytes to build with
+ */
+ColonetPacket* ColonetWireless::build_packet(unsigned char* buf, int len)
+{
+  static unsigned char packet_buf[PACKET_SIZE];
+  static int buf_pos = 0;
+
+  /* If this is pointer is returned - will either point to NULL or a complete
+   * packet */
+  ColonetPacket* complete_packet = NULL;
+
+  if (buf_pos >= PACKET_SIZE) {
+    buf_pos = 0;
+  }
+
+  for (int i = 0; i < len; i++) {
+    dbg_printf("%d ", buf[i]);
+
+    switch(buf_pos){
+    case 0: //prefix0
+      if(buf[i] == 'R'){
+        memset(packet_buf, 0, PACKET_SIZE);
+        packet_buf[0] = 'R';
+        buf_pos = 1;
+      }
+      break;
+    case 1: //prefix1
+      if(buf[i] == 'C'){
+        packet_buf[1] = 'C';
+        buf_pos = 2;
+      }else{
+        buf_pos = 0;
+      }
+      break;
+    default: 
+      /* anything except prefix0, prefix1, or checksum */
+      
+      /* Check for R,C - in this case, very likely that we missed a byte */
+      if (i > 0 && buf[i] == 'C' && buf[i-1] == 'R') {
+        packet_buf[0] = 'R';
+        packet_buf[1] = 'C';
+        
+        buf_pos = 2;
+      } else {
+        packet_buf[buf_pos] = buf[i];
+        buf_pos++;
+      }
+      break;
+    case (PACKET_SIZE-1):
+      /* At checksum location */
+      buf_pos = 0;
+      packet_buf[15] = buf[i];
+
+      /* Compute desired checksum */
+      unsigned char sum = 0;
+      for(int j = 2; j < PACKET_SIZE; j++){
+        sum += packet_buf[j];
+      }
+      
+      if(!sum){
+        //Checksum passed
+        dbg_printf("%s: checksum passed\n", __FUNCTION__);
+
+        complete_packet = create_packet(packet_buf[2], packet_buf[3], 
+                                        packet_buf[4], packet_buf[5], 
+                                        packet_buf[6], (packet_buf+7), 
+                                        packet_buf[PACKET_SIZE-2]);
+      }else{
+        dbg_printf("%s: checksum failed\n", __FUNCTION__);
+      }
+
+      break;
+    }
+  }
+
+  return complete_packet;
+}
+
+void ColonetWireless::update_network_props(ColonetPacket* pkt)
+{
+  if(first_packet_sent && pkt->token_dest == token_dest){
+    /* Another robot is sending to our dest - therefore the network
+     * doesn't know about us yet.  Try to register again. */
+    dbg_printf("Disconnected from network\n");
+    dbg_printf("%s: failed to register in network; trying again...\n", 
+               __FUNCTION__);
+    connected = false;
+
+  }
+
+  if(num_robots < pkt->num_robots){    
+    if(token_dest == 0){
+      /* If we were the last robot, we now point to newly added robot */
+      token_dest = num_robots;
+      dbg_printf("%s: token_dest updated to %d\n", __FUNCTION__, token_dest);
+    }
+
+    num_robots = pkt->num_robots;
+
+    dbg_printf("%s: num_robots updated to %d\n", __FUNCTION__, num_robots);
+  }else if(num_robots > pkt->num_robots && first_packet_sent){
+    /* A robot has left the network... hopefully not us */
+    dbg_printf("%s: number of robots decreased to %d\n", __FUNCTION__, 
+               pkt->num_robots);
+
+    num_robots = pkt->num_robots;
+  }
+}
+
+int ColonetWireless::join_network(ColonetPacket* pkt)
+{
+  dbg_printf("Attempting to join network...\n");
+
+  token_src = pkt->num_robots;
+  token_dest = 0;
+  num_robots = pkt->num_robots+1;
+
+  ColonetPacket* newpkt = create_packet(token_src, token_dest, 0, 0, 0, 
+                                        (unsigned char*)"", num_robots);
+  if(newpkt == NULL){
+    fprintf(stderr, "Error: %s - create_packet failed\n", __FUNCTION__);
+    return -1;
+  }
+
+  dbg_printf("JOIN PACKET:\n"
+             "token_src:%d\n"
+             "token_dest:%d\n"
+             "msg_dest:%d\n"
+             "msg_type:%d\n"
+             "msg_code:%d\n"
+             "num_robots:%d\n",
+             newpkt->token_src, newpkt->token_dest, newpkt->msg_dest, 
+             newpkt->msg_type, newpkt->msg_code, newpkt->num_robots);
+  
+  dbg_printf("data: ");
+
+  for(int i = 0; i < PACKET_DATA_LEN; i++){
+    dbg_printf("%d ", newpkt->data[i]);
+  }
+  dbg_printf("\n");
+
+  send_packet(newpkt);
+
+  connected = true;
+  dbg_printf("Connected to network.\n");
+
+  free(newpkt);
+
+  return 0;
+}
+
+int ColonetWireless::transmit_queued_message()
+{
+  ColonetPacket* top_pkt;
+  int ret;
+
+  if(have_token){
+    top_pkt = outbox.front();
+    if(top_pkt == NULL){
+      dbg_printf("%s: no messages to send -- Passing the token.\n", 
+                 __FUNCTION__);
+      /* If no packets need to be sent, just send a blank packet */
+      top_pkt = create_packet(token_src, token_dest, 0, 0, 0, 
+                              (unsigned char*)"", num_robots);
+    }else{
+      outbox.pop();
+    }
+
+    ret = send_packet(top_pkt);
+    free(top_pkt);
+    if(ret < 0){
+      dbg_fprintf(stderr, "%s: send_packet failed\n", __FUNCTION__);
+      return -1;
+    }
+
+    dbg_printf("%s: packet sent\n", __FUNCTION__);
+
+    have_token = false;
+  }
+
+  return 0;
+}
+
+int ColonetWireless::send_packet(ColonetPacket* pkt)
+{
+  int portfd = open(wireless_port, O_RDWR);
+
+  dbg_printf("\nsend packet: \n");
+
+  if (portfd == 0) {
+    return -1;
+  }
+
+  //write(portfd, (unsigned char*)pkt, 16);
+
+  for (int i = 0; i < PACKET_SIZE; i++) {
+    write(portfd, (unsigned char*)pkt+i, 1);
+    usleep(50); //delay here - robot wireless can't handle full data rate...
+    dbg_fprintf(stderr, "%x ", ((unsigned char*)pkt)[i]);
+  }
+  dbg_printf("\n");
+
+  close(portfd);
+
+  return 0;
+}
+
+unsigned char ColonetWireless::compute_checksum(ColonetPacket* pkt)
+{
+  char checksum = 0;
+
+  checksum -= pkt->token_src;
+  checksum -= pkt->token_dest;
+  checksum -= pkt->msg_dest;
+  checksum -= pkt->msg_type;
+  checksum -= pkt->msg_code;
+
+  for(int i = 0; i < PACKET_DATA_LEN; i++){
+    checksum -= pkt->data[i];
+  }
+
+  checksum -= pkt->num_robots;
+
+  return checksum;
+}
+
+ColonetPacket* ColonetWireless::create_packet(unsigned char token_src_, 
+                                              unsigned char token_dest_,
+                                              unsigned char msg_dest, 
+                                              unsigned char msg_type, 
+                                              unsigned char msg_code, 
+                                              unsigned char* data,
+                                              unsigned char num_robots_)
+{
+  ColonetPacket* dest_packet = new ColonetPacket;
+
+  dest_packet->prefix[0] = 'R';
+  dest_packet->prefix[1] = 'C';
+
+  dest_packet->token_src = token_src_;
+  dest_packet->token_dest = token_dest_;
+    
+  dest_packet->msg_dest = msg_dest;
+  dest_packet->msg_type = msg_type;
+  dest_packet->msg_code = msg_code;
+
+  memset(dest_packet->data, 0, PACKET_DATA_LEN);
+  memcpy(dest_packet->data, (char*)data, PACKET_DATA_LEN);
+
+  dest_packet->num_robots = num_robots_;
+  dest_packet->checksum = compute_checksum(dest_packet);
+
+  //printf("Made this packet: \n");
+  //print_packet(dest_packet);
+
+  return dest_packet;
+}
+
+void ColonetWireless::print_packet(ColonetPacket* pkt)
+{
+  int i;
+
+  printf("Prefix: %c%c\n", pkt->prefix[0], pkt->prefix[1]);
+  printf("Token src: %d\n", pkt->token_src);
+  printf("Token dest: %d\n", pkt->token_dest);
+  printf("Msg dest: %d\n", pkt->msg_dest);
+  printf("Msg type: %d\n", pkt->msg_type);
+  printf("Msg code: %d\n", pkt->msg_code);
+
+  printf("Data: ");
+  for(i = 0; i < PACKET_DATA_LEN; i++){
+    printf("%d ", pkt->data[i]);
+  }
+  printf("\n");
+  
+  printf("Num robots: %d\n", pkt->num_robots);
+  printf("Checksum: %d\n", pkt->checksum);
+}
+
+int ColonetWireless::handle_error(ColonetPacket* pkt)
+{
+  int dead_robot;
+  int errcode = ((char*)pkt)[WL_ERROR_LOC];
+
+  dbg_printf("%s: Handling error %d\n", __FUNCTION__, pkt->token_dest);
+
+  switch(errcode){ //token_dest 
+  case WL_ERRCODE_ROBOTDEATH:
+    dead_robot = ((char*)pkt)[WL_ERR_DEAD_LOC];
+
+    fprintf(stderr, "Dead robot: %d\n", dead_robot);
+    num_robots--;
+    
+    if(token_src > dead_robot){
+      if(token_src == num_robots){
+        token_src--;
+        token_dest = 0;
+      }else{
+        token_src--;
+        token_dest--;
+      }
+    }
+
+    //ensure that the last robot talks to the 0th one
+    //this won't be set if the LAST robot dies (all robots are < dead)
+    if(token_src == num_robots - 1){
+      token_dest = 0;
+    }
+
+    if(token_src == dead_robot){
+      //you took the place of the dead robot
+      //you start the token ring again
+      ColonetPacket* tmp_pkt = create_packet(token_src, token_dest, 0, 0, 0,
+                                             (unsigned char*)"", num_robots);
+      send_packet(tmp_pkt);
+      free(tmp_pkt);
+    }
+    break;
+  case WL_ERRCODE_NEEDTOCHARGE:
+    fprintf(stderr, "Need to charge error received\n");
+    break;
+  case WL_ERRCODE_CHARGESTATION:
+    fprintf(stderr, "Charge station error received\n");
+    break;
+  }
+    
+  return 0;
+}
+
+/** @brief 
+ *
+ * @param pkt Packet to be logged
+ *
+ * @return 0 on success, -1 on failure
+ */
+int ColonetWireless::log_packet(ColonetPacket* pkt)
+{
+  FILE* logfile = fopen(log_filename, "a");
+
+  if (logfile == NULL) {
+    dbg_printf("%s: Error - fopen %s failed.\n", log_filename, __FUNCTION__);
+    return -1;
+  }
+
+  for (int i = 0; i < PACKET_SIZE; i++) {
+    fprintf(logfile, "%d ", *((unsigned char*)pkt+i));
+  }
+
+  fprintf(logfile, "\n");
+
+  fclose(logfile);
+
+  return 0;
+}
Index: trunk/code/projects/colonet/lib/colonet_wireless/colonet_wireless_test2.cpp
===================================================================
--- trunk/code/projects/colonet/lib/colonet_wireless/colonet_wireless_test2.cpp	(nonexistent)
+++ trunk/code/projects/colonet/lib/colonet_wireless/colonet_wireless_test2.cpp	(revision 11)
@@ -0,0 +1,110 @@
+/** @file colonet_wireless_test2.cpp
+ * @brief colonet_wireless_test2 - tests the colonet_wireless library with
+ * manual control.
+ *
+ * @author Eugene Marinelli
+ * @date 2/5/06
+ */
+
+#include <iostream>
+#include <signal.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include "colonet_wireless.h"
+#include "colonet_defs.h"
+
+ColonetWireless* cw;
+
+int msg_handler(ColonetPacket* pkt)
+{
+  printf("Handler!\n");
+  return 0;
+}
+
+char get_mouse()
+{
+  int fd;
+  char buf[10];
+
+  fd = open("/dev/input/mouse0", O_RDONLY);
+
+  read(fd, buf, 1);
+
+  close(fd);
+
+  return buf[0];
+}
+
+void exit_handler(int sig)
+{
+  unsigned char data[10];
+
+  printf("Sending kill packet...\n");
+  cw->send(GLOBAL_DEST, COLONET_COMMAND, MOTORS_OFF, data);
+
+  printf("Exiting...\n");
+
+  sleep(2);
+  exit(0);
+}
+
+int main()
+{
+  unsigned char data[10];
+  char dir;
+  int paused = 0;
+
+  unsigned char motor_back_args[6] = {0, 0, 0, 0xFF, 0};
+  unsigned char motor_forward_args[6] = {0, 1, 0, 0xFF, 0};
+
+  cw = new ColonetWireless(SERIAL_PORT, msg_handler, NULL, true, true);
+
+  signal(SIGINT, exit_handler);
+
+  cw->run_listener_thread();
+
+  while(1){
+    dir = get_mouse();
+
+    usleep(300000);
+
+    printf("%d\n", dir);
+
+    switch (dir) {
+    case 40:
+      /* Forward */
+      cw->send(GLOBAL_DEST, COLONET_COMMAND, MOTOR1_SET, motor_forward_args);
+      cw->send(GLOBAL_DEST, COLONET_COMMAND, MOTOR2_SET, motor_forward_args);
+      break;
+    case 8:
+      /* Back */
+      cw->send(GLOBAL_DEST, COLONET_COMMAND, MOTOR1_SET, motor_back_args);
+      cw->send(GLOBAL_DEST, COLONET_COMMAND, MOTOR2_SET, motor_back_args);
+      break;
+    case 24:
+      /* Left */
+      //cw->send(GLOBAL_DEST, COLONET_COMMAND, MOTORS_OFF, data);
+      cw->send(GLOBAL_DEST, COLONET_COMMAND, MOTOR1_SET, motor_forward_args);
+      break;
+    case 56:
+      /* Right */
+      //cw->send(GLOBAL_DEST, COLONET_COMMAND, MOTORS_OFF, data);
+      cw->send(GLOBAL_DEST, COLONET_COMMAND, MOTOR2_SET, motor_forward_args);
+      break;
+    case 9:
+      /* Left click */
+      /* Stop */
+      cw->clear_message_queue();
+      cw->send(GLOBAL_DEST, COLONET_COMMAND, MOTORS_OFF, data);
+      break;
+    case 10:
+      /* Right click */
+      /* Execute first user-defined function */
+      cw->send(GLOBAL_DEST, COLONET_COMMAND, 0xF0, data);
+      break;
+    }
+  }
+
+  return 0;
+}
Index: trunk/code/projects/colonet/lib/colonet_wireless/colonet_wireless.h
===================================================================
--- trunk/code/projects/colonet/lib/colonet_wireless/colonet_wireless.h	(nonexistent)
+++ trunk/code/projects/colonet/lib/colonet_wireless/colonet_wireless.h	(revision 11)
@@ -0,0 +1,134 @@
+/** @file colonet_wireless.h
+ *
+ * @brief Wireless library for communicating with colony robots
+ * 
+ * @author Eugene Marinelli
+ * @date 10/26/06
+ *
+ * @bug gtkterm must be running for the library to work...
+ */
+
+/* 
+   NOTES
+   Things colonet server must be able to do with wireless:
+   - Send a commmand/request packet to a specific robot
+   - Accept packets from robots - need a "SIGNAL"-like function and a 
+   message queue
+   - Only send stuff when we have the token
+   - Pass token along to the next robot
+   - Join ad-hoc network automatically
+*/
+
+#ifndef COLONET_WIRELESS_H_
+#define COLONET_WIRELESS_H_
+
+#include <queue>
+#include <colonet_defs.h>
+
+using namespace std;
+
+typedef int(*MsgHandlerFunction)(ColonetPacket*);
+/* takes src, msg_type, req_code, data */
+
+class ColonetWireless {
+ public:
+  /** @brief Constructor - creates a new instance of ColonetWireless 
+   * and initializes values
+   * 
+   * @param wl_port Either SERIAL_PORT or USB_PORT (as defined in COLONET_DEFS)
+   * @param log_filename Path to log file - outputs all raw data on the network
+   * If set to NULL, logging is disabled.
+   * @param msg_handler Function to be called when a packet is received.
+   * Must take a ColonetPacket as an argument (see defn of MsgHandlerFunction)
+   * @param join_token_ring true if server should join the token ring,
+   * false if it should just observe the network
+   * 
+   * @return new ColonetWireless object
+   */
+  ColonetWireless(char* wl_port, MsgHandlerFunction message_handler_, 
+                  char* log_filename_, bool join_token_ring_, 
+									bool ignore_token_);
+
+  /**
+   * @brief Deconstructor - frees queue and other stuff
+   */
+  ~ColonetWireless(void);
+
+  /** @brief Spawns a thread which reads data from the hardware interface 
+   * with the colony (either a dongle or a robot programmed to relay data)
+   * and runs msg_handler when a full packet is received
+   *
+   * @return pointer to the thread
+   */
+  pthread_t* run_listener_thread(void);
+
+  /** @brief Adds a message to the message sending queue.  One message in the
+   * queue is sent each time the server receives the token.  Therefore
+   * there might be a delay on the order of seconds before the packet is 
+   * actually sent.
+   *
+   * @param msg_dest ID of the robot message is being sent to.  To send to 
+   * all robots, use GLOBAL_DEST
+   * @param msg_type Type of message being sent.  Should be either 
+   * COLONET_COMMAND or COLONET_REQUEST
+   * @param msg_code The message code/id telling the robot what to do or 
+   * return.  For example this might be ORB_SET
+   * @param data Pointer to a buffer of data to be sent.  Assumed to 
+   * point to valid data.  An invalid pointer will cause a segfault.
+   *
+   * @return -1 on failure, 0 on success
+   */
+  int send(unsigned char msg_dest, unsigned char msg_type, 
+           unsigned char msg_code, unsigned char* data);
+
+  /** @brief Clears the message queue
+   * @return void
+   */
+  void clear_message_queue(void);
+
+  /** @brief Handles a complete packet.
+   *
+   * @param pkt A complete packet to which we should react
+   *
+   * @return 0 on success, -1 on failure
+   */
+  int handle_packet(ColonetPacket* pkt);
+
+  //the rest of these would ideally be private, but must be accessed by 
+  //the listen function
+  ColonetPacket* create_packet(unsigned char token_src_, 
+                               unsigned char token_dest_, 
+                               unsigned char msg_dest, 
+                               unsigned char msg_type, 
+                               unsigned char msg_code, 
+                               unsigned char* data, unsigned char num_robots_);
+  ColonetPacket* build_packet(unsigned char* buf, int len);
+  int send_packet(ColonetPacket* pkt);
+
+  char wireless_port[80];
+  unsigned char token_src; //id of server in token ring
+  unsigned char token_dest; //id of "dest" robot in token ring
+  unsigned char num_robots;
+
+ private:
+  queue<ColonetPacket*> outbox;
+  bool join_token_ring;
+  MsgHandlerFunction message_handler;
+  bool have_token;
+  bool connected; //whether we are connected to the robot
+  bool first_packet_sent;
+  bool logging_enabled;
+	bool ignore_token;
+  char log_filename[80];
+
+  int transmit_queued_message(void);
+  int join_network(ColonetPacket* pkt);
+  void update_network_props(ColonetPacket* pkt);
+  unsigned char compute_checksum(ColonetPacket* pkt);
+  void print_packet(ColonetPacket* pkt);
+
+  int handle_error(ColonetPacket* pkt);
+  int log_packet(ColonetPacket* pkt);
+};
+
+#endif
Index: trunk/code/projects/colonet/lib/colonet_wireless/Makefile
===================================================================
--- trunk/code/projects/colonet/lib/colonet_wireless/Makefile	(nonexistent)
+++ trunk/code/projects/colonet/lib/colonet_wireless/Makefile	(revision 11)
@@ -0,0 +1,27 @@
+# colonet_wireless_test makefile
+
+CC = g++
+CFLAGS = -Wall -Wshadow -Wextra -g
+INCLUDES = ../
+
+all: colonet_wireless_test colonet_wireless_test2
+
+colonet_wireless_test: colonet_wireless_test.o colonet_wireless.o Makefile
+	$(CC) $(CFLAGS) -I ../ -pthread -o colonet_wireless_test colonet_wireless_test.o colonet_wireless.o 
+
+colonet_wireless_test2: colonet_wireless_test2.o colonet_wireless.o Makefile
+	$(CC) $(CFLAGS) -I ../ -pthread -o colonet_wireless_test2 colonet_wireless_test2.o colonet_wireless.o 
+
+colonet_wireless.o: colonet_wireless.cpp colonet_wireless.h
+	$(CC) $(CFLAGS) -I $(INCLUDES) -pthread -c colonet_wireless.cpp
+	ar rc ../libcolonet_wireless.a colonet_wireless.o 
+	ranlib ../libcolonet_wireless.a
+
+colonet_wireless_test.o: colonet_wireless_test.cpp
+	$(CC) $(CFLAGS) -I $(INCLUDES) -pthread -c colonet_wireless_test.cpp
+
+colonet_wireless_test2.o: colonet_wireless_test2.cpp
+	$(CC) $(CFLAGS) -I $(INCLUDES) -pthread -c colonet_wireless_test2.cpp
+
+clean: 
+	rm -rf *o colonet_wireless_test
Index: trunk/code/projects/colonet/lib/colonet_dragonfly/colonet_dragonfly.c
===================================================================
--- trunk/code/projects/colonet/lib/colonet_dragonfly/colonet_dragonfly.c	(nonexistent)
+++ trunk/code/projects/colonet/lib/colonet_dragonfly/colonet_dragonfly.c	(revision 11)
@@ -0,0 +1,297 @@
+/** @file colonet.c
+ * @brief Colonet library for DRAGONFLY colony robots
+ *
+ * @author Eugene Marinelli
+ * @date 4/17/07
+ * 
+ * @bug Handler registration not tested
+ * @bug Request reponding not implemented - only accepts commands.
+ */
+
+#include <dragonfly_lib.h>
+#include "colonet_dragonfly.h"
+
+typedef struct {
+  unsigned char msgId; //is this necessary?
+  void (*handler)(void);
+} UserHandler;
+
+/* Globals (internal) */
+static UserHandler user_handlers[USER_DEFINED_MSG_TOTAL];
+
+/* Internal function prototypes */
+static void packet_string_to_struct(ColonetPacket* dest_pkt, char* pkt_buf);
+static unsigned int two_bytes_to_int(char high, char low);
+
+/* Public functions */
+int colonet_handle_message(unsigned char robot_id, char* pkt_buf)
+{
+  ColonetPacket pkt;
+  unsigned char* args; //up to 7 char args
+  unsigned int int_args[3]; //up to 3 int (2-byte) args
+
+  packet_string_to_struct(&pkt, pkt_buf);
+
+  if(pkt.msg_dest != GLOBAL_DEST && pkt.msg_dest != robot_id){ 
+    //message not intended for us
+    return 1;
+  }
+
+  args = pkt.data;
+  
+  int_args[0] = two_bytes_to_int(args[0], args[1]);
+  int_args[1] = two_bytes_to_int(args[2], args[3]);
+  int_args[2] = two_bytes_to_int(args[4], args[5]);
+
+  if(pkt.msg_type == COLONET_REQUEST){
+    /* TODO - send back data! */
+
+    switch(pkt.msg_code){
+      //Sharp
+    case READ_DISTANCE:
+      break;
+    case LINEARIZE_DISTANCE:
+      break;
+    case LOG_DISTANCE:
+      break;
+
+
+      //Analog
+    case CALL_ANALOG8:
+      break;
+    case CALL_ANALOG10:
+      break;
+    case WHEEL:
+      break;
+    case BATTERY:
+      break;
+
+      //BOM
+    case GETMAXBOM:
+      break;
+
+      //Dio
+    case DIGITAL_INPUT:
+      break;
+    case BUTTON1_READ:
+      break;
+    case BUTTON2_READ:
+      break;
+
+      //Bumper
+    case DETECT_BUMP:
+      break;
+    }
+  }else if(pkt.msg_type == COLONET_COMMAND){
+    if(pkt.msg_code >= USER_DEFINED_MSG_ID_START && 
+       pkt.msg_code <= USER_DEFINED_MSG_ID_END){
+      if (user_handlers[pkt.msg_code - USER_DEFINED_MSG_ID_START].handler) {
+        /* Call the user's handler function if it the function's address
+         * is non-zero (has been set) */
+        user_handlers[pkt.msg_code - USER_DEFINED_MSG_ID_START].handler();
+      }
+
+      return 0;
+    }
+
+    switch(pkt.msg_code){
+    default:
+      printf("%s: Error - message code %d not implemented\n", __FUNCTION__,
+             pkt.msg_code);
+      return -1;
+      break;
+
+      //Buzzer
+    case BUZZER_INIT:
+      buzzer_init();
+      break;
+    case BUZZER_SET_VAL:
+      buzzer_set_val(args[0]);
+      break;
+    case BUZZER_SET_FREQ:
+      buzzer_set_freq(args[0]);
+      break;
+    case BUZZER_CHIRP:
+      buzzer_chirp(int_args[0], int_args[1]);
+      break;
+    case BUZZER_OFF:
+      buzzer_off();
+      break;
+      
+      //LCD
+    case LCD_INIT:
+      lcd_init();
+      break;
+    case LCD_CLEAR_SCREEN:
+      lcd_clear_screen();
+      break;
+    case LCD_PUTBYTE:
+      lcd_putbyte(args[0]);
+      break;
+    case LCD_PUTCHAR:
+      lcd_putchar((char)args[0]);
+      break;
+    case LCD_PUTSTR:
+      lcd_putstr((char*)args);
+      break;
+    case LCD_GOTOXY: 
+      lcd_gotoxy(int_args[0], int_args[1]);
+      break;
+    case LCD_PUTINT: 
+      lcd_putint(int_args[0]);
+      break;
+    case ORB_INIT:
+      orb_init();
+      break;
+      //Orb
+    case ORB_SET:
+      orb_set(args[0], args[1], args[2]);
+      break;
+    case ORB_SET_COLOR:
+      orb_set_color(int_args[0]);
+      break;
+    case ORB_DISABLE:
+      orb_disable();
+      break;
+    case ORB_ENABLE:
+      orb_enable();
+      break;
+    case LED_INIT:
+      break;
+    case LED_USER:
+      break;
+    case ORB_SEND:
+      //orb_send();
+      break;
+      //Motors
+    case MOTORS_INIT:
+      motors_init();
+      break;
+    case MOTOR1_SET:
+      motor1_set(int_args[0], int_args[1]);
+      break;
+    case MOTOR2_SET:
+      motor2_set(int_args[0], int_args[1]);
+      break;
+    case MOTORS_OFF:
+      motors_off();
+      break;
+
+      /*
+    case MOVE:
+      
+      break;
+      */
+
+    case XBEE_INIT:
+      xbee_init();
+      break;
+
+    case XBEE_PUTC:
+      xbee_putc((char)args[0]);
+      break;
+
+    case USB_INIT:
+      usb_init();
+      break;
+
+    case USB_PUTC:
+      usb_putc((char)args[0]);
+      break;
+
+    case PRINTF:
+      printf("%s", pkt.data);
+      break;
+    case KILL_ROBOT:
+      motors_off();
+      buzzer_off();
+      exit(0); //kill the robot
+      break;
+      //Time
+    case DELAY_MS:
+      delay_ms(int_args[0]);
+      break;
+
+      //Analog
+    case ANALOG_INIT:
+      analog_init();
+      break;
+
+      //BOM
+    case BOM_ON:
+      bom_on();
+      break;
+    case BOM_OFF:
+      bom_off();
+      break;
+    case OUTPUT_HIGH:
+      output_high(int_args[0]);
+      break;
+    case OUTPUT_LOW:
+      output_low(int_args[0]);
+      break;
+
+      //Dio
+    case DIGITAL_OUTPUT:
+      digital_output(int_args[0], int_args[1]);
+      break;
+    }
+  }else{
+    printf("%s: Error: Invalid colonet message type", __FUNCTION__);
+    return -1;
+  }
+
+  return 0;
+}
+
+/* colonet_add_message
+ * Adds a user-defined message
+ */
+int colonet_add_message(unsigned char msgId, void (*handler)(void))
+{
+  if(msgId < USER_DEFINED_MSG_ID_START || msgId > USER_DEFINED_MSG_ID_END){
+    return -1;
+  }
+
+  /* Register this function in the array */
+  user_handlers[msgId-USER_DEFINED_MSG_ID_START].msgId = msgId;
+  user_handlers[msgId-USER_DEFINED_MSG_ID_START].handler = handler;
+
+  return 0;
+}
+
+/* Private functions */
+static void packet_string_to_struct(ColonetPacket* dest_pkt, char* pkt_buf)
+{
+  int i;
+  
+  printf("\npacket:");
+  for(i = 0; i < 16; i++){
+    printf("%d ", pkt_buf[i]);
+  }
+
+  printf("\n");
+
+  dest_pkt->prefix[0] = pkt_buf[0];
+  dest_pkt->prefix[1] = pkt_buf[1];
+  dest_pkt->token_src = pkt_buf[2];
+  dest_pkt->token_dest = pkt_buf[3];
+  dest_pkt->msg_dest = pkt_buf[4];
+  dest_pkt->msg_type = pkt_buf[5];
+  dest_pkt->msg_code = pkt_buf[6];
+  
+  for(i = 0; i < PACKET_DATA_LEN; i++){
+    dest_pkt->data[i] = pkt_buf[7+i];
+  }
+
+  dest_pkt->num_robots = pkt_buf[PACKET_SIZE-2];
+  dest_pkt->checksum = pkt_buf[PACKET_SIZE-1];
+}
+
+/* two_bytes_to_int(char a, char b)
+ * Returns int of form [high][low]
+ */
+static unsigned int two_bytes_to_int(char high, char low)
+{
+  return (((unsigned int)high)<<8) + (unsigned int)low;
+}
Index: trunk/code/projects/colonet/lib/colonet_dragonfly/Makefile
===================================================================
--- trunk/code/projects/colonet/lib/colonet_dragonfly/Makefile	(nonexistent)
+++ trunk/code/projects/colonet/lib/colonet_dragonfly/Makefile	(revision 11)
@@ -0,0 +1,21 @@
+# colonet_wireless_test makefile
+MCU = atmega128
+F_CPU = 8000000
+CDEFS = -DF_CPU=$(F_CPU)UL
+
+CC = avr-gcc
+CFLAGS = -Wall -Wshadow -Wextra -g -mmcu=$(MCU)
+INCLUDES = -I../../../xfly_lib -I../
+
+all: colonet_dragonfly.o
+
+#colonet_dragonfly: colonet_dragonfly.o Makefile
+#	$(CC) $(CFLAGS) $(INCLUDES) -o colonet_wireless_test colonet_wireless.o
+
+colonet_dragonfly.o: colonet_dragonfly.c colonet_dragonfly.h
+	$(CC) $(CDEFS) $(CFLAGS) $(INCLUDES) -c colonet_dragonfly.c
+	ar rc ../libcolonet_dragonfly.a colonet_dragonfly.o
+	ranlib ../libcolonet_dragonfly.a
+
+clean: 
+	rm -rf *.o
Index: trunk/code/projects/colonet/lib/colonet_dragonfly/colonet_dragonfly.h
===================================================================
--- trunk/code/projects/colonet/lib/colonet_dragonfly/colonet_dragonfly.h	(nonexistent)
+++ trunk/code/projects/colonet/lib/colonet_dragonfly/colonet_dragonfly.h	(revision 11)
@@ -0,0 +1,34 @@
+/** @file colonet.h
+ * @brief Colonet library for colony robots
+ * @author Eugene Marinelli
+ * @date 10/26/06
+ */
+
+#ifndef COLONET_DRAGONFLY_H_
+#define COLONET_DRAGONFLYH_
+
+#include <colonet_defs.h>
+
+/** @brief Handles colonet packets.  Should be called by parse_buffer 
+ * when it is determined that a colonet message has been received.
+ *
+ * @param robot_id The robot id
+ * @param pkt_buf The packet buffer (e.g. wl_buf)
+ * 
+ * @return -1 on error (invalid msgId), 0 on success
+ */
+int colonet_handle_message(unsigned char robot_id, char* packet);
+
+/** @brief Registers a new colonet message handler function.  If a message
+ * with msgId is received, then handler will be called.
+ * 
+ * @param msgId The message id of the handler to be registered.  Must be
+ * between USER_DEFINED_MSG_ID_START and USER_DEFINED_MSG_ID_END
+ * @param handler The function to be called if a colonet packet with message
+ * id msgId is received
+ * 
+ * @return -1 on error (invalid msgId), 0 on success
+ */
+int colonet_add_message(unsigned char msgId, void (*handler)(void));
+
+#endif
Index: trunk/code/projects/colonet/lib/colonet_defs.h
===================================================================
--- trunk/code/projects/colonet/lib/colonet_defs.h	(nonexistent)
+++ trunk/code/projects/colonet/lib/colonet_defs.h	(revision 11)
@@ -0,0 +1,165 @@
+/* Eugene Marinelli, Fan
+ * 10/27/06
+ *
+ * Colonet Definitions - common definitions and structs used in all colonet 
+ * applications
+ */
+
+#ifndef COLONET_DEFS_H_
+#define COLONET_DEFS_H_
+
+//Message types
+#define COLONET_COMMAND 0x0D
+#define COLONET_REQUEST 0x0E
+#define COLONET_RESPONSE 0x0F
+
+//Packet properties
+#define PACKET_DATA_LEN 7
+#define PACKET_SIZE 16
+
+//Packet error codes
+#define WL_ERRCODE_ROBOTDEATH 123     //For timeouts
+#define WL_ERRCODE_NEEDTOCHARGE 250   //For pinging charging station
+#define WL_ERRCODE_CHARGESTATION 251  //Charging station response to ping
+#define WL_ERR_DEAD_LOC 5
+#define WL_ERROR_DEST 255
+#define WL_ERROR_LOC 4
+
+#define WL_DEFAULT_PAN 3332
+
+typedef struct {
+  unsigned char prefix[2];
+  unsigned char token_src;
+  unsigned char token_dest;
+  unsigned char msg_dest;
+  unsigned char msg_type;
+  unsigned char msg_code;
+  unsigned char data[PACKET_DATA_LEN];
+  unsigned char num_robots;
+  unsigned char checksum;
+} ColonetPacket;
+
+#define SERIAL_PORT "/dev/ttyS0"
+#define USB_PORT "/dev/ttyUSB0"
+
+// Message dests
+#define GLOBAL_DEST 200
+#define MAX_NUM_ROBOTS 7
+#define COLONET_SERVER_RESPONSE_ADDR 201
+
+#define USER_DEFINED_MSG_ID_START 0xF0
+#define USER_DEFINED_MSG_ID_END 0xFF
+#define USER_DEFINED_MSG_TOTAL 0x0F
+
+/* Low level robot commands */
+//BUZZER
+#define BUZZER_INIT 0x00
+#define BUZZER_SET_VAL 0x01
+#define BUZZER_SET_FREQ 0x02
+#define BUZZER_CHIRP 0x03
+#define BUZZER_OFF 0x04
+
+//LCD
+#define LCD_INIT 0x05
+#define LCD_CLEAR_SCREEN 0x06
+#define LCD_PUTBYTE 0x07
+#define LCD_PUTCHAR 0x08
+#define LCD_PUTSTR 0x09
+#define LCD_GOTOXY 0x0A
+#define LCD_PUTINT 0x0B
+
+//ORB
+#define ORB_INIT 0x0C
+#define ORB_SET 0x0D
+#define ORB_SET_COLOR 0x0E
+#define ORB_DISABLE 0x0F
+#define ORB_ENABLE 0x10
+#define ORB_SET_DIO 0x11
+#define LED_INIT 0x12
+#define LED_USER 0x13
+#define ORB_SET_NUM_NS 0x14
+#define ORB_SET_NUM 0x15
+#define ORB_SEND 0x16
+
+//MOTORS
+#define MOTORS_INIT 0x17
+#define MOTOR1_SET 0x18
+#define MOTOR2_SET 0x19
+#define MOTORS_OFF 0x1A
+#define MOVE 0x1B
+#define MOVE_AVOID 0x1C
+
+//SHARP
+#define READ_DISTANCE 0x24
+#define LINEARIZE_DISTANCE 0x25
+#define LOG_DISTANCE 0x26
+#define ENABLE_IR 0x27
+#define DISABLE_IR 0x28
+
+//SERIAL
+#define XBEE_INIT 0x29
+#define XBEE_PUTC 0x2A
+#define XBEE_GETC 0x2B
+
+#define USB_INIT 0x2D
+#define USB_PUTC 0x2E
+#define USB_GETC 0x2F
+
+
+
+//DELAY_MS
+#define DELAY_MS 0x31
+
+//ANALOG
+#define ANALOG_INIT 0x32
+#define SET_ADC_MUX 0x33
+#define ENABLE_ANALOG 0x34
+#define CALL_ANALOG8 0x35
+#define CALL_ANALOG10 0x36
+#define WHEEL 0x37
+#define BATTERY 0x38
+
+//BOM
+#define GETMAXBOM 0x39
+#define BOM_ON 0x3A
+#define BOM_OFF 0x3B
+#define OUTPUT_HIGH 0x3C
+#define OUTPUT_LOW 0x3D
+
+//DIO
+#define DIGITAL_INPUT 0x3E
+#define DIGITAL_OUTPUT 0x3F
+#define BUTTON1_READ 0x41
+#define BUTTON1_WAIT 0x42
+#define BUTTON1_WAIT_LED 0x43
+#define BUTTON2_READ 0x44
+#define BUTTON2_WAIT 0x45
+#define BUTTON2_WAIT_LED 0x46
+
+//WL 
+#define WL_INIT 0x47
+#define PARSE_BUFFER 0x48
+#define WL_SEND 0x49
+
+//BUMPER
+#define DETECT_BUMP 0x50
+
+//Other
+#define PRINTF 0x51
+#define KILL_ROBOT 0x52
+
+
+
+
+/* End low-level robot commands */
+
+
+//Colonet Client commands
+#define MAX_COMMAND_LEN 128
+#define MAX_RESPONSE_LEN 512
+
+#define SEND_TO_ROBOT      0x00
+#define REQUEST_FROM_ROBOT 0x01
+#define RESPONSE_TO_CLIENT_REQUEST 0x02
+
+#endif
Index: trunk/code/projects/colonet/lib/usb_dev_board_drivers/ftdi_sio.c
===================================================================
--- trunk/code/projects/colonet/lib/usb_dev_board_drivers/ftdi_sio.c	(nonexistent)
+++ trunk/code/projects/colonet/lib/usb_dev_board_drivers/ftdi_sio.c	(revision 11)
@@ -0,0 +1,1246 @@
+/*
+ * USB FTDI SIO driver
+ *
+ * 	Copyright (C) 1999 - 2001
+ * 	    Greg Kroah-Hartman (greg@kroah.com)
+ *          Bill Ryder (bryder@sgi.com)
+ *	Copyright (C) 2002
+ *	    Kuba Ober (kuba@mareimbrium.org)
+ *
+ * 	This program is free software; you can redistribute it and/or modify
+ * 	it under the terms of the GNU General Public License as published by
+ * 	the Free Software Foundation; either version 2 of the License, or
+ * 	(at your option) any later version.
+ *
+ * See Documentation/usb/usb-serial.txt for more information on using this driver
+ *
+ * See http://ftdi-usb-sio.sourceforge.net for upto date testing info
+ *	and extra documentation
+ *
+ * (25/Jul/2002) Bill Ryder inserted Dmitri's TIOCMIWAIT patch
+ *      Not tested by me but it doesn't break anything I use.
+ * 
+ * (04/Jan/2002) Kuba Ober
+ *	Implemented 38400 baudrate kludge, where it can be substituted with other
+ *	  values. That's the only way to set custom baudrates.
+ *	Implemented TIOCSSERIAL, TIOCGSERIAL ioctl's so that setserial is happy.
+ *	FIXME: both baudrate things should eventually go to usbserial.c as other
+ *	  devices may need that functionality too. Actually, it can probably be
+ *	  merged in serial.c somehow - too many drivers repeat this code over
+ *	  and over.
+ *	Fixed baudrate forgetfulness - open() used to reset baudrate to 9600 every time.
+ *	Divisors for baudrates are calculated by a macro.
+ *	Small code cleanups. Ugly whitespace changes for Plato's sake only ;-].
+ *
+ * (04/Nov/2001) Bill Ryder
+ *	Fixed bug in read_bulk_callback where incorrect urb buffer was used.
+ *	Cleaned up write offset calculation
+ *	Added write_room since default values can be incorrect for sio
+ *	Changed write_bulk_callback to use same queue_task as other drivers
+ *        (the previous version caused panics)
+ *	Removed port iteration code since the device only has one I/O port and it
+ *	  was wrong anyway.
+ * 
+ * (31/May/2001) gkh
+ *	Switched from using spinlock to a semaphore, which fixes lots of problems.
+ *
+ * (23/May/2001)   Bill Ryder
+ *	Added runtime debug patch (thanx Tyson D Sawyer).
+ *	Cleaned up comments for 8U232
+ *	Added parity, framing and overrun error handling
+ *	Added receive break handling.
+ * 
+ * (04/08/2001) gb
+ *	Identify version on module load.
+ *       
+ * (18/March/2001) Bill Ryder
+ *	(Not released)
+ *	Added send break handling. (requires kernel patch too)
+ *	Fixed 8U232AM hardware RTS/CTS etc status reporting.
+ *	Added flipbuf fix copied from generic device
+ * 
+ * (12/3/2000) Bill Ryder
+ *	Added support for 8U232AM device.
+ *	Moved PID and VIDs into header file only.
+ *	Turned on low-latency for the tty (device will do high baudrates)
+ *	Added shutdown routine to close files when device removed.
+ *	More debug and error message cleanups.
+ *
+ * (11/13/2000) Bill Ryder
+ *	Added spinlock protected open code and close code.
+ *	Multiple opens work (sort of - see webpage mentioned above).
+ *	Cleaned up comments. Removed multiple PID/VID definitions.
+ *	Factorised cts/dtr code
+ *	Made use of __FUNCTION__ in dbg's
+ *      
+ * (11/01/2000) Adam J. Richter
+ *	usb_device_id table support
+ * 
+ * (10/05/2000) gkh
+ *	Fixed bug with urb->dev not being set properly, now that the usb
+ *	core needs it.
+ * 
+ * (09/11/2000) gkh
+ *	Removed DEBUG #ifdefs with call to usb_serial_debug_data
+ *
+ * (07/19/2000) gkh
+ *	Added module_init and module_exit functions to handle the fact that this
+ *	driver is a loadable module now.
+ *
+ * (04/04/2000) Bill Ryder 
+ *	Fixed bugs in TCGET/TCSET ioctls (by removing them - they are
+ *        handled elsewhere in the tty io driver chain).
+ *
+ * (03/30/2000) Bill Ryder 
+ *	Implemented lots of ioctls
+ *	Fixed a race condition in write
+ *	Changed some dbg's to errs
+ *
+ * (03/26/2000) gkh
+ *	Split driver up into device specific pieces.
+ *
+ */
+
+/* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */
+/* Thanx to FTDI for so kindly providing details of the protocol required */
+/*   to talk to the device */
+/* Thanx to gkh and the rest of the usb dev group for all code I have assimilated :-) */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/fcntl.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/usb.h>
+#include <linux/serial.h>
+#ifdef CONFIG_USB_SERIAL_DEBUG
+	static int debug = 1;
+#else
+	static int debug;
+#endif
+
+#include "usb-serial.h"
+#include "ftdi_sio.h"
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.2.1"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>"
+#define DRIVER_DESC "USB FTDI Serial Converters Driver"
+
+static __devinitdata struct usb_device_id id_table_sio [] = {
+	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
+	{ }						/* Terminating entry */
+};
+
+/*
+ * The 8U232AM has the same API as the sio except for:
+ * - it can support MUCH higher baudrates; up to:
+ *   o 921600 for RS232 and 2000000 for RS422/485 at 48MHz
+ *   o 230400 at 12MHz
+ *   so .. 8U232AM's baudrate setting codes are different
+ * - it has a two byte status code.
+ * - it returns characters every 16ms (the FTDI does it every 40ms)
+ */
+
+
+static __devinitdata struct usb_device_id id_table_8U232AM [] = {
+	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
+	{ USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) },
+	{ }						/* Terminating entry */
+};
+
+
+static __devinitdata struct usb_device_id id_table_combined [] = {
+	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
+	{ USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) },
+	{ }						/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, id_table_combined);
+
+struct ftdi_private {
+	ftdi_chip_type_t chip_type;
+				/* type of the device, either SIO or FT8U232AM */
+	int baud_base;		/* baud base clock for divisor setting */
+	int custom_divisor;	/* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */
+	__u16 last_set_data_urb_value ;
+				/* the last data state set - needed for doing a break */
+        int write_offset;       /* This is the offset in the usb data block to write the serial data - 
+				 * it is different between devices
+				 */
+	int flags;		/* some ASYNC_xxxx flags are supported */
+        wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
+ 	char prev_status, diff_status;        /* Used for TIOCMIWAIT */
+};
+
+/* Used for TIOCMIWAIT */
+#define FTDI_STATUS_B0_MASK	(FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD)
+#define FTDI_STATUS_B1_MASK	(FTDI_RS_BI)
+/* End TIOCMIWAIT */
+
+#define FTDI_IMPL_ASYNC_FLAGS = ( ASYNC_SPD_HI | ASYNC_SPD_VHI \
+ ASYNC_SPD_CUST | ASYNC_SPD_SHI | ASYNC_SPD_WARP )
+
+/* function prototypes for a FTDI serial converter */
+static int  ftdi_SIO_startup		(struct usb_serial *serial);
+static int  ftdi_8U232AM_startup	(struct usb_serial *serial);
+static void ftdi_shutdown		(struct usb_serial *serial);
+static int  ftdi_open			(struct usb_serial_port *port, struct file *filp);
+static void ftdi_close			(struct usb_serial_port *port, struct file *filp);
+static int  ftdi_write			(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
+static int  ftdi_write_room		(struct usb_serial_port *port);
+static void ftdi_write_bulk_callback	(struct urb *urb);
+static void ftdi_read_bulk_callback	(struct urb *urb);
+static void ftdi_set_termios		(struct usb_serial_port *port, struct termios * old);
+static int  ftdi_ioctl			(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
+static void ftdi_break_ctl		(struct usb_serial_port *port, int break_state );
+
+static struct usb_serial_device_type ftdi_SIO_device = {
+	name:			"FTDI SIO",
+	id_table:		id_table_sio,
+	needs_interrupt_in:	MUST_HAVE_NOT,
+	needs_bulk_in:		MUST_HAVE,
+	needs_bulk_out:		MUST_HAVE,
+	num_interrupt_in:	0,
+	num_bulk_in:		1,
+	num_bulk_out:		1,
+	num_ports:		1,
+	open:			ftdi_open,
+	close:			ftdi_close,
+	write:			ftdi_write,
+	write_room:		ftdi_write_room,
+	read_bulk_callback:	ftdi_read_bulk_callback,
+	write_bulk_callback:	ftdi_write_bulk_callback,
+	ioctl:			ftdi_ioctl,
+	set_termios:		ftdi_set_termios,
+	break_ctl:		ftdi_break_ctl,
+	startup:		ftdi_SIO_startup,
+        shutdown:               ftdi_shutdown,
+};
+
+static struct usb_serial_device_type ftdi_8U232AM_device = {
+	name:			"FTDI 8U232AM",
+	id_table:		id_table_8U232AM,
+	needs_interrupt_in:	DONT_CARE,
+	needs_bulk_in:		MUST_HAVE,
+	needs_bulk_out:		MUST_HAVE,
+	num_interrupt_in:	0,
+	num_bulk_in:		1,
+	num_bulk_out:		1,
+	num_ports:		1,
+	open:			ftdi_open,
+	close:			ftdi_close,
+	write:			ftdi_write,
+	write_room:		ftdi_write_room,
+	read_bulk_callback:	ftdi_read_bulk_callback,
+	write_bulk_callback:	ftdi_write_bulk_callback,
+	ioctl:			ftdi_ioctl,
+	set_termios:		ftdi_set_termios,
+	break_ctl:		ftdi_break_ctl,
+	startup:		ftdi_8U232AM_startup,
+        shutdown:               ftdi_shutdown,
+};
+
+#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
+
+#define HIGH 1
+#define LOW 0
+
+/*
+ * ***************************************************************************
+ * Utlity functions
+ * ***************************************************************************
+ */
+
+
+static int set_rts(struct usb_device *dev,
+		   unsigned int pipe,
+		   int high_or_low)
+{
+	static char buf[1];
+	unsigned ftdi_high_or_low = (high_or_low? FTDI_SIO_SET_RTS_HIGH : 
+				FTDI_SIO_SET_RTS_LOW);
+	return(usb_control_msg(dev, pipe,
+			       FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
+			       FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
+			       ftdi_high_or_low, 0, 
+			       buf, 0, WDR_TIMEOUT));
+}
+
+
+static int set_dtr(struct usb_device *dev,
+                   unsigned int pipe,
+                   int high_or_low)
+{
+	static char buf[1];
+	unsigned ftdi_high_or_low = (high_or_low? FTDI_SIO_SET_DTR_HIGH : 
+				FTDI_SIO_SET_DTR_LOW);
+	return(usb_control_msg(dev, pipe,
+			       FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
+			       FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
+			       ftdi_high_or_low, 0, 
+			       buf, 0, WDR_TIMEOUT));
+}
+
+
+static __u16 get_ftdi_divisor(struct usb_serial_port * port);
+
+
+static int change_speed(struct usb_serial_port *port)
+{
+	char buf[1];
+        __u16 urb_value;
+
+	urb_value = get_ftdi_divisor(port);
+	
+	return (usb_control_msg(port->serial->dev,
+                          usb_sndctrlpipe(port->serial->dev, 0),
+                          FTDI_SIO_SET_BAUDRATE_REQUEST,
+                          FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE,
+                          urb_value, 0,
+                          buf, 0, 100) < 0);
+}
+
+
+static __u16 get_ftdi_divisor(struct usb_serial_port * port)
+{ /* get_ftdi_divisor */
+	
+	struct ftdi_private * priv = (struct ftdi_private *)port->private;
+	__u16 urb_value = 0;
+	int baud;
+
+	/*
+	 * The logic involved in setting the baudrate can be cleanly split in 3 steps.
+	 * Obtaining the actual baud rate is a little tricky since unix traditionally
+	 * somehow ignored the possibility to set non-standard baud rates.
+	 * 1. Standard baud rates are set in tty->termios->c_cflag
+	 * 2. If these are not enough, you can set any speed using alt_speed as follows:
+	 *    - set tty->termios->c_cflag speed to B38400
+	 *    - set your real speed in tty->alt_speed; it gets ignored when
+	 *      alt_speed==0, (or)
+	 *    - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows:
+	 *      flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP], this just
+	 *      sets alt_speed to (HI: 57600, VHI: 115200, SHI: 230400, WARP: 460800)
+	 * ** Steps 1, 2 are done courtesy of tty_get_baud_rate
+	 * 3. You can also set baud rate by setting custom divisor as follows
+	 *    - set tty->termios->c_cflag speed to B38400
+	 *    - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows:
+	 *      o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST
+	 *      o custom_divisor set to baud_base / your_new_baudrate
+	 * ** Step 3 is done courtesy of code borrowed from serial.c - I should really
+	 *    spend some time and separate+move this common code to serial.c, it is
+	 *    replicated in nearly every serial driver you see.
+	 */
+
+	/* 1. Get the baud rate from the tty settings, this observes alt_speed hack */
+
+	baud = tty_get_baud_rate(port->tty);
+	dbg(__FUNCTION__ " tty_get_baud_rate reports speed %d", baud);
+
+	/* 2. Observe async-compatible custom_divisor hack, update baudrate if needed */
+
+	if (baud == 38400 &&
+	    ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
+	     (priv->custom_divisor)) {
+		baud = priv->baud_base / priv->custom_divisor;
+		dbg(__FUNCTION__ " custom divisor %d sets baud rate to %d", priv->custom_divisor, baud);
+	}
+
+	/* 3. Convert baudrate to device-specific divisor */
+
+	if (!baud) baud = 9600;	
+	switch(priv->chip_type) {
+	case SIO: /* SIO chip */
+		switch(baud) {
+		case 300: urb_value = ftdi_sio_b300; break;
+		case 600: urb_value = ftdi_sio_b600; break;
+		case 1200: urb_value = ftdi_sio_b1200; break;
+		case 2400: urb_value = ftdi_sio_b2400; break;
+		case 4800: urb_value = ftdi_sio_b4800; break;
+		case 9600: urb_value = ftdi_sio_b9600; break;
+		case 19200: urb_value = ftdi_sio_b19200; break;
+		case 38400: urb_value = ftdi_sio_b38400; break;
+		case 57600: urb_value = ftdi_sio_b57600;  break;
+		case 115200: urb_value = ftdi_sio_b115200; break;
+		} /* baud */
+		if (urb_value == 0)
+			dbg(__FUNCTION__ " Baudrate (%d) requested is not supported", baud);
+		break;
+	case FT8U232AM: /* 8U232AM chip */
+		if (baud <= 3000000) {
+			urb_value = FTDI_SIO_BAUD_TO_DIVISOR(baud);
+		} else {
+	                dbg(__FUNCTION__ " Baud rate too high!");
+		}
+		break;
+	} /* priv->chip_type */
+
+	if (urb_value == 0) {
+		urb_value = ftdi_sio_b9600;
+	} else {
+		dbg(__FUNCTION__ " Baud rate set to %d (divisor %d) on chip %s", baud, urb_value, (priv->chip_type == SIO) ? "SIO" : "FT8U232AM" );
+	}
+
+	return(urb_value);
+}
+
+
+static int get_serial_info(struct usb_serial_port * port, struct serial_struct * retinfo)
+{
+	struct ftdi_private * priv = (struct ftdi_private*) port->private;
+	struct serial_struct tmp;
+
+	if (!retinfo)
+		return -EFAULT;
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.flags = priv->flags;
+	tmp.baud_base = priv->baud_base;
+	tmp.custom_divisor = priv->custom_divisor;
+	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+		return -EFAULT;
+	return 0;
+} /* get_serial_info */
+
+
+static int set_serial_info(struct usb_serial_port * port, struct serial_struct * newinfo)
+{ /* set_serial_info */
+	struct ftdi_private * priv = (struct ftdi_private *) port->private;
+	struct serial_struct new_serial;
+	struct ftdi_private old_priv;
+
+	if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
+		return -EFAULT;
+	old_priv = * priv;
+
+	/* Do error checking and permission checking */
+
+	if (!capable(CAP_SYS_ADMIN)) {
+		if (((new_serial.flags & ~ASYNC_USR_MASK) !=
+		     (priv->flags & ~ASYNC_USR_MASK)))
+			return -EPERM;
+		priv->flags = ((priv->flags & ~ASYNC_USR_MASK) |
+			       (new_serial.flags & ASYNC_USR_MASK));
+		priv->custom_divisor = new_serial.custom_divisor;
+		goto check_and_exit;
+	}
+
+	if ((new_serial.baud_base != priv->baud_base) ||
+	    (new_serial.baud_base < 9600))
+		return -EINVAL;
+
+	/* Make the changes - these are privileged changes! */
+
+	priv->flags = ((priv->flags & ~ASYNC_FLAGS) |
+	               (new_serial.flags & ASYNC_FLAGS));	
+	priv->custom_divisor = new_serial.custom_divisor;
+
+	port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+check_and_exit:
+	if (((old_priv.flags & ASYNC_SPD_MASK) !=
+	     (priv->flags & ASYNC_SPD_MASK)) ||
+	    (old_priv.custom_divisor != priv->custom_divisor)) {
+		if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+			port->tty->alt_speed = 57600;
+		if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+			port->tty->alt_speed = 115200;
+		if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+			port->tty->alt_speed = 230400;
+		if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+			port->tty->alt_speed = 460800;
+		change_speed(port);
+	}
+	
+	return (0);
+
+} /* set_serial_info */
+
+/*
+ * ***************************************************************************
+ * FTDI driver specific functions
+ * ***************************************************************************
+ */
+
+/* Startup for the SIO chip */
+static int ftdi_SIO_startup (struct usb_serial *serial)
+{
+	struct ftdi_private *priv;
+
+	priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL);
+	if (!priv){
+		err(__FUNCTION__"- kmalloc(%Zd) failed.", sizeof(struct ftdi_private));
+		return -ENOMEM;
+	}
+
+	priv->chip_type = SIO;
+	priv->baud_base = 12000000 / 16;
+	priv->custom_divisor = 0;
+	priv->write_offset = 1;
+ 	priv->prev_status = priv->diff_status = 0;
+	/* This will push the characters through immediately rather
+	   than queue a task to deliver them */
+	priv->flags = ASYNC_LOW_LATENCY;
+	
+	return (0);
+}
+
+/* Startup for the 8U232AM chip */
+static int ftdi_8U232AM_startup (struct usb_serial *serial)
+{
+	struct ftdi_private *priv;
+
+	priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL);
+	if (!priv){
+		err(__FUNCTION__"- kmalloc(%Zd) failed.", sizeof(struct ftdi_private));
+		return -ENOMEM;
+	}
+
+	priv->chip_type = FT8U232AM;
+	priv->baud_base = 48000000 / 2; /* Would be / 16, but FTDI supports 0.125, 0.25 and 0.5 divisor fractions! */
+	priv->custom_divisor = 0;
+	priv->write_offset = 0;
+        init_waitqueue_head(&priv->delta_msr_wait);
+	/* This will push the characters through immediately rather
+	   than queue a task to deliver them */
+	priv->flags = ASYNC_LOW_LATENCY;
+	
+	return (0);
+}
+
+
+static void ftdi_shutdown (struct usb_serial *serial)
+{
+	dbg (__FUNCTION__);
+
+	/* stop reads and writes on all ports */
+	while (serial->port[0].open_count > 0) {
+	        ftdi_close (&serial->port[0], NULL);
+	}
+	if (serial->port[0].private){
+		kfree(serial->port[0].private);
+		serial->port[0].private = NULL;
+	}
+}
+
+
+static int  ftdi_open (struct usb_serial_port *port, struct file *filp)
+{ /* ftdi_open */
+	struct termios tmp_termios;
+	struct usb_serial *serial = port->serial;
+	struct ftdi_private *priv = port->private;
+	
+	int result = 0;
+	char buf[1]; /* Needed for the usb_control_msg I think */
+
+	dbg(__FUNCTION__);
+
+	down (&port->sem);
+	
+	MOD_INC_USE_COUNT;
+	++port->open_count;
+
+	if (!port->active){
+		port->active = 1;
+
+		port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+		/* No error checking for this (will get errors later anyway) */
+		/* See ftdi_sio.h for description of what is reset */
+		usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+				FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, 
+				FTDI_SIO_RESET_SIO, 
+				0, buf, 0, WDR_TIMEOUT);
+
+		/* Termios defaults are set by usb_serial_init. We don't change
+		   port->tty->termios - this would loose speed settings, etc.
+		   This is same behaviour as serial.c/rs_open() - Kuba */
+
+		/* ftdi_set_termios  will send usb control messages */
+		ftdi_set_termios(port, &tmp_termios);
+
+		/* FIXME: Flow control might be enabled, so it should be checked -
+		   we have no control of defaults! */
+		/* Turn on RTS and DTR since we are not flow controlling by default */
+		if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0) {
+			err(__FUNCTION__ " Error from DTR HIGH urb");
+		}
+		if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0){
+			err(__FUNCTION__ " Error from RTS HIGH urb");
+		}
+	
+		/* Start reading from the device */
+		FILL_BULK_URB(port->read_urb, serial->dev, 
+			      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+			      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
+			      ftdi_read_bulk_callback, port);
+		result = usb_submit_urb(port->read_urb);
+		if (result)
+			err(__FUNCTION__ " - failed submitting read urb, error %d", result);
+	}
+
+	up (&port->sem);
+	return result;
+} /* ftdi_open */
+
+
+static void ftdi_close (struct usb_serial_port *port, struct file *filp)
+{ /* ftdi_close */
+	struct usb_serial *serial = port->serial; /* Checked in usbserial.c */
+	unsigned int c_cflag = port->tty->termios->c_cflag;
+	char buf[1];
+
+	dbg( __FUNCTION__);
+
+	down (&port->sem);
+	--port->open_count;
+
+	if (port->open_count <= 0) {
+		if (serial->dev) {
+			if (c_cflag & HUPCL){
+				/* Disable flow control */
+				if (usb_control_msg(serial->dev, 
+						    usb_sndctrlpipe(serial->dev, 0),
+						    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
+						    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
+						    0, 0, buf, 0, WDR_TIMEOUT) < 0) {
+					err("error from flowcontrol urb");
+				}	    
+
+				/* drop DTR */
+				if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0), LOW) < 0){
+					err("Error from DTR LOW urb");
+				}
+				/* drop RTS */
+				if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0) {
+					err("Error from RTS LOW urb");
+				}	
+			} /* Note change no line is hupcl is off */
+
+			/* shutdown our bulk reads and writes */
+			/* ***CHECK*** behaviour when there is nothing queued */
+			usb_unlink_urb (port->write_urb);
+			usb_unlink_urb (port->read_urb);
+		}
+		port->active = 0;
+		port->open_count = 0;
+	} else {  
+		/* Send a HUP if necessary */
+		if (!(port->tty->termios->c_cflag & CLOCAL)){
+			tty_hangup(port->tty);
+		}
+	}
+
+	up (&port->sem);
+	MOD_DEC_USE_COUNT;
+
+} /* ftdi_close */
+
+
+  
+/* The ftdi_sio requires the first byte to have:
+ *  B0 1
+ *  B1 0
+ *  B2..7 length of message excluding byte 0
+ */
+static int ftdi_write (struct usb_serial_port *port, int from_user,
+			   const unsigned char *buf, int count)
+{ /* ftdi_write */
+	struct usb_serial *serial = port->serial;
+	struct ftdi_private *priv = (struct ftdi_private *)port->private;
+	unsigned char *first_byte = port->write_urb->transfer_buffer;
+	int data_offset ;
+	int result;
+	
+	dbg(__FUNCTION__ " port %d, %d bytes", port->number, count);
+
+	if (count == 0) {
+		err("write request of 0 bytes");
+		return 0;
+	}
+	
+	data_offset = priv->write_offset;
+        dbg("data_offset set to %d",data_offset);
+
+	if (port->write_urb->status == -EINPROGRESS) {
+		dbg (__FUNCTION__ " - already writing");
+		return (0);
+	}		
+
+	down(&port->sem);
+
+	count += data_offset;
+	count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+
+	/* Copy in the data to send */
+	if (from_user) {
+		if (copy_from_user((char *)port->write_urb->transfer_buffer + data_offset,
+				   buf, count - data_offset )){
+			up (&port->sem);
+			return -EFAULT;
+		}
+	} else {
+		memcpy((char *)port->write_urb->transfer_buffer + data_offset,
+		       buf, count - data_offset );
+	}  
+
+	first_byte = port->write_urb->transfer_buffer;
+	if (data_offset > 0){
+		/* Write the control byte at the front of the packet*/
+		*first_byte = 1 | ((count-data_offset) << 2) ; 
+	}
+
+	dbg(__FUNCTION__ " Bytes: %d, First Byte: 0x%02x",count, first_byte[0]);
+	usb_serial_debug_data (__FILE__, __FUNCTION__, count, first_byte);
+		
+	/* send the data out the bulk port */
+	FILL_BULK_URB(port->write_urb, serial->dev, 
+		      usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
+		      port->write_urb->transfer_buffer, count,
+		      ftdi_write_bulk_callback, port);
+		
+	result = usb_submit_urb(port->write_urb);
+	if (result) {
+		err(__FUNCTION__ " - failed submitting write urb, error %d", result);
+		up (&port->sem);
+		return 0;
+	}
+	up (&port->sem);
+
+	dbg(__FUNCTION__ " write returning: %d", count - data_offset);
+	return (count - data_offset);
+
+} /* ftdi_write */
+
+
+static void ftdi_write_bulk_callback (struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	struct usb_serial *serial;
+
+	dbg(__FUNCTION__);
+
+	if (port_paranoia_check (port, "ftdi_write_bulk_callback")) {
+		return;
+	}
+	
+	serial = port->serial;
+	if (serial_paranoia_check (serial, "ftdi_write_bulk_callback")) {
+		return;
+	}
+	
+	if (urb->status) {
+		dbg("nonzero write bulk status received: %d", urb->status);
+		return;
+	}
+	queue_task(&port->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+
+	return;
+} /* ftdi_write_bulk_callback */
+
+
+static int ftdi_write_room( struct usb_serial_port *port )
+{
+	struct ftdi_private *priv = (struct ftdi_private *)port->private;
+	int room;
+
+	if ( port->write_urb->status == -EINPROGRESS) {
+		/* There is a race here with the _write routines but it won't hurt */
+		room = 0;
+	} else { 
+		room = port->bulk_out_size - priv->write_offset;
+	}
+	return(room);
+} /* ftdi_write_room */
+
+
+static void ftdi_read_bulk_callback (struct urb *urb)
+{ /* ftdi_read_bulk_callback */
+	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	struct usb_serial *serial;
+       	struct tty_struct *tty = port->tty ;
+	struct ftdi_private *priv = (struct ftdi_private *) port->private;
+	char error_flag;
+       	unsigned char *data = urb->transfer_buffer;
+
+	const int data_offset = 2;
+	int i;
+	int result;
+
+	dbg(__FUNCTION__ " - port %d", port->number);
+
+	if (port_paranoia_check (port, "ftdi_sio_read_bulk_callback")) {
+		return;
+	}
+
+	serial = port->serial;
+	if (serial_paranoia_check (serial, "ftdi_sio_read_bulk_callback")) {
+		return;
+	}
+
+	if (urb->status) {
+		/* This will happen at close every time so it is a dbg not an err */
+		dbg("nonzero read bulk status received: %d", urb->status);
+		return;
+	}
+
+	if (urb->actual_length > 2) {
+		usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
+	} else {
+                dbg("Just status 0o%03o0o%03o",data[0],data[1]);
+        }
+
+
+	/* TO DO -- check for hung up line and handle appropriately: */
+	/*   send hangup  */
+	/* See acm.c - you do a tty_hangup  - eg tty_hangup(tty) */
+	/* if CD is dropped and the line is not CLOCAL then we should hangup */
+
+	/* Compare new line status to the old one, signal if different */
+	if (priv != NULL) {
+		char new_status = data[0] & FTDI_STATUS_B0_MASK;
+		if (new_status != priv->prev_status) {
+			priv->diff_status |= new_status ^ priv->prev_status;
+			wake_up_interruptible(&priv->delta_msr_wait);
+			priv->prev_status = new_status;
+		}
+	}
+
+	/* Handle errors and break */
+	error_flag = TTY_NORMAL;
+        /* Although the device uses a bitmask and hence can have multiple */
+        /* errors on a packet - the order here sets the priority the */
+        /* error is returned to the tty layer  */
+	
+	if ( data[1] & FTDI_RS_OE ) { 
+		error_flag = TTY_OVERRUN;
+                dbg("OVERRRUN error");
+	}
+	if ( data[1] & FTDI_RS_BI ) { 
+		error_flag = TTY_BREAK;
+                dbg("BREAK received");
+	}
+	if ( data[1] & FTDI_RS_PE ) { 
+		error_flag = TTY_PARITY;
+                dbg("PARITY error");
+	}
+	if ( data[1] & FTDI_RS_FE ) { 
+		error_flag = TTY_FRAME;
+                dbg("FRAMING error");
+	}
+	if (urb->actual_length > data_offset) {
+
+		for (i = data_offset ; i < urb->actual_length ; ++i) {
+			/* have to make sure we don't overflow the buffer
+			  with tty_insert_flip_char's */
+			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+				tty_flip_buffer_push(tty);
+			}
+			/* Note that the error flag is duplicated for 
+			   every character received since we don't know
+			   which character it applied to */
+			tty_insert_flip_char(tty, data[i], error_flag);
+		}
+	  	tty_flip_buffer_push(tty);
+
+
+	} 
+
+#ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW
+	/* if a parity error is detected you get status packets forever
+	   until a character is sent without a parity error.
+	   This doesn't work well since the application receives a never
+	   ending stream of bad data - even though new data hasn't been sent.
+	   Therefore I (bill) have taken this out.
+	   However - this might make sense for framing errors and so on 
+	   so I am leaving the code in for now.
+	*/
+      else {
+		if (error_flag != TTY_NORMAL){
+			dbg("error_flag is not normal");
+				/* In this case it is just status - if that is an error send a bad character */
+				if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+					tty_flip_buffer_push(tty);
+				}
+				tty_insert_flip_char(tty, 0xff, error_flag);
+				tty_flip_buffer_push(tty);
+		}
+	}
+#endif
+
+	/* Continue trying to always read  */
+	FILL_BULK_URB(port->read_urb, serial->dev, 
+		      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+		      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
+		      ftdi_read_bulk_callback, port);
+
+	result = usb_submit_urb(port->read_urb);
+	if (result)
+		err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
+
+	return;
+} /* ftdi_read_bulk_callback */
+
+
+static void ftdi_break_ctl( struct usb_serial_port *port, int break_state )
+{
+	struct usb_serial *serial = port->serial;
+	struct ftdi_private *priv = (struct ftdi_private *)port->private;
+	__u16 urb_value = 0; 
+	char buf[1];
+	
+	/* break_state = -1 to turn on break, and 0 to turn off break */
+	/* see drivers/char/tty_io.c to see it used */
+	/* last_set_data_urb_value NEVER has the break bit set in it */
+
+	if (break_state) {
+		urb_value = priv->last_set_data_urb_value | FTDI_SIO_SET_BREAK;
+	} else {
+		urb_value = priv->last_set_data_urb_value; 
+	}
+
+	
+	if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			    FTDI_SIO_SET_DATA_REQUEST, 
+			    FTDI_SIO_SET_DATA_REQUEST_TYPE,
+			    urb_value , 0,
+			    buf, 0, WDR_TIMEOUT) < 0) {
+		err(__FUNCTION__ " FAILED to enable/disable break state (state was %d)",break_state);
+	}	   
+
+	dbg(__FUNCTION__ " break state is %d - urb is %d",break_state, urb_value);
+	
+}
+
+
+/* old_termios contains the original termios settings and tty->termios contains
+ * the new setting to be used
+ * WARNING: set_termios calls this with old_termios in kernel space
+ */
+
+static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+{ /* ftdi_termios */
+	struct usb_serial *serial = port->serial;
+	unsigned int cflag = port->tty->termios->c_cflag;
+	struct ftdi_private *priv = (struct ftdi_private *)port->private;	
+	__u16 urb_value; /* will hold the new flags */
+	char buf[1]; /* Perhaps I should dynamically alloc this? */
+	
+	
+	dbg(__FUNCTION__);
+
+
+	/* FIXME -For this cut I don't care if the line is really changing or 
+	   not  - so just do the change regardless  - should be able to 
+	   compare old_termios and tty->termios */
+	/* NOTE These routines can get interrupted by 
+	   ftdi_sio_read_bulk_callback  - need to examine what this 
+           means - don't see any problems yet */
+	
+	/* Set number of data bits, parity, stop bits */
+	
+	urb_value = 0;
+	urb_value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 :
+		      FTDI_SIO_SET_DATA_STOP_BITS_1);
+	urb_value |= (cflag & PARENB ? 
+		      (cflag & PARODD ? FTDI_SIO_SET_DATA_PARITY_ODD : 
+		       FTDI_SIO_SET_DATA_PARITY_EVEN) :
+		      FTDI_SIO_SET_DATA_PARITY_NONE);
+	if (cflag & CSIZE) {
+		switch (cflag & CSIZE) {
+		case CS5: urb_value |= 5; dbg("Setting CS5"); break;
+		case CS6: urb_value |= 6; dbg("Setting CS6"); break;
+		case CS7: urb_value |= 7; dbg("Setting CS7"); break;
+		case CS8: urb_value |= 8; dbg("Setting CS8"); break;
+		default:
+			err("CSIZE was set but not CS5-CS8");
+		}
+	}
+
+	/* This is needed by the break command since it uses the same command - but is
+	 *  or'ed with this value  */
+	priv->last_set_data_urb_value = urb_value;
+	
+	if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			    FTDI_SIO_SET_DATA_REQUEST, 
+			    FTDI_SIO_SET_DATA_REQUEST_TYPE,
+			    urb_value , 0,
+			    buf, 0, 100) < 0) {
+		err(__FUNCTION__ " FAILED to set databits/stopbits/parity");
+	}	   
+
+	/* Now do the baudrate */
+	if ((cflag & CBAUD) == B0 ) {
+		/* Disable flow control */
+		if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+				    FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
+				    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
+				    0, 0, 
+				    buf, 0, WDR_TIMEOUT) < 0) {
+			err(__FUNCTION__ " error from disable flowcontrol urb");
+		}	    
+		/* Drop RTS and DTR */
+		if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0){
+			err(__FUNCTION__ " Error from DTR LOW urb");
+		}
+		if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0){
+			err(__FUNCTION__ " Error from RTS LOW urb");
+		}	
+		
+	} else {
+		/* set the baudrate determined before */
+		if (change_speed(port)) {
+			err(__FUNCTION__ " urb failed to set baurdrate");
+		}
+	}
+
+	/* Set flow control */
+	/* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */
+	if (cflag & CRTSCTS) {
+		dbg(__FUNCTION__ " Setting to CRTSCTS flow control");
+		if (usb_control_msg(serial->dev, 
+				    usb_sndctrlpipe(serial->dev, 0),
+				    FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
+				    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
+				    0 , FTDI_SIO_RTS_CTS_HS,
+				    buf, 0, WDR_TIMEOUT) < 0) {
+			err("urb failed to set to rts/cts flow control");
+		}		
+		
+	} else { 
+		/* CHECKME Assuming XON/XOFF handled by tty stack - not by device */
+		dbg(__FUNCTION__ " Turning off hardware flow control");
+		if (usb_control_msg(serial->dev, 
+				    usb_sndctrlpipe(serial->dev, 0),
+				    FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
+				    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
+				    0, 0, 
+				    buf, 0, WDR_TIMEOUT) < 0) {
+			err("urb failed to clear flow control");
+		}				
+		
+	}
+	return;
+} /* ftdi_termios */
+
+
+static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+{
+	struct usb_serial *serial = port->serial;
+	struct ftdi_private *priv = (struct ftdi_private *)port->private;
+
+	__u16 urb_value=0; /* Will hold the new flags */
+	char buf[2];
+	int  ret, mask;
+	
+	dbg(__FUNCTION__ " cmd 0x%04x", cmd);
+
+	/* Based on code from acm.c and others */
+	switch (cmd) {
+
+	case TIOCMGET:
+		dbg(__FUNCTION__ " TIOCMGET");
+		switch (priv->chip_type) {
+		case SIO:
+			/* Request the status from the device */
+			if ((ret = usb_control_msg(serial->dev, 
+						   usb_rcvctrlpipe(serial->dev, 0),
+						   FTDI_SIO_GET_MODEM_STATUS_REQUEST, 
+						   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+						   0, 0, 
+						   buf, 1, WDR_TIMEOUT)) < 0 ) {
+				err(__FUNCTION__ " Could not get modem status of device - err: %d",
+				    ret);
+				return(ret);
+			}
+			break;
+		case FT8U232AM:
+			/* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same
+			   format as the data returned from the in point */
+			if ((ret = usb_control_msg(serial->dev, 
+						   usb_rcvctrlpipe(serial->dev, 0),
+						   FTDI_SIO_GET_MODEM_STATUS_REQUEST, 
+						   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+						   0, 0, 
+						   buf, 2, WDR_TIMEOUT)) < 0 ) {
+				err(__FUNCTION__ " Could not get modem status of device - err: %d",
+				    ret);
+				return(ret);
+			}
+			break;
+		default:
+			return -EFAULT;
+			break;
+		}
+
+		return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
+				(buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
+				(buf[0]  & FTDI_SIO_RI_MASK  ? TIOCM_RI  : 0) |
+				(buf[0]  & FTDI_SIO_RLSD_MASK ? TIOCM_CD  : 0),
+				(unsigned long *) arg);
+		break;
+
+	case TIOCMSET: /* Turns on and off the lines as specified by the mask */
+		dbg(__FUNCTION__ " TIOCMSET");
+		if (get_user(mask, (unsigned long *) arg))
+			return -EFAULT;
+		urb_value = ((mask & TIOCM_DTR) ? HIGH : LOW);
+		if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),urb_value) < 0){
+			err("Error from DTR set urb (TIOCMSET)");
+		}
+		urb_value = ((mask & TIOCM_RTS) ? HIGH : LOW);
+		if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),urb_value) < 0){
+			err("Error from RTS set urb (TIOCMSET)");
+		}	
+		break;
+					
+	case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
+		dbg(__FUNCTION__ " TIOCMBIS");
+ 	        if (get_user(mask, (unsigned long *) arg))
+			return -EFAULT;
+  	        if (mask & TIOCM_DTR){
+			if ((ret = set_dtr(serial->dev, 
+					   usb_sndctrlpipe(serial->dev, 0),
+					   HIGH)) < 0) {
+				err("Urb to set DTR failed");
+				return(ret);
+			}
+		}
+		if (mask & TIOCM_RTS) {
+			if ((ret = set_rts(serial->dev, 
+					   usb_sndctrlpipe(serial->dev, 0),
+					   HIGH)) < 0){
+				err("Urb to set RTS failed");
+				return(ret);
+			}
+		}
+					break;
+
+	case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
+		dbg(__FUNCTION__ " TIOCMBIC");
+ 	        if (get_user(mask, (unsigned long *) arg))
+			return -EFAULT;
+  	        if (mask & TIOCM_DTR){
+			if ((ret = set_dtr(serial->dev, 
+					   usb_sndctrlpipe(serial->dev, 0),
+					   LOW)) < 0){
+				err("Urb to unset DTR failed");
+				return(ret);
+			}
+		}	
+		if (mask & TIOCM_RTS) {
+			if ((ret = set_rts(serial->dev, 
+					   usb_sndctrlpipe(serial->dev, 0),
+					   LOW)) < 0){
+				err("Urb to unset RTS failed");
+				return(ret);
+			}
+		}
+		break;
+
+		/*
+		 * I had originally implemented TCSET{A,S}{,F,W} and
+		 * TCGET{A,S} here separately, however when testing I
+		 * found that the higher layers actually do the termios
+		 * conversions themselves and pass the call onto
+		 * ftdi_sio_set_termios. 
+		 *
+		 */
+
+	case TIOCGSERIAL: /* gets serial port data */
+		return get_serial_info(port, (struct serial_struct *) arg);
+
+	case TIOCSSERIAL: /* sets serial port data */
+		return set_serial_info(port, (struct serial_struct *) arg);
+
+	/*
+	 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+	 * - mask passed in arg for lines of interest
+	 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+	 * Caller should use TIOCGICOUNT to see which one it was.
+	 *
+	 * This code is borrowed from linux/drivers/char/serial.c
+	 */
+	case TIOCMIWAIT:
+		while (priv != NULL) {
+			interruptible_sleep_on(&priv->delta_msr_wait);
+			/* see if a signal did it */
+			if (signal_pending(current))
+				return -ERESTARTSYS;
+			else {
+				char diff = priv->diff_status;
+
+				if (diff == 0) {
+					return -EIO; /* no change => error */
+				}
+
+				/* Consume all events */
+				priv->diff_status = 0;
+
+				/* Return 0 if caller wanted to know about these bits */
+				if ( ((arg & TIOCM_RNG) && (diff & FTDI_RS0_RI)) ||
+				     ((arg & TIOCM_DSR) && (diff & FTDI_RS0_DSR)) ||
+				     ((arg & TIOCM_CD)  && (diff & FTDI_RS0_RLSD)) ||
+				     ((arg & TIOCM_CTS) && (diff & FTDI_RS0_CTS)) ) {
+					return 0;
+				}
+				/*
+				 * Otherwise caller can't care less about what happened,
+				 * and so we continue to wait for more events.
+				 */
+			}
+		}
+		/* NOTREACHED */
+
+	default:
+	  /* This is not an error - turns out the higher layers will do 
+	   *  some ioctls itself (see comment above)
+ 	   */
+		dbg(__FUNCTION__ " arg not supported - it was 0x%04x",cmd);
+		return(-ENOIOCTLCMD);
+		break;
+	}
+	return 0;
+} /* ftdi_ioctl */
+
+
+static int __init ftdi_init (void)
+{
+	dbg(__FUNCTION__);
+	usb_serial_register (&ftdi_SIO_device);
+	usb_serial_register (&ftdi_8U232AM_device);
+	info(DRIVER_VERSION ":" DRIVER_DESC);
+	return 0;
+}
+
+
+static void __exit ftdi_exit (void)
+{
+	dbg(__FUNCTION__);
+	usb_serial_deregister (&ftdi_SIO_device);
+	usb_serial_deregister (&ftdi_8U232AM_device);
+}
+
+
+module_init(ftdi_init);
+module_exit(ftdi_exit);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
Index: trunk/code/projects/colonet/lib/usb_dev_board_drivers/ftdi_sio.h
===================================================================
--- trunk/code/projects/colonet/lib/usb_dev_board_drivers/ftdi_sio.h	(nonexistent)
+++ trunk/code/projects/colonet/lib/usb_dev_board_drivers/ftdi_sio.h	(revision 11)
@@ -0,0 +1,472 @@
+/*
+ * Definitions for the FTDI USB Single Port Serial Converter - 
+ * known as FTDI_SIO (Serial Input/Output application of the chipset) 
+ *
+ * The example I have is known as the USC-1000 which is available from
+ * http://www.dse.co.nz - cat no XH4214 It looks similar to this:
+ * http://www.dansdata.com/usbser.htm but I can't be sure There are other
+ * USC-1000s which don't look like my device though so beware!
+ *
+ * The device is based on the FTDI FT8U100AX chip. It has a DB25 on one side, 
+ * USB on the other.
+ *
+ * Thanx to FTDI (http://www.ftdi.co.uk) for so kindly providing details
+ * of the protocol required to talk to the device and ongoing assistence
+ * during development.
+ *
+ * Bill Ryder - bryder@sgi.com of Silicon Graphics, Inc.- wrote the 
+ * FTDI_SIO implementation.
+ *
+ */
+
+#define FTDI_VID	0x0403	/* Vendor Id */
+#define FTDI_SIO_PID	0x8372	/* Product Id SIO application of 8U100AX  */
+#define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */
+#define FTDI_NF_RIC_VID	0x0DCD	/* Vendor Id */
+#define FTDI_NF_RIC_PID	0x0001	/* Product Id */
+
+#define FTDI_SIO_RESET 		0 /* Reset the port */
+#define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
+#define FTDI_SIO_SET_FLOW_CTRL	2 /* Set flow control register */
+#define FTDI_SIO_SET_BAUD_RATE	3 /* Set baud rate */
+#define FTDI_SIO_SET_DATA	4 /* Set the data characteristics of the port */
+#define FTDI_SIO_GET_MODEM_STATUS	5 /* Retrieve current value of modern status register */
+#define FTDI_SIO_SET_EVENT_CHAR	6 /* Set the event character */
+#define FTDI_SIO_SET_ERROR_CHAR	7 /* Set the error character */
+
+/* Port Identifier Table */
+#define PIT_DEFAULT 		0 /* SIOA */
+#define PIT_SIOA		1 /* SIOA */
+/* The device this driver is tested with one has only one port */
+#define PIT_SIOB		2 /* SIOB */
+#define PIT_PARALLEL		3 /* Parallel */
+
+/* FTDI_SIO_RESET */
+#define FTDI_SIO_RESET_REQUEST FTDI_SIO_RESET
+#define FTDI_SIO_RESET_REQUEST_TYPE 0x40
+#define FTDI_SIO_RESET_SIO 0
+#define FTDI_SIO_RESET_PURGE_RX 1
+#define FTDI_SIO_RESET_PURGE_TX 2
+
+/*
+ * BmRequestType:  0100 0000B
+ * bRequest:       FTDI_SIO_RESET
+ * wValue:         Control Value 
+ *                   0 = Reset SIO
+ *                   1 = Purge RX buffer
+ *                   2 = Purge TX buffer
+ * wIndex:         Port
+ * wLength:        0
+ * Data:           None
+ *
+ * The Reset SIO command has this effect:
+ *
+ *    Sets flow control set to 'none'
+ *    Event char = $0D
+ *    Event trigger = disabled
+ *    Purge RX buffer
+ *    Purge TX buffer
+ *    Clear DTR
+ *    Clear RTS
+ *    baud and data format not reset
+ *
+ * The Purge RX and TX buffer commands affect nothing except the buffers
+ *
+   */
+
+/* FTDI_SIO_SET_BAUDRATE */
+#define FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE 0x40
+#define FTDI_SIO_SET_BAUDRATE_REQUEST 3
+
+/*
+ * BmRequestType:  0100 0000B
+ * bRequest:       FTDI_SIO_SET_BAUDRATE
+ * wValue:         BaudDivisor value - see below
+ * wIndex:         Port
+ * wLength:        0
+ * Data:           None
+ * The BaudDivisor values are calculated as follows:
+ * - BaseClock is either 12000000 or 48000000 depending on the device. FIXME: I wish
+ *   I knew how to detect old chips to select proper base clock!
+ * - BaudDivisor is a fixed point number encoded in a funny way.
+ *   (--WRONG WAY OF THINKING--)
+ *   BaudDivisor is a fixed point number encoded with following bit weighs:
+ *   (-2)(-1)(13..0). It is a radical with a denominator of 4, so values
+ *   end with 0.0 (00...), 0.25 (10...), 0.5 (01...), and 0.75 (11...).
+ *   (--THE REALITY--)
+ *   The both-bits-set has quite different meaning from 0.75 - the chip designers
+ *   have decided it to mean 0.125 instead of 0.75.
+ *   This info looked up in FTDI application note "FT8U232 DEVICES \ Data Rates
+ *   and Flow Control Consideration for USB to RS232".
+ * - BaudDivisor = (BaseClock / 16) / BaudRate, where the (=) operation should
+ *   automagically re-encode the resulting value to take fractions into consideration.
+ * As all values are integers, some bit twiddling is in order:
+ *   BaudDivisor = (BaseClock / 16 / BaudRate) |
+ *   (((BaseClock / 2 / BaudRate) & 2) ? 0x8000 : 0) | // 0.25
+ *   (((BaseClock / 2 / BaudRate) & 4) ? 0x4000 : 0) | // 0.5
+ *   (((BaseClock / 2 / BaudRate) & 0x7) == 1 ? 0xc000) // 0.125 - this line due to funny encoding only
+ */
+
+typedef enum {
+	SIO = 1,
+	FT8U232AM = 2,
+} ftdi_chip_type_t;
+
+typedef enum {
+ ftdi_sio_b300 = 0, 
+ ftdi_sio_b600 = 1, 
+ ftdi_sio_b1200 = 2,
+ ftdi_sio_b2400 = 3,
+ ftdi_sio_b4800 = 4,
+ ftdi_sio_b9600 = 5,
+ ftdi_sio_b19200 = 6,
+ ftdi_sio_b38400 = 7,
+ ftdi_sio_b57600 = 8,
+ ftdi_sio_b115200 = 9
+} FTDI_SIO_baudrate_t ;
+
+#define FTDI_SIO_BASE_BAUD_TO_DIVISOR(base, baud) ( \
+((base/2/baud) >> 3) | \
+(((base/2/baud) & 2) ? 0x8000 : 0) | \
+(((base/2/baud) & 4) ? 0x4000 : 0) | \
+((((base/2/baud) & 0x7) == 1) ? 0xc000 : 0) )
+
+#define FTDI_SIO_BAUD_TO_DIVISOR(baud) FTDI_SIO_BASE_BAUD_TO_DIVISOR(48000000, baud)
+
+/*
+ * The ftdi_8U232AM_xxMHz_byyy constans have been removed. Their values can
+ * be calculated as follows: FTDI_SIO_BAUD_TO_DIVISOR(xx000000, yyy)
+ */
+
+#define FTDI_SIO_SET_DATA_REQUEST FTDI_SIO_SET_DATA
+#define FTDI_SIO_SET_DATA_REQUEST_TYPE 0x40
+#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8 )
+#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8 )
+#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8 )
+#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8 )
+#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8 )
+#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11 )
+#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11 )
+#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11 )
+#define FTDI_SIO_SET_BREAK (0x1 << 14)
+/* FTDI_SIO_SET_DATA */
+
+/*
+ * BmRequestType:  0100 0000B 
+ * bRequest:       FTDI_SIO_SET_DATA
+ * wValue:         Data characteristics (see below)
+ * wIndex:         Port
+ * wLength:        0
+ * Data:           No
+ *
+ * Data characteristics
+ *
+ *   B0..7   Number of data bits
+ *   B8..10  Parity
+ *           0 = None
+ *           1 = Odd
+ *           2 = Even
+ *           3 = Mark
+ *           4 = Space
+ *   B11..13 Stop Bits
+ *           0 = 1
+ *           1 = 1.5
+ *           2 = 2
+ *   B14
+ *           1 = TX ON (break)
+ *           0 = TX OFF (normal state)
+ *   B15 Reserved
+ *
+ */
+
+
+
+/* FTDI_SIO_MODEM_CTRL */
+#define FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE 0x40
+#define FTDI_SIO_SET_MODEM_CTRL_REQUEST FTDI_SIO_MODEM_CTRL
+
+/* 
+ * BmRequestType:   0100 0000B
+ * bRequest:        FTDI_SIO_MODEM_CTRL
+ * wValue:          ControlValue (see below)
+ * wIndex:          Port
+ * wLength:         0
+ * Data:            None
+ *
+ * NOTE: If the device is in RTS/CTS flow control, the RTS set by this
+ * command will be IGNORED without an error being returned
+ * Also - you can not set DTR and RTS with one control message
+ */
+
+#define FTDI_SIO_SET_DTR_MASK 0x1
+#define FTDI_SIO_SET_DTR_HIGH ( 1 | ( FTDI_SIO_SET_DTR_MASK  << 8))
+#define FTDI_SIO_SET_DTR_LOW  ( 0 | ( FTDI_SIO_SET_DTR_MASK  << 8))
+#define FTDI_SIO_SET_RTS_MASK 0x2
+#define FTDI_SIO_SET_RTS_HIGH ( 2 | ( FTDI_SIO_SET_RTS_MASK << 8 ))
+#define FTDI_SIO_SET_RTS_LOW ( 0 | ( FTDI_SIO_SET_RTS_MASK << 8 ))
+
+/*
+ * ControlValue
+ * B0    DTR state
+ *          0 = reset
+ *          1 = set
+ * B1    RTS state
+ *          0 = reset
+ *          1 = set
+ * B2..7 Reserved
+ * B8    DTR state enable
+ *          0 = ignore
+ *          1 = use DTR state
+ * B9    RTS state enable
+ *          0 = ignore
+ *          1 = use RTS state
+ * B10..15 Reserved
+ */
+
+/* FTDI_SIO_SET_FLOW_CTRL */
+#define FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE 0x40
+#define FTDI_SIO_SET_FLOW_CTRL_REQUEST FTDI_SIO_SET_FLOW_CTRL
+#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 
+#define FTDI_SIO_RTS_CTS_HS (0x1 << 8)
+#define FTDI_SIO_DTR_DSR_HS (0x2 << 8)
+#define FTDI_SIO_XON_XOFF_HS (0x4 << 8)
+/*
+ *   BmRequestType:  0100 0000b
+ *   bRequest:       FTDI_SIO_SET_FLOW_CTRL
+ *   wValue:         Xoff/Xon
+ *   wIndex:         Protocol/Port - hIndex is protocl / lIndex is port
+ *   wLength:        0 
+ *   Data:           None
+ *
+ * hIndex protocol is:
+ *   B0 Output handshaking using RTS/CTS
+ *       0 = disabled
+ *       1 = enabled
+ *   B1 Output handshaking using DTR/DSR
+ *       0 = disabled
+ *       1 = enabled
+ *   B2 Xon/Xoff handshaking
+ *       0 = disabled
+ *       1 = enabled
+ *
+ * A value of zero in the hIndex field disables handshaking
+ *
+ * If Xon/Xoff handshaking is specified, the hValue field should contain the XOFF character 
+ * and the lValue field contains the XON character.
+ */  
+ 
+/*
+ * FTDI_SIO_SET_EVENT_CHAR 
+ *
+ * Set the special event character for the specified communications port.
+ * If the device sees this character it will immediately return the
+ * data read so far - rather than wait 40ms or until 62 bytes are read
+ * which is what normally happens.
+ */
+
+
+#define  FTDI_SIO_SET_EVENT_CHAR_REQUEST FTDI_SIO_SET_EVENT_CHAR
+#define  FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE 0x40
+
+
+/* 
+ *  BmRequestType:   0100 0000b
+ *  bRequest:        FTDI_SIO_SET_EVENT_CHAR
+ *  wValue:          EventChar
+ *  wIndex:          Port
+ *  wLength:         0
+ *  Data:            None
+ *
+ * wValue:
+ *   B0..7   Event Character
+ *   B8      Event Character Processing
+ *             0 = disabled
+ *             1 = enabled
+ *   B9..15  Reserved
+ *
+ */
+          
+/* FTDI_SIO_SET_ERROR_CHAR */
+
+/* Set the parity error replacement character for the specified communications port */
+
+/* 
+ *  BmRequestType:  0100 0000b
+ *  bRequest:       FTDI_SIO_SET_EVENT_CHAR
+ *  wValue:         Error Char
+ *  wIndex:         Port
+ *  wLength:        0
+ *  Data:           None
+ *
+ *Error Char
+ *  B0..7  Error Character
+ *  B8     Error Character Processing
+ *           0 = disabled
+ *           1 = enabled
+ *  B9..15 Reserved
+ *
+ */
+
+/* FTDI_SIO_GET_MODEM_STATUS */
+/* Retreive the current value of the modem status register */
+
+#define FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE 0xc0
+#define FTDI_SIO_GET_MODEM_STATUS_REQUEST FTDI_SIO_GET_MODEM_STATUS
+#define FTDI_SIO_CTS_MASK 0x10
+#define FTDI_SIO_DSR_MASK 0x20
+#define FTDI_SIO_RI_MASK  0x40
+#define FTDI_SIO_RLSD_MASK 0x80
+/* 
+ *   BmRequestType:   1100 0000b
+ *   bRequest:        FTDI_SIO_GET_MODEM_STATUS
+ *   wValue:          zero
+ *   wIndex:          Port
+ *   wLength:         1
+ *   Data:            Status
+ * 
+ * One byte of data is returned 
+ * B0..3 0
+ * B4    CTS
+ *         0 = inactive
+ *         1 = active
+ * B5    DSR
+ *         0 = inactive
+ *         1 = active
+ * B6    Ring Indicator (RI)
+ *         0 = inactive
+ *         1 = active
+ * B7    Receive Line Signal Detect (RLSD)
+ *         0 = inactive
+ *         1 = active 
+ */
+
+
+
+/* Descriptors returned by the device 
+ * 
+ *  Device Descriptor
+ * 
+ * Offset	Field		Size	Value	Description
+ * 0	bLength		1	0x12	Size of descriptor in bytes
+ * 1	bDescriptorType	1	0x01	DEVICE Descriptor Type
+ * 2	bcdUSB		2	0x0110	USB Spec Release Number
+ * 4	bDeviceClass	1	0x00	Class Code
+ * 5	bDeviceSubClass	1	0x00	SubClass Code
+ * 6	bDeviceProtocol	1	0x00	Protocol Code
+ * 7	bMaxPacketSize0 1	0x08	Maximum packet size for endpoint 0
+ * 8	idVendor	2	0x0403	Vendor ID
+ * 10	idProduct	2	0x8372	Product ID (FTDI_SIO_PID)
+ * 12	bcdDevice	2	0x0001	Device release number
+ * 14	iManufacturer	1	0x01	Index of man. string desc
+ * 15	iProduct	1	0x02	Index of prod string desc
+ * 16	iSerialNumber	1	0x02	Index of serial nmr string desc
+ * 17	bNumConfigurations 1    0x01	Number of possible configurations
+ * 
+ * Configuration Descriptor
+ * 
+ * Offset	Field			Size	Value
+ * 0	bLength			1	0x09	Size of descriptor in bytes
+ * 1	bDescriptorType		1	0x02	CONFIGURATION Descriptor Type
+ * 2	wTotalLength		2	0x0020	Total length of data
+ * 4	bNumInterfaces		1	0x01	Number of interfaces supported
+ * 5	bConfigurationValue	1	0x01	Argument for SetCOnfiguration() req
+ * 6	iConfiguration		1	0x02	Index of config string descriptor
+ * 7	bmAttributes		1	0x20	Config characteristics Remote Wakeup
+ * 8	MaxPower		1	0x1E	Max power consumption
+ * 
+ * Interface Descriptor
+ * 
+ * Offset	Field			Size	Value
+ * 0	bLength			1	0x09	Size of descriptor in bytes
+ * 1	bDescriptorType		1	0x04	INTERFACE Descriptor Type
+ * 2	bInterfaceNumber	1	0x00	Number of interface
+ * 3	bAlternateSetting	1	0x00	Value used to select alternate
+ * 4	bNumEndpoints		1	0x02	Number of endpoints
+ * 5	bInterfaceClass		1	0xFF	Class Code
+ * 6	bInterfaceSubClass	1	0xFF	Subclass Code
+ * 7	bInterfaceProtocol	1	0xFF	Protocol Code
+ * 8	iInterface		1	0x02	Index of interface string description
+ * 
+ * IN Endpoint Descriptor
+ * 
+ * Offset	Field			Size	Value
+ * 0	bLength			1	0x07	Size of descriptor in bytes
+ * 1	bDescriptorType		1	0x05	ENDPOINT descriptor type
+ * 2	bEndpointAddress	1	0x82	Address of endpoint
+ * 3	bmAttributes		1	0x02	Endpoint attributes - Bulk
+ * 4	bNumEndpoints		2	0x0040	maximum packet size
+ * 5	bInterval		1	0x00	Interval for polling endpoint
+ * 
+ * OUT Endpoint Descriptor
+ * 
+ * Offset	Field			Size	Value
+ * 0	bLength			1	0x07	Size of descriptor in bytes
+ * 1	bDescriptorType		1	0x05	ENDPOINT descriptor type
+ * 2	bEndpointAddress	1	0x02	Address of endpoint
+ * 3	bmAttributes		1	0x02	Endpoint attributes - Bulk
+ * 4	bNumEndpoints		2	0x0040	maximum packet size
+ * 5	bInterval		1	0x00	Interval for polling endpoint
+ *     
+ * DATA FORMAT
+ * 
+ * IN Endpoint
+ * 
+ * The device reserves the first two bytes of data on this endpoint to contain the current
+ * values of the modem and line status registers. In the absence of data, the device 
+ * generates a message consisting of these two status bytes every 40 ms
+ * 
+ * Byte 0: Modem Status
+ * 
+ * Offset	Description
+ * B0	Reserved - must be 1
+ * B1	Reserved - must be 0
+ * B2	Reserved - must be 0
+ * B3	Reserved - must be 0
+ * B4	Clear to Send (CTS)
+ * B5	Data Set Ready (DSR)
+ * B6	Ring Indicator (RI)
+ * B7	Receive Line Signal Detect (RLSD)
+ * 
+ * Byte 1: Line Status
+ * 
+ * Offset	Description
+ * B0	Data Ready (DR)
+ * B1	Overrun Error (OE)
+ * B2	Parity Error (PE)
+ * B3	Framing Error (FE)
+ * B4	Break Interrupt (BI)
+ * B5	Transmitter Holding Register (THRE)
+ * B6	Transmitter Empty (TEMT)
+ * B7	Error in RCVR FIFO
+ * 
+ */
+#define FTDI_RS0_CTS	(1 << 4)
+#define FTDI_RS0_DSR	(1 << 5)
+#define FTDI_RS0_RI	(1 << 6)
+#define FTDI_RS0_RLSD	(1 << 7)
+
+#define FTDI_RS_DR  1
+#define FTDI_RS_OE (1<<1)
+#define FTDI_RS_PE (1<<2)
+#define FTDI_RS_FE (1<<3)
+#define FTDI_RS_BI (1<<4)
+#define FTDI_RS_THRE (1<<5)
+#define FTDI_RS_TEMT (1<<6)
+#define FTDI_RS_FIFO  (1<<7)
+
+/*
+ * OUT Endpoint
+ * 
+ * This device reserves the first bytes of data on this endpoint contain the length
+ * and port identifier of the message. For the FTDI USB Serial converter the port 
+ * identifier is always 1.
+ * 
+ * Byte 0: Line Status
+ * 
+ * Offset	Description
+ * B0	Reserved - must be 1
+ * B1	Reserved - must be 0
+ * B2..7	Length of message - (not including Byte 0)
+ * 
+ */
+
Index: trunk/code/projects/colonet/lib/usb_dev_board_drivers/readme.txt
===================================================================
--- trunk/code/projects/colonet/lib/usb_dev_board_drivers/readme.txt	(nonexistent)
+++ trunk/code/projects/colonet/lib/usb_dev_board_drivers/readme.txt	(revision 11)
@@ -0,0 +1,4 @@
+The Linux FTDI USB driver provided is version 1.2.1.  More information on the driver, 
+including updated versions can be found at http://ftdi-usb-sio.sourceforge.net/.  The driver 
+should be compiled either as a loadable module or into a kernel.  The PID should be changed in the header file to "0xEE18" which corresponds to the PID used 
+on FTDI USB Converter in the MaxStream PKG-U.  
\ No newline at end of file
Index: trunk/code/projects/colonet/lib/colonet_firefly+/colonet.c
===================================================================
--- trunk/code/projects/colonet/lib/colonet_firefly+/colonet.c	(nonexistent)
+++ trunk/code/projects/colonet/lib/colonet_firefly+/colonet.c	(revision 11)
@@ -0,0 +1,335 @@
+/** @file colonet.c
+ * @brief Colonet library for colony robots
+
+ * @author Eugene Marinelli
+ * @date 10/26/06
+ * 
+ * @bug Handler registration not tested
+ * @bug Request reponding not implemented - only accepts commands.
+ */
+
+#include <firefly+_lib.h>
+
+#include "colonet.h"
+
+typedef struct {
+  unsigned char msgId; //is this necessary?
+  void (*handler)(void);
+} UserHandler;
+
+/* Globals (internal) */
+static UserHandler user_handlers[USER_DEFINED_MSG_TOTAL];
+
+/* Internal function prototypes */
+void packet_string_to_struct(ColonetPacket* dest_pkt, char* pkt_buf);
+unsigned int two_bytes_to_int(char high, char low);
+
+/* Public functions */
+int colonet_handle_message(unsigned char robot_id, char* pkt_buf)
+{
+  ColonetPacket pkt;
+  unsigned char* args; //up to 7 char args
+  unsigned int int_args[3]; //up to 3 int (2-byte) args
+
+  packet_string_to_struct(&pkt, pkt_buf);
+
+  if(pkt.msg_dest != GLOBAL_DEST && pkt.msg_dest != robot_id){ 
+    //message not intended for us
+    return 1;
+  }
+
+  args = pkt.data;
+  
+  /* Hack - could be done more 1337ly with casting, but this way we don't have
+   * to worry about little/big endian stuff */
+  int_args[0] = two_bytes_to_int(args[0], args[1]);
+  int_args[1] = two_bytes_to_int(args[2], args[3]);
+  int_args[2] = two_bytes_to_int(args[4], args[5]);
+
+  if(pkt.msg_type == COLONET_REQUEST){
+    switch(pkt.msg_code){
+      //Sharp
+    case READ_DISTANCE:
+      break;
+    case LINEARIZE_DISTANCE:
+      break;
+    case LOG_DISTANCE:
+      break;
+
+      //Serial
+    case SERIAL_GETCHAR:
+      break;
+    case SERIAL_GETCHAR_NB:
+      break;
+    case SERIAL1_GETCHAR:
+      break;
+    case SERIAL1_GETCHAR_NB:
+      break;
+
+      //Analog
+    case ANALOG8:
+      break;
+    case ANALOG10:
+      break;
+    case WHEEL:
+      break;
+    case BATTERY:
+      break;
+
+      //BOM
+    case GETMAXBOM:
+      break;
+
+      //Dio
+    case DIGITAL_INPUT:
+      break;
+    case BUTTON1_READ:
+      break;
+    case BUTTON2_READ:
+      break;
+
+      //Bumper
+    case DETECT_BUMP:
+      break;
+    }
+
+    /* TODO - send back data! */
+
+  }else if(pkt.msg_type == COLONET_COMMAND){
+    if(pkt.msg_code >= USER_DEFINED_MSG_ID_START && 
+       pkt.msg_code <= USER_DEFINED_MSG_ID_END){
+      if (user_handlers[pkt.msg_code - USER_DEFINED_MSG_ID_START].handler) {
+        /* Call the user's handler function if it the function's address
+         * is non-zero (has been set) */
+        user_handlers[pkt.msg_code - USER_DEFINED_MSG_ID_START].handler();
+      }
+
+      return 0;
+    }
+
+    switch(pkt.msg_code){
+    default:
+      printf("%s: Error - message code %d not implemented\n", __FUNCTION__,
+             pkt.msg_code);
+      return -1;
+      break;
+
+      //Buzzer
+    case BUZZER_INIT:
+      buzzer_init();
+      break;
+    case BUZZER_SET_VAL:
+      buzzer_set_val(args[0]);
+      break;
+    case BUZZER_SET_FREQ:
+      buzzer_set_freq(args[0]);
+      break;
+    case BUZZER_CHIRP:
+      buzzer_chirp(int_args[0], int_args[1]);
+      break;
+    case BUZZER_OFF:
+      buzzer_off();
+      break;
+      
+      //LCD
+    case LCD_INIT:
+      lcd_init();
+      break;
+    case LCD_CLEAR_SCREEN:
+      lcd_clear_screen();
+      break;
+    case LCD_PUTBYTE:
+      lcd_putbyte(args[0]);
+      break;
+    case LCD_PUTCHAR:
+      lcd_putchar((char)args[0]);
+      break;
+    case LCD_PUTSTR:
+      lcd_putstr((char*)args);
+      break;
+    case LCD_GOTOXY: 
+      lcd_gotoxy(int_args[0], int_args[1]);
+      break;
+    case LCD_PUTINT: 
+      lcd_putint(int_args[0]);
+      break;
+    case ORB_INIT:
+      orb_init();
+      break;
+      //Orb
+    case ORB_SET:
+      orb_set(args[0], args[1], args[2]);
+      break;
+    case ORB_SET_COLOR:
+      orb_set_color(int_args[0]);
+      break;
+    case ORB_DISABLE:
+      orb_disable();
+      break;
+    case ORB_ENABLE:
+      orb_enable();
+      break;
+    case ORB_SET_DIO:
+      orb_set_dio(int_args[0], int_args[1], int_args[2]);
+      break;
+    case LED_INIT:
+      led_init();
+      break;
+    case LED_USER:
+      led_user(int_args[0]);
+      break;
+    case ORB_SEND:
+      //orb_send();
+      break;
+      //Motors
+    case MOTORS_INIT:
+      motors_init();
+      break;
+    case MOTOR1_SET:
+      motor1_set(int_args[0], int_args[1]);
+      break;
+    case MOTOR2_SET:
+      motor2_set(int_args[0], int_args[1]);
+      break;
+    case MOTORS_OFF:
+      motors_off();
+      break;
+
+      /*
+    case MOVE:
+      
+      break;
+      */
+
+      //SERIAL
+    case SERIAL_INIT:
+      serial_init(int_args[0]);
+      break;
+    case SERIAL_PUTCHAR:
+      serial_putchar((char)args[0]);
+      break;
+    case SERIAL1_INIT:
+      serial1_init(int_args[0]);
+      break;
+    case SERIAL1_PUTCHAR:
+      serial1_putchar((char)args[0]);
+      break;
+    case PRINTF:
+      printf("%s", pkt.data);
+      break;
+    case KILL_ROBOT:
+      motors_off();
+      buzzer_off();
+      exit(0); //kill the robot
+      break;
+      //Time
+    case DELAY_MS:
+      delay_ms(int_args[0]);
+      break;
+
+      //Analog
+    case ANALOG_INIT:
+      analog_init();
+      break;
+
+      //BOM
+    case BOM_ON:
+      bom_on();
+      break;
+    case BOM_OFF:
+      bom_off();
+      break;
+    case OUTPUT_HIGH:
+      output_high(int_args[0]);
+      break;
+    case OUTPUT_LOW:
+      output_low(int_args[0]);
+      break;
+
+      //Dio
+    case DIGITAL_OUTPUT:
+      digital_output(int_args[0], int_args[1]);
+      break;
+    case BUTTON1_WAIT:
+      button1_wait();
+      break;
+    case BUTTON1_WAIT_LED:
+      button1_wait_led();
+      break;
+    case BUTTON2_WAIT:
+      button2_wait();
+      break;
+    case BUTTON2_WAIT_LED:
+      button2_wait_led();
+      break;
+
+      //WL
+    case WL_INIT:
+      wl_init();
+      break;
+    case PARSE_BUFFER:
+      parse_buffer();
+      break;
+    case WL_SEND:
+      wl_send();
+      break;
+    }
+  }else{
+    printf("%s: Error: Invalid colonet message type", __FUNCTION__);
+    return -1;
+  }
+
+  return 0;
+}
+
+/* colonet_add_message
+ * Adds a user-defined message
+ */
+int colonet_add_message(unsigned char msgId, void (*handler)(void))
+{
+  if(msgId < USER_DEFINED_MSG_ID_START || msgId > USER_DEFINED_MSG_ID_END){
+    return -1;
+  }
+
+  /* Register this function in the array */
+  user_handlers[msgId-USER_DEFINED_MSG_ID_START].msgId = msgId;
+  user_handlers[msgId-USER_DEFINED_MSG_ID_START].handler = handler;
+
+  return 0;
+}
+
+/* Private functions */
+static void packet_string_to_struct(ColonetPacket* dest_pkt, char* pkt_buf)
+{
+  int i;
+  
+  printf("\npacket:");
+  for(i = 0; i < 16; i++){
+    printf("%d ", pkt_buf[i]);
+  }
+
+  printf("\n");
+
+  dest_pkt->prefix[0] = pkt_buf[0];
+  dest_pkt->prefix[1] = pkt_buf[1];
+  dest_pkt->token_src = pkt_buf[2];
+  dest_pkt->token_dest = pkt_buf[3];
+  dest_pkt->msg_dest = pkt_buf[4];
+  dest_pkt->msg_type = pkt_buf[5];
+  dest_pkt->msg_code = pkt_buf[6];
+  
+  for(i = 0; i < PACKET_DATA_LEN; i++){
+    dest_pkt->data[i] = pkt_buf[7+i];
+  }
+
+  dest_pkt->num_robots = pkt_buf[PACKET_SIZE-2];
+  dest_pkt->checksum = pkt_buf[PACKET_SIZE-1];
+}
+
+/* two_bytes_to_int(char a, char b)
+ * Returns int of form [high][low]
+ */
+static unsigned int two_bytes_to_int(char high, char low)
+{
+  return (((unsigned int)high)<<8) + (unsigned int)low;
+}
Index: trunk/code/projects/colonet/lib/colonet_firefly+/colonet.h
===================================================================
--- trunk/code/projects/colonet/lib/colonet_firefly+/colonet.h	(nonexistent)
+++ trunk/code/projects/colonet/lib/colonet_firefly+/colonet.h	(revision 11)
@@ -0,0 +1,34 @@
+/** @file colonet.h
+ * @brief Colonet library for colony robots
+ * @author Eugene Marinelli
+ * @date 10/26/06
+ */
+
+#ifndef COLONET_H_
+#define COLONET_H_
+
+#include <colonet_defs.h>
+
+/** @brief Handles colonet packets.  Should be called by parse_buffer 
+ * when it is determined that a colonet message has been received.
+ *
+ * @param robot_id The robot id
+ * @param pkt_buf The packet buffer (e.g. wl_buf)
+ * 
+ * @return -1 on error (invalid msgId), 0 on success
+ */
+int colonet_handle_message(unsigned char robot_id, char* packet);
+
+/** @brief Registers a new colonet message handler function.  If a message
+ * with msgId is received, then handler will be called.
+ * 
+ * @param msgId The message id of the handler to be registered.  Must be
+ * between USER_DEFINED_MSG_ID_START and USER_DEFINED_MSG_ID_END
+ * @param handler The function to be called if a colonet packet with message
+ * id msgId is received
+ * 
+ * @return -1 on error (invalid msgId), 0 on success
+ */
+int colonet_add_message(unsigned char msgId, void (*handler)(void));
+
+#endif
Index: trunk/code/projects/colonet/ColonetServer/client.cpp
===================================================================
--- trunk/code/projects/colonet/ColonetServer/client.cpp	(nonexistent)
+++ trunk/code/projects/colonet/ColonetServer/client.cpp	(revision 11)
@@ -0,0 +1,99 @@
+/** @file client.c
+ *
+ *  @author Jason Knichel
+ *  @author Eugene Marinelli
+ *
+ * @bug Weird segfault when processing tokens
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <colonet_wireless.h>
+
+#include "includes/client.h"
+#include "includes/options.h"
+#include "includes/ConnectionPool.h"
+
+/* Globals */
+static ColonetWireless* wireless;
+extern ConnectionPool connection_pool;
+
+
+/* Public functions */
+int wirelessMessageHandler(ColonetPacket* pkt)
+{
+  printf("Received wireless message!!!\n");
+  if (!pkt)
+  {
+    printf("The packet pointer was null.\n");
+    return -1;
+  }
+
+  if ((int)pkt->msg_type == COLONET_RESPONSE)
+  {
+    printf("response\n");
+
+    int dest = (int)(pkt->msg_dest);
+    if (dest < connection_pool.get_next_available_slot())
+    {
+      char buffer[WRITE_BUFFER_SIZE];
+          
+      int value = (int)(pkt->data[0]);
+      snprintf(buffer, WRITE_BUFFER_SIZE, "%d\n", value);
+          
+      //TODO:make a connection pool write function and move this code into it
+      int len = strlen(buffer);
+      if (len > (WRITE_BUFFER_SIZE-connection_pool.get_write_buffer_size(dest)))
+      {
+        printf("There is not enough room in the write buffer to send the data to the client.\n");
+        return -1;
+      }
+
+      memcpy(connection_pool.get_write_buffer(dest), buffer, len);
+      connection_pool.set_write_buffer_size(dest, len);
+      printf("Put data in write buffer for client.\n");
+    }
+    else
+    {
+      printf("The robot wanted to pass the data to a client not in our pool.\n");
+      return -1;
+    }
+  }
+  else
+  {
+    printf("not a response\n");
+  }
+
+  pkt = 0;
+  return 0;
+}
+
+int initWireless()
+{
+  char* log_filename = NULL;
+
+  if (optionsG.logging_enabled) {
+    log_filename = optionsG.log_filename;
+  }
+
+  wireless = new ColonetWireless(optionsG.wireless_port, 
+                                 wirelessMessageHandler, log_filename, 
+                                 /*!optionsG.listener_mode*/false, true);
+  //Note: last arg set to true ignores token ring;  in general, this should
+  //probably be false (changed for demo purposes)
+
+  if (!wireless->run_listener_thread()) {
+		return -1;
+	}
+
+	return 0;
+}
+
+void send_wireless_message(unsigned char msg_dest, unsigned char msg_type, 
+                          unsigned char msg_code, unsigned char* data) {
+  wireless->send(msg_dest, msg_type, msg_code, data);
+}
Index: trunk/code/projects/colonet/ColonetServer/includes/ConnectionPool.h
===================================================================
--- trunk/code/projects/colonet/ColonetServer/includes/ConnectionPool.h	(nonexistent)
+++ trunk/code/projects/colonet/ColonetServer/includes/ConnectionPool.h	(revision 11)
@@ -0,0 +1,80 @@
+/**
+ * @author Jason Knichel
+ * @date 7/22/07
+ */
+
+#ifndef CONNECTION_POOL_H
+#define CONNECTION_POOL_H
+
+#include <sys/select.h>
+
+#define MAX_TOKENS 15
+#define MAX_TOKEN_SIZE 30
+
+#define ROBOT_COMMAND_OFFSET 1
+#define ROBOT_COMMAND_LEN    3
+
+#define ERROR_INVALID_CLIENT_DESCRIPTOR -1
+#define ERROR_TOO_MANY_CLIENTS          -2
+#define ERROR_ALLOCATING_MEMORY         -3
+
+#define MAX_CONNECTIONS 250
+#define READ_BUFFER_SIZE 1024
+#define WRITE_BUFFER_SIZE 1024
+
+class ConnectionPool {
+
+public:
+  ConnectionPool();
+  ~ConnectionPool();
+
+  int add_client(int client_file_descriptor);
+  int remove_client(int client_file_descriptor);
+  int check_clients();
+  void set_listen_socket_in_ready_set(int listen_socket);
+  int perform_select(int listen_socket, struct timeval * select_timeout);
+  int is_socket_ready_to_read(int socket);
+  int is_socket_ready_to_write(int socket);
+
+
+  int get_max_file_descriptor();
+  void set_max_file_descriptor(int new_max_file_descriptor);
+
+  int get_next_available_slot();
+
+  int get_number_clients_ready();
+  void set_number_clients_ready(int new_number_clients_ready);
+
+  fd_set get_ready_set();
+  
+  fd_set get_read_set();
+  void set_read_set(fd_set new_set);
+
+  fd_set get_write_set();
+  void set_write_set(fd_set new_set);
+
+  int get_write_buffer_size(int pool_index);
+  void set_write_buffer_size(int pool_index, int new_buffer_size);
+
+  char * get_write_buffer(int pool_index);
+
+
+private:
+  int max_file_descriptor;
+  int next_available_slot;
+  int number_clients_ready;
+  fd_set ready_set;
+  fd_set read_set;
+  fd_set write_set;
+  int client_file_descriptor_array[MAX_CONNECTIONS];
+  char * read_buffer[MAX_CONNECTIONS];
+  int read_buffer_size[MAX_CONNECTIONS];
+  char * write_buffer[MAX_CONNECTIONS];
+  int write_buffer_size[MAX_CONNECTIONS];
+
+  int parse_command(char* command, int pool_index);
+  int tokenize_command(char* command, char tokens[MAX_TOKENS][MAX_TOKEN_SIZE]);
+  int check_tokens(unsigned char* tokens, int numTokens);
+};
+
+#endif
Index: trunk/code/projects/colonet/ColonetServer/includes/options.h
===================================================================
--- trunk/code/projects/colonet/ColonetServer/includes/options.h	(nonexistent)
+++ trunk/code/projects/colonet/ColonetServer/includes/options.h	(revision 11)
@@ -0,0 +1,26 @@
+/**
+ * @file options.h
+ * @brief Options for ColonetServer
+ * @author Eugene Marinelli
+ * @date 2/13/07
+ */
+
+#ifndef OPTIONS_H
+#define OPTIONS_H
+
+#define DEFAULTPORT 10123
+#define SMALLEST_POSS_LISTEN_PORT 2000
+
+typedef struct {
+  int listen_port;
+  char wireless_port[80];
+  char log_filename[80];
+  bool logging_enabled;
+  bool listener_mode;
+} ColonetServerOptionsT;
+
+extern ColonetServerOptionsT optionsG;
+
+void parseCmdLine(int argc, char** argv);
+
+#endif
Index: trunk/code/projects/colonet/ColonetServer/includes/client.h
===================================================================
--- trunk/code/projects/colonet/ColonetServer/includes/client.h	(nonexistent)
+++ trunk/code/projects/colonet/ColonetServer/includes/client.h	(revision 11)
@@ -0,0 +1,17 @@
+/**
+ *
+ *  @author Jason Knichel
+ *
+ */
+
+#ifndef CLIENT_H
+#define CLIENT_H
+
+#include <colonet_wireless.h>
+
+int wirelessMessageHandler(ColonetPacket* pkt);
+int initWireless(void);
+void send_wireless_message(unsigned char msg_dest, unsigned char msg_type, 
+                           unsigned char msg_code, unsigned char* data);
+
+#endif
Index: trunk/code/projects/colonet/ColonetServer/includes/Logging.h
===================================================================
--- trunk/code/projects/colonet/ColonetServer/includes/Logging.h	(nonexistent)
+++ trunk/code/projects/colonet/ColonetServer/includes/Logging.h	(revision 11)
@@ -0,0 +1,37 @@
+/**
+ *
+ *  @author Jason Knichel
+ *
+ */
+
+#ifndef LOGGING_H
+#define LOGGING_H
+
+#include <time.h>
+#include <stdio.h>
+
+#define LOG_TYPE_START_LOG  0
+#define LOG_TYPE_CONNECT    1
+#define LOG_TYPE_DISCONNECT 2
+#define LOG_TYPE_ERROR      3
+#define LOG_TYPE_MESSAGE    4
+
+#define LOG_MAX_TYPE_LENGTH 25
+#define LOG_MAX_TIME_LENGTH 64
+
+class Log {
+public:
+  Log(char * fileName);
+  ~Log();
+
+  int logMessage(int type, char * message);
+
+private:
+  struct tm getCurrentTime();
+
+  FILE * logFile;
+
+};
+
+
+#endif
Index: trunk/code/projects/colonet/ColonetServer/includes/initialization.h
===================================================================
--- trunk/code/projects/colonet/ColonetServer/includes/initialization.h	(nonexistent)
+++ trunk/code/projects/colonet/ColonetServer/includes/initialization.h	(revision 11)
@@ -0,0 +1,13 @@
+/**
+ *
+ *  @author Jason Knichel
+ *
+ */
+
+#ifndef INITIALIZATION_H
+#define INITIALIZATION_H
+
+int initializeServer(int argc, char * argv[]);
+int initConnection(int port);
+
+#endif
Index: trunk/code/projects/colonet/ColonetServer/Logging.cpp
===================================================================
--- trunk/code/projects/colonet/ColonetServer/Logging.cpp	(nonexistent)
+++ trunk/code/projects/colonet/ColonetServer/Logging.cpp	(revision 11)
@@ -0,0 +1,108 @@
+/**
+ *
+ *  @author Jason Knichel
+ *
+ */
+
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "includes/Logging.h"
+
+
+Log::Log(char * filename)
+{
+
+  printf("Creating log object\n");
+
+  if (!filename)
+    {
+      fprintf(stderr, "Provided a null filename when trying to create a log.\n");
+      return;
+    }
+
+  logFile = fopen(filename, "a"); //open file for appending
+  if (!logFile)
+    {
+      fprintf(stderr, "Error opening %s as log file.\n", filename);
+      return;
+    }
+
+  printf("About to log start message.\n");
+  logMessage(LOG_TYPE_START_LOG, "Starting server");
+}
+
+Log::~Log()
+{
+  if (!logFile)
+    fclose(logFile);
+}
+
+struct tm Log::getCurrentTime()
+{
+  struct tm currTime;
+  memset(&currTime, 0, sizeof(struct tm));
+  
+  time_t t = time(NULL);
+  localtime_r(&t, &currTime);
+  
+  return currTime;  
+}
+
+int Log::logMessage(int type, char * message)
+{
+  if (!logFile)
+    {
+      fprintf(stderr, "Tried to log a message but the file pointer was null.\n");
+      return -1;
+    }
+  if (!message)
+    {
+      fprintf(stderr, "Tried to log a null message.\n");
+      return -1;
+    }
+  
+  static char * start_log = "Starting Log";
+  static char * connect = "Client Connecting";
+  static char * disconnect = "Client Disconnecting";
+  static char * error = "Error";
+  static char * logGenMessage = "Generic Message";
+
+  char * messageType;
+
+  switch(type)
+    {
+    case LOG_TYPE_START_LOG:
+      messageType = start_log;
+      break;
+    case LOG_TYPE_CONNECT:
+      messageType = connect;
+      break;
+    case LOG_TYPE_DISCONNECT:
+      messageType = disconnect;
+      break;
+    case LOG_TYPE_ERROR:
+      messageType = error;
+      break;
+    case LOG_TYPE_MESSAGE:
+      messageType = logGenMessage;
+      break;
+    default:
+      fprintf(stderr, "Tried to log a message with an invalid type.\n");
+      return -1;
+    }
+
+  struct tm currTime = getCurrentTime();
+  
+  char buffer[LOG_MAX_TIME_LENGTH];
+  asctime_r(&currTime, buffer);
+  int len = strlen(buffer);
+  buffer[len-1] = '\0'; //remove the newline that is put at the end by asctime_r
+  fprintf(logFile, "%s %*s   %s\n", buffer, LOG_MAX_TYPE_LENGTH, messageType, message);
+  fflush(logFile);
+  
+
+  return 0;
+}
+    
Index: trunk/code/projects/colonet/ColonetServer/initialization.c
===================================================================
--- trunk/code/projects/colonet/ColonetServer/initialization.c	(nonexistent)
+++ trunk/code/projects/colonet/ColonetServer/initialization.c	(revision 11)
@@ -0,0 +1,152 @@
+/** 
+ * @file initialization.c
+ *
+ *  @author Jason Knichel
+ *  @author Eugene Marinelli
+ */
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "includes/initialization.h"
+#include "includes/client.h"
+#include "includes/options.h"
+#include "includes/Logging.h"
+
+extern int listenSocket;
+extern Log * logger;
+
+int initializeServer(int argc, char** argv)
+{
+  printf("Initializing Server...\n");
+
+  parseCmdLine(argc, argv);
+
+  //TODO: make it so the log file name is passed in on command line and default it to something if it isn't
+  logger = new Log("logFile.txt");
+
+  if (initConnection(optionsG.listen_port) < 0)
+    return -1;
+
+  if (initWireless() < 0) {
+    fprintf(stderr, "%s: initWireless failed\n", __FUNCTION__);
+    return -1;
+  }
+
+  return 0;
+}
+
+/*
+int parseCommandLine(int argc, char * argv[], commandParams_t * params)
+{
+  printf("Parsing Command Line...\n");
+  if (!params)
+    return -1;
+
+  //if no command line parameters were specified, set to defaults
+  if (argc == 1) {
+    printf("No port was specified for listening for client connections."
+           "  Defaulting to %d\n", DEFAULTPORT);
+    params->listenPort = DEFAULTPORT;
+  }
+
+  if (!argv)
+    return -1;
+
+  int i;
+  for (i = 1; i < argc; i++) {
+    char * temp = argv[i];
+    if (temp[0] != '-')
+      {
+        printUsage(argv[0]);
+        return -1;
+      }
+
+    switch(temp[1])
+      {
+      case 'h': printUsage(argv[0]);
+        break;
+      case 'p': 
+        {
+          if (i >= argc-1)
+            {
+              printUsage(argv[0]);
+              return -1;
+            }
+          i++;
+          char * portString = argv[i];
+          char * endptr = NULL;
+          int port = strtol(portString, &endptr, 10);
+          if (*endptr != '\0')
+            {
+              printf("Invalid port specified...%s, %d\n", endptr, port);
+              return -1;
+            }
+          if (port < SMALLEST_POSS_LISTEN_PORT)
+            {
+              printf("You cannot listen on a port less than %d.\n",
+                     SMALLEST_POSS_LISTEN_PORT);
+              return -1;
+            }
+          params->listenPort = port;
+          printf("Setting port to listen on to %d.\n", params->listenPort);
+        }
+        break;
+      default: printUsage(argv[0]);
+        return -1;
+        break;
+      }
+  }
+
+  return 0;
+}
+*/
+
+int initConnection(int port)
+{
+  printf("Initializing connection that will be used to listen for " 
+         "clients...\n");
+  int opts = 1;
+  struct sockaddr_in my_addr;
+
+  //get a socket fd
+  if ((listenSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+    printf("\tThere was an error creating a socket\n");
+    return -1;
+  }
+
+  //set up the address struct
+  memset(&my_addr,'\0',sizeof(my_addr));
+  my_addr.sin_family = AF_INET;
+  my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+  my_addr.sin_port = htons(port);
+  
+  setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &opts, sizeof(opts));
+
+  //get the current socket options
+  if ((opts = fcntl(listenSocket, F_GETFL)) < 0) {
+    printf("\tThere was an error getting the socket options.\n");
+    return -1;
+  }
+
+  //set the socket to non blocking
+  opts = (opts | O_NONBLOCK);
+  if (fcntl(listenSocket, F_SETFL, opts) < 0) {
+    printf("\tThere was an error setting the socket to be non blocking.\n");
+    return -1;
+  }
+  
+  //bind the socket to listen on the specified port
+  if (bind(listenSocket, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) {
+    printf("\tThere was an error binding the socket\n");
+    return -1;
+  }
+  
+  return 0;
+}
Index: trunk/code/projects/colonet/ColonetServer/ConnectionPool.cpp
===================================================================
--- trunk/code/projects/colonet/ColonetServer/ConnectionPool.cpp	(nonexistent)
+++ trunk/code/projects/colonet/ColonetServer/ConnectionPool.cpp	(revision 11)
@@ -0,0 +1,442 @@
+/**
+ * @author Jason Knichel
+ * @date 7/22/07
+ */
+
+#include <sys/select.h>
+#include <ctype.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "includes/ConnectionPool.h"
+#include "includes/client.h"
+#include "../lib/colonet_defs.h"
+
+ConnectionPool::ConnectionPool() {
+  max_file_descriptor = 0;
+  next_available_slot = 0;
+  number_clients_ready = 0;
+
+  FD_ZERO(&ready_set);
+  FD_ZERO(&read_set);
+  FD_ZERO(&write_set);
+
+  memset(&client_file_descriptor_array, 0, sizeof(int)*MAX_CONNECTIONS);
+  memset(&read_buffer, 0, sizeof(char *)*MAX_CONNECTIONS);
+  memset(&read_buffer_size, 0, sizeof(int)*MAX_CONNECTIONS);
+  memset(&write_buffer, 0, sizeof(char *)*MAX_CONNECTIONS);
+  memset(&write_buffer_size, 0, sizeof(int)*MAX_CONNECTIONS);
+}
+
+ConnectionPool::~ConnectionPool() {
+}
+
+int ConnectionPool::add_client(int client_file_descriptor) {
+  if (client_file_descriptor < 0) {
+    return ERROR_INVALID_CLIENT_DESCRIPTOR;
+  }
+
+  if (next_available_slot == MAX_CONNECTIONS) {
+    return ERROR_TOO_MANY_CLIENTS;
+  }
+
+  if (client_file_descriptor > max_file_descriptor) {
+    max_file_descriptor = client_file_descriptor;
+  }
+
+  FD_SET(client_file_descriptor, &ready_set);
+
+  int next_slot = next_available_slot;
+
+  client_file_descriptor_array[next_slot] = client_file_descriptor;
+  read_buffer[next_slot] = (char*) malloc(sizeof(char) * READ_BUFFER_SIZE);
+  if (!(read_buffer[next_slot])) {
+    return ERROR_ALLOCATING_MEMORY;
+  }
+  read_buffer_size[next_slot] = 0;
+  write_buffer[next_slot] = (char *)malloc(sizeof(char) * WRITE_BUFFER_SIZE);
+
+  if (!(write_buffer[next_slot])) {
+    free(read_buffer[next_slot]);
+    return ERROR_ALLOCATING_MEMORY;
+  }
+
+  write_buffer_size[next_slot] = 0;
+
+  next_available_slot++;
+
+  return 0;
+}
+
+int ConnectionPool::remove_client(int client_file_descriptor) {
+  if (client_file_descriptor < 0 || client_file_descriptor >= next_available_slot) {
+    return ERROR_INVALID_CLIENT_DESCRIPTOR;
+  }
+
+  int clientfd = client_file_descriptor_array[client_file_descriptor];
+
+  if (FD_ISSET(clientfd, &ready_set)) {
+    FD_CLR(clientfd, &ready_set);
+  }
+  if (FD_ISSET(clientfd, &read_set)) {
+    FD_CLR(clientfd, &read_set);
+  }
+  if (FD_ISSET(clientfd, &write_set)) {
+    FD_CLR(clientfd, &write_set);
+  }
+
+  free(read_buffer[client_file_descriptor]);
+  free(write_buffer[client_file_descriptor]);
+  for (int j = client_file_descriptor; j < next_available_slot - 1; j++) {
+    client_file_descriptor_array[client_file_descriptor] = client_file_descriptor_array[client_file_descriptor+1];
+    read_buffer[client_file_descriptor] = read_buffer[client_file_descriptor+1];
+    read_buffer_size[client_file_descriptor] = read_buffer_size[client_file_descriptor+1];
+    write_buffer[client_file_descriptor] = write_buffer[client_file_descriptor+1];
+    write_buffer_size[client_file_descriptor] = write_buffer_size[client_file_descriptor+1];
+  }
+  next_available_slot--;
+  int temp_max_file_descriptor = 0;
+
+  for (int j = 0; j < next_available_slot; j++) {
+    if (client_file_descriptor_array[j] > temp_max_file_descriptor)
+      temp_max_file_descriptor = client_file_descriptor_array[j];
+  }
+  max_file_descriptor = temp_max_file_descriptor;
+
+  printf("Removing client.\n");
+
+  return 0;
+}
+
+//TODO: test that it drops commands properly if it gets sent too much data
+//      do we want it to drop the data or drop the connection?
+//TODO: give variables a better name
+int ConnectionPool::check_clients() {
+  char temp[READ_BUFFER_SIZE];
+  char tempCommand[READ_BUFFER_SIZE+1];
+  int i;
+  int client_file_descriptor;
+  int n;
+  int len;
+  int sent;
+  int commandLen;
+
+  for (i = 0; i < next_available_slot; i++) {
+    client_file_descriptor = client_file_descriptor_array[i];
+
+    if (FD_ISSET(client_file_descriptor, &read_set)) {
+      n = read(client_file_descriptor, temp, READ_BUFFER_SIZE);
+
+      if (n == 0 || (n == -1 && errno == ECONNRESET)) {
+        remove_client(i);
+        i--;
+        continue;
+      }
+
+      while (n > 0) {
+        len = n;
+
+        if (len + read_buffer_size[i] > READ_BUFFER_SIZE) {
+          len = READ_BUFFER_SIZE - read_buffer_size[i];
+        }
+
+        memcpy(read_buffer[i]+read_buffer_size[i], temp, len);
+        read_buffer_size[i] += len;
+        n -= len;
+
+        if (n > 0) {
+          memmove(temp, temp+len, READ_BUFFER_SIZE - len);
+        }
+
+        printf("Read buffer is %s\n", read_buffer[i]);
+
+        char* newLine;
+
+        while ((newLine = strstr(read_buffer[i], "\n"))) {
+
+          //if no newline if found in the entire readbuffer (when its full), 
+          //toss out the command
+          // because either the command being given is too long or someone is trying
+          // to do something bad to the server
+          //TODO: this is from before all this code was put in the loop.  reconsider
+          //      how to check this error condition and do it elsewhere
+          if (!newLine && (read_buffer_size[i] == READ_BUFFER_SIZE)) {
+            read_buffer_size[i] = 0;
+            break;
+          }
+
+          //if no newline is found then there is not a command in the buffer
+          if (!newLine) {
+            break;
+          }
+
+          commandLen = (newLine - read_buffer[i])+1;
+
+          //the newline was found in garbage in the currently not used portion
+          // of the read buffer
+          if (commandLen > read_buffer_size[i]) {
+            break;
+          }
+
+          memcpy(tempCommand, read_buffer[i], commandLen);
+          //do commandLen-1 to get rid of the newline terminating the command
+          tempCommand[commandLen-1] = '\0';
+          //did this because telnet was putting a \r\n on the end instead of just \n
+          if (isspace(tempCommand[commandLen-2])) {
+            tempCommand[commandLen-2] = '\0';
+          }
+
+          memmove(read_buffer[i], read_buffer[i]+commandLen, read_buffer_size[i] - commandLen);
+          read_buffer_size[i] -= commandLen;
+
+          if (commandLen > MAX_COMMAND_LEN) {
+            printf("The command was too long.  Tossing command out.\n");
+            break;
+          }
+
+          if (parse_command(tempCommand, i) < 0) {
+            printf("There was an error parsing command\n");
+            break;
+          }
+        }
+      }
+    }
+
+    if (FD_ISSET(client_file_descriptor, &write_set)) {
+      if (write_buffer_size[i] == 0) {
+        continue;
+      }
+
+      sent = write(client_file_descriptor, write_buffer[i], write_buffer_size[i]);
+      memmove(write_buffer[i], write_buffer[i]+sent, WRITE_BUFFER_SIZE - sent);
+      write_buffer_size[i] -= sent;
+    }
+  }
+
+  return 0;
+}
+
+
+//TODO: put error checking on listen_socket to make sure its a valid socket
+void ConnectionPool::set_listen_socket_in_ready_set(int listen_socket) {
+  FD_SET(listen_socket, &ready_set);
+}
+
+int ConnectionPool::perform_select(int listen_socket, struct timeval * select_timeout) {
+  read_set = ready_set;
+  write_set = ready_set;
+
+  //TODO(Jason): think about why I put this there
+  if (max_file_descriptor < listen_socket)
+    max_file_descriptor = listen_socket;
+
+  number_clients_ready = select(max_file_descriptor+1, &(read_set), &(write_set), NULL, select_timeout);
+
+  return 0;
+}
+
+int ConnectionPool::is_socket_ready_to_read(int socket) {
+  return FD_ISSET(socket, &read_set);
+}
+
+int ConnectionPool::is_socket_ready_to_write(int socket) {
+  return FD_ISSET(socket, &write_set);
+}
+
+int ConnectionPool::get_max_file_descriptor() {
+  return max_file_descriptor;
+}
+
+void ConnectionPool::set_max_file_descriptor(int new_max_file_descriptor) {
+  max_file_descriptor = new_max_file_descriptor;
+}
+
+int ConnectionPool::get_next_available_slot() {
+  return next_available_slot;
+}
+
+int ConnectionPool::get_number_clients_ready() {
+  return number_clients_ready;
+}
+
+void ConnectionPool::set_number_clients_ready(int new_number_clients_ready) {
+  number_clients_ready = new_number_clients_ready;
+}
+
+fd_set ConnectionPool::get_ready_set() {
+  return ready_set;
+}
+
+fd_set ConnectionPool::get_read_set() {
+  return read_set;
+}
+
+void ConnectionPool::set_read_set(fd_set new_set) {
+  read_set = new_set;
+}
+
+fd_set ConnectionPool::get_write_set() {
+  return write_set;
+}
+
+void ConnectionPool::set_write_set(fd_set new_set) {
+  write_set = new_set;
+}
+
+//TODO: remove after a write_to_client or similar method is written so this won't be needed anymore
+int ConnectionPool::get_write_buffer_size(int pool_index) {
+  return write_buffer_size[pool_index];
+}
+
+//TODO: remove after a write_to_client or similar method is written so this won't be needed anymore
+void ConnectionPool::set_write_buffer_size(int pool_index, int new_buffer_size) {
+  write_buffer_size[pool_index] = new_buffer_size;
+}
+
+//TODO: remove after a write_to_client or similar method is written so this won't be needed anymore
+char * ConnectionPool::get_write_buffer(int pool_index) {
+  return write_buffer[pool_index];
+}
+
+//TODO: write a function to write data into the write buffers
+//TODO: fix names of variables to obey new style
+int ConnectionPool::parse_command(char* command, int pool_index) {
+  char tokens[MAX_TOKENS][MAX_TOKEN_SIZE];
+  unsigned char int_tokens[MAX_TOKENS];
+  int numTokens = 0;
+  char* endptr = NULL;
+  int commandID;
+  int i;
+  unsigned char args[PACKET_DATA_LEN];
+
+  memset(args, 1, PACKET_DATA_LEN);
+
+  if (!command) {
+    return -1;
+  }
+
+  if (pool_index < 0) {
+    return -1;
+  }
+
+  if (pool_index >= next_available_slot) {
+    return -1;
+  }
+
+  if ((numTokens = tokenize_command(command, tokens)) < 0) {
+    return -1;
+  }
+
+  //the 10 in the function call indicates number is base 10
+  commandID = strtol(tokens[0], &endptr, 10);
+
+  if (!endptr || *endptr != '\0') {
+    printf("There was an error converting first token into a number.\n");
+    return -1;
+  }
+
+  if (commandID == SEND_TO_ROBOT || REQUEST_FROM_ROBOT) {
+    int numIntTokens = numTokens;
+
+    /* Convert tokens to ints */
+    for (i = ROBOT_COMMAND_OFFSET; i < numIntTokens; i++) {
+      int_tokens[i-ROBOT_COMMAND_OFFSET] = atoi(tokens[i]);
+    }
+    if (commandID == REQUEST_FROM_ROBOT) {
+      if (i < MAX_TOKENS) {
+        for (;i >= 4; i--) {
+          int_tokens[i] = int_tokens[i-1];
+        }
+        int_tokens[3] = pool_index;
+        numIntTokens++;
+      } else {
+        //TODO: send an error back to client here also
+        fprintf(stderr, "Client attempted to request data from the robot but there was not enough room to put in the client's id.\n");
+        return -1;
+      }
+    }
+
+    /* Fill args buffer with args */
+    for (i = ROBOT_COMMAND_LEN; i < numIntTokens-ROBOT_COMMAND_OFFSET; i++) {
+      args[i-ROBOT_COMMAND_LEN] = int_tokens[i];
+    }
+
+    /* Check the tokens */
+    if (check_tokens(int_tokens, numIntTokens) < 0) {
+      fprintf(stderr, "%s: Error - Invalid command/request.\n", __FUNCTION__);
+      return 0;
+    }
+  
+    /* Send packet to robot */
+    fprintf(stderr, "Calling wireless->send(%d, %d, %d, args)\n", 
+            int_tokens[0], int_tokens[1], int_tokens[2]);
+    send_wireless_message(int_tokens[0], int_tokens[1], int_tokens[2], args);
+  }
+
+  return 0;
+}
+
+int ConnectionPool::tokenize_command(char* command, char tokens[MAX_TOKENS][MAX_TOKEN_SIZE]) {
+  char* nextToken = command;
+  char* endToken = NULL;
+  int numTokens = 0;
+
+  if (!command) {
+    return -1;
+  }
+
+  while ((endToken = strstr(nextToken, " "))) {
+    *endToken = '\0';
+
+    if (strlen(nextToken) > MAX_TOKEN_SIZE-1) {
+      return -1;
+    }
+
+    strcpy(tokens[numTokens], nextToken);
+
+    numTokens++;
+    nextToken = endToken + 1;
+
+    while (isspace(*nextToken) && *nextToken != '\0') {
+      nextToken++;
+    }
+  }
+
+  if (endToken == NULL && *nextToken != '\0') {
+    if (strlen(nextToken) > MAX_TOKEN_SIZE-1) {
+      return -1;
+    }
+
+    strcpy(tokens[numTokens], nextToken);
+
+    numTokens++;
+  }
+
+  return numTokens;
+}
+
+/** @brief checks a list of tokens to see if it's valid
+ *
+ * @return 0 if tokens is valid
+ */
+int ConnectionPool::check_tokens(unsigned char* tokens, int numTokens) {
+  if (numTokens > 3 + PACKET_DATA_LEN) {
+    /* Too many tokens */
+    return -1;
+  }
+
+  if (numTokens < 3) {
+    /* Not enough tokens */
+    return -1;
+  }
+  
+  if (tokens[1] != COLONET_REQUEST && tokens[1] != COLONET_COMMAND) {
+    /* Invalid message type */
+    return -1;
+  }
+
+  return 0;
+}
Index: trunk/code/projects/colonet/ColonetServer/ColonetServer.cpp
===================================================================
--- trunk/code/projects/colonet/ColonetServer/ColonetServer.cpp	(nonexistent)
+++ trunk/code/projects/colonet/ColonetServer/ColonetServer.cpp	(revision 11)
@@ -0,0 +1,109 @@
+/** @file ColonetServer.cpp
+ *
+ * @brief colonet_server - primary server application for Colonet
+ *
+ * @author Jason Knichel
+ * @author Eugene Marinelli
+ * @date 10/31/06
+ */
+
+#include <colonet_wireless.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <arpa/inet.h>
+
+#include "includes/initialization.h"
+#include "includes/ConnectionPool.h"
+#include "includes/client.h"
+#include "includes/options.h"
+#include "includes/Logging.h"
+
+#define LISTEN_BACKLOG 5
+#define LOG_BUFFER_LENGTH 128
+
+int listenSocket = 0;
+ConnectionPool connection_pool;
+Log * logger;
+
+int main(int argc, char** argv) {
+  if (initializeServer(argc, argv) < 0) {
+    printf("\t\nThere was an error initializing the server. "
+           "Terminating server...\n");
+    return -1;
+  }
+
+  if (listen(listenSocket, LISTEN_BACKLOG) < 0) {
+    printf("\t\nThere was an error telling the socket to "
+           "listen for connections from clients.  Terminating Server...\n");
+    return -1;
+  }
+
+  connection_pool.set_listen_socket_in_ready_set(listenSocket);
+
+  //TODO: why is all of this in that if statement and not just conn_pool.maxfd = listenSocket ?
+  if (listenSocket > connection_pool.get_max_file_descriptor()) {
+    connection_pool.set_max_file_descriptor(listenSocket);
+
+    int acceptSocket = 0;
+    struct sockaddr_in clientAddr;
+    socklen_t clen = sizeof(clientAddr);
+    struct timeval selectTimeout;
+    
+    memset(&selectTimeout,0,sizeof(selectTimeout));
+
+    logger->logMessage(LOG_TYPE_MESSAGE, "Server initialized.  About to start listening for connections");
+
+    while(1) {
+      connection_pool.perform_select(listenSocket, &selectTimeout);
+
+      //either no descriptors are ready or there was an error
+      //TODO: check for specific errors
+      if (connection_pool.get_number_clients_ready() <= 0) {
+        continue;
+      }
+
+      if (connection_pool.is_socket_ready_to_read(listenSocket)) {
+        printf("Something is trying to connect...\n");
+        if ((acceptSocket = accept(listenSocket, (struct sockaddr*) &clientAddr, &clen)) < 0) {
+          if (errno == EMFILE) {
+            printf("\tWhen attempting to accept a connection, "
+                   "reached the per process limit of file descriptors."
+                   "  Dropping the new connection.\n");
+            continue;
+          } else {
+            printf("\tThere was an error when attempting to accept a "
+                   "connection");
+          }
+          continue;
+        }
+
+        char logBuffer[LOG_BUFFER_LENGTH];
+        snprintf(logBuffer, LOG_BUFFER_LENGTH, "Client at address %s attempting to connect.", inet_ntoa(clientAddr.sin_addr));
+        logger->logMessage(LOG_TYPE_CONNECT, logBuffer);
+
+        //TODO: remove this
+        //printf("Attempting to add a client.\n");
+
+
+        if (connection_pool.add_client(acceptSocket) < 0) {
+          printf("\tThere was an error when trying to add a client to the "
+                 "connection pool.");
+          continue;
+        }
+
+        snprintf(logBuffer, LOG_BUFFER_LENGTH, "Client at address %s successfully added to connection pool.", inet_ntoa(clientAddr.sin_addr));
+        logger->logMessage(LOG_TYPE_CONNECT, logBuffer);
+        
+      }
+
+      if (connection_pool.check_clients() < 0) {
+        printf("\tThere was an error trying to update the clients.");
+        continue;
+      }
+    }
+  }
+
+   return 0;
+}
Index: trunk/code/projects/colonet/ColonetServer/options.c
===================================================================
--- trunk/code/projects/colonet/ColonetServer/options.c	(nonexistent)
+++ trunk/code/projects/colonet/ColonetServer/options.c	(revision 11)
@@ -0,0 +1,80 @@
+/**
+ * @file options.c
+ * @brief Options for ColonetServer
+ * @author Eugene Marinelli
+ * @date 2/13/07
+ *
+ * @bug Usage not written
+ */
+
+#include <stdio.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <colonet_defs.h>
+
+#include "includes/options.h"
+
+ColonetServerOptionsT optionsG;
+
+static void printUsage()
+{
+  printf("USAGE:\n");
+}
+
+void parseCmdLine(int argc, char** argv)
+{
+  int c;
+
+  memset(&optionsG, 0, sizeof(ColonetServerOptionsT));
+  
+  if (argc < 2) {
+    printf("No port was specified for listening for client connections."
+           "  Defaulting to %d\n", DEFAULTPORT);
+  }
+
+  /* Defaults */
+  optionsG.listen_port = DEFAULTPORT;
+  strcpy(optionsG.wireless_port, USB_PORT);
+  optionsG.logging_enabled = false;
+  optionsG.listener_mode = false;
+
+  /* Parse args */
+  while (1) {
+    c = getopt(argc, argv, "p:l:w:su");
+
+    if (c == -1) {
+      break;
+    }
+    
+    switch (c) {
+    case 'p':
+      /* Listen port */
+      optionsG.listen_port = atoi(optarg);
+      
+      if (optionsG.listen_port < SMALLEST_POSS_LISTEN_PORT) {
+        printf("You cannot listen on a port less than %d.\n", 
+               SMALLEST_POSS_LISTEN_PORT);
+        printf("Setting listener port to %d\n", DEFAULTPORT);
+        optionsG.listen_port = DEFAULTPORT;
+      }
+      break;
+    case 'w':
+      /* Set wireless port */
+      strcpy(optionsG.wireless_port, optarg);
+      break;
+    case 'l':
+      /* Set log filename (and enable logging) */
+      strcpy(optionsG.log_filename, optarg);
+      optionsG.logging_enabled = true;
+      break;
+    case 's':
+      /* Enable listener mode */
+      optionsG.listener_mode = true;
+      break;
+    case 'u':
+      printUsage();
+    }
+  }
+}
Index: trunk/code/projects/colonet/ColonetServer/Makefile
===================================================================
--- trunk/code/projects/colonet/ColonetServer/Makefile	(nonexistent)
+++ trunk/code/projects/colonet/ColonetServer/Makefile	(revision 11)
@@ -0,0 +1,26 @@
+# ColonetServer makefile
+
+CC = g++
+CFLAGS = -Wall -Wshadow -Wextra -g
+
+COLONETCPPFILES = ColonetServer.cpp client.cpp ConnectionPool.cpp
+COLONETCPPOBJECTS = $(COLONETCPPFILES:.cpp=.o)
+COLONETFILES = initialization.c options.c
+COLONETOBJECTS = $(COLONETFILES:.c=.o)
+LOGGINGFILES = Logging.cpp
+LOGGINGOBJECTS = $(LOGGINGFILES:.cpp=.o)
+
+.PHONY : all clean
+
+all: ColonetServer
+
+#TODO: make a variable that handles the multiple -I blah stuff so it doesn't have to be written on every line
+#TODO: make use of VPATH or vpath directive to point at lib directory and then use -lcolonet_wireless
+ColonetServer: $(COLONETCPPFILES) $(COLONETFILES) $(LOGGINGFILES) ../lib/libcolonet_wireless.a
+	$(CC) $(CFLAGS) -c $(COLONETFILES) -I ../lib/colonet_wireless -I ../lib
+	$(CC) $(CFLAGS) -c $(COLONETCPPFILES) -I ../lib/colonet_wireless -I ../lib
+	$(CC) $(CFLAGS) -c $(LOGGINGFILES) -I ../lib/colonet_wireless -I ../lib
+	$(CC) $(CFLAGS) $(COLONETOBJECTS) $(COLONETCPPOBJECTS) $(LOGGINGOBJECTS) -lpthread -I../lib/colonet_wireless -I../lib -o $@ -L../lib -lcolonet_wireless
+
+clean: 
+	rm -rf *.o ColonetServer
