// Read a packet from the serial port static void read_request_packet() { u16 temp16; u32 readbytes; while( 1 ) { // First read the length if( ( readbytes = ser_read( ser, rfs_buffer, RFS_START_OFFSET ) ) != RFS_START_OFFSET ) { log_msg( "read_request_packet: ERROR reading packet length. Requested %d bytes, got %d bytes\n", RFS_START_OFFSET, readbytes ); flush_serial(); continue; } if( remotefs_get_packet_size( rfs_buffer, &temp16 ) == REMOTEFS_ERR ) { log_msg( "read_request_packet: ERROR getting packet size.\n" ); flush_serial(); continue; } // Then the rest of the data if( ( readbytes = ser_read( ser, rfs_buffer + RFS_START_OFFSET, temp16 - RFS_START_OFFSET ) ) != temp16 - RFS_START_OFFSET ) { log_msg( "read_request_packet: ERROR reading full packet, got %u bytes, expected %u bytes\n", ( unsigned )readbytes, ( unsigned )temp16 - RFS_START_OFFSET ); flush_serial(); continue; } else break; } }
/*----------------------------------------------------------------------------*/ int nxp_check_isp(ASerialPort_t* aPort, ADeviceNXP_t* aDevice) { my1key_t key; char nxp_sync_char = aDevice ? aDevice->sync_char : NXP_SYNC_CHAR; int status = NXP_CHECK_START; flush_serial(aPort); purge_serial(aPort); while(status<NXP_CHECK_FOUND) { put_byte_serial(aPort,nxp_sync_char); wait_outgoing(aPort); if(check_incoming(aPort)) { byte_t test = get_byte_serial(aPort); if(test==nxp_sync_char) { status = NXP_CHECK_FOUND; break; } } key = get_keyhit(); if(key==KEY_ESCAPE) status = NXP_CHECK_ABORT; else if(key==KEY_BSPACE) status = NXP_CHECK_RESET; } flush_serial(aPort); purge_serial(aPort); return status; }
gboolean prepare_for_upload(gint fd) { gint res = 0; gchar buf[1024]; gchar * message = NULL; res = write(fd,"W",1); if (res != 1) { output("Error trying to initiate ECU wipe\n",FALSE); return FALSE; } flush_serial(fd,OUTBOUND); g_usleep(1000000); /* 1000ms timeout for flash to erase */ res = read(fd,&buf,1024); message = g_strndup(((gchar *)buf),res); if (g_strrstr_len(buf,res,"Complete")) { g_free(message); output("ECU Wipe complete\n",FALSE); res = write(fd,"U",1); if (res != 1) { output("Error trying to initiate ECU upgrade\n",FALSE); return FALSE; } flush_serial(fd,OUTBOUND); g_usleep(2000000); /* 2000ms timeout for flash to erase */ res = read(fd,&buf,1024); if (g_strrstr_len(buf,res,"waiting")) { output("Ready to update ECU firmware\n",FALSE); return TRUE; } else { message = g_strndup(buf,res); output(g_strdup_printf("ECU returned \"%s\"\n",message),TRUE); g_free(message); output("Error getting \"ready to update\" message from ECU\n",FALSE); return FALSE; } } else { output(g_strdup_printf("Error wiping ECU, result \"%s\"\n",message),TRUE); g_free(message); return FALSE; } }
void upload_firmware(gint fd, gint file_fd) { gint res = 0; gchar buf[128]; gint chunk = 128; gint result = 0; gint i = 0; GTimeVal last; GTimeVal now; GTimeVal begin; gfloat elapsed = 0.0; gint rate = 0; g_get_current_time(&begin); g_get_current_time(&now); res = read(file_fd,buf,chunk); while (res > 0) { last = now; g_get_current_time(&now); i+=res; result = write (fd,buf,chunk); elapsed = now.tv_usec - last.tv_usec; if (elapsed < 0) elapsed += 1000000; rate = (chunk*1000000)/elapsed; output(g_strdup_printf("%6i bytes written, %i bytes/sec.\n",i,rate),TRUE); res = read(file_fd,buf,chunk); } flush_serial(fd,BOTH); g_get_current_time(&now); output(g_strdup_printf("Upload completed in %li Seconds\n",now.tv_sec-begin.tv_sec),TRUE); return; }
void close_serial(int fd) { if (fd > 0) { flush_serial(fd); close(fd); } }
void close_port(gint fd) { #ifndef __WIN32__ tcsetattr(fd,TCSAFLUSH,&oldtio); flush_serial(fd,BOTH); #endif close(fd); return; }
int main( int argc, const char **argv ) { long serspeed; if( argc < 4 ) { fprintf( stderr, "Usage: %s <port> <speed> <dirname> [-v]\n", argv[ 0 ] ); fprintf( stderr, "(use -v for verbose output).\n"); return 1; } if( secure_atoi( argv[ SPEED_ARG_IDX ], &serspeed ) == 0 ) { fprintf( stderr, "Invalid speed\n" ); return 1; } if( !os_isdir( argv[ DIRNAME_ARG_IDX ] ) ) { fprintf( stderr, "Invalid directory %s\n", argv[ DIRNAME_ARG_IDX ] ); return 1; } if( ( argc >= 5 ) && !strcmp( argv[ VERBOSE_ARG_IDX ], "-v" ) ) log_init( LOG_ALL ); else log_init( LOG_NONE ); // Setup RFS server server_setup( argv[ DIRNAME_ARG_IDX ] ); // Setup serial port if( ( ser = ser_open( argv[ PORT_ARG_IDX ] ) ) == ( ser_handler )-1 ) { fprintf( stderr, "Cannot open port %s\n", argv[ PORT_ARG_IDX ] ); return 1; } if( ser_setup( ser, ( u32 )serspeed, SER_DATABITS_8, SER_PARITY_NONE, SER_STOPBITS_1 ) != SER_OK ) { fprintf( stderr, "Unable to initialize serial port\n" ); return 1; } flush_serial(); // User report printf( "Running RFS server on port %s (%u baud) in directory %s\n", argv[ PORT_ARG_IDX ], ( unsigned )serspeed, argv[ DIRNAME_ARG_IDX ] ); // Enter the server endless loop while( 1 ) { read_request_packet(); server_execute_request( rfs_buffer ); send_response_packet(); } ser_close( ser ); return 0; }
void reboot_ecu(gint fd) { gint res = 0; output("Sleeping 3 Seconds\n",FALSE); g_usleep(3000000); res = write (fd,"X",1); flush_serial(fd,OUTBOUND); if (res != 1) output("Error trying to Reboot ECU\n",FALSE); return ; }
gboolean jump_to_bootloader(gint fd) { gint res = 0; flush_serial(fd,OUTBOUND); res = write (fd,"!!",2); g_usleep(100000); /* 100ms timeout */ if (res != 2) { output("Error trying to get \"Boot>\" Prompt,\n",FALSE); return FALSE; } return TRUE; }
int open_serial(char *dev_name, struct serl_attr *attr) { int fd; struct termios tio; fd = open(dev_name, O_RDWR|O_NOCTTY|O_NDELAY); if (fd < 0) { return -1; } tcgetattr(fd, &tio); cfmakeraw(&tio); __set_baudrate(&tio, attr); __set_databits(&tio, attr); __set_parity(&tio, attr); __set_stopbits(&tio, attr); tcsetattr(fd, TCSANOW, &tio); flush_serial(fd); return fd; }
gint setup_port(gint fd, gint baud) { #ifdef __WIN32__ win32_setup_serial_params(fd, baud, 8, NONE, 1); #else gint _baud = 0; /* Save serial port status */ tcgetattr(fd,&oldtio); flush_serial(fd, BOTH); memset(&newtio, 0, sizeof(newtio)); /* * BAUDRATE: Set bps rate. You could also use cfsetispeed and * cfsetospeed * CRTSCTS : output hardware flow control (only used if the cable has * all necessary lines. See sect. 7 of Serial-HOWTO) * CS8 : 8n1 (8bit,no parity,1 stopbit) * CLOCAL : local connection, no modem contol * CREAD : enable receiving characters */ /* Set baud (posix way) */ if (baud == 9600) _baud = B9600; else if (baud == 115200) _baud = B115200; else printf("INVALID BAUD RATE %i\n",baud); cfsetispeed(&newtio, _baud); cfsetospeed(&newtio, _baud); /* Mask and set to 8N1 mode... */ newtio.c_cflag &= ~( PARENB | CSTOPB | CSIZE); /* Set additional flags, note |= syntax.. */ /* Enable receiver, ignore modem ctrls lines, use 8 bits */ newtio.c_cflag |= CLOCAL | CREAD | CS8; /* RAW Input */ /* Ignore signals, enable canonical, etc */ newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* Disable software flow control */ newtio.c_iflag &= ~(IXON | IXOFF ); /* Set raw output */ newtio.c_oflag &= ~OPOST; /* initialize all control characters default values can be found in /usr/include/termios.h, and are given in the comments, but we don't need them here * */ newtio.c_cc[VINTR] = 0; /* Ctrl-c */ newtio.c_cc[VQUIT] = 0; /* Ctrl-\ */ newtio.c_cc[VERASE] = 0; /* del */ newtio.c_cc[VKILL] = 0; /* @ */ newtio.c_cc[VEOF] = 0; /* Ctrl-d */ newtio.c_cc[VEOL] = 0; /* '\0' */ /* These are ZERO becasue we are using select() */ newtio.c_cc[VMIN] = 0; /* No min chars requirement */ newtio.c_cc[VTIME] = 0; /* 0ms timeout */ tcsetattr(fd,TCSANOW,&newtio); #endif return 0; }
int FlushRx(HANDLE fd) { flush_serial(fd); }
/*! \brief main() is the typical main function in a C program, it performs all core initialization, loading of all main parameters, initializing handlers and entering gtk_main to process events until program close \param argc (gint) count of command line arguments \param argv (char **) array of command line args \returns TRUE */ gint main(gint argc, gchar ** argv) { gint port_fd = 0; gint file_fd = 0; verify_args(argc, argv); output(g_strdup_printf("MegaTunix msloader %s\n",VERSION),TRUE); /* If we got this far, all is good argument wise */ if (!lock_port(argv[2])) { output("Could NOT LOCK Serial Port\nCheck for already running serial apps using the port\n",FALSE); exit(-1); } port_fd = open_port(argv[2]); if (port_fd > 0) output("Port successfully opened\n",FALSE); else { output("Could NOT open Port check permissions\n",FALSE); unlock_port(); exit(-1); } #ifdef __WIN32__ file_fd = open(argv[3], O_RDWR | O_BINARY ); #else file_fd = g_open(argv[3],O_RDONLY,S_IRUSR); #endif if (file_fd > 0 ) output("Firmware file successfully opened\n",FALSE); else { output("Could NOT open firmware file, check permissions/paths\n",FALSE); close_port(port_fd); unlock_port(); exit(-1); } if (type == MS1) { setup_port(port_fd, 9600); do_ms1_load(port_fd,file_fd); } else if (type == MS2) { setup_port(port_fd,115200); do_ms2_load(port_fd,file_fd); } else if (type == FREEEMS) { setup_port(port_fd,115200); do_freeems_load(port_fd,file_fd); } flush_serial(port_fd,BOTH); close_port(port_fd); unlock_port(); return (0) ; }
EcuState detect_ecu(gint fd) { gint res = 0; gint size = 1024; guchar buf[1024]; guchar *ptr = buf; gint total_read = 0; gint total_wanted = 0; gint zerocount = 0; gchar *message = NULL; /* Probe for response * First check for signature (running state) * If that fails, see if we are in bootloader mode already */ res = write (fd,"S",1); flush_serial(fd,BOTH); if (res != 1) output("Failure sending signature request!\n",FALSE); g_usleep(300000); /* 300ms timeout */ total_read = 0; total_wanted = size; zerocount = 0; while ((total_read < total_wanted ) && (total_wanted-total_read) > 0 ) { total_read += res = read(fd, ptr+total_read, total_wanted-total_read); /* If we get nothing back (i.e. timeout, assume done)*/ if (res <= 0) zerocount++; if (zerocount > 1) break; } if (total_read > 0) { message = g_strndup(((gchar *)buf),total_read); /* Check for "what" or "Boot" */ if (g_strrstr_len(message,total_read, "what")) { g_free(message); return IN_BOOTLOADER; } else if (g_strrstr_len(message,total_read, "Boot")) { g_free(message); return IN_BOOTLOADER; } else { output(g_strdup_printf("ECU signature: \"%s\"\n",message),TRUE); g_free(message); return LIVE_MODE; } } return NOT_LISTENING; }
gboolean get_ecu_signature(gint fd) { gint res = 0; gint size = 128; guchar buf[128]; guchar *ptr = buf; gint total_read = 0; gint total_wanted = 0; gint zerocount = 0; gchar *message = NULL; gint attempt = 0; /* Probe for response * First check for signature (running state) * If that fails, see if we are in bootloader mode already */ flush_serial(fd,BOTH); sig_check: if (attempt > 1) return FALSE; res = write (fd,"S",1); flush_serial(fd,OUTBOUND); if (res != 1) output("Failure sending signature request!\n",FALSE); g_usleep(300000); /* 300ms timeout */ total_read = 0; total_wanted = size; zerocount = 0; while ((total_read < total_wanted ) && (total_wanted-total_read) > 0 ) { total_read += res = read(fd, ptr+total_read, total_wanted-total_read); /* If we get nothing back (i.e. timeout, assume done)*/ if (res <= 0) break; } if (total_read > 0) { message = g_strndup(((gchar *)buf),total_read); /* Check for "what" or "Boot" */ if (g_strrstr_len(message,total_read, "Vector")) { g_free(message); output("ECU has corrupted firmware!\n",FALSE); return FALSE; } else if (g_strrstr_len(message,total_read, "what")) { g_free(message); attempt++; output("ECU is in bootloader mode, attempting reboot\n",FALSE); res = write (fd,"X",1); flush_serial(fd,BOTH); g_usleep(500000); goto sig_check; } else if (g_strrstr_len(message,total_read, "Boot")) { g_free(message); output("ECU is in bootloader mode, attempting reboot\n",FALSE); attempt++; res = write (fd,"X",1); flush_serial(fd,BOTH); g_usleep(500000); goto sig_check; } else { output(g_strdup_printf("Detected signature: \"%s\"\n",message),TRUE); g_free(message); return TRUE; } } return FALSE; }
/*! \brief setup_serial_params() is another wrapper that calls the appropriate calls to initialize the serial port to the proper speed, bits, flow, parity etc.. */ G_MODULE_EXPORT void setup_serial_params(void) { GMutex *serio_mutex = NULL; gchar * baud_str = NULL; Parity parity = NONE; gint baudrate = 0; gint bits = 0; gint stop = 0; Serial_Params *serial_params = NULL; #ifndef __WIN32__ speed_t baud; #endif serial_params = DATA_GET(global_data,"serial_params"); serio_mutex = DATA_GET(global_data,"serio_mutex"); baud_str = DATA_GET(global_data,"ecu_baud_str"); if (!parse_baud_str(baud_str,&baudrate,&bits,&parity,&stop)) MTXDBG(SERIAL_RD|SERIAL_WR|CRITICAL,_("ERROR! couldn't parse ecu_baud string %s\n"),baud_str); DATA_SET(global_data,"ecu_baud",GINT_TO_POINTER(baudrate)); if (serial_params->open == FALSE) return; if (DATA_GET(global_data,"network_mode")) { printf("network mode, exiting!\n"); return; } /*printf("setup_serial_params entered\n");*/ g_mutex_lock(serio_mutex); #ifdef __WIN32__ win32_setup_serial_params(serial_params->fd,baudrate,bits,parity,stop); #else /* Save serial port status */ tcgetattr(serial_params->fd,&serial_params->oldtio); g_mutex_unlock(serio_mutex); flush_serial(serial_params->fd, BOTH); g_mutex_lock(serio_mutex); /* Sets up serial port for the modes we want to use. * NOTE: Original serial tio params are stored and restored * in the open_serial() and close_serial() functions. */ /*clear struct for new settings*/ memset(&serial_params->newtio, 0, sizeof(serial_params->newtio)); /* * BAUDRATE: Set bps rate. You could also use cfsetispeed and * cfsetospeed * CRTSCTS : output hardware flow control (only used if the cable has * all necessary lines. See sect. 7 of Serial-HOWTO) * CS8 : 8n1 (8bit,no parity,1 stopbit) * CLOCAL : local connection, no modem contol * CREAD : enable receiving characters */ /* Set baud (posix way) */ switch (baudrate) { case 8192: baud = B38400; break; case 9600: baud = B9600; break; case 19200: baud = B19200; break; case 38400: baud = B38400; break; case 57600: baud = B57600; break; case 115200: baud = B115200; break; default: /* Assume 9600 */ baud = B9600; } cfsetispeed(&serial_params->newtio, baud); cfsetospeed(&serial_params->newtio, baud); /* Mask and set to 8N1 mode... */ /* Mask out HW flow control */ serial_params->newtio.c_cflag &= ~(CRTSCTS); /* Set additional flags, note |= syntax.. */ /* CLOCAL == Ignore modem control lines CREAD == Enable receiver */ serial_params->newtio.c_cflag |= CLOCAL | CREAD; /* Mask out Bit size */ serial_params->newtio.c_cflag &= ~(CSIZE); switch (bits) { case 8: serial_params->newtio.c_cflag |= CS8; break; case 7: serial_params->newtio.c_cflag |= CS7; break; case 6: serial_params->newtio.c_cflag |= CS6; break; case 5: serial_params->newtio.c_cflag |= CS5; break; } /* Mask out Parity Flags */ serial_params->newtio.c_cflag &= ~(PARENB | PARODD); switch (parity) { case ODD: serial_params->newtio.c_cflag |= (PARENB | PARODD); break; case EVEN: serial_params->newtio.c_cflag |= PARENB; break; case NONE: break; } /* Mask out Stip bit flags */ serial_params->newtio.c_cflag &= ~(CSTOPB); if (stop == 2) serial_params->newtio.c_cflag |= CSTOPB; /* 1 stop bit is default */ /* RAW Input */ /* Ignore signals, disable canonical, echo, etc */ /* serial_params->newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHONL | IEXTEN | ISIG); */ serial_params->newtio.c_lflag = 0; /* Disable software flow control */ serial_params->newtio.c_iflag &= ~(IXON | IXOFF | IXANY ); /* serial_params->newtio.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL ); */ serial_params->newtio.c_iflag = IGNBRK; /* Set raw output */ /* serial_params->newtio.c_oflag &= ~OPOST; */ serial_params->newtio.c_oflag = 0; /* initialize all control characters default values can be found in /usr/include/termios.h, and are given in the comments, but we don't need them here */ serial_params->newtio.c_cc[VINTR] = 0; /* Ctrl-c */ serial_params->newtio.c_cc[VQUIT] = 0; /* Ctrl-\ */ serial_params->newtio.c_cc[VERASE] = 0; /* del */ serial_params->newtio.c_cc[VKILL] = 0; /* @ */ serial_params->newtio.c_cc[VEOF] = 0; /* Ctrl-d */ serial_params->newtio.c_cc[VEOL] = 0; /* '\0' */ /* Fredcooke say vmin = 1 solves his hang on close issue with his broken FTDI driver, but that will break interrogation unless I completely transition to nonblocking IO */ serial_params->newtio.c_cc[VMIN] = 0; serial_params->newtio.c_cc[VTIME] = 1; /* 100ms timeout */ /* PIS Specific (odd baud rate) DISABLED */ /* if (ioctl(serial_params->fd, TIOCGSERIAL, &serial_params->oldctl) != 0) MTXDBG(SERIAL_RD|SERIAL_WR|CRITICAL, _("Error getting serial line information error %s\n"),strerror(errno)); else { MTXDBG(SERIAL_RD|SERIAL_WR, _("Get serial line info call OK\n")); // copy ioctl structure memcpy(&serial_params->newctl, &serial_params->oldctl, sizeof(serial_params->newctl)); // and if we are PIS 8192 make a custom divisor if (baudrate == 8192) { if (serial_params->newctl.baud_base < 115200) serial_params->newctl.baud_base = 115200; serial_params->newctl.custom_divisor = 14; serial_params->newctl.flags |= (ASYNC_SPD_MASK & ASYNC_SPD_CUST); if (ioctl(serial_params->fd, TIOCSSERIAL, &serial_params->newctl) != 0) MTXDBG(SERIAL_RD|SERIAL_WR|CRITICAL,_("Error setting ioctl\n")); else MTXDBG(SERIAL_RD|SERIAL_WR,_("Set ioctl OK\n")); } } */ tcsetattr(serial_params->fd, TCSANOW, &serial_params->newtio); #endif g_mutex_unlock(serio_mutex); flush_serial(serial_params->fd,BOTH); return; }