Raspberry usb reset
Problema[keisti]
RaspberrPI nenori draugauti su daugeliu webcam'ų pigių ir brangių variantų, lūžta USB stack'as ar pačios kameros nesusikalba. Reikia perkrovinėti patį Raspberrį kartais tai net nepadeda ir reikia išjungti ir vėl įjungti maitinimą, kad būtų kažkoks rezultatas.
Sprendimas[keisti]
Reikia padaryti device'ui "resetą".
usbreset.c[keisti]
Įrankis skirtas resetinti USB device'us ar jų HUB'us.
/* usbreset -- send a USB port reset to a USB device */
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/usbdevice_fs.h>
int main(int argc, char **argv)
{
const char *filename;
int fd;
int rc;
if (argc != 2) {
fprintf(stderr, "Usage: usbreset device-filename\n");
return 1;
}
filename = argv[1];
fd = open(filename, O_WRONLY);
if (fd < 0) {
perror("Error opening output file");
return 1;
}
printf("Resetting USB device %s\n", filename);
rc = ioctl(fd, USBDEVFS_RESET, 0);
if (rc < 0) {
perror("Error in ioctl");
return 1;
}
printf("Reset successful\n");
close(fd);
return 0;
}
gcc -o usbreset usbreset.c
/boot/config.txt[keisti]
sdhci-bcm2708.missing_status=0 sdhci-bcm2708.sync_after_dma=0 max_usb_current=1
Motion[keisti]
Jeigu naudojame kartu su motion programine įranga, tam yra parašytas motion log'o parseris, kuris tik aptikęs sujungimo su webcam klaidą tuojau pat perkrauna USB
#!/usr/bin/perl -w
# Handle motion errors on the fly on PI devices
# This tool will parse the motion log file and if it detects the usb problems it will reset the usb cameras or hubs
use strict;
use warnings;
use Time::localtime qw( localtime );
use IO::Handle;
use POSIX;
use File::Basename;
my $script_dir = undef;
if(-l __FILE__) {
$script_dir = dirname(readlink(__FILE__));
}
else {
$script_dir = dirname(__FILE__);
}
# dynamic variables
my $log;
sysopen($log, $script_dir."/motion-handler.log", O_APPEND | O_CREAT | O_RDWR) or die;
$log->autoflush(1);
sub write_log {
my ($text) = @_;
# one trully method, that actually works!
my $t = localtime;
printf $log ("%04d.%02d.%02d %02d:%02d:%02d -> %s\n", $t->year + 1900, $t->mon + 1, $t->mday, $t->hour, $t->min, $t->sec, $text);
}
sub reset_usb {
system("/root/usbreset /dev/bus/usb/001/002");
}
while (<STDIN>) {
chomp;
if ($_ =~ /.*Error selecting input.*Device or resource busy.*/gs) {
write_log("Error detected, resetting the usb devices...");
reset_usb();
}
}
Nepamirštame pakeisti /dev/bus/usb/001/002 sau reikiamu adresu. Kaip aptikti koks irenginys priklauso konkreciam device node'ui.
lsbusb
USB irenginiu failus galima paziureti taip:
Kameru irenginiu failai yra:
/dev/bus/usb/001/050 /dev/bus/usb/001/051
Scripte pakeiciam eiliute:
system("/root/usbreset /dev/bus/usb/001/050;/root/usbreset /dev/bus/usb/001/051");
Naudojimas:
tail -f /var/log/motion/motion.log | ./motion-handler.pl