Add initial code for handling Bluetooth Management interface messages. Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Acked-by: Andrei Emeltchenko <andrei.emeltchenko@nokia.com> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>tirimbino
parent
c02178d22b
commit
0381101fd6
@ -0,0 +1,99 @@ |
||||
/*
|
||||
BlueZ - Bluetooth protocol stack for Linux |
||||
Copyright (C) 2010 Nokia Corporation |
||||
|
||||
This program is free software; you can redistribute it and/or modify |
||||
it under the terms of the GNU General Public License version 2 as |
||||
published by the Free Software Foundation; |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. |
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY |
||||
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES |
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
|
||||
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, |
||||
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS |
||||
SOFTWARE IS DISCLAIMED. |
||||
*/ |
||||
|
||||
/* Bluetooth HCI Management interface */ |
||||
|
||||
#include <asm/uaccess.h> |
||||
#include <asm/unaligned.h> |
||||
|
||||
#include <net/bluetooth/bluetooth.h> |
||||
#include <net/bluetooth/hci_core.h> |
||||
#include <net/bluetooth/mgmt.h> |
||||
|
||||
static void cmd_status(struct sock *sk, u16 cmd, u8 status) |
||||
{ |
||||
struct sk_buff *skb; |
||||
struct mgmt_hdr *hdr; |
||||
struct mgmt_ev_cmd_status *ev; |
||||
|
||||
BT_DBG("sock %p", sk); |
||||
|
||||
skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_ATOMIC); |
||||
if (!skb) |
||||
return; |
||||
|
||||
hdr = (void *) skb_put(skb, sizeof(*hdr)); |
||||
|
||||
hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS); |
||||
hdr->len = cpu_to_le16(sizeof(*ev)); |
||||
|
||||
ev = (void *) skb_put(skb, sizeof(*ev)); |
||||
ev->status = status; |
||||
put_unaligned_le16(cmd, &ev->opcode); |
||||
|
||||
if (sock_queue_rcv_skb(sk, skb) < 0) |
||||
kfree_skb(skb); |
||||
} |
||||
|
||||
int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) |
||||
{ |
||||
unsigned char *buf; |
||||
struct mgmt_hdr *hdr; |
||||
u16 opcode, len; |
||||
int err; |
||||
|
||||
BT_DBG("got %zu bytes", msglen); |
||||
|
||||
if (msglen < sizeof(*hdr)) |
||||
return -EINVAL; |
||||
|
||||
buf = kmalloc(msglen, GFP_ATOMIC); |
||||
if (!buf) |
||||
return -ENOMEM; |
||||
|
||||
if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) { |
||||
err = -EFAULT; |
||||
goto done; |
||||
} |
||||
|
||||
hdr = (struct mgmt_hdr *) buf; |
||||
opcode = get_unaligned_le16(&hdr->opcode); |
||||
len = get_unaligned_le16(&hdr->len); |
||||
|
||||
if (len != msglen - sizeof(*hdr)) { |
||||
err = -EINVAL; |
||||
goto done; |
||||
} |
||||
|
||||
switch (opcode) { |
||||
default: |
||||
BT_DBG("Unknown op %u", opcode); |
||||
cmd_status(sk, opcode, 0x01); |
||||
break; |
||||
} |
||||
|
||||
err = msglen; |
||||
|
||||
done: |
||||
kfree(buf); |
||||
return err; |
||||
} |
Loading…
Reference in new issue