From b76c2437f1017bda4879a3a8ee6ddd00fdb5c281 Mon Sep 17 00:00:00 2001 From: Karin Hedlund Date: Fri, 20 May 2011 16:56:58 +0200 Subject: Initial commit --- .gitignore | 15 ++ CDAL/AsyncCommunication.cpp | 177 ++++++++++++++++ CDAL/AsyncCommunication.h | 61 ++++++ CDAL/CDAL.cpp | 223 ++++++++++++++++++++ CDAL/CDAL.h | 76 +++++++ CDAL/CDAL.mk | 70 +++++++ CDAL/CommDevice.cpp | 44 ++++ CDAL/CommDevice.h | 52 +++++ CDAL/CommDeviceManager.cpp | 56 +++++ CDAL/CommDeviceManager.h | 80 +++++++ CDAL/CommException.cpp | 38 ++++ CDAL/CommException.h | 29 +++ CDAL/Debug.h | 94 +++++++++ CDAL/LibusbDevice.cpp | 149 +++++++++++++ CDAL/LibusbDevice.h | 42 ++++ LICENSE | 25 +++ Makefile | 72 +++++++ README | 111 ++++++++++ config/riff.config | 32 +++ doc/man/man1 | 84 ++++++++ os_wrappers/CriticalSection.cpp | 66 ++++++ os_wrappers/CriticalSection.h | 82 ++++++++ os_wrappers/Event.cpp | 56 +++++ os_wrappers/Event.h | 66 ++++++ os_wrappers/Thread.cpp | 68 ++++++ os_wrappers/Thread.h | 73 +++++++ os_wrappers/Utilities.h | 57 +++++ packages/control | 9 + riff/Command.h | 52 +++++ riff/Config.cpp | 95 +++++++++ riff/Config.h | 76 +++++++ riff/DUT.cpp | 115 ++++++++++ riff/DUT.h | 123 +++++++++++ riff/DumpArea.cpp | 73 +++++++ riff/DumpArea.h | 67 ++++++ riff/DutManager.cpp | 65 ++++++ riff/DutManager.h | 63 ++++++ riff/EraseArea.cpp | 50 +++++ riff/EraseArea.h | 56 +++++ riff/InitializeDut.cpp | 452 ++++++++++++++++++++++++++++++++++++++++ riff/InitializeDut.h | 85 ++++++++ riff/Logger.cpp | 85 ++++++++ riff/Logger.h | 85 ++++++++ riff/ProcessRawImage.cpp | 79 +++++++ riff/ProcessRawImage.h | 61 ++++++ riff/SequenceFactory.cpp | 105 ++++++++++ riff/SequenceFactory.h | 92 ++++++++ riff/Shutdown.cpp | 47 +++++ riff/Shutdown.h | 50 +++++ riff/constants.h | 29 +++ riff/main.cpp | 240 +++++++++++++++++++++ riff/main.h | 75 +++++++ riff/riff.mk | 85 ++++++++ 53 files changed, 4412 insertions(+) create mode 100644 .gitignore create mode 100755 CDAL/AsyncCommunication.cpp create mode 100755 CDAL/AsyncCommunication.h create mode 100755 CDAL/CDAL.cpp create mode 100755 CDAL/CDAL.h create mode 100755 CDAL/CDAL.mk create mode 100755 CDAL/CommDevice.cpp create mode 100755 CDAL/CommDevice.h create mode 100755 CDAL/CommDeviceManager.cpp create mode 100755 CDAL/CommDeviceManager.h create mode 100755 CDAL/CommException.cpp create mode 100755 CDAL/CommException.h create mode 100755 CDAL/Debug.h create mode 100755 CDAL/LibusbDevice.cpp create mode 100755 CDAL/LibusbDevice.h create mode 100644 LICENSE create mode 100755 Makefile create mode 100755 README create mode 100755 config/riff.config create mode 100755 doc/man/man1 create mode 100755 os_wrappers/CriticalSection.cpp create mode 100755 os_wrappers/CriticalSection.h create mode 100755 os_wrappers/Event.cpp create mode 100755 os_wrappers/Event.h create mode 100755 os_wrappers/Thread.cpp create mode 100755 os_wrappers/Thread.h create mode 100755 os_wrappers/Utilities.h create mode 100755 packages/control create mode 100755 riff/Command.h create mode 100755 riff/Config.cpp create mode 100755 riff/Config.h create mode 100755 riff/DUT.cpp create mode 100755 riff/DUT.h create mode 100755 riff/DumpArea.cpp create mode 100755 riff/DumpArea.h create mode 100755 riff/DutManager.cpp create mode 100755 riff/DutManager.h create mode 100755 riff/EraseArea.cpp create mode 100755 riff/EraseArea.h create mode 100755 riff/InitializeDut.cpp create mode 100755 riff/InitializeDut.h create mode 100755 riff/Logger.cpp create mode 100755 riff/Logger.h create mode 100755 riff/ProcessRawImage.cpp create mode 100755 riff/ProcessRawImage.h create mode 100755 riff/SequenceFactory.cpp create mode 100755 riff/SequenceFactory.h create mode 100755 riff/Shutdown.cpp create mode 100755 riff/Shutdown.h create mode 100755 riff/constants.h create mode 100755 riff/main.cpp create mode 100755 riff/main.h create mode 100755 riff/riff.mk diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..71095c3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +.project +.cproject +LCD/liblcdriver.so +LCD/liblcdriver_x64.so +CDAL/core +CDAL/libcdal.so +riff/core +riff/riff +core +*~ +*.o +*.BASE.*.txt +*.BACKUP.*.txt +*.REMOTE.*.txt +*.orig 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 , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson 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(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(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 , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson 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 , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson 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 +#include +#include +#include +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(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(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(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 devices = CommDeviceManager::getAllDevices(); + + for (vector::iterator i = devices.begin(); i + != devices.end(); ++i) { + LibusbDevice* device = dynamic_cast(*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 , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson 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 +#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 , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson 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 , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +#pragma once + +#include "AsyncCommunication.h" +#include "CDAL.h" +#include + +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 , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +#include "CommDeviceManager.h" +#include "CommDevice.h" +#include "CommException.h" +#include "Debug.h" +#include +using namespace std; + +vector CommDeviceManager::devices_; + +const vector& CommDeviceManager::getAllDevices() +{ + return devices_; +} + +void CommDeviceManager::destroyDevice(CommDevice* device) +{ + if (0 == device) { + return; + } + + vector::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::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 , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +#pragma once + +#include "CDAL.h" +#include "CommDevice.h" +#include +#include + +class CommDeviceManager +{ +public: + static const std::vector& getAllDevices(); + + static void destroyDevice(CommDevice* device); + static void destroyAll(); + + template + static T* createDevice(U port) { + T* device = new T(port); + + T* existingDevice = dynamic_cast(getDevice(port)); + + if (0 != existingDevice) { + destroyDevice(existingDevice); + } + + devices_.push_back(device); + + return device; + } + + template + static T* getDevice(U port) { + T* device; + + for (std::vector::iterator i = devices_.begin(); i != devices_.end(); ++i) { + device = dynamic_cast(*i); + + if (0 != device && device->getPort() == port) { + return device; + } + } + + return 0; + } + + +private: + static std::vector devices_; +private: + CommDeviceManager() {} + CommDeviceManager(const CommDeviceManager&) {} + ~CommDeviceManager() {} +}; + +// template specialization used to get device for LCD object mapping +template <> +inline CommDevice* CommDeviceManager::getDevice(void* object) +{ + for (std::vector::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 , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +#include "CommException.h" +#include +#include +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 , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +#pragma once + +#include "CDAL.h" +#include +#include + +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 , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson 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 +#endif + +#if defined(DEBUG_ERROR) || defined(DEBUG_INFO) || defined(DEBUG_HEXDUMP) +#include +#include +#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 , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +#include "LibusbDevice.h" +#include "Debug.h" +#include "CommException.h" +#include + +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(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(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 , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +#pragma once +#include +#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_; +}; diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f7a800f --- /dev/null +++ b/LICENSE @@ -0,0 +1,25 @@ + +Copyright (c) 2011, ST-Ericsson S.A. +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 ST-Ericsson S.A. 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 ST-ERICSSON S.A. 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. diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..52c9e49 --- /dev/null +++ b/Makefile @@ -0,0 +1,72 @@ +# Makefile - riff + +.PHONY: all +all: \ + CDAL \ + riff + + +.PHONY: riff +riff: CDAL + cd riff/ && $(MAKE) -f riff.mk + +.PHONY: CDAL +CDAL: + cd CDAL/ && $(MAKE) -f CDAL.mk + +.PHONY: clean +clean: + cd riff/ && $(MAKE) -f riff.mk clean + cd CDAL/ && $(MAKE) -f CDAL.mk clean + rm -f packages/riff.deb + +.PHONY: depends +depends: + cd riff/ && $(MAKE) -f riff.mk depends + cd CDAL/ && $(MAKE) -f CDAL.mk depends + cd CDAL/ && $(MAKE) -f CDAL.mk depends + +.PHONY: debian +debian: clean all + mkdir -p debian/DEBIAN + mkdir -p debian/usr/bin + mkdir -p debian/usr/lib + mkdir -p debian/usr/share/doc/riff + mkdir -p debian/usr/share/man/man1 + mkdir doc/man/temp + nroff -man doc/man/man1 > doc/man/temp/riff.1 + gzip doc/man/temp/riff.1 + + cp packages/control debian/DEBIAN/ + cp riff/riff debian/usr/bin/ + cp LICENSE debian/usr/share/doc/riff/ + cp README debian/usr/share/doc/riff/ + + cp CDAL/libcdal.so debian/usr/lib/ + cp -r doc/man/temp/riff.1.gz debian/usr/share/man/man1 + + dpkg-deb --build debian packages/riff.deb || error + rm -rf debian + rm -rf doc/man/temp + +.PHONY: install +install: clean all + mv riff/riff /usr/bin/riff + mv CDAL/libcdal.so /usr/lib/libcdal.so + mkdir /usr/share/riff + mkdir /usr/share/riff/snowball + cp config/riff.config /usr/share/riff/snowball/config + ln -s /usr/share/riff/snowball/config /usr/share/riff + mkdir doc/man/temp + nroff -man doc/man/man1 > doc/man/temp/riff.1 + gzip doc/man/temp/riff.1 + cp -r doc/man/temp/riff.1.gz /usr/share/man/man1 + rm -rf doc/man/temp + +.PHONY: uninstall +uninstall: clean + rm /usr/bin/riff + rm /usr/lib/libcdal.so + rm -rf /usr/share/riff + rm /usr/share/man/man1/riff.1.gz + diff --git a/README b/README new file mode 100755 index 0000000..3963a4d --- /dev/null +++ b/README @@ -0,0 +1,111 @@ +riff - Raw Image File Flasher version 0.4.0 + +================================================================================= +Description: +================================================================================= +A tool for flashing a device. + +================================================================================= +Hardware and software requirements: +================================================================================= +NOTE that building the tool requires the following packages to be installed: + +libusb-dev-1.0-0 +riff-loadercomm +riff-configpack + +NOTE: To use riff on internal development board riff-configpack-internal also +needs to be installed. To use internal config pack instead of default create a +symlink to /usr/share/riff/snowball_internal/config in $HOME/.riff/config +$ ln -s /usr/share/riff/snowball_internal/config $HOME/.riff/config + +================================================================================= +Usage: +================================================================================= + +$ sudo make install + +Will build from source and put the binary and lib in /usr/bin/share and /usr/lib/ +respectively. It's then possible to run riff from anywhere. + +## Configuration file ## +A template config file is provided in the source tree as config/riff.config +It will be renamed and placed in /usr/share/riff/ +when using the make install target. + +This file can be overridden with a user-specific config file placed in +$HOME/.riff, or by providing a full path to a config file at +runtime, as option on the command line (using the -c option). + +riff will look for configuration file to use in the following order: +1) Config file provided on command line (using the -c option) at runtime. +2) Config file in user's home directory ($HOME/.riff/config) +3) /usr/share/riff + + +## Running ## + +Usage: riff [OPTION]...[FILE]... + + Available command line arguments are: + + -h, --help Display this help message. + -m, --mode ACTION Select the mode. + ACTION is `flash` or `erase` + -c, --config PATH Give path to configuration file. + -f, --flashimage IMAGEPATH Give path to flashimage. + -a, --address FLASHADDR Give a start address in hex. + -l, --length HEXLENGTH Length of the dump [Byte] in hex. + -d, --dumppath DUMPPATH File path on PC where to store dump. + -v, --verbose Shows more detailed information. + --version Shows version information. + +Examples: + +$ riff -f + +Default mode 'flash' will be used, and configuration originally from config/riff.config +but put in /usr/share/riff will be used (if the user hasn't overridden this file +by its own in $HOME/.riff/config). +The flashimage at the provided path will be flashed onto the device starting at address 0. + +To start at any other address than 0, use + +$ riff -f -a
+ +WARNING: +NOTE THAT RIFF HAS NO WAY OF KNOWING WHETHER YOU ARE OVERWRITING IMPORTANT +SECTIONS ON YOUR DEVICE OR NOT WHEN FLASHING! THE TOOL DOES NOT WARN YOU OR +PREVENT YOU FROM PROVIDING ANY ADDRESS TO FLASH TO. +In other words: it's up to you to know what you're doing, the tool takes no +responsibility for it! + +Path to flashimage can also be specified in the config file and the -f flag +can then be omitted. + + +Build from source without installing: +$ make + +riff binary ends up in riff directory. To run, libcdal (located in CDAL +directory) must be then be added to your LD_LIBRARY_PATH. + +================================================================================= +Known issues: +================================================================================= +1) Linux can't find device. +Power down device and disconnect and reconnect USB cable. +Restart the flash tool and power up the device. + +================================================================================= +Version history and changelog: +================================================================================= +0.3.0 Initial version. +0.4.0 Dump functionality added. +0.4.1 Packaging and README updated + +================================================================================= +Contact and support +================================================================================= +http://igloocommunity.org/support + diff --git a/config/riff.config b/config/riff.config new file mode 100755 index 0000000..678cdff --- /dev/null +++ b/config/riff.config @@ -0,0 +1,32 @@ +#Configuration file. +#Please set the correct paths below. + +# Path to ISSW +!set ISSWPATH /usr/share/riff/snowball/boot_image_issw.bin + +# Path to XLOADER +!set XLOADERPATH /usr/share/riff/snowball/boot_image_x-loader.bin + +# Path to PRCMU +!set PWRMGMTPATH /usr/share/riff/snowball/power_management.bin + +# Path to MEMINIT +!set MEMINITPATH /usr/share/riff/snowball/mem_init.bin + +# Path to LOADER +!set NORMALPATH /usr/share/riff/snowball/loader_v2.bin + +# Vendor ID +!set VENDORID 0x04cc + +# Product ID +!set PRODUCTID 0x8500 + +# Path to LCM library +!set LCMLIBPATH /usr/lib/liblcm.so.1 + +# Path to flash image +#!set FLASH_IMG_PATH /path_to_image + + + diff --git a/doc/man/man1 b/doc/man/man1 new file mode 100755 index 0000000..6b3c14d --- /dev/null +++ b/doc/man/man1 @@ -0,0 +1,84 @@ +.TH riff 1 + + +.SH NAME + riff - Raw Image File Flasher + +.SH SYNOPSIS +.B riff [OPTION]...[FILE]... + + +.SH DESCRIPTION +.br +riff flashes a device with a raw image file. + + +.SH OPTIONS +.B -h, --help +.br +Prints a breif description of the command-line options. + +.B -m ACTION, --mode ACTION +.br +Use ACTION to select flash or erase mode. + +.B -c PATH, --config PATH +.br +Give path to the configuration file. + +.B -f IMAGEPATH, --flashimage IMAGEPATH +.br +Give path the flashimage. + +.B -a FLASHADDR, --address FLASHADDR +.br +Give a start address in hex. + +.B -l HEXLENGTH, --length HEXLENGTH +.br +Length of the dump [Byte] in hex. + +.B -d DUMPPATH, --dumppath DUMPPATH +.br +File path on PC where to store dump. + +.B -v, --verbose +.br +Shows more detailed information. + +.B --version +.br +Shows version information. + +.SH COPYRIGHT +/******************************************************************************* +Copyright (c) 2011, ST-Ericsson S.A. +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 ST-Ericsson S.A. 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 ST-ERICSSON S.A. 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. + *******************************************************************************/ +.SH SUPPORT AND REPORTING BUGS +.br +For information see +.br +http://www.igloocommunity.org/support/index.php/Main_Page diff --git a/os_wrappers/CriticalSection.cpp b/os_wrappers/CriticalSection.cpp new file mode 100755 index 0000000..2374565 --- /dev/null +++ b/os_wrappers/CriticalSection.cpp @@ -0,0 +1,66 @@ +/* + * CriticalSection.cpp + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup OS Wrappers + * @{ + */ + +#include "CriticalSection.h" + +CriticalSection::CriticalSection() +{ +#ifdef _WIN32 + InitializeCriticalSection(&mutex_); +#else + pthread_mutex_init(&mutex_, NULL); +#endif +} + +CriticalSection::~CriticalSection() +{ +#ifdef _WIN32 + DeleteCriticalSection(&mutex_); +#else + pthread_mutex_destroy(&mutex_); +#endif +} + +void CriticalSection::enter() +{ +#ifdef _WIN32 + EnterCriticalSection(&mutex_); +#else + pthread_mutex_lock(&mutex_); +#endif +} + +void CriticalSection::leave() +{ +#ifdef _WIN32 + LeaveCriticalSection(&mutex_); +#else + pthread_mutex_unlock(&mutex_); +#endif +} + +CSLock::CSLock(CriticalSection* section): section_(section) +{ + section_->enter(); +} + +CSLock::~CSLock() +{ + section_->leave(); +} + +/* @} */ diff --git a/os_wrappers/CriticalSection.h b/os_wrappers/CriticalSection.h new file mode 100755 index 0000000..f67f42a --- /dev/null +++ b/os_wrappers/CriticalSection.h @@ -0,0 +1,82 @@ +/* + * CriticalSection.h + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup OS Wrappers + * @{ + */ + +#pragma once + +#ifndef _WIN32 +#include +#endif + +/** + * @brief Simple wrapper for OS synchronization primitive. + * + * This class wraps Win32 critical section and POSIX threads mutex. + */ +class CriticalSection +{ +public: + /** + * @brief Constructor creating new critical section. + */ + CriticalSection(); + + /** + * @brief Destructor that destroys the critical section. + */ + virtual ~CriticalSection(); + + /** + * @brief This method enters/locks the critical section. + */ + void enter(); + + /** + * @brief This method leaves/unlocks the critical section. + */ + void leave(); +private: +#ifdef _WIN32 + CRITICAL_SECTION mutex_; +#else + pthread_mutex_t mutex_; +#endif +}; + +/** + * @brief RAII class for critical section locking/unlocking. + */ +class CSLock +{ +public: + /** + * @brief Constructor that enters/locks the passed critical section. + * + * @param[in] section - critical section to lock. + */ + CSLock(CriticalSection* section); + + /** + * @brief Destructor that leaves/unlocks the associated critical section. + */ + virtual ~CSLock(); +private: + CriticalSection* section_; + CSLock(const CSLock&); + CSLock& operator=(const CSLock&); +}; + +/* @} */ diff --git a/os_wrappers/Event.cpp b/os_wrappers/Event.cpp new file mode 100755 index 0000000..0390735 --- /dev/null +++ b/os_wrappers/Event.cpp @@ -0,0 +1,56 @@ +/* + * Event.cpp + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup OS Wrappers + * @{ + */ + +#include "Event.h" + +Event::Event() +{ +#ifdef _WIN32 + semaphore_ = CreateSemaphore(NULL, 0, 256, NULL); +#else + sem_init(&semaphore_, 0, 0); +#endif +} + +Event::~Event() +{ +#ifdef _WIN32 + CloseHandle(semaphore_); +#else + sem_destroy(&semaphore_); +#endif +} + +void Event::signal() +{ +#ifdef _WIN32 + ReleaseSemaphore(semaphore_, 1, NULL); +#else + sem_post(&semaphore_); +#endif +} + +void Event::wait(unsigned long timeout __attribute__((unused))) +{ +#ifdef _WIN32 + WaitForSingleObject(semaphore_, timeout); +#else + sem_wait(&semaphore_); +#endif +} + +/* @} */ diff --git a/os_wrappers/Event.h b/os_wrappers/Event.h new file mode 100755 index 0000000..9bd46f6 --- /dev/null +++ b/os_wrappers/Event.h @@ -0,0 +1,66 @@ +/* + * Event.h + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup OS Wrappers + * @{ + */ + +#pragma once + +#ifdef _WIN32 +#include +#else +#include +#endif + +/** + * @brief Simple wrapper for OS synchronization primitive. + * + * This class wraps Win32 and POSIX semaphore. + */ +class Event +{ +public: + /** + * @brief Constructor creating new event. + */ + Event(); + + /** + * @brief Destructor that destroys the event. + */ + virtual ~Event(); + + /** + * @brief Wait on the event for specified time. + * + * By default it waits for infinite time and blocks the thread until + * the event is signaled. + */ + void wait(unsigned long timeout = -1); + + /** + * @brief Signal the event. + * + * When event is signaled the waiting thread is released. + */ + void signal(); +private: +#ifdef _WIN32 + HANDLE semaphore_; +#else + sem_t semaphore_; +#endif +}; + +/* @} */ diff --git a/os_wrappers/Thread.cpp b/os_wrappers/Thread.cpp new file mode 100755 index 0000000..cc50f73 --- /dev/null +++ b/os_wrappers/Thread.cpp @@ -0,0 +1,68 @@ +/* + * Thread.cpp + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup OS Wrappers + * @{ + */ + +#include "Thread.h" +#ifdef _WIN32 +#include +#else +#include +#endif + +Thread::Thread(ThreadFunction_t function, void* argument): function_(function), argument_(argument), end_(new Event()) +{ +#ifdef _WIN32 + _beginthread(ThreadFunction, 0, this); +#else + pthread_attr_init(&attributes_); + pthread_attr_setdetachstate(&attributes_, PTHREAD_CREATE_DETACHED); + pthread_create(&id_, &attributes_, ThreadFunction, this); +#endif +} + +Thread::~Thread() +{ +#ifndef _WIN32 + pthread_cancel(id_); + pthread_attr_destroy(&attributes_); +#endif + delete end_; +} + +void Thread::wait(unsigned long timeout) +{ + end_->wait(timeout); + // signal the event again to avoid locking infinitely on following calls + end_->signal(); +} + +#ifdef _WIN32 +void Thread::ThreadFunction(void* arg) +#else +void* Thread::ThreadFunction(void* arg) +#endif +{ + Thread* pthis = static_cast(arg); + pthis->function_(pthis->argument_); + pthis->end_->signal(); +#ifdef _WIN32 + _endthread(); +#else + return 0; +#endif +} + +/* @} */ diff --git a/os_wrappers/Thread.h b/os_wrappers/Thread.h new file mode 100755 index 0000000..a5e65b8 --- /dev/null +++ b/os_wrappers/Thread.h @@ -0,0 +1,73 @@ +/* + * Thread.h + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup OS Wrappers + * @{ + */ + +#pragma once + +#include "Event.h" +#ifndef _WIN32 +#include +#endif + +/** + * @brief Simple wrapper for OS thread. + * + * This class wraps Win32 and POSIX thread. + */ +class Thread +{ +public: + /** + * @brief Type for thread's start function. + */ + typedef void*(*ThreadFunction_t)(void*); + + /** + * @brief Constructor creating new thread + * + * It creates new thread and starts execution of the function. + * + * @param[in] function - thread's start function. + * @param[in] arg - argument to be passed to the function. + */ + Thread(ThreadFunction_t function, void* arg); + + /** + * @brief Destructor. + */ + virtual ~Thread(); + + /** + * @brief Wait for the thread to die for specified timeout. + * + * @param[in] timeout - Time in ms to wait. By default timeout is infinite. + */ + void wait(unsigned long timeout = -1); +private: +#ifdef _WIN32 + static void ThreadFunction(void* arg); +#else + pthread_t id_; + pthread_attr_t attributes_; + static void* ThreadFunction(void* arg); +#endif + ThreadFunction_t function_; + void* argument_; + + Event* end_; +}; + +/* @} */ diff --git a/os_wrappers/Utilities.h b/os_wrappers/Utilities.h new file mode 100755 index 0000000..ca7eac9 --- /dev/null +++ b/os_wrappers/Utilities.h @@ -0,0 +1,57 @@ +/* + * Utilities.h + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup Utilities + * @{ + */ + +#pragma once +#include +#include + +using namespace std; +class Utilities +{ +public: + static void sleep(int ms) { + timespec delay; + delay.tv_sec = 0; + delay.tv_nsec = ms * 1000000; + nanosleep(&delay, 0); + } + + template + static T convert(const F& fromValue) { + stringstream stream; + stream << fromValue; + + T toValue; + stream >> toValue; + return toValue; + } + + static void trim(std::string& s) { + static const std::string whitespace(" \t\r\n"); + size_t start = s.find_first_not_of(whitespace); + + if (std::string::npos != start) { + s.erase(0, start); + size_t end = s.find_last_not_of(whitespace); + s.erase(end + 1); + } else { + s.clear(); + } + } +}; + +/* @} */ diff --git a/packages/control b/packages/control new file mode 100755 index 0000000..07c35bb --- /dev/null +++ b/packages/control @@ -0,0 +1,9 @@ +Package: riff +Version: 0.4.0 +Priority: optional +Architecture: all +Depends: libusb-1.0-0, riff-configpack (>= 0.4.0), riff-loadercomm (>= 0.4.0) +Installed-Size: +Maintainer: igloocommunity +Section: devel +Description: A flashing tool initially developed for igloocommunity.org and snowball devices. diff --git a/riff/Command.h b/riff/Command.h new file mode 100755 index 0000000..e97d043 --- /dev/null +++ b/riff/Command.h @@ -0,0 +1,52 @@ +/* + * Command.h + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup Command + * @{ + */ + +#pragma once + +// DUT class declaration +class DUT; + +/** + * @brief Abstract class providing base for all command implementations. + */ +class Command +{ +public: + /** + * @brief Pure virtual method implemented by concrete command implementation. + * + * This method should be implemented in the inherited command class providing + * specific command behavior. + * + * @param[in] dut - Specific DUT instance on which to execute the command. + * @return int - Command execution error (0 on success, non-0 otherwise). + */ + virtual int run(DUT* dut) = 0; + + /** + * @brief Default virtual destructor. + */ + virtual ~Command() {} + + /** + * @brief Get the command name + */ + virtual const char * get_command_name() = 0; + +}; + +/* @} */ diff --git a/riff/Config.cpp b/riff/Config.cpp new file mode 100755 index 0000000..c35f333 --- /dev/null +++ b/riff/Config.cpp @@ -0,0 +1,95 @@ +/* + * Config.cpp + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup Config + * @{ + */ + +#include "Config.h" +#include "Utilities.h" +#include +#include +#include +using namespace std; + +Config::Config(): logger_("Config") +{ +} + +Config::Config(const string& path): logger_("Config") +{ + load(path); +} + +bool Config::load(const string& path) +{ + ifstream file; + file.open(path.c_str()); + + if (file.is_open()) { + + string line; + string command; + string key; + string value; + + while (getline(file, line)) { + Utilities::trim(line); + + if (line.length() == 0 || line[0] != '!') + continue; + + line.erase(0, 1); + + command = getToken(line); + + if (command == "set") { + key = getToken(line); + values_[key] = line; + } + } + + return true; + } else { + logger_.log(Logger::ERROR, "Failed to open configuration file \"%s\"", path.c_str()); + return false; + } +} + +const char* Config::getValue(const string& key) const +{ + map::const_iterator i = values_.find(key); + + if (i != values_.end()) { + return i->second.c_str(); + } else { + return ""; + } +} + +std::string Config::getToken(std::string& line) +{ + size_t pos = line.find_first_of(" "); + string token = line.substr(0, pos); + line.erase(0, pos + 1); + Utilities::trim(token); + return token; +} + +bool Config::valueExists(const string& key) const +{ + string value = getValue(key); + return value.size() != 0; +} + +/* @} */ diff --git a/riff/Config.h b/riff/Config.h new file mode 100755 index 0000000..33799f0 --- /dev/null +++ b/riff/Config.h @@ -0,0 +1,76 @@ +/* + * Config.h + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup Config + * @{ + */ + +#pragma once +#include "Logger.h" +#include +#include +#include + +/** + * @brief Class used for storing application configuration parameters. + * + * This class support reading and storing configuration parameters from/to + * configuration files. It also supports overriding of configuration parameters + * from command line. + */ +class Config +{ +public: + /** + * @brief Default constructor creating empty configuration. + */ + Config(); + + /** + * @brief Constructor that reads configuration parameters form file. + * + * @param[in] path - Path to the configuration file. + */ + Config(const std::string& path); + + /** + * @brief Function to load configuration from file. + * + * @param[in] path - Path to the configuration file. + */ + bool load(const std::string& path); + + /** + * @brief Gets the configuration value as C-style string. + * + * @param[in] key - Key of the configuration value. + * @return Configuration value as C-style string. + */ + const char* getValue(const std::string& key) const; + + /** + * @brief Checks if the configuration value exists. + * + * @param[in] key - Key of the configuration value. + * @return True if value exists, otherwise false. + */ + bool valueExists(const std::string& key) const; + +private: + std::map values_; + Logger logger_; + + std::string getToken(std::string& line); +}; + +/* @} */ diff --git a/riff/DUT.cpp b/riff/DUT.cpp new file mode 100755 index 0000000..6019518 --- /dev/null +++ b/riff/DUT.cpp @@ -0,0 +1,115 @@ +/* + * DUT.cpp + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup DUT + * @{ + */ + +#include "DUT.h" +#include "CDAL.h" +#include "LCDriver.h" +#include "Config.h" +#include +#include +#include +using namespace std; + +/** + * @brief Macro used by all command implementations to verify the Command return values. + */ +#define COMMAND_ERROR_VERIFY(error, message) \ + do { \ + if (0 != error) \ + { \ + logger_.log(Logger::ERROR,"COMMAND ERROR: %s %d", message, error); \ + usb_destroy_device(commDevice_, error); \ + errorcode_ = error; \ + return; \ + } \ + } while (0); + +DUT::DUT(Device_t commDevice, const string& id, CommandSequence_t sequence): + commDevice_(commDevice), + id_(id), + lcdContext_(0), + executionThread_(0), + shutdown_(false), + sequence_(sequence), + logger_(id) +{ + +} + +DUT::~DUT() +{ + shutdown_ = true; + executionThread_->wait(1000); + + logger_.log(Logger::INFO, "Destroying LCD context..."); + int error = DestroyContext(&lcdContext_); + + if (0 != error) { + logger_.log(Logger::ERROR, "LCD ERROR: Failed to destroy LCD context %d", error); + } else { + logger_.log(Logger::INFO, "LCD context destroyed successfully"); + } + + executionThread_->wait(1000); + + for (CommandSequence_t::iterator i = sequence_.begin(); i != sequence_.end(); ++i) { + delete *i; + } + + delete executionThread_; +} + +void DUT::startExecution() +{ + executionThread_ = new Thread(ExecutionThreadFunction, this); +} + +int DUT::getErrorCode() const +{ + return errorcode_; +} + +void DUT::executeSequence() +{ + int error = 0; + + for (CommandSequence_t::iterator i = sequence_.begin(); !shutdown_ && i != sequence_.end(); ++i) { + error = (*i)->run(this); + + // When the initialize DUT is failed, just set the error and exit (because + // the DUT is not started yet). But when other execution is failed, do a + // smooth exit by shutting down the DUT. + if ((error != 0) && (!strcmp((*i)->get_command_name(), "INITIALIZE_DUT"))) { + errorcode_ = error; + } else if ((error != 0) && (strcmp((*i)->get_command_name(), "SHUTDOWN"))) { + continue; + } + + COMMAND_ERROR_VERIFY(error, "Command execution failed"); + } + + return; +} + +void* DUT::ExecutionThreadFunction(void* arg) +{ + DUT* dut = static_cast(arg); + dut->executeSequence(); + return 0; +} + +/* @} */ diff --git a/riff/DUT.h b/riff/DUT.h new file mode 100755 index 0000000..98ddd1b --- /dev/null +++ b/riff/DUT.h @@ -0,0 +1,123 @@ +/* + * DUT.h + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup DUT + * @{ + */ + +#pragma once + +#include "CDAL.h" +#include "LCDriver.h" +#include "Thread.h" +#include "Config.h" +#include "Logger.h" +#include "Command.h" +#include "SequenceFactory.h" +#include +#include + +/** + * @brief Class that wraps all parameters related to the connected device. + * + * It also executes the command sequence that is set for this device. + */ +class DUT +{ +public: + + /** + * @brief Constructor. + * + * Constructor for the DUT class. It associates the newly created DUT with the + * communication device and sets the ID of the DUT. + * + * @param[in] commDevice - Communication device associated with the DUT. + * @param[in] id - ID of the DUT. + * @param[in] sequence - Execution sequence for the DUT. + */ + DUT(Device_t commDevice, const std::string& id, CommandSequence_t sequence); + + /** + * @brief Destructor. + * + * De-initializes the DUT by releasing all the resources used, stopping the execution + * of command sequence and destroying related LCD context. + */ + ~DUT(); + + /** + * @brief Start of execution of command sequence. + * + * Creates and starts new command execution thread. Each DUT instance is associated + * with separate command execution thread. + */ + void startExecution(); + + /** + * @brief This method returns the communication device associated with the DUT. + * + * @return Device_t - Communication device associated with the DUT. + */ + Device_t getCommDevice() const { + return commDevice_; + } + + /** + * @brief This method returns the ID of the DUT. + * + * @return const char* - string that contains the ID. + */ + const char* getId() const { + return id_.c_str(); + } + + /** + * @brief This method returns the LCD Context associated with the DUT. + * + * @return LCDContext - LCD Context associated with the DUT. + */ + LCDContext getLCDContext() { + return lcdContext_; + } + + /** + * @brief This method associates the DUT with a new LCDContext. + * + * @param[in] LCDContext - LCD Context that will be associated with the DUT. + */ + void setLCDContext(LCDContext lcdContext) { + lcdContext_ = lcdContext; + } + + /** + * @brief This method returns the errorcode produced by the sequence execution. + */ + int getErrorCode() const; + +private: + Device_t commDevice_; + std::string id_; + LCDContext lcdContext_; + Logger logger_; + CommandSequence_t sequence_; + int errorcode_; + + // command execution thread + Thread* executionThread_; + bool shutdown_; + static void* ExecutionThreadFunction(void* arg); + void executeSequence(); +}; + +/* @} */ diff --git a/riff/DumpArea.cpp b/riff/DumpArea.cpp new file mode 100755 index 0000000..2f7fcf6 --- /dev/null +++ b/riff/DumpArea.cpp @@ -0,0 +1,73 @@ +/* + * DumpArea.cpp + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup Commands + * @{ + */ + +/******************************************************************************* + * Includes + ******************************************************************************/ +#include "DumpArea.h" +#include +#include +#include "LCDriver.h" +using namespace flash; + +DumpArea::DumpArea(const char* path, uint64 start, uint64 length, const char* filepath, uint32 redundant, int useBulk): + logger_("DumpArea") +{ + pchPath = path; + uiStart = start; + uiLength = length; + pchFilePath = filepath; + uiRedundantArea = redundant; + iUseBulk = useBulk;; +} + +int DumpArea::run(DUT* dut) +{ + logger_.log(Logger::PROGRESS, "Dumping area..."); + logger_.log(Logger::PROGRESS, "Dump path is %s", pchFilePath); + int error = checkInput(); + if (error == -1) { + return error; + } + error = Flash_DumpArea(dut->getLCDContext(), pchPath, uiStart, uiLength, pchFilePath, uiRedundantArea, iUseBulk); + if (0 != error) + { + logger_.log(Logger::ERROR,"LCD ERROR: Dump area failed %d", error); + return error; + } + // Need a new line braek after the progress bar + logger_.logRaw("\n"); + logger_.log(Logger::INFO, "Dump area finished successfully"); + return error; +} + +int DumpArea::checkInput() +{ + if (uiLength <= 0) { + logger_.log(Logger::ERROR, "Length of the dump not specified. Use -l or --length option"); + return -1; + } + return 0; +} + +const char * DumpArea::get_command_name() +{ + return (char *)"DUMPAREA"; +} + + +/* @} */ diff --git a/riff/DumpArea.h b/riff/DumpArea.h new file mode 100755 index 0000000..bd37638 --- /dev/null +++ b/riff/DumpArea.h @@ -0,0 +1,67 @@ +/* + * DumpArea.h + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup Commands + * @{ + */ + +#pragma once +#include "DUT.h" +#include "Command.h" + +namespace flash +{ +/** + * @brief Class implementing Dump Area command from Flash group. + */ +class DumpArea : public Command +{ +public: + /** + * @brief Constructor initializing command parameters. + * + * @param[in] path - Path to the device to dump. + * @param[in] start - Start of the dump relative to the start of the device indicated by Path [Byte]. + * @param[in] lenght - Length of the dump [Byte]. Actual length is determined by the device block size. + * @param[in] filepath - File path on PC to store dump data to. + * @param[in] redundant - dump with redundant data, 1-> dump without redundant data. + * @param[in] useBulk - 1 = use bulk protocol. + */ + DumpArea(const char* path, uint64 start, uint64 length, const char* filepath, uint32 redundant, int useBulk); + + /** + * @brief Method that executes the dump process. + * + * @param[in] dut - Specific DUT instance on which to execute the command. + * @return int - Command execution error (0 on success, non-0 otherwise). + */ + int run(DUT* dut); + + const char * get_command_name(); + +private: + + int checkInput(); + + Logger logger_; + const char* pchPath; + uint64 uiStart; + uint64 uiLength; + const char* pchFilePath; + char dumpPath[50]; + uint32 uiRedundantArea; + int iUseBulk; +}; +} + +/* @} */ diff --git a/riff/DutManager.cpp b/riff/DutManager.cpp new file mode 100755 index 0000000..86a96c4 --- /dev/null +++ b/riff/DutManager.cpp @@ -0,0 +1,65 @@ +/* + * DUTManager.cpp + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup DUT Manager + * @{ + */ + +#include "DutManager.h" +#include "Utilities.h" +#include +using namespace std; + +vector DutManager::devices_; + +DUT* DutManager::createDut(Device_t device) +{ + string dutId = getDutId(device); + + DUT* dut = new DUT(device, dutId, SequenceFactory::getProfileSequence()); + devices_.push_back(dut); + + dut->startExecution(); + + return dut; +} + +const DUT* DutManager::getDut(Device_t device) +{ + for (vector::iterator i = devices_.begin(); i != devices_.end(); ++i) { + if ((*i)->getCommDevice() == device) { + return *i; + } + } + + return 0; +} + +void DutManager::destroyDut(Device_t device) +{ + for (vector::iterator i = devices_.begin(); i != devices_.end(); ++i) { + if ((*i)->getCommDevice() == device) { + delete *i; + devices_.erase(i); + break; + } + } +} + +string DutManager::getDutId(Device_t device) +{ + string physicalId = "Device@" + Utilities::convert(comm_get_physical_address(device)); + return physicalId; +} + +/* @} */ diff --git a/riff/DutManager.h b/riff/DutManager.h new file mode 100755 index 0000000..6a8009d --- /dev/null +++ b/riff/DutManager.h @@ -0,0 +1,63 @@ +/* + * DUTManager.h + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup DUT Manager + * @{ + */ + +#pragma once + +#include "DUT.h" +#include "CDAL.h" +#include "Logger.h" +#include + +class DutManager +{ +public: + /** + * @brief Creates new DUT instance, starts execution and adds the DUT in the list of active devices. + * + * @param[in] Device_t - Communication device on which the DUT will be created. + * + */ + static DUT* createDut(Device_t device); + + /** + * @brief Get the DUT instance that is associated with the connected devices.. + * + * @param[in] Device_t - Communication device. + * @return DUT* - pointer to the DUT. + * @return 0 - if the DUT can't be find in the list. + */ + static const DUT* getDut(Device_t device); + + /** + * @brief Destroys the DUT instance that is associated with the communication device. + * + * @param[in] Device_t - Communication device. + */ + static void destroyDut(Device_t device); + +private: + DutManager(); + ~DutManager(); + + /*list of connected devices*/ + static std::vector devices_; + + static std::string getDutId(Device_t device); +}; + +/* @} */ + diff --git a/riff/EraseArea.cpp b/riff/EraseArea.cpp new file mode 100755 index 0000000..3de8ed0 --- /dev/null +++ b/riff/EraseArea.cpp @@ -0,0 +1,50 @@ +/* + * EraseArea.cpp + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup Commands + * @{ + */ + +#include "EraseArea.h" +using namespace flash; + + +EraseArea::EraseArea(const char* path, uint64 start, uint64 length): + logger_("EraseArea") +{ + pchPath = path; + uiStart = start; + uiLength = length; +} + +int EraseArea::run(DUT* dut) +{ + logger_.log(Logger::PROGRESS, "Erasing area..."); + int error = Flash_EraseArea(dut->getLCDContext(), pchPath, uiStart, uiLength); + + if (0 != error) + { + logger_.log(Logger::ERROR,"LCD ERROR: Erase area failed %d", error); + return error; + } + + logger_.log(Logger::PROGRESS, "Erase area finished successfully"); + return error; +} + +const char * EraseArea::get_command_name() +{ + return (char *)"ERASEAREA"; +} + +/* @} */ diff --git a/riff/EraseArea.h b/riff/EraseArea.h new file mode 100755 index 0000000..d44e27a --- /dev/null +++ b/riff/EraseArea.h @@ -0,0 +1,56 @@ +/* + * EraseArea.h + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup Commands + * @{ + */ + +#pragma once +#include "DUT.h" +#include "Command.h" + +namespace flash +{ +/** + * @brief Class implementing Erase Area command from Flash group. + */ +class EraseArea : public Command +{ +public: + /** + * @brief Constructor initializing command parameters. + * + * @param[in] path - Path to the device to erase. + * @param[in] start - Start of the erase relative to the start of the device. + * @param[in] length - 1 = use bulk protocol. + */ + EraseArea(const char* path, uint64 start, uint64 length); + + /** + * @brief Method that executes the erase process. + * + * @param[in] dut - Specific DUT instance on which to execute the command. + * @return int - Command execution error (0 on success, non-0 otherwise). + */ + int run(DUT* dut); + + const char * get_command_name(); +private: + Logger logger_; + const char* pchPath; + uint64 uiStart; + uint64 uiLength; +}; +} + +/* @} */ diff --git a/riff/InitializeDut.cpp b/riff/InitializeDut.cpp new file mode 100755 index 0000000..e2feb18 --- /dev/null +++ b/riff/InitializeDut.cpp @@ -0,0 +1,452 @@ +/* + * InitializeDut.cpp + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup Commands + * @{ + */ + +#include "InitializeDut.h" +#include "Logger.h" +#include "DUT.h" +#include "Utilities.h" +#include +#include +#include +#include +#include + +using namespace std; + + +int InitializeDut::readIsswFile(char* buf) +{ + int res = 0; + FILE* isswImage; + + isswImage = fopen(isswPath_, "rb"); + + if (isswImage == NULL) { + logger_.log(Logger::ERROR, "InitializeDut.cpp (%d) %s() error while opening file %s", __LINE__, __FUNCTION__, isswPath_); + return -1; + } + + res = fread(buf, 1, issw_.size, isswImage); + + fclose(isswImage); + return 0; +} + +int InitializeDut::readSecondIsswFile(char* buf) +{ + int res = 0; + FILE* xloaderImage; + + xloaderImage = fopen(xloaderPath_, "rb"); + + if (xloaderImage == NULL) { + logger_.log(Logger::ERROR, "InitializeDut.cpp (%d) %s() error while opening file %s", __LINE__, __FUNCTION__, xloaderPath_); + return -1; + } + + res = fread(buf, 1, xload_.size, xloaderImage); + fclose(xloaderImage); + return 0; +} + +int InitializeDut::readPwrMgtFile(char* buf) +{ + FILE* pwrmgmtImage; + + pwrmgmtImage = fopen(pwrmgmtPath_, "rb"); + + if (pwrmgmtImage == NULL) { + logger_.log(Logger::ERROR, "InitializeDut.cpp (%d) %s() error while opening file %s", __LINE__, __FUNCTION__, pwrmgmtPath_); + return -1; + } + + fread(buf, 1, pwrMgt_.size, pwrmgmtImage); + fclose(pwrmgmtImage); + return 0; +} + +int InitializeDut::readMeminitFile(char* buf) +{ + FILE* meminitImage; + + meminitImage = fopen(meminitPath_, "rb"); + + if (meminitImage == NULL) { + logger_.log(Logger::ERROR, "InitializeDut.cpp (%d) %s() error while opening file %s", __LINE__, __FUNCTION__, meminitPath_); + return -1; + } + + fread(buf, 1, meminit_.size, meminitImage); + fclose(meminitImage); + return 0; +} + +int InitializeDut::readNormal(char* buf) +{ + FILE* normalImage; + + normalImage = fopen(normalPath_, "rb"); + + if (normalImage == NULL) { + logger_.log(Logger::ERROR, "InitializeDut.cpp (%d) %s() error while opening file %s", __LINE__, __FUNCTION__, normalPath_); + return -1; + } + + fread(buf, 1, normal_.size, normalImage); + fclose(normalImage); + return 0; +} + +int InitializeDut::commWrite2kChunks(Device_t device, void* buffer, size_t size) +{ + char* buf = static_cast(buffer); + + while (size) { + size_t toSend = size > 2048 ? 2048 : size; + + if (comm_write(device, buf, toSend) < 0) + return -1; + + size -= toSend; + buf += toSend; + } + + return 0; +} + +int InitializeDut::sendTocIssw(Device_t device) +{ + //Send TOC+ISSW to the board + int index = 0; + tocSection* tocSections = (tocSection*)tocArea; + unsigned int bootIndication; + char* sendBuffer = NULL; + int sendBufferSize = 0; + char* tempNORMAL = (char*) "NORMAL"; + + memset(tocSections, 0xff, 512); + + //Build TOC Sections List + tocSections[index++] = issw_; + + // X-Loader section + tocSections[index++] = xload_; + tocSections[index++] = meminit_; + + if (strcmp(pwrMgt_.filename, tempNORMAL) == 0) { + tocSections[index++] = normal_; + } else { + tocSections[index++] = pwrMgt_; + tocSections[index++] = normal_; + } + + sendBufferSize = 512 + issw_.size; + sendBuffer = (char*)malloc(sendBufferSize); + + bootIndication = 0xf0030002; + + if (comm_write(device, (char*)&bootIndication, 4) < 0) + return -1; + + if (comm_write(device, (char*)&sendBufferSize, 4) < 0) + return -1; + + memcpy(sendBuffer, tocSections, 512); + readIsswFile(sendBuffer + 512); + + commWrite2kChunks(device, sendBuffer, sendBufferSize); + + return 0; +} + +int InitializeDut::createTocEntry(tocSection* issw, tocSection* xload, tocSection* meminit, tocSection* normal, tocSection* pwrMgt) +{ + int offset = 512; + + createTocFile(issw, isswPath_, "ISSW", &offset); //ISSW TOC + createTocFile(xload, xloaderPath_, "X-LOADER", &offset); //X-LOADER TOC + createTocFile(meminit, meminitPath_, "MEM_INIT", &offset); //MEMINIT TOC + + if (strlen(pwrmgmtPath_) != 0) { + createTocFile(pwrMgt, pwrmgmtPath_, "PWR_MGT", &offset); //PWR_MGT TOC + createTocFile(normal, normalPath_, "NORMAL", &offset); //NORMAL TOC + } else { + createTocFile(pwrMgt, normalPath_, "NORMAL", &offset); //NORMAL TOC + *normal = *pwrMgt; + } + + return 0; +} + +int InitializeDut::createTocFile(tocSection* toc, const char* filePath, const char* tocName, int* offset) +{ + size_t size = 0; + + if ((filePath == NULL) || (strlen(filePath) == 0)) + return -1; + + size = getFileSize(filePath); + + // Create the TOC entry + toc->start = *offset; + toc->size = size; + toc->flags = 0; + toc->align = 0; + toc->loadAddress = 0; + strcpy(toc->filename, tocName); + + *offset += size; + + return 0; +} + +int InitializeDut::getFileSize(const char* filePath) +{ + + struct stat filestatus; + stat(filePath, &filestatus); + + return filestatus.st_size; + +} + +int InitializeDut::initializeHardware(Device_t device) +{ + + char asicIdUsb[65]; + unsigned char secureMode; + + unsigned int byteSynchro = 0x53548815; + + Config config(configPath_); + + isswPath_ = config.getValue("ISSWPATH"); + xloaderPath_ = config.getValue("XLOADERPATH"); + meminitPath_ = config.getValue("MEMINITPATH"); + pwrmgmtPath_ = config.getValue("PWRMGMTPATH"); + normalPath_ = config.getValue("NORMALPATH"); + + if (comm_write(device, (char*)&byteSynchro, 4) < 0) + return -1; + + if (comm_read(device, asicIdUsb, 65) < 0) + return -1; + + secureMode = asicIdUsb[11]; + + if (createTocEntry(&issw_, &xload_, &meminit_, &normal_, &pwrMgt_)) + return -1; + + if (sendTocIssw(device)) + return -1; + + while (1) { + unsigned int reqId; + + if (comm_read(device, (char*)&reqId, 4) < 0) + return -1; + + char *sendBuffer = NULL; + + switch (reqId) { + case 0xA0400000: + /* 2nd Loader ISSW Requested XLoader */ + logger_.log(Logger::INFO, "X-LOADER token"); + + if (comm_write(device, (char*)&xload_.size, 4) < 0) + return -1; + + sendBuffer = (char*)malloc(xload_.size); + + if (readSecondIsswFile(sendBuffer) < 0) + { + free(sendBuffer); + return -1; + } + + + + commWrite2kChunks(device, sendBuffer, xload_.size); + logger_.log(Logger::INFO, "X-LOADER sent"); + free(sendBuffer); + + break; + + case 0xA0300002: + /*PWR_MGT token*/ + logger_.log(Logger::INFO, "PWR_MGT token"); + + if (comm_write(device, (char*)&pwrMgt_.size, 4) < 0) + return -1; + + sendBuffer = (char*)malloc(pwrMgt_.size); + + if (readPwrMgtFile(sendBuffer) < 0) + { + free(sendBuffer); + return -1; + } + + commWrite2kChunks(device, sendBuffer, pwrMgt_.size); + logger_.log(Logger::INFO, "PWR_MGT sent"); + free(sendBuffer); + + break; + + case 0xA0300000: + /* Mem Init token */ + logger_.log(Logger::INFO, "MEM_INIT token"); + + if (comm_write(device, (char*)&meminit_.size, 4) < 0) + return -1; + + sendBuffer = (char*)malloc(meminit_.size); + + if (readMeminitFile(sendBuffer) < 0) + { + free(sendBuffer); + return -1; + } + + commWrite2kChunks(device, sendBuffer, meminit_.size); + logger_.log(Logger::INFO, "MEM_INIT sent"); + free(sendBuffer); + + break; + + case 0xA0300001: + /* Application token */ + logger_.log(Logger::INFO, "NORMAL token"); + + if (comm_write(device, (char*)&normal_.size, 4) < 0) + return -1; + + sendBuffer = (char*)malloc(normal_.size); + + if (readNormal(sendBuffer) < 0) + { + free(sendBuffer); + return -1; + } + + commWrite2kChunks(device, sendBuffer, normal_.size); + logger_.log(Logger::INFO, "NORMAL sent"); + free(sendBuffer); + + return 0; + + break; + + default: + logger_.log(Logger::INFO, "UNKNOWN token"); + } + } +} +InitializeDut::InitializeDut(const char* configPath): + logger_("InitializeDut") +{ + configPath_ = configPath; +} + +int InitializeDut::run(DUT* dut) +{ + int error = 0; + Device_t commDevice = dut->getCommDevice(); + LCDContext lcdContext = 0; + + char version[100] = {0}; + int versionSize = 100; + char protocol[100] = {0}; + int protocolSize = 100; + + logger_.log(Logger::INFO, "Initializing device..."); + + error = initializeHardware(commDevice); + if (0 != error) + { + logger_.log(Logger::ERROR,"LCD ERROR: Error while initializing device %d", error); + return error; + } + + logger_.log(Logger::INFO, "Initializing finished"); + + logger_.log(Logger::INFO, "Starting initialization of LCD..."); + void** deviceObjectStorage = comm_get_object_storage(commDevice); + error = CreateContext(&lcdContext, dut->getId()); + if (0 != error) + { + logger_.log(Logger::ERROR,"LCD ERROR: Error while creating LCD context %d", error); + return error; + } + + dut->setLCDContext(lcdContext); + error = ConfigureCommunicationDevice(lcdContext, (void*)comm_read_nowait, (void*)comm_write_nowait, (void*)comm_cancel); + if (0 != error) + { + logger_.log(Logger::ERROR,"LCD ERROR: Error while configuring communication device %d", error); + return error; + } + + + error = SwitchProtocolFamily(lcdContext, R15_PROTOCOL_FAMILY); + if (0 != error) + { + logger_.log(Logger::ERROR,"LCD ERROR: Error while setting protocol family %d", error); + return error; + } + + + error = StartContext(lcdContext, deviceObjectStorage); + if (0 != error) + { + logger_.log(Logger::ERROR,"LCD ERROR: Error while starting LCD context %d", error); + return error; + } + + logger_.log(Logger::INFO, "LCD initialization finished successfully"); + + error = SetProgressCallback(lcdContext, (void*)comm_progress); + if (0 != error) + { + logger_.log(Logger::ERROR,"LCD ERROR: Error while setting Progress listener %d", error); + return error; + } + + logger_.log(Logger::INFO, "Progress listener added successfully"); + + error = System_LoaderStartupStatus(dut->getLCDContext(), version, &versionSize, protocol, &protocolSize); + if (0 != error) + { + logger_.log(Logger::ERROR,"LCD ERROR: Failed to receive loader startup status %d", error); + return error; + } + + logger_.log(Logger::INFO, "Loader successfully started"); + logger_.log(Logger::INFO, " Version: %s", version); + logger_.log(Logger::INFO, " Protocol: %s", protocol); + + Utilities::sleep(100); + + return error; +} + +const char * InitializeDut::get_command_name() +{ + return (char *)"INITIALIZE_DUT"; +} + +/* @} */ diff --git a/riff/InitializeDut.h b/riff/InitializeDut.h new file mode 100755 index 0000000..6e0ab31 --- /dev/null +++ b/riff/InitializeDut.h @@ -0,0 +1,85 @@ +/* + * InitializeDut.h + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup Commands + * @{ + */ + +#pragma once +#include "Command.h" +#include "Config.h" +#include "DUT.h" +#include +#include +using namespace std; + +struct tocSection { + int start; + int size; + int flags; + int align; + int loadAddress; + char filename[12]; +}; + +/** + * @brief Class implementing command for DUT initialization. + */ +class InitializeDut : public Command +{ +public: + /** + * @brief Default constructor taking a config file path as parameter. + */ + InitializeDut(const char* configPath); + + /** + * @brief Method that executes the DUT initialization. + * + * This method initializes new LCD context and sets the DUT in service mode. + * + * @param[in] dut - Specific DUT instance on which to execute the command. + * @return int - Command execution error (0 on success, non-0 otherwise). + */ + int run(DUT* dut); + + const char * get_command_name(); + +private: + const char* configPath_; + const char* isswPath_; + const char* xloaderPath_; + const char* meminitPath_; + const char* pwrmgmtPath_; + const char* normalPath_; + + char tocArea[512]; + tocSection issw_, xload_, meminit_, normal_, pwrMgt_; + + Logger logger_; + + int commWrite2kChunks(Device_t device, void* buffer, size_t size); + int sendTocIssw(Device_t device); + int createTocEntry(tocSection* issw, tocSection* xload, tocSection* meminit, tocSection* normal, tocSection* pwrMgt); + int createTocFile(tocSection* toc, const char* filePath, const char* tocName, int* offset); + int getFileSize(const char* filePath); + int readIsswFile(char* buf); + int readSecondIsswFile(char* buf); + int readPwrMgtFile(char* buf); + int readMeminitFile(char* buf); + int readNormal(char* buf); + int initializeHardware(Device_t device); + +}; + +/* @} */ diff --git a/riff/Logger.cpp b/riff/Logger.cpp new file mode 100755 index 0000000..a54e447 --- /dev/null +++ b/riff/Logger.cpp @@ -0,0 +1,85 @@ +/* + * Logger.cpp + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup Logger + * @{ + */ + +#include "Logger.h" +#include +#include +#include +#include +#include +using namespace std; + +bool Logger::verbose_; + +Logger::Logger(const string& name): + name_(name) +{ + console_ = stdout; + +} + +Logger::~Logger() +{ +} + +void Logger::log(LogSeverity severity, const char* format, ...) const +{ + time_t t = time(0); + tm lt; + localtime_r(&t, <); + + if (verbose_ || severity == Logger::PROGRESS || severity == Logger::ERROR) { + flockfile(console_); + fprintf(console_, "%02d:%02d:%02d ", lt.tm_hour, lt.tm_min, lt.tm_sec); + + fprintf(console_, " - "); + + va_list args; + va_start(args, format); + vfprintf(console_, format, args); + va_end(args); + fprintf(console_, "\n"); + fflush(console_); + funlockfile(console_); + + } +} + +void Logger::hex(const unsigned char* buffer, size_t size) const +{ + flockfile(console_); + + for (size_t i = 0; i < size; i++) { + fprintf(console_, "%02x ", buffer[i]); + + if ((i + 1) % 16 == 0 || (i + 1) == size) + fprintf(console_, "\n"); + } + + fflush(console_); + funlockfile(console_); +} + +void Logger::logRaw(const char* message) const +{ + flockfile(console_); + fprintf(console_, "%s", message); + fflush(console_); + funlockfile(console_); +} + +/* @} */ diff --git a/riff/Logger.h b/riff/Logger.h new file mode 100755 index 0000000..c995abc --- /dev/null +++ b/riff/Logger.h @@ -0,0 +1,85 @@ +/* + * Logger.h + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup Logger + * @{ + */ + +#pragma once +#include + +/** + * @brief Class for storing and displaying logging information. + * + * This class implements simple command line logger that can display logging + * information either to the application console or separate logging console. + */ +class Logger +{ +public: + + enum LogSeverity { + PROGRESS, + ERROR, + WARNING, + INFO + }; + + + /** + * @brief Creates logger with the specified name. + * + * @param[in] name - Name of the logger. + */ + Logger(const std::string& name); + + /** + * @brief Destroys the logger. + */ + ~Logger(); + + /** + * @brief printf style log function to print formated message. + * + * It prints the message on separate line adding timestamp and logger name + * if printing in a shared console. + * + * @param[in] severity - the severity of the log message. + * @param[in] format - printf style format of the message. + * @param[in] ... - variable argument list. + */ + void log(LogSeverity severity, const char* format, ...) const __attribute__((format(printf, 3, 0))); + + /** + * @brief Print hex dump of the buffer. + * + * @param[in] buffer - buffer to be printed to the log. + * @param[in] size - size of the buffer. + */ + void hex(const unsigned char* buffer, size_t size) const; + + /** + * @brief Print raw message string to the logging console. + * + * @param[in] message - raw messsage to be printed. + */ + void logRaw(const char* message) const; + + static bool verbose_; + +private: + FILE* console_; + std::string name_; +}; + +/* @} */ diff --git a/riff/ProcessRawImage.cpp b/riff/ProcessRawImage.cpp new file mode 100755 index 0000000..a46337b --- /dev/null +++ b/riff/ProcessRawImage.cpp @@ -0,0 +1,79 @@ +/* + * ProcessRawImage.cpp + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup Commands + * @{ + */ + +/******************************************************************************* + * Includes + ******************************************************************************/ +#include "ProcessRawImage.h" +#include +#include +#include "LCDriver.h" +using namespace flash; + +ProcessRawImage::ProcessRawImage(const char* path, uint64 start, int useBulk, int deleteBuffers): + logger_("ProcessRawImage") +{ + pchPath = path; + uiStart = start; + uiDevice = 0; // Flashing the flash0 device + iUseBulk = useBulk; + iDeleteBuffers = deleteBuffers; +} + +int ProcessRawImage::run(DUT* dut) +{ + logger_.log(Logger::PROGRESS, "Flashing raw image..."); + uint64 length = filesize(pchPath); + int error = 0; + + if (length != 0) { + error = Flash_FlashRaw(dut->getLCDContext(), pchPath, uiStart, length, uiDevice, iUseBulk, iDeleteBuffers); + if (0 != error) + { + logger_.log(Logger::ERROR,"LCD ERROR: Process raw image failed %d", error); + return error; + } + + // Need a new line braek after the progress bar + logger_.logRaw("\n"); + logger_.log(Logger::PROGRESS, "Flashing finished successfully"); + } else { + error = -1; + logger_.log(Logger::ERROR,"LCD ERROR: Flash image is empty or doesn't exist %d", error); + return error; + } + + return error; +} + +size_t ProcessRawImage::filesize(const char* filename) +{ + struct stat st; + + if (stat(filename, &st) == 0) + return st.st_size; + + return 0; +} + +const char * ProcessRawImage::get_command_name() +{ + return (char *)"PROCESSRAWIMAGE"; +} + + +/* @} */ diff --git a/riff/ProcessRawImage.h b/riff/ProcessRawImage.h new file mode 100755 index 0000000..b429b88 --- /dev/null +++ b/riff/ProcessRawImage.h @@ -0,0 +1,61 @@ +/* + * ProcessRawImage.h + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup Commands + * @{ + */ + +#pragma once +#include "DUT.h" +#include "Command.h" + +namespace flash +{ +/** + * @brief Class implementing Process Raw Image command from Flash group. + */ +class ProcessRawImage : public Command +{ +public: + /** + * @brief Constructor initializing command parameters. + * + * @param[in] path - Path to the image file. + * @param[in] start - Address where flashing should start. + * @param[in] useBulk - 1 = use bulk protocol. + * @param[in] deleteBuffers - 1 = release flash archive buffers after finish. + */ + ProcessRawImage(const char* path, uint64 start, int useBulk, int deleteBuffers); + + /** + * @brief Method that executes the flashing process. + * + * @param[in] dut - Specific DUT instance on which to execute the command. + * @return int - Command execution error (0 on success, non-0 otherwise). + */ + int run(DUT* dut); + + const char * get_command_name(); + +private: + Logger logger_; + size_t filesize(const char* filename); + const char* pchPath; + uint64 uiStart; + uint32 uiDevice; + int iUseBulk; + int iDeleteBuffers; +}; +} + +/* @} */ diff --git a/riff/SequenceFactory.cpp b/riff/SequenceFactory.cpp new file mode 100755 index 0000000..8c42f78 --- /dev/null +++ b/riff/SequenceFactory.cpp @@ -0,0 +1,105 @@ +/* + * SequenceFactory.cpp + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup SequenceFactory + * @{ + */ + +#include "Config.h" +#include "SequenceFactory.h" +#include "Command.h" +#include "InitializeDut.h" +#include "ProcessRawImage.h" +#include "Shutdown.h" +#include "EraseArea.h" +#include "DumpArea.h" +#include "constants.h" +#include +#include +#include +#include +using namespace std; + +const SequenceFactory::SequenceId SequenceFactory::defaultSequence_ = SequenceFactory::BOARD_FLASH; + +const char* SequenceFactory::configPath_; +const char* SequenceFactory::flashmode_; +const char* SequenceFactory::flashImgPath_; +const char* SequenceFactory::dumpHostPath_; +int SequenceFactory::address_ = 0; +int SequenceFactory::length_ = 0; + +void SequenceFactory::setArguments(const char* configPath, const char* mode, const char* flashImg, const char* address, const char* length, const char* dumpPath) +{ + SequenceFactory::configPath_ = configPath; + SequenceFactory::flashmode_ = mode; + SequenceFactory::flashImgPath_ = flashImg; + SequenceFactory::address_ = strtol(address, NULL, 16); + SequenceFactory::length_ = strtol(length, NULL, 16); + SequenceFactory::dumpHostPath_ = dumpPath; +} + +CommandSequence_t SequenceFactory::getSequence(SequenceId id) +{ + CommandSequence_t sequence; + + // Initialize DUT + sequence.push_back(new InitializeDut(configPath_)); + + + switch (id) { + case BOARD_FLASH: { + // Process raw software image + sequence.push_back(new flash::ProcessRawImage(flashImgPath_, address_, USE_BULK_PROTOCOL, DELETE_BUFFER_YES)); + } + break; + case BOARD_ERASE: { + // erase complete flash + sequence.push_back(new flash::EraseArea(flash::FLASH_DEVICE_TYPE, 0, -1)); + } + break; + case BOARD_DUMP: { + // dump flash area + sequence.push_back(new flash::DumpArea(flash::FLASH_DEVICE_TYPE, address_, length_, dumpHostPath_, 1, USE_BULK_PROTOCOL)); + } + break; + + default: + cout << "No action to be performed" << endl; + + } + + // shut down + sequence.push_back(new System::Shutdown()); + + return sequence; +} + +CommandSequence_t SequenceFactory::getProfileSequence() +{ + if (SequenceFactory::flashmode_ == string("flash")) { + return getSequence(BOARD_FLASH); + } + + if (SequenceFactory::flashmode_ == string("erase")) { + return getSequence(BOARD_ERASE); + } + + if (SequenceFactory::flashmode_ == string("dump")) { + return getSequence(BOARD_DUMP); + } else { + return getSequence(defaultSequence_); + } +} + +/* @} */ diff --git a/riff/SequenceFactory.h b/riff/SequenceFactory.h new file mode 100755 index 0000000..a208f90 --- /dev/null +++ b/riff/SequenceFactory.h @@ -0,0 +1,92 @@ +/* + * SequenceFactory.h + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup SequenceFactory + * @{ + * + * Setup execution sequence for different mode (erase/flash). + */ + +#pragma once +#include "Config.h" +#include + +// Command class forward declaration +class Command; + +typedef std::vector CommandSequence_t; + +class SequenceFactory +{ +public: + /** + * @brief Sequence ID. + */ + enum SequenceId { + BOARD_FLASH, /**< Board flash sequence.> */ + BOARD_ERASE, /**< Board erase sequence. > */ + BOARD_DUMP /**< Board dump sequence. > */ + }; + + /** + * @brief Protocol type. + */ + enum UseBulk { + USE_COMMAND_PROTOCOL, /**< Use command protocol. > */ + USE_BULK_PROTOCOL /**< Use bulk protocol. > */ + }; + + /** + * @brief Delete buffer mode. + */ + enum DeleteBuffer { + DELETE_BUFFER_NO, /**< Don't delete buffer. > */ + DELETE_BUFFER_YES /**< Delete buffer. > */ + }; + + /** + * @brief Get new command sequence for the specified sequence ID. + * + * @param[in] id - ID of the sequence. + * @return Newly created command sequence. + */ + static CommandSequence_t getSequence(SequenceId id); + + /** + * @brief Get new command sequence for the sequence ID specified in the profile. + * + * @return Newly created command sequence. + */ + static CommandSequence_t getProfileSequence(); + + /** + * + */ + static void setArguments(const char* configPath, const char* mode, const char* flashImg, const char* address, const char* length, const char* dumpPath); + + static const char* configPath_; + static const char* flashmode_; + static const char* flashImgPath_; + static const char* dumpHostPath_; + static int address_; + static int length_; +private: + SequenceFactory(); + SequenceFactory(const SequenceFactory&); + ~SequenceFactory(); + + static const SequenceId defaultSequence_; + +}; + +/* @} */ diff --git a/riff/Shutdown.cpp b/riff/Shutdown.cpp new file mode 100755 index 0000000..3dcd1a9 --- /dev/null +++ b/riff/Shutdown.cpp @@ -0,0 +1,47 @@ +/* + * Shutdown.cpp + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup Commands + * @{ + */ + +#include "Shutdown.h" +#include "DUT.h" +using namespace System; + +Shutdown::Shutdown(): + logger_("ShutDown") +{ + +} + +int Shutdown::run(DUT* dut) +{ + logger_.log(Logger::INFO, "Shutting down device..."); + int error = System_Shutdown(dut->getLCDContext()); + if (0 != error) + { + logger_.log(Logger::ERROR,"LCD ERROR: Device shutdown failed %d", error); + return error; + } + + logger_.log(Logger::INFO, "Device shutdown finished successfully"); + return error; +} + +const char * Shutdown::get_command_name() +{ + return (char *)"SHUTDOWN"; +} + +/* @} */ diff --git a/riff/Shutdown.h b/riff/Shutdown.h new file mode 100755 index 0000000..812ffb5 --- /dev/null +++ b/riff/Shutdown.h @@ -0,0 +1,50 @@ +/* + * Shutdown.h + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup Commands + * @{ + */ + +#pragma once + +#include "Command.h" +#include "Logger.h" + +namespace System +{ +/** + * @brief Class implementing Shutdown command from System group. + */ +class Shutdown : public Command +{ +public: + /** + * @brief Default constructor taking no parameters. + */ + Shutdown(); + + /** + * @brief Method that executes the shutdown of the platform. + * + * @param[in] dut - Specific DUT instance on which to execute the command. + * @return int - Command execution error (0 on success, non-0 otherwise). + */ + int run(DUT* dut); + + const char * get_command_name(); +private: + Logger logger_; +}; +} + +/* @} */ diff --git a/riff/constants.h b/riff/constants.h new file mode 100755 index 0000000..28111af --- /dev/null +++ b/riff/constants.h @@ -0,0 +1,29 @@ +/* + * constants.h + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup Constants + * @{ + */ + +#pragma once + +namespace flash +{ +// flash archive type defined by the loader. +const char* const FLASH_ARCHIVE_TYPE = "x-empflash/flasharchive"; + +// device id +const char* const FLASH_DEVICE_TYPE = "/flash0"; +} + +/* @} */ diff --git a/riff/main.cpp b/riff/main.cpp new file mode 100755 index 0000000..076a65f --- /dev/null +++ b/riff/main.cpp @@ -0,0 +1,240 @@ +/* + * main.cpp + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup main + * @{ + */ +#include "main.h" +#include "CDAL.h" +#include "DutManager.h" +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +bool isDone = false; +const string info = \ + "\n \ +----------------------- riff - Raw Image File Flasher -------------------------\n \ +Version: 0.4.1\n \ +" + "Flash a device. Try `riff --help' for more information. \n \ +" + "-------------------------------------------------------------------------------"; + +const string cmdHelpString = " \n \ +Usage: riff [OPTION]...[FILE]...\n\n \ +Available command line arguments are:\n\n \ + -h, --help\t Display this help message.\n \ + -m, --mode ACTION\t Select the mode.\n \ + ACTION is `flash`, `erase` or `dump`\n \ + -c, --config PATH\t Give path to configuration file.\n \ + -f, --flashimage IMAGEPATH\t Give path to flashimage.\n \ + -a, --address FLASHADDR\t Give a start address in hex.\n \ + -l, --length HEXLENGTH Length of the dump [Byte] in hex.\n \ + -d, --dumppath DUMPPATH File path on PC where to store dump.\n \ + -v, --verbose\t Shows more detailed information.\n \ + --version\t Shows version information.\n \ +"; + + +int main(int argc, char* argv[]) +{ + signal(SIGINT, interrupt); + + cout << info << endl; + + handleCmdLineInput(argc, argv); + + logger_ = new Logger("Application"); + logger_->log(Logger::INFO, "Using config file %s", configFile); + + //Parse the config file. + config_ = new Config(configFile); + + // if flashimage path has not been set from commandline + //then use the path in the config file if it is set there. + if (!strlen(flashimage)) { + if (config_->valueExists("FLASH_IMG_PATH")) { + strcpy(flashimage, config_->getValue("FLASH_IMG_PATH")); + } + } + + // Set the LCM path from ConfigFile, init the USB driver and set the callback function + SetLCMLibPath(config_->getValue("LCMLIBPATH")); + usb_init_driver(config_->getValue("VENDORID"), config_->getValue("PRODUCTID")); + usb_set_listen_callback(UsbDeviceEventCallback); + + + logger_->log(Logger::PROGRESS, "Listening on USB for device connection..."); + + while (!isDone) { + sleep(1); + } + + usb_deinit_driver(); + + _exit(exitstatus); +} + +void interrupt(int param) +{ + logger_->log(Logger::PROGRESS, "Program interrupted..."); + exitstatus = 1; + isDone = true; +} + +void UsbDeviceEventCallback(DeviceStatus_t status, DeviceEvent_t event, Device_t device) +{ + if (COMM_DEVICE_SUCCESS == status) { + const DUT* dut; + + switch (event) { + case LIBUSB_DEVICE_CONNECTED: + + logger_->log(Logger::INFO, "Device detected on USB@%u", comm_get_physical_address(device)); + dut = DutManager::createDut(device); + + if (0 != dut) { + logger_->log(Logger::PROGRESS, "Connected %s", dut->getId()); + } + + break; + case LIBUSB_DEVICE_DISCONNECTED: { + logger_->log(Logger::INFO, "Disconnect detected on USB@%u", comm_get_physical_address(device)); + dut = DutManager::getDut(device); + + if (0 != dut) { + exitstatus = dut->getErrorCode(); + logger_->log(Logger::PROGRESS, "Disconnected %s", dut->getId()); + DutManager::destroyDut(device); + } + + isDone = true; + } + break; + default: + logger_->log(Logger::ERROR, "Unknown USB event %d", event); + break; + } + } else { + logger_->log(Logger::ERROR, "USB device error %d", status); + } +} +void handleCmdLineInput(int argc, char* argv[]) +{ + string input; + bool configPathSet = false; + + for (int i = 1; i != argc; ++i) { + input = argv[i]; + + if ("-h" == input || "--help" == input) { + cout << cmdHelpString << endl; + _exit(0); + } + + else if ("-v" == input || "--verbose" == input) { + Logger::verbose_ = true; + } + + else if ("--version" == input) { + _exit(0); + } + + else if ("-m" == input || "--mode" == input) { + i = checkCmdLineArgument(argc, i, argv, mode); + } + + else if ("-c" == input || "--config" == input) { + configPathSet = true; + i = checkCmdLineArgument(argc, i, argv, configFile); + + } + + else if ("-f" == input || "--flashimage" == input) { + i = checkCmdLineArgument(argc, i, argv, flashimage); + } + + else if ("-a" == input || "--address" == input) { + i = checkCmdLineArgument(argc, i, argv, address); + } + + else if ("-l" == input || "--length" == input) { + i = checkCmdLineArgument(argc, i, argv, length); + } + + else if ("-d" == input || "--dumppath" == input) { + i = checkCmdLineArgument(argc, i, argv, dumpPath); + } else { + cout << "Unknown option: " << input << endl; + } + } + + if (!configPathSet) { + FILE* userConfig; + char* home = getenv("HOME"); + char homeConfigPath[50]; + strcpy(homeConfigPath, home); + strcat(homeConfigPath, "/.riff/config"); + + + userConfig = fopen(homeConfigPath, "rb"); + + if (userConfig != NULL) { + strcpy(configFile, homeConfigPath); + fclose(userConfig); + } + else + { + // It will check the default config in /usr/share folder otherwise + userConfig = fopen(configFile, "r"); + if(userConfig == NULL) + { + cout << cmdHelpString << endl; + _exit(0); + } + } + + + } + if (*dumpPath == '\0') { + //Sets default dump path if not provided + char* home = getenv("HOME"); + strcpy(dumpPath, home); + strcat(dumpPath, "/flashdump.bin"); + } + SequenceFactory::setArguments(configFile, mode, flashimage, address, length, dumpPath); +} + +int checkCmdLineArgument(int argc, int counter, char* argv[], char* var) +{ + counter++; + + if (counter < argc) + + { + strcpy(var, argv[counter]); + } else { + cout << "Please give a parameter to the option" << endl; + counter--; + } + + return counter; +} + +/* @} */ diff --git a/riff/main.h b/riff/main.h new file mode 100755 index 0000000..7826eb4 --- /dev/null +++ b/riff/main.h @@ -0,0 +1,75 @@ +/* + * main.h + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda , + * Ola Borgelin , + * Karin Hedlund , + * Markus Andersson for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +/* + * @addtogroup main + * @{ + */ +#pragma once + +#include "CDAL.h" +#include "Config.h" +#include +#include "Logger.h" +#include +#define PATH_LENGTH 256 +#define MODE_STR_LENGTH 6 + +enum ConnectionType { + USB_CONNECTION, /**< USB connection. */ +}; + + +Logger* logger_; +Config* config_; +char configFile[PATH_LENGTH] = "/usr/share/riff/config"; +char flashimage[PATH_LENGTH] = "\0"; +char address[PATH_LENGTH] = "0"; +char length[PATH_LENGTH] = "0"; +char dumpPath[PATH_LENGTH] = "\0"; +char mode[MODE_STR_LENGTH]; +int exitstatus = 0; + +/** + * @brief USB device event callback function. + * + * This function is called when USB device is connected or disconnected. + * + * @param[in] status - Status of the device. + * @param[in] event - Event that was triggered. + * @param[in] device - The device that triggered the event. + */ +void UsbDeviceEventCallback(DeviceStatus_t status, DeviceEvent_t event, Device_t device); + +/** + * @brief Handling user commands from commandline + * + * This function is called to handle the commands typed by the user from commandline. + * + * @param[in] argc - number of inparameters + * @param[in] argv[] - inparameters given by user + */ +void handleCmdLineInput(int argc, char* argv[]); + +/** + * @brief Checking commandline arguments to the options + * + */ +int checkCmdLineArgument(int argc, int counter, char* argv[], char* var); + +/** + * @brief Handles user interupts (CTRL+C) + * + */ +void interrupt(int param); + +/* @} */ diff --git a/riff/riff.mk b/riff/riff.mk new file mode 100755 index 0000000..f083879 --- /dev/null +++ b/riff/riff.mk @@ -0,0 +1,85 @@ +# Makefile - riff + +CXX=g++ +CFLAGS=-I../os_wrappers -I../CDAL -D_FILE_OFFSET_BITS=64 +CXXFLAGS=$(CFLAGS) +LD=$(CXX) $(CXXFLAGS) +LDFLAGS=-L../CDAL +LIBS+=-llcdriver -lcdal -lstdc++ -lc + +ifndef TARGET +TARGET=riff +endif + +.PHONY: all +all: $(TARGET) + +%.o: %.cpp + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -c $< + +SOURCE_FILES= \ + ./Config.cpp \ + ./DumpArea.cpp \ + ./DUT.cpp \ + ./DUTManager.cpp \ + ./EraseArea.cpp \ + ./InitializeDut.cpp \ + ./Logger.cpp \ + ./main.cpp \ + ./ProcessRawImage.cpp \ + ./SequenceFactory.cpp \ + ./Shutdown.cpp \ + ../os_wrappers/CriticalSection.cpp \ + ../os_wrappers/Event.cpp \ + ../os_wrappers/Thread.cpp + +HEADER_FILES= \ + ./Command.h \ + ./Config.h \ + ./constants.h \ + ./DumpArea.h \ + ./DUT.h \ + ./DUTManager.h \ + ./EraseArea.h \ + ./InitializeDut.h \ + ./Logger.h \ + ./main.h \ + ./ProcessRawImage.h \ + ./SequenceFactory.h \ + ./Shutdown.h \ + ../os_wrappers/CriticalSection.h \ + ../os_wrappers/Event.h \ + ../os_wrappers/Thread.h \ + ../os_wrappers/Utilities.h \ + +OBJS= \ + ./Config.o \ + ./DumpArea.o \ + ./DUT.o \ + ./DutManager.o \ + ./EraseArea.o \ + ./InitializeDut.o \ + ./Logger.o \ + ./main.o \ + ./ProcessRawImage.o \ + ./SequenceFactory.o \ + ./Shutdown.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) riff.dep *.orig + +.PHONY: depends +depends: + -$(CXX) $(CXXFLAGS) $(CPPFLAGS) -MM $(filter %.c %.cc %.cpp %.cxx,$(SRCS)) > riff.dep + +-include riff.dep + -- cgit v1.2.3