The V-USB project is a really interesting project. It's goal is to provide free source code to implement USB 1.1 in a AVR processor, this makes it possible to build cheap devices that can connect to a PC. It's possible both to send commands from the PC and to recieve data from the cpu.
On the homepage there are a list of projects build on this technology.
The circuits used a really simple. Often the Atmega8 is used, it has several I/O-ports and a decent amount of memory. Other choices are the small ATTiny 8-pins like the ATTiny45.
This series are cheap, but have a drawback in the limited number of I/O-pins. Two pins are used for power, one is the reset pin. Another two is used for the USB-connection, which leaves us with three I/O's for connecting other stuff. Enough for a RGB-led, but not more.
Another drawback is in the develop process, as the USB D+ and D- in most cases are connected to PB0 and PB2, which is also MOSI and SCK. This makes it hard to use ISP-programming.
The ATTiny25 are also limited in use due to it's small memory, the USB-code leaves a few hundred bytes for other code.
The ATTiny2313 is also usable, more I/O but still limited memory. Example: http://www.delta7.de/projekte.php#usblcd
A commonly used cpu is the ATMega8, here we have plenty of memory and many I/O's at a reasonable price.
Read more at
http://www.obdev.at/products/vusb
Host software
A little theory about the software used. USBRelay (
Link) is used as an example.
1 - count.c. The number of arguments are checked.
if (argc != 1)
The USB device is initiated, if it fails an error is raised:
if (usbrelay_init()!=0) {
printf("%s\n", usbrelay_strerror());
If all ok:
printf("%i\n", usbrelay_count());
uchar usbrelay_count() is found in the file lib/usbrelay.c. Here this code is run:
usb_do(USB_ENDPOINT_IN, REQUEST_COUNT, 0, &result, 1);
return result;
usb_do is in this file too:
static int usb_do(int direction, int request, char value, char *data, int len)
Later in usb_do the following is run:
i= usb_control_msg(usb_handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | direction, request, value, 0, data, len, USB_TIMEOUT);
-usb_handle, // handle obtained with usb_open()
-USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN
From Libusb (/usr/include/usb.h):
#define USB_TYPE_VENDOR (0x02 << 5)
#define USB_RECIP_DEVICE 0x00
#define USB_ENDPOINT_IN 0x80
-request = REQUEST_COUNT // bRequest
In usbrelay.h we find this line:
#define REQUEST_COUNT 0
So in this case the request is GET_STATUS (0x00).
-value // wValue. Depends on request type.
-0 - wIndex
-data - pointer to destination buffer
-len - In USB-language called wLength, V-USB calls this numBytesRequested.
USB_TIMEOUT - timeoutInMilliseconds. usbrelay.c: #define USB_TIMEOUT 1000
To get more practical. In the host software we use this function to request a value from the usb-device:
static int usb_do(int direction, int request, char value, char *data, int len)
{
int i;
while (len > 254) {
usb_do(direction, request, value, data, 254);
data+= 254;
len-= 254;
}
i= usb_control_msg(usb_handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | direction, request, value, 0, data, len, USB_TIMEOUT);
if (i < 0) {
snprintf(str_error, sizeof(str_error), "usb error: %s", usb_strerror());
return i;
}
return 0;
}
The code to call the function looks like this:
uchar result;
usb_do(USB_ENDPOINT_IN, REQUEST_COUNT, 0, &result, 1);
The variable result will hold the data from the device.
'1' is the numBytesRequested, ie how many bytes we like to receive.
Device software
From V-USB wiki:
"When the host sends or receives a control message on endpoint 0 which is addressed to "vendor" or "class", the function usbFunctionSetup() is called in your code.".
This is just what our host software will do.
In the function we can use a switch-instruction to determine what to do:
switch(rq->bRequest){
In this code we also find:
#define REQUEST_DEVICE_COUNT 0
This is the same as REQUEST_COUNT in the host code. and can be any number. The USB Relay host code also has this:
#define REQUEST_SET 1
and in device code we find:
#define REQUEST_SET_RELAYS 1
The conclusion is that the device can run different code depending in the value of rq->bRequest:
case REQUEST_DEVICE_COUNT:
...
case REQUEST_SET_RELAYS:
...
Reference: http://vusb.wikidot.com/host-software, http://www.beyondlogic.org/usbnutshell/, http://dormouse.org.uk/sw/cyberphone.php