Welcome to MacBoardz.com!
FAQFAQ    SearchSearch      ProfileProfile    Private MessagesPrivate Messages   Log inLog in

RFCOMM channel to Lego NXT

 
   Macintosh computer (Home) -> General Discussion RSS
Next:  Mac Family Ref Manual (two editions)  
Author Message
outpaddling

External


Since: Dec 09, 2007
Posts: 3



(Msg. 1) Posted: Sun Dec 09, 2007 9:41 am
Post subject: RFCOMM channel to Lego NXT
Archived from groups: comp>sys>mac>programmer>misc (more info?)

Dear Mac programming heroes:

I'm developing a cross-platform C API for communicating with the Lego
NXT via USB and Bluetooth. The code is mostly functional on FreeBSD,
Linux, and OS X, with the exception of Bluetooth on OS X, which is
vastly different from the other two platforms' socket-based
interfaces.

I wrote a simple program to figure out the IOBluetooth framework, and
using just the online developer docs was able to complete almost
everything I need. I *thought* I was one line of code away from done
when I discovered that OS X has no support for synchronous reads on an
RFCOMM connection. (Argh.) I.e., there is no read analog to
IOBluetoothRFCOMMChannelWrite(). OK, fine. Asynchronous I/O will
probably become part of my API down the road anyway.

From what I was able to dig up on the docs and on the WEB, it seems I
need to set up a CFRunLoop in my program in order to make my callback
function work, but I haven't found any hints as to what type of input
source is required or how to set it up.

Everything works up to the point of sending a command to the NXT, and
I wrote a callback based on examples in the IOBluetooth framework
docs. The IOBluetoothRFCOMMChannelWrite() call indicates success, but
I can't yet read the response, presumably because my CFRunLoop is not
set up properly.

My code and the output are below. If someone can suggest a simple way
to set up the CFRunLoop, I'd really appreciate it. I'm hoping to
avoid buying yet another computer book I'll probably never look at
again.

Thanks.

Code:
#include <stdio.h>
#include <CoreFoundation/CFArray.h>
#include <CoreFoundation/CFNumber.h>
#include <IOBluetooth/IOBluetoothUserLib.h>

#define NXT_RFCOMM_CHANNEL_ID 1

void listener(IOBluetoothRFCOMMChannelRef rfcommChannel, void
*data, UInt16 l
ength, void *refCon);

int main(int argc,char *argv[])

