capidrv.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:63k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: capidrv.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
  2.  *
  3.  * ISDN4Linux Driver, using capi20 interface (kernelcapi)
  4.  *
  5.  * Copyright 1997 by Carsten Paeth <calle@calle.de>
  6.  *
  7.  * This software may be used and distributed according to the terms
  8.  * of the GNU General Public License, incorporated herein by reference.
  9.  *
  10.  */
  11. #include <linux/module.h>
  12. #include <linux/errno.h>
  13. #include <linux/kernel.h>
  14. #include <linux/major.h>
  15. #include <linux/sched.h>
  16. #include <linux/slab.h>
  17. #include <linux/fcntl.h>
  18. #include <linux/fs.h>
  19. #include <linux/signal.h>
  20. #include <linux/mm.h>
  21. #include <linux/timer.h>
  22. #include <linux/wait.h>
  23. #include <linux/skbuff.h>
  24. #include <linux/isdn.h>
  25. #include <linux/isdnif.h>
  26. #include <linux/proc_fs.h>
  27. #include <linux/capi.h>
  28. #include <linux/kernelcapi.h>
  29. #include <linux/ctype.h>
  30. #include <linux/init.h>
  31. #include <asm/segment.h>
  32. #include "capiutil.h"
  33. #include "capicmd.h"
  34. #include "capidrv.h"
  35. static char *revision = "$Revision: 1.1.4.1 $";
  36. static int debugmode = 0;
  37. MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux");
  38. MODULE_AUTHOR("Carsten Paeth");
  39. MODULE_LICENSE("GPL");
  40. MODULE_PARM(debugmode, "i");
  41. /* -------- type definitions ----------------------------------------- */
  42. struct capidrv_contr {
  43. struct capidrv_contr *next;
  44. __u32 contrnr;
  45. char name[20];
  46. /*
  47.  * for isdn4linux
  48.  */
  49. isdn_if interface;
  50. int myid;
  51. /*
  52.  * LISTEN state
  53.  */
  54. int state;
  55. __u32 cipmask;
  56. __u32 cipmask2;
  57.         struct timer_list listentimer;
  58. /*
  59.  * ID of capi message sent
  60.  */
  61. __u16 msgid;
  62. /*
  63.  * B-Channels
  64.  */
  65. int nbchan;
  66. struct capidrv_bchan {
  67. struct capidrv_contr *contr;
  68. __u8 msn[ISDN_MSNLEN];
  69. int l2;
  70. int l3;
  71. __u8 num[ISDN_MSNLEN];
  72. __u8 mynum[ISDN_MSNLEN];
  73. int si1;
  74. int si2;
  75. int incoming;
  76. int disconnecting;
  77. struct capidrv_plci {
  78. struct capidrv_plci *next;
  79. __u32 plci;
  80. __u32 ncci; /* ncci for CONNECT_ACTIVE_IND */
  81. __u16 msgid; /* to identfy CONNECT_CONF */
  82. int chan;
  83. int state;
  84. int leasedline;
  85. struct capidrv_ncci {
  86. struct capidrv_ncci *next;
  87. struct capidrv_plci *plcip;
  88. __u32 ncci;
  89. __u16 msgid; /* to identfy CONNECT_B3_CONF */
  90. int chan;
  91. int state;
  92. int oldstate;
  93. /* */
  94. __u16 datahandle;
  95. struct ncci_datahandle_queue {
  96.     struct ncci_datahandle_queue *next;
  97.     __u16                         datahandle;
  98.     int                           len;
  99. } *ackqueue;
  100. } *ncci_list;
  101. } *plcip;
  102. struct capidrv_ncci *nccip;
  103. } *bchans;
  104. struct capidrv_plci *plci_list;
  105. /* for q931 data */
  106. __u8  q931_buf[4096];
  107. __u8 *q931_read;
  108. __u8 *q931_write;
  109. __u8 *q931_end;
  110. };
  111. struct capidrv_data {
  112. __u16 appid;
  113. int ncontr;
  114. struct capidrv_contr *contr_list;
  115.         /* statistic */
  116. unsigned long nrecvctlpkt;
  117. unsigned long nrecvdatapkt;
  118. unsigned long nsentctlpkt;
  119. unsigned long nsentdatapkt;
  120. };
  121. typedef struct capidrv_plci capidrv_plci;
  122. typedef struct capidrv_ncci capidrv_ncci;
  123. typedef struct capidrv_contr capidrv_contr;
  124. typedef struct capidrv_data capidrv_data;
  125. typedef struct capidrv_bchan capidrv_bchan;
  126. /* -------- data definitions ----------------------------------------- */
  127. static capidrv_data global;
  128. static spinlock_t global_lock = SPIN_LOCK_UNLOCKED;
  129. static struct capi_interface *capifuncs;
  130. static void handle_dtrace_data(capidrv_contr *card,
  131. int send, int level2, __u8 *data, __u16 len);
  132. /* -------- convert functions ---------------------------------------- */
  133. static inline __u32 b1prot(int l2, int l3)
  134. {
  135. switch (l2) {
  136. case ISDN_PROTO_L2_X75I:
  137. case ISDN_PROTO_L2_X75UI:
  138. case ISDN_PROTO_L2_X75BUI:
  139. return 0;
  140. case ISDN_PROTO_L2_HDLC:
  141. default:
  142. return 0;
  143. case ISDN_PROTO_L2_TRANS:
  144. return 1;
  145.         case ISDN_PROTO_L2_V11096:
  146.         case ISDN_PROTO_L2_V11019:
  147.         case ISDN_PROTO_L2_V11038:
  148. return 2;
  149.         case ISDN_PROTO_L2_FAX:
  150. return 4;
  151. case ISDN_PROTO_L2_MODEM:
  152. return 8;
  153. }
  154. }
  155. static inline __u32 b2prot(int l2, int l3)
  156. {
  157. switch (l2) {
  158. case ISDN_PROTO_L2_X75I:
  159. case ISDN_PROTO_L2_X75UI:
  160. case ISDN_PROTO_L2_X75BUI:
  161. default:
  162. return 0;
  163. case ISDN_PROTO_L2_HDLC:
  164. case ISDN_PROTO_L2_TRANS:
  165.         case ISDN_PROTO_L2_V11096:
  166.         case ISDN_PROTO_L2_V11019:
  167.         case ISDN_PROTO_L2_V11038:
  168. case ISDN_PROTO_L2_MODEM:
  169. return 1;
  170.         case ISDN_PROTO_L2_FAX:
  171. return 4;
  172. }
  173. }
  174. static inline __u32 b3prot(int l2, int l3)
  175. {
  176. switch (l2) {
  177. case ISDN_PROTO_L2_X75I:
  178. case ISDN_PROTO_L2_X75UI:
  179. case ISDN_PROTO_L2_X75BUI:
  180. case ISDN_PROTO_L2_HDLC:
  181. case ISDN_PROTO_L2_TRANS:
  182.         case ISDN_PROTO_L2_V11096:
  183.         case ISDN_PROTO_L2_V11019:
  184.         case ISDN_PROTO_L2_V11038:
  185. case ISDN_PROTO_L2_MODEM:
  186. default:
  187. return 0;
  188.         case ISDN_PROTO_L2_FAX:
  189. return 4;
  190. }
  191. }
  192. static _cstruct b1config_async_v110(__u16 rate)
  193. {
  194. /* CAPI-Spec "B1 Configuration" */
  195. static unsigned char buf[9];
  196. buf[0] = 8; /* len */
  197. /* maximum bitrate */
  198. buf[1] = rate & 0xff; buf[2] = (rate >> 8) & 0xff;
  199. buf[3] = 8; buf[4] = 0; /* 8 bits per character */
  200. buf[5] = 0; buf[6] = 0; /* parity none */
  201. buf[7] = 0; buf[8] = 0; /* 1 stop bit */
  202. return buf;
  203. }
  204. static _cstruct b1config(int l2, int l3)
  205. {
  206. switch (l2) {
  207. case ISDN_PROTO_L2_X75I:
  208. case ISDN_PROTO_L2_X75UI:
  209. case ISDN_PROTO_L2_X75BUI:
  210. case ISDN_PROTO_L2_HDLC:
  211. case ISDN_PROTO_L2_TRANS:
  212. default:
  213. return 0;
  214.         case ISDN_PROTO_L2_V11096:
  215.     return b1config_async_v110(9600);
  216.         case ISDN_PROTO_L2_V11019:
  217.     return b1config_async_v110(19200);
  218.         case ISDN_PROTO_L2_V11038:
  219.     return b1config_async_v110(38400);
  220. }
  221. }
  222. static inline __u16 si2cip(__u8 si1, __u8 si2)
  223. {
  224. static const __u8 cip[17][5] =
  225. {
  226. /*  0  1  2  3  4  */
  227. {0, 0, 0, 0, 0}, /*0 */
  228. {16, 16, 4, 26, 16}, /*1 */
  229. {17, 17, 17, 4, 4}, /*2 */
  230. {2, 2, 2, 2, 2}, /*3 */
  231. {18, 18, 18, 18, 18}, /*4 */
  232. {2, 2, 2, 2, 2}, /*5 */
  233. {0, 0, 0, 0, 0}, /*6 */
  234. {2, 2, 2, 2, 2}, /*7 */
  235. {2, 2, 2, 2, 2}, /*8 */
  236. {21, 21, 21, 21, 21}, /*9 */
  237. {19, 19, 19, 19, 19}, /*10 */
  238. {0, 0, 0, 0, 0}, /*11 */
  239. {0, 0, 0, 0, 0}, /*12 */
  240. {0, 0, 0, 0, 0}, /*13 */
  241. {0, 0, 0, 0, 0}, /*14 */
  242. {22, 22, 22, 22, 22}, /*15 */
  243. {27, 27, 27, 28, 27} /*16 */
  244. };
  245. if (si1 > 16)
  246. si1 = 0;
  247. if (si2 > 4)
  248. si2 = 0;
  249. return (__u16) cip[si1][si2];
  250. }
  251. static inline __u8 cip2si1(__u16 cipval)
  252. {
  253. static const __u8 si[32] =
  254. {7, 1, 7, 7, 1, 1, 7, 7, /*0-7 */
  255.  7, 1, 0, 0, 0, 0, 0, 0, /*8-15 */
  256.  1, 2, 4, 10, 9, 9, 15, 7, /*16-23 */
  257.  7, 7, 1, 16, 16, 0, 0, 0}; /*24-31 */
  258. if (cipval > 31)
  259. cipval = 0; /* .... */
  260. return si[cipval];
  261. }
  262. static inline __u8 cip2si2(__u16 cipval)
  263. {
  264. static const __u8 si[32] =
  265. {0, 0, 0, 0, 2, 3, 0, 0, /*0-7 */
  266.  0, 3, 0, 0, 0, 0, 0, 0, /*8-15 */
  267.  1, 2, 0, 0, 9, 0, 0, 0, /*16-23 */
  268.  0, 0, 3, 2, 3, 0, 0, 0}; /*24-31 */
  269. if (cipval > 31)
  270. cipval = 0; /* .... */
  271. return si[cipval];
  272. }
  273. /* -------- controller management ------------------------------------- */
  274. static inline capidrv_contr *findcontrbydriverid(int driverid)
  275. {
  276.      unsigned long flags;
  277. capidrv_contr *p;
  278. spin_lock_irqsave(&global_lock, flags);
  279. for (p = global.contr_list; p; p = p->next)
  280. if (p->myid == driverid)
  281. break;
  282. spin_unlock_irqrestore(&global_lock, flags);
  283. return p;
  284. }
  285. static capidrv_contr *findcontrbynumber(__u32 contr)
  286. {
  287. unsigned long flags;
  288. capidrv_contr *p = global.contr_list;
  289. spin_lock_irqsave(&global_lock, flags);
  290. for (p = global.contr_list; p; p = p->next)
  291. if (p->contrnr == contr)
  292. break;
  293. spin_unlock_irqrestore(&global_lock, flags);
  294. return p;
  295. }
  296. /* -------- plci management ------------------------------------------ */
  297. static capidrv_plci *new_plci(capidrv_contr * card, int chan)
  298. {
  299. capidrv_plci *plcip;
  300. plcip = (capidrv_plci *) kmalloc(sizeof(capidrv_plci), GFP_ATOMIC);
  301. if (plcip == 0)
  302. return 0;
  303. memset(plcip, 0, sizeof(capidrv_plci));
  304. plcip->state = ST_PLCI_NONE;
  305. plcip->plci = 0;
  306. plcip->msgid = 0;
  307. plcip->chan = chan;
  308. plcip->next = card->plci_list;
  309. card->plci_list = plcip;
  310. card->bchans[chan].plcip = plcip;
  311. return plcip;
  312. }
  313. static capidrv_plci *find_plci_by_plci(capidrv_contr * card, __u32 plci)
  314. {
  315. capidrv_plci *p;
  316. for (p = card->plci_list; p; p = p->next)
  317. if (p->plci == plci)
  318. return p;
  319. return 0;
  320. }
  321. static capidrv_plci *find_plci_by_msgid(capidrv_contr * card, __u16 msgid)
  322. {
  323. capidrv_plci *p;
  324. for (p = card->plci_list; p; p = p->next)
  325. if (p->msgid == msgid)
  326. return p;
  327. return 0;
  328. }
  329. static capidrv_plci *find_plci_by_ncci(capidrv_contr * card, __u32 ncci)
  330. {
  331. capidrv_plci *p;
  332. for (p = card->plci_list; p; p = p->next)
  333. if (p->plci == (ncci & 0xffff))
  334. return p;
  335. return 0;
  336. }
  337. static void free_plci(capidrv_contr * card, capidrv_plci * plcip)
  338. {
  339. capidrv_plci **pp;
  340. for (pp = &card->plci_list; *pp; pp = &(*pp)->next) {
  341. if (*pp == plcip) {
  342. *pp = (*pp)->next;
  343. card->bchans[plcip->chan].plcip = 0;
  344. card->bchans[plcip->chan].disconnecting = 0;
  345. card->bchans[plcip->chan].incoming = 0;
  346. kfree(plcip);
  347. return;
  348. }
  349. }
  350. printk(KERN_ERR "capidrv-%d: free_plci %p (0x%x) not found, Huh?n",
  351.        card->contrnr, plcip, plcip->plci);
  352. }
  353. /* -------- ncci management ------------------------------------------ */
  354. static inline capidrv_ncci *new_ncci(capidrv_contr * card,
  355.      capidrv_plci * plcip,
  356.      __u32 ncci)
  357. {
  358. capidrv_ncci *nccip;
  359. nccip = (capidrv_ncci *) kmalloc(sizeof(capidrv_ncci), GFP_ATOMIC);
  360. if (nccip == 0)
  361. return 0;
  362. memset(nccip, 0, sizeof(capidrv_ncci));
  363. nccip->ncci = ncci;
  364. nccip->state = ST_NCCI_NONE;
  365. nccip->plcip = plcip;
  366. nccip->chan = plcip->chan;
  367. nccip->datahandle = 0;
  368. nccip->next = plcip->ncci_list;
  369. plcip->ncci_list = nccip;
  370. card->bchans[plcip->chan].nccip = nccip;
  371. return nccip;
  372. }
  373. static inline capidrv_ncci *find_ncci(capidrv_contr * card, __u32 ncci)
  374. {
  375. capidrv_plci *plcip;
  376. capidrv_ncci *p;
  377. if ((plcip = find_plci_by_ncci(card, ncci)) == 0)
  378. return 0;
  379. for (p = plcip->ncci_list; p; p = p->next)
  380. if (p->ncci == ncci)
  381. return p;
  382. return 0;
  383. }
  384. static inline capidrv_ncci *find_ncci_by_msgid(capidrv_contr * card,
  385.        __u32 ncci, __u16 msgid)
  386. {
  387. capidrv_plci *plcip;
  388. capidrv_ncci *p;
  389. if ((plcip = find_plci_by_ncci(card, ncci)) == 0)
  390. return 0;
  391. for (p = plcip->ncci_list; p; p = p->next)
  392. if (p->msgid == msgid)
  393. return p;
  394. return 0;
  395. }
  396. static void free_ncci(capidrv_contr * card, struct capidrv_ncci *nccip)
  397. {
  398. struct capidrv_ncci **pp;
  399. for (pp = &(nccip->plcip->ncci_list); *pp; pp = &(*pp)->next) {
  400. if (*pp == nccip) {
  401. *pp = (*pp)->next;
  402. break;
  403. }
  404. }
  405. card->bchans[nccip->chan].nccip = 0;
  406. kfree(nccip);
  407. }
  408. static int capidrv_add_ack(struct capidrv_ncci *nccip,
  409.            __u16 datahandle, int len)
  410. {
  411. struct ncci_datahandle_queue *n, **pp;
  412. n = (struct ncci_datahandle_queue *)
  413. kmalloc(sizeof(struct ncci_datahandle_queue), GFP_ATOMIC);
  414. if (!n) {
  415.    printk(KERN_ERR "capidrv: kmalloc ncci_datahandle failedn");
  416.    return -1;
  417. }
  418. n->next = 0;
  419. n->datahandle = datahandle;
  420. n->len = len;
  421. for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) ;
  422. *pp = n;
  423. return 0;
  424. }
  425. static int capidrv_del_ack(struct capidrv_ncci *nccip, __u16 datahandle)
  426. {
  427. struct ncci_datahandle_queue **pp, *p;
  428. int len;
  429. for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) {
  430.   if ((*pp)->datahandle == datahandle) {
  431. p = *pp;
  432. len = p->len;
  433. *pp = (*pp)->next;
  434.         kfree(p);
  435. return len;
  436. }
  437. }
  438. return -1;
  439. }
  440. /* -------- convert and send capi message ---------------------------- */
  441. static void send_message(capidrv_contr * card, _cmsg * cmsg)
  442. {
  443. struct sk_buff *skb;
  444. size_t len;
  445. capi_cmsg2message(cmsg, cmsg->buf);
  446. len = CAPIMSG_LEN(cmsg->buf);
  447. skb = alloc_skb(len, GFP_ATOMIC);
  448. memcpy(skb_put(skb, len), cmsg->buf, len);
  449. (*capifuncs->capi_put_message) (global.appid, skb);
  450. global.nsentctlpkt++;
  451. }
  452. /* -------- state machine -------------------------------------------- */
  453. struct listenstatechange {
  454. int actstate;
  455. int nextstate;
  456. int event;
  457. };
  458. static struct listenstatechange listentable[] =
  459. {
  460.   {ST_LISTEN_NONE, ST_LISTEN_WAIT_CONF, EV_LISTEN_REQ},
  461.   {ST_LISTEN_ACTIVE, ST_LISTEN_ACTIVE_WAIT_CONF, EV_LISTEN_REQ},
  462.   {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_ERROR},
  463.   {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_ERROR},
  464.   {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
  465.   {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
  466.   {ST_LISTEN_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
  467.   {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
  468.   {},
  469. };
  470. static void listen_change_state(capidrv_contr * card, int event)
  471. {
  472. struct listenstatechange *p = listentable;
  473. while (p->event) {
  474. if (card->state == p->actstate && p->event == event) {
  475. if (debugmode)
  476. printk(KERN_DEBUG "capidrv-%d: listen_change_state %d -> %dn",
  477.        card->contrnr, card->state, p->nextstate);
  478. card->state = p->nextstate;
  479. return;
  480. }
  481. p++;
  482. }
  483. printk(KERN_ERR "capidrv-%d: listen_change_state state=%d event=%d ????n",
  484.        card->contrnr, card->state, event);
  485. }
  486. /* ------------------------------------------------------------------ */
  487. static void p0(capidrv_contr * card, capidrv_plci * plci)
  488. {
  489. isdn_ctrl cmd;
  490. card->bchans[plci->chan].contr = 0;
  491. cmd.command = ISDN_STAT_DHUP;
  492. cmd.driver = card->myid;
  493. cmd.arg = plci->chan;
  494. card->interface.statcallb(&cmd);
  495. free_plci(card, plci);
  496. }
  497. /* ------------------------------------------------------------------ */
  498. struct plcistatechange {
  499. int actstate;
  500. int nextstate;
  501. int event;
  502. void (*changefunc) (capidrv_contr * card, capidrv_plci * plci);
  503. };
  504. static struct plcistatechange plcitable[] =
  505. {
  506.   /* P-0 */
  507.   {ST_PLCI_NONE, ST_PLCI_OUTGOING, EV_PLCI_CONNECT_REQ, 0},
  508.   {ST_PLCI_NONE, ST_PLCI_ALLOCATED, EV_PLCI_FACILITY_IND_UP, 0},
  509.   {ST_PLCI_NONE, ST_PLCI_INCOMING, EV_PLCI_CONNECT_IND, 0},
  510.   {ST_PLCI_NONE, ST_PLCI_RESUMEING, EV_PLCI_RESUME_REQ, 0},
  511.   /* P-0.1 */
  512.   {ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0},
  513.   {ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, 0},
  514.   /* P-1 */
  515.   {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},
  516.   {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
  517.   {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
  518.   {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
  519.   /* P-ACT */
  520.   {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
  521.   {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
  522.   {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
  523.   {ST_PLCI_ACTIVE, ST_PLCI_HELD, EV_PLCI_HOLD_IND, 0},
  524.   {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_SUSPEND_IND, 0},
  525.   /* P-2 */
  526.   {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},
  527.   {ST_PLCI_INCOMING, ST_PLCI_FACILITY_IND, EV_PLCI_FACILITY_IND_UP, 0},
  528.   {ST_PLCI_INCOMING, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_RESP, 0},
  529.   {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
  530.   {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
  531.   {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
  532.   {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CD_IND, 0},
  533.   /* P-3 */
  534.   {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},
  535.   {ST_PLCI_FACILITY_IND, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_ACTIVE_IND, 0},
  536.   {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
  537.   {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
  538.   {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
  539.   /* P-4 */
  540.   {ST_PLCI_ACCEPTING, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},
  541.   {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
  542.   {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
  543.   {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
  544.   /* P-5 */
  545.   {ST_PLCI_DISCONNECTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
  546.   /* P-6 */
  547.   {ST_PLCI_DISCONNECTED, ST_PLCI_NONE, EV_PLCI_DISCONNECT_RESP, p0},
  548.   /* P-0.Res */
  549.   {ST_PLCI_RESUMEING, ST_PLCI_NONE, EV_PLCI_RESUME_CONF_ERROR, p0},
  550.   {ST_PLCI_RESUMEING, ST_PLCI_RESUME, EV_PLCI_RESUME_CONF_OK, 0},
  551.   /* P-RES */
  552.   {ST_PLCI_RESUME, ST_PLCI_ACTIVE, EV_PLCI_RESUME_IND, 0},
  553.   /* P-HELD */
  554.   {ST_PLCI_HELD, ST_PLCI_ACTIVE, EV_PLCI_RETRIEVE_IND, 0},
  555.   {},
  556. };
  557. static void plci_change_state(capidrv_contr * card, capidrv_plci * plci, int event)
  558. {
  559. struct plcistatechange *p = plcitable;
  560. while (p->event) {
  561. if (plci->state == p->actstate && p->event == event) {
  562. if (debugmode)
  563. printk(KERN_DEBUG "capidrv-%d: plci_change_state:0x%x %d -> %dn",
  564.   card->contrnr, plci->plci, plci->state, p->nextstate);
  565. plci->state = p->nextstate;
  566. if (p->changefunc)
  567. p->changefunc(card, plci);
  568. return;
  569. }
  570. p++;
  571. }
  572. printk(KERN_ERR "capidrv-%d: plci_change_state:0x%x state=%d event=%d ????n",
  573.        card->contrnr, plci->plci, plci->state, event);
  574. }
  575. /* ------------------------------------------------------------------ */
  576. static _cmsg cmsg;
  577. static void n0(capidrv_contr * card, capidrv_ncci * ncci)
  578. {
  579. isdn_ctrl cmd;
  580. capi_fill_DISCONNECT_REQ(&cmsg,
  581.  global.appid,
  582.  card->msgid++,
  583.  ncci->plcip->plci,
  584.  0, /* BChannelinformation */
  585.  0, /* Keypadfacility */
  586.  0, /* Useruserdata */   /* $$$$ */
  587.  0 /* Facilitydataarray */
  588. );
  589. send_message(card, &cmsg);
  590. plci_change_state(card, ncci->plcip, EV_PLCI_DISCONNECT_REQ);
  591. cmd.command = ISDN_STAT_BHUP;
  592. cmd.driver = card->myid;
  593. cmd.arg = ncci->chan;
  594. card->interface.statcallb(&cmd);
  595. free_ncci(card, ncci);
  596. }
  597. /* ------------------------------------------------------------------ */
  598. struct nccistatechange {
  599. int actstate;
  600. int nextstate;
  601. int event;
  602. void (*changefunc) (capidrv_contr * card, capidrv_ncci * ncci);
  603. };
  604. static struct nccistatechange nccitable[] =
  605. {
  606.   /* N-0 */
  607.   {ST_NCCI_NONE, ST_NCCI_OUTGOING, EV_NCCI_CONNECT_B3_REQ, 0},
  608.   {ST_NCCI_NONE, ST_NCCI_INCOMING, EV_NCCI_CONNECT_B3_IND, 0},
  609.   /* N-0.1 */
  610.   {ST_NCCI_OUTGOING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_CONF_OK, 0},
  611.   {ST_NCCI_OUTGOING, ST_NCCI_NONE, EV_NCCI_CONNECT_B3_CONF_ERROR, n0},
  612.   /* N-1 */
  613.   {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_CONNECT_B3_REJECT, 0},
  614.   {ST_NCCI_INCOMING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_RESP, 0},
  615.   {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
  616.   {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
  617.   /* N-2 */
  618.   {ST_NCCI_ALLOCATED, ST_NCCI_ACTIVE, EV_NCCI_CONNECT_B3_ACTIVE_IND, 0},
  619.   {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
  620.   {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
  621.   /* N-ACT */
  622.   {ST_NCCI_ACTIVE, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0},
  623.   {ST_NCCI_ACTIVE, ST_NCCI_RESETING, EV_NCCI_RESET_B3_REQ, 0},
  624.   {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
  625.   {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
  626.   /* N-3 */
  627.   {ST_NCCI_RESETING, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0},
  628.   {ST_NCCI_RESETING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
  629.   {ST_NCCI_RESETING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
  630.   /* N-4 */
  631.   {ST_NCCI_DISCONNECTING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
  632.   {ST_NCCI_DISCONNECTING, ST_NCCI_PREVIOUS, EV_NCCI_DISCONNECT_B3_CONF_ERROR,0},
  633.   /* N-5 */
  634.   {ST_NCCI_DISCONNECTED, ST_NCCI_NONE, EV_NCCI_DISCONNECT_B3_RESP, n0},
  635.   {},
  636. };
  637. static void ncci_change_state(capidrv_contr * card, capidrv_ncci * ncci, int event)
  638. {
  639. struct nccistatechange *p = nccitable;
  640. while (p->event) {
  641. if (ncci->state == p->actstate && p->event == event) {
  642. if (debugmode)
  643. printk(KERN_DEBUG "capidrv-%d: ncci_change_state:0x%x %d -> %dn",
  644.   card->contrnr, ncci->ncci, ncci->state, p->nextstate);
  645. if (p->nextstate == ST_NCCI_PREVIOUS) {
  646. ncci->state = ncci->oldstate;
  647. ncci->oldstate = p->actstate;
  648. } else {
  649. ncci->oldstate = p->actstate;
  650. ncci->state = p->nextstate;
  651. }
  652. if (p->changefunc)
  653. p->changefunc(card, ncci);
  654. return;
  655. }
  656. p++;
  657. }
  658. printk(KERN_ERR "capidrv-%d: ncci_change_state:0x%x state=%d event=%d ????n",
  659.        card->contrnr, ncci->ncci, ncci->state, event);
  660. }
  661. /* ------------------------------------------------------------------- */
  662. static inline int new_bchan(capidrv_contr * card)
  663. {
  664. int i;
  665. for (i = 0; i < card->nbchan; i++) {
  666. if (card->bchans[i].plcip == 0) {
  667. card->bchans[i].disconnecting = 0;
  668. return i;
  669. }
  670. }
  671. return -1;
  672. }
  673. /* ------------------------------------------------------------------- */
  674. static void handle_controller(_cmsg * cmsg)
  675. {
  676. capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
  677. if (!card) {
  678. printk(KERN_ERR "capidrv: %s from unknown controller 0x%xn",
  679.        capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  680.        cmsg->adr.adrController & 0x7f);
  681. return;
  682. }
  683. switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {
  684. case CAPI_LISTEN_CONF: /* Controller */
  685. if (debugmode)
  686. printk(KERN_DEBUG "capidrv-%d: listenconf Info=0x%4x (%s) cipmask=0x%xn",
  687.        card->contrnr, cmsg->Info, capi_info2str(cmsg->Info), card->cipmask);
  688. if (cmsg->Info) {
  689. listen_change_state(card, EV_LISTEN_CONF_ERROR);
  690. } else if (card->cipmask == 0) {
  691. listen_change_state(card, EV_LISTEN_CONF_EMPTY);
  692. } else {
  693. listen_change_state(card, EV_LISTEN_CONF_OK);
  694. }
  695. break;
  696. case CAPI_MANUFACTURER_IND: /* Controller */
  697. if (   cmsg->ManuID == 0x214D5641
  698.     && cmsg->Class == 0
  699.     && cmsg->Function == 1) {
  700.    __u8  *data = cmsg->ManuData+3;
  701.    __u16  len = cmsg->ManuData[0];
  702.    __u16 layer;
  703.    int direction;
  704.    if (len == 255) {
  705.       len = (cmsg->ManuData[1] | (cmsg->ManuData[2] << 8));
  706.       data += 2;
  707.    }
  708.    len -= 2;
  709.    layer = ((*(data-1)) << 8) | *(data-2);
  710.    if (layer & 0x300)
  711. direction = (layer & 0x200) ? 0 : 1;
  712.    else direction = (layer & 0x800) ? 0 : 1;
  713.    if (layer & 0x0C00) {
  714.     if ((layer & 0xff) == 0x80) {
  715.            handle_dtrace_data(card, direction, 1, data, len);
  716.            break;
  717.     }
  718.    } else if ((layer & 0xff) < 0x80) {
  719.       handle_dtrace_data(card, direction, 0, data, len);
  720.       break;
  721.    }
  722.            printk(KERN_INFO "capidrv-%d: %s from controller 0x%x layer 0x%x, ignoredn",
  723.                         card->contrnr, 
  724. capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  725. cmsg->adr.adrController, layer);
  726.                    break;
  727. }
  728. goto ignored;
  729. case CAPI_MANUFACTURER_CONF: /* Controller */
  730. if (cmsg->ManuID == 0x214D5641) {
  731.    char *s = 0;
  732.    switch (cmsg->Class) {
  733.       case 0: break;
  734.       case 1: s = "unknown class"; break;
  735.       case 2: s = "unknown function"; break;
  736.       default: s = "unkown error"; break;
  737.    }
  738.    if (s)
  739.            printk(KERN_INFO "capidrv-%d: %s from controller 0x%x function %d: %sn",
  740. card->contrnr,
  741. capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  742. cmsg->adr.adrController,
  743. cmsg->Function, s);
  744.    break;
  745. }
  746. goto ignored;
  747. case CAPI_FACILITY_IND: /* Controller/plci/ncci */
  748. goto ignored;
  749. case CAPI_FACILITY_CONF: /* Controller/plci/ncci */
  750. goto ignored;
  751. case CAPI_INFO_IND: /* Controller/plci */
  752. goto ignored;
  753. case CAPI_INFO_CONF: /* Controller/plci */
  754. goto ignored;
  755. default:
  756. printk(KERN_ERR "capidrv-%d: got %s from controller 0x%x ???",
  757.        card->contrnr,
  758.        capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  759.        cmsg->adr.adrController);
  760. }
  761. return;
  762.       ignored:
  763. printk(KERN_INFO "capidrv-%d: %s from controller 0x%x ignoredn",
  764.        card->contrnr,
  765.        capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  766.        cmsg->adr.adrController);
  767. }
  768. static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
  769. {
  770. capidrv_plci *plcip;
  771. capidrv_bchan *bchan;
  772. isdn_ctrl cmd;
  773. int chan;
  774. if ((chan = new_bchan(card)) == -1) {
  775. printk(KERN_ERR "capidrv-%d: incoming call on not existing bchan ?n", card->contrnr);
  776. return;
  777. }
  778. bchan = &card->bchans[chan];
  779. if ((plcip = new_plci(card, chan)) == 0) {
  780. printk(KERN_ERR "capidrv-%d: incoming call: no memory, sorry.n", card->contrnr);
  781. return;
  782. }
  783. bchan->incoming = 1;
  784. plcip->plci = cmsg->adr.adrPLCI;
  785. plci_change_state(card, plcip, EV_PLCI_CONNECT_IND);
  786. cmd.command = ISDN_STAT_ICALL;
  787. cmd.driver = card->myid;
  788. cmd.arg = chan;
  789. memset(&cmd.parm.setup, 0, sizeof(cmd.parm.setup));
  790. strncpy(cmd.parm.setup.phone,
  791.         cmsg->CallingPartyNumber + 3,
  792. cmsg->CallingPartyNumber[0] - 2);
  793. strncpy(cmd.parm.setup.eazmsn,
  794.         cmsg->CalledPartyNumber + 2,
  795. cmsg->CalledPartyNumber[0] - 1);
  796. cmd.parm.setup.si1 = cip2si1(cmsg->CIPValue);
  797. cmd.parm.setup.si2 = cip2si2(cmsg->CIPValue);
  798. cmd.parm.setup.plan = cmsg->CallingPartyNumber[1];
  799. cmd.parm.setup.screen = cmsg->CallingPartyNumber[2];
  800. printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%sn", 
  801. card->contrnr,
  802. cmd.parm.setup.phone,
  803. cmd.parm.setup.si1,
  804. cmd.parm.setup.si2,
  805. cmd.parm.setup.eazmsn);
  806. if (cmd.parm.setup.si1 == 1 && cmd.parm.setup.si2 != 0) {
  807. printk(KERN_INFO "capidrv-%d: patching si2=%d to 0 for VBOXn", 
  808. card->contrnr,
  809. cmd.parm.setup.si2);
  810. cmd.parm.setup.si2 = 0;
  811. }
  812. switch (card->interface.statcallb(&cmd)) {
  813. case 0:
  814. case 3:
  815. /* No device matching this call.
  816.  * and isdn_common.c has send a HANGUP command
  817.  * which is ignored in state ST_PLCI_INCOMING,
  818.  * so we send RESP to ignore the call
  819.  */
  820. capi_cmsg_answer(cmsg);
  821. cmsg->Reject = 1; /* ignore */
  822. send_message(card, cmsg);
  823. plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
  824. printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s ignoredn",
  825. card->contrnr,
  826. cmd.parm.setup.phone,
  827. cmd.parm.setup.si1,
  828. cmd.parm.setup.si2,
  829. cmd.parm.setup.eazmsn);
  830. break;
  831. case 1:
  832. /* At least one device matching this call (RING on ttyI)
  833.  * HL-driver may send ALERTING on the D-channel in this
  834.  * case.
  835.  * really means: RING on ttyI or a net interface
  836.  * accepted this call already.
  837.  *
  838.  * If the call was accepted, state has already changed,
  839.  * and CONNECT_RESP already sent.
  840.  */
  841. if (plcip->state == ST_PLCI_INCOMING) {
  842. printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s tty alertingn",
  843. card->contrnr,
  844. cmd.parm.setup.phone,
  845. cmd.parm.setup.si1,
  846. cmd.parm.setup.si2,
  847. cmd.parm.setup.eazmsn);
  848. capi_fill_ALERT_REQ(cmsg,
  849.     global.appid,
  850.     card->msgid++,
  851.     plcip->plci, /* adr */
  852.     0, /* BChannelinformation */
  853.     0, /* Keypadfacility */
  854.     0, /* Useruserdata */
  855.     0 /* Facilitydataarray */
  856. );
  857. plcip->msgid = cmsg->Messagenumber;
  858. send_message(card, cmsg);
  859. } else {
  860. printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s on netdevn",
  861. card->contrnr,
  862. cmd.parm.setup.phone,
  863. cmd.parm.setup.si1,
  864. cmd.parm.setup.si2,
  865. cmd.parm.setup.eazmsn);
  866. }
  867. break;
  868. case 2: /* Call will be rejected. */
  869. capi_cmsg_answer(cmsg);
  870. cmsg->Reject = 2; /* reject call, normal call clearing */
  871. send_message(card, cmsg);
  872. plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
  873. break;
  874. default:
  875. /* An error happened. (Invalid parameters for example.) */
  876. capi_cmsg_answer(cmsg);
  877. cmsg->Reject = 8; /* reject call,
  878.    destination out of order */
  879. send_message(card, cmsg);
  880. plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
  881. break;
  882. }
  883. return;
  884. }
  885. static void handle_plci(_cmsg * cmsg)
  886. {
  887. capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
  888. capidrv_plci *plcip;
  889. isdn_ctrl cmd;
  890. if (!card) {
  891. printk(KERN_ERR "capidrv: %s from unknown controller 0x%xn",
  892.        capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  893.        cmsg->adr.adrController & 0x7f);
  894. return;
  895. }
  896. switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {
  897. case CAPI_DISCONNECT_IND: /* plci */
  898. if (cmsg->Reason) {
  899. printk(KERN_INFO "capidrv-%d: %s reason 0x%x (%s) for plci 0x%xn",
  900.    card->contrnr,
  901.    capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  902.        cmsg->Reason, capi_info2str(cmsg->Reason), cmsg->adr.adrPLCI);
  903. }
  904. if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI))) {
  905. capi_cmsg_answer(cmsg);
  906. send_message(card, cmsg);
  907. goto notfound;
  908. }
  909. card->bchans[plcip->chan].disconnecting = 1;
  910. plci_change_state(card, plcip, EV_PLCI_DISCONNECT_IND);
  911. capi_cmsg_answer(cmsg);
  912. send_message(card, cmsg);
  913. plci_change_state(card, plcip, EV_PLCI_DISCONNECT_RESP);
  914. break;
  915. case CAPI_DISCONNECT_CONF: /* plci */
  916. if (cmsg->Info) {
  917. printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%xn",
  918.    card->contrnr,
  919.    capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  920.        cmsg->Info, capi_info2str(cmsg->Info), 
  921.        cmsg->adr.adrPLCI);
  922. }
  923. if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
  924. goto notfound;
  925. card->bchans[plcip->chan].disconnecting = 1;
  926. break;
  927. case CAPI_ALERT_CONF: /* plci */
  928. if (cmsg->Info) {
  929. printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%xn",
  930.    card->contrnr,
  931.    capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  932.        cmsg->Info, capi_info2str(cmsg->Info), 
  933.        cmsg->adr.adrPLCI);
  934. }
  935. break;
  936. case CAPI_CONNECT_IND: /* plci */
  937. handle_incoming_call(card, cmsg);
  938. break;
  939. case CAPI_CONNECT_CONF: /* plci */
  940. if (cmsg->Info) {
  941. printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%xn",
  942.    card->contrnr,
  943.    capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  944.        cmsg->Info, capi_info2str(cmsg->Info), 
  945.        cmsg->adr.adrPLCI);
  946. }
  947. if (!(plcip = find_plci_by_msgid(card, cmsg->Messagenumber)))
  948. goto notfound;
  949. plcip->plci = cmsg->adr.adrPLCI;
  950. if (cmsg->Info) {
  951. plci_change_state(card, plcip, EV_PLCI_CONNECT_CONF_ERROR);
  952. } else {
  953. plci_change_state(card, plcip, EV_PLCI_CONNECT_CONF_OK);
  954. }
  955. break;
  956. case CAPI_CONNECT_ACTIVE_IND: /* plci */
  957. if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
  958. goto notfound;
  959. if (card->bchans[plcip->chan].incoming) {
  960. capi_cmsg_answer(cmsg);
  961. send_message(card, cmsg);
  962. plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND);
  963. } else {
  964. capidrv_ncci *nccip;
  965. capi_cmsg_answer(cmsg);
  966. send_message(card, cmsg);
  967. nccip = new_ncci(card, plcip, cmsg->adr.adrPLCI);
  968. if (!nccip) {
  969. printk(KERN_ERR "capidrv-%d: no mem for ncci, sorryn", card->contrnr);
  970. break; /* $$$$ */
  971. }
  972. capi_fill_CONNECT_B3_REQ(cmsg,
  973.  global.appid,
  974.  card->msgid++,
  975.  plcip->plci, /* adr */
  976.  0 /* NCPI */
  977. );
  978. nccip->msgid = cmsg->Messagenumber;
  979. send_message(card, cmsg);
  980. cmd.command = ISDN_STAT_DCONN;
  981. cmd.driver = card->myid;
  982. cmd.arg = plcip->chan;
  983. card->interface.statcallb(&cmd);
  984. plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND);
  985. ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_REQ);
  986. }
  987. break;
  988. case CAPI_INFO_IND: /* Controller/plci */
  989. if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
  990. goto notfound;
  991. if (cmsg->InfoNumber == 0x4000) {
  992. if (cmsg->InfoElement[0] == 4) {
  993. cmd.command = ISDN_STAT_CINF;
  994. cmd.driver = card->myid;
  995. cmd.arg = plcip->chan;
  996. sprintf(cmd.parm.num, "%lu",
  997. (unsigned long)
  998. ((__u32) cmsg->InfoElement[1]
  999.   | ((__u32) (cmsg->InfoElement[2]) << 8)
  1000.  | ((__u32) (cmsg->InfoElement[3]) << 16)
  1001.  | ((__u32) (cmsg->InfoElement[4]) << 24)));
  1002. card->interface.statcallb(&cmd);
  1003. break;
  1004. }
  1005. }
  1006. printk(KERN_ERR "capidrv-%d: %sn",
  1007. card->contrnr, capi_cmsg2str(cmsg));
  1008. break;
  1009. case CAPI_CONNECT_ACTIVE_CONF: /* plci */
  1010. goto ignored;
  1011. case CAPI_SELECT_B_PROTOCOL_CONF: /* plci */
  1012. goto ignored;
  1013. case CAPI_FACILITY_IND: /* Controller/plci/ncci */
  1014. goto ignored;
  1015. case CAPI_FACILITY_CONF: /* Controller/plci/ncci */
  1016. goto ignored;
  1017. case CAPI_INFO_CONF: /* Controller/plci */
  1018. goto ignored;
  1019. default:
  1020. printk(KERN_ERR "capidrv-%d: got %s for plci 0x%x ???",
  1021.        card->contrnr,
  1022.        capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  1023.        cmsg->adr.adrPLCI);
  1024. }
  1025. return;
  1026.       ignored:
  1027. printk(KERN_INFO "capidrv-%d: %s for plci 0x%x ignoredn",
  1028.        card->contrnr,
  1029.        capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  1030.        cmsg->adr.adrPLCI);
  1031. return;
  1032.       notfound:
  1033. printk(KERN_ERR "capidrv-%d: %s: plci 0x%x not foundn",
  1034.        card->contrnr,
  1035.        capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  1036.        cmsg->adr.adrPLCI);
  1037. return;
  1038. }
  1039. static void handle_ncci(_cmsg * cmsg)
  1040. {
  1041. capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
  1042. capidrv_plci *plcip;
  1043. capidrv_ncci *nccip;
  1044. isdn_ctrl cmd;
  1045. int len;
  1046. if (!card) {
  1047. printk(KERN_ERR "capidrv: %s from unknown controller 0x%xn",
  1048.        capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  1049.        cmsg->adr.adrController & 0x7f);
  1050. return;
  1051. }
  1052. switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {
  1053. case CAPI_CONNECT_B3_ACTIVE_IND: /* ncci */
  1054. if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
  1055. goto notfound;
  1056. capi_cmsg_answer(cmsg);
  1057. send_message(card, cmsg);
  1058. ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_ACTIVE_IND);
  1059. cmd.command = ISDN_STAT_BCONN;
  1060. cmd.driver = card->myid;
  1061. cmd.arg = nccip->chan;
  1062. card->interface.statcallb(&cmd);
  1063. printk(KERN_INFO "capidrv-%d: chan %d up with ncci 0x%xn",
  1064.        card->contrnr, nccip->chan, nccip->ncci);
  1065. break;
  1066. case CAPI_CONNECT_B3_ACTIVE_CONF: /* ncci */
  1067. goto ignored;
  1068. case CAPI_CONNECT_B3_IND: /* ncci */
  1069. plcip = find_plci_by_ncci(card, cmsg->adr.adrNCCI);
  1070. if (plcip) {
  1071. nccip = new_ncci(card, plcip, cmsg->adr.adrNCCI);
  1072. if (nccip) {
  1073. ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_IND);
  1074. capi_fill_CONNECT_B3_RESP(cmsg,
  1075.   global.appid,
  1076.   card->msgid++,
  1077.   nccip->ncci, /* adr */
  1078.   0, /* Reject */
  1079.   0 /* NCPI */
  1080. );
  1081. send_message(card, cmsg);
  1082. ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP);
  1083. break;
  1084. }
  1085. printk(KERN_ERR "capidrv-%d: no mem for ncci, sorryn", card->contrnr);
  1086. } else {
  1087. printk(KERN_ERR "capidrv-%d: %s: plci for ncci 0x%x not foundn",
  1088.    card->contrnr,
  1089.    capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  1090.        cmsg->adr.adrNCCI);
  1091. }
  1092. capi_fill_CONNECT_B3_RESP(cmsg,
  1093.   global.appid,
  1094.   card->msgid++,
  1095.   cmsg->adr.adrNCCI,
  1096.   2, /* Reject */
  1097.   0 /* NCPI */
  1098. );
  1099. send_message(card, cmsg);
  1100. break;
  1101. case CAPI_CONNECT_B3_CONF: /* ncci */
  1102. if (!(nccip = find_ncci_by_msgid(card,
  1103.  cmsg->adr.adrNCCI,
  1104.  cmsg->Messagenumber)))
  1105. goto notfound;
  1106. nccip->ncci = cmsg->adr.adrNCCI;
  1107. if (cmsg->Info) {
  1108. printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%xn",
  1109.    card->contrnr,
  1110.    capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  1111.        cmsg->Info, capi_info2str(cmsg->Info), 
  1112.        cmsg->adr.adrNCCI);
  1113. }
  1114. if (cmsg->Info)
  1115. ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_CONF_ERROR);
  1116. else
  1117. ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_CONF_OK);
  1118. break;
  1119. case CAPI_CONNECT_B3_T90_ACTIVE_IND: /* ncci */
  1120. capi_cmsg_answer(cmsg);
  1121. send_message(card, cmsg);
  1122. break;
  1123. case CAPI_DATA_B3_IND: /* ncci */
  1124. /* handled in handle_data() */
  1125. goto ignored;
  1126. case CAPI_DATA_B3_CONF: /* ncci */
  1127. if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
  1128. goto notfound;
  1129. len = capidrv_del_ack(nccip, cmsg->DataHandle);
  1130. if (len < 0)
  1131. break;
  1132.         cmd.command = ISDN_STAT_BSENT;
  1133.         cmd.driver = card->myid;
  1134.         cmd.arg = nccip->chan;
  1135. cmd.parm.length = len;
  1136.         card->interface.statcallb(&cmd);
  1137. break;
  1138. case CAPI_DISCONNECT_B3_IND: /* ncci */
  1139. if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
  1140. goto notfound;
  1141. card->bchans[nccip->chan].disconnecting = 1;
  1142. ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_IND);
  1143. capi_cmsg_answer(cmsg);
  1144. send_message(card, cmsg);
  1145. ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_RESP);
  1146. break;
  1147. case CAPI_DISCONNECT_B3_CONF: /* ncci */
  1148. if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
  1149. goto notfound;
  1150. if (cmsg->Info) {
  1151. printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%xn",
  1152.    card->contrnr,
  1153.    capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  1154.        cmsg->Info, capi_info2str(cmsg->Info), 
  1155.        cmsg->adr.adrNCCI);
  1156. ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_CONF_ERROR);
  1157. }
  1158. break;
  1159. case CAPI_RESET_B3_IND: /* ncci */
  1160. if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
  1161. goto notfound;
  1162. ncci_change_state(card, nccip, EV_NCCI_RESET_B3_IND);
  1163. capi_cmsg_answer(cmsg);
  1164. send_message(card, cmsg);
  1165. break;
  1166. case CAPI_RESET_B3_CONF: /* ncci */
  1167. goto ignored; /* $$$$ */
  1168. case CAPI_FACILITY_IND: /* Controller/plci/ncci */
  1169. goto ignored;
  1170. case CAPI_FACILITY_CONF: /* Controller/plci/ncci */
  1171. goto ignored;
  1172. default:
  1173. printk(KERN_ERR "capidrv-%d: got %s for ncci 0x%x ???",
  1174.        card->contrnr,
  1175.        capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  1176.        cmsg->adr.adrNCCI);
  1177. }
  1178. return;
  1179.       ignored:
  1180. printk(KERN_INFO "capidrv-%d: %s for ncci 0x%x ignoredn",
  1181.        card->contrnr,
  1182.        capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  1183.        cmsg->adr.adrNCCI);
  1184. return;
  1185.       notfound:
  1186. printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not foundn",
  1187.        card->contrnr,
  1188.        capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  1189.        cmsg->adr.adrNCCI);
  1190. }
  1191. static void handle_data(_cmsg * cmsg, struct sk_buff *skb)
  1192. {
  1193. capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
  1194. capidrv_ncci *nccip;
  1195. if (!card) {
  1196. printk(KERN_ERR "capidrv: %s from unknown controller 0x%xn",
  1197.        capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  1198.        cmsg->adr.adrController & 0x7f);
  1199. kfree_skb(skb);
  1200. return;
  1201. }
  1202. if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) {
  1203. printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not foundn",
  1204.        card->contrnr,
  1205.        capi_cmd2str(cmsg->Command, cmsg->Subcommand),
  1206.        cmsg->adr.adrNCCI);
  1207. kfree_skb(skb);
  1208. return;
  1209. }
  1210. (void) skb_pull(skb, CAPIMSG_LEN(skb->data));
  1211. card->interface.rcvcallb_skb(card->myid, nccip->chan, skb);
  1212. capi_cmsg_answer(cmsg);
  1213. send_message(card, cmsg);
  1214. }
  1215. static _cmsg s_cmsg;
  1216. static void capidrv_signal(__u16 applid, void *dummy)
  1217. {
  1218. struct sk_buff *skb = 0;
  1219. while ((*capifuncs->capi_get_message) (global.appid, &skb) == CAPI_NOERROR) {
  1220. capi_message2cmsg(&s_cmsg, skb->data);
  1221. if (debugmode > 2)
  1222. printk(KERN_DEBUG "capidrv_signal: applid=%d %sn",
  1223. applid, capi_cmsg2str(&s_cmsg));
  1224. if (s_cmsg.Command == CAPI_DATA_B3
  1225.     && s_cmsg.Subcommand == CAPI_IND) {
  1226. handle_data(&s_cmsg, skb);
  1227. global.nrecvdatapkt++;
  1228. continue;
  1229. }
  1230. if ((s_cmsg.adr.adrController & 0xffffff00) == 0)
  1231. handle_controller(&s_cmsg);
  1232. else if ((s_cmsg.adr.adrPLCI & 0xffff0000) == 0)
  1233. handle_plci(&s_cmsg);
  1234. else
  1235. handle_ncci(&s_cmsg);
  1236. /*
  1237.  * data of skb used in s_cmsg,
  1238.  * free data when s_cmsg is not used again
  1239.  * thanks to Lars Heete <hel@admin.de>
  1240.  */
  1241. kfree_skb(skb);
  1242. global.nrecvctlpkt++;
  1243. }
  1244. }
  1245. /* ------------------------------------------------------------------- */
  1246. #define PUTBYTE_TO_STATUS(card, byte) 
  1247. do { 
  1248. *(card)->q931_write++ = (byte); 
  1249.          if ((card)->q931_write > (card)->q931_end) 
  1250.    (card)->q931_write = (card)->q931_buf; 
  1251. } while (0)
  1252. static void handle_dtrace_data(capidrv_contr *card,
  1253.      int send, int level2, __u8 *data, __u16 len)
  1254. {
  1255.      __u8 *p, *end;
  1256.      isdn_ctrl cmd;
  1257.      if (!len) {
  1258. printk(KERN_DEBUG "capidrv-%d: avmb1_q931_data: len == %dn",
  1259. card->contrnr, len);
  1260. return;
  1261. }
  1262. if (level2) {
  1263. PUTBYTE_TO_STATUS(card, 'D');
  1264. PUTBYTE_TO_STATUS(card, '2');
  1265.          PUTBYTE_TO_STATUS(card, send ? '>' : '<');
  1266.          PUTBYTE_TO_STATUS(card, ':');
  1267. } else {
  1268.          PUTBYTE_TO_STATUS(card, 'D');
  1269.          PUTBYTE_TO_STATUS(card, '3');
  1270.          PUTBYTE_TO_STATUS(card, send ? '>' : '<');
  1271.          PUTBYTE_TO_STATUS(card, ':');
  1272.      }
  1273. for (p = data, end = data+len; p < end; p++) {
  1274. __u8 w;
  1275. PUTBYTE_TO_STATUS(card, ' ');
  1276. w = (*p >> 4) & 0xf;
  1277. PUTBYTE_TO_STATUS(card, (w < 10) ? '0'+w : 'A'-10+w);
  1278. w = *p & 0xf;
  1279. PUTBYTE_TO_STATUS(card, (w < 10) ? '0'+w : 'A'-10+w);
  1280. }
  1281. PUTBYTE_TO_STATUS(card, 'n');
  1282. cmd.command = ISDN_STAT_STAVAIL;
  1283. cmd.driver = card->myid;
  1284. cmd.arg = len*3+5;
  1285. card->interface.statcallb(&cmd);
  1286. }
  1287. /* ------------------------------------------------------------------- */
  1288. static _cmsg cmdcmsg;
  1289. static int capidrv_ioctl(isdn_ctrl * c, capidrv_contr * card)
  1290. {
  1291. switch (c->arg) {
  1292. case 1:
  1293. debugmode = (int)(*((unsigned int *)c->parm.num));
  1294. printk(KERN_DEBUG "capidrv-%d: debugmode=%dn",
  1295. card->contrnr, debugmode);
  1296. return 0;
  1297. default:
  1298. printk(KERN_DEBUG "capidrv-%d: capidrv_ioctl(%ld) called ??n",
  1299. card->contrnr, c->arg);
  1300. return -EINVAL;
  1301. }
  1302. return -EINVAL;
  1303. }
  1304. /*
  1305.  * Handle leased lines (CAPI-Bundling)
  1306.  */
  1307. struct internal_bchannelinfo {
  1308.    unsigned short channelalloc;
  1309.    unsigned short operation;
  1310.    unsigned char  cmask[31];
  1311. };
  1312. static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep)
  1313. {
  1314. unsigned long bmask = 0;
  1315. int active = !0;
  1316. char *s;
  1317. int i;
  1318. if (strncmp(teln, "FV:", 3) != 0)
  1319. return 1;
  1320. s = teln + 3;
  1321. while (*s && *s == ' ') s++;
  1322. if (!*s) return -2;
  1323. if (*s == 'p' || *s == 'P') {
  1324. active = 0;
  1325. s++;
  1326. }
  1327. if (*s == 'a' || *s == 'A') {
  1328. active = !0;
  1329. s++;
  1330. }
  1331. while (*s) {
  1332. int digit1 = 0;
  1333. int digit2 = 0;
  1334. if (!isdigit(*s)) return -3;
  1335. while (isdigit(*s)) { digit1 = digit1*10 + (*s - '0'); s++; }
  1336. if (digit1 <= 0 && digit1 > 30) return -4;
  1337. if (*s == 0 || *s == ',' || *s == ' ') {
  1338. bmask |= (1 << digit1);
  1339. digit1 = 0;
  1340. if (*s) s++;
  1341. continue;
  1342. }
  1343. if (*s != '-') return -5;
  1344. s++;
  1345. if (!isdigit(*s)) return -3;
  1346. while (isdigit(*s)) { digit2 = digit2*10 + (*s - '0'); s++; }
  1347. if (digit2 <= 0 && digit2 > 30) return -4;
  1348. if (*s == 0 || *s == ',' || *s == ' ') {
  1349. if (digit1 > digit2)
  1350. for (i = digit2; i <= digit1 ; i++)
  1351. bmask |= (1 << i);
  1352. else 
  1353. for (i = digit1; i <= digit2 ; i++)
  1354. bmask |= (1 << i);
  1355. digit1 = digit2 = 0;
  1356. if (*s) s++;
  1357. continue;
  1358. }
  1359. return -6;
  1360. }
  1361. if (activep) *activep = active;
  1362. if (bmaskp) *bmaskp = bmask;
  1363. return 0;
  1364. }
  1365. static int FVteln2capi20(char *teln, __u8 AdditionalInfo[1+2+2+31])
  1366. {
  1367. unsigned long bmask;
  1368. int active;
  1369. int rc, i;
  1370.    
  1371. rc = decodeFVteln(teln, &bmask, &active);
  1372. if (rc) return rc;
  1373. /* Length */
  1374. AdditionalInfo[0] = 2+2+31;
  1375.         /* Channel: 3 => use channel allocation */
  1376.         AdditionalInfo[1] = 3; AdditionalInfo[2] = 0;
  1377. /* Operation: 0 => DTE mode, 1 => DCE mode */
  1378.         if (active) {
  1379.     AdditionalInfo[3] = 0; AdditionalInfo[4] = 0;
  1380.     } else {
  1381.     AdditionalInfo[3] = 1; AdditionalInfo[4] = 0;
  1382. }
  1383. /* Channel mask array */
  1384. AdditionalInfo[5] = 0; /* no D-Channel */
  1385. for (i=1; i <= 30; i++)
  1386. AdditionalInfo[5+i] = (bmask & (1 << i)) ? 0xff : 0;
  1387. return 0;
  1388. }
  1389. static int capidrv_command(isdn_ctrl * c, capidrv_contr * card)
  1390. {
  1391. isdn_ctrl cmd;
  1392. struct capidrv_bchan *bchan;
  1393. struct capidrv_plci *plcip;
  1394. __u8 AdditionalInfo[1+2+2+31];
  1395.         int rc, isleasedline = 0;
  1396. if (c->command == ISDN_CMD_IOCTL)
  1397. return capidrv_ioctl(c, card);
  1398. switch (c->command) {
  1399. case ISDN_CMD_DIAL:{
  1400. __u8 calling[ISDN_MSNLEN + 3];
  1401. __u8 called[ISDN_MSNLEN + 2];
  1402. if (debugmode)
  1403. printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_DIAL(ch=%ld,"%s,%d,%d,%s")n",
  1404. card->contrnr,
  1405. c->arg,
  1406.         c->parm.setup.phone,
  1407.         c->parm.setup.si1,
  1408.         c->parm.setup.si2,
  1409.         c->parm.setup.eazmsn);
  1410. bchan = &card->bchans[c->arg % card->nbchan];
  1411. if (bchan->plcip) {
  1412. printk(KERN_ERR "capidrv-%d: dail ch=%ld,"%s,%d,%d,%s" in use (plci=0x%x)n",
  1413. card->contrnr,
  1414.          c->arg, 
  1415.         c->parm.setup.phone,
  1416.         c->parm.setup.si1,
  1417.         c->parm.setup.si2,
  1418.         c->parm.setup.eazmsn,
  1419.         bchan->plcip->plci);
  1420. return 0;
  1421. }
  1422. bchan->si1 = c->parm.setup.si1;
  1423. bchan->si2 = c->parm.setup.si2;
  1424. strncpy(bchan->num, c->parm.setup.phone, sizeof(bchan->num));
  1425. strncpy(bchan->mynum, c->parm.setup.eazmsn, sizeof(bchan->mynum));
  1426.                         rc = FVteln2capi20(bchan->num, AdditionalInfo);
  1427. isleasedline = (rc == 0);
  1428. if (rc < 0)
  1429. printk(KERN_ERR "capidrv-%d: WARNING: illegal leased linedefinition "%s"n", card->contrnr, bchan->num);
  1430. if (isleasedline) {
  1431. calling[0] = 0;
  1432. called[0] = 0;
  1433.         if (debugmode)
  1434. printk(KERN_DEBUG "capidrv-%d: connecting leased linen", card->contrnr);
  1435. } else {
  1436.          calling[0] = strlen(bchan->mynum) + 2;
  1437.          calling[1] = 0;
  1438.       calling[2] = 0x80;
  1439.     strncpy(calling + 3, bchan->mynum, ISDN_MSNLEN);
  1440. called[0] = strlen(bchan->num) + 1;
  1441. called[1] = 0x80;
  1442. strncpy(called + 2, bchan->num, ISDN_MSNLEN);
  1443. }
  1444. capi_fill_CONNECT_REQ(&cmdcmsg,
  1445.       global.appid,
  1446.       card->msgid++,
  1447.       card->contrnr, /* adr */
  1448.   si2cip(bchan->si1, bchan->si2), /* cipvalue */
  1449.       called, /* CalledPartyNumber */
  1450.       calling, /* CallingPartyNumber */
  1451.       0, /* CalledPartySubaddress */
  1452.       0, /* CallingPartySubaddress */
  1453.     b1prot(bchan->l2, bchan->l3), /* B1protocol */
  1454.     b2prot(bchan->l2, bchan->l3), /* B2protocol */
  1455.     b3prot(bchan->l2, bchan->l3), /* B3protocol */
  1456.     b1config(bchan->l2, bchan->l3), /* B1configuration */
  1457.       0, /* B2configuration */
  1458.       0, /* B3configuration */
  1459.       0, /* BC */
  1460.       0, /* LLC */
  1461.       0, /* HLC */
  1462.       /* BChannelinformation */
  1463.       isleasedline ? AdditionalInfo : 0,
  1464.       0, /* Keypadfacility */
  1465.       0, /* Useruserdata */
  1466.       0 /* Facilitydataarray */
  1467.     );
  1468. if ((plcip = new_plci(card, (c->arg % card->nbchan))) == 0) {
  1469. cmd.command = ISDN_STAT_DHUP;
  1470. cmd.driver = card->myid;
  1471. cmd.arg = (c->arg % card->nbchan);
  1472. card->interface.statcallb(&cmd);
  1473. return -1;
  1474. }
  1475. plcip->msgid = cmdcmsg.Messagenumber;
  1476. plcip->leasedline = isleasedline;
  1477. plci_change_state(card, plcip, EV_PLCI_CONNECT_REQ);
  1478. send_message(card, &cmdcmsg);
  1479. return 0;
  1480. }
  1481. case ISDN_CMD_ACCEPTD:
  1482. bchan = &card->bchans[c->arg % card->nbchan];
  1483. if (debugmode)
  1484. printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTD(ch=%ld) l2=%d l3=%dn",
  1485.        card->contrnr,
  1486.        c->arg, bchan->l2, bchan->l3);
  1487. capi_fill_CONNECT_RESP(&cmdcmsg,
  1488.        global.appid,
  1489.        card->msgid++,
  1490.        bchan->plcip->plci, /* adr */
  1491.        0, /* Reject */
  1492.        b1prot(bchan->l2, bchan->l3), /* B1protocol */
  1493.        b2prot(bchan->l2, bchan->l3), /* B2protocol */
  1494.        b3prot(bchan->l2, bchan->l3), /* B3protocol */
  1495.        b1config(bchan->l2, bchan->l3), /* B1configuration */
  1496.        0, /* B2configuration */
  1497.        0, /* B3configuration */
  1498.        0, /* ConnectedNumber */
  1499.        0, /* ConnectedSubaddress */
  1500.        0, /* LLC */
  1501.        0, /* BChannelinformation */
  1502.        0, /* Keypadfacility */
  1503.        0, /* Useruserdata */
  1504.        0 /* Facilitydataarray */
  1505. );
  1506. capi_cmsg2message(&cmdcmsg, cmdcmsg.buf);
  1507. plci_change_state(card, bchan->plcip, EV_PLCI_CONNECT_RESP);
  1508. send_message(card, &cmdcmsg);
  1509. return 0;
  1510. case ISDN_CMD_ACCEPTB:
  1511. if (debugmode)
  1512. printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTB(ch=%ld)n",
  1513.        card->contrnr,
  1514.        c->arg);
  1515. return -ENOSYS;
  1516. case ISDN_CMD_HANGUP:
  1517. if (debugmode)
  1518. printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_HANGUP(ch=%ld)n",
  1519.        card->contrnr,
  1520.        c->arg);
  1521. bchan = &card->bchans[c->arg % card->nbchan];
  1522. if (bchan->disconnecting) {
  1523. if (debugmode)
  1524. printk(KERN_DEBUG "capidrv-%d: chan %ld already disconnecting ...n",
  1525.        card->contrnr,
  1526.        c->arg);
  1527. return 0;
  1528. }
  1529. if (bchan->nccip) {
  1530. bchan->disconnecting = 1;
  1531. capi_fill_DISCONNECT_B3_REQ(&cmdcmsg,
  1532.     global.appid,
  1533.     card->msgid++,
  1534.     bchan->nccip->ncci,
  1535.     0 /* NCPI */
  1536. );
  1537. ncci_change_state(card, bchan->nccip, EV_NCCI_DISCONNECT_B3_REQ);
  1538. send_message(card, &cmdcmsg);
  1539. return 0;
  1540. } else if (bchan->plcip) {
  1541. if (bchan->plcip->state == ST_PLCI_INCOMING) {
  1542. /*
  1543.  * just ignore, we a called from
  1544.  * isdn_status_callback(),
  1545.  * which will return 0 or 2, this is handled
  1546.  * by the CONNECT_IND handler
  1547.  */
  1548. bchan->disconnecting = 1;
  1549. return 0;
  1550. } else if (bchan->plcip->plci) {
  1551. bchan->disconnecting = 1;
  1552. capi_fill_DISCONNECT_REQ(&cmdcmsg,
  1553.  global.appid,
  1554.  card->msgid++,
  1555.       bchan->plcip->plci,
  1556.  0, /* BChannelinformation */
  1557.  0, /* Keypadfacility */
  1558.  0, /* Useruserdata */
  1559.  0 /* Facilitydataarray */
  1560. );
  1561. plci_change_state(card, bchan->plcip, EV_PLCI_DISCONNECT_REQ);
  1562. send_message(card, &cmdcmsg);
  1563. return 0;
  1564. } else {
  1565. printk(KERN_ERR "capidrv-%d: chan %ld disconnect request while waiting for CONNECT_CONFn",
  1566.        card->contrnr,
  1567.        c->arg);
  1568. return -EINVAL;
  1569. }
  1570. }
  1571. printk(KERN_ERR "capidrv-%d: chan %ld disconnect request on free channeln",
  1572.        card->contrnr,
  1573.        c->arg);
  1574. return -EINVAL;
  1575. /* ready */
  1576. case ISDN_CMD_SETL2:
  1577. if (debugmode)
  1578. printk(KERN_DEBUG "capidrv-%d: set L2 on chan %ld to %ldn",
  1579.        card->contrnr,
  1580.        (c->arg & 0xff), (c->arg >> 8));
  1581. bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];
  1582. bchan->l2 = (c->arg >> 8);
  1583. return 0;
  1584. case ISDN_CMD_SETL3:
  1585. if (debugmode)
  1586. printk(KERN_DEBUG "capidrv-%d: set L3 on chan %ld to %ldn",
  1587.        card->contrnr,
  1588.        (c->arg & 0xff), (c->arg >> 8));
  1589. bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];
  1590. bchan->l3 = (c->arg >> 8);
  1591. return 0;
  1592. case ISDN_CMD_SETEAZ:
  1593. if (debugmode)
  1594. printk(KERN_DEBUG "capidrv-%d: set EAZ "%s" on chan %ldn",
  1595.        card->contrnr,
  1596.        c->parm.num, c->arg);
  1597. bchan = &card->bchans[c->arg % card->nbchan];
  1598. strncpy(bchan->msn, c->parm.num, ISDN_MSNLEN);
  1599. return 0;
  1600. case ISDN_CMD_CLREAZ:
  1601. if (debugmode)
  1602. printk(KERN_DEBUG "capidrv-%d: clearing EAZ on chan %ldn",
  1603. card->contrnr, c->arg);
  1604. bchan = &card->bchans[c->arg % card->nbchan];
  1605. bchan->msn[0] = 0;
  1606. return 0;
  1607. case ISDN_CMD_LOCK:
  1608. if (debugmode > 1)
  1609. printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_LOCK (%ld)n", card->contrnr, c->arg);
  1610. MOD_INC_USE_COUNT;
  1611. break;
  1612. case ISDN_CMD_UNLOCK:
  1613. if (debugmode > 1)
  1614. printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_UNLOCK (%ld)n",
  1615. card->contrnr, c->arg);
  1616. MOD_DEC_USE_COUNT;
  1617. break;
  1618. /* never called */
  1619. case ISDN_CMD_GETL2:
  1620. if (debugmode)
  1621. printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL2n",
  1622. card->contrnr);
  1623. return -ENODEV;
  1624. case ISDN_CMD_GETL3:
  1625. if (debugmode)
  1626. printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL3n",
  1627. card->contrnr);
  1628. return -ENODEV;
  1629. case ISDN_CMD_GETEAZ:
  1630. if (debugmode)
  1631. printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETEAZn",
  1632. card->contrnr);
  1633. return -ENODEV;
  1634. case ISDN_CMD_SETSIL:
  1635. if (debugmode)
  1636. printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_SETSILn",
  1637. card->contrnr);
  1638. return -ENODEV;
  1639. case ISDN_CMD_GETSIL:
  1640. if (debugmode)
  1641. printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETSILn",
  1642. card->contrnr);
  1643. return -ENODEV;
  1644. default:
  1645. printk(KERN_ERR "capidrv-%d: ISDN_CMD_%d, Huh?n",
  1646. card->contrnr, c->command);
  1647. return -EINVAL;
  1648. }
  1649. return 0;
  1650. }
  1651. static int if_command(isdn_ctrl * c)
  1652. {
  1653. capidrv_contr *card = findcontrbydriverid(c->driver);
  1654. if (card)
  1655. return capidrv_command(c, card);
  1656. printk(KERN_ERR
  1657.      "capidrv: if_command %d called with invalid driverId %d!n",
  1658. c->command, c->driver);
  1659. return -ENODEV;
  1660. }
  1661. static _cmsg sendcmsg;
  1662. static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb)
  1663. {
  1664. capidrv_contr *card = findcontrbydriverid(id);
  1665. capidrv_bchan *bchan;
  1666. capidrv_ncci *nccip;
  1667. int len = skb->len;
  1668. size_t msglen;
  1669. __u16 errcode;
  1670. __u16 datahandle;
  1671. if (!card) {
  1672. printk(KERN_ERR "capidrv: if_sendbuf called with invalid driverId %d!n",
  1673.        id);
  1674. return 0;
  1675. }
  1676. if (debugmode > 1)
  1677. printk(KERN_DEBUG "capidrv-%d: sendbuf len=%d skb=%p doack=%dn",
  1678. card->contrnr, len, skb, doack);
  1679. bchan = &card->bchans[channel % card->nbchan];
  1680. nccip = bchan->nccip;
  1681. if (!nccip || nccip->state != ST_NCCI_ACTIVE) {
  1682. printk(KERN_ERR "capidrv-%d: if_sendbuf: %s:%d: chan not up!n",
  1683.        card->contrnr, card->name, channel);
  1684. return 0;
  1685. }
  1686. datahandle = nccip->datahandle;
  1687. capi_fill_DATA_B3_REQ(&sendcmsg, global.appid, card->msgid++,
  1688.       nccip->ncci, /* adr */
  1689.       (__u32) skb->data, /* Data */
  1690.       skb->len, /* DataLength */
  1691.       datahandle, /* DataHandle */
  1692.       0 /* Flags */
  1693.     );
  1694. if (capidrv_add_ack(nccip, datahandle, doack ? skb->len : -1) < 0)
  1695.    return 0;
  1696. capi_cmsg2message(&sendcmsg, sendcmsg.buf);
  1697. msglen = CAPIMSG_LEN(sendcmsg.buf);
  1698. if (skb_headroom(skb) < msglen) {
  1699. struct sk_buff *nskb = skb_realloc_headroom(skb, msglen);
  1700. if (!nskb) {
  1701. printk(KERN_ERR "capidrv-%d: if_sendbuf: no memoryn",
  1702. card->contrnr);
  1703.         (void)capidrv_del_ack(nccip, datahandle);
  1704. return 0;
  1705. }
  1706. printk(KERN_DEBUG "capidrv-%d: only %d bytes headroom, need %dn",
  1707.        card->contrnr, skb_headroom(skb), msglen);
  1708. memcpy(skb_push(nskb, msglen), sendcmsg.buf, msglen);
  1709. errcode = (*capifuncs->capi_put_message) (global.appid, nskb);
  1710. if (errcode == CAPI_NOERROR) {
  1711. dev_kfree_skb(skb);
  1712. nccip->datahandle++;
  1713. global.nsentdatapkt++;
  1714. return len;
  1715. }
  1716.         (void)capidrv_del_ack(nccip, datahandle);
  1717.         dev_kfree_skb(nskb);
  1718. return errcode == CAPI_SENDQUEUEFULL ? 0 : -1;
  1719. } else {
  1720. memcpy(skb_push(skb, msglen), sendcmsg.buf, msglen);
  1721. errcode = (*capifuncs->capi_put_message) (global.appid, skb);
  1722. if (errcode == CAPI_NOERROR) {
  1723. nccip->datahandle++;
  1724. global.nsentdatapkt++;
  1725. return len;
  1726. }
  1727. skb_pull(skb, msglen);
  1728.         (void)capidrv_del_ack(nccip, datahandle);
  1729. return errcode == CAPI_SENDQUEUEFULL ? 0 : -1;
  1730. }
  1731. }
  1732. static int if_readstat(__u8 *buf, int len, int user, int id, int channel)
  1733. {
  1734. capidrv_contr *card = findcontrbydriverid(id);
  1735. int count;
  1736. __u8 *p;
  1737. if (!card) {
  1738. printk(KERN_ERR "capidrv: if_readstat called with invalid driverId %d!n",
  1739.        id);
  1740. return -ENODEV;
  1741. }
  1742. for (p=buf, count=0; count < len; p++, count++) {
  1743.         if (user)
  1744.                 put_user(*card->q931_read++, p);
  1745.         else
  1746.                 *p = *card->q931_read++;
  1747.         if (card->q931_read > card->q931_end)
  1748.                 card->q931_read = card->q931_buf;
  1749. }
  1750. return count;
  1751. }
  1752. static void enable_dchannel_trace(capidrv_contr *card)
  1753. {
  1754.         __u8 manufacturer[CAPI_MANUFACTURER_LEN];
  1755.         capi_version version;
  1756. __u16 contr = card->contrnr;
  1757. __u16 errcode;
  1758. __u16 avmversion[3];
  1759.         errcode = (*capifuncs->capi_get_manufacturer)(contr, manufacturer);
  1760.         if (errcode != CAPI_NOERROR) {
  1761.    printk(KERN_ERR "%s: can't get manufacturer (0x%x)n",
  1762. card->name, errcode);
  1763.    return;
  1764. }
  1765. if (strstr(manufacturer, "AVM") == 0) {
  1766.    printk(KERN_ERR "%s: not from AVM, no d-channel trace possible (%s)n",
  1767. card->name, manufacturer);
  1768.    return;
  1769. }
  1770.         errcode = (*capifuncs->capi_get_version)(contr, &version);
  1771.         if (errcode != CAPI_NOERROR) {
  1772.    printk(KERN_ERR "%s: can't get version (0x%x)n",
  1773. card->name, errcode);
  1774.    return;
  1775. }
  1776. avmversion[0] = (version.majormanuversion >> 4) & 0x0f;
  1777. avmversion[1] = (version.majormanuversion << 4) & 0xf0;
  1778. avmversion[1] |= (version.minormanuversion >> 4) & 0x0f;
  1779. avmversion[2] |= version.minormanuversion & 0x0f;
  1780.         if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 5)) {
  1781. printk(KERN_INFO "%s: D2 trace enabledn", card->name);
  1782. capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid,
  1783.    card->msgid++,
  1784.    contr,
  1785.    0x214D5641,  /* ManuID */
  1786.    0,           /* Class */
  1787.    1,           /* Function */
  1788.    (_cstruct)"04200140000");
  1789. } else {
  1790. printk(KERN_INFO "%s: D3 trace enabledn", card->name);
  1791. capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid,
  1792.    card->msgid++,
  1793.    contr,
  1794.    0x214D5641,  /* ManuID */
  1795.    0,           /* Class */
  1796.    1,           /* Function */
  1797.    (_cstruct)"0402030000");
  1798. }
  1799. send_message(card, &cmdcmsg);
  1800. }
  1801. static void send_listen(capidrv_contr *card)
  1802. {
  1803. capi_fill_LISTEN_REQ(&cmdcmsg, global.appid,
  1804.      card->msgid++,
  1805.      card->contrnr, /* controller */
  1806.      1 << 6, /* Infomask */
  1807.      card->cipmask,
  1808.      card->cipmask2,
  1809.      0, 0);
  1810. send_message(card, &cmdcmsg);
  1811. listen_change_state(card, EV_LISTEN_REQ);
  1812. }
  1813. static void listentimerfunc(unsigned long x)
  1814. {
  1815. capidrv_contr *card = (capidrv_contr *)x;
  1816. if (card->state != ST_LISTEN_NONE && card->state != ST_LISTEN_ACTIVE)
  1817. printk(KERN_ERR "%s: controller dead ??n", card->name);
  1818.         send_listen(card);
  1819. mod_timer(&card->listentimer, jiffies + 60*HZ);
  1820. }
  1821. static int capidrv_addcontr(__u16 contr, struct capi_profile *profp)
  1822. {
  1823. capidrv_contr *card;
  1824. long flags;
  1825. isdn_ctrl cmd;
  1826. char id[20];
  1827. int i;
  1828. MOD_INC_USE_COUNT;
  1829. sprintf(id, "capidrv-%d", contr);
  1830. if (!(card = (capidrv_contr *) kmalloc(sizeof(capidrv_contr), GFP_ATOMIC))) {
  1831. printk(KERN_WARNING
  1832.  "capidrv: (%s) Could not allocate contr-struct.n", id);
  1833. MOD_DEC_USE_COUNT;
  1834. return -1;
  1835. }
  1836. memset(card, 0, sizeof(capidrv_contr));
  1837. init_timer(&card->listentimer);
  1838. strcpy(card->name, id);
  1839. card->contrnr = contr;
  1840. card->nbchan = profp->nbchannel;
  1841. card->bchans = (capidrv_bchan *) kmalloc(sizeof(capidrv_bchan) * card->nbchan, GFP_ATOMIC);
  1842. if (!card->bchans) {
  1843. printk(KERN_WARNING
  1844. "capidrv: (%s) Could not allocate bchan-structs.n", id);
  1845. kfree(card);
  1846. MOD_DEC_USE_COUNT;
  1847. return -1;
  1848. }
  1849. card->interface.channels = profp->nbchannel;
  1850. card->interface.maxbufsize = 2048;
  1851. card->interface.command = if_command;
  1852. card->interface.writebuf_skb = if_sendbuf;
  1853. card->interface.writecmd = 0;
  1854. card->interface.readstat = if_readstat;
  1855. card->interface.features = ISDN_FEATURE_L2_HDLC |
  1856.         ISDN_FEATURE_L2_TRANS |
  1857.         ISDN_FEATURE_L3_TRANS |
  1858.    ISDN_FEATURE_P_UNKNOWN |
  1859.    ISDN_FEATURE_L2_X75I |
  1860.    ISDN_FEATURE_L2_X75UI |
  1861.    ISDN_FEATURE_L2_X75BUI;
  1862. if (profp->support1 & (1<<2))
  1863. card->interface.features |= ISDN_FEATURE_L2_V11096 |
  1864.          ISDN_FEATURE_L2_V11019 |
  1865.          ISDN_FEATURE_L2_V11038;
  1866. if (profp->support1 & (1<<8))
  1867. card->interface.features |= ISDN_FEATURE_L2_MODEM;
  1868. card->interface.hl_hdrlen = 22; /* len of DATA_B3_REQ */
  1869. strncpy(card->interface.id, id, sizeof(card->interface.id) - 1);
  1870. card->q931_read = card->q931_buf;
  1871. card->q931_write = card->q931_buf;
  1872. card->q931_end = card->q931_buf + sizeof(card->q931_buf) - 1;
  1873. if (!register_isdn(&card->interface)) {
  1874. printk(KERN_ERR "capidrv: Unable to register contr %sn", id);
  1875. kfree(card->bchans);
  1876. kfree(card);
  1877. MOD_DEC_USE_COUNT;
  1878. return -1;
  1879. }
  1880. card->myid = card->interface.channels;
  1881. spin_lock_irqsave(&global_lock, flags);
  1882. card->next = global.contr_list;
  1883. global.contr_list = card;
  1884. global.ncontr++;
  1885. spin_unlock_irqrestore(&global_lock, flags);
  1886. memset(card->bchans, 0, sizeof(capidrv_bchan) * card->nbchan);
  1887. for (i = 0; i < card->nbchan; i++) {
  1888. card->bchans[i].contr = card;
  1889. }
  1890. cmd.command = ISDN_STAT_RUN;
  1891. cmd.driver = card->myid;
  1892. card->interface.statcallb(&cmd);
  1893. card->cipmask = 0x1FFF03FF; /* any */
  1894. card->cipmask2 = 0;
  1895. send_listen(card);
  1896. card->listentimer.data = (unsigned long)card;
  1897. card->listentimer.function = listentimerfunc;
  1898. mod_timer(&card->listentimer, jiffies + 60*HZ);
  1899. printk(KERN_INFO "%s: now up (%d B channels)n",
  1900. card->name, card->nbchan);
  1901. enable_dchannel_trace(card);
  1902. return 0;
  1903. }
  1904. static int capidrv_delcontr(__u16 contr)
  1905. {
  1906. capidrv_contr **pp, *card;
  1907. unsigned long flags;
  1908. isdn_ctrl cmd;
  1909. spin_lock_irqsave(&global_lock, flags);
  1910. for (card = global.contr_list; card; card = card->next) {
  1911. if (card->contrnr == contr)
  1912. break;
  1913. }
  1914. if (!card) {
  1915. spin_unlock_irqrestore(&global_lock, flags);
  1916. printk(KERN_ERR "capidrv: delcontr: no contr %un", contr);
  1917. return -1;
  1918. }
  1919. spin_unlock_irqrestore(&global_lock, flags);
  1920. del_timer(&card->listentimer);
  1921. if (debugmode)
  1922. printk(KERN_DEBUG "capidrv-%d: id=%d unloadingn",
  1923. card->contrnr, card->myid);
  1924. cmd.command = ISDN_STAT_STOP;
  1925. cmd.driver = card->myid;
  1926. card->interface.statcallb(&cmd);
  1927. while (card->nbchan) {
  1928. cmd.command = ISDN_STAT_DISCH;
  1929. cmd.driver = card->myid;
  1930. cmd.arg = card->nbchan-1;
  1931.         cmd.parm.num[0] = 0;
  1932. if (debugmode)
  1933. printk(KERN_DEBUG "capidrv-%d: id=%d disable chan=%ldn",
  1934. card->contrnr, card->myid, cmd.arg);
  1935. card->interface.statcallb(&cmd);
  1936. if (card->bchans[card->nbchan-1].nccip)
  1937. free_ncci(card, card->bchans[card->nbchan-1].nccip);
  1938. if (card->bchans[card->nbchan-1].plcip)
  1939. free_plci(card, card->bchans[card->nbchan-1].plcip);
  1940. if (card->plci_list)
  1941. printk(KERN_ERR "capidrv: bug in free_plci()n");
  1942. card->nbchan--;
  1943. }
  1944. kfree(card->bchans);
  1945. card->bchans = 0;
  1946. if (debugmode)
  1947. printk(KERN_DEBUG "capidrv-%d: id=%d isdn unloadn",
  1948. card->contrnr, card->myid);
  1949. cmd.command = ISDN_STAT_UNLOAD;
  1950. cmd.driver = card->myid;
  1951. card->interface.statcallb(&cmd);
  1952. if (debugmode)
  1953. printk(KERN_DEBUG "capidrv-%d: id=%d remove contr from listn",
  1954. card->contrnr, card->myid);
  1955. spin_lock_irqsave(&global_lock, flags);
  1956. for (pp = &global.contr_list; *pp; pp = &(*pp)->next) {
  1957. if (*pp == card) {
  1958. *pp = (*pp)->next;
  1959. card->next = 0;
  1960. global.ncontr--;
  1961. break;
  1962. }
  1963. }
  1964. spin_unlock_irqrestore(&global_lock, flags);
  1965. printk(KERN_INFO "%s: now down.n", card->name);
  1966. kfree(card);
  1967. MOD_DEC_USE_COUNT;
  1968. return 0;
  1969. }
  1970. static void lower_callback(unsigned int cmd, __u32 contr, void *data)
  1971. {
  1972. switch (cmd) {
  1973. case KCI_CONTRUP:
  1974. printk(KERN_INFO "capidrv: controller %hu upn", contr);
  1975. (void) capidrv_addcontr(contr, (capi_profile *) data);
  1976. break;
  1977. case KCI_CONTRDOWN:
  1978. printk(KERN_INFO "capidrv: controller %hu downn", contr);
  1979. (void) capidrv_delcontr(contr);
  1980. break;
  1981. }
  1982. }
  1983. /*
  1984.  * /proc/capi/capidrv:
  1985.  * nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
  1986.  */
  1987. static int proc_capidrv_read_proc(char *page, char **start, off_t off,
  1988.                                        int count, int *eof, void *data)
  1989. {
  1990. int len = 0;
  1991. len += sprintf(page+len, "%lu %lu %lu %lun",
  1992. global.nrecvctlpkt,
  1993. global.nrecvdatapkt,
  1994. global.nsentctlpkt,
  1995. global.nsentdatapkt);
  1996. if (off+count >= len)
  1997.    *eof = 1;
  1998. if (len < off)
  1999.            return 0;
  2000. *start = page + off;
  2001. return ((count < len-off) ? count : len-off);
  2002. }
  2003. static struct procfsentries {
  2004.   char *name;
  2005.   mode_t mode;
  2006.   int (*read_proc)(char *page, char **start, off_t off,
  2007.                                        int count, int *eof, void *data);
  2008.   struct proc_dir_entry *procent;
  2009. } procfsentries[] = {
  2010.    /* { "capi",   S_IFDIR, 0 }, */
  2011.    { "capi/capidrv",    0  , proc_capidrv_read_proc },
  2012. };
  2013. static void __init proc_init(void)
  2014. {
  2015.     int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
  2016.     int i;
  2017.     for (i=0; i < nelem; i++) {
  2018.         struct procfsentries *p = procfsentries + i;
  2019. p->procent = create_proc_entry(p->name, p->mode, 0);
  2020. if (p->procent) p->procent->read_proc = p->read_proc;
  2021.     }
  2022. }
  2023. static void __exit proc_exit(void)
  2024. {
  2025.     int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
  2026.     int i;
  2027.     for (i=nelem-1; i >= 0; i--) {
  2028.         struct procfsentries *p = procfsentries + i;
  2029. if (p->procent) {
  2030.    remove_proc_entry(p->name, 0);
  2031.    p->procent = 0;
  2032. }
  2033.     }
  2034. }
  2035. static struct capi_interface_user cuser = {
  2036. name: "capidrv",
  2037. callback: lower_callback
  2038. };
  2039. static int __init capidrv_init(void)
  2040. {
  2041. struct capi_register_params rparam;
  2042. capi_profile profile;
  2043. char rev[32];
  2044. char *p;
  2045. __u32 ncontr, contr;
  2046. __u16 errcode;
  2047. MOD_INC_USE_COUNT;
  2048. capifuncs = attach_capi_interface(&cuser);
  2049. if (!capifuncs) {
  2050. MOD_DEC_USE_COUNT;
  2051. return -EIO;
  2052. }
  2053. if ((p = strchr(revision, ':')) != 0 && p[1]) {
  2054. strncpy(rev, p + 2, sizeof(rev));
  2055. rev[sizeof(rev)-1] = 0;
  2056. if ((p = strchr(rev, '$')) != 0 && p > rev)
  2057.    *(p-1) = 0;
  2058. } else
  2059. strcpy(rev, "1.0");
  2060. rparam.level3cnt = -2;  /* number of bchannels twice */
  2061. rparam.datablkcnt = 16;
  2062. rparam.datablklen = 2048;
  2063. errcode = (*capifuncs->capi_register) (&rparam, &global.appid);
  2064. if (errcode) {
  2065. detach_capi_interface(&cuser);
  2066. MOD_DEC_USE_COUNT;
  2067. return -EIO;
  2068. }
  2069. errcode = (*capifuncs->capi_get_profile) (0, &profile);
  2070. if (errcode != CAPI_NOERROR) {
  2071. (void) (*capifuncs->capi_release) (global.appid);
  2072. detach_capi_interface(&cuser);
  2073. MOD_DEC_USE_COUNT;
  2074. return -EIO;
  2075. }
  2076. (void) (*capifuncs->capi_set_signal) (global.appid, capidrv_signal, 0);
  2077. ncontr = profile.ncontroller;
  2078. for (contr = 1; contr <= ncontr; contr++) {
  2079. errcode = (*capifuncs->capi_get_profile) (contr, &profile);
  2080. if (errcode != CAPI_NOERROR)
  2081. continue;
  2082. (void) capidrv_addcontr(contr, &profile);
  2083. }
  2084. proc_init();
  2085. printk(KERN_NOTICE "capidrv: Rev %s: loadedn", rev);
  2086. MOD_DEC_USE_COUNT;
  2087. return 0;
  2088. }
  2089. static void __exit capidrv_exit(void)
  2090. {
  2091. char rev[10];
  2092. char *p;
  2093. if ((p = strchr(revision, ':')) != 0) {
  2094. strcpy(rev, p + 1);
  2095. p = strchr(rev, '$');
  2096. *p = 0;
  2097. } else {
  2098. strcpy(rev, " ??? ");
  2099. }
  2100. (void) (*capifuncs->capi_release) (global.appid);
  2101. detach_capi_interface(&cuser);
  2102. proc_exit();
  2103. printk(KERN_NOTICE "capidrv: Rev%s: unloadedn", rev);
  2104. }
  2105. module_init(capidrv_init);
  2106. module_exit(capidrv_exit);