Hi all.

I'm working on an embedded device using Linux (Debian kernel 2.6.27-4) and a home made software using /dev/ppp driver to connect our modems to GPRS networks.

(sorry for my bad english)

When our device is connected to internet via GPRS, I would like to send AT commands to my modem at the same time (using escape sequence "+++", and after AT commands to send SMS). With the same serial port used by /dev/ppp driver, and get my connection back with the same IP address.

Quickly, how I manage /dev/ppp after having connected my modem to GPRS network (AT*99***1#) :
1. Create PPP unit :
Code:
int
ppp_create_unit(struct ppp_unit *unit)
{
  int fd;
  int ret;
  char errnobuf[ERRNO_BUFSIZE];

  if ((fd = open("/dev/ppp", O_RDWR | O_NONBLOCK | O_NOCTTY)) == -1) {
    Log(LEVEL_ERROR, CLASS_PPP, "Unable to open /dev/ppp.\n");
    return -1;
  }
  SetCloseOnExec(fd, TRUE);

  unit->unit = -1;
  if ((ret = ioctl(fd, PPPIOCNEWUNIT, &unit->unit)) < 0) {
    Log(LEVEL_ERROR, CLASS_PPP, "PPPIOCNEWUNIT failed with '%s' (%d).\n",
      strerror_r(errno, errnobuf, ERRNO_BUFSIZE), errno);
    close(fd);
    return -1;
  }

  unit->unit_fd = fd;
  return 0;
}
2. Connect tty to this unit
Code:
int
ppp_connect_tty(struct ppp_unit *unit, int tty_fd)
{
  int ldisc = N_PPP;
  int channel;
  int ppp_fd;
  int ret;
  char errnobuf[ERRNO_BUFSIZE];

  /* Turn exclusive mode on. */
  if ((ret = ioctl(tty_fd, TIOCEXCL, 0)) < 0) {
    Log(LEVEL_ERROR, CLASS_PPP, "Unable to turn TTY exclusive mode on: %s (%d).\n",
      strerror_r(errno, errnobuf, ERRNO_BUFSIZE), errno);
  }

  /* Set the PPP line discipline. */
  if ((ret = ioctl(tty_fd, TIOCSETD, &ldisc)) < 0) {
    Log(LEVEL_ERROR, CLASS_PPP, "Unable to set PPP line discipline: %s (%d).\n",
      strerror_r(errno, errnobuf, ERRNO_BUFSIZE), errno);
    return -1;
  }

  /* Retrieve the channel number. */
  if ((ret = ioctl(tty_fd, PPPIOCGCHAN, &channel)) < 0) {
    Log(LEVEL_ERROR, CLASS_PPP, "Unable to retrieve PPP channel number: %s (%d).\n",
      strerror_r(errno, errnobuf, ERRNO_BUFSIZE), errno);
    return -1;
  }

  /* Connect the channel to the unit. */
  if ((ppp_fd = open("/dev/ppp", O_RDWR | O_NONBLOCK | O_NOCTTY)) == -1) {
    Log(LEVEL_ERROR, CLASS_PPP, "Unable to open /dev/ppp.\n");
    return -1;
  }
  SetCloseOnExec(ppp_fd, TRUE);

  Log(LEVEL_VERBOSE, CLASS_PPP, "Connect channel %d to unit %d.\n", channel, unit->unit);
  if ((ret = ioctl(ppp_fd, PPPIOCATTCHAN, &channel)) < 0) {
    Log(LEVEL_ERROR, CLASS_PPP, "PPPIOCATTACH failed with '%s' (%d).\n",
      strerror_r(errno, errnobuf, ERRNO_BUFSIZE), errno);
    close(ppp_fd);
    return -1;
  }

  if ((ret = ioctl(ppp_fd, PPPIOCCONNECT, &unit->unit)) < 0) {
    Log(LEVEL_ERROR, CLASS_PPP, "PPPIOCCONNECT failed with '%s' (%d).\n",
      strerror_r(errno, errnobuf, ERRNO_BUFSIZE), errno);
    close(ppp_fd);
    return -1;
  }

  unit->channel_fd = ppp_fd;
  return 0;

}
3. Start PPP handshaking

Here is my disconnect function :
Code:
int
ppp_disconnect_tty(struct ppp_unit *unit, int tty_fd)
{
  int ldisc = N_TTY;
  int ret;
  int channel;
  char errnobuf[ERRNO_BUFSIZE];

  /* Detach the channel from the unit. */
  /* Retrieve the channel number. */
  if ((ret = ioctl(tty_fd, PPPIOCGCHAN, &channel)) < 0) {
    Log(LEVEL_ERROR, CLASS_PPP, "Unable to retrieve PPP channel number: %s (%d).\n",
      strerror_r(errno, errnobuf, ERRNO_BUFSIZE), errno);
    return -1;
  }
  Log(LEVEL_VERBOSE, CLASS_PPP, "Disconnecting channel %d from unit %d.\n",
      channel, unit->unit);

  if ((ret = ioctl(unit->channel_fd, PPPIOCDISCONN, &unit->unit)) < 0) {
    Log(LEVEL_ERROR, CLASS_PPP, "PPPIOCDISCONN failed with '%s' (%d).\n",
      strerror_r(errno, errnobuf, ERRNO_BUFSIZE), errno);
    close(unit->channel_fd);
    return -1;
  }

  close(unit->channel_fd);

  /* Set the PPP line discipline. */
  if ((ret = ioctl(tty_fd, TIOCSETD, &ldisc)) < 0) {
    Log(LEVEL_ERROR, CLASS_PPP, "Unable to set PPP line discipline: %s (%d).\n",
      strerror_r(errno, errnobuf, ERRNO_BUFSIZE), errno);
    return -1;
  }

  /* Turn exclusive mode off. */
  if ((ret = ioctl(tty_fd, TIOCNXCL, 0)) < 0) {
    Log(LEVEL_ERROR, CLASS_PPP, "Unable to turn TTY exclusive mode off: %s (%d).\n",
      strerror_r(errno, errnobuf, ERRNO_BUFSIZE), errno);
  }

  return 0;
}
I've tried to disconnect PPP unit from tty (ppp_disconnect_tty), and then reconnect (ppp_connect_tty): I can send AT commands. But reconnection is not complete : seems that /dev/ppp don't want to relay incoming data from GSM network to my software.

The only way to do, is to close /dev/ppp and free PPP unit, re-open /dev/ppp and create a new PPP unit (ppp_create_unit and ppp_connect_tty) and relaunch a full PPP handshake : but it doesn't work on every modems, I don't know why, but some of them loose network GSM connection.

So, my question : is it a way to use a serial port already used by /dev/ppp, without closing any driver ressources ?

Please help ! Thank you.