/*------------------------------------------------------------------ * Func : mars_scd_work * * Desc : mars scd work routine * * Parm : p_this : handle of mars cec * * Retn : N/A *------------------------------------------------------------------*/ void mars_scd_work(mars_scd* p_this) { unsigned char id = p_this->id; unsigned long status = GET_SCIRSR(id); SC_INFO("SC%d - work!!\n", p_this->id); if (status & SC_CPRES_INT) { if (mars_scd_card_detect(p_this)) SC_INFO("SC%d - ICC detected!!\n", p_this->id); else SC_INFO("SC%d - ICC removed!!\n", p_this->id); complete(&p_this->card_detect_completion); } switch (p_this->fsm) { case IFD_FSM_RESET: mars_scd_fsm_reset(p_this); break; case IFD_FSM_ACTIVE: mars_scd_fsm_active(p_this); break; default: break; } SET_SCIRSR(id, status); }
/****************************************************************************** * FunctionName : esptouch_FailCb * Description : esp-touch fail callback *******************************************************************************/ void ICACHE_FLASH_ATTR esptouch_FailCb(void* data) { wifi_station_disconnect(); smartconfig_stop(); //wifi_set_opmode(STATIONAP_MODE); SC_INFO("ESP-TOUCH FAIL \r\n"); os_timer_disarm(&esptouch_tout_t); #if LIGHT_DEVICE light_shadeStart(HINT_RED,2000,0,1,NULL); #endif SC_INFO("ENABLE LIGHT ACTION(ESP-NOW)"); os_printf("debug: channel:%d\r\n",wifi_get_channel()); #if ESP_NOW_SUPPORT light_EspnowInit(); #endif #if ESP_MESH_SUPPORT SC_INFO("RESTART MESH NOW...\r\n"); #if LIGHT_DEVICE light_hint_stop(HINT_RED); #endif //user_MeshStart(); wifi_RestartMeshScan(5000); #else SC_INFO("ESP-TOUCH FAIL, OPEN WEBSERVER NOW"); mesh_SetSoftap();//check #endif }
/*------------------------------------------------------------------ * Func : mars_scd_activate * * Desc : activate an ICC * * Parm : p_this : handle of mars scd * * Retn : 0 : for success, others : fail *------------------------------------------------------------------*/ int mars_scd_activate(mars_scd* p_this) { switch(p_this->fsm) { case IFD_FSM_DISABLE: SC_WARNING("activate ICC failed, please enable IFD first\n"); return -1; case IFD_FSM_IDEL: if (p_this->reset(p_this)==0) { SC_INFO("activate ICC success\n"); return 0; } else { SC_WARNING("activate ICC failed\n"); return -1; } break; case IFD_FSM_RESET: SC_INFO("ICC has is reseting\n"); return 0; case IFD_FSM_ACTIVE: SC_INFO("ICC has been activated already\n"); return 0; default: SC_WARNING("activate ICC failed, unknown state\n"); return -1; } }
/****************************************************************************** * FunctionName : esptouch_SuccessCb * Description : esp-touch success callback *******************************************************************************/ void ICACHE_FLASH_ATTR esptouch_SuccessCb(void* data) { wifi_set_opmode(STATIONAP_MODE); os_timer_disarm(&esptouch_tout_t);//disable check timeout #if LIGHT_DEVICE light_hint_stop(HINT_WHITE); #endif SC_INFO("ESP-TOUCH SUCCESS \r\n"); SC_INFO("ENABLE LIGHT ACTION(ESP-NOW)"); SC_INFO("debug: channel:%d\r\n",wifi_get_channel()); #if ESP_MESH_SUPPORT if(MESH_DISABLE == espconn_mesh_get_status()){ //user_MeshStart(); //mesh_enable_task(); } user_esp_platform_connect_ap_cb(); //user_MeshStart(); #else user_esp_platform_connect_ap_cb(); #endif #if ESP_NOW_SUPPORT light_EspnowInit(); #endif SC_INFO("CONNECTED TO AP...ENABLE MESH AND RUN PLATFORM CODE ...WAIT...\r\n"); }
/****************************************************************************** * FunctionName : esptouch_StartCb * Description : esp-touch start callback *******************************************************************************/ void ICACHE_FLASH_ATTR esptouch_StartCb(void* para) { SC_INFO("LIGHT SHADE & START ESP-TOUCH"); #if LIGHT_DEVICE light_shadeStart(HINT_GREEN,1000,0,1,NULL); #endif }
/*------------------------------------------------------------------ * Func : scd_drv_suspend * * Desc : this function was used to suspend a scd device * * Parm : dev : scd device to be suspend * * Retn : 0 for success, others failed *------------------------------------------------------------------*/ int scd_drv_suspend(struct device * dev, pm_message_t state, u32 level) { scd_device* p_dev = to_scd_device(dev); scd_driver* p_drv = to_scd_driver(dev->driver); SC_INFO("suspend scd_dev '%s'\n", p_dev->name); return (p_drv->suspend) ? p_drv->suspend(p_dev) : 0; }
/*------------------------------------------------------------------ * Func : scd_drv_resume * * Desc : this function was used to resume a scd device * * Parm : dev : scd device to be suspend * * Retn : 0 for success, others failed *------------------------------------------------------------------*/ int scd_drv_resume(struct device * dev, u32 level) { scd_device* p_dev = to_scd_device(dev); scd_driver* p_drv = to_scd_driver(dev->driver); SC_INFO("resume scd_dev '%s'\n", p_dev->name); return (p_drv->resume) ? p_drv->resume(p_dev) : 0; }
/*------------------------------------------------------------------ * Func : scd_drv_shutdown * * Desc : this function was used to short down a scd device * * Parm : dev : scd device to be shut down * * Retn : 0 for success, others failed *------------------------------------------------------------------*/ void scd_drv_shutdown(struct device * dev) { scd_device* p_dev = to_scd_device(dev); scd_driver* p_drv = to_scd_driver(dev->driver); SC_INFO("shotdown smart card device '%s'\n", p_dev->name); if (p_drv->enable) p_drv->enable(p_dev, 0); }
/*------------------------------------------------------------------ * Func : scd_dev_module_init * * Desc : scd dev init function * * Parm : N/A * * Retn : 0 : success, others fail *------------------------------------------------------------------*/ static int __init scd_core_init(void) { SC_INFO("%s, register scd_bus %p\n",__FUNCTION__, &scd_bus_type); #ifdef CONFIG_SMARTCARD_DEV_FILE scd_dev_module_init(); #endif return bus_register(&scd_bus_type); // register scd bus type }
/*------------------------------------------------------------------ * Func : mars_scd_module_init * * Desc : init mars smart card interface driver * * Parm : N/A * * Retn : 0 : success, others fail *------------------------------------------------------------------*/ static int __init mars_scd_module_init(void) { SC_INFO("mars scd module init\n"); if (register_scd_driver(&mars_scd_driver)!=0) return -EFAULT; register_scd_device(&mars_scd_controller[0]); // register scd device register_scd_device(&mars_scd_controller[1]); // register scd device return 0; }
/****************************************************************************** * FunctionName : esptouch_FlowStart * Description : Set esp-touch callback and start esp-touch *******************************************************************************/ void ICACHE_FLASH_ATTR esptouch_FlowStart() { wifi_station_disconnect(); #if ESP_NOW_SUPPORT light_EspnowDeinit(); #endif WIFI_StopCheckIp(); //esptouch_setAckFlag(true); SC_INFO("ESP-TOUCH FLOW INIT...\r\n"); esptouch_proc.esptouch_fail_cb = esptouch_FailCb; esptouch_proc.esptouch_start_cb = esptouch_StartCb; esptouch_proc.esptouch_suc_cb = esptouch_SuccessCb; esptouch_proc.esptouch_type = SC_TYPE_ESPTOUCH; SC_INFO("ESP-TOUCH SET STATION MODE ...\r\n"); wifi_set_opmode(STATION_MODE); if(esptouch_proc.esptouch_fail_cb){ os_timer_disarm(&esptouch_tout_t); os_timer_setfn(&esptouch_tout_t,esptouch_proc.esptouch_fail_cb,NULL); os_timer_arm(&esptouch_tout_t,ESP_TOUCH_TIME_ENTER,0); } if(esptouch_cnt>=2){ SC_INFO("ALREADY DID ESPTOUCH %d TIMES\r\n",ESP_TOUCH_TIME_LIMIT); esptouch_setAckFlag(true); //stop getting into esptouch mode if(esptouch_proc.esptouch_fail_cb) esptouch_proc.esptouch_fail_cb(NULL); return; } esptouch_cnt += 1; SC_INFO("ESP-TOUCH START"); smartconfig_start(esptouch_ProcCb); }
/*------------------------------------------------------------------ * Func : register_scd_device * * Desc : register scd device * * Parm : device : scd device to be registered * * Retn : 0 *------------------------------------------------------------------*/ int register_scd_device(scd_device* device) { struct device* dev = &device->dev; SC_INFO("register scd device '%s' (%p) to scd%d\n", device->name, dev, scd_device_count); sprintf(dev->bus_id, "scd%d", scd_device_count++); dev->bus = &scd_bus_type; dev->release = scd_device_release; return device_register(dev); }
/*------------------------------------------------------------------ * Func : mars_scd_set_etu * * Desc : set etu of mars smart card interface * * Parm : p_this : handle of mars scd * etu : cycles * * Retn : 0 : for success, others : fail *------------------------------------------------------------------*/ int mars_scd_set_etu(mars_scd* p_this, unsigned long etu) { unsigned char id = p_this->id; unsigned long val; p_this->baud_div2 = 31; // to simplify, we always set the baud div2 to 31 p_this->baud_div1 = etu * p_this->clock_div / p_this->baud_div2; val = GET_SCFP(id) & ~SC_BAUDDIV_MASK; val |= SC_BAUDDIV1((p_this->baud_div1-1)) | SC_BAUDDIV2(0); SC_INFO("ETU = %lu. Baud Div2=31, Div1 = %lu\n", etu, p_this->baud_div1); SET_SCFP(id, val); return 0; }
/*------------------------------------------------------------------ * Func : register_scd_driver * * Desc : register scd device driver * * Parm : driver : scd device driver to be registered * * Retn : 0 *------------------------------------------------------------------*/ int register_scd_driver(scd_driver* driver) { struct device_driver* drv = &driver->drv; drv->name = driver->name; drv->bus = &scd_bus_type; drv->probe = scd_drv_probe; drv->remove = scd_drv_remove; drv->shutdown = scd_drv_shutdown; drv->suspend = scd_drv_suspend; drv->resume = scd_drv_resume; SC_INFO("register scd driver '%s' (%p)\n", drv->name, drv); return driver_register(drv); }
/*------------------------------------------------------------------ * Func : scd_drv_remove * * Desc : this function was used to inform the scd driver that a scd * device has been removed * * Parm : dev : scd device to be removed * * Retn : 0 for success, others failed *------------------------------------------------------------------*/ int scd_drv_remove(struct device * dev) { scd_device* p_dev = to_scd_device(dev); scd_driver* p_drv = to_scd_driver(dev->driver); SC_INFO("remove smart card device '%s'\n", p_dev->name); if (p_drv->remove) p_drv->remove(p_dev); #ifdef CONFIG_SMARTCARD_DEV_FILE create_scd_dev_node(p_dev); #endif return 0; }
/*------------------------------------------------------------------ * Func : scd_drv_probe * * Desc : probe scd device * * Parm : dev : scd device to be probed * * Retn : 0 : if supportted, others : failed *------------------------------------------------------------------*/ int scd_drv_probe(struct device * dev) { scd_device* p_dev = to_scd_device(dev); scd_driver* p_drv = to_scd_driver(dev->driver); SC_INFO("probe : scd_dev '%s' (%p), scd_drv '%s' (%p)\n", p_dev->name, dev,p_drv->name, dev->driver); if (!p_drv->probe) return -ENODEV; if (p_drv->probe(p_dev)==0) { #ifdef CONFIG_SMARTCARD_DEV_FILE create_scd_dev_node(p_dev); #endif return 0; } return -ENODEV; }
/*------------------------------------------------------------------ * Func : mars_scd_reset * * Desc : reset mars smart card interface * * Parm : p_this : handle of mars scd * * Retn : 0 : for success, others : fail *------------------------------------------------------------------*/ int mars_scd_reset(mars_scd* p_this) { unsigned long t; if (mars_scd_set_state(p_this, IFD_FSM_RESET)) return -1; t = jiffies + (HZ<<2); while(!time_after(jiffies,t) && p_this->fsm == IFD_FSM_RESET) msleep(100); if (p_this->fsm!=IFD_FSM_ACTIVE) { SC_WARNING("SC%d - Reset ICC failed\n", p_this->id); mars_scd_set_state(p_this, IFD_FSM_IDEL); return -1; } SC_INFO("SC%d - Reset ICC Complete\n", p_this->id); return 0; }
/*------------------------------------------------------------------ * Func : mars_scd_set_state * * Desc : receive data and wait atr * * Parm : p_this : handle of mars cec * * Retn : N/A *------------------------------------------------------------------*/ int mars_scd_set_state( mars_scd* p_this, IFD_FSM fsm ) { unsigned char id = p_this->id; if (p_this->fsm == fsm) return 0; switch(fsm) { case IFD_FSM_DISABLE: SC_INFO("SC%d - FSM = DISABLE\n", id); SET_SCCR (id, SC_FIFO_RST(1) | SC_SCEN(0) | SC_AUTO_ATR(1) | SC_CONV(0) | SC_PS(p_this->parity)); SET_SCIRER(id, 0); // Disable ISR SET_SCIRSR(id, 0xFFFFFFFF); p_this->atr.length = 0; break; case IFD_FSM_IDEL: SC_INFO("SC%d - FSM = IDEL\n", id); //SET_SCCR (id, SC_FIFO_RST(1) | SC_SCEN(0) | SC_AUTO_ATR(1) | SC_CONV(0) |SC_PS(p_this->parity)); SET_SCCR (id, SC_FIFO_RST(0) | SC_SCEN(1) | SC_AUTO_ATR(1) | SC_CONV(0) |SC_PS(p_this->parity)); SET_SCIRER(id, SC_CPRES_INT); SET_SCIRSR(id, 0xFFFFFFFF); p_this->atr.length = 0; break; case IFD_FSM_RESET: p_this->atr.length = 0; if (!mars_scd_card_detect(p_this)) { SC_WARNING("SC%d - RESET mars scd failed, no ICC exist\n", id); mars_scd_set_state(p_this, IFD_FSM_IDEL); return -1; } SET_SCIRER(id, SC_CPRES_INT | SC_ATRS_INT | SC_RXP_INT | SC_RX_FOVER_INT); SET_SCCR (id, SC_FIFO_RST(1) | // pull reset pin SC_RST(1) | SC_SCEN(1) | SC_AUTO_ATR(1) | SC_CONV(0) | SC_PS(p_this->parity)); p_this->atr_timeout = jiffies + HZ; SC_INFO("SC%d - FSM = RESET & ATR\n", id); break; case IFD_FSM_ACTIVE: SC_INFO("SC%d - FSM = ACTIVATE\n", id); break; default: case IFD_FSM_UNKNOWN: break; } p_this->fsm = fsm; return 0; }
/*------------------------------------------------------------------ * Func : mars_scd_open * * Desc : open a mars scd device * * Parm : id : channel id * * Retn : handle of mars scd *------------------------------------------------------------------*/ mars_scd* mars_scd_open(unsigned char id) { mars_scd* p_this; if (id >= 2) return NULL; #if 1 rtd_outl(0xb8000364, rtd_inl(0xb8000364) | 0x00003000); // Set Pin MUX #endif p_this = (mars_scd*) kmalloc(sizeof(mars_scd), GFP_KERNEL); if (p_this) { memset(p_this, 0, sizeof(mars_scd)); p_this->id = id; p_this->fsm = IFD_FSM_UNKNOWN; p_this->atr.length = 0; init_completion(&p_this->card_detect_completion); // configurations --- p_this->clock_div = 1; p_this->pre_clock_div = 8; p_this->baud_div1 = 12; // default etu = 372 = 31 * 12 p_this->baud_div2 = 31; p_this->parity = 1; // operations --- p_this->enable = mars_scd_enable; p_this->set_clock = mars_scd_set_clock; p_this->get_clock = mars_scd_get_clock; p_this->set_etu = mars_scd_set_etu; p_this->get_etu = mars_scd_get_etu; p_this->set_parity = mars_scd_set_parity; p_this->get_parity = mars_scd_get_parity; p_this->activate = mars_scd_activate; p_this->deactivate = mars_scd_deactivate; p_this->reset = mars_scd_reset; p_this->get_atr = mars_scd_get_atr; p_this->xmit = mars_scd_xmit; p_this->read = mars_scd_read; p_this->get_card_status = mars_scd_card_detect; p_this->poll_card_status = mars_scd_poll_card_status; // Set All Register to the initial value SET_SCFP (id, SC_CLK_EN(1) | SC_CLKDIV((p_this->clock_div-1))| SC_BAUDDIV2(0) | // fixed to 31 SC_BAUDDIV1((p_this->baud_div1-1))| SC_PRE_CLKDIV((p_this->pre_clock_div-1))); SET_SCCR (id, SC_FIFO_RST(1) | SC_SCEN(1) | SC_AUTO_ATR(1) | SC_CONV(0) | SC_PS(0)); SET_SCPCR (id, SC_TXGRDT(0) | SC_CWI(0) | SC_BWI(0) | SC_WWI(0) | SC_BGT(0x16) | SC_EDC_EN(0) | SC_CRC(0) | SC_PROTOCOL_T(0)| SC_T0RTY(0) | SC_T0RTY_CNT(0) ); SET_SCIRER(id, 0); SET_SCIRSR(id, 0xFFFFFFFF); // Set Interrupt or IRQ #ifdef ISR_POLLING init_timer(&p_this->timer); p_this->timer.data = (unsigned long)p_this; p_this->timer.function = mars_scd_timer; p_this->timer.expires = jiffies + ISR_POLLING_INTERVAL; add_timer(&p_this->timer); // register timer #else SC_INFO("Request IRQ #%d\n", MISC_IRQ); if (request_irq(MISC_IRQ, mars_scd_isr, SA_INTERRUPT | SA_SHIRQ, "MARS SCD", p_this) < 0) { SC_WARNING("scd : open mars scd failed, unable to request irq#%d\n", MISC_IRQ); return -1; } #endif mars_scd_set_state(p_this, IFD_FSM_DISABLE); } return p_this; }
/****************************************************************************** * FunctionName : esptouch_ProcCb * Description : esp-touch status change callback for smartconfig_start *******************************************************************************/ LOCAL void ICACHE_FLASH_ATTR esptouch_ProcCb(sc_status status, void *pdata) { switch(status) { case SC_STATUS_WAIT: SC_INFO("SC_STATUS_WAIT\n"); break; case SC_STATUS_FIND_CHANNEL: SC_INFO("SC_STATUS_FIND_CHANNEL\n"); if(esptouch_proc.esptouch_start_cb){ esptouch_proc.esptouch_start_cb(NULL); } break; case SC_STATUS_GETTING_SSID_PSWD: SC_INFO("SC_STATUS_GETTING_SSID_PSWD\n"); #if LIGHT_DEVICE light_shadeStart(HINT_BLUE,1000,0,1,NULL); #endif if(esptouch_proc.esptouch_fail_cb){ os_timer_disarm(&esptouch_tout_t); os_timer_setfn(&esptouch_tout_t,esptouch_proc.esptouch_fail_cb,NULL); os_timer_arm(&esptouch_tout_t,ESP_TOUCH_TIMEOUT_MS,0); } break; case SC_STATUS_LINK: SC_INFO("SC_STATUS_LINK\n"); struct station_config *sta_conf = pdata; //os_printf(); wifi_station_set_config(sta_conf); wifi_station_disconnect(); //wifi_station_disconnect(); //====================== #if ESP_MESH_SUPPORT //mesh_enable_task(); //user_MeshStart(); //user_esp_platform_connect_ap_cb(); #endif //====================== wifi_station_connect(); os_timer_disarm(&esptouch_tout_t); os_timer_arm(&esptouch_tout_t,ESPTOUCH_CONNECT_TIMEOUT_MS,0); #if LIGHT_DEVICE //light_blinkStart(HINT_WHITE); light_shadeStart(HINT_WHITE,1000,0,1,NULL); #endif break; case SC_STATUS_LINK_OVER: os_timer_disarm(&esptouch_tout_t); SC_INFO("SC_STATUS_LINK_OVER\n"); if (esptouch_proc.esptouch_type == SC_TYPE_ESPTOUCH) { uint8 phone_ip[4] = {0}; os_memcpy(phone_ip, (uint8*)pdata, 4); SC_INFO("Phone ip: %d.%d.%d.%d\n",phone_ip[0],phone_ip[1],phone_ip[2],phone_ip[3]); } smartconfig_stop(); SC_INFO("UPDATE PASSWORD HERE\r\n"); if(esptouch_proc.esptouch_suc_cb){ esptouch_proc.esptouch_suc_cb(NULL);//run finish cb } break; } }
/*------------------------------------------------------------------ * Func : mars_scd_fsm_deactivate * * Desc : * * Parm : p_this : handle of mars cec * * Retn : N/A *------------------------------------------------------------------*/ void mars_scd_fsm_reset(mars_scd* p_this) { unsigned char id = p_this->id; unsigned long event = GET_SCIRSR(id); unsigned long rx_len = 0; unsigned long i = 0; SC_INT_DGB("SC_RISR=%08lx\n", event); if ((event & SC_RXP_INT) || !(event & SC_PRES)|| time_after(jiffies, p_this->atr_timeout)) goto err_atr_failed; if (event & SC_RCV_INT) { if (p_this->atr.length==0 && !(event & SC_ATRS_INT)) { // unwanted data, drop it rx_len = GET_SC_RXLENR(id); for (i=0; i<rx_len; i++) GET_SC_RXFIFO(id); goto end_proc; } // receive atr : while(GET_SC_RXLENR(id)) { if (p_this->atr.length >= MAX_ATR_SIZE) goto err_atr_failed; p_this->atr.data[p_this->atr.length++] = GET_SC_RXFIFO(id); } // check atr if (is_atr_complete(&p_this->atr)) { SC_INFO("SC%d - Got ATR Completed\n", p_this->id); if (decompress_atr(&p_this->atr, &p_this->atr_info)<0) goto err_atr_failed; mars_scd_set_state(p_this, IFD_FSM_ACTIVE); // jump to active state } } end_proc: SET_SCIRSR(id, event); return; err_atr_failed: if (!(event & SC_PRES)) { SC_WARNING("SC%d - RESET ICC failed, no ICC detected\n", p_this->id); } if (event & SC_RXP_INT) { SC_WARNING("SC%d - RESET ICC failed, RX Parity Error\n", p_this->id); } if (time_after(jiffies, p_this->atr_timeout)) { SC_WARNING("SC%d - RESET ICC failed, timeout\n", p_this->id); } mars_scd_set_state(p_this, IFD_FSM_IDEL); goto end_proc; }
/*------------------------------------------------------------------ * Func : register_scd_device * * Desc : register scd device * * Parm : device : scd device to be registered * * Retn : N/A *------------------------------------------------------------------*/ void scd_device_release(struct device* dev) { scd_device* p_dev = to_scd_device(dev); SC_INFO("scd dev %s released\n", p_dev->name); }
/*------------------------------------------------------------------ * Func : unregister_scd_driver * * Desc : unregister scd driver * * Parm : driver : scd driver to be unregistered * * Retn : N/A *------------------------------------------------------------------*/ void unregister_scd_driver(scd_driver* driver) { struct device_driver* drv = &driver->drv; SC_INFO("unregister scd driver '%s' (%p)\n", drv->name, &driver->drv); driver_unregister(&driver->drv); }