20 files changed, 2131 insertions, 0 deletions
diff --git a/gammu/emb/common/device/bluetoth/affix.c b/gammu/emb/common/device/bluetoth/affix.c new file mode 100644 index 0000000..30a917b --- a/dev/null +++ b/gammu/emb/common/device/bluetoth/affix.c @@ -0,0 +1,44 @@ +/* (c) 2004 by Marcin Wiacek */ + +#include "../../gsmstate.h" + +#ifdef GSM_ENABLE_BLUETOOTHDEVICE +#ifdef GSM_ENABLE_AFFIX + +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <unistd.h> + +#include "../../gsmcomon.h" +#include "../devfunc.h" +#include "bluetoth.h" + +GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device) +{ + d->hPhone = fd; + return ERR_NONE; +} + +#ifdef BLUETOOTH_RF_SEARCHING + +static GSM_Error bluetooth_checkdevice(GSM_StateMachine *s, bdaddr_t *bdaddr, struct search_context *context) +{ +} + +GSM_Error bluetooth_findchannel(GSM_StateMachine *s) +{ + return error; +} + +#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/bluetoth/affix.h b/gammu/emb/common/device/bluetoth/affix.h new file mode 100644 index 0000000..896ecbe --- a/dev/null +++ b/gammu/emb/common/device/bluetoth/affix.h @@ -0,0 +1,3 @@ + +GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device); +GSM_Error bluetooth_findchannel(GSM_StateMachine *s); diff --git a/gammu/emb/common/device/bluetoth/blue_w32.c b/gammu/emb/common/device/bluetoth/blue_w32.c new file mode 100644 index 0000000..a631c9f --- a/dev/null +++ b/gammu/emb/common/device/bluetoth/blue_w32.c @@ -0,0 +1,216 @@ +/* (c) 2003-2004 by Marcin Wiacek and Intra */ + +#include "../../gsmstate.h" + +#ifdef GSM_ENABLE_BLUETOOTHDEVICE +#ifdef WIN32 + +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <windows.h> +#include <io.h> + +#include "../../misc/coding/coding.h" +#include "../../gsmcomon.h" +#include "../devfunc.h" +#include "bluetoth.h" +#include "blue_w32.h" + +GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device) +{ + GSM_Device_BlueToothData *d = &s->Device.Data.BlueTooth; + WSADATA wsaData; + SOCKADDR_BTH sab; + int i; + + smprintf(s, "Connecting to RF channel %i\n",port); + + WSAStartup(MAKEWORD(1,1), &wsaData); + + d->hPhone = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); + if (d->hPhone == INVALID_SOCKET) { + i = GetLastError(); + GSM_OSErrorInfo(s, "Socket in bluetooth_open"); + if (i == 10041) return ERR_DEVICENODRIVER;//unknown socket type + return ERR_UNKNOWN; + } + + memset (&sab, 0, sizeof(sab)); + sab.port = port; + sab.addressFamily = AF_BTH; + sab.btAddr = 0; + for (i=0;i<(int)strlen(device);i++) { + if (device[i] >='0' && device[i] <='9') { + sab.btAddr = sab.btAddr * 16; + sab.btAddr = sab.btAddr + (device[i]-'0'); + } + if (device[i] >='a' && device[i] <='f') { + sab.btAddr = sab.btAddr * 16; + sab.btAddr = sab.btAddr + (device[i]-'a'+10); + } + if (device[i] >='A' && device[i] <='F') { + sab.btAddr = sab.btAddr * 16; + sab.btAddr = sab.btAddr + (device[i]-'A'+10); + } + } + dbgprintf("Remote Bluetooth device is %04x%08x\n", + GET_NAP(sab.btAddr), GET_SAP(sab.btAddr)); + + if (connect (d->hPhone, (struct sockaddr *)&sab, sizeof(sab)) != 0) { + i = GetLastError(); + GSM_OSErrorInfo(s, "Connect in bluetooth_open"); + if (i == 10060) return ERR_TIMEOUT; //remote device failed to respond + if (i == 10050) return ERR_DEVICENOTWORK; //socket operation connected with dead network + //noauth + close(d->hPhone); + return ERR_UNKNOWN; + } + + return ERR_NONE; +} + +#ifdef BLUETOOTH_RF_SEARCHING + +#pragma comment(lib, "irprops.lib") +#pragma comment(lib, "ws2_32.lib") + +static GSM_Error bluetooth_checkdevice(GSM_StateMachine *s, char *address, WSAPROTOCOL_INFO *protocolInfo) +{ + GSM_Device_BlueToothData *d = &s->Device.Data.BlueTooth; + WSAQUERYSET querySet; + DWORD flags; + GUID protocol; + int i, result; + BYTE buffer[2000]; + char addressAsString[1000]; + DWORD bufferLength, addressSize; + WSAQUERYSET *pResults = (WSAQUERYSET*)&buffer; + HANDLE handle; + GSM_Error error; + + memset(&querySet, 0, sizeof(querySet)); + querySet.dwSize = sizeof(querySet); + protocol = L2CAP_PROTOCOL_UUID; + querySet.lpServiceClassId = &protocol; + querySet.dwNameSpace = NS_BTH; + querySet.lpszContext = address; + + flags = LUP_FLUSHCACHE | LUP_RETURN_NAME | + LUP_RETURN_TYPE | LUP_RETURN_ADDR | + LUP_RETURN_BLOB | LUP_RETURN_COMMENT; + + result = WSALookupServiceBegin(&querySet, flags, &handle); + if (result != 0) return ERR_UNKNOWN; + + bufferLength = sizeof(buffer); + while (1) { + result = WSALookupServiceNext(handle, flags, &bufferLength, pResults); + if (result != 0) break; + addressSize = sizeof(addressAsString); + addressAsString[0] = 0; + if (WSAAddressToString(pResults->lpcsaBuffer->RemoteAddr.lpSockaddr, + pResults->lpcsaBuffer->RemoteAddr.iSockaddrLength, protocolInfo, + addressAsString,&addressSize)==0) { + smprintf(s, "%s - ", addressAsString); + } + smprintf(s, "\"%s\"\n", pResults->lpszServiceInstanceName); + if (addressAsString[0] != 0) { + for (i=strlen(addressAsString)-1;i>0;i--) { + if (addressAsString[i] == ':') break; + } + if (bluetooth_checkservicename(s, pResults->lpszServiceInstanceName) == ERR_NONE) { + error = bluetooth_connect(s,atoi(addressAsString+i+1),address+1); + result = WSALookupServiceEnd(handle); + return error; + } + } + } + result = WSALookupServiceEnd(handle); + return ERR_NOTSUPPORTED; +} + +GSM_Error bluetooth_findchannel(GSM_StateMachine *s) +{ + GSM_Device_BlueToothData *d = &s->Device.Data.BlueTooth; + WSADATA wsaData; + int i, protocolInfoSize, result; + WSAPROTOCOL_INFO protocolInfo; + HANDLE handle; + DWORD flags; + WSAQUERYSET querySet; + BYTE buffer[2000]; + char addressAsString[1000]; + DWORD bufferLength, addressSize; + WSAQUERYSET *pResults = (WSAQUERYSET*)&buffer; + GSM_Error error; + + if (WSAStartup(MAKEWORD(2,2), &wsaData)!=0x00) return ERR_DEVICENODRIVER; + + d->hPhone = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); + if (d->hPhone == INVALID_SOCKET) { + i = GetLastError(); + GSM_OSErrorInfo(s, "Socket in bluetooth_open"); + if (i == 10041) return ERR_DEVICENODRIVER;//unknown socket type + return ERR_UNKNOWN; + } + + protocolInfoSize = sizeof(protocolInfo); + if (getsockopt(d->hPhone, SOL_SOCKET, SO_PROTOCOL_INFO, + (char*)&protocolInfo, &protocolInfoSize) != 0) + { + close(d->hPhone); + return ERR_UNKNOWN; + } + close(d->hPhone); + + if (!strcmp(s->CurrentConfig->Device,"com2:")) { + bufferLength = sizeof(buffer); + + flags = LUP_RETURN_NAME | LUP_CONTAINERS | + LUP_RETURN_ADDR | LUP_FLUSHCACHE | + LUP_RETURN_TYPE | LUP_RETURN_BLOB | LUP_RES_SERVICE; + + memset(&querySet, 0, sizeof(querySet)); + querySet.dwSize = sizeof(querySet); + querySet.dwNameSpace = NS_BTH; + + result = WSALookupServiceBegin(&querySet, flags, &handle); + if (result != 0) return ERR_UNKNOWN; + + while (1) { + result = WSALookupServiceNext(handle, flags, &bufferLength, pResults); + if (result != 0) break; + + smprintf(s, "\"%s\"", pResults->lpszServiceInstanceName); + + addressSize = sizeof(addressAsString); + addressAsString[0] = 0; + if (WSAAddressToString(pResults->lpcsaBuffer->RemoteAddr.lpSockaddr, + pResults->lpcsaBuffer->RemoteAddr.iSockaddrLength, &protocolInfo, + addressAsString,&addressSize)==0) { + smprintf(s, " - %s\n", addressAsString); + error = bluetooth_checkdevice(s, addressAsString,&protocolInfo); + if (error == ERR_NONE) { + result = WSALookupServiceEnd(handle); + return error; + } + } else smprintf(s, "\n"); + } + + result = WSALookupServiceEnd(handle); + return ERR_NOTSUPPORTED; + } else { + return bluetooth_checkdevice(s, s->CurrentConfig->Device,&protocolInfo); + } +} + +#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/bluetoth/blue_w32.h b/gammu/emb/common/device/bluetoth/blue_w32.h new file mode 100644 index 0000000..e457c92 --- a/dev/null +++ b/gammu/emb/common/device/bluetoth/blue_w32.h @@ -0,0 +1,188 @@ + +GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device); +GSM_Error bluetooth_findchannel(GSM_StateMachine *s); + +/* MS Platform SDK */ + +#ifndef __blue_w32_h +#define __blue_w32_h + +#include <pshpack1.h> // Without it compiled code hangs up BT stack + +typedef ULONGLONG BTH_ADDR, *PBTH_ADDR; + +#define NAP_MASK ((ULONGLONG) 0xFFFF00000000) +#define SAP_MASK ((ULONGLONG) 0x0000FFFFFFFF) + +#define NAP_BIT_OFFSET (8 * 4) +#define SAP_BIT_OFFSET (0) + +#define GET_NAP(_bth_addr) ((USHORT) (((_bth_addr) & NAP_MASK) >> NAP_BIT_OFFSET)) +#define GET_SAP(_bth_addr) ((ULONG) (((_bth_addr) & SAP_MASK) >> SAP_BIT_OFFSET)) + +#ifndef AF_BTH +#define AF_BTH 32 +#endif + +typedef struct _SOCKADDR_BTH { + USHORT addressFamily; // Always AF_BTH + BTH_ADDR btAddr; // Bluetooth device address + GUID serviceClassId; // [OPTIONAL] system will query SDP for port + ULONG port; // RFCOMM channel or L2CAP PSM +} SOCKADDR_BTH, *PSOCKADDR_BTH; + +#define BTHPROTO_RFCOMM 0x0003 + +#ifdef BLUETOOTH_RF_SEARCHING + +typedef struct _SOCKET_ADDRESS { + LPSOCKADDR lpSockaddr ; + INT iSockaddrLength ; +} SOCKET_ADDRESS, *PSOCKET_ADDRESS, FAR * LPSOCKET_ADDRESS ; + +typedef struct _CSADDR_INFO { + SOCKET_ADDRESS LocalAddr ; + SOCKET_ADDRESS RemoteAddr ; + INT iSocketType ; + INT iProtocol ; +} CSADDR_INFO, *PCSADDR_INFO, FAR * LPCSADDR_INFO ; + +typedef struct _AFPROTOCOLS { + INT iAddressFamily; + INT iProtocol; +} AFPROTOCOLS, *PAFPROTOCOLS, *LPAFPROTOCOLS; + +typedef enum _WSAEcomparator +{ + COMP_EQUAL = 0, + COMP_NOTLESS +} WSAECOMPARATOR, *PWSAECOMPARATOR, *LPWSAECOMPARATOR; + +typedef struct _WSAVersion +{ + DWORD dwVersion; + WSAECOMPARATOR ecHow; +}WSAVERSION, *PWSAVERSION, *LPWSAVERSION; + +typedef struct _WSAQuerySetA +{ + DWORD dwSize; + LPSTR lpszServiceInstanceName; + LPGUID lpServiceClassId; + LPWSAVERSION lpVersion; + LPSTR lpszComment; + DWORD dwNameSpace; + LPGUID lpNSProviderId; + LPSTR lpszContext; + DWORD dwNumberOfProtocols; + LPAFPROTOCOLS lpafpProtocols; + LPSTR lpszQueryString; + DWORD dwNumberOfCsAddrs; + LPCSADDR_INFO lpcsaBuffer; + DWORD dwOutputFlags; + LPBLOB lpBlob; +} WSAQUERYSET, WSAQUERYSETA, *PWSAQUERYSETA, *LPWSAQUERYSETA; + +DEFINE_GUID(L2CAP_PROTOCOL_UUID, 0x00000100, 0x0000, 0x1000, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB); + +#ifndef NS_BTH +# define NS_BTH 16 +#endif + +#define LUP_CONTAINERS 0x0002 +#define LUP_RETURN_NAME 0x0010 +#define LUP_RETURN_TYPE 0x0020 +#define LUP_RETURN_COMMENT 0x0080 +#define LUP_RETURN_ADDR 0x0100 +#define LUP_RETURN_BLOB 0x0200 +#define LUP_FLUSHCACHE 0x1000 +#define LUP_RES_SERVICE 0x8000 + +#define WSAAPI FAR PASCAL + +#ifndef WINSOCK_API_LINKAGE +#ifdef DECLSPEC_IMPORT +#define WINSOCK_API_LINKAGE DECLSPEC_IMPORT +#else +#define WINSOCK_API_LINKAGE +#endif +#endif + +WINSOCK_API_LINKAGE INT WSAAPI +WSALookupServiceBeginA( + IN LPWSAQUERYSETA lpqsRestrictions, + IN DWORD dwControlFlags, + OUT LPHANDLE lphLookup + ); + +#define WSALookupServiceBegin WSALookupServiceBeginA + +WINSOCK_API_LINKAGE INT WSAAPI +WSALookupServiceNextA( + IN HANDLE hLookup, + IN DWORD dwControlFlags, + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSAQUERYSETA lpqsResults + ); + +#define WSALookupServiceNext WSALookupServiceNextA + +WINSOCK_API_LINKAGE INT WSAAPI WSALookupServiceEnd(IN HANDLE hLookup); + +#define MAX_PROTOCOL_CHAIN 7 + +typedef struct _WSAPROTOCOLCHAIN { + int ChainLen; /* the length of the chain, */ + /* length = 0 means layered protocol, */ + /* length = 1 means base protocol, */ + /* length > 1 means protocol chain */ + DWORD ChainEntries[MAX_PROTOCOL_CHAIN]; /* a list of dwCatalogEntryIds */ +} WSAPROTOCOLCHAIN, FAR * LPWSAPROTOCOLCHAIN; + +#define WSAPROTOCOL_LEN 255 + +typedef struct _WSAPROTOCOL_INFOA { + DWORD dwServiceFlags1; + DWORD dwServiceFlags2; + DWORD dwServiceFlags3; + DWORD dwServiceFlags4; + DWORD dwProviderFlags; + GUID ProviderId; + DWORD dwCatalogEntryId; + WSAPROTOCOLCHAIN ProtocolChain; + int iVersion; + int iAddressFamily; + int iMaxSockAddr; + int iMinSockAddr; + int iSocketType; + int iProtocol; + int iProtocolMaxOffset; + int iNetworkByteOrder; + int iSecurityScheme; + DWORD dwMessageSize; + DWORD dwProviderReserved; + CHAR szProtocol[WSAPROTOCOL_LEN+1]; +} WSAPROTOCOL_INFOA, FAR * LPWSAPROTOCOL_INFOA; + +typedef WSAPROTOCOL_INFOA WSAPROTOCOL_INFO; + +#define SO_PROTOCOL_INFOA 0x2004 /* WSAPROTOCOL_INFOA structure */ +#define SO_PROTOCOL_INFO SO_PROTOCOL_INFOA + +WINSOCK_API_LINKAGE INT WSAAPI +WSAAddressToStringA( + IN LPSOCKADDR lpsaAddress, + IN DWORD dwAddressLength, + IN LPWSAPROTOCOL_INFOA lpProtocolInfo, + IN OUT LPSTR lpszAddressString, + IN OUT LPDWORD lpdwAddressStringLength + ); + +#define WSAAddressToString WSAAddressToStringA + +#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/bluetoth/bluetoth.c b/gammu/emb/common/device/bluetoth/bluetoth.c new file mode 100644 index 0000000..c20e04b --- a/dev/null +++ b/gammu/emb/common/device/bluetoth/bluetoth.c @@ -0,0 +1,85 @@ +/* (c) 2003-2004 by Marcin Wiacek and Marcel Holtmann and others */ + +#include "../../gsmstate.h" + +#ifdef GSM_ENABLE_BLUETOOTHDEVICE +#ifndef DJGPP + +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> + +#include "../../misc/coding/coding.h" +#include "../../gsmcomon.h" +#include "../devfunc.h" +#include "bluetoth.h" + +#ifdef GSM_ENABLE_BLUEZ +# include "bluez.h" +#endif +#ifdef GSM_ENABLE_AFFIX +# include "affix.h" +#endif +#ifdef WIN32 +# include "blue_w32.h" +#endif + +GSM_Error bluetooth_findrfchannel(GSM_StateMachine *s) +{ + GSM_Error error; + +#ifdef BLUETOOTH_RF_SEARCHING + if (!mystrncasecmp(s->CurrentConfig->Connection, "bluerf", 6)) return bluetooth_findchannel(s); +#endif + + switch (s->ConnectionType) { + case GCT_BLUEAT: + return bluetooth_connect(s,1,s->CurrentConfig->Device); + case GCT_BLUEOBEX: + return bluetooth_connect(s,9,s->CurrentConfig->Device); + case GCT_BLUEPHONET: + error = bluetooth_connect(s,14,s->CurrentConfig->Device); //older Series 40 - 8910, 6310 + if (error == ERR_NONE) return error; + return bluetooth_connect(s,15,s->CurrentConfig->Device); //new Series 40 - 6310i, 6230 + default: + return ERR_UNKNOWN; + } +} + +static int bluetooth_read(GSM_StateMachine *s, void *buf, size_t nbytes) +{ + return socket_read(s, buf, nbytes, s->Device.Data.BlueTooth.hPhone); +} + +#ifdef WIN32 +static int bluetooth_write(GSM_StateMachine *s, unsigned char *buf, size_t nbytes) +#else +static int bluetooth_write(GSM_StateMachine *s, void *buf, size_t nbytes) +#endif +{ + return socket_write(s, buf, nbytes, s->Device.Data.BlueTooth.hPhone); +} + +static GSM_Error bluetooth_close(GSM_StateMachine *s) +{ + return socket_close(s, s->Device.Data.BlueTooth.hPhone); +} + +GSM_Device_Functions BlueToothDevice = { + bluetooth_findrfchannel, + bluetooth_close, + NONEFUNCTION, + NONEFUNCTION, + NONEFUNCTION, + bluetooth_read, + bluetooth_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/bluetoth/bluetoth.h b/gammu/emb/common/device/bluetoth/bluetoth.h new file mode 100644 index 0000000..8a7fdf4 --- a/dev/null +++ b/gammu/emb/common/device/bluetoth/bluetoth.h @@ -0,0 +1,15 @@ + +#ifndef DJGPP +#ifndef unixbluetooth_h +#define unixbluetooth_h + +typedef struct { + int hPhone; +} GSM_Device_BlueToothData; + +#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/bluetoth/bluez.c b/gammu/emb/common/device/bluetoth/bluez.c new file mode 100644 index 0000000..8a4807e --- a/dev/null +++ b/gammu/emb/common/device/bluetoth/bluez.c @@ -0,0 +1,207 @@ +/* Based on work by Marcel Holtmann and other authors of Bluez */ + +#include "../../gsmstate.h" + +#ifdef GSM_ENABLE_BLUETOOTHDEVICE +#ifdef GSM_ENABLE_BLUEZ + +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <unistd.h> +#include <bluetooth/bluetooth.h> +#include <bluetooth/rfcomm.h> +#include <bluetooth/sdp.h> +#include <bluetooth/sdp_lib.h> + +#include "../../gsmcomon.h" +#include "../devfunc.h" +#include "bluetoth.h" + +GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device) +{ + GSM_Device_BlueToothData *d = &s->Device.Data.BlueTooth; + struct sockaddr_rc laddr, raddr; + bdaddr_t bdaddr; + int fd; + + smprintf(s, "Connecting to RF channel %i\n",port); + + fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + if (fd < 0) { + dbgprintf("Can't create socket\n"); + return ERR_DEVICENODRIVER; + } + + bacpy(&laddr.rc_bdaddr, BDADDR_ANY); + laddr.rc_family = AF_BLUETOOTH; + laddr.rc_channel = 0; + + if (bind(fd, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) { + dbgprintf("Can't bind socket\n"); + close(fd); + return ERR_DEVICEOPENERROR; + } + + str2ba(device, &bdaddr); + bacpy(&raddr.rc_bdaddr, &bdaddr); + raddr.rc_family = AF_BLUETOOTH; + raddr.rc_channel = port; + + if (connect(fd, (struct sockaddr *)&raddr, sizeof(raddr)) < 0) { + dbgprintf("Can't connect\n"); + close(fd); + return ERR_DEVICEOPENERROR; + } + + d->hPhone = fd; + return ERR_NONE; +} + +#ifdef BLUETOOTH_RF_SEARCHING + +struct search_context { + char *svc; + uuid_t group; + int tree; + uint32_t handle; +}; + +static void print_service_desc(void *value, void *user) +{ + sdp_data_t *p = (sdp_data_t *)value; + int i = 0, proto = 0, *channel = (int *)user; + + for (; p; p = p->next, i++) { + switch (p->dtd) { + case SDP_UUID16: + case SDP_UUID32: + case SDP_UUID128: + proto = 1;//sdp_uuid_to_proto(&p->val.uuid); + break; + case SDP_UINT8: + if (proto == RFCOMM_UUID) { + (*channel) = p->val.uint8; + return; + } + break; + } + } +} + +void print_access_protos(value, user) +{ + sdp_list_t *protDescSeq = (sdp_list_t *)value; + int *channel = (int *)user; + + sdp_list_foreach(protDescSeq,print_service_desc,channel); +} + +static GSM_Error bluetooth_checkdevice(GSM_StateMachine *s, bdaddr_t *bdaddr, struct search_context *context) +{ + sdp_session_t *sess; + sdp_list_t *attrid, *search, *seq, *next, *proto = 0; + uint32_t range = 0x0000ffff; + char str[20]; + sdp_record_t *rec; + sdp_data_t *d; + bdaddr_t interface; + struct search_context subcontext; + int channel,channel2; + + bacpy(&interface,BDADDR_ANY); + + ba2str(bdaddr, str); + smprintf(s,"%s\n", str); + + sess = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY); + if (!sess) { + dbgprintf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno)); + return ERR_UNKNOWN; + } + + attrid = sdp_list_append(0, &range); + search = sdp_list_append(0, &context->group); + if (sdp_service_search_attr_req(sess, search, SDP_ATTR_REQ_RANGE, attrid, &seq)) { + dbgprintf("Service Search failed: %s\n", strerror(errno)); + sdp_close(sess); + return ERR_UNKNOWN; + } + sdp_list_free(attrid, 0); + sdp_list_free(search, 0); + + channel2 = -1; + for (; seq; seq = next) { + rec = (sdp_record_t *) seq->data; + + if (channel2 == -1) { + if (!context->tree) { + d = sdp_data_get(rec,SDP_ATTR_SVCNAME_PRIMARY); + + if (false) { + channel = -1; + sdp_list_foreach(proto,print_access_protos,&channel); + //sdp_list_free(proto,(sdp_free_func_t)sdp_data_free); + } + smprintf(s,"Channel %i",channel); + if (d) smprintf(s," - \"%s\"",d->val.str); + smprintf(s,"\n"); + if (channel2 == -1 && bluetooth_checkservicename(s, d->val.str) == ERR_NONE) { + channel2 = channel; + } + } + if (sdp_get_group_id(rec,&subcontext.group) != -1) { + memcpy(&subcontext, context, sizeof(struct search_context)); + if (subcontext.group.value.uuid16 != context->group.value.uuid16) bluetooth_checkdevice(s,bdaddr,&subcontext); + } + } + + next = seq->next; + free(seq); + //sdp_record_free(rec); + } + sdp_close(sess); + + if (channel2 != -1) return bluetooth_connect(s, channel2, str); + + return ERR_UNKNOWN; +} + +GSM_Error bluetooth_findchannel(GSM_StateMachine *s) +{ + inquiry_info ii[20]; + uint8_t count = 0; + int i; + struct search_context context; + GSM_Error error = ERR_NOTSUPPORTED; + + memset(&context, '\0', sizeof(struct search_context)); + //sdp_uuid16_create(&(context.group),PUBLIC_BROWSE_GROUP); + + if (!strcmp(s->CurrentConfig->Device,"/dev/ttyS1")) { + dbgprintf("Searching for devices\n"); + if (sdp_general_inquiry(ii, 20, 8, &count) < 0) { + return ERR_UNKNOWN; + } + } else { + count = 1; + str2ba(s->CurrentConfig->Device,&ii[0].bdaddr); + } + for (i=0;i<count;i++) { + error = bluetooth_checkdevice(s,&ii[i].bdaddr,&context); + if (error == ERR_NONE) return error; + } + return error; +} + +#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/bluetoth/bluez.h b/gammu/emb/common/device/bluetoth/bluez.h new file mode 100644 index 0000000..896ecbe --- a/dev/null +++ b/gammu/emb/common/device/bluetoth/bluez.h @@ -0,0 +1,3 @@ + +GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device); +GSM_Error bluetooth_findchannel(GSM_StateMachine *s); diff --git a/gammu/emb/common/device/devfunc.c b/gammu/emb/common/device/devfunc.c new file mode 100644 index 0000000..d31ebbf --- a/dev/null +++ b/gammu/emb/common/device/devfunc.c @@ -0,0 +1,266 @@ + +#include <string.h> +#ifdef WIN32 +# include <io.h> +#else +# include <errno.h> +# include <signal.h> +#endif + +#include "../gsmstate.h" + +#ifdef GSM_ENABLE_BLUETOOTHDEVICE +#ifdef BLUETOOTH_RF_SEARCHING + +GSM_Error bluetooth_checkservicename(GSM_StateMachine *s, char *name) +{ + if (s->ConnectionType == GCT_BLUEPHONET && strstr(name,"Nokia PC Suite")!=NULL) return ERR_NONE; + if (s->ConnectionType == GCT_BLUEOBEX && strstr(name,"OBEX") !=NULL) return ERR_NONE; + if (s->ConnectionType == GCT_BLUEAT && strstr(name,"COM 1") !=NULL) return ERR_NONE; + return ERR_UNKNOWN; +} + +#endif +#endif + +#if defined (GSM_ENABLE_BLUETOOTHDEVICE) || defined (GSM_ENABLE_IRDADEVICE) + +int socket_read(GSM_StateMachine *s, void *buf, size_t nbytes, int hPhone) +{ + fd_set readfds; +#ifdef WIN32 + struct timeval timer; +#endif + + FD_ZERO(&readfds); + FD_SET(hPhone, &readfds); +#ifndef WIN32 + if (select(hPhone+1, &readfds, NULL, NULL, 0)) { + return(read(hPhone, buf, nbytes)); + } +#else + memset(&timer,0,sizeof(timer)); + if (select(0, &readfds, NULL, NULL, &timer) != 0) { + return(recv(hPhone, buf, nbytes, 0)); + } +#endif + return 0; +} + +#ifdef WIN32 +int socket_write(GSM_StateMachine *s, unsigned char *buf, size_t nbytes, int hPhone) +#else +int socket_write(GSM_StateMachine *s, void *buf, size_t nbytes, int hPhone) +#endif +{ + int ret; + size_t actual = 0; + + do { + ret = send(hPhone, buf, nbytes - actual, 0); + if (ret < 0) { + if (actual != nbytes) GSM_OSErrorInfo(s,"socket_write"); + return actual; + } + actual += ret; + buf += ret; + } while (actual < nbytes); + + return actual; +} + +GSM_Error socket_close(GSM_StateMachine *s, int hPhone) +{ + shutdown(hPhone, 0); +#ifdef WIN32 + closesocket(hPhone); /*FIXME: error checking */ +#else + close(hPhone); /*FIXME: error checking */ +#endif + return ERR_NONE; +} + +#endif + +#ifdef ENABLE_LGPL + +GSM_Error lock_device(const char* port, char **lock_device) +{ + *lock_device = 0; + return ERR_NONE; +} + +bool unlock_device(char **lock_file) +{ + return true; +} + +#else + +#define max_buf_len 128 +#define lock_path "/var/lock/LCK.." + +/* Lock the device. Allocated string with a lock name is returned + * in lock_device + */ +GSM_Error lock_device(const char* port, char **lock_device) +{ +#ifndef WIN32 + char *lock_file = NULL; + char buffer[max_buf_len]; + const char *aux; + int fd, len; + GSM_Error error = ERR_NONE; + + dbgprintf("Locking device\n"); + + aux = strrchr(port, '/'); + /* Remove leading '/' */ + if (aux) { + aux++; + } else { + /* No / in port */ + aux = port; + } + len = strlen(aux) + strlen(lock_path); + + memset(buffer, 0, sizeof(buffer)); + lock_file = calloc(len + 1, 1); + if (!lock_file) { + dbgprintf("Out of memory error while locking device\n"); + return ERR_MOREMEMORY; + } + /* I think we don't need to use strncpy, as we should have enough + * buffer due to strlen results + */ + strcpy(lock_file, lock_path); + strcat(lock_file, aux); + + /* Check for the stale lockfile. + * The code taken from minicom by Miquel van Smoorenburg */ + if ((fd = open(lock_file, O_RDONLY)) >= 0) { + char buf[max_buf_len]; + int pid, n = 0; + + n = read(fd, buf, sizeof(buf) - 1); + close(fd); + if (n > 0) { + pid = -1; + if (n == 4) + /* Kermit-style lockfile. */ + pid = *(int *)buf; + else { + /* Ascii lockfile. */ + buf[n] = 0; + sscanf(buf, "%d", &pid); + } + if (pid > 0 && kill((pid_t)pid, 0) < 0 && errno == ESRCH) { + dbgprintf("Lockfile %s is stale. Overriding it..\n", lock_file); + sleep(1); + if (unlink(lock_file) == -1) { + dbgprintf("Overriding failed, please check the permissions\n"); + dbgprintf("Cannot lock device\n"); + error = ERR_PERMISSION; + goto failed; + } + } else { + dbgprintf("Device already locked by PID %d.\n", pid); + error = ERR_DEVICELOCKED; + goto failed; + } + } + /* this must not happen. because we could open the file */ + /* no wrong permissions are set. only reason could be */ + /* flock/lockf or a empty lockfile due to a broken binary */ + /* which is more likely */ + if (n == 0) { + dbgprintf("Unable to read lockfile %s.\n", lock_file); + dbgprintf("Please check for reason and remove the lockfile by hand.\n"); + dbgprintf("Cannot lock device\n"); + error = ERR_UNKNOWN; + goto failed; + } + } + + /* Try to create a new file, with 0644 mode */ + fd = open(lock_file, O_CREAT | O_EXCL | O_WRONLY, 0644); + if (fd == -1) { + if (errno == EEXIST) { + dbgprintf("Device seems to be locked by unknown process\n"); + error = ERR_DEVICEOPENERROR; + } else if (errno == EACCES) { + dbgprintf("Please check permission on lock directory\n"); + error = ERR_PERMISSION; + } else if (errno == ENOENT) { + dbgprintf("Cannot create lockfile %s. Please check for existence of path\n", lock_file); + error = ERR_UNKNOWN; + } else { + dbgprintf("Unknown error with creating lockfile %s\n", lock_file); + error = ERR_UNKNOWN; + } + goto failed; + } + sprintf(buffer, "%10ld gammu\n", (long)getpid()); + write(fd, buffer, strlen(buffer)); + close(fd); + *lock_device = lock_file; + return ERR_NONE; +failed: + free(lock_file); + *lock_device = 0; + return error; +#else + *lock_device = 0; + return ERR_NONE; +#endif +} + +/* Removes lock and frees memory */ +bool unlock_device(char **lock_file) +{ +#ifndef WIN32 + int err; + + if (!lock_file) { + dbgprintf("Cannot unlock device\n"); + return false; + } + err = unlink(*lock_file); + free(*lock_file); + *lock_file = NULL; + return (err + 1); +#else + return true; +#endif +} + +#endif + +int FindSerialSpeed(char *buffer) +{ + switch (atoi(buffer)) { + case 50 : return 50; + case 75 : return 75; + case 110 : return 110; + case 134 : return 134; + case 150 : return 150; + case 200 : return 200; + case 300 : return 300; + case 600 : return 600; + case 1200 : return 1200; + case 1800 : return 1800; + case 2400 : return 2400; + case 4800 : return 4800; + case 9600 : return 9600; + case 19200 : return 19200; + case 38400 : return 38400; + case 57600 : return 57600; + case 115200 : return 115200; + case 230400 : return 230400; + default : return 0; + } +} + +/* 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/devfunc.h b/gammu/emb/common/device/devfunc.h new file mode 100644 index 0000000..6e8fb62 --- a/dev/null +++ b/gammu/emb/common/device/devfunc.h @@ -0,0 +1,38 @@ + +#ifndef device_functions_h +#define device_functions_h + +#include "../gsmstate.h" + +#ifdef GSM_ENABLE_BLUETOOTHDEVICE +#ifdef BLUETOOTH_RF_SEARCHING + +GSM_Error bluetooth_checkservicename(GSM_StateMachine *s, char *name); + +#endif +#endif + +#if defined (GSM_ENABLE_BLUETOOTHDEVICE) || defined (GSM_ENABLE_IRDADEVICE) + +int socket_read(GSM_StateMachine *s, void *buf, size_t nbytes, int hPhone); + +#ifdef WIN32 +int socket_write(GSM_StateMachine *s, unsigned char *buf, size_t nbytes, int hPhone); +#else +int socket_write(GSM_StateMachine *s, void *buf, size_t nbytes, int hPhone); +#endif + +GSM_Error socket_close(GSM_StateMachine *s, int hPhone); + +#endif + +GSM_Error lock_device (const char* port, char **lock_device); +bool unlock_device (char **lock_file); + +int FindSerialSpeed(char *buffer); + +#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/irda/irda.c b/gammu/emb/common/device/irda/irda.c new file mode 100644 index 0000000..fef50ac --- a/dev/null +++ b/gammu/emb/common/device/irda/irda.c @@ -0,0 +1,187 @@ +/* (c) 2001-2004 by Marcin Wiacek */ +/* based on some work from Ralf Thelen and MyGnokii */ +/* based on some work from Gnokii and MSDN */ + +/* You have to include wsock32.lib library to MS VC project to compile it */ + +#include "../../gsmstate.h" + +#ifdef GSM_ENABLE_IRDADEVICE +#ifndef DJGPP + +#ifndef WIN32 +# include <stdlib.h> +# include <unistd.h> +# include <stdio.h> +# include <fcntl.h> +# include <errno.h> +# include <string.h> +# include <sys/time.h> +# include <sys/poll.h> +# include <sys/socket.h> +# include <sys/ioctl.h> +#else +# include <windows.h> +# include <io.h> +#endif + +#include "../../gsmcomon.h" +#include "../devfunc.h" +#include "irda.h" + +static bool irda_discover_device(GSM_StateMachine *state) +{ + GSM_Device_IrdaData *d = &state->Device.Data.Irda; + struct irda_device_list *list; + unsigned char *buf; + unsigned int sec; + int s, z, len, fd, i; + GSM_DateTime Date; + bool founddevice = false; +#ifdef WIN32 + int index; +#endif + + fd = socket(AF_IRDA, SOCK_STREAM, 0); + + /* can handle maximally 10 devices during discovering */ + len = sizeof(struct irda_device_list) + sizeof(struct irda_device_info) * 10; + buf = malloc(len); + list = (struct irda_device_list *)buf; + + /* Trying to find device during 2 seconds */ + for (z=0;z<2;z++) { + GSM_GetCurrentDateTime (&Date); + sec = Date.Second; + while (sec==Date.Second) { + s = len; + memset(buf, 0, s); + + if (getsockopt(fd, SOL_IRLMP, IRLMP_ENUMDEVICES, buf, &s) == 0) { + for (i = 0; i < (int)list->numDevice; i++) { + dbgprintf("Irda: found device \"%s\" (address %x) - ",list->Device[i].irdaDeviceName,list->Device[i].irdaDeviceID); + if (strcmp(GetModelData(NULL,NULL,list->Device[i].irdaDeviceName)->number,"") != 0) { + founddevice = true; + /* Model AUTO */ + if (state->CurrentConfig->Model[0]==0) strcpy(state->Phone.Data.Model,GetModelData(NULL,NULL,list->Device[i].irdaDeviceName)->number); + state->Phone.Data.ModelInfo = GetModelData(NULL,state->Phone.Data.Model,NULL); + } + if (founddevice) { + dbgprintf("correct\n"); +#ifdef WIN32 + for(index=0; index <= 3; index++) + d->peer.irdaDeviceID[index] = list->Device[i].irdaDeviceID[index]; +#else + d->peer.irdaDeviceID = list->Device[i].irdaDeviceID; +#endif + break; + } + dbgprintf("\n"); + } + } + if (founddevice) break; + my_sleep(10); + GSM_GetCurrentDateTime(&Date); + } + if (founddevice) break; + } + free(buf); + close(fd); + + return founddevice; +} + +static GSM_Error irda_open (GSM_StateMachine *s) +{ + GSM_Device_IrdaData *d = &s->Device.Data.Irda; + int fd = -1; +#ifdef WIN32 + int Enable9WireMode = 1; + WSADATA wsaData; + + WSAStartup(MAKEWORD(1,1), &wsaData); +#else + if (s->ConnectionType == GCT_IRDAAT) return ERR_SOURCENOTAVAILABLE; +#endif + + /* discovering devices */ + if (irda_discover_device(s)==false) return ERR_TIMEOUT; + + /* Creating socket */ + fd = socket(AF_IRDA, SOCK_STREAM, 0); + + d->peer.irdaAddressFamily = AF_IRDA; +#ifndef WIN32 + d->peer.sir_lsap_sel = LSAP_ANY; +#endif + switch (s->ConnectionType) { + case GCT_IRDAAT: + strcpy(d->peer.irdaServiceName, "IrDA:IrCOMM"); + +#ifdef WIN32 + if (setsockopt(fd, SOL_IRLMP, IRLMP_9WIRE_MODE, (const char *) &Enable9WireMode, + sizeof(int))==SOCKET_ERROR) return ERR_UNKNOWN; +#endif + break; + case GCT_IRDAPHONET: + strcpy(d->peer.irdaServiceName, "Nokia:PhoNet"); + break; + case GCT_IRDAOBEX: + /* IrDA:OBEX not supported by N3650 */ +// strcpy(d->peer.irdaServiceName, "IrDA:OBEX"); + + strcpy(d->peer.irdaServiceName, "OBEX"); + + /* Alternative server is "OBEX:IrXfer" */ + break; + default: + return ERR_UNKNOWN; + } + + /* Connecting to service */ + if (connect(fd, (struct sockaddr *)&d->peer, sizeof(d->peer))) { + dbgprintf("Can't connect to service %s\n",d->peer.irdaServiceName); + close(fd); + return ERR_NOTSUPPORTED; + } + + d->hPhone=fd; + + return ERR_NONE; +} + +static int irda_read(GSM_StateMachine *s, void *buf, size_t nbytes) +{ + return socket_read(s, buf, nbytes, s->Device.Data.Irda.hPhone); +} + +#ifdef WIN32 +static int irda_write(GSM_StateMachine *s, unsigned char *buf, size_t nbytes) +#else +static int irda_write(GSM_StateMachine *s, void *buf, size_t nbytes) +#endif +{ + return socket_write(s, buf, nbytes, s->Device.Data.Irda.hPhone); +} + +static GSM_Error irda_close(GSM_StateMachine *s) +{ + return socket_close(s, s->Device.Data.Irda.hPhone); +} + +GSM_Device_Functions IrdaDevice = { + irda_open, + irda_close, + NONEFUNCTION, + NONEFUNCTION, + NONEFUNCTION, + irda_read, + irda_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/irda/irda.h b/gammu/emb/common/device/irda/irda.h new file mode 100644 index 0000000..455e6af --- a/dev/null +++ b/gammu/emb/common/device/irda/irda.h @@ -0,0 +1,22 @@ + +#ifndef DJGPP +#ifndef unixirda_h +#define unixirda_h + +#ifndef WIN32 +# include "irda_unx.h" +#else +# include "irda_w32.h" +#endif + +typedef struct { + int hPhone; + struct sockaddr_irda peer; +} GSM_Device_IrdaData; + +#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/irda/irda_unx.h b/gammu/emb/common/device/irda/irda_unx.h new file mode 100644 index 0000000..8dbcb97 --- a/dev/null +++ b/gammu/emb/common/device/irda/irda_unx.h @@ -0,0 +1,61 @@ +/* part of irda.h available in Linux kernel source */ + +/********************************************************************* + * + * Filename: irda.h + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli <dagb@cs.uit.no> + * Created at: Mon Mar 8 14:06:12 1999 + * Modified at: Sat Dec 25 16:06:42 1999 + * Modified by: Dag Brattli <dagb@cs.uit.no> + * + * Copyright (c) 1999 Dag Brattli, All Rights Reserved. + * + * 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. + * + * Neither Dag Brattli nor University of Tromsų admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef __irda_unx_h +#define __irda_unx_h + +#include <sys/types.h> +#include <sys/socket.h> + +#define SOL_IRLMP 266 /* Same as SOL_IRDA for now */ +#define IRLMP_ENUMDEVICES 1 /* Return discovery log */ +#define LSAP_ANY 0xff + +struct sockaddr_irda { + sa_family_t irdaAddressFamily; /* AF_IRDA */ + u_int8_t sir_lsap_sel; /* LSAP selector */ + u_int32_t irdaDeviceID; /* Device address */ + char irdaServiceName[25]; /* Usually <service>:IrDA:TinyTP */ +}; + +struct irda_device_info { + u_int32_t saddr; /* Address of local interface */ + u_int32_t irdaDeviceID; /* Address of remote device */ + char irdaDeviceName[22]; /* Description */ + u_int8_t charset; /* Charset used for description */ + u_int8_t hints[2]; /* Hint bits */ +}; + +struct irda_device_list { + u_int32_t numDevice; + struct irda_device_info Device[1]; +}; + +#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/irda/irda_w32.h b/gammu/emb/common/device/irda/irda_w32.h new file mode 100644 index 0000000..daffa37 --- a/dev/null +++ b/gammu/emb/common/device/irda/irda_w32.h @@ -0,0 +1,35 @@ + +/* MS Platform SDK */ + +#ifndef __irda_w32_h +#define __irda_w32_h + +#define AF_IRDA 26 +#define SOL_IRLMP 0x00FF +#define IRLMP_ENUMDEVICES 0x00000010 +#define IRLMP_9WIRE_MODE 0x00000016 + +struct sockaddr_irda { + unsigned short irdaAddressFamily; + unsigned char irdaDeviceID[4]; + char irdaServiceName[25]; +}; + +struct irda_device_info { + unsigned char irdaDeviceID[4]; + char irdaDeviceName[22]; + unsigned char irdaDeviceHints1; + unsigned char irdaDeviceHints2; + unsigned char irdaCharSet; +}; + +struct irda_device_list { + ULONG numDevice; + struct irda_device_info Device[1]; +}; + +#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.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: + */ |