5 * Copyright (C) 2007-2009 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
33 #define CONNMAN_API_SUBJECT_TO_CHANGE
34 #include <connman/device.h>
35 #include <connman/inet.h>
36 #include <connman/log.h>
38 #include <WiMaxType.h>
40 #include <WiMaxAPIEx.h>
44 /* Yes, this is dirty; see above on IWMX_SDK_DEV_MAX*/
45 static struct wmxsdk g_iwmx_sdk_devs[IWMX_SDK_DEV_MAX];
47 static struct wmxsdk *deviceid_to_wmxsdk(WIMAX_API_DEVICE_ID *device_id)
49 return container_of(device_id, struct wmxsdk, device_id);
52 static WIMAX_API_DEVICE_ID g_api;
56 * FIXME: pulled it it out of some hole
58 * the cinr to percentage computation comes from the L3/L4 doc
60 * But some other places (L4 code) have a more complex, seemingly
61 * logarithmical computation.
66 static int cinr_to_percentage(int cinr)
73 else /* Calc percentage on the value from -5 to 25 */
74 strength = ((100UL * (cinr - -5)) / (25 - -5));
79 * Convert a WiMAX API status to an string.
81 const char *iwmx_sdk_dev_status_to_str(WIMAX_API_DEVICE_STATUS status)
84 case WIMAX_API_DEVICE_STATUS_UnInitialized:
85 return "Uninitialized";
87 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
88 return "Device RF Off(both H/W and S/W)";
90 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
91 return "Device RF Off(via H/W switch)";
92 case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
93 return "Device RF Off(via S/W switch)";
94 case WIMAX_API_DEVICE_STATUS_Ready:
95 return "Device is ready";
96 case WIMAX_API_DEVICE_STATUS_Scanning:
97 return "Device is scanning";
98 case WIMAX_API_DEVICE_STATUS_Connecting:
99 return "Connection in progress";
100 case WIMAX_API_DEVICE_STATUS_Data_Connected:
101 return "Layer 2 connected";
102 #if HAVE_IWMXSDK_STATUS_IDLE
103 case WIMAX_API_DEVICE_STATUS_Connection_Idle:
104 return "Idle connection";
105 #endif /* #if HAVE_IWMXSDK_STATUS_IDLE */
107 return "unknown state";
112 * Get the device's status from the device
114 * Does NOT cache the result
115 * Does NOT trigger a state change in connman
117 * Returns < 0 errno code on error, status code if ok.
119 WIMAX_API_DEVICE_STATUS iwmx_sdk_get_device_status(struct wmxsdk *wmxsdk)
123 UINT32 errstr_size = sizeof(errstr);
125 WIMAX_API_DEVICE_STATUS dev_status;
126 WIMAX_API_CONNECTION_PROGRESS_INFO pi;
128 r = GetDeviceStatus(&wmxsdk->device_id, &dev_status, &pi);
129 if (r != WIMAX_API_RET_SUCCESS) {
130 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
131 connman_error("wmxsdk: Cannot read device state: %d (%s)\n",
139 * Get the device's status from the device but return a string describing it
141 * Same conditions as iwmx_sdk_get_device_status().
143 static const char *iwmx_sdk_get_device_status_str(struct wmxsdk *wmxsdk)
146 WIMAX_API_DEVICE_STATUS dev_status;
148 dev_status = iwmx_sdk_get_device_status(wmxsdk);
149 if ((int) dev_status < 0)
150 result = "cannot read device state";
152 result = iwmx_sdk_dev_status_to_str(dev_status);
157 * Translate a WiMAX network type to a readable name.
159 static const char *iwmx_sdk_network_type_name(enum _WIMAX_API_NETWORK_TYPE network_type)
161 static char *network_type_name[] = {
162 [WIMAX_API_HOME] = "",
163 [WIMAX_API_PARTNER] = " (partner network)",
164 [WIMAX_API_ROAMING_PARTNER] = " (roaming partner network)",
165 [WIMAX_API_UNKNOWN] = " (unknown network)",
167 if (network_type > WIMAX_API_UNKNOWN)
168 return "(BUG! UNKNOWN NETWORK_TYPE MODE)";
170 return network_type_name[network_type];
174 * If the device is connected but we don't know about the network,
175 * create the knowledge of it.
177 * Asks the WiMAX API to report which NSP we are connected to and we
178 * create/update a network_el in the device's network list. Then
181 * Returns NULL on error.
183 * NOTE: wmxsdk->network_mutex has to be taken
185 struct connman_network *__iwmx_sdk_get_connected_network(struct wmxsdk *wmxsdk)
187 struct connman_network *nw;
189 WIMAX_API_CONNECTED_NSP_INFO nsp_info;
192 UINT32 errstr_size = sizeof(errstr);
194 /* The device is getting connected due to an external (to
195 * connman) event; find which is the nw we are getting
196 * connected to. if we don't have it, add it */
197 r = GetConnectedNSP(&wmxsdk->device_id, &nsp_info);
198 if (r != WIMAX_API_RET_SUCCESS) {
199 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
201 "wmxsdk: Cannot get connected NSP info: %d (%s)\n",
203 strcpy((char *) nsp_info.NSPName, "unknown");
204 nw = iwmx_cm_network_available(
206 iwmx_sdk_network_type_name(WIMAX_API_UNKNOWN),
207 nsp_info.NSPName, strlen((char *) nsp_info.NSPName) + 1,
208 cinr_to_percentage(nsp_info.CINR - 10));
210 nw = iwmx_cm_network_available(
211 wmxsdk, (char *) nsp_info.NSPName,
212 iwmx_sdk_network_type_name(nsp_info.networkType),
213 nsp_info.NSPName, strlen((char *) nsp_info.NSPName) + 1,
214 cinr_to_percentage(nsp_info.CINR - 10));
220 * Callback for a RF State command
222 * Called by the WiMAX API when a command sent to change the RF state
223 * is completed. This is just a confirmation of what happened with the
226 * We don't do anything, as when the device changes state, the state
227 * change callback is called and that will fiddle with the connman
230 static void __iwmx_sdk_rf_state_cb(WIMAX_API_DEVICE_ID *device_id,
231 WIMAX_API_RF_STATE rf_state)
233 DBG("rf_state changed to %d\n", rf_state);
237 * Turn the radio on or off
239 * First it checks that we are in the right state before doing
240 * anything; there might be no need to do anything.
242 * Issue a command to the WiMAX API, wait for a callback confirming it
243 * is done. Sometimes the callback is missed -- in that case, do force
244 * a state change evaluation.
248 * Geezoos efing Xist, they make difficult even the most simple
251 * This thing is definitely a pain. If the radio is ON already
252 * and you switch it on again...well, there is no way to tell
253 * because you don't get a callback saying it basically
254 * suceeded. But on the other hand, if the thing was in a
255 * different state and action needs to be taken, you have to wait
256 * for a callback to confirm it's done. However, there is also an
257 * state change callback, which is almost the same, so now you
258 * have to handle things in two "unrelated" threads of execution.
260 * How the shpx are you expected to tell the difference? Check
261 * status first? On timeout? Nice gap (eighteen wheeler size) for
264 int iwmx_sdk_rf_state_set(struct wmxsdk *wmxsdk, WIMAX_API_RF_STATE rf_state)
270 UINT32 errstr_size = sizeof(errstr);
271 WIMAX_API_DEVICE_STATUS dev_status;
273 g_assert(rf_state == WIMAX_API_RF_ON || rf_state == WIMAX_API_RF_OFF);
275 /* Guess what the current radio state is; if it is ON
276 * already, don't redo it. */
277 dev_status = iwmx_sdk_get_device_status(wmxsdk);
278 if ((int) dev_status < 0) {
280 goto error_get_status;
282 switch (dev_status) {
283 case WIMAX_API_DEVICE_STATUS_UnInitialized:
286 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
287 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
289 "wmxsdk: cannot turn on radio: hw switch is off\n");
293 case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
294 if (rf_state == WIMAX_API_RF_OFF) {
296 DBG("radio is already off\n");
300 case WIMAX_API_DEVICE_STATUS_Ready:
301 case WIMAX_API_DEVICE_STATUS_Scanning:
302 case WIMAX_API_DEVICE_STATUS_Connecting:
303 case WIMAX_API_DEVICE_STATUS_Data_Connected:
304 #if HAVE_IWMXSDK_STATUS_IDLE
305 case WIMAX_API_DEVICE_STATUS_Connection_Idle:
307 if (rf_state == WIMAX_API_RF_ON) {
309 DBG("radio is already on\n");
316 /* Ok, flip the radio */
317 r = CmdControlPowerManagement(&wmxsdk->device_id, rf_state);
318 if (r != WIMAX_API_RET_SUCCESS) {
319 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
320 connman_error("wmxsdk: Cannot flip radio to %d: %d (%s) "
321 "[device is in state %s]\n",
323 iwmx_sdk_get_device_status_str(wmxsdk));
326 result = -EINPROGRESS;
334 * Callback for a Connect command
336 * Called by the WiMAX API when a command sent to connect is
337 * completed. This is just a confirmation of what happened with the
340 * WE DON'T DO MUCH HERE -- the real meat happens when a state change
341 * callback is sent, where we detect we move to connected state (or
342 * from disconnecting to something else); the state change callback is
343 * called and that will fiddle with the connman internals.
345 static void __iwmx_sdk_connect_cb(WIMAX_API_DEVICE_ID *device_id,
346 WIMAX_API_NETWORK_CONNECTION_RESP resp)
348 WIMAX_API_DEVICE_STATUS status;
349 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
351 status = iwmx_cm_status_get(wmxsdk);
352 if (resp == WIMAX_API_CONNECTION_SUCCESS) {
353 if (status != WIMAX_API_DEVICE_STATUS_Data_Connected
354 #if HAVE_IWMXSDK_STATUS_IDLE
355 && status != WIMAX_API_DEVICE_STATUS_Connection_Idle
358 connman_error("wmxsdk: error: connect worked, but state"
359 " didn't change (now it is %d [%s])\n",
361 iwmx_sdk_dev_status_to_str(status));
363 connman_error("wmxsdk: failed to connect (status %d: %s)\n",
364 status, iwmx_sdk_dev_status_to_str(status));
368 * Connect to a network
370 * This function starts the connection process to a given network;
371 * when the device changes status, the status change callback will
372 * tell connman if the network is finally connected or not.
374 * One of the reasons it is done like that is to allow external tools
375 * to control the device and the plugin just passing the status so
376 * connman displays the right info.
378 int iwmx_sdk_connect(struct wmxsdk *wmxsdk, struct connman_network *nw)
384 UINT32 errstr_size = sizeof(errstr);
385 WIMAX_API_DEVICE_STATUS dev_status;
386 const char *station_name = connman_network_get_identifier(nw);
387 const void *sdk_nspname;
388 unsigned int sdk_nspname_size;
390 g_mutex_lock(wmxsdk->connect_mutex);
391 /* Guess what the current radio state is; if it is ON
392 * already, don't redo it. */
393 dev_status = iwmx_cm_status_get(wmxsdk);
394 if ((int) dev_status < 0) {
396 goto error_get_status;
398 switch (dev_status) {
399 case WIMAX_API_DEVICE_STATUS_UnInitialized:
400 connman_error("wmxsdk: SW BUG? HW is uninitialized\n");
403 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
404 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
405 case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
406 connman_error("wmxsdk: Cannot connect: radio is off\n");
409 case WIMAX_API_DEVICE_STATUS_Ready:
410 case WIMAX_API_DEVICE_STATUS_Scanning:
412 case WIMAX_API_DEVICE_STATUS_Connecting:
413 DBG("Connect already pending, waiting for it\n");
414 result = -EINPROGRESS;
416 case WIMAX_API_DEVICE_STATUS_Data_Connected:
417 #if HAVE_IWMXSDK_STATUS_IDLE
418 case WIMAX_API_DEVICE_STATUS_Connection_Idle:
420 connman_error("wmxsdk: BUG? need to disconnect?\n");
427 /* Ok, do the connection, wait for a callback */
428 wmxsdk->connecting_nw = connman_network_ref(nw);
429 sdk_nspname = connman_network_get_blob(nw, "WiMAX.NSP.name",
431 g_assert(sdk_nspname != NULL);
432 r = CmdConnectToNetwork(&wmxsdk->device_id, (void *) sdk_nspname, 0, 0);
433 if (r != WIMAX_API_RET_SUCCESS) {
434 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
435 connman_error("wmxsdk: Cannot connect to network %s: %d (%s)"
436 " - device is in state '%s'\n",
437 station_name, r, errstr,
438 iwmx_sdk_get_device_status_str(wmxsdk));
440 connman_network_unref(nw);
441 wmxsdk->connecting_nw = NULL;
443 result = -EINPROGRESS;
446 g_mutex_unlock(wmxsdk->connect_mutex);
451 * Callback for a Disconnect command
453 * Called by the WiMAX API when a command sent to connect is
454 * completed. This is just a confirmation of what happened with the
457 * When the device changes state, the state change callback is called
458 * and that will fiddle with the connman internals.
460 * We just update the result of the command and wake up anybody who is
461 * waiting for this conditional variable.
463 static void __iwmx_sdk_disconnect_cb(WIMAX_API_DEVICE_ID *device_id,
464 WIMAX_API_NETWORK_CONNECTION_RESP resp)
466 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
467 WIMAX_API_DEVICE_STATUS status;
469 status = iwmx_cm_status_get(wmxsdk);
470 if (resp == WIMAX_API_CONNECTION_SUCCESS) {
471 if (status == WIMAX_API_DEVICE_STATUS_Data_Connected
472 #if HAVE_IWMXSDK_STATUS_IDLE
473 || status == WIMAX_API_DEVICE_STATUS_Connection_Idle
476 connman_error("wmxsdk: error: disconnect worked, "
477 "but state didn't change (now it is "
478 "%d [%s])\n", status,
479 iwmx_sdk_dev_status_to_str(status));
481 connman_error("wmxsdk: failed to disconnect (status %d: %s)\n",
482 status, iwmx_sdk_dev_status_to_str(status));
486 * Disconnect from a network
488 * This function tells the device to disconnect; the state change
489 * callback will take care of inform connman's internals.
491 int iwmx_sdk_disconnect(struct wmxsdk *wmxsdk)
497 UINT32 errstr_size = sizeof(errstr);
498 WIMAX_API_DEVICE_STATUS dev_status;
500 g_mutex_lock(wmxsdk->connect_mutex);
501 /* Guess what the current radio state is; if it is ON
502 * already, don't redo it. */
503 dev_status = iwmx_sdk_get_device_status(wmxsdk);
504 if ((int) dev_status < 0) {
506 goto error_get_status;
508 switch (dev_status) {
509 case WIMAX_API_DEVICE_STATUS_UnInitialized:
510 connman_error("wmxsdk: SW BUG? HW is uninitialized\n");
513 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
514 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
515 case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
516 DBG("Cannot disconnect, radio is off; ignoring\n");
519 case WIMAX_API_DEVICE_STATUS_Ready:
520 case WIMAX_API_DEVICE_STATUS_Scanning:
521 DBG("Cannot disconnect, already disconnected; ignoring\n");
524 case WIMAX_API_DEVICE_STATUS_Connecting:
525 case WIMAX_API_DEVICE_STATUS_Data_Connected:
526 #if HAVE_IWMXSDK_STATUS_IDLE
527 case WIMAX_API_DEVICE_STATUS_Connection_Idle:
533 /* Ok, flip the radio */
534 r = CmdDisconnectFromNetwork(&wmxsdk->device_id);
535 if (r != WIMAX_API_RET_SUCCESS) {
536 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
537 connman_error("wmxsdk: Cannot disconnect from network: "
538 "%d (%s)\n", r, errstr);
541 result = -EINPROGRESS;
544 g_mutex_unlock(wmxsdk->connect_mutex);
549 * Callback for state change messages
551 * Just pass them to the state transition handler
553 static void __iwmx_sdk_state_change_cb(WIMAX_API_DEVICE_ID *device_id,
554 WIMAX_API_DEVICE_STATUS status,
555 WIMAX_API_STATUS_REASON reason,
556 WIMAX_API_CONNECTION_PROGRESS_INFO pi)
558 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
559 iwmx_cm_state_change(wmxsdk, status);
563 * Called by _iwmx_sdk_*scan_cb() when [wide or preferred] scan results
566 * From here we update the connman core idea of which networks are
569 static void __iwmx_sdk_scan_common_cb(WIMAX_API_DEVICE_ID *device_id,
570 WIMAX_API_NSP_INFO_EX *nsp_list,
571 UINT32 nsp_list_size)
573 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
575 char station_name[256];
577 g_static_mutex_lock(&wmxsdk->network_mutex);
578 for (itr = 0; itr < nsp_list_size; itr++) {
580 WIMAX_API_NSP_INFO_EX *nsp_info = &nsp_list[itr];
581 snprintf(station_name, sizeof(station_name),
582 "%s", (char *)nsp_info->NSPName);
583 /* CAPI is reporing link quality as zero -- if it is
584 * zero, check if it is a bug by computing it based on
585 * CINR. If it is different, use the computed one. */
586 strength = nsp_info->linkQuality;
587 if (strength == 0) { /* huh */
589 cinr_to_percentage(nsp_info->CINR - 10);
590 if (linkq_expected != strength)
591 strength = linkq_expected;
594 __iwmx_cm_network_available(
595 wmxsdk, station_name,
596 iwmx_sdk_network_type_name(nsp_info->networkType),
598 strlen((char *) nsp_info->NSPName) + 1,
601 g_static_mutex_unlock(&wmxsdk->network_mutex);
605 * Called by the WiMAX API when we get a wide scan result
607 * We treat them same as wide, so we just call that.
609 static void __iwmx_sdk_wide_scan_cb(WIMAX_API_DEVICE_ID *device_id,
610 WIMAX_API_NSP_INFO_EX *nsp_list,
611 UINT32 nsp_list_size)
613 __iwmx_sdk_scan_common_cb(device_id, nsp_list, nsp_list_size);
617 * Called by the WiMAX API when we get a normal (non wide) scan result
619 * We treat them same as wide, so we just call that.
621 static void __iwmx_sdk_scan_cb(WIMAX_API_DEVICE_ID *device_id,
622 WIMAX_API_NSP_INFO_EX *nsp_list,
623 UINT32 nsp_list_size, UINT32 searchProgress)
625 __iwmx_sdk_scan_common_cb(device_id, nsp_list, nsp_list_size);
629 * Called to ask the device to scan for networks
631 * We don't really scan as the WiMAX SDK daemon scans in the
632 * background for us. We just get the results. See iwmx_sdk_setup().
634 int iwmx_sdk_scan(struct wmxsdk *wmxsdk)
638 UINT32 nsp_list_length = 10;
639 WIMAX_API_NSP_INFO_EX nsp_list[10]; /* FIXME: up to 32? */
643 UINT32 errstr_size = sizeof(errstr);
645 r = GetNetworkListEx(&wmxsdk->device_id, nsp_list, &nsp_list_length);
646 if (r != WIMAX_API_RET_SUCCESS) {
647 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
648 connman_error("wmxsdk: Cannot get network list: %d (%s)\n",
654 if (nsp_list_length == 0)
655 DBG("no networks\n");
657 __iwmx_sdk_scan_common_cb(&wmxsdk->device_id, nsp_list,
665 * Initialize the WiMAX API, register with it, setup callbacks
670 * connman_inet_create_device
674 int iwmx_sdk_setup(struct wmxsdk *wmxsdk)
681 UINT32 errstr_size = sizeof(errstr);
685 /* device_id initialized by iwmx_sdk_dev_add */
687 r = WiMaxDeviceOpen(&wmxsdk->device_id);
688 if (r != WIMAX_API_RET_SUCCESS) {
689 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
690 connman_error("wmxsdk: Cannot open device: %d (%s)\n",
692 goto error_wimaxdeviceopen;
696 * We scan in auto mode (in the background)
698 * Otherwise is messy -- if we have connman triggering a scan
699 * when we call iwmx_cm_scan() -> iwmx_sdk_scan(), most of the
700 * times that causes a race condition when the UI asks for a
701 * scan right before displaying the network menu. As there is
702 * no way to cancel an ongoing scan before connecting, we are
703 * stuck. So we do auto bg and have iwmx_sdk_scan() just return
704 * the current network list.
706 r = SetConnectionMode(&wmxsdk->device_id,
707 WIMAX_API_CONNECTION_AUTO_SCAN_MANUAL_CONNECT);
708 if (r != WIMAX_API_RET_SUCCESS) {
709 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
710 connman_error("wmxsdk: Cannot set connectin mode to manual: "
711 "%d (%s)\n", r, errstr);
712 goto error_connection_mode;
715 r = SubscribeControlPowerManagement(&wmxsdk->device_id,
716 __iwmx_sdk_rf_state_cb);
717 if (r != WIMAX_API_RET_SUCCESS) {
718 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
719 connman_error("wmxsdk: Cannot subscribe to radio change "
720 "events: %u (%s)\n", r, errstr);
722 goto error_subscribe_rf_state;
725 r = SubscribeDeviceStatusChange(&wmxsdk->device_id,
726 __iwmx_sdk_state_change_cb);
727 if (r != WIMAX_API_RET_SUCCESS) {
728 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
729 connman_error("wmxsdk: Cannot subscribe to state chaneg events:"
730 "%d (%s)\n", r, errstr);
731 goto error_subscribe_state_change;
734 r = SubscribeNetworkSearchWideScanEx(&wmxsdk->device_id,
735 __iwmx_sdk_wide_scan_cb);
736 if (r != WIMAX_API_RET_SUCCESS) {
737 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
738 connman_error("wmxsdk: Cannot subscribe to wide scan events: "
739 "%d (%s)\n", r, errstr);
740 goto error_subscribe_wide_scan;
742 r = SubscribeNetworkSearchEx(&wmxsdk->device_id, __iwmx_sdk_scan_cb);
743 if (r != WIMAX_API_RET_SUCCESS) {
744 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
745 connman_error("wmxsdk: Cannot subscribe to scan events: "
746 "%d (%s)\n", r, errstr);
747 goto error_subscribe_scan;
750 r = SubscribeConnectToNetwork(&wmxsdk->device_id,
751 __iwmx_sdk_connect_cb);
752 if (r != WIMAX_API_RET_SUCCESS) {
753 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
754 connman_error("wmxsdk: Cannot subscribe to connect events: "
755 "%d (%s)\n", r, errstr);
756 goto error_subscribe_connect;
759 r = SubscribeDisconnectToNetwork(&wmxsdk->device_id,
760 __iwmx_sdk_disconnect_cb);
761 if (r != WIMAX_API_RET_SUCCESS) {
762 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
763 connman_error("wmxsdk: Cannot subscribe to disconnect events: "
764 "%d (%s)\n", r, errstr);
765 goto error_subscribe_disconnect;
771 UnsubscribeDisconnectToNetwork(&wmxsdk->device_id);
772 error_subscribe_disconnect:
773 UnsubscribeConnectToNetwork(&wmxsdk->device_id);
774 error_subscribe_connect:
775 UnsubscribeNetworkSearchEx(&wmxsdk->device_id);
776 error_subscribe_scan:
777 UnsubscribeNetworkSearchWideScanEx(&wmxsdk->device_id);
778 error_subscribe_wide_scan:
779 UnsubscribeDeviceStatusChange(&wmxsdk->device_id);
780 error_subscribe_state_change:
781 UnsubscribeControlPowerManagement(&wmxsdk->device_id);
782 error_subscribe_rf_state:
783 error_connection_mode:
784 WiMaxDeviceClose(&wmxsdk->device_id);
785 error_wimaxdeviceopen:
790 * Called when a device is removed from connman
792 * Cleanup all that is done in iwmx_sdk_setup(). Remove callbacks,
793 * unregister from the WiMAX API.
795 void iwmx_sdk_remove(struct wmxsdk *wmxsdk)
797 UnsubscribeDisconnectToNetwork(&wmxsdk->device_id);
798 UnsubscribeConnectToNetwork(&wmxsdk->device_id);
799 UnsubscribeNetworkSearchEx(&wmxsdk->device_id);
800 UnsubscribeNetworkSearchWideScanEx(&wmxsdk->device_id);
801 UnsubscribeDeviceStatusChange(&wmxsdk->device_id);
802 UnsubscribeControlPowerManagement(&wmxsdk->device_id);
803 WiMaxDeviceClose(&wmxsdk->device_id);
806 static void iwmx_sdk_dev_add(unsigned idx, unsigned api_idx, const char *name)
809 struct wmxsdk *wmxsdk;
812 if (idx >= IWMX_SDK_DEV_MAX) {
813 connman_error("BUG! idx (%u) >= IWMX_SDK_DEV_MAX (%u)\n",
814 idx, IWMX_SDK_DEV_MAX);
817 wmxsdk = &g_iwmx_sdk_devs[idx];
818 if (wmxsdk->dev != NULL) {
819 connman_error("BUG! device index %u already enumerated?\n",
824 memset(wmxsdk, 0, sizeof(*wmxsdk));
827 * This depends on a hack in the WiMAX Network Service; it has
828 * to return, as part of the device name, a string "if:IFNAME"
829 * where the OS's device name is stored.
831 s = strstr(name, "if:");
833 || sscanf(s, "if:%15[^ \f\n\r\t\v]", wmxsdk->ifname) != 1) {
834 connman_error("Cannot extract network interface name off '%s'",
838 DBG("network interface name: '%s'", wmxsdk->ifname);
840 ifindex = if_nametoindex(wmxsdk->ifname);
843 connman_error("wxmsdk: %s: cannot find interface index\n",
848 wmxsdk->dev = connman_inet_create_device(ifindex);
849 if (wmxsdk->dev == NULL) {
850 connman_error("wmxsdk: %s: failed to create connman_device\n",
854 strncpy(wmxsdk->name, name, sizeof(wmxsdk->name));
855 connman_device_set_data(wmxsdk->dev, wmxsdk);
857 wmxsdk->device_id.privilege = WIMAX_API_PRIVILEGE_READ_WRITE;
858 wmxsdk->device_id.deviceIndex = api_idx;
860 result = connman_device_register(wmxsdk->dev);
862 connman_error("wmxsdk: %s: failed to register: %d\n",
863 wmxsdk->ifname, result);
870 connman_device_unref(wmxsdk->dev);
878 static void iwmx_sdk_dev_rm(unsigned idx)
880 struct wmxsdk *wmxsdk;
882 if (idx >= IWMX_SDK_DEV_MAX) {
883 connman_error("BUG! idx (%u) >= IWMX_SDK_DEV_MAX (%u)\n",
884 idx, IWMX_SDK_DEV_MAX);
887 wmxsdk = &g_iwmx_sdk_devs[idx];
888 if (wmxsdk->dev == NULL) {
889 DBG("device index %u not enumerated? ignoring\n", idx);
893 connman_device_unregister(wmxsdk->dev);
895 connman_device_unref(wmxsdk->dev);
896 memset(wmxsdk, 0, sizeof(*wmxsdk));
901 static void iwmx_sdk_addremove_cb(WIMAX_API_DEVICE_ID *devid,
906 WIMAX_API_HW_DEVICE_ID device_id_list[5];
907 UINT32 device_id_list_size = ARRAY_SIZE(device_id_list);
910 UINT32 errstr_size = sizeof(errstr);
912 DBG("cb: handle %u index #%u is %d\n", devid->sdkHandle,
913 devid->deviceIndex, presence);
915 r = GetListDevice(devid, device_id_list, &device_id_list_size);
916 if (r != WIMAX_API_RET_SUCCESS) {
917 GetErrorString(devid, r, errstr, &errstr_size);
918 connman_error("wmxsdk: Cannot obtain list "
919 "of devices: %d (%s)\n", r, errstr);
923 if (device_id_list_size == 0)
924 DBG("No WiMAX devices reported\n");
926 for (cnt = 0; cnt < device_id_list_size; cnt++) {
927 WIMAX_API_HW_DEVICE_ID *dev =
928 device_id_list + cnt;
929 DBG("#%u index #%u device %s\n",
930 cnt, dev->deviceIndex, dev->deviceName);
932 if (device_id_list_size < devid->deviceIndex) {
933 connman_error("wmxsdk: changed device (%u) not in the list? "
935 devid->deviceIndex, device_id_list_size);
940 WIMAX_API_HW_DEVICE_ID *dev =
941 device_id_list + devid->deviceIndex;
942 iwmx_sdk_dev_add(devid->deviceIndex, dev->deviceIndex,
945 iwmx_sdk_dev_rm(devid->deviceIndex);
950 * Initialize the WiMAX API, register with it, setup callbacks for
951 * device coming up / dissapearing
953 int iwmx_sdk_api_init(void)
959 UINT32 errstr_size = sizeof(errstr);
961 WIMAX_API_HW_DEVICE_ID device_id_list[5];
962 UINT32 device_id_list_size = ARRAY_SIZE(device_id_list);
964 memset(&g_api, 0, sizeof(g_api));
965 g_api.privilege = WIMAX_API_PRIVILEGE_READ_WRITE;
968 r = WiMaxAPIOpen(&g_api);
969 if (r != WIMAX_API_RET_SUCCESS) {
970 GetErrorString(&g_api, r, errstr, &errstr_size);
971 connman_error("wmxsdk: WiMaxAPIOpen failed with %d (%s)\n",
973 goto error_wimaxapiopen;
976 r = SubscribeDeviceInsertRemove(&g_api, iwmx_sdk_addremove_cb);
977 if (r != WIMAX_API_RET_SUCCESS) {
978 GetErrorString(&g_api, r, errstr, &errstr_size);
979 connman_error("wmxsdk: insert/remove subscribe failed with "
980 "%d (%s)\n", r, errstr);
984 r = GetListDevice(&g_api, device_id_list, &device_id_list_size);
985 if (r != WIMAX_API_RET_SUCCESS) {
986 GetErrorString(&g_api, r, errstr, &errstr_size);
987 connman_error("wmxsdk: Cannot obtain list "
988 "of devices: %d (%s)\n", r, errstr);
991 if (device_id_list_size < g_api.deviceIndex) {
992 connman_error("wmxsdk: changed device (%u) not in the list? "
994 g_api.deviceIndex, device_id_list_size);
997 if (device_id_list_size == 0)
998 DBG("No WiMAX devices reported\n");
1000 for (cnt = 0; cnt < device_id_list_size; cnt++) {
1001 WIMAX_API_HW_DEVICE_ID *dev =
1002 device_id_list + cnt;
1003 DBG("#%u index #%u device %s\n",
1004 cnt, dev->deviceIndex, dev->deviceName);
1005 iwmx_sdk_dev_add(cnt, dev->deviceIndex,
1011 WiMaxAPIClose(&g_api);
1016 void iwmx_sdk_api_exit(void)
1021 UINT32 errstr_size = sizeof(errstr);
1023 r = WiMaxAPIClose(&g_api);
1024 if (r != WIMAX_API_RET_SUCCESS) {
1025 GetErrorString(&g_api, r, errstr, &errstr_size);
1026 connman_error("wmxsdk: WiMaxAPIClose failed with %d (%s)\n",