{
BluetoothDeviceAddress btAddr =
{{0x00,0x16,0x53,0x01,0x11,0xB9}};
BluetoothDeviceName btName;
IOBluetoothRFCOMMChannelRef rfcommChannel;
IOBluetoothDeviceRef btDevice;
CFStringRef name;
char raw_name[100],
cmd[100];
int new_data;
/* Create a BluetoothDeviceAddress for use in setting up a
connection */
btDevice = IOBluetoothDeviceCreateWithAddress(&btAddr);
printf("btDevice = %p\n",btDevice);

/* Quick test of address */
if
( IOBluetoothDeviceRemoteNameRequest(btDevice,NULL,NULL,btName) !=
kIOReturnSuccess )
{
fprintf(stderr,"IOBluetoothDeviceRemoteNameRequest() failed.
\n");
return 1;
}
else
{
name = IOBluetoothDeviceGetName(btDevice);
printf("CFString name = %p\n",name);
if ( CFStringGetCString(name,raw_name,
100,kCFStringEncodingISOLatin1) )
printf("Device name = %s\n",raw_name);
else
fprintf(stderr,"CFStringGetCString() failed.\n");
}

/* Open an RFCOMM channel to the NXT. The underlying baseband
connection is automatically opened if needed. The process
isn't finished until a listener callback function is
registered,
since synchronous reads are not supported. */
if
( IOBluetoothDeviceOpenRFCOMMChannel(btDevice,NXT_RFCOMM_CHANNEL_ID,
&rfcommChannel) != kIOReturnSuccess )
{
fprintf(stderr,"IOBluetoothDeviceOpenRFCOMMChannel() failed.
\n");
return 1;
}
else
{
printf("Successfully opened RFCOMM channel!\n");
}

/* Check Max Transmission unit, just for kicks. */
printf("MTU = %d
\n",IOBluetoothRFCOMMChannelGetMTU(rfcommChannel));

/* Send a get-battery-level command and check response */
if ( IOBluetoothRFCOMMChannelRegisterIncomingDataListener(
rfcommChannel,listener,&new_data) == 0 )
{
/* Get battery level */
cmd[0] = 0x00;
cmd[1] = 0x0B;
new_data = 0; /* Make use of the refCon arg by setting a
flag. */
if ( IOBluetoothRFCOMMChannelWrite(rfcommChannel,cmd,2,0) ==
0 )
{
printf("Successfully sent command!\n");

/* Now read back response. This will require using the
callback function, since there is no synchronous read
function. */

// Use CFMessagePort?
//
CFRunLoopAddSource(CFRunLoopGetCurrent(),RFCOMMchannel,kCFRunLoopC
ommonModes);
//CFRunLoopRun();
}
else
{
fprintf(stderr,"IOBluetoothRFCOMMChannelWrite() failed.
\n");
}
}
else
{

fprintf(stderr,"IOBluetoothRFCOMMChannelRegisterIncomingDataListener()
f
ailed.\n");
}

if ( IOBluetoothRFCOMMChannelCloseChannel(rfcommChannel) != 0 )
fprintf(stderr,"IOBluetoothRFCOMMChannelCloseChannel() failed.
\n");
IOBluetoothDeviceCloseConnection(btDevice);
return 0;
}


void listener(IOBluetoothRFCOMMChannelRef rfcommChannel, void
*data,
UInt16 length, void *refCon)

{
int c,
*new_data = refCon;

puts("Got data!");
for (c=0; c<length; ++c)
printf("%02X ",((char *)data)[c]);
putchar('\n');
*new_data = 1;
//CFRunLoopStop(CFRunLoopGetCurrent());
}

Output:

btDevice = 0x305740
CFString name = 0x308790
Device name = NXT
Successfully opened RFCOMM channel!
MTU = 126
Successfully sent command!

 >> Stay informed about: RFCOMM channel to Lego NXT 
Back to top
Login to vote
Michael Ash1

External


Since: Jun 01, 2004
Posts: 617



(Msg. 2) Posted: Sun Dec 09, 2007 2:14 pm
Post subject: Re: RFCOMM channel to Lego NXT [Login to view extended thread Info.]
Archived from groups: per prev. post (more info?)

outpaddling wrote:
> My code and the output are below. If someone can suggest a simple way
> to set up the CFRunLoop, I'd really appreciate it. I'm hoping to
> avoid buying yet another computer book I'll probably never look at
> again.

I don't really know the answer to your specific question, but there are
examples in /Developer/Examples/Bluetooth which appear to do what you're
trying to do. If you haven't taken a look at them yet, maybe they can show
you the missing piece.

--
Michael Ash
Rogue Amoeba Software

 >> Stay informed about: RFCOMM channel to Lego NXT 
Back to top
Login to vote
outpaddling

External


Since: Dec 09, 2007
Posts: 3



(Msg. 3) Posted: Mon Dec 17, 2007 8:09 pm
Post subject: Re: RFCOMM channel to Lego NXT [Login to view extended thread Info.]
Archived from groups: per prev. post (more info?)

On Dec 9, 2:14 pm, Michael Ash wrote:
> outpaddling wrote:
> > My code and the output are below. If someone can suggest a simple way
> > to set up the CFRunLoop, I'd really appreciate it. I'm hoping to
> > avoid buying yet another computer book I'll probably never look at
> > again.
>
> I don't really know the answer to your specific question, but there are
> examples in /Developer/Examples/Bluetooth which appear to do what you're
> trying to do. If you haven't taken a look at them yet, maybe they can show
> you the missing piece.
>
> --
> Michael Ash
> Rogue Amoeba Software

Thanks for the suggestion. I looked at the examples, but
unfortunately, they don't seem to demonstrate what I need to do.

I tried just calling CFRunLoopRun() with the default env, but the
handler doesn't fire. Some other docs I found suggested that I need
to add a source using CFRunLoopAddSource(), but I haven't been able to
figure out how as yet.

Thanks anyway,

Jason
 >> Stay informed about: RFCOMM channel to Lego NXT 
Back to top
Login to vote
Michael Ash1

External


Since: Jun 01, 2004
Posts: 617



(Msg. 4) Posted: Tue Dec 18, 2007 10:03 am
Post subject: Re: RFCOMM channel to Lego NXT [Login to view extended thread Info.]
Archived from groups: per prev. post (more info?)

outpaddling wrote:
> I tried just calling CFRunLoopRun() with the default env, but the
> handler doesn't fire. Some other docs I found suggested that I need
> to add a source using CFRunLoopAddSource(), but I haven't been able to
> figure out how as yet.

The way this stuff *usually* works is, you create the object, set up a
callback, then there's some function to create a CFRunLoopSourceRef from
the thing you're working with. For example, a CFMessagePort has a function
called CFMessagePortCreateRunLoopSource which returns a CFRunLoopSourceRef
and you can then add that to the CFRunLoop.

I don't know if that's really how it works with Bluetooth, and I don't
know what the function would be if so, but I guess that's the sort of
thing to look for.

--
Michael Ash
Rogue Amoeba Software
 >> Stay informed about: RFCOMM channel to Lego NXT 
Back to top
Login to vote
outpaddling

External


Since: Dec 09, 2007
Posts: 3



(Msg. 5) Posted: Wed Dec 19, 2007 4:50 pm
Post subject: Re: RFCOMM channel to Lego NXT [Login to view extended thread Info.]
Archived from groups: per prev. post (more info?)

On Dec 18, 10:03 am, Michael Ash wrote:
> outpaddling wrote:
> > I tried just calling CFRunLoopRun() with the default env, but the
> > handler doesn't fire. Some other docs I found suggested that I need
> > to add a source using CFRunLoopAddSource(), but I haven't been able to
> > figure out how as yet.
>
> The way this stuff *usually* works is, you create the object, set up a
> callback, then there's some function to create a CFRunLoopSourceRef from
> the thing you're working with. For example, a CFMessagePort has a function
> called CFMessagePortCreateRunLoopSource which returns a CFRunLoopSourceRef
> and you can then add that to the CFRunLoop.
>
> I don't know if that's really how it works with Bluetooth, and I don't
> know what the function would be if so, but I guess that's the sort of
> thing to look for.
>
> --
> Michael Ash
> Rogue Amoeba Software

I actually already got this far, and found in the Xcode docs:

CFMessagePortCreateRunLoopSource
Creates a CFRunLoopSource object for a CFMessagePort object.

CFRunLoopSourceRef CFMessagePortCreateRunLoopSource (
CFAllocatorRef allocator,
CFMessagePortRef ms,
CFIndex order
);

Problem is, I don't know where to get the CFMessagePortRef from. I
browsed the framework docs, and found some possibilities, each with
additional parameters that I didn't know where to get. At this point
I just had to chuckle. The time required to explore every possible
branch of this trail grows geometrically with each additional layer,
and I'm not even certain that CFMEssagePort is the right path to
follow. It's clear that I would need to know a lot about Carbon/Cocoa
programming, including several core frameworks, in order to solve this
one on my own, and I just don't have the time, so I have to hope I can
find an analogous code example. It would have been so simple if Apple
would have just let us do synchronous reads. Oh well...

Thanks for the ideas,

Jason
 >> Stay informed about: RFCOMM channel to Lego NXT 
Back to top
Login to vote
Display posts from previous:   
Related Topics:
modify OS X keyboard mappings - Hello, I need to have access to the french characters. I can do this with the Canadian - CSA keyboard. However, that keyboard has a "," as a decimal. I need a ".". Changing it in the international control panel does not change...

Shared memory - Hello all, If you're not on the beach maybe you can give me a little help. I need to implement shared memory between my application and a helper tool. At first I tried CFMessageProts. This works, but if you transport huge amounts of data the data get al...

mouse freeze - My mouse has started to freeze on booting (OS 9.03). The problem is intermittent, after touching the mouse it sometimes moves just slightly and freezes again. Can someone help? Boris vainerb@access4less.net

Can ZBasic still run on Mac OSX??? - Hi all, I was going through some older floppies and ran across some of my programs from high school written in ZBasic on the old mac classic. Is it possible to find a copy of ZBasic that'll run on a Powermac G4 with OSX Jaguar? I know this app probabl...

Anti Microsoft Video Game for Macs: "Redmond Raid" - Attention People of Earth, Some "Disgruntled Penguin" created an Anti Microsoft Game for Macs online... check it out: http://www.RedmondRaid.com So, the Axis of evil includes Iraq, Iran, and North Korea..... According to a "Disgruntled ...
   Macintosh computer (Home) -> General Discussion All times are: Pacific Time (US & Canada)
Page 1 of 1

 
You can post new topics in this forum
You can reply to topics in this forum
You can edit your posts in this forum
You can delete your posts in this forum
You can vote in polls in this forum



[ Contact us | Terms of Service/Privacy Policy ]