diff --git a/src/menu/src/join_menu.c b/src/menu/src/join_menu.c index d6c7156..4755b5c 100644 --- a/src/menu/src/join_menu.c +++ b/src/menu/src/join_menu.c @@ -1,13 +1,14 @@ #include #include -#include #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -16,8 +17,8 @@ struct join_menu { struct gui_container cnt, bcnt; - struct gui_label type_label, address, port, connecting; - struct gui_button type_btn, back, connect; + struct gui_label type_label, address_device, port, connecting, speed; + struct gui_button type_btn, back, connect, device_btn, speed_btn; struct gui_line_edit address_le, port_le; enum @@ -30,7 +31,8 @@ struct join_menu } state; struct net_socket *socket; - size_t domain_i; + size_t domain_i, speed_i, device_i, n_devices; + const char *const *devices; }; static const enum net_domain domains[] = @@ -39,22 +41,22 @@ static const enum net_domain domains[] = NET_DOMAIN_SERIAL }; +static const char *const speeds[] = +{ + "19200", "38400", "57600", "115200" +}; + static void on_connected(void *const arg) { struct join_menu *const m = arg; - if (m->state == IDLE) - { - m->state = CONNECT; - m->connecting.text = "Connecting..."; - } + m->state = CONNECTED; } static void on_disconnected(void *const arg) { struct join_menu *const m = arg; - m->connecting.text = "Failed to connect"; m->state = CONNECT_FAILED; m->socket = NULL; } @@ -83,10 +85,13 @@ static int on_connect(struct join_menu *const m) { errno = 0; - const unsigned long port = strtoul(m->port_le.text, NULL, 0); + const unsigned long port = strtoul(m->port_le.text, NULL, 10); if (errno) + { + m->connecting.text = "Invalid port"; return -1; + } c.ipv4.addr = m->address_le.text; c.ipv4.port = port; @@ -100,6 +105,7 @@ static int on_connect(struct join_menu *const m) if (!(m->socket = net_connect(&c))) { fprintf(stderr, "%s: net_connect failed\n", __func__); + on_disconnected(m); return -1; } @@ -123,17 +129,20 @@ static int update(struct menu_common *const c, void *const arg) { case CONNECT: if (on_connect(m)) - return -1; + { + m->state = CONNECT_FAILED; + break; + } m->state = CONNECTING; - - if (!m->connecting.common.parent) - gui_add_child(&m->cnt.common, &m->connecting.common); - + m->connecting.text = "Connecting..."; + m->connecting.common.hidden = false; break; case CONNECT_FAILED: net_close(m->socket); + m->connecting.text = "Failed to connect"; + m->connecting.common.hidden = false; m->socket = NULL; m->state = IDLE; break; @@ -156,21 +165,80 @@ static int render(const struct menu_common *const c, void *const arg) return 0; } +static int update_domain(struct join_menu *const m) +{ + switch (domains[m->domain_i]) + { + case NET_DOMAIN_IPV4: + m->port.common.hidden = false; + m->port_le.common.hidden = false; + m->address_le.common.hidden = false; + m->device_btn.common.hidden = true; + m->speed.common.hidden = true; + m->speed_btn.common.hidden = true; + m->address_device.text = "Address:"; + break; + + case NET_DOMAIN_SERIAL: + m->port.common.hidden = true; + m->port_le.common.hidden = true; + m->address_le.common.hidden = true; + m->device_btn.common.hidden = false; + m->speed.common.hidden = false; + m->speed_btn.common.hidden = false; + m->address_device.text = "Device:"; + m->speed_btn.u.type1.label.text = speeds[m->speed_i = 0]; + m->devices = net_serial_devices(&m->n_devices); + + if (!m->devices) + return -1; + + m->device_btn.u.type1.label.text = m->devices[m->device_i = 0]; + break; + } + + return 0; +} + static void on_type_pressed(void *const arg) { struct join_menu *const m = arg; - if (++m->domain_i >= sizeof domains / sizeof *domains) - m->domain_i = 0; + do + if (++m->domain_i >= sizeof domains / sizeof *domains) + m->domain_i = 0; + while (!net_available(domains[m->domain_i])); m->type_btn.u.type1.label.text = net_domain_str(domains[m->domain_i]); + update_domain(m); +} + +static void on_device_pressed(void *const arg) +{ + struct join_menu *const m = arg; + + if (++m->device_i >= m->n_devices) + m->device_i = 0; + + m->device_btn.u.type1.label.text = m->devices[m->device_i]; +} + +static void on_speed_pressed(void *const arg) +{ + struct join_menu *const m = arg; + + if (++m->speed_i >= sizeof speeds / sizeof *speeds) + m->speed_i = 0; + + m->speed_btn.u.type1.label.text = speeds[m->speed_i]; } static void on_connect_pressed(void *const arg) { struct join_menu *const m = arg; - m->state = CONNECT; + if (m->state == IDLE) + m->state = CONNECT; } int menu_join(struct menu_common *const c) @@ -191,18 +259,28 @@ int menu_join(struct menu_common *const c) m.type_label.text = "Type:"; gui_add_child(&m.cnt.common, &m.type_label.common); + while (!net_available(domains[m.domain_i])) + if (++m.domain_i >= sizeof domains / sizeof *domains) + return -1; + gui_button_init(&m.type_btn, GUI_BUTTON_TYPE_1); m.type_btn.arg = &m; m.type_btn.u.type1.w = 140; m.type_btn.common.hcentered = true; m.type_btn.on_pressed = on_type_pressed; - m.type_btn.u.type1.label.text = net_domain_str(*domains); + m.type_btn.u.type1.label.text = net_domain_str(domains[m.domain_i]); gui_add_child(&m.cnt.common, &m.type_btn.common); - gui_label_init(&m.address); - m.address.common.hcentered = true; - m.address.text = "Address:"; - gui_add_child(&m.cnt.common, &m.address.common); + gui_label_init(&m.address_device); + m.address_device.common.hcentered = true; + gui_add_child(&m.cnt.common, &m.address_device.common); + + gui_button_init(&m.device_btn, GUI_BUTTON_TYPE_1); + m.device_btn.common.hcentered = true; + m.device_btn.on_pressed = on_device_pressed; + m.device_btn.arg = &m; + m.device_btn.u.type1.w = 140; + gui_add_child(&m.cnt.common, &m.device_btn.common); char address[sizeof "255.255.255.255"]; gui_line_edit_init(&m.address_le, address, sizeof address); @@ -221,8 +299,22 @@ int menu_join(struct menu_common *const c) m.port_le.common.hcentered = true; gui_add_child(&m.cnt.common, &m.port_le.common); + gui_label_init(&m.speed); + m.speed.font = FONT; + m.speed.text = "Baud rate:"; + m.speed.common.hcentered = true; + gui_add_child(&m.cnt.common, &m.speed.common); + + gui_button_init(&m.speed_btn, GUI_BUTTON_TYPE_1); + m.speed_btn.arg = &m; + m.speed_btn.on_pressed = on_speed_pressed; + m.speed_btn.u.type1.w = 140; + gui_add_child(&m.cnt.common, &m.speed_btn.common); + gui_label_init(&m.connecting); m.connecting.common.hcentered = true; + m.connecting.common.hidden = true; + gui_add_child(&m.cnt.common, &m.connecting.common); gui_container_init(&m.bcnt); m.bcnt.common.hcentered = true; @@ -246,6 +338,9 @@ int menu_join(struct menu_common *const c) m.back.common.vcentered = true; gui_add_child(&m.bcnt.common, &m.back.common); + if (update_domain(&m)) + return -1; + while (!back && !c->p.common.exit && !connect) { if (menu_update(c, update, render, &m))