Created
March 12, 2021 04:34
-
-
Save elcritch/4fe8d66f4d99bef2c68cffe00edbc8cf to your computer and use it in GitHub Desktop.
usbreset.nim -- Nim version of USB port reset on Linux
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## usbreset -- linux program reset a usb port using /dev/ttyUSB<n> file paths | |
# usage: usbreset /dev/ttyUSB0 | |
# Install: | |
# nim c usbreset.nim | |
# sudo cp usbreset /usr/local/bin | |
# Setuid to not need sudo (at your own peril): | |
# sudo chmod 4555 /usr/local/bin/usbreset | |
import os, system, osproc, posix, strutils, re, strformat | |
let | |
USBDEVFS_RESET {.header: "<linux/usbdevice_fs.h>", importc: "USBDEVFS_RESET", nodecl.}: uint | |
attr_regex = re"""ATTRS\{(busnum|devnum)\}=="(\d+)\"\s*""" | |
proc usbInfo(filepath: string): tuple[busnum: int, devnum: int] = | |
echo fmt"Looking up device info for: {filepath}" | |
let | |
outp = execProcess("udevadm", args=["info", "--attribute-walk", filepath], options={poUsePath}) | |
attrs = outp.findAll(pattern = attr_regex) | |
var | |
busnum = -1 | |
devnum = -1 | |
for attr in attrs: | |
var matches: array[2, string] | |
let ret = find(attr, attr_regex, matches=matches) | |
if ret == -1: | |
raise newException(OSError, "Error finding device info") | |
let (name, val) = (matches[0], matches[1].parseInt()) | |
case name: | |
of "busnum": busnum = val | |
of "devnum": devnum = val | |
if busnum > -1 and devnum > -1: | |
echo fmt"Found device with bus: {busnum:03} and device id: {devnum:03}" | |
return (busnum: busnum, devnum: devnum) | |
proc resetDevice(devpath: string) = | |
let fd = open(devpath, O_WRONLY) | |
if fd < 0: | |
raise newException(OSError, "Error opening usb device file: " & $devpath) | |
echo("Resetting USB device %s\n", devpath) | |
let | |
rc = ioctl(fd, USBDEVFS_RESET, 0) | |
if rc < 0: | |
raise newException(OSError, "Error in ioctl: " & $rc) | |
echo("Reset successful\n") | |
let res = close(fd) | |
if res < 0: | |
raise newException(OSError, "Usb reset but error closing file" & $res) | |
let args = commandLineParams() | |
if not args[0].startsWith("/dev/"): | |
echo("incorrect arguments...") | |
echo("usbreset /dev/tty<DEV>" ) | |
quit(1) | |
let | |
nums = usbinfo(args[0]) | |
(busnum, devnum) = nums | |
devicepath = fmt"/dev/bus/usb/{busnum:03}/{devnum:03}" | |
devicepath.resetDevice() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment