I figured out how to call all the nice ioctls the Broadcom linux driver provides (for linksys APs, cf. http://openwrt.org/) under OS X. This is possible since they use one driver source for everything.
This is based on the code found at http://www.macstumbler.com/airport.tar.gz
You can call arbitrary IOCTLs with this. What they do and what parameters they expect you'll need to figure out yourself.
The wlioctl.h file might give you a hint on what parameters each call expects, I have a list of implemented commands.
The airport.m tool as given must be called when Airport is turned OFF and will perform a loopback test, returning with an error if it fails.
First of all, add this to Apple80211.h
extern WIErr WirelessPrivate( WirelessContextPtr inContext, void* in_ptr, int in_bytes, void* out_ptr, int out_bytes);
It's the private command call. You can do lots more with it, but I'll leave it at calling the ioctls.
Next, find wlioctl.h, for example from http://files.wl500g.info/asus/wl500g/gpl/broadcom/src/include/wlioctl.h.
And finally, here's airport.m, based on the code from http://www.macstumbler.com/airport.tar.gz It's not clean at all. But you can make it so :)
#include <CoreFoundation/CoreFoundation.h> #include <Foundation/Foundation.h> #include <stdio.h> #include "Apple80211.h" /* you'll need to strip that file down as it doesn't compile as-is */ #include "wlioctl.h" WirelessContextPtr gWCtxt = NULL; char *gProgname; WIErr wlDetach(void) { WIErr err = 0; if(gWCtxt != NULL) { err = WirelessDetach(gWCtxt); if(err) fprintf(stderr, "Error: WirelessDetach: %d\n", (int) err); } return err; } void wlCheckAvail(int avail) { if(avail) return; fprintf(stderr, "%s: Error: Wireless interface not available!\n", gProgname); exit(-2); } WIErr wlc_ioctl(int command, int bufsize, void* buffer, int outsize, void* out) { if (!buffer) bufsize = 0; int* buf = malloc(bufsize+8); buf[0] = 3; /* private ioctl command code */ buf[1] = command; if (bufsize && buffer) memcpy(&buf[2], buffer, bufsize); return WirelessPrivate(gWCtxt, buf, bufsize+8, out, outsize); } int main(int argc, char **argv) { WIErr err = 0; NSAutoreleasePool *pool; int retVal = 0; int avail = 0; gProgname = argv[0]; pool = [[NSAutoreleasePool alloc] init]; avail = WirelessIsAvailable(); if(avail) { err = WirelessAttach(&gWCtxt, 0); if(err) { fprintf(stderr, "Error: WirelessAttach: %d\n", (int) err); exit(-1); } } wlCheckAvail(avail); int cookie, tmp; if (wlc_ioctl(WLC_GET_MAGIC, 0, NULL, 4, &cookie)) { fprintf(stderr, "%s: Error: %d\n", gProgname, (int) err); wlDetach(); return -1; } if (cookie != 0x14e46c77) { fprintf(stderr, "cookie mismatch\n"); wlDetach(); return -1; } tmp = 1; wlc_ioctl(WLC_SET_CLK, 4, &tmp, 0, NULL); err = wlc_ioctl(WLC_DIAG_LOOPBACK, 4, &tmp, 0, NULL); tmp = 0; wlc_ioctl(WLC_SET_CLK, 4, &tmp, 0, NULL); if(err != noErr) { fprintf(stderr, "%s: Error: %d\n", gProgname, (int) err); retVal = -1; } wlDetach(); return retVal; }
For a Makefile, copy the one from airport.tar.gz and remove all the hermes stuff.