<commit_before>/*
 *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <stdint.h>

#include "webrtc/base/array_view.h"
#include "webrtc/call/flexfec_receive_stream_impl.h"
#include "webrtc/call/rtp_stream_receiver_controller.h"
#include "webrtc/modules/pacing/packet_router.h"
#include "webrtc/modules/rtp_rtcp/include/flexfec_receiver.h"
#include "webrtc/modules/rtp_rtcp/mocks/mock_recovered_packet_receiver.h"
#include "webrtc/modules/rtp_rtcp/mocks/mock_rtcp_rtt_stats.h"
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "webrtc/modules/utility/include/mock/mock_process_thread.h"
#include "webrtc/test/gmock.h"
#include "webrtc/test/gtest.h"
#include "webrtc/test/mock_transport.h"

namespace webrtc {

namespace {

constexpr uint8_t kFlexfecPlType = 118;
constexpr uint8_t kFlexfecSsrc[] = {0x00, 0x00, 0x00, 0x01};
constexpr uint8_t kMediaSsrc[] = {0x00, 0x00, 0x00, 0x02};

FlexfecReceiveStream::Config CreateDefaultConfig(
    Transport* rtcp_send_transport) {
  FlexfecReceiveStream::Config config(rtcp_send_transport);
  config.payload_type = kFlexfecPlType;
  config.remote_ssrc = ByteReader<uint32_t>::ReadBigEndian(kFlexfecSsrc);
  config.protected_media_ssrcs = {
      ByteReader<uint32_t>::ReadBigEndian(kMediaSsrc)};
  EXPECT_TRUE(config.IsCompleteAndEnabled());
  return config;
}

RtpPacketReceived ParsePacket(rtc::ArrayView<const uint8_t> packet) {
  RtpPacketReceived parsed_packet(nullptr);
  EXPECT_TRUE(parsed_packet.Parse(packet));
  return parsed_packet;
}

}  // namespace

TEST(FlexfecReceiveStreamConfigTest, IsCompleteAndEnabled) {
  MockTransport rtcp_send_transport;
  FlexfecReceiveStream::Config config(&rtcp_send_transport);

  config.local_ssrc = 18374743;
  config.rtcp_mode = RtcpMode::kCompound;
  config.transport_cc = true;
  config.rtp_header_extensions.emplace_back(TransportSequenceNumber::kUri, 7);
  EXPECT_FALSE(config.IsCompleteAndEnabled());

  config.payload_type = 123;
  EXPECT_FALSE(config.IsCompleteAndEnabled());

  config.remote_ssrc = 238423838;
  EXPECT_FALSE(config.IsCompleteAndEnabled());

  config.protected_media_ssrcs.push_back(138989393);
  EXPECT_TRUE(config.IsCompleteAndEnabled());

  config.protected_media_ssrcs.push_back(33423423);
  EXPECT_FALSE(config.IsCompleteAndEnabled());
}

class FlexfecReceiveStreamTest : public ::testing::Test {
 protected:
  FlexfecReceiveStreamTest()
      : config_(CreateDefaultConfig(&rtcp_send_transport_)),
        receive_stream_(&rtp_stream_receiver_controller_,
                        config_,
                        &recovered_packet_receiver_,
                        &rtt_stats_,
                        &process_thread_) {}

  MockTransport rtcp_send_transport_;
  FlexfecReceiveStream::Config config_;
  MockRecoveredPacketReceiver recovered_packet_receiver_;
  MockRtcpRttStats rtt_stats_;
  MockProcessThread process_thread_;
  RtpStreamReceiverController rtp_stream_receiver_controller_;
  FlexfecReceiveStreamImpl receive_stream_;
};

TEST_F(FlexfecReceiveStreamTest, ConstructDestruct) {}

TEST_F(FlexfecReceiveStreamTest, StartStop) {
  receive_stream_.Start();
  receive_stream_.Stop();
}

// Create a FlexFEC packet that protects a single media packet and ensure
// that the callback is called. Correctness of recovery is checked in the
// FlexfecReceiver unit tests.
TEST_F(FlexfecReceiveStreamTest, RecoversPacketWhenStarted) {
  constexpr uint8_t kFlexfecSeqNum[] = {0x00, 0x01};
  constexpr uint8_t kFlexfecTs[] = {0x00, 0x11, 0x22, 0x33};
  constexpr uint8_t kMediaPlType = 107;
  constexpr uint8_t kMediaSeqNum[] = {0x00, 0x02};
  constexpr uint8_t kMediaTs[] = {0xaa, 0xbb, 0xcc, 0xdd};

  // This packet mask protects a single media packet, i.e., the FlexFEC payload
  // is a copy of that media packet. When inserted in the FlexFEC pipeline,
  // it will thus trivially recover the lost media packet.
  constexpr uint8_t kKBit0 = 1 << 7;
  constexpr uint8_t kFlexfecPktMask[] = {kKBit0 | 0x00, 0x01};
  constexpr uint8_t kPayloadLength[] = {0x00, 0x04};
  constexpr uint8_t kSsrcCount = 1;
  constexpr uint8_t kReservedBits = 0x00;
  constexpr uint8_t kPayloadBits = 0x00;
  // clang-format off
  constexpr uint8_t kFlexfecPacket[] = {
      // RTP header.
      0x80,            kFlexfecPlType,  kFlexfecSeqNum[0],  kFlexfecSeqNum[1],
      kFlexfecTs[0],   kFlexfecTs[1],   kFlexfecTs[2],      kFlexfecTs[3],
      kFlexfecSsrc[0], kFlexfecSsrc[1], kFlexfecSsrc[2],    kFlexfecSsrc[3],
      // FlexFEC header.
      0x00,            kMediaPlType,    kPayloadLength[0],  kPayloadLength[1],
      kMediaTs[0],     kMediaTs[1],     kMediaTs[2],        kMediaTs[3],
      kSsrcCount,      kReservedBits,   kReservedBits,      kReservedBits,
      kMediaSsrc[0],   kMediaSsrc[1],   kMediaSsrc[2],      kMediaSsrc[3],
      kMediaSeqNum[0], kMediaSeqNum[1], kFlexfecPktMask[0], kFlexfecPktMask[1],
      // FEC payload.
      kPayloadBits,    kPayloadBits,    kPayloadBits,       kPayloadBits};
  // clang-format on

  testing::StrictMock<MockRecoveredPacketReceiver> recovered_packet_receiver;
  FlexfecReceiveStreamImpl receive_stream(&rtp_stream_receiver_controller_,
                                          config_, &recovered_packet_receiver,
                                          &rtt_stats_, &process_thread_);

  // Do not call back before being started.
  receive_stream.OnRtpPacket(ParsePacket(kFlexfecPacket));

  // Call back after being started.
  receive_stream.Start();
  EXPECT_CALL(
      recovered_packet_receiver,
      OnRecoveredPacket(::testing::_, kRtpHeaderSize + kPayloadLength[1]));
  receive_stream.OnRtpPacket(ParsePacket(kFlexfecPacket));
}

}  // namespace webrtc
<commit_msg>Fix gmock warnings emanating from FlexfecReceiveStreamTest<commit_after>/*
 *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/call/flexfec_receive_stream_impl.h"

#include <stdint.h>
#include <memory>

#include "webrtc/base/array_view.h"
#include "webrtc/call/rtp_stream_receiver_controller.h"
#include "webrtc/modules/pacing/packet_router.h"
#include "webrtc/modules/rtp_rtcp/include/flexfec_receiver.h"
#include "webrtc/modules/rtp_rtcp/mocks/mock_recovered_packet_receiver.h"
#include "webrtc/modules/rtp_rtcp/mocks/mock_rtcp_rtt_stats.h"
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "webrtc/modules/utility/include/mock/mock_process_thread.h"
#include "webrtc/rtc_base/ptr_util.h"
#include "webrtc/test/gmock.h"
#include "webrtc/test/gtest.h"
#include "webrtc/test/mock_transport.h"

namespace webrtc {

namespace {

using ::testing::_;

constexpr uint8_t kFlexfecPlType = 118;
constexpr uint8_t kFlexfecSsrc[] = {0x00, 0x00, 0x00, 0x01};
constexpr uint8_t kMediaSsrc[] = {0x00, 0x00, 0x00, 0x02};

FlexfecReceiveStream::Config CreateDefaultConfig(
    Transport* rtcp_send_transport) {
  FlexfecReceiveStream::Config config(rtcp_send_transport);
  config.payload_type = kFlexfecPlType;
  config.remote_ssrc = ByteReader<uint32_t>::ReadBigEndian(kFlexfecSsrc);
  config.protected_media_ssrcs = {
      ByteReader<uint32_t>::ReadBigEndian(kMediaSsrc)};
  EXPECT_TRUE(config.IsCompleteAndEnabled());
  return config;
}

RtpPacketReceived ParsePacket(rtc::ArrayView<const uint8_t> packet) {
  RtpPacketReceived parsed_packet(nullptr);
  EXPECT_TRUE(parsed_packet.Parse(packet));
  return parsed_packet;
}

}  // namespace

TEST(FlexfecReceiveStreamConfigTest, IsCompleteAndEnabled) {
  MockTransport rtcp_send_transport;
  FlexfecReceiveStream::Config config(&rtcp_send_transport);

  config.local_ssrc = 18374743;
  config.rtcp_mode = RtcpMode::kCompound;
  config.transport_cc = true;
  config.rtp_header_extensions.emplace_back(TransportSequenceNumber::kUri, 7);
  EXPECT_FALSE(config.IsCompleteAndEnabled());

  config.payload_type = 123;
  EXPECT_FALSE(config.IsCompleteAndEnabled());

  config.remote_ssrc = 238423838;
  EXPECT_FALSE(config.IsCompleteAndEnabled());

  config.protected_media_ssrcs.push_back(138989393);
  EXPECT_TRUE(config.IsCompleteAndEnabled());

  config.protected_media_ssrcs.push_back(33423423);
  EXPECT_FALSE(config.IsCompleteAndEnabled());
}

class FlexfecReceiveStreamTest : public ::testing::Test {
 protected:
  FlexfecReceiveStreamTest()
      : config_(CreateDefaultConfig(&rtcp_send_transport_)) {
    EXPECT_CALL(process_thread_, RegisterModule(_, _)).Times(1);
    receive_stream_ = rtc::MakeUnique<FlexfecReceiveStreamImpl>(
        &rtp_stream_receiver_controller_, config_, &recovered_packet_receiver_,
        &rtt_stats_, &process_thread_);
  }

  ~FlexfecReceiveStreamTest() {
    EXPECT_CALL(process_thread_, DeRegisterModule(_)).Times(1);
  }

  MockTransport rtcp_send_transport_;
  FlexfecReceiveStream::Config config_;
  MockRecoveredPacketReceiver recovered_packet_receiver_;
  MockRtcpRttStats rtt_stats_;
  MockProcessThread process_thread_;
  RtpStreamReceiverController rtp_stream_receiver_controller_;
  std::unique_ptr<FlexfecReceiveStreamImpl> receive_stream_;
};

TEST_F(FlexfecReceiveStreamTest, ConstructDestruct) {}

TEST_F(FlexfecReceiveStreamTest, StartStop) {
  receive_stream_->Start();
  receive_stream_->Stop();
}

// Create a FlexFEC packet that protects a single media packet and ensure
// that the callback is called. Correctness of recovery is checked in the
// FlexfecReceiver unit tests.
TEST_F(FlexfecReceiveStreamTest, RecoversPacketWhenStarted) {
  constexpr uint8_t kFlexfecSeqNum[] = {0x00, 0x01};
  constexpr uint8_t kFlexfecTs[] = {0x00, 0x11, 0x22, 0x33};
  constexpr uint8_t kMediaPlType = 107;
  constexpr uint8_t kMediaSeqNum[] = {0x00, 0x02};
  constexpr uint8_t kMediaTs[] = {0xaa, 0xbb, 0xcc, 0xdd};

  // This packet mask protects a single media packet, i.e., the FlexFEC payload
  // is a copy of that media packet. When inserted in the FlexFEC pipeline,
  // it will thus trivially recover the lost media packet.
  constexpr uint8_t kKBit0 = 1 << 7;
  constexpr uint8_t kFlexfecPktMask[] = {kKBit0 | 0x00, 0x01};
  constexpr uint8_t kPayloadLength[] = {0x00, 0x04};
  constexpr uint8_t kSsrcCount = 1;
  constexpr uint8_t kReservedBits = 0x00;
  constexpr uint8_t kPayloadBits = 0x00;
  // clang-format off
  constexpr uint8_t kFlexfecPacket[] = {
      // RTP header.
      0x80,            kFlexfecPlType,  kFlexfecSeqNum[0],  kFlexfecSeqNum[1],
      kFlexfecTs[0],   kFlexfecTs[1],   kFlexfecTs[2],      kFlexfecTs[3],
      kFlexfecSsrc[0], kFlexfecSsrc[1], kFlexfecSsrc[2],    kFlexfecSsrc[3],
      // FlexFEC header.
      0x00,            kMediaPlType,    kPayloadLength[0],  kPayloadLength[1],
      kMediaTs[0],     kMediaTs[1],     kMediaTs[2],        kMediaTs[3],
      kSsrcCount,      kReservedBits,   kReservedBits,      kReservedBits,
      kMediaSsrc[0],   kMediaSsrc[1],   kMediaSsrc[2],      kMediaSsrc[3],
      kMediaSeqNum[0], kMediaSeqNum[1], kFlexfecPktMask[0], kFlexfecPktMask[1],
      // FEC payload.
      kPayloadBits,    kPayloadBits,    kPayloadBits,       kPayloadBits};
  // clang-format on

  testing::StrictMock<MockRecoveredPacketReceiver> recovered_packet_receiver;
  EXPECT_CALL(process_thread_, RegisterModule(_, _)).Times(1);
  FlexfecReceiveStreamImpl receive_stream(&rtp_stream_receiver_controller_,
                                          config_, &recovered_packet_receiver,
                                          &rtt_stats_, &process_thread_);

  // Do not call back before being started.
  receive_stream.OnRtpPacket(ParsePacket(kFlexfecPacket));

  // Call back after being started.
  receive_stream.Start();
  EXPECT_CALL(recovered_packet_receiver,
              OnRecoveredPacket(_, kRtpHeaderSize + kPayloadLength[1]));
  receive_stream.OnRtpPacket(ParsePacket(kFlexfecPacket));

  // Tear-down
  EXPECT_CALL(process_thread_, DeRegisterModule(_)).Times(1);
}

}  // namespace webrtc
<|endoftext|>


<commit_before>/**
 * << detailed description >>
 *
 * @file Config.cpp
 * @brief << brief description >>
 * @author clonker
 * @date 05.09.16
 */

