summaryrefslogtreecommitdiff
path: root/CDAL
diff options
context:
space:
mode:
authorKarin Hedlund <karin.hedlund@stericsson.com>2011-05-20 16:56:58 +0200
committerKarin Hedlund <karin.hedlund@stericsson.com>2011-05-20 16:56:58 +0200
commitb76c2437f1017bda4879a3a8ee6ddd00fdb5c281 (patch)
treefc3873776155e1d5ff021ae9370264d226893c69 /CDAL
Initial commit
Diffstat (limited to 'CDAL')
-rwxr-xr-xCDAL/AsyncCommunication.cpp177
-rwxr-xr-xCDAL/AsyncCommunication.h61
-rwxr-xr-xCDAL/CDAL.cpp223
-rwxr-xr-xCDAL/CDAL.h76
-rwxr-xr-xCDAL/CDAL.mk70
-rwxr-xr-xCDAL/CommDevice.cpp44
-rwxr-xr-xCDAL/CommDevice.h52
-rwxr-xr-xCDAL/CommDeviceManager.cpp56
-rwxr-xr-xCDAL/CommDeviceManager.h80
-rwxr-xr-xCDAL/CommException.cpp38
-rwxr-xr-xCDAL/CommException.h29
-rwxr-xr-xCDAL/Debug.h94
-rwxr-xr-xCDAL/LibusbDevice.cpp149
-rwxr-xr-xCDAL/LibusbDevice.h42
14 files changed, 1191 insertions, 0 deletions
diff --git a/CDAL/AsyncCommunication.cpp b/CDAL/AsyncCommunication.cpp
new file mode 100755
index 0000000..e767a61
--- /dev/null
+++ b/CDAL/AsyncCommunication.cpp
@@ -0,0 +1,177 @@
+/*
+ * AsyncCommunication.cpp
+ *
+ * Copyright (C) ST-Ericsson SA 2011
+ * Authors: Srimanta Panda <srimanta.panda@stericsson.com>,
+ * Ola Borgelin <ola.borgelin@stericsson.com>,
+ * Karin Hedlund <karin.hedlund@stericsson.com>,
+ * Markus Andersson <markus.m.andersson@stericsson.com> for ST-Ericsson.
+ * License terms: 3-clause BSD license
+ *
+ */
+
+#include "AsyncCommunication.h"
+#include "CommDevice.h"
+#include "Debug.h"
+
+AsyncCommunication::AsyncCommunication(CommDevice* device):
+ device_(device)
+{
+ isReadInvoked_ = false;
+ isWriteInvoked_ = false;
+
+ readRequest_.isActive = false;
+ readRequest_.isShutdown = false;
+ readRequest_.callback = NULL;
+
+ writeRequest_.isActive = false;
+ writeRequest_.isShutdown = false;
+ writeRequest_.callback = NULL;
+
+ readerThread_ = new Thread(AsyncCommunication::threadReadProc, this);
+ writerThread_ = new Thread(AsyncCommunication::threadWriteProc, this);
+}
+
+AsyncCommunication::~AsyncCommunication(void)
+{
+ readRequest_.isShutdown = true;
+ readRequestEvent_.signal();
+ writeRequest_.isShutdown = true;
+ writeRequestEvent_.signal();
+ readerThread_->wait();
+ writerThread_->wait();
+ delete readerThread_;
+ delete writerThread_;
+}
+
+int AsyncCommunication::readNoWait(void* buf, int len, DataCallback_t fn, void* param)
+{
+ int res = -1;
+ CSLock lock(&readCs_);
+
+ do {
+ if (readRequest_.isActive)
+ break;
+
+ readRequest_.buf = buf;
+ readRequest_.length = len;
+ readRequest_.isActive = true;
+ readRequest_.callback = fn;
+ readRequest_.param = param;
+ readRequestEvent_.signal();
+ res = 0;
+ } while (0);
+
+ return res;
+}
+
+int AsyncCommunication::writeNoWait(void* buf, int len, DataCallback_t fn, void* param)
+{
+ int res = -1;
+ CSLock lock(&writeCs_);
+
+ do {
+ if (writeRequest_.isActive)
+ break;
+
+ writeRequest_.buf = buf;
+ writeRequest_.length = len;
+ writeRequest_.isActive = true;
+ writeRequest_.callback = fn;
+ writeRequest_.param = param;
+ writeRequestEvent_.signal();
+ res = 0;
+ } while (0);
+
+ return res;
+}
+
+void* AsyncCommunication::threadReadProc(void* param)
+{
+ AsyncCommunication* asyncComm = (AsyncCommunication*)param;
+
+ while (1) {
+ asyncComm->readRequestEvent_.wait();
+
+ if (asyncComm->readRequest_.isShutdown) {
+ Debug::info("read thread: shutdown requested");
+ return 0;
+ }
+
+ asyncComm->readCs_.enter();
+ unsigned char* destBuf = static_cast<unsigned char*>(asyncComm->readRequest_.buf);
+ int length = asyncComm->readRequest_.length;
+ void* param = asyncComm->readRequest_.param;
+ DataCallback_t callback = asyncComm->readRequest_.callback;
+ asyncComm->readCs_.leave();
+
+ int readResult = asyncComm->device_->read(destBuf, length);
+
+ asyncComm->readCs_.enter();
+ asyncComm->readRequest_.isActive = false;
+ asyncComm->readCs_.leave();
+
+ if (readResult != CommDevice::COMM_DEVICE_SUCCESS) {
+ if (readResult == CommDevice::COMM_DEVICE_CANCEL) {
+ asyncComm->readCanceledEvent_.signal();
+ }
+
+ // if error occurs ignore the current request and wait for next one
+ // LCM should send the same request again after timeout
+ continue;
+ }
+
+ if (callback) {
+ Debug::hexdump("read", destBuf, length);
+ callback(destBuf, length, param);
+ }
+ }
+
+ return 0;
+}
+
+void* AsyncCommunication::threadWriteProc(void *param)
+{
+ AsyncCommunication* asyncComm = (AsyncCommunication*)param;
+
+ while (1) {
+ asyncComm->writeRequestEvent_.wait();
+
+ if (asyncComm->writeRequest_.isShutdown) {
+ Debug::info("write thread: shutdown requested");
+ return 0;
+ }
+
+ asyncComm->writeCs_.enter();
+ unsigned char* srcBuf = static_cast<unsigned char*>(asyncComm->writeRequest_.buf);
+ int len = asyncComm->writeRequest_.length;
+ void* localParam = asyncComm->writeRequest_.param;
+ DataCallback_t callback = asyncComm->writeRequest_.callback;
+ asyncComm->writeCs_.leave();
+
+ int writeResult = asyncComm->device_->write(srcBuf, len);
+
+ asyncComm->writeCs_.enter();
+ asyncComm->writeRequest_.isActive = false;
+ asyncComm->writeCs_.leave();
+
+ if (writeResult != CommDevice::COMM_DEVICE_SUCCESS) {
+ // if error occurs ignore the current request and wait for next one
+ // LCM should send the same request again after timeout
+ continue;
+ }
+
+ if (callback) {
+ Debug::hexdump("write", srcBuf, len);
+ callback(srcBuf, len, localParam);
+ }
+ }
+
+ return 0;
+}
+
+void AsyncCommunication::waitReadCanceled()
+{
+ readCanceledEvent_.wait();
+ Debug::info("AsyncCommunication waitReadCanceled finished");
+}
diff --git a/CDAL/AsyncCommunication.h b/CDAL/AsyncCommunication.h
new file mode 100755
index 0000000..36ce5c7
--- /dev/null
+++ b/CDAL/AsyncCommunication.h
@@ -0,0 +1,61 @@
+/*
+ * AsyncCommunication.h
+ *
+ * Copyright (C) ST-Ericsson SA 2011
+ * Authors: Srimanta Panda <srimanta.panda@stericsson.com>,
+ * Ola Borgelin <ola.borgelin@stericsson.com>,
+ * Karin Hedlund <karin.hedlund@stericsson.com>,
+ * Markus Andersson <markus.m.andersson@stericsson.com> for ST-Ericsson.
+ * License terms: 3-clause BSD license
+ *
+ */
+
+#pragma once
+
+#include "CDAL.h"
+#include "Event.h"
+#include "Thread.h"
+#include "CriticalSection.h"
+
+struct commRequest {
+ void* buf;
+ int length;
+ DataCallback_t callback;
+ void* param;
+ bool isShutdown;
+ bool isActive;
+};
+
+class AsyncCommunication
+{
+public:
+ AsyncCommunication(CommDevice* device);
+ ~AsyncCommunication();
+
+ int readNoWait(void* buf, int len, DataCallback_t fn, void* param);
+ int writeNoWait(void* buf, int len, DataCallback_t fn, void* param);
+
+ bool isReadActive() {
+ return readRequest_.isActive;
+ }
+ void waitReadCanceled();
+private:
+ CommDevice* device_;
+ bool isReadInvoked_;
+ bool isWriteInvoked_;
+
+ commRequest readRequest_;
+ CriticalSection readCs_;
+
+ commRequest writeRequest_;
+ CriticalSection writeCs_;
+
+ Thread* readerThread_;
+ static void* threadReadProc(void*);
+ Event readRequestEvent_;
+ Event readCanceledEvent_;
+
+ Thread* writerThread_;
+ static void* threadWriteProc(void*);
+ Event writeRequestEvent_;
+};
diff --git a/CDAL/CDAL.cpp b/CDAL/CDAL.cpp
new file mode 100755
index 0000000..24ded12
--- /dev/null
+++ b/CDAL/CDAL.cpp
@@ -0,0 +1,223 @@
+/*
+ * CDAL.cpp
+ *
+ * Copyright (C) ST-Ericsson SA 2011
+ * Authors: Srimanta Panda <srimanta.panda@stericsson.com>,
+ * Ola Borgelin <ola.borgelin@stericsson.com>,
+ * Karin Hedlund <karin.hedlund@stericsson.com>,
+ * Markus Andersson <markus.m.andersson@stericsson.com> for ST-Ericsson.
+ * License terms: 3-clause BSD license
+ *
+ */
+
+#include "CDAL.h"
+#include "Debug.h"
+#include "CommDevice.h"
+#include "CommDeviceManager.h"
+#include "CommException.h"
+#include "Event.h"
+#include "Thread.h"
+#include "LibusbDevice.h"
+#include <libusb.h>
+#include <vector>
+#include <stdio.h>
+#include <stdlib.h>
+using namespace std;
+
+static int DUT_VENDOR_ID = 0x04cc;
+static int DUT_PRODUCT_ID = 0x8500;
+static libusb_context* context;
+static Thread* workerThread;
+static void* LibusbWorker(void* arg);
+bool shutdown = false;
+int error = 0;
+
+static EventCallback_t OnDeviceCallback = NULL;
+
+void usb_init_driver(const char* vendorId, const char* productId)
+{
+ if (vendorId != NULL && *vendorId != '\0') {
+ DUT_VENDOR_ID = strtol(vendorId, NULL, 16);
+ }
+
+ if (productId != NULL && *productId != '\0') {
+ DUT_PRODUCT_ID = strtol(productId, NULL, 16);
+ }
+
+ libusb_init(&context);
+ libusb_set_debug(context, 3);
+
+ workerThread = new Thread(LibusbWorker, 0);
+}
+
+void usb_set_listen_callback(EventCallback_t callback)
+{
+ OnDeviceCallback = callback;
+}
+
+void usb_deinit_driver()
+{
+ shutdown = true;
+ workerThread->wait();
+ delete workerThread;
+
+ CommDeviceManager::destroyAll();
+
+ libusb_exit(context);
+}
+
+void usb_destroy_device(Device_t device, int error_code)
+{
+ device->cancel();
+ error = error_code;
+}
+
+int comm_read(Device_t device, void* buffer, size_t size)
+{
+ return device->read(buffer, size);
+}
+
+int comm_read_nowait(void* buffer, size_t size, DataCallback_t cb, void* param)
+{
+ CommDevice* device = CommDeviceManager::getDevice<CommDevice>(param);
+
+ if (NULL != device) {
+ return device->readNoWait(buffer, size, cb, param);
+ } else {
+ return COMM_DEVICE_OBJECT_NOT_MAPPED;
+ }
+}
+
+int comm_write(Device_t device, void* buffer, size_t size)
+{
+ return device->write(buffer, size);
+}
+
+int comm_write_nowait(void* buffer, size_t size, DataCallback_t cb, void* param)
+{
+ CommDevice* device = CommDeviceManager::getDevice<CommDevice>(param);
+
+ if (NULL != device) {
+ return device->writeNoWait(buffer, size, cb, param);
+ } else {
+ return COMM_DEVICE_OBJECT_NOT_MAPPED;
+ }
+}
+
+int comm_cancel(void* param)
+{
+ CommDevice* device = CommDeviceManager::getDevice<CommDevice>(param);
+
+ if (NULL != device) {
+ return device->cancel();
+ } else {
+ return COMM_DEVICE_OBJECT_NOT_MAPPED;
+ }
+}
+
+unsigned long comm_get_physical_address(Device_t device)
+{
+ return device->getPhysicalAddress();
+}
+
+void** comm_get_object_storage(Device_t device)
+{
+ return device->getObjectStorage();
+}
+
+void comm_progress(void *Communication_p, unsigned long long totalbytes,
+ unsigned long long tranferedbytes)
+{
+ double precentage = (tranferedbytes * 100) / totalbytes;
+
+ printf("\r%.1f %% ", precentage);
+ fflush(stdout);
+}
+
+static void* LibusbWorker(void* arg __attribute__((unused)))
+{
+ timespec delay;
+ delay.tv_sec = 0;
+ delay.tv_nsec = 10 * 1000000; // 10ms
+ libusb_device** deviceList;
+ ssize_t deviceCount;
+ libusb_device_descriptor descriptor;
+
+ while (!shutdown) {
+ deviceCount = libusb_get_device_list(context, &deviceList);
+
+ if (deviceCount < 0) {
+ nanosleep(&delay, 0);
+ continue;
+ }
+
+ for (int i = 0; i != deviceCount; ++i) {
+ int status = libusb_get_device_descriptor(deviceList[i],
+ &descriptor);
+
+ if (status != LIBUSB_SUCCESS) {
+ Debug::error(
+ "Libusb worker: error while getting device descriptor for device %d from %d devices",
+ i, deviceCount);
+ continue;
+ }
+
+ if (descriptor.idVendor == DUT_VENDOR_ID && descriptor.idProduct
+ == DUT_PRODUCT_ID && (!shutdown)) {
+ LibusbDevice* device = CommDeviceManager::getDevice <
+ LibusbDevice, libusb_device* > (deviceList[i]);
+
+ if (0 == device) {
+ // new device found
+ try {
+ device = CommDeviceManager::createDevice < LibusbDevice,
+ libusb_device* > (deviceList[i]);
+ Debug::info("Libusb worker: Connected libusb device");
+ OnDeviceCallback(COMM_DEVICE_SUCCESS,
+ LIBUSB_DEVICE_CONNECTED, device);
+ } catch (CommException e) {
+ Debug::error("Libusb worker: %s", e.what());
+ OnDeviceCallback(e.getError(),
+ COMM_DEVICE_UNDEFINED_EVENT, 0);
+ }
+ }
+ }
+ }
+
+ vector<CommDevice*> devices = CommDeviceManager::getAllDevices();
+
+ for (vector<CommDevice*>::iterator i = devices.begin(); i
+ != devices.end(); ++i) {
+ LibusbDevice* device = dynamic_cast<LibusbDevice*>(*i);
+
+ if (0 == device) {
+ continue;
+ }
+
+ bool connected = false;
+
+ for (int j = 0; j != deviceCount; ++j) {
+ if (deviceList[j] == device->getPort()) {
+ if (error == 0)
+ connected = true;
+
+ break;
+ }
+ }
+
+ if (!connected) {
+ Debug::info("Libusb worker: Disconnected device with id %d", *i);
+ OnDeviceCallback(COMM_DEVICE_SUCCESS,
+ LIBUSB_DEVICE_DISCONNECTED, *i);
+ shutdown = true;
+ }
+ }
+
+ libusb_free_device_list(deviceList, 1);
+
+ nanosleep(&delay, 0);
+ }
+
+ return 0;
+}
+
diff --git a/CDAL/CDAL.h b/CDAL/CDAL.h
new file mode 100755
index 0000000..d87b79b
--- /dev/null
+++ b/CDAL/CDAL.h
@@ -0,0 +1,76 @@
+/*
+ * CDAL.h
+ *
+ * Copyright (C) ST-Ericsson SA 2011
+ * Authors: Srimanta Panda <srimanta.panda@stericsson.com>,
+ * Ola Borgelin <ola.borgelin@stericsson.com>,
+ * Karin Hedlund <karin.hedlund@stericsson.com>,
+ * Markus Andersson <markus.m.andersson@stericsson.com> for ST-Ericsson.
+ * License terms: 3-clause BSD license
+ *
+ * CDAL API is implementation of communication device abstraction library,
+ * which adapts the usb driver interface. This device communication abstraction
+ * library is used to communicate with the device through the communication
+ * channel.
+ */
+#pragma once
+#include <cstddef>
+#ifdef CDAL_EXPORTS
+#define CDAL_API __attribute__((visibility("default")))
+#else
+#define CDAL_API
+#endif
+
+// type of the device
+typedef enum {
+ USB_DEVICE,
+ UART_DEVICE,
+ UNKNOWN_DEVICE
+} DeviceType_t;
+
+// error status codes
+typedef enum {
+ COMM_DEVICE_SUCCESS = 0,
+ COMM_DEVICE_GENERAL_ERROR = 1,
+ COMM_DEVICE_UNSUPPORTED_OPERATION = 2,
+ COMM_DEVICE_OBJECT_NOT_MAPPED = 3,
+ COMM_DEVICE_UART_FAILED_TO_OPEN_PORT = 4,
+ COMM_DEVICE_UART_FAILED_TO_CONFIGURE_PORT = 5,
+ COMM_DEVICE_LIBUSB_FAILED_TO_OPEN_PORT = 6,
+ COMM_DEVICE_LIBUSB_FAILED_TO_CLAIM_INTERFACE = 7,
+ COMM_DEVICE_PEEK_BUFFER_SIZE_ERROR = 8
+} DeviceStatus_t;
+
+// device events codes
+typedef enum {
+ COMM_DEVICE_UNDEFINED_EVENT = -1,
+ MEFLASH_DEVICE_CONNECTED = 0,
+ MEFLASH_DEVICE_DISCONNECTED = 1,
+ LIBUSB_DEVICE_CONNECTED = 2,
+ LIBUSB_DEVICE_DISCONNECTED = 3,
+ NOMADIK_DEVICE_CONNECTED = 4,
+ NOMADIK_DEVICE_DISCONNECTED = 5
+} DeviceEvent_t;
+
+typedef struct CommDevice* Device_t;
+
+// event and id parameters are valid only if status is 0 (COMM_DEVICE_SUCCESS)
+typedef void (*EventCallback_t)(DeviceStatus_t status, DeviceEvent_t event, Device_t id);
+
+typedef void (*DataCallback_t)(void* buffer, size_t len, void* param);
+
+extern "C" {
+ CDAL_API void usb_init_driver(const char* vendorID, const char* productID);
+ CDAL_API void usb_set_listen_callback(EventCallback_t callback);
+ CDAL_API void usb_deinit_driver();
+ CDAL_API void usb_destroy_device(Device_t device, int error_code);
+
+ CDAL_API int comm_read(Device_t device, void* buffer, size_t size);
+ CDAL_API int comm_read_nowait(void* buffer, size_t size, DataCallback_t cb, void* param);
+ CDAL_API int comm_write(Device_t device, void* buffer, size_t len);
+ CDAL_API int comm_write_nowait(void* buffer, size_t size, DataCallback_t cb, void* param);
+ CDAL_API int comm_cancel(void* param);
+ CDAL_API unsigned long comm_get_physical_address(Device_t device);
+ CDAL_API void** comm_get_object_storage(Device_t device);
+ CDAL_API void comm_progress(void *Communication_p, unsigned long long totalbytes, unsigned long long tranferedbytes);
+}
diff --git a/CDAL/CDAL.mk b/CDAL/CDAL.mk
new file mode 100755
index 0000000..e324b7d
--- /dev/null
+++ b/CDAL/CDAL.mk
@@ -0,0 +1,70 @@
+# Makefile - CDAL
+
+CXX=g++
+INCLUDE=-I../os_wrappers -fPIC -I/usr/include/libusb-1.0
+CFLAGS=-g $(INCLUDE)
+CXXFLAGS=$(CFLAGS)
+LIBS= -shared -lstdc++ -lusb-1.0
+LD=$(CXX) $(CXXFLAGS)
+
+ifndef TARGET
+TARGET=libcdal.so
+endif
+
+.PHONY: all
+all: $(TARGET)
+
+%.o: %.cpp
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -c $^
+
+SOURCE_FILES= \
+ ./AsyncCommunication.cpp \
+ ./CDAL.cpp \
+ ./CommDevice.cpp \
+ ./CommDeviceManager.cpp \
+ ./CommException.cpp \
+ ./LibusbDevice.cpp \
+ ../os_wrappers/CriticalSection.cpp \
+ ../os_wrappers/Event.cpp \
+ ../os_wrappers/Thread.cpp \
+
+HEADER_FILES= \
+ ./AsyncCommunication.h \
+ ./CDAL.h \
+ ./CommDevice.h \
+ ./CommDeviceManager.h \
+ ./CommException.h \
+ ./LibusbDevice.h \
+ ./Debug.h \
+ ../os_wrappers/CriticalSection.h \
+ ../os_wrappers/Event.h \
+ ../os_wrappers/Thread.h \
+ ../os_wrappers/Utilities.h
+
+OBJS= \
+ ./AsyncCommunication.o \
+ ./CDAL.o \
+ ./CommDevice.o \
+ ./CommDeviceManager.o \
+ ./CommException.o \
+ ./LibusbDevice.o \
+ ../os_wrappers/CriticalSection.o \
+ ../os_wrappers/Event.o \
+ ../os_wrappers/Thread.o \
+
+
+SRCS=$(SOURCE_FILES) $(HEADER_FILES)
+
+$(TARGET): $(OBJS)
+ $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+
+.PHONY: clean
+clean:
+ -rm -f -v $(OBJS) $(TARGET) CDAL.dep *.orig
+
+.PHONY: depends
+depends:
+ -$(CXX) $(CXXFLAGS) $(CPPFLAGS) -MM $(filter %.c %.cc %.cpp %.cxx,$(SRCS)) > CDAL.dep
+
+-include CDAL.dep
+
diff --git a/CDAL/CommDevice.cpp b/CDAL/CommDevice.cpp
new file mode 100755
index 0000000..d4c1f71
--- /dev/null
+++ b/CDAL/CommDevice.cpp
@@ -0,0 +1,44 @@
+/*
+ * CommDevice.cpp
+ *
+ * Copyright (C) ST-Ericsson SA 2011
+ * Authors: Srimanta Panda <srimanta.panda@stericsson.com>,
+ * Ola Borgelin <ola.borgelin@stericsson.com>,
+ * Karin Hedlund <karin.hedlund@stericsson.com>,
+ * Markus Andersson <markus.m.andersson@stericsson.com> for ST-Ericsson.
+ * License terms: 3-clause BSD license
+ *
+ */
+
+#include "CommDevice.h"
+#include "AsyncCommunication.h"
+
+CommDevice::CommDevice(): isReadCanceled_(false)
+{
+ async_ = new AsyncCommunication(this);
+}
+
+CommDevice::~CommDevice()
+{
+ delete async_;
+}
+
+int CommDevice::readNoWait(void *buffer, size_t size, DataCallback_t cb, void *param)
+{
+ return async_->readNoWait(buffer, size, cb, param);
+}
+
+int CommDevice::writeNoWait(void *buffer, size_t size, DataCallback_t cb, void *param)
+{
+ return async_->writeNoWait(buffer, size, cb, param);
+}
+
+int CommDevice::cancel()
+{
+ if (async_->isReadActive()) {
+ isReadCanceled_ = true;
+ async_->waitReadCanceled();
+ }
+
+ return 0;
+}
diff --git a/CDAL/CommDevice.h b/CDAL/CommDevice.h
new file mode 100755
index 0000000..98979fe
--- /dev/null
+++ b/CDAL/CommDevice.h
@@ -0,0 +1,52 @@
+/*
+ * CommDevice.h
+ *
+ * Copyright (C) ST-Ericsson SA 2011
+ * Authors: Srimanta Panda <srimanta.panda@stericsson.com>,
+ * Ola Borgelin <ola.borgelin@stericsson.com>,
+ * Karin Hedlund <karin.hedlund@stericsson.com>,
+ * Markus Andersson <markus.m.andersson@stericsson.com> for ST-Ericsson.
+ * License terms: 3-clause BSD license
+ *
+ */
+
+#pragma once
+
+#include "AsyncCommunication.h"
+#include "CDAL.h"
+#include <cstring>
+
+struct CommDevice {
+public:
+ enum Status {
+ COMM_DEVICE_SUCCESS,
+ COMM_DEVICE_CANCEL,
+ COMM_DEVICE_ERROR,
+ COMM_DEVICE_CLOSED
+ };
+
+ CommDevice();
+ virtual ~CommDevice();
+
+ virtual int read(void* buffer, size_t size) = 0;
+ int readNoWait(void* buffer, size_t size, DataCallback_t cb, void* param);
+
+ virtual int write(void* buffer, size_t size) = 0;
+ int writeNoWait(void* buffer, size_t size, DataCallback_t cb, void* param);
+
+ int cancel();
+
+ virtual unsigned long getPhysicalAddress() = 0;
+
+ void* getObject() {
+ return object_;
+ }
+ void** getObjectStorage() {
+ return &object_;
+ }
+protected:
+ bool isReadCanceled_;
+private:
+ void* object_;
+ AsyncCommunication* async_;
+};
diff --git a/CDAL/CommDeviceManager.cpp b/CDAL/CommDeviceManager.cpp
new file mode 100755
index 0000000..bd94651
--- /dev/null
+++ b/CDAL/CommDeviceManager.cpp
@@ -0,0 +1,56 @@
+/*
+ * CommDeviceManager.cpp
+ *
+ * Copyright (C) ST-Ericsson SA 2011
+ * Authors: Srimanta Panda <srimanta.panda@stericsson.com>,
+ * Ola Borgelin <ola.borgelin@stericsson.com>,
+ * Karin Hedlund <karin.hedlund@stericsson.com>,
+ * Markus Andersson <markus.m.andersson@stericsson.com> for ST-Ericsson.
+ * License terms: 3-clause BSD license
+ *
+ */
+
+#include "CommDeviceManager.h"
+#include "CommDevice.h"
+#include "CommException.h"
+#include "Debug.h"
+#include <vector>
+using namespace std;
+
+vector<CommDevice*> CommDeviceManager::devices_;
+
+const vector<CommDevice*>& CommDeviceManager::getAllDevices()
+{
+ return devices_;
+}
+
+void CommDeviceManager::destroyDevice(CommDevice* device)
+{
+ if (0 == device) {
+ return;
+ }
+
+ vector<CommDevice*>::iterator i = devices_.begin();
+
+ while (i != devices_.end()) {
+ if (device == *i) {
+ delete device;
+ break;
+ }
+
+ ++i;
+ }
+
+ if (i != devices_.end()) {
+ devices_.erase(i);
+ }
+}
+
+void CommDeviceManager::destroyAll()
+{
+ for (vector<CommDevice*>::iterator i = devices_.begin(); i != devices_.end(); ++i) {
+ delete *i;
+ }
+
+ devices_.clear();
+}
diff --git a/CDAL/CommDeviceManager.h b/CDAL/CommDeviceManager.h
new file mode 100755
index 0000000..fef36de
--- /dev/null
+++ b/CDAL/CommDeviceManager.h
@@ -0,0 +1,80 @@
+/*
+ * CommDeviceManager.h
+ *
+ * Copyright (C) ST-Ericsson SA 2011
+ * Authors: Srimanta Panda <srimanta.panda@stericsson.com>,
+ * Ola Borgelin <ola.borgelin@stericsson.com>,
+ * Karin Hedlund <karin.hedlund@stericsson.com>,
+ * Markus Andersson <markus.m.andersson@stericsson.com> for ST-Ericsson.
+ * License terms: 3-clause BSD license
+ *
+ */
+
+#pragma once
+
+#include "CDAL.h"
+#include "CommDevice.h"
+#include <vector>
+#include <libusb.h>
+
+class CommDeviceManager
+{
+public:
+ static const std::vector<CommDevice*>& getAllDevices();
+
+ static void destroyDevice(CommDevice* device);
+ static void destroyAll();
+
+ template <class T, class U>
+ static T* createDevice(U port) {
+ T* device = new T(port);
+
+ T* existingDevice = dynamic_cast<T*>(getDevice<T>(port));
+
+ if (0 != existingDevice) {
+ destroyDevice(existingDevice);
+ }
+
+ devices_.push_back(device);
+
+ return device;
+ }
+
+ template <class T, class U>
+ static T* getDevice(U port) {
+ T* device;
+
+ for (std::vector<CommDevice*>::iterator i = devices_.begin(); i != devices_.end(); ++i) {
+ device = dynamic_cast<T*>(*i);
+
+ if (0 != device && device->getPort() == port) {
+ return device;
+ }
+ }
+
+ return 0;
+ }
+
+
+private:
+ static std::vector<CommDevice*> devices_;
+private:
+ CommDeviceManager() {}
+ CommDeviceManager(const CommDeviceManager&) {}
+ ~CommDeviceManager() {}
+};
+
+// template specialization used to get device for LCD object mapping
+template <>
+inline CommDevice* CommDeviceManager::getDevice<CommDevice, void*>(void* object)
+{
+ for (std::vector<CommDevice*>::iterator i = devices_.begin(); i != devices_.end(); ++i) {
+ if ((*i)->getObject() == object) {
+ return *i;
+ }
+ }
+
+ return 0;
+}
+
+
diff --git a/CDAL/CommException.cpp b/CDAL/CommException.cpp
new file mode 100755
index 0000000..4485cba
--- /dev/null
+++ b/CDAL/CommException.cpp
@@ -0,0 +1,38 @@
+/*
+ * CommException.cpp
+ *
+ * Copyright (C) ST-Ericsson SA 2011
+ * Authors: Srimanta Panda <srimanta.panda@stericsson.com>,
+ * Ola Borgelin <ola.borgelin@stericsson.com>,
+ * Karin Hedlund <karin.hedlund@stericsson.com>,
+ * Markus Andersson <markus.m.andersson@stericsson.com> for ST-Ericsson.
+ * License terms: 3-clause BSD license
+ *
+ */
+
+#include "CommException.h"
+#include <stdexcept>
+#include <sstream>
+using namespace std;
+
+CommException::CommException(const string& message, DeviceStatus_t error):
+ runtime_error(message), error_(error)
+{
+}
+
+CommException::~CommException() throw()
+{
+}
+
+const char* CommException::what()
+{
+ ostringstream message;
+ message << this->runtime_error::what() << " " << error_;
+ message_ = message.str();
+ return message_.c_str();
+}
+
+DeviceStatus_t CommException::getError()
+{
+ return error_;
+}
diff --git a/CDAL/CommException.h b/CDAL/CommException.h
new file mode 100755
index 0000000..fc4d576
--- /dev/null
+++ b/CDAL/CommException.h
@@ -0,0 +1,29 @@
+/*
+ * CommException.h
+ *
+ * Copyright (C) ST-Ericsson SA 2011
+ * Authors: Srimanta Panda <srimanta.panda@stericsson.com>,
+ * Ola Borgelin <ola.borgelin@stericsson.com>,
+ * Karin Hedlund <karin.hedlund@stericsson.com>,
+ * Markus Andersson <markus.m.andersson@stericsson.com> for ST-Ericsson.
+ * License terms: 3-clause BSD license
+ *
+ */
+
+#pragma once
+
+#include "CDAL.h"
+#include <stdexcept>
+#include <string>
+
+class CommException : public std::runtime_error
+{
+public:
+ CommException(const std::string& message, DeviceStatus_t error);
+ virtual ~CommException() throw();
+ virtual const char* what();
+ DeviceStatus_t getError();
+private:
+ DeviceStatus_t error_;
+ std::string message_;
+};
diff --git a/CDAL/Debug.h b/CDAL/Debug.h
new file mode 100755
index 0000000..69e5112
--- /dev/null
+++ b/CDAL/Debug.h
@@ -0,0 +1,94 @@
+/*
+ * Debug.h
+ *
+ * Copyright (C) ST-Ericsson SA 2011
+ * Authors: Srimanta Panda <srimanta.panda@stericsson.com>,
+ * Ola Borgelin <ola.borgelin@stericsson.com>,
+ * Karin Hedlund <karin.hedlund@stericsson.com>,
+ * Markus Andersson <markus.m.andersson@stericsson.com> for ST-Ericsson.
+ * License terms: 3-clause BSD license
+ *
+ */
+
+#pragma once
+
+//#define _DEBUG
+#ifdef _DEBUG
+#define DEBUG_INFO
+#define DEBUG_ERROR
+#define DEBUG_HEXDUMP
+#define DEBUG_HEXDUMP_SIZE 1024
+#endif
+
+#ifdef _WIN32
+#define flockfile _lock_file
+#define funlockfile _unlock_file
+#else
+#include <cstddef>
+#endif
+
+#if defined(DEBUG_ERROR) || defined(DEBUG_INFO) || defined(DEBUG_HEXDUMP)
+#include <cstdio>
+#include <cstdarg>
+#endif
+
+class Debug
+{
+public:
+ inline static void error(const char* format, ...) __attribute__((format(printf, 1, 0))) {
+#ifdef DEBUG_ERROR
+ flockfile(stdout);
+ printf("ERROR - ");
+ va_list args;
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+ printf("\n");
+ fflush(stdout);
+ funlockfile(stdout);
+#endif
+ }
+
+ static inline void info(const char* format, ...) __attribute__((format(printf, 1, 0))) {
+#ifdef DEBUG_INFO
+ flockfile(stdout);
+ printf("INFO - ");
+ va_list args;
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+ printf("\n");
+ fflush(stdout);
+ funlockfile(stdout);
+#endif
+ }
+
+ inline static void hexdump(const char* message, unsigned char* buffer, size_t length) {
+#ifdef DEBUG_HEXDUMP
+ flockfile(stdout);
+ printf("%s (%d):\n", message, length);
+ size_t printLength = length < DEBUG_HEXDUMP_SIZE ? length : DEBUG_HEXDUMP_SIZE;
+
+ for (size_t i = 0; i < printLength; i++) {
+ printf("%02x ", buffer[i]);
+
+ if ((i + 1) % 16 == 0 && (i + 1) < printLength)
+ printf("\n");
+ }
+
+ printf("\n");
+
+ if (printLength != length) {
+ printf("%d bytes more...\n", length - printLength);
+ }
+
+ printf("\n");
+ fflush(stdout);
+ funlockfile(stdout);
+#endif
+ }
+private:
+ Debug() {}
+ ~Debug() {}
+ Debug(const Debug&) {}
+};
diff --git a/CDAL/LibusbDevice.cpp b/CDAL/LibusbDevice.cpp
new file mode 100755
index 0000000..337df46
--- /dev/null
+++ b/CDAL/LibusbDevice.cpp
@@ -0,0 +1,149 @@
+/*
+ * LibusbDevice.cpp
+ *
+ * Copyright (C) ST-Ericsson SA 2011
+ * Authors: Srimanta Panda <srimanta.panda@stericsson.com>,
+ * Ola Borgelin <ola.borgelin@stericsson.com>,
+ * Karin Hedlund <karin.hedlund@stericsson.com>,
+ * Markus Andersson <markus.m.andersson@stericsson.com> for ST-Ericsson.
+ * License terms: 3-clause BSD license
+ *
+ */
+
+#include "LibusbDevice.h"
+#include "Debug.h"
+#include "CommException.h"
+#include <libusb.h>
+
+using namespace std;
+
+#define MIN(A, B) ((A) < (B) ? (A) : (B))
+
+LibusbDevice::LibusbDevice(libusb_device* device): device_(device)
+{
+ int status = libusb_open(device_, &handle_);
+
+ if (status != LIBUSB_SUCCESS) {
+ throw CommException("failed to open usb device", COMM_DEVICE_LIBUSB_FAILED_TO_OPEN_PORT);
+ }
+
+ status = libusb_claim_interface(handle_, 0);
+
+ if (status != LIBUSB_SUCCESS) {
+ libusb_close(handle_);
+ throw CommException("failed to claim device interface", COMM_DEVICE_LIBUSB_FAILED_TO_CLAIM_INTERFACE);
+ }
+
+ libusb_config_descriptor* config;
+ libusb_get_active_config_descriptor(device, &config);
+ Debug::info("LibusbDevice: found %d endpoints", config->interface->altsetting->bNumEndpoints);
+
+ for (int i = 0; i != config->interface->altsetting->bNumEndpoints; ++i) {
+ if (config->interface->altsetting->endpoint[i].bEndpointAddress & LIBUSB_ENDPOINT_IN) {
+ inEndpoint_ = config->interface->altsetting->endpoint[i].bEndpointAddress;
+ Debug::info("LibusbDevice: in endpoint set to 0x%02x", inEndpoint_);
+ } else {
+ outEndpoint_ = config->interface->altsetting->endpoint[i].bEndpointAddress;
+ Debug::info("LibusbDevice: out endpoint set to 0x%02x", outEndpoint_);
+ }
+ }
+
+ libusb_free_config_descriptor(config);
+
+ libusb_get_device_descriptor(device, &descriptor_);
+
+ readBufferLength_ = 0;
+ readBufferHead_ = readBuffer_;
+}
+
+LibusbDevice::~LibusbDevice()
+{
+ libusb_release_interface(handle_, 0);
+ libusb_close(handle_);
+}
+
+int LibusbDevice::read(void *buffer, size_t size)
+{
+ Debug::info("LibusbDevice read: called with size %d", size);
+ unsigned char* dest = static_cast<unsigned char*>(buffer);
+
+ while (true) {
+ if (readBufferLength_) {
+ size_t toCopy = MIN(readBufferLength_, size);
+ memcpy(dest, readBufferHead_, toCopy);
+ dest += toCopy;
+ size -= toCopy;
+ readBufferLength_ -= toCopy;
+
+ if (readBufferLength_ != 0) {
+ readBufferHead_ += toCopy;
+ } else {
+ readBufferHead_ = readBuffer_;
+ }
+ }
+
+ if (size == 0) {
+ break;
+ }
+
+ int transfered;
+ int error = libusb_bulk_transfer(handle_, inEndpoint_, readBuffer_, READ_BUFFER_SIZE, &transfered, 100000);
+
+ if (isReadCanceled_) {
+ Debug::info("LibusbDevice read: canceled...");
+ Debug::hexdump("read canceled", dest, transfered);
+ isReadCanceled_ = false;
+ return COMM_DEVICE_CANCEL;
+ }
+
+ if (error) {
+ if (error == LIBUSB_ERROR_TIMEOUT) {
+ continue;
+ } else {
+ Debug::info("LibusbDevice read: error %d occured", error);
+ return error;
+ }
+ }
+
+ readBufferLength_ = transfered;
+ }
+
+ Debug::info("LibusbDevice read: complete");
+ return 0;
+}
+
+int LibusbDevice::write(void *buffer, size_t size)
+{
+ Debug::info("LibusbDevice write: called with size %d", size);
+ unsigned char* src = static_cast<unsigned char*>(buffer);
+
+ while (size) {
+ int transfered;
+ //Call with timeout to enable possible cancel
+ int error = libusb_bulk_transfer(handle_, outEndpoint_, src, size, &transfered, 0);
+
+ if (error) {
+ if (error == LIBUSB_ERROR_TIMEOUT) {
+ continue;
+ } else {
+ return error;
+ }
+ }
+
+ size -= transfered;
+ src += transfered;
+ }
+
+ Debug::info("LibusbDevice write: complete");
+ return 0;
+}
+
+int LibusbDevice::getVendorId()
+{
+ return descriptor_.idVendor;
+}
+
+libusb_device* LibusbDevice::getPort()
+{
+ return device_;
+}
diff --git a/CDAL/LibusbDevice.h b/CDAL/LibusbDevice.h
new file mode 100755
index 0000000..1865605
--- /dev/null
+++ b/CDAL/LibusbDevice.h
@@ -0,0 +1,42 @@
+/*
+ * LibusbDevice.h
+ *
+ * Copyright (C) ST-Ericsson SA 2011
+ * Authors: Srimanta Panda <srimanta.panda@stericsson.com>,
+ * Ola Borgelin <ola.borgelin@stericsson.com>,
+ * Karin Hedlund <karin.hedlund@stericsson.com>,
+ * Markus Andersson <markus.m.andersson@stericsson.com> for ST-Ericsson.
+ * License terms: 3-clause BSD license
+ *
+ */
+
+#pragma once
+#include <libusb.h>
+#include "CommDevice.h"
+
+class LibusbDevice : public CommDevice
+{
+public:
+ LibusbDevice(libusb_device* device);
+ ~LibusbDevice();
+
+ int read(void* buffer, size_t size);
+ int write(void* buffer, size_t size);
+
+ int getVendorId();
+ libusb_device* getPort();
+
+ unsigned long getPhysicalAddress() {
+ return 0;
+ }
+private:
+ libusb_device* device_;
+ libusb_device_handle* handle_;
+ libusb_device_descriptor descriptor_;
+ int outEndpoint_;
+ int inEndpoint_;
+ static const int READ_BUFFER_SIZE = 4096;
+ unsigned char readBuffer_[READ_BUFFER_SIZE];
+ unsigned char* readBufferHead_;
+ size_t readBufferLength_;
+};