gnokii-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnokii] 01/01: Rewrite MacOS X Bluetooth implementation


From: Daniele Forsi
Subject: [gnokii] 01/01: Rewrite MacOS X Bluetooth implementation
Date: Sun, 21 Feb 2016 10:28:19 +0000

dforsi pushed a commit to branch master
in repository gnokii.

commit 70f8eeb3ec4bb4ba75220c8b03aa444bd9fabc7f
Author: Fabrizio Gennari <address@hidden>
Date:   Tue Feb 2 22:50:15 2016 +0100

    Rewrite MacOS X Bluetooth implementation
    
    The old one used outdated APIs that have not compiled since OS X 10.7 Lion.
---
 ChangeLog                      |    2 +
 common/devices/Makefile.am     |   12 ++-
 common/devices/osxbluetooth.c  |  205 ----------------------------------------
 common/devices/osxbluetooth.m  |  183 +++++++++++++++++++++++++++++++++++
 configure.ac                   |   32 +++----
 include/devices/Makefile.am    |    1 -
 include/devices/osxbluetooth.h |   49 ----------
 7 files changed, 207 insertions(+), 277 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index cf6bb03..b2016d7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -36,6 +36,8 @@
                                                     (Daniele Forsi)
     o add ids for Nokia 7230 and 7230-1c to misc.c only; use
       model=series40                                 (Raphaël Droz)
+    o New MacOS X Bluetooth implementation: old one used has not
+      compiled since OS X 10.7 Lion              (Fabrizio Gennari)
  * at driver updates
     o in the default case autodetect if PDU SMS starts with SMSC
                                                     (Daniele Forsi)
diff --git a/common/devices/Makefile.am b/common/devices/Makefile.am
index 8d389f0..9beef37 100644
--- a/common/devices/Makefile.am
+++ b/common/devices/Makefile.am
@@ -9,16 +9,20 @@ WIN32_FILES = \
 
 UNIX_FILES = \
        unixserial.c \
-       unixbluetooth.c \
-       osxbluetooth.c \
        unixirda.c \
        tcp.c \
        socketphonet.c
 
+if FOR_MAC
+UNIX_SPECIFIC_FILES = osxbluetooth.m
+else
+UNIX_SPECIFIC_FILES = unixbluetooth.c
+endif
+
 if WIN32
 PLATFORM_FILES = $(WIN32_FILES)
 else
-PLATFORM_FILES = $(UNIX_FILES)
+PLATFORM_FILES = $(UNIX_FILES) $(UNIX_SPECIFIC_FILES)
 endif
 
 libDEVICES_la_SOURCES = \
@@ -36,5 +40,5 @@ libDEVICES_la_LIBADD =                \
        $(BLUETOOTH_LIBS)       \
        $(TCP_LIBS)
 
-EXTRA_DIST = $(WIN32_FILES) $(UNIX_FILES)
+EXTRA_DIST = $(WIN32_FILES) $(UNIX_FILES) $(UNIX_SPECIFIC_FILES)
 
