From 7b1ae2029ad33a38e1e718a33e2879325b389332 Mon Sep 17 00:00:00 2001 From: Srimanta Panda Date: Thu, 13 Oct 2011 10:17:16 +0200 Subject: Added Windows Support RIFF will be supported for the Windows platform. It requires libusb-win32 library to build it. --- CDAL/AsyncCommunication.cpp | 2 +- CDAL/CDAL.cpp | 116 +++++++++++++++++- CDAL/CDAL.h | 12 +- CDAL/CDAL.mk | 5 +- CDAL/CDAL.vcproj | 286 ++++++++++++++++++++++++++++++++++++++++++++ CDAL/CommDevice.cpp | 2 + CDAL/CommDeviceManager.cpp | 1 + CDAL/CommDeviceManager.h | 4 + CDAL/CommException.cpp | 1 + CDAL/Debug.h | 10 +- CDAL/LibusbDevice.cpp | 1 + CDAL/LibusbDevice_win.cpp | 195 ++++++++++++++++++++++++++++++ CDAL/LibusbDevice_win.h | 51 ++++++++ CDAL/stdafx.cpp | 13 ++ CDAL/stdafx.h | 30 +++++ 15 files changed, 721 insertions(+), 8 deletions(-) create mode 100644 CDAL/CDAL.vcproj create mode 100644 CDAL/LibusbDevice_win.cpp create mode 100644 CDAL/LibusbDevice_win.h create mode 100644 CDAL/stdafx.cpp create mode 100644 CDAL/stdafx.h (limited to 'CDAL') diff --git a/CDAL/AsyncCommunication.cpp b/CDAL/AsyncCommunication.cpp index e767a61..3987de8 100644 --- a/CDAL/AsyncCommunication.cpp +++ b/CDAL/AsyncCommunication.cpp @@ -9,7 +9,7 @@ * License terms: 3-clause BSD license * */ - +#include "stdafx.h" #include "AsyncCommunication.h" #include "CommDevice.h" #include "Debug.h" diff --git a/CDAL/CDAL.cpp b/CDAL/CDAL.cpp index 99cadf7..6b4a457 100644 --- a/CDAL/CDAL.cpp +++ b/CDAL/CDAL.cpp @@ -10,6 +10,7 @@ * */ +#include "stdafx.h" #include "CDAL.h" #include "Debug.h" #include "CommDevice.h" @@ -17,21 +18,28 @@ #include "CommException.h" #include "Event.h" #include "Thread.h" -#include "LibusbDevice.h" -#include #include #include #include +#ifdef _WIN32 +#include "LibusbDevice_win.h" +#else +#include "LibusbDevice.h" +#endif using namespace std; +#ifndef _WIN32 +static libusb_context* context; +#endif + static int DUT_VENDOR_ID = 0x04cc; static int DUT_PRODUCT_ID = 0x8500; -static libusb_context* context; static Thread* workerThread; static void* LibusbWorker(void* arg); volatile bool shutdown = false; int error = 0; + static EventCallback_t OnDeviceCallback = NULL; void usb_init_driver(const char* vendorId, const char* productId) @@ -44,8 +52,13 @@ void usb_init_driver(const char* vendorId, const char* productId) DUT_PRODUCT_ID = strtol(productId, NULL, 16); } +#ifdef _WIN32 + usb_init(); + usb_set_debug(2); +#else libusb_init(&context); - libusb_set_debug(context, 3); + libusb_set_debug(context, 2); +#endif workerThread = new Thread(LibusbWorker, 0); } @@ -63,7 +76,10 @@ void usb_deinit_driver() CommDeviceManager::destroyAll(); +#ifndef _WIN32 libusb_exit(context); +#endif + } void usb_destroy_device(Device_t device, int error_code) @@ -134,11 +150,102 @@ void comm_progress(void *Communication_p, unsigned long long totalbytes, fflush(stdout); } +#ifdef _WIN32 +// As we are going to use libusb 0.1 version in Windows, +// this function needs to be re-writtten with the API +// related to the 0.1 version. The libusb 1.0 and 0.1 +// differs a lot according to their function calls and +// the way USB devices are recognized and handled. +static void* LibusbWorker(void* arg) +{ + struct usb_bus *busses; + struct usb_bus *bus; + + while (!shutdown) { + + usb_find_busses(); + usb_find_devices(); + busses = usb_get_busses(); + + if(busses == NULL ) { + Debug::info("No USB device connected."); + Sleep(10); + continue; + } + + for (bus = busses; bus; bus = bus->next) { + struct usb_device *dev = NULL; + + for (dev = bus->devices; dev; dev = dev->next) { + if ((dev->descriptor.idProduct == DUT_PRODUCT_ID) && (dev->descriptor.idVendor == DUT_VENDOR_ID) && (!shutdown)) { + + LibusbDevice *device; + + device = CommDeviceManager::getDevice(dev); + + if (0 == device) { + // new device found + try { + device = CommDeviceManager::createDevice (dev); + 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; + struct usb_device *dev; + for (bus = busses; bus; bus = bus->next) { + for (dev = bus->devices; dev; dev = dev->next) { + if (dev == device->getPort()) { + connected = true; + break; + } + } + if(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; + } + } + + Sleep(10); + } + + return 0; +} +#else +// In Linux, libusb 1.0 version is used. Therefore, +// the below LibusbWorker function is based on API +// for libusb 1.0 for handling USB devices. 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; @@ -220,4 +327,5 @@ static void* LibusbWorker(void* arg __attribute__((unused))) return 0; } +#endif diff --git a/CDAL/CDAL.h b/CDAL/CDAL.h index d87b79b..33e6d18 100644 --- a/CDAL/CDAL.h +++ b/CDAL/CDAL.h @@ -14,12 +14,21 @@ * channel. */ #pragma once + +#if defined(_WIN32) +#ifdef CDAL_EXPORTS +#define CDAL_API __declspec(dllexport) +#else +#define CDAL_API __declspec(dllimport) +#endif +#elif defined(__linux__) #include #ifdef CDAL_EXPORTS #define CDAL_API __attribute__((visibility("default"))) #else #define CDAL_API #endif +#endif // type of the device typedef enum { @@ -38,7 +47,8 @@ typedef enum { 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 + COMM_DEVICE_PEEK_BUFFER_SIZE_ERROR = 8, + COMM_DEVICE_LIBUSB_FAILED_TO_SET_CONFIG = 9 } DeviceStatus_t; // device events codes diff --git a/CDAL/CDAL.mk b/CDAL/CDAL.mk index e324b7d..043015c 100644 --- a/CDAL/CDAL.mk +++ b/CDAL/CDAL.mk @@ -24,6 +24,7 @@ SOURCE_FILES= \ ./CommDeviceManager.cpp \ ./CommException.cpp \ ./LibusbDevice.cpp \ + ./stdafx.cpp \ ../os_wrappers/CriticalSection.cpp \ ../os_wrappers/Event.cpp \ ../os_wrappers/Thread.cpp \ @@ -34,8 +35,9 @@ HEADER_FILES= \ ./CommDevice.h \ ./CommDeviceManager.h \ ./CommException.h \ - ./LibusbDevice.h \ ./Debug.h \ + ./LibusbDevice.h \ + ./stdafx.h \ ../os_wrappers/CriticalSection.h \ ../os_wrappers/Event.h \ ../os_wrappers/Thread.h \ @@ -48,6 +50,7 @@ OBJS= \ ./CommDeviceManager.o \ ./CommException.o \ ./LibusbDevice.o \ + ./stdafx.o \ ../os_wrappers/CriticalSection.o \ ../os_wrappers/Event.o \ ../os_wrappers/Thread.o \ diff --git a/CDAL/CDAL.vcproj b/CDAL/CDAL.vcproj new file mode 100644 index 0000000..19485c4 --- /dev/null +++ b/CDAL/CDAL.vcproj @@ -0,0 +1,286 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CDAL/CommDevice.cpp b/CDAL/CommDevice.cpp index d4c1f71..4f4b1c7 100644 --- a/CDAL/CommDevice.cpp +++ b/CDAL/CommDevice.cpp @@ -10,9 +10,11 @@ * */ +#include "stdafx.h" #include "CommDevice.h" #include "AsyncCommunication.h" +using namespace std; CommDevice::CommDevice(): isReadCanceled_(false) { async_ = new AsyncCommunication(this); diff --git a/CDAL/CommDeviceManager.cpp b/CDAL/CommDeviceManager.cpp index bd94651..0c9da52 100644 --- a/CDAL/CommDeviceManager.cpp +++ b/CDAL/CommDeviceManager.cpp @@ -10,6 +10,7 @@ * */ +#include "stdafx.h" #include "CommDeviceManager.h" #include "CommDevice.h" #include "CommException.h" diff --git a/CDAL/CommDeviceManager.h b/CDAL/CommDeviceManager.h index fef36de..b13a613 100644 --- a/CDAL/CommDeviceManager.h +++ b/CDAL/CommDeviceManager.h @@ -15,7 +15,11 @@ #include "CDAL.h" #include "CommDevice.h" #include +#ifdef _WIN32 +#include +#else #include +#endif class CommDeviceManager { diff --git a/CDAL/CommException.cpp b/CDAL/CommException.cpp index 4485cba..81f78f7 100644 --- a/CDAL/CommException.cpp +++ b/CDAL/CommException.cpp @@ -10,6 +10,7 @@ * */ +#include "stdafx.h" #include "CommException.h" #include #include diff --git a/CDAL/Debug.h b/CDAL/Debug.h index 69e5112..cb3a503 100644 --- a/CDAL/Debug.h +++ b/CDAL/Debug.h @@ -13,9 +13,9 @@ #pragma once //#define _DEBUG +#define DEBUG_ERROR #ifdef _DEBUG #define DEBUG_INFO -#define DEBUG_ERROR #define DEBUG_HEXDUMP #define DEBUG_HEXDUMP_SIZE 1024 #endif @@ -35,7 +35,11 @@ class Debug { public: +#ifdef _WIN32 + inline static void error(const char* format, ...) { +#else inline static void error(const char* format, ...) __attribute__((format(printf, 1, 0))) { +#endif #ifdef DEBUG_ERROR flockfile(stdout); printf("ERROR - "); @@ -49,7 +53,11 @@ public: #endif } +#ifdef _WIN32 + static inline void info(const char* format, ...) { +#else static inline void info(const char* format, ...) __attribute__((format(printf, 1, 0))) { +#endif #ifdef DEBUG_INFO flockfile(stdout); printf("INFO - "); diff --git a/CDAL/LibusbDevice.cpp b/CDAL/LibusbDevice.cpp index 337df46..6e2c670 100644 --- a/CDAL/LibusbDevice.cpp +++ b/CDAL/LibusbDevice.cpp @@ -10,6 +10,7 @@ * */ +#include "stdafx.h" #include "LibusbDevice.h" #include "Debug.h" #include "CommException.h" diff --git a/CDAL/LibusbDevice_win.cpp b/CDAL/LibusbDevice_win.cpp new file mode 100644 index 0000000..443adcc --- /dev/null +++ b/CDAL/LibusbDevice_win.cpp @@ -0,0 +1,195 @@ +/* + * LibusbDevice_win.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 "stdafx.h" +#include "LibusbDevice_win.h" +#include "Debug.h" +#include "CommException.h" +#include +#include + +using namespace std; + +#define MIN(A, B) ((A) < (B) ? (A) : (B)) + +LibusbDevice::LibusbDevice(struct usb_device* device): + device_(device), + inEndpoint_(-1), + outEndpoint_(-1) +{ + // get the handle for the device + handle_ = usb_open(device_); + if (handle_ == NULL) { + throw CommException("failed to open usb device", COMM_DEVICE_LIBUSB_FAILED_TO_OPEN_PORT); + } + + int configValue_ = device_->config->bConfigurationValue; + + if (usb_set_configuration(handle_, configValue_)) { + Debug::error("Setting configuration failed!" ); + throw CommException("Setting configuration failed!", COMM_DEVICE_LIBUSB_FAILED_TO_SET_CONFIG); + } else { + Debug::info("Configuration has been set successfully.."); + } + + if ((this->device_->config->bNumInterfaces > 0) && (this->device_->config->interface->num_altsetting > 0)) { + interfaceNumber_ = device_->config->interface->altsetting->bInterfaceNumber; + +#if defined(LIBUSB_HAS_GET_DRIVER_NP) +#if defined(LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP) + char name[256]; + if (usb_get_driver_np(handle_, interfaceNumber_, (char *) name, sizeof(name))) { + Debug::info("Fetching driver name failed: %s", usb_strerror()); + } else { + Debug::info("Driver name: %s", name); + if (usb_detach_kernel_driver_np(handle_, interfaceNumber_)) { + Debug::error("Detaching kernel driver failed: %s", usb_strerror()); + } + Debug::info(""Kernel driver has been detached successfully."); + } +#endif +#endif + + // Claim the interface for the device + if (usb_claim_interface(handle_, interfaceNumber_)) { + opened_ = false; + Debug::error("Claiming interface failed: %s", usb_strerror()); + throw CommException("Claiming interface failed", COMM_DEVICE_LIBUSB_FAILED_TO_CLAIM_INTERFACE); + } else { + Debug::info("Interface has been claimed successfuly.."); + opened_ = true; + } + + Debug::info("Looking for endpoints.."); + + //find default endpoints + for (int i = 0; i < device_->config->interface->altsetting->bNumEndpoints; i++) { + if ((inEndpoint_ != -1) && (outEndpoint_ != -1)) break; + if (device_->config->interface->altsetting->endpoint[i].bEndpointAddress & 0x80) { + if ((inEndpoint_ == -1) + && ((device_->config->interface->altsetting->endpoint[i].bmAttributes & 0x3f) == 0x2)) + { + inEndpoint_ = device_->config->interface->altsetting->endpoint[i].bEndpointAddress; + Debug::info("Bulk IN endpoint found and ready to use on address %02xh", inEndpoint_); + } + } else { + if ((outEndpoint_ == -1) + && ((device_->config->interface->altsetting->endpoint[i].bmAttributes & 0x3f) == 0x2)) + { + outEndpoint_ = device_->config->interface->altsetting->endpoint[i].bEndpointAddress; + Debug::info("Bulk OUT endpoint found and ready to use on address %02xh", outEndpoint_); + } + } + } + + if ((inEndpoint_ == -1) || (outEndpoint_ == -1)) { + Debug::error("Bulk endpoints cannot be found!"); + throw CommException("Not able to set endpoints for device", COMM_DEVICE_LIBUSB_FAILED_TO_OPEN_PORT); + } + } + readBufferLength_ = 0; + readBufferHead_ = readBuffer_; +} + +LibusbDevice::~LibusbDevice() +{ + usb_release_interface(handle_, interfaceNumber_); + usb_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; + transfered = usb_bulk_read(handle_, inEndpoint_, readBuffer_, READ_BUFFER_SIZE, 100000); + + if (isReadCanceled_) { + Debug::info("LibusbDevice read: canceled..."); + Debug::hexdump("read canceled", dest, transfered); + isReadCanceled_ = false; + return COMM_DEVICE_CANCEL; + } + + if (transfered < 0) { + if( transfered == USB_TIMEOUT_ERROR) { + Debug::info("LibusbDevice read : Usb read timeout"); + continue; + } else { + Debug::info("LibusbDevice read: error %d occured", transfered); + return transfered; + } + } + + 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); + char* src = static_cast(buffer); + + while (size) { + int transfered; + //Call with timeout to enable possible cancel + transfered = usb_bulk_write(handle_, outEndpoint_, src, size, 100000); + if (transfered < 0) { + if( transfered == USB_TIMEOUT_ERROR) { + Debug::info("LibusbDevice write : Usb write timeout"); + continue; + } else { + Debug::info("LibusbDevice write: error %d occured", transfered); + return transfered; + } + } + + size -= transfered; + src += transfered; + } + + Debug::info("LibusbDevice write: complete"); + return 0; +} + +int LibusbDevice::getVendorId() +{ + return device_->descriptor.idVendor; +} + +struct usb_device* LibusbDevice::getPort() +{ + return device_; +} diff --git a/CDAL/LibusbDevice_win.h b/CDAL/LibusbDevice_win.h new file mode 100644 index 0000000..8ee484e --- /dev/null +++ b/CDAL/LibusbDevice_win.h @@ -0,0 +1,51 @@ +/* + * LibusbDevice_win.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 +#ifdef _WIN32 +#include +#else +#include +#endif +#include "CommDevice.h" + +// Timeout error code for usb transfer +#define USB_TIMEOUT_ERROR -116 + +class LibusbDevice : public CommDevice +{ +public: + LibusbDevice(struct usb_device* device); + ~LibusbDevice(); + + int read(void* buffer, size_t size); + int write(void* buffer, size_t size); + + int getVendorId(); + struct usb_device* getPort(); + + unsigned long getPhysicalAddress() { + return 0; + } +private: + struct usb_device* device_; + struct usb_dev_handle* handle_; + int interfaceNumber_; + int outEndpoint_; + int inEndpoint_; + bool opened_; + + static const int READ_BUFFER_SIZE = 4096; + char readBuffer_[READ_BUFFER_SIZE]; + char* readBufferHead_; + size_t readBufferLength_; +}; diff --git a/CDAL/stdafx.cpp b/CDAL/stdafx.cpp new file mode 100644 index 0000000..169b1ed --- /dev/null +++ b/CDAL/stdafx.cpp @@ -0,0 +1,13 @@ +/* + * stdafx.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 "stdafx.h" diff --git a/CDAL/stdafx.h b/CDAL/stdafx.h new file mode 100644 index 0000000..65d5da9 --- /dev/null +++ b/CDAL/stdafx.h @@ -0,0 +1,30 @@ +/* + * stdafx.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 + + +#ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files: +#include +#include +#include + +#include +#include +#include +#include +#else +#include +#endif // _WIN32 -- cgit v1.2.3