summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/device/serial
authorzautrix <zautrix>2004-08-07 17:24:40 (UTC)
committer zautrix <zautrix>2004-08-07 17:24:40 (UTC)
commit88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22 (patch) (side-by-side diff)
tree6331418973714243beb674abc87692277b83869d /gammu/emb/common/device/serial
parentef8a09ce74ad3f0a51484d03fdf009bd5b3677bf (diff)
downloadkdepimpi-88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22.zip
kdepimpi-88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22.tar.gz
kdepimpi-88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22.tar.bz2
Initial revision
Diffstat (limited to 'gammu/emb/common/device/serial') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/device/serial/ser_djg.c74
-rw-r--r--gammu/emb/common/device/serial/ser_djg.h15
-rw-r--r--gammu/emb/common/device/serial/ser_unx.c291
-rw-r--r--gammu/emb/common/device/serial/ser_unx.h22
-rw-r--r--gammu/emb/common/device/serial/ser_w32.c340
-rw-r--r--gammu/emb/common/device/serial/ser_w32.h19
6 files changed, 761 insertions, 0 deletions
diff --git a/gammu/emb/common/device/serial/ser_djg.c b/gammu/emb/common/device/serial/ser_djg.c
new file mode 100644
index 0000000..ac9d7c8
--- a/dev/null
+++ b/gammu/emb/common/device/serial/ser_djg.c
@@ -0,0 +1,74 @@
+
+#include "../../gsmstate.h"
+
+#ifdef GSM_ENABLE_SERIALDEVICE
+#ifdef DJGPP
+
+#include "../../gsmcomon.h"
+#include "ser_djg.h"
+
+static GSM_Error serial_close(GSM_StateMachine *s)
+{
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+
+ return ERR_NONE;
+}
+
+static GSM_Error serial_open (GSM_StateMachine *s)
+{
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+
+ return ERR_NONE;
+}
+
+static GSM_Error serial_setparity(GSM_StateMachine *s, bool parity)
+{
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+
+ return ERR_NONE;
+}
+
+static GSM_Error serial_setdtrrts(GSM_StateMachine *s, bool dtr, bool rts)
+{
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+
+ return ERR_NONE;
+}
+
+static GSM_Error serial_setspeed(GSM_StateMachine *s, int speed)
+{
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+
+ return ERR_NONE;
+}
+
+static int serial_read(GSM_StateMachine *s, void *buf, size_t nbytes)
+{
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+
+ return 0;
+}
+
+static int serial_write(GSM_StateMachine *s, void *buf, size_t nbytes)
+{
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+
+ return 0;
+}
+
+GSM_Device_Functions SerialDevice = {
+ serial_open,
+ serial_close,
+ serial_setparity,
+ serial_setdtrrts,
+ serial_setspeed,
+ serial_read,
+ serial_write
+};
+
+#endif
+#endif
+
+/* How should editor hadle tabs in this file? Add editor commands here.
+ * vim: noexpandtab sw=8 ts=8 sts=8:
+ */
diff --git a/gammu/emb/common/device/serial/ser_djg.h b/gammu/emb/common/device/serial/ser_djg.h
new file mode 100644
index 0000000..b35b282
--- a/dev/null
+++ b/gammu/emb/common/device/serial/ser_djg.h
@@ -0,0 +1,15 @@
+
+#ifdef DJGPP
+#ifndef djgppserial_h
+#define djgppserial_h
+
+typedef struct {
+ int hPhone;
+} GSM_Device_SerialData;
+
+#endif
+#endif
+
+/* How should editor hadle tabs in this file? Add editor commands here.
+ * vim: noexpandtab sw=8 ts=8 sts=8:
+ */
diff --git a/gammu/emb/common/device/serial/ser_unx.c b/gammu/emb/common/device/serial/ser_unx.c
new file mode 100644
index 0000000..2a87b11
--- a/dev/null
+++ b/gammu/emb/common/device/serial/ser_unx.c
@@ -0,0 +1,291 @@
+/* (c) 2002-2004 by Marcin Wiacek */
+/* locking device and settings all speeds by Michal Cihar */
+
+#include "../../gsmstate.h"
+
+#ifdef GSM_ENABLE_SERIALDEVICE
+#ifndef WIN32
+#ifndef DJGPP
+
+#include <sys/file.h>
+#include <sys/time.h>
+#include <string.h>
+#include <termios.h>
+#include <errno.h>
+
+#include "../../gsmcomon.h"
+#include "ser_unx.h"
+
+static GSM_Error serial_close(GSM_StateMachine *s)
+{
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+
+ /* Restores old settings */
+ tcsetattr(d->hPhone, TCSANOW, &d->old_settings);
+
+ /* Closes device */
+ close(d->hPhone);
+
+ return ERR_NONE;
+}
+
+#ifndef O_NONBLOCK
+# define O_NONBLOCK 0
+#endif
+
+static GSM_Error serial_open (GSM_StateMachine *s)
+{
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+ struct termios t;
+ int i;
+
+ /* O_NONBLOCK MUST is required to avoid waiting for DCD */
+ d->hPhone = open(s->CurrentConfig->Device, O_RDWR | O_NOCTTY | O_NONBLOCK);
+ if (d->hPhone < 0) {
+ i = errno;
+ GSM_OSErrorInfo(s,"open in serial_open");
+ if (i == 2) return ERR_DEVICENOTEXIST; //no such file or directory
+ if (i == 13) return ERR_DEVICENOPERMISSION; //permission denied
+ return ERR_DEVICEOPENERROR;
+ }
+
+#ifdef TIOCEXCL
+ /* open() calls from other applications shall fail now */
+ ioctl(d->hPhone, TIOCEXCL, (char *) 0);
+#endif
+
+ if (tcgetattr(d->hPhone, &d->old_settings) == -1) {
+ close(d->hPhone);
+ GSM_OSErrorInfo(s,"tcgetattr in serial_open");
+ return ERR_DEVICEREADERROR;
+ }
+
+ if (tcflush(d->hPhone, TCIOFLUSH) == -1) {
+ serial_close(s);
+ GSM_OSErrorInfo(s,"tcflush in serial_open");
+ return ERR_DEVICEOPENERROR;
+ }
+
+ memcpy(&t, &d->old_settings, sizeof(struct termios));
+
+ /* Opening without parity */
+ t.c_iflag = IGNPAR;
+ t.c_oflag = 0;
+ /* disconnect line, 8 bits, enable receiver,
+ * ignore modem lines,lower modem line after disconnect
+ */
+ t.c_cflag = B0 | CS8 | CREAD | CLOCAL | HUPCL;
+ /* enable hardware (RTS/CTS) flow control (NON POSIX) */
+ /* t.c_cflag |= CRTSCTS; */
+ t.c_lflag = 0;
+ t.c_cc[VMIN] = 1;
+ t.c_cc[VTIME] = 0;
+
+ if (tcsetattr(d->hPhone, TCSANOW, &t) == -1) {
+ serial_close(s);
+ GSM_OSErrorInfo(s,"tcsetattr in serial_open");
+ return ERR_DEVICEOPENERROR;
+ }
+
+ /* Making file descriptor asynchronous. */
+ if (fcntl(d->hPhone, F_SETFL, FASYNC | FNONBLOCK) == -1) {
+ serial_close(s);
+ GSM_OSErrorInfo(s,"fcntl in serial_open");
+ return ERR_DEVICEOPENERROR;
+ }
+
+ return ERR_NONE;
+}
+
+static GSM_Error serial_setparity(GSM_StateMachine *s, bool parity)
+{
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+ struct termios t;
+
+ if (tcgetattr(d->hPhone, &t)) {
+ GSM_OSErrorInfo(s,"tcgetattr in serial_setparity");
+ return ERR_DEVICEREADERROR;
+ }
+
+ if (parity) {
+ t.c_cflag |= (PARENB | PARODD);
+ t.c_iflag = 0;
+ } else {
+ t.c_iflag = IGNPAR;
+ }
+
+ if (tcsetattr(d->hPhone, TCSANOW, &t) == -1){
+ serial_close(s);
+ GSM_OSErrorInfo(s,"tcsetattr in serial_setparity");
+ return ERR_DEVICEPARITYERROR;
+ }
+
+ return ERR_NONE;
+}
+
+static GSM_Error serial_setdtrrts(GSM_StateMachine *s, bool dtr, bool rts)
+{
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+ struct termios t;
+ unsigned int flags;
+
+ if (tcgetattr(d->hPhone, &t)) {
+ GSM_OSErrorInfo(s,"tcgetattr in serial_setdtrrts");
+ return ERR_DEVICEREADERROR;
+ }
+
+#ifdef CRTSCTS
+ /* Disabling hardware flow control */
+ t.c_cflag &= ~CRTSCTS;
+#endif
+
+ if (tcsetattr(d->hPhone, TCSANOW, &t) == -1) {
+ serial_close(s);
+ GSM_OSErrorInfo(s,"tcsetattr in serial_setdtrrts");
+ return ERR_DEVICEDTRRTSERROR;
+ }
+
+ flags = TIOCM_DTR;
+ if (dtr) {
+ ioctl(d->hPhone, TIOCMBIS, &flags);
+ } else {
+ ioctl(d->hPhone, TIOCMBIC, &flags);
+ }
+
+ flags = TIOCM_RTS;
+ if (rts) {
+ ioctl(d->hPhone, TIOCMBIS, &flags);
+ } else {
+ ioctl(d->hPhone, TIOCMBIC, &flags);
+ }
+
+ flags = 0;
+ ioctl(d->hPhone, TIOCMGET, &flags);
+
+ dbgprintf("Serial device:");
+ dbgprintf(" DTR is %s", flags&TIOCM_DTR?"up":"down");
+ dbgprintf(", RTS is %s", flags&TIOCM_RTS?"up":"down");
+ dbgprintf(", CAR is %s", flags&TIOCM_CAR?"up":"down");
+ dbgprintf(", CTS is %s\n", flags&TIOCM_CTS?"up":"down");
+ if (((flags&TIOCM_DTR)==TIOCM_DTR) != dtr) return ERR_DEVICEDTRRTSERROR;
+ if (((flags&TIOCM_RTS)==TIOCM_RTS) != rts) return ERR_DEVICEDTRRTSERROR;
+
+ return ERR_NONE;
+}
+
+static GSM_Error serial_setspeed(GSM_StateMachine *s, int speed)
+{
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+ struct termios t;
+ int speed2 = B19200;
+
+ if (tcgetattr(d->hPhone, &t)) {
+ GSM_OSErrorInfo(s,"tcgetattr in serial_setspeed");
+ return ERR_DEVICEREADERROR;
+ }
+
+ smprintf(s, "Setting speed to %d\n", speed);
+
+ switch (speed) {
+ case 50: speed2 = B50; break;
+ case 75: speed2 = B75; break;
+ case 110: speed2 = B110; break;
+ case 134: speed2 = B134; break;
+ case 150: speed2 = B150; break;
+ case 200: speed2 = B200; break;
+ case 300: speed2 = B300; break;
+ case 600: speed2 = B600; break;
+ case 1200: speed2 = B1200; break;
+ case 1800: speed2 = B1800; break;
+ case 2400: speed2 = B2400; break;
+ case 4800: speed2 = B4800; break;
+ case 9600: speed2 = B9600; break;
+ case 19200: speed2 = B19200; break;
+ case 38400: speed2 = B38400; break;
+ case 57600: speed2 = B57600; break;
+ case 115200: speed2 = B115200; break;
+ case 230400: speed2 = B230400; break;
+ case 460800: speed2 = B460800; break;
+ case 500000: speed2 = B500000; break;
+ case 576000: speed2 = B576000; break;
+ case 921600: speed2 = B921600; break;
+ case 1000000: speed2 = B1000000; break;
+ case 1152000: speed2 = B1152000; break;
+ case 1500000: speed2 = B1500000; break;
+ case 2000000: speed2 = B2000000; break;
+ case 2500000: speed2 = B2500000; break;
+ case 3000000: speed2 = B3000000; break;
+ case 3500000: speed2 = B3500000; break;
+ case 4000000: speed2 = B4000000; break;
+ }
+
+ /* This should work on all systems because it is done according to POSIX */
+ cfsetispeed(&t, speed2);
+ cfsetospeed(&t, speed2);
+
+ if (tcsetattr(d->hPhone, TCSADRAIN, &t) == -1) {
+ serial_close(s);
+ GSM_OSErrorInfo(s,"tcsetattr in serial_setspeed");
+ return ERR_DEVICECHANGESPEEDERROR;
+ }
+
+ return ERR_NONE;
+}
+
+static int serial_read(GSM_StateMachine *s, void *buf, size_t nbytes)
+{
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+ struct timeval timeout2;
+ fd_set readfds;
+ int actual = 0;
+
+ FD_ZERO(&readfds);
+ FD_SET(d->hPhone, &readfds);
+
+ timeout2.tv_sec = 0;
+ timeout2.tv_usec = 1;
+
+ if (select(d->hPhone+1, &readfds, NULL, NULL, &timeout2)) {
+ actual = read(d->hPhone, buf, nbytes);
+ if (actual == -1) GSM_OSErrorInfo(s,"serial_read");
+ }
+ return actual;
+}
+
+static int serial_write(GSM_StateMachine *s, void *buf, size_t nbytes)
+{
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+ int ret;
+ size_t actual = 0;
+
+ do {
+ ret = write(d->hPhone, (unsigned char *)buf, nbytes - actual);
+ if (ret < 0 && errno == EAGAIN) continue;
+ if (ret < 0) {
+ if (actual != nbytes) GSM_OSErrorInfo(s,"serial_write");
+ return actual;
+ }
+ actual += ret;
+ buf += ret;
+ if (s->ConnectionType == GCT_FBUS2PL2303) my_sleep(1);
+ } while (actual < nbytes);
+ return actual;
+}
+
+GSM_Device_Functions SerialDevice = {
+ serial_open,
+ serial_close,
+ serial_setparity,
+ serial_setdtrrts,
+ serial_setspeed,
+ serial_read,
+ serial_write
+};
+
+#endif
+#endif
+#endif
+
+/* How should editor hadle tabs in this file? Add editor commands here.
+ * vim: noexpandtab sw=8 ts=8 sts=8:
+ */
diff --git a/gammu/emb/common/device/serial/ser_unx.h b/gammu/emb/common/device/serial/ser_unx.h
new file mode 100644
index 0000000..ca8fe5a
--- a/dev/null
+++ b/gammu/emb/common/device/serial/ser_unx.h
@@ -0,0 +1,22 @@
+
+#ifndef WIN32
+#ifndef DJGPP
+#ifndef unixserial_h
+#define unixserial_h
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+
+typedef struct {
+ int hPhone;
+ struct termios old_settings;
+} GSM_Device_SerialData;
+
+#endif
+#endif
+#endif
+
+/* How should editor hadle tabs in this file? Add editor commands here.
+ * vim: noexpandtab sw=8 ts=8 sts=8:
+ */
diff --git a/gammu/emb/common/device/serial/ser_w32.c b/gammu/emb/common/device/serial/ser_w32.c
new file mode 100644
index 0000000..9fa0135
--- a/dev/null
+++ b/gammu/emb/common/device/serial/ser_w32.c
@@ -0,0 +1,340 @@
+/* (c) 2002-2004 by Marcin Wiacek */
+/* based on some work from Gnokii, MSDN and others */
+
+#include "../../gsmstate.h"
+
+#ifdef GSM_ENABLE_SERIALDEVICE
+#ifdef WIN32
+
+#include <windows.h>
+#include <string.h>
+#include <stdio.h>
+#include <io.h>
+#include <memory.h>
+
+#include "../../gsmcomon.h"
+#include "ser_w32.h"
+
+static GSM_Error serial_close(GSM_StateMachine *s)
+{
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+
+ /* Disables all monitored events for device */
+ SetCommMask(d->hPhone, 0);
+
+ /* Discards all characters from input/output buffer and terminates
+ * pending read/write operations
+ */
+ PurgeComm(d->hPhone, PURGE_TXABORT | PURGE_RXABORT |
+ PURGE_TXCLEAR | PURGE_RXCLEAR);
+
+ /* Clears the DTR (data-terminal-ready) signal */
+ EscapeCommFunction(d->hPhone, CLRDTR);
+
+ /* Restores old settings */
+ if (SetCommState(d->hPhone, &d->old_settings)==0) {
+ GSM_OSErrorInfo(s, "SetCommState in serial_close");
+ }
+
+ /* Closes device */
+ if (CloseHandle(d->hPhone)==0) {
+ GSM_OSErrorInfo(s, "CloseHandle in serial_close");
+ }
+
+ return ERR_NONE;
+}
+
+static GSM_Error serial_open (GSM_StateMachine *s)
+{
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+ DCB dcb;
+ unsigned char DeviceName[80],DeviceName2[80];
+ int i;
+#ifdef GSM_ENABLE_FBUS2DKU5
+ HKEY hKey;
+ DWORD DeviceNameLen, KeyNameLen;
+ unsigned char KeyName[100];
+#endif
+
+ strcpy(DeviceName2,s->CurrentConfig->Device);
+
+#ifdef GSM_ENABLE_FBUS2DKU5
+ if (s->ConnectionType == GCT_FBUS2DKU5) {
+ smprintf(s,"Reading DKU5 device\n");
+ DeviceName2[0] = 0;
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) {
+ smprintf(s,"Error opening key\n");
+ return ERR_DEVICENOTWORK;
+ }
+ i = 0;
+ while(1) {
+ DeviceNameLen = 80;
+ KeyNameLen = 100;
+ if (RegEnumValue(hKey,i,KeyName,&KeyNameLen,NULL,NULL,DeviceName2,&DeviceNameLen) != ERROR_SUCCESS) {
+ smprintf(s,"Error reading key value\n");
+ return ERR_DEVICENOTWORK;
+ }
+// smprintf(s,"Key name is %s, value is %s\n",KeyName,DeviceName2);
+ if (!strncmp(KeyName,"\\Device\\AtmelVirtualPort",24)) break;
+ i++;
+ }
+ RegCloseKey(hKey);
+ if (strlen(DeviceName2) == 0) return ERR_DEVICENOTWORK;
+ smprintf(s,"DKU5 device is \"%s\"\n",DeviceName2);
+ //nodriver
+ }
+#endif
+
+ if ((s->ConnectionType == GCT_FBUS2DKU5) ||
+ (!strncmp(DeviceName2,"com",3) && strlen(DeviceName2)>3)) {
+ sprintf(DeviceName,"\\\\.\\COM%i",atoi(DeviceName2+3));
+ } else {
+ strcpy(DeviceName,DeviceName2);
+ }
+
+ smprintf(s,"Device is %s\n",DeviceName);
+
+ /* Allows for reading/writing, no device sharing */
+ d->hPhone = CreateFile(DeviceName,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ 0,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
+ NULL);
+
+ if (d->hPhone == INVALID_HANDLE_VALUE) {
+ i = GetLastError();
+ GSM_OSErrorInfo(s, "CreateFile in serial_open");
+ if (i == 2) return ERR_DEVICENOTWORK; //can't find specified file
+ if (i == 5) return ERR_DEVICEBUSY; //access denied
+ if (i == 31) return ERR_DEVICENOTWORK; //attached device not working
+ if (i == 123) return ERR_DEVICENOTEXIST;
+ return ERR_DEVICEOPENERROR;
+ }
+
+ d->old_settings.DCBlength = sizeof(DCB);
+ if (GetCommState(d->hPhone, &d->old_settings)==0) {
+ GSM_OSErrorInfo(s, "ReadDevice in serial_open");
+ return ERR_DEVICEREADERROR;
+ }
+
+ /* When char will be received, we will receive notifications */
+ SetCommMask(d->hPhone, EV_RXCHAR);
+
+ /* Sets size for input/output buffer */
+ SetupComm(d->hPhone, 4096, 4096);
+
+ /* Discards all characters from input/output buffer and terminates
+ * pending read/write operations
+ */
+ PurgeComm(d->hPhone, PURGE_TXABORT | PURGE_RXABORT |
+ PURGE_TXCLEAR | PURGE_RXCLEAR);
+
+ memcpy(&dcb, &d->old_settings, sizeof(DCB));
+
+ dcb.ByteSize = 8;
+ dcb.Parity = NOPARITY;
+ dcb.StopBits = ONESTOPBIT;
+
+ /* No Xon/Xof flow control */
+// dcb.fOutX = false;
+// dcb.fInX = false;
+
+ /* Hardware flow control */
+// dcb.fOutxDsrFlow = true;
+// dcb.fOutxCtsFlow = true;
+// dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
+// dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
+
+ /* Initialise the port settings */
+ if (SetCommState(d->hPhone, &dcb)==0) {
+ GSM_OSErrorInfo(s, "WriteDevice in serial_open");
+ return ERR_DEVICEOPENERROR;
+ }
+
+ return ERR_NONE;
+}
+
+static GSM_Error serial_setparity (GSM_StateMachine *s, bool parity)
+{
+ DCB dcb;
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+
+ dcb.DCBlength = sizeof(DCB);
+ if (GetCommState(d->hPhone, &dcb)==0) {
+ GSM_OSErrorInfo(s, "ReadDevice in serial_setparity");
+ return ERR_DEVICEREADERROR;
+ }
+
+ if (parity) {
+ dcb.Parity = ODDPARITY;
+ } else {
+ dcb.Parity = NOPARITY;
+ }
+
+ if (SetCommState(d->hPhone, &dcb)==0) {
+ GSM_OSErrorInfo(s, "WriteDevice in serial_setparity");
+ return ERR_DEVICEPARITYERROR;
+ }
+
+ return ERR_NONE;
+}
+
+static GSM_Error serial_setdtrrts(GSM_StateMachine *s, bool dtr, bool rts)
+{
+ DCB dcb;
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+
+ dcb.DCBlength = sizeof(DCB);
+ if (GetCommState(d->hPhone, &dcb)==0) {
+ GSM_OSErrorInfo(s, "ReadDevice in serial_setdtrrts");
+ return ERR_DEVICEREADERROR;
+ }
+
+ dcb.fOutxDsrFlow = 0;
+ dcb.fDtrControl = DTR_CONTROL_DISABLE;
+ if (dtr) dcb.fDtrControl = DTR_CONTROL_ENABLE;
+
+ dcb.fOutxCtsFlow = 0;
+ dcb.fRtsControl = RTS_CONTROL_DISABLE;
+ if (rts) dcb.fRtsControl = RTS_CONTROL_ENABLE;
+
+ /* no software (Xon/Xof) flow control */
+ dcb.fInX = dcb.fOutX = 0;
+
+ if (SetCommState(d->hPhone, &dcb)==0) {
+ GSM_OSErrorInfo(s, "WriteDevice in serial_setdtrrts");
+ return ERR_DEVICEDTRRTSERROR;
+ }
+
+ /* the rest of function checks, if setting was really done */
+
+ dcb.DCBlength = sizeof(DCB);
+ GetCommState(d->hPhone, &dcb);
+
+ dbgprintf("Serial device:");
+ dbgprintf(" DTR is ");
+ switch (dcb.fDtrControl) {
+ case DTR_CONTROL_ENABLE : dbgprintf("up"); break;
+ case DTR_CONTROL_DISABLE : dbgprintf("down"); break;
+ case DTR_CONTROL_HANDSHAKE : dbgprintf("handshake"); break;
+ }
+ dbgprintf(", RTS is ");
+ switch (dcb.fRtsControl) {
+ case RTS_CONTROL_ENABLE : dbgprintf("up"); break;
+ case RTS_CONTROL_DISABLE : dbgprintf("down"); break;
+ case RTS_CONTROL_HANDSHAKE : dbgprintf("handshake"); break;
+ case RTS_CONTROL_TOGGLE : dbgprintf("toggle"); break;
+ }
+ dbgprintf("\n");
+ if ( dtr && dcb.fDtrControl != DTR_CONTROL_ENABLE ) return ERR_DEVICEDTRRTSERROR;
+ if (!dtr && dcb.fDtrControl != DTR_CONTROL_DISABLE) return ERR_DEVICEDTRRTSERROR;
+ if ( rts && dcb.fRtsControl != RTS_CONTROL_ENABLE ) return ERR_DEVICEDTRRTSERROR;
+ if (!rts && dcb.fRtsControl != RTS_CONTROL_DISABLE) return ERR_DEVICEDTRRTSERROR;
+
+ return ERR_NONE;
+}
+
+static GSM_Error serial_setspeed(GSM_StateMachine *s, int speed)
+{
+ DCB dcb;
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+
+ dcb.DCBlength = sizeof(DCB);
+ if (GetCommState(d->hPhone, &dcb)==0) {
+ GSM_OSErrorInfo(s, "ReadDevice in serial_setspeed");
+ return ERR_DEVICEREADERROR;
+ }
+
+ dcb.BaudRate = speed;
+
+ if (SetCommState(d->hPhone, &dcb)==0) {
+ GSM_OSErrorInfo(s, "WriteDevice in serial_setspeed");
+ return ERR_DEVICECHANGESPEEDERROR;
+ }
+
+ return ERR_NONE;
+}
+
+static int serial_read(GSM_StateMachine *s, void *buf, size_t nbytes)
+{
+ COMSTAT ComStat;
+ DWORD ErrorFlags, Length;
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+
+ /* Gets information about a communications error and
+ * current status of device
+ */
+ ClearCommError(d->hPhone, &ErrorFlags, &ComStat);
+ Length = ComStat.cbInQue;
+
+ /* Nothing to read */
+ if (Length <= 0) return Length;
+
+ /* Read without problems */
+ if (ReadFile(d->hPhone, buf, Length, &Length, &d->osRead)) return Length;
+
+ if (GetLastError() != ERROR_IO_PENDING) {
+ GSM_OSErrorInfo(s, "serial_read1");
+ Length = 0;
+ ClearCommError(d->hPhone, &ErrorFlags, &ComStat);
+ return Length;
+ }
+
+ while(1) {
+ if (GetOverlappedResult(d->hPhone,&d->osRead, &Length, TRUE)) break;
+ if (GetLastError() != ERROR_IO_INCOMPLETE) {
+ GSM_OSErrorInfo(s, "serial_read2");
+ /* an error occurred, try to recover */
+ ClearCommError(d->hPhone, &ErrorFlags, &ComStat);
+ break;
+ }
+ }
+ return Length;
+}
+
+static int serial_write(GSM_StateMachine *s, void *buf, size_t nbytes)
+{
+ DWORD BytesWritten,ErrorFlags,BytesSent=0;
+ COMSTAT ComStat;
+ GSM_Device_SerialData *d = &s->Device.Data.Serial;
+
+ if (WriteFile(d->hPhone, buf, nbytes, &BytesSent, &d->osWrite)) return BytesSent;
+
+ if (GetLastError() != ERROR_IO_PENDING) {
+ GSM_OSErrorInfo(s, "serial_write1");
+ ClearCommError(d->hPhone, &ErrorFlags, &ComStat);
+ return BytesSent;
+ }
+
+ while (1) {
+ if (GetOverlappedResult(d->hPhone, &d->osWrite, &BytesWritten, TRUE)) break;
+ if (GetLastError() != ERROR_IO_INCOMPLETE) {
+ GSM_OSErrorInfo(s, "serial_write2");
+ ClearCommError(d->hPhone, &ErrorFlags, &ComStat);
+ break;
+ }
+ BytesSent += BytesWritten;
+ }
+ BytesSent += BytesWritten;
+
+ return BytesSent;
+}
+
+GSM_Device_Functions SerialDevice = {
+ serial_open,
+ serial_close,
+ serial_setparity,
+ serial_setdtrrts,
+ serial_setspeed,
+ serial_read,
+ serial_write
+};
+
+#endif
+#endif
+
+/* How should editor hadle tabs in this file? Add editor commands here.
+ * vim: noexpandtab sw=8 ts=8 sts=8:
+ */
diff --git a/gammu/emb/common/device/serial/ser_w32.h b/gammu/emb/common/device/serial/ser_w32.h
new file mode 100644
index 0000000..d226f32
--- a/dev/null
+++ b/gammu/emb/common/device/serial/ser_w32.h
@@ -0,0 +1,19 @@
+
+#ifdef WIN32
+#ifndef winserial_h
+#define winserial_h
+
+#include <windows.h>
+
+typedef struct {
+ HANDLE hPhone;
+ DCB old_settings;
+ OVERLAPPED osWrite,osRead;
+} GSM_Device_SerialData;
+
+#endif
+#endif
+
+/* How should editor hadle tabs in this file? Add editor commands here.
+ * vim: noexpandtab sw=8 ts=8 sts=8:
+ */