|
| 1 | +// Copyright lowRISC contributors. |
| 2 | +// Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| 3 | +// SPDX-License-Identifier: Apache-2.0 |
| 4 | + |
| 5 | +#include "kernel_driver.hh" |
| 6 | + |
| 7 | +#include <libudev.h> |
| 8 | +#include <libusb-1.0/libusb.h> |
| 9 | + |
| 10 | +#include <iostream> |
| 11 | + |
| 12 | +namespace ftdi { |
| 13 | + |
| 14 | +enum { kFtdiVid = 0x0403 }; |
| 15 | + |
| 16 | +// Use libusb to temporarily detach ftdi_sio from every interface of |
| 17 | +// every FTDI USB device. The kernel driver is re-attached automatically when |
| 18 | +// the D2XX / libft4222 handle is closed. |
| 19 | +void detach_ftdi_kernel_drivers(uint16_t pid) { |
| 20 | + libusb_context* ctx = nullptr; |
| 21 | + if (libusb_init(&ctx) != LIBUSB_SUCCESS) { |
| 22 | + std::cerr << "libusb_init failed\n"; |
| 23 | + return; |
| 24 | + } |
| 25 | + |
| 26 | + libusb_device** devs = nullptr; |
| 27 | + ssize_t cnt = libusb_get_device_list(ctx, &devs); |
| 28 | + if (cnt < 0) { |
| 29 | + libusb_exit(ctx); |
| 30 | + return; |
| 31 | + } |
| 32 | + |
| 33 | + for (ssize_t i = 0; i < cnt; i++) { |
| 34 | + libusb_device_descriptor desc{}; |
| 35 | + if (libusb_get_device_descriptor(devs[i], &desc) != LIBUSB_SUCCESS) continue; |
| 36 | + if (desc.idVendor != kFtdiVid || desc.idProduct != pid) continue; |
| 37 | + |
| 38 | + libusb_device_handle* handle = nullptr; |
| 39 | + if (libusb_open(devs[i], &handle) != LIBUSB_SUCCESS) continue; |
| 40 | + |
| 41 | + libusb_config_descriptor* config = nullptr; |
| 42 | + if (libusb_get_active_config_descriptor(devs[i], &config) == LIBUSB_SUCCESS) { |
| 43 | + for (uint8_t j = 0; j < config->bNumInterfaces; j++) { |
| 44 | + if (libusb_kernel_driver_active(handle, j) != 1) continue; |
| 45 | + int ret = libusb_detach_kernel_driver(handle, j); |
| 46 | + if (ret != LIBUSB_SUCCESS) { |
| 47 | + std::cerr << "Failed to detach kernel driver on interface " << (int)j << ": " |
| 48 | + << libusb_error_name(ret) << "\n"; |
| 49 | + } |
| 50 | + } |
| 51 | + libusb_free_config_descriptor(config); |
| 52 | + } |
| 53 | + |
| 54 | + libusb_close(handle); |
| 55 | + } |
| 56 | + |
| 57 | + libusb_free_device_list(devs, 1); |
| 58 | + libusb_exit(ctx); |
| 59 | +} |
| 60 | + |
| 61 | +} // namespace ftdi |
0 commit comments