sdbcommandexecutor.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2013 Jarek Pelczar <jpelczar@gmail.com>
  4. **
  5. ** This file is part of Qt Creator.
  6. **
  7. ** Commercial License Usage
  8. ** Licensees holding valid commercial Qt licenses may use this file in
  9. ** accordance with the commercial license agreement provided with the
  10. ** Software or, alternatively, in accordance with the terms contained in
  11. ** a written agreement between you and Digia. For licensing terms and
  12. ** conditions see http://qt.digia.com/licensing. For further information
  13. ** use the contact form at http://qt.digia.com/contact-us.
  14. **
  15. ** GNU Lesser General Public License Usage
  16. ** Alternatively, this file may be used under the terms of the GNU Lesser
  17. ** General Public License version 2.1 as published by the Free Software
  18. ** Foundation and appearing in the file LICENSE.LGPL included in the
  19. ** packaging of this file. Please review the following information to
  20. ** ensure the GNU Lesser General Public License version 2.1 requirements
  21. ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  22. **
  23. ** In addition, as a special exception, Digia gives you certain additional
  24. ** rights. These rights are described in the Digia Qt LGPL Exception
  25. ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
  26. **
  27. ****************************************************************************/
  28. #include "sdbcommandexecutor.h"
  29. #include "sdbconnector.h"
  30. #include "sdbpacketutils.h"
  31. #include <utils/qtcassert.h>
  32. #include <QDebug>
  33. namespace Tizen {
  34. SdbCommandExecutor::SdbCommandExecutor(SdbConnector * connector, QObject *parent) :
  35. QIODevice(parent),
  36. m_connector(connector),
  37. m_socket(NULL),
  38. m_state(Disconnected)
  39. {
  40. }
  41. SdbCommandExecutor::~SdbCommandExecutor()
  42. {
  43. if(m_socket) {
  44. m_socket->disconnect(this);
  45. m_socket->deleteLater();
  46. m_socket = NULL;
  47. }
  48. }
  49. bool SdbCommandExecutor::atEnd() const
  50. {
  51. return QIODevice::atEnd() && m_buffer.isEmpty();
  52. }
  53. qint64 SdbCommandExecutor::bytesAvailable() const
  54. {
  55. return QIODevice::bytesAvailable() + m_buffer.size();
  56. }
  57. bool SdbCommandExecutor::canReadLine() const
  58. {
  59. return QIODevice::canReadLine() || m_buffer.contains('\n');
  60. }
  61. void SdbCommandExecutor::close()
  62. {
  63. if(m_state == Disconnected)
  64. return;
  65. if(m_state == Disconnecting)
  66. return;
  67. if(m_state == Connecting) {
  68. m_socket->disconnect(this);
  69. m_socket->deleteLater();
  70. m_socket = NULL;
  71. return;
  72. }
  73. m_state = Disconnecting;
  74. m_socket->disconnectFromHost();
  75. QIODevice::close();
  76. }
  77. bool SdbCommandExecutor::isSequential() const
  78. {
  79. return true;
  80. }
  81. void SdbCommandExecutor::start(const QString &deviceId, const QString& command)
  82. {
  83. QTC_ASSERT(m_state == Disconnected, return);
  84. #ifdef QT_DEBUG
  85. qDebug() << this << ": Execute command" << command << "on device" << deviceId;
  86. #endif
  87. m_state = Connecting;
  88. m_command = command;
  89. m_deviceId = deviceId;
  90. m_socket = m_connector->createChannel(this);
  91. if(!m_socket) {
  92. setErrorString(tr("Can't create SDB socket"));
  93. emit failed();
  94. return;
  95. }
  96. connect(m_socket, SIGNAL(connected()), SLOT(socketConnected()));
  97. connect(m_socket, SIGNAL(disconnected()), SLOT(socketDisconnected()));
  98. connect(m_socket, SIGNAL(readyRead()), SLOT(socketReadyRead()));
  99. connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketError(QAbstractSocket::SocketError)));
  100. connect(m_socket, SIGNAL(readChannelFinished()), SIGNAL(readChannelFinished()));
  101. connect(m_socket, SIGNAL(aboutToClose()), SIGNAL(aboutToClose()));
  102. }
  103. qint64 SdbCommandExecutor::readData(char *data, qint64 maxlen)
  104. {
  105. const qint64 bytesRead = qMin(qint64(m_buffer.size()), maxlen);
  106. memcpy(data, m_buffer.constData(), bytesRead);
  107. m_buffer.remove(0, bytesRead);
  108. return bytesRead;
  109. }
  110. qint64 SdbCommandExecutor::writeData(const char *data, qint64 len)
  111. {
  112. if(m_state == Running) {
  113. return m_socket->write(data, len);
  114. }
  115. return 0;
  116. }
  117. void SdbCommandExecutor::socketReadyRead()
  118. {
  119. if(m_state == Running) {
  120. QByteArray chunk = m_socket->readAll();
  121. //#ifdef QT_DEBUG
  122. // qDebug() << this << "Read:" << chunk;
  123. //#endif
  124. m_buffer.append(chunk);
  125. emit readyRead();
  126. } else if(m_state == WaitForInitResponse) {
  127. m_cmdBuffer.append(m_socket->readAll());
  128. Tizen::SdbResponse resp;
  129. if(Tizen::SdbPacketUtils::parseResponse(m_cmdBuffer, false, resp)) {
  130. m_cmdBuffer.remove(0, resp.length_read);
  131. if(!resp.okay) {
  132. #ifdef QT_DEBUG
  133. qDebug() << this << ": Device selection failure: " << resp.message;
  134. #endif
  135. m_state = Disconnecting;
  136. m_socket->disconnectFromHost();
  137. setErrorString(resp.message);
  138. emit failed();
  139. return;
  140. }
  141. #ifdef QT_DEBUG
  142. qDebug() << this << ": Device selected for command. Request shell command";
  143. #endif
  144. m_socket->write(Tizen::SdbPacketUtils::makeRequest(QByteArray("shell:") + m_command.toUtf8()));
  145. m_state = WaitForExecResponse;
  146. }
  147. } else if(m_state == WaitForExecResponse) {
  148. m_cmdBuffer.append(m_socket->readAll());
  149. Tizen::SdbResponse resp;
  150. if(Tizen::SdbPacketUtils::parseResponse(m_cmdBuffer, false, resp)) {
  151. #ifdef QT_DEBUG
  152. #endif
  153. m_cmdBuffer.remove(0, resp.length_read);
  154. if(!resp.okay) {
  155. #ifdef QT_DEBUG
  156. qDebug() << this << ": Command exec failure: " << resp.message;
  157. #endif
  158. m_state = Disconnecting;
  159. disconnect(m_socket, SIGNAL(readyRead()), this, SLOT(socketReadyRead()));
  160. m_socket->disconnectFromHost();
  161. setErrorString(resp.message);
  162. emit failed();
  163. return;
  164. }
  165. open(QIODevice::ReadWrite);
  166. #ifdef QT_DEBUG
  167. qDebug() << this << ": Command started";
  168. #endif
  169. m_state = Running;
  170. emit started();
  171. qSwap(m_buffer, m_cmdBuffer);
  172. if(!m_buffer.isEmpty()) {
  173. //#ifdef QT_DEBUG
  174. // qDebug() << "Buffer is" << m_buffer;
  175. //#endif
  176. emit readyRead();
  177. }
  178. }
  179. }
  180. }
  181. void SdbCommandExecutor::socketConnected()
  182. {
  183. m_state = WaitForInitResponse;
  184. m_socket->write(Tizen::SdbPacketUtils::makeInitializeDeviceMessage(m_deviceId));
  185. #ifdef QT_DEBUG
  186. qDebug() << this << ": Socket connected. Wait for device selection";
  187. #endif
  188. }
  189. void SdbCommandExecutor::socketDisconnected()
  190. {
  191. #ifdef QT_DEBUG
  192. qDebug() << this << ": Socket disconnected in state" << m_state;
  193. #endif
  194. if(m_state == Disconnecting) {
  195. m_state = Disconnected;
  196. emit finished();
  197. }
  198. }
  199. void SdbCommandExecutor::socketError(QAbstractSocket::SocketError error)
  200. {
  201. #ifdef QT_DEBUG
  202. qDebug() << this << ": Socket error" << m_socket->errorString() << "in state" << m_state << ", " << m_buffer.size() << "bytes left in buffer";
  203. #endif
  204. if(m_state == Running) {
  205. if(error == QAbstractSocket::RemoteHostClosedError) {
  206. m_state = Disconnected;
  207. emit finished();
  208. return;
  209. }
  210. }
  211. setErrorString(m_socket->errorString());
  212. m_socket->disconnect(this);
  213. m_socket->deleteLater();
  214. m_socket = NULL;
  215. if(isOpen())
  216. QIODevice::close();
  217. m_state = Disconnected;
  218. emit failed();
  219. }
  220. } // namespace Tizen