[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 */