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>
39 #include <WiMaxAPIEx.h>
43 /* Yes, this is dirty; see above on IWMX_SDK_DEV_MAX*/
44 static struct wmxsdk g_iwmx_sdk_devs[IWMX_SDK_DEV_MAX];
46 static struct wmxsdk *deviceid_to_wmxsdk(struct WIMAX_API_DEVICE_ID *device_id)
48 return container_of(device_id, struct wmxsdk, device_id);
51 static struct WIMAX_API_DEVICE_ID g_api;
55 * FIXME: pulled it it out of some hole
57 * the cinr to percentage computation comes from the L3/L4 doc
59 * But some other places (L4 code) have a more complex, seemingly
60 * logarithmical computation.
65 static int cinr_to_percentage(int cinr)
72 else /* Calc percentage on the value from -5 to 25 */
73 strength = ((100UL * (cinr - -5)) / (25 - -5));
78 * Convert a WiMAX API status to an string.
80 const char *iwmx_sdk_dev_status_to_str(WIMAX_API_DEVICE_STATUS status)
83 case WIMAX_API_DEVICE_STATUS_UnInitialized:
84 return "Uninitialized";
86 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
87 return "Device RF Off(both H/W and S/W)";
89 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
90 return "Device RF Off(via H/W switch)";
91 case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
92 return "Device RF Off(via S/W switch)";
93 case WIMAX_API_DEVICE_STATUS_Ready:
94 return "Device is ready";
95 case WIMAX_API_DEVICE_STATUS_Scanning:
96 return "Device is scanning";
97 case WIMAX_API_DEVICE_STATUS_Connecting:
98 return "Connection in progress";
99 case WIMAX_API_DEVICE_STATUS_Data_Connected:
100 return "Layer 2 connected";
101 case WIMAX_API_DEVICE_STATUS_Connection_Idle:
102 return "Idle connection";
104 return "unknown state";
109 * Get the device's status from the device
111 * Does NOT cache the result
112 * Does NOT trigger a state change in connman
114 * Returns < 0 errno code on error, status code if ok.
116 WIMAX_API_DEVICE_STATUS iwmx_sdk_get_device_status(struct wmxsdk *wmxsdk)
120 UINT32 errstr_size = sizeof(errstr);
122 WIMAX_API_DEVICE_STATUS dev_status;
123 WIMAX_API_CONNECTION_PROGRESS_INFO pi;
125 r = GetDeviceStatus(&wmxsdk->device_id, &dev_status, &pi);
126 if (r != WIMAX_API_RET_SUCCESS) {
127 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
128 connman_error("wmxsdk: Cannot read device state: %d (%s)\n",
136 * Get the device's status from the device but return a string describing it
138 * Same conditions as iwmx_sdk_get_device_status().
140 static const char *iwmx_sdk_get_device_status_str(struct wmxsdk *wmxsdk)
143 WIMAX_API_DEVICE_STATUS dev_status;
145 dev_status = iwmx_sdk_get_device_status(wmxsdk);
146 if ((int) dev_status < 0)
147 result = "cannot read device state";
149 result = iwmx_sdk_dev_status_to_str(dev_status);
154 * Translate a WiMAX network type to a readable name.
156 static const char *iwmx_sdk_network_type_name(enum _WIMAX_API_NETWORK_TYPE network_type)
158 static char *network_type_name[] = {
159 [WIMAX_API_HOME] = "",
160 [WIMAX_API_PARTNER] = " (partner network)",
161 [WIMAX_API_ROAMING_PARTNER] = " (roaming partner network)",
162 [WIMAX_API_UNKNOWN] = " (unknown network)",
164 if (network_type > WIMAX_API_UNKNOWN)
165 return "(BUG! UNKNOWN NETWORK_TYPE MODE)";
167 return network_type_name[network_type];
171 * If the device is connected but we don't know about the network,
172 * create the knowledge of it.
174 * Asks the WiMAX API to report which NSP we are connected to and we
175 * create/update a network_el in the device's network list. Then
178 * Returns NULL on error.
180 * NOTE: wmxsdk->network_mutex has to be taken
182 struct connman_network *__iwmx_sdk_get_connected_network(struct wmxsdk *wmxsdk)
184 struct connman_network *nw;
186 struct WIMAX_API_CONNECTED_NSP_INFO nsp_info;
189 UINT32 errstr_size = sizeof(errstr);
191 /* The device is getting connected due to an external (to
192 * connman) event; find which is the nw we are getting
193 * connected to. if we don't have it, add it */
194 r = GetConnectedNSP(&wmxsdk->device_id, &nsp_info);
195 if (r != WIMAX_API_RET_SUCCESS) {
196 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
198 "wmxsdk: Cannot get connected NSP info: %d (%s)\n",
200 strcpy((char *) nsp_info.NSPName, "unknown");
201 nw = iwmx_cm_network_available(
203 iwmx_sdk_network_type_name(WIMAX_API_UNKNOWN),
204 nsp_info.NSPName, strlen((char *) nsp_info.NSPName) + 1,
205 cinr_to_percentage(nsp_info.CINR - 10));
207 nw = iwmx_cm_network_available(
208 wmxsdk, (char *) nsp_info.NSPName,
209 iwmx_sdk_network_type_name(nsp_info.networkType),
210 nsp_info.NSPName, strlen((char *) nsp_info.NSPName) + 1,
211 cinr_to_percentage(nsp_info.CINR - 10));
217 * Callback for a RF State command
219 * Called by the WiMAX API when a command sent to change the RF state
220 * is completed. This is just a confirmation of what happened with the
223 * We don't do anything, as when the device changes state, the state
224 * change callback is called and that will fiddle with the connman
227 static void __iwmx_sdk_rf_state_cb(struct WIMAX_API_DEVICE_ID *device_id,
228 WIMAX_API_RF_STATE rf_state)
230 DBG("rf_state changed to %d\n", rf_state);
234 * Turn the radio on or off
236 * First it checks that we are in the right state before doing
237 * anything; there might be no need to do anything.
239 * Issue a command to the WiMAX API, wait for a callback confirming it
240 * is done. Sometimes the callback is missed -- in that case, do force
241 * a state change evaluation.
245 * Geezoos efing Xist, they make difficult even the most simple
248 * This thing is definitely a pain. If the radio is ON already
249 * and you switch it on again...well, there is no way to tell
250 * because you don't get a callback saying it basically
251 * suceeded. But on the other hand, if the thing was in a
252 * different state and action needs to be taken, you have to wait
253 * for a callback to confirm it's done. However, there is also an
254 * state change callback, which is almost the same, so now you
255 * have to handle things in two "unrelated" threads of execution.
257 * How the shpx are you expected to tell the difference? Check
258 * status first? On timeout? Nice gap (eighteen wheeler size) for
261 int iwmx_sdk_rf_state_set(struct wmxsdk *wmxsdk, WIMAX_API_RF_STATE rf_state)
267 UINT32 errstr_size = sizeof(errstr);
268 WIMAX_API_DEVICE_STATUS dev_status;
270 g_assert(rf_state == WIMAX_API_RF_ON || rf_state == WIMAX_API_RF_OFF);
272 /* Guess what the current radio state is; if it is ON
273 * already, don't redo it. */
274 dev_status = iwmx_sdk_get_device_status(wmxsdk);
275 if ((int) dev_status < 0) {
277 goto error_get_status;
279 switch (dev_status) {
280 case WIMAX_API_DEVICE_STATUS_UnInitialized:
283 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
284 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
286 "wmxsdk: cannot turn on radio: hw switch is off\n");
290 case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
291 if (rf_state == WIMAX_API_RF_OFF) {
293 DBG("radio is already off\n");
297 case WIMAX_API_DEVICE_STATUS_Ready:
298 case WIMAX_API_DEVICE_STATUS_Scanning:
299 case WIMAX_API_DEVICE_STATUS_Connecting:
300 case WIMAX_API_DEVICE_STATUS_Data_Connected:
301 case WIMAX_API_DEVICE_STATUS_Connection_Idle:
302 if (rf_state == WIMAX_API_RF_ON) {
304 DBG("radio is already on\n");
311 /* Ok, flip the radio */
312 r = CmdControlPowerManagement(&wmxsdk->device_id, rf_state);
313 if (r != WIMAX_API_RET_SUCCESS) {
314 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
315 connman_error("wmxsdk: Cannot flip radio to %d: %d (%s) "
316 "[device is in state %s]\n",
318 iwmx_sdk_get_device_status_str(wmxsdk));
321 result = -EINPROGRESS;
329 * Callback for a Connect command
331 * Called by the WiMAX API when a command sent to connect is
332 * completed. This is just a confirmation of what happened with the
335 * WE DON'T DO MUCH HERE -- the real meat happens when a state change
336 * callback is sent, where we detect we move to connected state (or
337 * from disconnecting to something else); the state change callback is
338 * called and that will fiddle with the connman internals.
340 static void __iwmx_sdk_connect_cb(struct WIMAX_API_DEVICE_ID *device_id,
341 WIMAX_API_NETWORK_CONNECTION_RESP resp)
343 WIMAX_API_DEVICE_STATUS status;
344 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
346 status = iwmx_cm_status_get(wmxsdk);
347 if (resp == WIMAX_API_CONNECTION_SUCCESS) {
348 if (status != WIMAX_API_DEVICE_STATUS_Data_Connected
349 && status != WIMAX_API_DEVICE_STATUS_Connection_Idle)
350 connman_error("wmxsdk: error: connect worked, but state"
351 " didn't change (now it is %d [%s])\n",
353 iwmx_sdk_dev_status_to_str(status));
355 connman_error("wmxsdk: failed to connect (status %d: %s)\n",
356 status, iwmx_sdk_dev_status_to_str(status));
360 * Connect to a network
362 * This function starts the connection process to a given network;
363 * when the device changes status, the status change callback will
364 * tell connman if the network is finally connected or not.
366 * One of the reasons it is done like that is to allow external tools
367 * to control the device and the plugin just passing the status so
368 * connman displays the right info.
370 int iwmx_sdk_connect(struct wmxsdk *wmxsdk, struct connman_network *nw)
376 UINT32 errstr_size = sizeof(errstr);
377 WIMAX_API_DEVICE_STATUS dev_status;
378 const char *station_name = connman_network_get_identifier(nw);
379 const void *sdk_nspname;
380 unsigned int sdk_nspname_size;
382 g_mutex_lock(wmxsdk->connect_mutex);
383 /* Guess what the current radio state is; if it is ON
384 * already, don't redo it. */
385 dev_status = iwmx_cm_status_get(wmxsdk);
386 if ((int) dev_status < 0) {
388 goto error_get_status;
390 switch (dev_status) {
391 case WIMAX_API_DEVICE_STATUS_UnInitialized:
392 connman_error("wmxsdk: SW BUG? HW is uninitialized\n");
395 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
396 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
397 case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
398 connman_error("wmxsdk: Cannot connect: radio is off\n");
401 case WIMAX_API_DEVICE_STATUS_Ready:
402 case WIMAX_API_DEVICE_STATUS_Scanning:
404 case WIMAX_API_DEVICE_STATUS_Connecting:
405 DBG("Connect already pending, waiting for it\n");
406 result = -EINPROGRESS;
408 case WIMAX_API_DEVICE_STATUS_Data_Connected:
409 case WIMAX_API_DEVICE_STATUS_Connection_Idle:
410 connman_error("wmxsdk: BUG? need to disconnect?\n");
417 /* Ok, do the connection, wait for a callback */
418 wmxsdk->connecting_nw = connman_network_ref(nw);
419 sdk_nspname = connman_network_get_blob(nw, "WiMAX.NSP.name",
421 g_assert(sdk_nspname != NULL);
422 r = CmdConnectToNetwork(&wmxsdk->device_id, (void *) sdk_nspname, 0, 0);
423 if (r != WIMAX_API_RET_SUCCESS) {
424 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
425 connman_error("wmxsdk: Cannot connect to network %s: %d (%s)"
426 " - device is in state '%s'\n",
427 station_name, r, errstr,
428 iwmx_sdk_get_device_status_str(wmxsdk));
430 connman_network_unref(nw);
431 wmxsdk->connecting_nw = NULL;
433 result = -EINPROGRESS;
436 g_mutex_unlock(wmxsdk->connect_mutex);
441 * Callback for a Disconnect command
443 * Called by the WiMAX API when a command sent to connect is
444 * completed. This is just a confirmation of what happened with the
447 * When the device changes state, the state change callback is called
448 * and that will fiddle with the connman internals.
450 * We just update the result of the command and wake up anybody who is
451 * waiting for this conditional variable.
453 static void __iwmx_sdk_disconnect_cb(struct WIMAX_API_DEVICE_ID *device_id,
454 WIMAX_API_NETWORK_CONNECTION_RESP resp)
456 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
457 WIMAX_API_DEVICE_STATUS status;
459 status = iwmx_cm_status_get(wmxsdk);
460 if (resp == WIMAX_API_CONNECTION_SUCCESS) {
461 if (status == WIMAX_API_DEVICE_STATUS_Data_Connected
462 || status == WIMAX_API_DEVICE_STATUS_Connection_Idle)
463 connman_error("wmxsdk: error: disconnect worked, "
464 "but state didn't change (now it is "
465 "%d [%s])\n", status,
466 iwmx_sdk_dev_status_to_str(status));
468 connman_error("wmxsdk: failed to disconnect (status %d: %s)\n",
469 status, iwmx_sdk_dev_status_to_str(status));
473 * Disconnect from a network
475 * This function tells the device to disconnect; the state change
476 * callback will take care of inform connman's internals.
478 int iwmx_sdk_disconnect(struct wmxsdk *wmxsdk)
484 UINT32 errstr_size = sizeof(errstr);
485 WIMAX_API_DEVICE_STATUS dev_status;
487 g_mutex_lock(wmxsdk->connect_mutex);
488 /* Guess what the current radio state is; if it is ON
489 * already, don't redo it. */
490 dev_status = iwmx_sdk_get_device_status(wmxsdk);
491 if ((int) dev_status < 0) {
493 goto error_get_status;
495 switch (dev_status) {
496 case WIMAX_API_DEVICE_STATUS_UnInitialized:
497 connman_error("wmxsdk: SW BUG? HW is uninitialized\n");
500 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
501 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
502 case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
503 DBG("Cannot disconnect, radio is off; ignoring\n");
506 case WIMAX_API_DEVICE_STATUS_Ready:
507 case WIMAX_API_DEVICE_STATUS_Scanning:
508 DBG("Cannot disconnect, already disconnected; ignoring\n");
511 case WIMAX_API_DEVICE_STATUS_Connecting:
512 case WIMAX_API_DEVICE_STATUS_Data_Connected:
513 case WIMAX_API_DEVICE_STATUS_Connection_Idle:
518 /* Ok, flip the radio */
519 r = CmdDisconnectFromNetwork(&wmxsdk->device_id);
520 if (r != WIMAX_API_RET_SUCCESS) {
521 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
522 connman_error("wmxsdk: Cannot disconnect from network: "
523 "%d (%s)\n", r, errstr);
526 result = -EINPROGRESS;
529 g_mutex_unlock(wmxsdk->connect_mutex);
534 * Callback for state change messages
536 * Just pass them to the state transition handler
538 static void __iwmx_sdk_state_change_cb(struct WIMAX_API_DEVICE_ID *device_id,
539 WIMAX_API_DEVICE_STATUS status,
540 WIMAX_API_STATUS_REASON reason,
541 WIMAX_API_CONNECTION_PROGRESS_INFO pi)
543 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
544 iwmx_cm_state_change(wmxsdk, status);
548 * Called by _iwmx_sdk_*scan_cb() when [wide or preferred] scan results
551 * From here we update the connman core idea of which networks are
554 static void __iwmx_sdk_scan_common_cb(struct WIMAX_API_DEVICE_ID *device_id,
555 struct WIMAX_API_NSP_INFO_EX *nsp_list,
556 UINT32 nsp_list_size)
558 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
560 char station_name[256];
562 g_static_mutex_lock(&wmxsdk->network_mutex);
563 for (itr = 0; itr < nsp_list_size; itr++) {
565 struct WIMAX_API_NSP_INFO_EX *nsp_info = &nsp_list[itr];
566 snprintf(station_name, sizeof(station_name),
567 "%s", (char *)nsp_info->NSPName);
568 /* CAPI is reporing link quality as zero -- if it is
569 * zero, check if it is a bug by computing it based on
570 * CINR. If it is different, use the computed one. */
571 strength = nsp_info->linkQuality;
572 if (strength == 0) { /* huh */
574 cinr_to_percentage(nsp_info->CINR - 10);
575 if (linkq_expected != strength)
576 strength = linkq_expected;
579 __iwmx_cm_network_available(
580 wmxsdk, station_name,
581 iwmx_sdk_network_type_name(nsp_info->networkType),
583 strlen((char *) nsp_info->NSPName) + 1,
586 g_static_mutex_unlock(&wmxsdk->network_mutex);
590 * Called by the WiMAX API when we get a wide scan result
592 * We treat them same as wide, so we just call that.
594 static void __iwmx_sdk_wide_scan_cb(struct WIMAX_API_DEVICE_ID *device_id,
595 struct WIMAX_API_NSP_INFO_EX *nsp_list,
596 UINT32 nsp_list_size)
598 __iwmx_sdk_scan_common_cb(device_id, nsp_list, nsp_list_size);
602 * Called by the WiMAX API when we get a normal (non wide) scan result
604 * We treat them same as wide, so we just call that.
606 static void __iwmx_sdk_scan_cb(struct WIMAX_API_DEVICE_ID *device_id,
607 struct WIMAX_API_NSP_INFO_EX *nsp_list,
608 UINT32 nsp_list_size, UINT32 searchProgress)
610 __iwmx_sdk_scan_common_cb(device_id, nsp_list, nsp_list_size);
614 * Called to ask the device to scan for networks
616 * We don't really scan as the WiMAX SDK daemon scans in the
617 * background for us. We just get the results. See iwmx_sdk_setup().
619 int iwmx_sdk_scan(struct wmxsdk *wmxsdk)
623 UINT32 nsp_list_length = 10;
624 struct WIMAX_API_NSP_INFO_EX nsp_list[10]; /* FIXME: up to 32? */
628 UINT32 errstr_size = sizeof(errstr);
630 r = GetNetworkListEx(&wmxsdk->device_id, nsp_list, &nsp_list_length);
631 if (r != WIMAX_API_RET_SUCCESS) {
632 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
633 connman_error("wmxsdk: Cannot get network list: %d (%s)\n",
639 if (nsp_list_length == 0)
640 DBG("no networks\n");
642 __iwmx_sdk_scan_common_cb(&wmxsdk->device_id, nsp_list,
650 * Initialize the WiMAX API, register with it, setup callbacks
655 * connman_inet_create_device
659 int iwmx_sdk_setup(struct wmxsdk *wmxsdk)
666 UINT32 errstr_size = sizeof(errstr);
670 /* device_id initialized by iwmx_sdk_dev_add */
672 r = WiMaxDeviceOpen(&wmxsdk->device_id);
673 if (r != WIMAX_API_RET_SUCCESS) {
674 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
675 connman_error("wmxsdk: Cannot open device: %d (%s)\n",
677 goto error_wimaxdeviceopen;
681 * We scan in auto mode (in the background)
683 * Otherwise is messy -- if we have connman triggering a scan
684 * when we call iwmx_cm_scan() -> iwmx_sdk_scan(), most of the
685 * times that causes a race condition when the UI asks for a
686 * scan right before displaying the network menu. As there is
687 * no way to cancel an ongoing scan before connecting, we are
688 * stuck. So we do auto bg and have iwmx_sdk_scan() just return
689 * the current network list.
691 r = SetConnectionMode(&wmxsdk->device_id,
692 WIMAX_API_CONNECTION_AUTO_SCAN_MANUAL_CONNECT);
693 if (r != WIMAX_API_RET_SUCCESS) {
694 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
695 connman_error("wmxsdk: Cannot set connectin mode to manual: "
696 "%d (%s)\n", r, errstr);
697 goto error_connection_mode;
700 r = SubscribeControlPowerManagement(&wmxsdk->device_id,
701 __iwmx_sdk_rf_state_cb);
702 if (r != WIMAX_API_RET_SUCCESS) {
703 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
704 connman_error("wmxsdk: Cannot subscribe to radio change "
705 "events: %u (%s)\n", r, errstr);
707 goto error_subscribe_rf_state;
710 r = SubscribeDeviceStatusChange(&wmxsdk->device_id,
711 __iwmx_sdk_state_change_cb);
712 if (r != WIMAX_API_RET_SUCCESS) {
713 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
714 connman_error("wmxsdk: Cannot subscribe to state chaneg events:"
715 "%d (%s)\n", r, errstr);
716 goto error_subscribe_state_change;
719 r = SubscribeNetworkSearchWideScanEx(&wmxsdk->device_id,
720 __iwmx_sdk_wide_scan_cb);
721 if (r != WIMAX_API_RET_SUCCESS) {
722 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
723 connman_error("wmxsdk: Cannot subscribe to wide scan events: "
724 "%d (%s)\n", r, errstr);
725 goto error_subscribe_wide_scan;
727 r = SubscribeNetworkSearchEx(&wmxsdk->device_id, __iwmx_sdk_scan_cb);
728 if (r != WIMAX_API_RET_SUCCESS) {
729 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
730 connman_error("wmxsdk: Cannot subscribe to scan events: "
731 "%d (%s)\n", r, errstr);
732 goto error_subscribe_scan;
735 r = SubscribeConnectToNetwork(&wmxsdk->device_id,
736 __iwmx_sdk_connect_cb);
737 if (r != WIMAX_API_RET_SUCCESS) {
738 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
739 connman_error("wmxsdk: Cannot subscribe to connect events: "
740 "%d (%s)\n", r, errstr);
741 goto error_subscribe_connect;
744 r = SubscribeDisconnectToNetwork(&wmxsdk->device_id,
745 __iwmx_sdk_disconnect_cb);
746 if (r != WIMAX_API_RET_SUCCESS) {
747 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
748 connman_error("wmxsdk: Cannot subscribe to disconnect events: "
749 "%d (%s)\n", r, errstr);
750 goto error_subscribe_disconnect;
756 UnsubscribeDisconnectToNetwork(&wmxsdk->device_id);
757 error_subscribe_disconnect:
758 UnsubscribeConnectToNetwork(&wmxsdk->device_id);
759 error_subscribe_connect:
760 UnsubscribeNetworkSearchEx(&wmxsdk->device_id);
761 error_subscribe_scan:
762 UnsubscribeNetworkSearchWideScanEx(&wmxsdk->device_id);
763 error_subscribe_wide_scan:
764 UnsubscribeDeviceStatusChange(&wmxsdk->device_id);
765 error_subscribe_state_change:
766 UnsubscribeControlPowerManagement(&wmxsdk->device_id);
767 error_subscribe_rf_state:
768 error_connection_mode:
769 WiMaxDeviceClose(&wmxsdk->device_id);
770 error_wimaxdeviceopen:
775 * Called when a device is removed from connman
777 * Cleanup all that is done in iwmx_sdk_setup(). Remove callbacks,
778 * unregister from the WiMAX API.
780 void iwmx_sdk_remove(struct wmxsdk *wmxsdk)
782 UnsubscribeDisconnectToNetwork(&wmxsdk->device_id);
783 UnsubscribeConnectToNetwork(&wmxsdk->device_id);
784 UnsubscribeNetworkSearchEx(&wmxsdk->device_id);
785 UnsubscribeNetworkSearchWideScanEx(&wmxsdk->device_id);
786 UnsubscribeDeviceStatusChange(&wmxsdk->device_id);
787 UnsubscribeControlPowerManagement(&wmxsdk->device_id);
788 WiMaxDeviceClose(&wmxsdk->device_id);
791 static void iwmx_sdk_dev_add(unsigned idx, unsigned api_idx, const char *name)
794 struct wmxsdk *wmxsdk;
797 if (idx >= IWMX_SDK_DEV_MAX) {
798 connman_error("BUG! idx (%u) >= IWMX_SDK_DEV_MAX (%u)\n",
799 idx, IWMX_SDK_DEV_MAX);
802 wmxsdk = &g_iwmx_sdk_devs[idx];
803 if (wmxsdk->dev != NULL) {
804 connman_error("BUG! device index %u already enumerated?\n",
809 memset(wmxsdk, 0, sizeof(*wmxsdk));
812 * This depends on a hack in the WiMAX Network Service; it has
813 * to return, as part of the device name, a string "if:IFNAME"
814 * where the OS's device name is stored.
816 s = strstr(name, "if:");
818 || sscanf(s, "if:%15[^ \f\n\r\t\v]", wmxsdk->ifname) != 1) {
819 connman_error("Cannot extract network interface name off '%s'",
823 DBG("network interface name: '%s'", wmxsdk->ifname);
825 ifindex = if_nametoindex(wmxsdk->ifname);
828 connman_error("wxmsdk: %s: cannot find interface index\n",
833 wmxsdk->dev = connman_inet_create_device(ifindex);
834 if (wmxsdk->dev == NULL) {
835 connman_error("wmxsdk: %s: failed to create connman_device\n",
839 strncpy(wmxsdk->name, name, sizeof(wmxsdk->name));
840 connman_device_set_data(wmxsdk->dev, wmxsdk);
842 wmxsdk->device_id.privilege = WIMAX_API_PRIVILEGE_READ_WRITE;
843 wmxsdk->device_id.deviceIndex = api_idx;
845 result = connman_device_register(wmxsdk->dev);
847 connman_error("wmxsdk: %s: failed to register: %d\n",
848 wmxsdk->ifname, result);
855 connman_device_unref(wmxsdk->dev);
863 static void iwmx_sdk_dev_rm(unsigned idx)
865 struct wmxsdk *wmxsdk;
867 if (idx >= IWMX_SDK_DEV_MAX) {
868 connman_error("BUG! idx (%u) >= IWMX_SDK_DEV_MAX (%u)\n",
869 idx, IWMX_SDK_DEV_MAX);
872 wmxsdk = &g_iwmx_sdk_devs[idx];
873 if (wmxsdk->dev == NULL) {
874 DBG("device index %u not enumerated? ignoring\n", idx);
878 connman_device_unregister(wmxsdk->dev);
880 connman_device_unref(wmxsdk->dev);
881 memset(wmxsdk, 0, sizeof(*wmxsdk));
886 static void iwmx_sdk_addremove_cb(struct WIMAX_API_DEVICE_ID *devid,
891 struct WIMAX_API_HW_DEVICE_ID device_id_list[5];
892 UINT32 device_id_list_size = ARRAY_SIZE(device_id_list);
895 UINT32 errstr_size = sizeof(errstr);
897 DBG("cb: handle %u index #%u is %d\n", devid->sdkHandle,
898 devid->deviceIndex, presence);
900 r = GetListDevice(devid, device_id_list, &device_id_list_size);
901 if (r != WIMAX_API_RET_SUCCESS) {
902 GetErrorString(devid, r, errstr, &errstr_size);
903 connman_error("wmxsdk: Cannot obtain list "
904 "of devices: %d (%s)\n", r, errstr);
908 if (device_id_list_size == 0)
909 DBG("No WiMAX devices reported\n");
911 for (cnt = 0; cnt < device_id_list_size; cnt++) {
912 struct WIMAX_API_HW_DEVICE_ID *dev =
913 device_id_list + cnt;
914 DBG("#%u index #%u device %s\n",
915 cnt, dev->deviceIndex, dev->deviceName);
917 if (device_id_list_size < devid->deviceIndex) {
918 connman_error("wmxsdk: changed device (%u) not in the list? "
920 devid->deviceIndex, device_id_list_size);
925 struct WIMAX_API_HW_DEVICE_ID *dev =
926 device_id_list + devid->deviceIndex;
927 iwmx_sdk_dev_add(devid->deviceIndex, dev->deviceIndex,
930 iwmx_sdk_dev_rm(devid->deviceIndex);
935 * Initialize the WiMAX API, register with it, setup callbacks for
936 * device coming up / dissapearing
938 int iwmx_sdk_api_init(void)
944 UINT32 errstr_size = sizeof(errstr);
946 struct WIMAX_API_HW_DEVICE_ID device_id_list[5];
947 UINT32 device_id_list_size = ARRAY_SIZE(device_id_list);
949 memset(&g_api, 0, sizeof(g_api));
950 g_api.privilege = WIMAX_API_PRIVILEGE_READ_WRITE;
953 r = WiMaxAPIOpen(&g_api);
954 if (r != WIMAX_API_RET_SUCCESS) {
955 GetErrorString(&g_api, r, errstr, &errstr_size);
956 connman_error("wmxsdk: WiMaxAPIOpen failed with %d (%s)\n",
958 goto error_wimaxapiopen;
961 r = SubscribeDeviceInsertRemove(&g_api, iwmx_sdk_addremove_cb);
962 if (r != WIMAX_API_RET_SUCCESS) {
963 GetErrorString(&g_api, r, errstr, &errstr_size);
964 connman_error("wmxsdk: insert/remove subscribe failed with "
965 "%d (%s)\n", r, errstr);
969 r = GetListDevice(&g_api, device_id_list, &device_id_list_size);
970 if (r != WIMAX_API_RET_SUCCESS) {
971 GetErrorString(&g_api, r, errstr, &errstr_size);
972 connman_error("wmxsdk: Cannot obtain list "
973 "of devices: %d (%s)\n", r, errstr);
976 if (device_id_list_size < g_api.deviceIndex) {
977 connman_error("wmxsdk: changed device (%u) not in the list? "
979 g_api.deviceIndex, device_id_list_size);
982 if (device_id_list_size == 0)
983 DBG("No WiMAX devices reported\n");
985 for (cnt = 0; cnt < device_id_list_size; cnt++) {
986 struct WIMAX_API_HW_DEVICE_ID *dev =
987 device_id_list + cnt;
988 DBG("#%u index #%u device %s\n",
989 cnt, dev->deviceIndex, dev->deviceName);
990 iwmx_sdk_dev_add(cnt, dev->deviceIndex,
996 WiMaxAPIClose(&g_api);
1001 void iwmx_sdk_api_exit(void)
1006 UINT32 errstr_size = sizeof(errstr);
1008 r = WiMaxAPIClose(&g_api);
1009 if (r != WIMAX_API_RET_SUCCESS) {
1010 GetErrorString(&g_api, r, errstr, &errstr_size);
1011 connman_error("wmxsdk: WiMaxAPIClose failed with %d (%s)\n",