00001
00013 #include "apm.h"
00014 #include "apm_task.h"
00015 #include "me_utils.h"
00016 #include "bam.h"
00017 #include "ke_timer.h"
00018 #include "vif_mgmt.h"
00019 #include "chan.h"
00020 #include "me_task.h"
00021 #include "me.h"
00022 #include "ps.h"
00023 #include "tpc.h"
00024
00025 #if NX_BEACONING
00026
00045 static int
00046 apm_start_req_handler(ke_msg_id_t const msgid,
00047 struct apm_start_req *param,
00048 ke_task_id_t const dest_id,
00049 ke_task_id_t const src_id)
00050 {
00051
00052 struct apm_start_cfm *cfm;
00053 uint8_t status;
00054
00055 uint8_t chan_idx;
00056
00057 do
00058 {
00059 struct vif_info_tag *vif = &vif_info_tab[param->vif_idx];
00060
00061
00062 if (vif->type != VIF_AP)
00063 {
00064 status = CO_BAD_PARAM;
00065 break;
00066 }
00067
00068
00069 if (ke_state_get(TASK_APM) != APM_IDLE)
00070 {
00071 status = CO_BUSY;
00072 break;
00073 }
00074
00075
00076 if (vif->active)
00077 {
00078 status = CO_OP_IN_PROGRESS;
00079 break;
00080 }
00081
00082
00083 ASSERT_ERR(vif->chan_ctxt == NULL);
00084
00085
00086 apm_env.param = param;
00087
00088 if (chan_ctxt_add(¶m->chan, &chan_idx) == CO_OK)
00089 {
00090 struct me_bss_info *bss = &vif->bss_info;
00091
00092
00093 bss->chan = param->chan;
00094
00095
00096 bss->power_constraint = 0;
00097 tpc_update_vif_tx_power(vif);
00098
00099
00100 chan_ctxt_link(param->vif_idx, chan_idx);
00101
00102
00103
00104 if (param->chan.band == PHY_BAND_2G4)
00105 {
00106 uint32_t basic_11b_rates;
00107 basic_11b_rates = me_legacy_rate_bitfield_build(&(bss->rate_set), true) & 0x0F;
00108
00109 if (basic_11b_rates)
00110
00111 bss->high_11b_rate = 31 - co_clz(basic_11b_rates);
00112 else
00113
00114 bss->high_11b_rate = HW_RATE_2MBPS;
00115 }
00116
00117
00118 apm_set_bss_param();
00119 }
00120 else
00121 {
00122 status = CO_FAIL;
00123 break;
00124 }
00125
00126
00127 return (KE_MSG_NO_FREE);
00128 } while(0);
00129
00130 cfm = KE_MSG_ALLOC(APM_START_CFM, src_id, dest_id, apm_start_cfm);
00131 cfm->status = status;
00132 cfm->vif_idx = param->vif_idx;
00133
00134
00135 ke_msg_send(cfm);
00136
00137 return (KE_MSG_CONSUMED);
00138 }
00139
00155 static int
00156 me_set_ps_disable_cfm_handler(ke_msg_id_t const msgid,
00157 void const *param,
00158 ke_task_id_t const dest_id,
00159 ke_task_id_t const src_id)
00160 {
00161
00162 ASSERT_ERR((ke_state_get(TASK_APM) == APM_BSS_PARAM_SETTING) ||
00163 (ke_state_get(TASK_APM) == APM_IDLE) ||
00164 (ke_state_get(TASK_APM) == APM_STOPPING));
00165
00166
00167 if ((ke_state_get(TASK_APM) == APM_BSS_PARAM_SETTING) ||
00168 (ke_state_get(TASK_APM) == APM_STOPPING))
00169 {
00170
00171 apm_bss_config_send();
00172 }
00173
00174 return (KE_MSG_CONSUMED);
00175 }
00176
00192 static int
00193 mm_bss_param_setting_handler(ke_msg_id_t const msgid,
00194 void const *param,
00195 ke_task_id_t const dest_id,
00196 ke_task_id_t const src_id)
00197 {
00198
00199 ASSERT_ERR(ke_state_get(TASK_APM) == APM_BSS_PARAM_SETTING);
00200
00201
00202 apm_bss_config_send();
00203
00204 return (KE_MSG_CONSUMED);
00205 }
00206
00222 static int
00223 me_set_active_cfm_handler(ke_msg_id_t const msgid,
00224 void const *param,
00225 ke_task_id_t const dest_id,
00226 ke_task_id_t const src_id)
00227 {
00228
00229 ASSERT_ERR((ke_state_get(TASK_APM) == APM_BSS_PARAM_SETTING) ||
00230 (ke_state_get(TASK_APM) == APM_IDLE) ||
00231 (ke_state_get(TASK_APM) == APM_STOPPING));
00232
00233
00234 if (ke_state_get(TASK_APM) == APM_BSS_PARAM_SETTING)
00235 {
00236
00237 ASSERT_ERR(co_list_is_empty(&apm_env.bss_config));
00238
00239
00240 apm_bcn_set();
00241 }
00242 else if (ke_state_get(TASK_APM) == APM_STOPPING)
00243 {
00244
00245 ke_msg_send_basic(APM_STOP_CFM, TASK_API, TASK_APM);
00246 ke_state_set(TASK_APM, APM_IDLE);
00247 }
00248
00249 return (KE_MSG_CONSUMED);
00250 }
00251
00269 static int
00270 mm_bcn_change_cfm_handler(ke_msg_id_t const msgid,
00271 void const *param,
00272 ke_task_id_t const dest_id,
00273 ke_task_id_t const src_id)
00274 {
00275
00276 ASSERT_ERR(ke_state_get(TASK_APM) == APM_BCN_SETTING);
00277
00278
00279 apm_start_cfm(CO_OK);
00280
00281 return (KE_MSG_CONSUMED);
00282 }
00283
00296 static int
00297 mm_chan_ctxt_unlink_cfm_handler(ke_msg_id_t const msgid,
00298 void const *param,
00299 ke_task_id_t const dest_id,
00300 ke_task_id_t const src_id)
00301 {
00302
00303 ASSERT_ERR(ke_state_get(TASK_APM) == APM_STOPPING);
00304
00305
00306 apm_bss_config_send();
00307
00308 return (KE_MSG_CONSUMED);
00309 }
00310
00323 static int
00324 mm_set_vif_state_cfm_handler(ke_msg_id_t const msgid,
00325 void const *param,
00326 ke_task_id_t const dest_id,
00327 ke_task_id_t const src_id)
00328 {
00329
00330 ASSERT_ERR((ke_state_get(TASK_APM) == APM_STOPPING) ||
00331 (ke_state_get(TASK_APM) == APM_IDLE));
00332
00333
00334 if (ke_state_get(TASK_APM) == APM_STOPPING)
00335 {
00336
00337 apm_bss_config_send();
00338 }
00339
00340 return (KE_MSG_CONSUMED);
00341 }
00342
00357 static int
00358 apm_stop_req_handler(ke_msg_id_t const msgid,
00359 struct apm_stop_req const *param,
00360 ke_task_id_t const dest_id,
00361 ke_task_id_t const src_id)
00362 {
00363 struct vif_info_tag *vif = &vif_info_tab[param->vif_idx];
00364
00365 if ((vif->type != VIF_AP) || (!vif->active))
00366 {
00367
00368 ke_msg_send_basic(APM_STOP_CFM, src_id, dest_id);
00369 return KE_MSG_CONSUMED;
00370 }
00371 else if (ke_state_get(TASK_APM) != APM_IDLE)
00372 {
00373
00374 return KE_MSG_SAVED;
00375 }
00376
00377
00378 apm_stop(vif);
00379 return KE_MSG_CONSUMED;
00380 }
00381
00398 static int
00399 apm_start_cac_req_handler(ke_msg_id_t const msgid,
00400 struct apm_start_cac_req const *param,
00401 ke_task_id_t const dest_id,
00402 ke_task_id_t const src_id)
00403 {
00404 struct apm_start_cac_cfm *cfm;
00405 uint8_t status = CO_OK;
00406 uint8_t chan_idx = 0;
00407
00408 do
00409 {
00410 struct vif_info_tag *vif = &vif_info_tab[param->vif_idx];
00411
00412
00413 if (vif->type != VIF_AP) {
00414 status = CO_BAD_PARAM;
00415 break;
00416 }
00417
00418
00419 if (vif->active) {
00420 status = CO_BUSY;
00421 break;
00422 }
00423
00424
00425 if (ke_state_get(TASK_APM) != APM_IDLE) {
00426 status = CO_BUSY;
00427 break;
00428 }
00429
00430
00431 if (chan_ctxt_add(¶m->chan, &chan_idx) == CO_OK) {
00432
00433 chan_ctxt_link(param->vif_idx, chan_idx);
00434 } else {
00435 status = CO_FAIL;
00436 break;
00437 }
00438
00439 #if (NX_POWERSAVE)
00440
00441 GLOBAL_INT_DISABLE();
00442 ps_env.prevent_sleep |= PS_CAC_STARTED;
00443 GLOBAL_INT_RESTORE();
00444 #endif
00445
00446
00447 } while(0);
00448
00449
00450 cfm = KE_MSG_ALLOC(APM_START_CAC_CFM, src_id, dest_id, apm_start_cac_cfm);
00451 cfm->status = status;
00452 cfm->ch_idx = chan_idx;
00453
00454
00455 ke_msg_send(cfm);
00456
00457 return (KE_MSG_CONSUMED);
00458 }
00459
00474 static int
00475 apm_stop_cac_req_handler(ke_msg_id_t const msgid,
00476 struct apm_stop_cac_req const *param,
00477 ke_task_id_t const dest_id,
00478 ke_task_id_t const src_id)
00479 {
00480 do
00481 {
00482 struct vif_info_tag *vif = &vif_info_tab[param->vif_idx];
00483
00484
00485 if (vif->type != VIF_AP) {
00486 break;
00487 }
00488
00489
00490 if (vif->active) {
00491 break;
00492 }
00493
00494
00495 if (ke_state_get(TASK_APM) != APM_IDLE) {
00496 break;
00497 }
00498
00499 chan_ctxt_unlink(param->vif_idx);
00500
00501 #if (NX_POWERSAVE)
00502
00503 GLOBAL_INT_DISABLE();
00504 ps_env.prevent_sleep &= ~PS_CAC_STARTED;
00505 GLOBAL_INT_RESTORE();
00506 #endif
00507
00508 } while(0);
00509
00510
00511 ke_msg_send_basic(APM_STOP_CAC_CFM, src_id, dest_id);
00512
00513 return (KE_MSG_CONSUMED);
00514 }
00515
00516
00518 const struct ke_msg_handler apm_default_state[] =
00519 {
00520 {APM_START_REQ, (ke_msg_func_t)apm_start_req_handler},
00521 {APM_STOP_REQ, (ke_msg_func_t)apm_stop_req_handler},
00522 {ME_SET_ACTIVE_CFM, (ke_msg_func_t)me_set_active_cfm_handler},
00523 {MM_BCN_CHANGE_CFM, (ke_msg_func_t)mm_bcn_change_cfm_handler},
00524 {MM_SET_BSSID_CFM, mm_bss_param_setting_handler},
00525 {MM_SET_BASIC_RATES_CFM, mm_bss_param_setting_handler},
00526 {MM_SET_BEACON_INT_CFM, mm_bss_param_setting_handler},
00527 {ME_SET_PS_DISABLE_CFM, (ke_msg_func_t)me_set_ps_disable_cfm_handler},
00528 {MM_SET_VIF_STATE_CFM, (ke_msg_func_t)mm_set_vif_state_cfm_handler},
00529 {MM_CHAN_CTXT_UNLINK_CFM, (ke_msg_func_t)mm_chan_ctxt_unlink_cfm_handler},
00530 {APM_START_CAC_REQ, (ke_msg_func_t)apm_start_cac_req_handler},
00531 {APM_STOP_CAC_REQ, (ke_msg_func_t)apm_stop_cac_req_handler},
00532 };
00533
00535 const struct ke_state_handler apm_default_handler =
00536 KE_STATE_HANDLER(apm_default_state);
00537
00539 ke_state_t apm_state[APM_IDX_MAX];
00540
00542
00543 #endif
00544