chan_modem_bestdata.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. /*
  2. * Asterisk -- A telephony toolkit for Linux.
  3. *
  4. * BestData 56SX-92 Voice Modem Driver (Conexant)
  5. *
  6. * Copyright (C) 1999, Mark Spencer and 2001 Jim Dixon
  7. *
  8. * Mark Spencer <markster@linux-support.net>
  9. * Jim Dixon <jim@lambdatel.com>
  10. *
  11. * This program is free software, distributed under the terms of
  12. * the GNU General Public License
  13. */
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <stdlib.h>
  17. #include <errno.h>
  18. #include <unistd.h>
  19. #include <asterisk/lock.h>
  20. #include <asterisk/vmodem.h>
  21. #include <asterisk/module.h>
  22. #include <asterisk/frame.h>
  23. #include <asterisk/logger.h>
  24. #include <asterisk/options.h>
  25. #define STATE_COMMAND 0
  26. #define STATE_VOICE 1
  27. #define STATE_VOICEPLAY 2
  28. #define VRA "40" /* Number of 100ms of non-ring after a ring cadence after which we consider the lien to be answered */
  29. #define VRN "25" /* Number of 100ms of non-ring with no cadence after which we assume an answer */
  30. #define RINGT 7000
  31. static char *breakcmd = "\020!";
  32. static char *desc = "BestData (Conexant V.90 Chipset) VoiceModem Driver";
  33. static int usecnt;
  34. AST_MUTEX_DEFINE_STATIC(usecnt_lock);
  35. static char *bestdata_idents[] = {
  36. /* Identify BestData Modem */
  37. "ACF3_V1.010-V90_P21_FSH",
  38. NULL
  39. };
  40. static int bestdata_break(struct ast_modem_pvt *p);
  41. static int bestdata_startrec(struct ast_modem_pvt *p)
  42. {
  43. if (p->ministate != STATE_COMMAND) bestdata_break(p);
  44. if (ast_modem_send(p, "AT+VRX", 0) ||
  45. ast_modem_expect(p, "CONNECT", 5)) {
  46. ast_log(LOG_WARNING, "Unable to start recording\n");
  47. return -1;
  48. }
  49. p->ministate = STATE_VOICE;
  50. return 0;
  51. }
  52. static int bestdata_startplay(struct ast_modem_pvt *p)
  53. {
  54. if (p->ministate != STATE_COMMAND) bestdata_break(p);
  55. if (ast_modem_send(p, "AT+VTX", 0) ||
  56. ast_modem_expect(p, "CONNECT", 5)) {
  57. ast_log(LOG_WARNING, "Unable to start recording\n");
  58. return -1;
  59. }
  60. p->ministate = STATE_VOICEPLAY;
  61. return 0;
  62. }
  63. static int bestdata_break(struct ast_modem_pvt *p)
  64. {
  65. if (ast_modem_send(p, breakcmd, 2)) {
  66. ast_log(LOG_WARNING, "Failed to break\n");
  67. return -1;
  68. }
  69. p->ministate = STATE_COMMAND;
  70. usleep(10000);
  71. /* Read any outstanding junk */
  72. while(!ast_modem_read_response(p, 1));
  73. if (ast_modem_send(p, "AT", 0)) {
  74. /* Modem might be stuck in some weird mode, try to get it out */
  75. ast_modem_send(p, "+++", 3);
  76. if (ast_modem_expect(p, "OK", 10)) {
  77. ast_log(LOG_WARNING, "Modem is not responding\n");
  78. return -1;
  79. }
  80. if (ast_modem_send(p, "AT", 0)) {
  81. ast_log(LOG_WARNING, "Modem is not responding\n");
  82. return -1;
  83. }
  84. }
  85. if (ast_modem_expect(p, "OK", 5)) {
  86. ast_log(LOG_WARNING, "Modem did not respond properly\n");
  87. return -1;
  88. }
  89. return 0;
  90. }
  91. static int bestdata_init(struct ast_modem_pvt *p)
  92. {
  93. if (option_debug)
  94. ast_log(LOG_DEBUG, "bestdata_init()\n");
  95. if (bestdata_break(p))
  96. return -1;
  97. /* Force into command mode */
  98. p->ministate = STATE_COMMAND;
  99. if (ast_modem_send(p, "AT+FCLASS=8", 0) ||
  100. ast_modem_expect(p, "OK", 5)) {
  101. ast_log(LOG_WARNING, "Unable to set to voice mode\n");
  102. return -1;
  103. }
  104. if (ast_modem_send(p, "AT+VSM=1,8000,0,0", 0) ||
  105. ast_modem_expect(p, "OK", 5)) {
  106. ast_log(LOG_WARNING, "Unable to set to 8000 Hz sampling\n");
  107. return -1;
  108. }
  109. if (ast_modem_send(p, "AT+VLS=0", 0) ||
  110. ast_modem_expect(p, "OK", 5)) {
  111. ast_log(LOG_WARNING, "Unable to set to telco interface\n");
  112. return -1;
  113. }
  114. if (ast_modem_send(p, "AT+VRA=" VRA, 0) ||
  115. ast_modem_expect(p, "OK", 5)) {
  116. ast_log(LOG_WARNING, "Unable to set to 'ringback goes away' timer\n");
  117. return -1;
  118. }
  119. if (ast_modem_send(p, "AT+VRN=" VRN, 0) ||
  120. ast_modem_expect(p, "OK", 5)) {
  121. ast_log(LOG_WARNING, "Unable to set to 'ringback never came timer'\n");
  122. return -1;
  123. }
  124. if (ast_modem_send(p, "AT+VTD=63", 0) ||
  125. ast_modem_expect(p, "OK", 5)) {
  126. ast_log(LOG_WARNING, "Unable to set to tone detection\n");
  127. return -1;
  128. }
  129. if (ast_modem_send(p, "AT+VCID=1", 0) ||
  130. ast_modem_expect(p, "OK", 5)) {
  131. ast_log(LOG_WARNING, "Unable to enable Caller*ID\n");
  132. return -1;
  133. }
  134. return 0;
  135. }
  136. static struct ast_frame *bestdata_handle_escape(struct ast_modem_pvt *p, char esc)
  137. {
  138. char name[30]="",nmbr[30]="";
  139. time_t now;
  140. /* Handle escaped characters -- but sometimes we call it directly as
  141. a quick way to cause known responses */
  142. p->fr.frametype = AST_FRAME_NULL;
  143. p->fr.subclass = 0;
  144. p->fr.data = NULL;
  145. p->fr.datalen = 0;
  146. p->fr.samples = 0;
  147. p->fr.offset = 0;
  148. p->fr.mallocd = 0;
  149. p->fr.delivery.tv_sec = 0;
  150. p->fr.delivery.tv_usec = 0;
  151. if (esc)
  152. ast_log(LOG_DEBUG, "Escaped character '%c'\n", esc);
  153. switch(esc) {
  154. case 'R': /* Pseudo ring */
  155. time(&now);
  156. if (now > (p->lastring + (RINGT / 1000)))
  157. { /* if stale, treat as new */
  158. p->gotclid = 0;
  159. }
  160. if (p->gotclid)
  161. {
  162. p->fr.frametype = AST_FRAME_CONTROL;
  163. p->fr.subclass = AST_CONTROL_RING;
  164. }
  165. p->ringt = RINGT;
  166. time(&p->lastring);
  167. return &p->fr;
  168. case 'X': /* Caller-ID Spill */
  169. if (p->gotclid) return &p->fr;
  170. name[0] = nmbr[0] = 0;
  171. for(;;)
  172. {
  173. char res[1000]="";
  174. if (ast_modem_read_response(p, 5)) break;
  175. strncpy(res, p->response, sizeof(res)-1);
  176. ast_modem_trim(res);
  177. if (!strncmp(res,"\020.",2)) break;
  178. if (!strncmp(res,"NAME",4)) strncpy(name,res + 7, sizeof(name) - 1);
  179. if (!strncmp(res,"NMBR",4)) strncpy(nmbr,res + 7, sizeof(nmbr) - 1);
  180. }
  181. p->gotclid = 1;
  182. if ((!strcmp(name,"O")) || (!strcmp(name,"P"))) name[0] = 0;
  183. if ((!strcmp(nmbr,"O")) || (!strcmp(nmbr,"P"))) nmbr[0] = 0;
  184. if ((name[0]) && (nmbr[0])) snprintf(p->cid,sizeof(p->cid),
  185. "\"%s\" <%s>",name,nmbr);
  186. else if (name[0]) snprintf(p->cid,sizeof(p->cid),
  187. "\"%s\"",name);
  188. else if (nmbr[0]) snprintf(p->cid,sizeof(p->cid),
  189. "%s",nmbr);
  190. if (p->owner) p->owner->callerid = strdup(p->cid);
  191. return &p->fr;
  192. case '@': /* response from "OK" in command mode */
  193. if (p->owner)
  194. ast_setstate(p->owner, AST_STATE_UP);
  195. if (bestdata_startrec(p)) return NULL;
  196. p->fr.frametype = AST_FRAME_CONTROL;
  197. p->fr.subclass = AST_CONTROL_RING;
  198. return &p->fr;
  199. case 'b': /* Busy signal */
  200. p->fr.frametype = AST_FRAME_CONTROL;
  201. p->fr.subclass = AST_CONTROL_BUSY;
  202. return &p->fr;
  203. case 'o': /* Overrun */
  204. ast_log(LOG_WARNING, "Overflow on modem, flushing buffers\n");
  205. if (ast_modem_send(p, "\0x10E", 2))
  206. ast_log(LOG_WARNING, "Unable to flush buffers\n");
  207. return &p->fr;
  208. case '0': /* All the DTMF characters */
  209. case '1':
  210. case '2':
  211. case '3':
  212. case '4':
  213. case '5':
  214. case '6':
  215. case '7':
  216. case '8':
  217. case '9':
  218. case '*':
  219. case '#':
  220. case 'A':
  221. case 'B':
  222. case 'C':
  223. case 'D':
  224. p->dtmfrx = esc; /* save this for when its done */
  225. return &p->fr;
  226. case '/': /* Start of DTMF tone shielding */
  227. p->dtmfrx = ' ';
  228. return &p->fr;
  229. case '~': /* DTMF transition to off */
  230. if (p->dtmfrx > ' ')
  231. {
  232. p->fr.frametype = AST_FRAME_DTMF;
  233. p->fr.subclass = p->dtmfrx;
  234. }
  235. p->dtmfrx = 0;
  236. return &p->fr;
  237. case 'u': /* Underrun */
  238. ast_log(LOG_WARNING, "Data underrun\n");
  239. /* Fall Through */
  240. case CHAR_ETX: /* End Transmission */
  241. case 'd': /* Dialtone */
  242. case 'c': /* Calling Tone */
  243. case 'e': /* European version */
  244. case 'a': /* Answer Tone */
  245. case 'f': /* Bell Answer Tone */
  246. case 'T': /* Timing mark */
  247. case 't': /* Handset off hook */
  248. case 'h': /* Handset hungup */
  249. case 0: /* Pseudo signal */
  250. /* Ignore */
  251. return &p->fr;
  252. default:
  253. ast_log(LOG_DEBUG, "Unknown Escaped character '%c' (%d)\n", esc, esc);
  254. }
  255. return &p->fr;
  256. }
  257. static struct ast_frame *bestdata_read(struct ast_modem_pvt *p)
  258. {
  259. char result[256];
  260. short *b;
  261. struct ast_frame *f=NULL;
  262. int res;
  263. int x;
  264. if (p->ministate == STATE_COMMAND) {
  265. /* Read the first two bytes, first, in case it's a control message */
  266. fread(result, 1, 2, p->f);
  267. if (result[0] == CHAR_DLE) {
  268. return bestdata_handle_escape(p, result[1]);
  269. } else {
  270. if (p->ringt) /* if ring timeout specified */
  271. {
  272. x = fileno(p->f);
  273. res = ast_waitfor_n_fd(&x, 1, &p->ringt, NULL);
  274. if (res < 0) {
  275. return NULL;
  276. }
  277. }
  278. if ((result[0] == '\n') || (result[0] == '\r'))
  279. return bestdata_handle_escape(p, 0);
  280. /* Read the rest of the line */
  281. fgets(result + 2, sizeof(result) - 2, p->f);
  282. ast_modem_trim(result);
  283. if (!strcasecmp(result, "OK")) {
  284. /* If we're in immediate mode, reply now */
  285. if (p->mode == MODEM_MODE_IMMEDIATE)
  286. return bestdata_handle_escape(p, '@');
  287. } else
  288. if (!strcasecmp(result, "BUSY")) {
  289. /* Same as a busy signal */
  290. return bestdata_handle_escape(p, 'b');
  291. } else
  292. if (!strcasecmp(result, "RING")) {
  293. return bestdata_handle_escape(p, 'R');
  294. } else
  295. if (!strcasecmp(result, "NO DIALTONE")) {
  296. /* There's no dialtone, so the line isn't working */
  297. ast_log(LOG_WARNING, "Device '%s' lacking dialtone\n", p->dev);
  298. return NULL;
  299. }
  300. ast_log(LOG_DEBUG, "Modem said '%s'\n", result);
  301. return bestdata_handle_escape(p, 0);
  302. }
  303. } else {
  304. /* if playing, start recording instead */
  305. if (p->ministate == STATE_VOICEPLAY)
  306. {
  307. if (bestdata_startrec(p)) return NULL;
  308. }
  309. /* We have to be more efficient in voice mode */
  310. b = (short *)(p->obuf + p->obuflen);
  311. while (p->obuflen/2 < 240) {
  312. /* Read ahead the full amount */
  313. res = fread(result, 1, 240 - p->obuflen/2, p->f);
  314. if (res < 1) {
  315. /* If there's nothing there, just continue on */
  316. if (errno == EAGAIN)
  317. return bestdata_handle_escape(p, 0);
  318. ast_log(LOG_WARNING, "Read failed: %s\n", strerror(errno));
  319. }
  320. for (x=0;x<res;x++) {
  321. /* Process all the bytes that we've read */
  322. if (result[x] == CHAR_DLE) {
  323. /* We assume there is no more than one signal frame among our
  324. data. */
  325. if (f) ast_log(LOG_WARNING, "Warning: Dropped a signal frame\n");
  326. /* if not a DLE in the data */
  327. if (result[++x] != CHAR_DLE)
  328. {
  329. /* If bestdata_handle_escape says NULL, say it now, doesn't matter
  330. what else is there, the connection is dead. */
  331. f = bestdata_handle_escape(p, result[x]);
  332. if (p->dtmfrx) continue;
  333. return(f);
  334. }
  335. }
  336. /* Generate a 16-bit signed linear value from our
  337. unsigned 8-bit value */
  338. *(b++) = (((short)result[x]) - 127) * 0xff;
  339. p->obuflen += 2;
  340. }
  341. if (f) break;
  342. }
  343. /* If we have a control frame, return it now */
  344. if (f) return f;
  345. /* If we get here, we have a complete voice frame */
  346. p->fr.frametype = AST_FRAME_VOICE;
  347. p->fr.subclass = AST_FORMAT_SLINEAR;
  348. p->fr.samples = 240;
  349. p->fr.data = p->obuf;
  350. p->fr.datalen = p->obuflen;
  351. p->fr.mallocd = 0;
  352. p->fr.delivery.tv_sec = 0;
  353. p->fr.delivery.tv_usec = 0;
  354. p->fr.offset = AST_FRIENDLY_OFFSET;
  355. p->fr.src = __FUNCTION__;
  356. if (option_debug)
  357. ast_log(LOG_DEBUG, "bestdata_read(voice frame)\n");
  358. p->obuflen = 0;
  359. return &p->fr;
  360. }
  361. return NULL;
  362. }
  363. static int bestdata_write(struct ast_modem_pvt *p, struct ast_frame *f)
  364. {
  365. unsigned char c,buf[32768]; /* I hope we dont have frames larger then 16K */
  366. int i,j;
  367. short *sp;
  368. unsigned long u;
  369. #define DLE 16
  370. if (p->owner && (p->owner->_state == AST_STATE_UP) &&
  371. (p->ministate != STATE_VOICEPLAY) && bestdata_startplay(p)) return -1;
  372. sp = (short *) f->data;
  373. /* stick DLE's in ahead of anything else */
  374. for(i = 0,j = 0; i < f->datalen / 2; i++)
  375. {
  376. *sp *= 3;
  377. u = *sp++ + 32768;
  378. c = u >> 8;
  379. if (c == DLE) buf[j++] = DLE;
  380. buf[j++] = c;
  381. }
  382. do i = fwrite(buf,1,j,p->f);
  383. while ((i == -1) && (errno == EWOULDBLOCK));
  384. if (i != j)
  385. {
  386. ast_log(LOG_WARNING,"modem short write!!\n");
  387. return -1;
  388. }
  389. fflush(p->f);
  390. if (option_debug)
  391. ast_log(LOG_DEBUG, "bestdata_write()\n");
  392. return 0;
  393. }
  394. static char *bestdata_identify(struct ast_modem_pvt *p)
  395. {
  396. char identity[256];
  397. char mfr[80];
  398. char mdl[80];
  399. char rev[80];
  400. ast_modem_send(p, "AT+FMM", 0);
  401. ast_modem_read_response(p, 5);
  402. strncpy(mdl, p->response, sizeof(mdl)-1);
  403. ast_modem_trim(mdl);
  404. ast_modem_expect(p, "OK", 5);
  405. ast_modem_send(p, "AT+FMI", 0);
  406. ast_modem_read_response(p, 5);
  407. strncpy(mfr, p->response, sizeof(mfr)-1);
  408. ast_modem_trim(mfr);
  409. ast_modem_expect(p, "OK", 5);
  410. ast_modem_send(p, "AT+FMR", 0);
  411. ast_modem_read_response(p, 5);
  412. strncpy(rev, p->response, sizeof(rev)-1);
  413. ast_modem_trim(rev);
  414. ast_modem_expect(p, "OK", 5);
  415. snprintf(identity, sizeof(identity), "%s Model %s Revision %s", mfr, mdl, rev);
  416. return strdup(identity);
  417. }
  418. static void bestdata_incusecnt(void)
  419. {
  420. ast_mutex_lock(&usecnt_lock);
  421. usecnt++;
  422. ast_mutex_unlock(&usecnt_lock);
  423. ast_update_use_count();
  424. }
  425. static void bestdata_decusecnt(void)
  426. {
  427. ast_mutex_lock(&usecnt_lock);
  428. usecnt++;
  429. ast_mutex_unlock(&usecnt_lock);
  430. ast_update_use_count();
  431. }
  432. static int bestdata_answer(struct ast_modem_pvt *p)
  433. {
  434. p->ringt = 0;
  435. p->lastring = 0;
  436. if (ast_modem_send(p, "AT+VLS=1", 0) ||
  437. ast_modem_expect(p, "OK", 10)) {
  438. ast_log(LOG_WARNING, "Unable to answer: %s", p->response);
  439. return -1;
  440. }
  441. return 0;
  442. }
  443. static int bestdata_dialdigit(struct ast_modem_pvt *p, char digit)
  444. {
  445. char cmd[80];
  446. if (p->ministate != STATE_COMMAND) bestdata_break(p);
  447. snprintf(cmd, sizeof(cmd), "AT+VTS=%c", digit);
  448. if (ast_modem_send(p, cmd, 0) ||
  449. ast_modem_expect(p, "OK", 10)) {
  450. ast_log(LOG_WARNING, "Unable to answer: %s", p->response);
  451. return -1;
  452. }
  453. return 0;
  454. }
  455. static int bestdata_dial(struct ast_modem_pvt *p, char *stuff)
  456. {
  457. char cmd[800] = "",a[20]="";
  458. int i,j;
  459. if (p->ministate != STATE_COMMAND)
  460. {
  461. bestdata_break(p);
  462. strncpy(cmd, "AT+VTS=", sizeof(cmd) - 1);
  463. j = strlen(cmd);
  464. for(i = 0; stuff[i]; i++)
  465. {
  466. switch(stuff[i])
  467. {
  468. case '!' :
  469. a[0] = stuff[i];
  470. a[1] = 0;
  471. break;
  472. case ',':
  473. strncpy(a, "[,,100]", sizeof(a) - 1);
  474. break;
  475. default:
  476. snprintf(a, sizeof(a), "{%c,7}", stuff[i]);
  477. }
  478. if (stuff[i + 1]) strncat(a, ",", sizeof(a) - strlen(a) - 1);
  479. strncpy(cmd + j, a, sizeof(cmd) - j - 1);
  480. j += strlen(a);
  481. }
  482. }
  483. else
  484. {
  485. snprintf(cmd, sizeof(cmd), "ATD%c %s", p->dialtype,stuff);
  486. }
  487. if (ast_modem_send(p, cmd, 0)) {
  488. ast_log(LOG_WARNING, "Unable to dial\n");
  489. return -1;
  490. }
  491. return 0;
  492. }
  493. static int bestdata_hangup(struct ast_modem_pvt *p)
  494. {
  495. if (bestdata_break(p))
  496. return -1;
  497. /* Hangup by switching to data, then back to voice */
  498. if (ast_modem_send(p, "ATH", 0) ||
  499. ast_modem_expect(p, "OK", 8)) {
  500. ast_log(LOG_WARNING, "Unable to set to data mode\n");
  501. return -1;
  502. }
  503. if (ast_modem_send(p, "AT+FCLASS=8", 0) ||
  504. ast_modem_expect(p, "OK", 5)) {
  505. ast_log(LOG_WARNING, "Unable to set to voice mode\n");
  506. return -1;
  507. }
  508. p->gotclid = 0;
  509. p->ringt = 0;
  510. p->lastring = 0;
  511. p->dtmfrx = 0;
  512. return 0;
  513. }
  514. static struct ast_modem_driver bestdata_driver =
  515. {
  516. "BestData",
  517. bestdata_idents,
  518. AST_FORMAT_SLINEAR,
  519. 0, /* Not full duplex */
  520. bestdata_incusecnt, /* incusecnt */
  521. bestdata_decusecnt, /* decusecnt */
  522. bestdata_identify, /* identify */
  523. bestdata_init, /* init */
  524. NULL, /* setdev */
  525. bestdata_read,
  526. bestdata_write,
  527. bestdata_dial, /* dial */
  528. bestdata_answer, /* answer */
  529. bestdata_hangup, /* hangup */
  530. bestdata_startrec, /* start record */
  531. NULL, /* stop record */
  532. bestdata_startplay, /* start playback */
  533. NULL, /* stop playback */
  534. NULL, /* set silence supression */
  535. bestdata_dialdigit, /* dialdigit */
  536. };
  537. int usecount(void)
  538. {
  539. int res;
  540. ast_mutex_lock(&usecnt_lock);
  541. res = usecnt;
  542. ast_mutex_unlock(&usecnt_lock);
  543. return res;
  544. }
  545. int load_module(void)
  546. {
  547. return ast_register_modem_driver(&bestdata_driver);
  548. }
  549. int unload_module(void)
  550. {
  551. return ast_unregister_modem_driver(&bestdata_driver);
  552. }
  553. char *description()
  554. {
  555. return desc;
  556. }
  557. char *key()
  558. {
  559. return ASTERISK_GPL_KEY;
  560. }