aboutsummaryrefslogtreecommitdiffstats
path: root/devices.c
diff options
context:
space:
mode:
authorkraxel <kraxel>2008-10-17 22:46:47 +0000
committerkraxel <kraxel>2008-10-17 22:46:47 +0000
commit99537ea7f5f0622656b2a85e93fadcf875216349 (patch)
treead29fe74cc01c69f921d861de8348441225d152c /devices.c
parent3b6bd0694fa18ad018c2aff3611996097ece0acd (diff)
downloadqemu-gtk-99537ea7f5f0622656b2a85e93fadcf875216349.tar.gz
- usb hotplug
Diffstat (limited to 'devices.c')
-rw-r--r--devices.c235
1 files changed, 214 insertions, 21 deletions
diff --git a/devices.c b/devices.c
index 7d76580..a8cb8bd 100644
--- a/devices.c
+++ b/devices.c
@@ -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");
+}