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
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)
50 return container_of(device_id, struct wmxsdk, device_id);
53 static WIMAX_API_DEVICE_ID g_api;
57 * FIXME: pulled it it out of some hole
59 * the cinr to percentage computation comes from the L3/L4 doc
61 * But some other places (L4 code) have a more complex, seemingly
62 * logarithmical computation.
67 static int cinr_to_percentage(int cinr)
74 else /* Calc percentage on the value from -5 to 25 */
75 strength = ((100UL * (cinr - -5)) / (25 - -5));
80 * Convert a WiMAX API status to an string.
82 const char *iwmx_sdk_dev_status_to_str(WIMAX_API_DEVICE_STATUS status)
85 case WIMAX_API_DEVICE_STATUS_UnInitialized:
86 return "Uninitialized";
88 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
89 return "Device RF Off(both H/W and S/W)";
91 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
92 return "Device RF Off(via H/W switch)";
93 case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
94 return "Device RF Off(via S/W switch)";
95 case WIMAX_API_DEVICE_STATUS_Ready:
96 return "Device is ready";
97 case WIMAX_API_DEVICE_STATUS_Scanning:
98 return "Device is scanning";
99 case WIMAX_API_DEVICE_STATUS_Connecting:
100 return "Connection in progress";
101 case WIMAX_API_DEVICE_STATUS_Data_Connected:
102 return "Layer 2 connected";
103 #if HAVE_IWMXSDK_STATUS_IDLE
104 case WIMAX_API_DEVICE_STATUS_Connection_Idle:
105 return "Idle connection";
106 #endif /* #if HAVE_IWMXSDK_STATUS_IDLE */
108 return "unknown state";
113 * Get the device's status from the device
115 * Does NOT cache the result
116 * Does NOT trigger a state change in connman
118 * Returns < 0 errno code on error, status code if ok.
120 WIMAX_API_DEVICE_STATUS iwmx_sdk_get_device_status(struct wmxsdk *wmxsdk)
124 UINT32 errstr_size = sizeof(errstr);
126 WIMAX_API_DEVICE_STATUS dev_status;
127 WIMAX_API_CONNECTION_PROGRESS_INFO pi;
129 r = GetDeviceStatus(&wmxsdk->device_id, &dev_status, &pi);
130 if (r != WIMAX_API_RET_SUCCESS) {
131 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
132 connman_error("wmxsdk: Cannot read device state: %d (%s)\n",
140 * Get the device's status from the device but return a string describing it
142 * Same conditions as iwmx_sdk_get_device_status().
144 static const char *iwmx_sdk_get_device_status_str(struct wmxsdk *wmxsdk)
147 WIMAX_API_DEVICE_STATUS dev_status;
149 dev_status = iwmx_sdk_get_device_status(wmxsdk);
150 if ((int) dev_status < 0)
151 result = "cannot read device state";
153 result = iwmx_sdk_dev_status_to_str(dev_status);
158 * Translate a WiMAX network type to a readable name.
160 static const char *iwmx_sdk_network_type_name(enum _WIMAX_API_NETWORK_TYPE network_type)
162 static char *network_type_name[] = {
163 [WIMAX_API_HOME] = "",
164 [WIMAX_API_PARTNER] = " (partner network)",
165 [WIMAX_API_ROAMING_PARTNER] = " (roaming partner network)",
166 [WIMAX_API_UNKNOWN] = " (unknown network)",
168 if (network_type > WIMAX_API_UNKNOWN)
169 return "(BUG! UNKNOWN NETWORK_TYPE MODE)";
171 return network_type_name[network_type];
175 * If the device is connected but we don't know about the network,
176 * create the knowledge of it.
178 * Asks the WiMAX API to report which NSP we are connected to and we
179 * create/update a network_el in the device's network list. Then
182 * Returns NULL on error.
184 * NOTE: wmxsdk->network_mutex has to be taken
186 struct connman_network *__iwmx_sdk_get_connected_network(struct wmxsdk *wmxsdk)
188 struct connman_network *nw;
190 WIMAX_API_CONNECTED_NSP_INFO nsp_info;
193 UINT32 errstr_size = sizeof(errstr);
195 /* The device is getting connected due to an external (to
196 * connman) event; find which is the nw we are getting
197 * connected to. if we don't have it, add it */
198 r = GetConnectedNSP(&wmxsdk->device_id, &nsp_info);
199 if (r != WIMAX_API_RET_SUCCESS) {
200 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
202 "wmxsdk: Cannot get connected NSP info: %d (%s)\n",
204 strcpy((char *) nsp_info.NSPName, "unknown");
205 nw = iwmx_cm_network_available(
207 iwmx_sdk_network_type_name(WIMAX_API_UNKNOWN),
208 nsp_info.NSPName, strlen((char *) nsp_info.NSPName) + 1,
209 cinr_to_percentage(nsp_info.CINR - 10));
211 nw = iwmx_cm_network_available(
212 wmxsdk, (char *) nsp_info.NSPName,
213 iwmx_sdk_network_type_name(nsp_info.networkType),
214 nsp_info.NSPName, strlen((char *) nsp_info.NSPName) + 1,
215 cinr_to_percentage(nsp_info.CINR - 10));
221 * Callback for a RF State command
223 * Called by the WiMAX API when a command sent to change the RF state
224 * is completed. This is just a confirmation of what happened with the
227 * We don't do anything, as when the device changes state, the state
228 * change callback is called and that will fiddle with the connman
231 static void __iwmx_sdk_rf_state_cb(WIMAX_API_DEVICE_ID *device_id,
232 WIMAX_API_RF_STATE rf_state)
234 DBG("rf_state changed to %d\n", rf_state);
238 * Turn the radio on or off
240 * First it checks that we are in the right state before doing
241 * anything; there might be no need to do anything.
243 * Issue a command to the WiMAX API, wait for a callback confirming it
244 * is done. Sometimes the callback is missed -- in that case, do force
245 * a state change evaluation.
249 * Geezoos efing Xist, they make difficult even the most simple
252 * This thing is definitely a pain. If the radio is ON already
253 * and you switch it on again...well, there is no way to tell
254 * because you don't get a callback saying it basically
255 * suceeded. But on the other hand, if the thing was in a
256 * different state and action needs to be taken, you have to wait
257 * for a callback to confirm it's done. However, there is also an
258 * state change callback, which is almost the same, so now you
259 * have to handle things in two "unrelated" threads of execution.
261 * How the shpx are you expected to tell the difference? Check
262 * status first? On timeout? Nice gap (eighteen wheeler size) for
265 int iwmx_sdk_rf_state_set(struct wmxsdk *wmxsdk, WIMAX_API_RF_STATE rf_state)
271 UINT32 errstr_size = sizeof(errstr);
272 WIMAX_API_DEVICE_STATUS dev_status;
274 g_assert(rf_state == WIMAX_API_RF_ON || rf_state == WIMAX_API_RF_OFF);
276 /* Guess what the current radio state is; if it is ON
277 * already, don't redo it. */
278 dev_status = iwmx_sdk_get_device_status(wmxsdk);
279 if ((int) dev_status < 0) {
281 goto error_get_status;
283 switch (dev_status) {
284 case WIMAX_API_DEVICE_STATUS_UnInitialized:
287 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
288 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
290 "wmxsdk: cannot turn on radio: hw switch is off\n");
294 case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
295 if (rf_state == WIMAX_API_RF_OFF) {
297 DBG("radio is already off\n");
301 case WIMAX_API_DEVICE_STATUS_Ready:
302 case WIMAX_API_DEVICE_STATUS_Scanning:
303 case WIMAX_API_DEVICE_STATUS_Connecting:
304 case WIMAX_API_DEVICE_STATUS_Data_Connected:
305 #if HAVE_IWMXSDK_STATUS_IDLE
306 case WIMAX_API_DEVICE_STATUS_Connection_Idle:
308 if (rf_state == WIMAX_API_RF_ON) {
310 DBG("radio is already on\n");
317 /* Ok, flip the radio */
318 r = CmdControlPowerManagement(&wmxsdk->device_id, rf_state);
319 if (r != WIMAX_API_RET_SUCCESS) {
320 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
321 connman_error("wmxsdk: Cannot flip radio to %d: %d (%s) "
322 "[device is in state %s]\n",
324 iwmx_sdk_get_device_status_str(wmxsdk));
327 result = -EINPROGRESS;
335 * Callback for a Connect command
337 * Called by the WiMAX API when a command sent to connect is
338 * completed. This is just a confirmation of what happened with the
341 * WE DON'T DO MUCH HERE -- the real meat happens when a state change
342 * callback is sent, where we detect we move to connected state (or
343 * from disconnecting to something else); the state change callback is
344 * called and that will fiddle with the connman internals.
346 static void __iwmx_sdk_connect_cb(WIMAX_API_DEVICE_ID *device_id,
347 WIMAX_API_NETWORK_CONNECTION_RESP resp)
349 WIMAX_API_DEVICE_STATUS status;
350 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
352 status = iwmx_cm_status_get(wmxsdk);
353 if (resp == WIMAX_API_CONNECTION_SUCCESS) {
354 if (status != WIMAX_API_DEVICE_STATUS_Data_Connected
355 #if HAVE_IWMXSDK_STATUS_IDLE
356 && status != WIMAX_API_DEVICE_STATUS_Connection_Idle
359 connman_error("wmxsdk: error: connect worked, but state"
360 " didn't change (now it is %d [%s])\n",
362 iwmx_sdk_dev_status_to_str(status));
364 connman_error("wmxsdk: failed to connect (status %d: %s)\n",
365 status, iwmx_sdk_dev_status_to_str(status));
369 * Connect to a network
371 * This function starts the connection process to a given network;
372 * when the device changes status, the status change callback will
373 * tell connman if the network is finally connected or not.
375 * One of the reasons it is done like that is to allow external tools
376 * to control the device and the plugin just passing the status so
377 * connman displays the right info.
379 int iwmx_sdk_connect(struct wmxsdk *wmxsdk, struct connman_network *nw)
385 UINT32 errstr_size = sizeof(errstr);
386 WIMAX_API_DEVICE_STATUS dev_status;
387 const char *station_name = connman_network_get_identifier(nw);
388 const void *sdk_nspname;
389 unsigned int sdk_nspname_size;
391 g_mutex_lock(wmxsdk->connect_mutex);
392 /* Guess what the current radio state is; if it is ON
393 * already, don't redo it. */
394 dev_status = iwmx_cm_status_get(wmxsdk);
395 if ((int) dev_status < 0) {
397 goto error_get_status;
399 switch (dev_status) {
400 case WIMAX_API_DEVICE_STATUS_UnInitialized:
401 connman_error("wmxsdk: SW BUG? HW is uninitialized\n");
404 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
405 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
406 case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
407 connman_error("wmxsdk: Cannot connect: radio is off\n");
410 case WIMAX_API_DEVICE_STATUS_Ready:
411 case WIMAX_API_DEVICE_STATUS_Scanning:
413 case WIMAX_API_DEVICE_STATUS_Connecting:
414 DBG("Connect already pending, waiting for it\n");
415 result = -EINPROGRESS;
417 case WIMAX_API_DEVICE_STATUS_Data_Connected:
418 #if HAVE_IWMXSDK_STATUS_IDLE
419 case WIMAX_API_DEVICE_STATUS_Connection_Idle:
421 connman_error("wmxsdk: BUG? need to disconnect?\n");
428 /* Ok, do the connection, wait for a callback */
429 wmxsdk->connecting_nw = connman_network_ref(nw);
430 sdk_nspname = connman_network_get_blob(nw, "WiMAX.NSP.name",
432 g_assert(sdk_nspname != NULL);
433 r = CmdConnectToNetwork(&wmxsdk->device_id, (void *) sdk_nspname, 0, 0);
434 if (r != WIMAX_API_RET_SUCCESS) {
435 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
436 connman_error("wmxsdk: Cannot connect to network %s: %d (%s)"
437 " - device is in state '%s'\n",
438 station_name, r, errstr,
439 iwmx_sdk_get_device_status_str(wmxsdk));
441 connman_network_unref(nw);
442 wmxsdk->connecting_nw = NULL;
444 result = -EINPROGRESS;
447 g_mutex_unlock(wmxsdk->connect_mutex);
452 * Callback for a Disconnect command
454 * Called by the WiMAX API when a command sent to connect is
455 * completed. This is just a confirmation of what happened with the
458 * When the device changes state, the state change callback is called
459 * and that will fiddle with the connman internals.
461 * We just update the result of the command and wake up anybody who is
462 * waiting for this conditional variable.
464 static void __iwmx_sdk_disconnect_cb(WIMAX_API_DEVICE_ID *device_id,
465 WIMAX_API_NETWORK_CONNECTION_RESP resp)
467 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
468 WIMAX_API_DEVICE_STATUS status;
470 status = iwmx_cm_status_get(wmxsdk);
471 if (resp == WIMAX_API_CONNECTION_SUCCESS) {
472 if (status == WIMAX_API_DEVICE_STATUS_Data_Connected
473 #if HAVE_IWMXSDK_STATUS_IDLE
474 || status == WIMAX_API_DEVICE_STATUS_Connection_Idle
477 connman_error("wmxsdk: error: disconnect worked, "
478 "but state didn't change (now it is "
479 "%d [%s])\n", status,
480 iwmx_sdk_dev_status_to_str(status));
482 connman_error("wmxsdk: failed to disconnect (status %d: %s)\n",
483 status, iwmx_sdk_dev_status_to_str(status));
487 * Disconnect from a network
489 * This function tells the device to disconnect; the state change
490 * callback will take care of inform connman's internals.
492 int iwmx_sdk_disconnect(struct wmxsdk *wmxsdk)
498 UINT32 errstr_size = sizeof(errstr);
499 WIMAX_API_DEVICE_STATUS dev_status;
501 g_mutex_lock(wmxsdk->connect_mutex);
502 /* Guess what the current radio state is; if it is ON
503 * already, don't redo it. */
504 dev_status = iwmx_sdk_get_device_status(wmxsdk);
505 if ((int) dev_status < 0) {
507 goto error_get_status;
509 switch (dev_status) {
510 case WIMAX_API_DEVICE_STATUS_UnInitialized:
511 connman_error("wmxsdk: SW BUG? HW is uninitialized\n");
514 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
515 case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
516 case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
517 DBG("Cannot disconnect, radio is off; ignoring\n");
520 case WIMAX_API_DEVICE_STATUS_Ready:
521 case WIMAX_API_DEVICE_STATUS_Scanning:
522 DBG("Cannot disconnect, already disconnected; ignoring\n");
525 case WIMAX_API_DEVICE_STATUS_Connecting:
526 case WIMAX_API_DEVICE_STATUS_Data_Connected:
527 #if HAVE_IWMXSDK_STATUS_IDLE
528 case WIMAX_API_DEVICE_STATUS_Connection_Idle:
534 /* Ok, flip the radio */
535 r = CmdDisconnectFromNetwork(&wmxsdk->device_id);
536 if (r != WIMAX_API_RET_SUCCESS) {
537 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
538 connman_error("wmxsdk: Cannot disconnect from network: "
539 "%d (%s)\n", r, errstr);
542 result = -EINPROGRESS;
545 g_mutex_unlock(wmxsdk->connect_mutex);
550 * Callback for state change messages
552 * Just pass them to the state transition handler
554 static void __iwmx_sdk_state_change_cb(WIMAX_API_DEVICE_ID *device_id,
555 WIMAX_API_DEVICE_STATUS status,
556 WIMAX_API_STATUS_REASON reason,
557 WIMAX_API_CONNECTION_PROGRESS_INFO pi)
559 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
560 iwmx_cm_state_change(wmxsdk, status);
564 * Called by _iwmx_sdk_*scan_cb() when [wide or preferred] scan results
567 * From here we update the connman core idea of which networks are
570 static void __iwmx_sdk_scan_common_cb(WIMAX_API_DEVICE_ID *device_id,
571 WIMAX_API_NSP_INFO_EX *nsp_list,
572 UINT32 nsp_list_size)
574 struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id);
576 char station_name[256];
578 g_static_mutex_lock(&wmxsdk->network_mutex);
579 for (itr = 0; itr < nsp_list_size; itr++) {
581 WIMAX_API_NSP_INFO_EX *nsp_info = &nsp_list[itr];
582 snprintf(station_name, sizeof(station_name),
583 "%s", (char *)nsp_info->NSPName);
584 /* CAPI is reporing link quality as zero -- if it is
585 * zero, check if it is a bug by computing it based on
586 * CINR. If it is different, use the computed one. */
587 strength = nsp_info->linkQuality;
588 if (strength == 0) { /* huh */
590 cinr_to_percentage(nsp_info->CINR - 10);
591 if (linkq_expected != strength)
592 strength = linkq_expected;
595 __iwmx_cm_network_available(
596 wmxsdk, station_name,
597 iwmx_sdk_network_type_name(nsp_info->networkType),
599 strlen((char *) nsp_info->NSPName) + 1,
602 g_static_mutex_unlock(&wmxsdk->network_mutex);
606 * Called by the WiMAX API when we get a wide scan result
608 * We treat them same as wide, so we just call that.
610 static void __iwmx_sdk_wide_scan_cb(WIMAX_API_DEVICE_ID *device_id,
611 WIMAX_API_NSP_INFO_EX *nsp_list,
612 UINT32 nsp_list_size)
614 __iwmx_sdk_scan_common_cb(device_id, nsp_list, nsp_list_size);
618 * Called by the WiMAX API when we get a normal (non wide) scan result
620 * We treat them same as wide, so we just call that.
622 static void __iwmx_sdk_scan_cb(WIMAX_API_DEVICE_ID *device_id,
623 WIMAX_API_NSP_INFO_EX *nsp_list,
624 UINT32 nsp_list_size, UINT32 searchProgress)
626 __iwmx_sdk_scan_common_cb(device_id, nsp_list, nsp_list_size);
630 * Called to ask the device to scan for networks
632 * We don't really scan as the WiMAX SDK daemon scans in the
633 * background for us. We just get the results. See iwmx_sdk_setup().
635 int iwmx_sdk_scan(struct wmxsdk *wmxsdk)
639 UINT32 nsp_list_length = 10;
640 WIMAX_API_NSP_INFO_EX nsp_list[10]; /* FIXME: up to 32? */
644 UINT32 errstr_size = sizeof(errstr);
646 r = GetNetworkListEx(&wmxsdk->device_id, nsp_list, &nsp_list_length);
647 if (r != WIMAX_API_RET_SUCCESS) {
648 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
649 connman_error("wmxsdk: Cannot get network list: %d (%s)\n",
655 if (nsp_list_length == 0)
656 DBG("no networks\n");
658 __iwmx_sdk_scan_common_cb(&wmxsdk->device_id, nsp_list,
666 * Initialize the WiMAX API, register with it, setup callbacks
671 * connman_inet_create_device
675 int iwmx_sdk_setup(struct wmxsdk *wmxsdk)
682 UINT32 errstr_size = sizeof(errstr);
686 /* device_id initialized by iwmx_sdk_dev_add */
688 r = WiMaxDeviceOpen(&wmxsdk->device_id);
689 if (r != WIMAX_API_RET_SUCCESS) {
690 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
691 connman_error("wmxsdk: Cannot open device: %d (%s)\n",
693 goto error_wimaxdeviceopen;
697 * We scan in auto mode (in the background)
699 * Otherwise is messy -- if we have connman triggering a scan
700 * when we call iwmx_cm_scan() -> iwmx_sdk_scan(), most of the
701 * times that causes a race condition when the UI asks for a
702 * scan right before displaying the network menu. As there is
703 * no way to cancel an ongoing scan before connecting, we are
704 * stuck. So we do auto bg and have iwmx_sdk_scan() just return
705 * the current network list.
707 r = SetConnectionMode(&wmxsdk->device_id,
708 WIMAX_API_CONNECTION_AUTO_SCAN_MANUAL_CONNECT);
709 if (r != WIMAX_API_RET_SUCCESS) {
710 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
711 connman_error("wmxsdk: Cannot set connectin mode to manual: "
712 "%d (%s)\n", r, errstr);
713 goto error_connection_mode;
716 r = SubscribeControlPowerManagement(&wmxsdk->device_id,
717 __iwmx_sdk_rf_state_cb);
718 if (r != WIMAX_API_RET_SUCCESS) {
719 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
720 connman_error("wmxsdk: Cannot subscribe to radio change "
721 "events: %u (%s)\n", r, errstr);
723 goto error_subscribe_rf_state;
726 r = SubscribeDeviceStatusChange(&wmxsdk->device_id,
727 __iwmx_sdk_state_change_cb);
728 if (r != WIMAX_API_RET_SUCCESS) {
729 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
730 connman_error("wmxsdk: Cannot subscribe to state chaneg events:"
731 "%d (%s)\n", r, errstr);
732 goto error_subscribe_state_change;
735 r = SubscribeNetworkSearchWideScanEx(&wmxsdk->device_id,
736 __iwmx_sdk_wide_scan_cb);
737 if (r != WIMAX_API_RET_SUCCESS) {
738 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
739 connman_error("wmxsdk: Cannot subscribe to wide scan events: "
740 "%d (%s)\n", r, errstr);
741 goto error_subscribe_wide_scan;
743 r = SubscribeNetworkSearchEx(&wmxsdk->device_id, __iwmx_sdk_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 scan events: "
747 "%d (%s)\n", r, errstr);
748 goto error_subscribe_scan;
751 r = SubscribeConnectToNetwork(&wmxsdk->device_id,
752 __iwmx_sdk_connect_cb);
753 if (r != WIMAX_API_RET_SUCCESS) {
754 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
755 connman_error("wmxsdk: Cannot subscribe to connect events: "
756 "%d (%s)\n", r, errstr);
757 goto error_subscribe_connect;
760 r = SubscribeDisconnectToNetwork(&wmxsdk->device_id,
761 __iwmx_sdk_disconnect_cb);
762 if (r != WIMAX_API_RET_SUCCESS) {
763 GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size);
764 connman_error("wmxsdk: Cannot subscribe to disconnect events: "
765 "%d (%s)\n", r, errstr);
766 goto error_subscribe_disconnect;
772 UnsubscribeDisconnectToNetwork(&wmxsdk->device_id);
773 error_subscribe_disconnect:
774 UnsubscribeConnectToNetwork(&wmxsdk->device_id);
775 error_subscribe_connect:
776 UnsubscribeNetworkSearchEx(&wmxsdk->device_id);
777 error_subscribe_scan:
778 UnsubscribeNetworkSearchWideScanEx(&wmxsdk->device_id);
779 error_subscribe_wide_scan:
780 UnsubscribeDeviceStatusChange(&wmxsdk->device_id);
781 error_subscribe_state_change:
782 UnsubscribeControlPowerManagement(&wmxsdk->device_id);
783 error_subscribe_rf_state:
784 error_connection_mode:
785 WiMaxDeviceClose(&wmxsdk->device_id);
786 error_wimaxdeviceopen:
791 * Called when a device is removed from connman
793 * Cleanup all that is done in iwmx_sdk_setup(). Remove callbacks,
794 * unregister from the WiMAX API.
796 void iwmx_sdk_remove(struct wmxsdk *wmxsdk)
798 UnsubscribeDisconnectToNetwork(&wmxsdk->device_id);
799 UnsubscribeConnectToNetwork(&wmxsdk->device_id);
800 UnsubscribeNetworkSearchEx(&wmxsdk->device_id);
801 UnsubscribeNetworkSearchWideScanEx(&wmxsdk->device_id);
802 UnsubscribeDeviceStatusChange(&wmxsdk->device_id);
803 UnsubscribeControlPowerManagement(&wmxsdk->device_id);
804 WiMaxDeviceClose(&wmxsdk->device_id);
807 static void iwmx_sdk_dev_add(unsigned idx, unsigned api_idx, const char *name)
810 struct wmxsdk *wmxsdk;
813 if (idx >= IWMX_SDK_DEV_MAX) {
814 connman_error("BUG! idx (%u) >= IWMX_SDK_DEV_MAX (%u)\n",
815 idx, IWMX_SDK_DEV_MAX);
818 if (g_iwmx_sdk_devs[idx] != NULL) {
819 connman_error("BUG! device index %u already enumerated?\n",
824 wmxsdk = malloc(sizeof(*wmxsdk));
825 if (wmxsdk == NULL) {
826 connman_error("Can't allocate %zu bytes\n",
831 memset(wmxsdk, 0, sizeof(*wmxsdk));
834 * This depends on a hack in the WiMAX Network Service; it has
835 * to return, as part of the device name, a string "if:IFNAME"
836 * where the OS's device name is stored.
838 s = strstr(name, "if:");
840 || sscanf(s, "if:%15[^ \f\n\r\t\v]", wmxsdk->ifname) != 1) {
841 connman_error("Cannot extract network interface name off '%s'",
845 DBG("network interface name: '%s'", wmxsdk->ifname);
847 ifindex = if_nametoindex(wmxsdk->ifname);
850 connman_error("wxmsdk: %s: cannot find interface index\n",
855 wmxsdk->dev = connman_inet_create_device(ifindex);
856 if (wmxsdk->dev == NULL) {
857 connman_error("wmxsdk: %s: failed to create connman_device\n",
861 strncpy(wmxsdk->name, name, sizeof(wmxsdk->name));
862 connman_device_set_data(wmxsdk->dev, wmxsdk);
864 wmxsdk->device_id.privilege = WIMAX_API_PRIVILEGE_READ_WRITE;
865 wmxsdk->device_id.deviceIndex = api_idx;
867 result = connman_device_register(wmxsdk->dev);
869 connman_error("wmxsdk: %s: failed to register: %d\n",
870 wmxsdk->ifname, result);
873 g_iwmx_sdk_devs[idx] = wmxsdk;
878 connman_device_unref(wmxsdk->dev);
886 static void iwmx_sdk_dev_rm(unsigned idx)
888 struct wmxsdk *wmxsdk;
890 if (idx >= IWMX_SDK_DEV_MAX) {
891 connman_error("BUG! idx (%u) >= IWMX_SDK_DEV_MAX (%u)\n",
892 idx, IWMX_SDK_DEV_MAX);
895 wmxsdk = g_iwmx_sdk_devs[idx];
896 if (wmxsdk->dev == NULL) {
897 DBG("device index %u not enumerated? ignoring\n", idx);
901 connman_device_unregister(wmxsdk->dev);
903 connman_device_unref(wmxsdk->dev);
904 memset(wmxsdk, 0, sizeof(*wmxsdk));
905 g_iwmx_sdk_devs[idx] = NULL;
911 static void iwmx_sdk_addremove_cb(WIMAX_API_DEVICE_ID *devid,
916 WIMAX_API_HW_DEVICE_ID device_id_list[5];
917 UINT32 device_id_list_size = ARRAY_SIZE(device_id_list);
920 UINT32 errstr_size = sizeof(errstr);
922 DBG("cb: handle %u index #%u is %d\n", devid->sdkHandle,
923 devid->deviceIndex, presence);
925 r = GetListDevice(devid, device_id_list, &device_id_list_size);
926 if (r != WIMAX_API_RET_SUCCESS) {
927 GetErrorString(devid, r, errstr, &errstr_size);
928 connman_error("wmxsdk: Cannot obtain list "
929 "of devices: %d (%s)\n", r, errstr);
933 if (device_id_list_size == 0)
934 DBG("No WiMAX devices reported\n");
936 for (cnt = 0; cnt < device_id_list_size; cnt++) {
937 WIMAX_API_HW_DEVICE_ID *dev =
938 device_id_list + cnt;
939 DBG("#%u index #%u device %s\n",
940 cnt, dev->deviceIndex, dev->deviceName);
942 if (device_id_list_size < devid->deviceIndex) {
943 connman_error("wmxsdk: changed device (%u) not in the list? "
945 devid->deviceIndex, device_id_list_size);
950 WIMAX_API_HW_DEVICE_ID *dev =
951 device_id_list + devid->deviceIndex;
952 iwmx_sdk_dev_add(devid->deviceIndex, dev->deviceIndex,
955 iwmx_sdk_dev_rm(devid->deviceIndex);
960 * Initialize the WiMAX API, register with it, setup callbacks for
961 * device coming up / dissapearing
963 int iwmx_sdk_api_init(void)
969 UINT32 errstr_size = sizeof(errstr);
971 WIMAX_API_HW_DEVICE_ID device_id_list[5];
972 UINT32 device_id_list_size = ARRAY_SIZE(device_id_list);
974 memset(&g_api, 0, sizeof(g_api));
975 g_api.privilege = WIMAX_API_PRIVILEGE_READ_WRITE;
978 r = WiMaxAPIOpen(&g_api);
979 if (r != WIMAX_API_RET_SUCCESS) {
980 GetErrorString(&g_api, r, errstr, &errstr_size);
981 connman_error("wmxsdk: WiMaxAPIOpen failed with %d (%s)\n",
983 goto error_wimaxapiopen;
986 r = SubscribeDeviceInsertRemove(&g_api, iwmx_sdk_addremove_cb);
987 if (r != WIMAX_API_RET_SUCCESS) {
988 GetErrorString(&g_api, r, errstr, &errstr_size);
989 connman_error("wmxsdk: insert/remove subscribe failed with "
990 "%d (%s)\n", r, errstr);
994 r = GetListDevice(&g_api, device_id_list, &device_id_list_size);
995 if (r != WIMAX_API_RET_SUCCESS) {
996 GetErrorString(&g_api, r, errstr, &errstr_size);
997 connman_error("wmxsdk: Cannot obtain list "
998 "of devices: %d (%s)\n", r, errstr);
1001 if (device_id_list_size < g_api.deviceIndex) {
1002 connman_error("wmxsdk: changed device (%u) not in the list? "
1004 g_api.deviceIndex, device_id_list_size);
1007 if (device_id_list_size == 0)
1008 DBG("No WiMAX devices reported\n");
1010 for (cnt = 0; cnt < device_id_list_size; cnt++) {
1011 WIMAX_API_HW_DEVICE_ID *dev =
1012 device_id_list + cnt;
1013 DBG("#%u index #%u device %s\n",
1014 cnt, dev->deviceIndex, dev->deviceName);
1015 iwmx_sdk_dev_add(cnt, dev->deviceIndex,
1021 WiMaxAPIClose(&g_api);
1026 void iwmx_sdk_api_exit(void)
1031 UINT32 errstr_size = sizeof(errstr);
1033 r = WiMaxAPIClose(&g_api);
1034 if (r != WIMAX_API_RET_SUCCESS) {
1035 GetErrorString(&g_api, r, errstr, &errstr_size);
1036 connman_error("wmxsdk: WiMaxAPIClose failed with %d (%s)\n",