diff options
Diffstat (limited to 'fw/fe310/phone/wifi.c')
-rw-r--r-- | fw/fe310/phone/wifi.c | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/fw/fe310/phone/wifi.c b/fw/fe310/phone/wifi.c new file mode 100644 index 0000000..cb8a816 --- /dev/null +++ b/fw/fe310/phone/wifi.c @@ -0,0 +1,351 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include <eos.h> +#include <dev/net.h> + +#include <eve/eve.h> +#include <eve/eve_kbd.h> +#include <eve/eve_font.h> + +#include <eve/screen/window.h> +#include <eve/screen/page.h> +#include <eve/screen/form.h> + +#include "app/app.h" +#include "app/status.h" + +#include "wifi.h" + +#define WIFI_ACTION_NONE -1 +#define WIFI_ACTION_IDLE 0 +#define WIFI_ACTION_START 1 +#define WIFI_ACTION_STOP 2 +#define WIFI_ACTION_SCAN 3 +#define WIFI_ACTION_CONNECT 4 +#define WIFI_ACTION_DISCONNECT 5 + +static void handle_status(unsigned char type, unsigned char *buffer, uint16_t size) { + EVEPage *page; + WIFIStatus *status; + int action; + int rv; + + if (app_current_view() != wifi_app) goto handle_status_fin; + + page = (EVEPage *)app_search_view("main"); + status = page->v.param; + + rv = eos_wifi_status_parse(buffer, size, &status->status, status->ip_addr, status->ssid); + if (rv) { + APP_LOG(APP_LOG_ERR, "BAD STATUS ERR:%d\n", rv); + goto handle_status_fin; + } + + action = WIFI_ACTION_NONE; + switch (status->action) { + case WIFI_ACTION_IDLE: { + break; + } + case WIFI_ACTION_START: { + if (status->status == EOS_WIFI_STATUS_DISCONNECTED) { + action = WIFI_ACTION_SCAN; + } + break; + } + case WIFI_ACTION_STOP: { + if (status->status == EOS_WIFI_STATUS_OFF) { + action = WIFI_ACTION_IDLE; + } + break; + } + case WIFI_ACTION_CONNECT: { + if (status->status == EOS_WIFI_STATUS_CONNECTED) { + action = WIFI_ACTION_IDLE; + } else { + app_status_set_msg("CONNECT FAILED"); + action = WIFI_ACTION_SCAN; + } + break; + } + case WIFI_ACTION_DISCONNECT: { + if (status->status == EOS_WIFI_STATUS_DISCONNECTED) { + action = WIFI_ACTION_SCAN; + } + break; + } + case WIFI_ACTION_SCAN: { + /* ignore status updates during scan */ + goto handle_status_fin; + } + } + + if (action == WIFI_ACTION_SCAN) { + rv = eos_wifi_scan(buffer, 0); + if (rv) { + APP_LOG(APP_LOG_ERR, "WIFI SCAN ERR:%d\n", rv); + goto handle_status_fin; + } + buffer = NULL; + } + wifi_update_status(page, action); + app_refresh(); + +handle_status_fin: + if (buffer) eos_net_free(buffer, 0); +} + +static void handle_scan(unsigned char type, unsigned char *buffer, uint16_t size) { + EVEPage *page; + EVESelectWidget *selw; + + if (app_current_view() != wifi_app) goto handle_scan_fin; + + page = (EVEPage *)app_search_view("main"); + wifi_update_scanr(page, buffer + 1, size - 1); + app_refresh(); + +handle_scan_fin: + eos_net_free(buffer, 0); +} + +static void widget_ssid_draw(EVEFreeWidget *widget) { + EVEWidget *_widget = &widget->w; + WIFIStatus *status = _widget->page->v.param; + + if (_widget->flags & EVE_WIDGET_FLAG_BUSY) { + eve_freew_tag(widget); + eve_cmd(CMD_TEXT, "hhhhs", _widget->g.x, _widget->g.y, app_font()->id, 0, "BUSY!"); + } else if (status->status >= EOS_WIFI_STATUS_CONNECTED) { + char text[51]; + + if (status->status == EOS_WIFI_STATUS_CONNECTED) { + strcpy(text, status->ssid); + } else { + sprintf(text, "%s (%d.%d.%d.%d)", status->ssid, status->ip_addr[0], status->ip_addr[1], status->ip_addr[2], status->ip_addr[3]); + } + + eve_freew_tag(widget); + eve_cmd(CMD_TEXT, "hhhhs", _widget->g.x, _widget->g.y, app_font()->id, 0, text); + } +} + +static int widget_ssid_touch(EVEFreeWidget *widget, EVETouch *touch, uint16_t evt) { + if (evt & EVE_TOUCH_ETYPE_POINT_UP) { + EVEPage *page = widget->w.page; + int rv; + + rv = eos_wifi_disconnect(NULL, 0); + if (!rv) wifi_update_status(page, WIFI_ACTION_DISCONNECT); + return 1; + } + return 0; +} + +static int widget_enable_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt) { + EVEToggleWidget *widget = (EVEToggleWidget *)_widget; + EVEPage *page = _widget->page; + WIFIStatus *status = page->v.param; + + if (evt & EVE_TOUCH_ETYPE_TAG_UP) { + int rv; + + if (widget->state) { + rv = eos_wifi_stop(NULL, 0); + if (!rv) wifi_update_status(page, WIFI_ACTION_STOP); + } else { + rv = eos_wifi_start(NULL, 0); + if (!rv) wifi_update_status(page, WIFI_ACTION_START); + } + if (rv) (APP_LOG_ERR, "WIFI START ERR:%d\n", rv); + return 1; + } + + return 0; +} + +void wifi_init(void) { + eos_wifi_set_handler(EOS_WIFI_MTYPE_STATUS, handle_status); + eos_wifi_set_handler(EOS_WIFI_MTYPE_SCAN, handle_scan); +} + +int wifi_app(EVEWindow *window, EVEViewStack *stack) { + EVEFormSpec spec[] = { + APP_SPACERW(APP_SCREEN_W,20), + { + .label.title = "Enable:", + .label.g.w = APP_SCREEN_W - 100, + + .widget.type = EVE_WIDGET_TYPE_TOGGLE, + .widget.g.w = 100, + .widget.tspec.toggle.labels = "off\xffon", + }, + { + .widget.type = EVE_WIDGET_TYPE_FREE, + .widget.g.h = eve_font_h(app_font()), + .widget.tspec.free.draw = widget_ssid_draw, + .widget.tspec.free.touch = widget_ssid_touch, + }, + { + .label.g.w = APP_SCREEN_W, + .label.title = "Select network:", + + .widget.type = EVE_WIDGET_TYPE_SELECT, + .widget.g.w = APP_SCREEN_W, + .widget.tspec.select.option_size = EOS_WIFI_MAX_SCAN_RECORDS * EOS_WIFI_SIZE_SSID, + }, + APP_SPACERW(APP_SCREEN_W,50), + { + .label.title = "Password:", + + .widget.type = EVE_WIDGET_TYPE_STR, + .widget.tspec.str.str_size = EOS_WIFI_SIZE_PWD, + }, + }; + EVEPage *page; + EVEWidget *widget; + WIFIStatus *status; + int rv; + int action; + + page = eve_form_create(window, stack, spec, APP_SPEC_SIZE(spec), wifi_uievt, wifi_close); + if (page == NULL) { + rv = EVE_ERR_NOMEM; + APP_LOG(APP_LOG_ERR, "OUT OF MEMORY\n"); + return rv; + } + + status = eve_malloc(sizeof(WIFIStatus)); + if (status == NULL) { + rv = EVE_ERR_NOMEM; + eve_form_destroy(page); + APP_LOG(APP_LOG_ERR, "OUT OF MEMORY\n"); + return rv; + } + + page->v.param = status; + widget = eve_page_widget(page, 0); + widget->touch = widget_enable_touch; + + rv = eos_wifi_status(&status->status, status->ip_addr, status->ssid, NULL); + if (rv) { + wifi_close(page); + APP_LOG(APP_LOG_ERR, "BAD STATUS ERR:%d\n", rv); + return rv; + } + + action = WIFI_ACTION_IDLE; + if (status->status == EOS_WIFI_STATUS_DISCONNECTED) { + rv = eos_wifi_scan(NULL, 0); + if (rv) { + wifi_close(page); + APP_LOG(APP_LOG_ERR, "WIFI SCAN ERR:%d\n", rv); + return rv; + } + action = WIFI_ACTION_SCAN; + } + wifi_update_status(page, action); + + return EVE_OK; +} + +int wifi_uievt(EVEPage *page, uint16_t evt, void *param) { + int ret = 0; + + switch (evt) { + case EVE_UIEVT_WIDGET_FOCUS_OUT: { + if (param == eve_page_widget(page, 3)) { + EVESelectWidget *selw; + utf8_t *ssid; + + selw = (EVESelectWidget *)eve_page_widget(page, 2); + ssid = eve_selectw_option_selected(selw); + if (ssid) { + EVEStrWidget *strw = param; + WIFIStatus *status = page->v.param; + int rv; + + rv = eos_wifi_connect((char *)ssid, (char *)strw->str, NULL, 0); + if (!rv) wifi_update_status(page, WIFI_ACTION_CONNECT); + if (rv) APP_LOG(APP_LOG_ERR, "WIFI CONNECT ERR:%d\n", rv); + } + } + break; + } + + default: { + ret = eve_form_uievt(page, evt, param); + break; + } + } + + return ret; +} + +void wifi_close(EVEPage *page) { + eve_free(page->v.param); + eve_form_destroy(page); +} + +void wifi_update_status(EVEPage *page, int action) { + WIFIStatus *status = page->v.param; + EVEWidget *widget; + int i; + + /* enable */ + widget = eve_page_widget(page, 0); + if (status->status == EOS_WIFI_STATUS_OFF) { + ((EVEToggleWidget *)widget)->state = 0; + } else { + ((EVEToggleWidget *)widget)->state = 1; + } + + /* ssid */ + widget = eve_page_widget(page, 1); + eve_widget_clr_flags(widget, (EVE_WIDGET_FLAG_HIDDEN | EVE_WIDGET_FLAG_BUSY)); + if (action >= WIFI_ACTION_SCAN) { + eve_widget_set_flags(widget, EVE_WIDGET_FLAG_BUSY); + } + if ((status->status < EOS_WIFI_STATUS_CONNECTED) && !(widget->flags & EVE_WIDGET_FLAG_BUSY)) { + eve_widget_set_flags(widget, EVE_WIDGET_FLAG_HIDDEN); + } + + /* select network and password */ + widget = eve_page_widget(page, 2); + for (i=0; i<3; i++) { + eve_widget_set_flags(widget, EVE_WIDGET_FLAG_HIDDEN); + widget = eve_widget_next(widget); + } + if (action != WIFI_ACTION_NONE) status->action = action; + eve_form_update_g(page, NULL); +} + +void wifi_update_scanr(EVEPage *page, unsigned char *buffer, size_t size) { + WIFIStatus *status = page->v.param; + EVEWidget *widget; + EVESelectWidget *selw; + int i, rv; + + selw = (EVESelectWidget *)eve_page_widget(page, 2); + rv = eve_selectw_set_option(selw, buffer, size); + if (rv) { + APP_LOG(APP_LOG_ERR, "BAD SCAN ERR:%d\n", rv); + return; + } + + /* ssid */ + widget = eve_page_widget(page, 1); + eve_widget_clr_flags(widget, EVE_WIDGET_FLAG_BUSY); + eve_widget_set_flags(widget, EVE_WIDGET_FLAG_HIDDEN); + + /* select network and password */ + widget = eve_page_widget(page, 2); + for (i=0; i<3; i++) { + eve_widget_clr_flags(widget, EVE_WIDGET_FLAG_HIDDEN); + widget = eve_widget_next(widget); + } + status->action = WIFI_ACTION_IDLE; + eve_form_update_g(page, NULL); +} |