关闭 USB 端口的电源
Turn off power to a USB port
我正在寻找一种方法来关闭(然后重新打开)USB 端口的 power。解决方案可以是 C、bash 等。我正在为 armhf 使用 BeagleBone 运行ning 32 位 Ubuntu 16.04。
> uname -srvm
Linux 4.4.6-ti-r15 #1 SMP Tue Apr 5 12:32:22 UTC 2016 armv7l
我尝试了很多在 Whosebug 和 AskUbuntu 上讨论的事情,包括:
#include <linux/usbdevice_fs.h>
int main(void)
{
int fd = open( "/dev/bus/usb/001/002", O_WRONLY );
if (fd < 0) return 1;
int rc = ioctl( fd, USBDEVFS_RESET, 0 );
if (rc < 0) return 2;
close( fd );
return 0;
}
我需要关闭(并最终重新打开)的 USB 设备是 Champtek FS310 条形码 reader 当我 运行 lsusb 时它显示为磁卡条 reader :
> lsusb
Bus 001 Device 002: ID 040b:6543 Weltrend Semiconductor Manhattan Magnetic Card Strip Reader
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
> lsusb -t
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=musb-hdrc/1p, 480M
|__ Port 1: Dev 2, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
|__ Port 1: Dev 2, If 1, Class=Human Interface Device, Driver=usbhid, 1.5M
我发现 运行这两个命令会导致设备关闭:
echo "1-1" > /sys/bus/usb/drivers/usb/unbind
echo "1-1" > /sys/bus/usb/drivers/usb/bind
奇怪的是,它只在 "bind" 期间关闭,而不是 "unbind"。但是一旦它以这种方式关闭,我发现重新打开它的唯一方法是重新启动计算机,这不是一个可用的解决方案。
确实,另一个问题确实有一种技术可以满足我的要求。请注意,这不是通用的 Linux 答案,它仅适用于 BeagleBone Black 和类似设备。 (我在 BeagleBone Green 上进行了测试。)从 devmem2
示例向后工作,此 C++ 代码块会关闭 USB 电源,然后再打开:
const size_t page_size_in_bytes = getpagesize();
const size_t address_gpio3_13 = 0x47401c60; // see comment below
const size_t address_start = address_gpio3_13 / page_size_in_bytes * page_size_in_bytes;
const size_t address_offset = address_gpio3_13 - address_start;
int fd = open("/dev/mem", O_RDWR);
void *addr = mmap( 0, page_size_in_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, address_start );
uint8_t *byte_ptr = reinterpret_cast<uint8_t*>(addr);
byte_ptr[address_offset] = 0x00; // turn off USB
std::this_thread::sleep_for( std::chrono::milliseconds(500) );
byte_ptr[address_offset] = 0x01; // turn on USB
munmap( addr, page_size_in_bytes );
close(fd);
(不包括错误处理。)
神奇的数字0x47401c60
真的是一个神奇的数字。根据一些帖子,看起来需要签署 NDA 才能访问一些与 USB 相关的文档。在ARM335X技术参考手册中,唯一提到0x47401Cxx地址space的是第156页如下:
Block Name Start Address End Address
USB1 Core 0x4740_1C00 0x4740_1FFF
我正在寻找一种方法来关闭(然后重新打开)USB 端口的 power。解决方案可以是 C、bash 等。我正在为 armhf 使用 BeagleBone 运行ning 32 位 Ubuntu 16.04。
> uname -srvm
Linux 4.4.6-ti-r15 #1 SMP Tue Apr 5 12:32:22 UTC 2016 armv7l
我尝试了很多在 Whosebug 和 AskUbuntu 上讨论的事情,包括:
#include <linux/usbdevice_fs.h>
int main(void)
{
int fd = open( "/dev/bus/usb/001/002", O_WRONLY );
if (fd < 0) return 1;
int rc = ioctl( fd, USBDEVFS_RESET, 0 );
if (rc < 0) return 2;
close( fd );
return 0;
}
我需要关闭(并最终重新打开)的 USB 设备是 Champtek FS310 条形码 reader 当我 运行 lsusb 时它显示为磁卡条 reader :
> lsusb
Bus 001 Device 002: ID 040b:6543 Weltrend Semiconductor Manhattan Magnetic Card Strip Reader
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
> lsusb -t
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=musb-hdrc/1p, 480M
|__ Port 1: Dev 2, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
|__ Port 1: Dev 2, If 1, Class=Human Interface Device, Driver=usbhid, 1.5M
我发现 运行这两个命令会导致设备关闭:
echo "1-1" > /sys/bus/usb/drivers/usb/unbind
echo "1-1" > /sys/bus/usb/drivers/usb/bind
奇怪的是,它只在 "bind" 期间关闭,而不是 "unbind"。但是一旦它以这种方式关闭,我发现重新打开它的唯一方法是重新启动计算机,这不是一个可用的解决方案。
确实,另一个问题确实有一种技术可以满足我的要求。请注意,这不是通用的 Linux 答案,它仅适用于 BeagleBone Black 和类似设备。 (我在 BeagleBone Green 上进行了测试。)从 devmem2
示例向后工作,此 C++ 代码块会关闭 USB 电源,然后再打开:
const size_t page_size_in_bytes = getpagesize();
const size_t address_gpio3_13 = 0x47401c60; // see comment below
const size_t address_start = address_gpio3_13 / page_size_in_bytes * page_size_in_bytes;
const size_t address_offset = address_gpio3_13 - address_start;
int fd = open("/dev/mem", O_RDWR);
void *addr = mmap( 0, page_size_in_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, address_start );
uint8_t *byte_ptr = reinterpret_cast<uint8_t*>(addr);
byte_ptr[address_offset] = 0x00; // turn off USB
std::this_thread::sleep_for( std::chrono::milliseconds(500) );
byte_ptr[address_offset] = 0x01; // turn on USB
munmap( addr, page_size_in_bytes );
close(fd);
(不包括错误处理。)
神奇的数字0x47401c60
真的是一个神奇的数字。根据一些帖子,看起来需要签署 NDA 才能访问一些与 USB 相关的文档。在ARM335X技术参考手册中,唯一提到0x47401Cxx地址space的是第156页如下:
Block Name Start Address End Address
USB1 Core 0x4740_1C00 0x4740_1FFF