23 #include <linux/module.h>
25 #include <linux/types.h>
26 #include <linux/errno.h>
27 #include <linux/kernel.h>
28 #include <linux/sched.h>
29 #include <linux/slab.h>
30 #include <linux/poll.h>
31 #include <linux/fcntl.h>
34 #include <linux/socket.h>
60 if (!bacmp(bdaddr, &session->bdaddr))
68 list_add(&session->list, &cmtp_session_list);
71 static void __cmtp_unlink_session(
struct cmtp_session *session)
78 memset(ci, 0,
sizeof(*ci));
88 static inline int cmtp_alloc_block_id(
struct cmtp_session *session)
92 for (i = 0; i < 16; i++)
101 static inline void cmtp_free_block_id(
struct cmtp_session *session,
int id)
106 static inline void cmtp_add_msgpart(
struct cmtp_session *session,
int id,
const unsigned char *
buf,
int count)
111 BT_DBG(
"session %p buf %p count %d", session, buf, count);
113 size = (
skb) ? skb->
len + count : count;
117 BT_ERR(
"Can't allocate memory for CAPI message");
121 if (skb && (skb->
len > 0))
122 skb_copy_from_linear_data(skb,
skb_put(nskb, skb->
len), skb->
len);
136 BT_DBG(
"session %p skb %p len %d", session, skb, skb->
len);
138 while (skb->
len > 0) {
141 switch (hdr & 0xc0) {
148 len = skb->
data[1] | (skb->
data[2] << 8);
156 id = (hdr & 0x3c) >> 2;
158 BT_DBG(
"hdr 0x%02x hdrlen %d len %d id %d", hdr, hdrlen, len,
id);
160 if (hdrlen + len > skb->
len) {
161 BT_ERR(
"Wrong size or header information in CMTP frame");
170 switch (hdr & 0x03) {
172 cmtp_add_msgpart(session,
id, skb->
data + hdrlen, len);
177 cmtp_add_msgpart(session,
id, skb->
data + hdrlen, len);
193 static int cmtp_send_frame(
struct cmtp_session *session,
unsigned char *
data,
int len)
199 BT_DBG(
"session %p data %p len %d", session, data, len);
209 static void cmtp_process_transmit(
struct cmtp_session *session)
215 BT_DBG(
"session %p", session);
219 BT_ERR(
"Can't allocate memory for new frame");
226 tail = session->
mtu - nskb->
len;
228 cmtp_send_frame(session, nskb->
data, nskb->
len);
233 size =
min_t(
uint, ((tail < 258) ? (tail - 2) : (tail - 3)), skb->
len);
236 scb->
id = cmtp_alloc_block_id(session);
246 | ((scb->
id << 2) & 0x3c)
247 | ((skb->
len ==
size) ? 0x00 : 0x01);
252 | ((scb->
id << 2) & 0x3c)
253 | ((skb->
len ==
size) ? 0x00 : 0x01);
254 hdr[1] = size & 0xff;
258 skb_copy_from_linear_data(skb,
skb_put(nskb, size), size);
264 cmtp_free_block_id(session, scb->
id);
266 cmtp_send_frame(session, nskb->
data, nskb->
len);
273 cmtp_send_frame(session, nskb->
data, nskb->
len);
281 struct sock *
sk = session->
sock->sk;
285 BT_DBG(
"session %p", session);
289 init_waitqueue_entry(&wait,
current);
301 if (!skb_linearize(skb))
302 cmtp_recv_frame(session, skb);
307 cmtp_process_transmit(session);
321 __cmtp_unlink_session(session);
343 s = __cmtp_get_session(&
bt_sk(sock->
sk)->dst);
367 skb_queue_head_init(&session->
transmit);
369 for (i = 0; i < 16; i++)
374 __cmtp_link_session(session);
379 if (IS_ERR(session->
task)) {
381 err = PTR_ERR(session->
task);
399 __cmtp_unlink_session(session);
416 session = __cmtp_get_session(&req->
bdaddr);
443 __cmtp_copy_session(session, &ci);
450 if (++
n >= req->
cnum)
468 session = __cmtp_get_session(&ci->
bdaddr);
470 __cmtp_copy_session(session, ci);
479 static int __init cmtp_init(
void)
488 static void __exit cmtp_exit(
void)