00001
00019
00020
00021
00022
00023
00024 #include "p2p.h"
00025
00026 #if (NX_P2P)
00027
00028 #include "mac_ie.h"
00029 #include "ps.h"
00030 #include "mm.h"
00031 #include "mm_bcn.h"
00032 #include "vif_mgmt.h"
00033
00034 #if (NX_P2P_GO)
00035 #include "td.h"
00036 #endif //(NX_P2P_GO)
00037
00038
00039
00040
00041
00042
00043 #if (NX_P2P_GO)
00044 struct p2p_env_tag p2p_env;
00045 #endif //(NX_P2P_GO)
00046
00047 struct p2p_info_tag p2p_info_tab[NX_P2P_VIF_MAX];
00048
00049
00050
00051
00052
00053
00054 __INLINE void p2p_go_noa_get_intv_cnt(struct p2p_noa_info_tag *noa);
00055 static void p2p_cli_noa_cancel(struct p2p_noa_info_tag *noa);
00056
00057
00058
00059
00060
00061
00071 static inline uint32_t p2p_local_2_peer_time(struct vif_info_tag *vif, uint32_t local_time)
00072 {
00073 ASSERT_ERR(vif->type == VIF_STA);
00074 return local_time + vif->u.sta.last_tsf_offset;
00075 }
00076
00086 static inline uint32_t p2p_peer_2_local_time(struct vif_info_tag *vif, uint32_t peer_time)
00087 {
00088 ASSERT_ERR(vif->type == VIF_STA);
00089 return peer_time - vif->u.sta.last_tsf_offset;
00090 }
00091
00104 static uint32_t p2p_att_find(uint32_t ie_addr, uint16_t ie_total_len, uint8_t att_id)
00105 {
00106 uint32_t ie_end = ie_addr + ie_total_len;
00107
00108
00109 while (ie_addr < ie_end)
00110 {
00111
00112 if (att_id == co_read8p(ie_addr))
00113 {
00114
00115 return (ie_addr);
00116 }
00117
00118
00119 ie_addr += co_read16p(ie_addr + P2P_ATT_LEN_OFT) + P2P_ATT_BODY_OFT;
00120 }
00121
00122 return (0);
00123 }
00124
00130 static void p2p_goto_idle_cb(void)
00131 {
00132 TRACE_P2P(PS, "HW is now in IDLE, can flush TX/RX queues");
00133
00134
00135 mm_force_idle_req();
00136
00137
00138 mm_active();
00139 }
00140
00153 static bool p2p_noa_wait_end_abs(struct p2p_info_tag *p2p, uint8_t *low_noa_count)
00154 {
00155 uint8_t noa_idx;
00156 bool wait_end_abs = false;
00157 *low_noa_count = 255;
00158
00159 for (noa_idx = 0; noa_idx < P2P_NOA_NB_MAX; noa_idx++)
00160 {
00161 struct p2p_noa_info_tag *noa = &p2p->noa[noa_idx];
00162 if ((noa->noa_status == P2P_NOA_TIMER_WAIT_END_ABS)
00163 #if (NX_P2P_GO)
00164 && !(p2p->noa_paused && noa->dyn_noa && (noa->noa_type == P2P_NOA_TYPE_NORMAL))
00165 #endif
00166 )
00167 {
00168 wait_end_abs = true;
00169 if (noa->noa_init_counter < *low_noa_count)
00170 {
00171 *low_noa_count = noa->noa_init_counter;
00172 }
00173 }
00174 }
00175
00176 return (wait_end_abs);
00177 }
00178
00190 static void p2p_update_noa_presence_date(struct p2p_info_tag *p2p)
00191 {
00192 bool first_noa = true;
00193 bool no_next_absent = true;
00194 uint32_t in_progress = 0;
00195 uint32_t next_present = 0;
00196 uint32_t next_absent = 0;
00197 struct p2p_noa_info_tag *noa;
00198 uint32_t absent, present;
00199
00200
00201 for (noa = &p2p->noa[0]; noa < &p2p->noa[P2P_NOA_NB_MAX]; noa++)
00202 {
00203 if ((noa->noa_status != P2P_NOA_TIMER_WAIT_END_ABS) || (noa->noa_counter > 1)
00204 #if (NX_P2P_GO)
00205 || (p2p->noa_paused && noa->dyn_noa && (noa->noa_type == P2P_NOA_TYPE_NORMAL))
00206 #endif
00207 )
00208 continue;
00209
00210 present = noa->noa_timer.time;
00211
00212 if (first_noa)
00213 {
00214 next_present = present;
00215 first_noa = false;
00216 }
00217 else if (hal_machw_time_cmp(next_present, present))
00218 {
00219 next_present = present;
00220 }
00221 in_progress++;
00222 }
00223
00224
00225 for (noa = &p2p->noa[0]; noa < &p2p->noa[P2P_NOA_NB_MAX]; noa++)
00226 {
00227 if ((noa->noa_status != P2P_NOA_TIMER_WAIT_END_ABS) || (noa->noa_counter <= 1)
00228 #if (NX_P2P_GO)
00229 || (p2p->noa_paused && noa->dyn_noa && (noa->noa_type == P2P_NOA_TYPE_NORMAL))
00230 #endif
00231 )
00232 continue;
00233
00234 present = noa->noa_timer.time;
00235 absent = present + noa->noa_intv_us - noa->noa_dur_us;
00236
00237 if (first_noa)
00238 {
00239 next_present = present;
00240 next_absent = absent;
00241 no_next_absent = false;
00242 first_noa = false;
00243 }
00244 else
00245 {
00246 int counter = noa->noa_counter;
00247 while (hal_machw_time_cmp(absent, next_present) && --counter)
00248 {
00249 absent += noa->noa_intv_us;
00250 present += noa->noa_intv_us;
00251 }
00252 if (!counter)
00253 continue;
00254
00255 if (hal_machw_time_cmp(next_present, present))
00256 next_present = present;
00257
00258 if ((counter > 1) &&
00259 (no_next_absent || hal_machw_time_cmp(absent, next_absent)))
00260 {
00261 next_absent = absent;
00262 no_next_absent = false;
00263 }
00264 }
00265 in_progress++;
00266 }
00267
00268
00269 for (noa = &p2p->noa[0]; noa < &p2p->noa[P2P_NOA_NB_MAX]; noa++)
00270 {
00271 if (noa->noa_status != P2P_NOA_TIMER_WAIT_NEXT_ABS)
00272 continue;
00273
00274 absent = noa->noa_timer.time;
00275 present = absent + noa->noa_dur_us;
00276
00277 if (first_noa)
00278 {
00279 next_present = present;
00280 next_absent = absent;
00281 no_next_absent = false;
00282 first_noa = false;
00283 }
00284 else if (in_progress)
00285 {
00286
00287 int counter = noa->noa_counter;
00288 while (hal_machw_time_cmp(present, next_present) && counter--)
00289 {
00290 absent += noa->noa_intv_us;
00291 present += noa->noa_intv_us;
00292 }
00293 if (counter < 0)
00294 continue;
00295
00296 if (no_next_absent)
00297 {
00298 if (hal_machw_time_cmp(next_present, absent))
00299 {
00300 next_absent = absent;
00301 no_next_absent = false;
00302 }
00303 else
00304 {
00305 next_present = present;
00306 if (counter > 0)
00307 {
00308 next_absent = absent + noa->noa_intv_us;
00309 no_next_absent = false;
00310 }
00311 }
00312 }
00313 else if (hal_machw_time_cmp(next_absent, absent))
00314 {
00315
00316 }
00317 else if (hal_machw_time_cmp(next_present, absent))
00318 {
00319 next_absent = absent;
00320 }
00321 else if (hal_machw_time_cmp(present, next_absent))
00322 {
00323 next_present = present;
00324 absent += noa->noa_intv_us;
00325 if ((counter > 1) &&
00326 hal_machw_time_cmp(absent, next_absent))
00327 next_absent = absent;
00328 }
00329 else
00330 {
00331
00332
00333 ASSERT_WARN(0);
00334 next_present = present;
00335 next_absent = absent + noa->noa_intv_us;
00336 }
00337 }
00338 else
00339 {
00340
00341 if (hal_machw_time_cmp(present, next_absent))
00342 {
00343
00344 next_present = present;
00345 next_absent = absent;
00346 }
00347 else if (hal_machw_time_cmp(next_present, absent))
00348 {
00349
00350 }
00351 else
00352 {
00353
00354 if (hal_machw_time_cmp(absent, next_absent))
00355 next_absent = absent;
00356 if (hal_machw_time_cmp(next_present, present))
00357 next_present = present;
00358 }
00359 }
00360 }
00361
00362 p2p->next_present = next_present;
00363 if (no_next_absent)
00364 p2p->next_absent = next_present + 10;
00365 else
00366 p2p->next_absent = next_absent;
00367 }
00368
00379 static void p2p_update_go_ps_state(struct p2p_info_tag *p2p)
00380 {
00381 bool is_go_present = true;
00382 bool tbtt_in_noa = false;
00383 uint8_t low_noa_count;
00384
00385 if (p2p_noa_wait_end_abs(p2p, &low_noa_count))
00386 {
00387
00388
00389
00390
00391
00392
00393
00394 if ((low_noa_count == 1) ||
00395 (!p2p->is_waiting_bcn &&
00396 (p2p->oppps_status != P2P_OPPPS_TIMER_WAIT_END_CTW)))
00397 {
00398 is_go_present = false;
00399 }
00400 else if (p2p->is_waiting_bcn)
00401 {
00402 tbtt_in_noa = true;
00403 }
00404 }
00405 else
00406 {
00407
00408 do
00409 {
00410
00411 if (p2p->oppps_ctw == 0)
00412 {
00413
00414 break;
00415 }
00416
00417
00418 if (p2p->oppps_status == P2P_OPPPS_TIMER_WAIT_END_CTW)
00419 {
00420
00421 break;
00422 }
00423
00424 #if (NX_P2P_GO)
00425 if (p2p->role == P2P_ROLE_GO)
00426 {
00427
00428
00429 struct vif_info_tag *vif = &vif_info_tab[p2p->vif_index];
00430
00431 if (vif->u.ap.ps_sta_cnt != vif->p2p_link_nb)
00432 {
00433 break;
00434 }
00435 }
00436 else
00437 #endif //(NX_P2P_GO)
00438 {
00439
00440 #if (NX_POWERSAVE)
00441 if (!ps_env.ps_on || (ps_env.prevent_sleep & PS_PSM_PAUSED))
00442 {
00443 break;
00444 }
00445 #endif //(NX_POWERSAVE)
00446 }
00447
00448 is_go_present = false;
00449 } while (0);
00450 }
00451
00452
00453 if (is_go_present != p2p->is_go_present)
00454 {
00455 #if (NX_CHNL_CTXT)
00456 struct vif_info_tag *vif = &vif_info_tab[p2p->vif_index];
00457 #endif //(NX_CHNL_CTXT)
00458
00459
00460 struct mm_p2p_vif_ps_change_ind *ind = KE_MSG_ALLOC(MM_P2P_VIF_PS_CHANGE_IND,
00461 TASK_API, TASK_MM,
00462 mm_p2p_vif_ps_change_ind);
00463
00464 ind->vif_index = p2p->vif_index;
00465 ind->ps_state = (is_go_present) ? PS_MODE_OFF : PS_MODE_ON;
00466
00467 TRACE_P2P(NOA_DET, "{VIF-%d} GO is present = %d", p2p->vif_index, is_go_present);
00468
00469
00470 ke_msg_send(ind);
00471
00472
00473 p2p->is_go_present = is_go_present;
00474
00475 #if (NX_CHNL_CTXT)
00476
00477 chan_p2p_absence_update(vif->chan_ctxt, !is_go_present);
00478 #endif //(NX_CHNL_CTXT)
00479
00480 #if (NX_UAPSD)
00481
00482 ps_p2p_absence_update(vif, !is_go_present);
00483 #endif //(NX_UAPSD)
00484
00485 if (!is_go_present)
00486 {
00487 PROF_P2P_ABSENCE_SET();
00488
00489
00490 #if (NX_P2P_GO)
00491 if (vif->type == VIF_AP)
00492 {
00493 #if (NX_POWERSAVE)
00494
00495 vif->prevent_sleep &= ~PS_VIF_P2P_GO_PRESENT;
00496 #endif //(NX_POWERSAVE)
00497 if (mm_bcn_transmitting())
00498 {
00499 GLOBAL_INT_DISABLE();
00500 txl_cntrl_halt_ac(AC_BCN);
00501 txl_cntrl_flush_ac(AC_BCN, DESC_DONE_SW_TX_BIT);
00502 GLOBAL_INT_RESTORE();
00503 }
00504 }
00505 #endif //(NX_P2P_GO)
00506
00507
00508 struct mm_force_idle_req *req = KE_MSG_ALLOC(MM_FORCE_IDLE_REQ,
00509 TASK_MM, TASK_NONE,
00510 mm_force_idle_req);
00511
00512
00513 req->cb = p2p_goto_idle_cb;
00514
00515
00516 ke_msg_send(req);
00517 }
00518 else
00519 {
00520 PROF_P2P_ABSENCE_CLR();
00521
00522
00523 #if (NX_P2P_GO && NX_POWERSAVE)
00524 if (vif->type == VIF_AP)
00525 {
00526
00527 vif->prevent_sleep |= PS_VIF_P2P_GO_PRESENT;
00528 }
00529 #endif //(NX_P2P_GO && NX_POWERSAVE)
00530 }
00531 }
00532
00533 if ((p2p->role == P2P_ROLE_CLIENT) && is_go_present && !tbtt_in_noa)
00534 {
00535
00536 vif_mgmt_send_postponed_frame(&vif_info_tab[p2p->vif_index]);
00537 }
00538 }
00539
00549 static void p2p_noa_timer_prog(struct p2p_noa_info_tag *noa, uint32_t time)
00550 {
00551 TRACE_P2P(NOA_DET, "{VIF-%d} Set NOA-%d timer %t",
00552 p2p_info_tab[noa->p2p_index].vif_index, noa->noa_inst, TR_32(time));
00553
00554 mm_timer_set(&noa->noa_timer, time);
00555 }
00556
00565 static void p2p_noa_timer_end(void *env)
00566 {
00567 struct p2p_noa_info_tag *noa = (struct p2p_noa_info_tag *)env;
00568 struct p2p_info_tag *p2p = &p2p_info_tab[noa->p2p_index];
00569 struct vif_info_tag *vif = &vif_info_tab[p2p->vif_index];
00570 uint8_t next_noa_status = noa->noa_status;
00571 uint32_t next_time;
00572
00573 TRACE_P2P(NOA_DET, "{VIF-%d} NOA-%d timer expire status=%d",
00574 p2p->vif_index, noa->noa_inst, noa->noa_status);
00575
00576 #if NX_P2P_GO
00577 if (p2p->role == P2P_ROLE_GO)
00578 {
00579
00580 next_time = noa->noa_timer.time;
00581 }
00582 else
00583 #endif
00584 {
00585
00586 next_time = p2p_peer_2_local_time(vif, noa->peer_next_noa_time);
00587 }
00588
00589
00590 do
00591 {
00592
00593 switch (next_noa_status)
00594 {
00595 case (P2P_NOA_TIMER_WAIT_NEXT_ABS):
00596 {
00597 PROF_P2P_NOA_ABS_SET(noa->noa_inst);
00598
00599 next_noa_status = P2P_NOA_TIMER_WAIT_END_ABS;
00600 next_time += (noa->noa_dur_us);
00601 } break;
00602
00603 case (P2P_NOA_TIMER_WAIT_END_ABS):
00604 {
00605 PROF_P2P_NOA_ABS_CLR(noa->noa_inst);
00606
00607
00608 if (noa->noa_counter != P2P_NOA_CONTINUOUS_COUNTER)
00609 {
00610 noa->noa_counter--;
00611 }
00612
00613
00614 if (noa->noa_counter)
00615 {
00616 next_noa_status = P2P_NOA_TIMER_WAIT_NEXT_ABS;
00617 next_time += (noa->noa_intv_us - noa->noa_dur_us);
00618
00619 #if (NX_P2P_GO)
00620
00621 if ((p2p->role == P2P_ROLE_GO) && p2p->is_noa_bcn)
00622 {
00623
00624 noa->noa_start_time += noa->noa_intv_us;
00625
00626 noa->noa_time_upd_cnt--;
00627
00628 if (!noa->noa_time_upd_cnt)
00629 {
00630
00631 noa->noa_init_counter = noa->noa_counter;
00632
00633
00634 p2p_go_noa_get_intv_cnt(noa);
00635
00636
00637 mm_bcn_update_p2p_noa(vif->index, P2P_BCN_UPD_OP_NOA_UPD);
00638 }
00639 }
00640 #endif //(NX_P2P_GO)
00641 }
00642 else
00643 {
00644 next_noa_status = P2P_NOA_TIMER_NOT_STARTED;
00645
00646 #if (NX_P2P_GO)
00647
00648 if (p2p->role == P2P_ROLE_GO)
00649 {
00650 p2p_go_noa_stop(vif, noa->noa_inst, false);
00651 }
00652 else
00653 #endif //(NX_P2P_GO)
00654 {
00655 p2p_cli_noa_cancel(noa);
00656 }
00657 }
00658 } break;
00659
00660 default:
00661 {
00662
00663 ASSERT_ERR(0);
00664 }
00665 }
00666 } while (hal_machw_time_cmp(next_time, ke_time() + P2P_NOA_TIMER_MARGIN) &&
00667 (next_noa_status != P2P_NOA_TIMER_NOT_STARTED));
00668
00669
00670 if (next_noa_status != P2P_NOA_TIMER_NOT_STARTED)
00671 {
00672 if (p2p->role == P2P_ROLE_CLIENT)
00673 {
00674
00675 noa->peer_next_noa_time = p2p_local_2_peer_time(vif, next_time);
00676 }
00677
00678 p2p_noa_timer_prog(noa, next_time);
00679
00680
00681 noa->noa_status = next_noa_status;
00682 }
00683
00684 p2p_update_noa_presence_date(p2p);
00685
00686
00687 p2p_update_go_ps_state(p2p);
00688
00689 #if (NX_P2P_GO && NX_POWERSAVE)
00690
00691
00692
00693
00694
00695 if ((vif->type == VIF_AP) &&
00696 (next_noa_status == P2P_NOA_TIMER_WAIT_NEXT_ABS))
00697 {
00698 vif->prevent_sleep |= PS_VIF_P2P_GO_PRESENT;
00699 }
00700 #endif //(NX_P2P_GO && NX_POWERSAVE)
00701 }
00702
00716 static void p2p_oppps_timer_end(void *env)
00717 {
00718 struct p2p_info_tag *p2p = (struct p2p_info_tag *)env;
00719
00720 TRACE_P2P(PS, "{VIF-%d} oppPS timer end status=%d", p2p->vif_index, p2p->oppps_status);
00721
00722 if (p2p->oppps_status == P2P_OPPPS_TIMER_WAIT_END_CTW)
00723 {
00724 PROF_P2P_CTW_CLR();
00725 p2p->oppps_status = P2P_OPPPS_TIMER_NOT_STARTED;
00726 p2p_update_go_ps_state(p2p);
00727 }
00728 else if (p2p->oppps_status == P2P_OPPPS_TIMER_WAIT_START_CTW)
00729 {
00730 PROF_P2P_CTW_SET();
00731 p2p->oppps_status = P2P_OPPPS_TIMER_WAIT_END_CTW;
00732 mm_timer_set(&p2p->oppps_timer, p2p->oppps_ctw_end);
00733 p2p_update_go_ps_state(p2p);
00734 }
00735 }
00736
00737 #if (NX_P2P_GO)
00738
00747 static void p2p_go_send_noa_upd_ind(struct p2p_info_tag *p2p, uint8_t noa_instance)
00748 {
00749 struct p2p_noa_info_tag *noa = &p2p->noa[noa_instance];
00750 struct mm_p2p_noa_upd_ind *ind = KE_MSG_ALLOC(MM_P2P_NOA_UPD_IND, TASK_API,
00751 TASK_MM, mm_p2p_noa_upd_ind);
00752
00753 ind->vif_index = p2p->vif_index;
00754 ind->noa_inst_nb = noa_instance;
00755 ind->count = (noa->noa_status != P2P_NOA_TIMER_NOT_STARTED) ? noa->noa_init_counter : 0;
00756
00757 if (ind->count)
00758 {
00759 ind->noa_type = noa->noa_type;
00760 ind->duration_us = noa->noa_dur_us;
00761 ind->interval_us = noa->noa_intv_us;
00762 ind->start_time = noa->noa_start_time;
00763 }
00764
00765
00766 ke_msg_send(ind);
00767 }
00768
00778 static uint8_t p2p_go_get_noa_inst(struct p2p_info_tag *p2p)
00779 {
00780 uint8_t noa_idx;
00781
00782 for (noa_idx = 0; noa_idx < P2P_NOA_NB_MAX; noa_idx++)
00783 {
00784 struct p2p_noa_info_tag *noa = &p2p->noa[noa_idx];
00785
00786
00787 if (noa->noa_status == P2P_NOA_TIMER_NOT_STARTED)
00788 {
00789 break;
00790 }
00791 }
00792
00793 return (noa_idx);
00794 }
00795
00806 __INLINE void p2p_go_noa_get_intv_cnt(struct p2p_noa_info_tag *noa)
00807 {
00808 if (noa->noa_intv_us == 0)
00809 return;
00810
00811
00812
00813
00814 noa->noa_time_upd_cnt = ((1 << 31) / noa->noa_intv_us) - 1;
00815 }
00816 #endif //(NX_P2P_GO)
00817
00833 static uint32_t p2p_cli_noa_get_abs_time(struct p2p_noa_info_tag *noa, uint8_t vif_index,
00834 uint32_t start_time, uint32_t tsf_peer)
00835 {
00836 struct vif_info_tag *vif = &vif_info_tab[vif_index];
00837 uint32_t absence_time;
00838 uint32_t missed_intv;
00839
00840 if (tsf_peer >= start_time)
00841 {
00842
00843 if (noa->noa_counter == 1)
00844 {
00845 return (0);
00846 }
00847
00848
00849 missed_intv = ((tsf_peer - start_time) / noa->noa_intv_us) + 1;
00850 }
00851 else
00852 {
00853 missed_intv = 0;
00854 }
00855
00856 TRACE_P2P(NOA_DET, "{VIF-%d} NoA startime=%ld, Peer's TSF=%ld => miss %d iteration",
00857 vif->index, TR_32(start_time), TR_32(tsf_peer), missed_intv);
00858
00859
00860 noa->peer_next_noa_time = start_time + (missed_intv * noa->noa_intv_us);
00861 absence_time = p2p_peer_2_local_time(vif, noa->peer_next_noa_time);
00862
00863 if (noa->noa_counter != P2P_NOA_CONTINUOUS_COUNTER)
00864 {
00865 noa->noa_counter -= co_min(missed_intv, noa->noa_counter);
00866 }
00867
00868
00869 while (hal_machw_time_past(absence_time) && noa->noa_counter)
00870 {
00871 absence_time += noa->noa_intv_us;
00872
00873 if (noa->noa_counter != P2P_NOA_CONTINUOUS_COUNTER)
00874 {
00875
00876 noa->noa_counter--;
00877 }
00878 }
00879
00880 if (!noa->noa_counter)
00881 {
00882
00883 return (0);
00884 }
00885
00886 TRACE_P2P(NOA_DET, "Next NOA iteration starts %t (TSF offset=%ld)",
00887 TR_32(absence_time), TR_32(vif->u.sta.last_tsf_offset));
00888
00889 return (absence_time);
00890 }
00891
00904 static bool p2p_cli_noa_start(struct p2p_noa_info_tag *noa, uint8_t vif_index,
00905 uint32_t start_time, uint32_t tsf_peer)
00906 {
00907 uint32_t first_abs_time;
00908 TRACE_P2P(NOA, "{VIF-%d} start NOA-%d: count=%d intv=%ld us, dur=%ld us",
00909 vif_index, noa->noa_inst, noa->noa_counter,
00910 TR_32(noa->noa_intv_us), TR_32(noa->noa_dur_us));
00911
00912 first_abs_time = p2p_cli_noa_get_abs_time(noa, vif_index, start_time, tsf_peer);
00913 if (first_abs_time)
00914 {
00915
00916 p2p_noa_timer_prog(noa, first_abs_time);
00917
00918 noa->noa_status = P2P_NOA_TIMER_WAIT_NEXT_ABS;
00919 }
00920
00921 return ((bool)first_abs_time);
00922 }
00923
00931 static void p2p_cli_noa_cancel(struct p2p_noa_info_tag *noa)
00932 {
00933 TRACE_P2P(NOA, "{VIF-%d} Cancel NOA-%d",
00934 p2p_info_tab[noa->p2p_index].vif_index, noa->noa_inst);
00935
00936 if (noa->noa_status != P2P_NOA_TIMER_NOT_STARTED)
00937 {
00938
00939 mm_timer_clear(&noa->noa_timer);
00940
00941
00942 noa->noa_status = P2P_NOA_TIMER_NOT_STARTED;
00943
00944 PROF_P2P_NOA_ABS_CLR(noa->noa_inst);
00945 }
00946 }
00947
00957 static void p2p_cli_noa_handle_att(uint8_t p2p_index,
00958 uint32_t a_noa_att,
00959 uint32_t tsf_peer)
00960 {
00961 struct p2p_info_tag *p2p = &p2p_info_tab[p2p_index];
00962 uint8_t noa_idx;
00963
00964 TRACE_P2P(NOA_DET, "{VIF-%d} NOA attribute present=%d", p2p->vif_index, (a_noa_att != 0));
00965
00966 if (a_noa_att)
00967 {
00968 uint8_t nb_noa_desc;
00969 uint8_t noa_index = co_read8p(a_noa_att + P2P_NOA_ATT_INDEX_OFT);
00970 uint16_t length;
00971 uint8_t ctw_oppps;
00972
00973 TRACE_P2P(NOA_DET, "index=%d, last index=%d", noa_index, p2p->noa_index);
00974
00975
00976 if (p2p->is_noa_bcn && (p2p->noa_index == noa_index))
00977 {
00978
00979 return;
00980 }
00981
00982
00983 p2p->is_noa_bcn = true;
00984 p2p->noa_index = noa_index;
00985
00986
00987 if (p2p->noa_nb)
00988 {
00989 for (noa_idx = 0; noa_idx < P2P_NOA_NB_MAX; noa_idx++)
00990 {
00991
00992 p2p_cli_noa_cancel(&p2p->noa[noa_idx]);
00993 p2p->noa_nb = 0;
00994 }
00995
00996
00997 p2p_update_go_ps_state(p2p);
00998 }
00999
01000
01001 length = co_read16p(a_noa_att + P2P_ATT_LEN_OFT);
01002 nb_noa_desc = (length - 2) / P2P_NOA_DESC_LENGTH;
01003
01004 for (noa_idx = 0; noa_idx < nb_noa_desc; noa_idx++)
01005 {
01006 struct p2p_noa_info_tag *noa = &p2p->noa[noa_idx];
01007
01008 uint32_t a_noa_desc = a_noa_att + P2P_NOA_ATT_NOA_DESC_OFT
01009 + (noa_idx * P2P_NOA_DESC_LENGTH);
01010
01011
01012 noa->noa_init_counter = co_read8p(a_noa_desc + P2P_NOA_DESC_COUNT_OFT);
01013
01014
01015 if (noa->noa_init_counter != 0)
01016 {
01017
01018 uint32_t noa_intv = co_read32p(a_noa_desc + P2P_NOA_DESC_INTV_OFT);
01019
01020
01021 if ((noa->noa_init_counter > 1) && !noa_intv)
01022 {
01023 continue;
01024 }
01025
01026
01027 noa->noa_dur_us = co_read32p(a_noa_desc + P2P_NOA_DESC_DUR_OFT);
01028 noa->noa_intv_us = noa_intv;
01029 noa->noa_counter = noa->noa_init_counter;
01030
01031
01032 if (p2p_cli_noa_start(noa, p2p->vif_index,
01033 co_read32p(a_noa_desc + P2P_NOA_DESC_START_OFT),
01034 tsf_peer))
01035 {
01036 p2p->noa_nb++;
01037 }
01038 }
01039 }
01040
01041 ctw_oppps = co_read8p(a_noa_att + P2P_NOA_ATT_CTW_OPPPS_OFT);
01042
01043
01044 if ((ctw_oppps & P2P_OPPPS_MASK) == P2P_OPPPS_MASK)
01045 {
01046
01047 p2p->oppps_ctw = ctw_oppps & P2P_CTWINDOW_MASK;
01048 TRACE_P2P(PS, "{VIF-%d} P2P GO configured a CTW of %d TU",
01049 p2p->vif_index, p2p->oppps_ctw)
01050 }
01051 else
01052 {
01053
01054 p2p->oppps_ctw = 0;
01055 }
01056 }
01057 else
01058 {
01059 p2p->is_noa_bcn = false;
01060
01061
01062 if (p2p->noa_nb)
01063 {
01064 for (noa_idx = 0; noa_idx < P2P_NOA_NB_MAX; noa_idx++)
01065 {
01066
01067 p2p_cli_noa_cancel(&p2p->noa[noa_idx]);
01068 p2p->noa_nb = 0;
01069 }
01070
01071 p2p_update_go_ps_state(p2p);
01072 }
01073
01074
01075 p2p->oppps_ctw = 0;
01076 }
01077 }
01078
01079
01080
01081
01082
01083
01084 void p2p_init(void)
01085 {
01086 uint8_t counter;
01087
01088 TRACE_P2P(ITF, "P2P init");
01089
01090 #if (NX_P2P_GO)
01091 memset(&p2p_env, 0, sizeof(struct p2p_env_tag));
01092 #endif //(NX_P2P_GO)
01093
01094
01095
01096 for (counter = 0; counter < NX_P2P_VIF_MAX; counter++)
01097 {
01098 struct p2p_info_tag *p2p = &p2p_info_tab[counter];
01099 p2p->vif_index = INVALID_VIF_IDX;
01100 }
01101 }
01102
01103 uint8_t p2p_create(uint8_t vif_index, uint8_t role)
01104 {
01105 uint8_t p2p_index = P2P_INVALID_IDX;
01106 uint8_t p2p_idx;
01107
01108
01109 for (p2p_idx = 0; p2p_idx < NX_P2P_VIF_MAX; p2p_idx++)
01110 {
01111 struct p2p_info_tag *p2p = &p2p_info_tab[p2p_idx];
01112
01113 if (p2p->vif_index == INVALID_VIF_IDX)
01114 {
01115 uint8_t noa_idx;
01116
01117
01118 memset(p2p, 0, sizeof(struct p2p_info_tag));
01119
01120
01121 p2p_index = p2p_idx;
01122
01123
01124 p2p->vif_index = vif_index;
01125 p2p->role = role;
01126
01127 #if (NX_P2P_GO)
01128 if (p2p->role == P2P_ROLE_GO)
01129 {
01130 p2p_env.nb_p2p_go++;
01131 }
01132 #endif //(NX_P2P_GO)
01133
01134
01135 for (noa_idx = 0; noa_idx < P2P_NOA_NB_MAX; noa_idx++)
01136 {
01137 struct p2p_noa_info_tag *noa = &p2p->noa[noa_idx];
01138
01139 noa->noa_timer.cb = p2p_noa_timer_end;
01140 noa->noa_timer.env = noa;
01141 noa->p2p_index = p2p_idx;
01142 noa->noa_inst = noa_idx;
01143 }
01144
01145
01146 p2p->oppps_timer.cb = p2p_oppps_timer_end;
01147 p2p->oppps_timer.env = p2p;
01148
01149
01150 p2p_update_go_ps_state(p2p);
01151
01152
01153 break;
01154 }
01155 }
01156
01157 TRACE_P2P(ITF, "CREATE: {VIF-%d} role=%d, p2p_idx=%d", vif_index, role, p2p_index);
01158
01159 return (p2p_index);
01160 }
01161
01162 void p2p_cancel(uint8_t p2p_index, bool vif_del)
01163 {
01164 struct p2p_info_tag *p2p = &p2p_info_tab[p2p_index];
01165
01166 TRACE_P2P(ITF, "DELETE: {VIF-%d} p2p_idx=%d", p2p->vif_index, p2p_index);
01167
01168
01169 if (p2p->vif_index != INVALID_VIF_IDX)
01170 {
01171
01172 if (p2p->is_waiting_bcn)
01173 {
01174 PROF_P2P_WAIT_BCN_CLR();
01175 }
01176
01177 #if (NX_P2P_GO)
01178 if (p2p->role == P2P_ROLE_GO)
01179 {
01180 p2p_env.nb_p2p_go--;
01181 }
01182 #endif //(NX_P2P_GO)
01183
01184 if (vif_del)
01185 {
01186
01187 p2p->vif_index = INVALID_VIF_IDX;
01188 }
01189 }
01190 }
01191
01192 void p2p_set_vif_state(struct vif_info_tag *vif, bool active)
01193 {
01194 struct p2p_info_tag *p2p;
01195
01196 if (!vif->p2p)
01197 {
01198 return;
01199 }
01200
01201 TRACE_P2P(ITF, "{VIF-%d} active=%d", vif->index, active);
01202
01203 p2p = &p2p_info_tab[vif->p2p_index];
01204
01205 if (vif->type == VIF_STA)
01206 {
01207 if (!active)
01208 {
01209 for (int noa_idx = 0; noa_idx < P2P_NOA_NB_MAX; noa_idx++)
01210 {
01211 p2p_cli_noa_cancel(&p2p->noa[noa_idx]);
01212 }
01213
01214 p2p->oppps_ctw = 0;
01215 p2p->noa_index = 0;
01216 p2p->is_noa_bcn = false;
01217
01218
01219 if (p2p->oppps_status != P2P_OPPPS_TIMER_NOT_STARTED)
01220 {
01221 mm_timer_clear(&p2p->oppps_timer);
01222 p2p->oppps_status = P2P_OPPPS_TIMER_NOT_STARTED;
01223 PROF_P2P_CTW_CLR();
01224 }
01225 p2p_update_go_ps_state(p2p);
01226 }
01227 }
01228 }
01229
01230 bool p2p_is_present(uint8_t p2p_index)
01231 {
01232 struct p2p_info_tag *p2p = &p2p_info_tab[p2p_index];
01233 return (p2p->is_go_present);
01234 }
01235
01236 bool p2p_go_get_next_NOA_date(struct vif_info_tag *vif,
01237 uint32_t *next_p2p_present,
01238 uint32_t *next_p2p_absent)
01239 {
01240 struct p2p_info_tag *p2p;
01241 ASSERT_ERR(vif->p2p);
01242
01243 p2p = &p2p_info_tab[vif->p2p_index];
01244 *next_p2p_present = p2p->next_present;
01245 *next_p2p_absent = p2p->next_absent;
01246
01247 return hal_machw_time_cmp(*next_p2p_absent, *next_p2p_present);
01248 }
01249
01250 uint32_t p2p_go_get_next_noa_end_date(struct vif_info_tag *vif,
01251 uint8_t noa_inst)
01252 {
01253 struct p2p_info_tag *p2p;
01254 struct p2p_noa_info_tag *noa;
01255 ASSERT_ERR(vif->p2p && (noa_inst < P2P_NOA_NB_MAX));
01256
01257 p2p = &p2p_info_tab[vif->p2p_index];
01258 noa = &p2p->noa[noa_inst];
01259
01260 switch (noa->noa_status)
01261 {
01262 case P2P_NOA_TIMER_WAIT_END_ABS:
01263 return noa->noa_timer.time;
01264 case P2P_NOA_TIMER_WAIT_NEXT_ABS:
01265 return noa->noa_timer.time + noa->noa_dur_us;
01266 default:
01267 ASSERT_WARN(0);
01268 }
01269
01270 return 0;
01271 }
01272
01273 void p2p_tbtt_handle(struct vif_info_tag *vif, uint32_t tbtt_time)
01274 {
01275 struct p2p_info_tag *p2p;
01276
01277 if (!vif->p2p)
01278 {
01279 return;
01280 }
01281 TRACE_P2P(TBTT, "{VIF-%d} TBTT starts", vif->index);
01282
01283 p2p = &p2p_info_tab[vif->p2p_index];
01284
01285 PROF_P2P_WAIT_BCN_SET();
01286
01287
01288 p2p->is_waiting_bcn = true;
01289 #if (NX_POWERSAVE)
01290 vif->prevent_sleep &= ~(PS_VIF_P2P_WAIT_TBTT);
01291 #endif //(NX_POWERSAVE)
01292
01293
01294 if (p2p->oppps_ctw)
01295 {
01296
01297 uint32_t ctw_end = tbtt_time + (p2p->oppps_ctw << 10);
01298
01299 if (p2p->role == P2P_ROLE_CLIENT)
01300 {
01301 tbtt_time += 300;
01302 if (hal_machw_time_cmp(ke_time() + 50, tbtt_time))
01303 {
01304
01305
01306 p2p->oppps_status = P2P_OPPPS_TIMER_WAIT_START_CTW;
01307 p2p->oppps_ctw_end = ctw_end;
01308 mm_timer_set(&p2p->oppps_timer, tbtt_time);
01309 return;
01310 }
01311 }
01312
01313 p2p->oppps_status = P2P_OPPPS_TIMER_WAIT_END_CTW;
01314 mm_timer_set(&p2p->oppps_timer, ctw_end);
01315 PROF_P2P_CTW_SET();
01316 }
01317
01318
01319 p2p_update_go_ps_state(p2p);
01320 }
01321
01322 void p2p_bcn_evt_handle(struct vif_info_tag *vif)
01323 {
01324 struct p2p_info_tag *p2p = &p2p_info_tab[vif->p2p_index];
01325
01326 TRACE_P2P(TBTT, "{VIF-%d} TBTT ends", vif->index);
01327 PROF_P2P_WAIT_BCN_CLR();
01328
01329
01330 p2p->is_waiting_bcn = false;
01331
01332
01333 p2p_update_go_ps_state(p2p);
01334 }
01335
01336 uint32_t p2p_cli_bcn_check_noa(struct vif_info_tag *vif,
01337 struct rx_pbd *pyld_desc, struct rx_dmadesc *dma_hdrdesc)
01338 {
01339 uint32_t noa_pos = 0;
01340 uint32_t rd_addr;
01341 uint32_t end_addr;
01342 struct bcn_frame *bcn;
01343
01344
01345 if ((!vif->p2p) || (vif->type != VIF_STA))
01346 {
01347 return noa_pos;
01348 }
01349
01350 ASSERT_ERR(vif->p2p_index < NX_P2P_VIF_MAX);
01351 TRACE_P2P(NOA_DET, "{VIF-%d} Check for NOA attribute in beacon", vif->index);
01352
01353 rd_addr = pyld_desc->datastartptr + MAC_BEACON_VARIABLE_PART_OFT;
01354 end_addr = rd_addr + dma_hdrdesc->hd.frmlen - MAC_BEACON_VARIABLE_PART_OFT;
01355
01356
01357 while (rd_addr < end_addr)
01358 {
01359
01360 uint32_t addr = rd_addr;
01361
01362 rd_addr += co_read8p(addr + MAC_INFOELT_LEN_OFT) + MAC_INFOELT_INFO_OFT;
01363
01364
01365 if (co_read8p(addr) != P2P_ELMT_ID)
01366 {
01367
01368 continue;
01369 }
01370
01371
01372 if (co_read8p(addr + P2P_IE_OUI_TYPE_OFT) != P2P_OUI_TYPE_P2P)
01373 {
01374
01375 continue;
01376 }
01377
01378
01379 noa_pos = p2p_att_find(addr + P2P_IE_ATT_OFT,
01380 co_read8p(addr + P2P_IE_LEN_OFT) - 4,
01381 P2P_ATT_ID_NOTICE_OF_ABSENCE);
01382
01383 if (!noa_pos)
01384 {
01385
01386 continue;
01387 }
01388
01389 break;
01390 }
01391
01392
01393 bcn = (struct bcn_frame *)HW2CPU(
01394 ((struct rx_pbd *)HW2CPU(dma_hdrdesc->hd.first_pbd_ptr))->datastartptr);
01395
01396 p2p_cli_noa_handle_att(vif->p2p_index, noa_pos, bcn->tsf);
01397
01398 return (noa_pos);
01399 }
01400
01401 void p2p_cli_handle_action(struct vif_info_tag *vif, uint32_t a_frame, uint16_t length,
01402 uint32_t rx_tsf)
01403 {
01404 uint32_t addr = a_frame + MAC_SHORT_MAC_HDR_LEN;
01405 uint16_t len = length - MAC_SHORT_MAC_HDR_LEN;
01406
01407 TRACE_P2P(NOA_DET, "{VIF-%d} check for NOA attribute in P2P action frame", vif->index);
01408
01409
01410 if (co_read8p(addr + MAC_ACTION_CATEGORY_OFT) != MAC_VENDOR_ACTION_CATEGORY)
01411 {
01412 return;
01413 }
01414
01415
01416 if (co_read8p(addr + MAC_ACTION_P2P_ACTION_OFT) == MAC_P2P_ACTION_NOA_SUBTYPE)
01417 {
01418
01419 addr += MAC_ACTION_P2P_TAGGED_OFT;
01420 len -= MAC_ACTION_P2P_TAGGED_OFT;
01421
01422
01423 if (co_read8p(addr + P2P_IE_ID_OFT) != P2P_ELMT_ID)
01424 {
01425 return;
01426 }
01427
01428
01429 if (co_read8p(addr + P2P_IE_OUI_TYPE_OFT) != P2P_OUI_TYPE_P2P)
01430 {
01431 return;
01432 }
01433
01434 if (co_read8p(addr + P2P_IE_ATT_OFT) != P2P_ATT_ID_NOTICE_OF_ABSENCE)
01435 {
01436 return;
01437 }
01438
01439
01440 p2p_cli_noa_handle_att(vif->p2p_index, addr + P2P_IE_ATT_OFT,
01441 p2p_local_2_peer_time(vif, rx_tsf));
01442 }
01443 }
01444
01445
01446
01447
01448
01449
01450
01451 #if (NX_P2P_GO)
01452 #if (NX_POWERSAVE)
01453 bool p2p_go_check_ps_mode(void)
01454 {
01455
01456
01457
01458
01459
01460 struct vif_info_tag *vif;
01461
01462
01463 if (!p2p_env.nb_p2p_go)
01464 {
01465 return false;
01466 }
01467
01468
01469 #if (NX_MULTI_ROLE)
01470 if (vif_mgmt_env.vif_sta_cnt || (vif_mgmt_env.vif_ap_cnt > 1))
01471 {
01472 return false;
01473 }
01474 #endif //(NX_MULTI_ROLE)
01475
01476 vif = (struct vif_info_tag *)co_list_pick(&vif_mgmt_env.used_list);
01477
01478 while (vif)
01479 {
01480 if ((vif->type == VIF_AP) && vif->p2p)
01481 {
01482 struct p2p_info_tag *p2p = &p2p_info_tab[vif->p2p_index];
01483
01484
01485 return ! p2p->is_go_present;
01486 }
01487
01488 vif = (struct vif_info_tag *)vif_mgmt_next(vif);
01489 }
01490
01491 return false;
01492 }
01493 #endif //(NX_POWERSAVE)
01494
01495 void p2p_go_td_evt(uint8_t vif_index, uint8_t new_status)
01496 {
01497 struct vif_info_tag *vif = &vif_info_tab[vif_index];
01498
01499 if (vif->p2p && (vif->type == VIF_AP))
01500 {
01501 struct p2p_info_tag *p2p = &p2p_info_tab[vif->p2p_index];
01502
01503 if (new_status)
01504 {
01505 PROF_P2P_PS_PAUSED_SET();
01506 p2p->noa_paused = true;
01507 }
01508 else
01509 {
01510 PROF_P2P_PS_PAUSED_CLR();
01511 p2p->noa_paused = false;
01512 }
01513
01514 if (p2p->is_noa_bcn)
01515 {
01516
01517 mm_bcn_update_p2p_noa(p2p->vif_index, P2P_BCN_UPD_OP_NOA_UPD);
01518 }
01519
01520 p2p_update_go_ps_state(p2p);
01521 }
01522 }
01523
01524 void p2p_go_oppps_start(struct vif_info_tag *vif, uint8_t ctw)
01525 {
01526 struct p2p_info_tag *p2p = &p2p_info_tab[vif->p2p_index];
01527
01528 TRACE_P2P(PS, "{VIF-%d} start oppPS CTW=%d TU", vif->index, ctw);
01529
01530
01531 p2p->oppps_ctw = ctw;
01532
01533 p2p->oppps_status = P2P_OPPPS_TIMER_WAIT_END_CTW;
01534
01535
01536 mm_bcn_update_p2p_noa(p2p->vif_index, P2P_BCN_UPD_OP_NOA_UPD);
01537
01538
01539 p2p_update_go_ps_state(p2p);
01540 }
01541
01542 void p2p_go_oppps_stop(struct vif_info_tag *vif)
01543 {
01544 struct p2p_info_tag *p2p = &p2p_info_tab[vif->p2p_index];
01545
01546 TRACE_P2P(PS, "{VIF-%d} stop oppPS", vif->index);
01547
01548
01549 p2p->oppps_ctw = 0;
01550 if (p2p->oppps_status != P2P_OPPPS_TIMER_NOT_STARTED)
01551 {
01552 mm_timer_clear(&p2p->oppps_timer);
01553 p2p->oppps_status = P2P_OPPPS_TIMER_NOT_STARTED;
01554 PROF_P2P_CTW_CLR();
01555 }
01556 p2p_update_go_ps_state(p2p);
01557
01558 if (!p2p->noa_nb)
01559 {
01560
01561 mm_bcn_update_p2p_noa(p2p->vif_index, P2P_BCN_UPD_OP_NOA_RMV);
01562 }
01563 else
01564 {
01565
01566 mm_bcn_update_p2p_noa(p2p->vif_index, P2P_BCN_UPD_OP_NOA_UPD);
01567 }
01568 }
01569
01570 void p2p_go_ps_state_update(struct vif_info_tag *vif)
01571 {
01572 if (!vif->p2p)
01573 {
01574 return;
01575 }
01576
01577 TRACE_P2P(PS, "{VIF-%d} update GO PS state", vif->index);
01578 p2p_update_go_ps_state(&p2p_info_tab[vif->p2p_index]);
01579 }
01580
01581 uint8_t p2p_go_noa_start(struct vif_info_tag *vif, bool concurrent, bool dyn_noa,
01582 uint8_t counter, uint32_t intv_us, uint32_t dur_us,
01583 uint32_t start_time)
01584 {
01585 struct p2p_info_tag *p2p = &p2p_info_tab[vif->p2p_index];
01586 struct p2p_noa_info_tag *noa;
01587 uint8_t noa_inst = P2P_NOA_NB_MAX;
01588
01589 if (p2p->role != P2P_ROLE_GO)
01590 return P2P_INVALID_IDX;
01591
01592 noa_inst = p2p_go_get_noa_inst(p2p);
01593
01594 TRACE_P2P(NOA, "{VIF-%d} start NOA-%d: count=%d, intv=%ld us, dur=%ld us, start %t",
01595 vif->index, noa_inst, counter, TR_32(intv_us), TR_32(dur_us),
01596 TR_32(start_time));
01597
01598 if (noa_inst >= P2P_NOA_NB_MAX)
01599 return P2P_INVALID_IDX;
01600
01601 noa = &p2p->noa[noa_inst];
01602
01603
01604 noa->noa_counter = counter;
01605 noa->noa_init_counter = counter;
01606 noa->noa_intv_us = intv_us;
01607 noa->noa_dur_us = dur_us;
01608 noa->noa_start_time = start_time;
01609 noa->dyn_noa = dyn_noa;
01610 noa->noa_type = (concurrent) ? P2P_NOA_TYPE_CONCURRENT : P2P_NOA_TYPE_NORMAL;
01611
01612 p2p->noa_nb++;
01613
01614 if (concurrent)
01615 {
01616 p2p->noa_cm_nb++;
01617 }
01618
01619
01620 p2p_go_noa_get_intv_cnt(noa);
01621
01622
01623 p2p_noa_timer_prog(noa, noa->noa_start_time);
01624
01625 noa->noa_status = P2P_NOA_TIMER_WAIT_NEXT_ABS;
01626
01627
01628 mm_bcn_update_p2p_noa(p2p->vif_index, P2P_BCN_UPD_OP_NOA_UPD);
01629
01630
01631 p2p_go_send_noa_upd_ind(p2p, noa_inst);
01632
01633 p2p_update_noa_presence_date(p2p);
01634
01635
01636 p2p_update_go_ps_state(p2p);
01637
01638 return noa_inst;
01639 }
01640
01641 uint8_t p2p_go_noa_stop(struct vif_info_tag *vif, uint8_t noa_inst, bool host_req)
01642 {
01643 struct p2p_info_tag *p2p = &p2p_info_tab[vif->p2p_index];
01644 struct p2p_noa_info_tag *noa;
01645
01646 if ((p2p->role != P2P_ROLE_GO) || (noa_inst >= P2P_NOA_NB_MAX))
01647 {
01648 return CO_FAIL;
01649 }
01650
01651 TRACE_P2P(NOA, "{VIF-%d} stop NOA-%d (host_req=%d)", vif->index, noa_inst, host_req);
01652
01653 noa = &p2p->noa[noa_inst];
01654 if ((noa->noa_status == P2P_NOA_TIMER_NOT_STARTED) ||
01655 (host_req && (noa->noa_type == P2P_NOA_TYPE_CONCURRENT)))
01656 {
01657 return CO_FAIL;
01658 }
01659
01660
01661 PROF_P2P_NOA_ABS_CLR(noa->noa_inst);
01662 mm_timer_clear(&noa->noa_timer);
01663 noa->noa_status = P2P_NOA_TIMER_NOT_STARTED;
01664 p2p_update_noa_presence_date(p2p);
01665 p2p_update_go_ps_state(p2p);
01666 p2p->noa_nb--;
01667 if (noa->noa_type == P2P_NOA_TYPE_NORMAL)
01668 {
01669 p2p->noa_cm_nb--;
01670 }
01671
01672 if ((p2p->oppps_ctw == 0) && (p2p->noa_nb == 0))
01673 {
01674
01675 mm_bcn_update_p2p_noa(p2p->vif_index, P2P_BCN_UPD_OP_NOA_RMV);
01676 }
01677 else
01678 {
01679
01680 mm_bcn_update_p2p_noa(p2p->vif_index, P2P_BCN_UPD_OP_NOA_UPD);
01681 }
01682
01683
01684 p2p_go_send_noa_upd_ind(p2p, noa_inst);
01685
01686 return CO_OK;
01687 }
01688
01689 #if (NX_CHNL_CTXT)
01690 void p2p_go_noa_concurrent_move(struct vif_info_tag *vif, int32_t offset)
01691 {
01692 struct p2p_info_tag *p2p = &p2p_info_tab[vif->p2p_index];
01693 bool update_date = false;
01694 uint8_t noa_idx;
01695
01696 for (noa_idx = 0; noa_idx < P2P_NOA_NB_MAX; noa_idx++)
01697 {
01698 struct p2p_noa_info_tag *noa = &p2p->noa[noa_idx];
01699 if ((noa->noa_type == P2P_NOA_TYPE_CONCURRENT) &&
01700 (noa->noa_status != P2P_NOA_TIMER_NOT_STARTED))
01701 {
01702 p2p_noa_timer_prog(noa, noa->noa_timer.time + offset);
01703 update_date = true;
01704 }
01705 }
01706
01707 if (update_date)
01708 p2p_update_noa_presence_date(p2p);
01709 }
01710 #endif //(NX_CHNL_CTXT)
01711
01712 uint8_t p2p_go_bcn_get_noa_len(uint8_t p2p_index)
01713 {
01714 struct p2p_info_tag *p2p = &p2p_info_tab[p2p_index];
01715 uint8_t noa_ie_len = 0;
01716
01717 if ((p2p->vif_index != INVALID_VIF_IDX) && p2p->is_noa_bcn)
01718 {
01719 noa_ie_len = P2P_IE_NOA_NO_NOA_DESC_LENGTH
01720 + p2p->noa_in_bcn_nb * P2P_NOA_DESC_LENGTH;
01721 }
01722
01723 return (noa_ie_len);
01724 }
01725
01726 void p2p_go_bcn_init_noa_pyld(uint32_t a_noa_ie_elt)
01727 {
01728 co_write8p(a_noa_ie_elt + P2P_IE_ID_OFT, P2P_ELMT_ID);
01729 co_write8p(a_noa_ie_elt + P2P_IE_OUI_OFT, P2P_OUI_WIFI_ALL_BYTE0);
01730 co_write8p(a_noa_ie_elt + P2P_IE_OUI_OFT + 1, P2P_OUI_WIFI_ALL_BYTE1);
01731 co_write8p(a_noa_ie_elt + P2P_IE_OUI_OFT + 2, P2P_OUI_WIFI_ALL_BYTE2);
01732 co_write8p(a_noa_ie_elt + P2P_IE_OUI_TYPE_OFT, P2P_OUI_TYPE_P2P);
01733 co_write8p(a_noa_ie_elt + P2P_IE_ATT_OFT, P2P_ATT_ID_NOTICE_OF_ABSENCE);
01734 }
01735
01736 void p2p_go_bcn_upd_noa_pyld(uint8_t p2p_index, uint32_t a_noa_ie_elt)
01737 {
01738 struct p2p_info_tag *p2p = &p2p_info_tab[p2p_index];
01739 uint8_t noa_idx, noa_proc_nb = 0;
01740 uint16_t att_length;
01741
01742 TRACE_P2P(NOA_DET, "{VIF-%d} update NOA payload in beacon", p2p->vif_index);
01743
01744 co_write8p(a_noa_ie_elt + P2P_IE_ATT_OFT + P2P_NOA_ATT_INDEX_OFT, p2p->noa_index);
01745
01746
01747 p2p->noa_index++;
01748
01749 if (p2p->oppps_ctw)
01750 {
01751
01752 co_write8p(a_noa_ie_elt + P2P_IE_ATT_OFT + P2P_NOA_ATT_CTW_OPPPS_OFT,
01753 p2p->oppps_ctw | P2P_OPPPS_MASK);
01754 }
01755 else
01756 {
01757 co_write8p(a_noa_ie_elt + P2P_IE_ATT_OFT + P2P_NOA_ATT_CTW_OPPPS_OFT, 0);
01758 }
01759
01760 for (noa_idx = 0; noa_idx < P2P_NOA_NB_MAX; noa_idx++)
01761 {
01762 struct p2p_noa_info_tag *noa = &p2p->noa[noa_idx];
01763
01764
01765
01766 if ((noa->noa_status != P2P_NOA_TIMER_NOT_STARTED) &&
01767 !(p2p->noa_paused && noa->dyn_noa && (noa->noa_type == P2P_NOA_TYPE_NORMAL)))
01768 {
01769 uint32_t a_noa_desc = a_noa_ie_elt + P2P_IE_ATT_OFT + P2P_NOA_ATT_NOA_DESC_OFT
01770 + (P2P_NOA_DESC_LENGTH * noa_idx);
01771
01772 noa_proc_nb++;
01773
01774 co_write8p(a_noa_desc + P2P_NOA_DESC_COUNT_OFT, noa->noa_init_counter);
01775 co_write32p(a_noa_desc + P2P_NOA_DESC_DUR_OFT, noa->noa_dur_us);
01776 co_write32p(a_noa_desc + P2P_NOA_DESC_INTV_OFT, noa->noa_intv_us);
01777
01778
01779
01780
01781 co_write32p(a_noa_desc + P2P_NOA_DESC_START_OFT,
01782 noa->noa_start_time - (ke_time() - nxmac_tsf_lo_get()));
01783 }
01784 }
01785
01786
01787 p2p->noa_in_bcn_nb = noa_proc_nb;
01788
01789
01790 att_length = 2 + noa_proc_nb * P2P_NOA_DESC_LENGTH;
01791
01792 co_write16p(a_noa_ie_elt + P2P_IE_ATT_OFT + P2P_ATT_LEN_OFT, att_length);
01793 co_write8p(a_noa_ie_elt + P2P_IE_LEN_OFT, 7 + (uint8_t)att_length);
01794 }
01795
01796 void p2p_go_bcn_op_done(uint8_t p2p_index, uint8_t operation)
01797 {
01798 struct p2p_info_tag *p2p = &p2p_info_tab[p2p_index];
01799
01800 TRACE_P2P(NOA_DET, "{VIF-%d} Beacon updated operation=%d",
01801 p2p->vif_index, operation);
01802
01803 switch (operation)
01804 {
01805 case (P2P_BCN_UPD_OP_NOA_ADD):
01806 {
01807 p2p->is_noa_bcn = true;
01808 } break;
01809
01810 case (P2P_BCN_UPD_OP_NOA_RMV):
01811 {
01812 p2p->is_noa_bcn = false;
01813 } break;
01814
01815 case (P2P_BCN_UPD_OP_NOA_UPD):
01816 {
01817
01818 if (!p2p->is_noa_bcn)
01819 {
01820 mm_bcn_update_p2p_noa(p2p->vif_index, P2P_BCN_UPD_OP_NOA_ADD);
01821 }
01822
01823 } break;
01824
01825 default:
01826 {
01827 ASSERT_ERR(0);
01828 }
01829 }
01830 }
01831
01832 #if (NX_POWERSAVE)
01833 void p2p_go_pre_tbtt(struct vif_info_tag *vif)
01834 {
01835
01836 if (vif->p2p && vif->active)
01837 {
01838
01839
01840
01841 vif->prevent_sleep |= PS_VIF_P2P_WAIT_TBTT;
01842 }
01843 }
01844 #endif //(NX_POWERSAVE)
01845 #endif //(NX_P2P_GO)
01846
01847 #endif //(NX_P2P)
01848