Commit 0c980532 authored by Marcel Holtmann's avatar Marcel Holtmann

Merge bk://linux.bkbits.net/linux-2.6

into hostme.bitkeeper.com:/repos/l/linux-mh/bluetooth-2.6
parents 31a37910 68c3b8a8
......@@ -40,6 +40,7 @@
#include <linux/unistd.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
......@@ -65,6 +66,10 @@
#define URB_ZERO_PACKET 0
#endif
#ifdef CONFIG_BT_HCIUSB_SCO
static int isoc = 1;
#endif
#define VERSION "2.7"
static struct usb_driver hci_usb_driver;
......@@ -867,7 +872,7 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
isoc_ifnum = 1;
#ifdef CONFIG_BT_HCIUSB_SCO
if (!(id->driver_info & HCI_BROKEN_ISOC))
if (isoc && !(id->driver_info & HCI_BROKEN_ISOC))
isoc_iface = usb_ifnum_to_if(udev, isoc_ifnum);
if (isoc_iface) {
......@@ -1018,6 +1023,11 @@ static void __exit hci_usb_exit(void)
module_init(hci_usb_init);
module_exit(hci_usb_exit);
#ifdef CONFIG_BT_HCIUSB_SCO
module_param(isoc, bool, 0);
MODULE_PARM_DESC(isoc, "Set isochronous transfers for SCO over HCI support");
#endif
MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth HCI USB driver ver " VERSION);
MODULE_VERSION(VERSION);
......
......@@ -133,6 +133,7 @@ uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait);
int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo);
void bt_accept_enqueue(struct sock *parent, struct sock *sk);
void bt_accept_unlink(struct sock *sk);
struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock);
/* Skb helpers */
......
......@@ -68,7 +68,9 @@ enum {
HCI_ENCRYPT,
HCI_INQUIRY,
HCI_RAW
HCI_RAW,
HCI_SECMGR
};
/* HCI ioctl defines */
......@@ -91,7 +93,8 @@ enum {
#define HCISETLINKMODE _IOW('H', 226, int)
#define HCISETACLMTU _IOW('H', 227, int)
#define HCISETSCOMTU _IOW('H', 228, int)
#define HCISETRAWVND _IOW('H', 229, int)
#define HCISETSECMGR _IOW('H', 230, int)
#define HCIINQUIRY _IOR('H', 240, int)
......@@ -324,20 +327,28 @@ struct hci_cp_inquiry {
#define OCF_INQUIRY_CANCEL 0x0002
#define OCF_LINK_KEY_REPLY 0x000B
#define OCF_LINK_KEY_NEG_REPLY 0x000C
struct hci_cp_link_key_reply {
bdaddr_t bdaddr;
__u8 link_key[16];
} __attribute__ ((packed));
#define OCF_LINK_KEY_NEG_REPLY 0x000C
struct hci_cp_link_key_neg_reply {
bdaddr_t bdaddr;
} __attribute__ ((packed));
#define OCF_PIN_CODE_REPLY 0x000D
#define OCF_PIN_CODE_NEG_REPLY 0x000E
struct hci_cp_pin_code_reply {
bdaddr_t bdaddr;
__u8 pin_len;
__u8 pin_code[16];
} __attribute__ ((packed));
#define OCF_PIN_CODE_NEG_REPLY 0x000E
struct hci_cp_pin_code_neg_reply {
bdaddr_t bdaddr;
} __attribute__ ((packed));
#define OCF_CHANGE_CONN_PTYPE 0x000F
struct hci_cp_change_conn_ptype {
__u16 handle;
......
......@@ -53,7 +53,8 @@ struct inquiry_cache {
struct hci_conn_hash {
struct list_head list;
spinlock_t lock;
unsigned int num;
unsigned int acl_num;
unsigned int sco_num;
};
struct hci_dev {
......@@ -209,21 +210,28 @@ static inline void hci_conn_hash_init(struct hci_dev *hdev)
struct hci_conn_hash *h = &hdev->conn_hash;
INIT_LIST_HEAD(&h->list);
spin_lock_init(&h->lock);
h->num = 0;
h->acl_num = 0;
h->sco_num = 0;
}
static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
{
struct hci_conn_hash *h = &hdev->conn_hash;
list_add(&c->list, &h->list);
h->num++;
if (c->type == ACL_LINK)
h->acl_num++;
else
h->sco_num++;
}
static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
{
struct hci_conn_hash *h = &hdev->conn_hash;
list_del(&c->list);
h->num--;
if (c->type == ACL_LINK)
h->acl_num++;
else
h->sco_num--;
}
static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
......
......@@ -165,7 +165,7 @@ void bt_accept_enqueue(struct sock *parent, struct sock *sk)
}
EXPORT_SYMBOL(bt_accept_enqueue);
static void bt_accept_unlink(struct sock *sk)
void bt_accept_unlink(struct sock *sk)
{
BT_DBG("sk %p state %d", sk, sk->sk_state);
......@@ -174,6 +174,7 @@ static void bt_accept_unlink(struct sock *sk)
bt_sk(sk)->parent = NULL;
sock_put(sk);
}
EXPORT_SYMBOL(bt_accept_unlink);
struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
{
......@@ -186,6 +187,8 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
lock_sock(sk);
/* FIXME: Is this check still needed */
if (sk->sk_state == BT_CLOSED) {
release_sock(sk);
bt_accept_unlink(sk);
......@@ -199,6 +202,7 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
release_sock(sk);
return sk;
}
release_sock(sk);
}
return NULL;
......
......@@ -493,7 +493,6 @@ static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
application = cmtp_application_get(session, CMTP_APPLID, appl);
if ((!application) || (application->state != BT_CONNECTED)) {
BT_ERR("Can't find application with id %d", appl);
kfree_skb(skb);
return CAPI_ILLAPPNR;
}
......
......@@ -163,12 +163,13 @@ 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;
}
......@@ -195,11 +196,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);
......
......@@ -104,7 +104,7 @@ static void hci_cc_link_policy(struct hci_dev *hdev, __u16 ocf, struct sk_buff *
else
conn->link_mode |= HCI_LM_MASTER;
}
hci_dev_unlock(hdev);
break;
......@@ -229,8 +229,11 @@ static void hci_cc_host_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb
BT_DBG("%s: voice setting 0x%04x", hdev->name, setting);
if (hdev->notify)
if (hdev->notify) {
tasklet_disable(&hdev->tx_task);
hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
tasklet_enable(&hdev->tx_task);
}
}
break;
......@@ -247,8 +250,11 @@ static void hci_cc_host_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb
BT_DBG("%s: voice setting 0x%04x", hdev->name, setting);
if (hdev->notify)
if (hdev->notify) {
tasklet_disable(&hdev->tx_task);
hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
tasklet_enable(&hdev->tx_task);
}
}
hci_req_complete(hdev, status);
break;
......@@ -320,7 +326,7 @@ static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *s
hdev->sco_pkts = hdev->sco_cnt = __le16_to_cpu(bs->sco_max_pkt);
BT_DBG("%s mtu: acl %d, sco %d max_pkt: acl %d, sco %d", hdev->name,
hdev->acl_mtu, hdev->sco_mtu, hdev->acl_pkts, hdev->sco_pkts);
hdev->acl_mtu, hdev->sco_mtu, hdev->acl_pkts, hdev->sco_pkts);
break;
case OCF_READ_BD_ADDR:
......@@ -400,7 +406,7 @@ static void hci_cs_link_ctl(struct hci_dev *hdev, __u16 ocf, __u8 status)
BT_DBG("%s Add SCO error: handle %d status 0x%x", hdev->name, handle, status);
hci_dev_lock(hdev);
acl = hci_conn_hash_lookup_handle(hdev, handle);
if (acl && (sco = acl->link)) {
sco->state = BT_CLOSED;
......@@ -542,7 +548,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_dev_unlock(hdev);
bacpy(&cp.bdaddr, &ev->bdaddr);
if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
cp.role = 0x00; /* Become master */
else
......@@ -585,7 +591,6 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
if (test_bit(HCI_ENCRYPT, &hdev->flags))
conn->link_mode |= HCI_LM_ENCRYPT;
/* Set link policy */
if (conn->type == ACL_LINK && hdev->link_policy) {
struct hci_cp_write_link_policy cp;
......@@ -710,7 +715,7 @@ static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb
if (conn) {
if (ev->role)
conn->link_mode &= ~HCI_LM_MASTER;
else
else
conn->link_mode |= HCI_LM_MASTER;
}
......@@ -774,13 +779,28 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
conn->link_mode &= ~HCI_LM_ENCRYPT;
}
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
hci_proto_encrypt_cfm(conn, ev->status);
}
hci_dev_unlock(hdev);
}
/* Pin Code Request*/
static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
}
/* Link Key Request */
static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
}
/* Link Key Notification */
static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
}
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_event_hdr *hdr = (struct hci_event_hdr *) skb->data;
......@@ -833,6 +853,18 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_encrypt_change_evt(hdev, skb);
break;
case HCI_EV_PIN_CODE_REQ:
hci_pin_code_request_evt(hdev, skb);
break;
case HCI_EV_LINK_KEY_REQ:
hci_link_key_request_evt(hdev, skb);
break;
case HCI_EV_LINK_KEY_NOTIFY:
hci_link_key_notify_evt(hdev, skb);
break;
case HCI_EV_CMD_STATUS:
cs = (struct hci_ev_cmd_status *) skb->data;
skb_pull(skb, sizeof(cs));
......
......@@ -185,6 +185,17 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign
return 0;
case HCISETSECMGR:
if (!capable(CAP_NET_ADMIN))
return -EACCES;
if (arg)
set_bit(HCI_SECMGR, &hdev->flags);
else
clear_bit(HCI_SECMGR, &hdev->flags);
return 0;
case HCIGETCONNINFO:
return hci_get_conn_info(hdev, (void __user *)arg);
......
......@@ -1005,9 +1005,10 @@ static void l2cap_chan_del(struct sock *sk, int err)
if (err)
sk->sk_err = err;
if (parent)
if (parent) {
bt_accept_unlink(sk);
parent->sk_data_ready(parent, 0);
else
} else
sk->sk_state_change(sk);
}
......@@ -1303,7 +1304,7 @@ static int l2cap_build_conf_req(struct sock *sk, void *data)
if (pi->imtu != L2CAP_DEFAULT_MTU)
l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
/* FIXME. Need actual value of the flush timeout */
/* FIXME: Need actual value of the flush timeout */
//if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
// l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to);
......
......@@ -97,17 +97,26 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err)
if (err)
sk->sk_err = err;
sk->sk_state = d->state;
parent = bt_sk(sk)->parent;
if (!parent) {
if (parent) {
if (d->state == BT_CLOSED) {
sk->sk_zapped = 1;
bt_accept_unlink(sk);
}
parent->sk_data_ready(parent, 0);
} else {
if (d->state == BT_CONNECTED)
rfcomm_session_getaddr(d->session, &bt_sk(sk)->src, NULL);
sk->sk_state_change(sk);
} else
parent->sk_data_ready(parent, 0);
}
bh_unlock_sock(sk);
if (parent && sk->sk_zapped)
rfcomm_sock_kill(sk);
}
/* ---- Socket functions ---- */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment