From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Kk5YN-0006EE-Pl for qemu-devel@nongnu.org; Sun, 28 Sep 2008 19:19:51 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Kk5YM-0006Du-Rj for qemu-devel@nongnu.org; Sun, 28 Sep 2008 19:19:51 -0400 Received: from [199.232.76.173] (port=36959 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Kk5YM-0006Dr-MA for qemu-devel@nongnu.org; Sun, 28 Sep 2008 19:19:50 -0400 Received: from savannah.gnu.org ([199.232.41.3]:52647 helo=sv.gnu.org) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1Kk5YL-0003A0-UY for qemu-devel@nongnu.org; Sun, 28 Sep 2008 19:19:50 -0400 Received: from cvs.savannah.gnu.org ([199.232.41.69]) by sv.gnu.org with esmtp (Exim 4.63) (envelope-from ) id 1Kk5YK-0002FO-UC for qemu-devel@nongnu.org; Sun, 28 Sep 2008 23:19:49 +0000 Received: from balrog by cvs.savannah.gnu.org with local (Exim 4.63) (envelope-from ) id 1Kk5YK-0002FK-B6 for qemu-devel@nongnu.org; Sun, 28 Sep 2008 23:19:48 +0000 MIME-Version: 1.0 Errors-To: balrog Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Andrzej Zaborowski Message-Id: Date: Sun, 28 Sep 2008 23:19:48 +0000 Subject: [Qemu-devel] [5342] Add a "null" bluetooth HCI and a header file for bluetooth. Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Revision: 5342 http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=5342 Author: balrog Date: 2008-09-28 23:19:47 +0000 (Sun, 28 Sep 2008) Log Message: ----------- Add a "null" bluetooth HCI and a header file for bluetooth. Modified Paths: -------------- trunk/Makefile trunk/hw/nseries.c trunk/net.h trunk/qemu-common.h trunk/vl.c Added Paths: ----------- trunk/hw/bt.c trunk/hw/bt.h Modified: trunk/Makefile =================================================================== --- trunk/Makefile 2008-09-28 22:02:30 UTC (rev 5341) +++ trunk/Makefile 2008-09-28 23:19:47 UTC (rev 5342) @@ -81,6 +81,7 @@ OBJS+=usb.o usb-hub.o usb-linux.o usb-hid.o usb-msd.o usb-wacom.o OBJS+=usb-serial.o usb-net.o OBJS+=sd.o ssi-sd.o +OBJS+=bt.o ifdef CONFIG_BRLAPI OBJS+= baum.o Added: trunk/hw/bt.c =================================================================== --- trunk/hw/bt.c (rev 0) +++ trunk/hw/bt.c 2008-09-28 23:19:47 UTC (rev 5342) @@ -0,0 +1,123 @@ +/* + * Convenience functions for bluetooth. + * + * Copyright (C) 2008 Andrzej Zaborowski + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include "qemu-common.h" +#include "net.h" +#include "bt.h" + +/* Slave implementations can ignore this */ +static void bt_dummy_lmp_mode_change(struct bt_link_s *link) +{ +} + +/* Slaves should never receive these PDUs */ +static void bt_dummy_lmp_connection_complete(struct bt_link_s *link) +{ + if (link->slave->reject_reason) + fprintf(stderr, "%s: stray LMP_not_accepted received, fixme\n", + __FUNCTION__); + else + fprintf(stderr, "%s: stray LMP_accepted received, fixme\n", + __FUNCTION__); + exit(-1); +} + +static void bt_dummy_lmp_disconnect_master(struct bt_link_s *link) +{ + fprintf(stderr, "%s: stray LMP_detach received, fixme\n", __FUNCTION__); + exit(-1); +} + +static void bt_dummy_lmp_acl_resp(struct bt_link_s *link, + const uint8_t *data, int start, int len) +{ + fprintf(stderr, "%s: stray ACL response PDU, fixme\n", __FUNCTION__); + exit(-1); +} + +/* Slaves that don't hold any additional per link state can use these */ +static void bt_dummy_lmp_connection_request(struct bt_link_s *req) +{ + struct bt_link_s *link = qemu_mallocz(sizeof(struct bt_link_s)); + + link->slave = req->slave; + link->host = req->host; + + req->host->reject_reason = 0; + req->host->lmp_connection_complete(link); +} + +static void bt_dummy_lmp_disconnect_slave(struct bt_link_s *link) +{ + qemu_free(link); +} + +static void bt_dummy_destroy(struct bt_device_s *device) +{ + bt_device_done(device); + qemu_free(device); +} + +static int bt_dev_idx = 0; + +void bt_device_init(struct bt_device_s *dev, struct bt_scatternet_s *net) +{ + memset(dev, 0, sizeof(*dev)); + dev->inquiry_scan = 1; + dev->page_scan = 1; + + dev->bd_addr.b[0] = bt_dev_idx & 0xff; + dev->bd_addr.b[1] = bt_dev_idx >> 8; + dev->bd_addr.b[2] = 0xd0; + dev->bd_addr.b[3] = 0xba; + dev->bd_addr.b[4] = 0xbe; + dev->bd_addr.b[5] = 0xba; + bt_dev_idx ++; + + /* Simple slave-only devices need to implement only .lmp_acl_data */ + dev->lmp_connection_complete = bt_dummy_lmp_connection_complete; + dev->lmp_disconnect_master = bt_dummy_lmp_disconnect_master; + dev->lmp_acl_resp = bt_dummy_lmp_acl_resp; + dev->lmp_mode_change = bt_dummy_lmp_mode_change; + dev->lmp_connection_request = bt_dummy_lmp_connection_request; + dev->lmp_disconnect_slave = bt_dummy_lmp_disconnect_slave; + + dev->handle_destroy = bt_dummy_destroy; + + dev->net = net; + dev->next = net->slave; + net->slave = dev; +} + +void bt_device_done(struct bt_device_s *dev) +{ + struct bt_device_s **p = &dev->net->slave; + + while (*p && *p != dev) + p = &(*p)->next; + if (*p != dev) { + fprintf(stderr, "%s: bad bt device \"%s\"\n", __FUNCTION__, + dev->lmp_name ?: "(null)"); + exit(-1); + } + + *p = dev->next; +} Added: trunk/hw/bt.h =================================================================== --- trunk/hw/bt.h (rev 0) +++ trunk/hw/bt.h 2008-09-28 23:19:47 UTC (rev 5342) @@ -0,0 +1,105 @@ +/* + * QEMU Bluetooth HCI helpers. + * + * Copyright (C) 2007 OpenMoko, Inc. + * Written by Andrzej Zaborowski + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +/* BD Address */ +typedef struct { + uint8_t b[6]; +} __attribute__((packed)) bdaddr_t; + +#define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0}}) +#define BDADDR_ALL (&(bdaddr_t) {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}) +#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}}) + +/* Copy, swap, convert BD Address */ +static inline int bacmp(const bdaddr_t *ba1, const bdaddr_t *ba2) +{ + return memcmp(ba1, ba2, sizeof(bdaddr_t)); +} +static inline void bacpy(bdaddr_t *dst, const bdaddr_t *src) +{ + memcpy(dst, src, sizeof(bdaddr_t)); +} + +#define BAINIT(orig) { .b = { \ + (orig)->b[0], (orig)->b[1], (orig)->b[2], \ + (orig)->b[3], (orig)->b[4], (orig)->b[5], \ +}, } + +/* The twisted structures of a bluetooth environment */ +struct bt_device_s; +struct bt_scatternet_s; +struct bt_piconet_s; +struct bt_link_s; + +struct bt_scatternet_s { + struct bt_device_s *slave; +}; + +struct bt_link_s { + struct bt_device_s *slave, *host; + uint16_t handle; /* Master (host) side handle */ + uint16_t acl_interval; + enum { + acl_active, + acl_hold, + acl_sniff, + acl_parked, + } acl_mode; +}; + +struct bt_device_s { + int lt_addr; + bdaddr_t bd_addr; + int mtu; + int setup; + struct bt_scatternet_s *net; + + uint8_t key[16]; + int key_present; + uint8_t class[3]; + + uint8_t reject_reason; + + uint64_t lmp_caps; + const char *lmp_name; + void (*lmp_connection_request)(struct bt_link_s *link); + void (*lmp_connection_complete)(struct bt_link_s *link); + void (*lmp_disconnect_master)(struct bt_link_s *link); + void (*lmp_disconnect_slave)(struct bt_link_s *link); + void (*lmp_acl_data)(struct bt_link_s *link, const uint8_t *data, + int start, int len); + void (*lmp_acl_resp)(struct bt_link_s *link, const uint8_t *data, + int start, int len); + void (*lmp_mode_change)(struct bt_link_s *link); + + void (*handle_destroy)(struct bt_device_s *device); + struct bt_device_s *next; /* Next in the piconet/scatternet */ + + int inquiry_scan; + int page_scan; + + uint16_t clkoff; /* Note: Always little-endian */ +}; + +/* bt.c */ +void bt_device_init(struct bt_device_s *dev, struct bt_scatternet_s *net); +void bt_device_done(struct bt_device_s *dev); Modified: trunk/hw/nseries.c =================================================================== --- trunk/hw/nseries.c 2008-09-28 22:02:30 UTC (rev 5341) +++ trunk/hw/nseries.c 2008-09-28 23:19:47 UTC (rev 5342) @@ -31,6 +31,7 @@ #include "devices.h" #include "flash.h" #include "hw.h" +#include "bt.h" /* Nokia N8x0 support */ struct n800_s { @@ -122,10 +123,6 @@ #define N8X0_BD_ADDR 0x00, 0x1a, 0x89, 0x9e, 0x3e, 0x81 -typedef struct { - uint8_t b[6]; -} __attribute__((packed)) bdaddr_t; /* XXX: move to BT headers */ - static void n800_mmc_cs_cb(void *opaque, int line, int level) { /* TODO: this seems to actually be connected to the menelaus, to Modified: trunk/net.h =================================================================== --- trunk/net.h 2008-09-28 22:02:30 UTC (rev 5341) +++ trunk/net.h 2008-09-28 23:19:47 UTC (rev 5342) @@ -48,6 +48,20 @@ extern int nb_nics; extern NICInfo nd_table[MAX_NICS]; +/* BT HCI info */ + +struct HCIInfo { + int (*bdaddr_set)(struct HCIInfo *hci, const uint8_t *bd_addr); + void (*cmd_send)(struct HCIInfo *hci, const uint8_t *data, int len); + void (*sco_send)(struct HCIInfo *hci, const uint8_t *data, int len); + void (*acl_send)(struct HCIInfo *hci, const uint8_t *data, int len); + void *opaque; + void (*evt_recv)(void *opaque, const uint8_t *data, int len); + void (*acl_recv)(void *opaque, const uint8_t *data, int len); +}; + +struct HCIInfo *qemu_next_hci(void); + /* checksumming functions (net-checksum.c) */ uint32_t net_checksum_add(int len, uint8_t *buf); uint16_t net_checksum_finish(uint32_t sum); Modified: trunk/qemu-common.h =================================================================== --- trunk/qemu-common.h 2008-09-28 22:02:30 UTC (rev 5341) +++ trunk/qemu-common.h 2008-09-28 23:19:47 UTC (rev 5342) @@ -116,6 +116,7 @@ /* A load of opaque types so that device init declarations don't have to pull in all the real definitions. */ typedef struct NICInfo NICInfo; +typedef struct HCIInfo HCIInfo; typedef struct AudioState AudioState; typedef struct BlockDriverState BlockDriverState; typedef struct DisplayState DisplayState; Modified: trunk/vl.c =================================================================== --- trunk/vl.c 2008-09-28 22:02:30 UTC (rev 5341) +++ trunk/vl.c 2008-09-28 23:19:47 UTC (rev 5342) @@ -29,6 +29,7 @@ #include "hw/audiodev.h" #include "hw/isa.h" #include "hw/baum.h" +#include "hw/bt.h" #include "net.h" #include "console.h" #include "sysemu.h" @@ -5361,6 +5362,61 @@ } } +/***********************************************************/ +/* Bluetooth support */ +static int nb_hcis; +static int cur_hci; +static struct HCIInfo *hci_table[MAX_NICS]; +static struct bt_vlan_s { + struct bt_scatternet_s net; + int id; + struct bt_vlan_s *next; +} *first_bt_vlan; + +/* find or alloc a new bluetooth "VLAN" */ +struct bt_scatternet_s *qemu_find_bt_vlan(int id) +{ + struct bt_vlan_s **pvlan, *vlan; + for (vlan = first_bt_vlan; vlan != NULL; vlan = vlan->next) { + if (vlan->id == id) + return &vlan->net; + } + vlan = qemu_mallocz(sizeof(struct bt_vlan_s)); + vlan->id = id; + pvlan = &first_bt_vlan; + while (*pvlan != NULL) + pvlan = &(*pvlan)->next; + *pvlan = vlan; + return &vlan->net; +} + +static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, int len) +{ +} + +static int null_hci_addr_set(struct HCIInfo *hci, const uint8_t *bd_addr) +{ + return -ENOTSUP; +} + +static struct HCIInfo null_hci = { + .cmd_send = null_hci_send, + .sco_send = null_hci_send, + .acl_send = null_hci_send, + .bdaddr_set = null_hci_addr_set, +}; + +struct HCIInfo *qemu_next_hci(void) +{ + if (cur_hci == nb_hcis) + return &null_hci; + + return hci_table[cur_hci++]; +} + +/***********************************************************/ +/* QEMU Block devices */ + #define HD_ALIAS "index=%d,media=disk" #ifdef TARGET_PPC #define CDROM_ALIAS "index=1,media=cdrom"