diff options
author | kraxel <kraxel> | 2008-10-17 22:46:47 +0000 |
---|---|---|
committer | kraxel <kraxel> | 2008-10-17 22:46:47 +0000 |
commit | 99537ea7f5f0622656b2a85e93fadcf875216349 (patch) | |
tree | ad29fe74cc01c69f921d861de8348441225d152c | |
parent | 3b6bd0694fa18ad018c2aff3611996097ece0acd (diff) | |
download | qemu-gtk-99537ea7f5f0622656b2a85e93fadcf875216349.tar.gz |
- usb hotplug
-rw-r--r-- | devices.c | 235 | ||||
-rw-r--r-- | monitor.c | 26 | ||||
-rw-r--r-- | qemu-gtk.c | 33 | ||||
-rw-r--r-- | qemu-gtk.h | 7 |
4 files changed, 267 insertions, 34 deletions
@@ -14,10 +14,32 @@ static char media_xml[] = "<ui>\n" " <menubar name='MainMenu'>\n" " <menu action='DevicesMenu'>\n" +" <menu action='ChangeMediaSubMenu'>\n" +"%s" +" </menu>\n" " <menu action='EjectMediaSubMenu'>\n" "%s" " </menu>\n" -" <menu action='ChangeMediaSubMenu'>\n" +" </menu>\n" +" </menubar>\n" +"</ui>\n"; + +static char plug_usb_xml[] = +"<ui>\n" +" <menubar name='MainMenu'>\n" +" <menu action='DevicesMenu'>\n" +" <menu action='PlugUsbSubMenu'>\n" +"%s" +" </menu>\n" +" </menu>\n" +" </menubar>\n" +"</ui>\n"; + +static char unplug_usb_xml[] = +"<ui>\n" +" <menubar name='MainMenu'>\n" +" <menu action='DevicesMenu'>\n" +" <menu action='UnplugUsbSubMenu'>\n" "%s" " </menu>\n" " </menu>\n" @@ -77,12 +99,63 @@ static void menu_cb_eject_media(GtkAction *action, void *data) monitor_append(win, "info block"); } +static void menu_cb_plug_usb(GtkAction *action, void *data) +{ + struct qemu_window *win = data; + char device[32], cmd[128]; + + if (1 != sscanf(gtk_action_get_name(action), "PlugUsb_%31s", device)) + return; + if (debug) + fprintf(stderr, "%s: %s\n", __FUNCTION__, device); + + snprintf(cmd, sizeof(cmd), "usb_add %s", device); + monitor_append(win, cmd); + monitor_append(win, "info usb"); +} + +static void menu_cb_unplug_usb(GtkAction *action, void *data) +{ + struct qemu_window *win = data; + char device[32], cmd[128]; + + if (1 != sscanf(gtk_action_get_name(action), "UnplugUsb_%31s", device)) + return; + if (debug) + fprintf(stderr, "%s: %s\n", __FUNCTION__, device); + + snprintf(cmd, sizeof(cmd), "usb_del %s", device); + monitor_append(win, cmd); + monitor_append(win, "info usb"); +} + +/* ----------------------------------------------------------------- */ + +static void add_entry(struct qemu_window *win, + GtkActionGroup *ag, + void (*cb)(GtkAction *action, void *data), + char **i_xml, int *i_pos, + char *label, char *type, char *name) +{ + GtkActionEntry entry; + char action[128]; + + snprintf(action, sizeof(action), "%s_%s", type, name); + memset(&entry, 0, sizeof(entry)); + entry.callback = G_CALLBACK(cb); + entry.name = action; + entry.label = label; + gtk_action_group_add_actions(ag, &entry, 1, win); + *i_xml = realloc(*i_xml, (*i_pos) + 128); + *i_pos += snprintf((*i_xml)+(*i_pos), 128, + " <menuitem action='%s'/>\n", action); +} + void devices_parse_info_block(struct qemu_window *win, char *str) { char name[32], type[16], line[256], *file, *ptr, *xml; - char action[128], label[128]; + char label[128]; int removable, pos, len, rc, eject; - GtkActionEntry c_entry, e_entry; char *c_xml = NULL, *e_xml = NULL; int c_pos = 0, e_pos = 0; GError *err = NULL; @@ -99,10 +172,6 @@ void devices_parse_info_block(struct qemu_window *win, char *str) } /* start */ - memset(&c_entry, 0, sizeof(c_entry)); - c_entry.callback = G_CALLBACK(menu_cb_change_media); - memset(&e_entry, 0, sizeof(e_entry)); - e_entry.callback = G_CALLBACK(menu_cb_eject_media); win->mc_ag = gtk_action_group_new("MediaActions"); /* parse & build */ @@ -135,29 +204,21 @@ void devices_parse_info_block(struct qemu_window *win, char *str) fprintf(stderr, "%s: %s (%s, %s) - [%s]\n", __FUNCTION__, name, type, file, line); - snprintf(action, sizeof(action), "ChangeMedia_%s", name); snprintf(label, sizeof(label), "%s (%s, %s)", name, type, file); - c_entry.name = action; - c_entry.label = label; - gtk_action_group_add_actions(win->mc_ag, &c_entry, 1, win); - c_xml = realloc(c_xml, c_pos + 128); - c_pos += snprintf(c_xml+c_pos, 128, " <menuitem action='%s'/>\n", action); + add_entry(win, win->mc_ag, menu_cb_change_media, &c_xml, &c_pos, + label, "ChangeMedia", name); if (eject) { - snprintf(action, sizeof(action), "EjectMedia_%s", name); snprintf(label, sizeof(label), "%s (%s, %s)", name, type, file); - e_entry.name = action; - e_entry.label = label; - gtk_action_group_add_actions(win->mc_ag, &e_entry, 1, win); - e_xml = realloc(e_xml, e_pos + 128); - e_pos += snprintf(e_xml+e_pos, 128, " <menuitem action='%s'/>\n", action); + add_entry(win, win->mc_ag, menu_cb_eject_media, &e_xml, &e_pos, + label, "EjectMedia", name); } } xml = malloc(e_pos + c_pos + strlen(media_xml)); sprintf(xml, media_xml, - e_pos ? e_xml : "", - c_pos ? c_xml : ""); + c_pos ? c_xml : "", + e_pos ? e_xml : ""); /* add */ if (debug) @@ -173,3 +234,135 @@ void devices_parse_info_block(struct qemu_window *win, char *str) free(e_xml); free(xml); } + +void devices_parse_info_usb(struct qemu_window *win, char *str) +{ + char device[16], name[64], speed[16], *xml; + char label[128]; + GError *err = NULL; + int pos, len, rc; + char *i_xml = NULL; + int i_pos = 0; + + /* remove */ + if (win->usb_id) { + gtk_ui_manager_remove_ui(win->ui, win->usb_id); + win->usb_id = 0; + } + if (win->usb_ag) { + gtk_ui_manager_remove_action_group(win->ui, win->usb_ag); + g_object_unref(win->usb_ag); + win->usb_ag = NULL; + } + + /* start */ + win->usb_ag = gtk_action_group_new("UnplugUsbActions"); + + /* parse & build */ + for (pos = 0;; pos += len) { + rc = sscanf(str+pos, " Device %15[^,], Speed %15s Mb/s, Product %63[^\r\n]%n", + device, speed, name, &len); + if (rc != 3) + break; + while (str[pos+len] == '\r' || str[pos+len] == '\n') + len++; + if (debug) + fprintf(stderr, "%s: %s - %s - %s\n", + __FUNCTION__, device, speed, name); + + snprintf(label, sizeof(label), "%s (%s)", name, device); + add_entry(win, win->usb_ag, menu_cb_unplug_usb, &i_xml, &i_pos, + label, "UnplugUsb", device); + } + + xml = malloc(i_pos + strlen(unplug_usb_xml)); + sprintf(xml, unplug_usb_xml, + i_pos ? i_xml : ""); + + /* add */ + if (debug) + fprintf(stderr, "---\n%s---\n", xml); + gtk_ui_manager_insert_action_group(win->ui, win->usb_ag, 1); + win->usb_id = gtk_ui_manager_add_ui_from_string(win->ui, xml, -1, &err); + if (!win->usb_id) { + g_message("building unplug usb menu failed: %s", err->message); + g_error_free(err); + } + + free(i_xml); + free(xml); +} + +void devices_parse_info_usbhost(struct qemu_window *win, char *str) +{ + char device[16], speed[16], class[32], name[64], *xml; + char action[128], label[128]; + GError *err = NULL; + int pos, len, rc, vendor, product; + char *i_xml = NULL; + int i_pos = 0; + + /* remove */ + if (win->usbhost_id) { + gtk_ui_manager_remove_ui(win->ui, win->usbhost_id); + win->usbhost_id = 0; + } + if (win->usbhost_ag) { + gtk_ui_manager_remove_action_group(win->ui, win->usbhost_ag); + g_object_unref(win->usbhost_ag); + win->usbhost_ag = NULL; + } + + /* start */ + win->usbhost_ag = gtk_action_group_new("PlugUsbActions"); + + /* parse & build */ + for (pos = 0;; pos += len) { + rc = sscanf(str+pos, + " Device %15[^,], speed %15s Mb/s\n" + " %31[^:]: USB device %x:%x, %63[^\r\n]%n", + device, speed, class, &vendor, &product, name, &len); + if (rc != 6) + break; + while (str[pos+len] == '\r' || str[pos+len] == '\n') + len++; + if (0 == strcmp("Hub", class)) + continue; + if (1 || debug) + fprintf(stderr, "%s: %s (%04x:%04x) - %s - %s\n", + __FUNCTION__, device, vendor, product, class, name); + + snprintf(label, sizeof(label), "%s (host %s)", name, device); + snprintf(action, sizeof(action), "host:%s", device); + add_entry(win, win->usbhost_ag, menu_cb_plug_usb, &i_xml, &i_pos, + label, "PlugUsb", action); + } + + /* static */ + add_entry(win, win->usbhost_ag, menu_cb_plug_usb, &i_xml, &i_pos, + "QEMU USB Tablet (virtual)", "PlugUsb", "tablet"); + + xml = malloc(i_pos + strlen(plug_usb_xml)); + sprintf(xml, plug_usb_xml, + i_pos ? i_xml : ""); + + /* add */ + if (debug) + fprintf(stderr, "---\n%s---\n", xml); + gtk_ui_manager_insert_action_group(win->ui, win->usbhost_ag, 1); + win->usbhost_id = gtk_ui_manager_add_ui_from_string(win->ui, xml, -1, &err); + if (!win->usbhost_id) { + g_message("building host usb menu failed: %s", err->message); + g_error_free(err); + } + + free(i_xml); + free(xml); +} + +void devices_rescan(struct qemu_window *win) +{ + monitor_append(win, "info block"); + monitor_append(win, "info usb"); + monitor_append(win, "info usbhost"); +} @@ -70,13 +70,14 @@ static int monitor_parse(struct qemu_window *win, char *buf, int len) cmd = win->mrun->cmd; reply = strstr(buf, "\r\n"); if (!reply) { + reply = ""; if (debug) - fprintf(stderr, "%s: no reply for \"%s\"\n", __FUNCTION__, cmd); - goto out; + fprintf(stderr, "%s: empty reply for \"%s\"\n", __FUNCTION__, cmd); + } else { + reply += 2; + if (debug) + fprintf(stderr, "%s: \"%s\" -> [%s]\n", __FUNCTION__, cmd, reply); } - reply += 2; - if (debug) - fprintf(stderr, "%s: \"%s\" -> [%s]\n", __FUNCTION__, cmd, reply); /* parse reply */ if (0 == strcmp(cmd, "info version")) { @@ -111,9 +112,18 @@ static int monitor_parse(struct qemu_window *win, char *buf, int len) } else if (0 == strcmp(cmd, "info block")) { devices_parse_info_block(win, reply); + } else if (0 == strcmp(cmd, "info usb")) { + devices_parse_info_usb(win, reply); + + } else if (0 == strcmp(cmd, "info usbhost")) { + devices_parse_info_usbhost(win, reply); + } else if (0 == strncmp(cmd, "eject ", 6) || - 0 == strncmp(cmd, "change ", 7)) { - show_error(win, cmd, reply); + 0 == strncmp(cmd, "change ", 7) || + 0 == strncmp(cmd, "usb_add ", 8) || + 0 == strncmp(cmd, "usb_del ", 8)) { + if (strlen(reply)) + show_error(win, cmd, reply); } out: @@ -234,6 +244,6 @@ int monitor_connect(struct qemu_window *win, char *dest) monitor_append(win, "info version"); monitor_append(win, "info name"); monitor_append(win, "info vnc"); - monitor_append(win, "info block"); + devices_rescan(win); return fd; } @@ -101,7 +101,6 @@ static void vte_configure(struct qemu_window *win, GtkWidget *vte) vte_terminal_set_backspace_binding(VTE_TERMINAL(vte), VTE_ERASE_ASCII_BACKSPACE); - fprintf(stderr, "%s: %s %s\n", __FUNCTION__, win->tty_fg, win->tty_bg); gdk_color_parse(win->tty_fg, &fg); gdk_color_parse(win->tty_bg, &bg); vte_terminal_set_color_foreground(VTE_TERMINAL(vte), &fg); @@ -227,6 +226,7 @@ static void menu_cb_config_font(GtkAction *action, void *data) win->tty_font = gtk_font_selection_dialog_get_font_name (GTK_FONT_SELECTION_DIALOG(dialog)); g_key_file_set_string(config, "tty", "font", win->tty_font); + config_dirty++; vtes_set_font(win); break; } @@ -254,6 +254,7 @@ static int pickcolor(char *title, char *group, char *key, char *current) snprintf(name, sizeof(name), "#%04x%04x%04x", color.red, color.green, color.blue); g_key_file_set_string(config, group, key, name); + config_dirty++; rc = 0; } gtk_widget_destroy(dialog); @@ -292,6 +293,12 @@ static void menu_cb_send_ctrlaltdel(GtkToggleAction *action, gpointer userdata) VNC_DISPLAY_KEY_EVENT_CLICK); } +static void menu_cb_devices_rescan(GtkToggleAction *action, gpointer userdata) +{ + struct qemu_window *win = userdata; + devices_rescan(win); +} + static void menu_cb_about(GtkAction *action, gpointer userdata) { static char *comments = "gtk ui for qemu"; @@ -595,11 +602,17 @@ static const GtkActionEntry entries[] = { },{ /* --- sub menus --- */ + .name = "ChangeMediaSubMenu", + .label = "_Change media", + },{ .name = "EjectMediaSubMenu", .label = "_Eject media", },{ - .name = "ChangeMediaSubMenu", - .label = "_Change media", + .name = "PlugUsbSubMenu", + .label = "_Plugin USB", + },{ + .name = "UnplugUsbSubMenu", + .label = "_Unplug USB", },{ /* --- file menu --- */ @@ -656,6 +669,12 @@ static const GtkActionEntry entries[] = { .callback = G_CALLBACK(menu_cb_run_gdb), },{ + /* --- devices menu --- */ + .name = "DevicesRescan", + .label = "_Rescan devices", + .callback = G_CALLBACK(menu_cb_devices_rescan), + },{ + /* --- help menu --- */ .name = "About", .stock_id = GTK_STOCK_ABOUT, @@ -716,8 +735,12 @@ static char ui_xml[] = " <menuitem action='RunGdb'/>" " </menu>" " <menu action='DevicesMenu'>" -" <menu action='EjectMediaSubMenu'/>" " <menu action='ChangeMediaSubMenu'/>" +" <menu action='EjectMediaSubMenu'/>" +" <menu action='PlugUsbSubMenu'/>" +" <menu action='UnplugUsbSubMenu'/>" +" <separator/>" +" <menuitem action='DevicesRescan'/>" " </menu>" " <menu action='HelpMenu'>" " <menuitem action='About'/>" @@ -812,7 +835,7 @@ static struct qemu_window *qemu_create_window(void) win->tty_bg = g_key_file_get_string(config, "tty", "background", &err); /* config defaults */ - if (!win->tty_fg) + if (!win->tty_font) win->tty_font = "console 12"; if (!win->tty_fg) win->tty_fg = "white"; @@ -55,6 +55,10 @@ struct qemu_window { /* devices */ GtkActionGroup *mc_ag; guint mc_id; + GtkActionGroup *usb_ag; + guint usb_id; + GtkActionGroup *usbhost_ag; + guint usbhost_id; /* gdb */ GtkWidget *gdb_vte; @@ -88,3 +92,6 @@ void monitor_append(struct qemu_window *win, char *cmd); /* devices.c */ void devices_parse_info_block(struct qemu_window *win, char *str); +void devices_parse_info_usb(struct qemu_window *win, char *str); +void devices_parse_info_usbhost(struct qemu_window *win, char *str); +void devices_rescan(struct qemu_window *win); |