This commit is contained in:
JerryXiao 2022-11-13 00:05:27 +08:00
parent 902e7f8e30
commit 2441e32b79
Signed by: Jerry
GPG key ID: 22618F758B5BE2E5
2 changed files with 175 additions and 159 deletions

199
d-modem.c
View file

@ -37,9 +37,9 @@
pa_simple *pa_s1 = NULL; pa_simple *pa_s1 = NULL;
pa_simple *pa_s2 = NULL; pa_simple *pa_s2 = NULL;
const pa_sample_spec pa_ss = { const pa_sample_spec pa_ss = {
.format = PA_SAMPLE_S16LE, .format = PA_SAMPLE_S16LE,
.rate = 9600, .rate = 9600,
.channels = 1 .channels = 1
}; };
#endif #endif
#ifdef PCM_FILE #ifdef PCM_FILE
@ -54,6 +54,7 @@ int wave_transmit = -1;
uint8_t mode = DMODEM_DIAL_MODE; uint8_t mode = DMODEM_DIAL_MODE;
uint8_t ringing = 0; uint8_t ringing = 0;
uint8_t answered = 0; uint8_t answered = 0;
int ppid;
pjsua_call_id incoming; pjsua_call_id incoming;
struct dmodem { struct dmodem {
@ -72,65 +73,65 @@ static void error_exit(const char *title, pj_status_t status) {
if (!destroying) { if (!destroying) {
destroying = true; destroying = true;
pjsua_destroy(); pjsua_destroy();
stop_pa(); stop_pa();
if (answered) if (answered)
execl("/bin/sh", "/bin/sh", "-cx", "kill -INT $PPID", NULL); kill(ppid, SIGINT);
exit(1); exit(1);
} }
} }
void start_pa() { void start_pa() {
#ifdef PCM_FILE #ifdef PCM_FILE
char _wavbuf[50]; char _wavbuf[50];
sprintf(_wavbuf, PCM_FILE, "recv"); sprintf(_wavbuf, PCM_FILE, "recv");
wave_recv = open(_wavbuf, O_WRONLY | O_CREAT, 00644); wave_recv = open(_wavbuf, O_WRONLY | O_CREAT, 00644);
sprintf(_wavbuf, PCM_FILE, "transmit"); sprintf(_wavbuf, PCM_FILE, "transmit");
wave_recv = open(_wavbuf, O_WRONLY | O_CREAT, 00644); wave_recv = open(_wavbuf, O_WRONLY | O_CREAT, 00644);
if (wave_recv <= 0 || wave_transmit <= 0) if (wave_recv <= 0 || wave_transmit <= 0)
error_exit("open wave files", 1); error_exit("open wave files", 1);
#endif #endif
#ifdef HAS_PULSE #ifdef HAS_PULSE
pa_s1 = pa_simple_new(NULL, // Use the default server. pa_s1 = pa_simple_new(NULL, // Use the default server.
"dmodem", // Our application's name. "dmodem", // Our application's name.
PA_STREAM_PLAYBACK, PA_STREAM_PLAYBACK,
NULL, // Use the default device. NULL, // Use the default device.
"recv", // Description of our stream. "recv", // Description of our stream.
&pa_ss, // Our sample format. &pa_ss, // Our sample format.
NULL, // Use default channel map NULL, // Use default channel map
NULL, // Use default buffering attributes. NULL, // Use default buffering attributes.
NULL // Ignore error code. NULL // Ignore error code.
); );
pa_s2 = pa_simple_new(NULL, // Use the default server. pa_s2 = pa_simple_new(NULL, // Use the default server.
"dmodem", // Our application's name. "dmodem", // Our application's name.
PA_STREAM_PLAYBACK, PA_STREAM_PLAYBACK,
NULL, // Use the default device. NULL, // Use the default device.
"transmit", // Description of our stream. "transmit", // Description of our stream.
&pa_ss, // Our sample format. &pa_ss, // Our sample format.
NULL, // Use default channel map NULL, // Use default channel map
NULL, // Use default buffering attributes. NULL, // Use default buffering attributes.
NULL // Ignore error code. NULL // Ignore error code.
); );
if (!pa_s1 || !pa_s2) if (!pa_s1 || !pa_s2)
error_exit("pulseaudio", 1); error_exit("pulseaudio", 1);
#endif #endif
} }
void stop_pa() { void stop_pa() {
#ifdef HAS_PULSE #ifdef HAS_PULSE
if(pa_s1) if(pa_s1)
pa_simple_free(pa_s1); pa_simple_free(pa_s1);
if(pa_s2) if(pa_s2)
pa_simple_free(pa_s2); pa_simple_free(pa_s2);
pa_s1 = 0; pa_s1 = 0;
pa_s1 = 0; pa_s1 = 0;
#endif #endif
#ifdef PCM_FILE #ifdef PCM_FILE
if (wave_recv >= 0) if (wave_recv >= 0)
close(wave_recv); close(wave_recv);
if (wave_transmit >= 0) if (wave_transmit >= 0)
close(wave_transmit); close(wave_transmit);
wave_recv = -1; wave_recv = -1;
wave_transmit = -1; wave_transmit = -1;
#endif #endif
} }
@ -140,10 +141,10 @@ static pj_status_t dmodem_put_frame(pjmedia_port *this_port, pjmedia_frame *fram
if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO) { if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO) {
#ifdef HAS_PULSE #ifdef HAS_PULSE
pa_simple_write(pa_s1, frame->buf, frame->size, NULL); pa_simple_write(pa_s1, frame->buf, frame->size, NULL);
#endif #endif
#ifdef PCM_FILE #ifdef PCM_FILE
write(wave_recv, frame->buf, frame->size); write(wave_recv, frame->buf, frame->size);
#endif #endif
if ((len=write(sm->sock, frame->buf, frame->size)) != frame->size) { if ((len=write(sm->sock, frame->buf, frame->size)) != frame->size) {
error_exit("error writing frame",0); error_exit("error writing frame",0);
@ -166,10 +167,10 @@ static pj_status_t dmodem_get_frame(pjmedia_port *this_port, pjmedia_frame *fram
frame->type = PJMEDIA_FRAME_TYPE_AUDIO; frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
sm->timestamp.u64 += PJMEDIA_PIA_SPF(&this_port->info); sm->timestamp.u64 += PJMEDIA_PIA_SPF(&this_port->info);
#ifdef HAS_PULSE #ifdef HAS_PULSE
pa_simple_write(pa_s2, frame->buf, frame->size, NULL); pa_simple_write(pa_s2, frame->buf, frame->size, NULL);
#endif #endif
#ifdef PCM_FILE #ifdef PCM_FILE
write(wave_transmit, frame->buf, frame->size); write(wave_transmit, frame->buf, frame->size);
#endif #endif
return PJ_SUCCESS; return PJ_SUCCESS;
@ -177,8 +178,8 @@ static pj_status_t dmodem_get_frame(pjmedia_port *this_port, pjmedia_frame *fram
static pj_status_t dmodem_on_destroy(pjmedia_port *this_port) { static pj_status_t dmodem_on_destroy(pjmedia_port *this_port) {
printf("destroy\n"); printf("destroy\n");
if (answered) if (answered)
execl("/bin/sh", "/bin/sh", "-cx", "kill -INT $PPID", NULL); kill(ppid, SIGINT);
exit(-1); exit(-1);
} }
@ -199,8 +200,8 @@ static void on_call_state(pjsua_call_id call_id, pjsip_event *e) {
destroying = true; destroying = true;
pjsua_destroy(); pjsua_destroy();
stop_pa(); stop_pa();
if (answered) if (answered)
execl("/bin/sh", "/bin/sh", "-cx", "kill -INT $PPID", NULL); kill(ppid, SIGINT);
exit(0); exit(0);
} }
} }
@ -212,12 +213,12 @@ static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_r
char* tmp = malloc(pj_strlen(&ci.remote_contact)+1); char* tmp = malloc(pj_strlen(&ci.remote_contact)+1);
strcpy(tmp, ci.remote_contact.ptr); strcpy(tmp, ci.remote_contact.ptr);
tmp[pj_strlen(&ci.remote_contact)] = '\0'; tmp[pj_strlen(&ci.remote_contact)] = '\0';
if (answered) { if (answered) {
printf("Incoming call rejected from: %s\n", tmp); PJ_LOG(2,(__FILE__, "Incoming call rejected from: %s", tmp));
pjsua_call_hangup(call_id, 0u, NULL, NULL); pjsua_call_hangup(call_id, 0u, NULL, NULL);
return; return;
} }
printf("Incoming call from: %s\n", tmp); PJ_LOG(2,(__FILE__, "Incoming call from: %s", tmp));
free(tmp); free(tmp);
incoming = call_id; incoming = call_id;
ringing = 1; ringing = 1;
@ -247,23 +248,35 @@ static void on_call_media_state(pjsua_call_id call_id) {
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
pjsua_acc_id acc_id; pjsua_acc_id acc_id;
pj_status_t status; pj_status_t status;
if (argc != 3) { if (argc != 5) {
return -1; return -1;
} }
ppid = atoi(argv[3]);
char* _modemid_tmp = argv[4];
for (size_t i = strlen(_modemid_tmp) - 1 ; ; i--) {
if (i < 0 || _modemid_tmp[i] < '0' || _modemid_tmp[i] > '9') {
_modemid_tmp += i+1;
break;
}
}
int sip_port = atoi(_modemid_tmp);
sip_port = sip_port >= 0 ? sip_port : 0;
sip_port += 5060;
sip_port = sip_port <= 65535 ? sip_port : 65535;
if(!strncmp(argv[1], "rr", 2)) { if(!strncmp(argv[1], "rr", 2)) {
mode = DMODEM_ANSWER_MODE; mode = DMODEM_ANSWER_MODE;
} }
signal(SIGPIPE,SIG_IGN); signal(SIGPIPE,SIG_IGN);
char *dialstr = argv[1]; char *dialstr = argv[1];
int has_sip_user = 1; int has_sip_user = 1;
char *sip_user = getenv("SIP_LOGIN"); char *sip_user = getenv("SIP_LOGIN");
if (!sip_user) { if (!sip_user) {
has_sip_user = 0; has_sip_user = 0;
printf("[!] SIP_LOGIN is empty, no registration will be attempted\n"); printf("[!] SIP_LOGIN is empty, no registration will be attempted\n");
char sip_user_buf[40]; char sip_user_buf[40];
strcpy(sip_user_buf, "placeholder:placeholder@placeholder"); strcpy(sip_user_buf, "placeholder:placeholder@placeholder");
sip_user = sip_user_buf; sip_user = sip_user_buf;
} }
if (!sip_user) { if (!sip_user) {
return -1; return -1;
@ -297,17 +310,16 @@ int main(int argc, char *argv[]) {
} }
pjsua_logging_config_default(&log_cfg); pjsua_logging_config_default(&log_cfg);
log_cfg.console_level = 4; // log_cfg.console_level = 4;
log_cfg.console_level = 2;
pjsua_media_config_default(&med_cfg); pjsua_media_config_default(&med_cfg);
med_cfg.no_vad = true; med_cfg.no_vad = true;
med_cfg.ec_tail_len = 0; med_cfg.ec_tail_len = 0;
med_cfg.jb_max = 2000; med_cfg.jb_max = -1;
// med_cfg.jb_init = 200; med_cfg.jb_init = -1;
/* // med_cfg.jb_init = 200 */
// med_cfg.jb_init = 0;
/* med_cfg.audio_frame_ptime = 5; */
med_cfg.audio_frame_ptime = 10; med_cfg.audio_frame_ptime = 10;
med_cfg.quality = 10;
status = pjsua_init(&cfg, &log_cfg, &med_cfg); status = pjsua_init(&cfg, &log_cfg, &med_cfg);
if (status != PJ_SUCCESS) error_exit("Error in pjsua_init()", status); if (status != PJ_SUCCESS) error_exit("Error in pjsua_init()", status);
@ -331,22 +343,22 @@ int main(int argc, char *argv[]) {
// printf("codec: %s %d\n",pj_strbuf(&codecs[i].codec_id),pri); // printf("codec: %s %d\n",pj_strbuf(&codecs[i].codec_id),pri);
} }
pjsua_transport_id transport_id; pjsua_transport_id transport_id;
/* Add UDP transport. */ /* Add UDP transport. */
{ {
pjsua_transport_config cfg; pjsua_transport_config cfg;
pjsua_transport_config_default(&cfg); pjsua_transport_config_default(&cfg);
if (mode) if (mode)
cfg.port = 5160; cfg.port = sip_port;
if (getenv("PJSIP_IPV6")) if (getenv("PJSIP_IPV6"))
status = pjsua_transport_create(PJSIP_TRANSPORT_UDP6, &cfg, &transport_id); status = pjsua_transport_create(PJSIP_TRANSPORT_UDP6, &cfg, &transport_id);
else else
status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &cfg, &transport_id); status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &cfg, &transport_id);
if (status != PJ_SUCCESS) error_exit("Error creating transport", status); if (status != PJ_SUCCESS) error_exit("Error creating transport", status);
} }
char buf[384]; char buf[384];
printf("Initializing pool\n"); //printf("Initializing pool\n");
pj_caching_pool cp; pj_caching_pool cp;
pj_caching_pool_init(&cp, NULL, 1024*1024); pj_caching_pool_init(&cp, NULL, 1024*1024);
pool = pj_pool_create(&cp.factory, "pool1", 4000, 4000, NULL); pool = pj_pool_create(&cp.factory, "pool1", 4000, 4000, NULL);
@ -366,7 +378,7 @@ int main(int argc, char *argv[]) {
status = pjsua_start(); status = pjsua_start();
if (status != PJ_SUCCESS) error_exit("Error starting pjsua", status); if (status != PJ_SUCCESS) error_exit("Error starting pjsua", status);
if (has_sip_user) if (has_sip_user)
{ {
pjsua_acc_config cfg; pjsua_acc_config cfg;
pjsua_acc_config_default(&cfg); pjsua_acc_config_default(&cfg);
@ -387,21 +399,20 @@ int main(int argc, char *argv[]) {
} }
else else
{ {
printf("acc add local\n"); status == pjsua_acc_add_local(transport_id, 1, &acc_id);
status == pjsua_acc_add_local(transport_id, 1, &acc_id);
if (status != PJ_SUCCESS) error_exit("Error adding local account", status); if (status != PJ_SUCCESS) error_exit("Error adding local account", status);
} }
pjsua_get_var()->tpdata[transport_id].has_bound_addr = PJ_TRUE; pjsua_get_var()->tpdata[transport_id].has_bound_addr = PJ_TRUE;
if (getenv("PJSIP_IPV6")) if (getenv("PJSIP_IPV6"))
pjsua_get_var()->acc[acc_id].cfg.ipv6_media_use = PJSUA_IPV6_ENABLED; pjsua_get_var()->acc[acc_id].cfg.ipv6_media_use = PJSUA_IPV6_ENABLED;
start_pa(); start_pa();
if(mode == DMODEM_DIAL_MODE) { if(mode == DMODEM_DIAL_MODE) {
if (has_sip_user) if (has_sip_user)
snprintf(buf,sizeof(buf),"sip:%s@%s",dialstr,sip_domain); snprintf(buf,sizeof(buf),"sip:%s@%s",dialstr,sip_domain);
else else
snprintf(buf,sizeof(buf),"sip:%s",dialstr); snprintf(buf,sizeof(buf),"sip:%s",dialstr);
printf("calling %s\n",buf); PJ_LOG(2,(__FILE__, "calling %s\n",buf));
pj_str_t uri = pj_str(buf); pj_str_t uri = pj_str(buf);
pjsua_call_id callid; pjsua_call_id callid;
status = pjsua_call_make_call(acc_id, &uri, 0, NULL, NULL, &callid); status = pjsua_call_make_call(acc_id, &uri, 0, NULL, NULL, &callid);
@ -412,10 +423,10 @@ int main(int argc, char *argv[]) {
while(1) { while(1) {
if(mode == DMODEM_ANSWER_MODE) { if(mode == DMODEM_ANSWER_MODE) {
if(ringing) { if(ringing) {
status = pjsua_call_answer(incoming, 200, NULL, NULL); status = pjsua_call_answer(incoming, 200, NULL, NULL);
if (status != PJ_SUCCESS) error_exit("Error answering call", status); if (status != PJ_SUCCESS) error_exit("Error answering call", status);
ringing = 0; ringing = 0;
answered = 1; answered = 1;
} }
} }
nanosleep(&ts,NULL); nanosleep(&ts,NULL);

View file

@ -217,19 +217,19 @@ static int alsa_device_setup(struct device_struct *dev, const char *dev_name)
ret = snd_pcm_open(&dev->phandle, dev_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); ret = snd_pcm_open(&dev->phandle, dev_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
if(ret < 0) { if(ret < 0) {
ERR("alsa setup: cannot open playback device '%s': %s\n", ERR("alsa setup: cannot open playback device '%s': %s\n",
dev_name, snd_strerror(ret)); dev_name, snd_strerror(ret));
return -1; return -1;
} }
ret = snd_pcm_open(&dev->chandle, dev_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK); ret = snd_pcm_open(&dev->chandle, dev_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
if(ret < 0) { if(ret < 0) {
ERR("alsa setup: cannot open playback device '%s': %s\n", ERR("alsa setup: cannot open playback device '%s': %s\n",
dev_name, snd_strerror(ret)); dev_name, snd_strerror(ret));
return -1; return -1;
} }
ret = snd_pcm_poll_descriptors(dev->chandle, &pfd, 1); ret = snd_pcm_poll_descriptors(dev->chandle, &pfd, 1);
if(ret <= 0) { if(ret <= 0) {
ERR("alsa setup: cannot get poll descriptors of '%s': %s\n", ERR("alsa setup: cannot get poll descriptors of '%s': %s\n",
dev_name, snd_strerror(ret)); dev_name, snd_strerror(ret));
return -1; return -1;
} }
dev->fd = pfd.fd; dev->fd = pfd.fd;
@ -313,7 +313,7 @@ static int alsa_device_write(struct device_struct *dev, const char *buf, int cou
if (ret == -EAGAIN) if (ret == -EAGAIN)
continue; continue;
if (ret == -EPIPE) { if (ret == -EPIPE) {
ret = alsa_xrun_recovery(dev); ret = alsa_xrun_recovery(dev);
} }
written = ret; written = ret;
break; break;
@ -373,7 +373,7 @@ static int setup_stream(snd_pcm_t *handle, struct modem *m, const char *stream_n
ERR("cannot set format for %s: %s\n", stream_name, snd_strerror(err)); ERR("cannot set format for %s: %s\n", stream_name, snd_strerror(err));
return err; return err;
} }
err = snd_pcm_hw_params_set_channels(handle, hw_params, 1); err = snd_pcm_hw_params_set_channels(handle, hw_params, 1);
if (err < 0) { if (err < 0) {
ERR("cannot set channels for %s: %s\n", stream_name, snd_strerror(err)); ERR("cannot set channels for %s: %s\n", stream_name, snd_strerror(err));
return err; return err;
@ -386,7 +386,7 @@ static int setup_stream(snd_pcm_t *handle, struct modem *m, const char *stream_n
} }
if ( rrate != rate ) { if ( rrate != rate ) {
ERR("rate %d is not supported by %s (%d).\n", ERR("rate %d is not supported by %s (%d).\n",
rate, stream_name, rrate); rate, stream_name, rrate);
return -1; return -1;
} }
rsize = size = dev->period ; rsize = size = dev->period ;
@ -397,7 +397,7 @@ static int setup_stream(snd_pcm_t *handle, struct modem *m, const char *stream_n
} }
if ( rsize < size ) { if ( rsize < size ) {
ERR("period size %ld is not supported by %s (%ld).\n", ERR("period size %ld is not supported by %s (%ld).\n",
size, stream_name, rsize); size, stream_name, rsize);
return -1; return -1;
} }
rsize = size = use_short_buffer ? rsize * dev->buf_periods : rsize * 32; rsize = size = use_short_buffer ? rsize * dev->buf_periods : rsize * 32;
@ -408,7 +408,7 @@ static int setup_stream(snd_pcm_t *handle, struct modem *m, const char *stream_n
} }
if ( rsize != size ) { if ( rsize != size ) {
DBG("buffer size for %s is changed %ld -> %ld\n", DBG("buffer size for %s is changed %ld -> %ld\n",
stream_name, size, rsize); stream_name, size, rsize);
} }
err = snd_pcm_hw_params(handle, hw_params); err = snd_pcm_hw_params(handle, hw_params);
if (err < 0) { if (err < 0) {
@ -523,9 +523,9 @@ static int alsa_ioctl(struct modem *m, unsigned int cmd, unsigned long arg)
struct device_struct *dev = m->dev_data; struct device_struct *dev = m->dev_data;
DBG("alsa_ioctl: cmd %x, arg %lx...\n",cmd,arg); DBG("alsa_ioctl: cmd %x, arg %lx...\n",cmd,arg);
switch(cmd) { switch(cmd) {
case MDMCTL_CAPABILITIES: case MDMCTL_CAPABILITIES:
return -EINVAL; return -EINVAL;
case MDMCTL_HOOKSTATE: case MDMCTL_HOOKSTATE:
return (dev->hook_off_elem) ? return (dev->hook_off_elem) ?
snd_mixer_selem_set_playback_switch_all( snd_mixer_selem_set_playback_switch_all(
dev->hook_off_elem, dev->hook_off_elem,
@ -534,9 +534,9 @@ static int alsa_ioctl(struct modem *m, unsigned int cmd, unsigned long arg)
return (dev->speaker_elem) ? return (dev->speaker_elem) ?
snd_mixer_selem_set_playback_volume_all( snd_mixer_selem_set_playback_volume_all(
dev->speaker_elem, arg) : 0 ; dev->speaker_elem, arg) : 0 ;
case MDMCTL_CODECTYPE: case MDMCTL_CODECTYPE:
return CODEC_SILABS; return CODEC_SILABS;
case MDMCTL_IODELAY: case MDMCTL_IODELAY:
DBG("delay = %d\n", dev->delay); DBG("delay = %d\n", dev->delay);
return dev->delay; return dev->delay;
default: default:
@ -547,10 +547,10 @@ static int alsa_ioctl(struct modem *m, unsigned int cmd, unsigned long arg)
struct modem_driver alsa_modem_driver = { struct modem_driver alsa_modem_driver = {
.name = "alsa modem driver", .name = "alsa modem driver",
.start = alsa_start, .start = alsa_start,
.stop = alsa_stop, .stop = alsa_stop,
.ioctl = alsa_ioctl, .ioctl = alsa_ioctl,
}; };
@ -568,7 +568,7 @@ static int modemap_start (struct modem *m)
int ret; int ret;
DBG("modemap_start...\n"); DBG("modemap_start...\n");
dev->delay = 0; dev->delay = 0;
ret = ioctl(dev->fd,100000+MDMCTL_START,0); ret = ioctl(dev->fd,100000+MDMCTL_START,0);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = 192*2; ret = 192*2;
@ -586,7 +586,7 @@ static int modemap_stop (struct modem *m)
{ {
struct device_struct *dev = m->dev_data; struct device_struct *dev = m->dev_data;
DBG("modemap_stop...\n"); DBG("modemap_stop...\n");
return ioctl(dev->fd,100000+MDMCTL_STOP,0); return ioctl(dev->fd,100000+MDMCTL_STOP,0);
} }
static int modemap_ioctl(struct modem *m, unsigned int cmd, unsigned long arg) static int modemap_ioctl(struct modem *m, unsigned int cmd, unsigned long arg)
@ -607,10 +607,10 @@ static int modemap_ioctl(struct modem *m, unsigned int cmd, unsigned long arg)
struct modem_driver mdm_modem_driver = { struct modem_driver mdm_modem_driver = {
.name = "modemap driver", .name = "modemap driver",
.start = modemap_start, .start = modemap_start,
.stop = modemap_stop, .stop = modemap_stop,
.ioctl = modemap_ioctl, .ioctl = modemap_ioctl,
}; };
static int socket_start (struct modem *m) static int socket_start (struct modem *m)
@ -626,22 +626,27 @@ static int socket_start (struct modem *m)
exit(-1); exit(-1);
} }
pid_t ppid = getpid();
pid_t pid = fork(); pid_t pid = fork();
if (pid == -1) { if (pid == -1) {
perror("fork"); perror("fork");
exit(-1); exit(-1);
} }
if (pid == 0) { // child if (pid == 0) { // child
char str[16]; char _str[12];
snprintf(str,sizeof(str),"%d",sockets[0]); char _parent[12];
snprintf(_str,sizeof(_str),"%d",sockets[0]);
snprintf(_parent,sizeof(_parent),"%d",ppid);
char *_modem_path = strrchr(modem_dev_name, '/');
_modem_path = _modem_path == NULL ? modem_dev_name : _modem_path + 1;
close(sockets[1]); close(sockets[1]);
if(_MODEM_DO_ANSWER) { if(_MODEM_DO_ANSWER) {
DBG("MODEM_ANSW execl arg: %s, %s, %s\n",modem_exec,"rr",str); DBG("MODEM_ANSW execl arg: %s, %s, %s, %s, %s\n",modem_exec,"rr",_str,_parent,_modem_path);
ret = execl(modem_exec,modem_exec,"rr",str,NULL); ret = execl(modem_exec,modem_exec,"rr",_str,_parent,_modem_path,NULL);
} }
else { else {
DBG("MODEM_DIAL execl arg: %s, %s, %s\n",modem_exec,m->dial_string,str); DBG("MODEM_DIAL execl arg: %s, %s, %s, %s, %s\n",modem_exec,"rr",_str,_parent,_modem_path);
ret = execl(modem_exec,modem_exec,m->dial_string,str,NULL); ret = execl(modem_exec,modem_exec,m->dial_string,_str,_parent,_modem_path,NULL);
} }
if (ret == -1) { if (ret == -1) {
ERR("prog: %s\n", modem_exec); ERR("prog: %s\n", modem_exec);
@ -715,10 +720,10 @@ static int socket_ioctl(struct modem *m, unsigned int cmd, unsigned long arg)
} }
struct modem_driver socket_modem_driver = { struct modem_driver socket_modem_driver = {
.name = "socket driver", .name = "socket driver",
.start = socket_start, .start = socket_start,
.stop = socket_stop, .stop = socket_stop,
.ioctl = socket_ioctl, .ioctl = socket_ioctl,
}; };
static int mdm_device_read(struct device_struct *dev, char *buf, int size) static int mdm_device_read(struct device_struct *dev, char *buf, int size)
@ -790,11 +795,11 @@ int create_pty(struct modem *m)
if(m->pty) if(m->pty)
close(m->pty); close(m->pty);
pty = getpt(); pty = getpt();
if (pty < 0 || grantpt(pty) < 0 || unlockpt(pty) < 0) { if (pty < 0 || grantpt(pty) < 0 || unlockpt(pty) < 0) {
ERR("getpt: %s\n", strerror(errno)); ERR("getpt: %s\n", strerror(errno));
return -1; return -1;
} }
if(m->pty) { if(m->pty) {
termios = m->termios; termios = m->termios;
@ -807,11 +812,11 @@ int create_pty(struct modem *m)
cfsetospeed(&termios, B115200); cfsetospeed(&termios, B115200);
} }
ret = tcsetattr(pty, TCSANOW, &termios); ret = tcsetattr(pty, TCSANOW, &termios);
if (ret) { if (ret) {
ERR("tcsetattr: %s\n",strerror(errno)); ERR("tcsetattr: %s\n",strerror(errno));
return -1; return -1;
} }
fcntl(pty,F_SETFL,O_NONBLOCK); fcntl(pty,F_SETFL,O_NONBLOCK);
@ -822,18 +827,18 @@ int create_pty(struct modem *m)
modem_update_termios(m,&termios); modem_update_termios(m,&termios);
modem_group = NULL; modem_group = NULL;
if(modem_group && *modem_group) { if(modem_group && *modem_group) {
struct group *grp = getgrnam(modem_group); struct group *grp = getgrnam(modem_group);
if(!grp) { if(!grp) {
ERR("cannot find group '%s': %s\n", modem_group, ERR("cannot find group '%s': %s\n", modem_group,
strerror(errno)); strerror(errno));
} }
else { else {
ret = chown(pty_name, -1, grp->gr_gid); ret = chown(pty_name, -1, grp->gr_gid);
if(ret < 0) { if(ret < 0) {
ERR("cannot chown '%s' to ':%s': %s\n", ERR("cannot chown '%s' to ':%s': %s\n",
pty_name, modem_group, strerror(errno)); pty_name, modem_group, strerror(errno));
} }
} }
} }
@ -841,19 +846,19 @@ int create_pty(struct modem *m)
ret = chmod(pty_name, modem_perm); ret = chmod(pty_name, modem_perm);
if (ret < 0) { if (ret < 0) {
ERR("cannot chmod '%s' to %o: %s\n", ERR("cannot chmod '%s' to %o: %s\n",
pty_name, modem_perm, strerror(errno)); pty_name, modem_perm, strerror(errno));
} }
if(*link_name) { if(*link_name) {
unlink(link_name); unlink(link_name);
if(symlink(pty_name,link_name)) { if(symlink(pty_name,link_name)) {
ERR("cannot create symbolink link `%s' -> `%s': %s\n", ERR("cannot create symbolink link `%s' -> `%s': %s\n",
link_name,pty_name,strerror(errno)); link_name,pty_name,strerror(errno));
*link_name = '\0'; *link_name = '\0';
} }
else { else {
INFO("symbolic link `%s' -> `%s' created.\n", INFO("symbolic link `%s' -> `%s' created.\n",
link_name, pty_name); link_name, pty_name);
} }
} }
@ -901,9 +906,9 @@ static int modem_run(struct modem *m, struct device_struct *dev)
modem_ring_detector_start(m); modem_ring_detector_start(m);
#endif #endif
tmo.tv_sec = 1; tmo.tv_sec = 1;
tmo.tv_usec= 0; tmo.tv_usec= 0;
FD_ZERO(&rset); FD_ZERO(&rset);
FD_ZERO(&eset); FD_ZERO(&eset);
if(m->started) if(m->started)
FD_SET(dev->fd,&rset); FD_SET(dev->fd,&rset);
@ -921,14 +926,14 @@ static int modem_run(struct modem *m, struct device_struct *dev)
if(m->pty > max_fd) max_fd = m->pty; if(m->pty > max_fd) max_fd = m->pty;
} }
ret = select(max_fd + 1,&rset,NULL,&eset,&tmo); ret = select(max_fd + 1,&rset,NULL,&eset,&tmo);
if (ret < 0) { if (ret < 0) {
if (errno == EINTR) if (errno == EINTR)
continue; continue;
ERR("select: %s\n",strerror(errno)); ERR("select: %s\n",strerror(errno));
return ret; return ret;
} }
if ( ret == 0 ) if ( ret == 0 )
continue; continue;
@ -1005,7 +1010,7 @@ static int modem_run(struct modem *m, struct device_struct *dev)
} }
if(count != m->update_delay) { if(count != m->update_delay) {
ERR("cannot update delay: %d instead of %d.\n", ERR("cannot update delay: %d instead of %d.\n",
count, m->update_delay); count, m->update_delay);
return -1; return -1;
} }
dev->delay += m->update_delay; dev->delay += m->update_delay;
@ -1106,7 +1111,7 @@ int modem_main(const char *dev_name)
} }
INFO("modem `%s' created. TTY is `%s'\n", INFO("modem `%s' created. TTY is `%s'\n",
m->name, m->pty_name); m->name, m->pty_name);
// sprintf(path_name,"/var/lib/slmodem/data.%s",basename(dev_name)); // sprintf(path_name,"/var/lib/slmodem/data.%s",basename(dev_name));
// datafile_load_info(path_name,&m->dsp_info); // datafile_load_info(path_name,&m->dsp_info);
@ -1150,11 +1155,11 @@ int modem_main(const char *dev_name)
} }
ret = (setgroups(1,&pwd->pw_gid) || ret = (setgroups(1,&pwd->pw_gid) ||
setgid(pwd->pw_gid) || setgid(pwd->pw_gid) ||
setuid(pwd->pw_uid)); setuid(pwd->pw_uid));
if (ret) { if (ret) {
ERR("setgroups or setgid %ld or setuid %ld failed: %s\n", ERR("setgroups or setgid %ld or setuid %ld failed: %s\n",
(long)pwd->pw_gid,(long)pwd->pw_uid,strerror(errno)); (long)pwd->pw_gid,(long)pwd->pw_uid,strerror(errno));
exit(-1); exit(-1);
} }
@ -1163,11 +1168,11 @@ int modem_main(const char *dev_name)
exit(-1); exit(-1);
} }
DBG("dropped privileges to %ld.%ld\n", DBG("dropped privileges to %ld.%ld\n",
(long)pwd->pw_gid,(long)pwd->pw_uid); (long)pwd->pw_gid,(long)pwd->pw_uid);
#endif #endif
INFO("Use `%s' as modem device, Ctrl+C for termination.\n", INFO("Use `%s' as modem device, Ctrl+C for termination.\n",
*link_name ? link_name : m->pty_name); *link_name ? link_name : m->pty_name);
/* main loop here */ /* main loop here */
ret = modem_run(m,&device); ret = modem_run(m,&device);