From b72d50c2b2fd39f97807c5600ffc859975eae1c0 Mon Sep 17 00:00:00 2001 From: gustavo panizzo Date: Sun, 11 Mar 2018 22:34:43 +0800 Subject: Import uhubctl_2.0.0-1.debian.tar.xz [dgit import tarball uhubctl 2.0.0-1 uhubctl_2.0.0-1.debian.tar.xz] --- changelog | 5 +++++ compat | 1 + control | 17 +++++++++++++++++ copyright | 32 ++++++++++++++++++++++++++++++++ gbp.conf | 6 ++++++ patches/debian-ways | 24 ++++++++++++++++++++++++ patches/series | 1 + rules | 4 ++++ source/format | 1 + tests/control | 1 + tests/run-uhubctl-v | 7 +++++++ uhubctl.docs | 1 + watch | 3 +++ 13 files changed, 103 insertions(+) create mode 100644 changelog create mode 100644 compat create mode 100644 control create mode 100644 copyright create mode 100644 gbp.conf create mode 100644 patches/debian-ways create mode 100644 patches/series create mode 100755 rules create mode 100644 source/format create mode 100644 tests/control create mode 100644 tests/run-uhubctl-v create mode 100644 uhubctl.docs create mode 100644 watch diff --git a/changelog b/changelog new file mode 100644 index 0000000..d1d49b5 --- /dev/null +++ b/changelog @@ -0,0 +1,5 @@ +uhubctl (2.0.0-1) unstable; urgency=medium + + * Initial release. (Closes: #892424) + + -- gustavo panizzo Sun, 11 Mar 2018 14:34:43 +0000 diff --git a/compat b/compat new file mode 100644 index 0000000..f599e28 --- /dev/null +++ b/compat @@ -0,0 +1 @@ +10 diff --git a/control b/control new file mode 100644 index 0000000..ff1943c --- /dev/null +++ b/control @@ -0,0 +1,17 @@ +Source: uhubctl +Section: electronics +Priority: optional +Maintainer: gustavo panizzo +Build-Depends: debhelper (>= 10.0.0), libusb-1.0-0-dev, autopkgtest +Standards-Version: 4.1.3 +Homepage: https://github.com/mvp/uhubctl + +Package: uhubctl +Architecture: any +Depends: ${misc:Depends}, ${shlibs:Depends} +Description: USB hub per-port power control + Utility to control USB power per-port on smart USB hubs. + Smart hub is defined as one that implements per-port power switching. + . + Original idea for this code was inspired by hub-ctrl.c by Niibe Yutaka: + http://www.gniibe.org/development/ac-power-control-by-USB-hub diff --git a/copyright b/copyright new file mode 100644 index 0000000..73566a6 --- /dev/null +++ b/copyright @@ -0,0 +1,32 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: uhubctl +Source: + +Files: * +Copyright: <2015-2018> Vadim Mikhailov +License: GPL-2 + +License: GPL-2 + uhubctl – USB hub per-port power control. + . + Copyright (c) 2009-2018, Vadim Mikhailov + . + 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, version 2. + . + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + . + On Debian systems, the complete text of the GNU General + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". + +Files: debian/* +Copyright: <2018> gustavo panizzo +License: GPL-2 diff --git a/gbp.conf b/gbp.conf new file mode 100644 index 0000000..f3a2d52 --- /dev/null +++ b/gbp.conf @@ -0,0 +1,6 @@ +[DEFAULT] +upstream-branch = master +debian-branch = debian/unstable +upstream-tag = v%(version)s +compression = gz +pristine-tar = True diff --git a/patches/debian-ways b/patches/debian-ways new file mode 100644 index 0000000..0aec10b --- /dev/null +++ b/patches/debian-ways @@ -0,0 +1,24 @@ +Description: + This patch overrides upstream's method to detect the release + version +Forwarded: no +Author: gustavo panizzo +Last-Update: 2018-03-11 +--- a/Makefile ++++ b/Makefile +@@ -15,7 +15,14 @@ CC ?= gcc + CFLAGS ?= -g -O0 + CFLAGS += -Wall -Wextra -std=c99 -pedantic + GIT_VERSION := $(shell git describe --abbrev=4 --dirty --always --tags) +-CFLAGS += -DPROGRAM_VERSION=\"$(GIT_VERSION)\" ++ ++# Gets the full version of the source package including debian version ++DEB_VERSION := $(shell dpkg-parsechangelog | egrep '^Version:' | cut -f 2 -d ' ') ++DEB_NOEPOCH_VERSION := $(shell echo $(DEB_VERSION) | cut -d: -f2-) ++# # Gets only the upstream version of the package ++DEB_UPSTREAM_VERSION := $(shell echo $(DEB_NOEPOCH_VERSION) | sed 's/-[^-]*$$//') ++ ++CFLAGS += -DPROGRAM_VERSION=\"$(DEB_UPSTREAM_VERSION)\" + + ifeq ($(UNAME_S),Linux) + LDFLAGS += -Wl,-z,relro -lusb-1.0 diff --git a/patches/series b/patches/series new file mode 100644 index 0000000..b2e9488 --- /dev/null +++ b/patches/series @@ -0,0 +1 @@ +debian-ways diff --git a/rules b/rules new file mode 100755 index 0000000..2d33f6a --- /dev/null +++ b/rules @@ -0,0 +1,4 @@ +#!/usr/bin/make -f + +%: + dh $@ diff --git a/source/format b/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/tests/control b/tests/control new file mode 100644 index 0000000..5d678f8 --- /dev/null +++ b/tests/control @@ -0,0 +1 @@ +Tests: run-uhubctl-v diff --git a/tests/run-uhubctl-v b/tests/run-uhubctl-v new file mode 100644 index 0000000..ad9ad39 --- /dev/null +++ b/tests/run-uhubctl-v @@ -0,0 +1,7 @@ +#!/bin/sh + +exec 2>&1 + +set -e + +uhubctl -v diff --git a/uhubctl.docs b/uhubctl.docs new file mode 100644 index 0000000..b43bf86 --- /dev/null +++ b/uhubctl.docs @@ -0,0 +1 @@ +README.md diff --git a/watch b/watch new file mode 100644 index 0000000..11ee23f --- /dev/null +++ b/watch @@ -0,0 +1,3 @@ +version=3 +opts=filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/uhubctl-$1\.tar\.gz/ \ + https://github.com/mvp/uhubctl/releases .*/v?(\d\S*)\.tar\.gz -- cgit v1.2.3 From e45d72486b6bfb08a8e6e2f4c789a6186ffa4e73 Mon Sep 17 00:00:00 2001 From: gustavo panizzo Date: Sun, 11 Mar 2018 22:34:43 +0800 Subject: Import uhubctl_2.0.0.orig.tar.gz [dgit import orig uhubctl_2.0.0.orig.tar.gz] --- .gitignore | 8 + COPYING | 339 +++++++++++++++++++++ Formula/uhubctl.rb | 16 + LICENSE | 16 + Makefile | 47 +++ README.md | 128 ++++++++ uhubctl.c | 880 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 1434 insertions(+) create mode 100644 .gitignore create mode 100644 COPYING create mode 100644 Formula/uhubctl.rb create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 uhubctl.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0ab4458 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +# Executables +uhubctl + +# Object files +*.o + +# Mac symbols +*.dSYM diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 2 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/Formula/uhubctl.rb b/Formula/uhubctl.rb new file mode 100644 index 0000000..440b1cd --- /dev/null +++ b/Formula/uhubctl.rb @@ -0,0 +1,16 @@ +class Uhubctl < Formula + desc "control USB hubs powering per-port" + homepage "https://github.com/mvp/uhubctl" + head "https://github.com/mvp/uhubctl.git" + + depends_on "libusb" + + def install + system "make" + bin.install "uhubctl" + end + + test do + system "#{bin}/uhubctl", "-v" + end +end diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a842461 --- /dev/null +++ b/LICENSE @@ -0,0 +1,16 @@ +uhubctl – USB hub per-port power control. + +Copyright (c) 2009-2018, Vadim Mikhailov + +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, version 2. + +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., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7074cbf --- /dev/null +++ b/Makefile @@ -0,0 +1,47 @@ +# uhubctl Makefile +# +UNAME_S := $(shell uname -s) + +DESTDIR ?= +prefix ?= /usr +sbindir ?= $(prefix)/sbin + +INSTALL := install +INSTALL_DIR := $(INSTALL) -m 755 -d +INSTALL_PROGRAM := $(INSTALL) -m 755 +RM := rm -rf + +CC ?= gcc +CFLAGS ?= -g -O0 +CFLAGS += -Wall -Wextra -std=c99 -pedantic +GIT_VERSION := $(shell git describe --abbrev=4 --dirty --always --tags) +CFLAGS += -DPROGRAM_VERSION=\"$(GIT_VERSION)\" + +ifeq ($(UNAME_S),Linux) + LDFLAGS += -Wl,-z,relro -lusb-1.0 +endif + +ifeq ($(UNAME_S),Darwin) +ifneq ($(wildcard /opt/local/include),) + # MacPorts + CFLAGS += -I/opt/local/include + LDFLAGS += -L/opt/local/lib +endif + LDFLAGS += -lusb-1.0 +endif + +ifeq ($(UNAME_S),FreeBSD) + LDFLAGS += -lusb +endif + +PROGRAM = uhubctl + +$(PROGRAM): $(PROGRAM).c + $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) + +install: + $(INSTALL_DIR) $(DESTDIR)$(sbindir) + $(INSTALL_PROGRAM) $(PROGRAM) $(DESTDIR)$(sbindir) + +clean: + $(RM) $(PROGRAM).o $(PROGRAM).dSYM $(PROGRAM) diff --git a/README.md b/README.md new file mode 100644 index 0000000..06aec22 --- /dev/null +++ b/README.md @@ -0,0 +1,128 @@ +uhubctl +======= + +uhubctl is utility to control USB power per-port on smart USB hubs. +Smart hub is defined as one that implements per-port power switching. + +Original idea for this code was inspired by hub-ctrl.c by Niibe Yutaka: +http://www.gniibe.org/development/ac-power-control-by-USB-hub + + +Compatible USB hubs +=================== + +Note that very few hubs actually support per-port power switching. +Some of them are no longer manufactured and can be hard to find. + +This is list of known compatible USB hubs: + +| Manufacturer | Product | VID:PID | Release | EOL | +|:-------------------|:-------------------------------------------------------|:----------|:--------|:-----| +| AmazonBasics | HU3641V1, 4 Port USB3 Hub (see USB3 note below) |`2109:2811`| 2013 | | +| AmazonBasics | HU3770V1, 7 Port USB3 Hub (see USB3 note below) |`2109:2811`| 2013 | | +| Apple | Thunderbolt Display 27" (internal USB hub) | | 2011 | 2016 | +| Apple | USB Keyboard With Numeric Pad (internal USB hub) | | 2011 | | +| Asus | Z87-PLUS Motherboard (onboard USB hubs) | | 2013 | 2016 | +| B&B Electronics | UHR204 | | 2013 | | +| Belkin | F5U701-BLK | | 2008 | 2012 | +| Circuitco | Beagleboard-xM (internal USB hub) |`0424:9514`| 2010 | | +| CyberPower | CP-H420P |`0409:0059`| 2004 | | +| Cypress | CY4608 HX2VL development kit |`04b4:6570`| 2012 | | +| D-Link | DUB-H4 rev D1 (black edition, old silver not working) |`05E3:0608`| 2012 | | +| D-Link | DUB-H7 (silver edition only, new black not working) |`2001:F103`| 2005 | 2010 | +| Elecom | U2H-G4S | | 2006 | 2011 | +| Hawking Technology | UH214 | | 2003 | 2008 | +| Lenovo | ThinkPad EU Ultra Dockingstation (40A20090EU) |`17EF:100F`| 2015 | | +| Lenovo | ThinkPad X200 Ultrabase 42X4963 |`17EF:1005`| 2008 | 2011 | +| Linksys | USB2HUB4 | | 2004 | 2010 | +| Maplin | A08CQ |`0409:0059`| 2008 | 2011 | +| Microchip | EVB-USB2517 | | 2008 | | +| Plugable | USB3-HUB7BC (see USB3 note below) |`2109:0813`| 2015 | | +| Plugable | USB3-HUB7-81X (see USB3 note below) |`2109:0813`| 2012 | | +| Plugable | USB2-HUB10S | | 2010 | | +| Raspberry Pi | Model B+, Model 2 B, Model 3 B (port 2 only) | | 2011 | | +| Rosewill | RHUB-210 |`0409:005A`| 2011 | 2014 | +| Sanwa Supply | USB-HUB14GPH | | 2001 | 2003 | +| Sunix | SHB4200MA |`0409:0058`| 2006 | 2009 | +| Targus | PAUH212U | | 2004 | 2009 | + +This table is by no means complete. +If your hub works with uhubctl, but is not listed above, please report it +by opening new issue at https://github.com/mvp/uhubctl/issues, +so we can add it to supported table. In your report, please provide +exact product model and add output from uhubctl. + +Note that quite a few modern motherboards have built-in root hubs that +do support this feature - you may not even need to buy any external hub. +WARNING: turning off built-in USB ports may cut off your keyboard or mouse, +so be careful what ports you are turning off! + + +USB 3.0 duality note +==================== +If you have compatible USB 3.0 hub connected to USB3 upstream port, +it will be detected as 2 independent virtual hubs: USB2 and USB3, and your USB devices will be +connected to USB2 or USB3 virtual hub depending on their capabilities and connection speed. +To control power for such hubs, it is necessary to turn off/on power on **both** USB2 and USB3 +virtual hubs for power off/on changes to take effect. `uhubctl` will try to do this automatically +(unless you disable this behavior with option `-e`). + +Unfortunately, while most hubs will cut off data USB connection, some may still not cut off VBUS to port, +which means connected phone may still continue to charge from port that is powered off by uhubctl. + + +Compiling +========= + +This utility was tested to compile and work on Linux +(Ubuntu/Debian, Redhat/Fedora/CentOS, Arch Linux, Gentoo, OpenSUSE, Buildroot), FreeBSD and Mac OS X. + +While `uhubctl` compiles on Windows, USB power switching does not work on Windows because `libusb` +is using `winusb.sys` driver, which according to Microsoft does not support +[necessary USB control requests](https://social.msdn.microsoft.com/Forums/sqlserver/en-US/f680b63f-ca4f-4e52-baa9-9e64f8eee101). +This may be fixed if `libusb` starts supporting different driver on Windows. + +First, you need to install library libusb-1.0 (version 1.0.12 or later): + +* Ubuntu: `sudo apt-get install libusb-1.0-0-dev` +* Redhat: `sudo yum install libusb1-devel` +* MacOSX: `brew install libusb`, or `sudo port install libusb-devel` + Note that Mac OS Sierra may be affected by issue https://github.com/libusb/libusb/issues/303. + Until libusb 1.0.22 is released, use `brew install --HEAD libusb` as a workaround. +* FreeBSD: libusb is included by default +* Windows: TBD? + +To compile, simply run `make` - this will generate `uhubctl` binary. + +Also, for Mac OS X you can install `uhubctl` with Homebrew custom tap: + +``` +brew tap mvp/uhubctl https://github.com/mvp/uhubctl +brew install --HEAD uhubctl +``` + +Usage +===== + +You can control the power on a USB port(s) like this: + + uhubctl -a off -p 235 + +This means operate on default smart hub and turn power off (`-a off`, or `-a 0`) +on ports 2,3,5 (`-p 235`). Supported actions are `off`/`on`/`cycle` (or `0`/`1`/`2`). +`cycle` means turn power off, wait some delay (configurable with `-d`) and turn it back on. + +On Linux, you may need to run it with `sudo`, or to configure `udev` USB permissions. + +If you have more than one smart USB hub connected, you should choose +specific hub to control using `-l` (location) parameter. +To find hub locations, simply run uhubctl without any parameters. + + +Copyright +========= + +Copyright (C) 2009-2018 Vadim Mikhailov + +This file can be distributed under the terms and conditions of the +GNU General Public License version 2. diff --git a/uhubctl.c b/uhubctl.c new file mode 100644 index 0000000..96ffc3e --- /dev/null +++ b/uhubctl.c @@ -0,0 +1,880 @@ +/* + * Copyright (c) 2009-2018 Vadim Mikhailov + * + * Utility to turn USB port power on/off + * for USB hubs that support per-port power switching. + * + * This file can be distributed under the terms and conditions of the + * GNU General Public License version 2. + * + */ + +#define _XOPEN_SOURCE 500 + +#include +#include +#include +#include +#include +#include +#include + +#if defined(_WIN32) +#include +#include +#include +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#else +#include +#endif + +#if defined(__FreeBSD__) || defined(_WIN32) +#include +#else +#include +#endif + +#if defined(__APPLE__) /* snprintf is not available in pure C mode */ +int snprintf(char * __restrict __str, size_t __size, const char * __restrict __format, ...) __printflike(3, 4); +#endif + +#if _POSIX_C_SOURCE >= 199309L +#include /* for nanosleep */ +#endif + +/* cross-platform sleep function */ + +void sleep_ms(int milliseconds) +{ +#if defined(_WIN32) + Sleep(milliseconds); +#elif _POSIX_C_SOURCE >= 199309L + struct timespec ts; + ts.tv_sec = milliseconds / 1000; + ts.tv_nsec = (milliseconds % 1000) * 1000000; + nanosleep(&ts, NULL); +#else + usleep(milliseconds * 1000); +#endif +} + +/* Max number of hub ports supported. + * This is somewhat artifically limited by "-p" option parser. + * If "-p" parser is improved, we can support up to 32 ports. + * However, biggest number of ports on smart hub I've seen was 8. + * I've also observed onboard USB hub with whopping 14 ports, + * but that hub did not support per-port power switching. + */ +#define MAX_HUB_PORTS 9 +#define ALL_HUB_PORTS ((1 << MAX_HUB_PORTS) - 1) /* bitmask */ + +#define USB_CTRL_GET_TIMEOUT 5000 + +#define USB_PORT_FEAT_POWER (1 << 3) + +#define POWER_KEEP (-1) +#define POWER_OFF 0 +#define POWER_ON 1 +#define POWER_CYCLE 2 + +#define MAX_HUB_CHAIN 8 /* Per USB 3.0 spec max hub chain is 7 */ + +/* Partially borrowed from linux/usb/ch11.h */ + +#pragma pack(push,1) +struct usb_hub_descriptor { + unsigned char bDescLength; + unsigned char bDescriptorType; + unsigned char bNbrPorts; + unsigned char wHubCharacteristics[2]; + unsigned char bPwrOn2PwrGood; + unsigned char bHubContrCurrent; + unsigned char data[1]; /* use 1 to avoid zero-sized array warning */ +}; +#pragma pack(pop) + +/* + * Hub Status and Hub Change results + * See USB 2.0 spec Table 11-19 and Table 11-20 + */ +#pragma pack(push,1) +struct usb_port_status { + int16_t wPortStatus; + int16_t wPortChange; +}; +#pragma pack(pop) + +/* + * wPortStatus bit field + * See USB 2.0 spec Table 11-21 + */ +#define USB_PORT_STAT_CONNECTION 0x0001 +#define USB_PORT_STAT_ENABLE 0x0002 +#define USB_PORT_STAT_SUSPEND 0x0004 +#define USB_PORT_STAT_OVERCURRENT 0x0008 +#define USB_PORT_STAT_RESET 0x0010 +#define USB_PORT_STAT_L1 0x0020 +/* bits 6 to 7 are reserved */ +#define USB_PORT_STAT_POWER 0x0100 +#define USB_PORT_STAT_LOW_SPEED 0x0200 +#define USB_PORT_STAT_HIGH_SPEED 0x0400 +#define USB_PORT_STAT_TEST 0x0800 +#define USB_PORT_STAT_INDICATOR 0x1000 +/* bits 13 to 15 are reserved */ + + +#define USB_SS_BCD 0x0300 +/* + * Additions to wPortStatus bit field from USB 3.0 + * See USB 3.0 spec Table 10-10 + */ +#define USB_PORT_STAT_LINK_STATE 0x01e0 +#define USB_SS_PORT_STAT_POWER 0x0200 +#define USB_SS_PORT_STAT_SPEED 0x1c00 +#define USB_PORT_STAT_SPEED_5GBPS 0x0000 +/* Valid only if port is enabled */ +/* Bits that are the same from USB 2.0 */ +#define USB_SS_PORT_STAT_MASK (USB_PORT_STAT_CONNECTION | \ + USB_PORT_STAT_ENABLE | \ + USB_PORT_STAT_OVERCURRENT | \ + USB_PORT_STAT_RESET) + +/* + * Definitions for PORT_LINK_STATE values + * (bits 5-8) in wPortStatus + */ +#define USB_SS_PORT_LS_U0 0x0000 +#define USB_SS_PORT_LS_U1 0x0020 +#define USB_SS_PORT_LS_U2 0x0040 +#define USB_SS_PORT_LS_U3 0x0060 +#define USB_SS_PORT_LS_SS_DISABLED 0x0080 +#define USB_SS_PORT_LS_RX_DETECT 0x00a0 +#define USB_SS_PORT_LS_SS_INACTIVE 0x00c0 +#define USB_SS_PORT_LS_POLLING 0x00e0 +#define USB_SS_PORT_LS_RECOVERY 0x0100 +#define USB_SS_PORT_LS_HOT_RESET 0x0120 +#define USB_SS_PORT_LS_COMP_MOD 0x0140 +#define USB_SS_PORT_LS_LOOPBACK 0x0160 + + +/* + * wHubCharacteristics (masks) + * See USB 2.0 spec Table 11-13, offset 3 + */ +#define HUB_CHAR_LPSM 0x0003 /* Logical Power Switching Mode mask */ +#define HUB_CHAR_COMMON_LPSM 0x0000 /* All ports at once power switching */ +#define HUB_CHAR_INDV_PORT_LPSM 0x0001 /* Per-port power switching */ +#define HUB_CHAR_NO_LPSM 0x0002 /* No power switching */ + +#define HUB_CHAR_COMPOUND 0x0004 /* hub is part of a compound device */ + +#define HUB_CHAR_OCPM 0x0018 /* Over-Current Protection Mode mask */ +#define HUB_CHAR_COMMON_OCPM 0x0000 /* All ports at once over-current protection */ +#define HUB_CHAR_INDV_PORT_OCPM 0x0008 /* Per-port over-current protection */ +#define HUB_CHAR_NO_OCPM 0x0010 /* No over-current protection support */ + +#define HUB_CHAR_TTTT 0x0060 /* TT Think Time mask */ +#define HUB_CHAR_PORTIND 0x0080 /* per-port indicators (LEDs) */ + +/* List of all USB devices enumerated by libusb */ +static struct libusb_device **usb_devs = NULL; + +struct hub_info { + struct libusb_device *dev; + int bcd_usb; + int nports; + int ppps; + int actionable; /* true if this hub is subject to action */ + char vendor[16]; + char location[32]; + char description[256]; +}; + +/* Array of all enumerated USB hubs */ +#define MAX_HUBS 128 +static struct hub_info hubs[MAX_HUBS]; +static int hub_count = 0; +static int hub_phys_count = 0; + +/* default options */ +static char opt_vendor[16] = ""; +static char opt_location[32] = ""; /* Hub location a-b.c.d */ +static int opt_ports = ALL_HUB_PORTS; /* Bitmask of ports to operate on */ +static int opt_action = POWER_KEEP; +static int opt_delay = 2; +static int opt_repeat = 1; +static int opt_wait = 20; /* wait before repeating in ms */ +static int opt_exact = 0; /* exact location match - disable USB3 duality handling */ +static int opt_reset = 0; /* reset hub after operation(s) */ + +static const struct option long_options[] = { + { "loc", required_argument, NULL, 'l' }, + { "vendor", required_argument, NULL, 'n' }, + { "ports", required_argument, NULL, 'p' }, + { "action", required_argument, NULL, 'a' }, + { "delay", required_argument, NULL, 'd' }, + { "repeat", required_argument, NULL, 'r' }, + { "wait", required_argument, NULL, 'w' }, + { "exact", no_argument, NULL, 'e' }, + { "reset", no_argument, NULL, 'R' }, + { "version", no_argument, NULL, 'v' }, + { "help", no_argument, NULL, 'h' }, + { 0, 0, NULL, 0 }, +}; + + +int print_usage() +{ + printf( + "uhubctl %s: utility to control USB port power for smart hubs.\n" + "Usage: uhubctl [options]\n" + "Without options, show status for all smart hubs.\n" + "\n" + "Options [defaults in brackets]:\n" + "--action, -a - action to off/on/cycle (0/1/2) for affected ports.\n" + "--ports, -p - ports to operate on [all hub ports].\n" + "--loc, -l - limit hub by location [all smart hubs].\n" + "--vendor, -n - limit hub by vendor id [%s] (partial ok).\n" + "--delay, -d - delay for cycle action [%d sec].\n" + "--repeat, -r - repeat power off count [%d] (some devices need it to turn off).\n" + "--exact, -e - exact location (no USB3 duality handling).\n" + "--reset, -R - reset hub after each power-on action, causing all devices to reassociate.\n" + "--wait, -w - wait before repeat power off [%d ms].\n" + "--version, -v - print program version.\n" + "--help, -h - print this text.\n" + "\n" + "Send bugs and requests to: https://github.com/mvp/uhubctl\n", + PROGRAM_VERSION, + strlen(opt_vendor) ? opt_vendor : "any", + opt_delay, + opt_repeat, + opt_wait + ); + return 0; +} + + +/* trim trailing spaces from a string */ + +static char* rtrim(char* str) +{ + int i; + for (i = strlen(str)-1; i>=0 && isspace(str[i]); i--) { + str[i] = 0; + } + return str; +} + + +/* + * get USB hub properties. + * most hub_info fields are filled, except for description. + * returns 0 for success and error code for failure. + */ + +int get_hub_info(struct libusb_device *dev, struct hub_info *info) +{ + int rc = 0; + int len = 0; + struct libusb_device_handle *devh = NULL; + unsigned char buf[LIBUSB_DT_HUB_NONVAR_SIZE + 2 + 3] = {0}; + struct usb_hub_descriptor *uhd = + (struct usb_hub_descriptor *)buf; + int minlen = LIBUSB_DT_HUB_NONVAR_SIZE + 2; + struct libusb_device_descriptor desc; + rc = libusb_get_device_descriptor(dev, &desc); + if (rc) + return rc; + if (desc.bDeviceClass != LIBUSB_CLASS_HUB) + return LIBUSB_ERROR_INVALID_PARAM; + int bcd_usb = libusb_le16_to_cpu(desc.bcdUSB); + int desc_type = bcd_usb >= USB_SS_BCD ? LIBUSB_DT_SUPERSPEED_HUB + : LIBUSB_DT_HUB; + rc = libusb_open(dev, &devh); + if (rc == 0) { + len = libusb_control_transfer(devh, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS + | LIBUSB_RECIPIENT_DEVICE, /* hub status */ + LIBUSB_REQUEST_GET_DESCRIPTOR, + desc_type << 8, + 0, + buf, sizeof(buf), + USB_CTRL_GET_TIMEOUT + ); + + if (len >= minlen) { + unsigned char port_numbers[MAX_HUB_CHAIN] = {0}; + info->dev = dev; + info->bcd_usb = bcd_usb; + info->nports = uhd->bNbrPorts; + snprintf( + info->vendor, sizeof(info->vendor), + "%04x:%04x", + libusb_le16_to_cpu(desc.idVendor), + libusb_le16_to_cpu(desc.idProduct) + ); + + /* Convert bus and ports array into USB location string */ + int bus = libusb_get_bus_number(dev); + snprintf(info->location, sizeof(info->location), "%d", bus); +#if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000102) + /* + * libusb_get_port_path is deprecated since libusb v1.0.16, + * therefore use libusb_get_port_numbers when supported + */ + int pcount = libusb_get_port_numbers(dev, port_numbers, MAX_HUB_CHAIN); +#else + int pcount = libusb_get_port_path(NULL, dev, port_numbers, MAX_HUB_CHAIN); +#endif + int k; + for (k=0; klocation, s); + } + + info->ppps = 0; + /* Logical Power Switching Mode */ + int lpsm = uhd->wHubCharacteristics[0] & HUB_CHAR_LPSM; + /* Over-Current Protection Mode */ + int ocpm = uhd->wHubCharacteristics[0] & HUB_CHAR_OCPM; + /* LPSM must be supported per-port, and OCPM per port or ganged */ + if ((lpsm == HUB_CHAR_INDV_PORT_LPSM) && + (ocpm == HUB_CHAR_INDV_PORT_OCPM || + ocpm == HUB_CHAR_COMMON_OCPM)) + { + info->ppps = 1; + } + } else { + rc = len; + } + libusb_close(devh); + } + return rc; +} + + +/* + * Assuming that devh is opened device handle for USB hub, + * return state for given hub port. + * In case of error, returns -1 (inspect errno for more information). + */ + +static int get_port_status(struct libusb_device_handle *devh, int port) +{ + int rc; + struct usb_port_status ust; + if (devh == NULL) + return -1; + + rc = libusb_control_transfer(devh, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS + | LIBUSB_RECIPIENT_OTHER, /* port status */ + LIBUSB_REQUEST_GET_STATUS, 0, + port, (unsigned char*)&ust, sizeof(ust), + USB_CTRL_GET_TIMEOUT + ); + + if (rc < 0) { + return rc; + } + return ust.wPortStatus; +} + + +/* + * Get USB device description as a string. + * + * It will use following format: + * + * " , " + * + * vid:pid will be always present, but vendor, product or serial + * may be skipped if they are empty or not enough permissions to read them. + * will be present only for USB hubs. + * + * returns 0 for success and error code for failure. + * in case of failure description buffer is not altered. + */ + +static int get_device_description(struct libusb_device * dev, char* description, int desc_len) +{ + int rc; + int id_vendor = 0; + int id_product = 0; + char vendor[64] = ""; + char product[64] = ""; + char serial[64] = ""; + char ports[64] = ""; + struct libusb_device_descriptor desc; + struct libusb_device_handle *devh = NULL; + rc = libusb_get_device_descriptor(dev, &desc); + if (rc) + return rc; + id_vendor = libusb_le16_to_cpu(desc.idVendor); + id_product = libusb_le16_to_cpu(desc.idProduct); + rc = libusb_open(dev, &devh); + if (rc == 0) { + if (desc.iManufacturer) { + libusb_get_string_descriptor_ascii(devh, + desc.iManufacturer, (unsigned char*)vendor, sizeof(vendor)); + rtrim(vendor); + } + if (desc.iProduct) { + libusb_get_string_descriptor_ascii(devh, + desc.iProduct, (unsigned char*)product, sizeof(product)); + rtrim(product); + } + if (desc.iSerialNumber) { + libusb_get_string_descriptor_ascii(devh, + desc.iSerialNumber, (unsigned char*)serial, sizeof(serial)); + rtrim(serial); + } + if (desc.bDeviceClass == LIBUSB_CLASS_HUB) { + struct hub_info info; + rc = get_hub_info(dev, &info); + if (rc == 0) { + snprintf(ports, sizeof(ports), ", USB %x.%02x, %d ports", + info.bcd_usb >> 8, info.bcd_usb & 0xFF, info.nports); + } + } + libusb_close(devh); + } + snprintf(description, desc_len, + "%04x:%04x%s%s%s%s%s%s%s", + id_vendor, id_product, + vendor[0] ? " " : "", vendor, + product[0] ? " " : "", product, + serial[0] ? " " : "", serial, + ports + ); + return 0; +} + + +/* + * show status for hub ports + * portmask is bitmap of ports to display + * if portmask is 0, show all ports + */ + +static int print_port_status(struct hub_info * hub, int portmask) +{ + int port_status; + struct libusb_device_handle * devh = NULL; + int rc = 0; + struct libusb_device *dev = hub->dev; + rc = libusb_open(dev, &devh); + if (rc == 0) { + int port; + for (port = 1; port <= hub->nports; port++) { + if (portmask > 0 && (portmask & (1 << (port-1))) == 0) continue; + + port_status = get_port_status(devh, port); + if (port_status == -1) { + fprintf(stderr, + "cannot read port %d status, %s (%d)\n", + port, strerror(errno), errno); + break; + } + + printf(" Port %d: %04x", port, port_status); + + char description[256] = ""; + struct libusb_device * udev; + int i = 0; + while ((udev = usb_devs[i++]) != NULL) { + if (libusb_get_parent(udev) == dev && + libusb_get_port_number(udev) == port) + { + rc = get_device_description(udev, description, sizeof(description)); + if (rc == 0) + break; + } + } + + if (hub->bcd_usb < USB_SS_BCD) { + if (port_status == 0) { + printf(" off"); + } else { + if (port_status & USB_PORT_STAT_POWER) printf(" power"); + if (port_status & USB_PORT_STAT_INDICATOR) printf(" indicator"); + if (port_status & USB_PORT_STAT_TEST) printf(" test"); + if (port_status & USB_PORT_STAT_HIGH_SPEED) printf(" highspeed"); + if (port_status & USB_PORT_STAT_LOW_SPEED) printf(" lowspeed"); + if (port_status & USB_PORT_STAT_SUSPEND) printf(" suspend"); + } + } else { + if (port_status == USB_SS_PORT_LS_SS_DISABLED) { + printf(" off"); + } else { + int link_state = port_status & USB_PORT_STAT_LINK_STATE; + if (port_status & USB_SS_PORT_STAT_POWER) printf(" power"); + if ((port_status & USB_SS_PORT_STAT_SPEED) + == USB_PORT_STAT_SPEED_5GBPS) + { + printf(" 5gbps"); + } + if (link_state == USB_SS_PORT_LS_U0) printf(" U0"); + if (link_state == USB_SS_PORT_LS_U1) printf(" U1"); + if (link_state == USB_SS_PORT_LS_U2) printf(" U2"); + if (link_state == USB_SS_PORT_LS_U3) printf(" U3"); + if (link_state == USB_SS_PORT_LS_SS_DISABLED) printf(" SS.Disabled"); + if (link_state == USB_SS_PORT_LS_RX_DETECT) printf(" Rx.Detect"); + if (link_state == USB_SS_PORT_LS_SS_INACTIVE) printf(" SS.Inactive"); + if (link_state == USB_SS_PORT_LS_POLLING) printf(" Polling"); + if (link_state == USB_SS_PORT_LS_RECOVERY) printf(" Recovery"); + if (link_state == USB_SS_PORT_LS_HOT_RESET) printf(" HotReset"); + if (link_state == USB_SS_PORT_LS_COMP_MOD) printf(" Compliance"); + if (link_state == USB_SS_PORT_LS_LOOPBACK) printf(" Loopback"); + } + } + if (port_status & USB_PORT_STAT_RESET) printf(" reset"); + if (port_status & USB_PORT_STAT_OVERCURRENT) printf(" oc"); + if (port_status & USB_PORT_STAT_ENABLE) printf(" enable"); + if (port_status & USB_PORT_STAT_CONNECTION) printf(" connect"); + + if (port_status & USB_PORT_STAT_CONNECTION) printf(" [%s]", description); + + printf("\n"); + } + libusb_close(devh); + } + return 0; +} + + +/* + * Find all USB hubs and fill hubs[] array. + * Set actionable to 1 on all hubs that we are going to operate on + * (this applies possible constraints like location or vendor). + * Returns count of found actionable physical hubs + * (USB3 hubs are counted once despite having USB2 dual partner). + * In case of error returns negative error code. + */ + +static int usb_find_hubs() +{ + struct libusb_device *dev; + int perm_ok = 1; + int rc = 0; + int i = 0; + int j = 0; + while ((dev = usb_devs[i++]) != NULL) { + struct libusb_device_descriptor desc; + rc = libusb_get_device_descriptor(dev, &desc); + /* only scan for hubs: */ + if (rc == 0 && desc.bDeviceClass != LIBUSB_CLASS_HUB) + continue; + struct hub_info info; + bzero(&info, sizeof(info)); + rc = get_hub_info(dev, &info); + if (rc) { + perm_ok = 0; /* USB permission issue? */ + } + get_device_description(dev, info.description, sizeof(info.description)); + if (info.ppps) { /* PPPS is supported */ + if (hub_count < MAX_HUBS) { + info.actionable = 1; + if (strlen(opt_location)>0) { + if (strcasecmp(opt_location, info.location)) { + info.actionable = 0; + } + } + if (strlen(opt_vendor)>0) { + if (strncasecmp(opt_vendor, info.vendor, strlen(opt_vendor))) { + info.actionable = 0; + } + } + memcpy(&hubs[hub_count], &info, sizeof(info)); + hub_count++; + } + } + } + hub_phys_count = 0; + for (i=0; i= 0) + hubs[match].actionable = 1; + } + if (perm_ok == 0 && hub_phys_count == 0) { + return LIBUSB_ERROR_ACCESS; + } + return hub_phys_count; +} + + +int main(int argc, char *argv[]) +{ + int rc; + int c = 0; + int option_index = 0; + + for (;;) { + c = getopt_long(argc, argv, "l:n:a:p:d:r:w:hveR", + long_options, &option_index); + if (c == -1) + break; /* no more options left */ + switch (c) { + case 0: + /* If this option set a flag, do nothing else now. */ + if (long_options[option_index].flag != 0) + break; + printf("option %s", long_options[option_index].name); + if (optarg) + printf(" with arg %s", optarg); + printf("\n"); + break; + case 'l': + strncpy(opt_location, optarg, sizeof(opt_location)); + break; + case 'n': + strncpy(opt_vendor, optarg, sizeof(opt_vendor)); + break; + case 'p': + if (!strcasecmp(optarg, "all")) { /* all ports is the default */ + break; + } + if (strlen(optarg)) { + /* parse port list */ + opt_ports = 0; + size_t i; + for (i=0; i 1 && opt_action >= 0) { + fprintf(stderr, + "Error: changing port state for multiple hubs at once is not supported.\n" + "Use -l to limit operation to one hub!\n" + ); + exit(1); + } + int i; + for (i=0; i 0) { + rc = libusb_control_transfer(devh, + LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_OTHER, + request, USB_PORT_FEAT_POWER, + port, NULL, 0, USB_CTRL_GET_TIMEOUT + ); + if (rc < 0) { + perror("Failed to control port power!\n"); + } + if (repeat > 0) { + sleep_ms(opt_wait); + } + } + } + } + if (k==0 && opt_action == POWER_CYCLE) + sleep_ms(opt_delay * 1000); + /* USB3 hubs need extra delay to actually turn off: */ + if (k==0 && hubs[i].bcd_usb >= USB_SS_BCD) + sleep_ms(150); + printf("Sent power %s request\n", + request == LIBUSB_REQUEST_CLEAR_FEATURE ? "off" : "on" + ); + printf("New status for hub %s [%s]\n", + hubs[i].location, hubs[i].description + ); + print_port_status(&hubs[i], opt_ports); + + if (k == 1 && opt_reset == 1) { + printf("Resetting hub...\n"); + rc = libusb_reset_device(devh); + if (rc < 0) { + perror("Reset failed!\n"); + } else { + printf("Reset successful!\n"); + } + } + } + libusb_close(devh); + } + } + rc = 0; +cleanup: + if (usb_devs) + libusb_free_device_list(usb_devs, 1); + usb_devs = NULL; + libusb_exit(NULL); + return rc; +} -- cgit v1.2.3 From 9169cb7fbcc8da368eb49623db824c8e80f0ca1d Mon Sep 17 00:00:00 2001 From: gustavo panizzo Date: Sun, 11 Mar 2018 22:34:43 +0800 Subject: debian-ways Gbp-Pq: Name debian-ways --- Makefile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7074cbf..8adee05 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,14 @@ CC ?= gcc CFLAGS ?= -g -O0 CFLAGS += -Wall -Wextra -std=c99 -pedantic GIT_VERSION := $(shell git describe --abbrev=4 --dirty --always --tags) -CFLAGS += -DPROGRAM_VERSION=\"$(GIT_VERSION)\" + +# Gets the full version of the source package including debian version +DEB_VERSION := $(shell dpkg-parsechangelog | egrep '^Version:' | cut -f 2 -d ' ') +DEB_NOEPOCH_VERSION := $(shell echo $(DEB_VERSION) | cut -d: -f2-) +# # Gets only the upstream version of the package +DEB_UPSTREAM_VERSION := $(shell echo $(DEB_NOEPOCH_VERSION) | sed 's/-[^-]*$$//') + +CFLAGS += -DPROGRAM_VERSION=\"$(DEB_UPSTREAM_VERSION)\" ifeq ($(UNAME_S),Linux) LDFLAGS += -Wl,-z,relro -lusb-1.0 -- cgit v1.2.3