Rev 799 | Rev 901 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
////// Copyright 2013 user890104////// This file is part of emCORE.//// emCORE 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 2 of the// License, or (at your option) any later version.//// emCORE 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 emCORE. If not, see <http://www.gnu.org/licenses/>.////#include "global.h"#include "emcore.h"#include "util.h"#include "usb.h"libusb_context *usb_ctx = NULL;libusb_device_handle *usb_handle = NULL;uint8_t usb_iface_num = 0;int32_t usb_init(void) {int32_t res;#ifdef DEBUGfprintf(stderr, "Initialising USB library...\n");#endifres = libusb_init(&usb_ctx);if (res != LIBUSB_SUCCESS) {return res;}#ifdef DEBUGfprintf(stderr, "USB library initialized!\n");libusb_set_debug(usb_ctx, 3);#endifreturn LIBUSB_SUCCESS;}int32_t usb_find(uint16_t vendor_id, uint16_t product_id, uint8_t *reattach) {libusb_device **devs, *dev = NULL;ssize_t devs_cnt, i, j, k, l;int32_t res;uint8_t found;struct libusb_device_descriptor dev_desc;struct libusb_config_descriptor *cfg_desc;const struct libusb_interface *iface;const struct libusb_interface_descriptor *iface_desc;#ifdef DEBUGfprintf(stderr, "Getting USB device list...\n");#endifdevs_cnt = libusb_get_device_list(usb_ctx, &devs);if (devs_cnt < 0) {return devs_cnt;}#ifdef DEBUGfprintf(stderr, "Found %Zd USB devices!\n", devs_cnt);#endiffor (i = 0; i < devs_cnt; ++i) {dev = devs[i];#ifdef DEBUGfprintf(stderr, "Getting device descriptor of USB device %d...\n", i);#endifres = libusb_get_device_descriptor(dev, &dev_desc);if (res != LIBUSB_SUCCESS) {#ifdef DEBUGfprintf(stderr, "Unable to get device descriptor of device %d!\n", i);#endifcontinue;}#ifdef DEBUGfprintf(stderr, "[%04x:%04x] bus %d, device %d, USB ver. %04x\n", dev_desc.idVendor,dev_desc.idProduct, libusb_get_bus_number(dev),libusb_get_device_address(dev), dev_desc.bcdUSB);#endifif (dev_desc.idVendor != vendor_id || dev_desc.idProduct != product_id) {continue;}#ifdef DEBUGfprintf(stderr, "Found emCORE USB device!\n");#endifif (!dev_desc.bNumConfigurations) {#ifdef DEBUGfprintf(stderr, "No configs found...\n");#endifcontinue;}#ifdef DEBUGfprintf(stderr, "Found %Zd configs...\n", dev_desc.bNumConfigurations);#endiffor (j = 0; j < dev_desc.bNumConfigurations; ++j) {#ifdef DEBUGfprintf(stderr, "Getting config descriptor %Zd of device...\n", j);#endifres = libusb_get_config_descriptor(dev, j, &cfg_desc);if (res != LIBUSB_SUCCESS) {return res;}if (!cfg_desc->bNumInterfaces) {#ifdef DEBUGfprintf(stderr, "No interfaces found...\n");#endifcontinue;}for (k = 0; k < cfg_desc->bNumInterfaces; ++k) {iface = &cfg_desc->interface[k];if (!iface->num_altsetting) {#ifdef DEBUGfprintf(stderr, "No altsettings found...\n");#endifcontinue;}for (l = 0; l < iface->num_altsetting; ++l) {iface_desc = &iface->altsetting[l];if (iface_desc->bInterfaceClass != EMCORE_USB_INTERFACE_CLASS ||iface_desc->bInterfaceSubClass != EMCORE_USB_INTERFACE_SUB_CLASS ||iface_desc->bInterfaceProtocol != EMCORE_USB_INTERFACE_PROTOCOL) {#ifdef DEBUGfprintf(stderr, "Wrong interface class (%02X %02X %02X), trying next device...\n", iface_desc->bInterfaceClass, iface_desc->bInterfaceSubClass, iface_desc->bInterfaceProtocol);#endifcontinue;}#ifdef DEBUGfprintf(stderr, "emCORE Debugger interface at %Zd\n", iface_desc->bInterfaceNumber);#endifusb_iface_num = iface_desc->bInterfaceNumber;found = 1;goto outside_search_loop;}}}}outside_search_loop:if (found) {res = usb_open(dev, reattach);}else {fprintf(stderr, "emCORE Debugger interface not found!\n");res = EMCORE_ERROR_NO_DEVICE;}#ifdef DEBUGfprintf(stderr, "Freeing device list...\n");#endiflibusb_free_device_list(devs, 1);return res;}int32_t usb_open(libusb_device *dev, uint8_t *reattach) {int32_t res;#ifdef DEBUGfprintf(stderr, "Opening USB device...\n");#endifres = libusb_open(dev, &usb_handle);if (res != LIBUSB_SUCCESS) {return res;}#ifdef DEBUGfprintf(stderr, "USB device opened!\n");fprintf(stderr, "Setting USB configuration 1...\n");#endifres = libusb_set_configuration(usb_handle, 1);if (res != LIBUSB_SUCCESS) {return res;}#ifdef DEBUGfprintf(stderr, "USB configuration set!\n");#endifres = libusb_kernel_driver_active(usb_handle, 0);if (res < 0) {return res;}if (res == 1) {*reattach = 1;res = libusb_detach_kernel_driver(usb_handle, 0);}if (res != LIBUSB_SUCCESS) {return res;}#ifdef DEBUGfprintf(stderr, "Claiming interface 0...\n");#endifres = libusb_claim_interface(usb_handle, 0);if (res != LIBUSB_SUCCESS) {return res;}#ifdef DEBUGfprintf(stderr, "Interface claimed successfully!\n");#endifreturn LIBUSB_SUCCESS;}int32_t usb_control_transfer(uint8_t rq_type, void *data, size_t length) {int32_t res;res = libusb_control_transfer(usb_handle, rq_type, 0, 0, usb_iface_num, (unsigned char *)data, length, 10000);if (res < 0) {return res;}if ((size_t)res != length) {return EMCORE_ERROR_INCOMPLETE;}return LIBUSB_SUCCESS;}int32_t usb_close(uint8_t reattach) {int32_t res;#ifdef DEBUGfprintf(stderr, "Releasing USB interface...\n");#endifres = libusb_release_interface(usb_handle, 0);if (res != LIBUSB_SUCCESS) {return res;}#ifdef DEBUGfprintf(stderr, "Released interface successfully!\n");#endifif (reattach) {#ifdef DEBUGfprintf(stderr, "Reattaching kernel driver...\n");#endifres = libusb_attach_kernel_driver(usb_handle, 0);if (res == LIBUSB_SUCCESS) {#ifdef DEBUGfprintf(stderr, "Reattached successfully!\n");#endif}else {print_error(res);res = LIBUSB_SUCCESS;}}#ifdef DEBUGfprintf(stderr, "Closing USB device handle...\n");#endiflibusb_close(usb_handle);return res;}void usb_exit(void) {#ifdef DEBUGfprintf(stderr, "Deinitializing USB library...\n");#endiflibusb_exit(usb_ctx);}int32_t usb_destroy(uint8_t reattach) {int32_t res = LIBUSB_SUCCESS;if (usb_handle) {res = usb_close(reattach);}if (usb_ctx) {usb_exit();}return res;}