From 6356c03bceba4ef974d277d9f28a7a05253a2d71 Mon Sep 17 00:00:00 2001 From: Volker Ruppert Date: Sat, 1 Feb 2025 11:54:21 +0100 Subject: [PATCH] GTK USB debugger: Some work on the xHCI context dialog. Fill in strings for read-only items. Prepared save-to-context feature (detect EP context item changes). TODO: save changes to context, string context dialog. --- bochs/gui/gtk_usb_debug.cc | 124 +++++++++++++++++++++++++++++++------ bochs/gui/usb_debug.cc | 75 ++++++++++++++++++++++ bochs/gui/usb_debug.h | 17 +++++ bochs/gui/win32usb.cc | 75 ---------------------- 4 files changed, 197 insertions(+), 94 deletions(-) diff --git a/bochs/gui/gtk_usb_debug.cc b/bochs/gui/gtk_usb_debug.cc index da9a4caf3..eaadac501 100644 --- a/bochs/gui/gtk_usb_debug.cc +++ b/bochs/gui/gtk_usb_debug.cc @@ -1303,11 +1303,6 @@ void xhci_message_dialog(GtkWindow *parent, const char *msg) gtk_widget_destroy(error); } -static Bit64u xhci_context_address = 0; -static Bit8u *xhci_context = NULL; -static int xhci_current_ep_context = 1; // 0 through 30 (slot, control_ep, ep1_out, ep1_in, ep2_out, ep2_in, etc) -static bool xhci_context_changed = 0; - static void xhci_string_context_dialog(GtkWidget *widget, gpointer data) { // TODO @@ -1355,7 +1350,7 @@ static void xhci_context_flags_dialog(GtkWidget *widget, gpointer data) GtkWidget *apply_button_2; -static void xhci_context_ep_apply(GtkWidget *widget, gpointer data) +static void xhci_ep_context_apply(GtkWidget *widget, gpointer data) { GtkWidget **CTXitem = (GtkWidget**)data; @@ -1367,7 +1362,16 @@ static void xhci_context_ep_apply(GtkWidget *widget, gpointer data) gtk_widget_set_sensitive(apply_button_2, 0); } -static void xhci_context_ep_select(GtkWidget *widget, gpointer data) +bool xhci_ep_context_change_dlg(GtkWindow *parent) +{ + GtkWidget *ask = gtk_message_dialog_new(parent, GTK_DIALOG_MODAL, + GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "%s", "Save EP context changes ?"); + int ret = gtk_dialog_run(GTK_DIALOG(ask)); + gtk_widget_destroy(ask); + return (ret == GTK_RESPONSE_YES); +} + +static void xhci_ep_context_select(GtkWidget *widget, gpointer data) { GtkWidget **CTXitem = (GtkWidget**)data; char str[COMMON_STR_SIZE]; @@ -1377,9 +1381,9 @@ static void xhci_context_ep_select(GtkWidget *widget, gpointer data) if (widget == CTXitem[ID_CONTEXT_PREV]) { if (xhci_current_ep_context > 1) { if (xhci_context_changed) { - // TODO - xhci_message_dialog(GTK_WINDOW(gtk_widget_get_toplevel(widget)), - "Saving EP context changes not implemented yet"); + if (xhci_ep_context_change_dlg(GTK_WINDOW(gtk_widget_get_toplevel(widget)))) { + xhci_ep_context_apply(widget, data); + } } xhci_current_ep_context--; } else { @@ -1388,9 +1392,9 @@ static void xhci_context_ep_select(GtkWidget *widget, gpointer data) } else if (widget == CTXitem[ID_CONTEXT_NEXT]) { if (xhci_current_ep_context < 31) { if (xhci_context_changed) { - // TODO - xhci_message_dialog(GTK_WINDOW(gtk_widget_get_toplevel(widget)), - "Saving EP context changes not implemented yet"); + if (xhci_ep_context_change_dlg(GTK_WINDOW(gtk_widget_get_toplevel(widget)))) { + xhci_ep_context_apply(widget, data); + } } xhci_current_ep_context++; } else { @@ -1466,10 +1470,53 @@ static void xhci_context_ep_select(GtkWidget *widget, gpointer data) gtk_widget_set_sensitive(apply_button_2, 0); } +static void context_string_changed(GtkWidget *widget, gpointer data) +{ + GtkWidget **CTXitem = (GtkWidget**)data; + char str[COMMON_STR_SIZE]; + int i; + + strcpy(str, gtk_entry_get_text(GTK_ENTRY(widget))); + if (widget == CTXitem[ID_CONTEXT_SPEED]) { + i = strtol(str, NULL, 0); + if (i > 15) i = 16; + gtk_entry_set_text(GTK_ENTRY(CTXitem[ID_CONTEXT_SPEED_STR]), slot_speed_str[i]); + } else if (widget == CTXitem[ID_CONTEXT_SLOT_STATE]) { + i = strtol(str, NULL, 0); + if (i > 3) i = 4; + gtk_entry_set_text(GTK_ENTRY(CTXitem[ID_CONTEXT_SLOT_STATE_STR]), slot_type_str[i]); + } else if (widget == CTXitem[ID_CONTEXT_EP_STATE]) { + i = strtol(str, NULL, 0); + if (i > 7) i = 7; + gtk_entry_set_text(GTK_ENTRY(CTXitem[ID_CONTEXT_EP_STATE_STR]), ep_state_str[i]); + } else if (widget == CTXitem[ID_CONTEXT_EP_TYPE]) { + i = strtol(str, NULL, 0); + if (i > 7) i = 7; + gtk_entry_set_text(GTK_ENTRY(CTXitem[ID_CONTEXT_EP_TYPE_STR]), ep_type_str[i]); + } else if (widget == CTXitem[ID_CONTEXT_MAX_PSTREAMS]) { + i = strtol(str, NULL, 0); + if (i == 0) + gtk_entry_set_text(GTK_ENTRY(CTXitem[ID_CONTEXT_MAXPS_STR]), "None"); + else if (i <= 15) { + sprintf(str, "%i", (1 << (i + 1))); + gtk_entry_set_text(GTK_ENTRY(CTXitem[ID_CONTEXT_MAXPS_STR]), str); + } else + gtk_entry_set_text(GTK_ENTRY(CTXitem[ID_CONTEXT_MAXPS_STR]), "Error"); + gtk_widget_set_sensitive(GTK_WIDGET(CTXitem[ID_CONTEXT_STREAM_CONTEXT]), (i > 0) && (i <=15)); + } +} + static void ep_context_entry_changed(GtkWidget *widget, gpointer data) { - *((bool*)data) = 1; + GtkWidget **CTXitem = (GtkWidget**)data; + + xhci_context_changed = 1; gtk_widget_set_sensitive(apply_button_2, 1); + if ((widget == CTXitem[ID_CONTEXT_MAX_PSTREAMS]) || + (widget == CTXitem[ID_CONTEXT_EP_STATE]) || + (widget == CTXitem[ID_CONTEXT_EP_TYPE])) { + context_string_changed(widget, data); + } } static void xhci_context_dialog(GtkWidget *widget, gpointer data) @@ -1526,11 +1573,11 @@ static void xhci_context_dialog(GtkWidget *widget, gpointer data) CTXitem[ID_CONTEXT_INTFACE_NUM] = usbdlg_create_entry_with_label(grid, "Interface Num", 3, 1); CTXitem[ID_CONTEXT_CONFIG_VALUE] = usbdlg_create_entry_with_label(grid, "Config Value", 3, 2); CTXitem[ID_CONTEXT_PREV] = gtk_button_new_with_label("<<"); - g_signal_connect(CTXitem[ID_CONTEXT_PREV], "clicked", G_CALLBACK(xhci_context_ep_select), &CTXitem); + g_signal_connect(CTXitem[ID_CONTEXT_PREV], "clicked", G_CALLBACK(xhci_ep_context_select), &CTXitem); gtk_grid_attach(GTK_GRID(grid), CTXitem[ID_CONTEXT_PREV], 5, 2, 1, 1); CTXitem[ID_CONTEXT_OF_STR] = usbdlg_create_ro_entry(grid, 6, 2); CTXitem[ID_CONTEXT_NEXT] = gtk_button_new_with_label(">>"); - g_signal_connect(CTXitem[ID_CONTEXT_NEXT], "clicked", G_CALLBACK(xhci_context_ep_select), &CTXitem); + g_signal_connect(CTXitem[ID_CONTEXT_NEXT], "clicked", G_CALLBACK(xhci_ep_context_select), &CTXitem); gtk_grid_attach(GTK_GRID(grid), CTXitem[ID_CONTEXT_NEXT], 7, 2, 1, 1); SLframe = gtk_frame_new("Slot Context"); @@ -1545,6 +1592,8 @@ static void xhci_context_dialog(GtkWidget *widget, gpointer data) CTXitem[ID_CONTEXT_MTT] = gtk_check_button_new_with_label("MTT"); gtk_grid_attach(GTK_GRID(SLgrid), CTXitem[ID_CONTEXT_MTT], 1, 2, 1, 1); CTXitem[ID_CONTEXT_SPEED] = usbdlg_create_entry_with_label(SLgrid, "Speed", 0, 3); + g_signal_connect(GTK_EDITABLE(CTXitem[ID_CONTEXT_SPEED]), "changed", + G_CALLBACK(context_string_changed), &CTXitem); CTXitem[ID_CONTEXT_SPEED_STR] = usbdlg_create_ro_entry(SLgrid, 2, 3); CTXitem[ID_CONTEXT_ROUTE_STRING] = usbdlg_create_entry_with_label(SLgrid, "Route String", 0, 4); CTXitem[ID_CONTEXT_NUM_PORTS] = usbdlg_create_entry_with_label(SLgrid, "Number of Ports", 0, 5); @@ -1555,6 +1604,8 @@ static void xhci_context_dialog(GtkWidget *widget, gpointer data) CTXitem[ID_CONTEXT_TT_PORT_NUM] = usbdlg_create_entry_with_label(SLgrid, "TT Port Number", 0, 10); CTXitem[ID_CONTEXT_TT_HUB_SLOT_ID] = usbdlg_create_entry_with_label(SLgrid, "TT Hub Slot ID", 0, 11); CTXitem[ID_CONTEXT_SLOT_STATE] = usbdlg_create_entry_with_label(SLgrid, "Slot State", 0, 12); + g_signal_connect(GTK_EDITABLE(CTXitem[ID_CONTEXT_SLOT_STATE]), "changed", + G_CALLBACK(context_string_changed), &CTXitem); CTXitem[ID_CONTEXT_SLOT_STATE_STR] = usbdlg_create_ro_entry(SLgrid, 2, 12); CTXitem[ID_CONTEXT_DEV_ADDRESS] = usbdlg_create_entry_with_label(SLgrid, "USB Device Address", 0, 13); for (i = 0; i < 12; i++) { @@ -1572,37 +1623,67 @@ static void xhci_context_dialog(GtkWidget *widget, gpointer data) gtk_grid_set_column_spacing(GTK_GRID(EPgrid), 5); gtk_container_add(GTK_CONTAINER(EPframe), EPgrid); apply_button_2 = gtk_button_new_with_label(g_dgettext("gtk30", "_Apply")); - g_signal_connect(apply_button_2, "clicked", G_CALLBACK(xhci_context_ep_apply), &CTXitem); + g_signal_connect(apply_button_2, "clicked", G_CALLBACK(xhci_ep_context_apply), &CTXitem); gtk_grid_attach(GTK_GRID(EPgrid), apply_button_2, 2, 0, 1, 1); CTXitem[ID_CONTEXT_MAX_ESIT_HI] = usbdlg_create_entry_with_label(EPgrid, "Max ESIT Payload Hi", 0, 1); g_signal_connect(GTK_EDITABLE(CTXitem[ID_CONTEXT_MAX_ESIT_HI]), "changed", - G_CALLBACK(ep_context_entry_changed), &xhci_context_changed); + G_CALLBACK(ep_context_entry_changed), &CTXitem); CTXitem[ID_CONTEXT_INTERVAL] = usbdlg_create_entry_with_label(EPgrid, "Interval", 0, 2); + g_signal_connect(GTK_EDITABLE(CTXitem[ID_CONTEXT_INTERVAL]), "changed", + G_CALLBACK(ep_context_entry_changed), &CTXitem); CTXitem[ID_CONTEXT_LSA] = gtk_check_button_new_with_label("LSA"); + g_signal_connect(GTK_TOGGLE_BUTTON(CTXitem[ID_CONTEXT_LSA]), "toggled", + G_CALLBACK(ep_context_entry_changed), &CTXitem); gtk_grid_attach(GTK_GRID(EPgrid), CTXitem[ID_CONTEXT_LSA], 1, 3, 1, 1); CTXitem[ID_CONTEXT_MAX_PSTREAMS] = usbdlg_create_entry_with_label(EPgrid, "MaxPStreams", 0, 4); + g_signal_connect(GTK_EDITABLE(CTXitem[ID_CONTEXT_MAX_PSTREAMS]), "changed", + G_CALLBACK(ep_context_entry_changed), &CTXitem); CTXitem[ID_CONTEXT_MAXPS_STR] = usbdlg_create_ro_entry(EPgrid, 2, 4); CTXitem[ID_CONTEXT_MULT] = usbdlg_create_entry_with_label(EPgrid, "Mult", 0, 5); + g_signal_connect(GTK_EDITABLE(CTXitem[ID_CONTEXT_MULT]), "changed", + G_CALLBACK(ep_context_entry_changed), &CTXitem); CTXitem[ID_CONTEXT_EP_STATE] = usbdlg_create_entry_with_label(EPgrid, "EP State", 0, 6); + g_signal_connect(GTK_EDITABLE(CTXitem[ID_CONTEXT_EP_STATE]), "changed", + G_CALLBACK(ep_context_entry_changed), &CTXitem); CTXitem[ID_CONTEXT_EP_STATE_STR] = usbdlg_create_ro_entry(EPgrid, 2, 6); CTXitem[ID_CONTEXT_MAX_PACKET_SIZE] = usbdlg_create_entry_with_label(EPgrid, "Max Packet Size", 0, 7); + g_signal_connect(GTK_EDITABLE(CTXitem[ID_CONTEXT_MAX_PACKET_SIZE]), "changed", + G_CALLBACK(ep_context_entry_changed), &CTXitem); CTXitem[ID_CONTEXT_MAX_BURST_SIZE] = usbdlg_create_entry_with_label(EPgrid, "Max Burst Size", 0, 8); + g_signal_connect(GTK_EDITABLE(CTXitem[ID_CONTEXT_MAX_BURST_SIZE]), "changed", + G_CALLBACK(ep_context_entry_changed), &CTXitem); CTXitem[ID_CONTEXT_HID] = gtk_check_button_new_with_label("HID"); + g_signal_connect(GTK_TOGGLE_BUTTON(CTXitem[ID_CONTEXT_HID]), "toggled", + G_CALLBACK(ep_context_entry_changed), &CTXitem); gtk_grid_attach(GTK_GRID(EPgrid), CTXitem[ID_CONTEXT_HID], 1, 9, 1, 1); CTXitem[ID_CONTEXT_EP_TYPE] = usbdlg_create_entry_with_label(EPgrid, "EP Type", 0, 10); + g_signal_connect(GTK_EDITABLE(CTXitem[ID_CONTEXT_EP_TYPE]), "changed", + G_CALLBACK(ep_context_entry_changed), &CTXitem); CTXitem[ID_CONTEXT_EP_TYPE_STR] = usbdlg_create_ro_entry(EPgrid, 2, 10); CTXitem[ID_CONTEXT_CERR] = usbdlg_create_entry_with_label(EPgrid, "CErr", 0, 11); + g_signal_connect(GTK_EDITABLE(CTXitem[ID_CONTEXT_CERR]), "changed", + G_CALLBACK(ep_context_entry_changed), &CTXitem); CTXitem[ID_CONTEXT_TR_DEQUEUE_PTR] = usbdlg_create_entry_with_label(EPgrid, "TR Dequeue Pointer", 0, 12); + g_signal_connect(GTK_EDITABLE(CTXitem[ID_CONTEXT_TR_DEQUEUE_PTR]), "changed", + G_CALLBACK(ep_context_entry_changed), &CTXitem); CTXitem[ID_CONTEXT_STREAM_CONTEXT] = gtk_button_new_with_label(">"); g_signal_connect(CTXitem[ID_CONTEXT_STREAM_CONTEXT], "clicked", G_CALLBACK(xhci_string_context_dialog), NULL); gtk_grid_attach(GTK_GRID(EPgrid), CTXitem[ID_CONTEXT_STREAM_CONTEXT], 2, 12, 1, 1); CTXitem[ID_CONTEXT_DCS] = gtk_check_button_new_with_label("DCS"); + g_signal_connect(GTK_TOGGLE_BUTTON(CTXitem[ID_CONTEXT_DCS]), "toggled", + G_CALLBACK(ep_context_entry_changed), &CTXitem); gtk_grid_attach(GTK_GRID(EPgrid), CTXitem[ID_CONTEXT_DCS], 1, 13, 1, 1); CTXitem[ID_CONTEXT_MAX_ESIT_LO] = usbdlg_create_entry_with_label(EPgrid, "Max ESIT Payload Lo", 0, 14); + g_signal_connect(GTK_EDITABLE(CTXitem[ID_CONTEXT_MAX_ESIT_LO]), "changed", + G_CALLBACK(ep_context_entry_changed), &CTXitem); CTXitem[ID_CONTEXT_AVERAGE_LEN] = usbdlg_create_entry_with_label(EPgrid, "Average TRB Length", 0, 15); + g_signal_connect(GTK_EDITABLE(CTXitem[ID_CONTEXT_AVERAGE_LEN]), "changed", + G_CALLBACK(ep_context_entry_changed), &CTXitem); for (i = 0; i < 11; i++) { sprintf(str, "RsvdO (%02Xh-%02Xh)", 20 + (i << 2) + 3, 20 + (i << 2)); CTXitem[ID_CONTEXT_RSVDO_EP_0 + i] = usbdlg_create_entry_with_label(EPgrid, str, 0, 16 + i); + g_signal_connect(GTK_EDITABLE(CTXitem[ID_CONTEXT_RSVDO_EP_0 + i]), "changed", + G_CALLBACK(ep_context_entry_changed), &CTXitem); if (i > 3) { gtk_widget_set_sensitive(CTXitem[ID_CONTEXT_RSVDO_EP_0 + i], 0); } @@ -1665,12 +1746,17 @@ static void xhci_context_dialog(GtkWidget *widget, gpointer data) #endif // Endpoint Context - xhci_context_ep_select(NULL, &CTXitem); + xhci_ep_context_select(NULL, &CTXitem); // Show dialog gtk_widget_show_all(dialog); ret = gtk_dialog_run(GTK_DIALOG(dialog)); if (ret == GTK_RESPONSE_OK) { + if (xhci_context_changed) { + if (xhci_ep_context_change_dlg(GTK_WINDOW(dialog))) { + xhci_ep_context_apply(apply_button_2, &CTXitem); + } + } // TODO } delete [] xhci_context; diff --git a/bochs/gui/usb_debug.cc b/bochs/gui/usb_debug.cc index 6a96cba45..ae3eda799 100644 --- a/bochs/gui/usb_debug.cc +++ b/bochs/gui/usb_debug.cc @@ -194,6 +194,81 @@ const char *ring_type[] = { "Transfer" // VIEW_TRB_TYPE_TRANSFER }; +Bit64u xhci_context_address = 0; +Bit8u *xhci_context = NULL; +int xhci_current_ep_context = 1; // 0 through 30 (slot, control_ep, ep1_out, ep1_in, ep2_out, ep2_in, etc) +bool xhci_context_changed = 0; + +Bit64u xhci_str_context_address = 0; +Bit8u *xhci_str_context = NULL; +int xhci_str_current_context = 0; +bool xhci_str_context_changed = 0; +int xhci_max_streams = 0; + +const char *slot_speed_str[] = { + "Undefined", + "Full", + "Low", + "High", + "Super Gen1x1", + "Super Gen2x1", + "Super Gen1x2", + "Super Gen2x2", + "Undefined", + "Undefined", + "Undefined", + "Undefined", + "Undefined", + "Undefined", + "Undefined", + "Undefined", + "Not Valid" +}; + +const char *slot_type_str[] = { + "Disabled/Enabled", + "Default", + "Addressed", + "Configured", + "Reserved" +}; + +const char *ep_type_str[] = { + "n/a", + "ISO Out", + "Bulk Out", + "Int Out", + "Control", + "ISO In", + "Bulk In", + "Int In", + "Not Valid" +}; + +const char *ep_state_str[] = { + "Disabled", + "Running", + "Halted", + "Stopped", + "Error", + "Reserved", + "Reserved", + "Reserved", + "Not Valid" +}; + +const char *string_sct_str[] = { + "Secondary / Transfer Ring / N/A", + "Primary / Transfer Ring / N/A", + "Primary / SSA / 8", + "Primary / SSA / 16", + "Primary / SSA / 32", + "Primary / SSA / 64", + "Primary / SSA / 128", + "Primary / SSA / 256", + "Error" +}; + int usb_debug_type = USB_DEBUG_NONE; bx_param_c *host_param = NULL; Bit32u pci_bar_address; diff --git a/bochs/gui/usb_debug.h b/bochs/gui/usb_debug.h index c643049a3..ffaef3c6f 100644 --- a/bochs/gui/usb_debug.h +++ b/bochs/gui/usb_debug.h @@ -117,6 +117,23 @@ extern struct S_ATTRIBUTES attribs_x_ports[]; extern const struct VIEW_TRB_TYPE trb_types[]; extern const char *ring_type[]; +extern Bit64u xhci_context_address; +extern Bit8u *xhci_context; +extern int xhci_current_ep_context; +extern bool xhci_context_changed; + +extern Bit64u xhci_str_context_address; +extern Bit8u *xhci_str_context; +extern int xhci_str_current_context; +extern bool xhci_str_context_changed; +extern int xhci_max_streams; + +extern const char *slot_speed_str[]; +extern const char *slot_type_str[]; +extern const char *ep_type_str[]; +extern const char *ep_state_str[]; +extern const char *string_sct_str[]; + // USB debug API void usb_dbg_register_type(int type); diff --git a/bochs/gui/win32usb.cc b/bochs/gui/win32usb.cc index 5913dcdd0..02fcc27aa 100644 --- a/bochs/gui/win32usb.cc +++ b/bochs/gui/win32usb.cc @@ -2937,81 +2937,6 @@ INT_PTR CALLBACK hc_xhci_callback_trb_necfwevent(HWND hDlg, UINT msg, WPARAM wPa return 0; } -static Bit64u xhci_context_address = 0; -static Bit8u *xhci_context = NULL; -static int xhci_current_ep_context = 1; // 0 through 30 (slot, control_ep, ep1_out, ep1_in, ep2_out, ep2_in, etc) -static bool xhci_context_changed = 0; - -static Bit64u xhci_str_context_address = 0; -static Bit8u *xhci_str_context = NULL; -static int xhci_str_current_context = 0; -static bool xhci_str_context_changed = 0; -static int xhci_max_streams = 0; - -static const char *slot_speed_str[] = { - "Undefined", - "Full", - "Low", - "High", - "Super Gen1x1", - "Super Gen2x1", - "Super Gen1x2", - "Super Gen2x2", - "Undefined", - "Undefined", - "Undefined", - "Undefined", - "Undefined", - "Undefined", - "Undefined", - "Undefined", - "Not Valid" -}; - -static const char *slot_type_str[] = { - "Disabled/Enabled", - "Default", - "Addressed", - "Configured", - "Reserved" -}; - -static const char *ep_type_str[] = { - "n/a", - "ISO Out", - "Bulk Out", - "Int Out", - "Control", - "ISO In", - "Bulk In", - "Int In", - "Not Valid" -}; - -static const char *ep_state_str[] = { - "Disabled", - "Running", - "Halted", - "Stopped", - "Error", - "Reserved", - "Reserved", - "Reserved", - "Not Valid" -}; - -static const char *string_sct_str[] = { - "Secondary / Transfer Ring / N/A", - "Primary / Transfer Ring / N/A", - "Primary / SSA / 8", - "Primary / SSA / 16", - "Primary / SSA / 32", - "Primary / SSA / 64", - "Primary / SSA / 128", - "Primary / SSA / 256", - "Error" -}; - // xHCI 1.2: 6.2.5.1, Page 461 static void hc_xhci_callback_context_ep_get(HWND hDlg) {