1 /*
2 CMTP implementation for Linux Bluetooth stack (BlueZ).
3 Copyright (C) 2002-2003 Marcel Holtmann <marcel@holtmann.org>
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 as
7 published by the Free Software Foundation;
8
9 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
12 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
13 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
19 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
20 SOFTWARE IS DISCLAIMED.
21 */
22
23 #include <linux/config.h>
24 #include <linux/module.h>
25
26 #include <linux/types.h>
27 #include <linux/errno.h>
28 #include <linux/kernel.h>
29 #include <linux/major.h>
30 #include <linux/sched.h>
31 #include <linux/slab.h>
32 #include <linux/poll.h>
33 #include <linux/fcntl.h>
34 #include <linux/skbuff.h>
35 #include <linux/socket.h>
36 #include <linux/ioctl.h>
37 #include <linux/file.h>
38 #include <net/sock.h>
39
40 #include <linux/capi.h>
41
42 #include "../drivers/isdn/avmb1/capilli.h"
43 #include "../drivers/isdn/avmb1/capicmd.h"
44 #include "../drivers/isdn/avmb1/capiutil.h"
45
46 #include "cmtp.h"
47
48 #ifndef CONFIG_BLUEZ_CMTP_DEBUG
49 #undef BT_DBG
50 #define BT_DBG(D...)
51 #endif
52
53 #define REVISION "1.0"
54
55 #define CAPI_INTEROPERABILITY 0x20
56
57 #define CAPI_INTEROPERABILITY_REQ CAPICMD(CAPI_INTEROPERABILITY, CAPI_REQ)
58 #define CAPI_INTEROPERABILITY_CONF CAPICMD(CAPI_INTEROPERABILITY, CAPI_CONF)
59 #define CAPI_INTEROPERABILITY_IND CAPICMD(CAPI_INTEROPERABILITY, CAPI_IND)
60 #define CAPI_INTEROPERABILITY_RESP CAPICMD(CAPI_INTEROPERABILITY, CAPI_RESP)
61
62 #define CAPI_INTEROPERABILITY_REQ_LEN (CAPI_MSG_BASELEN + 2)
63 #define CAPI_INTEROPERABILITY_CONF_LEN (CAPI_MSG_BASELEN + 4)
64 #define CAPI_INTEROPERABILITY_IND_LEN (CAPI_MSG_BASELEN + 2)
65 #define CAPI_INTEROPERABILITY_RESP_LEN (CAPI_MSG_BASELEN + 2)
66
67 #define CAPI_FUNCTION_REGISTER 0
68 #define CAPI_FUNCTION_RELEASE 1
69 #define CAPI_FUNCTION_GET_PROFILE 2
70 #define CAPI_FUNCTION_GET_MANUFACTURER 3
71 #define CAPI_FUNCTION_GET_VERSION 4
72 #define CAPI_FUNCTION_GET_SERIAL_NUMBER 5
73 #define CAPI_FUNCTION_MANUFACTURER 6
74 #define CAPI_FUNCTION_LOOPBACK 7
75
76 static struct capi_driver_interface *di;
77
78
79 #define CMTP_MSGNUM 1
80 #define CMTP_APPLID 2
81 #define CMTP_MAPPING 3
82
cmtp_application_add(struct cmtp_session * session,__u16 appl)83 static struct cmtp_application *cmtp_application_add(struct cmtp_session *session, __u16 appl)
84 {
85 struct cmtp_application *app = kmalloc(sizeof(*app), GFP_KERNEL);
86
87 BT_DBG("session %p application %p appl %d", session, app, appl);
88
89 if (!app)
90 return NULL;
91
92 memset(app, 0, sizeof(*app));
93
94 app->state = BT_OPEN;
95 app->appl = appl;
96
97 list_add_tail(&app->list, &session->applications);
98
99 return app;
100 }
101
cmtp_application_del(struct cmtp_session * session,struct cmtp_application * app)102 static void cmtp_application_del(struct cmtp_session *session, struct cmtp_application *app)
103 {
104 BT_DBG("session %p application %p", session, app);
105
106 if (app) {
107 list_del(&app->list);
108 kfree(app);
109 }
110 }
111
cmtp_application_get(struct cmtp_session * session,int pattern,__u16 value)112 static struct cmtp_application *cmtp_application_get(struct cmtp_session *session, int pattern, __u16 value)
113 {
114 struct cmtp_application *app;
115 struct list_head *p, *n;
116
117 list_for_each_safe(p, n, &session->applications) {
118 app = list_entry(p, struct cmtp_application, list);
119 switch (pattern) {
120 case CMTP_MSGNUM:
121 if (app->msgnum == value)
122 return app;
123 break;
124 case CMTP_APPLID:
125 if (app->appl == value)
126 return app;
127 break;
128 case CMTP_MAPPING:
129 if (app->mapping == value)
130 return app;
131 break;
132 }
133 }
134
135 return NULL;
136 }
137
cmtp_msgnum_get(struct cmtp_session * session)138 static int cmtp_msgnum_get(struct cmtp_session *session)
139 {
140 session->msgnum++;
141
142 if ((session->msgnum & 0xff) > 200)
143 session->msgnum = CMTP_INITIAL_MSGNUM + 1;
144
145 return session->msgnum;
146 }
147
148
cmtp_send_interopmsg(struct cmtp_session * session,__u8 subcmd,__u16 appl,__u16 msgnum,__u16 function,unsigned char * buf,int len)149 static void cmtp_send_interopmsg(struct cmtp_session *session,
150 __u8 subcmd, __u16 appl, __u16 msgnum,
151 __u16 function, unsigned char *buf, int len)
152 {
153 struct sk_buff *skb;
154 unsigned char *s;
155
156 BT_DBG("session %p subcmd 0x%02x appl %d msgnum %d", session, subcmd, appl, msgnum);
157
158 if (!(skb = alloc_skb(CAPI_MSG_BASELEN + 6 + len, GFP_ATOMIC))) {
159 BT_ERR("Can't allocate memory for interoperability packet");
160 return;
161 }
162
163 s = skb_put(skb, CAPI_MSG_BASELEN + 6 + len);
164
165 capimsg_setu16(s, 0, CAPI_MSG_BASELEN + 6 + len);
166 capimsg_setu16(s, 2, appl);
167 capimsg_setu8 (s, 4, CAPI_INTEROPERABILITY);
168 capimsg_setu8 (s, 5, subcmd);
169 capimsg_setu16(s, 6, msgnum);
170
171 /* Interoperability selector (Bluetooth Device Management) */
172 capimsg_setu16(s, 8, 0x0001);
173
174 capimsg_setu8 (s, 10, 3 + len);
175 capimsg_setu16(s, 11, function);
176 capimsg_setu8 (s, 13, len);
177
178 if (len > 0)
179 memcpy(s + 14, buf, len);
180
181 cmtp_send_capimsg(session, skb);
182 }
183
cmtp_recv_interopmsg(struct cmtp_session * session,struct sk_buff * skb)184 static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *skb)
185 {
186 struct capi_ctr *ctrl = session->ctrl;
187 struct cmtp_application *application;
188 __u16 appl, msgnum, func, info;
189 __u32 controller;
190
191 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
192
193 switch (CAPIMSG_SUBCOMMAND(skb->data)) {
194 case CAPI_CONF:
195 if (skb->len < CAPI_MSG_BASELEN + 10)
196 break;
197
198 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
199 info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);
200
201 switch (func) {
202 case CAPI_FUNCTION_REGISTER:
203 msgnum = CAPIMSG_MSGID(skb->data);
204
205 application = cmtp_application_get(session, CMTP_MSGNUM, msgnum);
206 if (application) {
207 application->state = BT_CONNECTED;
208 application->msgnum = 0;
209 application->mapping = CAPIMSG_APPID(skb->data);
210 wake_up_interruptible(&session->wait);
211 }
212
213 break;
214
215 case CAPI_FUNCTION_RELEASE:
216 appl = CAPIMSG_APPID(skb->data);
217
218 application = cmtp_application_get(session, CMTP_MAPPING, appl);
219 if (application) {
220 application->state = BT_CLOSED;
221 application->msgnum = 0;
222 wake_up_interruptible(&session->wait);
223 }
224
225 break;
226
227 case CAPI_FUNCTION_GET_PROFILE:
228 if (skb->len < CAPI_MSG_BASELEN + 11 + sizeof(capi_profile))
229 break;
230
231 controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11);
232 msgnum = CAPIMSG_MSGID(skb->data);
233
234 if (!info && (msgnum == CMTP_INITIAL_MSGNUM)) {
235 session->ncontroller = controller;
236 wake_up_interruptible(&session->wait);
237 break;
238 }
239
240 if (!info && ctrl) {
241 memcpy(&ctrl->profile,
242 skb->data + CAPI_MSG_BASELEN + 11,
243 sizeof(capi_profile));
244 session->state = BT_CONNECTED;
245 ctrl->ready(ctrl);
246 }
247
248 break;
249
250 case CAPI_FUNCTION_GET_MANUFACTURER:
251 if (skb->len < CAPI_MSG_BASELEN + 15)
252 break;
253
254 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10);
255
256 if (!info && ctrl) {
257 int len = min_t(uint, CAPI_MANUFACTURER_LEN,
258 skb->data[CAPI_MSG_BASELEN + 14]);
259
260 memset(ctrl->manu, 0, CAPI_MANUFACTURER_LEN);
261 strncpy(ctrl->manu,
262 skb->data + CAPI_MSG_BASELEN + 15, len);
263 }
264
265 break;
266
267 case CAPI_FUNCTION_GET_VERSION:
268 if (skb->len < CAPI_MSG_BASELEN + 32)
269 break;
270
271 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
272
273 if (!info && ctrl) {
274 ctrl->version.majorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 16);
275 ctrl->version.minorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 20);
276 ctrl->version.majormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 24);
277 ctrl->version.minormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 28);
278 }
279
280 break;
281
282 case CAPI_FUNCTION_GET_SERIAL_NUMBER:
283 if (skb->len < CAPI_MSG_BASELEN + 17)
284 break;
285
286 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
287
288 if (!info && ctrl) {
289 int len = min_t(uint, CAPI_SERIAL_LEN,
290 skb->data[CAPI_MSG_BASELEN + 16]);
291
292 memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
293 strncpy(ctrl->serial,
294 skb->data + CAPI_MSG_BASELEN + 17, len);
295 }
296
297 break;
298 }
299
300 break;
301
302 case CAPI_IND:
303 if (skb->len < CAPI_MSG_BASELEN + 6)
304 break;
305
306 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
307
308 if (func == CAPI_FUNCTION_LOOPBACK) {
309 int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6,
310 skb->data[CAPI_MSG_BASELEN + 5]);
311 appl = CAPIMSG_APPID(skb->data);
312 msgnum = CAPIMSG_MSGID(skb->data);
313 cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
314 skb->data + CAPI_MSG_BASELEN + 6, len);
315 }
316
317 break;
318 }
319
320 kfree_skb(skb);
321 }
322
cmtp_recv_capimsg(struct cmtp_session * session,struct sk_buff * skb)323 void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
324 {
325 struct capi_ctr *ctrl = session->ctrl;
326 struct cmtp_application *application;
327 __u16 cmd, appl, info;
328 __u32 ncci, contr;
329
330 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
331
332 if (skb->len < CAPI_MSG_BASELEN)
333 return;
334
335 if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
336 cmtp_recv_interopmsg(session, skb);
337 return;
338 }
339
340 if (session->flags & (1 << CMTP_LOOPBACK)) {
341 kfree_skb(skb);
342 return;
343 }
344
345 cmd = CAPICMD(CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data));
346 appl = CAPIMSG_APPID(skb->data);
347 contr = CAPIMSG_CONTROL(skb->data);
348
349 application = cmtp_application_get(session, CMTP_MAPPING, appl);
350 if (application) {
351 appl = application->appl;
352 CAPIMSG_SETAPPID(skb->data, appl);
353 } else {
354 BT_ERR("Can't find application with id %d", appl);
355 kfree_skb(skb);
356 return;
357 }
358
359 if ((contr & 0x7f) == 0x01) {
360 contr = (contr & 0xffffff80) | session->num;
361 CAPIMSG_SETCONTROL(skb->data, contr);
362 }
363
364 if (!ctrl) {
365 BT_ERR("Can't find controller %d for message", session->num);
366 kfree_skb(skb);
367 return;
368 }
369
370 switch (cmd) {
371 case CAPI_CONNECT_B3_CONF:
372 ncci = CAPIMSG_NCCI(skb->data);
373 info = CAPIMSG_U16(skb->data, 12);
374
375 BT_DBG("CONNECT_B3_CONF ncci 0x%02x info 0x%02x", ncci, info);
376
377 if (info == 0)
378 ctrl->new_ncci(ctrl, appl, ncci, 8);
379
380 ctrl->handle_capimsg(ctrl, appl, skb);
381 break;
382
383 case CAPI_CONNECT_B3_IND:
384 ncci = CAPIMSG_NCCI(skb->data);
385
386 BT_DBG("CONNECT_B3_IND ncci 0x%02x", ncci);
387
388 ctrl->new_ncci(ctrl, appl, ncci, 8);
389 ctrl->handle_capimsg(ctrl, appl, skb);
390 break;
391
392 case CAPI_DISCONNECT_B3_IND:
393 ncci = CAPIMSG_NCCI(skb->data);
394
395 BT_DBG("DISCONNECT_B3_IND ncci 0x%02x", ncci);
396
397 if (ncci == 0xffffffff)
398 BT_ERR("DISCONNECT_B3_IND with ncci 0xffffffff");
399
400 ctrl->handle_capimsg(ctrl, appl, skb);
401 ctrl->free_ncci(ctrl, appl, ncci);
402 break;
403
404 default:
405 ctrl->handle_capimsg(ctrl, appl, skb);
406 break;
407 }
408 }
409
cmtp_send_capimsg(struct cmtp_session * session,struct sk_buff * skb)410 void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb)
411 {
412 struct cmtp_scb *scb = (void *) skb->cb;
413
414 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
415
416 scb->id = -1;
417 scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3);
418
419 skb_queue_tail(&session->transmit, skb);
420
421 cmtp_schedule(session);
422 }
423
424
cmtp_load_firmware(struct capi_ctr * ctrl,capiloaddata * data)425 static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
426 {
427 BT_DBG("ctrl %p data %p", ctrl, data);
428
429 return -EIO;
430 }
431
cmtp_reset_ctr(struct capi_ctr * ctrl)432 static void cmtp_reset_ctr(struct capi_ctr *ctrl)
433 {
434 BT_DBG("ctrl %p", ctrl);
435
436 ctrl->reseted(ctrl);
437 }
438
cmtp_remove_ctr(struct capi_ctr * ctrl)439 static void cmtp_remove_ctr(struct capi_ctr *ctrl)
440 {
441 struct cmtp_session *session = ctrl->driverdata;
442
443 BT_DBG("ctrl %p", ctrl);
444
445 ctrl->suspend_output(ctrl);
446
447 atomic_inc(&session->terminate);
448 cmtp_schedule(session);
449 }
450
cmtp_register_appl(struct capi_ctr * ctrl,__u16 appl,capi_register_params * rp)451 static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
452 {
453 DECLARE_WAITQUEUE(wait, current);
454 struct cmtp_session *session = ctrl->driverdata;
455 struct cmtp_application *application;
456 unsigned long timeo = CMTP_INTEROP_TIMEOUT;
457 unsigned char buf[8];
458 int err = 0, nconn, want = rp->level3cnt;
459
460 BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d",
461 ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
462
463 application = cmtp_application_add(session, appl);
464 if (!application) {
465 BT_ERR("Can't allocate memory for new application");
466 ctrl->appl_released(ctrl, appl);
467 return;
468 }
469
470 if (want < 0)
471 nconn = ctrl->profile.nbchannel * -want;
472 else
473 nconn = want;
474
475 if (nconn == 0)
476 nconn = ctrl->profile.nbchannel;
477
478 capimsg_setu16(buf, 0, nconn);
479 capimsg_setu16(buf, 2, rp->datablkcnt);
480 capimsg_setu16(buf, 4, rp->datablklen);
481
482 application->state = BT_CONFIG;
483 application->msgnum = cmtp_msgnum_get(session);
484
485 cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum,
486 CAPI_FUNCTION_REGISTER, buf, 6);
487
488 add_wait_queue(&session->wait, &wait);
489 while (1) {
490 set_current_state(TASK_INTERRUPTIBLE);
491
492 if (!timeo) {
493 err = -EAGAIN;
494 break;
495 }
496
497 if (application->state == BT_CLOSED) {
498 err = -application->err;
499 break;
500 }
501
502 if (application->state == BT_CONNECTED)
503 break;
504
505 if (signal_pending(current)) {
506 err = -EINTR;
507 break;
508 }
509
510 timeo = schedule_timeout(timeo);
511 }
512 set_current_state(TASK_RUNNING);
513 remove_wait_queue(&session->wait, &wait);
514
515 if (err) {
516 ctrl->appl_released(ctrl, appl);
517 cmtp_application_del(session, application);
518 return;
519 }
520
521 ctrl->appl_registered(ctrl, appl);
522 }
523
cmtp_release_appl(struct capi_ctr * ctrl,__u16 appl)524 static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl)
525 {
526 DECLARE_WAITQUEUE(wait, current);
527 struct cmtp_session *session = ctrl->driverdata;
528 struct cmtp_application *application;
529 unsigned long timeo = CMTP_INTEROP_TIMEOUT;
530
531 BT_DBG("ctrl %p appl %d", ctrl, appl);
532
533 application = cmtp_application_get(session, CMTP_APPLID, appl);
534 if (!application) {
535 BT_ERR("Can't find application");
536 return;
537 }
538
539 application->msgnum = cmtp_msgnum_get(session);
540
541 cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum,
542 CAPI_FUNCTION_RELEASE, NULL, 0);
543
544 add_wait_queue(&session->wait, &wait);
545 while (timeo) {
546 set_current_state(TASK_INTERRUPTIBLE);
547
548 if (application->state == BT_CLOSED)
549 break;
550
551 if (signal_pending(current))
552 break;
553
554 timeo = schedule_timeout(timeo);
555 }
556 set_current_state(TASK_RUNNING);
557 remove_wait_queue(&session->wait, &wait);
558
559 cmtp_application_del(session, application);
560 ctrl->appl_released(ctrl, appl);
561 }
562
cmtp_send_message(struct capi_ctr * ctrl,struct sk_buff * skb)563 static void cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
564 {
565 struct cmtp_session *session = ctrl->driverdata;
566 struct cmtp_application *application;
567 __u16 appl;
568 __u32 contr;
569
570 BT_DBG("ctrl %p skb %p", ctrl, skb);
571
572 appl = CAPIMSG_APPID(skb->data);
573 contr = CAPIMSG_CONTROL(skb->data);
574
575 application = cmtp_application_get(session, CMTP_APPLID, appl);
576 if ((!application) || (application->state != BT_CONNECTED)) {
577 BT_ERR("Can't find application with id %d", appl);
578 kfree_skb(skb);
579 return;
580 }
581
582 CAPIMSG_SETAPPID(skb->data, application->mapping);
583
584 if ((contr & 0x7f) == session->num) {
585 contr = (contr & 0xffffff80) | 0x01;
586 CAPIMSG_SETCONTROL(skb->data, contr);
587 }
588
589 cmtp_send_capimsg(session, skb);
590 }
591
cmtp_procinfo(struct capi_ctr * ctrl)592 static char *cmtp_procinfo(struct capi_ctr *ctrl)
593 {
594 return "CAPI Message Transport Protocol";
595 }
596
cmtp_ctr_read_proc(char * page,char ** start,off_t off,int count,int * eof,struct capi_ctr * ctrl)597 static int cmtp_ctr_read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl)
598 {
599 struct cmtp_session *session = ctrl->driverdata;
600 struct cmtp_application *app;
601 struct list_head *p, *n;
602 int len = 0;
603
604 len += sprintf(page + len, "%s (Revision %s)\n\n", cmtp_procinfo(ctrl), REVISION);
605 len += sprintf(page + len, "addr %s\n", session->name);
606 len += sprintf(page + len, "ctrl %d\n", session->num);
607
608 list_for_each_safe(p, n, &session->applications) {
609 app = list_entry(p, struct cmtp_application, list);
610 len += sprintf(page + len, "appl %d -> %d\n", app->appl, app->mapping);
611 }
612
613 if (off + count >= len)
614 *eof = 1;
615
616 if (len < off)
617 return 0;
618
619 *start = page + off;
620
621 return ((count < len - off) ? count : len - off);
622 }
623
624 static struct capi_driver cmtp_driver = {
625 name: "cmtp",
626 revision: REVISION,
627 load_firmware: cmtp_load_firmware,
628 reset_ctr: cmtp_reset_ctr,
629 remove_ctr: cmtp_remove_ctr,
630 register_appl: cmtp_register_appl,
631 release_appl: cmtp_release_appl,
632 send_message: cmtp_send_message,
633 procinfo: cmtp_procinfo,
634 ctr_read_proc: cmtp_ctr_read_proc,
635
636 driver_read_proc: 0,
637 add_card: 0,
638 };
639
640
cmtp_attach_device(struct cmtp_session * session)641 int cmtp_attach_device(struct cmtp_session *session)
642 {
643 DECLARE_WAITQUEUE(wait, current);
644 unsigned long timeo = CMTP_INTEROP_TIMEOUT;
645 unsigned char buf[4];
646
647 BT_DBG("session %p", session);
648
649 capimsg_setu32(buf, 0, 0);
650
651 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
652 CAPI_FUNCTION_GET_PROFILE, buf, 4);
653
654 add_wait_queue(&session->wait, &wait);
655 while (timeo) {
656 set_current_state(TASK_INTERRUPTIBLE);
657
658 if (session->ncontroller)
659 break;
660
661 if (signal_pending(current))
662 break;
663
664 timeo = schedule_timeout(timeo);
665 }
666 set_current_state(TASK_RUNNING);
667 remove_wait_queue(&session->wait, &wait);
668
669 BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
670
671 if (!timeo)
672 return -ETIMEDOUT;
673
674 if (!session->ncontroller)
675 return -ENODEV;
676
677
678 if (session->ncontroller > 1)
679 BT_INFO("Setting up only CAPI controller 1");
680
681 if (!(session->ctrl = di->attach_ctr(&cmtp_driver, session->name, session))) {
682 BT_ERR("Can't attach new controller");
683 return -EBUSY;
684 }
685
686 session->num = session->ctrl->cnr;
687
688 BT_DBG("session %p ctrl %p num %d", session, session->ctrl, session->num);
689
690 capimsg_setu32(buf, 0, 1);
691
692 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
693 CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
694
695 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
696 CAPI_FUNCTION_GET_VERSION, buf, 4);
697
698 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
699 CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
700
701 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
702 CAPI_FUNCTION_GET_PROFILE, buf, 4);
703
704 return 0;
705 }
706
cmtp_detach_device(struct cmtp_session * session)707 void cmtp_detach_device(struct cmtp_session *session)
708 {
709 struct capi_ctr *ctrl = session->ctrl;
710
711 BT_DBG("session %p ctrl %p", session, ctrl);
712
713 if (!ctrl)
714 return;
715
716 ctrl->reseted(ctrl);
717
718 di->detach_ctr(ctrl);
719 }
720
cmtp_init_capi(void)721 int cmtp_init_capi(void)
722 {
723 if (!(di = attach_capi_driver(&cmtp_driver))) {
724 BT_ERR("Can't attach CAPI driver");
725 return -EIO;
726 }
727
728 return 0;
729 }
730
cmtp_cleanup_capi(void)731 void cmtp_cleanup_capi(void)
732 {
733 detach_capi_driver(&cmtp_driver);
734 }
735