X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fbluetooth%2Fhci_conn.c;h=a2bd4b1c19da3ab5044150bbdaf54fb54fdb91ce;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=962ce3a3485ec9caf2533b96efeddc483b9e7d80;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 962ce3a34..a2bd4b1c1 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -22,11 +22,7 @@ SOFTWARE IS DISCLAIMED. */ -/* - * HCI Connection handling. - * - * $Id: hci_conn.c,v 1.2 2002/04/17 17:37:16 maxk Exp $ - */ +/* Bluetooth HCI connection handling. */ #include #include @@ -54,10 +50,10 @@ #ifndef CONFIG_BT_HCI_CORE_DEBUG #undef BT_DBG -#define BT_DBG( A... ) +#define BT_DBG(D...) #endif -void hci_acl_connect(struct hci_conn *conn) +static void hci_acl_connect(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; struct inquiry_entry *ie; @@ -73,11 +69,12 @@ void hci_acl_connect(struct hci_conn *conn) bacpy(&cp.bdaddr, &conn->dst); cp.pscan_rep_mode = 0x02; - if ((ie = inquiry_cache_lookup(hdev, &conn->dst)) && + if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst)) && inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) { - cp.pscan_rep_mode = ie->info.pscan_rep_mode; - cp.pscan_mode = ie->info.pscan_mode; - cp.clock_offset = ie->info.clock_offset | __cpu_to_le16(0x8000); + cp.pscan_rep_mode = ie->data.pscan_rep_mode; + cp.pscan_mode = ie->data.pscan_mode; + cp.clock_offset = ie->data.clock_offset | __cpu_to_le16(0x8000); + memcpy(conn->dev_class, ie->data.dev_class, 3); } cp.pkt_type = __cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK); @@ -167,21 +164,22 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) hci_dev_hold(hdev); tasklet_disable(&hdev->tx_task); - hci_conn_hash_add(hdev, conn); - tasklet_enable(&hdev->tx_task); + hci_conn_hash_add(hdev, conn); if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_CONN_ADD); + tasklet_enable(&hdev->tx_task); + return conn; } int hci_conn_del(struct hci_conn *conn) { - struct hci_dev *hdev = conn->hdev; + struct hci_dev *hdev = conn->hdev; BT_DBG("%s conn %p handle %d", hdev->name, conn, conn->handle); - + hci_conn_del_timer(conn); if (conn->type == SCO_LINK) { @@ -199,11 +197,12 @@ int hci_conn_del(struct hci_conn *conn) hdev->acl_cnt += conn->sent; } + tasklet_disable(&hdev->tx_task); + + hci_conn_hash_del(hdev, conn); if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_CONN_DEL); - tasklet_disable(&hdev->tx_task); - hci_conn_hash_del(hdev, conn); tasklet_enable(&hdev->tx_task); skb_queue_purge(&conn->data_q); @@ -226,14 +225,14 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) list_for_each(p, &hci_dev_list) { struct hci_dev *d = list_entry(p, struct hci_dev, list); - - if (!test_bit(HCI_UP, &d->flags)) + + if (!test_bit(HCI_UP, &d->flags) || test_bit(HCI_RAW, &d->flags)) continue; /* Simple routing: - * No source address - find interface with bdaddr != dst - * Source address - find interface with bdaddr == src - */ + * No source address - find interface with bdaddr != dst + * Source address - find interface with bdaddr == src + */ if (use_src) { if (!bacmp(&d->bdaddr, src)) { @@ -252,6 +251,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) read_unlock_bh(&hci_dev_list_lock); return hdev; } +EXPORT_SYMBOL(hci_get_route); /* Create SCO or ACL connection. * Device _must_ be locked */ @@ -294,15 +294,16 @@ struct hci_conn * hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) return acl; } } +EXPORT_SYMBOL(hci_connect); /* Authenticate remote device */ int hci_conn_auth(struct hci_conn *conn) { BT_DBG("conn %p", conn); - + if (conn->link_mode & HCI_LM_AUTH) return 1; - + if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { struct hci_cp_auth_requested cp; cp.handle = __cpu_to_le16(conn->handle); @@ -310,15 +311,16 @@ int hci_conn_auth(struct hci_conn *conn) } return 0; } +EXPORT_SYMBOL(hci_conn_auth); /* Enable encryption */ int hci_conn_encrypt(struct hci_conn *conn) { BT_DBG("conn %p", conn); - + if (conn->link_mode & HCI_LM_ENCRYPT) return 1; - + if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) return 0; @@ -330,12 +332,27 @@ int hci_conn_encrypt(struct hci_conn *conn) } return 0; } +EXPORT_SYMBOL(hci_conn_encrypt); + +/* Change link key */ +int hci_conn_change_link_key(struct hci_conn *conn) +{ + BT_DBG("conn %p", conn); + + if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { + struct hci_cp_change_conn_link_key cp; + cp.handle = __cpu_to_le16(conn->handle); + hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_CHANGE_CONN_LINK_KEY, sizeof(cp), &cp); + } + return 0; +} +EXPORT_SYMBOL(hci_conn_change_link_key); /* Drop all connection on the device */ void hci_conn_hash_flush(struct hci_dev *hdev) { struct hci_conn_hash *h = &hdev->conn_hash; - struct list_head *p; + struct list_head *p; BT_DBG("hdev %s", hdev->name); @@ -353,7 +370,7 @@ void hci_conn_hash_flush(struct hci_dev *hdev) } } -int hci_get_conn_list(unsigned long arg) +int hci_get_conn_list(void __user *arg) { struct hci_conn_list_req req, *cl; struct hci_conn_info *ci; @@ -361,7 +378,7 @@ int hci_get_conn_list(unsigned long arg) struct list_head *p; int n = 0, size, err; - if (copy_from_user(&req, (void *) arg, sizeof(req))) + if (copy_from_user(&req, arg, sizeof(req))) return -EFAULT; if (!req.conn_num || req.conn_num > (PAGE_SIZE * 2) / sizeof(*ci)) @@ -401,20 +418,20 @@ int hci_get_conn_list(unsigned long arg) hci_dev_put(hdev); - err = copy_to_user((void *) arg, cl, size); + err = copy_to_user(arg, cl, size); kfree(cl); return err ? -EFAULT : 0; } -int hci_get_conn_info(struct hci_dev *hdev, unsigned long arg) +int hci_get_conn_info(struct hci_dev *hdev, void __user *arg) { struct hci_conn_info_req req; struct hci_conn_info ci; struct hci_conn *conn; - char *ptr = (void *) arg + sizeof(req); + char __user *ptr = arg + sizeof(req); - if (copy_from_user(&req, (void *) arg, sizeof(req))) + if (copy_from_user(&req, arg, sizeof(req))) return -EFAULT; hci_dev_lock_bh(hdev);