#include <thread>
#include "readdy/kernel/cpu/util/Config.h"

namespace readdy {
    namespace kernel {
        namespace cpu {
            namespace util {
                Config::Config() {
                    nThreads = std::thread::hardware_concurrency();
                }
            }
        }
    }
}<commit_msg>made n threads of cpu kernel customizable by environment variable<commit_after>/**
 * << detailed description >>
 *
 * @file Config.cpp
 * @brief << brief description >>
 * @author clonker
 * @date 05.09.16
 */

#include <thread>
#include <boost/log/trivial.hpp>
#include "readdy/kernel/cpu/util/Config.h"

namespace readdy {
    namespace kernel {
        namespace cpu {
            namespace util {
                Config::Config() {
                    nThreads = std::thread::hardware_concurrency();
                    const char *env = std::getenv("READDY_N_CORES");
                    if(env) {
                        nThreads = static_cast<unsigned long>(std::stol(env));
                        BOOST_LOG_TRIVIAL(debug) << "Using "
                                                 << nThreads << " threads (by environment variable READDY_N_CORES)";
                    }
                }
            }
        }
    }
}<|endoftext|>


<commit_before>/* Copyright 2012-2016 QReal Research Group
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. */

#include "nxtKit/communication/usbRobotCommunicationThread.h"

#include <QtCore/QCoreApplication>
#include <time.h>

#include <qrkernel/logging.h>
#include <plugins/robots/thirdparty/libusb-1.0.19/include/libusb-1.0/libusb.h>

#include "nxtKit/communication/nxtCommandConstants.h"
#include "nxtKit/communication/nxtUsbDriverInstaller.h"

using namespace nxt::communication;

const int packetHeaderSize = 2;

static const int NXT_VID   = 0x0694;
static const int NXT_PID   = 0x0002;
static const int ATMEL_VID  = 0x03EB;
static const int SAMBA_PID = 0x6124;
static const int NXT_USB_TIMEOUT = 2000;
static const int NXT_EP_OUT = 0x01;
static const int NXT_EP_IN = 0x82;
static const int NXT_INTERFACE_NUMBER = 0;
static const int DEBUG_LEVEL = 3;

UsbRobotCommunicationThread::UsbRobotCommunicationThread()
	: mHandle(nullptr)
	, mFirmwareMode(false)
	, mKeepAliveTimer(new QTimer(this))
	, mDriverInstaller(new NxtUsbDriverInstaller)
	, mStopped(false)
{
	QObject::connect(mKeepAliveTimer, &QTimer::timeout, this, &UsbRobotCommunicationThread::checkForConnection);
	mDriverInstaller->moveToThread(qApp->thread());
	QObject::connect(this, &UsbRobotCommunicationThread::noDriversFound, mDriverInstaller.data()
			, &NxtUsbDriverInstaller::installUsbDriver, Qt::QueuedConnection);
	QObject::connect(mDriverInstaller.data(), &NxtUsbDriverInstaller::errorOccured
			, this, &UsbRobotCommunicationThread::errorOccured, Qt::QueuedConnection);
	QObject::connect(mDriverInstaller.data(), &NxtUsbDriverInstaller::messageArrived
			, this, &UsbRobotCommunicationThread::messageArrived, Qt::QueuedConnection);
}

UsbRobotCommunicationThread::~UsbRobotCommunicationThread()
{
	if (mHandle) {
		disconnect();
	}
}

