5 * Copyright (C) 2007-2010 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 iwmx_sdk_network_type_name(WIMAX_API_UNKNOWN),
215 nsp_info.NSPName, strlen((char *) nsp_info.NSPName) + 1,
216 cinr_to_percentage(nsp_info.CINR - 10));
218 nw = iwmx_cm_network_available(
219 wmxsdk, (char *) nsp_info.NSPName,
220 iwmx_sdk_network_type_name(nsp_info.networkType),
221 nsp_info.NSPName, strlen((char *) nsp_info.NSPName) + 1,
222 cinr_to_percentage(nsp_info.CINR - 10));
228 * Callback for a RF State command
230 * Called by the WiMAX API when a command sent to change the RF state
231 * is completed. This is just a confirmation of what happened with the
234 * We don't do anything, as when the device changes state, the state
235 * change callback is called and that will fiddle with the connman
238 static void __iwmx_sdk_rf_state_cb(WIMAX_API_DEVICE_ID *device_id,
239 WIMAX_API_RF_STATE rf_state)
241 DBG("rf_state changed to %d\n", rf_state);
245 * Turn the radio on or off
247 * First it checks that we are in the right state before doing
248 * anything; there might be no need to do anything.
250 * Issue a command to the WiMAX API, wait for a callback confirming it
251 * is done. Sometimes the callback is missed -- in that case, do force
252 * a state change evaluation.
256 * Geezoos efing Xist, they make difficult even the most simple
259 * This thing is definitely a pain. If the radio is ON already
260 * and you switch it on again...well, there is no way to tell
261 * because you don't get a callback saying it basically
262 * suceeded. But on the other hand, if the thing was in a
263 * different state and action needs to be taken, you have to wait
264 * for a callback to confirm it's done. However, there is also an
265 * state change callback, which is almost the same, so now you
266 * have to handle things in two "unrelated" threads of execution.
268 * How the shpx are you expected to tell the difference? Check
269 * status first? On timeout? Nice gap (eighteen wheeler size) for
272 int iwmx_sdk_rf_state_set(struct wmxsdk *wmxsdk, WIMAX_API_RF_STATE rf_state)
278 UINT32 errstr_size = sizeof(errstr);
279 WIMAX_API_DEVICE_STATUS dev_status;
281 g_assert(rf_state == WIMAX_API_RF_ON || rf_state == WIMAX_API_RF_OFF);
283 /* Guess what the current radio state is; if it is ON
284 * already, don't redo it. */
285 dev_status = iwmx_sdk_get_device_status(wmxsdk);
286 if ((int) dev_status < 0) {
288 goto error_get_status;
290 switch (dev_status) {
291 case WIMAX_API_DEVICE_STATUS_UnInitialized:
294 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
295 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
297 "wmxsdk: cannot turn on radio: hw switch is off\n");
301 case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
302 if (rf_state == WIMAX_API_RF_OFF) {
304 DBG("radio is already off\n");
308 case WIMAX_API_DEVICE_STATUS_Ready:
309 case WIMAX_API_DEVICE_STATUS_Scanning:
310 case WIMAX_API_DEVICE_STATUS_Connecting:
311 case WIMAX_API_DEVICE_STATUS_Data_Connected:
312 #if HAVE_IWMXSDK_STATUS_IDLE
313 case WIMAX_API_DEVICE_STATUS_Connection_Idle:
315 if (rf_state == WIMAX_API_RF_ON) {
317 DBG("radio is already on\n");
324 /* Ok, flip the radio */
325 r = CmdControlPowerManagement(&wmxsdk->device_id, rf_state);
326 if (r != WIMAX_API_RET_SUCCESS) {
327 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
328 connman_error("wmxsdk: Cannot flip radio to %d: %d (%s) "
329 "[device is in state %s]\n",
331 iwmx_sdk_get_device_status_str(wmxsdk));
334 result = -EINPROGRESS;
342 * Callback for a Connect command
344 * Called by the WiMAX API when a command sent to connect is
345 * completed. This is just a confirmation of what happened with the
348 * WE DON'T DO MUCH HERE -- the real meat happens when a state change
349 * callback is sent, where we detect we move to connected state (or
350 * from disconnecting to something else); the state change callback is
351 * called and that will fiddle with the connman internals.
353 static void __iwmx_sdk_connect_cb(WIMAX_API_DEVICE_ID *device_id,
354 WIMAX_API_NETWORK_CONNECTION_RESP resp)
356 WIMAX_API_DEVICE_STATUS status;
357 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
359 status = iwmx_cm_status_get(wmxsdk);
360 if (resp == WIMAX_API_CONNECTION_SUCCESS) {
361 if (status != WIMAX_API_DEVICE_STATUS_Data_Connected
362 #if HAVE_IWMXSDK_STATUS_IDLE
363 && status != WIMAX_API_DEVICE_STATUS_Connection_Idle
366 connman_error("wmxsdk: error: connect worked, but state"
367 " didn't change (now it is %d [%s])\n",
369 iwmx_sdk_dev_status_to_str(status));
371 connman_error("wmxsdk: failed to connect (status %d: %s)\n",
372 status, iwmx_sdk_dev_status_to_str(status));
376 * Connect to a network
378 * This function starts the connection process to a given network;
379 * when the device changes status, the status change callback will
380 * tell connman if the network is finally connected or not.
382 * One of the reasons it is done like that is to allow external tools
383 * to control the device and the plugin just passing the status so
384 * connman displays the right info.
386 int iwmx_sdk_connect(struct wmxsdk *wmxsdk, struct connman_network *nw)
392 UINT32 errstr_size = sizeof(errstr);
393 WIMAX_API_DEVICE_STATUS dev_status;
394 const char *station_name = connman_network_get_identifier(nw);
395 const void *sdk_nspname;
396 unsigned int sdk_nspname_size;
398 g_mutex_lock(wmxsdk->connect_mutex);
399 /* Guess what the current radio state is; if it is ON
400 * already, don't redo it. */
401 dev_status = iwmx_cm_status_get(wmxsdk);
402 if ((int) dev_status < 0) {
404 goto error_get_status;
406 switch (dev_status) {
407 case WIMAX_API_DEVICE_STATUS_UnInitialized:
408 connman_error("wmxsdk: SW BUG? HW is uninitialized\n");
411 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
412 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
413 case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
414 connman_error("wmxsdk: Cannot connect: radio is off\n");
417 case WIMAX_API_DEVICE_STATUS_Ready:
418 case WIMAX_API_DEVICE_STATUS_Scanning:
420 case WIMAX_API_DEVICE_STATUS_Connecting:
421 DBG("Connect already pending, waiting for it\n");
422 result = -EINPROGRESS;
424 case WIMAX_API_DEVICE_STATUS_Data_Connected:
425 #if HAVE_IWMXSDK_STATUS_IDLE
426 case WIMAX_API_DEVICE_STATUS_Connection_Idle:
428 connman_error("wmxsdk: BUG? need to disconnect?\n");
435 /* Ok, do the connection, wait for a callback */
436 wmxsdk->connecting_nw = connman_network_ref(nw);
437 sdk_nspname = connman_network_get_blob(nw, "WiMAX.NSP.name",
439 g_assert(sdk_nspname != NULL);
440 r = CmdConnectToNetwork(&wmxsdk->device_id, (void *) sdk_nspname, 0, 0);
441 if (r != WIMAX_API_RET_SUCCESS) {
442 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
443 connman_error("wmxsdk: Cannot connect to network %s: %d (%s)"
444 " - device is in state '%s'\n",
445 station_name, r, errstr,
446 iwmx_sdk_get_device_status_str(wmxsdk));
448 connman_network_unref(nw);
449 wmxsdk->connecting_nw = NULL;
451 result = -EINPROGRESS;
454 g_mutex_unlock(wmxsdk->connect_mutex);
459 * Callback for a Disconnect command
461 * Called by the WiMAX API when a command sent to connect is
462 * completed. This is just a confirmation of what happened with the
465 * When the device changes state, the state change callback is called
466 * and that will fiddle with the connman internals.
468 * We just update the result of the command and wake up anybody who is
469 * waiting for this conditional variable.
471 static void __iwmx_sdk_disconnect_cb(WIMAX_API_DEVICE_ID *device_id,
472 WIMAX_API_NETWORK_CONNECTION_RESP resp)
474 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
475 WIMAX_API_DEVICE_STATUS status;
477 status = iwmx_cm_status_get(wmxsdk);
478 if (resp == WIMAX_API_CONNECTION_SUCCESS) {
479 if (status == WIMAX_API_DEVICE_STATUS_Data_Connected
480 #if HAVE_IWMXSDK_STATUS_IDLE
481 || status == WIMAX_API_DEVICE_STATUS_Connection_Idle
484 connman_error("wmxsdk: error: disconnect worked, "
485 "but state didn't change (now it is "
486 "%d [%s])\n", status,
487 iwmx_sdk_dev_status_to_str(status));
489 connman_error("wmxsdk: failed to disconnect (status %d: %s)\n",
490 status, iwmx_sdk_dev_status_to_str(status));
494 * Disconnect from a network
496 * This function tells the device to disconnect; the state change
497 * callback will take care of inform connman's internals.
499 int iwmx_sdk_disconnect(struct wmxsdk *wmxsdk)
505 UINT32 errstr_size = sizeof(errstr);
506 WIMAX_API_DEVICE_STATUS dev_status;
508 g_mutex_lock(wmxsdk->connect_mutex);
509 /* Guess what the current radio state is; if it is ON
510 * already, don't redo it. */
511 dev_status = iwmx_sdk_get_device_status(wmxsdk);
512 if ((int) dev_status < 0) {
514 goto error_get_status;
516 switch (dev_status) {
517 case WIMAX_API_DEVICE_STATUS_UnInitialized:
518 connman_error("wmxsdk: SW BUG? HW is uninitialized\n");
521 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
522 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
523 case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
524 DBG("Cannot disconnect, radio is off; ignoring\n");
527 case WIMAX_API_DEVICE_STATUS_Ready:
528 case WIMAX_API_DEVICE_STATUS_Scanning:
529 DBG("Cannot disconnect, already disconnected; ignoring\n");
532 case WIMAX_API_DEVICE_STATUS_Connecting:
533 case WIMAX_API_DEVICE_STATUS_Data_Connected:
534 #if HAVE_IWMXSDK_STATUS_IDLE
535 case WIMAX_API_DEVICE_STATUS_Connection_Idle:
541 /* Ok, flip the radio */
542 r = CmdDisconnectFromNetwork(&wmxsdk->device_id);
543 if (r != WIMAX_API_RET_SUCCESS) {
544 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
545 connman_error("wmxsdk: Cannot disconnect from network: "
546 "%d (%s)\n", r, errstr);
549 result = -EINPROGRESS;
552 g_mutex_unlock(wmxsdk->connect_mutex);
557 * Callback for state change messages
559 * Just pass them to the state transition handler
561 static void __iwmx_sdk_state_change_cb(WIMAX_API_DEVICE_ID *device_id,
562 WIMAX_API_DEVICE_STATUS status,
563 WIMAX_API_STATUS_REASON reason,
564 WIMAX_API_CONNECTION_PROGRESS_INFO pi)
566 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
567 iwmx_cm_state_change(wmxsdk, status);
571 * Called by _iwmx_sdk_*scan_cb() when [wide or preferred] scan results
574 * From here we update the connman core idea of which networks are
577 static void __iwmx_sdk_scan_common_cb(WIMAX_API_DEVICE_ID *device_id,
578 WIMAX_API_NSP_INFO_EX *nsp_list,
579 UINT32 nsp_list_size)
581 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
583 char station_name[256];
585 g_static_mutex_lock(&wmxsdk->network_mutex);
586 for (itr = 0; itr < nsp_list_size; itr++) {
588 WIMAX_API_NSP_INFO_EX *nsp_info = &nsp_list[itr];
589 snprintf(station_name, sizeof(station_name),
590 "%s", (char *)nsp_info->NSPName);
591 /* CAPI is reporing link quality as zero -- if it is
592 * zero, check if it is a bug by computing it based on
593 * CINR. If it is different, use the computed one. */
594 strength = nsp_info->linkQuality;
595 if (strength == 0) { /* huh */
597 cinr_to_percentage(nsp_info->CINR - 10);
598 if (linkq_expected != strength)
599 strength = linkq_expected;
602 __iwmx_cm_network_available(
603 wmxsdk, station_name,
604 iwmx_sdk_network_type_name(nsp_info->networkType),
606 strlen((char *) nsp_info->NSPName) + 1,
609 g_static_mutex_unlock(&wmxsdk->network_mutex);
613 * Called by the WiMAX API when we get a wide scan result
615 * We treat them same as wide, so we just call that.
617 static void __iwmx_sdk_wide_scan_cb(WIMAX_API_DEVICE_ID *device_id,
618 WIMAX_API_NSP_INFO_EX *nsp_list,
619 UINT32 nsp_list_size)
621 __iwmx_sdk_scan_common_cb(device_id, nsp_list, nsp_list_size);
625 * Called by the WiMAX API when we get a normal (non wide) scan result
627 * We treat them same as wide, so we just call that.
629 static void __iwmx_sdk_scan_cb(WIMAX_API_DEVICE_ID *device_id,
630 WIMAX_API_NSP_INFO_EX *nsp_list,
631 UINT32 nsp_list_size, UINT32 searchProgress)
633 __iwmx_sdk_scan_common_cb(device_id, nsp_list, nsp_list_size);
637 * Called to ask the device to scan for networks
639 * We don't really scan as the WiMAX SDK daemon scans in the
640 * background for us. We just get the results. See iwmx_sdk_setup().
642 int iwmx_sdk_scan(struct wmxsdk *wmxsdk)
646 UINT32 nsp_list_length = 10;
647 WIMAX_API_NSP_INFO_EX nsp_list[10]; /* FIXME: up to 32? */
651 UINT32 errstr_size = sizeof(errstr);
653 r = GetNetworkListEx(&wmxsdk->device_id, nsp_list, &nsp_list_length);
654 if (r != WIMAX_API_RET_SUCCESS) {
655 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
656 connman_error("wmxsdk: Cannot get network list: %d (%s)\n",
662 if (nsp_list_length == 0)
663 DBG("no networks\n");
665 __iwmx_sdk_scan_common_cb(&wmxsdk->device_id, nsp_list,
673 * Initialize the WiMAX API, register with it, setup callbacks
678 * connman_inet_create_device
682 int iwmx_sdk_setup(struct wmxsdk *wmxsdk)
689 UINT32 errstr_size = sizeof(errstr);
693 /* device_id initialized by iwmx_sdk_dev_add */
695 r = WiMaxDeviceOpen(&wmxsdk->device_id);
696 if (r != WIMAX_API_RET_SUCCESS) {
697 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
698 connman_error("wmxsdk: Cannot open device: %d (%s)\n",
700 goto error_wimaxdeviceopen;
704 * We scan in auto mode (in the background)
706 * Otherwise is messy -- if we have connman triggering a scan
707 * when we call iwmx_cm_scan() -> iwmx_sdk_scan(), most of the
708 * times that causes a race condition when the UI asks for a
709 * scan right before displaying the network menu. As there is
710 * no way to cancel an ongoing scan before connecting, we are
711 * stuck. So we do auto bg and have iwmx_sdk_scan() just return
712 * the current network list.
714 r = SetConnectionMode(&wmxsdk->device_id,
715 WIMAX_API_CONNECTION_AUTO_SCAN_MANUAL_CONNECT);
716 if (r != WIMAX_API_RET_SUCCESS) {
717 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
718 connman_error("wmxsdk: Cannot set connectin mode to manual: "
719 "%d (%s)\n", r, errstr);
720 goto error_connection_mode;
723 r = SubscribeControlPowerManagement(&wmxsdk->device_id,
724 __iwmx_sdk_rf_state_cb);
725 if (r != WIMAX_API_RET_SUCCESS) {
726 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
727 connman_error("wmxsdk: Cannot subscribe to radio change "
728 "events: %u (%s)\n", r, errstr);
730 goto error_subscribe_rf_state;
733 r = SubscribeDeviceStatusChange(&wmxsdk->device_id,
734 __iwmx_sdk_state_change_cb);
735 if (r != WIMAX_API_RET_SUCCESS) {
736 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
737 connman_error("wmxsdk: Cannot subscribe to state chaneg events:"
738 "%d (%s)\n", r, errstr);
739 goto error_subscribe_state_change;
742 r = SubscribeNetworkSearchWideScanEx(&wmxsdk->device_id,
743 __iwmx_sdk_wide_scan_cb);
744 if (r != WIMAX_API_RET_SUCCESS) {
745 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
746 connman_error("wmxsdk: Cannot subscribe to wide scan events: "
747 "%d (%s)\n", r, errstr);
748 goto error_subscribe_wide_scan;
750 r = SubscribeNetworkSearchEx(&wmxsdk->device_id, __iwmx_sdk_scan_cb);
751 if (r != WIMAX_API_RET_SUCCESS) {
752 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
753 connman_error("wmxsdk: Cannot subscribe to scan events: "
754 "%d (%s)\n", r, errstr);
755 goto error_subscribe_scan;
758 r = SubscribeConnectToNetwork(&wmxsdk->device_id,
759 __iwmx_sdk_connect_cb);
760 if (r != WIMAX_API_RET_SUCCESS) {
761 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
762 connman_error("wmxsdk: Cannot subscribe to connect events: "
763 "%d (%s)\n", r, errstr);
764 goto error_subscribe_connect;
767 r = SubscribeDisconnectToNetwork(&wmxsdk->device_id,
768 __iwmx_sdk_disconnect_cb);
769 if (r != WIMAX_API_RET_SUCCESS) {
770 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
771 connman_error("wmxsdk: Cannot subscribe to disconnect events: "
772 "%d (%s)\n", r, errstr);
773 goto error_subscribe_disconnect;
779 UnsubscribeDisconnectToNetwork(&wmxsdk->device_id);
780 error_subscribe_disconnect:
781 UnsubscribeConnectToNetwork(&wmxsdk->device_id);
782 error_subscribe_connect:
783 UnsubscribeNetworkSearchEx(&wmxsdk->device_id);
784 error_subscribe_scan:
785 UnsubscribeNetworkSearchWideScanEx(&wmxsdk->device_id);
786 error_subscribe_wide_scan:
787 UnsubscribeDeviceStatusChange(&wmxsdk->device_id);
788 error_subscribe_state_change:
789 UnsubscribeControlPowerManagement(&wmxsdk->device_id);
790 error_subscribe_rf_state:
791 error_connection_mode:
792 WiMaxDeviceClose(&wmxsdk->device_id);
793 error_wimaxdeviceopen:
798 * Called when a device is removed from connman
800 * Cleanup all that is done in iwmx_sdk_setup(). Remove callbacks,
801 * unregister from the WiMAX API.
803 void iwmx_sdk_remove(struct wmxsdk *wmxsdk)
805 UnsubscribeDisconnectToNetwork(&wmxsdk->device_id);
806 UnsubscribeConnectToNetwork(&wmxsdk->device_id);
807 UnsubscribeNetworkSearchEx(&wmxsdk->device_id);
808 UnsubscribeNetworkSearchWideScanEx(&wmxsdk->device_id);
809 UnsubscribeDeviceStatusChange(&wmxsdk->device_id);
810 UnsubscribeControlPowerManagement(&wmxsdk->device_id);
811 WiMaxDeviceClose(&wmxsdk->device_id);
814 static void iwmx_sdk_dev_add(unsigned idx, unsigned api_idx, const char *name)
817 struct wmxsdk *wmxsdk;
820 if (idx >= IWMX_SDK_DEV_MAX) {
821 connman_error("BUG! idx (%u) >= IWMX_SDK_DEV_MAX (%u)\n",
822 idx, IWMX_SDK_DEV_MAX);
825 if (g_iwmx_sdk_devs[idx] != NULL) {
826 connman_error("BUG! device index %u already enumerated?\n",
831 wmxsdk = malloc(sizeof(*wmxsdk));
832 if (wmxsdk == NULL) {
833 connman_error("Can't allocate %zu bytes\n",
838 memset(wmxsdk, 0, sizeof(*wmxsdk));
841 * This depends on a hack in the WiMAX Network Service; it has
842 * to return, as part of the device name, a string "if:IFNAME"
843 * where the OS's device name is stored.
845 s = strstr(name, "if:");
847 || sscanf(s, "if:%15[^ \f\n\r\t\v]", wmxsdk->ifname) != 1) {
848 connman_error("Cannot extract network interface name off '%s'",
852 DBG("network interface name: '%s'", wmxsdk->ifname);
854 ifindex = if_nametoindex(wmxsdk->ifname);
857 connman_error("wxmsdk: %s: cannot find interface index\n",
862 wmxsdk->dev = connman_inet_create_device(ifindex);
863 if (wmxsdk->dev == NULL) {
864 connman_error("wmxsdk: %s: failed to create connman_device\n",
868 strncpy(wmxsdk->name, name, sizeof(wmxsdk->name));
869 connman_device_set_data(wmxsdk->dev, wmxsdk);
871 wmxsdk->device_id.privilege = WIMAX_API_PRIVILEGE_READ_WRITE;
872 wmxsdk->device_id.deviceIndex = api_idx;
874 result = connman_device_register(wmxsdk->dev);
876 connman_error("wmxsdk: %s: failed to register: %d\n",
877 wmxsdk->ifname, result);
880 g_iwmx_sdk_devs[idx] = wmxsdk;
885 connman_device_unref(wmxsdk->dev);
893 static void iwmx_sdk_dev_rm(unsigned idx)
895 struct wmxsdk *wmxsdk;
897 if (idx >= IWMX_SDK_DEV_MAX) {
898 connman_error("BUG! idx (%u) >= IWMX_SDK_DEV_MAX (%u)\n",
899 idx, IWMX_SDK_DEV_MAX);
902 wmxsdk = g_iwmx_sdk_devs[idx];
903 if (wmxsdk->dev == NULL) {
904 DBG("device index %u not enumerated? ignoring\n", idx);
908 connman_device_unregister(wmxsdk->dev);
910 connman_device_unref(wmxsdk->dev);
911 memset(wmxsdk, 0, sizeof(*wmxsdk));
912 g_iwmx_sdk_devs[idx] = NULL;
918 static void iwmx_sdk_addremove_cb(WIMAX_API_DEVICE_ID *devid,
923 WIMAX_API_HW_DEVICE_ID device_id_list[5];
924 UINT32 device_id_list_size = ARRAY_SIZE(device_id_list);
927 UINT32 errstr_size = sizeof(errstr);
929 DBG("cb: handle %u index #%u is %d\n", devid->sdkHandle,
930 devid->deviceIndex, presence);
932 r = GetListDevice(devid, device_id_list, &device_id_list_size);
933 if (r != WIMAX_API_RET_SUCCESS) {
934 GetErrorString(devid, r, errstr, &errstr_size);
935 connman_error("wmxsdk: Cannot obtain list "
936 "of devices: %d (%s)\n", r, errstr);
940 if (device_id_list_size == 0)
941 DBG("No WiMAX devices reported\n");
943 for (cnt = 0; cnt < device_id_list_size; cnt++) {
944 WIMAX_API_HW_DEVICE_ID *dev =
945 device_id_list + cnt;
946 DBG("#%u index #%u device %s\n",
947 cnt, dev->deviceIndex, dev->deviceName);
949 if (device_id_list_size < devid->deviceIndex) {
950 connman_error("wmxsdk: changed device (%u) not in the list? "
952 devid->deviceIndex, device_id_list_size);
957 WIMAX_API_HW_DEVICE_ID *dev =
958 device_id_list + devid->deviceIndex;
959 iwmx_sdk_dev_add(devid->deviceIndex, dev->deviceIndex,
962 iwmx_sdk_dev_rm(devid->deviceIndex);
967 * Initialize the WiMAX API, register with it, setup callbacks for
968 * device coming up / dissapearing
970 int iwmx_sdk_api_init(void)
976 UINT32 errstr_size = sizeof(errstr);
978 WIMAX_API_HW_DEVICE_ID device_id_list[5];
979 UINT32 device_id_list_size = ARRAY_SIZE(device_id_list);
981 memset(&g_api, 0, sizeof(g_api));
982 g_api.privilege = WIMAX_API_PRIVILEGE_READ_WRITE;
985 r = WiMaxAPIOpen(&g_api);
986 if (r != WIMAX_API_RET_SUCCESS) {
987 GetErrorString(&g_api, r, errstr, &errstr_size);
988 connman_error("wmxsdk: WiMaxAPIOpen failed with %d (%s)\n",
990 goto error_wimaxapiopen;
993 r = SubscribeDeviceInsertRemove(&g_api, iwmx_sdk_addremove_cb);
994 if (r != WIMAX_API_RET_SUCCESS) {
995 GetErrorString(&g_api, r, errstr, &errstr_size);
996 connman_error("wmxsdk: insert/remove subscribe failed with "
997 "%d (%s)\n", r, errstr);
1001 r = GetListDevice(&g_api, device_id_list, &device_id_list_size);
1002 if (r != WIMAX_API_RET_SUCCESS) {
1003 GetErrorString(&g_api, r, errstr, &errstr_size);
1004 connman_error("wmxsdk: Cannot obtain list "
1005 "of devices: %d (%s)\n", r, errstr);
1008 if (device_id_list_size < g_api.deviceIndex) {
1009 connman_error("wmxsdk: changed device (%u) not in the list? "
1011 g_api.deviceIndex, device_id_list_size);
1014 if (device_id_list_size == 0)
1015 DBG("No WiMAX devices reported\n");
1017 for (cnt = 0; cnt < device_id_list_size; cnt++) {
1018 WIMAX_API_HW_DEVICE_ID *dev =
1019 device_id_list + cnt;
1020 DBG("#%u index #%u device %s\n",
1021 cnt, dev->deviceIndex, dev->deviceName);
1022 iwmx_sdk_dev_add(cnt, dev->deviceIndex,
1028 WiMaxAPIClose(&g_api);
1033 void iwmx_sdk_api_exit(void)
1038 UINT32 errstr_size = sizeof(errstr);
1040 r = WiMaxAPIClose(&g_api);
1041 if (r != WIMAX_API_RET_SUCCESS) {
1042 GetErrorString(&g_api, r, errstr, &errstr_size);
1043 connman_error("wmxsdk: WiMaxAPIClose failed with %d (%s)\n",