Beispiel #1
0
int Delay(int ticks)
{
  int clock_tid;
  int r, t = MyTid();
  char msg[5];
  char *ip;

  clock_tid = WhoIs("clck");
  clock_tid = 2;

  msg[0] = 'd';
  ip = (char *)&ticks;
  msg[1] = *ip++;
  msg[2] = *ip++;
  msg[3] = *ip++;
  msg[4] = *ip++;
  DPRINT("Delayed tid %d with msg \'%x%x%x%x%x\' to server at tid %d\r\n",
         MyTid(), msg[0], msg[1], msg[2], msg[3], msg[4], clock_tid);

  //if (t == 5) { bwputstr(COM2, "YAYA\r\n"); }
  r = Send(clock_tid, msg, 5, NULL, 0);
  if (r < 0) {
    DPRINTERR("Send() from inside Delay() failed with retval %d\r\n", r);
    PANIC;
  }
  return 0;
}
void task_codes (){

	kprintf("Task id: %d\tParent task id: %d\n\r", MyTid(), MyParentTid());
	Pass();
	kprintf("Task id: %d\tParent task id: %d\n\r", MyTid(), MyParentTid());
	
	Exit();
	kprintf ("Unexpected return from Exit() at task_codes\n\r");
}
Beispiel #3
0
void other_user_task()
{
  bwprintf(COM2, "My TID is %d and my parent's TID is %d.\n",
           MyTid(), MyParentTid());
  Pass();
  bwprintf(COM2, "My TID is %d and my parent's TID is %d.\n",
           MyTid(), MyParentTid());
  Exit();
}
Beispiel #4
0
void lol()
{
  int i;
  bwprintf(COM2, "HAHA! I'm a new user task and my tid is '%d'\n", MyTid());
  for(i = 0; i < 50000; ++i);
  Exit();
}
Beispiel #5
0
void switch_server() {
    server_tid = MyTid();

    switches_init();

    // Find the location server.
    tid_t location_server_tid = -2;
    do {
        location_server_tid = WhoIs("LocationServer");
        dlog("Location Server Tid %d\n", location_server_tid);
    } while (location_server_tid < 0);

    tid_t tid;
    SwitchServerMessage msg, reply;
    while (1) {
        Receive(&tid, (char *) &msg, sizeof(msg));
        switch (msg.type) {
        case SET_SWITCH:
            reply.type = SET_SWITCH_RESPONSE;
            Reply(tid, (char *) &reply, sizeof(reply));
            switch_set(msg.switch_no, msg.direction, location_server_tid);
            break;
        default:
            break;
        }
    }
}
static void SensorSlave() {
    SensorRequest_t t;
    int status, byte;
    unsigned int i, j, index, parent;
    volatile uint32_t sensors[TRAIN_SENSOR_COUNT * TRAIN_MODULE_COUNT] = {0};

    parent = MyParentTid();

    debug("SensorSlave: Tid %d", MyTid());
    t.type = SENSOR_RETURNED;
    t.sensor = (uint32_t)sensors;

    while (true) {
        pollSensors();
        for (i = 0; i < TRAIN_MODULE_COUNT; ++i) {
            index = i * TRAIN_SENSOR_COUNT;

            byte = trgetchar();
            for (j = 0; j < TRAIN_SENSOR_COUNT / 2; ++j) {
                sensors[index++] = EXTRACT_BIT(byte, (TRAIN_SENSOR_COUNT / 2) - j - 1) & 1;
            }

            byte = trgetchar();
            for (; j < TRAIN_SENSOR_COUNT; ++j) {
                sensors[index++] = EXTRACT_BIT(byte, TRAIN_SENSOR_COUNT - j - 1) & 1;
            }
        }
        Send(parent, &t, sizeof(t), &status, sizeof(status));
    }

    Exit();
}
Beispiel #7
0
void RPSClient_Initialize(RPSClient * client) {
	client->tid = MyTid();
	RNG_Initialize(&client->rng, client->tid);
	client->server_id = WhoIs((char*) RPS_SERVER_NAME);
	client->num_rounds_to_play = 5;
	client->running = 1;
}
Beispiel #8
0
void RPSClient_Start() {
	robprintfbusy((const unsigned char *)"RPSClient created, tid=%d\n", MyTid());
	RPSClient client;
	RPSClient_Initialize(&client);

	// Want to play
	robprintfbusy((const unsigned char *)"Client: %d - I want to play\n", client.tid);

	RPSMessage * send_message;
	RPSMessage * reply_message;

	send_message = (RPSMessage *) client.send_buffer;
	send_message->message_type= MESSAGE_TYPE_SIGN_UP;
	Send(client.server_id, client.send_buffer, MESSAGE_SIZE, client.reply_buffer,MESSAGE_SIZE);
	reply_message = (RPSMessage *) client.reply_buffer;

	assert(reply_message->message_type == MESSAGE_TYPE_SIGN_UP_OK, "Client didn't sign up successfully");

	int i;
	for (i = 0; i < client.num_rounds_to_play; i++) {
		RPSClient_PlayARound(&client);
		Pass();
		if (!client.running) {
			robprintfbusy((const unsigned char *)"Client: %d - Quiting due to server shutdown\n", client.tid);
			Exit();
		}
	}

	RPSClient_Quit(&client);

	Exit();
}
Beispiel #9
0
void RPSServer_Start() {
	robprintfbusy((const unsigned char *)"RPSServer created tid=%d\n", MyTid());

	int result = RegisterAs((char*) RPS_SERVER_NAME);

	assert(result == 0, "RPSServer_Start failed to register name");

	ChannelDescription terminal_channel;
	terminal_channel.channel = COM2;
	terminal_channel.speed = 115200;
	robsetspeed( &terminal_channel);

	RPSServer server;
	RPSServer_Initialize(&server);

	while(1) {
		RPSServer_ProcessMessage(&server);

		if (!server.running) {
			break;
		}
	}

	robprintfbusy((const unsigned char *)"RPSServer exited\n");

	NameServerMessage * name_server_message = (NameServerMessage *) server.send_buffer;
	NameServerMessage * reply_message = (NameServerMessage *) server.reply_buffer;
	name_server_message->message_type = MESSAGE_TYPE_NAME_SERVER_SHUTDOWN;
	Send(NAMESERVER_TID, server.send_buffer, MESSAGE_SIZE, server.reply_buffer, MESSAGE_SIZE);
	assert(reply_message->message_type==MESSAGE_TYPE_ACK, "RPSServer didn't get ACK from name server");

	Exit();

	assert(0, "Shouldn't see me\n");
}
Beispiel #10
0
main() {
    int taskB, taskC;
    char strWrite[50];

    sprintf(strWrite, "I am TaskA[%d], priority[%d] \n", MyTid(), MyPriority());
    Write(strWrite, strLen(strWrite), WYSE);

    Send(TASK_C, NULL,NULL,NULL,NULL);

    sprintf(strWrite, "TaskA replied from TaskC\n");
    Write(strWrite, strLen(strWrite), WYSE);

    sprintf(strWrite, "I am TaskA[%d], priority[%d] \n", MyTid(), MyPriority());
    Write(strWrite, strLen(strWrite), WYSE);

    Exit();
}
void other_task() {
	int mytid = MyTid();
	int myparenttid = MyParentTid();
	bwprintf( COM2, "My tid: %d\tMy parent tid:%d\n\r", mytid, myparenttid);
	Pass();
	bwprintf( COM2, "My tid: %d\tMy parent tid:%d\n\r", mytid, myparenttid);
	Exit();
}
Beispiel #12
0
static void user_task3() {
  child_2_tid = MyTid();

  int p_tid = MyParentTid();
  assert_int_equals(parent_tid, p_tid, "Basic Test: Child_2 Check Parent Tid");

  Exit();
}
Beispiel #13
0
void NameServer_Initialize(NameServer * ns) {
	ns->num_clients = 0;
	ns->tid = MyTid();

	int i;
	for (i = 0; i < MAX_TASKS + 1; i++) {
		ns->filled[i] = 0;
	}
}
Beispiel #14
0
void clockTick() {
	unsigned int time = 0;
	int tid = MyTid();
	while(1) {
		AwaitEvent(EVENT_TIME_ELAP, NULL, 0);
		time++;
		bwprintf(COM2, "%d: %ds\n", tid, time);
	}
}
Beispiel #15
0
void ipc1 () {
  bwprintf (COM2, "ipc1: I am %d\r\n", MyTid());
  bwprintf (COM2, "ipc1: Registering as LOL\r\n");
  RegisterAs ("LOL"); RegisterAs ("POO");
  bwprintf (COM2, "ipc1: Registration complete.\r\n");
  bwprintf (COM2, "ipc1: WhoIs(\"LOL\") = %d\r\n",WhoIs("LOL"));
  bwprintf (COM2, "ipc1: Exiting.\r\n");
  bwprintf (COM2, "ipc1: WhoIs(\"POO\") = %d\r\n",WhoIs("POO"));
  Exit();
}
Beispiel #16
0
void delayTask() {
  int delayTicks, reply = 0, src;
  Receive(&src, (char *)&delayTicks, sizeof(int));
  Reply(src, (char *)&reply, sizeof(int));

  DelayUntil(delayTicks);

  Send(src, (char *)&delayTicks, sizeof(int), (char *)&reply, sizeof(int));
  Destroy(MyTid());
}
Beispiel #17
0
void sensorWaitTask() {
  int sensorNum, reply = 0, src;
  Receive(&src, (char *)&sensorNum, sizeof(int));
  Reply(src, (char *)&reply, sizeof(int));

  waitOnSensor(sensorNum);

  Send(src, (char *)&sensorNum, sizeof(int), (char *)&reply, sizeof(int));
  Destroy(MyTid());
}
Beispiel #18
0
static void user_task2() {
  int tid = MyTid();
  assert_int_equals(child_1_tid, tid, "Basic Test: Child Check Tid");

  int p_tid = MyParentTid();
  assert_int_equals(parent_tid, p_tid, "Basic Test: Child Check Parent Tid");

  flag = 1;

  Exit();
}
Beispiel #19
0
void ClockServer_Initialize(ClockServer * server) {
	server->tid = MyTid();
	server->ticks = 0;
	server->shutdown = 0;
	server->running = 1;
	
	int tid;
	for (tid = 0; tid < MAX_TASKS + 1; tid++) {
		server->tid_to_delay_until[tid] = 0;
	}
}
int WaitAnySensor() {
    int errno, status;
    SensorRequest_t wait;

    ASSERT(sensor_server_tid >= 0, "server TID not available");

    wait.type = SENSOR_WAIT_ANY;
    errno = Send(sensor_server_tid, &wait, sizeof(wait), &status, sizeof(status));
    ASSERT(errno >= 0, "Error in send: %d got %d, sending to %d", MyTid(), errno, sensor_server_tid);

    return status;
}
// -----------------------------------------------------------------------------------------------------------------------------------------------
// Sensors Server Notifier
// -----------------------------------------------------------------------------------------------------------------------------------------------
void sensors_server_notifier(){
	bwdebug( DBG_SYS, SENSORS_SERVER_DEBUG_AREA, "SENSORS_SERVER_NOTIFIER: enters" );

	// Initialization
	Init_sensor_msg init_msg; 
	Sensor_msg sensor_msg; 
	Cmd_request cmd_request; 
	int sensor_server_tid, my_tid, last_recieved; 
	char *sensor_data; 
	
	bwdebug( DBG_SYS, SENSORS_SERVER_DEBUG_AREA, "SENSORS_SERVER_NOTIFIER: recieving init info" );
	Receive( &sensor_server_tid, (char *)&init_msg, sizeof(init_msg) );
	//Reply( sensor_server_tid, 0, 0 );
	sensor_data = init_msg.sensor_data_buff; 
	
	int cmd_server_tid = WhoIs( COMMAND_SERVER_NAME );
	bwassert( cmd_server_tid >= 0, "SENSORS SERVER: This task requires the command server to be able to operate." ); 
	
	// Reset the sensors
	bwdebug( DBG_SYS, SENSORS_SERVER_DEBUG_AREA, "SENSORS_SERVER_NOTIFIER: Resetting sensors" );
	my_tid = MyTid(); 
	cmd_request.type = QUERY_CMD_REQUEST; 
	cmd_request.cmd.cmd_type = RESET_SENSORS_CMD_TYPE; 	
	cmd_request.cmd.sender_tid = my_tid; 
	Send( cmd_server_tid, ( char * ) &cmd_request, sizeof( cmd_request ), 0, 0  );
	
	// Receive trash?
	bwdebug( DBG_SYS, SENSORS_SERVER_DEBUG_AREA, "SENSORS_SERVER_NOTIFIER: recieving trash" );
	cmd_request.type = QUERY_CMD_REQUEST; 
	cmd_request.cmd.cmd_type = QUERY_SENSORS_CMD_TYPE; 
	cmd_request.cmd.sensors = sensor_data; 
	Send( cmd_server_tid, ( char * ) &cmd_request, sizeof( cmd_request ), 0, 0  ); 

	bwdebug( DBG_SYS, SENSORS_SERVER_DEBUG_AREA, "SENSORS_SERVER_NOTIFIER: Unblocking sensor server" );
	Reply( sensor_server_tid, 0, 0 );
	
	// Configure the messages. 
	sensor_msg.type = SENSOR_DATA_RECEIVED_MSG; 
	
	FOREVER{
		last_recieved = Time();
		
		// Get the data from the command server
		Send( cmd_server_tid, ( char * ) &cmd_request, sizeof( cmd_request ), 0, 0  ); 
		
		// Inform the sensor server that new data arrived
		Send( sensor_server_tid, ( char * ) &sensor_msg, sizeof( sensor_msg ), 0, 0 ); 
		
		//DelayUntil( last_recieved + 100 / SENSOR_QUERY_FREQENCY );
		Delay( 20 );	// 10 
	}
}
int FreeSensor(unsigned int id) {
    int errno, status;
    SensorRequest_t wait;

    ASSERT(sensor_server_tid >= 0, "server TID not available");

    wait.type = SENSOR_FREE;
    wait.sensor = id;
    errno = Send(sensor_server_tid, &wait, sizeof(wait), &status, sizeof(status));

    ASSERT(errno >= 0, "Error in send: %d got %d, sending to %d", MyTid(), errno, sensor_server_tid);

    return status;
}
int LastSensorPoll(unsigned int *data) {
    int errno, status;
    SensorRequest_t poll;

    ASSERT(sensor_server_tid >= 0, "server TID not available");

    poll.type = SENSOR_LAST_POLL;
    poll.sensor = (uint32_t)data;
    errno = Send(sensor_server_tid, &poll, sizeof(poll), &status, sizeof(status));

    ASSERT(errno >= 0, "Error in send: %d got %d, sending to %d", MyTid(), errno, sensor_server_tid);

    return status;
}
Beispiel #24
0
void reverser() {
  int reply = 0, src;
  struct trainInfo info;
  Receive(&src, (char *)&info, sizeof(struct trainInfo));
  Reply(src, (char *)&reply, sizeof(int));

  Delay(250);
  //reverse command
  Putc2(1, (char)15, (char)info.number);
  //back to speed command
  Putc2(1, (char)info.speed, (char)info.number);

  Destroy(MyTid());
}
int WaitWithTimeout(unsigned int id, unsigned int to) {
    int errno, status;
    SensorRequest_t msg;

    ASSERT(sensor_server_tid >= 0, "server TID not available");

    msg.type = SENSOR_WAIT_TIMEOUT;
    msg.sensor = id;
    msg.timeout = to;

    errno = Send(sensor_server_tid, &msg, sizeof(msg), &status, sizeof(status));

    ASSERT(errno >= 0, "Error in send: %d got %d, sending to %d\r\n", MyTid(), errno, sensor_server_tid);

    return status;
}
Beispiel #26
0
void client_code(void) {
    int ptid = MyParentTid();
    int mtid = MyTid();
    int i = 0;
    int ticks = 0, times = 0;
    struct dr req;
    Send(ptid, &req, sizeof(struct dr), &req, sizeof(struct dr));
    ticks = req.ticks;
    times = req.iters;
    for(i = 0; i < times; i++) {
        DEBUG("task %d calls delay()", mtid);
        Delay(req.ticks);
        kprintf("Tid: %d\tDelay Interval: %d ms\t Times:%d\n\r", mtid, ticks*10, i+1);
    }
    kprintf("Task %d exits\n\r", mtid);
    Exit();
}
Beispiel #27
0
void RPSServer_Initialize(RPSServer * server) {
	server->tid = MyTid();
	Queue_Initialize(&server->player_tid_queue);
	server->player_1_tid = 0;
	server->player_2_tid = 0;
	server->is_playing_game = 0;
	server->player_1_choice = NO_CHOICE;
	server->player_2_choice = NO_CHOICE;
	server->running = 1;
	server->games_played = 0;
	server->is_shutdown = 0;

	int i;
	for (i = 0; i < MAX_TASKS + 1; i++) {
		server->signed_in_players[i] = 0;
	}
}
Beispiel #28
0
static void user_task() {
  did_run = 1;
  parent_tid = MyTid();

  child_1_tid = Create(MED_PRI, &user_task2);

  int p_tid = MyParentTid();
  assert_int_equals(-1, p_tid, "Basic Test: Parent Check Parent Tid");

  Pass();
  assert_int_equals(1, flag, "Basic Test: Parent Check Pass");

  // Let child run first to test that the right return value is returned.
  int tid = Create(HI_PRI, &user_task3);
  assert_int_equals(child_2_tid, tid, "Basic Test: Parent Check Child_2 Tid");

  Exit();
}
Beispiel #29
0
void nameServer( )
{
	ns_tid = MyTid();
	int name_space[MAX_NAME_HASH];
	int clientTid, retVal, clientMsg,req;
	for (retVal = 0; retVal < MAX_NAME_HASH; retVal++){
		name_space[retVal] = NS_UNDEFINED_TID;
	}

	while(1)
	{
		//bwprintf(COM2, "nameserver calls receive\n");
		req = Receive( (int *)&clientTid, (char*)&clientMsg, sizeof(int)/sizeof(char) );
		bwprintf(COM2, "nameserver got clientTid: %d, req: %d\n\r", clientTid,req);
		switch ( req ) 
		{
			case ( NS_REGISTER ):
				if ( name_space[clientMsg] == NS_UNDEFINED_TID ) {
					//bwprintf(COM2, "Registering %d to have tid %d\n",clientMsg,clientTid);
					name_space[clientMsg] = clientTid;
					retVal = NS_SUCCESS;
				} else {
					kprintf(COM2, "collision has occured\n");
					retVal = NS_HASH_COLLISION;
				}
				break;
			case ( NS_WHOIS ):
				retVal = name_space[clientMsg];
				retVal = (retVal == NS_UNDEFINED_TID) ? NS_NOT_FOUND : retVal;
				break;
			default :
				//kprintf(COM2, "Invalid who is was made by Tid:%d\n", clientTid);
				retVal = NS_INVALID_REQUEST;
		}
		Reply( clientTid, (char*)&retVal, sizeof( int )/sizeof(char) );
	}
}
Beispiel #30
0
void multitrain_driver() {
  MultiTrainDriver me;

  initDriver(&me);
  unsigned int naggCount = 0;
  unsigned int updateStoppingDistanceCount = 0;

  for (;;) {
    int tid = -1;
    MultiTrainDriverMsg actualMsg;
    DriverMsg* msg = (DriverMsg*)&actualMsg;
    msg->data3 = 0;
    Receive(&tid, (char *)msg, sizeof(MultiTrainDriverMsg));
    if (msg->type != REPORT_INFO &&
        msg->type != QUERY_STOP_COUNT &&
        msg->type != MULTI_TRAIN_DRIVER_COURIER &&
        msg->type != SENSOR_TRIGGER &&
        msg->type != DELTA_DISTANCE) {
      Reply(tid, (char*)1, 0);
    }

    switch (msg->type) {
      case SET_SPEED: {
        if (!me.tailMode) {
          Reply(msg->replyTid, (char*)1, 0);
        }

        groupSetSpeed(&me, msg->data2);
        break;
      }
      case SENSOR_TRIGGER: {
        if (me.tailMode && tid == me.sensorWatcher) {
          Reply(tid, (char *)NULL, 0);
          break;
        }

        if (me.tailMode) {
          int isHandled = 0;
          Send(me.trainId[0],
              (char*)msg, sizeof(DriverMsg), (char *)&isHandled, sizeof(int));
          Reply(tid, (char *)&isHandled, sizeof(int));
        } else {
          int isSensorReserved = QueryIsSensorReserved(&me, msg->data2, msg->data3);
          if (isSensorReserved) {
            // sensor is reserved
            for (int i = 0; i < me.numTrainInGroup; i ++) {
              int isHandled = 0;
              Send(me.trainId[i],
                  (char*)msg, sizeof(DriverMsg), (char *)&isHandled, sizeof(int));
              if (isHandled) {
                break;
              }
            }
          }
          Reply(tid, (char *)NULL, 0);
        }
        break;
      } // case
      case NAVIGATE_NAGGER: {
        if (me.tailMode) break;

        updateInfo(&me);

        if (me.routeRemaining != -1) {
          if (!me.stopCommited) {
            if (shouldStopNow(&me)) {
              if (me.route.nodes[me.stopNode].num == REVERSE) {
                //TrainDebug(&me, "Navi reversing.");
                groupSetSpeed(&me, -1); // reverse
              }
              else {
                //TrainDebug(&me, "Navi Nagger stopping.");
                groupSetSpeed(&me, 0); // stopping
                me.route.length = 0; // Finished the route.
                me.testMode = 0;
                me.routeRemaining = -1;
              }
              me.stopCommited = 1;
              me.useLastSensorNow = 0;
              me.stopNow = 0;
              me.stopSensorHit = 0;
            } else {
              if ((++updateStoppingDistanceCount & 15) == 0) updateStopNode(&me);
            }
          }
        }

        if (me.nextSetSwitchNode != -1 && (++me.setSwitchNaggerCount & 3) == 0) {
          trySetSwitch_and_getNextSwitch(&me);
        }
        if (me.rerouteCountdown-- == 0) {
          if (me.testMode) {
            int reserveStatus = makeReservation(&me, 440);
            if (reserveStatus == RESERVE_FAIL) {
              reroute(&me);
            } else {
              me.nextSetSwitchNode = -1;
              updateSetSwitch(&me);
              groupSetSpeed(&me, 8);
            }
          } else {
            // reroute
            if (me.route.length != 0) {
              setRoute(&me, &(me.info[0].pos), &(me.routeMsg));
            }
          }
        }
        break;
      }
      case UPDATE_PREDICTION: {
        if (me.tailMode) {
          MultiTrainDriverCourierMsg cMsg;
          cMsg.destTid = me.headTid;
          cMsg.msg = actualMsg;
          cMsg.msg.data = MyTid();
          Reply(me.courier, (char *)&cMsg, sizeof(MultiTrainDriverCourierMsg));
          break;
        }

        for (int i = 0; i < MAX_TRAIN_IN_GROUP; i++) {
          if (actualMsg.data == me.trainId[i]) {
            for (int j = 0; j < actualMsg.numSensors; j++) {
              me.sensorToReserve[i][j] = actualMsg.sensors[j];
            }
            me.numSensorToReserve[i] = actualMsg.numSensors;
          }
        }
        makeReservation(&me, me.info[0].maxStoppingDistance);
        break;
      }
      case STOP_COMPLETED: {
        // notify actual train controller.
        if (me.tailMode) {
          MultiTrainDriverCourierMsg cMsg;
          cMsg.destTid = me.headTid;
          cMsg.msg = actualMsg;
          cMsg.msg.data = MyTid();
          Reply(me.courier, (char *)&cMsg, sizeof(MultiTrainDriverCourierMsg));
          break;
        }
        me.stoppedCount++;

        if (me.stoppedCount == me.numTrainInGroup) {
          makeReservation(&me, 1);
          if (me.isReversing) {
            handleReverse(&me);
          } else if (me.route.length != 0) {
            // Reroute.
            setRoute(&me, &(me.info[0].pos), &(me.routeMsg));
          }
        }

        if (!me.reserveTrackMode) {
          clearReservation(me.trackManager, me.trainNum);
        }
        break;
      }
      case SET_ROUTE: {
        Reply(msg->replyTid, (char*)1, 0);
        me.routeMsg = *msg;
        setRoute(&me, &(me.info[0].pos), msg);
        break;
      }
      case GET_POSITION: {
        if (me.tailMode) {
          PrintDebug(me.ui, "Get position from a tail train ??");
          break;
        }
        // If don't have any valid info yet, reply empty message
        if (me.infoUpdater == -1) {
          Reply(msg->replyTid, (char*)1, 0);
        } else {
          Reply(msg->replyTid, (char*)&(me.info[0]), sizeof(DumbDriverInfo));
        }
        break;
      }
      case FIND_POSITION: {
        if (me.tailMode) {
          PrintDebug(me.ui, "find position while merge????");
          break;
        }
        me.reserveTrackMode = (msg->data2 == RESERVE);

        PrintDebug(me.ui, "Train locking %d", me.trainNum);
        // Only 1 train can lock at the same time.
        lock(me.timeserver);
        // begin finding position in a slow speed
        DumbTrainSetSpeed(me.trainId[0], 5);
        Reply(msg->replyTid, (char*)1, 0);
        for (;;) {
          Receive(&tid, (char*)msg, sizeof(MultiTrainDriverMsg));
          Reply(tid, (char*)1, 0);
          if (msg->type == SENSOR_TRIGGER) {
            Send(me.trainId[0], (char*)msg,
                sizeof(DriverMsg), (char*)NULL, 0);
            DumbTrainSetSpeed(me.trainId[0], 0);
            break;
          } else if (msg->type == GET_POSITION) {
            Reply(msg->replyTid, (char*)1, 0);
          } else {
            PrintDebug(me.ui, "WARNN Drop %d", msg->type);
          }
        }
        DriverMsg dMsg;
        dMsg.type = REPORT_INFO;
        for (int i = 0; i < me.numTrainInGroup; i++) {
          Send(me.trainId[i],
              (char *)&dMsg, sizeof(DriverMsg),
              (char*)&me.info[i], sizeof(DumbDriverInfo));
        }
        me.infoUpdater = Create(3, trainNavigateNagger);
        unlock();
        break;
      }
      case MERGE_HEAD: {
        if (me.tailMode) {
          PrintDebug(me.ui, "Cannot be a head when in tail mode??");
          break;
        }
        me.reserveTrackMode = 1; //  Head always reserves track.
        // Other train controller's id.
        me.trainId[me.numTrainInGroup] = msg->data2;
        me.numTrainInGroup++;
        Reply(msg->replyTid, (char*)1, 0);
        DriverMsg dMsg;
        dMsg.type = QUERY_STOP_COUNT;
        int tailStopCount = 0;
        Send(msg->data2, (char *)&dMsg, sizeof(DriverMsg), (char *)&tailStopCount, sizeof(int));
        me.stoppedCount += tailStopCount;

        dMsg.type = UPDATE_PARENT_ABOUT_PREDICTION;
        Send(msg->data2, (char *)&dMsg, sizeof(DriverMsg), (char *)NULL, 0);

        PrintDebug(me.ui, "merged. head is %d", me.trainNum);
        break;
      }
      case MERGE_TAIL: {
        if (me.tailMode) {
          PrintDebug(me.ui, "Double merge tail??");
          break;
        }
        // Enters courier mode that passes dumb_train msg to 'real' controller
        me.tailMode = 1;
        me.headTid = msg->data2;
        clearReservation(me.trackManager, me.trainNum);
        Reply(msg->replyTid, (char*)1, 0);
        PrintDebug(me.ui, "Train %d is tail", me.trainNum);
        break;
      }
      case SEPARATE_TAIL: {
        if (!me.tailMode) {
          PrintDebug(me.ui, "Not in tail mode..??"); break;
        }
        me.tailMode = 0;
        me.headTid = 0;
        // TODO, behaviour is not clearly defined yet.
        // reserve my own track and prediction??
        break;
      }
      case REPORT_INFO: {
        if (!me.tailMode) {
          PrintDebug(me.ui, "Report info Not in tail mode..??"); break;
        }

        // ASSUME ONLY 1 train when in tail mode.
        Send(me.trainId[0], (char*)msg, sizeof(DriverMsg),
            (char*)&me.info[0], sizeof(DumbDriverInfo));
        // Reply the head that made query.
        Reply(me.headTid, (char*)&me.info[0], sizeof(DumbDriverInfo));
        break;
      }
      case DELTA_DISTANCE: {
        if (!me.tailMode) {
          PrintDebug(me.ui, "Delta distance and not in tail mode..??"); break;
        }

        // ASSUME ONLY 1 train when in tail mode.
        Send(me.trainId[0], (char*)msg,
            sizeof(DriverMsg) - sizeof(Position), (char*)1, 0);
        // Reply the head that made query.
        Reply(me.headTid, (char*)1, 0);
        break;
      }
      case UPDATE_PARENT_ABOUT_PREDICTION: {
        if (!me.tailMode) {
          PrintDebug(me.ui, "%d Update Parent Not in tail mode..??", me.trainNum);
          break;
        }
        // ASSUME ONLY 1 train when in tail mode.
        Send(me.trainId[0], (char*)msg, sizeof(DriverMsg),
            (char*)NULL, 0);
        break;
      }
      case QUERY_STOP_COUNT: {
        // asuumption: no tree strucutre
        Reply(tid, (char *)&me.stoppedCount, sizeof(int));
        break;
      }
      case MULTI_TRAIN_DRIVER_COURIER: {
        // nothing
        break;
      }
      case REVERSE_SPEED: {
        if (!me.tailMode) {
          PrintDebug(me.ui, "Reverse Speed Not in tail mode..??"); break;
        }

        for (int i = 0; i < me.numTrainInGroup; i++) {
          Send(me.trainId[i], (char *)msg, sizeof(DriverMsg), (char*)1, 0);
        }
        break;
      }
      case QUERY_STOPPING_DISTANCE: {
        if (!me.tailMode) {
          PrintDebug(me.ui, "Query stopping dist Not in tail mode..??"); break;
        }

        int stoppingDist = 0;
        // ASSUME ONLY 1 train when in tail mode.
        Send(me.trainId[0], (char*)msg, sizeof(DriverMsg),
            (char*)&stoppingDist, sizeof(int));
        // Reply the head that made query.
        Reply(me.headTid, (char*)&stoppingDist, sizeof(int));
        break;
      }
      case HIT_SECONDARY: {
        if (me.route.length != 0) {
          PrintDebug(me.ui, "Hit secondary rerouting..");
          groupSetSpeed(&me, 0);
        }
        break;
      }
      case SET_FOLLOWING_DISTANCE: {
        me.minFollowingDist = msg->data2;
        me.maxFollowingDist = msg->data3;

        Reply(msg->replyTid, (char*)1, 0);
        break;
      }
      default: {
        PrintDebug(me.ui, "Not Handled %d", msg->type);
      }
    } // switch
  } // for
}