From d2244d83d1e2d48b4cdb7b708284153fcb4988ec Mon Sep 17 00:00:00 2001 From: Mathieu Rondonneau Date: Sun, 19 May 2013 21:49:53 -0700 Subject: [PATCH 001/120] OP-958: GCS HID plugin basic cleanup: - new plugin (opHID) to deprecate old one (rawhid). - remove pjrc HID api implementation. - add hidapi library taken from https://github.com/signal11/hidapi.git (copied files, the lib is not compiled from its git repo). - history of those files is broken (cp instead of git mv) but the history is all in rawhid plugin. - mac and windows not tested yet. --- .../src/plugins/opHID/hidapi/libusb/hid.c | 1423 +++++++++++++++++ .../src/plugins/opHID/hidapi/linux/hid.c | 786 +++++++++ .../src/plugins/opHID/hidapi/mac/hid.c | 1111 +++++++++++++ .../src/plugins/opHID/hidapi/windows/hid.c | 923 +++++++++++ .../src/plugins/opHID/inc/hidapi.h | 385 +++++ .../src/plugins/opHID/inc/opHID.h | 95 ++ .../src/plugins/opHID/inc/opHID_const.h | 66 + .../src/plugins/opHID/inc/opHID_global.h | 40 + .../src/plugins/opHID/inc/opHID_hidapi.h | 96 ++ .../src/plugins/opHID/inc/opHID_plugin.h | 101 ++ .../src/plugins/opHID/inc/opHID_usbmon.h | 203 +++ .../src/plugins/opHID/inc/opHID_usbsignal.h | 55 + .../src/plugins/opHID/opHID.pluginspec | 10 + .../openpilotgcs/src/plugins/opHID/opHID.pri | 3 + .../openpilotgcs/src/plugins/opHID/opHID.pro | 72 + .../src/plugins/opHID/opHID_dependencies.pri | 1 + .../src/plugins/opHID/src/opHID.cpp | 497 ++++++ .../src/plugins/opHID/src/opHID_hidapi.cpp | 380 +++++ .../src/plugins/opHID/src/opHID_plugin.cpp | 272 ++++ .../plugins/opHID/src/opHID_usbmon_linux.cpp | 245 +++ .../plugins/opHID/src/opHID_usbmon_mac.cpp | 244 +++ .../plugins/opHID/src/opHID_usbmon_win.cpp | 378 +++++ .../src/plugins/opHID/src/opHID_usbsignal.cpp | 74 + ground/openpilotgcs/src/plugins/plugins.pro | 10 +- .../src/plugins/powerlog/PowerLog.pluginspec | 2 +- .../powerlog/powerlog_dependencies.pri | 2 +- .../src/plugins/powerlog/powerlogplugin.cpp | 2 +- .../src/plugins/powerlog/powerlogplugin.h | 4 +- .../src/plugins/uploader/Uploader.pluginspec | 2 +- .../src/plugins/uploader/op_dfu.h | 8 +- .../uploader/uploader_dependencies.pri | 2 +- .../plugins/uploader/uploadergadgetwidget.h | 2 +- 32 files changed, 7477 insertions(+), 17 deletions(-) create mode 100644 ground/openpilotgcs/src/plugins/opHID/hidapi/libusb/hid.c create mode 100644 ground/openpilotgcs/src/plugins/opHID/hidapi/linux/hid.c create mode 100644 ground/openpilotgcs/src/plugins/opHID/hidapi/mac/hid.c create mode 100755 ground/openpilotgcs/src/plugins/opHID/hidapi/windows/hid.c create mode 100644 ground/openpilotgcs/src/plugins/opHID/inc/hidapi.h create mode 100644 ground/openpilotgcs/src/plugins/opHID/inc/opHID.h create mode 100644 ground/openpilotgcs/src/plugins/opHID/inc/opHID_const.h create mode 100644 ground/openpilotgcs/src/plugins/opHID/inc/opHID_global.h create mode 100644 ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h create mode 100644 ground/openpilotgcs/src/plugins/opHID/inc/opHID_plugin.h create mode 100644 ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h create mode 100644 ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbsignal.h create mode 100644 ground/openpilotgcs/src/plugins/opHID/opHID.pluginspec create mode 100644 ground/openpilotgcs/src/plugins/opHID/opHID.pri create mode 100644 ground/openpilotgcs/src/plugins/opHID/opHID.pro create mode 100644 ground/openpilotgcs/src/plugins/opHID/opHID_dependencies.pri create mode 100644 ground/openpilotgcs/src/plugins/opHID/src/opHID.cpp create mode 100644 ground/openpilotgcs/src/plugins/opHID/src/opHID_hidapi.cpp create mode 100644 ground/openpilotgcs/src/plugins/opHID/src/opHID_plugin.cpp create mode 100644 ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_linux.cpp create mode 100644 ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp create mode 100644 ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_win.cpp create mode 100644 ground/openpilotgcs/src/plugins/opHID/src/opHID_usbsignal.cpp diff --git a/ground/openpilotgcs/src/plugins/opHID/hidapi/libusb/hid.c b/ground/openpilotgcs/src/plugins/opHID/hidapi/libusb/hid.c new file mode 100644 index 000000000..94c1b3b69 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/hidapi/libusb/hid.c @@ -0,0 +1,1423 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + 8/22/2009 + Linux Version - 6/2/2010 + Libusb Version - 8/13/2010 + FreeBSD Version - 11/1/2011 + + Copyright 2009, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . +********************************************************/ + +#define _GNU_SOURCE /* needed for wcsdup() before glibc 2.10 */ + +/* C */ +#include +#include +#include +#include +#include +#include + +/* Unix */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* GNU / LibUSB */ +#include "libusb.h" +#include "iconv.h" + +#include "hidapi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef DEBUG_PRINTF +#define LOG(...) fprintf(stderr, __VA_ARGS__) +#else +#define LOG(...) do {} while (0) +#endif + +#ifndef __FreeBSD__ +#define DETACH_KERNEL_DRIVER +#endif + +/* Uncomment to enable the retrieval of Usage and Usage Page in +hid_enumerate(). Warning, on platforms different from FreeBSD +this is very invasive as it requires the detach +and re-attach of the kernel driver. See comments inside hid_enumerate(). +libusb HIDAPI programs are encouraged to use the interface number +instead to differentiate between interfaces on a composite HID device. */ +/*#define INVASIVE_GET_USAGE*/ + +/* Linked List of input reports received from the device. */ +struct input_report { + uint8_t *data; + size_t len; + struct input_report *next; +}; + + +struct hid_device_ { + /* Handle to the actual device. */ + libusb_device_handle *device_handle; + + /* Endpoint information */ + int input_endpoint; + int output_endpoint; + int input_ep_max_packet_size; + + /* The interface number of the HID */ + int interface; + + /* Indexes of Strings */ + int manufacturer_index; + int product_index; + int serial_index; + + /* Whether blocking reads are used */ + int blocking; /* boolean */ + + /* Read thread objects */ + pthread_t thread; + pthread_mutex_t mutex; /* Protects input_reports */ + pthread_cond_t condition; + pthread_barrier_t barrier; /* Ensures correct startup sequence */ + int shutdown_thread; + struct libusb_transfer *transfer; + + /* List of received input reports. */ + struct input_report *input_reports; +}; + +static libusb_context *usb_context = NULL; + +uint16_t get_usb_code_for_current_locale(void); +static int return_data(hid_device *dev, unsigned char *data, size_t length); + +static hid_device *new_hid_device(void) +{ + hid_device *dev = calloc(1, sizeof(hid_device)); + dev->blocking = 1; + + pthread_mutex_init(&dev->mutex, NULL); + pthread_cond_init(&dev->condition, NULL); + pthread_barrier_init(&dev->barrier, NULL, 2); + + return dev; +} + +static void free_hid_device(hid_device *dev) +{ + /* Clean up the thread objects */ + pthread_barrier_destroy(&dev->barrier); + pthread_cond_destroy(&dev->condition); + pthread_mutex_destroy(&dev->mutex); + + /* Free the device itself */ + free(dev); +} + +#if 0 +/*TODO: Implement this funciton on hidapi/libusb.. */ +static void register_error(hid_device *device, const char *op) +{ + +} +#endif + +#ifdef INVASIVE_GET_USAGE +/* Get bytes from a HID Report Descriptor. + Only call with a num_bytes of 0, 1, 2, or 4. */ +static uint32_t get_bytes(uint8_t *rpt, size_t len, size_t num_bytes, size_t cur) +{ + /* Return if there aren't enough bytes. */ + if (cur + num_bytes >= len) + return 0; + + if (num_bytes == 0) + return 0; + else if (num_bytes == 1) { + return rpt[cur+1]; + } + else if (num_bytes == 2) { + return (rpt[cur+2] * 256 + rpt[cur+1]); + } + else if (num_bytes == 4) { + return (rpt[cur+4] * 0x01000000 + + rpt[cur+3] * 0x00010000 + + rpt[cur+2] * 0x00000100 + + rpt[cur+1] * 0x00000001); + } + else + return 0; +} + +/* Retrieves the device's Usage Page and Usage from the report + descriptor. The algorithm is simple, as it just returns the first + Usage and Usage Page that it finds in the descriptor. + The return value is 0 on success and -1 on failure. */ +static int get_usage(uint8_t *report_descriptor, size_t size, + unsigned short *usage_page, unsigned short *usage) +{ + unsigned int i = 0; + int size_code; + int data_len, key_size; + int usage_found = 0, usage_page_found = 0; + + while (i < size) { + int key = report_descriptor[i]; + int key_cmd = key & 0xfc; + + //printf("key: %02hhx\n", key); + + if ((key & 0xf0) == 0xf0) { + /* This is a Long Item. The next byte contains the + length of the data section (value) for this key. + See the HID specification, version 1.11, section + 6.2.2.3, titled "Long Items." */ + if (i+1 < size) + data_len = report_descriptor[i+1]; + else + data_len = 0; /* malformed report */ + key_size = 3; + } + else { + /* This is a Short Item. The bottom two bits of the + key contain the size code for the data section + (value) for this key. Refer to the HID + specification, version 1.11, section 6.2.2.2, + titled "Short Items." */ + size_code = key & 0x3; + switch (size_code) { + case 0: + case 1: + case 2: + data_len = size_code; + break; + case 3: + data_len = 4; + break; + default: + /* Can't ever happen since size_code is & 0x3 */ + data_len = 0; + break; + }; + key_size = 1; + } + + if (key_cmd == 0x4) { + *usage_page = get_bytes(report_descriptor, size, data_len, i); + usage_page_found = 1; + //printf("Usage Page: %x\n", (uint32_t)*usage_page); + } + if (key_cmd == 0x8) { + *usage = get_bytes(report_descriptor, size, data_len, i); + usage_found = 1; + //printf("Usage: %x\n", (uint32_t)*usage); + } + + if (usage_page_found && usage_found) + return 0; /* success */ + + /* Skip over this key and it's associated data */ + i += data_len + key_size; + } + + return -1; /* failure */ +} +#endif /* INVASIVE_GET_USAGE */ + +#ifdef __FreeBSD__ +/* The FreeBSD version of libusb doesn't have this funciton. In mainline + libusb, it's inlined in libusb.h. This function will bear a striking + resemblence to that one, because there's about one way to code it. + + Note that the data parameter is Unicode in UTF-16LE encoding. + Return value is the number of bytes in data, or LIBUSB_ERROR_*. + */ +static inline int libusb_get_string_descriptor(libusb_device_handle *dev, + uint8_t descriptor_index, uint16_t lang_id, + unsigned char *data, int length) +{ + return libusb_control_transfer(dev, + LIBUSB_ENDPOINT_IN | 0x0, /* Endpoint 0 IN */ + LIBUSB_REQUEST_GET_DESCRIPTOR, + (LIBUSB_DT_STRING << 8) | descriptor_index, + lang_id, data, (uint16_t) length, 1000); +} + +#endif + + +/* Get the first language the device says it reports. This comes from + USB string #0. */ +static uint16_t get_first_language(libusb_device_handle *dev) +{ + uint16_t buf[32]; + int len; + + /* Get the string from libusb. */ + len = libusb_get_string_descriptor(dev, + 0x0, /* String ID */ + 0x0, /* Language */ + (unsigned char*)buf, + sizeof(buf)); + if (len < 4) + return 0x0; + + return buf[1]; /* First two bytes are len and descriptor type. */ +} + +static int is_language_supported(libusb_device_handle *dev, uint16_t lang) +{ + uint16_t buf[32]; + int len; + int i; + + /* Get the string from libusb. */ + len = libusb_get_string_descriptor(dev, + 0x0, /* String ID */ + 0x0, /* Language */ + (unsigned char*)buf, + sizeof(buf)); + if (len < 4) + return 0x0; + + + len /= 2; /* language IDs are two-bytes each. */ + /* Start at index 1 because there are two bytes of protocol data. */ + for (i = 1; i < len; i++) { + if (buf[i] == lang) + return 1; + } + + return 0; +} + + +/* This function returns a newly allocated wide string containing the USB + device string numbered by the index. The returned string must be freed + by using free(). */ +static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx) +{ + char buf[512]; + int len; + wchar_t *str = NULL; + wchar_t wbuf[256]; + + /* iconv variables */ + iconv_t ic; + size_t inbytes; + size_t outbytes; + size_t res; +#ifdef __FreeBSD__ + const char *inptr; +#else + char *inptr; +#endif + char *outptr; + + /* Determine which language to use. */ + uint16_t lang; + lang = get_usb_code_for_current_locale(); + if (!is_language_supported(dev, lang)) + lang = get_first_language(dev); + + /* Get the string from libusb. */ + len = libusb_get_string_descriptor(dev, + idx, + lang, + (unsigned char*)buf, + sizeof(buf)); + if (len < 0) + return NULL; + + /* buf does not need to be explicitly NULL-terminated because + it is only passed into iconv() which does not need it. */ + + /* Initialize iconv. */ + ic = iconv_open("WCHAR_T", "UTF-16LE"); + if (ic == (iconv_t)-1) { + LOG("iconv_open() failed\n"); + return NULL; + } + + /* Convert to native wchar_t (UTF-32 on glibc/BSD systems). + Skip the first character (2-bytes). */ + inptr = buf+2; + inbytes = len-2; + outptr = (char*) wbuf; + outbytes = sizeof(wbuf); + res = iconv(ic, &inptr, &inbytes, &outptr, &outbytes); + if (res == (size_t)-1) { + LOG("iconv() failed\n"); + goto err; + } + + /* Write the terminating NULL. */ + wbuf[sizeof(wbuf)/sizeof(wbuf[0])-1] = 0x00000000; + if (outbytes >= sizeof(wbuf[0])) + *((wchar_t*)outptr) = 0x00000000; + + /* Allocate and copy the string. */ + str = wcsdup(wbuf); + +err: + iconv_close(ic); + + return str; +} + +static char *make_path(libusb_device *dev, int interface_number) +{ + char str[64]; + snprintf(str, sizeof(str), "%04x:%04x:%02x", + libusb_get_bus_number(dev), + libusb_get_device_address(dev), + interface_number); + str[sizeof(str)-1] = '\0'; + + return strdup(str); +} + + +int HID_API_EXPORT hid_init(void) +{ + if (!usb_context) { + const char *locale; + + /* Init Libusb */ + if (libusb_init(&usb_context)) + return -1; + + /* Set the locale if it's not set. */ + locale = setlocale(LC_CTYPE, NULL); + if (!locale) + setlocale(LC_CTYPE, ""); + } + + return 0; +} + +int HID_API_EXPORT hid_exit(void) +{ + if (usb_context) { + libusb_exit(usb_context); + usb_context = NULL; + } + + return 0; +} + +struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) +{ + libusb_device **devs; + libusb_device *dev; + libusb_device_handle *handle; + ssize_t num_devs; + int i = 0; + + struct hid_device_info *root = NULL; /* return object */ + struct hid_device_info *cur_dev = NULL; + + if(hid_init() < 0) + return NULL; + + num_devs = libusb_get_device_list(usb_context, &devs); + if (num_devs < 0) + return NULL; + while ((dev = devs[i++]) != NULL) { + struct libusb_device_descriptor desc; + struct libusb_config_descriptor *conf_desc = NULL; + int j, k; + int interface_num = 0; + + int res = libusb_get_device_descriptor(dev, &desc); + unsigned short dev_vid = desc.idVendor; + unsigned short dev_pid = desc.idProduct; + + res = libusb_get_active_config_descriptor(dev, &conf_desc); + if (res < 0) + libusb_get_config_descriptor(dev, 0, &conf_desc); + if (conf_desc) { + for (j = 0; j < conf_desc->bNumInterfaces; j++) { + const struct libusb_interface *intf = &conf_desc->interface[j]; + for (k = 0; k < intf->num_altsetting; k++) { + const struct libusb_interface_descriptor *intf_desc; + intf_desc = &intf->altsetting[k]; + if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) { + interface_num = intf_desc->bInterfaceNumber; + + /* Check the VID/PID against the arguments */ + if ((vendor_id == 0x0 || vendor_id == dev_vid) && + (product_id == 0x0 || product_id == dev_pid)) { + struct hid_device_info *tmp; + + /* VID/PID match. Create the record. */ + tmp = calloc(1, sizeof(struct hid_device_info)); + if (cur_dev) { + cur_dev->next = tmp; + } + else { + root = tmp; + } + cur_dev = tmp; + + /* Fill out the record */ + cur_dev->next = NULL; + cur_dev->path = make_path(dev, interface_num); + + res = libusb_open(dev, &handle); + + if (res >= 0) { + /* Serial Number */ + if (desc.iSerialNumber > 0) + cur_dev->serial_number = + get_usb_string(handle, desc.iSerialNumber); + + /* Manufacturer and Product strings */ + if (desc.iManufacturer > 0) + cur_dev->manufacturer_string = + get_usb_string(handle, desc.iManufacturer); + if (desc.iProduct > 0) + cur_dev->product_string = + get_usb_string(handle, desc.iProduct); + +#ifdef INVASIVE_GET_USAGE +{ + /* + This section is removed because it is too + invasive on the system. Getting a Usage Page + and Usage requires parsing the HID Report + descriptor. Getting a HID Report descriptor + involves claiming the interface. Claiming the + interface involves detaching the kernel driver. + Detaching the kernel driver is hard on the system + because it will unclaim interfaces (if another + app has them claimed) and the re-attachment of + the driver will sometimes change /dev entry names. + It is for these reasons that this section is + #if 0. For composite devices, use the interface + field in the hid_device_info struct to distinguish + between interfaces. */ + unsigned char data[256]; +#ifdef DETACH_KERNEL_DRIVER + int detached = 0; + /* Usage Page and Usage */ + res = libusb_kernel_driver_active(handle, interface_num); + if (res == 1) { + res = libusb_detach_kernel_driver(handle, interface_num); + if (res < 0) + LOG("Couldn't detach kernel driver, even though a kernel driver was attached."); + else + detached = 1; + } +#endif + res = libusb_claim_interface(handle, interface_num); + if (res >= 0) { + /* Get the HID Report Descriptor. */ + res = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_INTERFACE, LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_REPORT << 8)|interface_num, 0, data, sizeof(data), 5000); + if (res >= 0) { + unsigned short page=0, usage=0; + /* Parse the usage and usage page + out of the report descriptor. */ + get_usage(data, res, &page, &usage); + cur_dev->usage_page = page; + cur_dev->usage = usage; + } + else + LOG("libusb_control_transfer() for getting the HID report failed with %d\n", res); + + /* Release the interface */ + res = libusb_release_interface(handle, interface_num); + if (res < 0) + LOG("Can't release the interface.\n"); + } + else + LOG("Can't claim interface %d\n", res); +#ifdef DETACH_KERNEL_DRIVER + /* Re-attach kernel driver if necessary. */ + if (detached) { + res = libusb_attach_kernel_driver(handle, interface_num); + if (res < 0) + LOG("Couldn't re-attach kernel driver.\n"); + } +#endif +} +#endif /* INVASIVE_GET_USAGE */ + + libusb_close(handle); + } + /* VID/PID */ + cur_dev->vendor_id = dev_vid; + cur_dev->product_id = dev_pid; + + /* Release Number */ + cur_dev->release_number = desc.bcdDevice; + + /* Interface Number */ + cur_dev->interface_number = interface_num; + } + } + } /* altsettings */ + } /* interfaces */ + libusb_free_config_descriptor(conf_desc); + } + } + + libusb_free_device_list(devs, 1); + + return root; +} + +void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) +{ + struct hid_device_info *d = devs; + while (d) { + struct hid_device_info *next = d->next; + free(d->path); + free(d->serial_number); + free(d->manufacturer_string); + free(d->product_string); + free(d); + d = next; + } +} + +hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) +{ + struct hid_device_info *devs, *cur_dev; + const char *path_to_open = NULL; + hid_device *handle = NULL; + + devs = hid_enumerate(vendor_id, product_id); + cur_dev = devs; + while (cur_dev) { + if (cur_dev->vendor_id == vendor_id && + cur_dev->product_id == product_id) { + if (serial_number) { + if (wcscmp(serial_number, cur_dev->serial_number) == 0) { + path_to_open = cur_dev->path; + break; + } + } + else { + path_to_open = cur_dev->path; + break; + } + } + cur_dev = cur_dev->next; + } + + if (path_to_open) { + /* Open the device */ + handle = hid_open_path(path_to_open); + } + + hid_free_enumeration(devs); + + return handle; +} + +static void read_callback(struct libusb_transfer *transfer) +{ + hid_device *dev = transfer->user_data; + int res; + + if (transfer->status == LIBUSB_TRANSFER_COMPLETED) { + + struct input_report *rpt = malloc(sizeof(*rpt)); + rpt->data = malloc(transfer->actual_length); + memcpy(rpt->data, transfer->buffer, transfer->actual_length); + rpt->len = transfer->actual_length; + rpt->next = NULL; + + pthread_mutex_lock(&dev->mutex); + + /* Attach the new report object to the end of the list. */ + if (dev->input_reports == NULL) { + /* The list is empty. Put it at the root. */ + dev->input_reports = rpt; + pthread_cond_signal(&dev->condition); + } + else { + /* Find the end of the list and attach. */ + struct input_report *cur = dev->input_reports; + int num_queued = 0; + while (cur->next != NULL) { + cur = cur->next; + num_queued++; + } + cur->next = rpt; + + /* Pop one off if we've reached 30 in the queue. This + way we don't grow forever if the user never reads + anything from the device. */ + if (num_queued > 30) { + return_data(dev, NULL, 0); + } + } + pthread_mutex_unlock(&dev->mutex); + } + else if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { + dev->shutdown_thread = 1; + return; + } + else if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE) { + dev->shutdown_thread = 1; + return; + } + else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) { + //LOG("Timeout (normal)\n"); + } + else { + LOG("Unknown transfer code: %d\n", transfer->status); + } + + /* Re-submit the transfer object. */ + res = libusb_submit_transfer(transfer); + if (res != 0) { + LOG("Unable to submit URB. libusb error code: %d\n", res); + dev->shutdown_thread = 1; + } +} + + +static void *read_thread(void *param) +{ + hid_device *dev = param; + unsigned char *buf; + const size_t length = dev->input_ep_max_packet_size; + + /* Set up the transfer object. */ + buf = malloc(length); + dev->transfer = libusb_alloc_transfer(0); + libusb_fill_interrupt_transfer(dev->transfer, + dev->device_handle, + dev->input_endpoint, + buf, + length, + read_callback, + dev, + 5000/*timeout*/); + + /* Make the first submission. Further submissions are made + from inside read_callback() */ + libusb_submit_transfer(dev->transfer); + + /* Notify the main thread that the read thread is up and running. */ + pthread_barrier_wait(&dev->barrier); + + /* Handle all the events. */ + while (!dev->shutdown_thread) { + int res; + res = libusb_handle_events(usb_context); + if (res < 0) { + /* There was an error. */ + LOG("read_thread(): libusb reports error # %d\n", res); + + /* Break out of this loop only on fatal error.*/ + if (res != LIBUSB_ERROR_BUSY && + res != LIBUSB_ERROR_TIMEOUT && + res != LIBUSB_ERROR_OVERFLOW && + res != LIBUSB_ERROR_INTERRUPTED) { + break; + } + } + } + + /* Cancel any transfer that may be pending. This call will fail + if no transfers are pending, but that's OK. */ + if (libusb_cancel_transfer(dev->transfer) == 0) { + /* The transfer was cancelled, so wait for its completion. */ + libusb_handle_events(usb_context); + } + + /* Now that the read thread is stopping, Wake any threads which are + waiting on data (in hid_read_timeout()). Do this under a mutex to + make sure that a thread which is about to go to sleep waiting on + the condition acutally will go to sleep before the condition is + signaled. */ + pthread_mutex_lock(&dev->mutex); + pthread_cond_broadcast(&dev->condition); + pthread_mutex_unlock(&dev->mutex); + + /* The dev->transfer->buffer and dev->transfer objects are cleaned up + in hid_close(). They are not cleaned up here because this thread + could end either due to a disconnect or due to a user + call to hid_close(). In both cases the objects can be safely + cleaned up after the call to pthread_join() (in hid_close()), but + since hid_close() calls libusb_cancel_transfer(), on these objects, + they can not be cleaned up here. */ + + return NULL; +} + + +hid_device * HID_API_EXPORT hid_open_path(const char *path) +{ + hid_device *dev = NULL; + + libusb_device **devs; + libusb_device *usb_dev; + int res; + int d = 0; + int good_open = 0; + + dev = new_hid_device(); + + if(hid_init() < 0) + return NULL; + + libusb_get_device_list(usb_context, &devs); + while ((usb_dev = devs[d++]) != NULL) { + struct libusb_device_descriptor desc; + struct libusb_config_descriptor *conf_desc = NULL; + int i,j,k; + libusb_get_device_descriptor(usb_dev, &desc); + + if (libusb_get_active_config_descriptor(usb_dev, &conf_desc) < 0) + continue; + for (j = 0; j < conf_desc->bNumInterfaces; j++) { + const struct libusb_interface *intf = &conf_desc->interface[j]; + for (k = 0; k < intf->num_altsetting; k++) { + const struct libusb_interface_descriptor *intf_desc; + intf_desc = &intf->altsetting[k]; + if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) { + char *dev_path = make_path(usb_dev, intf_desc->bInterfaceNumber); + if (!strcmp(dev_path, path)) { + /* Matched Paths. Open this device */ + + /* OPEN HERE */ + res = libusb_open(usb_dev, &dev->device_handle); + if (res < 0) { + LOG("can't open device\n"); + free(dev_path); + break; + } + good_open = 1; +#ifdef DETACH_KERNEL_DRIVER + /* Detach the kernel driver, but only if the + device is managed by the kernel */ + if (libusb_kernel_driver_active(dev->device_handle, intf_desc->bInterfaceNumber) == 1) { + res = libusb_detach_kernel_driver(dev->device_handle, intf_desc->bInterfaceNumber); + if (res < 0) { + libusb_close(dev->device_handle); + LOG("Unable to detach Kernel Driver\n"); + free(dev_path); + good_open = 0; + break; + } + } +#endif + res = libusb_claim_interface(dev->device_handle, intf_desc->bInterfaceNumber); + if (res < 0) { + LOG("can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res); + free(dev_path); + libusb_close(dev->device_handle); + good_open = 0; + break; + } + + /* Store off the string descriptor indexes */ + dev->manufacturer_index = desc.iManufacturer; + dev->product_index = desc.iProduct; + dev->serial_index = desc.iSerialNumber; + + /* Store off the interface number */ + dev->interface = intf_desc->bInterfaceNumber; + + /* Find the INPUT and OUTPUT endpoints. An + OUTPUT endpoint is not required. */ + for (i = 0; i < intf_desc->bNumEndpoints; i++) { + const struct libusb_endpoint_descriptor *ep + = &intf_desc->endpoint[i]; + + /* Determine the type and direction of this + endpoint. */ + int is_interrupt = + (ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) + == LIBUSB_TRANSFER_TYPE_INTERRUPT; + int is_output = + (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) + == LIBUSB_ENDPOINT_OUT; + int is_input = + (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) + == LIBUSB_ENDPOINT_IN; + + /* Decide whether to use it for intput or output. */ + if (dev->input_endpoint == 0 && + is_interrupt && is_input) { + /* Use this endpoint for INPUT */ + dev->input_endpoint = ep->bEndpointAddress; + dev->input_ep_max_packet_size = ep->wMaxPacketSize; + } + if (dev->output_endpoint == 0 && + is_interrupt && is_output) { + /* Use this endpoint for OUTPUT */ + dev->output_endpoint = ep->bEndpointAddress; + } + } + + pthread_create(&dev->thread, NULL, read_thread, dev); + + /* Wait here for the read thread to be initialized. */ + pthread_barrier_wait(&dev->barrier); + + } + free(dev_path); + } + } + } + libusb_free_config_descriptor(conf_desc); + + } + + libusb_free_device_list(devs, 1); + + /* If we have a good handle, return it. */ + if (good_open) { + return dev; + } + else { + /* Unable to open any devices. */ + free_hid_device(dev); + return NULL; + } +} + + +int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) +{ + int res; + int report_number = data[0]; + int skipped_report_id = 0; + + if (report_number == 0x0) { + data++; + length--; + skipped_report_id = 1; + } + + + if (dev->output_endpoint <= 0) { + /* No interrput out endpoint. Use the Control Endpoint */ + res = libusb_control_transfer(dev->device_handle, + LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT, + 0x09/*HID Set_Report*/, + (2/*HID output*/ << 8) | report_number, + dev->interface, + (unsigned char *)data, length, + 1000/*timeout millis*/); + + if (res < 0) + return -1; + + if (skipped_report_id) + length++; + + return length; + } + else { + /* Use the interrupt out endpoint */ + int actual_length; + res = libusb_interrupt_transfer(dev->device_handle, + dev->output_endpoint, + (unsigned char*)data, + length, + &actual_length, 1000); + + if (res < 0) + return -1; + + if (skipped_report_id) + actual_length++; + + return actual_length; + } +} + +/* Helper function, to simplify hid_read(). + This should be called with dev->mutex locked. */ +static int return_data(hid_device *dev, unsigned char *data, size_t length) +{ + /* Copy the data out of the linked list item (rpt) into the + return buffer (data), and delete the liked list item. */ + struct input_report *rpt = dev->input_reports; + size_t len = (length < rpt->len)? length: rpt->len; + if (len > 0) + memcpy(data, rpt->data, len); + dev->input_reports = rpt->next; + free(rpt->data); + free(rpt); + return len; +} + +static void cleanup_mutex(void *param) +{ + hid_device *dev = param; + pthread_mutex_unlock(&dev->mutex); +} + + +int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) +{ + int bytes_read = -1; + +#if 0 + int transferred; + int res = libusb_interrupt_transfer(dev->device_handle, dev->input_endpoint, data, length, &transferred, 5000); + LOG("transferred: %d\n", transferred); + return transferred; +#endif + + pthread_mutex_lock(&dev->mutex); + pthread_cleanup_push(&cleanup_mutex, dev); + + /* There's an input report queued up. Return it. */ + if (dev->input_reports) { + /* Return the first one */ + bytes_read = return_data(dev, data, length); + goto ret; + } + + if (dev->shutdown_thread) { + /* This means the device has been disconnected. + An error code of -1 should be returned. */ + bytes_read = -1; + goto ret; + } + + if (milliseconds == -1) { + /* Blocking */ + while (!dev->input_reports && !dev->shutdown_thread) { + pthread_cond_wait(&dev->condition, &dev->mutex); + } + if (dev->input_reports) { + bytes_read = return_data(dev, data, length); + } + } + else if (milliseconds > 0) { + /* Non-blocking, but called with timeout. */ + int res; + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += milliseconds / 1000; + ts.tv_nsec += (milliseconds % 1000) * 1000000; + if (ts.tv_nsec >= 1000000000L) { + ts.tv_sec++; + ts.tv_nsec -= 1000000000L; + } + + while (!dev->input_reports && !dev->shutdown_thread) { + res = pthread_cond_timedwait(&dev->condition, &dev->mutex, &ts); + if (res == 0) { + if (dev->input_reports) { + bytes_read = return_data(dev, data, length); + break; + } + + /* If we're here, there was a spurious wake up + or the read thread was shutdown. Run the + loop again (ie: don't break). */ + } + else if (res == ETIMEDOUT) { + /* Timed out. */ + bytes_read = 0; + break; + } + else { + /* Error. */ + bytes_read = -1; + break; + } + } + } + else { + /* Purely non-blocking */ + bytes_read = 0; + } + +ret: + pthread_mutex_unlock(&dev->mutex); + pthread_cleanup_pop(0); + + return bytes_read; +} + +int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) +{ + return hid_read_timeout(dev, data, length, dev->blocking ? -1 : 0); +} + +int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) +{ + dev->blocking = !nonblock; + + return 0; +} + + +int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) +{ + int res = -1; + int skipped_report_id = 0; + int report_number = data[0]; + + if (report_number == 0x0) { + data++; + length--; + skipped_report_id = 1; + } + + res = libusb_control_transfer(dev->device_handle, + LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT, + 0x09/*HID set_report*/, + (3/*HID feature*/ << 8) | report_number, + dev->interface, + (unsigned char *)data, length, + 1000/*timeout millis*/); + + if (res < 0) + return -1; + + /* Account for the report ID */ + if (skipped_report_id) + length++; + + return length; +} + +int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) +{ + int res = -1; + int skipped_report_id = 0; + int report_number = data[0]; + + if (report_number == 0x0) { + /* Offset the return buffer by 1, so that the report ID + will remain in byte 0. */ + data++; + length--; + skipped_report_id = 1; + } + res = libusb_control_transfer(dev->device_handle, + LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN, + 0x01/*HID get_report*/, + (3/*HID feature*/ << 8) | report_number, + dev->interface, + (unsigned char *)data, length, + 1000/*timeout millis*/); + + if (res < 0) + return -1; + + if (skipped_report_id) + res++; + + return res; +} + + +void HID_API_EXPORT hid_close(hid_device *dev) +{ + if (!dev) + return; + + /* Cause read_thread() to stop. */ + dev->shutdown_thread = 1; + libusb_cancel_transfer(dev->transfer); + + /* Wait for read_thread() to end. */ + pthread_join(dev->thread, NULL); + + /* Clean up the Transfer objects allocated in read_thread(). */ + free(dev->transfer->buffer); + libusb_free_transfer(dev->transfer); + + /* release the interface */ + libusb_release_interface(dev->device_handle, dev->interface); + + /* Close the handle */ + libusb_close(dev->device_handle); + + /* Clear out the queue of received reports. */ + pthread_mutex_lock(&dev->mutex); + while (dev->input_reports) { + return_data(dev, NULL, 0); + } + pthread_mutex_unlock(&dev->mutex); + + free_hid_device(dev); +} + + +int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return hid_get_indexed_string(dev, dev->manufacturer_index, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return hid_get_indexed_string(dev, dev->product_index, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return hid_get_indexed_string(dev, dev->serial_index, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) +{ + wchar_t *str; + + str = get_usb_string(dev->device_handle, string_index); + if (str) { + wcsncpy(string, str, maxlen); + string[maxlen-1] = L'\0'; + free(str); + return 0; + } + else + return -1; +} + + +HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) +{ + return NULL; +} + + +struct lang_map_entry { + const char *name; + const char *string_code; + uint16_t usb_code; +}; + +#define LANG(name,code,usb_code) { name, code, usb_code } +static struct lang_map_entry lang_map[] = { + LANG("Afrikaans", "af", 0x0436), + LANG("Albanian", "sq", 0x041C), + LANG("Arabic - United Arab Emirates", "ar_ae", 0x3801), + LANG("Arabic - Bahrain", "ar_bh", 0x3C01), + LANG("Arabic - Algeria", "ar_dz", 0x1401), + LANG("Arabic - Egypt", "ar_eg", 0x0C01), + LANG("Arabic - Iraq", "ar_iq", 0x0801), + LANG("Arabic - Jordan", "ar_jo", 0x2C01), + LANG("Arabic - Kuwait", "ar_kw", 0x3401), + LANG("Arabic - Lebanon", "ar_lb", 0x3001), + LANG("Arabic - Libya", "ar_ly", 0x1001), + LANG("Arabic - Morocco", "ar_ma", 0x1801), + LANG("Arabic - Oman", "ar_om", 0x2001), + LANG("Arabic - Qatar", "ar_qa", 0x4001), + LANG("Arabic - Saudi Arabia", "ar_sa", 0x0401), + LANG("Arabic - Syria", "ar_sy", 0x2801), + LANG("Arabic - Tunisia", "ar_tn", 0x1C01), + LANG("Arabic - Yemen", "ar_ye", 0x2401), + LANG("Armenian", "hy", 0x042B), + LANG("Azeri - Latin", "az_az", 0x042C), + LANG("Azeri - Cyrillic", "az_az", 0x082C), + LANG("Basque", "eu", 0x042D), + LANG("Belarusian", "be", 0x0423), + LANG("Bulgarian", "bg", 0x0402), + LANG("Catalan", "ca", 0x0403), + LANG("Chinese - China", "zh_cn", 0x0804), + LANG("Chinese - Hong Kong SAR", "zh_hk", 0x0C04), + LANG("Chinese - Macau SAR", "zh_mo", 0x1404), + LANG("Chinese - Singapore", "zh_sg", 0x1004), + LANG("Chinese - Taiwan", "zh_tw", 0x0404), + LANG("Croatian", "hr", 0x041A), + LANG("Czech", "cs", 0x0405), + LANG("Danish", "da", 0x0406), + LANG("Dutch - Netherlands", "nl_nl", 0x0413), + LANG("Dutch - Belgium", "nl_be", 0x0813), + LANG("English - Australia", "en_au", 0x0C09), + LANG("English - Belize", "en_bz", 0x2809), + LANG("English - Canada", "en_ca", 0x1009), + LANG("English - Caribbean", "en_cb", 0x2409), + LANG("English - Ireland", "en_ie", 0x1809), + LANG("English - Jamaica", "en_jm", 0x2009), + LANG("English - New Zealand", "en_nz", 0x1409), + LANG("English - Phillippines", "en_ph", 0x3409), + LANG("English - Southern Africa", "en_za", 0x1C09), + LANG("English - Trinidad", "en_tt", 0x2C09), + LANG("English - Great Britain", "en_gb", 0x0809), + LANG("English - United States", "en_us", 0x0409), + LANG("Estonian", "et", 0x0425), + LANG("Farsi", "fa", 0x0429), + LANG("Finnish", "fi", 0x040B), + LANG("Faroese", "fo", 0x0438), + LANG("French - France", "fr_fr", 0x040C), + LANG("French - Belgium", "fr_be", 0x080C), + LANG("French - Canada", "fr_ca", 0x0C0C), + LANG("French - Luxembourg", "fr_lu", 0x140C), + LANG("French - Switzerland", "fr_ch", 0x100C), + LANG("Gaelic - Ireland", "gd_ie", 0x083C), + LANG("Gaelic - Scotland", "gd", 0x043C), + LANG("German - Germany", "de_de", 0x0407), + LANG("German - Austria", "de_at", 0x0C07), + LANG("German - Liechtenstein", "de_li", 0x1407), + LANG("German - Luxembourg", "de_lu", 0x1007), + LANG("German - Switzerland", "de_ch", 0x0807), + LANG("Greek", "el", 0x0408), + LANG("Hebrew", "he", 0x040D), + LANG("Hindi", "hi", 0x0439), + LANG("Hungarian", "hu", 0x040E), + LANG("Icelandic", "is", 0x040F), + LANG("Indonesian", "id", 0x0421), + LANG("Italian - Italy", "it_it", 0x0410), + LANG("Italian - Switzerland", "it_ch", 0x0810), + LANG("Japanese", "ja", 0x0411), + LANG("Korean", "ko", 0x0412), + LANG("Latvian", "lv", 0x0426), + LANG("Lithuanian", "lt", 0x0427), + LANG("F.Y.R.O. Macedonia", "mk", 0x042F), + LANG("Malay - Malaysia", "ms_my", 0x043E), + LANG("Malay – Brunei", "ms_bn", 0x083E), + LANG("Maltese", "mt", 0x043A), + LANG("Marathi", "mr", 0x044E), + LANG("Norwegian - Bokml", "no_no", 0x0414), + LANG("Norwegian - Nynorsk", "no_no", 0x0814), + LANG("Polish", "pl", 0x0415), + LANG("Portuguese - Portugal", "pt_pt", 0x0816), + LANG("Portuguese - Brazil", "pt_br", 0x0416), + LANG("Raeto-Romance", "rm", 0x0417), + LANG("Romanian - Romania", "ro", 0x0418), + LANG("Romanian - Republic of Moldova", "ro_mo", 0x0818), + LANG("Russian", "ru", 0x0419), + LANG("Russian - Republic of Moldova", "ru_mo", 0x0819), + LANG("Sanskrit", "sa", 0x044F), + LANG("Serbian - Cyrillic", "sr_sp", 0x0C1A), + LANG("Serbian - Latin", "sr_sp", 0x081A), + LANG("Setsuana", "tn", 0x0432), + LANG("Slovenian", "sl", 0x0424), + LANG("Slovak", "sk", 0x041B), + LANG("Sorbian", "sb", 0x042E), + LANG("Spanish - Spain (Traditional)", "es_es", 0x040A), + LANG("Spanish - Argentina", "es_ar", 0x2C0A), + LANG("Spanish - Bolivia", "es_bo", 0x400A), + LANG("Spanish - Chile", "es_cl", 0x340A), + LANG("Spanish - Colombia", "es_co", 0x240A), + LANG("Spanish - Costa Rica", "es_cr", 0x140A), + LANG("Spanish - Dominican Republic", "es_do", 0x1C0A), + LANG("Spanish - Ecuador", "es_ec", 0x300A), + LANG("Spanish - Guatemala", "es_gt", 0x100A), + LANG("Spanish - Honduras", "es_hn", 0x480A), + LANG("Spanish - Mexico", "es_mx", 0x080A), + LANG("Spanish - Nicaragua", "es_ni", 0x4C0A), + LANG("Spanish - Panama", "es_pa", 0x180A), + LANG("Spanish - Peru", "es_pe", 0x280A), + LANG("Spanish - Puerto Rico", "es_pr", 0x500A), + LANG("Spanish - Paraguay", "es_py", 0x3C0A), + LANG("Spanish - El Salvador", "es_sv", 0x440A), + LANG("Spanish - Uruguay", "es_uy", 0x380A), + LANG("Spanish - Venezuela", "es_ve", 0x200A), + LANG("Southern Sotho", "st", 0x0430), + LANG("Swahili", "sw", 0x0441), + LANG("Swedish - Sweden", "sv_se", 0x041D), + LANG("Swedish - Finland", "sv_fi", 0x081D), + LANG("Tamil", "ta", 0x0449), + LANG("Tatar", "tt", 0X0444), + LANG("Thai", "th", 0x041E), + LANG("Turkish", "tr", 0x041F), + LANG("Tsonga", "ts", 0x0431), + LANG("Ukrainian", "uk", 0x0422), + LANG("Urdu", "ur", 0x0420), + LANG("Uzbek - Cyrillic", "uz_uz", 0x0843), + LANG("Uzbek – Latin", "uz_uz", 0x0443), + LANG("Vietnamese", "vi", 0x042A), + LANG("Xhosa", "xh", 0x0434), + LANG("Yiddish", "yi", 0x043D), + LANG("Zulu", "zu", 0x0435), + LANG(NULL, NULL, 0x0), +}; + +uint16_t get_usb_code_for_current_locale(void) +{ + char *locale; + char search_string[64]; + char *ptr; + struct lang_map_entry *lang; + + /* Get the current locale. */ + locale = setlocale(0, NULL); + if (!locale) + return 0x0; + + /* Make a copy of the current locale string. */ + strncpy(search_string, locale, sizeof(search_string)); + search_string[sizeof(search_string)-1] = '\0'; + + /* Chop off the encoding part, and make it lower case. */ + ptr = search_string; + while (*ptr) { + *ptr = tolower(*ptr); + if (*ptr == '.') { + *ptr = '\0'; + break; + } + ptr++; + } + + /* Find the entry which matches the string code of our locale. */ + lang = lang_map; + while (lang->string_code) { + if (!strcmp(lang->string_code, search_string)) { + return lang->usb_code; + } + lang++; + } + + /* There was no match. Find with just the language only. */ + /* Chop off the variant. Chop it off at the '_'. */ + ptr = search_string; + while (*ptr) { + *ptr = tolower(*ptr); + if (*ptr == '_') { + *ptr = '\0'; + break; + } + ptr++; + } + +#if 0 /* TODO: Do we need this? */ + /* Find the entry which matches the string code of our language. */ + lang = lang_map; + while (lang->string_code) { + if (!strcmp(lang->string_code, search_string)) { + return lang->usb_code; + } + lang++; + } +#endif + + /* Found nothing. */ + return 0x0; +} + +#ifdef __cplusplus +} +#endif diff --git a/ground/openpilotgcs/src/plugins/opHID/hidapi/linux/hid.c b/ground/openpilotgcs/src/plugins/opHID/hidapi/linux/hid.c new file mode 100644 index 000000000..38f67537c --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/hidapi/linux/hid.c @@ -0,0 +1,786 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + 8/22/2009 + Linux Version - 6/2/2009 + + Copyright 2009, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . +********************************************************/ + +/* C */ +#include +#include +#include +#include +#include + +/* Unix */ +#include +#include +#include +#include +#include +#include +#include + +/* Linux */ +#include +#include +#include +#include + +#include "hidapi.h" + +/* Definitions from linux/hidraw.h. Since these are new, some distros + may not have header files which contain them. */ +#ifndef HIDIOCSFEATURE +#define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len) +#endif +#ifndef HIDIOCGFEATURE +#define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len) +#endif + + +/* USB HID device property names */ +const char *device_string_names[] = { + "manufacturer", + "product", + "serial", +}; + +/* Symbolic names for the properties above */ +enum device_string_id { + DEVICE_STRING_MANUFACTURER, + DEVICE_STRING_PRODUCT, + DEVICE_STRING_SERIAL, + + DEVICE_STRING_COUNT, +}; + +struct hid_device_ { + int device_handle; + int blocking; + int uses_numbered_reports; +}; + + +static __u32 kernel_version = 0; + +static hid_device *new_hid_device(void) +{ + hid_device *dev = calloc(1, sizeof(hid_device)); + dev->device_handle = -1; + dev->blocking = 1; + dev->uses_numbered_reports = 0; + + return dev; +} + + +/* The caller must free the returned string with free(). */ +static wchar_t *utf8_to_wchar_t(const char *utf8) +{ + wchar_t *ret = NULL; + + if (utf8) { + size_t wlen = mbstowcs(NULL, utf8, 0); + if ((size_t) -1 == wlen) { + return wcsdup(L""); + } + ret = calloc(wlen+1, sizeof(wchar_t)); + mbstowcs(ret, utf8, wlen+1); + ret[wlen] = 0x0000; + } + + return ret; +} + +/* Get an attribute value from a udev_device and return it as a whar_t + string. The returned string must be freed with free() when done.*/ +static wchar_t *copy_udev_string(struct udev_device *dev, const char *udev_name) +{ + return utf8_to_wchar_t(udev_device_get_sysattr_value(dev, udev_name)); +} + +/* uses_numbered_reports() returns 1 if report_descriptor describes a device + which contains numbered reports. */ +static int uses_numbered_reports(__u8 *report_descriptor, __u32 size) { + unsigned int i = 0; + int size_code; + int data_len, key_size; + + while (i < size) { + int key = report_descriptor[i]; + + /* Check for the Report ID key */ + if (key == 0x85/*Report ID*/) { + /* This device has a Report ID, which means it uses + numbered reports. */ + return 1; + } + + //printf("key: %02hhx\n", key); + + if ((key & 0xf0) == 0xf0) { + /* This is a Long Item. The next byte contains the + length of the data section (value) for this key. + See the HID specification, version 1.11, section + 6.2.2.3, titled "Long Items." */ + if (i+1 < size) + data_len = report_descriptor[i+1]; + else + data_len = 0; /* malformed report */ + key_size = 3; + } + else { + /* This is a Short Item. The bottom two bits of the + key contain the size code for the data section + (value) for this key. Refer to the HID + specification, version 1.11, section 6.2.2.2, + titled "Short Items." */ + size_code = key & 0x3; + switch (size_code) { + case 0: + case 1: + case 2: + data_len = size_code; + break; + case 3: + data_len = 4; + break; + default: + /* Can't ever happen since size_code is & 0x3 */ + data_len = 0; + break; + }; + key_size = 1; + } + + /* Skip over this key and it's associated data */ + i += data_len + key_size; + } + + /* Didn't find a Report ID key. Device doesn't use numbered reports. */ + return 0; +} + +/* + * The caller is responsible for free()ing the (newly-allocated) character + * strings pointed to by serial_number_utf8 and product_name_utf8 after use. + */ +static int +parse_uevent_info(const char *uevent, int *bus_type, + unsigned short *vendor_id, unsigned short *product_id, + char **serial_number_utf8, char **product_name_utf8) +{ + char *tmp = strdup(uevent); + char *saveptr = NULL; + char *line; + char *key; + char *value; + + int found_id = 0; + int found_serial = 0; + int found_name = 0; + + line = strtok_r(tmp, "\n", &saveptr); + while (line != NULL) { + /* line: "KEY=value" */ + key = line; + value = strchr(line, '='); + if (!value) { + goto next_line; + } + *value = '\0'; + value++; + + if (strcmp(key, "HID_ID") == 0) { + /** + * type vendor product + * HID_ID=0003:000005AC:00008242 + **/ + int ret = sscanf(value, "%x:%hx:%hx", bus_type, vendor_id, product_id); + if (ret == 3) { + found_id = 1; + } + } else if (strcmp(key, "HID_NAME") == 0) { + /* The caller has to free the product name */ + *product_name_utf8 = strdup(value); + found_name = 1; + } else if (strcmp(key, "HID_UNIQ") == 0) { + /* The caller has to free the serial number */ + *serial_number_utf8 = strdup(value); + found_serial = 1; + } + +next_line: + line = strtok_r(NULL, "\n", &saveptr); + } + + free(tmp); + return (found_id && found_name && found_serial); +} + + +static int get_device_string(hid_device *dev, enum device_string_id key, wchar_t *string, size_t maxlen) +{ + struct udev *udev; + struct udev_device *udev_dev, *parent, *hid_dev; + struct stat s; + int ret = -1; + char *serial_number_utf8 = NULL; + char *product_name_utf8 = NULL; + + /* Create the udev object */ + udev = udev_new(); + if (!udev) { + printf("Can't create udev\n"); + return -1; + } + + /* Get the dev_t (major/minor numbers) from the file handle. */ + fstat(dev->device_handle, &s); + /* Open a udev device from the dev_t. 'c' means character device. */ + udev_dev = udev_device_new_from_devnum(udev, 'c', s.st_rdev); + if (udev_dev) { + hid_dev = udev_device_get_parent_with_subsystem_devtype( + udev_dev, + "hid", + NULL); + if (hid_dev) { + unsigned short dev_vid; + unsigned short dev_pid; + int bus_type; + size_t retm; + + ret = parse_uevent_info( + udev_device_get_sysattr_value(hid_dev, "uevent"), + &bus_type, + &dev_vid, + &dev_pid, + &serial_number_utf8, + &product_name_utf8); + + if (bus_type == BUS_BLUETOOTH) { + switch (key) { + case DEVICE_STRING_MANUFACTURER: + wcsncpy(string, L"", maxlen); + ret = 0; + break; + case DEVICE_STRING_PRODUCT: + retm = mbstowcs(string, product_name_utf8, maxlen); + ret = (retm == (size_t)-1)? -1: 0; + break; + case DEVICE_STRING_SERIAL: + retm = mbstowcs(string, serial_number_utf8, maxlen); + ret = (retm == (size_t)-1)? -1: 0; + break; + case DEVICE_STRING_COUNT: + default: + ret = -1; + break; + } + } + else { + /* This is a USB device. Find its parent USB Device node. */ + parent = udev_device_get_parent_with_subsystem_devtype( + udev_dev, + "usb", + "usb_device"); + if (parent) { + const char *str; + const char *key_str = NULL; + + if (key >= 0 && key < DEVICE_STRING_COUNT) { + key_str = device_string_names[key]; + } else { + ret = -1; + goto end; + } + + str = udev_device_get_sysattr_value(parent, key_str); + if (str) { + /* Convert the string from UTF-8 to wchar_t */ + retm = mbstowcs(string, str, maxlen); + ret = (retm == (size_t)-1)? -1: 0; + goto end; + } + } + } + } + } + +end: + free(serial_number_utf8); + free(product_name_utf8); + + udev_device_unref(udev_dev); + /* parent and hid_dev don't need to be (and can't be) unref'd. + I'm not sure why, but they'll throw double-free() errors. */ + udev_unref(udev); + + return ret; +} + +int HID_API_EXPORT hid_init(void) +{ + const char *locale; + + /* Set the locale if it's not set. */ + locale = setlocale(LC_CTYPE, NULL); + if (!locale) + setlocale(LC_CTYPE, ""); + + return 0; +} + +int HID_API_EXPORT hid_exit(void) +{ + /* Nothing to do for this in the Linux/hidraw implementation. */ + return 0; +} + + +struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) +{ + struct udev *udev; + struct udev_enumerate *enumerate; + struct udev_list_entry *devices, *dev_list_entry; + + struct hid_device_info *root = NULL; /* return object */ + struct hid_device_info *cur_dev = NULL; + struct hid_device_info *prev_dev = NULL; /* previous device */ + + hid_init(); + + /* Create the udev object */ + udev = udev_new(); + if (!udev) { + printf("Can't create udev\n"); + return NULL; + } + + /* Create a list of the devices in the 'hidraw' subsystem. */ + enumerate = udev_enumerate_new(udev); + udev_enumerate_add_match_subsystem(enumerate, "hidraw"); + udev_enumerate_scan_devices(enumerate); + devices = udev_enumerate_get_list_entry(enumerate); + /* For each item, see if it matches the vid/pid, and if so + create a udev_device record for it */ + udev_list_entry_foreach(dev_list_entry, devices) { + const char *sysfs_path; + const char *dev_path; + const char *str; + struct udev_device *raw_dev; /* The device's hidraw udev node. */ + struct udev_device *hid_dev; /* The device's HID udev node. */ + struct udev_device *usb_dev; /* The device's USB udev node. */ + struct udev_device *intf_dev; /* The device's interface (in the USB sense). */ + unsigned short dev_vid; + unsigned short dev_pid; + char *serial_number_utf8 = NULL; + char *product_name_utf8 = NULL; + int bus_type; + int result; + + /* Get the filename of the /sys entry for the device + and create a udev_device object (dev) representing it */ + sysfs_path = udev_list_entry_get_name(dev_list_entry); + raw_dev = udev_device_new_from_syspath(udev, sysfs_path); + dev_path = udev_device_get_devnode(raw_dev); + + hid_dev = udev_device_get_parent_with_subsystem_devtype( + raw_dev, + "hid", + NULL); + + if (!hid_dev) { + /* Unable to find parent hid device. */ + goto next; + } + + result = parse_uevent_info( + udev_device_get_sysattr_value(hid_dev, "uevent"), + &bus_type, + &dev_vid, + &dev_pid, + &serial_number_utf8, + &product_name_utf8); + + if (!result) { + /* parse_uevent_info() failed for at least one field. */ + goto next; + } + + if (bus_type != BUS_USB && bus_type != BUS_BLUETOOTH) { + /* We only know how to handle USB and BT devices. */ + goto next; + } + + /* Check the VID/PID against the arguments */ + if ((vendor_id == 0x0 || vendor_id == dev_vid) && + (product_id == 0x0 || product_id == dev_pid)) { + struct hid_device_info *tmp; + + /* VID/PID match. Create the record. */ + tmp = malloc(sizeof(struct hid_device_info)); + if (cur_dev) { + cur_dev->next = tmp; + } + else { + root = tmp; + } + prev_dev = cur_dev; + cur_dev = tmp; + + /* Fill out the record */ + cur_dev->next = NULL; + cur_dev->path = dev_path? strdup(dev_path): NULL; + + /* VID/PID */ + cur_dev->vendor_id = dev_vid; + cur_dev->product_id = dev_pid; + + /* Serial Number */ + cur_dev->serial_number = utf8_to_wchar_t(serial_number_utf8); + + /* Release Number */ + cur_dev->release_number = 0x0; + + /* Interface Number */ + cur_dev->interface_number = -1; + + switch (bus_type) { + case BUS_USB: + /* The device pointed to by raw_dev contains information about + the hidraw device. In order to get information about the + USB device, get the parent device with the + subsystem/devtype pair of "usb"/"usb_device". This will + be several levels up the tree, but the function will find + it. */ + usb_dev = udev_device_get_parent_with_subsystem_devtype( + raw_dev, + "usb", + "usb_device"); + + if (!usb_dev) { + /* Free this device */ + free(cur_dev->serial_number); + free(cur_dev->path); + free(cur_dev); + + /* Take it off the device list. */ + if (prev_dev) { + prev_dev->next = NULL; + cur_dev = prev_dev; + } + else { + cur_dev = root = NULL; + } + + goto next; + } + + /* Manufacturer and Product strings */ + cur_dev->manufacturer_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_MANUFACTURER]); + cur_dev->product_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_PRODUCT]); + + /* Release Number */ + str = udev_device_get_sysattr_value(usb_dev, "bcdDevice"); + cur_dev->release_number = (str)? strtol(str, NULL, 16): 0x0; + + /* Get a handle to the interface's udev node. */ + intf_dev = udev_device_get_parent_with_subsystem_devtype( + raw_dev, + "usb", + "usb_interface"); + if (intf_dev) { + str = udev_device_get_sysattr_value(intf_dev, "bInterfaceNumber"); + cur_dev->interface_number = (str)? strtol(str, NULL, 16): -1; + } + + break; + + case BUS_BLUETOOTH: + /* Manufacturer and Product strings */ + cur_dev->manufacturer_string = wcsdup(L""); + cur_dev->product_string = utf8_to_wchar_t(product_name_utf8); + + break; + + default: + /* Unknown device type - this should never happen, as we + * check for USB and Bluetooth devices above */ + break; + } + } + + next: + free(serial_number_utf8); + free(product_name_utf8); + udev_device_unref(raw_dev); + /* hid_dev, usb_dev and intf_dev don't need to be (and can't be) + unref()d. It will cause a double-free() error. I'm not + sure why. */ + } + /* Free the enumerator and udev objects. */ + udev_enumerate_unref(enumerate); + udev_unref(udev); + + return root; +} + +void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) +{ + struct hid_device_info *d = devs; + while (d) { + struct hid_device_info *next = d->next; + free(d->path); + free(d->serial_number); + free(d->manufacturer_string); + free(d->product_string); + free(d); + d = next; + } +} + +hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) +{ + struct hid_device_info *devs, *cur_dev; + const char *path_to_open = NULL; + hid_device *handle = NULL; + + devs = hid_enumerate(vendor_id, product_id); + cur_dev = devs; + while (cur_dev) { + if (cur_dev->vendor_id == vendor_id && + cur_dev->product_id == product_id) { + if (serial_number) { + if (wcscmp(serial_number, cur_dev->serial_number) == 0) { + path_to_open = cur_dev->path; + break; + } + } + else { + path_to_open = cur_dev->path; + break; + } + } + cur_dev = cur_dev->next; + } + + if (path_to_open) { + /* Open the device */ + handle = hid_open_path(path_to_open); + } + + hid_free_enumeration(devs); + + return handle; +} + +hid_device * HID_API_EXPORT hid_open_path(const char *path) +{ + hid_device *dev = NULL; + + hid_init(); + + dev = new_hid_device(); + + if (kernel_version == 0) { + struct utsname name; + int major, minor, release; + int ret; + uname(&name); + ret = sscanf(name.release, "%d.%d.%d", &major, &minor, &release); + if (ret == 3) { + kernel_version = major << 16 | minor << 8 | release; + //printf("Kernel Version: %d\n", kernel_version); + } + else { + printf("Couldn't sscanf() version string %s\n", name.release); + } + } + + /* OPEN HERE */ + dev->device_handle = open(path, O_RDWR); + + /* If we have a good handle, return it. */ + if (dev->device_handle > 0) { + + /* Get the report descriptor */ + int res, desc_size = 0; + struct hidraw_report_descriptor rpt_desc; + + memset(&rpt_desc, 0x0, sizeof(rpt_desc)); + + /* Get Report Descriptor Size */ + res = ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size); + if (res < 0) + perror("HIDIOCGRDESCSIZE"); + + + /* Get Report Descriptor */ + rpt_desc.size = desc_size; + res = ioctl(dev->device_handle, HIDIOCGRDESC, &rpt_desc); + if (res < 0) { + perror("HIDIOCGRDESC"); + } else { + /* Determine if this device uses numbered reports. */ + dev->uses_numbered_reports = + uses_numbered_reports(rpt_desc.value, + rpt_desc.size); + } + + return dev; + } + else { + /* Unable to open any devices. */ + free(dev); + return NULL; + } +} + + +int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) +{ + int bytes_written; + + bytes_written = write(dev->device_handle, data, length); + + return bytes_written; +} + + +int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) +{ + int bytes_read; + + if (milliseconds >= 0) { + /* Milliseconds is either 0 (non-blocking) or > 0 (contains + a valid timeout). In both cases we want to call poll() + and wait for data to arrive. Don't rely on non-blocking + operation (O_NONBLOCK) since some kernels don't seem to + properly report device disconnection through read() when + in non-blocking mode. */ + int ret; + struct pollfd fds; + + fds.fd = dev->device_handle; + fds.events = POLLIN; + fds.revents = 0; + ret = poll(&fds, 1, milliseconds); + if (ret == -1 || ret == 0) { + /* Error or timeout */ + return ret; + } + else { + /* Check for errors on the file descriptor. This will + indicate a device disconnection. */ + if (fds.revents & (POLLERR | POLLHUP | POLLNVAL)) + return -1; + } + } + + bytes_read = read(dev->device_handle, data, length); + if (bytes_read < 0 && (errno == EAGAIN || errno == EINPROGRESS)) + bytes_read = 0; + + if (bytes_read >= 0 && + kernel_version < KERNEL_VERSION(2,6,34) && + dev->uses_numbered_reports) { + /* Work around a kernel bug. Chop off the first byte. */ + memmove(data, data+1, bytes_read); + bytes_read--; + } + + return bytes_read; +} + +int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) +{ + return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); +} + +int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) +{ + /* Do all non-blocking in userspace using poll(), since it looks + like there's a bug in the kernel in some versions where + read() will not return -1 on disconnection of the USB device */ + + dev->blocking = !nonblock; + return 0; /* Success */ +} + + +int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) +{ + int res; + + res = ioctl(dev->device_handle, HIDIOCSFEATURE(length), data); + if (res < 0) + perror("ioctl (SFEATURE)"); + + return res; +} + +int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) +{ + int res; + + res = ioctl(dev->device_handle, HIDIOCGFEATURE(length), data); + if (res < 0) + perror("ioctl (GFEATURE)"); + + + return res; +} + + +void HID_API_EXPORT hid_close(hid_device *dev) +{ + if (!dev) + return; + close(dev->device_handle); + free(dev); +} + + +int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return get_device_string(dev, DEVICE_STRING_MANUFACTURER, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return get_device_string(dev, DEVICE_STRING_PRODUCT, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return get_device_string(dev, DEVICE_STRING_SERIAL, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) +{ + return -1; +} + + +HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) +{ + return NULL; +} diff --git a/ground/openpilotgcs/src/plugins/opHID/hidapi/mac/hid.c b/ground/openpilotgcs/src/plugins/opHID/hidapi/mac/hid.c new file mode 100644 index 000000000..13109239e --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/hidapi/mac/hid.c @@ -0,0 +1,1111 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + 2010-07-03 + + Copyright 2010, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . +********************************************************/ + +/* See Apple Technical Note TN2187 for details on IOHidManager. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hidapi.h" + +/* Barrier implementation because Mac OSX doesn't have pthread_barrier. + It also doesn't have clock_gettime(). So much for POSIX and SUSv2. + This implementation came from Brent Priddy and was posted on + StackOverflow. It is used with his permission. */ +typedef int pthread_barrierattr_t; +typedef struct pthread_barrier { + pthread_mutex_t mutex; + pthread_cond_t cond; + int count; + int trip_count; +} pthread_barrier_t; + +static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count) +{ + if(count == 0) { + errno = EINVAL; + return -1; + } + + if(pthread_mutex_init(&barrier->mutex, 0) < 0) { + return -1; + } + if(pthread_cond_init(&barrier->cond, 0) < 0) { + pthread_mutex_destroy(&barrier->mutex); + return -1; + } + barrier->trip_count = count; + barrier->count = 0; + + return 0; +} + +static int pthread_barrier_destroy(pthread_barrier_t *barrier) +{ + pthread_cond_destroy(&barrier->cond); + pthread_mutex_destroy(&barrier->mutex); + return 0; +} + +static int pthread_barrier_wait(pthread_barrier_t *barrier) +{ + pthread_mutex_lock(&barrier->mutex); + ++(barrier->count); + if(barrier->count >= barrier->trip_count) + { + barrier->count = 0; + pthread_cond_broadcast(&barrier->cond); + pthread_mutex_unlock(&barrier->mutex); + return 1; + } + else + { + pthread_cond_wait(&barrier->cond, &(barrier->mutex)); + pthread_mutex_unlock(&barrier->mutex); + return 0; + } +} + +static int return_data(hid_device *dev, unsigned char *data, size_t length); + +/* Linked List of input reports received from the device. */ +struct input_report { + uint8_t *data; + size_t len; + struct input_report *next; +}; + +struct hid_device_ { + IOHIDDeviceRef device_handle; + int blocking; + int uses_numbered_reports; + int disconnected; + CFStringRef run_loop_mode; + CFRunLoopRef run_loop; + CFRunLoopSourceRef source; + uint8_t *input_report_buf; + CFIndex max_input_report_len; + struct input_report *input_reports; + + pthread_t thread; + pthread_mutex_t mutex; /* Protects input_reports */ + pthread_cond_t condition; + pthread_barrier_t barrier; /* Ensures correct startup sequence */ + pthread_barrier_t shutdown_barrier; /* Ensures correct shutdown sequence */ + int shutdown_thread; +}; + +static hid_device *new_hid_device(void) +{ + hid_device *dev = calloc(1, sizeof(hid_device)); + dev->device_handle = NULL; + dev->blocking = 1; + dev->uses_numbered_reports = 0; + dev->disconnected = 0; + dev->run_loop_mode = NULL; + dev->run_loop = NULL; + dev->source = NULL; + dev->input_report_buf = NULL; + dev->input_reports = NULL; + dev->shutdown_thread = 0; + + /* Thread objects */ + pthread_mutex_init(&dev->mutex, NULL); + pthread_cond_init(&dev->condition, NULL); + pthread_barrier_init(&dev->barrier, NULL, 2); + pthread_barrier_init(&dev->shutdown_barrier, NULL, 2); + + return dev; +} + +static void free_hid_device(hid_device *dev) +{ + if (!dev) + return; + + /* Delete any input reports still left over. */ + struct input_report *rpt = dev->input_reports; + while (rpt) { + struct input_report *next = rpt->next; + free(rpt->data); + free(rpt); + rpt = next; + } + + /* Free the string and the report buffer. The check for NULL + is necessary here as CFRelease() doesn't handle NULL like + free() and others do. */ + if (dev->run_loop_mode) + CFRelease(dev->run_loop_mode); + if (dev->source) + CFRelease(dev->source); + free(dev->input_report_buf); + + /* Clean up the thread objects */ + pthread_barrier_destroy(&dev->shutdown_barrier); + pthread_barrier_destroy(&dev->barrier); + pthread_cond_destroy(&dev->condition); + pthread_mutex_destroy(&dev->mutex); + + /* Free the structure itself. */ + free(dev); +} + +static IOHIDManagerRef hid_mgr = 0x0; + + +#if 0 +static void register_error(hid_device *device, const char *op) +{ + +} +#endif + + +static int32_t get_int_property(IOHIDDeviceRef device, CFStringRef key) +{ + CFTypeRef ref; + int32_t value; + + ref = IOHIDDeviceGetProperty(device, key); + if (ref) { + if (CFGetTypeID(ref) == CFNumberGetTypeID()) { + CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, &value); + return value; + } + } + return 0; +} + +static unsigned short get_vendor_id(IOHIDDeviceRef device) +{ + return get_int_property(device, CFSTR(kIOHIDVendorIDKey)); +} + +static unsigned short get_product_id(IOHIDDeviceRef device) +{ + return get_int_property(device, CFSTR(kIOHIDProductIDKey)); +} + +static int32_t get_location_id(IOHIDDeviceRef device) +{ + return get_int_property(device, CFSTR(kIOHIDLocationIDKey)); +} + +static int32_t get_max_report_length(IOHIDDeviceRef device) +{ + return get_int_property(device, CFSTR(kIOHIDMaxInputReportSizeKey)); +} + +static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t *buf, size_t len) +{ + CFStringRef str; + + if (!len) + return 0; + + str = IOHIDDeviceGetProperty(device, prop); + + buf[0] = 0; + + if (str) { + CFIndex str_len = CFStringGetLength(str); + CFRange range; + CFIndex used_buf_len; + CFIndex chars_copied; + + len --; + + range.location = 0; + range.length = ((size_t)str_len > len)? len: (size_t)str_len; + chars_copied = CFStringGetBytes(str, + range, + kCFStringEncodingUTF32LE, + (char)'?', + FALSE, + (UInt8*)buf, + len * sizeof(wchar_t), + &used_buf_len); + + if (chars_copied == len) + buf[len] = 0; /* len is decremented above */ + else + buf[chars_copied] = 0; + + return 0; + } + else + return -1; + +} + +static int get_string_property_utf8(IOHIDDeviceRef device, CFStringRef prop, char *buf, size_t len) +{ + CFStringRef str; + if (!len) + return 0; + + str = IOHIDDeviceGetProperty(device, prop); + + buf[0] = 0; + + if (str) { + len--; + + CFIndex str_len = CFStringGetLength(str); + CFRange range; + range.location = 0; + range.length = str_len; + CFIndex used_buf_len; + CFIndex chars_copied; + chars_copied = CFStringGetBytes(str, + range, + kCFStringEncodingUTF8, + (char)'?', + FALSE, + (UInt8*)buf, + len, + &used_buf_len); + + if (used_buf_len == len) + buf[len] = 0; /* len is decremented above */ + else + buf[used_buf_len] = 0; + + return used_buf_len; + } + else + return 0; +} + + +static int get_serial_number(IOHIDDeviceRef device, wchar_t *buf, size_t len) +{ + return get_string_property(device, CFSTR(kIOHIDSerialNumberKey), buf, len); +} + +static int get_manufacturer_string(IOHIDDeviceRef device, wchar_t *buf, size_t len) +{ + return get_string_property(device, CFSTR(kIOHIDManufacturerKey), buf, len); +} + +static int get_product_string(IOHIDDeviceRef device, wchar_t *buf, size_t len) +{ + return get_string_property(device, CFSTR(kIOHIDProductKey), buf, len); +} + + +/* Implementation of wcsdup() for Mac. */ +static wchar_t *dup_wcs(const wchar_t *s) +{ + size_t len = wcslen(s); + wchar_t *ret = malloc((len+1)*sizeof(wchar_t)); + wcscpy(ret, s); + + return ret; +} + + +static int make_path(IOHIDDeviceRef device, char *buf, size_t len) +{ + int res; + unsigned short vid, pid; + char transport[32]; + int32_t location; + + buf[0] = '\0'; + + res = get_string_property_utf8( + device, CFSTR(kIOHIDTransportKey), + transport, sizeof(transport)); + + if (!res) + return -1; + + location = get_location_id(device); + vid = get_vendor_id(device); + pid = get_product_id(device); + + res = snprintf(buf, len, "%s_%04hx_%04hx_%x", + transport, vid, pid, location); + + + buf[len-1] = '\0'; + return res+1; +} + +/* Initialize the IOHIDManager. Return 0 for success and -1 for failure. */ +static int init_hid_manager(void) +{ + /* Initialize all the HID Manager Objects */ + hid_mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + if (hid_mgr) { + IOHIDManagerSetDeviceMatching(hid_mgr, NULL); + IOHIDManagerScheduleWithRunLoop(hid_mgr, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + return 0; + } + + return -1; +} + +/* Initialize the IOHIDManager if necessary. This is the public function, and + it is safe to call this function repeatedly. Return 0 for success and -1 + for failure. */ +int HID_API_EXPORT hid_init(void) +{ + if (!hid_mgr) { + return init_hid_manager(); + } + + /* Already initialized. */ + return 0; +} + +int HID_API_EXPORT hid_exit(void) +{ + if (hid_mgr) { + /* Close the HID manager. */ + IOHIDManagerClose(hid_mgr, kIOHIDOptionsTypeNone); + CFRelease(hid_mgr); + hid_mgr = NULL; + } + + return 0; +} + +static void process_pending_events(void) { + SInt32 res; + do { + res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.001, FALSE); + } while(res != kCFRunLoopRunFinished && res != kCFRunLoopRunTimedOut); +} + +struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) +{ + struct hid_device_info *root = NULL; /* return object */ + struct hid_device_info *cur_dev = NULL; + CFIndex num_devices; + int i; + + /* Set up the HID Manager if it hasn't been done */ + if (hid_init() < 0) + return NULL; + + /* give the IOHIDManager a chance to update itself */ + process_pending_events(); + + /* Get a list of the Devices */ + CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr); + + /* Convert the list into a C array so we can iterate easily. */ + num_devices = CFSetGetCount(device_set); + IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef)); + CFSetGetValues(device_set, (const void **) device_array); + + /* Iterate over each device, making an entry for it. */ + for (i = 0; i < num_devices; i++) { + unsigned short dev_vid; + unsigned short dev_pid; + #define BUF_LEN 256 + wchar_t buf[BUF_LEN]; + char cbuf[BUF_LEN]; + + IOHIDDeviceRef dev = device_array[i]; + + if (!dev) { + continue; + } + dev_vid = get_vendor_id(dev); + dev_pid = get_product_id(dev); + + /* Check the VID/PID against the arguments */ + if ((vendor_id == 0x0 || vendor_id == dev_vid) && + (product_id == 0x0 || product_id == dev_pid)) { + struct hid_device_info *tmp; + size_t len; + + /* VID/PID match. Create the record. */ + tmp = malloc(sizeof(struct hid_device_info)); + if (cur_dev) { + cur_dev->next = tmp; + } + else { + root = tmp; + } + cur_dev = tmp; + + /* Get the Usage Page and Usage for this device. */ + cur_dev->usage_page = get_int_property(dev, CFSTR(kIOHIDPrimaryUsagePageKey)); + cur_dev->usage = get_int_property(dev, CFSTR(kIOHIDPrimaryUsageKey)); + + /* Fill out the record */ + cur_dev->next = NULL; + len = make_path(dev, cbuf, sizeof(cbuf)); + cur_dev->path = strdup(cbuf); + + /* Serial Number */ + get_serial_number(dev, buf, BUF_LEN); + cur_dev->serial_number = dup_wcs(buf); + + /* Manufacturer and Product strings */ + get_manufacturer_string(dev, buf, BUF_LEN); + cur_dev->manufacturer_string = dup_wcs(buf); + get_product_string(dev, buf, BUF_LEN); + cur_dev->product_string = dup_wcs(buf); + + /* VID/PID */ + cur_dev->vendor_id = dev_vid; + cur_dev->product_id = dev_pid; + + /* Release Number */ + cur_dev->release_number = get_int_property(dev, CFSTR(kIOHIDVersionNumberKey)); + + /* Interface Number (Unsupported on Mac)*/ + cur_dev->interface_number = -1; + } + } + + free(device_array); + CFRelease(device_set); + + return root; +} + +void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) +{ + /* This function is identical to the Linux version. Platform independent. */ + struct hid_device_info *d = devs; + while (d) { + struct hid_device_info *next = d->next; + free(d->path); + free(d->serial_number); + free(d->manufacturer_string); + free(d->product_string); + free(d); + d = next; + } +} + +hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) +{ + /* This function is identical to the Linux version. Platform independent. */ + struct hid_device_info *devs, *cur_dev; + const char *path_to_open = NULL; + hid_device * handle = NULL; + + devs = hid_enumerate(vendor_id, product_id); + cur_dev = devs; + while (cur_dev) { + if (cur_dev->vendor_id == vendor_id && + cur_dev->product_id == product_id) { + if (serial_number) { + if (wcscmp(serial_number, cur_dev->serial_number) == 0) { + path_to_open = cur_dev->path; + break; + } + } + else { + path_to_open = cur_dev->path; + break; + } + } + cur_dev = cur_dev->next; + } + + if (path_to_open) { + /* Open the device */ + handle = hid_open_path(path_to_open); + } + + hid_free_enumeration(devs); + + return handle; +} + +static void hid_device_removal_callback(void *context, IOReturn result, + void *sender) +{ + /* Stop the Run Loop for this device. */ + hid_device *d = context; + + d->disconnected = 1; + CFRunLoopStop(d->run_loop); +} + +/* The Run Loop calls this function for each input report received. + This function puts the data into a linked list to be picked up by + hid_read(). */ +static void hid_report_callback(void *context, IOReturn result, void *sender, + IOHIDReportType report_type, uint32_t report_id, + uint8_t *report, CFIndex report_length) +{ + struct input_report *rpt; + hid_device *dev = context; + + /* Make a new Input Report object */ + rpt = calloc(1, sizeof(struct input_report)); + rpt->data = calloc(1, report_length); + memcpy(rpt->data, report, report_length); + rpt->len = report_length; + rpt->next = NULL; + + /* Lock this section */ + pthread_mutex_lock(&dev->mutex); + + /* Attach the new report object to the end of the list. */ + if (dev->input_reports == NULL) { + /* The list is empty. Put it at the root. */ + dev->input_reports = rpt; + } + else { + /* Find the end of the list and attach. */ + struct input_report *cur = dev->input_reports; + int num_queued = 0; + while (cur->next != NULL) { + cur = cur->next; + num_queued++; + } + cur->next = rpt; + + /* Pop one off if we've reached 30 in the queue. This + way we don't grow forever if the user never reads + anything from the device. */ + if (num_queued > 30) { + return_data(dev, NULL, 0); + } + } + + /* Signal a waiting thread that there is data. */ + pthread_cond_signal(&dev->condition); + + /* Unlock */ + pthread_mutex_unlock(&dev->mutex); + +} + +/* This gets called when the read_thred's run loop gets signaled by + hid_close(), and serves to stop the read_thread's run loop. */ +static void perform_signal_callback(void *context) +{ + hid_device *dev = context; + CFRunLoopStop(dev->run_loop); /*TODO: CFRunLoopGetCurrent()*/ +} + +static void *read_thread(void *param) +{ + hid_device *dev = param; + SInt32 code; + + /* Move the device's run loop to this thread. */ + IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode); + + /* Create the RunLoopSource which is used to signal the + event loop to stop when hid_close() is called. */ + CFRunLoopSourceContext ctx; + memset(&ctx, 0, sizeof(ctx)); + ctx.version = 0; + ctx.info = dev; + ctx.perform = &perform_signal_callback; + dev->source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0/*order*/, &ctx); + CFRunLoopAddSource(CFRunLoopGetCurrent(), dev->source, dev->run_loop_mode); + + /* Store off the Run Loop so it can be stopped from hid_close() + and on device disconnection. */ + dev->run_loop = CFRunLoopGetCurrent(); + + /* Notify the main thread that the read thread is up and running. */ + pthread_barrier_wait(&dev->barrier); + + /* Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input + reports into the hid_report_callback(). */ + while (!dev->shutdown_thread && !dev->disconnected) { + code = CFRunLoopRunInMode(dev->run_loop_mode, 1000/*sec*/, FALSE); + /* Return if the device has been disconnected */ + if (code == kCFRunLoopRunFinished) { + dev->disconnected = 1; + break; + } + + + /* Break if The Run Loop returns Finished or Stopped. */ + if (code != kCFRunLoopRunTimedOut && + code != kCFRunLoopRunHandledSource) { + /* There was some kind of error. Setting + shutdown seems to make sense, but + there may be something else more appropriate */ + dev->shutdown_thread = 1; + break; + } + } + + /* Now that the read thread is stopping, Wake any threads which are + waiting on data (in hid_read_timeout()). Do this under a mutex to + make sure that a thread which is about to go to sleep waiting on + the condition acutally will go to sleep before the condition is + signaled. */ + pthread_mutex_lock(&dev->mutex); + pthread_cond_broadcast(&dev->condition); + pthread_mutex_unlock(&dev->mutex); + + /* Wait here until hid_close() is called and makes it past + the call to CFRunLoopWakeUp(). This thread still needs to + be valid when that function is called on the other thread. */ + pthread_barrier_wait(&dev->shutdown_barrier); + + return NULL; +} + +hid_device * HID_API_EXPORT hid_open_path(const char *path) +{ + int i; + hid_device *dev = NULL; + CFIndex num_devices; + + dev = new_hid_device(); + + /* Set up the HID Manager if it hasn't been done */ + if (hid_init() < 0) + return NULL; + + /* give the IOHIDManager a chance to update itself */ + process_pending_events(); + + CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr); + + num_devices = CFSetGetCount(device_set); + IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef)); + CFSetGetValues(device_set, (const void **) device_array); + for (i = 0; i < num_devices; i++) { + char cbuf[BUF_LEN]; + size_t len; + IOHIDDeviceRef os_dev = device_array[i]; + + len = make_path(os_dev, cbuf, sizeof(cbuf)); + if (!strcmp(cbuf, path)) { + /* Matched Paths. Open this Device. */ + IOReturn ret = IOHIDDeviceOpen(os_dev, kIOHIDOptionsTypeSeizeDevice); + if (ret == kIOReturnSuccess) { + char str[32]; + + free(device_array); + CFRetain(os_dev); + CFRelease(device_set); + dev->device_handle = os_dev; + + /* Create the buffers for receiving data */ + dev->max_input_report_len = (CFIndex) get_max_report_length(os_dev); + dev->input_report_buf = calloc(dev->max_input_report_len, sizeof(uint8_t)); + + /* Create the Run Loop Mode for this device. + printing the reference seems to work. */ + sprintf(str, "HIDAPI_%p", os_dev); + dev->run_loop_mode = + CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII); + + /* Attach the device to a Run Loop */ + IOHIDDeviceRegisterInputReportCallback( + os_dev, dev->input_report_buf, dev->max_input_report_len, + &hid_report_callback, dev); + IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev); + + /* Start the read thread */ + pthread_create(&dev->thread, NULL, read_thread, dev); + + /* Wait here for the read thread to be initialized. */ + pthread_barrier_wait(&dev->barrier); + + return dev; + } + else { + goto return_error; + } + } + } + +return_error: + free(device_array); + CFRelease(device_set); + free_hid_device(dev); + return NULL; +} + +static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char *data, size_t length) +{ + const unsigned char *data_to_send; + size_t length_to_send; + IOReturn res; + + /* Return if the device has been disconnected. */ + if (dev->disconnected) + return -1; + + if (data[0] == 0x0) { + /* Not using numbered Reports. + Don't send the report number. */ + data_to_send = data+1; + length_to_send = length-1; + } + else { + /* Using numbered Reports. + Send the Report Number */ + data_to_send = data; + length_to_send = length; + } + + if (!dev->disconnected) { + res = IOHIDDeviceSetReport(dev->device_handle, + type, + data[0], /* Report ID*/ + data_to_send, length_to_send); + + if (res == kIOReturnSuccess) { + return length; + } + else + return -1; + } + + return -1; +} + +int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) +{ + return set_report(dev, kIOHIDReportTypeOutput, data, length); +} + +/* Helper function, so that this isn't duplicated in hid_read(). */ +static int return_data(hid_device *dev, unsigned char *data, size_t length) +{ + /* Copy the data out of the linked list item (rpt) into the + return buffer (data), and delete the liked list item. */ + struct input_report *rpt = dev->input_reports; + size_t len = (length < rpt->len)? length: rpt->len; + memcpy(data, rpt->data, len); + dev->input_reports = rpt->next; + free(rpt->data); + free(rpt); + return len; +} + +static int cond_wait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + while (!dev->input_reports) { + int res = pthread_cond_wait(cond, mutex); + if (res != 0) + return res; + + /* A res of 0 means we may have been signaled or it may + be a spurious wakeup. Check to see that there's acutally + data in the queue before returning, and if not, go back + to sleep. See the pthread_cond_timedwait() man page for + details. */ + + if (dev->shutdown_thread || dev->disconnected) + return -1; + } + + return 0; +} + +static int cond_timedwait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) +{ + while (!dev->input_reports) { + int res = pthread_cond_timedwait(cond, mutex, abstime); + if (res != 0) + return res; + + /* A res of 0 means we may have been signaled or it may + be a spurious wakeup. Check to see that there's acutally + data in the queue before returning, and if not, go back + to sleep. See the pthread_cond_timedwait() man page for + details. */ + + if (dev->shutdown_thread || dev->disconnected) + return -1; + } + + return 0; + +} + +int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) +{ + int bytes_read = -1; + + /* Lock the access to the report list. */ + pthread_mutex_lock(&dev->mutex); + + /* There's an input report queued up. Return it. */ + if (dev->input_reports) { + /* Return the first one */ + bytes_read = return_data(dev, data, length); + goto ret; + } + + /* Return if the device has been disconnected. */ + if (dev->disconnected) { + bytes_read = -1; + goto ret; + } + + if (dev->shutdown_thread) { + /* This means the device has been closed (or there + has been an error. An error code of -1 should + be returned. */ + bytes_read = -1; + goto ret; + } + + /* There is no data. Go to sleep and wait for data. */ + + if (milliseconds == -1) { + /* Blocking */ + int res; + res = cond_wait(dev, &dev->condition, &dev->mutex); + if (res == 0) + bytes_read = return_data(dev, data, length); + else { + /* There was an error, or a device disconnection. */ + bytes_read = -1; + } + } + else if (milliseconds > 0) { + /* Non-blocking, but called with timeout. */ + int res; + struct timespec ts; + struct timeval tv; + gettimeofday(&tv, NULL); + TIMEVAL_TO_TIMESPEC(&tv, &ts); + ts.tv_sec += milliseconds / 1000; + ts.tv_nsec += (milliseconds % 1000) * 1000000; + if (ts.tv_nsec >= 1000000000L) { + ts.tv_sec++; + ts.tv_nsec -= 1000000000L; + } + + res = cond_timedwait(dev, &dev->condition, &dev->mutex, &ts); + if (res == 0) + bytes_read = return_data(dev, data, length); + else if (res == ETIMEDOUT) + bytes_read = 0; + else + bytes_read = -1; + } + else { + /* Purely non-blocking */ + bytes_read = 0; + } + +ret: + /* Unlock */ + pthread_mutex_unlock(&dev->mutex); + return bytes_read; +} + +int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) +{ + return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); +} + +int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) +{ + /* All Nonblocking operation is handled by the library. */ + dev->blocking = !nonblock; + + return 0; +} + +int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) +{ + return set_report(dev, kIOHIDReportTypeFeature, data, length); +} + +int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) +{ + CFIndex len = length; + IOReturn res; + + /* Return if the device has been unplugged. */ + if (dev->disconnected) + return -1; + + res = IOHIDDeviceGetReport(dev->device_handle, + kIOHIDReportTypeFeature, + data[0], /* Report ID */ + data, &len); + if (res == kIOReturnSuccess) + return len; + else + return -1; +} + + +void HID_API_EXPORT hid_close(hid_device *dev) +{ + if (!dev) + return; + + /* Disconnect the report callback before close. */ + if (!dev->disconnected) { + IOHIDDeviceRegisterInputReportCallback( + dev->device_handle, dev->input_report_buf, dev->max_input_report_len, + NULL, dev); + IOHIDDeviceRegisterRemovalCallback(dev->device_handle, NULL, dev); + IOHIDDeviceUnscheduleFromRunLoop(dev->device_handle, dev->run_loop, dev->run_loop_mode); + IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetMain(), kCFRunLoopDefaultMode); + } + + /* Cause read_thread() to stop. */ + dev->shutdown_thread = 1; + + /* Wake up the run thread's event loop so that the thread can exit. */ + CFRunLoopSourceSignal(dev->source); + CFRunLoopWakeUp(dev->run_loop); + + /* Notify the read thread that it can shut down now. */ + pthread_barrier_wait(&dev->shutdown_barrier); + + /* Wait for read_thread() to end. */ + pthread_join(dev->thread, NULL); + + /* Close the OS handle to the device, but only if it's not + been unplugged. If it's been unplugged, then calling + IOHIDDeviceClose() will crash. */ + if (!dev->disconnected) { + IOHIDDeviceClose(dev->device_handle, kIOHIDOptionsTypeSeizeDevice); + } + + /* Clear out the queue of received reports. */ + pthread_mutex_lock(&dev->mutex); + while (dev->input_reports) { + return_data(dev, NULL, 0); + } + pthread_mutex_unlock(&dev->mutex); + CFRelease(dev->device_handle); + + free_hid_device(dev); +} + +int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return get_manufacturer_string(dev->device_handle, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return get_product_string(dev->device_handle, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return get_serial_number(dev->device_handle, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) +{ + /* TODO: */ + + return 0; +} + + +HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) +{ + /* TODO: */ + + return NULL; +} + + + + + + + +#if 0 +static int32_t get_usage(IOHIDDeviceRef device) +{ + int32_t res; + res = get_int_property(device, CFSTR(kIOHIDDeviceUsageKey)); + if (!res) + res = get_int_property(device, CFSTR(kIOHIDPrimaryUsageKey)); + return res; +} + +static int32_t get_usage_page(IOHIDDeviceRef device) +{ + int32_t res; + res = get_int_property(device, CFSTR(kIOHIDDeviceUsagePageKey)); + if (!res) + res = get_int_property(device, CFSTR(kIOHIDPrimaryUsagePageKey)); + return res; +} + +static int get_transport(IOHIDDeviceRef device, wchar_t *buf, size_t len) +{ + return get_string_property(device, CFSTR(kIOHIDTransportKey), buf, len); +} + + +int main(void) +{ + IOHIDManagerRef mgr; + int i; + + mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + IOHIDManagerSetDeviceMatching(mgr, NULL); + IOHIDManagerOpen(mgr, kIOHIDOptionsTypeNone); + + CFSetRef device_set = IOHIDManagerCopyDevices(mgr); + + CFIndex num_devices = CFSetGetCount(device_set); + IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef)); + CFSetGetValues(device_set, (const void **) device_array); + + for (i = 0; i < num_devices; i++) { + IOHIDDeviceRef dev = device_array[i]; + printf("Device: %p\n", dev); + printf(" %04hx %04hx\n", get_vendor_id(dev), get_product_id(dev)); + + wchar_t serial[256], buf[256]; + char cbuf[256]; + get_serial_number(dev, serial, 256); + + + printf(" Serial: %ls\n", serial); + printf(" Loc: %ld\n", get_location_id(dev)); + get_transport(dev, buf, 256); + printf(" Trans: %ls\n", buf); + make_path(dev, cbuf, 256); + printf(" Path: %s\n", cbuf); + + } + + return 0; +} +#endif diff --git a/ground/openpilotgcs/src/plugins/opHID/hidapi/windows/hid.c b/ground/openpilotgcs/src/plugins/opHID/hidapi/windows/hid.c new file mode 100755 index 000000000..cd9e4bb0f --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/hidapi/windows/hid.c @@ -0,0 +1,923 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + 8/22/2009 + + Copyright 2009, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . +********************************************************/ + +#include + +#ifndef _NTDEF_ +typedef LONG NTSTATUS; +#endif + +#ifdef __MINGW32__ +#include +#include +#endif + +#ifdef __CYGWIN__ +#include +#define _wcsdup wcsdup +#endif + +/*#define HIDAPI_USE_DDK*/ + +#ifdef __cplusplus +extern "C" { +#endif + #include + #include + #ifdef HIDAPI_USE_DDK + #include + #endif + + /* Copied from inc/ddk/hidclass.h, part of the Windows DDK. */ + #define HID_OUT_CTL_CODE(id) \ + CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS) + #define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include +#include + + +#include "hidapi.h" + +#ifdef _MSC_VER + /* Thanks Microsoft, but I know how to use strncpy(). */ + #pragma warning(disable:4996) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef HIDAPI_USE_DDK + /* Since we're not building with the DDK, and the HID header + files aren't part of the SDK, we have to define all this + stuff here. In lookup_functions(), the function pointers + defined below are set. */ + typedef struct _HIDD_ATTRIBUTES{ + ULONG Size; + USHORT VendorID; + USHORT ProductID; + USHORT VersionNumber; + } HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; + + typedef USHORT USAGE; + typedef struct _HIDP_CAPS { + USAGE Usage; + USAGE UsagePage; + USHORT InputReportByteLength; + USHORT OutputReportByteLength; + USHORT FeatureReportByteLength; + USHORT Reserved[17]; + USHORT fields_not_used_by_hidapi[10]; + } HIDP_CAPS, *PHIDP_CAPS; + typedef void* PHIDP_PREPARSED_DATA; + #define HIDP_STATUS_SUCCESS 0x110000 + + typedef BOOLEAN (__stdcall *HidD_GetAttributes_)(HANDLE device, PHIDD_ATTRIBUTES attrib); + typedef BOOLEAN (__stdcall *HidD_GetSerialNumberString_)(HANDLE device, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_GetManufacturerString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length); + typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length); + typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data); + typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data); + typedef NTSTATUS (__stdcall *HidP_GetCaps_)(PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *caps); + + static HidD_GetAttributes_ HidD_GetAttributes; + static HidD_GetSerialNumberString_ HidD_GetSerialNumberString; + static HidD_GetManufacturerString_ HidD_GetManufacturerString; + static HidD_GetProductString_ HidD_GetProductString; + static HidD_SetFeature_ HidD_SetFeature; + static HidD_GetFeature_ HidD_GetFeature; + static HidD_GetIndexedString_ HidD_GetIndexedString; + static HidD_GetPreparsedData_ HidD_GetPreparsedData; + static HidD_FreePreparsedData_ HidD_FreePreparsedData; + static HidP_GetCaps_ HidP_GetCaps; + + static HMODULE lib_handle = NULL; + static BOOLEAN initialized = FALSE; +#endif /* HIDAPI_USE_DDK */ + +struct hid_device_ { + HANDLE device_handle; + BOOL blocking; + USHORT output_report_length; + size_t input_report_length; + void *last_error_str; + DWORD last_error_num; + BOOL read_pending; + char *read_buf; + OVERLAPPED ol; +}; + +static hid_device *new_hid_device() +{ + hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device)); + dev->device_handle = INVALID_HANDLE_VALUE; + dev->blocking = TRUE; + dev->output_report_length = 0; + dev->input_report_length = 0; + dev->last_error_str = NULL; + dev->last_error_num = 0; + dev->read_pending = FALSE; + dev->read_buf = NULL; + memset(&dev->ol, 0, sizeof(dev->ol)); + dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*inital state f=nonsignaled*/, NULL); + + return dev; +} + +static void free_hid_device(hid_device *dev) +{ + CloseHandle(dev->ol.hEvent); + CloseHandle(dev->device_handle); + LocalFree(dev->last_error_str); + free(dev->read_buf); + free(dev); +} + +static void register_error(hid_device *device, const char *op) +{ + WCHAR *ptr, *msg; + + FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPVOID)&msg, 0/*sz*/, + NULL); + + /* Get rid of the CR and LF that FormatMessage() sticks at the + end of the message. Thanks Microsoft! */ + ptr = msg; + while (*ptr) { + if (*ptr == '\r') { + *ptr = 0x0000; + break; + } + ptr++; + } + + /* Store the message off in the Device entry so that + the hid_error() function can pick it up. */ + LocalFree(device->last_error_str); + device->last_error_str = msg; +} + +#ifndef HIDAPI_USE_DDK +static int lookup_functions() +{ + lib_handle = LoadLibraryA("hid.dll"); + if (lib_handle) { +#define RESOLVE(x) x = (x##_)GetProcAddress(lib_handle, #x); if (!x) return -1; + RESOLVE(HidD_GetAttributes); + RESOLVE(HidD_GetSerialNumberString); + RESOLVE(HidD_GetManufacturerString); + RESOLVE(HidD_GetProductString); + RESOLVE(HidD_SetFeature); + RESOLVE(HidD_GetFeature); + RESOLVE(HidD_GetIndexedString); + RESOLVE(HidD_GetPreparsedData); + RESOLVE(HidD_FreePreparsedData); + RESOLVE(HidP_GetCaps); +#undef RESOLVE + } + else + return -1; + + return 0; +} +#endif + +static HANDLE open_device(const char *path, BOOL enumerate) +{ + HANDLE handle; + DWORD desired_access = (enumerate)? 0: (GENERIC_WRITE | GENERIC_READ); + DWORD share_mode = (enumerate)? + FILE_SHARE_READ|FILE_SHARE_WRITE: + FILE_SHARE_READ; + + handle = CreateFileA(path, + desired_access, + share_mode, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED,/*FILE_ATTRIBUTE_NORMAL,*/ + 0); + + return handle; +} + +int HID_API_EXPORT hid_init(void) +{ +#ifndef HIDAPI_USE_DDK + if (!initialized) { + if (lookup_functions() < 0) { + hid_exit(); + return -1; + } + initialized = TRUE; + } +#endif + return 0; +} + +int HID_API_EXPORT hid_exit(void) +{ +#ifndef HIDAPI_USE_DDK + if (lib_handle) + FreeLibrary(lib_handle); + lib_handle = NULL; + initialized = FALSE; +#endif + return 0; +} + +struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id) +{ + BOOL res; + struct hid_device_info *root = NULL; /* return object */ + struct hid_device_info *cur_dev = NULL; + + /* Windows objects for interacting with the driver. */ + GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} }; + SP_DEVINFO_DATA devinfo_data; + SP_DEVICE_INTERFACE_DATA device_interface_data; + SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL; + HDEVINFO device_info_set = INVALID_HANDLE_VALUE; + int device_index = 0; + int i; + + if (hid_init() < 0) + return NULL; + + /* Initialize the Windows objects. */ + memset(&devinfo_data, 0x0, sizeof(devinfo_data)); + devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA); + device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + + /* Get information for all the devices belonging to the HID class. */ + device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + + /* Iterate over each device in the HID class, looking for the right one. */ + + for (;;) { + HANDLE write_handle = INVALID_HANDLE_VALUE; + DWORD required_size = 0; + HIDD_ATTRIBUTES attrib; + + res = SetupDiEnumDeviceInterfaces(device_info_set, + NULL, + &InterfaceClassGuid, + device_index, + &device_interface_data); + + if (!res) { + /* A return of FALSE from this function means that + there are no more devices. */ + break; + } + + /* Call with 0-sized detail size, and let the function + tell us how long the detail struct needs to be. The + size is put in &required_size. */ + res = SetupDiGetDeviceInterfaceDetailA(device_info_set, + &device_interface_data, + NULL, + 0, + &required_size, + NULL); + + /* Allocate a long enough structure for device_interface_detail_data. */ + device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size); + device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); + + /* Get the detailed data for this device. The detail data gives us + the device path for this device, which is then passed into + CreateFile() to get a handle to the device. */ + res = SetupDiGetDeviceInterfaceDetailA(device_info_set, + &device_interface_data, + device_interface_detail_data, + required_size, + NULL, + NULL); + + if (!res) { + /* register_error(dev, "Unable to call SetupDiGetDeviceInterfaceDetail"); + Continue to the next device. */ + goto cont; + } + + /* Make sure this device is of Setup Class "HIDClass" and has a + driver bound to it. */ + for (i = 0; ; i++) { + char driver_name[256]; + + /* Populate devinfo_data. This function will return failure + when there are no more interfaces left. */ + res = SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data); + if (!res) + goto cont; + + res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, + SPDRP_CLASS, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); + if (!res) + goto cont; + + if (strcmp(driver_name, "HIDClass") == 0) { + /* See if there's a driver bound. */ + res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, + SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); + if (res) + break; + } + } + + //wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath); + + /* Open a handle to the device */ + write_handle = open_device(device_interface_detail_data->DevicePath, TRUE); + + /* Check validity of write_handle. */ + if (write_handle == INVALID_HANDLE_VALUE) { + /* Unable to open the device. */ + //register_error(dev, "CreateFile"); + goto cont_close; + } + + + /* Get the Vendor ID and Product ID for this device. */ + attrib.Size = sizeof(HIDD_ATTRIBUTES); + HidD_GetAttributes(write_handle, &attrib); + //wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID); + + /* Check the VID/PID to see if we should add this + device to the enumeration list. */ + if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) && + (product_id == 0x0 || attrib.ProductID == product_id)) { + + #define WSTR_LEN 512 + const char *str; + struct hid_device_info *tmp; + PHIDP_PREPARSED_DATA pp_data = NULL; + HIDP_CAPS caps; + BOOLEAN res; + NTSTATUS nt_res; + wchar_t wstr[WSTR_LEN]; /* TODO: Determine Size */ + size_t len; + + /* VID/PID match. Create the record. */ + tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); + if (cur_dev) { + cur_dev->next = tmp; + } + else { + root = tmp; + } + cur_dev = tmp; + + /* Get the Usage Page and Usage for this device. */ + res = HidD_GetPreparsedData(write_handle, &pp_data); + if (res) { + nt_res = HidP_GetCaps(pp_data, &caps); + if (nt_res == HIDP_STATUS_SUCCESS) { + cur_dev->usage_page = caps.UsagePage; + cur_dev->usage = caps.Usage; + } + + HidD_FreePreparsedData(pp_data); + } + + /* Fill out the record */ + cur_dev->next = NULL; + str = device_interface_detail_data->DevicePath; + if (str) { + len = strlen(str); + cur_dev->path = (char*) calloc(len+1, sizeof(char)); + strncpy(cur_dev->path, str, len+1); + cur_dev->path[len] = '\0'; + } + else + cur_dev->path = NULL; + + /* Serial Number */ + res = HidD_GetSerialNumberString(write_handle, wstr, sizeof(wstr)); + wstr[WSTR_LEN-1] = 0x0000; + if (res) { + cur_dev->serial_number = _wcsdup(wstr); + } + + /* Manufacturer String */ + res = HidD_GetManufacturerString(write_handle, wstr, sizeof(wstr)); + wstr[WSTR_LEN-1] = 0x0000; + if (res) { + cur_dev->manufacturer_string = _wcsdup(wstr); + } + + /* Product String */ + res = HidD_GetProductString(write_handle, wstr, sizeof(wstr)); + wstr[WSTR_LEN-1] = 0x0000; + if (res) { + cur_dev->product_string = _wcsdup(wstr); + } + + /* VID/PID */ + cur_dev->vendor_id = attrib.VendorID; + cur_dev->product_id = attrib.ProductID; + + /* Release Number */ + cur_dev->release_number = attrib.VersionNumber; + + /* Interface Number. It can sometimes be parsed out of the path + on Windows if a device has multiple interfaces. See + http://msdn.microsoft.com/en-us/windows/hardware/gg487473 or + search for "Hardware IDs for HID Devices" at MSDN. If it's not + in the path, it's set to -1. */ + cur_dev->interface_number = -1; + if (cur_dev->path) { + char *interface_component = strstr(cur_dev->path, "&mi_"); + if (interface_component) { + char *hex_str = interface_component + 4; + char *endptr = NULL; + cur_dev->interface_number = strtol(hex_str, &endptr, 16); + if (endptr == hex_str) { + /* The parsing failed. Set interface_number to -1. */ + cur_dev->interface_number = -1; + } + } + } + } + +cont_close: + CloseHandle(write_handle); +cont: + /* We no longer need the detail data. It can be freed */ + free(device_interface_detail_data); + + device_index++; + + } + + /* Close the device information handle. */ + SetupDiDestroyDeviceInfoList(device_info_set); + + return root; + +} + +void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs) +{ + /* TODO: Merge this with the Linux version. This function is platform-independent. */ + struct hid_device_info *d = devs; + while (d) { + struct hid_device_info *next = d->next; + free(d->path); + free(d->serial_number); + free(d->manufacturer_string); + free(d->product_string); + free(d); + d = next; + } +} + + +HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) +{ + /* TODO: Merge this functions with the Linux version. This function should be platform independent. */ + struct hid_device_info *devs, *cur_dev; + const char *path_to_open = NULL; + hid_device *handle = NULL; + + devs = hid_enumerate(vendor_id, product_id); + cur_dev = devs; + while (cur_dev) { + if (cur_dev->vendor_id == vendor_id && + cur_dev->product_id == product_id) { + if (serial_number) { + if (wcscmp(serial_number, cur_dev->serial_number) == 0) { + path_to_open = cur_dev->path; + break; + } + } + else { + path_to_open = cur_dev->path; + break; + } + } + cur_dev = cur_dev->next; + } + + if (path_to_open) { + /* Open the device */ + handle = hid_open_path(path_to_open); + } + + hid_free_enumeration(devs); + + return handle; +} + +HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path) +{ + hid_device *dev; + HIDP_CAPS caps; + PHIDP_PREPARSED_DATA pp_data = NULL; + BOOLEAN res; + NTSTATUS nt_res; + + if (hid_init() < 0) { + return NULL; + } + + dev = new_hid_device(); + + /* Open a handle to the device */ + dev->device_handle = open_device(path, FALSE); + + /* Check validity of write_handle. */ + if (dev->device_handle == INVALID_HANDLE_VALUE) { + /* Unable to open the device. */ + register_error(dev, "CreateFile"); + goto err; + } + + /* Get the Input Report length for the device. */ + res = HidD_GetPreparsedData(dev->device_handle, &pp_data); + if (!res) { + register_error(dev, "HidD_GetPreparsedData"); + goto err; + } + nt_res = HidP_GetCaps(pp_data, &caps); + if (nt_res != HIDP_STATUS_SUCCESS) { + register_error(dev, "HidP_GetCaps"); + goto err_pp_data; + } + dev->output_report_length = caps.OutputReportByteLength; + dev->input_report_length = caps.InputReportByteLength; + HidD_FreePreparsedData(pp_data); + + dev->read_buf = (char*) malloc(dev->input_report_length); + + return dev; + +err_pp_data: + HidD_FreePreparsedData(pp_data); +err: + free_hid_device(dev); + return NULL; +} + +int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length) +{ + DWORD bytes_written; + BOOL res; + + OVERLAPPED ol; + unsigned char *buf; + memset(&ol, 0, sizeof(ol)); + + /* Make sure the right number of bytes are passed to WriteFile. Windows + expects the number of bytes which are in the _longest_ report (plus + one for the report number) bytes even if the data is a report + which is shorter than that. Windows gives us this value in + caps.OutputReportByteLength. If a user passes in fewer bytes than this, + create a temporary buffer which is the proper size. */ + if (length >= dev->output_report_length) { + /* The user passed the right number of bytes. Use the buffer as-is. */ + buf = (unsigned char *) data; + } else { + /* Create a temporary buffer and copy the user's data + into it, padding the rest with zeros. */ + buf = (unsigned char *) malloc(dev->output_report_length); + memcpy(buf, data, length); + memset(buf + length, 0, dev->output_report_length - length); + length = dev->output_report_length; + } + + res = WriteFile(dev->device_handle, buf, length, NULL, &ol); + + if (!res) { + if (GetLastError() != ERROR_IO_PENDING) { + /* WriteFile() failed. Return error. */ + register_error(dev, "WriteFile"); + bytes_written = -1; + goto end_of_function; + } + } + + /* Wait here until the write is done. This makes + hid_write() synchronous. */ + res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE/*wait*/); + if (!res) { + /* The Write operation failed. */ + register_error(dev, "WriteFile"); + bytes_written = -1; + goto end_of_function; + } + +end_of_function: + if (buf != data) + free(buf); + + return bytes_written; +} + + +int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) +{ + DWORD bytes_read = 0; + BOOL res; + + /* Copy the handle for convenience. */ + HANDLE ev = dev->ol.hEvent; + + if (!dev->read_pending) { + /* Start an Overlapped I/O read. */ + dev->read_pending = TRUE; + memset(dev->read_buf, 0, dev->input_report_length); + ResetEvent(ev); + res = ReadFile(dev->device_handle, dev->read_buf, dev->input_report_length, &bytes_read, &dev->ol); + + if (!res) { + if (GetLastError() != ERROR_IO_PENDING) { + /* ReadFile() has failed. + Clean up and return error. */ + CancelIo(dev->device_handle); + dev->read_pending = FALSE; + goto end_of_function; + } + } + } + + if (milliseconds >= 0) { + /* See if there is any data yet. */ + res = WaitForSingleObject(ev, milliseconds); + if (res != WAIT_OBJECT_0) { + /* There was no data this time. Return zero bytes available, + but leave the Overlapped I/O running. */ + return 0; + } + } + + /* Either WaitForSingleObject() told us that ReadFile has completed, or + we are in non-blocking mode. Get the number of bytes read. The actual + data has been copied to the data[] array which was passed to ReadFile(). */ + res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/); + + /* Set pending back to false, even if GetOverlappedResult() returned error. */ + dev->read_pending = FALSE; + + if (res && bytes_read > 0) { + if (dev->read_buf[0] == 0x0) { + /* If report numbers aren't being used, but Windows sticks a report + number (0x0) on the beginning of the report anyway. To make this + work like the other platforms, and to make it work more like the + HID spec, we'll skip over this byte. */ + size_t copy_len; + bytes_read--; + copy_len = length > bytes_read ? bytes_read : length; + memcpy(data, dev->read_buf+1, copy_len); + } + else { + /* Copy the whole buffer, report number and all. */ + size_t copy_len = length > bytes_read ? bytes_read : length; + memcpy(data, dev->read_buf, copy_len); + } + } + +end_of_function: + if (!res) { + register_error(dev, "GetOverlappedResult"); + return -1; + } + + return bytes_read; +} + +int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length) +{ + return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); +} + +int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock) +{ + dev->blocking = !nonblock; + return 0; /* Success */ +} + +int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) +{ + BOOL res = HidD_SetFeature(dev->device_handle, (PVOID)data, length); + if (!res) { + register_error(dev, "HidD_SetFeature"); + return -1; + } + + return length; +} + + +int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) +{ + BOOL res; +#if 0 + res = HidD_GetFeature(dev->device_handle, data, length); + if (!res) { + register_error(dev, "HidD_GetFeature"); + return -1; + } + return 0; /* HidD_GetFeature() doesn't give us an actual length, unfortunately */ +#else + DWORD bytes_returned; + + OVERLAPPED ol; + memset(&ol, 0, sizeof(ol)); + + res = DeviceIoControl(dev->device_handle, + IOCTL_HID_GET_FEATURE, + data, length, + data, length, + &bytes_returned, &ol); + + if (!res) { + if (GetLastError() != ERROR_IO_PENDING) { + /* DeviceIoControl() failed. Return error. */ + register_error(dev, "Send Feature Report DeviceIoControl"); + return -1; + } + } + + /* Wait here until the write is done. This makes + hid_get_feature_report() synchronous. */ + res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/); + if (!res) { + /* The operation failed. */ + register_error(dev, "Send Feature Report GetOverLappedResult"); + return -1; + } + return bytes_returned; +#endif +} + +void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev) +{ + if (!dev) + return; + CancelIo(dev->device_handle); + free_hid_device(dev); +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetManufacturerString(dev->device_handle, string, sizeof(wchar_t) * maxlen); + if (!res) { + register_error(dev, "HidD_GetManufacturerString"); + return -1; + } + + return 0; +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetProductString(dev->device_handle, string, sizeof(wchar_t) * maxlen); + if (!res) { + register_error(dev, "HidD_GetProductString"); + return -1; + } + + return 0; +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetSerialNumberString(dev->device_handle, string, sizeof(wchar_t) * maxlen); + if (!res) { + register_error(dev, "HidD_GetSerialNumberString"); + return -1; + } + + return 0; +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetIndexedString(dev->device_handle, string_index, string, sizeof(wchar_t) * maxlen); + if (!res) { + register_error(dev, "HidD_GetIndexedString"); + return -1; + } + + return 0; +} + + +HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) +{ + return (wchar_t*)dev->last_error_str; +} + + +/*#define PICPGM*/ +/*#define S11*/ +#define P32 +#ifdef S11 + unsigned short VendorID = 0xa0a0; + unsigned short ProductID = 0x0001; +#endif + +#ifdef P32 + unsigned short VendorID = 0x04d8; + unsigned short ProductID = 0x3f; +#endif + + +#ifdef PICPGM + unsigned short VendorID = 0x04d8; + unsigned short ProductID = 0x0033; +#endif + + +#if 0 +int __cdecl main(int argc, char* argv[]) +{ + int res; + unsigned char buf[65]; + + UNREFERENCED_PARAMETER(argc); + UNREFERENCED_PARAMETER(argv); + + /* Set up the command buffer. */ + memset(buf,0x00,sizeof(buf)); + buf[0] = 0; + buf[1] = 0x81; + + + /* Open the device. */ + int handle = open(VendorID, ProductID, L"12345"); + if (handle < 0) + printf("unable to open device\n"); + + + /* Toggle LED (cmd 0x80) */ + buf[1] = 0x80; + res = write(handle, buf, 65); + if (res < 0) + printf("Unable to write()\n"); + + /* Request state (cmd 0x81) */ + buf[1] = 0x81; + write(handle, buf, 65); + if (res < 0) + printf("Unable to write() (2)\n"); + + /* Read requested state */ + read(handle, buf, 65); + if (res < 0) + printf("Unable to read()\n"); + + /* Print out the returned buffer. */ + for (int i = 0; i < 4; i++) + printf("buf[%d]: %d\n", i, buf[i]); + + return 0; +} +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/hidapi.h b/ground/openpilotgcs/src/plugins/opHID/inc/hidapi.h new file mode 100644 index 000000000..e58e8a484 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/inc/hidapi.h @@ -0,0 +1,385 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + 8/22/2009 + + Copyright 2009, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . +********************************************************/ + +/** @file + * @defgroup API hidapi API + */ + +#ifndef HIDAPI_H__ +#define HIDAPI_H__ + +#include + +#ifdef _WIN32 + #define HID_API_EXPORT __declspec(dllexport) + #define HID_API_CALL +#else + #define HID_API_EXPORT /**< API export macro */ + #define HID_API_CALL /**< API call macro */ +#endif + +#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/ + +#ifdef __cplusplus +extern "C" { +#endif + struct hid_device_; + typedef struct hid_device_ hid_device; /**< opaque hidapi structure */ + + /** hidapi info structure */ + struct hid_device_info { + /** Platform-specific device path */ + char *path; + /** Device Vendor ID */ + unsigned short vendor_id; + /** Device Product ID */ + unsigned short product_id; + /** Serial Number */ + wchar_t *serial_number; + /** Device Release Number in binary-coded decimal, + also known as Device Version Number */ + unsigned short release_number; + /** Manufacturer String */ + wchar_t *manufacturer_string; + /** Product string */ + wchar_t *product_string; + /** Usage Page for this Device/Interface + (Windows/Mac only). */ + unsigned short usage_page; + /** Usage for this Device/Interface + (Windows/Mac only).*/ + unsigned short usage; + /** The USB interface which this logical device + represents. Valid on both Linux implementations + in all cases, and valid on the Windows implementation + only if the device contains more than one interface. */ + int interface_number; + + /** Pointer to the next device */ + struct hid_device_info *next; + }; + + + /** @brief Initialize the HIDAPI library. + + This function initializes the HIDAPI library. Calling it is not + strictly necessary, as it will be called automatically by + hid_enumerate() and any of the hid_open_*() functions if it is + needed. This function should be called at the beginning of + execution however, if there is a chance of HIDAPI handles + being opened by different threads simultaneously. + + @ingroup API + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_init(void); + + /** @brief Finalize the HIDAPI library. + + This function frees all of the static data associated with + HIDAPI. It should be called at the end of execution to avoid + memory leaks. + + @ingroup API + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_exit(void); + + /** @brief Enumerate the HID Devices. + + This function returns a linked list of all the HID devices + attached to the system which match vendor_id and product_id. + If @p vendor_id is set to 0 then any vendor matches. + If @p product_id is set to 0 then any product matches. + If @p vendor_id and @p product_id are both set to 0, then + all HID devices will be returned. + + @ingroup API + @param vendor_id The Vendor ID (VID) of the types of device + to open. + @param product_id The Product ID (PID) of the types of + device to open. + + @returns + This function returns a pointer to a linked list of type + struct #hid_device, containing information about the HID devices + attached to the system, or NULL in the case of failure. Free + this linked list by calling hid_free_enumeration(). + */ + struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id); + + /** @brief Free an enumeration Linked List + + This function frees a linked list created by hid_enumerate(). + + @ingroup API + @param devs Pointer to a list of struct_device returned from + hid_enumerate(). + */ + void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs); + + /** @brief Open a HID device using a Vendor ID (VID), Product ID + (PID) and optionally a serial number. + + If @p serial_number is NULL, the first device with the + specified VID and PID is opened. + + @ingroup API + @param vendor_id The Vendor ID (VID) of the device to open. + @param product_id The Product ID (PID) of the device to open. + @param serial_number The Serial Number of the device to open + (Optionally NULL). + + @returns + This function returns a pointer to a #hid_device object on + success or NULL on failure. + */ + HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number); + + /** @brief Open a HID device by its path name. + + The path name be determined by calling hid_enumerate(), or a + platform-specific path name can be used (eg: /dev/hidraw0 on + Linux). + + @ingroup API + @param path The path name of the device to open + + @returns + This function returns a pointer to a #hid_device object on + success or NULL on failure. + */ + HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path); + + /** @brief Write an Output report to a HID device. + + The first byte of @p data[] must contain the Report ID. For + devices which only support a single report, this must be set + to 0x0. The remaining bytes contain the report data. Since + the Report ID is mandatory, calls to hid_write() will always + contain one more byte than the report contains. For example, + if a hid report is 16 bytes long, 17 bytes must be passed to + hid_write(), the Report ID (or 0x0, for devices with a + single report), followed by the report data (16 bytes). In + this example, the length passed in would be 17. + + hid_write() will send the data on the first OUT endpoint, if + one exists. If it does not, it will send the data through + the Control Endpoint (Endpoint 0). + + @ingroup API + @param device A device handle returned from hid_open(). + @param data The data to send, including the report number as + the first byte. + @param length The length in bytes of the data to send. + + @returns + This function returns the actual number of bytes written and + -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length); + + /** @brief Read an Input report from a HID device with timeout. + + Input reports are returned + to the host through the INTERRUPT IN endpoint. The first byte will + contain the Report number if the device uses numbered reports. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data A buffer to put the read data into. + @param length The number of bytes to read. For devices with + multiple reports, make sure to read an extra byte for + the report number. + @param milliseconds timeout in milliseconds or -1 for blocking wait. + + @returns + This function returns the actual number of bytes read and + -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds); + + /** @brief Read an Input report from a HID device. + + Input reports are returned + to the host through the INTERRUPT IN endpoint. The first byte will + contain the Report number if the device uses numbered reports. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data A buffer to put the read data into. + @param length The number of bytes to read. For devices with + multiple reports, make sure to read an extra byte for + the report number. + + @returns + This function returns the actual number of bytes read and + -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length); + + /** @brief Set the device handle to be non-blocking. + + In non-blocking mode calls to hid_read() will return + immediately with a value of 0 if there is no data to be + read. In blocking mode, hid_read() will wait (block) until + there is data to read before returning. + + Nonblocking can be turned on and off at any time. + + @ingroup API + @param device A device handle returned from hid_open(). + @param nonblock enable or not the nonblocking reads + - 1 to enable nonblocking + - 0 to disable nonblocking. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock); + + /** @brief Send a Feature report to the device. + + Feature reports are sent over the Control endpoint as a + Set_Report transfer. The first byte of @p data[] must + contain the Report ID. For devices which only support a + single report, this must be set to 0x0. The remaining bytes + contain the report data. Since the Report ID is mandatory, + calls to hid_send_feature_report() will always contain one + more byte than the report contains. For example, if a hid + report is 16 bytes long, 17 bytes must be passed to + hid_send_feature_report(): the Report ID (or 0x0, for + devices which do not use numbered reports), followed by the + report data (16 bytes). In this example, the length passed + in would be 17. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data The data to send, including the report number as + the first byte. + @param length The length in bytes of the data to send, including + the report number. + + @returns + This function returns the actual number of bytes written and + -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length); + + /** @brief Get a feature report from a HID device. + + Make sure to set the first byte of @p data[] to the Report + ID of the report to be read. Make sure to allow space for + this extra byte in @p data[]. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data A buffer to put the read data into, including + the Report ID. Set the first byte of @p data[] to the + Report ID of the report to be read. + @param length The number of bytes to read, including an + extra byte for the report ID. The buffer can be longer + than the actual report. + + @returns + This function returns the number of bytes read and + -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length); + + /** @brief Close a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + */ + void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device); + + /** @brief Get The Manufacturer String from a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen); + + /** @brief Get The Product String from a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen); + + /** @brief Get The Serial Number String from a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen); + + /** @brief Get a string from a HID device, based on its string index. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string_index The index of the string to get. + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen); + + /** @brief Get a string describing the last error which occurred. + + @ingroup API + @param device A device handle returned from hid_open(). + + @returns + This function returns a string containing the last error + which occurred or NULL if none has occurred. + */ + HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID.h new file mode 100644 index 000000000..9e8cd9ea9 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID.h @@ -0,0 +1,95 @@ +/** + ****************************************************************************** + * + * @file rawhid.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup opHIDPlugin Raw HID Plugin + * @{ + * @brief Impliments a HID USB connection to the flight hardware as a QIODevice + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef OPHID_H +#define OPHID_H + +#include "opHID_global.h" + +#include +#include +#include +#include +#include "opHID_hidapi.h" +#include "opHID_usbmon.h" + +class RawHIDReadThread; +class RawHIDWriteThread; + +/** +* The actual IO device that will be used to communicate +* with the board. +*/ +class OPHID_EXPORT RawHID : public QIODevice +{ + Q_OBJECT + + friend class RawHIDReadThread; + friend class RawHIDWriteThread; + +public: + RawHID(); + RawHID(const QString &deviceName); + virtual ~RawHID(); + + virtual bool open(OpenMode mode); + virtual void close(); + virtual bool isSequential() const; + +signals: + void closed(); + +public slots: + void onDeviceUnplugged(int num); + +protected: + virtual qint64 readData(char *data, qint64 maxSize); + virtual qint64 writeData(const char *data, qint64 maxSize); + virtual qint64 bytesAvailable() const; + virtual qint64 bytesToWrite() const; + + //! Callback from the read thread to open the device + bool openDevice(); + + //! Callback from teh read thread to close the device + bool closeDevice(); + + QString serialNumber; + + int m_deviceNo; + opHID_hidapi dev; + bool device_open; + + RawHIDReadThread *m_readThread; + RawHIDWriteThread *m_writeThread; + + QMutex *m_mutex; + QMutex *m_startedMutex; +}; + +#endif // OPHID_H + diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_const.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_const.h new file mode 100644 index 000000000..bef7341ac --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_const.h @@ -0,0 +1,66 @@ +/** + ****************************************************************************** + * + * @file rawhid_const.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup RawHIDPlugin Raw HID Plugin + * @{ + * @brief Impliments a HID USB connection to the flight hardware as a QIODevice + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef OPHID_CONST_H +#define OPHID_CONST_H + +#define printf qDebug +#define OPHID_DEBUG_ON 1 +#ifdef OPHID_DEBUG_ON +#define OPHID_DEBUG(fmt, args...) qDebug("[DEBUG] "fmt, ## args) +#define OPHID_TRACE(fmt, args...) qDebug("[TRACE] %s:%s:%d: "fmt, __FILE__, __func__, __LINE__, ## args) +#define OPHID_ERROR(fmt, args...) qDebug("[ERROR] %s:%s:%d: "fmt, __FILE__, __func__, __LINE__, ## args) +#define OPHID_WARNING(fmt, args...) qDebug("[WARNING] "fmt, ## args) +#else +#define OPHID_DEBUG(fmt, args...) +#define OPHID_TRACE(fmt, args...) +#define OPHID_ERROR(fmt, args...) +#define OPHID_WARNING(fmt, args...) +#endif + + + +// USB +#define USB_MAX_DEVICES 10 +#define USB_VID 0x20A0 +#define USB_PID 0x4117 +#define USB_USAGE_PAGE 0xFF9C +#define USB_USAGE 0x0001 +#define USB_DEV_SERIAL_LEN 24 +#define USB_PID_ANY -1 +#define USB_MAX_STRING_SIZE 255 + +// ERROR +#define OPHID_NO_ERROR 0 +#define OPHID_ERROR_RET -1 +#define OPHID_ERROR_POINTER -2 +#define OPHID_ERROR_PARAMETER -3 +#define OPHID_ERROR_HANDLE -4 +#define OPHID_ERROR_INIT -5 + +#endif // OPHID_CONST_H + diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_global.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_global.h new file mode 100644 index 000000000..a1266a946 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_global.h @@ -0,0 +1,40 @@ +/** + ****************************************************************************** + * + * @file rawhid_global.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup opHIDPlugin Raw HID Plugin + * @{ + * @brief Impliments a HID USB connection to the flight hardware as a QIODevice + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef OPHID_GLOBAL_H +#define OPHID_GLOBAL_H + +#include + +#if defined(OPHID_LIBRARY) +# define OPHID_EXPORT Q_DECL_EXPORT +#else +# define OPHID_EXPORT Q_DECL_IMPORT +#endif + +#endif // OPHID_GLOBAL_H + diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h new file mode 100644 index 000000000..c023a4866 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h @@ -0,0 +1,96 @@ +/** + ****************************************************************************** + * + * @file pjrc_rawhid.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup opHIDPlugin HID Plugin + * @{ + * @brief Impliments a HID USB connection to the flight hardware as a QIODevice + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef OPHID_HIDAPI_H +#define OPHID_HIDAPI_H +#include +#include +#include +#include +#include +#include +#include +#include "hidapi.h" +#include "opHID_const.h" +#include "opHID_global.h" + +typedef struct hid_struct hid_t; +struct hid_struct +{ + usb_dev_handle *usb; + int open; + int iface; + int ep_in; + int ep_out; + struct hid_struct *prev; + struct hid_struct *next; +}; + +struct hidapi_wrapper_device +{ + struct hid_device_info *list_ptr; + hid_device *handle; +}; + + +class OPHID_EXPORT opHID_hidapi: public QObject +{ + + Q_OBJECT + +public: + + opHID_hidapi(); + + ~opHID_hidapi(); + + int enumerate(int *devices_found); + + int open(int max, int vid, int pid, int usage_page, int usage); + + int receive(int, void *buf, int len, int timeout); + + void close(int num); + + int send(int num, void *buf, int len, int timeout); + + QString getserial(int num); + +private: + struct hidapi_wrapper_device hidapi_device; + + /** A mutex to protect hid write */ + QMutex hid_write_Mtx; + + /** A mutex to protect hid read */ + QMutex hid_read_Mtx; + +signals: + void deviceUnplugged(int); +}; + +#endif diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_plugin.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_plugin.h new file mode 100644 index 000000000..d62b2076a --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_plugin.h @@ -0,0 +1,101 @@ +/** + ****************************************************************************** + * + * @file rawhid.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup opHIDPlugin Raw HID Plugin + * @{ + * @brief Impliments a HID USB connection to the flight hardware as a QIODevice + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef OPHID_PLUGIN_H +#define OPHID_PLUGIN_H + +#include +#include +#include +#include "coreplugin/iconnection.h" + +#include "opHID.h" +#include "opHID_global.h" +#include "opHID_usbmon.h" + +class IConnection; +class RawHIDConnection; + + +/** +* Define a connection via the IConnection interface +* Plugin will add a instance of this class to the pool, +* so the connection manager can use it. +*/ +class OPHID_EXPORT RawHIDConnection: public Core::IConnection +{ + Q_OBJECT + +public: + RawHIDConnection(); + virtual ~RawHIDConnection(); + + virtual QList < Core::IConnection::device> availableDevices(); + virtual QIODevice *openDevice(const QString &deviceName); + virtual void closeDevice(const QString &deviceName); + + virtual QString connectionName(); + virtual QString shortName(); + virtual void suspendPolling(); + virtual void resumePolling(); + + bool deviceOpened() { return (RawHidHandle != NULL); } // Pip + +protected slots: + void onDeviceConnected(); + void onDeviceDisconnected(); + +private: + RawHID *RawHidHandle; + bool enablePolling; + +protected: + QMutex m_enumMutex; + USBMonitor* m_usbMonitor; + bool m_deviceOpened; +}; + +class OPHID_EXPORT RawHIDPlugin + : public ExtensionSystem::IPlugin +{ + Q_OBJECT + +public: + RawHIDPlugin(); + ~RawHIDPlugin(); + + virtual bool initialize(const QStringList &arguments, QString *error_message); + virtual void extensionsInitialized(); + +private: + RawHIDConnection *hidConnection; + USBMonitor* m_usbMonitor; + +}; + +#endif // OPHID_PLUGIN_H + diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h new file mode 100644 index 000000000..474876051 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h @@ -0,0 +1,203 @@ +/** + ****************************************************************************** + * + * @file usbmonitor.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup RawHIDPlugin Raw HID Plugin + * @{ + * @brief Monitors the USB bus for devince insertion/removal + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef OPHID_USBMON_H +#define OPHID_USBMON_H + +#include "opHID_global.h" + +#include +#include + +// Arch dependent +#if defined( Q_OS_MAC) +#include +#include +#elif defined(Q_OS_UNIX) +#include +#include +#elif defined (Q_OS_WIN32) +#ifndef _WIN32_WINNT + #define _WIN32_WINNT 0x0500 +#endif +#ifndef _WIN32_WINDOWS + #define _WIN32_WINDOWS 0x0500 +#endif +#ifndef WINVER + #define WINVER 0x0500 +#endif +#include +#include +#include +#include +#include +#endif + + +#ifdef Q_OS_WIN +#ifdef QT_GUI_LIB +#include +class USBMonitor; + +class USBRegistrationWidget : public QWidget +{ + Q_OBJECT +public: + USBRegistrationWidget( USBMonitor* qese ) { + this->qese = qese; + } + ~USBRegistrationWidget( ) {} + +protected: + USBMonitor* qese; + bool winEvent( MSG* message, long* result ); +}; +#endif +#endif + +struct USBPortInfo { + //QString friendName; ///< Friendly name. + //QString physName; + //QString enumName; ///< It seems its the only one with meaning + QString serialNumber; // As a string as it can be anything, really... + QString manufacturer; + QString product; +#if defined(Q_OS_WIN32) + QString devicePath; //only has meaning on windows +#elif defined(Q_OS_MAC) + IOHIDDeviceRef dev_handle; +#endif + int UsagePage; + int Usage; + int vendorID; ///< Vendor ID. + int productID; ///< Product ID + int bcdDevice; +}; + +/** +* A monitoring thread which will wait for device events. +*/ + +class OPHID_EXPORT USBMonitor : public QThread +{ + Q_OBJECT + +public: + enum RunState { + Bootloader = 0x01, + Running = 0x02 + }; + + enum USBConstants { + idVendor_OpenPilot = 0x20a0, + idProduct_OpenPilot = 0x415a, + idProduct_CopterControl = 0x415b, + idProduct_PipXtreme = 0x415c + }; + + static USBMonitor *instance(); + + USBMonitor(QObject *parent = 0); + ~USBMonitor(); + QList availableDevices(); + QList availableDevices(int vid, int pid, int boardModel, int runState); +#if defined (Q_OS_WIN32) + LRESULT onDeviceChangeWin( WPARAM wParam, LPARAM lParam ); +#endif +signals: + /*! + A new device has been connected to the system. + + setUpNotifications() must be called first to enable event-driven device notifications. + Currently only implemented on Windows and OS X. + \param info The device that has been discovered. + */ + void deviceDiscovered( const USBPortInfo & info ); + /*! + A device has been disconnected from the system. + + setUpNotifications() must be called first to enable event-driven device notifications. + Currently only implemented on Windows and OS X. + \param info The device that was disconnected. + */ + void deviceRemoved( const USBPortInfo & info ); + +private slots: + /** + Callback available for whenever the system that is put in place gets + an event + */ + void deviceEventReceived(); + +private: + + //! Mutex for modifying the list of available devices + QMutex * listMutex; + + //! List of known devices maintained by callbacks + QList knowndevices; + + Q_DISABLE_COPY(USBMonitor) + static USBMonitor *m_instance; + + + // Depending on the OS, we'll need different things: +#if defined( Q_OS_MAC) + static void attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev); + static void detach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev); + void addDevice(USBPortInfo info); + void removeDevice(IOHIDDeviceRef dev); + IOHIDManagerRef hid_manager; +#elif defined(Q_OS_UNIX) + struct udev *context; + struct udev_monitor *monitor; + QSocketNotifier *monitorNotifier; + USBPortInfo makePortInfo(struct udev_device *dev); +#elif defined (Q_OS_WIN32) + GUID guid_hid; + void setUpNotifications(); + /*! + * Get specific property from registry. + * \param devInfo pointer to the device information set that contains the interface + * and its underlying device. Returned by SetupDiGetClassDevs() function. + * \param devData pointer to an SP_DEVINFO_DATA structure that defines the device instance. + * this is returned by SetupDiGetDeviceInterfaceDetail() function. + * \param property registry property. One of defined SPDRP_* constants. + * \return property string. + */ + static QString getDeviceProperty(HDEVINFO devInfo, PSP_DEVINFO_DATA devData, DWORD property); + static int infoFromHandle(const GUID & guid,USBPortInfo & info,HDEVINFO & devInfo,DWORD & index); + static void enumerateDevicesWin( const GUID & guidDev, QList* infoList ); + bool matchAndDispatchChangedDevice(const QString & deviceID, const GUID & guid, WPARAM wParam); +#ifdef QT_GUI_LIB + USBRegistrationWidget* notificationWidget; +#endif +#endif + +}; +#endif // OPHID_USBMON_H + diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbsignal.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbsignal.h new file mode 100644 index 000000000..15a3376a4 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbsignal.h @@ -0,0 +1,55 @@ +/** + ****************************************************************************** + * + * @file usbmonitor.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup opHIDPlugin Raw HID Plugin + * @{ + * @brief Monitors the USB bus for devince insertion/removal + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef OPHID_USBSIGNAL_H +#define OPHID_USBSIGNAL_H + +#include +#include "opHID_usbmon.h" + +class OPHID_EXPORT USBSignalFilter : public QObject +{ + Q_OBJECT + +private: + int m_vid; + int m_pid; + int m_boardModel; + int m_runState; + +signals: + void deviceDiscovered(); + +private slots: + void m_deviceDiscovered(USBPortInfo port); + +public: + USBSignalFilter(int vid, int pid, int boardModel, int runState); +}; + +#endif // OPHID_USBSIGNAL_H + diff --git a/ground/openpilotgcs/src/plugins/opHID/opHID.pluginspec b/ground/openpilotgcs/src/plugins/opHID/opHID.pluginspec new file mode 100644 index 000000000..cbbe8982c --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/opHID.pluginspec @@ -0,0 +1,10 @@ + +The OpenPilot Project + (C) 2013 OpenPilot Project + GNU Public License (GPL) Version 3 + Connection to OpenPilot board using HID USB interface + http://www.openpilot.org + + + + diff --git a/ground/openpilotgcs/src/plugins/opHID/opHID.pri b/ground/openpilotgcs/src/plugins/opHID/opHID.pri new file mode 100644 index 000000000..2c05da83d --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/opHID.pri @@ -0,0 +1,3 @@ +include(opHID_dependencies.pri) + +LIBS *= -l$$qtLibraryName(opHID) diff --git a/ground/openpilotgcs/src/plugins/opHID/opHID.pro b/ground/openpilotgcs/src/plugins/opHID/opHID.pro new file mode 100644 index 000000000..1080f4c67 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/opHID.pro @@ -0,0 +1,72 @@ +TEMPLATE = lib +TARGET = opHID +include(../../openpilotgcsplugin.pri) +include(opHID_dependencies.pri) +HEADERS += inc/opHID_global.h \ + inc/opHID_plugin.h \ + inc/opHID.h \ + inc/opHID_hidapi.h \ + inc/opHID_const.h \ + inc/opHID_usbmon.h \ + inc/opHID_usbsignal.h \ + inc/hidapi.h +SOURCES += src/opHID_plugin.cpp \ + src/opHID.cpp \ + src/opHID_usbsignal.cpp \ + src/opHID_hidapi.cpp +FORMS += +RESOURCES += +DEFINES += OPHID_LIBRARY +OTHER_FILES += opHID.pluginspec +INCLUDEPATH += ./inc +# Platform Specific +win32 { + SOURCES += src/opHID_usbmon_win.cpp \ + hidapi/windows/hid.c + LIBS += -lhid -lsetupapi +} +macx { + SOURCES += src/opHID_usbmon_mac.cpp \ + hidapi/mac/hid.c + SDK = /Developer/SDKs/MacOSX10.5.sdk + ARCH = -mmacosx-version-min=10.5 \ + -arch \ + ppc \ + -arch \ + i386 + LIBS += $(ARCH) \ + -Wl,-syslibroot,$(SDK) \ + -framework \ + IOKit \ + -framework \ + CoreFoundation +} +linux-g++ { + SOURCES += src/opHID_usbmon_linux.cpp + LIBS += -lusb -ludev + +# hidapi library +## rawhid +# SOURCES += hidapi/linux/hid.c +## libusb + SOURCES += hidapi/libusb/hid.c + LIBS += `pkg-config libusb-1.0 --libs` -lrt -lpthread + INCLUDEPATH += /usr/include/libusb-1.0 +# INCLUDEPATH += `pkg-config libusb-1.0 --cflags` + +} +linux-g++-64 { + SOURCES += src/opHID_usbmon_linux.cpp + LIBS += -lusb -ludev + +# hidapi library +## rawhid +# SOURCES += hidapi/linux/hid.c +## libusb + SOURCES += hidapi/libusb/hid.c + LIBS += `pkg-config libusb-1.0 --libs` -lrt -lpthread + INCLUDEPATH += /usr/include/libusb-1.0 +# INCLUDEPATH += `pkg-config libusb-1.0 --cflags` + +} + diff --git a/ground/openpilotgcs/src/plugins/opHID/opHID_dependencies.pri b/ground/openpilotgcs/src/plugins/opHID/opHID_dependencies.pri new file mode 100644 index 000000000..a64caedc1 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/opHID_dependencies.pri @@ -0,0 +1 @@ +include(../../plugins/coreplugin/coreplugin.pri) diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID.cpp b/ground/openpilotgcs/src/plugins/opHID/src/opHID.cpp new file mode 100644 index 000000000..60472f75c --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/src/opHID.cpp @@ -0,0 +1,497 @@ +/** + ****************************************************************************** + * + * @file rawhid.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup opHIDPlugin HID Plugin + * @{ + * @brief Impliments a HID USB connection to the flight hardware as a QIODevice + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "opHID.h" +#include "opHID_const.h" +#include "coreplugin/connectionmanager.h" +#include +#include +#include +#include +#include + +class IConnection; + +//timeout value used when we want to return directly without waiting +static const int READ_TIMEOUT = 200; +static const int READ_SIZE = 64; + +static const int WRITE_TIMEOUT = 1000; +static const int WRITE_SIZE = 64; + + + +// ********************************************************************************* + +/** +* Thread to desynchronize reading from the device +*/ +class RawHIDReadThread : public QThread +{ +public: + RawHIDReadThread(RawHID *hid); + virtual ~RawHIDReadThread(); + + /** Return the data read so far without waiting */ + int getReadData(char *data, int size); + + /** return the bytes buffered */ + qint64 getBytesAvailable(); + +public slots: + void terminate() { + m_running = false; + } + +protected: + void run(); + + /** QByteArray might not be the most efficient way to implement + a circular buffer but it's good enough and very simple */ + QByteArray m_readBuffer; + + /** A mutex to protect read buffer */ + QMutex m_readBufMtx; + + RawHID *m_hid; + + opHID_hidapi *hiddev; + int hidno; + + bool m_running; +}; + + +// ********************************************************************************* + +/** +* This class is nearly the same than RawHIDReadThread but for writing +*/ +class RawHIDWriteThread : public QThread +{ +public: + RawHIDWriteThread(RawHID *hid); + virtual ~RawHIDWriteThread(); + + /** Add some data to be written without waiting */ + int pushDataToWrite(const char *data, int size); + + /** Return the number of bytes buffered */ + qint64 getBytesToWrite(); + +public slots: + void terminate() { + m_running = false; + } + +protected: + void run(); + + /** QByteArray might not be the most efficient way to implement + a circular buffer but it's good enough and very simple */ + QByteArray m_writeBuffer; + + /** A mutex to protect read buffer */ + QMutex m_writeBufMtx; + + /** Synchronize task with data arival */ + QWaitCondition m_newDataToWrite; + + RawHID *m_hid; + + opHID_hidapi *hiddev; + int hidno; + + bool m_running; +}; + +// ********************************************************************************* + +RawHIDReadThread::RawHIDReadThread(RawHID *hid) + : m_hid(hid), + hiddev(&hid->dev), + hidno(hid->m_deviceNo), + m_running(true) +{ + OPHID_TRACE("IN"); + hid->m_startedMutex->lock(); + OPHID_TRACE("OUT"); +} + +RawHIDReadThread::~RawHIDReadThread() +{ + m_running = false; + //wait for the thread to terminate + if(wait(10000) == false) + qDebug() << "Cannot terminate RawHIDReadThread"; +} + +void RawHIDReadThread::run() +{ + OPHID_TRACE("IN"); + + m_running = m_hid->openDevice(); + + while(m_running) + { + //here we use a temporary buffer so we don't need to lock + //the mutex while we are reading from the device + + // Want to read in regular chunks that match the packet size the device + // is using. In this case it is 64 bytes (the interrupt packet limit) + // although it would be nice if the device had a different report to + // configure this + char buffer[READ_SIZE] = {0}; + + int ret = hiddev->receive(hidno, buffer, READ_SIZE, READ_TIMEOUT); + + if(ret > 0) //read some data + { + QMutexLocker lock(&m_readBufMtx); + // Note: Preprocess the USB packets in this OS independent code + // First byte is report ID, second byte is the number of valid bytes + m_readBuffer.append(&buffer[2], buffer[1]); + + emit m_hid->readyRead(); + } + else if(ret == 0) //nothing read + { + } + else // < 0 => error + { + //TODO! make proper error handling, this only quick hack for unplug freeze + m_running=false; + } + } + m_hid->closeDevice(); + + OPHID_TRACE("OUT"); +} + +int RawHIDReadThread::getReadData(char *data, int size) +{ + QMutexLocker lock(&m_readBufMtx); + + size = qMin(size, m_readBuffer.size()); + + memcpy(data, m_readBuffer.constData(), size); + m_readBuffer.remove(0, size); + + return size; +} + +qint64 RawHIDReadThread::getBytesAvailable() +{ + QMutexLocker lock(&m_readBufMtx); + return m_readBuffer.size(); +} + +RawHIDWriteThread::RawHIDWriteThread(RawHID *hid) + : m_hid(hid), + hiddev(&hid->dev), + hidno(hid->m_deviceNo), + m_running(true) +{ +} + +// ********************************************************************************* + +RawHIDWriteThread::~RawHIDWriteThread() +{ + m_running = false; + //wait for the thread to terminate + if(wait(10000) == false) + qDebug() << "Cannot terminate RawHIDReadThread"; +} + +void RawHIDWriteThread::run() +{ + while(m_running) + { + char buffer[WRITE_SIZE] = {0}; + + m_writeBufMtx.lock(); + int size = qMin(WRITE_SIZE-2, m_writeBuffer.size()); + while(size <= 0) + { + //wait on new data to write condition, the timeout + //enable the thread to shutdown properly + m_newDataToWrite.wait(&m_writeBufMtx, 200); + if(!m_running) + return; + + size = m_writeBuffer.size(); + } + + //NOTE: data size is limited to 2 bytes less than the + //usb packet size (64 bytes for interrupt) to make room + //for the reportID and valid data length + size = qMin(WRITE_SIZE-2, m_writeBuffer.size()); + memcpy(&buffer[2], m_writeBuffer.constData(), size); + buffer[1] = size; //valid data length + buffer[0] = 2; //reportID + m_writeBufMtx.unlock(); + + // must hold lock through the send to know how much was sent + int ret = hiddev->send(hidno, buffer, WRITE_SIZE, WRITE_TIMEOUT); + + if(ret > 0) + { + //only remove the size actually written to the device + QMutexLocker lock(&m_writeBufMtx); + m_writeBuffer.remove(0, size); + + emit m_hid->bytesWritten(ret - 2); + } + else if(ret < 0) // < 0 => error + { + //TODO! make proper error handling, this only quick hack for unplug freeze + m_running=false; + qDebug() << "Error writing to device (" << ret << ")"; + } + else + { + qDebug() << "No data written to device ??"; + } + } +} + +int RawHIDWriteThread::pushDataToWrite(const char *data, int size) +{ + QMutexLocker lock(&m_writeBufMtx); + + m_writeBuffer.append(data, size); + m_newDataToWrite.wakeOne(); //signal that new data arrived + + return size; +} + +qint64 RawHIDWriteThread::getBytesToWrite() +{ + // QMutexLocker lock(&m_writeBufMtx); + return m_writeBuffer.size(); +} + +// ********************************************************************************* + +RawHID::RawHID(const QString &deviceName) + :QIODevice(), + serialNumber(deviceName), + m_deviceNo(-1), + m_readThread(NULL), + m_writeThread(NULL), + m_mutex(NULL) +{ + OPHID_TRACE("IN"); + + m_mutex = new QMutex(QMutex::Recursive); + + m_startedMutex = new QMutex(); + + // detect if the USB device is unplugged + QObject::connect(&dev, SIGNAL(deviceUnplugged(int)), this, SLOT(onDeviceUnplugged(int))); + + m_writeThread = new RawHIDWriteThread(this); + + // Starting the read thread will lock the m_startexMutex until the + // device is opened (which happens in that thread). + m_readThread = new RawHIDReadThread(this); + + m_readThread->start(); + + m_startedMutex->lock(); + + OPHID_TRACE("OUT"); +} + +/** + * @brief RawHID::openDevice This method opens the USB connection + * It is uses as a callback from the read thread so that the USB + * system code is registered in that thread instead of the calling + * thread (usually UI) + */ +bool RawHID::openDevice() { + + OPHID_TRACE("IN"); + + uint32_t opened = dev.open(USB_MAX_DEVICES, USB_VID, USB_PID_ANY, USB_USAGE_PAGE, USB_USAGE); + + OPHID_DEBUG("opened %d devices", opened); + for (uint32_t i=0; i < opened; i++) { + if (serialNumber == dev.getserial(i)) + m_deviceNo = i; + else + dev.close(i); + } + + // Now things are opened or not (from read thread) allow the constructor to complete + m_startedMutex->unlock(); + + // Leave if we have not found one device + // It should be the one we are looking for + if (!opened) + { + OPHID_TRACE("OUT"); + return false; + } + + m_writeThread->start(); + + OPHID_TRACE("OUT"); + return true; +} + +/** + * @brief RawHID::closeDevice This method closes the USB connection + * It is uses as a callback from the read thread so that the USB + * system code is unregistered from that thread\ + */ +bool RawHID::closeDevice() { + + OPHID_TRACE("IN"); + + dev.close(m_deviceNo); + + OPHID_TRACE("OUT"); + + return 0; +} + +RawHID::~RawHID() +{ +// OPHID_TRACE("IN"); + + // If the read thread exists then the device is open + if (m_readThread) + close(); + + // OPHID_TRACE("OUT"); +} + +void RawHID::onDeviceUnplugged(int num) +{ + if (num != m_deviceNo) + return; + + // The USB device has been unplugged + close(); +} + +bool RawHID::open(OpenMode mode) +{ + QMutexLocker locker(m_mutex); + + if (m_deviceNo < 0) + return false; + + QIODevice::open(mode); + + Q_ASSERT(m_readThread); + Q_ASSERT(m_writeThread); + if (m_readThread) m_readThread->start(); + if (m_writeThread) m_writeThread->start(); + + return true; +} + +void RawHID::close() +{ + OPHID_TRACE("IN"); + + emit aboutToClose(); + + if (m_writeThread) + { + OPHID_DEBUG("Terminating write thread"); + m_writeThread->terminate(); + delete m_writeThread; + m_writeThread = NULL; + OPHID_DEBUG("Write thread terminated"); + } + + + if (m_readThread) + { + OPHID_DEBUG("Terminating read thread"); + m_readThread->terminate(); + delete m_readThread; + m_readThread = NULL; + OPHID_DEBUG("Read thread terminated"); + } + + emit closed(); + + QIODevice::close(); + + OPHID_TRACE("OUT"); +} + +bool RawHID::isSequential() const +{ + return true; +} + +qint64 RawHID::bytesAvailable() const +{ + QMutexLocker locker(m_mutex); + + if (!m_readThread) + return -1; + + return m_readThread->getBytesAvailable() + QIODevice::bytesAvailable(); +} + +qint64 RawHID::bytesToWrite() const +{ + QMutexLocker locker(m_mutex); + + if (!m_writeThread) + return -1; + + return m_writeThread->getBytesToWrite() + QIODevice::bytesToWrite(); +} + +qint64 RawHID::readData(char *data, qint64 maxSize) +{ + QMutexLocker locker(m_mutex); + + if (!m_readThread || !data) + return -1; + + return m_readThread->getReadData(data, maxSize); +} + +qint64 RawHID::writeData(const char *data, qint64 maxSize) +{ + QMutexLocker locker(m_mutex); + + if (!m_writeThread || !data) + return -1; + + return m_writeThread->pushDataToWrite(data, maxSize); +} + diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_hidapi.cpp b/ground/openpilotgcs/src/plugins/opHID/src/opHID_hidapi.cpp new file mode 100644 index 000000000..c1cc64c9c --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/src/opHID_hidapi.cpp @@ -0,0 +1,380 @@ +/** + ****************************************************************************** + * + * @file rawhid.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup opHIDPlugin OpenPilot HID Plugin + * @{ + * @brief Impliments a HID USB connection to the flight hardware as a QIODevice + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include "opHID_const.h" +#include "opHID_hidapi.h" + +/** +* \brief Constructor +* +* \note +* +*/ +opHID_hidapi::opHID_hidapi() +{ + OPHID_TRACE("IN"); + + hidapi_device.list_ptr = NULL; + hidapi_device.handle = NULL; + + // Make sure hidapi lib is ready + if (hid_init()) + OPHID_ERROR("Lib initialization (hidpai)."); + + OPHID_TRACE("OUT"); +} + + +/** +* \brief Destructor +* +* \note This does not handle the cleanup of hidapi lib +* +*/ +opHID_hidapi::~opHID_hidapi() +{ + OPHID_TRACE("IN"); + + OPHID_TRACE("OUT"); +} + + +// Function: enumerate the HID devices connected. +// Return: +// - a pointer to a list of HID devices found +// - number of HID devices found +int opHID_hidapi::enumerate(int *devices_found) +{ + *devices_found = 0; + struct hid_device_info *current_device_ptr = NULL; + + OPHID_TRACE("IN"); + + // Free any previous enumeration + if (hidapi_device.list_ptr) + hid_free_enumeration(hidapi_device.list_ptr); + + // Enumerate + hidapi_device.list_ptr = hid_enumerate(USB_VID, 0x0); + + // Display the list of devices found (for debug) + current_device_ptr = hidapi_device.list_ptr; + + while (current_device_ptr) { + OPHID_DEBUG("HID Device Found"); + OPHID_DEBUG(" type:............VID(%04hx).PID(%04hx)", current_device_ptr->vendor_id, current_device_ptr->product_id); + OPHID_DEBUG(" path:............%s", current_device_ptr->path); + OPHID_DEBUG(" Release:.........%hx", current_device_ptr->release_number); + OPHID_DEBUG(" Interface:.......%d", current_device_ptr->interface_number); + current_device_ptr = current_device_ptr->next; + (*devices_found)++; + } + + OPHID_TRACE("OUT"); + return OPHID_NO_ERROR; +} + + +/** +* \brief Open HID device using hidapi library +* +* \note This function does \b not support opening multiple devices at once. +* +* \param[in] vid USB vendor id of the device to open (-1 for any). +* \param[in] pid USB product id of the device to open (-1 for any). +* \return Number of opened device. +* \retval 0 or 1. +*/ +int opHID_hidapi::open(int max, int vid, int pid, int usage_page, int usage) +{ + int devices_found = false; + struct hid_device_info *current_device_ptr = NULL; + + OPHID_TRACE("IN"); + + OPHID_DEBUG("max: %d, vid: 0x%X, pid: 0x%X, usage_page: %d, usage: %d.", max, vid, pid, usage_page, usage); + + if (hidapi_device.handle) + { + OPHID_WARNING("WARNING: device seems already open."); + } + + // if caller knows which one to look for open it + if (vid != -1 && pid != -1) + { + if (pid == -1) + pid = 0; + if (vid == -1) + vid = 0; + hidapi_device.handle = hid_open(vid, pid, NULL); + + if (!hidapi_device.handle) + { + OPHID_ERROR("Unable to open device."); + devices_found = false; + } + else + { + OPHID_DEBUG("HID Device Found"); + OPHID_DEBUG(" type:............VID(%04hx).PID(%04hx)", vid, pid); + devices_found = true; + } + } + else + { + // Get the list of available hid devices + if (enumerate(&devices_found) != OPHID_NO_ERROR) + { + OPHID_ERROR("Error during enumeration"); + return 0; + } + + // Look for the first one of interest + if (devices_found) + { +// devices_found = false; + current_device_ptr = hidapi_device.list_ptr; +#if 0 + // Currently assuming the last one is the right one + // This won't be necessary true later (TODO) + while (current_device_ptr) + { + // + if (current_device_ptr->vendor_id == vid) + { + devices_found = true; + break; + } + current_device_ptr = current_device_ptr->next; + } +#endif + } + + if (devices_found) + { + OPHID_DEBUG("Opening device VID(%04hx).PID(%04hx)", + current_device_ptr->vendor_id, + current_device_ptr->product_id); + + vid = current_device_ptr->vendor_id; + pid = current_device_ptr->product_id; + + if (hidapi_device.list_ptr) + hid_free_enumeration(hidapi_device.list_ptr); + + hidapi_device.handle = hid_open(vid /*current_device_ptr->vendor_id*/, + pid /*current_device_ptr->product_id*/, + NULL); + if (!hidapi_device.handle) + { + OPHID_ERROR("Unable to open device."); + devices_found = false; + } + } + } + + OPHID_DEBUG("Found %d devices", devices_found); + + OPHID_TRACE("OUT"); + + return devices_found; +} + + +/** +* \brief Read an Input report from a HID device. +* +* \note This function does \b not block for now. +* Tests show that it does not need to. +* +* \param[in] num Id of the device to receive packet (NOT supported). +* \param[in] buf Pointer to the bufer to write the received packet to. +* \param[in] len Size of the buffer. +* \param[in] timeout Not supported. +* \return Number of bytes received, or -1 on error. +* \retval -1 for error or bytes received. +*/ +int opHID_hidapi::receive(int num, void *buf, int len, int timeout) +{ + Q_UNUSED(num); + Q_UNUSED(timeout); + + int bytes_read = 0; + + if (!buf) + { + OPHID_ERROR("Unexpected parameter value (ptr)."); + return OPHID_ERROR_POINTER; + } + + if (!len) + { + OPHID_ERROR("Unexpected parameter value (incorrect lenght)."); + return OPHID_ERROR_PARAMETER; + } + + if (hidapi_device.handle == NULL) + { + OPHID_ERROR("Handle invalid."); + return OPHID_ERROR_HANDLE; + } + + hid_read_Mtx.lock(); + bytes_read = hid_read(hidapi_device.handle, (unsigned char*)buf, len); + hid_read_Mtx.unlock(); + + // hidapi lib does not expose the libusb errors. + if (bytes_read == -1) + { + OPHID_ERROR("hidapi: %d", bytes_read); + } + + return bytes_read; +} + +/** +* \brief Write an Output report to a HID device. +* +* \note timeout is 1000ms for control transfer and +* 1000 ms for interrupt transfer. +* +* \param[in] num Id of the device to receive packet (NOT supported). +* \param[in] buf Pointer to the bufer to send. +* \param[in] len Size of the buffer. +* \param[in] timeout (not supported). +* \return Number of bytes received, or -1 on error. +* \retval -1 for error or bytes received. +*/ +int opHID_hidapi::send(int num, void *buf, int len, int timeout) +{ + Q_UNUSED(num); + Q_UNUSED(timeout); + + int bytes_written = 0; + int retry = 5; + + if (!buf) + { + OPHID_ERROR("Unexpected parameter value (ptr)."); + return OPHID_ERROR_POINTER; + } + + if (!len) + { + OPHID_ERROR("Unexpected parameter value (incorrect lenght)."); + return OPHID_ERROR_PARAMETER; + } + + if (hidapi_device.handle == NULL) + { + OPHID_ERROR("Handle invalid."); + return OPHID_ERROR_HANDLE; + } + + // hidapi has a timeout hardcoded to 1000ms, retry 5 times + while(retry--) + { + hid_write_Mtx.lock(); + bytes_written = hid_write(hidapi_device.handle, (const unsigned char*)buf, len); + hid_write_Mtx.unlock(); + if (bytes_written >= 0) + { + break; + } + } + + // hidapi lib does not expose the libusb errors. + if (bytes_written < 0) + { + OPHID_ERROR("hidapi: %d", bytes_written); + } + + return bytes_written; +} + + +/** +* \brief Return the serial number of a device. +* +* \note This function does \b not handle multiple +* HID devices. Only the serial number of the +* current HID device will supported. +* +* \param[in] num Id of the device to request SN (NOT supported). +* \return Serial number +* \retval string +*/ +QString opHID_hidapi::getserial(int num) +{ + Q_UNUSED(num); + + OPHID_TRACE("IN"); + + wchar_t buf[USB_MAX_STRING_SIZE]; + + if (hidapi_device.handle == NULL) + { + OPHID_ERROR("Handle invalid."); + return QString(""); + } + + if (hid_get_serial_number_string(hidapi_device.handle, buf, USB_MAX_STRING_SIZE) < 0) + { + OPHID_ERROR("Unable to read serial number string."); + return QString(""); + } + + OPHID_TRACE("OUT"); + return QString().fromWCharArray(buf); +} + + +/** +* \brief Close a HID device +* +* \note This function does \b not handle multiple +* HID devices currently. +* +* \param[in] num Id of the device to close (NOT supported). +*/ +void opHID_hidapi::close(int num) +{ + Q_UNUSED(num); + + OPHID_TRACE("IN"); + + if (hidapi_device.handle) + hid_close(hidapi_device.handle); + + OPHID_TRACE("OUT"); +} + diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_plugin.cpp b/ground/openpilotgcs/src/plugins/opHID/src/opHID_plugin.cpp new file mode 100644 index 000000000..d903ff65d --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/src/opHID_plugin.cpp @@ -0,0 +1,272 @@ +/** + ****************************************************************************** + * + * @file opHID_plugin.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup opHIDPlugin HID Plugin + * @{ + * @brief Impliments a HID USB connection to the flight hardware as a QIODevice + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "opHID_global.h" +#include "opHID_plugin.h" +#include + +#include +#include + +#include "opHID_hidapi.h" +#include "opHID_const.h" + + +/** +* \brief Constructor +* +* \note +* +*/ +RawHIDConnection::RawHIDConnection() +{ + RawHidHandle = NULL; + enablePolling = true; + + m_usbMonitor = USBMonitor::instance(); + + connect(m_usbMonitor, SIGNAL(deviceDiscovered(USBPortInfo)), this, SLOT(onDeviceConnected())); + connect(m_usbMonitor, SIGNAL(deviceRemoved(USBPortInfo)), this, SLOT(onDeviceDisconnected())); + +} + + +/** +* \brief Destructor +* +* \note +* +*/ +RawHIDConnection::~RawHIDConnection() +{ + if (RawHidHandle) + if (RawHidHandle->isOpen()) + RawHidHandle->close(); +} + + +/** +* \brief New device plugged +* +* \note The USB monitor tells us a new device appeared +* +*/ +void RawHIDConnection::onDeviceConnected() +{ + emit availableDevChanged(this); +} + + +/** +* \brief Device unplugged +* +* \note The USB monitor tells us a new device disappeared +* +*/ +void RawHIDConnection::onDeviceDisconnected() +{ + qDebug() << "onDeviceDisconnected()"; + if (enablePolling) + emit availableDevChanged(this); +} + + +/** +* \brief Available devices +* +* \return List of all currently available devices +*/ +QList < Core::IConnection::device> RawHIDConnection::availableDevices() +{ + QList < Core::IConnection::device> devices; + + QList portsList = m_usbMonitor->availableDevices(USBMonitor::idVendor_OpenPilot, -1, -1,USBMonitor::Running); + + // We currently list devices by their serial number + device dev; + foreach(USBPortInfo prt, portsList) { + dev.name=prt.serialNumber; + dev.displayName=prt.product; + devices.append(dev); + } + return devices; +} + + +/** +* \brief Open device +* +* \param[in] deviceName String name of the device to open +* \return initialized handle +*/ +QIODevice *RawHIDConnection::openDevice(const QString &deviceName) +{ + OPHID_TRACE("IN"); + + if (RawHidHandle) + closeDevice(deviceName); + + RawHidHandle = new RawHID(deviceName); + + if (!RawHidHandle) + { + OPHID_ERROR("Could not instentiate HID device"); + } + + OPHID_TRACE("OUT"); + + return RawHidHandle; +} + + +/** +* \brief Close device +* +* \param[in] deviceName String name of the device to close +*/ +void RawHIDConnection::closeDevice(const QString &deviceName) +{ + OPHID_TRACE("IN"); + + Q_UNUSED(deviceName); + + if (RawHidHandle) + { + OPHID_DEBUG("Closing device"); + RawHidHandle->close(); + delete RawHidHandle; + RawHidHandle = NULL; + } + + OPHID_TRACE("OUT"); +} + + +/** +* \brief Get connection name +* +* \return name of the connection +*/ +QString RawHIDConnection::connectionName() +{ + return QString("Raw HID USB"); +} + + +/** +* \brief Get shorter connection name +* +* \return shorter name of the connection +*/ +QString RawHIDConnection::shortName() +{ + return QString("USB"); +} + + +/** +* \brief Suspend polling +* +* \note Tells the Raw HID plugin to stop polling for USB devices +*/ +void RawHIDConnection::suspendPolling() +{ + enablePolling = false; +} + + +/** +* \brief Resume polling +* +* \note Tells the Raw HID plugin to resume polling for USB devices +*/ +void RawHIDConnection::resumePolling() +{ + enablePolling = true; +} + + +/** +* \brief Plugin Constructor +* +* \note +* +*/ +RawHIDPlugin::RawHIDPlugin() +{ + hidConnection = NULL; // Pip +} + + +/** +* \brief Plugin Destructor +* +* \note +* +*/ +RawHIDPlugin::~RawHIDPlugin() +{ + m_usbMonitor->quit(); + m_usbMonitor->wait(500); +} + + +/** +* \brief Instantiate a connection +* +* \note +* +*/ +void RawHIDPlugin::extensionsInitialized() +{ + hidConnection = new RawHIDConnection(); + addAutoReleasedObject(hidConnection); + + //temp for test + //addAutoReleasedObject(new RawHIDTestThread); +} + + +/** +* \brief instantiate the udev monotor engine +* +* \note +* +*/ +bool RawHIDPlugin::initialize(const QStringList & arguments, QString * errorString) +{ + Q_UNUSED(arguments); + Q_UNUSED(errorString); + + // We have to create the USB Monitor here: + m_usbMonitor = new USBMonitor(this); + + return true; +} + +Q_EXPORT_PLUGIN(RawHIDPlugin) + diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_linux.cpp b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_linux.cpp new file mode 100644 index 000000000..1cd404e37 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_linux.cpp @@ -0,0 +1,245 @@ +/** + ****************************************************************************** + * + * @file usbmonitor_linux.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup opHIDPlugin HID Plugin + * @{ + * @brief Implements the USB monitor on Linux using libudev + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "opHID_usbmon.h" +#include +#include "opHID_const.h" + + +/** +* \brief Display device info +* +* \note USB strings are Unicode, UCS2 +* encoded, but the strings returned from +* udev_device_get_sysattr_value() are UTF-8 encoded. +* +* \param[in] dev To display the information of. +*/ +void printPortInfo(struct udev_device *dev) +{ + OPHID_DEBUG(" Node: %s", udev_device_get_devnode(dev)); + OPHID_DEBUG(" Subsystem: %s", udev_device_get_subsystem(dev)); + OPHID_DEBUG(" Devtype: %s", udev_device_get_devtype(dev)); + OPHID_DEBUG(" Action: %s", udev_device_get_action(dev)); + OPHID_DEBUG(" VID/PID/bcdDevice : %s %s %s", + udev_device_get_sysattr_value(dev,"idVendor"), + udev_device_get_sysattr_value(dev, "idProduct"), + udev_device_get_sysattr_value(dev,"bcdDevice")); + OPHID_DEBUG(" %s - %s", + udev_device_get_sysattr_value(dev,"manufacturer"), + udev_device_get_sysattr_value(dev,"product")); + OPHID_DEBUG(" serial: %s", + udev_device_get_sysattr_value(dev, "serial")); + +} + + +/** +* \brief Handle event +* +* \note +* +*/ +void USBMonitor::deviceEventReceived() { + + qDebug() << "Device event"; + struct udev_device *dev; + + dev = udev_monitor_receive_device(this->monitor); + if (dev) { + printf("------- Got Device Event"); + QString action = QString(udev_device_get_action(dev)); + QString devtype = QString(udev_device_get_devtype(dev)); + if (action == "add" && devtype == "usb_device") { + printPortInfo(dev); + emit deviceDiscovered(makePortInfo(dev)); + } else if (action == "remove" && devtype == "usb_device"){ + printPortInfo(dev); + emit deviceRemoved(makePortInfo(dev)); + } + + udev_device_unref(dev); + } + else { + printf("No Device from receive_device(). An error occured."); + } + +} + + +/** +* \brief Return USB monitor instance +* +* \note . +* +* \return instance. +* \retval USBMonitor pointer. +*/ +USBMonitor* USBMonitor::instance() +{ + return m_instance; +} + + +USBMonitor* USBMonitor::m_instance = 0; + + +/** +* \brief Initialize udev monitor (contructor). +* +* \note +* +*/ +USBMonitor::USBMonitor(QObject *parent): QThread(parent) { + + m_instance = this; + + this->context = udev_new(); + + this->monitor = udev_monitor_new_from_netlink(this->context, "udev"); + udev_monitor_filter_add_match_subsystem_devtype( + this->monitor, "usb", NULL); + udev_monitor_enable_receiving(this->monitor); + this->monitorNotifier = new QSocketNotifier( + udev_monitor_get_fd(this->monitor), QSocketNotifier::Read, this); + connect(this->monitorNotifier, SIGNAL(activated(int)), + this, SLOT(deviceEventReceived())); + qDebug() << "Starting the Udev client"; + + start(); // Start the thread event loop so that the socketnotifier works +} + + +/** +* \brief Destructor +* +* \note +* +*/ +USBMonitor::~USBMonitor() +{ + quit(); +} + + +/** +* \brief Returns a list of all currently available devices +* +* \note +* +* \return List of all currently available devices +* \retval Qlist +*/ +QList USBMonitor::availableDevices() +{ + QList devicesList; + struct udev_list_entry *devices, *dev_list_entry; + struct udev_enumerate *enumerate; + struct udev_device *dev; + + enumerate = udev_enumerate_new(this->context); + udev_enumerate_add_match_subsystem(enumerate,"usb"); + //udev_enumerate_add_match_sysattr(enumerate, "idVendor", "20a0"); + udev_enumerate_scan_devices(enumerate); + devices = udev_enumerate_get_list_entry(enumerate); + // Will use the 'native' udev functions to loop: + udev_list_entry_foreach(dev_list_entry,devices) { + const char *path; + + /* Get the filename of the /sys entry for the device + and create a udev_device object (dev) representing it */ + path = udev_list_entry_get_name(dev_list_entry); + dev = udev_device_new_from_syspath(this->context, path); + if (QString(udev_device_get_devtype(dev)) == "usb_device") + devicesList.append(makePortInfo(dev)); + udev_device_unref(dev); + } + // free the enumerator object + udev_enumerate_unref(enumerate); + + return devicesList; +} + + +/** +* \brief Search for particular devices +* +* \note Be a bit more picky and ask only for a specific type of device: +* On OpenPilot, the bcdDeviceLSB indicates the run state: bootloader or running. +* bcdDeviceMSB indicates the board model. +* +* \param[in] vid USB vendor id of the device. +* \param[in] pid USB product id of the device. +* \param[in] bcdDeviceMSB MSB of the device in bcd format. +* \param[in] bcdDeviceLSB LSB of the device in bcd format. +* \return List of available devices +* \retval QList. +*/ +QList USBMonitor::availableDevices(int vid, int pid, int bcdDeviceMSB, int bcdDeviceLSB) +{ + QList allPorts = availableDevices(); + QList thePortsWeWant; + + foreach (USBPortInfo port, allPorts) { + if((port.vendorID==vid || vid==-1) && (port.productID==pid || pid==-1) && ((port.bcdDevice>>8)==bcdDeviceMSB || bcdDeviceMSB==-1) && + ( (port.bcdDevice&0x00ff) ==bcdDeviceLSB || bcdDeviceLSB==-1)) + thePortsWeWant.append(port); + } + return thePortsWeWant; +} + + +/** +* \brief Initialize port information of a specific device. +* +* \note +* +* \param[in] dev Udev device. +* \return Port info +* \retval USBPortInfo structure filled +*/ +USBPortInfo USBMonitor::makePortInfo(struct udev_device *dev) +{ + USBPortInfo prtInfo; + bool ok; + +#ifdef OPHID_DEBUG_INFO + printPortInfo(dev); +#endif + + prtInfo.vendorID = QString(udev_device_get_sysattr_value(dev, "idVendor")).toInt(&ok, 16); + prtInfo.productID = QString(udev_device_get_sysattr_value(dev, "idProduct")).toInt(&ok, 16); + prtInfo.serialNumber = QString(udev_device_get_sysattr_value(dev, "serial")); + prtInfo.manufacturer = QString(udev_device_get_sysattr_value(dev,"manufacturer")); + prtInfo.product = QString(udev_device_get_sysattr_value(dev,"product")); +// prtInfo.UsagePage = QString(udev_device_get_sysattr_value(dev,"")); +// prtInfo.Usage = QString(udev_device_get_sysattr_value(dev,"")); + prtInfo.bcdDevice = QString(udev_device_get_sysattr_value(dev,"bcdDevice")).toInt(&ok, 16); + + return prtInfo; +} + diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp new file mode 100644 index 000000000..aec0a83a7 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp @@ -0,0 +1,244 @@ +/** + ****************************************************************************** + * + * @file usbmonitor_mac.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup opHIDPlugin HID Plugin + * @{ + * @brief Implements the USB monitor on Mac using IOHID + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "opHID_usbmon.h" +#include +#include +#include +#include +#include +#include +#include "opHID_const.h" + +#define printf qDebug + +// ! Local helper functions +static bool HID_GetIntProperty(IOHIDDeviceRef dev, CFStringRef property, int *value); +static bool HID_GetStrProperty(IOHIDDeviceRef dev, CFStringRef property, QString & value); + +/** + Initialize the USB monitor here + */ +USBMonitor::USBMonitor(QObject *parent) : QThread(parent) +{ + hid_manager = NULL; + IOReturn ret; + + m_instance = this; + + listMutex = new QMutex(); + knowndevices.clear(); + + hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + if (hid_manager == NULL || CFGetTypeID(hid_manager) != IOHIDManagerGetTypeID()) { + if (hid_manager) { + CFRelease(hid_manager); + } + Q_ASSERT(0); + } + + // No matching filter + IOHIDManagerSetDeviceMatching(hid_manager, NULL); + + // set up a callbacks for device attach & detach + IOHIDManagerScheduleWithRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, attach_callback, NULL); + IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, detach_callback, NULL); + ret = IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone); + if (ret != kIOReturnSuccess) { + IOHIDManagerUnscheduleFromRunLoop(hid_manager, + CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + CFRelease(hid_manager); + return; + } + + start(); +} + +USBMonitor::~USBMonitor() +{ + // if(hid_manager != NULL) + // IOHIDManagerUnscheduleFromRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + quit(); +} + +void USBMonitor::deviceEventReceived() +{ + qDebug() << "Device event"; +} + +USBMonitor *USBMonitor::instance() +{ + return m_instance; +} + +USBMonitor *USBMonitor::m_instance = 0; + + +void USBMonitor::removeDevice(IOHIDDeviceRef dev) +{ + for (int i = 0; i < knowndevices.length(); i++) { + USBPortInfo port = knowndevices.at(i); + if (port.dev_handle == dev) { + QMutexLocker locker(listMutex); + knowndevices.removeAt(i); + emit deviceRemoved(port); + return; + } + } +} + +/** + * @brief Static callback for the USB driver to indicate device removed + */ +void USBMonitor::detach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev) +{ + Q_UNUSED(context); + Q_UNUSED(r); + Q_UNUSED(hid_mgr); + + qDebug() << "USBMonitor: Device detached event"; + instance()->removeDevice(dev); +} + +void USBMonitor::addDevice(USBPortInfo info) +{ + QMutexLocker locker(listMutex); + + knowndevices.append(info); + emit deviceDiscovered(info); +} + +void USBMonitor::attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev) +{ + Q_UNUSED(context); + Q_UNUSED(r); + Q_UNUSED(hid_mgr); + + bool got_properties = true; + + USBPortInfo deviceInfo; + + deviceInfo.dev_handle = dev; + + qDebug() << "USBMonitor: Device attached event"; + + // Populate the device info structure + got_properties &= HID_GetIntProperty(dev, CFSTR(kIOHIDVendorIDKey), &deviceInfo.vendorID); + got_properties &= HID_GetIntProperty(dev, CFSTR(kIOHIDProductIDKey), &deviceInfo.productID); + got_properties &= HID_GetIntProperty(dev, CFSTR(kIOHIDVersionNumberKey), &deviceInfo.bcdDevice); + got_properties &= HID_GetStrProperty(dev, CFSTR(kIOHIDSerialNumberKey), deviceInfo.serialNumber); + got_properties &= HID_GetStrProperty(dev, CFSTR(kIOHIDProductKey), deviceInfo.product); + got_properties &= HID_GetStrProperty(dev, CFSTR(kIOHIDManufacturerKey), deviceInfo.manufacturer); + // TOOD: Eventually want to take array of usages if devices start needing that + got_properties &= HID_GetIntProperty(dev, CFSTR(kIOHIDPrimaryUsageKey), &deviceInfo.Usage); + got_properties &= HID_GetIntProperty(dev, CFSTR(kIOHIDPrimaryUsagePageKey), &deviceInfo.UsagePage); + + // Currently only enumerating objects that have the complete list of properties + if (got_properties) { + qDebug() << "USBMonitor: Adding device"; + instance()->addDevice(deviceInfo); + } +} + +/** + Returns a list of all currently available devices + */ +QList USBMonitor::availableDevices() +{ + // QMutexLocker locker(listMutex); + return knowndevices; +} + +/** + * @brief Be a bit more picky and ask only for a specific type of device: + * @param[in] vid VID to screen or -1 to ignore + * @param[in] pid PID to screen or -1 to ignore + * @param[in] bcdDeviceMSB MSB of bcdDevice to screen or -1 to ignore + * @param[in] bcdDeviceLSB LSB of bcdDevice to screen or -1 to ignore + * @return List of USBPortInfo that meet this criterion + * @note + * On OpenPilot, the bcdDeviceLSB indicates the run state: bootloader or running. + * bcdDeviceMSB indicates the board model. + */ +QList USBMonitor::availableDevices(int vid, int pid, int bcdDeviceMSB, int bcdDeviceLSB) +{ + QList allPorts = availableDevices(); + QList thePortsWeWant; + + foreach(USBPortInfo port, allPorts) { + if ((port.vendorID == vid || vid == -1) && (port.productID == pid || pid == -1) && ((port.bcdDevice >> 8) == bcdDeviceMSB || bcdDeviceMSB == -1) && + ((port.bcdDevice & 0x00ff) == bcdDeviceLSB || bcdDeviceLSB == -1)) { + thePortsWeWant.append(port); + } + } + + return thePortsWeWant; +} + +/** + * @brief Helper function get get a HID integer property + * @param[in] dev Device reference + * @param[in] property The property to get (constants defined in IOKIT) + * @param[out] value Pointer to integer to set + * @return True if successful, false otherwise + */ +static bool HID_GetIntProperty(IOHIDDeviceRef dev, CFStringRef property, int *value) +{ + CFTypeRef prop = IOHIDDeviceGetProperty(dev, property); + + if (prop) { + if (CFNumberGetTypeID() == CFGetTypeID(prop)) { // if a number + CFNumberGetValue((CFNumberRef)prop, kCFNumberSInt32Type, value); + return true; + } + } + return false; +} + +/** + * @brief Helper function get get a HID string property + * @param[in] dev Device reference + * @param[in] property The property to get (constants defined in IOKIT) + * @param[out] value The QString to set + * @return True if successful, false otherwise + */ +static bool HID_GetStrProperty(IOHIDDeviceRef dev, CFStringRef property, QString & value) +{ + CFTypeRef prop = IOHIDDeviceGetProperty(dev, property); + + if (prop) { + if (CFStringGetTypeID() == CFGetTypeID(prop)) { // if a string + char buffer[2550]; + bool success = CFStringGetCString((CFStringRef)prop, buffer, sizeof(buffer), kCFStringEncodingMacRoman); + value = QString(buffer); + return success; + } + } + return false; +} diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_win.cpp b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_win.cpp new file mode 100644 index 000000000..4492106c2 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_win.cpp @@ -0,0 +1,378 @@ +/** + ****************************************************************************** + * + * @file usbmonitor_win.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup opHIDPlugin HID Plugin + * @{ + * @brief Implements the USB monitor on Windows using system API + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include "opHID_usbmon.h" +#include +#include "opHID_const.h" + +#define printf qDebug + +void USBMonitor::deviceEventReceived() +{ + qDebug() << "Device event"; + // Dispatch and emit the signals here... +} + +USBMonitor *USBMonitor::instance() +{ + return m_instance; +} + +USBMonitor *USBMonitor::m_instance = 0; + + +USBMonitor::USBMonitor(QObject *parent) : QThread(parent) +{ + HidD_GetHidGuid(&guid_hid); + if (!QMetaType::isRegistered(QMetaType::type("USBPortInfo"))) { + qRegisterMetaType("USBPortInfo"); + } +#if (defined QT_GUI_LIB) + notificationWidget = 0; +#endif // Q_OS_WIN + setUpNotifications(); + m_instance = this; +} + +USBMonitor::~USBMonitor() +{ +#if (defined QT_GUI_LIB) + if (notificationWidget) { + delete notificationWidget; + } +#endif + quit(); +} + +/** + Be a bit more picky and ask only for a specific type of device: + On OpenPilot, the bcdDeviceLSB indicates the run state: bootloader or running. + bcdDeviceMSB indicates the board model. + */ +QList USBMonitor::availableDevices(int vid, int pid, int bcdDeviceMSB, int bcdDeviceLSB) +{ + QList allPorts = availableDevices(); + qDebug() << "USBMonitor::availableDevices list off all ports:"; + qDebug() << "USBMonitor::availableDevices total ports:" << allPorts.length(); + foreach(USBPortInfo info, allPorts) { + qDebug() << "----------"; + qDebug() << "bcdDevice:" << info.bcdDevice; + qDebug() << "devicePath:" << info.devicePath; + qDebug() << "product:" << info.product; + } + qDebug() << "END OF LIST"; + QList thePortsWeWant; + qDebug() << "USBMonitor::availableDevices bcdLSB=" << bcdDeviceLSB; + foreach(USBPortInfo port, allPorts) { + qDebug() << "USBMonitorWin:Port VID=" << port.vendorID << "PID=" << port.productID << "bcddevice=" << port.bcdDevice; + if ((port.vendorID == vid || vid == -1) && (port.productID == pid || pid == -1) && ((port.bcdDevice >> 8) == bcdDeviceMSB || bcdDeviceMSB == -1) && + ((port.bcdDevice & 0x00ff) == bcdDeviceLSB || bcdDeviceLSB == -1)) { + thePortsWeWant.append(port); + } + } + qDebug() << "USBMonitor::availableDevices list off matching ports vid pid bcdMSD bcdLSD:" << vid << pid << bcdDeviceMSB << bcdDeviceLSB; + qDebug() << "USBMonitor::availableDevices total matching ports:" << thePortsWeWant.length(); + foreach(USBPortInfo info, thePortsWeWant) { + qDebug() << "----------"; + qDebug() << "bcdDevice:" << info.bcdDevice; + qDebug() << "devicePath:" << info.devicePath; + qDebug() << "product:" << info.product; + } + qDebug() << "END OF LIST"; + return thePortsWeWant; +} + + +// see http://msdn.microsoft.com/en-us/library/ms791134.aspx for list of GUID classes +/*#ifndef GUID_DEVCLASS_PORTS + DEFINE_GUID(GUID_DEVCLASS_PORTS, //0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30); + //0x745a17a0, 0x74d3, 0x11d0, 0xb6, 0xfe, 0x00, 0xa0, 0xc9, 0x0f, 0x57, 0xda); + 0xA5DCBF10, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED); + #endif + */ +/* Gordon Schumacher's macros for TCHAR -> QString conversions and vice versa */ +#ifdef UNICODE +#define QStringToTCHAR(x) (wchar_t *)x.utf16() +#define PQStringToTCHAR(x) (wchar_t *)x->utf16() +#define TCHARToQString(x) QString::fromUtf16((ushort *)(x)) +#define TCHARToQStringN(x, y) QString::fromUtf16((ushort *)(x), (y)) +#else +#define QStringToTCHAR(x) x.local8Bit().constData() +#define PQStringToTCHAR(x) x->local8Bit().constData() +#define TCHARToQString(x) QString::fromLocal8Bit((x)) +#define TCHARToQStringN(x, y) QString::fromLocal8Bit((x), (y)) +#endif /*UNICODE*/ + +void USBMonitor::setUpNotifications() +{ +#ifdef QT_GUI_LIB + if (notificationWidget) { + return; + } + notificationWidget = new USBRegistrationWidget(this); + + DEV_BROADCAST_DEVICEINTERFACE dbh; + ZeroMemory(&dbh, sizeof(dbh)); + dbh.dbcc_size = sizeof(dbh); + dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + CopyMemory(&dbh.dbcc_classguid, &guid_hid, sizeof(GUID)); + if (RegisterDeviceNotification(notificationWidget->winId(), &dbh, DEVICE_NOTIFY_WINDOW_HANDLE) == NULL) { + qWarning() << "RegisterDeviceNotification failed:" << GetLastError(); + } + // setting up notifications doesn't tell us about devices already connected + // so get those manually + foreach(USBPortInfo port, availableDevices()) + emit deviceDiscovered(port); +#else + qWarning("GUI not enabled - can't register for device notifications."); +#endif // QT_GUI_LIB +} +LRESULT USBMonitor::onDeviceChangeWin(WPARAM wParam, LPARAM lParam) +{ + if (DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam) { + PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam; + if (pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) { + PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr; + // delimiters are different across APIs...change to backslash. ugh. + QString deviceID = TCHARToQString(pDevInf->dbcc_name).toUpper().replace("#", "\\"); + matchAndDispatchChangedDevice(deviceID, guid_hid, wParam); + } + } + return 0; +} +#ifdef QT_GUI_LIB +bool USBRegistrationWidget::winEvent(MSG *message, long *result) +{ + if (message->message == WM_DEVICECHANGE) { + qese->onDeviceChangeWin(message->wParam, message->lParam); + *result = 1; + return true; + } + return false; +} +#endif +bool USBMonitor::matchAndDispatchChangedDevice(const QString & deviceID, const GUID & guid, WPARAM wParam) +{ + qDebug() << "USB_MONITOR matchAndDispatchChangedDevice deviceID=" << deviceID; + bool rv = false; + DWORD dwFlag = (DBT_DEVICEARRIVAL == wParam) ? DIGCF_PRESENT : DIGCF_ALLCLASSES; + HDEVINFO devInfo; + if ((devInfo = SetupDiGetClassDevs(&guid, NULL, NULL, dwFlag | DIGCF_DEVICEINTERFACE)) != INVALID_HANDLE_VALUE) { + SP_DEVINFO_DATA spDevInfoData; + spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + for (DWORD i = 0; SetupDiEnumDeviceInfo(devInfo, i, &spDevInfoData); i++) { + DWORD nSize = 0; + TCHAR buf[MAX_PATH]; + if (SetupDiGetDeviceInstanceId(devInfo, &spDevInfoData, buf, MAX_PATH, &nSize) && + deviceID.contains(TCHARToQString(buf))) { // we found a match + USBPortInfo info; + info.devicePath = deviceID; + if (wParam == DBT_DEVICEARRIVAL) { + qDebug() << "USB_MONITOR INSERTION"; + if (infoFromHandle(guid, info, devInfo, i) != 1) { + qDebug() << "USB_MONITOR infoFromHandle failed on matchAndDispatchChangedDevice"; + break; + } + bool m_break = false; + foreach(USBPortInfo m_info, knowndevices) { + if (m_info.serialNumber == info.serialNumber && m_info.productID == info.productID && m_info.bcdDevice == info.bcdDevice && m_info.devicePath == info.devicePath) { + qDebug() << "USB_MONITOR device already present don't emit signal"; + m_break = true; + } + } + if (m_break) { + break; + } + if (info.bcdDevice == 0 || info.product.isEmpty()) { + qDebug() << "USB_MONITOR empty information on device not emiting signal"; + break; + } + knowndevices.append(info); + qDebug() << "USB_MONITOR emit device discovered on device:" << info.product << info.bcdDevice; + emit deviceDiscovered(info); + break; + } else if (wParam == DBT_DEVICEREMOVECOMPLETE) { + bool found = false; + for (int x = 0; x < knowndevices.count(); ++x) { + if (knowndevices[x].devicePath == deviceID) { + USBPortInfo temp = knowndevices.at(x); + knowndevices.removeAt(x); + qDebug() << "USB_MONITOR emit device removed on device:" << temp.product << temp.bcdDevice; + emit deviceRemoved(temp); + found = true; + break; + } + } + if (!found) { + qDebug() << "USB_MONITOR emit device removed on unknown device"; + emit deviceRemoved(info); + } + } + break; + } + } + SetupDiDestroyDeviceInfoList(devInfo); + } + return rv; +} + +QString USBMonitor::getDeviceProperty(HDEVINFO devInfo, PSP_DEVINFO_DATA devData, DWORD property) +{ + DWORD buffSize = 0; + + SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, NULL, 0, &buffSize); + BYTE *buff = new BYTE[buffSize]; + SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, buff, buffSize, NULL); + QString result = TCHARToQString(buff); + delete[] buff; + return result; +} +/** + Returns a list of all currently available devices + */ +QList USBMonitor::availableDevices() +{ + QList ports; + enumerateDevicesWin(guid_hid, &ports); + // qDebug()<<"USBMonitorWin availabledevices="< *infoList) +{ + HDEVINFO devInfo; + USBPortInfo info; + + // qDebug()<<"enumerateDevicesWin1"; + if ((devInfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)) != INVALID_HANDLE_VALUE) { + // qDebug()<<"enumerateDevicesWin2"; + SP_DEVINFO_DATA devInfoData; + devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + for (DWORD i = 0; SetupDiEnumDeviceInfo(devInfo, i, &devInfoData); i++) { + int r = infoFromHandle(guid, info, devInfo, i); + if (r == 1) { + infoList->append(info); + } else if (r == 0) { + break; + } + } + + SetupDiDestroyDeviceInfoList(devInfo); + } +} + +int USBMonitor::infoFromHandle(const GUID & guid, USBPortInfo & info, HDEVINFO & devInfo, DWORD & index) +{ + // qDebug()<<"index0="<DevicePath); + + free(details); + return 2; + } + // qDebug()<<"index4="<DevicePath).toUpper().replace("#", "\\"); + attrib.Size = sizeof(HIDD_ATTRIBUTES); + ret = HidD_GetAttributes(h, &attrib); + info.vendorID = attrib.VendorID; + info.productID = attrib.ProductID; + info.bcdDevice = attrib.VersionNumber; + + + if (!ret || !HidD_GetPreparsedData(h, &hid_data)) { + CloseHandle(h); + return 2; + } + // qDebug()<<"index5="< + + +/** +* \brief trigger device discovered signal +* +* \note +* +* \param[in] port. +*/ +void USBSignalFilter::m_deviceDiscovered(USBPortInfo port) +{ + if((port.vendorID==m_vid || m_vid==-1) && + (port.productID==m_pid || m_pid==-1) && + ((port.bcdDevice>>8)==m_boardModel || m_boardModel==-1) && + ((port.bcdDevice&0x00ff) ==m_runState || m_runState==-1)) + { + qDebug()<<"USBSignalFilter emit device discovered"; + emit deviceDiscovered(); + } +} + + +/** +* \brief Constructor +* +* \note +* +* \param[in] vid USB vendor id of the device to open (-1 for any). +* \param[in] pid USB product id of the device to open (-1 for any). +* \param[in] boardModel. +* \param[in] runState. +*/ +USBSignalFilter::USBSignalFilter(int vid, int pid, int boardModel, int runState): + m_vid(vid), + m_pid(pid), + m_boardModel(boardModel), + m_runState(runState) +{ + connect(USBMonitor::instance(), + SIGNAL(deviceDiscovered(USBPortInfo)), + this, + SLOT(m_deviceDiscovered(USBPortInfo))); +} + + diff --git a/ground/openpilotgcs/src/plugins/plugins.pro b/ground/openpilotgcs/src/plugins/plugins.pro index c8591071f..f397a67d6 100644 --- a/ground/openpilotgcs/src/plugins/plugins.pro +++ b/ground/openpilotgcs/src/plugins/plugins.pro @@ -28,10 +28,10 @@ plugin_welcome.subdir = welcome plugin_welcome.depends = plugin_coreplugin SUBDIRS += plugin_welcome -# RawHID connection plugin -SUBDIRS += plugin_rawhid -plugin_rawhid.subdir = rawhid -plugin_rawhid.depends = plugin_coreplugin +# opHID connection plugin +SUBDIRS += plugin_opHID +plugin_opHID.subdir = opHID +plugin_opHID.depends = plugin_coreplugin # Serial port connection plugin SUBDIRS += plugin_serial @@ -93,7 +93,7 @@ plugin_uploader.subdir = uploader plugin_uploader.depends = plugin_coreplugin plugin_uploader.depends += plugin_uavobjects plugin_uploader.depends += plugin_uavtalk -plugin_uploader.depends += plugin_rawhid +plugin_uploader.depends += plugin_opHID plugin_uploader.depends += plugin_uavobjectutil SUBDIRS += plugin_uploader diff --git a/ground/openpilotgcs/src/plugins/powerlog/PowerLog.pluginspec b/ground/openpilotgcs/src/plugins/powerlog/PowerLog.pluginspec index fab57c77a..24ac39811 100644 --- a/ground/openpilotgcs/src/plugins/powerlog/PowerLog.pluginspec +++ b/ground/openpilotgcs/src/plugins/powerlog/PowerLog.pluginspec @@ -6,6 +6,6 @@ http://www.openpilot.org - + diff --git a/ground/openpilotgcs/src/plugins/powerlog/powerlog_dependencies.pri b/ground/openpilotgcs/src/plugins/powerlog/powerlog_dependencies.pri index 7418c99b1..f77ee6b96 100644 --- a/ground/openpilotgcs/src/plugins/powerlog/powerlog_dependencies.pri +++ b/ground/openpilotgcs/src/plugins/powerlog/powerlog_dependencies.pri @@ -1,2 +1,2 @@ include(../../plugins/coreplugin/coreplugin.pri) -include(../../plugins/rawhid/rawhid.pri) +include(../../plugins/rawhid/opHID.pri) diff --git a/ground/openpilotgcs/src/plugins/powerlog/powerlogplugin.cpp b/ground/openpilotgcs/src/plugins/powerlog/powerlogplugin.cpp index da2080638..5f0b9c820 100644 --- a/ground/openpilotgcs/src/plugins/powerlog/powerlogplugin.cpp +++ b/ground/openpilotgcs/src/plugins/powerlog/powerlogplugin.cpp @@ -69,7 +69,7 @@ void PowerlogThread::run() // TODO: pop up a dialog here! qDebug() << "Connect a Junsi PowerLog 6S and watch the logging output"; - pjrc_rawhid hidHandle; + opHID_hidapi hidHandle; int numDevices = hidHandle.open(1, 0x0483, 0x5750, 0, 0); // 0xff9c,0x0001); if (numDevices == 0) { numDevices = hidHandle.open(1, 0x0483, 0, 0, 0); diff --git a/ground/openpilotgcs/src/plugins/powerlog/powerlogplugin.h b/ground/openpilotgcs/src/plugins/powerlog/powerlogplugin.h index 517f950de..70054cfab 100644 --- a/ground/openpilotgcs/src/plugins/powerlog/powerlogplugin.h +++ b/ground/openpilotgcs/src/plugins/powerlog/powerlogplugin.h @@ -32,8 +32,8 @@ #include #include #include -#include "rawhid/usbmonitor.h" -#include "rawhid/pjrc_rawhid.h" +#include "opHID/inc/opHID_usbmon.h" +#include "opHID/inc/opHID_hidapi.h" #include #include diff --git a/ground/openpilotgcs/src/plugins/uploader/Uploader.pluginspec b/ground/openpilotgcs/src/plugins/uploader/Uploader.pluginspec index 76bbf550e..fd42037a5 100644 --- a/ground/openpilotgcs/src/plugins/uploader/Uploader.pluginspec +++ b/ground/openpilotgcs/src/plugins/uploader/Uploader.pluginspec @@ -8,7 +8,7 @@ - + diff --git a/ground/openpilotgcs/src/plugins/uploader/op_dfu.h b/ground/openpilotgcs/src/plugins/uploader/op_dfu.h index 8805fe477..c7b315235 100644 --- a/ground/openpilotgcs/src/plugins/uploader/op_dfu.h +++ b/ground/openpilotgcs/src/plugins/uploader/op_dfu.h @@ -2,9 +2,9 @@ #define OP_DFU_H #include -#include -#include -#include +#include +#include +#include #include #include #include @@ -181,7 +181,7 @@ private: // USB Bootloader: - pjrc_rawhid hidHandle; + opHID_hidapi hidHandle; int setStartBit(int command) { return command | 0x20; diff --git a/ground/openpilotgcs/src/plugins/uploader/uploader_dependencies.pri b/ground/openpilotgcs/src/plugins/uploader/uploader_dependencies.pri index b85fc46a1..d8d4a18eb 100644 --- a/ground/openpilotgcs/src/plugins/uploader/uploader_dependencies.pri +++ b/ground/openpilotgcs/src/plugins/uploader/uploader_dependencies.pri @@ -2,5 +2,5 @@ include(../../openpilotgcsplugin.pri) include(../../plugins/coreplugin/coreplugin.pri) include(../../plugins/uavobjects/uavobjects.pri) include(../../plugins/uavtalk/uavtalk.pri) -include(../../plugins/rawhid/rawhid.pri) +include(../../plugins/opHID/opHID.pri) include(../../plugins/uavobjectutil/uavobjectutil.pri) diff --git a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h index 5a3032230..d3a1d7527 100644 --- a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h +++ b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h @@ -45,7 +45,7 @@ #include "coreplugin/icore.h" #include "coreplugin/connectionmanager.h" -#include "rawhid/rawhidplugin.h" +#include "opHID/inc/opHID_plugin.h" #include #include #include From 6e909f0dcf880aaff05ba401f8aaf48efc1f0e38 Mon Sep 17 00:00:00 2001 From: Mathieu Rondonneau Date: Mon, 20 May 2013 02:46:45 -0700 Subject: [PATCH 002/120] OP-958: HID plugin basic cleanup: - minor forgotten cleanup. --- .../src/plugins/opHID/src/opHID_hidapi.cpp | 61 ++++++++----------- 1 file changed, 24 insertions(+), 37 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_hidapi.cpp b/ground/openpilotgcs/src/plugins/opHID/src/opHID_hidapi.cpp index c1cc64c9c..367a93c99 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID_hidapi.cpp +++ b/ground/openpilotgcs/src/plugins/opHID/src/opHID_hidapi.cpp @@ -68,10 +68,17 @@ opHID_hidapi::~opHID_hidapi() } -// Function: enumerate the HID devices connected. -// Return: -// - a pointer to a list of HID devices found -// - number of HID devices found +/** +* \brief Enumerate the list of HID device with our vendor id +* +* \note Why don't we use the one from within the hidapi directly +* in caller? because later we will do more parsing herer. +* WARNING: our vendor id is harcoded here (not good idea). +* +* \param[out] devices_found Number of devices found. +* \return error. +* \retval 0 on success. +*/ int opHID_hidapi::enumerate(int *devices_found) { *devices_found = 0; @@ -128,13 +135,15 @@ int opHID_hidapi::open(int max, int vid, int pid, int usage_page, int usage) OPHID_WARNING("WARNING: device seems already open."); } - // if caller knows which one to look for open it - if (vid != -1 && pid != -1) + // This is a hack to prevent changing all the callers (for now) + if (vid == -1) + vid = 0; + if (pid == -1) + pid = 0; + + // If caller knows which one to look for open it right away + if (vid != 0 && pid != 0) { - if (pid == -1) - pid = 0; - if (vid == -1) - vid = 0; hidapi_device.handle = hid_open(vid, pid, NULL); if (!hidapi_device.handle) @@ -158,47 +167,25 @@ int opHID_hidapi::open(int max, int vid, int pid, int usage_page, int usage) return 0; } - // Look for the first one of interest if (devices_found) { -// devices_found = false; + // Look for the first one of interest for now current_device_ptr = hidapi_device.list_ptr; -#if 0 - // Currently assuming the last one is the right one - // This won't be necessary true later (TODO) - while (current_device_ptr) - { - // - if (current_device_ptr->vendor_id == vid) - { - devices_found = true; - break; - } - current_device_ptr = current_device_ptr->next; - } -#endif - } - if (devices_found) - { OPHID_DEBUG("Opening device VID(%04hx).PID(%04hx)", current_device_ptr->vendor_id, current_device_ptr->product_id); - vid = current_device_ptr->vendor_id; - pid = current_device_ptr->product_id; - - if (hidapi_device.list_ptr) - hid_free_enumeration(hidapi_device.list_ptr); - - hidapi_device.handle = hid_open(vid /*current_device_ptr->vendor_id*/, - pid /*current_device_ptr->product_id*/, + hidapi_device.handle = hid_open(current_device_ptr->vendor_id, + current_device_ptr->product_id, NULL); if (!hidapi_device.handle) { OPHID_ERROR("Unable to open device."); devices_found = false; } + + hid_free_enumeration(hidapi_device.list_ptr); } } From 8e7e7e052a3bd39b29ff81acc524b08c54776eaf Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Tue, 21 May 2013 00:45:45 +0200 Subject: [PATCH 003/120] OP-962 Fix Stack size for ComUSBBridge +review OPReview --- flight/modules/ComUsbBridge/ComUsbBridge.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/flight/modules/ComUsbBridge/ComUsbBridge.c b/flight/modules/ComUsbBridge/ComUsbBridge.c index 09425e008..c7674ec00 100644 --- a/flight/modules/ComUsbBridge/ComUsbBridge.c +++ b/flight/modules/ComUsbBridge/ComUsbBridge.c @@ -47,7 +47,9 @@ static void updateSettings(); // **************** // Private constants -#define STACK_SIZE_BYTES 280 +#define U2C_STACK_SIZE_BYTES 260 +#define C2U_STACK_SIZE_BYTES 315 + #define TASK_PRIORITY (tskIDLE_PRIORITY + 1) #define BRIDGE_BUF_LEN 10 @@ -76,9 +78,9 @@ static int32_t comUsbBridgeStart(void) { if (bridge_enabled) { // Start tasks - xTaskCreate(com2UsbBridgeTask, (signed char *)"Com2UsbBridge", STACK_SIZE_BYTES / 4, NULL, TASK_PRIORITY, &com2UsbBridgeTaskHandle); + xTaskCreate(com2UsbBridgeTask, (signed char *)"Com2UsbBridge", C2U_STACK_SIZE_BYTES / 4, NULL, TASK_PRIORITY, &com2UsbBridgeTaskHandle); PIOS_TASK_MONITOR_RegisterTask(TASKINFO_RUNNING_COM2USBBRIDGE, com2UsbBridgeTaskHandle); - xTaskCreate(usb2ComBridgeTask, (signed char *)"Usb2ComBridge", STACK_SIZE_BYTES / 4, NULL, TASK_PRIORITY, &usb2ComBridgeTaskHandle); + xTaskCreate(usb2ComBridgeTask, (signed char *)"Usb2ComBridge", U2C_STACK_SIZE_BYTES / 4, NULL, TASK_PRIORITY, &usb2ComBridgeTaskHandle); PIOS_TASK_MONITOR_RegisterTask(TASKINFO_RUNNING_USB2COMBRIDGE, usb2ComBridgeTaskHandle); return 0; } From 81e10c9d1b65038ecf593dfd2368a087cb5a1b87 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Tue, 21 May 2013 00:15:18 +0200 Subject: [PATCH 004/120] OP-960 Prevent a warning to appear each time an alarm not in svg is received +review OPReview --- .../systemhealth/systemhealthgadgetwidget.cpp | 46 +++++++++++-------- .../systemhealth/systemhealthgadgetwidget.h | 2 +- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/systemhealth/systemhealthgadgetwidget.cpp b/ground/openpilotgcs/src/plugins/systemhealth/systemhealthgadgetwidget.cpp index 38f62569d..a1e4c8908 100644 --- a/ground/openpilotgcs/src/plugins/systemhealth/systemhealthgadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/systemhealth/systemhealthgadgetwidget.cpp @@ -48,7 +48,7 @@ SystemHealthGadgetWidget::SystemHealthGadgetWidget(QWidget *parent) : QGraphicsV background = new QGraphicsSvgItem(); foreground = new QGraphicsSvgItem(); nolink = new QGraphicsSvgItem(); - + missingElements = new QStringList(); paint(); // Now connect the widget to the SystemAlarms UAVObject @@ -100,26 +100,32 @@ void SystemHealthGadgetWidget::updateAlarms(UAVObject *systemAlarm) for (uint i = 0; i < field->getNumElements(); ++i) { QString element = field->getElementNames()[i]; QString value = field->getValue(i).toString(); - if (m_renderer->elementExists(element)) { - QMatrix blockMatrix = m_renderer->matrixForElement(element); - qreal startX = blockMatrix.mapRect(m_renderer->boundsOnElement(element)).x(); - qreal startY = blockMatrix.mapRect(m_renderer->boundsOnElement(element)).y(); - QString element2 = element + "-" + value; - if (m_renderer->elementExists(element2)) { - QGraphicsSvgItem *ind = new QGraphicsSvgItem(); - ind->setSharedRenderer(m_renderer); - ind->setElementId(element2); - ind->setParentItem(background); - QTransform matrix; - matrix.translate(startX, startY); - ind->setTransform(matrix, false); - } else { - if (value.compare("Uninitialised") != 0) { - qDebug() << "Warning: element " << element2 << " not found in SVG."; + if (!missingElements->contains(element)){ + if (m_renderer->elementExists(element)) { + QMatrix blockMatrix = m_renderer->matrixForElement(element); + qreal startX = blockMatrix.mapRect(m_renderer->boundsOnElement(element)).x(); + qreal startY = blockMatrix.mapRect(m_renderer->boundsOnElement(element)).y(); + QString element2 = element + "-" + value; + if (!missingElements->contains(element2)) { + if (m_renderer->elementExists(element2)) { + QGraphicsSvgItem *ind = new QGraphicsSvgItem(); + ind->setSharedRenderer(m_renderer); + ind->setElementId(element2); + ind->setParentItem(background); + QTransform matrix; + matrix.translate(startX, startY); + ind->setTransform(matrix, false); + } else { + if (value.compare("Uninitialised") != 0) { + missingElements->append(element2); + qDebug() << "Warning: element " << element2 << " not found in SVG."; + } + } } + } else { + missingElements->append(element); + qDebug() << "Warning: Element " << element << " not found in SVG."; } - } else { - qDebug() << "Warning: Element " << element << " not found in SVG."; } } } @@ -133,6 +139,8 @@ SystemHealthGadgetWidget::~SystemHealthGadgetWidget() void SystemHealthGadgetWidget::setSystemFile(QString dfn) { + // Clear the list of elements not found on svg + missingElements->clear(); setBackgroundBrush(QBrush(Utils::StyleHelper::baseColor())); if (QFile::exists(dfn)) { m_renderer->load(dfn); diff --git a/ground/openpilotgcs/src/plugins/systemhealth/systemhealthgadgetwidget.h b/ground/openpilotgcs/src/plugins/systemhealth/systemhealthgadgetwidget.h index a76c58e1a..c48526382 100644 --- a/ground/openpilotgcs/src/plugins/systemhealth/systemhealthgadgetwidget.h +++ b/ground/openpilotgcs/src/plugins/systemhealth/systemhealthgadgetwidget.h @@ -64,7 +64,7 @@ private: QGraphicsSvgItem *background; QGraphicsSvgItem *foreground; QGraphicsSvgItem *nolink; - + QStringList *missingElements; // Simple flag to skip rendering if the bool fgenabled; // layer does not exist. From d4a4588011ce726f176743f3eb1fab9c83085a5e Mon Sep 17 00:00:00 2001 From: Brian Webb Date: Mon, 20 May 2013 18:21:07 -0700 Subject: [PATCH 005/120] OP-932 Changes the RFM22 frequency hopping to change channels every Tx period. Also increases the Tx clock period from 8ms to 16ms, and adds a check on calculation the the time delta that it doesn't change the previous estimated time delta by too much. If the delta between the current time delta and the previously estimated time delta is too large it could indicate that there was a delay somewhere that makes the calculated time delta inaccurate. Rearanges the packet send priority in the rfm22b driver so that PPM packets are top priority. --- flight/pios/common/pios_rfm22b.c | 147 ++++++++++++++++------------- flight/pios/inc/pios_rfm22b_priv.h | 2 + 2 files changed, 81 insertions(+), 68 deletions(-) diff --git a/flight/pios/common/pios_rfm22b.c b/flight/pios/common/pios_rfm22b.c index 8282ce9d7..a4c447fa8 100644 --- a/flight/pios/common/pios_rfm22b.c +++ b/flight/pios/common/pios_rfm22b.c @@ -85,7 +85,7 @@ #define MAX_RADIOSTATS_MISS_COUNT 3 // The time between PPM updates -#define PPM_UPDATE_PERIOD_MS 20 +#define PPM_UPDATE_PERIOD_MS 30 // this is too adjust the RF module so that it is on frequency #define OSC_LOAD_CAP 0x7F // cap = 12.5pf .. default @@ -1375,6 +1375,8 @@ static enum pios_radio_event rfm22_init(struct pios_rfm22b_dev *rfm22b_dev) rfm22b_dev->destination_id = 0xffffffff; rfm22b_dev->send_status = false; rfm22b_dev->send_connection_request = false; + rfm22b_dev->send_ack_nack = false; + rfm22b_dev->resend_packet = false; // Initialize the packets. rfm22b_dev->rx_packet_len = 0; @@ -1801,54 +1803,63 @@ static enum pios_radio_event radio_txStart(struct pios_rfm22b_dev *radio_dev) return RADIO_EVENT_RX_MODE; } - // See if there's a packet ready to send. - if (radio_dev->tx_packet) { - p = radio_dev->tx_packet; - } else { - // Don't send a packet if we're waiting for an ACK - if (radio_dev->prev_tx_packet) { - return RADIO_EVENT_RX_MODE; - } - - // Send a connection request? - if (!p && radio_dev->send_connection_request) { - p = (PHPacketHandle) & (radio_dev->con_packet); - radio_dev->send_connection_request = false; - } - #ifdef PIOS_PPM_RECEIVER - // Send a PPM packet? - if (!p && radio_dev->send_ppm) { - p = (PHPacketHandle) & (radio_dev->ppm_packet); - radio_dev->send_ppm = false; - } + // Send a PPM packet? + if (radio_dev->send_ppm) { + p = (PHPacketHandle) & (radio_dev->ppm_packet); + radio_dev->send_ppm = false; + } #endif - // Send status? - if (!p && radio_dev->send_status) { - p = (PHPacketHandle) & (radio_dev->status_packet); - radio_dev->send_status = false; + // Send an ACK/NACK? + if (!p && radio_dev->send_ack_nack) { + p = (PHPacketHandle) & (radio_dev->ack_nack_packet); + radio_dev->send_ack_nack = false; + } + + // Resend a packet? + if (!p && radio_dev->resend_packet) { + p = radio_dev->prev_tx_packet; + radio_dev->prev_tx_packet = NULL; + radio_dev->resend_packet = false; + } + + // Don't send another packet if we're waiting for an ACK. + if (!p && radio_dev->prev_tx_packet) { + return RADIO_EVENT_RX_MODE; + } + + // Send a connection request? + if (!p && radio_dev->send_connection_request) { + p = (PHPacketHandle) & (radio_dev->con_packet); + radio_dev->send_connection_request = false; + } + + // Try to get some data to send + if (!p) { + bool need_yield = false; + p = &radio_dev->data_packet; + p->header.type = PACKET_TYPE_DATA; + p->header.destination_id = radio_dev->destination_id; + if (radio_dev->tx_out_cb && (p->header.data_size == 0)) { + p->header.data_size = (radio_dev->tx_out_cb)(radio_dev->tx_out_context, p->data, PH_MAX_DATA, NULL, &need_yield); } - // Try to get some data to send - if (!p) { - bool need_yield = false; - p = &radio_dev->data_packet; - p->header.type = PACKET_TYPE_DATA; - p->header.destination_id = radio_dev->destination_id; - if (radio_dev->tx_out_cb && (p->header.data_size == 0)) { - p->header.data_size = (radio_dev->tx_out_cb)(radio_dev->tx_out_context, p->data, PH_MAX_DATA, NULL, &need_yield); - } - - // Don't send any data until we're connected. - if (!rfm22_isConnected(radio_dev)) { - p->header.data_size = 0; - } - if (p->header.data_size == 0) { - p = NULL; - } + // Don't send any data until we're connected. + if (!rfm22_isConnected(radio_dev)) { + p->header.data_size = 0; + } + if (p->header.data_size == 0) { + p = NULL; } } + + // Send status? + if (!p && radio_dev->send_status) { + p = (PHPacketHandle) & (radio_dev->status_packet); + radio_dev->send_status = false; + } + if (!p) { return RADIO_EVENT_RX_MODE; } @@ -1902,9 +1913,10 @@ static enum pios_radio_event radio_txData(struct pios_rfm22b_dev *radio_dev) if (radio_dev->rx_packet.header.type == PACKET_TYPE_CON_REQUEST) { rfm22_setConnectionParameters(radio_dev); } - } else if ((radio_dev->tx_packet->header.type != PACKET_TYPE_NACK) && (radio_dev->tx_packet->header.type != PACKET_TYPE_PPM) && - (radio_dev->tx_packet->header.type != PACKET_TYPE_STATUS) && (radio_dev->tx_packet->header.type != PACKET_TYPE_PPM)) { - // We need to wait for an ACK if this packet it not an ACK, NACK, or PPM. + } else if ((radio_dev->tx_packet->header.type != PACKET_TYPE_NACK) && + (radio_dev->tx_packet->header.type != PACKET_TYPE_PPM) && + (radio_dev->tx_packet->header.type != PACKET_TYPE_STATUS)) { + // We need to wait for an ACK if this packet it not an ACK, NACK, PPM, or status packet. radio_dev->prev_tx_packet = radio_dev->tx_packet; } radio_dev->tx_packet = 0; @@ -2058,7 +2070,11 @@ static enum pios_radio_event radio_receivePacket(struct pios_rfm22b_dev *radio_d if (seq_num == (prev_seq_num + 1)) { portTickType local_rx_time = radio_dev->rx_complete_ticks; portTickType remote_tx_time = radio_dev->rx_packet.header.prev_tx_time; - radio_dev->time_delta = remote_tx_time - local_rx_time; + portTickType time_delta = remote_tx_time - local_rx_time; + portTickType time_delta_delta = (time_delta > radio_dev->time_delta) ? (time_delta - radio_dev->time_delta) : (radio_dev->time_delta - time_delta); + if (time_delta_delta <= 2) { + radio_dev->time_delta = remote_tx_time - local_rx_time; + } } else if (seq_num > prev_seq_num) { // Add any missed packets into the stats. uint16_t missed_packets = seq_num - prev_seq_num - 1; @@ -2130,8 +2146,8 @@ static enum pios_radio_event radio_rxData(struct pios_rfm22b_dev *radio_dev) */ static void rfm22_sendStatus(struct pios_rfm22b_dev *rfm22b_dev) { - // Don't send if a status is already queued. - if (rfm22b_dev->send_status) { + // Don't send if a status is already queued or if we're the coordinator and not connected. + if (rfm22b_dev->send_status || (rfm22b_dev->coordinator && !rfm22_isConnected(rfm22b_dev))) { return; } @@ -2205,7 +2221,7 @@ static enum pios_radio_event rfm22_sendAck(struct pios_rfm22b_dev *rfm22b_dev) aph->header.destination_id = rfm22b_dev->destination_id; aph->header.type = PACKET_TYPE_ACK; aph->header.data_size = PH_ACK_NACK_DATA_SIZE(aph); - rfm22b_dev->tx_packet = (PHPacketHandle)aph; + rfm22b_dev->send_ack_nack = true; } return RADIO_EVENT_TX_START; } @@ -2220,10 +2236,13 @@ static enum pios_radio_event rfm22_sendNack(struct pios_rfm22b_dev *rfm22b_dev) { PHAckNackPacketHandle aph = (PHAckNackPacketHandle)(&(rfm22b_dev->ack_nack_packet)); - aph->header.destination_id = rfm22b_dev->destination_id; - aph->header.type = PACKET_TYPE_NACK; - aph->header.data_size = PH_ACK_NACK_DATA_SIZE(aph); - rfm22b_dev->tx_packet = (PHPacketHandle)aph; + // We don't NACK PPM or status packets. + if ((rfm22b_dev->rx_packet.header.type != PACKET_TYPE_PPM) && (rfm22b_dev->rx_packet.header.type != PACKET_TYPE_STATUS)) { + aph->header.destination_id = rfm22b_dev->destination_id; + aph->header.type = PACKET_TYPE_NACK; + aph->header.data_size = PH_ACK_NACK_DATA_SIZE(aph); + rfm22b_dev->send_ack_nack = true; + } return RADIO_EVENT_TX_START; } @@ -2462,9 +2481,6 @@ static void rfm22_setConnectionParameters(struct pios_rfm22b_dev *rfm22b_dev) */ static enum pios_radio_event rfm22_acceptConnection(struct pios_rfm22b_dev *rfm22b_dev) { - // Set our connection state to connected - rfm22b_dev->stats.link_state = OPLINKSTATUS_LINKSTATE_CONNECTED; - // Copy the connection packet PHConnectionPacketHandle cph = (PHConnectionPacketHandle)(&(rfm22b_dev->rx_packet)); PHConnectionPacketHandle lcph = (PHConnectionPacketHandle)(&(rfm22b_dev->con_packet)); @@ -2509,11 +2525,9 @@ static portTickType rfm22_coordinatorTime(struct pios_rfm22b_dev *rfm22b_dev, po static bool rfm22_timeToSend(struct pios_rfm22b_dev *rfm22b_dev) { portTickType time = rfm22_coordinatorTime(rfm22b_dev, xTaskGetTickCount()); - // Divide time into 8ms blocks. Coordinator sends in firs 2 ms, and remote send in 5th and 6th ms. - bool tts = (rfm22b_dev->coordinator) ? ((time & 0x06) == 0) : (((time + 4) & 0x06) == 0); - - // Noone starts a transmit just prior to a channel change. - return tts && ((time & 0x7e) < 0x7b); + // Divide time into 8ms blocks. Coordinator sends in first 2 ms, and remote send in 5th and 6th ms. + // Channel changes occur in the last 2 ms. + return (rfm22b_dev->coordinator) ? ((time & 0x0C) == 0) : (((time + 8) & 0x0C) == 0); } /** @@ -2524,13 +2538,10 @@ static bool rfm22_timeToSend(struct pios_rfm22b_dev *rfm22b_dev) static uint8_t rfm22_calcChannel(struct pios_rfm22b_dev *rfm22b_dev) { portTickType time = rfm22_coordinatorTime(rfm22b_dev, xTaskGetTickCount()); - // We change channels every 128 ms. - uint16_t n = (time >> 7) & 0xffff; - - // The channel is calculated using the 16 bit CRC as the pseudo random number generator. - n = PIOS_CRC16_updateByte(n, 0); - float num_channels = rfm22b_dev->num_channels; - return (uint8_t)(num_channels * (float)n / (float)0xffff); + // Divide time into 8ms blocks. Coordinator sends in first 2 ms, and remote send in 5th and 6th ms. + // Channel changes occur in the last 2 ms. + uint8_t n = (((time + 0x0C) >> 4) & 0xff); + return PIOS_CRC_updateByte(0, n) % rfm22b_dev->num_channels; } /** diff --git a/flight/pios/inc/pios_rfm22b_priv.h b/flight/pios/inc/pios_rfm22b_priv.h index 467ace794..8e274ef44 100644 --- a/flight/pios/inc/pios_rfm22b_priv.h +++ b/flight/pios/inc/pios_rfm22b_priv.h @@ -794,6 +794,8 @@ struct pios_rfm22b_dev { bool send_status; bool send_ppm; bool send_connection_request; + bool send_ack_nack; + bool resend_packet; // The initial frequency uint32_t init_frequency; From 2e3e5be0530828d43d071018b62b33da6737c4c7 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Tue, 21 May 2013 08:29:35 +0200 Subject: [PATCH 006/120] OP-960 Fixed spacing +review OPReview-481 --- .../src/plugins/systemhealth/systemhealthgadgetwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/systemhealth/systemhealthgadgetwidget.cpp b/ground/openpilotgcs/src/plugins/systemhealth/systemhealthgadgetwidget.cpp index a1e4c8908..52d6d1f80 100644 --- a/ground/openpilotgcs/src/plugins/systemhealth/systemhealthgadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/systemhealth/systemhealthgadgetwidget.cpp @@ -100,7 +100,7 @@ void SystemHealthGadgetWidget::updateAlarms(UAVObject *systemAlarm) for (uint i = 0; i < field->getNumElements(); ++i) { QString element = field->getElementNames()[i]; QString value = field->getValue(i).toString(); - if (!missingElements->contains(element)){ + if (!missingElements->contains(element)) { if (m_renderer->elementExists(element)) { QMatrix blockMatrix = m_renderer->matrixForElement(element); qreal startX = blockMatrix.mapRect(m_renderer->boundsOnElement(element)).x(); From 3b6ce9dbc3dfb2fb00e1d7d3c290cde9d83f4655 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Tue, 21 May 2013 15:16:56 +0200 Subject: [PATCH 007/120] OP-958 Fix compilation issues on Windows platform --- .../src/plugins/opHID/inc/opHID_hidapi.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h index c023a4866..04f3ea282 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -38,18 +37,6 @@ #include "opHID_const.h" #include "opHID_global.h" -typedef struct hid_struct hid_t; -struct hid_struct -{ - usb_dev_handle *usb; - int open; - int iface; - int ep_in; - int ep_out; - struct hid_struct *prev; - struct hid_struct *next; -}; - struct hidapi_wrapper_device { struct hid_device_info *list_ptr; From c3033ece11fddac3f71b19085a5e7244b0318ea2 Mon Sep 17 00:00:00 2001 From: Mathieu Rondonneau Date: Tue, 21 May 2013 09:00:50 -0700 Subject: [PATCH 008/120] OP-958: add usb.h include only for linux --- ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h index 04f3ea282..1c784de1c 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h @@ -33,6 +33,9 @@ #include #include #include +#if defined(Q_OS_UNIX) +#include +#endif #include "hidapi.h" #include "opHID_const.h" #include "opHID_global.h" From 464d2be9f77029155b37fe04053df0f406cd4212 Mon Sep 17 00:00:00 2001 From: a*morale Date: Tue, 21 May 2013 22:40:35 +0200 Subject: [PATCH 009/120] Port OP-754 to Revolution attitude estimation module --- flight/modules/Attitude/revolution/attitude.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/flight/modules/Attitude/revolution/attitude.c b/flight/modules/Attitude/revolution/attitude.c index bf8aa5d5b..30927fe53 100644 --- a/flight/modules/Attitude/revolution/attitude.c +++ b/flight/modules/Attitude/revolution/attitude.c @@ -113,7 +113,7 @@ const uint32_t SENSOR_QUEUE_SIZE = 10; static bool volatile variance_error = true; static bool volatile initialization_required = true; static uint32_t volatile running_algorithm = 0xffffffff; // we start with no algorithm running - +static float rollPitchBiasRate = 0; // Private functions static void AttitudeTask(void *parameters); @@ -367,18 +367,21 @@ static int32_t updateAttitudeComplementary(bool first_run) if ((init == 0 && xTaskGetTickCount() < 7000) && (xTaskGetTickCount() > 1000)) { // For first 7 seconds use accels to get gyro bias attitudeSettings.AccelKp = 1.0f; - attitudeSettings.AccelKi = 0.9f; + attitudeSettings.AccelKi = 0.0f; attitudeSettings.YawBiasRate = 0.23f; + rollPitchBiasRate = 0.01f; magKp = 1.0f; } else if ((attitudeSettings.ZeroDuringArming == ATTITUDESETTINGS_ZERODURINGARMING_TRUE) && (flightStatus.Armed == FLIGHTSTATUS_ARMED_ARMING)) { attitudeSettings.AccelKp = 1.0f; - attitudeSettings.AccelKi = 0.9f; + attitudeSettings.AccelKi = 0.0f; attitudeSettings.YawBiasRate = 0.23f; + rollPitchBiasRate = 0.01f; magKp = 1.0f; init = 0; } else if (init == 0) { // Reload settings (all the rates) AttitudeSettingsGet(&attitudeSettings); + rollPitchBiasRate = 0.0f; magKp = 0.01f; init = 1; } @@ -450,8 +453,8 @@ static int32_t updateAttitudeComplementary(bool first_run) // Accumulate integral of error. Scale here so that units are (deg/s) but Ki has units of s GyrosBiasData gyrosBias; GyrosBiasGet(&gyrosBias); - gyrosBias.x -= accel_err[0] * attitudeSettings.AccelKi; - gyrosBias.y -= accel_err[1] * attitudeSettings.AccelKi; + gyrosBias.x -= accel_err[0] * attitudeSettings.AccelKi + gyrosData.x * rollPitchBiasRate;; + gyrosBias.y -= accel_err[1] * attitudeSettings.AccelKi + gyrosData.y * rollPitchBiasRate; gyrosBias.z -= mag_err[2] * magKi; GyrosBiasSet(&gyrosBias); From 0b5a28f19ec526c066f50441108be31c5bf86cd9 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Tue, 21 May 2013 23:44:12 +0200 Subject: [PATCH 010/120] Port OP-754 to Revolution attitude estimation module: subtract GyroBIAS to work on raw value Added MagKp and MagKi to AttitudeSetting UAVO --- flight/modules/Attitude/revolution/attitude.c | 23 ++++++++++--------- .../uavobjectdefinition/attitudesettings.xml | 2 ++ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/flight/modules/Attitude/revolution/attitude.c b/flight/modules/Attitude/revolution/attitude.c index 30927fe53..bd64f85aa 100644 --- a/flight/modules/Attitude/revolution/attitude.c +++ b/flight/modules/Attitude/revolution/attitude.c @@ -289,8 +289,6 @@ float accel_mag; float qmag; float attitudeDt; float mag_err[3]; -float magKi = 0.000001f; -float magKp = 0.01f; static int32_t updateAttitudeComplementary(bool first_run) { @@ -370,19 +368,18 @@ static int32_t updateAttitudeComplementary(bool first_run) attitudeSettings.AccelKi = 0.0f; attitudeSettings.YawBiasRate = 0.23f; rollPitchBiasRate = 0.01f; - magKp = 1.0f; + attitudeSettings.MagKp = 1.0f; } else if ((attitudeSettings.ZeroDuringArming == ATTITUDESETTINGS_ZERODURINGARMING_TRUE) && (flightStatus.Armed == FLIGHTSTATUS_ARMED_ARMING)) { attitudeSettings.AccelKp = 1.0f; attitudeSettings.AccelKi = 0.0f; attitudeSettings.YawBiasRate = 0.23f; rollPitchBiasRate = 0.01f; - magKp = 1.0f; + attitudeSettings.MagKp = 1.0f; init = 0; } else if (init == 0) { // Reload settings (all the rates) AttitudeSettingsGet(&attitudeSettings); rollPitchBiasRate = 0.0f; - magKp = 0.01f; init = 1; } @@ -453,22 +450,26 @@ static int32_t updateAttitudeComplementary(bool first_run) // Accumulate integral of error. Scale here so that units are (deg/s) but Ki has units of s GyrosBiasData gyrosBias; GyrosBiasGet(&gyrosBias); - gyrosBias.x -= accel_err[0] * attitudeSettings.AccelKi + gyrosData.x * rollPitchBiasRate;; - gyrosBias.y -= accel_err[1] * attitudeSettings.AccelKi + gyrosData.y * rollPitchBiasRate; - gyrosBias.z -= mag_err[2] * magKi; - GyrosBiasSet(&gyrosBias); + if(revoCalibration.BiasCorrectedRaw == REVOCALIBRATION_BIASCORRECTEDRAW_TRUE) { + gyrosBias.x -= accel_err[0] * attitudeSettings.AccelKi + (gyrosData.x + gyrosBias.x) * rollPitchBiasRate;; + gyrosBias.y -= accel_err[1] * attitudeSettings.AccelKi + (gyrosData.y + gyrosBias.y) * rollPitchBiasRate; + } else { + gyrosBias.x -= accel_err[0] * attitudeSettings.AccelKi + gyrosData.x * rollPitchBiasRate;; + gyrosBias.y -= accel_err[1] * attitudeSettings.AccelKi + gyrosData.y * rollPitchBiasRate; - if (revoCalibration.BiasCorrectedRaw != REVOCALIBRATION_BIASCORRECTEDRAW_TRUE) { // if the raw values are not adjusted, we need to adjust here. gyrosData.x -= gyrosBias.x; gyrosData.y -= gyrosBias.y; gyrosData.z -= gyrosBias.z; } + gyrosBias.z -= mag_err[2] * attitudeSettings.MagKi; + GyrosBiasSet(&gyrosBias); + // Correct rates based on error, integral component dealt with in updateSensors gyrosData.x += accel_err[0] * attitudeSettings.AccelKp / dT; gyrosData.y += accel_err[1] * attitudeSettings.AccelKp / dT; - gyrosData.z += accel_err[2] * attitudeSettings.AccelKp / dT + mag_err[2] * magKp / dT; + gyrosData.z += accel_err[2] * attitudeSettings.AccelKp / dT + mag_err[2] * attitudeSettings.MagKp / dT; // Work out time derivative from INSAlgo writeup // Also accounts for the fact that gyros are in deg/s diff --git a/shared/uavobjectdefinition/attitudesettings.xml b/shared/uavobjectdefinition/attitudesettings.xml index 274a2ef30..56dac2f46 100644 --- a/shared/uavobjectdefinition/attitudesettings.xml +++ b/shared/uavobjectdefinition/attitudesettings.xml @@ -7,6 +7,8 @@ + + From 294a2955104fbd78a6407a74caa4e79c5e16ce00 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Wed, 22 May 2013 00:55:10 +0200 Subject: [PATCH 011/120] Port CF patch from Cyr that filters accel to reduce attitude drift due to vibrations --- flight/modules/Attitude/revolution/attitude.c | 64 ++++++++++++++++++- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/flight/modules/Attitude/revolution/attitude.c b/flight/modules/Attitude/revolution/attitude.c index bd64f85aa..e88fb5da0 100644 --- a/flight/modules/Attitude/revolution/attitude.c +++ b/flight/modules/Attitude/revolution/attitude.c @@ -114,6 +114,13 @@ static bool volatile variance_error = true; static bool volatile initialization_required = true; static uint32_t volatile running_algorithm = 0xffffffff; // we start with no algorithm running static float rollPitchBiasRate = 0; + +// Accel filtering +static float accel_alpha = 0; +static bool accel_filter_enabled = false; +static float accels_filtered[3]; +static float grot_filtered[3]; + // Private functions static void AttitudeTask(void *parameters); @@ -285,6 +292,19 @@ static void AttitudeTask(__attribute__((unused)) void *parameters) } } +static inline void apply_accel_filter(const float *raw, float *filtered) +{ + if (accel_filter_enabled) { + filtered[0] = filtered[0] * accel_alpha + raw[0] * (1 - accel_alpha); + filtered[1] = filtered[1] * accel_alpha + raw[1] * (1 - accel_alpha); + filtered[2] = filtered[2] * accel_alpha + raw[2] * (1 - accel_alpha); + } else { + filtered[0] = raw[0]; + filtered[1] = raw[1]; + filtered[2] = raw[2]; + } +} + float accel_mag; float qmag; float attitudeDt; @@ -367,12 +387,14 @@ static int32_t updateAttitudeComplementary(bool first_run) attitudeSettings.AccelKp = 1.0f; attitudeSettings.AccelKi = 0.0f; attitudeSettings.YawBiasRate = 0.23f; + accel_filter_enabled = false; rollPitchBiasRate = 0.01f; attitudeSettings.MagKp = 1.0f; } else if ((attitudeSettings.ZeroDuringArming == ATTITUDESETTINGS_ZERODURINGARMING_TRUE) && (flightStatus.Armed == FLIGHTSTATUS_ARMED_ARMING)) { attitudeSettings.AccelKp = 1.0f; attitudeSettings.AccelKi = 0.0f; attitudeSettings.YawBiasRate = 0.23f; + accel_filter_enabled = false; rollPitchBiasRate = 0.01f; attitudeSettings.MagKp = 1.0f; init = 0; @@ -380,6 +402,8 @@ static int32_t updateAttitudeComplementary(bool first_run) // Reload settings (all the rates) AttitudeSettingsGet(&attitudeSettings); rollPitchBiasRate = 0.0f; + if (accel_alpha > 0.0f) + accel_filter_enabled = true; init = 1; } @@ -400,19 +424,43 @@ static int32_t updateAttitudeComplementary(bool first_run) // Get the current attitude estimate quat_copy(&attitudeActual.q1, q); + // Apply smoothing to accel values, to reduce vibration noise before main calculations. + apply_accel_filter((const float *)&accelsData.x, accels_filtered); + // Rotate gravity to body frame and cross with accels grot[0] = -(2.0f * (q[1] * q[3] - q[0] * q[2])); grot[1] = -(2.0f * (q[2] * q[3] + q[0] * q[1])); grot[2] = -(q[0] * q[0] - q[1] * q[1] - q[2] * q[2] + q[3] * q[3]); - CrossProduct((const float *)&accelsData.x, (const float *)grot, accel_err); + + apply_accel_filter(grot, grot_filtered); + + CrossProduct((const float *)accels_filtered, (const float *)grot_filtered, accel_err); // Account for accel magnitude - accel_mag = accelsData.x * accelsData.x + accelsData.y * accelsData.y + accelsData.z * accelsData.z; + accel_mag = accels_filtered[0]*accels_filtered[0] + accels_filtered[1]*accels_filtered[1] + accels_filtered[2]*accels_filtered[2]; accel_mag = sqrtf(accel_mag); + + //TODO! check accel vector magnitude value for correctness + accel_err[0] /= accel_mag; accel_err[1] /= accel_mag; accel_err[2] /= accel_mag; + float grot_mag; + if (accel_filter_enabled) { + + grot_mag = sqrtf(grot_filtered[0] * grot_filtered[0] + grot_filtered[1] * grot_filtered[1] + grot_filtered[2] * grot_filtered[2]); + } else { + grot_mag = 1.0f; + } + + // TODO! check grot_mag value for correctness. + + accel_err[0] /= (accel_mag * grot_mag); + accel_err[1] /= (accel_mag * grot_mag); + accel_err[2] /= (accel_mag * grot_mag); + + if (xQueueReceive(magQueue, &ev, 0) != pdTRUE) { // Rotate gravity to body frame and cross with accels float brot[3]; @@ -451,7 +499,7 @@ static int32_t updateAttitudeComplementary(bool first_run) GyrosBiasData gyrosBias; GyrosBiasGet(&gyrosBias); if(revoCalibration.BiasCorrectedRaw == REVOCALIBRATION_BIASCORRECTEDRAW_TRUE) { - gyrosBias.x -= accel_err[0] * attitudeSettings.AccelKi + (gyrosData.x + gyrosBias.x) * rollPitchBiasRate;; + gyrosBias.x -= accel_err[0] * attitudeSettings.AccelKi + (gyrosData.x + gyrosBias.x) * rollPitchBiasRate; gyrosBias.y -= accel_err[1] * attitudeSettings.AccelKi + (gyrosData.y + gyrosBias.y) * rollPitchBiasRate; } else { gyrosBias.x -= accel_err[0] * attitudeSettings.AccelKi + gyrosData.x * rollPitchBiasRate;; @@ -1133,6 +1181,16 @@ static void settingsUpdatedCb(UAVObjEvent *ev) } if (ev == NULL || ev->obj == AttitudeSettingsHandle()) { AttitudeSettingsGet(&attitudeSettings); + + // Calculate accel filter alpha, in the same way as for gyro data in stabilization module. + const float fakeDt = 0.0025f; + if (attitudeSettings.AccelTau < 0.0001f) { + accel_alpha = 0; // not trusting this to resolve to 0 + accel_filter_enabled = false; + } else { + accel_alpha = expf(-fakeDt / attitudeSettings.AccelTau); + accel_filter_enabled = true; + } } } /** From dbce08a1514f1f99def2cf31554fdf7404668a46 Mon Sep 17 00:00:00 2001 From: Brian Webb Date: Tue, 21 May 2013 17:40:05 -0700 Subject: [PATCH 012/120] OP-932 Changes the radio task loop to loop every 1ms, and reduces the tx transmit period back down to 8ms. Also reduces the Tx windows to 1ms for each modem, and reserves the latter half of the Tx window for channel changing. --- flight/pios/common/pios_rfm22b.c | 33 +++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/flight/pios/common/pios_rfm22b.c b/flight/pios/common/pios_rfm22b.c index a4c447fa8..f1fa466e3 100644 --- a/flight/pios/common/pios_rfm22b.c +++ b/flight/pios/common/pios_rfm22b.c @@ -62,7 +62,7 @@ /* Local Defines */ #define STACK_SIZE_BYTES 200 #define TASK_PRIORITY (tskIDLE_PRIORITY + 2) -#define ISR_TIMEOUT 2 // ms +#define ISR_TIMEOUT 1 // ms #define EVENT_QUEUE_SIZE 5 #define RFM22B_DEFAULT_RX_DATARATE RFM22_datarate_9600 #define RFM22B_DEFAULT_TX_POWER RFM22_tx_pwr_txpow_0 @@ -1375,13 +1375,13 @@ static enum pios_radio_event rfm22_init(struct pios_rfm22b_dev *rfm22b_dev) rfm22b_dev->destination_id = 0xffffffff; rfm22b_dev->send_status = false; rfm22b_dev->send_connection_request = false; - rfm22b_dev->send_ack_nack = false; - rfm22b_dev->resend_packet = false; + rfm22b_dev->send_ack_nack = false; + rfm22b_dev->resend_packet = false; // Initialize the packets. - rfm22b_dev->rx_packet_len = 0; - rfm22b_dev->tx_packet = NULL; - rfm22b_dev->prev_tx_packet = NULL; + rfm22b_dev->rx_packet_len = 0; + rfm22b_dev->tx_packet = NULL; + rfm22b_dev->prev_tx_packet = NULL; rfm22b_dev->data_packet.header.data_size = 0; // Initialize the devide state @@ -2068,9 +2068,9 @@ static enum pios_radio_event radio_receivePacket(struct pios_rfm22b_dev *radio_d // which should match the time that the last packet was received. uint16_t prev_seq_num = radio_dev->stats.rx_seq; if (seq_num == (prev_seq_num + 1)) { - portTickType local_rx_time = radio_dev->rx_complete_ticks; - portTickType remote_tx_time = radio_dev->rx_packet.header.prev_tx_time; - portTickType time_delta = remote_tx_time - local_rx_time; + portTickType local_rx_time = radio_dev->rx_complete_ticks; + portTickType remote_tx_time = radio_dev->rx_packet.header.prev_tx_time; + portTickType time_delta = remote_tx_time - local_rx_time; portTickType time_delta_delta = (time_delta > radio_dev->time_delta) ? (time_delta - radio_dev->time_delta) : (radio_dev->time_delta - time_delta); if (time_delta_delta <= 2) { radio_dev->time_delta = remote_tx_time - local_rx_time; @@ -2221,7 +2221,7 @@ static enum pios_radio_event rfm22_sendAck(struct pios_rfm22b_dev *rfm22b_dev) aph->header.destination_id = rfm22b_dev->destination_id; aph->header.type = PACKET_TYPE_ACK; aph->header.data_size = PH_ACK_NACK_DATA_SIZE(aph); - rfm22b_dev->send_ack_nack = true; + rfm22b_dev->send_ack_nack = true; } return RADIO_EVENT_TX_START; } @@ -2241,7 +2241,7 @@ static enum pios_radio_event rfm22_sendNack(struct pios_rfm22b_dev *rfm22b_dev) aph->header.destination_id = rfm22b_dev->destination_id; aph->header.type = PACKET_TYPE_NACK; aph->header.data_size = PH_ACK_NACK_DATA_SIZE(aph); - rfm22b_dev->send_ack_nack = true; + rfm22b_dev->send_ack_nack = true; } return RADIO_EVENT_TX_START; } @@ -2484,6 +2484,7 @@ static enum pios_radio_event rfm22_acceptConnection(struct pios_rfm22b_dev *rfm2 // Copy the connection packet PHConnectionPacketHandle cph = (PHConnectionPacketHandle)(&(rfm22b_dev->rx_packet)); PHConnectionPacketHandle lcph = (PHConnectionPacketHandle)(&(rfm22b_dev->con_packet)); + memcpy((uint8_t *)lcph, (uint8_t *)cph, PH_PACKET_SIZE((PHPacketHandle)cph)); // Set the destination ID to the source of the connection request message. @@ -2525,9 +2526,10 @@ static portTickType rfm22_coordinatorTime(struct pios_rfm22b_dev *rfm22b_dev, po static bool rfm22_timeToSend(struct pios_rfm22b_dev *rfm22b_dev) { portTickType time = rfm22_coordinatorTime(rfm22b_dev, xTaskGetTickCount()); - // Divide time into 8ms blocks. Coordinator sends in first 2 ms, and remote send in 5th and 6th ms. - // Channel changes occur in the last 2 ms. - return (rfm22b_dev->coordinator) ? ((time & 0x0C) == 0) : (((time + 8) & 0x0C) == 0); + + // Divide time into 8ms blocks. Coordinator sends in first 1 ms, and remote send in 4th. + // Channel changes occurs in the 7th. + return (rfm22b_dev->coordinator) ? ((time & 0x7) == 0) : ((time & 0x7) == 3); } /** @@ -2540,7 +2542,8 @@ static uint8_t rfm22_calcChannel(struct pios_rfm22b_dev *rfm22b_dev) portTickType time = rfm22_coordinatorTime(rfm22b_dev, xTaskGetTickCount()); // Divide time into 8ms blocks. Coordinator sends in first 2 ms, and remote send in 5th and 6th ms. // Channel changes occur in the last 2 ms. - uint8_t n = (((time + 0x0C) >> 4) & 0xff); + uint8_t n = (((time + 2) >> 3) & 0xff); + return PIOS_CRC_updateByte(0, n) % rfm22b_dev->num_channels; } From 133a801dc59304ccf8b367642fe70b44b08ba73e Mon Sep 17 00:00:00 2001 From: Mathieu Rondonneau Date: Tue, 21 May 2013 19:06:48 -0700 Subject: [PATCH 013/120] OP-958: fix compiler error (showing on bambo) --- ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h index 1c784de1c..85b615b67 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h @@ -33,7 +33,7 @@ #include #include #include -#if defined(Q_OS_UNIX) +#if defined(Q_OS_LINUX) #include #endif #include "hidapi.h" From ac4847c8ac010afce9d835a2c57cfb32bf8d9db9 Mon Sep 17 00:00:00 2001 From: Brian Webb Date: Tue, 21 May 2013 19:48:21 -0700 Subject: [PATCH 014/120] OP-932 Moves the configuration of the com ports on the coordinator OPLink to startup. --- .../modules/RadioComBridge/RadioComBridge.c | 126 ++++++++---------- flight/pios/common/pios_rfm22b.c | 31 ++++- flight/pios/inc/pios_rfm22b.h | 3 +- .../boards/revolution/firmware/pios_board.c | 60 --------- 4 files changed, 85 insertions(+), 135 deletions(-) diff --git a/flight/modules/RadioComBridge/RadioComBridge.c b/flight/modules/RadioComBridge/RadioComBridge.c index 56a4e6ea8..125a14de7 100644 --- a/flight/modules/RadioComBridge/RadioComBridge.c +++ b/flight/modules/RadioComBridge/RadioComBridge.c @@ -110,9 +110,8 @@ static int32_t RadioSendHandler(uint8_t *buf, int32_t length); static void ProcessInputStream(UAVTalkConnection connectionHandle, uint8_t rxbyte); static void queueEvent(xQueueHandle queue, void *obj, uint16_t instId, UAVObjEventType type); static void configureComCallback(OPLinkSettingsRemoteMainPortOptions main_port, OPLinkSettingsRemoteFlexiPortOptions flexi_port, - OPLinkSettingsRemoteVCPPortOptions vcp_port, OPLinkSettingsComSpeedOptions com_speed, - uint32_t min_frequency, uint32_t max_frequency, uint32_t channel_spacing); -static void updateSettings(); + OPLinkSettingsRemoteVCPPortOptions vcp_port, OPLinkSettingsComSpeedOptions com_speed); +static void updateSettings(OPLinkSettingsData *oplinkSettings); // **************** // Private variables @@ -127,9 +126,6 @@ static RadioComBridgeData *data; static int32_t RadioComBridgeStart(void) { if (data) { - // Configure the com port configuration callback - PIOS_RFM22B_SetComConfigCallback(pios_rfm22b_id, &configureComCallback); - // Get the settings. OPLinkSettingsData oplinkSettings; OPLinkSettingsGet(&oplinkSettings); @@ -140,6 +136,9 @@ static int32_t RadioComBridgeStart(void) // Set the frequency range. PIOS_RFM22B_SetFrequencyRange(pios_rfm22b_id, oplinkSettings.MinFrequency, oplinkSettings.MaxFrequency, oplinkSettings.ChannelSpacing); + // Set the com baud rates. + updateSettings(&oplinkSettings); + // Reinitilize the modem. PIOS_RFM22B_Reinit(pios_rfm22b_id); @@ -147,6 +146,9 @@ static int32_t RadioComBridgeStart(void) data->parseUAVTalk = ((oplinkSettings.MainPort != OPLINKSETTINGS_MAINPORT_SERIAL) && (oplinkSettings.FlexiPort != OPLINKSETTINGS_FLEXIPORT_SERIAL) && (oplinkSettings.VCPPort != OPLINKSETTINGS_VCPPORT_SERIAL)); + } else { + // Configure the com port configuration callback on the remote modem. + PIOS_RFM22B_SetComConfigCallback(pios_rfm22b_id, &configureComCallback); } // Set the maximum radio RF power. @@ -572,78 +574,65 @@ static void queueEvent(xQueueHandle queue, void *obj, uint16_t instId, UAVObjEve * @param[in] com_speed The com port speed */ static void configureComCallback(OPLinkSettingsRemoteMainPortOptions main_port, OPLinkSettingsRemoteFlexiPortOptions flexi_port, - OPLinkSettingsRemoteVCPPortOptions vcp_port, OPLinkSettingsComSpeedOptions com_speed, - uint32_t min_frequency, uint32_t max_frequency, uint32_t channel_spacing) + OPLinkSettingsRemoteVCPPortOptions vcp_port, OPLinkSettingsComSpeedOptions com_speed) { // Update the com baud rate data->comSpeed = com_speed; - // Set the output main/flexi/vcp port and speed. - bool is_coordinator = PIOS_RFM22B_IsCoordinator(pios_rfm22b_id); - if (!is_coordinator) { - // Get the settings. - OPLinkSettingsData oplinkSettings; - OPLinkSettingsGet(&oplinkSettings); + // Get the settings. + OPLinkSettingsData oplinkSettings; + OPLinkSettingsGet(&oplinkSettings); - switch (main_port) { - case OPLINKSETTINGS_REMOTEMAINPORT_DISABLED: - oplinkSettings.MainPort = OPLINKSETTINGS_MAINPORT_DISABLED; - break; - case OPLINKSETTINGS_REMOTEMAINPORT_SERIAL: - oplinkSettings.MainPort = OPLINKSETTINGS_MAINPORT_SERIAL; - break; - case OPLINKSETTINGS_REMOTEMAINPORT_PPM: - oplinkSettings.MainPort = OPLINKSETTINGS_MAINPORT_PPM; - break; - } - - switch (flexi_port) { - case OPLINKSETTINGS_REMOTEFLEXIPORT_DISABLED: - oplinkSettings.FlexiPort = OPLINKSETTINGS_FLEXIPORT_DISABLED; - break; - case OPLINKSETTINGS_REMOTEFLEXIPORT_SERIAL: - oplinkSettings.FlexiPort = OPLINKSETTINGS_FLEXIPORT_SERIAL; - break; - case OPLINKSETTINGS_REMOTEFLEXIPORT_PPM: - oplinkSettings.FlexiPort = OPLINKSETTINGS_FLEXIPORT_PPM; - break; - } - - switch (vcp_port) { - case OPLINKSETTINGS_REMOTEVCPPORT_DISABLED: - oplinkSettings.VCPPort = OPLINKSETTINGS_VCPPORT_DISABLED; - break; - case OPLINKSETTINGS_REMOTEVCPPORT_SERIAL: - oplinkSettings.VCPPort = OPLINKSETTINGS_VCPPORT_SERIAL; - break; - } - - // Set the frequency range. - PIOS_RFM22B_SetFrequencyRange(pios_rfm22b_id, min_frequency, max_frequency, channel_spacing); - - // We will not parse/send UAVTalk if any ports are configured as Serial (except for over the USB HID port). - data->parseUAVTalk = ((oplinkSettings.MainPort != OPLINKSETTINGS_MAINPORT_SERIAL) && - (oplinkSettings.FlexiPort != OPLINKSETTINGS_FLEXIPORT_SERIAL) && - (oplinkSettings.VCPPort != OPLINKSETTINGS_VCPPORT_SERIAL)); - - // Update the OPLinkSettings object. - OPLinkSettingsSet(&oplinkSettings); + switch (main_port) { + case OPLINKSETTINGS_REMOTEMAINPORT_DISABLED: + oplinkSettings.MainPort = OPLINKSETTINGS_MAINPORT_DISABLED; + break; + case OPLINKSETTINGS_REMOTEMAINPORT_SERIAL: + oplinkSettings.MainPort = OPLINKSETTINGS_MAINPORT_SERIAL; + break; + case OPLINKSETTINGS_REMOTEMAINPORT_PPM: + oplinkSettings.MainPort = OPLINKSETTINGS_MAINPORT_PPM; + break; } + switch (flexi_port) { + case OPLINKSETTINGS_REMOTEFLEXIPORT_DISABLED: + oplinkSettings.FlexiPort = OPLINKSETTINGS_FLEXIPORT_DISABLED; + break; + case OPLINKSETTINGS_REMOTEFLEXIPORT_SERIAL: + oplinkSettings.FlexiPort = OPLINKSETTINGS_FLEXIPORT_SERIAL; + break; + case OPLINKSETTINGS_REMOTEFLEXIPORT_PPM: + oplinkSettings.FlexiPort = OPLINKSETTINGS_FLEXIPORT_PPM; + break; + } + + switch (vcp_port) { + case OPLINKSETTINGS_REMOTEVCPPORT_DISABLED: + oplinkSettings.VCPPort = OPLINKSETTINGS_VCPPORT_DISABLED; + break; + case OPLINKSETTINGS_REMOTEVCPPORT_SERIAL: + oplinkSettings.VCPPort = OPLINKSETTINGS_VCPPORT_SERIAL; + break; + } + + // We will not parse/send UAVTalk if any ports are configured as Serial (except for over the USB HID port). + data->parseUAVTalk = ((oplinkSettings.MainPort != OPLINKSETTINGS_MAINPORT_SERIAL) && + (oplinkSettings.FlexiPort != OPLINKSETTINGS_FLEXIPORT_SERIAL) && + (oplinkSettings.VCPPort != OPLINKSETTINGS_VCPPORT_SERIAL)); + + // Update the OPLinkSettings object. + OPLinkSettingsSet(&oplinkSettings); + // Perform the update. - updateSettings(); + updateSettings(&oplinkSettings); } /** * Update the oplink settings. */ -static void updateSettings() +static void updateSettings(OPLinkSettingsData *oplinkSettings) { - // Get the settings. - OPLinkSettingsData oplinkSettings; - - OPLinkSettingsGet(&oplinkSettings); - // We can only configure the hardware once. if (data->configured) { return; @@ -652,7 +641,7 @@ static void updateSettings() // Configure the main port bool is_coordinator = PIOS_RFM22B_IsCoordinator(pios_rfm22b_id); - switch (oplinkSettings.MainPort) { + switch (oplinkSettings->MainPort) { case OPLINKSETTINGS_MAINPORT_TELEMETRY: case OPLINKSETTINGS_MAINPORT_SERIAL: /* Configure the main port for uart serial */ @@ -667,7 +656,7 @@ static void updateSettings() } // Configure the flexi port - switch (oplinkSettings.FlexiPort) { + switch (oplinkSettings->FlexiPort) { case OPLINKSETTINGS_FLEXIPORT_TELEMETRY: case OPLINKSETTINGS_FLEXIPORT_SERIAL: /* Configure the flexi port as uart serial */ @@ -682,7 +671,7 @@ static void updateSettings() } // Configure the USB VCP port - switch (oplinkSettings.VCPPort) { + switch (oplinkSettings->VCPPort) { case OPLINKSETTINGS_VCPPORT_SERIAL: PIOS_COM_TELEMETRY = PIOS_COM_TELEM_USB_VCP; break; @@ -715,9 +704,6 @@ static void updateSettings() comBaud = 115200; break; } - if (PIOS_COM_RADIO) { - PIOS_COM_ChangeBaud(PIOS_COM_RADIO, comBaud); - } if (PIOS_COM_TELEMETRY) { PIOS_COM_ChangeBaud(PIOS_COM_TELEMETRY, comBaud); } diff --git a/flight/pios/common/pios_rfm22b.c b/flight/pios/common/pios_rfm22b.c index f1fa466e3..bebdf0ac5 100644 --- a/flight/pios/common/pios_rfm22b.c +++ b/flight/pios/common/pios_rfm22b.c @@ -2464,12 +2464,37 @@ static void rfm22_setConnectionParameters(struct pios_rfm22b_dev *rfm22b_dev) // Call the com port configuration function if (rfm22b_dev->com_config_cb) { - rfm22b_dev->com_config_cb(cph->main_port, cph->flexi_port, cph->vcp_port, cph->com_speed, - cph->min_frequency, cph->max_frequency, cph->channel_spacing); + rfm22b_dev->com_config_cb(cph->main_port, cph->flexi_port, cph->vcp_port, cph->com_speed); } - // Configure this modem from the connection request message. + // Configure this modem min an max frequency. rfm22_setNominalCarrierFrequency(rfm22b_dev, cph->min_frequency, cph->max_frequency, cph->channel_spacing); + + // Configure the modem datarate. + rfm22b_dev->datarate = RFM22_datarate_64000; + switch (cph->com_speed) { + case OPLINKSETTINGS_COMSPEED_2400: + rfm22b_dev->datarate = RFM22_datarate_8000; + break; + case OPLINKSETTINGS_COMSPEED_4800: + rfm22b_dev->datarate = RFM22_datarate_8000; + break; + case OPLINKSETTINGS_COMSPEED_9600: + rfm22b_dev->datarate = RFM22_datarate_16000; + break; + case OPLINKSETTINGS_COMSPEED_19200: + rfm22b_dev->datarate = RFM22_datarate_32000; + break; + case OPLINKSETTINGS_COMSPEED_38400: + rfm22b_dev->datarate = RFM22_datarate_57600; + break; + case OPLINKSETTINGS_COMSPEED_57600: + rfm22b_dev->datarate = RFM22_datarate_128000; + break; + case OPLINKSETTINGS_COMSPEED_115200: + rfm22b_dev->datarate = RFM22_datarate_192000; + break; + } pios_rfm22_setDatarate(rfm22b_dev, rfm22b_dev->datarate, true); } diff --git a/flight/pios/inc/pios_rfm22b.h b/flight/pios/inc/pios_rfm22b.h index 0763a6ae1..c6417cc80 100644 --- a/flight/pios/inc/pios_rfm22b.h +++ b/flight/pios/inc/pios_rfm22b.h @@ -106,8 +106,7 @@ struct rfm22b_stats { /* Callback function prototypes */ typedef void (*PIOS_RFM22B_ComConfigCallback)(OPLinkSettingsRemoteMainPortOptions main_port, OPLinkSettingsRemoteFlexiPortOptions flexi_port, - OPLinkSettingsRemoteVCPPortOptions vcp_port, OPLinkSettingsComSpeedOptions com_speed, - uint32_t min_frequency, uint32_t max_frequency, uint32_t channel_spacing); + OPLinkSettingsRemoteVCPPortOptions vcp_port, OPLinkSettingsComSpeedOptions com_speed); /* Public Functions */ extern int32_t PIOS_RFM22B_Init(uint32_t *rfb22b_id, uint32_t spi_id, uint32_t slave_num, const struct pios_rfm22b_cfg *cfg); diff --git a/flight/targets/boards/revolution/firmware/pios_board.c b/flight/targets/boards/revolution/firmware/pios_board.c index b4ea2d7be..38d07c8fb 100644 --- a/flight/targets/boards/revolution/firmware/pios_board.c +++ b/flight/targets/boards/revolution/firmware/pios_board.c @@ -42,13 +42,6 @@ */ #include "../board_hw_defs.c" -#if defined(PIOS_INCLUDE_RFM22B) -// Forward declarations -static void configureComCallback(OPLinkSettingsRemoteMainPortOptions main_port, OPLinkSettingsRemoteFlexiPortOptions flexi_port, - OPLinkSettingsRemoteVCPPortOptions vcp_port, OPLinkSettingsComSpeedOptions com_speed, - uint32_t min_frequency, uint32_t max_frequency, uint32_t channel_spacing); -#endif - /** * Sensor configurations */ @@ -785,10 +778,6 @@ void PIOS_Board_Init(void) } pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_OPLINK] = pios_rfm22b_rcvr_id; #endif - - // Set the com port configuration callback. - PIOS_RFM22B_SetComConfigCallback(pios_rfm22b_id, &configureComCallback); - break; } } @@ -881,55 +870,6 @@ void PIOS_Board_Init(void) #endif } -#if defined(PIOS_INCLUDE_RFM22B) -/** - * Configure the radio com port based on a configuration event from the remote coordinator. - * \param[in] main_port The main com port options - * \param[in] flexi_port The flexi com port options - * \param[in] vcp_port The USB virtual com port options - * \param[in] com_speed The com port speed - */ -static void configureComCallback(__attribute__((unused)) OPLinkSettingsRemoteMainPortOptions main_port, - __attribute__((unused)) OPLinkSettingsRemoteFlexiPortOptions flexi_port, - __attribute__((unused)) OPLinkSettingsRemoteVCPPortOptions vcp_port, - OPLinkSettingsComSpeedOptions com_speed, - uint32_t min_frequency, uint32_t max_frequency, uint32_t channel_spacing) -{ - uint32_t comBaud = 9600; - - switch (com_speed) { - case OPLINKSETTINGS_COMSPEED_2400: - comBaud = 2400; - break; - case OPLINKSETTINGS_COMSPEED_4800: - comBaud = 4800; - break; - case OPLINKSETTINGS_COMSPEED_9600: - comBaud = 9600; - break; - case OPLINKSETTINGS_COMSPEED_19200: - comBaud = 19200; - break; - case OPLINKSETTINGS_COMSPEED_38400: - comBaud = 38400; - break; - case OPLINKSETTINGS_COMSPEED_57600: - comBaud = 57600; - break; - case OPLINKSETTINGS_COMSPEED_115200: - comBaud = 115200; - break; - } - if (PIOS_COM_TELEM_RF) { - PIOS_COM_ChangeBaud(PIOS_COM_TELEM_RF, comBaud); - } - - // Set the frequency range. - PIOS_RFM22B_SetFrequencyRange(pios_rfm22b_id, min_frequency, max_frequency, channel_spacing); -} - -#endif /* if defined(PIOS_INCLUDE_RFM22B) */ - /** * @} * @} From 4b68c6da7434f76a815478def83fe0edabc32da3 Mon Sep 17 00:00:00 2001 From: Mathieu Rondonneau Date: Tue, 21 May 2013 20:10:37 -0700 Subject: [PATCH 015/120] OP-958: adding clearer message regarding the requirement for libusb-1.0.0 dev package: - break the build nicely telling the user to install the dev library package. --- ground/openpilotgcs/src/plugins/opHID/opHID.pro | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/opHID/opHID.pro b/ground/openpilotgcs/src/plugins/opHID/opHID.pro index 1080f4c67..274040cee 100644 --- a/ground/openpilotgcs/src/plugins/opHID/opHID.pro +++ b/ground/openpilotgcs/src/plugins/opHID/opHID.pro @@ -53,7 +53,9 @@ linux-g++ { LIBS += `pkg-config libusb-1.0 --libs` -lrt -lpthread INCLUDEPATH += /usr/include/libusb-1.0 # INCLUDEPATH += `pkg-config libusb-1.0 --cflags` - +!exists(/usr/include/libusb-1.0) { + error(Install libusb-1.0.0-dev using your package manager.) + } } linux-g++-64 { SOURCES += src/opHID_usbmon_linux.cpp @@ -67,6 +69,8 @@ linux-g++-64 { LIBS += `pkg-config libusb-1.0 --libs` -lrt -lpthread INCLUDEPATH += /usr/include/libusb-1.0 # INCLUDEPATH += `pkg-config libusb-1.0 --cflags` - +!exists(/usr/include/libusb-1.0) { + error(Install libusb-1.0.0-dev using your package manager.) + } } From bfcb608b8274a82cf577eda240a694beff09e8b8 Mon Sep 17 00:00:00 2001 From: Mathieu Rondonneau Date: Tue, 21 May 2013 21:04:44 -0700 Subject: [PATCH 016/120] OP-958: More cleanup and handle some corner cases: - retry discovery 5 times max before giving up. - open the last hid device in the list in case there are several hid device of the same vid. - remove structure and move handle to class. --- .../src/plugins/opHID/inc/opHID_hidapi.h | 13 +-- .../src/plugins/opHID/src/opHID_hidapi.cpp | 109 ++++++++++-------- 2 files changed, 67 insertions(+), 55 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h index 85b615b67..36379c274 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h @@ -40,12 +40,6 @@ #include "opHID_const.h" #include "opHID_global.h" -struct hidapi_wrapper_device -{ - struct hid_device_info *list_ptr; - hid_device *handle; -}; - class OPHID_EXPORT opHID_hidapi: public QObject { @@ -58,8 +52,6 @@ public: ~opHID_hidapi(); - int enumerate(int *devices_found); - int open(int max, int vid, int pid, int usage_page, int usage); int receive(int, void *buf, int len, int timeout); @@ -71,7 +63,10 @@ public: QString getserial(int num); private: - struct hidapi_wrapper_device hidapi_device; + + int enumerate(struct hid_device_info **current_device_pptr, int *devices_found); + + hid_device *handle; /** A mutex to protect hid write */ QMutex hid_write_Mtx; diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_hidapi.cpp b/ground/openpilotgcs/src/plugins/opHID/src/opHID_hidapi.cpp index 367a93c99..6f6d837d7 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID_hidapi.cpp +++ b/ground/openpilotgcs/src/plugins/opHID/src/opHID_hidapi.cpp @@ -43,8 +43,7 @@ opHID_hidapi::opHID_hidapi() { OPHID_TRACE("IN"); - hidapi_device.list_ptr = NULL; - hidapi_device.handle = NULL; + handle = NULL; // Make sure hidapi lib is ready if (hid_init()) @@ -75,39 +74,44 @@ opHID_hidapi::~opHID_hidapi() * in caller? because later we will do more parsing herer. * WARNING: our vendor id is harcoded here (not good idea). * +* \param[out] current_device_pptr Pointer to the list of device * \param[out] devices_found Number of devices found. * \return error. * \retval 0 on success. */ -int opHID_hidapi::enumerate(int *devices_found) +int opHID_hidapi::enumerate(struct hid_device_info **current_device_pptr, int *devices_found) { - *devices_found = 0; - struct hid_device_info *current_device_ptr = NULL; + int retry = 5; + *devices_found = 0; - OPHID_TRACE("IN"); + struct hid_device_info *current_device_ptr = NULL; - // Free any previous enumeration - if (hidapi_device.list_ptr) - hid_free_enumeration(hidapi_device.list_ptr); + OPHID_TRACE("IN"); - // Enumerate - hidapi_device.list_ptr = hid_enumerate(USB_VID, 0x0); + while(retry--) + { + // Enumerate + *current_device_pptr = hid_enumerate(USB_VID, 0x0); - // Display the list of devices found (for debug) - current_device_ptr = hidapi_device.list_ptr; + // Display the list of devices found (for debug) + current_device_ptr = *current_device_pptr; while (current_device_ptr) { - OPHID_DEBUG("HID Device Found"); - OPHID_DEBUG(" type:............VID(%04hx).PID(%04hx)", current_device_ptr->vendor_id, current_device_ptr->product_id); - OPHID_DEBUG(" path:............%s", current_device_ptr->path); - OPHID_DEBUG(" Release:.........%hx", current_device_ptr->release_number); - OPHID_DEBUG(" Interface:.......%d", current_device_ptr->interface_number); - current_device_ptr = current_device_ptr->next; - (*devices_found)++; + OPHID_DEBUG("HID Device Found"); + OPHID_DEBUG(" type:............VID(%04hx).PID(%04hx)", current_device_ptr->vendor_id, current_device_ptr->product_id); + OPHID_DEBUG(" path:............%s", current_device_ptr->path); + OPHID_DEBUG(" Release:.........%hx", current_device_ptr->release_number); + OPHID_DEBUG(" Interface:.......%d", current_device_ptr->interface_number); + current_device_ptr = current_device_ptr->next; + (*devices_found)++; } - OPHID_TRACE("OUT"); - return OPHID_NO_ERROR; + if (*devices_found) + break; + } + + OPHID_TRACE("OUT"); + return OPHID_NO_ERROR; } @@ -124,15 +128,17 @@ int opHID_hidapi::enumerate(int *devices_found) int opHID_hidapi::open(int max, int vid, int pid, int usage_page, int usage) { int devices_found = false; - struct hid_device_info *current_device_ptr = NULL; + struct hid_device_info *current_device_ptr = NULL; + struct hid_device_info *last_device_ptr = NULL; + struct hid_device_info **current_device_pptr = ¤t_device_ptr; OPHID_TRACE("IN"); OPHID_DEBUG("max: %d, vid: 0x%X, pid: 0x%X, usage_page: %d, usage: %d.", max, vid, pid, usage_page, usage); - if (hidapi_device.handle) + if (handle) { - OPHID_WARNING("WARNING: device seems already open."); + OPHID_WARNING("HID device seems already open."); } // This is a hack to prevent changing all the callers (for now) @@ -144,9 +150,9 @@ int opHID_hidapi::open(int max, int vid, int pid, int usage_page, int usage) // If caller knows which one to look for open it right away if (vid != 0 && pid != 0) { - hidapi_device.handle = hid_open(vid, pid, NULL); + handle = hid_open(vid, pid, NULL); - if (!hidapi_device.handle) + if (!handle) { OPHID_ERROR("Unable to open device."); devices_found = false; @@ -161,7 +167,7 @@ int opHID_hidapi::open(int max, int vid, int pid, int usage_page, int usage) else { // Get the list of available hid devices - if (enumerate(&devices_found) != OPHID_NO_ERROR) + if (enumerate(current_device_pptr, &devices_found) != OPHID_NO_ERROR) { OPHID_ERROR("Error during enumeration"); return 0; @@ -169,23 +175,32 @@ int opHID_hidapi::open(int max, int vid, int pid, int usage_page, int usage) if (devices_found) { - // Look for the first one of interest for now - current_device_ptr = hidapi_device.list_ptr; + // Look for the last one in the list + // WARNING: for now this prevent to have devices chained + last_device_ptr = current_device_ptr; + while (last_device_ptr->next) + last_device_ptr = last_device_ptr->next; OPHID_DEBUG("Opening device VID(%04hx).PID(%04hx)", - current_device_ptr->vendor_id, - current_device_ptr->product_id); + last_device_ptr->vendor_id, + last_device_ptr->product_id); - hidapi_device.handle = hid_open(current_device_ptr->vendor_id, - current_device_ptr->product_id, - NULL); - if (!hidapi_device.handle) + handle = hid_open(last_device_ptr->vendor_id, + last_device_ptr->product_id, + NULL); + + hid_free_enumeration(current_device_ptr); + + if (!handle) { OPHID_ERROR("Unable to open device."); devices_found = false; } - - hid_free_enumeration(hidapi_device.list_ptr); + + } + else + { + OPHID_WARNING("Unable to find any HID device."); } } @@ -229,14 +244,14 @@ int opHID_hidapi::receive(int num, void *buf, int len, int timeout) return OPHID_ERROR_PARAMETER; } - if (hidapi_device.handle == NULL) + if (handle == NULL) { OPHID_ERROR("Handle invalid."); return OPHID_ERROR_HANDLE; } hid_read_Mtx.lock(); - bytes_read = hid_read(hidapi_device.handle, (unsigned char*)buf, len); + bytes_read = hid_read(handle, (unsigned char*)buf, len); hid_read_Mtx.unlock(); // hidapi lib does not expose the libusb errors. @@ -281,7 +296,7 @@ int opHID_hidapi::send(int num, void *buf, int len, int timeout) return OPHID_ERROR_PARAMETER; } - if (hidapi_device.handle == NULL) + if (handle == NULL) { OPHID_ERROR("Handle invalid."); return OPHID_ERROR_HANDLE; @@ -291,7 +306,7 @@ int opHID_hidapi::send(int num, void *buf, int len, int timeout) while(retry--) { hid_write_Mtx.lock(); - bytes_written = hid_write(hidapi_device.handle, (const unsigned char*)buf, len); + bytes_written = hid_write(handle, (const unsigned char*)buf, len); hid_write_Mtx.unlock(); if (bytes_written >= 0) { @@ -328,13 +343,13 @@ QString opHID_hidapi::getserial(int num) wchar_t buf[USB_MAX_STRING_SIZE]; - if (hidapi_device.handle == NULL) + if (handle == NULL) { OPHID_ERROR("Handle invalid."); return QString(""); } - if (hid_get_serial_number_string(hidapi_device.handle, buf, USB_MAX_STRING_SIZE) < 0) + if (hid_get_serial_number_string(handle, buf, USB_MAX_STRING_SIZE) < 0) { OPHID_ERROR("Unable to read serial number string."); return QString(""); @@ -359,8 +374,10 @@ void opHID_hidapi::close(int num) OPHID_TRACE("IN"); - if (hidapi_device.handle) - hid_close(hidapi_device.handle); + if (handle) + hid_close(handle); + + handle = NULL; OPHID_TRACE("OUT"); } From 697874b3153c0f427e5baf8398d1b8ccc8937862 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Wed, 22 May 2013 20:27:12 +0200 Subject: [PATCH 017/120] Port of OP-754 On Revo. Fixed signs on bias calculation. Added rate zeroing at startup to yaw --- flight/modules/Attitude/revolution/attitude.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/flight/modules/Attitude/revolution/attitude.c b/flight/modules/Attitude/revolution/attitude.c index e88fb5da0..51668f5c9 100644 --- a/flight/modules/Attitude/revolution/attitude.c +++ b/flight/modules/Attitude/revolution/attitude.c @@ -499,11 +499,14 @@ static int32_t updateAttitudeComplementary(bool first_run) GyrosBiasData gyrosBias; GyrosBiasGet(&gyrosBias); if(revoCalibration.BiasCorrectedRaw == REVOCALIBRATION_BIASCORRECTEDRAW_TRUE) { - gyrosBias.x -= accel_err[0] * attitudeSettings.AccelKi + (gyrosData.x + gyrosBias.x) * rollPitchBiasRate; - gyrosBias.y -= accel_err[1] * attitudeSettings.AccelKi + (gyrosData.y + gyrosBias.y) * rollPitchBiasRate; + gyrosBias.x -= accel_err[0] * attitudeSettings.AccelKi - gyrosData.x * rollPitchBiasRate; + gyrosBias.y -= accel_err[1] * attitudeSettings.AccelKi - gyrosData.y * rollPitchBiasRate; + gyrosBias.z -= - gyrosData.z * rollPitchBiasRate; + } else { - gyrosBias.x -= accel_err[0] * attitudeSettings.AccelKi + gyrosData.x * rollPitchBiasRate;; - gyrosBias.y -= accel_err[1] * attitudeSettings.AccelKi + gyrosData.y * rollPitchBiasRate; + gyrosBias.x -= accel_err[0] * attitudeSettings.AccelKi - (gyrosData.x - gyrosBias.x) * rollPitchBiasRate;; + gyrosBias.y -= accel_err[1] * attitudeSettings.AccelKi - (gyrosData.y - gyrosBias.y) * rollPitchBiasRate; + gyrosBias.z -= - (gyrosData.z - gyrosBias.z) * rollPitchBiasRate; // if the raw values are not adjusted, we need to adjust here. gyrosData.x -= gyrosBias.x; From 711f1ad35b8f2fc18e2b731fcd34d08aa09717b3 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Thu, 23 May 2013 00:47:38 +0200 Subject: [PATCH 018/120] Fix indentation --- flight/modules/Attitude/revolution/attitude.c | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/flight/modules/Attitude/revolution/attitude.c b/flight/modules/Attitude/revolution/attitude.c index 51668f5c9..e49257b40 100644 --- a/flight/modules/Attitude/revolution/attitude.c +++ b/flight/modules/Attitude/revolution/attitude.c @@ -387,24 +387,25 @@ static int32_t updateAttitudeComplementary(bool first_run) attitudeSettings.AccelKp = 1.0f; attitudeSettings.AccelKi = 0.0f; attitudeSettings.YawBiasRate = 0.23f; - accel_filter_enabled = false; - rollPitchBiasRate = 0.01f; + accel_filter_enabled = false; + rollPitchBiasRate = 0.01f; attitudeSettings.MagKp = 1.0f; } else if ((attitudeSettings.ZeroDuringArming == ATTITUDESETTINGS_ZERODURINGARMING_TRUE) && (flightStatus.Armed == FLIGHTSTATUS_ARMED_ARMING)) { attitudeSettings.AccelKp = 1.0f; attitudeSettings.AccelKi = 0.0f; attitudeSettings.YawBiasRate = 0.23f; - accel_filter_enabled = false; - rollPitchBiasRate = 0.01f; + accel_filter_enabled = false; + rollPitchBiasRate = 0.01f; attitudeSettings.MagKp = 1.0f; init = 0; } else if (init == 0) { // Reload settings (all the rates) AttitudeSettingsGet(&attitudeSettings); rollPitchBiasRate = 0.0f; - if (accel_alpha > 0.0f) + if (accel_alpha > 0.0f) { accel_filter_enabled = true; - init = 1; + } + init = 1; } GyrosGet(&gyrosData); @@ -437,10 +438,10 @@ static int32_t updateAttitudeComplementary(bool first_run) CrossProduct((const float *)accels_filtered, (const float *)grot_filtered, accel_err); // Account for accel magnitude - accel_mag = accels_filtered[0]*accels_filtered[0] + accels_filtered[1]*accels_filtered[1] + accels_filtered[2]*accels_filtered[2]; - accel_mag = sqrtf(accel_mag); + accel_mag = accels_filtered[0] * accels_filtered[0] + accels_filtered[1] * accels_filtered[1] + accels_filtered[2] * accels_filtered[2]; + accel_mag = sqrtf(accel_mag); - //TODO! check accel vector magnitude value for correctness + // TODO! check accel vector magnitude value for correctness accel_err[0] /= accel_mag; accel_err[1] /= accel_mag; @@ -448,17 +449,16 @@ static int32_t updateAttitudeComplementary(bool first_run) float grot_mag; if (accel_filter_enabled) { + grot_mag = sqrtf(grot_filtered[0] * grot_filtered[0] + grot_filtered[1] * grot_filtered[1] + grot_filtered[2] * grot_filtered[2]); + } else { + grot_mag = 1.0f; + } - grot_mag = sqrtf(grot_filtered[0] * grot_filtered[0] + grot_filtered[1] * grot_filtered[1] + grot_filtered[2] * grot_filtered[2]); - } else { - grot_mag = 1.0f; - } + // TODO! check grot_mag value for correctness. - // TODO! check grot_mag value for correctness. - - accel_err[0] /= (accel_mag * grot_mag); - accel_err[1] /= (accel_mag * grot_mag); - accel_err[2] /= (accel_mag * grot_mag); + accel_err[0] /= (accel_mag * grot_mag); + accel_err[1] /= (accel_mag * grot_mag); + accel_err[2] /= (accel_mag * grot_mag); if (xQueueReceive(magQueue, &ev, 0) != pdTRUE) { @@ -498,15 +498,14 @@ static int32_t updateAttitudeComplementary(bool first_run) // Accumulate integral of error. Scale here so that units are (deg/s) but Ki has units of s GyrosBiasData gyrosBias; GyrosBiasGet(&gyrosBias); - if(revoCalibration.BiasCorrectedRaw == REVOCALIBRATION_BIASCORRECTEDRAW_TRUE) { + if (revoCalibration.BiasCorrectedRaw == REVOCALIBRATION_BIASCORRECTEDRAW_TRUE) { gyrosBias.x -= accel_err[0] * attitudeSettings.AccelKi - gyrosData.x * rollPitchBiasRate; gyrosBias.y -= accel_err[1] * attitudeSettings.AccelKi - gyrosData.y * rollPitchBiasRate; - gyrosBias.z -= - gyrosData.z * rollPitchBiasRate; - + gyrosBias.z -= -gyrosData.z * rollPitchBiasRate; } else { gyrosBias.x -= accel_err[0] * attitudeSettings.AccelKi - (gyrosData.x - gyrosBias.x) * rollPitchBiasRate;; gyrosBias.y -= accel_err[1] * attitudeSettings.AccelKi - (gyrosData.y - gyrosBias.y) * rollPitchBiasRate; - gyrosBias.z -= - (gyrosData.z - gyrosBias.z) * rollPitchBiasRate; + gyrosBias.z -= -(gyrosData.z - gyrosBias.z) * rollPitchBiasRate; // if the raw values are not adjusted, we need to adjust here. gyrosData.x -= gyrosBias.x; From 1d0c18ebcd7e9b0949c298eeae74445f28bcd757 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Thu, 23 May 2013 22:52:26 +0200 Subject: [PATCH 019/120] Applied hidapi branch iokit_path from https://github.com/mrpippy/hidapi.git --- .../src/plugins/opHID/hidapi/mac/hid.c | 230 +++++++++--------- 1 file changed, 110 insertions(+), 120 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/opHID/hidapi/mac/hid.c b/ground/openpilotgcs/src/plugins/opHID/hidapi/mac/hid.c index 13109239e..d556eac53 100644 --- a/ground/openpilotgcs/src/plugins/opHID/hidapi/mac/hid.c +++ b/ground/openpilotgcs/src/plugins/opHID/hidapi/mac/hid.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -264,46 +265,6 @@ static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t } -static int get_string_property_utf8(IOHIDDeviceRef device, CFStringRef prop, char *buf, size_t len) -{ - CFStringRef str; - if (!len) - return 0; - - str = IOHIDDeviceGetProperty(device, prop); - - buf[0] = 0; - - if (str) { - len--; - - CFIndex str_len = CFStringGetLength(str); - CFRange range; - range.location = 0; - range.length = str_len; - CFIndex used_buf_len; - CFIndex chars_copied; - chars_copied = CFStringGetBytes(str, - range, - kCFStringEncodingUTF8, - (char)'?', - FALSE, - (UInt8*)buf, - len, - &used_buf_len); - - if (used_buf_len == len) - buf[len] = 0; /* len is decremented above */ - else - buf[used_buf_len] = 0; - - return used_buf_len; - } - else - return 0; -} - - static int get_serial_number(IOHIDDeviceRef device, wchar_t *buf, size_t len) { return get_string_property(device, CFSTR(kIOHIDSerialNumberKey), buf, len); @@ -330,33 +291,54 @@ static wchar_t *dup_wcs(const wchar_t *s) return ret; } +#if MAC_OS_X_VERSION_MIN_REQUIRED != MAC_OS_X_VERSION_10_5 +#warning "hidapi must be compiled/linked with -mmacosx-version-min=10.5 if you want OS X 10.5 compatibility" +#endif -static int make_path(IOHIDDeviceRef device, char *buf, size_t len) +/* hidapi_IOHIDDeviceGetService() + * + * Return the io_service_t corresponding to a given IOHIDDeviceRef, either by: + * - on OS X 10.6 and above, calling IOHIDDeviceGetService() + * - on OS X 10.5, extract it from the IOHIDDevice struct + */ +static io_service_t hidapi_IOHIDDeviceGetService(IOHIDDeviceRef device) { - int res; - unsigned short vid, pid; - char transport[32]; - int32_t location; + /* When compiled with '-mmacosx-version-min=10.5', IOHIDDeviceGetService() + * is weakly linked in so we can decide to use it (or not) at runtime. + */ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 + if (IOHIDDeviceGetService != NULL) { + /* OS X 10.6 and above: IOHIDDeviceGetService() exists */ + return IOHIDDeviceGetService(device); + } + else +#endif + { + /* OS X 10.5: IOHIDDeviceGetService() doesn't exist. + * Be naughty and pull the service out of the IOHIDDevice. + * Tested and working on OS X 10.5.8 i386, x86_64, and ppc + */ + struct IOHIDDevice_internal { + /* The first field of the IOHIDDevice struct is a + * CFRuntimeBase (which is a private CF struct). + * + * a, b, and c are the 3 fields that make up a CFRuntimeBase. + * See http://opensource.apple.com/source/CF/CF-476.18/CFRuntime.h + * + * The second field of the IOHIDDevice is the io_service_t we're looking for. + */ + //CFRuntimeBase base; + uintptr_t a; + uint8_t b[4]; +#if __LP64__ + uint32_t c; +#endif + io_service_t service; + }; + struct IOHIDDevice_internal *tmp = (struct IOHIDDevice_internal *)device; - buf[0] = '\0'; - - res = get_string_property_utf8( - device, CFSTR(kIOHIDTransportKey), - transport, sizeof(transport)); - - if (!res) - return -1; - - location = get_location_id(device); - vid = get_vendor_id(device); - pid = get_product_id(device); - - res = snprintf(buf, len, "%s_%04hx_%04hx_%x", - transport, vid, pid, location); - - - buf[len-1] = '\0'; - return res+1; + return tmp->service; + } } /* Initialize the IOHIDManager. Return 0 for success and -1 for failure. */ @@ -433,7 +415,6 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short dev_pid; #define BUF_LEN 256 wchar_t buf[BUF_LEN]; - char cbuf[BUF_LEN]; IOHIDDeviceRef dev = device_array[i]; @@ -447,7 +428,9 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, if ((vendor_id == 0x0 || vendor_id == dev_vid) && (product_id == 0x0 || product_id == dev_pid)) { struct hid_device_info *tmp; - size_t len; + io_object_t iokit_dev; + kern_return_t res; + io_string_t path; /* VID/PID match. Create the record. */ tmp = malloc(sizeof(struct hid_device_info)); @@ -465,8 +448,14 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, /* Fill out the record */ cur_dev->next = NULL; - len = make_path(dev, cbuf, sizeof(cbuf)); - cur_dev->path = strdup(cbuf); + + /* Fill in the path (IOService plane) */ + iokit_dev = hidapi_IOHIDDeviceGetService(dev); + res = IORegistryEntryGetPath(iokit_dev, kIOServicePlane, path); + if (res == KERN_SUCCESS) + cur_dev->path = strdup(path); + else + cur_dev->path = strdup(""); /* Serial Number */ get_serial_number(dev, buf, BUF_LEN); @@ -680,76 +669,77 @@ static void *read_thread(void *param) return NULL; } +/* hid_open_path() + * + * path must be a valid path to an IOHIDDevice in the IOService plane + * Example: "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/EHC1@1D,7/AppleUSBEHCI/PLAYSTATION(R)3 Controller@fd120000/IOUSBInterface@0/IOUSBHIDDriver" + */ hid_device * HID_API_EXPORT hid_open_path(const char *path) { - int i; hid_device *dev = NULL; - CFIndex num_devices; - + io_registry_entry_t entry = MACH_PORT_NULL; + dev = new_hid_device(); /* Set up the HID Manager if it hasn't been done */ if (hid_init() < 0) return NULL; - /* give the IOHIDManager a chance to update itself */ - process_pending_events(); + /* Get the IORegistry entry for the given path */ + entry = IORegistryEntryFromPath(kIOMasterPortDefault, path); + if (entry == MACH_PORT_NULL) { + /* Path wasn't valid (maybe device was removed?) */ + goto return_error; + } - CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr); + /* Create an IOHIDDevice for the entry */ + dev->device_handle = IOHIDDeviceCreate(kCFAllocatorDefault, entry); + if (dev->device_handle == NULL) { + /* Error creating the HID device */ + goto return_error; + } - num_devices = CFSetGetCount(device_set); - IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef)); - CFSetGetValues(device_set, (const void **) device_array); - for (i = 0; i < num_devices; i++) { - char cbuf[BUF_LEN]; - size_t len; - IOHIDDeviceRef os_dev = device_array[i]; + /* Open the IOHIDDevice */ + IOReturn ret = IOHIDDeviceOpen(dev->device_handle, kIOHIDOptionsTypeSeizeDevice); + if (ret == kIOReturnSuccess) { + char str[32]; - len = make_path(os_dev, cbuf, sizeof(cbuf)); - if (!strcmp(cbuf, path)) { - /* Matched Paths. Open this Device. */ - IOReturn ret = IOHIDDeviceOpen(os_dev, kIOHIDOptionsTypeSeizeDevice); - if (ret == kIOReturnSuccess) { - char str[32]; + /* Create the buffers for receiving data */ + dev->max_input_report_len = (CFIndex) get_max_report_length(dev->device_handle); + dev->input_report_buf = calloc(dev->max_input_report_len, sizeof(uint8_t)); - free(device_array); - CFRetain(os_dev); - CFRelease(device_set); - dev->device_handle = os_dev; + /* Create the Run Loop Mode for this device. + printing the reference seems to work. */ + sprintf(str, "HIDAPI_%p", dev->device_handle); + dev->run_loop_mode = + CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII); + + /* Attach the device to a Run Loop */ + IOHIDDeviceRegisterInputReportCallback( + dev->device_handle, dev->input_report_buf, dev->max_input_report_len, + &hid_report_callback, dev); + IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev); - /* Create the buffers for receiving data */ - dev->max_input_report_len = (CFIndex) get_max_report_length(os_dev); - dev->input_report_buf = calloc(dev->max_input_report_len, sizeof(uint8_t)); + /* Start the read thread */ + pthread_create(&dev->thread, NULL, read_thread, dev); - /* Create the Run Loop Mode for this device. - printing the reference seems to work. */ - sprintf(str, "HIDAPI_%p", os_dev); - dev->run_loop_mode = - CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII); - - /* Attach the device to a Run Loop */ - IOHIDDeviceRegisterInputReportCallback( - os_dev, dev->input_report_buf, dev->max_input_report_len, - &hid_report_callback, dev); - IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev); - - /* Start the read thread */ - pthread_create(&dev->thread, NULL, read_thread, dev); - - /* Wait here for the read thread to be initialized. */ - pthread_barrier_wait(&dev->barrier); - - return dev; - } - else { - goto return_error; - } - } + /* Wait here for the read thread to be initialized. */ + pthread_barrier_wait(&dev->barrier); + + IOObjectRelease(entry); + return dev; + } + else { + goto return_error; } return_error: - free(device_array); - CFRelease(device_set); + if (dev->device_handle != NULL) + CFRelease(dev->device_handle); + + if (entry != MACH_PORT_NULL) + IOObjectRelease(entry); + free_hid_device(dev); return NULL; } From ccc7e4a0ab3bcbdb73ad9525873193ab657715c8 Mon Sep 17 00:00:00 2001 From: Mathieu Rondonneau Date: Thu, 23 May 2013 19:33:54 -0700 Subject: [PATCH 020/120] OP-958: fix cast. I am about to check-in something that I have not compiled :( Will check build server to make sure it pass build and revert if needed. --- .../openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp index aec0a83a7..61fd86230 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp +++ b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp @@ -230,12 +230,12 @@ static bool HID_GetIntProperty(IOHIDDeviceRef dev, CFStringRef property, int *va */ static bool HID_GetStrProperty(IOHIDDeviceRef dev, CFStringRef property, QString & value) { - CFTypeRef prop = IOHIDDeviceGetProperty(dev, property); + CFStringRef prop = static_cast(IOHIDDeviceGetProperty(dev, property)); if (prop) { if (CFStringGetTypeID() == CFGetTypeID(prop)) { // if a string char buffer[2550]; - bool success = CFStringGetCString((CFStringRef)prop, buffer, sizeof(buffer), kCFStringEncodingMacRoman); + bool success = CFStringGetCString(prop, buffer, sizeof(buffer), kCFStringEncodingMacRoman); value = QString(buffer); return success; } From 3b7c6eaa5fed5d0de5baefd25ff290fe4f1efbd6 Mon Sep 17 00:00:00 2001 From: Voha Date: Fri, 24 May 2013 21:53:35 +0300 Subject: [PATCH 021/120] =?UTF-8?q?*[mac=20only]=20definition=20usb=20devi?= =?UTF-8?q?ces=20made=20=E2=80=8B=E2=80=8Bin=20an=20additional=20thread?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/plugins/opHID/inc/opHID_usbmon.h | 13 +++ .../src/plugins/opHID/src/opHID_plugin.cpp | 9 +- .../plugins/opHID/src/opHID_usbmon_mac.cpp | 86 ++++++++++++------- .../src/plugins/opHID/src/opHID_usbsignal.cpp | 3 +- 4 files changed, 75 insertions(+), 36 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h index 474876051..2a514904a 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h @@ -137,6 +137,9 @@ signals: \param info The device that has been discovered. */ void deviceDiscovered( const USBPortInfo & info ); +#ifdef __APPLE__ + void deviceDiscovered(); +#endif // __APPLE__ /*! A device has been disconnected from the system. @@ -145,6 +148,9 @@ signals: \param info The device that was disconnected. */ void deviceRemoved( const USBPortInfo & info ); +#ifdef __APPLE__ + void deviceRemoved(); +#endif // __APPLE__ private slots: /** @@ -198,6 +204,13 @@ private: #endif #endif +#ifdef __APPLE__ +protected: + bool m_terminate; + + void run(); +#endif // __APPLE__ + }; #endif // OPHID_USBMON_H diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_plugin.cpp b/ground/openpilotgcs/src/plugins/opHID/src/opHID_plugin.cpp index d903ff65d..84efc3bfd 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID_plugin.cpp +++ b/ground/openpilotgcs/src/plugins/opHID/src/opHID_plugin.cpp @@ -49,8 +49,13 @@ RawHIDConnection::RawHIDConnection() m_usbMonitor = USBMonitor::instance(); - connect(m_usbMonitor, SIGNAL(deviceDiscovered(USBPortInfo)), this, SLOT(onDeviceConnected())); - connect(m_usbMonitor, SIGNAL(deviceRemoved(USBPortInfo)), this, SLOT(onDeviceDisconnected())); +#ifndef __APPLE__ + connect(m_usbMonitor, SIGNAL(deviceDiscovered(USBPortInfo)), this, SLOT(onDeviceConnected())); + connect(m_usbMonitor, SIGNAL(deviceRemoved(USBPortInfo)), this, SLOT(onDeviceDisconnected())); +#else + connect(m_usbMonitor, SIGNAL(deviceDiscovered()), this, SLOT(onDeviceConnected())); + connect(m_usbMonitor, SIGNAL(deviceRemoved()), this, SLOT(onDeviceDisconnected())); +#endif } diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp index 61fd86230..667b281db 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp +++ b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp @@ -35,6 +35,8 @@ #include #include "opHID_const.h" +#define OP_LOOPMODE_NAME_MAC "Open_Pilot_Loop_Mode" + #define printf qDebug // ! Local helper functions @@ -46,45 +48,25 @@ static bool HID_GetStrProperty(IOHIDDeviceRef dev, CFStringRef property, QString */ USBMonitor::USBMonitor(QObject *parent) : QThread(parent) { - hid_manager = NULL; - IOReturn ret; - - m_instance = this; - - listMutex = new QMutex(); - knowndevices.clear(); - - hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); - if (hid_manager == NULL || CFGetTypeID(hid_manager) != IOHIDManagerGetTypeID()) { - if (hid_manager) { - CFRelease(hid_manager); - } - Q_ASSERT(0); - } - - // No matching filter - IOHIDManagerSetDeviceMatching(hid_manager, NULL); - - // set up a callbacks for device attach & detach - IOHIDManagerScheduleWithRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); - IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, attach_callback, NULL); - IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, detach_callback, NULL); - ret = IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone); - if (ret != kIOReturnSuccess) { - IOHIDManagerUnscheduleFromRunLoop(hid_manager, - CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); - CFRelease(hid_manager); - return; - } + m_instance = this; + hid_manager = NULL; + listMutex = new QMutex(); + knowndevices.clear(); + m_terminate = false; start(); } USBMonitor::~USBMonitor() { + m_terminate = true; // if(hid_manager != NULL) // IOHIDManagerUnscheduleFromRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); - quit(); +// quit(); + + while (hid_manager != 0) { + this->sleep(10); + } } void USBMonitor::deviceEventReceived() @@ -108,6 +90,7 @@ void USBMonitor::removeDevice(IOHIDDeviceRef dev) QMutexLocker locker(listMutex); knowndevices.removeAt(i); emit deviceRemoved(port); + emit deviceRemoved(); return; } } @@ -130,8 +113,9 @@ void USBMonitor::addDevice(USBPortInfo info) { QMutexLocker locker(listMutex); - knowndevices.append(info); - emit deviceDiscovered(info); + knowndevices.append(info); + emit deviceDiscovered(info); + emit deviceDiscovered(); } void USBMonitor::attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev) @@ -201,6 +185,42 @@ QList USBMonitor::availableDevices(int vid, int pid, int bcdDeviceM return thePortsWeWant; } +void USBMonitor::run() +{ + IOReturn ret; + + hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + if (hid_manager == NULL || CFGetTypeID(hid_manager) != IOHIDManagerGetTypeID()) { + if (hid_manager) { + CFRelease(hid_manager); + } + assert(0); + } + + // No matching filter + IOHIDManagerSetDeviceMatching(hid_manager, NULL); + + CFRunLoopRef loop = CFRunLoopGetCurrent(); + // set up a callbacks for device attach & detach + IOHIDManagerScheduleWithRunLoop(hid_manager, loop, kCFRunLoopDefaultMode); + IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, attach_callback, this); + IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, detach_callback, this); + ret = IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone); + if (ret != kIOReturnSuccess) { + IOHIDManagerUnscheduleFromRunLoop(hid_manager, loop, kCFRunLoopDefaultMode); + CFRelease(hid_manager); + return; + } + + while(!m_terminate) { + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, false); + } + IOHIDManagerUnscheduleFromRunLoop(hid_manager, loop, kCFRunLoopDefaultMode); + CFRelease(hid_manager); + + hid_manager = NULL; +} + /** * @brief Helper function get get a HID integer property * @param[in] dev Device reference diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbsignal.cpp b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbsignal.cpp index e6ab5e39c..68dee238d 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbsignal.cpp +++ b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbsignal.cpp @@ -68,7 +68,8 @@ USBSignalFilter::USBSignalFilter(int vid, int pid, int boardModel, int runState) connect(USBMonitor::instance(), SIGNAL(deviceDiscovered(USBPortInfo)), this, - SLOT(m_deviceDiscovered(USBPortInfo))); + SLOT(m_deviceDiscovered(USBPortInfo)), + Qt::QueuedConnection); } From f61340f30a415b604eefeb7bb3c68469992f520b Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sat, 25 May 2013 00:41:27 +0300 Subject: [PATCH 022/120] OP-958: do not uncrustify hidapi library (add .no-auto-format file) --- ground/openpilotgcs/src/plugins/opHID/hidapi/.no-auto-format | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ground/openpilotgcs/src/plugins/opHID/hidapi/.no-auto-format diff --git a/ground/openpilotgcs/src/plugins/opHID/hidapi/.no-auto-format b/ground/openpilotgcs/src/plugins/opHID/hidapi/.no-auto-format new file mode 100644 index 000000000..e69de29bb From c10932b45792f69daa98137955f43f59ddd6c44b Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sat, 25 May 2013 00:45:00 +0300 Subject: [PATCH 023/120] OP-958: move hidapi.h under library root to stop uncrustification --- ground/openpilotgcs/src/plugins/opHID/{inc => hidapi}/hidapi.h | 0 ground/openpilotgcs/src/plugins/opHID/opHID.pro | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename ground/openpilotgcs/src/plugins/opHID/{inc => hidapi}/hidapi.h (100%) diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/hidapi.h b/ground/openpilotgcs/src/plugins/opHID/hidapi/hidapi.h similarity index 100% rename from ground/openpilotgcs/src/plugins/opHID/inc/hidapi.h rename to ground/openpilotgcs/src/plugins/opHID/hidapi/hidapi.h diff --git a/ground/openpilotgcs/src/plugins/opHID/opHID.pro b/ground/openpilotgcs/src/plugins/opHID/opHID.pro index 274040cee..eccb05bdd 100644 --- a/ground/openpilotgcs/src/plugins/opHID/opHID.pro +++ b/ground/openpilotgcs/src/plugins/opHID/opHID.pro @@ -9,7 +9,7 @@ HEADERS += inc/opHID_global.h \ inc/opHID_const.h \ inc/opHID_usbmon.h \ inc/opHID_usbsignal.h \ - inc/hidapi.h + hidapi/hidapi.h SOURCES += src/opHID_plugin.cpp \ src/opHID.cpp \ src/opHID_usbsignal.cpp \ From f6d2f152b9abcfc7352a3b9606027ab58b166794 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sat, 25 May 2013 01:19:18 +0300 Subject: [PATCH 024/120] OP-958: windows/hid.c: fix file mode (was executable) --- ground/openpilotgcs/src/plugins/opHID/hidapi/windows/hid.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 ground/openpilotgcs/src/plugins/opHID/hidapi/windows/hid.c diff --git a/ground/openpilotgcs/src/plugins/opHID/hidapi/windows/hid.c b/ground/openpilotgcs/src/plugins/opHID/hidapi/windows/hid.c old mode 100755 new mode 100644 From d1dd944bc3421576bb4321bde52dfe8f27c081d5 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sat, 25 May 2013 01:23:02 +0300 Subject: [PATCH 025/120] OP-958: uncrustify sources --- .../src/plugins/opHID/inc/opHID.h | 14 +- .../src/plugins/opHID/inc/opHID_const.h | 48 ++-- .../src/plugins/opHID/inc/opHID_global.h | 21 +- .../src/plugins/opHID/inc/opHID_hidapi.h | 10 +- .../src/plugins/opHID/inc/opHID_plugin.h | 45 ++- .../src/plugins/opHID/inc/opHID_usbmon.h | 115 ++++---- .../src/plugins/opHID/inc/opHID_usbsignal.h | 4 +- .../src/plugins/opHID/src/opHID.cpp | 183 ++++++------ .../src/plugins/opHID/src/opHID_hidapi.cpp | 272 ++++++++---------- .../src/plugins/opHID/src/opHID_plugin.cpp | 206 ++++++------- .../plugins/opHID/src/opHID_usbmon_linux.cpp | 182 ++++++------ .../plugins/opHID/src/opHID_usbmon_mac.cpp | 84 +++--- .../src/plugins/opHID/src/opHID_usbsignal.cpp | 49 ++-- 13 files changed, 596 insertions(+), 637 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID.h index 9e8cd9ea9..fc1700deb 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID.h +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID.h @@ -41,11 +41,10 @@ class RawHIDReadThread; class RawHIDWriteThread; /** -* The actual IO device that will be used to communicate -* with the board. -*/ -class OPHID_EXPORT RawHID : public QIODevice -{ + * The actual IO device that will be used to communicate + * with the board. + */ +class OPHID_EXPORT RawHID : public QIODevice { Q_OBJECT friend class RawHIDReadThread; @@ -72,10 +71,10 @@ protected: virtual qint64 bytesAvailable() const; virtual qint64 bytesToWrite() const; - //! Callback from the read thread to open the device + // Callback from the read thread to open the device bool openDevice(); - //! Callback from teh read thread to close the device + // Callback from teh read thread to close the device bool closeDevice(); QString serialNumber; @@ -92,4 +91,3 @@ protected: }; #endif // OPHID_H - diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_const.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_const.h index bef7341ac..9a2e12fbb 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_const.h +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_const.h @@ -28,39 +28,37 @@ #ifndef OPHID_CONST_H #define OPHID_CONST_H -#define printf qDebug +#define printf qDebug #define OPHID_DEBUG_ON 1 #ifdef OPHID_DEBUG_ON -#define OPHID_DEBUG(fmt, args...) qDebug("[DEBUG] "fmt, ## args) -#define OPHID_TRACE(fmt, args...) qDebug("[TRACE] %s:%s:%d: "fmt, __FILE__, __func__, __LINE__, ## args) -#define OPHID_ERROR(fmt, args...) qDebug("[ERROR] %s:%s:%d: "fmt, __FILE__, __func__, __LINE__, ## args) -#define OPHID_WARNING(fmt, args...) qDebug("[WARNING] "fmt, ## args) +#define OPHID_DEBUG(fmt, args ...) qDebug("[DEBUG] "fmt,##args) +#define OPHID_TRACE(fmt, args ...) qDebug("[TRACE] %s:%s:%d: "fmt, __FILE__, __func__, __LINE__,##args) +#define OPHID_ERROR(fmt, args ...) qDebug("[ERROR] %s:%s:%d: "fmt, __FILE__, __func__, __LINE__,##args) +#define OPHID_WARNING(fmt, args ...) qDebug("[WARNING] "fmt,##args) #else -#define OPHID_DEBUG(fmt, args...) -#define OPHID_TRACE(fmt, args...) -#define OPHID_ERROR(fmt, args...) -#define OPHID_WARNING(fmt, args...) +#define OPHID_DEBUG(fmt, args ...) +#define OPHID_TRACE(fmt, args ...) +#define OPHID_ERROR(fmt, args ...) +#define OPHID_WARNING(fmt, args ...) #endif - // USB -#define USB_MAX_DEVICES 10 -#define USB_VID 0x20A0 -#define USB_PID 0x4117 -#define USB_USAGE_PAGE 0xFF9C -#define USB_USAGE 0x0001 -#define USB_DEV_SERIAL_LEN 24 -#define USB_PID_ANY -1 -#define USB_MAX_STRING_SIZE 255 +#define USB_MAX_DEVICES 10 +#define USB_VID 0x20A0 +#define USB_PID 0x4117 +#define USB_USAGE_PAGE 0xFF9C +#define USB_USAGE 0x0001 +#define USB_DEV_SERIAL_LEN 24 +#define USB_PID_ANY -1 +#define USB_MAX_STRING_SIZE 255 // ERROR -#define OPHID_NO_ERROR 0 -#define OPHID_ERROR_RET -1 -#define OPHID_ERROR_POINTER -2 -#define OPHID_ERROR_PARAMETER -3 -#define OPHID_ERROR_HANDLE -4 -#define OPHID_ERROR_INIT -5 +#define OPHID_NO_ERROR 0 +#define OPHID_ERROR_RET -1 +#define OPHID_ERROR_POINTER -2 +#define OPHID_ERROR_PARAMETER -3 +#define OPHID_ERROR_HANDLE -4 +#define OPHID_ERROR_INIT -5 #endif // OPHID_CONST_H - diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_global.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_global.h index a1266a946..a08279318 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_global.h +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_global.h @@ -10,18 +10,18 @@ * @brief Impliments a HID USB connection to the flight hardware as a QIODevice *****************************************************************************/ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -37,4 +37,3 @@ #endif #endif // OPHID_GLOBAL_H - diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h index 36379c274..3151917db 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h @@ -41,10 +41,8 @@ #include "opHID_global.h" -class OPHID_EXPORT opHID_hidapi: public QObject -{ - - Q_OBJECT +class OPHID_EXPORT opHID_hidapi : public QObject { + Q_OBJECT public: @@ -64,7 +62,7 @@ public: private: - int enumerate(struct hid_device_info **current_device_pptr, int *devices_found); + int enumerate(struct hid_device_info * *current_device_pptr, int *devices_found); hid_device *handle; @@ -78,4 +76,4 @@ signals: void deviceUnplugged(int); }; -#endif +#endif // ifndef OPHID_HIDAPI_H diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_plugin.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_plugin.h index d62b2076a..37f08d2a5 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_plugin.h +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_plugin.h @@ -10,18 +10,18 @@ * @brief Impliments a HID USB connection to the flight hardware as a QIODevice *****************************************************************************/ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -42,12 +42,11 @@ class RawHIDConnection; /** -* Define a connection via the IConnection interface -* Plugin will add a instance of this class to the pool, -* so the connection manager can use it. -*/ -class OPHID_EXPORT RawHIDConnection: public Core::IConnection -{ + * Define a connection via the IConnection interface + * Plugin will add a instance of this class to the pool, + * so the connection manager can use it. + */ +class OPHID_EXPORT RawHIDConnection : public Core::IConnection { Q_OBJECT public: @@ -63,7 +62,10 @@ public: virtual void suspendPolling(); virtual void resumePolling(); - bool deviceOpened() { return (RawHidHandle != NULL); } // Pip + bool deviceOpened() + { + return RawHidHandle != NULL; + } // Pip protected slots: void onDeviceConnected(); @@ -75,13 +77,12 @@ private: protected: QMutex m_enumMutex; - USBMonitor* m_usbMonitor; + USBMonitor *m_usbMonitor; bool m_deviceOpened; }; class OPHID_EXPORT RawHIDPlugin - : public ExtensionSystem::IPlugin -{ + : public ExtensionSystem::IPlugin { Q_OBJECT public: @@ -93,9 +94,7 @@ public: private: RawHIDConnection *hidConnection; - USBMonitor* m_usbMonitor; - + USBMonitor *m_usbMonitor; }; #endif // OPHID_PLUGIN_H - diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h index 2a514904a..7a991ea00 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h @@ -34,28 +34,28 @@ #include // Arch dependent -#if defined( Q_OS_MAC) +#if defined(Q_OS_MAC) #include #include #elif defined(Q_OS_UNIX) #include #include -#elif defined (Q_OS_WIN32) +#elif defined(Q_OS_WIN32) #ifndef _WIN32_WINNT - #define _WIN32_WINNT 0x0500 + #define _WIN32_WINNT 0x0500 #endif #ifndef _WIN32_WINDOWS #define _WIN32_WINDOWS 0x0500 #endif #ifndef WINVER - #define WINVER 0x0500 + #define WINVER 0x0500 #endif #include #include #include #include #include -#endif +#endif // if defined(Q_OS_MAC) #ifdef Q_OS_WIN @@ -63,60 +63,59 @@ #include class USBMonitor; -class USBRegistrationWidget : public QWidget -{ +class USBRegistrationWidget : public QWidget { Q_OBJECT public: - USBRegistrationWidget( USBMonitor* qese ) { + USBRegistrationWidget(USBMonitor *qese) + { this->qese = qese; } - ~USBRegistrationWidget( ) {} + ~USBRegistrationWidget() {} protected: - USBMonitor* qese; - bool winEvent( MSG* message, long* result ); + USBMonitor *qese; + bool winEvent(MSG *message, long *result); }; #endif #endif struct USBPortInfo { - //QString friendName; ///< Friendly name. - //QString physName; - //QString enumName; ///< It seems its the only one with meaning + // QString friendName; ///< Friendly name. + // QString physName; + // QString enumName; ///< It seems its the only one with meaning QString serialNumber; // As a string as it can be anything, really... QString manufacturer; QString product; #if defined(Q_OS_WIN32) - QString devicePath; //only has meaning on windows + QString devicePath; // only has meaning on windows #elif defined(Q_OS_MAC) IOHIDDeviceRef dev_handle; #endif int UsagePage; int Usage; - int vendorID; ///< Vendor ID. - int productID; ///< Product ID + int vendorID; ///< Vendor ID. + int productID; ///< Product ID int bcdDevice; }; /** -* A monitoring thread which will wait for device events. -*/ + * A monitoring thread which will wait for device events. + */ -class OPHID_EXPORT USBMonitor : public QThread -{ +class OPHID_EXPORT USBMonitor : public QThread { Q_OBJECT public: enum RunState { Bootloader = 0x01, - Running = 0x02 + Running = 0x02 }; enum USBConstants { - idVendor_OpenPilot = 0x20a0, - idProduct_OpenPilot = 0x415a, + idVendor_OpenPilot = 0x20a0, + idProduct_OpenPilot = 0x415a, idProduct_CopterControl = 0x415b, - idProduct_PipXtreme = 0x415c + idProduct_PipXtreme = 0x415c }; static USBMonitor *instance(); @@ -125,54 +124,54 @@ public: ~USBMonitor(); QList availableDevices(); QList availableDevices(int vid, int pid, int boardModel, int runState); -#if defined (Q_OS_WIN32) - LRESULT onDeviceChangeWin( WPARAM wParam, LPARAM lParam ); +#if defined(Q_OS_WIN32) + LRESULT onDeviceChangeWin(WPARAM wParam, LPARAM lParam); #endif signals: /*! - A new device has been connected to the system. + A new device has been connected to the system. - setUpNotifications() must be called first to enable event-driven device notifications. - Currently only implemented on Windows and OS X. - \param info The device that has been discovered. - */ - void deviceDiscovered( const USBPortInfo & info ); + setUpNotifications() must be called first to enable event-driven device notifications. + Currently only implemented on Windows and OS X. + \param info The device that has been discovered. + */ + void deviceDiscovered(const USBPortInfo & info); #ifdef __APPLE__ - void deviceDiscovered(); + void deviceDiscovered(); #endif // __APPLE__ - /*! - A device has been disconnected from the system. + /*! + A device has been disconnected from the system. - setUpNotifications() must be called first to enable event-driven device notifications. - Currently only implemented on Windows and OS X. - \param info The device that was disconnected. - */ - void deviceRemoved( const USBPortInfo & info ); + setUpNotifications() must be called first to enable event-driven device notifications. + Currently only implemented on Windows and OS X. + \param info The device that was disconnected. + */ + void deviceRemoved(const USBPortInfo & info); #ifdef __APPLE__ - void deviceRemoved(); + void deviceRemoved(); #endif // __APPLE__ private slots: /** - Callback available for whenever the system that is put in place gets - an event + Callback available for whenever the system that is put in place gets + an event */ void deviceEventReceived(); private: - //! Mutex for modifying the list of available devices - QMutex * listMutex; + // ! Mutex for modifying the list of available devices + QMutex *listMutex; - //! List of known devices maintained by callbacks + // ! List of known devices maintained by callbacks QList knowndevices; Q_DISABLE_COPY(USBMonitor) - static USBMonitor *m_instance; + static USBMonitor * m_instance; // Depending on the OS, we'll need different things: -#if defined( Q_OS_MAC) +#if defined(Q_OS_MAC) static void attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev); static void detach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev); void addDevice(USBPortInfo info); @@ -183,10 +182,10 @@ private: struct udev_monitor *monitor; QSocketNotifier *monitorNotifier; USBPortInfo makePortInfo(struct udev_device *dev); -#elif defined (Q_OS_WIN32) +#elif defined(Q_OS_WIN32) GUID guid_hid; void setUpNotifications(); - /*! + /*! * Get specific property from registry. * \param devInfo pointer to the device information set that contains the interface * and its underlying device. Returned by SetupDiGetClassDevs() function. @@ -196,21 +195,19 @@ private: * \return property string. */ static QString getDeviceProperty(HDEVINFO devInfo, PSP_DEVINFO_DATA devData, DWORD property); - static int infoFromHandle(const GUID & guid,USBPortInfo & info,HDEVINFO & devInfo,DWORD & index); - static void enumerateDevicesWin( const GUID & guidDev, QList* infoList ); + static int infoFromHandle(const GUID & guid, USBPortInfo & info, HDEVINFO & devInfo, DWORD & index); + static void enumerateDevicesWin(const GUID & guidDev, QList *infoList); bool matchAndDispatchChangedDevice(const QString & deviceID, const GUID & guid, WPARAM wParam); #ifdef QT_GUI_LIB - USBRegistrationWidget* notificationWidget; -#endif + USBRegistrationWidget *notificationWidget; #endif +#endif // if defined(Q_OS_MAC) #ifdef __APPLE__ protected: - bool m_terminate; + bool m_terminate; - void run(); + void run(); #endif // __APPLE__ - }; #endif // OPHID_USBMON_H - diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbsignal.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbsignal.h index 15a3376a4..221359911 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbsignal.h +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbsignal.h @@ -31,8 +31,7 @@ #include #include "opHID_usbmon.h" -class OPHID_EXPORT USBSignalFilter : public QObject -{ +class OPHID_EXPORT USBSignalFilter : public QObject { Q_OBJECT private: @@ -52,4 +51,3 @@ public: }; #endif // OPHID_USBSIGNAL_H - diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID.cpp b/ground/openpilotgcs/src/plugins/opHID/src/opHID.cpp index 60472f75c..db38ad42d 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID.cpp +++ b/ground/openpilotgcs/src/plugins/opHID/src/opHID.cpp @@ -36,22 +36,20 @@ class IConnection; -//timeout value used when we want to return directly without waiting -static const int READ_TIMEOUT = 200; -static const int READ_SIZE = 64; +// timeout value used when we want to return directly without waiting +static const int READ_TIMEOUT = 200; +static const int READ_SIZE = 64; static const int WRITE_TIMEOUT = 1000; -static const int WRITE_SIZE = 64; - +static const int WRITE_SIZE = 64; // ********************************************************************************* /** -* Thread to desynchronize reading from the device -*/ -class RawHIDReadThread : public QThread -{ + * Thread to desynchronize reading from the device + */ +class RawHIDReadThread : public QThread { public: RawHIDReadThread(RawHID *hid); virtual ~RawHIDReadThread(); @@ -63,7 +61,8 @@ public: qint64 getBytesAvailable(); public slots: - void terminate() { + void terminate() + { m_running = false; } @@ -71,7 +70,7 @@ protected: void run(); /** QByteArray might not be the most efficient way to implement - a circular buffer but it's good enough and very simple */ + a circular buffer but it's good enough and very simple */ QByteArray m_readBuffer; /** A mutex to protect read buffer */ @@ -89,10 +88,9 @@ protected: // ********************************************************************************* /** -* This class is nearly the same than RawHIDReadThread but for writing -*/ -class RawHIDWriteThread : public QThread -{ + * This class is nearly the same than RawHIDReadThread but for writing + */ +class RawHIDWriteThread : public QThread { public: RawHIDWriteThread(RawHID *hid); virtual ~RawHIDWriteThread(); @@ -104,7 +102,8 @@ public: qint64 getBytesToWrite(); public slots: - void terminate() { + void terminate() + { m_running = false; } @@ -112,7 +111,7 @@ protected: void run(); /** QByteArray might not be the most efficient way to implement - a circular buffer but it's good enough and very simple */ + a circular buffer but it's good enough and very simple */ QByteArray m_writeBuffer; /** A mutex to protect read buffer */ @@ -145,9 +144,10 @@ RawHIDReadThread::RawHIDReadThread(RawHID *hid) RawHIDReadThread::~RawHIDReadThread() { m_running = false; - //wait for the thread to terminate - if(wait(10000) == false) + // wait for the thread to terminate + if (wait(10000) == false) { qDebug() << "Cannot terminate RawHIDReadThread"; + } } void RawHIDReadThread::run() @@ -156,35 +156,29 @@ void RawHIDReadThread::run() m_running = m_hid->openDevice(); - while(m_running) - { - //here we use a temporary buffer so we don't need to lock - //the mutex while we are reading from the device + while (m_running) { + // here we use a temporary buffer so we don't need to lock + // the mutex while we are reading from the device // Want to read in regular chunks that match the packet size the device // is using. In this case it is 64 bytes (the interrupt packet limit) // although it would be nice if the device had a different report to // configure this - char buffer[READ_SIZE] = {0}; + char buffer[READ_SIZE] = { 0 }; int ret = hiddev->receive(hidno, buffer, READ_SIZE, READ_TIMEOUT); - if(ret > 0) //read some data - { + if (ret > 0) { // read some data QMutexLocker lock(&m_readBufMtx); // Note: Preprocess the USB packets in this OS independent code // First byte is report ID, second byte is the number of valid bytes m_readBuffer.append(&buffer[2], buffer[1]); emit m_hid->readyRead(); - } - else if(ret == 0) //nothing read - { - } - else // < 0 => error - { - //TODO! make proper error handling, this only quick hack for unplug freeze - m_running=false; + } else if (ret == 0) { // nothing read + } else { // < 0 => error + // TODO! make proper error handling, this only quick hack for unplug freeze + m_running = false; } } m_hid->closeDevice(); @@ -207,6 +201,7 @@ int RawHIDReadThread::getReadData(char *data, int size) qint64 RawHIDReadThread::getBytesAvailable() { QMutexLocker lock(&m_readBufMtx); + return m_readBuffer.size(); } @@ -215,66 +210,60 @@ RawHIDWriteThread::RawHIDWriteThread(RawHID *hid) hiddev(&hid->dev), hidno(hid->m_deviceNo), m_running(true) -{ -} +{} // ********************************************************************************* RawHIDWriteThread::~RawHIDWriteThread() { m_running = false; - //wait for the thread to terminate - if(wait(10000) == false) + // wait for the thread to terminate + if (wait(10000) == false) { qDebug() << "Cannot terminate RawHIDReadThread"; + } } void RawHIDWriteThread::run() { - while(m_running) - { - char buffer[WRITE_SIZE] = {0}; + while (m_running) { + char buffer[WRITE_SIZE] = { 0 }; m_writeBufMtx.lock(); - int size = qMin(WRITE_SIZE-2, m_writeBuffer.size()); - while(size <= 0) - { - //wait on new data to write condition, the timeout - //enable the thread to shutdown properly + int size = qMin(WRITE_SIZE - 2, m_writeBuffer.size()); + while (size <= 0) { + // wait on new data to write condition, the timeout + // enable the thread to shutdown properly m_newDataToWrite.wait(&m_writeBufMtx, 200); - if(!m_running) + if (!m_running) { return; + } size = m_writeBuffer.size(); } - //NOTE: data size is limited to 2 bytes less than the - //usb packet size (64 bytes for interrupt) to make room - //for the reportID and valid data length - size = qMin(WRITE_SIZE-2, m_writeBuffer.size()); + // NOTE: data size is limited to 2 bytes less than the + // usb packet size (64 bytes for interrupt) to make room + // for the reportID and valid data length + size = qMin(WRITE_SIZE - 2, m_writeBuffer.size()); memcpy(&buffer[2], m_writeBuffer.constData(), size); - buffer[1] = size; //valid data length - buffer[0] = 2; //reportID + buffer[1] = size; // valid data length + buffer[0] = 2; // reportID m_writeBufMtx.unlock(); // must hold lock through the send to know how much was sent int ret = hiddev->send(hidno, buffer, WRITE_SIZE, WRITE_TIMEOUT); - if(ret > 0) - { - //only remove the size actually written to the device + if (ret > 0) { + // only remove the size actually written to the device QMutexLocker lock(&m_writeBufMtx); m_writeBuffer.remove(0, size); emit m_hid->bytesWritten(ret - 2); - } - else if(ret < 0) // < 0 => error - { - //TODO! make proper error handling, this only quick hack for unplug freeze - m_running=false; + } else if (ret < 0) { // < 0 => error + // TODO! make proper error handling, this only quick hack for unplug freeze + m_running = false; qDebug() << "Error writing to device (" << ret << ")"; - } - else - { + } else { qDebug() << "No data written to device ??"; } } @@ -285,7 +274,7 @@ int RawHIDWriteThread::pushDataToWrite(const char *data, int size) QMutexLocker lock(&m_writeBufMtx); m_writeBuffer.append(data, size); - m_newDataToWrite.wakeOne(); //signal that new data arrived + m_newDataToWrite.wakeOne(); // signal that new data arrived return size; } @@ -299,12 +288,12 @@ qint64 RawHIDWriteThread::getBytesToWrite() // ********************************************************************************* RawHID::RawHID(const QString &deviceName) - :QIODevice(), + : QIODevice(), serialNumber(deviceName), m_deviceNo(-1), m_readThread(NULL), - m_writeThread(NULL), - m_mutex(NULL) + m_writeThread(NULL), + m_mutex(NULL) { OPHID_TRACE("IN"); @@ -334,18 +323,19 @@ RawHID::RawHID(const QString &deviceName) * system code is registered in that thread instead of the calling * thread (usually UI) */ -bool RawHID::openDevice() { - +bool RawHID::openDevice() +{ OPHID_TRACE("IN"); uint32_t opened = dev.open(USB_MAX_DEVICES, USB_VID, USB_PID_ANY, USB_USAGE_PAGE, USB_USAGE); OPHID_DEBUG("opened %d devices", opened); - for (uint32_t i=0; i < opened; i++) { - if (serialNumber == dev.getserial(i)) + for (uint32_t i = 0; i < opened; i++) { + if (serialNumber == dev.getserial(i)) { m_deviceNo = i; - else + } else { dev.close(i); + } } // Now things are opened or not (from read thread) allow the constructor to complete @@ -353,8 +343,7 @@ bool RawHID::openDevice() { // Leave if we have not found one device // It should be the one we are looking for - if (!opened) - { + if (!opened) { OPHID_TRACE("OUT"); return false; } @@ -370,8 +359,8 @@ bool RawHID::openDevice() { * It is uses as a callback from the read thread so that the USB * system code is unregistered from that thread\ */ -bool RawHID::closeDevice() { - +bool RawHID::closeDevice() +{ OPHID_TRACE("IN"); dev.close(m_deviceNo); @@ -383,19 +372,21 @@ bool RawHID::closeDevice() { RawHID::~RawHID() { -// OPHID_TRACE("IN"); +// OPHID_TRACE("IN"); // If the read thread exists then the device is open - if (m_readThread) + if (m_readThread) { close(); + } - // OPHID_TRACE("OUT"); + // OPHID_TRACE("OUT"); } void RawHID::onDeviceUnplugged(int num) { - if (num != m_deviceNo) + if (num != m_deviceNo) { return; + } // The USB device has been unplugged close(); @@ -405,15 +396,20 @@ bool RawHID::open(OpenMode mode) { QMutexLocker locker(m_mutex); - if (m_deviceNo < 0) + if (m_deviceNo < 0) { return false; + } QIODevice::open(mode); Q_ASSERT(m_readThread); Q_ASSERT(m_writeThread); - if (m_readThread) m_readThread->start(); - if (m_writeThread) m_writeThread->start(); + if (m_readThread) { + m_readThread->start(); + } + if (m_writeThread) { + m_writeThread->start(); + } return true; } @@ -424,8 +420,7 @@ void RawHID::close() emit aboutToClose(); - if (m_writeThread) - { + if (m_writeThread) { OPHID_DEBUG("Terminating write thread"); m_writeThread->terminate(); delete m_writeThread; @@ -434,8 +429,7 @@ void RawHID::close() } - if (m_readThread) - { + if (m_readThread) { OPHID_DEBUG("Terminating read thread"); m_readThread->terminate(); delete m_readThread; @@ -459,8 +453,9 @@ qint64 RawHID::bytesAvailable() const { QMutexLocker locker(m_mutex); - if (!m_readThread) + if (!m_readThread) { return -1; + } return m_readThread->getBytesAvailable() + QIODevice::bytesAvailable(); } @@ -469,8 +464,9 @@ qint64 RawHID::bytesToWrite() const { QMutexLocker locker(m_mutex); - if (!m_writeThread) + if (!m_writeThread) { return -1; + } return m_writeThread->getBytesToWrite() + QIODevice::bytesToWrite(); } @@ -479,8 +475,9 @@ qint64 RawHID::readData(char *data, qint64 maxSize) { QMutexLocker locker(m_mutex); - if (!m_readThread || !data) + if (!m_readThread || !data) { return -1; + } return m_readThread->getReadData(data, maxSize); } @@ -489,9 +486,9 @@ qint64 RawHID::writeData(const char *data, qint64 maxSize) { QMutexLocker locker(m_mutex); - if (!m_writeThread || !data) + if (!m_writeThread || !data) { return -1; + } return m_writeThread->pushDataToWrite(data, maxSize); } - diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_hidapi.cpp b/ground/openpilotgcs/src/plugins/opHID/src/opHID_hidapi.cpp index 6f6d837d7..8c214612e 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID_hidapi.cpp +++ b/ground/openpilotgcs/src/plugins/opHID/src/opHID_hidapi.cpp @@ -34,11 +34,11 @@ #include "opHID_hidapi.h" /** -* \brief Constructor -* -* \note -* -*/ + * \brief Constructor + * + * \note + * + */ opHID_hidapi::opHID_hidapi() { OPHID_TRACE("IN"); @@ -46,19 +46,20 @@ opHID_hidapi::opHID_hidapi() handle = NULL; // Make sure hidapi lib is ready - if (hid_init()) + if (hid_init()) { OPHID_ERROR("Lib initialization (hidpai)."); + } OPHID_TRACE("OUT"); } /** -* \brief Destructor -* -* \note This does not handle the cleanup of hidapi lib -* -*/ + * \brief Destructor + * + * \note This does not handle the cleanup of hidapi lib + * + */ opHID_hidapi::~opHID_hidapi() { OPHID_TRACE("IN"); @@ -68,33 +69,33 @@ opHID_hidapi::~opHID_hidapi() /** -* \brief Enumerate the list of HID device with our vendor id -* -* \note Why don't we use the one from within the hidapi directly -* in caller? because later we will do more parsing herer. -* WARNING: our vendor id is harcoded here (not good idea). -* -* \param[out] current_device_pptr Pointer to the list of device -* \param[out] devices_found Number of devices found. -* \return error. -* \retval 0 on success. -*/ -int opHID_hidapi::enumerate(struct hid_device_info **current_device_pptr, int *devices_found) + * \brief Enumerate the list of HID device with our vendor id + * + * \note Why don't we use the one from within the hidapi directly + * in caller? because later we will do more parsing herer. + * WARNING: our vendor id is harcoded here (not good idea). + * + * \param[out] current_device_pptr Pointer to the list of device + * \param[out] devices_found Number of devices found. + * \return error. + * \retval 0 on success. + */ +int opHID_hidapi::enumerate(struct hid_device_info * *current_device_pptr, int *devices_found) { int retry = 5; + *devices_found = 0; struct hid_device_info *current_device_ptr = NULL; OPHID_TRACE("IN"); - while(retry--) - { - // Enumerate + while (retry--) { + // Enumerate *current_device_pptr = hid_enumerate(USB_VID, 0x0); // Display the list of devices found (for debug) - current_device_ptr = *current_device_pptr; + current_device_ptr = *current_device_pptr; while (current_device_ptr) { OPHID_DEBUG("HID Device Found"); @@ -106,8 +107,9 @@ int opHID_hidapi::enumerate(struct hid_device_info **current_device_pptr, int *d (*devices_found)++; } - if (*devices_found) + if (*devices_found) { break; + } } OPHID_TRACE("OUT"); @@ -116,90 +118,80 @@ int opHID_hidapi::enumerate(struct hid_device_info **current_device_pptr, int *d /** -* \brief Open HID device using hidapi library -* -* \note This function does \b not support opening multiple devices at once. -* -* \param[in] vid USB vendor id of the device to open (-1 for any). -* \param[in] pid USB product id of the device to open (-1 for any). -* \return Number of opened device. -* \retval 0 or 1. -*/ + * \brief Open HID device using hidapi library + * + * \note This function does \b not support opening multiple devices at once. + * + * \param[in] vid USB vendor id of the device to open (-1 for any). + * \param[in] pid USB product id of the device to open (-1 for any). + * \return Number of opened device. + * \retval 0 or 1. + */ int opHID_hidapi::open(int max, int vid, int pid, int usage_page, int usage) { int devices_found = false; - struct hid_device_info *current_device_ptr = NULL; - struct hid_device_info *last_device_ptr = NULL; - struct hid_device_info **current_device_pptr = ¤t_device_ptr; + struct hid_device_info *current_device_ptr = NULL; + struct hid_device_info *last_device_ptr = NULL; + struct hid_device_info * *current_device_pptr = ¤t_device_ptr; OPHID_TRACE("IN"); OPHID_DEBUG("max: %d, vid: 0x%X, pid: 0x%X, usage_page: %d, usage: %d.", max, vid, pid, usage_page, usage); - if (handle) - { + if (handle) { OPHID_WARNING("HID device seems already open."); } // This is a hack to prevent changing all the callers (for now) - if (vid == -1) + if (vid == -1) { vid = 0; - if (pid == -1) + } + if (pid == -1) { pid = 0; + } // If caller knows which one to look for open it right away - if (vid != 0 && pid != 0) - { + if (vid != 0 && pid != 0) { handle = hid_open(vid, pid, NULL); - if (!handle) - { + if (!handle) { OPHID_ERROR("Unable to open device."); devices_found = false; - } - else - { + } else { OPHID_DEBUG("HID Device Found"); OPHID_DEBUG(" type:............VID(%04hx).PID(%04hx)", vid, pid); devices_found = true; } - } - else - { + } else { // Get the list of available hid devices - if (enumerate(current_device_pptr, &devices_found) != OPHID_NO_ERROR) - { + if (enumerate(current_device_pptr, &devices_found) != OPHID_NO_ERROR) { OPHID_ERROR("Error during enumeration"); return 0; } - if (devices_found) - { + if (devices_found) { // Look for the last one in the list // WARNING: for now this prevent to have devices chained last_device_ptr = current_device_ptr; - while (last_device_ptr->next) + while (last_device_ptr->next) { last_device_ptr = last_device_ptr->next; + } + + OPHID_DEBUG("Opening device VID(%04hx).PID(%04hx)", + last_device_ptr->vendor_id, + last_device_ptr->product_id); - OPHID_DEBUG("Opening device VID(%04hx).PID(%04hx)", - last_device_ptr->vendor_id, - last_device_ptr->product_id); - handle = hid_open(last_device_ptr->vendor_id, - last_device_ptr->product_id, + last_device_ptr->product_id, NULL); hid_free_enumeration(current_device_ptr); - if (!handle) - { - OPHID_ERROR("Unable to open device."); + if (!handle) { + OPHID_ERROR("Unable to open device."); devices_found = false; } - - } - else - { + } else { OPHID_WARNING("Unable to find any HID device."); } } @@ -208,23 +200,23 @@ int opHID_hidapi::open(int max, int vid, int pid, int usage_page, int usage) OPHID_TRACE("OUT"); - return devices_found; + return devices_found; } /** -* \brief Read an Input report from a HID device. -* -* \note This function does \b not block for now. -* Tests show that it does not need to. -* -* \param[in] num Id of the device to receive packet (NOT supported). -* \param[in] buf Pointer to the bufer to write the received packet to. -* \param[in] len Size of the buffer. -* \param[in] timeout Not supported. -* \return Number of bytes received, or -1 on error. -* \retval -1 for error or bytes received. -*/ + * \brief Read an Input report from a HID device. + * + * \note This function does \b not block for now. + * Tests show that it does not need to. + * + * \param[in] num Id of the device to receive packet (NOT supported). + * \param[in] buf Pointer to the bufer to write the received packet to. + * \param[in] len Size of the buffer. + * \param[in] timeout Not supported. + * \return Number of bytes received, or -1 on error. + * \retval -1 for error or bytes received. + */ int opHID_hidapi::receive(int num, void *buf, int len, int timeout) { Q_UNUSED(num); @@ -232,50 +224,46 @@ int opHID_hidapi::receive(int num, void *buf, int len, int timeout) int bytes_read = 0; - if (!buf) - { + if (!buf) { OPHID_ERROR("Unexpected parameter value (ptr)."); return OPHID_ERROR_POINTER; } - if (!len) - { + if (!len) { OPHID_ERROR("Unexpected parameter value (incorrect lenght)."); return OPHID_ERROR_PARAMETER; } - if (handle == NULL) - { + if (handle == NULL) { OPHID_ERROR("Handle invalid."); return OPHID_ERROR_HANDLE; } hid_read_Mtx.lock(); - bytes_read = hid_read(handle, (unsigned char*)buf, len); + bytes_read = hid_read(handle, (unsigned char *)buf, len); hid_read_Mtx.unlock(); // hidapi lib does not expose the libusb errors. - if (bytes_read == -1) - { + if (bytes_read == -1) { OPHID_ERROR("hidapi: %d", bytes_read); } - + return bytes_read; } /** -* \brief Write an Output report to a HID device. -* -* \note timeout is 1000ms for control transfer and -* 1000 ms for interrupt transfer. -* -* \param[in] num Id of the device to receive packet (NOT supported). -* \param[in] buf Pointer to the bufer to send. -* \param[in] len Size of the buffer. -* \param[in] timeout (not supported). -* \return Number of bytes received, or -1 on error. -* \retval -1 for error or bytes received. -*/ + * \brief Write an Output report to a HID device. + * + * \note timeout is 1000ms for control transfer and + * 1000 ms for interrupt transfer. + * + * \param[in] num Id of the device to receive packet (NOT supported). + * \param[in] buf Pointer to the bufer to send. + * \param[in] len Size of the buffer. + * \param[in] timeout (not supported). + * \return Number of bytes received, or -1 on error. + * \retval -1 for error or bytes received. + */ int opHID_hidapi::send(int num, void *buf, int len, int timeout) { Q_UNUSED(num); @@ -284,39 +272,33 @@ int opHID_hidapi::send(int num, void *buf, int len, int timeout) int bytes_written = 0; int retry = 5; - if (!buf) - { - OPHID_ERROR("Unexpected parameter value (ptr)."); + if (!buf) { + OPHID_ERROR("Unexpected parameter value (ptr)."); return OPHID_ERROR_POINTER; } - if (!len) - { + if (!len) { OPHID_ERROR("Unexpected parameter value (incorrect lenght)."); return OPHID_ERROR_PARAMETER; } - if (handle == NULL) - { + if (handle == NULL) { OPHID_ERROR("Handle invalid."); return OPHID_ERROR_HANDLE; } // hidapi has a timeout hardcoded to 1000ms, retry 5 times - while(retry--) - { + while (retry--) { hid_write_Mtx.lock(); - bytes_written = hid_write(handle, (const unsigned char*)buf, len); + bytes_written = hid_write(handle, (const unsigned char *)buf, len); hid_write_Mtx.unlock(); - if (bytes_written >= 0) - { + if (bytes_written >= 0) { break; } } // hidapi lib does not expose the libusb errors. - if (bytes_written < 0) - { + if (bytes_written < 0) { OPHID_ERROR("hidapi: %d", bytes_written); } @@ -325,16 +307,16 @@ int opHID_hidapi::send(int num, void *buf, int len, int timeout) /** -* \brief Return the serial number of a device. -* -* \note This function does \b not handle multiple -* HID devices. Only the serial number of the -* current HID device will supported. -* -* \param[in] num Id of the device to request SN (NOT supported). -* \return Serial number -* \retval string -*/ + * \brief Return the serial number of a device. + * + * \note This function does \b not handle multiple + * HID devices. Only the serial number of the + * current HID device will supported. + * + * \param[in] num Id of the device to request SN (NOT supported). + * \return Serial number + * \retval string + */ QString opHID_hidapi::getserial(int num) { Q_UNUSED(num); @@ -342,43 +324,41 @@ QString opHID_hidapi::getserial(int num) OPHID_TRACE("IN"); wchar_t buf[USB_MAX_STRING_SIZE]; - - if (handle == NULL) - { + + if (handle == NULL) { OPHID_ERROR("Handle invalid."); return QString(""); } - if (hid_get_serial_number_string(handle, buf, USB_MAX_STRING_SIZE) < 0) - { + if (hid_get_serial_number_string(handle, buf, USB_MAX_STRING_SIZE) < 0) { OPHID_ERROR("Unable to read serial number string."); return QString(""); } - + OPHID_TRACE("OUT"); return QString().fromWCharArray(buf); } /** -* \brief Close a HID device -* -* \note This function does \b not handle multiple -* HID devices currently. -* -* \param[in] num Id of the device to close (NOT supported). -*/ + * \brief Close a HID device + * + * \note This function does \b not handle multiple + * HID devices currently. + * + * \param[in] num Id of the device to close (NOT supported). + */ void opHID_hidapi::close(int num) { Q_UNUSED(num); OPHID_TRACE("IN"); - if (handle) - hid_close(handle); + if (handle) { + hid_close(handle); + } handle = NULL; OPHID_TRACE("OUT"); } - diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_plugin.cpp b/ground/openpilotgcs/src/plugins/opHID/src/opHID_plugin.cpp index 84efc3bfd..d471965b1 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID_plugin.cpp +++ b/ground/openpilotgcs/src/plugins/opHID/src/opHID_plugin.cpp @@ -10,18 +10,18 @@ * @brief Impliments a HID USB connection to the flight hardware as a QIODevice *****************************************************************************/ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -37,49 +37,50 @@ /** -* \brief Constructor -* -* \note -* -*/ + * \brief Constructor + * + * \note + * + */ RawHIDConnection::RawHIDConnection() { - RawHidHandle = NULL; + RawHidHandle = NULL; enablePolling = true; - m_usbMonitor = USBMonitor::instance(); + m_usbMonitor = USBMonitor::instance(); #ifndef __APPLE__ - connect(m_usbMonitor, SIGNAL(deviceDiscovered(USBPortInfo)), this, SLOT(onDeviceConnected())); - connect(m_usbMonitor, SIGNAL(deviceRemoved(USBPortInfo)), this, SLOT(onDeviceDisconnected())); + connect(m_usbMonitor, SIGNAL(deviceDiscovered(USBPortInfo)), this, SLOT(onDeviceConnected())); + connect(m_usbMonitor, SIGNAL(deviceRemoved(USBPortInfo)), this, SLOT(onDeviceDisconnected())); #else - connect(m_usbMonitor, SIGNAL(deviceDiscovered()), this, SLOT(onDeviceConnected())); - connect(m_usbMonitor, SIGNAL(deviceRemoved()), this, SLOT(onDeviceDisconnected())); + connect(m_usbMonitor, SIGNAL(deviceDiscovered()), this, SLOT(onDeviceConnected())); + connect(m_usbMonitor, SIGNAL(deviceRemoved()), this, SLOT(onDeviceDisconnected())); #endif - } /** -* \brief Destructor -* -* \note -* -*/ + * \brief Destructor + * + * \note + * + */ RawHIDConnection::~RawHIDConnection() { - if (RawHidHandle) - if (RawHidHandle->isOpen()) - RawHidHandle->close(); + if (RawHidHandle) { + if (RawHidHandle->isOpen()) { + RawHidHandle->close(); + } + } } /** -* \brief New device plugged -* -* \note The USB monitor tells us a new device appeared -* -*/ + * \brief New device plugged + * + * \note The USB monitor tells us a new device appeared + * + */ void RawHIDConnection::onDeviceConnected() { emit availableDevChanged(this); @@ -87,35 +88,36 @@ void RawHIDConnection::onDeviceConnected() /** -* \brief Device unplugged -* -* \note The USB monitor tells us a new device disappeared -* -*/ + * \brief Device unplugged + * + * \note The USB monitor tells us a new device disappeared + * + */ void RawHIDConnection::onDeviceDisconnected() { qDebug() << "onDeviceDisconnected()"; - if (enablePolling) + if (enablePolling) { emit availableDevChanged(this); + } } /** -* \brief Available devices -* -* \return List of all currently available devices -*/ + * \brief Available devices + * + * \return List of all currently available devices + */ QList < Core::IConnection::device> RawHIDConnection::availableDevices() { QList < Core::IConnection::device> devices; - QList portsList = m_usbMonitor->availableDevices(USBMonitor::idVendor_OpenPilot, -1, -1,USBMonitor::Running); + QList portsList = m_usbMonitor->availableDevices(USBMonitor::idVendor_OpenPilot, -1, -1, USBMonitor::Running); // We currently list devices by their serial number device dev; foreach(USBPortInfo prt, portsList) { - dev.name=prt.serialNumber; - dev.displayName=prt.product; + dev.name = prt.serialNumber; + dev.displayName = prt.product; devices.append(dev); } return devices; @@ -123,22 +125,22 @@ QList < Core::IConnection::device> RawHIDConnection::availableDevices() /** -* \brief Open device -* -* \param[in] deviceName String name of the device to open -* \return initialized handle -*/ + * \brief Open device + * + * \param[in] deviceName String name of the device to open + * \return initialized handle + */ QIODevice *RawHIDConnection::openDevice(const QString &deviceName) { OPHID_TRACE("IN"); - if (RawHidHandle) + if (RawHidHandle) { closeDevice(deviceName); + } RawHidHandle = new RawHID(deviceName); - if (!RawHidHandle) - { + if (!RawHidHandle) { OPHID_ERROR("Could not instentiate HID device"); } @@ -149,18 +151,17 @@ QIODevice *RawHIDConnection::openDevice(const QString &deviceName) /** -* \brief Close device -* -* \param[in] deviceName String name of the device to close -*/ + * \brief Close device + * + * \param[in] deviceName String name of the device to close + */ void RawHIDConnection::closeDevice(const QString &deviceName) { OPHID_TRACE("IN"); Q_UNUSED(deviceName); - if (RawHidHandle) - { + if (RawHidHandle) { OPHID_DEBUG("Closing device"); RawHidHandle->close(); delete RawHidHandle; @@ -172,10 +173,10 @@ void RawHIDConnection::closeDevice(const QString &deviceName) /** -* \brief Get connection name -* -* \return name of the connection -*/ + * \brief Get connection name + * + * \return name of the connection + */ QString RawHIDConnection::connectionName() { return QString("Raw HID USB"); @@ -183,10 +184,10 @@ QString RawHIDConnection::connectionName() /** -* \brief Get shorter connection name -* -* \return shorter name of the connection -*/ + * \brief Get shorter connection name + * + * \return shorter name of the connection + */ QString RawHIDConnection::shortName() { return QString("USB"); @@ -194,10 +195,10 @@ QString RawHIDConnection::shortName() /** -* \brief Suspend polling -* -* \note Tells the Raw HID plugin to stop polling for USB devices -*/ + * \brief Suspend polling + * + * \note Tells the Raw HID plugin to stop polling for USB devices + */ void RawHIDConnection::suspendPolling() { enablePolling = false; @@ -205,10 +206,10 @@ void RawHIDConnection::suspendPolling() /** -* \brief Resume polling -* -* \note Tells the Raw HID plugin to resume polling for USB devices -*/ + * \brief Resume polling + * + * \note Tells the Raw HID plugin to resume polling for USB devices + */ void RawHIDConnection::resumePolling() { enablePolling = true; @@ -216,23 +217,23 @@ void RawHIDConnection::resumePolling() /** -* \brief Plugin Constructor -* -* \note -* -*/ + * \brief Plugin Constructor + * + * \note + * + */ RawHIDPlugin::RawHIDPlugin() { - hidConnection = NULL; // Pip + hidConnection = NULL; // Pip } /** -* \brief Plugin Destructor -* -* \note -* -*/ + * \brief Plugin Destructor + * + * \note + * + */ RawHIDPlugin::~RawHIDPlugin() { m_usbMonitor->quit(); @@ -241,28 +242,28 @@ RawHIDPlugin::~RawHIDPlugin() /** -* \brief Instantiate a connection -* -* \note -* -*/ + * \brief Instantiate a connection + * + * \note + * + */ void RawHIDPlugin::extensionsInitialized() { hidConnection = new RawHIDConnection(); addAutoReleasedObject(hidConnection); - //temp for test - //addAutoReleasedObject(new RawHIDTestThread); + // temp for test + // addAutoReleasedObject(new RawHIDTestThread); } /** -* \brief instantiate the udev monotor engine -* -* \note -* -*/ -bool RawHIDPlugin::initialize(const QStringList & arguments, QString * errorString) + * \brief instantiate the udev monotor engine + * + * \note + * + */ +bool RawHIDPlugin::initialize(const QStringList & arguments, QString *errorString) { Q_UNUSED(arguments); Q_UNUSED(errorString); @@ -274,4 +275,3 @@ bool RawHIDPlugin::initialize(const QStringList & arguments, QString * errorStri } Q_EXPORT_PLUGIN(RawHIDPlugin) - diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_linux.cpp b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_linux.cpp index 1cd404e37..d6aa168f3 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_linux.cpp +++ b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_linux.cpp @@ -31,14 +31,14 @@ /** -* \brief Display device info -* -* \note USB strings are Unicode, UCS2 -* encoded, but the strings returned from -* udev_device_get_sysattr_value() are UTF-8 encoded. -* -* \param[in] dev To display the information of. -*/ + * \brief Display device info + * + * \note USB strings are Unicode, UCS2 + * encoded, but the strings returned from + * udev_device_get_sysattr_value() are UTF-8 encoded. + * + * \param[in] dev To display the information of. + */ void printPortInfo(struct udev_device *dev) { OPHID_DEBUG(" Node: %s", udev_device_get_devnode(dev)); @@ -46,77 +46,74 @@ void printPortInfo(struct udev_device *dev) OPHID_DEBUG(" Devtype: %s", udev_device_get_devtype(dev)); OPHID_DEBUG(" Action: %s", udev_device_get_action(dev)); OPHID_DEBUG(" VID/PID/bcdDevice : %s %s %s", - udev_device_get_sysattr_value(dev,"idVendor"), + udev_device_get_sysattr_value(dev, "idVendor"), udev_device_get_sysattr_value(dev, "idProduct"), - udev_device_get_sysattr_value(dev,"bcdDevice")); + udev_device_get_sysattr_value(dev, "bcdDevice")); OPHID_DEBUG(" %s - %s", - udev_device_get_sysattr_value(dev,"manufacturer"), - udev_device_get_sysattr_value(dev,"product")); + udev_device_get_sysattr_value(dev, "manufacturer"), + udev_device_get_sysattr_value(dev, "product")); OPHID_DEBUG(" serial: %s", udev_device_get_sysattr_value(dev, "serial")); - } /** -* \brief Handle event -* -* \note -* -*/ -void USBMonitor::deviceEventReceived() { - + * \brief Handle event + * + * \note + * + */ +void USBMonitor::deviceEventReceived() +{ qDebug() << "Device event"; struct udev_device *dev; dev = udev_monitor_receive_device(this->monitor); if (dev) { printf("------- Got Device Event"); - QString action = QString(udev_device_get_action(dev)); + QString action = QString(udev_device_get_action(dev)); QString devtype = QString(udev_device_get_devtype(dev)); if (action == "add" && devtype == "usb_device") { printPortInfo(dev); emit deviceDiscovered(makePortInfo(dev)); - } else if (action == "remove" && devtype == "usb_device"){ + } else if (action == "remove" && devtype == "usb_device") { printPortInfo(dev); emit deviceRemoved(makePortInfo(dev)); } udev_device_unref(dev); - } - else { + } else { printf("No Device from receive_device(). An error occured."); } - } /** -* \brief Return USB monitor instance -* -* \note . -* -* \return instance. -* \retval USBMonitor pointer. -*/ -USBMonitor* USBMonitor::instance() + * \brief Return USB monitor instance + * + * \note . + * + * \return instance. + * \retval USBMonitor pointer. + */ +USBMonitor *USBMonitor::instance() { return m_instance; } -USBMonitor* USBMonitor::m_instance = 0; +USBMonitor *USBMonitor::m_instance = 0; /** -* \brief Initialize udev monitor (contructor). -* -* \note -* -*/ -USBMonitor::USBMonitor(QObject *parent): QThread(parent) { - - m_instance = this; + * \brief Initialize udev monitor (contructor). + * + * \note + * + */ +USBMonitor::USBMonitor(QObject *parent) : QThread(parent) +{ + m_instance = this; this->context = udev_new(); @@ -135,11 +132,11 @@ USBMonitor::USBMonitor(QObject *parent): QThread(parent) { /** -* \brief Destructor -* -* \note -* -*/ + * \brief Destructor + * + * \note + * + */ USBMonitor::~USBMonitor() { quit(); @@ -147,13 +144,13 @@ USBMonitor::~USBMonitor() /** -* \brief Returns a list of all currently available devices -* -* \note -* -* \return List of all currently available devices -* \retval Qlist -*/ + * \brief Returns a list of all currently available devices + * + * \note + * + * \return List of all currently available devices + * \retval Qlist + */ QList USBMonitor::availableDevices() { QList devicesList; @@ -162,20 +159,21 @@ QList USBMonitor::availableDevices() struct udev_device *dev; enumerate = udev_enumerate_new(this->context); - udev_enumerate_add_match_subsystem(enumerate,"usb"); - //udev_enumerate_add_match_sysattr(enumerate, "idVendor", "20a0"); + udev_enumerate_add_match_subsystem(enumerate, "usb"); + // udev_enumerate_add_match_sysattr(enumerate, "idVendor", "20a0"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); // Will use the 'native' udev functions to loop: - udev_list_entry_foreach(dev_list_entry,devices) { + udev_list_entry_foreach(dev_list_entry, devices) { const char *path; /* Get the filename of the /sys entry for the device - and create a udev_device object (dev) representing it */ + and create a udev_device object (dev) representing it */ path = udev_list_entry_get_name(dev_list_entry); - dev = udev_device_new_from_syspath(this->context, path); - if (QString(udev_device_get_devtype(dev)) == "usb_device") + dev = udev_device_new_from_syspath(this->context, path); + if (QString(udev_device_get_devtype(dev)) == "usb_device") { devicesList.append(makePortInfo(dev)); + } udev_device_unref(dev); } // free the enumerator object @@ -186,42 +184,43 @@ QList USBMonitor::availableDevices() /** -* \brief Search for particular devices -* -* \note Be a bit more picky and ask only for a specific type of device: -* On OpenPilot, the bcdDeviceLSB indicates the run state: bootloader or running. -* bcdDeviceMSB indicates the board model. -* -* \param[in] vid USB vendor id of the device. -* \param[in] pid USB product id of the device. -* \param[in] bcdDeviceMSB MSB of the device in bcd format. -* \param[in] bcdDeviceLSB LSB of the device in bcd format. -* \return List of available devices -* \retval QList. -*/ + * \brief Search for particular devices + * + * \note Be a bit more picky and ask only for a specific type of device: + * On OpenPilot, the bcdDeviceLSB indicates the run state: bootloader or running. + * bcdDeviceMSB indicates the board model. + * + * \param[in] vid USB vendor id of the device. + * \param[in] pid USB product id of the device. + * \param[in] bcdDeviceMSB MSB of the device in bcd format. + * \param[in] bcdDeviceLSB LSB of the device in bcd format. + * \return List of available devices + * \retval QList. + */ QList USBMonitor::availableDevices(int vid, int pid, int bcdDeviceMSB, int bcdDeviceLSB) { QList allPorts = availableDevices(); QList thePortsWeWant; - foreach (USBPortInfo port, allPorts) { - if((port.vendorID==vid || vid==-1) && (port.productID==pid || pid==-1) && ((port.bcdDevice>>8)==bcdDeviceMSB || bcdDeviceMSB==-1) && - ( (port.bcdDevice&0x00ff) ==bcdDeviceLSB || bcdDeviceLSB==-1)) + foreach(USBPortInfo port, allPorts) { + if ((port.vendorID == vid || vid == -1) && (port.productID == pid || pid == -1) && ((port.bcdDevice >> 8) == bcdDeviceMSB || bcdDeviceMSB == -1) && + ((port.bcdDevice & 0x00ff) == bcdDeviceLSB || bcdDeviceLSB == -1)) { thePortsWeWant.append(port); + } } return thePortsWeWant; } /** -* \brief Initialize port information of a specific device. -* -* \note -* -* \param[in] dev Udev device. -* \return Port info -* \retval USBPortInfo structure filled -*/ + * \brief Initialize port information of a specific device. + * + * \note + * + * \param[in] dev Udev device. + * \return Port info + * \retval USBPortInfo structure filled + */ USBPortInfo USBMonitor::makePortInfo(struct udev_device *dev) { USBPortInfo prtInfo; @@ -231,15 +230,14 @@ USBPortInfo USBMonitor::makePortInfo(struct udev_device *dev) printPortInfo(dev); #endif - prtInfo.vendorID = QString(udev_device_get_sysattr_value(dev, "idVendor")).toInt(&ok, 16); - prtInfo.productID = QString(udev_device_get_sysattr_value(dev, "idProduct")).toInt(&ok, 16); + prtInfo.vendorID = QString(udev_device_get_sysattr_value(dev, "idVendor")).toInt(&ok, 16); + prtInfo.productID = QString(udev_device_get_sysattr_value(dev, "idProduct")).toInt(&ok, 16); prtInfo.serialNumber = QString(udev_device_get_sysattr_value(dev, "serial")); - prtInfo.manufacturer = QString(udev_device_get_sysattr_value(dev,"manufacturer")); - prtInfo.product = QString(udev_device_get_sysattr_value(dev,"product")); -// prtInfo.UsagePage = QString(udev_device_get_sysattr_value(dev,"")); -// prtInfo.Usage = QString(udev_device_get_sysattr_value(dev,"")); - prtInfo.bcdDevice = QString(udev_device_get_sysattr_value(dev,"bcdDevice")).toInt(&ok, 16); + prtInfo.manufacturer = QString(udev_device_get_sysattr_value(dev, "manufacturer")); + prtInfo.product = QString(udev_device_get_sysattr_value(dev, "product")); +// prtInfo.UsagePage = QString(udev_device_get_sysattr_value(dev,"")); +// prtInfo.Usage = QString(udev_device_get_sysattr_value(dev,"")); + prtInfo.bcdDevice = QString(udev_device_get_sysattr_value(dev, "bcdDevice")).toInt(&ok, 16); return prtInfo; } - diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp index 667b281db..39dc27dfc 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp +++ b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp @@ -37,7 +37,7 @@ #define OP_LOOPMODE_NAME_MAC "Open_Pilot_Loop_Mode" -#define printf qDebug +#define printf qDebug // ! Local helper functions static bool HID_GetIntProperty(IOHIDDeviceRef dev, CFStringRef property, int *value); @@ -48,25 +48,25 @@ static bool HID_GetStrProperty(IOHIDDeviceRef dev, CFStringRef property, QString */ USBMonitor::USBMonitor(QObject *parent) : QThread(parent) { - m_instance = this; - hid_manager = NULL; - listMutex = new QMutex(); - knowndevices.clear(); + m_instance = this; + hid_manager = NULL; + listMutex = new QMutex(); + knowndevices.clear(); - m_terminate = false; + m_terminate = false; start(); } USBMonitor::~USBMonitor() { - m_terminate = true; + m_terminate = true; // if(hid_manager != NULL) // IOHIDManagerUnscheduleFromRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); -// quit(); +// quit(); - while (hid_manager != 0) { - this->sleep(10); - } + while (hid_manager != 0) { + this->sleep(10); + } } void USBMonitor::deviceEventReceived() @@ -90,7 +90,7 @@ void USBMonitor::removeDevice(IOHIDDeviceRef dev) QMutexLocker locker(listMutex); knowndevices.removeAt(i); emit deviceRemoved(port); - emit deviceRemoved(); + emit deviceRemoved(); return; } } @@ -113,9 +113,9 @@ void USBMonitor::addDevice(USBPortInfo info) { QMutexLocker locker(listMutex); - knowndevices.append(info); - emit deviceDiscovered(info); - emit deviceDiscovered(); + knowndevices.append(info); + emit deviceDiscovered(info); + emit deviceDiscovered(); } void USBMonitor::attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev) @@ -187,38 +187,38 @@ QList USBMonitor::availableDevices(int vid, int pid, int bcdDeviceM void USBMonitor::run() { - IOReturn ret; + IOReturn ret; - hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); - if (hid_manager == NULL || CFGetTypeID(hid_manager) != IOHIDManagerGetTypeID()) { - if (hid_manager) { - CFRelease(hid_manager); - } - assert(0); - } + hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + if (hid_manager == NULL || CFGetTypeID(hid_manager) != IOHIDManagerGetTypeID()) { + if (hid_manager) { + CFRelease(hid_manager); + } + assert(0); + } - // No matching filter - IOHIDManagerSetDeviceMatching(hid_manager, NULL); + // No matching filter + IOHIDManagerSetDeviceMatching(hid_manager, NULL); - CFRunLoopRef loop = CFRunLoopGetCurrent(); - // set up a callbacks for device attach & detach - IOHIDManagerScheduleWithRunLoop(hid_manager, loop, kCFRunLoopDefaultMode); - IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, attach_callback, this); - IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, detach_callback, this); - ret = IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone); - if (ret != kIOReturnSuccess) { - IOHIDManagerUnscheduleFromRunLoop(hid_manager, loop, kCFRunLoopDefaultMode); - CFRelease(hid_manager); - return; - } + CFRunLoopRef loop = CFRunLoopGetCurrent(); + // set up a callbacks for device attach & detach + IOHIDManagerScheduleWithRunLoop(hid_manager, loop, kCFRunLoopDefaultMode); + IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, attach_callback, this); + IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, detach_callback, this); + ret = IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone); + if (ret != kIOReturnSuccess) { + IOHIDManagerUnscheduleFromRunLoop(hid_manager, loop, kCFRunLoopDefaultMode); + CFRelease(hid_manager); + return; + } - while(!m_terminate) { - CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, false); - } - IOHIDManagerUnscheduleFromRunLoop(hid_manager, loop, kCFRunLoopDefaultMode); - CFRelease(hid_manager); + while (!m_terminate) { + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, false); + } + IOHIDManagerUnscheduleFromRunLoop(hid_manager, loop, kCFRunLoopDefaultMode); + CFRelease(hid_manager); - hid_manager = NULL; + hid_manager = NULL; } /** diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbsignal.cpp b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbsignal.cpp index 68dee238d..ae39e497d 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbsignal.cpp +++ b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbsignal.cpp @@ -30,36 +30,35 @@ /** -* \brief trigger device discovered signal -* -* \note -* -* \param[in] port. -*/ + * \brief trigger device discovered signal + * + * \note + * + * \param[in] port. + */ void USBSignalFilter::m_deviceDiscovered(USBPortInfo port) { - if((port.vendorID==m_vid || m_vid==-1) && - (port.productID==m_pid || m_pid==-1) && - ((port.bcdDevice>>8)==m_boardModel || m_boardModel==-1) && - ((port.bcdDevice&0x00ff) ==m_runState || m_runState==-1)) - { - qDebug()<<"USBSignalFilter emit device discovered"; + if ((port.vendorID == m_vid || m_vid == -1) && + (port.productID == m_pid || m_pid == -1) && + ((port.bcdDevice >> 8) == m_boardModel || m_boardModel == -1) && + ((port.bcdDevice & 0x00ff) == m_runState || m_runState == -1)) { + qDebug() << "USBSignalFilter emit device discovered"; emit deviceDiscovered(); } } /** -* \brief Constructor -* -* \note -* -* \param[in] vid USB vendor id of the device to open (-1 for any). -* \param[in] pid USB product id of the device to open (-1 for any). -* \param[in] boardModel. -* \param[in] runState. -*/ -USBSignalFilter::USBSignalFilter(int vid, int pid, int boardModel, int runState): + * \brief Constructor + * + * \note + * + * \param[in] vid USB vendor id of the device to open (-1 for any). + * \param[in] pid USB product id of the device to open (-1 for any). + * \param[in] boardModel. + * \param[in] runState. + */ +USBSignalFilter::USBSignalFilter(int vid, int pid, int boardModel, int runState) : m_vid(vid), m_pid(pid), m_boardModel(boardModel), @@ -68,8 +67,6 @@ USBSignalFilter::USBSignalFilter(int vid, int pid, int boardModel, int runState) connect(USBMonitor::instance(), SIGNAL(deviceDiscovered(USBPortInfo)), this, - SLOT(m_deviceDiscovered(USBPortInfo)), - Qt::QueuedConnection); + SLOT(m_deviceDiscovered(USBPortInfo)), + Qt::QueuedConnection); } - - From 9474550351ea6365ea09fb4b2f1d9c916cd588af Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sat, 25 May 2013 01:31:23 +0300 Subject: [PATCH 026/120] OP-958: usbmon_mac: remove unused code --- .../src/plugins/opHID/src/opHID_usbmon_mac.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp index 39dc27dfc..06574b0a5 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp +++ b/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp @@ -35,11 +35,7 @@ #include #include "opHID_const.h" -#define OP_LOOPMODE_NAME_MAC "Open_Pilot_Loop_Mode" - -#define printf qDebug - -// ! Local helper functions +// Local helper functions static bool HID_GetIntProperty(IOHIDDeviceRef dev, CFStringRef property, int *value); static bool HID_GetStrProperty(IOHIDDeviceRef dev, CFStringRef property, QString & value); @@ -60,9 +56,6 @@ USBMonitor::USBMonitor(QObject *parent) : QThread(parent) USBMonitor::~USBMonitor() { m_terminate = true; - // if(hid_manager != NULL) - // IOHIDManagerUnscheduleFromRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); -// quit(); while (hid_manager != 0) { this->sleep(10); From 5ee36070e3de9dc927907af3187e9f685897a31f Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sat, 25 May 2013 01:36:24 +0300 Subject: [PATCH 027/120] OP-958: usbmon.h: remove superfluous #ifdef --- ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h index 7a991ea00..2b3849044 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h +++ b/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h @@ -136,9 +136,7 @@ signals: \param info The device that has been discovered. */ void deviceDiscovered(const USBPortInfo & info); -#ifdef __APPLE__ void deviceDiscovered(); -#endif // __APPLE__ /*! A device has been disconnected from the system. @@ -147,9 +145,7 @@ signals: \param info The device that was disconnected. */ void deviceRemoved(const USBPortInfo & info); -#ifdef __APPLE__ void deviceRemoved(); -#endif // __APPLE__ private slots: /** From 0f33a16ed88de521418e78b6e118c4ee7f82405a Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sat, 25 May 2013 02:25:49 +0300 Subject: [PATCH 028/120] OP-958: rename opHID plugin directory to lower case (same as all other plugins) --- .../openpilotgcs/src/plugins/opHID/opHID.pro | 76 ----------------- .../{opHID => ophid}/hidapi/.no-auto-format | 0 .../plugins/{opHID => ophid}/hidapi/hidapi.h | 0 .../{opHID => ophid}/hidapi/libusb/hid.c | 2 +- .../{opHID => ophid}/hidapi/linux/hid.c | 2 +- .../plugins/{opHID => ophid}/hidapi/mac/hid.c | 2 +- .../{opHID => ophid}/hidapi/windows/hid.c | 2 +- .../{opHID/inc/opHID.h => ophid/inc/ophid.h} | 8 +- .../opHID_const.h => ophid/inc/ophid_const.h} | 2 +- .../inc/ophid_global.h} | 2 +- .../inc/ophid_hidapi.h} | 8 +- .../inc/ophid_plugin.h} | 8 +- .../inc/ophid_usbmon.h} | 4 +- .../inc/ophid_usbsignal.h} | 4 +- .../plugins/{opHID => ophid}/opHID.pluginspec | 0 .../{opHID/opHID.pri => ophid/ophid.pri} | 2 +- .../openpilotgcs/src/plugins/ophid/ophid.pro | 81 +++++++++++++++++++ .../ophid_dependencies.pri} | 0 .../src/opHID.cpp => ophid/src/ophid.cpp} | 4 +- .../src/ophid_hidapi.cpp} | 4 +- .../src/ophid_plugin.cpp} | 8 +- .../src/ophid_usbmon_linux.cpp} | 4 +- .../src/ophid_usbmon_mac.cpp} | 4 +- .../src/ophid_usbmon_win.cpp} | 4 +- .../src/ophid_usbsignal.cpp} | 2 +- ground/openpilotgcs/src/plugins/plugins.pro | 2 +- 26 files changed, 120 insertions(+), 115 deletions(-) delete mode 100644 ground/openpilotgcs/src/plugins/opHID/opHID.pro rename ground/openpilotgcs/src/plugins/{opHID => ophid}/hidapi/.no-auto-format (100%) rename ground/openpilotgcs/src/plugins/{opHID => ophid}/hidapi/hidapi.h (100%) rename ground/openpilotgcs/src/plugins/{opHID => ophid}/hidapi/libusb/hid.c (99%) rename ground/openpilotgcs/src/plugins/{opHID => ophid}/hidapi/linux/hid.c (99%) rename ground/openpilotgcs/src/plugins/{opHID => ophid}/hidapi/mac/hid.c (99%) rename ground/openpilotgcs/src/plugins/{opHID => ophid}/hidapi/windows/hid.c (99%) rename ground/openpilotgcs/src/plugins/{opHID/inc/opHID.h => ophid/inc/ophid.h} (95%) rename ground/openpilotgcs/src/plugins/{opHID/inc/opHID_const.h => ophid/inc/ophid_const.h} (98%) rename ground/openpilotgcs/src/plugins/{opHID/inc/opHID_global.h => ophid/inc/ophid_global.h} (97%) rename ground/openpilotgcs/src/plugins/{opHID/inc/opHID_hidapi.h => ophid/inc/ophid_hidapi.h} (94%) rename ground/openpilotgcs/src/plugins/{opHID/inc/opHID_plugin.h => ophid/inc/ophid_plugin.h} (96%) rename ground/openpilotgcs/src/plugins/{opHID/inc/opHID_usbmon.h => ophid/inc/ophid_usbmon.h} (99%) rename ground/openpilotgcs/src/plugins/{opHID/inc/opHID_usbsignal.h => ophid/inc/ophid_usbsignal.h} (96%) rename ground/openpilotgcs/src/plugins/{opHID => ophid}/opHID.pluginspec (100%) rename ground/openpilotgcs/src/plugins/{opHID/opHID.pri => ophid/ophid.pri} (51%) create mode 100644 ground/openpilotgcs/src/plugins/ophid/ophid.pro rename ground/openpilotgcs/src/plugins/{opHID/opHID_dependencies.pri => ophid/ophid_dependencies.pri} (100%) rename ground/openpilotgcs/src/plugins/{opHID/src/opHID.cpp => ophid/src/ophid.cpp} (99%) rename ground/openpilotgcs/src/plugins/{opHID/src/opHID_hidapi.cpp => ophid/src/ophid_hidapi.cpp} (99%) rename ground/openpilotgcs/src/plugins/{opHID/src/opHID_plugin.cpp => ophid/src/ophid_plugin.cpp} (98%) rename ground/openpilotgcs/src/plugins/{opHID/src/opHID_usbmon_linux.cpp => ophid/src/ophid_usbmon_linux.cpp} (99%) rename ground/openpilotgcs/src/plugins/{opHID/src/opHID_usbmon_mac.cpp => ophid/src/ophid_usbmon_mac.cpp} (99%) rename ground/openpilotgcs/src/plugins/{opHID/src/opHID_usbmon_win.cpp => ophid/src/ophid_usbmon_win.cpp} (99%) rename ground/openpilotgcs/src/plugins/{opHID/src/opHID_usbsignal.cpp => ophid/src/ophid_usbsignal.cpp} (98%) diff --git a/ground/openpilotgcs/src/plugins/opHID/opHID.pro b/ground/openpilotgcs/src/plugins/opHID/opHID.pro deleted file mode 100644 index eccb05bdd..000000000 --- a/ground/openpilotgcs/src/plugins/opHID/opHID.pro +++ /dev/null @@ -1,76 +0,0 @@ -TEMPLATE = lib -TARGET = opHID -include(../../openpilotgcsplugin.pri) -include(opHID_dependencies.pri) -HEADERS += inc/opHID_global.h \ - inc/opHID_plugin.h \ - inc/opHID.h \ - inc/opHID_hidapi.h \ - inc/opHID_const.h \ - inc/opHID_usbmon.h \ - inc/opHID_usbsignal.h \ - hidapi/hidapi.h -SOURCES += src/opHID_plugin.cpp \ - src/opHID.cpp \ - src/opHID_usbsignal.cpp \ - src/opHID_hidapi.cpp -FORMS += -RESOURCES += -DEFINES += OPHID_LIBRARY -OTHER_FILES += opHID.pluginspec -INCLUDEPATH += ./inc -# Platform Specific -win32 { - SOURCES += src/opHID_usbmon_win.cpp \ - hidapi/windows/hid.c - LIBS += -lhid -lsetupapi -} -macx { - SOURCES += src/opHID_usbmon_mac.cpp \ - hidapi/mac/hid.c - SDK = /Developer/SDKs/MacOSX10.5.sdk - ARCH = -mmacosx-version-min=10.5 \ - -arch \ - ppc \ - -arch \ - i386 - LIBS += $(ARCH) \ - -Wl,-syslibroot,$(SDK) \ - -framework \ - IOKit \ - -framework \ - CoreFoundation -} -linux-g++ { - SOURCES += src/opHID_usbmon_linux.cpp - LIBS += -lusb -ludev - -# hidapi library -## rawhid -# SOURCES += hidapi/linux/hid.c -## libusb - SOURCES += hidapi/libusb/hid.c - LIBS += `pkg-config libusb-1.0 --libs` -lrt -lpthread - INCLUDEPATH += /usr/include/libusb-1.0 -# INCLUDEPATH += `pkg-config libusb-1.0 --cflags` -!exists(/usr/include/libusb-1.0) { - error(Install libusb-1.0.0-dev using your package manager.) - } -} -linux-g++-64 { - SOURCES += src/opHID_usbmon_linux.cpp - LIBS += -lusb -ludev - -# hidapi library -## rawhid -# SOURCES += hidapi/linux/hid.c -## libusb - SOURCES += hidapi/libusb/hid.c - LIBS += `pkg-config libusb-1.0 --libs` -lrt -lpthread - INCLUDEPATH += /usr/include/libusb-1.0 -# INCLUDEPATH += `pkg-config libusb-1.0 --cflags` -!exists(/usr/include/libusb-1.0) { - error(Install libusb-1.0.0-dev using your package manager.) - } -} - diff --git a/ground/openpilotgcs/src/plugins/opHID/hidapi/.no-auto-format b/ground/openpilotgcs/src/plugins/ophid/hidapi/.no-auto-format similarity index 100% rename from ground/openpilotgcs/src/plugins/opHID/hidapi/.no-auto-format rename to ground/openpilotgcs/src/plugins/ophid/hidapi/.no-auto-format diff --git a/ground/openpilotgcs/src/plugins/opHID/hidapi/hidapi.h b/ground/openpilotgcs/src/plugins/ophid/hidapi/hidapi.h similarity index 100% rename from ground/openpilotgcs/src/plugins/opHID/hidapi/hidapi.h rename to ground/openpilotgcs/src/plugins/ophid/hidapi/hidapi.h diff --git a/ground/openpilotgcs/src/plugins/opHID/hidapi/libusb/hid.c b/ground/openpilotgcs/src/plugins/ophid/hidapi/libusb/hid.c similarity index 99% rename from ground/openpilotgcs/src/plugins/opHID/hidapi/libusb/hid.c rename to ground/openpilotgcs/src/plugins/ophid/hidapi/libusb/hid.c index 94c1b3b69..a25eaa6f3 100644 --- a/ground/openpilotgcs/src/plugins/opHID/hidapi/libusb/hid.c +++ b/ground/openpilotgcs/src/plugins/ophid/hidapi/libusb/hid.c @@ -47,7 +47,7 @@ #include "libusb.h" #include "iconv.h" -#include "hidapi.h" +#include "../hidapi.h" #ifdef __cplusplus extern "C" { diff --git a/ground/openpilotgcs/src/plugins/opHID/hidapi/linux/hid.c b/ground/openpilotgcs/src/plugins/ophid/hidapi/linux/hid.c similarity index 99% rename from ground/openpilotgcs/src/plugins/opHID/hidapi/linux/hid.c rename to ground/openpilotgcs/src/plugins/ophid/hidapi/linux/hid.c index 38f67537c..a54543047 100644 --- a/ground/openpilotgcs/src/plugins/opHID/hidapi/linux/hid.c +++ b/ground/openpilotgcs/src/plugins/ophid/hidapi/linux/hid.c @@ -43,7 +43,7 @@ #include #include -#include "hidapi.h" +#include "../hidapi.h" /* Definitions from linux/hidraw.h. Since these are new, some distros may not have header files which contain them. */ diff --git a/ground/openpilotgcs/src/plugins/opHID/hidapi/mac/hid.c b/ground/openpilotgcs/src/plugins/ophid/hidapi/mac/hid.c similarity index 99% rename from ground/openpilotgcs/src/plugins/opHID/hidapi/mac/hid.c rename to ground/openpilotgcs/src/plugins/ophid/hidapi/mac/hid.c index d556eac53..2d473253f 100644 --- a/ground/openpilotgcs/src/plugins/opHID/hidapi/mac/hid.c +++ b/ground/openpilotgcs/src/plugins/ophid/hidapi/mac/hid.c @@ -32,7 +32,7 @@ #include #include -#include "hidapi.h" +#include "../hidapi.h" /* Barrier implementation because Mac OSX doesn't have pthread_barrier. It also doesn't have clock_gettime(). So much for POSIX and SUSv2. diff --git a/ground/openpilotgcs/src/plugins/opHID/hidapi/windows/hid.c b/ground/openpilotgcs/src/plugins/ophid/hidapi/windows/hid.c similarity index 99% rename from ground/openpilotgcs/src/plugins/opHID/hidapi/windows/hid.c rename to ground/openpilotgcs/src/plugins/ophid/hidapi/windows/hid.c index cd9e4bb0f..9b85b19bb 100644 --- a/ground/openpilotgcs/src/plugins/opHID/hidapi/windows/hid.c +++ b/ground/openpilotgcs/src/plugins/ophid/hidapi/windows/hid.c @@ -60,7 +60,7 @@ extern "C" { #include -#include "hidapi.h" +#include "../hidapi.h" #ifdef _MSC_VER /* Thanks Microsoft, but I know how to use strncpy(). */ diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID.h b/ground/openpilotgcs/src/plugins/ophid/inc/ophid.h similarity index 95% rename from ground/openpilotgcs/src/plugins/opHID/inc/opHID.h rename to ground/openpilotgcs/src/plugins/ophid/inc/ophid.h index fc1700deb..6f29227d8 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID.h +++ b/ground/openpilotgcs/src/plugins/ophid/inc/ophid.h @@ -1,7 +1,7 @@ /** ****************************************************************************** * - * @file rawhid.h + * @file ophid.h * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. * @addtogroup GCSPlugins GCS Plugins * @{ @@ -28,14 +28,14 @@ #ifndef OPHID_H #define OPHID_H -#include "opHID_global.h" +#include "ophid_global.h" #include #include #include #include -#include "opHID_hidapi.h" -#include "opHID_usbmon.h" +#include "ophid_hidapi.h" +#include "ophid_usbmon.h" class RawHIDReadThread; class RawHIDWriteThread; diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_const.h b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_const.h similarity index 98% rename from ground/openpilotgcs/src/plugins/opHID/inc/opHID_const.h rename to ground/openpilotgcs/src/plugins/ophid/inc/ophid_const.h index 9a2e12fbb..f0928891e 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_const.h +++ b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_const.h @@ -1,7 +1,7 @@ /** ****************************************************************************** * - * @file rawhid_const.h + * @file ophid_const.h * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @addtogroup GCSPlugins GCS Plugins * @{ diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_global.h b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_global.h similarity index 97% rename from ground/openpilotgcs/src/plugins/opHID/inc/opHID_global.h rename to ground/openpilotgcs/src/plugins/ophid/inc/ophid_global.h index a08279318..d5f2217b8 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_global.h +++ b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_global.h @@ -1,7 +1,7 @@ /** ****************************************************************************** * - * @file rawhid_global.h + * @file ophid_global.h * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. * @addtogroup GCSPlugins GCS Plugins * @{ diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_hidapi.h similarity index 94% rename from ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h rename to ground/openpilotgcs/src/plugins/ophid/inc/ophid_hidapi.h index 3151917db..30366338a 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_hidapi.h +++ b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_hidapi.h @@ -1,7 +1,7 @@ /** ****************************************************************************** * - * @file pjrc_rawhid.h + * @file ophid_hidapi.h * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. * @addtogroup GCSPlugins GCS Plugins * @{ @@ -36,9 +36,9 @@ #if defined(Q_OS_LINUX) #include #endif -#include "hidapi.h" -#include "opHID_const.h" -#include "opHID_global.h" +#include "../hidapi/hidapi.h" +#include "ophid_const.h" +#include "ophid_global.h" class OPHID_EXPORT opHID_hidapi : public QObject { diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_plugin.h b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_plugin.h similarity index 96% rename from ground/openpilotgcs/src/plugins/opHID/inc/opHID_plugin.h rename to ground/openpilotgcs/src/plugins/ophid/inc/ophid_plugin.h index 37f08d2a5..73f84dadc 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_plugin.h +++ b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_plugin.h @@ -1,7 +1,7 @@ /** ****************************************************************************** * - * @file rawhid.h + * @file ophid_plugin.h * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. * @addtogroup GCSPlugins GCS Plugins * @{ @@ -33,9 +33,9 @@ #include #include "coreplugin/iconnection.h" -#include "opHID.h" -#include "opHID_global.h" -#include "opHID_usbmon.h" +#include "ophid.h" +#include "ophid_global.h" +#include "ophid_usbmon.h" class IConnection; class RawHIDConnection; diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h similarity index 99% rename from ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h rename to ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h index 2b3849044..c169e7040 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbmon.h +++ b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h @@ -1,7 +1,7 @@ /** ****************************************************************************** * - * @file usbmonitor.h + * @file ophid_usbmon.h * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. * @addtogroup GCSPlugins GCS Plugins * @{ @@ -28,7 +28,7 @@ #ifndef OPHID_USBMON_H #define OPHID_USBMON_H -#include "opHID_global.h" +#include "ophid_global.h" #include #include diff --git a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbsignal.h b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbsignal.h similarity index 96% rename from ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbsignal.h rename to ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbsignal.h index 221359911..ad461d9fb 100644 --- a/ground/openpilotgcs/src/plugins/opHID/inc/opHID_usbsignal.h +++ b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbsignal.h @@ -1,7 +1,7 @@ /** ****************************************************************************** * - * @file usbmonitor.h + * @file ophid_usbsignal.h * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. * @addtogroup GCSPlugins GCS Plugins * @{ @@ -29,7 +29,7 @@ #define OPHID_USBSIGNAL_H #include -#include "opHID_usbmon.h" +#include "ophid_usbmon.h" class OPHID_EXPORT USBSignalFilter : public QObject { Q_OBJECT diff --git a/ground/openpilotgcs/src/plugins/opHID/opHID.pluginspec b/ground/openpilotgcs/src/plugins/ophid/opHID.pluginspec similarity index 100% rename from ground/openpilotgcs/src/plugins/opHID/opHID.pluginspec rename to ground/openpilotgcs/src/plugins/ophid/opHID.pluginspec diff --git a/ground/openpilotgcs/src/plugins/opHID/opHID.pri b/ground/openpilotgcs/src/plugins/ophid/ophid.pri similarity index 51% rename from ground/openpilotgcs/src/plugins/opHID/opHID.pri rename to ground/openpilotgcs/src/plugins/ophid/ophid.pri index 2c05da83d..8ddbc3c4f 100644 --- a/ground/openpilotgcs/src/plugins/opHID/opHID.pri +++ b/ground/openpilotgcs/src/plugins/ophid/ophid.pri @@ -1,3 +1,3 @@ -include(opHID_dependencies.pri) +include(ophid_dependencies.pri) LIBS *= -l$$qtLibraryName(opHID) diff --git a/ground/openpilotgcs/src/plugins/ophid/ophid.pro b/ground/openpilotgcs/src/plugins/ophid/ophid.pro new file mode 100644 index 000000000..d5f2d04cb --- /dev/null +++ b/ground/openpilotgcs/src/plugins/ophid/ophid.pro @@ -0,0 +1,81 @@ +TEMPLATE = lib +TARGET = opHID + +include(../../openpilotgcsplugin.pri) +include(ophid_dependencies.pri) + +HEADERS += inc/ophid_global.h \ + inc/ophid_plugin.h \ + inc/ophid.h \ + inc/ophid_hidapi.h \ + inc/ophid_const.h \ + inc/ophid_usbmon.h \ + inc/ophid_usbsignal.h \ + hidapi/hidapi.h +SOURCES += src/ophid_plugin.cpp \ + src/ophid.cpp \ + src/ophid_usbsignal.cpp \ + src/ophid_hidapi.cpp +FORMS += +RESOURCES += +DEFINES += OPHID_LIBRARY +OTHER_FILES += opHID.pluginspec + +INCLUDEPATH += ./inc + +# Platform Specific + +win32 { + SOURCES += src/ophid_usbmon_win.cpp \ + hidapi/windows/hid.c + LIBS += -lhid -lsetupapi +} + +macx { + SOURCES += src/ophid_usbmon_mac.cpp \ + hidapi/mac/hid.c + SDK = /Developer/SDKs/MacOSX10.5.sdk + ARCH = -mmacosx-version-min=10.5 \ + -arch ppc \ + -arch i386 + LIBS += $(ARCH) \ + -Wl,-syslibroot,$(SDK) \ + -framework IOKit \ + -framework CoreFoundation +} + +linux-g++ { + SOURCES += src/ophid_usbmon_linux.cpp + LIBS += -lusb -ludev + + # hidapi library + ## rawhid + # SOURCES += hidapi/linux/hid.c + ## libusb + SOURCES += hidapi/libusb/hid.c + LIBS += `pkg-config libusb-1.0 --libs` -lrt -lpthread + INCLUDEPATH += /usr/include/libusb-1.0 +# INCLUDEPATH += `pkg-config libusb-1.0 --cflags` + + !exists(/usr/include/libusb-1.0) { + error(Install libusb-1.0.0-dev using your package manager.) + } +} + +linux-g++-64 { + SOURCES += src/ophid_usbmon_linux.cpp + LIBS += -lusb -ludev + + # hidapi library + ## rawhid + # SOURCES += hidapi/linux/hid.c + ## libusb + SOURCES += hidapi/libusb/hid.c + LIBS += `pkg-config libusb-1.0 --libs` -lrt -lpthread + INCLUDEPATH += /usr/include/libusb-1.0 +# INCLUDEPATH += `pkg-config libusb-1.0 --cflags` + !exists(/usr/include/libusb-1.0) { + error(Install libusb-1.0.0-dev using your package manager.) + } +} + diff --git a/ground/openpilotgcs/src/plugins/opHID/opHID_dependencies.pri b/ground/openpilotgcs/src/plugins/ophid/ophid_dependencies.pri similarity index 100% rename from ground/openpilotgcs/src/plugins/opHID/opHID_dependencies.pri rename to ground/openpilotgcs/src/plugins/ophid/ophid_dependencies.pri diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID.cpp b/ground/openpilotgcs/src/plugins/ophid/src/ophid.cpp similarity index 99% rename from ground/openpilotgcs/src/plugins/opHID/src/opHID.cpp rename to ground/openpilotgcs/src/plugins/ophid/src/ophid.cpp index db38ad42d..afcc28446 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID.cpp +++ b/ground/openpilotgcs/src/plugins/ophid/src/ophid.cpp @@ -25,8 +25,8 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "opHID.h" -#include "opHID_const.h" +#include "ophid.h" +#include "ophid_const.h" #include "coreplugin/connectionmanager.h" #include #include diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_hidapi.cpp b/ground/openpilotgcs/src/plugins/ophid/src/ophid_hidapi.cpp similarity index 99% rename from ground/openpilotgcs/src/plugins/opHID/src/opHID_hidapi.cpp rename to ground/openpilotgcs/src/plugins/ophid/src/ophid_hidapi.cpp index 8c214612e..baacd5502 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID_hidapi.cpp +++ b/ground/openpilotgcs/src/plugins/ophid/src/ophid_hidapi.cpp @@ -30,8 +30,8 @@ #include #include #include -#include "opHID_const.h" -#include "opHID_hidapi.h" +#include "ophid_const.h" +#include "ophid_hidapi.h" /** * \brief Constructor diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_plugin.cpp b/ground/openpilotgcs/src/plugins/ophid/src/ophid_plugin.cpp similarity index 98% rename from ground/openpilotgcs/src/plugins/opHID/src/opHID_plugin.cpp rename to ground/openpilotgcs/src/plugins/ophid/src/ophid_plugin.cpp index d471965b1..34b2bf790 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID_plugin.cpp +++ b/ground/openpilotgcs/src/plugins/ophid/src/ophid_plugin.cpp @@ -25,15 +25,15 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "opHID_global.h" -#include "opHID_plugin.h" +#include "ophid_global.h" +#include "ophid_plugin.h" #include #include #include -#include "opHID_hidapi.h" -#include "opHID_const.h" +#include "ophid_hidapi.h" +#include "ophid_const.h" /** diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_linux.cpp b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_linux.cpp similarity index 99% rename from ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_linux.cpp rename to ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_linux.cpp index d6aa168f3..9e6f3ef70 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_linux.cpp +++ b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_linux.cpp @@ -25,9 +25,9 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "opHID_usbmon.h" +#include "ophid_usbmon.h" #include -#include "opHID_const.h" +#include "ophid_const.h" /** diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp similarity index 99% rename from ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp rename to ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp index 06574b0a5..c3a804531 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_mac.cpp +++ b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp @@ -26,14 +26,14 @@ */ -#include "opHID_usbmon.h" +#include "ophid_usbmon.h" #include #include #include #include #include #include -#include "opHID_const.h" +#include "ophid_const.h" // Local helper functions static bool HID_GetIntProperty(IOHIDDeviceRef dev, CFStringRef property, int *value); diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_win.cpp b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_win.cpp similarity index 99% rename from ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_win.cpp rename to ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_win.cpp index 4492106c2..5c3d90251 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbmon_win.cpp +++ b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_win.cpp @@ -30,9 +30,9 @@ #include #include #include -#include "opHID_usbmon.h" +#include "ophid_usbmon.h" #include -#include "opHID_const.h" +#include "ophid_const.h" #define printf qDebug diff --git a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbsignal.cpp b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbsignal.cpp similarity index 98% rename from ground/openpilotgcs/src/plugins/opHID/src/opHID_usbsignal.cpp rename to ground/openpilotgcs/src/plugins/ophid/src/ophid_usbsignal.cpp index ae39e497d..6e1335f16 100644 --- a/ground/openpilotgcs/src/plugins/opHID/src/opHID_usbsignal.cpp +++ b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbsignal.cpp @@ -25,7 +25,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "opHID_usbsignal.h" +#include "ophid_usbsignal.h" #include diff --git a/ground/openpilotgcs/src/plugins/plugins.pro b/ground/openpilotgcs/src/plugins/plugins.pro index f397a67d6..20b402704 100644 --- a/ground/openpilotgcs/src/plugins/plugins.pro +++ b/ground/openpilotgcs/src/plugins/plugins.pro @@ -30,7 +30,7 @@ SUBDIRS += plugin_welcome # opHID connection plugin SUBDIRS += plugin_opHID -plugin_opHID.subdir = opHID +plugin_opHID.subdir = ophid plugin_opHID.depends = plugin_coreplugin # Serial port connection plugin From 3757c8e3914cf729efa339a0b0b06c57f90defcb Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sat, 25 May 2013 02:29:57 +0300 Subject: [PATCH 029/120] OP-958: uncrustify sources --- .../src/plugins/ophid/inc/ophid_usbmon.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h index c169e7040..178db7a54 100644 --- a/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h +++ b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h @@ -137,13 +137,14 @@ signals: */ void deviceDiscovered(const USBPortInfo & info); void deviceDiscovered(); - /*! - A device has been disconnected from the system. - setUpNotifications() must be called first to enable event-driven device notifications. - Currently only implemented on Windows and OS X. - \param info The device that was disconnected. - */ + /*! + A device has been disconnected from the system. + + setUpNotifications() must be called first to enable event-driven device notifications. + Currently only implemented on Windows and OS X. + \param info The device that was disconnected. + */ void deviceRemoved(const USBPortInfo & info); void deviceRemoved(); From b00e25c3936eddb63c333c8ae9b1a1c4d2455cde Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sat, 25 May 2013 03:50:24 +0300 Subject: [PATCH 030/120] OP-958: fix opHID file name case for linux --- ground/openpilotgcs/src/plugins/uploader/op_dfu.h | 6 +++--- .../src/plugins/uploader/uploadergadgetwidget.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/uploader/op_dfu.h b/ground/openpilotgcs/src/plugins/uploader/op_dfu.h index c7b315235..ea3629587 100644 --- a/ground/openpilotgcs/src/plugins/uploader/op_dfu.h +++ b/ground/openpilotgcs/src/plugins/uploader/op_dfu.h @@ -2,9 +2,9 @@ #define OP_DFU_H #include -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h index d3a1d7527..461b82daa 100644 --- a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h +++ b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h @@ -45,7 +45,7 @@ #include "coreplugin/icore.h" #include "coreplugin/connectionmanager.h" -#include "opHID/inc/opHID_plugin.h" +#include "ophid/inc/ophid_plugin.h" #include #include #include From 667c717e6870ead52a0f58f36d5b497e166f63c2 Mon Sep 17 00:00:00 2001 From: a*morale Date: Sat, 25 May 2013 00:50:04 +0200 Subject: [PATCH 031/120] OP-958 Fixed a connection problem due to missing qRegisterMetaType for USBPortInfo --- ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp index c3a804531..fc95c6eba 100644 --- a/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp +++ b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp @@ -48,7 +48,7 @@ USBMonitor::USBMonitor(QObject *parent) : QThread(parent) hid_manager = NULL; listMutex = new QMutex(); knowndevices.clear(); - + qRegisterMetaType("USBPortInfo"); m_terminate = false; start(); } From 13beee32af89eb9535475d18791f59bcd0d5a39d Mon Sep 17 00:00:00 2001 From: Mathieu Rondonneau Date: Fri, 24 May 2013 19:22:19 -0700 Subject: [PATCH 032/120] OP-958: Fixing issue due to renaming. --- .../openpilotgcs/src/plugins/uploader/uploader_dependencies.pri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/uploader/uploader_dependencies.pri b/ground/openpilotgcs/src/plugins/uploader/uploader_dependencies.pri index d8d4a18eb..8d6238f60 100644 --- a/ground/openpilotgcs/src/plugins/uploader/uploader_dependencies.pri +++ b/ground/openpilotgcs/src/plugins/uploader/uploader_dependencies.pri @@ -2,5 +2,5 @@ include(../../openpilotgcsplugin.pri) include(../../plugins/coreplugin/coreplugin.pri) include(../../plugins/uavobjects/uavobjects.pri) include(../../plugins/uavtalk/uavtalk.pri) -include(../../plugins/opHID/opHID.pri) +include(../../plugins/ophid/ophid.pri) include(../../plugins/uavobjectutil/uavobjectutil.pri) From bd538703ea3ddb297a86047c1f012dd84bd179f0 Mon Sep 17 00:00:00 2001 From: "Richard Flay (Hyper)" Date: Sat, 25 May 2013 17:10:41 +0930 Subject: [PATCH 033/120] OP-962: Tweaked C2U_STACK_SIZE_BYTES to be a multiple of 4. +review OPReview-480 --- flight/modules/ComUsbBridge/ComUsbBridge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flight/modules/ComUsbBridge/ComUsbBridge.c b/flight/modules/ComUsbBridge/ComUsbBridge.c index c7674ec00..95b42dc22 100644 --- a/flight/modules/ComUsbBridge/ComUsbBridge.c +++ b/flight/modules/ComUsbBridge/ComUsbBridge.c @@ -48,7 +48,7 @@ static void updateSettings(); // Private constants #define U2C_STACK_SIZE_BYTES 260 -#define C2U_STACK_SIZE_BYTES 315 +#define C2U_STACK_SIZE_BYTES 316 #define TASK_PRIORITY (tskIDLE_PRIORITY + 1) From 03a2e82ba374c12d1296ebc7548db6342d1cd62e Mon Sep 17 00:00:00 2001 From: Fredrik Arvidsson Date: Sat, 25 May 2013 09:42:26 +0200 Subject: [PATCH 034/120] OP-970 Adds antenna warning dialog when activating built in modem for Revolution. --- ground/openpilotgcs/src/plugins/config/configrevohwwidget.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/config/configrevohwwidget.cpp b/ground/openpilotgcs/src/plugins/config/configrevohwwidget.cpp index f04b3b493..7c0feaad1 100644 --- a/ground/openpilotgcs/src/plugins/config/configrevohwwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configrevohwwidget.cpp @@ -32,6 +32,7 @@ #include "hwsettings.h" #include #include +#include ConfigRevoHWWidget::ConfigRevoHWWidget(QWidget *parent) : ConfigTaskWidget(parent) @@ -93,7 +94,7 @@ void ConfigRevoHWWidget::setupCustomCombos() connect(m_ui->cbFlexi, SIGNAL(currentIndexChanged(int)), this, SLOT(flexiPortChanged(int))); connect(m_ui->cbMain, SIGNAL(currentIndexChanged(int)), this, SLOT(mainPortChanged(int))); - connect(m_ui->cbModem, SIGNAL(currentIndexChanged(int)), this, SLOT(modemPortChanged(int))); + connect(m_ui->cbModem, SIGNAL(currentIndexChanged(int)), this, SLOT(modemPortChanged(int))); } void ConfigRevoHWWidget::refreshWidgetsValues(UAVObject *obj) @@ -291,6 +292,7 @@ void ConfigRevoHWWidget::modemPortChanged(int index) m_ui->cbTxPower->setVisible(true); m_ui->lblInitFreq->setVisible(true); m_ui->leInitFreq->setVisible(true); + QMessageBox::warning(this, tr("Warning"), tr("Activating the Radio requires an antenna be attached, or modem damage will occur.")); } else { m_ui->lblTxPower->setVisible(false); m_ui->cbTxPower->setVisible(false); From 3c55485d88302748e13006978a4fff8a964e367b Mon Sep 17 00:00:00 2001 From: Fredrik Arvidsson Date: Sat, 25 May 2013 09:43:59 +0200 Subject: [PATCH 035/120] OP-970 Removes a comma. --- ground/openpilotgcs/src/plugins/config/configrevohwwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/config/configrevohwwidget.cpp b/ground/openpilotgcs/src/plugins/config/configrevohwwidget.cpp index 7c0feaad1..73e18ba1c 100644 --- a/ground/openpilotgcs/src/plugins/config/configrevohwwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configrevohwwidget.cpp @@ -292,7 +292,7 @@ void ConfigRevoHWWidget::modemPortChanged(int index) m_ui->cbTxPower->setVisible(true); m_ui->lblInitFreq->setVisible(true); m_ui->leInitFreq->setVisible(true); - QMessageBox::warning(this, tr("Warning"), tr("Activating the Radio requires an antenna be attached, or modem damage will occur.")); + QMessageBox::warning(this, tr("Warning"), tr("Activating the Radio requires an antenna be attached or modem damage will occur.")); } else { m_ui->lblTxPower->setVisible(false); m_ui->cbTxPower->setVisible(false); From d492d3e14e1bbd858ab1caf193aec18486fce07a Mon Sep 17 00:00:00 2001 From: Fredrik Arvidsson Date: Sat, 25 May 2013 12:04:50 +0200 Subject: [PATCH 036/120] OP-970 Fixes a problem with the Radio/Modem warning dialog showing up on board connection. --- .../src/plugins/config/configrevohwwidget.cpp | 9 +++++++-- .../openpilotgcs/src/plugins/config/configrevohwwidget.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/configrevohwwidget.cpp b/ground/openpilotgcs/src/plugins/config/configrevohwwidget.cpp index 73e18ba1c..c5a72f0b6 100644 --- a/ground/openpilotgcs/src/plugins/config/configrevohwwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configrevohwwidget.cpp @@ -35,7 +35,7 @@ #include -ConfigRevoHWWidget::ConfigRevoHWWidget(QWidget *parent) : ConfigTaskWidget(parent) +ConfigRevoHWWidget::ConfigRevoHWWidget(QWidget *parent) : ConfigTaskWidget(parent), m_refreshing(true) { m_ui = new Ui_RevoHWWidget(); m_ui->setupUi(this); @@ -76,6 +76,7 @@ ConfigRevoHWWidget::ConfigRevoHWWidget(QWidget *parent) : ConfigTaskWidget(paren populateWidgets(); refreshWidgetsValues(); forceConnectedState(); + m_refreshing = false; } ConfigRevoHWWidget::~ConfigRevoHWWidget() @@ -99,12 +100,14 @@ void ConfigRevoHWWidget::setupCustomCombos() void ConfigRevoHWWidget::refreshWidgetsValues(UAVObject *obj) { + m_refreshing = true; ConfigTaskWidget::refreshWidgetsValues(obj); usbVCPPortChanged(0); mainPortChanged(0); flexiPortChanged(0); modemPortChanged(0); + m_refreshing = false; } void ConfigRevoHWWidget::updateObjectsFromWidgets() @@ -292,7 +295,9 @@ void ConfigRevoHWWidget::modemPortChanged(int index) m_ui->cbTxPower->setVisible(true); m_ui->lblInitFreq->setVisible(true); m_ui->leInitFreq->setVisible(true); - QMessageBox::warning(this, tr("Warning"), tr("Activating the Radio requires an antenna be attached or modem damage will occur.")); + if(!m_refreshing) { + QMessageBox::warning(this, tr("Warning"), tr("Activating the Radio requires an antenna be attached or modem damage will occur.")); + } } else { m_ui->lblTxPower->setVisible(false); m_ui->cbTxPower->setVisible(false); diff --git a/ground/openpilotgcs/src/plugins/config/configrevohwwidget.h b/ground/openpilotgcs/src/plugins/config/configrevohwwidget.h index bfabea5b4..d7eb30b66 100644 --- a/ground/openpilotgcs/src/plugins/config/configrevohwwidget.h +++ b/ground/openpilotgcs/src/plugins/config/configrevohwwidget.h @@ -44,6 +44,7 @@ public: ~ConfigRevoHWWidget(); private: + bool m_refreshing; Ui_RevoHWWidget *m_ui; void setupCustomCombos(); From 45e18127a33ea2f7a510e921edc4ea67fede384a Mon Sep 17 00:00:00 2001 From: Mathieu Rondonneau Date: Sat, 25 May 2013 08:06:41 -0700 Subject: [PATCH 037/120] OP-958: adding patch for map to use proper lock mechanism. --- .../src/plugins/ophid/inc/ophid_usbmon.h | 3 ++- .../src/plugins/ophid/src/ophid_usbmon_mac.cpp | 12 ++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h index 178db7a54..20ef05031 100644 --- a/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h +++ b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h @@ -32,6 +32,7 @@ #include #include +#include // Arch dependent #if defined(Q_OS_MAC) @@ -202,7 +203,7 @@ private: #ifdef __APPLE__ protected: - bool m_terminate; + QSemaphore m_terminate; void run(); #endif // __APPLE__ diff --git a/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp index fc95c6eba..8d308a8cf 100644 --- a/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp +++ b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp @@ -42,24 +42,20 @@ static bool HID_GetStrProperty(IOHIDDeviceRef dev, CFStringRef property, QString /** Initialize the USB monitor here */ -USBMonitor::USBMonitor(QObject *parent) : QThread(parent) +USBMonitor::USBMonitor(QObject *parent) : QThread(parent), m_terminate(1) { m_instance = this; hid_manager = NULL; listMutex = new QMutex(); knowndevices.clear(); qRegisterMetaType("USBPortInfo"); - m_terminate = false; start(); } USBMonitor::~USBMonitor() { - m_terminate = true; - - while (hid_manager != 0) { - this->sleep(10); - } + m_terminate.tryAcquire(); + wait(); } void USBMonitor::deviceEventReceived() @@ -205,7 +201,7 @@ void USBMonitor::run() return; } - while (!m_terminate) { + while (m_terminate.available()) { CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, false); } IOHIDManagerUnscheduleFromRunLoop(hid_manager, loop, kCFRunLoopDefaultMode); From 0bff51f79fb84ad00d23e7e61efd730f1c40aab9 Mon Sep 17 00:00:00 2001 From: David Ankers Date: Sun, 26 May 2013 02:13:43 +1000 Subject: [PATCH 038/120] Add uninstall information, Icon and other details Keeping Unicode intact this time --- package/winx86/openpilotgcs.nsi | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/package/winx86/openpilotgcs.nsi b/package/winx86/openpilotgcs.nsi index ea682d6a9..071b27ba5 100644 --- a/package/winx86/openpilotgcs.nsi +++ b/package/winx86/openpilotgcs.nsi @@ -262,9 +262,15 @@ Section ; create uninstall info ; Write the installation path into the registry WriteRegStr HKCU "Software\OpenPilot" "Install Location" $INSTDIR - ; Write the uninstall keys for Windows + ; Write the uninstall keys for Windows WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "DisplayName" "OpenPilot GCS" WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "UninstallString" '"$INSTDIR\Uninstall.exe"' + WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "DisplayIcon" '"$INSTDIR\bin\openpilotgcs.exe"' + WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "Publisher" "OpenPilot Team" + WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "DisplayVersion" "Stumpy" + WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "URLInfoAbout" "http://openpilot.org" + WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "HelpLink" "http://wiki.openpilot.org" + WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "EstimatedSize" 100600 WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "NoModify" 1 WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "NoRepair" 1 From 4f6c633815d597878ebf04b6caaf9704047b0914 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sat, 25 May 2013 14:27:27 +0200 Subject: [PATCH 039/120] OP-770: extend VersionInfo class to include most of the info available --- .../version_info/version_info.cpp.template | 88 ++++++++++++++++++- .../src/libs/version_info/version_info.h | 32 ++++++- 2 files changed, 114 insertions(+), 6 deletions(-) diff --git a/ground/openpilotgcs/src/libs/version_info/version_info.cpp.template b/ground/openpilotgcs/src/libs/version_info/version_info.cpp.template index 214ad7b3b..3e887c134 100644 --- a/ground/openpilotgcs/src/libs/version_info/version_info.cpp.template +++ b/ground/openpilotgcs/src/libs/version_info/version_info.cpp.template @@ -27,22 +27,102 @@ VersionInfo::VersionInfo() { } +QString VersionInfo::origin() +{ + return "${ORIGIN}"; +} + QString VersionInfo::revision() { return "${REVISION}"; } +QString VersionInfo::hash() +{ + return "${HASH}"; +} + +QString VersionInfo::uavoHashTxt() +{ + return "${UAVOSHA1TXT}"; +} + +QString VersionInfo::uavoHash() +{ + return "{ ${UAVOSHA1} }"; +} + +QString VersionInfo::label() +{ + return "${LABEL}"; +} + +QString VersionInfo::tag() +{ + return "${TAG}"; +} + +QString VersionInfo::tagOrBranch() +{ + return "${TAG_OR_BRANCH}"; +} + +QString VersionInfo::tagOrHash8() +{ + return "${TAG_OR_HASH8}"; +} + +QString VersionInfo::hash8() +{ + return "${HASH8}"; +} + +QString VersionInfo::fwTag() +{ + return "${FWTAG}"; +} + +QString VersionInfo::unixTime() +{ + return "${UNIXTIME}"; +} + +QString VersionInfo::dateTime() +{ + return "${DATETIME}"; +} + +QString VersionInfo::date() +{ + return "${DATE}"; +} + +QString VersionInfo::day() +{ + return "${DAY}"; +} + +QString VersionInfo::month() +{ + return "${MONTH}"; +} + QString VersionInfo::year() { return "${YEAR}"; } -QString VersionInfo::origin() +QString VersionInfo::hour() { - return "${ORIGIN}"; + return "${HOUR}"; } -QString VersionInfo::uavoHash() +QString VersionInfo::minute() { - return "{ ${UAVOSHA1} }"; + return "${MINUTE}"; +} + +QString VersionInfo::dirty() +{ + return "${DIRTY}"; } diff --git a/ground/openpilotgcs/src/libs/version_info/version_info.h b/ground/openpilotgcs/src/libs/version_info/version_info.h index b517e7307..f9c9a8995 100644 --- a/ground/openpilotgcs/src/libs/version_info/version_info.h +++ b/ground/openpilotgcs/src/libs/version_info/version_info.h @@ -27,12 +27,40 @@ #include +/** + * @class VersionInfo + * @brief Library class to provide version info information extracted from a git repository. + * + * Class static members return read-only strings extracted from a git repository at compile time. + * The content is generated by the version-info.py utility using template. + * + * @note If repository or git utility is unavailable, strings can be empty or be "None". + * So do not assume they have some particular format when used, use them as strings only. + * + * More info: http://wiki.openpilot.org/display/Doc/Building+and+Packaging+Overview + */ class VersionInfo { public: - static QString revision(); - static QString year(); static QString origin(); + static QString revision(); + static QString hash(); + static QString uavoHashTxt(); static QString uavoHash(); + static QString label(); + static QString tag(); + static QString tagOrBranch(); + static QString tagOrHash8(); + static QString hash8(); + static QString fwTag(); + static QString unixTime(); + static QString dateTime(); + static QString date(); + static QString day(); + static QString month(); + static QString year(); + static QString hour(); + static QString minute(); + static QString dirty(); private: VersionInfo(); }; From 444431579ed2db63cd253e65798f0cf502c5b0c7 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sat, 25 May 2013 16:40:58 +0200 Subject: [PATCH 040/120] OP-770: add/rename some version-info.py template variables --- Makefile | 2 +- flight/templates/firmware_info.c.template | 5 ++--- .../libs/version_info/version_info.cpp.template | 12 ++++++------ .../src/libs/version_info/version_info.h | 2 +- .../src/plugins/config/configpipxtremewidget.cpp | 16 ++++++++-------- .../src/plugins/coreplugin/authorsdialog.cpp | 4 ++-- .../src/plugins/coreplugin/versiondialog.cpp | 4 ++-- .../uavobjectutil/uavobjectutilmanager.cpp | 14 +++++++------- .../plugins/uploader/uploadergadgetwidget.cpp | 2 +- make/scripts/version-info.py | 11 ++++++----- make/templates/build-info.txt | 2 +- 11 files changed, 37 insertions(+), 37 deletions(-) diff --git a/Makefile b/Makefile index 58f849bf7..7388b6767 100644 --- a/Makefile +++ b/Makefile @@ -563,7 +563,7 @@ $$(UAVO_COLLECTION_DIR)/$(1)/uavohash: $$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml # The sed bit truncates the UAVO hash to 16 hex digits $$(V1) $$(VERSION_INFO) \ --uavodir=$$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml/shared/uavobjectdefinition \ - --format='$$$${UAVOSHA1TXT}' | \ + --format='$$$${UAVO_HASH}' | \ $(SED) -e 's|\(................\).*|\1|' > $$@ $$(V0) @$(ECHO) " UAVOHASH $(1) ->" $$$$(cat $$(UAVO_COLLECTION_DIR)/$(1)/uavohash) diff --git a/flight/templates/firmware_info.c.template b/flight/templates/firmware_info.c.template index babc4eff3..4fe8842f3 100644 --- a/flight/templates/firmware_info.c.template +++ b/flight/templates/firmware_info.c.template @@ -30,7 +30,6 @@ /** * We have 100 bytes for the whole description. * - * * Structure is: * 4 bytes: header: "OpFw". * 4 bytes: GIT commit tag (short version of SHA1). @@ -66,6 +65,6 @@ const struct fw_version_info fw_version_blob __attribute__((used)) __attribute__ .board_type = ${BOARD_TYPE}, .board_revision = ${BOARD_REVISION}, .commit_tag_name = "${FWTAG}", - .sha1sum = { ${SHA1} }, - .uavosha1 = { ${UAVOSHA1} }, + .sha1sum = { ${IMAGE_HASH_ARRAY} }, + .uavosha1 = { ${UAVO_HASH_ARRAY} }, }; diff --git a/ground/openpilotgcs/src/libs/version_info/version_info.cpp.template b/ground/openpilotgcs/src/libs/version_info/version_info.cpp.template index 3e887c134..6486eb9a3 100644 --- a/ground/openpilotgcs/src/libs/version_info/version_info.cpp.template +++ b/ground/openpilotgcs/src/libs/version_info/version_info.cpp.template @@ -42,14 +42,14 @@ QString VersionInfo::hash() return "${HASH}"; } -QString VersionInfo::uavoHashTxt() -{ - return "${UAVOSHA1TXT}"; -} - QString VersionInfo::uavoHash() { - return "{ ${UAVOSHA1} }"; + return "${UAVO_HASH}"; +} + +QString VersionInfo::uavoHashArray() +{ + return "{ ${UAVO_HASH_ARRAY} }"; } QString VersionInfo::label() diff --git a/ground/openpilotgcs/src/libs/version_info/version_info.h b/ground/openpilotgcs/src/libs/version_info/version_info.h index f9c9a8995..ede18e81c 100644 --- a/ground/openpilotgcs/src/libs/version_info/version_info.h +++ b/ground/openpilotgcs/src/libs/version_info/version_info.h @@ -44,8 +44,8 @@ public: static QString origin(); static QString revision(); static QString hash(); - static QString uavoHashTxt(); static QString uavoHash(); + static QString uavoHashArray(); static QString label(); static QString tag(); static QString tagOrBranch(); diff --git a/ground/openpilotgcs/src/plugins/config/configpipxtremewidget.cpp b/ground/openpilotgcs/src/plugins/config/configpipxtremewidget.cpp index 9bbbab0d9..27f0603ac 100644 --- a/ground/openpilotgcs/src/plugins/config/configpipxtremewidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configpipxtremewidget.cpp @@ -234,15 +234,15 @@ void ConfigPipXtremeWidget::updateStatus(UAVObject *object) UAVObjectField *descField = object->getField("Description"); if (descField) { /* - * This looks like a binary with a description at the end - * 4 bytes: header: "OpFw" - * 4 bytes: git commit hash (short version of SHA1) - * 4 bytes: Unix timestamp of last git commit - * 2 bytes: target platform. Should follow same rule as BOARD_TYPE and BOARD_REVISION in board define files. - * 26 bytes: commit tag if it is there, otherwise "Unreleased". Zero-padded - * ---- 40 bytes limit --- + * This looks like a binary with a description at the end: + * 4 bytes: header: "OpFw". + * 4 bytes: GIT commit tag (short version of SHA1). + * 4 bytes: Unix timestamp of compile time. + * 2 bytes: target platform. Should follow same rule as BOARD_TYPE and BOARD_REVISION in board define files. + * 26 bytes: commit tag if it is there, otherwise branch name. '-dirty' may be added if needed. Zero-padded. * 20 bytes: SHA1 sum of the firmware. - * 40 bytes: free for now. + * 20 bytes: SHA1 sum of the uavo definitions. + * 20 bytes: free for now. */ char buf[OPLinkStatus::DESCRIPTION_NUMELEM]; for (unsigned int i = 0; i < 26; ++i) { diff --git a/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.cpp b/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.cpp index 847fb5369..690f3dec0 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.cpp +++ b/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.cpp @@ -76,10 +76,10 @@ AuthorsDialog::AuthorsDialog(QWidget *parent) ideRev = tr("From revision %1
").arg(VersionInfo::revision().left(10)); QString uavoHashStr; - if (VersionInfo::uavoHash().length() > 15) { + if (VersionInfo::uavoHashArray().length() > 15) { // : This gets conditionally inserted as argument %11 into the description string. QByteArray uavoHashArray; - QString uavoHash = VersionInfo::uavoHash(); + QString uavoHash = VersionInfo::uavoHashArray(); uavoHash.chop(2); uavoHash.remove(0, 2); uavoHash = uavoHash.trimmed(); diff --git a/ground/openpilotgcs/src/plugins/coreplugin/versiondialog.cpp b/ground/openpilotgcs/src/plugins/coreplugin/versiondialog.cpp index 8fb160ef3..995078ee5 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/versiondialog.cpp +++ b/ground/openpilotgcs/src/plugins/coreplugin/versiondialog.cpp @@ -60,10 +60,10 @@ VersionDialog::VersionDialog(QWidget *parent) layout->setSizeConstraint(QLayout::SetFixedSize); QString uavoHashStr; - if (VersionInfo::uavoHash().length() > 15) { + if (VersionInfo::uavoHashArray().length() > 15) { // : This gets conditionally inserted as argument %11 into the description string. QByteArray uavoHashArray; - QString uavoHash = VersionInfo::uavoHash(); + QString uavoHash = VersionInfo::uavoHashArray(); uavoHash.chop(2); uavoHash.remove(0, 2); uavoHash = uavoHash.trimmed(); diff --git a/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp b/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp index c89683412..34133de24 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp @@ -423,14 +423,14 @@ bool UAVObjectUtilManager::descriptionToStructure(QByteArray desc, deviceDescrip { if (desc.startsWith("OpFw")) { /* - * This looks like a binary with a description at the end - * 4 bytes: header: "OpFw" - * 4 bytes: git commit hash (short version of SHA1) - * 4 bytes: Unix timestamp of last git commit - * 2 bytes: target platform. Should follow same rule as BOARD_TYPE and BOARD_REVISION in board define files. - * 26 bytes: commit tag if it is there, otherwise "Unreleased". Zero-padded + * This looks like a binary with a description at the end: + * 4 bytes: header: "OpFw". + * 4 bytes: GIT commit tag (short version of SHA1). + * 4 bytes: Unix timestamp of compile time. + * 2 bytes: target platform. Should follow same rule as BOARD_TYPE and BOARD_REVISION in board define files. + * 26 bytes: commit tag if it is there, otherwise branch name. '-dirty' may be added if needed. Zero-padded. * 20 bytes: SHA1 sum of the firmware. - * 20 bytes: SHA1 sum of the UAVO definition files. + * 20 bytes: SHA1 sum of the uavo definitions. * 20 bytes: free for now. */ diff --git a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp index 1bdc0e4ef..2b26332c4 100644 --- a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp @@ -957,7 +957,7 @@ void UploaderGadgetWidget::versionMatchCheck() UAVObjectUtilManager *utilMngr = pm->getObject(); deviceDescriptorStruct boardDescription = utilMngr->getBoardDescriptionStruct(); QByteArray uavoHashArray; - QString uavoHash = VersionInfo::uavoHash(); + QString uavoHash = VersionInfo::uavoHashArray(); uavoHash.chop(2); uavoHash.remove(0, 2); diff --git a/make/scripts/version-info.py b/make/scripts/version-info.py index 4b9d366f3..79cf95904 100644 --- a/make/scripts/version-info.py +++ b/make/scripts/version-info.py @@ -271,7 +271,7 @@ def xtrim(string, suffix, length): assert n > 0, "length of truncated string+suffix exceeds maximum length" return ''.join([string[:n], '+', suffix]) -def get_hash_of_dirs(directory, verbose = 0, raw = 0): +def get_hash_of_dirs(directory, verbose = 0, raw = 0, n = 40): """Return hash of XML files from UAVObject definition directory""" import hashlib, os SHAhash = hashlib.sha1() @@ -322,7 +322,7 @@ def get_hash_of_dirs(directory, verbose = 0, raw = 0): print 'Final hash is', SHAhash.hexdigest() if raw == 1: - return SHAhash.hexdigest() + return SHAhash.hexdigest()[:n] else: hex_stream = lambda s:",".join(['0x'+hex(ord(c))[2:].zfill(2) for c in s]) return hex_stream(SHAhash.digest()) @@ -417,9 +417,10 @@ string given. MINUTE = r.time('%M'), BOARD_TYPE = args.type, BOARD_REVISION = args.revision, - SHA1 = sha1(args.image), - UAVOSHA1TXT = get_hash_of_dirs(args.uavodir, verbose = 0, raw = 1), - UAVOSHA1 = get_hash_of_dirs(args.uavodir, verbose = 0, raw = 0), + UAVO_HASH = get_hash_of_dirs(args.uavodir, verbose = 0, raw = 1), + UAVO_HASH8 = get_hash_of_dirs(args.uavodir, verbose = 0, raw = 1, n = 8), + UAVO_HASH_ARRAY = get_hash_of_dirs(args.uavodir, verbose = 0, raw = 0), + IMAGE_HASH_ARRAY = sha1(args.image), ) # Process positional arguments in the form of: diff --git a/make/templates/build-info.txt b/make/templates/build-info.txt index ce348b86c..4f9b9d75c 100644 --- a/make/templates/build-info.txt +++ b/make/templates/build-info.txt @@ -15,7 +15,7 @@ ORIGIN='${ORIGIN}' REVISION='${REVISION}' HASH='${HASH}' -UAVOSHA1='${UAVOSHA1TXT}' +UAVO_HASH='${UAVO_HASH}' LABEL='${LABEL}' TAG='${TAG}' TAG_OR_BRANCH='${TAG_OR_BRANCH}' From f62391028acb2bb3a0b0e1307e5ec0ceca5a6902 Mon Sep 17 00:00:00 2001 From: Mathieu Rondonneau Date: Sat, 25 May 2013 19:08:53 -0700 Subject: [PATCH 041/120] OP-958: Add function header doc and give credit to Richard (not mentionned in a previous commit). I gorgot to mention that the following commit was a patch from Richard. Thanks to richard for suggesting this patch. commit 45e18127a33ea2f7a510e921edc4ea67fede384a Author: Mathieu Rondonneau Date: Sat May 25 08:06:41 2013 -0700 OP-958: adding patch for map to use proper lock mechanism. --- .../plugins/ophid/src/ophid_usbmon_mac.cpp | 53 +++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp index 8d308a8cf..8524c4b57 100644 --- a/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp +++ b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp @@ -40,7 +40,9 @@ static bool HID_GetIntProperty(IOHIDDeviceRef dev, CFStringRef property, int *va static bool HID_GetStrProperty(IOHIDDeviceRef dev, CFStringRef property, QString & value); /** - Initialize the USB monitor here + * \brief Initialize the USB monitor + * + * \note */ USBMonitor::USBMonitor(QObject *parent) : QThread(parent), m_terminate(1) { @@ -52,17 +54,32 @@ USBMonitor::USBMonitor(QObject *parent) : QThread(parent), m_terminate(1) start(); } +/** + * \brief Free the USB monitor + * + * \note + */ USBMonitor::~USBMonitor() { m_terminate.tryAcquire(); wait(); } +/** + * \brief Event received callback + * + * \note + */ void USBMonitor::deviceEventReceived() { qDebug() << "Device event"; } +/** + * \brief instace of USB monitor + * + * \note + */ USBMonitor *USBMonitor::instance() { return m_instance; @@ -71,6 +88,11 @@ USBMonitor *USBMonitor::instance() USBMonitor *USBMonitor::m_instance = 0; +/** + * \brief Remove device + * + * \note + */ void USBMonitor::removeDevice(IOHIDDeviceRef dev) { for (int i = 0; i < knowndevices.length(); i++) { @@ -85,8 +107,11 @@ void USBMonitor::removeDevice(IOHIDDeviceRef dev) } } + /** - * @brief Static callback for the USB driver to indicate device removed + * \brief Static callback for the USB driver to indicate device removed + * + * \note */ void USBMonitor::detach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev) { @@ -98,6 +123,12 @@ void USBMonitor::detach_callback(void *context, IOReturn r, void *hid_mgr, IOHID instance()->removeDevice(dev); } + +/** + * \brief Add device + * + * \note + */ void USBMonitor::addDevice(USBPortInfo info) { QMutexLocker locker(listMutex); @@ -107,6 +138,12 @@ void USBMonitor::addDevice(USBPortInfo info) emit deviceDiscovered(); } + +/** + * \brief Attach device + * + * \note + */ void USBMonitor::attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev) { Q_UNUSED(context); @@ -139,8 +176,11 @@ void USBMonitor::attach_callback(void *context, IOReturn r, void *hid_mgr, IOHID } } + /** - Returns a list of all currently available devices + * \brief Returns a list of all currently available devices + * + * \note */ QList USBMonitor::availableDevices() { @@ -174,6 +214,12 @@ QList USBMonitor::availableDevices(int vid, int pid, int bcdDeviceM return thePortsWeWant; } + +/** + * \brief USBMonitor thread + * + * \note + */ void USBMonitor::run() { IOReturn ret; @@ -251,3 +297,4 @@ static bool HID_GetStrProperty(IOHIDDeviceRef dev, CFStringRef property, QString } return false; } + From d5eccea78f3acb027e7af5e01f6e41220299bad9 Mon Sep 17 00:00:00 2001 From: David Ankers Date: Sun, 26 May 2013 15:48:02 +1000 Subject: [PATCH 042/120] Comment and header renames, change PipX to OPLink Mini --- flight/libraries/op_dfu.c | 4 ++-- flight/targets/boards/coptercontrol/bootloader/pios_board.c | 2 +- flight/targets/boards/oplinkmini/bootloader/pios_board.c | 2 +- flight/targets/common/bootloader_updater/pios_board.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/flight/libraries/op_dfu.c b/flight/libraries/op_dfu.c index 882b106a8..e952a886c 100644 --- a/flight/libraries/op_dfu.c +++ b/flight/libraries/op_dfu.c @@ -245,7 +245,7 @@ void processComand(uint8_t *xReceive_Buffer) } break; case Remote_flash_via_spi: - result = false; // No support for this for the PipX + result = false; // No support for this for the OPLink Mini break; default: result = 0; @@ -476,7 +476,7 @@ bool flash_read(uint8_t *buffer, uint32_t adr, DFUProgType type) { switch (type) { case Remote_flash_via_spi: - return false; // We should not get this for the PipX + return false; // We should not get this for the OPLink Mini break; case Self_flash: diff --git a/flight/targets/boards/coptercontrol/bootloader/pios_board.c b/flight/targets/boards/coptercontrol/bootloader/pios_board.c index bd437df42..8071a3c32 100644 --- a/flight/targets/boards/coptercontrol/bootloader/pios_board.c +++ b/flight/targets/boards/coptercontrol/bootloader/pios_board.c @@ -3,7 +3,7 @@ * * @file pios_board.c * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Defines board specific static initializers for hardware for the PipBee board. + * @brief Defines board specific static initializers for hardware for the CopterControl board. * @see The GNU Public License (GPL) Version 3 * *****************************************************************************/ diff --git a/flight/targets/boards/oplinkmini/bootloader/pios_board.c b/flight/targets/boards/oplinkmini/bootloader/pios_board.c index 7bcd5ce8a..94a73e708 100644 --- a/flight/targets/boards/oplinkmini/bootloader/pios_board.c +++ b/flight/targets/boards/oplinkmini/bootloader/pios_board.c @@ -3,7 +3,7 @@ * * @file pios_board.c * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Defines board specific static initializers for hardware for the PipBee board. + * @brief Defines board specific static initializers for hardware for the OPLink Mini board. * @see The GNU Public License (GPL) Version 3 * *****************************************************************************/ diff --git a/flight/targets/common/bootloader_updater/pios_board.c b/flight/targets/common/bootloader_updater/pios_board.c index 8ef335e3f..1557c7b83 100644 --- a/flight/targets/common/bootloader_updater/pios_board.c +++ b/flight/targets/common/bootloader_updater/pios_board.c @@ -3,7 +3,7 @@ * * @file pios_board.c * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Defines board specific static initializers for hardware for the PipBee board. + * @brief Defines board specific static initializers for hardware for the OPLink Mini board. * @see The GNU Public License (GPL) Version 3 * *****************************************************************************/ From 892da0d9775d6d390ec00379d07b7f949bfca609 Mon Sep 17 00:00:00 2001 From: David Ankers Date: Sun, 26 May 2013 15:56:59 +1000 Subject: [PATCH 043/120] Update comments in linux packaging scripts to OPLink Mini --- package/linux/45-openpilot-permissions.rules | 2 +- package/linux/deb_common/openpilot.udev | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package/linux/45-openpilot-permissions.rules b/package/linux/45-openpilot-permissions.rules index d04d31b7f..74e415c39 100644 --- a/package/linux/45-openpilot-permissions.rules +++ b/package/linux/45-openpilot-permissions.rules @@ -3,7 +3,7 @@ SUBSYSTEM=="usb", ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="415a", MODE="0664", GROUP="plugdev" # OpenPilot coptercontrol flight control board SUBSYSTEM=="usb", ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="415b", MODE="0664", GROUP="plugdev" - # OpenPilot Pipx radio modem board + # OpenPilot OPLink Mini radio modem board SUBSYSTEM=="usb", ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="415c", MODE="0664", GROUP="plugdev" # unprogrammed openpilot flight control board SUBSYSTEM=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5750", MODE="0664", GROUP="plugdev" diff --git a/package/linux/deb_common/openpilot.udev b/package/linux/deb_common/openpilot.udev index 3d84dd426..a7852b192 100644 --- a/package/linux/deb_common/openpilot.udev +++ b/package/linux/deb_common/openpilot.udev @@ -4,7 +4,7 @@ SUBSYSTEM=="usb", ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="415a", MODE="0664", GROUP="plugdev" # OpenPilot CopterControl flight control board SUBSYSTEM=="usb", ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="415b", MODE="0664", GROUP="plugdev" - # OpenPilot Pipx radio modem board + # OpenPilot OPlink Mini radio modem board SUBSYSTEM=="usb", ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="415c", MODE="0664", GROUP="plugdev" # OpenPilot CopterControl3D flight control board SUBSYSTEM=="usb", ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="415d", MODE="0664", GROUP="plugdev" From a5b856d1bc5408335a3020b10b1bc8c0f90fef03 Mon Sep 17 00:00:00 2001 From: David Ankers Date: Sun, 26 May 2013 16:04:55 +1000 Subject: [PATCH 044/120] Change board description name to OPLink Mini --- .../boards/oplinkmini/pios_usb_board_data.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/flight/targets/boards/oplinkmini/pios_usb_board_data.c b/flight/targets/boards/oplinkmini/pios_usb_board_data.c index 5aa5ab5f9..be48bdf78 100644 --- a/flight/targets/boards/oplinkmini/pios_usb_board_data.c +++ b/flight/targets/boards/oplinkmini/pios_usb_board_data.c @@ -36,15 +36,16 @@ static const uint8_t usb_product_id[20] = { sizeof(usb_product_id), USB_DESC_TYPE_STRING, + 'O', 0, 'P', 0, + 'L', 0, 'i', 0, - 'p', 0, - 'X', 0, - 't', 0, - 'r', 0, - 'e', 0, - 'm', 0, - 'e', 0, + 'n', 0, + 'k', 0, + 'M', 0, + 'i', 0, + 'n', 0, + 'i', 0, }; static uint8_t usb_serial_number[2 + PIOS_SYS_SERIAL_NUM_ASCII_LEN * 2 + (sizeof(PIOS_USB_BOARD_SN_SUFFIX) - 1) * 2] = { From f7a9f94a367ec72d384c307beacf8930fe13add7 Mon Sep 17 00:00:00 2001 From: David Ankers Date: Sun, 26 May 2013 16:09:55 +1000 Subject: [PATCH 045/120] Missing file header --- .../targets/boards/oplinkmini/board_hw_defs.c | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/flight/targets/boards/oplinkmini/board_hw_defs.c b/flight/targets/boards/oplinkmini/board_hw_defs.c index 42598b96c..cec0d3d51 100644 --- a/flight/targets/boards/oplinkmini/board_hw_defs.c +++ b/flight/targets/boards/oplinkmini/board_hw_defs.c @@ -1,3 +1,29 @@ +/** + ****************************************************************************** + * + * @file board_hw_defs.c.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. + * @brief Defines board hardware for the OpenPilot OPLink Mini board. + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + #if defined(PIOS_INCLUDE_LED) #include From 7a9466bbf9c26381bef4372e2a8f412fae3276c9 Mon Sep 17 00:00:00 2001 From: David Ankers Date: Sun, 26 May 2013 16:12:35 +1000 Subject: [PATCH 046/120] State in the header which board this is for --- flight/targets/boards/oplinkmini/pios_board.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flight/targets/boards/oplinkmini/pios_board.h b/flight/targets/boards/oplinkmini/pios_board.h index bc0a9f321..92bd020e0 100644 --- a/flight/targets/boards/oplinkmini/pios_board.h +++ b/flight/targets/boards/oplinkmini/pios_board.h @@ -3,7 +3,7 @@ * * @file pios_board.h * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Defines board hardware for the OpenPilot Version 1.1 hardware. + * @brief Defines PiOS board hardware for the OpenPilot OPLink Mini board. * @see The GNU Public License (GPL) Version 3 * *****************************************************************************/ From 9cc314f7dbd871a6ee9550d633f539f5e3a41831 Mon Sep 17 00:00:00 2001 From: David Ankers Date: Sun, 26 May 2013 16:29:33 +1000 Subject: [PATCH 047/120] Remove Rawhid folder, replaced by OPHid from Mathieu, Richard and Voha --- .../src/plugins/rawhid/RawHID.pluginspec | 10 - .../src/plugins/rawhid/pjrc_rawhid.h | 163 ------ .../src/plugins/rawhid/pjrc_rawhid_mac.cpp | 423 --------------- .../src/plugins/rawhid/pjrc_rawhid_unix.cpp | 421 --------------- .../src/plugins/rawhid/pjrc_rawhid_win.cpp | 483 ------------------ .../src/plugins/rawhid/rawhid.cpp | 465 ----------------- .../openpilotgcs/src/plugins/rawhid/rawhid.h | 95 ---- .../src/plugins/rawhid/rawhid.pri | 3 - .../src/plugins/rawhid/rawhid.pro | 52 -- .../src/plugins/rawhid/rawhid_const.h | 41 -- .../plugins/rawhid/rawhid_dependencies.pri | 1 - .../src/plugins/rawhid/rawhid_global.h | 39 -- .../src/plugins/rawhid/rawhidplugin.cpp | 186 ------- .../src/plugins/rawhid/rawhidplugin.h | 99 ---- .../src/plugins/rawhid/usbmonitor.h | 202 -------- .../src/plugins/rawhid/usbmonitor_linux.cpp | 201 -------- .../src/plugins/rawhid/usbmonitor_mac.cpp | 243 --------- .../src/plugins/rawhid/usbmonitor_win.cpp | 376 -------------- .../src/plugins/rawhid/usbsignalfilter.cpp | 19 - .../src/plugins/rawhid/usbsignalfilter.h | 20 - 20 files changed, 3542 deletions(-) delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/RawHID.pluginspec delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid.h delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_mac.cpp delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_unix.cpp delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_win.cpp delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/rawhid.cpp delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/rawhid.h delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/rawhid.pri delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/rawhid.pro delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/rawhid_const.h delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/rawhid_dependencies.pri delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/rawhid_global.h delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/rawhidplugin.cpp delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/rawhidplugin.h delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/usbmonitor.h delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/usbmonitor_linux.cpp delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/usbmonitor_mac.cpp delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/usbmonitor_win.cpp delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/usbsignalfilter.cpp delete mode 100644 ground/openpilotgcs/src/plugins/rawhid/usbsignalfilter.h diff --git a/ground/openpilotgcs/src/plugins/rawhid/RawHID.pluginspec b/ground/openpilotgcs/src/plugins/rawhid/RawHID.pluginspec deleted file mode 100644 index 7cb190038..000000000 --- a/ground/openpilotgcs/src/plugins/rawhid/RawHID.pluginspec +++ /dev/null @@ -1,10 +0,0 @@ - -The OpenPilot Project - (C) 2010 OpenPilot Project - GNU Public License (GPL) Version 3 - Connection to OpenPilot board using RawHID USB interface - http://www.openpilot.org - - - - diff --git a/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid.h b/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid.h deleted file mode 100644 index 486f88b92..000000000 --- a/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid.h +++ /dev/null @@ -1,163 +0,0 @@ -/** - ****************************************************************************** - * - * @file pjrc_rawhid.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @addtogroup RawHIDPlugin Raw HID Plugin - * @{ - * @brief Impliments a HID USB connection to the flight hardware as a QIODevice - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PJRC_RAWHID_H -#define PJRC_RAWHID_H - -#include -#include -#include -#include -#include -#include -#include "rawhid_global.h" - -#if defined(Q_OS_MAC) - -#include -#include -#include - -#elif defined(Q_OS_UNIX) -// #elif defined(Q_OS_LINUX) -#include -#include -#include -#elif defined(Q_OS_WIN32) -#include -#include -#include -#include -#endif - -// ************ - -#if defined(Q_OS_MAC) - -// todo: - -#elif defined(Q_OS_UNIX) -// #elif defined(Q_OS_LINUX) - -typedef struct hid_struct hid_t; -struct hid_struct { - usb_dev_handle *usb; - int open; - int iface; - int ep_in; - int ep_out; - struct hid_struct *prev; - struct hid_struct *next; -}; - -#elif defined(Q_OS_WIN32) - -typedef struct hid_struct hid_t; - -struct hid_struct { - HANDLE handle; - int open; - struct hid_struct *prev; - struct hid_struct *next; -}; - -#endif // if defined(Q_OS_MAC) - - -class RAWHID_EXPORT pjrc_rawhid : public QObject { - Q_OBJECT - -public: - pjrc_rawhid(); - ~pjrc_rawhid(); - int open(int max, int vid, int pid, int usage_page, int usage); - int receive(int, void *buf, int len, int timeout); - void close(int num); - int send(int num, void *buf, int len, int timeout); - QString getserial(int num); -signals: - void deviceUnplugged(int); - -private: -#if defined(Q_OS_MAC) - - // Static callbacks called by the HID system with handles to the PJRC object - static void attach_callback(void *, IOReturn, void *, IOHIDDeviceRef); - static void dettach_callback(void *, IOReturn, void *hid_mgr, IOHIDDeviceRef dev); - static void input_callback(void *, IOReturn, void *, IOHIDReportType, uint32_t, uint8_t *, CFIndex); - static void timeout_callback(CFRunLoopTimerRef, void *); - - // Non static methods to call into - void attach(IOHIDDeviceRef dev); - void dettach(IOHIDDeviceRef dev); - void input(uint8_t *, CFIndex); - - // Platform specific handles for the USB device - IOHIDManagerRef hid_manager; - IOHIDDeviceRef dev; - CFRunLoopRef the_correct_runloop; - CFRunLoopRef received_runloop; - - static const int BUFFER_SIZE = 64; - uint8_t buffer[BUFFER_SIZE]; - int attach_count; - int buffer_count; - bool device_open; - bool unplugged; - - QMutex *m_writeMutex; - QMutex *m_readMutex; -#elif defined(Q_OS_UNIX) - - hid_t * first_hid; - hid_t *last_hid; - - void add_hid(hid_t *h); - hid_t *get_hid(int num); - void free_all_hid(void); - void hid_close(hid_t *hid); - int hid_parse_item(uint32_t *val, uint8_t * *data, const uint8_t *end); - -#elif defined(Q_OS_WIN32) - - hid_t * first_hid; - hid_t *last_hid; - HANDLE rx_event; - HANDLE tx_event; - CRITICAL_SECTION rx_mutex; - CRITICAL_SECTION tx_mutex; - - void add_hid(hid_t *h); - hid_t *get_hid(int num); - void free_all_hid(void); - void hid_close(hid_t *hid); - void print_win32_err(DWORD err); - -#endif // if defined(Q_OS_MAC) -}; - -#endif // ifndef PJRC_RAWHID_H diff --git a/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_mac.cpp b/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_mac.cpp deleted file mode 100644 index 1ca909ccd..000000000 --- a/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_mac.cpp +++ /dev/null @@ -1,423 +0,0 @@ -/* @file pjrc_rawhid_mac.cpp - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @addtogroup RawHIDPlugin Raw HID Plugin - * @{ - * @brief Impliments a HID USB connection to the flight hardware as a QIODevice - *****************************************************************************/ - -/* Simple Raw HID functions for Linux - for use with Teensy RawHID example - * http://www.pjrc.com/teensy/rawhid.html - * Copyright (c) 2009 PJRC.COM, LLC - * - * rawhid_open - open 1 or more devices - * rawhid_recv - receive a packet - * rawhid_send - send a packet - * rawhid_close - close a device - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above description, website URL and copyright notice and this permission - * notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * Version 1.0: Initial Release - */ - - -#include "pjrc_rawhid.h" - -#include -#include -#include -#include -#include - -struct timeout_info { - CFRunLoopRef loopRef; - bool timed_out; -}; - -pjrc_rawhid::pjrc_rawhid() : - device_open(false), hid_manager(NULL), buffer_count(0), unplugged(false) -{ - m_writeMutex = new QMutex(); - m_readMutex = new QMutex(); -} - -pjrc_rawhid::~pjrc_rawhid() -{ - if (device_open) { - close(0); - } - - if (m_writeMutex) { - delete m_writeMutex; - m_writeMutex = NULL; - } - - if (m_readMutex) { - delete m_readMutex; - m_readMutex = NULL; - } -} - -/** - * @brief open - open 1 or more devices - * @param[in] max maximum number of devices to open - * @param[in] vid Vendor ID, or -1 if any - * @param[in] pid Product ID, or -1 if any - * @param[in] usage_page top level usage page, or -1 if any - * @param[in] usage top level usage number, or -1 if any - * @returns actual number of devices opened - */ -int pjrc_rawhid::open(int max, int vid, int pid, int usage_page, int usage) -{ - CFMutableDictionaryRef dict; - CFNumberRef num; - IOReturn ret; - - Q_ASSERT(hid_manager == NULL); - Q_ASSERT(device_open == false); - - attach_count = 0; - - // Start the HID Manager - hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); - if (hid_manager == NULL || CFGetTypeID(hid_manager) != IOHIDManagerGetTypeID()) { - if (hid_manager) { - CFRelease(hid_manager); - } - return 0; - } - - if (vid > 0 || pid > 0 || usage_page > 0 || usage > 0) { - // Tell the HID Manager what type of devices we want - dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (!dict) { - return 0; - } - if (vid > 0) { - num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &vid); - CFDictionarySetValue(dict, CFSTR(kIOHIDVendorIDKey), num); - CFRelease(num); - } - if (pid > 0) { - num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &pid); - CFDictionarySetValue(dict, CFSTR(kIOHIDProductIDKey), num); - CFRelease(num); - } - if (usage_page > 0) { - num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage_page); - CFDictionarySetValue(dict, CFSTR(kIOHIDPrimaryUsagePageKey), num); - CFRelease(num); - } - if (usage > 0) { - num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage); - CFDictionarySetValue(dict, CFSTR(kIOHIDPrimaryUsageKey), num); - CFRelease(num); - } - IOHIDManagerSetDeviceMatching(hid_manager, dict); - CFRelease(dict); - } else { - IOHIDManagerSetDeviceMatching(hid_manager, NULL); - } - - // Set the run loop reference before configuring the attach callback - the_correct_runloop = CFRunLoopGetCurrent(); - - // set up a callbacks for device attach & detach - IOHIDManagerScheduleWithRunLoop(hid_manager, CFRunLoopGetCurrent(), - kCFRunLoopDefaultMode); - IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, pjrc_rawhid::attach_callback, this); - IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, pjrc_rawhid::dettach_callback, this); - ret = IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone); - if (ret != kIOReturnSuccess) { - IOHIDManagerUnscheduleFromRunLoop(hid_manager, - CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); - CFRelease(hid_manager); - return 0; - } - - // let it do the callback for all devices - while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) == kCFRunLoopRunHandledSource) { - ; - } - - // count up how many were added by the callback - return attach_count; -} - -/** - * @brief receive - receive a packet - * @param[in] num device to receive from (unused now) - * @param[in] buf buffer to receive packet - * @param[in] len buffer's size - * @param[in] timeout = time to wait, in milliseconds - * @returns number of bytes received, or -1 on error - */ -int pjrc_rawhid::receive(int, void *buf, int len, int timeout) -{ - QMutexLocker locker(m_readMutex); - - Q_UNUSED(locker); - - if (!device_open) { - return -1; - } - - // Pass information to the callback to stop this run loop and signal if a timeout occurred - struct timeout_info info; - info.loopRef = CFRunLoopGetCurrent();; - info.timed_out = false; - CFRunLoopTimerContext context; - memset(&context, 0, sizeof(context)); - context.info = &info; - - // Set up the timer for the timeout - CFRunLoopTimerRef timer; - timer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent() + (double)timeout / 1000.0, 0, 0, 0, timeout_callback, &context); - CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode); - - received_runloop = CFRunLoopGetCurrent(); - - // Run the CFRunLoop until either a timeout or data is available - while (1) { - if (buffer_count != 0) { - if (len > buffer_count) { - len = buffer_count; - } - memcpy(buf, buffer, len); - buffer_count = 0; - break; - } else if (info.timed_out) { - len = 0; - break; - } - CFRunLoopRun(); // Wait for data - } - - CFRunLoopTimerInvalidate(timer); - CFRelease(timer); - - received_runloop = NULL; - - return len; -} - -/** - * @brief Helper class that will workaround the fact - * that the HID send is broken on OSX - */ -class Sender : public QThread { -public: - Sender(IOHIDDeviceRef d, uint8_t *b, int l) : - dev(d), buf(b), len(l), result(-1) {} - - void run() - { - ret = IOHIDDeviceSetReport(dev, kIOHIDReportTypeOutput, 2, buf, len); - result = (ret == kIOReturnSuccess) ? len : -1; - } - - int result; - IOReturn ret; -private: - IOHIDDeviceRef dev; - uint8_t *buf; - int len; -}; - -/** - * @brief send - send a packet - * @param[in] num device to transmit to (zero based) - * @param[in] buf buffer containing packet to send - * @param[in] len number of bytes to transmit - * @param[in] timeout = time to wait, in milliseconds - * @returns number of bytes sent, or -1 on error - */ -int pjrc_rawhid::send(int, void *buf, int len, int timeout) -{ - // This lock ensures that when closing we don't do it until the - // write has terminated (and then the device_open flag is set to false) - QMutexLocker locker(m_writeMutex); - - Q_UNUSED(locker); - - if (!device_open || unplugged) { - return -1; - } - - uint8_t *report_buf = (uint8_t *)malloc(len); - memcpy(&report_buf[0], buf, len); - - QEventLoop el; - Sender sender(dev, report_buf, len); - connect(&sender, SIGNAL(finished()), &el, SLOT(quit())); - sender.start(); - QTimer::singleShot(timeout, &el, SLOT(quit())); - el.exec(); - - return sender.result; -} - -// ! Get the serial number for a HID device -QString pjrc_rawhid::getserial(int num) -{ - QMutexLocker locker(m_readMutex); - - Q_UNUSED(locker); - - if (!device_open || unplugged) { - return ""; - } - - CFTypeRef serialnum = IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDSerialNumberKey)); - if (serialnum && CFGetTypeID(serialnum) == CFStringGetTypeID()) { - // Note: I'm not sure it will always succeed if encoded as MacRoman but that - // is a superset of UTF8 so I think this is fine - CFStringRef str = static_cast(serialnum); - int length = CFStringGetLength(str); - if (length == 0) { - return ""; - } - char *ptr = (char *)malloc(length + 1); - Boolean ret = CFStringGetCString(str, ptr, length + 1, kCFStringEncodingMacRoman); - QString strResult; - if (ret == true) { - strResult = ptr; - } - free(ptr); - return strResult; - } - - return QString("Error"); -} - -// ! Close the HID device -void pjrc_rawhid::close(int) -{ - // Make sure any pending locks are done - QMutexLocker lock(m_writeMutex); - - if (device_open) { - device_open = false; - CFRunLoopStop(the_correct_runloop); - - if (!unplugged) { - IOHIDDeviceUnscheduleFromRunLoop(dev, the_correct_runloop, kCFRunLoopDefaultMode); - IOHIDDeviceRegisterInputReportCallback(dev, buffer, sizeof(buffer), NULL, NULL); - IOHIDDeviceClose(dev, kIOHIDOptionsTypeNone); - } - - IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, NULL, NULL); - IOHIDManagerClose(hid_manager, 0); - - dev = NULL; - hid_manager = NULL; - } -} - -/** - * @brief input Called to add input data to the buffer - * @param[in] id Report id - * @param[in] data The data buffer - * @param[in] len The report length - */ -void pjrc_rawhid::input(uint8_t *data, CFIndex len) -{ - if (!device_open) { - return; - } - - if (len > BUFFER_SIZE) { - len = BUFFER_SIZE; - } - // Note: packet preprocessing done in OS independent code - memcpy(buffer, &data[0], len); - buffer_count = len; - - if (received_runloop) { - CFRunLoopStop(received_runloop); - } -} - -// ! Callback for the HID driver on an input report -void pjrc_rawhid::input_callback(void *c, IOReturn ret, void *sender, IOHIDReportType type, uint32_t id, uint8_t *data, CFIndex len) -{ - if (ret != kIOReturnSuccess || len < 1) { - return; - } - - pjrc_rawhid *context = (pjrc_rawhid *)c; - context->input(data, len); -} - -// ! Timeout used for the -void pjrc_rawhid::timeout_callback(CFRunLoopTimerRef, void *i) -{ - struct timeout_info *info = (struct timeout_info *)i; - - info->timed_out = true; - CFRunLoopStop(info->loopRef); -} - -// ! Called on a dettach event -void pjrc_rawhid::dettach(IOHIDDeviceRef d) -{ - unplugged = true; - if (d == dev) { - emit deviceUnplugged(0); - } -} - -// ! Called from the USB system and forwarded to the instance (context) -void pjrc_rawhid::dettach_callback(void *context, IOReturn, void *, IOHIDDeviceRef dev) -{ - pjrc_rawhid *p = (pjrc_rawhid *)context; - - p->dettach(dev); -} - -/** - * @brief Called by the USB system - * @param dev The device that was attached - */ -void pjrc_rawhid::attach(IOHIDDeviceRef d) -{ - // Store the device handle - dev = d; - - if (IOHIDDeviceOpen(dev, kIOHIDOptionsTypeNone) != kIOReturnSuccess) { - return; - } - // Disconnect the attach callback since we don't want to automatically reconnect - IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, NULL, NULL); - IOHIDDeviceScheduleWithRunLoop(dev, the_correct_runloop, kCFRunLoopDefaultMode); - IOHIDDeviceRegisterInputReportCallback(dev, buffer, sizeof(buffer), pjrc_rawhid::input_callback, this); - - attach_count++; - device_open = true; - unplugged = false; -} - -// ! Called from the USB system and forwarded to the instance (context) -void pjrc_rawhid::attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev) -{ - pjrc_rawhid *p = (pjrc_rawhid *)context; - - p->attach(dev); -} diff --git a/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_unix.cpp b/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_unix.cpp deleted file mode 100644 index f8f123c3a..000000000 --- a/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_unix.cpp +++ /dev/null @@ -1,421 +0,0 @@ -/* @file pjrc_rawhid_unix.cpp - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @addtogroup RawHIDPlugin Raw HID Plugin - * @{ - * @brief Impliments a HID USB connection to the flight hardware as a QIODevice - *****************************************************************************/ - -/* Simple Raw HID functions for Linux - for use with Teensy RawHID example - * http://www.pjrc.com/teensy/rawhid.html - * Copyright (c) 2009 PJRC.COM, LLC - * - * rawhid_open - open 1 or more devices - * rawhid_recv - receive a packet - * rawhid_send - send a packet - * rawhid_close - close a device - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above description, website URL and copyright notice and this permission - * notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * Version 1.0: Initial Release - */ - -#include "pjrc_rawhid.h" - -#define printf qDebug - -pjrc_rawhid::pjrc_rawhid() -{ - first_hid = NULL; - last_hid = NULL; -} - -pjrc_rawhid::~pjrc_rawhid() -{} - -// open - open 1 or more devices -// -// Inputs: -// max = maximum number of devices to open -// vid = Vendor ID, or -1 if any -// pid = Product ID, or -1 if any -// usage_page = top level usage page, or -1 if any -// usage = top level usage number, or -1 if any -// Output: -// actual number of devices opened -// -int pjrc_rawhid::open(int max, int vid, int pid, int usage_page, int usage) -{ - struct usb_bus *bus; - struct usb_device *dev; - struct usb_interface *iface; - struct usb_interface_descriptor *desc; - struct usb_endpoint_descriptor *ep; - usb_dev_handle *u; - uint8_t buf[1024], *p; - int i, n, len, tag, ep_in, ep_out, count = 0, claimed; - uint32_t val = 0, parsed_usage, parsed_usage_page; - hid_t *hid; - - if (first_hid) { - free_all_hid(); - } - // printf("pjrc_rawhid_open, max=%d\n", max); - - if (max < 1) { - return 0; - } - - usb_init(); - usb_find_busses(); - usb_find_devices(); - - for (bus = usb_get_busses(); bus; bus = bus->next) { - for (dev = bus->devices; dev; dev = dev->next) { - if (vid > 0 && dev->descriptor.idVendor != vid) { - continue; - } - if (pid > 0 && dev->descriptor.idProduct != pid) { - continue; - } - if (!dev->config) { - continue; - } - if (dev->config->bNumInterfaces < 1) { - continue; - } - printf("device: vid=%04X, pic=%04X, with %d iface", - dev->descriptor.idVendor, - dev->descriptor.idProduct, - dev->config->bNumInterfaces); - iface = dev->config->interface; - u = NULL; - claimed = 0; - for (i = 0; i < dev->config->bNumInterfaces && iface; i++, iface++) { - desc = iface->altsetting; - if (!desc) { - continue; - } - - printf(" type %d, %d, %d", desc->bInterfaceClass, desc->bInterfaceSubClass, desc->bInterfaceProtocol); - - if (desc->bInterfaceClass != 3) { - continue; - } - if (desc->bInterfaceSubClass != 0) { - continue; - } - if (desc->bInterfaceProtocol != 0) { - continue; - } - - ep = desc->endpoint; - ep_in = ep_out = 0; - for (n = 0; n < desc->bNumEndpoints; n++, ep++) { - if (ep->bEndpointAddress & 0x80) { - if (!ep_in) { - ep_in = ep->bEndpointAddress & 0x7F; - } - qDebug() << " IN endpoint " << ep_in; - } else { - if (!ep_out) { - ep_out = ep->bEndpointAddress; - } - qDebug() << " OUT endpoint " << ep_out; - } - } - if (!ep_in) { - continue; - } - - if (!u) { - u = usb_open(dev); - if (!u) { - qDebug() << " unable to open device"; - break; - } - } - qDebug() << " hid interface (generic)"; - if (usb_get_driver_np(u, i, (char *)buf, sizeof(buf)) >= 0) { - printf(" in use by driver \"%s\"", buf); - if (usb_detach_kernel_driver_np(u, i) < 0) { - printf(" unable to detach from kernel"); - continue; - } - } - - if (usb_claim_interface(u, i) < 0) { - printf(" unable claim interface %d", i); - continue; - } - - len = usb_control_msg(u, 0x81, 6, 0x2200, i, (char *)buf, sizeof(buf), 250); - printf(" descriptor, len=%d", len); - if (len < 2) { - usb_release_interface(u, i); - continue; - } - - p = buf; - parsed_usage_page = parsed_usage = 0; - while ((tag = hid_parse_item(&val, &p, buf + len)) >= 0) { - printf(" tag: %X, val %X", tag, val); - if (tag == 4) { - parsed_usage_page = val; - } - if (tag == 8) { - parsed_usage = val; - } - if (parsed_usage_page && parsed_usage) { - break; - } - } - if ((!parsed_usage_page) || (!parsed_usage) || - (usage_page > 0 && parsed_usage_page != (uint32_t)usage_page) || - (usage > 0 && parsed_usage != (uint32_t)usage)) { - usb_release_interface(u, i); - continue; - } - - hid = (struct hid_struct *)malloc(sizeof(struct hid_struct)); - if (!hid) { - usb_release_interface(u, i); - continue; - } - - hid->usb = u; - hid->iface = i; - hid->ep_in = ep_in; - hid->ep_out = ep_out; - hid->open = 1; - add_hid(hid); - - claimed++; - count++; - if (count >= max) { - return count; - } - } - - if (u && !claimed) { - usb_close(u); - } - } - } - - return count; -} - -// recveive - receive a packet -// Inputs: -// num = device to receive from (zero based) -// buf = buffer to receive packet -// len = buffer's size -// timeout = time to wait, in milliseconds -// Output: -// number of bytes received, or -1 on error -// -int pjrc_rawhid::receive(int num, void *buf, int len, int timeout) -{ - if (!buf) { - return -1; - } - - hid_t *hid = get_hid(num); - if (!hid || !hid->open) { - return -1; - } - - int r = usb_interrupt_read(hid->usb, hid->ep_in, (char *)buf, len, timeout); - if (r >= 0) { - return r; - } - if (r == -110) { - return 0; // timeout - } - return -1; -} - -// send - send a packet -// Inputs: -// num = device to transmit to (zero based) -// buf = buffer containing packet to send -// len = number of bytes to transmit -// timeout = time to wait, in milliseconds -// Output: -// number of bytes sent, or -1 on error -// -int pjrc_rawhid::send(int num, void *buf, int len, int timeout) -{ - hid_t *hid; - - hid = get_hid(num); - if (!hid || !hid->open) { - return -1; - } - if (hid->ep_out) { - return usb_interrupt_write(hid->usb, hid->ep_out, (char *)buf, len, timeout); - } else { - return usb_control_msg(hid->usb, 0x21, 9, 0, hid->iface, (char *)buf, len, timeout); - } -} - -// getserial - get the serialnumber of the device -// -// Inputs: -// num = device to close (zero based) -// buf = buffer to read the serialnumber into -// Output -// number of bytes in found, or -1 on error -// -QString pjrc_rawhid::getserial(int num) -{ - hid_t *hid; - char buf[128]; - - hid = get_hid(num); - if (!hid || !hid->open) { - return QString(""); - } - - int retlen = usb_get_string_simple(hid->usb, 3, buf, 128); - return QString().fromAscii(buf, -1); -} - -// close - close a device -// -// Inputs: -// num = device to close (zero based) -// Output -// (nothing) -// -void pjrc_rawhid::close(int num) -{ - hid_close(get_hid(num)); -} - -// Chuck Robey wrote a real HID report parser -// (chuckr@telenix.org) chuckr@chuckr.org -// http://people.freebsd.org/~chuckr/code/python/uhidParser-0.2.tbz -// this tiny thing only needs to extract the top-level usage page -// and usage, and even then is may not be truly correct, but it does -// work with the Teensy Raw HID example. -int pjrc_rawhid::hid_parse_item(uint32_t *val, uint8_t * *data, const uint8_t *end) -{ - const uint8_t *p = *data; - uint8_t tag; - int table[4] = { 0, 1, 2, 4 }; - int len; - - if (p >= end) { - return -1; - } - if (p[0] == 0xFE) { - // long item, HID 1.11, 6.2.2.3, page 27 - if (p + 5 >= end || p + p[1] >= end) { - return -1; - } - tag = p[2]; - *val = 0; - len = p[1] + 5; - } else { - // short item, HID 1.11, 6.2.2.2, page 26 - tag = p[0] & 0xFC; - len = table[p[0] & 0x03]; - if (p + len + 1 >= end) { - return -1; - } - switch (p[0] & 0x03) { - case 3: *val = p[1] | (p[2] << 8) | (p[3] << 16) | (p[4] << 24); break; - case 2: *val = p[1] | (p[2] << 8); break; - case 1: *val = p[1]; break; - case 0: *val = 0; break; - } - } - *data += len + 1; - return tag; -} - -void pjrc_rawhid::add_hid(hid_t *h) -{ - if (!h) { - return; - } - - if (!first_hid || !last_hid) { - first_hid = last_hid = h; - h->next = h->prev = NULL; - return; - } - last_hid->next = h; - h->prev = last_hid; - h->next = NULL; - last_hid = h; -} - -hid_t *pjrc_rawhid::get_hid(int num) -{ - hid_t *p = NULL; - - for (p = first_hid; p && num > 0; p = p->next, num--) { - ; - } - return p; -} - -void pjrc_rawhid::free_all_hid(void) -{ - for (hid_t *p = first_hid; p; p = p->next) { - hid_close(p); - } - - hid_t *p = first_hid; - while (p) { - hid_t *q = p; - p = p->next; - free(q); - } - - first_hid = last_hid = NULL; -} - -void pjrc_rawhid::hid_close(hid_t *hid) -{ - if (!hid) { - return; - } - if (!hid->open) { - return; - } - - usb_release_interface(hid->usb, hid->iface); - - int others = 0; - for (hid_t *p = first_hid; p; p = p->next) { - if (p->open && p->usb == hid->usb) { - others++; - } - } - if (!others) { - usb_close(hid->usb); - } - - hid->usb = NULL; - hid->open = 0; -} diff --git a/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_win.cpp b/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_win.cpp deleted file mode 100644 index 37d4a9075..000000000 --- a/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_win.cpp +++ /dev/null @@ -1,483 +0,0 @@ -/* @file pjrc_rawhid_windows.cpp - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @addtogroup RawHIDPlugin Raw HID Plugin - * @{ - * @brief Impliments a HID USB connection to the flight hardware as a QIODevice - *****************************************************************************/ - -/* Simple Raw HID functions for Windows - for use with Teensy RawHID example - * http://www.pjrc.com/teensy/rawhid.html - * Copyright (c) 2009 PJRC.COM, LLC - * - * rawhid_open - open 1 or more devices - * rawhid_recv - receive a packet - * rawhid_send - send a packet - * rawhid_close - close a device - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above description, website URL and copyright notice and this permission - * notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * Version 1.0: Initial Release - */ -/* See: http://msdn.microsoft.com/en-us/library/ms794141.aspx */ - -#include "pjrc_rawhid.h" -#include -#define printf qDebug - -pjrc_rawhid::pjrc_rawhid() -{ - first_hid = NULL; - last_hid = NULL; - rx_event = NULL; - tx_event = NULL; -} - -pjrc_rawhid::~pjrc_rawhid() -{} - -// open - open 1 or more devices -// -// Inputs: -// max = maximum number of devices to open -// vid = Vendor ID, or -1 if any -// pid = Product ID, or -1 if any -// usage_page = top level usage page, or -1 if any -// usage = top level usage number, or -1 if any -// Output: -// actual number of devices opened -// -int pjrc_rawhid::open(int max, int vid, int pid, int usage_page, int usage) -{ - GUID guid; - HDEVINFO info; - DWORD index = 0, reqd_size; - SP_DEVICE_INTERFACE_DATA iface; - SP_DEVICE_INTERFACE_DETAIL_DATA *details; - HIDD_ATTRIBUTES attrib; - PHIDP_PREPARSED_DATA hid_data; - HIDP_CAPS capabilities; - HANDLE h; - BOOL ret; - hid_t *hid; - - int count = 0; - - if (first_hid) { - free_all_hid(); - } - - if (max < 1) { - return 0; - } - - if (!rx_event) { - rx_event = CreateEvent(NULL, TRUE, TRUE, NULL); - tx_event = CreateEvent(NULL, TRUE, TRUE, NULL); - InitializeCriticalSection(&rx_mutex); - InitializeCriticalSection(&tx_mutex); - } - - HidD_GetHidGuid(&guid); - - info = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - if (info == INVALID_HANDLE_VALUE) { - return 0; - } - - for (index = 0; 1; index++) { - iface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - ret = SetupDiEnumDeviceInterfaces(info, NULL, &guid, index, &iface); - if (!ret) { - return count; - } - - SetupDiGetInterfaceDeviceDetail(info, &iface, NULL, 0, &reqd_size, NULL); - details = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(reqd_size); - if (details == NULL) { - continue; - } - - memset(details, 0, reqd_size); - details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); - ret = SetupDiGetDeviceInterfaceDetail(info, &iface, details, reqd_size, NULL, NULL); - if (!ret) { - free(details); - continue; - } - - h = CreateFile(details->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if (h == INVALID_HANDLE_VALUE) { - DWORD err = GetLastError(); - - // I get ERROR_ACCESS_DENIED with most/all my input devices (mice/trackballs/tablet). - // Let's not log it :) - if (err == ERROR_ACCESS_DENIED) { - free(details); - continue; - } - - // qDebug wipes the GetLastError() it seems, so do that after print_win32_err(). - print_win32_err(err); - qDebug() << "Problem opening handle, path: " << QString().fromWCharArray(details->DevicePath); - - free(details); - continue; - } - - free(details); - - attrib.Size = sizeof(HIDD_ATTRIBUTES); - ret = HidD_GetAttributes(h, &attrib); - // printf("vid: %4x\n", attrib.VendorID); - if (!ret || (vid > 0 && attrib.VendorID != vid) || - (pid > 0 && attrib.ProductID != pid) || - !HidD_GetPreparsedData(h, &hid_data)) { - CloseHandle(h); - continue; - } - - if (!HidP_GetCaps(hid_data, &capabilities) || - (usage_page > 0 && capabilities.UsagePage != usage_page) || - (usage > 0 && capabilities.Usage != usage)) { - HidD_FreePreparsedData(hid_data); - CloseHandle(h); - continue; - } - - HidD_FreePreparsedData(hid_data); - - hid = (struct hid_struct *)malloc(sizeof(struct hid_struct)); - if (!hid) { - CloseHandle(h); - continue; - } - -// COMMTIMEOUTS CommTimeouts; -// CommTimeouts.ReadIntervalTimeout = 100; // 100ms -// CommTimeouts.ReadTotalTimeoutConstant = 5; // ms -// CommTimeouts.ReadTotalTimeoutMultiplier = 1; // -// CommTimeouts.WriteTotalTimeoutConstant = 5; // ms -// CommTimeouts.WriteTotalTimeoutMultiplier = 1; // -// if (!SetCommTimeouts(h, &CommTimeouts)) -// { -//// DWORD err = GetLastError(); -// -// } - - qDebug("Open: Handle address: %li for num: %i", (long int)h, count); - - hid->handle = h; - add_hid(hid); - - count++; - if (count >= max) { - return count; - } - } - - return count; -} - -// recveive - receive a packet -// Inputs: -// num = device to receive from (zero based) -// buf = buffer to receive packet -// len = buffer's size -// timeout = time to wait, in milliseconds -// Output: -// number of bytes received, or -1 on error -// -int pjrc_rawhid::receive(int num, void *buf, int len, int timeout) -{ - OVERLAPPED ov; - DWORD n; - - hid_t *hid = get_hid(num); - - if (!hid) { - return -1; - } - if (!hid->handle) { - return -1; - } - - EnterCriticalSection(&rx_mutex); - - ResetEvent(&rx_event); - - memset(&ov, 0, sizeof(ov)); - ov.hEvent = rx_event; - - if (!ReadFile(hid->handle, buf, len, NULL, &ov)) { - DWORD err = GetLastError(); - - if (err == ERROR_DEVICE_NOT_CONNECTED) { // the device has been unplugged - print_win32_err(err); - hid_close(hid); - LeaveCriticalSection(&rx_mutex); - emit deviceUnplugged(num); - return -1; - } - - if (err != ERROR_IO_PENDING) { - print_win32_err(err); - LeaveCriticalSection(&rx_mutex); - return -1; - } - - DWORD r = WaitForSingleObject(rx_event, timeout); - if (r == WAIT_TIMEOUT) { - CancelIo(hid->handle); - LeaveCriticalSection(&rx_mutex); - return 0; - } - if (r != WAIT_OBJECT_0) { - DWORD err = GetLastError(); - print_win32_err(err); - LeaveCriticalSection(&rx_mutex); - return -1; - } - } - - if (!GetOverlappedResult(hid->handle, &ov, &n, FALSE)) { - DWORD err = GetLastError(); - print_win32_err(err); - - if (err == ERROR_DEVICE_NOT_CONNECTED) { // the device has been unplugged - hid_close(hid); - LeaveCriticalSection(&rx_mutex); - emit deviceUnplugged(num); - return -1; - } - - LeaveCriticalSection(&rx_mutex); - return -1; - } - - LeaveCriticalSection(&rx_mutex); - - if (n <= 0) { - return -1; - } - -// qDebug("Received %i bytes, first %x, second %x", len, *((char *) buf),*((char *)buf + 1)); - - if ((int)n > len) { - n = len; - } - return n; -} - -// send - send a packet -// Inputs: -// num = device to transmit to (zero based) -// buf = buffer containing packet to send -// len = number of bytes to transmit -// timeout = time to wait, in milliseconds -// Output: -// number of bytes sent, or -1 on error -// -int pjrc_rawhid::send(int num, void *buf, int len, int timeout) -{ - OVERLAPPED ov; - DWORD n, r; - - hid_t *hid = get_hid(num); - - if (!hid) { - return -1; - } - if (!hid->handle) { - return -1; - } - -// qDebug("Send: Handle address: %li for num: %i", (long int) hid->handle, num); - - EnterCriticalSection(&tx_mutex); - - ResetEvent(&tx_event); - - memset(&ov, 0, sizeof(ov)); - ov.hEvent = tx_event; - -// qDebug("Trying to write %u bytes. First %x second %x",len, *((char *) buf), *((char *)buf + 1)); - - if (!WriteFile(hid->handle, buf, len, NULL, &ov)) { - DWORD err = GetLastError(); - - if (err == ERROR_DEVICE_NOT_CONNECTED) { // the device has been unplugged - hid_close(hid); - LeaveCriticalSection(&tx_mutex); - emit deviceUnplugged(num); - return -1; - } - - if (err == ERROR_SUCCESS || err == ERROR_IO_PENDING) { -// qDebug("Waiting for write to finish"); - r = WaitForSingleObject(tx_event, timeout); - if (r == WAIT_TIMEOUT) { - CancelIo(hid->handle); - LeaveCriticalSection(&tx_mutex); - return 0; - } - if (r != WAIT_OBJECT_0) { - DWORD err = GetLastError(); - print_win32_err(err); - LeaveCriticalSection(&tx_mutex); - return -1; - } - } else { -// qDebug("Error writing to file"); - print_win32_err(err); - LeaveCriticalSection(&tx_mutex); - return -1; - } - } - - if (!GetOverlappedResult(hid->handle, &ov, &n, FALSE)) { - DWORD err = GetLastError(); - - qDebug("Problem getting overlapped result"); - print_win32_err(err); - - if (err == ERROR_DEVICE_NOT_CONNECTED) { // the device has been unplugged - hid_close(hid); - LeaveCriticalSection(&tx_mutex); - emit deviceUnplugged(num); - return -1; - } - } - - LeaveCriticalSection(&tx_mutex); - - if (n <= 0) { - return -1; - } - return n; -} - -QString pjrc_rawhid::getserial(int num) -{ - hid_t *hid = get_hid(num); - - if (!hid) { - return ""; - } - if (!hid->handle) { - return ""; - } - - // Should we do some "critical section" stuff here?? - char temp[126]; - if (!HidD_GetSerialNumberString(hid->handle, temp, sizeof(temp))) { - DWORD err = GetLastError(); - print_win32_err(err); - - if (err == ERROR_DEVICE_NOT_CONNECTED) { // the device has been unplugged - hid_close(hid); - emit deviceUnplugged(num); - return ""; - } - - return QString("Error"); - } - - return QString().fromUtf16((ushort *)temp, -1); -} - -// close - close a device -// -// Inputs: -// num = device to close (zero based) -// Output -// (nothing) -// -void pjrc_rawhid::close(int num) -{ - hid_close(get_hid(num)); -} - -void pjrc_rawhid::add_hid(hid_t *h) -{ - if (!h) { - return; - } - - if (!first_hid || !last_hid) { - first_hid = last_hid = h; - h->next = h->prev = NULL; - return; - } - - last_hid->next = h; - h->prev = last_hid; - h->next = NULL; - last_hid = h; -} - -hid_t *pjrc_rawhid::get_hid(int num) -{ - hid_t *p; - - for (p = first_hid; p && num > 0; p = p->next, num--) { - ; - } - return p; -} - -void pjrc_rawhid::free_all_hid(void) -{ - for (hid_t *p = first_hid; p; p = p->next) { - hid_close(p); - } - - hid_t *p = first_hid; - while (p) { - hid_t *q = p; - p = p->next; - free(q); - } - - first_hid = last_hid = NULL; -} - -void pjrc_rawhid::hid_close(hid_t *hid) -{ - if (!hid) { - return; - } - if (!hid->handle) { - return; - } - - CloseHandle(hid->handle); - hid->handle = NULL; -} - -void pjrc_rawhid::print_win32_err(DWORD err) -{ - char buf[256]; - char temp[256]; - - // FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, (WCHAR*)buf, sizeof(buf), NULL); - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), (WCHAR *)buf, sizeof(buf), NULL); - WideCharToMultiByte(CP_ACP, 0, (WCHAR *)buf, sizeof(buf), temp, sizeof(temp), NULL, NULL); - printf("err %ld: %s\n", err, temp); -} diff --git a/ground/openpilotgcs/src/plugins/rawhid/rawhid.cpp b/ground/openpilotgcs/src/plugins/rawhid/rawhid.cpp deleted file mode 100644 index 3e3d8a4ad..000000000 --- a/ground/openpilotgcs/src/plugins/rawhid/rawhid.cpp +++ /dev/null @@ -1,465 +0,0 @@ -/** - ****************************************************************************** - * - * @file rawhid.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @addtogroup RawHIDPlugin Raw HID Plugin - * @{ - * @brief Impliments a HID USB connection to the flight hardware as a QIODevice - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "rawhid.h" - -#include "rawhid_const.h" -#include "coreplugin/connectionmanager.h" -#include -#include -#include -#include -#include - -class IConnection; - -// timeout value used when we want to return directly without waiting -static const int READ_TIMEOUT = 200; -static const int READ_SIZE = 64; - -static const int WRITE_TIMEOUT = 1000; -static const int WRITE_SIZE = 64; - - -// ********************************************************************************* - -/** - * Thread to desynchronize reading from the device - */ -class RawHIDReadThread : public QThread { -public: - RawHIDReadThread(RawHID *hid); - virtual ~RawHIDReadThread(); - - /** Return the data read so far without waiting */ - int getReadData(char *data, int size); - - /** return the bytes buffered */ - qint64 getBytesAvailable(); - -public slots: - void terminate() - { - m_running = false; - } - -protected: - void run(); - - /** QByteArray might not be the most efficient way to implement - a circular buffer but it's good enough and very simple */ - QByteArray m_readBuffer; - - /** A mutex to protect read buffer */ - QMutex m_readBufMtx; - - RawHID *m_hid; - - pjrc_rawhid *hiddev; - int hidno; - - bool m_running; -}; - - -// ********************************************************************************* - -/** - * This class is nearly the same than RawHIDReadThread but for writing - */ -class RawHIDWriteThread : public QThread { -public: - RawHIDWriteThread(RawHID *hid); - virtual ~RawHIDWriteThread(); - - /** Add some data to be written without waiting */ - int pushDataToWrite(const char *data, int size); - - /** Return the number of bytes buffered */ - qint64 getBytesToWrite(); - -public slots: - void terminate() - { - m_running = false; - } - -protected: - void run(); - - /** QByteArray might not be the most efficient way to implement - a circular buffer but it's good enough and very simple */ - QByteArray m_writeBuffer; - - /** A mutex to protect read buffer */ - QMutex m_writeBufMtx; - - /** Synchronize task with data arival */ - QWaitCondition m_newDataToWrite; - - RawHID *m_hid; - - pjrc_rawhid *hiddev; - int hidno; - - bool m_running; -}; - -// ********************************************************************************* - -RawHIDReadThread::RawHIDReadThread(RawHID *hid) - : m_hid(hid), - hiddev(&hid->dev), - hidno(hid->m_deviceNo), - m_running(true) -{ - hid->m_startedMutex->lock(); -} - -RawHIDReadThread::~RawHIDReadThread() -{ - m_running = false; - // wait for the thread to terminate - if (wait(10000) == false) { - qDebug() << "Cannot terminate RawHIDReadThread"; - } -} - -void RawHIDReadThread::run() -{ - m_running = m_hid->openDevice(); - while (m_running) { - // here we use a temporary buffer so we don't need to lock - // the mutex while we are reading from the device - - // Want to read in regular chunks that match the packet size the device - // is using. In this case it is 64 bytes (the interrupt packet limit) - // although it would be nice if the device had a different report to - // configure this - char buffer[READ_SIZE] = { 0 }; - - int ret = hiddev->receive(hidno, buffer, READ_SIZE, READ_TIMEOUT); - - if (ret > 0) { // read some data - QMutexLocker lock(&m_readBufMtx); - // Note: Preprocess the USB packets in this OS independent code - // First byte is report ID, second byte is the number of valid bytes - m_readBuffer.append(&buffer[2], buffer[1]); - - emit m_hid->readyRead(); - } else if (ret == 0) { // nothing read - } else { // < 0 => error - // TODO! make proper error handling, this only quick hack for unplug freeze - m_running = false; - } - } - m_hid->closeDevice(); -} - -int RawHIDReadThread::getReadData(char *data, int size) -{ - QMutexLocker lock(&m_readBufMtx); - - size = qMin(size, m_readBuffer.size()); - - memcpy(data, m_readBuffer.constData(), size); - m_readBuffer.remove(0, size); - - return size; -} - -qint64 RawHIDReadThread::getBytesAvailable() -{ - QMutexLocker lock(&m_readBufMtx); - - return m_readBuffer.size(); -} - -RawHIDWriteThread::RawHIDWriteThread(RawHID *hid) - : m_hid(hid), - hiddev(&hid->dev), - hidno(hid->m_deviceNo), - m_running(true) -{} - -// ********************************************************************************* - -RawHIDWriteThread::~RawHIDWriteThread() -{ - m_running = false; - // wait for the thread to terminate - if (wait(10000) == false) { - qDebug() << "Cannot terminate RawHIDReadThread"; - } -} - -void RawHIDWriteThread::run() -{ - while (m_running) { - char buffer[WRITE_SIZE] = { 0 }; - - m_writeBufMtx.lock(); - int size = qMin(WRITE_SIZE - 2, m_writeBuffer.size()); - while (size <= 0) { - // wait on new data to write condition, the timeout - // enable the thread to shutdown properly - m_newDataToWrite.wait(&m_writeBufMtx, 200); - if (!m_running) { - return; - } - - size = m_writeBuffer.size(); - } - - // NOTE: data size is limited to 2 bytes less than the - // usb packet size (64 bytes for interrupt) to make room - // for the reportID and valid data length - size = qMin(WRITE_SIZE - 2, m_writeBuffer.size()); - memcpy(&buffer[2], m_writeBuffer.constData(), size); - buffer[1] = size; // valid data length - buffer[0] = 2; // reportID - m_writeBufMtx.unlock(); - - // must hold lock through the send to know how much was sent - int ret = hiddev->send(hidno, buffer, WRITE_SIZE, WRITE_TIMEOUT); - - if (ret > 0) { - // only remove the size actually written to the device - QMutexLocker lock(&m_writeBufMtx); - m_writeBuffer.remove(0, size); - - emit m_hid->bytesWritten(ret - 2); - } else if (ret < 0) { // < 0 => error - // TODO! make proper error handling, this only quick hack for unplug freeze - m_running = false; - qDebug() << "Error writing to device"; - } else { - qDebug() << "No data written to device ??"; - } - } -} - -int RawHIDWriteThread::pushDataToWrite(const char *data, int size) -{ - QMutexLocker lock(&m_writeBufMtx); - - m_writeBuffer.append(data, size); - m_newDataToWrite.wakeOne(); // signal that new data arrived - - return size; -} - -qint64 RawHIDWriteThread::getBytesToWrite() -{ - // QMutexLocker lock(&m_writeBufMtx); - return m_writeBuffer.size(); -} - -// ********************************************************************************* - -RawHID::RawHID(const QString &deviceName) - : QIODevice(), - serialNumber(deviceName), - m_deviceNo(-1), - m_readThread(NULL), - m_writeThread(NULL), - m_mutex(NULL) -{ - m_mutex = new QMutex(QMutex::Recursive); - m_startedMutex = new QMutex(); - - // detect if the USB device is unplugged - QObject::connect(&dev, SIGNAL(deviceUnplugged(int)), this, SLOT(onDeviceUnplugged(int))); - - m_writeThread = new RawHIDWriteThread(this); - - // Starting the read thread will lock the m_startexMutex until the - // device is opened (which happens in that thread). - m_readThread = new RawHIDReadThread(this); - m_readThread->start(); - - m_startedMutex->lock(); -} - -/** - * @brief RawHID::openDevice This method opens the USB connection - * It is uses as a callback from the read thread so that the USB - * system code is registered in that thread instead of the calling - * thread (usually UI) - */ -bool RawHID::openDevice() -{ - int opened = dev.open(USB_MAX_DEVICES, USBMonitor::idVendor_OpenPilot, -1, USB_USAGE_PAGE, USB_USAGE); - - for (int i = 0; i < opened; i++) { - if (serialNumber == dev.getserial(i)) { - m_deviceNo = i; - } else { - dev.close(i); - } - } - - // Now things are opened or not (from read thread) allow the constructor to complete - m_startedMutex->unlock(); - - // didn't find the device we are trying to open (shouldnt happen) - device_open = opened >= 0; - if (opened < 0) { - return false; - } - - m_writeThread->start(); - - return true; -} - -/** - * @brief RawHID::closeDevice This method closes the USB connection - * It is uses as a callback from the read thread so that the USB - * system code is unregistered from that thread\ - */ -bool RawHID::closeDevice() -{ - dev.close(m_deviceNo); -} - -RawHID::~RawHID() -{ - // If the read thread exists then the device is open - if (m_readThread) { - close(); - } -} - -void RawHID::onDeviceUnplugged(int num) -{ - if (num != m_deviceNo) { - return; - } - - // the USB device has been unplugged - close(); -} - -bool RawHID::open(OpenMode mode) -{ - QMutexLocker locker(m_mutex); - - if (m_deviceNo < 0) { - return false; - } - - QIODevice::open(mode); - - Q_ASSERT(m_readThread); - Q_ASSERT(m_writeThread); - if (m_readThread) { - m_readThread->start(); - } - if (m_writeThread) { - m_writeThread->start(); - } - - return true; -} - -void RawHID::close() -{ - qDebug() << "RawHID::close()"; - emit aboutToClose(); - if (m_writeThread) { - qDebug() << "About to terminate write thread"; - m_writeThread->terminate(); - delete m_writeThread; - m_writeThread = NULL; - qDebug() << "Write thread terminated"; - } - - - if (m_readThread) { - qDebug() << "About to terminate read thread"; - m_readThread->terminate(); - delete m_readThread; // calls wait - m_readThread = NULL; - qDebug() << "Read thread terminated"; - } - - emit closed(); - - QIODevice::close(); -} - -bool RawHID::isSequential() const -{ - return true; -} - -qint64 RawHID::bytesAvailable() const -{ - QMutexLocker locker(m_mutex); - - if (!m_readThread) { - return -1; - } - - return m_readThread->getBytesAvailable() + QIODevice::bytesAvailable(); -} - -qint64 RawHID::bytesToWrite() const -{ - QMutexLocker locker(m_mutex); - - if (!m_writeThread) { - return -1; - } - - return m_writeThread->getBytesToWrite() + QIODevice::bytesToWrite(); -} - -qint64 RawHID::readData(char *data, qint64 maxSize) -{ - QMutexLocker locker(m_mutex); - - if (!m_readThread || !data) { - return -1; - } - - return m_readThread->getReadData(data, maxSize); -} - -qint64 RawHID::writeData(const char *data, qint64 maxSize) -{ - QMutexLocker locker(m_mutex); - - if (!m_writeThread || !data) { - return -1; - } - - return m_writeThread->pushDataToWrite(data, maxSize); -} - -// ********************************************************************************* diff --git a/ground/openpilotgcs/src/plugins/rawhid/rawhid.h b/ground/openpilotgcs/src/plugins/rawhid/rawhid.h deleted file mode 100644 index 72275b4b4..000000000 --- a/ground/openpilotgcs/src/plugins/rawhid/rawhid.h +++ /dev/null @@ -1,95 +0,0 @@ -/** - ****************************************************************************** - * - * @file rawhid.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @addtogroup RawHIDPlugin Raw HID Plugin - * @{ - * @brief Impliments a HID USB connection to the flight hardware as a QIODevice - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef RAWHID_H -#define RAWHID_H - -#include "rawhid_global.h" - -#include -#include -#include -#include - -#include "pjrc_rawhid.h" -#include "usbmonitor.h" - -// helper classes -class RawHIDReadThread; -class RawHIDWriteThread; - -/** - * The actual IO device that will be used to communicate - * with the board. - */ -class RAWHID_EXPORT RawHID : public QIODevice { - Q_OBJECT - - friend class RawHIDReadThread; - friend class RawHIDWriteThread; - -public: - RawHID(); - RawHID(const QString &deviceName); - virtual ~RawHID(); - - virtual bool open(OpenMode mode); - virtual void close(); - virtual bool isSequential() const; - -signals: - void closed(); - -public slots: - void onDeviceUnplugged(int num); - -protected: - virtual qint64 readData(char *data, qint64 maxSize); - virtual qint64 writeData(const char *data, qint64 maxSize); - virtual qint64 bytesAvailable() const; - virtual qint64 bytesToWrite() const; - - // ! Callback from the read thread to open the device - bool openDevice(); - - // ! Callback from teh read thread to close the device - bool closeDevice(); - - QString serialNumber; - - int m_deviceNo; - pjrc_rawhid dev; - bool device_open; - - RawHIDReadThread *m_readThread; - RawHIDWriteThread *m_writeThread; - - QMutex *m_mutex; - QMutex *m_startedMutex; -}; - -#endif // RAWHID_H diff --git a/ground/openpilotgcs/src/plugins/rawhid/rawhid.pri b/ground/openpilotgcs/src/plugins/rawhid/rawhid.pri deleted file mode 100644 index 4982d3408..000000000 --- a/ground/openpilotgcs/src/plugins/rawhid/rawhid.pri +++ /dev/null @@ -1,3 +0,0 @@ -include(rawhid_dependencies.pri) - -LIBS *= -l$$qtLibraryName(RawHID) diff --git a/ground/openpilotgcs/src/plugins/rawhid/rawhid.pro b/ground/openpilotgcs/src/plugins/rawhid/rawhid.pro deleted file mode 100644 index f857ef72a..000000000 --- a/ground/openpilotgcs/src/plugins/rawhid/rawhid.pro +++ /dev/null @@ -1,52 +0,0 @@ -TEMPLATE = lib -TARGET = RawHID -include(../../openpilotgcsplugin.pri) -include(rawhid_dependencies.pri) -HEADERS += rawhid_global.h \ - rawhidplugin.h \ - rawhid.h \ - pjrc_rawhid.h \ - rawhid_const.h \ - usbmonitor.h \ - usbsignalfilter.h -SOURCES += rawhidplugin.cpp \ - rawhid.cpp \ - usbsignalfilter.cpp -FORMS += -RESOURCES += -DEFINES += RAWHID_LIBRARY -OTHER_FILES += RawHID.pluginspec - -# Platform Specific USB HID Stuff -win32 { - SOURCES += pjrc_rawhid_win.cpp \ - usbmonitor_win.cpp - LIBS += -lhid \ - -lsetupapi -} -macx { - SOURCES += pjrc_rawhid_mac.cpp \ - usbmonitor_mac.cpp - SDK = /Developer/SDKs/MacOSX10.5.sdk - ARCH = -mmacosx-version-min=10.5 \ - -arch \ - ppc \ - -arch \ - i386 - LIBS += $(ARCH) \ - -Wl,-syslibroot,$(SDK) \ - -framework \ - IOKit \ - -framework \ - CoreFoundation -} -linux-g++ { - SOURCES += pjrc_rawhid_unix.cpp \ - usbmonitor_linux.cpp - LIBS += -lusb -ludev -} -linux-g++-64 { - SOURCES += pjrc_rawhid_unix.cpp \ - usbmonitor_linux.cpp - LIBS += -lusb -ludev -} diff --git a/ground/openpilotgcs/src/plugins/rawhid/rawhid_const.h b/ground/openpilotgcs/src/plugins/rawhid/rawhid_const.h deleted file mode 100644 index 9e58720cf..000000000 --- a/ground/openpilotgcs/src/plugins/rawhid/rawhid_const.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - ****************************************************************************** - * - * @file rawhid_const.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @addtogroup RawHIDPlugin Raw HID Plugin - * @{ - * @brief Impliments a HID USB connection to the flight hardware as a QIODevice - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef RAWHID_CONST_H -#define RAWHID_CONST_H - -static const int USB_MAX_DEVICES = 10; - -static const int USB_VID = 0x20A0; -static const int USB_PID = 0x4117; - -static const int USB_USAGE_PAGE = 0xFF9C; -static const int USB_USAGE = 0x0001; - -static const int USB_DEV_SERIAL_LEN = 24; - -#endif // RAWHID_CONST_H diff --git a/ground/openpilotgcs/src/plugins/rawhid/rawhid_dependencies.pri b/ground/openpilotgcs/src/plugins/rawhid/rawhid_dependencies.pri deleted file mode 100644 index 0e063b82b..000000000 --- a/ground/openpilotgcs/src/plugins/rawhid/rawhid_dependencies.pri +++ /dev/null @@ -1 +0,0 @@ -include(../../plugins/coreplugin/coreplugin.pri) \ No newline at end of file diff --git a/ground/openpilotgcs/src/plugins/rawhid/rawhid_global.h b/ground/openpilotgcs/src/plugins/rawhid/rawhid_global.h deleted file mode 100644 index 84ab9c0e0..000000000 --- a/ground/openpilotgcs/src/plugins/rawhid/rawhid_global.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - ****************************************************************************** - * - * @file rawhid_global.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @addtogroup RawHIDPlugin Raw HID Plugin - * @{ - * @brief Impliments a HID USB connection to the flight hardware as a QIODevice - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef RAWHID_GLOBAL_H -#define RAWHID_GLOBAL_H - -#include - -#if defined(RAWHID_LIBRARY) -# define RAWHID_EXPORT Q_DECL_EXPORT -#else -# define RAWHID_EXPORT Q_DECL_IMPORT -#endif - -#endif // RAWHID_GLOBAL_H diff --git a/ground/openpilotgcs/src/plugins/rawhid/rawhidplugin.cpp b/ground/openpilotgcs/src/plugins/rawhid/rawhidplugin.cpp deleted file mode 100644 index 4dd682758..000000000 --- a/ground/openpilotgcs/src/plugins/rawhid/rawhidplugin.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/** - ****************************************************************************** - * - * @file rawhidplugin.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @addtogroup RawHIDPlugin Raw HID Plugin - * @{ - * @brief Impliments a HID USB connection to the flight hardware as a QIODevice - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "rawhidplugin.h" -#include "rawhid.h" -#include - -#include -#include - -#include "pjrc_rawhid.h" - -#include "rawhid_const.h" - - -// ********************************************************************** - -RawHIDConnection::RawHIDConnection() -{ - // added by andrew - RawHidHandle = NULL; - enablePolling = true; - - m_usbMonitor = USBMonitor::instance(); - - connect(m_usbMonitor, SIGNAL(deviceDiscovered(USBPortInfo)), this, SLOT(onDeviceConnected())); - connect(m_usbMonitor, SIGNAL(deviceRemoved(USBPortInfo)), this, SLOT(onDeviceDisconnected())); -} - -RawHIDConnection::~RawHIDConnection() -{ - if (RawHidHandle) { - if (RawHidHandle->isOpen()) { - RawHidHandle->close(); - } - } -} - -/** - The USB monitor tells us a new device appeared - */ -void RawHIDConnection::onDeviceConnected() -{ - emit availableDevChanged(this); -} - -/** - The USB monitor tells us a device disappeard - */ -void RawHIDConnection::onDeviceDisconnected() -{ - qDebug() << "onDeviceDisconnected()"; - if (enablePolling) { - emit availableDevChanged(this); - } -} - -/** - Returns the list of all currently available devices - */ -QList < Core::IConnection::device> RawHIDConnection::availableDevices() -{ - QList < Core::IConnection::device> devices; - - QList portsList = m_usbMonitor->availableDevices(USBMonitor::idVendor_OpenPilot, -1, -1, USBMonitor::Running); - // We currently list devices by their serial number - device dev; - foreach(USBPortInfo prt, portsList) { - dev.name = prt.serialNumber; - dev.displayName = prt.product; - devices.append(dev); - } - return devices; -} - -QIODevice *RawHIDConnection::openDevice(const QString &deviceName) -{ - // added by andrew - if (RawHidHandle) { - closeDevice(deviceName); - } - // end added by andrew - - // return new RawHID(deviceName); - RawHidHandle = new RawHID(deviceName); - return RawHidHandle; -} - - -void RawHIDConnection::closeDevice(const QString &deviceName) -{ - Q_UNUSED(deviceName); - if (RawHidHandle) { - qDebug() << "Closing the device here"; - RawHidHandle->close(); - delete RawHidHandle; - RawHidHandle = NULL; - } -} - -QString RawHIDConnection::connectionName() -{ - return QString("Raw HID USB"); -} - -QString RawHIDConnection::shortName() -{ - return QString("USB"); -} - -/** - Tells the Raw HID plugin to stop polling for USB devices - */ -void RawHIDConnection::suspendPolling() -{ - enablePolling = false; -} - -/** - Tells the Raw HID plugin to resume polling for USB devices - */ -void RawHIDConnection::resumePolling() -{ - enablePolling = true; -} - -// ********************************************************************** - -RawHIDPlugin::RawHIDPlugin() -{ - hidConnection = NULL; // Pip -} - -RawHIDPlugin::~RawHIDPlugin() -{ - m_usbMonitor->quit(); - m_usbMonitor->wait(500); -} - -void RawHIDPlugin::extensionsInitialized() -{ - hidConnection = new RawHIDConnection(); - addAutoReleasedObject(hidConnection); - - // temp for test - // addAutoReleasedObject(new RawHIDTestThread); -} - -bool RawHIDPlugin::initialize(const QStringList & arguments, QString *errorString) -{ - Q_UNUSED(arguments); - Q_UNUSED(errorString); - - // We have to create the USB Monitor here: - m_usbMonitor = new USBMonitor(this); - - return true; -} - -Q_EXPORT_PLUGIN(RawHIDPlugin) - -// ********************************************************************** diff --git a/ground/openpilotgcs/src/plugins/rawhid/rawhidplugin.h b/ground/openpilotgcs/src/plugins/rawhid/rawhidplugin.h deleted file mode 100644 index 3b241c6e5..000000000 --- a/ground/openpilotgcs/src/plugins/rawhid/rawhidplugin.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - ****************************************************************************** - * - * @file rawhid.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @addtogroup RawHIDPlugin Raw HID Plugin - * @{ - * @brief Impliments a HID USB connection to the flight hardware as a QIODevice - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef RAWHIDPLUGIN_H -#define RAWHIDPLUGIN_H - -#include "rawhid_global.h" -#include "rawhid.h" -#include "usbmonitor.h" -#include "coreplugin/iconnection.h" -#include - -#include -#include - -class IConnection; -class RawHIDConnection; - - -/** - * Define a connection via the IConnection interface - * Plugin will add a instance of this class to the pool, - * so the connection manager can use it. - */ -class RAWHID_EXPORT RawHIDConnection - : public Core::IConnection { - Q_OBJECT -public: - RawHIDConnection(); - virtual ~RawHIDConnection(); - - virtual QList < Core::IConnection::device> availableDevices(); - virtual QIODevice *openDevice(const QString &deviceName); - virtual void closeDevice(const QString &deviceName); - - virtual QString connectionName(); - virtual QString shortName(); - virtual void suspendPolling(); - virtual void resumePolling(); - - bool deviceOpened() - { - return RawHidHandle != NULL; - } // Pip - -protected slots: - void onDeviceConnected(); - void onDeviceDisconnected(); - -private: - RawHID *RawHidHandle; - bool enablePolling; - -protected: - QMutex m_enumMutex; - USBMonitor *m_usbMonitor; - bool m_deviceOpened; -}; - -class RAWHID_EXPORT RawHIDPlugin - : public ExtensionSystem::IPlugin { - Q_OBJECT - -public: - RawHIDPlugin(); - ~RawHIDPlugin(); - - virtual bool initialize(const QStringList &arguments, QString *error_message); - virtual void extensionsInitialized(); -private: - RawHIDConnection *hidConnection; - USBMonitor *m_usbMonitor; -}; - -#endif // RAWHIDPLUGIN_H diff --git a/ground/openpilotgcs/src/plugins/rawhid/usbmonitor.h b/ground/openpilotgcs/src/plugins/rawhid/usbmonitor.h deleted file mode 100644 index 9dde7e1ec..000000000 --- a/ground/openpilotgcs/src/plugins/rawhid/usbmonitor.h +++ /dev/null @@ -1,202 +0,0 @@ -/** - ****************************************************************************** - * - * @file usbmonitor.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @addtogroup RawHIDPlugin Raw HID Plugin - * @{ - * @brief Monitors the USB bus for devince insertion/removal - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef USBMONITOR_H -#define USBMONITOR_H - -#include "rawhid_global.h" - -#include -#include - -// Depending on the OS, we'll need different things: -#if defined(Q_OS_MAC) -#include -#include -#elif defined(Q_OS_UNIX) - -#include -#include - -#elif defined(Q_OS_WIN32) -#ifndef _WIN32_WINNT - #define _WIN32_WINNT 0x0500 -#endif -#ifndef _WIN32_WINDOWS - #define _WIN32_WINDOWS 0x0500 -#endif -#ifndef WINVER - #define WINVER 0x0500 -#endif -#include -#include -#include -#include -#include -#endif // if defined(Q_OS_MAC) - - -#ifdef Q_OS_WIN -#ifdef QT_GUI_LIB -#include -class USBMonitor; - -class USBRegistrationWidget : public QWidget { - Q_OBJECT -public: - USBRegistrationWidget(USBMonitor *qese) - { - this->qese = qese; - } - ~USBRegistrationWidget() {} - -protected: - USBMonitor *qese; - bool winEvent(MSG *message, long *result); -}; -#endif -#endif - -struct USBPortInfo { - // QString friendName; ///< Friendly name. - // QString physName; - // QString enumName; ///< It seems its the only one with meaning - QString serialNumber; // As a string as it can be anything, really... - QString manufacturer; - QString product; -#if defined(Q_OS_WIN32) - QString devicePath; // only has meaning on windows -#elif defined(Q_OS_MAC) - IOHIDDeviceRef dev_handle; -#endif - int UsagePage; - int Usage; - int vendorID; ///< Vendor ID. - int productID; ///< Product ID - int bcdDevice; -}; - -/** - * A monitoring thread which will wait for device events. - */ - -class RAWHID_EXPORT USBMonitor : public QThread { - Q_OBJECT - -public: - enum RunState { - Bootloader = 0x01, - Running = 0x02 - }; - - enum USBConstants { - idVendor_OpenPilot = 0x20a0, - idProduct_OpenPilot = 0x415a, - idProduct_CopterControl = 0x415b, - idProduct_PipXtreme = 0x415c - }; - - static USBMonitor *instance(); - - USBMonitor(QObject *parent = 0); - ~USBMonitor(); - QList availableDevices(); - QList availableDevices(int vid, int pid, int boardModel, int runState); - #if defined(Q_OS_WIN32) - LRESULT onDeviceChangeWin(WPARAM wParam, LPARAM lParam); - #endif -signals: - /*! - A new device has been connected to the system. - - setUpNotifications() must be called first to enable event-driven device notifications. - Currently only implemented on Windows and OS X. - \param info The device that has been discovered. - */ - void deviceDiscovered(const USBPortInfo & info); - /*! - A device has been disconnected from the system. - - setUpNotifications() must be called first to enable event-driven device notifications. - Currently only implemented on Windows and OS X. - \param info The device that was disconnected. - */ - void deviceRemoved(const USBPortInfo & info); - -private slots: - /** - Callback available for whenever the system that is put in place gets - an event - */ - void deviceEventReceived(); - -private: - - // ! Mutex for modifying the list of available devices - QMutex *listMutex; - - // ! List of known devices maintained by callbacks - QList knowndevices; - - Q_DISABLE_COPY(USBMonitor) - static USBMonitor * m_instance; - - - // Depending on the OS, we'll need different things: -#if defined(Q_OS_MAC) - static void attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev); - static void detach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev); - void addDevice(USBPortInfo info); - void removeDevice(IOHIDDeviceRef dev); - IOHIDManagerRef hid_manager; -#elif defined(Q_OS_UNIX) - struct udev *context; - struct udev_monitor *monitor; - QSocketNotifier *monitorNotifier; - USBPortInfo makePortInfo(struct udev_device *dev); -#elif defined(Q_OS_WIN32) - GUID guid_hid; - void setUpNotifications(); - /*! - * Get specific property from registry. - * \param devInfo pointer to the device information set that contains the interface - * and its underlying device. Returned by SetupDiGetClassDevs() function. - * \param devData pointer to an SP_DEVINFO_DATA structure that defines the device instance. - * this is returned by SetupDiGetDeviceInterfaceDetail() function. - * \param property registry property. One of defined SPDRP_* constants. - * \return property string. - */ - static QString getDeviceProperty(HDEVINFO devInfo, PSP_DEVINFO_DATA devData, DWORD property); - static int infoFromHandle(const GUID & guid, USBPortInfo & info, HDEVINFO & devInfo, DWORD & index); - static void enumerateDevicesWin(const GUID & guidDev, QList *infoList); - bool matchAndDispatchChangedDevice(const QString & deviceID, const GUID & guid, WPARAM wParam); -#ifdef QT_GUI_LIB - USBRegistrationWidget *notificationWidget; -#endif -#endif // if defined(Q_OS_MAC) -}; -#endif // USBMONITOR_H diff --git a/ground/openpilotgcs/src/plugins/rawhid/usbmonitor_linux.cpp b/ground/openpilotgcs/src/plugins/rawhid/usbmonitor_linux.cpp deleted file mode 100644 index 7fc9d77c8..000000000 --- a/ground/openpilotgcs/src/plugins/rawhid/usbmonitor_linux.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/** - ****************************************************************************** - * - * @file usbmonitor_linux.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @addtogroup RawHIDPlugin Raw HID Plugin - * @{ - * @brief Implements the USB monitor on Linux using libudev - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - Need help wihth udev ? - There is a great tuturial at: http://www.signal11.us/oss/udev/ - */ - -#include "usbmonitor.h" -#include - -#define printf qDebug - - -void printPortInfo(struct udev_device *dev) -{ - printf(" Node: %s", udev_device_get_devnode(dev)); - printf(" Subsystem: %s", udev_device_get_subsystem(dev)); - printf(" Devtype: %s", udev_device_get_devtype(dev)); - printf(" Action: %s", udev_device_get_action(dev)); - /* From here, we can call get_sysattr_value() for each file - in the device's /sys entry. The strings passed into these - functions (idProduct, idVendor, serial, etc.) correspond - directly to the files in the directory which represents - the USB device. Note that USB strings are Unicode, UCS2 - encoded, but the strings returned from - udev_device_get_sysattr_value() are UTF-8 encoded. */ - printf(" VID/PID/bcdDevice : %s %s %s", - udev_device_get_sysattr_value(dev, "idVendor"), - udev_device_get_sysattr_value(dev, "idProduct"), - udev_device_get_sysattr_value(dev, "bcdDevice")); - printf(" %s - %s", - udev_device_get_sysattr_value(dev, "manufacturer"), - udev_device_get_sysattr_value(dev, "product")); - printf(" serial: %s", - udev_device_get_sysattr_value(dev, "serial")); -} - - -void USBMonitor::deviceEventReceived() -{ - qDebug() << "Device event"; - struct udev_device *dev; - - dev = udev_monitor_receive_device(this->monitor); - if (dev) { - printf("------- Got Device Event"); - QString action = QString(udev_device_get_action(dev)); - QString devtype = QString(udev_device_get_devtype(dev)); - if (action == "add" && devtype == "usb_device") { - printPortInfo(dev); - emit deviceDiscovered(makePortInfo(dev)); - } else if (action == "remove" && devtype == "usb_device") { - printPortInfo(dev); - emit deviceRemoved(makePortInfo(dev)); - } - - udev_device_unref(dev); - } else { - printf("No Device from receive_device(). An error occured."); - } -} - - -USBMonitor *USBMonitor::instance() -{ - return m_instance; -} - -USBMonitor *USBMonitor::m_instance = 0; - -/** - Initialize the udev monitor here - */ -USBMonitor::USBMonitor(QObject *parent) : QThread(parent) -{ - m_instance = this; - - this->context = udev_new(); - - this->monitor = udev_monitor_new_from_netlink(this->context, "udev"); - udev_monitor_filter_add_match_subsystem_devtype( - this->monitor, "usb", NULL); - udev_monitor_enable_receiving(this->monitor); - this->monitorNotifier = new QSocketNotifier( - udev_monitor_get_fd(this->monitor), QSocketNotifier::Read, this); - connect(this->monitorNotifier, SIGNAL(activated(int)), - this, SLOT(deviceEventReceived())); - qDebug() << "Starting the Udev client"; - - start(); // Start the thread event loop so that the socketnotifier works -} - -USBMonitor::~USBMonitor() -{ - quit(); -} - -/** - Returns a list of all currently available devices - */ -QList USBMonitor::availableDevices() -{ - QList devicesList; - struct udev_list_entry *devices, *dev_list_entry; - struct udev_enumerate *enumerate; - struct udev_device *dev; - - enumerate = udev_enumerate_new(this->context); - udev_enumerate_add_match_subsystem(enumerate, "usb"); -// udev_enumerate_add_match_sysattr(enumerate, "idVendor", "20a0"); - udev_enumerate_scan_devices(enumerate); - devices = udev_enumerate_get_list_entry(enumerate); - // Will use the 'native' udev functions to loop: - udev_list_entry_foreach(dev_list_entry, devices) { - const char *path; - - /* Get the filename of the /sys entry for the device - and create a udev_device object (dev) representing it */ - path = udev_list_entry_get_name(dev_list_entry); - dev = udev_device_new_from_syspath(this->context, path); - if (QString(udev_device_get_devtype(dev)) == "usb_device") { - devicesList.append(makePortInfo(dev)); - } - udev_device_unref(dev); - } - /* free the enumerator object */ - udev_enumerate_unref(enumerate); - - return devicesList; -} - -/** - Be a bit more picky and ask only for a specific type of device: - On OpenPilot, the bcdDeviceLSB indicates the run state: bootloader or running. - bcdDeviceMSB indicates the board model. - */ -QList USBMonitor::availableDevices(int vid, int pid, int bcdDeviceMSB, int bcdDeviceLSB) -{ - QList allPorts = availableDevices(); - QList thePortsWeWant; - - foreach(USBPortInfo port, allPorts) { - if ((port.vendorID == vid || vid == -1) && (port.productID == pid || pid == -1) && ((port.bcdDevice >> 8) == bcdDeviceMSB || bcdDeviceMSB == -1) && - ((port.bcdDevice & 0x00ff) == bcdDeviceLSB || bcdDeviceLSB == -1)) { - thePortsWeWant.append(port); - } - } - return thePortsWeWant; -} - - -USBPortInfo USBMonitor::makePortInfo(struct udev_device *dev) -{ - USBPortInfo prtInfo; - - ////////// - // Debug info - ////////// -#ifdef DEBUG - printPortInfo(dev); -#endif - - - bool ok; - prtInfo.vendorID = QString(udev_device_get_sysattr_value(dev, "idVendor")).toInt(&ok, 16); - prtInfo.productID = QString(udev_device_get_sysattr_value(dev, "idProduct")).toInt(&ok, 16); - prtInfo.serialNumber = QString(udev_device_get_sysattr_value(dev, "serial")); - prtInfo.manufacturer = QString(udev_device_get_sysattr_value(dev, "manufacturer")); - prtInfo.product = QString(udev_device_get_sysattr_value(dev, "product")); -// prtInfo.UsagePage = QString(udev_device_get_sysattr_value(dev,"")); -// prtInfo.Usage = QString(udev_device_get_sysattr_value(dev,"")); - prtInfo.bcdDevice = QString(udev_device_get_sysattr_value(dev, "bcdDevice")).toInt(&ok, 16); - - - return prtInfo; -} diff --git a/ground/openpilotgcs/src/plugins/rawhid/usbmonitor_mac.cpp b/ground/openpilotgcs/src/plugins/rawhid/usbmonitor_mac.cpp deleted file mode 100644 index 19aac0a47..000000000 --- a/ground/openpilotgcs/src/plugins/rawhid/usbmonitor_mac.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/** - ****************************************************************************** - * - * @file usbmonitor_mac.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @addtogroup RawHIDPlugin Raw HID Plugin - * @{ - * @brief Implements the USB monitor on Mac using XXXXX - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include "usbmonitor.h" -#include -#include -#include -#include -#include -#include - -#define printf qDebug - -// ! Local helper functions -static bool HID_GetIntProperty(IOHIDDeviceRef dev, CFStringRef property, int *value); -static bool HID_GetStrProperty(IOHIDDeviceRef dev, CFStringRef property, QString & value); - -/** - Initialize the USB monitor here - */ -USBMonitor::USBMonitor(QObject *parent) : QThread(parent) -{ - hid_manager = NULL; - IOReturn ret; - - m_instance = this; - - listMutex = new QMutex(); - knowndevices.clear(); - - hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); - if (hid_manager == NULL || CFGetTypeID(hid_manager) != IOHIDManagerGetTypeID()) { - if (hid_manager) { - CFRelease(hid_manager); - } - Q_ASSERT(0); - } - - // No matching filter - IOHIDManagerSetDeviceMatching(hid_manager, NULL); - - // set up a callbacks for device attach & detach - IOHIDManagerScheduleWithRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); - IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, attach_callback, NULL); - IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, detach_callback, NULL); - ret = IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone); - if (ret != kIOReturnSuccess) { - IOHIDManagerUnscheduleFromRunLoop(hid_manager, - CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); - CFRelease(hid_manager); - return; - } - - start(); -} - -USBMonitor::~USBMonitor() -{ - // if(hid_manager != NULL) - // IOHIDManagerUnscheduleFromRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); - quit(); -} - -void USBMonitor::deviceEventReceived() -{ - qDebug() << "Device event"; -} - -USBMonitor *USBMonitor::instance() -{ - return m_instance; -} - -USBMonitor *USBMonitor::m_instance = 0; - - -void USBMonitor::removeDevice(IOHIDDeviceRef dev) -{ - for (int i = 0; i < knowndevices.length(); i++) { - USBPortInfo port = knowndevices.at(i); - if (port.dev_handle == dev) { - QMutexLocker locker(listMutex); - knowndevices.removeAt(i); - emit deviceRemoved(port); - return; - } - } -} - -/** - * @brief Static callback for the USB driver to indicate device removed - */ -void USBMonitor::detach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev) -{ - Q_UNUSED(context); - Q_UNUSED(r); - Q_UNUSED(hid_mgr); - - qDebug() << "USBMonitor: Device detached event"; - instance()->removeDevice(dev); -} - -void USBMonitor::addDevice(USBPortInfo info) -{ - QMutexLocker locker(listMutex); - - knowndevices.append(info); - emit deviceDiscovered(info); -} - -void USBMonitor::attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev) -{ - Q_UNUSED(context); - Q_UNUSED(r); - Q_UNUSED(hid_mgr); - - bool got_properties = true; - - USBPortInfo deviceInfo; - - deviceInfo.dev_handle = dev; - - qDebug() << "USBMonitor: Device attached event"; - - // Populate the device info structure - got_properties &= HID_GetIntProperty(dev, CFSTR(kIOHIDVendorIDKey), &deviceInfo.vendorID); - got_properties &= HID_GetIntProperty(dev, CFSTR(kIOHIDProductIDKey), &deviceInfo.productID); - got_properties &= HID_GetIntProperty(dev, CFSTR(kIOHIDVersionNumberKey), &deviceInfo.bcdDevice); - got_properties &= HID_GetStrProperty(dev, CFSTR(kIOHIDSerialNumberKey), deviceInfo.serialNumber); - got_properties &= HID_GetStrProperty(dev, CFSTR(kIOHIDProductKey), deviceInfo.product); - got_properties &= HID_GetStrProperty(dev, CFSTR(kIOHIDManufacturerKey), deviceInfo.manufacturer); - // TOOD: Eventually want to take array of usages if devices start needing that - got_properties &= HID_GetIntProperty(dev, CFSTR(kIOHIDPrimaryUsageKey), &deviceInfo.Usage); - got_properties &= HID_GetIntProperty(dev, CFSTR(kIOHIDPrimaryUsagePageKey), &deviceInfo.UsagePage); - - // Currently only enumerating objects that have the complete list of properties - if (got_properties) { - qDebug() << "USBMonitor: Adding device"; - instance()->addDevice(deviceInfo); - } -} - -/** - Returns a list of all currently available devices - */ -QList USBMonitor::availableDevices() -{ - // QMutexLocker locker(listMutex); - return knowndevices; -} - -/** - * @brief Be a bit more picky and ask only for a specific type of device: - * @param[in] vid VID to screen or -1 to ignore - * @param[in] pid PID to screen or -1 to ignore - * @param[in] bcdDeviceMSB MSB of bcdDevice to screen or -1 to ignore - * @param[in] bcdDeviceLSB LSB of bcdDevice to screen or -1 to ignore - * @return List of USBPortInfo that meet this criterion - * @note - * On OpenPilot, the bcdDeviceLSB indicates the run state: bootloader or running. - * bcdDeviceMSB indicates the board model. - */ -QList USBMonitor::availableDevices(int vid, int pid, int bcdDeviceMSB, int bcdDeviceLSB) -{ - QList allPorts = availableDevices(); - QList thePortsWeWant; - - foreach(USBPortInfo port, allPorts) { - if ((port.vendorID == vid || vid == -1) && (port.productID == pid || pid == -1) && ((port.bcdDevice >> 8) == bcdDeviceMSB || bcdDeviceMSB == -1) && - ((port.bcdDevice & 0x00ff) == bcdDeviceLSB || bcdDeviceLSB == -1)) { - thePortsWeWant.append(port); - } - } - - return thePortsWeWant; -} - -/** - * @brief Helper function get get a HID integer property - * @param[in] dev Device reference - * @param[in] property The property to get (constants defined in IOKIT) - * @param[out] value Pointer to integer to set - * @return True if successful, false otherwise - */ -static bool HID_GetIntProperty(IOHIDDeviceRef dev, CFStringRef property, int *value) -{ - CFTypeRef prop = IOHIDDeviceGetProperty(dev, property); - - if (prop) { - if (CFNumberGetTypeID() == CFGetTypeID(prop)) { // if a number - CFNumberGetValue((CFNumberRef)prop, kCFNumberSInt32Type, value); - return true; - } - } - return false; -} - -/** - * @brief Helper function get get a HID string property - * @param[in] dev Device reference - * @param[in] property The property to get (constants defined in IOKIT) - * @param[out] value The QString to set - * @return True if successful, false otherwise - */ -static bool HID_GetStrProperty(IOHIDDeviceRef dev, CFStringRef property, QString & value) -{ - CFTypeRef prop = IOHIDDeviceGetProperty(dev, property); - - if (prop) { - if (CFStringGetTypeID() == CFGetTypeID(prop)) { // if a string - char buffer[2550]; - bool success = CFStringGetCString((CFStringRef)prop, buffer, sizeof(buffer), kCFStringEncodingMacRoman); - value = QString(buffer); - return success; - } - } - return false; -} diff --git a/ground/openpilotgcs/src/plugins/rawhid/usbmonitor_win.cpp b/ground/openpilotgcs/src/plugins/rawhid/usbmonitor_win.cpp deleted file mode 100644 index 04f5c8154..000000000 --- a/ground/openpilotgcs/src/plugins/rawhid/usbmonitor_win.cpp +++ /dev/null @@ -1,376 +0,0 @@ -/** - ****************************************************************************** - * - * @file usbmonitor_win.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @addtogroup GCSPlugins GCS Plugins - * @{ - * @addtogroup RawHIDPlugin Raw HID Plugin - * @{ - * @brief Implements the USB monitor on Windows using system API - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include "usbmonitor.h" -#include -#define printf qDebug - -void USBMonitor::deviceEventReceived() -{ - qDebug() << "Device event"; - // Dispatch and emit the signals here... -} - -USBMonitor *USBMonitor::instance() -{ - return m_instance; -} - -USBMonitor *USBMonitor::m_instance = 0; - - -USBMonitor::USBMonitor(QObject *parent) : QThread(parent) -{ - HidD_GetHidGuid(&guid_hid); - if (!QMetaType::isRegistered(QMetaType::type("USBPortInfo"))) { - qRegisterMetaType("USBPortInfo"); - } -#if (defined QT_GUI_LIB) - notificationWidget = 0; -#endif // Q_OS_WIN - setUpNotifications(); - m_instance = this; -} - -USBMonitor::~USBMonitor() -{ -#if (defined QT_GUI_LIB) - if (notificationWidget) { - delete notificationWidget; - } -#endif - quit(); -} - -/** - Be a bit more picky and ask only for a specific type of device: - On OpenPilot, the bcdDeviceLSB indicates the run state: bootloader or running. - bcdDeviceMSB indicates the board model. - */ -QList USBMonitor::availableDevices(int vid, int pid, int bcdDeviceMSB, int bcdDeviceLSB) -{ - QList allPorts = availableDevices(); - qDebug() << "USBMonitor::availableDevices list off all ports:"; - qDebug() << "USBMonitor::availableDevices total ports:" << allPorts.length(); - foreach(USBPortInfo info, allPorts) { - qDebug() << "----------"; - qDebug() << "bcdDevice:" << info.bcdDevice; - qDebug() << "devicePath:" << info.devicePath; - qDebug() << "product:" << info.product; - } - qDebug() << "END OF LIST"; - QList thePortsWeWant; - qDebug() << "USBMonitor::availableDevices bcdLSB=" << bcdDeviceLSB; - foreach(USBPortInfo port, allPorts) { - qDebug() << "USBMonitorWin:Port VID=" << port.vendorID << "PID=" << port.productID << "bcddevice=" << port.bcdDevice; - if ((port.vendorID == vid || vid == -1) && (port.productID == pid || pid == -1) && ((port.bcdDevice >> 8) == bcdDeviceMSB || bcdDeviceMSB == -1) && - ((port.bcdDevice & 0x00ff) == bcdDeviceLSB || bcdDeviceLSB == -1)) { - thePortsWeWant.append(port); - } - } - qDebug() << "USBMonitor::availableDevices list off matching ports vid pid bcdMSD bcdLSD:" << vid << pid << bcdDeviceMSB << bcdDeviceLSB; - qDebug() << "USBMonitor::availableDevices total matching ports:" << thePortsWeWant.length(); - foreach(USBPortInfo info, thePortsWeWant) { - qDebug() << "----------"; - qDebug() << "bcdDevice:" << info.bcdDevice; - qDebug() << "devicePath:" << info.devicePath; - qDebug() << "product:" << info.product; - } - qDebug() << "END OF LIST"; - return thePortsWeWant; -} - - -// see http://msdn.microsoft.com/en-us/library/ms791134.aspx for list of GUID classes -/*#ifndef GUID_DEVCLASS_PORTS - DEFINE_GUID(GUID_DEVCLASS_PORTS, //0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30); - //0x745a17a0, 0x74d3, 0x11d0, 0xb6, 0xfe, 0x00, 0xa0, 0xc9, 0x0f, 0x57, 0xda); - 0xA5DCBF10, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED); - #endif - */ -/* Gordon Schumacher's macros for TCHAR -> QString conversions and vice versa */ -#ifdef UNICODE -#define QStringToTCHAR(x) (wchar_t *)x.utf16() -#define PQStringToTCHAR(x) (wchar_t *)x->utf16() -#define TCHARToQString(x) QString::fromUtf16((ushort *)(x)) -#define TCHARToQStringN(x, y) QString::fromUtf16((ushort *)(x), (y)) -#else -#define QStringToTCHAR(x) x.local8Bit().constData() -#define PQStringToTCHAR(x) x->local8Bit().constData() -#define TCHARToQString(x) QString::fromLocal8Bit((x)) -#define TCHARToQStringN(x, y) QString::fromLocal8Bit((x), (y)) -#endif /*UNICODE*/ - -void USBMonitor::setUpNotifications() -{ -#ifdef QT_GUI_LIB - if (notificationWidget) { - return; - } - notificationWidget = new USBRegistrationWidget(this); - - DEV_BROADCAST_DEVICEINTERFACE dbh; - ZeroMemory(&dbh, sizeof(dbh)); - dbh.dbcc_size = sizeof(dbh); - dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; - CopyMemory(&dbh.dbcc_classguid, &guid_hid, sizeof(GUID)); - if (RegisterDeviceNotification(notificationWidget->winId(), &dbh, DEVICE_NOTIFY_WINDOW_HANDLE) == NULL) { - qWarning() << "RegisterDeviceNotification failed:" << GetLastError(); - } - // setting up notifications doesn't tell us about devices already connected - // so get those manually - foreach(USBPortInfo port, availableDevices()) - emit deviceDiscovered(port); -#else - qWarning("GUI not enabled - can't register for device notifications."); -#endif // QT_GUI_LIB -} -LRESULT USBMonitor::onDeviceChangeWin(WPARAM wParam, LPARAM lParam) -{ - if (DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam) { - PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam; - if (pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) { - PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr; - // delimiters are different across APIs...change to backslash. ugh. - QString deviceID = TCHARToQString(pDevInf->dbcc_name).toUpper().replace("#", "\\"); - matchAndDispatchChangedDevice(deviceID, guid_hid, wParam); - } - } - return 0; -} -#ifdef QT_GUI_LIB -bool USBRegistrationWidget::winEvent(MSG *message, long *result) -{ - if (message->message == WM_DEVICECHANGE) { - qese->onDeviceChangeWin(message->wParam, message->lParam); - *result = 1; - return true; - } - return false; -} -#endif -bool USBMonitor::matchAndDispatchChangedDevice(const QString & deviceID, const GUID & guid, WPARAM wParam) -{ - qDebug() << "USB_MONITOR matchAndDispatchChangedDevice deviceID=" << deviceID; - bool rv = false; - DWORD dwFlag = (DBT_DEVICEARRIVAL == wParam) ? DIGCF_PRESENT : DIGCF_ALLCLASSES; - HDEVINFO devInfo; - if ((devInfo = SetupDiGetClassDevs(&guid, NULL, NULL, dwFlag | DIGCF_DEVICEINTERFACE)) != INVALID_HANDLE_VALUE) { - SP_DEVINFO_DATA spDevInfoData; - spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA); - for (DWORD i = 0; SetupDiEnumDeviceInfo(devInfo, i, &spDevInfoData); i++) { - DWORD nSize = 0; - TCHAR buf[MAX_PATH]; - if (SetupDiGetDeviceInstanceId(devInfo, &spDevInfoData, buf, MAX_PATH, &nSize) && - deviceID.contains(TCHARToQString(buf))) { // we found a match - USBPortInfo info; - info.devicePath = deviceID; - if (wParam == DBT_DEVICEARRIVAL) { - qDebug() << "USB_MONITOR INSERTION"; - if (infoFromHandle(guid, info, devInfo, i) != 1) { - qDebug() << "USB_MONITOR infoFromHandle failed on matchAndDispatchChangedDevice"; - break; - } - bool m_break = false; - foreach(USBPortInfo m_info, knowndevices) { - if (m_info.serialNumber == info.serialNumber && m_info.productID == info.productID && m_info.bcdDevice == info.bcdDevice && m_info.devicePath == info.devicePath) { - qDebug() << "USB_MONITOR device already present don't emit signal"; - m_break = true; - } - } - if (m_break) { - break; - } - if (info.bcdDevice == 0 || info.product.isEmpty()) { - qDebug() << "USB_MONITOR empty information on device not emiting signal"; - break; - } - knowndevices.append(info); - qDebug() << "USB_MONITOR emit device discovered on device:" << info.product << info.bcdDevice; - emit deviceDiscovered(info); - break; - } else if (wParam == DBT_DEVICEREMOVECOMPLETE) { - bool found = false; - for (int x = 0; x < knowndevices.count(); ++x) { - if (knowndevices[x].devicePath == deviceID) { - USBPortInfo temp = knowndevices.at(x); - knowndevices.removeAt(x); - qDebug() << "USB_MONITOR emit device removed on device:" << temp.product << temp.bcdDevice; - emit deviceRemoved(temp); - found = true; - break; - } - } - if (!found) { - qDebug() << "USB_MONITOR emit device removed on unknown device"; - emit deviceRemoved(info); - } - } - break; - } - } - SetupDiDestroyDeviceInfoList(devInfo); - } - return rv; -} - -QString USBMonitor::getDeviceProperty(HDEVINFO devInfo, PSP_DEVINFO_DATA devData, DWORD property) -{ - DWORD buffSize = 0; - - SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, NULL, 0, &buffSize); - BYTE *buff = new BYTE[buffSize]; - SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, buff, buffSize, NULL); - QString result = TCHARToQString(buff); - delete[] buff; - return result; -} -/** - Returns a list of all currently available devices - */ -QList USBMonitor::availableDevices() -{ - QList ports; - enumerateDevicesWin(guid_hid, &ports); - // qDebug()<<"USBMonitorWin availabledevices="< *infoList) -{ - HDEVINFO devInfo; - USBPortInfo info; - - // qDebug()<<"enumerateDevicesWin1"; - if ((devInfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)) != INVALID_HANDLE_VALUE) { - // qDebug()<<"enumerateDevicesWin2"; - SP_DEVINFO_DATA devInfoData; - devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); - for (DWORD i = 0; SetupDiEnumDeviceInfo(devInfo, i, &devInfoData); i++) { - int r = infoFromHandle(guid, info, devInfo, i); - if (r == 1) { - infoList->append(info); - } else if (r == 0) { - break; - } - } - - SetupDiDestroyDeviceInfoList(devInfo); - } -} - -int USBMonitor::infoFromHandle(const GUID & guid, USBPortInfo & info, HDEVINFO & devInfo, DWORD & index) -{ - // qDebug()<<"index0="<DevicePath); - - free(details); - return 2; - } - // qDebug()<<"index4="<DevicePath).toUpper().replace("#", "\\"); - attrib.Size = sizeof(HIDD_ATTRIBUTES); - ret = HidD_GetAttributes(h, &attrib); - info.vendorID = attrib.VendorID; - info.productID = attrib.ProductID; - info.bcdDevice = attrib.VersionNumber; - - - if (!ret || !HidD_GetPreparsedData(h, &hid_data)) { - CloseHandle(h); - return 2; - } - // qDebug()<<"index5="< -void USBSignalFilter::m_deviceDiscovered(USBPortInfo port) -{ - if ((port.vendorID == m_vid || m_vid == -1) && (port.productID == m_pid || m_pid == -1) && ((port.bcdDevice >> 8) == m_boardModel || m_boardModel == -1) && - ((port.bcdDevice & 0x00ff) == m_runState || m_runState == -1)) { - qDebug() << "USBSignalFilter emit device discovered"; - emit deviceDiscovered(); - } -} - -USBSignalFilter::USBSignalFilter(int vid, int pid, int boardModel, int runState) : - m_vid(vid), - m_pid(pid), - m_boardModel(boardModel), - m_runState(runState) -{ - connect(USBMonitor::instance(), SIGNAL(deviceDiscovered(USBPortInfo)), this, SLOT(m_deviceDiscovered(USBPortInfo))); -} diff --git a/ground/openpilotgcs/src/plugins/rawhid/usbsignalfilter.h b/ground/openpilotgcs/src/plugins/rawhid/usbsignalfilter.h deleted file mode 100644 index a3eafa131..000000000 --- a/ground/openpilotgcs/src/plugins/rawhid/usbsignalfilter.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef USBSIGNALFILTER_H -#define USBSIGNALFILTER_H -#include -#include "usbmonitor.h" - -class RAWHID_EXPORT USBSignalFilter : public QObject { - Q_OBJECT -private: - int m_vid; - int m_pid; - int m_boardModel; - int m_runState; -signals: - void deviceDiscovered(); -private slots: - void m_deviceDiscovered(USBPortInfo port); -public: - USBSignalFilter(int vid, int pid, int boardModel, int runState); -}; -#endif // USBSIGNALFILTER_H From 9f44e588f7c33106a4a88a0ed7b276b29a277c61 Mon Sep 17 00:00:00 2001 From: David Ankers Date: Sun, 26 May 2013 16:37:33 +1000 Subject: [PATCH 048/120] Rename USB Constants that map product to PID, changes PipX to OPLM --- ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h index 20ef05031..b39c74952 100644 --- a/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h +++ b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h @@ -116,7 +116,7 @@ public: idVendor_OpenPilot = 0x20a0, idProduct_OpenPilot = 0x415a, idProduct_CopterControl = 0x415b, - idProduct_PipXtreme = 0x415c + idProduct_OPLinkMini = 0x415c }; static USBMonitor *instance(); From 2f9c9df7363738ec7538c5c0c9d198c1ecfe94b4 Mon Sep 17 00:00:00 2001 From: David Ankers Date: Sun, 26 May 2013 17:03:48 +1000 Subject: [PATCH 049/120] Increase the size of the USB Descriptor array to take extra char --- flight/targets/boards/oplinkmini/pios_usb_board_data.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flight/targets/boards/oplinkmini/pios_usb_board_data.c b/flight/targets/boards/oplinkmini/pios_usb_board_data.c index be48bdf78..2f6a2753c 100644 --- a/flight/targets/boards/oplinkmini/pios_usb_board_data.c +++ b/flight/targets/boards/oplinkmini/pios_usb_board_data.c @@ -33,7 +33,7 @@ #include /* PIOS_USBHOOK_* */ #include /* PIOS_USB_UTIL_AsciiToUtf8 */ -static const uint8_t usb_product_id[20] = { +static const uint8_t usb_product_id[22] = { sizeof(usb_product_id), USB_DESC_TYPE_STRING, 'O', 0, @@ -45,7 +45,7 @@ static const uint8_t usb_product_id[20] = { 'M', 0, 'i', 0, 'n', 0, - 'i', 0, + 'i', 0, }; static uint8_t usb_serial_number[2 + PIOS_SYS_SERIAL_NUM_ASCII_LEN * 2 + (sizeof(PIOS_USB_BOARD_SN_SUFFIX) - 1) * 2] = { From 69ede538c9241362b4506108419303a9968a0f3a Mon Sep 17 00:00:00 2001 From: David Ankers Date: Sun, 26 May 2013 17:50:44 +1000 Subject: [PATCH 050/120] Update date bu just an easy ay to start review +review OPReview-485 --- flight/targets/boards/oplinkmini/pios_board.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flight/targets/boards/oplinkmini/pios_board.h b/flight/targets/boards/oplinkmini/pios_board.h index 92bd020e0..9d2ae2b6e 100644 --- a/flight/targets/boards/oplinkmini/pios_board.h +++ b/flight/targets/boards/oplinkmini/pios_board.h @@ -2,7 +2,7 @@ ****************************************************************************** * * @file pios_board.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. * @brief Defines PiOS board hardware for the OpenPilot OPLink Mini board. * @see The GNU Public License (GPL) Version 3 * From e9f83bcc80f0f62d1953c25c3c8a09acdb72ac5e Mon Sep 17 00:00:00 2001 From: Brian Webb Date: Sun, 26 May 2013 08:36:38 -0700 Subject: [PATCH 051/120] Fixes a bug in the rfm22b driver that was reading past the end of the bindings list when receiving a status message. Also adds some formatting changes that came about after doing a make uncrustify_all. --- flight/modules/ComUsbBridge/ComUsbBridge.c | 4 +- flight/pios/common/pios_rfm22b.c | 83 +++++++++---------- .../src/plugins/config/configrevohwwidget.cpp | 4 +- .../plugins/ophid/src/ophid_usbmon_mac.cpp | 21 +++-- 4 files changed, 54 insertions(+), 58 deletions(-) diff --git a/flight/modules/ComUsbBridge/ComUsbBridge.c b/flight/modules/ComUsbBridge/ComUsbBridge.c index 95b42dc22..0a21fb605 100644 --- a/flight/modules/ComUsbBridge/ComUsbBridge.c +++ b/flight/modules/ComUsbBridge/ComUsbBridge.c @@ -50,9 +50,9 @@ static void updateSettings(); #define U2C_STACK_SIZE_BYTES 260 #define C2U_STACK_SIZE_BYTES 316 -#define TASK_PRIORITY (tskIDLE_PRIORITY + 1) +#define TASK_PRIORITY (tskIDLE_PRIORITY + 1) -#define BRIDGE_BUF_LEN 10 +#define BRIDGE_BUF_LEN 10 // **************** // Private variables diff --git a/flight/pios/common/pios_rfm22b.c b/flight/pios/common/pios_rfm22b.c index bebdf0ac5..242f17b21 100644 --- a/flight/pios/common/pios_rfm22b.c +++ b/flight/pios/common/pios_rfm22b.c @@ -265,16 +265,15 @@ static const struct pios_rfm22b_transition rfm22b_transitions[RADIO_STATE_NUM_ST [RADIO_STATE_RX_DATA] = { .entry_fn = radio_rxData, .next_state = { - [RADIO_EVENT_INT_RECEIVED] = RADIO_STATE_RX_DATA, - [RADIO_EVENT_TX_START] = RADIO_STATE_TX_START, - [RADIO_EVENT_REQUEST_CONNECTION] = RADIO_STATE_REQUESTING_CONNECTION, - [RADIO_EVENT_ACK_TIMEOUT] = RADIO_STATE_RECEIVING_NACK, - [RADIO_EVENT_RX_COMPLETE] = RADIO_STATE_SENDING_ACK, + [RADIO_EVENT_INT_RECEIVED] = RADIO_STATE_RX_DATA, + [RADIO_EVENT_TX_START] = RADIO_STATE_TX_START, + [RADIO_EVENT_ACK_TIMEOUT] = RADIO_STATE_RECEIVING_NACK, + [RADIO_EVENT_RX_COMPLETE] = RADIO_STATE_SENDING_ACK, [RADIO_EVENT_RX_MODE] = RADIO_STATE_RX_MODE, - [RADIO_EVENT_STATUS_RECEIVED] = RADIO_STATE_RECEIVING_STATUS, + [RADIO_EVENT_STATUS_RECEIVED] = RADIO_STATE_RECEIVING_STATUS, [RADIO_EVENT_CONNECTION_REQUESTED] = RADIO_STATE_ACCEPTING_CONNECTION, - [RADIO_EVENT_PACKET_ACKED] = RADIO_STATE_RECEIVING_ACK, - [RADIO_EVENT_PACKET_NACKED] = RADIO_STATE_RECEIVING_NACK, + [RADIO_EVENT_PACKET_ACKED] = RADIO_STATE_RECEIVING_ACK, + [RADIO_EVENT_PACKET_NACKED] = RADIO_STATE_RECEIVING_NACK, [RADIO_EVENT_FAILURE] = RADIO_STATE_RX_FAILURE, [RADIO_EVENT_TIMEOUT] = RADIO_STATE_TIMEOUT, [RADIO_EVENT_ERROR] = RADIO_STATE_ERROR, @@ -307,6 +306,7 @@ static const struct pios_rfm22b_transition rfm22b_transitions[RADIO_STATE_NUM_ST .entry_fn = rfm22_receiveStatus, .next_state = { [RADIO_EVENT_RX_COMPLETE] = RADIO_STATE_TX_START, + [RADIO_EVENT_REQUEST_CONNECTION] = RADIO_STATE_REQUESTING_CONNECTION, [RADIO_EVENT_TIMEOUT] = RADIO_STATE_TIMEOUT, [RADIO_EVENT_ERROR] = RADIO_STATE_ERROR, [RADIO_EVENT_INITIALIZE] = RADIO_STATE_INITIALIZING, @@ -517,7 +517,7 @@ int32_t PIOS_RFM22B_Init(uint32_t *rfm22b_id, uint32_t spi_id, uint32_t slave_nu PIOS_EXTI_Init(cfg->exti_cfg); // Register the watchdog timer for the radio driver task -#ifdef PIOS_WDG_RFM22B +#if defined(PIOS_INCLUDE_WDG) && defined(PIOS_WDG_RFM22B) PIOS_WDG_RegisterFlag(PIOS_WDG_RFM22B); #endif /* PIOS_WDG_RFM22B */ @@ -1156,7 +1156,7 @@ static void pios_rfm22_task(void *parameters) portTickType lastPPMTicks = lastEventTicks; while (1) { -#ifdef PIOS_WDG_RFM22B +#if defined(PIOS_INCLUDE_WDG) && defined(PIOS_WDG_RFM22B) // Update the watchdog timer PIOS_WDG_UpdateFlag(PIOS_WDG_RFM22B); #endif /* PIOS_WDG_RFM22B */ @@ -1988,21 +1988,7 @@ static enum pios_radio_event radio_receivePacket(struct pios_rfm22b_dev *radio_d switch (p->header.type) { case PACKET_TYPE_STATUS: ret_event = RADIO_EVENT_STATUS_RECEIVED; - - // Send a connection request message if we're not connected, and this is a status message from a modem that we're bound to. - if (radio_dev->coordinator && !rfm22_isConnected(radio_dev)) { - PHStatusPacketHandle status = (PHStatusPacketHandle) & (radio_dev->rx_packet); - uint32_t source_id = status->source_id; - for (uint8_t i = 0; OPLINKSETTINGS_BINDINGS_NUMELEM; ++i) { - if (radio_dev->bindings[i].pairID == source_id) { - radio_dev->cur_binding = i; - ret_event = RADIO_EVENT_REQUEST_CONNECTION; - break; - } - } - } break; - case PACKET_TYPE_CON_REQUEST: ret_event = RADIO_EVENT_CONNECTION_REQUESTED; break; @@ -2333,19 +2319,20 @@ static enum pios_radio_event rfm22_receiveNack(struct pios_rfm22b_dev *rfm22b_de * @param[in] rfm22b_dev The device structure * @return enum pios_radio_event The next event to inject */ -static enum pios_radio_event rfm22_receiveStatus(struct pios_rfm22b_dev *rfm22b_dev) +static enum pios_radio_event rfm22_receiveStatus(struct pios_rfm22b_dev *radio_dev) { - PHStatusPacketHandle status = (PHStatusPacketHandle) & (rfm22b_dev->rx_packet); - int8_t rssi = rfm22b_dev->rssi_dBm; - int8_t afc = rfm22b_dev->afc_correction_Hz; - uint32_t id = status->source_id; + PHStatusPacketHandle status = (PHStatusPacketHandle) & (radio_dev->rx_packet); + int8_t rssi = radio_dev->rssi_dBm; + int8_t afc = radio_dev->afc_correction_Hz; + uint32_t id = status->source_id; + enum pios_radio_event ret_event = RADIO_EVENT_RX_COMPLETE; // Have we seen this device recently? bool found = false; uint8_t id_idx = 0; for (; id_idx < OPLINKSTATUS_PAIRIDS_NUMELEM; ++id_idx) { - if (rfm22b_dev->pair_stats[id_idx].pairID == id) { + if (radio_dev->pair_stats[id_idx].pairID == id) { found = true; break; } @@ -2353,27 +2340,37 @@ static enum pios_radio_event rfm22_receiveStatus(struct pios_rfm22b_dev *rfm22b_ // If we have seen it, update the RSSI and reset the last contact couter if (found) { - rfm22b_dev->pair_stats[id_idx].rssi = rssi; - rfm22b_dev->pair_stats[id_idx].afc_correction = afc; - rfm22b_dev->pair_stats[id_idx].lastContact = 0; - - // If we haven't seen it, find a slot to put it in. + radio_dev->pair_stats[id_idx].rssi = rssi; + radio_dev->pair_stats[id_idx].afc_correction = afc; + radio_dev->pair_stats[id_idx].lastContact = 0; } else { + // If we haven't seen it, find a slot to put it in. uint8_t min_idx = 0; - int8_t min_rssi = rfm22b_dev->pair_stats[0].rssi; + int8_t min_rssi = radio_dev->pair_stats[0].rssi; for (id_idx = 1; id_idx < OPLINKSTATUS_PAIRIDS_NUMELEM; ++id_idx) { - if (rfm22b_dev->pair_stats[id_idx].rssi < min_rssi) { - min_rssi = rfm22b_dev->pair_stats[id_idx].rssi; + if (radio_dev->pair_stats[id_idx].rssi < min_rssi) { + min_rssi = radio_dev->pair_stats[id_idx].rssi; min_idx = id_idx; } } - rfm22b_dev->pair_stats[min_idx].pairID = id; - rfm22b_dev->pair_stats[min_idx].rssi = rssi; - rfm22b_dev->pair_stats[min_idx].afc_correction = afc; - rfm22b_dev->pair_stats[min_idx].lastContact = 0; + radio_dev->pair_stats[min_idx].pairID = id; + radio_dev->pair_stats[min_idx].rssi = rssi; + radio_dev->pair_stats[min_idx].afc_correction = afc; + radio_dev->pair_stats[min_idx].lastContact = 0; } - return RADIO_EVENT_RX_COMPLETE; + // Send a connection request message if we're not connected, and this is a status message from a modem that we're bound to. + if (radio_dev->coordinator && !rfm22_isConnected(radio_dev)) { + for (uint8_t i = 0; i < OPLINKSETTINGS_BINDINGS_NUMELEM; ++i) { + if (radio_dev->bindings[i].pairID == id) { + radio_dev->cur_binding = i; + ret_event = RADIO_EVENT_REQUEST_CONNECTION; + break; + } + } + } + + return ret_event; } diff --git a/ground/openpilotgcs/src/plugins/config/configrevohwwidget.cpp b/ground/openpilotgcs/src/plugins/config/configrevohwwidget.cpp index c5a72f0b6..22da2b6b8 100644 --- a/ground/openpilotgcs/src/plugins/config/configrevohwwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configrevohwwidget.cpp @@ -95,7 +95,7 @@ void ConfigRevoHWWidget::setupCustomCombos() connect(m_ui->cbFlexi, SIGNAL(currentIndexChanged(int)), this, SLOT(flexiPortChanged(int))); connect(m_ui->cbMain, SIGNAL(currentIndexChanged(int)), this, SLOT(mainPortChanged(int))); - connect(m_ui->cbModem, SIGNAL(currentIndexChanged(int)), this, SLOT(modemPortChanged(int))); + connect(m_ui->cbModem, SIGNAL(currentIndexChanged(int)), this, SLOT(modemPortChanged(int))); } void ConfigRevoHWWidget::refreshWidgetsValues(UAVObject *obj) @@ -295,7 +295,7 @@ void ConfigRevoHWWidget::modemPortChanged(int index) m_ui->cbTxPower->setVisible(true); m_ui->lblInitFreq->setVisible(true); m_ui->leInitFreq->setVisible(true); - if(!m_refreshing) { + if (!m_refreshing) { QMessageBox::warning(this, tr("Warning"), tr("Activating the Radio requires an antenna be attached or modem damage will occur.")); } } else { diff --git a/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp index 8524c4b57..ca907a301 100644 --- a/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp +++ b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_mac.cpp @@ -42,7 +42,7 @@ static bool HID_GetStrProperty(IOHIDDeviceRef dev, CFStringRef property, QString /** * \brief Initialize the USB monitor * - * \note + * \note */ USBMonitor::USBMonitor(QObject *parent) : QThread(parent), m_terminate(1) { @@ -57,7 +57,7 @@ USBMonitor::USBMonitor(QObject *parent) : QThread(parent), m_terminate(1) /** * \brief Free the USB monitor * - * \note + * \note */ USBMonitor::~USBMonitor() { @@ -68,7 +68,7 @@ USBMonitor::~USBMonitor() /** * \brief Event received callback * - * \note + * \note */ void USBMonitor::deviceEventReceived() { @@ -78,7 +78,7 @@ void USBMonitor::deviceEventReceived() /** * \brief instace of USB monitor * - * \note + * \note */ USBMonitor *USBMonitor::instance() { @@ -91,7 +91,7 @@ USBMonitor *USBMonitor::m_instance = 0; /** * \brief Remove device * - * \note + * \note */ void USBMonitor::removeDevice(IOHIDDeviceRef dev) { @@ -111,7 +111,7 @@ void USBMonitor::removeDevice(IOHIDDeviceRef dev) /** * \brief Static callback for the USB driver to indicate device removed * - * \note + * \note */ void USBMonitor::detach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev) { @@ -127,7 +127,7 @@ void USBMonitor::detach_callback(void *context, IOReturn r, void *hid_mgr, IOHID /** * \brief Add device * - * \note + * \note */ void USBMonitor::addDevice(USBPortInfo info) { @@ -142,7 +142,7 @@ void USBMonitor::addDevice(USBPortInfo info) /** * \brief Attach device * - * \note + * \note */ void USBMonitor::attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev) { @@ -180,7 +180,7 @@ void USBMonitor::attach_callback(void *context, IOReturn r, void *hid_mgr, IOHID /** * \brief Returns a list of all currently available devices * - * \note + * \note */ QList USBMonitor::availableDevices() { @@ -218,7 +218,7 @@ QList USBMonitor::availableDevices(int vid, int pid, int bcdDeviceM /** * \brief USBMonitor thread * - * \note + * \note */ void USBMonitor::run() { @@ -297,4 +297,3 @@ static bool HID_GetStrProperty(IOHIDDeviceRef dev, CFStringRef property, QString } return false; } - From 78dda599f5319655188b6a1047d45fc273c3cc3a Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sun, 26 May 2013 18:09:15 +0200 Subject: [PATCH 052/120] OP-939 Changed default power output for OPLink and Revo to lowest setting --- shared/uavobjectdefinition/hwsettings.xml | 2 +- shared/uavobjectdefinition/oplinksettings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/uavobjectdefinition/hwsettings.xml b/shared/uavobjectdefinition/hwsettings.xml index 08a62c5b8..5d0a29fec 100644 --- a/shared/uavobjectdefinition/hwsettings.xml +++ b/shared/uavobjectdefinition/hwsettings.xml @@ -17,7 +17,7 @@ - + diff --git a/shared/uavobjectdefinition/oplinksettings.xml b/shared/uavobjectdefinition/oplinksettings.xml index d6dfd7844..b78b8d4c9 100644 --- a/shared/uavobjectdefinition/oplinksettings.xml +++ b/shared/uavobjectdefinition/oplinksettings.xml @@ -9,7 +9,7 @@ - + From 6e277906e2b97c368706439e7cee2fe6ad47dfda Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sun, 26 May 2013 19:42:16 +0200 Subject: [PATCH 053/120] OP-761 Fix visualization of UAV GPS coordinates for CC/CC3D When positionActual is (0,0,0) uses GPS position as the UAV position +review OPReview --- .../src/plugins/opmap/opmapgadgetwidget.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/opmap/opmapgadgetwidget.cpp b/ground/openpilotgcs/src/plugins/opmap/opmapgadgetwidget.cpp index c7d193f24..9b2b34326 100644 --- a/ground/openpilotgcs/src/plugins/opmap/opmapgadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/opmap/opmapgadgetwidget.cpp @@ -2170,6 +2170,19 @@ bool OPMapGadgetWidget::getUAVPosition(double &latitude, double &longitude, doub Q_ASSERT(obm != NULL); + PositionActual *positionActual = PositionActual::GetInstance(obm); + Q_ASSERT(positionActual != NULL); + PositionActual::DataFields positionActualData = positionActual->getData(); + if(positionActualData.North == 0 && positionActualData.East == 0 && positionActualData.Down == 0){ + GPSPosition *gpsPositionObj = GPSPosition::GetInstance(obm); + Q_ASSERT(gpsPositionObj); + + GPSPosition::DataFields gpsPositionData = gpsPositionObj->getData(); + latitude = gpsPositionData.Latitude / 1e7f; + longitude = gpsPositionData.Longitude / 1e7f; + altitude = gpsPositionData.Altitude; + return true; + } HomeLocation *homeLocation = HomeLocation::GetInstance(obm); Q_ASSERT(homeLocation != NULL); HomeLocation::DataFields homeLocationData = homeLocation->getData(); @@ -2178,9 +2191,6 @@ bool OPMapGadgetWidget::getUAVPosition(double &latitude, double &longitude, doub homeLLA[1] = homeLocationData.Longitude / 1e7; homeLLA[2] = homeLocationData.Altitude; - PositionActual *positionActual = PositionActual::GetInstance(obm); - Q_ASSERT(positionActual != NULL); - PositionActual::DataFields positionActualData = positionActual->getData(); NED[0] = positionActualData.North; NED[1] = positionActualData.East; From b6d3b2ac220b41203bb29f515b684f8d302ebcea Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sun, 26 May 2013 22:47:43 +0300 Subject: [PATCH 054/120] OP-893: do not include *.opfw firmware files into package Now GCS has all firmware embedded and available through the Vehicle Setup Wizard or Auto-Update function. Hence it is not necessary to include another copies of the same files. But the code to do this is kept because later we will include sim targets as firmware. Linux version does include it already, OSX and Windows should follow. --- package/linux/deb_common/rules | 2 +- package/osx/package | 2 +- package/winx86/openpilotgcs.nsi | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package/linux/deb_common/rules b/package/linux/deb_common/rules index 5b0fa10ac..9bf1a3e68 100644 --- a/package/linux/deb_common/rules +++ b/package/linux/deb_common/rules @@ -43,7 +43,7 @@ install: cp -arp package/linux/openpilot_menu.menu debian/openpilot/etc/xdg/menus/applications-merged cp -arp package/linux/openpilot_menu.directory debian/openpilot/usr/share/desktop-directories ifdef PACKAGE_DIR - cp -a $(PACKAGE_DIR)/* debian/openpilot/usr/local/OpenPilot/firmware/ + cp -a $(PACKAGE_DIR)/*.elf debian/openpilot/usr/local/OpenPilot/firmware/ else $(error PACKAGE_DIR not defined! $(PACKAGE_DIR)) endif diff --git a/package/osx/package b/package/osx/package index 4d9064d34..bfc3d9443 100755 --- a/package/osx/package +++ b/package/osx/package @@ -20,7 +20,7 @@ device=$(hdiutil attach "${TEMP_FILE}" | \ # packaging goes here cp -a "${APP_PATH}" "/Volumes/${VOL_NAME}" -ls "${FW_DIR}" | xargs -n 1 -I {} cp "${FW_DIR}/{}" "/Volumes/${VOL_NAME}/Firmware" +#ls "${FW_DIR}" | xargs -n 1 -I {} cp "${FW_DIR}/{}" "/Volumes/${VOL_NAME}/Firmware" cp "${BUILD_DIR}/uavobject-synthetics/matlab/OPLogConvert.m" "/Volumes/${VOL_NAME}/Utilities" cp "${ROOT_DIR}/HISTORY.txt" "/Volumes/${VOL_NAME}" diff --git a/package/winx86/openpilotgcs.nsi b/package/winx86/openpilotgcs.nsi index 071b27ba5..7710585b8 100644 --- a/package/winx86/openpilotgcs.nsi +++ b/package/winx86/openpilotgcs.nsi @@ -202,7 +202,7 @@ Section "-Localization" InSecLocalization SectionEnd ; Copy firmware files -Section "Firmware" InSecFirmware +Section /o "-Firmware" InSecFirmware SetOutPath "$INSTDIR\firmware" File /r "${PACKAGE_DIR}\${FIRMWARE_DIR}\*" SectionEnd From 9937b093c824f2b9d8da789119fdf438e1ccd25b Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sun, 26 May 2013 23:54:27 +0300 Subject: [PATCH 055/120] OP-893: fix simposix firmware copy rule (we include ELF files only) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 58f849bf7..2aab91743 100644 --- a/Makefile +++ b/Makefile @@ -764,7 +764,7 @@ package: all_fw all_ground uavobjects_matlab $(V1) [ ! -d "$(PACKAGE_DIR)" ] || $(RM) -rf "$(PACKAGE_DIR)" $(V1) $(MKDIR) -p "$(PACKAGE_DIR)/firmware" $(foreach fw_targ, $(PACKAGE_FW_TARGETS), $(call COPY_FW_FILES,$(fw_targ),.opfw,.opfw)) - $(foreach fw_targ, $(PACKAGE_ELF_TARGETS), $(call COPY_FW_FILES,$(fw_targ),.elf,)) + $(foreach fw_targ, $(PACKAGE_ELF_TARGETS), $(call COPY_FW_FILES,$(fw_targ),.elf,.elf)) $(MAKE) --no-print-directory -C $(ROOT_DIR)/package --file=$(UNAME).mk $@ ############################## From 6f32ff3f68afe608b215c6b46366e5ea596fd4e5 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Sun, 26 May 2013 23:23:09 +0200 Subject: [PATCH 056/120] OP-968: HITL Simulation gadget has fixed size buttons and button text gets truncated in French translation +review OPReview --- .../src/plugins/hitl/hitlwidget.ui | 85 ++++++++++++------- 1 file changed, 52 insertions(+), 33 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/hitl/hitlwidget.ui b/ground/openpilotgcs/src/plugins/hitl/hitlwidget.ui index a51aeba58..31bf31aa2 100644 --- a/ground/openpilotgcs/src/plugins/hitl/hitlwidget.ui +++ b/ground/openpilotgcs/src/plugins/hitl/hitlwidget.ui @@ -187,6 +187,12 @@ color: rgba(0, 0, 0, 128); + + + 0 + 0 + + Request update @@ -208,7 +214,7 @@ color: rgba(0, 0, 0, 128); - 10 + 5 20 @@ -219,6 +225,12 @@ color: rgba(0, 0, 0, 128); false + + + 0 + 0 + + Send update @@ -347,22 +359,6 @@ color: rgba(0, 0, 0, 128); - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 10 - 20 - - - - @@ -390,7 +386,7 @@ color: rgba(0, 0, 0, 128); - + Qt::Horizontal @@ -399,27 +395,44 @@ color: rgba(0, 0, 0, 128); - 5 + 10 20 - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + true + + + + 0 + 0 + + + + + 140 + 0 + + + + + 0 + 0 + + + + + 0 + 0 + + + + false + Clear Log @@ -466,6 +479,12 @@ color: rgba(0, 0, 0, 128); + + startButton + stopButton + buttonClearLog + textBrowser + From 6df6ec20a4494cb42899226cf32cbb2138b0fc20 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Mon, 27 May 2013 00:23:18 +0200 Subject: [PATCH 057/120] OP-761 fix constants type+ +review OPReview-487 --- .../openpilotgcs/src/plugins/opmap/opmapgadgetwidget.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/opmap/opmapgadgetwidget.cpp b/ground/openpilotgcs/src/plugins/opmap/opmapgadgetwidget.cpp index 9b2b34326..267cd2ec5 100644 --- a/ground/openpilotgcs/src/plugins/opmap/opmapgadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/opmap/opmapgadgetwidget.cpp @@ -2178,8 +2178,8 @@ bool OPMapGadgetWidget::getUAVPosition(double &latitude, double &longitude, doub Q_ASSERT(gpsPositionObj); GPSPosition::DataFields gpsPositionData = gpsPositionObj->getData(); - latitude = gpsPositionData.Latitude / 1e7f; - longitude = gpsPositionData.Longitude / 1e7f; + latitude = gpsPositionData.Latitude / 1.0e7; + longitude = gpsPositionData.Longitude / 1.0e7; altitude = gpsPositionData.Altitude; return true; } @@ -2187,8 +2187,8 @@ bool OPMapGadgetWidget::getUAVPosition(double &latitude, double &longitude, doub Q_ASSERT(homeLocation != NULL); HomeLocation::DataFields homeLocationData = homeLocation->getData(); - homeLLA[0] = homeLocationData.Latitude / 1e7; - homeLLA[1] = homeLocationData.Longitude / 1e7; + homeLLA[0] = homeLocationData.Latitude / 1.0e7; + homeLLA[1] = homeLocationData.Longitude / 1.0e7; homeLLA[2] = homeLocationData.Altitude; From 1e4262b3097c63a98734f99982b0f2811695cd94 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Mon, 27 May 2013 19:55:25 +0200 Subject: [PATCH 058/120] OP-926 Fix huge tab height on kde due to wrong telemetrymonitorwidget size. Patch from Noxs, more details here: http://git.openpilot.org/cru/OPReview-486 +review OPReview-486 --- .../src/plugins/coreplugin/telemetrymonitorwidget.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/coreplugin/telemetrymonitorwidget.cpp b/ground/openpilotgcs/src/plugins/coreplugin/telemetrymonitorwidget.cpp index 268c7f1d4..0463d68d2 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/telemetrymonitorwidget.cpp +++ b/ground/openpilotgcs/src/plugins/coreplugin/telemetrymonitorwidget.cpp @@ -7,8 +7,8 @@ TelemetryMonitorWidget::TelemetryMonitorWidget(QWidget *parent) : QGraphicsView(parent) { - setMinimumSize(180, 100); - setMaximumSize(180, 100); + setMinimumSize(180, 25); // From 100->25 to shorten the qwidget. + setMaximumSize(180, 25); // as above. setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); @@ -18,7 +18,7 @@ TelemetryMonitorWidget::TelemetryMonitorWidget(QWidget *parent) : QGraphicsView( setAttribute(Qt::WA_TranslucentBackground); setWindowFlags(Qt::FramelessWindowHint); - QGraphicsScene *scene = new QGraphicsScene(0, 0, 180, 100, this); + QGraphicsScene *scene = new QGraphicsScene(0, 0, 180, 25, this); // keeping the scene in line with the widget for testing. QSvgRenderer *renderer = new QSvgRenderer(); if (renderer->load(QString(":/core/images/tx-rx.svg"))) { @@ -172,6 +172,5 @@ void TelemetryMonitorWidget::resizeEvent(QResizeEvent *event) { Q_UNUSED(event); - graph->setPos(0, -130); fitInView(graph, Qt::KeepAspectRatio); } From c40976c26049bbb8f5791d815778732428376107 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Mon, 27 May 2013 20:11:59 +0200 Subject: [PATCH 059/120] OP-925 converted mixed tabs/spaces to spaces only +review OPReview-484 --- shared/uavobjectdefinition/attitudesettings.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/shared/uavobjectdefinition/attitudesettings.xml b/shared/uavobjectdefinition/attitudesettings.xml index 56dac2f46..8c86e2af3 100644 --- a/shared/uavobjectdefinition/attitudesettings.xml +++ b/shared/uavobjectdefinition/attitudesettings.xml @@ -7,13 +7,13 @@ - - - + + + - - - + + + From 94d38a4b486b63e254ba80f17566ffa8d0d71a42 Mon Sep 17 00:00:00 2001 From: Fredrik Arvidsson Date: Mon, 27 May 2013 20:42:56 +0200 Subject: [PATCH 060/120] OP-770 Updates version info code used in AUV settings export file. --- .../uavsettingsimportexportfactory.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexportfactory.cpp b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexportfactory.cpp index f54317daa..42fcb3b8f 100644 --- a/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexportfactory.cpp +++ b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexportfactory.cpp @@ -246,15 +246,10 @@ QString UAVSettingsImportExportFactory::createXMLDocument(const enum storedData fw.setAttribute("tag", board.gitTag); versionInfo.appendChild(fw); - QString gcsRevision = VersionInfo::revision(); - QString gcsGitDate = gcsRevision.mid(gcsRevision.indexOf(" ") + 1, 14); - QString gcsGitHash = gcsRevision.mid(gcsRevision.indexOf(":") + 1, 8); - QString gcsGitTag = gcsRevision.left(gcsRevision.indexOf(":")); - - QDomElement gcs = doc.createElement("gcs"); - gcs.setAttribute("date", gcsGitDate); - gcs.setAttribute("hash", gcsGitHash); - gcs.setAttribute("tag", gcsGitTag); + QDomElement gcs = doc.createElement("gcs"); + gcs.setAttribute("date", VersionInfo::dateTime()); + gcs.setAttribute("hash", VersionInfo::hash()); + gcs.setAttribute("tag", VersionInfo::tagOrBranch()); versionInfo.appendChild(gcs); // create settings and/or data elements From a286a20cb01cc47e27986423d7b9212dc6343f55 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Mon, 27 May 2013 21:05:39 +0200 Subject: [PATCH 061/120] OP-925 Changed dT to comply with revo sensor rate +review OPReview-484 --- flight/modules/Attitude/revolution/attitude.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flight/modules/Attitude/revolution/attitude.c b/flight/modules/Attitude/revolution/attitude.c index e49257b40..6334017e2 100644 --- a/flight/modules/Attitude/revolution/attitude.c +++ b/flight/modules/Attitude/revolution/attitude.c @@ -1185,7 +1185,7 @@ static void settingsUpdatedCb(UAVObjEvent *ev) AttitudeSettingsGet(&attitudeSettings); // Calculate accel filter alpha, in the same way as for gyro data in stabilization module. - const float fakeDt = 0.0025f; + const float fakeDt = 0.0015f; if (attitudeSettings.AccelTau < 0.0001f) { accel_alpha = 0; // not trusting this to resolve to 0 accel_filter_enabled = false; From 316afefff7a36ebdefc43a0a60c5ab06d1d3bb6d Mon Sep 17 00:00:00 2001 From: Fredrik Arvidsson Date: Mon, 27 May 2013 22:25:17 +0200 Subject: [PATCH 062/120] OP-906 Changed defaults for Stabilization settings and Flight modes. --- .../plugins/setupwizard/vehicleconfigurationhelper.cpp | 10 +++++----- shared/uavobjectdefinition/manualcontrolsettings.xml | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationhelper.cpp b/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationhelper.cpp index 81d60f3c2..e38c23e4f 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationhelper.cpp +++ b/ground/openpilotgcs/src/plugins/setupwizard/vehicleconfigurationhelper.cpp @@ -321,11 +321,11 @@ void VehicleConfigurationHelper::applyFlighModeConfiguration() data.Stabilization3Settings[2] = ManualControlSettings::STABILIZATION3SETTINGS_RATE; data.FlightModeNumber = 3; data.FlightModePosition[0] = ManualControlSettings::FLIGHTMODEPOSITION_STABILIZED1; - data.FlightModePosition[1] = ManualControlSettings::FLIGHTMODEPOSITION_STABILIZED1; - data.FlightModePosition[2] = ManualControlSettings::FLIGHTMODEPOSITION_STABILIZED1; - data.FlightModePosition[3] = ManualControlSettings::FLIGHTMODEPOSITION_STABILIZED1; - data.FlightModePosition[4] = ManualControlSettings::FLIGHTMODEPOSITION_STABILIZED1; - data.FlightModePosition[5] = ManualControlSettings::FLIGHTMODEPOSITION_STABILIZED1; + data.FlightModePosition[1] = ManualControlSettings::FLIGHTMODEPOSITION_STABILIZED2; + data.FlightModePosition[2] = ManualControlSettings::FLIGHTMODEPOSITION_STABILIZED3; + data.FlightModePosition[3] = ManualControlSettings::FLIGHTMODEPOSITION_ALTITUDEHOLD; + data.FlightModePosition[4] = ManualControlSettings::FLIGHTMODEPOSITION_POSITIONHOLD; + data.FlightModePosition[5] = ManualControlSettings::FLIGHTMODEPOSITION_MANUAL; controlSettings->setData(data); addModifiedObject(controlSettings, tr("Writing flight mode settings")); } diff --git a/shared/uavobjectdefinition/manualcontrolsettings.xml b/shared/uavobjectdefinition/manualcontrolsettings.xml index c8486ce15..0c627d92e 100644 --- a/shared/uavobjectdefinition/manualcontrolsettings.xml +++ b/shared/uavobjectdefinition/manualcontrolsettings.xml @@ -23,7 +23,7 @@ @@ -44,7 +44,7 @@ type="enum" elements="6" options="Manual,Stabilized1,Stabilized2,Stabilized3,Autotune,AltitudeHold,VelocityControl,PositionHold,ReturnToBase,Land,PathPlanner,POI" - defaultvalue="Manual,Stabilized1,Stabilized2,Stabilized3,AltitudeHold,PositionHold" + defaultvalue="Stabilized1,Stabilized2,Stabilized3,AltitudeHold,PositionHold,Manual" limits="\ %0401NE:Autotune:AltitudeHold:VelocityControl:PositionHold:ReturnToBase:Land:PathPlanner:POI,\ %0402NE:Autotune:AltitudeHold:VelocityControl:PositionHold:ReturnToBase:Land:PathPlanner:POI,\ From 208278a7cb66fde29f8e4607a6a9a918506bc461 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Tue, 28 May 2013 03:40:03 +0300 Subject: [PATCH 063/120] OP-770: use VersionInfo::uavoHash() instead of dynamic string --- .../src/plugins/coreplugin/authorsdialog.cpp | 25 ++----------------- .../src/plugins/coreplugin/versiondialog.cpp | 25 ++----------------- 2 files changed, 4 insertions(+), 46 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.cpp b/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.cpp index 690f3dec0..13af48f34 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.cpp +++ b/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.cpp @@ -75,31 +75,10 @@ AuthorsDialog::AuthorsDialog(QWidget *parent) // : This gets conditionally inserted as argument %8 into the description string. ideRev = tr("From revision %1
").arg(VersionInfo::revision().left(10)); - QString uavoHashStr; - if (VersionInfo::uavoHashArray().length() > 15) { - // : This gets conditionally inserted as argument %11 into the description string. - QByteArray uavoHashArray; - QString uavoHash = VersionInfo::uavoHashArray(); - uavoHash.chop(2); - uavoHash.remove(0, 2); - uavoHash = uavoHash.trimmed(); - bool ok; - foreach(QString str, uavoHash.split(",")) { - uavoHashArray.append(str.toInt(&ok, 16)); - } - QString gcsUavoHashStr; - foreach(char i, uavoHashArray) { - gcsUavoHashStr.append(QString::number(i, 16).right(2)); - } - uavoHashStr = gcsUavoHashStr; - } else { - uavoHashStr = "N/A"; - } - const QString description = tr( "

OpenPilot Ground Control Station

" "GCS Revision: %1
" - "UAVO Hash: %2
" + "UAVO Hash: %2
" "
" "Built from %3
" "Built on %4 at %5
" @@ -117,7 +96,7 @@ AuthorsDialog::AuthorsDialog(QWidget *parent) "PARTICULAR PURPOSE." ).arg( VersionInfo::revision().left(60), // %1 - uavoHashStr, // %2 + VersionInfo::uavoHash().left(8), // %2 VersionInfo::origin(), // $3 QLatin1String(__DATE__), // %4 QLatin1String(__TIME__), // %5 diff --git a/ground/openpilotgcs/src/plugins/coreplugin/versiondialog.cpp b/ground/openpilotgcs/src/plugins/coreplugin/versiondialog.cpp index 995078ee5..cd3e2b192 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/versiondialog.cpp +++ b/ground/openpilotgcs/src/plugins/coreplugin/versiondialog.cpp @@ -59,31 +59,10 @@ VersionDialog::VersionDialog(QWidget *parent) QGridLayout *layout = new QGridLayout(this); layout->setSizeConstraint(QLayout::SetFixedSize); - QString uavoHashStr; - if (VersionInfo::uavoHashArray().length() > 15) { - // : This gets conditionally inserted as argument %11 into the description string. - QByteArray uavoHashArray; - QString uavoHash = VersionInfo::uavoHashArray(); - uavoHash.chop(2); - uavoHash.remove(0, 2); - uavoHash = uavoHash.trimmed(); - bool ok; - foreach(QString str, uavoHash.split(",")) { - uavoHashArray.append(str.toInt(&ok, 16)); - } - QString gcsUavoHashStr; - foreach(char i, uavoHashArray) { - gcsUavoHashStr.append(QString::number(i, 16).right(2)); - } - uavoHashStr = gcsUavoHashStr; - } else { - uavoHashStr = "N/A"; - } - const QString description = tr( "

OpenPilot Ground Control Station

" "GCS Revision: %1
" - "UAVO Hash: %2
" + "UAVO Hash: %2
" "
" "Built from %3
" "Built on %4 at %5
" @@ -101,7 +80,7 @@ VersionDialog::VersionDialog(QWidget *parent) "PARTICULAR PURPOSE." ).arg( VersionInfo::revision().left(60), // %1 - uavoHashStr, // %2 + VersionInfo::uavoHash().left(8), // %2 VersionInfo::origin(), // $3 QLatin1String(__DATE__), // %4 QLatin1String(__TIME__), // %5 From 0512ca79efee5245989618fe70bfbca6717ec4e4 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Tue, 28 May 2013 04:14:54 +0300 Subject: [PATCH 064/120] OP-770: export GCS branch dirty state and short UAVO hash --- .../uavsettingsimportexportfactory.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexportfactory.cpp b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexportfactory.cpp index 42fcb3b8f..d5b1c7e9a 100644 --- a/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexportfactory.cpp +++ b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexportfactory.cpp @@ -241,15 +241,18 @@ QString UAVSettingsImportExportFactory::createXMLDocument(const enum storedData versionInfo.appendChild(hw); QDomElement fw = doc.createElement("firmware"); + QString uavo = board.uavoHash.toHex(); + fw.setAttribute("tag", board.gitTag); fw.setAttribute("date", board.gitDate); fw.setAttribute("hash", board.gitHash); - fw.setAttribute("tag", board.gitTag); + fw.setAttribute("uavo", uavo.left(8)); versionInfo.appendChild(fw); QDomElement gcs = doc.createElement("gcs"); + gcs.setAttribute("tag", VersionInfo::tagOrBranch() + VersionInfo::dirty()); gcs.setAttribute("date", VersionInfo::dateTime()); - gcs.setAttribute("hash", VersionInfo::hash()); - gcs.setAttribute("tag", VersionInfo::tagOrBranch()); + gcs.setAttribute("hash", VersionInfo::hash().left(8)); + gcs.setAttribute("uavo", VersionInfo::uavoHash().left(8)); versionInfo.appendChild(gcs); // create settings and/or data elements From 854d976a7d5d185fd809f412a89378429e46aefc Mon Sep 17 00:00:00 2001 From: Mathieu Rondonneau Date: Mon, 27 May 2013 18:52:27 -0700 Subject: [PATCH 065/120] OP-958: Go through the list of enumerated devices, and try to open the device until end of the list. Leave if we open one with success. --- .../src/plugins/ophid/src/ophid_hidapi.cpp | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/ophid/src/ophid_hidapi.cpp b/ground/openpilotgcs/src/plugins/ophid/src/ophid_hidapi.cpp index baacd5502..69007d804 100644 --- a/ground/openpilotgcs/src/plugins/ophid/src/ophid_hidapi.cpp +++ b/ground/openpilotgcs/src/plugins/ophid/src/ophid_hidapi.cpp @@ -131,8 +131,8 @@ int opHID_hidapi::open(int max, int vid, int pid, int usage_page, int usage) { int devices_found = false; struct hid_device_info *current_device_ptr = NULL; - struct hid_device_info *last_device_ptr = NULL; - struct hid_device_info * *current_device_pptr = ¤t_device_ptr; + struct hid_device_info *tmp_device_ptr = NULL; + struct hid_device_info **current_device_pptr = ¤t_device_ptr; OPHID_TRACE("IN"); @@ -170,21 +170,27 @@ int opHID_hidapi::open(int max, int vid, int pid, int usage_page, int usage) } if (devices_found) { - // Look for the last one in the list - // WARNING: for now this prevent to have devices chained - last_device_ptr = current_device_ptr; - while (last_device_ptr->next) { - last_device_ptr = last_device_ptr->next; + + // Go through the list until we can open one + // WARNING: for now this prevent to have device chained + tmp_device_ptr = current_device_ptr; + + while (tmp_device_ptr) { + + OPHID_DEBUG("Opening device VID(%04hx).PID(%04hx)", + tmp_device_ptr->vendor_id, + tmp_device_ptr->product_id); + + handle = hid_open(tmp_device_ptr->vendor_id, + tmp_device_ptr->product_id, + NULL); + + if (handle) + break; + + tmp_device_ptr = tmp_device_ptr->next; } - OPHID_DEBUG("Opening device VID(%04hx).PID(%04hx)", - last_device_ptr->vendor_id, - last_device_ptr->product_id); - - handle = hid_open(last_device_ptr->vendor_id, - last_device_ptr->product_id, - NULL); - hid_free_enumeration(current_device_ptr); if (!handle) { From 6b7080d9588fd9b75ce10b559d74cdb944638745 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Tue, 28 May 2013 15:32:27 +0200 Subject: [PATCH 066/120] OP-843 setting dialog reordering: plugin options pages (top part) are now sorted on their untranslated name this solve the issue of the order changing per language The bottom part of the tree (gadget options pages) is still sorted by translated name as before. Additional fixes: - Moved GCS page to Environment node + renamed to Workspaces - Renamed Notigy Plugin node to Notification - Moved the two Telemetry nodes together - Split plane size is now persistent (in addition to size and selected node) --- .../translations/openpilotgcs_de.ts | 2 +- .../translations/openpilotgcs_es.ts | 2 +- .../translations/openpilotgcs_fr.ts | 4 +- .../translations/openpilotgcs_ru.ts | 2 +- .../translations/openpilotgcs_zh_CN.ts | 2 +- .../coreplugin/dialogs/settingsdialog.cpp | 316 +++++++++++------- .../coreplugin/dialogs/settingsdialog.h | 6 + .../plugins/coreplugin/workspacesettings.cpp | 4 +- .../ipconnection/ipconnectionoptionspage.h | 2 +- .../plugins/notify/notifypluginoptionspage.h | 2 +- .../serialpluginoptionspage.h | 2 +- 11 files changed, 207 insertions(+), 137 deletions(-) diff --git a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_de.ts b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_de.ts index 554a8c5c7..1e431f98f 100644 --- a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_de.ts +++ b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_de.ts @@ -2146,7 +2146,7 @@ p, li { white-space: pre-wrap; } - Notify Plugin + Notification diff --git a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_es.ts b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_es.ts index 32554073c..183101e99 100644 --- a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_es.ts +++ b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_es.ts @@ -2147,7 +2147,7 @@ p, li { white-space: pre-wrap; } - Notify Plugin + Notification diff --git a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_fr.ts b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_fr.ts index 529fd4f7a..7463d76bf 100644 --- a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_fr.ts +++ b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_fr.ts @@ -2175,8 +2175,8 @@ p, li { white-space: pre-wrap; } - Notify Plugin - Plugin de Notification + Notification + Notification diff --git a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_ru.ts b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_ru.ts index 611533c3e..e26c74211 100644 --- a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_ru.ts +++ b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_ru.ts @@ -2256,7 +2256,7 @@ p, li { white-space: pre-wrap; } - Notify Plugin + Notification Оповещения diff --git a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_zh_CN.ts b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_zh_CN.ts index a27bc2920..4d92f3c34 100644 --- a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_zh_CN.ts +++ b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_zh_CN.ts @@ -3189,7 +3189,7 @@ p, li { white-space: pre-wrap; } - Notify Plugin + Notification diff --git a/ground/openpilotgcs/src/plugins/coreplugin/dialogs/settingsdialog.cpp b/ground/openpilotgcs/src/plugins/coreplugin/dialogs/settingsdialog.cpp index fd772b0bb..d5581ff75 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/dialogs/settingsdialog.cpp +++ b/ground/openpilotgcs/src/plugins/coreplugin/dialogs/settingsdialog.cpp @@ -32,7 +32,6 @@ #include "icore.h" #include "coreplugin/uavgadgetinstancemanager.h" #include "coreplugin/uavgadgetoptionspagedecorator.h" -// #include "coreimpl.h" #include #include @@ -40,49 +39,58 @@ #include #include +using namespace Core; +using namespace Core::Internal; + namespace { -struct PageData { - int index; - QString category; - QString id; -}; + + struct PageData { + int index; + QString category; + QString id; + + }; + + // helper to sort by translated category and name + bool compareOptionsPageByCategoryAndNameTr(const IOptionsPage *p1, const IOptionsPage *p2) + { + const UAVGadgetOptionsPageDecorator *gp1 = qobject_cast(p1); + const UAVGadgetOptionsPageDecorator *gp2 = qobject_cast(p2); + if (gp1 && !gp2) { + return false; + } + if (gp2 && !gp1) { + return true; + } + if (const int cc = QString::localeAwareCompare(p1->trCategory(), p2->trCategory())) { + return cc < 0; + } + return QString::localeAwareCompare(p1->trName(), p2->trName()) < 0; + } + + // helper to sort by category and id + bool compareOptionsPageByCategoryAndId(const IOptionsPage *p1, const IOptionsPage *p2) + { + const UAVGadgetOptionsPageDecorator *gp1 = qobject_cast(p1); + const UAVGadgetOptionsPageDecorator *gp2 = qobject_cast(p2); + if (gp1 && !gp2) { + return false; + } + if (gp2 && !gp1) { + return true; + } + if (const int cc = QString::localeAwareCompare(p1->category(), p2->category())) { + return cc < 0; + } + return QString::localeAwareCompare(p1->id(), p2->id()) < 0; + } + } Q_DECLARE_METATYPE(::PageData) -using namespace Core; -using namespace Core::Internal; - -// Helpers to sort by category. id -bool optionsPageLessThan(const IOptionsPage *p1, const IOptionsPage *p2) -{ - const UAVGadgetOptionsPageDecorator *gp1 = qobject_cast(p1); - const UAVGadgetOptionsPageDecorator *gp2 = qobject_cast(p2); - - if (gp1 && (gp2 == NULL)) { - return false; - } - - if (gp2 && (gp1 == NULL)) { - return true; - } - - if (const int cc = QString::localeAwareCompare(p1->trCategory(), p2->trCategory())) { - return cc < 0; - } - - return QString::localeAwareCompare(p1->trName(), p2->trName()) < 0; -} - -static inline QList sortedOptionsPages() -{ - QList rc = ExtensionSystem::PluginManager::instance()->getObjects(); - qStableSort(rc.begin(), rc.end(), optionsPageLessThan); - return rc; -} - -SettingsDialog::SettingsDialog(QWidget *parent, const QString &categoryId, const QString &pageId) - : QDialog(parent), m_applied(false) +SettingsDialog::SettingsDialog(QWidget *parent, const QString &categoryId, const QString &pageId) : + QDialog(parent), m_applied(false) { setupUi(this); #ifdef Q_OS_MAC @@ -92,6 +100,7 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &categoryId, const #endif QSettings *settings = ICore::instance()->settings(); + settings->beginGroup("General"); // restore last displayed category and page @@ -104,6 +113,7 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &categoryId, const initialPage = settings->value("LastPreferencePage", QVariant(QString())).toString(); qDebug() << "SettingsDialog settings initial category:" << initialCategory << ", initial page: " << initialPage; } + // restore window size int windowWidth = settings->value("SettingsWindowWidth", 0).toInt(); int windowHeight = settings->value("SettingsWindowHeight", 0).toInt(); @@ -111,114 +121,99 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &categoryId, const if (windowWidth > 0 && windowHeight > 0) { resize(windowWidth, windowHeight); } + + // restore splitter size + int size0 = settings->value("SettingsSplitterSize0", 0).toInt(); + int size1 = settings->value("SettingsSplitterSize1", 0).toInt(); + qDebug() << "SettingsDialog splitter size0:" << size0 << ", size1:" << size1; + QList sizes; + if (size0 > 0 && size1 > 0) { + sizes << size0 << size1; + } + else { + sizes << 150 << 300; + } + splitter->setSizes(sizes); + settings->endGroup(); + // all extra space must go to the option page and none to the tree + splitter->setStretchFactor(splitter->indexOf(pageTree), 0); + splitter->setStretchFactor(splitter->indexOf(layoutWidget), 1); + buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(apply())); m_instanceManager = Core::ICore::instance()->uavGadgetInstanceManager(); - connect(this, SIGNAL(settingsDialogShown(Core::Internal::SettingsDialog *)), m_instanceManager, SLOT(settingsDialogShown(Core::Internal::SettingsDialog *))); + connect(this, SIGNAL(settingsDialogShown(Core::Internal::SettingsDialog *)), m_instanceManager, + SLOT(settingsDialogShown(Core::Internal::SettingsDialog *))); connect(this, SIGNAL(settingsDialogRemoved()), m_instanceManager, SLOT(settingsDialogRemoved())); - connect(this, SIGNAL(categoryItemSelected()), this, SLOT(categoryItemSelectedShowChildInstead()), Qt::QueuedConnection); + connect(this, SIGNAL(categoryItemSelected()), this, SLOT(categoryItemSelectedShowChildInstead()), + Qt::QueuedConnection); splitter->setCollapsible(0, false); splitter->setCollapsible(1, false); pageTree->header()->setVisible(false); -// pageTree->setIconSize(QSize(24, 24)); - connect(pageTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), - this, SLOT(pageSelected())); + connect(pageTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this, SLOT(pageSelected())); - QMap categories; + QList pluginPages; + QList gadgetPages; - QList pages = sortedOptionsPages(); + // get all pages and split them between plugin and gadget list + QList pages = ExtensionSystem::PluginManager::instance()->getObjects(); + foreach(IOptionsPage *page, pages) { + if (qobject_cast(page)) { + gadgetPages.append(page); + } else { + pluginPages.append(page); + } + } - int index = 0; - bool firstUavGadgetOptionsPageFound = false; + // the plugin options page list sorted by untranslated names to facilitate access to the language settings when GCS + // is not running in a language understood by the user. + qStableSort(pluginPages.begin(), pluginPages.end(), compareOptionsPageByCategoryAndId); + // the plugin options page list sorted is sorted by translated names + qStableSort(gadgetPages.begin(), gadgetPages.end(), compareOptionsPageByCategoryAndNameTr); + + // will hold the initially selected item if any QTreeWidgetItem *initialItem = 0; - foreach(IOptionsPage * page, pages) { - PageData pageData; - pageData.index = index; - pageData.category = page->category(); - pageData.id = page->id(); - - QTreeWidgetItem *item = new QTreeWidgetItem; - item->setText(0, page->trName()); - item->setData(0, Qt::UserRole, qVariantFromValue(pageData)); - - QString trCategories = page->trCategory(); - QString currentCategory = page->category(); - - QTreeWidgetItem *categoryItem; - if (!categories.contains(currentCategory)) { - // Above the first gadget option we insert a separator - if (!firstUavGadgetOptionsPageFound) { - UAVGadgetOptionsPageDecorator *pd = qobject_cast(page); - if (pd) { - firstUavGadgetOptionsPageFound = true; - QTreeWidgetItem *separator = new QTreeWidgetItem(pageTree); - separator->setFlags(separator->flags() & ~Qt::ItemIsSelectable & ~Qt::ItemIsEnabled); - separator->setText(0, QString(30, 0xB7)); - } - } - categoryItem = new QTreeWidgetItem(pageTree); - categoryItem->setIcon(0, page->icon()); - categoryItem->setText(0, trCategories); - categoryItem->setData(0, Qt::UserRole, qVariantFromValue(pageData)); - categories.insert(currentCategory, categoryItem); - } - - QList *categoryItemList = m_categoryItemsMap.value(currentCategory); - if (!categoryItemList) { - categoryItemList = new QList(); - m_categoryItemsMap.insert(currentCategory, categoryItemList); - } - categoryItemList->append(item); - - m_pages.append(page); - - // creating all option pages upfront is slow, so we create place holder widgets instead - // the real option page widget will be created later when the user selects it - // the place holder is a QLabel and we assume that no option page will be a QLabel... - QLabel *placeholderWidget = new QLabel(stackedPages); - stackedPages->addWidget(placeholderWidget); - - if (page->id() == initialPage && currentCategory == initialCategory) { + // add plugin pages + foreach(IOptionsPage *page, pluginPages) { + QTreeWidgetItem *item = addPage(page); + // to automatically expand all plugin categories, uncomment next line + //item->parent()->setExpanded(true); + if (page->id() == initialPage && page->category() == initialCategory) { initialItem = item; } - - index++; } - foreach(QString category, m_categoryItemsMap.keys()) { - QList *categoryItemList = m_categoryItemsMap.value(category); - if (categoryItemList->size() > 1) { - foreach(QTreeWidgetItem * item, *categoryItemList) { - QTreeWidgetItem *categoryItem = categories.value(category); + // insert separator bewteen plugin and gadget pages + QTreeWidgetItem *separator = new QTreeWidgetItem(pageTree); + separator->setFlags(separator->flags() & ~Qt::ItemIsSelectable & ~Qt::ItemIsEnabled); + separator->setText(0, QString(30, 0xB7)); - categoryItem->addChild(item); - } + // add gadget pages + foreach(IOptionsPage *page, gadgetPages) { + QTreeWidgetItem *item = addPage(page); + if (page->id() == initialPage && page->category() == initialCategory) { + initialItem = item; } } + // handle initially selected item if (initialItem) { - if (!initialItem->parent()) { - // item has no parent, meaning it is single child - // so select category item instead as single child are not added to the tree - initialItem = categories.value(initialCategory); + if (initialItem->isHidden()) { + // item is hidden, meaning it is single child + // so select parent category item instead + initialItem = initialItem->parent(); } pageTree->setCurrentItem(initialItem); } - QList sizes; - sizes << 150 << 300; - splitter->setSizes(sizes); - - splitter->setStretchFactor(splitter->indexOf(pageTree), 0); - splitter->setStretchFactor(splitter->indexOf(layoutWidget), 1); } SettingsDialog::~SettingsDialog() @@ -236,6 +231,64 @@ SettingsDialog::~SettingsDialog() } } +QTreeWidgetItem *SettingsDialog::addPage(IOptionsPage *page) { + PageData pageData; + pageData.index = m_pages.count(); + pageData.category = page->category(); + pageData.id = page->id(); + + QString category = page->category(); + + QList *categoryItemList = m_categoryItemsMap.value(category); + if (!categoryItemList) { + categoryItemList = new QList(); + m_categoryItemsMap.insert(category, categoryItemList); + } + + QTreeWidgetItem *categoryItem = NULL; + for (int i = 0; i < pageTree->topLevelItemCount(); ++i) { + QTreeWidgetItem *tw = pageTree->topLevelItem(i); + PageData data = tw->data(0, Qt::UserRole).value(); + if (data.category == page->category()) { + categoryItem = tw; + break; + } + } + if (!categoryItem) { + categoryItem = new QTreeWidgetItem(pageTree); + categoryItem->setIcon(0, page->icon()); + categoryItem->setText(0, page->trCategory()); + categoryItem->setData(0, Qt::UserRole, qVariantFromValue(pageData)); + } + + QTreeWidgetItem *item = new QTreeWidgetItem(categoryItem); + item->setText(0, page->trName()); + item->setData(0, Qt::UserRole, qVariantFromValue(pageData)); + + switch (categoryItemList->size()) { + case 0: + item->setHidden(true); + break; + case 1: + categoryItemList->at(0)->setHidden(false); + break; + default: + break; + } + + categoryItemList->append(item); + + m_pages.append(page); + + // creating all option pages upfront is slow, so we create place holder widgets instead + // the real option page widget will be created later when the user selects it + // the place holder is a QLabel and we assume that no option page will be a QLabel... + QLabel *placeholderWidget = new QLabel(stackedPages); + stackedPages->addWidget(placeholderWidget); + + return item; +} + void SettingsDialog::pageSelected() { QTreeWidgetItem *item = pageTree->currentItem(); @@ -281,15 +334,18 @@ void SettingsDialog::deletePage() QString category = data.category; QList *categoryItemList = m_categoryItemsMap.value(category); - QTreeWidgetItem *parentItem = item->parent(); - parentItem->removeChild(item); - categoryItemList->removeOne(item); - if (parentItem->childCount() == 1) { - parentItem->removeChild(parentItem->child(0)); + if (categoryItemList) { + categoryItemList->removeOne(item); + QTreeWidgetItem *parentItem = item->parent(); + parentItem->removeChild(item); + if (parentItem->childCount() == 1) { + parentItem->child(0)->setHidden(true); + } } pageSelected(); } +// TODO duplicates a lot of the addPage code... void SettingsDialog::insertPage(IOptionsPage *page) { PageData pageData; @@ -314,9 +370,9 @@ void SettingsDialog::insertPage(IOptionsPage *page) // If this category has no child right now // we need to add the "default child" QList *categoryItemList = m_categoryItemsMap.value(page->category()); - if (categoryItem->childCount() == 0) { + if (categoryItem->childCount() == 1) { QTreeWidgetItem *defaultItem = categoryItemList->at(0); - categoryItem->addChild(defaultItem); + defaultItem->setHidden(false); } QTreeWidgetItem *item = new QTreeWidgetItem; @@ -396,10 +452,18 @@ bool SettingsDialog::execDialog() void SettingsDialog::done(int val) { QSettings *settings = ICore::instance()->settings(); + settings->beginGroup("General"); + + settings->setValue("LastPreferenceCategory", m_currentCategory); + settings->setValue("LastPreferencePage", m_currentPage); + settings->setValue("SettingsWindowWidth", this->width()); + settings->setValue("SettingsWindowHeight", this->height()); + QList sizes = splitter->sizes(); + qDebug() << "SettingsDialog splitter saving size0:" << sizes[0] << ", size1:" << sizes[1]; + settings->setValue("SettingsSplitterSize0", sizes[0]); + settings->setValue("SettingsSplitterSize1", sizes[1]); + + settings->endGroup(); - settings->setValue("General/LastPreferenceCategory", m_currentCategory); - settings->setValue("General/LastPreferencePage", m_currentPage); - settings->setValue("General/SettingsWindowWidth", this->width()); - settings->setValue("General/SettingsWindowHeight", this->height()); QDialog::done(val); } diff --git a/ground/openpilotgcs/src/plugins/coreplugin/dialogs/settingsdialog.h b/ground/openpilotgcs/src/plugins/coreplugin/dialogs/settingsdialog.h index ade61b525..7333844a4 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/dialogs/settingsdialog.h +++ b/ground/openpilotgcs/src/plugins/coreplugin/dialogs/settingsdialog.h @@ -36,9 +36,11 @@ #include "coreplugin/dialogs/ioptionspage.h" namespace Core { + class UAVGadgetInstanceManager; namespace Internal { + class SettingsDialog : public QDialog, public::Ui::SettingsDialog { Q_OBJECT @@ -75,8 +77,12 @@ private: bool m_applied; QString m_currentCategory; QString m_currentPage; + + QTreeWidgetItem *addPage(IOptionsPage *page); }; + } // namespace Internal + } // namespace Core #endif // SETTINGSDIALOG_H diff --git a/ground/openpilotgcs/src/plugins/coreplugin/workspacesettings.cpp b/ground/openpilotgcs/src/plugins/coreplugin/workspacesettings.cpp index 62279fd1a..43d552f44 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/workspacesettings.cpp +++ b/ground/openpilotgcs/src/plugins/coreplugin/workspacesettings.cpp @@ -60,12 +60,12 @@ QString WorkspaceSettings::trName() const QString WorkspaceSettings::category() const { - return QLatin1String("GCS"); + return QLatin1String("Environment"); } QString WorkspaceSettings::trCategory() const { - return tr("GCS"); + return tr("Environment"); } QWidget *WorkspaceSettings::createPage(QWidget *parent) diff --git a/ground/openpilotgcs/src/plugins/ipconnection/ipconnectionoptionspage.h b/ground/openpilotgcs/src/plugins/ipconnection/ipconnectionoptionspage.h index d0110339c..b00c585f4 100644 --- a/ground/openpilotgcs/src/plugins/ipconnection/ipconnectionoptionspage.h +++ b/ground/openpilotgcs/src/plugins/ipconnection/ipconnectionoptionspage.h @@ -58,7 +58,7 @@ public: } QString category() const { - return "IP Network Telemetry"; + return "Telemetry - IP Network"; }; QString trCategory() const { diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h index adeadde9a..9c39639e5 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h @@ -76,7 +76,7 @@ public: } QString trCategory() const { - return tr("Notify Plugin"); + return tr("Notification"); } QWidget *createPage(QWidget *parent); diff --git a/ground/openpilotgcs/src/plugins/serialconnection/serialpluginoptionspage.h b/ground/openpilotgcs/src/plugins/serialconnection/serialpluginoptionspage.h index 1a0475f48..28e6b94b3 100644 --- a/ground/openpilotgcs/src/plugins/serialconnection/serialpluginoptionspage.h +++ b/ground/openpilotgcs/src/plugins/serialconnection/serialpluginoptionspage.h @@ -62,7 +62,7 @@ public: } QString category() const { - return "Serial Telemetry"; + return "Telemetry - Serial"; } QString trCategory() const { From 0faa77b3fb009a2164e1ecae270d64f1010f1120 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Tue, 28 May 2013 16:57:03 +0200 Subject: [PATCH 067/120] Uncrustify sources --- .../openpilotgcs/src/plugins/opmap/opmapgadgetwidget.cpp | 9 ++++----- .../uavsettingsimportexportfactory.cpp | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/opmap/opmapgadgetwidget.cpp b/ground/openpilotgcs/src/plugins/opmap/opmapgadgetwidget.cpp index 267cd2ec5..75cd66c73 100644 --- a/ground/openpilotgcs/src/plugins/opmap/opmapgadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/opmap/opmapgadgetwidget.cpp @@ -2173,7 +2173,7 @@ bool OPMapGadgetWidget::getUAVPosition(double &latitude, double &longitude, doub PositionActual *positionActual = PositionActual::GetInstance(obm); Q_ASSERT(positionActual != NULL); PositionActual::DataFields positionActualData = positionActual->getData(); - if(positionActualData.North == 0 && positionActualData.East == 0 && positionActualData.Down == 0){ + if (positionActualData.North == 0 && positionActualData.East == 0 && positionActualData.Down == 0) { GPSPosition *gpsPositionObj = GPSPosition::GetInstance(obm); Q_ASSERT(gpsPositionObj); @@ -2191,10 +2191,9 @@ bool OPMapGadgetWidget::getUAVPosition(double &latitude, double &longitude, doub homeLLA[1] = homeLocationData.Longitude / 1.0e7; homeLLA[2] = homeLocationData.Altitude; - - NED[0] = positionActualData.North; - NED[1] = positionActualData.East; - NED[2] = positionActualData.Down; + NED[0] = positionActualData.North; + NED[1] = positionActualData.East; + NED[2] = positionActualData.Down; Utils::CoordinateConversions().NED2LLA_HomeLLA(homeLLA, NED, LLA); diff --git a/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexportfactory.cpp b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexportfactory.cpp index d5b1c7e9a..10fcc70cd 100644 --- a/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexportfactory.cpp +++ b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexportfactory.cpp @@ -241,7 +241,7 @@ QString UAVSettingsImportExportFactory::createXMLDocument(const enum storedData versionInfo.appendChild(hw); QDomElement fw = doc.createElement("firmware"); - QString uavo = board.uavoHash.toHex(); + QString uavo = board.uavoHash.toHex(); fw.setAttribute("tag", board.gitTag); fw.setAttribute("date", board.gitDate); fw.setAttribute("hash", board.gitHash); From cb494777cbc7e01758291f985478a50c254f01c0 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Tue, 28 May 2013 20:58:07 +0300 Subject: [PATCH 068/120] Makefile: remove unused target (gcs_all_clean) --- Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 72ad97ffe..32cdb2da3 100644 --- a/Makefile +++ b/Makefile @@ -440,7 +440,7 @@ sim_osx_%: uavobjects_flight all_ground: openpilotgcs # Convenience target for the GCS -.PHONY: gcs gcs_clean gcs_all_clean +.PHONY: gcs gcs_clean gcs: openpilotgcs gcs_clean: openpilotgcs_clean @@ -946,7 +946,6 @@ help: @$(ECHO) " gcs - Build the Ground Control System (GCS) application (debug|release)" @$(ECHO) " gcs_clean - Remove the Ground Control System (GCS) application (debug|release)" @$(ECHO) " Supported build configurations: GCS_BUILD_CONF=debug|release (default is $(GCS_BUILD_CONF))" - @$(ECHO) " gcs_all_clean - Remove the Ground Control System (GCS) application (all build confgurations)" @$(ECHO) @$(ECHO) " [AndroidGCS]" @$(ECHO) " androidgcs - Build the Android Ground Control System (GCS) application" From 74cc1315b4bc826f3012b38fe10684d5a2c272fe Mon Sep 17 00:00:00 2001 From: Mathieu Rondonneau Date: Tue, 28 May 2013 12:59:46 -0700 Subject: [PATCH 069/120] OP-958: only report the number of device we actually open successfully. Limitation: only one (1) or zero (0) for now. --- ground/openpilotgcs/src/plugins/ophid/src/ophid_hidapi.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ground/openpilotgcs/src/plugins/ophid/src/ophid_hidapi.cpp b/ground/openpilotgcs/src/plugins/ophid/src/ophid_hidapi.cpp index 69007d804..c03cb0ba3 100644 --- a/ground/openpilotgcs/src/plugins/ophid/src/ophid_hidapi.cpp +++ b/ground/openpilotgcs/src/plugins/ophid/src/ophid_hidapi.cpp @@ -171,6 +171,8 @@ int opHID_hidapi::open(int max, int vid, int pid, int usage_page, int usage) if (devices_found) { + devices_found = 0; + // Go through the list until we can open one // WARNING: for now this prevent to have device chained tmp_device_ptr = current_device_ptr; @@ -186,7 +188,10 @@ int opHID_hidapi::open(int max, int vid, int pid, int usage_page, int usage) NULL); if (handle) + { + devices_found = 1 ; break; + } tmp_device_ptr = tmp_device_ptr->next; } From 6a838417fb4e23be01119ae9b332dc8968afbe0d Mon Sep 17 00:00:00 2001 From: Mathieu Rondonneau Date: Tue, 28 May 2013 21:36:10 -0700 Subject: [PATCH 070/120] OP-958: WINDOWS HACK ONLY: This is to filter out gamepadcontroller HID device during reconnect. This is temporary until multiple HID are supported (if needed). --- ground/openpilotgcs/src/plugins/ophid/src/ophid_hidapi.cpp | 5 ++--- .../openpilotgcs/src/plugins/ophid/src/ophid_usbmon_win.cpp | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/ophid/src/ophid_hidapi.cpp b/ground/openpilotgcs/src/plugins/ophid/src/ophid_hidapi.cpp index c03cb0ba3..6edb883ee 100644 --- a/ground/openpilotgcs/src/plugins/ophid/src/ophid_hidapi.cpp +++ b/ground/openpilotgcs/src/plugins/ophid/src/ophid_hidapi.cpp @@ -187,9 +187,8 @@ int opHID_hidapi::open(int max, int vid, int pid, int usage_page, int usage) tmp_device_ptr->product_id, NULL); - if (handle) - { - devices_found = 1 ; + if (handle) { + devices_found = 1; break; } diff --git a/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_win.cpp b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_win.cpp index 5c3d90251..6c77a5464 100644 --- a/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_win.cpp +++ b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_win.cpp @@ -131,6 +131,7 @@ QList USBMonitor::availableDevices(int vid, int pid, int bcdDeviceM #define TCHARToQString(x) QString::fromLocal8Bit((x)) #define TCHARToQStringN(x, y) QString::fromLocal8Bit((x), (y)) #endif /*UNICODE*/ +#define HIDMATCHSTRING "COL01" void USBMonitor::setUpNotifications() { @@ -193,7 +194,7 @@ bool USBMonitor::matchAndDispatchChangedDevice(const QString & deviceID, const G DWORD nSize = 0; TCHAR buf[MAX_PATH]; if (SetupDiGetDeviceInstanceId(devInfo, &spDevInfoData, buf, MAX_PATH, &nSize) && - deviceID.contains(TCHARToQString(buf))) { // we found a match + deviceID.contains(TCHARToQString(buf)) && deviceID.contains(HIDMATCHSTRING)) { // we found a match USBPortInfo info; info.devicePath = deviceID; if (wParam == DBT_DEVICEARRIVAL) { From 4c3469531501d167f4dd1785ee3cd2d4fc79b69e Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Wed, 29 May 2013 12:05:35 +0300 Subject: [PATCH 071/120] Windows installer: better web site name --- package/winx86/openpilotgcs.nsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/winx86/openpilotgcs.nsi b/package/winx86/openpilotgcs.nsi index 7710585b8..0e6ff1fd1 100644 --- a/package/winx86/openpilotgcs.nsi +++ b/package/winx86/openpilotgcs.nsi @@ -268,7 +268,7 @@ Section ; create uninstall info WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "DisplayIcon" '"$INSTDIR\bin\openpilotgcs.exe"' WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "Publisher" "OpenPilot Team" WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "DisplayVersion" "Stumpy" - WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "URLInfoAbout" "http://openpilot.org" + WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "URLInfoAbout" "http://www.openpilot.org" WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "HelpLink" "http://wiki.openpilot.org" WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "EstimatedSize" 100600 WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "NoModify" 1 From afeeed6f65a56859c8058692201f371a4eefc356 Mon Sep 17 00:00:00 2001 From: Mathieu Rondonneau Date: Wed, 29 May 2013 05:57:46 -0700 Subject: [PATCH 072/120] OP-958: WINDOWS HACK: do not filter out the bl. --- .../openpilotgcs/src/plugins/ophid/src/ophid_usbmon_win.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_win.cpp b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_win.cpp index 6c77a5464..8d16e7099 100644 --- a/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_win.cpp +++ b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_win.cpp @@ -131,7 +131,8 @@ QList USBMonitor::availableDevices(int vid, int pid, int bcdDeviceM #define TCHARToQString(x) QString::fromLocal8Bit((x)) #define TCHARToQStringN(x, y) QString::fromLocal8Bit((x), (y)) #endif /*UNICODE*/ -#define HIDMATCHSTRING "COL01" +#define MATCHOPHIDSTRING "COL01" +#define MATCHOPBLSTRING "161A0549" void USBMonitor::setUpNotifications() { @@ -194,7 +195,8 @@ bool USBMonitor::matchAndDispatchChangedDevice(const QString & deviceID, const G DWORD nSize = 0; TCHAR buf[MAX_PATH]; if (SetupDiGetDeviceInstanceId(devInfo, &spDevInfoData, buf, MAX_PATH, &nSize) && - deviceID.contains(TCHARToQString(buf)) && deviceID.contains(HIDMATCHSTRING)) { // we found a match + deviceID.contains(TCHARToQString(buf)) && (deviceID.contains(MATCHOPHIDSTRING) || + deviceID.contains(MATCHOPBLSTRING))) { // we found a match USBPortInfo info; info.devicePath = deviceID; if (wParam == DBT_DEVICEARRIVAL) { From b5711b88355c8483a12a8535383d14eec0f2b8d4 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Wed, 29 May 2013 16:38:36 +0300 Subject: [PATCH 073/120] Change build-info.txt format from DOS to Unix It is used by Bamboo server shell scripts, and being CRLF terminated, this sometimes results in broken file names, for example, of Android package. --- make/.gitattributes | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/make/.gitattributes b/make/.gitattributes index f02d5b2be..5d3895071 100644 --- a/make/.gitattributes +++ b/make/.gitattributes @@ -7,5 +7,7 @@ *.sh text eol=lf /doxygen/* text eol=lf -/templates/*.txt text eol=crlf /uncrustify/*.cfg text eol=lf + +/templates/*.txt text eol=crlf +/templates/build-info.txt text eol=lf From 01309d50b58eb7cfc8403fd608ec97934e64ed54 Mon Sep 17 00:00:00 2001 From: David Ankers Date: Thu, 30 May 2013 06:26:47 +1000 Subject: [PATCH 074/120] Keep credits only in GCS, easier to maintain and more visable to users --- CREDITS.txt | 206 ---------------------------------------------------- 1 file changed, 206 deletions(-) delete mode 100644 CREDITS.txt diff --git a/CREDITS.txt b/CREDITS.txt deleted file mode 100644 index ac785d256..000000000 --- a/CREDITS.txt +++ /dev/null @@ -1,206 +0,0 @@ -This is a credits file of people that are or have been key contributors to the OpenPilot code base in this Git repository. -Without the work of the people in this file and many that are not who help the community, OpenPilot would not be what it is today. - -It is sorted alphabetically by name and formatted so that it allows for easy grepping and beautification by scripts. - -The fields are: - -Name (N) -Description of work (D) -Current maintainer function (M) - ----------- - -N: Connor Abbott -D: Win32 OpenPilot port - -N: David Ankers -D: Co-founder, Project Coordination -D: Minor GCS infrastructure, updating the credit file -M: Admin - -N: Sergiy Anikeyev -D: Improvments to Camera Gimbal control - -N: Pedro Assuncao -D: Initial GCS Settings Gadget work - -N: Fredrik Arvidsson -D: GCS Setup Wizard -M: GCS Setup Wizard - -N: Werner Backes -D: Port of CopterControl to PS3 Move Controller (MoveCopter) - -N: Jose Barros -D: Next-Gen OP Map Lib, Y-Modem Library, Uploader Plugin -D: OP Bootloader, AHRS Bootloader, OPUploadTool and much else -M: Bootloader, OP MAP Lib - -N: David "Buzz" Carlson -D: 3D ModelView GCS Plugin, sponsor of HITL merge work and XPlane addition - -N: James Cotton -D: Multiplatform HID implementation (firmware & GCS), GCS Joystick control -D: Posix OpenPilot work and Mac implementation -D: Firmware implementation of Professor Schinstock's INS/GPS -D: Android GCS and much else -M: Architecture co-lead, Android GCS Lead - -N: Steve Doll -D: Much Artwork, Logo rework, Welcome page design - -N: Piotr Esden-Tempski -D: Floss-JTAG Rev A, 4-layer initial design - -N: Richard Flay -D: Multiple fixes / Review guru - -N: Darren Furniss -D: GCS Artwork and Android GCS Artwork - -N: Frederic Goddeeris -D: I2C work and FreeRTOS work, MK integration -D: EagleTree OSD implementation - -N: Daniel Godin -D: Sponsor: Notify Plugin for the GCS - -N: Bani Greyling -D: GCS Scope plugin - -N: Nuno Guedes -D: 3D artwork, moving surfaces and work on ModelView -D: PFD Artwork - -N: Erik Gustavsson -D: Attitude LPF improvments to Self Level - -N: Peter Gunnarsson -D: GCS Core Developer -D: Multiple GCS plugins, Gadget foundations, UAVObject viewer - -N: Dean Hall -D: Creator of http://pythononachip.org - -N: Joe Hlebasko -D: Early versions of Main Board & Production OP GPS -M: Hardware Architecture Team - -N: Andy Honecker -D: Hardware design review and optimisation - -N: Mark James -D: Some of Silk Icon set used in GCS - http://www.famfamfam.com/lab/icons/silk - -N: Sami Korhonen -D: GPS Module, Spektrum RC Module, OSD work -M: OpenPilot OSD - -N: Thorsten Klose -D: Embedded STM32 infrastructure - -N: Hallvard Kristiansen -D: GCS Artwork, Quad layout diagrams - -N: Mike Labranche -D: Tab bar Telem Monitor - -N: Edouard Lafargue -D: GCS Dial Plugins, GCS PFD Plugin, GCS GPS plugin, GCS Config plugin -D: Artwork including standard display dials - -N: Matt Lipski -D: Deluxe Dials Set artwork, (Artificial Horizon, Compass, Turn Indicator) - -N: Les Newell -D: Advanced mixer matrix, SPI protocol based on UAVObjects, feedforward - -N: Ken Northup -D: 3D Modelling, Easystar adaption from FMS - -N: Guy McCaldin -D: Artwork and design including work on the Deluxe Dial Set - -N: Alessio Morale -D: Firmware/Architecture Lead - -N: Cathy Moss -D: Hardware design Lead: Gen 2 Mainboard, PipXtreme, Current Sensor -D: PipXtreme designer, creator OP Map Plugin - -N: Angus Peart -D: Co-founder, Principal hardware architect. -D: Hardware design of early OpenPilot, AHRS, GPS and other hardware - -N: Dmytro Poplavskiy -D: QML PFD, QML Welcome page -M: Qml plugins - -N: Eric Price -D: IL2 HITL GCS Plugin, Posix OpenPilot, Advanced stabilisation module -M: SITL Posix, SLAM work - -N: Richard Querin -D: Graphic Design, OpenPilot Logo - -N: Laurent Ribon -D: The GLC_lib as used in the ModelView Plugin -D: See: http://www.glc-lib.net/ - -N: Julien Rouviere -D: GCS Framework and Plugins for the GCS - -N: Zik Saleeba -D: Initial schematic based on Zik's Flying Fox schematic - -N: Professor Dale Schinstock -D: Lead INS Developer -D: Creator of the OpenPilot INS / EKF - -N: Professor Kenn Sebesta -D: Lead Fixed Wing Developer CC3D / Controls -D: GCS improvments including HiTL Merge -M: Fixed Wing support CC3D - -N: Oleg Semyonov -D: Core Developer & Project organisation -D: TxPID module -M: CameraStab module -M: Common part of multi-platform packaging system -M: Windows NSIS Installer - -N: Stacey Sheldon -D: Core Embedded Developer -D: SPI protocol for AHRS, I2C rewrite and much core work - -N: Troy Schultz -D: INS design review and optimisation - -N: Dr. Erhard Siegl -D: Configuration engine for the GCS - -N: Pete Stapley -D: PPM inputs - -N: Rowan Taubitz -D: Hardware debugging and testing, creation of 2-layer Floss-JTAG Rev B -D: Creation of Next-Gen FOSS-JTAG board - -N: Andrew Thoms -D: IP Telemtry plugin for the GCS -D: Helicopter support code and mixing for CCPM - -N: Vassilis Varveropoulos -D: Co-founder, Principal embedded software architect. -D: Module architecture and UAVTalk/UAVObjects implementation. - -N: Alex Vrubel -D: Russian translation of the GCS - -N: Brian Webb -D: Modem lead developer -M: OP Modems - -N: Dmitriy Zaitsev -D: AeroSim-RC HiTL plugin From d0b0cb77d4f35066e67ef0b5853048337375d2c7 Mon Sep 17 00:00:00 2001 From: Mathieu Rondonneau Date: Thu, 30 May 2013 19:08:22 -0700 Subject: [PATCH 075/120] OP-958: only enumerate openpilot devices in udev. (not sure the reason of not doing that) --- .../plugins/ophid/src/ophid_usbmon_linux.cpp | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_linux.cpp b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_linux.cpp index 9e6f3ef70..c57af06de 100644 --- a/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_linux.cpp +++ b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_linux.cpp @@ -65,14 +65,15 @@ void printPortInfo(struct udev_device *dev) */ void USBMonitor::deviceEventReceived() { - qDebug() << "Device event"; + OPHID_TRACE("IN"); struct udev_device *dev; dev = udev_monitor_receive_device(this->monitor); if (dev) { - printf("------- Got Device Event"); + //this->monitorNotifier->setEnabled(0); QString action = QString(udev_device_get_action(dev)); QString devtype = QString(udev_device_get_devtype(dev)); + qDebug() << "[DEBUG] Action: " << action << " device: " <monitorNotifier->setEnabled(1); } else { - printf("No Device from receive_device(). An error occured."); + OPHID_ERROR("No Device event from udev. Spurious event?."); } + OPHID_TRACE("OUT"); } @@ -120,12 +123,13 @@ USBMonitor::USBMonitor(QObject *parent) : QThread(parent) this->monitor = udev_monitor_new_from_netlink(this->context, "udev"); udev_monitor_filter_add_match_subsystem_devtype( this->monitor, "usb", NULL); + //udev_monitor_filter_add_match_tag(this->monitor, "openpilot"); udev_monitor_enable_receiving(this->monitor); this->monitorNotifier = new QSocketNotifier( udev_monitor_get_fd(this->monitor), QSocketNotifier::Read, this); connect(this->monitorNotifier, SIGNAL(activated(int)), this, SLOT(deviceEventReceived())); - qDebug() << "Starting the Udev client"; + OPHID_DEBUG("Starting the Udev client"); start(); // Start the thread event loop so that the socketnotifier works } @@ -139,7 +143,9 @@ USBMonitor::USBMonitor(QObject *parent) : QThread(parent) */ USBMonitor::~USBMonitor() { + OPHID_TRACE("IN"); quit(); + OPHID_TRACE("OUT"); } @@ -158,9 +164,12 @@ QList USBMonitor::availableDevices() struct udev_enumerate *enumerate; struct udev_device *dev; + OPHID_TRACE("IN"); + enumerate = udev_enumerate_new(this->context); udev_enumerate_add_match_subsystem(enumerate, "usb"); - // udev_enumerate_add_match_sysattr(enumerate, "idVendor", "20a0"); + //udev_enumerate_add_match_tag(enumerate, "openpilot"); + udev_enumerate_add_match_sysattr(enumerate, "idVendor", "20a0"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); // Will use the 'native' udev functions to loop: @@ -171,7 +180,9 @@ QList USBMonitor::availableDevices() and create a udev_device object (dev) representing it */ path = udev_list_entry_get_name(dev_list_entry); dev = udev_device_new_from_syspath(this->context, path); + OPHID_DEBUG("Found path: %s", path); if (QString(udev_device_get_devtype(dev)) == "usb_device") { + OPHID_DEBUG("Added path: %s", path); devicesList.append(makePortInfo(dev)); } udev_device_unref(dev); @@ -179,6 +190,7 @@ QList USBMonitor::availableDevices() // free the enumerator object udev_enumerate_unref(enumerate); + OPHID_TRACE("OUT"); return devicesList; } @@ -199,15 +211,21 @@ QList USBMonitor::availableDevices() */ QList USBMonitor::availableDevices(int vid, int pid, int bcdDeviceMSB, int bcdDeviceLSB) { + OPHID_TRACE("IN"); QList allPorts = availableDevices(); QList thePortsWeWant; foreach(USBPortInfo port, allPorts) { - if ((port.vendorID == vid || vid == -1) && (port.productID == pid || pid == -1) && ((port.bcdDevice >> 8) == bcdDeviceMSB || bcdDeviceMSB == -1) && + if ((port.vendorID == vid || vid == -1) && + (port.productID == pid || pid == -1) && + ((port.bcdDevice >> 8) == bcdDeviceMSB || bcdDeviceMSB == -1) && ((port.bcdDevice & 0x00ff) == bcdDeviceLSB || bcdDeviceLSB == -1)) { + OPHID_DEBUG("Append: 0x%X/0x%X/0x%X", port.vendorID, port.productID, port.bcdDevice); thePortsWeWant.append(port); } } + + OPHID_TRACE("OUT"); return thePortsWeWant; } @@ -226,10 +244,6 @@ USBPortInfo USBMonitor::makePortInfo(struct udev_device *dev) USBPortInfo prtInfo; bool ok; -#ifdef OPHID_DEBUG_INFO - printPortInfo(dev); -#endif - prtInfo.vendorID = QString(udev_device_get_sysattr_value(dev, "idVendor")).toInt(&ok, 16); prtInfo.productID = QString(udev_device_get_sysattr_value(dev, "idProduct")).toInt(&ok, 16); prtInfo.serialNumber = QString(udev_device_get_sysattr_value(dev, "serial")); From e81ef1dba41fa389247741816ce09ce3688b8632 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Fri, 31 May 2013 17:05:06 +0300 Subject: [PATCH 076/120] OP-910: reformat LICENSE.txt, no text changes --- LICENSE.txt | 72 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 8b960825e..eae509ca1 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,42 +1,64 @@ +The OpenPilot code is licensed under the GPLv3. There are a few minor exceptions to this so please see +the headers of all source code for copyright and license information. The full text of the GPLv3 can be +read here: http://www.gnu.org/licenses/gpl-3.0.txt -The OpenPilot code is licensed under the GPLv3, there are a few minor exceptions to this so please see the headers of all source code for copyright and license information. - -The full text of the GPLv3 can be read here: http://www.gnu.org/licenses/gpl-3.0.txt - -Artwork is licensed under the Creative Commons BY-SA v3 license. +Artwork is licensed under the Creative Commons BY-SA v3 license. Documentation including translations is also licensed under the Creative Commons BY-SA v3 license. - For details please see: http://creativecommons.org/licenses/by-sa/3.0/ -Licenses for the hardware files are included in the directories that contain the hardware, not all items are under the same license and you must check the files for each individual hardware design. +Licenses for the hardware files are included in the directories that contain the hardware, not all items +are under the same license and you must check the files for each individual hardware design. Please note +that some of the hardware files are licensed under the Creative Commons BY-NC-SA v3 license, this is a +non-commercial license. OpenPilot is purely a non-profit hobby project with zero commercial intent. If you +just want people to work for free or do your R&D for zero cost, please find a project that allows this as +that not what OpenPilot is about. We are hobbyists and we want to share our work with fellow hobbyists, +additionally we need to ensure the future of the project and make sure it is sustainable. -Please note that some of the hardware files are licensed under the Creative Commons BY-NC-SA v3 license, this is a Non-commercial license. OpenPilot is purely a non-profit hobby project with zero commercial intent, if you just want people to work for free or do your R&D for zero cost, please find a project that allows this as that not what OpenPilot is about. -We are hobbyists and we want to share our work with fellow hobbyists, additionally we need to ensure the future of the project and make sure it is sustainable. +If you wish to sell/distribute OpenPilot hardware or derivatives of OpenPilot hardware that are under a +non-commercial license, please get in touch with one of the members of OpenPilot Foundation's +administration committee. We can then negotiate a license waiver where a portion of the profits are donated +to the OpenPilot Project to ensure its survival and future progression. Please note that this is in +reference to PCB and Schematic designs. For people wishing to combine OpenPilot in to a Ready to Fly +solution, this is perfectly fine as long as OpenPilot PCBs are bought from the OpenPilot project or one +of the approved distributors. -If you wish to sell / distribute OpenPilot hardware or derivatives of OpenPilot hardware that are under a non-commercial license, please get in touch with one of the members of OpenPilot Foundation's administration committee. We can then negotiate a license waiver where a portion of the profits are donated to the OpenPilot Project to ensure its survival and future progression. Please note that this is in reference to PCB and Schematic designs, for people wishing to combine OpenPilot in to a Ready to Fly solution, this is perfectly fine as long as OpenPilot PCBs are bought from the OpenPilot project or one of the approved distributors. +For details the non-commercial license please see: http://creativecommons.org/licenses/by-nc-sa/3.0/ +A quick summary of what this license talk means, firstly using any work that is licensed under a form of +the Creative Commons BY license, requires that credit is to be given. The SA or Share Alike part of the +license means that you must also use the same license in any work derived from the work under this license. -For details the Non-Commercial license please see: http://creativecommons.org/licenses/by-nc-sa/3.0/ +Hardware +The items under the non-commercial license means exactly that: they are for non-commercial use only and +any derivatives that are made are also covered by the same non-commercial license. The hardware files +under a non-commercial license are for reference and for fellow hobbyists; they are not to be used to +generate profit of any kind. Please note that even the OpenPilot project its self is a non-profit project. -A quick summary of what this license talk means, firstly using any work that is licensed under a form of the Creative Commons BY license, requires that credit is to be given. - -The SA or Share Alike part of the license means that you must also use the same license in any work derived from the work under this license. - -Hardware -The items under the non-commercial license means exactly that: they are for non-commercial use only and any derivatives that are made are also covered by the same non-commercial license. The hardware files under a non-commercial license are for -reference and for fellow hobbyists; they are not to be used to generate profit of any kind. Please note that even the OpenPilot project its self is a non-profit project. - -For all items both non-commercial and items that allows commercial use, the OP logo must be placed on any work or derivative work and be clearly visible. If any web addresses are present on the hardware, these are also required to remain on any replications or any derivative work. +For all items both non-commercial and items that allows commercial use, the OP logo must be placed on any +work or derivative work and be clearly visible. If any web addresses are present on the hardware, these +are also required to remain on any replications or any derivative work. Documentation -In documentation, authors names must be kept along with any logos. If documentation is for a physical product such as a schematic, the OpenPilot logo should be shown and any web addresses also displayed on the final physical hardware it was derived from. +In documentation, authors names must be kept along with any logos. If documentation is for a physical +product such as a schematic, the OpenPilot logo should be shown and any web addresses also displayed on +the final physical hardware it was derived from. Artwork -If artwork is to be reused, the OpenPilot project should be credited. If for example this is a software application, credit should be given on the application splash screen or in a separate part of the application that is visible to users. For example the Help / About screen. +If artwork is to be reused, the OpenPilot project should be credited. If for example this is a software +application, credit should be given on the application splash screen or in a separate part of the +application that is visible to users. For example the Help/About screen. Contact Us -If you are unsure, please contact one of the OpenPilot Foundation's administrators. Additionally, if you plan to use parts of the OpenPilot project in your own work, we would appreciate it if you get in touch with us anyway, it is possible we could combine efforts or have some work already in progress that might be helpful. This of course is our baby and we want to see what great things people do with it as well. +If you are unsure, please contact one of the OpenPilot Foundation's administrators. Additionally, if you +plan to use parts of the OpenPilot project in your own work, we would appreciate it if you get in touch +with us anyway, it is possible we could combine efforts or have some work already in progress that might +be helpful. This of course is our baby and we want to see what great things people do with it as well. -A final note, OpenPilot is a non-profit for fun project and we have only volunteers. A great deal of time, money and effort has been donated to this project; please respect the people that are part of it and their generosity. OpenPilot is funded entirely by the generous people who donate money and time to the community and help it grow. Giving full and proper credit is not only a legal requirement of the CC-BY-SA license, it is also the right thing to do. +A final note, OpenPilot is a non-profit for fun project and we have only volunteers. A great deal of time, +money and effort has been donated to this project; please respect the people that are part of it and their +generosity. OpenPilot is funded entirely by the generous people who donate money and time to the community +and help it grow. Giving full and proper credit is not only a legal requirement of the CC-BY-SA license, +it is also the right thing to do. -Buying hardware from the OpenPilot project is very important to the survival and continuing progress of the project, a project like OpenPilot is extremely expensive to produce. +Buying hardware from the OpenPilot project is very important to the survival and continuing progress of +the project, a project like OpenPilot is extremely expensive to produce. From 88bf09abf3c2dce4e92d1fc9cd5dca69a1205b41 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Fri, 31 May 2013 17:26:51 +0300 Subject: [PATCH 077/120] OP-910: reformat and update MILESTONES.txt --- MILESTONES.txt | 64 +++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/MILESTONES.txt b/MILESTONES.txt index 0ea7d4c3d..95f7d5ee8 100644 --- a/MILESTONES.txt +++ b/MILESTONES.txt @@ -1,16 +1,18 @@ -This is the Milestones file of the OpenPilot project, its intent is to record the major accomplishments achieved by people using the OpenPilot platform and who gets the karma for performing them. +This is the Milestones file of the OpenPilot project, its intent is to record the major accomplishments +achieved by people using the OpenPilot platform and who gets the karma for performing them. +The Contributors list in the About dialog of the GCS application records the developers and contributors. +This file is different as it is aimed at recording and giving credit to the people who achieve milestones +in the use of OpenPilot. -The CREDITS.txt in SVN records the developers and the achievements made by each individual; this file is different as it is aimed at recording and giving credit to the people who achieve milestones in the use of OpenPilot. - +Notice: now we have the rule: no video - it has never happened. So please make sure you have video +recorded if you want to submit your milestone (listed below or not yet) to this list. The fields are: - -Milestone description (M) -Credited to (C) -Date (D) -Video (V) - Optional link to video showing milestone - + (M) Milestone description + (C) Credited to + (D) Date + (V) Link to video showing milestone M: OpenPilot driving EagleTree OSD C: Frederic Goddeeris @@ -147,7 +149,6 @@ C: Sergey Solodennikov (alconaft43) D: August 2011 V: http://www.youtube.com/watch?v=8SrfIS7OkB4 - M: First CopterControl Return to Base Fixed Wing C: Eric Price (Corvus Corax) D: August 2011 @@ -168,6 +169,11 @@ C: Kavin Gustafson (k_g) D: October 2012 V: http://www.youtube.com/watch?v=MGO68TqIwKk +M: First successful flight using just a mobile phone +C: Jose (please complete details), demoed in Portugal +D: +V: + M: First CopterControl over 10km FixedWing navigation flight C: D: @@ -178,17 +184,6 @@ C: D: V: -M: First successful flight using just a mobile phone -C: Jose (please complete details), demoed in Portugal -D: -V: - - -M: First Revo Altitude Hold using Sonar -C: -D: -V: - M: First CopterControl Navigation on RC Ground Vechicle C: D: @@ -199,17 +194,18 @@ C: D: V: + M: First Revo Navigated flight on a FixedWing C: It got done somewhere along the line, likely Corvus. +M: First Revo 5km Navigated flight on a FixedWing +C: Eric Price (Corvus Corax) +D: March 2012 +V: + M: First Revo Navigated flight on a MultiRotor C: It got done somewhere along the line, James or Sami -M: First Revo Navigated flight on a Heli -C: -D: -V: - M: First Revo 1km Navigated flight on a MultiRotor C: D: @@ -220,10 +216,10 @@ C: D: V: -M: First Revo 5km Navigated flight on a FixedWing -C: Eric Price (Corvus Corax) -D: March 2012 -V: +M: First Revo Navigated flight on a Heli +C: +D: +V: M: First Revo 1km Navigated flight on a Heli C: @@ -235,6 +231,11 @@ C: D: V: +M: First Revo Altitude Hold using Sonar +C: +D: +V: + M: First use of the Magic Waypoint feature C: D: @@ -251,7 +252,7 @@ D: V: M: First Auto landing on a MultiRotor using Revo -C: +C: Sami (please complete details) D: V: @@ -264,4 +265,3 @@ M: First Auto landing on a Heli using Revo C: D: V: - From 99983c852e7996741b08c8e92c80d1f5cba19c39 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Fri, 31 May 2013 17:32:20 +0300 Subject: [PATCH 078/120] OP-910: get rid of KNOWN_ISSUES.txt and move the info into HISTORY.txt --- HISTORY.txt | 29 ++++++++++++++++++++++++----- KNOWN_ISSUES.txt | 20 -------------------- 2 files changed, 24 insertions(+), 25 deletions(-) delete mode 100644 KNOWN_ISSUES.txt diff --git a/HISTORY.txt b/HISTORY.txt index 69c7b410e..7d13bdbb3 100644 --- a/HISTORY.txt +++ b/HISTORY.txt @@ -2,10 +2,9 @@ Short summary of changes. For a complete list see the git log. 2012-11-17 Advanced camera stabilization features. -They include optional manual control input filtering (moved from camera -stabilization to manual control input and now available also for main controls), -optional airframe attitude filtering used by camera stabilization, and optional -camera actuator feed forward to improve gimbal response. +They include optional manual control input filtering (moved from camera stabilization to manual +control input and now available also for main controls), optional airframe attitude filtering +used by camera stabilization, and optional camera actuator feed forward to improve gimbal response. --- RELEASE-12.10.2 --- Mayan Apocalypse Release --- @@ -16,6 +15,27 @@ OP-459, OP-545, OP-674, OP-679, OP-685, OP-686, OP-687, OP-690, OP-691, OP-702, OP-703, OP-714, OP-715, OP-716, OP-721, OP-728, OP-746, OP-748, OP-749, OP-750, OP-758, OP-759, OP-760 +Here is a list of some known unresolved issues. If an issue has JIRA ID [OP-XXX], +you may track it using the following URL: http://bugs.openpilot.org/browse/OP-XXX + ++ Only French translation is updated, use English for other locales or help with translations. ++ Radio Wizard confused by a reversed throttle, fix it on your transmitter before starting wizard. ++ Radio Wizard Throttle display does not show full range properly. ++ [Windows 8] USB Driver is broken. ++ Firmware Update Instructions on Firmware Tab not entirely accurate for all upgrade paths. ++ Tricopter's using Vehicle Wizard need to check servo does not need reversed manually. ++ XAircraft ESCs uses non-standard PPM range which may cause issues with Vehicle Wizard. ++ Spectrum Satellite Receivers setup in Radio Wizard may have wrong protocol set. ++ Old Intel 965 have an OpenGL bug that turns the QML PFD black and while. ++ [OP-732] Import UAV Settings for inactive modules crashes the running firmware (board restarts). + Workaround: update firmware, power cycle, enable modules, power cycle, import configuration. ++ [OP-747] Board infinitely reboots itself after firmware upgrade (settings erase firmware is a workaround). ++ [OP-723] GCS uses the system language ot the 1st run. After restart it uses English (can be changed later). ++ [OP-725] GCS camera stab config error message disappears too fast (but config error is cleared as it should) ++ [OP-767] GCS does not send AttitudeActual packets over serial port when GPS is connected and system is armed ++ [OP-768] GCS does not show UAV position on the map (master or next CC branches, but works in Revo branches) ++ [OP-769] Can't enter "12,45" on German system. Workaround: change GCS language (in fact, locale) to German. + 2012-11-12 Implemented smoothing filter for accelerometer data. Added support for Mode 3 and Mode 4 to the TX Configuration Wizard. @@ -202,4 +222,3 @@ selected from ManualControlSettings.InputMode and the aircraft must be rebooted after changing this. Also for CopterControl the HwSettings object must indicate which modules are connected to which ports. PPM currently not working. - diff --git a/KNOWN_ISSUES.txt b/KNOWN_ISSUES.txt deleted file mode 100644 index c9ac135f1..000000000 --- a/KNOWN_ISSUES.txt +++ /dev/null @@ -1,20 +0,0 @@ -Here is a list of some known unresolved issues. If an issue has JIRA ID [OP-XXX], you may track it using the -following URL: http://bugs.openpilot.org/browse/OP-XXX - -+ Only French translation is updated, use English for other locales or help with translations. -+ Radio Wizard confused by a reversed throttle, fix it on your transmitter before starting wizard. -+ Radio Wizard Throttle display does not show full range properly. -+ [Windows 8] USB Driver is broken. -+ Firmware Update Instructions on Firmware Tab not entirely accurate for all upgrade paths. -+ Tricopter's using Vehicle Wizard need to check servo does not need reversed manually. -+ XAircraft ESCs uses non-standard PPM range which may cause issues with Vehicle Wizard. -+ Spectrum Satellite Receivers setup in Radio Wizard may have wrong protocol set. -+ Old Intel 965 have an OpenGL bug that turns the QML PFD black and while. -+ [OP-732] Import UAV Settings for inactive modules crashes the running firmware (board restarts). - Workaround: update firmware, power cycle, enable modules, power cycle, import configuration. -+ [OP-747] Board infinitely reboots itself after firmware upgrade (settings erase firmware is a workaround). -+ [OP-723] GCS uses the system language ot the 1st run. After restart it uses English (can be changed later). -+ [OP-725] GCS camera stab config error message disappears too fast (but config error is cleared as it should) -+ [OP-767] GCS does not send AttitudeActual packets over serial port when GPS is connected and system is armed -+ [OP-768] GCS does not show UAV position on the map (master or next CC branches, but works in Revo branches) -+ [OP-769] Can't enter "12,45" on German system. Workaround: change GCS language (in fact, locale) to German. From 8f555da51be99e54fe55431c67396f4f34a6bf17 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Fri, 31 May 2013 17:42:04 +0300 Subject: [PATCH 079/120] OP-910: rename HISTORY.txt to WHATSNEW.txt --- HISTORY.txt => WHATSNEW.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename HISTORY.txt => WHATSNEW.txt (100%) diff --git a/HISTORY.txt b/WHATSNEW.txt similarity index 100% rename from HISTORY.txt rename to WHATSNEW.txt From 844b6c0acd7a7a8585fecd1358f594c48421df13 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sat, 1 Jun 2013 23:09:27 +0300 Subject: [PATCH 080/120] OP-910: add RELEASE-13.06 release notes --- WHATSNEW.txt | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 7d13bdbb3..7b884f12a 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,5 +1,124 @@ Short summary of changes. For a complete list see the git log. +--- RELEASE-13.06 --- Italian Stallion Release --- + +This is the first Revo software release which also supports CC, CC3D, OPLinkMini and unreleased +yet OP OSD boards. This is a major change: from different toolchains and build system to the whole +source code reformatting according to project style guidelines. The goal of this release is to +provide CC-style features for new Revo platform + radio using Revo's internal modem and external +OPLinkMini board. All advanced features like Altitude Hold, Position Hold, Guidance, Return to Home, +AutoLanding etc. are not released yet and planned for followin releases. + +Flight code changes: +- initial version of Revo code; +- initial version of OPLinkMini code; +- CopterControl/CC3D code reworked to reuse parts of Revo code; +- switched to new ARM-supported GCC 4.7 toolchain with hardware floating point support; +- major code cleanup and use of compiler warning flags to early catch errors; +- major directory and Makefiles reorganisation and cleanup; +- all source code fixed to use float variables instead of doubles (to use hardware FPU); +- added multi-binding support for OPLinkMini; +- added frequency hopping for Revo and OPLinkMini; +- replaced entire flash generation code; +- new U-Blox GPS binary protocol parser; +- added STM32 DSP library; +- updated STM32 CMSIS library; +- updated STM32 USB OTG driver; +- updated STM32 F1 StdPeriph driver library; +- updated STM32 F4 StdPeriph driver library; +- updated FreeRTOS (real-time operating system used by the flight code to run many tasks); +- PyMite moved to a library; +- fixed nasty bug in PyMite Makefile, single file was rebuilt 5 times fo no reason; +- added configurable accel/gyro rates; +- added visualisation of errors in bootloader updater; +- added numerous sanity checks to the flight code to prevent unsafe arming; +- new flash file system, much faster and higly optimised; +- Revo settings are now stored in embedded MCU flash freeing up external one for flight logs; +- OPLinkMini now stores settings in the MCU flash using FlashFS too; +- a catalog of known flash types is used to support different flash types by the same firmware; +- fixed broken overo submodule remote repository link; +- fixed DSMX protocol error with some Tx/Rx combintions; +- added new pios_*.h headers to support commonly used constants, functions and defines; +- numerous fixes for data alignment and memory allocation strategy; +- new bootloaders to support more features (for example, board settings erase); +- added new feature to erase settings without special firmware; +- removed CC/CC3D setting erase firmware (now not necessary due to new erase feature); +- introduced new delayed callback scheduler to run modules from a single task; +- many changes to AeroSim-RC simulator interface; +- fixed broken debug pins API; +- fixed few bugs in the EKF code; +- introduced bootloader updater for F4 boards (including Revo and OSD); +- some changes in RAM and flash memory partitioning to better utilize resources; +- changes in bootloader to allow remote reboot via serial port or radio modem; +- the EKF "Huge Formula" is replaced by optimised set of of loops to make it editable; +- Cyr's attitude patch is ported from CC3D to Revo; +- added magnetometer options (mags are disabled by default for Revo complimenary filter); +- advance camera stabilisation is now officially released; +- fixed numerous internal firmware bugs (too many to list here). + +GCS code changes: +- nice loading splash screen; +- now GCS uses system language by default if translation is available, English otherwise; +- French translation officially added. Please help with other languages; +- fixed some crashes of uploader gadget; +- fixed double config read on restore; +- improvements in GCS options dialog handling; +- optimised option dialog creating; +- added UI tooltips for many options; +- removed unused yet options from configuration UI; +- removed GCS config dialog on the first run, one default is used now if missing; +- added Revo configuration page, similar to CC/CC3D one; +- added OPLinkMini configuration page; +- hardware options are now dynamically enabled/disabled to allow supported configurations only; +- new artwork for all boards everywhere; +- optimised some 3D models; +- new About dialog showing version info and contrubutors list; +- fixed badly broken HiTL options dialog; +- fixed compilation problem on OSX, now GCS should be compatible with OSX 10.5+; +- major vehicle config cleanup with lazy creation (speeds up GCS start); +- UI config pages improvements (responsiveness, etc) +- new auto-update feature added, *.opfw firmware files removed from distributables; +- anti-aliased scope plugin; +- numerous code fixes and cleanups (too many to list here). + +Common parts: +- added simple toolchain install make targets; +- added self-hosted toolchains to ensure that they're always available; +- added support for globally istalled tools used by many working copies; +- added Windows bootstrap script to pull all other build tools; +- added unit testing framework, also supported by Bamboo CI server and agents; +- added code style formatting make targets, easy to use by developers; +- added doxygen make targets. The documentation still must be completely revised, though; +- enforced global line ending policy, source files are updated accordingly; +- reworked packaging to provide correct dependencies and safe multi-threaded builds; +- multiply renames of board names and directories, now we have correct names; +- fixed dependencies in Makefiles, now 'make -j' works reliably; +- CLEAN_BUILD make option is deprecated, use 'package' or 'clean_package' instead; +- simposix elf is now included into linux distribution and can be run with default GCS settings; +- revised 'make help' message; + +Android GCS: +- not officially released yet; +- full rewrite has been started; + +Infrastructure: +- Bamboo continuous integration server is actively used; +- around 10 build agents running 4 different operating systems are set up; +- every push to any branch is now build-tested, and unit tests run are performed; + +Due to major rework of all code and integration of Revo code into mainline (next) it is almost +impossible to list all corresponding JIRA issues for the list above. Some of them can be found +using this link: + +http://progress.openpilot.org/issues/?filter=10860 + +OP-678, OP-693, OP-719, OP-747, OP-761, OP-769, OP-770, OP-772, OP-792, OP-807, OP-812, OP-816, +OP-817, OP-820, OP-821, OP-843, OP-846, OP-854, OP-855, OP-856, OP-864, OP-867, OP-871, OP-873, +OP-874, OP-875, OP-879, OP-885, OP-886, OP-888, OP-889, OP-890, OP-891, OP-892, OP-893, OP-894, +OP-895, OP-896, OP-897, OP-898, OP-899, OP-900, OP-903, OP-905, OP-906, OP-907, OP-910, OP-912, +OP-917, OP-920, OP-925, OP-926, OP-928, OP-935, OP-936, OP-939, OP-952, OP-955, OP-957, OP-968, +OP-969, OP-970, OP-977, OP-980 + 2012-11-17 Advanced camera stabilization features. They include optional manual control input filtering (moved from camera stabilization to manual From 1c04bcae36e1c90a7907c503b06500266d080338 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sat, 1 Jun 2013 23:26:43 +0300 Subject: [PATCH 081/120] OP-910: update Windows installer --- package/winx86/openpilotgcs.nsi | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/package/winx86/openpilotgcs.nsi b/package/winx86/openpilotgcs.nsi index 0e6ff1fd1..47e8b07b9 100644 --- a/package/winx86/openpilotgcs.nsi +++ b/package/winx86/openpilotgcs.nsi @@ -116,7 +116,7 @@ ;-------------------------------- ; Settings for MUI_PAGE_FINISH !define MUI_FINISHPAGE_RUN - !define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\HISTORY.txt" + !define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\WHATSNEW.txt" !define MUI_FINISHPAGE_RUN_FUNCTION "RunApplication" ;-------------------------------- @@ -158,7 +158,10 @@ Section "Core files" InSecCore SetOutPath "$INSTDIR\bin" File /r "${GCS_BUILD_TREE}\bin\*" SetOutPath "$INSTDIR" - File "${PROJECT_ROOT}\HISTORY.txt" + File "${PROJECT_ROOT}\LICENSE.txt" + File "${PROJECT_ROOT}\README.txt" + File "${PROJECT_ROOT}\WHATSNEW.txt" + File "${PROJECT_ROOT}\MILESTONES.txt" SectionEnd ; Copy GCS plugins @@ -245,7 +248,13 @@ Section "Shortcuts" InSecShortcuts "" "$INSTDIR\bin\openpilotgcs.exe" 0 "" "" "${PRODUCT_NAME} ${PRODUCT_VERSION}. ${BUILD_DESCRIPTION}" CreateShortCut "$SMPROGRAMS\OpenPilot\OpenPilot GCS (clean configuration).lnk" "$INSTDIR\bin\openpilotgcs.exe" \ "-clean-config" "$INSTDIR\bin\openpilotgcs.exe" 0 "" "" "${PRODUCT_NAME} ${PRODUCT_VERSION}. ${BUILD_DESCRIPTION}" - CreateShortCut "$SMPROGRAMS\OpenPilot\OpenPilot ChangeLog.lnk" "$INSTDIR\HISTORY.txt" \ + CreateShortCut "$SMPROGRAMS\OpenPilot\OpenPilot License.lnk" "$INSTDIR\LICENSE.txt" \ + "" "$INSTDIR\bin\openpilotgcs.exe" 0 + CreateShortCut "$SMPROGRAMS\OpenPilot\OpenPilot ReadMe.lnk" "$INSTDIR\README.txt" \ + "" "$INSTDIR\bin\openpilotgcs.exe" 0 + CreateShortCut "$SMPROGRAMS\OpenPilot\OpenPilot ReleaseNotes.lnk" "$INSTDIR\WHATSNEW.txt" \ + "" "$INSTDIR\bin\openpilotgcs.exe" 0 + CreateShortCut "$SMPROGRAMS\OpenPilot\OpenPilot Milestones.lnk" "$INSTDIR\MILESTONES.txt" \ "" "$INSTDIR\bin\openpilotgcs.exe" 0 CreateShortCut "$SMPROGRAMS\OpenPilot\OpenPilot Website.lnk" "http://www.openpilot.org" \ "" "$INSTDIR\bin\openpilotgcs.exe" 0 @@ -267,7 +276,7 @@ Section ; create uninstall info WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "UninstallString" '"$INSTDIR\Uninstall.exe"' WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "DisplayIcon" '"$INSTDIR\bin\openpilotgcs.exe"' WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "Publisher" "OpenPilot Team" - WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "DisplayVersion" "Stumpy" + WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "DisplayVersion" "Fatty Patty" WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "URLInfoAbout" "http://www.openpilot.org" WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "HelpLink" "http://wiki.openpilot.org" WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "EstimatedSize" 100600 @@ -317,7 +326,7 @@ Section "un.OpenPilot GCS" UnSecProgram RMDir /r /rebootok "$INSTDIR\utilities" RMDir /r /rebootok "$INSTDIR\drivers" RMDir /r /rebootok "$INSTDIR\misc" - Delete /rebootok "$INSTDIR\HISTORY.txt" + Delete /rebootok "$INSTDIR\*.txt" Delete /rebootok "$INSTDIR\Uninstall.exe" ; Remove directory From 166baaeaf2222d1c1120cec06af9db9c58f70b71 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sat, 1 Jun 2013 23:39:40 +0300 Subject: [PATCH 082/120] OP-910: fix Mac package script --- package/osx/package | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/osx/package b/package/osx/package index bfc3d9443..fc623b7b2 100755 --- a/package/osx/package +++ b/package/osx/package @@ -22,7 +22,7 @@ device=$(hdiutil attach "${TEMP_FILE}" | \ cp -a "${APP_PATH}" "/Volumes/${VOL_NAME}" #ls "${FW_DIR}" | xargs -n 1 -I {} cp "${FW_DIR}/{}" "/Volumes/${VOL_NAME}/Firmware" cp "${BUILD_DIR}/uavobject-synthetics/matlab/OPLogConvert.m" "/Volumes/${VOL_NAME}/Utilities" -cp "${ROOT_DIR}/HISTORY.txt" "/Volumes/${VOL_NAME}" +cp "${ROOT_DIR}/WHATSNEW.txt" "/Volumes/${VOL_NAME}" "${ROOT_DIR}/package/osx/libraries" \ "/Volumes/${VOL_NAME}/OpenPilot GCS.app" || exit 1 From 35b580a34e2aa709f71fcffc55c2856a106e75af Mon Sep 17 00:00:00 2001 From: "Richard Flay (Hyper)" Date: Sun, 2 Jun 2013 08:44:54 +0930 Subject: [PATCH 083/120] OP-982: Adds Revolution related entries to OpenPilot-CDC.inf for Windows. +review OPReview --- flight/Project/Windows USB/OpenPilot-CDC.inf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flight/Project/Windows USB/OpenPilot-CDC.inf b/flight/Project/Windows USB/OpenPilot-CDC.inf index ad82db783..1edf92ea7 100644 --- a/flight/Project/Windows USB/OpenPilot-CDC.inf +++ b/flight/Project/Windows USB/OpenPilot-CDC.inf @@ -11,10 +11,12 @@ DriverVer=10/15/2009,1.0.0.0 [DeviceList.NTx86] %CopterControl%= DriverInstall,USB\VID_20A0&PID_415b&MI_00 %OPLink%= DriverInstall,USB\VID_20A0&PID_415c&MI_00 +%Revolution%= DriverInstall,USB\VID_20A0&PID_415e&MI_00 [DeviceList.NTamd64] %CopterControl%= DriverInstall,USB\VID_20A0&PID_415b&MI_00 %OPLink%= DriverInstall,USB\VID_20A0&PID_415c&MI_00 +%Revolution%= DriverInstall,USB\VID_20A0&PID_415e&MI_00 [DriverInstall] include=mdmcpq.inf @@ -33,3 +35,4 @@ HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" ProviderName = "CDC Driver" CopterControl = "OpenPilot CDC Driver" OPLink = "OpenPilot CDC Driver" +Revolution = "OpenPilot CDC Driver" From 9683ddc37af01155e52ef6d6cbe42c9e7ceffacc Mon Sep 17 00:00:00 2001 From: Kevin Vertucio Date: Sat, 1 Jun 2013 23:11:28 -0400 Subject: [PATCH 084/120] Updated AuthorsModel. Added utility script for generating QML ListElements of authors. --- .../plugins/coreplugin/CREDITS-utility.html | 44 +++++++++++++++++++ .../src/plugins/coreplugin/CREDITS.html | 2 + .../plugins/coreplugin/qml/AuthorsModel.qml | 4 ++ 3 files changed, 50 insertions(+) create mode 100644 ground/openpilotgcs/src/plugins/coreplugin/CREDITS-utility.html diff --git a/ground/openpilotgcs/src/plugins/coreplugin/CREDITS-utility.html b/ground/openpilotgcs/src/plugins/coreplugin/CREDITS-utility.html new file mode 100644 index 000000000..0041a5246 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/coreplugin/CREDITS-utility.html @@ -0,0 +1,44 @@ + + + + CREDITS Utility + + + + + +

Author Dialog authorModel Utility

+

This utility will parse a \n delimited list of names and generate ListElement components for entry into the QML model located in /qml/AuthorsModel.qml.

+
+
+ + +
+ + + + + diff --git a/ground/openpilotgcs/src/plugins/coreplugin/qml/AuthorsModel.qml b/ground/openpilotgcs/src/plugins/coreplugin/qml/AuthorsModel.qml index 307098bc6..d89d4fa12 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/qml/AuthorsModel.qml +++ b/ground/openpilotgcs/src/plugins/coreplugin/qml/AuthorsModel.qml @@ -130,6 +130,8 @@ ListModel { ListElement{ name:"Alex Sowa" } ListElement{ name:"Pete Stapley" } + + ListElement{ name:"Vova Starikh" } ListElement{ name:"Rowan Taubitz" } @@ -151,5 +153,7 @@ ListModel { ListElement{ name:"Kendal Wells" } + ListElement { name: "David Willis" } + ListElement{ name:"Dmitriy Zaitsev" } } \ No newline at end of file From 5732c2fd4c0e566c59dbe293e7ebc29fec827664 Mon Sep 17 00:00:00 2001 From: Mathieu Rondonneau Date: Sat, 1 Jun 2013 22:13:04 -0700 Subject: [PATCH 085/120] OP-958L: Some fixes for 15s hang and unplug/plug issue reported lately. This is not cleanedup but I want to get this in so other people can test. --- .../src/plugins/ophid/inc/ophid_const.h | 1 + .../src/plugins/ophid/inc/ophid_usbmon.h | 2 +- .../plugins/ophid/src/ophid_usbmon_win.cpp | 225 ++++++++++++------ 3 files changed, 153 insertions(+), 75 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/ophid/inc/ophid_const.h b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_const.h index f0928891e..e583cc8ec 100644 --- a/ground/openpilotgcs/src/plugins/ophid/inc/ophid_const.h +++ b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_const.h @@ -60,5 +60,6 @@ #define OPHID_ERROR_PARAMETER -3 #define OPHID_ERROR_HANDLE -4 #define OPHID_ERROR_INIT -5 +#define OPHID_ERROR_ENUMERATION -6 #endif // OPHID_CONST_H diff --git a/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h index b39c74952..89bf6a806 100644 --- a/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h +++ b/ground/openpilotgcs/src/plugins/ophid/inc/ophid_usbmon.h @@ -194,7 +194,7 @@ private: */ static QString getDeviceProperty(HDEVINFO devInfo, PSP_DEVINFO_DATA devData, DWORD property); static int infoFromHandle(const GUID & guid, USBPortInfo & info, HDEVINFO & devInfo, DWORD & index); - static void enumerateDevicesWin(const GUID & guidDev, QList *infoList); + void enumerateDevicesWin(const GUID & guidDev); bool matchAndDispatchChangedDevice(const QString & deviceID, const GUID & guid, WPARAM wParam); #ifdef QT_GUI_LIB USBRegistrationWidget *notificationWidget; diff --git a/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_win.cpp b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_win.cpp index 8d16e7099..f0fb8b2e4 100644 --- a/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_win.cpp +++ b/ground/openpilotgcs/src/plugins/ophid/src/ophid_usbmon_win.cpp @@ -36,6 +36,8 @@ #define printf qDebug +static QMutex DeviceChangeMutex; + void USBMonitor::deviceEventReceived() { qDebug() << "Device event"; @@ -80,34 +82,34 @@ USBMonitor::~USBMonitor() */ QList USBMonitor::availableDevices(int vid, int pid, int bcdDeviceMSB, int bcdDeviceLSB) { - QList allPorts = availableDevices(); - qDebug() << "USBMonitor::availableDevices list off all ports:"; - qDebug() << "USBMonitor::availableDevices total ports:" << allPorts.length(); - foreach(USBPortInfo info, allPorts) { - qDebug() << "----------"; - qDebug() << "bcdDevice:" << info.bcdDevice; - qDebug() << "devicePath:" << info.devicePath; - qDebug() << "product:" << info.product; - } - qDebug() << "END OF LIST"; + int i; QList thePortsWeWant; - qDebug() << "USBMonitor::availableDevices bcdLSB=" << bcdDeviceLSB; - foreach(USBPortInfo port, allPorts) { - qDebug() << "USBMonitorWin:Port VID=" << port.vendorID << "PID=" << port.productID << "bcddevice=" << port.bcdDevice; - if ((port.vendorID == vid || vid == -1) && (port.productID == pid || pid == -1) && ((port.bcdDevice >> 8) == bcdDeviceMSB || bcdDeviceMSB == -1) && - ((port.bcdDevice & 0x00ff) == bcdDeviceLSB || bcdDeviceLSB == -1)) { - thePortsWeWant.append(port); + + OPHID_TRACE("IN"); + + // Trigger enumeration + //OPHID_DEBUG("Enumerate"); + //availableDevices(); + + // Print the list + qDebug() << "List off (" << knowndevices.length() << ") devices that are tracked:"; + foreach(USBPortInfo info, knowndevices /*thePortsWeWant*/) { + qDebug() << "product:" << info.product + << " bcdDevice:" << info.bcdDevice + << " devicePath:" << info.devicePath; + + // + if ((info.vendorID == vid || vid == -1) && + (info.productID == pid || pid == -1) && + ((info.bcdDevice >> 8) == bcdDeviceMSB || bcdDeviceMSB == -1) && + ((info.bcdDevice & 0x00ff) == bcdDeviceLSB || bcdDeviceLSB == -1)) { + thePortsWeWant.append(info); + OPHID_DEBUG("Found device."); } } - qDebug() << "USBMonitor::availableDevices list off matching ports vid pid bcdMSD bcdLSD:" << vid << pid << bcdDeviceMSB << bcdDeviceLSB; - qDebug() << "USBMonitor::availableDevices total matching ports:" << thePortsWeWant.length(); - foreach(USBPortInfo info, thePortsWeWant) { - qDebug() << "----------"; - qDebug() << "bcdDevice:" << info.bcdDevice; - qDebug() << "devicePath:" << info.devicePath; - qDebug() << "product:" << info.product; - } - qDebug() << "END OF LIST"; + + OPHID_TRACE("OUT"); + return thePortsWeWant; } @@ -131,8 +133,8 @@ QList USBMonitor::availableDevices(int vid, int pid, int bcdDeviceM #define TCHARToQString(x) QString::fromLocal8Bit((x)) #define TCHARToQStringN(x, y) QString::fromLocal8Bit((x), (y)) #endif /*UNICODE*/ -#define MATCHOPHIDSTRING "COL01" -#define MATCHOPBLSTRING "161A0549" +#define HID2IGNOREUC "COL02" +#define HID2IGNORElc "col02" void USBMonitor::setUpNotifications() { @@ -160,6 +162,7 @@ void USBMonitor::setUpNotifications() } LRESULT USBMonitor::onDeviceChangeWin(WPARAM wParam, LPARAM lParam) { + OPHID_TRACE("IN"); if (DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam) { PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam; if (pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) { @@ -169,34 +172,46 @@ LRESULT USBMonitor::onDeviceChangeWin(WPARAM wParam, LPARAM lParam) matchAndDispatchChangedDevice(deviceID, guid_hid, wParam); } } + OPHID_TRACE("OUT"); return 0; } #ifdef QT_GUI_LIB bool USBRegistrationWidget::winEvent(MSG *message, long *result) { + bool ret = false; + if (message->message == WM_DEVICECHANGE) { + OPHID_TRACE("IN"); qese->onDeviceChangeWin(message->wParam, message->lParam); *result = 1; - return true; + ret = true; + OPHID_TRACE("OUT"); } - return false; + + return ret; } #endif bool USBMonitor::matchAndDispatchChangedDevice(const QString & deviceID, const GUID & guid, WPARAM wParam) { qDebug() << "USB_MONITOR matchAndDispatchChangedDevice deviceID=" << deviceID; bool rv = false; - DWORD dwFlag = (DBT_DEVICEARRIVAL == wParam) ? DIGCF_PRESENT : DIGCF_ALLCLASSES; + bool rc; + DWORD dwFlag = (DBT_DEVICEARRIVAL == wParam) ? DIGCF_PRESENT : 0/*DIGCF_ALLCLASSES*/; HDEVINFO devInfo; +// QString qHIDSymbolicName="HID"; +// WCHAR wHIDSymbolicName[10]; +// qHIDSymbolicName.toWCharArray(wHIDSymbolicName); + if ((devInfo = SetupDiGetClassDevs(&guid, NULL, NULL, dwFlag | DIGCF_DEVICEINTERFACE)) != INVALID_HANDLE_VALUE) { SP_DEVINFO_DATA spDevInfoData; spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA); for (DWORD i = 0; SetupDiEnumDeviceInfo(devInfo, i, &spDevInfoData); i++) { DWORD nSize = 0; TCHAR buf[MAX_PATH]; - if (SetupDiGetDeviceInstanceId(devInfo, &spDevInfoData, buf, MAX_PATH, &nSize) && - deviceID.contains(TCHARToQString(buf)) && (deviceID.contains(MATCHOPHIDSTRING) || - deviceID.contains(MATCHOPBLSTRING))) { // we found a match + rc = SetupDiGetDeviceInstanceId(devInfo, &spDevInfoData, buf, MAX_PATH, &nSize); + qDebug() << "PATH:" << TCHARToQString(buf); + if (rc && deviceID.contains(TCHARToQString(buf)) /*&& !QString().contains(TCHARToQString(HID2IGNOREUC))*/) { // we found a match + qDebug() << "ACCEPTED" << TCHARToQString(buf); USBPortInfo info; info.devicePath = deviceID; if (wParam == DBT_DEVICEARRIVAL) { @@ -205,46 +220,61 @@ bool USBMonitor::matchAndDispatchChangedDevice(const QString & deviceID, const G qDebug() << "USB_MONITOR infoFromHandle failed on matchAndDispatchChangedDevice"; break; } - bool m_break = false; - foreach(USBPortInfo m_info, knowndevices) { - if (m_info.serialNumber == info.serialNumber && m_info.productID == info.productID && m_info.bcdDevice == info.bcdDevice && m_info.devicePath == info.devicePath) { - qDebug() << "USB_MONITOR device already present don't emit signal"; - m_break = true; + if (knowndevices.length()) { + foreach(USBPortInfo m_info, knowndevices) { + + qDebug() << m_info.devicePath; + qDebug() << info.devicePath; + + if (m_info.serialNumber == info.serialNumber && + m_info.productID == info.productID && + m_info.bcdDevice == info.bcdDevice && + m_info.devicePath == info.devicePath) { + qDebug() << "USB_MONITOR device already present don't emit signal"; + break; + } } - } - if (m_break) { - break; - } + } if (info.bcdDevice == 0 || info.product.isEmpty()) { qDebug() << "USB_MONITOR empty information on device not emiting signal"; break; } knowndevices.append(info); - qDebug() << "USB_MONITOR emit device discovered on device:" << info.product << info.bcdDevice; + qDebug() << "USB_MONITOR emit device discovered on device:" + << info.product + << info.bcdDevice; emit deviceDiscovered(info); break; } else if (wParam == DBT_DEVICEREMOVECOMPLETE) { bool found = false; + // DeviceChangeMutex.lock(); for (int x = 0; x < knowndevices.count(); ++x) { - if (knowndevices[x].devicePath == deviceID) { + // if (knowndevices[x].devicePath == deviceID) { USBPortInfo temp = knowndevices.at(x); knowndevices.removeAt(x); qDebug() << "USB_MONITOR emit device removed on device:" << temp.product << temp.bcdDevice; - emit deviceRemoved(temp); + + //emit deviceRemoved(temp); + found = true; - break; - } + // break; + // } } - if (!found) { - qDebug() << "USB_MONITOR emit device removed on unknown device"; + + //if (!found) { + // qDebug() << "USB_MONITOR emit device removed on unknown device"; emit deviceRemoved(info); - } + //} + //else + break; +// DeviceChangeMutex.unlock(); } break; } } SetupDiDestroyDeviceInfoList(devInfo); } + OPHID_TRACE("OUT"); return rv; } @@ -259,44 +289,57 @@ QString USBMonitor::getDeviceProperty(HDEVINFO devInfo, PSP_DEVINFO_DATA devData delete[] buff; return result; } -/** - Returns a list of all currently available devices - */ -QList USBMonitor::availableDevices() -{ - QList ports; - enumerateDevicesWin(guid_hid, &ports); - // qDebug()<<"USBMonitorWin availabledevices="< USBMonitor::availableDevices() { + + enumerateDevicesWin(guid_hid); + return knowndevices; } -void USBMonitor::enumerateDevicesWin(const GUID & guid, QList *infoList) + +void USBMonitor::enumerateDevicesWin(const GUID & guid) { HDEVINFO devInfo; USBPortInfo info; + DWORD j = 0; + DWORD i = 0; + OPHID_TRACE("IN"); + DeviceChangeMutex.lock(); +// QString qHIDSymbolicName = "HID"; +// WCHAR wHIDSymbolicName[10]; +// qHIDSymbolicName.toWCharArray(wHIDSymbolicName); // qDebug()<<"enumerateDevicesWin1"; if ((devInfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)) != INVALID_HANDLE_VALUE) { // qDebug()<<"enumerateDevicesWin2"; SP_DEVINFO_DATA devInfoData; devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); - for (DWORD i = 0; SetupDiEnumDeviceInfo(devInfo, i, &devInfoData); i++) { + // only handle the first one enumerated that matches openpilot vendor + // the second one is expected to be the gamepad controller which we don't want to deal with + for (i = 0; SetupDiEnumDeviceInfo(devInfo, i, &devInfoData); i++) { int r = infoFromHandle(guid, info, devInfo, i); if (r == 1) { - infoList->append(info); - } else if (r == 0) { + //infoList->append(info); + knowndevices.append(info); + j++; + // break; + } else if (r == OPHID_ERROR_ENUMERATION) { break; } } - SetupDiDestroyDeviceInfoList(devInfo); } + OPHID_DEBUG("Added %d device(s).", j); + DeviceChangeMutex.unlock(); + OPHID_TRACE("OUT"); } int USBMonitor::infoFromHandle(const GUID & guid, USBPortInfo & info, HDEVINFO & devInfo, DWORD & index) { + OPHID_TRACE("IN"); // qDebug()<<"index0="<DevicePath /*DevicePath*/, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (h == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); @@ -335,13 +398,15 @@ int USBMonitor::infoFromHandle(const GUID & guid, USBPortInfo & info, HDEVINFO & // Let's not log it :) if (err == ERROR_ACCESS_DENIED) { free(details); - return 2; + ret = 2; + goto leave; } qDebug() << "Problem opening handle, path: " << QString().fromWCharArray(details->DevicePath); free(details); - return 2; + ret = 2; + goto leave; } // qDebug()<<"index4="< Date: Sun, 2 Jun 2013 18:11:04 +0930 Subject: [PATCH 086/120] OP-982: Updates to spacing and Strings in response to review feedback. +review OPReview-493 --- flight/Project/Windows USB/OpenPilot-CDC.inf | 38 ++++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/flight/Project/Windows USB/OpenPilot-CDC.inf b/flight/Project/Windows USB/OpenPilot-CDC.inf index 1edf92ea7..b848fa642 100644 --- a/flight/Project/Windows USB/OpenPilot-CDC.inf +++ b/flight/Project/Windows USB/OpenPilot-CDC.inf @@ -1,27 +1,27 @@ [Version] -Signature="$Windows NT$" -Class=Ports -ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} -Provider=%ProviderName% -DriverVer=10/15/2009,1.0.0.0 +Signature = "$Windows NT$" +Class = Ports +ClassGuid = {4D36E978-E325-11CE-BFC1-08002BE10318} +Provider = %ProviderName% +DriverVer = 10/15/2009,1.0.0.0 [MANUFACTURER] -%ProviderName%=DeviceList, NTx86, NTamd64 +%ProviderName% = DeviceList, NTx86, NTamd64 [DeviceList.NTx86] -%CopterControl%= DriverInstall,USB\VID_20A0&PID_415b&MI_00 -%OPLink%= DriverInstall,USB\VID_20A0&PID_415c&MI_00 -%Revolution%= DriverInstall,USB\VID_20A0&PID_415e&MI_00 +%CopterControl% = DriverInstall,USB\VID_20A0&PID_415b&MI_00 +%OPLink% = DriverInstall,USB\VID_20A0&PID_415c&MI_00 +%Revolution% = DriverInstall,USB\VID_20A0&PID_415e&MI_00 [DeviceList.NTamd64] -%CopterControl%= DriverInstall,USB\VID_20A0&PID_415b&MI_00 -%OPLink%= DriverInstall,USB\VID_20A0&PID_415c&MI_00 -%Revolution%= DriverInstall,USB\VID_20A0&PID_415e&MI_00 +%CopterControl% = DriverInstall,USB\VID_20A0&PID_415b&MI_00 +%OPLink% = DriverInstall,USB\VID_20A0&PID_415c&MI_00 +%Revolution% = DriverInstall,USB\VID_20A0&PID_415e&MI_00 [DriverInstall] -include=mdmcpq.inf -CopyFiles=FakeModemCopyFileSection -AddReg=LowerFilterAddReg,SerialPropPageAddReg +include = mdmcpq.inf +CopyFiles = FakeModemCopyFileSection +AddReg = LowerFilterAddReg,SerialPropPageAddReg [DriverInstall.Services] include = mdmcpq.inf @@ -32,7 +32,7 @@ AddService = usbser, 0x00000002, LowerFilter_Service_Inst HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" [Strings] -ProviderName = "CDC Driver" -CopterControl = "OpenPilot CDC Driver" -OPLink = "OpenPilot CDC Driver" -Revolution = "OpenPilot CDC Driver" +ProviderName = "OpenPilot Team" +CopterControl = "CopterControl Virtual Serial Port" +OPLink = "OPLink Virtual Serial Port" +Revolution = "Revolution Virtual Serial Port" From b0111c12d1dcc09fb5dc9f056c23013878bc85e1 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Sun, 2 Jun 2013 10:55:34 +0200 Subject: [PATCH 087/120] OP-981 fixed broken GCS clean configuration link created by installer --- package/winx86/openpilotgcs.nsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/winx86/openpilotgcs.nsi b/package/winx86/openpilotgcs.nsi index 47e8b07b9..ed2bf0edf 100644 --- a/package/winx86/openpilotgcs.nsi +++ b/package/winx86/openpilotgcs.nsi @@ -247,7 +247,7 @@ Section "Shortcuts" InSecShortcuts CreateShortCut "$SMPROGRAMS\OpenPilot\OpenPilot GCS.lnk" "$INSTDIR\bin\openpilotgcs.exe" \ "" "$INSTDIR\bin\openpilotgcs.exe" 0 "" "" "${PRODUCT_NAME} ${PRODUCT_VERSION}. ${BUILD_DESCRIPTION}" CreateShortCut "$SMPROGRAMS\OpenPilot\OpenPilot GCS (clean configuration).lnk" "$INSTDIR\bin\openpilotgcs.exe" \ - "-clean-config" "$INSTDIR\bin\openpilotgcs.exe" 0 "" "" "${PRODUCT_NAME} ${PRODUCT_VERSION}. ${BUILD_DESCRIPTION}" + "-reset" "$INSTDIR\bin\openpilotgcs.exe" 0 "" "" "${PRODUCT_NAME} ${PRODUCT_VERSION}. ${BUILD_DESCRIPTION}" CreateShortCut "$SMPROGRAMS\OpenPilot\OpenPilot License.lnk" "$INSTDIR\LICENSE.txt" \ "" "$INSTDIR\bin\openpilotgcs.exe" 0 CreateShortCut "$SMPROGRAMS\OpenPilot\OpenPilot ReadMe.lnk" "$INSTDIR\README.txt" \ From 8c494dce003a8374d300f855adc4b999145b8ea9 Mon Sep 17 00:00:00 2001 From: "Richard Flay (Hyper)" Date: Sun, 2 Jun 2013 18:43:37 +0930 Subject: [PATCH 088/120] OP-982: Further updates to Strings in response to review feedback. +review OPReview-493 --- flight/Project/Windows USB/OpenPilot-CDC.inf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flight/Project/Windows USB/OpenPilot-CDC.inf b/flight/Project/Windows USB/OpenPilot-CDC.inf index b848fa642..faab6ef5c 100644 --- a/flight/Project/Windows USB/OpenPilot-CDC.inf +++ b/flight/Project/Windows USB/OpenPilot-CDC.inf @@ -32,7 +32,7 @@ AddService = usbser, 0x00000002, LowerFilter_Service_Inst HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" [Strings] -ProviderName = "OpenPilot Team" -CopterControl = "CopterControl Virtual Serial Port" -OPLink = "OPLink Virtual Serial Port" -Revolution = "Revolution Virtual Serial Port" +ProviderName = "OpenPilot" +CopterControl = "CopterControl Virtual COM Port" +OPLink = "OPLink Virtual COM Port" +Revolution = "Revolution Virtual COM Port" From 73f72430194432187858264172e947731620765e Mon Sep 17 00:00:00 2001 From: David Ankers Date: Sun, 2 Jun 2013 20:22:46 +1000 Subject: [PATCH 089/120] Change to next release name, this was likely to be forgotten so doing it while I remember. --- package/winx86/openpilotgcs.nsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/winx86/openpilotgcs.nsi b/package/winx86/openpilotgcs.nsi index ed2bf0edf..194d64884 100644 --- a/package/winx86/openpilotgcs.nsi +++ b/package/winx86/openpilotgcs.nsi @@ -276,7 +276,7 @@ Section ; create uninstall info WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "UninstallString" '"$INSTDIR\Uninstall.exe"' WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "DisplayIcon" '"$INSTDIR\bin\openpilotgcs.exe"' WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "Publisher" "OpenPilot Team" - WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "DisplayVersion" "Fatty Patty" + WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "DisplayVersion" "Italian Stallion" WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "URLInfoAbout" "http://www.openpilot.org" WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "HelpLink" "http://wiki.openpilot.org" WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "EstimatedSize" 100600 From 218d197aa8368eb22684bb73c39bdca4b2eba5bc Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Sun, 2 Jun 2013 12:42:15 +0200 Subject: [PATCH 090/120] OP-983 fixed minor spelling issues in GCS --- .../openpilotgcs/translations/openpilotgcs_de.ts | 6 +++--- .../openpilotgcs/translations/openpilotgcs_es.ts | 6 +++--- .../openpilotgcs/translations/openpilotgcs_fr.ts | 16 ++++++++-------- .../openpilotgcs/translations/openpilotgcs_ru.ts | 6 +++--- .../translations/openpilotgcs_zh_CN.ts | 6 +++--- .../src/experimental/USB_UPLOAD_TOOL/main.cpp | 2 +- .../plugins/setupwizard/pages/autoupdatepage.cpp | 2 +- .../plugins/uploader/uploadergadgetwidget.cpp | 8 ++++---- 8 files changed, 26 insertions(+), 26 deletions(-) diff --git a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_de.ts b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_de.ts index 1e431f98f..fad9557a4 100644 --- a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_de.ts +++ b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_de.ts @@ -14033,12 +14033,12 @@ or power cycle to force a board reset. - Please disconnect all openpilot boards + Please disconnect your OpenPilot board - Please connect the board (USB only!) + Please connect your OpenPilot board (USB only!) @@ -14048,7 +14048,7 @@ or power cycle to force a board reset. - Openpilot Uploader + OpenPilot Uploader diff --git a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_es.ts b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_es.ts index 183101e99..5f29e13a0 100644 --- a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_es.ts +++ b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_es.ts @@ -14034,12 +14034,12 @@ or power cycle to force a board reset. - Please disconnect all openpilot boards + Please disconnect your OpenPilot board - Please connect the board (USB only!) + Please connect your OpenPilot board (USB only!) @@ -14049,7 +14049,7 @@ or power cycle to force a board reset. - Openpilot Uploader + OpenPilot Uploader diff --git a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_fr.ts b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_fr.ts index 7463d76bf..d7414840c 100644 --- a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_fr.ts +++ b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_fr.ts @@ -23,7 +23,7 @@ OpenPilot GCS - Plugin loader messages - Openpilot GCS - Messages du chargeur de modules complémentaires + OpenPilot GCS - Messages du chargeur de modules complémentaires @@ -158,12 +158,12 @@ About &OpenPilot GCS - A propos d'&Openpilot GCS + A propos d'&OpenPilot GCS About &OpenPilot GCS... - A propos d'&Openpilot GCS... + A propos d'&OpenPilot GCS... @@ -415,7 +415,7 @@ About OpenPilot GCS - A propos d'Openpilot GCS + A propos d'OpenPilot GCS @@ -12844,7 +12844,7 @@ p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Sélection du type de véhicule</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt; font-weight:600;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Pour continuer, l'assistant a besoin de connaître sur quel type de véhicule la carte Openpilot va être utilisée. Cette étape est cruciale car une grande partie de la configuration qui suit est spécifique au type de véhicule.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Pour continuer, l'assistant a besoin de connaître sur quel type de véhicule la carte OpenPilot va être utilisée. Cette étape est cruciale car une grande partie de la configuration qui suit est spécifique au type de véhicule.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Allez-y et sélectionnez le type de véhicule pour lequel vous souhaitez créer une configuration.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> @@ -14471,12 +14471,12 @@ or power cycle to force a board reset. - Please disconnect all openpilot boards + Please disconnect your OpenPilot board - Please connect the board (USB only!) + Please connect your OpenPilot board (USB only!) @@ -14486,7 +14486,7 @@ or power cycle to force a board reset. - Openpilot Uploader + OpenPilot Uploader diff --git a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_ru.ts b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_ru.ts index e26c74211..842ad65d1 100644 --- a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_ru.ts +++ b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_ru.ts @@ -14056,12 +14056,12 @@ or power cycle to force a board reset. - Please disconnect all openpilot boards + Please disconnect your OpenPilot board - Please connect the board (USB only!) + Please connect your OpenPilot board (USB only!) @@ -14071,7 +14071,7 @@ or power cycle to force a board reset. - Openpilot Uploader + OpenPilot Uploader diff --git a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_zh_CN.ts b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_zh_CN.ts index 4d92f3c34..6c3652305 100644 --- a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_zh_CN.ts +++ b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_zh_CN.ts @@ -14036,12 +14036,12 @@ or power cycle to force a board reset. - Please disconnect all openpilot boards + Please disconnect your OpenPilot board - Please connect the board (USB only!) + Please connect your OpenPilot board (USB only!) @@ -14051,7 +14051,7 @@ or power cycle to force a board reset. - Openpilot Uploader + OpenPilot Uploader diff --git a/ground/openpilotgcs/src/experimental/USB_UPLOAD_TOOL/main.cpp b/ground/openpilotgcs/src/experimental/USB_UPLOAD_TOOL/main.cpp index e5c98386b..104bbd6a0 100644 --- a/ground/openpilotgcs/src/experimental/USB_UPLOAD_TOOL/main.cpp +++ b/ground/openpilotgcs/src/experimental/USB_UPLOAD_TOOL/main.cpp @@ -61,7 +61,7 @@ int main(int argc, char *argv[]) cout << "| examples: |\n"; cout << "| |\n"; cout << "| program and verify device #0 |\n"; - cout << "| OPUploadTool -p c:/OpenPilot.bin -w \"Openpilot Firmware\" -v -d 0 |\n"; + cout << "| OPUploadTool -p c:/OpenPilot.bin -w \"OpenPilot Firmware\" -v -d 0 |\n"; cout << "| |\n"; cout << "| Perform a quick compare of FW in file with FW in device #1 |\n"; cout << "| OPUploadTool -ch c:/OpenPilot2.bin -d 2 |\n"; diff --git a/ground/openpilotgcs/src/plugins/setupwizard/pages/autoupdatepage.cpp b/ground/openpilotgcs/src/plugins/setupwizard/pages/autoupdatepage.cpp index ca67102fa..57a6b7723 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/pages/autoupdatepage.cpp +++ b/ground/openpilotgcs/src/plugins/setupwizard/pages/autoupdatepage.cpp @@ -70,7 +70,7 @@ void AutoUpdatePage::updateStatus(uploader::AutoUpdateStep status, QVariant valu break; case uploader::SUCCESS: enableButtons(true); - ui->statusLabel->setText("Board Updated, please press the 'next' button below"); + ui->statusLabel->setText("Board updated, please press 'Next' to continue"); break; case uploader::FAILURE: getWizard()->setWindowFlags(getWizard()->windowFlags() | Qt::WindowStaysOnTopHint); diff --git a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp index 2b26332c4..5fa1049ee 100644 --- a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp @@ -541,7 +541,7 @@ bool UploaderGadgetWidget::autoUpdate() connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); while (USBMonitor::instance()->availableDevices(0x20a0, -1, -1, -1).length() > 0) { emit autoUpdateSignal(WAITING_DISCONNECT, QVariant()); - if (QMessageBox::warning(this, tr("OpenPilot Uploader"), tr("Please disconnect all openpilot boards"), QMessageBox::Ok, QMessageBox::Cancel) == QMessageBox::Cancel) { + if (QMessageBox::warning(this, tr("OpenPilot Uploader"), tr("Please disconnect your OpenPilot board"), QMessageBox::Ok, QMessageBox::Cancel) == QMessageBox::Cancel) { emit autoUpdateSignal(FAILURE, QVariant()); return false; } @@ -684,7 +684,7 @@ void UploaderGadgetWidget::systemRescue() log("**********************************************************"); log("You will be prompted to first connect USB, then system power"); if (USBMonitor::instance()->availableDevices(0x20a0, -1, -1, -1).length() > 0) { - if (QMessageBox::warning(this, tr("OpenPilot Uploader"), tr("Please disconnect all openpilot boards"), QMessageBox::Ok, QMessageBox::Cancel) == QMessageBox::Cancel) { + if (QMessageBox::warning(this, tr("OpenPilot Uploader"), tr("Please disconnect your OpenPilot board"), QMessageBox::Ok, QMessageBox::Cancel) == QMessageBox::Cancel) { m_config->rescueButton->setEnabled(true); return; } @@ -695,7 +695,7 @@ void UploaderGadgetWidget::systemRescue() log("** Follow those instructions to attempt a system rescue **"); log("**********************************************************"); log("You will be prompted to first connect USB, then system power"); - m_progress = new QProgressDialog(tr("Please connect the board (USB only!)"), tr("Cancel"), 0, 20); + m_progress = new QProgressDialog(tr("Please connect your OpenPilot board (USB only!)"), tr("Cancel"), 0, 20); QProgressBar *bar = new QProgressBar(m_progress); bar->setFormat("Timeout"); m_progress->setBar(bar); @@ -710,7 +710,7 @@ void UploaderGadgetWidget::systemRescue() if (!m_timer->isActive()) { m_progress->close(); m_timer->stop(); - QMessageBox::warning(this, tr("Openpilot Uploader"), tr("No board connection was detected!")); + QMessageBox::warning(this, tr("OpenPilot Uploader"), tr("No board connection was detected!")); m_config->rescueButton->setEnabled(true); return; } From 48945ffeb6619f12b2ba38c9eef4dfbfe19a5c3b Mon Sep 17 00:00:00 2001 From: Kevin Vertucio Date: Sun, 2 Jun 2013 07:29:23 -0400 Subject: [PATCH 091/120] added authors to CREDITS. --- ground/openpilotgcs/src/plugins/coreplugin/CREDITS.html | 3 +++ .../src/plugins/coreplugin/qml/AuthorsModel.qml | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/ground/openpilotgcs/src/plugins/coreplugin/CREDITS.html b/ground/openpilotgcs/src/plugins/coreplugin/CREDITS.html index 594314676..0a632e389 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/CREDITS.html +++ b/ground/openpilotgcs/src/plugins/coreplugin/CREDITS.html @@ -56,7 +56,9 @@ Dmytro Poplavskiy Eric Price Richard Querin Randy Ram +Philippe Renon Laurent Ribon +Mathieu Rondonneau Julien Rouviere Jackson Russell Zik Saleeba @@ -72,6 +74,7 @@ Pete Stapley Vova Starikh Rowan Taubitz Andrew Thoms +Philippe Vanhaesendonck Jasper van Loenen Vassilis Varveropoulos Kevin Vertucio diff --git a/ground/openpilotgcs/src/plugins/coreplugin/qml/AuthorsModel.qml b/ground/openpilotgcs/src/plugins/coreplugin/qml/AuthorsModel.qml index d89d4fa12..226a186b5 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/qml/AuthorsModel.qml +++ b/ground/openpilotgcs/src/plugins/coreplugin/qml/AuthorsModel.qml @@ -104,9 +104,13 @@ ListModel { ListElement{ name:"Richard Querin" } ListElement{ name:"Randy Ram" } + + ListElement{ name:"Philippe Renon" } ListElement{ name:"Laurent Ribon" } + ListElement{ name:"Mathieu Rondonneau" } + ListElement{ name:"Julien Rouviere" } ListElement{ name:"Jackson Russell" } @@ -137,6 +141,8 @@ ListModel { ListElement{ name:"Andrew Thoms" } + ListElement{ name:"Philippe Vanhaesendonck" } + ListElement{ name:"Jasper van Loenen" } ListElement{ name:"Vassilis Varveropoulos" } From 214793d0ad829d2a5102e2cedf4829630debc658 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sun, 2 Jun 2013 14:32:15 +0300 Subject: [PATCH 092/120] OP-910: add release notes for RELEASE-13.06-RC1 --- WHATSNEW.txt | 121 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 113 insertions(+), 8 deletions(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 7b884f12a..b1c3b2057 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -2,12 +2,115 @@ Short summary of changes. For a complete list see the git log. --- RELEASE-13.06 --- Italian Stallion Release --- -This is the first Revo software release which also supports CC, CC3D, OPLinkMini and unreleased -yet OP OSD boards. This is a major change: from different toolchains and build system to the whole -source code reformatting according to project style guidelines. The goal of this release is to -provide CC-style features for new Revo platform + radio using Revo's internal modem and external -OPLinkMini board. All advanced features like Altitude Hold, Position Hold, Guidance, Return to Home, -AutoLanding etc. are not released yet and planned for followin releases. +This is the first Revolution software release which also supports CC, CC3D, OPLinkMini and +unreleased yet OP OSD boards. This is a major change: from different toolchains and build +system to the whole source code reformatting according to project style guidelines. The goal +of this release is to provide CC-style features for new Revo platform + radio using Revo's +internal modem and external OPLinkMini board. All advanced features like Altitude Hold, +Position Hold, Guidance, Return to Home, AutoLanding etc. are not released yet and planned +for following releases. + +Some video tutorials: + http://wiki.openpilot.org/display/DocDE/OpenPilot+Tutorials + +Important Release Notes: + +- Since this release the packaged distribution does not contain firmware files in a folder. + They are now integrated into the GCS so always are up to date. To update you must use + either Vehicle Setup Wizard (big green button on the Welcome GCS tab) or new Auto-Update + button on the Firmware tab. + +- New Auto-Update feature simplifies all OpenPilot board firmware updates. Just click it + and follow on-screen directions to reflash your board (CC, CC3D, OPLinkMini, Revolution + or OSD prototypes). Internally it is the same as Rescue but uses embedded firmware images, + no need to browse for them anymore. + +- New bootloaders are REQUIRED for this release to support some of new features like settings + erase and some others. As always, bootloaders can be updated without any special programmer + hardware using bootloader updaters firmware. Currently F1 boards (CC, CC3D, OPLinkMini) + require bootloader version 4 or higher, and F4 boards (Revolution, OSD prototype) require + bootloader version 5 or higher. Check the wiki for details of how to update them: + http://wiki.openpilot.org/display/BUILDS/Bootloader+update + +- New feature: settings erase option. In the past some special settings erase firmware was + used to erase bad or incompatible settings from CC/CC3D boards. Now it is deprecated, and + this functionality is now integrated into bootloader and firmware. To erase any board + settings you must have latest bootloader. Then enter DFU (boot) mode (using Halt or Rescue + function) and click "Erase settings" button on the Firmware tab and follow on-screen + instructions. This will NOT work with older bootloader, and the button will be disabled. + +- On Linux you should remove OpenPilot package if was installed, then install new one. This + is a known issue and likely be fixed later. + +- On Windows there is a CDC driver installer option. This is an optional USB virtual serial + port useful, for example, for updating your GPS configuration using U-Blox u-Center software. + But it is NOT required to configure boards. If not installed, virtual serial port features + will not be available. This driver is not signed by Microsoft, but in fact it uses serial + port drivers from Windows and only driver information INF file is supplied by the OpenPilot. + Hence it is safe to install. + +- Due to changes in USB descriptors to support new features, USB drivers on Windows must be + updated. If after Rescue or Wizard or Auto-Update button the GCS cannot connect to the board, + it may be due to this issue. To resolve you should remove old drivers (ones with yellow + exclamation mark) and allow Windows to find them again. Here is how: + + Windows XP: + - click on the desktop "My Computer" icon and select "Properties"; + - select the "Hardware" tab by clicking on it once; + - select the "Device Manager" tab by clicking on it; + - scroll down the list until you see the "Universal Serial Bus Controllers" selection. + Click it to expand the list of USB drivers. Right-click on the driver(s) you wish to + uninstall and select the "Uninstall" function. The driver will be uninstalled. + + Windows 7/Vista: + - on the desktop right-click the "Computer" icon and select "Properties"; + - select "Device Manager" in the upper left-hand corner of the window; + - scroll down the list until you see the "Universal Serial Bus Controllers" selection. + Click it once to expand the list of USB drivers. Right-click on the driver(s) you wish + to uninstall and select the "Uninstall" function. The driver will be uninstalled. + + Then disconnect the board from USB, wait few seconds and connect it back. Windows should find new + drivers and install them properly. + +- GCS now uses system default language (only French and English are available yet, please + contribute). You can choose language using GCS Options dialog if you have existing GCS + configuaration. + +- This release provides only CC3D-class features + radio. For example, it does NOT use + magnetometers to correct yaw and uses simple complimentary filter for attitude estimation. + So you should expect from it only CC3D-like performance. More advanced features will be + enabled step by step in the following releases with some help from new contributors, + we hope. Remember that the first Revo hardware batch was inended for developers, not + end users. + +- Lots of help tooltips were added to the GCS. Try watching them when tuning. + +- If GCS crashes when switching to the Flight data tab, it usually means your PC needs newer + video drivers. That tab contains ModelView widget which uses OpenGL. It is known to crash + in some cases. + +- Sensor calibration is not final. It will be reworked completely to increase its accuracy + and make it easier to use. + +- AltitudeHold mode is enabled, but it is not officially released. Do not expect it to be of + production quality. But you may play with it and report your issues and suggestions. It is + recommended to use some foam to protect baro sensor from wind and light. Also note that + throttle stick in AltitudeHold mode is used to control vertical velocity. + +- Tuning your system please set PIDs as tight as possible for better stabilisation. To soften + the stick response if necessary use new Responsiveness options. This will result in better + stabilisation, and at the same time soft or sharp response according to your preferences. + +- There is no configuration options for Radio module in the Revo config except for Radio + enable/disable and output power. This is intentional because all configuration should be + done using its paired ground OPLink coordinator. Enable radio in the Revo, save and + disconnect Revo from USB. Power it from external supply to continue. Then connect OPLink + board to USB and scroll down the GCS config widget to find OPLink icon in the end of list. + This icon is only available when OPLink is connected and recognised, this also requires new + bootloader and matching to Revo and GCS firmware on the OPLink board. To pair select the Revo + side Radio address in the list of found boards, select it, click Add to add to the list of + paired radios and click Save. After USB unplugging and plugging back your OPLink should show + "Connected", and you can continue with configuration. Flight code changes: - initial version of Revo code; @@ -72,14 +175,15 @@ GCS code changes: - hardware options are now dynamically enabled/disabled to allow supported configurations only; - new artwork for all boards everywhere; - optimised some 3D models; -- new About dialog showing version info and contrubutors list; +- new About dialog showing version info and contributors list; - fixed badly broken HiTL options dialog; - fixed compilation problem on OSX, now GCS should be compatible with OSX 10.5+; - major vehicle config cleanup with lazy creation (speeds up GCS start); - UI config pages improvements (responsiveness, etc) - new auto-update feature added, *.opfw firmware files removed from distributables; - anti-aliased scope plugin; -- numerous code fixes and cleanups (too many to list here). +- numerous code fixes and cleanups (too many to list here); +- USB HID code is replaced by new cross-platform hidapi library to fix old Linux/OSX problems. Common parts: - added simple toolchain install make targets; @@ -96,6 +200,7 @@ Common parts: - CLEAN_BUILD make option is deprecated, use 'package' or 'clean_package' instead; - simposix elf is now included into linux distribution and can be run with default GCS settings; - revised 'make help' message; +- updated Windows driver to support Revolution and use correct board names. Android GCS: - not officially released yet; From 3b6fcefca6f5a1c980a734ff39e97cc8ef0937b8 Mon Sep 17 00:00:00 2001 From: Kevin Vertucio Date: Sun, 2 Jun 2013 08:18:40 -0400 Subject: [PATCH 093/120] removed bootstrap from utility --- .../openpilotgcs/src/plugins/coreplugin/CREDITS-utility.html | 3 --- 1 file changed, 3 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/coreplugin/CREDITS-utility.html b/ground/openpilotgcs/src/plugins/coreplugin/CREDITS-utility.html index 0041a5246..4e6258b52 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/CREDITS-utility.html +++ b/ground/openpilotgcs/src/plugins/coreplugin/CREDITS-utility.html @@ -2,8 +2,6 @@ CREDITS Utility - - - - -

Author Dialog authorModel Utility

-

This utility will parse a \n delimited list of names and generate ListElement components for entry into the QML model located in /qml/AuthorsModel.qml.

-
-
- - -
- - - - - - -

This is a credits file of people that are or have been key contributors to the OpenPilot project. Without the work of the people in this list, OpenPilot would not be what it is today.

- -

This list is sorted alphabetically by name

- -
Connor Abbott
-David Ankers
-Sergiy Anikeyev
-Pedro Assuncao
-Fredrik Arvidsson
-Werner Backes
-Jose Barros
-Pete  Boehl
-David Carlson
-James Cotton
-Steve Doll
-Piotr Esden-Tempski
-Richard Flay
-Peter Farnworth
-Ed Faulkner
-Darren Furniss
-Frederic Goddeeris
-Daniel Godin
-Bani Greyling
-Nuno Guedes
-Erik Gustavsson
-Peter Gunnarsson
-Dean Hall
-Joe Hlebasko
-Andy Honecker
-Ryan Hunt
-Mark James
-Sami Korhonen
-Thorsten Klose
-Hallvard Kristiansen
-Edouard Lafargue
-Mike Labranche
-Fredrik Larsson
-Pablo Lema
-David Llama
-Matt Lipski
-Les Newell
-Ken Northup
-Greg Matthews
-Guy McCaldin
-Gary Mortimer
-Alessio Morale
-Cathy Moss
-Angus Peart
-Dmytro Poplavskiy
-Eric Price
-Richard Querin
-Randy Ram
-Philippe Renon
-Laurent Ribon
-Mathieu Rondonneau
-Julien Rouviere
-Jackson Russell
-Zik Saleeba
-Professor Dale Schinstock
-Professor Kenn Sebesta
-Oleg Semyonov
-Stacey Sheldon
-Troy Schultz
-Dr. Erhard Siegl
-Mike Smith
-Alex Sowa
-Pete Stapley
-Vova Starikh
-Rowan Taubitz
-Andrew Thoms
-Philippe Vanhaesendonck
-Jasper van Loenen
-Vassilis Varveropoulos
-Kevin Vertucio
-Alex Vrubel
-Brian Webb
-Justin Welander
-Mat Wellington
-Kendal Wells
-David Willis
-Dmitriy Zaitsev
-
- - diff --git a/ground/openpilotgcs/src/plugins/coreplugin/core.qrc b/ground/openpilotgcs/src/plugins/coreplugin/core.qrc index 13cd18868..8a4418c53 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/core.qrc +++ b/ground/openpilotgcs/src/plugins/coreplugin/core.qrc @@ -50,7 +50,6 @@ images/optionsicon.png images/helpicon.png images/openpiloticon.png - CREDITS.html images/ah.png images/config.png images/flight.png diff --git a/ground/openpilotgcs/src/plugins/coreplugin/qml/AuthorsModel.qml b/ground/openpilotgcs/src/plugins/coreplugin/qml/AuthorsModel.qml deleted file mode 100644 index 226a186b5..000000000 --- a/ground/openpilotgcs/src/plugins/coreplugin/qml/AuthorsModel.qml +++ /dev/null @@ -1,165 +0,0 @@ -/* -This list model was created for the AuthorsDialog. -*/ -import QtQuick 1.1 - -ListModel { - - ListElement{ name:"Connor Abbott" } - - ListElement{ name:"David Ankers" } - - ListElement{ name:"Sergiy Anikeyev" } - - ListElement{ name:"Pedro Assuncao" } - - ListElement{ name:"Fredrik Arvidsson" } - - ListElement{ name:"Werner Backes" } - - ListElement{ name:"Jose Barros" } - - ListElement{ name:"Pete Boehl" } - - ListElement{ name:"David Carlson" } - - ListElement{ name:"James Cotton" } - - ListElement{ name:"Steve Doll" } - - ListElement{ name:"Piotr Esden-Tempski" } - - ListElement{ name:"Richard Flay" } - - ListElement{ name:"Peter Farnworth" } - - ListElement{ name:"Ed Faulkner" } - - ListElement{ name:"Darren Furniss" } - - ListElement{ name:"Frederic Goddeeris" } - - ListElement{ name:"Daniel Godin" } - - ListElement{ name:"Bani Greyling" } - - ListElement{ name:"Nuno Guedes" } - - ListElement{ name:"Erik Gustavsson" } - - ListElement{ name:"Peter Gunnarsson" } - - ListElement{ name:"Dean Hall" } - - ListElement{ name:"Joe Hlebasko" } - - ListElement{ name:"Andy Honecker" } - - ListElement{ name:"Ryan Hunt" } - - ListElement{ name:"Mark James" } - - ListElement{ name:"Sami Korhonen" } - - ListElement{ name:"Thorsten Klose" } - - ListElement{ name:"Rick King" } - - ListElement{ name:"Hallvard Kristiansen" } - - ListElement{ name:"Edouard Lafargue" } - - ListElement{ name:"Mike Labranche" } - - ListElement{ name:"Fredrik Larsson" } - - ListElement{ name:"Pablo Lema" } - - ListElement{ name:"David Llama" } - - ListElement{ name:"Matt Lipski" } - - ListElement{ name:"Les Newell" } - - ListElement{ name:"Ken Northup" } - - ListElement{ name:"Greg Matthews" } - - ListElement{ name:"Guy McCaldin" } - - ListElement{ name:"Gary Mortimer" } - - ListElement{ name:"Alessio Morale" } - - ListElement{ name:"Cathy Moss" } - - ListElement{ name:"Angus Peart" } - - ListElement{ name:"John Pike" } - - ListElement{ name:"Dmytro Poplavskiy" } - - ListElement{ name:"Eric Price" } - - ListElement{ name:"Richard Querin" } - - ListElement{ name:"Randy Ram" } - - ListElement{ name:"Philippe Renon" } - - ListElement{ name:"Laurent Ribon" } - - ListElement{ name:"Mathieu Rondonneau" } - - ListElement{ name:"Julien Rouviere" } - - ListElement{ name:"Jackson Russell" } - - ListElement{ name:"Zik Saleeba" } - - ListElement{ name:"Professor Dale Schinstock" } - - ListElement{ name:"Professor Kenn Sebesta" } - - ListElement{ name:"Oleg Semyonov" } - - ListElement{ name:"Stacey Sheldon" } - - ListElement{ name:"Troy Schultz" } - - ListElement{ name:"Dr. Erhard Siegl" } - - ListElement{ name:"Mike Smith" } - - ListElement{ name:"Alex Sowa" } - - ListElement{ name:"Pete Stapley" } - - ListElement{ name:"Vova Starikh" } - - ListElement{ name:"Rowan Taubitz" } - - ListElement{ name:"Andrew Thoms" } - - ListElement{ name:"Philippe Vanhaesendonck" } - - ListElement{ name:"Jasper van Loenen" } - - ListElement{ name:"Vassilis Varveropoulos" } - - ListElement{ name:"Kevin Vertucio" } - - ListElement{ name:"Alex Vrubel" } - - ListElement{ name:"Brian Webb" } - - ListElement{ name:"Justin Welander" } - - ListElement{ name:"Mat Wellington" } - - ListElement{ name:"Kendal Wells" } - - ListElement { name: "David Willis" } - - ListElement{ name:"Dmitriy Zaitsev" } -} \ No newline at end of file From 38cf0bf8b0ffa198460aa4dd1fe4bde836f67d1b Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Wed, 5 Jun 2013 17:55:12 +0300 Subject: [PATCH 111/120] Update release notes (JIRA issues fixed) --- WHATSNEW.txt | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index a1755dc15..26dc5dbf3 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -169,14 +169,15 @@ Due to major rework of all code and integration of Revo code into mainline list above. Some of them can be found using this link: http://progress.openpilot.org/issues/?filter=10860 -OP-678, OP-693, OP-719, OP-747, OP-761, OP-769, OP-770, OP-772, OP-792, -OP-807, OP-812, OP-816, OP-817, OP-820, OP-821, OP-843, OP-846, OP-854, -OP-855, OP-856, OP-864, OP-867, OP-871, OP-873, OP-874, OP-875, OP-879, -OP-885, OP-886, OP-888, OP-889, OP-890, OP-891, OP-892, OP-893, OP-894, -OP-895, OP-896, OP-897, OP-898, OP-899, OP-900, OP-903, OP-905, OP-906, -OP-907, OP-910, OP-912, OP-917, OP-920, OP-925, OP-926, OP-928, OP-935, -OP-936, OP-939, OP-952, OP-955, OP-957, OP-968, OP-969, OP-970, OP-977, -OP-980 +OP-678, OP-693, OP-719, OP-726, OP-727, OP-747, OP-761, OP-769, OP-770, +OP-772, OP-792, OP-804, OP-807, OP-812, OP-816, OP-817, OP-820, OP-821, +OP-843, OP-846, OP-854, OP-855, OP-856, OP-861, OP-864, OP-867, OP-871, +OP-873, OP-874, OP-875, OP-879, OP-885, OP-886, OP-888, OP-889, OP-890, +OP-891, OP-892, OP-893, OP-894, OP-895, OP-896, OP-897, OP-898, OP-899, +OP-900, OP-903, OP-905, OP-906, OP-907, OP-910, OP-912, OP-917, OP-920, +OP-925, OP-926, OP-928, OP-935, OP-936, OP-939, OP-952, OP-955, OP-957, +OP-968, OP-969, OP-970, OP-977, OP-980, OP-981, OP-982, OP-983, OP-987, +OP-988, OP-989 Short summary of changes. For a complete list see the git log. From a7d1e2b29844f95dd7848cd37ce927196aedcac6 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Wed, 5 Jun 2013 23:21:54 +0300 Subject: [PATCH 112/120] OP-910: fix line endings and whitespaces (didn't work on Linux) --- ground/.gitattributes | 9 +- .../src/plugins/coreplugin/authorsdialog.py | 104 +++++++++--------- 2 files changed, 58 insertions(+), 55 deletions(-) diff --git a/ground/.gitattributes b/ground/.gitattributes index 0417f63e1..42263f54b 100644 --- a/ground/.gitattributes +++ b/ground/.gitattributes @@ -3,6 +3,9 @@ # http://wiki.openpilot.org/display/Doc/Coding+Style # +*.pri text eol=crlf +*.pro text eol=crlf + *.c text eol=crlf *.cpp text eol=crlf *.h text eol=crlf @@ -13,9 +16,9 @@ *.qml text eol=crlf *.pluginspec text eol=crlf -*.pri text eol=crlf -*.pro text eol=crlf - *.h.template text eol=crlf *.c.template text eol=crlf *.cpp.template text eol=crlf +*.qml.template text eol=crlf + +*.py text eol=lf diff --git a/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.py b/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.py index 1f4910e6a..27cc98290 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.py +++ b/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.py @@ -1,52 +1,52 @@ -#!/usr/bin/env python -# -# Helper function to generate a QML list of contributors -# -# (c) 2013, The OpenPilot Team, http://www.openpilot.org -# See also: The GNU Public License (GPL) Version 3 -# - -import optparse -import sys - -def create_qml_file(args): - """This function reads input and template files and writes output QML file""" - - assert args.infile is not None - assert args.outfile is not None - assert args.template is not None - - with open(args.infile, "rt") as input_file: - names = input_file.readlines() - - names_list = "" - for name in names: - if name.strip(): - names_list += " ListElement { name: \"" + name.strip() + "\" }\n" - - with open(args.template, "rt") as template_file, open(args.outfile, "wt") as output_file: - template = template_file.read() - output_file.write(template.replace("${LIST_ELEMENTS}\n", names_list)) - - return 0 - -def main(): - """Helper function to generate a QML list of contributors""" - - parser = optparse.OptionParser(description = main.__doc__); - - parser.add_option('--infile', action='store', - help='name of input file, one name per line'); - parser.add_option('--outfile', action='store', - help='name of output QML file'); - parser.add_option('--template', action='store', - help='name of QML template file'); - (args, positional_args) = parser.parse_args() - - if (len(positional_args) != 0) or (len(sys.argv) == 1): - parser.error("incorrect number of arguments, try --help for help") - - return create_qml_file(args) - -if __name__ == "__main__": - sys.exit(main()) +#!/usr/bin/env python +# +# Helper function to generate a QML list of contributors +# +# (c) 2013, The OpenPilot Team, http://www.openpilot.org +# See also: The GNU Public License (GPL) Version 3 +# + +import optparse +import sys + +def create_qml_file(args): + """This function reads input and template files and writes output QML file""" + + assert args.infile is not None + assert args.outfile is not None + assert args.template is not None + + with open(args.infile, "rt") as input_file: + names = input_file.readlines() + + names_list = "" + for name in names: + if name.strip(): + names_list += " ListElement { name: \"" + name.strip() + "\" }\n" + + with open(args.template, "rt") as template_file, open(args.outfile, "wt") as output_file: + template = template_file.read() + output_file.write(template.replace("${LIST_ELEMENTS}", names_list.rstrip())) + + return 0 + +def main(): + """Helper function to generate a QML list of contributors""" + + parser = optparse.OptionParser(description = main.__doc__); + + parser.add_option('--infile', action='store', + help='name of input file, one name per line'); + parser.add_option('--outfile', action='store', + help='name of output QML file'); + parser.add_option('--template', action='store', + help='name of QML template file'); + (args, positional_args) = parser.parse_args() + + if (len(positional_args) != 0) or (len(sys.argv) == 1): + parser.error("incorrect number of arguments, try --help for help") + + return create_qml_file(args) + +if __name__ == "__main__": + sys.exit(main()) From 13e7f51174b4036b05964aab4b29571750c2be05 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Wed, 5 Jun 2013 23:25:50 +0300 Subject: [PATCH 113/120] OP-910: fix circular dependencies --- ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.pri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.pri b/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.pri index c42d800bd..96d7457ef 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.pri +++ b/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.pri @@ -25,7 +25,7 @@ include(../../python.pri) --infile=\"$$AUTHORS_SOURCE\" \ --template=\"$$AUTHORS_TEMPLATE\" \ --outfile=\"$$AUTHORS_FILE\" - authors.depends = FORCE + authors.depends = $$AUTHORS_SOURCE QMAKE_EXTRA_TARGETS += authors # Hook authors target in between qmake's Makefile update and From d54e507ffb66f693b39ad05b95c886c60df430a2 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Thu, 6 Jun 2013 00:46:59 +0300 Subject: [PATCH 114/120] OP-910: don't use python 2.7+ features (make it compatible with 2.6) --- ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.py b/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.py index 27cc98290..1b2ed397b 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.py +++ b/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.py @@ -24,8 +24,10 @@ def create_qml_file(args): if name.strip(): names_list += " ListElement { name: \"" + name.strip() + "\" }\n" - with open(args.template, "rt") as template_file, open(args.outfile, "wt") as output_file: + with open(args.template, "rt") as template_file: template = template_file.read() + + with open(args.outfile, "wt") as output_file: output_file.write(template.replace("${LIST_ELEMENTS}", names_list.rstrip())) return 0 From a834226968d3a548592efb20a2d3bc3a2135797a Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Thu, 6 Jun 2013 02:20:32 +0300 Subject: [PATCH 115/120] OP-910: fix mixed line endings in generated QML --- ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.py b/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.py index 1b2ed397b..c5fe0c736 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.py +++ b/ground/openpilotgcs/src/plugins/coreplugin/authorsdialog.py @@ -22,12 +22,12 @@ def create_qml_file(args): names_list = "" for name in names: if name.strip(): - names_list += " ListElement { name: \"" + name.strip() + "\" }\n" + names_list += " ListElement { name: \"" + name.strip() + "\" }\r\n" - with open(args.template, "rt") as template_file: + with open(args.template, "rb") as template_file: template = template_file.read() - with open(args.outfile, "wt") as output_file: + with open(args.outfile, "wb") as output_file: output_file.write(template.replace("${LIST_ELEMENTS}", names_list.rstrip())) return 0 From d2fae1abed0e6b23121bb8b6711df6606657359b Mon Sep 17 00:00:00 2001 From: Mathieu Rondonneau Date: Wed, 5 Jun 2013 19:15:47 -0700 Subject: [PATCH 116/120] OP-976: fixing function name in the macro although don't have any effect since the linker directives are local. --- flight/pios/inc/pios_initcall.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flight/pios/inc/pios_initcall.h b/flight/pios/inc/pios_initcall.h index 8ec6c96f3..8a5482b04 100644 --- a/flight/pios/inc/pios_initcall.h +++ b/flight/pios/inc/pios_initcall.h @@ -86,7 +86,7 @@ extern void StartModules(); __attribute__((__section__(".initcall" level ".init"))) = fn #define __define_module_initcall(level, ifn, sfn) \ - static initmodule_t __initcall_##fn __attribute__((__used__)) \ + static initmodule_t __initcall_##ifn __attribute__((__used__)) \ __attribute__((__section__(".initcall" level ".init"))) = { .fn_minit = ifn, .fn_tinit = sfn }; #define MODULE_INITCALL(ifn, sfn); __define_module_initcall("module", ifn, sfn) From a8c946dcb248a6f2270b719d128f093a1c2e707d Mon Sep 17 00:00:00 2001 From: Mathieu Rondonneau Date: Wed, 5 Jun 2013 19:46:55 -0700 Subject: [PATCH 117/120] OP-976: Fix uncrustify changes that put a space before the ";" in the macro --- flight/pios/inc/pios_initcall.h | 6 +++--- flight/pios/osx/inc/pios_initcall.h | 2 +- flight/pios/win32/inc/pios_initcall.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/flight/pios/inc/pios_initcall.h b/flight/pios/inc/pios_initcall.h index 8a5482b04..d44f8f56f 100644 --- a/flight/pios/inc/pios_initcall.h +++ b/flight/pios/inc/pios_initcall.h @@ -56,7 +56,7 @@ extern initmodule_t __module_initcall_start[], __module_initcall_end[]; extern void InitModules(); extern void StartModules(); -#define MODULE_INITCALL(ifn, sfn); +#define MODULE_INITCALL(ifn, sfn) #define MODULE_TASKCREATE_ALL \ { \ @@ -87,9 +87,9 @@ extern void StartModules(); #define __define_module_initcall(level, ifn, sfn) \ static initmodule_t __initcall_##ifn __attribute__((__used__)) \ - __attribute__((__section__(".initcall" level ".init"))) = { .fn_minit = ifn, .fn_tinit = sfn }; + __attribute__((__section__(".initcall" level ".init"))) = { .fn_minit = ifn, .fn_tinit = sfn } -#define MODULE_INITCALL(ifn, sfn); __define_module_initcall("module", ifn, sfn) +#define MODULE_INITCALL(ifn, sfn) __define_module_initcall("module", ifn, sfn) #define MODULE_INITIALISE_ALL \ { for (initmodule_t *fn = __module_initcall_start; fn < __module_initcall_end; fn++) { \ diff --git a/flight/pios/osx/inc/pios_initcall.h b/flight/pios/osx/inc/pios_initcall.h index 53142e900..6b1c4421a 100644 --- a/flight/pios/osx/inc/pios_initcall.h +++ b/flight/pios/osx/inc/pios_initcall.h @@ -51,7 +51,7 @@ extern initmodule_t __module_initcall_start[], __module_initcall_end[]; extern void InitModules(); extern void StartModules(); -#define MODULE_INITCALL(ifn, sfn); +#define MODULE_INITCALL(ifn, sfn) #define MODULE_TASKCREATE_ALL \ { \ diff --git a/flight/pios/win32/inc/pios_initcall.h b/flight/pios/win32/inc/pios_initcall.h index 935004b92..e60b8755d 100644 --- a/flight/pios/win32/inc/pios_initcall.h +++ b/flight/pios/win32/inc/pios_initcall.h @@ -38,7 +38,7 @@ * and we cannot define a linker script for each of them atm */ -#define MODULE_INITCALL(ifn, sfn); +#define MODULE_INITCALL(ifn, sfn) #define MODULE_TASKCREATE_ALL From 45391abd550b02c293c816c85c2c572115939c01 Mon Sep 17 00:00:00 2001 From: Mathieu Rondonneau Date: Wed, 5 Jun 2013 19:48:56 -0700 Subject: [PATCH 118/120] OP-976: RE-run uncrustify --- flight/pios/inc/pios_initcall.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flight/pios/inc/pios_initcall.h b/flight/pios/inc/pios_initcall.h index d44f8f56f..2b9f32418 100644 --- a/flight/pios/inc/pios_initcall.h +++ b/flight/pios/inc/pios_initcall.h @@ -89,7 +89,7 @@ extern void StartModules(); static initmodule_t __initcall_##ifn __attribute__((__used__)) \ __attribute__((__section__(".initcall" level ".init"))) = { .fn_minit = ifn, .fn_tinit = sfn } -#define MODULE_INITCALL(ifn, sfn) __define_module_initcall("module", ifn, sfn) +#define MODULE_INITCALL(ifn, sfn) __define_module_initcall("module", ifn, sfn) #define MODULE_INITIALISE_ALL \ { for (initmodule_t *fn = __module_initcall_start; fn < __module_initcall_end; fn++) { \ From b6312b3faa36c9406330ef1bd5b7691e33386f64 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Thu, 6 Jun 2013 11:12:21 +0300 Subject: [PATCH 119/120] OP-910: update python path comment in make/tools.mk to keep in sync --- make/tools.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/tools.mk b/make/tools.mk index d1245ba17..5abc12cea 100644 --- a/make/tools.mk +++ b/make/tools.mk @@ -81,7 +81,7 @@ endif GTEST_URL := http://wiki.openpilot.org/download/attachments/18612236/gtest-1.6.0.zip -# Changing PYTHON_DIR, also update it in ground\openpilotgcs\src\app\gcsversioninfo.pri +# Changing PYTHON_DIR, also update it in ground/openpilotgcs/src/python.pri ARM_SDK_DIR := $(TOOLS_DIR)/gcc-arm-none-eabi-4_7-2013q1 QT_SDK_DIR := $(TOOLS_DIR)/qt-4.8.4 MINGW_DIR := $(TOOLS_DIR)/mingw-4.4.0 From 68e18dcb383a940913300e653e00dc08de6993f8 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Thu, 6 Jun 2013 11:16:47 +0300 Subject: [PATCH 120/120] OP-910: fix line endings in QML template --- .../coreplugin/qml/AuthorsModel.qml.template | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/coreplugin/qml/AuthorsModel.qml.template b/ground/openpilotgcs/src/plugins/coreplugin/qml/AuthorsModel.qml.template index 4ac54838b..63d7e45cc 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/qml/AuthorsModel.qml.template +++ b/ground/openpilotgcs/src/plugins/coreplugin/qml/AuthorsModel.qml.template @@ -1,8 +1,8 @@ -/* -This list model was created for the AuthorsDialog. -*/ -import QtQuick 1.1 - -ListModel { -${LIST_ELEMENTS} -} +/* +This list model was created for the AuthorsDialog. +*/ +import QtQuick 1.1 + +ListModel { +${LIST_ELEMENTS} +}