📄 ixj.c
字号:
ixj_init_tone(board, &ti); ti.tone_index = 24; ti.gain0 = 1; ti.freq0 = hz2450; ti.gain1 = 0; ti.freq1 = 0; ixj_init_tone(board, &ti); ti.tone_index = 25; ti.gain0 = 1; ti.freq0 = hz350; ti.gain1 = 0; ti.freq1 = hz440; ixj_init_tone(board, &ti); ti.tone_index = 26; ti.gain0 = 1; ti.freq0 = hz440; ti.gain1 = 0; ti.freq1 = hz480; ixj_init_tone(board, &ti); ti.tone_index = 27; ti.gain0 = 1; ti.freq0 = hz480; ti.gain1 = 0; ti.freq1 = hz620; ixj_init_tone(board, &ti); idle(board); if (file_p->f_mode & FMODE_READ) j->readers--; if (file_p->f_mode & FMODE_WRITE) j->writers--; if (j->read_buffer && !j->readers) { kfree(j->read_buffer); j->read_buffer = NULL; j->read_buffer_size = 0; } if (j->write_buffer && !j->writers) { kfree(j->write_buffer); j->write_buffer = NULL; j->write_buffer_size = 0; } j->rec_codec = j->play_codec = 0; j->rec_frame_size = j->play_frame_size = 0; ixj_fasync(-1, file_p, 0); // remove from list of async notification MOD_DEC_USE_COUNT; return 0;}static int read_filters(int board){ unsigned short fc, cnt; IXJ *j = &ixj[board]; if (ixj_WriteDSPCommand(0x5144, board)) return -1; fc = j->ssr.high << 8 | j->ssr.low; if (fc == j->frame_count) return 1; j->frame_count = fc; for (cnt = 0; cnt < 4; cnt++) { if (ixj_WriteDSPCommand(0x5154 + cnt, board)) return -1; if (ixj_WriteDSPCommand(0x515C, board)) return -1; j->filter_hist[cnt] = j->ssr.high << 8 | j->ssr.low; if ((j->filter_hist[cnt] & 1 && !(j->filter_hist[cnt] & 2)) || (j->filter_hist[cnt] & 2 && !(j->filter_hist[cnt] & 1))) { switch (cnt) { case 0: j->ex.bits.f0 = 1; break; case 1: j->ex.bits.f1 = 1; break; case 2: j->ex.bits.f2 = 1; break; case 3: j->ex.bits.f3 = 1; break; } } } return 0;}static int LineMonitor(int board){ IXJ *j = &ixj[board]; if (j->dtmf_proc) { return -1; } j->dtmf_proc = 1; if (ixj_WriteDSPCommand(0x7000, board)) // Line Monitor return -1; j->dtmf.bytes.high = j->ssr.high; j->dtmf.bytes.low = j->ssr.low; if (!j->dtmf_state && j->dtmf.bits.dtmf_valid) { j->dtmf_state = 1; j->dtmf_current = j->dtmf.bits.digit; } if (j->dtmf_state && !j->dtmf.bits.dtmf_valid) // && j->dtmf_wp != j->dtmf_rp) { j->dtmfbuffer[j->dtmf_wp] = j->dtmf_current; j->dtmf_wp++; if (j->dtmf_wp == 79) j->dtmf_wp = 0; j->ex.bits.dtmf_ready = 1; j->dtmf_state = 0; } j->dtmf_proc = 0; return 0;}ssize_t ixj_read(struct file * file_p, char *buf, size_t length, loff_t * ppos){ unsigned long i = *ppos; IXJ *j = &ixj[NUM(file_p->f_dentry->d_inode->i_rdev)]; struct wait_queue wait = {current, NULL}; add_wait_queue(&j->read_q, &wait); current->state = TASK_INTERRUPTIBLE; mb(); while (!j->read_buffer_ready || (j->dtmf_state && j->flags.dtmf_oob)) { ++j->read_wait; if (file_p->f_flags & O_NONBLOCK) { current->state = TASK_RUNNING; remove_wait_queue(&j->read_q, &wait); return -EAGAIN; } if (!ixj_hookstate(NUM(file_p->f_dentry->d_inode->i_rdev))) { current->state = TASK_RUNNING; remove_wait_queue(&j->read_q, &wait); return 0; } interruptible_sleep_on(&j->read_q); if (signal_pending(current)) { current->state = TASK_RUNNING; remove_wait_queue(&j->read_q, &wait); return -EINTR; } } remove_wait_queue(&j->read_q, &wait); current->state = TASK_RUNNING; /* Don't ever copy more than the user asks */ i = copy_to_user(buf, j->read_buffer, min(length, j->read_buffer_size)); j->read_buffer_ready = 0; if (i) return -EFAULT; else return min(length, j->read_buffer_size);}ssize_t ixj_enhanced_read(struct file * file_p, char *buf, size_t length, loff_t * ppos){ int pre_retval; ssize_t read_retval = 0; IXJ *j = &ixj[NUM(file_p->f_dentry->d_inode->i_rdev)]; pre_retval = ixj_PreRead(j, 0L); switch (pre_retval) { case NORMAL: read_retval = ixj_read(file_p, buf, length, ppos); ixj_PostRead(j, 0L); break; case NOPOST: read_retval = ixj_read(file_p, buf, length, ppos); break; case POSTONLY: ixj_PostRead(j, 0L); break; default: read_retval = pre_retval; } return read_retval;}ssize_t ixj_write(struct file * file_p, const char *buf, size_t count, loff_t * ppos){ unsigned long i = *ppos; int board = NUM(file_p->f_dentry->d_inode->i_rdev); IXJ *j = &ixj[board]; struct wait_queue wait = {current, NULL}; add_wait_queue(&j->read_q, &wait); current->state = TASK_INTERRUPTIBLE; mb(); while (!j->write_buffers_empty) { ++j->write_wait; if (file_p->f_flags & O_NONBLOCK) { current->state = TASK_RUNNING; remove_wait_queue(&j->read_q, &wait); return -EAGAIN; } if (!ixj_hookstate(NUM(file_p->f_dentry->d_inode->i_rdev))) { current->state = TASK_RUNNING; remove_wait_queue(&j->read_q, &wait); return 0; } interruptible_sleep_on(&j->write_q); if (signal_pending(current)) { current->state = TASK_RUNNING; remove_wait_queue(&j->read_q, &wait); return -EINTR; } } current->state = TASK_RUNNING; remove_wait_queue(&j->read_q, &wait); if (j->write_buffer_wp + count >= j->write_buffer_end) j->write_buffer_wp = j->write_buffer; i = copy_from_user(j->write_buffer_wp, buf, min(count, j->write_buffer_size)); if (i) return -EFAULT; return min(count, j->write_buffer_size);}ssize_t ixj_enhanced_write(struct file * file_p, const char *buf, size_t count, loff_t * ppos){ int pre_retval; ssize_t write_retval = 0; IXJ *j = &ixj[NUM(file_p->f_dentry->d_inode->i_rdev)]; pre_retval = ixj_PreWrite(j, 0L); switch (pre_retval) { case NORMAL: write_retval = ixj_write(file_p, buf, count, ppos); if (write_retval != -EFAULT) { ixj_PostWrite(j, 0L); j->write_buffer_wp += count; j->write_buffers_empty--; } break; case NOPOST: write_retval = ixj_write(file_p, buf, count, ppos); if (write_retval != -EFAULT) { j->write_buffer_wp += count; j->write_buffers_empty--; } break; case POSTONLY: ixj_PostWrite(j, 0L); break; default: write_retval = pre_retval; } return write_retval;}static void ixj_read_frame(int board){ int cnt, dly; IXJ *j = &ixj[board]; if (j->read_buffer) { for (cnt = 0; cnt < j->rec_frame_size * 2; cnt += 2) { if (!(cnt % 16) && !IsRxReady(board)) { dly = 0; while (!IsRxReady(board)) { if (dly++ > 5) { dly = 0; break; } udelay(10); } } // Throw away word 0 of the 8021 compressed format to get standard G.729. if (j->rec_codec == G729 && (cnt == 0 || cnt == 5 || cnt == 10)) { inb_p(j->DSPbase + 0x0E); inb_p(j->DSPbase + 0x0F); } *(j->read_buffer + cnt) = inb_p(j->DSPbase + 0x0E); *(j->read_buffer + cnt + 1) = inb_p(j->DSPbase + 0x0F); }#ifdef PERFMON_STATS ++j->framesread;#endif if (j->intercom != -1) { if (IsTxReady(j->intercom)) { for (cnt = 0; cnt < j->rec_frame_size * 2; cnt += 2) { if (!(cnt % 16) && !IsTxReady(board)) { dly = 0; while (!IsTxReady(board)) { if (dly++ > 5) { dly = 0; break; } udelay(10); } } outb_p(*(j->read_buffer + cnt), ixj[j->intercom].DSPbase + 0x0C); outb_p(*(j->read_buffer + cnt + 1), ixj[j->intercom].DSPbase + 0x0D); }#ifdef PERFMON_STATS ++ixj[j->intercom].frameswritten;#endif } } else { j->read_buffer_ready = 1; wake_up_interruptible(&j->read_q); // Wake any blocked readers wake_up_interruptible(&j->poll_q); // Wake any blocked selects if (j->async_queue) kill_fasync(j->async_queue, SIGIO); // Send apps notice of frame } }}static void ixj_write_frame(int board){ int cnt, frame_count, dly; BYTES blankword; IXJ *j = &ixj[board]; frame_count = 0; if (j->write_buffer && j->write_buffers_empty < 2) { if (j->write_buffer_wp > j->write_buffer_rp) { frame_count = (j->write_buffer_wp - j->write_buffer_rp) / (j->play_frame_size * 2); } if (j->write_buffer_rp > j->write_buffer_wp) { frame_count = (j->write_buffer_wp - j->write_buffer) / (j->play_frame_size * 2) + (j->write_buffer_end - j->write_buffer_rp) / (j->play_frame_size * 2); } if (frame_count >= 1) { if (j->ver.low == 0x12 && j->play_mode && j->flags.play_first_frame) { switch (j->play_mode) { case PLAYBACK_MODE_ULAW: case PLAYBACK_MODE_ALAW: blankword.low = blankword.high = 0xFF; break; case PLAYBACK_MODE_8LINEAR: case PLAYBACK_MODE_16LINEAR: blankword.low = blankword.high = 0x00; break; case PLAYBACK_MODE_8LINEAR_WSS: blankword.low = blankword.high = 0x80; break; } for (cnt = 0; cnt < 16; cnt++) { if (!(cnt % 16) && !IsTxReady(board)) { dly = 0; while (!IsTxReady(board)) { if (dly++ > 5) { dly = 0; break; } udelay(10); } } outb_p((blankword.low), j->DSPbase + 0x0C); outb_p((blankword.high), j->DSPbase + 0x0D); } j->flags.play_first_frame = 0; } for (cnt = 0; cnt < j->play_frame_size * 2; cnt += 2) { if (!(cnt % 16) && !IsTxReady(board)) { dly = 0; while (!IsTxReady(board)) { if (dly++ > 5) { dly = 0; break; } udelay(10); } }// Add word 0 to G.729 frames for the 8021. Right now we don't do VAD/CNG // so all frames are type 1. if (j->play_codec == G729 && (cnt == 0 || cnt == 5 || cnt == 10)) { outb_p(0x01, j->DSPbase + 0x0C); outb_p(0x00, j->DSPbase + 0x0D); } outb_p(*(j->write_buffer_rp + cnt), j->DSPbase + 0x0C); outb_p(*(j->write_buffer_rp + cnt + 1), j->DSPbase + 0x0D); *(j->write_buffer_rp + cnt) = 0; *(j->write_buffer_rp + cnt + 1) = 0; } j->write_buffer_rp += j->play_frame_size * 2; if (j->write_buffer_rp >= j->write_buffer_end) { j->write_buffer_rp = j->write_buffer; } j->write_buffers_empty++; wake_up_interruptible(&(j->write_q)); // Wake any blocked writers wake_up_interruptible(&j->poll_q); // Wake any blocked selects if (j->async_queue) kill_fasync(j->async_queue, SIGIO); // Send apps notice of empty buffer#ifdef PERFMON_STATS ++j->frameswritten;#endif } } else { j->drybuffer++; }}static int idle(int board){ IXJ *j = &ixj[board]; if (ixj_WriteDSPCommand(0x0000, board)) // DSP Idle return 0; if (j->ssr.high || j->ssr.low) return 0; else return 1;}static int set_base_frame(int board, int size){ unsigned short cmd; int cnt; IXJ *j = &ixj[board]; aec_stop(board); for (cnt = 0; cnt < 10; cnt++) { if (idle(board)) break; } if (j->ssr.high || j->ssr.low) return -1; if (j->dsp.low != 0x20) { switch (size) { case 30: cmd = 0x07F0; /* Set Base Frame Size to 240 pg9-10 8021 */ break; case 20: cmd = 0x07A0; /* Set Base Frame Size to 160 pg9-10 8021 */ break; case 10: cmd = 0x0750; /* Set Base Frame Size to 80 pg9-10 8021 */ break; default: return -1; } } else { if (size == 30) return size; else return -1; } if (ixj_WriteDSPCommand(cmd, board)) { j->baseframe.high = j->baseframe.low = 0xFF; return -1; } else { j->baseframe.high = j->ssr.high; j->baseframe.low = j->ssr.low; } return size;}static int set_rec_codec(int board, int rate){ int retval = 0; IXJ *j = &ixj[board]; j->rec_codec = rate; switch (rate) { case G723_63: if (j->ver.low != 0x12 || ixj_convert_loaded) { j->rec_frame_size = 12; j->rec_mode = 0; } else { retval = 1; } break; case G723_53: if (j->ver.low != 0x12 || ixj_convert_loaded) { j->rec_frame_size = 10; j->rec_mode = 0; } else { retval = 1; } break; case TS85: if (j->dsp.low == 0x20 || j->flags.ts85_loaded) { j->rec_frame_size = 16; j->rec_mode = 0; } else { retval = 1; } break; case TS48: if (j->ver.low != 0x12 || ixj_convert_loaded) { j->rec_frame_size = 9; j->rec_mode = 0; } else { retval = 1; } break; case TS41: if (j->ver.low != 0x12 || ixj_convert_loaded) { j->rec_frame_size = 8; j->rec_mode = 0; } else { retval = 1; } break; case G728: if (j->dsp.low != 0x20) { j->rec_frame_size = 48; j->rec_mode = 0; } else { retval = 1; } break; case G729: if (j->dsp.low != 0x20) { if (!j->flags.g729_loaded) { retval = 1; break; } switch (j->baseframe.low) { case 0xA0: j->rec_frame_size = 10; break; case 0x50: j->rec_frame_size = 5; break; default: j->rec_frame_size = 15; break; } j->rec_mode = 0; } else { retval = 1; } break; case ULAW: switch (j->baseframe.low) { case 0xA0: j->rec_frame_size = 80; break; case 0x50: j->rec_frame_size = 40; break; default: j->rec_frame_size = 120; break; } j->rec_mode = 4; break; case ALAW: switch (j->baseframe.low) { case 0xA0:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -