Monday, September 29, 2008

winform [Dont Panic] = new windows.forms.DontPanic();

USB Panic Button
If you're reading this because you are googling the phrase "usb panic button" then my advice is to take a deep breath and DONT PANIC.

Neat little button, right? It's a little red button with a plastic cover (for your protection) and some fancy yellow and black striping so you know it's serious. There's a USB plug in the back so you can plug it into your computer. I bought one of these a few months ago figuring that I could use it for some extra input in windows. There are a few situations I have in mind where I'd love to be able to hit a button and have some specific effect (chosen, perhaps through a settings menu with some check boxes or choose file dialogs, depending on what needs to happen programatically).

Specifically, I hate that windows doesn't have a shortcut to create a new folder, so this would be my final solution™.

How hard could that be, honestly? It's a USB device and there's plenty of documentation on the web on that subject, right? I mean, how often do you use complicated usb devices everyday without even thinking about it? I'm writing this post right now with a USB keyboard and my mouse is a USB device as well. USB, as an industry standard, is something we depend on for a lot of devices but the intricacies of the interface and specifications are completely hidden from us - handled by drivers and your operating system.

Once this device arrived (a few months ago) I had some free time at work so I began researching some of the specifications of USB devices and how you talk to them. The software that is packaged with the device is useless beyond useless, effectively showing a static image and not even in a very nice way.

//insert images here
//this is the contents of the CD included
//this is what the application itself looks like. Probably created in visual studio or some c++ IDE in china.
//This is the splash screen. Probably the best image on the CD (not saying much).
//Here is one of the included images of an excel chart. Note the horrible compression
//this image is a little better, but not much...

I will not be posting the full app I wrote here yet, but I will write a post shortly (probably this evening if I remember) expanding on how I got this device working. While searching for a solution I found an incredible dearth of information on how to really interface with a USB device and even found some examples where people specifically withheld their code because it wasn't "clean enough". There is only one rule of blogging about software people, and it very simple.

THE ONE RULE OF BLOGGING ABOUT SOFTWARE
1. If you talk about it, post your code!

One simple deduction from this rule is that if you do not post your code, then your solution is beyond invalid - it doesn't even exist. Without a spec or even a crumb of information you cannot expect people to be able to believe what you're saying. There are tons of people scouring the web for code snippets and examples of some problem they are banging their collective heads against the wall because they are trying to write some code they can't figure out themselves. Coming across a web page that says "neener neener, I got this to work, but you never will" is the most insulting thing imaginable.

On that note, is here the method that took me literally three months to write:

static private void LoopForever()
{//"U", "S", "B", "C", "0", "8", "1", "0" in Hexadecimal
byte[] Magicbuffer = new byte[] { 0x55, 0x53, 0x42, 0x43, 0x0, 0x08, 0x01, 0x0 };
bool result = false;
while (true)
{
if (device == null)
{
continue;
}
System.Threading.Thread.Sleep(100);
device.SendControlMessage(0xA1, 0x01, 8, Magicbuffer);
result = (0 != Magicbuffer[0]);
if (result)
{//start a new process
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo("IExplore.exe", "http://illmaticprogrammatic.blogspot.com/") );
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo("IExplore.exe", "http://illmaticprogrammatic.blogspot.com/") ); }
displaytext = "Device found and communicating";
}//if someone can give me a hint on how to format this code better, please post a comment. My experience in blogging is very limited and this is something I'd like to be able to do on a regular basis.

edit: indents are a BITCH in html. I should make a table or edit my style sheets.
edit2: the language is C# and this is using the amazingly poorly maintained ICSharpCode wrapper for libusb (which is actually pretty amazing in and of itself).

5 comments:

Anonymous said...

For formatting, if you can use html tags, try <pre> and </pre> after you tab your text out. Also, this code looks much better than anything else others have to offer. I'm trying to blend your inner loop with the generic hid code found at http://www.lvr.com/hidpage.htm . So far, limited luck, but I'll have a working solution eventually. =)

In the long run, I think this type of solution is much better than "the other guys'" 'hacked' panic button solution. If I get it, you can be sure that I'll make this code available to the general public, no matter how sloppy it is. This button *has* to be able to do more!

Anonymous said...

http://www.orkey.net/PanicTray.zip

My Solution using Jan Axelson's Example. Free to use... the modification was *very* simple.

I didn't use any magic buffer or libusb stuff... check it out if you have the time. I can provide code as well if you like. :)

Tim Jarratt said...

Thanks Jesse, I really don't spend enough time in HTML to format stuff like code - I just expect it to work :(

This is a pretty cool example although off the bat I'm not sure how at all you were able to do this without any magic strings or usb libraries. Maybe if I ever get some free time from work I'll update this with a full working version...

Tim Jarratt said...

This is interesting, using win32 FILE I/O with a wrapper. At the end of the day they do the same thing, although mine is easier to port to/from *nix since it doesn't rely on any crazy windows file handles. =P

One thing I'm really curious about is how you handle the device being removed - the library I'm using doesn't handle that cleanly at all and the best way I found around it was to close/reopen the application programmtically.

Anonymous said...

It doesn't really handle device removal at all. However, once I unplugged/replugged the device and it just kept on ticking... it's kind of a read-only thing anyway.

libusb has been notorious for breaking things in the past for me. Stuff that should "just work" out of the box. I know the libusb authors now provide a device driver installer of sorts, but I never quite got it to work. I just figure if you need a native windows solution then this works.

I'm currently using this application runs a windows autohotkey script to play a sound and run the end-of-day summary report for a UPS Worldship station at the office. It meant we could take the monitor off the box and put it securely in a back room.

The magic string is just "00 01 00 00 00 00 00 ". No error handling or anything. It is crude, but it works.