capi.c revision 25ea6db04a96d7871e7ece27d566f3228d59d932
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/module.h> 24 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> 32#include <linux/skbuff.h> 33#include <linux/socket.h> 34#include <linux/ioctl.h> 35#include <linux/file.h> 36#include <linux/wait.h> 37#include <net/sock.h> 38 39#include <linux/isdn/capilli.h> 40#include <linux/isdn/capicmd.h> 41#include <linux/isdn/capiutil.h> 42 43#include "cmtp.h" 44 45#ifndef CONFIG_BT_CMTP_DEBUG 46#undef BT_DBG 47#define BT_DBG(D...) 48#endif 49 50#define CAPI_INTEROPERABILITY 0x20 51 52#define CAPI_INTEROPERABILITY_REQ CAPICMD(CAPI_INTEROPERABILITY, CAPI_REQ) 53#define CAPI_INTEROPERABILITY_CONF CAPICMD(CAPI_INTEROPERABILITY, CAPI_CONF) 54#define CAPI_INTEROPERABILITY_IND CAPICMD(CAPI_INTEROPERABILITY, CAPI_IND) 55#define CAPI_INTEROPERABILITY_RESP CAPICMD(CAPI_INTEROPERABILITY, CAPI_RESP) 56 57#define CAPI_INTEROPERABILITY_REQ_LEN (CAPI_MSG_BASELEN + 2) 58#define CAPI_INTEROPERABILITY_CONF_LEN (CAPI_MSG_BASELEN + 4) 59#define CAPI_INTEROPERABILITY_IND_LEN (CAPI_MSG_BASELEN + 2) 60#define CAPI_INTEROPERABILITY_RESP_LEN (CAPI_MSG_BASELEN + 2) 61 62#define CAPI_FUNCTION_REGISTER 0 63#define CAPI_FUNCTION_RELEASE 1 64#define CAPI_FUNCTION_GET_PROFILE 2 65#define CAPI_FUNCTION_GET_MANUFACTURER 3 66#define CAPI_FUNCTION_GET_VERSION 4 67#define CAPI_FUNCTION_GET_SERIAL_NUMBER 5 68#define CAPI_FUNCTION_MANUFACTURER 6 69#define CAPI_FUNCTION_LOOPBACK 7 70 71 72#define CMTP_MSGNUM 1 73#define CMTP_APPLID 2 74#define CMTP_MAPPING 3 75 76static struct cmtp_application *cmtp_application_add(struct cmtp_session *session, __u16 appl) 77{ 78 struct cmtp_application *app = kzalloc(sizeof(*app), GFP_KERNEL); 79 80 BT_DBG("session %p application %p appl %d", session, app, appl); 81 82 if (!app) 83 return NULL; 84 85 app->state = BT_OPEN; 86 app->appl = appl; 87 88 list_add_tail(&app->list, &session->applications); 89 90 return app; 91} 92 93static void cmtp_application_del(struct cmtp_session *session, struct cmtp_application *app) 94{ 95 BT_DBG("session %p application %p", session, app); 96 97 if (app) { 98 list_del(&app->list); 99 kfree(app); 100 } 101} 102 103static struct cmtp_application *cmtp_application_get(struct cmtp_session *session, int pattern, __u16 value) 104{ 105 struct cmtp_application *app; 106 struct list_head *p, *n; 107 108 list_for_each_safe(p, n, &session->applications) { 109 app = list_entry(p, struct cmtp_application, list); 110 switch (pattern) { 111 case CMTP_MSGNUM: 112 if (app->msgnum == value) 113 return app; 114 break; 115 case CMTP_APPLID: 116 if (app->appl == value) 117 return app; 118 break; 119 case CMTP_MAPPING: 120 if (app->mapping == value) 121 return app; 122 break; 123 } 124 } 125 126 return NULL; 127} 128 129static int cmtp_msgnum_get(struct cmtp_session *session) 130{ 131 session->msgnum++; 132 133 if ((session->msgnum & 0xff) > 200) 134 session->msgnum = CMTP_INITIAL_MSGNUM + 1; 135 136 return session->msgnum; 137} 138 139static void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb) 140{ 141 struct cmtp_scb *scb = (void *) skb->cb; 142 143 BT_DBG("session %p skb %p len %d", session, skb, skb->len); 144 145 scb->id = -1; 146 scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3); 147 148 skb_queue_tail(&session->transmit, skb); 149 150 cmtp_schedule(session); 151} 152 153static void cmtp_send_interopmsg(struct cmtp_session *session, 154 __u8 subcmd, __u16 appl, __u16 msgnum, 155 __u16 function, unsigned char *buf, int len) 156{ 157 struct sk_buff *skb; 158 unsigned char *s; 159 160 BT_DBG("session %p subcmd 0x%02x appl %d msgnum %d", session, subcmd, appl, msgnum); 161 162 if (!(skb = alloc_skb(CAPI_MSG_BASELEN + 6 + len, GFP_ATOMIC))) { 163 BT_ERR("Can't allocate memory for interoperability packet"); 164 return; 165 } 166 167 s = skb_put(skb, CAPI_MSG_BASELEN + 6 + len); 168 169 capimsg_setu16(s, 0, CAPI_MSG_BASELEN + 6 + len); 170 capimsg_setu16(s, 2, appl); 171 capimsg_setu8 (s, 4, CAPI_INTEROPERABILITY); 172 capimsg_setu8 (s, 5, subcmd); 173 capimsg_setu16(s, 6, msgnum); 174 175 /* Interoperability selector (Bluetooth Device Management) */ 176 capimsg_setu16(s, 8, 0x0001); 177 178 capimsg_setu8 (s, 10, 3 + len); 179 capimsg_setu16(s, 11, function); 180 capimsg_setu8 (s, 13, len); 181 182 if (len > 0) 183 memcpy(s + 14, buf, len); 184 185 cmtp_send_capimsg(session, skb); 186} 187 188static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *skb) 189{ 190 struct capi_ctr *ctrl = &session->ctrl; 191 struct cmtp_application *application; 192 __u16 appl, msgnum, func, info; 193 __u32 controller; 194 195 BT_DBG("session %p skb %p len %d", session, skb, skb->len); 196 197 switch (CAPIMSG_SUBCOMMAND(skb->data)) { 198 case CAPI_CONF: 199 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5); 200 info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8); 201 202 switch (func) { 203 case CAPI_FUNCTION_REGISTER: 204 msgnum = CAPIMSG_MSGID(skb->data); 205 206 application = cmtp_application_get(session, CMTP_MSGNUM, msgnum); 207 if (application) { 208 application->state = BT_CONNECTED; 209 application->msgnum = 0; 210 application->mapping = CAPIMSG_APPID(skb->data); 211 wake_up_interruptible(&session->wait); 212 } 213 214 break; 215 216 case CAPI_FUNCTION_RELEASE: 217 appl = CAPIMSG_APPID(skb->data); 218 219 application = cmtp_application_get(session, CMTP_MAPPING, appl); 220 if (application) { 221 application->state = BT_CLOSED; 222 application->msgnum = 0; 223 wake_up_interruptible(&session->wait); 224 } 225 226 break; 227 228 case CAPI_FUNCTION_GET_PROFILE: 229 controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11); 230 msgnum = CAPIMSG_MSGID(skb->data); 231 232 if (!info && (msgnum == CMTP_INITIAL_MSGNUM)) { 233 session->ncontroller = controller; 234 wake_up_interruptible(&session->wait); 235 break; 236 } 237 238 if (!info && ctrl) { 239 memcpy(&ctrl->profile, 240 skb->data + CAPI_MSG_BASELEN + 11, 241 sizeof(capi_profile)); 242 session->state = BT_CONNECTED; 243 capi_ctr_ready(ctrl); 244 } 245 246 break; 247 248 case CAPI_FUNCTION_GET_MANUFACTURER: 249 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10); 250 251 if (!info && ctrl) { 252 strncpy(ctrl->manu, 253 skb->data + CAPI_MSG_BASELEN + 15, 254 skb->data[CAPI_MSG_BASELEN + 14]); 255 } 256 257 break; 258 259 case CAPI_FUNCTION_GET_VERSION: 260 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12); 261 262 if (!info && ctrl) { 263 ctrl->version.majorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 16); 264 ctrl->version.minorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 20); 265 ctrl->version.majormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 24); 266 ctrl->version.minormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 28); 267 } 268 269 break; 270 271 case CAPI_FUNCTION_GET_SERIAL_NUMBER: 272 controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12); 273 274 if (!info && ctrl) { 275 memset(ctrl->serial, 0, CAPI_SERIAL_LEN); 276 strncpy(ctrl->serial, 277 skb->data + CAPI_MSG_BASELEN + 17, 278 skb->data[CAPI_MSG_BASELEN + 16]); 279 } 280 281 break; 282 } 283 284 break; 285 286 case CAPI_IND: 287 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3); 288 289 if (func == CAPI_FUNCTION_LOOPBACK) { 290 appl = CAPIMSG_APPID(skb->data); 291 msgnum = CAPIMSG_MSGID(skb->data); 292 cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func, 293 skb->data + CAPI_MSG_BASELEN + 6, 294 skb->data[CAPI_MSG_BASELEN + 5]); 295 } 296 297 break; 298 } 299 300 kfree_skb(skb); 301} 302 303void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb) 304{ 305 struct capi_ctr *ctrl = &session->ctrl; 306 struct cmtp_application *application; 307 __u16 cmd, appl; 308 __u32 contr; 309 310 BT_DBG("session %p skb %p len %d", session, skb, skb->len); 311 312 if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) { 313 cmtp_recv_interopmsg(session, skb); 314 return; 315 } 316 317 if (session->flags & (1 << CMTP_LOOPBACK)) { 318 kfree_skb(skb); 319 return; 320 } 321 322 cmd = CAPICMD(CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data)); 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 %d", 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 if (!ctrl) { 342 BT_ERR("Can't find controller %d for message", session->num); 343 kfree_skb(skb); 344 return; 345 } 346 347 capi_ctr_handle_message(ctrl, appl, skb); 348} 349 350static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) 351{ 352 BT_DBG("ctrl %p data %p", ctrl, data); 353 354 return 0; 355} 356 357static void cmtp_reset_ctr(struct capi_ctr *ctrl) 358{ 359 struct cmtp_session *session = ctrl->driverdata; 360 361 BT_DBG("ctrl %p", ctrl); 362 363 capi_ctr_reseted(ctrl); 364 365 atomic_inc(&session->terminate); 366 cmtp_schedule(session); 367} 368 369static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp) 370{ 371 DECLARE_WAITQUEUE(wait, current); 372 struct cmtp_session *session = ctrl->driverdata; 373 struct cmtp_application *application; 374 unsigned long timeo = CMTP_INTEROP_TIMEOUT; 375 unsigned char buf[8]; 376 int err = 0, nconn, want = rp->level3cnt; 377 378 BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d", 379 ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen); 380 381 application = cmtp_application_add(session, appl); 382 if (!application) { 383 BT_ERR("Can't allocate memory for new application"); 384 return; 385 } 386 387 if (want < 0) 388 nconn = ctrl->profile.nbchannel * -want; 389 else 390 nconn = want; 391 392 if (nconn == 0) 393 nconn = ctrl->profile.nbchannel; 394 395 capimsg_setu16(buf, 0, nconn); 396 capimsg_setu16(buf, 2, rp->datablkcnt); 397 capimsg_setu16(buf, 4, rp->datablklen); 398 399 application->state = BT_CONFIG; 400 application->msgnum = cmtp_msgnum_get(session); 401 402 cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum, 403 CAPI_FUNCTION_REGISTER, buf, 6); 404 405 add_wait_queue(&session->wait, &wait); 406 while (1) { 407 set_current_state(TASK_INTERRUPTIBLE); 408 409 if (!timeo) { 410 err = -EAGAIN; 411 break; 412 } 413 414 if (application->state == BT_CLOSED) { 415 err = -application->err; 416 break; 417 } 418 419 if (application->state == BT_CONNECTED) 420 break; 421 422 if (signal_pending(current)) { 423 err = -EINTR; 424 break; 425 } 426 427 timeo = schedule_timeout(timeo); 428 } 429 set_current_state(TASK_RUNNING); 430 remove_wait_queue(&session->wait, &wait); 431 432 if (err) { 433 cmtp_application_del(session, application); 434 return; 435 } 436} 437 438static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl) 439{ 440 struct cmtp_session *session = ctrl->driverdata; 441 struct cmtp_application *application; 442 443 BT_DBG("ctrl %p appl %d", ctrl, appl); 444 445 application = cmtp_application_get(session, CMTP_APPLID, appl); 446 if (!application) { 447 BT_ERR("Can't find application"); 448 return; 449 } 450 451 application->msgnum = cmtp_msgnum_get(session); 452 453 cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum, 454 CAPI_FUNCTION_RELEASE, NULL, 0); 455 456 wait_event_interruptible_timeout(session->wait, 457 (application->state == BT_CLOSED), CMTP_INTEROP_TIMEOUT); 458 459 cmtp_application_del(session, application); 460} 461 462static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) 463{ 464 struct cmtp_session *session = ctrl->driverdata; 465 struct cmtp_application *application; 466 __u16 appl; 467 __u32 contr; 468 469 BT_DBG("ctrl %p skb %p", ctrl, skb); 470 471 appl = CAPIMSG_APPID(skb->data); 472 contr = CAPIMSG_CONTROL(skb->data); 473 474 application = cmtp_application_get(session, CMTP_APPLID, appl); 475 if ((!application) || (application->state != BT_CONNECTED)) { 476 BT_ERR("Can't find application with id %d", appl); 477 return CAPI_ILLAPPNR; 478 } 479 480 CAPIMSG_SETAPPID(skb->data, application->mapping); 481 482 if ((contr & 0x7f) == session->num) { 483 contr = (contr & 0xffffff80) | 0x01; 484 CAPIMSG_SETCONTROL(skb->data, contr); 485 } 486 487 cmtp_send_capimsg(session, skb); 488 489 return CAPI_NOERROR; 490} 491 492static char *cmtp_procinfo(struct capi_ctr *ctrl) 493{ 494 return "CAPI Message Transport Protocol"; 495} 496 497static int cmtp_ctr_read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl) 498{ 499 struct cmtp_session *session = ctrl->driverdata; 500 struct cmtp_application *app; 501 struct list_head *p, *n; 502 int len = 0; 503 504 len += sprintf(page + len, "%s\n\n", cmtp_procinfo(ctrl)); 505 len += sprintf(page + len, "addr %s\n", session->name); 506 len += sprintf(page + len, "ctrl %d\n", session->num); 507 508 list_for_each_safe(p, n, &session->applications) { 509 app = list_entry(p, struct cmtp_application, list); 510 len += sprintf(page + len, "appl %d -> %d\n", app->appl, app->mapping); 511 } 512 513 if (off + count >= len) 514 *eof = 1; 515 516 if (len < off) 517 return 0; 518 519 *start = page + off; 520 521 return ((count < len - off) ? count : len - off); 522} 523 524 525int cmtp_attach_device(struct cmtp_session *session) 526{ 527 unsigned char buf[4]; 528 long ret; 529 530 BT_DBG("session %p", session); 531 532 capimsg_setu32(buf, 0, 0); 533 534 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM, 535 CAPI_FUNCTION_GET_PROFILE, buf, 4); 536 537 ret = wait_event_interruptible_timeout(session->wait, 538 session->ncontroller, CMTP_INTEROP_TIMEOUT); 539 540 BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name); 541 542 if (!ret) 543 return -ETIMEDOUT; 544 545 if (!session->ncontroller) 546 return -ENODEV; 547 548 if (session->ncontroller > 1) 549 BT_INFO("Setting up only CAPI controller 1"); 550 551 session->ctrl.owner = THIS_MODULE; 552 session->ctrl.driverdata = session; 553 strcpy(session->ctrl.name, session->name); 554 555 session->ctrl.driver_name = "cmtp"; 556 session->ctrl.load_firmware = cmtp_load_firmware; 557 session->ctrl.reset_ctr = cmtp_reset_ctr; 558 session->ctrl.register_appl = cmtp_register_appl; 559 session->ctrl.release_appl = cmtp_release_appl; 560 session->ctrl.send_message = cmtp_send_message; 561 562 session->ctrl.procinfo = cmtp_procinfo; 563 session->ctrl.ctr_read_proc = cmtp_ctr_read_proc; 564 565 if (attach_capi_ctr(&session->ctrl) < 0) { 566 BT_ERR("Can't attach new controller"); 567 return -EBUSY; 568 } 569 570 session->num = session->ctrl.cnr; 571 572 BT_DBG("session %p num %d", session, session->num); 573 574 capimsg_setu32(buf, 0, 1); 575 576 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session), 577 CAPI_FUNCTION_GET_MANUFACTURER, buf, 4); 578 579 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session), 580 CAPI_FUNCTION_GET_VERSION, buf, 4); 581 582 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session), 583 CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4); 584 585 cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session), 586 CAPI_FUNCTION_GET_PROFILE, buf, 4); 587 588 return 0; 589} 590 591void cmtp_detach_device(struct cmtp_session *session) 592{ 593 BT_DBG("session %p", session); 594 595 detach_capi_ctr(&session->ctrl); 596} 597