Skip to content

Instantly share code, notes, and snippets.

@elcritch
Created March 12, 2021 04:34
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elcritch/4fe8d66f4d99bef2c68cffe00edbc8cf to your computer and use it in GitHub Desktop.
Save elcritch/4fe8d66f4d99bef2c68cffe00edbc8cf to your computer and use it in GitHub Desktop.
usbreset.nim -- Nim version of USB port reset on Linux
## 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