Skip to content

Commit

Permalink
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/holtmann/bluetooth-next-2.6
  • Loading branch information
David S. Miller committed Feb 27, 2009
2 parents 43be636 + b1fb068 commit 63748aa
Show file tree
Hide file tree
Showing 19 changed files with 968 additions and 362 deletions.
3 changes: 1 addition & 2 deletions drivers/bluetooth/bfusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,7 @@ static inline int bfusb_recv_block(struct bfusb_data *data, int hdr, unsigned ch

if (hdr & 0x10) {
BT_ERR("%s error in block", data->hdev->name);
if (data->reassembly)
kfree_skb(data->reassembly);
kfree_skb(data->reassembly);
data->reassembly = NULL;
return -EIO;
}
Expand Down
4 changes: 2 additions & 2 deletions drivers/bluetooth/bt3c_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -359,9 +359,9 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst)
BT_ERR("Very strange (stat=0x%04x)", stat);
} else if ((stat & 0xff) != 0xff) {
if (stat & 0x0020) {
int stat = bt3c_read(iobase, 0x7002) & 0x10;
int status = bt3c_read(iobase, 0x7002) & 0x10;
BT_INFO("%s: Antenna %s", info->hdev->name,
stat ? "out" : "in");
status ? "out" : "in");
}
if (stat & 0x0001)
bt3c_receive(info);
Expand Down
40 changes: 23 additions & 17 deletions drivers/bluetooth/btusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>

#define VERSION "0.4"
#define VERSION "0.5"

static int ignore_dga;
static int ignore_csr;
Expand Down Expand Up @@ -171,6 +171,7 @@ struct btusb_data {

__u8 cmdreq_type;

unsigned int sco_num;
int isoc_altsetting;
int suspend_count;
};
Expand Down Expand Up @@ -496,11 +497,23 @@ static int btusb_open(struct hci_dev *hdev)
return 0;

err = btusb_submit_intr_urb(hdev, GFP_KERNEL);
if (err < 0)
goto failed;

err = btusb_submit_bulk_urb(hdev, GFP_KERNEL);
if (err < 0) {
clear_bit(BTUSB_INTR_RUNNING, &data->flags);
clear_bit(HCI_RUNNING, &hdev->flags);
usb_kill_anchored_urbs(&data->intr_anchor);
goto failed;
}

set_bit(BTUSB_BULK_RUNNING, &data->flags);
btusb_submit_bulk_urb(hdev, GFP_KERNEL);

return 0;

failed:
clear_bit(BTUSB_INTR_RUNNING, &data->flags);
clear_bit(HCI_RUNNING, &hdev->flags);
return err;
}

Expand Down Expand Up @@ -655,19 +668,10 @@ static void btusb_notify(struct hci_dev *hdev, unsigned int evt)

BT_DBG("%s evt %d", hdev->name, evt);

if (hdev->conn_hash.acl_num > 0) {
if (!test_and_set_bit(BTUSB_BULK_RUNNING, &data->flags)) {
if (btusb_submit_bulk_urb(hdev, GFP_ATOMIC) < 0)
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
else
btusb_submit_bulk_urb(hdev, GFP_ATOMIC);
}
} else {
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
usb_unlink_anchored_urbs(&data->bulk_anchor);
if (hdev->conn_hash.sco_num != data->sco_num) {
data->sco_num = hdev->conn_hash.sco_num;
schedule_work(&data->work);
}

schedule_work(&data->work);
}

static int inline __set_isoc_interface(struct hci_dev *hdev, int altsetting)
Expand Down Expand Up @@ -982,9 +986,11 @@ static int btusb_resume(struct usb_interface *intf)
}

if (test_bit(BTUSB_BULK_RUNNING, &data->flags)) {
if (btusb_submit_bulk_urb(hdev, GFP_NOIO) < 0)
err = btusb_submit_bulk_urb(hdev, GFP_NOIO);
if (err < 0) {
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
else
return err;
} else
btusb_submit_bulk_urb(hdev, GFP_NOIO);
}

Expand Down
3 changes: 1 addition & 2 deletions drivers/bluetooth/hci_h4.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,7 @@ static int h4_close(struct hci_uart *hu)

skb_queue_purge(&h4->txq);

