Commit 06e0c41d authored by David S. Miller's avatar David S. Miller

Merge nuts.davemloft.net:/disk1/BK/network-2.6

into nuts.davemloft.net:/disk1/BK/net-2.6
parents 235fc023 ddc06b10
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/moduleparam.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -65,6 +66,10 @@ ...@@ -65,6 +66,10 @@
#define URB_ZERO_PACKET 0 #define URB_ZERO_PACKET 0
#endif #endif
#ifdef CONFIG_BT_HCIUSB_SCO
static int isoc = 1;
#endif
#define VERSION "2.7" #define VERSION "2.7"
static struct usb_driver hci_usb_driver; 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) ...@@ -867,7 +872,7 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
isoc_ifnum = 1; isoc_ifnum = 1;
#ifdef CONFIG_BT_HCIUSB_SCO #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); isoc_iface = usb_ifnum_to_if(udev, isoc_ifnum);
if (isoc_iface) { if (isoc_iface) {
...@@ -1018,6 +1023,11 @@ static void __exit hci_usb_exit(void) ...@@ -1018,6 +1023,11 @@ static void __exit hci_usb_exit(void)
module_init(hci_usb_init); module_init(hci_usb_init);
module_exit(hci_usb_exit); 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_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth HCI USB driver ver " VERSION); MODULE_DESCRIPTION("Bluetooth HCI USB driver ver " VERSION);
MODULE_VERSION(VERSION); MODULE_VERSION(VERSION);
......
...@@ -133,6 +133,7 @@ uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait); ...@@ -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); 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_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); struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock);
/* Skb helpers */ /* Skb helpers */
......
...@@ -68,7 +68,9 @@ enum { ...@@ -68,7 +68,9 @@ enum {
HCI_ENCRYPT, HCI_ENCRYPT,
HCI_INQUIRY, HCI_INQUIRY,
HCI_RAW HCI_RAW,
HCI_SECMGR
}; };
/* HCI ioctl defines */ /* HCI ioctl defines */
...@@ -91,7 +93,8 @@ enum { ...@@ -91,7 +93,8 @@ enum {
#define HCISETLINKMODE _IOW('H', 226, int) #define HCISETLINKMODE _IOW('H', 226, int)
#define HCISETACLMTU _IOW('H', 227, int) #define HCISETACLMTU _IOW('H', 227, int)
#define HCISETSCOMTU _IOW('H', 228, 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) #define HCIINQUIRY _IOR('H', 240, int)
...@@ -324,20 +327,28 @@ struct hci_cp_inquiry { ...@@ -324,20 +327,28 @@ struct hci_cp_inquiry {
#define OCF_INQUIRY_CANCEL 0x0002 #define OCF_INQUIRY_CANCEL 0x0002
#define OCF_LINK_KEY_REPLY 0x000B #define OCF_LINK_KEY_REPLY 0x000B
#define OCF_LINK_KEY_NEG_REPLY 0x000C
struct hci_cp_link_key_reply { struct hci_cp_link_key_reply {
bdaddr_t bdaddr; bdaddr_t bdaddr;
__u8 link_key[16]; __u8 link_key[16];
} __attribute__ ((packed)); } __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_REPLY 0x000D
#define OCF_PIN_CODE_NEG_REPLY 0x000E
struct hci_cp_pin_code_reply { struct hci_cp_pin_code_reply {
bdaddr_t bdaddr; bdaddr_t bdaddr;
__u8 pin_len; __u8 pin_len;
__u8 pin_code[16]; __u8 pin_code[16];
} __attribute__ ((packed)); } __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 #define OCF_CHANGE_CONN_PTYPE 0x000F
struct hci_cp_change_conn_ptype { struct hci_cp_change_conn_ptype {
__u16 handle; __u16 handle;
......
...@@ -53,7 +53,8 @@ struct inquiry_cache { ...@@ -53,7 +53,8 @@ struct inquiry_cache {
struct hci_conn_hash { struct hci_conn_hash {
struct list_head list; struct list_head list;
spinlock_t lock; spinlock_t lock;
unsigned int num; unsigned int acl_num;
unsigned int sco_num;
}; };
struct hci_dev { struct hci_dev {
...@@ -209,21 +210,28 @@ static inline void hci_conn_hash_init(struct hci_dev *hdev) ...@@ -209,21 +210,28 @@ static inline void hci_conn_hash_init(struct hci_dev *hdev)
struct hci_conn_hash *h = &hdev->conn_hash; struct hci_conn_hash *h = &hdev->conn_hash;
INIT_LIST_HEAD(&h->list); INIT_LIST_HEAD(&h->list);
spin_lock_init(&h->lock); 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) static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
{ {
struct hci_conn_hash *h = &hdev->conn_hash; struct hci_conn_hash *h = &hdev->conn_hash;
list_add(&c->list, &h->list); 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) static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
{ {
struct hci_conn_hash *h = &hdev->conn_hash; struct hci_conn_hash *h = &hdev->conn_hash;
list_del(&c->list); 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, static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
......
...@@ -1336,6 +1336,13 @@ static inline void sock_valbool_flag(struct sock *sk, int bit, int valbool) ...@@ -1336,6 +1336,13 @@ static inline void sock_valbool_flag(struct sock *sk, int bit, int valbool)
extern __u32 sysctl_wmem_max; extern __u32 sysctl_wmem_max;
extern __u32 sysctl_rmem_max; extern __u32 sysctl_rmem_max;
#ifdef CONFIG_NET
int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
#else
static inline int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
return -ENODEV;
}
#endif
#endif /* _SOCK_H */ #endif /* _SOCK_H */
...@@ -277,6 +277,7 @@ cond_syscall(sys_set_mempolicy) ...@@ -277,6 +277,7 @@ cond_syscall(sys_set_mempolicy)
cond_syscall(compat_mbind) cond_syscall(compat_mbind)
cond_syscall(compat_get_mempolicy) cond_syscall(compat_get_mempolicy)
cond_syscall(compat_set_mempolicy) cond_syscall(compat_set_mempolicy)
cond_syscall(compat_sys_socketcall)
/* arch-specific weak syscall entries */ /* arch-specific weak syscall entries */
cond_syscall(sys_pciconfig_read) cond_syscall(sys_pciconfig_read)
......
...@@ -165,7 +165,7 @@ void bt_accept_enqueue(struct sock *parent, struct sock *sk) ...@@ -165,7 +165,7 @@ void bt_accept_enqueue(struct sock *parent, struct sock *sk)
} }
EXPORT_SYMBOL(bt_accept_enqueue); 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); BT_DBG("sk %p state %d", sk, sk->sk_state);
...@@ -174,6 +174,7 @@ static void bt_accept_unlink(struct sock *sk) ...@@ -174,6 +174,7 @@ static void bt_accept_unlink(struct sock *sk)
bt_sk(sk)->parent = NULL; bt_sk(sk)->parent = NULL;
sock_put(sk); sock_put(sk);
} }
EXPORT_SYMBOL(bt_accept_unlink);
struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock) 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) ...@@ -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); sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
lock_sock(sk); lock_sock(sk);
/* FIXME: Is this check still needed */
if (sk->sk_state == BT_CLOSED) { if (sk->sk_state == BT_CLOSED) {
release_sock(sk); release_sock(sk);
bt_accept_unlink(sk); bt_accept_unlink(sk);
...@@ -199,6 +202,7 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock) ...@@ -199,6 +202,7 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
release_sock(sk); release_sock(sk);
return sk; return sk;
} }
release_sock(sk); release_sock(sk);
} }
return NULL; return NULL;
......
...@@ -493,7 +493,6 @@ static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) ...@@ -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); application = cmtp_application_get(session, CMTP_APPLID, appl);
if ((!application) || (application->state != BT_CONNECTED)) { if ((!application) || (application->state != BT_CONNECTED)) {
BT_ERR("Can't find application with id %d", appl); BT_ERR("Can't find application with id %d", appl);
kfree_skb(skb);
return CAPI_ILLAPPNR; return CAPI_ILLAPPNR;
} }
......
...@@ -163,12 +163,13 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) ...@@ -163,12 +163,13 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
hci_dev_hold(hdev); hci_dev_hold(hdev);
tasklet_disable(&hdev->tx_task); 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) if (hdev->notify)
hdev->notify(hdev, HCI_NOTIFY_CONN_ADD); hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
tasklet_enable(&hdev->tx_task);
return conn; return conn;
} }
...@@ -195,11 +196,12 @@ int hci_conn_del(struct hci_conn *conn) ...@@ -195,11 +196,12 @@ int hci_conn_del(struct hci_conn *conn)
hdev->acl_cnt += conn->sent; hdev->acl_cnt += conn->sent;
} }
tasklet_disable(&hdev->tx_task);
hci_conn_hash_del(hdev, conn);
if (hdev->notify) if (hdev->notify)
hdev->notify(hdev, HCI_NOTIFY_CONN_DEL); hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
tasklet_disable(&hdev->tx_task);
hci_conn_hash_del(hdev, conn);
tasklet_enable(&hdev->tx_task); tasklet_enable(&hdev->tx_task);
skb_queue_purge(&conn->data_q); 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 * ...@@ -104,7 +104,7 @@ static void hci_cc_link_policy(struct hci_dev *hdev, __u16 ocf, struct sk_buff *
else else
conn->link_mode |= HCI_LM_MASTER; conn->link_mode |= HCI_LM_MASTER;
} }
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
break; break;
...@@ -229,8 +229,11 @@ static void hci_cc_host_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb ...@@ -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); 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); hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
tasklet_enable(&hdev->tx_task);
}
} }
break; break;
...@@ -247,8 +250,11 @@ static void hci_cc_host_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb ...@@ -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); 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); hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
tasklet_enable(&hdev->tx_task);
}
} }
hci_req_complete(hdev, status); hci_req_complete(hdev, status);
break; break;
...@@ -320,7 +326,7 @@ static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *s ...@@ -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); 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, 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; break;
case OCF_READ_BD_ADDR: case OCF_READ_BD_ADDR:
...@@ -400,7 +406,7 @@ static void hci_cs_link_ctl(struct hci_dev *hdev, __u16 ocf, __u8 status) ...@@ -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); BT_DBG("%s Add SCO error: handle %d status 0x%x", hdev->name, handle, status);
hci_dev_lock(hdev); hci_dev_lock(hdev);
acl = hci_conn_hash_lookup_handle(hdev, handle); acl = hci_conn_hash_lookup_handle(hdev, handle);
if (acl && (sco = acl->link)) { if (acl && (sco = acl->link)) {
sco->state = BT_CLOSED; sco->state = BT_CLOSED;
...@@ -542,7 +548,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk ...@@ -542,7 +548,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
bacpy(&cp.bdaddr, &ev->bdaddr); bacpy(&cp.bdaddr, &ev->bdaddr);
if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
cp.role = 0x00; /* Become master */ cp.role = 0x00; /* Become master */
else else
...@@ -585,7 +591,6 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s ...@@ -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)) if (test_bit(HCI_ENCRYPT, &hdev->flags))
conn->link_mode |= HCI_LM_ENCRYPT; conn->link_mode |= HCI_LM_ENCRYPT;
/* Set link policy */ /* Set link policy */
if (conn->type == ACL_LINK && hdev->link_policy) { if (conn->type == ACL_LINK && hdev->link_policy) {
struct hci_cp_write_link_policy cp; 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 ...@@ -710,7 +715,7 @@ static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb
if (conn) { if (conn) {
if (ev->role) if (ev->role)
conn->link_mode &= ~HCI_LM_MASTER; conn->link_mode &= ~HCI_LM_MASTER;
else else
conn->link_mode |= HCI_LM_MASTER; conn->link_mode |= HCI_LM_MASTER;
} }
...@@ -774,13 +779,28 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff * ...@@ -774,13 +779,28 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
conn->link_mode &= ~HCI_LM_ENCRYPT; conn->link_mode &= ~HCI_LM_ENCRYPT;
} }
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
hci_proto_encrypt_cfm(conn, ev->status); hci_proto_encrypt_cfm(conn, ev->status);
} }
hci_dev_unlock(hdev); 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) void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
{ {
struct hci_event_hdr *hdr = (struct hci_event_hdr *) skb->data; 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) ...@@ -833,6 +853,18 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_encrypt_change_evt(hdev, skb); hci_encrypt_change_evt(hdev, skb);
break; 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: case HCI_EV_CMD_STATUS:
cs = (struct hci_ev_cmd_status *) skb->data; cs = (struct hci_ev_cmd_status *) skb->data;
skb_pull(skb, sizeof(cs)); skb_pull(skb, sizeof(cs));
......
...@@ -185,6 +185,17 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign ...@@ -185,6 +185,17 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign
return 0; 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: case HCIGETCONNINFO:
return hci_get_conn_info(hdev, (void __user *)arg); return hci_get_conn_info(hdev, (void __user *)arg);
......
...@@ -1005,9 +1005,10 @@ static void l2cap_chan_del(struct sock *sk, int err) ...@@ -1005,9 +1005,10 @@ static void l2cap_chan_del(struct sock *sk, int err)
if (err) if (err)
sk->sk_err = err; sk->sk_err = err;
if (parent) if (parent) {
bt_accept_unlink(sk);
parent->sk_data_ready(parent, 0); parent->sk_data_ready(parent, 0);
else } else
sk->sk_state_change(sk); sk->sk_state_change(sk);
} }
...@@ -1303,7 +1304,7 @@ static int l2cap_build_conf_req(struct sock *sk, void *data) ...@@ -1303,7 +1304,7 @@ static int l2cap_build_conf_req(struct sock *sk, void *data)
if (pi->imtu != L2CAP_DEFAULT_MTU) if (pi->imtu != L2CAP_DEFAULT_MTU)
l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu); 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) //if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
// l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->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) ...@@ -97,17 +97,26 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err)
if (err) if (err)
sk->sk_err = err; sk->sk_err = err;
sk->sk_state = d->state; sk->sk_state = d->state;
parent = bt_sk(sk)->parent; 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) if (d->state == BT_CONNECTED)
rfcomm_session_getaddr(d->session, &bt_sk(sk)->src, NULL); rfcomm_session_getaddr(d->session, &bt_sk(sk)->src, NULL);
sk->sk_state_change(sk); sk->sk_state_change(sk);
} else }
parent->sk_data_ready(parent, 0);
bh_unlock_sock(sk); bh_unlock_sock(sk);
if (parent && sk->sk_zapped)
rfcomm_sock_kill(sk);
} }
/* ---- Socket functions ---- */ /* ---- 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