From 8f10f5a4526f74ceb6c8a5643ca35e633297279d Mon Sep 17 00:00:00 2001 From: Andrzej Zaborowski Date: Mon, 29 Sep 2008 02:48:58 +0200 Subject: [PATCH] Add commandline options to make use of bluetooth features, e.g attach devices. --- vl.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 164 insertions(+), 0 deletions(-) diff --git a/vl.c b/vl.c index b19a631..cf913f9 100644 --- a/vl.c +++ b/vl.c @@ -5414,6 +5414,105 @@ struct HCIInfo *qemu_next_hci(void) return hci_table[cur_hci++]; } +static struct HCIInfo *hci_init(const char *str) +{ + char *endp; + struct bt_scatternet_s *vlan = 0; + + if (!strcmp(str, "null")) + /* bt null */ + return &null_hci; + else if (!strncmp(str, "host", 4) && (str[4] == '\0' || str[4] == ':')) + /* bt host[:hciN] */ + return bt_host_hci(str[4] ? str + 5 : "hci0"); + else if (!strncmp(str, "hci", 3)) { + /* bt hci[,vlan=n] */ + if (str[3]) { + if (!strncmp(str + 3, ",vlan=", 6)) { + vlan = qemu_find_bt_vlan(strtol(str + 9, &endp, 0)); + if (*endp) + vlan = 0; + } + } else + vlan = qemu_find_bt_vlan(0); + if (vlan) + return bt_new_hci(vlan); + } + + fprintf(stderr, "qemu: Unknown bluetooth HCI `%s'.\n", str); + + return 0; +} + +static int bt_hci_parse(const char *str) +{ + struct HCIInfo *hci; + bdaddr_t bdaddr; + + if (nb_hcis >= MAX_NICS) { + fprintf(stderr, "qemu: Too many bluetooth HCIs (max %i).\n", MAX_NICS); + return -1; + } + + hci = hci_init(str); + if (!hci) + return -1; + + bdaddr.b[0] = 0x52; + bdaddr.b[1] = 0x54; + bdaddr.b[2] = 0x00; + bdaddr.b[3] = 0x12; + bdaddr.b[4] = 0x34; + bdaddr.b[5] = 0x56 + nb_hcis; + hci->bdaddr_set(hci, bdaddr.b); + + hci_table[nb_hcis++] = hci; + + return 0; +} + +static void bt_vhci_add(int vlan_id) +{ + struct bt_scatternet_s *vlan = qemu_find_bt_vlan(vlan_id); + + if (!vlan->slave) + fprintf(stderr, "qemu: warning: adding a VHCI to " + "an empty scatternet %i\n", vlan_id); + + bt_vhci_init(bt_new_hci(vlan)); +} + +static struct bt_device_s *bt_device_add(const char *opt) +{ + struct bt_scatternet_s *vlan; + int vlan_id = 0; + char *endp = strchr(opt, ':'); + int len = (endp ? endp - opt : strlen(opt)) + 1; + char devname[10]; + + pstrcpy(devname, MIN(sizeof(devname), len), opt); + + if (endp) { + vlan_id = strtol(endp + 1, &endp, 0); + if (*endp) { + fprintf(stderr, "qemu: unrecognised bluetooth vlan Id\n"); + return 0; + } + } + + vlan = qemu_find_bt_vlan(vlan_id); + + if (!vlan->slave) + fprintf(stderr, "qemu: warning: adding a slave device to " + "an empty scatternet %i\n", vlan_id); + + if (!strcmp(devname, "keyboard")) + return bt_keyboard_init(vlan); + + fprintf(stderr, "qemu: unsupported bluetooth device `%s'\n", opt); + return 0; +} + /***********************************************************/ /* QEMU Block devices */ @@ -5864,6 +5963,9 @@ static int usb_device_add(const char *devname) return -1; nd_table[nic].model = "usb"; dev = usb_net_init(&nd_table[nic]); + } else if (!strcmp(devname, "bt") || strstart(devname, "bt:", &p)) { + dev = usb_bt_init(devname[2] ? hci_init(p) : + bt_new_hci(qemu_find_bt_vlan(0))); } else { return -1; } @@ -7791,6 +7893,13 @@ static void help(int exitcode) "-net none use it alone to have zero network devices; if no -net option\n" " is provided, the default is '-net nic -net user'\n" "\n" + "-bt null Dumb bluetooth HCI - doesn't respond to commands\n" + "-bt host[:id] Use host's HCI with the given name\n" + "-bt hci[,vlan=n]Emulate a standard HCI in virtual scatternet 'n'\n" + "-vhci n Add host computer to virtual scatternet 'n' using VHCI\n" + "-btdevice dev[,vlan=n]\n" + " Emulate a bluetooth device 'dev' in scatternet 'n'\n" + "\n" #ifdef CONFIG_SLIRP "-tftp dir allow tftp access to files in dir [-net user]\n" "-bootp file advertise file in BOOTP replies\n" @@ -7899,6 +8008,9 @@ enum { QEMU_OPTION_bootp, QEMU_OPTION_smb, QEMU_OPTION_redir, + QEMU_OPTION_bt, + QEMU_OPTION_btdevice, + QEMU_OPTION_vhci, QEMU_OPTION_kernel, QEMU_OPTION_append, @@ -7996,6 +8108,9 @@ const QEMUOption qemu_options[] = { #endif { "redir", HAS_ARG, QEMU_OPTION_redir }, #endif + { "bt", HAS_ARG, QEMU_OPTION_bt }, + { "btdevice", HAS_ARG, QEMU_OPTION_btdevice }, + { "vhci", HAS_ARG, QEMU_OPTION_vhci }, { "kernel", HAS_ARG, QEMU_OPTION_kernel }, { "append", HAS_ARG, QEMU_OPTION_append }, @@ -8333,6 +8448,12 @@ int main(int argc, char **argv) int cyls, heads, secs, translation; const char *net_clients[MAX_NET_CLIENTS]; int nb_net_clients; + const char *bt_opts[MAX_NET_CLIENTS]; + int nb_bt_opts; + int vhci_opts[MAX_NET_CLIENTS]; + int nb_vhci_opts; + const char *btdevice_opts[MAX_NET_CLIENTS]; + int nb_btdevice_opts; int hda_index; int optind; const char *r, *optarg; @@ -8415,6 +8536,9 @@ int main(int argc, char **argv) usb_devices_index = 0; nb_net_clients = 0; + nb_bt_opts = 0; + nb_vhci_opts = 0; + nb_btdevice_opts = 0; nb_drives = 0; nb_drives_opt = 0; hda_index = -1; @@ -8649,6 +8773,36 @@ int main(int argc, char **argv) net_slirp_redir(optarg); break; #endif + case QEMU_OPTION_bt: + if (nb_bt_opts >= MAX_NET_CLIENTS) { + fprintf(stderr, "qemu: too many bluetooth devices\n"); + exit(1); + } + bt_opts[nb_bt_opts++] = optarg; + break; + case QEMU_OPTION_vhci: + { + char *endp; + int vlan = strtol(optarg, &endp, 0); + + if (*endp) { + fprintf(stderr, "qemu: bad scatternet '%s'\n", optarg); + exit(1); + } + if (nb_vhci_opts >= MAX_NET_CLIENTS) { + fprintf(stderr, "qemu: too many VHCI HCIs\n"); + exit(1); + } + vhci_opts[nb_vhci_opts++] = vlan; + } + break; + case QEMU_OPTION_btdevice: + if (nb_btdevice_opts >= MAX_NET_CLIENTS) { + fprintf(stderr, "qemu: too many bluetooth slaves\n"); + exit(1); + } + btdevice_opts[nb_btdevice_opts++] = optarg; + break; #ifdef HAS_AUDIO case QEMU_OPTION_audio_help: AUD_help (); @@ -9118,6 +9272,16 @@ int main(int argc, char **argv) } #endif + /* init the bluetooth world */ + for (i = 0; i < nb_bt_opts; i++) + if (bt_hci_parse(bt_opts[i])) + exit(1); + for (i = 0; i < nb_vhci_opts; i++) + bt_vhci_add(vhci_opts[i]); + for (i = 0; i < nb_btdevice_opts; i++) + if (!bt_device_add(btdevice_opts[i])) + exit(1); + /* init the memory */ phys_ram_size = machine->ram_require & ~RAMSIZE_FIXED; -- 1.5.3.4