qserialiodevice.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. /****************************************************************************
  2. **
  3. ** This file is part of the Qt Extended Opensource Package.
  4. **
  5. ** Copyright (C) 2009 Trolltech ASA.
  6. **
  7. ** Contact: Qt Extended Information (info@qtextended.org)
  8. **
  9. ** This file may be used under the terms of the GNU General Public License
  10. ** version 2.0 as published by the Free Software Foundation and appearing
  11. ** in the file LICENSE.GPL included in the packaging of this file.
  12. **
  13. ** Please review the following information to ensure GNU General Public
  14. ** Licensing requirements will be met:
  15. ** http://www.fsf.org/licensing/licenses/info/GPLv2.html.
  16. **
  17. **
  18. ****************************************************************************/
  19. #include "qserialiodevice.h"
  20. #include "qserialiodevice_p.h"
  21. #include "qatchat.h"
  22. #include <QDebug>
  23. #include <qsocketnotifier.h>
  24. #include <qtimer.h>
  25. #include <termios.h>
  26. #include <stdio.h>
  27. #include <unistd.h>
  28. #include <errno.h>
  29. #include <sys/types.h>
  30. #include <sys/time.h>
  31. #include <sys/stat.h>
  32. #include <sys/socket.h>
  33. #include <sys/ioctl.h>
  34. #include <sys/select.h>
  35. #include <fcntl.h>
  36. #include <netdb.h>
  37. #include <netinet/in.h>
  38. #include <arpa/inet.h>
  39. #define USE_POSIX_SYSCALLS 1
  40. #define USE_TERMIOS 1
  41. /*!
  42. \class QSerialIODevice
  43. \inpublicgroup QtBaseModule
  44. \brief The QSerialIODevice class is the base for all serial devices.
  45. \ingroup io
  46. \ingroup telephony::serial
  47. The abstract QSerialIODevice class extends QIODevice with functionality
  48. that is specific to serial devices. Subclasses implement specific kinds
  49. of serial devices. In particular, QSerialPort implements a physical hardware
  50. serial port.
  51. \sa QIODevice, QSerialPort
  52. */
  53. /*!
  54. Construct a new QSerialIODevice object attached to \a parent.
  55. */
  56. QSerialIODevice::QSerialIODevice( QObject *parent )
  57. : QIODevice( parent )
  58. {
  59. process = 0;
  60. chat = 0;
  61. }
  62. /*!
  63. Destruct a QSerialIODevice object.
  64. */
  65. QSerialIODevice::~QSerialIODevice()
  66. {
  67. if ( process )
  68. process->clearDevice();
  69. }
  70. /*!
  71. Returns if this device is sequential in nature; false otherwise. Serial devices are
  72. always sequential.
  73. */
  74. bool QSerialIODevice::isSequential() const
  75. {
  76. return true;
  77. }
  78. /*!
  79. Returns the serial device's baud rate. The default implementation
  80. returns 9600. Subclasses are expected to override this value.
  81. */
  82. int QSerialIODevice::rate() const
  83. {
  84. return 9600;
  85. }
  86. /*!
  87. \fn bool QSerialIODevice::dtr() const
  88. Returns true if the current state of the DTR modem status line is active; otherwise returns false.
  89. \sa setDtr()
  90. */
  91. /*!
  92. \fn void QSerialIODevice::setDtr( bool value )
  93. Sets the state of the DTR modem status line to \a value.
  94. \sa dtr()
  95. */
  96. /*!
  97. \fn bool QSerialIODevice::dsr() const
  98. Returns true if the current state of the DSR modem status line is active; otherwise returns false.
  99. \sa dsrChanged()
  100. */
  101. /*!
  102. \fn bool QSerialIODevice::carrier() const
  103. Returns true if the current state of the DCD (carrier) modem status line is active; otherwise returns false.
  104. \sa setCarrier(), carrierChanged()
  105. */
  106. /*!
  107. Sets the DCD (carrier) modem status line to \a value. This is used by
  108. programs that accept incoming serial connections to indicate to the
  109. peer machine that the carrier has dropped.
  110. By default, this calls setDtr(), which supports the case where a
  111. null modem cable is connecting DTR to DSR and DCD on the peer machine.
  112. The caller should wait for a small delay and then setDtr(true)
  113. to restore DTR to the correct value.
  114. This function will return false if it uses setDtr() to transmit the
  115. carrier change, or true if it can use a real carrier signal
  116. (QGsm0710MultiplexerServer supports real carrier signals).
  117. \sa carrier()
  118. */
  119. bool QSerialIODevice::setCarrier( bool value )
  120. {
  121. setDtr( value );
  122. return false;
  123. }
  124. /*!
  125. \fn bool QSerialIODevice::rts() const
  126. Returns true if the current state of the RTS modem status line is active; otherwise returns false.
  127. \sa setRts()
  128. */
  129. /*!
  130. \fn void QSerialIODevice::setRts( bool value )
  131. Sets the state of the RTS modem status line to \a value.
  132. \sa rts()
  133. */
  134. /*!
  135. \fn bool QSerialIODevice::cts() const
  136. Returns true if current state of the CTS modem status line is active; otherwise returns false.
  137. \sa ctsChanged()
  138. */
  139. /*!
  140. \fn void QSerialIODevice::discard()
  141. Discard pending buffered data without transmitting it. This function
  142. will do nothing if the underlying serial device implementation cannot discard buffers.
  143. */
  144. /*!
  145. Returns true if the caller should wait for the ready() signal to
  146. be emitted before sending data on this device. Returns false if
  147. the caller can send data immediately after calling open().
  148. The default implementation returns false.
  149. \sa ready()
  150. */
  151. bool QSerialIODevice::waitForReady() const
  152. {
  153. return false;
  154. }
  155. /*!
  156. Returns true if this serial device can validly transfer data; false otherwise.
  157. If this function returns false, there is no point writing
  158. data to this device, or attempting to read data from it,
  159. because it will never give a useful result.
  160. The default implementation returns the same value as isOpen().
  161. The QNullSerialIODevice class overrides this to always return
  162. false, even if the device is technically open.
  163. */
  164. bool QSerialIODevice::isValid() const
  165. {
  166. return isOpen();
  167. }
  168. /*!
  169. \fn void QSerialIODevice::dsrChanged( bool value );
  170. Signal that is emitted when the state of the DSR modem
  171. status line changes to \a value.
  172. \sa dsr()
  173. */
  174. /*!
  175. \fn void QSerialIODevice::carrierChanged( bool value );
  176. Signal that is emitted when the state of the DCD (carrier) modem
  177. status line changes to \a value.
  178. \sa carrier()
  179. */
  180. /*!
  181. \fn void QSerialIODevice::ctsChanged( bool value );
  182. Signal that is emitted when the state of the CTS modem
  183. status line changes to \a value.
  184. \sa cts()
  185. */
  186. /*!
  187. \fn void QSerialIODevice::ready()
  188. Signal that is emitted when the device is ready to accept data
  189. after being opened. This signal will only be emitted if the
  190. waitForReady() function returns true.
  191. \sa waitForReady()
  192. */
  193. #ifdef USE_POSIX_SYSCALLS
  194. // We would like to use "openpty", but it isn't in libc on some systems.
  195. static bool createPseudoTty(int& masterFd, int& slaveFd, char *ttyname)
  196. {
  197. // try opening Unix98 pseudo tty
  198. if ((masterFd = ::open("/dev/ptmx", O_RDWR | O_NONBLOCK, 0)) >= 0) {
  199. if (grantpt(masterFd) == 0) {
  200. if (unlockpt(masterFd) == 0) {
  201. ptsname_r(masterFd, ttyname, BUFSIZ);
  202. if ((slaveFd = ::open(ttyname, O_RDWR | O_NOCTTY, 0)) >= 0)
  203. return true;
  204. }
  205. }
  206. ::close(masterFd);
  207. }
  208. // opening Unix98 pseudo tty failed, fall back to BSD style pseudo tty
  209. static char const firstChars[] = "pqrstuvwxyzabcde";
  210. static char const secondChars[] = "0123456789abcdef";
  211. const char *first;
  212. const char *second;
  213. char ptyname[16];
  214. for ( first = firstChars; *first != '\0'; ++first ) {
  215. for ( second = secondChars; *second != '\0'; ++second ) {
  216. sprintf( ptyname, "/dev/pty%c%c", *first, *second );
  217. sprintf( ttyname, "/dev/tty%c%c", *first, *second );
  218. if ( ( masterFd = ::open( ptyname, O_RDWR | O_NONBLOCK, 0 ) ) >= 0 ) {
  219. if ( ( slaveFd = ::open( ttyname, O_RDWR | O_NOCTTY, 0 ) )
  220. >= 0 ) {
  221. return true;
  222. }
  223. ::close( masterFd );
  224. }
  225. }
  226. }
  227. return false;
  228. }
  229. #endif // USE_POSIX_SYSCALLS
  230. /*!
  231. Run a program with the supplied \a arguments, redirecting the
  232. device's data to stdin and stdout on the new process via a
  233. pseudo-tty. Redirection will stop when the process exits.
  234. This function returns a QProcess object that can be used to control the
  235. new process. The caller is responsible for destroying this object when it
  236. is no longer required. Returns null if the process could not be started
  237. for some reason.
  238. If \a addPPPdOptions is true, then the caller is attempting to start
  239. pppd. The base class implementation will insert the pseudo-tty's device
  240. name at the beginning of the command arguments.
  241. Subclasses may override this method to run pppd directly on an
  242. underlying device.
  243. The readyRead() signal will be suppressed while the process is running.
  244. */
  245. QProcess *QSerialIODevice::run( const QStringList& arguments,
  246. bool addPPPdOptions )
  247. {
  248. #ifdef USE_POSIX_SYSCALLS
  249. // Bail out if we are already running a process on this device.
  250. if ( process )
  251. return 0;
  252. // Create a pseudo-tty to manage communication with the process.
  253. int masterFd = -1;
  254. int slaveFd = -1;
  255. char slaveName[BUFSIZ];
  256. if ( !createPseudoTty( masterFd, slaveFd, slaveName ) ) {
  257. qWarning( "QServiceDeviceBase::run: could not find a pseudo-tty" );
  258. return 0;
  259. }
  260. // Make sure that the device is open.
  261. if ( !isOpen() )
  262. open( QIODevice::ReadWrite );
  263. // Insert the name of the slave into the argument list if necessary.
  264. QStringList newargs;
  265. if ( addPPPdOptions ) {
  266. newargs << QString( slaveName );
  267. }
  268. for ( int index = 1; index < arguments.size(); ++index )
  269. newargs << arguments[index];
  270. // Construct a process object to manage the communication.
  271. process = new QPseudoTtyProcess( this, masterFd, slaveFd, addPPPdOptions );
  272. process->setReadChannelMode( QProcess::ForwardedChannels );
  273. process->start( arguments[0], newargs );
  274. // We don't need the slave in the parent process any more.
  275. ::close( slaveFd );
  276. // Return to the caller with the new process.
  277. return process;
  278. #else
  279. return 0;
  280. #endif
  281. }
  282. /*!
  283. Returns the modem AT command chat object for this serial device.
  284. This is an alternative to accessing the raw binary data via
  285. read() and write().
  286. \sa QAtChat
  287. */
  288. QAtChat *QSerialIODevice::atchat()
  289. {
  290. if ( !chat )
  291. chat = new QAtChat( this );
  292. return chat;
  293. }
  294. /*!
  295. Abort an \c{ATD} dial command. The default implementation transmits a
  296. single CR character.
  297. If a modem needs to change the way abortDial() works, a multiplexer plug-in
  298. should be written which overrides the abortDial() function on
  299. the channels that need different abort logic.
  300. \sa QSerialIODeviceMultiplexerPlugin
  301. */
  302. void QSerialIODevice::abortDial()
  303. {
  304. static char const abortString[] = "\r";
  305. write( abortString, 1 );
  306. }
  307. /*!
  308. Emit the readyRead() signal. If a process is currently running
  309. on this device, then the readyRead() signal will be suppressed.
  310. Subclasses should call this slot rather than emit readyRead()
  311. directly.
  312. */
  313. void QSerialIODevice::internalReadyRead()
  314. {
  315. if ( process )
  316. process->deviceReadyRead();
  317. else
  318. emit readyRead();
  319. }
  320. QPseudoTtyProcess::QPseudoTtyProcess
  321. ( QSerialIODevice *device, int masterFd, int slaveFd, bool isPPP )
  322. : QProcess()
  323. {
  324. this->device = device;
  325. this->masterFd = masterFd;
  326. this->slaveFd = slaveFd;
  327. this->isPPP = isPPP;
  328. this->readySeen = false;
  329. connect( this, SIGNAL(stateChanged(QProcess::ProcessState)),
  330. this, SLOT(childStateChanged(QProcess::ProcessState)) );
  331. if ( device->waitForReady() ) {
  332. // We cannot start writing data until the device indicates
  333. // that it is ready for us to do so.
  334. connect( device, SIGNAL(ready()), this, SLOT(deviceReady()) );
  335. } else {
  336. // We can start writing data immediately.
  337. deviceReady();
  338. }
  339. }
  340. QPseudoTtyProcess::~QPseudoTtyProcess()
  341. {
  342. if ( device )
  343. device->process = 0;
  344. #ifdef USE_POSIX_SYSCALLS
  345. if ( masterFd != -1 )
  346. ::close( masterFd );
  347. #endif
  348. }
  349. void QPseudoTtyProcess::deviceReadyRead()
  350. {
  351. if ( device ) {
  352. qint64 len = device->read( buffer, sizeof(buffer) );
  353. #ifdef USE_POSIX_SYSCALLS
  354. if ( len > 0 && masterFd != -1 ) {
  355. // Write the data into the master side of the pseudo-tty.
  356. int temp;
  357. const char *data = buffer;
  358. while ( len > 0 ) {
  359. temp = ::write( masterFd, data, (int)len );
  360. if ( temp >= 0 ) {
  361. len -= (qint64)temp;
  362. data += (uint)temp;
  363. } else if ( errno != EINTR && errno != EWOULDBLOCK ) {
  364. qDebug() << "write(" << masterFd << ") errno = "
  365. << errno;
  366. break;
  367. }
  368. }
  369. }
  370. #endif
  371. }
  372. }
  373. void QPseudoTtyProcess::setupChildProcess()
  374. {
  375. #ifdef USE_POSIX_SYSCALLS
  376. if ( isPPP ) {
  377. // Convert pppd's stdin into the slave, but leave stdout and stderr
  378. // as-is so that debug output goes to our parent's stdout/stderr.
  379. ::dup2( slaveFd, 0 );
  380. } else {
  381. // Convert stdin and stdout into the slave, but leave stderr alone.
  382. ::dup2( slaveFd, 0 );
  383. ::dup2( slaveFd, 1 );
  384. }
  385. // We don't need the master and slave fd's any more.
  386. ::close( masterFd );
  387. ::close( slaveFd );
  388. masterFd = -1;
  389. //we have to change pppd's process group because pppd terminates its process group
  390. //when receiving SIGTERM while it is running the chat script
  391. int ret = ::setpgrp();
  392. if ( ret < 0 )
  393. perror("change process grp");
  394. #endif
  395. }
  396. void QPseudoTtyProcess::masterReadyRead()
  397. {
  398. #ifdef USE_POSIX_SYSCALLS
  399. if ( masterFd == -1 )
  400. return;
  401. int len;
  402. for(;;) {
  403. len = ::read( masterFd, buffer, sizeof(buffer) );
  404. if ( !len ) {
  405. // Process has probably exited, so clean up the master device.
  406. ::close( masterFd );
  407. masterFd = -1;
  408. break;
  409. } else if ( len > 0 ) {
  410. // Write the data we got from the master to the raw device.
  411. if ( device )
  412. device->write( buffer, len );
  413. } else if ( errno == EWOULDBLOCK ) {
  414. break;
  415. } else if ( errno != EINTR ) {
  416. qDebug() << "read(" << masterFd << ") errno = " << errno;
  417. break;
  418. }
  419. }
  420. #endif
  421. }
  422. void QPseudoTtyProcess::childStateChanged( QProcess::ProcessState state )
  423. {
  424. if ( state == QProcess::NotRunning ) {
  425. // Detach ourselves from the QSerialIODevice instance.
  426. if ( device ) {
  427. device->process = 0;
  428. device = 0;
  429. }
  430. }
  431. }
  432. void QPseudoTtyProcess::deviceReady()
  433. {
  434. if ( !readySeen ) {
  435. // Now that the device is ready, we can start listening for
  436. // data on the master fd.
  437. QSocketNotifier *notifier = new QSocketNotifier
  438. ( masterFd, QSocketNotifier::Read, this );
  439. connect( notifier, SIGNAL(activated(int)),
  440. this, SLOT(masterReadyRead()) );
  441. readySeen = true;
  442. }
  443. }
  444. /*!
  445. \class QNullSerialIODevice
  446. \inpublicgroup QtBaseModule
  447. \brief The QNullSerialIODevice class provides a null implementation of serial device functionality
  448. \ingroup io
  449. All bytes written to a QNullSerialIODevice instance are quietly ignored,
  450. and no data will ever arrive on the device.
  451. This class can be used when a regular serial device could not
  452. be opened with QSerialPort::create(), but the application still
  453. needs a valid object.
  454. \sa QSerialIODevice, QSerialPort
  455. */
  456. /*!
  457. Create a null serial device and attach it to \a parent.
  458. */
  459. QNullSerialIODevice::QNullSerialIODevice( QObject *parent )
  460. : QSerialIODevice( parent )
  461. {
  462. // Nothing to do here.
  463. }
  464. /*!
  465. Destruct this null serial device.
  466. */
  467. QNullSerialIODevice::~QNullSerialIODevice()
  468. {
  469. // Nothing to do here.
  470. }
  471. /*!
  472. Opens this null serial device in \a mode. Returns true if the
  473. device can be opened; false otherwise.
  474. */
  475. bool QNullSerialIODevice::open( OpenMode mode )
  476. {
  477. setOpenMode( mode );
  478. return true;
  479. }
  480. /*!
  481. Closes this null serial device.
  482. */
  483. void QNullSerialIODevice::close()
  484. {
  485. setOpenMode( NotOpen );
  486. }
  487. /*!
  488. Returns the number of bytes that are available on this
  489. null serial device (always 0).
  490. */
  491. qint64 QNullSerialIODevice::bytesAvailable() const
  492. {
  493. return 0;
  494. }
  495. /*!
  496. \reimp
  497. */
  498. int QNullSerialIODevice::rate() const
  499. {
  500. return 9600;
  501. }
  502. /*!
  503. \reimp
  504. */
  505. bool QNullSerialIODevice::dtr() const
  506. {
  507. return true;
  508. }
  509. /*!
  510. \reimp
  511. */
  512. void QNullSerialIODevice::setDtr( bool )
  513. {
  514. // Nothing to do here.
  515. }
  516. /*!
  517. \reimp
  518. */
  519. bool QNullSerialIODevice::dsr() const
  520. {
  521. return true;
  522. }
  523. /*!
  524. \reimp
  525. */
  526. bool QNullSerialIODevice::carrier() const
  527. {
  528. return true;
  529. }
  530. /*!
  531. \reimp
  532. */
  533. bool QNullSerialIODevice::rts() const
  534. {
  535. return true;
  536. }
  537. /*!
  538. \reimp
  539. */
  540. void QNullSerialIODevice::setRts( bool )
  541. {
  542. // Nothing to do here.
  543. }
  544. /*!
  545. \reimp
  546. */
  547. bool QNullSerialIODevice::cts() const
  548. {
  549. return true;
  550. }
  551. /*!
  552. \reimp
  553. */
  554. void QNullSerialIODevice::discard()
  555. {
  556. // Nothing to do here.
  557. }
  558. /*!
  559. This override always returns false.
  560. */
  561. bool QNullSerialIODevice::isValid() const
  562. {
  563. return false;
  564. }
  565. /*!
  566. Read up to \a maxlen bytes of data from this serial device into \a data.
  567. */
  568. qint64 QNullSerialIODevice::readData( char *, qint64 )
  569. {
  570. return 0;
  571. }
  572. /*!
  573. Write \a len bytes from \a data.
  574. */
  575. qint64 QNullSerialIODevice::writeData( const char *, qint64 len )
  576. {
  577. return len;
  578. }