diff --git a/common/devices/osxbluetooth.c b/common/devices/osxbluetooth.c
deleted file mode 100644
index 254bf52..0000000
--- a/common/devices/osxbluetooth.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
-
-  G N O K I I
-
-  A Linux/Unix toolset and driver for the mobile phones.
-
-  This file is part of gnokii.
-
-  Copyright (C) 1999-2000  Hugh Blemings & Pavel Jan�k ml.
-  Copyright (C) 2003       Siegfried Schloissnig
-
-*/
-
-#include "config.h"
-
-#ifdef HAVE_BLUETOOTH_MACOSX
-
-#include "compat.h"
-#include "devices/osxbluetooth.h"
-#include "misc.h"
-#include "gnokii.h"
-#include "devices/unixbluetooth.h"
-
-/* ----- bluetooth io thread ----- */
-
-static void thread_rfcommDataListener(IOBluetoothRFCOMMChannelRef 
rfcommChannel,
-                               void* data, UInt16 length, void* refCon)
-{
-       threadContext *pContext = (threadContext *)refCon;
-       void *pBuffer = malloc(length);
-       dataBlock *pDataBlock = (dataBlock *)malloc(sizeof(dataBlock));
-
-       memcpy(pBuffer, data, length);
-
-       pDataBlock->pData = pBuffer;
-       pDataBlock->nSize = length;
-
-       pthread_mutex_lock(&(pContext->mutexWait));
-       CFArrayAppendValue(pContext->arrDataReceived, pDataBlock);
-       pthread_mutex_unlock(&(pContext->mutexWait));
-}
-
-static void *thread_main(void *pArg)
-{
-       threadContext* pContext = (threadContext *)pArg;
-       IOBluetoothDeviceRef device = 
IOBluetoothDeviceCreateWithAddress(&(pContext->deviceAddress));
-       IOBluetoothRFCOMMChannelRef rfcommChannel;
-
-       if (IOBluetoothDeviceOpenRFCOMMChannel(device, pContext->nChannel,
-                                     &rfcommChannel) != kIOReturnSuccess) {
-               rfcommChannel = 0;
-       } else {
-               /* register an incoming data listener */
-               if 
(IOBluetoothRFCOMMChannelRegisterIncomingDataListener(rfcommChannel,
-                        thread_rfcommDataListener, pArg) != kIOReturnSuccess) {
-                   rfcommChannel = 0;
-               }
-       }
-
-       pContext->rfcommChannel = rfcommChannel;
-
-       pthread_mutex_unlock(&(pContext->mutexWait));
-
-       /* start the runloop */
-       CFRunLoopRun();
-}
-
-/* ---- bluetooth io thread ---- */
-
-int bluetooth_open(const char* addr, uint8_t channel, struct gn_statemachine* 
state)
-{
-       /* create the thread context and start the thread */
-       CFStringRef strDevice;
-       pthread_t threadID;
-       threadContext *pContext = (threadContext 
*)malloc(sizeof(threadContext));
-
-       strDevice = CFStringCreateWithCString(kCFAllocatorDefault, addr, 
kCFStringEncodingMacRomanLatin1);
-       IOBluetoothNSStringToDeviceAddress(strDevice, &pContext->deviceAddress);
-       CFRelease(strDevice);
-
-       pContext->arrDataReceived = CFArrayCreateMutable(kCFAllocatorDefault, 
0, NULL);
-       pContext->rfcommChannel = 0;
-       pContext->nChannel = channel;
-
-       pthread_mutex_init(&(pContext->mutexWait), NULL);
-       pthread_mutex_lock(&(pContext->mutexWait));     /* lock */
-
-       pthread_create(&(pContext->threadID), NULL, thread_main, pContext);
-
-       /* wait until main finishes its initialization */
-       pthread_mutex_lock(&(pContext->mutexWait));
-       /* unblock the mutex */
-       pthread_mutex_unlock(&(pContext->mutexWait));
-
-       if (pContext->rfcommChannel == 0)
-               return -1;
-       else
-               /* return the thread context as the file descriptor */
-               return (int)pContext;
-}
-
-int bluetooth_close(int fd, struct gn_statemachine *state)
-{
-       threadContext *pContext = (threadContext *)fd;
-        IOBluetoothDeviceRef device;
-
-       sleep(2);
-
-       if (fd != -1 && pContext->rfcommChannel > 0) {
-               /* de-register the callback */
-               
IOBluetoothRFCOMMChannelRegisterIncomingDataListener(pContext->rfcommChannel, 
NULL, NULL);
-
-               /* close channel and device connection */
-               IOBluetoothRFCOMMChannelCloseChannel(pContext->rfcommChannel);
-               device = 
IOBluetoothRFCOMMChannelGetDevice(pContext->rfcommChannel);
-               IOBluetoothDeviceCloseConnection(device);
-               /* IOBluetoothObjectRelease(pContext->rfcommChannel); */
-               IOBluetoothObjectRelease(device);
-       }
-
-       return 1;
-}
-
-int bluetooth_write(int fd, const __ptr_t bytes, int size, struct 
gn_statemachine *state)
-{
-       threadContext *pContext = (threadContext *)fd;
-
-       if (IOBluetoothRFCOMMChannelWrite(pContext->rfcommChannel, bytes, size, 
TRUE) != kIOReturnSuccess)
-               return -1;
-
-       return size;
-}
-
-int bluetooth_read(int fd, __ptr_t bytes, int size, struct gn_statemachine 
*state)
-{
-       threadContext *pContext = (threadContext *)fd;
-       int nOffset = 0;
-       int nBytes = 0;
-        dataBlock* pDataBlock;
-
-       /* no data received so far */
-       if (CFArrayGetCount(pContext->arrDataReceived) == 0)
-               return 0;
-
-       while (CFArrayGetCount(pContext->arrDataReceived) != 0) {
-               pthread_mutex_lock(&(pContext->mutexWait));
-               pDataBlock = 
(dataBlock*)CFArrayGetValueAtIndex(pContext->arrDataReceived, 0);
-               pthread_mutex_unlock(&(pContext->mutexWait));
-
-               if (pDataBlock->nSize == size) {
-                       /* copy data and remove block */
-                       memcpy(bytes + nOffset, pDataBlock->pData, size);
-
-                       pthread_mutex_lock(&(pContext->mutexWait));
-                       CFArrayRemoveValueAtIndex(pContext->arrDataReceived, 0);
-                       pthread_mutex_unlock(&(pContext->mutexWait));
-
-                       free(pDataBlock->pData);
-                       free(pDataBlock);
-
-                       return nBytes + size;
-               } else if (pDataBlock->nSize > size) {
-                       /* copy data and update block contents */
-                       memcpy(bytes + nOffset, pDataBlock->pData, size);
-                       memmove(pDataBlock->pData, pDataBlock->pData + size, 
pDataBlock->nSize - size);
-                       pDataBlock->nSize -= size;
-                       return nBytes + size;
-               } else { /* pDataBlock->nSize < size */
-                       /* copy data and remove block */
-                       memcpy(bytes + nOffset, pDataBlock->pData, 
pDataBlock->nSize);
-
-                       size -= pDataBlock->nSize;
-                       nOffset += pDataBlock->nSize;
-                       nBytes += pDataBlock->nSize;
-
-                       pthread_mutex_lock(&(pContext->mutexWait));
-                       CFArrayRemoveValueAtIndex(pContext->arrDataReceived, 0);
-                       pthread_mutex_unlock(&(pContext->mutexWait));
-
-                       free(pDataBlock->pData);
-                       free(pDataBlock);
-               }
-       }
-
-       return nBytes;
-}
-
-int bluetooth_select(int fd, struct timeval *timeout, struct gn_statemachine 
*state)
-{
-       threadContext *pContext = (threadContext *)fd;
-       int nRetVal = 0;
-
-       usleep(timeout->tv_usec);
-
-       pthread_mutex_lock(&(pContext->mutexWait));
-
-       if (CFArrayGetCount(pContext->arrDataReceived) > 0)
-               nRetVal = 1;
-
-       pthread_mutex_unlock(&(pContext->mutexWait));
-
-       return nRetVal;
-}
-
-#endif /* HAVE_BLUETOOTH_MACOSX */
diff --git a/common/devices/osxbluetooth.m b/common/devices/osxbluetooth.m
new file mode 100644
index 0000000..6216cc5
--- /dev/null
+++ b/common/devices/osxbluetooth.m
@@ -0,0 +1,183 @@
+/*
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the mobile phones.
+
+  This file is part of gnokii.
+
+  Copyright (C) 2015       Fabrizio Gennari
+
+*/
+
+#include "config.h"
+
+#ifdef HAVE_BLUETOOTH_MACOSX
+
+#include <IOBluetooth/objc/IOBluetoothRFCOMMChannel.h>
+#include <IOBluetooth/objc/IOBluetoothDevice.h>
+
+#include "devices/unixbluetooth.h"
+
+static NSMutableDictionary *queues;
+static int next_fd = 1;
+
address@hidden GnokiiOSXBluetooth : NSObject <IOBluetoothRFCOMMChannelDelegate> 
{
address@hidden
+    NSMutableData *queue;
+    IOBluetoothRFCOMMChannel *channel;
+}
+- (BOOL)connect:(const char*)addr chid:(BluetoothRFCOMMChannelID)channelID;
+- (int)select:(CFAbsoluteTime)timeoutDate;
+- (int)read:(__ptr_t)bytes size:(int)size;
+- (BOOL)write:(const __ptr_t *)data length:(int)length;
address@hidden
+
address@hidden GnokiiOSXBluetooth
+- (id)init {
+    if ((self = [super init])) {
+        queue = [[NSMutableData alloc] init];
+    }
+    return self;
+}
+
+- (BOOL)connect:(const char*)addr chid:(BluetoothRFCOMMChannelID)channelID {
+    NSString *address = [[[NSString alloc] initWithCString:addr 
encoding:NSASCIIStringEncoding] autorelease];
+    IOBluetoothDevice* btDevice = [[IOBluetoothDevice 
deviceWithAddressString:address] autorelease];
+    return btDevice != nil &&
+    [btDevice openRFCOMMChannelSync:&channel withChannelID:channelID 
delegate:self] == kIOReturnSuccess; // after connection it is established.. the 
delegates methoed are triggered.
+}
+
+-(BOOL)write:(const __ptr_t *)data length:(int)length {
+    int i;\
+    IOReturn ret = [channel writeSync:(void*)data length:(UInt16)length];
+    return ret == kIOReturnSuccess;
+}
+
+- (void)dealloc {
+    if (channel != nil) {
+        [channel closeChannel];
+        [[channel getDevice] closeConnection];
+        [channel release];
+    }
+    [queue release];
+    [super dealloc];
+}
+
+- (int)waitForData:(NSTimeInterval)timeout {
+    int ret = -1;
+    if ([queue length] <= 0 && [channel isOpen]) {
+        NSTimer *timer = nil;
+        if (timeout > 0){
+            timer =     [NSTimer scheduledTimerWithTimeInterval:timeout
+             target:self
+             selector:@selector(timerElapsed:)
+             userInfo:nil
+             repeats:NO];
+        }
+        CFRunLoopRun();
+        if (timer != nil){
+            if ([timer isValid])
+                [timer invalidate];
+            else
+                ret = 0;
+        }
+    }
+    if ([queue length] > 0)
+        return 1;
+    return ret;
+}
+
+- (int)select:(NSTimeInterval)timeout {
+    return [self waitForData:timeout];
+}
+
+-(int)read:(__ptr_t)bytes size:(int)size {
+    if (![self waitForData:0])
+        return -1;
+
+    if (size > [queue length])
+        size = [queue length];
+    memcpy (bytes, [queue mutableBytes], size);
+    NSRange range = {0, size};
+    [queue replaceBytesInRange:range withBytes:nil length:0];
+    return size;
+}
+
+- (void)rfcommChannelData:(IOBluetoothRFCOMMChannel*)rfcommChannel data:(void 
*)dataPointer length:(size_t)dataLength {
+    int i;
+    [queue appendBytes:dataPointer length:dataLength];
+    if ([queue length] > 0)
+        CFRunLoopStop(CFRunLoopGetCurrent());
+}
+
+- (void)rfcommChannelClosed:(IOBluetoothRFCOMMChannel*)rfcommChannel {
+    if (channel == rfcommChannel)
+        CFRunLoopStop(CFRunLoopGetCurrent());
+}
+- (void) timerElapsed:(NSTimer*) timer {
+    CFRunLoopStop(CFRunLoopGetCurrent());
+}
address@hidden
+
+int bluetooth_open(const char* addr, uint8_t channel_num, struct 
gn_statemachine* state)
+{
+    if (queues == nil)
+        queues = [NSMutableDictionary dictionaryWithCapacity:1];
+    GnokiiOSXBluetooth *q = [[GnokiiOSXBluetooth alloc] init];
+    if (![q connect:addr chid:(BluetoothRFCOMMChannelID)channel_num]) { // 
after connection it is established.. the delegates methoed are triggered.
+        [q release];
+        return -1;
+    }
+    int ret = next_fd++;
+    [queues setObject:q forKey:@(ret)];
+    return ret;
+}
+
+int bluetooth_write(int fd, const __ptr_t bytes, int size, struct 
gn_statemachine *state)
+{
+    if (queues == nil)
+        return -1;
+    GnokiiOSXBluetooth *q = [queues objectForKey:@(fd)];
+    sleep(2);
+    if (q == nil
+        || ![q write:bytes length:size])
+        return -1;
+
+    return size;
+}
+
+int bluetooth_read(int fd, __ptr_t bytes, int size, struct gn_statemachine 
*state)
+{
+    if (queues == nil)
+        return -1;
+    GnokiiOSXBluetooth *q = [queues objectForKey:@(fd)];
+    if (q == nil)
+        return -1;
+    return [q read:bytes size:size];
+}
+
+int bluetooth_select(int fd, struct timeval *timeout, struct gn_statemachine 
*state)
+{
+    if (queues == nil)
+        return -1;
+    GnokiiOSXBluetooth *q = [queues objectForKey:@(fd)];
+    if (q == nil)
+        return -1;
+
+    return [q select:(NSTimeInterval)(timeout->tv_sec + timeout->tv_usec / 
1000000.0)];
+}
+
+int bluetooth_close(int fd, struct gn_statemachine *state)
+{
+    if (queues == nil)
+        return -1;
+    GnokiiOSXBluetooth *q = [queues objectForKey:@(fd)];
+    if (q == nil)
+        return -1;
+    [q release];
+    [queues removeObjectForKey:@(fd)];
+    return 1;
+}
+
+#endif
diff --git a/configure.ac b/configure.ac
index ecae200..e6cefb5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -54,6 +54,7 @@ AC_PROG_CC
 AM_PROG_CC_C_O
 AC_PROG_CPP
 AC_PROG_LEX