bool UsbRobotCommunicationThread::connectImpl(bool firmwareMode, int vid, int pid, const QString &notConnectedErrorText)
{
	if (mHandle) {
		emit connected(true, QString());
		return true;
	}

	QLOG_INFO() << "Connecting to NXT brick" << (firmwareMode ? "in firmware mode" : "");
	libusb_init(nullptr);
	libusb_set_debug(nullptr, DEBUG_LEVEL);

	libusb_device **devices;
	int count = libusb_get_device_list(nullptr, &devices);
	for (int i = 0; i < count; ++i) {
		libusb_device_descriptor device_descriptor;
		if (libusb_get_device_descriptor(devices[i], &device_descriptor) < 0) {
			continue;
		}

		if (device_descriptor.idVendor == vid && device_descriptor.idProduct == pid) {
			const int err = libusb_open(devices[i], &mHandle);
			if (err == LIBUSB_ERROR_NOT_SUPPORTED) {
				emit noDriversFound();
				libusb_free_device_list(devices, 1);
				if (mHandle) {
					libusb_close(mHandle);
				}

				return false;
			} else if (err < 0 || !mHandle) {
				QLOG_ERROR() << "libusb_open returned" << err;
				emit connected(false, notConnectedErrorText);
				libusb_free_device_list(devices, 1);
				return false;
			} else {
				break;
			}
		}
	}

	if (!mHandle) {
		libusb_free_device_list(devices, 1);
		emit connected(false, notConnectedErrorText);
		return false;
	}

	if (libusb_kernel_driver_active(mHandle, NXT_INTERFACE_NUMBER)) {
		libusb_detach_kernel_driver(mHandle, NXT_INTERFACE_NUMBER);
	}

	const QList<int> configurations = {0, 1, 2};
	bool configurationFound = false;
	for (int configiration : configurations) {
		const int err = libusb_set_configuration(mHandle, configiration);
		if (err < 0 && err != LIBUSB_ERROR_NOT_FOUND && err != LIBUSB_ERROR_INVALID_PARAM) {
			QLOG_ERROR() << "libusb_set_configuration for NXT returned" << err << "for configuration" << configiration;
			break;
		} else if (err >= 0) {
			configurationFound = true;
			break;
		}
	}

	if (!configurationFound) {
		QLOG_ERROR() << "No appropriate configuration found among" << configurations << ". Giving up.";
		emit connected(false, tr("USB Device configuration problem. Try to restart TRIK Studio and re-plug NXT."));
		libusb_close(mHandle);
		mHandle = nullptr;
		libusb_free_device_list(devices, 1);
		return false;
	}

	const QList<int> interfaces = firmwareMode ? QList<int>({1, 2}) : QList<int>({0, 1, 2});
	bool interfaceFound = false;
	for (int interface : interfaces) {
		const int err = libusb_claim_interface(mHandle, interface);
		if (err < 0 && err != LIBUSB_ERROR_NOT_FOUND && err != LIBUSB_ERROR_INVALID_PARAM) {
			QLOG_ERROR() << "libusb_claim_interface for NXT returned" << err << "for interface" << interface;
			break;
		} else if (err >= 0) {
			interfaceFound = true;
			break;
		}
	}

	if (!interfaceFound) {
		QLOG_ERROR() << "No appropriate interface found among" << interfaces << ". Giving up.";
		emit connected(false, tr("NXT device is already used by another software."));
		libusb_close(mHandle);
		mHandle = nullptr;
		libusb_free_device_list(devices, 1);
		return false;
	}

	mFirmwareMode = firmwareMode;
	QByteArray getFirmwareCommand(4, 0);
	getFirmwareCommand[0] = '\0';
	getFirmwareCommand[1] = '\0';
	// Sending direct command telegram to flashed robot or "N#" in samba mode
	getFirmwareCommand[2] = firmwareMode ? 'N' : static_cast<char>(enums::telegramType::directCommandResponseRequired);
	getFirmwareCommand[3] = firmwareMode ? '#' : 0x88;

	QByteArray handshakeResponse;
	send(getFirmwareCommand, firmwareMode ? 4 : 9, handshakeResponse);
	// In samba mode NXT should answer "\n\r"
	const bool correctFirmwareResponce = !firmwareMode ||
			(handshakeResponse.length() == 4 && handshakeResponse[2] == '\n' && handshakeResponse[3] == '\r');
	if (handshakeResponse.isEmpty() || !correctFirmwareResponce) {
		emit connected(false, tr("NXT handshake procedure failed. Please contact developers."));
		libusb_close(mHandle);
		mHandle = nullptr;
		libusb_free_device_list(devices, 1);
		return false;
	}

	QLOG_INFO() << "Connected successfully!";
	emit connected(true, QString());

	if (!firmwareMode) {
		mKeepAliveTimer->moveToThread(thread());
		mKeepAliveTimer->start(500);
	}

	return true;
}

bool UsbRobotCommunicationThread::connect()
{
	const QString error = tr("Cannot find NXT device. Check robot connected and turned on and try again.");
	return connectImpl(false, NXT_VID, NXT_PID, error);
}

bool UsbRobotCommunicationThread::send(QObject *addressee, const QByteArray &buffer, int responseSize)
{
	QByteArray outputBuffer;
	outputBuffer.resize(responseSize);
	const bool result = send(buffer, responseSize, outputBuffer);
	if (!isResponseNeeded(buffer)) {
		emit response(addressee, QByteArray());
	} else {
		emit response(addressee, outputBuffer);
	}

	return result;
}

bool UsbRobotCommunicationThread::send(const QByteArray &buffer, int responseSize, QByteArray &outputBuffer)
{
	if (!mHandle) {
		return false;
	}

	QByteArray newBuffer;
	for (int i = packetHeaderSize; i < buffer.length(); ++i) {
		newBuffer[i - packetHeaderSize] = buffer[i];
	}

	uchar *cmd = reinterpret_cast<uchar *>(const_cast<char *>(newBuffer.data()));
	int actualLength = 0;
	int err = libusb_bulk_transfer(mHandle, NXT_EP_OUT, cmd, newBuffer.length(), &actualLength, NXT_USB_TIMEOUT);
	if (err == LIBUSB_ERROR_IO || err == LIBUSB_ERROR_PIPE
			|| err == LIBUSB_ERROR_INTERRUPTED || err == LIBUSB_ERROR_NO_DEVICE)
	{
		QLOG_ERROR() << "Connection to NXT lost with code" << err << "during sending buffers";
		emit errorOccured(tr("Connection to NXT lost"));
		disconnect();
		return false;
	} else if (err < 0) {
		QLOG_ERROR() << "Sending" << buffer << "failed with libusb error" << err;
		return false;
	}

	const bool responceUnneeded = (mFirmwareMode && responseSize == 0) || (!mFirmwareMode && !isResponseNeeded(buffer));
	if (responceUnneeded) {
		return true;
	}

	uchar response[responseSize];
	actualLength = 0;
	outputBuffer = QByteArray(responseSize, '\0');
	err = libusb_bulk_transfer(mHandle, NXT_EP_IN, response, responseSize, &actualLength, NXT_USB_TIMEOUT);
	if (err == LIBUSB_ERROR_IO || err == LIBUSB_ERROR_PIPE || err == LIBUSB_ERROR_INTERRUPTED) {
		QLOG_ERROR() << "Connection to NXT lost with code" << err << "during recieving answer";
		emit errorOccured(tr("Connection to NXT lost"));
		disconnect();
		return false;
	} else if (err < 0) {
		QLOG_TRACE() << "Recieving answer from command" << buffer << "failed with libusb error" << err;
		return false;
	}

	outputBuffer[0] = responseSize - 2;
	outputBuffer[1] = 0;
	for (int i = 0; i < responseSize - packetHeaderSize; ++i) {
		outputBuffer[i + packetHeaderSize] = response[i];
	}

	return true;
}

void UsbRobotCommunicationThread::reconnect()
{
	connect();
}

void UsbRobotCommunicationThread::disconnect()
{
	if (mHandle) {
		libusb_attach_kernel_driver(mHandle, NXT_INTERFACE_NUMBER);
		libusb_close(mHandle);
		libusb_exit(nullptr);
		mHandle = nullptr;
	}

	mKeepAliveTimer->stop();
	emit disconnected();
}

void UsbRobotCommunicationThread::allowLongJobs(bool allow)
{
	mStopped = !allow;
}

bool UsbRobotCommunicationThread::connectFirmware()
{
	const QString error = tr("Cannot find NXT device in resetted mode. Check robot resetted, connected and ticking "\
			"and try again.");
	return connectImpl(true, ATMEL_VID, SAMBA_PID, error);
}

void UsbRobotCommunicationThread::checkForConnection()
{
	QByteArray command(4, 0);
	command[3] = enums::commandCode::KEEPALIVE;

	const int keepAliveResponseSize = 9;

	QByteArray response;
	response.resize(keepAliveResponseSize);

	send(command, keepAliveResponseSize, response);

	if (response[3] == '\0') {
		emit disconnected();
	}
}

bool UsbRobotCommunicationThread::isResponseNeeded(const QByteArray &buffer)
{
	return buffer.size() >= 3 && (buffer[2] == enums::telegramType::directCommandResponseRequired
			|| buffer[2] == enums::telegramType::systemCommandResponseRequired);
}
<commit_msg>right order for interfaces<commit_after>/* Copyright 2012-2016 QReal Research Group
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. */

#include "nxtKit/communication/usbRobotCommunicationThread.h"

#include <QtCore/QCoreApplication>
#include <time.h>

#include <qrkernel/logging.h>
#include <plugins/robots/thirdparty/libusb-1.0.19/include/libusb-1.0/libusb.h>

#include "nxtKit/communication/nxtCommandConstants.h"
#include "nxtKit/communication/nxtUsbDriverInstaller.h"

using namespace nxt::communication;

const int packetHeaderSize = 2;

static const int NXT_VID   = 0x0694;
static const int NXT_PID   = 0x0002;
static const int ATMEL_VID  = 0x03EB;
static const int SAMBA_PID = 0x6124;
static const int NXT_USB_TIMEOUT = 2000;
static const int NXT_EP_OUT = 0x01;
static const int NXT_EP_IN = 0x82;
static const int NXT_INTERFACE_NUMBER = 0;
static const int DEBUG_LEVEL = 3;

