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/export.h> 24 #include <linux/proc_fs.h> 25 #include <linux/seq_file.h> 26 #include <linux/types.h> 27 #include <linux/errno.h> 28 #include <linux/kernel.h> 29 #include <linux/sched/signal.h> 30 #include <linux/slab.h> 31 #include <linux/poll.h> 32 #include <linux/fcntl.h> 33 #include <linux/skbuff.h> 34 #include <linux/socket.h> 35 #include <linux/ioctl.h> 36 #include <linux/file.h> 37 #include <linux/wait.h> 38 #include <linux/kthread.h> 39 #include <net/sock.h> 40 41 #include <linux/isdn/capilli.h> 42 #include <linux/isdn/capicmd.h> 43 #include <linux/isdn/capiutil.h> 44 45 #include "cmtp.h" 46 47 #define CAPI_INTEROPERABILITY 0x20 48 49 #define CAPI_INTEROPERABILITY_REQ CAPICMD(CAPI_INTEROPERABILITY, CAPI_REQ) 50 #define CAPI_INTEROPERABILITY_CONF CAPICMD(CAPI_INTEROPERABILITY, CAPI_CONF) 51 #define CAPI_INTEROPERABILITY_IND CAPICMD(CAPI_INTEROPERABILITY, CAPI_IND) 52 #define CAPI_INTEROPERABILITY_RESP CAPICMD(CAPI_INTEROPERABILITY, CAPI_RESP) 53 54 #define CAPI_INTEROPERABILITY_REQ_LEN (CAPI_MSG_BASELEN + 2) 55 #define CAPI_INTEROPERABILITY_CONF_LEN (CAPI_MSG_BASELEN + 4) 56 #define CAPI_INTEROPERABILITY_IND_LEN (CAPI_MSG_BASELEN + 2) 57 #define CAPI_INTEROPERABILITY_RESP_LEN (CAPI_MSG_BASELEN + 2) 58 59 #define CAPI_FUNCTION_REGISTER 0 60 #define CAPI_FUNCTION_RELEASE 1 61 #define CAPI_FUNCTION_GET_PROFILE 2 62 #define CAPI_FUNCTION_GET_MANUFACTURER 3 63 #define CAPI_FUNCTION_GET_VERSION 4 64 #define CAPI_FUNCTION_GET_SERIAL_NUMBER 5 65 #define CAPI_FUNCTION_MANUFACTURER 6 66 #define CAPI_FUNCTION_LOOPBACK 7 67 68 69 #define CMTP_MSGNUM 1 70 #define CMTP_APPLID 2 71 #define CMTP_MAPPING 3 72 73 static struct cmtp_application *cmtp_application_add(struct cmtp_session *session, __u16 appl) 74 { 75 struct cmtp_application *app = kzalloc(sizeof(*app), GFP_KERNEL); 76 77 BT_DBG("session %p application %p appl %u", session, app, appl); 78 79 if (!app) 80 return NULL; 81 82 app->state = BT_OPEN; 83 app->appl = appl; 84 85 list_add_tail(&app->list, &session->applications); 86 87 return app; 88 } 89 90 static void cmtp_application_del(struct cmtp_session *session, struct cmtp_application *app) 91 { 92 BT_DBG("session %p application %p", session, app); 93 94 if (app) { 95 list_del(&app->list); 96 kfree(app); 97 } 98 } 99 100 static struct cmtp_application *cmtp_application_get(struct cmtp_session *session, int pattern, __u16 value) 101 { 102 struct cmtp_application *app; 103 104 list_for_each_entry(app, &session->applications, list) { 105 switch (pattern) { 106 case CMTP_MSGNUM: 107 if (app->msgnum == value) 108 return app; 109 break; 110 case CMTP_APPLID: 111 if (app->appl == value) 112 return app; 113 break; 114 case CMTP_MAPPING: 115 if (app->mapping == value) 116 return app; 117 break; 118 } 119 } 120 121 return NULL; 122 } 123 124 static int cmtp_msgnum_get(struct cmtp_session *session) 125 { 126 session->msgnum++; 127 128 if ((session->msgnum & 0xff) > 200) 129 session->msgnum = CMTP_INITIAL_MSGNUM + 1; 130 131 return session->msgnum; 132 } 133 134 static void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb) 135 { 136 struct cmtp_scb *scb = (void *) skb->cb; 137 138 BT_DBG("session %p skb %p len %u", session, skb, skb->len); 139 140 scb->id = -1; 141 scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3); 142 143 skb_queue_tail(&session->transmit, skb); 144 145 wake_up_interruptible(sk_sleep(session->sock->sk)); 146 } 147 148 static void cmtp_send_interopmsg(struct cmtp_session *session, 149 __u8 subcmd, __u16 appl, __u16 msgnum, 150 __u16 function, unsigned char *buf, int len) 151 { 152 struct sk_buff *skb; 153 unsigned char *s; 154 155 BT_DBG("session %p subcmd 0x%02x appl %u msgnum %u", session, subcmd, appl, msgnum); 156 157 skb = alloc_skb(CAPI_MSG_BASELEN + 6 + len, GFP_ATOMIC); 158 if (!skb) { 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 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 %u", 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 capi_ctr_ready(ctrl); 246 } 247 248 break; 249 250 case CAPI_FUNCTION_GET_MANUFACTURER: 251 if (!info && ctrl && skb->len > CAPI_MSG_BASELEN + 14) 252 strscpy_pad(ctrl->manu, 253 skb->data + CAPI_MSG_BASELEN + 15, 254 skb->data[CAPI_MSG_BASELEN + 14]); 255 break; 256 257 case CAPI_FUNCTION_GET_VERSION: 258 if (skb->len < CAPI_MSG_BASELEN + 32) 259 break; 260 261 if (!info && ctrl) { 262 ctrl->version.majorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 16); 263 ctrl->version.minorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 20); 264 ctrl->version.majormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 24); 265 ctrl->version.minormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 28); 266 } 267 268 break; 269 270 case CAPI_FUNCTION_GET_SERIAL_NUMBER: 271 if (!info && ctrl && skb->len > CAPI_MSG_BASELEN + 16) 272 strscpy_pad(ctrl->serial, 273 skb->data + CAPI_MSG_BASELEN + 17, 274 skb->data[CAPI_MSG_BASELEN + 16]); 275 break; 276 } 277 278 break; 279 280 case CAPI_IND: 281 if (skb->len < CAPI_MSG_BASELEN + 6) 282 break; 283 284 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3); 285 286 if (func == CAPI_FUNCTION_LOOPBACK) { 287 int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6, 288 skb->data[CAPI_MSG_BASELEN + 5]); 289 appl = CAPIMSG_APPID(skb->data); 290 msgnum = CAPIMSG_MSGID(skb->data); 291 cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func, 292 skb->data + CAPI_MSG_BASELEN + 6, len); 293 } 294 295 break; 296 } 297 298 kfree_skb(skb); 299 } 300 301 void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb) 302 { 303 struct capi_ctr *ctrl = &session->ctrl; 304 struct cmtp_application *application; 305 __u16 appl; 306 __u32 contr; 307 308 BT_DBG("session %p skb %p len %u", session, skb, skb->len); 309 310 if (skb->len < CAPI_MSG_BASELEN) 311 return; 312 313 if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) { 314 cmtp_recv_interopmsg(session, skb); 315 return; 316 } 317 318 if (session->flags & BIT(CMTP_LOOPBACK)) { 319 kfree_skb(skb); 320 return; 321 } 322 323 appl = CAPIMSG_APPID(skb->data); 324 contr = CAPIMSG_CONTROL(skb->data); 325 326 application = cmtp_application_get(session, CMTP_MAPPING, appl); 327 if (application) { 328 appl = application->appl; 329 CAPIMSG_SETAPPID(skb->data, appl); 330 } else { 331 BT_ERR("Can't find application with id %u", appl); 332 kfree_skb(skb); 333 return; 334 } 335 336 if ((contr & 0x7f) == 0x01) { 337 contr = (contr & 0xffffff80) | session->num; 338 CAPIMSG_SETCONTROL(skb->data, contr); 339 } 340 341 capi_ctr_handle_message(ctrl, appl, skb); 342 } 343 344 static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) 345 { 346 BT_DBG("ctrl %p data %p", ctrl, data); 347 348 return 0; 349 } 350 351 static void cmtp_reset_ctr(struct capi_ctr *ctrl) 352 { 353 struct cmtp_session *session = ctrl->driverdata; 354 355 BT_DBG("ctrl %p", ctrl); 356 357 capi_ctr_down(ctrl); 358 359 atomic_inc(&session->terminate); 360 wake_up_process(session->task); 361 } 362 363 static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp) 364 { 365 DECLARE_WAITQUEUE(wait, current); 366 struct cmtp_session *session = ctrl->driverdata; 367 struct cmtp_application *application; 368 unsigned long timeo = CMTP_INTEROP_TIMEOUT; 369 unsigned char buf[8]; 370 int err = 0, nconn, want = rp->level3cnt; 371 372 BT_DBG("ctrl %p appl %u level3cnt %u datablkcnt %u datablklen %u", 373 ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen); 374 375 application = cmtp_application_add(session, appl); 376 if (!application) { 377 BT_ERR("Can't allocate memory for new application"); 378 return; 379 } 380 381 if (want < 0) 382 nconn = ctrl->profile.nbchannel * -want; 383 else 384 nconn = want; 385 386 if (nconn == 0) 387 nconn = ctrl->profile.nbchannel; 388 389 capimsg_setu16(buf, 0, nconn); 390 capimsg_setu16(buf, 2, rp->datablkcnt); 391 capimsg_setu16(buf, 4, rp->datablklen); 392 393 application->state = BT_CONFIG; 394 application->msgnum = cmtp_msgnum_get(session); 395 396 cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum, 397 CAPI_FUNCTION_REGISTER, buf, 6); 398 399 add_wait_queue(&session->wait, &wait); 400 while (1) { 401 set_current_state(TASK_INTERRUPTIBLE); 402 403 if (!timeo) { 404 err = -EAGAIN; 405 break; 406 } 407 408 if (application->state == BT_CLOSED) { 409 err = -application->err; 410 break; 411 } 412 413 if (application->state == BT_CONNECTED) 414 break; 415 416 if (signal_pending(current)) { 417 err = -EINTR; 418 break; 419 } 420 421 timeo = schedule_timeout(timeo); 422 } 423 set_current_state(TASK_RUNNING); 424 remove_wait_queue(&session->wait, &wait); 425 426 if (err) { 427 cmtp_application_del(session, application); 428 return; 429 } 430 } 431 432 static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl) 433 { 434 struct cmtp_session *session = ctrl->driverdata; 435 struct cmtp_application *application; 436 437 BT_DBG("ctrl %p appl %u", ctrl, appl); 438 439 application = cmtp_application_get(session, CMTP_APPLID, appl); 440 if (!application) { 441 BT_ERR("Can't find application"); 442 return; 443 } 444 445 application->msgnum = cmtp_msgnum_get(session); 446 447 cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum, 448 CAPI_FUNCTION_RELEASE, NULL, 0); 449 450 wait_event_interruptible_timeout(session->wait, 451 (application->state == BT_CLOSED), CMTP_INTEROP_TIMEOUT); 452 453 cmtp_application_del(session, application); 454 } 455 456 static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) 457 { 458 struct cmtp_session *session = ctrl->driverdata; 459 struct cmtp_application *application; 460 __u16 appl; 461 __u32 contr; 462 463 BT_DBG("ctrl %p skb %p", ctrl, skb); 464 465 appl = CAPIMSG_APPID(skb->data); 466 contr = CAPIMSG_CONTROL(skb->data); 467 468 application = cmtp_application_get(session, CMTP_APPLID, appl); 469 if ((!application) || (application->state != BT_CONNECTED)) { 470 BT_ERR("Can't find application with id %u", appl); 471 return CAPI_ILLAPPNR; 472 } 473 474 CAPIMSG_SETAPPID(skb->data, application->mapping); 475 476 if ((contr & 0x7f) == session->num) { 477 contr = (contr & 0xffffff80) | 0x01; 478 CAPIMSG_SETCONTROL(skb->data, contr); 479 } 480 481 cmtp_send_capimsg(session, skb); 482 483 return CAPI_NOERROR; 484 } 485 486 static char *cmtp_procinfo(struct capi_ctr *ctrl) 487 { 488 return "CAPI Message Transport Protocol"; 489 } 490 491 static int cmtp_proc_show(struct seq_file *m, void *v) 492 { 493 struct capi_ctr *ctrl = m->private; 494 struct cmtp_session *session = ctrl->driverdata; 495 struct cmtp_application *app; 496 497 seq_printf(m, "%s\n\n", cmtp_procinfo(ctrl)); 498 seq_printf(m, "addr %s\n", session->name); 499 seq_printf(m, "ctrl %d\n", session->num); 500 501 list_for_each_entry(app, &session->applications, list) { 502 seq_printf(m, "appl %u -> %u\n", app->appl, app->mapping); 503 } 504 505 return 0; 506 } 507 508 int cmtp_attach_device(struct cmtp_session *session) 509 { 510 unsigned char buf[4]; 511 long ret; 512 513 BT_DBG("session %p", session); 514 515 capimsg_setu32(buf, 0, 0); 516 517 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM, 518 CAPI_FUNCTION_GET_PROFILE, buf, 4); 519 520 ret = wait_event_interruptible_timeout(session->wait, 521 session->ncontroller, CMTP_INTEROP_TIMEOUT); 522 523 BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name); 524 525 if (!ret) 526 return -ETIMEDOUT; 527 528 if (!session->ncontroller) 529 return -ENODEV; 530 531 if (session->ncontroller > 1) 532 BT_INFO("Setting up only CAPI controller 1"); 533 534 session->ctrl.owner = THIS_MODULE; 535 session->ctrl.driverdata = session; 536 strcpy(session->ctrl.name, session->name); 537 538 session->ctrl.driver_name = "cmtp"; 539 session->ctrl.load_firmware = cmtp_load_firmware; 540 session->ctrl.reset_ctr = cmtp_reset_ctr; 541 session->ctrl.register_appl = cmtp_register_appl; 542 session->ctrl.release_appl = cmtp_release_appl; 543 session->ctrl.send_message = cmtp_send_message; 544 545 session->ctrl.procinfo = cmtp_procinfo; 546 session->ctrl.proc_show = cmtp_proc_show; 547 548 if (attach_capi_ctr(&session->ctrl) < 0) { 549 BT_ERR("Can't attach new controller"); 550 return -EBUSY; 551 } 552 553 session->num = session->ctrl.cnr; 554 555 BT_DBG("session %p num %d", session, session->num); 556 557 capimsg_setu32(buf, 0, 1); 558 559 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session), 560 CAPI_FUNCTION_GET_MANUFACTURER, buf, 4); 561 562 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session), 563 CAPI_FUNCTION_GET_VERSION, buf, 4); 564 565 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session), 566 CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4); 567 568 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session), 569 CAPI_FUNCTION_GET_PROFILE, buf, 4); 570 571 return 0; 572 } 573 574 void cmtp_detach_device(struct cmtp_session *session) 575 { 576 BT_DBG("session %p", session); 577 578 detach_capi_ctr(&session->ctrl); 579 } 580