diff --git a/src/fw_downloader/CMakeLists.txt b/src/fw_downloader/CMakeLists.txt
index 969571b2a1ea8a07471304992d780861da89a94c..cab8f0f4fe5be61c790ce05b0d51fc5c0f24edf0 100755
--- a/src/fw_downloader/CMakeLists.txt
+++ b/src/fw_downloader/CMakeLists.txt
@@ -18,3 +18,9 @@ ADD_EXECUTABLE(fw_downloader ${sources})
 # link necessary libraries
 TARGET_LINK_LIBRARIES(fw_downloader ${iriutils_LIBRARY})
 TARGET_LINK_LIBRARIES(fw_downloader ${comm_LIBRARY})
+
+INSTALL(TARGETS fw_downloader
+        RUNTIME DESTINATION bin
+        LIBRARY DESTINATION lib/iridrivers
+        ARCHIVE DESTINATION lib/iridrivers)
+
diff --git a/src/fw_downloader/fw_downloader.cpp b/src/fw_downloader/fw_downloader.cpp
index f41efc83e46febd1b57c24bac8db40c97e385400..633665f1968f1274f43fbc717f5020c7f1d5799f 100755
--- a/src/fw_downloader/fw_downloader.cpp
+++ b/src/fw_downloader/fw_downloader.cpp
@@ -10,11 +10,26 @@
 #include <iostream>
 
 const unsigned char bootloader_ping='#';
