Bluetooth: A2MP: Build and Send msg helpers
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / bluetooth / a2mp.c
CommitLineData
466f8004
AE
1/*
2 Copyright (c) 2010,2011 Code Aurora Forum. All rights reserved.
3 Copyright (c) 2011,2012 Intel Corp.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2 and
7 only version 2 as published by the Free Software Foundation.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13*/
14
15#include <net/bluetooth/bluetooth.h>
16#include <net/bluetooth/hci_core.h>
17#include <net/bluetooth/l2cap.h>
9740e49d 18#include <net/bluetooth/a2mp.h>
466f8004 19
f6d3c6e7
AE
20/* A2MP build & send command helper functions */
21static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data)
22{
23 struct a2mp_cmd *cmd;
24 int plen;
25
26 plen = sizeof(*cmd) + len;
27 cmd = kzalloc(plen, GFP_KERNEL);
28 if (!cmd)
29 return NULL;
30
31 cmd->code = code;
32 cmd->ident = ident;
33 cmd->len = cpu_to_le16(len);
34
35 memcpy(cmd->data, data, len);
36
37 return cmd;
38}
39
40static void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len,
41 void *data)
42{
43 struct l2cap_chan *chan = mgr->a2mp_chan;
44 struct a2mp_cmd *cmd;
45 u16 total_len = len + sizeof(*cmd);
46 struct kvec iv;
47 struct msghdr msg;
48
49 cmd = __a2mp_build(code, ident, len, data);
50 if (!cmd)
51 return;
52
53 iv.iov_base = cmd;
54 iv.iov_len = total_len;
55
56 memset(&msg, 0, sizeof(msg));
57
58 msg.msg_iov = (struct iovec *) &iv;
59 msg.msg_iovlen = 1;
60
61 l2cap_chan_send(chan, &msg, total_len, 0);
62
63 kfree(cmd);
64}
65
466f8004
AE
66static struct l2cap_ops a2mp_chan_ops = {
67 .name = "L2CAP A2MP channel",
68};
69
70static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn)
71{
72 struct l2cap_chan *chan;
73 int err;
74
75 chan = l2cap_chan_create();
76 if (!chan)
77 return NULL;
78
79 BT_DBG("chan %p", chan);
80
81 hci_conn_hold(conn->hcon);
82
83 chan->omtu = L2CAP_A2MP_DEFAULT_MTU;
84 chan->imtu = L2CAP_A2MP_DEFAULT_MTU;
85 chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
86
87 chan->ops = &a2mp_chan_ops;
88
89 l2cap_chan_set_defaults(chan);
90 chan->remote_max_tx = chan->max_tx;
91 chan->remote_tx_win = chan->tx_win;
92
93 chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
94 chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
95
96 skb_queue_head_init(&chan->tx_q);
97
98 chan->mode = L2CAP_MODE_ERTM;
99
100 err = l2cap_ertm_init(chan);
101 if (err < 0) {
102 l2cap_chan_del(chan, 0);
103 return NULL;
104 }
105
106 chan->conf_state = 0;
107
108 l2cap_chan_add(conn, chan);
109
110 chan->remote_mps = chan->omtu;
111 chan->mps = chan->omtu;
112
113 chan->state = BT_CONNECTED;
114
115 return chan;
116}
9740e49d
AE
117
118/* AMP Manager functions */
119void amp_mgr_get(struct amp_mgr *mgr)
120{
121 BT_DBG("mgr %p", mgr);
122
123 kref_get(&mgr->kref);
124}
125
126static void amp_mgr_destroy(struct kref *kref)
127{
128 struct amp_mgr *mgr = container_of(kref, struct amp_mgr, kref);
129
130 BT_DBG("mgr %p", mgr);
131
132 kfree(mgr);
133}
134
135int amp_mgr_put(struct amp_mgr *mgr)
136{
137 BT_DBG("mgr %p", mgr);
138
139 return kref_put(&mgr->kref, &amp_mgr_destroy);
140}
141
142static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
143{
144 struct amp_mgr *mgr;
145 struct l2cap_chan *chan;
146
147 mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
148 if (!mgr)
149 return NULL;
150
151 BT_DBG("conn %p mgr %p", conn, mgr);
152
153 mgr->l2cap_conn = conn;
154
155 chan = a2mp_chan_open(conn);
156 if (!chan) {
157 kfree(mgr);
158 return NULL;
159 }
160
161 mgr->a2mp_chan = chan;
162 chan->data = mgr;
163
164 conn->hcon->amp_mgr = mgr;
165
166 kref_init(&mgr->kref);
167
168 return mgr;
169}