if (h4->rx_skb)
kfree_skb(h4->rx_skb);
kfree_skb(h4->rx_skb);

hu->priv = NULL;
kfree(h4);
Expand Down
3 changes: 1 addition & 2 deletions drivers/bluetooth/hci_ll.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,7 @@ static int ll_close(struct hci_uart *hu)
skb_queue_purge(&ll->tx_wait_q);
skb_queue_purge(&ll->txq);

if (ll->rx_skb)
kfree_skb(ll->rx_skb);
kfree_skb(ll->rx_skb);

hu->priv = NULL;

Expand Down
12 changes: 12 additions & 0 deletions include/net/bluetooth/bluetooth.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@
#define SOL_SCO 17
#define SOL_RFCOMM 18

#define BT_SECURITY 4
struct bt_security {
__u8 level;
};
#define BT_SECURITY_SDP 0
#define BT_SECURITY_LOW 1
#define BT_SECURITY_MEDIUM 2
#define BT_SECURITY_HIGH 3

#define BT_DEFER_SETUP 7

#define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg)
#define BT_ERR(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg)
#define BT_DBG(fmt, arg...) pr_debug("%s: " fmt "\n" , __func__ , ## arg)
Expand Down Expand Up @@ -108,6 +119,7 @@ struct bt_sock {
bdaddr_t dst;
struct list_head accept_q;
struct sock *parent;
u32 defer_setup;
};

struct bt_sock_list {
Expand Down
8 changes: 8 additions & 0 deletions include/net/bluetooth/hci.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,13 @@ enum {
#define ESCO_EV3 0x0008
#define ESCO_EV4 0x0010
#define ESCO_EV5 0x0020
#define ESCO_2EV3 0x0040
#define ESCO_3EV3 0x0080
#define ESCO_2EV5 0x0100
#define ESCO_3EV5 0x0200

#define SCO_ESCO_MASK (ESCO_HV1 | ESCO_HV2 | ESCO_HV3)
#define EDR_ESCO_MASK (ESCO_2EV3 | ESCO_3EV3 | ESCO_2EV5 | ESCO_3EV5)

/* ACL flags */
#define ACL_CONT 0x01
Expand Down Expand Up @@ -176,6 +181,9 @@ enum {
#define LMP_EV5 0x02

#define LMP_SNIFF_SUBR 0x02
#define LMP_EDR_ESCO_2M 0x20
#define LMP_EDR_ESCO_3M 0x40
#define LMP_EDR_3S_ESCO 0x80

#define LMP_SIMPLE_PAIR 0x08

Expand Down
84 changes: 57 additions & 27 deletions include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ struct hci_conn {
__u16 link_policy;
__u32 link_mode;
__u8 auth_type;
__u8 sec_level;
__u8 power_save;
unsigned long pend;

Expand Down Expand Up @@ -325,12 +326,11 @@ int hci_conn_del(struct hci_conn *conn);
void hci_conn_hash_flush(struct hci_dev *hdev);
void hci_conn_check_pending(struct hci_dev *hdev);

struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type);
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type);
int hci_conn_check_link_mode(struct hci_conn *conn);
int hci_conn_auth(struct hci_conn *conn);
int hci_conn_encrypt(struct hci_conn *conn);
int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
int hci_conn_change_link_key(struct hci_conn *conn);
int hci_conn_switch_role(struct hci_conn *conn, uint8_t role);
int hci_conn_switch_role(struct hci_conn *conn, __u8 role);

void hci_conn_enter_active_mode(struct hci_conn *conn);
void hci_conn_enter_sniff_mode(struct hci_conn *conn);
Expand Down Expand Up @@ -470,26 +470,26 @@ void hci_conn_del_sysfs(struct hci_conn *conn);

/* ----- HCI protocols ----- */
struct hci_proto {
char *name;
char *name;
unsigned int id;
unsigned long flags;

void *priv;

int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type);
int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type);
int (*connect_cfm) (struct hci_conn *conn, __u8 status);
int (*disconn_ind) (struct hci_conn *conn, __u8 reason);
int (*disconn_ind) (struct hci_conn *conn);
int (*disconn_cfm) (struct hci_conn *conn, __u8 reason);
int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
int (*recv_scodata) (struct hci_conn *conn, struct sk_buff *skb);
int (*auth_cfm) (struct hci_conn *conn, __u8 status);
int (*encrypt_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
int (*security_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
};

static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
{
register struct hci_proto *hp;
int mask = 0;

hp = hci_proto[HCI_PROTO_L2CAP];
if (hp && hp->connect_ind)
mask |= hp->connect_ind(hdev, bdaddr, type);
Expand All @@ -514,43 +514,65 @@ static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status)
hp->connect_cfm(conn, status);
}

static inline void hci_proto_disconn_ind(struct hci_conn *conn, __u8 reason)
static inline int hci_proto_disconn_ind(struct hci_conn *conn)
{
register struct hci_proto *hp;
int reason = 0x13;

hp = hci_proto[HCI_PROTO_L2CAP];
if (hp && hp->disconn_ind)
hp->disconn_ind(conn, reason);
reason = hp->disconn_ind(conn);

hp = hci_proto[HCI_PROTO_SCO];
if (hp && hp->disconn_ind)
hp->disconn_ind(conn, reason);
reason = hp->disconn_ind(conn);

return reason;
}

static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason)
{
register struct hci_proto *hp;

hp = hci_proto[HCI_PROTO_L2CAP];
if (hp && hp->disconn_cfm)
hp->disconn_cfm(conn, reason);

hp = hci_proto[HCI_PROTO_SCO];
if (hp && hp->disconn_cfm)
hp->disconn_cfm(conn, reason);
}

