This source file includes following definitions.
- cmtp_application_add
- cmtp_application_del
- cmtp_application_get
- cmtp_msgnum_get
- cmtp_send_capimsg
- cmtp_send_interopmsg
- cmtp_recv_interopmsg
- cmtp_recv_capimsg
- cmtp_load_firmware
- cmtp_reset_ctr
- cmtp_register_appl
- cmtp_release_appl
- cmtp_send_message
- cmtp_procinfo
- cmtp_proc_show
- cmtp_attach_device
- cmtp_detach_device
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  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 %d", 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 %d", 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 %d msgnum %d", 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         
 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 %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                                 capi_ctr_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                         if (!info && ctrl) {
 255                                 int len = min_t(uint, CAPI_MANUFACTURER_LEN,
 256                                                 skb->data[CAPI_MSG_BASELEN + 14]);
 257 
 258                                 memset(ctrl->manu, 0, CAPI_MANUFACTURER_LEN);
 259                                 strncpy(ctrl->manu,
 260                                         skb->data + CAPI_MSG_BASELEN + 15, len);
 261                         }
 262 
 263                         break;
 264 
 265                 case CAPI_FUNCTION_GET_VERSION:
 266                         if (skb->len < CAPI_MSG_BASELEN + 32)
 267                                 break;
 268 
 269                         if (!info && ctrl) {
 270                                 ctrl->version.majorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 16);
 271                                 ctrl->version.minorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 20);
 272                                 ctrl->version.majormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 24);
 273                                 ctrl->version.minormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 28);
 274                         }
 275 
 276                         break;
 277 
 278                 case CAPI_FUNCTION_GET_SERIAL_NUMBER:
 279                         if (skb->len < CAPI_MSG_BASELEN + 17)
 280                                 break;
 281 
 282                         if (!info && ctrl) {
 283                                 int len = min_t(uint, CAPI_SERIAL_LEN,
 284                                                 skb->data[CAPI_MSG_BASELEN + 16]);
 285 
 286                                 memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
 287                                 strncpy(ctrl->serial,
 288                                         skb->data + CAPI_MSG_BASELEN + 17, len);
 289                         }
 290 
 291                         break;
 292                 }
 293 
 294                 break;
 295 
 296         case CAPI_IND:
 297                 if (skb->len < CAPI_MSG_BASELEN + 6)
 298                         break;
 299 
 300                 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
 301 
 302                 if (func == CAPI_FUNCTION_LOOPBACK) {
 303                         int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6,
 304                                                 skb->data[CAPI_MSG_BASELEN + 5]);
 305                         appl = CAPIMSG_APPID(skb->data);
 306                         msgnum = CAPIMSG_MSGID(skb->data);
 307                         cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
 308                                                 skb->data + CAPI_MSG_BASELEN + 6, len);
 309                 }
 310 
 311                 break;
 312         }
 313 
 314         kfree_skb(skb);
 315 }
 316 
 317 void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
 318 {
 319         struct capi_ctr *ctrl = &session->ctrl;
 320         struct cmtp_application *application;
 321         __u16 appl;
 322         __u32 contr;
 323 
 324         BT_DBG("session %p skb %p len %d", session, skb, skb->len);
 325 
 326         if (skb->len < CAPI_MSG_BASELEN)
 327                 return;
 328 
 329         if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
 330                 cmtp_recv_interopmsg(session, skb);
 331                 return;
 332         }
 333 
 334         if (session->flags & BIT(CMTP_LOOPBACK)) {
 335                 kfree_skb(skb);
 336                 return;
 337         }
 338 
 339         appl = CAPIMSG_APPID(skb->data);
 340         contr = CAPIMSG_CONTROL(skb->data);
 341 
 342         application = cmtp_application_get(session, CMTP_MAPPING, appl);
 343         if (application) {
 344                 appl = application->appl;
 345                 CAPIMSG_SETAPPID(skb->data, appl);
 346         } else {
 347                 BT_ERR("Can't find application with id %d", appl);
 348                 kfree_skb(skb);
 349                 return;
 350         }
 351 
 352         if ((contr & 0x7f) == 0x01) {
 353                 contr = (contr & 0xffffff80) | session->num;
 354                 CAPIMSG_SETCONTROL(skb->data, contr);
 355         }
 356 
 357         capi_ctr_handle_message(ctrl, appl, skb);
 358 }
 359 
 360 static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
 361 {
 362         BT_DBG("ctrl %p data %p", ctrl, data);
 363 
 364         return 0;
 365 }
 366 
 367 static void cmtp_reset_ctr(struct capi_ctr *ctrl)
 368 {
 369         struct cmtp_session *session = ctrl->driverdata;
 370 
 371         BT_DBG("ctrl %p", ctrl);
 372 
 373         capi_ctr_down(ctrl);
 374 
 375         atomic_inc(&session->terminate);
 376         wake_up_process(session->task);
 377 }
 378 
 379 static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
 380 {
 381         DECLARE_WAITQUEUE(wait, current);
 382         struct cmtp_session *session = ctrl->driverdata;
 383         struct cmtp_application *application;
 384         unsigned long timeo = CMTP_INTEROP_TIMEOUT;
 385         unsigned char buf[8];
 386         int err = 0, nconn, want = rp->level3cnt;
 387 
 388         BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d",
 389                 ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
 390 
 391         application = cmtp_application_add(session, appl);
 392         if (!application) {
 393                 BT_ERR("Can't allocate memory for new application");
 394                 return;
 395         }
 396 
 397         if (want < 0)
 398                 nconn = ctrl->profile.nbchannel * -want;
 399         else
 400                 nconn = want;
 401 
 402         if (nconn == 0)
 403                 nconn = ctrl->profile.nbchannel;
 404 
 405         capimsg_setu16(buf, 0, nconn);
 406         capimsg_setu16(buf, 2, rp->datablkcnt);
 407         capimsg_setu16(buf, 4, rp->datablklen);
 408 
 409         application->state = BT_CONFIG;
 410         application->msgnum = cmtp_msgnum_get(session);
 411 
 412         cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum,
 413                                 CAPI_FUNCTION_REGISTER, buf, 6);
 414 
 415         add_wait_queue(&session->wait, &wait);
 416         while (1) {
 417                 set_current_state(TASK_INTERRUPTIBLE);
 418 
 419                 if (!timeo) {
 420                         err = -EAGAIN;
 421                         break;
 422                 }
 423 
 424                 if (application->state == BT_CLOSED) {
 425                         err = -application->err;
 426                         break;
 427                 }
 428 
 429                 if (application->state == BT_CONNECTED)
 430                         break;
 431 
 432                 if (signal_pending(current)) {
 433                         err = -EINTR;
 434                         break;
 435                 }
 436 
 437                 timeo = schedule_timeout(timeo);
 438         }
 439         set_current_state(TASK_RUNNING);
 440         remove_wait_queue(&session->wait, &wait);
 441 
 442         if (err) {
 443                 cmtp_application_del(session, application);
 444                 return;
 445         }
 446 }
 447 
 448 static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl)
 449 {
 450         struct cmtp_session *session = ctrl->driverdata;
 451         struct cmtp_application *application;
 452 
 453         BT_DBG("ctrl %p appl %d", ctrl, appl);
 454 
 455         application = cmtp_application_get(session, CMTP_APPLID, appl);
 456         if (!application) {
 457                 BT_ERR("Can't find application");
 458                 return;
 459         }
 460 
 461         application->msgnum = cmtp_msgnum_get(session);
 462 
 463         cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum,
 464                                 CAPI_FUNCTION_RELEASE, NULL, 0);
 465 
 466         wait_event_interruptible_timeout(session->wait,
 467                         (application->state == BT_CLOSED), CMTP_INTEROP_TIMEOUT);
 468 
 469         cmtp_application_del(session, application);
 470 }
 471 
 472 static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
 473 {
 474         struct cmtp_session *session = ctrl->driverdata;
 475         struct cmtp_application *application;
 476         __u16 appl;
 477         __u32 contr;
 478 
 479         BT_DBG("ctrl %p skb %p", ctrl, skb);
 480 
 481         appl = CAPIMSG_APPID(skb->data);
 482         contr = CAPIMSG_CONTROL(skb->data);
 483 
 484         application = cmtp_application_get(session, CMTP_APPLID, appl);
 485         if ((!application) || (application->state != BT_CONNECTED)) {
 486                 BT_ERR("Can't find application with id %d", appl);
 487                 return CAPI_ILLAPPNR;
 488         }
 489 
 490         CAPIMSG_SETAPPID(skb->data, application->mapping);
 491 
 492         if ((contr & 0x7f) == session->num) {
 493                 contr = (contr & 0xffffff80) | 0x01;
 494                 CAPIMSG_SETCONTROL(skb->data, contr);
 495         }
 496 
 497         cmtp_send_capimsg(session, skb);
 498 
 499         return CAPI_NOERROR;
 500 }
 501 
 502 static char *cmtp_procinfo(struct capi_ctr *ctrl)
 503 {
 504         return "CAPI Message Transport Protocol";
 505 }
 506 
 507 static int cmtp_proc_show(struct seq_file *m, void *v)
 508 {
 509         struct capi_ctr *ctrl = m->private;
 510         struct cmtp_session *session = ctrl->driverdata;
 511         struct cmtp_application *app;
 512 
 513         seq_printf(m, "%s\n\n", cmtp_procinfo(ctrl));
 514         seq_printf(m, "addr %s\n", session->name);
 515         seq_printf(m, "ctrl %d\n", session->num);
 516 
 517         list_for_each_entry(app, &session->applications, list) {
 518                 seq_printf(m, "appl %d -> %d\n", app->appl, app->mapping);
 519         }
 520 
 521         return 0;
 522 }
 523 
 524 int cmtp_attach_device(struct cmtp_session *session)
 525 {
 526         unsigned char buf[4];
 527         long ret;
 528 
 529         BT_DBG("session %p", session);
 530 
 531         capimsg_setu32(buf, 0, 0);
 532 
 533         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
 534                                 CAPI_FUNCTION_GET_PROFILE, buf, 4);
 535 
 536         ret = wait_event_interruptible_timeout(session->wait,
 537                         session->ncontroller, CMTP_INTEROP_TIMEOUT);
 538 
 539         BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
 540 
 541         if (!ret)
 542                 return -ETIMEDOUT;
 543 
 544         if (!session->ncontroller)
 545                 return -ENODEV;
 546 
 547         if (session->ncontroller > 1)
 548                 BT_INFO("Setting up only CAPI controller 1");
 549 
 550         session->ctrl.owner      = THIS_MODULE;
 551         session->ctrl.driverdata = session;
 552         strcpy(session->ctrl.name, session->name);
 553 
 554         session->ctrl.driver_name   = "cmtp";
 555         session->ctrl.load_firmware = cmtp_load_firmware;
 556         session->ctrl.reset_ctr     = cmtp_reset_ctr;
 557         session->ctrl.register_appl = cmtp_register_appl;
 558         session->ctrl.release_appl  = cmtp_release_appl;
 559         session->ctrl.send_message  = cmtp_send_message;
 560 
 561         session->ctrl.procinfo      = cmtp_procinfo;
 562         session->ctrl.proc_show     = cmtp_proc_show;
 563 
 564         if (attach_capi_ctr(&session->ctrl) < 0) {
 565                 BT_ERR("Can't attach new controller");
 566                 return -EBUSY;
 567         }
 568 
 569         session->num = session->ctrl.cnr;
 570 
 571         BT_DBG("session %p num %d", session, session->num);
 572 
 573         capimsg_setu32(buf, 0, 1);
 574 
 575         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
 576                                 CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
 577 
 578         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
 579                                 CAPI_FUNCTION_GET_VERSION, buf, 4);
 580 
 581         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
 582                                 CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
 583 
 584         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
 585                                 CAPI_FUNCTION_GET_PROFILE, buf, 4);
 586 
 587         return 0;
 588 }
 589 
 590 void cmtp_detach_device(struct cmtp_session *session)
 591 {
 592         BT_DBG("session %p", session);
 593 
 594         detach_capi_ctr(&session->ctrl);
 595 }