/*
  charge - a simple tool to enble the built in charger in
  Mobile Action USB data cables

  Copyright (C) 2006 Martin Leopold <leopold@diku.dk>

  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.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <termios.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <sys/types.h>

struct termios oldkey, newkey;       //place for old and new port settings for keyboard teletype

main(int argc, char *argv[]) {
  int tty, flags, n;
  char c[6]={'U','U','U','U',0x4,0x1};
  char *ttydevice;
   
  if (argc != 1) {
     ttydevice = argv[1];
  } else {
     ttydevice = "/dev/ttyUSB0";
  }
   
  tty = open(ttydevice, O_RDWR | O_NOCTTY | O_NONBLOCK);

  if (tty == -1)
    {
      /*
       * Could not open the port.
       */
       fprintf(stderr, "open_port: Unable to open tty %s\n", ttydevice);
       return 1;
    }

  tcgetattr(tty,&oldkey); // save current port settings

  //charger.exe sets each as an ioctl
  //XON/XOFF flow control, 8 databits, 1 stop bit, parity none
  newkey.c_cflag =  CLOCAL | CREAD |
    B9600 | // Set baud rate
    CS8 | // 8 data bits
    IXON | IXOFF| IXANY & // Enable software flow control
    ~CSTOPB; // 1 stop bit

  newkey.c_iflag = IGNPAR; //set input mode (ignore parity, non-canonical, no echo,...)
  newkey.c_oflag = 0;
  newkey.c_lflag = 0; 

  // Mimics "charger.exe" settings
  // NB. Timeouts are ignored in canonical input mode or when the NDELAY option is set 
  newkey.c_cc[VMIN]  = 0;   /* blocking read until x chars received */
  newkey.c_cc[VTIME] = 10;  /* inter-character timer unused in 1/10 s */

  // Mimics the settings of the structure SERIAL_CHARS in Windows as best I can
  newkey.c_cc[VSTART] = 11; //XON
  newkey.c_cc[VSTOP]  = 13; //OFF
  newkey.c_cc[VEOF]   = 0;
  newkey.c_cc[VQUIT]  = 0;  //No equal to Windows 'ErrorChar'
  newkey.c_cc[VERASE] = 0;
  newkey.c_cc[VINTR]  = 0;  //'EventChar'

  tcsetattr(tty,TCSANOW,&newkey);
  tcflush(tty, TCIOFLUSH);

  // Set DTR and RTS high
  // This is done w. two IOCTLS in charger.exe
  ioctl(tty, TIOCMGET, &flags);
  flags |= TIOCM_RTS;  // Set RTS
  flags |= TIOCM_DTR;  // Set DTR
  ioctl(tty, TIOCMSET, &flags);
  tcflush(tty, TCIOFLUSH);

  usleep(100);

  // Clear DTR
  ioctl(tty, TIOCMGET, &flags);
  flags |= TIOCM_RTS;  // Set RTS
  flags &= ~TIOCM_DTR; // Clr DTR
  ioctl(tty, TIOCMSET, &flags);
  tcflush(tty, TCIOFLUSH);

  n = write(tty,&c,6);
  if (n < 0)
    fputs("write() of 6 bytes failed!\n", stderr);

  ioctl(tty, TCFLSH);
  //  tcsetattr(tty,TCSANOW,&oldkey);
  close(tty);
}

