0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include "kcapi.h"
0014 #include <linux/module.h>
0015 #include <linux/mm.h>
0016 #include <linux/interrupt.h>
0017 #include <linux/ioport.h>
0018 #include <linux/proc_fs.h>
0019 #include <linux/sched/signal.h>
0020 #include <linux/seq_file.h>
0021 #include <linux/skbuff.h>
0022 #include <linux/workqueue.h>
0023 #include <linux/capi.h>
0024 #include <linux/kernelcapi.h>
0025 #include <linux/init.h>
0026 #include <linux/moduleparam.h>
0027 #include <linux/delay.h>
0028 #include <linux/slab.h>
0029 #include <linux/uaccess.h>
0030 #include <linux/isdn/capicmd.h>
0031 #include <linux/isdn/capiutil.h>
0032 #include <linux/mutex.h>
0033 #include <linux/rcupdate.h>
0034
0035 static int showcapimsgs;
0036 static struct workqueue_struct *kcapi_wq;
0037
0038 module_param(showcapimsgs, uint, 0);
0039
0040
0041
0042 struct capictr_event {
0043 struct work_struct work;
0044 unsigned int type;
0045 u32 controller;
0046 };
0047
0048
0049
0050 static const struct capi_version driver_version = {2, 0, 1, 1 << 4};
0051 static char driver_serial[CAPI_SERIAL_LEN] = "0004711";
0052 static char capi_manufakturer[64] = "AVM Berlin";
0053
0054 #define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f)
0055
0056 struct capi_ctr *capi_controller[CAPI_MAXCONTR];
0057 DEFINE_MUTEX(capi_controller_lock);
0058
0059 struct capi20_appl *capi_applications[CAPI_MAXAPPL];
0060
0061 static int ncontrollers;
0062
0063
0064
0065 static inline struct capi_ctr *
0066 capi_ctr_get(struct capi_ctr *ctr)
0067 {
0068 if (!try_module_get(ctr->owner))
0069 return NULL;
0070 return ctr;
0071 }
0072
0073 static inline void
0074 capi_ctr_put(struct capi_ctr *ctr)
0075 {
0076 module_put(ctr->owner);
0077 }
0078
0079
0080
0081 static inline struct capi_ctr *get_capi_ctr_by_nr(u16 contr)
0082 {
0083 if (contr < 1 || contr - 1 >= CAPI_MAXCONTR)
0084 return NULL;
0085
0086 return capi_controller[contr - 1];
0087 }
0088
0089 static inline struct capi20_appl *__get_capi_appl_by_nr(u16 applid)
0090 {
0091 lockdep_assert_held(&capi_controller_lock);
0092
0093 if (applid < 1 || applid - 1 >= CAPI_MAXAPPL)
0094 return NULL;
0095
0096 return capi_applications[applid - 1];
0097 }
0098
0099 static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid)
0100 {
0101 if (applid < 1 || applid - 1 >= CAPI_MAXAPPL)
0102 return NULL;
0103
0104 return rcu_dereference(capi_applications[applid - 1]);
0105 }
0106
0107
0108
0109 static inline int capi_cmd_valid(u8 cmd)
0110 {
0111 switch (cmd) {
0112 case CAPI_ALERT:
0113 case CAPI_CONNECT:
0114 case CAPI_CONNECT_ACTIVE:
0115 case CAPI_CONNECT_B3_ACTIVE:
0116 case CAPI_CONNECT_B3:
0117 case CAPI_CONNECT_B3_T90_ACTIVE:
0118 case CAPI_DATA_B3:
0119 case CAPI_DISCONNECT_B3:
0120 case CAPI_DISCONNECT:
0121 case CAPI_FACILITY:
0122 case CAPI_INFO:
0123 case CAPI_LISTEN:
0124 case CAPI_MANUFACTURER:
0125 case CAPI_RESET_B3:
0126 case CAPI_SELECT_B_PROTOCOL:
0127 return 1;
0128 }
0129 return 0;
0130 }
0131
0132 static inline int capi_subcmd_valid(u8 subcmd)
0133 {
0134 switch (subcmd) {
0135 case CAPI_REQ:
0136 case CAPI_CONF:
0137 case CAPI_IND:
0138 case CAPI_RESP:
0139 return 1;
0140 }
0141 return 0;
0142 }
0143
0144
0145
0146 static void
0147 register_appl(struct capi_ctr *ctr, u16 applid, capi_register_params *rparam)
0148 {
0149 ctr = capi_ctr_get(ctr);
0150
0151 if (ctr)
0152 ctr->register_appl(ctr, applid, rparam);
0153 else
0154 printk(KERN_WARNING "%s: cannot get controller resources\n",
0155 __func__);
0156 }
0157
0158
0159 static void release_appl(struct capi_ctr *ctr, u16 applid)
0160 {
0161 DBG("applid %#x", applid);
0162
0163 ctr->release_appl(ctr, applid);
0164 capi_ctr_put(ctr);
0165 }
0166
0167 static void notify_up(u32 contr)
0168 {
0169 struct capi20_appl *ap;
0170 struct capi_ctr *ctr;
0171 u16 applid;
0172
0173 mutex_lock(&capi_controller_lock);
0174
0175 if (showcapimsgs & 1)
0176 printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr);
0177
0178 ctr = get_capi_ctr_by_nr(contr);
0179 if (ctr) {
0180 if (ctr->state == CAPI_CTR_RUNNING)
0181 goto unlock_out;
0182
0183 ctr->state = CAPI_CTR_RUNNING;
0184
0185 for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
0186 ap = __get_capi_appl_by_nr(applid);
0187 if (ap)
0188 register_appl(ctr, applid, &ap->rparam);
0189 }
0190 } else
0191 printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr);
0192
0193 unlock_out:
0194 mutex_unlock(&capi_controller_lock);
0195 }
0196
0197 static void ctr_down(struct capi_ctr *ctr, int new_state)
0198 {
0199 struct capi20_appl *ap;
0200 u16 applid;
0201
0202 if (ctr->state == CAPI_CTR_DETECTED || ctr->state == CAPI_CTR_DETACHED)
0203 return;
0204
0205 ctr->state = new_state;
0206
0207 memset(ctr->manu, 0, sizeof(ctr->manu));
0208 memset(&ctr->version, 0, sizeof(ctr->version));
0209 memset(&ctr->profile, 0, sizeof(ctr->profile));
0210 memset(ctr->serial, 0, sizeof(ctr->serial));
0211
0212 for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
0213 ap = __get_capi_appl_by_nr(applid);
0214 if (ap)
0215 capi_ctr_put(ctr);
0216 }
0217 }
0218
0219 static void notify_down(u32 contr)
0220 {
0221 struct capi_ctr *ctr;
0222
0223 mutex_lock(&capi_controller_lock);
0224
0225 if (showcapimsgs & 1)
0226 printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr);
0227
0228 ctr = get_capi_ctr_by_nr(contr);
0229 if (ctr)
0230 ctr_down(ctr, CAPI_CTR_DETECTED);
0231 else
0232 printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr);
0233
0234 mutex_unlock(&capi_controller_lock);
0235 }
0236
0237 static void do_notify_work(struct work_struct *work)
0238 {
0239 struct capictr_event *event =
0240 container_of(work, struct capictr_event, work);
0241
0242 switch (event->type) {
0243 case CAPICTR_UP:
0244 notify_up(event->controller);
0245 break;
0246 case CAPICTR_DOWN:
0247 notify_down(event->controller);
0248 break;
0249 }
0250
0251 kfree(event);
0252 }
0253
0254 static int notify_push(unsigned int event_type, u32 controller)
0255 {
0256 struct capictr_event *event = kmalloc(sizeof(*event), GFP_ATOMIC);
0257
0258 if (!event)
0259 return -ENOMEM;
0260
0261 INIT_WORK(&event->work, do_notify_work);
0262 event->type = event_type;
0263 event->controller = controller;
0264
0265 queue_work(kcapi_wq, &event->work);
0266 return 0;
0267 }
0268
0269
0270
0271 static void recv_handler(struct work_struct *work)
0272 {
0273 struct sk_buff *skb;
0274 struct capi20_appl *ap =
0275 container_of(work, struct capi20_appl, recv_work);
0276
0277 if ((!ap) || (ap->release_in_progress))
0278 return;
0279
0280 mutex_lock(&ap->recv_mtx);
0281 while ((skb = skb_dequeue(&ap->recv_queue))) {
0282 if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_IND)
0283 ap->nrecvdatapkt++;
0284 else
0285 ap->nrecvctlpkt++;
0286
0287 ap->recv_message(ap, skb);
0288 }
0289 mutex_unlock(&ap->recv_mtx);
0290 }
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301 void capi_ctr_handle_message(struct capi_ctr *ctr, u16 appl,
0302 struct sk_buff *skb)
0303 {
0304 struct capi20_appl *ap;
0305 int showctl = 0;
0306 u8 cmd, subcmd;
0307 _cdebbuf *cdb;
0308
0309 if (ctr->state != CAPI_CTR_RUNNING) {
0310 cdb = capi_message2str(skb->data);
0311 if (cdb) {
0312 printk(KERN_INFO "kcapi: controller [%03d] not active, got: %s",
0313 ctr->cnr, cdb->buf);
0314 cdebbuf_free(cdb);
0315 } else
0316 printk(KERN_INFO "kcapi: controller [%03d] not active, cannot trace\n",
0317 ctr->cnr);
0318 goto error;
0319 }
0320
0321 cmd = CAPIMSG_COMMAND(skb->data);
0322 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
0323 if (cmd == CAPI_DATA_B3 && subcmd == CAPI_IND) {
0324 ctr->nrecvdatapkt++;
0325 if (ctr->traceflag > 2)
0326 showctl |= 2;
0327 } else {
0328 ctr->nrecvctlpkt++;
0329 if (ctr->traceflag)
0330 showctl |= 2;
0331 }
0332 showctl |= (ctr->traceflag & 1);
0333 if (showctl & 2) {
0334 if (showctl & 1) {
0335 printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u\n",
0336 ctr->cnr, CAPIMSG_APPID(skb->data),
0337 capi_cmd2str(cmd, subcmd),
0338 CAPIMSG_LEN(skb->data));
0339 } else {
0340 cdb = capi_message2str(skb->data);
0341 if (cdb) {
0342 printk(KERN_DEBUG "kcapi: got [%03d] %s\n",
0343 ctr->cnr, cdb->buf);
0344 cdebbuf_free(cdb);
0345 } else
0346 printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u, cannot trace\n",
0347 ctr->cnr, CAPIMSG_APPID(skb->data),
0348 capi_cmd2str(cmd, subcmd),
0349 CAPIMSG_LEN(skb->data));
0350 }
0351
0352 }
0353
0354 rcu_read_lock();
0355 ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data));
0356 if (!ap) {
0357 rcu_read_unlock();
0358 cdb = capi_message2str(skb->data);
0359 if (cdb) {
0360 printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n",
0361 CAPIMSG_APPID(skb->data), cdb->buf);
0362 cdebbuf_free(cdb);
0363 } else
0364 printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s) cannot trace\n",
0365 CAPIMSG_APPID(skb->data),
0366 capi_cmd2str(cmd, subcmd));
0367 goto error;
0368 }
0369 skb_queue_tail(&ap->recv_queue, skb);
0370 queue_work(kcapi_wq, &ap->recv_work);
0371 rcu_read_unlock();
0372
0373 return;
0374
0375 error:
0376 kfree_skb(skb);
0377 }
0378
0379 EXPORT_SYMBOL(capi_ctr_handle_message);
0380
0381
0382
0383
0384
0385
0386
0387
0388 void capi_ctr_ready(struct capi_ctr *ctr)
0389 {
0390 printk(KERN_NOTICE "kcapi: controller [%03d] \"%s\" ready.\n",
0391 ctr->cnr, ctr->name);
0392
0393 notify_push(CAPICTR_UP, ctr->cnr);
0394 }
0395
0396 EXPORT_SYMBOL(capi_ctr_ready);
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406 void capi_ctr_down(struct capi_ctr *ctr)
0407 {
0408 printk(KERN_NOTICE "kcapi: controller [%03d] down.\n", ctr->cnr);
0409
0410 notify_push(CAPICTR_DOWN, ctr->cnr);
0411 }
0412
0413 EXPORT_SYMBOL(capi_ctr_down);
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425 int attach_capi_ctr(struct capi_ctr *ctr)
0426 {
0427 int i;
0428
0429 mutex_lock(&capi_controller_lock);
0430
0431 for (i = 0; i < CAPI_MAXCONTR; i++) {
0432 if (!capi_controller[i])
0433 break;
0434 }
0435 if (i == CAPI_MAXCONTR) {
0436 mutex_unlock(&capi_controller_lock);
0437 printk(KERN_ERR "kcapi: out of controller slots\n");
0438 return -EBUSY;
0439 }
0440 capi_controller[i] = ctr;
0441
0442 ctr->nrecvctlpkt = 0;
0443 ctr->nrecvdatapkt = 0;
0444 ctr->nsentctlpkt = 0;
0445 ctr->nsentdatapkt = 0;
0446 ctr->cnr = i + 1;
0447 ctr->state = CAPI_CTR_DETECTED;
0448 ctr->blocked = 0;
0449 ctr->traceflag = showcapimsgs;
0450
0451 sprintf(ctr->procfn, "capi/controllers/%d", ctr->cnr);
0452 ctr->procent = proc_create_single_data(ctr->procfn, 0, NULL,
0453 ctr->proc_show, ctr);
0454
0455 ncontrollers++;
0456
0457 mutex_unlock(&capi_controller_lock);
0458
0459 printk(KERN_NOTICE "kcapi: controller [%03d]: %s attached\n",
0460 ctr->cnr, ctr->name);
0461 return 0;
0462 }
0463
0464 EXPORT_SYMBOL(attach_capi_ctr);
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475 int detach_capi_ctr(struct capi_ctr *ctr)
0476 {
0477 int err = 0;
0478
0479 mutex_lock(&capi_controller_lock);
0480
0481 ctr_down(ctr, CAPI_CTR_DETACHED);
0482
0483 if (ctr->cnr < 1 || ctr->cnr - 1 >= CAPI_MAXCONTR) {
0484 err = -EINVAL;
0485 goto unlock_out;
0486 }
0487
0488 if (capi_controller[ctr->cnr - 1] != ctr) {
0489 err = -EINVAL;
0490 goto unlock_out;
0491 }
0492 capi_controller[ctr->cnr - 1] = NULL;
0493 ncontrollers--;
0494
0495 if (ctr->procent)
0496 remove_proc_entry(ctr->procfn, NULL);
0497
0498 printk(KERN_NOTICE "kcapi: controller [%03d]: %s unregistered\n",
0499 ctr->cnr, ctr->name);
0500
0501 unlock_out:
0502 mutex_unlock(&capi_controller_lock);
0503
0504 return err;
0505 }
0506
0507 EXPORT_SYMBOL(detach_capi_ctr);
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520 u16 capi20_isinstalled(void)
0521 {
0522 u16 ret = CAPI_REGNOTINSTALLED;
0523 int i;
0524
0525 mutex_lock(&capi_controller_lock);
0526
0527 for (i = 0; i < CAPI_MAXCONTR; i++)
0528 if (capi_controller[i] &&
0529 capi_controller[i]->state == CAPI_CTR_RUNNING) {
0530 ret = CAPI_NOERROR;
0531 break;
0532 }
0533
0534 mutex_unlock(&capi_controller_lock);
0535
0536 return ret;
0537 }
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551 u16 capi20_register(struct capi20_appl *ap)
0552 {
0553 int i;
0554 u16 applid;
0555
0556 DBG("");
0557
0558 if (ap->rparam.datablklen < 128)
0559 return CAPI_LOGBLKSIZETOSMALL;
0560
0561 ap->nrecvctlpkt = 0;
0562 ap->nrecvdatapkt = 0;
0563 ap->nsentctlpkt = 0;
0564 ap->nsentdatapkt = 0;
0565 mutex_init(&ap->recv_mtx);
0566 skb_queue_head_init(&ap->recv_queue);
0567 INIT_WORK(&ap->recv_work, recv_handler);
0568 ap->release_in_progress = 0;
0569
0570 mutex_lock(&capi_controller_lock);
0571
0572 for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
0573 if (capi_applications[applid - 1] == NULL)
0574 break;
0575 }
0576 if (applid > CAPI_MAXAPPL) {
0577 mutex_unlock(&capi_controller_lock);
0578 return CAPI_TOOMANYAPPLS;
0579 }
0580
0581 ap->applid = applid;
0582 capi_applications[applid - 1] = ap;
0583
0584 for (i = 0; i < CAPI_MAXCONTR; i++) {
0585 if (!capi_controller[i] ||
0586 capi_controller[i]->state != CAPI_CTR_RUNNING)
0587 continue;
0588 register_appl(capi_controller[i], applid, &ap->rparam);
0589 }
0590
0591 mutex_unlock(&capi_controller_lock);
0592
0593 if (showcapimsgs & 1) {
0594 printk(KERN_DEBUG "kcapi: appl %d up\n", applid);
0595 }
0596
0597 return CAPI_NOERROR;
0598 }
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610 u16 capi20_release(struct capi20_appl *ap)
0611 {
0612 int i;
0613
0614 DBG("applid %#x", ap->applid);
0615
0616 mutex_lock(&capi_controller_lock);
0617
0618 ap->release_in_progress = 1;
0619 capi_applications[ap->applid - 1] = NULL;
0620
0621 synchronize_rcu();
0622
0623 for (i = 0; i < CAPI_MAXCONTR; i++) {
0624 if (!capi_controller[i] ||
0625 capi_controller[i]->state != CAPI_CTR_RUNNING)
0626 continue;
0627 release_appl(capi_controller[i], ap->applid);
0628 }
0629
0630 mutex_unlock(&capi_controller_lock);
0631
0632 flush_workqueue(kcapi_wq);
0633 skb_queue_purge(&ap->recv_queue);
0634
0635 if (showcapimsgs & 1) {
0636 printk(KERN_DEBUG "kcapi: appl %d down\n", ap->applid);
0637 }
0638
0639 return CAPI_NOERROR;
0640 }
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651 u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb)
0652 {
0653 struct capi_ctr *ctr;
0654 int showctl = 0;
0655 u8 cmd, subcmd;
0656
0657 DBG("applid %#x", ap->applid);
0658
0659 if (ncontrollers == 0)
0660 return CAPI_REGNOTINSTALLED;
0661 if ((ap->applid == 0) || ap->release_in_progress)
0662 return CAPI_ILLAPPNR;
0663 if (skb->len < 12
0664 || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data))
0665 || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data)))
0666 return CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
0667
0668
0669
0670
0671
0672
0673 ctr = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data));
0674 if (!ctr || ctr->state != CAPI_CTR_RUNNING)
0675 return CAPI_REGNOTINSTALLED;
0676 if (ctr->blocked)
0677 return CAPI_SENDQUEUEFULL;
0678
0679 cmd = CAPIMSG_COMMAND(skb->data);
0680 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
0681
0682 if (cmd == CAPI_DATA_B3 && subcmd == CAPI_REQ) {
0683 ctr->nsentdatapkt++;
0684 ap->nsentdatapkt++;
0685 if (ctr->traceflag > 2)
0686 showctl |= 2;
0687 } else {
0688 ctr->nsentctlpkt++;
0689 ap->nsentctlpkt++;
0690 if (ctr->traceflag)
0691 showctl |= 2;
0692 }
0693 showctl |= (ctr->traceflag & 1);
0694 if (showctl & 2) {
0695 if (showctl & 1) {
0696 printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u\n",
0697 CAPIMSG_CONTROLLER(skb->data),
0698 CAPIMSG_APPID(skb->data),
0699 capi_cmd2str(cmd, subcmd),
0700 CAPIMSG_LEN(skb->data));
0701 } else {
0702 _cdebbuf *cdb = capi_message2str(skb->data);
0703 if (cdb) {
0704 printk(KERN_DEBUG "kcapi: put [%03d] %s\n",
0705 CAPIMSG_CONTROLLER(skb->data),
0706 cdb->buf);
0707 cdebbuf_free(cdb);
0708 } else
0709 printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u cannot trace\n",
0710 CAPIMSG_CONTROLLER(skb->data),
0711 CAPIMSG_APPID(skb->data),
0712 capi_cmd2str(cmd, subcmd),
0713 CAPIMSG_LEN(skb->data));
0714 }
0715 }
0716 return ctr->send_message(ctr, skb);
0717 }
0718
0719
0720
0721
0722
0723
0724
0725
0726
0727
0728
0729 u16 capi20_get_manufacturer(u32 contr, u8 buf[CAPI_MANUFACTURER_LEN])
0730 {
0731 struct capi_ctr *ctr;
0732 u16 ret;
0733
0734 if (contr == 0) {
0735 strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
0736 return CAPI_NOERROR;
0737 }
0738
0739 mutex_lock(&capi_controller_lock);
0740
0741 ctr = get_capi_ctr_by_nr(contr);
0742 if (ctr && ctr->state == CAPI_CTR_RUNNING) {
0743 strncpy(buf, ctr->manu, CAPI_MANUFACTURER_LEN);
0744 ret = CAPI_NOERROR;
0745 } else
0746 ret = CAPI_REGNOTINSTALLED;
0747
0748 mutex_unlock(&capi_controller_lock);
0749 return ret;
0750 }
0751
0752
0753
0754
0755
0756
0757
0758
0759
0760
0761
0762 u16 capi20_get_version(u32 contr, struct capi_version *verp)
0763 {
0764 struct capi_ctr *ctr;
0765 u16 ret;
0766
0767 if (contr == 0) {
0768 *verp = driver_version;
0769 return CAPI_NOERROR;
0770 }
0771
0772 mutex_lock(&capi_controller_lock);
0773
0774 ctr = get_capi_ctr_by_nr(contr);
0775 if (ctr && ctr->state == CAPI_CTR_RUNNING) {
0776 memcpy(verp, &ctr->version, sizeof(capi_version));
0777 ret = CAPI_NOERROR;
0778 } else
0779 ret = CAPI_REGNOTINSTALLED;
0780
0781 mutex_unlock(&capi_controller_lock);
0782 return ret;
0783 }
0784
0785
0786
0787
0788
0789
0790
0791
0792
0793
0794
0795 u16 capi20_get_serial(u32 contr, u8 serial[CAPI_SERIAL_LEN])
0796 {
0797 struct capi_ctr *ctr;
0798 u16 ret;
0799
0800 if (contr == 0) {
0801 strlcpy(serial, driver_serial, CAPI_SERIAL_LEN);
0802 return CAPI_NOERROR;
0803 }
0804
0805 mutex_lock(&capi_controller_lock);
0806
0807 ctr = get_capi_ctr_by_nr(contr);
0808 if (ctr && ctr->state == CAPI_CTR_RUNNING) {
0809 strlcpy(serial, ctr->serial, CAPI_SERIAL_LEN);
0810 ret = CAPI_NOERROR;
0811 } else
0812 ret = CAPI_REGNOTINSTALLED;
0813
0814 mutex_unlock(&capi_controller_lock);
0815 return ret;
0816 }
0817
0818
0819
0820
0821
0822
0823
0824
0825
0826
0827
0828 u16 capi20_get_profile(u32 contr, struct capi_profile *profp)
0829 {
0830 struct capi_ctr *ctr;
0831 u16 ret;
0832
0833 if (contr == 0) {
0834 profp->ncontroller = ncontrollers;
0835 return CAPI_NOERROR;
0836 }
0837
0838 mutex_lock(&capi_controller_lock);
0839
0840 ctr = get_capi_ctr_by_nr(contr);
0841 if (ctr && ctr->state == CAPI_CTR_RUNNING) {
0842 memcpy(profp, &ctr->profile, sizeof(struct capi_profile));
0843 ret = CAPI_NOERROR;
0844 } else
0845 ret = CAPI_REGNOTINSTALLED;
0846
0847 mutex_unlock(&capi_controller_lock);
0848 return ret;
0849 }
0850
0851
0852
0853
0854
0855
0856
0857
0858
0859
0860 int capi20_manufacturer(unsigned long cmd, void __user *data)
0861 {
0862 struct capi_ctr *ctr;
0863 int retval;
0864
0865 switch (cmd) {
0866 case KCAPI_CMD_TRACE:
0867 {
0868 kcapi_flagdef fdef;
0869
0870 if (copy_from_user(&fdef, data, sizeof(kcapi_flagdef)))
0871 return -EFAULT;
0872
0873 mutex_lock(&capi_controller_lock);
0874
0875 ctr = get_capi_ctr_by_nr(fdef.contr);
0876 if (ctr) {
0877 ctr->traceflag = fdef.flag;
0878 printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n",
0879 ctr->cnr, ctr->traceflag);
0880 retval = 0;
0881 } else
0882 retval = -ESRCH;
0883
0884 mutex_unlock(&capi_controller_lock);
0885
0886 return retval;
0887 }
0888
0889 default:
0890 printk(KERN_ERR "kcapi: manufacturer command %lu unknown.\n",
0891 cmd);
0892 break;
0893
0894 }
0895 return -EINVAL;
0896 }
0897
0898
0899
0900
0901
0902
0903
0904
0905
0906 int __init kcapi_init(void)
0907 {
0908 int err;
0909
0910 kcapi_wq = alloc_workqueue("kcapi", 0, 0);
0911 if (!kcapi_wq)
0912 return -ENOMEM;
0913
0914 err = cdebug_init();
0915 if (err) {
0916 destroy_workqueue(kcapi_wq);
0917 return err;
0918 }
0919
0920 kcapi_proc_init();
0921 return 0;
0922 }
0923
0924 void kcapi_exit(void)
0925 {
0926 kcapi_proc_exit();
0927
0928 cdebug_exit();
0929 destroy_workqueue(kcapi_wq);
0930 }