UsbRobotCommunicationThread::UsbRobotCommunicationThread()
	: mHandle(nullptr)
	, mFirmwareMode(false)
	, mKeepAliveTimer(new QTimer(this))
	, mDriverInstaller(new NxtUsbDriverInstaller)
	, mStopped(false)
{
	QObject::connect(mKeepAliveTimer, &QTimer::timeout, this, &UsbRobotCommunicationThread::checkForConnection);
	mDriverInstaller->moveToThread(qApp->thread());
	QObject::connect(this, &UsbRobotCommunicationThread::noDriversFound, mDriverInstaller.data()
			, &NxtUsbDriverInstaller::installUsbDriver, Qt::QueuedConnection);
	QObject::connect(mDriverInstaller.data(), &NxtUsbDriverInstaller::errorOccured
			, this, &UsbRobotCommunicationThread::errorOccured, Qt::QueuedConnection);
	QObject::connect(mDriverInstaller.data(), &NxtUsbDriverInstaller::messageArrived
			, this, &UsbRobotCommunicationThread::messageArrived, Qt::QueuedConnection);
}

UsbRobotCommunicationThread::~UsbRobotCommunicationThread()
{
	if (mHandle) {
		disconnect();
	}
}

bool UsbRobotCommunicationThread::connectImpl(bool firmwareMode, int vid, int pid, const QString &notConnectedErrorText)
{
	if (mHandle) {
		emit connected(true, QString());
		return true;
	}

	QLOG_INFO() << "Connecting to NXT brick" << (firmwareMode ? "in firmware mode" : "");
	libusb_init(nullptr);
	libusb_set_debug(nullptr, DEBUG_LEVEL);

	libusb_device **devices;
	int count = libusb_get_device_list(nullptr, &devices);
	for (int i = 0; i < count; ++i) {
		libusb_device_descriptor device_descriptor;
		if (libusb_get_device_descriptor(devices[i], &device_descriptor) < 0) {
			continue;
		}

		if (device_descriptor.idVendor == vid && device_descriptor.idProduct == pid) {
			const int err = libusb_open(devices[i], &mHandle);
			if (err == LIBUSB_ERROR_NOT_SUPPORTED) {
				emit noDriversFound();
				libusb_free_device_list(devices, 1);
				if (mHandle) {
					libusb_close(mHandle);
				}

				return false;
			} else if (err < 0 || !mHandle) {
				QLOG_ERROR() << "libusb_open returned" << err;
				emit connected(false, notConnectedErrorText);
				libusb_free_device_list(devices, 1);
				return false;
			} else {
				break;
			}
		}
	}

	if (!mHandle) {
		libusb_free_device_list(devices, 1);
		emit connected(false, notConnectedErrorText);
		return false;
	}

	if (libusb_kernel_driver_active(mHandle, NXT_INTERFACE_NUMBER)) {
		libusb_detach_kernel_driver(mHandle, NXT_INTERFACE_NUMBER);
	}

	// old tool libnxt says that it should be 1
	const QList<int> configurations = {1, 0, 2};
	bool configurationFound = false;
	for (int configiration : configurations) {
		const int err = libusb_set_configuration(mHandle, configiration);
		if (err < 0 && err != LIBUSB_ERROR_NOT_FOUND && err != LIBUSB_ERROR_INVALID_PARAM) {
			QLOG_ERROR() << "libusb_set_configuration for NXT returned" << err << "for configuration" << configiration;
			break;
		} else if (err >= 0) {
			configurationFound = true;
			break;
		}
	}

	if (!configurationFound) {
		QLOG_ERROR() << "No appropriate configuration found among" << configurations << ". Giving up.";
		emit connected(false, tr("USB Device configuration problem. Try to restart TRIK Studio and re-plug NXT."));
		libusb_close(mHandle);
		mHandle = nullptr;
		libusb_free_device_list(devices, 1);
		return false;
	}

	// old tool libnxt says that it should be 1
	const QList<int> interfaces = QList<int>({1, 0, 2});
	bool interfaceFound = false;
	for (int interface : interfaces) {
		const int err = libusb_claim_interface(mHandle, interface);
		if (err < 0 && err != LIBUSB_ERROR_NOT_FOUND && err != LIBUSB_ERROR_INVALID_PARAM) {
			QLOG_ERROR() << "libusb_claim_interface for NXT returned" << err << "for interface" << interface;
			break;
		} else if (err >= 0) {
			interfaceFound = true;
			break;
		}
	}

	if (!interfaceFound) {
		QLOG_ERROR() << "No appropriate interface found among" << interfaces << ". Giving up.";
		emit connected(false, tr("NXT device is already used by another software."));
		libusb_close(mHandle);
		mHandle = nullptr;
		libusb_free_device_list(devices, 1);
		return false;
	}

	mFirmwareMode = firmwareMode;
	QByteArray getFirmwareCommand(4, 0);
	getFirmwareCommand[0] = '\0';
	getFirmwareCommand[1] = '\0';
	// Sending direct command telegram to flashed robot or "N#" in samba mode
	getFirmwareCommand[2] = firmwareMode ? 'N' : static_cast<char>(enums::telegramType::directCommandResponseRequired);
	getFirmwareCommand[3] = firmwareMode ? '#' : 0x88;

	QByteArray handshakeResponse;
	send(getFirmwareCommand, firmwareMode ? 4 : 9, handshakeResponse);
	// In samba mode NXT should answer "\n\r"
	const bool correctFirmwareResponce = !firmwareMode ||
			(handshakeResponse.length() == 4 && handshakeResponse[2] == '\n' && handshakeResponse[3] == '\r');
	if (handshakeResponse.isEmpty() || !correctFirmwareResponce) {
		emit connected(false, tr("NXT handshake procedure failed. Please contact developers."));
		libusb_close(mHandle);
		mHandle = nullptr;
		libusb_free_device_list(devices, 1);
		return false;
	}

	QLOG_INFO() << "Connected successfully!";
	emit connected(true, QString());

	if (!firmwareMode) {
		mKeepAliveTimer->moveToThread(thread());
		mKeepAliveTimer->start(500);
	}

	return true;
}

bool UsbRobotCommunicationThread::connect()
{
	const QString error = tr("Cannot find NXT device. Check robot connected and turned on and try again.");
	return connectImpl(false, NXT_VID, NXT_PID, error);
}

bool UsbRobotCommunicationThread::send(QObject *addressee, const QByteArray &buffer, int responseSize)
{
	QByteArray outputBuffer;
	outputBuffer.resize(responseSize);
	const bool result = send(buffer, responseSize, outputBuffer);
	if (!isResponseNeeded(buffer)) {
		emit response(addressee, QByteArray());
	} else {
		emit response(addressee, outputBuffer);
	}

	return result;
}

bool UsbRobotCommunicationThread::send(const QByteArray &buffer, int responseSize, QByteArray &outputBuffer)
{
	if (!mHandle) {
		return false;
	}

	QByteArray newBuffer;
	for (int i = packetHeaderSize; i < buffer.length(); ++i) {
		newBuffer[i - packetHeaderSize] = buffer[i];
	}

	uchar *cmd = reinterpret_cast<uchar *>(const_cast<char *>(newBuffer.data()));
	int actualLength = 0;
	int err = libusb_bulk_transfer(mHandle, NXT_EP_OUT, cmd, newBuffer.length(), &actualLength, NXT_USB_TIMEOUT);
	if (err == LIBUSB_ERROR_IO || err == LIBUSB_ERROR_PIPE
			|| err == LIBUSB_ERROR_INTERRUPTED || err == LIBUSB_ERROR_NO_DEVICE)
	{
		QLOG_ERROR() << "Connection to NXT lost with code" << err << "during sending buffers";
		emit errorOccured(tr("Connection to NXT lost"));
		disconnect();
		return false;
	} else if (err < 0) {
		QLOG_ERROR() << "Sending" << buffer << "failed with libusb error" << err;
		return false;
	}

	const bool responceUnneeded = (mFirmwareMode && responseSize == 0) || (!mFirmwareMode && !isResponseNeeded(buffer));
	if (responceUnneeded) {
		return true;
	}

	uchar response[responseSize];
	actualLength = 0;
	outputBuffer = QByteArray(responseSize, '\0');
	err = libusb_bulk_transfer(mHandle, NXT_EP_IN, response, responseSize, &actualLength, NXT_USB_TIMEOUT);
	if (err == LIBUSB_ERROR_IO || err == LIBUSB_ERROR_PIPE || err == LIBUSB_ERROR_INTERRUPTED) {
		QLOG_ERROR() << "Connection to NXT lost with code" << err << "during recieving answer";
		emit errorOccured(tr("Connection to NXT lost"));
		disconnect();
		return false;
	} else if (err < 0) {
		QLOG_TRACE() << "Recieving answer from command" << buffer << "failed with libusb error" << err;
		return false;
	}

	outputBuffer[0] = responseSize - 2;
	outputBuffer[1] = 0;
	for (int i = 0; i < responseSize - packetHeaderSize; ++i) {
		outputBuffer[i + packetHeaderSize] = response[i];
	}

	return true;
}

void UsbRobotCommunicationThread::reconnect()
{
	connect();
}

void UsbRobotCommunicationThread::disconnect()
{
	if (mHandle) {
		libusb_attach_kernel_driver(mHandle, NXT_INTERFACE_NUMBER);
		libusb_close(mHandle);
		libusb_exit(nullptr);
		mHandle = nullptr;
	}

	mKeepAliveTimer->stop();
	emit disconnected();
}

