diff --git a/src/wimax/iwmxsdk.c b/src/wimax/iwmxsdk.c index 050f745c8..ba5bb9c71 100644 --- a/src/wimax/iwmxsdk.c +++ b/src/wimax/iwmxsdk.c @@ -209,6 +209,45 @@ _schedule_state_change(struct wmxsdk *wmxsdk, g_idle_add(state_change_handler, info); } +typedef struct { + struct wmxsdk *wmxsdk; + WIMAX_API_MEDIA_STATUS media_status; +} MediaStatusInfo; + +static gboolean +media_status_change_handler(gpointer user_data) +{ + MediaStatusInfo *info = user_data; + + if (info->wmxsdk->media_status_cb) { + info->wmxsdk->media_status_cb(info->wmxsdk, + info->media_status, + info->wmxsdk->callback_data); + } + wmxsdk_unref(info->wmxsdk); + memset(info, 0, sizeof(*info)); + free(info); + return FALSE; +} + +static void +_schedule_media_status_change(struct wmxsdk *wmxsdk, + WIMAX_API_MEDIA_STATUS media_status) +{ + MediaStatusInfo *info; + + info = malloc(sizeof (*info)); + if (!info) + return; + + memset(info, 0, sizeof(*info)); + info->wmxsdk = wmxsdk; + info->media_status = media_status; + + wmxsdk_ref(wmxsdk); + g_idle_add(media_status_change_handler, info); +} + typedef struct { struct wmxsdk *wmxsdk; WIMAX_API_NETWORK_CONNECTION_RESP result; @@ -400,6 +439,19 @@ const char *iwmx_sdk_reason_to_str(WIMAX_API_STATUS_REASON reason) } } +const char *iwmx_sdk_media_status_to_str(WIMAX_API_MEDIA_STATUS status) +{ + switch (status) { + case WIMAX_API_MEDIA_STATUS_LINK_UP: + return "link-up"; + case WIMAX_API_MEDIA_STATUS_LINK_DOWN: + return "link-down"; + case WIMAX_API_MEDIA_STATUS_LINK_RENEW: + return "link-renew"; + default: + return "unknown"; + } +} /* * Get the device's status from the device @@ -810,6 +862,24 @@ error_get_status: return result; } +static void __iwmx_sdk_media_status_update_cb (WIMAX_API_DEVICE_ID_P device_id, + WIMAX_API_MEDIA_STATUS mediaStatus) +{ + struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); + + /* Ignore redundant LINK_UP events */ + if ( mediaStatus == WIMAX_API_MEDIA_STATUS_LINK_UP + && wmxsdk->media_status == WIMAX_API_MEDIA_STATUS_LINK_UP) + return; + + wmxsdk->media_status = mediaStatus; + + nm_log_dbg(LOGD_WIMAX, "wmxsdk: media status change to (%d) %s", + mediaStatus, iwmx_sdk_media_status_to_str (mediaStatus)); + + _schedule_media_status_change(wmxsdk, mediaStatus); +} + /* * Callback for state change messages * @@ -1002,6 +1072,13 @@ static int iwmx_sdk_setup(struct wmxsdk *wmxsdk) goto error_subscribe_disconnect; } + r = SubscribeMediaStatusUpdate(&wmxsdk->device_id, __iwmx_sdk_media_status_update_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to media status events: %d (%s)", r, errstr); + goto error_subscribe_media_status; + } + status = iwmx_sdk_get_device_status(wmxsdk); if ((int) status < 0) status = WIMAX_API_DEVICE_STATUS_UnInitialized; @@ -1017,6 +1094,8 @@ static int iwmx_sdk_setup(struct wmxsdk *wmxsdk) return 0; + UnsubscribeMediaStatusUpdate(&wmxsdk->device_id); +error_subscribe_media_status: UnsubscribeDisconnectToNetwork(&wmxsdk->device_id); error_subscribe_disconnect: UnsubscribeConnectToNetwork(&wmxsdk->device_id); @@ -1043,6 +1122,7 @@ error_wimaxdeviceopen: */ static void iwmx_sdk_remove(struct wmxsdk *wmxsdk) { + UnsubscribeMediaStatusUpdate(&wmxsdk->device_id); UnsubscribeDisconnectToNetwork(&wmxsdk->device_id); UnsubscribeConnectToNetwork(&wmxsdk->device_id); UnsubscribeNetworkSearchEx(&wmxsdk->device_id); @@ -1054,12 +1134,14 @@ static void iwmx_sdk_remove(struct wmxsdk *wmxsdk) void iwmx_sdk_set_callbacks(struct wmxsdk *wmxsdk, WimaxStateChangeFunc state_change_cb, + WimaxMediaStatusFunc media_status_cb, WimaxConnectResultFunc connect_result_cb, WimaxScanResultFunc scan_result_cb, WimaxRemovedFunc removed_cb, void *user_data) { wmxsdk->state_change_cb = state_change_cb; + wmxsdk->media_status_cb = media_status_cb; wmxsdk->connect_result_cb = connect_result_cb; wmxsdk->scan_result_cb = scan_result_cb; wmxsdk->removed_cb = removed_cb; diff --git a/src/wimax/iwmxsdk.h b/src/wimax/iwmxsdk.h index e065b0a83..1cef36fa3 100644 --- a/src/wimax/iwmxsdk.h +++ b/src/wimax/iwmxsdk.h @@ -24,6 +24,7 @@ #include #include +#include struct wmxsdk; @@ -35,6 +36,10 @@ typedef void (*WimaxStateChangeFunc) (struct wmxsdk *wmxsdk, WIMAX_API_STATUS_REASON reason, void *user_data); +typedef void (*WimaxMediaStatusFunc) (struct wmxsdk *wmxsdk, + WIMAX_API_MEDIA_STATUS media_status, + void *user_data); + typedef void (*WimaxConnectResultFunc) (struct wmxsdk *wmxsdk, WIMAX_API_NETWORK_CONNECTION_RESP resp, void *user_data); @@ -52,6 +57,7 @@ struct wmxsdk { WIMAX_API_DEVICE_ID device_id; WimaxStateChangeFunc state_change_cb; + WimaxMediaStatusFunc media_status_cb; WimaxConnectResultFunc connect_result_cb; WimaxScanResultFunc scan_result_cb; WimaxRemovedFunc removed_cb; @@ -60,6 +66,7 @@ struct wmxsdk { GStaticMutex network_mutex; WIMAX_API_DEVICE_STATUS status; + WIMAX_API_MEDIA_STATUS media_status; GMutex *status_mutex; GMutex *connect_mutex; @@ -79,6 +86,7 @@ void iwmx_sdk_new_callback_unregister(WimaxNewWmxsdkFunc callback, void *user_da void iwmx_sdk_set_callbacks(struct wmxsdk *wmxsdk, WimaxStateChangeFunc state_change_cb, + WimaxMediaStatusFunc media_status_func, WimaxConnectResultFunc connect_result_cb, WimaxScanResultFunc scan_result_cb, WimaxRemovedFunc removed_cb, @@ -90,6 +98,7 @@ int iwmx_sdk_disconnect(struct wmxsdk *wmxsdk); WIMAX_API_CONNECTED_NSP_INFO_EX *iwmx_sdk_get_connected_network(struct wmxsdk *wmxsdk); const char *iwmx_sdk_dev_status_to_str(WIMAX_API_DEVICE_STATUS status); const char *iwmx_sdk_reason_to_str(WIMAX_API_STATUS_REASON reason); +const char *iwmx_sdk_media_status_to_str(WIMAX_API_MEDIA_STATUS status); int iwmx_sdk_rf_state_set(struct wmxsdk *wmxsdk, WIMAX_API_RF_STATE rf_state); int iwmx_sdk_get_networks(struct wmxsdk *wmxsdk); int iwmx_sdk_api_init(void); diff --git a/src/wimax/nm-device-wimax.c b/src/wimax/nm-device-wimax.c index 71525c38e..86df993aa 100644 --- a/src/wimax/nm-device-wimax.c +++ b/src/wimax/nm-device-wimax.c @@ -700,6 +700,38 @@ wmx_state_change_cb (struct wmxsdk *wmxsdk, } } +static void +wmx_media_status_cb (struct wmxsdk *wmxsdk, + WIMAX_API_MEDIA_STATUS new_status, + void *user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceState state; + const char *iface; + + iface = nm_device_get_iface (NM_DEVICE (self)); + state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self)); + + nm_log_dbg (LOGD_WIMAX, "(%s): media status change to %d", + iface, iwmx_sdk_media_status_to_str (new_status)); + + /* We only care about media events while activated */ + if (state != NM_DEVICE_STATE_ACTIVATED) + return; + + switch (new_status) { + case WIMAX_API_MEDIA_STATUS_LINK_UP: + break; + case WIMAX_API_MEDIA_STATUS_LINK_DOWN: + break; + case WIMAX_API_MEDIA_STATUS_LINK_RENEW: + break; + default: + nm_log_err (LOGD_WIMAX, "(%s): unhandled media status %d", iface, new_status); + break; + } +} + static void wmx_connect_result_cb (struct wmxsdk *wmxsdk, WIMAX_API_NETWORK_CONNECTION_RESP result, @@ -810,7 +842,7 @@ wmx_removed_cb (struct wmxsdk *wmxsdk, void *user_data) if (priv->sdk) { /* Clear callbacks just in case we don't hold the last reference */ - iwmx_sdk_set_callbacks (priv->sdk, NULL, NULL, NULL, NULL, NULL); + iwmx_sdk_set_callbacks (priv->sdk, NULL, NULL, NULL, NULL, NULL, NULL); wmxsdk_unref (priv->sdk); priv->sdk = NULL; @@ -871,6 +903,7 @@ wmx_new_sdk_cb (struct wmxsdk *sdk, void *user_data) priv->sdk = wmxsdk_ref (sdk); iwmx_sdk_set_callbacks(priv->sdk, wmx_state_change_cb, + wmx_media_status_cb, wmx_connect_result_cb, wmx_scan_result_cb, wmx_removed_cb, @@ -987,7 +1020,7 @@ dispose (GObject *object) g_source_remove (priv->sdk_action_defer_id); if (priv->sdk) { - iwmx_sdk_set_callbacks (priv->sdk, NULL, NULL, NULL, NULL, NULL); + iwmx_sdk_set_callbacks (priv->sdk, NULL, NULL, NULL, NULL, NULL, NULL); wmxsdk_unref (priv->sdk); }