+AC_PROG_OBJC
 # If there's no flex/lex utility and there's no generated common/gnvcal.c 
file, we won't be able to compile
 if test "x$LEX" = "x:" && test ! -f common/gnvcal.c; then
        echo "You need one of the following:"
@@ -545,26 +546,20 @@ fi
 dnl ======================== Checks for MacOSX Bluetooth support
 if test `uname -s` = "Darwin" ; then
        if test "$enable_bluetooth" = "yes" -a "$USE_BLUETOOTH" = "no"; then
-               AC_MSG_NOTICE([checking for the MacOS X Bluetooth support])
-               AC_CHECK_HEADERS(CoreFoundation/CoreFoundation.h)
-               AC_CHECK_HEADERS(IOBluetooth/Bluetooth.h)
-               AC_CHECK_HEADERS([IOBluetooth/IOBluetoothUserLib.h], [], [],
-                       [[#ifdef HAVE_COREFOUNDATION_COREFOUNDATION_H
-                         #  include <CoreFoundation/CoreFoundation.h>
-                         #endif
-                         #ifdef HAVE_IOBLUETOOTH_BLUETOOTH_H
-                         #  include <IOBluetooth/Bluetooth.h>
-                         #endif
-                       ]])
-               AC_TRY_COMPILE([#include <CoreFoundation/CoreFoundation.h>
-                               #include <IOBluetooth/Bluetooth.h>
-                               #include <IOBluetooth/IOBluetoothUserLib.h>],
-
-                               [CFStringRef strDevice;
-                               strDevice = CFStringCreateWithCString(NULL, 
NULL, NULL);
-                               IOBluetoothNSStringToDeviceAddress(NULL, 
NULL);],
+               AC_LANG_PUSH([Objective C])
+               AC_CHECK_HEADERS(IOBluetooth/objc/IOBluetoothRFCOMMChannel.h)
+               AC_CHECK_HEADERS(IOBluetooth/objc/IOBluetoothDevice.h)
+               AC_MSG_CHECKING([for MacOS X Bluetooth support])
+               AC_TRY_COMPILE([#include 
<IOBluetooth/objc/IOBluetoothRFCOMMChannel.h>
+               #include <IOBluetooth/objc/IOBluetoothDevice.h>],
+                               [
+                               IOBluetoothDevice* btDevice = 
[[IOBluetoothDevice deviceWithAddressString:@"00:00:00:00:00:00"] autorelease];
+                           ],
+                       AC_MSG_RESULT(yes)
                        ac_cv_have_iobluetooth=yes,
+                       AC_MSG_RESULT(no)
                        ac_cv_have_iobluetooth=no)
+               AC_LANG_POP([Objective C])
 
                if test $ac_cv_have_iobluetooth = yes; then
                        AC_DEFINE(HAVE_BLUETOOTH, 1, [Whether Bluetooth is 
available])
@@ -575,6 +570,7 @@ if test `uname -s` = "Darwin" ; then
                fi
        fi
 fi
+AM_CONDITIONAL([FOR_MAC], [test x$ac_cv_have_iobluetooth = xyes])
 
 dnl ======================== Checks for FreeBSD/netgraph Bluetooth support
 if test `uname -s` = "FreeBSD" ; then
diff --git a/include/devices/Makefile.am b/include/devices/Makefile.am
index f892c02..2b5058d 100644
--- a/include/devices/Makefile.am
+++ b/include/devices/Makefile.am
@@ -3,7 +3,6 @@ EXTRA_HEADERS = \
                dku2libusb.h \
                irda.h \
                linuxirda.h \
-               osxbluetooth.h \
                tcp.h \
                tekram.h \
                unixbluetooth.h \
diff --git a/include/devices/osxbluetooth.h b/include/devices/osxbluetooth.h
deleted file mode 100644
index 8de6bf1..0000000
--- a/include/devices/osxbluetooth.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-
-  G N O K I I
-
-  A Linux/Unix toolset and driver for the mobile phones.
-
-  This file is part of gnokii.
-
-  Copyright (C) 1999, 2000 Hugh Blemings & Pavel Jan�k ml.
-  Copyright (C) 2003       Siegfried Schloissnig
-
-*/
-
-#ifndef _gnokii_osx_bluetooth_h
-#define _gnokii_osx_bluetooth_h
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <IOBluetooth/Bluetooth.h>
-#include <IOBluetooth/IOBluetoothUserLib.h>
-#include <pthread.h>
-
-typedef struct {
-       IOBluetoothRFCOMMChannelRef rfcommChannel;
-       IOReturn ioReturnValue;
-       pthread_t threadID;
-
-       BluetoothDeviceAddress deviceAddress;
-       uint8_t nChannel;
-
-       pthread_mutex_t mutexWait;
-
-       CFMutableArrayRef arrDataReceived;
-} threadContext;
-
-typedef struct {
-       void *pData;
-       unsigned int nSize;
-} dataBlock;
-
-#endif /* _gnokii_osx_bluetooth_h */



reply via email to

[Prev in Thread] Current Thread [Next in Thread]