void UsbRobotCommunicationThread::allowLongJobs(bool allow)
{
	mStopped = !allow;
}

bool UsbRobotCommunicationThread::connectFirmware()
{
	const QString error = tr("Cannot find NXT device in resetted mode. Check robot resetted, connected and ticking "\
			"and try again.");
	return connectImpl(true, ATMEL_VID, SAMBA_PID, error);
}

void UsbRobotCommunicationThread::checkForConnection()
{
	QByteArray command(4, 0);
	command[3] = enums::commandCode::KEEPALIVE;

	const int keepAliveResponseSize = 9;

	QByteArray response;
	response.resize(keepAliveResponseSize);

	send(command, keepAliveResponseSize, response);

	if (response[3] == '\0') {
		emit disconnected();
	}
}

bool UsbRobotCommunicationThread::isResponseNeeded(const QByteArray &buffer)
{
	return buffer.size() >= 3 && (buffer[2] == enums::telegramType::directCommandResponseRequired
			|| buffer[2] == enums::telegramType::systemCommandResponseRequired);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: SubSequence.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: vg $ $Date: 2008-01-24 15:56:42 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef INCLUDED_SUB_SEQUENCE_HXX
#define INCLUDED_SUB_SEQUENCE_HXX

#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

#include <boost/shared_ptr.hpp>
#include <iostream>
#include <ctype.h>
#include "exceptions.hxx"
#include <WriterFilterDllApi.hxx>
#include <resourcemodel/OutputWithDepth.hxx>

namespace writerfilter {
using namespace ::std;

template <class T>
class SubSequence;

template <typename T>
void dumpLine(OutputWithDepth<string> & o, SubSequence<T> & rSeq,
              sal_uInt32 nOffset, sal_uInt32 nStep);

template <class T>
class WRITERFILTER_DLLPUBLIC SubSequence
{
    typedef boost::shared_ptr<com::sun::star::uno::Sequence<T> >
    SequencePointer;

    SequencePointer mpSequence;
    sal_uInt32 mnOffset;
    sal_uInt32 mnCount;

public:
    typedef boost::shared_ptr<SubSequence> Pointer_t;

    SubSequence() : mpSequence(new ::com::sun::star::uno::Sequence<T>()),
                    mnOffset(0), mnCount(0)
    {
    }

    SubSequence(SequencePointer pSequence, sal_uInt32 nOffset_,
                sal_uInt32 nCount_)
        : mpSequence(pSequence), mnOffset(nOffset_), mnCount(nCount_)
    {
    }

    SubSequence(SequencePointer pSequence)
        : mpSequence(pSequence), mnOffset(0), mnCount(pSequence->getLength())
    {
    }

    SubSequence(const SubSequence & rSubSequence, sal_uInt32 nOffset_,
                sal_uInt32 nCount_)
        : mpSequence(rSubSequence.mpSequence),
          mnOffset(rSubSequence.mnOffset + nOffset_),
          mnCount(nCount_)
    {
    }

    SubSequence(const T * pStart, sal_uInt32 nCount_)
        : mpSequence(new com::sun::star::uno::Sequence<T>(pStart, nCount_)),
          mnOffset(0), mnCount(nCount_)
    {
    }

    SubSequence(sal_Int32 nCount_)
        : mpSequence(new com::sun::star::uno::Sequence<T>(nCount_)), mnOffset(0),
          mnCount(nCount_)
    {
    }

    ::com::sun::star::uno::Sequence<T> & getSequence()
    {
        return *mpSequence;
    }

    const ::com::sun::star::uno::Sequence<T> & getSequence() const
    {
        return *mpSequence;
    }

    void reset() {
        mnOffset = 0;
        mnCount = mpSequence->getLength();
    }

    sal_uInt32 getOffset() const { return mnOffset; }
    sal_uInt32 getCount() const { return mnCount; }

    const T & operator[] (sal_uInt32 nIndex) const
    {
        if (mnOffset + nIndex >=
            sal::static_int_cast<sal_uInt32>(mpSequence->getLength()))
            throw ExceptionOutOfBounds("SubSequence::operator[]");

        return (*mpSequence)[mnOffset + nIndex];
    }

    void dump(ostream & o) const
    {
        {
            char sBuffer[256];

            snprintf(sBuffer, sizeof(sBuffer),
                     "<sequence id='%p' offset='%lx' count='%lx'>",
                     mpSequence.get(), mnOffset, mnCount);
            o << sBuffer << endl;
        }

        sal_uInt32 n = 0;
        sal_uInt32 nStep = 16;

        while (n < getCount())
        {
            char sBuffer[256];

            o << "<line>";

            snprintf(sBuffer, 255, "%08lx: ", n);

            o << sBuffer;

            for (sal_uInt32 i = 0; i < nStep; i++)
            {
                if (n + i < getCount())
                {
                    snprintf(sBuffer, 255, "%02x ", operator[](n + i));
                    o << sBuffer;
                }
                else
                    o << "   ";

                if (i % 8 == 7)
                    o << " ";
            }

            {
                for (sal_uInt32 i = 0; i < nStep; i++)
                {
                    if (n + i < getCount())
                    {
                        unsigned char c =
                            static_cast<unsigned char>(operator[](n + i));

                        if (c=='&')
                            o << "&";
                        else if (c=='<')
                            o << "<";
                        else if (c=='>')
                            o << ">";
                        else if (c < 128 && isprint(c))
                            o << c;
                        else
                            o << ".";
                    }

                }
            }

            o << "</line>" << endl;

            n += nStep;
        }

        o << "</sequence>" << endl;
    }

    void dump(OutputWithDepth<string> & o)
    {
        {
            char sBuffer[256];

            snprintf(sBuffer, sizeof(sBuffer),
                     "<sequence id='%p' offset='%" SAL_PRIxUINT32 "' count='%" SAL_PRIxUINT32 "'>",
                     mpSequence.get(), mnOffset, mnCount);
            o.addItem(sBuffer);
        }

        sal_uInt32 n = 0;
        sal_uInt32 nStep = 16;

        try
        {
            sal_uInt32 nCount = getCount();
            while (n < nCount)
            {
                sal_uInt32 nBytes = nCount - n;

                if (nBytes > nStep)
                    nBytes = nStep;

                SubSequence<T> aSeq(*this, n, nBytes);
                dumpLine(o, aSeq, n, nStep);

                n += nBytes;
            }
        }
        catch (...)
        {
            o.addItem("<exception/>");
        }

        o.addItem("</sequence>");
    }

    string toString() const
    {
        sal_uInt32 n = 0;
        sal_uInt32 nStep = 16;

        string sResult;

        while (n < getCount())
        {
            char sBuffer[256];

            snprintf(sBuffer, 255, "<line>%08" SAL_PRIxUINT32 ": ", n);

            sResult += sBuffer;

            for (sal_uInt32 i = 0; i < nStep; i++)
            {
                if (n + i < getCount())
                {
                    snprintf(sBuffer, 255, "%02x ", operator[](n + i));
                    sResult += sBuffer;
                }
                else
                    sResult += "   ";

                if (i % 8 == 7)
                    sResult += " ";
            }

            {
                for (sal_uInt32 i = 0; i < nStep; i++)
                {
                    if (n + i < getCount())
                    {
                        unsigned char c =
                            static_cast<unsigned char>(operator[](n + i));

                        if (c=='&')
                            sResult += "&";
                        else if (c=='<')
                            sResult += "<";
                        else if (c=='>')
                            sResult += ">";
                        else if (c < 128 && isprint(c))
                            sResult += c;
                        else
                            sResult += ".";
                    }
                }
            }

            sResult += "</line>\n";

            n += nStep;
        }

        return sResult;
    }
};

template <typename T>
void dumpLine(OutputWithDepth<string> & o, SubSequence<T> & rSeq,
              sal_uInt32 nOffset, sal_uInt32 nStep)
{
    sal_uInt32 nCount = rSeq.getCount();
    char sBuffer[256];

    string tmpStr = "<line>";

    snprintf(sBuffer, 255, "%08" SAL_PRIxUINT32 ": ", nOffset);

    tmpStr += sBuffer;

    for (sal_uInt32 i = 0; i < nStep; i++)
    {
        if (i < nCount)
        {
            snprintf(sBuffer, 255, "%02x ", rSeq[i]);
            tmpStr += sBuffer;
        }
        else
            tmpStr += "   ";

        if (i % 8 == 7)
            tmpStr += " ";
    }

    {
        for (sal_uInt32 i = 0; i < nStep; i++)
        {
            if (i < nCount)
            {
                unsigned char c =
                    static_cast<unsigned char>(rSeq[i]);

                if (c=='&')
                    tmpStr += "&";
                else if (c=='<')
                    tmpStr += "<";
                else if (c=='>')
                    tmpStr += ">";
                else if (c < 128 && isprint(c))
                    tmpStr += c;
                else
                    tmpStr += ".";
            }

        }
    }

    tmpStr += "</line>";

    o.addItem(tmpStr);
}

}

#endif // INCLUDED_SUB_SEQUENCE_HXX
<commit_msg>INTEGRATION: CWS changefileheader (1.3.10); FILE MERGED 2008/04/01 16:06:41 thb 1.3.10.2: #i85898# Stripping all external header guards 2008/03/28 15:52:57 rt 1.3.10.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: SubSequence.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef INCLUDED_SUB_SEQUENCE_HXX
#define INCLUDED_SUB_SEQUENCE_HXX

#include <com/sun/star/uno/Sequence.hxx>

#include <boost/shared_ptr.hpp>
#include <iostream>
#include <ctype.h>
#include "exceptions.hxx"
#include <WriterFilterDllApi.hxx>
#include <resourcemodel/OutputWithDepth.hxx>

namespace writerfilter {
using namespace ::std;

template <class T>
class SubSequence;

template <typename T>
void dumpLine(OutputWithDepth<string> & o, SubSequence<T> & rSeq,
              sal_uInt32 nOffset, sal_uInt32 nStep);

template <class T>
class WRITERFILTER_DLLPUBLIC SubSequence
{
    typedef boost::shared_ptr<com::sun::star::uno::Sequence<T> >
    SequencePointer;

    SequencePointer mpSequence;
    sal_uInt32 mnOffset;
    sal_uInt32 mnCount;

public:
    typedef boost::shared_ptr<SubSequence> Pointer_t;

    SubSequence() : mpSequence(new ::com::sun::star::uno::Sequence<T>()),
                    mnOffset(0), mnCount(0)
    {
    }

    SubSequence(SequencePointer pSequence, sal_uInt32 nOffset_,
                sal_uInt32 nCount_)
        : mpSequence(pSequence), mnOffset(nOffset_), mnCount(nCount_)
    {
    }

    SubSequence(SequencePointer pSequence)
        : mpSequence(pSequence), mnOffset(0), mnCount(pSequence->getLength())
    {
    }

    SubSequence(const SubSequence & rSubSequence, sal_uInt32 nOffset_,
                sal_uInt32 nCount_)
        : mpSequence(rSubSequence.mpSequence),
          mnOffset(rSubSequence.mnOffset + nOffset_),
          mnCount(nCount_)
    {
    }

    SubSequence(const T * pStart, sal_uInt32 nCount_)
        : mpSequence(new com::sun::star::uno::Sequence<T>(pStart, nCount_)),
          mnOffset(0), mnCount(nCount_)
    {
    }

    SubSequence(sal_Int32 nCount_)
        : mpSequence(new com::sun::star::uno::Sequence<T>(nCount_)), mnOffset(0),
          mnCount(nCount_)
    {
    }

    ::com::sun::star::uno::Sequence<T> & getSequence()
    {
        return *mpSequence;
    }

    const ::com::sun::star::uno::Sequence<T> & getSequence() const
    {
        return *mpSequence;
    }

    void reset() {
        mnOffset = 0;
        mnCount = mpSequence->getLength();
    }

    sal_uInt32 getOffset() const { return mnOffset; }
    sal_uInt32 getCount() const { return mnCount; }

    const T & operator[] (sal_uInt32 nIndex) const
    {
        if (mnOffset + nIndex >=
            sal::static_int_cast<sal_uInt32>(mpSequence->getLength()))
            throw ExceptionOutOfBounds("SubSequence::operator[]");

        return (*mpSequence)[mnOffset + nIndex];
    }

    void dump(ostream & o) const
    {
        {
            char sBuffer[256];

            snprintf(sBuffer, sizeof(sBuffer),
                     "<sequence id='%p' offset='%lx' count='%lx'>",
                     mpSequence.get(), mnOffset, mnCount);
            o << sBuffer << endl;
        }

        sal_uInt32 n = 0;
        sal_uInt32 nStep = 16;

        while (n < getCount())
        {
            char sBuffer[256];

            o << "<line>";

            snprintf(sBuffer, 255, "%08lx: ", n);

            o << sBuffer;

            for (sal_uInt32 i = 0; i < nStep; i++)
            {
                if (n + i < getCount())
                {
                    snprintf(sBuffer, 255, "%02x ", operator[](n + i));
                    o << sBuffer;
                }
                else
                    o << "   ";

                if (i % 8 == 7)
                    o << " ";
            }

            {
                for (sal_uInt32 i = 0; i < nStep; i++)
                {
                    if (n + i < getCount())
                    {
                        unsigned char c =
                            static_cast<unsigned char>(operator[](n + i));

                        if (c=='&')
                            o << "&";
                        else if (c=='<')
                            o << "<";
                        else if (c=='>')
                            o << ">";
                        else if (c < 128 && isprint(c))
                            o << c;
                        else
                            o << ".";
                    }

                }
            }

            o << "</line>" << endl;

            n += nStep;
        }

        o << "</sequence>" << endl;
    }

    void dump(OutputWithDepth<string> & o)
    {
        {
            char sBuffer[256];

            snprintf(sBuffer, sizeof(sBuffer),
                     "<sequence id='%p' offset='%" SAL_PRIxUINT32 "' count='%" SAL_PRIxUINT32 "'>",
                     mpSequence.get(), mnOffset, mnCount);
            o.addItem(sBuffer);
        }

        sal_uInt32 n = 0;
        sal_uInt32 nStep = 16;

        try
        {
            sal_uInt32 nCount = getCount();
            while (n < nCount)
            {
                sal_uInt32 nBytes = nCount - n;

                if (nBytes > nStep)
                    nBytes = nStep;

                SubSequence<T> aSeq(*this, n, nBytes);
                dumpLine(o, aSeq, n, nStep);

                n += nBytes;
            }
        }
        catch (...)
        {
            o.addItem("<exception/>");
        }

        o.addItem("</sequence>");
    }

    string toString() const
    {
        sal_uInt32 n = 0;
        sal_uInt32 nStep = 16;

        string sResult;

        while (n < getCount())
        {
            char sBuffer[256];

            snprintf(sBuffer, 255, "<line>%08" SAL_PRIxUINT32 ": ", n);

            sResult += sBuffer;

            for (sal_uInt32 i = 0; i < nStep; i++)
            {
                if (n + i < getCount())
                {
                    snprintf(sBuffer, 255, "%02x ", operator[](n + i));
                    sResult += sBuffer;
                }
                else
                    sResult += "   ";

                if (i % 8 == 7)
                    sResult += " ";
            }

            {
                for (sal_uInt32 i = 0; i < nStep; i++)
                {
                    if (n + i < getCount())
                    {
                        unsigned char c =
                            static_cast<unsigned char>(operator[](n + i));

                        if (c=='&')
                            sResult += "&";
                        else if (c=='<')
                            sResult += "<";
                        else if (c=='>')
                            sResult += ">";
                        else if (c < 128 && isprint(c))
                            sResult += c;
                        else
                            sResult += ".";
                    }
                }
            }

            sResult += "</line>\n";

            n += nStep;
        }

        return sResult;
    }
};

template <typename T>
void dumpLine(OutputWithDepth<string> & o, SubSequence<T> & rSeq,
              sal_uInt32 nOffset, sal_uInt32 nStep)
{
    sal_uInt32 nCount = rSeq.getCount();
    char sBuffer[256];

    string tmpStr = "<line>";

    snprintf(sBuffer, 255, "%08" SAL_PRIxUINT32 ": ", nOffset);

    tmpStr += sBuffer;

    for (sal_uInt32 i = 0; i < nStep; i++)
    {
        if (i < nCount)
        {
            snprintf(sBuffer, 255, "%02x ", rSeq[i]);
            tmpStr += sBuffer;
        }
        else
            tmpStr += "   ";

        if (i % 8 == 7)
            tmpStr += " ";
    }

    {
        for (sal_uInt32 i = 0; i < nStep; i++)
        {
            if (i < nCount)
            {
                unsigned char c =
                    static_cast<unsigned char>(rSeq[i]);

                if (c=='&')
                    tmpStr += "&";
                else if (c=='<')
                    tmpStr += "<";
                else if (c=='>')
                    tmpStr += ">";
                else if (c < 128 && isprint(c))
                    tmpStr += c;
                else
                    tmpStr += ".";
            }

        }
    }

    tmpStr += "</line>";

    o.addItem(tmpStr);
}

}

#endif // INCLUDED_SUB_SEQUENCE_HXX
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2010 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2007-2008 The Florida State University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Stephen Hines
 */
#ifndef __ARCH_ARM_INSTS_PREDINST_HH__
#define __ARCH_ARM_INSTS_PREDINST_HH__

#include "arch/arm/insts/static_inst.hh"
#include "base/trace.hh"

namespace ArmISA
{
static inline uint32_t
rotate_imm(uint32_t immValue, int rotateValue)
{
    return ((immValue >> (rotateValue & 31)) |
            (immValue << (32 - (rotateValue & 31))));
}

static inline uint32_t
modified_imm(uint8_t ctrlImm, uint8_t dataImm)
{
    uint32_t bigData = dataImm;
    uint32_t bigCtrl = ctrlImm;
    if (bigCtrl < 4) {
        switch (bigCtrl) {
          case 0:
            return bigData;
          case 1:
            return bigData | (bigData << 16);
          case 2:
            return (bigData << 8) | (bigData << 24);
          case 3:
            return (bigData << 0) | (bigData << 8) |
                   (bigData << 16) | (bigData << 24);
        }
    }
    bigCtrl = (bigCtrl << 1) | ((bigData >> 7) & 0x1);
    bigData |= (1 << 7);
    return bigData << (32 - bigCtrl);
}

static inline uint64_t
simd_modified_imm(bool op, uint8_t cmode, uint8_t data)
{
    uint64_t bigData = data;
    switch (cmode) {
      case 0x0:
      case 0x1:
        bigData = (bigData << 0) | (bigData << 32);
        break;
      case 0x2:
      case 0x3:
        bigData = (bigData << 8) | (bigData << 40);
        break;
      case 0x4:
      case 0x5:
        bigData = (bigData << 16) | (bigData << 48);
        break;
      case 0x6:
      case 0x7:
        bigData = (bigData << 24) | (bigData << 56);
        break;
      case 0x8:
      case 0x9:
        bigData = (bigData << 0) | (bigData << 16) |
                  (bigData << 32) | (bigData << 48);
        break;
      case 0xa:
      case 0xb:
        bigData = (bigData << 8) | (bigData << 24) |
                  (bigData << 40) | (bigData << 56);
        break;
      case 0xc:
        bigData = (0xffULL << 0) | (bigData << 8) |
                  (0xffULL << 32) | (bigData << 40);
        break;
      case 0xd:
        bigData = (0xffffULL << 0) | (bigData << 16) |
                  (0xffffULL << 32) | (bigData << 48);
        break;
      case 0xe:
        if (op) {
            bigData = (bigData << 0)  | (bigData << 8)  |
                      (bigData << 16) | (bigData << 24) |
                      (bigData << 32) | (bigData << 40) |
                      (bigData << 48) | (bigData << 56);
        } else {
            bigData = 0;
            for (int i = 7; i >= 0; i--) {
                if (bits(data, i)) {
                    bigData |= (0xFF << (i * 8));
                }
            }
        }
      case 0xf:
        if (!op) {
            uint64_t bVal = bits(bigData, 6) ? (0x1F) : (0x20);
            bigData = (bits(bigData, 5, 0) << 19) |
                      (bVal << 25) | (bits(bigData, 7) << 31);
            bigData |= (bigData << 32);
        }
        // Fall through
      default:
        panic("Illegal modified SIMD immediate parameters.\n");
    }
    return bigData;
}

/**
 * Base class for predicated integer operations.
 */
class PredOp : public ArmStaticInst
{
  protected:

    ConditionCode condCode;

    /// Constructor
    PredOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
           ArmStaticInst(mnem, _machInst, __opClass),
           condCode((ConditionCode)(unsigned)machInst.condCode)
    {
    }
};

/**
 * Base class for predicated immediate operations.
 */
class PredImmOp : public PredOp
{
    protected:

    uint32_t imm;
    uint32_t rotated_imm;
    uint32_t rotated_carry;
    uint32_t rotate;

    /// Constructor
    PredImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
              PredOp(mnem, _machInst, __opClass),
              imm(machInst.imm), rotated_imm(0), rotated_carry(0),
              rotate(machInst.rotate << 1)
    {
        rotated_imm = rotate_imm(imm, rotate);
        if (rotate != 0)
            rotated_carry = bits(rotated_imm, 31);
    }

    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};

/**
 * Base class for predicated integer operations.
 */
class PredIntOp : public PredOp
{
    protected:

    uint32_t shift_size;
    uint32_t shift;

    /// Constructor
    PredIntOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
              PredOp(mnem, _machInst, __opClass),
              shift_size(machInst.shiftSize), shift(machInst.shift)
    {
    }

    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};

class DataImmOp : public PredOp
{
  protected:
    IntRegIndex dest, op1;
    uint32_t imm;
    // Whether the carry flag should be modified if that's an option for
    // this instruction.
    bool rotC;

    DataImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
              IntRegIndex _dest, IntRegIndex _op1, uint32_t _imm, bool _rotC) :
        PredOp(mnem, _machInst, __opClass),
        dest(_dest), op1(_op1), imm(_imm), rotC(_rotC)
    {}

    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};

class DataRegOp : public PredOp
{
  protected:
    IntRegIndex dest, op1, op2;
    int32_t shiftAmt;
    ArmShiftType shiftType;

    DataRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
              IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
              int32_t _shiftAmt, ArmShiftType _shiftType) :
        PredOp(mnem, _machInst, __opClass),
        dest(_dest), op1(_op1), op2(_op2),
        shiftAmt(_shiftAmt), shiftType(_shiftType)
    {}

    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};

