Commit 1cdd77fe authored by David S. Miller's avatar David S. Miller

Merge http://linux-mh.bkbits.net/bluetooth-2.6

into nuts.davemloft.net:/disk1/BK/net-2.6
parents e0512113 0d8b93d0
......@@ -46,6 +46,8 @@
#define VERSION "1.0"
static int ignore = 0;
static struct usb_device_id bcm203x_table[] = {
/* Broadcom Blutonium (BCM2033) */
{ USB_DEVICE(0x0a5c, 0x2033) },
......@@ -55,7 +57,6 @@ static struct usb_device_id bcm203x_table[] = {
MODULE_DEVICE_TABLE(usb, bcm203x_table);
#define BCM203X_ERROR 0
#define BCM203X_RESET 1
#define BCM203X_LOAD_MINIDRV 2
......@@ -175,7 +176,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
BT_DBG("intf %p id %p", intf, id);
if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
if (ignore || (intf->cur_altsetting->desc.bInterfaceNumber != 0))
return -ENODEV;
data = kmalloc(sizeof(*data), GFP_KERNEL);
......@@ -304,6 +305,9 @@ static void __exit bcm203x_exit(void)
module_init(bcm203x_init);
module_exit(bcm203x_exit);
module_param(ignore, bool, 0644);
MODULE_PARM_DESC(ignore, "Ignore devices from the matching table");
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Broadcom Blutonium firmware driver ver " VERSION);
MODULE_VERSION(VERSION);
......
......@@ -47,6 +47,8 @@
#define VERSION "1.1"
static int ignore = 0;
static struct usb_driver bfusb_driver;
static struct usb_device_id bfusb_table[] = {
......@@ -655,6 +657,9 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
BT_DBG("intf %p id %p", intf, id);
if (ignore)
return -ENODEV;
/* Check number of endpoints */
if (intf->cur_altsetting->desc.bNumEndpoints < 2)
return -EIO;
......@@ -792,6 +797,9 @@ static void __exit bfusb_exit(void)
module_init(bfusb_init);
module_exit(bfusb_exit);
module_param(ignore, bool, 0644);
MODULE_PARM_DESC(ignore, "Ignore devices from the matching table");
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("BlueFRITZ! USB driver ver " VERSION);
MODULE_VERSION(VERSION);
......
......@@ -265,7 +265,7 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
/* This is a rewrite of pkt_avail in ABCSP */
static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
{
struct bcsp_struct *bcsp = (struct bcsp_struct *) hu->priv;
struct bcsp_struct *bcsp = hu->priv;
unsigned long flags;
struct sk_buff *skb;
......@@ -629,7 +629,7 @@ static int bcsp_recv(struct hci_uart *hu, void *data, int count)
static void bcsp_timed_event(unsigned long arg)
{
struct hci_uart *hu = (struct hci_uart *) arg;
struct bcsp_struct *bcsp = (struct bcsp_struct *) hu->priv;
struct bcsp_struct *bcsp = hu->priv;
struct sk_buff *skb;
unsigned long flags;
......
......@@ -51,6 +51,7 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include "hci_uart.h"
#ifndef CONFIG_BT_HCIUART_DEBUG
......@@ -60,6 +61,8 @@
#define BT_DMP( A... )
#endif
static int reset = 0;
static struct hci_uart_proto *hup[HCI_UART_MAX_PROTO];
int hci_uart_register_proto(struct hci_uart_proto *p)
......@@ -412,7 +415,10 @@ static int hci_uart_register_dev(struct hci_uart *hu)
hdev->destruct = hci_uart_destruct;
hdev->owner = THIS_MODULE;
if (reset)
set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);
if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device");
hci_free_dev(hdev);
......@@ -577,7 +583,10 @@ static void __exit hci_uart_exit(void)
module_init(hci_uart_init);
module_exit(hci_uart_exit);
MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>");
module_param(reset, bool, 0644);
MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth HCI UART driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
......
......@@ -66,6 +66,9 @@
#define URB_ZERO_PACKET 0
#endif
static int ignore = 0;
static int reset = 0;
#ifdef CONFIG_BT_HCIUSB_SCO
static int isoc = 2;
#endif
......@@ -827,7 +830,7 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id
id = match;
}
if (id->driver_info & HCI_IGNORE)
if (ignore || id->driver_info & HCI_IGNORE)
return -ENODEV;
if (intf->cur_altsetting->desc.bInterfaceNumber > 0)
......@@ -963,7 +966,7 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id
hdev->owner = THIS_MODULE;
if (id->driver_info & HCI_RESET)
if (reset || id->driver_info & HCI_RESET)
set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);
if (hci_register_dev(hdev) < 0) {
......@@ -1036,6 +1039,12 @@ static void __exit hci_usb_exit(void)
module_init(hci_usb_init);
module_exit(hci_usb_exit);
module_param(ignore, bool, 0644);
MODULE_PARM_DESC(ignore, "Ignore devices from the matching table");
module_param(reset, bool, 0644);
MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
#ifdef CONFIG_BT_HCIUSB_SCO
module_param(isoc, int, 0644);
MODULE_PARM_DESC(isoc, "Set isochronous transfers for SCO over HCI support");
......
......@@ -277,7 +277,6 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
return NULL;
}
void hci_acl_connect(struct hci_conn *conn);
void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
void hci_add_sco(struct hci_conn *conn, __u16 handle);
......@@ -589,6 +588,5 @@ struct hci_sec_filter {
#define hci_req_unlock(d) up(&d->req_lock)
void hci_req_complete(struct hci_dev *hdev, int result);
void hci_req_cancel(struct hci_dev *hdev, int err);
#endif /* __HCI_CORE_H */
......@@ -38,17 +38,19 @@ struct sockaddr_l2 {
bdaddr_t l2_bdaddr;
};
/* Socket options */
/* L2CAP socket options */
#define L2CAP_OPTIONS 0x01
struct l2cap_options {
__u16 omtu;
__u16 imtu;
__u16 flush_to;
__u8 mode;
};
#define L2CAP_CONNINFO 0x02
#define L2CAP_CONNINFO 0x02
struct l2cap_conninfo {
__u16 hci_handle;
__u8 dev_class[3];
};
#define L2CAP_LM 0x03
......@@ -59,20 +61,6 @@ struct l2cap_conninfo {
#define L2CAP_LM_RELIABLE 0x0010
#define L2CAP_LM_SECURE 0x0020
#define L2CAP_QOS 0x04
struct l2cap_qos {
__u16 service_type;
__u32 token_rate;
__u32 token_bucket_size;
__u32 peak_bandwidth;
__u32 latency;
__u32 delay_variation;
};
#define L2CAP_SERV_NO_TRAFFIC 0x00
#define L2CAP_SERV_BEST_EFFORT 0x01
#define L2CAP_SERV_GUARANTEED 0x02
/* L2CAP command codes */
#define L2CAP_COMMAND_REJ 0x01
#define L2CAP_CONN_REQ 0x02
......@@ -154,6 +142,7 @@ struct l2cap_conf_opt {
#define L2CAP_CONF_MTU 0x01
#define L2CAP_CONF_FLUSH_TO 0x02
#define L2CAP_CONF_QOS 0x03
#define L2CAP_CONF_RFC 0x04
#define L2CAP_CONF_MAX_SIZE 22
......@@ -198,11 +187,11 @@ struct l2cap_conn {
bdaddr_t *dst;
bdaddr_t *src;
unsigned int mtu;
spinlock_t lock;
struct sk_buff *rx_skb;
__u32 rx_len;
__u8 rx_ident;
......@@ -222,7 +211,7 @@ struct l2cap_pinfo {
__u16 imtu;
__u16 omtu;
__u16 flush_to;
__u32 link_mode;
__u8 conf_state;
......
......@@ -181,6 +181,8 @@ struct rfcomm_dlc {
u8 v24_sig;
u8 mscex;
u32 link_mode;
uint mtu;
uint cfc;
uint rx_credits;
......@@ -216,22 +218,6 @@ struct rfcomm_dlc {
#define RFCOMM_CFC_DISABLED 0
#define RFCOMM_CFC_ENABLED RFCOMM_MAX_CREDITS
extern struct task_struct *rfcomm_thread;
extern unsigned long rfcomm_event;
static inline void rfcomm_schedule(uint event)
{
if (!rfcomm_thread)
return;
//set_bit(event, &rfcomm_event);
set_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);
wake_up_process(rfcomm_thread);
}
extern struct semaphore rfcomm_sem;
#define rfcomm_lock() down(&rfcomm_sem);
#define rfcomm_unlock() up(&rfcomm_sem);
/* ---- RFCOMM DLCs (channels) ---- */
struct rfcomm_dlc *rfcomm_dlc_alloc(int prio);
void rfcomm_dlc_free(struct rfcomm_dlc *d);
......@@ -271,11 +257,6 @@ static inline void rfcomm_dlc_unthrottle(struct rfcomm_dlc *d)
}
/* ---- RFCOMM sessions ---- */
struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state);
struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst);
struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int *err);
void rfcomm_session_del(struct rfcomm_session *s);
void rfcomm_session_close(struct rfcomm_session *s, int err);
void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, bdaddr_t *dst);
static inline void rfcomm_session_hold(struct rfcomm_session *s)
......@@ -283,27 +264,36 @@ static inline void rfcomm_session_hold(struct rfcomm_session *s)
atomic_inc(&s->refcnt);
}
static inline void rfcomm_session_put(struct rfcomm_session *s)
{
if (atomic_dec_and_test(&s->refcnt))
rfcomm_session_del(s);
}
/* ---- RFCOMM chechsum ---- */
extern u8 rfcomm_crc_table[];
/* ---- RFCOMM sockets ---- */
struct sockaddr_rc {
sa_family_t rc_family;
bdaddr_t rc_bdaddr;
u8 rc_channel;
sa_family_t rc_family;
bdaddr_t rc_bdaddr;
u8 rc_channel;
};
#define RFCOMM_CONNINFO 0x02
struct rfcomm_conninfo {
__u16 hci_handle;
__u8 dev_class[3];
};
#define RFCOMM_LM 0x03
#define RFCOMM_LM_MASTER 0x0001
#define RFCOMM_LM_AUTH 0x0002
#define RFCOMM_LM_ENCRYPT 0x0004
#define RFCOMM_LM_TRUSTED 0x0008
#define RFCOMM_LM_RELIABLE 0x0010
#define RFCOMM_LM_SECURE 0x0020
#define rfcomm_pi(sk) ((struct rfcomm_pinfo *)sk->sk_protinfo)
struct rfcomm_pinfo {
struct rfcomm_dlc *dlc;
u8 channel;
u32 link_mode;
};
int rfcomm_init_sockets(void);
......
......@@ -39,15 +39,16 @@ struct sockaddr_sco {
bdaddr_t sco_bdaddr;
};
/* set/get sockopt defines */
#define SCO_OPTIONS 0x01
/* SCO socket options */
#define SCO_OPTIONS 0x01
struct sco_options {
__u16 mtu;
};
#define SCO_CONNINFO 0x02
#define SCO_CONNINFO 0x02
struct sco_conninfo {
__u16 hci_handle;
__u8 dev_class[3];
};
/* ---- SCO connections ---- */
......
......@@ -139,6 +139,19 @@ static int cmtp_msgnum_get(struct cmtp_session *session)
return session->msgnum;
}
static void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb)
{
struct cmtp_scb *scb = (void *) skb->cb;
BT_DBG("session %p skb %p len %d", session, skb, skb->len);
scb->id = -1;
scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3);
skb_queue_tail(&session->transmit, skb);
cmtp_schedule(session);
}
static void cmtp_send_interopmsg(struct cmtp_session *session,
__u8 subcmd, __u16 appl, __u16 msgnum,
......@@ -337,21 +350,6 @@ void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
capi_ctr_handle_message(ctrl, appl, skb);
}
void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb)
{
struct cmtp_scb *scb = (void *) skb->cb;
BT_DBG("session %p skb %p len %d", session, skb, skb->len);
scb->id = -1;
scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3);
skb_queue_tail(&session->transmit, skb);
cmtp_schedule(session);
}
static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
{
BT_DBG("ctrl %p data %p", ctrl, data);
......
......@@ -120,7 +120,6 @@ int cmtp_attach_device(struct cmtp_session *session);
void cmtp_detach_device(struct cmtp_session *session);
void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb);
void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb);
static inline void cmtp_schedule(struct cmtp_session *session)
{
......
......@@ -53,7 +53,7 @@
#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;
......
......@@ -59,7 +59,7 @@ static void hci_rx_task(unsigned long arg);
static void hci_tx_task(unsigned long arg);
static void hci_notify(struct hci_dev *hdev, int event);
rwlock_t hci_task_lock = RW_LOCK_UNLOCKED;
static rwlock_t hci_task_lock = RW_LOCK_UNLOCKED;
/* HCI device list */
LIST_HEAD(hci_dev_list);
......@@ -106,7 +106,7 @@ void hci_req_complete(struct hci_dev *hdev, int result)
}
}
void hci_req_cancel(struct hci_dev *hdev, int err)
static void hci_req_cancel(struct hci_dev *hdev, int err)
{
BT_DBG("%s err 0x%2.2x", hdev->name, err);
......
......@@ -447,7 +447,7 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
goto done;
}
int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int len)
static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int len)
{
struct hci_ufilter uf = { .opcode = 0 };
struct sock *sk = sock->sk;
......@@ -514,7 +514,7 @@ int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user
return err;
}
int hci_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
{
struct hci_ufilter uf;
struct sock *sk = sock->sk;
......@@ -567,7 +567,7 @@ int hci_sock_getsockopt(struct socket *sock, int level, int optname, char __user
return 0;
}
struct proto_ops hci_sock_ops = {
static struct proto_ops hci_sock_ops = {
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = hci_sock_release,
......@@ -647,13 +647,13 @@ static int hci_sock_dev_event(struct notifier_block *this, unsigned long event,
return NOTIFY_DONE;
}
struct net_proto_family hci_sock_family_ops = {
static struct net_proto_family hci_sock_family_ops = {
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.create = hci_sock_create,
};
struct notifier_block hci_sock_nblock = {
static struct notifier_block hci_sock_nblock = {
.notifier_call = hci_sock_dev_event
};
......
......@@ -50,7 +50,7 @@
#define BT_DBG(D...)
#endif
#define VERSION "1.0"
#define VERSION "1.1"
static DECLARE_RWSEM(hidp_session_sem);
static LIST_HEAD(hidp_session_list);
......@@ -130,7 +130,7 @@ static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned i
struct sk_buff *skb;
unsigned char newleds;
BT_DBG("session %p hid %p data %p size %d", session, device, data, size);
BT_DBG("input %p type %d code %d value %d", dev, type, code, value);
if (type != EV_LED)
return -1;
......@@ -151,7 +151,7 @@ static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned i
return -ENOMEM;
}
*skb_put(skb, 1) = 0xa2;
*skb_put(skb, 1) = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
*skb_put(skb, 1) = 0x01;
*skb_put(skb, 1) = newleds;
......@@ -232,36 +232,171 @@ static inline void hidp_del_timer(struct hidp_session *session)
del_timer(&session->timer);
}
static inline void hidp_send_message(struct hidp_session *session, unsigned char hdr)
static int __hidp_send_ctrl_message(struct hidp_session *session,
unsigned char hdr, unsigned char *data, int size)
{
struct sk_buff *skb;
BT_DBG("session %p", session);
BT_DBG("session %p data %p size %d", session, data, size);
if (!(skb = alloc_skb(1, GFP_ATOMIC))) {
BT_ERR("Can't allocate memory for message");
return;
if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) {
BT_ERR("Can't allocate memory for new frame");
return -ENOMEM;
}
*skb_put(skb, 1) = hdr;
if (data && size > 0)
memcpy(skb_put(skb, size), data, size);
skb_queue_tail(&session->ctrl_transmit, skb);
return 0;
}
static int inline hidp_send_ctrl_message(struct hidp_session *session,
unsigned char hdr, unsigned char *data, int size)
{
int err;
err = __hidp_send_ctrl_message(session, hdr, data, size);
hidp_schedule(session);
return err;
}
static inline void hidp_process_handshake(struct hidp_session *session, unsigned char param)
{
BT_DBG("session %p param 0x%02x", session, param);
switch (param) {
case HIDP_HSHK_SUCCESSFUL:
/* FIXME: Call into SET_ GET_ handlers here */
break;
case HIDP_HSHK_NOT_READY:
case HIDP_HSHK_ERR_INVALID_REPORT_ID:
case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST:
case HIDP_HSHK_ERR_INVALID_PARAMETER:
/* FIXME: Call into SET_ GET_ handlers here */
break;
case HIDP_HSHK_ERR_UNKNOWN:
break;
case HIDP_HSHK_ERR_FATAL:
/* Device requests a reboot, as this is the only way this error
* can be recovered. */
__hidp_send_ctrl_message(session,
HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0);
break;
default:
__hidp_send_ctrl_message(session,
HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
break;
}
}
static inline void hidp_process_hid_control(struct hidp_session *session, unsigned char param)
{
BT_DBG("session %p param 0x%02x", session, param);
switch (param) {
case HIDP_CTRL_NOP:
break;
case HIDP_CTRL_VIRTUAL_CABLE_UNPLUG:
/* Flush the transmit queues */
skb_queue_purge(&session->ctrl_transmit);
skb_queue_purge(&session->intr_transmit);
/* Kill session thread */
atomic_inc(&session->terminate);
break;
case HIDP_CTRL_HARD_RESET:
case HIDP_CTRL_SOFT_RESET:
case HIDP_CTRL_SUSPEND:
case HIDP_CTRL_EXIT_SUSPEND:
/* FIXME: We have to parse these and return no error */
break;
default:
__hidp_send_ctrl_message(session,
HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
break;
}
}
static inline int hidp_recv_frame(struct hidp_session *session, struct sk_buff *skb)
static inline void hidp_process_data(struct hidp_session *session, struct sk_buff *skb, unsigned char param)
{
__u8 hdr;
BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
switch (param) {
case HIDP_DATA_RTYPE_INPUT:
hidp_set_timer(session);
if (session->input)
hidp_input_report(session, skb);
break;
case HIDP_DATA_RTYPE_OTHER:
case HIDP_DATA_RTYPE_OUPUT:
case HIDP_DATA_RTYPE_FEATURE:
break;
default:
__hidp_send_ctrl_message(session,
HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
}
}
static inline void hidp_recv_ctrl_frame(struct hidp_session *session, struct sk_buff *skb)
{
unsigned char hdr, type, param;
BT_DBG("session %p skb %p len %d", session, skb, skb->len);
hdr = skb->data[0];
skb_pull(skb, 1);
if (hdr == 0xa1) {
hidp_set_timer(session);
type = hdr & HIDP_HEADER_TRANS_MASK;
param = hdr & HIDP_HEADER_PARAM_MASK;
switch (type) {
case HIDP_TRANS_HANDSHAKE:
hidp_process_handshake(session, param);
break;
case HIDP_TRANS_HID_CONTROL:
hidp_process_hid_control(session, param);
break;
case HIDP_TRANS_DATA:
hidp_process_data(session, skb, param);
break;
default:
__hidp_send_ctrl_message(session,
HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0);
break;
}
kfree_skb(skb);
}
static inline void hidp_recv_intr_frame(struct hidp_session *session, struct sk_buff *skb)
{
unsigned char hdr;
BT_DBG("session %p skb %p len %d", session, skb, skb->len);
hdr = skb->data[0];
skb_pull(skb, 1);
if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
hidp_set_timer(session);
if (session->input)
hidp_input_report(session, skb);
} else {
......@@ -269,7 +404,6 @@ static inline int hidp_recv_frame(struct hidp_session *session, struct sk_buff *
}
kfree_skb(skb);
return 0;
}
static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
......@@ -350,12 +484,12 @@ static int hidp_session(void *arg)
while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
skb_orphan(skb);
hidp_recv_frame(session, skb);
hidp_recv_ctrl_frame(session, skb);
}
while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
skb_orphan(skb);
hidp_recv_frame(session, skb);
hidp_recv_intr_frame(session, skb);
}
hidp_process_transmit(session);
......@@ -514,7 +648,8 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
goto unlink;
if (session->input) {
hidp_send_message(session, 0x70);
hidp_send_ctrl_message(session,
HIDP_TRANS_SET_PROTOCOL | HIDP_PROTO_BOOT, NULL, 0);
session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
session->leds = 0xff;
......@@ -554,7 +689,8 @@ int hidp_del_connection(struct hidp_conndel_req *req)
session = __hidp_get_session(&req->bdaddr);
if (session) {
if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
hidp_send_message(session, 0x15);
hidp_send_ctrl_message(session,
HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG, NULL, 0);
} else {
/* Flush the transmit queues */
skb_queue_purge(&session->ctrl_transmit);
......
......@@ -26,6 +26,51 @@
#include <linux/types.h>
#include <net/bluetooth/bluetooth.h>
/* HIDP header masks */
#define HIDP_HEADER_TRANS_MASK 0xf0
#define HIDP_HEADER_PARAM_MASK 0x0f
/* HIDP transaction types */
#define HIDP_TRANS_HANDSHAKE 0x00
#define HIDP_TRANS_HID_CONTROL 0x10
#define HIDP_TRANS_GET_REPORT 0x40
#define HIDP_TRANS_SET_REPORT 0x50
#define HIDP_TRANS_GET_PROTOCOL 0x60
#define HIDP_TRANS_SET_PROTOCOL 0x70
#define HIDP_TRANS_GET_IDLE 0x80
#define HIDP_TRANS_SET_IDLE 0x90
#define HIDP_TRANS_DATA 0xa0
#define HIDP_TRANS_DATC 0xb0
/* HIDP handshake results */
#define HIDP_HSHK_SUCCESSFUL 0x00
#define HIDP_HSHK_NOT_READY 0x01
#define HIDP_HSHK_ERR_INVALID_REPORT_ID 0x02
#define HIDP_HSHK_ERR_UNSUPPORTED_REQUEST 0x03
#define HIDP_HSHK_ERR_INVALID_PARAMETER 0x04
#define HIDP_HSHK_ERR_UNKNOWN 0x0e
#define HIDP_HSHK_ERR_FATAL 0x0f
/* HIDP control operation parameters */
#define HIDP_CTRL_NOP 0x00
#define HIDP_CTRL_HARD_RESET 0x01
#define HIDP_CTRL_SOFT_RESET 0x02
#define HIDP_CTRL_SUSPEND 0x03
#define HIDP_CTRL_EXIT_SUSPEND 0x04
#define HIDP_CTRL_VIRTUAL_CABLE_UNPLUG 0x05
/* HIDP data transaction headers */
#define HIDP_DATA_RTYPE_MASK 0x03
#define HIDP_DATA_RSRVD_MASK 0x0c
#define HIDP_DATA_RTYPE_OTHER 0x00
#define HIDP_DATA_RTYPE_INPUT 0x01
#define HIDP_DATA_RTYPE_OUPUT 0x02
#define HIDP_DATA_RTYPE_FEATURE 0x03
/* HIDP protocol header parameters */
#define HIDP_PROTO_BOOT 0x00
#define HIDP_PROTO_REPORT 0x01
/* HIDP ioctl defines */
#define HIDPCONNADD _IOW('H', 200, int)
#define HIDPCONNDEL _IOW('H', 201, int)
......
......@@ -57,11 +57,11 @@
#define BT_DBG(D...)
#endif
#define VERSION "2.6"
#define VERSION "2.7"
static struct proto_ops l2cap_sock_ops;
struct bt_sock_list l2cap_sk_list = {
static struct bt_sock_list l2cap_sk_list = {
.lock = RW_LOCK_UNLOCKED
};
......@@ -798,7 +798,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
switch (optname) {
case L2CAP_OPTIONS:
len = min_t(unsigned int, sizeof(opts), optlen);
if (copy_from_user((char *)&opts, optval, len)) {
if (copy_from_user((char *) &opts, optval, len)) {
err = -EFAULT;
break;
}
......@@ -807,7 +807,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
break;
case L2CAP_LM:
if (get_user(opt, (u32 __user *)optval)) {
if (get_user(opt, (u32 __user *) optval)) {
err = -EFAULT;
break;
}
......@@ -829,7 +829,9 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
struct sock *sk = sock->sk;
struct l2cap_options opts;
struct l2cap_conninfo cinfo;
int len, err = 0;
int len, err = 0;
BT_DBG("sk %p", sk);
if (get_user(len, optlen))
return -EFAULT;
......@@ -841,15 +843,16 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
opts.imtu = l2cap_pi(sk)->imtu;
opts.omtu = l2cap_pi(sk)->omtu;
opts.flush_to = l2cap_pi(sk)->flush_to;
opts.mode = 0x00;
len = min_t(unsigned int, len, sizeof(opts));
if (copy_to_user(optval, (char *)&opts, len))
if (copy_to_user(optval, (char *) &opts, len))
err = -EFAULT;
break;
case L2CAP_LM:
if (put_user(l2cap_pi(sk)->link_mode, (u32 __user *)optval))
if (put_user(l2cap_pi(sk)->link_mode, (u32 __user *) optval))
err = -EFAULT;
break;
......@@ -860,9 +863,10 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
}
cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle;
memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3);
len = min_t(unsigned int, len, sizeof(cinfo));
if (copy_to_user(optval, (char *)&cinfo, len))
if (copy_to_user(optval, (char *) &cinfo, len))
err = -EFAULT;
break;
......
......@@ -50,7 +50,7 @@
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/rfcomm.h>
#define VERSION "1.3"
#define VERSION "1.4"
#ifndef CONFIG_BT_RFCOMM_DEBUG
#undef BT_DBG
......@@ -61,8 +61,12 @@
struct proc_dir_entry *proc_bt_rfcomm;
#endif
struct task_struct *rfcomm_thread;
DECLARE_MUTEX(rfcomm_sem);
static struct task_struct *rfcomm_thread;
static DECLARE_MUTEX(rfcomm_sem);
#define rfcomm_lock() down(&rfcomm_sem);
#define rfcomm_unlock() up(&rfcomm_sem);
unsigned long rfcomm_event;
static LIST_HEAD(session_list);
......@@ -81,6 +85,10 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr);
static void rfcomm_process_connect(struct rfcomm_session *s);
static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int *err);
static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst);
static void rfcomm_session_del(struct rfcomm_session *s);
/* ---- RFCOMM frame parsing macros ---- */
#define __get_dlci(b) ((b & 0xfc) >> 2)
#define __get_channel(b) ((b & 0xf8) >> 3)
......@@ -111,6 +119,21 @@ static void rfcomm_process_connect(struct rfcomm_session *s);
#define __get_rpn_stop_bits(line) (((line) >> 2) & 0x1)
#define __get_rpn_parity(line) (((line) >> 3) & 0x3)
static inline void rfcomm_schedule(uint event)
{
if (!rfcomm_thread)
return;
//set_bit(event, &rfcomm_event);
set_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);
wake_up_process(rfcomm_thread);
}
static inline void rfcomm_session_put(struct rfcomm_session *s)
{
if (atomic_dec_and_test(&s->refcnt))
rfcomm_session_del(s);
}
/* ---- RFCOMM FCS computation ---- */
/* CRC on 2 bytes */
......@@ -458,7 +481,7 @@ int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig)
}
/* ---- RFCOMM sessions ---- */
struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state)
static struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state)
{
struct rfcomm_session *s = kmalloc(sizeof(*s), GFP_KERNEL);
if (!s)
......@@ -487,7 +510,7 @@ struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state)
return s;
}
void rfcomm_session_del(struct rfcomm_session *s)
static void rfcomm_session_del(struct rfcomm_session *s)
{
int state = s->state;
......@@ -505,7 +528,7 @@ void rfcomm_session_del(struct rfcomm_session *s)
module_put(THIS_MODULE);
}
struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst)
static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst)
{
struct rfcomm_session *s;
struct list_head *p, *n;
......@@ -521,7 +544,7 @@ struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst)
return NULL;
}
void rfcomm_session_close(struct rfcomm_session *s, int err)
static void rfcomm_session_close(struct rfcomm_session *s, int err)
{
struct rfcomm_dlc *d;
struct list_head *p, *n;
......@@ -542,7 +565,7 @@ void rfcomm_session_close(struct rfcomm_session *s, int err)
rfcomm_session_put(s);
}
struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int *err)
static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int *err)
{
struct rfcomm_session *s = NULL;
struct sockaddr_l2 addr;
......
......@@ -51,6 +51,8 @@
#include <asm/uaccess.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/rfcomm.h>
#ifndef CONFIG_BT_RFCOMM_DEBUG
......@@ -261,10 +263,18 @@ static void rfcomm_sock_close(struct sock *sk)
static void rfcomm_sock_init(struct sock *sk, struct sock *parent)
{
struct rfcomm_pinfo *pi = rfcomm_pi(sk);
BT_DBG("sk %p", sk);
if (parent)
if (parent) {
sk->sk_type = parent->sk_type;
pi->link_mode = rfcomm_pi(parent)->link_mode;
} else {
pi->link_mode = 0;
}
pi->dlc->link_mode = pi->link_mode;
}
static struct sock *rfcomm_sock_alloc(struct socket *sock, int proto, int prio)
......@@ -393,7 +403,7 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
return err;
}
int rfcomm_sock_listen(struct socket *sock, int backlog)
static int rfcomm_sock_listen(struct socket *sock, int backlog)
{
struct sock *sk = sock->sk;
int err = 0;
......@@ -437,7 +447,7 @@ int rfcomm_sock_listen(struct socket *sock, int backlog)
return err;
}
int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int flags)
static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int flags)
{
DECLARE_WAITQUEUE(wait, current);
struct sock *sk = sock->sk, *nsk;
......@@ -671,12 +681,22 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
{
struct sock *sk = sock->sk;
int err = 0;
u32 opt;
BT_DBG("sk %p", sk);
lock_sock(sk);
switch (optname) {
case RFCOMM_LM:
if (get_user(opt, (u32 __user *) optval)) {
err = -EFAULT;
break;
}
rfcomm_pi(sk)->link_mode = opt;
break;
default:
err = -ENOPROTOOPT;
break;
......@@ -689,7 +709,9 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
{
struct sock *sk = sock->sk;
int len, err = 0;
struct sock *l2cap_sk;
struct rfcomm_conninfo cinfo;
int len, err = 0;
BT_DBG("sk %p", sk);
......@@ -699,10 +721,32 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c
lock_sock(sk);
switch (optname) {
case RFCOMM_LM:
if (put_user(rfcomm_pi(sk)->link_mode, (u32 __user *) optval))
err = -EFAULT;
break;
case RFCOMM_CONNINFO:
if (sk->sk_state != BT_CONNECTED) {
err = -ENOTCONN;
break;
}
l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk;
cinfo.hci_handle = l2cap_pi(l2cap_sk)->conn->hcon->handle;
memcpy(cinfo.dev_class, l2cap_pi(l2cap_sk)->conn->hcon->dev_class, 3);
len = min_t(unsigned int, len, sizeof(cinfo));
if (copy_to_user(optval, (char *) &cinfo, len))
err = -EFAULT;
break;
default:
err = -ENOPROTOOPT;
break;
};
}
release_sock(sk);
return err;
......
......@@ -56,7 +56,7 @@
#define BT_DBG(D...)
#endif
#define VERSION "0.3"
#define VERSION "0.4"
static struct proto_ops sco_sock_ops;
......@@ -705,6 +705,7 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char
}
cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
len = min_t(unsigned int, len, sizeof(cinfo));
if (copy_to_user(optval, (char *)&cinfo, len))
......@@ -1045,7 +1046,7 @@ static void __exit sco_exit(void)
module_init(sco_init);
module_exit(sco_exit);
MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>");
MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth SCO ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
......
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