Commit dc72ac14d8ceeaac0ca63f385ba3f44fd580b963
1 parent
793a10a2
Add the -bt switch for setting up bluetooth stuff.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5652 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
172 additions
and
2 deletions
vl.c
... | ... | @@ -169,6 +169,9 @@ |
169 | 169 | /* Max number of USB devices that can be specified on the commandline. */ |
170 | 170 | #define MAX_USB_CMDLINE 8 |
171 | 171 | |
172 | +/* Max number of bluetooth switches on the commandline. */ | |
173 | +#define MAX_BT_CMDLINE 10 | |
174 | + | |
172 | 175 | /* XXX: use a two level table to limit memory usage */ |
173 | 176 | #define MAX_IOPORTS 65536 |
174 | 177 | |
... | ... | @@ -1935,7 +1938,7 @@ int check_params(char *buf, int buf_size, |
1935 | 1938 | static int nb_hcis; |
1936 | 1939 | static int cur_hci; |
1937 | 1940 | static struct HCIInfo *hci_table[MAX_NICS]; |
1938 | -#if 0 | |
1941 | + | |
1939 | 1942 | static struct bt_vlan_s { |
1940 | 1943 | struct bt_scatternet_s net; |
1941 | 1944 | int id; |
... | ... | @@ -1958,7 +1961,6 @@ static struct bt_scatternet_s *qemu_find_bt_vlan(int id) |
1958 | 1961 | *pvlan = vlan; |
1959 | 1962 | return &vlan->net; |
1960 | 1963 | } |
1961 | -#endif | |
1962 | 1964 | |
1963 | 1965 | static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, int len) |
1964 | 1966 | { |
... | ... | @@ -1984,6 +1986,144 @@ struct HCIInfo *qemu_next_hci(void) |
1984 | 1986 | return hci_table[cur_hci++]; |
1985 | 1987 | } |
1986 | 1988 | |
1989 | +static struct HCIInfo *hci_init(const char *str) | |
1990 | +{ | |
1991 | + char *endp; | |
1992 | + struct bt_scatternet_s *vlan = 0; | |
1993 | + | |
1994 | + if (!strcmp(str, "null")) | |
1995 | + /* null */ | |
1996 | + return &null_hci; | |
1997 | + else if (!strncmp(str, "host", 4) && (str[4] == '\0' || str[4] == ':')) | |
1998 | + /* host[:hciN] */ | |
1999 | + return bt_host_hci(str[4] ? str + 5 : "hci0"); | |
2000 | + else if (!strncmp(str, "hci", 3)) { | |
2001 | + /* hci[,vlan=n] */ | |
2002 | + if (str[3]) { | |
2003 | + if (!strncmp(str + 3, ",vlan=", 6)) { | |
2004 | + vlan = qemu_find_bt_vlan(strtol(str + 9, &endp, 0)); | |
2005 | + if (*endp) | |
2006 | + vlan = 0; | |
2007 | + } | |
2008 | + } else | |
2009 | + vlan = qemu_find_bt_vlan(0); | |
2010 | + if (vlan) | |
2011 | + return bt_new_hci(vlan); | |
2012 | + } | |
2013 | + | |
2014 | + fprintf(stderr, "qemu: Unknown bluetooth HCI `%s'.\n", str); | |
2015 | + | |
2016 | + return 0; | |
2017 | +} | |
2018 | + | |
2019 | +static int bt_hci_parse(const char *str) | |
2020 | +{ | |
2021 | + struct HCIInfo *hci; | |
2022 | + bdaddr_t bdaddr; | |
2023 | + | |
2024 | + if (nb_hcis >= MAX_NICS) { | |
2025 | + fprintf(stderr, "qemu: Too many bluetooth HCIs (max %i).\n", MAX_NICS); | |
2026 | + return -1; | |
2027 | + } | |
2028 | + | |
2029 | + hci = hci_init(str); | |
2030 | + if (!hci) | |
2031 | + return -1; | |
2032 | + | |
2033 | + bdaddr.b[0] = 0x52; | |
2034 | + bdaddr.b[1] = 0x54; | |
2035 | + bdaddr.b[2] = 0x00; | |
2036 | + bdaddr.b[3] = 0x12; | |
2037 | + bdaddr.b[4] = 0x34; | |
2038 | + bdaddr.b[5] = 0x56 + nb_hcis; | |
2039 | + hci->bdaddr_set(hci, bdaddr.b); | |
2040 | + | |
2041 | + hci_table[nb_hcis++] = hci; | |
2042 | + | |
2043 | + return 0; | |
2044 | +} | |
2045 | + | |
2046 | +static void bt_vhci_add(int vlan_id) | |
2047 | +{ | |
2048 | + struct bt_scatternet_s *vlan = qemu_find_bt_vlan(vlan_id); | |
2049 | + | |
2050 | + if (!vlan->slave) | |
2051 | + fprintf(stderr, "qemu: warning: adding a VHCI to " | |
2052 | + "an empty scatternet %i\n", vlan_id); | |
2053 | + | |
2054 | + bt_vhci_init(bt_new_hci(vlan)); | |
2055 | +} | |
2056 | + | |
2057 | +static struct bt_device_s *bt_device_add(const char *opt) | |
2058 | +{ | |
2059 | + struct bt_scatternet_s *vlan; | |
2060 | + int vlan_id = 0; | |
2061 | + char *endp = strstr(opt, ",vlan="); | |
2062 | + int len = (endp ? endp - opt : strlen(opt)) + 1; | |
2063 | + char devname[10]; | |
2064 | + | |
2065 | + pstrcpy(devname, MIN(sizeof(devname), len), opt); | |
2066 | + | |
2067 | + if (endp) { | |
2068 | + vlan_id = strtol(endp + 6, &endp, 0); | |
2069 | + if (*endp) { | |
2070 | + fprintf(stderr, "qemu: unrecognised bluetooth vlan Id\n"); | |
2071 | + return 0; | |
2072 | + } | |
2073 | + } | |
2074 | + | |
2075 | + vlan = qemu_find_bt_vlan(vlan_id); | |
2076 | + | |
2077 | + if (!vlan->slave) | |
2078 | + fprintf(stderr, "qemu: warning: adding a slave device to " | |
2079 | + "an empty scatternet %i\n", vlan_id); | |
2080 | + | |
2081 | + if (!strcmp(devname, "keyboard")) | |
2082 | + return bt_keyboard_init(vlan); | |
2083 | + | |
2084 | + fprintf(stderr, "qemu: unsupported bluetooth device `%s'\n", devname); | |
2085 | + return 0; | |
2086 | +} | |
2087 | + | |
2088 | +static int bt_parse(const char *opt) | |
2089 | +{ | |
2090 | + const char *endp, *p; | |
2091 | + int vlan; | |
2092 | + | |
2093 | + if (strstart(opt, "hci", &endp)) { | |
2094 | + if (!*endp || *endp == ',') { | |
2095 | + if (*endp) | |
2096 | + if (!strstart(endp, ",vlan=", 0)) | |
2097 | + opt = endp + 1; | |
2098 | + | |
2099 | + return bt_hci_parse(opt); | |
2100 | + } | |
2101 | + } else if (strstart(opt, "vhci", &endp)) { | |
2102 | + if (!*endp || *endp == ',') { | |
2103 | + if (*endp) { | |
2104 | + if (strstart(endp, ",vlan=", &p)) { | |
2105 | + vlan = strtol(p, (char **) &endp, 0); | |
2106 | + if (*endp) { | |
2107 | + fprintf(stderr, "qemu: bad scatternet '%s'\n", p); | |
2108 | + return 1; | |
2109 | + } | |
2110 | + } else { | |
2111 | + fprintf(stderr, "qemu: bad parameter '%s'\n", endp + 1); | |
2112 | + return 1; | |
2113 | + } | |
2114 | + } else | |
2115 | + vlan = 0; | |
2116 | + | |
2117 | + bt_vhci_add(vlan); | |
2118 | + return 0; | |
2119 | + } | |
2120 | + } else if (strstart(opt, "device:", &endp)) | |
2121 | + return !bt_device_add(endp); | |
2122 | + | |
2123 | + fprintf(stderr, "qemu: bad bluetooth parameter '%s'\n", opt); | |
2124 | + return 1; | |
2125 | +} | |
2126 | + | |
1987 | 2127 | /***********************************************************/ |
1988 | 2128 | /* QEMU Block devices */ |
1989 | 2129 | |
... | ... | @@ -2440,6 +2580,9 @@ static int usb_device_add(const char *devname) |
2440 | 2580 | return -1; |
2441 | 2581 | nd_table[nic].model = "usb"; |
2442 | 2582 | dev = usb_net_init(&nd_table[nic]); |
2583 | + } else if (!strcmp(devname, "bt") || strstart(devname, "bt:", &p)) { | |
2584 | + dev = usb_bt_init(devname[2] ? hci_init(p) : | |
2585 | + bt_new_hci(qemu_find_bt_vlan(0))); | |
2443 | 2586 | } else { |
2444 | 2587 | return -1; |
2445 | 2588 | } |
... | ... | @@ -4823,6 +4966,16 @@ static void help(int exitcode) |
4823 | 4966 | "-net none use it alone to have zero network devices; if no -net option\n" |
4824 | 4967 | " is provided, the default is '-net nic -net user'\n" |
4825 | 4968 | "\n" |
4969 | + "-bt hci,null Dumb bluetooth HCI - doesn't respond to commands\n" | |
4970 | + "-bt hci,host[:id]\n" | |
4971 | + " Use host's HCI with the given name\n" | |
4972 | + "-bt hci[,vlan=n]\n" | |
4973 | + " Emulate a standard HCI in virtual scatternet 'n'\n" | |
4974 | + "-bt vhci[,vlan=n]\n" | |
4975 | + " Add host computer to virtual scatternet 'n' using VHCI\n" | |
4976 | + "-bt device:dev[,vlan=n]\n" | |
4977 | + " Emulate a bluetooth device 'dev' in scatternet 'n'\n" | |
4978 | + "\n" | |
4826 | 4979 | #ifdef CONFIG_SLIRP |
4827 | 4980 | "-tftp dir allow tftp access to files in dir [-net user]\n" |
4828 | 4981 | "-bootp file advertise file in BOOTP replies\n" |
... | ... | @@ -4934,6 +5087,7 @@ enum { |
4934 | 5087 | QEMU_OPTION_bootp, |
4935 | 5088 | QEMU_OPTION_smb, |
4936 | 5089 | QEMU_OPTION_redir, |
5090 | + QEMU_OPTION_bt, | |
4937 | 5091 | |
4938 | 5092 | QEMU_OPTION_kernel, |
4939 | 5093 | QEMU_OPTION_append, |
... | ... | @@ -5033,6 +5187,7 @@ static const QEMUOption qemu_options[] = { |
5033 | 5187 | #endif |
5034 | 5188 | { "redir", HAS_ARG, QEMU_OPTION_redir }, |
5035 | 5189 | #endif |
5190 | + { "bt", HAS_ARG, QEMU_OPTION_bt }, | |
5036 | 5191 | |
5037 | 5192 | { "kernel", HAS_ARG, QEMU_OPTION_kernel }, |
5038 | 5193 | { "append", HAS_ARG, QEMU_OPTION_append }, |
... | ... | @@ -5374,6 +5529,8 @@ int main(int argc, char **argv) |
5374 | 5529 | int cyls, heads, secs, translation; |
5375 | 5530 | const char *net_clients[MAX_NET_CLIENTS]; |
5376 | 5531 | int nb_net_clients; |
5532 | + const char *bt_opts[MAX_BT_CMDLINE]; | |
5533 | + int nb_bt_opts; | |
5377 | 5534 | int hda_index; |
5378 | 5535 | int optind; |
5379 | 5536 | const char *r, *optarg; |
... | ... | @@ -5457,6 +5614,7 @@ int main(int argc, char **argv) |
5457 | 5614 | usb_devices_index = 0; |
5458 | 5615 | |
5459 | 5616 | nb_net_clients = 0; |
5617 | + nb_bt_opts = 0; | |
5460 | 5618 | nb_drives = 0; |
5461 | 5619 | nb_drives_opt = 0; |
5462 | 5620 | hda_index = -1; |
... | ... | @@ -5692,6 +5850,13 @@ int main(int argc, char **argv) |
5692 | 5850 | net_slirp_redir(optarg); |
5693 | 5851 | break; |
5694 | 5852 | #endif |
5853 | + case QEMU_OPTION_bt: | |
5854 | + if (nb_bt_opts >= MAX_BT_CMDLINE) { | |
5855 | + fprintf(stderr, "qemu: too many bluetooth options\n"); | |
5856 | + exit(1); | |
5857 | + } | |
5858 | + bt_opts[nb_bt_opts++] = optarg; | |
5859 | + break; | |
5695 | 5860 | #ifdef HAS_AUDIO |
5696 | 5861 | case QEMU_OPTION_audio_help: |
5697 | 5862 | AUD_help (); |
... | ... | @@ -6182,6 +6347,11 @@ int main(int argc, char **argv) |
6182 | 6347 | } |
6183 | 6348 | #endif |
6184 | 6349 | |
6350 | + /* init the bluetooth world */ | |
6351 | + for (i = 0; i < nb_bt_opts; i++) | |
6352 | + if (bt_parse(bt_opts[i])) | |
6353 | + exit(1); | |
6354 | + | |
6185 | 6355 | /* init the memory */ |
6186 | 6356 | phys_ram_size = machine->ram_require & ~RAMSIZE_FIXED; |
6187 | 6357 | ... | ... |