7 #include "glib/gtypes.h"
14 #define osso_context_t DBusConnection
15 typedef struct osso_rpc_t_values {
19 typedef struct osso_rpc_t {
21 osso_rpc_t_values value;
25 #define WIFISCAND_VERSION_STRING "1.1"
27 #define OSSO_NAME "wifiscan"
28 #define OSSO_SERVICE "org.javiplx."OSSO_NAME
29 #define OSSO_OBJECT "/org/javiplx/"OSSO_NAME
30 #define OSSO_IFACE "org.javiplx."OSSO_NAME
40 /* --------------------------------------------------------------------------- WirelessInterface */
47 /* ------------------------------------------------------------------ WirelessInterface_ScanItem */
49 static int WirelessInterface_ScanItem(struct iw_event* event, ScanInfo **scaninfo) {
55 *scaninfo = (ScanInfo*) malloc( sizeof(ScanInfo) );
56 memset(*scaninfo, 0, sizeof(ScanInfo) );
58 iw_ether_ntop( (const struct ether_addr*)(event->u.ap_addr.sa_data), (*scaninfo)->mac);
63 (*scaninfo)->rssi = event->u.qual.level - 0x100;
73 /* ---------------------------------------------------------------------- */
75 void* makeScan(WirelessInterface* coso, gchar *message) {
77 unsigned char* buffer = NULL;
78 int buflen = IW_SCAN_MAX_DATA;
82 int timeout = 10000000;
84 ScanInfo **scan = NULL;
86 has_range = (iw_get_range_info(coso->sock, coso->ifname, &range) >= 0);
90 wrq.u.data.pointer = NULL;
92 wrq.u.data.length = 0;
94 if(iw_set_ext(coso->sock, coso->ifname, SIOCSIWSCAN, &wrq) < 0) {
96 message = "Interface doesn't support scanning";
101 timeout -= tv.tv_usec;
111 ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
114 if(errno == EAGAIN || errno == EINTR) continue;
117 message = "Unknown scanning error";
123 unsigned char* newbuf;
126 newbuf = (unsigned char*) realloc(buffer, buflen);
129 if(buffer) free(buffer);
130 message = "Memory allocation failure in scan";
136 wrq.u.data.pointer = buffer;
137 wrq.u.data.flags = 0;
138 wrq.u.data.length = buflen;
140 if(iw_get_ext(coso->sock, coso->ifname, SIOCGIWSCAN, &wrq) < 0) {
141 if((errno == E2BIG)) {
142 if(wrq.u.data.length > buflen) buflen = wrq.u.data.length;
148 if(errno == EAGAIN) {
151 timeout -= tv.tv_usec;
153 if(timeout > 0) continue;
158 message = "Unable to read scan data";
168 if(wrq.u.data.length) {
172 void* scan_dict = NULL;
174 iw_init_event_stream(&stream, (char*)(buffer), wrq.u.data.length);
176 scan = (ScanInfo**) malloc( 25 * sizeof(ScanInfo *) );
177 memset(scan, 0, 25 * sizeof(ScanInfo *) );
180 for (i=0; i<25; i++) *(scan+i) = NULL;
185 ret = iw_extract_event_stream(&stream, &iwe, range.we_version_compiled);
188 int sr = WirelessInterface_ScanItem(&iwe, &sc);
199 message = "Unknown error";
208 static void refresh(WirelessInterface* coso) {
211 iw_get_basic_config(coso->sock, coso->ifname, &(coso->info.b));
212 iw_get_range_info(coso->sock, coso->ifname, &(coso->info.range));
214 iw_get_ext(coso->sock, coso->ifname, SIOCGIWRATE, &wrq);
215 memcpy(&(coso->info.bitrate), &wrq.u.bitrate, sizeof(iwparam));
217 iw_get_ext(coso->sock, coso->ifname, SIOCGIWAP, &wrq);
218 memcpy(&(coso->info.ap_addr), &wrq.u.ap_addr, sizeof (sockaddr));
221 coso->sock, coso->ifname, &(coso->info.stats),
222 &(coso->info.range), coso->info.has_range
226 /* Application UI data struct */
227 typedef struct _AppData AppData;
229 WirelessInterface iface;
230 osso_context_t *osso_context;
234 static GMainLoop *event_loop = NULL;
236 static short int start_flags = 0;
239 int submit_reply_message(DBusConnection *connection, DBusMessage *message, char *string) {
240 DBusMessage *reply = dbus_message_new_method_return (message);
243 if (!dbus_message_append_args (reply, DBUS_TYPE_STRING, &string, DBUS_TYPE_INVALID))
245 if (!dbus_connection_send (connection, reply, NULL))
247 dbus_message_unref (reply);
248 return DBUS_HANDLER_RESULT_HANDLED;
252 /* Callback for normal D-BUS messages */
254 gint dbus_req_handler(const gchar * interface, const gchar * method,
255 GArray * arguments, gpointer data,
258 static DBusHandlerResult dbus_req_handler (DBusConnection *connection,
259 DBusMessage *message,
264 osso_rpc_t *retval = malloc(sizeof(osso_rpc_t));
268 appdata = (AppData *) data;
270 retval->type = DBUS_TYPE_STRING;
271 retval->value.s = (gchar*) malloc( sizeof(gchar *) );
272 retval->value.s[0] = '\0';
275 if ( strcmp(method,"wakeup")==0 ) {
277 if (dbus_message_is_method_call(message, OSSO_IFACE, "wakeup")) {
279 retval->value.s = (gchar *) realloc(retval->value.s,16*sizeof(gchar *));
280 snprintf(retval->value.s,16,"WifiScand ready");
284 return submit_reply_message(connection, message, retval->value.s);
289 if ( strcmp(method,"start")==0 ) {
291 if (dbus_message_is_method_call(message, OSSO_IFACE, "start")) {
294 if( (appdata->iface.sock=iw_sockets_open()) < 0) {
295 retval->value.s = (gchar *) realloc(retval->value.s,33*sizeof(gchar *));
296 snprintf(retval->value.s,33,"Failure in socket initialization");
300 return submit_reply_message(connection, message, retval->value.s);
305 strncpy(frq.ifr_name, appdata->iface.ifname, IFNAMSIZ);
306 if(ioctl(appdata->iface.sock, SIOCGIFFLAGS, &frq)) {
307 retval->value.s = (gchar *) realloc(retval->value.s,28*sizeof(gchar *));
308 snprintf(retval->value.s,28,"Cannot get interface status");
312 return submit_reply_message(connection, message, retval->value.s);
316 start_flags = frq.ifr_flags;
317 frq.ifr_flags |= IFF_UP | IFF_RUNNING;
319 if(ioctl(appdata->iface.sock, SIOCSIFFLAGS, &frq)) {
320 retval->value.s = (gchar *) realloc(retval->value.s,27*sizeof(gchar *));
321 snprintf(retval->value.s,27,"Cannot set interface state");
325 return submit_reply_message(connection, message, retval->value.s);
329 refresh(&appdata->iface);
330 retval->value.s = (gchar *) realloc(retval->value.s,22*sizeof(gchar *));
331 snprintf(retval->value.s,22,"Interface initialized");
335 return submit_reply_message(connection, message, retval->value.s);
340 if ( strcmp(method,"stop")==0 ) {
342 if (dbus_message_is_method_call(message, OSSO_IFACE, "stop")) {
345 strncpy(frq.ifr_name, appdata->iface.ifname, IFNAMSIZ);
346 if(!ioctl(appdata->iface.sock, SIOCGIFFLAGS, &frq)) {
347 frq.ifr_flags = start_flags;
348 if(!ioctl(appdata->iface.sock, SIOCSIFFLAGS, &frq))
349 refresh(&appdata->iface);
351 iw_sockets_close(appdata->iface.sock);
352 appdata->iface.sock = 0;
354 osso_deinitialize(appdata->osso_context);
356 dbus_connection_unref(appdata->osso_context);
359 /* Instead of exiting, signaling finish to main loop could be better
360 retval->value.s = (gchar *) realloc(retval->value.s,34*sizeof(gchar *));
361 snprintf(retval->value.s,34,"Interface moved to original state");
367 if ( strcmp(method,"scan")==0 ) {
369 if (dbus_message_is_method_call(message, OSSO_IFACE, "scan")) {
372 ScanInfo **scan = (ScanInfo **) makeScan(&appdata->iface,retval->value.s);
374 retval->value.s = (gchar *) realloc(retval->value.s,64*sizeof(gchar *));
375 snprintf(retval->value.s,64,"ERROR");
379 return submit_reply_message(connection, message, retval->value.s);
384 for (i=0; i<25&&*(scan+i)!=NULL; i++) {
385 ScanInfo* sc = *(scan+i);
386 retval->value.s = (gchar *) realloc(retval->value.s,23*(i+1)*sizeof(gchar *));
387 if ( retval->value.s == NULL ) {
388 retval->value.s = "Error allocating memory";
392 return submit_reply_message(connection, message, retval->value.s);
395 sprintf(retval->value.s+strlen(retval->value.s),"%s:%d ",sc->mac,sc->rssi);
398 retval->value.s[strlen(retval->value.s)-1] = '\0';
402 return submit_reply_message(connection, message, retval->value.s);
406 retval->value.s = (gchar *) realloc(retval->value.s,64*sizeof(gchar *));
407 snprintf(retval->value.s,64,"Unknown method");
411 return submit_reply_message(connection, message, retval->value.s);
416 static DBusObjectPathVTable
417 dbus_req_handler_vtable = {
426 osso_context_t *osso_context;
431 /* Initialize maemo application */
433 osso_context = osso_initialize(OSSO_NAME, WIFISCAND_VERSION_STRING, TRUE, NULL);
435 dbus_error_init(&error);
436 osso_context = dbus_bus_get(DBUS_BUS_STARTER, &error);
439 /* Check that initialization was ok */
440 if (osso_context == NULL) {
442 fprintf (stderr, "*** Failed to open connection to activating message bus: %s\n", error.message);
443 dbus_error_free (&error);
451 appdata = g_new0(AppData, 1);
453 appdata = malloc(sizeof(AppData));
455 appdata->osso_context = osso_context;
457 memset(&(appdata->iface.info), 0, sizeof(wireless_info));
458 appdata->iface.ifname = "wlan0";
459 appdata->iface.sock = 0;
461 /* Add handler for hello D-BUS messages */
463 osso_return_t result = osso_rpc_set_cb_f(osso_context, OSSO_SERVICE, OSSO_OBJECT, OSSO_IFACE, dbus_req_handler, appdata);
465 int result = dbus_connection_register_fallback(osso_context, OSSO_OBJECT, &dbus_req_handler_vtable, appdata);
467 // NOTE : valid return codes do not match from both functions
469 if (result != OSSO_OK) {
474 osso_system_note_infoprint(appdata->osso_context, "Failure while setting OSSO callback", NULL);
480 result = dbus_bus_request_name (osso_context, OSSO_SERVICE, 0, &error);
481 if (dbus_error_is_set (&error)) {
482 fprintf (stderr, "Error %s\n", error.message);
483 dbus_error_free (&error);
488 /* INITIALIZATION FINISH */
491 event_loop = g_main_loop_new(NULL, FALSE);
492 g_main_loop_run(event_loop);
494 while (dbus_connection_read_write_dispatch (osso_context, -1)) {}
497 /* Deinitialize OSSO */
499 osso_deinitialize(osso_context);
501 dbus_connection_unref(osso_context);