class DataRegRegOp : public PredOp
{
  protected:
    IntRegIndex dest, op1, op2, shift;
    ArmShiftType shiftType;

    DataRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
                 IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
                 IntRegIndex _shift, ArmShiftType _shiftType) :
        PredOp(mnem, _machInst, __opClass),
        dest(_dest), op1(_op1), op2(_op2), shift(_shift),
        shiftType(_shiftType)
    {}

    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};

/**
 * Base class for predicated macro-operations.
 */
class PredMacroOp : public PredOp
{
    protected:

    uint32_t numMicroops;
    StaticInstPtr * microOps;

    /// Constructor
    PredMacroOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
                PredOp(mnem, _machInst, __opClass),
                numMicroops(0)
    {
        // We rely on the subclasses of this object to handle the
        // initialization of the micro-operations, since they are
        // all of variable length
        flags[IsMacroop] = true;
    }

    ~PredMacroOp()
    {
        if (numMicroops)
            delete [] microOps;
    }

    StaticInstPtr
    fetchMicroop(MicroPC microPC)
    {
        assert(microPC < numMicroops);
        return microOps[microPC];
    }

    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};

/**
 * Base class for predicated micro-operations.
 */
class PredMicroop : public PredOp
{
    /// Constructor
    PredMicroop(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
                PredOp(mnem, _machInst, __opClass)
    {
        flags[IsMicroop] = true;
    }
};
}

