1 /*****************************************************************************\
3 ** Linux-Call-Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
10 \*****************************************************************************/
16 PCM: A bit is defined as sample value. A 1 is positive level, a 0 negative.
17 The bit rate is 8000 Hz.
19 PWM: A bit is defined by a duration between polarity change of signal. 4
20 samples duration is 0, 12 samples duration is 1.
33 G=guard / sync sequnce (bit=1)
34 L=length information (lsb first)
36 C=CRC (lsb first, network byte order)
44 #define DOV_PWM_LEVEL 819
45 #define DOV_PCM_LEVEL 100
46 #define DOV_PCM_GUARD 400
47 #define DOV_PWM_GUARD 34
49 #define DOV_TX_SEND_DELAY 3, 0
50 #define DOV_RX_LISTEN_TIMEOUT 30, 0
52 static unsigned int dov_crc32_table[256];
54 inline unsigned int dov_crc_reflect(unsigned int ref, unsigned char ch)
56 unsigned int value = 0;
59 for (i = 1; i < ch + 1; i++) {
61 value |= 1 << (ch - i);
69 * initialize CRC table
71 void dov_crc_init(void)
73 unsigned int ulPolynomial = 0x04c11db7;
76 for (i = 0; i < 256; i++) {
77 dov_crc32_table[i] = dov_crc_reflect(i, 8) << 24;
78 for (j = 0; j < 8; j++)
79 dov_crc32_table[i] = (dov_crc32_table[i] << 1) ^
80 (dov_crc32_table[i] & (1 << 31) ?
83 dov_crc_reflect(dov_crc32_table[i], 32);
89 * calculate CRC 32 of given data
91 * data: pointer to data
92 * length: length of data
95 unsigned int dov_crc32(unsigned char *data, int length)
97 unsigned int crc = 0xffffffff;
100 crc = (crc >> 8) ^ dov_crc32_table[(crc & 0xff) ^ *data++];
102 return crc ^ 0xffffffff;
105 int dov_tx_timer(struct lcr_timer *timer, void *instance, int index);
106 int dov_rx_timer(struct lcr_timer *timer, void *instance, int index);
108 void Port::dov_init(void)
111 printf("DOV: init\n");
117 p_dov_tx_data = NULL;
118 p_dov_rx_data = NULL;
119 memset(&p_dov_tx_timer, 0, sizeof(p_dov_tx_timer));
120 add_timer(&p_dov_tx_timer, dov_tx_timer, this, 0);
121 memset(&p_dov_rx_timer, 0, sizeof(p_dov_rx_timer));
122 add_timer(&p_dov_rx_timer, dov_rx_timer, this, 0);
126 void Port::dov_reset_tx(void)
129 printf("DOV: reset TX\n");
133 FREE(p_dov_tx_data, p_dov_tx_data_length);
134 p_dov_tx_data = NULL;
136 unsched_timer(&p_dov_tx_timer);
139 void Port::dov_reset_rx(void)
142 printf("DOV: reset RX\n");
146 FREE(p_dov_rx_data, 255 + 5);
147 p_dov_rx_data = NULL;
150 unsched_timer(&p_dov_rx_timer);
153 void Port::dov_exit(void)
156 printf("DOV: exit\n");
160 del_timer(&p_dov_tx_timer);
162 del_timer(&p_dov_rx_timer);
165 void Port::dov_sendmsg(unsigned char *data, int length, enum dov_type type, int level)
170 printf("DOV: send message, start timer\n");
177 p_dov_tx_data = (unsigned char *)MALLOC(length + 5);
178 p_dov_tx_data[0] = length;
179 memcpy(p_dov_tx_data + 1, data, length);
180 crc = dov_crc32(data, length);
181 p_dov_tx_data[length+1] = crc >> 24;
182 p_dov_tx_data[length+2] = crc >> 16;
183 p_dov_tx_data[length+3] = crc >> 8;
184 p_dov_tx_data[length+4] = crc;
185 p_dov_tx_data_length = length + 5;
186 p_dov_tx_data_pos = 0;
188 p_dov_tx_bit_pos = 0;
189 p_dov_tx_pwm_pos = 0;
191 p_dov_tx_type = type;
193 p_dov_up = audio_s16_to_law[(level) & 0xffff];
194 p_dov_down = audio_s16_to_law[(-level) & 0xffff];
195 } else if (type == DOV_TYPE_PWM) {
196 p_dov_up = audio_s16_to_law[(DOV_PWM_LEVEL) & 0xffff];
197 p_dov_down = audio_s16_to_law[(-DOV_PWM_LEVEL) & 0xffff];
199 p_dov_up = audio_s16_to_law[(DOV_PCM_LEVEL) & 0xffff];
200 p_dov_down = audio_s16_to_law[(-DOV_PCM_LEVEL) & 0xffff];
203 schedule_timer(&p_dov_tx_timer, DOV_TX_SEND_DELAY);
206 int dov_tx_timer(struct lcr_timer *timer, void *instance, int index)
208 class Port *port = (class Port *)instance;
211 printf("DOV: timer fires, now sending\n");
219 int Port::dov_tx(unsigned char *data, int length)
226 switch (p_dov_tx_type) {
229 printf("DOV: prepare %d bytes of PWM data\n", length);
231 left = dov_tx_pwm(data, length);
235 printf("DOV: prepare %d bytes of PCM data\n", length);
237 left = dov_tx_pcm(data, length);
241 return length - left;
244 int Port::dov_tx_pwm(unsigned char *data, int length)
247 /* send sync / guard sequence */
250 while (p_dov_tx_pwm_pos < 12) {
258 while (p_dov_tx_pwm_pos < 12) {
259 *data++ = p_dov_down;
266 p_dov_tx_pwm_pos = 0;
267 if (++p_dov_tx_bit_pos == DOV_PWM_GUARD) {
269 printf("DOV: TX, done with guard\n");
271 p_dov_tx_bit_pos = -1;
272 if (p_dov_tx_sync == 2) {
281 /* send start of byte */
282 if (p_dov_tx_data_length == -1) {
284 while (p_dov_tx_pwm_pos < 4) {
292 while (p_dov_tx_pwm_pos < 4) {
293 *data++ = p_dov_down;
300 p_dov_tx_pwm_pos = 0;
301 p_dov_tx_bit_pos = 0;
306 if ((p_dov_tx_data[p_dov_tx_data_pos] >> p_dov_tx_bit_pos) & 1) {
308 while (p_dov_tx_pwm_pos < 12) {
316 while (p_dov_tx_pwm_pos < 12) {
317 *data++ = p_dov_down;
326 while (p_dov_tx_pwm_pos < 4) {
334 while (p_dov_tx_pwm_pos < 4) {
335 *data++ = p_dov_down;
343 p_dov_tx_pwm_pos = 0;
344 if (++p_dov_tx_bit_pos == 8) {
345 p_dov_tx_bit_pos = -1;
347 printf("DOV: TX, done with byte %d\n", p_dov_tx_data[p_dov_tx_data_pos]);
349 if (p_dov_tx_data_pos++ == p_dov_tx_data_length) {
358 int Port::dov_tx_pcm(unsigned char *data, int length)
361 /* send sync / guard sequence */
364 if (++p_dov_tx_bit_pos == DOV_PCM_GUARD) {
366 printf("DOV: TX, done with guard\n");
368 p_dov_tx_bit_pos = -1;
369 if (p_dov_tx_sync == 2) {
378 /* send start of byte */
379 if (p_dov_tx_data_length == -1) {
380 *data++ = p_dov_down;
381 p_dov_tx_bit_pos = 0;
386 *data++ = (((p_dov_tx_data[p_dov_tx_data_pos] >> p_dov_tx_bit_pos) & 1)) ? p_dov_up : p_dov_down;
387 if (++p_dov_tx_bit_pos == 8) {
388 p_dov_tx_bit_pos = -1;
390 printf("DOV: TX, done with byte %d\n", p_dov_tx_data[p_dov_tx_data_pos]);
392 if (p_dov_tx_data_pos++ == p_dov_tx_data_length) {
401 void Port::dov_listen(enum dov_type type)
404 printf("DOV: start listening, start timer\n");
409 p_dov_rx_data = (unsigned char *)MALLOC(255 + 5);
410 p_dov_rx_data_pos = 0;
412 p_dov_rx_bit_pos = 0;
413 p_dov_rx_pwm_pos = 0;
414 p_dov_rx_pwm_duration = 0;
415 p_dov_rx_pwm_polarity = 0;
416 p_dov_rx_sync_word = 0;
418 p_dov_rx_type = type;
423 schedule_timer(&p_dov_rx_timer, DOV_RX_LISTEN_TIMEOUT);
426 int dov_rx_timer(struct lcr_timer *timer, void *instance, int index)
428 class Port *port = (class Port *)instance;
431 printf("DOV: timer fires, now stop listening\n");
434 port->dov_reset_rx();
439 void Port::dov_rx(unsigned char *data, int length)
444 switch (p_dov_rx_type) {
447 printf("DOV: received %d bytes of PWM data\n", length);
449 dov_rx_pwm(data, length);
453 printf("DOV: received %d bytes of PCM data\n", length);
455 dov_rx_pcm(data, length);
460 void Port::dov_rx_pwm(unsigned char *data, int length)
466 sample = audio_law_to_s32[*data++];
467 p_dov_rx_pwm_duration++;
468 if (p_dov_rx_pwm_polarity == 1) {
471 p_dov_rx_pwm_polarity = 0;
472 if (p_dov_rx_pwm_duration < 8)
476 p_dov_rx_pwm_duration = 0;
480 p_dov_rx_pwm_polarity = 1;
481 if (p_dov_rx_pwm_duration < 8)
485 p_dov_rx_pwm_duration = 0;
489 p_dov_rx_sync_word <<= 1;
491 p_dov_rx_sync_word |= 1;
492 if ((p_dov_rx_sync_word & 0x1ff) == 0x1ff) {
493 p_dov_rx_bit_pos = -1;
495 p_dov_rx_data_pos = 0;
499 if (!p_dov_rx_sync) {
503 if (p_dov_rx_bit_pos == -1) {
504 /* check violation of start bit */
509 p_dov_rx_bit_pos = 0;
513 p_dov_rx_data[p_dov_rx_data_pos] >>= 1;
515 p_dov_rx_data[p_dov_rx_data_pos] |= 128;
516 if (++p_dov_rx_bit_pos == 8) {
518 printf("DOV: RX byte %d\n", p_dov_rx_data[p_dov_rx_data_pos]);
520 p_dov_rx_bit_pos = -1;
521 /* check for length,data,crc32 */
522 if (++p_dov_rx_data_pos == p_dov_rx_data[0] + 5) {
523 dov_message(p_dov_rx_data + 1, p_dov_rx_data[0]);
531 void Port::dov_rx_pcm(unsigned char *data, int length)
536 level = audio_law_to_s32[*data++];
538 p_dov_rx_sync_word <<= 1;
540 p_dov_rx_sync_word |= 1;
541 if ((p_dov_rx_sync_word & 0x1ff) == 0x1ff) {
542 p_dov_rx_bit_pos = -1;
544 p_dov_rx_data_pos = 0;
548 if (!p_dov_rx_sync) {
552 if (p_dov_rx_bit_pos == -1) {
553 /* check violation of start bit */
558 p_dov_rx_bit_pos = 0;
562 p_dov_rx_data[p_dov_rx_data_pos] >>= 1;
564 p_dov_rx_data[p_dov_rx_data_pos] |= 128;
565 if (++p_dov_rx_bit_pos == 8) {
567 printf("DOV: RX byte %d\n", p_dov_rx_data[p_dov_rx_data_pos]);
569 p_dov_rx_bit_pos = -1;
570 /* check for length,data,crc32 */
571 if (++p_dov_rx_data_pos == p_dov_rx_data[0] + 5) {
572 dov_message(p_dov_rx_data + 1, p_dov_rx_data[0]);
579 void Port::dov_message(unsigned char *data, int length)
582 struct lcr_msg *message;
584 /* prevent receiving zeroes (due to line noise). this would cause 0 crc, which seems correct. */
589 printf("DOV: received message\n");
592 crc = dov_crc32(p_dov_rx_data + 1, p_dov_rx_data[0]);
593 if (crc != (unsigned int) ( ((p_dov_rx_data[length+1]) << 24) |
594 ((p_dov_rx_data[length+2]) << 16) |
595 ((p_dov_rx_data[length+3]) << 8) |
596 (p_dov_rx_data[length+4]) ))
600 printf("DOV: crc OK\n");
603 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DOV_INDICATION);
604 message->param.dov.type = p_dov_rx_type;
605 message->param.dov.length = p_dov_rx_data[0];
606 memcpy(message->param.dov.data, p_dov_rx_data + 1, p_dov_rx_data[0]);
607 PDEBUG(DEBUG_PORT, "PmISDN(%s) Data-Over-Voice message received (len=%d)\n", p_name, message->param.dov.length);
608 message_put(message);