mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Update wifi driver for rda target UNO_91H
							parent
							
								
									46603f831e
								
							
						
					
					
						commit
						d6730f5afc
					
				| 
						 | 
					@ -159,8 +159,12 @@ nsapi_error_t RDAWiFiInterface::disconnect()
 | 
				
			||||||
    if(sta_state < 2) {
 | 
					    if(sta_state < 2) {
 | 
				
			||||||
        return NSAPI_ERROR_NO_CONNECTION;
 | 
					        return NSAPI_ERROR_NO_CONNECTION;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    void* wifi_disconnect_sem = rda_sem_create(0);
 | 
				
			||||||
    msg.type = WLAND_DISCONNECT;
 | 
					    msg.type = WLAND_DISCONNECT;
 | 
				
			||||||
 | 
					    msg.arg1 = (unsigned int)wifi_disconnect_sem;
 | 
				
			||||||
    rda_mail_put(wland_msgQ, (void*)&msg, osWaitForever);
 | 
					    rda_mail_put(wland_msgQ, (void*)&msg, osWaitForever);
 | 
				
			||||||
 | 
					    rda_sem_wait(wifi_disconnect_sem, osWaitForever);
 | 
				
			||||||
 | 
					    rda_sem_delete(wifi_disconnect_sem);
 | 
				
			||||||
    if (_interface) {
 | 
					    if (_interface) {
 | 
				
			||||||
        return _interface->bringdown();
 | 
					        return _interface->bringdown();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,6 +88,7 @@ typedef struct {
 | 
				
			||||||
    void (*mbed_critical_sec_end)(void);
 | 
					    void (*mbed_critical_sec_end)(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Create interrupt in mbed, input param: vector/priority/isr(function), */
 | 
					    /* Create interrupt in mbed, input param: vector/priority/isr(function), */
 | 
				
			||||||
 | 
					    unsigned int (*mbed_critical_sec_counter_get)(void);
 | 
				
			||||||
    /* return: interrupt handle, non-zero is valid                           */
 | 
					    /* return: interrupt handle, non-zero is valid                           */
 | 
				
			||||||
    void * (*mbed_create_interrupt)(unsigned int vec, unsigned int pri, void *isr);
 | 
					    void * (*mbed_create_interrupt)(unsigned int vec, unsigned int pri, void *isr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,6 +52,7 @@ typedef enum {
 | 
				
			||||||
    WLAND_STAJOINED,
 | 
					    WLAND_STAJOINED,
 | 
				
			||||||
    WLAND_STAEXITED,
 | 
					    WLAND_STAEXITED,
 | 
				
			||||||
    WLAND_STADEAUTH,
 | 
					    WLAND_STADEAUTH,
 | 
				
			||||||
 | 
					    WLAND_STADELETETIMER,
 | 
				
			||||||
    WLAND_MAC_CONNECTED,
 | 
					    WLAND_MAC_CONNECTED,
 | 
				
			||||||
    WLAND_MAC_AP_CONNECTED,
 | 
					    WLAND_MAC_AP_CONNECTED,
 | 
				
			||||||
    WLAND_ADD_GTK,
 | 
					    WLAND_ADD_GTK,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
					@ -45,7 +45,7 @@
 | 
				
			||||||
 * Variables
 | 
					 * Variables
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int maclib_task_run = 0;
 | 
					static int maclib_task_run = 0;
 | 
				
			||||||
static sys_mbox_t maclib_mbox;
 | 
					static void* maclib_mbox;
 | 
				
			||||||
static int g_event_num = 0;
 | 
					static int g_event_num = 0;
 | 
				
			||||||
static int g_event_proc_done = 1;
 | 
					static int g_event_proc_done = 1;
 | 
				
			||||||
static sys_sem_t g_maclib_sem_sleep;
 | 
					static sys_sem_t g_maclib_sem_sleep;
 | 
				
			||||||
| 
						 | 
					@ -56,55 +56,13 @@ extern maclib_func_t *maclib_func_p;
 | 
				
			||||||
extern void rda_critical_sec_start(void);
 | 
					extern void rda_critical_sec_start(void);
 | 
				
			||||||
extern void rda_critical_sec_end(void);
 | 
					extern void rda_critical_sec_end(void);
 | 
				
			||||||
extern void wland_set_sta_sleep(unsigned char is_sleep);
 | 
					extern void wland_set_sta_sleep(unsigned char is_sleep);
 | 
				
			||||||
 | 
					 | 
				
			||||||
#define MAX_MSG_POOL_NUM    (64)
 | 
					 | 
				
			||||||
maclib_msg_t msg_str_pool[MAX_MSG_POOL_NUM];
 | 
					 | 
				
			||||||
int msg_str_pool_inited = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void init_msg_str_pool(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    int idx;
 | 
					 | 
				
			||||||
    for(idx = 0; idx < MAX_MSG_POOL_NUM; idx++) {
 | 
					 | 
				
			||||||
        msg_str_pool[idx].is_free = 1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
maclib_msg_t *alloc_msg_str(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    int idx;
 | 
					 | 
				
			||||||
    maclib_msg_t *ret = NULL;
 | 
					 | 
				
			||||||
    rda_critical_sec_start();
 | 
					 | 
				
			||||||
    if (0 == msg_str_pool_inited) {
 | 
					 | 
				
			||||||
        init_msg_str_pool();
 | 
					 | 
				
			||||||
        msg_str_pool_inited = 1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    rda_critical_sec_end();
 | 
					 | 
				
			||||||
    for (idx = 0; idx < MAX_MSG_POOL_NUM; idx++) {
 | 
					 | 
				
			||||||
        rda_critical_sec_start();
 | 
					 | 
				
			||||||
        ret = &msg_str_pool[idx];
 | 
					 | 
				
			||||||
        if (1 == ret->is_free) {
 | 
					 | 
				
			||||||
            ret->is_free = 0;
 | 
					 | 
				
			||||||
            rda_critical_sec_end();
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        rda_critical_sec_end();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void free_msg_str(maclib_msg_t *p_msg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    rda_critical_sec_start();
 | 
					 | 
				
			||||||
    p_msg->is_free = 1;
 | 
					 | 
				
			||||||
    rda_critical_sec_end();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Functions
 | 
					 * Functions
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
/* maybe called in isr, should not use "printf", "malloc" */
 | 
					/* maybe called in isr, should not use "printf", "malloc" */
 | 
				
			||||||
void mbed_event_handle_cb(unsigned int event)
 | 
					void mbed_event_handle_cb(unsigned int event)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    static unsigned int sec_cnt = 0;
 | 
				
			||||||
    MACLIB_EVENT_HANDLE_T type = (MACLIB_EVENT_HANDLE_T)event;
 | 
					    MACLIB_EVENT_HANDLE_T type = (MACLIB_EVENT_HANDLE_T)event;
 | 
				
			||||||
    if ((maclib_task_run == 0) && (MACLIB_EVENT_CLEANUP != type)) {
 | 
					    if ((maclib_task_run == 0) && (MACLIB_EVENT_CLEANUP != type)) {
 | 
				
			||||||
        mbed_error_printf("evntHndlCb_nulldata\r\n");
 | 
					        mbed_error_printf("evntHndlCb_nulldata\r\n");
 | 
				
			||||||
| 
						 | 
					@ -115,18 +73,13 @@ void mbed_event_handle_cb(unsigned int event)
 | 
				
			||||||
            rda_critical_sec_start();
 | 
					            rda_critical_sec_start();
 | 
				
			||||||
            g_event_num++;
 | 
					            g_event_num++;
 | 
				
			||||||
            if((1 == g_event_num) && (1 == g_event_proc_done)) {
 | 
					            if((1 == g_event_num) && (1 == g_event_proc_done)) {
 | 
				
			||||||
                maclib_msg_t *msg;
 | 
					                maclib_msg_t msg;
 | 
				
			||||||
#if MACLIB_TASK_DEBUG
 | 
					#if MACLIB_TASK_DEBUG
 | 
				
			||||||
                mbed_error_printf("#1-1,%d(%08X)\r\n", g_event_num, __get_xPSR());
 | 
					                mbed_error_printf("#1-1,%d(%08X)\r\n", g_event_num, __get_xPSR());
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
                msg = alloc_msg_str();
 | 
					                msg.type = MACLIB_MSG_EVNT_HNDL;
 | 
				
			||||||
                if(NULL == msg) {
 | 
					                msg.msg = NULL;
 | 
				
			||||||
                    mbed_error_printf("malloc err\r\n");
 | 
					                rda_mail_put(maclib_mbox, (void*)&msg, 0);
 | 
				
			||||||
                    return;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                msg->type = MACLIB_MSG_EVNT_HNDL;
 | 
					 | 
				
			||||||
                msg->msg = NULL;
 | 
					 | 
				
			||||||
                sys_mbox_trypost(&(maclib_mbox), msg);
 | 
					 | 
				
			||||||
#if MACLIB_TASK_DEBUG
 | 
					#if MACLIB_TASK_DEBUG
 | 
				
			||||||
                mbed_error_printf("#1-2\r\n");
 | 
					                mbed_error_printf("#1-2\r\n");
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -205,9 +158,9 @@ void maclib_task(void *pvParameters)
 | 
				
			||||||
    sys_sem_new(&g_maclib_sem_sleep, 0);
 | 
					    sys_sem_new(&g_maclib_sem_sleep, 0);
 | 
				
			||||||
    //sleep_entry_register(&maclib_sleep_entry);
 | 
					    //sleep_entry_register(&maclib_sleep_entry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = sys_mbox_new(&(maclib_mbox), 8);
 | 
					    maclib_mbox = (void *)rda_mail_create(8, sizeof(maclib_msg_t));//ret = sys_mbox_new(&(maclib_mbox), 8);
 | 
				
			||||||
    if(0 != ret) {
 | 
					    if(NULL == maclib_mbox) {
 | 
				
			||||||
        LWIP_DEBUGF(NETIF_DEBUG,"msgbox init err!\r\n");
 | 
					        mbed_error_printf("msgbox init err!\r\n");
 | 
				
			||||||
        goto mac_lib_err;
 | 
					        goto mac_lib_err;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
#if MACLIB_TASK_DEBUG
 | 
					#if MACLIB_TASK_DEBUG
 | 
				
			||||||
| 
						 | 
					@ -215,14 +168,13 @@ void maclib_task(void *pvParameters)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    maclib_task_run = 1;
 | 
					    maclib_task_run = 1;
 | 
				
			||||||
    while(1) {
 | 
					    while(1) {
 | 
				
			||||||
        int mem_free = 1;
 | 
					        maclib_msg_t msg;
 | 
				
			||||||
        maclib_msg_t *msg = NULL;
 | 
					        osStatus_t status = rda_mail_get(maclib_mbox, (void *)&msg, osWaitForever);
 | 
				
			||||||
        unsigned int time = sys_arch_mbox_fetch(&(maclib_mbox), (void **)&msg, 0);
 | 
					        if(osOK != status) {
 | 
				
			||||||
        if ((SYS_ARCH_TIMEOUT == time) || (NULL == msg)) {
 | 
					            mbed_error_printf("ml_task: invalid msg ret=%08X\r\n", status);
 | 
				
			||||||
            LWIP_DEBUGF(NETIF_DEBUG, "ml_task: invalid msg\r\n");
 | 
					 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        switch(msg->type) {
 | 
					        switch(msg.type) {
 | 
				
			||||||
            case MACLIB_MSG_EVNT_HNDL: {
 | 
					            case MACLIB_MSG_EVNT_HNDL: {
 | 
				
			||||||
                rda_critical_sec_start();
 | 
					                rda_critical_sec_start();
 | 
				
			||||||
                g_event_proc_done = 0;
 | 
					                g_event_proc_done = 0;
 | 
				
			||||||
| 
						 | 
					@ -246,11 +198,10 @@ void maclib_task(void *pvParameters)
 | 
				
			||||||
#if MACLIB_TASK_DEBUG
 | 
					#if MACLIB_TASK_DEBUG
 | 
				
			||||||
                    mbed_error_printf("#2-1\r\n");
 | 
					                    mbed_error_printf("#2-1\r\n");
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
                    sys_mbox_trypost(&(maclib_mbox), msg);
 | 
					                    rda_mail_put(maclib_mbox, (void*)&msg, 0);
 | 
				
			||||||
#if MACLIB_TASK_DEBUG
 | 
					#if MACLIB_TASK_DEBUG
 | 
				
			||||||
                    mbed_error_printf("#2-2\r\n");
 | 
					                    mbed_error_printf("#2-2\r\n");
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
                    mem_free = 0;
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                rda_critical_sec_end();
 | 
					                rda_critical_sec_end();
 | 
				
			||||||
#if MACLIB_TASK_DEBUG
 | 
					#if MACLIB_TASK_DEBUG
 | 
				
			||||||
| 
						 | 
					@ -261,12 +212,9 @@ void maclib_task(void *pvParameters)
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (mem_free) {
 | 
					 | 
				
			||||||
            free_msg_str(msg);
 | 
					 | 
				
			||||||
#if MACLIB_TASK_DEBUG
 | 
					#if MACLIB_TASK_DEBUG
 | 
				
			||||||
            mbed_error_printf("#4\r\n");
 | 
					            mbed_error_printf("#4\r\n");
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mac_lib_err:
 | 
					mac_lib_err:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -110,7 +110,7 @@ void rda_netif_link_down(int netif)
 | 
				
			||||||
    rda_msg msg;
 | 
					    rda_msg msg;
 | 
				
			||||||
    msg.type = 1;
 | 
					    msg.type = 1;
 | 
				
			||||||
    msg.arg1 = 0;
 | 
					    msg.arg1 = 0;
 | 
				
			||||||
    rda_mail_put(packet_rx_queue, (void*)&msg, osWaitForever);
 | 
					    rda_mail_put(packet_rx_queue, (void*)&msg, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void rda_netif_up(int netif)
 | 
					void rda_netif_up(int netif)
 | 
				
			||||||
| 
						 | 
					@ -127,7 +127,7 @@ void rda_netif_link_up(int netif)
 | 
				
			||||||
    rda_msg msg;
 | 
					    rda_msg msg;
 | 
				
			||||||
    msg.type = 1;
 | 
					    msg.type = 1;
 | 
				
			||||||
    msg.arg1 = 1;
 | 
					    msg.arg1 = 1;
 | 
				
			||||||
    rda_mail_put(packet_rx_queue, (void*)&msg, osWaitForever);
 | 
					    rda_mail_put(packet_rx_queue, (void*)&msg, 0);
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -181,6 +181,32 @@ void rda_critical_sec_end(void)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned int rda_critical_sec_counter_get(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (__get_IPSR() == 0U) {
 | 
				
			||||||
 | 
					        return g_critical_sec_counter;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return 0xFFFFFFFF;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rda_critical_sec_start_resume(unsigned int cnt)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    unsigned int i = 0;
 | 
				
			||||||
 | 
					    for(i=0; i<cnt; i++) {
 | 
				
			||||||
 | 
					        rda_critical_sec_start();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned int rda_critical_sec_end_all(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    unsigned int ret = g_critical_sec_counter;
 | 
				
			||||||
 | 
					    while(g_critical_sec_counter !=0 ) {
 | 
				
			||||||
 | 
					        rda_critical_sec_end();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void * rda_create_interrupt(unsigned int vec, unsigned int pri, void *isr)
 | 
					void * rda_create_interrupt(unsigned int vec, unsigned int pri, void *isr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    NVIC_SetPriority((IRQn_Type)vec, (uint32_t) pri);
 | 
					    NVIC_SetPriority((IRQn_Type)vec, (uint32_t) pri);
 | 
				
			||||||
| 
						 | 
					@ -278,18 +304,13 @@ static struct pbuf *r91h_low_level_input(struct netif *netif, u8_t *data, u32_t
 | 
				
			||||||
 *  \param[in] netif the lwip network interface structure
 | 
					 *  \param[in] netif the lwip network interface structure
 | 
				
			||||||
 *  \param[in] idx   index of packet to be read
 | 
					 *  \param[in] idx   index of packet to be read
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void *data_sem = NULL;
 | 
					 | 
				
			||||||
void r91h_wifiif_input(struct netif *netif, u8_t *data, u32_t len, int idx)
 | 
					void r91h_wifiif_input(struct netif *netif, u8_t *data, u32_t len, int idx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(data_sem == NULL)
 | 
					 | 
				
			||||||
        data_sem = rda_sem_create(0);
 | 
					 | 
				
			||||||
    rda_msg msg;
 | 
					    rda_msg msg;
 | 
				
			||||||
    msg.type = 0;
 | 
					    msg.type = 0;
 | 
				
			||||||
    msg.arg1 = (int)data;
 | 
					    msg.arg1 = (int)data;
 | 
				
			||||||
    msg.arg2 = len;
 | 
					    msg.arg2 = len;
 | 
				
			||||||
    msg.arg3 = (int)data_sem;
 | 
					    rda_mail_put(packet_rx_queue, (void*)&msg, 0);
 | 
				
			||||||
    rda_mail_put(packet_rx_queue, (void*)&msg, osWaitForever);
 | 
					 | 
				
			||||||
    rda_sem_wait(data_sem, osWaitForever);
 | 
					 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -239,10 +239,13 @@ int rda_alarm_stop(void *handle)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (NULL != handle) {
 | 
					    if (NULL != handle) {
 | 
				
			||||||
        osTimerId timer_id = (osTimerId)handle;
 | 
					        osTimerId timer_id = (osTimerId)handle;
 | 
				
			||||||
        osStatus retval = osTimerStop(timer_id);
 | 
					        os_timer_t *timer = osRtxTimerId(timer_id);
 | 
				
			||||||
        if (osOK != retval) {
 | 
					        if(timer->state == osRtxTimerRunning){
 | 
				
			||||||
            RDA_SYS_PRINT("Stop alarm error: %d\r\n", retval);
 | 
					            osStatus retval = osTimerStop(timer_id);
 | 
				
			||||||
            return ERR;
 | 
					            if(osOK != retval) {
 | 
				
			||||||
 | 
					                RDA_SYS_PRINT("Stop alarm error: %d\r\n", retval);
 | 
				
			||||||
 | 
					                return ERR;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return NO_ERR;
 | 
					        return NO_ERR;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -172,10 +172,8 @@ void RDA5981x_EMAC::packet_rx()
 | 
				
			||||||
            case 0:
 | 
					            case 0:
 | 
				
			||||||
                p = low_level_input((unsigned char*)msg.arg1, msg.arg2);
 | 
					                p = low_level_input((unsigned char*)msg.arg1, msg.arg2);
 | 
				
			||||||
                if (p == NULL) {
 | 
					                if (p == NULL) {
 | 
				
			||||||
                    rda_sem_release((void*)msg.arg3);
 | 
					 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                rda_sem_release((void*)msg.arg3);
 | 
					 | 
				
			||||||
                if (p) {
 | 
					                if (p) {
 | 
				
			||||||
                    emac_link_input_cb(p);
 | 
					                    emac_link_input_cb(p);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue