--- /dev/null
+
+#include <iwlib.h>
+
+#include <libosso.h>
+
+#define WIFISCAND_VERSION_STRING "1.0"
+
+#define OSSO_NAME "wifiscan"
+#define OSSO_SERVICE "org.javiplx."OSSO_NAME
+#define OSSO_OBJECT "/org/javiplx/"OSSO_NAME
+#define OSSO_IFACE "org.javiplx."OSSO_NAME
+
+
+typedef struct {
+ char mac[18];
+ int rssi;
+ int noise;
+} ScanInfo;
+
+
+/* --------------------------------------------------------------------------- WirelessInterface */
+typedef struct {
+ wireless_info info;
+ char* ifname;
+ int sock;
+} WirelessInterface;
+
+/* ------------------------------------------------------------------ WirelessInterface_ScanItem */
+
+static int WirelessInterface_ScanItem(struct iw_event* event, ScanInfo **scaninfo) {
+
+ switch(event->cmd) {
+
+ case SIOCGIWAP: {
+
+ *scaninfo = (ScanInfo*) malloc( sizeof(ScanInfo) );
+ memset(*scaninfo, 0, sizeof(ScanInfo) );
+
+ iw_ether_ntop( (const struct ether_addr*)(event->u.ap_addr.sa_data), (*scaninfo)->mac);
+ return 1;
+ }
+
+ case IWEVQUAL: {
+ (*scaninfo)->rssi = event->u.qual.level - 0x100;
+ return 0;
+ }
+
+ default: {
+ return 0;
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+void* makeScan(WirelessInterface* coso, gchar *message) {
+ struct iwreq wrq;
+ unsigned char* buffer = NULL;
+ int buflen = IW_SCAN_MAX_DATA;
+ iwrange range;
+ int has_range;
+ struct timeval tv;
+ int timeout = 10000000;
+
+ ScanInfo **scan = NULL;
+
+ has_range = (iw_get_range_info(coso->sock, coso->ifname, &range) >= 0);
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 250000;
+ wrq.u.data.pointer = NULL;
+ wrq.u.data.flags = 0;
+ wrq.u.data.length = 0;
+
+ if(iw_set_ext(coso->sock, coso->ifname, SIOCSIWSCAN, &wrq) < 0) {
+ if(errno != EPERM) {
+ message = "Interface doesn't support scanning";
+ return NULL;
+ }
+ tv.tv_usec = 0;
+ }
+ timeout -= tv.tv_usec;
+
+ while(1) {
+ fd_set rfds;
+ int last_fd;
+ int ret;
+
+ FD_ZERO(&rfds);
+ last_fd = -1;
+
+ ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
+
+ if(ret < 0) {
+ if(errno == EAGAIN || errno == EINTR) continue;
+
+ else {
+ message = "Unknown scanning error";
+ return NULL;
+ }
+ }
+
+ if(!ret) {
+ unsigned char* newbuf;
+
+ realloc:
+ newbuf = (unsigned char*) realloc(buffer, buflen);
+
+ if(!newbuf) {
+ if(buffer) free(buffer);
+ message = "Memory allocation failure in scan";
+ return NULL;
+ }
+
+ buffer = newbuf;
+
+ wrq.u.data.pointer = buffer;
+ wrq.u.data.flags = 0;
+ wrq.u.data.length = buflen;
+
+ if(iw_get_ext(coso->sock, coso->ifname, SIOCGIWSCAN, &wrq) < 0) {
+ if((errno == E2BIG)) {
+ if(wrq.u.data.length > buflen) buflen = wrq.u.data.length;
+ else buflen *= 2;
+
+ goto realloc;
+ }
+
+ if(errno == EAGAIN) {
+ tv.tv_sec = 0;
+ tv.tv_usec = 100000;
+ timeout -= tv.tv_usec;
+
+ if(timeout > 0) continue;
+ }
+
+ free(buffer);
+
+ message = "Unable to read scan data";
+
+ return NULL;
+ }
+
+ else break;
+ }
+ }
+
+
+ if(wrq.u.data.length) {
+ struct iw_event iwe;
+ stream_descr stream;
+ int ret;
+ void* scan_dict = NULL;
+
+ iw_init_event_stream(&stream, (char*)(buffer), wrq.u.data.length);
+
+ scan = (ScanInfo**) malloc( 25 * sizeof(ScanInfo *) );
+ memset(scan, 0, 25 * sizeof(ScanInfo *) );
+ *scan = NULL;
+ int i;
+ for (i=0; i<25; i++) *(scan+i) = NULL;
+
+ i = 0;
+ ScanInfo *sc = NULL;
+ do {
+ ret = iw_extract_event_stream(&stream, &iwe, range.we_version_compiled);
+
+ if(ret > 0) {
+ int sr = WirelessInterface_ScanItem(&iwe, &sc);
+ if(sr && i<25) {
+ *(scan+i) = sc;
+ i++;
+ }
+ }
+ }
+
+ while(ret > 0);
+
+ } else {
+ message = "Unknown error";
+ free(buffer);
+ return NULL;
+ }
+
+ free(buffer);
+ return scan;
+}
+
+static void refresh(WirelessInterface* coso) {
+ struct iwreq wrq;
+
+ iw_get_basic_config(coso->sock, coso->ifname, &(coso->info.b));
+ iw_get_range_info(coso->sock, coso->ifname, &(coso->info.range));
+
+ iw_get_ext(coso->sock, coso->ifname, SIOCGIWRATE, &wrq);
+ memcpy(&(coso->info.bitrate), &wrq.u.bitrate, sizeof(iwparam));
+
+ iw_get_ext(coso->sock, coso->ifname, SIOCGIWAP, &wrq);
+ memcpy(&(coso->info.ap_addr), &wrq.u.ap_addr, sizeof (sockaddr));
+
+ iw_get_stats(
+ coso->sock, coso->ifname, &(coso->info.stats),
+ &(coso->info.range), coso->info.has_range
+ );
+}
+
+/* Application UI data struct */
+typedef struct _AppData AppData;
+struct _AppData {
+ WirelessInterface iface;
+ osso_context_t *osso_context;
+};
+
+/* Callback for normal D-BUS messages */
+gint dbus_req_handler(const gchar * interface, const gchar * method,
+ GArray * arguments, gpointer data,
+ osso_rpc_t * retval)
+{
+ AppData *appdata;
+ appdata = (AppData *) data;
+
+ retval->type = DBUS_TYPE_STRING;
+ retval->value.s = (gchar*) malloc( sizeof(gchar *) );
+ retval->value.s[0] = '\0';
+
+ if ( strcmp(method,"start")==0 ) {
+ // osso_system_note_infoprint(appdata->osso_context, "Starting WifiScan", NULL);
+ return OSSO_OK;
+ }
+
+ if ( strcmp(method,"stop")==0 ) {
+ iw_sockets_close(appdata->iface.sock);
+ appdata->iface.sock = 0;
+ // osso_system_note_infoprint(appdata->osso_context, "Stopping WifiScan", NULL);
+ osso_deinitialize(appdata->osso_context);
+ exit(0);
+ }
+
+ if ( strcmp(method,"scan")==0 ) {
+ // osso_system_note_infoprint(appdata->osso_context, "Scanning ...", NULL);
+
+ ScanInfo **scan = (ScanInfo **) makeScan(&appdata->iface,retval->value.s);
+ if(scan == NULL) {
+ retval->value.s = (gchar *) realloc(retval->value.s,64*sizeof(gchar *));
+ snprintf(retval->value.s,64,"ERROR");
+ return OSSO_ERROR;
+ }
+
+ int i;
+ for (i=0; i<25&&*(scan+i)!=NULL; i++) {
+ ScanInfo* sc = *(scan+i);
+ retval->value.s = (gchar *) realloc(retval->value.s,23*(i+1)*sizeof(gchar *));
+ if ( retval->value.s == NULL ) {
+ retval->value.s = "Error allocating memory";
+ return OSSO_ERROR;
+ }
+ sprintf(retval->value.s+strlen(retval->value.s),"%s:%d ",sc->mac,sc->rssi);
+ }
+
+ retval->value.s[strlen(retval->value.s)-1] = '\0';
+ return OSSO_OK;
+ }
+
+ retval->value.s = (gchar *) realloc(retval->value.s,64*sizeof(gchar *));
+ snprintf(retval->value.s,64,"Unknown method");
+ return OSSO_ERROR;
+}
+
+static GMainLoop *event_loop = NULL;
+
+int main( void ) {
+
+ osso_context_t *osso_context;
+
+ /* Initialize maemo application */
+ osso_context = osso_initialize(OSSO_NAME, WIFISCAND_VERSION_STRING, TRUE, NULL);
+
+ /* Check that initialization was ok */
+ if (osso_context == NULL) {
+ exit(OSSO_ERROR);
+ }
+
+ /* Create AppData */
+ AppData *appdata;
+ appdata = g_new0(AppData, 1);
+ appdata->osso_context = osso_context;
+
+ memset(&(appdata->iface.info), 0, sizeof(wireless_info));
+ appdata->iface.ifname = "wlan0";
+ appdata->iface.sock = 0;
+
+ /* Add handler for hello D-BUS messages */
+ osso_return_t result = osso_rpc_set_cb_f(osso_context, OSSO_SERVICE, OSSO_OBJECT, OSSO_IFACE, dbus_req_handler, appdata);
+ if (result != OSSO_OK) {
+ osso_system_note_infoprint(appdata->osso_context, "Failure while setting OSSO callback", NULL);
+ return OSSO_ERROR;
+ }
+
+ /* INITIALIZATION */
+ appdata->iface.sock = iw_sockets_open();
+
+ if(appdata->iface.sock < 0) {
+ osso_system_note_infoprint(osso_context, "Failure in socket initialization", NULL);
+ return OSSO_ERROR;
+ }
+
+ struct ifreq frq;
+
+ strncpy(frq.ifr_name, appdata->iface.ifname, IFNAMSIZ);
+
+ if(ioctl(appdata->iface.sock, SIOCGIFFLAGS, &frq)) {
+ osso_system_note_infoprint(osso_context, "Cannot scan", NULL);
+ return OSSO_ERROR;
+ }
+
+ frq.ifr_flags |= IFF_UP | IFF_RUNNING;
+
+ ioctl(appdata->iface.sock, SIOCSIFFLAGS, &frq);
+
+ refresh(&appdata->iface);
+ /* INITIALIZATION FINISH */
+
+ event_loop = g_main_loop_new(NULL, FALSE);
+ g_main_loop_run(event_loop);
+
+ /* Deinitialize OSSO */
+ osso_deinitialize(osso_context);
+
+ exit(0);
+}
+