capiutil.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075
  1. /* $Id: capiutil.c,v 1.13.6.4 2001/09/23 22:24:33 kai Exp $
  2. *
  3. * CAPI 2.0 convert capi message to capi message struct
  4. *
  5. * From CAPI 2.0 Development Kit AVM 1995 (msg.c)
  6. * Rewritten for Linux 1996 by Carsten Paeth <calle@calle.de>
  7. *
  8. * This software may be used and distributed according to the terms
  9. * of the GNU General Public License, incorporated herein by reference.
  10. *
  11. */
  12. #include <linux/module.h>
  13. #include <linux/string.h>
  14. #include <linux/ctype.h>
  15. #include <linux/stddef.h>
  16. #include <linux/kernel.h>
  17. #include <linux/mm.h>
  18. #include <linux/init.h>
  19. #include <linux/isdn/capiutil.h>
  20. /* from CAPI2.0 DDK AVM Berlin GmbH */
  21. #ifndef CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
  22. char *capi_info2str(u16 reason)
  23. {
  24. return "..";
  25. }
  26. #else
  27. char *capi_info2str(u16 reason)
  28. {
  29. switch (reason) {
  30. /*-- informative values (corresponding message was processed) -----*/
  31. case 0x0001:
  32. return "NCPI not supported by current protocol, NCPI ignored";
  33. case 0x0002:
  34. return "Flags not supported by current protocol, flags ignored";
  35. case 0x0003:
  36. return "Alert already sent by another application";
  37. /*-- error information concerning CAPI_REGISTER -----*/
  38. case 0x1001:
  39. return "Too many applications";
  40. case 0x1002:
  41. return "Logical block size too small, must be at least 128 Bytes";
  42. case 0x1003:
  43. return "Buffer exceeds 64 kByte";
  44. case 0x1004:
  45. return "Message buffer size too small, must be at least 1024 Bytes";
  46. case 0x1005:
  47. return "Max. number of logical connections not supported";
  48. case 0x1006:
  49. return "Reserved";
  50. case 0x1007:
  51. return "The message could not be accepted because of an internal busy condition";
  52. case 0x1008:
  53. return "OS resource error (no memory ?)";
  54. case 0x1009:
  55. return "CAPI not installed";
  56. case 0x100A:
  57. return "Controller does not support external equipment";
  58. case 0x100B:
  59. return "Controller does only support external equipment";
  60. /*-- error information concerning message exchange functions -----*/
  61. case 0x1101:
  62. return "Illegal application number";
  63. case 0x1102:
  64. return "Illegal command or subcommand or message length less than 12 bytes";
  65. case 0x1103:
  66. return "The message could not be accepted because of a queue full condition !! The error code does not imply that CAPI cannot receive messages directed to another controller, PLCI or NCCI";
  67. case 0x1104:
  68. return "Queue is empty";
  69. case 0x1105:
  70. return "Queue overflow, a message was lost !! This indicates a configuration error. The only recovery from this error is to perform a CAPI_RELEASE";
  71. case 0x1106:
  72. return "Unknown notification parameter";
  73. case 0x1107:
  74. return "The Message could not be accepted because of an internal busy condition";
  75. case 0x1108:
  76. return "OS Resource error (no memory ?)";
  77. case 0x1109:
  78. return "CAPI not installed";
  79. case 0x110A:
  80. return "Controller does not support external equipment";
  81. case 0x110B:
  82. return "Controller does only support external equipment";
  83. /*-- error information concerning resource / coding problems -----*/
  84. case 0x2001:
  85. return "Message not supported in current state";
  86. case 0x2002:
  87. return "Illegal Controller / PLCI / NCCI";
  88. case 0x2003:
  89. return "Out of PLCI";
  90. case 0x2004:
  91. return "Out of NCCI";
  92. case 0x2005:
  93. return "Out of LISTEN";
  94. case 0x2006:
  95. return "Out of FAX resources (protocol T.30)";
  96. case 0x2007:
  97. return "Illegal message parameter coding";
  98. /*-- error information concerning requested services -----*/
  99. case 0x3001:
  100. return "B1 protocol not supported";
  101. case 0x3002:
  102. return "B2 protocol not supported";
  103. case 0x3003:
  104. return "B3 protocol not supported";
  105. case 0x3004:
  106. return "B1 protocol parameter not supported";
  107. case 0x3005:
  108. return "B2 protocol parameter not supported";
  109. case 0x3006:
  110. return "B3 protocol parameter not supported";
  111. case 0x3007:
  112. return "B protocol combination not supported";
  113. case 0x3008:
  114. return "NCPI not supported";
  115. case 0x3009:
  116. return "CIP Value unknown";
  117. case 0x300A:
  118. return "Flags not supported (reserved bits)";
  119. case 0x300B:
  120. return "Facility not supported";
  121. case 0x300C:
  122. return "Data length not supported by current protocol";
  123. case 0x300D:
  124. return "Reset procedure not supported by current protocol";
  125. /*-- informations about the clearing of a physical connection -----*/
  126. case 0x3301:
  127. return "Protocol error layer 1 (broken line or B-channel removed by signalling protocol)";
  128. case 0x3302:
  129. return "Protocol error layer 2";
  130. case 0x3303:
  131. return "Protocol error layer 3";
  132. case 0x3304:
  133. return "Another application got that call";
  134. /*-- T.30 specific reasons -----*/
  135. case 0x3311:
  136. return "Connecting not successful (remote station is no FAX G3 machine)";
  137. case 0x3312:
  138. return "Connecting not successful (training error)";
  139. case 0x3313:
  140. return "Disconnected before transfer (remote station does not support transfer mode, e.g. resolution)";
  141. case 0x3314:
  142. return "Disconnected during transfer (remote abort)";
  143. case 0x3315:
  144. return "Disconnected during transfer (remote procedure error, e.g. unsuccessful repetition of T.30 commands)";
  145. case 0x3316:
  146. return "Disconnected during transfer (local tx data underrun)";
  147. case 0x3317:
  148. return "Disconnected during transfer (local rx data overflow)";
  149. case 0x3318:
  150. return "Disconnected during transfer (local abort)";
  151. case 0x3319:
  152. return "Illegal parameter coding (e.g. SFF coding error)";
  153. /*-- disconnect causes from the network according to ETS 300 102-1/Q.931 -----*/
  154. case 0x3481: return "Unallocated (unassigned) number";
  155. case 0x3482: return "No route to specified transit network";
  156. case 0x3483: return "No route to destination";
  157. case 0x3486: return "Channel unacceptable";
  158. case 0x3487:
  159. return "Call awarded and being delivered in an established channel";
  160. case 0x3490: return "Normal call clearing";
  161. case 0x3491: return "User busy";
  162. case 0x3492: return "No user responding";
  163. case 0x3493: return "No answer from user (user alerted)";
  164. case 0x3495: return "Call rejected";
  165. case 0x3496: return "Number changed";
  166. case 0x349A: return "Non-selected user clearing";
  167. case 0x349B: return "Destination out of order";
  168. case 0x349C: return "Invalid number format";
  169. case 0x349D: return "Facility rejected";
  170. case 0x349E: return "Response to STATUS ENQUIRY";
  171. case 0x349F: return "Normal, unspecified";
  172. case 0x34A2: return "No circuit / channel available";
  173. case 0x34A6: return "Network out of order";
  174. case 0x34A9: return "Temporary failure";
  175. case 0x34AA: return "Switching equipment congestion";
  176. case 0x34AB: return "Access information discarded";
  177. case 0x34AC: return "Requested circuit / channel not available";
  178. case 0x34AF: return "Resources unavailable, unspecified";
  179. case 0x34B1: return "Quality of service unavailable";
  180. case 0x34B2: return "Requested facility not subscribed";
  181. case 0x34B9: return "Bearer capability not authorized";
  182. case 0x34BA: return "Bearer capability not presently available";
  183. case 0x34BF: return "Service or option not available, unspecified";
  184. case 0x34C1: return "Bearer capability not implemented";
  185. case 0x34C2: return "Channel type not implemented";
  186. case 0x34C5: return "Requested facility not implemented";
  187. case 0x34C6: return "Only restricted digital information bearer capability is available";
  188. case 0x34CF: return "Service or option not implemented, unspecified";
  189. case 0x34D1: return "Invalid call reference value";
  190. case 0x34D2: return "Identified channel does not exist";
  191. case 0x34D3: return "A suspended call exists, but this call identity does not";
  192. case 0x34D4: return "Call identity in use";
  193. case 0x34D5: return "No call suspended";
  194. case 0x34D6: return "Call having the requested call identity has been cleared";
  195. case 0x34D8: return "Incompatible destination";
  196. case 0x34DB: return "Invalid transit network selection";
  197. case 0x34DF: return "Invalid message, unspecified";
  198. case 0x34E0: return "Mandatory information element is missing";
  199. case 0x34E1: return "Message type non-existent or not implemented";
  200. case 0x34E2: return "Message not compatible with call state or message type non-existent or not implemented";
  201. case 0x34E3: return "Information element non-existent or not implemented";
  202. case 0x34E4: return "Invalid information element contents";
  203. case 0x34E5: return "Message not compatible with call state";
  204. case 0x34E6: return "Recovery on timer expiry";
  205. case 0x34EF: return "Protocol error, unspecified";
  206. case 0x34FF: return "Interworking, unspecified";
  207. default: return "No additional information";
  208. }
  209. }
  210. #endif
  211. typedef struct {
  212. int typ;
  213. size_t off;
  214. } _cdef;
  215. #define _CBYTE 1
  216. #define _CWORD 2
  217. #define _CDWORD 3
  218. #define _CSTRUCT 4
  219. #define _CMSTRUCT 5
  220. #define _CEND 6
  221. static _cdef cdef[] =
  222. {
  223. /*00 */
  224. {_CEND},
  225. /*01 */
  226. {_CEND},
  227. /*02 */
  228. {_CEND},
  229. /*03 */
  230. {_CDWORD, offsetof(_cmsg, adr.adrController)},
  231. /*04 */
  232. {_CMSTRUCT, offsetof(_cmsg, AdditionalInfo)},
  233. /*05 */
  234. {_CSTRUCT, offsetof(_cmsg, B1configuration)},
  235. /*06 */
  236. {_CWORD, offsetof(_cmsg, B1protocol)},
  237. /*07 */
  238. {_CSTRUCT, offsetof(_cmsg, B2configuration)},
  239. /*08 */
  240. {_CWORD, offsetof(_cmsg, B2protocol)},
  241. /*09 */
  242. {_CSTRUCT, offsetof(_cmsg, B3configuration)},
  243. /*0a */
  244. {_CWORD, offsetof(_cmsg, B3protocol)},
  245. /*0b */
  246. {_CSTRUCT, offsetof(_cmsg, BC)},
  247. /*0c */
  248. {_CSTRUCT, offsetof(_cmsg, BChannelinformation)},
  249. /*0d */
  250. {_CMSTRUCT, offsetof(_cmsg, BProtocol)},
  251. /*0e */
  252. {_CSTRUCT, offsetof(_cmsg, CalledPartyNumber)},
  253. /*0f */
  254. {_CSTRUCT, offsetof(_cmsg, CalledPartySubaddress)},
  255. /*10 */
  256. {_CSTRUCT, offsetof(_cmsg, CallingPartyNumber)},
  257. /*11 */
  258. {_CSTRUCT, offsetof(_cmsg, CallingPartySubaddress)},
  259. /*12 */
  260. {_CDWORD, offsetof(_cmsg, CIPmask)},
  261. /*13 */
  262. {_CDWORD, offsetof(_cmsg, CIPmask2)},
  263. /*14 */
  264. {_CWORD, offsetof(_cmsg, CIPValue)},
  265. /*15 */
  266. {_CDWORD, offsetof(_cmsg, Class)},
  267. /*16 */
  268. {_CSTRUCT, offsetof(_cmsg, ConnectedNumber)},
  269. /*17 */
  270. {_CSTRUCT, offsetof(_cmsg, ConnectedSubaddress)},
  271. /*18 */
  272. {_CDWORD, offsetof(_cmsg, Data)},
  273. /*19 */
  274. {_CWORD, offsetof(_cmsg, DataHandle)},
  275. /*1a */
  276. {_CWORD, offsetof(_cmsg, DataLength)},
  277. /*1b */
  278. {_CSTRUCT, offsetof(_cmsg, FacilityConfirmationParameter)},
  279. /*1c */
  280. {_CSTRUCT, offsetof(_cmsg, Facilitydataarray)},
  281. /*1d */
  282. {_CSTRUCT, offsetof(_cmsg, FacilityIndicationParameter)},
  283. /*1e */
  284. {_CSTRUCT, offsetof(_cmsg, FacilityRequestParameter)},
  285. /*1f */
  286. {_CWORD, offsetof(_cmsg, FacilitySelector)},
  287. /*20 */
  288. {_CWORD, offsetof(_cmsg, Flags)},
  289. /*21 */
  290. {_CDWORD, offsetof(_cmsg, Function)},
  291. /*22 */
  292. {_CSTRUCT, offsetof(_cmsg, HLC)},
  293. /*23 */
  294. {_CWORD, offsetof(_cmsg, Info)},
  295. /*24 */
  296. {_CSTRUCT, offsetof(_cmsg, InfoElement)},
  297. /*25 */
  298. {_CDWORD, offsetof(_cmsg, InfoMask)},
  299. /*26 */
  300. {_CWORD, offsetof(_cmsg, InfoNumber)},
  301. /*27 */
  302. {_CSTRUCT, offsetof(_cmsg, Keypadfacility)},
  303. /*28 */
  304. {_CSTRUCT, offsetof(_cmsg, LLC)},
  305. /*29 */
  306. {_CSTRUCT, offsetof(_cmsg, ManuData)},
  307. /*2a */
  308. {_CDWORD, offsetof(_cmsg, ManuID)},
  309. /*2b */
  310. {_CSTRUCT, offsetof(_cmsg, NCPI)},
  311. /*2c */
  312. {_CWORD, offsetof(_cmsg, Reason)},
  313. /*2d */
  314. {_CWORD, offsetof(_cmsg, Reason_B3)},
  315. /*2e */
  316. {_CWORD, offsetof(_cmsg, Reject)},
  317. /*2f */
  318. {_CSTRUCT, offsetof(_cmsg, Useruserdata)}
  319. };
  320. static unsigned char *cpars[] =
  321. {
  322. /* ALERT_REQ */ [0x01] = "\x03\x04\x0c\x27\x2f\x1c\x01\x01",
  323. /* CONNECT_REQ */ [0x02] = "\x03\x14\x0e\x10\x0f\x11\x0d\x06\x08\x0a\x05\x07\x09\x01\x0b\x28\x22\x04\x0c\x27\x2f\x1c\x01\x01",
  324. /* DISCONNECT_REQ */ [0x04] = "\x03\x04\x0c\x27\x2f\x1c\x01\x01",
  325. /* LISTEN_REQ */ [0x05] = "\x03\x25\x12\x13\x10\x11\x01",
  326. /* INFO_REQ */ [0x08] = "\x03\x0e\x04\x0c\x27\x2f\x1c\x01\x01",
  327. /* FACILITY_REQ */ [0x09] = "\x03\x1f\x1e\x01",
  328. /* SELECT_B_PROTOCOL_REQ */ [0x0a] = "\x03\x0d\x06\x08\x0a\x05\x07\x09\x01\x01",
  329. /* CONNECT_B3_REQ */ [0x0b] = "\x03\x2b\x01",
  330. /* DISCONNECT_B3_REQ */ [0x0d] = "\x03\x2b\x01",
  331. /* DATA_B3_REQ */ [0x0f] = "\x03\x18\x1a\x19\x20\x01",
  332. /* RESET_B3_REQ */ [0x10] = "\x03\x2b\x01",
  333. /* ALERT_CONF */ [0x13] = "\x03\x23\x01",
  334. /* CONNECT_CONF */ [0x14] = "\x03\x23\x01",
  335. /* DISCONNECT_CONF */ [0x16] = "\x03\x23\x01",
  336. /* LISTEN_CONF */ [0x17] = "\x03\x23\x01",
  337. /* MANUFACTURER_REQ */ [0x18] = "\x03\x2a\x15\x21\x29\x01",
  338. /* INFO_CONF */ [0x1a] = "\x03\x23\x01",
  339. /* FACILITY_CONF */ [0x1b] = "\x03\x23\x1f\x1b\x01",
  340. /* SELECT_B_PROTOCOL_CONF */ [0x1c] = "\x03\x23\x01",
  341. /* CONNECT_B3_CONF */ [0x1d] = "\x03\x23\x01",
  342. /* DISCONNECT_B3_CONF */ [0x1f] = "\x03\x23\x01",
  343. /* DATA_B3_CONF */ [0x21] = "\x03\x19\x23\x01",
  344. /* RESET_B3_CONF */ [0x22] = "\x03\x23\x01",
  345. /* CONNECT_IND */ [0x26] = "\x03\x14\x0e\x10\x0f\x11\x0b\x28\x22\x04\x0c\x27\x2f\x1c\x01\x01",
  346. /* CONNECT_ACTIVE_IND */ [0x27] = "\x03\x16\x17\x28\x01",
  347. /* DISCONNECT_IND */ [0x28] = "\x03\x2c\x01",
  348. /* MANUFACTURER_CONF */ [0x2a] = "\x03\x2a\x15\x21\x29\x01",
  349. /* INFO_IND */ [0x2c] = "\x03\x26\x24\x01",
  350. /* FACILITY_IND */ [0x2d] = "\x03\x1f\x1d\x01",
  351. /* CONNECT_B3_IND */ [0x2f] = "\x03\x2b\x01",
  352. /* CONNECT_B3_ACTIVE_IND */ [0x30] = "\x03\x2b\x01",
  353. /* DISCONNECT_B3_IND */ [0x31] = "\x03\x2d\x2b\x01",
  354. /* DATA_B3_IND */ [0x33] = "\x03\x18\x1a\x19\x20\x01",
  355. /* RESET_B3_IND */ [0x34] = "\x03\x2b\x01",
  356. /* CONNECT_B3_T90_ACTIVE_IND */ [0x35] = "\x03\x2b\x01",
  357. /* CONNECT_RESP */ [0x38] = "\x03\x2e\x0d\x06\x08\x0a\x05\x07\x09\x01\x16\x17\x28\x04\x0c\x27\x2f\x1c\x01\x01",
  358. /* CONNECT_ACTIVE_RESP */ [0x39] = "\x03\x01",
  359. /* DISCONNECT_RESP */ [0x3a] = "\x03\x01",
  360. /* MANUFACTURER_IND */ [0x3c] = "\x03\x2a\x15\x21\x29\x01",
  361. /* INFO_RESP */ [0x3e] = "\x03\x01",
  362. /* FACILITY_RESP */ [0x3f] = "\x03\x1f\x01",
  363. /* CONNECT_B3_RESP */ [0x41] = "\x03\x2e\x2b\x01",
  364. /* CONNECT_B3_ACTIVE_RESP */ [0x42] = "\x03\x01",
  365. /* DISCONNECT_B3_RESP */ [0x43] = "\x03\x01",
  366. /* DATA_B3_RESP */ [0x45] = "\x03\x19\x01",
  367. /* RESET_B3_RESP */ [0x46] = "\x03\x01",
  368. /* CONNECT_B3_T90_ACTIVE_RESP */ [0x47] = "\x03\x01",
  369. /* MANUFACTURER_RESP */ [0x4e] = "\x03\x2a\x15\x21\x29\x01",
  370. };
  371. /*-------------------------------------------------------*/
  372. #define byteTLcpy(x,y) *(u8 *)(x)=*(u8 *)(y);
  373. #define wordTLcpy(x,y) *(u16 *)(x)=*(u16 *)(y);
  374. #define dwordTLcpy(x,y) memcpy(x,y,4);
  375. #define structTLcpy(x,y,l) memcpy (x,y,l)
  376. #define structTLcpyovl(x,y,l) memmove (x,y,l)
  377. #define byteTRcpy(x,y) *(u8 *)(y)=*(u8 *)(x);
  378. #define wordTRcpy(x,y) *(u16 *)(y)=*(u16 *)(x);
  379. #define dwordTRcpy(x,y) memcpy(y,x,4);
  380. #define structTRcpy(x,y,l) memcpy (y,x,l)
  381. #define structTRcpyovl(x,y,l) memmove (y,x,l)
  382. /*-------------------------------------------------------*/
  383. static unsigned command_2_index(unsigned c, unsigned sc)
  384. {
  385. if (c & 0x80)
  386. c = 0x9 + (c & 0x0f);
  387. else if (c <= 0x0f);
  388. else if (c == 0x41)
  389. c = 0x9 + 0x1;
  390. else if (c == 0xff)
  391. c = 0x00;
  392. return (sc & 3) * (0x9 + 0x9) + c;
  393. }
  394. /*-------------------------------------------------------*/
  395. #define TYP (cdef[cmsg->par[cmsg->p]].typ)
  396. #define OFF (((u8 *)cmsg)+cdef[cmsg->par[cmsg->p]].off)
  397. static void jumpcstruct(_cmsg * cmsg)
  398. {
  399. unsigned layer;
  400. for (cmsg->p++, layer = 1; layer;) {
  401. /* $$$$$ assert (cmsg->p); */
  402. cmsg->p++;
  403. switch (TYP) {
  404. case _CMSTRUCT:
  405. layer++;
  406. break;
  407. case _CEND:
  408. layer--;
  409. break;
  410. }
  411. }
  412. }
  413. /*-------------------------------------------------------*/
  414. static void pars_2_message(_cmsg * cmsg)
  415. {
  416. for (; TYP != _CEND; cmsg->p++) {
  417. switch (TYP) {
  418. case _CBYTE:
  419. byteTLcpy(cmsg->m + cmsg->l, OFF);
  420. cmsg->l++;
  421. break;
  422. case _CWORD:
  423. wordTLcpy(cmsg->m + cmsg->l, OFF);
  424. cmsg->l += 2;
  425. break;
  426. case _CDWORD:
  427. dwordTLcpy(cmsg->m + cmsg->l, OFF);
  428. cmsg->l += 4;
  429. break;
  430. case _CSTRUCT:
  431. if (*(u8 **) OFF == NULL) {
  432. *(cmsg->m + cmsg->l) = '\0';
  433. cmsg->l++;
  434. } else if (**(_cstruct *) OFF != 0xff) {
  435. structTLcpy(cmsg->m + cmsg->l, *(_cstruct *) OFF, 1 + **(_cstruct *) OFF);
  436. cmsg->l += 1 + **(_cstruct *) OFF;
  437. } else {
  438. _cstruct s = *(_cstruct *) OFF;
  439. structTLcpy(cmsg->m + cmsg->l, s, 3 + *(u16 *) (s + 1));
  440. cmsg->l += 3 + *(u16 *) (s + 1);
  441. }
  442. break;
  443. case _CMSTRUCT:
  444. /*----- Metastruktur 0 -----*/
  445. if (*(_cmstruct *) OFF == CAPI_DEFAULT) {
  446. *(cmsg->m + cmsg->l) = '\0';
  447. cmsg->l++;
  448. jumpcstruct(cmsg);
  449. }
  450. /*----- Metastruktur wird composed -----*/
  451. else {
  452. unsigned _l = cmsg->l;
  453. unsigned _ls;
  454. cmsg->l++;
  455. cmsg->p++;
  456. pars_2_message(cmsg);
  457. _ls = cmsg->l - _l - 1;
  458. if (_ls < 255)
  459. (cmsg->m + _l)[0] = (u8) _ls;
  460. else {
  461. structTLcpyovl(cmsg->m + _l + 3, cmsg->m + _l + 1, _ls);
  462. (cmsg->m + _l)[0] = 0xff;
  463. wordTLcpy(cmsg->m + _l + 1, &_ls);
  464. }
  465. }
  466. break;
  467. }
  468. }
  469. }
  470. /**
  471. * capi_cmsg2message() - assemble CAPI 2.0 message from _cmsg structure
  472. * @cmsg: _cmsg structure
  473. * @msg: buffer for assembled message
  474. *
  475. * Return value: 0 for success
  476. */
  477. unsigned capi_cmsg2message(_cmsg * cmsg, u8 * msg)
  478. {
  479. cmsg->m = msg;
  480. cmsg->l = 8;
  481. cmsg->p = 0;
  482. cmsg->par = cpars[command_2_index(cmsg->Command, cmsg->Subcommand)];
  483. pars_2_message(cmsg);
  484. wordTLcpy(msg + 0, &cmsg->l);
  485. byteTLcpy(cmsg->m + 4, &cmsg->Command);
  486. byteTLcpy(cmsg->m + 5, &cmsg->Subcommand);
  487. wordTLcpy(cmsg->m + 2, &cmsg->ApplId);
  488. wordTLcpy(cmsg->m + 6, &cmsg->Messagenumber);
  489. return 0;
  490. }
  491. /*-------------------------------------------------------*/
  492. static void message_2_pars(_cmsg * cmsg)
  493. {
  494. for (; TYP != _CEND; cmsg->p++) {
  495. switch (TYP) {
  496. case _CBYTE:
  497. byteTRcpy(cmsg->m + cmsg->l, OFF);
  498. cmsg->l++;
  499. break;
  500. case _CWORD:
  501. wordTRcpy(cmsg->m + cmsg->l, OFF);
  502. cmsg->l += 2;
  503. break;
  504. case _CDWORD:
  505. dwordTRcpy(cmsg->m + cmsg->l, OFF);
  506. cmsg->l += 4;
  507. break;
  508. case _CSTRUCT:
  509. *(u8 **) OFF = cmsg->m + cmsg->l;
  510. if (cmsg->m[cmsg->l] != 0xff)
  511. cmsg->l += 1 + cmsg->m[cmsg->l];
  512. else
  513. cmsg->l += 3 + *(u16 *) (cmsg->m + cmsg->l + 1);
  514. break;
  515. case _CMSTRUCT:
  516. /*----- Metastruktur 0 -----*/
  517. if (cmsg->m[cmsg->l] == '\0') {
  518. *(_cmstruct *) OFF = CAPI_DEFAULT;
  519. cmsg->l++;
  520. jumpcstruct(cmsg);
  521. } else {
  522. unsigned _l = cmsg->l;
  523. *(_cmstruct *) OFF = CAPI_COMPOSE;
  524. cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1;
  525. cmsg->p++;
  526. message_2_pars(cmsg);
  527. }
  528. break;
  529. }
  530. }
  531. }
  532. /**
  533. * capi_message2cmsg() - disassemble CAPI 2.0 message into _cmsg structure
  534. * @cmsg: _cmsg structure
  535. * @msg: buffer for assembled message
  536. *
  537. * Return value: 0 for success
  538. */
  539. unsigned capi_message2cmsg(_cmsg * cmsg, u8 * msg)
  540. {
  541. memset(cmsg, 0, sizeof(_cmsg));
  542. cmsg->m = msg;
  543. cmsg->l = 8;
  544. cmsg->p = 0;
  545. byteTRcpy(cmsg->m + 4, &cmsg->Command);
  546. byteTRcpy(cmsg->m + 5, &cmsg->Subcommand);
  547. cmsg->par = cpars[command_2_index(cmsg->Command, cmsg->Subcommand)];
  548. message_2_pars(cmsg);
  549. wordTRcpy(msg + 0, &cmsg->l);
  550. wordTRcpy(cmsg->m + 2, &cmsg->ApplId);
  551. wordTRcpy(cmsg->m + 6, &cmsg->Messagenumber);
  552. return 0;
  553. }
  554. /**
  555. * capi_cmsg_header() - initialize header part of _cmsg structure
  556. * @cmsg: _cmsg structure
  557. * @_ApplId: ApplID field value
  558. * @_Command: Command field value
  559. * @_Subcommand: Subcommand field value
  560. * @_Messagenumber: Message Number field value
  561. * @_Controller: Controller/PLCI/NCCI field value
  562. *
  563. * Return value: 0 for success
  564. */
  565. unsigned capi_cmsg_header(_cmsg * cmsg, u16 _ApplId,
  566. u8 _Command, u8 _Subcommand,
  567. u16 _Messagenumber, u32 _Controller)
  568. {
  569. memset(cmsg, 0, sizeof(_cmsg));
  570. cmsg->ApplId = _ApplId;
  571. cmsg->Command = _Command;
  572. cmsg->Subcommand = _Subcommand;
  573. cmsg->Messagenumber = _Messagenumber;
  574. cmsg->adr.adrController = _Controller;
  575. return 0;
  576. }
  577. /*-------------------------------------------------------*/
  578. static char *mnames[] =
  579. {
  580. [0x01] = "ALERT_REQ",
  581. [0x02] = "CONNECT_REQ",
  582. [0x04] = "DISCONNECT_REQ",
  583. [0x05] = "LISTEN_REQ",
  584. [0x08] = "INFO_REQ",
  585. [0x09] = "FACILITY_REQ",
  586. [0x0a] = "SELECT_B_PROTOCOL_REQ",
  587. [0x0b] = "CONNECT_B3_REQ",
  588. [0x0d] = "DISCONNECT_B3_REQ",
  589. [0x0f] = "DATA_B3_REQ",
  590. [0x10] = "RESET_B3_REQ",
  591. [0x13] = "ALERT_CONF",
  592. [0x14] = "CONNECT_CONF",
  593. [0x16] = "DISCONNECT_CONF",
  594. [0x17] = "LISTEN_CONF",
  595. [0x18] = "MANUFACTURER_REQ",
  596. [0x1a] = "INFO_CONF",
  597. [0x1b] = "FACILITY_CONF",
  598. [0x1c] = "SELECT_B_PROTOCOL_CONF",
  599. [0x1d] = "CONNECT_B3_CONF",
  600. [0x1f] = "DISCONNECT_B3_CONF",
  601. [0x21] = "DATA_B3_CONF",
  602. [0x22] = "RESET_B3_CONF",
  603. [0x26] = "CONNECT_IND",
  604. [0x27] = "CONNECT_ACTIVE_IND",
  605. [0x28] = "DISCONNECT_IND",
  606. [0x2a] = "MANUFACTURER_CONF",
  607. [0x2c] = "INFO_IND",
  608. [0x2d] = "FACILITY_IND",
  609. [0x2f] = "CONNECT_B3_IND",
  610. [0x30] = "CONNECT_B3_ACTIVE_IND",
  611. [0x31] = "DISCONNECT_B3_IND",
  612. [0x33] = "DATA_B3_IND",
  613. [0x34] = "RESET_B3_IND",
  614. [0x35] = "CONNECT_B3_T90_ACTIVE_IND",
  615. [0x38] = "CONNECT_RESP",
  616. [0x39] = "CONNECT_ACTIVE_RESP",
  617. [0x3a] = "DISCONNECT_RESP",
  618. [0x3c] = "MANUFACTURER_IND",
  619. [0x3e] = "INFO_RESP",
  620. [0x3f] = "FACILITY_RESP",
  621. [0x41] = "CONNECT_B3_RESP",
  622. [0x42] = "CONNECT_B3_ACTIVE_RESP",
  623. [0x43] = "DISCONNECT_B3_RESP",
  624. [0x45] = "DATA_B3_RESP",
  625. [0x46] = "RESET_B3_RESP",
  626. [0x47] = "CONNECT_B3_T90_ACTIVE_RESP",
  627. [0x4e] = "MANUFACTURER_RESP"
  628. };
  629. /**
  630. * capi_cmd2str() - convert CAPI 2.0 command/subcommand number to name
  631. * @cmd: command number
  632. * @subcmd: subcommand number
  633. *
  634. * Return value: static string, NULL if command/subcommand unknown
  635. */
  636. char *capi_cmd2str(u8 cmd, u8 subcmd)
  637. {
  638. return mnames[command_2_index(cmd, subcmd)];
  639. }
  640. /*-------------------------------------------------------*/
  641. #ifdef CONFIG_CAPI_TRACE
  642. /*-------------------------------------------------------*/
  643. static char *pnames[] =
  644. {
  645. /*00 */ NULL,
  646. /*01 */ NULL,
  647. /*02 */ NULL,
  648. /*03 */ "Controller/PLCI/NCCI",
  649. /*04 */ "AdditionalInfo",
  650. /*05 */ "B1configuration",
  651. /*06 */ "B1protocol",
  652. /*07 */ "B2configuration",
  653. /*08 */ "B2protocol",
  654. /*09 */ "B3configuration",
  655. /*0a */ "B3protocol",
  656. /*0b */ "BC",
  657. /*0c */ "BChannelinformation",
  658. /*0d */ "BProtocol",
  659. /*0e */ "CalledPartyNumber",
  660. /*0f */ "CalledPartySubaddress",
  661. /*10 */ "CallingPartyNumber",
  662. /*11 */ "CallingPartySubaddress",
  663. /*12 */ "CIPmask",
  664. /*13 */ "CIPmask2",
  665. /*14 */ "CIPValue",
  666. /*15 */ "Class",
  667. /*16 */ "ConnectedNumber",
  668. /*17 */ "ConnectedSubaddress",
  669. /*18 */ "Data32",
  670. /*19 */ "DataHandle",
  671. /*1a */ "DataLength",
  672. /*1b */ "FacilityConfirmationParameter",
  673. /*1c */ "Facilitydataarray",
  674. /*1d */ "FacilityIndicationParameter",
  675. /*1e */ "FacilityRequestParameter",
  676. /*1f */ "FacilitySelector",
  677. /*20 */ "Flags",
  678. /*21 */ "Function",
  679. /*22 */ "HLC",
  680. /*23 */ "Info",
  681. /*24 */ "InfoElement",
  682. /*25 */ "InfoMask",
  683. /*26 */ "InfoNumber",
  684. /*27 */ "Keypadfacility",
  685. /*28 */ "LLC",
  686. /*29 */ "ManuData",
  687. /*2a */ "ManuID",
  688. /*2b */ "NCPI",
  689. /*2c */ "Reason",
  690. /*2d */ "Reason_B3",
  691. /*2e */ "Reject",
  692. /*2f */ "Useruserdata"
  693. };
  694. #include <stdarg.h>
  695. /*-------------------------------------------------------*/
  696. static _cdebbuf *bufprint(_cdebbuf *cdb, char *fmt,...)
  697. {
  698. va_list f;
  699. size_t n,r;
  700. if (!cdb)
  701. return NULL;
  702. va_start(f, fmt);
  703. r = cdb->size - cdb->pos;
  704. n = vsnprintf(cdb->p, r, fmt, f);
  705. va_end(f);
  706. if (n >= r) {
  707. /* truncated, need bigger buffer */
  708. size_t ns = 2 * cdb->size;
  709. u_char *nb;
  710. while ((ns - cdb->pos) <= n)
  711. ns *= 2;
  712. nb = kmalloc(ns, GFP_ATOMIC);
  713. if (!nb) {
  714. cdebbuf_free(cdb);
  715. return NULL;
  716. }
  717. memcpy(nb, cdb->buf, cdb->pos);
  718. kfree(cdb->buf);
  719. nb[cdb->pos] = 0;
  720. cdb->buf = nb;
  721. cdb->p = cdb->buf + cdb->pos;
  722. cdb->size = ns;
  723. va_start(f, fmt);
  724. r = cdb->size - cdb->pos;
  725. n = vsnprintf(cdb->p, r, fmt, f);
  726. va_end(f);
  727. }
  728. cdb->p += n;
  729. cdb->pos += n;
  730. return cdb;
  731. }
  732. static _cdebbuf *printstructlen(_cdebbuf *cdb, u8 * m, unsigned len)
  733. {
  734. unsigned hex = 0;
  735. if (!cdb)
  736. return NULL;
  737. for (; len; len--, m++)
  738. if (isalnum(*m) || *m == ' ') {
  739. if (hex)
  740. cdb = bufprint(cdb, ">");
  741. cdb = bufprint(cdb, "%c", *m);
  742. hex = 0;
  743. } else {
  744. if (!hex)
  745. cdb = bufprint(cdb, "<%02x", *m);
  746. else
  747. cdb = bufprint(cdb, " %02x", *m);
  748. hex = 1;
  749. }
  750. if (hex)
  751. cdb = bufprint(cdb, ">");
  752. return cdb;
  753. }
  754. static _cdebbuf *printstruct(_cdebbuf *cdb, u8 * m)
  755. {
  756. unsigned len;
  757. if (m[0] != 0xff) {
  758. len = m[0];
  759. m += 1;
  760. } else {
  761. len = ((u16 *) (m + 1))[0];
  762. m += 3;
  763. }
  764. cdb = printstructlen(cdb, m, len);
  765. return cdb;
  766. }
  767. /*-------------------------------------------------------*/
  768. #define NAME (pnames[cmsg->par[cmsg->p]])
  769. static _cdebbuf *protocol_message_2_pars(_cdebbuf *cdb, _cmsg *cmsg, int level)
  770. {
  771. for (; TYP != _CEND; cmsg->p++) {
  772. int slen = 29 + 3 - level;
  773. int i;
  774. if (!cdb)
  775. return NULL;
  776. cdb = bufprint(cdb, " ");
  777. for (i = 0; i < level - 1; i++)
  778. cdb = bufprint(cdb, " ");
  779. switch (TYP) {
  780. case _CBYTE:
  781. cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l));
  782. cmsg->l++;
  783. break;
  784. case _CWORD:
  785. cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l));
  786. cmsg->l += 2;
  787. break;
  788. case _CDWORD:
  789. cdb = bufprint(cdb, "%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l));
  790. cmsg->l += 4;
  791. break;
  792. case _CSTRUCT:
  793. cdb = bufprint(cdb, "%-*s = ", slen, NAME);
  794. if (cmsg->m[cmsg->l] == '\0')
  795. cdb = bufprint(cdb, "default");
  796. else
  797. cdb = printstruct(cdb, cmsg->m + cmsg->l);
  798. cdb = bufprint(cdb, "\n");
  799. if (cmsg->m[cmsg->l] != 0xff)
  800. cmsg->l += 1 + cmsg->m[cmsg->l];
  801. else
  802. cmsg->l += 3 + *(u16 *) (cmsg->m + cmsg->l + 1);
  803. break;
  804. case _CMSTRUCT:
  805. /*----- Metastruktur 0 -----*/
  806. if (cmsg->m[cmsg->l] == '\0') {
  807. cdb = bufprint(cdb, "%-*s = default\n", slen, NAME);
  808. cmsg->l++;
  809. jumpcstruct(cmsg);
  810. } else {
  811. char *name = NAME;
  812. unsigned _l = cmsg->l;
  813. cdb = bufprint(cdb, "%-*s\n", slen, name);
  814. cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1;
  815. cmsg->p++;
  816. cdb = protocol_message_2_pars(cdb, cmsg, level + 1);
  817. }
  818. break;
  819. }
  820. }
  821. return cdb;
  822. }
  823. /*-------------------------------------------------------*/
  824. static _cdebbuf *g_debbuf;
  825. static u_long g_debbuf_lock;
  826. static _cmsg *g_cmsg;
  827. static _cdebbuf *cdebbuf_alloc(void)
  828. {
  829. _cdebbuf *cdb;
  830. if (likely(!test_and_set_bit(1, &g_debbuf_lock))) {
  831. cdb = g_debbuf;
  832. goto init;
  833. } else
  834. cdb = kmalloc(sizeof(_cdebbuf), GFP_ATOMIC);
  835. if (!cdb)
  836. return NULL;
  837. cdb->buf = kmalloc(CDEBUG_SIZE, GFP_ATOMIC);
  838. if (!cdb->buf) {
  839. kfree(cdb);
  840. return NULL;
  841. }
  842. cdb->size = CDEBUG_SIZE;
  843. init:
  844. cdb->buf[0] = 0;
  845. cdb->p = cdb->buf;
  846. cdb->pos = 0;
  847. return cdb;
  848. }
  849. /**
  850. * cdebbuf_free() - free CAPI debug buffer
  851. * @cdb: buffer to free
  852. */
  853. void cdebbuf_free(_cdebbuf *cdb)
  854. {
  855. if (likely(cdb == g_debbuf)) {
  856. test_and_clear_bit(1, &g_debbuf_lock);
  857. return;
  858. }
  859. if (likely(cdb))
  860. kfree(cdb->buf);
  861. kfree(cdb);
  862. }
  863. /**
  864. * capi_message2str() - format CAPI 2.0 message for printing
  865. * @msg: CAPI 2.0 message
  866. *
  867. * Allocates a CAPI debug buffer and fills it with a printable representation
  868. * of the CAPI 2.0 message in @msg.
  869. * Return value: allocated debug buffer, NULL on error
  870. * The returned buffer should be freed by a call to cdebbuf_free() after use.
  871. */
  872. _cdebbuf *capi_message2str(u8 * msg)
  873. {
  874. _cdebbuf *cdb;
  875. _cmsg *cmsg;
  876. cdb = cdebbuf_alloc();
  877. if (unlikely(!cdb))
  878. return NULL;
  879. if (likely(cdb == g_debbuf))
  880. cmsg = g_cmsg;
  881. else
  882. cmsg = kmalloc(sizeof(_cmsg), GFP_ATOMIC);
  883. if (unlikely(!cmsg)) {
  884. cdebbuf_free(cdb);
  885. return NULL;
  886. }
  887. cmsg->m = msg;
  888. cmsg->l = 8;
  889. cmsg->p = 0;
  890. byteTRcpy(cmsg->m + 4, &cmsg->Command);
  891. byteTRcpy(cmsg->m + 5, &cmsg->Subcommand);
  892. cmsg->par = cpars[command_2_index(cmsg->Command, cmsg->Subcommand)];
  893. cdb = bufprint(cdb, "%-26s ID=%03d #0x%04x LEN=%04d\n",
  894. mnames[command_2_index(cmsg->Command, cmsg->Subcommand)],
  895. ((unsigned short *) msg)[1],
  896. ((unsigned short *) msg)[3],
  897. ((unsigned short *) msg)[0]);
  898. cdb = protocol_message_2_pars(cdb, cmsg, 1);
  899. if (unlikely(cmsg != g_cmsg))
  900. kfree(cmsg);
  901. return cdb;
  902. }
  903. /**
  904. * capi_cmsg2str() - format _cmsg structure for printing
  905. * @cmsg: _cmsg structure
  906. *
  907. * Allocates a CAPI debug buffer and fills it with a printable representation
  908. * of the CAPI 2.0 message stored in @cmsg by a previous call to
  909. * capi_cmsg2message() or capi_message2cmsg().
  910. * Return value: allocated debug buffer, NULL on error
  911. * The returned buffer should be freed by a call to cdebbuf_free() after use.
  912. */
  913. _cdebbuf *capi_cmsg2str(_cmsg * cmsg)
  914. {
  915. _cdebbuf *cdb;
  916. if (!cmsg->m)
  917. return NULL; /* no message */
  918. cdb = cdebbuf_alloc();
  919. if (!cdb)
  920. return NULL;
  921. cmsg->l = 8;
  922. cmsg->p = 0;
  923. cdb = bufprint(cdb, "%s ID=%03d #0x%04x LEN=%04d\n",
  924. mnames[command_2_index(cmsg->Command, cmsg->Subcommand)],
  925. ((u16 *) cmsg->m)[1],
  926. ((u16 *) cmsg->m)[3],
  927. ((u16 *) cmsg->m)[0]);
  928. cdb = protocol_message_2_pars(cdb, cmsg, 1);
  929. return cdb;
  930. }
  931. int __init cdebug_init(void)
  932. {
  933. g_cmsg= kmalloc(sizeof(_cmsg), GFP_KERNEL);
  934. if (!g_cmsg)
  935. return -ENOMEM;
  936. g_debbuf = kmalloc(sizeof(_cdebbuf), GFP_KERNEL);
  937. if (!g_debbuf) {
  938. kfree(g_cmsg);
  939. return -ENOMEM;
  940. }
  941. g_debbuf->buf = kmalloc(CDEBUG_GSIZE, GFP_KERNEL);
  942. if (!g_debbuf->buf) {
  943. kfree(g_cmsg);
  944. kfree(g_debbuf);
  945. return -ENOMEM;
  946. }
  947. g_debbuf->size = CDEBUG_GSIZE;
  948. g_debbuf->buf[0] = 0;
  949. g_debbuf->p = g_debbuf->buf;
  950. g_debbuf->pos = 0;
  951. return 0;
  952. }
  953. void __exit cdebug_exit(void)
  954. {
  955. if (g_debbuf)
  956. kfree(g_debbuf->buf);
  957. kfree(g_debbuf);
  958. kfree(g_cmsg);
  959. }
  960. #else /* !CONFIG_CAPI_TRACE */
  961. static _cdebbuf g_debbuf = {"CONFIG_CAPI_TRACE not enabled", NULL, 0, 0};
  962. _cdebbuf *capi_message2str(u8 * msg)
  963. {
  964. return &g_debbuf;
  965. }
  966. _cdebbuf *capi_cmsg2str(_cmsg * cmsg)
  967. {
  968. return &g_debbuf;
  969. }
  970. void cdebbuf_free(_cdebbuf *cdb)
  971. {
  972. }
  973. int __init cdebug_init(void)
  974. {
  975. return 0;
  976. }
  977. void __exit cdebug_exit(void)
  978. {
  979. }
  980. #endif
  981. EXPORT_SYMBOL(cdebbuf_free);
  982. EXPORT_SYMBOL(capi_cmsg2message);
  983. EXPORT_SYMBOL(capi_message2cmsg);
  984. EXPORT_SYMBOL(capi_cmsg_header);
  985. EXPORT_SYMBOL(capi_cmd2str);
  986. EXPORT_SYMBOL(capi_cmsg2str);
  987. EXPORT_SYMBOL(capi_message2str);
  988. EXPORT_SYMBOL(capi_info2str);