USB demo
This tutorial is based on a USB testing demo using gint, fxlink bulk USB, and JustUI.
Step 1: Include USB and JustUI
Section titled “Step 1: Include USB and JustUI”The demo combines USB helpers with a touch interface:
#include <gint/display.h>#include <gint/keyboard.h>#include <gint/usb.h>#include <gint/usb-ff-bulk.h>#include <justui/jbutton.h>#include <justui/jlabel.h>#include <justui/jlayout.h>#include <justui/jscene.h>#include <justui/jwidget.h>usb-ff-bulk.h provides the fxlink-style bulk interface.
Step 2: Declare the USB interface
Section titled “Step 2: Declare the USB interface”The USB stack needs a list of interfaces:
static usb_interface_t const *interfaces[] = {&usb_ff_bulk, NULL};The final NULL marks the end of the list.
Step 3: Prepare test data
Section titled “Step 3: Prepare test data”The demo sends short text and optionally the VRAM:
static usb_fxlink_header_t header_text;static usb_fxlink_header_t header_image;static char const *short_text = "Hello JustUI!";static char read_buffer[256];Before sending data, headers are filled with usb_fxlink_fill_header().
Step 4: Build a USB tab
Section titled “Step 4: Build a USB tab”The UI has a tab with status text and buttons:
jlabel *usb_status = jlabel_create("USB Status: Idle", tab4);jbutton *btn_u1 = jbutton_create("Open", col1);jbutton *btn_u3 = jbutton_create("Close", col1);jbutton *btn_u6 = jbutton_create("WA Text", col1);The button labels are short so they fit on the ClassPad screen.
Step 5: Handle button actions
Section titled “Step 5: Handle button actions”When a button is triggered, call the matching USB function and update the status label:
else if (e.source == btn_u1) { int rc = usb_open(interfaces, GINT_CALL_NULL); sprintf(status_buf, "usb_open: %d", rc); jlabel_set_text(usb_status, status_buf);}The demo includes both async and sync writes, commits, and reads.
Step 6: Close cleanly
Section titled “Step 6: Close cleanly”Use usb_close() when you are done testing, and keep an Exit button in the UI so the app can leave the test screen.
Final Code
Section titled “Final Code”This is the demo source.
#include <gint/display.h>#include <gint/keyboard.h>#include <gint/usb.h>#include <gint/usb-ff-bulk.h>#include <justui/jbutton.h>#include <justui/jlabel.h>#include <justui/jlayout.h>#include <justui/jscene.h>#include <justui/jwidget.h>#include <stdio.h>#include <string.h>
static usb_interface_t const *interfaces[] = {&usb_ff_bulk, NULL};
static usb_fxlink_header_t header_text;static usb_fxlink_header_t header_image;static char const *short_text = "Hello JustUI!";static char read_buffer[256];
int main(void){ usb_fxlink_fill_header(&header_text, "justui", "text", strlen(short_text));
int vram_size = DWIDTH * DHEIGHT * sizeof(color_t); usb_fxlink_fill_header(&header_image, "justui", "image", vram_size);
jscene *scene = jscene_create_fullscreen(NULL); jlayout_set_vbox(scene)->spacing = 0;
jwidget *stack = jwidget_create(scene); jlayout_set_stack(stack); jwidget_set_stretch(stack, 1, 1, false);
jwidget *tab1 = jwidget_create(stack); jlayout_set_vbox(tab1)->spacing = 10; jwidget_set_padding(tab1, 15, 15, 15, 15); jlabel_create("Welcome to JustUI ClassPad!", tab1); jlabel_create("This is Tab 1.", tab1); jlabel_create("Select bottom buttons to navigate.", tab1);
jwidget *tab2 = jwidget_create(stack); jlayout_set_vbox(tab2)->spacing = 15; jwidget_set_padding(tab2, 15, 15, 15, 15); jlabel_create("Features (Tab 2)", tab2); jbutton *btn_action = jbutton_create("Click Me!", tab2); jwidget_set_padding(btn_action, 15, 20, 15, 20); jlabel *t2_status = jlabel_create("Button not clicked yet.", tab2);
jwidget *tab3 = jwidget_create(stack); jlayout_set_vbox(tab3)->spacing = 10; jwidget_set_padding(tab3, 15, 15, 15, 15); jlabel_create("About JustUI (Tab 3)", tab3); jlabel_create("JustUI elegantly handles layout.", tab3); jlabel_create("It automatically supports touch!", tab3); jlabel_create("Stack layouts make tabs easy.", tab3);
jwidget *tab4 = jwidget_create(stack); jlayout_set_vbox(tab4)->spacing = 2; jwidget_set_padding(tab4, 5, 5, 5, 5);
jlabel *usb_status = jlabel_create("USB Status: Idle", tab4);
jwidget *usb_cols = jwidget_create(tab4); jlayout_set_hbox(usb_cols)->spacing = 10; jwidget_set_stretch(usb_cols, 1, 1, false);
jwidget *col1 = jwidget_create(usb_cols); jlayout_set_vbox(col1)->spacing = 5; jwidget_set_stretch(col1, 1, 1, false);
jwidget *col2 = jwidget_create(usb_cols); jlayout_set_vbox(col2)->spacing = 5; jwidget_set_stretch(col2, 1, 1, false);
void style_usb_btn(jbutton *b) { jwidget_set_padding(b, 12, 5, 12, 5); }
jbutton *btn_u1 = jbutton_create("Open", col1); style_usb_btn(btn_u1); jbutton *btn_u2 = jbutton_create("Open Wait", col1); style_usb_btn(btn_u2); jbutton *btn_u3 = jbutton_create("Close", col1); style_usb_btn(btn_u3); jbutton *btn_u4 = jbutton_create("WA TxtHead", col1); style_usb_btn(btn_u4); jbutton *btn_u5 = jbutton_create("WA ImgHead", col1); style_usb_btn(btn_u5); jbutton *btn_u6 = jbutton_create("WA Text", col1); style_usb_btn(btn_u6); jbutton *btn_u7 = jbutton_create("WA VRAM", col1); style_usb_btn(btn_u7); jbutton *btn_u14 = jbutton_create("Read Async", col1); style_usb_btn(btn_u14);
jbutton *btn_u8 = jbutton_create("WS TxtHead", col2); style_usb_btn(btn_u8); jbutton *btn_u9 = jbutton_create("WS ImgHead", col2); style_usb_btn(btn_u9); jbutton *btn_u10 = jbutton_create("WS Text", col2); style_usb_btn(btn_u10); jbutton *btn_u11 = jbutton_create("WS VRAM", col2); style_usb_btn(btn_u11); jbutton *btn_u12 = jbutton_create("Commit A", col2); style_usb_btn(btn_u12); jbutton *btn_u13 = jbutton_create("Commit S", col2); style_usb_btn(btn_u13); jbutton *btn_u15 = jbutton_create("Read Sync", col2); style_usb_btn(btn_u15);
jwidget *buttons = jwidget_create(scene); jlayout_set_hbox(buttons)->spacing = 6; jwidget_set_stretch(buttons, 1, 0, false); jwidget_set_padding(buttons, 8, 8, 8, 8);
jbutton *b_tab1 = jbutton_create("Tab 1", buttons); jbutton *b_tab2 = jbutton_create("Tab 2", buttons); jbutton *b_tab3 = jbutton_create("Tab 3", buttons); jbutton *b_tab4 = jbutton_create("USB", buttons);
jwidget *spacer = jwidget_create(buttons); jwidget_set_stretch(spacer, 1, 0, false);
jbutton *b_exit = jbutton_create("Exit", buttons);
jscene_show_and_focus(scene, tab1); jbutton_set_disabled(b_tab1, true);
int action_count = 0; bool running = true; static char status_buf[64];
while (running) { jevent e = jscene_run(scene);
if (e.type == JSCENE_PAINT) { dclear(C_WHITE); jscene_render(scene); dupdate(); } else if (e.type == JBUTTON_TRIGGERED) { if (e.source == b_exit) { running = false; } else if (e.source == b_tab1) { jscene_show_and_focus(scene, tab1); jbutton_set_disabled(b_tab1, true); jbutton_set_disabled(b_tab2, false); jbutton_set_disabled(b_tab3, false); jbutton_set_disabled(b_tab4, false); } else if (e.source == b_tab2) { jscene_show_and_focus(scene, tab2); jbutton_set_disabled(b_tab1, false); jbutton_set_disabled(b_tab2, true); jbutton_set_disabled(b_tab3, false); jbutton_set_disabled(b_tab4, false); } else if (e.source == b_tab3) { jscene_show_and_focus(scene, tab3); jbutton_set_disabled(b_tab1, false); jbutton_set_disabled(b_tab2, false); jbutton_set_disabled(b_tab3, true); jbutton_set_disabled(b_tab4, false); } else if (e.source == b_tab4) { jscene_show_and_focus(scene, tab4); jbutton_set_disabled(b_tab1, false); jbutton_set_disabled(b_tab2, false); jbutton_set_disabled(b_tab3, false); jbutton_set_disabled(b_tab4, true); } else if (e.source == btn_action) { action_count++; static char buf[64]; sprintf(buf, "Clicked %d times!", action_count); jlabel_set_text(t2_status, buf); } else if (e.source == btn_u1) { int rc = usb_open(interfaces, GINT_CALL_NULL); sprintf(status_buf, "usb_open: %d", rc); jlabel_set_text(usb_status, status_buf); } else if (e.source == btn_u2) { usb_open_wait(); jlabel_set_text(usb_status, "usb_open_wait: done"); } else if (e.source == btn_u3) { usb_close(); jlabel_set_text(usb_status, "usb_close: done"); } else if (e.source == btn_u4) { int rc = usb_write_async(usb_ff_bulk_output(), &header_text, sizeof(header_text), false, GINT_CALL_NULL); sprintf(status_buf, "WA TxtHead: %d", rc); jlabel_set_text(usb_status, status_buf); } else if (e.source == btn_u5) { int rc = usb_write_async(usb_ff_bulk_output(), &header_image, sizeof(header_image), false, GINT_CALL_NULL); sprintf(status_buf, "WA ImgHead: %d", rc); jlabel_set_text(usb_status, status_buf); } else if (e.source == btn_u6) { int rc = usb_write_async(usb_ff_bulk_output(), short_text, strlen(short_text), false, GINT_CALL_NULL); sprintf(status_buf, "WA Text: %d", rc); jlabel_set_text(usb_status, status_buf); } else if (e.source == btn_u7) { int rc = usb_write_async(usb_ff_bulk_output(), gint_vram, vram_size, false, GINT_CALL_NULL); sprintf(status_buf, "WA VRAM: %d", rc); jlabel_set_text(usb_status, status_buf); } else if (e.source == btn_u8) { int rc = usb_write_sync(usb_ff_bulk_output(), &header_text, sizeof(header_text), false); sprintf(status_buf, "WS TxtHead: %d", rc); jlabel_set_text(usb_status, status_buf); } else if (e.source == btn_u9) { int rc = usb_write_sync(usb_ff_bulk_output(), &header_image, sizeof(header_image), false); sprintf(status_buf, "WS ImgHead: %d", rc); jlabel_set_text(usb_status, status_buf); } else if (e.source == btn_u10) { int rc = usb_write_sync(usb_ff_bulk_output(), short_text, strlen(short_text), false); sprintf(status_buf, "WS Text: %d", rc); jlabel_set_text(usb_status, status_buf); } else if (e.source == btn_u11) { int rc = usb_write_sync(usb_ff_bulk_output(), gint_vram, vram_size, false); sprintf(status_buf, "WS VRAM: %d", rc); jlabel_set_text(usb_status, status_buf); } else if (e.source == btn_u12) { int rc = usb_commit_async(usb_ff_bulk_output(), GINT_CALL_NULL); sprintf(status_buf, "Commit A: %d", rc); jlabel_set_text(usb_status, status_buf); } else if (e.source == btn_u13) { usb_commit_sync(usb_ff_bulk_output()); jlabel_set_text(usb_status, "Commit S: done"); } else if (e.source == btn_u14) { int rc = usb_read_async(usb_ff_bulk_input(), read_buffer, 64, USB_READ_IGNORE_ZEROS, NULL, NULL, GINT_CALL_NULL); sprintf(status_buf, "Read A started: %d", rc); jlabel_set_text(usb_status, status_buf); } else if (e.source == btn_u15) { memset(read_buffer, 0, 64); int rc = usb_read_sync(usb_ff_bulk_input(), read_buffer, 64, false); sprintf(status_buf, "Read Sync: %d", rc); jlabel_set_text(usb_status, status_buf); } } else if (e.type == JWIDGET_KEY && e.key.type == KEYEV_DOWN) { if (e.key.key == KEY_EXIT || e.key.key == KEY_CLEAR) { running = false; } } }
jwidget_destroy(scene); return 1;}