summaryrefslogtreecommitdiff
path: root/SDL_Core/src/components/transport_manager/src/usb
diff options
context:
space:
mode:
Diffstat (limited to 'SDL_Core/src/components/transport_manager/src/usb')
-rw-r--r--SDL_Core/src/components/transport_manager/src/usb/libusb/platform_usb_device.cc79
-rw-r--r--SDL_Core/src/components/transport_manager/src/usb/libusb/usb_connection.cc313
-rw-r--r--SDL_Core/src/components/transport_manager/src/usb/libusb/usb_handler.cc418
-rw-r--r--SDL_Core/src/components/transport_manager/src/usb/qnx/platform_usb_device.cc75
-rw-r--r--SDL_Core/src/components/transport_manager/src/usb/qnx/usb_connection.cc399
-rw-r--r--SDL_Core/src/components/transport_manager/src/usb/qnx/usb_handler.cc296
-rw-r--r--SDL_Core/src/components/transport_manager/src/usb/usb_aoa_adapter.cc80
-rw-r--r--SDL_Core/src/components/transport_manager/src/usb/usb_connection_factory.cc91
-rw-r--r--SDL_Core/src/components/transport_manager/src/usb/usb_device_scanner.cc213
9 files changed, 1964 insertions, 0 deletions
diff --git a/SDL_Core/src/components/transport_manager/src/usb/libusb/platform_usb_device.cc b/SDL_Core/src/components/transport_manager/src/usb/libusb/platform_usb_device.cc
new file mode 100644
index 000000000..2110ac3fc
--- /dev/null
+++ b/SDL_Core/src/components/transport_manager/src/usb/libusb/platform_usb_device.cc
@@ -0,0 +1,79 @@
+/**
+ * \file platform_usb_device.cc
+ * \brief Libusb PlatformUsbDevice class source file.
+ *
+ * Copyright (c) 2013, Ford Motor Company
+ * 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 Ford Motor Company 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 HOLDER 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.
+ */
+
+#include "transport_manager/usb/libusb/platform_usb_device.h"
+#include "transport_manager/transport_adapter/transport_adapter_impl.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+PlatformUsbDevice::PlatformUsbDevice(
+ uint8_t bus_number, uint8_t address,
+ const libusb_device_descriptor& device_descriptor,
+ libusb_device* device_libusb, libusb_device_handle* device_handle_libusb)
+ : bus_number_(bus_number),
+ address_(address),
+ vendor_id_(device_descriptor.idVendor),
+ product_id_(device_descriptor.idProduct),
+ device_descriptor_(device_descriptor),
+ libusb_device_handle_(device_handle_libusb),
+ libusb_device_(device_libusb) {}
+
+std::string PlatformUsbDevice::GetDescString(uint8_t index) const {
+ unsigned char buf[128];
+ const int libusb_ret = libusb_get_string_descriptor_ascii(
+ libusb_device_handle_, index, buf, sizeof(buf));
+ if (libusb_ret < 0) {
+ LOG4CXX_INFO(logger_, "Failed to get USB string descriptor: "
+ << libusb_error_name(libusb_ret));
+ return "";
+ }
+ return std::string(reinterpret_cast<char*>(buf));
+}
+
+std::string PlatformUsbDevice::GetManufacturer() const {
+ return GetDescString(device_descriptor_.iManufacturer);
+}
+
+std::string PlatformUsbDevice::GetProductName() const {
+ return GetDescString(device_descriptor_.iProduct);
+}
+
+std::string PlatformUsbDevice::GetSerialNumber() const {
+ return GetDescString(device_descriptor_.iSerialNumber);
+}
+
+} // namespace
+} // namespace
diff --git a/SDL_Core/src/components/transport_manager/src/usb/libusb/usb_connection.cc b/SDL_Core/src/components/transport_manager/src/usb/libusb/usb_connection.cc
new file mode 100644
index 000000000..00c792de8
--- /dev/null
+++ b/SDL_Core/src/components/transport_manager/src/usb/libusb/usb_connection.cc
@@ -0,0 +1,313 @@
+/**
+ * \file usb_connection.cc
+ * \brief UsbConnection class source file.
+ *
+ * Copyright (c) 2013, Ford Motor Company
+ * 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 Ford Motor Company 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 HOLDER 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.
+ */
+
+#include <iomanip>
+
+#include <libusb/libusb.h>
+
+#include "transport_manager/usb/libusb/usb_connection.h"
+#include "transport_manager/transport_adapter/transport_adapter_impl.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+UsbConnection::UsbConnection(const DeviceUID& device_uid,
+ const ApplicationHandle& app_handle,
+ TransportAdapterController* controller,
+ const UsbHandlerSptr& usb_handler,
+ PlatformUsbDevice* device)
+ : device_uid_(device_uid),
+ app_handle_(app_handle),
+ controller_(controller),
+ usb_handler_(usb_handler),
+ libusb_device_(device->GetLibusbDevice()),
+ device_handle_(device->GetLibusbHandle()),
+ in_endpoint_(0),
+ in_endpoint_max_packet_size_(0),
+ out_endpoint_(0),
+ out_endpoint_max_packet_size_(0),
+ in_buffer_(0),
+ in_transfer_(0),
+ out_transfer_(0),
+ out_messages_(),
+ current_out_message_(),
+ out_messages_mutex_(),
+ bytes_sent_(0),
+ disconnecting_(false),
+ waiting_in_transfer_cancel_(false),
+ waiting_out_transfer_cancel_(false) {
+ pthread_mutex_init(&out_messages_mutex_, 0);
+}
+
+UsbConnection::~UsbConnection() {
+ Finalise();
+ if (in_transfer_) {
+ libusb_free_transfer(in_transfer_);
+ }
+ if (in_buffer_) {
+ delete[] in_buffer_;
+ }
+ pthread_mutex_destroy(&out_messages_mutex_);
+}
+
+void InTransferCallback(libusb_transfer* transfer) {
+ static_cast<UsbConnection*>(transfer->user_data)->OnInTransfer(transfer);
+}
+
+void OutTransferCallback(libusb_transfer* transfer) {
+ static_cast<UsbConnection*>(transfer->user_data)->OnOutTransfer(transfer);
+}
+
+bool UsbConnection::PostInTransfer() {
+ libusb_fill_bulk_transfer(in_transfer_, device_handle_, in_endpoint_,
+ in_buffer_, in_endpoint_max_packet_size_,
+ InTransferCallback, this, 0);
+ const int libusb_ret = libusb_submit_transfer(in_transfer_);
+ if (LIBUSB_SUCCESS != libusb_ret) {
+ LOG4CXX_ERROR(logger_, "libusb_submit_transfer failed: "
+ << libusb_error_name(libusb_ret));
+ return false;
+ }
+ return true;
+}
+
+void UsbConnection::OnInTransfer(libusb_transfer* transfer) {
+ if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
+ if (logger_->isTraceEnabled()) {
+ std::ostringstream hexdata;
+ for (int i = 0; i < transfer->actual_length; ++i) {
+ hexdata << " " << std::hex << std::setw(2) << std::setfill('0')
+ << (int)transfer->buffer[i];
+ }
+ LOG4CXX_TRACE(logger_, "USB incoming transfer, size:"
+ << transfer->actual_length
+ << ", data:" << hexdata.str());
+ }
+ RawMessageSptr data(new protocol_handler::RawMessage(
+ 0, 0, in_buffer_, transfer->actual_length));
+ controller_->DataReceiveDone(device_uid_, app_handle_, data);
+ } else {
+ LOG4CXX_ERROR(logger_, "USB transfer failed: " << transfer->status);
+ controller_->DataReceiveFailed(device_uid_, app_handle_,
+ DataReceiveError());
+ }
+ if (disconnecting_) {
+ waiting_in_transfer_cancel_ = false;
+ } else {
+ if (!PostInTransfer()) {
+ controller_->ConnectionAborted(device_uid_, app_handle_,
+ CommunicationError());
+ Disconnect();
+ }
+ }
+}
+
+void UsbConnection::PopOutMessage() {
+ bytes_sent_ = 0;
+ if (out_messages_.empty()) {
+ current_out_message_.reset();
+ } else {
+ current_out_message_ = out_messages_.front();
+ out_messages_.pop_front();
+ PostOutTransfer();
+ }
+}
+
+bool UsbConnection::PostOutTransfer() {
+ out_transfer_ = libusb_alloc_transfer(0);
+ if (0 == out_transfer_) {
+ LOG4CXX_ERROR(logger_, "libusb_alloc_transfer failed");
+ return false;
+ }
+ libusb_fill_bulk_transfer(out_transfer_, device_handle_, out_endpoint_,
+ current_out_message_->data() + bytes_sent_,
+ current_out_message_->data_size() - bytes_sent_,
+ OutTransferCallback, this, 0);
+ const int libusb_ret = libusb_submit_transfer(out_transfer_);
+ if (LIBUSB_SUCCESS != libusb_ret) {
+ LOG4CXX_ERROR(logger_, "libusb_submit_transfer failed: "
+ << libusb_error_name(libusb_ret));
+ controller_->ConnectionAborted(device_uid_, app_handle_,
+ CommunicationError());
+ Disconnect();
+ return false;
+ }
+ return true;
+}
+
+void UsbConnection::OnOutTransfer(libusb_transfer* transfer) {
+ pthread_mutex_lock(&out_messages_mutex_);
+ if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
+ bytes_sent_ += transfer->actual_length;
+ if (bytes_sent_ == current_out_message_->data_size()) {
+ LOG4CXX_INFO(logger_, "USB out transfer, data sent: "
+ << current_out_message_.get());
+ controller_->DataSendDone(device_uid_, app_handle_, current_out_message_);
+ PopOutMessage();
+ }
+ } else {
+ LOG4CXX_ERROR(logger_, "USB transfer failed: " << transfer->status);
+ controller_->DataSendFailed(device_uid_, app_handle_, current_out_message_,
+ DataSendError());
+ PopOutMessage();
+ }
+ libusb_free_transfer(transfer);
+ out_transfer_ = 0;
+ pthread_mutex_unlock(&out_messages_mutex_);
+ waiting_out_transfer_cancel_ = false;
+}
+
+TransportAdapter::Error UsbConnection::SendData(RawMessageSptr message) {
+ if (disconnecting_) {
+ return TransportAdapter::BAD_STATE;
+ }
+ pthread_mutex_lock(&out_messages_mutex_);
+ if (current_out_message_.valid()) {
+ out_messages_.push_back(message);
+ } else {
+ current_out_message_ = message;
+ if (!PostOutTransfer()) {
+ controller_->DataSendFailed(device_uid_, app_handle_, message,
+ DataSendError());
+ }
+ }
+ pthread_mutex_unlock(&out_messages_mutex_);
+ return TransportAdapter::OK;
+}
+
+void UsbConnection::Finalise() {
+ LOG4CXX_INFO(logger_, "Finalise USB connection " << device_uid_);
+ pthread_mutex_lock(&out_messages_mutex_);
+ disconnecting_ = true;
+ if (out_transfer_) {
+ waiting_out_transfer_cancel_ = true;
+ if (LIBUSB_SUCCESS != libusb_cancel_transfer(out_transfer_)) {
+ waiting_out_transfer_cancel_ = false;
+ }
+ }
+ if (in_transfer_) {
+ waiting_in_transfer_cancel_ = true;
+ if (LIBUSB_SUCCESS != libusb_cancel_transfer(in_transfer_)) {
+ waiting_in_transfer_cancel_ = false;
+ }
+ }
+ for (std::list<RawMessageSptr>::iterator it = out_messages_.begin();
+ it != out_messages_.end(); it = out_messages_.erase(it)) {
+ controller_->DataSendFailed(device_uid_, app_handle_, *it, DataSendError());
+ }
+ pthread_mutex_unlock(&out_messages_mutex_);
+
+ while (waiting_in_transfer_cancel_ || waiting_out_transfer_cancel_) {
+ pthread_yield();
+ }
+}
+
+TransportAdapter::Error UsbConnection::Disconnect() {
+ Finalise();
+ LOG4CXX_INFO(logger_, "USB disconnect done " << device_uid_);
+ controller_->DisconnectDone(device_uid_, app_handle_);
+ return TransportAdapter::OK;
+}
+
+bool UsbConnection::Init() {
+ if (!FindEndpoints()) {
+ return false;
+ }
+
+ in_buffer_ = new unsigned char[in_endpoint_max_packet_size_];
+ if (0 == in_buffer_) {
+ LOG4CXX_ERROR(logger_, "in buffer allocation failed (size "
+ << in_endpoint_max_packet_size_ << ")");
+ return false;
+ }
+
+ in_transfer_ = libusb_alloc_transfer(0);
+ if (0 == in_transfer_) {
+ LOG4CXX_ERROR(logger_, "libusb_alloc_transfer failed");
+ return false;
+ }
+
+ controller_->ConnectDone(device_uid_, app_handle_);
+ if (!PostInTransfer()) {
+ controller_->ConnectionAborted(device_uid_, app_handle_,
+ CommunicationError());
+ return true;
+ }
+
+ return true;
+}
+
+bool UsbConnection::FindEndpoints() {
+ struct libusb_config_descriptor* config;
+ const int libusb_ret =
+ libusb_get_active_config_descriptor(libusb_device_, &config);
+ if (LIBUSB_SUCCESS != libusb_ret) {
+ LOG4CXX_ERROR(logger_, "libusb_get_active_config_descriptor failed: "
+ << libusb_error_name(libusb_ret));
+ return false;
+ }
+
+ bool find_in_endpoint = true;
+ bool find_out_endpoint = true;
+
+ for (int i = 0; i < config->bNumInterfaces; ++i) {
+ const libusb_interface& interface = config->interface[i];
+ for (int i = 0; i < interface.num_altsetting; ++i) {
+ const libusb_interface_descriptor& iface_desc = interface.altsetting[i];
+ for (int i = 0; i < iface_desc.bNumEndpoints; ++i) {
+ const libusb_endpoint_descriptor& endpoint_desc =
+ iface_desc.endpoint[i];
+
+ const uint8_t endpoint_dir =
+ endpoint_desc.bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK;
+ if (find_in_endpoint && endpoint_dir == LIBUSB_ENDPOINT_IN) {
+ in_endpoint_ = endpoint_desc.bEndpointAddress;
+ in_endpoint_max_packet_size_ = endpoint_desc.wMaxPacketSize;
+ find_in_endpoint = false;
+ } else if (find_out_endpoint && endpoint_dir == LIBUSB_ENDPOINT_OUT) {
+ out_endpoint_ = endpoint_desc.bEndpointAddress;
+ out_endpoint_max_packet_size_ = endpoint_desc.wMaxPacketSize;
+ find_out_endpoint = false;
+ }
+ }
+ }
+ }
+ libusb_free_config_descriptor(config);
+
+ return !(find_in_endpoint || find_out_endpoint);
+}
+
+} // namespace transport_adapter
+} // namespace transport_manager
diff --git a/SDL_Core/src/components/transport_manager/src/usb/libusb/usb_handler.cc b/SDL_Core/src/components/transport_manager/src/usb/libusb/usb_handler.cc
new file mode 100644
index 000000000..88c4ee1da
--- /dev/null
+++ b/SDL_Core/src/components/transport_manager/src/usb/libusb/usb_handler.cc
@@ -0,0 +1,418 @@
+/**
+ * \file usb_handler.cc
+ * \brief UsbHandler class source file.
+ *
+ * Copyright (c) 2013, Ford Motor Company
+ * 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 Ford Motor Company 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 HOLDER 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.
+ */
+
+#include <cstring>
+#include <cstdlib>
+
+#include "transport_manager/usb/common.h"
+#include "transport_manager/transport_adapter/transport_adapter_impl.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+class UsbHandler::ControlTransferSequenceState {
+ public:
+ ControlTransferSequenceState(class UsbHandler* usb_handler,
+ UsbControlTransferSequence* sequence,
+ PlatformUsbDevice* device);
+ ~ControlTransferSequenceState();
+ void Finish();
+ bool Finished() const { return finished_; }
+ UsbControlTransfer* CurrentTransfer();
+ UsbControlTransfer* Next();
+ UsbHandler* usb_handler() const { return usb_handler_; }
+ PlatformUsbDevice* device() const { return device_; }
+
+ private:
+ UsbHandler* usb_handler_;
+ PlatformUsbDevice* device_;
+ bool finished_;
+ UsbControlTransferSequence* sequence_;
+ UsbControlTransferSequence::Transfers::const_iterator current_transfer_;
+};
+
+UsbHandler::UsbHandler()
+ : shutdown_requested_(false),
+ thread_(),
+ usb_device_listeners_(),
+ devices_(),
+ transfer_sequences_(),
+ device_handles_to_close_(),
+ libusb_context_(NULL),
+ arrived_callback_handle_(),
+ left_callback_handle_() {}
+
+UsbHandler::~UsbHandler() {
+ shutdown_requested_ = true;
+ if (libusb_context_ != 0) {
+ libusb_hotplug_deregister_callback(libusb_context_,
+ arrived_callback_handle_);
+ libusb_hotplug_deregister_callback(libusb_context_, left_callback_handle_);
+ }
+ pthread_join(thread_, 0);
+ LOG4CXX_INFO(logger_, "UsbHandler thread finished");
+ if (libusb_context_) {
+ libusb_exit(libusb_context_);
+ libusb_context_ = 0;
+ }
+}
+
+void UsbHandler::DeviceArrived(libusb_device* device_libusb) {
+ const uint8_t bus_number = libusb_get_bus_number(device_libusb);
+ const uint8_t device_address = libusb_get_device_address(device_libusb);
+ libusb_device_descriptor descriptor;
+ int libusb_ret = libusb_get_device_descriptor(device_libusb, &descriptor);
+ if (LIBUSB_SUCCESS != libusb_ret) {
+ LOG4CXX_ERROR(logger_,
+ "libusb_get_device_descriptor failed: " << libusb_ret);
+ return;
+ }
+
+ libusb_device_handle* device_handle_libusb;
+ libusb_ret = libusb_open(device_libusb, &device_handle_libusb);
+ if (libusb_ret != LIBUSB_SUCCESS) {
+ LOG4CXX_ERROR(logger_,
+ "libusb_open failed: " << libusb_error_name(libusb_ret));
+ return;
+ }
+
+ int configuration;
+ libusb_ret = libusb_get_configuration(device_handle_libusb, &configuration);
+ if (LIBUSB_SUCCESS != libusb_ret) {
+ LOG4CXX_INFO(
+ logger_,
+ "libusb_get_configuration failed: " << libusb_error_name(libusb_ret));
+ return;
+ }
+
+ if (configuration != kUsbConfiguration) {
+ libusb_ret = libusb_set_configuration(device_handle_libusb, kUsbConfiguration);
+ if (LIBUSB_SUCCESS != libusb_ret) {
+ LOG4CXX_INFO(
+ logger_,
+ "libusb_set_configuration failed: " << libusb_error_name(libusb_ret));
+ return;
+ }
+ }
+
+ libusb_ret = libusb_claim_interface(device_handle_libusb, 0);
+ if (LIBUSB_SUCCESS != libusb_ret) {
+ LOG4CXX_INFO(logger_, "libusb_claim_interface failed: "
+ << libusb_error_name(libusb_ret));
+ CloseDeviceHandle(device_handle_libusb);
+ return;
+ }
+
+ PlatformUsbDevice* device(new PlatformUsbDevice(bus_number, device_address,
+ descriptor, device_libusb,
+ device_handle_libusb));
+ devices_.push_back(device);
+
+ for (std::list<UsbDeviceListener*>::iterator it =
+ usb_device_listeners_.begin();
+ it != usb_device_listeners_.end(); ++it) {
+ (*it)->OnDeviceArrived(device);
+ }
+}
+
+void UsbHandler::DeviceLeft(libusb_device* device_libusb) {
+ PlatformUsbDevice* device = NULL;
+ for (Devices::iterator it = devices_.begin(); it != devices_.end(); ++it) {
+ if ((*it)->GetLibusbDevice() == device_libusb) {
+ device = *it;
+ break;
+ }
+ }
+ if (NULL == device) {
+ return;
+ }
+
+ for (std::list<UsbDeviceListener*>::iterator it =
+ usb_device_listeners_.begin();
+ it != usb_device_listeners_.end(); ++it) {
+ (*it)->OnDeviceLeft(device);
+ }
+
+ for (Devices::iterator it = devices_.begin(); it != devices_.end(); ++it) {
+ if ((*it)->GetLibusbDevice() == device_libusb) {
+ devices_.erase(it);
+ break;
+ }
+ }
+
+ if (device->GetLibusbHandle()) {
+ libusb_release_interface(device->GetLibusbHandle(), 0);
+ CloseDeviceHandle(device->GetLibusbHandle());
+ }
+ delete device;
+}
+
+void UsbHandler::StartControlTransferSequence(
+ UsbControlTransferSequence* sequence, PlatformUsbDevice* device) {
+ TransferSequences::iterator it = transfer_sequences_.insert(
+ transfer_sequences_.end(),
+ new ControlTransferSequenceState(this, sequence, device));
+ SubmitControlTransfer(*it);
+}
+
+void UsbHandler::CloseDeviceHandle(libusb_device_handle* device_handle) {
+ device_handles_to_close_.push_back(device_handle);
+}
+
+void* UsbHandlerThread(void* data) {
+ static_cast<UsbHandler*>(data)->Thread();
+ return 0;
+}
+
+int ArrivedCallback(libusb_context* context, libusb_device* device,
+ libusb_hotplug_event event, void* data) {
+ LOG4CXX_INFO(logger_, "libusb device arrived (bus number "
+ << static_cast<int>(libusb_get_bus_number(device))
+ << ", device address "
+ << static_cast<int>(
+ libusb_get_device_address(device)) << ")");
+ UsbHandler* usb_handler = static_cast<UsbHandler*>(data);
+ usb_handler->DeviceArrived(device);
+ return 0;
+}
+
+int LeftCallback(libusb_context* context, libusb_device* device,
+ libusb_hotplug_event event, void* data) {
+ LOG4CXX_INFO(logger_, "libusb device left (bus number "
+ << static_cast<int>(libusb_get_bus_number(device))
+ << ", device address "
+ << static_cast<int>(
+ libusb_get_device_address(device)) << ")");
+ UsbHandler* usb_handler = static_cast<UsbHandler*>(data);
+ usb_handler->DeviceLeft(device);
+ return 0;
+}
+
+TransportAdapter::Error UsbHandler::Init() {
+ int libusb_ret = libusb_init(&libusb_context_);
+
+ if (LIBUSB_SUCCESS != libusb_ret) {
+ LOG4CXX_ERROR(logger_, "libusb_init failed: " << libusb_ret);
+ return TransportAdapter::FAIL;
+ }
+
+ if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
+ LOG4CXX_ERROR(logger_, "LIBUSB_CAP_HAS_HOTPLUG not supported");
+ return TransportAdapter::FAIL;
+ }
+
+ libusb_ret = libusb_hotplug_register_callback(
+ libusb_context_, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
+ LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY,
+ LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, ArrivedCallback, this,
+ &arrived_callback_handle_);
+
+ if (LIBUSB_SUCCESS != libusb_ret) {
+ LOG4CXX_ERROR(logger_,
+ "libusb_hotplug_register_callback failed: " << libusb_ret);
+ return TransportAdapter::FAIL;
+ }
+
+ libusb_ret = libusb_hotplug_register_callback(
+ libusb_context_, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
+ static_cast<libusb_hotplug_flag>(0), LIBUSB_HOTPLUG_MATCH_ANY,
+ LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, LeftCallback, this,
+ &left_callback_handle_);
+
+ if (LIBUSB_SUCCESS != libusb_ret) {
+ LOG4CXX_ERROR(logger_,
+ "libusb_hotplug_register_callback failed: " << libusb_ret);
+ return TransportAdapter::FAIL;
+ }
+
+ const int thread_start_error =
+ pthread_create(&thread_, 0, &UsbHandlerThread, this);
+ if (0 == thread_start_error) {
+ LOG4CXX_INFO(logger_, "UsbHandler thread started");
+ return TransportAdapter::OK;
+ } else {
+ LOG4CXX_ERROR(logger_, "USB device scanner thread start failed, error code "
+ << thread_start_error);
+ return TransportAdapter::FAIL;
+ }
+}
+
+void UsbHandler::Thread() {
+ int completed = 0;
+ while (!shutdown_requested_) {
+ libusb_handle_events_completed(libusb_context_, &completed);
+
+ for (TransferSequences::iterator it = transfer_sequences_.begin();
+ it != transfer_sequences_.end();) {
+ ControlTransferSequenceState* sequence_state = *it;
+ if (sequence_state->Finished()) {
+ delete *it;
+ it = transfer_sequences_.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
+ for (std::list<libusb_device_handle*>::iterator it =
+ device_handles_to_close_.begin();
+ it != device_handles_to_close_.end();
+ it = device_handles_to_close_.erase(it)) {
+ libusb_close(*it);
+ }
+ }
+}
+
+void UsbTransferSequenceCallback(libusb_transfer* transfer) {
+ UsbHandler::ControlTransferSequenceState* sequence_state =
+ static_cast<UsbHandler::ControlTransferSequenceState*>(transfer->user_data);
+ sequence_state->usb_handler()->ControlTransferCallback(transfer);
+}
+
+void UsbHandler::SubmitControlTransfer(
+ ControlTransferSequenceState* sequence_state) {
+ UsbControlTransfer* transfer = sequence_state->CurrentTransfer();
+ if (NULL == transfer) return;
+
+ libusb_transfer* libusb_transfer = libusb_alloc_transfer(0);
+ if (0 == libusb_transfer) {
+ LOG4CXX_ERROR(logger_, "libusb_alloc_transfer failed");
+ sequence_state->Finish();
+ return;
+ }
+
+ assert(transfer->Type() == UsbControlTransfer::VENDOR);
+ const libusb_request_type request_type = LIBUSB_REQUEST_TYPE_VENDOR;
+
+ libusb_endpoint_direction endpoint_direction;
+ if (transfer->Direction() == UsbControlTransfer::IN) {
+ endpoint_direction = LIBUSB_ENDPOINT_IN;
+ } else if (transfer->Direction() == UsbControlTransfer::OUT) {
+ endpoint_direction = LIBUSB_ENDPOINT_OUT;
+ } else {
+ assert(0);
+ }
+ const uint8_t request = transfer->Request();
+ const uint16_t value = transfer->Value();
+ const uint16_t index = transfer->Index();
+ const uint16_t length = transfer->Length();
+
+ unsigned char* buffer =
+ static_cast<unsigned char*>(malloc(length + LIBUSB_CONTROL_SETUP_SIZE));
+ if (NULL == buffer) {
+ LOG4CXX_ERROR(logger_, "buffer allocation failed");
+ libusb_free_transfer(libusb_transfer);
+ sequence_state->Finish();
+ return;
+ }
+
+ libusb_fill_control_setup(buffer, request_type | endpoint_direction, request,
+ value, index, length);
+
+ if (0 != length && endpoint_direction == LIBUSB_ENDPOINT_OUT) {
+ const char* data = static_cast<UsbControlOutTransfer*>(transfer)->Data();
+ memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, length);
+ }
+ libusb_fill_control_transfer(
+ libusb_transfer, sequence_state->device()->GetLibusbHandle(), buffer,
+ UsbTransferSequenceCallback, sequence_state, 0);
+ libusb_transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER;
+
+ const int libusb_ret = libusb_submit_transfer(libusb_transfer);
+ if (LIBUSB_SUCCESS != libusb_ret) {
+ LOG4CXX_ERROR(logger_, "libusb_submit_transfer failed: "
+ << libusb_error_name(libusb_ret));
+ libusb_free_transfer(libusb_transfer);
+ sequence_state->Finish();
+ }
+}
+
+void UsbHandler::ControlTransferCallback(libusb_transfer* transfer) {
+ ControlTransferSequenceState* sequence_state =
+ static_cast<ControlTransferSequenceState*>(transfer->user_data);
+ if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
+ LOG4CXX_INFO(logger_, "USB control transfer completed");
+ UsbControlTransfer* current_transfer = sequence_state->CurrentTransfer();
+ bool submit_next = true;
+ if (current_transfer &&
+ current_transfer->Direction() == UsbControlTransfer::IN) {
+ submit_next =
+ static_cast<UsbControlInTransfer*>(current_transfer)
+ ->OnCompleted(libusb_control_transfer_get_data(transfer));
+ }
+
+ sequence_state->Next();
+ if (submit_next && !sequence_state->Finished()) {
+ SubmitControlTransfer(sequence_state);
+ } else {
+ sequence_state->Finish();
+ }
+ } else {
+ LOG4CXX_ERROR(logger_, "USB control transfer failed: " << transfer->status);
+ sequence_state->Finish();
+ }
+ libusb_free_transfer(transfer);
+}
+
+UsbHandler::ControlTransferSequenceState::ControlTransferSequenceState(
+ UsbHandler* usb_handler, UsbControlTransferSequence* sequence,
+ PlatformUsbDevice* device)
+ : usb_handler_(usb_handler),
+ device_(device),
+ finished_(false),
+ sequence_(sequence),
+ current_transfer_(sequence->transfers().begin()) {}
+
+UsbHandler::ControlTransferSequenceState::~ControlTransferSequenceState() {
+ delete sequence_;
+}
+
+UsbControlTransfer* UsbHandler::ControlTransferSequenceState::Next() {
+ if (finished_) return NULL;
+ if (++current_transfer_ == sequence_->transfers().end()) {
+ Finish();
+ return NULL;
+ } else {
+ return *current_transfer_;
+ }
+}
+
+UsbControlTransfer* UsbHandler::ControlTransferSequenceState::CurrentTransfer() {
+ return finished_ ? NULL : *current_transfer_;
+}
+
+void UsbHandler::ControlTransferSequenceState::Finish() { finished_ = true; }
+
+} // namespace
+} // namespace
diff --git a/SDL_Core/src/components/transport_manager/src/usb/qnx/platform_usb_device.cc b/SDL_Core/src/components/transport_manager/src/usb/qnx/platform_usb_device.cc
new file mode 100644
index 000000000..c17c2aab6
--- /dev/null
+++ b/SDL_Core/src/components/transport_manager/src/usb/qnx/platform_usb_device.cc
@@ -0,0 +1,75 @@
+/**
+ * \file platform_usb_device.cc
+ * \brief QNX PlatformUsbDevice class source file.
+ *
+ * Copyright (c) 2013, Ford Motor Company
+ * 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 Ford Motor Company 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 HOLDER 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.
+ */
+
+#include "transport_manager/usb/qnx/platform_usb_device.h"
+#include "transport_manager/transport_adapter/transport_adapter_impl.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+PlatformUsbDevice::PlatformUsbDevice(
+ usbd_device_instance_t* instance, usbd_device* device,
+ const usbd_device_descriptor_t& device_descriptor)
+ : bus_number_(instance->path),
+ address_(instance->devno),
+ vendor_id_(instance->ident.vendor),
+ product_id_(instance->ident.device),
+ device_descriptor_(device_descriptor),
+ usbd_device_instance_(*instance),
+ usbd_device_(device) {}
+
+std::string PlatformUsbDevice::GetDescString(uint8_t index) const {
+ char* str = usbd_string(usbd_device_, index, 0);
+ if (NULL == str) {
+ LOG4CXX_INFO(logger_, "Failed to get USB string descriptor");
+ return "";
+ }
+ return std::string(str);
+}
+
+std::string PlatformUsbDevice::GetManufacturer() const {
+ return GetDescString(device_descriptor_.iManufacturer);
+}
+
+std::string PlatformUsbDevice::GetProductName() const {
+ return GetDescString(device_descriptor_.iProduct);
+}
+
+std::string PlatformUsbDevice::GetSerialNumber() const {
+ return GetDescString(device_descriptor_.iSerialNumber);
+}
+
+} // namespace
+} // namespace
diff --git a/SDL_Core/src/components/transport_manager/src/usb/qnx/usb_connection.cc b/SDL_Core/src/components/transport_manager/src/usb/qnx/usb_connection.cc
new file mode 100644
index 000000000..dec5267ba
--- /dev/null
+++ b/SDL_Core/src/components/transport_manager/src/usb/qnx/usb_connection.cc
@@ -0,0 +1,399 @@
+/**
+ * \file usb_connection.cc
+ * \brief UsbConnection class source file.
+ *
+ * Copyright (c) 2013, Ford Motor Company
+ * 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 Ford Motor Company 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 HOLDER 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.
+ */
+
+#include <sched.h>
+#include <cstring>
+
+#include "transport_manager/usb/qnx/usb_connection.h"
+#include "transport_manager/transport_adapter/transport_adapter_impl.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+UsbConnection::UsbConnection(const DeviceUID& device_uid,
+ const ApplicationHandle& app_handle,
+ TransportAdapterController* controller,
+ const UsbHandlerSptr& libusb_handler,
+ PlatformUsbDevice* device)
+ : device_uid_(device_uid),
+ app_handle_(app_handle),
+ controller_(controller),
+ libusb_handler_(libusb_handler),
+ usbd_device_(device->GetUsbdDevice()),
+ in_pipe_(NULL),
+ out_pipe_(NULL),
+ in_buffer_(NULL),
+ in_urb_(NULL),
+ out_urb_(NULL),
+ out_messages_(),
+ current_out_message_(),
+ out_messages_mutex_(),
+ bytes_sent_(0),
+ disconnecting_(false),
+ pending_in_transfer_(false),
+ pending_out_transfer_(false) {
+ pthread_mutex_init(&out_messages_mutex_, 0);
+}
+
+UsbConnection::~UsbConnection() {
+ Finalise();
+ if (in_urb_) usbd_free_urb(in_urb_);
+ if (out_urb_) usbd_free_urb(out_urb_);
+
+ if (in_pipe_) {
+ const int close_pipe_rc = usbd_close_pipe(in_pipe_);
+ if (EOK != close_pipe_rc) {
+ LOG4CXX_ERROR(logger_, "Failed to close pipe: " << close_pipe_rc);
+ }
+ }
+ if (out_pipe_) {
+ const int close_pipe_rc = usbd_close_pipe(out_pipe_);
+ if (EOK != close_pipe_rc) {
+ LOG4CXX_ERROR(logger_, "Failed to close pipe: " << close_pipe_rc);
+ }
+ }
+
+ pthread_mutex_destroy(&out_messages_mutex_);
+}
+
+void InTransferCallback(usbd_urb* urb, usbd_pipe*, void* data) {
+ static_cast<UsbConnection*>(data)->OnInTransfer(urb);
+}
+
+void OutTransferCallback(usbd_urb* urb, usbd_pipe*, void* data) {
+ static_cast<UsbConnection*>(data)->OnOutTransfer(urb);
+}
+
+bool UsbConnection::PostInTransfer() {
+ usbd_setup_bulk(in_urb_, URB_DIR_IN, in_buffer_, kInBufferSize);
+ pending_in_transfer_ = true;
+ const int io_rc =
+ usbd_io(in_urb_, in_pipe_, InTransferCallback, this, USBD_TIME_INFINITY);
+ if (EOK != io_rc) {
+ pending_in_transfer_ = false;
+ LOG4CXX_ERROR(logger_, "Failed to post in transfer: " << io_rc);
+ return false;
+ }
+ return true;
+}
+
+void UsbConnection::OnInTransfer(usbd_urb* urb) {
+ uint32_t status = 0;
+ uint32_t len = 0;
+ bool error = false;
+ const int urb_status_rc = usbd_urb_status(urb, &status, &len);
+ if (EOK != urb_status_rc && EIO != urb_status_rc) { // EIO is OK
+ LOG4CXX_ERROR(logger_, "Get in urb status failed: " << urb_status_rc);
+ error = true;
+ }
+ LOG4CXX_INFO(logger_, "USB in transfer, status " << std::hex << status
+ << ", length " << std::dec
+ << len);
+
+ if (!error) {
+ const uint32_t urb_status = status & USBD_URB_STATUS_MASK;
+ switch (status) {
+ case USBD_STATUS_CMP:
+ case USBD_STATUS_CMP_ERR | USBD_STATUS_DATA_UNDERRUN:
+ error = false;
+ break;
+ default:
+ error = true;
+ break;
+ }
+ }
+
+ if (error) {
+ LOG4CXX_ERROR(logger_, "USB in transfer failed");
+ controller_->DataReceiveFailed(device_uid_, app_handle_,
+ DataReceiveError());
+ } else {
+ RawMessageSptr msg(new protocol_handler::RawMessage(0, 0, in_buffer_, len));
+ controller_->DataReceiveDone(device_uid_, app_handle_, msg);
+ }
+
+ pending_in_transfer_ = false;
+ if (!disconnecting_) {
+ if (!PostInTransfer()) {
+ controller_->ConnectionAborted(device_uid_, app_handle_,
+ CommunicationError());
+ Disconnect();
+ }
+ }
+}
+
+void UsbConnection::PopOutMessage() {
+ bytes_sent_ = 0;
+ if (out_messages_.empty()) {
+ current_out_message_.reset();
+ } else {
+ current_out_message_ = out_messages_.front();
+ out_messages_.pop_front();
+ }
+}
+
+bool UsbConnection::PostOutTransfer() {
+ const int len = current_out_message_->data_size() - bytes_sent_;
+ out_buffer_ = usbd_alloc(len);
+ memmove(out_buffer_, current_out_message_->data() + bytes_sent_, len);
+ usbd_setup_bulk(out_urb_, URB_DIR_OUT, out_buffer_, len);
+ LOG4CXX_INFO(logger_, "out transfer :" << len);
+ pending_out_transfer_ = true;
+ const int io_rc = usbd_io(out_urb_, out_pipe_, OutTransferCallback, this,
+ USBD_TIME_INFINITY);
+ if (EOK != io_rc) {
+ pending_out_transfer_ = false;
+ usbd_free(out_buffer_);
+ LOG4CXX_ERROR(logger_, "Failed to post out transfer: " << io_rc);
+ return false;
+ }
+ return true;
+}
+
+void UsbConnection::OnOutTransfer(usbd_urb* urb) {
+ usbd_free(out_buffer_);
+ uint32_t status = 0;
+ uint32_t len = 0;
+ bool error = false;
+ const int urb_status_rc = usbd_urb_status(urb, &status, &len);
+ if (EOK != urb_status_rc && EIO != urb_status_rc) { // EIO is OK
+ LOG4CXX_ERROR(logger_, "Get out urb status failed: " << urb_status_rc);
+ error = true;
+ }
+ LOG4CXX_INFO(logger_, "USB out transfer, status " << std::hex << status
+ << ", length " << std::dec
+ << len);
+
+ if (!error) {
+ const uint32_t urb_status = status & USBD_URB_STATUS_MASK;
+ switch (status) {
+ case USBD_STATUS_CMP:
+ case USBD_STATUS_CMP_ERR | USBD_STATUS_DATA_UNDERRUN:
+ error = false;
+ break;
+ default:
+ error = true;
+ break;
+ }
+ }
+
+ pthread_mutex_lock(&out_messages_mutex_);
+
+ if (error) {
+ LOG4CXX_ERROR(logger_, "USB out transfer failed");
+ controller_->DataSendFailed(device_uid_, app_handle_, current_out_message_,
+ DataSendError());
+ PopOutMessage();
+ } else {
+ bytes_sent_ += len;
+ if (bytes_sent_ == current_out_message_->data_size()) {
+ LOG4CXX_INFO(logger_, "USB out transfer, data sent: "
+ << current_out_message_.get());
+ controller_->DataSendDone(device_uid_, app_handle_, current_out_message_);
+ PopOutMessage();
+ }
+ }
+
+ if ((!disconnecting_) && current_out_message_.valid()) {
+ PostOutTransfer();
+ } else {
+ pending_out_transfer_ = false;
+ }
+ pthread_mutex_unlock(&out_messages_mutex_);
+}
+
+TransportAdapter::Error UsbConnection::SendData(RawMessageSptr message) {
+ if (disconnecting_) {
+ return TransportAdapter::BAD_STATE;
+ }
+ pthread_mutex_lock(&out_messages_mutex_);
+ if (current_out_message_.valid()) {
+ out_messages_.push_back(message);
+ } else {
+ current_out_message_ = message;
+ if (!PostOutTransfer()) {
+ controller_->DataSendFailed(device_uid_, app_handle_, message,
+ DataSendError());
+ }
+ }
+ pthread_mutex_unlock(&out_messages_mutex_);
+ return TransportAdapter::OK;
+}
+
+void UsbConnection::Finalise() {
+ LOG4CXX_INFO(logger_, "Finalising");
+ pthread_mutex_lock(&out_messages_mutex_);
+ disconnecting_ = true;
+ usbd_abort_pipe(in_pipe_);
+ usbd_abort_pipe(out_pipe_);
+ for (std::list<RawMessageSptr>::iterator it = out_messages_.begin();
+ it != out_messages_.end(); it = out_messages_.erase(it)) {
+ controller_->DataSendFailed(device_uid_, app_handle_, *it, DataSendError());
+ }
+ pthread_mutex_unlock(&out_messages_mutex_);
+ while (pending_in_transfer_ || pending_out_transfer_) sched_yield();
+}
+
+TransportAdapter::Error UsbConnection::Disconnect() {
+ LOG4CXX_INFO(logger_, "Disconnecting");
+ Finalise();
+ controller_->DisconnectDone(device_uid_, app_handle_);
+ return TransportAdapter::OK;
+}
+
+bool UsbConnection::Init() {
+ if (!OpenEndpoints()) return false;
+
+ in_urb_ = usbd_alloc_urb(NULL);
+ out_urb_ = usbd_alloc_urb(NULL);
+ if (NULL == in_urb_ || NULL == out_urb_) {
+ LOG4CXX_ERROR(logger_, "usbd_alloc_urb failed");
+ return false;
+ }
+
+ in_buffer_ = static_cast<unsigned char*>(usbd_alloc(kInBufferSize));
+ if (NULL == in_buffer_) {
+ LOG4CXX_ERROR(logger_, "usbd_alloc failed");
+ return false;
+ }
+
+ controller_->ConnectDone(device_uid_, app_handle_);
+
+ if (!PostInTransfer()) {
+ controller_->ConnectionAborted(device_uid_, app_handle_,
+ CommunicationError());
+ return true;
+ }
+
+ return true;
+}
+
+bool UsbConnection::OpenEndpoints() {
+ usbd_descriptors_t* in_endpoint_desc = NULL;
+ usbd_descriptors_t* out_endpoint_desc = NULL;
+
+ usbd_desc_node* device_desc_node = NULL;
+ usbd_device_descriptor_t* device_desc =
+ usbd_device_descriptor(usbd_device_, &device_desc_node);
+ if (0 == device_desc) {
+ LOG4CXX_ERROR(logger_, "Device descriptor not found");
+ return false;
+ }
+ usbd_desc_node* cfg_desc_node = NULL;
+ usbd_descriptors_t* config_desc = NULL;
+ usbd_descriptors_t* iface_desc = NULL;
+ int cfg = 0;
+ bool found = false;
+ while (!found) {
+ config_desc =
+ usbd_parse_descriptors(usbd_device_, device_desc_node,
+ USB_DESC_CONFIGURATION, cfg++, &cfg_desc_node);
+ if (config_desc == NULL) {
+ break;
+ }
+ LOG4CXX_INFO(logger_, "USB configuration "
+ << static_cast<int>(config_desc->configuration
+ .bConfigurationValue));
+ int iface = 0;
+ usbd_desc_node* iface_desc_node;
+ while (!found) {
+ iface_desc =
+ usbd_parse_descriptors(usbd_device_, cfg_desc_node,
+ USB_DESC_INTERFACE, iface++, &iface_desc_node);
+ if (iface_desc == NULL) {
+ break;
+ }
+ const uint8_t interface_number = iface_desc->interface.bInterfaceNumber;
+ const uint8_t interface_subclass =
+ iface_desc->interface.bInterfaceSubClass;
+ LOG4CXX_INFO(logger_, "USB interface number "
+ << static_cast<int>(interface_number)
+ << ", subclass " << std::hex
+ << static_cast<int>(interface_subclass)
+ << std::dec);
+ if (interface_subclass != 0xff) {
+ continue;
+ }
+ int endpoint = 0;
+ in_endpoint_desc = NULL;
+ out_endpoint_desc = NULL;
+ while (true) {
+ usbd_descriptors_t* endpoint_desc = usbd_parse_descriptors(
+ usbd_device_, iface_desc_node, USB_DESC_ENDPOINT, endpoint++, NULL);
+ if (NULL == endpoint_desc) break;
+ const uint8_t attributes = endpoint_desc->endpoint.bmAttributes;
+ if ((attributes & 0x03) == USB_ATTRIB_BULK) {
+ const uint8_t endpoint_address =
+ endpoint_desc->endpoint.bEndpointAddress;
+ LOG4CXX_INFO(logger_, "Endpoint with address "
+ << std::hex
+ << static_cast<int>(endpoint_address)
+ << std::dec << " found");
+ if (endpoint_address & USB_ENDPOINT_IN) {
+ if (NULL == in_endpoint_desc) {
+ in_endpoint_desc = endpoint_desc;
+ }
+ } else {
+ if (NULL == out_endpoint_desc) {
+ out_endpoint_desc = endpoint_desc;
+ }
+ }
+ }
+ }
+ if (in_endpoint_desc != NULL && out_endpoint_desc != NULL) {
+ found = true;
+ }
+ }
+ }
+
+ if (!found) return false;
+
+ int open_pipe_rc = usbd_open_pipe(usbd_device_, in_endpoint_desc, &in_pipe_);
+ if (EOK != open_pipe_rc) {
+ LOG4CXX_ERROR(logger_, "Cannot open input pipe, error " << open_pipe_rc);
+ return false;
+ }
+
+ open_pipe_rc = usbd_open_pipe(usbd_device_, out_endpoint_desc, &out_pipe_);
+ if (EOK != open_pipe_rc) {
+ LOG4CXX_ERROR(logger_, "Cannot open output pipe, error " << open_pipe_rc);
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace transport_adapter
+} // namespace transport_manager
diff --git a/SDL_Core/src/components/transport_manager/src/usb/qnx/usb_handler.cc b/SDL_Core/src/components/transport_manager/src/usb/qnx/usb_handler.cc
new file mode 100644
index 000000000..ccb9cd0d5
--- /dev/null
+++ b/SDL_Core/src/components/transport_manager/src/usb/qnx/usb_handler.cc
@@ -0,0 +1,296 @@
+/**
+ * \file usb_handler.cc
+ * \brief UsbHandler class source file.
+ *
+ * Copyright (c) 2013, Ford Motor Company
+ * 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 Ford Motor Company 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 HOLDER 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.
+ */
+
+#include <cstring>
+#include <cstdlib>
+
+#include "transport_manager/usb/common.h"
+#include "transport_manager/transport_adapter/transport_adapter_impl.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+namespace {
+UsbHandler* usb_handler;
+}
+
+UsbHandler::UsbHandler()
+ : usb_device_listeners_(),
+ devices_(),
+ usbd_general_connection_(NULL),
+ usbd_aoa_connection_(NULL) {
+ usb_handler = this;
+}
+
+UsbHandler::~UsbHandler() {
+ usb_handler = NULL;
+ if (usbd_general_connection_) {
+ const int disconnect_rc = usbd_disconnect(usbd_general_connection_);
+ if (EOK != disconnect_rc) {
+ LOG4CXX_ERROR(logger_, "usbd_disconnect failed, error code "
+ << disconnect_rc);
+ }
+ }
+ if (usbd_aoa_connection_) {
+ const int disconnect_rc = usbd_disconnect(usbd_aoa_connection_);
+ if (EOK != disconnect_rc) {
+ LOG4CXX_ERROR(logger_, "usbd_disconnect failed, error code "
+ << disconnect_rc);
+ }
+ }
+}
+
+bool operator==(const usbd_device_instance_t& a,
+ const usbd_device_instance_t& b) {
+ return a.path == b.path && a.devno == b.devno;
+}
+
+void UsbHandler::DeviceArrived(usbd_connection* connection,
+ usbd_device_instance_t* instance) {
+ for (Devices::const_iterator it = devices_.begin(); it != devices_.end();
+ ++it) {
+ if ((*it)->GetDeviceInstance() == *instance) return;
+ }
+ usbd_device* device_usbd = 0;
+ const int attach_rc = usbd_attach(connection, instance, 0, &device_usbd);
+ if (EOK != attach_rc) {
+ LOG4CXX_ERROR(logger_, "usbd_attach failed: " << attach_rc);
+ return;
+ }
+
+ usbd_desc_node* node;
+ usbd_device_descriptor_t* descriptor =
+ usbd_device_descriptor(device_usbd, &node);
+ if (NULL == descriptor) {
+ LOG4CXX_ERROR(logger_, "usbd_device_descriptor failed");
+ return;
+ }
+
+ PlatformUsbDevice* device(
+ new PlatformUsbDevice(instance, device_usbd, *descriptor));
+ devices_.push_back(device);
+ for (std::list<UsbDeviceListener*>::iterator it =
+ usb_device_listeners_.begin();
+ it != usb_device_listeners_.end(); ++it) {
+ (*it)->OnDeviceArrived(device);
+ }
+}
+
+void UsbHandler::DeviceLeft(usbd_device_instance_t* instance) {
+ PlatformUsbDevice* device = NULL;
+ for (Devices::iterator it = devices_.begin(); it != devices_.end(); ++it) {
+ if (((*it)->GetDeviceInstance()) == *instance) {
+ device = *it;
+ break;
+ }
+ }
+ if (NULL == device) {
+ return;
+ }
+
+ for (std::list<UsbDeviceListener*>::iterator it =
+ usb_device_listeners_.begin();
+ it != usb_device_listeners_.end(); ++it) {
+ (*it)->OnDeviceLeft(device);
+ }
+
+ for (Devices::iterator it = devices_.begin(); it != devices_.end(); ++it) {
+ if ((*it)->GetDeviceInstance() == *instance) {
+ const int detach_rc = usbd_detach((*it)->GetUsbdDevice());
+ if (EOK != detach_rc)
+ LOG4CXX_ERROR(logger_, "usbd_detach failed: " << detach_rc);
+ devices_.erase(it);
+ break;
+ }
+ }
+
+ delete device;
+}
+
+void UsbHandler::StartControlTransferSequence(
+ UsbControlTransferSequence* sequence, PlatformUsbDevice* device) {
+ usbd_descriptors_t* descriptor = usbd_parse_descriptors(
+ device->GetUsbdDevice(), NULL, USB_DESC_DEVICE, 0, NULL);
+ if (NULL == descriptor) {
+ LOG4CXX_ERROR(logger_, "usbd_parse_descriptors failed");
+ }
+
+ usbd_pipe* usb_pipe = 0;
+ const int open_pipe_rc =
+ usbd_open_pipe(device->GetUsbdDevice(), descriptor, &usb_pipe);
+ if (EOK != open_pipe_rc) {
+ LOG4CXX_ERROR(logger_, "usbd_open_pipe failed, error " << open_pipe_rc);
+ return;
+ }
+
+ for (UsbControlTransferSequence::Transfers::const_iterator it =
+ sequence->transfers().begin();
+ it != sequence->transfers().end(); ++it) {
+ UsbControlTransfer* transfer = *it;
+
+ usbd_urb* urb = usbd_alloc_urb(NULL);
+ if (NULL == urb) {
+ LOG4CXX_ERROR(logger_, "usbd_alloc_urb failed");
+ break;
+ }
+
+ unsigned char* buf =
+ static_cast<unsigned char*>(usbd_alloc(transfer->Length()));
+ if (NULL == buf) {
+ LOG4CXX_ERROR(logger_, "usbd_alloc failed");
+ break;
+ }
+
+ uint32_t flags = 0;
+ if (transfer->Direction() == UsbControlTransfer::IN) {
+ flags = URB_DIR_IN;
+ } else if (transfer->Direction() == UsbControlTransfer::OUT) {
+ flags = URB_DIR_OUT;
+ UsbControlOutTransfer* out_transfer =
+ static_cast<UsbControlOutTransfer*>(transfer);
+ std::copy(out_transfer->Data(),
+ out_transfer->Data() + out_transfer->Length(), buf);
+ } else {
+ assert(0);
+ }
+
+ assert(transfer->Type() == UsbControlTransfer::VENDOR);
+
+ usbd_setup_vendor(urb, flags, transfer->Request(), USB_TYPE_VENDOR,
+ transfer->Value(), transfer->Index(), buf,
+ transfer->Length());
+ const int io_rc = usbd_io(urb, usb_pipe, 0, 0, USBD_TIME_DEFAULT);
+
+ bool submit_next = true;
+ if (io_rc == EOK) {
+ if (transfer->Direction() == UsbControlTransfer::IN) {
+ submit_next =
+ static_cast<UsbControlInTransfer*>(transfer)->OnCompleted(buf);
+ }
+ } else {
+ LOG4CXX_ERROR(logger_, "usbd_io failed, error " << io_rc);
+ submit_next = false;
+ }
+ usbd_free(buf);
+ usbd_free_urb(urb);
+ if (!submit_next) break;
+ }
+ usbd_close_pipe(usb_pipe);
+
+ delete sequence;
+}
+
+void ArrivedCallback(usbd_connection* connection,
+ usbd_device_instance_t* instance) {
+ if (kAoaVid == instance->ident.vendor) return;
+ LOG4CXX_INFO(logger_, "USB device arrived (path "
+ << static_cast<int>(instance->path) << ", devno "
+ << static_cast<int>(instance->devno) << ", config "
+ << static_cast<int>(instance->config) << ", iface "
+ << static_cast<int>(instance->iface) << ")");
+ usb_handler->DeviceArrived(connection, instance);
+}
+
+void ArrivedAoaCallback(usbd_connection* connection,
+ usbd_device_instance_t* instance) {
+ if (kAoaVid != instance->ident.vendor) return;
+ LOG4CXX_INFO(logger_, "USB AOA device arrived (path "
+ << static_cast<int>(instance->path) << ", devno "
+ << static_cast<int>(instance->devno) << ", config "
+ << static_cast<int>(instance->config) << ", iface "
+ << static_cast<int>(instance->iface) << ")");
+ usb_handler->DeviceArrived(connection, instance);
+}
+
+void LeftCallback(usbd_connection* connection,
+ usbd_device_instance_t* instance) {
+ if (kAoaVid == instance->ident.vendor) return;
+ LOG4CXX_INFO(logger_, "USB device left (path "
+ << static_cast<int>(instance->path) << ", devno "
+ << static_cast<int>(instance->devno) << ", config "
+ << static_cast<int>(instance->config) << ", iface "
+ << static_cast<int>(instance->iface) << ")");
+ usb_handler->DeviceLeft(instance);
+}
+
+void LeftAoaCallback(usbd_connection* connection,
+ usbd_device_instance_t* instance) {
+ if (kAoaVid != instance->ident.vendor) return;
+ LOG4CXX_INFO(logger_, "USB AOA device left (path "
+ << static_cast<int>(instance->path) << ", devno "
+ << static_cast<int>(instance->devno) << ", config "
+ << static_cast<int>(instance->config) << ", iface "
+ << static_cast<int>(instance->iface) << ")");
+ usb_handler->DeviceLeft(instance);
+}
+
+TransportAdapter::Error UsbHandler::Init() {
+ {
+ usbd_device_ident_t interest = {
+ USBD_CONNECT_WILDCARD, USBD_CONNECT_WILDCARD, kAoaInterfaceSubclass,
+ USBD_CONNECT_WILDCARD, USBD_CONNECT_WILDCARD};
+ usbd_funcs_t funcs = {_USBDI_NFUNCS, ArrivedCallback, LeftCallback, NULL};
+ usbd_connect_parm_t cparms = {NULL, USB_VERSION, USBD_VERSION, 0, 0,
+ NULL, 0, &interest, &funcs};
+
+ const int connect_rc = usbd_connect(&cparms, &usbd_general_connection_);
+
+ if (EOK != connect_rc) {
+ LOG4CXX_ERROR(logger_, "usbd_connect failed, error code " << connect_rc);
+ return TransportAdapter::FAIL;
+ }
+ }
+ {
+ usbd_device_ident_t interest = {
+ kAoaVid, USBD_CONNECT_WILDCARD, USBD_CONNECT_WILDCARD,
+ kAoaInterfaceSubclass, USBD_CONNECT_WILDCARD};
+ usbd_funcs_t funcs = {_USBDI_NFUNCS, ArrivedAoaCallback,
+ LeftAoaCallback, NULL};
+ usbd_connect_parm_t cparms = {NULL, USB_VERSION, USBD_VERSION, 0, 0,
+ NULL, 0, &interest, &funcs};
+
+ const int connect_rc = usbd_connect(&cparms, &usbd_aoa_connection_);
+
+ if (EOK != connect_rc) {
+ LOG4CXX_ERROR(logger_, "usbd_connect failed, error code " << connect_rc);
+ return TransportAdapter::FAIL;
+ }
+ }
+
+ return TransportAdapter::OK;
+}
+
+} // namespace
+} // namespace
diff --git a/SDL_Core/src/components/transport_manager/src/usb/usb_aoa_adapter.cc b/SDL_Core/src/components/transport_manager/src/usb/usb_aoa_adapter.cc
new file mode 100644
index 000000000..88487bcc1
--- /dev/null
+++ b/SDL_Core/src/components/transport_manager/src/usb/usb_aoa_adapter.cc
@@ -0,0 +1,80 @@
+/**
+ * \file usb_aoa_adapter.cpp
+ * \brief UsbAoaAdapter class source file.
+ *
+ * Copyright (c) 2013, Ford Motor Company
+ * 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 Ford Motor Company 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 HOLDER 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.
+ */
+
+#include "transport_manager/usb/usb_aoa_adapter.h"
+#include "transport_manager/usb/usb_device_scanner.h"
+#include "transport_manager/usb/usb_connection_factory.h"
+#include "transport_manager/usb/common.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+UsbAoaAdapter::UsbAoaAdapter()
+ : TransportAdapterImpl(new UsbDeviceScanner(this),
+ new UsbConnectionFactory(this), 0),
+ is_initialised_(false),
+ usb_handler_(new UsbHandler()) {
+ static_cast<UsbDeviceScanner*>(device_scanner_)->SetUsbHandler(usb_handler_);
+ static_cast<UsbConnectionFactory*>(server_connection_factory_)
+ ->SetUsbHandler(usb_handler_);
+}
+
+UsbAoaAdapter::~UsbAoaAdapter() {}
+
+DeviceType UsbAoaAdapter::GetDeviceType() const { return "sdl-usb-aoa"; }
+
+bool UsbAoaAdapter::IsInitialised() const {
+ return is_initialised_ && TransportAdapterImpl::IsInitialised();
+}
+
+TransportAdapter::Error UsbAoaAdapter::Init() {
+ TransportAdapter::Error error = usb_handler_->Init();
+ if (error != TransportAdapter::OK) {
+ return error;
+ }
+ error = TransportAdapterImpl::Init();
+ if (error != TransportAdapter::OK) {
+ return error;
+ }
+ is_initialised_ = true;
+ return TransportAdapter::OK;
+}
+
+bool UsbAoaAdapter::ToBeAutoConnected(DeviceSptr device) const {
+ return true;
+}
+
+} // namespace transport_adapter
+} // namespace transport_manager
diff --git a/SDL_Core/src/components/transport_manager/src/usb/usb_connection_factory.cc b/SDL_Core/src/components/transport_manager/src/usb/usb_connection_factory.cc
new file mode 100644
index 000000000..4081ac40f
--- /dev/null
+++ b/SDL_Core/src/components/transport_manager/src/usb/usb_connection_factory.cc
@@ -0,0 +1,91 @@
+/**
+ * \file usb_connection_factory.cc
+ * \brief UsbConnectionFactory class source file.
+ *
+ * Copyright (c) 2013, Ford Motor Company
+ * 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 Ford Motor Company 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 HOLDER 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.
+ */
+
+#include "transport_manager/usb/usb_connection_factory.h"
+#include "transport_manager/usb/usb_device.h"
+#include "transport_manager/transport_adapter/transport_adapter_impl.h"
+
+#if defined(__QNX__) || defined(__QNXNTO__)
+#include "transport_manager/usb/qnx/usb_connection.h"
+#else
+#include "transport_manager/usb/libusb/usb_connection.h"
+#endif
+
+namespace transport_manager {
+namespace transport_adapter {
+
+UsbConnectionFactory::UsbConnectionFactory(
+ TransportAdapterController* controller)
+ : controller_(controller), usb_handler_() {}
+
+TransportAdapter::Error UsbConnectionFactory::Init() {
+ return TransportAdapter::OK;
+}
+
+void UsbConnectionFactory::SetUsbHandler(const UsbHandlerSptr& usb_handler) {
+ usb_handler_ = usb_handler;
+}
+
+TransportAdapter::Error UsbConnectionFactory::CreateConnection(
+ const DeviceUID& device_uid, const ApplicationHandle& app_handle) {
+ DeviceSptr device = controller_->FindDevice(device_uid);
+ if (!device.valid()) {
+ LOG4CXX_ERROR(logger_, "device " << device_uid << " not found");
+ return TransportAdapter::BAD_PARAM;
+ }
+
+ UsbDevice* usb_device = static_cast<UsbDevice*>(device.get());
+ UsbConnection* usb_connection =
+ new UsbConnection(device_uid, app_handle, controller_, usb_handler_,
+ usb_device->usb_device());
+ ConnectionSptr connection(usb_connection);
+
+ controller_->ConnectionCreated(connection, device_uid, app_handle);
+ if (!usb_connection->Init()) {
+ return TransportAdapter::FAIL;
+ }
+ LOG4CXX_INFO(logger_, "Usb connection initialised");
+
+ return TransportAdapter::OK;
+}
+
+void UsbConnectionFactory::Terminate() {}
+
+bool UsbConnectionFactory::IsInitialised() const { return true; }
+
+UsbConnectionFactory::~UsbConnectionFactory() {}
+
+} // namespace transport_adapter
+} // namespace transport_manager
diff --git a/SDL_Core/src/components/transport_manager/src/usb/usb_device_scanner.cc b/SDL_Core/src/components/transport_manager/src/usb/usb_device_scanner.cc
new file mode 100644
index 000000000..78358d419
--- /dev/null
+++ b/SDL_Core/src/components/transport_manager/src/usb/usb_device_scanner.cc
@@ -0,0 +1,213 @@
+/**
+ * \file usb_device_scanner.cc
+ * \brief UsbDeviceScanner class source file.
+ *
+ * Copyright (c) 2013, Ford Motor Company
+ * 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 Ford Motor Company 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 HOLDER 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.
+ */
+
+#include <sstream>
+
+#include "transport_manager/transport_adapter/transport_adapter_impl.h"
+#include "transport_manager/usb/usb_device_scanner.h"
+#include "transport_manager/usb/usb_device.h"
+#include "transport_manager/usb/common.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+class AoaInitSequence : public UsbControlTransferSequence {
+ public:
+ AoaInitSequence();
+ virtual ~AoaInitSequence() {}
+
+ private:
+ class AoaGetProtocolRequest;
+ class AoaSendIdString;
+ class AoaTurnIntoAccessoryMode;
+};
+
+bool IsGoogleAccessory(uint16_t vid, uint16_t pid) {
+ return (vid == kAoaVid) && (pid == kAoaPid1 || pid == kAoaPid2);
+}
+
+void UsbDeviceScanner::OnDeviceArrived(PlatformUsbDevice* device) {
+ if (IsGoogleAccessory(device->vendor_id(), device->product_id())) {
+ GoogleAccessoryFound(device);
+ } else {
+ TurnIntoAccessoryMode(device);
+ }
+}
+
+void UsbDeviceScanner::OnDeviceLeft(PlatformUsbDevice* device) {
+ bool list_changed = false;
+ pthread_mutex_lock(&devices_mutex_);
+ for (Devices::iterator it = devices_.begin(); it != devices_.end(); ++it) {
+ if (device == *it) {
+ devices_.erase(it);
+ list_changed = true;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&devices_mutex_);
+ if (list_changed) UpdateList();
+}
+
+UsbDeviceScanner::UsbDeviceScanner(TransportAdapterController* controller)
+ : controller_(controller) {
+ pthread_mutex_init(&devices_mutex_, 0);
+}
+
+UsbDeviceScanner::~UsbDeviceScanner() {
+ pthread_mutex_destroy(&devices_mutex_);
+}
+
+class AoaInitSequence::AoaGetProtocolRequest : public UsbControlInTransfer {
+ virtual ~AoaGetProtocolRequest() {}
+ virtual RequestType Type() const { return VENDOR; }
+ virtual uint8_t Request() const { return 51; }
+ virtual uint16_t Value() const { return 0; }
+ virtual uint16_t Index() const { return 0; }
+ virtual uint16_t Length() const { return 2; }
+ virtual bool OnCompleted(unsigned char* data) const {
+ const int protocol_version = data[1] << 8 | data[0];
+ LOG4CXX_INFO(logger_, "AOA protocol version " << protocol_version);
+ if (protocol_version == 0) {
+ // AOA protocol not supported
+ return false;
+ }
+ return true;
+ }
+};
+
+class AoaInitSequence::AoaSendIdString : public UsbControlOutTransfer {
+ public:
+ AoaSendIdString(uint16_t index, const char* string, uint16_t length)
+ : index_(index), string_(string), length_(length) {}
+
+ private:
+ virtual ~AoaSendIdString() {}
+ virtual RequestType Type() const { return VENDOR; }
+ virtual uint8_t Request() const { return 52; }
+ virtual uint16_t Value() const { return 0; }
+ virtual uint16_t Index() const { return index_; }
+ virtual uint16_t Length() const { return length_; }
+ virtual const char* Data() const { return string_; }
+ uint16_t index_;
+ const char* string_;
+ uint16_t length_;
+};
+
+class AoaInitSequence::AoaTurnIntoAccessoryMode : public UsbControlOutTransfer {
+ virtual ~AoaTurnIntoAccessoryMode() {}
+ virtual RequestType Type() const { return VENDOR; }
+ virtual uint8_t Request() const { return 53; }
+ virtual uint16_t Value() const { return 0; }
+ virtual uint16_t Index() const { return 0; }
+ virtual uint16_t Length() const { return 0; }
+ virtual const char* Data() const { return 0; }
+};
+
+static char manufacturer[] = "Ford";
+static char model_name[] = "HMI";
+static char description[] = "Human machine interface";
+static char version[] = "1.0";
+static char uri[] = "http://www.ford.com";
+static char serial_num[] = "N000000";
+
+AoaInitSequence::AoaInitSequence() : UsbControlTransferSequence() {
+ AddTransfer(new AoaGetProtocolRequest);
+ AddTransfer(new AoaSendIdString(0, manufacturer, sizeof(manufacturer)));
+ AddTransfer(new AoaSendIdString(1, model_name, sizeof(model_name)));
+ AddTransfer(new AoaSendIdString(2, description, sizeof(description)));
+ AddTransfer(new AoaSendIdString(3, version, sizeof(version)));
+ AddTransfer(new AoaSendIdString(4, uri, sizeof(uri)));
+ AddTransfer(new AoaSendIdString(5, serial_num, sizeof(serial_num)));
+ AddTransfer(new AoaTurnIntoAccessoryMode);
+}
+
+void UsbDeviceScanner::TurnIntoAccessoryMode(PlatformUsbDevice* device) {
+ LOG4CXX_INFO(logger_, "USB device VID:" << device->vendor_id()
+ << " PID:" << device->product_id()
+ << " turning into accessory mode");
+ GetUsbHandler()->StartControlTransferSequence(new AoaInitSequence, device);
+}
+
+void UsbDeviceScanner::GoogleAccessoryFound(PlatformUsbDevice* device) {
+ LOG4CXX_INFO(logger_, "Google accessory found");
+
+ pthread_mutex_lock(&devices_mutex_);
+ devices_.push_back(device);
+ pthread_mutex_unlock(&devices_mutex_);
+ LOG4CXX_INFO(logger_, "Google accessory (bus number "
+ << static_cast<int>(device->bus_number())
+ << ", address "
+ << static_cast<int>(device->address())
+ << ") identified as: " << device->GetManufacturer()
+ << ", " << device->GetProductName());
+ UpdateList();
+}
+
+TransportAdapter::Error UsbDeviceScanner::Init() {
+ return TransportAdapter::OK;
+}
+
+TransportAdapter::Error UsbDeviceScanner::Scan() {
+ return TransportAdapter::OK;
+}
+
+void UsbDeviceScanner::UpdateList() {
+ DeviceVector device_vector;
+ pthread_mutex_lock(&devices_mutex_);
+ for (Devices::const_iterator it = devices_.begin(); it != devices_.end();
+ ++it) {
+ const std::string device_name =
+ (*it)->GetManufacturer() + " " + (*it)->GetProductName();
+ std::ostringstream oss;
+ oss << (*it)->GetManufacturer() << ":" << (*it)->GetProductName() << ":"
+ << (*it)->GetSerialNumber() << ":"
+ << static_cast<int>((*it)->bus_number()) << ":"
+ << static_cast<int>((*it)->address());
+ const DeviceUID device_uid = oss.str();
+ DeviceSptr device(new UsbDevice(*it, device_name, device_uid));
+ device_vector.push_back(device);
+ }
+ pthread_mutex_unlock(&devices_mutex_);
+
+ LOG4CXX_INFO(logger_, "USB search done " << device_vector.size());
+ controller_->SearchDeviceDone(device_vector);
+}
+
+void UsbDeviceScanner::Terminate() {}
+
+bool UsbDeviceScanner::IsInitialised() const { return true; }
+
+} // namespace
+} // namespace