#endif //__ARCH_ARM_INSTS_PREDINST_HH__
<commit_msg>ARM: Add a function to decode VFP modified immediate constants.<commit_after>/*
 * Copyright (c) 2010 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2007-2008 The Florida State University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Stephen Hines
 */
#ifndef __ARCH_ARM_INSTS_PREDINST_HH__
#define __ARCH_ARM_INSTS_PREDINST_HH__

#include "arch/arm/insts/static_inst.hh"
#include "base/trace.hh"

namespace ArmISA
{
static inline uint32_t
rotate_imm(uint32_t immValue, int rotateValue)
{
    return ((immValue >> (rotateValue & 31)) |
            (immValue << (32 - (rotateValue & 31))));
}

static inline uint32_t
modified_imm(uint8_t ctrlImm, uint8_t dataImm)
{
    uint32_t bigData = dataImm;
    uint32_t bigCtrl = ctrlImm;
    if (bigCtrl < 4) {
        switch (bigCtrl) {
          case 0:
            return bigData;
          case 1:
            return bigData | (bigData << 16);
          case 2:
            return (bigData << 8) | (bigData << 24);
          case 3:
            return (bigData << 0) | (bigData << 8) |
                   (bigData << 16) | (bigData << 24);
        }
    }
    bigCtrl = (bigCtrl << 1) | ((bigData >> 7) & 0x1);
    bigData |= (1 << 7);
    return bigData << (32 - bigCtrl);
}

static inline uint64_t
simd_modified_imm(bool op, uint8_t cmode, uint8_t data)
{
    uint64_t bigData = data;
    switch (cmode) {
      case 0x0:
      case 0x1:
        bigData = (bigData << 0) | (bigData << 32);
        break;
      case 0x2:
      case 0x3:
        bigData = (bigData << 8) | (bigData << 40);
        break;
      case 0x4:
      case 0x5:
        bigData = (bigData << 16) | (bigData << 48);
        break;
      case 0x6:
      case 0x7:
        bigData = (bigData << 24) | (bigData << 56);
        break;
      case 0x8:
      case 0x9:
        bigData = (bigData << 0) | (bigData << 16) |
                  (bigData << 32) | (bigData << 48);
        break;
      case 0xa:
      case 0xb:
        bigData = (bigData << 8) | (bigData << 24) |
                  (bigData << 40) | (bigData << 56);
        break;
      case 0xc:
        bigData = (0xffULL << 0) | (bigData << 8) |
                  (0xffULL << 32) | (bigData << 40);
        break;
      case 0xd:
        bigData = (0xffffULL << 0) | (bigData << 16) |
                  (0xffffULL << 32) | (bigData << 48);
        break;
      case 0xe:
        if (op) {
            bigData = (bigData << 0)  | (bigData << 8)  |
                      (bigData << 16) | (bigData << 24) |
                      (bigData << 32) | (bigData << 40) |
                      (bigData << 48) | (bigData << 56);
        } else {
            bigData = 0;
            for (int i = 7; i >= 0; i--) {
                if (bits(data, i)) {
                    bigData |= (0xFF << (i * 8));
                }
            }
        }
      case 0xf:
        if (!op) {
            uint64_t bVal = bits(bigData, 6) ? (0x1F) : (0x20);
            bigData = (bits(bigData, 5, 0) << 19) |
                      (bVal << 25) | (bits(bigData, 7) << 31);
            bigData |= (bigData << 32);
        }
        // Fall through
      default:
        panic("Illegal modified SIMD immediate parameters.\n");
    }
    return bigData;
}

static inline uint64_t
vfp_modified_imm(uint8_t data, bool wide)
{
    uint64_t bigData = data;
    uint64_t repData;
    if (wide) {
        repData = bits(data, 6) ? 0xFF : 0;
        bigData = (bits(bigData, 5, 0) << 48) |
                  (repData << 54) | (bits(~bigData, 6) << 62) |
                  (bits(bigData, 7) << 63);
    } else {
        repData = bits(data, 6) ? 0x1F : 0;
        bigData = (bits(bigData, 5, 0) << 19) |
                  (repData << 25) | (bits(~bigData, 6) << 30) |
                  (bits(bigData, 7) << 31);
    }
    return bigData;
}

/**
 * Base class for predicated integer operations.
 */
class PredOp : public ArmStaticInst
{
  protected:

    ConditionCode condCode;