static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
{
register struct hci_proto *hp;
__u8 encrypt;

if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
return;

encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;

hp = hci_proto[HCI_PROTO_L2CAP];
if (hp && hp->auth_cfm)
hp->auth_cfm(conn, status);
if (hp && hp->security_cfm)
hp->security_cfm(conn, status, encrypt);

hp = hci_proto[HCI_PROTO_SCO];
if (hp && hp->auth_cfm)
hp->auth_cfm(conn, status);
if (hp && hp->security_cfm)
hp->security_cfm(conn, status, encrypt);
}

static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt)
{
register struct hci_proto *hp;

hp = hci_proto[HCI_PROTO_L2CAP];
if (hp && hp->encrypt_cfm)
hp->encrypt_cfm(conn, status, encrypt);
if (hp && hp->security_cfm)
hp->security_cfm(conn, status, encrypt);

hp = hci_proto[HCI_PROTO_SCO];
if (hp && hp->encrypt_cfm)
hp->encrypt_cfm(conn, status, encrypt);
if (hp && hp->security_cfm)
hp->security_cfm(conn, status, encrypt);
}

int hci_register_proto(struct hci_proto *hproto);
Expand All @@ -562,23 +584,28 @@ struct hci_cb {

char *name;

void (*auth_cfm) (struct hci_conn *conn, __u8 status);
void (*encrypt_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
void (*security_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
void (*key_change_cfm) (struct hci_conn *conn, __u8 status);
void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
};

static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
{
struct list_head *p;
__u8 encrypt;

hci_proto_auth_cfm(conn, status);

if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
return;

encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;

read_lock_bh(&hci_cb_list_lock);
list_for_each(p, &hci_cb_list) {
struct hci_cb *cb = list_entry(p, struct hci_cb, list);
if (cb->auth_cfm)
cb->auth_cfm(conn, status);
if (cb->security_cfm)
cb->security_cfm(conn, status, encrypt);
}
read_unlock_bh(&hci_cb_list_lock);
}
Expand All @@ -587,13 +614,16 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encr
{
struct list_head *p;

if (conn->sec_level == BT_SECURITY_SDP)
conn->sec_level = BT_SECURITY_LOW;

hci_proto_encrypt_cfm(conn, status, encrypt);

read_lock_bh(&hci_cb_list_lock);
list_for_each(p, &hci_cb_list) {
struct hci_cb *cb = list_entry(p, struct hci_cb, list);
if (cb->encrypt_cfm)
cb->encrypt_cfm(conn, status, encrypt);
if (cb->security_cfm)
cb->security_cfm(conn, status, encrypt);
}
read_unlock_bh(&hci_cb_list_lock);
}
Expand Down
Loading

0 comments on commit 63748aa

Please sign in to comment.