So there’s this huge pile of source code, with an enormous amount of functions and methods. How can you quickly find where each is defined? IDEs has this functionality built in, but it’s not so easy to push an already existing (and huge) project into an IDE.
The solution is so simple. For example,
$ ctags -f sourcemap -R OpenCV-2.4.0/
which will scan the OpenCV-2.4.0 directory for source file, parse them, and create a textual file, sourcemap, with (probably) all method and function definitions listed in alphabetical order. With the files they were found in. The format isn’t very human-friendly, but still quite easy to find the answer in.
Just a quick summary on how to compile my own cross-compiler in 20 minutes.
I’m trying to find Altera boards that have an embedded ARM (Cortex A9) on them. This is my list so far.
If you know about another board, please comment below. I’ll remove the comment and add the board to the list.
Cyclone V
- Altera’s official Cyclone SoC Development kit with a 5CSXFC6D6F31C8NES.
- The Sockit by Arrow / Terasic with a 5CSXFC6D6F31C8ES.
- The DE-1 SoC board by Terasic, with a 5CSEMA5F31C6, strikingly similar to SoCKit.
- SoCrates by Devboards with a 5CSEBA6U23C7N (how’s your German?)
- Helio by CyTech global (Hong Kong) with a 5CSXFC6C6U23ES
About a year ago, I had a client failing to get the PCIe working on an Avnet LX150T development board. Despite countless joint efforts, we failed to get the card detected as a PCIe device by the computer.
A recent comment from another client supplied the clue: The user guide (which I downloaded recently from Avnet) is simply wrong about the DIP switch setting of the board. Table 5 (page 11) says that SW8 should be set OFF-ON-OFF to have a reference clock of 125 MHz to the FPGA.
On the other hand, Avnet’s AXI PCIe Endpoint Design guide for the same board (also downloaded recently from Avnet) says on page 30, that the setting for the same frequency should be ON-ON-ON.
Hmmm… So which one is correct?
Well, those signals go to an IDT ICS874003-05 PCI Express jitter attenuator, which consists of a frequency synthesizer. It multiplies the board’s 100 MHz reference clock by 5 on its internal VCO, and then divides that clock by an integer. The DIP switch setting determines the integers used for both outputs.
Ah, yes, there are generally two different divisors for the two outputs, depending on the DIP switch settings. In other words, PCIe-REFCLK0 and PCIe-REFCLK2 run at different frequencies (except for two settings, for which they happen to be the same). It’s worth to download the chip’s datasheet and have a look. It’s on the first page of the datasheet.
The bottom line is that the correct setting for a 125 MHz clock is ON-ON-ON, for which the correct clock is generated on both clock outputs. By the way, if it’s OFF-OFF-OFF, a 250 MHz clock appears on both outputs.
All other combinations generate two different clocks. Refer to the datasheet if you need a 100 MHz clock.
The mission
What I really needed was a proper timeout for a certain chunk of Perl code. There is alarm() of course, but one has to watch out with certain commands that cancel it (sleep() and other less expected functions). The script also uses “system()” to run processes outside the native Perl domain, so getting a bulletproof timeout mechanism with alarm() seems even less feasible.
The chosen solution was to fork(), and let the child do whatever it wants to. Let the alarm clock kill the entire process.
These are my notes as I figured out how to do this.
Return values from wait()
Since there’s a fork() involved, there’s a need to tell how the child ended up. It’s documented in “man perlvar”. This is a small script for experimenting with it:
#!/usr/bin/perl
use warnings;
use strict;
my $child = fork();
die("Failed to fork\n")
unless (defined $child);
if ($child) { # Parent running
my $pid;
$pid = wait;
my $status = $?;
die("No child process\n")
if ($pid < 0);
die("Child process = $child but process $pid was reaped\n")
unless ($child == $pid);
die("There was a core dump!\n")
if ($status & 128);
my $exit = $? >> 8;
my $signal = $? & 127;
print "Full status = $status (exit=$exit, signal=$signal)\n";
} else { # Child running
die("Bye bye cruel world\n");
}
The results
Note: Please refer to “perldoc -f die” for an outline of the exit codes used when Perl dies. In particular, Perl dies with the current value of $! (errno), and if it happens to be zero, Perl returns with 255. This matches the results below, but it should not be concluded that Perl always dies with 255.
To get unused error codes for custom use, check with the command line utility perror (254 and down are vacant).
- Termination of child due to end of script: Full status = 0 (exit=0, signal=0)
- Termination on “exit n” call of child: exit=n, signal=0
- Termination on “die()” call of child: Full status = 65280 (exit=255, signal=0)
- Termination on runtime error of child (division by zero, calling undefined subroutines etc.): Full status = 65280 (exit=255, signal=0)
- Child was killed with a signal, e.g. kill -9 {child’s pid}: Full status = 9 (exit=0, signal=9)
Fail #1:Using sleep() for waiting
The bottom line is that it’s a bad idea. But it’s presented here anyhow.
Suppose that we want to wait() with a timeout, and continue normally (i.e. not die() ) on timeout. Using alarm() won’t help, because wait() ignores the signal. Signal handlers won’t help much, because they run asynchronously, which makes them not so reliable for anything else than calling exit() or die().
(On afterthought, signal handlers are supposed to be reliable these days, so the handler could kill the child process and cause the wait() to return. See the aftermath below.)
So the idea is to change the beginning of the child’s code with something like this (for a timeout of 5 seconds, which in this example calles die(), but the execution context is reliable for anything else as well):
use POSIX ":sys_wait_h";
$SIG{CHLD} = sub { }; # This makes sleep() wake up on SIGCHLD
[ ... ]
if ($child) { # Parent running
my $pid;
my $endtime = time() + 5;
while (1) {
my $tosleep = $endtime - time();
print "$tosleep seconds left to sleep\n";
last unless ($tosleep > 0);
sleep $tosleep;
$pid = waitpid(-1, WNOHANG);
last if ($pid > 0);
}
if ($pid <= 0) {
print "Timed out!\n";
kill 9, $child;
exit 0;
}
Two things to be aware of:
- If sleep() is called after the signal has fired off, it will be ignored by sleep(), which will sleep for the given time or until another signal is sent to the process. This is important in particular if sleep() is used as a combined wait-with-timeout function, which is called “immediately” after a fork() to wait for the child. The problem may occur if the child dies before sleep() is reached. In practice, it’s unlikely to happen, so real tests will show that sleep() wakes up on SIGCHLD even if the child exits right away, giving the illusion that the concept is OK. But there is no guarantee that this will always work this way.
- A handler must be defined for the signal with e.g. $SIG{CHLD}, or the signal will not wake up sleep(). This handler may be an empty subroutine.
I couldn’t think of a way to make sure that sleep() before the child process can die. There’s also a possibility that another signal would wake up sleep(), which would lead to a short check with the time, and sleeping back. But if the child process dies in the middle of this check, sleep() misses it. It a rare race condition, causing very rare bugs and a royal headache.
Fail #2: Using select() for waiting
The bottom line, again, is that this is a bad idea.
But the idea was to open a pipe with the child process, as if there was an intention to pass data. The nice thing is that when the child process dies, the pipe breaks. It’s hence possible to use select() with a timeout argument. The even nicer thing about select() is that it always returns immediately if it’s told to wait for a broken pipe. No matter how many times.
Let’s look at the test routine, and then see why it’s worthless.
#!/usr/bin/perl
use warnings;
use strict;
pipe R, W;
my $child = fork();
die("Failed to fork\n")
unless (defined $child);
if ($child) { # Parent running
close W;
my $endtime = time() + 5;
while (1) {
my $tosleep = $endtime - time();
unless ($tosleep > 0) {
print "Timed out!\n";
kill 9, $child;
exit 0;
}
my ($rin, $rout, $ein, $eout);
$rin = '';
vec($rin, fileno(R), 1) = 1;
$ein = $rin;
my $nfound = select($rout=$rin, undef, $eout=$ein, $tosleep);
last if (ord($rout) || ord($eout));
}
my $pid;
$pid = wait;
my $status = $?;
die("No child process\n")
if ($pid < 0);
die("Child process = $child but process $pid was reaped\n")
unless ($child == $pid);
die("There was a core dump!\n")
if ($status & 128);
my $exit = $? >> 8;
my $signal = $? & 127;
print "Full status = $status (exit=$exit, signal=$signal)\n";
} else { # Child running
close R;
die("Bye bye cruel world\n");
}
The special thing here is the creation of a pipe, and closing one end on each side. And the use of select() of course. I would warmly recommend IO::Select instead of my own hacks above. I’m not sure if referring to ord($rout) and ord($eout) is correct, and will work even for larger file numbers than 3 (which is what I got in the example). Please imitate IO::Select and not the code above, if you insist on using select() directly. I simply didn’t bother. Anyhow, just for general knowledge, ord($rin) and ord($ein) were 8 in my case (because fileno(R) = 3). Upon return of select, ord($rout) was 0 on timeout, and 8 when the child process had died. ord($eout) always turned out to be zero. Well, actually, not really. Here comes problem #1:
If a signal was sent to the parent process, select() returned with both $rout and $eout turned on (that is, ord($rout)=ord($eout)=8) making it look as if the child had died. But it hadn’t, so wait() blocked.
This was worked around by considering ord($eout) != 0 to say that the child hasn’t died, and hence repeat the loop. This works with a signal, but what if there is a real error condition on the file descriptor for some unforeseen reason? And endless loop.
Another approach could have been using the non-blocking version of wait() (i.e. waitpid(-1, WNOHANG) ), but the child isn’t necessarily ready to be reaped by the time select() returns, so it’s too early for a non-blocking wait, which typically returns saying there’s nothing to reap, even if the child is just about to die.
Problem #2 is that the exit code of the child process is lost. It was always: Full status = 7424 (exit=29, signal=0). May I guess that code 29 means “broken pipe”?
All in all, this direction is too tangled for being a robust candidate for the job.
Success: Two children
Since it seems difficult to be both an alarm clock and wait for the process, the ultimate solution is to fork() twice: Once for generating the process running the task, and second for a watchdog process, which just sleeps for a given time, and then dies.
The idea is simple: The parent just calls wait(). The first process to terminate causes the parent to kill the other one. If the watchdog time died first, it’s a timeout situation. If it’s the task process, check its status.
Code follows.
#!/usr/bin/perl
use warnings;
use strict;
my $timeout = 10;
my $was_timeout = 0;
my $child = fork();
die("Failed to fork\n")
unless (defined $child);
if ($child) { # Parent running
my $killer = sub { kill 15, $child };
$SIG{HUP} = $killer;
$SIG{TERM} = $killer;
$SIG{INT} = $killer;
$SIG{QUIT} = $killer;
# Make the task process the head of a process group
setpgrp($child, 0) or die("Failed to set PGRP for process $child\n");
my $pgid = getpgrp($child);
my $watchdog = fork();
die("Failed to fork for watchdog\n")
unless (defined $watchdog);
if ($watchdog) { # Parent (of both processes) running
my $pid = wait;
my $status;
die("No child / watchdog process\n")
if ($pid < 0);
if ($pid == $child) {
$status = $?;
kill 9, $watchdog;
} elsif ($pid == $watchdog) {
# If the watchdog didn't exit with 0, it was killed ==> not a timeout.
$was_timeout = 1 if ($? == 0);
kill 9, $child;
} else {
die("$pid was reaped, expected $child (child process) or $watchdog (watchdog)\n");
}
# Reap the second process, which was just killed or happened to terminate
# by itself -- it doesn't matter now.
$pid = wait;
die("No child / watchdog process on second reap\n")
if ($pid < 0);
$status = $?
if ($pid == $child);
warn("There was a core dump!\n")
if ($status & 128);
if ($was_timeout) {
print "Timed out!\n";
} else {
my $exit = $status >> 8;
my $signal = $status & 127;
print "Full status = $status (exit=$exit, signal=$signal)\n";
}
# Just before quitting, send a SIGTERM to the entire process group,
# in case the task process has some forgotten children. This kills
# only processes previously fathered by the task process.
kill -15, $pgid;
} else { # Watchdog running
my $endtime = time() + $timeout;
# sleep() can wake up on signals. So keep looping until the time
# has passed.
while (1) {
my $tosleep = $endtime - time();
print "$tosleep seconds left to sleep\n";
last unless ($tosleep > 0);
sleep $tosleep;
}
exit 0;
}
} else { # Child running
`sleep 1000`;
exit 0;
}
First, a fork(), which creates the task process. This is followed by setting up a signal handler for the four main signals which may kill the parent process. This is necessary so that the children are killed along with the parent. CTRL-C from the console handles this automatically, but SIGTERM doesn’t. The handler only kills the task process, but that will always trigger a full wrap-up.
A call to setpgrp makes sure that the task process is the head of a new process group. This will be used later on.
To see how the processes are organized, go
$ ps o pid,pgrp,ppid,sess,tpgid,euid,ruid,comm
And then comes a second fork() for the watchdog process. All it does is sleep for a known amount of time. Note that it inherited the signal handlers from its parent, so it won’t die if killed by e.g. SIGTERM. Instead, the signal handler will kills task process, resulting in the correct wrap-up sequence. This is a good thing, because it’s difficult to tell which process is which, and killing the watchdog would trigger off a false timeout error, had it not been for these signal handlers. Well, actually not, because the exit status of the watchdog process is checked.
The parent process then calls wait(), and acts according to which process died first. The other process is then killed as well, and wait() is called again to collect the pieces.
An important add-on is sending a SIGTERM to all processes that remained in the task process group. There may do nothing, since the two others were killed, but if the task process ran some other process (as shown in the example with an external `sleep 1000`) it is killed too.
Some aftermath
The question that rises now is: If I trust the signal handler to kill the child process, why don’t I use it for timeout? In other words, why don’t I call alarm() in the waiting parent process, and let the SIGALRM signal handler kill the child, causing wait() to return?
The reason is that processes don’t always die when they get a signal, even if it’s a SIGKILL (the infamous number 9). For example, if the process is in an uninterruptible sleep (e.g. trying to access a dead NFS server), nothing happens. The timeout hence misses its purpose: The parent process remains stuck along with the child process.
The routine above doesn’t solve this problem, since it always waits twice. So even if the first wait() returns on the timeout process, the second wait() blocks forever on the stuck process.
But this can be worked around. For example, the second wait() can be exchanged with this:
$SIG{ALRM} = sub { die("Fatal: Child process refuses to quit\n"); };
alarm 30;
$pid = wait;
alarm 0;
undef $SIG{ALRM}
This gives the process, which has just received a signal, 30 seconds to die, or the parent process dies along with it. This is not the most elegant solution, but at least the parent process isn’t stuck.
There is maybe a way to keep the parent process alive despite a stuck child, possibly with a reaper waiting for it within a signal handler for SIGCHLD. The problem is that the child process may terminate suddenly, interfering with another wait() call that may come later on. So it’s simplest to just quit the parent process, and let process number 1 handle the reaping, whenever it comes. Even though there is a workaround for the problem caused by the workaround.
Intro
I needed some neat overlay to appear when the user clicks those question-mark icons on a specific, Drupal-based page. So I went for using jQuery’s tooltip widget, with due adaptations. It turned out to be a wise choice.
The idea is simple: Click on the question mark, an overlay window appears right underneath it, and stays there. Click on the “X” at the window’s top right, the window closes. Simple and clean.
These are my notes as I set this up. Most of the work is around the fact that tooltips usually appear and disappear on mouse hovering, not clicks.
Getting a bundle for a tooltip
Build your own set and download on jQuery’s official site. For a plain tooltip activation, pick the following options: All UI Core, no Interactions. Widgets: Only Tooltip. Effects: Only Effects Core and Fade Effect.
From the downloaded bundle, the following inclusions (in the <head> section) suffice (version numbers may vary):
<style>@import url("jquery-ui-1.10.0.custom.css");</style>
and
<script type="text/javascript" src="jquery-1.9.0.js"></script>
<script type="text/javascript" src="jquery-ui-1.10.0.custom.min.js"></script>
The “.min” version is just a condensed version of the non-min JavaScript file. The rest of the bundle can be ignored for a minimal tooltip implementation.
In a Drupal environment
Since Drupal uses jQuery as well, the initial idea was to rely on the script loaded anyhow, but I got the “$ is not a function” error in the error console. To solve this, the script inclusions shown above should appear after Drupal’s. In theory, the jQuery.noConflict() call should be used to save the previous “$” function, but since Drupal doesn’t inject jQuery calls after its last declaration in <head>, there is no need for this. This is OK for me, since I work on one specific page, but it’s theoretically possible that other Drupal pages put JavaScript in the <body>. So keep this in mind.
Maybe the best way is to load your own jQuery script bundle before Drupal’s, run noConflict() and then load Drupal’s. Just to be safe.
IE6 note
Internet Explorer 6 is an ancient thing, but since I always check against antique browsers, I noted that if there’s a selection box under the tooltip, it will appear above the tooltip, despite the latter’s z-index set to 9999. This is a bug specific to IE6, and therefore nothing to worry about too much. Anyone with IE6 is used to pages appearing ugly anyhow.
Declaring the jQuery handlers and hooks
This is a general note on how to inject jQuery definitions into the HTML.
Following jQuery’s recommendation, the application-specific definitions are made in the <head> section, in an anonymous function which is triggered by the “ready” event. This makes the jQuery hooks up and running as soon as the DOM hierarchy is set up, but doesn’t requires the onload event, which is triggered only when all assets (e.g. images) have been loaded.
So to run a tooltip on all elements marked “myclass” (they need to have a title= assignment),
<script>
$(function() {
$( ".myclass" ).tooltip();
});
</script>
The hooking to the “ready” event is implicit by the $(function() { … }) declaration.
Appear on click, don’t disappear
To make a “Hello world” tooltip appear on clicking an image of class “helpimg”, this goes into the <head> section (partly taken from here):
<script>
$(function() {
$( ".helpimg" ).tooltip({
content: "<i>Hello, world</i>",
items: 'img'
})
.off( "mouseover" )
.on( "click", function(){
var clicked = this;
$( ".helpimg" ).each(function (i) {
if (this != clicked) {
$( this ).tooltip( "close" );
}
});
$( this ).tooltip( "open" );
$( this ).unbind( "mouseleave" );
return false;
});
$( "body" ).on( "click", ".helpclose", function(){
$( ".helpimg" ).each(function (i) { $( this ).tooltip( "close" ); });
return false;
});
});
</script>
This little script does two things: Assign a tooltip object for each DOM element of class “helpimg” (for opening the tooltip) and an event handler to each “helpclose” element (for closing it).
See the tooltip API reference for the meanings of the attributes (content, item etc.).
Open the tooltip (.helpimg assignment)
The “content” attribute obviously sets the tooltip’s content. Here it’s given as a string itself, which is OK if the data is known when the tooltip is generated. Another possibility is to put a function here. Unlike what some documentation implies, there is no bodyHandler attribute (on jquery-ui-1.10.0). To provide a callback, a function is given instead of the string. For example, to put the ID of the element clicked on in the tooltip box, it should say (replacing the content: assignment above):
content: function() {
return $( this ).attr( "id" );
},
The “item” attribute defines the item type(s) involved. If this is absent, the click operation works only once: After the tooltip fades away, another click on the same item do nothing. Frankly, I don’t understand why this is.
The anonymous function defined in the .on() call is called when the element is clicked. Its first part (the definition of “clicked” and the “each” call) scans all elements of class “helpimg” and sends them a “close” command. This part is optional, to maintain an exclusive tooltip open. The if-statement in the each-function prevents closing the tooltip that is just about to be opened, to prevent flickering. Maybe it’s better to let the flickering happen, so that the user gets some feedback on the click. A matter of taste, I suppose.
Note that the function defined in the “each” call has a variable, which is the index. It’s not used in this case.
The call to unbind() (marked in red) kills the “mouseleave” event handler(s) that are related to the tooltip, so it doesn’t listen to this event. Normally, the “open” method sets an event handler for either “mouseleave” or “focusout”, depending on whether the triggering event was “mouseover” or “focusin”, respectively.
There is a non-specific call to unbind(), which makes the tooltip deaf to any event, but that made the tooltip appear only on the first click and then not again. So obviously there are some events handlers that should be left (maybe timers?).
Closing the tooltip
Since the tooltip won’t close by itself, this must be done by clicking on some element. The dedicated elements (actually, top-right “X” boxes) are given the “helpclose” class. When one of those elements get the “onclick” event, all tooltips are closed, with a function identical to the one used before opening a tooltip.
The important difference is the selection of these elements. Since they are hidden when the script is run, selecting them with $( “.xillyclose”).on( “click”, …) will catch nothing. The solution is to delegate the event to the “body” object, which is of course visible, and push the selector to within the .on() call. This way, the to-be visible elements are selected as they appear.
Closing on ESC keystroke
I found myself hitting ESC to close a tooltip, so why not support it? The idea is to catch keyup events, check if the key code happens to be 27 (ESC), and act as necessary.
$( document ).on( "keyup", function(event){
if (event.keyCode == 27) {
$( ".helpimg" ).each(function (i) { $( this ).tooltip( "close" ); });
return false;
}
I found the key code for ESC by running the demo on the .keyup() API page. Note that the .keyup() command is just a shorthand for the .on() call used above.
Position the tooltip
To get the tooltip properly positioned, the position property is set up during initialization. The declaration above should therefore start as
$(function() {
$( ".helpimg" ).tooltip({
content: "<i>Hello, world</i>",
items: 'img'
position: {
my: "center top",
at: "center bottom+5",
collision: "fit",
within: "#content"
}
[ ... ]
To avoid confusion, let’s think about the tooltip as a piece of paper that we want to nail on a billboard.
As described in the docs, the “my” property says where the on the tooltip we should place that nail (on the horizontal center and top of the tooltip), and the “at” property says where we should stick that nail (the horizontal center and bottom of the object is relates to, just 5 pixels lower).
The “collision property” tells what to do when the positioning would make the tooltip exceed the given area (“fit” means push it away from the border as necessary, but don’t throw it to the opposite side). “within” defines the framework in which the tooltip should be placed (the id=”content”, which is the main context box, defined by Drupal).
Conclusion
It took some time to get the hang of it, but all in all, jQuery is worth it, in particular by making the application code compact and therefore less bug prone.
It also handles those corner cases gracefully and takes care of browser compatibility. After all, what’s good for Wikipedia is good for me.
Every now and then, some USB device misbehaves badly enough to knock out the entire interface, to the extent that the system doesn’t detect any new USB devices. Or work so well with the existing ones, for that matter. The solution for me until now was to reboot the computer. But hey, I don’t like rebooting Linux!
April 2023 update:
Except for the solution suggested below, there are two additional methods for solving a problem like this. These two methods are more targeted towards the offending device, so I would suggest trying them out first (plus, there are zh/ja/ko translations).
So this script (I call it usbreset) performs a reset to the USB drivers as necessary to bring them back to life. As a side effect, an equivalent to unplugging and replugging all USB devices takes place. If possible, unmount any connected USB storage device (e.g. disk on key) before doing this. Also, if you’re in the middle of printing through a USB device, or some other operation, this will not be graceful.
An interesting thing I noted, was that if there’s a really problematic device on the bus (for example, a device that fails to enumerate), this script doesn’t return. It probably gets stuck on one of the writes to “bind” (hasn’t checked that all the way through).
Use at your own risk. You are root, you should know what you’re doing (or gamble like myself). Script follows.
If it doesn’t work for you, check the comments below. The names of the /sys files vary slightly among different distributions.
A word about how this script works, so it goes like this: The USB controllers are PCI / PCIe / fake PCI devices. So the script goes to the /sys directory that is related to the PCI devices’ driver, and unbinds them from the device, and then bind them back. So it’s like saying, nah, this device doesn’t belong to the driver, and then say, well, it is. And in the latter stage, the driver initializes the device, which does the job. On a good day.
Those file names like 0000:00:14.0 that appear in /sys/bus/pci/drivers/xhci_hcd/ are the PCI bus addresses of the USB controllers that are handled by the xhci_hcd driver. These will vanish from the directory after writing to “unbind” and return after writing to “bind”. The names can be found in /sys/bus/pci/devices/. Use “lspci” to tell which device is which.
#!/bin/bash
if [[ $EUID != 0 ]] ; then
echo This must be run as root!
exit 1
fi
for xhci in /sys/bus/pci/drivers/?hci_hcd ; do
if ! cd $xhci ; then
echo Weird error. Failed to change directory to $xhci
exit 1
fi
echo Resetting devices from $xhci...
for i in ????:??:??.? ; do
echo -n "$i" > unbind
echo -n "$i" > bind
done
done
The script above is in fact a newer version of the script, which I updated to in June 2014, after upgrading my kernel to 3.12. The older one, to which some of the comments relate, is this one:
#!/bin/bash
SYSEHCI=/sys/bus/pci/drivers/ehci_hcd
SYSUHCI=/sys/bus/pci/drivers/uhci_hcd
if [[ $EUID != 0 ]] ; then
echo This must be run as root!
exit 1
fi
if ! cd $SYSUHCI ; then
echo Weird error. Failed to change directory to $SYSUHCI
exit 1
fi
for i in ????:??:??.? ; do
echo -n "$i" > unbind
echo -n "$i" > bind
done
if ! cd $SYSEHCI ; then
echo Weird error. Failed to change directory to $SYSEHCI
exit 1
fi
for i in ????:??:??.? ; do
echo -n "$i" > unbind
echo -n "$i" > bind
done
The problem with the old script is that the EHCI subdirectory doesn’t appear on my system, because xHCI is a catch-all for all USB versions, hence when a USB port is 3.0 capable, it’s driven by the xhci_hcd driver only. The new script catches all possibilities. Hopefully.
So I bought this $10 mini DV camera on EBay. Since the user’s manual is pretty out of sync with itself and the product (Chinese and English doesn’t match, even by looking at the specification and drawings) I’ve written down some basic howto, in case I need to remember what to do at a later stage.
I can’t say I’m disappointed, because I didn’t really expect things to work as specified on a $10 camera.
Even though the manual promises 70 minutes of recording time, I got 48 minutes in reality before the camera stopped itself (the memory card wasn’t full, it was the battery that ran out).
Note that a MicroSD card needs to be purchased separately, which will cost significantly relative to the camera’s price (some $8 in a store, possibly $4 on EBay for a Sandisk card). The largest file I managed to obtain with a 48 minutes recording was 1.7 GB, so a 2 GB card is probably large enough.
LED colors
It looks like the LED colors were changed since the manual was written. The blue LED is the power LED, indicating that the device is on. The red LED says something is happening.
Optics and image quality
The image is a 720x480, apparently progressive (non-interlaced) rolling shutter with a noise level that resembles web cameras from the late 90′s. The measured opening angle on the frame’s width was as narrow as 25 degrees which, I suppose is about 80mm focal length on a 35mm-equivalent scale. In other words, this is with a slight touch of a tele lens.
The camera was announced having an 80 degrees view angle by its EBay seller, which turned out to be wrong. The narrow angle is a problem for most relevant applications, since it the desired subject gets off-frame easily. It’s also the reason for the shaky footage this camera emits. I’m not even sure about using this as a helmet camera.
With a $1 Jelly Lens, the angle of view rises to 40 degrees, which is around 50mm focal length (on a 35mm scale). In other words, the extra lens is some x0.6 (not very impressive, but what did I expect from a $1 lens?) and it gives the camera a “normal” focal length. The sticky adhesive on the jelly lens held the very small piece of plastic firmly in place. I don’t know how well this would work on a helmet cam, though. Did I say $1?
I should mention, that for a cellular phone with an already pretty wide angle, this Jelly Lens actually achieves an impressive wide angle (and green visible borders). So it’s a very good deal, given its price…
Another lens tried out was the AGPtek “180 Degrees” lens for cellular phones for some $5. It is often announced as x0.28, but it’s not. My measurement was 53 degrees, which is about 36 mm focal length (on a 35mm scale), so the lens did in fact x0.45. Better than the Jelly Lens, but by far not as good as expected. It does have a slight roundoff in the corners like a fish-eye lens at 53 degrees view angle, which gives the illusion that it’s wider than it actually is.
Charging
Connect the camera to a computer via USB, so it gets power. The blue LED goes on, and the red LED starts blinking. According to the user’s manual, a green LED should be blinking, but it looks like the color was changed to red. The user’s manual also says that the LED should stop blinking when the battery is charged, but that didn’t happen even after an overnight charging. It just went on blinking (red). According to the seller at EBay, the charging time should be 3 hours. Go figure.
Note that the MicroSD is mounted on the computer due to the USB connection.
Accessing the MicroSD card
Well, simply connect to the computer (as in for charging). The following (or similar) will appear at the log:
Jan 31 17:54:27 myhost kernel: hub 1-2:1.0: unable to enumerate USB device on port 2
Jan 31 17:54:29 myhost kernel: usb 1-2.2: new high speed USB device using ehci_hcd and address 62
Jan 31 17:54:29 myhost kernel: usb 1-2.2: New USB device found, idVendor=04d6, idProduct=e101
Jan 31 17:54:29 myhost kernel: usb 1-2.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
Jan 31 17:54:29 myhost kernel: usb 1-2.2: Product: usbdisk
Jan 31 17:54:29 myhost kernel: usb 1-2.2: Manufacturer: anyka
Jan 31 17:54:29 myhost kernel: usb 1-2.2: SerialNumber: 942954944
Jan 31 17:54:29 myhost kernel: scsi102 : usb-storage 1-2.2:1.0
Jan 31 17:54:30 myhost kernel: scsi 102:0:0:0: Direct-Access anyka MMC Disk 1.00 PQ: 0 ANSI: 2
Jan 31 17:54:30 myhost kernel: sd 102:0:0:0: Attached scsi generic sg4 type 0
Jan 31 17:54:30 myhost kernel: sd 102:0:0:0: [sdd] 3858560 512-byte logical blocks: (1.97 GB/1.83 GiB)
Jan 31 17:54:30 myhost kernel: sd 102:0:0:0: [sdd] Write Protect is off
Jan 31 17:54:30 myhost kernel: sd 102:0:0:0: [sdd] Assuming drive cache: write through
Jan 31 17:54:30 myhost kernel: sd 102:0:0:0: [sdd] Assuming drive cache: write through
Jan 31 17:54:30 myhost kernel: sdd:
Jan 31 17:54:30 myhost kernel: sd 102:0:0:0: [sdd] Assuming drive cache: write through
Jan 31 17:54:30 myhost kernel: sd 102:0:0:0: [sdd] Attached SCSI removable disk
This is just like connecting a disk-on-key, and so is the access to the content.
Using as a webcam
This is useful for getting an idea of the image quality, and immediate feedback for aiming the camera properly.
With the camera connected via USB (and hence the MicroSD card mounted), unmount the volume (“Safely Remove Drive” or something) and press the camera’s Power button for three seconds or so. The red LED will stop blinking, and the blue remains steadily on. The following lines in the log indicate the transformation into a web cam:
Jan 31 17:55:20 myhost kernel: usb 1-2.2: USB disconnect, address 62
Jan 31 17:55:21 myhost gnome-keyring-daemon[28416]: removing removable location: /media/New flash
Jan 31 17:55:21 myhost gnome-keyring-daemon[28416]: no volume registered at: /media/New flash
Jan 31 17:55:21 myhost gnome-keyring-daemon[3139]: removing removable location: /media/New flash
Jan 31 17:55:21 myhost gnome-keyring-daemon[3139]: no volume registered at: /media/New flash
Jan 31 17:55:23 myhost kernel: usb 1-2.2: new high speed USB device using ehci_hcd and address 63
Jan 31 17:55:23 myhost kernel: usb 1-2.2: New USB device found, idVendor=04d6, idProduct=e102
Jan 31 17:55:23 myhost kernel: usb 1-2.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
Jan 31 17:55:23 myhost kernel: usb 1-2.2: Product: UVC..
Jan 31 17:55:23 myhost kernel: usb 1-2.2: Manufacturer: ANYKA
Jan 31 17:55:23 myhost kernel: usb 1-2.2: SerialNumber: 12345
Jan 31 17:55:23 myhost kernel: uvcvideo: Found UVC 1.00 device UVC.. (04d6:e102)
Jan 31 17:55:23 myhost kernel: uvcvideo: UVC non compliance - GET_DEF(PROBE) not supported. Enabling workaround.
Jan 31 17:55:23 myhost kernel: input: UVC.. as /devices/pci0000:00/0000:00:1a.7/usb1/1-2/1-2.2/1-2.2:1.0/input/input13
The last row indicates the generation of /dev/video0:
$ ls -l /dev/video0
crw-rw----+ 1 root video 81, 0 2013-01-31 17:55 /dev/video0
It’s important to start doing something with the webcam soon, or the camera goes into sleep mode. Running Cheese Webcam Booth (2.28.1) shows an immediate image. No configuration should be necessary (it should find /dev/video0 automatically).
Using as a stand-alone camera
According to the manual, the camera has two modes: Normal recording and audio-triggered. I haven’t tried the audio-triggered mode, and neither do I want to. To switch from one mode to another, there’s the “Mode” button. Which I’m not touching.
Needless to say, a MicroSD card must be inserted for this to work.
To start, make sure that the device is disconnected from the computer and off (no LED is on). Press the Power button for a second, wait a few seconds. Only the blue LED should lit steadily.
To start and stop recording, press the button on the camera’s short edge (next to the record/stop symbols). The red LED will blink at 0.5 Hz during recording.
If the “Mode” button is pressed, the red LED will blink at 2-3 Hz to indicate audio-triggered recording. Turning the camera off and on is the best way to make sure the camera is at a known state.
Playback
The video files are put in the “VIDEO” subdirectory. A typical playback session with mplayer looks like this:
$ mplayer "/media/New Flash/VIDEO/2012-9-21 18-26-54.AVI"
MPlayer SVN-r31628-4.4.4 (C) 2000-2010 MPlayer Team
mplayer: could not connect to socket
mplayer: No such file or directory
Failed to open LIRC support. You will not be able to use your remote control.
Playing /media/New Flash/VIDEO/2012-9-21 18-26-54.AVI.
AVI file format detected.
[aviheader] Video stream found, -vid 0
[aviheader] Audio stream found, -aid 1
VIDEO: [MJPG] 720x480 24bpp 30.000 fps 2449.9 kbps (299.1 kbyte/s)
Clip info:
Software: ankarec
Failed to open VDPAU backend libvdpau_nvidia.so: cannot open shared object file: No such file or directory
[vdpau] Error when calling vdp_device_create_x11: 1
==========================================================================
Opening video decoder: [ffmpeg] FFmpeg's libavcodec codec family
Selected video codec: [ffmjpeg] vfm: ffmpeg (FFmpeg MJPEG)
==========================================================================
==========================================================================
Opening audio decoder: [pcm] Uncompressed PCM audio decoder
AUDIO: 8000 Hz, 1 ch, s16le, 128.0 kbit/100.00% (ratio: 16000->16000)
Selected audio codec: [pcm] afm: pcm (Uncompressed PCM)
==========================================================================
AO: [pulse] 8000Hz 1ch s16le (2 bytes per sample)
Starting playback...
Movie-Aspect is undefined - no prescaling applied.
VO: [xv] 720x480 => 720x480 Planar YV12
A: 3.0 V: 3.0 A-V: 0.001 ct: 0.002 92/ 92 5% 0% 0.1% 0 0
The video format is MJPEG 720x480 (not sure about the aspect ratio) with uncompressed 16 bit per sample mono sound, at 8 kHz sample rate. The file name represents the time at which recording began.
A small timestamp appears at the lower right of the recorded image.
Setting the time
This is somewhat confusing. The way to set the time, is to create a file called time.txt in the card’s root directory. To make things a bit complicated, the camera creates a file called TIME.TXT in the same place, with a timestamp sample (or something). Editing this file will do nothing. It’s a new file that needs to be created with something like
$ vi "/media/New Flash/time.txt"
It looks like the file appears from nowhere, with a sample timestamp (2012-09-21 17:08:56) set. Update it to something like
2013-01-31 19:45:00
or write it from scratch if nothing appears. Write and quit vi. Unmount the volume, unplug the camera, and turn it off. The camera will update the time to the file’s content when it starts up the next time.
There’s a null-character in the end in the sample timestamp. It can be omitted or left. Doesn’t matter.
Conclusion
Pretty much expected, it’s a piece of junk with poor documentation. Otherwise, it wouldn’t go for $10. But it’s good for putting in places where it has a good chance to get lost or destroyed, and hopefully get some cool footage when put on a helmet or something like that.
Sometimes, in particular when working on a relatively new Xilinx device family, the “map” tool fails on several errors like
ERROR:MapLib:979 - LUT5 symbol
"project/project_core/module/module_empty_user_w_smb_wren_d_O
R_201_o_inv1" (output
signal=project/project_core/module/module_empty_user_w_smb_wr
en_d_OR_201_o_inv) has input signal
"project/project_core/module/module_almostfull_d" which will
be trimmed. See Section 5 of the Map Report File for details about why the
input signal will become undriven
The first thing to say about this, is that it’s a bug in Xilinx’ tools. Sooner or later, Xilinx will announce that it has been fixed, and ask people to upgrade to recent versions (like in this case).
What the message says is more or less
Hi, this is the mapper. I was too eager to throw away logic which I thought was useless, but oops, it turns out I need this piece of logic after all. Please look in Section 5, and try to figure out why I made this mistake.
My own experience with solving this problem is that there is no quick fix. No flag to add or anything like that. The trick is to find what provoked the mapper into removing logic eagerly (usually whole blocks of logic) and accidentally remove a few elements too much. Look in section 5 for the signal that was trimmed (called “input signal” in the error message), and try to spot what triggered off the logic removal. It’s usually a significant chunk of logic (a functional block) which is effectively useless, because it’s fed with constant signals. A very possible reason for this is that those signals aren’t even connected in the module’s instantiation, so they are all held constant zero. So the mapper rightfully removes this dead weight. Just a bit too much.
Another thing to mention in this context, is that this problem always occurs with black-box logic in the design, that is, IP cores (e.g. FIFOs) and other logic blocks that are included as netlists to the project (as opposed to HDL sources). Dead logic is optimized out by the synthesizer when possible, so the only reason for dead logic in the mapping stage is that it came from different netlists.
So the exact thing to look for is an IP core or another black box that was instantiated with some of its ports either constant or ignored, causing significant parts of it turning into dead logic.
And finally, let’s say this again: This is a bug in Xilinx’ tools, and one of the reasons why working with new device families is a bit difficult. There is no excuse for failing a build because some of the logic is unused.
Just set up your mail server? Congratulations! Now you should test it. In particular, check if it relays mails to other servers and if the response time is reasonable. Here’s a script for doing the testing. Just edit the arguments to send_mail() to match your setting.
#!/usr/bin/perl
use warnings;
use strict;
use Net::SMTP;
send_mail('127.0.0.1', # Host
'sender@nowhere.com', #From
'myself@myhost.com', #to
'Just a test, please ignore', #Message body
"Testing email.\n" # Subject
);
sub send_mail {
my ($SMTP_HOST, $from, $to_addr, $body, $subject, $msg) = @_;
$msg = "MIME-Version: 1.0\n"
. "From: $from\n"
. "To: " . ( ref($to_addr) ? join(';', @$to_addr) : $to_addr ) . "\n"
. "Subject: $subject\n\n" # Double \n
. $body;
#
# Open a SMTP session
#
my $smtp = Net::SMTP->new( $SMTP_HOST,
'Debug' => 1, # Change to a 1 to turn on debug messages
Port => 587,
);
die("SMTP ERROR: Unable to open smtp session.\n")
if(!defined($smtp) || !($smtp));
die("Failed to set FROM address\n")
if (! ($smtp->mail( $from ) ) );
die("Failed to set receipient\n")
if (! ($smtp->recipient( ( ref($to_addr) ? @$to_addr : $to_addr ) ) ) );
$smtp->data( $msg );
$smtp->quit;
}
Two things to note:
The Port assignment marked red above makes an encryption connection with the server. It can be changed to 25, but many servers don’t answer strangers on that port.
July 2024 update: Nowadays, the situation seems to be the opposite. Mail servers that appear in the MX records and owned by Internet actors seem to answer only to port 25, and apparently only small servers answer to 587. Possibly because port 587 is commonly used for outgoing mail by MUAs (mail clients wishing to send an email) and port 25 is used only between servers (MTAs) …?
And if this script is used to talk with a remote server, odds are it won’t work due to authentication issues. If your server runs sendmail, it can be made less picky by making the following temporary changes to allow for testing:
In /etc/mail/sendmail.mc, change confAUTH_OPTIONS from `A’ to `’ (nothing, no authentication required). Also, change
DAEMON_OPTIONS(`Port=submission, Name=MSA, M=Ea')dnl
to
DAEMON_OPTIONS(`Port=submission, Name=MSA')dnl
and then compile the configuration file and restart the server with
# make -C /etc/mail
# service sendmail restart
Needless to say, it’s recommended to return the original settings after the testing is done. Your mail server should have some self-respect.
Anyhow, a typical output should look like this:
Net::SMTP>>> Net::SMTP(2.31)
Net::SMTP>>> Net::Cmd(2.29)
Net::SMTP>>> Exporter(5.62)
Net::SMTP>>> IO::Socket::INET(1.31)
Net::SMTP>>> IO::Socket(1.30_01)
Net::SMTP>>> IO::Handle(1.27)
Net::SMTP=GLOB(0x7c9d98)<<< 220 myhost.localdomain ESMTP Sendmail 8.14.4/8.14.4; Mon, 14 Jan 2013 14:03:26 +0200
Net::SMTP=GLOB(0x7c9d98)>>> EHLO localhost.localdomain
Net::SMTP=GLOB(0x7c9d98)<<< 250-myhost.localdomain Hello localhost.localdomain [127.0.0.1], pleased to meet you
Net::SMTP=GLOB(0x7c9d98)<<< 250-ENHANCEDSTATUSCODES
Net::SMTP=GLOB(0x7c9d98)<<< 250-PIPELINING
Net::SMTP=GLOB(0x7c9d98)<<< 250-8BITMIME
Net::SMTP=GLOB(0x7c9d98)<<< 250-SIZE
Net::SMTP=GLOB(0x7c9d98)<<< 250-DSN
Net::SMTP=GLOB(0x7c9d98)<<< 250-ETRN
Net::SMTP=GLOB(0x7c9d98)<<< 250-AUTH DIGEST-MD5 CRAM-MD5 LOGIN PLAIN
Net::SMTP=GLOB(0x7c9d98)<<< 250-DELIVERBY
Net::SMTP=GLOB(0x7c9d98)<<< 250 HELP
Net::SMTP=GLOB(0x7c9d98)>>> MAIL FROM:<sender@nowhere.com>
Net::SMTP=GLOB(0x7c9d98)<<< 250 2.1.0 <sender@nowhere.com>... Sender ok
Net::SMTP=GLOB(0x7c9d98)>>> RCPT TO:<myself@myhost.com>
Net::SMTP=GLOB(0x7c9d98)<<< 250 2.1.5 <myself@myhost.com>... Recipient ok
Net::SMTP=GLOB(0x7c9d98)>>> DATA
Net::SMTP=GLOB(0x7c9d98)<<< 354 Enter mail, end with "." on a line by itself
Net::SMTP=GLOB(0x7c9d98)>>> MIME-Version: 1.0
Net::SMTP=GLOB(0x7c9d98)>>> From: sender@nowhere.com
Net::SMTP=GLOB(0x7c9d98)>>> To: myself@myhost.com
Net::SMTP=GLOB(0x7c9d98)>>> Subject: Testing email.
Net::SMTP=GLOB(0x7c9d98)>>>
Net::SMTP=GLOB(0x7c9d98)>>>
Net::SMTP=GLOB(0x7c9d98)>>> Just a test, please ignore
Net::SMTP=GLOB(0x7c9d98)>>> .
Net::SMTP=GLOB(0x7c9d98)<<< 250 2.0.0 r0EC3Qm3030991 Message accepted for delivery
Net::SMTP=GLOB(0x7c9d98)>>> QUIT
Net::SMTP=GLOB(0x7c9d98)<<< 221 2.0.0 myhost.localdomain closing connection