5 * Copyright (C) 2007-2012 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #define CONNMAN_API_SUBJECT_TO_CHANGE
35 #include <connman/device.h>
36 #include <connman/inet.h>
37 #include <connman/log.h>
39 #include <WiMaxType.h>
41 #include <WiMaxAPIEx.h>
45 /* Yes, this is dirty; see above on IWMX_SDK_DEV_MAX*/
46 static struct wmxsdk *g_iwmx_sdk_devs[IWMX_SDK_DEV_MAX];
48 static struct wmxsdk *deviceid_to_wmxsdk(WIMAX_API_DEVICE_ID *device_id)
51 for (cnt = 0; cnt < IWMX_SDK_DEV_MAX; cnt++) {
52 struct wmxsdk *wmxsdk = g_iwmx_sdk_devs[cnt];
54 wmxsdk->device_id.deviceIndex == device_id->deviceIndex)
60 static WIMAX_API_DEVICE_ID g_api;
64 * FIXME: pulled it it out of some hole
66 * the cinr to percentage computation comes from the L3/L4 doc
68 * But some other places (L4 code) have a more complex, seemingly
69 * logarithmical computation.
74 static int cinr_to_percentage(int cinr)
81 else /* Calc percentage on the value from -5 to 25 */
82 strength = ((100UL * (cinr - -5)) / (25 - -5));
87 * Convert a WiMAX API status to an string.
89 const char *iwmx_sdk_dev_status_to_str(WIMAX_API_DEVICE_STATUS status)
92 case WIMAX_API_DEVICE_STATUS_UnInitialized:
93 return "Uninitialized";
95 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
96 return "Device RF Off(both H/W and S/W)";
98 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
99 return "Device RF Off(via H/W switch)";
100 case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
101 return "Device RF Off(via S/W switch)";
102 case WIMAX_API_DEVICE_STATUS_Ready:
103 return "Device is ready";
104 case WIMAX_API_DEVICE_STATUS_Scanning:
105 return "Device is scanning";
106 case WIMAX_API_DEVICE_STATUS_Connecting:
107 return "Connection in progress";
108 case WIMAX_API_DEVICE_STATUS_Data_Connected:
109 return "Layer 2 connected";
110 #if HAVE_IWMXSDK_STATUS_IDLE
111 case WIMAX_API_DEVICE_STATUS_Connection_Idle:
112 return "Idle connection";
113 #endif /* #if HAVE_IWMXSDK_STATUS_IDLE */
115 return "unknown state";
120 * Get the device's status from the device
122 * Does NOT cache the result
123 * Does NOT trigger a state change in connman
125 * Returns < 0 errno code on error, status code if ok.
127 WIMAX_API_DEVICE_STATUS iwmx_sdk_get_device_status(struct wmxsdk *wmxsdk)
131 UINT32 errstr_size = sizeof(errstr);
133 WIMAX_API_DEVICE_STATUS dev_status;
134 WIMAX_API_CONNECTION_PROGRESS_INFO pi;
136 r = GetDeviceStatus(&wmxsdk->device_id, &dev_status, &pi);
137 if (r != WIMAX_API_RET_SUCCESS) {
138 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
139 connman_error("wmxsdk: Cannot read device state: %d (%s)\n",
147 * Get the device's status from the device but return a string describing it
149 * Same conditions as iwmx_sdk_get_device_status().
151 static const char *iwmx_sdk_get_device_status_str(struct wmxsdk *wmxsdk)
154 WIMAX_API_DEVICE_STATUS dev_status;
156 dev_status = iwmx_sdk_get_device_status(wmxsdk);
157 if ((int) dev_status < 0)
158 result = "cannot read device state";
160 result = iwmx_sdk_dev_status_to_str(dev_status);
165 * Translate a WiMAX network type to a readable name.
167 static const char *iwmx_sdk_network_type_name(enum _WIMAX_API_NETWORK_TYPE network_type)
169 static char *network_type_name[] = {
170 [WIMAX_API_HOME] = "",
171 [WIMAX_API_PARTNER] = " (partner network)",
172 [WIMAX_API_ROAMING_PARTNER] = " (roaming partner network)",
173 [WIMAX_API_UNKNOWN] = " (unknown network)",
175 if (network_type > WIMAX_API_UNKNOWN)
176 return "(BUG! UNKNOWN NETWORK_TYPE MODE)";
178 return network_type_name[network_type];
182 * If the device is connected but we don't know about the network,
183 * create the knowledge of it.
185 * Asks the WiMAX API to report which NSP we are connected to and we
186 * create/update a network_el in the device's network list. Then
189 * Returns NULL on error.
191 * NOTE: wmxsdk->network_mutex has to be taken
193 struct connman_network *__iwmx_sdk_get_connected_network(struct wmxsdk *wmxsdk)
195 struct connman_network *nw;
197 WIMAX_API_CONNECTED_NSP_INFO nsp_info;
200 UINT32 errstr_size = sizeof(errstr);
202 /* The device is getting connected due to an external (to
203 * connman) event; find which is the nw we are getting
204 * connected to. if we don't have it, add it */
205 r = GetConnectedNSP(&wmxsdk->device_id, &nsp_info);
206 if (r != WIMAX_API_RET_SUCCESS) {
207 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
209 "wmxsdk: Cannot get connected NSP info: %d (%s)\n",
211 strcpy((char *) nsp_info.NSPName, "unknown");
212 nw = iwmx_cm_network_available(
214 nsp_info.NSPName, strlen((char *) nsp_info.NSPName) + 1,
215 cinr_to_percentage(nsp_info.CINR - 10));
217 nw = iwmx_cm_network_available(
218 wmxsdk, (char *) nsp_info.NSPName,
219 nsp_info.NSPName, strlen((char *) nsp_info.NSPName) + 1,
220 cinr_to_percentage(nsp_info.CINR - 10));
226 * Callback for a RF State command
228 * Called by the WiMAX API when a command sent to change the RF state
229 * is completed. This is just a confirmation of what happened with the
232 * We don't do anything, as when the device changes state, the state
233 * change callback is called and that will fiddle with the connman
236 static void __iwmx_sdk_rf_state_cb(WIMAX_API_DEVICE_ID *device_id,
237 WIMAX_API_RF_STATE rf_state)
239 DBG("rf_state changed to %d\n", rf_state);
243 * Turn the radio on or off
245 * First it checks that we are in the right state before doing
246 * anything; there might be no need to do anything.
248 * Issue a command to the WiMAX API, wait for a callback confirming it
249 * is done. Sometimes the callback is missed -- in that case, do force
250 * a state change evaluation.
254 * Geezoos efing Xist, they make difficult even the most simple
257 * This thing is definitely a pain. If the radio is ON already
258 * and you switch it on again...well, there is no way to tell
259 * because you don't get a callback saying it basically
260 * suceeded. But on the other hand, if the thing was in a
261 * different state and action needs to be taken, you have to wait
262 * for a callback to confirm it's done. However, there is also an
263 * state change callback, which is almost the same, so now you
264 * have to handle things in two "unrelated" threads of execution.
266 * How the shpx are you expected to tell the difference? Check
267 * status first? On timeout? Nice gap (eighteen wheeler size) for
270 int iwmx_sdk_rf_state_set(struct wmxsdk *wmxsdk, WIMAX_API_RF_STATE rf_state)
276 UINT32 errstr_size = sizeof(errstr);
277 WIMAX_API_DEVICE_STATUS dev_status;
279 g_assert(rf_state == WIMAX_API_RF_ON || rf_state == WIMAX_API_RF_OFF);
281 /* Guess what the current radio state is; if it is ON
282 * already, don't redo it. */
283 dev_status = iwmx_sdk_get_device_status(wmxsdk);
284 if ((int) dev_status < 0) {
286 goto error_get_status;
288 switch (dev_status) {
289 case WIMAX_API_DEVICE_STATUS_UnInitialized:
292 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
293 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
295 "wmxsdk: cannot turn on radio: hw switch is off\n");
299 case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
300 if (rf_state == WIMAX_API_RF_OFF) {
302 DBG("radio is already off\n");
306 case WIMAX_API_DEVICE_STATUS_Ready:
307 case WIMAX_API_DEVICE_STATUS_Scanning:
308 case WIMAX_API_DEVICE_STATUS_Connecting:
309 case WIMAX_API_DEVICE_STATUS_Data_Connected:
310 #if HAVE_IWMXSDK_STATUS_IDLE
311 case WIMAX_API_DEVICE_STATUS_Connection_Idle:
313 if (rf_state == WIMAX_API_RF_ON) {
315 DBG("radio is already on\n");
322 /* Ok, flip the radio */
323 r = CmdControlPowerManagement(&wmxsdk->device_id, rf_state);
324 if (r != WIMAX_API_RET_SUCCESS) {
325 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
326 connman_error("wmxsdk: Cannot flip radio to %d: %d (%s) "
327 "[device is in state %s]\n",
329 iwmx_sdk_get_device_status_str(wmxsdk));
332 result = -EINPROGRESS;
340 * Callback for a Connect command
342 * Called by the WiMAX API when a command sent to connect is
343 * completed. This is just a confirmation of what happened with the
346 * WE DON'T DO MUCH HERE -- the real meat happens when a state change
347 * callback is sent, where we detect we move to connected state (or
348 * from disconnecting to something else); the state change callback is
349 * called and that will fiddle with the connman internals.
351 static void __iwmx_sdk_connect_cb(WIMAX_API_DEVICE_ID *device_id,
352 WIMAX_API_NETWORK_CONNECTION_RESP resp)
354 WIMAX_API_DEVICE_STATUS status;
355 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
357 status = iwmx_cm_status_get(wmxsdk);
358 if (resp == WIMAX_API_CONNECTION_SUCCESS) {
359 if (status != WIMAX_API_DEVICE_STATUS_Data_Connected
360 #if HAVE_IWMXSDK_STATUS_IDLE
361 && status != WIMAX_API_DEVICE_STATUS_Connection_Idle
364 connman_error("wmxsdk: error: connect worked, but state"
365 " didn't change (now it is %d [%s])\n",
367 iwmx_sdk_dev_status_to_str(status));
369 connman_error("wmxsdk: failed to connect (status %d: %s)\n",
370 status, iwmx_sdk_dev_status_to_str(status));
374 * Connect to a network
376 * This function starts the connection process to a given network;
377 * when the device changes status, the status change callback will
378 * tell connman if the network is finally connected or not.
380 * One of the reasons it is done like that is to allow external tools
381 * to control the device and the plugin just passing the status so
382 * connman displays the right info.
384 int iwmx_sdk_connect(struct wmxsdk *wmxsdk, struct connman_network *nw)
390 UINT32 errstr_size = sizeof(errstr);
391 WIMAX_API_DEVICE_STATUS dev_status;
392 const char *station_name = connman_network_get_identifier(nw);
393 const void *sdk_nspname;
394 unsigned int sdk_nspname_size;
396 g_mutex_lock(wmxsdk->connect_mutex);
397 /* Guess what the current radio state is; if it is ON
398 * already, don't redo it. */
399 dev_status = iwmx_cm_status_get(wmxsdk);
400 if ((int) dev_status < 0) {
402 goto error_get_status;
404 switch (dev_status) {
405 case WIMAX_API_DEVICE_STATUS_UnInitialized:
406 connman_error("wmxsdk: SW BUG? HW is uninitialized\n");
409 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
410 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
411 case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
412 connman_error("wmxsdk: Cannot connect: radio is off\n");
415 case WIMAX_API_DEVICE_STATUS_Ready:
416 case WIMAX_API_DEVICE_STATUS_Scanning:
418 case WIMAX_API_DEVICE_STATUS_Connecting:
419 DBG("Connect already pending, waiting for it\n");
420 result = -EINPROGRESS;
422 case WIMAX_API_DEVICE_STATUS_Data_Connected:
423 #if HAVE_IWMXSDK_STATUS_IDLE
424 case WIMAX_API_DEVICE_STATUS_Connection_Idle:
426 connman_error("wmxsdk: BUG? need to disconnect?\n");
433 /* Ok, do the connection, wait for a callback */
434 wmxsdk->connecting_nw = connman_network_ref(nw);
435 sdk_nspname = connman_network_get_blob(nw, "WiMAX.NSP.name",
437 g_assert(sdk_nspname != NULL);
438 r = CmdConnectToNetwork(&wmxsdk->device_id, (void *) sdk_nspname, 0, 0);
439 if (r != WIMAX_API_RET_SUCCESS) {
440 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
441 connman_error("wmxsdk: Cannot connect to network %s: %d (%s)"
442 " - device is in state '%s'\n",
443 station_name, r, errstr,
444 iwmx_sdk_get_device_status_str(wmxsdk));
446 connman_network_unref(nw);
447 wmxsdk->connecting_nw = NULL;
449 result = -EINPROGRESS;
452 g_mutex_unlock(wmxsdk->connect_mutex);
457 * Callback for a Disconnect command
459 * Called by the WiMAX API when a command sent to connect is
460 * completed. This is just a confirmation of what happened with the
463 * When the device changes state, the state change callback is called
464 * and that will fiddle with the connman internals.
466 * We just update the result of the command and wake up anybody who is
467 * waiting for this conditional variable.
469 static void __iwmx_sdk_disconnect_cb(WIMAX_API_DEVICE_ID *device_id,
470 WIMAX_API_NETWORK_CONNECTION_RESP resp)
472 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
473 WIMAX_API_DEVICE_STATUS status;
475 status = iwmx_cm_status_get(wmxsdk);
476 if (resp == WIMAX_API_CONNECTION_SUCCESS) {
477 if (status == WIMAX_API_DEVICE_STATUS_Data_Connected
478 #if HAVE_IWMXSDK_STATUS_IDLE
479 || status == WIMAX_API_DEVICE_STATUS_Connection_Idle
482 connman_error("wmxsdk: error: disconnect worked, "
483 "but state didn't change (now it is "
484 "%d [%s])\n", status,
485 iwmx_sdk_dev_status_to_str(status));
487 connman_error("wmxsdk: failed to disconnect (status %d: %s)\n",
488 status, iwmx_sdk_dev_status_to_str(status));
492 * Disconnect from a network
494 * This function tells the device to disconnect; the state change
495 * callback will take care of inform connman's internals.
497 int iwmx_sdk_disconnect(struct wmxsdk *wmxsdk)
503 UINT32 errstr_size = sizeof(errstr);
504 WIMAX_API_DEVICE_STATUS dev_status;
506 g_mutex_lock(wmxsdk->connect_mutex);
507 /* Guess what the current radio state is; if it is ON
508 * already, don't redo it. */
509 dev_status = iwmx_sdk_get_device_status(wmxsdk);
510 if ((int) dev_status < 0) {
512 goto error_get_status;
514 switch (dev_status) {
515 case WIMAX_API_DEVICE_STATUS_UnInitialized:
516 connman_error("wmxsdk: SW BUG? HW is uninitialized\n");
519 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
520 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
521 case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
522 DBG("Cannot disconnect, radio is off; ignoring\n");
525 case WIMAX_API_DEVICE_STATUS_Ready:
526 case WIMAX_API_DEVICE_STATUS_Scanning:
527 DBG("Cannot disconnect, already disconnected; ignoring\n");
530 case WIMAX_API_DEVICE_STATUS_Connecting:
531 case WIMAX_API_DEVICE_STATUS_Data_Connected:
532 #if HAVE_IWMXSDK_STATUS_IDLE
533 case WIMAX_API_DEVICE_STATUS_Connection_Idle:
539 /* Ok, flip the radio */
540 r = CmdDisconnectFromNetwork(&wmxsdk->device_id);
541 if (r != WIMAX_API_RET_SUCCESS) {
542 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
543 connman_error("wmxsdk: Cannot disconnect from network: "
544 "%d (%s)\n", r, errstr);
547 result = -EINPROGRESS;
550 g_mutex_unlock(wmxsdk->connect_mutex);
555 * Callback for state change messages
557 * Just pass them to the state transition handler
559 static void __iwmx_sdk_state_change_cb(WIMAX_API_DEVICE_ID *device_id,
560 WIMAX_API_DEVICE_STATUS status,
561 WIMAX_API_STATUS_REASON reason,
562 WIMAX_API_CONNECTION_PROGRESS_INFO pi)
564 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
565 iwmx_cm_state_change(wmxsdk, status);
569 * Called by _iwmx_sdk_*scan_cb() when [wide or preferred] scan results
572 * From here we update the connman core idea of which networks are
575 static void __iwmx_sdk_scan_common_cb(WIMAX_API_DEVICE_ID *device_id,
576 WIMAX_API_NSP_INFO_EX *nsp_list,
577 UINT32 nsp_list_size)
579 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
581 char station_name[256];
583 g_static_mutex_lock(&wmxsdk->network_mutex);
584 for (itr = 0; itr < nsp_list_size; itr++) {
586 WIMAX_API_NSP_INFO_EX *nsp_info = &nsp_list[itr];
587 snprintf(station_name, sizeof(station_name),
588 "%s", (char *)nsp_info->NSPName);
589 /* CAPI is reporing link quality as zero -- if it is
590 * zero, check if it is a bug by computing it based on
591 * CINR. If it is different, use the computed one. */
592 strength = nsp_info->linkQuality;
593 if (strength == 0) { /* huh */
595 cinr_to_percentage(nsp_info->CINR - 10);
596 if (linkq_expected != strength)
597 strength = linkq_expected;
600 __iwmx_cm_network_available(
601 wmxsdk, station_name,
603 strlen((char *) nsp_info->NSPName) + 1,
606 g_static_mutex_unlock(&wmxsdk->network_mutex);
610 * Called by the WiMAX API when we get a wide scan result
612 * We treat them same as wide, so we just call that.
614 static void __iwmx_sdk_wide_scan_cb(WIMAX_API_DEVICE_ID *device_id,
615 WIMAX_API_NSP_INFO_EX *nsp_list,
616 UINT32 nsp_list_size)
618 __iwmx_sdk_scan_common_cb(device_id, nsp_list, nsp_list_size);
622 * Called by the WiMAX API when we get a normal (non wide) scan result
624 * We treat them same as wide, so we just call that.
626 static void __iwmx_sdk_scan_cb(WIMAX_API_DEVICE_ID *device_id,
627 WIMAX_API_NSP_INFO_EX *nsp_list,
628 UINT32 nsp_list_size, UINT32 searchProgress)
630 __iwmx_sdk_scan_common_cb(device_id, nsp_list, nsp_list_size);
634 * Called to ask the device to scan for networks
636 * We don't really scan as the WiMAX SDK daemon scans in the
637 * background for us. We just get the results. See iwmx_sdk_setup().
639 int iwmx_sdk_scan(struct wmxsdk *wmxsdk)
643 UINT32 nsp_list_length = 10;
644 WIMAX_API_NSP_INFO_EX nsp_list[10]; /* FIXME: up to 32? */
648 UINT32 errstr_size = sizeof(errstr);
650 r = GetNetworkListEx(&wmxsdk->device_id, nsp_list, &nsp_list_length);
651 if (r != WIMAX_API_RET_SUCCESS) {
652 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
653 connman_error("wmxsdk: Cannot get network list: %d (%s)\n",
659 if (nsp_list_length == 0)
660 DBG("no networks\n");
662 __iwmx_sdk_scan_common_cb(&wmxsdk->device_id, nsp_list,
670 * Initialize the WiMAX API, register with it, setup callbacks
675 * connman_inet_create_device
679 int iwmx_sdk_setup(struct wmxsdk *wmxsdk)
686 UINT32 errstr_size = sizeof(errstr);
690 /* device_id initialized by iwmx_sdk_dev_add */
692 r = WiMaxDeviceOpen(&wmxsdk->device_id);
693 if (r != WIMAX_API_RET_SUCCESS) {
694 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
695 connman_error("wmxsdk: Cannot open device: %d (%s)\n",
697 goto error_wimaxdeviceopen;
701 * We scan in auto mode (in the background)
703 * Otherwise is messy -- if we have connman triggering a scan
704 * when we call iwmx_cm_scan() -> iwmx_sdk_scan(), most of the
705 * times that causes a race condition when the UI asks for a
706 * scan right before displaying the network menu. As there is
707 * no way to cancel an ongoing scan before connecting, we are
708 * stuck. So we do auto bg and have iwmx_sdk_scan() just return
709 * the current network list.
711 r = SetConnectionMode(&wmxsdk->device_id,
712 WIMAX_API_CONNECTION_AUTO_SCAN_MANUAL_CONNECT);
713 if (r != WIMAX_API_RET_SUCCESS) {
714 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
715 connman_error("wmxsdk: Cannot set connectin mode to manual: "
716 "%d (%s)\n", r, errstr);
717 goto error_connection_mode;
720 r = SubscribeControlPowerManagement(&wmxsdk->device_id,
721 __iwmx_sdk_rf_state_cb);
722 if (r != WIMAX_API_RET_SUCCESS) {
723 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
724 connman_error("wmxsdk: Cannot subscribe to radio change "
725 "events: %u (%s)\n", r, errstr);
727 goto error_subscribe_rf_state;
730 r = SubscribeDeviceStatusChange(&wmxsdk->device_id,
731 __iwmx_sdk_state_change_cb);
732 if (r != WIMAX_API_RET_SUCCESS) {
733 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
734 connman_error("wmxsdk: Cannot subscribe to state chaneg events:"
735 "%d (%s)\n", r, errstr);
736 goto error_subscribe_state_change;
739 r = SubscribeNetworkSearchWideScanEx(&wmxsdk->device_id,
740 __iwmx_sdk_wide_scan_cb);
741 if (r != WIMAX_API_RET_SUCCESS) {
742 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
743 connman_error("wmxsdk: Cannot subscribe to wide scan events: "
744 "%d (%s)\n", r, errstr);
745 goto error_subscribe_wide_scan;
747 r = SubscribeNetworkSearchEx(&wmxsdk->device_id, __iwmx_sdk_scan_cb);
748 if (r != WIMAX_API_RET_SUCCESS) {
749 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
750 connman_error("wmxsdk: Cannot subscribe to scan events: "
751 "%d (%s)\n", r, errstr);
752 goto error_subscribe_scan;
755 r = SubscribeConnectToNetwork(&wmxsdk->device_id,
756 __iwmx_sdk_connect_cb);
757 if (r != WIMAX_API_RET_SUCCESS) {
758 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
759 connman_error("wmxsdk: Cannot subscribe to connect events: "
760 "%d (%s)\n", r, errstr);
761 goto error_subscribe_connect;
764 r = SubscribeDisconnectToNetwork(&wmxsdk->device_id,
765 __iwmx_sdk_disconnect_cb);
766 if (r != WIMAX_API_RET_SUCCESS) {
767 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
768 connman_error("wmxsdk: Cannot subscribe to disconnect events: "
769 "%d (%s)\n", r, errstr);
770 goto error_subscribe_disconnect;
776 UnsubscribeDisconnectToNetwork(&wmxsdk->device_id);
777 error_subscribe_disconnect:
778 UnsubscribeConnectToNetwork(&wmxsdk->device_id);
779 error_subscribe_connect:
780 UnsubscribeNetworkSearchEx(&wmxsdk->device_id);
781 error_subscribe_scan:
782 UnsubscribeNetworkSearchWideScanEx(&wmxsdk->device_id);
783 error_subscribe_wide_scan:
784 UnsubscribeDeviceStatusChange(&wmxsdk->device_id);
785 error_subscribe_state_change:
786 UnsubscribeControlPowerManagement(&wmxsdk->device_id);
787 error_subscribe_rf_state:
788 error_connection_mode:
789 WiMaxDeviceClose(&wmxsdk->device_id);
790 error_wimaxdeviceopen:
795 * Called when a device is removed from connman
797 * Cleanup all that is done in iwmx_sdk_setup(). Remove callbacks,
798 * unregister from the WiMAX API.
800 void iwmx_sdk_remove(struct wmxsdk *wmxsdk)
802 UnsubscribeDisconnectToNetwork(&wmxsdk->device_id);
803 UnsubscribeConnectToNetwork(&wmxsdk->device_id);
804 UnsubscribeNetworkSearchEx(&wmxsdk->device_id);
805 UnsubscribeNetworkSearchWideScanEx(&wmxsdk->device_id);
806 UnsubscribeDeviceStatusChange(&wmxsdk->device_id);
807 UnsubscribeControlPowerManagement(&wmxsdk->device_id);
808 WiMaxDeviceClose(&wmxsdk->device_id);
811 static void iwmx_sdk_dev_add(unsigned idx, unsigned api_idx, const char *name)
814 struct wmxsdk *wmxsdk;
817 if (idx >= IWMX_SDK_DEV_MAX) {
818 connman_error("BUG! idx (%u) >= IWMX_SDK_DEV_MAX (%u)\n",
819 idx, IWMX_SDK_DEV_MAX);
822 if (g_iwmx_sdk_devs[idx] != NULL) {
823 connman_error("BUG! device index %u already enumerated?\n",
828 wmxsdk = malloc(sizeof(*wmxsdk));
829 if (wmxsdk == NULL) {
830 connman_error("Can't allocate %zu bytes\n",
835 memset(wmxsdk, 0, sizeof(*wmxsdk));
838 * This depends on a hack in the WiMAX Network Service; it has
839 * to return, as part of the device name, a string "if:IFNAME"
840 * where the OS's device name is stored.
842 s = strstr(name, "if:");
844 || sscanf(s, "if:%15[^ \f\n\r\t\v]", wmxsdk->ifname) != 1) {
845 connman_error("Cannot extract network interface name off '%s'",
849 DBG("network interface name: '%s'", wmxsdk->ifname);
851 ifindex = if_nametoindex(wmxsdk->ifname);
854 connman_error("wxmsdk: %s: cannot find interface index\n",
859 wmxsdk->dev = connman_inet_create_device(ifindex);
860 if (wmxsdk->dev == NULL) {
861 connman_error("wmxsdk: %s: failed to create connman_device\n",
865 strncpy(wmxsdk->name, name, sizeof(wmxsdk->name));
866 connman_device_set_data(wmxsdk->dev, wmxsdk);
868 wmxsdk->device_id.privilege = WIMAX_API_PRIVILEGE_READ_WRITE;
869 wmxsdk->device_id.deviceIndex = api_idx;
871 result = connman_device_register(wmxsdk->dev);
873 connman_error("wmxsdk: %s: failed to register: %d\n",
874 wmxsdk->ifname, result);
877 g_iwmx_sdk_devs[idx] = wmxsdk;
882 connman_device_unref(wmxsdk->dev);
890 static void iwmx_sdk_dev_rm(unsigned idx)
892 struct wmxsdk *wmxsdk;
894 if (idx >= IWMX_SDK_DEV_MAX) {
895 connman_error("BUG! idx (%u) >= IWMX_SDK_DEV_MAX (%u)\n",
896 idx, IWMX_SDK_DEV_MAX);
899 wmxsdk = g_iwmx_sdk_devs[idx];
900 if (wmxsdk->dev == NULL) {
901 DBG("device index %u not enumerated? ignoring\n", idx);
905 connman_device_unregister(wmxsdk->dev);
907 connman_device_unref(wmxsdk->dev);
908 memset(wmxsdk, 0, sizeof(*wmxsdk));
909 g_iwmx_sdk_devs[idx] = NULL;
915 static void iwmx_sdk_addremove_cb(WIMAX_API_DEVICE_ID *devid,
920 WIMAX_API_HW_DEVICE_ID device_id_list[5];
921 UINT32 device_id_list_size = ARRAY_SIZE(device_id_list);
924 UINT32 errstr_size = sizeof(errstr);
926 DBG("cb: handle %u index #%u is %d\n", devid->sdkHandle,
927 devid->deviceIndex, presence);
929 r = GetListDevice(devid, device_id_list, &device_id_list_size);
930 if (r != WIMAX_API_RET_SUCCESS) {
931 GetErrorString(devid, r, errstr, &errstr_size);
932 connman_error("wmxsdk: Cannot obtain list "
933 "of devices: %d (%s)\n", r, errstr);
937 if (device_id_list_size == 0)
938 DBG("No WiMAX devices reported\n");
940 for (cnt = 0; cnt < device_id_list_size; cnt++) {
941 WIMAX_API_HW_DEVICE_ID *dev =
942 device_id_list + cnt;
943 DBG("#%u index #%u device %s\n",
944 cnt, dev->deviceIndex, dev->deviceName);
946 if (device_id_list_size < devid->deviceIndex) {
947 connman_error("wmxsdk: changed device (%u) not in the list? "
949 devid->deviceIndex, device_id_list_size);
954 WIMAX_API_HW_DEVICE_ID *dev =
955 device_id_list + devid->deviceIndex;
956 iwmx_sdk_dev_add(devid->deviceIndex, dev->deviceIndex,
959 iwmx_sdk_dev_rm(devid->deviceIndex);
964 * Initialize the WiMAX API, register with it, setup callbacks for
965 * device coming up / dissapearing
967 int iwmx_sdk_api_init(void)
973 UINT32 errstr_size = sizeof(errstr);
975 WIMAX_API_HW_DEVICE_ID device_id_list[5];
976 UINT32 device_id_list_size = ARRAY_SIZE(device_id_list);
978 memset(&g_api, 0, sizeof(g_api));
979 g_api.privilege = WIMAX_API_PRIVILEGE_READ_WRITE;
982 r = WiMaxAPIOpen(&g_api);
983 if (r != WIMAX_API_RET_SUCCESS) {
984 GetErrorString(&g_api, r, errstr, &errstr_size);
985 connman_error("wmxsdk: WiMaxAPIOpen failed with %d (%s)\n",
987 goto error_wimaxapiopen;
990 r = SubscribeDeviceInsertRemove(&g_api, iwmx_sdk_addremove_cb);
991 if (r != WIMAX_API_RET_SUCCESS) {
992 GetErrorString(&g_api, r, errstr, &errstr_size);
993 connman_error("wmxsdk: insert/remove subscribe failed with "
994 "%d (%s)\n", r, errstr);
998 r = GetListDevice(&g_api, device_id_list, &device_id_list_size);
999 if (r != WIMAX_API_RET_SUCCESS) {
1000 GetErrorString(&g_api, r, errstr, &errstr_size);
1001 connman_error("wmxsdk: Cannot obtain list "
1002 "of devices: %d (%s)\n", r, errstr);
1005 if (device_id_list_size < g_api.deviceIndex) {
1006 connman_error("wmxsdk: changed device (%u) not in the list? "
1008 g_api.deviceIndex, device_id_list_size);
1011 if (device_id_list_size == 0)
1012 DBG("No WiMAX devices reported\n");
1014 for (cnt = 0; cnt < device_id_list_size; cnt++) {
1015 WIMAX_API_HW_DEVICE_ID *dev =
1016 device_id_list + cnt;
1017 DBG("#%u index #%u device %s\n",
1018 cnt, dev->deviceIndex, dev->deviceName);
1019 iwmx_sdk_dev_add(cnt, dev->deviceIndex,
1025 WiMaxAPIClose(&g_api);
1030 void iwmx_sdk_api_exit(void)
1035 UINT32 errstr_size = sizeof(errstr);
1037 r = WiMaxAPIClose(&g_api);
1038 if (r != WIMAX_API_RET_SUCCESS) {
1039 GetErrorString(&g_api, r, errstr, &errstr_size);
1040 connman_error("wmxsdk: WiMaxAPIClose failed with %d (%s)\n",