-const unsigned char bootloader_ack[]="\n";
-//const unsigned char bootloader_load_hex[]="l 0x08003000\n";
-const unsigned char bootloader_load_hex[]="l";
-const unsigned char bootloader_load_motion[]="l 0x08060000\n";
-const unsigned char bootloader_go[]="\ngo\n";
+const unsigned char bootloader_ack='\n';
+const unsigned char bootloader_load='l';
+const unsigned char bootloader_go='g';
+
+typedef enum {original_protocol=0,new_protocol=1} protocol_t;
+
+void show_help(char *name) 
+{
+  std::cout << "Usage: " << name << "-d <serial device> -f <firmware file> -p <protocol> [-h]" << std::endl;
+  std::cout << "       -d serial_device  Linux serial device used to communicate" << std::endl;
+  std::cout << "       -f firmware_file  desired firmware file in Intel Hex format" << std::endl;
+  std::cout << "       -p protocol       Communication protocol to be used (original or new)" << std::endl;
+  std::cout << "                         devices supported by the original protocol:" << std::endl;
+  std::cout << "                         - ax servo family" << std::endl;
+  std::cout << "                         - rx servo family" << std::endl;
+  std::cout << "                         devices supported by the new protocol:" << std::endl;
+  std::cout << "                         - cm510" << std::endl;
+  std::cout << "                         - mx servo family" << std::endl;
+  std::cout << "       -h                shows this help" << std::endl;
+}
 
 int main(int argc,char *argv[])
 {
@@ -25,34 +40,19 @@ int main(int argc,char *argv[])
   TRS232_config serial_config;
   long int num_data=0,i=0;
   bool end=false;
-  // input arguments parser variables
-  static struct option long_options[] = {{"h", no_argument, 0, 0},// display help message
-                                         {"help", no_argument, 0, 0},
-                                         {"d", required_argument, 0, 0},// select the desired output device
-                                         {"device", required_argument, 0, 0},
-                                         {"f", required_argument, 0, 0},// select the desired firmware file
-                                         {"firmware", required_argument, 0, 0},
-                                         {"m", required_argument, 0, 0},// select the desired motion file
-                                         {"motion", required_argument, 0, 0},
-                                         {"s", required_argument, 0, 0},// select the desired servo model
-                                         {"servo", required_argument, 0, 0},
-                                         {0, 0, 0, 0}
-                                        };
-  int opt_status,opt_index;
-  std::string opt_device,opt_fw_file,opt_motion_file,servo_model;
+  int option;
+  std::string opt_device,opt_fw_file;
+  protocol_t protocol;
   // binary file variables
   unsigned char binary_file[MEMORY_MAXSIZE];
-  long int downloaded_size=0,downloaded_block_size=0;
+  long int downloaded_size=0;
   long int start_address=0;
   long int binary_size=0;
-  int block_size=0,count=0,small_block_size=0;
+  int block_size=0,count=0;
   // bootloader variables
   unsigned char bootloader_data[MEMORY_MAXSIZE];
-  bool bootloader_connected=false,error=false;
+  bool bootloader_connected=false;
   unsigned char checksum=0x00;
-  char load_hex_address[32];
-  // motion file variables
-  FILE *motion_fd;
 
   // configuration information for the serial device
   serial_config.baud=57600;
@@ -60,58 +60,47 @@ int main(int argc,char *argv[])
   serial_config.parity=none;
   serial_config.stop_bits=1;
 
-  for(i=0;i<MEMORY_MAXSIZE;i++)
-    binary_file[i]=0xFF;
+  memset(binary_file,0xFF,MEMORY_MAXSIZE);
 
   // parse the input arguments
-  do{
-    opt_status=getopt_long_only(argc,argv,"",long_options,&opt_index);
-    if(opt_status!=-1)
+  while((option = getopt(argc, argv, "hd:f:p:")) != -1) 
+  {
+    switch(option) 
     {
-      if(opt_status=='?')// option not recognized or argument missing
-      {
-        printf("Unknown option \n");
-        return 0;
-        /* handle the error and exit */
-      }
-      else// process the argument
-      {
-        switch(opt_index)
+      case 'h':// show help message
+        show_help(argv[0]);
+        break;
+      case 'd':// select serial device
+        std::cout << "Output device: " << optarg << std::endl;
+        opt_device=std::string(optarg);
+        break;
+      case 'f':// select firmware file
+        std::cout << "Firmware file: " << optarg << std::endl;
+        opt_fw_file=std::string(optarg);
+        break;
+      case 'p':// select protocol
+        std::cout << "Selected protocol: " << optarg << std::endl;
+        if(std::string(optarg)=="original")
+          protocol=original_protocol;
+        else if(std::string(optarg)=="new")
+          protocol=new_protocol;
+        else
         {
-          case 0:
-          case 1: /* display the help information and exit */
-                  break;
-          case 2:
-          case 3: printf("output device: %s\n",optarg);
-                  opt_device=std::string(optarg);
-                  break;
-          case 4:
-          case 5: printf("Hex file: %s\n", optarg);
-                  opt_fw_file=std::string(optarg);
-                  break;
-          case 6:
-          case 7: printf("Motion file: %s\n",optarg);
-                  opt_motion_file=std::string(optarg);
-                  break;
-          case 8:
-          case 9: printf("servo model: %s\n",optarg);
-                  servo_model=std::string(optarg);
-                  break;
+          std::cout << "Unsupported protocol" << std::endl;
+          show_help(argv[0]);
+          return 0;
         }
-      }
+        break;
     }
-  }while(opt_status!=-1);
+  }
+
   // check that the two arguments have been entered
   if(opt_device.size()!=0)
   {
-    if(opt_fw_file.size()!=0 && opt_motion_file.size()!=0)
-    {
-      printf("Only one file can be download at a time.\n");
-      return 0;
-    }
-    else if(opt_fw_file.size()==0 && opt_motion_file.size()==0)
+    if(opt_fw_file.size()==0)
     {
-      printf("At least one file have to be specified.\n");
+      std::cout << "No firmware file has been specified" << std::endl;
+      show_help(argv[0]);
       return 0;
     }
     else
@@ -129,77 +118,55 @@ int main(int argc,char *argv[])
           if(hex2bin((char *)opt_fw_file.c_str(), binary_file, &start_address, &binary_size) == false)
           {
             serial_port.close();
-            printf("Error converting the firmware hex file.\n");
+            std::cout << "Error converting the firmware hex file" << std::endl;
             return 0;
-            /* throw an exception */
           }
         }
-        else
+        std::cout << "Switch off device power and turn it on" << std::endl;
+        // ping the device 
+        while(!bootloader_connected)
         {
-          // the motion file is already a binary file
-          motion_fd = fopen(opt_motion_file.c_str(), "r");
-          if (!motion_fd)
-          {
-            printf("Can not find file!\n");
-            return 0;
-          }
-          fseek(motion_fd, 0, SEEK_END );
-          if(ftell(motion_fd)!=(long)(MEMORY_MAXSIZE/2))
-          {
-            printf("The motion file is too short or too large.\n");
-            return 0;
-          }
-          rewind(motion_fd);
-          // read the contents of the file
-          fread(binary_file,1,MEMORY_MAXSIZE/2,motion_fd);
-          start_address=0;
-          binary_size=MEMORY_MAXSIZE/2;
-          // close the file
-          fclose(motion_fd);
-        }
-        printf("Press DARwIn-OP's Reset button to start...\n");
-        if(servo_model!="cm9")
-        {
-          while(!bootloader_connected)
-          {
-            try{
-              event_server->wait_all(events,20);
-              num_data=serial_port.get_num_data();
-              serial_port.read((unsigned char *)bootloader_data,num_data);
-              bootloader_data[num_data]='\0';
-              printf("%s",bootloader_data);
-              fflush(stdout);
-              for(i=0;i<num_data;i++)
+          try{
+            event_server->wait_all(events,20);
+            num_data=serial_port.get_num_data();
+            serial_port.read((unsigned char *)bootloader_data,num_data);
+            bootloader_data[num_data]='\0';
+            printf("%s",bootloader_data);
+            fflush(stdout);
+            for(i=0;i<num_data;i++)
+            {
+              if(protocol==new_protocol)
               {
-                if(servo_model=="mx28")
+                if(bootloader_data[i]=='#')
                 {
-                  if(bootloader_data[i]=='#')
-                  {
-                    count++;
-                    if(count==5)
-                      bootloader_connected=true;
-                  }
+                  count++;
+                  if(count==5)
+                    bootloader_connected=true;
                 }
-                else if(servo_model=="ax12" || servo_model=="rx28")
+              }
+              else 
+              {
+                if(bootloader_data[i]=='*')
                 {
-                  if(bootloader_data[i]=='*')
-                  {
-                    count++;
-                    if(count==5)
-                      bootloader_connected=true;
-                  }
+                  count++;
+                  if(count==5)
+                    bootloader_connected=true;
                 }
               }
-            }catch(CEventTimeoutException &e){
-              // do nothing and retry
-              serial_port.write((unsigned char *)&bootloader_ping, 1);
             }
+          }catch(CEventTimeoutException &e){
+            // do nothing and retry
+            serial_port.write((unsigned char *)&bootloader_ping, 1);
           }
-          serial_port.write((unsigned char *)bootloader_ack, 1);
+        }
+        if(protocol==new_protocol)
+        {
+          /* send acknowledgment to the device*/
+          serial_port.write((unsigned char *)&bootloader_ack, 1);
           while(!end)
           {
             try{
-              event_server->wait_all(events,3000);
+              event_server->wait_all(events,300);
               num_data=serial_port.get_num_data();
               serial_port.read(bootloader_data,num_data);
               bootloader_data[num_data]='\0';
@@ -210,15 +177,16 @@ int main(int argc,char *argv[])
               end=true;
             }
           }
+          end=false;
         }
-        sleep(1);
-        end=false;
         // start the download
-        serial_port.write((unsigned char *)bootloader_load_hex,1);
+        serial_port.write((unsigned char *)&bootloader_load,1);
+        if(protocol==new_protocol)
+          serial_port.write((unsigned char *)&bootloader_ack,1);
         while(!end)
         {
           try{
-            event_server->wait_all(events,3000);
+            event_server->wait_all(events,300);
             num_data=serial_port.get_num_data();
             serial_port.read(bootloader_data,num_data);
             bootloader_data[num_data]='\0';
@@ -229,126 +197,6 @@ int main(int argc,char *argv[])
             end=true;
           }
         }
-        sleep(1);
-/*        if(servo_model=="mx28")
-        {
-          end=false;
-          serial_port.write((unsigned char *)bootloader_ack, 1);
-          while(!end)
-          {
-            try{
-              event_server->wait_all(events,3000);
-              num_data=serial_port.get_num_data();
-              serial_port.read(bootloader_data,num_data);
-              bootloader_data[num_data]='\0';
-              printf("%s",bootloader_data);
-              fflush(stdout);
-            }catch(CEventTimeoutException &e){
-              // the flash has been properly erased
-              end=true;
-            }
-          }
-          sleep(1);
-        }*/
-/*        end=false;
-        while(downloaded_size < binary_size)
-        {
-          sleep(1);
-          end=false;
-          sprintf(load_hex_address,"l 0x%08x\n",(int)(0x08000000+start_address+downloaded_size));
-          serial_port.write((unsigned char *)load_hex_address, strlen(load_hex_address));
-          while(!end)
-          {
-            try{
-              event_server->wait_all(events,1000);
-              error=true;
-              num_data=serial_port.get_num_data();
-              serial_port.read(bootloader_data,num_data);
-              bootloader_data[num_data]='\0';
-              printf("%s",bootloader_data);
-              fflush(stdout);
-            }catch(CEventTimeoutException &e){
-              // the flash has been properly erased
-              if(error)
-              {
-                serial_port.close();
-                return 0;
-              }
-              else
-                end=true;
-            }
-          }
-          sleep(1);
-          if(servo_model=="mx28")
-          {
-            error=false;
-            end=false;
-            serial_port.write((unsigned char *)bootloader_ack, 1);
-            while(!end)
-            {
-              try{
-                event_server->wait_all(events,3000);
-                num_data=serial_port.get_num_data();
-                serial_port.read(bootloader_data,num_data);
-                bootloader_data[num_data]='\0';
-                printf("%s",bootloader_data);
-                fflush(stdout);
-              }catch(CEventTimeoutException &e){
-                // the flash has been properly erased
-                if(error)
-                {
-                  serial_port.close();
-                  return 0;
-                }
-                else
-                  end=true;
-              }
-            }
-            sleep(1);
-          }
-          block_size=binary_size-downloaded_size;
-          if(block_size>64*1024)
-            block_size=64*1024;
-          // compute the binary file checksum
-          checksum=0;
-          for(i=0;i<block_size;i++)
-            checksum+=binary_file[start_address+downloaded_size+i];
-          downloaded_block_size=0;
-          while(downloaded_block_size < block_size)
-          {
-            usleep(1000);
-            small_block_size=block_size-downloaded_block_size;
-            if(small_block_size>64)
-              small_block_size=64;
-            serial_port.write(&binary_file[start_address+downloaded_size+downloaded_block_size],small_block_size);
-            downloaded_block_size+=small_block_size;
-            printf("\rDownloading Firmware (%ld/%ld byte)", downloaded_block_size, block_size);
-          }
-          downloaded_size+=block_size;
-          serial_port.write(&checksum,1);
-          sleep(1);
-          end=false;
-          while(!end)
-          {
-            try{
-              event_server->wait_all(events,3000);
-              // there has been an error
-              num_data=serial_port.get_num_data();
-              serial_port.read(bootloader_data,num_data);
-              bootloader_data[num_data]='\0';
-              printf("%s",bootloader_data);
-            }catch(CEventTimeoutException &e){
-              // no error to report
-              if(error)
-              {
-                serial_port.close();
-                return 0;
-              }
-              else
-                end=true;
-            }
-          }
-        }*/
         // compute the binary file checksum
         for(i=0;i<binary_size;i++)
           checksum+=binary_file[start_address+i];
@@ -356,31 +204,22 @@ int main(int argc,char *argv[])
         while(downloaded_size < binary_size)
         { 
           usleep(1000);
-          if((num_data=serial_port.get_num_data())!=0)
-          {
-            serial_port.read(bootloader_data,num_data);
-            bootloader_data[num_data]='\0';
-            printf("%s",bootloader_data);
-            return 0;
-          }
           block_size=binary_size-downloaded_size;
-//          if(block_size>64)
-//            block_size=64;
-          block_size=binary_size;
+          if(block_size>64)
+            block_size=64;
           serial_port.write(&binary_file[start_address+downloaded_size],block_size);
           downloaded_size+=block_size;
           printf("\rDownloading Firmware (%ld/%ld byte)", downloaded_size, binary_size);
-          sync();
+          fflush(stdout);
         }
         // send the checksum
         serial_port.write(&checksum,1);
-        sleep(1);
-        printf("\nDownload complete\n");
+        std::cout << std::endl << "Download complete" << std::endl;
         end=false;
-/*        while(!end)
+        while(!end)
         {
           try{
-            event_server->wait_all(events,3000);
+            event_server->wait_all(events,300);
             // there has been an error
             num_data=serial_port.get_num_data();
             serial_port.read(bootloader_data,num_data);
@@ -390,37 +229,36 @@ int main(int argc,char *argv[])
             // no error to report
             end=true;
           }
-        }*/
-        return 0;
-        if(opt_fw_file.size()!=0)
+        }
+        // start the loaded program
+        serial_port.write((unsigned char *)&bootloader_go,1);
+        if(protocol==new_protocol)
+          serial_port.write((unsigned char *)&bootloader_ack,1);
+        end=false;
+        while(!end)
         {
-          // start the loaded program
-          serial_port.write((unsigned char *)bootloader_go,4);
-          end=false;
-          while(!end)
-          {
-            try{
-              event_server->wait_all(events,1000);
-              // there has been an error
-              num_data=serial_port.get_num_data();
-              serial_port.read(bootloader_data,num_data);
-              bootloader_data[num_data]='\0';
-              printf("%s",bootloader_data);
-            }catch(CEventTimeoutException &e){
-              // no error to report
-              end=true;
-            }
+          try{
+            event_server->wait_all(events,300);
+            // there has been an error
+            num_data=serial_port.get_num_data();
+            serial_port.read(bootloader_data,num_data);
+            bootloader_data[num_data]='\0';
+            printf("%s",bootloader_data);
+          }catch(CEventTimeoutException &e){
+            // no error to report
+            end=true;
           }
         }
         serial_port.close();
       }catch(CException &e){
         /* handle exceptions */
-        printf("%s\n",e.what().c_str());
+        std::cout << e.what() << std::endl;
       }
     }
   }
   else
   {
-    /* display the help information and exit */
+    std::cout << "No serial device specified" << std::endl;
+    show_help(argv[0]);
   }
 }