http://marcin-wiacek.fkn.pl/english/zips/mygnokii.tar.gz
[gnokii.git] / common / devices / device.c
diff --git a/common/devices/device.c b/common/devices/device.c
new file mode 100644 (file)
index 0000000..45330c2
--- /dev/null
@@ -0,0 +1,464 @@
+/*
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for Nokia mobile phones.
+
+  Released under the terms of the GNU GPL, see file COPYING for more details.
+
+*/
+
+#ifndef WIN32
+  #include "devices/unixserial.h"
+  #include "devices/unixirda.h"
+  #include "devices/tekram.h"
+  #include <sys/ioctl.h>
+  #include <pthread.h>
+  #include <termios.h>
+  #include <signal.h>
+  #include <errno.h>
+#else
+  #include <windows.h>
+  #include "devices/winserial.h"
+#endif
+
+#include "gsm-api.h"
+#include "devices/device.h"
+
+#include <string.h>
+
+#ifdef VC6
+  /* for VC6 make scripts save VERSION constant in mversion.h file */
+  #include "mversion.h"
+#endif
+
+char PortDevice[GSM_MAX_DEVICE_NAME_LENGTH]={0x00};
+
+bool duringwrite;
+
+#ifndef WIN32
+
+//pthread_t Thread;
+#if defined(__svr4__) || defined(__FreeBSD__)
+  pthread_t selThread;
+#endif
+
+int device_portfd = -1;
+
+/*
+ * Structure to store the filedescriptor we use.
+ *
+ */
+int device_getfd(void)
+{
+  return device_portfd;
+}
+
+int device_open(__const char *__file, int __with_odd_parity) {
+
+  switch (CurrentConnectionType) {
+    case GCT_Tekram:
+      device_portfd = tekram_open(__file);
+      break;
+    case GCT_Irda:
+      device_portfd = irda_open();
+      break;
+    default:
+      device_portfd = serial_opendevice(__file, __with_odd_parity, true, false);
+      break;
+  }
+  
+  return (device_portfd >= 0);
+}
+
+void device_close(void)
+{
+  AppendLogText("CLOSE\n",false);
+
+  /* Now wait for thread to terminate. */
+  //pthread_join(Thread, NULL);
+
+  switch (CurrentConnectionType) {
+    case GCT_Tekram: tekram_close(device_portfd); break;
+    case GCT_Irda  :   irda_close(device_portfd); break;
+    default        : serial_close(device_portfd); break;
+  }
+
+  PortDevice[0]=0x00;
+}
+
+void device_reset(void) {
+}
+
+void device_setdtrrts(int __dtr, int __rts)
+{
+  switch (CurrentConnectionType) {
+    case GCT_Tekram:
+    case GCT_Irda:
+      break;
+    default:
+      serial_setdtrrts(device_portfd, __dtr, __rts);
+#ifdef DEBUG
+      device_dumpserial();
+#endif
+      break;
+  }
+}
+
+void device_changespeed(int __speed)
+{
+  switch (CurrentConnectionType) {
+    case GCT_Irda:
+      break;
+    case GCT_Tekram:
+      tekram_changespeed(device_portfd, __speed);
+      break;
+    default:
+      serial_changespeed(device_portfd, __speed);
+#ifdef DEBUG
+      fprintf(stdout,_("Serial device: changing speed to %i\n"),__speed);
+#endif
+      break;
+  }
+}
+
+size_t device_read(__ptr_t __buf, size_t __nbytes)
+{
+  switch (CurrentConnectionType) {
+    case GCT_Tekram: return (tekram_read(device_portfd, __buf, __nbytes)); break;
+    case GCT_Irda  : return (  irda_read(device_portfd, __buf, __nbytes)); break;
+    default        : return (serial_read(device_portfd, __buf, __nbytes)); break;
+  }
+}
+
+size_t device_write(__const __ptr_t __buf, size_t __n) {
+  u8 buffer[300];
+  size_t mysize;
+  
+  while (duringwrite) {}
+
+  memcpy(buffer,__buf,__n);
+  AppendLog(buffer,__n,true);
+
+  duringwrite=true;
+  switch (CurrentConnectionType) {
+    case GCT_Irda  : mysize =   irda_write(device_portfd, __buf, __n); break;
+    case GCT_Tekram: mysize = tekram_write(device_portfd, __buf, __n); break;      
+    default        : mysize = serial_write(device_portfd, __buf, __n); break;
+  }
+  duringwrite=false;
+  return mysize;
+}
+
+#ifdef DEBUG
+void device_dumpserial(void)
+{
+  int PortFD;
+  unsigned int Flags=0;
+
+  PortFD = device_getfd();
+
+  ioctl(PortFD, TIOCMGET, &Flags);
+
+  fprintf(stdout, _("Serial device:"));
+  fprintf(stdout,  _(" DTR is %s"), Flags&TIOCM_DTR?_("up"):_("down"));
+  fprintf(stdout, _(", RTS is %s"), Flags&TIOCM_RTS?_("up"):_("down"));
+  fprintf(stdout, _(", CAR is %s"), Flags&TIOCM_CAR?_("up"):_("down"));
+  fprintf(stdout, _(", CTS is %s\n"), Flags&TIOCM_CTS?_("up"):_("down"));
+}
+#endif /* DEBUG */
+
+void SigHandler(int status)
+{
+
+  unsigned char buffer[2048];
+
+  int count, res;
+
+  res = device_read(buffer, 255);
+
+  for (count = 0; count < res ; count ++) {
+    Protocol->StateMachine(buffer[count]);
+  }
+}
+
+
+#if defined(__svr4__) || defined(__FreeBSD__)
+/* thread for handling incoming data */
+void SelectLoop() {
+  int err;
+  fd_set readfds;
+  struct timeval timeout;
+
+  FD_ZERO(&readfds);
+  FD_SET(device_portfd,&readfds);
+  /* set timeout to 15 seconds */
+  timeout.tv_sec=15;
+  timeout.tv_usec=0;
+  while (!CurrentRequestTerminate) {
+    err=select(device_portfd+1,&readfds,NULL,NULL,&timeout);
+    if ( err > 0 ) {
+      /* call singal handler to process incoming data */
+      SigHandler(0);
+      /* refresh timeout, just for linux :-( */\r
+      /* required for irda */
+      timeout.tv_sec=15;\r
+    } else {
+      if (err == -1)
+      perror("Error in SelectLoop");
+    }
+  }
+}
+#endif
+
+bool StartConnection (char *port_device, bool with_odd_parity, GSM_ConnectionType con)
+{
+  int result;
+
+  char text[100];
+
+#if defined(__svr4__) || defined(__FreeBSD__)
+  int rtn;
+#else
+  struct sigaction sig_io;
+#endif
+
+#ifdef DEBUG
+      if ((strstr(GSM_Info->IrdaModels,"decode")!=NULL) &&  (CurrentConnectionType == GCT_Irda))
+       {
+         printf("DEBUG and Irda decode Model -> not realy open ;-)\n");
+         return true;
+       }
+#endif 
+
+  if (PortDevice[0]!=0x00) return true;
+
+  duringwrite=false;
+  
+  strncpy(PortDevice, port_device, GSM_MAX_DEVICE_NAME_LENGTH);
+
+#ifdef DEBUG
+  fprintf(stdout,_("Opening \"%s\" device...\n"),PortDevice);
+#endif
+
+  strcpy(text,"\n\n\nMygnokii ");
+  sprintf(text+strlen(text), "%s",VERSION);
+  strcpy(text+strlen(text),"\n");
+  AppendLogText(text,false);
+
+  strcpy(text,"Port ");
+  strcpy(text+strlen(text),PortDevice);
+  strcpy(text+strlen(text),"\n");
+  AppendLogText(text,false);
+
+  strcpy(text,"Connection ");
+  switch (con) {
+    case GCT_FBUS    :strcpy(text+strlen(text),"FBUS");break;
+    case GCT_Infrared:strcpy(text+strlen(text),"infrared");break;
+    case GCT_Irda    :strcpy(text+strlen(text),"irda sockets");break;
+    case GCT_MBUS    :strcpy(text+strlen(text),"MBUS");break;
+    case GCT_DLR3    :strcpy(text+strlen(text),"DLR3");break;
+    case GCT_Tekram  :strcpy(text+strlen(text),"Tekram");break;
+    case GCT_AT      :strcpy(text+strlen(text),"AT");break;
+    default          :strcpy(text+strlen(text),"unknown");break;
+  }
+  strcpy(text+strlen(text),"\n");
+  AppendLogText(text,false);
+
+  /* Ralf Thelen: In this moment there is NO method of communication,
+   which require keepalive packets and GSM->KeepAlive is
+   always NULL_KeepAlive, I comment this thread, */
+
+  /* Create and start main thread. */
+//  rtn = pthread_create(&Thread, NULL,(void*)GSM->KeepAlive, (void *)NULL);
+//
+//  if (rtn != 0) {
+//    fprintf(stdout,_("Error\n"));  
+//    return false;
+//  }
+
+#if defined(__svr4__) || defined(__FreeBSD__)
+#else
+        /* Set up and install handler before enabling async IO on port. */
+        sig_io.sa_handler = SigHandler;
+        sig_io.sa_flags = 0;
+        sigaction (SIGIO, &sig_io, NULL);
+#endif
+
+    /* Open device. */
+    result = device_open(PortDevice, with_odd_parity);
+    
+    if (!result) {
+      fprintf(stdout,_("Error\n"));  
+      return false;
+    }
+
+#if defined(__svr4__) || defined(__FreeBSD__)
+    /* create a thread to handle incoming data from mobile phone */
+    rtn=pthread_create(&selThread,NULL,(void*)SelectLoop,(void*)NULL);
+    if (rtn != 0) {
+      fprintf(stdout,_("Error\n"));  
+      return false;
+    }
+#endif
+
+  return true;
+}
+
+/* ---------------- RTH:   #ifdef WIN32 ------------------ */  
+
+#else
+
+  extern HANDLE hPhone;
+
+void device_close(void)
+{
+  AppendLogText("CLOSE\n",false);
+
+  CloseConnection();
+
+  PortDevice[0]=0x00;
+}
+
+#ifdef DEBUG
+void device_dumpserial(void)
+{
+  DCB dcb;
+  
+  dcb.DCBlength = sizeof(DCB);
+  GetCommState(hPhone, &dcb);
+
+  fprintf(stdout, _("Serial device:"));
+  fprintf(stdout,  _(" DTR is "));
+  switch (dcb.fDtrControl) {
+    case DTR_CONTROL_ENABLE   : fprintf(stdout,  _("up"));       break;
+    case DTR_CONTROL_DISABLE  : fprintf(stdout,  _("down"));     break;
+    case DTR_CONTROL_HANDSHAKE: fprintf(stdout,  _("handshake"));break;
+  }
+  fprintf(stdout, _(", RTS is "));
+  switch (dcb.fRtsControl) {
+    case RTS_CONTROL_ENABLE   : fprintf(stdout,  _("up\n"));       break;
+    case RTS_CONTROL_DISABLE  : fprintf(stdout,  _("down\n"));     break;
+    case RTS_CONTROL_HANDSHAKE: fprintf(stdout,  _("handshake\n"));break;
+    case RTS_CONTROL_TOGGLE   : fprintf(stdout,  _("toggle\n"));   break;
+  }
+}
+#endif /* DEBUG */
+
+void device_setdtrrts(int __dtr, int __rts)
+{
+  DCB dcb;
+  
+  dcb.DCBlength = sizeof(DCB);
+  GetCommState(hPhone, &dcb);
+
+  if (__dtr==1) dcb.fDtrControl = DTR_CONTROL_ENABLE;
+           else dcb.fDtrControl = DTR_CONTROL_DISABLE;
+
+   if (__rts==1) dcb.fRtsControl = RTS_CONTROL_ENABLE;
+            else dcb.fRtsControl = RTS_CONTROL_DISABLE;
+
+   SetCommState(hPhone, &dcb);
+
+#ifdef DEBUG
+  device_dumpserial();
+#endif
+}
+
+void device_changespeed(int __speed)
+{
+
+  DCB dcb;
+
+  dcb.DCBlength = sizeof(DCB);
+  GetCommState(hPhone, &dcb);
+
+  switch (__speed) {
+    case 115200: dcb.BaudRate=CBR_115200; break;
+    case 19200 : dcb.BaudRate=CBR_19200;  break;
+    case 9600  : dcb.BaudRate=CBR_9600;   break;
+   }
+   
+   SetCommState(hPhone, &dcb);
+
+#ifdef DEBUG
+   fprintf(stdout,_("Serial device: changing speed to %i\n"),__speed);
+#endif
+}
+
+bool StartConnection (char *port_device, bool with_odd_parity, GSM_ConnectionType con)
+{
+  DCB dcb;
+  char text[100];
+
+  int rtn;
+
+  if (PortDevice[0]!=0x00) return true;  
+
+  duringwrite=false;
+  strncpy(PortDevice, port_device, GSM_MAX_DEVICE_NAME_LENGTH);
+
+#ifdef DEBUG
+  fprintf(stdout,_("Opening \"%s\" device...\n"),PortDevice);
+#endif
+
+  strcpy(text,"\n\n\nMygnokii ");
+  sprintf(text+strlen(text), "%s",VERSION);
+  strcpy(text+strlen(text),"\n");
+  AppendLogText(text,false);
+
+  strcpy(text,"Port ");
+  strcpy(text+strlen(text),PortDevice);
+  strcpy(text+strlen(text),"\n");
+  AppendLogText(text,false);
+
+  strcpy(text,"Connection ");
+  switch (con) {
+    case GCT_FBUS    :strcpy(text+strlen(text),"FBUS");break;
+    case GCT_Infrared:strcpy(text+strlen(text),"infrared");break;
+    case GCT_Irda    :strcpy(text+strlen(text),"irda sockets");break;
+    case GCT_MBUS    :strcpy(text+strlen(text),"MBUS");break;
+    case GCT_DLR3    :strcpy(text+strlen(text),"DLR3");break;
+    case GCT_Tekram  :strcpy(text+strlen(text),"Tekram");break;
+    case GCT_AT      :strcpy(text+strlen(text),"AT");break;
+    default          :strcpy(text+strlen(text),"unknown");break;
+  }
+  strcpy(text+strlen(text),"\n");
+  AppendLogText(text,false);
+
+  CurrentDisableKeepAlive = true;
+
+  /* Create and start main thread. */
+  rtn = ! OpenConnection(PortDevice, Protocol->StateMachine, GSM->KeepAlive);
+
+  if (rtn != 0) {
+
+    fprintf(stdout,_("Error\n"));  
+    return false;
+  } else {
+    CurrentDisableKeepAlive = false;
+  }
+
+  if (with_odd_parity) {
+    dcb.DCBlength = sizeof(DCB);
+    GetCommState(hPhone, &dcb);
+
+    dcb.Parity=ODDPARITY;
+
+    SetCommState(hPhone, &dcb);
+  }
+  
+  return true;
+}
+
+size_t device_write(const __ptr_t __buf, size_t __n) {
+  int i;
+  while (duringwrite) {}
+  duringwrite=true;
+  AppendLog(__buf,__n,true);
+  i=WriteCommBlock(__buf,__n);
+  duringwrite=false;
+  if (i) return __n; else return 0;
+}
+
+#endif /*WIN32*/