    /// Constructor
    PredOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
           ArmStaticInst(mnem, _machInst, __opClass),
           condCode((ConditionCode)(unsigned)machInst.condCode)
    {
    }
};

/**
 * Base class for predicated immediate operations.
 */
class PredImmOp : public PredOp
{
    protected:

    uint32_t imm;
    uint32_t rotated_imm;
    uint32_t rotated_carry;
    uint32_t rotate;

    /// Constructor
    PredImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
              PredOp(mnem, _machInst, __opClass),
              imm(machInst.imm), rotated_imm(0), rotated_carry(0),
              rotate(machInst.rotate << 1)
    {
        rotated_imm = rotate_imm(imm, rotate);
        if (rotate != 0)
            rotated_carry = bits(rotated_imm, 31);
    }

    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};

/**
 * Base class for predicated integer operations.
 */
class PredIntOp : public PredOp
{
    protected:

    uint32_t shift_size;
    uint32_t shift;

    /// Constructor
    PredIntOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
              PredOp(mnem, _machInst, __opClass),
              shift_size(machInst.shiftSize), shift(machInst.shift)
    {
    }

    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};

class DataImmOp : public PredOp
{
  protected:
    IntRegIndex dest, op1;
    uint32_t imm;
    // Whether the carry flag should be modified if that's an option for
    // this instruction.
    bool rotC;

    DataImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
              IntRegIndex _dest, IntRegIndex _op1, uint32_t _imm, bool _rotC) :
        PredOp(mnem, _machInst, __opClass),
        dest(_dest), op1(_op1), imm(_imm), rotC(_rotC)
    {}

    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};

class DataRegOp : public PredOp
{
  protected:
    IntRegIndex dest, op1, op2;
    int32_t shiftAmt;
    ArmShiftType shiftType;

    DataRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
              IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
              int32_t _shiftAmt, ArmShiftType _shiftType) :
        PredOp(mnem, _machInst, __opClass),
        dest(_dest), op1(_op1), op2(_op2),
        shiftAmt(_shiftAmt), shiftType(_shiftType)
    {}

    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};

class DataRegRegOp : public PredOp
{
  protected:
    IntRegIndex dest, op1, op2, shift;
    ArmShiftType shiftType;

    DataRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
                 IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
                 IntRegIndex _shift, ArmShiftType _shiftType) :
        PredOp(mnem, _machInst, __opClass),
        dest(_dest), op1(_op1), op2(_op2), shift(_shift),
        shiftType(_shiftType)
    {}

    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};

/**
 * Base class for predicated macro-operations.
 */
class PredMacroOp : public PredOp
{
    protected:

    uint32_t numMicroops;
    StaticInstPtr * microOps;

    /// Constructor
    PredMacroOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
                PredOp(mnem, _machInst, __opClass),
                numMicroops(0)
    {
        // We rely on the subclasses of this object to handle the
        // initialization of the micro-operations, since they are
        // all of variable length
        flags[IsMacroop] = true;
    }

    ~PredMacroOp()
    {
        if (numMicroops)
            delete [] microOps;
    }

    StaticInstPtr
    fetchMicroop(MicroPC microPC)
    {
        assert(microPC < numMicroops);
        return microOps[microPC];
    }

    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};

/**
 * Base class for predicated micro-operations.
 */
class PredMicroop : public PredOp
{
    /// Constructor
    PredMicroop(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
                PredOp(mnem, _machInst, __opClass)
    {
        flags[IsMicroop] = true;
    }
};
}

#endif //__ARCH_ARM_INSTS_PREDINST_HH__
<|endoftext|>


<commit_before>/*
    This file is part of KMail, the KDE mail client.
    Copyright (c) 2004 Till Adam <adam@kde.org>

    KMail is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    KMail is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/
#include "headerlistquicksearch.h"

#include <qapplication.h>
#include <qlabel.h>
#include <qcombobox.h>
#include <qtimer.h>

#include <kaction.h>
#include <klistview.h>
#include <klocale.h>

#include "kmheaders.h"
#include "kmsearchpattern.h"

namespace KMail {

HeaderListQuickSearch::HeaderListQuickSearch( QWidget *parent,
                                              KListView *listView,
                                              KActionCollection *actionCollection,
                                              const char *name )
  : KListViewSearchLine(parent, listView, name), mStatusCombo(0), mStatus(0)
{
  KAction *resetQuickSearch = new KAction( i18n( "Reset Quick Search" ),
                                           QApplication::reverseLayout()
                                           ? "clear_left"
                                           : "locationbar_erase",
                                           0, this,
                                           SLOT( reset() ),
                                           actionCollection,
                                           "reset_quicksearch" );
  resetQuickSearch->plug( parent );
  resetQuickSearch->setWhatsThis( i18n( "Reset Quick Search\n"
                                        "Resets the quick search so that "
                                        "all messages are shown again." ) );

  QLabel *label = new QLabel( i18n("Stat&us:"), parent, "kde toolbar widget" );

  mStatusCombo = new QComboBox( parent, "quick search status combo box" );
  mStatusCombo->insertItem( i18n("Any Status") );
  for ( int i = 0; i < KMail::StatusValueCount; i++ )
    mStatusCombo->insertItem( i18n( KMail::StatusValues[i] ) );
  mStatusCombo->setCurrentItem( KMail::StatusValueCount );
  connect( mStatusCombo, SIGNAL ( activated( int ) ),
           this, SLOT( slotStatusChanged( int ) ) );

  label->setBuddy( mStatusCombo );
}

HeaderListQuickSearch::~HeaderListQuickSearch()
{
}

bool HeaderListQuickSearch::itemMatches(const QListViewItem *item, const QString &s) const
{
  if ( mStatus != 0 ) {
    KMHeaders *headers = static_cast<KMHeaders*>( item->listView() );
    const KMMsgBase *msg = headers->getMsgBaseForItem( item );
    if ( ! ( msg->status() & mStatus ) )
      return false;
  }
  return KListViewSearchLine::itemMatches(item, s);
}

//-----------------------------------------------------------------------------
void HeaderListQuickSearch::reset()
{
  clear();
  mStatusCombo->setCurrentItem( 0 );
  slotStatusChanged( 0 );
}

void HeaderListQuickSearch::slotStatusChanged( int index )
{
  if ( index == 0 )
    mStatus = 0;
  else
    mStatus =
      KMSearchRuleStatus::statusFromEnglishName( KMail::StatusValues[index-1] );
  updateSearch();
}

} // namespace KMail

#include "headerlistquicksearch.moc"
<commit_msg>Fix crash when we have two account: -> imap account -> pop account<commit_after>/*
    This file is part of KMail, the KDE mail client.
    Copyright (c) 2004 Till Adam <adam@kde.org>

    KMail is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    KMail is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/
#include "headerlistquicksearch.h"

#include <qapplication.h>
#include <qlabel.h>
#include <qcombobox.h>
#include <qtimer.h>

#include <kaction.h>
#include <klistview.h>
#include <klocale.h>

#include "kmheaders.h"
#include "kmsearchpattern.h"

namespace KMail {

HeaderListQuickSearch::HeaderListQuickSearch( QWidget *parent,
                                              KListView *listView,
                                              KActionCollection *actionCollection,
                                              const char *name )
  : KListViewSearchLine(parent, listView, name), mStatusCombo(0), mStatus(0)
{
  KAction *resetQuickSearch = new KAction( i18n( "Reset Quick Search" ),
                                           QApplication::reverseLayout()
                                           ? "clear_left"
                                           : "locationbar_erase",
                                           0, this,
                                           SLOT( reset() ),
                                           actionCollection,
                                           "reset_quicksearch" );
  resetQuickSearch->plug( parent );
  resetQuickSearch->setWhatsThis( i18n( "Reset Quick Search\n"
                                        "Resets the quick search so that "
                                        "all messages are shown again." ) );

  QLabel *label = new QLabel( i18n("Stat&us:"), parent, "kde toolbar widget" );

  mStatusCombo = new QComboBox( parent, "quick search status combo box" );
  mStatusCombo->insertItem( i18n("Any Status") );
  for ( int i = 0; i < KMail::StatusValueCount; i++ )
    mStatusCombo->insertItem( i18n( KMail::StatusValues[i] ) );
  mStatusCombo->setCurrentItem( KMail::StatusValueCount );
  connect( mStatusCombo, SIGNAL ( activated( int ) ),
           this, SLOT( slotStatusChanged( int ) ) );

  label->setBuddy( mStatusCombo );
}

HeaderListQuickSearch::~HeaderListQuickSearch()
{
}

bool HeaderListQuickSearch::itemMatches(const QListViewItem *item, const QString &s) const
{
  if ( mStatus != 0 ) {
    KMHeaders *headers = static_cast<KMHeaders*>( item->listView() );
    const KMMsgBase *msg = headers->getMsgBaseForItem( item );
    if ( !msg || ! ( msg->status() & mStatus ) )
      return false;
  }
  return KListViewSearchLine::itemMatches(item, s);
}

//-----------------------------------------------------------------------------
void HeaderListQuickSearch::reset()
{
  clear();
  mStatusCombo->setCurrentItem( 0 );
  slotStatusChanged( 0 );
}

void HeaderListQuickSearch::slotStatusChanged( int index )
{
  if ( index == 0 )
    mStatus = 0;
  else
    mStatus =
      KMSearchRuleStatus::statusFromEnglishName( KMail::StatusValues[index-1] );
  updateSearch();
}

} // namespace KMail

#include "headerlistquicksearch.moc"
<|endoftext|>