Home | History | Annotate | Download | only in hw
      1 /*
      2  * Convenience functions for bluetooth.
      3  *
      4  * Copyright (C) 2008 Andrzej Zaborowski  <balrog (at) zabor.org>
      5  *
      6  * This program is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU General Public License as
      8  * published by the Free Software Foundation; either version 2 or
      9  * (at your option) version 3 of the License.
     10  *
     11  * This program is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  * GNU General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU General Public License along
     17  * with this program; if not, see <http://www.gnu.org/licenses/>.
     18  */
     19 
     20 #include "qemu-common.h"
     21 #include "net.h"
     22 #include "bt.h"
     23 
     24 /* Slave implementations can ignore this */
     25 static void bt_dummy_lmp_mode_change(struct bt_link_s *link)
     26 {
     27 }
     28 
     29 /* Slaves should never receive these PDUs */
     30 static void bt_dummy_lmp_connection_complete(struct bt_link_s *link)
     31 {
     32     if (link->slave->reject_reason)
     33         fprintf(stderr, "%s: stray LMP_not_accepted received, fixme\n",
     34                         __FUNCTION__);
     35     else
     36         fprintf(stderr, "%s: stray LMP_accepted received, fixme\n",
     37                         __FUNCTION__);
     38     exit(-1);
     39 }
     40 
     41 static void bt_dummy_lmp_disconnect_master(struct bt_link_s *link)
     42 {
     43     fprintf(stderr, "%s: stray LMP_detach received, fixme\n", __FUNCTION__);
     44     exit(-1);
     45 }
     46 
     47 static void bt_dummy_lmp_acl_resp(struct bt_link_s *link,
     48                 const uint8_t *data, int start, int len)
     49 {
     50     fprintf(stderr, "%s: stray ACL response PDU, fixme\n", __FUNCTION__);
     51     exit(-1);
     52 }
     53 
     54 /* Slaves that don't hold any additional per link state can use these */
     55 static void bt_dummy_lmp_connection_request(struct bt_link_s *req)
     56 {
     57     struct bt_link_s *link = qemu_mallocz(sizeof(struct bt_link_s));
     58 
     59     link->slave = req->slave;
     60     link->host = req->host;
     61 
     62     req->host->reject_reason = 0;
     63     req->host->lmp_connection_complete(link);
     64 }
     65 
     66 static void bt_dummy_lmp_disconnect_slave(struct bt_link_s *link)
     67 {
     68     qemu_free(link);
     69 }
     70 
     71 static void bt_dummy_destroy(struct bt_device_s *device)
     72 {
     73     bt_device_done(device);
     74     qemu_free(device);
     75 }
     76 
     77 static int bt_dev_idx = 0;
     78 
     79 void bt_device_init(struct bt_device_s *dev, struct bt_scatternet_s *net)
     80 {
     81     memset(dev, 0, sizeof(*dev));
     82     dev->inquiry_scan = 1;
     83     dev->page_scan = 1;
     84 
     85     dev->bd_addr.b[0] = bt_dev_idx & 0xff;
     86     dev->bd_addr.b[1] = bt_dev_idx >> 8;
     87     dev->bd_addr.b[2] = 0xd0;
     88     dev->bd_addr.b[3] = 0xba;
     89     dev->bd_addr.b[4] = 0xbe;
     90     dev->bd_addr.b[5] = 0xba;
     91     bt_dev_idx ++;
     92 
     93     /* Simple slave-only devices need to implement only .lmp_acl_data */
     94     dev->lmp_connection_complete = bt_dummy_lmp_connection_complete;
     95     dev->lmp_disconnect_master = bt_dummy_lmp_disconnect_master;
     96     dev->lmp_acl_resp = bt_dummy_lmp_acl_resp;
     97     dev->lmp_mode_change = bt_dummy_lmp_mode_change;
     98     dev->lmp_connection_request = bt_dummy_lmp_connection_request;
     99     dev->lmp_disconnect_slave = bt_dummy_lmp_disconnect_slave;
    100 
    101     dev->handle_destroy = bt_dummy_destroy;
    102 
    103     dev->net = net;
    104     dev->next = net->slave;
    105     net->slave = dev;
    106 }
    107 
    108 void bt_device_done(struct bt_device_s *dev)
    109 {
    110     struct bt_device_s **p = &dev->net->slave;
    111 
    112     while (*p && *p != dev)
    113         p = &(*p)->next;
    114     if (*p != dev) {
    115         fprintf(stderr, "%s: bad bt device \"%s\"\n", __FUNCTION__,
    116                         dev->lmp_name ?: "(null)");
    117         exit(-1);
    118     }
    119 
    120     *p = dev->next;
    121 }
    122